Changes of Revision 18

pipewire-aptx.changes Changed
x
 
1
@@ -1,4 +1,9 @@
2
 -------------------------------------------------------------------
3
+Sat Dec  3 00:09:52 UTC 2022 - Bjørn Lie <zaitor@opensuse.org>
4
+
5
+- Update to version 0.3.61
6
+
7
+-------------------------------------------------------------------
8
 Mon Nov 21 11:36:55 UTC 2022 - Bjørn Lie <zaitor@opensuse.org>
9
 
10
 - Update to version 0.3.60
11
pipewire-aptx.spec Changed
10
 
1
@@ -7,7 +7,7 @@
2
 %define soversion 0_2
3
 
4
 Name:           pipewire-aptx
5
-Version:        0.3.60
6
+Version:        0.3.61
7
 Release:        0
8
 Summary:        PipeWire Bluetooth aptX codec plugin
9
 License:        MIT
10
pipewire-0.3.60.tar.gz/NEWS -> pipewire-0.3.61.tar.gz/NEWS Changed
85
 
1
@@ -1,3 +1,73 @@
2
+# PipeWire 0.3.61 (2022-11-24)
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 bug in audioadapter that could cause crashes when switching
9
+    bluetooth profiles.
10
+  - Fix sound in QEMU, deadbeef and openal again.
11
+  - libcamera plugin fixes, dynamic add and remove should now work with
12
+    the next wireplumber version.
13
+  - Fix a regression in pw-midiplay where the first buffer would not
14
+    play and some events would be missing.
15
+  - The network module now doesn't export other network sources
16
+    anymore.
17
+  - pulse-server now detects clients that keep underrunning for a long time
18
+    and will pause them to save power.
19
+  - Many more bugfixes and improvements.
20
+
21
+
22
+## PipeWire
23
+  - Optimize away some useless graph recalculations.
24
+  - Increase alternative sample rates from 16 to 32.
25
+  - FreeBSD and musl build fixes.
26
+  - Silence some module loading errors when the error can be ignored.
27
+  - Fix initial buffer requested size for pw-stream when operating in
28
+    async mode. This also indirectly fixes the first buffer in
29
+    pw-midiplay. (#2843)
30
+
31
+## Modules
32
+  - Set the network property on pulse-tunnel streams so that they are
33
+    not exported anymore. (#2384)
34
+  - Filter-chain has optimized mix functions now.
35
+
36
+## SPA
37
+  - Handle some errors in libcamera better.
38
+  - Fix libcamera remove events. Fix the id allocation for devices.
39
+  - Fix a bug in audioadapter where it would not renegotiate after
40
+    a port reconfiguration, leading to crashes, especially when
41
+    automatically switching profiles in bluetooth. (#2764)
42
+  - Do ALSA probing in 44100Hz again. Some devices seem to fail
43
+    otherwise for some unknown reason. (#2718)
44
+  - Force playback start when the ALSA buffer is full. This fixes sound
45
+    in QEMU. (#2830)
46
+  - Support Digital 5.1 AC3 for Asus Xonar SE.
47
+  - Improve format renegotiation in audioadapter. This makes the ALSA
48
+    plugin work again for deadbeef. (#2832)
49
+  - Fix latency reporting on adapter DSP ports.
50
+
51
+## pulse-server
52
+  - Fix a bug where openal based applications would hang. (#2821)
53
+  - Improve zeroconf publish. Only publish on the address of the first
54
+    running server. This avoids duplicate entries for IPv4 and IPv6.
55
+    Add support for republish entries when new servers are started.
56
+  - Add a pulse.idle.timeout option (default to 5 seconds) to pause
57
+    streams that have been underrunning for this amount of time. Badly
58
+    behaving clients will then not keep the graph and device busy so
59
+    that devices can be suspended to save battery. This should give
60
+    better default behaviour with speech-dispatcher. (#2839)
61
+
62
+## JACK
63
+  - Add an option to configure the filter character.
64
+  - Fix connect_callbacks. It was only called once for output ports.
65
+    (#2841)
66
+  - Add option to set node.passive on jack clients. Make some quirks
67
+    for qsynth to make it suspend and fade out better.
68
+
69
+
70
+Older versions:
71
+
72
 # PipeWire 0.3.60 (2022-11-10)
73
 
74
 This is a bugfix release that is API and ABI compatible with previous
75
@@ -143,9 +213,6 @@
76
   - jack_port_register() and jack_port_unregister() can be called on an
77
     active client so make this thread safe. (#2652)
78
 
79
-
80
-Older versions:
81
-
82
 # PipeWire 0.3.59 (2022-09-30)
83
 
84
 This is a bugfix release that is API and ABI compatible with previous
85
pipewire-0.3.60.tar.gz/meson.build -> pipewire-0.3.61.tar.gz/meson.build Changed
8
 
1
@@ -1,5 +1,5 @@
2
 project('pipewire', 'c' ,
3
-  version : '0.3.60',
4
+  version : '0.3.61',
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.60.tar.gz/pipewire-jack/src/pipewire-jack.c -> pipewire-0.3.61.tar.gz/pipewire-jack/src/pipewire-jack.c Changed
79
 
1
@@ -404,6 +404,7 @@
2
    int rt_max;
3
    unsigned int fix_midi_events:1;
4
    unsigned int global_buffer_size:1;
5
+   char filter_char;
6
 
7
    jack_position_t jack_position;
8
    jack_transport_state_t jack_state;
9
@@ -2483,7 +2484,7 @@
10
        else
11
            mix->peer_port = l->port_link.our_input;
12
 
13
-       pw_log_info("peer port %p %p %p", mix->peer_port,
14
+       pw_log_debug("peer port %p %p %p", mix->peer_port,
15
                l->port_link.our_output, l->port_link.our_input);
16
 
17
        if (!l->port_link.is_complete) {
18
@@ -2793,12 +2794,12 @@
19
 #define FILTER_NAME    " ().:*$"
20
 #define FILTER_PORT    " ().*$"
21
 
22
-static void filter_name(char *str, const char *filter)
23
+static void filter_name(char *str, const char *filter, char filter_char)
24
 {
25
    char *p;
26
    for (p = str; *p; p++) {
27
        if (strchr(filter, *p) != NULL)
28
-           *p = ' ';
29
+           *p = filter_char;
30
    }
31
 }
32
 
33
@@ -2863,7 +2864,7 @@
34
            snprintf(tmp, sizeof(tmp), "%s", str);
35
 
36
        if (c->filter_name)
37
-           filter_name(tmp, FILTER_NAME);
38
+           filter_name(tmp, FILTER_NAME, c->filter_char);
39
 
40
        ot = find_node(c, tmp);
41
        if (ot != NULL && o->node.client_id != ot->node.client_id) {
42
@@ -2980,7 +2981,7 @@
43
                snprintf(tmp, sizeof(tmp), "%s:%s", ot->node.name, str);
44
 
45
            if (c->filter_name)
46
-               filter_name(tmp, FILTER_PORT);
47
+               filter_name(tmp, FILTER_PORT, c->filter_char);
48
 
49
            op = find_port_by_name(c, tmp);
50
            if (op != NULL)
51
@@ -3388,6 +3389,8 @@
52
        pw_properties_set(client->props, PW_KEY_NODE_LATENCY, str);
53
    if ((str = getenv("PIPEWIRE_RATE")) != NULL)
54
        pw_properties_set(client->props, PW_KEY_NODE_RATE, str);
55
+   if ((str = getenv("PIPEWIRE_LINK_PASSIVE")) != NULL)
56
+       pw_properties_set(client->props, PW_KEY_NODE_PASSIVE, str);
57
 
58
    if ((str = pw_properties_get(client->props, PW_KEY_NODE_LATENCY)) != NULL) {
59
        uint32_t num, denom;
60
@@ -3444,6 +3447,9 @@
61
    client->merge_monitor = pw_properties_get_bool(client->props, "jack.merge-monitor", false);
62
    client->short_name = pw_properties_get_bool(client->props, "jack.short-name", false);
63
    client->filter_name = pw_properties_get_bool(client->props, "jack.filter-name", false);
64
+   client->filter_char = ' ';
65
+   if ((str = pw_properties_get(client->props, "jack.filter-char")) != NULL && str0 != '\0')
66
+       client->filter_char = str0;
67
    client->locked_process = pw_properties_get_bool(client->props, "jack.locked-process", true);
68
    client->default_as_system = pw_properties_get_bool(client->props, "jack.default-as-system", false);
69
    client->fix_midi_events = pw_properties_get_bool(client->props, "jack.fix-midi-events", true);
70
@@ -5168,7 +5174,7 @@
71
    itemsprops.n_items++ = SPA_DICT_ITEM_INIT(PW_KEY_LINK_INPUT_NODE, val2);
72
    itemsprops.n_items++ = SPA_DICT_ITEM_INIT(PW_KEY_LINK_INPUT_PORT, val3);
73
    itemsprops.n_items++ = SPA_DICT_ITEM_INIT(PW_KEY_OBJECT_LINGER, "true");
74
-   if ((str = getenv("PIPEWIRE_LINK_PASSIVE")) != NULL &&
75
+   if ((str = pw_properties_get(c->props, PW_KEY_NODE_PASSIVE)) != NULL &&
76
        pw_properties_parse_bool(str))
77
        itemsprops.n_items++ = SPA_DICT_ITEM_INIT(PW_KEY_LINK_PASSIVE, "true");
78
 
79
pipewire-0.3.60.tar.gz/po/ka.po -> pipewire-0.3.61.tar.gz/po/ka.po Changed
201
 
1
@@ -1,7 +1,7 @@
2
-# SOME DESCRIPTIVE TITLE.
3
-# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
4
+# Georgian translation for pipewire.
5
+# Copyright (C) 2022 pipewire'S authors
6
 # This file is distributed under the same license as the pipewire package.
7
-# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
8
+# Temuri Doghonadze <temuri.doghonadze@gmail.com>, 2022.
9
 #
10
 msgid ""
11
 msgstr ""
12
@@ -9,15 +9,15 @@
13
 "Report-Msgid-Bugs-To: https://gitlab.freedesktop.org/pipewire/pipewire/"
14
 "issues/new\n"
15
 "POT-Creation-Date: 2022-06-30 12:50+0200\n"
16
-"PO-Revision-Date: 2022-07-25 13:11+0200\n"
17
+"PO-Revision-Date: 2022-11-20 11:50+0100\n"
18
 "Last-Translator: Temuri Doghonadze <temuri.doghonadze@gmail.com>\n"
19
-"Language-Team: Georgian <(nothing)>\n"
20
+"Language-Team: \n"
21
 "Language: ka\n"
22
 "MIME-Version: 1.0\n"
23
 "Content-Type: text/plain; charset=UTF-8\n"
24
 "Content-Transfer-Encoding: 8bit\n"
25
 "Plural-Forms: nplurals=2; plural=(n != 1);\n"
26
-"X-Generator: Poedit 3.1.1\n"
27
+"X-Generator: Poedit 3.2\n"
28
 
29
 #: src/daemon/pipewire.c:46
30
 #, c-format
31
@@ -42,7 +42,7 @@
32
 msgid "Dummy Output"
33
 msgstr "ნულოვანი გამოყვანა"
34
 
35
-#: src/modules/module-pulse-tunnel.c:648
36
+#: src/modules/module-pulse-tunnel.c:662
37
 #, c-format
38
 msgid "Tunnel for %s@%s"
39
 msgstr "გვირაბი %s@%s-სთვის"
40
@@ -153,7 +153,7 @@
41
 "   -d, --dsd                             DSD რეჟიმი\n"
42
 "\n"
43
 
44
-#: src/tools/pw-cli.c:3165
45
+#: src/tools/pw-cli.c:2250
46
 #, c-format
47
 msgid ""
48
 "%s options command\n"
49
@@ -174,8 +174,8 @@
50
 msgid "Pro Audio"
51
 msgstr "Pro Audio"
52
 
53
-#: spa/plugins/alsa/acp/acp.c:446 spa/plugins/alsa/acp/alsa-mixer.c:4648
54
-#: spa/plugins/bluez5/bluez5-device.c:1161
55
+#: spa/plugins/alsa/acp/acp.c:444 spa/plugins/alsa/acp/alsa-mixer.c:4648
56
+#: spa/plugins/bluez5/bluez5-device.c:1236
57
 msgid "Off"
58
 msgstr "გამორთული"
59
 
60
@@ -202,7 +202,7 @@
61
 
62
 #: spa/plugins/alsa/acp/alsa-mixer.c:2657
63
 #: spa/plugins/alsa/acp/alsa-mixer.c:2741
64
-#: spa/plugins/bluez5/bluez5-device.c:1330
65
+#: spa/plugins/bluez5/bluez5-device.c:1454
66
 msgid "Microphone"
67
 msgstr "მიკროფონი"
68
 
69
@@ -268,7 +268,7 @@
70
 msgstr "Bass-ის გაძლიერების გარეშე"
71
 
72
 #: spa/plugins/alsa/acp/alsa-mixer.c:2672
73
-#: spa/plugins/bluez5/bluez5-device.c:1335
74
+#: spa/plugins/bluez5/bluez5-device.c:1460
75
 msgid "Speaker"
76
 msgstr "დინამიკი"
77
 
78
@@ -383,7 +383,7 @@
79
 
80
 #: spa/plugins/alsa/acp/alsa-mixer.c:4484
81
 #: spa/plugins/alsa/acp/alsa-mixer.c:4642
82
-#: spa/plugins/bluez5/bluez5-device.c:1320
83
+#: spa/plugins/bluez5/bluez5-device.c:1442
84
 msgid "Headset"
85
 msgstr "ყურსაცვამები & მიკროფონი"
86
 
87
@@ -507,7 +507,7 @@
88
 msgid "%s Input"
89
 msgstr "%s შეყვანა"
90
 
91
-#: spa/plugins/alsa/acp/alsa-util.c:1173 spa/plugins/alsa/acp/alsa-util.c:1267
92
+#: spa/plugins/alsa/acp/alsa-util.c:1187 spa/plugins/alsa/acp/alsa-util.c:1281
93
 #, c-format
94
 msgid ""
95
 "snd_pcm_avail() returned a value that is exceptionally large: %lu byte (%lu "
96
@@ -530,7 +530,7 @@
97
 "ყველაზე ხშირად ეს ALSA-ს დრაივერის (%s) შეცდომის გამო ხდება. დაუკავშირდით "
98
 "ALSA-ის პროგრამისტებს."
99
 
100
-#: spa/plugins/alsa/acp/alsa-util.c:1239
101
+#: spa/plugins/alsa/acp/alsa-util.c:1253
102
 #, c-format
103
 msgid ""
104
 "snd_pcm_delay() returned a value that is exceptionally large: %li byte (%s"
105
@@ -553,7 +553,7 @@
106
 "ყველაზე ხშირად ეს ALSA-ს დრაივერის (%s) შეცდომის გამო ხდება. დაუკავშირდით "
107
 "ALSA-ის პროგრამისტებს."
108
 
109
-#: spa/plugins/alsa/acp/alsa-util.c:1286
110
+#: spa/plugins/alsa/acp/alsa-util.c:1300
111
 #, c-format
112
 msgid ""
113
 "snd_pcm_avail_delay() returned strange values: delay %lu is less than avail "
114
@@ -566,7 +566,7 @@
115
 "ყველაზე ხშირად ეს ALSA-ს დრაივერის (%s) შეცდომის გამო ხდება. დაუკავშირდით "
116
 "ALSA-ის პროგრამისტებს."
117
 
118
-#: spa/plugins/alsa/acp/alsa-util.c:1329
119
+#: spa/plugins/alsa/acp/alsa-util.c:1343
120
 #, c-format
121
 msgid ""
122
 "snd_pcm_mmap_begin() returned a value that is exceptionally large: %lu byte "
123
@@ -601,61 +601,92 @@
124
 msgid "Modem"
125
 msgstr "მოდემი"
126
 
127
-#: spa/plugins/bluez5/bluez5-device.c:1172
128
+#: spa/plugins/bluez5/bluez5-device.c:1247
129
 msgid "Audio Gateway (A2DP Source & HSP/HFP AG)"
130
 msgstr "Audio Gateway (A2DP წყარო & HSP/HFP AG)"
131
 
132
-#: spa/plugins/bluez5/bluez5-device.c:1197
133
+#: spa/plugins/bluez5/bluez5-device.c:1272
134
 #, c-format
135
 msgid "High Fidelity Playback (A2DP Sink, codec %s)"
136
 msgstr "მაღალი ხარისხის ხმა (A2DP Sink, კოდეკი %s)"
137
 
138
-#: spa/plugins/bluez5/bluez5-device.c:1200
139
+#: spa/plugins/bluez5/bluez5-device.c:1275
140
 #, c-format
141
 msgid "High Fidelity Duplex (A2DP Source/Sink, codec %s)"
142
 msgstr "მაღალი ხარისხის დუპლექსი (A2DP წყარო/Sink, კოდეკი %s)"
143
 
144
-#: spa/plugins/bluez5/bluez5-device.c:1208
145
+#: spa/plugins/bluez5/bluez5-device.c:1283
146
 msgid "High Fidelity Playback (A2DP Sink)"
147
 msgstr "მაღალი ხარისხის ხმა (A2DP Sink)"
148
 
149
-#: spa/plugins/bluez5/bluez5-device.c:1210
150
+#: spa/plugins/bluez5/bluez5-device.c:1285
151
 msgid "High Fidelity Duplex (A2DP Source/Sink)"
152
 msgstr "მაღალი ხარისხის დუპლექსი(A2DP წყარო/Sink)"
153
 
154
-#: spa/plugins/bluez5/bluez5-device.c:1238
155
+#: spa/plugins/bluez5/bluez5-device.c:1322
156
+#, c-format
157
+msgid "High Fidelity Playback (BAP Sink, codec %s)"
158
+msgstr "მაღალი ხარისხის დაკვრა (BAP Sink, კოდეკი %s)"
159
+
160
+#: spa/plugins/bluez5/bluez5-device.c:1326
161
+#, c-format
162
+msgid "High Fidelity Input (BAP Source, codec %s)"
163
+msgstr "მაღალი ხარისხის შეყვანა (BAP წყარო, კოდეკი %s)"
164
+
165
+#: spa/plugins/bluez5/bluez5-device.c:1330
166
+#, c-format
167
+msgid "High Fidelity Duplex (BAP Source/Sink, codec %s)"
168
+msgstr "მაღალი ხარისხის დუპლექსი (BAP წყარო/Sink, კოდეკი %s)"
169
+
170
+#: spa/plugins/bluez5/bluez5-device.c:1359
171
 #, c-format
172
 msgid "Headset Head Unit (HSP/HFP, codec %s)"
173
 msgstr "Headset Head Unit (HSP/HFP, კოდეკი %s)"
174
 
175
-#: spa/plugins/bluez5/bluez5-device.c:1243
176
+#: spa/plugins/bluez5/bluez5-device.c:1364
177
 msgid "Headset Head Unit (HSP/HFP)"
178
 msgstr "Headset Head Unit (HSP/HFP)"
179
 
180
-#: spa/plugins/bluez5/bluez5-device.c:1325
181
+#: spa/plugins/bluez5/bluez5-device.c:1443
182
+#: spa/plugins/bluez5/bluez5-device.c:1448
183
+#: spa/plugins/bluez5/bluez5-device.c:1455
184
+#: spa/plugins/bluez5/bluez5-device.c:1461
185
+#: spa/plugins/bluez5/bluez5-device.c:1467
186
+#: spa/plugins/bluez5/bluez5-device.c:1473
187
+#: spa/plugins/bluez5/bluez5-device.c:1479
188
+#: spa/plugins/bluez5/bluez5-device.c:1485
189
+#: spa/plugins/bluez5/bluez5-device.c:1491
190
 msgid "Handsfree"
191
 msgstr "ხელის გარეშე სამართავი"
192
 
193
-#: spa/plugins/bluez5/bluez5-device.c:1340
194
+#: spa/plugins/bluez5/bluez5-device.c:1449
195
+msgid "Handsfree (HFP)"
196
+msgstr "ხელის გარეშე სამართავი (HFP)"
197
+
198
+#: spa/plugins/bluez5/bluez5-device.c:1466
199
 msgid "Headphone"
200
 msgstr "ყურსაცვამი"
201
pipewire-0.3.60.tar.gz/spa/plugins/alsa/acp/acp.c -> pipewire-0.3.61.tar.gz/spa/plugins/alsa/acp/acp.c Changed
28
 
1
@@ -34,6 +34,8 @@
2
 
3
 struct spa_i18n *acp_i18n;
4
 
5
+#define DEFAULT_RATE   44100
6
+
7
 #define VOLUME_ACCURACY (PA_VOLUME_NORM/100)  /* don't require volume adjustments to be perfectly correct. don't necessarily extend granularity in software unless the differences get greater than this level */
8
 
9
 static const uint32_t channel_tablePA_CHANNEL_POSITION_MAX = {
10
@@ -312,7 +314,7 @@
11
    snd_pcm_uframes_t try_period_size, try_buffer_size;
12
 
13
    ss.format = PA_SAMPLE_S32LE;
14
-   ss.rate = 48000;
15
+   ss.rate = DEFAULT_RATE;
16
    ss.channels = 64;
17
 
18
    ap = pa_xnew0(pa_alsa_profile, 1);
19
@@ -1571,7 +1573,7 @@
20
    }
21
 
22
    impl->ucm.default_sample_spec.format = PA_SAMPLE_S16NE;
23
-   impl->ucm.default_sample_spec.rate = 48000;
24
+   impl->ucm.default_sample_spec.rate = DEFAULT_RATE;
25
    impl->ucm.default_sample_spec.channels = 2;
26
    pa_channel_map_init_extend(&impl->ucm.default_channel_map,
27
            impl->ucm.default_sample_spec.channels, PA_CHANNEL_MAP_ALSA);
28
pipewire-0.3.60.tar.gz/spa/plugins/alsa/alsa-pcm.c -> pipewire-0.3.61.tar.gz/spa/plugins/alsa/alsa-pcm.c Changed
10
 
1
@@ -2128,7 +2128,7 @@
2
 
3
    state->sample_count += total_written;
4
 
5
-   if (SPA_UNLIKELY(!state->alsa_started && total_written > 0))
6
+   if (SPA_UNLIKELY(!state->alsa_started && (total_written > 0 || frames == 0)))
7
        do_start(state);
8
 
9
    return 0;
10
pipewire-0.3.60.tar.gz/spa/plugins/alsa/mixer/profile-sets/asus-xonar-se.conf -> pipewire-0.3.61.tar.gz/spa/plugins/alsa/mixer/profile-sets/asus-xonar-se.conf Changed
22
 
1
@@ -76,4 +76,18 @@
2
 device-strings = iec958:%f
3
 channel-map = left,right
4
 paths-output = iec958-stereo-output
5
-priority = 5
6
\ No newline at end of file
7
+priority = 5
8
+
9
+Mapping iec958-ac3-surround-40
10
+device-strings = a52:%f
11
+channel-map = front-left,front-right,rear-left,rear-right
12
+paths-output = iec958-stereo-output
13
+priority = 2
14
+direction = output
15
+
16
+Mapping iec958-ac3-surround-51
17
+device-strings = a52:%f
18
+channel-map = front-left,front-right,rear-left,rear-right,front-center,lfe
19
+paths-output = iec958-stereo-output
20
+priority = 3
21
+direction = output
22
pipewire-0.3.60.tar.gz/spa/plugins/audioconvert/audioadapter.c -> pipewire-0.3.61.tar.gz/spa/plugins/audioconvert/audioadapter.c Changed
81
 
1
@@ -438,6 +438,9 @@
2
 {
3
    int res;
4
 
5
+   if (format == NULL && !this->have_format)
6
+       return 0;
7
+
8
    spa_log_debug(this->log, "%p: configure format:", this);
9
    if (format && spa_log_level_enabled(this->log, SPA_LOG_LEVEL_DEBUG))
10
        spa_debug_format(0, NULL, format);
11
@@ -894,10 +897,11 @@
12
                (this->paramsidx.flags & SPA_PARAM_INFO_SERIAL) |
13
                (info->paramsi.flags & SPA_PARAM_INFO_READWRITE);
14
 
15
-           if (!this->add_listener) {
16
-               this->paramsidx.user++;
17
-               spa_log_debug(this->log, "param %d changed", info->paramsi.id);
18
-           }
19
+           if (this->add_listener)
20
+               continue;
21
+
22
+           this->paramsidx.user++;
23
+           spa_log_debug(this->log, "param %d changed", info->paramsi.id);
24
        }
25
    }
26
    emit_node_info(this, false);
27
@@ -1002,10 +1006,11 @@
28
                (this->paramsidx.flags & SPA_PARAM_INFO_SERIAL) |
29
                (info->paramsi.flags & SPA_PARAM_INFO_READWRITE);
30
 
31
-           if (!this->add_listener) {
32
-               this->paramsidx.user++;
33
-               spa_log_debug(this->log, "param %d changed", info->paramsi.id);
34
-           }
35
+           if (this->add_listener)
36
+               continue;
37
+
38
+           this->paramsidx.user++;
39
+           spa_log_debug(this->log, "param %d changed", info->paramsi.id);
40
        }
41
    }
42
    emit_node_info(this, false);
43
@@ -1082,26 +1087,32 @@
44
            default:
45
                continue;
46
            }
47
+
48
            if (!this->add_listener &&
49
                this->follower_params_flagsidx == info->paramsi.flags)
50
                continue;
51
 
52
+           this->info.change_mask |= SPA_NODE_CHANGE_MASK_PARAMS;
53
            this->follower_params_flagsidx = info->paramsi.flags;
54
            this->paramsidx.flags =
55
                (this->paramsidx.flags & SPA_PARAM_INFO_SERIAL) |
56
                (info->paramsi.flags & SPA_PARAM_INFO_READWRITE);
57
 
58
+           if (this->add_listener)
59
+               continue;
60
+
61
            if (idx == IDX_Latency) {
62
                res = recalc_latency(this, direction, port_id);
63
                spa_log_debug(this->log, "latency: %d (%s)", res,
64
                        spa_strerror(res));
65
            }
66
-
67
-           this->info.change_mask |= SPA_NODE_CHANGE_MASK_PARAMS;
68
-           if (!this->add_listener) {
69
-               this->paramsidx.user++;
70
-               spa_log_debug(this->log, "param %d changed", info->paramsi.id);
71
+           if (idx == IDX_EnumFormat) {
72
+               spa_log_debug(this->log, "new formats");
73
+               configure_format(this, 0, NULL);
74
            }
75
+
76
+           this->paramsidx.user++;
77
+           spa_log_debug(this->log, "param %d changed", info->paramsi.id);
78
        }
79
    }
80
    emit_node_info(this, false);
81
pipewire-0.3.60.tar.gz/spa/plugins/audioconvert/audioconvert.c -> pipewire-0.3.61.tar.gz/spa/plugins/audioconvert/audioconvert.c Changed
62
 
1
@@ -979,6 +979,7 @@
2
    }
3
 
4
    this->monitor = monitor;
5
+   this->setup = false;
6
    dir->control = control;
7
    dir->have_profile = true;
8
    dir->mode = mode;
9
@@ -1645,7 +1646,6 @@
10
                 struct spa_pod_builder *builder)
11
 {
12
    struct impl *this = object;
13
-   struct port *port = GET_PORT(this, direction, port_id);
14
 
15
    switch (index) {
16
    case 0:
17
@@ -1659,11 +1659,7 @@
18
                SPA_TYPE_OBJECT_Format, SPA_PARAM_EnumFormat,
19
                SPA_FORMAT_mediaType,      SPA_POD_Id(SPA_MEDIA_TYPE_application),
20
                SPA_FORMAT_mediaSubtype,   SPA_POD_Id(SPA_MEDIA_SUBTYPE_control));
21
-       } else if (port->have_format) {
22
-           *param = spa_format_audio_raw_build(builder,
23
-               SPA_PARAM_EnumFormat, &this->dirdirection.format.info.raw);
24
-       }
25
-       else {
26
+       } else {
27
            uint32_t rate = this->io_position ?
28
                this->io_position->clock.rate.denom : DEFAULT_RATE;
29
 
30
@@ -1873,7 +1869,7 @@
31
               const struct spa_pod *latency)
32
 {
33
    struct impl *this = object;
34
-   struct port *port;
35
+   struct port *port, *oport;
36
    enum spa_direction other = SPA_DIRECTION_REVERSE(direction);
37
    uint32_t i;
38
 
39
@@ -1895,10 +1891,10 @@
40
    }
41
 
42
    for (i = 0; i < this->dirother.n_ports; i++) {
43
-       port = GET_PORT(this, other, i);
44
-       port->info.change_mask |= SPA_PORT_CHANGE_MASK_PARAMS;
45
-       port->paramsIDX_Latency.user++;
46
-       emit_port_info(this, port, false);
47
+       oport = GET_PORT(this, other, i);
48
+       oport->info.change_mask |= SPA_PORT_CHANGE_MASK_PARAMS;
49
+       oport->paramsIDX_Latency.user++;
50
+       emit_port_info(this, oport, false);
51
    }
52
    port->info.change_mask |= SPA_PORT_CHANGE_MASK_PARAMS;
53
    port->paramsIDX_Latency.user++;
54
@@ -1988,6 +1984,7 @@
55
            }
56
            this->dirdirection.format = info;
57
            this->dirdirection.have_format = true;
58
+           this->setup = false;
59
        }
60
        port->format = info;
61
        port->have_format = true;
62
pipewire-0.3.60.tar.gz/spa/plugins/audioconvert/resample-native-impl.h -> pipewire-0.3.61.tar.gz/spa/plugins/audioconvert/resample-native-impl.h Changed
70
 
1
@@ -94,6 +94,14 @@
2
    *out_len = ooffs;                           \
3
 }
4
 
5
+#define INC(index,phase,n_phases) \
6
+   index += inc;                       \
7
+   phase += frac;                      \
8
+   if (phase >= n_phases) {                \
9
+       phase -= n_phases;              \
10
+       index += 1;                 \
11
+   }
12
+
13
 #define MAKE_RESAMPLER_FULL(arch)                      \
14
 DEFINE_RESAMPLER(full,arch)                            \
15
 {                                      \
16
@@ -114,17 +122,10 @@
17
        phase = data->phase;                        \
18
                                        \
19
        for (o = ooffs; o < olen && index + n_taps <= ilen; o++) {  \
20
-           const float *ip, *taps;                 \
21
-                                       \
22
-           ip = &sindex;                       \
23
-           taps = &data->filterphase * stride;         \
24
-           index += inc;                       \
25
-           phase += frac;                      \
26
-           if (phase >= n_phases) {                \
27
-               phase -= n_phases;              \
28
-               index += 1;                 \
29
-           }                           \
30
-           inner_product_##arch(&do, ip, taps, n_taps);        \
31
+           inner_product_##arch(&do, &sindex,          \
32
+                   &data->filterphase * stride,        \
33
+                   n_taps);                \
34
+           INC(index, phase, n_phases);                \
35
        }                               \
36
    }                                   \
37
    *in_len = index;                            \
38
@@ -153,24 +154,13 @@
39
        phase = data->phase;                        \
40
                                        \
41
        for (o = ooffs; o < olen && index + n_taps <= ilen; o++) {  \
42
-           const float *ip, *t0, *t1;              \
43
-           float ph, x;                        \
44
-           uint32_t offset;                    \
45
-                                       \
46
-           ip = &sindex;                       \
47
-           ph = (float)phase * n_phases / out_rate;        \
48
-           offset = floor(ph);                 \
49
-           x = ph - (float)offset;                 \
50
-                                       \
51
-           t0 = &data->filter(offset + 0) * stride;        \
52
-           t1 = &data->filter(offset + 1) * stride;        \
53
-           index += inc;                       \
54
-           phase += frac;                      \
55
-           if (phase >= out_rate) {                \
56
-               phase -= out_rate;              \
57
-               index += 1;                 \
58
-           }                           \
59
-           inner_product_ip_##arch(&do, ip, t0, t1, x, n_taps);    \
60
+           float ph = (float)phase * n_phases / out_rate;      \
61
+           uint32_t offset = floorf(ph);               \
62
+           inner_product_ip_##arch(&do, &sindex,       \
63
+                   &data->filter(offset + 0) * stride, \
64
+                   &data->filter(offset + 1) * stride, \
65
+                   ph - offset, n_taps);           \
66
+           INC(index, phase, out_rate);                \
67
        }                               \
68
    }                                   \
69
    *in_len = index;                            \
70
pipewire-0.3.60.tar.gz/spa/plugins/audioconvert/test-channelmix.c -> pipewire-0.3.61.tar.gz/spa/plugins/audioconvert/test-channelmix.c Changed
41
 
1
@@ -269,9 +269,19 @@
2
                   0.0, 1.0, 0.707107, 0.0, 0.0, 0.707107, 0.0, 0.707107));
3
 }
4
 
5
+static void check_samples(float **s1, float **s2, uint32_t n_s, uint32_t n_samples)
6
+{
7
+   uint32_t i, j;
8
+   for (i = 0; i < n_s; i++) {
9
+       for (j = 0; j < n_samples; j++) {
10
+           spa_assert_se(CLOSE_ENOUGH(s1ij, s2ij));
11
+       }
12
+   }
13
+}
14
+
15
 static void run_n_m_impl(struct channelmix *mix, const void **src, uint32_t n_samples)
16
 {
17
-   uint32_t dst_chan = mix->dst_chan, i, j;
18
+   uint32_t dst_chan = mix->dst_chan, i;
19
    float dst_c_datadst_chann_samples;
20
    float dst_x_datadst_chann_samples;
21
    void *dst_cdst_chan, *dst_xdst_chan;
22
@@ -283,14 +293,13 @@
23
 
24
    channelmix_f32_n_m_c(mix, dst_c, src, n_samples);
25
 
26
+   channelmix_f32_n_m_c(mix, dst_x, src, n_samples);
27
+   check_samples((float**)dst_c, (float**)dst_x, dst_chan, n_samples);
28
+
29
 #if defined(HAVE_SSE)
30
    if (cpu_flags & SPA_CPU_FLAG_SSE) {
31
        channelmix_f32_n_m_sse(mix, dst_x, src, n_samples);
32
-       for (i = 0; i < mix->dst_chan; i++) {
33
-           for (j = 0; j < n_samples; j++) {
34
-               spa_assert_se(CLOSE_ENOUGH(dst_c_dataij, dst_x_dataij));
35
-           }
36
-       }
37
+       check_samples((float**)dst_c, (float**)dst_x, dst_chan, n_samples);
38
    }
39
 #endif
40
 }
41
pipewire-0.3.60.tar.gz/spa/plugins/bluez5/backend-native.c -> pipewire-0.3.61.tar.gz/spa/plugins/bluez5/backend-native.c Changed
14
 
1
@@ -1111,10 +1111,10 @@
2
            return true;
3
        }
4
    } else if (spa_strstartswith(buf, "ATD")) {
5
-       char number30;
6
+       char number31, sep;
7
        enum cmee_error error;
8
 
9
-       if (sscanf(buf, "ATD%30s;", number) != 1) {
10
+       if (sscanf(buf, "ATD%30^;%c", number, &sep) != 2 || sep != ';') {
11
            spa_log_debug(backend->log, "Failed to parse ATD: \"%s\"", buf);
12
            rfcomm_send_error(rfcomm, CMEE_AG_FAILURE);
13
            return true;
14
pipewire-0.3.60.tar.gz/spa/plugins/bluez5/bap-codec-lc3.c -> pipewire-0.3.61.tar.gz/spa/plugins/bluez5/bap-codec-lc3.c Changed
9
 
1
@@ -24,7 +24,6 @@
2
  * DEALINGS IN THE SOFTWARE.
3
  */
4
 
5
-#include <bits/stdint-uintn.h>
6
 #include <string.h>
7
 #include <unistd.h>
8
 #include <stddef.h>
9
pipewire-0.3.60.tar.gz/spa/plugins/bluez5/modemmanager.c -> pipewire-0.3.61.tar.gz/spa/plugins/bluez5/modemmanager.c Changed
58
 
1
@@ -1023,35 +1023,25 @@
2
    dbus_message_iter_close_container(dict, &dict_entry_it);
3
 }
4
 
5
+static inline bool is_valid_dial_string_char(char c)
6
+{
7
+   return ('0' <= c && c <= '9')
8
+       || ('A' <= c && c <= 'C')
9
+       || c == '*'
10
+       || c == '#'
11
+       || c == '+';
12
+}
13
+
14
 bool mm_do_call(void *modemmanager, const char* number, void *user_data, enum cmee_error *error)
15
 {
16
    struct impl *this = modemmanager;
17
-   unsigned int k, j;
18
-   char *number_filtered;
19
    struct dbus_cmd_data *data;
20
    DBusMessage *m;
21
    DBusMessageIter iter, dict;
22
 
23
-   /* Filter extracted number from invalid characters
24
-       * Allowed characters: 0-9, *, #, +, A-C
25
-       */
26
-   k=0;
27
-   number_filtered = calloc(1, 30);
28
-   for (j=0; j < 30; j++) {
29
-       if ((numberj >= '0' && numberj <= '9')
30
-           || (numberj == '*')
31
-           || (numberj == '#')
32
-           || (numberj == '+')
33
-           || (numberj >= 'A' && numberj <= 'C')) {
34
-           number_filteredk = numberj;
35
-           k++;
36
-       }
37
-       /* ATD commands ends with ';' */
38
-       else if (numberj == ';')
39
-           break;
40
-       /* Send error for invalid characters */
41
-       else {
42
-           spa_log_warn(this->log, "Call creation canceled, invalid character found in dial string: %c", numberj);
43
+   for (size_t i = 0; numberi; i++) {
44
+       if (!is_valid_dial_string_char(numberi)) {
45
+           spa_log_warn(this->log, "Call creation canceled, invalid character found in dial string: %c", numberi);
46
            if (error)
47
                *error = CMEE_INVALID_CHARACTERS_DIAL_STRING;
48
            return false;
49
@@ -1075,7 +1065,7 @@
50
    }
51
    dbus_message_iter_init_append(m, &iter);
52
    dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "{sv}", &dict);
53
-   append_basic_variant_dict_entry(&dict, "number", DBUS_TYPE_STRING, "s", &number_filtered);
54
+   append_basic_variant_dict_entry(&dict, "number", DBUS_TYPE_STRING, "s", &number);
55
    dbus_message_iter_close_container(&iter, &dict);
56
    if (!mm_dbus_connection_send_with_reply(this, m, &this->voice_pending, mm_get_call_create_reply, data)) {
57
        spa_log_error(this->log, "dbus call failure");
58
pipewire-0.3.60.tar.gz/spa/plugins/libcamera/libcamera-client.c -> pipewire-0.3.61.tar.gz/spa/plugins/libcamera/libcamera-client.c Changed
34
 
1
@@ -77,8 +77,8 @@
2
    itemsn_items++ = SPA_DICT_ITEM_INIT(SPA_KEY_DEVICE_API, "libcamera");
3
    itemsn_items++ = SPA_DICT_ITEM_INIT(SPA_KEY_MEDIA_CLASS, "Video/Device");
4
 
5
-    info.props = &SPA_DICT_INIT(items, n_items);
6
-    spa_device_emit_object_info(&this->hooks, id, &info);
7
+   info.props = &SPA_DICT_INIT(items, n_items);
8
+   spa_device_emit_object_info(&this->hooks, id, &info);
9
 
10
    return 1;
11
 }
12
@@ -112,18 +112,18 @@
13
        const struct spa_device_events *events, void *data)
14
 {
15
    struct impl *this = object;
16
-    struct spa_hook_list save;
17
+   struct spa_hook_list save;
18
 
19
    spa_return_val_if_fail(this != NULL, -EINVAL);
20
    spa_return_val_if_fail(events != NULL, -EINVAL);
21
 
22
-    spa_hook_list_isolate(&this->hooks, &save, listener, events, data);
23
+   spa_hook_list_isolate(&this->hooks, &save, listener, events, data);
24
 
25
    emit_device_info(this, true);
26
 
27
    emit_object_info(this, 0);
28
 
29
-    spa_hook_list_join(&this->hooks, &save);
30
+   spa_hook_list_join(&this->hooks, &save);
31
 
32
    listener->removed = impl_hook_removed;
33
    listener->priv = this;
34
pipewire-0.3.60.tar.gz/spa/plugins/libcamera/libcamera-manager.cpp -> pipewire-0.3.61.tar.gz/spa/plugins/libcamera/libcamera-manager.cpp Changed
62
 
1
@@ -117,6 +117,13 @@
2
 
3
    return manager;
4
 }
5
+static uint32_t get_free_id(struct impl *impl)
6
+{
7
+   for (std::size_t i = 0; i < MAX_DEVICES; i++)
8
+       if (impl->devicesi.camera == nullptr)
9
+           return i;
10
+   return 0;
11
+}
12
 
13
 static struct device *add_device(struct impl *impl, std::shared_ptr<Camera> camera)
14
 {
15
@@ -125,10 +132,11 @@
16
 
17
    if (impl->n_devices >= MAX_DEVICES)
18
        return NULL;
19
-   id = impl->n_devices++;
20
+   id = get_free_id(impl);;
21
    device = &impl->devicesid;
22
-   device->id = id;
23
+   device->id = get_free_id(impl);;
24
    device->camera = std::move(camera);
25
+   impl->n_devices++;
26
    return device;
27
 }
28
 
29
@@ -144,8 +152,10 @@
30
 
31
 static void remove_device(struct impl *impl, struct device *device)
32
 {
33
+   uint32_t old = --impl->n_devices;
34
    device->camera.reset();
35
-   *device = std::move(impl->devices--impl->n_devices);
36
+   *device = std::move(impl->devicesold);
37
+   impl->devicesold.camera = nullptr;
38
 }
39
 
40
 static void clear_devices(struct impl *impl)
41
@@ -196,7 +206,8 @@
42
    if ((device = add_device(impl, std::move(camera))) == NULL)
43
        return;
44
 
45
-   spa_log_info(impl->log, "camera added: %s", device->camera->id().c_str());
46
+   spa_log_info(impl->log, "camera added: id:%d %s", device->id,
47
+           device->camera->id().c_str());
48
    emit_object_info(impl, device);
49
 }
50
 
51
@@ -207,7 +218,9 @@
52
    if ((device = find_device(impl, camera)) == NULL)
53
        return;
54
 
55
-   spa_log_info(impl->log, "camera removed: %s", device->camera->id().c_str());
56
+   spa_log_info(impl->log, "camera removed: id:%d %s", device->id,
57
+           device->camera->id().c_str());
58
+   spa_device_emit_object_info(&impl->hooks, device->id, NULL);
59
    remove_device(impl, device);
60
 }
61
 
62
pipewire-0.3.60.tar.gz/spa/plugins/libcamera/libcamera-source.cpp -> pipewire-0.3.61.tar.gz/spa/plugins/libcamera/libcamera-source.cpp Changed
28
 
1
@@ -833,15 +833,9 @@
2
    return res;
3
 }
4
 
5
-static void set_control(struct impl *impl, struct port *port, uint32_t control_id, float value)
6
-{
7
-   spa_log_error(impl->log, "Failed to set control");
8
-}
9
-
10
 static int process_control(struct impl *impl, struct spa_pod_sequence *control)
11
 {
12
    struct spa_pod_control *c;
13
-   struct port *port;
14
 
15
    SPA_POD_SEQUENCE_FOREACH(control, c) {
16
        switch (c->type) {
17
@@ -851,9 +845,7 @@
18
            struct spa_pod_object *obj = (struct spa_pod_object *) &c->value;
19
 
20
            SPA_POD_OBJECT_FOREACH(obj, prop) {
21
-               port = GET_OUT_PORT(impl, 0);
22
-               set_control(impl, port, prop->key,
23
-                       SPA_POD_VALUE(struct spa_pod_float, &prop->value));
24
+               spa_libcamera_set_control(impl, prop);
25
            }
26
            break;
27
        }
28
pipewire-0.3.60.tar.gz/spa/plugins/libcamera/libcamera-utils.cpp -> pipewire-0.3.61.tar.gz/spa/plugins/libcamera/libcamera-utils.cpp Changed
37
 
1
@@ -857,11 +857,11 @@
2
 
3
    spa_log_info(impl->log, "starting camera %s", impl->device_id.c_str());
4
    if ((res = impl->camera->start()) < 0)
5
-       return res == -EACCES ? -EBUSY : res;
6
+       goto error;
7
 
8
    for (Request *req : impl->pendingRequests) {
9
        if ((res = impl->camera->queueRequest(req)) < 0)
10
-           return res == -EACCES ? -EBUSY : res;
11
+           goto error_stop;
12
    }
13
    impl->pendingRequests.clear();
14
 
15
@@ -872,13 +872,20 @@
16
    impl->source.rmask = 0;
17
    if (impl->source.fd < 0) {
18
        spa_log_error(impl->log, "Failed to create eventfd: %s", spa_strerror(impl->source.fd));
19
-       return impl->source.fd;
20
+       res = impl->source.fd;
21
+       goto error_stop;
22
    }
23
    spa_loop_add_source(impl->data_loop, &impl->source);
24
 
25
    impl->active = true;
26
 
27
    return 0;
28
+
29
+error_stop:
30
+   impl->camera->stop();
31
+error:
32
+   impl->camera->requestCompleted.disconnect(impl, &impl::requestComplete);
33
+   return res == -EACCES ? -EBUSY : res;
34
 }
35
 
36
 static int do_remove_source(struct spa_loop *loop,
37
pipewire-0.3.60.tar.gz/spa/plugins/v4l2/v4l2-source.c -> pipewire-0.3.61.tar.gz/spa/plugins/v4l2/v4l2-source.c Changed
84
 
1
@@ -325,7 +325,6 @@
2
        struct props *p = &this->props;
3
        struct spa_pod_object *obj = (struct spa_pod_object *) param;
4
        struct spa_pod_prop *prop;
5
-       int res = 0;
6
 
7
        if (param == NULL) {
8
            reset_props(p);
9
@@ -339,11 +338,9 @@
10
                        sizeof(p->device)-1);
11
                break;
12
            default:
13
-               res = spa_v4l2_set_control(this, prop->key, prop);
14
+               spa_v4l2_set_control(this, prop->key, prop);
15
                break;
16
            }
17
-           if (res < 0)
18
-               return res;
19
        }
20
 
21
        break;
22
@@ -825,45 +822,9 @@
23
    return res;
24
 }
25
 
26
-static uint32_t prop_to_control_id(uint32_t prop)
27
-{
28
-   switch (prop) {
29
-   case SPA_PROP_brightness:
30
-       return V4L2_CID_BRIGHTNESS;
31
-   case SPA_PROP_contrast:
32
-       return V4L2_CID_CONTRAST;
33
-   case SPA_PROP_saturation:
34
-       return V4L2_CID_SATURATION;
35
-   case SPA_PROP_hue:
36
-       return V4L2_CID_HUE;
37
-   case SPA_PROP_gamma:
38
-       return V4L2_CID_GAMMA;
39
-   case SPA_PROP_exposure:
40
-       return V4L2_CID_EXPOSURE;
41
-   case SPA_PROP_gain:
42
-       return V4L2_CID_GAIN;
43
-   case SPA_PROP_sharpness:
44
-       return V4L2_CID_SHARPNESS;
45
-   default:
46
-       return 0;
47
-   }
48
-}
49
-
50
-static void set_control(struct impl *this, struct port *port, uint32_t control_id, float value)
51
-{
52
-   struct v4l2_control c;
53
-
54
-   spa_zero(c);
55
-   c.id = control_id;
56
-   c.value = value;
57
-   if (ioctl(port->dev.fd, VIDIOC_S_CTRL, &c) < 0)
58
-       spa_log_error(this->log, "VIDIOC_S_CTRL %m");
59
-}
60
-
61
 static int process_control(struct impl *this, struct spa_pod_sequence *control)
62
 {
63
    struct spa_pod_control *c;
64
-   struct port *port;
65
 
66
    SPA_POD_SEQUENCE_FOREACH(control, c) {
67
        switch (c->type) {
68
@@ -873,14 +834,7 @@
69
            struct spa_pod_object *obj = (struct spa_pod_object *) &c->value;
70
 
71
            SPA_POD_OBJECT_FOREACH(obj, prop) {
72
-               uint32_t control_id;
73
-
74
-               if ((control_id = prop_to_control_id(prop->key)) == 0)
75
-                   continue;
76
-
77
-               port = GET_OUT_PORT(this, 0);
78
-               set_control(this, port, control_id,
79
-                       SPA_POD_VALUE(struct spa_pod_float, &prop->value));
80
+               spa_v4l2_set_control(this, prop->key, prop);
81
            }
82
            break;
83
        }
84
pipewire-0.3.60.tar.gz/spa/plugins/v4l2/v4l2-utils.c -> pipewire-0.3.61.tar.gz/spa/plugins/v4l2/v4l2-utils.c Changed
45
 
1
@@ -56,7 +56,7 @@
2
        return -EIO;
3
    }
4
 
5
-   spa_log_info(dev->log, "Playback device is '%s'", path);
6
+   spa_log_info(dev->log, "device is '%s'", path);
7
 
8
    dev->fd = open(path, O_RDWR | O_NONBLOCK, 0);
9
    if (dev->fd == -1) {
10
@@ -84,6 +84,7 @@
11
        spa_log_error(dev->log, "'%s' QUERYCAP: %m", path);
12
        goto error_close;
13
    }
14
+   snprintf(dev->path, sizeof(dev->path), "%s", path);
15
    return 0;
16
 
17
 error_close:
18
@@ -109,7 +110,7 @@
19
    if (dev->active || dev->have_format)
20
        return 0;
21
 
22
-   spa_log_info(dev->log, "close");
23
+   spa_log_info(dev->log, "close '%s'", dev->path);
24
 
25
    if (close(dev->fd))
26
        spa_log_warn(dev->log, "close: %m");
27
@@ -972,7 +973,7 @@
28
        return match ? 0 : 1;
29
 
30
    spa_log_info(this->log, "'%s' got %.4s %dx%d %d/%d",
31
-           this->props.device, (char *)&fmt.fmt.pix.pixelformat,
32
+           dev->path, (char *)&fmt.fmt.pix.pixelformat,
33
            fmt.fmt.pix.width, fmt.fmt.pix.height,
34
            streamparm.parm.capture.timeperframe.denominator,
35
            streamparm.parm.capture.timeperframe.numerator);
36
@@ -1610,7 +1611,7 @@
37
        }
38
        spa_v4l2_buffer_recycle(this, i);
39
    }
40
-   spa_log_info(this->log, "have %u buffers using %s", n_buffers,
41
+   spa_log_info(this->log, "%s: have %u buffers using %s", dev->path, n_buffers,
42
            use_expbuf ? "EXPBUF" : "MMAP");
43
 
44
    port->n_buffers = n_buffers;
45
pipewire-0.3.60.tar.gz/spa/plugins/v4l2/v4l2.h -> pipewire-0.3.61.tar.gz/spa/plugins/v4l2/v4l2.h Changed
9
 
1
@@ -41,6 +41,7 @@
2
    struct v4l2_capability cap;
3
    unsigned int active:1;
4
    unsigned int have_format:1;
5
+   char path64;
6
 };
7
 
8
 int spa_v4l2_open(struct spa_v4l2_device *dev, const char *path);
9
pipewire-0.3.60.tar.gz/src/daemon/jack.conf.in -> pipewire-0.3.61.tar.gz/src/daemon/jack.conf.in Changed
37
 
1
@@ -73,6 +73,7 @@
2
      #jack.merge-monitor = false
3
      #jack.short-name    = false
4
      #jack.filter-name   = false
5
+     #jack.filter-char   = " "
6
      #
7
      # allow:           Don't restrict self connect requests
8
      # fail-external:   Fail self connect requests to external ports only
9
@@ -103,15 +104,22 @@
10
             }
11
         }
12
     }
13
-    {
14
-        matches = 
15
-            {
16
-                application.process.binary = "jack_bufsize"
17
+    { matches = 
18
+            { application.process.binary = "jack_bufsize" }
19
+        
20
+        actions = {
21
+            update-props = {
22
+                jack.global-buffer-size = true   # quantum set globally using metadata
23
             }
24
+        }
25
+    }
26
+    { matches = 
27
+            { application.process.binary = "qsynth" }
28
         
29
         actions = {
30
             update-props = {
31
-                jack.global-buffer-size = true
32
+                node.pause-on-idle = false  # makes audio fade out when idle
33
+                node.passive = true         # makes the sink and qsynth suspend
34
             }
35
         }
36
     }
37
pipewire-0.3.60.tar.gz/src/daemon/pipewire-pulse.conf.in -> pipewire-0.3.61.tar.gz/src/daemon/pipewire-pulse.conf.in Changed
17
 
1
@@ -90,6 +90,7 @@
2
     #pulse.default.frag     = 96000/48000   # 2 seconds
3
     #pulse.default.tlength  = 96000/48000   # 2 seconds
4
     #pulse.min.quantum      = 256/48000     # 5ms
5
+    #pulse.idle.timeout     = 5             # pause after 5s of underruns
6
     #pulse.default.format   = F32
7
     #pulse.default.position =  FL FR 
8
     # These overrides are only applied when running in a vm.
9
@@ -141,6 +142,7 @@
10
             update-props = {
11
                 pulse.min.req          = 1024/48000     # 21ms
12
                 pulse.min.quantum      = 1024/48000     # 21ms
13
+                #pulse.idle.timeout    = 0
14
             }
15
         }
16
     }
17
pipewire-0.3.60.tar.gz/src/examples/audio-capture.c -> pipewire-0.3.61.tar.gz/src/examples/audio-capture.c Changed
29
 
1
@@ -42,6 +42,7 @@
2
    struct pw_stream *stream;
3
 
4
    struct spa_audio_info format;
5
+   unsigned move:1;
6
 };
7
 
8
 /* our data processing function is in general:
9
@@ -73,6 +74,9 @@
10
    n_channels = data->format.info.raw.channels;
11
    n_samples = buf->datas0.chunk->size / sizeof(float);
12
 
13
+   /* move cursor up */
14
+   if (data->move)
15
+       fprintf(stdout, "%c%dA", 0x1b, n_channels + 1);
16
    fprintf(stdout, "captured %d samples\n", n_samples / n_channels);
17
    for (c = 0; c < data->format.info.raw.channels; c++) {
18
        max = 0.0f;
19
@@ -84,8 +88,7 @@
20
        fprintf(stdout, "channel %d: |%*s%*s| peak:%f\n",
21
                c, peak+1, "*", 40 - peak, "", max);
22
    }
23
-   /* move cursor up */
24
-   fprintf(stdout, "%c%dA", 0x1b, n_channels + 1);
25
+   data->move = true;
26
    fflush(stdout);
27
 
28
    pw_stream_queue_buffer(data->stream, b);
29
pipewire-0.3.60.tar.gz/src/modules/meson.build -> pipewire-0.3.61.tar.gz/src/modules/meson.build Changed
46
 
1
@@ -61,33 +61,36 @@
2
 simd_dependencies = 
3
 
4
 if have_sse
5
-  pffft_sse = static_library('pffft_sse',
6
-    'module-filter-chain/pffft.c' ,
7
+  filter_chain_sse = static_library('filter_chain_sse',
8
+    'module-filter-chain/pffft.c',
9
+     'module-filter-chain/dsp-ops-sse.c' ,
10
     c_args : sse_args, '-O3', '-DHAVE_SSE',
11
     dependencies :  spa_dep ,
12
     install : false
13
     )
14
   simd_cargs += '-DHAVE_SSE'
15
-  simd_dependencies += pffft_sse
16
+  simd_dependencies += filter_chain_sse
17
 endif
18
 if have_neon
19
-  pffft_neon = static_library('pffft_neon',
20
+  filter_chain_neon = static_library('filter_chain_neon',
21
     'module-filter-chain/pffft.c' ,
22
     c_args : neon_args, '-O3', '-DHAVE_NEON',
23
     dependencies :  spa_dep ,
24
     install : false
25
     )
26
   simd_cargs += '-DHAVE_NEON'
27
-  simd_dependencies += pffft_neon
28
+  simd_dependencies += filter_chain_neon
29
 endif
30
 
31
-pffft_c = static_library('pffft_c',
32
-  'module-filter-chain/pffft.c' ,
33
+filter_chain_c = static_library('filter_chain_c',
34
+  'module-filter-chain/pffft.c',
35
+   'module-filter-chain/dsp-ops.c',
36
+   'module-filter-chain/dsp-ops-c.c' ,
37
   c_args : simd_cargs, '-O3', '-DPFFFT_SIMD_DISABLE',
38
   dependencies :  spa_dep ,
39
   install : false
40
 )
41
-simd_dependencies += pffft_c
42
+simd_dependencies += filter_chain_c
43
 
44
 filter_chain_sources = 
45
   'module-filter-chain.c',
46
pipewire-0.3.60.tar.gz/src/modules/module-client-node/client-node.c -> pipewire-0.3.61.tar.gz/src/modules/module-client-node/client-node.c Changed
69
 
1
@@ -744,7 +744,7 @@
2
    struct node *this = &impl->node;
3
    struct port *p;
4
    struct mix *mix;
5
-   uint32_t i, j, peer_id;
6
+   uint32_t i, j;
7
    struct pw_client_node_buffer *mb;
8
 
9
    p = GET_PORT(this, direction, port_id);
10
@@ -762,8 +762,6 @@
11
    if ((mix = find_mix(p, mix_id)) == NULL || !mix->valid)
12
        return -EINVAL;
13
 
14
-   peer_id = mix->peer_id;
15
-
16
    if (direction == SPA_DIRECTION_OUTPUT) {
17
        mix_id = SPA_ID_INVALID;
18
        if ((mix = find_mix(p, mix_id)) == NULL || !mix->valid)
19
@@ -881,10 +879,6 @@
20
    }
21
    mix->n_buffers = n_buffers;
22
 
23
-   if (this->resource->version >= 4)
24
-       pw_client_node_resource_port_set_mix_info(this->resource,
25
-                        direction, port_id, mix_id,
26
-                        peer_id, NULL);
27
    return pw_client_node_resource_port_use_buffers(this->resource,
28
                         direction, port_id, mix_id, flags,
29
                         n_buffers, mb);
30
@@ -1486,6 +1480,7 @@
31
    struct port *p = object;
32
    struct pw_impl_port *port = p->port;
33
    struct impl *impl = port->owner_data;
34
+   struct node *this = &impl->node;
35
    struct pw_impl_port_mix *mix;
36
 
37
    mix = pw_map_lookup(&port->mix_port_map, mix_id);
38
@@ -1497,6 +1492,11 @@
39
            mix->io = data;
40
        else
41
            mix->io = NULL;
42
+
43
+       if (mix->io != NULL && this->resource && this->resource->version >= 4)
44
+           pw_client_node_resource_port_set_mix_info(this->resource,
45
+                        direction, port->port_id,
46
+                        mix->port.port_id, mix->peer_id, NULL);
47
    }
48
 
49
    return do_port_set_io(impl,
50
@@ -1558,14 +1558,14 @@
51
    struct impl *impl = data;
52
    struct port *p = pw_impl_port_get_user_data(port);
53
 
54
-   pw_impl_port_set_mix(port, &p->mix_node,
55
-           PW_IMPL_PORT_MIX_FLAG_MULTI |
56
-           PW_IMPL_PORT_MIX_FLAG_MIX_ONLY);
57
-
58
    port->flags |= PW_IMPL_PORT_FLAG_NO_MIXER;
59
 
60
    port->impl = SPA_CALLBACKS_INIT(&port_impl, p);
61
    port->owner_data = impl;
62
+
63
+   pw_impl_port_set_mix(port, &p->mix_node,
64
+           PW_IMPL_PORT_MIX_FLAG_MULTI |
65
+           PW_IMPL_PORT_MIX_FLAG_MIX_ONLY);
66
 }
67
 
68
 static void node_port_removed(void *data, struct pw_impl_port *port)
69
pipewire-0.3.60.tar.gz/src/modules/module-client-node/protocol-native.c -> pipewire-0.3.61.tar.gz/src/modules/module-client-node/protocol-native.c Changed
20
 
1
@@ -556,6 +556,8 @@
2
                          SPA_POD_Id(&m->type),
3
                          SPA_POD_Int(&m->size), NULL) < 0)
4
                return -EINVAL;
5
+
6
+           m->data = NULL;
7
        }
8
        if (spa_pod_parser_get(&prs,
9
                    SPA_POD_Int(&buf->n_datas), NULL) < 0)
10
@@ -576,7 +578,9 @@
11
                          SPA_POD_Int(&d->maxsize), NULL) < 0)
12
                return -EINVAL;
13
 
14
+           d->fd = -1;
15
            d->data = SPA_UINT32_TO_PTR(data_id);
16
+           d->chunk = NULL;
17
        }
18
    }
19
    pw_proxy_notify(proxy, struct pw_client_node_events, port_use_buffers, 0,
20
pipewire-0.3.60.tar.gz/src/modules/module-filter-chain/builtin_plugin.c -> pipewire-0.3.61.tar.gz/src/modules/module-filter-chain/builtin_plugin.c Changed
75
 
1
@@ -40,6 +40,9 @@
2
 #include "biquad.h"
3
 #include "pffft.h"
4
 #include "convolver.h"
5
+#include "dsp-ops.h"
6
+
7
+static struct dsp_ops dsp_ops;
8
 
9
 struct builtin {
10
    unsigned long rate;
11
@@ -82,7 +85,7 @@
12
 {
13
    struct builtin *impl = Instance;
14
    float *in = impl->port1, *out = impl->port0;
15
-   memcpy(out, in, SampleCount * sizeof(float));
16
+   dsp_ops_copy(&dsp_ops, out, in, SampleCount);
17
 }
18
 
19
 static struct fc_port copy_ports = {
20
@@ -112,10 +115,10 @@
21
 static void mixer_run(void * Instance, unsigned long SampleCount)
22
 {
23
    struct builtin *impl = Instance;
24
-   int i;
25
-   unsigned long j;
26
+   int i, n_src = 0;
27
    float *out = impl->port0;
28
-   bool first = true;
29
+   const void *src8;
30
+   float gains8;
31
 
32
    if (out == NULL)
33
        return;
34
@@ -127,24 +130,10 @@
35
        if (in == NULL || gain == 0.0f)
36
            continue;
37
 
38
-       if (first) {
39
-           if (gain == 1.0f)
40
-               memcpy(out, in, SampleCount * sizeof(float));
41
-           else
42
-               for (j = 0; j < SampleCount; j++)
43
-                   outj = inj * gain;
44
-           first = false;
45
-       } else {
46
-           if (gain == 1.0f)
47
-               for (j = 0; j < SampleCount; j++)
48
-                   outj += inj;
49
-           else
50
-               for (j = 0; j < SampleCount; j++)
51
-                   outj += inj * gain;
52
-       }
53
+       srcn_src = in;
54
+       gainsn_src++ = gain;
55
    }
56
-   if (first)
57
-       memset(out, 0, SampleCount * sizeof(float));
58
+   dsp_ops_mix_gain(&dsp_ops, out, src, gains, n_src, SampleCount);
59
 }
60
 
61
 static struct fc_port mixer_ports = {
62
@@ -941,7 +930,11 @@
63
        const char *plugin, const char *config)
64
 {
65
    struct spa_cpu *cpu_iface;
66
+   uint32_t cpu_flags;
67
    cpu_iface = spa_support_find(support, n_support, SPA_TYPE_INTERFACE_CPU);
68
-   pffft_select_cpu(cpu_iface ? spa_cpu_get_flags(cpu_iface) : 0);
69
+   cpu_flags = cpu_iface ? spa_cpu_get_flags(cpu_iface) : 0;
70
+   dsp_ops.cpu_flags = cpu_flags;
71
+   dsp_ops_init(&dsp_ops);
72
+   pffft_select_cpu(cpu_flags);
73
    return &builtin_plugin;
74
 }
75
pipewire-0.3.61.tar.gz/src/modules/module-filter-chain/dsp-ops-c.c Added
102
 
1
@@ -0,0 +1,100 @@
2
+/* Spa
3
+ *
4
+ * Copyright © 2022 Wim Taymans
5
+ *
6
+ * Permission is hereby granted, free of charge, to any person obtaining a
7
+ * copy of this software and associated documentation files (the "Software"),
8
+ * to deal in the Software without restriction, including without limitation
9
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10
+ * and/or sell copies of the Software, and to permit persons to whom the
11
+ * Software is furnished to do so, subject to the following conditions:
12
+ *
13
+ * The above copyright notice and this permission notice (including the next
14
+ * paragraph) shall be included in all copies or substantial portions of the
15
+ * Software.
16
+ *
17
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
20
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
23
+ * DEALINGS IN THE SOFTWARE.
24
+ */
25
+
26
+#include <string.h>
27
+#include <stdio.h>
28
+#include <math.h>
29
+
30
+#include <spa/utils/defs.h>
31
+
32
+#include "dsp-ops.h"
33
+
34
+static inline void dsp_clear_c(struct dsp_ops *ops, void * SPA_RESTRICT dst, uint32_t n_samples)
35
+{
36
+   memset(dst, 0, sizeof(float) * n_samples);
37
+}
38
+
39
+static inline void dsp_add_c(struct dsp_ops *ops, void * SPA_RESTRICT dst,
40
+           const void * SPA_RESTRICT src, uint32_t n_samples)
41
+{
42
+   uint32_t i;
43
+   const float *s = src;
44
+   float *d = dst;
45
+   for (i = 0; i < n_samples; i++)
46
+       di += si;
47
+}
48
+
49
+static inline void dsp_gain_c(struct dsp_ops *ops, void * SPA_RESTRICT dst,
50
+           const void * SPA_RESTRICT src, float gain, uint32_t n_samples)
51
+{
52
+   uint32_t i;
53
+   const float *s = src;
54
+   float *d = dst;
55
+   for (i = 0; i < n_samples; i++)
56
+       di = si * gain;
57
+}
58
+
59
+static inline void dsp_gain_add_c(struct dsp_ops *ops, void * SPA_RESTRICT dst,
60
+           const void * SPA_RESTRICT src, float gain, uint32_t n_samples)
61
+{
62
+   uint32_t i;
63
+   const float *s = src;
64
+   float *d = dst;
65
+   for (i = 0; i < n_samples; i++)
66
+       di += si * gain;
67
+}
68
+
69
+
70
+void dsp_copy_c(struct dsp_ops *ops, void * SPA_RESTRICT dst,
71
+           const void * SPA_RESTRICT src, uint32_t n_samples)
72
+{
73
+   if (dst != src)
74
+       spa_memcpy(dst, src, sizeof(float) * n_samples);
75
+}
76
+
77
+void dsp_mix_gain_c(struct dsp_ops *ops,
78
+       void * SPA_RESTRICT dst,
79
+       const void * SPA_RESTRICT src,
80
+       float gain, uint32_t n_src, uint32_t n_samples)
81
+{
82
+   uint32_t i;
83
+   if (n_src == 0) {
84
+       dsp_clear_c(ops, dst, n_samples);
85
+   } else if (n_src == 1) {
86
+       if (dst != src0)
87
+           dsp_copy_c(ops, dst, src0, n_samples);
88
+   } else {
89
+       if (gain0 == 1.0f)
90
+           dsp_copy_c(ops, dst, src0, n_samples);
91
+       else
92
+           dsp_gain_c(ops, dst, src0, gain0, n_samples);
93
+
94
+       for (i = 1; i < n_src; i++) {
95
+           if (gaini == 1.0f)
96
+               dsp_add_c(ops, dst, srci, n_samples);
97
+           else
98
+               dsp_gain_add_c(ops, dst, srci, gaini, n_samples);
99
+       }
100
+   }
101
+}
102
pipewire-0.3.61.tar.gz/src/modules/module-filter-chain/dsp-ops-sse.c Added
93
 
1
@@ -0,0 +1,91 @@
2
+/* Spa
3
+ *
4
+ * Copyright © 2022 Wim Taymans
5
+ *
6
+ * Permission is hereby granted, free of charge, to any person obtaining a
7
+ * copy of this software and associated documentation files (the "Software"),
8
+ * to deal in the Software without restriction, including without limitation
9
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10
+ * and/or sell copies of the Software, and to permit persons to whom the
11
+ * Software is furnished to do so, subject to the following conditions:
12
+ *
13
+ * The above copyright notice and this permission notice (including the next
14
+ * paragraph) shall be included in all copies or substantial portions of the
15
+ * Software.
16
+ *
17
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
20
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
23
+ * DEALINGS IN THE SOFTWARE.
24
+ */
25
+
26
+#include <string.h>
27
+#include <stdio.h>
28
+#include <math.h>
29
+
30
+#include <spa/utils/defs.h>
31
+
32
+#include "dsp-ops.h"
33
+
34
+#include <xmmintrin.h>
35
+
36
+void dsp_mix_gain_sse(struct dsp_ops *ops,
37
+       void * SPA_RESTRICT dst,
38
+       const void * SPA_RESTRICT src,
39
+       float gain, uint32_t n_src, uint32_t n_samples)
40
+{
41
+   if (n_src == 0) {
42
+       memset(dst, 0, n_samples * sizeof(float));
43
+   } else if (n_src == 1) {
44
+       if (dst != src0)
45
+           spa_memcpy(dst, src0, n_samples * sizeof(float));
46
+   } else {
47
+       uint32_t n, i, unrolled;
48
+       __m128 in4, g;
49
+       const float **s = (const float **)src;
50
+       float *d = dst;
51
+
52
+       if (SPA_LIKELY(SPA_IS_ALIGNED(dst, 16))) {
53
+           unrolled = n_samples & ~15;
54
+           for (i = 0; i < n_src; i++) {
55
+               if (SPA_UNLIKELY(!SPA_IS_ALIGNED(srci, 16))) {
56
+                   unrolled = 0;
57
+                   break;
58
+               }
59
+           }
60
+       } else
61
+           unrolled = 0;
62
+
63
+       for (n = 0; n < unrolled; n += 16) {
64
+           g = _mm_set1_ps(gain0);
65
+           in0 = _mm_mul_ps(g, _mm_load_ps(&s0n+ 0));
66
+           in1 = _mm_mul_ps(g, _mm_load_ps(&s0n+ 4));
67
+           in2 = _mm_mul_ps(g, _mm_load_ps(&s0n+ 8));
68
+           in3 = _mm_mul_ps(g, _mm_load_ps(&s0n+12));
69
+
70
+           for (i = 1; i < n_src; i++) {
71
+               g = _mm_set1_ps(gaini);
72
+               in0 = _mm_add_ps(in0, _mm_mul_ps(g, _mm_load_ps(&sin+ 0)));
73
+               in1 = _mm_add_ps(in1, _mm_mul_ps(g, _mm_load_ps(&sin+ 4)));
74
+               in2 = _mm_add_ps(in2, _mm_mul_ps(g, _mm_load_ps(&sin+ 8)));
75
+               in3 = _mm_add_ps(in3, _mm_mul_ps(g, _mm_load_ps(&sin+12)));
76
+           }
77
+           _mm_store_ps(&dn+ 0, in0);
78
+           _mm_store_ps(&dn+ 4, in1);
79
+           _mm_store_ps(&dn+ 8, in2);
80
+           _mm_store_ps(&dn+12, in3);
81
+       }
82
+       for (; n < n_samples; n++) {
83
+           g = _mm_set_ss(gain0);
84
+           in0 = _mm_mul_ss(g, _mm_load_ss(&s0n));
85
+           for (i = 1; i < n_src; i++) {
86
+               g = _mm_set_ss(gaini);
87
+               in0 = _mm_add_ss(in0, _mm_mul_ss(g, _mm_load_ss(&sin)));
88
+           }
89
+           _mm_store_ss(&dn, in0);
90
+       }
91
+   }
92
+}
93
pipewire-0.3.61.tar.gz/src/modules/module-filter-chain/dsp-ops.c Added
94
 
1
@@ -0,0 +1,92 @@
2
+/* Spa
3
+ *
4
+ * Copyright © 2022 Wim Taymans
5
+ *
6
+ * Permission is hereby granted, free of charge, to any person obtaining a
7
+ * copy of this software and associated documentation files (the "Software"),
8
+ * to deal in the Software without restriction, including without limitation
9
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10
+ * and/or sell copies of the Software, and to permit persons to whom the
11
+ * Software is furnished to do so, subject to the following conditions:
12
+ *
13
+ * The above copyright notice and this permission notice (including the next
14
+ * paragraph) shall be included in all copies or substantial portions of the
15
+ * Software.
16
+ *
17
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
20
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
23
+ * DEALINGS IN THE SOFTWARE.
24
+ */
25
+
26
+#include <string.h>
27
+#include <stdio.h>
28
+#include <math.h>
29
+
30
+#include <spa/support/cpu.h>
31
+#include <spa/utils/defs.h>
32
+#include <spa/param/audio/format-utils.h>
33
+
34
+#include "dsp-ops.h"
35
+
36
+struct dsp_info {
37
+   uint32_t cpu_flags;
38
+
39
+   void (*copy) (struct dsp_ops *ops,
40
+           void * SPA_RESTRICT dst,
41
+           const void * SPA_RESTRICT src, uint32_t n_samples);
42
+   void (*mix_gain) (struct dsp_ops *ops,
43
+           void * SPA_RESTRICT dst,
44
+           const void * SPA_RESTRICT src,
45
+           float gain, uint32_t n_src, uint32_t n_samples);
46
+};
47
+
48
+static struct dsp_info dsp_table =
49
+{
50
+#if defined (HAVE_SSE)
51
+   { SPA_CPU_FLAG_SSE,
52
+       .copy = dsp_copy_c,
53
+       .mix_gain = dsp_mix_gain_sse,
54
+   },
55
+#endif
56
+   { 0,
57
+       .copy = dsp_copy_c,
58
+       .mix_gain = dsp_mix_gain_c,
59
+   },
60
+};
61
+
62
+#define MATCH_CPU_FLAGS(a,b)   ((a) == 0 || ((a) & (b)) == a)
63
+
64
+static const struct dsp_info *find_dsp_info(uint32_t cpu_flags)
65
+{
66
+   SPA_FOR_EACH_ELEMENT_VAR(dsp_table, t) {
67
+       if (MATCH_CPU_FLAGS(t->cpu_flags, cpu_flags))
68
+           return t;
69
+   }
70
+   return NULL;
71
+}
72
+
73
+static void impl_dsp_ops_free(struct dsp_ops *ops)
74
+{
75
+   spa_zero(*ops);
76
+}
77
+
78
+int dsp_ops_init(struct dsp_ops *ops)
79
+{
80
+   const struct dsp_info *info;
81
+
82
+   info = find_dsp_info(ops->cpu_flags);
83
+   if (info == NULL)
84
+       return -ENOTSUP;
85
+
86
+   ops->priv = info;
87
+   ops->cpu_flags = info->cpu_flags;
88
+   ops->copy = info->copy;
89
+   ops->mix_gain = info->mix_gain;
90
+   ops->free = impl_dsp_ops_free;
91
+
92
+   return 0;
93
+}
94
pipewire-0.3.61.tar.gz/src/modules/module-filter-chain/dsp-ops.h Added
64
 
1
@@ -0,0 +1,62 @@
2
+/* Spa
3
+ *
4
+ * Copyright © 2022 Wim Taymans
5
+ *
6
+ * Permission is hereby granted, free of charge, to any person obtaining a
7
+ * copy of this software and associated documentation files (the "Software"),
8
+ * to deal in the Software without restriction, including without limitation
9
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10
+ * and/or sell copies of the Software, and to permit persons to whom the
11
+ * Software is furnished to do so, subject to the following conditions:
12
+ *
13
+ * The above copyright notice and this permission notice (including the next
14
+ * paragraph) shall be included in all copies or substantial portions of the
15
+ * Software.
16
+ *
17
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
20
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
23
+ * DEALINGS IN THE SOFTWARE.
24
+ */
25
+
26
+#include <spa/utils/defs.h>
27
+
28
+struct dsp_ops {
29
+   uint32_t cpu_flags;
30
+
31
+   void (*clear) (struct dsp_ops *ops, void * SPA_RESTRICT dst, uint32_t n_samples);
32
+   void (*copy) (struct dsp_ops *ops,
33
+           void * SPA_RESTRICT dst,
34
+           const void * SPA_RESTRICT src, uint32_t n_samples);
35
+   void (*mix_gain) (struct dsp_ops *ops,
36
+           void * SPA_RESTRICT dst,
37
+           const void * SPA_RESTRICT src,
38
+           float gain, uint32_t n_src, uint32_t n_samples);
39
+   void (*free) (struct dsp_ops *ops);
40
+
41
+   const void *priv;
42
+};
43
+
44
+int dsp_ops_init(struct dsp_ops *ops);
45
+
46
+#define dsp_ops_copy(ops,...)      (ops)->copy(ops, __VA_ARGS__)
47
+#define dsp_ops_mix_gain(ops,...)  (ops)->mix_gain(ops, __VA_ARGS__)
48
+#define dsp_ops_free(ops)      (ops)->free(ops)
49
+
50
+
51
+#define MAKE_COPY_FUNC(arch) \
52
+void dsp_copy_##arch(struct dsp_ops *ops, void * SPA_RESTRICT dst, \
53
+           const void * SPA_RESTRICT src, uint32_t n_samples)
54
+#define MAKE_MIX_GAIN_FUNC(arch) \
55
+void dsp_mix_gain_##arch(struct dsp_ops *ops, void * SPA_RESTRICT dst, \
56
+   const void * SPA_RESTRICT src, float gain, uint32_t n_src, uint32_t n_samples)
57
+
58
+
59
+MAKE_COPY_FUNC(c);
60
+MAKE_MIX_GAIN_FUNC(c);
61
+#if defined (HAVE_SSE)
62
+MAKE_MIX_GAIN_FUNC(sse);
63
+#endif
64
pipewire-0.3.60.tar.gz/src/modules/module-protocol-pulse/internal.h -> pipewire-0.3.61.tar.gz/src/modules/module-protocol-pulse/internal.h Changed
45
 
1
@@ -36,6 +36,7 @@
2
 #include <pipewire/private.h>
3
 
4
 #include "format.h"
5
+#include "server.h"
6
 
7
 struct pw_loop;
8
 struct pw_context;
9
@@ -52,6 +53,7 @@
10
    struct sample_spec sample_spec;
11
    struct channel_map channel_map;
12
    uint32_t quantum_limit;
13
+   uint32_t idle_timeout;
14
 };
15
 
16
 struct stats {
17
@@ -72,6 +74,7 @@
18
 
19
    struct ratelimit rate_limit;
20
 
21
+   struct spa_hook_list hooks;
22
    struct spa_list servers;
23
 
24
    struct pw_work_queue *work_queue;
25
@@ -85,6 +88,19 @@
26
    struct stats stat;
27
 };
28
 
29
+struct impl_events {
30
+#define VERSION_IMPL_EVENTS    0
31
+   uint32_t version;
32
+
33
+   void (*server_started) (void *data, struct server *server);
34
+
35
+   void (*server_stopped) (void *data, struct server *server);
36
+};
37
+
38
+void impl_add_listener(struct impl *impl,
39
+       struct spa_hook *listener,
40
+       const struct impl_events *events, void *data);
41
+
42
 extern bool debug_messages;
43
 
44
 void broadcast_subscribe_event(struct impl *impl, uint32_t mask, uint32_t event, uint32_t id);
45
pipewire-0.3.60.tar.gz/src/modules/module-protocol-pulse/modules/module-zeroconf-publish.c -> pipewire-0.3.61.tar.gz/src/modules/module-protocol-pulse/modules/module-zeroconf-publish.c Changed
201
 
1
@@ -24,6 +24,7 @@
2
  */
3
 
4
 #include <sys/utsname.h>
5
+#include <arpa/inet.h>
6
 
7
 #include <pipewire/pipewire.h>
8
 
9
@@ -32,6 +33,7 @@
10
 #include "../manager.h"
11
 #include "../module.h"
12
 #include "../pulse-server.h"
13
+#include "../server.h"
14
 #include "../../module-zeroconf-discover/avahi-poll.h"
15
 
16
 #include <avahi-client/client.h>
17
@@ -83,6 +85,7 @@
18
    struct pw_properties *props;
19
 
20
    char service_nameAVAHI_LABEL_MAX;
21
+   unsigned published:1;
22
 };
23
 
24
 struct module_zeroconf_publish_data {
25
@@ -93,8 +96,7 @@
26
 
27
    struct spa_hook core_listener;
28
    struct spa_hook manager_listener;
29
-
30
-   unsigned int port;
31
+   struct spa_hook impl_listener;
32
 
33
    AvahiPoll *avahi_poll;
34
    AvahiClient *client;
35
@@ -151,6 +153,7 @@
36
 {
37
    spa_list_remove(&s->link);
38
    spa_list_append(&s->userdata->pending, &s->link);
39
+   s->published = false;
40
 }
41
 
42
 static void unpublish_all_services(struct module_zeroconf_publish_data *d)
43
@@ -315,6 +318,11 @@
44
    struct service *s = userdata;
45
 
46
    spa_assert(s);
47
+   if (!s->published) {
48
+       pw_log_info("cancel unpublished service: %s", s->service_name);
49
+       clear_entry_group(s);
50
+       return;
51
+   }
52
 
53
    switch (state) {
54
    case AVAHI_ENTRY_GROUP_ESTABLISHED:
55
@@ -389,17 +397,47 @@
56
    return txt;
57
 }
58
 
59
+static int find_port(struct service *s, int *proto, uint16_t *port)
60
+{
61
+   struct module_zeroconf_publish_data *d = s->userdata;
62
+   struct impl *impl = d->module->impl;
63
+   struct server *server;
64
+
65
+   spa_list_for_each(server, &impl->servers, link) {
66
+       if (server->addr.ss_family == AF_INET) {
67
+           *proto = AVAHI_PROTO_INET;
68
+           *port = ntohs(((struct sockaddr_in*) &server->addr)->sin_port);
69
+           return 0;
70
+       } else if (server->addr.ss_family == AF_INET6) {
71
+           *proto = AVAHI_PROTO_INET6;
72
+           *port = ntohs(((struct sockaddr_in6*) &server->addr)->sin6_port);
73
+           return 0;
74
+       }
75
+   }
76
+   return -ENODEV;
77
+}
78
+
79
 static void publish_service(struct service *s)
80
 {
81
-   if (!s->userdata->client || avahi_client_get_state(s->userdata->client) != AVAHI_CLIENT_S_RUNNING)
82
+   struct module_zeroconf_publish_data *d = s->userdata;
83
+   int proto;
84
+   uint16_t port;
85
+
86
+   if (find_port(s, &proto, &port) < 0)
87
+       return;
88
+
89
+   pw_log_debug("found proto:%d port:%d", proto, port);
90
+
91
+   if (!d->client || avahi_client_get_state(d->client) != AVAHI_CLIENT_S_RUNNING)
92
        return;
93
 
94
+   s->published = true;
95
    if (!s->entry_group) {
96
-       s->entry_group = avahi_entry_group_new(s->userdata->client, service_entry_group_callback, s);
97
+       s->entry_group = avahi_entry_group_new(d->client, service_entry_group_callback, s);
98
        if (s->entry_group == NULL) {
99
            pw_log_error("avahi_entry_group_new(): %s",
100
-                   avahi_strerror(avahi_client_errno(s->userdata->client)));
101
-           return;
102
+                   avahi_strerror(avahi_client_errno(d->client)));
103
+           goto error;
104
        }
105
    } else {
106
        avahi_entry_group_reset(s->entry_group);
107
@@ -410,22 +448,22 @@
108
 
109
    if (avahi_entry_group_add_service_strlst(
110
                s->entry_group,
111
-               AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC,
112
+               AVAHI_IF_UNSPEC, proto,
113
                0,
114
                s->service_name,
115
                s->service_type,
116
                NULL,
117
                NULL,
118
-               s->userdata->port,
119
+               port,
120
                s->txt) < 0) {
121
        pw_log_error("avahi_entry_group_add_service_strlst(): %s",
122
-           avahi_strerror(avahi_client_errno(s->userdata->client)));
123
-       return;
124
+           avahi_strerror(avahi_client_errno(d->client)));
125
+       goto error;
126
    }
127
 
128
    if (avahi_entry_group_add_service_subtype(
129
                s->entry_group,
130
-               AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC,
131
+               AVAHI_IF_UNSPEC, proto,
132
                0,
133
                s->service_name,
134
                s->service_type,
135
@@ -434,35 +472,40 @@
136
                (s->subtype == SUBTYPE_HARDWARE ? SERVICE_SUBTYPE_SOURCE_HARDWARE : (s->subtype == SUBTYPE_VIRTUAL ? SERVICE_SUBTYPE_SOURCE_VIRTUAL : SERVICE_SUBTYPE_SOURCE_MONITOR))) < 0) {
137
 
138
        pw_log_error("avahi_entry_group_add_service_subtype(): %s",
139
-           avahi_strerror(avahi_client_errno(s->userdata->client)));
140
-       return;
141
+           avahi_strerror(avahi_client_errno(d->client)));
142
+       goto error;
143
    }
144
 
145
    if (!s->is_sink && s->subtype != SUBTYPE_MONITOR) {
146
        if (avahi_entry_group_add_service_subtype(
147
                    s->entry_group,
148
-                   AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC,
149
+                   AVAHI_IF_UNSPEC, proto,
150
                    0,
151
                    s->service_name,
152
                    SERVICE_TYPE_SOURCE,
153
                    NULL,
154
                    SERVICE_SUBTYPE_SOURCE_NON_MONITOR) < 0) {
155
            pw_log_error("avahi_entry_group_add_service_subtype(): %s",
156
-                   avahi_strerror(avahi_client_errno(s->userdata->client)));
157
-           return;
158
+                   avahi_strerror(avahi_client_errno(d->client)));
159
+           goto error;
160
        }
161
    }
162
 
163
    if (avahi_entry_group_commit(s->entry_group) < 0) {
164
        pw_log_error("avahi_entry_group_commit(): %s",
165
-               avahi_strerror(avahi_client_errno(s->userdata->client)));
166
-       return;
167
+               avahi_strerror(avahi_client_errno(d->client)));
168
+       goto error;
169
    }
170
 
171
    spa_list_remove(&s->link);
172
-   spa_list_append(&s->userdata->published, &s->link);
173
+   spa_list_append(&d->published, &s->link);
174
 
175
    pw_log_info("created service: %s", s->service_name);
176
+   return;
177
+
178
+error:
179
+   s->published = false;
180
+   return;
181
 }
182
 
183
 static void publish_pending(struct module_zeroconf_publish_data *data)
184
@@ -571,6 +614,28 @@
185
    .removed = manager_removed,
186
 };
187
 
188
+
189
+static void impl_server_started(void *data, struct server *server)
190
+{
191
+   struct module_zeroconf_publish_data *d = data;
192
+   pw_log_info("a new server is started, try publish");
193
+   publish_pending(d);
194
+}
195
+
196
+static void impl_server_stopped(void *data, struct server *server)
197
+{
198
+   struct module_zeroconf_publish_data *d = data;
199
+   pw_log_info("a server stopped, try republish");
200
+   unpublish_all_services(d);
201
pipewire-0.3.60.tar.gz/src/modules/module-protocol-pulse/pulse-server.c -> pipewire-0.3.61.tar.gz/src/modules/module-protocol-pulse/pulse-server.c Changed
164
 
1
@@ -85,6 +85,7 @@
2
 #define DEFAULT_MIN_QUANTUM    "256/48000"
3
 #define DEFAULT_FORMAT     "F32"
4
 #define DEFAULT_POSITION   " FL FR "
5
+#define DEFAULT_IDLE_TIMEOUT   "5"
6
 
7
 #define MAX_FORMATS    32
8
 /* The max amount of data we send in one block when capturing. In PulseAudio this
9
@@ -1241,7 +1242,7 @@
10
                SPA_PROP_mute, 1, &val, 0);
11
        }
12
        if (stream->corked)
13
-           pw_stream_set_active(stream->stream, false);
14
+           stream_set_paused(stream, true, "cork after create");
15
 
16
        /* if peer exists, reply immediately, otherwise reply when the link is created */
17
        peer = find_linked(stream->client->manager, stream->id, stream->direction);
18
@@ -1276,6 +1277,7 @@
19
    uint32_t minreq;
20
    uint32_t quantum;
21
    unsigned int underrun:1;
22
+   unsigned int idle:1;
23
 };
24
 
25
 static int
26
@@ -1315,6 +1317,17 @@
27
            else
28
                stream_send_started(stream);
29
        }
30
+       if (pd->idle) {
31
+           if (!stream->is_idle) {
32
+               stream->idle_time = stream->timestamp;
33
+           } else if (!stream->is_paused &&
34
+               stream->idle_timeout_sec > 0 &&
35
+               stream->timestamp - stream->idle_time >
36
+                   (stream->idle_timeout_sec * SPA_NSEC_PER_SEC)) {
37
+               stream_set_paused(stream, true, "long underrun");
38
+           }
39
+       }
40
+       stream->is_idle = pd->idle;
41
        stream->playing_for += pd->playing_for;
42
        if (stream->underrun_for != (uint64_t)-1)
43
            stream->underrun_for += pd->underrun_for;
44
@@ -1433,12 +1446,14 @@
45
                        stream->buffer, MAXLENGTH,
46
                        index % MAXLENGTH,
47
                        p, avail);
48
-                   index += avail;
49
-                   pd.read_inc = avail;
50
-                   spa_ringbuffer_read_update(&stream->ring, index);
51
                }
52
+               index += size;
53
+               pd.read_inc = size;
54
+               spa_ringbuffer_read_update(&stream->ring, index);
55
+
56
                pd.playing_for = size;
57
            }
58
+           pd.idle = true;
59
            pw_log_debug("%p: %s underrun read:%u avail:%d max:%u",
60
                    stream, client->name, index, avail, minreq);
61
        } else {
62
@@ -1523,7 +1538,7 @@
63
        reply_simple_ack(stream->client, stream->drain_tag);
64
        stream->drain_tag = 0;
65
 
66
-       pw_stream_set_active(stream->stream, true);
67
+       stream_set_paused(stream, false, "complete drain");
68
    }
69
 }
70
 
71
@@ -2701,7 +2716,7 @@
72
        return -ENOENT;
73
 
74
    stream->corked = cork;
75
-   pw_stream_set_active(stream->stream, !cork);
76
+   stream_set_paused(stream, cork, "cork request");
77
    if (cork) {
78
        stream->is_underrun = true;
79
    } else {
80
@@ -3461,7 +3476,7 @@
81
 
82
    stream->drain_tag = tag;
83
    stream->draining = true;
84
-   pw_stream_set_active(stream->stream, true);
85
+   stream_set_paused(stream, false, "drain start");
86
 
87
    return 0;
88
 }
89
@@ -5460,6 +5475,8 @@
90
    pw_map_for_each(&impl->samples, impl_free_sample, impl);
91
    pw_map_clear(&impl->samples);
92
 
93
+   spa_hook_list_clean(&impl->hooks);
94
+
95
 #ifdef HAVE_DBUS
96
    if (impl->dbus_name) {
97
        dbus_release_name(impl->dbus_name);
98
@@ -5499,8 +5516,10 @@
99
    if (props == NULL ||
100
        (str = pw_properties_get(props, key)) == NULL)
101
        str = def;
102
-   if (sscanf(str, "%u/%u", &res->num, &res->denom) != 2 || res->denom == 0)
103
-       return -EINVAL;
104
+   if (sscanf(str, "%u/%u", &res->num, &res->denom) != 2 || res->denom == 0) {
105
+       pw_log_warn(": invalid fraction %s, default to %s", str, def);
106
+       sscanf(def, "%u/%u", &res->num, &res->denom);
107
+   }
108
    pw_log_info(": defaults: %s = %u/%u", key, res->num, res->denom);
109
    return 0;
110
 }
111
@@ -5540,7 +5559,21 @@
112
        pw_log_warn(": unknown format %s, default to %s", str, def);
113
        res->format = format_name2id(def);
114
    }
115
-   pw_log_info(": defaults: %s = %s", key, str);
116
+   pw_log_info(": defaults: %s = %s", key, format_id2name(res->format));
117
+   return 0;
118
+}
119
+static int parse_uint32(struct pw_properties *props, const char *key, const char *def,
120
+       uint32_t *res)
121
+{
122
+   const char *str;
123
+   if (props == NULL ||
124
+       (str = pw_properties_get(props, key)) == NULL)
125
+       str = def;
126
+   if (!spa_atou32(str, res, 0)) {
127
+       pw_log_warn(": invalid uint32_t %s, default to %s", str, def);
128
+       spa_atou32(def, res, 0);
129
+   }
130
+   pw_log_info(": defaults: %s = %u", key, *res);
131
    return 0;
132
 }
133
 
134
@@ -5554,6 +5587,7 @@
135
    parse_frac(props, "pulse.min.quantum", DEFAULT_MIN_QUANTUM, &def->min_quantum);
136
    parse_format(props, "pulse.default.format", DEFAULT_FORMAT, &def->sample_spec);
137
    parse_position(props, "pulse.default.position", DEFAULT_POSITION, &def->channel_map);
138
+   parse_uint32(props, "pulse.idle.timeout", DEFAULT_IDLE_TIMEOUT, &def->idle_timeout);
139
    def->sample_spec.channels = def->channel_map.channels;
140
    def->quantum_limit = 8192;
141
 }
142
@@ -5598,6 +5632,7 @@
143
 
144
    impl->work_queue = pw_context_get_work_queue(context);
145
 
146
+   spa_hook_list_init(&impl->hooks);
147
    spa_list_init(&impl->servers);
148
    impl->rate_limit.interval = 2 * SPA_NSEC_PER_SEC;
149
    impl->rate_limit.burst = 1;
150
@@ -5649,6 +5684,13 @@
151
    return NULL;
152
 }
153
 
154
+void impl_add_listener(struct impl *impl,
155
+       struct spa_hook *listener,
156
+       const struct impl_events *events, void *data)
157
+{
158
+   spa_hook_list_append(&impl->hooks, listener, events, data);
159
+}
160
+
161
 void *pw_protocol_pulse_get_user_data(struct pw_protocol_pulse *pulse)
162
 {
163
    return SPA_PTROFF(pulse, sizeof(struct impl), void);
164
pipewire-0.3.60.tar.gz/src/modules/module-protocol-pulse/server.c -> pipewire-0.3.61.tar.gz/src/modules/module-protocol-pulse/server.c Changed
38
 
1
@@ -191,6 +191,9 @@
2
 
3
    stream_send_request(stream);
4
 
5
+   if (stream->is_paused && !stream->corked)
6
+       stream_set_paused(stream, false, "new data");
7
+
8
 finish:
9
    message_free(msg, false, false);
10
    return res;
11
@@ -899,7 +902,7 @@
12
 
13
 static int server_start(struct server *server, const struct sockaddr_storage *addr)
14
 {
15
-   const struct impl * const impl = server->impl;
16
+   struct impl * const impl = server->impl;
17
    int res = 0, fd;
18
 
19
    switch (addr->ss_family) {
20
@@ -924,6 +927,8 @@
21
        res = -errno;
22
        pw_log_error("server %p: can't create server source: %m", impl);
23
    }
24
+   if (res >= 0)
25
+       spa_hook_list_call(&impl->hooks, struct impl_events, server_started, 0, server);
26
 
27
    return res;
28
 }
29
@@ -1069,6 +1074,8 @@
30
        client_unref(c);
31
    }
32
 
33
+   spa_hook_list_call(&impl->hooks, struct impl_events, server_stopped, 0, server);
34
+
35
    if (server->source)
36
        pw_loop_destroy_source(impl->loop, server->source);
37
 
38
pipewire-0.3.60.tar.gz/src/modules/module-protocol-pulse/stream.c -> pipewire-0.3.61.tar.gz/src/modules/module-protocol-pulse/stream.c Changed
40
 
1
@@ -64,6 +64,7 @@
2
 {
3
    int res;
4
    struct defs *defs = &client->impl->defs;
5
+   const char *str;
6
 
7
    struct stream *stream = calloc(1, sizeof(*stream));
8
    if (stream == NULL)
9
@@ -90,6 +91,9 @@
10
    parse_frac(client->props, "pulse.default.req", &defs->default_req, &stream->default_req);
11
    parse_frac(client->props, "pulse.default.frag", &defs->default_frag, &stream->default_frag);
12
    parse_frac(client->props, "pulse.default.tlength", &defs->default_tlength, &stream->default_tlength);
13
+   stream->idle_timeout_sec = defs->idle_timeout;
14
+   if ((str = pw_properties_get(client->props, "pulse.idle.timeout")) != NULL)
15
+       spa_atou32(str, &stream->idle_timeout_sec, 0);
16
 
17
    switch (type) {
18
    case STREAM_TYPE_RECORD:
19
@@ -207,6 +211,20 @@
20
    return missing;
21
 }
22
 
23
+void stream_set_paused(struct stream *stream, bool paused, const char *reason)
24
+{
25
+   if (stream->is_paused == paused)
26
+       return;
27
+
28
+   if (reason && stream->client)
29
+       pw_log_info("%p: %s %s because of %s",
30
+               stream, stream->client->name,
31
+               paused ? "paused" : "resumed", reason);
32
+
33
+   stream->is_paused = paused;
34
+   pw_stream_set_active(stream->stream, !paused);
35
+}
36
+
37
 int stream_send_underflow(struct stream *stream, int64_t offset)
38
 {
39
    struct client *client = stream->client;
40
pipewire-0.3.60.tar.gz/src/modules/module-protocol-pulse/stream.h -> pipewire-0.3.61.tar.gz/src/modules/module-protocol-pulse/stream.h Changed
35
 
1
@@ -82,6 +82,7 @@
2
    uint64_t playing_for;
3
    uint64_t ticks_base;
4
    uint64_t timestamp;
5
+   uint64_t idle_time;
6
    int64_t delay;
7
 
8
    uint32_t last_quantum;
9
@@ -93,6 +94,7 @@
10
    struct spa_fraction default_frag;
11
    struct spa_fraction default_tlength;
12
    struct spa_fraction min_quantum;
13
+   uint32_t idle_timeout_sec;
14
 
15
    struct sample_spec ss;
16
    struct channel_map map;
17
@@ -115,6 +117,8 @@
18
    unsigned int in_prebuf:1;
19
    unsigned int killed:1;
20
    unsigned int pending:1;
21
+   unsigned int is_idle:1;
22
+   unsigned int is_paused:1;
23
 };
24
 
25
 struct stream *stream_new(struct client *client, enum stream_type type, uint32_t create_tag,
26
@@ -124,6 +128,8 @@
27
 void stream_flush(struct stream *stream);
28
 uint32_t stream_pop_missing(struct stream *stream);
29
 
30
+void stream_set_paused(struct stream *stream, bool paused, const char *reason);
31
+
32
 int stream_send_underflow(struct stream *stream, int64_t offset);
33
 int stream_send_overflow(struct stream *stream);
34
 int stream_send_killed(struct stream *stream);
35
pipewire-0.3.60.tar.gz/src/modules/module-pulse-tunnel.c -> pipewire-0.3.61.tar.gz/src/modules/module-pulse-tunnel.c Changed
26
 
1
@@ -72,7 +72,7 @@
2
  *                  (Default `sink`)
3
  * - `pulse.server.address`: the address of the PulseAudio server to tunnel to.
4
  * - `pulse.latency`: the latency to end-to-end latency in milliseconds to
5
- *                    maintain (Default 200ms).
6
+ *                    maintain (Default 200).
7
  * - `stream.props`: Extra properties for the local stream.
8
  *
9
  * ## General options
10
@@ -101,6 +101,7 @@
11
  *         tunnel.mode = sink
12
  *         # Set the remote address to tunnel to
13
  *         pulse.server.address = "tcp:192.168.1.126"
14
+ *         #pulse.latency = 200
15
  *         #audio.rate=<sample rate>
16
  *         #audio.channels=<number of channels>
17
  *         #audio.position=<channel map>
18
@@ -1012,6 +1013,7 @@
19
    copy_props(impl, props, PW_KEY_NODE_GROUP);
20
    copy_props(impl, props, PW_KEY_NODE_LATENCY);
21
    copy_props(impl, props, PW_KEY_NODE_VIRTUAL);
22
+   copy_props(impl, props, PW_KEY_NODE_NETWORK);
23
    copy_props(impl, props, PW_KEY_MEDIA_CLASS);
24
 
25
    parse_audio_info(impl->stream_props, &impl->info);
26
pipewire-0.3.60.tar.gz/src/modules/module-raop-sink.c -> pipewire-0.3.61.tar.gz/src/modules/module-raop-sink.c Changed
14
 
1
@@ -579,10 +579,10 @@
2
 
3
        if (ip_version == 4) {
4
            sa4.sin_port = htons(*port);
5
-           ret = bind(fd, &sa4, sizeof(sa4));
6
+           ret = bind(fd, (struct sockaddr*)&sa4, sizeof(sa4));
7
        } else {
8
            sa6.sin6_port = htons(*port);
9
-           ret = bind(fd, &sa6, sizeof(sa6));
10
+           ret = bind(fd, (struct sockaddr*)&sa6, sizeof(sa6));
11
        }
12
        if (ret == 0)
13
            break;
14
pipewire-0.3.60.tar.gz/src/modules/module-rtp-sink.c -> pipewire-0.3.61.tar.gz/src/modules/module-rtp-sink.c Changed
27
 
1
@@ -31,6 +31,7 @@
2
 #include <sys/ioctl.h>
3
 #include <arpa/inet.h>
4
 #include <netinet/ip.h>
5
+#include <netinet/in.h>
6
 #include <net/if.h>
7
 #include <ctype.h>
8
 
9
@@ -439,14 +440,14 @@
10
        if (setsockopt(fd, IPPROTO_IP, IP_MULTICAST_TTL, &val, sizeof(val)) < 0)
11
            pw_log_warn("setsockopt(IP_MULTICAST_TTL) failed: %m");
12
    }
13
-
14
+#ifdef SO_PRIORITY
15
    val = 6;
16
    if (setsockopt(fd, SOL_SOCKET, SO_PRIORITY, &val, sizeof(val)) < 0)
17
        pw_log_warn("setsockopt(SO_PRIORITY) failed: %m");
18
-
19
+#endif
20
    val = IPTOS_LOWDELAY;
21
    if (setsockopt(fd, IPPROTO_IP, IP_TOS, &val, sizeof(val)) < 0)
22
-       pw_log_warn("setsockopt(SO_PRIORITY) failed: %m");
23
+       pw_log_warn("setsockopt(IP_TOS) failed: %m");
24
 
25
 
26
    return fd;
27
pipewire-0.3.60.tar.gz/src/modules/module-rtp-source.c -> pipewire-0.3.61.tar.gz/src/modules/module-rtp-source.c Changed
11
 
1
@@ -46,6 +46,9 @@
2
 #include <module-rtp/sap.h>
3
 #include <module-rtp/rtp.h>
4
 
5
+#ifdef __FreeBSD__
6
+#define ifr_ifindex ifr_index
7
+#endif
8
 
9
 /** \page page_module_rtp_source PipeWire Module: RTP source
10
  *
11
pipewire-0.3.60.tar.gz/src/pipewire/context.c -> pipewire-0.3.61.tar.gz/src/pipewire/context.c Changed
45
 
1
@@ -1168,6 +1168,10 @@
2
            if (s->active)
3
                running = !n->passive;
4
 
5
+           pw_log_debug("%p: follower %p running:%d passive:%d rate:%u/%u latency %u/%u '%s'",
6
+               context, s, running, s->passive, rate.num, rate.denom,
7
+               latency.num, latency.denom, s->name);
8
+
9
            s->moved = false;
10
        }
11
 
12
@@ -1195,6 +1199,7 @@
13
        }
14
 
15
        if (target_rate != current_rate) {
16
+           bool do_suspend = false;
17
            /* we doing a rate switch */
18
            pw_log_info("(%s-%u) state:%s new rate:%u->%u",
19
                    n->name, n->info.id,
20
@@ -1204,18 +1209,21 @@
21
 
22
            if (force_rate) {
23
                if (settings->clock_rate_update_mode == CLOCK_RATE_UPDATE_MODE_HARD)
24
-                   suspend_driver(context, n);
25
+                   do_suspend = true;
26
            } else {
27
                if (n->info.state >= PW_NODE_STATE_SUSPENDED)
28
-                   suspend_driver(context, n);
29
+                   do_suspend = true;
30
            }
31
+           if (do_suspend)
32
+               suspend_driver(context, n);
33
            /* we're setting the pending rate. This will become the new
34
             * current rate in the next iteration of the graph. */
35
            n->current_rate = SPA_FRACTION(1, target_rate);
36
            n->current_pending = true;
37
            current_rate = target_rate;
38
            /* we might be suspended now and the links need to be prepared again */
39
-           goto again;
40
+           if (do_suspend)
41
+               goto again;
42
        }
43
 
44
        if (rate_quantum != 0 && current_rate != rate_quantum) {
45
pipewire-0.3.60.tar.gz/src/pipewire/impl-module.c -> pipewire-0.3.61.tar.gz/src/pipewire/impl-module.c Changed
23
 
1
@@ -178,6 +178,8 @@
2
        NULL
3
    };
4
 
5
+   pw_log_info("%p: name:%s args:%s", context, name, args);
6
+
7
    module_dir = getenv("PIPEWIRE_MODULE_DIR");
8
    if (module_dir == NULL) {
9
        module_dir = MODULEDIR;
10
@@ -276,10 +278,10 @@
11
 
12
 error_not_found:
13
    res = -ENOENT;
14
-   pw_log_error("No module \"%s\" was found", name);
15
+   pw_log_info("No module \"%s\" was found", name);
16
    goto error_cleanup;
17
 error_open_failed:
18
-   res = -ENOENT;
19
+   res = -EIO;
20
    pw_log_error("Failed to open module: \"%s\" %s", filename, dlerror());
21
    goto error_free_filename;
22
 error_no_pw_module:
23
pipewire-0.3.60.tar.gz/src/pipewire/private.h -> pipewire-0.3.61.tar.gz/src/pipewire/private.h Changed
10
 
1
@@ -49,7 +49,7 @@
2
 #define spa_debug(...) pw_log_trace(__VA_ARGS__)
3
 #endif
4
 
5
-#define MAX_RATES              16u
6
+#define MAX_RATES              32u
7
 #define CLOCK_MIN_QUANTUM          4u
8
 #define CLOCK_MAX_QUANTUM          65536u
9
 
10
pipewire-0.3.60.tar.gz/src/pipewire/stream.c -> pipewire-0.3.61.tar.gz/src/pipewire/stream.c Changed
71
 
1
@@ -587,6 +587,28 @@
2
    return 0;
3
 }
4
 
5
+static inline void copy_position(struct stream *impl, int64_t queued)
6
+{
7
+   struct spa_io_position *p = impl->rt.position;
8
+
9
+   SEQ_WRITE(impl->seq);
10
+   if (SPA_LIKELY(p != NULL)) {
11
+       impl->time.now = p->clock.nsec;
12
+       impl->time.rate = p->clock.rate;
13
+       if (SPA_UNLIKELY(impl->clock_id != p->clock.id)) {
14
+           impl->base_pos = p->clock.position - impl->time.ticks;
15
+           impl->clock_id = p->clock.id;
16
+       }
17
+       impl->time.ticks = p->clock.position - impl->base_pos;
18
+       impl->time.delay = 0;
19
+       impl->time.queued = queued;
20
+       impl->quantum = p->clock.duration;
21
+   }
22
+   if (SPA_LIKELY(impl->rate_match != NULL))
23
+       impl->rate_queued = impl->rate_match->delay;
24
+   SEQ_WRITE(impl->seq);
25
+}
26
+
27
 static int impl_send_command(void *object, const struct spa_command *command)
28
 {
29
    struct stream *impl = object;
30
@@ -614,8 +636,10 @@
31
 
32
            if (impl->direction == SPA_DIRECTION_INPUT)
33
                impl->io->status = SPA_STATUS_NEED_DATA;
34
-           else if (!impl->process_rt && !impl->driving)
35
+           else if (!impl->process_rt && !impl->driving) {
36
+               copy_position(impl, impl->queued.incount);
37
                call_process(impl);
38
+           }
39
 
40
            stream_set_state(stream, PW_STREAM_STATE_STREAMING, NULL);
41
        }
42
@@ -963,28 +987,6 @@
43
    return 0;
44
 }
45
 
46
-static inline void copy_position(struct stream *impl, int64_t queued)
47
-{
48
-   struct spa_io_position *p = impl->rt.position;
49
-
50
-   SEQ_WRITE(impl->seq);
51
-   if (SPA_LIKELY(p != NULL)) {
52
-       impl->time.now = p->clock.nsec;
53
-       impl->time.rate = p->clock.rate;
54
-       if (SPA_UNLIKELY(impl->clock_id != p->clock.id)) {
55
-           impl->base_pos = p->clock.position - impl->time.ticks;
56
-           impl->clock_id = p->clock.id;
57
-       }
58
-       impl->time.ticks = p->clock.position - impl->base_pos;
59
-       impl->time.delay = 0;
60
-       impl->time.queued = queued;
61
-       impl->quantum = p->clock.duration;
62
-   }
63
-   if (SPA_LIKELY(impl->rate_match != NULL))
64
-       impl->rate_queued = impl->rate_match->delay;
65
-   SEQ_WRITE(impl->seq);
66
-}
67
-
68
 static int impl_node_process_input(void *object)
69
 {
70
    struct stream *impl = object;
71