Overview
pipewire-aptx.changes
Changed
x
1
2
-------------------------------------------------------------------
3
+Wed Oct 18 08:54:11 UTC 2023 - Bjørn Lie <zaitor@opensuse.org>
4
+
5
+- Update to version 0.3.82
6
+
7
+-------------------------------------------------------------------
8
Sun Oct 8 16:26:36 UTC 2023 - Bjørn Lie <zaitor@opensuse.org>
9
10
- Update to version 0.3.81
11
pipewire-aptx.spec
Changed
10
1
2
%define soversion 0_2
3
4
Name: pipewire-aptx
5
-Version: 0.3.81
6
+Version: 0.3.82
7
Release: 0
8
Summary: PipeWire Bluetooth aptX codec plugin
9
License: MIT
10
pipewire-0.3.81.tar.gz/.gitlab/ci/check_missing_headers.sh -> pipewire-0.3.82.tar.gz/.gitlab/ci/check_missing_headers.sh
Changed
10
1
2
3
LIST=""
4
5
-for i in $(find spa/include -name '*.h' -a -not -path 'spa/include/spa/utils/cleanup.h' | sed s#spa/include/##);
6
+for i in $(find spa/include -name '*.h' | sed s#spa/include/##);
7
do
8
-f "$PREFIX/include/spa-0.2/$i" || LIST="$i $LIST"
9
done
10
pipewire-0.3.81.tar.gz/NEWS -> pipewire-0.3.82.tar.gz/NEWS
Changed
80
1
2
+# PipeWire 0.3.82 (2023-10-13)
3
+
4
+This is the second 1.0 release candidate that is API and ABI compatible
5
+with previous 0.3.x releases.
6
+
7
+## Highlights
8
+ - Fix a regression in some devices when the Pro-Audio profile was selected.
9
+ Only enable the IRQ based scheduling and device linking in specific
10
+ safe cases. (#3556)
11
+ - Improve rate switching. In some cases the graph rate would not switch
12
+ correctly. (#2929)
13
+ - Fix regression in alsa wakeups that would cause silence in VMs.
14
+ - Fix a leak in the SBC codecs for SCO.
15
+ - More improvements to the RAOP module.
16
+ - Other small improvements and fixes.
17
+
18
+
19
+## PipeWire
20
+ - Improve client property checks.
21
+ - Allow non-power-of-2 quantums when forced.
22
+ - Improve rate switching. In some cases the graph rate would not switch
23
+ correctly. (#2929)
24
+ - The PIPEWIRE_QUANTUM env variable now forces the size and rate in the
25
+ graph for the duration of the application. The softer PIPEWIRE_LATENCY
26
+ and PIPEWIRE_RATE can still be used to merely suggest a maximum latency
27
+ and a rate.
28
+
29
+## modules
30
+ - Remove the RTSP FLUSH request in RAOP because it does not seem necessary.
31
+ - The RAOP module now uses the common RTP stream functions.
32
+ - Add sockets option to protocol-native to make pipewire listen on multiple
33
+ sockets.
34
+
35
+## SPA
36
+ - Clean up some of the log functions.
37
+ - Add an option in ALSA to disable linking devices together.
38
+ - Only link pcms together when 1 capture and 1 playback pcm. For more complex
39
+ devices we can't be sure which ones can be linked. (#3556)
40
+ - disable tsched only when using linked devices.
41
+ - Add some extra checks in ALSA to avoid segfaults. (#3554)
42
+ - Add Tag support to alsa-sink and alsa-source.
43
+ - Use dynamic pod builder when we can.
44
+ - Set priority.driver on midi-bridge to allow it as a fallback driver. (#3562)
45
+ - Fix regression in alsa wakeups. (#3565)
46
+ - The PTP clock can now be found from the interface in node-driver.
47
+
48
+## pulse-server
49
+ - Some small cleanups and internal improvements.
50
+ - Add some memory debugging messages.
51
+ - Add Tag messages to streams.
52
+
53
+## Bluetooth
54
+ - Fix a leak in the SBC codecs for SCO.
55
+
56
+## JACK
57
+ - Patch up midi events in the destination buffer instead of writing to the
58
+ source buffer. (#3580)
59
+ - Group all jack clients together to avoid transport issues. (#3562)
60
+
61
+## ALSA-plugins
62
+ - Add also.deny option to block alsa clients from opening the PCM.
63
+
64
+Older versions:
65
+
66
+
67
# PipeWire 0.3.81 (2023-10-06)
68
69
This is the first 1.0 release candidate that is API and ABI compatible
70
71
- jack_property now always manages to actually change the metadata because
72
it waits for a roundtrip before exiting.
73
74
-Older versions:
75
-
76
-
77
# PipeWire 0.3.80 (2023-09-14)
78
79
This is a bugfix release that is API and ABI compatible with previous
80
pipewire-0.3.81.tar.gz/README.md -> pipewire-0.3.82.tar.gz/README.md
Changed
13
1
2
the samplerate.
3
* `PIPEWIRE_RATE=<num/denom>` to configure a rate for the graph.
4
* `PIPEWIRE_QUANTUM=<num/denom>` to configure latency as a fraction and a
5
- samplerate. This function will attempt to change
6
- the graph samplerate to `denom` and use the
7
- specified `num` as the buffer size.
8
+ samplerate. This function will force the graph samplerate to
9
+ `denom` and force the specified `num` as the buffer size.
10
* `PIPEWIRE_NODE=<id>` to request a link to the specified node. The
11
id can be a node.name or object.serial of the target node.
12
13
pipewire-0.3.81.tar.gz/meson.build -> pipewire-0.3.82.tar.gz/meson.build
Changed
35
1
2
project('pipewire', 'c' ,
3
- version : '0.3.81',
4
+ version : '0.3.82',
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
'sys/random.h', 'HAVE_SYS_RANDOM_H',
10
'sys/vfs.h', 'HAVE_SYS_VFS_H',
11
'pwd.h', 'HAVE_PWD_H',
12
+ 'grp.h', 'HAVE_GRP_H',
13
14
15
foreach h : check_headers
16
17
summary({'libsystemd': systemd_dep.found()}, bool_yn: true)
18
cdata.set('HAVE_SYSTEMD', systemd.found() and systemd_dep.found())
19
20
+selinux_dep = dependency('libselinux', required: get_option('selinux'))
21
+summary({'libselinux': selinux_dep.found()}, bool_yn: true)
22
+cdata.set('HAVE_SELINUX', selinux_dep.found())
23
+
24
configinc = include_directories('.')
25
includes_inc = include_directories('include')
26
pipewire_inc = include_directories('src')
27
28
'sigabbrev_np', '#include <string.h>', '-D_GNU_SOURCE', ,
29
'XSetIOErrorExitHandler', '#include <X11/Xlib.h>', , x11_dep,
30
'malloc_trim', '#include <malloc.h>', , ,
31
+ 'malloc_info', '#include <malloc.h>', , ,
32
33
34
foreach f : check_functions
35
pipewire-0.3.81.tar.gz/meson_options.txt -> pipewire-0.3.82.tar.gz/meson_options.txt
Changed
12
1
2
description: 'Install systemd user service file (ignored without systemd)',
3
type: 'feature',
4
value: 'enabled')
5
+option('selinux',
6
+ description: 'Enable SELinux integration',
7
+ type: 'feature',
8
+ value: 'auto')
9
option('pipewire-alsa',
10
description: 'Enable pipewire-alsa integration',
11
type: 'feature',
12
pipewire-0.3.81.tar.gz/pipewire-alsa/alsa-plugins/pcm_pipewire.c -> pipewire-0.3.82.tar.gz/pipewire-alsa/alsa-plugins/pcm_pipewire.c
Changed
14
1
2
if (str != NULL)
3
pw_properties_update_string(pw->props, str, strlen(str));
4
5
+ if ((str = pw_properties_get(pw->props, "alsa.deny")) != NULL &&
6
+ spa_atob(str)) {
7
+ err = -EACCES;
8
+ goto error;
9
+ }
10
+
11
str = getenv("PIPEWIRE_NODE");
12
if (str != NULL && str0)
13
pw_properties_set(pw->props, PW_KEY_TARGET_OBJECT, str);
14
pipewire-0.3.81.tar.gz/pipewire-jack/src/pipewire-jack.c -> pipewire-0.3.82.tar.gz/pipewire-jack/src/pipewire-jack.c
Changed
95
1
2
return b.state.offset;
3
}
4
5
-static inline void fix_midi_event(uint8_t *data, size_t size)
6
-{
7
- /* fixup NoteOn with vel 0 */
8
- if (size > 2 && (data0 & 0xF0) == 0x90 && data2 == 0x00) {
9
- data0 = 0x80 + (data0 & 0x0F);
10
- data2 = 0x40;
11
- }
12
-}
13
-
14
static inline int event_sort(struct spa_pod_control *a, struct spa_pod_control *b)
15
{
16
if (a->offset < b->offset)
17
18
}
19
}
20
21
+static inline void fix_midi_event(uint8_t *data, size_t size)
22
+{
23
+ /* fixup NoteOn with vel 0 */
24
+ if (size > 2 && (data0 & 0xF0) == 0x90 && data2 == 0x00) {
25
+ data0 = 0x80 + (data0 & 0x0F);
26
+ data2 = 0x40;
27
+ }
28
+}
29
+
30
+static inline int midi_event_write(void *port_buffer,
31
+ jack_nframes_t time,
32
+ const jack_midi_data_t *data,
33
+ size_t data_size, bool fix)
34
+{
35
+ jack_midi_data_t *retbuf = jack_midi_event_reserve (port_buffer, time, data_size);
36
+ if (SPA_UNLIKELY(retbuf == NULL))
37
+ return -ENOBUFS;
38
+ memcpy (retbuf, data, data_size);
39
+ if (fix)
40
+ fix_midi_event(retbuf, data_size);
41
+ return 0;
42
+}
43
+
44
static void convert_to_midi(struct spa_pod_sequence **seq, uint32_t n_seq, void *midi, bool fix)
45
{
46
struct spa_pod_control *cn_seq;
47
48
uint8_t *data = SPA_POD_BODY(&next->value);
49
size_t size = SPA_POD_BODY_SIZE(&next->value);
50
51
- if (fix)
52
- fix_midi_event(data, size);
53
-
54
- if ((res = jack_midi_event_write(midi, next->offset, data, size)) < 0)
55
+ if ((res = midi_event_write(midi, next->offset, data, size, fix)) < 0)
56
pw_log_warn("midi %p: can't write event: %s", midi,
57
spa_strerror(res));
58
break;
59
60
if ((str = getenv("PIPEWIRE_QUANTUM")) != NULL) {
61
struct spa_fraction q;
62
if (sscanf(str, "%u/%u", &q.num, &q.denom) == 2 && q.denom != 0) {
63
- pw_properties_setf(client->props, PW_KEY_NODE_RATE,
64
+ pw_properties_setf(client->props, PW_KEY_NODE_FORCE_RATE,
65
"1/%u", q.denom);
66
- pw_properties_setf(client->props, PW_KEY_NODE_LATENCY,
67
- "%u/%u", q.num, q.denom);
68
+ pw_properties_setf(client->props, PW_KEY_NODE_FORCE_QUANTUM,
69
+ "%u", q.num);
70
} else {
71
pw_log_warn("invalid PIPEWIRE_QUANTUM: %s", str);
72
}
73
74
if (pw_properties_get(client->props, PW_KEY_NODE_NAME) == NULL)
75
pw_properties_set(client->props, PW_KEY_NODE_NAME, client_name);
76
if (pw_properties_get(client->props, PW_KEY_NODE_GROUP) == NULL)
77
- pw_properties_setf(client->props, PW_KEY_NODE_GROUP, "jack-%d", getpid());
78
+ pw_properties_setf(client->props, PW_KEY_NODE_GROUP, "group.dsp.0");
79
if (pw_properties_get(client->props, PW_KEY_NODE_DESCRIPTION) == NULL)
80
pw_properties_set(client->props, PW_KEY_NODE_DESCRIPTION, client_name);
81
if (pw_properties_get(client->props, PW_KEY_MEDIA_TYPE) == NULL)
82
83
const jack_midi_data_t *data,
84
size_t data_size)
85
{
86
- jack_midi_data_t *retbuf = jack_midi_event_reserve (port_buffer, time, data_size);
87
- if (SPA_UNLIKELY(retbuf == NULL))
88
- return -ENOBUFS;
89
- memcpy (retbuf, data, data_size);
90
- return 0;
91
+ return midi_event_write(port_buffer, time, data, data_size, false);
92
}
93
94
SPA_EXPORT
95
pipewire-0.3.81.tar.gz/spa/include/meson.build -> pipewire-0.3.82.tar.gz/spa/include/meson.build
Changed
9
1
2
spa_headers = 'spa' # used by doxygen
3
install_subdir('spa',
4
install_dir : get_option('includedir') / spa_name,
5
- exclude_files :
6
- 'utils/cleanup.h',
7
- ,
8
)
9
pipewire-0.3.81.tar.gz/spa/include/spa/pod/dynamic.h -> pipewire-0.3.82.tar.gz/spa/include/spa/pod/dynamic.h
Changed
40
1
2
#endif
3
4
#include <spa/pod/builder.h>
5
+#include <spa/utils/cleanup.h>
6
7
struct spa_pod_dynamic_builder {
8
struct spa_pod_builder b;
9
10
struct spa_pod_dynamic_builder *d = (struct spa_pod_dynamic_builder*)data;
11
int32_t old_size = d->b.size;
12
int32_t new_size = SPA_ROUND_UP_N(size, d->extend);
13
- void *old_data = d->b.data;
14
+ void *old_data = d->b.data, *new_data;
15
16
if (old_data == d->data)
17
d->b.data = NULL;
18
- if ((d->b.data = realloc(d->b.data, new_size)) == NULL)
19
+ if ((new_data = realloc(d->b.data, new_size)) == NULL)
20
return -errno;
21
- if (old_data == d->data && d->b.data != old_data && old_size > 0)
22
- memcpy(d->b.data, old_data, old_size);
23
+ if (old_data == d->data && new_data != old_data && old_size > 0)
24
+ memcpy(new_data, old_data, old_size);
25
+ d->b.data = new_data;
26
d->b.size = new_size;
27
return 0;
28
}
29
30
free(builder->b.data);
31
}
32
33
+SPA_DEFINE_AUTO_CLEANUP(spa_pod_dynamic_builder, struct spa_pod_dynamic_builder, {
34
+ spa_pod_dynamic_builder_clean(thing);
35
+})
36
+
37
#ifdef __cplusplus
38
} /* extern "C" */
39
#endif
40
pipewire-0.3.81.tar.gz/spa/include/spa/support/log.h -> pipewire-0.3.82.tar.gz/spa/include/spa/support/log.h
Changed
53
1
2
#define SPA_LOG_TOPIC(v, t) \
3
(struct spa_log_topic){ .version = (v), .topic = (t)}
4
5
-#define spa_log_topic_init(l, topic) \
6
-do { \
7
- struct spa_log *_l = l; \
8
- if (SPA_LIKELY(_l)) { \
9
- struct spa_interface *_if = &_l->iface; \
10
- spa_interface_call(_if, struct spa_log_methods, \
11
- topic_init, 1, topic); \
12
- } \
13
-} while(0)
14
-
15
-/* Unused, left for backwards compat */
16
-#define spa_log_level_enabled(l,lev) ((l) && (l)->level >= (lev))
17
-
18
-#define spa_log_level_topic_enabled(l,topic,lev) \
19
-({ \
20
- struct spa_log *_log = l; \
21
- enum spa_log_level _lev = _log ? _log->level : SPA_LOG_LEVEL_NONE; \
22
- struct spa_log_topic *_t = (struct spa_log_topic *)(topic); \
23
- if (_t && _t->has_custom_level) \
24
- _lev = _t->level; \
25
- _lev >= (lev); \
26
-})
27
+static inline void spa_log_topic_init(struct spa_log *log, struct spa_log_topic *topic)
28
+{
29
+ if (SPA_UNLIKELY(!log))
30
+ return;
31
+
32
+ spa_interface_call(&log->iface, struct spa_log_methods, topic_init, 1, topic);
33
+}
34
+
35
+static inline bool spa_log_level_topic_enabled(const struct spa_log *log,
36
+ const struct spa_log_topic *topic,
37
+ enum spa_log_level level)
38
+{
39
+ enum spa_log_level max_level;
40
+
41
+ if (topic && topic->has_custom_level)
42
+ max_level = topic->level;
43
+ else if (log)
44
+ max_level = log->level;
45
+ else
46
+ max_level = SPA_LOG_LEVEL_NONE;
47
+
48
+ return level <= max_level;
49
+}
50
51
/* Transparently calls to version 0 log if v1 is not supported */
52
#define spa_log_logt(l,lev,topic,...) \
53
pipewire-0.3.81.tar.gz/spa/include/spa/utils/cleanup.h -> pipewire-0.3.82.tar.gz/spa/include/spa/utils/cleanup.h
Changed
116
1
2
#ifndef SPA_UTILS_CLEANUP_H
3
#define SPA_UTILS_CLEANUP_H
4
5
-#if !defined(__has_attribute) || !__has_attribute(__cleanup__)
6
-#error "attribute `cleanup` is required"
7
+#define spa_exchange(var, new_value) \
8
+__extension__ ({ \
9
+ __typeof__(var) *_ptr = &(var); \
10
+ __typeof__(var) _old_value = *_ptr; \
11
+ *_ptr = (new_value); \
12
+ _old_value; \
13
+})
14
+
15
+/* ========================================================================== */
16
+
17
+#if __GNUC__ >= 10 || defined(__clang__)
18
+#define spa_steal_ptr(ptr) ((__typeof__(*(ptr)) *) spa_exchange((ptr), NULL))
19
+#else
20
+#define spa_steal_ptr(ptr) spa_exchange((ptr), NULL)
21
#endif
22
23
+#define spa_clear_ptr(ptr, destructor) \
24
+__extension__ ({ \
25
+ __typeof__(ptr) _old_value = spa_steal_ptr(ptr); \
26
+ if (_old_value) \
27
+ destructor(_old_value); \
28
+ (void) 0; \
29
+})
30
+
31
+/* ========================================================================== */
32
+
33
+#include <unistd.h>
34
+
35
+#define spa_steal_fd(fd) spa_exchange((fd), -1)
36
+
37
+#define spa_clear_fd(fd) \
38
+__extension__ ({ \
39
+ int _old_value = spa_steal_fd(fd), _res = 0; \
40
+ if (_old_value >= 0) \
41
+ _res = close(_old_value); \
42
+ _res; \
43
+})
44
+
45
+/* ========================================================================== */
46
+
47
+#if defined(__has_attribute) && __has_attribute(__cleanup__)
48
+
49
#define spa_cleanup(func) __attribute__((__cleanup__(func)))
50
51
#define SPA_DEFINE_AUTO_CLEANUP(name, type, ...) \
52
53
spa_cleanup(_spa_autoptr_cleanup_func_ ## name) \
54
_spa_autoptr_cleanup_type_ ## name
55
56
-#define spa_exchange(var, new_value) \
57
-__extension__ ({ \
58
- __typeof__(var) *_ptr = &(var); \
59
- __typeof__(var) _old_value = *_ptr; \
60
- *_ptr = (new_value); \
61
- _old_value; \
62
-})
63
-
64
-#if __GNUC__ >= 10 || defined(__clang__)
65
-#define spa_steal_ptr(ptr) ((__typeof__(*(ptr)) *) spa_exchange((ptr), NULL))
66
-#else
67
-#define spa_steal_ptr(ptr) spa_exchange((ptr), NULL)
68
-#endif
69
-
70
-#define spa_steal_fd(fd) spa_exchange((fd), -1)
71
-
72
/* ========================================================================== */
73
74
#include <stdlib.h>
75
76
-#define spa_clear_ptr(ptr, destructor) \
77
-__extension__ ({ \
78
- __typeof__(ptr) _old_value = spa_steal_ptr(ptr); \
79
- if (_old_value) \
80
- destructor(_old_value); \
81
- (void) 0; \
82
-})
83
-
84
static inline void _spa_autofree_cleanup_func(void *p)
85
{
86
free(*(void **) p);
87
88
89
/* ========================================================================== */
90
91
-#include <unistd.h>
92
-
93
-#define spa_clear_fd(fd) \
94
-__extension__ ({ \
95
- int _old_value = spa_steal_fd(fd), _res = 0; \
96
- if (_old_value >= 0) \
97
- _res = close(_old_value); \
98
- _res; \
99
-})
100
-
101
static inline void _spa_autoclose_cleanup_func(int *fd)
102
{
103
spa_clear_fd(*fd);
104
105
spa_clear_ptr(*thing, closedir);
106
})
107
108
+#else
109
+
110
+#define SPA_DEFINE_AUTO_CLEANUP(name, type, ...)
111
+#define SPA_DEFINE_AUTOPTR_CLEANUP(name, type, ...)
112
+
113
+#endif
114
+
115
#endif /* SPA_UTILS_CLEANUP_H */
116
pipewire-0.3.81.tar.gz/spa/plugins/alsa/acp/acp.c -> pipewire-0.3.82.tar.gz/spa/plugins/alsa/acp/acp.c
Changed
65
1
2
static int add_pro_profile(pa_card *impl, uint32_t index)
3
{
4
snd_ctl_t *ctl_hndl;
5
- int err, dev, count = 0;
6
+ int err, dev, count = 0, n_capture = 0, n_playback = 0;
7
pa_alsa_profile *ap;
8
pa_alsa_profile_set *ps = impl->profile_set;
9
pa_alsa_mapping *m;
10
11
snd_pcm_info_t *pcminfo;
12
pa_sample_spec ss;
13
snd_pcm_uframes_t try_period_size, try_buffer_size;
14
+ uint32_t idx;
15
16
if (impl->use_ucm) {
17
const char *verb = find_best_verb(impl);
18
19
pa_alsa_init_proplist_pcm(NULL, m->output_proplist, m->output_pcm);
20
pa_proplist_setf(m->output_proplist, "clock.name", "api.alsa.%u", index);
21
pa_proplist_setf(m->output_proplist, "device.profile.pro", "true");
22
- pa_proplist_setf(m->output_proplist, "node.group", "pro-audio-%u", index);
23
- pa_proplist_setf(m->output_proplist, "node.link-group", "pro-audio-%u", index);
24
pa_alsa_close(&m->output_pcm);
25
m->supported = true;
26
pa_channel_map_init_auto(&m->channel_map, m->sample_spec.channels, PA_CHANNEL_MAP_AUX);
27
+ n_playback++;
28
}
29
pa_idxset_put(ap->output_mappings, m, NULL);
30
free(name);
31
32
pa_alsa_init_proplist_pcm(NULL, m->input_proplist, m->input_pcm);
33
pa_proplist_setf(m->input_proplist, "clock.name", "api.alsa.%u", index);
34
pa_proplist_setf(m->input_proplist, "device.profile.pro", "true");
35
- pa_proplist_setf(m->input_proplist, "node.group", "pro-audio-%u", index);
36
- pa_proplist_setf(m->input_proplist, "node.link-group", "pro-audio-%u", index);
37
pa_alsa_close(&m->input_pcm);
38
m->supported = true;
39
pa_channel_map_init_auto(&m->channel_map, m->sample_spec.channels, PA_CHANNEL_MAP_AUX);
40
+ n_capture++;
41
}
42
pa_idxset_put(ap->input_mappings, m, NULL);
43
free(name);
44
45
}
46
snd_ctl_close(ctl_hndl);
47
48
+ if (n_capture == 1 && n_playback == 1) {
49
+ PA_IDXSET_FOREACH(m, ap->output_mappings, idx) {
50
+ pa_proplist_setf(m->output_proplist, "node.group", "pro-audio-%u", index);
51
+ pa_proplist_setf(m->output_proplist, "node.link-group", "pro-audio-%u", index);
52
+ pa_proplist_setf(m->output_proplist, "api.alsa.auto-link", "true");
53
+ pa_proplist_setf(m->output_proplist, "api.alsa.disable-tsched", "true");
54
+ }
55
+ PA_IDXSET_FOREACH(m, ap->input_mappings, idx) {
56
+ pa_proplist_setf(m->input_proplist, "node.group", "pro-audio-%u", index);
57
+ pa_proplist_setf(m->input_proplist, "node.link-group", "pro-audio-%u", index);
58
+ pa_proplist_setf(m->input_proplist, "api.alsa.auto-link", "true");
59
+ pa_proplist_setf(m->input_proplist, "api.alsa.disable-tsched", "true");
60
+ }
61
+ }
62
return 0;
63
}
64
65
pipewire-0.3.81.tar.gz/spa/plugins/alsa/alsa-acp-device.c -> pipewire-0.3.82.tar.gz/spa/plugins/alsa/alsa-acp-device.c
Changed
83
1
2
#include <spa/param/param.h>
3
#include <spa/pod/filter.h>
4
#include <spa/pod/parser.h>
5
+#include <spa/pod/dynamic.h>
6
#include <spa/debug/pod.h>
7
#include <spa/debug/log.h>
8
9
10
{
11
struct impl *this = object;
12
struct spa_pod *param;
13
- struct spa_pod_builder b = { 0 };
14
+ spa_auto(spa_pod_dynamic_builder) b = { 0 };
15
+ struct spa_pod_builder_state state;
16
uint8_t buffer4096;
17
struct spa_result_device_params result;
18
uint32_t count = 0;
19
20
spa_return_val_if_fail(this != NULL, -EINVAL);
21
spa_return_val_if_fail(num != 0, -EINVAL);
22
23
+ spa_pod_dynamic_builder_init(&b, buffer, sizeof(buffer), 4096);
24
+ spa_pod_builder_get_state(&b.b, &state);
25
+
26
card = this->card;
27
28
result.id = id;
29
30
next:
31
result.index = result.next++;
32
33
- spa_pod_builder_init(&b, buffer, sizeof(buffer));
34
+ spa_pod_builder_reset(&b.b, &state);
35
36
switch (id) {
37
case SPA_PARAM_EnumProfile:
38
39
return 0;
40
41
pr = card->profilesresult.index;
42
- param = build_profile(&b, id, pr, false);
43
+ param = build_profile(&b.b, id, pr, false);
44
break;
45
46
case SPA_PARAM_Profile:
47
48
return 0;
49
50
pr = card->profilescard->active_profile_index;
51
- param = build_profile(&b, id, pr, true);
52
+ param = build_profile(&b.b, id, pr, true);
53
break;
54
55
case SPA_PARAM_EnumRoute:
56
57
return 0;
58
59
p = card->portsresult.index;
60
- param = build_route(&b, id, p, NULL, SPA_ID_INVALID);
61
+ param = build_route(&b.b, id, p, NULL, SPA_ID_INVALID);
62
break;
63
64
case SPA_PARAM_Route:
65
66
result.index++;
67
}
68
result.next = result.index + 1;
69
- param = build_route(&b, id, p, dev, card->active_profile_index);
70
+ param = build_route(&b.b, id, p, dev, card->active_profile_index);
71
if (param == NULL)
72
return -errno;
73
break;
74
75
return -ENOENT;
76
}
77
78
- if (spa_pod_filter(&b, &result.param, param, filter) < 0)
79
+ if (spa_pod_filter(&b.b, &result.param, param, filter) < 0)
80
goto next;
81
82
spa_device_emit_result(&this->hooks, seq, 0,
83
pipewire-0.3.81.tar.gz/spa/plugins/alsa/alsa-pcm-sink.c -> pipewire-0.3.82.tar.gz/spa/plugins/alsa/alsa-pcm-sink.c
Changed
316
1
2
#include <spa/utils/string.h>
3
#include <spa/param/audio/format.h>
4
#include <spa/pod/filter.h>
5
+#include <spa/pod/dynamic.h>
6
#include <spa/debug/log.h>
7
#include <spa/debug/pod.h>
8
9
10
{
11
struct state *this = object;
12
struct spa_pod *param;
13
- struct spa_pod_builder b = { 0 };
14
+ spa_auto(spa_pod_dynamic_builder) b = { 0 };
15
+ struct spa_pod_builder_state state;
16
uint8_t buffer4096;
17
struct spa_result_node_params result;
18
uint32_t count = 0;
19
20
spa_return_val_if_fail(this != NULL, -EINVAL);
21
spa_return_val_if_fail(num != 0, -EINVAL);
22
23
+ spa_pod_dynamic_builder_init(&b, buffer, sizeof(buffer), 4096);
24
+ spa_pod_builder_get_state(&b.b, &state);
25
+
26
result.id = id;
27
result.next = start;
28
- next:
29
+next:
30
result.index = result.next++;
31
32
- spa_pod_builder_init(&b, buffer, sizeof(buffer));
33
+ spa_pod_builder_reset(&b.b, &state);
34
35
switch (id) {
36
case SPA_PARAM_PropInfo:
37
38
39
switch (result.index) {
40
case 0:
41
- param = spa_pod_builder_add_object(&b,
42
+ param = spa_pod_builder_add_object(&b.b,
43
SPA_TYPE_OBJECT_PropInfo, id,
44
SPA_PROP_INFO_id, SPA_POD_Id(SPA_PROP_device),
45
SPA_PROP_INFO_name, SPA_POD_String(SPA_KEY_API_ALSA_PATH),
46
47
SPA_PROP_INFO_type, SPA_POD_Stringn(p->device, sizeof(p->device)));
48
break;
49
case 1:
50
- param = spa_pod_builder_add_object(&b,
51
+ param = spa_pod_builder_add_object(&b.b,
52
SPA_TYPE_OBJECT_PropInfo, id,
53
SPA_PROP_INFO_id, SPA_POD_Id(SPA_PROP_deviceName),
54
SPA_PROP_INFO_description, SPA_POD_String("The ALSA device name"),
55
SPA_PROP_INFO_type, SPA_POD_Stringn(p->device_name, sizeof(p->device_name)));
56
break;
57
case 2:
58
- param = spa_pod_builder_add_object(&b,
59
+ param = spa_pod_builder_add_object(&b.b,
60
SPA_TYPE_OBJECT_PropInfo, id,
61
SPA_PROP_INFO_id, SPA_POD_Id(SPA_PROP_cardName),
62
SPA_PROP_INFO_description, SPA_POD_String("The ALSA card name"),
63
SPA_PROP_INFO_type, SPA_POD_Stringn(p->card_name, sizeof(p->card_name)));
64
break;
65
case 3:
66
- param = spa_pod_builder_add_object(&b,
67
+ param = spa_pod_builder_add_object(&b.b,
68
SPA_TYPE_OBJECT_PropInfo, id,
69
SPA_PROP_INFO_id, SPA_POD_Id(SPA_PROP_latencyOffsetNsec),
70
SPA_PROP_INFO_description, SPA_POD_String("Latency offset (ns)"),
71
72
case 4:
73
if (!this->is_iec958 && !this->is_hdmi)
74
goto next;
75
- param = spa_pod_builder_add_object(&b,
76
+ param = spa_pod_builder_add_object(&b.b,
77
SPA_TYPE_OBJECT_PropInfo, id,
78
SPA_PROP_INFO_id, SPA_POD_Id(SPA_PROP_iec958Codecs),
79
SPA_PROP_INFO_name, SPA_POD_String("iec958.codecs"),
80
81
SPA_PROP_INFO_container, SPA_POD_Id(SPA_TYPE_Array));
82
break;
83
default:
84
- param = spa_alsa_enum_propinfo(this, result.index - 5, &b);
85
+ param = spa_alsa_enum_propinfo(this, result.index - 5, &b.b);
86
if (param == NULL)
87
return 0;
88
}
89
90
91
switch (result.index) {
92
case 0:
93
- spa_pod_builder_push_object(&b, &f,
94
+ spa_pod_builder_push_object(&b.b, &f,
95
SPA_TYPE_OBJECT_Props, id);
96
- spa_pod_builder_add(&b,
97
+ spa_pod_builder_add(&b.b,
98
SPA_PROP_device, SPA_POD_Stringn(p->device, sizeof(p->device)),
99
SPA_PROP_deviceName, SPA_POD_Stringn(p->device_name, sizeof(p->device_name)),
100
SPA_PROP_cardName, SPA_POD_Stringn(p->card_name, sizeof(p->card_name)),
101
102
103
if (this->is_iec958 || this->is_hdmi) {
104
n_codecs = spa_alsa_get_iec958_codecs(this, codecs, SPA_N_ELEMENTS(codecs));
105
- spa_pod_builder_prop(&b, SPA_PROP_iec958Codecs, 0);
106
- spa_pod_builder_array(&b, sizeof(uint32_t), SPA_TYPE_Id,
107
+ spa_pod_builder_prop(&b.b, SPA_PROP_iec958Codecs, 0);
108
+ spa_pod_builder_array(&b.b, sizeof(uint32_t), SPA_TYPE_Id,
109
n_codecs, codecs);
110
}
111
- spa_alsa_add_prop_params(this, &b);
112
- param = spa_pod_builder_pop(&b, &f);
113
+ spa_alsa_add_prop_params(this, &b.b);
114
+ param = spa_pod_builder_pop(&b.b, &f);
115
break;
116
default:
117
return 0;
118
119
case SPA_PARAM_IO:
120
switch (result.index) {
121
case 0:
122
- param = spa_pod_builder_add_object(&b,
123
+ param = spa_pod_builder_add_object(&b.b,
124
SPA_TYPE_OBJECT_ParamIO, id,
125
SPA_PARAM_IO_id, SPA_POD_Id(SPA_IO_Clock),
126
SPA_PARAM_IO_size, SPA_POD_Int(sizeof(struct spa_io_clock)));
127
break;
128
case 1:
129
- param = spa_pod_builder_add_object(&b,
130
+ param = spa_pod_builder_add_object(&b.b,
131
SPA_TYPE_OBJECT_ParamIO, id,
132
SPA_PARAM_IO_id, SPA_POD_Id(SPA_IO_Position),
133
SPA_PARAM_IO_size, SPA_POD_Int(sizeof(struct spa_io_position)));
134
135
case SPA_PARAM_ProcessLatency:
136
switch (result.index) {
137
case 0:
138
- param = spa_process_latency_build(&b, id, &this->process_latency);
139
+ param = spa_process_latency_build(&b.b, id, &this->process_latency);
140
break;
141
default:
142
return 0;
143
144
return -ENOENT;
145
}
146
147
- if (spa_pod_filter(&b, &result.param, param, filter) < 0)
148
+ if (spa_pod_filter(&b.b, &result.param, param, filter) < 0)
149
goto next;
150
151
spa_node_emit_result(&this->hooks, seq, 0, SPA_RESULT_TYPE_NODE_PARAMS, &result);
152
153
154
struct state *this = object;
155
struct spa_pod *param;
156
- struct spa_pod_builder b = { 0 };
157
+ spa_auto(spa_pod_dynamic_builder) b = { 0 };
158
+ struct spa_pod_builder_state state;
159
uint8_t buffer1024;
160
struct spa_result_node_params result;
161
uint32_t count = 0;
162
163
164
spa_return_val_if_fail(CHECK_PORT(this, direction, port_id), -EINVAL);
165
166
+ spa_pod_dynamic_builder_init(&b, buffer, sizeof(buffer), 4096);
167
+ spa_pod_builder_get_state(&b.b, &state);
168
+
169
result.id = id;
170
result.next = start;
171
next:
172
result.index = result.next++;
173
174
- spa_pod_builder_init(&b, buffer, sizeof(buffer));
175
+ spa_pod_builder_reset(&b.b, &state);
176
177
switch (id) {
178
case SPA_PARAM_EnumFormat:
179
180
181
switch (this->current_format.media_subtype) {
182
case SPA_MEDIA_SUBTYPE_raw:
183
- param = spa_format_audio_raw_build(&b, id,
184
+ param = spa_format_audio_raw_build(&b.b, id,
185
&this->current_format.info.raw);
186
break;
187
case SPA_MEDIA_SUBTYPE_iec958:
188
- param = spa_format_audio_iec958_build(&b, id,
189
+ param = spa_format_audio_iec958_build(&b.b, id,
190
&this->current_format.info.iec958);
191
break;
192
case SPA_MEDIA_SUBTYPE_dsd:
193
- param = spa_format_audio_dsd_build(&b, id,
194
+ param = spa_format_audio_dsd_build(&b.b, id,
195
&this->current_format.info.dsd);
196
break;
197
default:
198
199
if (result.index > 0)
200
return 0;
201
202
- param = spa_pod_builder_add_object(&b,
203
+ param = spa_pod_builder_add_object(&b.b,
204
SPA_TYPE_OBJECT_ParamBuffers, id,
205
SPA_PARAM_BUFFERS_buffers, SPA_POD_CHOICE_RANGE_Int(2, 1, MAX_BUFFERS),
206
SPA_PARAM_BUFFERS_blocks, SPA_POD_Int(this->blocks),
207
208
case SPA_PARAM_Meta:
209
switch (result.index) {
210
case 0:
211
- param = spa_pod_builder_add_object(&b,
212
+ param = spa_pod_builder_add_object(&b.b,
213
SPA_TYPE_OBJECT_ParamMeta, id,
214
SPA_PARAM_META_type, SPA_POD_Id(SPA_META_Header),
215
SPA_PARAM_META_size, SPA_POD_Int(sizeof(struct spa_meta_header)));
216
217
case SPA_PARAM_IO:
218
switch (result.index) {
219
case 0:
220
- param = spa_pod_builder_add_object(&b,
221
+ param = spa_pod_builder_add_object(&b.b,
222
SPA_TYPE_OBJECT_ParamIO, id,
223
SPA_PARAM_IO_id, SPA_POD_Id(SPA_IO_Buffers),
224
SPA_PARAM_IO_size, SPA_POD_Int(sizeof(struct spa_io_buffers)));
225
break;
226
case 1:
227
- param = spa_pod_builder_add_object(&b,
228
+ param = spa_pod_builder_add_object(&b.b,
229
SPA_TYPE_OBJECT_ParamIO, id,
230
SPA_PARAM_IO_id, SPA_POD_Id(SPA_IO_RateMatch),
231
SPA_PARAM_IO_size, SPA_POD_Int(sizeof(struct spa_io_rate_match)));
232
233
struct spa_latency_info latency = this->latencyresult.index;
234
if (latency.direction == SPA_DIRECTION_INPUT)
235
spa_process_latency_info_add(&this->process_latency, &latency);
236
- param = spa_latency_build(&b, id, &latency);
237
+ param = spa_latency_build(&b.b, id, &latency);
238
break;
239
}
240
default:
241
return 0;
242
}
243
break;
244
-
245
+ case SPA_PARAM_Tag:
246
+ switch (result.index) {
247
+ case 0: case 1:
248
+ if ((param = this->tagresult.index) == NULL)
249
+ goto next;
250
+ break;
251
+ default:
252
+ return 0;
253
+ }
254
+ break;
255
default:
256
return -ENOENT;
257
}
258
259
- if (spa_pod_filter(&b, &result.param, param, filter) < 0)
260
+ if (spa_pod_filter(&b.b, &result.param, param, filter) < 0)
261
goto next;
262
263
spa_node_emit_result(&this->hooks, seq, 0, SPA_RESULT_TYPE_NODE_PARAMS, &result);
264
265
break;
266
case SPA_PARAM_Latency:
267
{
268
+ enum spa_direction other = SPA_DIRECTION_REVERSE(direction);
269
struct spa_latency_info info;
270
if (param == NULL)
271
- info = SPA_LATENCY_INFO(SPA_DIRECTION_REVERSE(direction));
272
+ info = SPA_LATENCY_INFO(other);
273
else if ((res = spa_latency_parse(param, &info)) < 0)
274
return res;
275
- if (direction == info.direction)
276
+ if (info.direction != other)
277
return -EINVAL;
278
279
this->latencyinfo.direction = info;
280
281
break;
282
}
283
case SPA_PARAM_Tag:
284
- if (param != NULL)
285
- spa_debug_log_pod(this->log, SPA_LOG_LEVEL_DEBUG, 0, NULL, param);
286
+ {
287
+ enum spa_direction other = SPA_DIRECTION_REVERSE(direction);
288
+ if (param != NULL) {
289
+ struct spa_tag_info info;
290
+ void *state = NULL;
291
+ if (spa_tag_parse(param, &info, &state) < 0 ||
292
+ info.direction != other)
293
+ return -EINVAL;
294
+ }
295
+ if (spa_tag_compare(param, this->tagother) != 0) {
296
+ free(this->tagother);
297
+ this->tagother = param ? spa_pod_copy(param) : NULL;
298
+
299
+ this->port_info.change_mask |= SPA_PORT_CHANGE_MASK_PARAMS;
300
+ this->port_paramsPORT_Tag.user++;
301
+ emit_port_info(this, false);
302
+ }
303
break;
304
+ }
305
default:
306
res = -ENOENT;
307
break;
308
309
this->port_paramsPORT_Format = SPA_PARAM_INFO(SPA_PARAM_Format, SPA_PARAM_INFO_WRITE);
310
this->port_paramsPORT_Buffers = SPA_PARAM_INFO(SPA_PARAM_Buffers, 0);
311
this->port_paramsPORT_Latency = SPA_PARAM_INFO(SPA_PARAM_Latency, SPA_PARAM_INFO_READWRITE);
312
+ this->port_paramsPORT_Tag = SPA_PARAM_INFO(SPA_PARAM_Tag, SPA_PARAM_INFO_READWRITE);
313
this->port_info.params = this->port_params;
314
this->port_info.n_params = N_PORT_PARAMS;
315
316
pipewire-0.3.81.tar.gz/spa/plugins/alsa/alsa-pcm-source.c -> pipewire-0.3.82.tar.gz/spa/plugins/alsa/alsa-pcm-source.c
Changed
297
1
2
#include <spa/monitor/device.h>
3
#include <spa/param/audio/format.h>
4
#include <spa/pod/filter.h>
5
+#include <spa/pod/dynamic.h>
6
7
#include "alsa.h"
8
9
10
struct state *this = object;
11
struct spa_pod *param;
12
uint8_t buffer4096;
13
- struct spa_pod_builder b = { 0 };
14
+ spa_auto(spa_pod_dynamic_builder) b = { 0 };
15
+ struct spa_pod_builder_state state;
16
struct props *p;
17
struct spa_result_node_params result;
18
uint32_t count = 0;
19
20
spa_return_val_if_fail(this != NULL, -EINVAL);
21
spa_return_val_if_fail(num != 0, -EINVAL);
22
23
+ spa_pod_dynamic_builder_init(&b, buffer, sizeof(buffer), 4096);
24
+ spa_pod_builder_get_state(&b.b, &state);
25
+
26
p = &this->props;
27
28
result.id = id;
29
30
next:
31
result.index = result.next++;
32
33
- spa_pod_builder_init(&b, buffer, sizeof(buffer));
34
+ spa_pod_builder_reset(&b.b, &state);
35
36
switch (id) {
37
case SPA_PARAM_PropInfo:
38
switch (result.index) {
39
case 0:
40
- param = spa_pod_builder_add_object(&b,
41
+ param = spa_pod_builder_add_object(&b.b,
42
SPA_TYPE_OBJECT_PropInfo, id,
43
SPA_PROP_INFO_id, SPA_POD_Id(SPA_PROP_device),
44
SPA_PROP_INFO_name, SPA_POD_String(SPA_KEY_API_ALSA_PATH),
45
46
SPA_PROP_INFO_type, SPA_POD_Stringn(p->device, sizeof(p->device)));
47
break;
48
case 1:
49
- param = spa_pod_builder_add_object(&b,
50
+ param = spa_pod_builder_add_object(&b.b,
51
SPA_TYPE_OBJECT_PropInfo, id,
52
SPA_PROP_INFO_id, SPA_POD_Id(SPA_PROP_deviceName),
53
SPA_PROP_INFO_description, SPA_POD_String("The ALSA device name"),
54
SPA_PROP_INFO_type, SPA_POD_Stringn(p->device_name, sizeof(p->device_name)));
55
break;
56
case 2:
57
- param = spa_pod_builder_add_object(&b,
58
+ param = spa_pod_builder_add_object(&b.b,
59
SPA_TYPE_OBJECT_PropInfo, id,
60
SPA_PROP_INFO_id, SPA_POD_Id(SPA_PROP_cardName),
61
SPA_PROP_INFO_description, SPA_POD_String("The ALSA card name"),
62
SPA_PROP_INFO_type, SPA_POD_Stringn(p->card_name, sizeof(p->card_name)));
63
break;
64
case 3:
65
- param = spa_pod_builder_add_object(&b,
66
+ param = spa_pod_builder_add_object(&b.b,
67
SPA_TYPE_OBJECT_PropInfo, id,
68
SPA_PROP_INFO_id, SPA_POD_Id(SPA_PROP_latencyOffsetNsec),
69
SPA_PROP_INFO_description, SPA_POD_String("Latency offset (ns)"),
70
SPA_PROP_INFO_type, SPA_POD_CHOICE_RANGE_Long(0LL, 0LL, 2 * SPA_NSEC_PER_SEC));
71
break;
72
default:
73
- param = spa_alsa_enum_propinfo(this, result.index - 4, &b);
74
+ param = spa_alsa_enum_propinfo(this, result.index - 4, &b.b);
75
if (param == NULL)
76
return 0;
77
}
78
79
80
switch (result.index) {
81
case 0:
82
- spa_pod_builder_push_object(&b, &f,
83
+ spa_pod_builder_push_object(&b.b, &f,
84
SPA_TYPE_OBJECT_Props, id);
85
- spa_pod_builder_add(&b,
86
+ spa_pod_builder_add(&b.b,
87
SPA_PROP_device, SPA_POD_Stringn(p->device, sizeof(p->device)),
88
SPA_PROP_deviceName, SPA_POD_Stringn(p->device_name, sizeof(p->device_name)),
89
SPA_PROP_cardName, SPA_POD_Stringn(p->card_name, sizeof(p->card_name)),
90
SPA_PROP_latencyOffsetNsec, SPA_POD_Long(this->process_latency.ns),
91
0);
92
- spa_alsa_add_prop_params(this, &b);
93
- param = spa_pod_builder_pop(&b, &f);
94
+ spa_alsa_add_prop_params(this, &b.b);
95
+ param = spa_pod_builder_pop(&b.b, &f);
96
break;
97
default:
98
return 0;
99
100
case SPA_PARAM_IO:
101
switch (result.index) {
102
case 0:
103
- param = spa_pod_builder_add_object(&b,
104
+ param = spa_pod_builder_add_object(&b.b,
105
SPA_TYPE_OBJECT_ParamIO, id,
106
SPA_PARAM_IO_id, SPA_POD_Id(SPA_IO_Clock),
107
SPA_PARAM_IO_size, SPA_POD_Int(sizeof(struct spa_io_clock)));
108
break;
109
case 1:
110
- param = spa_pod_builder_add_object(&b,
111
+ param = spa_pod_builder_add_object(&b.b,
112
SPA_TYPE_OBJECT_ParamIO, id,
113
SPA_PARAM_IO_id, SPA_POD_Id(SPA_IO_Position),
114
SPA_PARAM_IO_size, SPA_POD_Int(sizeof(struct spa_io_position)));
115
116
case SPA_PARAM_ProcessLatency:
117
switch (result.index) {
118
case 0:
119
- param = spa_process_latency_build(&b, id, &this->process_latency);
120
+ param = spa_process_latency_build(&b.b, id, &this->process_latency);
121
break;
122
default:
123
return 0;
124
125
return -ENOENT;
126
}
127
128
- if (spa_pod_filter(&b, &result.param, param, filter) < 0)
129
+ if (spa_pod_filter(&b.b, &result.param, param, filter) < 0)
130
goto next;
131
132
spa_node_emit_result(&this->hooks, seq, 0, SPA_RESULT_TYPE_NODE_PARAMS, &result);
133
134
{
135
struct state *this = object;
136
struct spa_pod *param;
137
- struct spa_pod_builder b = { 0 };
138
+ spa_auto(spa_pod_dynamic_builder) b = { 0 };
139
+ struct spa_pod_builder_state state;
140
uint8_t buffer1024;
141
struct spa_result_node_params result;
142
uint32_t count = 0;
143
144
spa_return_val_if_fail(this != NULL, -EINVAL);
145
spa_return_val_if_fail(num != 0, -EINVAL);
146
-
147
spa_return_val_if_fail(CHECK_PORT(this, direction, port_id), -EINVAL);
148
149
+ spa_pod_dynamic_builder_init(&b, buffer, sizeof(buffer), 4096);
150
+ spa_pod_builder_get_state(&b.b, &state);
151
+
152
result.id = id;
153
result.next = start;
154
next:
155
result.index = result.next++;
156
157
- spa_pod_builder_init(&b, buffer, sizeof(buffer));
158
+ spa_pod_builder_reset(&b.b, &state);
159
160
switch (id) {
161
case SPA_PARAM_EnumFormat:
162
163
if (result.index > 0)
164
return 0;
165
166
- param = spa_format_audio_raw_build(&b, id, &this->current_format.info.raw);
167
+ param = spa_format_audio_raw_build(&b.b, id, &this->current_format.info.raw);
168
break;
169
170
case SPA_PARAM_Buffers:
171
172
if (result.index > 0)
173
return 0;
174
175
- param = spa_pod_builder_add_object(&b,
176
+ param = spa_pod_builder_add_object(&b.b,
177
SPA_TYPE_OBJECT_ParamBuffers, id,
178
SPA_PARAM_BUFFERS_buffers, SPA_POD_CHOICE_RANGE_Int(2, 1, MAX_BUFFERS),
179
SPA_PARAM_BUFFERS_blocks, SPA_POD_Int(this->blocks),
180
181
case SPA_PARAM_Meta:
182
switch (result.index) {
183
case 0:
184
- param = spa_pod_builder_add_object(&b,
185
+ param = spa_pod_builder_add_object(&b.b,
186
SPA_TYPE_OBJECT_ParamMeta, id,
187
SPA_PARAM_META_type, SPA_POD_Id(SPA_META_Header),
188
SPA_PARAM_META_size, SPA_POD_Int(sizeof(struct spa_meta_header)));
189
190
case SPA_PARAM_IO:
191
switch (result.index) {
192
case 0:
193
- param = spa_pod_builder_add_object(&b,
194
+ param = spa_pod_builder_add_object(&b.b,
195
SPA_TYPE_OBJECT_ParamIO, id,
196
SPA_PARAM_IO_id, SPA_POD_Id(SPA_IO_Buffers),
197
SPA_PARAM_IO_size, SPA_POD_Int(sizeof(struct spa_io_buffers)));
198
break;
199
case 1:
200
- param = spa_pod_builder_add_object(&b,
201
+ param = spa_pod_builder_add_object(&b.b,
202
SPA_TYPE_OBJECT_ParamIO, id,
203
SPA_PARAM_IO_id, SPA_POD_Id(SPA_IO_RateMatch),
204
SPA_PARAM_IO_size, SPA_POD_Int(sizeof(struct spa_io_rate_match)));
205
206
struct spa_latency_info latency = this->latencyresult.index;
207
if (latency.direction == SPA_DIRECTION_OUTPUT)
208
spa_process_latency_info_add(&this->process_latency, &latency);
209
- param = spa_latency_build(&b, id, &latency);
210
+ param = spa_latency_build(&b.b, id, &latency);
211
break;
212
}
213
default:
214
return 0;
215
}
216
break;
217
+ case SPA_PARAM_Tag:
218
+ switch (result.index) {
219
+ case 0: case 1:
220
+ if ((param = this->tagresult.index) == NULL)
221
+ goto next;
222
+ break;
223
+ default:
224
+ return 0;
225
+ }
226
+ break;
227
228
default:
229
return -ENOENT;
230
}
231
232
- if (spa_pod_filter(&b, &result.param, param, filter) < 0)
233
+ if (spa_pod_filter(&b.b, &result.param, param, filter) < 0)
234
goto next;
235
236
spa_node_emit_result(&this->hooks, seq, 0, SPA_RESULT_TYPE_NODE_PARAMS, &result);
237
238
const struct spa_pod *param)
239
{
240
struct state *this = object;
241
- int res;
242
+ int res = 0;
243
244
spa_return_val_if_fail(this != NULL, -EINVAL);
245
246
247
break;
248
case SPA_PARAM_Latency:
249
{
250
+ enum spa_direction other = SPA_DIRECTION_REVERSE(direction);
251
struct spa_latency_info info;
252
if (param == NULL)
253
- info = SPA_LATENCY_INFO(SPA_DIRECTION_REVERSE(direction));
254
+ info = SPA_LATENCY_INFO(other);
255
else if ((res = spa_latency_parse(param, &info)) < 0)
256
return res;
257
- if (direction == info.direction)
258
+ if (info.direction != other)
259
return -EINVAL;
260
261
this->latencyinfo.direction = info;
262
this->port_info.change_mask |= SPA_PORT_CHANGE_MASK_PARAMS;
263
this->port_paramsPORT_Latency.user++;
264
emit_port_info(this, false);
265
- res = 0;
266
+ break;
267
+ }
268
+ case SPA_PARAM_Tag:
269
+ {
270
+ enum spa_direction other = SPA_DIRECTION_REVERSE(direction);
271
+ if (param != NULL) {
272
+ struct spa_tag_info info;
273
+ void *state = NULL;
274
+ if (spa_tag_parse(param, &info, &state) < 0 ||
275
+ info.direction != other)
276
+ return -EINVAL;
277
+ }
278
+ if (spa_tag_compare(param, this->tagother) != 0) {
279
+ free(this->tagother);
280
+ this->tagother = param ? spa_pod_copy(param) : NULL;
281
+
282
+ this->port_info.change_mask |= SPA_PORT_CHANGE_MASK_PARAMS;
283
+ this->port_paramsPORT_Tag.user++;
284
+ emit_port_info(this, false);
285
+ }
286
break;
287
}
288
default:
289
290
this->port_paramsPORT_Format = SPA_PARAM_INFO(SPA_PARAM_Format, SPA_PARAM_INFO_WRITE);
291
this->port_paramsPORT_Buffers = SPA_PARAM_INFO(SPA_PARAM_Buffers, 0);
292
this->port_paramsPORT_Latency = SPA_PARAM_INFO(SPA_PARAM_Latency, SPA_PARAM_INFO_READWRITE);
293
+ this->port_paramsPORT_Tag = SPA_PARAM_INFO(SPA_PARAM_Tag, SPA_PARAM_INFO_READWRITE);
294
this->port_info.params = this->port_params;
295
this->port_info.n_params = N_PORT_PARAMS;
296
297
pipewire-0.3.81.tar.gz/spa/plugins/alsa/alsa-pcm.c -> pipewire-0.3.82.tar.gz/spa/plugins/alsa/alsa-pcm.c
Changed
138
1
2
state->multi_rate = spa_atob(s);
3
} else if (spa_streq(k, "api.alsa.htimestamp")) {
4
state->htimestamp = spa_atob(s);
5
+ } else if (spa_streq(k, "api.alsa.auto-link")) {
6
+ state->auto_link = spa_atob(s);
7
} else if (spa_streq(k, "latency.internal.rate")) {
8
state->process_latency.rate = atoi(s);
9
} else if (spa_streq(k, "latency.internal.ns")) {
10
11
12
state->multi_rate = true;
13
state->htimestamp = false;
14
- state->disable_tsched = state->is_pro;
15
for (i = 0; info && i < info->n_items; i++) {
16
const char *k = info->itemsi.key;
17
const char *s = info->itemsi.value;
18
19
spa_log_warn(state->log, "output close failed: %s", snd_strerror(err));
20
fclose(state->log_file);
21
22
+ free(state->tag0);
23
+ free(state->tag1);
24
+
25
return err;
26
}
27
28
29
30
CHECK(set_swparams(state), "swparams");
31
32
- if ((err = snd_pcm_prepare(state->hndl)) < 0 && err != -EBUSY) {
33
+ if ((!state->linked) && (err = snd_pcm_prepare(state->hndl)) < 0 && err != -EBUSY) {
34
spa_log_error(state->log, "%s: snd_pcm_prepare error: %s",
35
state->name, snd_strerror(err));
36
return err;
37
38
if (SPA_UNLIKELY((res = check_position_config(state)) < 0))
39
return res;
40
41
- if (SPA_UNLIKELY((res = get_status(state, current_time, &avail, &delay, &target)) < 0))
42
+ if (SPA_UNLIKELY((res = get_status(state, current_time, &avail, &delay, &target)) < 0)) {
43
+ spa_log_error(state->log, "get_status error");
44
+ state->next_time += state->threshold * 1e9 / state->rate;
45
return res;
46
+ }
47
48
- if (SPA_UNLIKELY(!following && delay > target + state->max_error)) {
49
+ if (SPA_UNLIKELY(!following && state->alsa_started && delay > target + state->max_error)) {
50
spa_log_trace(state->log, "%p: early wakeup %ld %lu %lu", state,
51
avail, delay, target);
52
if (delay > target * 3)
53
54
if (SPA_UNLIKELY((res = update_time(state, current_time, delay, target, following)) < 0))
55
return res;
56
57
- if (following && !state->linked) {
58
+ if (following && state->alsa_started && !state->linked) {
59
if (SPA_UNLIKELY(state->alsa_sync)) {
60
enum spa_log_level lev;
61
62
63
64
int spa_alsa_write(struct state *state)
65
{
66
- int res = 0;
67
if (state->following && state->rt.driver == NULL) {
68
uint64_t current_time = state->position->clock.nsec;
69
- if ((res = alsa_write_sync(state, current_time)) < 0)
70
- return res;
71
+ alsa_write_sync(state, current_time);
72
}
73
return alsa_write_frames(state);
74
}
75
76
if (SPA_UNLIKELY((res = check_position_config(state)) < 0))
77
return res;
78
79
- if (SPA_UNLIKELY((res = get_status(state, current_time, &avail, &delay, &target)) < 0))
80
+ if (SPA_UNLIKELY((res = get_status(state, current_time, &avail, &delay, &target)) < 0)) {
81
+ spa_log_error(state->log, "get_status error");
82
+ state->next_time += state->threshold * 1e9 / state->rate;
83
return res;
84
+ }
85
86
if (SPA_UNLIKELY(!following && avail < state->read_size)) {
87
spa_log_trace(state->log, "%p: early wakeup %ld %ld %ld %d", state,
88
89
return res;
90
91
max_read = state->buffer_frames;
92
- if (following) {
93
+ if (following && !state->linked) {
94
if (state->alsa_sync) {
95
enum spa_log_level lev;
96
97
98
99
int spa_alsa_read(struct state *state)
100
{
101
- int res;
102
if (state->following && state->rt.driver == NULL) {
103
uint64_t current_time = state->position->clock.nsec;
104
- if ((res = alsa_read_sync(state, current_time)) < 0)
105
- return res;
106
+ alsa_read_sync(state, current_time);
107
}
108
return alsa_read_frames(state);
109
}
110
111
struct state *follower;
112
int err;
113
114
+ if (!state->opened)
115
+ return -EIO;
116
+
117
spa_alsa_pause(state);
118
119
if (state->prepared)
120
121
spa_list_for_each(follower, &state->followers, driver_link) {
122
if (follower != state && !follower->matching) {
123
spa_alsa_prepare(follower);
124
- if (!follower->linked)
125
+ if (!follower->linked && state->auto_link)
126
do_link(state, follower);
127
}
128
}
129
130
131
if (state->started)
132
return 0;
133
+ else if (!state->opened)
134
+ return -EIO;
135
136
spa_alsa_prepare(state);
137
138
pipewire-0.3.81.tar.gz/spa/plugins/alsa/alsa-pcm.h -> pipewire-0.3.82.tar.gz/spa/plugins/alsa/alsa-pcm.h
Changed
36
1
2
#include <spa/param/param.h>
3
#include <spa/param/latency-utils.h>
4
#include <spa/param/audio/format-utils.h>
5
+#include <spa/param/tag-utils.h>
6
7
#include "alsa.h"
8
9
10
#define PORT_Format 3
11
#define PORT_Buffers 4
12
#define PORT_Latency 5
13
-#define N_PORT_PARAMS 6
14
+#define PORT_Tag 6
15
+#define N_PORT_PARAMS 7
16
struct spa_param_info port_paramsN_PORT_PARAMS;
17
enum spa_direction port_direction;
18
struct spa_io_buffers *io;
19
20
unsigned int htimestamp:1;
21
unsigned int is_pro:1;
22
unsigned int sources_added:1;
23
+ unsigned int auto_link:1;
24
unsigned int linked:1;
25
26
uint64_t iec958_codecs;
27
28
struct spa_latency_info latency2;
29
struct spa_process_latency_info process_latency;
30
31
+ struct spa_pod *tag2;
32
+
33
/* Rate match via an ALSA ctl */
34
snd_ctl_t *ctl;
35
snd_ctl_elem_value_t *pitch_elem;
36
pipewire-0.3.81.tar.gz/spa/plugins/alsa/alsa-seq-bridge.c -> pipewire-0.3.82.tar.gz/spa/plugins/alsa/alsa-seq-bridge.c
Changed
9
1
2
{ SPA_KEY_DEVICE_API, "alsa" },
3
{ SPA_KEY_MEDIA_CLASS, "Midi/Bridge" },
4
{ SPA_KEY_NODE_DRIVER, "true" },
5
+ { "priority.driver", "1" },
6
};
7
8
static void emit_node_info(struct seq_state *this, bool full)
9
pipewire-0.3.81.tar.gz/spa/plugins/alsa/alsa.c -> pipewire-0.3.82.tar.gz/spa/plugins/alsa/alsa.c
Changed
20
1
2
#include <spa/support/plugin.h>
3
#include <spa/support/log.h>
4
5
+#include "alsa.h"
6
+
7
extern const struct spa_handle_factory spa_alsa_source_factory;
8
extern const struct spa_handle_factory spa_alsa_sink_factory;
9
extern const struct spa_handle_factory spa_alsa_udev_factory;
10
11
extern const struct spa_handle_factory spa_alsa_compress_offload_device_factory;
12
#endif
13
14
-struct spa_log_topic log_topic = SPA_LOG_TOPIC(0, "spa.alsa");
15
-struct spa_log_topic *alsa_log_topic = &log_topic;
16
+struct spa_log_topic alsa_log_topic = SPA_LOG_TOPIC(0, "spa.alsa");
17
18
SPA_EXPORT
19
int spa_handle_factory_enum(const struct spa_handle_factory **factory, uint32_t *index)
20
pipewire-0.3.81.tar.gz/spa/plugins/alsa/alsa.h -> pipewire-0.3.82.tar.gz/spa/plugins/alsa/alsa.h
Changed
17
1
2
#include <spa/support/log.h>
3
4
#undef SPA_LOG_TOPIC_DEFAULT
5
-#define SPA_LOG_TOPIC_DEFAULT alsa_log_topic
6
-extern struct spa_log_topic *alsa_log_topic;
7
+#define SPA_LOG_TOPIC_DEFAULT &alsa_log_topic
8
+extern struct spa_log_topic alsa_log_topic;
9
10
static inline void alsa_log_topic_init(struct spa_log *log)
11
{
12
- spa_log_topic_init(log, alsa_log_topic);
13
+ spa_log_topic_init(log, &alsa_log_topic);
14
}
15
16
#endif /* SPA_ALSA_H */
17
pipewire-0.3.81.tar.gz/spa/plugins/audioconvert/audioadapter.c -> pipewire-0.3.82.tar.gz/spa/plugins/audioconvert/audioadapter.c
Changed
118
1
2
#include <spa/debug/log.h>
3
4
#undef SPA_LOG_TOPIC_DEFAULT
5
-#define SPA_LOG_TOPIC_DEFAULT log_topic
6
-static struct spa_log_topic *log_topic = &SPA_LOG_TOPIC(0, "spa.audioadapter");
7
+#define SPA_LOG_TOPIC_DEFAULT &log_topic
8
+static struct spa_log_topic log_topic = SPA_LOG_TOPIC(0, "spa.audioadapter");
9
10
#define DEFAULT_ALIGN 16
11
12
13
{
14
struct impl *this = object;
15
uint8_t buffer4096;
16
- struct spa_pod_dynamic_builder b;
17
+ spa_auto(spa_pod_dynamic_builder) b = { 0 };
18
+ struct spa_pod_builder_state state;
19
struct spa_result_node_params result;
20
uint32_t count = 0;
21
int res;
22
23
spa_return_val_if_fail(this != NULL, -EINVAL);
24
spa_return_val_if_fail(num != 0, -EINVAL);
25
26
+ spa_pod_dynamic_builder_init(&b, buffer, sizeof(buffer), 4096);
27
+ spa_pod_builder_get_state(&b.b, &state);
28
+
29
result.id = id;
30
result.next = start;
31
next:
32
33
34
spa_log_debug(this->log, "%p: %d id:%u", this, seq, id);
35
36
- spa_pod_dynamic_builder_init(&b, buffer, sizeof(buffer), 4096);
37
+ spa_pod_builder_reset(&b.b, &state);
38
39
switch (id) {
40
case SPA_PARAM_EnumPortConfig:
41
42
default:
43
return -ENOENT;
44
}
45
-
46
- if (res == 1) {
47
- spa_node_emit_result(&this->hooks, seq, 0, SPA_RESULT_TYPE_NODE_PARAMS, &result);
48
- count++;
49
- }
50
- spa_pod_dynamic_builder_clean(&b);
51
-
52
if (res != 1)
53
return res;
54
55
+ spa_node_emit_result(&this->hooks, seq, 0, SPA_RESULT_TYPE_NODE_PARAMS, &result);
56
+ count++;
57
+
58
if (count != num)
59
goto next;
60
61
62
static int recalc_tag(struct impl *this, struct spa_node *src, enum spa_direction direction,
63
uint32_t port_id, struct spa_node *dst)
64
{
65
- struct spa_pod_builder b = { 0 };
66
- uint8_t buffer1024;
67
+ spa_auto(spa_pod_dynamic_builder) b = { 0 };
68
+ struct spa_pod_builder_state state;
69
+ uint8_t buffer2048;
70
struct spa_pod *param;
71
uint32_t index = 0;
72
struct spa_tag_info info;
73
74
if (this->target == this->follower)
75
return 0;
76
77
+ spa_pod_dynamic_builder_init(&b, buffer, sizeof(buffer), 2048);
78
+ spa_pod_builder_get_state(&b.b, &state);
79
+
80
while (true) {
81
- void *state = NULL;
82
- spa_pod_builder_init(&b, buffer, sizeof(buffer));
83
+ void *tag_state = NULL;
84
+ spa_pod_builder_reset(&b.b, &state);
85
if ((res = spa_node_port_enum_params_sync(src,
86
direction, port_id, SPA_PARAM_Tag,
87
- &index, NULL, ¶m, &b)) != 1) {
88
+ &index, NULL, ¶m, &b.b)) != 1) {
89
param = NULL;
90
break;
91
}
92
- if ((res = spa_tag_parse(param, &info, &state)) < 0)
93
+ if ((res = spa_tag_parse(param, &info, &tag_state)) < 0)
94
return res;
95
if (info.direction == direction)
96
break;
97
}
98
- if ((res = spa_node_port_set_param(dst,
99
- SPA_DIRECTION_REVERSE(direction), 0,
100
- SPA_PARAM_Tag, 0, param)) < 0)
101
- return res;
102
-
103
- return 0;
104
+ return spa_node_port_set_param(dst, SPA_DIRECTION_REVERSE(direction), 0,
105
+ SPA_PARAM_Tag, 0, param);
106
}
107
108
109
110
this = (struct impl *) handle;
111
112
this->log = spa_support_find(support, n_support, SPA_TYPE_INTERFACE_Log);
113
- spa_log_topic_init(this->log, log_topic);
114
+ spa_log_topic_init(this->log, &log_topic);
115
116
this->cpu = spa_support_find(support, n_support, SPA_TYPE_INTERFACE_CPU);
117
118
pipewire-0.3.81.tar.gz/spa/plugins/audioconvert/audioconvert.c -> pipewire-0.3.82.tar.gz/spa/plugins/audioconvert/audioconvert.c
Changed
21
1
2
#include "wavfile.h"
3
4
#undef SPA_LOG_TOPIC_DEFAULT
5
-#define SPA_LOG_TOPIC_DEFAULT log_topic
6
-static struct spa_log_topic *log_topic = &SPA_LOG_TOPIC(0, "spa.audioconvert");
7
+#define SPA_LOG_TOPIC_DEFAULT &log_topic
8
+static struct spa_log_topic log_topic = SPA_LOG_TOPIC(0, "spa.audioconvert");
9
10
#define DEFAULT_RATE 48000
11
#define DEFAULT_CHANNELS 2
12
13
this = (struct impl *) handle;
14
15
this->log = spa_support_find(support, n_support, SPA_TYPE_INTERFACE_Log);
16
- spa_log_topic_init(this->log, log_topic);
17
+ spa_log_topic_init(this->log, &log_topic);
18
19
this->cpu = spa_support_find(support, n_support, SPA_TYPE_INTERFACE_CPU);
20
if (this->cpu) {
21
pipewire-0.3.81.tar.gz/spa/plugins/audiomixer/audiomixer.c -> pipewire-0.3.82.tar.gz/spa/plugins/audiomixer/audiomixer.c
Changed
21
1
2
#include "mix-ops.h"
3
4
#undef SPA_LOG_TOPIC_DEFAULT
5
-#define SPA_LOG_TOPIC_DEFAULT log_topic
6
-static struct spa_log_topic *log_topic = &SPA_LOG_TOPIC(0, "spa.audiomixer");
7
+#define SPA_LOG_TOPIC_DEFAULT &log_topic
8
+static struct spa_log_topic log_topic = SPA_LOG_TOPIC(0, "spa.audiomixer");
9
10
#define DEFAULT_RATE 48000
11
#define DEFAULT_CHANNELS 2
12
13
this = (struct impl *) handle;
14
15
this->log = spa_support_find(support, n_support, SPA_TYPE_INTERFACE_Log);
16
- spa_log_topic_init(this->log, log_topic);
17
+ spa_log_topic_init(this->log, &log_topic);
18
19
this->data_loop = spa_support_find(support, n_support, SPA_TYPE_INTERFACE_DataLoop);
20
if (this->data_loop == NULL) {
21
pipewire-0.3.81.tar.gz/spa/plugins/audiomixer/mixer-dsp.c -> pipewire-0.3.82.tar.gz/spa/plugins/audiomixer/mixer-dsp.c
Changed
21
1
2
#include "mix-ops.h"
3
4
#undef SPA_LOG_TOPIC_DEFAULT
5
-#define SPA_LOG_TOPIC_DEFAULT log_topic
6
-static struct spa_log_topic *log_topic = &SPA_LOG_TOPIC(0, "spa.mixer-dsp");
7
+#define SPA_LOG_TOPIC_DEFAULT &log_topic
8
+static struct spa_log_topic log_topic = SPA_LOG_TOPIC(0, "spa.mixer-dsp");
9
10
#define MAX_BUFFERS 64
11
#define MAX_PORTS 512
12
13
this = (struct impl *) handle;
14
15
this->log = spa_support_find(support, n_support, SPA_TYPE_INTERFACE_Log);
16
- spa_log_topic_init(this->log, log_topic);
17
+ spa_log_topic_init(this->log, &log_topic);
18
19
this->data_loop = spa_support_find(support, n_support, SPA_TYPE_INTERFACE_DataLoop);
20
if (this->data_loop == NULL) {
21
pipewire-0.3.81.tar.gz/spa/plugins/avb/avb.c -> pipewire-0.3.82.tar.gz/spa/plugins/avb/avb.c
Changed
16
1
2
#include <spa/support/plugin.h>
3
#include <spa/support/log.h>
4
5
+#include "avb.h"
6
+
7
extern const struct spa_handle_factory spa_avb_sink_factory;
8
extern const struct spa_handle_factory spa_avb_source_factory;
9
10
-struct spa_log_topic log_topic = SPA_LOG_TOPIC(0, "spa.avb");
11
-struct spa_log_topic *avb_log_topic = &log_topic;
12
+struct spa_log_topic avb_log_topic = SPA_LOG_TOPIC(0, "spa.avb");
13
14
SPA_EXPORT
15
int spa_handle_factory_enum(const struct spa_handle_factory **factory, uint32_t *index)
16
pipewire-0.3.81.tar.gz/spa/plugins/avb/avb.h -> pipewire-0.3.82.tar.gz/spa/plugins/avb/avb.h
Changed
17
1
2
#include <spa/support/log.h>
3
4
#undef SPA_LOG_TOPIC_DEFAULT
5
-#define SPA_LOG_TOPIC_DEFAULT avb_log_topic
6
-extern struct spa_log_topic *avb_log_topic;
7
+#define SPA_LOG_TOPIC_DEFAULT &avb_log_topic
8
+extern struct spa_log_topic avb_log_topic;
9
10
static inline void avb_log_topic_init(struct spa_log *log)
11
{
12
- spa_log_topic_init(log, avb_log_topic);
13
+ spa_log_topic_init(log, &avb_log_topic);
14
}
15
16
#endif /* SPA_AVB_H */
17
pipewire-0.3.81.tar.gz/spa/plugins/bluez5/sco-sink.c -> pipewire-0.3.82.tar.gz/spa/plugins/bluez5/sco-sink.c
Changed
29
1
2
3
/* Init mSBC if needed */
4
if (this->transport->codec == HFP_AUDIO_CODEC_MSBC) {
5
- sbc_init_msbc(&this->msbc, 0);
6
+ res = sbc_init_msbc(&this->msbc, 0);
7
+ if (res < 0)
8
+ return res;
9
/* Libsbc expects audio samples by default in host endianness, mSBC requires little endian */
10
this->msbc.endian = SBC_LE;
11
12
13
fail:
14
free(this->buffer);
15
this->buffer = NULL;
16
+ sbc_finish(&this->msbc);
17
return res;
18
}
19
20
21
this->buffer = NULL;
22
this->buffer_head = this->buffer_next = this->buffer;
23
}
24
+
25
+ sbc_finish(&this->msbc);
26
}
27
28
static int do_stop(struct impl *this)
29
pipewire-0.3.81.tar.gz/spa/plugins/bluez5/sco-source.c -> pipewire-0.3.82.tar.gz/spa/plugins/bluez5/sco-source.c
Changed
30
1
2
3
/* Init mSBC if needed */
4
if (this->transport->codec == HFP_AUDIO_CODEC_MSBC) {
5
- sbc_init_msbc(&this->msbc, 0);
6
+ res = sbc_init_msbc(&this->msbc, 0);
7
+ if (res < 0)
8
+ return res;
9
+
10
/* Libsbc expects audio samples by default in host endianness, mSBC requires little endian */
11
this->msbc.endian = SBC_LE;
12
this->msbc_seq_initialized = false;
13
14
return 0;
15
16
fail:
17
+ sbc_finish(&this->msbc);
18
return res;
19
}
20
21
22
spa_loop_invoke(this->data_loop, do_remove_transport_source, 0, NULL, 0, true, this);
23
24
spa_bt_decode_buffer_clear(&port->buffer);
25
+
26
+ sbc_finish(&this->msbc);
27
}
28
29
static int do_stop(struct impl *this)
30
pipewire-0.3.81.tar.gz/spa/plugins/libcamera/libcamera.c -> pipewire-0.3.82.tar.gz/spa/plugins/libcamera/libcamera.c
Changed
11
1
2
3
#include "libcamera.h"
4
5
-struct spa_log_topic log_topic = SPA_LOG_TOPIC(0, "spa.libcamera");
6
-struct spa_log_topic *libcamera_log_topic = &log_topic;
7
+struct spa_log_topic libcamera_log_topic = SPA_LOG_TOPIC(0, "spa.libcamera");
8
9
SPA_EXPORT
10
int spa_handle_factory_enum(const struct spa_handle_factory **factory,
11
pipewire-0.3.81.tar.gz/spa/plugins/libcamera/libcamera.h -> pipewire-0.3.82.tar.gz/spa/plugins/libcamera/libcamera.h
Changed
17
1
2
extern const struct spa_handle_factory spa_libcamera_device_factory;
3
4
#undef SPA_LOG_TOPIC_DEFAULT
5
-#define SPA_LOG_TOPIC_DEFAULT libcamera_log_topic
6
-extern struct spa_log_topic *libcamera_log_topic;
7
+#define SPA_LOG_TOPIC_DEFAULT &libcamera_log_topic
8
+extern struct spa_log_topic libcamera_log_topic;
9
10
static inline void libcamera_log_topic_init(struct spa_log *log)
11
{
12
- spa_log_topic_init(log, libcamera_log_topic);
13
+ spa_log_topic_init(log, &libcamera_log_topic);
14
}
15
16
#ifdef __cplusplus
17
pipewire-0.3.81.tar.gz/spa/plugins/support/log-patterns.c -> pipewire-0.3.82.tar.gz/spa/plugins/support/log-patterns.c
Changed
22
1
2
struct spa_log_topic *t)
3
{
4
enum spa_log_level level = default_level;
5
+ bool has_custom_level = false;
6
const char *topic = t->topic;
7
struct support_log_pattern *pattern;
8
9
10
if (fnmatch(pattern->pattern, topic, 0) != 0)
11
continue;
12
level = pattern->level;
13
- t->has_custom_level = true;
14
+ has_custom_level = true;
15
}
16
17
t->level = level;
18
+ t->has_custom_level = has_custom_level;
19
}
20
21
int
22
pipewire-0.3.81.tar.gz/spa/plugins/support/node-driver.c -> pipewire-0.3.82.tar.gz/spa/plugins/support/node-driver.c
Changed
77
1
2
#include <string.h>
3
#include <stdio.h>
4
#include <fcntl.h>
5
+#if !defined(__FreeBSD__) && !defined(__MidnightBSD__)
6
+#include <linux/ethtool.h>
7
+#include <linux/sockios.h>
8
+#endif
9
+#include <net/if.h>
10
11
#include <spa/support/plugin.h>
12
#include <spa/support/log.h>
13
14
return sizeof(struct impl);
15
}
16
17
+int get_phc_index(struct spa_system *s, const char *name) {
18
+#ifdef ETHTOOL_GET_TS_INFO
19
+ struct ethtool_ts_info info = {0};
20
+ struct ifreq ifr = {0};
21
+ int fd, err;
22
+
23
+ info.cmd = ETHTOOL_GET_TS_INFO;
24
+ strncpy(ifr.ifr_name, name, IFNAMSIZ - 1);
25
+ ifr.ifr_data = (char *) &info;
26
+ fd = socket(AF_INET, SOCK_DGRAM, 0);
27
+
28
+ if (fd < 0) {
29
+ return -1;
30
+ }
31
+
32
+ err = spa_system_ioctl(s, fd, SIOCETHTOOL, &ifr);
33
+ close(fd);
34
+ if (err < 0) {
35
+ return err;
36
+ }
37
+
38
+ return info.phc_index;
39
+#else
40
+ return -1;
41
+#endif
42
+}
43
+
44
static int
45
impl_init(const struct spa_handle_factory *factory,
46
struct spa_handle *handle,
47
48
this->props.clock_id = DEFAULT_CLOCK_ID;
49
}
50
} else if (spa_streq(k, "clock.device")) {
51
+ if (this->clock_fd >= 0) {
52
+ close(this->clock_fd);
53
+ }
54
this->clock_fd = open(s, O_RDWR);
55
+
56
+ if (this->clock_fd == -1) {
57
+ spa_log_warn(this->log, "failed to open clock device '%s'", s);
58
+ } else {
59
+ this->props.clock_id = FD_TO_CLOCKID(this->clock_fd);
60
+ }
61
+ } else if (spa_streq(k, "clock.interface") && this->clock_fd < 0) {
62
+ int phc_index = get_phc_index(this->data_system, s);
63
+ if (phc_index < 0) {
64
+ spa_log_warn(this->log, "failed to get phc device index for interface '%s'", s);
65
+ } else {
66
+ char dev19;
67
+ spa_scnprintf(dev, sizeof(dev), "/dev/ptp%d", phc_index);
68
+ this->clock_fd = open(dev, O_RDWR);
69
+ }
70
+
71
if (this->clock_fd == -1) {
72
- spa_log_info(this->log, "failed to open clock device '%s'", s);
73
+ spa_log_warn(this->log, "failed to open clock device '%s'", s);
74
} else {
75
this->props.clock_id = FD_TO_CLOCKID(this->clock_fd);
76
}
77
pipewire-0.3.81.tar.gz/spa/plugins/v4l2/v4l2.c -> pipewire-0.3.82.tar.gz/spa/plugins/v4l2/v4l2.c
Changed
17
1
2
#include <spa/support/plugin.h>
3
#include <spa/support/log.h>
4
5
+#include "v4l2.h"
6
+
7
extern const struct spa_handle_factory spa_v4l2_source_factory;
8
extern const struct spa_handle_factory spa_v4l2_udev_factory;
9
extern const struct spa_handle_factory spa_v4l2_device_factory;
10
11
-struct spa_log_topic log_topic = SPA_LOG_TOPIC(0, "spa.v4l2");
12
-struct spa_log_topic *v4l2_log_topic = &log_topic;
13
+struct spa_log_topic v4l2_log_topic = SPA_LOG_TOPIC(0, "spa.v4l2");
14
15
SPA_EXPORT
16
int spa_handle_factory_enum(const struct spa_handle_factory **factory,
17
pipewire-0.3.81.tar.gz/spa/plugins/v4l2/v4l2.h -> pipewire-0.3.82.tar.gz/spa/plugins/v4l2/v4l2.h
Changed
22
1
2
3
#include <errno.h>
4
5
+#include <linux/videodev2.h>
6
+
7
#include <spa/support/log.h>
8
9
#undef SPA_LOG_TOPIC_DEFAULT
10
-#define SPA_LOG_TOPIC_DEFAULT v4l2_log_topic
11
-extern struct spa_log_topic *v4l2_log_topic;
12
+#define SPA_LOG_TOPIC_DEFAULT &v4l2_log_topic
13
+extern struct spa_log_topic v4l2_log_topic;
14
15
static inline void v4l2_log_topic_init(struct spa_log *log)
16
{
17
- spa_log_topic_init(log, v4l2_log_topic);
18
+ spa_log_topic_init(log, &v4l2_log_topic);
19
}
20
21
struct spa_v4l2_device {
22
pipewire-0.3.81.tar.gz/spa/plugins/videoconvert/videoadapter.c -> pipewire-0.3.82.tar.gz/spa/plugins/videoconvert/videoadapter.c
Changed
21
1
2
#include <spa/debug/log.h>
3
4
#undef SPA_LOG_TOPIC_DEFAULT
5
-#define SPA_LOG_TOPIC_DEFAULT log_topic
6
-static struct spa_log_topic *log_topic = &SPA_LOG_TOPIC(0, "spa.videoadapter");
7
+#define SPA_LOG_TOPIC_DEFAULT &log_topic
8
+static struct spa_log_topic log_topic = SPA_LOG_TOPIC(0, "spa.videoadapter");
9
10
#define DEFAULT_ALIGN 16
11
12
13
this = (struct impl *) handle;
14
15
this->log = spa_support_find(support, n_support, SPA_TYPE_INTERFACE_Log);
16
- spa_log_topic_init(this->log, log_topic);
17
+ spa_log_topic_init(this->log, &log_topic);
18
19
this->cpu = spa_support_find(support, n_support, SPA_TYPE_INTERFACE_CPU);
20
21
pipewire-0.3.81.tar.gz/src/daemon/client-rt.conf.in -> pipewire-0.3.82.tar.gz/src/daemon/client-rt.conf.in
Changed
9
1
2
3
4
alsa.properties = {
5
+ #alsa.deny = false
6
# ALSA params take a single value, an array of values
7
# or a range { min=.. max=... }
8
#alsa.access = MMAP_INTERLEAVED MMAP_NONINTERLEAVED RW_INTERLEAVED RW_NONINTERLEAVED
9
pipewire-0.3.81.tar.gz/src/daemon/pipewire-aes67.conf.in -> pipewire-0.3.82.tar.gz/src/daemon/pipewire-aes67.conf.in
Changed
27
1
2
}
3
4
context.objects =
5
- # An example clock reading from /dev/ptp0. Another option is to sync the
6
- # ptp clock to CLOCK_TAI and then set clock.id = tai.
7
- # If both device and ID are given and available, device takes precedence
8
+ # An example clock reading from /dev/ptp0. You can also specify the network interface name,
9
+ # pipewire will query the interface for the current active PHC index. Another option is to
10
+ # sync the ptp clock to CLOCK_TAI and then set clock.id = tai, keep in mind that tai may
11
+ # also be synced by a NTP client.
12
+ # The precedence is: device, interface, id
13
{ factory = spa-node-factory
14
args = {
15
factory.name = support.node.driver
16
17
# This driver should only be used for network nodes marked with group
18
priority.driver = 0
19
clock.name = "clock.system.ptp0"
20
+ #clock.id = tai
21
clock.device = "/dev/ptp0"
22
- clock.id = tai
23
+ #clock.interface = "eth0"
24
object.export = true
25
}
26
}
27
pipewire-0.3.81.tar.gz/src/daemon/pipewire.conf.in -> pipewire-0.3.82.tar.gz/src/daemon/pipewire.conf.in
Changed
15
1
2
}
3
4
# The native communication protocol.
5
- { name = libpipewire-module-protocol-native }
6
+ { name = libpipewire-module-protocol-native
7
+ args = {
8
+ # List of server Unix sockets, and optionally permissions
9
+ #sockets = { name = "pipewire-0" }, { name = "pipewire-manager-0" }
10
+ }
11
+ }
12
13
# The profile module. Allows application to access profiler
14
# and performance data. It provides an interface that is used
15
pipewire-0.3.81.tar.gz/src/modules/flatpak-utils.h -> pipewire-0.3.82.tar.gz/src/modules/flatpak-utils.h
Changed
31
1
2
spa_autoclose int root_fd = openat(AT_FDCWD, root_path, O_RDONLY | O_NONBLOCK | O_DIRECTORY | O_CLOEXEC | O_NOCTTY);
3
if (root_fd < 0) {
4
res = -errno;
5
+ pw_log_info("failed to open \"%s\": %s", root_path, spa_strerror(res));
6
+
7
if (res == -EACCES) {
8
- struct statfs buf;
9
- /* Access to the root dir isn't allowed. This can happen if the root is on a fuse
10
- * filesystem, such as in a toolbox container. We will never have a fuse rootfs
11
- * in the flatpak case, so in that case its safe to ignore this and
12
- * continue to detect other types of apps. */
13
- if (statfs(root_path, &buf) == 0 &&
14
- buf.f_type == 0x65735546) /* FUSE_SUPER_MAGIC */
15
- return 0;
16
+ /* If we can't access the root filesystem, consider not sandboxed.
17
+ * This should not happen but for now it is a workaround for selinux
18
+ * where we can't access the gnome-shell root when it connects for
19
+ * screen sharing.
20
+ */
21
+ return 0;
22
}
23
+
24
/* Not able to open the root dir shouldn't happen. Probably the app died and
25
* we're failing due to /proc/$pid not existing. In that case fail instead
26
* of treating this as privileged. */
27
- pw_log_info("failed to open \"%s\": %s", root_path, spa_strerror(res));
28
return res;
29
}
30
31
pipewire-0.3.81.tar.gz/src/modules/meson.build -> pipewire-0.3.82.tar.gz/src/modules/meson.build
Changed
28
1
2
pipewire_module_protocol_deps += systemd_dep
3
endif
4
5
+if selinux_dep.found()
6
+ pipewire_module_protocol_deps += selinux_dep
7
+endif
8
+
9
pipewire_module_protocol_native = shared_library('pipewire-module-protocol-native',
10
'module-protocol-native.c',
11
'module-protocol-native/local-socket.c',
12
13
if build_module_raop
14
pipewire_module_raop_sink = shared_library('pipewire-module-raop-sink',
15
'module-raop-sink.c',
16
- 'module-raop/rtsp-client.c' ,
17
+ 'module-raop/rtsp-client.c',
18
+ 'module-rtp/stream.c' ,
19
include_directories : configinc,
20
install : true,
21
install_dir : modules_install_dir,
22
install_rpath: modules_install_dir,
23
- dependencies : mathlib, dl_lib, rt_lib, pipewire_dep, openssl_lib,
24
+ dependencies : mathlib, dl_lib, rt_lib, pipewire_dep, opus_dep, openssl_lib,
25
)
26
endif
27
summary({'raop-sink (requires OpenSSL)': build_module_raop}, bool_yn: true, section: 'Optional Modules')
28
pipewire-0.3.81.tar.gz/src/modules/module-access.c -> pipewire-0.3.82.tar.gz/src/modules/module-access.c
Changed
21
1
2
3
res = pw_check_flatpak(pid, &flatpak_app_id, NULL);
4
if (res != 0) {
5
- if (res < 0) {
6
- if (res == -EACCES) {
7
- access = "unrestricted";
8
- goto granted;
9
- }
10
+ if (res < 0)
11
pw_log_warn("%p: client %p sandbox check failed: %s",
12
impl, client, spa_strerror(res));
13
- }
14
- else if (res > 0) {
15
+ else
16
pw_log_debug(" %p: flatpak client %p added", impl, client);
17
- }
18
access = "flatpak";
19
itemsnitems++ = SPA_DICT_ITEM_INIT("pipewire.access.portal.app_id",
20
flatpak_app_id);
21
pipewire-0.3.81.tar.gz/src/modules/module-filter-chain.c -> pipewire-0.3.82.tar.gz/src/modules/module-filter-chain.c
Changed
21
1
2
*
3
* Normally the volume of the sink/source is handled by the stream software volume.
4
* With the capture.volumes and playback.volumes properties this can be handled
5
- * by a control port in the graph instead.
6
+ * by a control port in the graph instead. Use capture.volumes for the volume of the
7
+ * input of the filter (when for example used as a sink). Use playback,volumes for
8
+ * the volume of the output of the filter (when for example used as a source).
9
*
10
* The min and max values (defaults 0.0 and 1.0) respectively can be used to scale
11
* and translate the volume min and max values.
12
13
/**
14
* {
15
* control = name:portname
16
- * min = <float, defaukt 0.0>
17
+ * min = <float, default 0.0>
18
* max = <float, default 1.0>
19
* scale = <string, default "linear", options "linear","cubic">
20
* }
21
pipewire-0.3.81.tar.gz/src/modules/module-protocol-native.c -> pipewire-0.3.82.tar.gz/src/modules/module-protocol-native.c
Changed
358
1
2
#include <fcntl.h>
3
#include <sys/file.h>
4
#include <ctype.h>
5
+#include <limits.h>
6
#ifdef HAVE_PWD_H
7
#include <pwd.h>
8
#endif
9
+#ifdef HAVE_GRP_H
10
+#include <grp.h>
11
+#endif
12
#if defined(__FreeBSD__) || defined(__MidnightBSD__)
13
#include <sys/ucred.h>
14
#endif
15
16
#include <spa/pod/builder.h>
17
#include <spa/utils/result.h>
18
#include <spa/utils/string.h>
19
+#include <spa/utils/json.h>
20
21
#ifdef HAVE_SYSTEMD
22
#include <systemd/sd-daemon.h>
23
#endif
24
25
+#ifdef HAVE_SELINUX
26
+#include <selinux/selinux.h>
27
+#endif
28
+
29
#include <pipewire/impl.h>
30
#include <pipewire/extensions/protocol-native.h>
31
+#include <pipewire/cleanup.h>
32
33
#include "pipewire/private.h"
34
35
36
*
37
* ## Module Options
38
*
39
- * The module has no options.
40
+ * The module supports the following arguments:
41
+ *
42
+ * - `sockets`: ` { name = "socket-name", owner = "owner", group = "group", mode = "mode", selinux.context = "context" }, ... `
43
+ *
44
+ * Array of Unix socket names and (optionally) owner/permissions to serve,
45
+ * if the context is a server. If not absolute paths, the sockets are created
46
+ * in the default runtime directory. If not specified, one socket with
47
+ * a default name is created.
48
+ *
49
+ * The permissions have no effect for sockets from Systemd socket activation.
50
+ * Those should be configured via the systemd.socket(5) mechanism.
51
*
52
* ## General Options
53
*
54
55
{ name = libpipewire-module-protocol-native }
56
*
57
*\endcode
58
+ *
59
+ *\code{.unparsed}
60
+ * context.modules =
61
+ * { name = libpipewire-module-protocol-native,
62
+ * args = { sockets = { name = "pipewire-0" }, { name = "pipewire-1" } } }
63
+ *
64
+ *\endcode
65
*/
66
67
#ifndef UNIX_PATH_MAX
68
69
free(impl);
70
}
71
72
+struct socket_info {
73
+ char *name;
74
+ uid_t uid;
75
+ gid_t gid;
76
+ int mode;
77
+ char *selinux_context;
78
+ unsigned int has_owner:1;
79
+ unsigned int has_mode:1;
80
+};
81
+
82
struct server {
83
struct pw_protocol_server this;
84
85
int fd_lock;
86
struct sockaddr_un addr;
87
char lock_addrUNIX_PATH_MAX + LOCK_SUFFIXLEN;
88
+ struct socket_info socket_info;
89
90
struct pw_loop *loop;
91
struct spa_source *source;
92
93
if (props == NULL)
94
goto exit;
95
96
+ pw_properties_set(props, PW_KEY_SEC_SOCKET, s->socket_info.name);
97
+
98
#if defined(__linux__)
99
len = sizeof(ucred);
100
if (getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &ucred, &len) < 0) {
101
102
return res;
103
}
104
105
+static int set_socket_permissions(struct server *s)
106
+{
107
+ struct socket_info *info = &s->socket_info;
108
+ const char *path = s->addr.sun_path;
109
+
110
+ if (info->has_owner)
111
+ if (chown(path, info->uid, info->gid) < 0)
112
+ return -errno;
113
+
114
+ if (info->has_mode)
115
+ if (chmod(path, info->mode) < 0)
116
+ return -errno;
117
+
118
+ if (info->selinux_context) {
119
+#ifdef HAVE_SELINUX
120
+ if (setfilecon(path, info->selinux_context) < 0)
121
+ return -errno;
122
+#else
123
+ return -EOPNOTSUPP;
124
+#endif
125
+ }
126
+
127
+ return 0;
128
+}
129
+
130
static int add_socket(struct pw_protocol *protocol, struct server *s)
131
{
132
socklen_t size;
133
134
goto error_close;
135
}
136
137
+ if ((res = set_socket_permissions(s)) < 0) {
138
+ errno = -res;
139
+ pw_log_error("server %p: failed to set socket %s permissions: %m",
140
+ s, s->socket_info.name);
141
+ goto error_close;
142
+ }
143
+
144
if (listen(fd, 128) < 0) {
145
res = -errno;
146
pw_log_error("server %p: listen() failed with error: %m", s);
147
goto error_close;
148
}
149
+ } else {
150
+ if (s->socket_info.has_owner || s->socket_info.has_mode || s->socket_info.selinux_context)
151
+ pw_log_info("server %p: permissions ignored for socket %s from systemd",
152
+ s, s->socket_info.name);
153
}
154
155
res = write_socket_address(s);
156
157
unlink(s->lock_addr);
158
if (s->fd_lock != -1)
159
close(s->fd_lock);
160
+ free(s->socket_info.name);
161
+ free(s->socket_info.selinux_context);
162
free(s);
163
}
164
165
166
}
167
168
static struct pw_protocol_server *
169
-impl_add_server(struct pw_protocol *protocol,
170
+add_server(struct pw_protocol *protocol,
171
struct pw_impl_core *core,
172
- const struct spa_dict *props)
173
+ const struct spa_dict *props,
174
+ struct socket_info *socket_info)
175
{
176
struct pw_protocol_server *this;
177
struct server *s;
178
179
180
this = &s->this;
181
182
- name = get_server_name(props);
183
+ if (socket_info) {
184
+ s->socket_info = *socket_info;
185
+ s->socket_info.name = strdup(socket_info->name);
186
+ s->socket_info.selinux_context = socket_info->selinux_context ?
187
+ strdup(socket_info->selinux_context) : NULL;
188
+ name = socket_info->name;
189
+ } else {
190
+ name = get_server_name(props);
191
+ s->socket_info.name = strdup(name);
192
+ }
193
194
if ((res = init_socket_name(s, name)) < 0)
195
goto error;
196
197
return NULL;
198
}
199
200
+static struct pw_protocol_server *
201
+impl_add_server(struct pw_protocol *protocol,
202
+ struct pw_impl_core *core,
203
+ const struct spa_dict *props)
204
+{
205
+ return add_server(protocol, core, props, NULL);
206
+}
207
+
208
static const struct pw_protocol_implementation protocol_impl = {
209
PW_VERSION_PROTOCOL_IMPLEMENTATION,
210
.new_client = impl_new_client,
211
212
return 0;
213
}
214
215
+static int create_servers(struct pw_protocol *this, struct pw_impl_core *core,
216
+ const struct pw_properties *props, const struct pw_properties *args)
217
+{
218
+ const char *sockets = args ? pw_properties_get(args, "sockets") : NULL;
219
+ struct spa_json it3;
220
+
221
+ if (sockets == NULL) {
222
+ if (add_server(this, core, &props->dict, NULL) == NULL)
223
+ return -errno;
224
+
225
+ return 0;
226
+ }
227
+
228
+ spa_json_init(&it0, sockets, strlen(sockets));
229
+
230
+ if (spa_json_enter_array(&it0, &it1) <= 0)
231
+ goto error_invalid;
232
+
233
+ while (spa_json_enter_object(&it1, &it2) > 0) {
234
+ struct socket_info info = {0};
235
+ char key256;
236
+ char namePATH_MAX;
237
+ char selinux_contextPATH_MAX;
238
+
239
+ info.uid = getuid();
240
+ info.gid = getgid();
241
+
242
+ while (spa_json_get_string(&it2, key, sizeof(key)) > 0) {
243
+ const char *value;
244
+ int len;
245
+
246
+ if ((len = spa_json_next(&it2, &value)) <= 0)
247
+ goto error_invalid;
248
+
249
+ if (spa_streq(key, "name")) {
250
+ if (spa_json_parse_stringn(value, len, name, sizeof(name)) < 0)
251
+ goto error_invalid;
252
+ info.name = name;
253
+ } else if (spa_streq(key, "selinux.context")) {
254
+ if (spa_json_parse_stringn(value, len, selinux_context, sizeof(selinux_context)) < 0)
255
+ goto error_invalid;
256
+ info.selinux_context = selinux_context;
257
+ } else if (spa_streq(key, "owner")) {
258
+ char buffer16384;
259
+ char ownerPATH_MAX;
260
+ struct passwd pwd, *result = NULL;
261
+ int64_t val;
262
+
263
+ if (spa_json_parse_stringn(value, len, owner, sizeof(owner)) < 0)
264
+ goto error_invalid;
265
+
266
+ if (spa_atoi64(owner, &val, 10))
267
+ info.uid = val;
268
+ else if (getpwnam_r(owner, &pwd, buffer, sizeof(buffer), &result) == 0 && result)
269
+ info.uid = result->pw_uid;
270
+ else
271
+ goto error_invalid;
272
+
273
+ info.has_owner = true;
274
+ } else if (spa_streq(key, "group")) {
275
+ char buffer16384;
276
+ char groupPATH_MAX;
277
+ struct group grp, *result = NULL;
278
+ int64_t val;
279
+
280
+ if (spa_json_parse_stringn(value, len, group, sizeof(group)) < 0)
281
+ goto error_invalid;
282
+
283
+ if (spa_atoi64(group, &val, 10))
284
+ info.gid = val;
285
+ else if (getgrnam_r(group, &grp, buffer, sizeof(buffer), &result) == 0 && result)
286
+ info.gid = result->gr_gid;
287
+ else
288
+ goto error_invalid;
289
+
290
+ info.has_owner = true;
291
+ } else if (spa_streq(key, "mode")) {
292
+ char modePATH_MAX;
293
+ int64_t val;
294
+
295
+ if (spa_json_parse_stringn(value, len, mode, sizeof(mode)) < 0)
296
+ goto error_invalid;
297
+
298
+ if (spa_atoi64(mode, &val, 0))
299
+ info.mode = val;
300
+ else
301
+ goto error_invalid;
302
+
303
+ info.has_mode = true;
304
+ }
305
+ }
306
+
307
+ if (info.name == NULL)
308
+ goto error_invalid;
309
+
310
+ if (add_server(this, core, &props->dict, &info) == NULL)
311
+ return -errno;
312
+ }
313
+
314
+ return 0;
315
+
316
+error_invalid:
317
+ pw_log_error("invalid module 'sockets' argument: %s", sockets);
318
+ return -EINVAL;
319
+}
320
+
321
SPA_EXPORT
322
-int pipewire__module_init(struct pw_impl_module *module, const char *args)
323
+int pipewire__module_init(struct pw_impl_module *module, const char *args_str)
324
{
325
struct pw_context *context = pw_impl_module_get_context(module);
326
struct pw_protocol *this;
327
struct pw_impl_core *core = context->core;
328
struct protocol_data *d;
329
const struct pw_properties *props;
330
+ spa_autoptr(pw_properties) args = NULL;
331
int res;
332
333
PW_LOG_TOPIC_INIT(mod_topic);
334
335
return -EEXIST;
336
}
337
338
+ args = args_str ? pw_properties_new_string(args_str) : NULL;
339
+
340
this = pw_protocol_new(context, PW_TYPE_INFO_PROTOCOL_Native, sizeof(struct protocol_data));
341
if (this == NULL)
342
return -errno;
343
344
props = pw_context_get_properties(context);
345
d->local = create_server(this, core, &props->dict);
346
347
- if (need_server(context, &props->dict)) {
348
- if (impl_add_server(this, core, &props->dict) == NULL) {
349
- res = -errno;
350
+ if (need_server(context, &props->dict))
351
+ if ((res = create_servers(this, core, props, args)) < 0)
352
goto error_cleanup;
353
- }
354
- }
355
356
pw_impl_module_add_listener(module, &d->module_listener, &module_events, d);
357
358
pipewire-0.3.81.tar.gz/src/modules/module-protocol-pulse/manager.h -> pipewire-0.3.82.tar.gz/src/modules/module-protocol-pulse/manager.h
Changed
27
1
2
extern "C" {
3
#endif
4
5
+#include <stdio.h>
6
+
7
#include <spa/utils/defs.h>
8
#include <spa/pod/pod.h>
9
10
#include <pipewire/pipewire.h>
11
12
+struct client;
13
struct pw_manager_object;
14
15
struct pw_manager_events {
16
17
struct pw_properties *props;
18
struct pw_proxy *proxy;
19
char *message_object_path;
20
- int (*message_handler)(struct pw_manager *m, struct pw_manager_object *o,
21
- const char *message, const char *params, char **response);
22
+ int (*message_handler)(struct client *client, struct pw_manager_object *o,
23
+ const char *message, const char *params, FILE *response);
24
25
void *info;
26
struct spa_param_info *params;
27
pipewire-0.3.81.tar.gz/src/modules/module-protocol-pulse/message-handler.c -> pipewire-0.3.82.tar.gz/src/modules/module-protocol-pulse/message-handler.c
Changed
119
1
2
/* SPDX-License-Identifier: MIT */
3
4
#include <stdint.h>
5
+#include <stdio.h>
6
7
#include <regex.h>
8
+#include <malloc.h>
9
10
#include <spa/param/props.h>
11
#include <spa/pod/builder.h>
12
13
14
#include <pipewire/pipewire.h>
15
16
+#include "client.h"
17
#include "collect.h"
18
#include "log.h"
19
#include "manager.h"
20
#include "message-handler.h"
21
22
-static int bluez_card_object_message_handler(struct pw_manager *m, struct pw_manager_object *o, const char *message, const char *params, char **response)
23
+static int bluez_card_object_message_handler(struct client *client, struct pw_manager_object *o, const char *message, const char *params, FILE *response)
24
{
25
struct transport_codec_info codecs64;
26
uint32_t n_codecs, active;
27
28
29
pw_device_set_param((struct pw_device *)o->proxy,
30
SPA_PARAM_Props, 0, param);
31
- return 0;
32
} else if (spa_streq(message, "list-codecs")) {
33
uint32_t i;
34
- FILE *r;
35
- size_t size;
36
bool first = true;
37
38
- r = open_memstream(response, &size);
39
- if (r == NULL)
40
- return -errno;
41
-
42
- fputc('', r);
43
+ fputc('', response);
44
for (i = 0; i < n_codecs; ++i) {
45
const char *desc = codecsi.description;
46
- fprintf(r, "%s{\"name\":\"%d\",\"description\":\"%s\"}",
47
+ fprintf(response, "%s{\"name\":\"%d\",\"description\":\"%s\"}",
48
first ? "" : ",",
49
(int)codecsi.id, desc ? desc : "Unknown");
50
first = false;
51
}
52
- fputc('', r);
53
-
54
- return fclose(r) ? -errno : 0;
55
+ fputc('', response);
56
} else if (spa_streq(message, "get-codec")) {
57
if (active == SPA_ID_INVALID)
58
- *response = strdup("null");
59
+ fputs("null", response);
60
else
61
- *response = spa_aprintf("\"%d\"", (int)codecsactive.id);
62
- return *response ? 0 : -ENOMEM;
63
+ fprintf(response, "\"%d\"", (int) codecsactive.id);
64
+ } else {
65
+ return -ENOSYS;
66
}
67
68
- return -ENOSYS;
69
+ return 0;
70
}
71
72
-static int core_object_message_handler(struct pw_manager *m, struct pw_manager_object *o, const char *message, const char *params, char **response)
73
+static int core_object_message_handler(struct client *client, struct pw_manager_object *o, const char *message, const char *params, FILE *response)
74
{
75
pw_log_debug(": core %p object message:'%s' params:'%s'", o, message, params);
76
77
if (spa_streq(message, "list-handlers")) {
78
- FILE *r;
79
- size_t size;
80
bool first = true;
81
82
- r = open_memstream(response, &size);
83
- if (r == NULL)
84
- return -errno;
85
-
86
- fputc('', r);
87
- spa_list_for_each(o, &m->object_list, link) {
88
+ fputc('', response);
89
+ spa_list_for_each(o, &client->manager->object_list, link) {
90
if (o->message_object_path) {
91
- fprintf(r, "%s{\"name\":\"%s\",\"description\":\"%s\"}",
92
+ fprintf(response, "%s{\"name\":\"%s\",\"description\":\"%s\"}",
93
first ? "" : ",",
94
o->message_object_path, o->type);
95
first = false;
96
}
97
}
98
- fputc('', r);
99
- return fclose(r) ? -errno : 0;
100
+ fputc('', response);
101
+#ifdef HAVE_MALLOC_INFO
102
+ } else if (spa_streq(message, "pipewire-pulse:malloc-info")) {
103
+ malloc_info(0, response);
104
+#endif
105
+#ifdef HAVE_MALLOC_TRIM
106
+ } else if (spa_streq(message, "pipewire-pulse:malloc-trim")) {
107
+ int res = malloc_trim(0);
108
+ fprintf(response, "%d", res);
109
+#endif
110
+ } else {
111
+ return -ENOSYS;
112
}
113
114
- return -ENOSYS;
115
+ return 0;
116
}
117
118
void register_object_message_handlers(struct pw_manager_object *o)
119
pipewire-0.3.81.tar.gz/src/modules/module-protocol-pulse/pulse-server.c -> pipewire-0.3.82.tar.gz/src/modules/module-protocol-pulse/pulse-server.c
Changed
101
1
2
PW_STREAM_FLAG_MAP_BUFFERS,
3
params, n_params);
4
5
+ stream_update_tag_param(stream);
6
+
7
return 0;
8
9
error_errno:
10
11
if (stream == NULL || stream->type == STREAM_TYPE_UPLOAD)
12
return -ENOENT;
13
14
- pw_stream_update_properties(stream->stream, &props->dict);
15
+ if (pw_stream_update_properties(stream->stream, &props->dict) > 0)
16
+ stream_update_tag_param(stream);
17
} else {
18
if (pw_properties_update(client->props, &props->dict) > 0) {
19
client_update_quirks(client);
20
21
{
22
struct impl *impl = client->impl;
23
struct pw_manager *manager = client->manager;
24
- const char *object_path = NULL;
25
- const char *message = NULL;
26
- const char *params = NULL;
27
- struct message *reply;
28
+ const char *object_path = NULL, *message = NULL, *params = NULL;
29
struct pw_manager_object *o;
30
- int len = 0;
31
+ spa_autofree char *response_str = NULL;
32
+ size_t path_len = 0, response_len = 0;
33
+ FILE *response;
34
+ int res = -ENOENT;
35
36
if (message_get(m,
37
TAG_STRING, &object_path,
38
39
if (object_path == NULL || message == NULL)
40
return -EINVAL;
41
42
- len = strlen(object_path);
43
- if (len > 0 && object_pathlen - 1 == '/')
44
- --len;
45
-
46
- spa_autofree char *path = strndup(object_path, len);
47
+ path_len = strlen(object_path);
48
+ if (path_len > 0 && object_pathpath_len - 1 == '/')
49
+ --path_len;
50
+ spa_autofree char *path = strndup(object_path, path_len);
51
if (path == NULL)
52
return -ENOMEM;
53
54
- spa_autofree char *response = NULL;
55
- int res = -ENOENT;
56
-
57
spa_list_for_each(o, &manager->object_list, link) {
58
- if (o->message_object_path && spa_streq(o->message_object_path, path)) {
59
- if (o->message_handler)
60
- res = o->message_handler(manager, o, message, params, &response);
61
- else
62
- res = -ENOSYS;
63
+ if (spa_streq(o->message_object_path, path))
64
break;
65
- }
66
}
67
+ if (spa_list_is_end(o, &manager->object_list, link))
68
+ return -ENOENT;
69
70
- if (res < 0)
71
- return res;
72
+ if (o->message_handler == NULL)
73
+ return -ENOSYS;
74
75
- pw_log_debug("%p: object message response:'%s'", impl, response ? response : "<null>");
76
+ response = open_memstream(&response_str, &response_len);
77
+ if (response == NULL)
78
+ return -errno;
79
80
- reply = reply_new(client, tag);
81
- message_put(reply, TAG_STRING, response, TAG_INVALID);
82
+ res = o->message_handler(client, o, message, params, response);
83
84
- return client_queue_message(client, reply);
85
+ if (fclose(response))
86
+ return -errno;
87
+
88
+ pw_log_debug("%p: object message response: (%d) '%s'", impl, res, response_str ? response_str : "<null>");
89
+
90
+ if (res >= 0) {
91
+ struct message *reply = reply_new(client, tag);
92
+
93
+ message_put(reply, TAG_STRING, response_str, TAG_INVALID);
94
+ res = client_queue_message(client, reply);
95
+ }
96
+
97
+ return res;
98
}
99
100
static int do_error_access(struct client *client, uint32_t command, uint32_t tag, struct message *m)
101
pipewire-0.3.81.tar.gz/src/modules/module-protocol-pulse/stream.c -> pipewire-0.3.82.tar.gz/src/modules/module-protocol-pulse/stream.c
Changed
48
1
2
3
#include <spa/utils/hook.h>
4
#include <spa/utils/ringbuffer.h>
5
+#include <spa/pod/dynamic.h>
6
+#include <spa/param/tag-utils.h>
7
+
8
#include <pipewire/log.h>
9
#include <pipewire/loop.h>
10
#include <pipewire/map.h>
11
12
}
13
return client_queue_message(client, reply);
14
}
15
+
16
+int stream_update_tag_param(struct stream *stream)
17
+{
18
+ struct spa_pod_dynamic_builder b;
19
+ const struct pw_properties *props = pw_stream_get_properties(stream->stream);
20
+ const struct spa_pod *param1;
21
+ struct spa_dict_item items64;
22
+ uint32_t i, n_items = 0;
23
+ uint8_t buffer4096;
24
+
25
+ if (props == NULL)
26
+ return -EIO;
27
+
28
+ spa_pod_dynamic_builder_init(&b, buffer, sizeof(buffer), 4096);
29
+
30
+ for (i = 0; i < props->dict.n_items; i++) {
31
+ if (n_items < SPA_N_ELEMENTS(items) &&
32
+ spa_strstartswith(props->dict.itemsi.key, "media."))
33
+ itemsn_items++ = props->dict.itemsi;
34
+ }
35
+ if (n_items > 0) {
36
+ struct spa_pod_frame f;
37
+ spa_tag_build_start(&b.b, &f, SPA_PARAM_Tag, SPA_DIRECTION_OUTPUT);
38
+ spa_tag_build_add_dict(&b.b, &SPA_DICT_INIT(items, n_items));
39
+ param0 = spa_tag_build_end(&b.b, &f);
40
+ } else {
41
+ param0 = NULL;
42
+ }
43
+ if (param0 != NULL)
44
+ pw_stream_update_params(stream->stream, param, 1);
45
+ spa_pod_dynamic_builder_clean(&b);
46
+ return 0;
47
+}
48
pipewire-0.3.81.tar.gz/src/modules/module-protocol-pulse/stream.h -> pipewire-0.3.82.tar.gz/src/modules/module-protocol-pulse/stream.h
Changed
8
1
2
int stream_send_request(struct stream *stream);
3
int stream_update_minreq(struct stream *stream, uint32_t minreq);
4
int stream_send_moved(struct stream *stream, uint32_t peer_index, const char *peer_name);
5
+int stream_update_tag_param(struct stream *stream);
6
7
#endif /* PULSER_SERVER_STREAM_H */
8
pipewire-0.3.81.tar.gz/src/modules/module-raop-sink.c -> pipewire-0.3.82.tar.gz/src/modules/module-raop-sink.c
Changed
1019
1
2
3
#include "module-raop/rtsp-client.h"
4
#include "module-rtp/rtp.h"
5
+#include "module-rtp/stream.h"
6
7
/** \page page_module_raop_sink PipeWire Module: AirPlay Sink
8
*
9
10
PW_LOG_TOPIC_STATIC(mod_topic, "mod." NAME);
11
#define PW_LOG_TOPIC_DEFAULT mod_topic
12
13
-#define FRAMES_PER_TCP_PACKET 4096
14
-#define FRAMES_PER_UDP_PACKET 352
15
+#define BUFFER_SIZE (1u<<22)
16
+#define BUFFER_MASK (BUFFER_SIZE-1)
17
+#define BUFFER_SIZE2 (BUFFER_SIZE>>1)
18
+#define BUFFER_MASK2 (BUFFER_SIZE2-1)
19
20
-#define RAOP_LATENCY_MIN 11025u
21
-#define DEFAULT_LATENCY_MS "1500"
22
+#define FRAMES_PER_TCP_PACKET 4096
23
+#define FRAMES_PER_UDP_PACKET 352
24
25
-#define DEFAULT_TCP_AUDIO_PORT 6000
26
-#define DEFAULT_UDP_AUDIO_PORT 6000
27
-#define DEFAULT_UDP_CONTROL_PORT 6001
28
-#define DEFAULT_UDP_TIMING_PORT 6002
29
+#define RAOP_AUDIO_PORT 6000
30
+#define RAOP_UDP_CONTROL_PORT 6001
31
+#define RAOP_UDP_TIMING_PORT 6002
32
33
#define AES_CHUNK_SIZE 16
34
#ifndef MD5_DIGEST_LENGTH
35
#define MD5_DIGEST_LENGTH 16
36
#endif
37
-#define MD5_HASH_LENGTH (2*MD5_DIGEST_LENGTH)
38
+#define MD5_HASH_LENGTH (2*MD5_DIGEST_LENGTH)
39
40
#define DEFAULT_USER_NAME "PipeWire"
41
#define RAOP_AUTH_USER_NAME "iTunes"
42
43
-#define MAX_PORT_RETRY 128
44
+#define MAX_PORT_RETRY 128
45
46
-#define DEFAULT_FORMAT "S16"
47
-#define DEFAULT_RATE 44100
48
-#define DEFAULT_CHANNELS 2
49
-#define DEFAULT_POSITION " FL FR "
50
+#define RAOP_FORMAT "S16LE"
51
+#define RAOP_STRIDE (2*DEFAULT_CHANNELS)
52
+#define RAOP_RATE 44100
53
+#define RAOP_LATENCY_MS 250
54
55
-#define VOLUME_MAX 0.0
56
-#define VOLUME_MIN -30.0
57
-#define VOLUME_MUTE -144.0
58
+#define VOLUME_MAX 0.0
59
+#define VOLUME_MIN -30.0
60
+#define VOLUME_MUTE -144.0
61
62
#define MODULE_USAGE "( raop.ip=<ip address of host> ) " \
63
"( raop.port=<remote port> ) " \
64
65
"( node.latency=<latency as fraction> ) " \
66
"( node.name=<name of the nodes> ) " \
67
"( node.description=<description of the nodes> ) " \
68
- "( audio.format=<format, default:"DEFAULT_FORMAT"> ) " \
69
- "( audio.rate=<sample rate, default: "SPA_STRINGIFY(DEFAULT_RATE)"> ) " \
70
+ "( audio.format=<format, default:"RAOP_FORMAT"> ) " \
71
+ "( audio.rate=<sample rate, default: "SPA_STRINGIFY(RAOP_RATE)"> ) " \
72
"( audio.channels=<number of channels, default:"SPA_STRINGIFY(DEFAULT_CHANNELS)"> ) " \
73
"( audio.position=<channel map, default:"DEFAULT_POSITION"> ) " \
74
"( stream.props=<properties> ) "
75
76
struct spa_hook core_listener;
77
78
struct pw_properties *stream_props;
79
- struct pw_stream *stream;
80
- struct spa_hook stream_listener;
81
- struct spa_audio_info_raw info;
82
- uint32_t frame_size;
83
+ struct rtp_stream *stream;
84
85
struct pw_rtsp_client *rtsp;
86
struct spa_hook rtsp_listener;
87
88
int server_fd;
89
struct spa_source *server_source;
90
91
- uint32_t block_size;
92
+ uint32_t psamples;
93
+ uint64_t rate;
94
+ uint32_t mtu;
95
+ uint32_t stride;
96
uint32_t latency;
97
98
- uint16_t seq, cseq;
99
- uint32_t rtptime;
100
uint32_t ssrc;
101
uint32_t sync;
102
uint32_t sync_period;
103
- unsigned int first:1;
104
unsigned int connected:1;
105
unsigned int ready:1;
106
unsigned int recording:1;
107
108
bool mute;
109
float volume;
110
111
- uint8_t bufferFRAMES_PER_TCP_PACKET * 4;
112
+ struct spa_ringbuffer ring;
113
+ uint8_t bufferBUFFER_SIZE;
114
+
115
+ struct spa_io_position *io_position;
116
+
117
uint32_t filled;
118
};
119
120
-static void stream_destroy(void *d)
121
-{
122
- struct impl *impl = d;
123
- spa_hook_remove(&impl->stream_listener);
124
- impl->stream = NULL;
125
-}
126
-
127
static inline void bit_writer(uint8_t **p, int *pos, uint8_t data, int len)
128
{
129
int rb = 8 - *pos - len;
130
131
return timespec_to_ntp(&now);
132
}
133
134
-static int send_udp_sync_packet(struct impl *impl,
135
- struct sockaddr *dest_addr, socklen_t addrlen)
136
+static int send_udp_sync_packet(struct impl *impl, uint32_t rtptime, unsigned int first)
137
{
138
uint32_t out3;
139
- uint32_t rtptime = impl->rtptime;
140
uint32_t latency = impl->latency;
141
uint64_t transmitted;
142
struct rtp_header header;
143
144
145
spa_zero(header);
146
header.v = 2;
147
- if (impl->first)
148
+ if (first)
149
header.x = 1;
150
header.m = 1;
151
header.pt = 84;
152
- header.sequence_number = htons(impl->cseq);
153
+ header.sequence_number = 7;
154
header.timestamp = htonl(rtptime - latency);
155
156
iov0.iov_base = &header;
157
158
iov1.iov_base = out;
159
iov1.iov_len = sizeof(out);
160
161
- msg.msg_name = dest_addr;
162
- msg.msg_namelen = addrlen;
163
+ msg.msg_name = NULL;
164
+ msg.msg_namelen = 0;
165
msg.msg_iov = iov;
166
msg.msg_iovlen = 2;
167
msg.msg_control = NULL;
168
169
pw_log_warn("error sending control packet: %d", res);
170
}
171
172
- impl->cseq = (impl->cseq + 1) & 0xffff;
173
-
174
- pw_log_debug("raop control sync: cseq:%d first:%d latency:%u now:%"PRIx64" rtptime:%u",
175
- impl->cseq, impl->first, latency, transmitted, rtptime);
176
+ pw_log_debug("raop control sync: first:%d latency:%u now:%"PRIx64" rtptime:%u",
177
+ first, latency, transmitted, rtptime);
178
179
return res;
180
}
181
182
return bp - b + 1;
183
}
184
185
-static int flush_to_udp_packet(struct impl *impl)
186
+static ssize_t send_packet(int fd, struct msghdr *msg)
187
{
188
- const size_t max = 8 + impl->block_size;
189
- uint32_t outmax, len, n_frames;
190
- struct rtp_header header;
191
- struct iovec iov2;
192
+ ssize_t n;
193
+ n = sendmsg(fd, msg, MSG_NOSIGNAL);
194
+ if (n < 0)
195
+ pw_log_debug("sendmsg() failed: %m");
196
+ return n;
197
+}
198
+
199
+static void stream_send_packet(void *data, struct iovec *iov, size_t iovlen)
200
+{
201
+ struct impl *impl = data;
202
+ const size_t max = 8 + impl->mtu;
203
+ uint32_t tcp_pkt1, outmax, len, n_frames, rtptime;
204
+ struct iovec out_vec3;
205
+ struct rtp_header *header;
206
struct msghdr msg;
207
uint8_t *dst;
208
- int res;
209
210
if (!impl->recording)
211
- return 0;
212
-
213
- if (impl->first || ++impl->sync == impl->sync_period) {
214
- impl->sync = 0;
215
- send_udp_sync_packet(impl, NULL, 0);
216
- }
217
-
218
- spa_zero(header);
219
- header.v = 2;
220
- header.pt = 96;
221
- if (impl->first)
222
- header.m = 1;
223
- header.sequence_number = htons(impl->seq);
224
- header.timestamp = htonl(impl->rtptime);
225
- header.ssrc = htonl(impl->ssrc);
226
+ return;
227
228
- iov0.iov_base = &header;
229
- iov0.iov_len = 12;
230
+ header = (struct rtp_header*)iov0.iov_base;
231
+ if (header->v != 2)
232
+ pw_log_warn("invalid rtp packet version");
233
234
- n_frames = impl->filled / impl->frame_size;
235
- dst = (uint8_t*)&out0;
236
+ rtptime = htonl(header->timestamp);
237
238
- switch (impl->codec) {
239
- case CODEC_PCM:
240
- case CODEC_ALAC:
241
- len = write_codec_pcm(dst, impl->buffer, n_frames);
242
- break;
243
- default:
244
- len = 8 + impl->block_size;
245
- memset(dst, 0, len);
246
- break;
247
+ if (header->m || ++impl->sync == impl->sync_period) {
248
+ send_udp_sync_packet(impl, rtptime, header->m);
249
+ impl->sync = 0;
250
}
251
- if (impl->encryption == CRYPTO_RSA)
252
- aes_encrypt(impl, dst, len);
253
-
254
- iov1.iov_base = out;
255
- iov1.iov_len = len;
256
257
- impl->rtptime += n_frames;
258
- impl->seq = (impl->seq + 1) & 0xffff;
259
+ n_frames = iov1.iov_len / impl->stride;
260
261
msg.msg_name = NULL;
262
msg.msg_namelen = 0;
263
- msg.msg_iov = iov;
264
- msg.msg_iovlen = 2;
265
+ msg.msg_iov = out_vec;
266
+ msg.msg_iovlen = 0;
267
msg.msg_control = NULL;
268
msg.msg_controllen = 0;
269
msg.msg_flags = 0;
270
271
- res = sendmsg(impl->server_fd, &msg, MSG_NOSIGNAL);
272
- if (res < 0) {
273
- res = -errno;
274
- pw_log_warn("error streaming packet: %d", res);
275
- }
276
-
277
- impl->first = false;
278
-
279
- return res;
280
-}
281
-
282
-static int flush_to_tcp_packet(struct impl *impl)
283
-{
284
- const size_t max = 8 + impl->block_size;
285
- uint32_t tcp_pkt1, outmax, len, n_frames;
286
- struct rtp_header header;
287
- struct iovec iov3;
288
- struct msghdr msg;
289
- uint8_t *dst;
290
- int res;
291
-
292
- if (!impl->recording)
293
- return 0;
294
-
295
- tcp_pkt0 = htonl(0x24000000);
296
-
297
- iov0.iov_base = &tcp_pkt;
298
- iov0.iov_len = 4;
299
-
300
- spa_zero(header);
301
- header.v = 2;
302
- header.pt = 96;
303
- header.sequence_number = htons(impl->seq);
304
- header.timestamp = htonl(impl->rtptime);
305
- header.ssrc = htonl(impl->ssrc);
306
-
307
- iov1.iov_base = &header;
308
- iov1.iov_len = 12;
309
-
310
- n_frames = impl->filled / impl->frame_size;
311
dst = (uint8_t*)&out0;
312
313
switch (impl->codec) {
314
case CODEC_PCM:
315
case CODEC_ALAC:
316
- len = write_codec_pcm(dst, impl->buffer, n_frames);
317
+ len = write_codec_pcm(dst, (void *)iov1.iov_base, n_frames);
318
break;
319
default:
320
- len = 8 + impl->block_size;
321
+ len = 8 + impl->mtu;
322
memset(dst, 0, len);
323
break;
324
}
325
if (impl->encryption == CRYPTO_RSA)
326
aes_encrypt(impl, dst, len);
327
328
- out0 |= htonl((uint32_t) len + 12);
329
-
330
- iov2.iov_base = out;
331
- iov2.iov_len = len;
332
-
333
- impl->rtptime += n_frames;
334
- impl->seq = (impl->seq + 1) & 0xffff;
335
-
336
- msg.msg_name = NULL;
337
- msg.msg_namelen = 0;
338
- msg.msg_iov = iov;
339
- msg.msg_iovlen = 2;
340
- msg.msg_control = NULL;
341
- msg.msg_controllen = 0;
342
- msg.msg_flags = 0;
343
-
344
- res = sendmsg(impl->server_fd, &msg, MSG_NOSIGNAL);
345
- if (res < 0) {
346
- res = -errno;
347
- pw_log_warn("error streaming packet: %d", res);
348
+ if (impl->protocol == PROTO_TCP) {
349
+ out0 |= htonl((uint32_t) len + 12);
350
+ tcp_pkt0 = htonl(0x24000000);
351
+ out_vecmsg.msg_iovlen++ = (struct iovec) { tcp_pkt, 4 };
352
}
353
354
- impl->first = false;
355
+ out_vecmsg.msg_iovlen++ = (struct iovec) { header, 12 };
356
+ out_vecmsg.msg_iovlen++ = (struct iovec) { out, len };
357
358
- return res;
359
+ pw_log_debug("raop sending %ld", out_vec0.iov_len + out_vec1.iov_len + out_vec2.iov_len);
360
+
361
+ send_packet(impl->server_fd, &msg);
362
}
363
364
-static void playback_stream_process(void *d)
365
+static inline void
366
+set_iovec(struct spa_ringbuffer *rbuf, void *buffer, uint32_t size,
367
+ uint32_t offset, struct iovec *iov, uint32_t len)
368
{
369
- struct impl *impl = d;
370
- struct pw_buffer *buf;
371
- struct spa_data *bd;
372
- uint8_t *data;
373
- uint32_t offs, size;
374
-
375
- if ((buf = pw_stream_dequeue_buffer(impl->stream)) == NULL) {
376
- pw_log_debug("out of buffers: %m");
377
- return;
378
- }
379
-
380
- bd = &buf->buffer->datas0;
381
-
382
- offs = SPA_MIN(bd->chunk->offset, bd->maxsize);
383
- size = SPA_MIN(bd->chunk->size, bd->maxsize - offs);
384
- data = SPA_PTROFF(bd->data, offs, uint8_t);
385
-
386
- while (size > 0 && impl->block_size > 0) {
387
- uint32_t avail, to_fill;
388
-
389
- avail = impl->block_size - impl->filled;
390
- to_fill = SPA_MIN(avail, size);
391
-
392
- memcpy(&impl->bufferimpl->filled, data, to_fill);
393
-
394
- impl->filled += to_fill;
395
- avail -= to_fill;
396
- size -= to_fill;
397
- data += to_fill;
398
-
399
- if (avail == 0) {
400
- switch (impl->protocol) {
401
- case PROTO_UDP:
402
- flush_to_udp_packet(impl);
403
- break;
404
- case PROTO_TCP:
405
- flush_to_tcp_packet(impl);
406
- break;
407
- }
408
- impl->filled = 0;
409
- }
410
- }
411
-
412
- pw_stream_queue_buffer(impl->stream, buf);
413
+ iov0.iov_len = SPA_MIN(len, size - offset);
414
+ iov0.iov_base = SPA_PTROFF(buffer, offset, void);
415
+ iov1.iov_len = len - iov0.iov_len;
416
+ iov1.iov_base = buffer;
417
}
418
419
static int create_udp_socket(struct impl *impl, uint16_t *port)
420
421
return 0;
422
}
423
424
-static int rtsp_do_flush(struct impl *impl)
425
-{
426
- int res;
427
-
428
- if (!impl->recording)
429
- return 0;
430
-
431
- pw_properties_set(impl->headers, "Range", "npt=0-");
432
- pw_properties_setf(impl->headers, "RTP-Info",
433
- "seq=%u;rtptime=%u", impl->seq, impl->rtptime);
434
-
435
- impl->recording = false;
436
-
437
- res = rtsp_send(impl, "FLUSH", NULL, NULL, rtsp_log_reply_status);
438
-
439
- pw_properties_set(impl->headers, "Range", NULL);
440
- pw_properties_set(impl->headers, "RTP-Info", NULL);
441
-
442
- return res;
443
-}
444
-
445
static int rtsp_send_volume(struct impl *impl)
446
{
447
if (!impl->recording)
448
449
NULL, NULL, 0, rtsp_log_reply_status, impl);
450
}
451
452
+static uint32_t msec_to_samples(struct impl *impl, uint32_t msec)
453
+{
454
+ return msec * impl->rate / 1000;
455
+}
456
+
457
static int rtsp_record_reply(void *data, int status, const struct spa_dict *headers, const struct pw_array *content)
458
{
459
struct impl *impl = data;
460
461
462
spa_zero(latency);
463
latency.direction = PW_DIRECTION_INPUT;
464
- latency.min_rate = latency.max_rate = impl->latency + RAOP_LATENCY_MIN;
465
+ latency.min_rate = latency.max_rate = impl->latency + msec_to_samples(impl, RAOP_LATENCY_MS);
466
467
n_params = 0;
468
spa_pod_builder_init(&b, buffer, sizeof(buffer));
469
paramsn_params++ = spa_latency_build(&b, SPA_PARAM_Latency, &latency);
470
471
- pw_stream_update_params(impl->stream, params, n_params);
472
+ rtp_stream_update_params(impl->stream, params, n_params);
473
+
474
+ rtp_stream_set_first(impl->stream);
475
476
- impl->first = true;
477
impl->sync = 0;
478
- impl->sync_period = impl->info.rate / (impl->block_size / impl->frame_size);
479
+ impl->sync_period = impl->rate / (impl->mtu / impl->stride);
480
impl->recording = true;
481
482
rtsp_send_volume(impl);
483
484
static int rtsp_do_record(struct impl *impl)
485
{
486
int res;
487
+ uint16_t seq;
488
+ uint32_t rtptime;
489
490
if (!impl->ready || impl->recording)
491
return 0;
492
493
+ seq = rtp_stream_get_seq(impl->stream);
494
+ rtptime = rtp_stream_get_time(impl->stream, &impl->rate);
495
+
496
pw_properties_set(impl->headers, "Range", "npt=0-");
497
pw_properties_setf(impl->headers, "RTP-Info",
498
- "seq=%u;rtptime=%u", impl->seq, impl->rtptime);
499
+ "seq=%u;rtptime=%u", seq, rtptime);
500
501
res = rtsp_send(impl, "RECORD", NULL, NULL, rtsp_record_reply);
502
503
504
goto error;
505
506
impl->ready = true;
507
- if (pw_stream_get_state(impl->stream, NULL) == PW_STREAM_STATE_STREAMING)
508
+ if (rtp_stream_get_state(impl->stream, NULL) == PW_STREAM_STATE_STREAMING)
509
rtsp_do_record(impl);
510
}
511
return;
512
513
size_t len;
514
uint64_t ntp;
515
uint16_t control_port, timing_port;
516
- int res;
517
518
pw_log_info("setup status: %d", status);
519
520
521
return 0;
522
}
523
524
- if ((res = pw_getrandom(&impl->seq, sizeof(impl->seq), 0)) < 0 ||
525
- (res = pw_getrandom(&impl->rtptime, sizeof(impl->rtptime), 0)) < 0) {
526
- pw_log_error("error generating random seq and rtptime: %s", spa_strerror(res));
527
- return 0;
528
- }
529
-
530
pw_log_info("server port:%u", impl->server_port);
531
532
switch (impl->protocol) {
533
534
SPA_IO_IN, false, on_control_source_io, impl);
535
536
impl->ready = true;
537
- if (pw_stream_get_state(impl->stream, NULL) == PW_STREAM_STATE_STREAMING)
538
+ if (rtp_stream_get_state(impl->stream, NULL) == PW_STREAM_STATE_STREAMING)
539
rtsp_do_record(impl);
540
break;
541
default:
542
543
break;
544
545
case PROTO_UDP:
546
- impl->control_port = DEFAULT_UDP_CONTROL_PORT;
547
- impl->timing_port = DEFAULT_UDP_TIMING_PORT;
548
+ impl->control_port = RAOP_UDP_CONTROL_PORT;
549
+ impl->timing_port = RAOP_UDP_TIMING_PORT;
550
551
impl->control_fd = create_udp_socket(impl, &impl->control_port);
552
impl->timing_fd = create_udp_socket(impl, &impl->timing_port);
553
554
{
555
const char *host;
556
uint8_t rsakey512;
557
+ uint32_t rtp_latency;
558
char key512*2;
559
char iv16*2;
560
- int res, frames, rsa_len, ip_version;
561
+ int res, rsa_len, ip_version;
562
spa_autofree char *sdp = NULL;
563
char local_ip256;
564
host = pw_properties_get(impl->props, "raop.ip");
565
-
566
- if (impl->protocol == PROTO_TCP)
567
- frames = FRAMES_PER_TCP_PACKET;
568
- else
569
- frames = FRAMES_PER_UDP_PACKET;
570
-
571
- impl->block_size = frames * impl->frame_size;
572
+ rtp_latency = msec_to_samples(impl, RAOP_LATENCY_MS);
573
574
pw_rtsp_client_get_local_ip(impl->rtsp, &ip_version,
575
local_ip, sizeof(local_ip));
576
577
"a=rtpmap:96 AppleLossless\r\n"
578
"a=fmtp:96 %d 0 16 40 10 14 2 255 0 0 %u\r\n",
579
impl->session_id, ip_version, local_ip,
580
- ip_version, host, frames, impl->info.rate);
581
+ ip_version, host, impl->psamples, (uint32_t)impl->rate);
582
if (!sdp)
583
return -errno;
584
break;
585
586
"a=fmtp:96 %d 0 16 40 10 14 2 255 0 0 %u\r\n"
587
"a=min-latency:%d",
588
impl->session_id, ip_version, local_ip,
589
- ip_version, host, frames, impl->info.rate,
590
- RAOP_LATENCY_MIN);
591
+ ip_version, host, impl->psamples, (uint32_t)impl->rate,
592
+ rtp_latency);
593
if (!sdp)
594
return -errno;
595
break;
596
597
"a=rsaaeskey:%s\r\n"
598
"a=aesiv:%s\r\n",
599
impl->session_id, ip_version, local_ip,
600
- ip_version, host, frames, impl->info.rate,
601
+ ip_version, host, impl->psamples, (uint32_t)impl->rate,
602
key, iv);
603
if (!sdp)
604
return -errno;
605
606
.message = rtsp_message,
607
};
608
609
-static void stream_state_changed(void *d, enum pw_stream_state old,
610
- enum pw_stream_state state, const char *error)
611
+static void stream_destroy(void *d)
612
{
613
struct impl *impl = d;
614
- switch (state) {
615
- case PW_STREAM_STATE_ERROR:
616
- case PW_STREAM_STATE_UNCONNECTED:
617
+ impl->stream = NULL;
618
+}
619
+
620
+static void stream_state_changed(void *data, bool started, const char *error)
621
+{
622
+ struct impl *impl = data;
623
+
624
+ if (error) {
625
+ pw_log_error("stream error: %s", error);
626
pw_impl_module_schedule_destroy(impl->module);
627
- break;
628
- case PW_STREAM_STATE_PAUSED:
629
- rtsp_do_flush(impl);
630
- break;
631
- case PW_STREAM_STATE_STREAMING:
632
- rtsp_do_record(impl);
633
- break;
634
- default:
635
- break;
636
+ return;
637
}
638
+ if (started)
639
+ rtsp_do_record(impl);
640
}
641
642
static int rtsp_do_connect(struct impl *impl)
643
644
645
static int rtsp_do_teardown(struct impl *impl)
646
{
647
+ impl->recording = false;
648
+
649
if (!impl->ready)
650
return 0;
651
652
653
}
654
param = spa_pod_builder_pop(&b, &f0);
655
656
- pw_stream_set_param(impl->stream, id, param);
657
+ rtp_stream_set_param(impl->stream, id, param);
658
}
659
660
static void stream_param_changed(void *data, uint32_t id, const struct spa_pod *param)
661
662
}
663
}
664
665
-static const struct pw_stream_events playback_stream_events = {
666
- PW_VERSION_STREAM_EVENTS,
667
+static const struct rtp_stream_events stream_events = {
668
+ RTP_VERSION_STREAM_EVENTS,
669
.destroy = stream_destroy,
670
.state_changed = stream_state_changed,
671
.param_changed = stream_param_changed,
672
- .process = playback_stream_process
673
+ .send_packet = stream_send_packet
674
};
675
676
-static int create_stream(struct impl *impl)
677
-{
678
- int res;
679
- uint32_t n_params;
680
- const struct spa_pod *params1;
681
- uint8_t buffer1024;
682
- struct spa_pod_builder b;
683
-
684
- impl->stream = pw_stream_new(impl->core, "RAOP sink", impl->stream_props);
685
- impl->stream_props = NULL;
686
-
687
- if (impl->stream == NULL)
688
- return -errno;
689
-
690
- pw_stream_add_listener(impl->stream,
691
- &impl->stream_listener,
692
- &playback_stream_events, impl);
693
-
694
- n_params = 0;
695
- spa_pod_builder_init(&b, buffer, sizeof(buffer));
696
- paramsn_params++ = spa_format_audio_raw_build(&b,
697
- SPA_PARAM_EnumFormat, &impl->info);
698
-
699
- if ((res = pw_stream_connect(impl->stream,
700
- PW_DIRECTION_INPUT,
701
- PW_ID_ANY,
702
- PW_STREAM_FLAG_MAP_BUFFERS |
703
- PW_STREAM_FLAG_RT_PROCESS,
704
- params, n_params)) < 0)
705
- return res;
706
-
707
- impl->headers = pw_properties_new(NULL, NULL);
708
-
709
- impl->rtsp = pw_rtsp_client_new(impl->loop, NULL, 0);
710
- if (impl->rtsp == NULL)
711
- return -errno;
712
-
713
- pw_rtsp_client_add_listener(impl->rtsp, &impl->rtsp_listener,
714
- &rtsp_events, impl);
715
-
716
- return 0;
717
-}
718
-
719
static void core_error(void *data, uint32_t id, int seq, int res, const char *message)
720
{
721
struct impl *impl = data;
722
723
static void impl_destroy(struct impl *impl)
724
{
725
if (impl->stream)
726
- pw_stream_destroy(impl->stream);
727
+ rtp_stream_destroy(impl->stream);
728
if (impl->core && impl->do_disconnect)
729
pw_core_disconnect(impl->core);
730
731
732
.destroy = module_destroy,
733
};
734
735
-static inline uint32_t format_from_name(const char *name, size_t len)
736
-{
737
- int i;
738
- for (i = 0; spa_type_audio_formati.name; i++) {
739
- if (strncmp(name, spa_debug_type_short_name(spa_type_audio_formati.name), len) == 0)
740
- return spa_type_audio_formati.type;
741
- }
742
- return SPA_AUDIO_FORMAT_UNKNOWN;
743
-}
744
-
745
-static uint32_t channel_from_name(const char *name)
746
-{
747
- int i;
748
- for (i = 0; spa_type_audio_channeli.name; i++) {
749
- if (spa_streq(name, spa_debug_type_short_name(spa_type_audio_channeli.name)))
750
- return spa_type_audio_channeli.type;
751
- }
752
- return SPA_AUDIO_CHANNEL_UNKNOWN;
753
-}
754
-
755
-static void parse_position(struct spa_audio_info_raw *info, const char *val, size_t len)
756
-{
757
- struct spa_json it2;
758
- char v256;
759
-
760
- spa_json_init(&it0, val, len);
761
- if (spa_json_enter_array(&it0, &it1) <= 0)
762
- spa_json_init(&it1, val, len);
763
-
764
- info->channels = 0;
765
- while (spa_json_get_string(&it1, v, sizeof(v)) > 0 &&
766
- info->channels < SPA_AUDIO_MAX_CHANNELS) {
767
- info->positioninfo->channels++ = channel_from_name(v);
768
- }
769
-}
770
-
771
-static void parse_audio_info(const struct pw_properties *props, struct spa_audio_info_raw *info)
772
-{
773
- const char *str;
774
-
775
- spa_zero(*info);
776
- if ((str = pw_properties_get(props, PW_KEY_AUDIO_FORMAT)) == NULL)
777
- str = DEFAULT_FORMAT;
778
- info->format = format_from_name(str, strlen(str));
779
-
780
- info->rate = pw_properties_get_uint32(props, PW_KEY_AUDIO_RATE, info->rate);
781
- if (info->rate == 0)
782
- info->rate = DEFAULT_RATE;
783
-
784
- info->channels = pw_properties_get_uint32(props, PW_KEY_AUDIO_CHANNELS, info->channels);
785
- info->channels = SPA_MIN(info->channels, SPA_AUDIO_MAX_CHANNELS);
786
- if ((str = pw_properties_get(props, SPA_KEY_AUDIO_POSITION)) != NULL)
787
- parse_position(info, str, strlen(str));
788
- if (info->channels == 0)
789
- parse_position(info, DEFAULT_POSITION, strlen(DEFAULT_POSITION));
790
-}
791
-
792
-static int calc_frame_size(struct spa_audio_info_raw *info)
793
-{
794
- int res = info->channels;
795
- switch (info->format) {
796
- case SPA_AUDIO_FORMAT_U8:
797
- case SPA_AUDIO_FORMAT_S8:
798
- case SPA_AUDIO_FORMAT_ALAW:
799
- case SPA_AUDIO_FORMAT_ULAW:
800
- return res;
801
- case SPA_AUDIO_FORMAT_S16:
802
- case SPA_AUDIO_FORMAT_S16_OE:
803
- case SPA_AUDIO_FORMAT_U16:
804
- return res * 2;
805
- case SPA_AUDIO_FORMAT_S24:
806
- case SPA_AUDIO_FORMAT_S24_OE:
807
- case SPA_AUDIO_FORMAT_U24:
808
- return res * 3;
809
- case SPA_AUDIO_FORMAT_S24_32:
810
- case SPA_AUDIO_FORMAT_S24_32_OE:
811
- case SPA_AUDIO_FORMAT_S32:
812
- case SPA_AUDIO_FORMAT_S32_OE:
813
- case SPA_AUDIO_FORMAT_U32:
814
- case SPA_AUDIO_FORMAT_U32_OE:
815
- case SPA_AUDIO_FORMAT_F32:
816
- case SPA_AUDIO_FORMAT_F32_OE:
817
- return res * 4;
818
- case SPA_AUDIO_FORMAT_F64:
819
- case SPA_AUDIO_FORMAT_F64_OE:
820
- return res * 8;
821
- default:
822
- return 0;
823
- }
824
-}
825
-
826
static void copy_props(struct impl *impl, struct pw_properties *props, const char *key)
827
{
828
const char *str;
829
830
struct pw_properties *props = NULL;
831
struct impl *impl;
832
const char *str, *name, *hostname, *ip, *port;
833
- int res;
834
+ int res = 0;
835
836
PW_LOG_TOPIC_INIT(mod_topic);
837
838
839
goto error;
840
}
841
842
- if (pw_properties_get(props, PW_KEY_NODE_VIRTUAL) == NULL)
843
- pw_properties_set(props, PW_KEY_NODE_VIRTUAL, "true");
844
-
845
- if (pw_properties_get(props, PW_KEY_MEDIA_CLASS) == NULL)
846
- pw_properties_set(props, PW_KEY_MEDIA_CLASS, "Audio/Sink");
847
-
848
- if (pw_properties_get(props, PW_KEY_DEVICE_ICON_NAME) == NULL)
849
- pw_properties_set(props, PW_KEY_DEVICE_ICON_NAME, "audio-speakers");
850
-
851
- if ((name = pw_properties_get(props, "raop.name")) == NULL)
852
- name = "RAOP";
853
-
854
- if ((str = strstr(name, "@"))) {
855
- str++;
856
- if (strlen(str) > 0)
857
- name = str;
858
- }
859
- if ((hostname = pw_properties_get(props, "raop.hostname")) == NULL)
860
- hostname = name;
861
-
862
- if (pw_properties_get(props, PW_KEY_NODE_NAME) == NULL)
863
- pw_properties_setf(props, PW_KEY_NODE_NAME, "raop_sink.%s.%s.%s",
864
- hostname, ip, port);
865
- if (pw_properties_get(props, PW_KEY_NODE_DESCRIPTION) == NULL)
866
- pw_properties_setf(props, PW_KEY_NODE_DESCRIPTION,
867
- "%s", name);
868
- if (pw_properties_get(props, PW_KEY_NODE_LATENCY) == NULL)
869
- pw_properties_set(props, PW_KEY_NODE_LATENCY, "352/44100");
870
-
871
- if ((str = pw_properties_get(props, "stream.props")) != NULL)
872
- pw_properties_update_string(impl->stream_props, str, strlen(str));
873
-
874
- copy_props(impl, props, PW_KEY_AUDIO_FORMAT);
875
- copy_props(impl, props, PW_KEY_AUDIO_RATE);
876
- copy_props(impl, props, PW_KEY_AUDIO_CHANNELS);
877
- copy_props(impl, props, SPA_KEY_AUDIO_POSITION);
878
- copy_props(impl, props, PW_KEY_DEVICE_ICON_NAME);
879
- copy_props(impl, props, PW_KEY_NODE_NAME);
880
- copy_props(impl, props, PW_KEY_NODE_DESCRIPTION);
881
- copy_props(impl, props, PW_KEY_NODE_GROUP);
882
- copy_props(impl, props, PW_KEY_NODE_LATENCY);
883
- copy_props(impl, props, PW_KEY_NODE_VIRTUAL);
884
- copy_props(impl, props, PW_KEY_MEDIA_CLASS);
885
-
886
- parse_audio_info(impl->stream_props, &impl->info);
887
-
888
- impl->frame_size = calc_frame_size(&impl->info);
889
- if (impl->frame_size == 0) {
890
- pw_log_error("unsupported audio format:%d channels:%d",
891
- impl->info.format, impl->info.channels);
892
- res = -EINVAL;
893
- goto error;
894
- }
895
-
896
if ((str = pw_properties_get(props, "raop.transport")) == NULL)
897
str = "udp";
898
- if (spa_streq(str, "udp"))
899
+ if (spa_streq(str, "udp")) {
900
impl->protocol = PROTO_UDP;
901
- else if (spa_streq(str, "tcp"))
902
+ impl->psamples = FRAMES_PER_UDP_PACKET;
903
+ } else if (spa_streq(str, "tcp")) {
904
impl->protocol = PROTO_TCP;
905
- else {
906
+ impl->psamples = FRAMES_PER_TCP_PACKET;
907
+ } else {
908
pw_log_error( "can't handle transport %s", str);
909
res = -EINVAL;
910
goto error;
911
912
str = pw_properties_get(props, "raop.password");
913
impl->password = str ? strdup(str) : NULL;
914
915
- if ((str = pw_properties_get(props, "raop.latency.ms")) == NULL)
916
- str = DEFAULT_LATENCY_MS;
917
- impl->latency = SPA_MAX(atoi(str) * impl->info.rate / 1000u, RAOP_LATENCY_MIN);
918
+ if ((name = pw_properties_get(props, "raop.name")) == NULL)
919
+ name = "RAOP";
920
+
921
+ if ((str = strchr(name, '@')) != NULL) {
922
+ str++;
923
+ if (strlen(str) > 0)
924
+ name = str;
925
+ }
926
+ if ((hostname = pw_properties_get(props, "raop.hostname")) == NULL)
927
+ hostname = name;
928
+
929
+ impl->rate = RAOP_RATE;
930
+ impl->latency = msec_to_samples(impl, RAOP_LATENCY_MS);
931
+ impl->stride = RAOP_STRIDE;
932
+ impl->mtu = impl->stride * impl->psamples;
933
+ impl->sync_period = impl->rate / impl->psamples;
934
+
935
+ if (pw_properties_get(props, PW_KEY_AUDIO_FORMAT) == NULL)
936
+ pw_properties_setf(props, PW_KEY_AUDIO_FORMAT, "%s", RAOP_FORMAT);
937
+ if (pw_properties_get(props, PW_KEY_AUDIO_RATE) == NULL)
938
+ pw_properties_setf(props, PW_KEY_AUDIO_RATE, "%ld", impl->rate);
939
+ if (pw_properties_get(props, PW_KEY_DEVICE_ICON_NAME) == NULL)
940
+ pw_properties_set(props, PW_KEY_DEVICE_ICON_NAME, "audio-speakers");
941
+ if (pw_properties_get(props, PW_KEY_NODE_NAME) == NULL)
942
+ pw_properties_setf(props, PW_KEY_NODE_NAME, "raop_sink.%s.%s.%s",
943
+ hostname, ip, port);
944
+ if (pw_properties_get(props, PW_KEY_NODE_DESCRIPTION) == NULL)
945
+ pw_properties_setf(props, PW_KEY_NODE_DESCRIPTION, "%s", name);
946
+ if (pw_properties_get(props, PW_KEY_NODE_LATENCY) == NULL)
947
+ pw_properties_setf(props, PW_KEY_NODE_LATENCY, "%d/%ld",
948
+ impl->psamples, impl->rate);
949
+ if (pw_properties_get(props, PW_KEY_NODE_VIRTUAL) == NULL)
950
+ pw_properties_set(props, PW_KEY_NODE_VIRTUAL, "true");
951
+ if (pw_properties_get(props, PW_KEY_MEDIA_CLASS) == NULL)
952
+ pw_properties_set(props, PW_KEY_MEDIA_CLASS, "Audio/Sink");
953
+ if (pw_properties_get(props, PW_KEY_MEDIA_FORMAT) == NULL)
954
+ pw_properties_setf(props, PW_KEY_MEDIA_FORMAT, "%d", SPA_AUDIO_FORMAT_S16_LE);
955
+ if (pw_properties_get(props, "net.mtu") == NULL)
956
+ pw_properties_setf(props, "net.mtu", "%d", impl->mtu);
957
+ if (pw_properties_get(props, "rtp.sender-ts-offset") == NULL)
958
+ pw_properties_setf(props, "rtp.sender-ts-offset", "%d", 0);
959
+ if (pw_properties_get(props, "sess.ts-direct") == NULL)
960
+ pw_properties_set(props, "sess.ts-direct", 0);
961
+ if (pw_properties_get(props, "sess.media") == NULL)
962
+ pw_properties_set(props, "sess.media", "raop");
963
+ if (pw_properties_get(props, "sess.latency.msec") == NULL)
964
+ pw_properties_setf(props, "sess.latency.msec", "%d", RAOP_LATENCY_MS);
965
+
966
+ if ((str = pw_properties_get(props, "stream.props")) != NULL)
967
+ pw_properties_update_string(impl->stream_props, str, strlen(str));
968
+
969
+ copy_props(impl, props, PW_KEY_AUDIO_FORMAT);
970
+ copy_props(impl, props, PW_KEY_AUDIO_RATE);
971
+ copy_props(impl, props, PW_KEY_AUDIO_CHANNELS);
972
+ copy_props(impl, props, SPA_KEY_AUDIO_POSITION);
973
+ copy_props(impl, props, PW_KEY_DEVICE_ICON_NAME);
974
+ copy_props(impl, props, PW_KEY_NODE_NAME);
975
+ copy_props(impl, props, PW_KEY_NODE_DESCRIPTION);
976
+ copy_props(impl, props, PW_KEY_NODE_GROUP);
977
+ copy_props(impl, props, PW_KEY_NODE_LATENCY);
978
+ copy_props(impl, props, PW_KEY_NODE_VIRTUAL);
979
+ copy_props(impl, props, PW_KEY_MEDIA_CLASS);
980
+ copy_props(impl, props, PW_KEY_MEDIA_FORMAT);
981
+ copy_props(impl, props, "net.mtu");
982
+ copy_props(impl, props, "rtp.sender-ts-offset");
983
+ copy_props(impl, props, "sess.media");
984
+ copy_props(impl, props, "sess.name");
985
+ copy_props(impl, props, "sess.min-ptime");
986
+ copy_props(impl, props, "sess.max-ptime");
987
+ copy_props(impl, props, "sess.latency.msec");
988
+ copy_props(impl, props, "sess.ts-refclk");
989
+ copy_props(impl, props, "sess.ts-direct");
990
991
impl->core = pw_context_get_object(impl->context, PW_TYPE_INTERFACE_Core);
992
if (impl->core == NULL) {
993
994
&impl->core_listener,
995
&core_events, impl);
996
997
- if ((res = create_stream(impl)) < 0)
998
+ impl->stream = rtp_stream_new(impl->core,
999
+ PW_DIRECTION_INPUT, pw_properties_copy(impl->stream_props),
1000
+ &stream_events, impl);
1001
+ if (impl->stream == NULL) {
1002
+ res = -errno;
1003
+ pw_log_error("can't create raop stream: %m");
1004
+ goto error;
1005
+ }
1006
+
1007
+ impl->headers = pw_properties_new(NULL, NULL);
1008
+
1009
+ impl->rtsp = pw_rtsp_client_new(impl->loop, NULL, 0);
1010
+ if (impl->rtsp == NULL)
1011
goto error;
1012
1013
+ pw_rtsp_client_add_listener(impl->rtsp, &impl->rtsp_listener,
1014
+ &rtsp_events, impl);
1015
+
1016
pw_impl_module_add_listener(module, &impl->module_listener, &module_events, impl);
1017
1018
pw_impl_module_update_properties(module, &SPA_DICT_INIT_ARRAY(module_props));
1019
pipewire-0.3.81.tar.gz/src/modules/module-rt.c -> pipewire-0.3.82.tar.gz/src/modules/module-rt.c
Changed
19
1
2
#include <sys/thr.h>
3
#endif
4
#if defined(__GNU__)
5
-#include <mach.h>
6
+#include <hurd.h>
7
#endif
8
#include <fcntl.h>
9
#include <unistd.h>
10
11
thr_self(&pid);
12
return (pid_t)pid;
13
#elif defined(__GNU__)
14
- mach_port_t thread = mach_thread_self();
15
+ mach_port_t thread = hurd_thread_self();
16
return (pid_t)thread;
17
#else
18
#error "No gettid impl"
19
pipewire-0.3.81.tar.gz/src/modules/module-rtp/audio.c -> pipewire-0.3.82.tar.gz/src/modules/module-rtp/audio.c
Changed
26
1
2
iov0.iov_len = sizeof(header);
3
4
while (avail >= tosend) {
5
+ if (impl->marker_on_first && impl->first)
6
+ header.m = 1;
7
+ else
8
+ header.m = 0;
9
header.sequence_number = htons(impl->seq);
10
header.timestamp = htonl(impl->ts_offset + timestamp);
11
12
13
(timestamp * stride) & BUFFER_MASK,
14
&iov1, tosend * stride);
15
16
- pw_log_trace("sending %d timestamp:%d", tosend, timestamp);
17
+ pw_log_trace("sending %d avail:%d ts_offset:%d timestamp:%d", tosend, avail, impl->ts_offset, timestamp);
18
19
rtp_stream_emit_send_packet(impl, iov, 3);
20
21
impl->seq++;
22
+ impl->first = false;
23
timestamp += tosend;
24
avail -= tosend;
25
}
26
pipewire-0.3.81.tar.gz/src/modules/module-rtp/stream.c -> pipewire-0.3.82.tar.gz/src/modules/module-rtp/stream.c
Changed
115
1
2
struct rtp_stream_events, m, v, ##__VA_ARGS__)
3
#define rtp_stream_emit_destroy(s) rtp_stream_emit(s, destroy, 0)
4
#define rtp_stream_emit_state_changed(s,n,e) rtp_stream_emit(s, state_changed,0,n,e)
5
+#define rtp_stream_emit_param_changed(s,i,p) rtp_stream_emit(s, param_changed,0,i,p)
6
#define rtp_stream_emit_send_packet(s,i,l) rtp_stream_emit(s, send_packet,0,i,l)
7
#define rtp_stream_emit_send_feedback(s,seq) rtp_stream_emit(s, send_feedback,0,seq)
8
9
10
unsigned have_ssrc:1;
11
unsigned ignore_ssrc:1;
12
unsigned have_seq:1;
13
+ unsigned marker_on_first:1;
14
uint32_t ts_offset;
15
uint32_t psamples;
16
uint32_t mtu;
17
18
{ SPA_MEDIA_SUBTYPE_raw, SPA_AUDIO_FORMAT_ALAW, 1, "PCMA", "audio" },
19
{ SPA_MEDIA_SUBTYPE_raw, SPA_AUDIO_FORMAT_ULAW, 1, "PCMU", "audio" },
20
{ SPA_MEDIA_SUBTYPE_raw, SPA_AUDIO_FORMAT_S16_BE, 2, "L16", "audio" },
21
+ { SPA_MEDIA_SUBTYPE_raw, SPA_AUDIO_FORMAT_S16_LE, 2, "L16", "audio" },
22
{ SPA_MEDIA_SUBTYPE_raw, SPA_AUDIO_FORMAT_S24_BE, 3, "L24", "audio" },
23
{ SPA_MEDIA_SUBTYPE_control, 0, 1, "rtp-midi", "audio" },
24
{ SPA_MEDIA_SUBTYPE_opus, 0, 4, "opus", "audio" },
25
26
if (impl->started)
27
return 0;
28
29
+ impl->first = true;
30
+
31
rtp_stream_emit_state_changed(impl, true, NULL);
32
33
impl->started = true;
34
35
}
36
}
37
38
+static void on_stream_param_changed (void *d, uint32_t id, const struct spa_pod *param)
39
+{
40
+ struct impl *impl = d;
41
+ rtp_stream_emit_param_changed(impl, id, param);
42
+};
43
+
44
static const struct pw_stream_events stream_events = {
45
PW_VERSION_STREAM_EVENTS,
46
.destroy = stream_destroy,
47
.state_changed = on_stream_state_changed,
48
+ .param_changed = on_stream_param_changed,
49
.io_changed = stream_io_changed,
50
};
51
52
53
impl->info.media_subtype = SPA_MEDIA_SUBTYPE_raw;
54
impl->payload = 127;
55
}
56
+ else if (spa_streq(str, "raop")) {
57
+ impl->info.media_type = SPA_MEDIA_TYPE_audio;
58
+ impl->info.media_subtype = SPA_MEDIA_SUBTYPE_raw;
59
+ impl->payload = 0x60;
60
+ impl->marker_on_first = 1;
61
+ }
62
else if (spa_streq(str, "midi")) {
63
impl->info.media_type = SPA_MEDIA_TYPE_application;
64
impl->info.media_subtype = SPA_MEDIA_SUBTYPE_control;
65
66
if (pw_properties_get(props, PW_KEY_NODE_NETWORK) == NULL)
67
pw_properties_set(props, PW_KEY_NODE_NETWORK, "true");
68
69
+ impl->marker_on_first = pw_properties_get_bool(props, "sess.marker-on-first", false);
70
impl->ignore_ssrc = pw_properties_get_bool(props, "sess.ignore-ssrc", false);
71
impl->direct_timestamp = pw_properties_get_bool(props, "sess.ts-direct", false);
72
73
74
return pos->clock.position * impl->rate *
75
pos->clock.rate.num / pos->clock.rate.denom;
76
}
77
+
78
+uint16_t rtp_stream_get_seq(struct rtp_stream *s)
79
+{
80
+ struct impl *impl = (struct impl*)s;
81
+
82
+ return impl->seq;
83
+}
84
+
85
+void rtp_stream_set_first(struct rtp_stream *s)
86
+{
87
+ struct impl *impl = (struct impl*)s;
88
+
89
+ impl->first = true;
90
+}
91
+
92
+enum pw_stream_state rtp_stream_get_state(struct rtp_stream *s, const char **error)
93
+{
94
+ struct impl *impl = (struct impl*)s;
95
+
96
+ return pw_stream_get_state(impl->stream, error);
97
+}
98
+
99
+int rtp_stream_set_param(struct rtp_stream *s, uint32_t id, const struct spa_pod *param)
100
+{
101
+ struct impl *impl = (struct impl*)s;
102
+
103
+ return pw_stream_set_param(impl->stream, id, param);
104
+}
105
+
106
+int rtp_stream_update_params(struct rtp_stream *s,
107
+ const struct spa_pod **params,
108
+ uint32_t n_params)
109
+{
110
+ struct impl *impl = (struct impl*)s;
111
+
112
+ return pw_stream_update_params(impl->stream, params, n_params);
113
+}
114
\ No newline at end of file
115
pipewire-0.3.81.tar.gz/src/modules/module-rtp/stream.h -> pipewire-0.3.82.tar.gz/src/modules/module-rtp/stream.h
Changed
32
1
2
3
void (*state_changed) (void *data, bool started, const char *error);
4
5
+ void (*param_changed) (void *data, uint32_t id, const struct spa_pod *param);
6
+
7
void (*send_packet) (void *data, struct iovec *iov, size_t iovlen);
8
9
- void (*send_feedback) (void *data, uint32_t senum);
10
+ void (*send_feedback) (void *data, uint32_t seqnum);
11
};
12
13
struct rtp_stream *rtp_stream_new(struct pw_core *core,
14
15
16
uint64_t rtp_stream_get_time(struct rtp_stream *s, uint64_t *rate);
17
18
+uint16_t rtp_stream_get_seq(struct rtp_stream *s);
19
+
20
+void rtp_stream_set_first(struct rtp_stream *s);
21
+
22
+enum pw_stream_state rtp_stream_get_state(struct rtp_stream *s, const char **error);
23
+
24
+int rtp_stream_set_param(struct rtp_stream *s, uint32_t id, const struct spa_pod *param);
25
+
26
+int rtp_stream_update_params(struct rtp_stream *stream,
27
+ const struct spa_pod **params,
28
+ uint32_t n_params);
29
30
#ifdef __cplusplus
31
}
32
pipewire-0.3.81.tar.gz/src/pipewire/context.c -> pipewire-0.3.82.tar.gz/src/pipewire/context.c
Changed
80
1
2
context, n, n->name);
3
4
if (n->info.state >= PW_NODE_STATE_IDLE)
5
- n->reconfigure = true;
6
+ n->need_resume = !n->pause_on_idle;
7
pw_impl_node_set_state(n, PW_NODE_STATE_SUSPENDED);
8
}
9
10
11
uint32_t target_quantum, target_rate, current_rate, current_quantum;
12
uint64_t quantum_stamp = 0, rate_stamp = 0;
13
bool force_rate, force_quantum, restore_rate = false, restore_quantum = false;
14
- bool do_reconfigure = false, was_target_pending;
15
+ bool do_reconfigure = false, need_resume, was_target_pending;
16
const uint32_t *node_rates;
17
uint32_t node_n_rates, node_def_rate;
18
uint32_t node_max_quantum, node_min_quantum, node_def_quantum, node_rate_quantum;
19
20
if (force_rate)
21
lock_rate = false;
22
23
- if (n->reconfigure)
24
+ need_resume = n->need_resume;
25
+ if (need_resume) {
26
running = true;
27
+ n->need_resume = false;
28
+ }
29
30
current_rate = n->target_rate.denom;
31
if (!restore_rate &&
32
- (lock_rate || n->reconfigure || !running ||
33
- (!force_rate && (n->info.state > PW_NODE_STATE_IDLE))))
34
+ (lock_rate || need_resume || !running ||
35
+ (!force_rate && (n->info.state > PW_NODE_STATE_IDLE)))) {
36
+ pw_log_debug("%p: keep rate:1/%u restore:%u lock:%u resume:%u "
37
+ "running:%u force:%u state:%s", context,
38
+ current_rate, restore_rate, lock_rate, need_resume,
39
+ running, force_rate,
40
+ pw_node_state_as_string(n->info.state));
41
+
42
/* when we don't need to restore or rate and
43
* when someone wants us to lock the rate of this driver or
44
* when we are in the process of reconfiguring the driver or
45
46
* when the driver is busy and we don't need to force a rate,
47
* keep the current rate */
48
target_rate = current_rate;
49
+ }
50
else {
51
/* Here we are allowed to change the rate of the driver.
52
* Start with the default rate. If the desired rate is
53
54
55
current_quantum = n->target_quantum;
56
if (!restore_quantum &&
57
- (lock_quantum || n->reconfigure || !running ||
58
- (!force_quantum && (n->info.state > PW_NODE_STATE_IDLE))))
59
+ (lock_quantum || need_resume || !running ||
60
+ (!force_quantum && (n->info.state > PW_NODE_STATE_IDLE)))) {
61
+ pw_log_debug("%p: keep quantum:%u restore:%u lock:%u resume:%u "
62
+ "running:%u force:%u state:%s", context,
63
+ current_quantum, restore_quantum, lock_quantum, need_resume,
64
+ running, force_quantum,
65
+ pw_node_state_as_string(n->info.state));
66
target_quantum = current_quantum;
67
+ }
68
else {
69
target_quantum = node_def_quantum;
70
if (latency.denom != 0)
71
72
target_quantum = SPA_CLAMP(target_quantum, node_min_quantum, node_max_quantum);
73
target_quantum = SPA_MIN(target_quantum, lim_quantum);
74
75
- if (settings->clock_power_of_two_quantum)
76
+ if (settings->clock_power_of_two_quantum && !force_quantum)
77
target_quantum = flp2(target_quantum);
78
}
79
80
pipewire-0.3.81.tar.gz/src/pipewire/filter.c -> pipewire-0.3.82.tar.gz/src/pipewire/filter.c
Changed
15
1
2
if ((str = getenv("PIPEWIRE_QUANTUM")) != NULL) {
3
struct spa_fraction q;
4
if (sscanf(str, "%u/%u", &q.num, &q.denom) == 2 && q.denom != 0) {
5
- pw_properties_setf(filter->properties, PW_KEY_NODE_RATE,
6
+ pw_properties_setf(filter->properties, PW_KEY_NODE_FORCE_RATE,
7
"1/%u", q.denom);
8
- pw_properties_setf(filter->properties, PW_KEY_NODE_LATENCY,
9
- "%u/%u", q.num, q.denom);
10
+ pw_properties_setf(filter->properties, PW_KEY_NODE_FORCE_QUANTUM,
11
+ "%u", q.num);
12
}
13
}
14
if ((str = getenv("PIPEWIRE_LATENCY")) != NULL)
15
pipewire-0.3.81.tar.gz/src/pipewire/impl-client.c -> pipewire-0.3.82.tar.gz/src/pipewire/impl-client.c
Changed
74
1
2
return false;
3
}
4
5
-static int update_properties(struct pw_impl_client *client, const struct spa_dict *dict, bool filter)
6
+static bool check_client_property_update(struct pw_impl_client *client,
7
+ const char *key, const char *old, const char *new)
8
{
9
static const char * const ignored = {
10
+ PW_KEY_PROTOCOL,
11
PW_KEY_OBJECT_ID,
12
+ PW_KEY_OBJECT_SERIAL,
13
+ PW_KEY_ACCESS,
14
NULL
15
};
16
17
+ /* Refuse specific restricted keys */
18
+ if (has_key(ignored, key))
19
+ goto deny;
20
+
21
+ /* Refuse all security keys */
22
+ if (spa_strstartswith(key, "pipewire.sec."))
23
+ goto deny;
24
+
25
+ /* Restrict other pipewire.* keys */
26
+ if (spa_strstartswith(key, "pipewire.")) {
27
+ /* Refuse changing existing values */
28
+ if (old != NULL)
29
+ goto deny;
30
+ }
31
+
32
+ return true;
33
+
34
+deny:
35
+ if (!spa_streq(old, new))
36
+ pw_log_warn("%p: refuse property update '%s' from '%s' to '%s'",
37
+ client, key, old ? old : "<unset>", new ? new : "<unset>");
38
+ return false;
39
+}
40
+
41
+static int update_properties(struct pw_impl_client *client, const struct spa_dict *dict, bool filter)
42
+{
43
struct pw_resource *resource;
44
int changed = 0;
45
uint32_t i;
46
- const char *old;
47
48
for (i = 0; i < dict->n_items; i++) {
49
if (filter) {
50
- if (spa_strstartswith(dict->itemsi.key, "pipewire.") &&
51
- (old = pw_properties_get(client->properties, dict->itemsi.key)) != NULL &&
52
- (dict->itemsi.value == NULL || !spa_streq(old, dict->itemsi.value))) {
53
- pw_log_warn("%p: refuse property update '%s' from '%s' to '%s'",
54
- client, dict->itemsi.key, old,
55
- dict->itemsi.value);
56
- continue;
57
+ const char *old = pw_properties_get(client->properties, dict->itemsi.key);
58
+ const char *new = dict->itemsi.value;
59
60
- }
61
- if (has_key(ignored, dict->itemsi.key))
62
+ if (!check_client_property_update(client, dict->itemsi.key, old, new))
63
continue;
64
}
65
changed += pw_properties_set(client->properties, dict->itemsi.key, dict->itemsi.value);
66
67
PW_KEY_SEC_UID,
68
PW_KEY_SEC_GID,
69
PW_KEY_SEC_LABEL,
70
+ PW_KEY_SEC_SOCKET,
71
NULL
72
};
73
74
pipewire-0.3.81.tar.gz/src/pipewire/impl-node.c -> pipewire-0.3.82.tar.gz/src/pipewire/impl-node.c
Changed
16
1
2
spa_list_for_each(resource, &node->global->resource_list, link)
3
pw_resource_error(resource, res, error);
4
}
5
- if (node->reconfigure) {
6
- if (state == PW_NODE_STATE_SUSPENDED &&
7
- node->pause_on_idle) {
8
- node->reconfigure = false;
9
- }
10
- if (state == PW_NODE_STATE_RUNNING)
11
- node->reconfigure = false;
12
- }
13
if (old == PW_NODE_STATE_RUNNING &&
14
state == PW_NODE_STATE_IDLE &&
15
node->suspend_on_idle) {
16
pipewire-0.3.81.tar.gz/src/pipewire/keys.h -> pipewire-0.3.82.tar.gz/src/pipewire/keys.h
Changed
10
1
2
#define PW_KEY_SEC_GID "pipewire.sec.gid" /**< client gid, set by protocol*/
3
#define PW_KEY_SEC_LABEL "pipewire.sec.label" /**< client security label, set by protocol*/
4
5
+#define PW_KEY_SEC_SOCKET "pipewire.sec.socket" /**< client socket name, set by protocol */
6
+
7
#define PW_KEY_LIBRARY_NAME_SYSTEM "library.name.system" /**< name of the system library to use */
8
#define PW_KEY_LIBRARY_NAME_LOOP "library.name.loop" /**< name of the loop library to use */
9
#define PW_KEY_LIBRARY_NAME_DBUS "library.name.dbus" /**< name of the dbus library to use */
10
pipewire-0.3.81.tar.gz/src/pipewire/log.c -> pipewire-0.3.82.tar.gz/src/pipewire/log.c
Changed
15
1
2
}
3
}
4
5
-SPA_EXPORT
6
-void
7
-_pw_log_topic_new(struct spa_log_topic *topic)
8
-{
9
- spa_log_topic_init(global_log, topic);
10
-}
11
-
12
void
13
pw_log_init(void)
14
{
15
pipewire-0.3.81.tar.gz/src/pipewire/log.h -> pipewire-0.3.82.tar.gz/src/pipewire/log.h
Changed
19
1
2
int line, const char *func,
3
const char *fmt, va_list args) SPA_PRINTF_FUNC(5, 0);
4
5
-/** Initialize the log topic. The returned topic is owned by the pipewire
6
- * context and the topic must not be modified or freed.
7
- * Do not use this function directly, use one of PW_LOG_TOPIC_* instead.
8
- *
9
- * \see PW_LOG_TOPIC_STATIC
10
- * \see PW_LOG_TOPIC_EXTERN
11
- * \see PW_LOG_TOPIC
12
- */
13
-void
14
-_pw_log_topic_new(struct spa_log_topic *topic);
15
-
16
/**
17
* Declare a static log topic named \a var. The usual usage is:
18
* \code
19
pipewire-0.3.81.tar.gz/src/pipewire/map.h -> pipewire-0.3.82.tar.gz/src/pipewire/map.h
Changed
21
1
2
* \param id the index to look at
3
* \return the item at \a id or NULL when no such item exists
4
*/
5
-static inline void *pw_map_lookup(struct pw_map *map, uint32_t id)
6
+static inline void *pw_map_lookup(const struct pw_map *map, uint32_t id)
7
{
8
if (SPA_LIKELY(pw_map_check_id(map, id))) {
9
union pw_map_item *item = pw_map_get_item(map, id);
10
11
* \param data data to pass to \a func
12
* \return the result of the last call to \a func or 0 when all callbacks returned 0.
13
*/
14
-static inline int pw_map_for_each(struct pw_map *map,
15
- int (*func) (void *item_data, void *data), void *data)
16
+static inline int pw_map_for_each(const struct pw_map *map,
17
+ int (*func) (void *item_data, void *data), void *data)
18
{
19
union pw_map_item *item;
20
int res = 0;
21
pipewire-0.3.81.tar.gz/src/pipewire/private.h -> pipewire-0.3.82.tar.gz/src/pipewire/private.h
Changed
10
1
2
unsigned int added:1; /**< the node was add to graph */
3
unsigned int pause_on_idle:1; /**< Pause processing when IDLE */
4
unsigned int suspend_on_idle:1;
5
- unsigned int reconfigure:1;
6
+ unsigned int need_resume:1;
7
unsigned int forced_rate:1;
8
unsigned int forced_quantum:1;
9
unsigned int trigger:1; /**< has the TRIGGER property and needs an extra
10
pipewire-0.3.81.tar.gz/src/pipewire/stream.c -> pipewire-0.3.82.tar.gz/src/pipewire/stream.c
Changed
15
1
2
if ((str = getenv("PIPEWIRE_QUANTUM")) != NULL) {
3
struct spa_fraction q;
4
if (sscanf(str, "%u/%u", &q.num, &q.denom) == 2 && q.denom != 0) {
5
- pw_properties_setf(stream->properties, PW_KEY_NODE_RATE,
6
+ pw_properties_setf(stream->properties, PW_KEY_NODE_FORCE_RATE,
7
"1/%u", q.denom);
8
- pw_properties_setf(stream->properties, PW_KEY_NODE_LATENCY,
9
- "%u/%u", q.num, q.denom);
10
+ pw_properties_setf(stream->properties, PW_KEY_NODE_FORCE_QUANTUM,
11
+ "%u", q.num);
12
}
13
}
14
if ((str = getenv("PIPEWIRE_LATENCY")) != NULL)
15
pipewire-0.3.81.tar.gz/src/tools/pw-cat.c -> pipewire-0.3.82.tar.gz/src/tools/pw-cat.c
Changed
11
1
2
uint32_t i, n_items = 0;
3
4
for (i = 0; i < data.props->dict.n_items; i++) {
5
- if (spa_strstartswith(data.props->dict.itemsi.key, "media."))
6
+ if (n_items < SPA_N_ELEMENTS(items) &&
7
+ spa_strstartswith(data.props->dict.itemsi.key, "media."))
8
itemsn_items++ = data.props->dict.itemsi;
9
}
10
if (n_items > 0) {
11
Refresh
No build results available
Refresh
No rpmlint results available
Login required, please
login
or
signup
in order to comment