We truncated the diff of some files because they were too big.
If you want to see the full diff for every file, click here.
Changes of Revision 15
pipewire-aptx.changes
Changed
x
1
2
-------------------------------------------------------------------
3
+Sun Sep 18 13:29:55 UTC 2022 - Bjørn Lie <zaitor@opensuse.org>
4
+
5
+- Update to version 0.3.58
6
+
7
+-------------------------------------------------------------------
8
Wed Sep 7 13:36:51 UTC 2022 - Bjørn Lie <zaitor@opensuse.org>
9
10
- Update to version 0.3.57
11
pipewire-aptx.spec
Changed
10
1
2
%define soversion 0_2
3
4
Name: pipewire-aptx
5
-Version: 0.3.57
6
+Version: 0.3.58
7
Release: 0
8
Summary: PipeWire Bluetooth aptX codec plugin
9
License: MIT
10
pipewire-0.3.57.tar.gz/NEWS -> pipewire-0.3.58.tar.gz/NEWS
Changed
112
1
2
+# PipeWire 0.3.58 (2022-09-15)
3
+
4
+This is a bugfix release that is API and ABI compatible with previous
5
+0.3.x releases.
6
+
7
+## Highlights
8
+ - Fix a regression that could cause audio crackling.
9
+ - Fix a regression in RTKit because rlimit was not set correctly.
10
+ - JAVA sound applications will now alsa work with the pulseaudio-alsa plugin.
11
+ - pw-top will now show the negotiated formats of devices and streams.
12
+ - Fix some potential crashes when starting streams.
13
+ - The ALSA plugin has had improved timing reporting and poll descriptor
14
+ handling that should improve compatibility.
15
+ - Many more improvements and bugfixes.
16
+
17
+
18
+## PipeWire
19
+ - Avoid scheduling nodes before they are added to the graph. This could
20
+ avoid some crashes when scheduling nodes that were not completely
21
+ started yet. (#2677)
22
+
23
+## Tools
24
+ - pw-top now also shows the negotiated formats of streams and devices.
25
+ (#2566)
26
+ - pw-top prints microseconds as "us" now to avoid unicode problems.
27
+
28
+## Modules
29
+ - Fix compilation with newer lv2.
30
+ - Fix setting realtime priority with RTKit, it was not setting rlimit
31
+ correctly and RTKit would refuse to change the priority.
32
+ - Fix some playback problems with RAOP sink. (#2673)
33
+ - Filter chain will now warn when a non-existing control property is
34
+ used in the config file. (#2685)
35
+ - Filter chain can now handle control port names with ":" in the name.
36
+ (#2685)
37
+ - The echo-cancel module and interface now has activate/deactivate
38
+ functions to make it possible for plugins to reset their state.
39
+
40
+## SPA
41
+ - Make sure audioconvert uses the given channelmap and channels for the
42
+ volumes, even when not negotiated yet. This makes it possible to change
43
+ the volume before the node has been negotiated.
44
+ - Refactor the peaks resampler. Fix an error in the SSE code.
45
+ - Fix DSD min/max rates, avoid exposing impossible rates.
46
+ - Set monitor port buffer size correctly. This could cause some crackling
47
+ and hickups. (#2677)
48
+ - Make ALSA sequencer port names unique.
49
+
50
+## Pulse-server
51
+ - Rework the capture buffer attributes to better match pulseaudio. This
52
+ fixes a regression where opening pavucontrol could cause crackling.
53
+ (#2671)
54
+ - Implement TRIGGER and PREBUF methods.
55
+ - Handle clients that send more than the requested amount of data.
56
+ PipeWire will now also keep this as extra buffered data like PulseAudio.
57
+ This fixes JAVA sound applications when they are running on top of the
58
+ PulseAudio ALSA plugin. (#2626,#2674)
59
+ - Update the requested amount of bytes more like PulseAudio. Fixes
60
+ stuttering after resume with the GStreamer pulseaudio sink. (#2680)
61
+
62
+## ALSA Plugin
63
+ - More debug info was added. The time reporting was improved.
64
+ - The poll descriptor handling was improved, avoiding some spurious
65
+ wakeups. (#1697)
66
+
67
+
68
+Older versions:
69
+
70
+
71
# PipeWire 0.3.57 (2022-09-02)
72
73
This is a bugfix release that is API and ABI compatible with previous
74
0.3.x releases.
75
76
## Highlights
77
+ - Support masking of conf.d/ files. (#2629)
78
+ - Use org.freedesktop.portal.Realtime when available. This does the
79
+ correct PID/TID mappings to make realtime also work from flatpaks.
80
+ - Fix rate adjustement logic in pulse-tunnel. This would cause
81
+ increasing delays and hickups when using tunnels. (#2548)
82
+ - Add OPUS as a new vendor codec. Add OPUS-A2DP spec. PipeWire can now
83
+ send and reveive OPUS data over bluetooth.
84
+ - An AAC decoder was added so that PipeWire can now also function as
85
+ an A2DP AAC receiver.
86
+ - Fix some issues where the wrong samplerate was used. (#2614)
87
+ - Fix rate match for sources. This fixes an error where follower sources
88
+ would generate many resync warnings.
89
+ - Many more bugfixes and improvements.
90
+
91
92
## PipeWire
93
- Support masking of conf.d/ files. (#2629)
94
95
host_machine.
96
- Check return values of pw_getrandom().
97
98
-
99
## Tools
100
- Updates to pw-cli manpages. (#2552)
101
- Remove the pw-cli dump command. It is mostly implemented as part of
102
103
- JACK clients from the same application will be added to the same group
104
so that they share the quantum and rate.
105
106
-
107
-Older versions:
108
-
109
# PipeWire 0.3.56 (2022-07-19)
110
111
This is a quick bugfix release that is API and ABI compatible with previous
112
pipewire-0.3.57.tar.gz/doc/index.dox -> pipewire-0.3.58.tar.gz/doc/index.dox
Changed
8
1
2
- PipeWire: The Linux audio/video bus (LWN)(https://lwn.net/Articles/847412)
3
- PipeWire Wikipedia(https://en.wikipedia.org/wiki/PipeWire)
4
- Bluetooth, PipeWire and Whatsapp calls(https://gjhenrique.com/pipewire.html)
5
+- Intoduction to PipeWire(https://bootlin.com/blog/an-introduction-to-pipewire/)
6
7
*/
8
pipewire-0.3.57.tar.gz/man/pw-cat.1.rst.in -> pipewire-0.3.58.tar.gz/man/pw-cat.1.rst.in
Changed
34
1
2
server. It understands all audio file formats supported by
3
``libsndfile`` for PCM capture and playback.
4
5
-It understands standard MIDI files for playback and recording,
6
+It understands standard MIDI files for playback and recording. This tool
7
+will not render MIDI files, it will simply make the MIDI events available
8
+to the graph. You need a MIDI renderer such as qsynth, timidity or a hardware
9
+MIDI rendered to hear the MIDI.
10
11
-DSD playback is supported with the DSF file format.
12
+DSD playback is supported with the DSF file format. This tool will only work
13
+with native DSD capable hardware and will produce an error when no such
14
+hardware was found.
15
16
When the *FILE* is - input and output will be from STDIN and
17
STDOUT respectively.
18
19
-m | --midi
20
MIDI mode. *FILE* is a MIDI file. If the tool is called under the name
21
**pw-midiplay** or **pw-midirecord** this is the default.
22
+ Note that this program will *not* render the MIDI events into audible samples,
23
+ it will simply provide the MIDI events in the graph. You need a separate
24
+ MIDI renderer such as qsynth, timidity or a hardware renderer to hear the MIDI.
25
26
-d | --dsd
27
DSD mode. *FILE* is a DSF file. If the tool is called under the name
28
**pw-dsdplay** this is the default.
29
+ Note that this program will *not* render the DSD audio. You need a DSD capable
30
+ device to play DSD content or this program will exit with an error.
31
32
--media-type=VALUE
33
Set the media type property (default Audio/Midi depending on mode).
34
pipewire-0.3.57.tar.gz/man/pw-top.1.rst.in -> pipewire-0.3.58.tar.gz/man/pw-top.1.rst.in
Changed
40
1
2
The current rate (for drivers) and the suggested rate for follower
3
nodes.
4
5
- This is the rate at which the graph processes data and needs to be combined with
6
+ This is the rate at which the *graph* processes data and needs to be combined with
7
the QUANT value to derive the duration of a processing cycle in the graph.
8
9
Some nodes can have a 0 RATE, which means that they don't have any rate
10
11
The RATE on (audio) driver nodes usually also translates directly to the
12
samplerate used by the device. Although some devices might not be able to
13
operate at the given samplerate, in which case resampling will need to be
14
- done.
15
+ done. The negotiated samplerate with the device and stream can be found in
16
+ the FORMAT column.
17
18
WAIT
19
The waiting time of a node is the elapsed time between when the node
20
21
Xruns for followers are incremented when the node started processing but
22
did not complete before the end of the graph cycle deadline.
23
24
+FORMAT
25
+ The format used by the driver node or the stream. This is the hardware format
26
+ negotiated with the device or stream.
27
+
28
+ If the stream of driver has a different rate than the graph, resampling will
29
+ be done.
30
+
31
+ For raw audio formats, the layout is <sampleformat> <channels> <samplerate>.
32
+
33
+ For DSD formats, the layout is <dsd-rate> <channels>.
34
+
35
+ For Video formats, the layout is <pixelformat> <width>x<height>.
36
+
37
NAME
38
Name assigned to the device/node, as found in *pw-dump* node.name
39
40
pipewire-0.3.57.tar.gz/meson.build -> pipewire-0.3.58.tar.gz/meson.build
Changed
8
1
2
project('pipewire', 'c' ,
3
- version : '0.3.57',
4
+ version : '0.3.58',
5
license : 'MIT', 'LGPL-2.1-or-later', 'GPL-2.0-only' ,
6
meson_version : '>= 0.59.0',
7
default_options : 'warning_level=3',
8
pipewire-0.3.57.tar.gz/pipewire-alsa/alsa-plugins/pcm_pipewire.c -> pipewire-0.3.58.tar.gz/pipewire-alsa/alsa-plugins/pcm_pipewire.c
Changed
201
1
2
3
#include <pipewire/pipewire.h>
4
5
+#define ATOMIC_INC(s) __atomic_add_fetch(&(s), 1, __ATOMIC_SEQ_CST)
6
+#define ATOMIC_LOAD(s) __atomic_load_n(&(s), __ATOMIC_SEQ_CST)
7
+
8
+#define SEQ_WRITE(s) ATOMIC_INC(s)
9
+#define SEQ_WRITE_SUCCESS(s1,s2) ((s1) + 1 == (s2) && ((s2) & 1) == 0)
10
+
11
+#define SEQ_READ(s) ATOMIC_LOAD(s)
12
+#define SEQ_READ_SUCCESS(s1,s2) ((s1) == (s2) && ((s2) & 1) == 0)
13
+
14
PW_LOG_TOPIC_STATIC(alsa_log_topic, "alsa.pcm");
15
#define PW_LOG_TOPIC_DEFAULT alsa_log_topic
16
17
18
typedef struct {
19
snd_pcm_ioplug_t io;
20
21
+ snd_output_t *output;
22
+ FILE *log_file;
23
+
24
char *node_name;
25
char *target;
26
char *role;
27
28
unsigned int draining:1;
29
unsigned int xrun_detected:1;
30
unsigned int hw_params_changed:1;
31
+ unsigned int active:1;
32
33
snd_pcm_uframes_t hw_ptr;
34
snd_pcm_uframes_t boundary;
35
36
struct pw_stream *stream;
37
struct spa_hook stream_listener;
38
39
- struct pw_time time;
40
+ int64_t delay;
41
+ uint64_t now;
42
+ uintptr_t seq;
43
44
struct spa_audio_info_raw format;
45
} snd_pcm_pipewire_t;
46
47
static int snd_pcm_pipewire_stop(snd_pcm_ioplug_t *io);
48
49
-static int block_check(snd_pcm_ioplug_t *io)
50
+static int check_active(snd_pcm_ioplug_t *io)
51
{
52
snd_pcm_pipewire_t *pw = io->private_data;
53
snd_pcm_sframes_t avail;
54
- uint64_t val;
55
+ bool active;
56
57
avail = snd_pcm_ioplug_avail(io, pw->hw_ptr, io->appl_ptr);
58
- if (avail >= 0 && avail < (snd_pcm_sframes_t)pw->min_avail) {
59
- spa_system_eventfd_read(pw->system, io->poll_fd, &val);
60
- return 1;
61
+
62
+ if (io->state == SND_PCM_STATE_DRAINING) {
63
+ active = pw->drained;
64
}
65
- return 0;
66
+ else if (avail >= 0 && avail < (snd_pcm_sframes_t)pw->min_avail) {
67
+ active = false;
68
+ }
69
+ else if (avail >= (snd_pcm_sframes_t)pw->min_avail) {
70
+ active = true;
71
+ } else {
72
+ active = false;
73
+ }
74
+ if (pw->active != active) {
75
+ pw_log_trace("%p: avail:%lu min-avail:%lu state:%s hw:%lu appl:%lu active:%d->%d state:%s",
76
+ pw, avail, pw->min_avail, snd_pcm_state_name(io->state),
77
+ pw->hw_ptr, io->appl_ptr, pw->active, active,
78
+ snd_pcm_state_name(io->state));
79
+ }
80
+ return active;
81
}
82
83
-static int pcm_poll_block_check(snd_pcm_ioplug_t *io)
84
+
85
+static int update_active(snd_pcm_ioplug_t *io)
86
{
87
snd_pcm_pipewire_t *pw = io->private_data;
88
+ bool active;
89
90
- if (io->state == SND_PCM_STATE_DRAINING) {
91
+ active = check_active(io);
92
+
93
+ if (pw->active != active) {
94
uint64_t val;
95
- spa_system_eventfd_read(pw->system, io->poll_fd, &val);
96
- return 0;
97
- } else if (io->state == SND_PCM_STATE_RUNNING ||
98
- (io->state == SND_PCM_STATE_PREPARED && io->stream == SND_PCM_STREAM_CAPTURE)) {
99
- return block_check(io);
100
- }
101
- return 0;
102
-}
103
104
-static inline int pcm_poll_unblock_check(snd_pcm_ioplug_t *io)
105
-{
106
- snd_pcm_pipewire_t *pw = io->private_data;
107
- snd_pcm_uframes_t avail;
108
+ pw->active = active;
109
110
- avail = snd_pcm_ioplug_avail(io, pw->hw_ptr, io->appl_ptr);
111
- if (avail >= pw->min_avail || io->state == SND_PCM_STATE_DRAINING) {
112
- spa_system_eventfd_write(pw->system, pw->fd, 1);
113
- return 1;
114
+ if (active)
115
+ spa_system_eventfd_write(pw->system, io->poll_fd, 1);
116
+ else
117
+ spa_system_eventfd_read(pw->system, io->poll_fd, &val);
118
}
119
- return 0;
120
+ return active;
121
}
122
123
static void snd_pcm_pipewire_free(snd_pcm_pipewire_t *pw)
124
125
if (pw == NULL)
126
return;
127
128
- pw_log_debug("%p:", pw);
129
+ pw_log_debug("%p: free", pw);
130
if (pw->main_loop)
131
pw_thread_loop_stop(pw->main_loop);
132
if (pw->stream)
133
134
pw_thread_loop_destroy(pw->main_loop);
135
free(pw->node_name);
136
free(pw->target);
137
+ snd_output_close(pw->output);
138
+ fclose(pw->log_file);
139
free(pw);
140
}
141
142
static int snd_pcm_pipewire_close(snd_pcm_ioplug_t *io)
143
{
144
snd_pcm_pipewire_t *pw = io->private_data;
145
- pw_log_debug("%p:", pw);
146
+ pw_log_debug("%p: close", pw);
147
snd_pcm_pipewire_free(pw);
148
return 0;
149
}
150
151
static int snd_pcm_pipewire_poll_descriptors(snd_pcm_ioplug_t *io, struct pollfd *pfds, unsigned int space)
152
{
153
snd_pcm_pipewire_t *pw = io->private_data;
154
- pcm_poll_unblock_check(io); /* unblock socket for polling if needed */
155
+ update_active(io);
156
pfds->fd = pw->fd;
157
pfds->events = POLLIN | POLLERR | POLLNVAL;
158
return 1;
159
160
return pw->error;
161
162
*revents = pfds0.revents & ~(POLLIN | POLLOUT);
163
- if (pfds0.revents & POLLIN && !pcm_poll_block_check(io))
164
+ if (pfds0.revents & POLLIN && check_active(io))
165
*revents |= (io->stream == SND_PCM_STREAM_PLAYBACK) ? POLLOUT : POLLIN;
166
167
return 0;
168
169
static int snd_pcm_pipewire_delay(snd_pcm_ioplug_t *io, snd_pcm_sframes_t *delayp)
170
{
171
snd_pcm_pipewire_t *pw = io->private_data;
172
- int64_t elapsed = 0, filled, avail;
173
+ uintptr_t seq1, seq2;
174
+ int64_t elapsed = 0, delay, now, avail;
175
+ struct timespec ts;
176
+ int64_t diff;
177
+
178
+ do {
179
+ seq1 = SEQ_READ(pw->seq);
180
+
181
+ delay = pw->delay;
182
+ now = pw->now;
183
+ if (io->stream == SND_PCM_STREAM_PLAYBACK)
184
+ avail = snd_pcm_ioplug_hw_avail(io, pw->hw_ptr, io->appl_ptr);
185
+ else
186
+ avail = snd_pcm_ioplug_avail(io, pw->hw_ptr, io->appl_ptr);
187
+
188
+ seq2 = SEQ_READ(pw->seq);
189
+ } while (!SEQ_READ_SUCCESS(seq1, seq2));
190
191
- if (pw->time.rate.num != 0) {
192
- struct timespec ts;
193
- int64_t diff;
194
+ if (now != 0 && (io->state == SND_PCM_STATE_RUNNING ||
195
+ io->state == SND_PCM_STATE_DRAINING)) {
196
clock_gettime(CLOCK_MONOTONIC, &ts);
197
- diff = SPA_TIMESPEC_TO_NSEC(&ts) - pw->time.now;
198
- elapsed = (pw->time.rate.denom * diff) / (pw->time.rate.num * SPA_NSEC_PER_SEC);
199
- }
200
- if (io->stream == SND_PCM_STREAM_PLAYBACK)
201
pipewire-0.3.57.tar.gz/spa/include/spa/interfaces/audio/aec.h -> pipewire-0.3.58.tar.gz/spa/include/spa/interfaces/audio/aec.h
Changed
39
1
2
3
#define SPA_TYPE_INTERFACE_AUDIO_AEC SPA_TYPE_INFO_INTERFACE_BASE "Audio:AEC"
4
5
-#define SPA_VERSION_AUDIO_AEC 0
6
+#define SPA_VERSION_AUDIO_AEC 1
7
struct spa_audio_aec {
8
struct spa_interface iface;
9
const char *name;
10
11
};
12
13
struct spa_audio_aec_methods {
14
-#define SPA_VERSION_AUDIO_AEC_METHODS 0
15
+#define SPA_VERSION_AUDIO_AEC_METHODS 1
16
uint32_t version;
17
18
int (*add_listener) (void *object,
19
20
int (*init) (void *object, const struct spa_dict *args, const struct spa_audio_info_raw *info);
21
int (*run) (void *object, const float *rec, const float *play, float *out, uint32_t n_samples);
22
int (*set_props) (void *object, const struct spa_dict *args);
23
+ /* since 0.3.58, version 1:1 */
24
+ int (*activate) (void *object);
25
+ /* since 0.3.58, version 1:1 */
26
+ int (*deactivate) (void *object);
27
};
28
29
#define spa_audio_aec_method(o,method,version,...) \
30
31
#define spa_audio_aec_init(o,...) spa_audio_aec_method(o, init, 0, __VA_ARGS__)
32
#define spa_audio_aec_run(o,...) spa_audio_aec_method(o, run, 0, __VA_ARGS__)
33
#define spa_audio_aec_set_props(o,...) spa_audio_aec_method(o, set_props, 0, __VA_ARGS__)
34
+#define spa_audio_aec_activate(o) spa_audio_aec_method(o, activate, 1)
35
+#define spa_audio_aec_deactivate(o) spa_audio_aec_method(o, deactivate, 1)
36
37
#ifdef __cplusplus
38
} /* extern "C" */
39
pipewire-0.3.57.tar.gz/spa/include/spa/support/log.h -> pipewire-0.3.58.tar.gz/spa/include/spa/support/log.h
Changed
26
1
2
#define spa_log_trace_fp(l,...)
3
#endif
4
5
+#define spa_log_hexdump(l,lev,indent,data,len) \
6
+({ \
7
+ char str512; \
8
+ uint8_t *buf = (uint8_t *)data; \
9
+ size_t i; \
10
+ int pos = 0; \
11
+ \
12
+ for (i = 0; i < len; i++) { \
13
+ if (i % 16 == 0) \
14
+ pos = 0; \
15
+ pos += sprintf(str + pos, "%02x ", bufi); \
16
+ if (i % 16 == 15 || i == len - 1) { \
17
+ spa_log_log(l,lev,__FILE__,__LINE__,__func__, \
18
+ "%*s" "%s",indent,"", str); \
19
+ } \
20
+ } \
21
+})
22
+
23
/** \fn spa_log_error */
24
25
/** keys can be given when initializing the logger handle */
26
pipewire-0.3.57.tar.gz/spa/include/spa/utils/keys.h -> pipewire-0.3.58.tar.gz/spa/include/spa/utils/keys.h
Changed
10
1
2
#define SPA_KEY_API_ALSA_USE_UCM "api.alsa.use-ucm" /**< if UCM should be used */
3
#define SPA_KEY_API_ALSA_IGNORE_DB "api.alsa.ignore-dB" /**< if decibel info should be ignored */
4
#define SPA_KEY_API_ALSA_OPEN_UCM "api.alsa.open.ucm" /**< if UCM should be opened card */
5
+#define SPA_KEY_API_ALSA_DISABLE_LONGNAME \
6
+ "api.alsa.disable-longname" /**< if card long name should not be passed to MIDI port */
7
8
/** info from alsa card_info */
9
#define SPA_KEY_API_ALSA_CARD_ID "api.alsa.card.id" /**< id from card_info */
10
pipewire-0.3.57.tar.gz/spa/plugins/alsa/acp/acp.c -> pipewire-0.3.58.tar.gz/spa/plugins/alsa/acp/acp.c
Changed
10
1
2
}
3
4
impl->ucm.default_sample_spec.format = PA_SAMPLE_S16NE;
5
- impl->ucm.default_sample_spec.rate = 44100;
6
+ impl->ucm.default_sample_spec.rate = 48000;
7
impl->ucm.default_sample_spec.channels = 2;
8
pa_channel_map_init_extend(&impl->ucm.default_channel_map,
9
impl->ucm.default_sample_spec.channels, PA_CHANNEL_MAP_ALSA);
10
pipewire-0.3.57.tar.gz/spa/plugins/alsa/alsa-pcm-sink.c -> pipewire-0.3.58.tar.gz/spa/plugins/alsa/alsa-pcm-sink.c
Changed
26
1
2
if (full)
3
this->info.change_mask = this->info_all;
4
if (this->info.change_mask) {
5
- struct spa_dict_item items4;
6
+ struct spa_dict_item items7;
7
uint32_t i, n_items = 0;
8
- char latency64;
9
+ char latency64, period64, nperiods64, headroom64;
10
11
itemsn_items++ = SPA_DICT_ITEM_INIT(SPA_KEY_DEVICE_API, "alsa");
12
itemsn_items++ = SPA_DICT_ITEM_INIT(SPA_KEY_MEDIA_CLASS, "Audio/Sink");
13
14
if (this->have_format) {
15
snprintf(latency, sizeof(latency), "%lu/%d", this->buffer_frames / 2, this->rate);
16
itemsn_items++ = SPA_DICT_ITEM_INIT(SPA_KEY_NODE_MAX_LATENCY, latency);
17
+ snprintf(period, sizeof(period), "%lu", this->period_frames);
18
+ itemsn_items++ = SPA_DICT_ITEM_INIT("api.alsa.period-size", period);
19
+ snprintf(nperiods, sizeof(nperiods), "%lu", this->buffer_frames / this->period_frames);
20
+ itemsn_items++ = SPA_DICT_ITEM_INIT("api.alsa.period-num", nperiods);
21
+ snprintf(headroom, sizeof(headroom), "%u", this->headroom);
22
+ itemsn_items++ = SPA_DICT_ITEM_INIT("api.alsa.headroom", headroom);
23
}
24
this->info.props = &SPA_DICT_INIT(items, n_items);
25
26
pipewire-0.3.57.tar.gz/spa/plugins/alsa/alsa-pcm-source.c -> pipewire-0.3.58.tar.gz/spa/plugins/alsa/alsa-pcm-source.c
Changed
26
1
2
if (full)
3
this->info.change_mask = this->info_all;
4
if (this->info.change_mask) {
5
- struct spa_dict_item items4;
6
+ struct spa_dict_item items7;
7
uint32_t i, n_items = 0;
8
- char latency64;
9
+ char latency64, period64, nperiods64, headroom64;
10
11
itemsn_items++ = SPA_DICT_ITEM_INIT(SPA_KEY_DEVICE_API, "alsa");
12
itemsn_items++ = SPA_DICT_ITEM_INIT(SPA_KEY_MEDIA_CLASS, "Audio/Source");
13
14
if (this->have_format) {
15
snprintf(latency, sizeof(latency), "%lu/%d", this->buffer_frames / 2, this->rate);
16
itemsn_items++ = SPA_DICT_ITEM_INIT(SPA_KEY_NODE_MAX_LATENCY, latency);
17
+ snprintf(period, sizeof(period), "%lu", this->period_frames);
18
+ itemsn_items++ = SPA_DICT_ITEM_INIT("api.alsa.period-size", period);
19
+ snprintf(nperiods, sizeof(nperiods), "%lu", this->buffer_frames / this->period_frames);
20
+ itemsn_items++ = SPA_DICT_ITEM_INIT("api.alsa.period-num", nperiods);
21
+ snprintf(headroom, sizeof(headroom), "%u", this->headroom);
22
+ itemsn_items++ = SPA_DICT_ITEM_INIT("api.alsa.headroom", headroom);
23
}
24
this->info.props = &SPA_DICT_INIT(items, n_items);
25
26
pipewire-0.3.57.tar.gz/spa/plugins/alsa/alsa-pcm.c -> pipewire-0.3.58.tar.gz/spa/plugins/alsa/alsa-pcm.c
Changed
56
1
2
return false;
3
}
4
5
-static int add_rate(struct state *state, uint32_t scale, bool all, uint32_t index, uint32_t *next,
6
+static int add_rate(struct state *state, uint32_t scale, uint32_t interleave, bool all, uint32_t index, uint32_t *next,
7
uint32_t min_allowed_rate, snd_pcm_hw_params_t *params, struct spa_pod_builder *b)
8
{
9
struct spa_pod_frame f1;
10
11
CHECK(snd_pcm_hw_params_get_rate_min(params, &min, &dir), "get_rate_min");
12
CHECK(snd_pcm_hw_params_get_rate_max(params, &max, &dir), "get_rate_max");
13
14
- spa_log_debug(state->log, "min:%u max:%u min-allowed:%u scale:%u all:%d",
15
- min, max, min_allowed_rate, scale, all);
16
+ spa_log_debug(state->log, "min:%u max:%u min-allowed:%u scale:%u interleave:%u all:%d",
17
+ min, max, min_allowed_rate, scale, interleave, all);
18
19
- min_allowed_rate /= scale;
20
- min = SPA_MAX(min_allowed_rate, min);
21
+ min = SPA_MAX(min_allowed_rate * scale / interleave, min) * interleave / scale;
22
+ max = max * interleave / scale;
23
+ if (max < min)
24
+ return 0;
25
26
if (!state->multi_rate && state->card->format_ref > 0)
27
rate = state->card->rate;
28
29
choice->body.type = SPA_CHOICE_Enum;
30
spa_pod_builder_pop(b, &f1);
31
32
- if ((res = add_rate(state, 1, false, index & 0xffff, next, 0, params, b)) != 1)
33
+ if ((res = add_rate(state, 1, 1, false, index & 0xffff, next, 0, params, b)) != 1)
34
return res;
35
36
if ((res = add_channels(state, false, index & 0xffff, next, params, b)) != 1)
37
38
}
39
spa_pod_builder_pop(b, &f1);
40
41
- if ((res = add_rate(state, 1, true, index & 0xffff, next, 0, params, b)) != 1)
42
+ if ((res = add_rate(state, 1, 1, true, index & 0xffff, next, 0, params, b)) != 1)
43
return res;
44
45
(*next)++;
46
47
* 176400. This would correspond to "DSD32" (which does not exist). Trying
48
* to use such a rate with DSD hardware does not work and may cause undefined
49
* behavior in said hardware. */
50
- if ((res = add_rate(state, SPA_ABS(interleave), true, index & 0xffff, next, 44100 * 64 / 8, params, b)) != 1)
51
+ if ((res = add_rate(state, 8, SPA_ABS(interleave), true, index & 0xffff,
52
+ next, 44100, params, b)) != 1)
53
return res;
54
55
if ((res = add_channels(state, true, index & 0xffff, next, params, b)) != 1)
56
pipewire-0.3.57.tar.gz/spa/plugins/alsa/alsa-seq-bridge.c -> pipewire-0.3.58.tar.gz/spa/plugins/alsa/alsa-seq-bridge.c
Changed
67
1
2
{
3
strncpy(props->device, DEFAULT_DEVICE, sizeof(props->device));
4
strncpy(props->clock_name, DEFAULT_CLOCK_NAME, sizeof(props->clock_name));
5
+ props->disable_longname = 0;
6
}
7
8
static int impl_node_enum_params(void *object, int seq,
9
10
snd_seq_port_info_t *info;
11
snd_seq_client_info_t *client_info;
12
char card8;
13
- char name128;
14
+ char name256;
15
char path128;
16
char alias128;
17
18
19
snd_seq_get_any_client_info(this->sys.hndl,
20
port->addr.client, client_info);
21
22
- snprintf(name, sizeof(name), "%s:(%s_%d) %s",
23
- snd_seq_client_info_get_name(client_info),
24
- port->direction == SPA_DIRECTION_OUTPUT ? "capture" : "playback",
25
- port->addr.port,
26
- snd_seq_port_info_get_name(info));
27
+ int card_id;
28
+
29
+ // Failed to obtain card number (software device) or disabled
30
+ if (this->props.disable_longname || (card_id = snd_seq_client_info_get_card(client_info)) < 0) {
31
+ snprintf(name, sizeof(name), "%s:(%s_%d) %s",
32
+ snd_seq_client_info_get_name(client_info),
33
+ port->direction == SPA_DIRECTION_OUTPUT ? "capture" : "playback",
34
+ port->addr.port,
35
+ snd_seq_port_info_get_name(info));
36
+ } else {
37
+ char *longname;
38
+ if (snd_card_get_longname(card_id, &longname) == 0) {
39
+ snprintf(name, sizeof(name), "%s:(%s_%d) %s",
40
+ longname,
41
+ port->direction == SPA_DIRECTION_OUTPUT ? "capture" : "playback",
42
+ port->addr.port,
43
+ snd_seq_port_info_get_name(info));
44
+ free(longname);
45
+ } else {
46
+ // At least add card number to be distinct
47
+ snprintf(name, sizeof(name), "%s %d:(%s_%d) %s",
48
+ snd_seq_client_info_get_name(client_info),
49
+ card_id,
50
+ port->direction == SPA_DIRECTION_OUTPUT ? "capture" : "playback",
51
+ port->addr.port,
52
+ snd_seq_port_info_get_name(info));
53
+ }
54
+ }
55
clean_name(name);
56
57
snprintf(path, sizeof(path), "alsa:seq:%s:client_%d:%s_%d",
58
59
} else if (spa_streq(k, "clock.name")) {
60
spa_scnprintf(this->props.clock_name,
61
sizeof(this->props.clock_name), "%s", s);
62
+ } else if (spa_streq(k, SPA_KEY_API_ALSA_DISABLE_LONGNAME)) {
63
+ this->props.disable_longname = spa_atob(s);
64
}
65
}
66
67
pipewire-0.3.57.tar.gz/spa/plugins/alsa/alsa-seq.h -> pipewire-0.3.58.tar.gz/spa/plugins/alsa/alsa-seq.h
Changed
9
1
2
struct props {
3
char device64;
4
char clock_name64;
5
+ bool disable_longname;
6
};
7
8
#define MAX_EVENT_SIZE 1024
9
pipewire-0.3.57.tar.gz/spa/plugins/audioconvert/audioconvert.c -> pipewire-0.3.58.tar.gz/spa/plugins/audioconvert/audioconvert.c
Changed
113
1
2
#include <spa/support/log.h>
3
#include <spa/utils/result.h>
4
#include <spa/utils/list.h>
5
+#include <spa/utils/json.h>
6
#include <spa/utils/names.h>
7
#include <spa/utils/string.h>
8
#include <spa/node/node.h>
9
10
spa_log_info(this->log, "key:'%s' val:'%s'", name, value);
11
changed += audioconvert_set_param(this, name, value);
12
}
13
- if (changed) {
14
- channelmix_init(&this->mix);
15
- set_volume(this);
16
- }
17
return changed;
18
}
19
20
21
else if (have_channel_volume)
22
p->have_soft_volume = false;
23
24
+ channelmix_init(&this->mix);
25
set_volume(this);
26
}
27
return changed;
28
29
float volumesSPA_AUDIO_MAX_CHANNELS;
30
struct dir *dir = &this->dirthis->direction;
31
32
- spa_log_debug(this->log, "%p", this);
33
+ spa_log_debug(this->log, "%p have_format:%d", this, dir->have_format);
34
35
if (dir->have_format)
36
remap_volumes(this, &dir->format);
37
38
case SPA_PARAM_Buffers:
39
{
40
uint32_t size;
41
- struct dir *dir;
42
43
if (!port->have_format)
44
return -EIO;
45
if (result.index > 0)
46
return 0;
47
48
- dir = &this->dirdirection;
49
- if (dir->mode == SPA_PARAM_PORT_CONFIG_MODE_dsp) {
50
+ if (PORT_IS_DSP(this, direction, port_id)) {
51
/* DSP ports always use the quantum_limit as the buffer
52
* size. */
53
size = this->quantum_limit;
54
} else {
55
uint32_t irate, orate;
56
+ struct dir *dir = &this->dirdirection;
57
+
58
/* Convert ports are scaled so that they can always
59
* provide one quantum of data */
60
irate = dir->format.info.raw.rate;
61
62
return sizeof(struct impl);
63
}
64
65
+static uint32_t channel_from_name(const char *name)
66
+{
67
+ int i;
68
+ for (i = 0; spa_type_audio_channeli.name; i++) {
69
+ if (spa_streq(name, spa_debug_type_short_name(spa_type_audio_channeli.name)))
70
+ return spa_type_audio_channeli.type;
71
+ }
72
+ return SPA_AUDIO_CHANNEL_UNKNOWN;
73
+}
74
+
75
+static inline uint32_t parse_position(uint32_t *pos, const char *val, size_t len)
76
+{
77
+ struct spa_json it2;
78
+ char v256;
79
+ uint32_t i = 0;
80
+
81
+ spa_json_init(&it0, val, len);
82
+ if (spa_json_enter_array(&it0, &it1) <= 0)
83
+ spa_json_init(&it1, val, len);
84
+
85
+ while (spa_json_get_string(&it1, v, sizeof(v)) > 0 &&
86
+ i < SPA_AUDIO_MAX_CHANNELS) {
87
+ posi++ = channel_from_name(v);
88
+ }
89
+ return i;
90
+}
91
+
92
+
93
static int
94
impl_init(const struct spa_handle_factory *factory,
95
struct spa_handle *handle,
96
97
else
98
this->direction = SPA_DIRECTION_INPUT;
99
}
100
+ else if (spa_streq(k, SPA_KEY_AUDIO_POSITION))
101
+ this->props.n_channels = parse_position(this->props.channel_map, s, strlen(s));
102
else
103
audioconvert_set_param(this, k, s);
104
}
105
106
+ this->props.channel.n_volumes = this->props.n_channels;
107
+ this->props.soft.n_volumes = this->props.n_channels;
108
+ this->props.monitor.n_volumes = this->props.n_channels;
109
+
110
this->dirSPA_DIRECTION_INPUT.latency = SPA_LATENCY_INFO(SPA_DIRECTION_INPUT);
111
this->dirSPA_DIRECTION_OUTPUT.latency = SPA_LATENCY_INFO(SPA_DIRECTION_OUTPUT);
112
113
pipewire-0.3.57.tar.gz/spa/plugins/audioconvert/channelmix-ops.c -> pipewire-0.3.58.tar.gz/spa/plugins/audioconvert/channelmix-ops.c
Changed
36
1
2
#include <spa/support/log.h>
3
#include <spa/utils/defs.h>
4
5
-#define VOLUME_MIN 0.0f
6
-#define VOLUME_NORM 1.0f
7
-
8
#include "channelmix-ops.h"
9
#include "hilbert.h"
10
11
-
12
-#define _M(ch) (1UL << SPA_AUDIO_CHANNEL_ ## ch)
13
-#define MASK_MONO _M(FC)|_M(MONO)|_M(UNKNOWN)
14
-#define MASK_STEREO _M(FL)|_M(FR)|_M(UNKNOWN)
15
-#define MASK_QUAD _M(FL)|_M(FR)|_M(RL)|_M(RR)|_M(UNKNOWN)
16
-#define MASK_3_1 _M(FL)|_M(FR)|_M(FC)|_M(LFE)
17
-#define MASK_5_1 _M(FL)|_M(FR)|_M(FC)|_M(LFE)|_M(SL)|_M(SR)|_M(RL)|_M(RR)
18
-#define MASK_7_1 _M(FL)|_M(FR)|_M(FC)|_M(LFE)|_M(SL)|_M(SR)|_M(RL)|_M(RR)
19
-
20
#define ANY ((uint32_t)-1)
21
#define EQ ((uint32_t)-2)
22
23
24
for (i = 0; i < SPA_AUDIO_MAX_CHANNELS; i++)
25
matrixii= 1.0f;
26
}
27
+ if (dst_mask & FRONT)
28
+ filter_fc = true;
29
+ if (dst_mask & _MASK(LFE))
30
+ filter_lfe = true;
31
src_mask = dst_mask = ~0LU;
32
- filter_fc = filter_lfe = true;
33
goto done;
34
} else {
35
spa_log_debug(mix->log, "matching channels");
36
pipewire-0.3.57.tar.gz/spa/plugins/audioconvert/meson.build -> pipewire-0.3.58.tar.gz/spa/plugins/audioconvert/meson.build
Changed
10
1
2
'resample-peaks-sse.c',
3
'volume-ops-sse.c',
4
'channelmix-ops-sse.c' ,
5
- c_args : sse_args, '-O3', '-DHAVE_SSE',
6
+ c_args : sse_args, '-Ofast', '-DHAVE_SSE',
7
dependencies : spa_dep ,
8
install : false
9
)
10
pipewire-0.3.57.tar.gz/spa/plugins/audioconvert/resample-native-avx.c -> pipewire-0.3.58.tar.gz/spa/plugins/audioconvert/resample-native-avx.c
Changed
19
1
2
#include <assert.h>
3
#include <immintrin.h>
4
5
-static void inner_product_avx(float *d, const float * SPA_RESTRICT s,
6
+static inline void inner_product_avx(float *d, const float * SPA_RESTRICT s,
7
const float * SPA_RESTRICT taps, uint32_t n_taps)
8
{
9
__m256 sy2 = { _mm256_setzero_ps(), _mm256_setzero_ps() }, ty;
10
11
_mm_store_ss(d, sx0);
12
}
13
14
-static void inner_product_ip_avx(float *d, const float * SPA_RESTRICT s,
15
+static inline void inner_product_ip_avx(float *d, const float * SPA_RESTRICT s,
16
const float * SPA_RESTRICT t0, const float * SPA_RESTRICT t1, float x,
17
uint32_t n_taps)
18
{
19
pipewire-0.3.57.tar.gz/spa/plugins/audioconvert/resample-native-c.c -> pipewire-0.3.58.tar.gz/spa/plugins/audioconvert/resample-native-c.c
Changed
19
1
2
3
#include "resample-native-impl.h"
4
5
-static void inner_product_c(float *d, const float * SPA_RESTRICT s,
6
+static inline void inner_product_c(float *d, const float * SPA_RESTRICT s,
7
const float * SPA_RESTRICT taps, uint32_t n_taps)
8
{
9
float sum = 0.0f;
10
11
*d = sum;
12
}
13
14
-static void inner_product_ip_c(float *d, const float * SPA_RESTRICT s,
15
+static inline void inner_product_ip_c(float *d, const float * SPA_RESTRICT s,
16
const float * SPA_RESTRICT t0, const float * SPA_RESTRICT t1, float x,
17
uint32_t n_taps)
18
{
19
pipewire-0.3.57.tar.gz/spa/plugins/audioconvert/resample-native-neon.c -> pipewire-0.3.58.tar.gz/spa/plugins/audioconvert/resample-native-neon.c
Changed
19
1
2
3
#include <arm_neon.h>
4
5
-static void inner_product_neon(float *d, const float * SPA_RESTRICT s,
6
+static inline void inner_product_neon(float *d, const float * SPA_RESTRICT s,
7
const float * SPA_RESTRICT taps, uint32_t n_taps)
8
{
9
unsigned int remainder = n_taps % 16;
10
11
#endif
12
}
13
14
-static void inner_product_ip_neon(float *d, const float * SPA_RESTRICT s,
15
+static inline void inner_product_ip_neon(float *d, const float * SPA_RESTRICT s,
16
const float * SPA_RESTRICT t0, const float * SPA_RESTRICT t1, float x,
17
uint32_t n_taps)
18
{
19
pipewire-0.3.57.tar.gz/spa/plugins/audioconvert/resample-native-sse.c -> pipewire-0.3.58.tar.gz/spa/plugins/audioconvert/resample-native-sse.c
Changed
19
1
2
3
#include <xmmintrin.h>
4
5
-static void inner_product_sse(float *d, const float * SPA_RESTRICT s,
6
+static inline void inner_product_sse(float *d, const float * SPA_RESTRICT s,
7
const float * SPA_RESTRICT taps, uint32_t n_taps)
8
{
9
__m128 sum = _mm_setzero_ps();
10
11
_mm_store_ss(d, sum);
12
}
13
14
-static void inner_product_ip_sse(float *d, const float * SPA_RESTRICT s,
15
+static inline void inner_product_ip_sse(float *d, const float * SPA_RESTRICT s,
16
const float * SPA_RESTRICT t0, const float * SPA_RESTRICT t1, float x,
17
uint32_t n_taps)
18
{
19
pipewire-0.3.57.tar.gz/spa/plugins/audioconvert/resample-native-ssse3.c -> pipewire-0.3.58.tar.gz/spa/plugins/audioconvert/resample-native-ssse3.c
Changed
19
1
2
3
#include <tmmintrin.h>
4
5
-static void inner_product_ssse3(float *d, const float * SPA_RESTRICT s,
6
+static inline void inner_product_ssse3(float *d, const float * SPA_RESTRICT s,
7
const float * SPA_RESTRICT taps, uint32_t n_taps)
8
{
9
__m128 sum = _mm_setzero_ps();
10
11
_mm_store_ss(d, sum);
12
}
13
14
-static void inner_product_ip_ssse3(float *d, const float * SPA_RESTRICT s,
15
+static inline void inner_product_ip_ssse3(float *d, const float * SPA_RESTRICT s,
16
const float * SPA_RESTRICT t0, const float * SPA_RESTRICT t1, float x,
17
uint32_t n_taps)
18
{
19
pipewire-0.3.57.tar.gz/spa/plugins/audioconvert/resample-peaks-c.c -> pipewire-0.3.58.tar.gz/spa/plugins/audioconvert/resample-peaks-c.c
Changed
57
1
2
3
#include "resample-peaks-impl.h"
4
5
-void resample_peaks_process_c(struct resample *r,
6
- const void * SPA_RESTRICT src, uint32_t *in_len,
7
- void * SPA_RESTRICT dst, uint32_t *out_len)
8
+static inline float find_abs_max_c(const float *s, uint32_t n_samples, float m)
9
{
10
- struct peaks_data *pd = r->data;
11
- uint32_t c, i, o, end, chunk, o_count, i_count;
12
-
13
- if (SPA_UNLIKELY(r->channels == 0))
14
- return;
15
-
16
- for (c = 0; c < r->channels; c++) {
17
- const float *s = srcc;
18
- float *d = dstc, m = pd->max_fc;
19
-
20
- o_count = pd->o_count;
21
- i_count = pd->i_count;
22
- o = i = 0;
23
-
24
- while (i < *in_len && o < *out_len) {
25
- end = ((uint64_t) (o_count + 1) * r->i_rate) / r->o_rate;
26
- end = end > i_count ? end - i_count : 0;
27
- chunk = SPA_MIN(end, *in_len);
28
-
29
- for (; i < chunk; i++)
30
- m = SPA_MAX(fabsf(si), m);
31
-
32
- if (i == end) {
33
- do++ = m;
34
- m = 0.0f;
35
- o_count++;
36
- }
37
- }
38
- pd->max_fc = m;
39
- }
40
-
41
- *out_len = o;
42
- *in_len = i;
43
- pd->o_count = o_count;
44
- pd->i_count = i_count + i;
45
-
46
- while (pd->i_count >= r->i_rate) {
47
- pd->i_count -= r->i_rate;
48
- pd->o_count -= r->o_rate;
49
- }
50
+ uint32_t n;
51
+ for (n = 0; n < n_samples; n++)
52
+ m = fmaxf(fabsf(sn), m);
53
+ return m;
54
}
55
+
56
+MAKE_PEAKS(c);
57
pipewire-0.3.57.tar.gz/spa/plugins/audioconvert/resample-peaks-impl.h -> pipewire-0.3.58.tar.gz/spa/plugins/audioconvert/resample-peaks-impl.h
Changed
67
1
2
float max_f;
3
};
4
5
-void resample_peaks_process_c(struct resample *r,
6
- const void * SPA_RESTRICT src, uint32_t *in_len,
7
- void * SPA_RESTRICT dst, uint32_t *out_len);
8
+#define DEFINE_PEAKS(arch) \
9
+void resample_peaks_process_##arch(struct resample *r, \
10
+ const void * SPA_RESTRICT src, uint32_t *in_len, \
11
+ void * SPA_RESTRICT dst, uint32_t *out_len)
12
+
13
+#define MAKE_PEAKS(arch) \
14
+DEFINE_PEAKS(arch) \
15
+{ \
16
+ struct peaks_data *pd = r->data; \
17
+ uint32_t c, i, o, end, chunk, i_count, o_count; \
18
+ \
19
+ if (SPA_UNLIKELY(r->channels == 0)) \
20
+ return; \
21
+ \
22
+ for (c = 0; c < r->channels; c++) { \
23
+ const float *s = srcc; \
24
+ float *d = dstc, m = pd->max_fc; \
25
+ \
26
+ o_count = pd->o_count; \
27
+ i_count = pd->i_count; \
28
+ o = i = 0; \
29
+ \
30
+ while (i < *in_len && o < *out_len) { \
31
+ end = ((uint64_t) (o_count + 1) \
32
+ * r->i_rate) / r->o_rate; \
33
+ end = end > i_count ? end - i_count : 0; \
34
+ chunk = SPA_MIN(end, *in_len); \
35
+ \
36
+ m = find_abs_max_##arch(&si, chunk - i, m); \
37
+ \
38
+ i += chunk; \
39
+ \
40
+ if (i == end) { \
41
+ do++ = m; \
42
+ m = 0.0f; \
43
+ o_count++; \
44
+ } \
45
+ } \
46
+ pd->max_fc = m; \
47
+ } \
48
+ *out_len = o; \
49
+ *in_len = i; \
50
+ pd->o_count = o_count; \
51
+ pd->i_count = i_count + i; \
52
+ \
53
+ while (pd->i_count >= r->i_rate) { \
54
+ pd->i_count -= r->i_rate; \
55
+ pd->o_count -= r->o_rate; \
56
+ } \
57
+}
58
+
59
+
60
+DEFINE_PEAKS(c);
61
#if defined (HAVE_SSE)
62
-void resample_peaks_process_sse(struct resample *r,
63
- const void * SPA_RESTRICT src, uint32_t *in_len,
64
- void * SPA_RESTRICT dst, uint32_t *out_len);
65
+DEFINE_PEAKS(sse);
66
#endif
67
pipewire-0.3.57.tar.gz/spa/plugins/audioconvert/resample-peaks-sse.c -> pipewire-0.3.58.tar.gz/spa/plugins/audioconvert/resample-peaks-sse.c
Changed
86
1
2
{
3
__m128 t = _mm_movehl_ps(val, val);
4
t = _mm_max_ps(t, val);
5
- val = _mm_shuffle_ps(val, t, 0x55);
6
+ val = _mm_shuffle_ps(t, t, 0x55);
7
val = _mm_max_ss(t, val);
8
return _mm_cvtss_f32(val);
9
}
10
11
-void resample_peaks_process_sse(struct resample *r,
12
- const void * SPA_RESTRICT src, uint32_t *in_len,
13
- void * SPA_RESTRICT dst, uint32_t *out_len)
14
+static inline float find_abs_max_sse(const float *s, uint32_t n_samples, float m)
15
{
16
- struct peaks_data *pd = r->data;
17
- uint32_t c, i, o, end, chunk, unrolled, i_count, o_count;
18
- __m128 in, max, mask = _mm_andnot_ps(_mm_set_ps1(-0.0f),
19
- _mm_cmpeq_ps(_mm_setzero_ps(), _mm_setzero_ps()));
20
+ __m128 in2, max;
21
+ uint32_t n, unrolled;
22
+ const __m128 mask = _mm_set1_ps(-0.0f);
23
24
- if (r->channels == 0)
25
- return;
26
+ max = _mm_set1_ps(m);
27
28
- for (c = 0; c < r->channels; c++) {
29
- const float *s = srcc;
30
- float *d = dstc, m = pd->max_fc;
31
+ unrolled = n_samples & ~7;
32
33
- o_count = pd->o_count;
34
- i_count = pd->i_count;
35
- o = i = 0;
36
-
37
- max = _mm_set1_ps(m);
38
-
39
- while (i < *in_len && o < *out_len) {
40
- end = ((uint64_t) (o_count + 1) * r->i_rate) / r->o_rate;
41
- end = end > i_count ? end - i_count : 0;
42
- chunk = SPA_MIN(end, *in_len);
43
-
44
- unrolled = chunk - ((chunk - i) & 3);
45
-
46
- for (; i < unrolled; i+=4) {
47
- in = _mm_loadu_ps(&si);
48
- in = _mm_and_ps(mask, in);
49
- max = _mm_max_ps(in, max);
50
- }
51
- for (; i < chunk; i++)
52
- m = SPA_MAX(fabsf(si), m);
53
-
54
- if (i == end) {
55
- do++ = SPA_MAX(hmax_ps(max), m);
56
- m = 0.0f;
57
- max = _mm_set1_ps(m);
58
- o_count++;
59
- }
60
- }
61
- pd->max_fc = SPA_MAX(hmax_ps(max), m);
62
+ for (n = 0; n < unrolled; n += 8) {
63
+ in0 = _mm_loadu_ps(&sn + 0);
64
+ in1 = _mm_loadu_ps(&sn + 4);
65
+ in0 = _mm_andnot_ps(mask, in0);
66
+ in1 = _mm_andnot_ps(mask, in1);
67
+ max = _mm_max_ps(max, in0);
68
+ max = _mm_max_ps(max, in1);
69
}
70
+ for (; n < n_samples; n++)
71
+ m = fmaxf(fabsf(sn), m);
72
73
- *out_len = o;
74
- *in_len = i;
75
- pd->o_count = o_count;
76
- pd->i_count = i_count + i;
77
-
78
- while (pd->i_count >= r->i_rate) {
79
- pd->i_count -= r->i_rate;
80
- pd->o_count -= r->o_rate;
81
- }
82
+ return fmaxf(hmax_ps(max), m);
83
}
84
+
85
+MAKE_PEAKS(sse);
86
pipewire-0.3.57.tar.gz/spa/plugins/audiomixer/audiomixer.c -> pipewire-0.3.58.tar.gz/spa/plugins/audiomixer/audiomixer.c
Changed
24
1
2
#define SPA_LOG_TOPIC_DEFAULT log_topic
3
static struct spa_log_topic *log_topic = &SPA_LOG_TOPIC(0, "spa.audiomixer");
4
5
+#define DEFAULT_RATE 48000
6
+#define DEFAULT_CHANNELS 2
7
+
8
#define MAX_BUFFERS 64
9
#define MAX_PORTS 128
10
#define MAX_CHANNELS 64
11
12
SPA_AUDIO_FORMAT_U24_32,
13
SPA_AUDIO_FORMAT_F32,
14
SPA_AUDIO_FORMAT_F64),
15
- SPA_FORMAT_AUDIO_rate, SPA_POD_CHOICE_RANGE_Int(44100, 1, INT32_MAX),
16
- SPA_FORMAT_AUDIO_channels, SPA_POD_CHOICE_RANGE_Int(2, 1, INT32_MAX));
17
+ SPA_FORMAT_AUDIO_rate, SPA_POD_CHOICE_RANGE_Int(
18
+ DEFAULT_RATE, 1, INT32_MAX),
19
+ SPA_FORMAT_AUDIO_channels, SPA_POD_CHOICE_RANGE_Int(
20
+ DEFAULT_CHANNELS, 1, INT32_MAX));
21
}
22
break;
23
default:
24
pipewire-0.3.57.tar.gz/spa/plugins/audiotestsrc/audiotestsrc.c -> pipewire-0.3.58.tar.gz/spa/plugins/audiotestsrc/audiotestsrc.c
Changed
24
1
2
WAVE_SQUARE,
3
};
4
5
+#define DEFAULT_RATE 48000
6
+#define DEFAULT_CHANNELS 2
7
+
8
#define DEFAULT_LIVE true
9
#define DEFAULT_WAVE WAVE_SINE
10
#define DEFAULT_FREQ 440.0
11
12
SPA_AUDIO_FORMAT_S32,
13
SPA_AUDIO_FORMAT_F32,
14
SPA_AUDIO_FORMAT_F64),
15
- SPA_FORMAT_AUDIO_rate, SPA_POD_CHOICE_RANGE_Int(44100, 1, INT32_MAX),
16
- SPA_FORMAT_AUDIO_channels, SPA_POD_CHOICE_RANGE_Int(2, 1, INT32_MAX));
17
+ SPA_FORMAT_AUDIO_rate, SPA_POD_CHOICE_RANGE_Int(
18
+ DEFAULT_RATE, 1, INT32_MAX),
19
+ SPA_FORMAT_AUDIO_channels, SPA_POD_CHOICE_RANGE_Int(
20
+ DEFAULT_CHANNELS, 1, INT32_MAX));
21
break;
22
default:
23
return 0;
24
pipewire-0.3.57.tar.gz/spa/plugins/bluez5/README-OPUS-A2DP.md -> pipewire-0.3.58.tar.gz/spa/plugins/bluez5/README-OPUS-A2DP.md
Changed
201
1
2
3
# OPUS-A2DP-0.5 specification
4
5
-DRAFT
6
+In this file, a way to use Opus as an A2DP vendor codec is specified.
7
8
-In this file, we specify how to use Opus as an A2DP vendor codec. We
9
-will call this "OPUS-A2DP-0.5". There is no previous public
10
+We will call this "OPUS-A2DP-0.5". There is no previous public
11
specification for using Opus as an A2DP vendor codec (to my
12
knowledge), which is why we need this one.
13
14
_TOC_
15
16
-# A2DP Codec Capabilities
17
+# Media Codec Capabilities
18
19
-The A2DP capability structure is as follows.
20
-
21
-Integer fields and multi-byte bitfields are laid out in **little
22
-endian** order. All integer fields are unsigned.
23
-
24
-Each entry may have different meaning when present as a capability.
25
-Below, we indicate this by abbreviations CAP/SNK for sink capability,
26
-CAP/SRC for source capability, CAP for capability as either, and SEL
27
-for the selected value by SRC.
28
-
29
-Bits in fields marked RFA (Reserved For Additions) shall be set to
30
-zero.
31
-
32
-The capability and configuration structure is as follows:
33
+The Media Codec Specific Information Elements (AVDTP v1.3, §8.21.5)
34
+capability and configuration structure is as follows:
35
36
| Octet | Bits | Meaning |
37
|-------|------|-----------------------------------------------|
38
39
| 17-20 | 0-7 | Return Direction Audio Location Configuration |
40
| 21-23 | 0-7 | Return Direction Limits Configuration |
41
42
-See `a2dp-codec-caps.h` for definition as C structs.
43
+All integer fields and multi-byte bitfields are laid out in **little
44
+endian** order. All integer fields are unsigned.
45
+
46
+Each entry may have different meaning when present as a capability.
47
+Below, we indicate this by abbreviations CAP for capability and SEL
48
+for the value selected by SRC.
49
+
50
+Bits in fields marked RFA (Reserved For Additions) shall be set to
51
+zero.
52
+
53
+> **Note**
54
+>
55
+> See `a2dp-codec-caps.h` for definition as C structs.
56
57
## Vendor ID Part
58
59
60
| 0-3 | 0-7 | A2DP Vendor ID (0x05F1) |
61
| 4-5 | 0-7 | A2DP Vendor Codec ID (0x1005) |
62
63
-The Vendor ID is that of the Linux Foundation, and we are using it
64
-here unofficially.
65
+> **Note**
66
+>
67
+> The Vendor ID is that of the Linux Foundation, and we are using it
68
+> here unofficially.
69
70
## Channel Configuration
71
72
-The channel configuration consists of the channel count and a bitfield
73
-indicating which of them are encoded in coupled streams.
74
+The channel configuration consists of the channel count, and the count
75
+of coupled streams. The latter indicates which channels are encoded as
76
+left/right pairs, as defined in Sec. 5.1.1 of Opus Ogg Encapsulation RFC7845.
77
78
| Octet | Bits | Meaning |
79
|-------|------|------------------------------------------------------------|
80
81
`(Channel Count) >= 2*(Coupled Stream Count)`.
82
The Stream Count is `(Channel Count) - (Coupled Stream Count)`.
83
84
-Streams and Coupled Streams have the same meaning as in Sec. 5.1.1 of
85
-Opus Multistream RFC7845.
86
-
87
The logical Channels are identified by a Channel Index *j* such that `0 <= j
88
< (Channel Count)`. The channels `0 <= j < 2*(Coupled Stream Count)`
89
are encoded in the *k*-th stream of the payload, where `k = floor(j/2)` and
90
`j mod 2` determines which of the two channels of the stream the logical
91
channel is. The channels `2*(Coupled Stream Count) <= j < (Channel Count)`
92
are encoded in the *k*-th stream of the payload, where `k = j - (Coupled Stream Count)`.
93
-The prescription here is identical to RFC7845 with channel mapping
94
-`mappingj = j`.
95
96
-The semantic meaning for each channel is determined by their Audio
97
-Location.
98
+> **Note**
99
+>
100
+> The prescription here is identical to RFC7845 with channel mapping
101
+> `mappingj = j`. We do not want to include the mapping table in the
102
+> A2DP capabilities, so it is assumed to be trivial.
103
104
## Audio Location Configuration
105
106
-The channel audio location specification is similar to the location
107
-bitfield of the `Audio_Channel_Allocation` LTV structure in Bluetooth
108
-SIG Assigned Numbers, Generic Audio used in the LE Audio.
109
+The semantic meaning for each channel is determined by their Audio
110
+Location bitfield.
111
112
| Octet | Bits | Meaning |
113
|-------|------|------------------------------------------------------|
114
115
that were not set in CAP. SNK shall handle unsupported audio
116
locations. It may do this for example by ignoring unsupported channels
117
or via suitable up/downmixing. Hence, SRC may transmit channels with
118
-audio locations that are not marked supported by SNK. The maximum
119
-Channel Count however shall not be exceeded.
120
+audio locations that are not marked supported by SNK.
121
122
-The audio location bitfield values defined in Assigned Numbers,
123
-Generic Audio are:
124
+The audio location bit values are:
125
126
| Channel Order | Bitmask | Audio Location |
127
|---------------|------------|-------------------------|
128
129
| 30 | 0x40000000 | RFA |
130
| 31 | 0x80000000 | RFA |
131
132
-In addition, we define a specific Channel Order for each. The bits
133
-set in the bitfield define audio locations for the streams present in the
134
+Each bit value is associated with a Channel Order. The bits set in
135
+the bitfield define audio locations for the streams present in the
136
payload. The set bit with the smallest Channel Order value defines the
137
audio location for the Channel Index *j=0*, the bit with the next
138
lowest Channel Order value defines the audio location for the Channel
139
140
When the Channel Count is larger than the number of bits set in the
141
Audio Location bitfield, the audio locations of the remaining channels
142
are unspecified. Implementations may handle them as appropriate for
143
-their use case, considering them as AUX0-AUXN, or in the case of
144
+their use case, considering them as AUX0–AUXN, or in the case of
145
Channel Count = 1, as the single mono audio channel.
146
147
When the Channel Count is smaller than the number of bits set in the
148
Audio Location bitfield, the audio locations for the channels are
149
assigned as above, and remaining excess bits shall be ignored.
150
151
-The channel ordering defined here is compatible with the internal
152
-stream ordering in the reference Opus Multistream surround encoder
153
-Mapping Family 0 and 1 output. This allows making use of its surround
154
-masking and LFE handling capabilities. The stream ordering of the
155
-reference Opus surround encoder, although being unchanged since its
156
-addition in 2013, is an internal detail of the
157
-encoder. Implementations using the surround encoder shall check that
158
-the mapping table used by the encoder corresponds to the above channel
159
-ordering.
160
-
161
-For reference, we list the Audio Location bitfield values
162
-corresponding to the different channel counts in Opus Mapping Family 0
163
-and 1 surround encoder output, and the expected mapping table:
164
-
165
-| Mapping Family | Channel Count | Audio Location Value | Stream Ordering | Mapping Table |
166
-|----------------|---------------|----------------------|---------------------------------|--------------------------|
167
-| 0 | 1 | 0x00000000 | mono | {0} |
168
-| 0 | 2 | 0x00000003 | FL, FR | {0, 1} |
169
-| 1 | 1 | 0x00000000 | mono | {0} |
170
-| 1 | 2 | 0x00000003 | FL, FR | {0, 1} |
171
-| 1 | 3 | 0x00000007 | FL, FR, FC | {0, 2, 1} |
172
-| 1 | 4 | 0x00000033 | FL, FR, BL, BR | {0, 1, 2, 3} |
173
-| 1 | 5 | 0x00000037 | FL, FR, BL, BR, FC | {0, 4, 1, 2, 3} |
174
-| 1 | 6 | 0x0000003f | FL, FR, BL, BR, FC, LFE | {0, 4, 1, 2, 3, 5} |
175
-| 1 | 7 | 0x00000d0f | FL, FR, SL, SR, FC, BC, LFE | {0, 4, 1, 2, 3, 5, 6} |
176
-| 1 | 8 | 0x00000c3f | FL, FR, SL, SR, BL, BR, FC, LFE | {0, 6, 1, 2, 3, 4, 5, 7} |
177
-
178
-The Mapping Table in the table indicates the mapping table selected by
179
-`opus_multistream_surround_encoder_create` (Opus 1.3.1). If the
180
-encoder outputs a different mapping table in a future Opus encoder
181
-release, the channel ordering will be incorrect, and the surround
182
-encoder can not be used. We expect that the probability of the Opus
183
-encoder authors making such changes is negligible.
184
+> **Note**
185
+>
186
+> The channel audio location specification is similar to the location
187
+> bitfield of the `Audio_Channel_Allocation` LTV structure in Bluetooth
188
+> SIG Assigned Numbers, Generic Audio used in the LE Audio, and the
189
+> bitmasks defined above are the same.
190
+>
191
+> The channel ordering differs from LE Audio, and is defined here to be
192
+> compatible with the internal stream ordering in the reference Opus
193
+> Multistream surround encoder Mapping Family 0 and 1 output. This
194
+> allows making use of its surround masking and LFE handling
195
+> capabilities. The stream ordering of the reference Opus surround
196
+> encoder, although being unchanged since its addition in 2013, is an
197
+> internal detail of the encoder. Implementations using the surround
198
+> encoder need to check that the mapping table used by the encoder
199
+> corresponds to the above channel ordering.
200
+>
201
pipewire-0.3.57.tar.gz/spa/plugins/bluez5/a2dp-sink.c -> pipewire-0.3.58.tar.gz/spa/plugins/bluez5/a2dp-sink.c
Changed
21
1
2
3
static int do_start(struct impl *this)
4
{
5
- int i, res, val, size;
6
+ int res, val, size;
7
struct port *port;
8
socklen_t len;
9
uint8_t *conf;
10
11
conf = this->transport->configuration;
12
size = this->transport->configuration_len;
13
14
- for (i = 0; i < size; i++)
15
- spa_log_debug(this->log, " %d: %02x", i, confi);
16
+ spa_log_debug(this->log, "Transport configuration:");
17
+ spa_log_hexdump(this->log, SPA_LOG_LEVEL_DEBUG, 2, conf, (size_t)size);
18
19
this->codec_data = this->codec->init(this->codec,
20
this->is_duplex ? A2DP_CODEC_FLAG_SINK : 0,
21
pipewire-0.3.57.tar.gz/spa/plugins/bluez5/bluez5-dbus.c -> pipewire-0.3.58.tar.gz/spa/plugins/bluez5/bluez5-dbus.c
Changed
68
1
2
uint8_t *pconf = (uint8_t *) config;
3
DBusMessage *r;
4
DBusError err;
5
- int i, size, res;
6
+ int size, res;
7
const struct a2dp_codec *codec;
8
bool sink;
9
10
11
return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
12
}
13
spa_log_info(monitor->log, "%p: %s select conf %d", monitor, path, size);
14
- for (i = 0; i < size; i++)
15
- spa_log_debug(monitor->log, " %d: %02x", i, capi);
16
+ spa_log_hexdump(monitor->log, SPA_LOG_LEVEL_DEBUG, 2, cap, (size_t)size);
17
18
codec = a2dp_endpoint_to_codec(monitor, path, &sink);
19
if (codec != NULL)
20
21
return DBUS_HANDLER_RESULT_NEED_MEMORY;
22
goto exit_send;
23
}
24
- for (i = 0; i < size; i++)
25
- spa_log_debug(monitor->log, " %d: %02x", i, pconfi);
26
+ spa_log_hexdump(monitor->log, SPA_LOG_LEVEL_DEBUG, 2, pconf, (size_t)size);
27
28
if ((r = dbus_message_new_method_return(m)) == NULL)
29
return DBUS_HANDLER_RESULT_NEED_MEMORY;
30
31
else if (spa_streq(key, "Capabilities")) {
32
DBusMessageIter iter;
33
uint8_t *value;
34
- int i, len;
35
+ int len;
36
37
if (!check_iter_signature(&it1, "ay"))
38
goto next;
39
40
dbus_message_iter_get_fixed_array(&iter, &value, &len);
41
42
spa_log_debug(monitor->log, "remote_endpoint %p: %s=%d", remote_endpoint, key, len);
43
- for (i = 0; i < len; i++)
44
- spa_log_debug(monitor->log, " %d: %02x", i, valuei);
45
+ spa_log_hexdump(monitor->log, SPA_LOG_LEVEL_DEBUG, 2, value, (size_t)len);
46
47
free(remote_endpoint->capabilities);
48
remote_endpoint->capabilities_len = 0;
49
50
else if (spa_streq(key, "Configuration")) {
51
DBusMessageIter iter;
52
uint8_t *value;
53
- int i, len;
54
+ int len;
55
56
if (!check_iter_signature(&it1, "ay"))
57
goto next;
58
59
dbus_message_iter_get_fixed_array(&iter, &value, &len);
60
61
spa_log_debug(monitor->log, "transport %p: %s=%d", transport, key, len);
62
- for (i = 0; i < len; i++)
63
- spa_log_debug(monitor->log, " %d: %02x", i, valuei);
64
+ spa_log_hexdump(monitor->log, SPA_LOG_LEVEL_DEBUG, 2, value, (size_t)len);
65
66
free(transport->configuration);
67
transport->configuration_len = 0;
68
pipewire-0.3.57.tar.gz/spa/plugins/libcamera/libcamera-utils.cpp -> pipewire-0.3.58.tar.gz/spa/plugins/libcamera/libcamera-utils.cpp
Changed
10
1
2
port->streamConfig = impl->config->at(0);
3
4
if ((res = allocBuffers(impl, port, port->streamConfig.bufferCount)) < 0)
5
- return res;
6
+ goto error;
7
8
port->have_format = true;
9
10
pipewire-0.3.57.tar.gz/spa/plugins/support/null-audio-sink.c -> pipewire-0.3.58.tar.gz/spa/plugins/support/null-audio-sink.c
Changed
10
1
2
}
3
4
#define DEFAULT_CHANNELS 2
5
-#define DEFAULT_RATE 44100
6
+#define DEFAULT_RATE 48000
7
8
#define MAX_BUFFERS 16
9
#define MAX_PORTS 1
10
pipewire-0.3.57.tar.gz/spa/plugins/v4l2/v4l2-source.c -> pipewire-0.3.58.tar.gz/spa/plugins/v4l2/v4l2-source.c
Changed
10
1
2
3
switch (SPA_NODE_COMMAND_ID(command)) {
4
case SPA_NODE_COMMAND_ParamBegin:
5
- if ((res = spa_v4l2_open(&port->dev, NULL)) < 0)
6
+ if ((res = spa_v4l2_open(&port->dev, this->props.device)) < 0)
7
return res;
8
break;
9
case SPA_NODE_COMMAND_ParamEnd:
10
pipewire-0.3.57.tar.gz/spa/plugins/videoconvert/videoadapter.c -> pipewire-0.3.58.tar.gz/spa/plugins/videoconvert/videoadapter.c
Changed
201
1
2
3
#include <spa/support/plugin.h>
4
#include <spa/support/log.h>
5
+#include <spa/support/cpu.h>
6
7
#include <spa/node/node.h>
8
#include <spa/node/io.h>
9
#include <spa/node/utils.h>
10
#include <spa/node/keys.h>
11
-#include <spa/utils/result.h>
12
#include <spa/utils/names.h>
13
+#include <spa/utils/result.h>
14
#include <spa/utils/string.h>
15
#include <spa/buffer/alloc.h>
16
#include <spa/pod/parser.h>
17
#include <spa/pod/filter.h>
18
+#include <spa/pod/dynamic.h>
19
+#include <spa/param/param.h>
20
+#include <spa/param/video/format-utils.h>
21
+#include <spa/param/latency-utils.h>
22
#include <spa/debug/format.h>
23
#include <spa/debug/pod.h>
24
25
+#undef SPA_LOG_TOPIC_DEFAULT
26
+#define SPA_LOG_TOPIC_DEFAULT log_topic
27
+static struct spa_log_topic *log_topic = &SPA_LOG_TOPIC(0, "spa.videoadapter");
28
+
29
#define DEFAULT_ALIGN 16
30
31
-#define NAME "videoadapter"
32
+#define MAX_PORTS 1
33
34
/** \cond */
35
36
37
struct spa_node node;
38
39
struct spa_log *log;
40
+ struct spa_cpu *cpu;
41
42
+ uint32_t max_align;
43
enum spa_direction direction;
44
45
struct spa_node *target;
46
- struct spa_hook target_listener;
47
48
struct spa_node *follower;
49
struct spa_hook follower_listener;
50
uint32_t follower_flags;
51
+ struct spa_video_info follower_current_format;
52
+ struct spa_video_info default_format;
53
54
struct spa_handle *hnd_convert;
55
struct spa_node *convert;
56
-
57
+ struct spa_hook convert_listener;
58
uint32_t convert_flags;
59
60
uint32_t n_buffers;
61
62
63
struct spa_io_buffers io_buffers;
64
struct spa_io_rate_match io_rate_match;
65
+ struct spa_io_position *io_position;
66
67
uint64_t info_all;
68
struct spa_node_info info;
69
- struct spa_param_info params5;
70
+#define IDX_EnumFormat 0
71
+#define IDX_PropInfo 1
72
+#define IDX_Props 2
73
+#define IDX_Format 3
74
+#define IDX_EnumPortConfig 4
75
+#define IDX_PortConfig 5
76
+#define IDX_Latency 6
77
+#define IDX_ProcessLatency 7
78
+#define N_NODE_PARAMS 8
79
+ struct spa_param_info paramsN_NODE_PARAMS;
80
+ uint32_t convert_params_flagsN_NODE_PARAMS;
81
+ uint32_t follower_params_flagsN_NODE_PARAMS;
82
83
struct spa_hook_list hooks;
84
struct spa_callbacks callbacks;
85
86
- unsigned int use_converter:1;
87
+ unsigned int add_listener:1;
88
+ unsigned int have_format:1;
89
unsigned int started:1;
90
- unsigned int active:1;
91
unsigned int driver:1;
92
- unsigned int driving:1;
93
- unsigned int monitor:1;
94
+ unsigned int async:1;
95
+ unsigned int passthrough:1;
96
+ unsigned int follower_removing:1;
97
};
98
99
/** \endcond */
100
101
+static int follower_enum_params(struct impl *this,
102
+ uint32_t id,
103
+ uint32_t idx,
104
+ struct spa_result_node_params *result,
105
+ const struct spa_pod *filter,
106
+ struct spa_pod_builder *builder)
107
+{
108
+ int res;
109
+ if (result->next < 0x100000) {
110
+ if (this->convert != NULL &&
111
+ (res = spa_node_enum_params_sync(this->convert,
112
+ id, &result->next, filter, &result->param, builder)) == 1)
113
+ return res;
114
+ result->next = 0x100000;
115
+ }
116
+ if (result->next < 0x200000 && this->follower_params_flagsidx & SPA_PARAM_INFO_READ) {
117
+ result->next &= 0xfffff;
118
+ if ((res = spa_node_enum_params_sync(this->follower,
119
+ id, &result->next, filter, &result->param, builder)) == 1) {
120
+ result->next |= 0x100000;
121
+ return res;
122
+ }
123
+ result->next = 0x200000;
124
+ }
125
+ return 0;
126
+}
127
+
128
static int impl_node_enum_params(void *object, int seq,
129
uint32_t id, uint32_t start, uint32_t num,
130
const struct spa_pod *filter)
131
{
132
struct impl *this = object;
133
- struct spa_pod *param;
134
- struct spa_pod_builder b = { 0 };
135
- uint8_t buffer1024;
136
+ uint8_t buffer4096;
137
+ struct spa_pod_dynamic_builder b;
138
struct spa_result_node_params result;
139
uint32_t count = 0;
140
int res;
141
142
result.id = id;
143
result.next = start;
144
next:
145
- result.index = result.next++;
146
+ result.index = result.next;
147
148
- spa_pod_builder_init(&b, buffer, sizeof(buffer));
149
+ spa_log_debug(this->log, "%p: %d id:%u", this, seq, id);
150
+
151
+ spa_pod_dynamic_builder_init(&b, buffer, sizeof(buffer), 4096);
152
153
switch (id) {
154
+ case SPA_PARAM_EnumPortConfig:
155
+ case SPA_PARAM_PortConfig:
156
+ if (this->convert == NULL)
157
+ return 0;
158
+ res = spa_node_enum_params(this->convert, seq, id, start, num, filter);
159
+ return res;
160
case SPA_PARAM_PropInfo:
161
+ res = follower_enum_params(this,
162
+ id, IDX_PropInfo, &result, filter, &b.b);
163
+ break;
164
case SPA_PARAM_Props:
165
- if ((res = spa_node_enum_params_sync(this->target,
166
- id, &start, filter, ¶m, &b)) != 1)
167
- return res;
168
+ res = follower_enum_params(this,
169
+ id, IDX_Props, &result, filter, &b.b);
170
+ break;
171
+ case SPA_PARAM_ProcessLatency:
172
+ res = follower_enum_params(this,
173
+ id, IDX_ProcessLatency, &result, filter, &b.b);
174
break;
175
-
176
case SPA_PARAM_EnumFormat:
177
case SPA_PARAM_Format:
178
- if ((res = spa_node_port_enum_params_sync(this->follower,
179
+ case SPA_PARAM_Latency:
180
+ res = spa_node_port_enum_params_sync(this->follower,
181
this->direction, 0,
182
- id, &start, filter, ¶m, &b)) != 1)
183
- return res;
184
+ id, &result.next, filter, &result.param, &b.b);
185
break;
186
-
187
default:
188
return -ENOENT;
189
}
190
191
- if (spa_pod_filter(&b, &result.param, param, filter) < 0)
192
- goto next;
193
+ if (res == 1) {
194
+ spa_node_emit_result(&this->hooks, seq, 0, SPA_RESULT_TYPE_NODE_PARAMS, &result);
195
+ count++;
196
+ }
197
+ spa_pod_dynamic_builder_clean(&b);
198
199
- spa_node_emit_result(&this->hooks, seq, 0, SPA_RESULT_TYPE_NODE_PARAMS, &result);
200
+ if (res != 1)
201
pipewire-0.3.57.tar.gz/spa/plugins/volume/volume.c -> pipewire-0.3.58.tar.gz/spa/plugins/volume/volume.c
Changed
24
1
2
3
#define NAME "volume"
4
5
+#define DEFAULT_RATE 48000
6
+#define DEFAULT_CHANNELS 2
7
+
8
#define DEFAULT_VOLUME 1.0
9
#define DEFAULT_MUTE false
10
11
12
SPA_AUDIO_FORMAT_S16,
13
SPA_AUDIO_FORMAT_S16,
14
SPA_AUDIO_FORMAT_S32),
15
- SPA_FORMAT_AUDIO_rate, SPA_POD_CHOICE_RANGE_Int(44100, 1, INT32_MAX),
16
- SPA_FORMAT_AUDIO_channels, SPA_POD_CHOICE_RANGE_Int(2, 1, INT32_MAX));
17
+ SPA_FORMAT_AUDIO_rate, SPA_POD_CHOICE_RANGE_Int(
18
+ DEFAULT_RATE, 1, INT32_MAX),
19
+ SPA_FORMAT_AUDIO_channels, SPA_POD_CHOICE_RANGE_Int(
20
+ DEFAULT_CHANNELS, 1, INT32_MAX));
21
break;
22
default:
23
return 0;
24
pipewire-0.3.57.tar.gz/src/modules/module-echo-cancel.c -> pipewire-0.3.58.tar.gz/src/modules/module-echo-cancel.c
Changed
111
1
2
pw_stream_queue_buffer(impl->capture, buf);
3
}
4
5
-static void input_state_changed(void *data, enum pw_stream_state old,
6
+static void capture_state_changed(void *data, enum pw_stream_state old,
7
enum pw_stream_state state, const char *error)
8
{
9
struct impl *impl = data;
10
11
}
12
}
13
14
+static void source_state_changed(void *data, enum pw_stream_state old,
15
+ enum pw_stream_state state, const char *error)
16
+{
17
+ struct impl *impl = data;
18
+ int res;
19
+
20
+ switch (state) {
21
+ case PW_STREAM_STATE_PAUSED:
22
+ pw_stream_flush(impl->source, false);
23
+ pw_stream_flush(impl->capture, false);
24
+
25
+ if (old == PW_STREAM_STATE_STREAMING) {
26
+ pw_log_debug("%p: deactivate %s", impl, impl->aec->name);
27
+ res = spa_audio_aec_deactivate(impl->aec);
28
+ if (res < 0 && res != -EOPNOTSUPP) {
29
+ pw_log_error("aec plugin %s deactivate failed: %s", impl->aec->name, spa_strerror(res));
30
+ }
31
+ }
32
+ break;
33
+ case PW_STREAM_STATE_STREAMING:
34
+ pw_log_debug("%p: activate %s", impl, impl->aec->name);
35
+ res = spa_audio_aec_activate(impl->aec);
36
+ if (res < 0 && res != -EOPNOTSUPP) {
37
+ pw_log_error("aec plugin %s activate failed: %s", impl->aec->name, spa_strerror(res));
38
+ }
39
+ break;
40
+ case PW_STREAM_STATE_UNCONNECTED:
41
+ pw_log_info("%p: input unconnected", impl);
42
+ pw_impl_module_schedule_destroy(impl->module);
43
+ break;
44
+ case PW_STREAM_STATE_ERROR:
45
+ pw_log_info("%p: input error: %s", impl, error);
46
+ break;
47
+ default:
48
+ break;
49
+ }
50
+}
51
+
52
static void input_param_latency_changed(struct impl *impl, const struct spa_pod *param)
53
{
54
struct spa_latency_info latency;
55
56
static const struct pw_stream_events capture_events = {
57
PW_VERSION_STREAM_EVENTS,
58
.destroy = capture_destroy,
59
- .state_changed = input_state_changed,
60
+ .state_changed = capture_state_changed,
61
.process = capture_process,
62
.param_changed = input_param_changed
63
};
64
65
static const struct pw_stream_events source_events = {
66
PW_VERSION_STREAM_EVENTS,
67
.destroy = source_destroy,
68
- .state_changed = input_state_changed,
69
+ .state_changed = source_state_changed,
70
.param_changed = input_param_changed
71
};
72
73
74
75
handle = spa_plugin_loader_load(impl->loader, SPA_NAME_AEC, &info);
76
if (handle == NULL) {
77
- pw_log_error("AEC codec plugin %s not available library.name %s", SPA_NAME_AEC, path);
78
+ pw_log_error("aec plugin %s not available library.name %s", SPA_NAME_AEC, path);
79
return -ENOENT;
80
}
81
82
83
}
84
impl->aec = iface;
85
impl->spa_handle = handle;
86
- if (impl->aec->iface.version != SPA_VERSION_AUDIO_AEC) {
87
- pw_log_error("codec plugin %s has incompatible ABI version (%d != %d)",
88
+
89
+ if (impl->aec->iface.version > SPA_VERSION_AUDIO_AEC) {
90
+ pw_log_error("codec plugin %s has incompatible ABI version (%d > %d)",
91
SPA_NAME_AEC, impl->aec->iface.version, SPA_VERSION_AUDIO_AEC);
92
res = -ENOENT;
93
goto error;
94
}
95
96
- pw_log_info("Using plugin AEC %s", impl->aec->name);
97
+ pw_log_info("Using plugin AEC %s with version %d", impl->aec->name,
98
+ impl->aec->iface.version);
99
100
if ((str = pw_properties_get(props, "aec.args")) != NULL)
101
aec_props = pw_properties_new_string(str);
102
103
pw_properties_free(aec_props);
104
105
if (res < 0) {
106
- pw_log_error("codec plugin %s create failed: %s", impl->aec->name,
107
+ pw_log_error("aec plugin %s create failed: %s", impl->aec->name,
108
spa_strerror(res));
109
goto error;
110
}
111
pipewire-0.3.57.tar.gz/src/modules/module-filter-chain.c -> pipewire-0.3.58.tar.gz/src/modules/module-filter-chain.c
Changed
75
1
2
str = strdupa(name);
3
col = strchr(str, ':');
4
if (col != NULL) {
5
+ struct node *find;
6
node_name = str;
7
port_name = col + 1;
8
*col = '\0';
9
- node = find_node(node->graph, node_name);
10
- } else {
11
+ find = find_node(node->graph, node_name);
12
+ if (find == NULL) {
13
+ /* it's possible that the : is part of the port name,
14
+ * try again without splitting things up. */
15
+ *col = ':';
16
+ col = NULL;
17
+ } else {
18
+ node = find;
19
+ }
20
+ }
21
+ if (col == NULL) {
22
node_name = node->name;
23
port_name = str;
24
}
25
26
27
port = find_port(node, name, FC_PORT_INPUT | FC_PORT_CONTROL);
28
if (port == NULL)
29
- return 0;
30
+ return -ENOENT;
31
32
node = port->node;
33
desc = node->desc;
34
35
{
36
struct spa_pod_parser prs;
37
struct spa_pod_frame f;
38
- int changed = 0;
39
+ int res, changed = 0;
40
struct node *def_node;
41
42
def_node = spa_list_first(&graph->node_list, struct node, link);
43
44
struct spa_pod *pod;
45
spa_pod_parser_get_pod(&prs, &pod);
46
}
47
- changed += set_control_value(def_node, name, val);
48
+ if ((res = set_control_value(def_node, name, val)) > 0)
49
+ changed += res;
50
}
51
return changed;
52
}
53
54
while (spa_json_get_string(control, key, sizeof(key)) > 0) {
55
float fl;
56
const char *val;
57
- int len;
58
+ int res, len;
59
60
if ((len = spa_json_next(control, &val)) < 0)
61
break;
62
63
- if (spa_json_parse_float(val, len, &fl) <= 0)
64
+ if (spa_json_parse_float(val, len, &fl) <= 0) {
65
pw_log_warn("control '%s' expects a number, ignoring", key);
66
- else
67
- set_control_value(node, key, &fl);
68
+ }
69
+ else if ((res = set_control_value(node, key, &fl)) < 0) {
70
+ pw_log_warn("control '%s' can not be set: %s", key, spa_strerror(res));
71
+ }
72
}
73
return 0;
74
}
75
pipewire-0.3.57.tar.gz/src/modules/module-filter-chain/lv2_plugin.c -> pipewire-0.3.58.tar.gz/src/modules/module-filter-chain/lv2_plugin.c
Changed
34
1
2
#include <pipewire/array.h>
3
4
#include <lilv/lilv.h>
5
-#include <lv2/lv2plug.in/ns/ext/atom/atom.h>
6
-#include <lv2/lv2plug.in/ns/ext/buf-size/buf-size.h>
7
-#include <lv2/lv2plug.in/ns/ext/worker/worker.h>
8
-#include <lv2/lv2plug.in/ns/ext/options/options.h>
9
-#include <lv2/lv2plug.in/ns/ext/parameters/parameters.h>
10
+
11
+#if defined __has_include
12
+# if __has_include (<lv2/atom/atom.h>)
13
+
14
+ #include <lv2/atom/atom.h>
15
+ #include <lv2/buf-size/buf-size.h>
16
+ #include <lv2/worker/worker.h>
17
+ #include <lv2/options/options.h>
18
+ #include <lv2/parameters/parameters.h>
19
+
20
+# else
21
+
22
+ #include <lv2/lv2plug.in/ns/ext/atom/atom.h>
23
+ #include <lv2/lv2plug.in/ns/ext/buf-size/buf-size.h>
24
+ #include <lv2/lv2plug.in/ns/ext/worker/worker.h>
25
+ #include <lv2/lv2plug.in/ns/ext/options/options.h>
26
+ #include <lv2/lv2plug.in/ns/ext/parameters/parameters.h>
27
+
28
+# endif
29
+
30
+#endif
31
32
#include "plugin.h"
33
34
pipewire-0.3.57.tar.gz/src/modules/module-loopback.c -> pipewire-0.3.58.tar.gz/src/modules/module-loopback.c
Changed
23
1
2
if (pw_properties_get(props, PW_KEY_NODE_VIRTUAL) == NULL)
3
pw_properties_set(props, PW_KEY_NODE_VIRTUAL, "true");
4
5
- if (pw_properties_get(props, PW_KEY_NODE_DESCRIPTION) == NULL)
6
- pw_properties_setf(props, PW_KEY_NODE_DESCRIPTION,
7
- "loopback-%u-%u", pid, id);
8
-
9
if ((str = pw_properties_get(props, "capture.props")) != NULL)
10
pw_properties_update_string(impl->capture_props, str, strlen(str));
11
if ((str = pw_properties_get(props, "playback.props")) != NULL)
12
13
if (pw_properties_get(impl->playback_props, PW_KEY_NODE_NAME) == NULL)
14
pw_properties_setf(impl->playback_props, PW_KEY_NODE_NAME,
15
"output.%s", str);
16
+ if (pw_properties_get(impl->capture_props, PW_KEY_NODE_DESCRIPTION) == NULL)
17
+ pw_properties_set(impl->capture_props, PW_KEY_NODE_DESCRIPTION, str);
18
+ if (pw_properties_get(impl->playback_props, PW_KEY_NODE_DESCRIPTION) == NULL)
19
+ pw_properties_set(impl->playback_props, PW_KEY_NODE_DESCRIPTION, str);
20
21
parse_audio_info(impl->capture_props, &impl->capture_info);
22
parse_audio_info(impl->playback_props, &impl->playback_info);
23
pipewire-0.3.57.tar.gz/src/modules/module-protocol-pulse/pulse-server.c -> pipewire-0.3.58.tar.gz/src/modules/module-protocol-pulse/pulse-server.c
Changed
194
1
2
#define DEFAULT_POSITION " FL FR "
3
4
#define MAX_FORMATS 32
5
+/* The max amount of data we send in one block when capturing. In PulseAudio this
6
+ * size is derived from the mempool PA_MEMPOOL_SLOT_SIZE */
7
+#define MAX_FRAGSIZE (64*1024)
8
9
#define TEMPORARY_MOVE_TIMEOUT (SPA_NSEC_PER_SEC)
10
11
12
return (uint32_t) u;
13
}
14
15
-static uint32_t fix_playback_buffer_attr(struct stream *s, struct buffer_attr *attr)
16
+static void clamp_latency(struct stream *s, struct spa_fraction *lat)
17
+{
18
+ if (lat->num * s->min_quantum.denom / lat->denom < s->min_quantum.num)
19
+ lat->num = (s->min_quantum.num * lat->denom +
20
+ (s->min_quantum.denom -1)) / s->min_quantum.denom;
21
+}
22
+
23
+static uint64_t fix_playback_buffer_attr(struct stream *s, struct buffer_attr *attr,
24
+ uint32_t rate, struct spa_fraction *lat)
25
{
26
uint32_t frame_size, max_prebuf, minreq, latency, max_latency;
27
struct defs *defs = &s->impl->defs;
28
29
30
attr->fragsize = 0;
31
32
- pw_log_info("%s maxlength:%u tlength:%u minreq:%u/%u prebuf:%u latency:%u %u",
33
+ lat->num = latency / frame_size;
34
+ lat->denom = rate;
35
+ clamp_latency(s, lat);
36
+
37
+ pw_log_info("%s maxlength:%u tlength:%u minreq:%u/%u prebuf:%u latency:%u/%u %u",
38
s->client->name, attr->maxlength, attr->tlength,
39
- attr->minreq, minreq, attr->prebuf, latency, frame_size);
40
+ attr->minreq, minreq, attr->prebuf, lat->num, lat->denom, frame_size);
41
42
- return latency / frame_size;
43
+ return lat->num * SPA_USEC_PER_SEC / lat->denom;
44
}
45
46
static uint64_t set_playback_buffer_attr(struct stream *s, struct buffer_attr *attr)
47
48
char attr_prebuf32;
49
char attr_minreq32;
50
51
- lat.denom = s->ss.rate;
52
- lat.num = fix_playback_buffer_attr(s, attr);
53
+ lat_usec = fix_playback_buffer_attr(s, attr, s->ss.rate, &lat);
54
55
s->attr = *attr;
56
57
- if (lat.num * s->min_quantum.denom / lat.denom < s->min_quantum.num)
58
- lat.num = (s->min_quantum.num * lat.denom +
59
- (s->min_quantum.denom -1)) / s->min_quantum.denom;
60
- lat_usec = lat.num * SPA_USEC_PER_SEC / lat.denom;
61
-
62
snprintf(latency, sizeof(latency), "%u/%u", lat.num, lat.denom);
63
snprintf(rate, sizeof(rate), "1/%u", lat.denom);
64
snprintf(attr_maxlength, sizeof(attr_maxlength), "%u", s->attr.maxlength);
65
66
return client_queue_message(client, reply);
67
}
68
69
-static uint32_t fix_record_buffer_attr(struct stream *s, struct buffer_attr *attr)
70
+static uint64_t fix_record_buffer_attr(struct stream *s, struct buffer_attr *attr,
71
+ uint32_t rate, struct spa_fraction *lat)
72
{
73
uint32_t frame_size, minfrag, latency;
74
75
76
if (frame_size == 0)
77
frame_size = 4;
78
79
- pw_log_info("%s maxlength:%u fragsize:%u",
80
- s->client->name, attr->maxlength, attr->fragsize);
81
+ pw_log_info("%s maxlength:%u fragsize:%u framesize:%u",
82
+ s->client->name, attr->maxlength, attr->fragsize,
83
+ frame_size);
84
85
if (attr->maxlength == (uint32_t) -1 || attr->maxlength > MAXLENGTH)
86
attr->maxlength = MAXLENGTH;
87
88
attr->fragsize = SPA_ROUND_UP(attr->fragsize, frame_size);
89
attr->fragsize = SPA_MAX(attr->fragsize, minfrag);
90
91
- /* pulseaudio configures the source to half of the fragsize. It also
92
- * immediately sends chunks to clients. Configure a 2/3 of the fragsize
93
- * as the latency. */
94
- latency = attr->fragsize * 2 / 3;
95
-
96
- if (s->adjust_latency)
97
- attr->fragsize = SPA_ROUND_UP(latency, frame_size);
98
-
99
- attr->tlength = attr->prebuf = 0;
100
+ attr->tlength = attr->minreq = attr->prebuf = 0;
101
102
/* make sure can queue at least to fragsize without overruns */
103
if (attr->maxlength < attr->fragsize * 4)
104
attr->maxlength = attr->fragsize * 4;
105
106
- pw_log_info("%s maxlength:%u fragsize:%u minfrag:%u latency:%u",
107
+ latency = attr->fragsize / frame_size;
108
+
109
+ lat->num = latency;
110
+ lat->denom = rate;
111
+ clamp_latency(s, lat);
112
+
113
+ pw_log_info("%s maxlength:%u fragsize:%u minfrag:%u latency:%u/%u",
114
s->client->name, attr->maxlength, attr->fragsize, minfrag,
115
- latency);
116
+ lat->num, lat->denom);
117
118
- return latency / frame_size;
119
+ return lat->num * SPA_USEC_PER_SEC / lat->denom;
120
}
121
122
static uint64_t set_record_buffer_attr(struct stream *s, struct buffer_attr *attr)
123
124
struct spa_fraction lat;
125
uint64_t lat_usec;
126
127
- lat.denom = s->ss.rate;
128
- lat.num = fix_record_buffer_attr(s, &s->attr);
129
+ lat_usec = fix_record_buffer_attr(s, attr, s->ss.rate, &lat);
130
131
- if (lat.num * s->min_quantum.denom / lat.denom < s->min_quantum.num)
132
- lat.num = (s->min_quantum.num * lat.denom +
133
- (s->min_quantum.denom -1)) / s->min_quantum.denom;
134
- lat_usec = lat.num * SPA_USEC_PER_SEC / lat.denom;
135
+ s->attr = *attr;
136
137
snprintf(latency, sizeof(latency), "%u/%u", lat.num, lat.denom);
138
snprintf(rate, sizeof(rate), "1/%u", lat.denom);
139
140
pw_log_trace("avail:%d index:%u", avail, index);
141
142
while ((uint32_t)avail >= stream->attr.fragsize) {
143
- towrite = SPA_MIN((uint32_t)avail, stream->attr.fragsize);
144
+ towrite = SPA_MIN(avail, MAX_FRAGSIZE);
145
+ towrite = SPA_ROUND_DOWN(towrite, stream->frame_size);
146
147
msg = message_alloc(impl, stream->channel, towrite);
148
if (msg == NULL)
149
150
stream->underrun_for = -1;
151
152
if (rate != 0) {
153
+ struct spa_fraction lat;
154
+ fix_playback_buffer_attr(stream, &attr, rate, &lat);
155
pw_properties_setf(props, PW_KEY_NODE_RATE, "1/%u", rate);
156
pw_properties_setf(props, PW_KEY_NODE_LATENCY, "%u/%u",
157
- fix_playback_buffer_attr(stream, &attr), rate);
158
+ lat.num, lat.denom);
159
}
160
if (no_remix)
161
pw_properties_set(props, PW_KEY_STREAM_DONT_REMIX, "true");
162
163
no_move = false;
164
165
if (rate != 0) {
166
+ struct spa_fraction lat;
167
+ fix_record_buffer_attr(stream, &attr, rate, &lat);
168
pw_properties_setf(props, PW_KEY_NODE_RATE, "1/%u", rate);
169
pw_properties_setf(props, PW_KEY_NODE_LATENCY, "%u/%u",
170
- fix_record_buffer_attr(stream, &attr), rate);
171
+ lat.num, lat.denom);
172
}
173
if (peak_detect)
174
pw_properties_set(props, PW_KEY_STREAM_MONITOR, "true");
175
176
break;
177
case COMMAND_TRIGGER_PLAYBACK_STREAM:
178
case COMMAND_PREBUF_PLAYBACK_STREAM:
179
+ if (stream->type != STREAM_TYPE_PLAYBACK)
180
+ return -ENOENT;
181
+ if (command == COMMAND_TRIGGER_PLAYBACK_STREAM)
182
+ stream->in_prebuf = false;
183
+ else if (stream->attr.prebuf > 0)
184
+ stream->in_prebuf = true;
185
+ stream_send_request(stream);
186
break;
187
default:
188
return -EINVAL;
189
}
190
-
191
return reply_simple_ack(client, tag);
192
}
193
194
pipewire-0.3.57.tar.gz/src/modules/module-protocol-pulse/server.c -> pipewire-0.3.58.tar.gz/src/modules/module-protocol-pulse/server.c
Changed
23
1
2
index += diff;
3
filled += diff;
4
stream->write_index += diff;
5
+ if ((flags & FLAG_SEEKMASK) == SEEK_RELATIVE)
6
+ stream->requested -= diff;
7
8
if (filled < 0) {
9
/* underrun, reported on reader side */
10
11
msg->data,
12
SPA_MIN(msg->length, MAXLENGTH));
13
index += msg->length;
14
- stream->write_index += msg->length;
15
spa_ringbuffer_write_update(&stream->ring, index);
16
- stream->requested -= SPA_MIN(msg->length, stream->requested);
17
+
18
+ stream->write_index += msg->length;
19
+ stream->requested -= msg->length;
20
21
stream_send_request(stream);
22
23
pipewire-0.3.57.tar.gz/src/modules/module-raop-sink.c -> pipewire-0.3.58.tar.gz/src/modules/module-raop-sink.c
Changed
102
1
2
*
3
* Creates a new Sink to stream to an Airplay device.
4
*
5
+ * Normally this sink is automatically created with \ref page_module_raop_discover
6
+ * with the right parameters but it is possible to manually create a RAOP sink
7
+ * as well.
8
+ *
9
* ## Module Options
10
*
11
+ * Options specific to the behavior of this module
12
+ *
13
+ * - `raop.hostname`: The hostname of the remote end.
14
+ * - `raop.port`: The port of the remote end.
15
+ * - `raop.transport`: The data transport to use, one of "udp" or "tcp". Defaults
16
+ * to "udp".
17
+ * - `raop.encryption.type`: The encryption type to use. One of "none", "RSA" or
18
+ * "auth_setup". Default is "none".
19
+ * - `raop.audio.codec`: The audio codec to use. Needs to be "PCM". Defaults to "PCM".
20
+ * - `raop.password`: The password to use.
21
+ * - `stream.props = {}`: properties to be passed to the sink stream
22
+ *
23
+ * Options with well-known behavior.
24
+ *
25
+ * - \ref PW_KEY_REMOTE_NAME
26
+ * - \ref PW_KEY_AUDIO_FORMAT
27
+ * - \ref PW_KEY_AUDIO_RATE
28
+ * - \ref PW_KEY_AUDIO_CHANNELS
29
+ * - \ref SPA_KEY_AUDIO_POSITION
30
+ * - \ref PW_KEY_NODE_NAME
31
+ * - \ref PW_KEY_NODE_DESCRIPTION
32
+ * - \ref PW_KEY_NODE_GROUP
33
+ * - \ref PW_KEY_NODE_LATENCY
34
+ * - \ref PW_KEY_NODE_VIRTUAL
35
+ * - \ref PW_KEY_MEDIA_CLASS
36
+ *
37
* ## Example configuration
38
*
39
+ *\code{.unparsed}
40
+ * context.modules =
41
+ * { name = libpipewire-module-raop-sink
42
+ * args = {
43
+ * # Set the remote address to tunnel to
44
+ * raop.hostname = "my-raop-device"
45
+ * raop.port = 8190
46
+ * #raop.transport = "udp"
47
+ * raop.encryption = "RSA"
48
+ * #raop.audio.codec = "PCM"
49
+ * #raop.password = "****"
50
+ * #audio.format = "S16"
51
+ * #audio.rate = 44100
52
+ * #audio.channels = 22
53
+ * #audio.position = FL FR
54
+ * stream.props = {
55
+ * # extra sink properties
56
+ * }
57
+ * }
58
+ * }
59
+ *
60
+ *\endcode
61
+ *
62
* ## See also
63
*
64
* \ref page_module_raop_discover
65
66
67
#define DEFAULT_LATENCY (DEFAULT_RATE*2)
68
69
-#define MODULE_USAGE " node.latency=<latency as fraction> " \
70
+#define MODULE_USAGE " raop.hostname=<name of host> " \
71
+ " raop.port=<remote port> " \
72
+ " raop.transport=<transport, default:udp> " \
73
+ " raop.encryption.type=<encryption, default:none> " \
74
+ " raop.audio.codec=PCM " \
75
+ " raop.password=<password for auth> " \
76
+ " node.latency=<latency as fraction> " \
77
" node.name=<name of the nodes> " \
78
" node.description=<description of the nodes> " \
79
" audio.format=<format, default:"DEFAULT_FORMAT"> " \
80
81
82
static int rtsp_do_auth_setup(struct impl *impl)
83
{
84
- int res;
85
-
86
- char output =
87
+ static const unsigned char content33 =
88
"\x01"
89
"\x59\x02\xed\xe9\x0d\x4e\xf2\xbd\x4c\xb6\x8a\x63\x30\x03\x82\x07"
90
"\xa9\x4d\xbd\x50\xd8\xaa\x46\x5b\x5d\x8c\x01\x2a\x0c\x7e\x1d\x4e";
91
92
- res = pw_rtsp_client_url_send(impl->rtsp, "/auth-setup", "POST", &impl->headers->dict,
93
- "application/octet-stream", output, rtsp_auth_setup_reply, impl);
94
-
95
- return res;
96
+ return pw_rtsp_client_url_send(impl->rtsp, "/auth-setup", "POST", &impl->headers->dict,
97
+ "application/octet-stream", content, sizeof(content),
98
+ rtsp_auth_setup_reply, impl);
99
}
100
101
static const char *find_attr(char **tokens, const char *key)
102
pipewire-0.3.57.tar.gz/src/modules/module-raop/rtsp-client.c -> pipewire-0.3.58.tar.gz/src/modules/module-raop/rtsp-client.c
Changed
201
1
2
void *data;
3
size_t len;
4
size_t offset;
5
- int cseq;
6
+ uint32_t cseq;
7
void (*reply) (void *user_data, int status, const struct spa_dict *headers);
8
void *user_data;
9
};
10
11
+enum client_recv_state {
12
+ CLIENT_RECV_NONE,
13
+ CLIENT_RECV_STATUS,
14
+ CLIENT_RECV_HEADERS,
15
+ CLIENT_RECV_CONTENT,
16
+};
17
+
18
struct pw_rtsp_client {
19
struct pw_loop *loop;
20
struct pw_properties *props;
21
22
struct spa_source *source;
23
unsigned int connecting:1;
24
unsigned int need_flush:1;
25
- unsigned int wait_status:1;
26
27
+ enum client_recv_state recv_state;
28
int status;
29
char line_buf1024;
30
size_t line_pos;
31
struct pw_properties *headers;
32
+ size_t content_length;
33
34
- char *session;
35
- int cseq;
36
+ uint32_t cseq;
37
38
struct spa_list messages;
39
struct spa_list pending;
40
41
spa_list_init(&client->pending);
42
spa_hook_list_init(&client->listener_list);
43
client->headers = pw_properties_new(NULL, NULL);
44
+ client->recv_state = CLIENT_RECV_NONE;
45
46
pw_log_info("new client %p", client);
47
48
49
if (ip)
50
inet_ntop(client->local_addr.sa.sa_family,
51
&client->local_addr.in.sin_addr, ip, len);
52
- } else if (client->local_addr.sa.sa_family == AF_INET6) {
53
+ } else if (client->local_addr.sa.sa_family == AF_INET6) {
54
*version = 6;
55
if (ip)
56
inet_ntop(client->local_addr.sa.sa_family,
57
58
{
59
int res, ip_version;
60
socklen_t len;
61
- char local_ipINET6_ADDRSTRLEN;
62
+ char local_ipINET6_ADDRSTRLEN;
63
64
len = sizeof(res);
65
if (getsockopt(fd, SOL_SOCKET, SO_ERROR, &res, &len) < 0) {
66
67
68
if (ip_version == 4)
69
asprintf(&client->url, "rtsp://%s/%s", local_ip, client->session_id);
70
- else
71
+ else
72
asprintf(&client->url, "rtsp://%s/%s", local_ip, client->session_id);
73
74
pw_log_info("connected local ip %s", local_ip);
75
76
client->connecting = false;
77
- client->wait_status = true;
78
+
79
+ client->recv_state = CLIENT_RECV_STATUS;
80
+ pw_properties_clear(client->headers);
81
+ client->status = 0;
82
+ client->line_pos = 0;
83
+ client->content_length = 0;
84
+
85
pw_rtsp_client_emit_connected(client);
86
87
return 0;
88
89
return 0;
90
}
91
92
-static struct message *find_pending(struct pw_rtsp_client *client, int cseq)
93
+static struct message *find_pending(struct pw_rtsp_client *client, uint32_t cseq)
94
{
95
struct message *msg;
96
spa_list_for_each(msg, &client->pending, link) {
97
98
return NULL;
99
}
100
101
-static int process_input(struct pw_rtsp_client *client)
102
+static int process_status(struct pw_rtsp_client *client, char *buf)
103
{
104
- char *buf = NULL;
105
- int res;
106
+ const char *state = NULL, *s;
107
+ size_t len;
108
109
- if ((res = read_line(client, &buf)) <= 0)
110
- return res;
111
+ pw_log_info("status: %s", buf);
112
113
- pw_log_debug("%s", buf);
114
+ s = pw_split_walk(buf, " ", &len, &state);
115
+ if (!spa_strstartswith(s, "RTSP/"))
116
+ return -EPROTO;
117
118
- if (client->wait_status) {
119
- const char *state = NULL, *s;
120
- size_t len;
121
+ s = pw_split_walk(buf, " ", &len, &state);
122
+ if (s == NULL)
123
+ return -EPROTO;
124
125
- pw_log_info("status: %s", buf);
126
+ client->status = atoi(s);
127
+ if (client->status == 0)
128
+ return -EPROTO;
129
130
- s = pw_split_walk(buf, " ", &len, &state);
131
- if (!spa_strstartswith(s, "RTSP/"))
132
- goto error;
133
+ s = pw_split_walk(buf, " ", &len, &state);
134
+ if (s == NULL)
135
+ return -EPROTO;
136
137
- s = pw_split_walk(buf, " ", &len, &state);
138
- if (s == NULL)
139
- goto error;
140
+ pw_properties_clear(client->headers);
141
+ client->recv_state = CLIENT_RECV_HEADERS;
142
143
- client->status = atoi(s);
144
+ return 0;
145
+}
146
147
- s = pw_split_walk(buf, " ", &len, &state);
148
- if (s == NULL)
149
- goto error;
150
+static void dispatch_handler(struct pw_rtsp_client *client)
151
+{
152
+ uint32_t cseq;
153
+ if (pw_properties_fetch_uint32(client->headers, "CSeq", &cseq) < 0)
154
+ return;
155
156
- client->wait_status = false;
157
- pw_properties_clear(client->headers);
158
- } else {
159
- if (strlen(buf) == 0) {
160
- int cseq;
161
- struct message *msg;
162
- const struct spa_dict_item *it;
163
- const char *content_type;
164
- unsigned int content_length;
165
-
166
- spa_dict_for_each(it, &client->headers->dict)
167
- pw_log_info(" %s: %s", it->key, it->value);
168
-
169
- cseq = pw_properties_get_int32(client->headers, "CSeq", 0);
170
- content_type = pw_properties_get(client->headers, "Content-Type");
171
- if (content_type != NULL && strcmp(content_type, "application/octet-stream") == 0) {
172
- pw_log_info("binary response received");
173
- content_length = pw_properties_get_uint64(client->headers, "Content-Length", 0);
174
- char content_bufcontent_length;
175
- res = read(client->source->fd, content_buf, content_length);
176
- pw_log_debug("read %d bytes", res);
177
- if (res == 0)
178
- return -EPIPE;
179
- if (res < 0) {
180
- res = -errno;
181
- if (res != -EAGAIN && res != -EWOULDBLOCK)
182
- return res;
183
- return 0;
184
- }
185
- pw_properties_set(client->headers, "body", content_buf);
186
- }
187
- if ((msg = find_pending(client, cseq)) != NULL) {
188
- msg->reply(msg->user_data, client->status, &client->headers->dict);
189
- spa_list_remove(&msg->link);
190
- free(msg);
191
- } else {
192
- pw_rtsp_client_emit_message(client, client->status,
193
- &client->headers->dict);
194
- }
195
- client->wait_status = true;
196
- } else {
197
- char *key, *value;
198
+ pw_log_info("received reply to request with cseq:%" PRIu32, cseq);
199
200
- key = buf;
201
pipewire-0.3.57.tar.gz/src/modules/module-raop/rtsp-client.h -> pipewire-0.3.58.tar.gz/src/modules/module-raop/rtsp-client.h
Changed
10
1
2
3
int pw_rtsp_client_url_send(struct pw_rtsp_client *client, const char *url,
4
const char *cmd, const struct spa_dict *headers,
5
- const char *content_type, const char *content,
6
+ const char *content_type, const void *content, size_t content_length,
7
void (*reply) (void *user_data, int status, const struct spa_dict *headers),
8
void *user_data);
9
10
pipewire-0.3.57.tar.gz/src/modules/module-rt.c -> pipewire-0.3.58.tar.gz/src/modules/module-rt.c
Changed
17
1
2
if (set_nice(impl, impl->nice_level, !can_use_rtkit) < 0)
3
use_rtkit = can_use_rtkit;
4
}
5
- set_rlimit(impl);
6
7
#ifdef HAVE_DBUS
8
impl->use_rtkit = use_rtkit;
9
10
set_nice(impl, impl->nice_level, true);
11
}
12
#endif
13
+ set_rlimit(impl);
14
15
impl->thread_utils.iface = SPA_INTERFACE_INIT(
16
SPA_TYPE_INTERFACE_ThreadUtils,
17
pipewire-0.3.57.tar.gz/src/pipewire/impl-link.c -> pipewire-0.3.58.tar.gz/src/pipewire/impl-link.c
Changed
10
1
2
pw_log_debug("%p: activate activated:%d state:%s", this, impl->activated,
3
pw_link_state_as_string(this->info.state));
4
5
- if (impl->activated || !this->prepared || !impl->inode->active || !impl->onode->active)
6
+ if (impl->activated || !this->prepared || !impl->inode->added || !impl->onode->active)
7
return 0;
8
9
if (!impl->io_set) {
10
pipewire-0.3.57.tar.gz/src/pipewire/impl-node.c -> pipewire-0.3.58.tar.gz/src/pipewire/impl-node.c
Changed
86
1
2
spa_loop_remove_source(loop, &this->source);
3
remove_node(this);
4
}
5
+ this->added = false;
6
return 0;
7
}
8
9
10
return res;
11
}
12
13
-static void node_activate(struct pw_impl_node *this)
14
+static void node_activate_outputs(struct pw_impl_node *this)
15
{
16
struct pw_impl_port *port;
17
18
pw_log_debug("%p: activate", this);
19
- spa_list_for_each(port, &this->input_ports, link) {
20
+ spa_list_for_each(port, &this->output_ports, link) {
21
struct pw_impl_link *link;
22
- spa_list_for_each(link, &port->links, input_link)
23
+ spa_list_for_each(link, &port->links, output_link)
24
pw_impl_link_activate(link);
25
}
26
- spa_list_for_each(port, &this->output_ports, link) {
27
+}
28
+
29
+static void node_activate_inputs(struct pw_impl_node *this)
30
+{
31
+ struct pw_impl_port *port;
32
+
33
+ pw_log_debug("%p: activate", this);
34
+ spa_list_for_each(port, &this->input_ports, link) {
35
struct pw_impl_link *link;
36
- spa_list_for_each(link, &port->links, output_link)
37
+ spa_list_for_each(link, &port->links, input_link)
38
pw_impl_link_activate(link);
39
}
40
}
41
42
struct impl *impl = SPA_CONTAINER_OF(this, struct impl, this);
43
int res = 0;
44
45
- node_activate(this);
46
+ /* First activate the outputs so that when the node starts pushing,
47
+ * we can process the outputs */
48
+ node_activate_outputs(this);
49
50
if (impl->pending_state >= PW_NODE_STATE_RUNNING)
51
return 0;
52
53
spa_loop_add_source(loop, &this->source);
54
add_node(this, driver);
55
}
56
+ this->added = true;
57
return 0;
58
}
59
60
61
error = spa_aprintf("Start error: %s", spa_strerror(res));
62
}
63
}
64
- if (res >= 0)
65
+ if (res >= 0) {
66
pw_loop_invoke(node->data_loop, do_node_add, 1, NULL, 0, true, node);
67
+ /* now activate the inputs */
68
+ node_activate_inputs(node);
69
+ }
70
break;
71
default:
72
break;
73
74
a->status = PW_NODE_ACTIVATION_AWAKE;
75
a->awake_time = SPA_TIMESPEC_TO_NSEC(&ts);
76
77
+ if (!this->added) {
78
+ /* This should not happen here. We activate the input
79
+ * links after we add the node to the graph. */
80
+ pw_log_warn("%p: scheduling non-active node", this);
81
+ return -EIO;
82
+ }
83
pw_log_trace_fp("%p: process %"PRIu64, this, a->awake_time);
84
85
/* when transport sync is not supported, just clear the flag */
86
pipewire-0.3.57.tar.gz/src/pipewire/private.h -> pipewire-0.3.58.tar.gz/src/pipewire/private.h
Changed
9
1
2
unsigned int transport_sync:1; /**< supports transport sync */
3
unsigned int current_pending:1; /**< a quantum/rate update is pending */
4
unsigned int moved:1; /**< the node was moved drivers */
5
+ unsigned int added:1; /**< the node was add to graph */
6
7
uint32_t port_user_data_size; /**< extra size for port user data */
8
9
pipewire-0.3.57.tar.gz/src/pipewire/stream.c -> pipewire-0.3.58.tar.gz/src/pipewire/stream.c
Changed
125
1
2
uint32_t port_change_mask_all;
3
struct spa_port_info port_info;
4
struct pw_properties *port_props;
5
-#define IDX_EnumFormat 0
6
-#define IDX_Meta 1
7
-#define IDX_IO 2
8
-#define IDX_Format 3
9
-#define IDX_Buffers 4
10
-#define IDX_Latency 5
11
+#define PORT_EnumFormat 0
12
+#define PORT_Meta 1
13
+#define PORT_IO 2
14
+#define PORT_Format 3
15
+#define PORT_Buffers 4
16
+#define PORT_Latency 5
17
#define N_PORT_PARAMS 6
18
struct spa_param_info port_paramsN_PORT_PARAMS;
19
20
21
22
uint32_t change_mask_all;
23
struct spa_node_info info;
24
-#define IDX_PropInfo 0
25
-#define IDX_Props 1
26
-#define N_NODE_PARAMS 2
27
+#define NODE_PropInfo 0
28
+#define NODE_Props 1
29
+#define NODE_EnumFormat 2
30
+#define NODE_Format 3
31
+#define N_NODE_PARAMS 4
32
struct spa_param_info paramsN_NODE_PARAMS;
33
34
uint32_t media_type;
35
36
{
37
switch (id) {
38
case SPA_PARAM_PropInfo:
39
- return IDX_PropInfo;
40
+ return NODE_PropInfo;
41
case SPA_PARAM_Props:
42
- return IDX_Props;
43
+ return NODE_Props;
44
+ case SPA_PARAM_EnumFormat:
45
+ return NODE_EnumFormat;
46
+ case SPA_PARAM_Format:
47
+ return NODE_Format;
48
default:
49
return -1;
50
}
51
52
{
53
switch (id) {
54
case SPA_PARAM_EnumFormat:
55
- return IDX_EnumFormat;
56
+ return PORT_EnumFormat;
57
case SPA_PARAM_Meta:
58
- return IDX_Meta;
59
+ return PORT_Meta;
60
case SPA_PARAM_IO:
61
- return IDX_IO;
62
+ return PORT_IO;
63
case SPA_PARAM_Format:
64
- return IDX_Format;
65
+ return PORT_Format;
66
case SPA_PARAM_Buffers:
67
- return IDX_Buffers;
68
+ return PORT_Buffers;
69
case SPA_PARAM_Latency:
70
- return IDX_Latency;
71
+ return PORT_Latency;
72
default:
73
return -1;
74
}
75
76
impl->info.change_mask |= SPA_NODE_CHANGE_MASK_PARAMS;
77
impl->paramsidx.flags |= SPA_PARAM_INFO_READ;
78
impl->paramsidx.user++;
79
- } else if ((idx = get_port_param_index(id)) != -1) {
80
+ }
81
+ if ((idx = get_port_param_index(id)) != -1) {
82
impl->port_info.change_mask |= SPA_PORT_CHANGE_MASK_PARAMS;
83
impl->port_paramsidx.flags |= SPA_PARAM_INFO_READ;
84
impl->port_paramsidx.user++;
85
86
if (stream->state == PW_STREAM_STATE_ERROR)
87
return -EIO;
88
89
+ emit_node_info(impl, false);
90
emit_port_info(impl, false);
91
92
return 0;
93
94
if (!impl->process_rt)
95
impl->info.flags |= SPA_NODE_FLAG_ASYNC;
96
impl->info.props = &stream->properties->dict;
97
- impl->paramsIDX_PropInfo = SPA_PARAM_INFO(SPA_PARAM_PropInfo, 0);
98
- impl->paramsIDX_Props = SPA_PARAM_INFO(SPA_PARAM_Props, SPA_PARAM_INFO_WRITE);
99
+ impl->paramsNODE_PropInfo = SPA_PARAM_INFO(SPA_PARAM_PropInfo, 0);
100
+ impl->paramsNODE_Props = SPA_PARAM_INFO(SPA_PARAM_Props, SPA_PARAM_INFO_WRITE);
101
+ impl->paramsNODE_EnumFormat = SPA_PARAM_INFO(SPA_PARAM_EnumFormat, 0);
102
+ impl->paramsNODE_Format = SPA_PARAM_INFO(SPA_PARAM_Format, SPA_PARAM_INFO_WRITE);
103
impl->info.params = impl->params;
104
impl->info.n_params = N_NODE_PARAMS;
105
impl->info.change_mask = impl->change_mask_all;
106
107
impl->port_info.flags = 0;
108
if (SPA_FLAG_IS_SET(flags, PW_STREAM_FLAG_ALLOC_BUFFERS))
109
impl->port_info.flags |= SPA_PORT_FLAG_CAN_ALLOC_BUFFERS;
110
- impl->port_paramsIDX_EnumFormat = SPA_PARAM_INFO(SPA_PARAM_EnumFormat, 0);
111
- impl->port_paramsIDX_Meta = SPA_PARAM_INFO(SPA_PARAM_Meta, 0);
112
- impl->port_paramsIDX_IO = SPA_PARAM_INFO(SPA_PARAM_IO, 0);
113
- impl->port_paramsIDX_Format = SPA_PARAM_INFO(SPA_PARAM_Format, SPA_PARAM_INFO_WRITE);
114
- impl->port_paramsIDX_Buffers = SPA_PARAM_INFO(SPA_PARAM_Buffers, 0);
115
- impl->port_paramsIDX_Latency = SPA_PARAM_INFO(SPA_PARAM_Latency, SPA_PARAM_INFO_WRITE);
116
+ impl->port_paramsPORT_EnumFormat = SPA_PARAM_INFO(SPA_PARAM_EnumFormat, 0);
117
+ impl->port_paramsPORT_Meta = SPA_PARAM_INFO(SPA_PARAM_Meta, 0);
118
+ impl->port_paramsPORT_IO = SPA_PARAM_INFO(SPA_PARAM_IO, 0);
119
+ impl->port_paramsPORT_Format = SPA_PARAM_INFO(SPA_PARAM_Format, SPA_PARAM_INFO_WRITE);
120
+ impl->port_paramsPORT_Buffers = SPA_PARAM_INFO(SPA_PARAM_Buffers, 0);
121
+ impl->port_paramsPORT_Latency = SPA_PARAM_INFO(SPA_PARAM_Latency, SPA_PARAM_INFO_WRITE);
122
impl->port_info.props = &impl->port_props->dict;
123
impl->port_info.params = impl->port_params;
124
impl->port_info.n_params = N_PORT_PARAMS;
125
pipewire-0.3.57.tar.gz/src/tools/pw-top.c -> pipewire-0.3.58.tar.gz/src/tools/pw-top.c
Changed
201
1
2
#include <spa/utils/string.h>
3
#include <spa/pod/parser.h>
4
#include <spa/debug/pod.h>
5
+#include <spa/param/format-utils.h>
6
+#include <spa/param/audio/format-utils.h>
7
+#include <spa/param/video/format-utils.h>
8
9
#include <pipewire/impl.h>
10
#include <pipewire/extensions/profiler.h>
11
12
+#define MAX_FORMAT 16
13
#define MAX_NAME 128
14
15
struct driver {
16
17
struct node {
18
struct spa_list link;
19
uint32_t id;
20
- char nameMAX_NAME;
21
+ char nameMAX_NAME+1;
22
struct measurement measurement;
23
struct driver info;
24
struct node *driver;
25
uint32_t errors;
26
int32_t last_error_status;
27
uint32_t generation;
28
+ char formatMAX_FORMAT+1;
29
+ struct pw_proxy *proxy;
30
+ struct spa_hook proxy_listener;
31
+ struct spa_hook object_listener;
32
};
33
34
struct data {
35
36
return NULL;
37
}
38
39
+static void on_node_removed(void *data)
40
+{
41
+ struct node *n = data;
42
+ pw_proxy_destroy(n->proxy);
43
+}
44
+
45
+static void on_node_destroy(void *data)
46
+{
47
+ struct node *n = data;
48
+ n->proxy = NULL;
49
+ spa_hook_remove(&n->proxy_listener);
50
+ spa_hook_remove(&n->object_listener);
51
+}
52
+
53
+static const struct pw_proxy_events proxy_events = {
54
+ PW_VERSION_PROXY_EVENTS,
55
+ .removed = on_node_removed,
56
+ .destroy = on_node_destroy,
57
+};
58
+
59
+static void node_param(void *data, int seq,
60
+ uint32_t id, uint32_t index, uint32_t next,
61
+ const struct spa_pod *param)
62
+{
63
+ struct node *n = data;
64
+
65
+ switch (id) {
66
+ case SPA_PARAM_Format:
67
+ {
68
+ uint32_t media_type, media_subtype;
69
+
70
+ spa_format_parse(param, &media_type, &media_subtype);
71
+
72
+ switch(media_type) {
73
+ case SPA_MEDIA_TYPE_audio:
74
+ switch(media_subtype) {
75
+ case SPA_MEDIA_SUBTYPE_raw:
76
+ {
77
+ struct spa_audio_info_raw info;
78
+ if (spa_format_audio_raw_parse(param, &info) >= 0) {
79
+ snprintf(n->format, sizeof(n->format), "%6.6s %d %d",
80
+ spa_debug_type_find_short_name(spa_type_audio_format, info.format),
81
+ info.channels, info.rate);
82
+ }
83
+ break;
84
+ }
85
+ case SPA_MEDIA_SUBTYPE_dsd:
86
+ {
87
+ struct spa_audio_info_dsd info;
88
+ if (spa_format_audio_dsd_parse(param, &info) >= 0) {
89
+ snprintf(n->format, sizeof(n->format), "DSD%d %d ",
90
+ 8 * info.rate / 44100, info.channels);
91
+
92
+ }
93
+ break;
94
+ }
95
+ }
96
+ break;
97
+ case SPA_MEDIA_TYPE_video:
98
+ switch(media_subtype) {
99
+ case SPA_MEDIA_SUBTYPE_raw:
100
+ {
101
+ struct spa_video_info_raw info;
102
+ if (spa_format_video_raw_parse(param, &info) >= 0) {
103
+ snprintf(n->format, sizeof(n->format), "%6.6s %dx%d",
104
+ spa_debug_type_find_short_name(spa_type_video_format, info.format),
105
+ info.size.width, info.size.height);
106
+ }
107
+ break;
108
+ }
109
+ }
110
+ break;
111
+ case SPA_MEDIA_TYPE_application:
112
+ switch(media_subtype) {
113
+ case SPA_MEDIA_SUBTYPE_control:
114
+ snprintf(n->format, sizeof(n->format), "%s", "CONTROL");
115
+ break;
116
+ }
117
+ break;
118
+ }
119
+ break;
120
+ }
121
+ default:
122
+ break;
123
+ }
124
+}
125
+
126
+static const struct pw_node_events node_events = {
127
+ PW_VERSION_NODE,
128
+ .param = node_param,
129
+};
130
+
131
static struct node *add_node(struct data *d, uint32_t id, const char *name)
132
{
133
struct node *n;
134
135
return NULL;
136
137
if (name)
138
- strncpy(n->name, name, MAX_NAME-1);
139
+ strncpy(n->name, name, MAX_NAME);
140
else
141
snprintf(n->name, sizeof(n->name), "%u", id);
142
n->id = id;
143
n->driver = n;
144
+ n->proxy = pw_registry_bind(d->registry, id, PW_TYPE_INTERFACE_Node, PW_VERSION_NODE, 0);
145
+ if (n->proxy) {
146
+ uint32_t ids1 = { SPA_PARAM_Format };
147
+
148
+ pw_proxy_add_listener(n->proxy,
149
+ &n->proxy_listener, &proxy_events, n);
150
+ pw_proxy_add_object_listener(n->proxy,
151
+ &n->object_listener, &node_events, n);
152
+
153
+ pw_node_subscribe_params((struct pw_node*)n->proxy,
154
+ ids, 1);
155
+ }
156
spa_list_append(&d->node_list, &n->link);
157
d->n_nodes++;
158
159
160
161
static void remove_node(struct data *d, struct node *n)
162
{
163
+ if (n->proxy)
164
+ pw_proxy_destroy(n->proxy);
165
spa_list_remove(&n->link);
166
d->n_nodes--;
167
free(n);
168
169
else if (val == (uint64_t)-2)
170
snprintf(buf, len, " +++ ");
171
else if (val < 1000000llu)
172
- snprintf(buf, len, "%5.1fµs", val/1000.f);
173
+ snprintf(buf, len, "%5.1fus", val/1000.f);
174
else if (val < 1000000000llu)
175
snprintf(buf, len, "%5.1fms", val/1000000.f);
176
else
177
178
else
179
busy = -1;
180
181
- mvwprintw(d->win, y, 0, "%s %4.1u %6.1u %6.1u %s %s %s %s %3.1u %s%s",
182
+ mvwprintw(d->win, y, 0, "%s %4.1u %6.1u %6.1u %s %s %s %s %3.1u %16.16s %s%s",
183
n->measurement.status != 3 ? "!" : " ",
184
n->id,
185
frac.num, frac.denom,
186
187
print_perc(buf3, 64, waiting, quantum),
188
print_perc(buf4, 64, busy, quantum),
189
i->xrun_count + n->errors,
190
+ n->measurement.status != 3 ? "" : n->format,
191
n->driver == n ? "" : " + ",
192
n->name);
193
}
194
195
196
wclear(d->win);
197
wattron(d->win, A_REVERSE);
198
- wprintw(d->win, "%-*.*s", COLS, COLS, "S ID QUANT RATE WAIT BUSY W/Q B/Q ERR NAME ");
199
+ wprintw(d->win, "%-*.*s", COLS, COLS, "S ID QUANT RATE WAIT BUSY W/Q B/Q ERR FORMAT NAME ");
200
wattroff(d->win, A_REVERSE);
201