Overview

Request 5823 (accepted)

New upstream rel, sync with Tw

Submit package home:zaitor:...s:Essentials / pipewire-aptx to package Essentials / pipewire-aptx

pipewire-aptx.changes Changed
x
 
1
@@ -1,4 +1,9 @@
2
 -------------------------------------------------------------------
3
+Wed Aug 30 13:49:39 UTC 2023 - Bjørn Lie <zaitor@opensuse.org>
4
+
5
+- Update to version 0.3.79
6
+
7
+-------------------------------------------------------------------
8
 Wed Aug  9 15:43:07 UTC 2023 - Bjørn Lie <zaitor@opensuse.org>
9
 
10
 - Update to version 0.3.77
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.77
6
+Version:        0.3.79
7
 Release:        0
8
 Summary:        PipeWire Bluetooth aptX codec plugin
9
 License:        MIT
10
pipewire-0.3.77.tar.gz/NEWS -> pipewire-0.3.79.tar.gz/NEWS Changed
123
 
1
@@ -1,3 +1,111 @@
2
+# PipeWire 0.3.79 (2023-08-29)
3
+
4
+This is a quick bugfix release that is API and ABI compatible with previous
5
+0.3.x releases.
6
+
7
+## Highlights
8
+  - Fix a regression in suspend that could cause silence.
9
+  - Fix a regression in JACK port registration that could cause all kinds of
10
+    JACK problems. (#3485)
11
+  - Fix a typo in the neon sample conversion functions that could cause
12
+    distortion.
13
+  - Add BAP broadcast source and sink support.
14
+  - pw-top now has a batch mode to dump the output to stdout.
15
+  - Many more bugfixes and improvements.
16
+
17
+
18
+## PipeWire
19
+  - Fix a regression in shutdown where a node might not first suspend
20
+    properly. This cause loss of sound in some cases. (#3378)
21
+  - Failure to compile a regular expression in the config file will now
22
+    be reported and ! can be used to negate the match. (#3460)
23
+  - Fix a regression where some nodes might not set running in some
24
+    cases.
25
+  - Nodes are now suspended before the format is cleared, which might
26
+    fix some crashes.
27
+
28
+## Tools
29
+  - pw-top now has a batch mode to dump the output to stdout.
30
+
31
+## SPA
32
+  - The queued samples in audioconvert are now correctly reported in the
33
+    delay. (#3454)
34
+  - Make it easier to add a custom profile in ACP.
35
+  - Fix a typo in the neon sample conversion functions that could cause
36
+    distortion. (#3463)
37
+  - device.profile.pro=true is added for pro audio nodes.
38
+  - An xrun counter was added to spa_io_clock to detect and track skipped
39
+    data because of xruns.
40
+
41
+## Pulse-server
42
+  - Add alsa-sink and alsa-source modules. (#3456)
43
+
44
+## Bluetooth
45
+  - Fix a regression where only the BAP off profile is shown.
46
+  - Add BAP broadcast source and sink support.
47
+
48
+## JACK
49
+  - Also emit a latency notify when the buffer size changes.
50
+  - Fix a regression in JACK port registration. (#3485)
51
+  - jack_port_tie() is now supported.
52
+
53
+## ALSA
54
+  - Improve property handling, support lists and ranges in addition to
55
+    fixed values. (#3451)
56
+
57
+Older versions:
58
+
59
+
60
+# PipeWire 0.3.78 (2023-08-22)
61
+
62
+This is a small bugfix release that is API and ABI compatible with previous
63
+0.3.x releases.
64
+
65
+## Highlights
66
+  - An old regression was fixed with where some nodes would not run.
67
+  - A regression was fixed where removed events would not be shown in some
68
+    cases. This would result in duplicate entries in audio clients.
69
+  - Fix an off-by-one in the vban audio receiver. Tweak the rate adaption
70
+    a little.
71
+  - ACP will now set a UCM verb before probing the pro-audio devices.
72
+  - More bugfixes and improvements.
73
+
74
+
75
+## PipeWire
76
+  - An old regression was fixed with where some nodes would not run. (#3405)
77
+  - Suspend was improved a little to avoid races when the session manager would
78
+    suspend right when a driver was starting.
79
+
80
+## Modules
81
+  - module-rtp-sap does not use the deprecated inet_aton anymore.
82
+  - Fix an off-by-one in the vban audio receiver. Tweak the rate adaption
83
+    a little. (#3380)
84
+
85
+## SPA
86
+  - ACP will now set a UCM verb before probing the pro-audio devices. (#3407)
87
+  - The mandatory flag will be set now on the video modifiers.
88
+  - EVL was updated to Xenomai4 r46 and xbuf creation was improved.
89
+  - An option was added to force colors in the log even when logging to !tty.
90
+  - The return type of spa_pod_builder_control() was fixed.
91
+  - inotify errors are handled better now. (#3439)
92
+
93
+## pulse-server
94
+  - A regression was fixed where removed events would not be shown in some
95
+    cases. (#3414)
96
+
97
+## Bluetooth
98
+  - Improve compatibility with more devices, avoid reusing the same transport
99
+    for different media-sink instances to avoid encoder resets.
100
+  - Improve enumeration of codec profiles for BAP and A2DP.
101
+
102
+## JACK
103
+  - Ensure we can't iterate ports from a deactivated client. Also make sure
104
+    the JACK clients with the node.always-process=false always show their
105
+    ports. (#3416)
106
+
107
+## GStreamer
108
+  - A potential crash was fixed in the device provider when stopping.
109
+
110
 # PipeWire 0.3.77 (2023-08-04)
111
 
112
 This is a quick bugfix release that is API and ABI compatible with previous
113
@@ -49,9 +157,6 @@
114
 ## bluetooth
115
   - Use some more autoptr cleanups, fix some leaks.
116
 
117
-Older versions:
118
-
119
-
120
 # PipeWire 0.3.76 (2023-07-28)
121
 
122
 This is a quick bugfix release that is API and ABI compatible with previous
123
pipewire-0.3.77.tar.gz/doc/dma-buf.dox -> pipewire-0.3.79.tar.gz/doc/dma-buf.dox Changed
141
 
1
@@ -1,7 +1,7 @@
2
 /** \page page_dma_buf DMA-BUF Sharing
3
 
4
 PipeWire supports sharing Direct Memory Access buffers (DMA-BUFs) between
5
-clients via the `SPA_DATA_DmaBuf` data type. However properly negotiating
6
+clients via the \ref SPA_DATA_DmaBuf data type. However properly negotiating
7
 DMA-BUF support on both the producer and the consumer side require following
8
 a specific procedure. This page describes said procedure by using events and
9
 methods from the filter or stream API.
10
@@ -21,37 +21,37 @@
11
 
12
 ## pw_stream_connect
13
 
14
-The stream parameters should contain two `SPA_PARAM_EnumFormat` objects for
15
+The stream parameters should contain two \ref SPA_PARAM_EnumFormat objects for
16
 each format: one for DMA-BUFs, one for shared memory buffers as a fallback.
17
 
18
 Query the list of all supported modifiers from your graphics API of choice.
19
-Add a `SPA_FORMAT_VIDEO_modifier` property to the first stream parameter with
20
+Add a \ref SPA_FORMAT_VIDEO_modifier property to the first stream parameter with
21
 the flags `SPA_POD_PROP_FLAG_MANDATORY | SPA_POD_PROP_FLAG_DONT_FIXATE`. The
22
-value of the property should be set to a `SPA_CHOICE_Enum` containing one
23
+value of the property should be set to a \ref SPA_CHOICE_Enum containing one
24
 `long` choice per supported modifier, plus `DRM_FORMAT_MOD_INVALID` if the
25
 graphics API supports modifier-less buffers.
26
 
27
 Note: When a producer is only supporting modifier-less buffers it can omit
28
-the `SPA_POD_PROP_FLAG_DONT_FIXATE` (see param_changed hook, For producers).
29
+the \ref SPA_POD_PROP_FLAG_DONT_FIXATE (see param_changed hook, For producers).
30
 
31
-The second stream parameter should not contain any `SPA_FORMAT_VIDEO_modifier`
32
+The second stream parameter should not contain any \ref SPA_FORMAT_VIDEO_modifier
33
 property.
34
 
35
-To prioritise DMA-BUFs place those `SPA_PARAM_EnumFormat` containing modifiers
36
+To prioritise DMA-BUFs place those \ref SPA_PARAM_EnumFormat containing modifiers
37
 first, when emitting them to PipeWire.
38
 
39
 ## param_changed Hook
40
 
41
-When the `param_changed` hook is called for a `SPA_PARAM_Format` the client
42
+When the `param_changed` hook is called for a \ref SPA_PARAM_Format the client
43
 has to parse the `spa_pod` directly. Use
44
 `spa_pod_find_prop(param, NULL, SPA_FORMAT_VIDEO_modifier)` to check
45
 whether modifiers were negotiated. If they were negotiated, set the
46
-`SPA_PARAM_BUFFERS_dataType` property to `1 << SPA_DATA_DmaBuf`. If they were
47
+\ref SPA_PARAM_BUFFERS_dataType property to `1 << SPA_DATA_DmaBuf`. If they were
48
 not negotiated, fall back to shared memory by setting the
49
-`SPA_PARAM_BUFFERS_dataType` property to `1 << SPA_DATA_MemFd`,
50
+\ref SPA_PARAM_BUFFERS_dataType property to `1 << SPA_DATA_MemFd`,
51
 `1 << SPA_DATA_MemPtr`, or both.
52
 
53
-While consumers only have to parse the resulting `SPA_PARAM_Format` for any
54
+While consumers only have to parse the resulting \ref SPA_PARAM_Format for any
55
 format related information, it's up to the producer to fixate onto a single
56
 format modifier pair. The producer is also responsible to check if all clients
57
 announce sufficient capabilities or fallback to shared memory buffers when
58
@@ -59,7 +59,7 @@
59
 
60
 ### For Consumers
61
 
62
-Use `spa_format_video_raw_parse` to get the format and modifier.
63
+Use \ref spa_format_video_raw_parse to get the format and modifier.
64
 
65
 ### For Producers
66
 
67
@@ -70,28 +70,28 @@
68
 - modifier-less:
69
   In this case only the modifier `DRM_FORMAT_MOD_INVALID` was announced with
70
   the format.
71
-  It is sufficient to check if the `SPA_PARAM_Format` contains the modifier
72
+  It is sufficient to check if the \ref SPA_PARAM_Format contains the modifier
73
   property as described above. If that is the case, use DMA-BUFs for screen-sharing,
74
   else fall back to SHM, if possible.
75
 - modifier-aware:
76
   In this case a list with all supported modifiers will be returned in the format.
77
   (using `DRM_FORMAT_MOD_INVALID` as the token for the modifier-less API).
78
   On the `param_changed` event check if the modifier key is present and has the flag
79
-  `SPA_POD_PROP_FLAG_DONT_FIXATE` attached to it. In this case, extract all modifiers
80
+  \ref SPA_POD_PROP_FLAG_DONT_FIXATE attached to it. In this case, extract all modifiers
81
   from the list and do a test allocation with your allocator to choose the preferred
82
-  modifier. Fixate on that `EnumFormat` by announcing a `SPA_PARAM_EnumFormat` with
83
-  only one modifier in the `SPA_CHOICE_Enum` and without the
84
-  `SPA_POD_PROP_FLAG_DONT_FIXATE` flag, followed by the previous announced
85
-  `EnumFormat`. This will retrigger the `param_changed` event with an
86
-  `SPA_PARAM_Format` as described below.
87
-  If the `SPA_PARAM_Format` contains a modifier key, without the flag
88
-  `SPA_POD_PROP_FLAG_DONT_FIXATE`, it should only contain one value in the
89
-  `SPA_CHOICE_Enum`. In this case announce the `SPA_PARAM_Buffers` accordingly
90
+  modifier. Fixate on that \ref EnumFormat by announcing a \ref SPA_PARAM_EnumFormat with
91
+  only one modifier in the \ref SPA_CHOICE_Enum and without the
92
+  \ref SPA_POD_PROP_FLAG_DONT_FIXATE flag, followed by the previous announced
93
+  \ref EnumFormat. This will retrigger the `param_changed` event with an
94
+  \ref SPA_PARAM_Format as described below.
95
+  If the \ref SPA_PARAM_Format contains a modifier key, without the flag
96
+  \ref SPA_POD_PROP_FLAG_DONT_FIXATE, it should only contain one value in the
97
+  \ref SPA_CHOICE_Enum. In this case announce the \ref SPA_PARAM_Buffers accordingly
98
   to the selected format and modifier. It is important to query the plane count
99
   of the used format modifier pair and set `SPA_PARAM_BUFFERS_blocks` accordingly.
100
 
101
 Note: When test allocating a buffer, collect all possible modifiers, while omitting
102
-`DRM_FORMAT_MOD_INVALID` from the `SPA_FORMAT_VIDEO_modifier` property and
103
+`DRM_FORMAT_MOD_INVALID` from the \ref SPA_FORMAT_VIDEO_modifier property and
104
 pass them all to the graphics API. If the allocation fails and the list of
105
 possible modifiers contains `DRM_FORMAT_MOD_INVALID`, fall back to allocating
106
 without an explicit modifier if the graphics API allows it.
107
@@ -106,9 +106,9 @@
108
 
109
 This is relevant for consumers.
110
 
111
-Check the type of the dequeued buffer. If its `SPA_DATA_MemFd` or
112
-`SPA_DATA_MemPtr` use the fallback SHM import mechanism.
113
-If it's `SPA_DATA_DmaBuf` 
114
+Check the type of the dequeued buffer. If its \ref SPA_DATA_MemFd or
115
+\ref SPA_DATA_MemPtr use the fallback SHM import mechanism.
116
+If it's \ref SPA_DATA_DmaBuf
117
 get the DMA-BUF FDs (the plane count is encoded in the `n_datas` variable of the
118
 `spa_buffer` struct) and import them with the graphics API.
119
 
120
@@ -150,15 +150,18 @@
121
 # SPA param video format helpers
122
 
123
 SPA offers helper functions to parse and build a spa_pod object to/from the spa_video_info_*
124
-struct. The flags `SPA_VIDEO_FLAG_MODIFIER` and `SPA_VIDEO_FLAG_MODIFIER_FIXATION_REQUIRED`
125
+struct. The flags \ref SPA_VIDEO_FLAG_MODIFIER and \ref SPA_VIDEO_FLAG_MODIFIER_FIXATION_REQUIRED
126
 are used to indicate modifier usage with the format. `SPA_VIDEO_FLAG_MODIFIER` declares the
127
 parsed/provided spa_video_info_* struct contains valid modifier information. For legacy
128
 reasons `spa_format_video_*_build` will announce any modifier != 0 even when this flag is
129
 unused. `SPA_VIDEO_FLAG_MODIFIER_FIXATION_REQUIRED` is exclusive to the parse helpers and
130
 declares that the parsed spa_pod contains modifier information which needs to be fixated as
131
-described aboath. The list of available modifiers has to be parsed manually from the spa_pod
132
+described above. The list of available modifiers has to be parsed manually from the spa_pod
133
 object.
134
 
135
+- \ref spa_video_info_raw, \ref spa_format_video_raw_parse, \ref spa_format_video_raw_build
136
+- \ref spa_video_info_dsp, \ref spa_format_video_dsp_parse, \ref spa_format_video_dsp_build
137
+
138
 # v4l2
139
 
140
 Another use case for streaming via DMA-BUFs are exporting a camera feed from v4l2
141
pipewire-0.3.77.tar.gz/doc/pipewire-daemon.dox -> pipewire-0.3.79.tar.gz/doc/pipewire-daemon.dox Changed
9
 
1
@@ -171,5 +171,7 @@
2
 - `PIPEWIRE_LOG_SYSTEMD=false`: Disable logging to the systemd journal.
3
 - `PIPEWIRE_LOG=<filename>`: Redirect the log to the given filename.
4
 - `PIPEWIRE_LOG_LINE=false`: Don't log filename, function, and source code line.
5
+- `PIPEWIRE_LOG_COLOR=true/false/force`: Enable/disable color logging, and optionally force
6
+  colors even when logging to a file.
7
 
8
 */
9
pipewire-0.3.77.tar.gz/meson.build -> pipewire-0.3.79.tar.gz/meson.build Changed
8
 
1
@@ -1,5 +1,5 @@
2
 project('pipewire', 'c' ,
3
-  version : '0.3.77',
4
+  version : '0.3.79',
5
   license :  'MIT', 'LGPL-2.1-or-later', 'GPL-2.0-only' ,
6
   meson_version : '>= 0.61.1',
7
   default_options :  'warning_level=3',
8
pipewire-0.3.77.tar.gz/pipewire-alsa/alsa-plugins/pcm_pipewire.c -> pipewire-0.3.79.tar.gz/pipewire-alsa/alsa-plugins/pcm_pipewire.c Changed
311
 
1
@@ -22,6 +22,7 @@
2
 #include <spa/utils/atomic.h>
3
 #include <spa/utils/result.h>
4
 #include <spa/utils/string.h>
5
+#include <spa/utils/json.h>
6
 
7
 #include <pipewire/pipewire.h>
8
 
9
@@ -919,118 +920,199 @@
10
    .query_chmaps = snd_pcm_pipewire_query_chmaps,
11
 };
12
 
13
-static int pipewire_set_hw_constraint(snd_pcm_pipewire_t *pw)
14
+#define MAX_VALS   64
15
+struct param_info {
16
+   const char *prop;
17
+   int key;
18
+#define TYPE_LIST  0
19
+#define TYPE_MIN_MAX   1
20
+   int type;
21
+   unsigned int valsMAX_VALS;
22
+   unsigned int n_vals;
23
+   int (*collect) (const char *str, int len, unsigned int *val);
24
+
25
+};
26
+
27
+static int collect_access(const char *str, int len, unsigned int *val)
28
+{
29
+   char key64;
30
+
31
+   if (spa_json_parse_stringn(str, len, key, sizeof(key)) <= 0)
32
+       return -EINVAL;
33
+
34
+   if (strcasecmp(key, "MMAP_INTERLEAVED") == 0)
35
+       *val = SND_PCM_ACCESS_MMAP_INTERLEAVED;
36
+   else if (strcasecmp(key, "MMAP_NONINTERLEAVED") == 0)
37
+       *val = SND_PCM_ACCESS_MMAP_NONINTERLEAVED;
38
+   else if (strcasecmp(key, "RW_INTERLEAVED") == 0)
39
+       *val = SND_PCM_ACCESS_RW_INTERLEAVED;
40
+   else if (strcasecmp(key, "RW_NONINTERLEAVED") == 0)
41
+       *val = SND_PCM_ACCESS_RW_NONINTERLEAVED;
42
+   else
43
+       return -EINVAL;
44
+   return 0;
45
+}
46
+
47
+static int collect_format(const char *str, int len, unsigned int *val)
48
+{
49
+   char key64;
50
+   snd_pcm_format_t fmt;
51
+
52
+   if (spa_json_parse_stringn(str, len, key, sizeof(key)) < 0)
53
+       return -EINVAL;
54
+
55
+   fmt = snd_pcm_format_value(key);
56
+   if (fmt != SND_PCM_FORMAT_UNKNOWN)
57
+       *val = fmt;
58
+   else
59
+       return -EINVAL;
60
+   return 0;
61
+}
62
+
63
+static int collect_int(const char *str, int len, unsigned int *val)
64
 {
65
-   unsigned int access_list = {
66
-       SND_PCM_ACCESS_MMAP_INTERLEAVED,
67
-       SND_PCM_ACCESS_MMAP_NONINTERLEAVED,
68
-       SND_PCM_ACCESS_RW_INTERLEAVED,
69
-       SND_PCM_ACCESS_RW_NONINTERLEAVED
70
-   };
71
-   unsigned int format_list = {
72
+   int v;
73
+   if (spa_json_parse_int(str, len, &v) > 0)
74
+       *val = v;
75
+   else
76
+       return -EINVAL;
77
+   return 0;
78
+}
79
+
80
+struct param_info infos = {
81
+   { "alsa.access", SND_PCM_IOPLUG_HW_ACCESS, TYPE_LIST,
82
+       { SND_PCM_ACCESS_MMAP_INTERLEAVED,
83
+           SND_PCM_ACCESS_MMAP_NONINTERLEAVED,
84
+           SND_PCM_ACCESS_RW_INTERLEAVED,
85
+           SND_PCM_ACCESS_RW_NONINTERLEAVED }, 4, collect_access },
86
+   { "alsa.format", SND_PCM_IOPLUG_HW_FORMAT, TYPE_LIST,
87
+       {
88
 #if __BYTE_ORDER == __LITTLE_ENDIAN
89
-       SND_PCM_FORMAT_FLOAT_LE,
90
-       SND_PCM_FORMAT_S32_LE,
91
-       SND_PCM_FORMAT_S24_LE,
92
-       SND_PCM_FORMAT_S24_3LE,
93
-       SND_PCM_FORMAT_S24_3BE,
94
-       SND_PCM_FORMAT_S16_LE,
95
+           SND_PCM_FORMAT_FLOAT_LE,
96
+           SND_PCM_FORMAT_S32_LE,
97
+           SND_PCM_FORMAT_S24_LE,
98
+           SND_PCM_FORMAT_S24_3LE,
99
+           SND_PCM_FORMAT_S24_3BE,
100
+           SND_PCM_FORMAT_S16_LE,
101
 #elif __BYTE_ORDER == __BIG_ENDIAN
102
-       SND_PCM_FORMAT_FLOAT_BE,
103
-       SND_PCM_FORMAT_S32_BE,
104
-       SND_PCM_FORMAT_S24_BE,
105
-       SND_PCM_FORMAT_S24_3LE,
106
-       SND_PCM_FORMAT_S24_3BE,
107
-       SND_PCM_FORMAT_S16_BE,
108
+           SND_PCM_FORMAT_FLOAT_BE,
109
+           SND_PCM_FORMAT_S32_BE,
110
+           SND_PCM_FORMAT_S24_BE,
111
+           SND_PCM_FORMAT_S24_3LE,
112
+           SND_PCM_FORMAT_S24_3BE,
113
+           SND_PCM_FORMAT_S16_BE,
114
 #endif
115
-       SND_PCM_FORMAT_U8,
116
-   };
117
-   int val;
118
-   int min_rate;
119
-   int max_rate;
120
-   int min_channels;
121
-   int max_channels;
122
-   int min_period_bytes;
123
-   int max_period_bytes;
124
-   int min_buffer_bytes;
125
-   int max_buffer_bytes;
126
-   const char *str;
127
-   snd_pcm_format_t format;
128
-   int err;
129
+           SND_PCM_FORMAT_U8 }, 7, collect_format },
130
+   { "alsa.rate", SND_PCM_IOPLUG_HW_RATE, TYPE_MIN_MAX,
131
+       { 1, MAX_RATE }, 2, collect_int },
132
+   { "alsa.channels", SND_PCM_IOPLUG_HW_CHANNELS, TYPE_MIN_MAX,
133
+       { 1, MAX_CHANNELS }, 2, collect_int },
134
+   { "alsa.buffer-bytes", SND_PCM_IOPLUG_HW_BUFFER_BYTES, TYPE_MIN_MAX,
135
+       { MIN_BUFFER_BYTES, MAX_BUFFER_BYTES }, 2, collect_int },
136
+   { "alsa.period-bytes", SND_PCM_IOPLUG_HW_PERIOD_BYTES, TYPE_MIN_MAX,
137
+       { MIN_PERIOD_BYTES, MAX_PERIOD_BYTES }, 2, collect_int },
138
+   { "alsa.periods", SND_PCM_IOPLUG_HW_PERIODS, TYPE_MIN_MAX,
139
+       { MIN_BUFFERS, 1024 }, 2, collect_int },
140
+};
141
 
142
-   val = pw_properties_get_uint32(pw->props, "alsa.rate", 0);
143
-   if (val > 0) {
144
-       min_rate = max_rate = SPA_CLAMP(val, 1, MAX_RATE);
145
-   } else {
146
-       min_rate = 1;
147
-       max_rate = MAX_RATE;
148
-   }
149
-   val = pw_properties_get_uint32(pw->props, "alsa.channels", 0);
150
-   if (val > 0) {
151
-       min_channels = max_channels = SPA_CLAMP(val, 1, MAX_CHANNELS);
152
-   } else {
153
-       min_channels = 1;
154
-       max_channels = MAX_CHANNELS;
155
+static struct param_info *param_info_by_key(int key)
156
+{
157
+   SPA_FOR_EACH_ELEMENT_VAR(infos, p) {
158
+       if (p->key == key)
159
+           return p;
160
    }
161
-   val = pw_properties_get_uint32(pw->props, "alsa.period-bytes", 0);
162
-   if (val > 0) {
163
-       min_period_bytes = max_period_bytes = SPA_CLAMP(val,
164
-               MIN_PERIOD_BYTES, MAX_PERIOD_BYTES);
165
-   } else {
166
-       min_period_bytes = MIN_PERIOD_BYTES;
167
-       max_period_bytes = MAX_PERIOD_BYTES;
168
+   return NULL;
169
+}
170
+
171
+static int parse_value(const char *str, struct param_info *info)
172
+{
173
+   struct spa_json it2;
174
+   unsigned int v;
175
+   const char *val;
176
+   int len;
177
+
178
+   spa_json_init(&it0, str, strlen(str));
179
+   if ((len = spa_json_next(&it0, &val)) <= 0)
180
+       return -EINVAL;
181
+
182
+   if (spa_json_is_array(val, len)) {
183
+       info->type = TYPE_LIST;
184
+       info->n_vals = 0;
185
+       spa_json_enter(&it0, &it1);
186
+       while ((len = spa_json_next(&it1, &val)) > 0 && info->n_vals < MAX_VALS) {
187
+           if (info->collect(val, len, &v) < 0)
188
+               continue;
189
+           info->valsinfo->n_vals++ = v;
190
+       }
191
    }
192
-   val = pw_properties_get_uint32(pw->props, "alsa.buffer-bytes", 0);
193
-   if (val > 0) {
194
-       min_buffer_bytes = max_buffer_bytes = SPA_CLAMP(val,
195
-               MIN_BUFFER_BYTES, MAX_BUFFER_BYTES);
196
-   } else {
197
-       min_buffer_bytes = MIN_BUFFER_BYTES;
198
-       max_buffer_bytes = MAX_BUFFER_BYTES;
199
+   else if (spa_json_is_object(val, len)) {
200
+       char key64;
201
+       info->type = TYPE_MIN_MAX;
202
+       info->n_vals = 2;
203
+       spa_json_enter(&it0, &it1);
204
+                while (spa_json_get_string(&it1, key, sizeof(key)) > 0) {
205
+                        if ((len = spa_json_next(&it1, &val)) <= 0)
206
+                                break;
207
+           if (info->collect(val, len, &v) < 0)
208
+               continue;
209
+           if (spa_streq(key, "min"))
210
+               info->vals0 = v;
211
+           else if (spa_streq(key, "max"))
212
+               info->vals1 = v;
213
+                }
214
    }
215
-   if (min_period_bytes * 2 > max_buffer_bytes)
216
-       min_period_bytes = max_period_bytes = max_buffer_bytes / 2;
217
-
218
-   if ((err = snd_pcm_ioplug_set_param_list(&pw->io, SND_PCM_IOPLUG_HW_ACCESS,
219
-                          SPA_N_ELEMENTS(access_list), access_list)) < 0 ||
220
-       (err = snd_pcm_ioplug_set_param_minmax(&pw->io, SND_PCM_IOPLUG_HW_CHANNELS,
221
-                          min_channels, max_channels)) < 0 ||
222
-       (err = snd_pcm_ioplug_set_param_minmax(&pw->io, SND_PCM_IOPLUG_HW_RATE,
223
-                          min_rate, max_rate)) < 0 ||
224
-       (err = snd_pcm_ioplug_set_param_minmax(&pw->io, SND_PCM_IOPLUG_HW_BUFFER_BYTES,
225
-                          min_buffer_bytes,
226
-                          max_buffer_bytes)) < 0 ||
227
-       (err = snd_pcm_ioplug_set_param_minmax(&pw->io,
228
-                          SND_PCM_IOPLUG_HW_PERIOD_BYTES,
229
-                          min_period_bytes,
230
-                          max_period_bytes)) < 0 ||
231
-       (err = snd_pcm_ioplug_set_param_minmax(&pw->io, SND_PCM_IOPLUG_HW_PERIODS,
232
-                          MIN_BUFFERS, 1024)) < 0) {
233
-       pw_log_warn("Can't set param list: %s", snd_strerror(err));
234
-       return err;
235
+   else if (info->collect(val, len, &v) >= 0) {
236
+       info->type = TYPE_LIST;
237
+       info->vals0 = v;
238
+       info->n_vals = 1;
239
    }
240
-   format = SND_PCM_FORMAT_UNKNOWN;
241
-   if ((str = pw_properties_get(pw->props, "alsa.format")))
242
-       format = snd_pcm_format_value(str);
243
-
244
-   if (format != SND_PCM_FORMAT_UNKNOWN) {
245
-       err = snd_pcm_ioplug_set_param_list(&pw->io,
246
-               SND_PCM_IOPLUG_HW_FORMAT,
247
-               1, (unsigned int *)&format);
248
-       if (err < 0) {
249
-           pw_log_warn("Can't set param list: %s", snd_strerror(err));
250
-           return err;
251
-       }
252
-   } else {
253
-       err = snd_pcm_ioplug_set_param_list(&pw->io,
254
-               SND_PCM_IOPLUG_HW_FORMAT,
255
-               SPA_N_ELEMENTS(format_list),
256
-               format_list);
257
-       if (err < 0) {
258
-           pw_log_warn("Can't set param list: %s", snd_strerror(err));
259
-           return err;
260
-       }
261
+   return 0;
262
+}
263
+
264
+static int set_constraint(snd_pcm_pipewire_t *pw, int key)
265
+{
266
+   struct param_info *p = param_info_by_key(key), info;
267
+   const char *str;
268
+   int err;
269
+
270
+   if (p == NULL)
271
+       return -EINVAL;
272
+
273
+   info = *p;
274
+
275
+   str = pw_properties_get(pw->props, p->prop);
276
+   if (str != NULL)
277
+       parse_value(str, &info);
278
+
279
+   switch (info.type) {
280
+   case TYPE_LIST:
281
+       pw_log_info("%s: list %d", p->prop, info.n_vals);
282
+       err = snd_pcm_ioplug_set_param_list(&pw->io, key, info.n_vals, info.vals);
283
+       break;
284
+   case TYPE_MIN_MAX:
285
+       pw_log_info("%s: min:%u max:%u", p->prop, info.vals0, info.vals1);
286
+       err = snd_pcm_ioplug_set_param_minmax(&pw->io, key, info.vals0, info.vals1);
287
+       break;
288
+   default:
289
+       return -EIO;
290
    }
291
+   if (err < 0)
292
+       pw_log_warn("Can't set param %s: %s", info.prop, snd_strerror(err));
293
+
294
+   return err;
295
+
296
+}
297
+static int pipewire_set_hw_constraint(snd_pcm_pipewire_t *pw)
298
+{
299
+   int err;
300
+   if ((err = set_constraint(pw, SND_PCM_IOPLUG_HW_ACCESS)) < 0 ||
301
+       (err = set_constraint(pw, SND_PCM_IOPLUG_HW_FORMAT)) < 0 ||
302
+       (err = set_constraint(pw, SND_PCM_IOPLUG_HW_RATE)) < 0 ||
303
+       (err = set_constraint(pw, SND_PCM_IOPLUG_HW_CHANNELS)) < 0 ||
304
+       (err = set_constraint(pw, SND_PCM_IOPLUG_HW_PERIOD_BYTES)) < 0 ||
305
+       (err = set_constraint(pw, SND_PCM_IOPLUG_HW_BUFFER_BYTES)) < 0 ||
306
+       (err = set_constraint(pw, SND_PCM_IOPLUG_HW_PERIODS)) < 0)
307
+       return err;
308
    return 0;
309
 }
310
 
311
pipewire-0.3.77.tar.gz/pipewire-jack/jack/intclient.h -> pipewire-0.3.79.tar.gz/pipewire-jack/jack/intclient.h Changed
10
 
1
@@ -13,7 +13,7 @@
2
 *  
3
 *  You should have received a copy of the GNU Lesser General Public License
4
 *  along with this program; if not, write to the Free Software 
5
-*  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
6
+*  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA.
7
 *
8
 */
9
 
10
pipewire-0.3.77.tar.gz/pipewire-jack/jack/jack.h -> pipewire-0.3.79.tar.gz/pipewire-jack/jack/jack.h Changed
10
 
1
@@ -14,7 +14,7 @@
2
 
3
   You should have received a copy of the GNU Lesser General Public License
4
   along with this program; if not, write to the Free Software
5
-  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
6
+  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA.
7
 
8
 */
9
 
10
pipewire-0.3.77.tar.gz/pipewire-jack/jack/jslist.h -> pipewire-0.3.79.tar.gz/pipewire-jack/jack/jslist.h Changed
10
 
1
@@ -18,7 +18,7 @@
2
 
3
   You should have received a copy of the GNU Lesser General Public License
4
   along with this program; if not, write to the Free Software
5
-  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
6
+  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA.
7
 
8
 */
9
 
10
pipewire-0.3.77.tar.gz/pipewire-jack/jack/metadata.h -> pipewire-0.3.79.tar.gz/pipewire-jack/jack/metadata.h Changed
10
 
1
@@ -14,7 +14,7 @@
2
 
3
   You should have received a copy of the GNU Lesser General Public License
4
   along with this program; if not, write to the Free Software Foundation,
5
-  Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
6
+  Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA.
7
 */
8
 
9
 /**
10
pipewire-0.3.77.tar.gz/pipewire-jack/jack/midiport.h -> pipewire-0.3.79.tar.gz/pipewire-jack/jack/midiport.h Changed
10
 
1
@@ -13,7 +13,7 @@
2
 
3
     You should have received a copy of the GNU Lesser General Public License
4
     along with this program; if not, write to the Free Software
5
-    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
6
+    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA.
7
 
8
 */
9
 
10
pipewire-0.3.77.tar.gz/pipewire-jack/jack/net.h -> pipewire-0.3.79.tar.gz/pipewire-jack/jack/net.h Changed
10
 
1
@@ -13,7 +13,7 @@
2
 
3
   You should have received a copy of the GNU Lesser General Public License
4
   along with this program; if not, write to the Free Software
5
-  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
6
+  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA.
7
 
8
 */
9
 
10
pipewire-0.3.77.tar.gz/pipewire-jack/jack/ringbuffer.h -> pipewire-0.3.79.tar.gz/pipewire-jack/jack/ringbuffer.h Changed
10
 
1
@@ -14,7 +14,7 @@
2
   
3
   You should have received a copy of the GNU Lesser General Public License
4
   along with this program; if not, write to the Free Software 
5
-  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
6
+  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA.
7
 
8
 */
9
 
10
pipewire-0.3.77.tar.gz/pipewire-jack/jack/session.h -> pipewire-0.3.79.tar.gz/pipewire-jack/jack/session.h Changed
10
 
1
@@ -15,7 +15,7 @@
2
 
3
     You should have received a copy of the GNU Lesser General Public License
4
     along with this program; if not, write to the Free Software
5
-    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
6
+    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA.
7
 */
8
 
9
 #ifndef __jack_session_h__
10
pipewire-0.3.77.tar.gz/pipewire-jack/jack/thread.h -> pipewire-0.3.79.tar.gz/pipewire-jack/jack/thread.h Changed
10
 
1
@@ -13,7 +13,7 @@
2
 
3
    You should have received a copy of the GNU Lesser General Public License
4
    along with this program; if not, write to the Free Software
5
-   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
6
+   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA.
7
 
8
 */
9
 
10
pipewire-0.3.77.tar.gz/pipewire-jack/jack/transport.h -> pipewire-0.3.79.tar.gz/pipewire-jack/jack/transport.h Changed
10
 
1
@@ -14,7 +14,7 @@
2
 
3
     You should have received a copy of the GNU Lesser General Public License
4
     along with this program; if not, write to the Free Software
5
-    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
6
+    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA.
7
 
8
 */
9
 
10
pipewire-0.3.77.tar.gz/pipewire-jack/jack/types.h -> pipewire-0.3.79.tar.gz/pipewire-jack/jack/types.h Changed
10
 
1
@@ -14,7 +14,7 @@
2
 
3
   You should have received a copy of the GNU Lesser General Public License
4
   along with this program; if not, write to the Free Software
5
-  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
6
+  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA.
7
 
8
 */
9
 
10
pipewire-0.3.77.tar.gz/pipewire-jack/jack/uuid.h -> pipewire-0.3.79.tar.gz/pipewire-jack/jack/uuid.h Changed
10
 
1
@@ -13,7 +13,7 @@
2
 
3
     You should have received a copy of the GNU Lesser General Public License
4
     along with this program; if not, write to the Free Software
5
-    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
6
+    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA.
7
 
8
 */
9
 
10
pipewire-0.3.77.tar.gz/pipewire-jack/jack/weakjack.h -> pipewire-0.3.79.tar.gz/pipewire-jack/jack/weakjack.h Changed
10
 
1
@@ -13,7 +13,7 @@
2
 
3
     You should have received a copy of the GNU Lesser General Public License
4
     along with this program; if not, write to the Free Software
5
-    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
6
+    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA.
7
 
8
 */
9
 
10
pipewire-0.3.77.tar.gz/pipewire-jack/jack/weakmacros.h -> pipewire-0.3.79.tar.gz/pipewire-jack/jack/weakmacros.h Changed
10
 
1
@@ -13,7 +13,7 @@
2
 
3
     You should have received a copy of the GNU Lesser General Public License
4
     along with this program; if not, write to the Free Software
5
-    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
6
+    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA.
7
 
8
 */
9
 
10
pipewire-0.3.77.tar.gz/pipewire-jack/src/pipewire-jack.c -> pipewire-0.3.79.tar.gz/pipewire-jack/src/pipewire-jack.c Changed
360
 
1
@@ -86,12 +86,12 @@
2
 #define NOTIFY_TYPE_REGISTRATION   ((1<<4))
3
 #define NOTIFY_TYPE_PORTREGISTRATION   ((2<<4)|NOTIFY_ACTIVE_FLAG)
4
 #define NOTIFY_TYPE_CONNECT        ((3<<4)|NOTIFY_ACTIVE_FLAG)
5
-#define NOTIFY_TYPE_GRAPH      ((4<<4)|NOTIFY_ACTIVE_FLAG)
6
-#define NOTIFY_TYPE_BUFFER_FRAMES  ((5<<4)|NOTIFY_ACTIVE_FLAG)
7
-#define NOTIFY_TYPE_SAMPLE_RATE        ((6<<4)|NOTIFY_ACTIVE_FLAG)
8
-#define NOTIFY_TYPE_FREEWHEEL      ((7<<4)|NOTIFY_ACTIVE_FLAG)
9
-#define NOTIFY_TYPE_SHUTDOWN       ((8<<4)|NOTIFY_ACTIVE_FLAG)
10
-#define NOTIFY_TYPE_LATENCY        ((9<<4)|NOTIFY_ACTIVE_FLAG)
11
+#define NOTIFY_TYPE_BUFFER_FRAMES  ((4<<4)|NOTIFY_ACTIVE_FLAG)
12
+#define NOTIFY_TYPE_SAMPLE_RATE        ((5<<4)|NOTIFY_ACTIVE_FLAG)
13
+#define NOTIFY_TYPE_FREEWHEEL      ((6<<4)|NOTIFY_ACTIVE_FLAG)
14
+#define NOTIFY_TYPE_SHUTDOWN       ((7<<4)|NOTIFY_ACTIVE_FLAG)
15
+#define NOTIFY_TYPE_LATENCY        ((8<<4)|NOTIFY_ACTIVE_FLAG)
16
+#define NOTIFY_TYPE_TOTAL_LATENCY  ((9<<4)|NOTIFY_ACTIVE_FLAG)
17
    int type;
18
    struct object *object;
19
    int arg1;
20
@@ -171,6 +171,7 @@
21
    struct spa_hook proxy_listener;
22
    struct spa_hook object_listener;
23
    int registered;
24
+   unsigned int visible;
25
    unsigned int removing:1;
26
    unsigned int removed:1;
27
 };
28
@@ -248,6 +249,8 @@
29
    struct spa_list mix;
30
    struct mix *global_mix;
31
 
32
+   struct port *tied;
33
+
34
    unsigned int empty_out:1;
35
    unsigned int zeroed:1;
36
 
37
@@ -718,12 +721,20 @@
38
    return false;
39
 }
40
 
41
+static inline bool client_port_visible(struct client *c, struct object *o)
42
+{
43
+   if (o->port.port != NULL && o->port.port->client == c)
44
+       return true;
45
+   return o->visible;
46
+}
47
+
48
 static struct object *find_port_by_name(struct client *c, const char *name)
49
 {
50
    struct object *o;
51
 
52
    spa_list_for_each(o, &c->context.objects, link) {
53
-       if (o->type != INTERFACE_Port || o->removed)
54
+       if (o->type != INTERFACE_Port || o->removed ||
55
+           (!client_port_visible(c, o)))
56
            continue;
57
        if (spa_streq(o->port.name, name) ||
58
            spa_streq(o->port.alias1, name) ||
59
@@ -900,12 +911,6 @@
60
    return name;
61
 }
62
 
63
-static void recompute_latencies(struct client *c)
64
-{
65
-   do_callback(c, latency_callback, c->active, JackCaptureLatency, c->latency_arg);
66
-   do_callback(c, latency_callback, c->active, JackPlaybackLatency, c->latency_arg);
67
-}
68
-
69
 #define freeze_callbacks(c)        \
70
 ({                 \
71
    (c)->frozen_callbacks++;    \
72
@@ -928,7 +933,7 @@
73
    int32_t avail;
74
    uint32_t index;
75
    struct notify *notify;
76
-   bool do_graph = false;
77
+   bool do_graph = false, do_recompute_capture = false, do_recompute_playback = false;
78
 
79
    if (c->frozen_callbacks != 0 || !c->pending_callbacks)
80
        return;
81
@@ -981,10 +986,7 @@
82
                    c->connect_arg);
83
 
84
            do_graph = true;
85
-           break;
86
-       case NOTIFY_TYPE_GRAPH:
87
-           pw_log_debug("%p: graph", c);
88
-           do_graph = true;
89
+           do_recompute_capture = do_recompute_playback = true;
90
            break;
91
        case NOTIFY_TYPE_BUFFER_FRAMES:
92
            pw_log_debug("%p: buffer frames %d", c, notify->arg1);
93
@@ -992,7 +994,7 @@
94
                do_callback_expr(c, c->buffer_frames = notify->arg1,
95
                        bufsize_callback, c->active,
96
                        notify->arg1, c->bufsize_arg);
97
-               recompute_latencies(c);
98
+               do_recompute_capture = do_recompute_playback = true;
99
            }
100
            break;
101
        case NOTIFY_TYPE_SAMPLE_RATE:
102
@@ -1019,7 +1021,14 @@
103
            break;
104
        case NOTIFY_TYPE_LATENCY:
105
            pw_log_debug("%p: latency %d", c, notify->arg1);
106
-           do_callback(c, latency_callback, c->active, notify->arg1, c->latency_arg);
107
+           if (notify->arg1 == JackCaptureLatency)
108
+               do_recompute_capture = true;
109
+           else if (notify->arg1 == JackPlaybackLatency)
110
+               do_recompute_playback = true;
111
+           break;
112
+       case NOTIFY_TYPE_TOTAL_LATENCY:
113
+           pw_log_debug("%p: total latency", c);
114
+           do_recompute_capture = do_recompute_playback = true;
115
            break;
116
        default:
117
            break;
118
@@ -1035,10 +1044,13 @@
119
        index += sizeof(struct notify);
120
        spa_ringbuffer_read_update(&c->notify_ring, index);
121
    }
122
-   if (do_graph) {
123
-       recompute_latencies(c);
124
+   if (do_recompute_capture)
125
+       do_callback(c, latency_callback, c->active, JackCaptureLatency, c->latency_arg);
126
+   if (do_recompute_playback)
127
+       do_callback(c, latency_callback, c->active, JackPlaybackLatency, c->latency_arg);
128
+   if (do_graph)
129
        do_callback(c, graph_callback, c->active, c->graph_arg);
130
-   }
131
+
132
    thaw_callbacks(c);
133
    pw_log_debug("%p: leave", c);
134
 }
135
@@ -1049,6 +1061,7 @@
136
    uint32_t index;
137
    struct notify *notify;
138
    bool emit = false;
139
+   int res = 0;
140
 
141
    switch (type) {
142
    case NOTIFY_TYPE_REGISTRATION:
143
@@ -1056,13 +1069,11 @@
144
        break;
145
    case NOTIFY_TYPE_PORTREGISTRATION:
146
        emit = c->portregistration_callback != NULL && o != NULL;
147
+       o->visible = arg1;
148
        break;
149
    case NOTIFY_TYPE_CONNECT:
150
        emit = c->connect_callback != NULL && o != NULL;
151
        break;
152
-   case NOTIFY_TYPE_GRAPH:
153
-       emit = c->graph_callback != NULL || c->latency_callback != NULL;
154
-       break;
155
    case NOTIFY_TYPE_BUFFER_FRAMES:
156
        emit = c->bufsize_callback != NULL;
157
        break;
158
@@ -1076,6 +1087,7 @@
159
        emit = c->info_shutdown_callback != NULL || c->shutdown_callback != NULL;
160
        break;
161
    case NOTIFY_TYPE_LATENCY:
162
+   case NOTIFY_TYPE_TOTAL_LATENCY:
163
        emit = c->latency_callback != NULL;
164
        break;
165
    default:
166
@@ -1084,8 +1096,10 @@
167
    if (!emit || ((type & NOTIFY_ACTIVE_FLAG) && !c->active)) {
168
        switch (type) {
169
        case NOTIFY_TYPE_BUFFER_FRAMES:
170
-           if (!emit)
171
+           if (!emit) {
172
                c->buffer_frames = arg1;
173
+               queue_notify(c, NOTIFY_TYPE_TOTAL_LATENCY, NULL, 0, NULL);
174
+           }
175
            break;
176
        case NOTIFY_TYPE_SAMPLE_RATE:
177
            if (!emit)
178
@@ -1098,13 +1112,15 @@
179
            o->removing = false;
180
            free_object(c, o);
181
        }
182
-       return 0;
183
+       return res;
184
    }
185
 
186
+   pthread_mutex_lock(&c->context.lock);
187
    filled = spa_ringbuffer_get_write_index(&c->notify_ring, &index);
188
    if (filled < 0 || filled + sizeof(struct notify) > NOTIFY_BUFFER_SIZE) {
189
        pw_log_warn("%p: notify queue full %d", c, type);
190
-       return -ENOSPC;
191
+       res = -ENOSPC;
192
+       goto done;
193
    }
194
 
195
    notify = SPA_PTROFF(c->notify_buffer, index & NOTIFY_BUFFER_MASK, struct notify);
196
@@ -1118,7 +1134,9 @@
197
    spa_ringbuffer_write_update(&c->notify_ring, index);
198
    c->pending_callbacks = true;
199
    check_callbacks(c);
200
-   return 0;
201
+done:
202
+   pthread_mutex_unlock(&c->context.lock);
203
+   return res;
204
 }
205
 
206
 static void on_notify_event(void *data, uint64_t count)
207
@@ -1419,22 +1437,27 @@
208
 
209
 static inline void process_empty(struct port *p, uint32_t frames)
210
 {
211
-   void *ptr;
212
+   void *ptr, *src = p->emptyptr;
213
+   struct port *tied = p->tied;
214
+
215
+   if (SPA_UNLIKELY(tied != NULL)) {
216
+       if ((src = tied->get_buffer(tied, frames)) == NULL)
217
+           src = p->emptyptr;
218
+   }
219
 
220
    switch (p->object->port.type_id) {
221
    case TYPE_ID_AUDIO:
222
        ptr = get_buffer_output(p, frames, sizeof(float), NULL);
223
        if (SPA_LIKELY(ptr != NULL))
224
-           memcpy(ptr, p->emptyptr, frames * sizeof(float));
225
+           memcpy(ptr, src, frames * sizeof(float));
226
        break;
227
    case TYPE_ID_MIDI:
228
    {
229
        struct buffer *b;
230
        ptr = get_buffer_output(p, MAX_BUFFER_FRAMES, 1, &b);
231
-       if (SPA_LIKELY(ptr != NULL)) {
232
-           b->datas0.chunk->size = convert_from_midi(p->emptyptr,
233
+       if (SPA_LIKELY(ptr != NULL))
234
+           b->datas0.chunk->size = convert_from_midi(src,
235
                    ptr, MAX_BUFFER_FRAMES * sizeof(float));
236
-       }
237
        break;
238
    }
239
    default:
240
@@ -1447,7 +1470,7 @@
241
 {
242
    struct mix *mix;
243
 
244
-   if (SPA_UNLIKELY(p->empty_out))
245
+   if (SPA_UNLIKELY(p->empty_out || p->tied))
246
        process_empty(p, frames);
247
 
248
    spa_list_for_each(mix, &p->mix, port_link) {
249
@@ -1462,6 +1485,15 @@
250
    struct mix *mix;
251
    union pw_map_item *item;
252
 
253
+   pw_array_for_each(item, &c->portsSPA_DIRECTION_OUTPUT.items) {
254
+                if (pw_map_item_is_free(item))
255
+           continue;
256
+       p = item->data;
257
+       if (!p->valid)
258
+           continue;
259
+       prepare_output(p, frames);
260
+       p->io.status = SPA_STATUS_NEED_DATA;
261
+   }
262
    pw_array_for_each(item, &c->portsSPA_DIRECTION_INPUT.items) {
263
                 if (pw_map_item_is_free(item))
264
            continue;
265
@@ -1473,15 +1505,6 @@
266
                mix->io->status = SPA_STATUS_NEED_DATA;
267
        }
268
         }
269
-   pw_array_for_each(item, &c->portsSPA_DIRECTION_OUTPUT.items) {
270
-                if (pw_map_item_is_free(item))
271
-           continue;
272
-       p = item->data;
273
-       if (!p->valid)
274
-           continue;
275
-       prepare_output(p, frames);
276
-       p->io.status = SPA_STATUS_NEED_DATA;
277
-   }
278
 }
279
 
280
 static inline void debug_position(struct client *c, jack_position_t *p)
281
@@ -3073,11 +3096,18 @@
282
 {
283
    struct object *n = data;
284
    struct client *c = n->client;
285
+   const char *str;
286
+
287
+   if (info->change_mask & PW_NODE_CHANGE_MASK_PROPS) {
288
+       str = spa_dict_lookup(info->props, PW_KEY_NODE_ALWAYS_PROCESS);
289
+       n->node.is_jack = str ? spa_atob(str) : false;
290
+   }
291
 
292
-   pw_log_info("DSP node %d state change %s", info->id,
293
-           pw_node_state_as_string(info->state));
294
+   n->node.is_running = !n->node.is_jack || (info->state == PW_NODE_STATE_RUNNING);
295
 
296
-   n->node.is_running = (info->state == PW_NODE_STATE_RUNNING);
297
+   pw_log_debug("DSP node %d %08"PRIx64" jack:%u state change %s running:%d", info->id,
298
+           info->change_mask, n->node.is_jack,
299
+           pw_node_state_as_string(info->state), n->node.is_running);
300
 
301
    if (info->change_mask & PW_NODE_CHANGE_MASK_STATE) {
302
        struct object *p;
303
@@ -5256,15 +5286,32 @@
304
 SPA_EXPORT
305
 int jack_port_tie (jack_port_t *src, jack_port_t *dst)
306
 {
307
-   pw_log_warn("not implemented %p %p", src, dst);
308
-   return -ENOTSUP;
309
+   struct object *s = (struct object *) src;
310
+   struct object *d = (struct object *) dst;
311
+   struct port *sp, *dp;
312
+
313
+   sp = s->port.port;
314
+   dp = d->port.port;
315
+   if (sp == NULL || !sp->valid ||
316
+       dp == NULL || !dp->valid ||
317
+       sp->client != dp->client)
318
+       return -EINVAL;
319
+
320
+   dp->tied = sp;
321
+   return 0;
322
 }
323
 
324
 SPA_EXPORT
325
 int jack_port_untie (jack_port_t *port)
326
 {
327
-   pw_log_warn("not implemented %p", port);
328
-   return -ENOTSUP;
329
+   struct object *o = (struct object *) port;
330
+   struct port *p;
331
+
332
+   p = o->port.port;
333
+   if (p == NULL || !p->valid)
334
+       return -EINVAL;
335
+   p->tied = NULL;
336
+   return 0;
337
 }
338
 
339
 SPA_EXPORT
340
@@ -5851,9 +5898,7 @@
341
 int jack_recompute_total_latencies (jack_client_t *client)
342
 {
343
    struct client *c = (struct client *) client;
344
-   queue_notify(c, NOTIFY_TYPE_LATENCY, NULL, JackCaptureLatency, NULL);
345
-   queue_notify(c, NOTIFY_TYPE_LATENCY, NULL, JackPlaybackLatency, NULL);
346
-   return 0;
347
+   return queue_notify(c, NOTIFY_TYPE_TOTAL_LATENCY, NULL, 0, NULL);
348
 }
349
 
350
 static jack_nframes_t port_get_latency (jack_port_t *port)
351
@@ -5989,7 +6034,7 @@
352
    count = 0;
353
 
354
    spa_list_for_each(o, &c->context.objects, link) {
355
-       if (o->type != INTERFACE_Port || o->removed)
356
+       if (o->type != INTERFACE_Port || o->removed || !o->visible)
357
            continue;
358
        pw_log_debug("%p: check port type:%d flags:%08lx name:\"%s\"", c,
359
                o->port.type_id, o->port.flags, o->port.name);
360
pipewire-0.3.77.tar.gz/po/ka.po -> pipewire-0.3.79.tar.gz/po/ka.po Changed
386
 
1
@@ -1,25 +1,25 @@
2
-# Georgian translation for pipewire.
3
-# Copyright (C) 2022 pipewire'S authors
4
+# Georgian translation of pipewire
5
+# Copyright (C) 2023 pipewire's authors
6
 # This file is distributed under the same license as the pipewire package.
7
-# Temuri Doghonadze <temuri.doghonadze@gmail.com>, 2022.
8
+# Temuri Doghonadze <temuri.doghonadze@gmail.com>, 2023.
9
 #
10
 msgid ""
11
 msgstr ""
12
 "Project-Id-Version: pipewire\n"
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-11-20 11:50+0100\n"
17
+"POT-Creation-Date: 2023-08-07 22:01+0200\n"
18
+"PO-Revision-Date: 2023-08-07 22:06+0200\n"
19
 "Last-Translator: Temuri Doghonadze <temuri.doghonadze@gmail.com>\n"
20
-"Language-Team: \n"
21
+"Language-Team: Georgian <(nothing)>\n"
22
 "Language: ka\n"
23
 "MIME-Version: 1.0\n"
24
 "Content-Type: text/plain; charset=UTF-8\n"
25
 "Content-Transfer-Encoding: 8bit\n"
26
 "Plural-Forms: nplurals=2; plural=(n != 1);\n"
27
-"X-Generator: Poedit 3.2\n"
28
+"X-Generator: Poedit 3.3.2\n"
29
 
30
-#: src/daemon/pipewire.c:46
31
+#: src/daemon/pipewire.c:26
32
 #, c-format
33
 msgid ""
34
 "%s options\n"
35
@@ -32,36 +32,44 @@
36
 "       --version ვერსიის ჩვენება\n"
37
 "   -c, --config ჩატვირთვის კონფიგურაცია (ნაგულისხმები %s)\n"
38
 
39
-#: src/modules/module-protocol-pulse/modules/module-tunnel-sink.c:180
40
-#: src/modules/module-protocol-pulse/modules/module-tunnel-source.c:180
41
+#: src/daemon/pipewire.desktop.in:4
42
+msgid "PipeWire Media System"
43
+msgstr "PipeWire Media System"
44
+
45
+#: src/daemon/pipewire.desktop.in:5
46
+msgid "Start the PipeWire Media System"
47
+msgstr "PipeWire Media System-ის გაშვება"
48
+
49
+#: src/modules/module-protocol-pulse/modules/module-tunnel-sink.c:141
50
+#: src/modules/module-protocol-pulse/modules/module-tunnel-source.c:141
51
 #, c-format
52
-msgid "Tunnel to %s/%s"
53
-msgstr "გვირაბი %s/%s -მდე"
54
+msgid "Tunnel to %s%s%s"
55
+msgstr "გვირაბი %s%s%s-მდე"
56
 
57
-#: src/modules/module-fallback-sink.c:51
58
+#: src/modules/module-fallback-sink.c:31
59
 msgid "Dummy Output"
60
 msgstr "ნულოვანი გამოყვანა"
61
 
62
-#: src/modules/module-pulse-tunnel.c:662
63
+#: src/modules/module-pulse-tunnel.c:847
64
 #, c-format
65
 msgid "Tunnel for %s@%s"
66
 msgstr "გვირაბი %s@%s-სთვის"
67
 
68
-#: src/modules/module-zeroconf-discover.c:332
69
+#: src/modules/module-zeroconf-discover.c:311
70
 msgid "Unknown device"
71
 msgstr "უცნობი მოწყობილობა"
72
 
73
-#: src/modules/module-zeroconf-discover.c:344
74
+#: src/modules/module-zeroconf-discover.c:323
75
 #, c-format
76
 msgid "%s on %s@%s"
77
 msgstr "%s %s@%s -ზე"
78
 
79
-#: src/modules/module-zeroconf-discover.c:348
80
+#: src/modules/module-zeroconf-discover.c:327
81
 #, c-format
82
 msgid "%s on %s"
83
 msgstr "%s %s-ზე"
84
 
85
-#: src/tools/pw-cat.c:784
86
+#: src/tools/pw-cat.c:979
87
 #, c-format
88
 msgid ""
89
 "%s options <file>|-\n"
90
@@ -76,14 +84,15 @@
91
 "   -v, --verbose დამატებითი შეტყობინებების გამოტანა\n"
92
 "\n"
93
 
94
-#: src/tools/pw-cat.c:791
95
+#: src/tools/pw-cat.c:986
96
 #, c-format
97
 msgid ""
98
 "  -R, --remote                          Remote daemon name\n"
99
 "      --media-type                      Set media type (default %s)\n"
100
 "      --media-category                  Set media category (default %s)\n"
101
 "      --media-role                      Set media role (default %s)\n"
102
-"      --target                          Set node target (default %s)\n"
103
+"      --target                          Set node target serial or name "
104
+"(default %s)\n"
105
 "                                          0 means don't link\n"
106
 "      --latency                         Set node latency (default %s)\n"
107
 "                                          Xunit (unit = s, ms, us, ns)\n"
108
@@ -106,7 +115,7 @@
109
 "ფაილი\n"
110
 "   -P --properties კვანძის თვისებების დაყენება\n"
111
 
112
-#: src/tools/pw-cat.c:809
113
+#: src/tools/pw-cat.c:1004
114
 #, c-format
115
 msgid ""
116
 "      --rate                            Sample rate (req. for rec) (default "
117
@@ -139,21 +148,23 @@
118
 "   -q --quality                         Resampler ხარისხი (0 - 15) "
119
 "(ნაგულისხმები %d)\n"
120
 
121
-#: src/tools/pw-cat.c:826
122
+#: src/tools/pw-cat.c:1021
123
 msgid ""
124
 "  -p, --playback                        Playback mode\n"
125
 "  -r, --record                          Recording mode\n"
126
 "  -m, --midi                            Midi mode\n"
127
 "  -d, --dsd                             DSD mode\n"
128
+"  -o, --encoded                         Encoded mode\n"
129
 "\n"
130
 msgstr ""
131
-"   -p, --playback                        დაკვრის რეჟიმი\n"
132
-"   -r, -- record                          ჩაწერის რეჟიმი\n"
133
-"   -m, --midi                            Midi რეჟიმი\n"
134
-"   -d, --dsd                             DSD რეჟიმი\n"
135
+"  -p, --playback                        დაკვრის რეჟიმი\n"
136
+"  -r, --record                          ჩაწერის რეჟიმი\n"
137
+"  -m, --midi                            Midi რეჟიმი\n"
138
+"  -d, --dsd                             DSD რეჟიმი\n"
139
+"  -o, --encoded                         დაშიფრული რეჟიმი\n"
140
 "\n"
141
 
142
-#: src/tools/pw-cli.c:2250
143
+#: src/tools/pw-cli.c:2220
144
 #, c-format
145
 msgid ""
146
 "%s options command\n"
147
@@ -161,23 +172,26 @@
148
 "      --version                         Show version\n"
149
 "  -d, --daemon                          Start as daemon (Default false)\n"
150
 "  -r, --remote                          Remote daemon name\n"
151
+"  -m, --monitor                         Monitor activity\n"
152
 "\n"
153
 msgstr ""
154
 "%s პარამეტრები ბრძანება\n"
155
-"   -h, --help                            ამ დახმარების ჩვენება\n"
156
-"       --version                         ვერსიის ჩვენება\n"
157
-"   -d, --daemon                          დაწყება როგორც დემონი (ნაგულისხმები "
158
-"false)\n"
159
-"   -r, --remote                          დაშორებული დემონის სახელი\n"
160
+"  -h, --help                            ამ დახმარების ჩვენება\n"
161
+"      --version                         ვერსიის ჩვენება\n"
162
+"  -d, --daemon                          დემონის სახით გაშვება (ნაგულისხმევად "
163
+"გამორთულია)\n"
164
+"  -r, --remote                          დაშორებული დემონის სახელი\n"
165
+"  -m, --monitor                         აქტივობის მონიტორინგი\n"
166
+"\n"
167
 
168
-#: spa/plugins/alsa/acp/acp.c:321
169
+#: spa/plugins/alsa/acp/acp.c:325
170
 msgid "Pro Audio"
171
 msgstr "Pro Audio"
172
 
173
-#: spa/plugins/alsa/acp/acp.c:444 spa/plugins/alsa/acp/alsa-mixer.c:4648
174
-#: spa/plugins/bluez5/bluez5-device.c:1236
175
+#: spa/plugins/alsa/acp/acp.c:449 spa/plugins/alsa/acp/alsa-mixer.c:4648
176
+#: spa/plugins/bluez5/bluez5-device.c:1586
177
 msgid "Off"
178
-msgstr "გამორთული"
179
+msgstr "გამორთულია"
180
 
181
 #: spa/plugins/alsa/acp/alsa-mixer.c:2652
182
 msgid "Input"
183
@@ -193,7 +207,7 @@
184
 
185
 #: spa/plugins/alsa/acp/alsa-mixer.c:2655
186
 msgid "Docking Station Line In"
187
-msgstr "Docking Station Line In"
188
+msgstr "Docking Station-ის Line In პორტი"
189
 
190
 #: spa/plugins/alsa/acp/alsa-mixer.c:2656
191
 #: spa/plugins/alsa/acp/alsa-mixer.c:2747
192
@@ -202,7 +216,7 @@
193
 
194
 #: spa/plugins/alsa/acp/alsa-mixer.c:2657
195
 #: spa/plugins/alsa/acp/alsa-mixer.c:2741
196
-#: spa/plugins/bluez5/bluez5-device.c:1454
197
+#: spa/plugins/bluez5/bluez5-device.c:1831
198
 msgid "Microphone"
199
 msgstr "მიკროფონი"
200
 
201
@@ -268,7 +282,7 @@
202
 msgstr "Bass-ის გაძლიერების გარეშე"
203
 
204
 #: spa/plugins/alsa/acp/alsa-mixer.c:2672
205
-#: spa/plugins/bluez5/bluez5-device.c:1460
206
+#: spa/plugins/bluez5/bluez5-device.c:1837
207
 msgid "Speaker"
208
 msgstr "დინამიკი"
209
 
210
@@ -383,7 +397,7 @@
211
 
212
 #: spa/plugins/alsa/acp/alsa-mixer.c:4484
213
 #: spa/plugins/alsa/acp/alsa-mixer.c:4642
214
-#: spa/plugins/bluez5/bluez5-device.c:1442
215
+#: spa/plugins/bluez5/bluez5-device.c:1819
216
 msgid "Headset"
217
 msgstr "ყურსაცვამები & მიკროფონი"
218
 
219
@@ -497,12 +511,12 @@
220
 msgid "Mono Chat + 7.1 Surround"
221
 msgstr "მონო ჩატი + 7.1 სივრცითი"
222
 
223
-#: spa/plugins/alsa/acp/alsa-mixer.c:4754
224
+#: spa/plugins/alsa/acp/alsa-mixer.c:4748
225
 #, c-format
226
 msgid "%s Output"
227
 msgstr "%s გამოყვანა"
228
 
229
-#: spa/plugins/alsa/acp/alsa-mixer.c:4761
230
+#: spa/plugins/alsa/acp/alsa-mixer.c:4756
231
 #, c-format
232
 msgid "%s Input"
233
 msgstr "%s შეყვანა"
234
@@ -533,13 +547,13 @@
235
 #: spa/plugins/alsa/acp/alsa-util.c:1253
236
 #, c-format
237
 msgid ""
238
-"snd_pcm_delay() returned a value that is exceptionally large: %li byte (%s"
239
-"%lu ms).\n"
240
+"snd_pcm_delay() returned a value that is exceptionally large: %li byte "
241
+"(%s%lu ms).\n"
242
 "Most likely this is a bug in the ALSA driver '%s'. Please report this issue "
243
 "to the ALSA developers."
244
 msgid_plural ""
245
-"snd_pcm_delay() returned a value that is exceptionally large: %li bytes (%s"
246
-"%lu ms).\n"
247
+"snd_pcm_delay() returned a value that is exceptionally large: %li bytes "
248
+"(%s%lu ms).\n"
249
 "Most likely this is a bug in the ALSA driver '%s'. Please report this issue "
250
 "to the ALSA developers."
251
 msgstr0 ""
252
@@ -601,92 +615,104 @@
253
 msgid "Modem"
254
 msgstr "მოდემი"
255
 
256
-#: spa/plugins/bluez5/bluez5-device.c:1247
257
+#: spa/plugins/bluez5/bluez5-device.c:1597
258
 msgid "Audio Gateway (A2DP Source & HSP/HFP AG)"
259
 msgstr "Audio Gateway (A2DP წყარო & HSP/HFP AG)"
260
 
261
-#: spa/plugins/bluez5/bluez5-device.c:1272
262
+#: spa/plugins/bluez5/bluez5-device.c:1622
263
 #, c-format
264
 msgid "High Fidelity Playback (A2DP Sink, codec %s)"
265
 msgstr "მაღალი ხარისხის ხმა (A2DP Sink, კოდეკი %s)"
266
 
267
-#: spa/plugins/bluez5/bluez5-device.c:1275
268
+#: spa/plugins/bluez5/bluez5-device.c:1625
269
 #, c-format
270
 msgid "High Fidelity Duplex (A2DP Source/Sink, codec %s)"
271
 msgstr "მაღალი ხარისხის დუპლექსი (A2DP წყარო/Sink, კოდეკი %s)"
272
 
273
-#: spa/plugins/bluez5/bluez5-device.c:1283
274
+#: spa/plugins/bluez5/bluez5-device.c:1633
275
 msgid "High Fidelity Playback (A2DP Sink)"
276
 msgstr "მაღალი ხარისხის ხმა (A2DP Sink)"
277
 
278
-#: spa/plugins/bluez5/bluez5-device.c:1285
279
+#: spa/plugins/bluez5/bluez5-device.c:1635
280
 msgid "High Fidelity Duplex (A2DP Source/Sink)"
281
 msgstr "მაღალი ხარისხის დუპლექსი(A2DP წყარო/Sink)"
282
 
283
-#: spa/plugins/bluez5/bluez5-device.c:1322
284
+#: spa/plugins/bluez5/bluez5-device.c:1677
285
 #, c-format
286
 msgid "High Fidelity Playback (BAP Sink, codec %s)"
287
 msgstr "მაღალი ხარისხის დაკვრა (BAP Sink, კოდეკი %s)"
288
 
289
-#: spa/plugins/bluez5/bluez5-device.c:1326
290
+#: spa/plugins/bluez5/bluez5-device.c:1681
291
 #, c-format
292
 msgid "High Fidelity Input (BAP Source, codec %s)"
293
 msgstr "მაღალი ხარისხის შეყვანა (BAP წყარო, კოდეკი %s)"
294
 
295
-#: spa/plugins/bluez5/bluez5-device.c:1330
296
+#: spa/plugins/bluez5/bluez5-device.c:1685
297
 #, c-format
298
 msgid "High Fidelity Duplex (BAP Source/Sink, codec %s)"
299
 msgstr "მაღალი ხარისხის დუპლექსი (BAP წყარო/Sink, კოდეკი %s)"
300
 
301
-#: spa/plugins/bluez5/bluez5-device.c:1359
302
+#: spa/plugins/bluez5/bluez5-device.c:1693
303
+msgid "High Fidelity Playback (BAP Sink)"
304
+msgstr "მაღალი ხარისხის დაკვრა (BAP Sink)"
305
+
306
+#: spa/plugins/bluez5/bluez5-device.c:1696
307
+msgid "High Fidelity Input (BAP Source)"
308
+msgstr "მაღალი ხარისხის შეყვანა (BAP წყარო)"
309
+
310
+#: spa/plugins/bluez5/bluez5-device.c:1699
311
+msgid "High Fidelity Duplex (BAP Source/Sink)"
312
+msgstr "მაღალი ხარისხის დუპლექსი (BAP წყარო/Sink)"
313
+
314
+#: spa/plugins/bluez5/bluez5-device.c:1735
315
 #, c-format
316
 msgid "Headset Head Unit (HSP/HFP, codec %s)"
317
 msgstr "Headset Head Unit (HSP/HFP, კოდეკი %s)"
318
 
319
-#: spa/plugins/bluez5/bluez5-device.c:1364
320
+#: spa/plugins/bluez5/bluez5-device.c:1740
321
 msgid "Headset Head Unit (HSP/HFP)"
322
 msgstr "Headset Head Unit (HSP/HFP)"
323
 
324
-#: spa/plugins/bluez5/bluez5-device.c:1443
325
-#: spa/plugins/bluez5/bluez5-device.c:1448
326
-#: spa/plugins/bluez5/bluez5-device.c:1455
327
-#: spa/plugins/bluez5/bluez5-device.c:1461
328
-#: spa/plugins/bluez5/bluez5-device.c:1467
329
-#: spa/plugins/bluez5/bluez5-device.c:1473
330
-#: spa/plugins/bluez5/bluez5-device.c:1479
331
-#: spa/plugins/bluez5/bluez5-device.c:1485
332
-#: spa/plugins/bluez5/bluez5-device.c:1491
333
+#: spa/plugins/bluez5/bluez5-device.c:1820
334
+#: spa/plugins/bluez5/bluez5-device.c:1825
335
+#: spa/plugins/bluez5/bluez5-device.c:1832
336
+#: spa/plugins/bluez5/bluez5-device.c:1838
337
+#: spa/plugins/bluez5/bluez5-device.c:1844
338
+#: spa/plugins/bluez5/bluez5-device.c:1850
339
+#: spa/plugins/bluez5/bluez5-device.c:1856
340
+#: spa/plugins/bluez5/bluez5-device.c:1862
341
+#: spa/plugins/bluez5/bluez5-device.c:1868
342
 msgid "Handsfree"
343
 msgstr "ხელის გარეშე სამართავი"
344
 
345
-#: spa/plugins/bluez5/bluez5-device.c:1449
346
+#: spa/plugins/bluez5/bluez5-device.c:1826
347
 msgid "Handsfree (HFP)"
348
 msgstr "ხელის გარეშე სამართავი (HFP)"
349
 
350
-#: spa/plugins/bluez5/bluez5-device.c:1466
351
+#: spa/plugins/bluez5/bluez5-device.c:1843
352
 msgid "Headphone"
353
 msgstr "ყურსაცვამი"
354
 
355
-#: spa/plugins/bluez5/bluez5-device.c:1472
356
+#: spa/plugins/bluez5/bluez5-device.c:1849
357
 msgid "Portable"
358
 msgstr "გადატანადი"
359
 
360
-#: spa/plugins/bluez5/bluez5-device.c:1478
361
+#: spa/plugins/bluez5/bluez5-device.c:1855
362
 msgid "Car"
363
 msgstr "მანქანა"
364
 
365
-#: spa/plugins/bluez5/bluez5-device.c:1484
366
+#: spa/plugins/bluez5/bluez5-device.c:1861
367
 msgid "HiFi"
368
 msgstr "HiFi"
369
 
370
-#: spa/plugins/bluez5/bluez5-device.c:1490
371
+#: spa/plugins/bluez5/bluez5-device.c:1867
372
 msgid "Phone"
373
 msgstr "ტელეფონი"
374
 
375
-#: spa/plugins/bluez5/bluez5-device.c:1497
376
+#: spa/plugins/bluez5/bluez5-device.c:1874
377
 msgid "Bluetooth"
378
-msgstr "Bluetooth"
379
+msgstr "ლურჯკბილა"
380
 
381
-#: spa/plugins/bluez5/bluez5-device.c:1498
382
+#: spa/plugins/bluez5/bluez5-device.c:1875
383
 msgid "Bluetooth (HFP)"
384
-msgstr "Bluetooth (HFP)"
385
+msgstr "ბლუთუზი (HFP)"
386
pipewire-0.3.77.tar.gz/po/sv.po -> pipewire-0.3.79.tar.gz/po/sv.po Changed
287
 
1
@@ -19,8 +19,8 @@
2
 "Project-Id-Version: pipewire\n"
3
 "Report-Msgid-Bugs-To: https://gitlab.freedesktop.org/pipewire/pipewire/-/"
4
 "issues\n"
5
-"POT-Creation-Date: 2023-02-26 15:27+0000\n"
6
-"PO-Revision-Date: 2023-02-26 17:32+0100\n"
7
+"POT-Creation-Date: 2023-08-07 15:27+0000\n"
8
+"PO-Revision-Date: 2023-05-12 18:46+0200\n"
9
 "Last-Translator: Anders Jonsson <anders.jonsson@norsjovallen.se>\n"
10
 "Language-Team: Swedish <tp-sv@listor.tp-sv.se>\n"
11
 "Language: sv\n"
12
@@ -51,36 +51,36 @@
13
 msgid "Start the PipeWire Media System"
14
 msgstr "Starta mediasystemet PipeWire"
15
 
16
-#: src/modules/module-protocol-pulse/modules/module-tunnel-sink.c:159
17
-#: src/modules/module-protocol-pulse/modules/module-tunnel-source.c:159
18
+#: src/modules/module-protocol-pulse/modules/module-tunnel-sink.c:141
19
+#: src/modules/module-protocol-pulse/modules/module-tunnel-source.c:141
20
 #, c-format
21
-msgid "Tunnel to %s/%s"
22
-msgstr "Tunnel till %s/%s"
23
+msgid "Tunnel to %s%s%s"
24
+msgstr "Tunnel till %s%s%s"
25
 
26
 #: src/modules/module-fallback-sink.c:31
27
 msgid "Dummy Output"
28
 msgstr "Attrapputgång"
29
 
30
-#: src/modules/module-pulse-tunnel.c:675
31
+#: src/modules/module-pulse-tunnel.c:847
32
 #, c-format
33
 msgid "Tunnel for %s@%s"
34
 msgstr "Tunnel för %s@%s"
35
 
36
-#: src/modules/module-zeroconf-discover.c:315
37
+#: src/modules/module-zeroconf-discover.c:311
38
 msgid "Unknown device"
39
 msgstr "Okänd enhet"
40
 
41
-#: src/modules/module-zeroconf-discover.c:327
42
+#: src/modules/module-zeroconf-discover.c:323
43
 #, c-format
44
 msgid "%s on %s@%s"
45
 msgstr "%s på %s@%s"
46
 
47
-#: src/modules/module-zeroconf-discover.c:331
48
+#: src/modules/module-zeroconf-discover.c:327
49
 #, c-format
50
 msgid "%s on %s"
51
 msgstr "%s på %s"
52
 
53
-#: src/tools/pw-cat.c:974
54
+#: src/tools/pw-cat.c:979
55
 #, c-format
56
 msgid ""
57
 "%s options <file>|-\n"
58
@@ -95,7 +95,7 @@
59
 "  -v, --verbose                         Aktivera utförliga operationer\n"
60
 "\n"
61
 
62
-#: src/tools/pw-cat.c:981
63
+#: src/tools/pw-cat.c:986
64
 #, c-format
65
 msgid ""
66
 "  -R, --remote                          Remote daemon name\n"
67
@@ -127,7 +127,7 @@
68
 "  -P  --properties                      Sätt nodegenskaper\n"
69
 "\n"
70
 
71
-#: src/tools/pw-cat.c:999
72
+#: src/tools/pw-cat.c:1004
73
 #, c-format
74
 msgid ""
75
 "      --rate                            Sample rate (req. for rec) (default "
76
@@ -162,7 +162,7 @@
77
 "%d)\n"
78
 "\n"
79
 
80
-#: src/tools/pw-cat.c:1016
81
+#: src/tools/pw-cat.c:1021
82
 msgid ""
83
 "  -p, --playback                        Playback mode\n"
84
 "  -r, --record                          Recording mode\n"
85
@@ -178,7 +178,7 @@
86
 "  -o, --encoded                         Kodat läge\n"
87
 "\n"
88
 
89
-#: src/tools/pw-cli.c:2216
90
+#: src/tools/pw-cli.c:2220
91
 #, c-format
92
 msgid ""
93
 "%s options command\n"
94
@@ -197,12 +197,12 @@
95
 "  -m, --monitor                         Övervaka aktivitet\n"
96
 "\n"
97
 
98
-#: spa/plugins/alsa/acp/acp.c:303
99
+#: spa/plugins/alsa/acp/acp.c:325
100
 msgid "Pro Audio"
101
 msgstr "Professionellt ljud"
102
 
103
-#: spa/plugins/alsa/acp/acp.c:427 spa/plugins/alsa/acp/alsa-mixer.c:4648
104
-#: spa/plugins/bluez5/bluez5-device.c:1283
105
+#: spa/plugins/alsa/acp/acp.c:449 spa/plugins/alsa/acp/alsa-mixer.c:4648
106
+#: spa/plugins/bluez5/bluez5-device.c:1586
107
 msgid "Off"
108
 msgstr "Av"
109
 
110
@@ -229,7 +229,7 @@
111
 
112
 #: spa/plugins/alsa/acp/alsa-mixer.c:2657
113
 #: spa/plugins/alsa/acp/alsa-mixer.c:2741
114
-#: spa/plugins/bluez5/bluez5-device.c:1519
115
+#: spa/plugins/bluez5/bluez5-device.c:1831
116
 msgid "Microphone"
117
 msgstr "Mikrofon"
118
 
119
@@ -295,7 +295,7 @@
120
 msgstr "Ingen basökning"
121
 
122
 #: spa/plugins/alsa/acp/alsa-mixer.c:2672
123
-#: spa/plugins/bluez5/bluez5-device.c:1525
124
+#: spa/plugins/bluez5/bluez5-device.c:1837
125
 msgid "Speaker"
126
 msgstr "Högtalare"
127
 
128
@@ -410,7 +410,7 @@
129
 
130
 #: spa/plugins/alsa/acp/alsa-mixer.c:4484
131
 #: spa/plugins/alsa/acp/alsa-mixer.c:4642
132
-#: spa/plugins/bluez5/bluez5-device.c:1507
133
+#: spa/plugins/bluez5/bluez5-device.c:1819
134
 msgid "Headset"
135
 msgstr "Headset"
136
 
137
@@ -524,12 +524,12 @@
138
 msgid "Mono Chat + 7.1 Surround"
139
 msgstr "Mono Chatt + 7.1 Surround"
140
 
141
-#: spa/plugins/alsa/acp/alsa-mixer.c:4754
142
+#: spa/plugins/alsa/acp/alsa-mixer.c:4748
143
 #, c-format
144
 msgid "%s Output"
145
 msgstr "%s-utgång"
146
 
147
-#: spa/plugins/alsa/acp/alsa-mixer.c:4761
148
+#: spa/plugins/alsa/acp/alsa-mixer.c:4756
149
 #, c-format
150
 msgid "%s Input"
151
 msgstr "%s-ingång"
152
@@ -628,104 +628,104 @@
153
 msgid "Modem"
154
 msgstr "Modem"
155
 
156
-#: spa/plugins/bluez5/bluez5-device.c:1294
157
+#: spa/plugins/bluez5/bluez5-device.c:1597
158
 msgid "Audio Gateway (A2DP Source & HSP/HFP AG)"
159
 msgstr "Audio gateway (A2DP-källa & HSP/HFP AG)"
160
 
161
-#: spa/plugins/bluez5/bluez5-device.c:1319
162
+#: spa/plugins/bluez5/bluez5-device.c:1622
163
 #, c-format
164
 msgid "High Fidelity Playback (A2DP Sink, codec %s)"
165
 msgstr "High fidelity-uppspelning (A2DP-utgång, kodek %s)"
166
 
167
-#: spa/plugins/bluez5/bluez5-device.c:1322
168
+#: spa/plugins/bluez5/bluez5-device.c:1625
169
 #, c-format
170
 msgid "High Fidelity Duplex (A2DP Source/Sink, codec %s)"
171
 msgstr "High fidelity duplex (A2DP-källa/utgång, kodek %s)"
172
 
173
-#: spa/plugins/bluez5/bluez5-device.c:1330
174
+#: spa/plugins/bluez5/bluez5-device.c:1633
175
 msgid "High Fidelity Playback (A2DP Sink)"
176
 msgstr "High fidelity-uppspelning (A2DP-utgång)"
177
 
178
-#: spa/plugins/bluez5/bluez5-device.c:1332
179
+#: spa/plugins/bluez5/bluez5-device.c:1635
180
 msgid "High Fidelity Duplex (A2DP Source/Sink)"
181
 msgstr "High fidelity duplex (A2DP-källa/utgång)"
182
 
183
-#: spa/plugins/bluez5/bluez5-device.c:1374
184
+#: spa/plugins/bluez5/bluez5-device.c:1677
185
 #, c-format
186
 msgid "High Fidelity Playback (BAP Sink, codec %s)"
187
 msgstr "High fidelity-uppspelning (BAP-utgång, kodek %s)"
188
 
189
-#: spa/plugins/bluez5/bluez5-device.c:1378
190
+#: spa/plugins/bluez5/bluez5-device.c:1681
191
 #, c-format
192
 msgid "High Fidelity Input (BAP Source, codec %s)"
193
 msgstr "High fidelity-ingång (BAP-källa, kodek %s)"
194
 
195
-#: spa/plugins/bluez5/bluez5-device.c:1382
196
+#: spa/plugins/bluez5/bluez5-device.c:1685
197
 #, c-format
198
 msgid "High Fidelity Duplex (BAP Source/Sink, codec %s)"
199
 msgstr "High fidelity duplex (BAP-källa/utgång, kodek %s)"
200
 
201
-#: spa/plugins/bluez5/bluez5-device.c:1390
202
+#: spa/plugins/bluez5/bluez5-device.c:1693
203
 msgid "High Fidelity Playback (BAP Sink)"
204
 msgstr "High fidelity-uppspelning (BAP-utgång)"
205
 
206
-#: spa/plugins/bluez5/bluez5-device.c:1393
207
+#: spa/plugins/bluez5/bluez5-device.c:1696
208
 msgid "High Fidelity Input (BAP Source)"
209
 msgstr "High fidelity-ingång (BAP-källa)"
210
 
211
-#: spa/plugins/bluez5/bluez5-device.c:1396
212
+#: spa/plugins/bluez5/bluez5-device.c:1699
213
 msgid "High Fidelity Duplex (BAP Source/Sink)"
214
 msgstr "High fidelity duplex (BAP-källa/utgång)"
215
 
216
-#: spa/plugins/bluez5/bluez5-device.c:1424
217
+#: spa/plugins/bluez5/bluez5-device.c:1735
218
 #, c-format
219
 msgid "Headset Head Unit (HSP/HFP, codec %s)"
220
 msgstr "Headset-huvudenhet (HSP/HFP, kodek %s)"
221
 
222
-#: spa/plugins/bluez5/bluez5-device.c:1429
223
+#: spa/plugins/bluez5/bluez5-device.c:1740
224
 msgid "Headset Head Unit (HSP/HFP)"
225
 msgstr "Headset-huvudenhet (HSP/HFP)"
226
 
227
-#: spa/plugins/bluez5/bluez5-device.c:1508
228
-#: spa/plugins/bluez5/bluez5-device.c:1513
229
-#: spa/plugins/bluez5/bluez5-device.c:1520
230
-#: spa/plugins/bluez5/bluez5-device.c:1526
231
-#: spa/plugins/bluez5/bluez5-device.c:1532
232
-#: spa/plugins/bluez5/bluez5-device.c:1538
233
-#: spa/plugins/bluez5/bluez5-device.c:1544
234
-#: spa/plugins/bluez5/bluez5-device.c:1550
235
-#: spa/plugins/bluez5/bluez5-device.c:1556
236
+#: spa/plugins/bluez5/bluez5-device.c:1820
237
+#: spa/plugins/bluez5/bluez5-device.c:1825
238
+#: spa/plugins/bluez5/bluez5-device.c:1832
239
+#: spa/plugins/bluez5/bluez5-device.c:1838
240
+#: spa/plugins/bluez5/bluez5-device.c:1844
241
+#: spa/plugins/bluez5/bluez5-device.c:1850
242
+#: spa/plugins/bluez5/bluez5-device.c:1856
243
+#: spa/plugins/bluez5/bluez5-device.c:1862
244
+#: spa/plugins/bluez5/bluez5-device.c:1868
245
 msgid "Handsfree"
246
 msgstr "Handsfree"
247
 
248
-#: spa/plugins/bluez5/bluez5-device.c:1514
249
+#: spa/plugins/bluez5/bluez5-device.c:1826
250
 msgid "Handsfree (HFP)"
251
 msgstr "Handsfree (HFP)"
252
 
253
-#: spa/plugins/bluez5/bluez5-device.c:1531
254
+#: spa/plugins/bluez5/bluez5-device.c:1843
255
 msgid "Headphone"
256
 msgstr "Hörlurar"
257
 
258
-#: spa/plugins/bluez5/bluez5-device.c:1537
259
+#: spa/plugins/bluez5/bluez5-device.c:1849
260
 msgid "Portable"
261
 msgstr "Bärbar"
262
 
263
-#: spa/plugins/bluez5/bluez5-device.c:1543
264
+#: spa/plugins/bluez5/bluez5-device.c:1855
265
 msgid "Car"
266
 msgstr "Bil"
267
 
268
-#: spa/plugins/bluez5/bluez5-device.c:1549
269
+#: spa/plugins/bluez5/bluez5-device.c:1861
270
 msgid "HiFi"
271
 msgstr "HiFi"
272
 
273
-#: spa/plugins/bluez5/bluez5-device.c:1555
274
+#: spa/plugins/bluez5/bluez5-device.c:1867
275
 msgid "Phone"
276
 msgstr "Telefon"
277
 
278
-#: spa/plugins/bluez5/bluez5-device.c:1562
279
+#: spa/plugins/bluez5/bluez5-device.c:1874
280
 msgid "Bluetooth"
281
 msgstr "Bluetooth"
282
 
283
-#: spa/plugins/bluez5/bluez5-device.c:1563
284
+#: spa/plugins/bluez5/bluez5-device.c:1875
285
 msgid "Bluetooth (HFP)"
286
 msgstr "Bluetooth (HFP)"
287
pipewire-0.3.77.tar.gz/spa/include/spa/node/io.h -> pipewire-0.3.79.tar.gz/spa/include/spa/node/io.h Changed
21
 
1
@@ -117,7 +117,7 @@
2
                      *  is unique per clock and can be used to check if nodes
3
                      *  share the same clock. */
4
    uint64_t nsec;          /**< time in nanoseconds against monotonic clock */
5
-   struct spa_fraction rate;   /**< rate for position/duration/delay */
6
+   struct spa_fraction rate;   /**< rate for position/duration/delay/xrun */
7
    uint64_t position;      /**< current position */
8
    uint64_t duration;      /**< duration of current cycle */
9
    int64_t delay;          /**< delay between position and hardware,
10
@@ -129,8 +129,8 @@
11
    uint64_t target_duration;       /**< target duration of next cycle */
12
    uint32_t target_seq;            /**< seq counter. must be equal at start and
13
                          *  end of read and lower bit must be 0 */
14
-
15
-   uint32_t padding3;
16
+   uint32_t padding;
17
+   uint64_t xrun;          /**< estimated accumulated xrun duration */
18
 };
19
 
20
 /* the size of the video in this cycle */
21
pipewire-0.3.77.tar.gz/spa/include/spa/param/video/dsp-utils.h -> pipewire-0.3.79.tar.gz/spa/include/spa/param/video/dsp-utils.h Changed
16
 
1
@@ -49,9 +49,11 @@
2
    if (info->format != SPA_VIDEO_FORMAT_UNKNOWN)
3
        spa_pod_builder_add(builder,
4
            SPA_FORMAT_VIDEO_format,    SPA_POD_Id(info->format), 0);
5
-   if (info->modifier != 0 || info->flags & SPA_VIDEO_FLAG_MODIFIER)
6
-       spa_pod_builder_add(builder,
7
-           SPA_FORMAT_VIDEO_modifier,  SPA_POD_Long(info->modifier), 0);
8
+   if (info->modifier != 0 || info->flags & SPA_VIDEO_FLAG_MODIFIER) {
9
+       spa_pod_builder_prop(builder,
10
+           SPA_FORMAT_VIDEO_modifier,  SPA_POD_PROP_FLAG_MANDATORY);
11
+       spa_pod_builder_long(builder,           info->modifier);
12
+   }
13
    return (struct spa_pod*)spa_pod_builder_pop(builder, &f);
14
 }
15
 
16
pipewire-0.3.77.tar.gz/spa/include/spa/param/video/raw-utils.h -> pipewire-0.3.79.tar.gz/spa/include/spa/param/video/raw-utils.h Changed
16
 
1
@@ -68,9 +68,11 @@
2
    if (info->framerate.denom != 0)
3
        spa_pod_builder_add(builder,
4
            SPA_FORMAT_VIDEO_framerate, SPA_POD_Fraction(&info->framerate), 0);
5
-   if (info->modifier != 0 || info->flags & SPA_VIDEO_FLAG_MODIFIER)
6
-       spa_pod_builder_add(builder,
7
-           SPA_FORMAT_VIDEO_modifier,  SPA_POD_Long(info->modifier), 0);
8
+   if (info->modifier != 0 || info->flags & SPA_VIDEO_FLAG_MODIFIER) {
9
+       spa_pod_builder_prop(builder,
10
+           SPA_FORMAT_VIDEO_modifier,  SPA_POD_PROP_FLAG_MANDATORY);
11
+       spa_pod_builder_long(builder,           info->modifier);
12
+   }
13
    if (info->max_framerate.denom != 0)
14
        spa_pod_builder_add(builder,
15
            SPA_FORMAT_VIDEO_maxFramerate,  SPA_POD_Fraction(info->max_framerate), 0);
16
pipewire-0.3.77.tar.gz/spa/include/spa/pod/builder.h -> pipewire-0.3.79.tar.gz/spa/include/spa/pod/builder.h Changed
10
 
1
@@ -441,7 +441,7 @@
2
    return res;
3
 }
4
 
5
-static inline uint32_t
6
+static inline int
7
 spa_pod_builder_control(struct spa_pod_builder *builder, uint32_t offset, uint32_t type)
8
 {
9
    const struct { uint32_t offset; uint32_t type; } p = { offset, type };
10
pipewire-0.3.77.tar.gz/spa/include/spa/support/log.h -> pipewire-0.3.79.tar.gz/spa/include/spa/support/log.h Changed
11
 
1
@@ -284,7 +284,8 @@
2
 
3
 /** keys can be given when initializing the logger handle */
4
 #define SPA_KEY_LOG_LEVEL      "log.level"     /**< the default log level */
5
-#define SPA_KEY_LOG_COLORS     "log.colors"        /**< enable colors in the logger */
6
+#define SPA_KEY_LOG_COLORS     "log.colors"        /**< enable colors in the logger, set to "force" to enable
7
+                                 *  colors even when not logging to a terminal */
8
 #define SPA_KEY_LOG_FILE       "log.file"      /**< log to the specified file instead of
9
                                  *  stderr. */
10
 #define SPA_KEY_LOG_TIMESTAMP      "log.timestamp"     /**< log timestamps */
11
pipewire-0.3.77.tar.gz/spa/plugins/alsa/acp/acp.c -> pipewire-0.3.79.tar.gz/spa/plugins/alsa/acp/acp.c Changed
53
 
1
@@ -281,6 +281,18 @@
2
    }
3
 }
4
 
5
+static const char *find_best_verb(pa_card *impl)
6
+{
7
+   const char *res = NULL;
8
+   unsigned prio = 0;
9
+   pa_alsa_ucm_verb *verb;
10
+   PA_LLIST_FOREACH(verb, impl->ucm.verbs) {
11
+       if (verb->priority >= prio)
12
+           res = pa_proplist_gets(verb->proplist, PA_ALSA_PROP_UCM_NAME);
13
+   }
14
+   return res;
15
+}
16
+
17
 static int add_pro_profile(pa_card *impl, uint32_t index)
18
 {
19
    snd_ctl_t *ctl_hndl;
20
@@ -293,6 +305,16 @@
21
    pa_sample_spec ss;
22
    snd_pcm_uframes_t try_period_size, try_buffer_size;
23
 
24
+   if (impl->use_ucm) {
25
+       const char *verb = find_best_verb(impl);
26
+       if (verb == NULL)
27
+           return -ENOTSUP;
28
+       if ((err = snd_use_case_set(impl->ucm.ucm_mgr, "_verb", verb)) < 0) {
29
+           pa_log_error("error setting verb: %s", snd_strerror(err));
30
+           return err;
31
+       }
32
+   }
33
+
34
    ss.format = PA_SAMPLE_S32LE;
35
    ss.rate = impl->rate;
36
    ss.channels = impl->pro_channels;
37
@@ -365,6 +387,7 @@
38
                            0, NULL, NULL, false))) {
39
                pa_alsa_init_proplist_pcm(NULL, m->output_proplist, m->output_pcm);
40
                pa_proplist_setf(m->output_proplist, "clock.name", "api.alsa.%u", index);
41
+               pa_proplist_setf(m->output_proplist, "device.profile.pro", "true");
42
                pa_alsa_close(&m->output_pcm);
43
                m->supported = true;
44
                pa_channel_map_init_auto(&m->channel_map, m->sample_spec.channels, PA_CHANNEL_MAP_AUX);
45
@@ -395,6 +418,7 @@
46
                            0, NULL, NULL, false))) {
47
                pa_alsa_init_proplist_pcm(NULL, m->input_proplist, m->input_pcm);
48
                pa_proplist_setf(m->input_proplist, "clock.name", "api.alsa.%u", index);
49
+               pa_proplist_setf(m->input_proplist, "device.profile.pro", "true");
50
                pa_alsa_close(&m->input_pcm);
51
                m->supported = true;
52
                pa_channel_map_init_auto(&m->channel_map, m->sample_spec.channels, PA_CHANNEL_MAP_AUX);
53
pipewire-0.3.77.tar.gz/spa/plugins/alsa/alsa-pcm.c -> pipewire-0.3.79.tar.gz/spa/plugins/alsa/alsa-pcm.c Changed
102
 
1
@@ -499,9 +499,13 @@
2
 {
3
    uint32_t i;
4
    int err;
5
+   const char *str;
6
 
7
    snd_config_update_free_global();
8
 
9
+   if ((str = spa_dict_lookup(info, "device.profile.pro")) != NULL)
10
+       state->is_pro = spa_atob(str);
11
+
12
    state->multi_rate = true;
13
    state->htimestamp = false;
14
    for (i = 0; info && i < info->n_items; i++) {
15
@@ -1645,31 +1649,27 @@
16
 
17
    dir = 0;
18
    period_size = state->default_period_size;
19
-   is_batch = snd_pcm_hw_params_is_batch(params) &&
20
-       !state->disable_batch;
21
+   is_batch = snd_pcm_hw_params_is_batch(params) && !state->disable_batch;
22
 
23
    /* no period size specified. If we are batch or not using timers,
24
     * use the graph duration as the period */
25
    if (period_size == 0 && (is_batch || state->disable_tsched))
26
-       period_size = state->position ? state->position->clock.duration : DEFAULT_PERIOD;
27
-
28
-   if (is_batch) {
29
-       if (period_size == 0)
30
-           period_size = DEFAULT_PERIOD;
31
-       /* batch devices get their hw pointers updated every period. Make
32
-        * the period smaller and add one period of headroom. Limit the
33
-        * period size to our default so that we don't create too much
34
-        * headroom. */
35
-       if (!state->disable_tsched)
36
+       period_size = state->position ? state->position->clock.target_duration : DEFAULT_PERIOD;
37
+   if (period_size == 0)
38
+       period_size = DEFAULT_PERIOD;
39
+
40
+   if (!state->disable_tsched) {
41
+       if (is_batch) {
42
+           /* batch devices get their hw pointers updated every period. Make
43
+            * the period smaller and add one period of headroom. Limit the
44
+            * period size to our default so that we don't create too much
45
+            * headroom. */
46
            period_size = SPA_MIN(period_size, DEFAULT_PERIOD) / 2;
47
-       spa_log_info(state->log, "%s: batch mode, period_size:%ld",
48
-           state->props.device, period_size);
49
-   } else {
50
-       if (period_size == 0)
51
-           period_size = DEFAULT_PERIOD;
52
-       /* disable ALSA wakeups, if we use a timer */
53
-       if (!state->disable_tsched && snd_pcm_hw_params_can_disable_period_wakeup(params))
54
-           CHECK(snd_pcm_hw_params_set_period_wakeup(hndl, params, 0), "set_period_wakeup");
55
+       } else {
56
+           /* disable ALSA wakeups */
57
+           if (snd_pcm_hw_params_can_disable_period_wakeup(params))
58
+               CHECK(snd_pcm_hw_params_set_period_wakeup(hndl, params, 0), "set_period_wakeup");
59
+       }
60
    }
61
 
62
    CHECK(snd_pcm_hw_params_set_period_size_near(hndl, params, &period_size, &dir), "set_period_size_near");
63
@@ -1729,7 +1729,7 @@
64
 
65
    spa_log_info(state->log, "%s (%s): format:%s access:%s-%s rate:%d channels:%d "
66
            "buffer frames %lu, period frames %lu, periods %u, frame_size %zd "
67
-           "headroom %u start-delay:%u tsched:%u",
68
+           "headroom %u start-delay:%u batch:%u tsched:%u",
69
            state->props.device,
70
            state->stream == SND_PCM_STREAM_CAPTURE ? "capture" : "playback",
71
            snd_pcm_format_name(state->format),
72
@@ -1737,7 +1737,7 @@
73
            planar ? "planar" : "interleaved",
74
            state->rate, state->channels, state->buffer_frames, state->period_frames,
75
            periods, state->frame_size, state->headroom, state->start_delay,
76
-           !state->disable_tsched);
77
+           is_batch, !state->disable_tsched);
78
 
79
    /* write the parameters to device */
80
    CHECK(snd_pcm_hw_params(hndl, params), "set_hw_params");
81
@@ -1931,14 +1931,18 @@
82
 
83
        delay = SPA_TIMEVAL_TO_USEC(&diff);
84
        missing = delay * state->rate / SPA_USEC_PER_SEC;
85
+       if (missing == 0)
86
+           missing = state->threshold;
87
 
88
        spa_log_trace(state->log, "%p: xrun of %"PRIu64" usec %"PRIu64,
89
                state, delay, missing);
90
 
91
+       if (state->clock)
92
+           state->clock->xrun += missing;
93
+       state->sample_count += missing;
94
+
95
        spa_node_call_xrun(&state->callbacks,
96
                SPA_TIMEVAL_TO_USEC(&trigger), delay, NULL);
97
-
98
-       state->sample_count += missing ? missing : state->threshold;
99
        break;
100
    }
101
    case SND_PCM_STATE_SUSPENDED:
102
pipewire-0.3.77.tar.gz/spa/plugins/alsa/alsa-pcm.h -> pipewire-0.3.79.tar.gz/spa/plugins/alsa/alsa-pcm.h Changed
9
 
1
@@ -199,6 +199,7 @@
2
    unsigned int is_hdmi:1;
3
    unsigned int multi_rate:1;
4
    unsigned int htimestamp:1;
5
+   unsigned int is_pro:1;
6
 
7
    uint64_t iec958_codecs;
8
 
9
pipewire-0.3.79.tar.gz/spa/plugins/alsa/mixer/profile-sets/9999-custom.conf Added
24
 
1
@@ -0,0 +1,22 @@
2
+# This file is part of PulseAudio.
3
+#
4
+# PulseAudio is free software; you can redistribute it and/or modify
5
+# it under the terms of the GNU Lesser General Public License as
6
+# published by the Free Software Foundation; either version 2.1 of the
7
+# License, or (at your option) any later version.
8
+#
9
+# PulseAudio is distributed in the hope that it will be useful, but
10
+# WITHOUT ANY WARRANTY; without even the implied warranty of
11
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12
+# General Public License for more details.
13
+#
14
+# You should have received a copy of the GNU Lesser General Public License
15
+# along with PulseAudio; if not, see <http://www.gnu.org/licenses/>.
16
+
17
+; Put your custom profiles here.
18
+
19
+; An example for defining multiple-sink profiles
20
+#Profile output:analog-stereo+output:iec958-stereo+input:analog-stereo
21
+#description = Foobar
22
+#output-mappings = analog-stereo iec958-stereo
23
+#input-mappings = analog-stereo
24
pipewire-0.3.77.tar.gz/spa/plugins/alsa/mixer/profile-sets/default.conf -> pipewire-0.3.79.tar.gz/spa/plugins/alsa/mixer/profile-sets/default.conf Changed
11
 
1
@@ -573,8 +573,4 @@
2
 priority = 1
3
 direction = input
4
 
5
-; An example for defining multiple-sink profiles
6
-#Profile output:analog-stereo+output:iec958-stereo+input:analog-stereo
7
-#description = Foobar
8
-#output-mappings = analog-stereo iec958-stereo
9
-#input-mappings = analog-stereo
10
+.include 9999-custom.conf
11
pipewire-0.3.77.tar.gz/spa/plugins/audioconvert/audioconvert.c -> pipewire-0.3.79.tar.gz/spa/plugins/audioconvert/audioconvert.c Changed
10
 
1
@@ -2594,7 +2594,7 @@
2
    spa_log_trace_fp(this->log, "%p: next match %u", this, match_size);
3
 
4
    if (this->io_rate_match) {
5
-       this->io_rate_match->delay = delay;
6
+       this->io_rate_match->delay = delay + in_queued;
7
        this->io_rate_match->size = match_size;
8
    }
9
    return match_size;
10
pipewire-0.3.77.tar.gz/spa/plugins/audioconvert/fmt-ops-neon.c -> pipewire-0.3.79.tar.gz/spa/plugins/audioconvert/fmt-ops-neon.c Changed
10
 
1
@@ -294,7 +294,7 @@
2
        "      beq 4f\n"
3
        "3:"
4
        "      ld1 { v0.s }0, %s0, #4\n"
5
-       "      ld1 { v2.s }0, %s1, #4\n"
6
+       "      ld1 { v1.s }0, %s1, #4\n"
7
        "      subs %remainder, %remainder, #1\n"
8
        "      sqadd  v0.4s, v0.4s, v2.4s\n"
9
        "      sqadd  v1.4s, v1.4s, v2.4s\n"
10
pipewire-0.3.77.tar.gz/spa/plugins/bluez5/bluez5-dbus.c -> pipewire-0.3.79.tar.gz/spa/plugins/bluez5/bluez5-dbus.c Changed
486
 
1
@@ -193,13 +193,14 @@
2
  * stopped/started rapidly, postpone release until the transport has remained
3
  * unused for a time.
4
  *
5
- * Avoiding unnecessary release+reacquire also makes sense for other transports,
6
- * so we use the release timeout for all of them.
7
+ * Avoiding unnecessary release+reacquire also makes sense for ISO.
8
  */
9
 #define TRANSPORT_RELEASE_TIMEOUT_MSEC 1000
10
 
11
 #define TRANSPORT_VOLUME_TIMEOUT_MSEC 200
12
 
13
+#define SPA_BT_TRANSPORT_IS_A2DP(transport) ((transport)->profile & (SPA_BT_PROFILE_A2DP_SOURCE | SPA_BT_PROFILE_A2DP_SINK))
14
+
15
 static int spa_bt_transport_stop_volume_timer(struct spa_bt_transport *transport);
16
 static int spa_bt_transport_start_volume_timer(struct spa_bt_transport *transport);
17
 static int spa_bt_transport_stop_release_timer(struct spa_bt_transport *transport);
18
@@ -406,8 +407,12 @@
19
 
20
    if (direction == SPA_BT_MEDIA_SOURCE)
21
        endpoint = codec->bap ? BAP_SOURCE_ENDPOINT : A2DP_SOURCE_ENDPOINT;
22
-   else
23
+   else if (direction == SPA_BT_MEDIA_SINK) 
24
        endpoint = codec->bap ? BAP_SINK_ENDPOINT : A2DP_SINK_ENDPOINT;
25
+   else if (direction == SPA_BT_MEDIA_SOURCE_BROADCAST) 
26
+       endpoint = BAP_BROADCAST_SOURCE_ENDPOINT;
27
+   else if (direction == SPA_BT_MEDIA_SINK_BROADCAST) 
28
+       endpoint = BAP_BROADCAST_SINK_ENDPOINT;
29
 
30
    *object_path = spa_aprintf("%s/%s", endpoint,
31
        codec->endpoint_name ? codec->endpoint_name : codec->name);
32
@@ -435,6 +440,12 @@
33
    } else if (spa_strstartswith(endpoint, BAP_SINK_ENDPOINT "/")) {
34
        ep_name = endpoint + strlen(BAP_SINK_ENDPOINT "/");
35
        *sink = true;
36
+   } else if (spa_strstartswith(endpoint, BAP_BROADCAST_SOURCE_ENDPOINT "/")) {
37
+       ep_name = endpoint + strlen(BAP_BROADCAST_SOURCE_ENDPOINT "/");
38
+       *sink = false;
39
+   } else if (spa_strstartswith(endpoint, BAP_BROADCAST_SINK_ENDPOINT "/")) {
40
+       ep_name = endpoint + strlen(BAP_BROADCAST_SINK_ENDPOINT "/");
41
+       *sink = true;
42
    } else {
43
        *sink = true;
44
        return NULL;
45
@@ -471,6 +482,10 @@
46
        return SPA_BT_PROFILE_BAP_SOURCE;
47
    else if (spa_strstartswith(endpoint, BAP_SOURCE_ENDPOINT "/"))
48
        return SPA_BT_PROFILE_BAP_SINK;
49
+   else if (spa_strstartswith(endpoint, BAP_BROADCAST_SINK_ENDPOINT "/"))
50
+       return SPA_BT_PROFILE_BAP_BROADCAST_SOURCE;
51
+   else if (spa_strstartswith(endpoint, BAP_BROADCAST_SOURCE_ENDPOINT "/"))
52
+       return SPA_BT_PROFILE_BAP_BROADCAST_SINK;
53
    else
54
        return SPA_BT_PROFILE_NULL;
55
 }
56
@@ -484,8 +499,10 @@
57
 {
58
    switch (direction) {
59
    case SPA_BT_MEDIA_SOURCE:
60
+   case SPA_BT_MEDIA_SOURCE_BROADCAST:
61
        return codec->encode;
62
    case SPA_BT_MEDIA_SINK:
63
+   case SPA_BT_MEDIA_SINK_BROADCAST:
64
        return codec->decode;
65
    default:
66
        spa_assert_not_reached();
67
@@ -500,6 +517,10 @@
68
        return codec->bap ? SPA_BT_PROFILE_BAP_SOURCE : SPA_BT_PROFILE_A2DP_SOURCE;
69
    case SPA_BT_MEDIA_SINK:
70
        return codec->bap ? SPA_BT_PROFILE_BAP_SINK : SPA_BT_PROFILE_A2DP_SINK;
71
+   case SPA_BT_MEDIA_SOURCE_BROADCAST:
72
+       return SPA_BT_PROFILE_BAP_BROADCAST_SOURCE;
73
+   case SPA_BT_MEDIA_SINK_BROADCAST:
74
+       return SPA_BT_PROFILE_BAP_BROADCAST_SINK;
75
    default:
76
        spa_assert_not_reached();
77
    }
78
@@ -963,6 +984,10 @@
79
                    adapter->profiles |= SPA_BT_PROFILE_BAP_SINK;
80
                    spa_log_debug(monitor->log, "adapter %p: add UUID=%s", adapter, SPA_BT_UUID_BAP_SOURCE);
81
                    adapter->profiles |= SPA_BT_PROFILE_BAP_SOURCE;
82
+                   spa_log_debug(monitor->log, "adapter %p: add UUID=%s", adapter, SPA_BT_UUID_BAP_BROADCAST_SOURCE);
83
+                   adapter->profiles |= SPA_BT_PROFILE_BAP_BROADCAST_SOURCE;
84
+                   spa_log_debug(monitor->log, "adapter %p: add UUID=%s", adapter, SPA_BT_UUID_BAP_BROADCAST_SINK);
85
+                   adapter->profiles |= SPA_BT_PROFILE_BAP_BROADCAST_SINK;
86
                }
87
                dbus_message_iter_next(&iter);
88
            }
89
@@ -1010,6 +1035,14 @@
90
                    spa_log_info(monitor->log, "Adapter %s: LE Audio supported",
91
                            adapter->path);
92
                }
93
+
94
+               if (spa_streq(uuid, SPA_BT_UUID_BAP_BROADCAST_SOURCE) ||
95
+                   spa_streq(uuid, SPA_BT_UUID_BAP_BROADCAST_SINK)) {
96
+                   adapter->le_audio_bcast_supported = true;
97
+                   spa_log_info(monitor->log, "Adapter %s: LE Broadcast Audio supported",
98
+                           adapter->path);
99
+               }
100
+
101
                dbus_message_iter_next(&iter);
102
            }
103
        }
104
@@ -1163,6 +1196,11 @@
105
    if (profiles & SPA_BT_PROFILE_BAP_SOURCE)
106
        mask |= SPA_BT_PROFILE_BAP_SINK;
107
 
108
+   if (profiles & SPA_BT_PROFILE_BAP_BROADCAST_SINK)
109
+       mask |= SPA_BT_PROFILE_BAP_BROADCAST_SOURCE;
110
+   if (profiles & SPA_BT_PROFILE_BAP_BROADCAST_SOURCE)
111
+       mask |= SPA_BT_PROFILE_BAP_BROADCAST_SINK;
112
+
113
    if (profiles & SPA_BT_PROFILE_HSP_AG)
114
        mask |= SPA_BT_PROFILE_HSP_HS;
115
    if (profiles & SPA_BT_PROFILE_HSP_HS)
116
@@ -1624,6 +1662,10 @@
117
        device_try_connect_profile(device, SPA_BT_UUID_BAP_SINK);
118
    if (reconnect & SPA_BT_PROFILE_BAP_SOURCE)
119
        device_try_connect_profile(device, SPA_BT_UUID_BAP_SOURCE);
120
+   if (reconnect & SPA_BT_PROFILE_BAP_BROADCAST_SINK)
121
+       device_try_connect_profile(device, SPA_BT_UUID_BAP_BROADCAST_SINK);
122
+   if (reconnect & SPA_BT_PROFILE_BAP_BROADCAST_SOURCE)
123
+       device_try_connect_profile(device, SPA_BT_UUID_BAP_BROADCAST_SOURCE);
124
 
125
    return reconnect;
126
 }
127
@@ -2228,13 +2270,15 @@
128
            return false;
129
    }
130
 
131
-   if (codec->bap)
132
-       codec_profile = sink ? SPA_BT_PROFILE_BAP_SINK : SPA_BT_PROFILE_BAP_SOURCE;
133
-   else
134
-       codec_profile = sink ? SPA_BT_PROFILE_A2DP_SINK : SPA_BT_PROFILE_A2DP_SOURCE;
135
-
136
    spa_list_for_each(ep, &device->remote_endpoint_list, device_link) {
137
-       const enum spa_bt_profile profile = spa_bt_profile_from_uuid(ep->uuid);
138
+       enum spa_bt_profile profile = spa_bt_profile_from_uuid(ep->uuid);
139
+       if (codec->bap) {
140
+           if ((profile == SPA_BT_PROFILE_BAP_BROADCAST_SINK) || (profile == SPA_BT_PROFILE_BAP_BROADCAST_SOURCE))
141
+               codec_profile = sink ? SPA_BT_PROFILE_BAP_BROADCAST_SINK : SPA_BT_PROFILE_BAP_BROADCAST_SOURCE;
142
+           else
143
+               codec_profile = sink ? SPA_BT_PROFILE_BAP_SINK : SPA_BT_PROFILE_BAP_SOURCE;
144
+       } else
145
+           codec_profile = sink ? SPA_BT_PROFILE_A2DP_SINK : SPA_BT_PROFILE_A2DP_SOURCE;
146
 
147
        if (profile != codec_profile)
148
            continue;
149
@@ -2252,6 +2296,14 @@
150
     * can only know that the currently configured codec is supported.
151
     */
152
    spa_list_for_each(t, &device->transport_list, device_link) {
153
+       if (codec->bap) {
154
+           if((t->profile == SPA_BT_PROFILE_BAP_BROADCAST_SINK) || (t->profile == SPA_BT_PROFILE_BAP_BROADCAST_SOURCE))
155
+               codec_profile = sink ? SPA_BT_PROFILE_BAP_BROADCAST_SINK : SPA_BT_PROFILE_BAP_BROADCAST_SOURCE;
156
+           else
157
+               codec_profile = sink ? SPA_BT_PROFILE_BAP_SINK : SPA_BT_PROFILE_BAP_SOURCE;
158
+       } else
159
+           codec_profile = sink ? SPA_BT_PROFILE_A2DP_SINK : SPA_BT_PROFILE_A2DP_SOURCE;
160
+
161
        if (t->profile != codec_profile)
162
            continue;
163
 
164
@@ -2321,6 +2373,41 @@
165
    return NULL;
166
 }
167
 
168
+static struct spa_bt_device* create_bcast_device(struct spa_bt_monitor *monitor,
169
+                                           const char *object_path)
170
+{  
171
+   struct spa_bt_device *d;
172
+   d = device_create(monitor, object_path);
173
+   if (d == NULL) {
174
+       spa_log_warn(monitor->log, "can't create Bluetooth device %s: %m",
175
+               object_path);
176
+       return NULL;
177
+   }
178
+
179
+   d->adapter = adapter_find(monitor, object_path);
180
+   if (d->adapter == NULL) {
181
+       spa_log_warn(monitor->log, "unknown adapter %s", d->adapter_path);
182
+   }
183
+   d->adapter_path = d->adapter->path;
184
+   d->alias = strdup("bcast_device");
185
+   d->name = strdup("bcast_device");
186
+   d->address = strdup("00:00:00:00:00:00");
187
+   
188
+   spa_bt_device_check_profiles(d, false);
189
+   d->reconnect_state = BT_DEVICE_RECONNECT_INIT;
190
+
191
+   if (!device_props_ready(d))
192
+   {
193
+       return NULL;
194
+   }
195
+
196
+   device_update_hw_volume_profiles(d);
197
+
198
+   spa_bt_device_add_profile(d, SPA_BT_PROFILE_NULL);
199
+
200
+   return d;
201
+}
202
+
203
 static int remote_endpoint_update_props(struct spa_bt_remote_endpoint *remote_endpoint,
204
                DBusMessageIter *props_iter,
205
                DBusMessageIter *invalidated_iter)
206
@@ -2353,8 +2440,25 @@
207
            else if (spa_streq(key, "Device")) {
208
                struct spa_bt_device *device;
209
                device = spa_bt_device_find(monitor, value);
210
-               if (device == NULL)
211
-                   goto next;
212
+               if (device == NULL) {
213
+                   /*
214
+                   * If a broadcast sink endpoint is detected (over DBus) a new device
215
+                   * will be created.  This device will be our simulated remote device. 
216
+                   * This is done because BlueZ sets the adapter as the device
217
+                   * that is connected to for a broadcast sink endpoint/transport.
218
+                   */
219
+                   if(spa_streq(remote_endpoint->uuid, SPA_BT_UUID_BAP_BROADCAST_SINK)) {
220
+                       device = create_bcast_device(monitor, value);
221
+                       if(device == NULL) {
222
+                           goto next;
223
+                       }
224
+                       remote_endpoint->acceptor = true;
225
+                       device_set_connected(device, 1);
226
+                   } else {
227
+                       goto next;
228
+                   }
229
+               }
230
+
231
                spa_log_debug(monitor->log, "remote_endpoint %p: device -> %p", remote_endpoint, device);
232
 
233
                if (remote_endpoint->device != device) {
234
@@ -2492,6 +2596,8 @@
235
    t->latency_us = SPA_BT_UNKNOWN_DELAY;
236
    t->bap_cig = 0xff;
237
    t->bap_cis = 0xff;
238
+   t->bap_big = 0xff;
239
+   t->bap_bis = 0xff;
240
    t->user_data = SPA_PTROFF(t, sizeof(struct spa_bt_transport), void);
241
    spa_hook_list_init(&t->listener_list);
242
    spa_list_init(&t->bap_transport_linked);
243
@@ -2700,7 +2806,8 @@
244
    /* Postpone active transport releases, since we might need it again soon.
245
     * If not active, release now since it has to be reacquired before using again.
246
     */
247
-   if (transport->state == SPA_BT_TRANSPORT_STATE_ACTIVE) {
248
+   if (transport->state == SPA_BT_TRANSPORT_STATE_ACTIVE &&
249
+           !SPA_BT_TRANSPORT_IS_A2DP(transport)) {
250
        return spa_bt_transport_start_release_timer(transport);
251
    } else {
252
        spa_bt_transport_do_release(transport);
253
@@ -2954,6 +3061,12 @@
254
                case SPA_BT_PROFILE_BAP_SINK:
255
                    transport->profile = SPA_BT_PROFILE_BAP_SOURCE;
256
                    break;
257
+               case SPA_BT_PROFILE_BAP_BROADCAST_SOURCE:
258
+                   transport->profile = SPA_BT_PROFILE_BAP_BROADCAST_SINK;
259
+                   break;
260
+               case SPA_BT_PROFILE_BAP_BROADCAST_SINK:
261
+                   transport->profile = SPA_BT_PROFILE_BAP_BROADCAST_SOURCE;
262
+                   break;
263
                default:
264
                    spa_log_warn(monitor->log, "unknown profile %s", value);
265
                    break;
266
@@ -3165,6 +3278,20 @@
267
            else
268
                transport->bap_cis = value;
269
        }
270
+       else if (spa_streq(key, "BIG") || spa_streq(key, "BIS")) {
271
+           uint8_t value;
272
+
273
+           if (type != DBUS_TYPE_BYTE)
274
+               goto next;
275
+           dbus_message_iter_get_basic(&it1, &value);
276
+
277
+           spa_log_debug(monitor->log, "transport %p: %s=%d", transport, key, (int)value);
278
+
279
+           if (spa_streq(key, "BIG"))
280
+               transport->bap_big = value;
281
+           else
282
+               transport->bap_bis = value;
283
+       }
284
 next:
285
        dbus_message_iter_next(props_iter);
286
    }
287
@@ -3261,11 +3388,18 @@
288
    struct spa_bt_monitor *monitor = transport->monitor;
289
    struct spa_bt_transport *t;
290
 
291
-   if (!(transport->profile & (SPA_BT_PROFILE_BAP_SINK | SPA_BT_PROFILE_BAP_SOURCE)))
292
+   if (!(transport->profile & (SPA_BT_PROFILE_BAP_SINK | SPA_BT_PROFILE_BAP_SOURCE |
293
+       SPA_BT_PROFILE_BAP_BROADCAST_SINK | SPA_BT_PROFILE_BAP_BROADCAST_SOURCE)))
294
        return 0;
295
 
296
-   if (transport->bap_cig == 0xff || transport->bap_cis == 0xff)
297
-       return -EINVAL;
298
+   if ((transport->profile == SPA_BT_PROFILE_BAP_BROADCAST_SINK) ||
299
+       (transport->profile == SPA_BT_PROFILE_BAP_BROADCAST_SOURCE)) {
300
+       if (transport->bap_big == 0xff || transport->bap_bis == 0xff)
301
+           return -EINVAL;
302
+   } else {
303
+       if (transport->bap_cig == 0xff || transport->bap_cis == 0xff)
304
+           return -EINVAL;
305
+   }
306
 
307
    if (transport->iso_io) {
308
        spa_log_debug(monitor->log, "transport %p: remove ISO IO", transport);
309
@@ -3275,11 +3409,19 @@
310
 
311
    /* Transports in same connected iso group share the same i/o */
312
    spa_list_for_each(t, &monitor->transport_list, link) {
313
-       if (!(t->profile & (SPA_BT_PROFILE_BAP_SINK | SPA_BT_PROFILE_BAP_SOURCE)))
314
-           continue;
315
-       if (t->bap_cig != transport->bap_cig)
316
+       if (!(t->profile & (SPA_BT_PROFILE_BAP_SINK | SPA_BT_PROFILE_BAP_SOURCE |
317
+               SPA_BT_PROFILE_BAP_BROADCAST_SINK | SPA_BT_PROFILE_BAP_BROADCAST_SOURCE)))
318
            continue;
319
 
320
+       if ((transport->profile == SPA_BT_PROFILE_BAP_BROADCAST_SINK) ||
321
+           (transport->profile == SPA_BT_PROFILE_BAP_BROADCAST_SOURCE)) {
322
+           if (t->bap_big != transport->bap_big)
323
+               continue;
324
+       } else {
325
+           if (t->bap_cig != transport->bap_cig)
326
+               continue;
327
+       }
328
+
329
        if (t->iso_io) {
330
            spa_log_debug(monitor->log, "transport %p: attach ISO IO to %p",
331
                    transport, t);
332
@@ -3358,9 +3500,15 @@
333
        if (transport_create_iso_io(transport) < 0)
334
            spa_log_error(monitor->log, "transport %p: transport_create_iso_io failed",
335
                    transport);
336
-
337
-       if (!transport->bap_initiator)
338
+       /* For broadcast the initiator moves the transport state to SPA_BT_TRANSPORT_STATE_ACTIVE */
339
+       /* TODO: handeling multiple BIGs support */
340
+       if ((transport->profile == SPA_BT_PROFILE_BAP_BROADCAST_SINK) ||
341
+           (transport->profile == SPA_BT_PROFILE_BAP_BROADCAST_SOURCE))    {
342
            spa_bt_transport_set_state(transport, SPA_BT_TRANSPORT_STATE_ACTIVE);
343
+       } else {
344
+           if (!transport->bap_initiator)
345
+               spa_bt_transport_set_state(transport, SPA_BT_TRANSPORT_STATE_ACTIVE);
346
+       }
347
    }
348
 
349
    /* For LE Audio, multiple transport from the same device may share the same
350
@@ -3384,8 +3532,14 @@
351
            spa_log_error(monitor->log, "transport %p: transport_create_iso_io failed",
352
                    t_linked);
353
 
354
-       if (!transport->bap_initiator)
355
-           spa_bt_transport_set_state(t_linked, SPA_BT_TRANSPORT_STATE_ACTIVE);
356
+       /* For broadcast there initiator moves the transport state to SPA_BT_TRANSPORT_STATE_ACTIVE */
357
+       if ((transport->profile == SPA_BT_PROFILE_BAP_BROADCAST_SINK) ||
358
+           (transport->profile == SPA_BT_PROFILE_BAP_BROADCAST_SOURCE))    {
359
+           spa_bt_transport_set_state(transport, SPA_BT_TRANSPORT_STATE_ACTIVE);
360
+       } else {
361
+           if (!transport->bap_initiator)
362
+               spa_bt_transport_set_state(transport, SPA_BT_TRANSPORT_STATE_ACTIVE);
363
+       }
364
    }
365
 
366
    /*
367
@@ -4525,6 +4679,8 @@
368
    }
369
    else if (dbus_message_is_method_call(m, "org.freedesktop.DBus.ObjectManager", "GetManagedObjects")) {
370
        spa_autoptr(DBusMessage) r = NULL;
371
+       struct spa_bt_adapter *a;
372
+       bool register_bcast = false;
373
 
374
        if ((r = dbus_message_new_method_return(m)) == NULL)
375
            return DBUS_HANDLER_RESULT_NEED_MEMORY;
376
@@ -4532,6 +4688,17 @@
377
        dbus_message_iter_init_append(r, &iter);
378
        dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "{oa{sa{sv}}}", &array);
379
 
380
+       /*
381
+        * Verify if an adapter exists that supports bap broadcast.
382
+        * If this adapter exists will register the broadcast endpoint.
383
+        */
384
+       spa_list_for_each(a, &monitor->adapter_list, link) {
385
+           if (a->le_audio_bcast_supported) {
386
+                   register_bcast = true;
387
+                   break;
388
+               }
389
+       }
390
+
391
        for (i = 0; media_codecsi; i++) {
392
            const struct media_codec *codec = media_codecsi;
393
            uint8_t capsA2DP_MAX_CAPS_SIZE;
394
@@ -4573,6 +4740,38 @@
395
                            codec_id, caps, caps_size);
396
                }
397
            }
398
+
399
+           if (codec->bap && register_bcast) {
400
+               if (endpoint_should_be_registered(monitor, codec, SPA_BT_MEDIA_SOURCE_BROADCAST)) {
401
+                   caps_size = codec->fill_caps(codec, 0, caps);
402
+                   if (caps_size < 0)
403
+                       continue;
404
+
405
+                   spa_autofree char *endpoint = NULL;
406
+                   ret = media_codec_to_endpoint(codec, SPA_BT_MEDIA_SOURCE_BROADCAST, &endpoint);
407
+                       if (ret == 0) {
408
+                           spa_log_info(monitor->log, "register media source codec %s: %s", media_codecsi->name, endpoint);
409
+                           append_media_object(&array, endpoint,
410
+                                   SPA_BT_UUID_BAP_BROADCAST_SOURCE,
411
+                                   codec_id, caps, caps_size);
412
+                       }
413
+               }
414
+               
415
+               if (endpoint_should_be_registered(monitor, codec, SPA_BT_MEDIA_SINK_BROADCAST)) {
416
+                   caps_size = codec->fill_caps(codec, MEDIA_CODEC_FLAG_SINK, caps);
417
+                   if (caps_size < 0)
418
+                       continue;
419
+
420
+                   spa_autofree char *endpoint = NULL;
421
+                   ret = media_codec_to_endpoint(codec, SPA_BT_MEDIA_SINK_BROADCAST, &endpoint);
422
+                   if (ret == 0) {
423
+                       spa_log_info(monitor->log, "register broadcast media sink codec %s: %s", media_codecsi->name, endpoint);
424
+                       append_media_object(&array, endpoint,
425
+                               SPA_BT_UUID_BAP_BROADCAST_SINK,
426
+                               codec_id, caps, caps_size);
427
+                   }
428
+               }
429
+           }
430
        }
431
 
432
        dbus_message_iter_close_container(&iter, &array);
433
@@ -4700,6 +4899,10 @@
434
 
435
        register_media_endpoint(monitor, codec, SPA_BT_MEDIA_SOURCE);
436
        register_media_endpoint(monitor, codec, SPA_BT_MEDIA_SINK);
437
+       if (codec->bap) {
438
+           register_media_endpoint(monitor, codec, SPA_BT_MEDIA_SOURCE_BROADCAST);
439
+           register_media_endpoint(monitor, codec, SPA_BT_MEDIA_SINK_BROADCAST);
440
+       }
441
    }
442
 
443
    return 0;
444
@@ -4732,6 +4935,10 @@
445
 
446
        unregister_media_endpoint(monitor, codec, SPA_BT_MEDIA_SOURCE);
447
        unregister_media_endpoint(monitor, codec, SPA_BT_MEDIA_SINK);
448
+       if (codec->bap) {
449
+           unregister_media_endpoint(monitor, codec, SPA_BT_MEDIA_SOURCE_BROADCAST);
450
+           unregister_media_endpoint(monitor, codec, SPA_BT_MEDIA_SINK_BROADCAST);
451
+       }
452
    }
453
 
454
    dbus_connection_unregister_object_path(monitor->conn, BAP_OBJECT_MANAGER_PATH);
455
@@ -4749,7 +4956,9 @@
456
        if (codec->bap != bap)
457
            continue;
458
        if (endpoint_should_be_registered(monitor, codec, SPA_BT_MEDIA_SINK) ||
459
-               endpoint_should_be_registered(monitor, codec, SPA_BT_MEDIA_SOURCE))
460
+               endpoint_should_be_registered(monitor, codec, SPA_BT_MEDIA_SOURCE) ||
461
+               endpoint_should_be_registered(monitor, codec, SPA_BT_MEDIA_SOURCE_BROADCAST) || 
462
+               endpoint_should_be_registered(monitor, codec, SPA_BT_MEDIA_SINK_BROADCAST))
463
            return true;
464
    }
465
    return false;
466
@@ -4768,7 +4977,7 @@
467
    if (!bap && a->a2dp_application_registered)
468
        return 0;
469
 
470
-   if (bap && !a->le_audio_supported) {
471
+   if ((bap && !a->le_audio_supported) && (bap && !a->le_audio_bcast_supported)) {
472
        spa_log_info(monitor->log, "Adapter %s indicates LE Audio unsupported: not registering application",
473
                a->path);
474
        return -ENOTSUP;
475
@@ -5485,6 +5694,10 @@
476
            profiles |= SPA_BT_PROFILE_BAP_SINK;
477
        } else if (spa_streq(role_name, "bap_source")) {
478
            profiles |= SPA_BT_PROFILE_BAP_SOURCE;
479
+       } else if (spa_streq(role_name, "bap_bcast_source")) {
480
+           profiles |= SPA_BT_PROFILE_BAP_BROADCAST_SOURCE;
481
+       } else if (spa_streq(role_name, "bap_bcast_sink")) {
482
+           profiles |= SPA_BT_PROFILE_BAP_BROADCAST_SINK;
483
        }
484
    }
485
 
486
pipewire-0.3.77.tar.gz/spa/plugins/bluez5/bluez5-device.c -> pipewire-0.3.79.tar.gz/spa/plugins/bluez5/bluez5-device.c Changed
156
 
1
@@ -1051,6 +1051,26 @@
2
                emit_device_set_node(this, DEVICE_ID_SINK_SET);
3
        }
4
 
5
+       if (this->bt_dev->connected_profiles & (SPA_BT_PROFILE_BAP_BROADCAST_SINK)) {
6
+           t = find_transport(this, SPA_BT_PROFILE_BAP_BROADCAST_SINK, this->props.codec);
7
+           if (t) {
8
+               this->props.codec = t->media_codec->id;
9
+               emit_node(this, t, DEVICE_ID_SINK, SPA_NAME_API_BLUEZ5_MEDIA_SINK, false);
10
+           }
11
+
12
+           if (this->device_set.leader && this->device_set.sinks > 0)
13
+               emit_device_set_node(this, DEVICE_ID_SINK_SET);
14
+       }
15
+
16
+       if (this->bt_dev->connected_profiles & (SPA_BT_PROFILE_BAP_BROADCAST_SOURCE)) {
17
+           t = find_transport(this, SPA_BT_PROFILE_BAP_BROADCAST_SOURCE, this->props.codec);
18
+           if (t) {
19
+               this->props.codec = t->media_codec->id;
20
+               emit_dynamic_node(&this->dyn_media_source, this, t,
21
+                   DEVICE_ID_SOURCE, SPA_NAME_API_BLUEZ5_MEDIA_SOURCE, false);
22
+           }
23
+       }
24
+
25
        if (get_supported_media_codec(this, this->props.codec, NULL) == NULL)
26
            this->props.codec = 0;
27
        break;
28
@@ -1467,19 +1487,8 @@
29
    if (profile == DEVICE_PROFILE_OFF || profile == DEVICE_PROFILE_AG)
30
        return profile;
31
 
32
-   if (profile == DEVICE_PROFILE_A2DP) {
33
-       if (codec == 0 || (this->bt_dev->connected_profiles & SPA_BT_PROFILE_MEDIA_SOURCE))
34
-           return profile;
35
-
36
-       return codec + DEVICE_PROFILE_LAST;
37
-   }
38
-
39
-   if (profile == DEVICE_PROFILE_BAP) {
40
-       if (codec == 0)
41
-           return profile;
42
-
43
+   if ((profile == DEVICE_PROFILE_A2DP) || (profile == DEVICE_PROFILE_BAP))
44
        return codec + DEVICE_PROFILE_LAST;
45
-   }
46
 
47
    if (profile == DEVICE_PROFILE_HSP_HFP) {
48
        if (codec == 0 || (this->bt_dev->connected_profiles & SPA_BT_PROFILE_HFP_AG))
49
@@ -1607,6 +1616,11 @@
50
        if (!(profile & SPA_BT_PROFILE_A2DP_SINK)) {
51
            return NULL;
52
        }
53
+
54
+       /* A2DP will only enlist codec profiles */
55
+       if (!codec)
56
+           return NULL;
57
+
58
        name = spa_bt_profile_name(profile);
59
        n_sink++;
60
        if (codec) {
61
@@ -1617,7 +1631,15 @@
62
                return NULL;
63
            }
64
            name_and_codec = spa_aprintf("%s-%s", name, media_codec->name);
65
-           name = name_and_codec;
66
+
67
+           /*
68
+            * Give base name to highest priority profile, so that best codec can be
69
+            * selected at command line with out knowing which codecs are actually
70
+            * supported
71
+            */
72
+           if (idx != 0)
73
+               name = name_and_codec;
74
+
75
            if (profile == SPA_BT_PROFILE_A2DP_SINK && !media_codec->duplex_codec) {
76
                desc_and_codec = spa_aprintf(_("High Fidelity Playback (A2DP Sink, codec %s)"),
77
                                 media_codec->description);
78
@@ -1641,29 +1663,28 @@
79
    case DEVICE_PROFILE_BAP:
80
    {
81
        uint32_t profile = device->connected_profiles &
82
-             (SPA_BT_PROFILE_BAP_SINK | SPA_BT_PROFILE_BAP_SOURCE);
83
+             (SPA_BT_PROFILE_BAP_SINK | SPA_BT_PROFILE_BAP_SOURCE 
84
+               | SPA_BT_PROFILE_BAP_BROADCAST_SOURCE 
85
+               | SPA_BT_PROFILE_BAP_BROADCAST_SINK);
86
        size_t idx;
87
        const struct media_codec *media_codec;
88
 
89
+       /* BAP will only enlist codec profiles */
90
+       if (codec == 0)
91
+           return NULL;
92
+
93
        if (profile == 0)
94
            return NULL;
95
 
96
-       if (profile & (SPA_BT_PROFILE_BAP_SINK))
97
+       if ((profile & (SPA_BT_PROFILE_BAP_SINK)) || 
98
+           (profile & (SPA_BT_PROFILE_BAP_BROADCAST_SINK)))
99
            n_sink++;
100
-       if (profile & (SPA_BT_PROFILE_BAP_SOURCE))
101
+       if ((profile & (SPA_BT_PROFILE_BAP_SOURCE)) || 
102
+           (profile & (SPA_BT_PROFILE_BAP_BROADCAST_SOURCE)))
103
            n_source++;
104
 
105
        name = spa_bt_profile_name(profile);
106
 
107
-       /* If we can't codec switch, emit codecless profile */
108
-       if (current && !can_bap_codec_switch(this)) {
109
-           codec = 0;
110
-           index = get_index_from_profile(this, profile_index, codec);
111
-       } else if ((codec != 0) != can_bap_codec_switch(this)) {
112
-           errno = -EINVAL;
113
-           return NULL;
114
-       }
115
-
116
        if (codec) {
117
            media_codec = get_supported_media_codec(this, codec, &idx);
118
            if (media_codec == NULL) {
119
@@ -1671,13 +1692,23 @@
120
                return NULL;
121
            }
122
            name_and_codec = spa_aprintf("%s-%s", name, media_codec->name);
123
-           name = name_and_codec;
124
+
125
+           /*
126
+            * Give base name to highest priority profile, so that best codec can be
127
+            * selected at command line with out knowing which codecs are actually
128
+            * supported
129
+            */
130
+           if (idx != 0)
131
+               name = name_and_codec;
132
+
133
            switch (profile) {
134
            case SPA_BT_PROFILE_BAP_SINK:
135
+           case SPA_BT_PROFILE_BAP_BROADCAST_SINK:
136
                desc_and_codec = spa_aprintf(_("High Fidelity Playback (BAP Sink, codec %s)"),
137
                        media_codec->description);
138
                break;
139
            case SPA_BT_PROFILE_BAP_SOURCE:
140
+           case SPA_BT_PROFILE_BAP_BROADCAST_SOURCE:
141
                desc_and_codec = spa_aprintf(_("High Fidelity Input (BAP Source, codec %s)"),
142
                        media_codec->description);
143
                break;
144
@@ -1690,9 +1721,11 @@
145
        } else {
146
            switch (profile) {
147
            case SPA_BT_PROFILE_BAP_SINK:
148
+           case SPA_BT_PROFILE_BAP_BROADCAST_SINK:
149
                desc = _("High Fidelity Playback (BAP Sink)");
150
                break;
151
            case SPA_BT_PROFILE_BAP_SOURCE:
152
+           case SPA_BT_PROFILE_BAP_BROADCAST_SOURCE:
153
                desc = _("High Fidelity Input (BAP Source)");
154
                break;
155
            default:
156
pipewire-0.3.77.tar.gz/spa/plugins/bluez5/defs.h -> pipewire-0.3.79.tar.gz/spa/plugins/bluez5/defs.h Changed
89
 
1
@@ -125,6 +125,8 @@
2
 #define SPA_BT_UUID_PACS        "00001850-0000-1000-8000-00805f9b34fb"
3
 #define SPA_BT_UUID_BAP_SINK    "00002bc9-0000-1000-8000-00805f9b34fb"
4
 #define SPA_BT_UUID_BAP_SOURCE  "00002bcb-0000-1000-8000-00805f9b34fb"
5
+#define SPA_BT_UUID_BAP_BROADCAST_SOURCE  "00001852-0000-1000-8000-00805f9b34fb"
6
+#define SPA_BT_UUID_BAP_BROADCAST_SINK    "00001851-0000-1000-8000-00805f9b34fb"
7
 
8
 #define PROFILE_HSP_AG "/Profile/HSPAG"
9
 #define PROFILE_HSP_HS "/Profile/HSPHS"
10
@@ -149,6 +151,8 @@
11
 #define BAP_OBJECT_MANAGER_PATH "/MediaEndpointLE"
12
 #define BAP_SINK_ENDPOINT  BAP_OBJECT_MANAGER_PATH "/BAPSink"
13
 #define BAP_SOURCE_ENDPOINT    BAP_OBJECT_MANAGER_PATH "/BAPSource"
14
+#define BAP_BROADCAST_SOURCE_ENDPOINT  BAP_OBJECT_MANAGER_PATH "/BAPBroadcastSource"
15
+#define BAP_BROADCAST_SINK_ENDPOINT        BAP_OBJECT_MANAGER_PATH "/BAPBroadcastSink"
16
 
17
 #define SPA_BT_UNKNOWN_DELAY           0
18
 
19
@@ -163,6 +167,8 @@
20
 enum spa_bt_media_direction {
21
    SPA_BT_MEDIA_SOURCE,
22
    SPA_BT_MEDIA_SINK,
23
+   SPA_BT_MEDIA_SOURCE_BROADCAST,
24
+   SPA_BT_MEDIA_SINK_BROADCAST,
25
 };
26
 
27
 enum spa_bt_profile {
28
@@ -175,6 +181,8 @@
29
    SPA_BT_PROFILE_HSP_AG =     (1 << 5),
30
    SPA_BT_PROFILE_HFP_HF =     (1 << 6),
31
    SPA_BT_PROFILE_HFP_AG =     (1 << 7),
32
+   SPA_BT_PROFILE_BAP_BROADCAST_SOURCE =   (1 << 8),
33
+   SPA_BT_PROFILE_BAP_BROADCAST_SINK   =   (1 << 9),
34
 
35
    SPA_BT_PROFILE_A2DP_DUPLEX =    (SPA_BT_PROFILE_A2DP_SINK | SPA_BT_PROFILE_A2DP_SOURCE),
36
    SPA_BT_PROFILE_BAP_DUPLEX =     (SPA_BT_PROFILE_BAP_SINK | SPA_BT_PROFILE_BAP_SOURCE),
37
@@ -182,8 +190,10 @@
38
    SPA_BT_PROFILE_HEADSET_AUDIO_GATEWAY = (SPA_BT_PROFILE_HSP_AG | SPA_BT_PROFILE_HFP_AG),
39
    SPA_BT_PROFILE_HEADSET_AUDIO =  (SPA_BT_PROFILE_HEADSET_HEAD_UNIT | SPA_BT_PROFILE_HEADSET_AUDIO_GATEWAY),
40
 
41
-   SPA_BT_PROFILE_MEDIA_SINK =     (SPA_BT_PROFILE_A2DP_SINK | SPA_BT_PROFILE_BAP_SINK),
42
-   SPA_BT_PROFILE_MEDIA_SOURCE =   (SPA_BT_PROFILE_A2DP_SOURCE | SPA_BT_PROFILE_BAP_SOURCE),
43
+   SPA_BT_PROFILE_MEDIA_SINK =     (SPA_BT_PROFILE_A2DP_SINK | SPA_BT_PROFILE_BAP_SINK |
44
+                                       SPA_BT_PROFILE_BAP_BROADCAST_SINK),
45
+   SPA_BT_PROFILE_MEDIA_SOURCE =   (SPA_BT_PROFILE_A2DP_SOURCE | SPA_BT_PROFILE_BAP_SOURCE |
46
+                                       SPA_BT_PROFILE_BAP_BROADCAST_SOURCE),
47
 };
48
 
49
 static inline enum spa_bt_profile spa_bt_profile_from_uuid(const char *uuid)
50
@@ -206,6 +216,10 @@
51
        return SPA_BT_PROFILE_BAP_SINK;
52
    else if (strcasecmp(uuid, SPA_BT_UUID_BAP_SOURCE) == 0)
53
        return SPA_BT_PROFILE_BAP_SOURCE;
54
+   else if (strcasecmp(uuid, SPA_BT_UUID_BAP_BROADCAST_SOURCE) == 0)
55
+       return SPA_BT_PROFILE_BAP_BROADCAST_SOURCE;
56
+   else if (strcasecmp(uuid, SPA_BT_UUID_BAP_BROADCAST_SINK) == 0)
57
+       return SPA_BT_PROFILE_BAP_BROADCAST_SINK;
58
    else
59
        return 0;
60
 }
61
@@ -307,8 +321,10 @@
62
       case SPA_BT_PROFILE_HEADSET_AUDIO:
63
    return "headset-audio";
64
       case SPA_BT_PROFILE_BAP_SOURCE:
65
+      case SPA_BT_PROFILE_BAP_BROADCAST_SOURCE:
66
         return "bap-source";
67
       case SPA_BT_PROFILE_BAP_SINK:
68
+      case SPA_BT_PROFILE_BAP_BROADCAST_SINK:
69
         return "bap-sink";
70
       case SPA_BT_PROFILE_BAP_DUPLEX:
71
         return "bap-duplex";
72
@@ -349,6 +365,7 @@
73
    unsigned int le_audio_supported:1;
74
    unsigned int has_adapter1_interface:1;
75
    unsigned int has_media1_interface:1;
76
+   unsigned int le_audio_bcast_supported:1;
77
 };
78
 
79
 enum spa_bt_form_factor {
80
@@ -630,6 +647,8 @@
81
    unsigned int latency_us;
82
    uint8_t bap_cig;
83
    uint8_t bap_cis;
84
+   uint8_t bap_big;
85
+   uint8_t bap_bis;
86
    uint32_t bap_interval;
87
 
88
    struct spa_bt_iso_io *iso_io;
89
pipewire-0.3.77.tar.gz/spa/plugins/bluez5/iso-io.c -> pipewire-0.3.79.tar.gz/spa/plugins/bluez5/iso-io.c Changed
17
 
1
@@ -315,7 +315,14 @@
2
    int block_size = 0;
3
    struct spa_audio_info format = { 0 };
4
    int res;
5
-   bool sink = (t->profile & SPA_BT_PROFILE_BAP_SINK) != 0;
6
+   bool sink;
7
+   if((t->profile == SPA_BT_PROFILE_BAP_SINK) || 
8
+       (t->profile == SPA_BT_PROFILE_BAP_BROADCAST_SINK)) {
9
+       sink = true;
10
+   } else {
11
+       sink = false;
12
+   }
13
+
14
 
15
    if (!t->media_codec->bap) {
16
        res = -EINVAL;
17
pipewire-0.3.77.tar.gz/spa/plugins/support/evl-system.c -> pipewire-0.3.79.tar.gz/spa/plugins/support/evl-system.c Changed
63
 
1
@@ -18,6 +18,7 @@
2
 #include <spa/support/log.h>
3
 #include <spa/support/system.h>
4
 #include <spa/support/plugin.h>
5
+#include <spa/utils/names.h>
6
 #include <spa/utils/type.h>
7
 #include <spa/utils/result.h>
8
 #include <spa/utils/string.h>
9
@@ -133,7 +134,7 @@
10
    e->fd = fd;
11
    e->events = events;
12
    e->data = data;
13
-   return evl_add_pollfd(pfd, fd, e->events);
14
+   return evl_add_pollfd(pfd, fd, e->events, evl_nil);
15
 }
16
 
17
 static int impl_pollfd_mod(void *object, int pfd, int fd, uint32_t events, void *data)
18
@@ -147,7 +148,7 @@
19
 
20
    e->events = events;
21
    e->data = data;
22
-   return evl_mod_pollfd(pfd, fd, e->events);
23
+   return evl_mod_pollfd(pfd, fd, e->events, evl_nil);
24
 }
25
 
26
 static int impl_pollfd_del(void *object, int pfd, int fd)
27
@@ -248,10 +249,8 @@
28
 }
29
 static int impl_timerfd_read(void *object, int fd, uint64_t *expirations)
30
 {
31
-   uint32_t ticks;
32
-   if (oob_read(fd, &ticks, sizeof(ticks)) != sizeof(ticks))
33
+   if (oob_read(fd, expirations, sizeof(uint64_t)) != sizeof(uint64_t))
34
        return -errno;
35
-   *expirations = ticks;
36
    return 0;
37
 }
38
 
39
@@ -259,17 +258,18 @@
40
 static int impl_eventfd_create(void *object, int flags)
41
 {
42
    struct impl *impl = object;
43
-   int res;
44
+   int res, fl;
45
+
46
+   fl = EVL_CLONE_PRIVATE;
47
+   if (flags & SPA_FD_NONBLOCK)
48
+       fl |= EVL_CLONE_NONBLOCK;
49
 
50
-   res = evl_new_xbuf(1024, 1024, "xbuf-%d-%p-%d", impl->pid, impl, impl->n_xbuf);
51
+   res = evl_create_xbuf(1024, 1024, fl, "xbuf-%d-%p-%d", impl->pid, impl, impl->n_xbuf);
52
    if (res < 0)
53
        return res;
54
 
55
    impl->n_xbuf++;
56
 
57
-   if (flags & SPA_FD_NONBLOCK)
58
-       fcntl(res, F_SETFL, fcntl(res, F_GETFL) | O_NONBLOCK);
59
-
60
    return res;
61
 }
62
 
63
pipewire-0.3.77.tar.gz/spa/plugins/support/logger.c -> pipewire-0.3.79.tar.gz/spa/plugins/support/logger.c Changed
37
 
1
@@ -295,6 +295,7 @@
2
    struct spa_loop *loop = NULL;
3
    const char *str, *dest = "";
4
    bool linebuf = false;
5
+   bool force_colors = false;
6
 
7
    spa_return_val_if_fail(factory != NULL, -EINVAL);
8
    spa_return_val_if_fail(handle != NULL, -EINVAL);
9
@@ -333,8 +334,14 @@
10
            this->timestamp = spa_atob(str);
11
        if ((str = spa_dict_lookup(info, SPA_KEY_LOG_LINE)) != NULL)
12
            this->line = spa_atob(str);
13
-       if ((str = spa_dict_lookup(info, SPA_KEY_LOG_COLORS)) != NULL)
14
-           this->colors = spa_atob(str);
15
+       if ((str = spa_dict_lookup(info, SPA_KEY_LOG_COLORS)) != NULL) {
16
+           if (spa_streq(str, "force")) {
17
+               this->colors = true;
18
+               force_colors = true;
19
+           } else {
20
+               this->colors = spa_atob(str);
21
+           }
22
+       }
23
        if ((str = spa_dict_lookup(info, SPA_KEY_LOG_LEVEL)) != NULL)
24
            this->log.level = atoi(str);
25
        if ((str = spa_dict_lookup(info, SPA_KEY_LOG_FILE)) != NULL) {
26
@@ -363,8 +370,9 @@
27
    if (linebuf)
28
        setlinebuf(this->file);
29
 
30
-   if (!isatty(fileno(this->file)))
31
+   if (!isatty(fileno(this->file)) && !force_colors) {
32
        this->colors = false;
33
+   }
34
 
35
    spa_ringbuffer_init(&this->trace_rb);
36
 
37
pipewire-0.3.77.tar.gz/spa/plugins/support/meson.build -> pipewire-0.3.79.tar.gz/spa/plugins/support/meson.build Changed
13
 
1
@@ -24,9 +24,9 @@
2
 spa_support_dep = declare_dependency(link_with: spa_support_lib)
3
 
4
 if get_option('evl').allowed()
5
-  evl_inc = include_directories('/usr/evl/include')
6
+  evl_inc = include_directories('/usr/include')
7
   evl_lib = cc.find_library('evl',
8
-                            dirs: '/usr/evl/lib/',
9
+                            dirs: '/usr/lib/',
10
                             required: get_option('evl'))
11
 
12
   spa_evl_sources = 'evl-system.c', 'evl-plugin.c'
13
pipewire-0.3.77.tar.gz/spa/plugins/v4l2/v4l2-udev.c -> pipewire-0.3.79.tar.gz/spa/plugins/v4l2/v4l2-udev.c Changed
54
 
1
@@ -393,6 +393,19 @@
2
    }
3
 }
4
 
5
+static int stop_inotify(struct device *dev)
6
+{
7
+   struct impl *impl = dev->impl;
8
+   if (dev->notify.fd == -1)
9
+       return 0;
10
+   spa_log_info(impl->log, "stop inotify for /dev/video%u", dev->id);
11
+   spa_loop_remove_source(impl->main_loop, &dev->notify);
12
+   close(dev->notify.fd);
13
+   dev->notify.fd = -1;
14
+   return 0;
15
+}
16
+
17
+
18
 static void impl_on_notify_events(struct spa_source *source)
19
 {
20
    struct device *dev = source->data;
21
@@ -402,7 +415,12 @@
22
        struct inotify_event e; /* for appropriate alignment */
23
    } buf;
24
 
25
-   while (true) {
26
+   if (source->rmask & (SPA_IO_ERR | SPA_IO_HUP)) {
27
+       spa_log_warn(impl->log, "notify error on /dev/video%u", dev->id);
28
+       stop_inotify(dev);
29
+       return;
30
+   }
31
+   while (source->rmask & SPA_IO_IN) {
32
        ssize_t len;
33
        const struct inotify_event *event;
34
        void *p, *e;
35
@@ -469,18 +487,6 @@
36
    return 0;
37
 }
38
 
39
-static int stop_inotify(struct device *dev)
40
-{
41
-   struct impl *impl = dev->impl;
42
-   if (dev->notify.fd == -1)
43
-       return 0;
44
-   spa_log_info(impl->log, "stop inotify for /dev/video%u", dev->id);
45
-   spa_loop_remove_source(impl->main_loop, &dev->notify);
46
-   close(dev->notify.fd);
47
-   dev->notify.fd = -1;
48
-   return 0;
49
-}
50
-
51
 static void impl_on_fd_events(struct spa_source *source)
52
 {
53
    struct impl *impl = source->data;
54
pipewire-0.3.77.tar.gz/src/daemon/client-rt.conf.in -> pipewire-0.3.79.tar.gz/src/daemon/client-rt.conf.in Changed
41
 
1
@@ -94,13 +94,33 @@
2
     #dither.noise = 0
3
 }
4
 
5
+stream.rules = 
6
+    {   matches = 
7
+            {
8
+                # all keys must match the value. ! negates. ~ starts regex.
9
+                #application.name       = "pw-cat"
10
+                #node.name         = "~Google Chrome$"
11
+            }
12
+        
13
+        actions = {
14
+            update-props = {
15
+                #node.latency = 512/48000
16
+            }
17
+        }
18
+    }
19
+
20
+
21
 alsa.properties = {
22
-    #alsa.format = 0
23
-    #alsa.rate = 0
24
-    #alsa.channels = 0
25
-    #alsa.period-bytes = 0
26
-    #alsa.buffer-bytes = 0
27
-    #alsa.volume-method = cubic        # linear, cubic
28
+    # ALSA params take a single value, an array  of values
29
+    # or a range { min=.. max=... }
30
+    #alsa.access =  MMAP_INTERLEAVED MMAP_NONINTERLEAVED RW_INTERLEAVED RW_NONINTERLEAVED 
31
+    #alsa.format =  FLOAT S32 S24 S24_3 S16 U8 
32
+    #alsa.rate = { min=1 max=384000 }      # or  44100 48000 .. 
33
+    #alsa.channels = { min=1 max=64 }      # or  2 4 6 .. 
34
+    #alsa.period-bytes = { min=128 max=2097152 } # or  128 256 1024 .. 
35
+    #alsa.buffer-bytes = { min=256 max=4194304 } # or  256 512 4096 .. 
36
+
37
+    #alsa.volume-method = cubic            # linear, cubic
38
 }
39
 
40
 # client specific properties
41
pipewire-0.3.77.tar.gz/src/daemon/jack.conf.in -> pipewire-0.3.79.tar.gz/src/daemon/jack.conf.in Changed
10
 
1
@@ -95,7 +95,7 @@
2
 jack.rules = 
3
     {   matches = 
4
             {
5
-                # all keys must match the value. ~ starts regex.
6
+                # all keys must match the value. ! negates. ~ starts regex.
7
                 #client.name                = "Carla"
8
                 #application.process.binary = "jack_simple_client"
9
                 #application.name           = "~jack_simple_client.*"
10
pipewire-0.3.77.tar.gz/src/daemon/pipewire-pulse.conf.in -> pipewire-0.3.79.tar.gz/src/daemon/pipewire-pulse.conf.in Changed
10
 
1
@@ -116,7 +116,7 @@
2
     {
3
         matches = 
4
             {
5
-                # all keys must match the value. ~ starts regex.
6
+                # all keys must match the value. ! negates. ~ starts regex.
7
                 #client.name                = "Firefox"
8
                 #application.process.binary = "teams"
9
                 #application.name           = "~speech-dispatcher.*"
10
pipewire-0.3.77.tar.gz/src/gst/gstpipewiredeviceprovider.c -> pipewire-0.3.79.tar.gz/src/gst/gstpipewiredeviceprovider.c Changed
20
 
1
@@ -665,11 +665,16 @@
2
 {
3
   GstPipeWireDeviceProvider *self = GST_PIPEWIRE_DEVICE_PROVIDER (provider);
4
 
5
-  pw_thread_loop_lock (self->core->loop);
6
+  /* core might be NULL if we failed to connect in _start. */
7
+  if (self->core != NULL) {
8
+    pw_thread_loop_lock (self->core->loop);
9
+  }
10
   GST_DEBUG_OBJECT (self, "stopping provider");
11
 
12
   g_clear_pointer ((struct pw_proxy**)&self->registry, pw_proxy_destroy);
13
-  pw_thread_loop_unlock (self->core->loop);
14
+  if (self->core != NULL) {
15
+    pw_thread_loop_unlock (self->core->loop);
16
+  }
17
   g_clear_pointer (&self->core, gst_pipewire_core_release);
18
 }
19
 
20
pipewire-0.3.77.tar.gz/src/modules/meson.build -> pipewire-0.3.79.tar.gz/src/modules/meson.build Changed
10
 
1
@@ -356,6 +356,8 @@
2
   'module-protocol-pulse/stream.c',
3
   'module-protocol-pulse/utils.c',
4
   'module-protocol-pulse/volume.c',
5
+  'module-protocol-pulse/modules/module-alsa-sink.c',
6
+  'module-protocol-pulse/modules/module-alsa-source.c',
7
   'module-protocol-pulse/modules/module-always-sink.c',
8
   'module-protocol-pulse/modules/module-combine-sink.c',
9
   'module-protocol-pulse/modules/module-echo-cancel.c',
10
pipewire-0.3.77.tar.gz/src/modules/module-combine-stream.c -> pipewire-0.3.79.tar.gz/src/modules/module-combine-stream.c Changed
10
 
1
@@ -93,7 +93,7 @@
2
  *                     # any of the items in matches needs to match, if one does,
3
  *                     # actions are emited.
4
  *                     {
5
- *                         # all keys must match the value. ~ in value starts regex.
6
+ *                         # all keys must match the value. ! negates. ~ starts regex.
7
  *                         #node.name = "~alsa_input.*"
8
  *                         media.class = "Audio/Sink"
9
  *                     }
10
pipewire-0.3.77.tar.gz/src/modules/module-profiler.c -> pipewire-0.3.79.tar.gz/src/modules/module-profiler.c Changed
13
 
1
@@ -104,7 +104,11 @@
2
    struct spa_source *flush_event;
3
    unsigned int listening:1;
4
 
5
+#ifdef max_align_t
6
    alignas(max_align_t)
7
+#else
8
+   alignas(64)
9
+#endif
10
    uint8_t flushFLUSH_BUFFER + sizeof(struct spa_pod_struct);
11
 };
12
 
13
pipewire-0.3.77.tar.gz/src/modules/module-protocol-pulse/manager.c -> pipewire-0.3.79.tar.gz/src/modules/module-protocol-pulse/manager.c Changed
14
 
1
@@ -641,9 +641,10 @@
2
 
3
    o->this.removing = true;
4
 
5
-   if (!o->this.creating)
6
+   if (!o->this.creating) {
7
+       o->this.change_mask = ~0;
8
        manager_emit_removed(m, &o->this);
9
-
10
+   }
11
    object_destroy(o);
12
 }
13
 
14
pipewire-0.3.79.tar.gz/src/modules/module-protocol-pulse/modules/module-alsa-sink.c Added
241
 
1
@@ -0,0 +1,239 @@
2
+/* PipeWire */
3
+/* SPDX-FileCopyrightText: Copyright © 2023 Wim Taymans <wim.taymans@gmail.com> */
4
+/* SPDX-License-Identifier: MIT */
5
+
6
+#include <pipewire/pipewire.h>
7
+
8
+#include "../manager.h"
9
+#include "../module.h"
10
+
11
+#define NAME "alsa-sink"
12
+
13
+#define DEFAULT_DEVICE "default"
14
+
15
+PW_LOG_TOPIC_STATIC(mod_topic, "mod." NAME);
16
+#define PW_LOG_TOPIC_DEFAULT mod_topic
17
+
18
+struct module_alsa_sink_data {
19
+   struct pw_core *core;
20
+   struct spa_hook core_listener;
21
+
22
+   struct pw_proxy *proxy;
23
+   struct spa_hook proxy_listener;
24
+};
25
+
26
+static void module_alsa_sink_proxy_removed(void *data)
27
+{
28
+   struct module *module = data;
29
+   struct module_alsa_sink_data *d = module->user_data;
30
+   pw_proxy_destroy(d->proxy);
31
+}
32
+
33
+static void module_alsa_sink_proxy_destroy(void *data)
34
+{
35
+   struct module *module = data;
36
+   struct module_alsa_sink_data *d = module->user_data;
37
+
38
+   pw_log_info("proxy %p destroy", d->proxy);
39
+
40
+   spa_hook_remove(&d->proxy_listener);
41
+   d->proxy = NULL;
42
+
43
+   module_schedule_unload(module);
44
+}
45
+
46
+static void module_alsa_sink_proxy_bound_props(void *data, uint32_t global_id, const struct spa_dict *props)
47
+{
48
+   struct module *module = data;
49
+   struct module_alsa_sink_data *d = module->user_data;
50
+
51
+   pw_log_info("proxy %p bound", d->proxy);
52
+
53
+   module_emit_loaded(module, 0);
54
+}
55
+
56
+static void module_alsa_sink_proxy_error(void *data, int seq, int res, const char *message)
57
+{
58
+   struct module *module = data;
59
+   struct module_alsa_sink_data *d = module->user_data;
60
+
61
+   pw_log_info("proxy %p error %d", d->proxy, res);
62
+
63
+   pw_proxy_destroy(d->proxy);
64
+}
65
+
66
+static const struct pw_proxy_events proxy_events = {
67
+   PW_VERSION_PROXY_EVENTS,
68
+   .removed = module_alsa_sink_proxy_removed,
69
+   .bound_props = module_alsa_sink_proxy_bound_props,
70
+   .error = module_alsa_sink_proxy_error,
71
+   .destroy = module_alsa_sink_proxy_destroy,
72
+};
73
+
74
+static void module_alsa_sink_core_error(void *data, uint32_t id, int seq, int res, const char *message)
75
+{
76
+   struct module *module = data;
77
+
78
+   pw_log_warn("error id:%u seq:%d res:%d (%s): %s",
79
+           id, seq, res, spa_strerror(res), message);
80
+
81
+   if (id == PW_ID_CORE && res == -EPIPE)
82
+       module_schedule_unload(module);
83
+}
84
+
85
+static const struct pw_core_events core_events = {
86
+   PW_VERSION_CORE_EVENTS,
87
+   .error = module_alsa_sink_core_error,
88
+};
89
+
90
+static int module_alsa_sink_load(struct module *module)
91
+{
92
+   struct module_alsa_sink_data *d = module->user_data;
93
+
94
+   d->core = pw_context_connect(module->impl->context, NULL, 0);
95
+   if (d->core == NULL)
96
+       return -errno;
97
+
98
+   pw_core_add_listener(d->core, &d->core_listener, &core_events, module);
99
+
100
+   pw_properties_setf(module->props, "pulse.module.id", "%u", module->index);
101
+
102
+   d->proxy = pw_core_create_object(d->core,
103
+                    "adapter", PW_TYPE_INTERFACE_Node, PW_VERSION_NODE,
104
+                    module->props ? &module->props->dict : NULL, 0);
105
+   if (d->proxy == NULL)
106
+       return -errno;
107
+
108
+   pw_proxy_add_listener(d->proxy, &d->proxy_listener, &proxy_events, module);
109
+
110
+   return SPA_RESULT_RETURN_ASYNC(0);
111
+}
112
+
113
+static int module_alsa_sink_unload(struct module *module)
114
+{
115
+   struct module_alsa_sink_data *d = module->user_data;
116
+
117
+   if (d->proxy != NULL) {
118
+       spa_hook_remove(&d->proxy_listener);
119
+       pw_proxy_destroy(d->proxy);
120
+       d->proxy = NULL;
121
+   }
122
+
123
+   if (d->core != NULL) {
124
+       spa_hook_remove(&d->core_listener);
125
+       pw_core_disconnect(d->core);
126
+       d->core = NULL;
127
+   }
128
+
129
+   return 0;
130
+}
131
+
132
+static const struct spa_dict_item module_alsa_sink_info = {
133
+   { PW_KEY_MODULE_AUTHOR, "Wim Taymans <wim.taymans@gmail.com>" },
134
+   { PW_KEY_MODULE_DESCRIPTION, "An ALSA sink" },
135
+   { PW_KEY_MODULE_USAGE,
136
+       "name=<name of the sink, to be prefixed> "
137
+       "sink_name=<name for the sink> "
138
+       "sink_properties=<properties for the sink> "
139
+       "namereg_fail=<when false attempt to synthesise new sink_name if it is already taken> "
140
+       "device=<ALSA device> "
141
+       "device_id=<ALSA card index> "
142
+       "format=<sample format> "
143
+       "rate=<sample rate> "
144
+       "alternate_rate=<alternate sample rate> "
145
+       "channels=<number of channels> "
146
+       "channel_map=<channel map> "
147
+       "fragments=<number of fragments> "
148
+       "fragment_size=<fragment size> "
149
+       "mmap=<enable memory mapping?> "
150
+       "tsched=<enable system timer based scheduling mode?> "
151
+       "tsched_buffer_size=<buffer size when using timer based scheduling> "
152
+       "tsched_buffer_watermark=<lower fill watermark> "
153
+       "ignore_dB=<ignore dB information from the device?> "
154
+       "control=<name of mixer control, or name and index separated by a comma> "
155
+       "rewind_safeguard=<number of bytes that cannot be rewound> "
156
+       "deferred_volume=<Synchronize software and hardware volume changes to avoid momentary jumps?> "
157
+       "deferred_volume_safety_margin=<usec adjustment depending on volume direction> "
158
+       "deferred_volume_extra_delay=<usec adjustment to HW volume changes> "
159
+       "fixed_latency_range=<disable latency range changes on underrun?>" },
160
+   { PW_KEY_MODULE_VERSION, PACKAGE_VERSION },
161
+};
162
+
163
+static int module_alsa_sink_prepare(struct module * const module)
164
+{
165
+   struct pw_properties * const props = module->props;
166
+   const char *str, *dev_id;
167
+   struct spa_audio_info_raw info = { 0 };
168
+
169
+   PW_LOG_TOPIC_INIT(mod_topic);
170
+
171
+   dev_id = pw_properties_get(props, "device_id");
172
+   if (dev_id == NULL)
173
+       dev_id = pw_properties_get(props, "device");
174
+   if (dev_id == NULL)
175
+       dev_id = DEFAULT_DEVICE;
176
+
177
+   pw_properties_set(props, "api.alsa.path", dev_id);
178
+
179
+   if ((str = pw_properties_get(props, "sink_name")) != NULL) {
180
+       pw_properties_set(props, PW_KEY_NODE_NAME, str);
181
+       pw_properties_set(props, "sink_name", NULL);
182
+   }
183
+   else if ((str = pw_properties_get(props, "name")) != NULL) {
184
+       pw_properties_setf(props, PW_KEY_NODE_NAME, "alsa_output.%s", str);
185
+       pw_properties_set(props, "name", NULL);
186
+   }
187
+   else {
188
+       pw_properties_setf(props, PW_KEY_NODE_NAME, "alsa_output.%s", dev_id);
189
+   }
190
+
191
+   if ((str = pw_properties_get(props, "sink_properties")) != NULL) {
192
+       module_args_add_props(props, str);
193
+       pw_properties_set(props, "sink_properties", NULL);
194
+   }
195
+
196
+   if ((str = pw_properties_get(props, "fragments")) != NULL) {
197
+       pw_properties_set(props, "api.alsa.period-num", str);
198
+       pw_properties_set(props, "fragments", NULL);
199
+   }
200
+   if ((str = pw_properties_get(props, "fragment_size")) != NULL) {
201
+       pw_properties_set(props, "api.alsa.period-size", str);
202
+       pw_properties_set(props, "fragment_size", NULL);
203
+   }
204
+   if ((str = pw_properties_get(props, "mmap")) != NULL) {
205
+       pw_properties_setf(props, "api.alsa.disable-mmap",
206
+               spa_atob(str) ? "false" : "true");
207
+       pw_properties_set(props, "mmap", NULL);
208
+   }
209
+
210
+   if (module_args_to_audioinfo_keys(module->impl, props,
211
+           "format", "rate", "channels", "channel_map", &info) < 0)
212
+       return -EINVAL;
213
+
214
+   audioinfo_to_properties(&info, props);
215
+
216
+   if (pw_properties_get(props, PW_KEY_MEDIA_CLASS) == NULL)
217
+       pw_properties_set(props, PW_KEY_MEDIA_CLASS, "Audio/Sink");
218
+
219
+   if ((str = pw_properties_get(props, PW_KEY_NODE_DESCRIPTION)) == NULL)
220
+       pw_properties_setf(props, PW_KEY_NODE_DESCRIPTION,
221
+                       "ALSA Sink on %s", dev_id);
222
+
223
+   pw_properties_set(props, PW_KEY_FACTORY_NAME, "api.alsa.pcm.sink");
224
+
225
+   if (pw_properties_get(props, "monitor.channel-volumes") == NULL)
226
+       pw_properties_set(props, "monitor.channel-volumes", "true");
227
+   if (pw_properties_get(props, "node.suspend-on-idle") == NULL)
228
+       pw_properties_set(props, "node.suspend-on-idle", "true");
229
+
230
+   return 0;
231
+}
232
+
233
+DEFINE_MODULE_INFO(module_alsa_sink) = {
234
+   .name = "module-alsa-sink",
235
+   .prepare = module_alsa_sink_prepare,
236
+   .load = module_alsa_sink_load,
237
+   .unload = module_alsa_sink_unload,
238
+   .properties = &SPA_DICT_INIT_ARRAY(module_alsa_sink_info),
239
+   .data_size = sizeof(struct module_alsa_sink_data),
240
+};
241
pipewire-0.3.79.tar.gz/src/modules/module-protocol-pulse/modules/module-alsa-source.c Added
241
 
1
@@ -0,0 +1,239 @@
2
+/* PipeWire */
3
+/* SPDX-FileCopyrightText: Copyright © 2023 Wim Taymans <wim.taymans@gmail.com> */
4
+/* SPDX-License-Identifier: MIT */
5
+
6
+#include <pipewire/pipewire.h>
7
+
8
+#include "../manager.h"
9
+#include "../module.h"
10
+
11
+#define NAME "alsa-source"
12
+
13
+#define DEFAULT_DEVICE "default"
14
+
15
+PW_LOG_TOPIC_STATIC(mod_topic, "mod." NAME);
16
+#define PW_LOG_TOPIC_DEFAULT mod_topic
17
+
18
+struct module_alsa_source_data {
19
+   struct pw_core *core;
20
+   struct spa_hook core_listener;
21
+
22
+   struct pw_proxy *proxy;
23
+   struct spa_hook proxy_listener;
24
+};
25
+
26
+static void module_alsa_source_proxy_removed(void *data)
27
+{
28
+   struct module *module = data;
29
+   struct module_alsa_source_data *d = module->user_data;
30
+   pw_proxy_destroy(d->proxy);
31
+}
32
+
33
+static void module_alsa_source_proxy_destroy(void *data)
34
+{
35
+   struct module *module = data;
36
+   struct module_alsa_source_data *d = module->user_data;
37
+
38
+   pw_log_info("proxy %p destroy", d->proxy);
39
+
40
+   spa_hook_remove(&d->proxy_listener);
41
+   d->proxy = NULL;
42
+
43
+   module_schedule_unload(module);
44
+}
45
+
46
+static void module_alsa_source_proxy_bound_props(void *data, uint32_t global_id, const struct spa_dict *props)
47
+{
48
+   struct module *module = data;
49
+   struct module_alsa_source_data *d = module->user_data;
50
+
51
+   pw_log_info("proxy %p bound", d->proxy);
52
+
53
+   module_emit_loaded(module, 0);
54
+}
55
+
56
+static void module_alsa_source_proxy_error(void *data, int seq, int res, const char *message)
57
+{
58
+   struct module *module = data;
59
+   struct module_alsa_source_data *d = module->user_data;
60
+
61
+   pw_log_info("proxy %p error %d", d->proxy, res);
62
+
63
+   pw_proxy_destroy(d->proxy);
64
+}
65
+
66
+static const struct pw_proxy_events proxy_events = {
67
+   PW_VERSION_PROXY_EVENTS,
68
+   .removed = module_alsa_source_proxy_removed,
69
+   .bound_props = module_alsa_source_proxy_bound_props,
70
+   .error = module_alsa_source_proxy_error,
71
+   .destroy = module_alsa_source_proxy_destroy,
72
+};
73
+
74
+static void module_alsa_source_core_error(void *data, uint32_t id, int seq, int res, const char *message)
75
+{
76
+   struct module *module = data;
77
+
78
+   pw_log_warn("error id:%u seq:%d res:%d (%s): %s",
79
+           id, seq, res, spa_strerror(res), message);
80
+
81
+   if (id == PW_ID_CORE && res == -EPIPE)
82
+       module_schedule_unload(module);
83
+}
84
+
85
+static const struct pw_core_events core_events = {
86
+   PW_VERSION_CORE_EVENTS,
87
+   .error = module_alsa_source_core_error,
88
+};
89
+
90
+static int module_alsa_source_load(struct module *module)
91
+{
92
+   struct module_alsa_source_data *d = module->user_data;
93
+
94
+   d->core = pw_context_connect(module->impl->context, NULL, 0);
95
+   if (d->core == NULL)
96
+       return -errno;
97
+
98
+   pw_core_add_listener(d->core, &d->core_listener, &core_events, module);
99
+
100
+   pw_properties_setf(module->props, "pulse.module.id", "%u", module->index);
101
+
102
+   d->proxy = pw_core_create_object(d->core,
103
+                    "adapter", PW_TYPE_INTERFACE_Node, PW_VERSION_NODE,
104
+                    module->props ? &module->props->dict : NULL, 0);
105
+   if (d->proxy == NULL)
106
+       return -errno;
107
+
108
+   pw_proxy_add_listener(d->proxy, &d->proxy_listener, &proxy_events, module);
109
+
110
+   return SPA_RESULT_RETURN_ASYNC(0);
111
+}
112
+
113
+static int module_alsa_source_unload(struct module *module)
114
+{
115
+   struct module_alsa_source_data *d = module->user_data;
116
+
117
+   if (d->proxy != NULL) {
118
+       spa_hook_remove(&d->proxy_listener);
119
+       pw_proxy_destroy(d->proxy);
120
+       d->proxy = NULL;
121
+   }
122
+
123
+   if (d->core != NULL) {
124
+       spa_hook_remove(&d->core_listener);
125
+       pw_core_disconnect(d->core);
126
+       d->core = NULL;
127
+   }
128
+
129
+   return 0;
130
+}
131
+
132
+static const struct spa_dict_item module_alsa_source_info = {
133
+   { PW_KEY_MODULE_AUTHOR, "Wim Taymans <wim.taymans@gmail.com>" },
134
+   { PW_KEY_MODULE_DESCRIPTION, "An ALSA source" },
135
+   { PW_KEY_MODULE_USAGE,
136
+       "name=<name of the source, to be prefixed> "
137
+       "source_name=<name for the source> "
138
+       "source_properties=<properties for the source> "
139
+       "namereg_fail=<when false attempt to synthesise new source_name if it is already taken> "
140
+       "device=<ALSA device> "
141
+       "device_id=<ALSA card index> "
142
+       "format=<sample format> "
143
+       "rate=<sample rate> "
144
+       "alternate_rate=<alternate sample rate> "
145
+       "channels=<number of channels> "
146
+       "channel_map=<channel map> "
147
+       "fragments=<number of fragments> "
148
+       "fragment_size=<fragment size> "
149
+       "mmap=<enable memory mapping?> "
150
+       "tsched=<enable system timer based scheduling mode?> "
151
+       "tsched_buffer_size=<buffer size when using timer based scheduling> "
152
+       "tsched_buffer_watermark=<lower fill watermark> "
153
+       "ignore_dB=<ignore dB information from the device?> "
154
+       "control=<name of mixer control, or name and index separated by a comma> "
155
+       "rewind_safeguard=<number of bytes that cannot be rewound> "
156
+       "deferred_volume=<Synchronize software and hardware volume changes to avoid momentary jumps?> "
157
+       "deferred_volume_safety_margin=<usec adjustment depending on volume direction> "
158
+       "deferred_volume_extra_delay=<usec adjustment to HW volume changes> "
159
+       "fixed_latency_range=<disable latency range changes on underrun?>" },
160
+   { PW_KEY_MODULE_VERSION, PACKAGE_VERSION },
161
+};
162
+
163
+static int module_alsa_source_prepare(struct module * const module)
164
+{
165
+   struct pw_properties * const props = module->props;
166
+   const char *str, *dev_id;
167
+   struct spa_audio_info_raw info = { 0 };
168
+
169
+   PW_LOG_TOPIC_INIT(mod_topic);
170
+
171
+   dev_id = pw_properties_get(props, "device_id");
172
+   if (dev_id == NULL)
173
+       dev_id = pw_properties_get(props, "device");
174
+   if (dev_id == NULL)
175
+       dev_id = DEFAULT_DEVICE;
176
+
177
+   pw_properties_set(props, "api.alsa.path", dev_id);
178
+
179
+   if ((str = pw_properties_get(props, "source_name")) != NULL) {
180
+       pw_properties_set(props, PW_KEY_NODE_NAME, str);
181
+       pw_properties_set(props, "source_name", NULL);
182
+   }
183
+   else if ((str = pw_properties_get(props, "name")) != NULL) {
184
+       pw_properties_setf(props, PW_KEY_NODE_NAME, "alsa_output.%s", str);
185
+       pw_properties_set(props, "name", NULL);
186
+   }
187
+   else {
188
+       pw_properties_setf(props, PW_KEY_NODE_NAME, "alsa_output.%s", dev_id);
189
+   }
190
+
191
+   if ((str = pw_properties_get(props, "source_properties")) != NULL) {
192
+       module_args_add_props(props, str);
193
+       pw_properties_set(props, "source_properties", NULL);
194
+   }
195
+
196
+   if ((str = pw_properties_get(props, "fragments")) != NULL) {
197
+       pw_properties_set(props, "api.alsa.period-num", str);
198
+       pw_properties_set(props, "fragments", NULL);
199
+   }
200
+   if ((str = pw_properties_get(props, "fragment_size")) != NULL) {
201
+       pw_properties_set(props, "api.alsa.period-size", str);
202
+       pw_properties_set(props, "fragment_size", NULL);
203
+   }
204
+   if ((str = pw_properties_get(props, "mmap")) != NULL) {
205
+       pw_properties_setf(props, "api.alsa.disable-mmap",
206
+               spa_atob(str) ? "false" : "true");
207
+       pw_properties_set(props, "mmap", NULL);
208
+   }
209
+
210
+   if (module_args_to_audioinfo_keys(module->impl, props,
211
+           "format", "rate", "channels", "channel_map", &info) < 0)
212
+       return -EINVAL;
213
+
214
+   audioinfo_to_properties(&info, props);
215
+
216
+   if (pw_properties_get(props, PW_KEY_MEDIA_CLASS) == NULL)
217
+       pw_properties_set(props, PW_KEY_MEDIA_CLASS, "Audio/Source");
218
+
219
+   if ((str = pw_properties_get(props, PW_KEY_NODE_DESCRIPTION)) == NULL)
220
+       pw_properties_setf(props, PW_KEY_NODE_DESCRIPTION,
221
+                       "ALSA Source on %s", dev_id);
222
+
223
+   pw_properties_set(props, PW_KEY_FACTORY_NAME, "api.alsa.pcm.source");
224
+
225
+   if (pw_properties_get(props, "monitor.channel-volumes") == NULL)
226
+       pw_properties_set(props, "monitor.channel-volumes", "true");
227
+   if (pw_properties_get(props, "node.suspend-on-idle") == NULL)
228
+       pw_properties_set(props, "node.suspend-on-idle", "true");
229
+
230
+   return 0;
231
+}
232
+
233
+DEFINE_MODULE_INFO(module_alsa_source) = {
234
+   .name = "module-alsa-source",
235
+   .prepare = module_alsa_source_prepare,
236
+   .load = module_alsa_source_load,
237
+   .unload = module_alsa_source_unload,
238
+   .properties = &SPA_DICT_INIT_ARRAY(module_alsa_source_info),
239
+   .data_size = sizeof(struct module_alsa_source_data),
240
+};
241
pipewire-0.3.77.tar.gz/src/modules/module-rtp-sap.c -> pipewire-0.3.79.tar.gz/src/modules/module-rtp-sap.c Changed
44
 
1
@@ -75,7 +75,7 @@
2
  *             {   matches = 
3
  *                     # any of the items in matches needs to match, if one does,
4
  *                     # actions are emited.
5
- *                     {   # all keys must match the value. ~ in value starts regex.
6
+ *                     {   # all keys must match the value. ! negates. ~ starts regex.
7
  *                         #rtp.origin = "wim 3883629975 0 IN IP4 0.0.0.0"
8
  *                         #rtp.payload = "127"
9
  *                         #rtp.fmt = "L16/48000/2"
10
@@ -91,7 +91,7 @@
11
  *                 }
12
  *             }
13
  *             {   matches = 
14
- *                     {   # all keys must match the value. ~ in value starts regex.
15
+ *                     {   # all keys must match the value. ! negates. ~ starts regex.
16
  *                         #rtp.origin = "wim 3883629975 0 IN IP4 0.0.0.0"
17
  *                         #rtp.payload = "127"
18
  *                         #rtp.fmt = "L16/48000/2"
19
@@ -1435,6 +1435,7 @@
20
    uint32_t port;
21
    const char *str;
22
    int res = 0;
23
+   char addr64;
24
 
25
    PW_LOG_TOPIC_INIT(mod_topic);
26
 
27
@@ -1484,7 +1485,15 @@
28
                res = ioctl(fd, SIOCGIFADDR, &req);
29
                if (res < 0)
30
                    pw_log_warn("SIOCGIFADDR %s failed: %m", impl->ifname);
31
-               str = inet_ntoa(((struct sockaddr_in *)&req.ifr_addr)->sin_addr);
32
+               str = inet_ntop(req.ifr_addr.sa_family,
33
+                       &((struct sockaddr_in *)&req.ifr_addr)->sin_addr,
34
+                       addr, sizeof(addr));
35
+               if (str == NULL) {
36
+                   pw_log_warn("can't parse interface ip: %m");
37
+                   str = DEFAULT_SOURCE_IP;
38
+               } else {
39
+                   pw_log_info("interface %s IP: %s", impl->ifname, str);
40
+               }
41
                close(fd);
42
            }
43
        }
44
pipewire-0.3.77.tar.gz/src/modules/module-vban/audio.c -> pipewire-0.3.79.tar.gz/src/modules/module-vban/audio.c Changed
28
 
1
@@ -103,7 +103,7 @@
2
 
3
    hlen = VBAN_HEADER_SIZE;
4
    plen = len - hlen;
5
-   samples = SPA_MIN(hdr->format_nbs, plen / stride);
6
+   samples = SPA_MIN(hdr->format_nbs+1, plen / stride);
7
 
8
    n_frames = hdr->n_frames;
9
    if (impl->have_sync && impl->n_frames != n_frames) {
10
@@ -132,7 +132,7 @@
11
        filled = impl->target_buffer;
12
 
13
        spa_dll_init(&impl->dll);
14
-       spa_dll_set_bw(&impl->dll, SPA_DLL_BW_MIN, 128, impl->rate);
15
+       spa_dll_set_bw(&impl->dll, SPA_DLL_BW_MAX, 128, impl->rate);
16
        memset(impl->buffer, 0, BUFFER_SIZE);
17
        impl->have_sync = true;
18
    } else if (expected_write != write) {
19
@@ -145,7 +145,7 @@
20
                BUFFER_SIZE / stride);
21
        impl->have_sync = false;
22
    } else {
23
-       pw_log_debug("got samples:%u", samples);
24
+       pw_log_trace("got samples:%u", samples);
25
        spa_ringbuffer_write_data(&impl->ring,
26
                impl->buffer,
27
                BUFFER_SIZE,
28
pipewire-0.3.77.tar.gz/src/modules/module-vban/stream.c -> pipewire-0.3.79.tar.gz/src/modules/module-vban/stream.c Changed
10
 
1
@@ -393,7 +393,7 @@
2
        pw_properties_setf(props, "vban.channels", "%u", impl->info.info.raw.channels);
3
 
4
    spa_dll_init(&impl->dll);
5
-   spa_dll_set_bw(&impl->dll, SPA_DLL_BW_MIN, 128, impl->rate);
6
+   spa_dll_set_bw(&impl->dll, SPA_DLL_BW_MAX, 128, impl->rate);
7
    impl->corr = 1.0;
8
 
9
    impl->stream = pw_stream_new(core, "vban-session", props);
10
pipewire-0.3.77.tar.gz/src/pipewire/conf.c -> pipewire-0.3.79.tar.gz/src/pipewire/conf.c Changed
70
 
1
@@ -586,6 +586,7 @@
2
 /*
3
  * {
4
  *     # all keys must match the value. ~ in value starts regex.
5
+ *     # ! as the first char of the value negates the match
6
  *     <key> = <value>
7
  *     ...
8
  * }
9
@@ -598,7 +599,7 @@
10
        char key256, val1024;
11
        const char *str, *value;
12
        int match = 0, fail = 0;
13
-       int len;
14
+       int len, skip = 0;
15
 
16
        while (spa_json_get_string(&it0, key, sizeof(key)) > 0) {
17
            bool success = false;
18
@@ -615,18 +616,28 @@
19
                    continue;
20
                value = val;
21
                len = strlen(val);
22
+               if (len > 0 && value0 == '!') {
23
+                   success = !success;
24
+                   skip++;
25
+               }
26
            }
27
            if (str != NULL) {
28
-               if (value0 == '~') {
29
+               if (valueskip == '~') {
30
                    regex_t preg;
31
-                   if (regcomp(&preg, value+1, REG_EXTENDED | REG_NOSUB) == 0) {
32
+                   int res;
33
+                   skip++;
34
+                   if ((res = regcomp(&preg, value+skip, REG_EXTENDED | REG_NOSUB)) != 0) {
35
+                       char errbuf1024;
36
+                       regerror(res, &preg, errbuf, sizeof(errbuf));
37
+                       pw_log_warn("invalid regex %s: %s", value+skip, errbuf);
38
+                   } else {
39
                        if (regexec(&preg, str, 0, NULL, 0) == 0)
40
-                           success = true;
41
+                           success = !success;
42
                        regfree(&preg);
43
                    }
44
-               } else if (strncmp(str, value, len) == 0 &&
45
-                   strlen(str) == (size_t)len) {
46
-                   success = true;
47
+               } else if (strncmp(str, value+skip, len-skip) == 0 &&
48
+                   strlen(str) == (size_t)(len-skip)) {
49
+                   success = !success;
50
                }
51
            }
52
            if (success) {
53
@@ -634,6 +645,7 @@
54
                pw_log_debug("'%s' match '%s' < > '%.*s'", key, str, len, value);
55
            }
56
            else {
57
+               pw_log_debug("'%s' fail '%s' < > '%.*s'", key, str, len, value);
58
                fail++;
59
                break;
60
            }
61
@@ -1075,7 +1087,7 @@
62
  *             # any of the items in matches needs to match, if one does,
63
  *             # actions are emited.
64
  *             {
65
- *                 # all keys must match the value. ~ in value starts regex.
66
+ *                 # all keys must match the value. ! negates. ~ starts regex.
67
  *                 <key> = <value>
68
  *                 ...
69
  *             }
70
pipewire-0.3.77.tar.gz/src/pipewire/context.c -> pipewire-0.3.79.tar.gz/src/pipewire/context.c Changed
114
 
1
@@ -787,44 +787,46 @@
2
    return pw_impl_node_set_state(node, state);
3
 }
4
 
5
-/* From a node (that is runnable) follow all prepared links and groups to
6
- * active nodes up to the driver and make them recursively runnable as well.
7
- *
8
- * We stop at driver nodes so that other paths linked to the driver will stay
9
- * unrunnable when no other runnable path exists.
10
+/* From a node (that is runnable) follow all prepared links in the given direction
11
+ * and groups to active nodes and make them recursively runnable as well.
12
  */
13
-static inline int run_nodes(struct pw_context *context, struct pw_impl_node *node, struct spa_list *nodes)
14
+static inline int run_nodes(struct pw_context *context, struct pw_impl_node *node,
15
+       struct spa_list *nodes, enum pw_direction direction)
16
 {
17
    struct pw_impl_node *t;
18
    struct pw_impl_port *p;
19
    struct pw_impl_link *l;
20
 
21
-   pw_log_debug("node %p: '%s'", node, node->name);
22
+   pw_log_debug("node %p: '%s' direction:%s", node, node->name,
23
+           pw_direction_as_string(direction));
24
 
25
-   spa_list_for_each(p, &node->input_ports, link) {
26
-       spa_list_for_each(l, &p->links, input_link) {
27
-           t = l->output->node;
28
+   SPA_FLAG_SET(node->checked, 1u<<direction);
29
 
30
-           if (!t->active || !l->prepared || t->runnable)
31
-               continue;
32
+   if (direction == PW_DIRECTION_INPUT) {
33
+       spa_list_for_each(p, &node->input_ports, link) {
34
+           spa_list_for_each(l, &p->links, input_link) {
35
+               t = l->output->node;
36
 
37
-           pw_log_debug("  peer %p: '%s'", t, t->name);
38
-           t->runnable = true;
39
-           if (!t->driving)
40
-               run_nodes(context, t, nodes);
41
+               if (!t->active || !l->prepared || (!t->driving && t->runnable))
42
+                   continue;
43
+
44
+               pw_log_debug("  peer %p: '%s'", t, t->name);
45
+               t->runnable = true;
46
+               run_nodes(context, t, nodes, direction);
47
+           }
48
        }
49
-   }
50
-   spa_list_for_each(p, &node->output_ports, link) {
51
-       spa_list_for_each(l, &p->links, output_link) {
52
-           t = l->input->node;
53
+   } else {
54
+       spa_list_for_each(p, &node->output_ports, link) {
55
+           spa_list_for_each(l, &p->links, output_link) {
56
+               t = l->input->node;
57
 
58
-           if (!t->active || !l->prepared || t->runnable)
59
-               continue;
60
+               if (!t->active || !l->prepared || (!t->driving && t->runnable))
61
+                   continue;
62
 
63
-           pw_log_debug("  peer %p: '%s'", t, t->name);
64
-           t->runnable = true;
65
-           if (!t->driving)
66
-               run_nodes(context, t, nodes);
67
+               pw_log_debug("  peer %p: '%s'", t, t->name);
68
+               t->runnable = true;
69
+               run_nodes(context, t, nodes, direction);
70
+           }
71
        }
72
    }
73
    /* now go through all the nodes that have the same link group and
74
@@ -834,7 +836,8 @@
75
     * them. */
76
    if (node->link_group != NULL) {
77
        spa_list_for_each(t, nodes, sort_link) {
78
-           if (t->exported || !t->active || t->runnable)
79
+           if (t->exported || !t->active ||
80
+               SPA_FLAG_IS_SET(t->checked,  1u<<direction))
81
                continue;
82
            if (!spa_streq(t->link_group, node->link_group))
83
                continue;
84
@@ -842,7 +845,7 @@
85
            pw_log_debug("  group %p: '%s'", t, t->name);
86
            t->runnable = true;
87
            if (!t->driving)
88
-               run_nodes(context, t, nodes);
89
+               run_nodes(context, t, nodes, direction);
90
        }
91
    }
92
    return 0;
93
@@ -944,8 +947,10 @@
94
        pw_log_debug(" next node %p: '%s' runnable:%u", n, n->name, n->runnable);
95
    }
96
    spa_list_for_each(n, collect, sort_link)
97
-       if (!n->driving && n->runnable)
98
-           run_nodes(context, n, collect);
99
+       if (!n->driving && n->runnable) {
100
+           run_nodes(context, n, collect, PW_DIRECTION_OUTPUT);
101
+           run_nodes(context, n, collect, PW_DIRECTION_INPUT);
102
+       }
103
 
104
    return 0;
105
 }
106
@@ -1199,6 +1204,7 @@
107
    /* clean up the flags first */
108
    spa_list_for_each(n, &context->node_list, link) {
109
        n->visited = false;
110
+       n->checked = 0;
111
        n->runnable = n->always_process && n->active;
112
    }
113
 
114
pipewire-0.3.77.tar.gz/src/pipewire/impl-node.c -> pipewire-0.3.79.tar.gz/src/pipewire/impl-node.c Changed
51
 
1
@@ -445,6 +445,17 @@
2
 
3
    node_deactivate(this);
4
 
5
+   pw_log_debug("%p: suspend node driving:%d driver:%d added:%d", this,
6
+           this->driving, this->driver, this->added);
7
+
8
+   res = spa_node_send_command(this->node,
9
+                   &SPA_NODE_COMMAND_INIT(SPA_NODE_COMMAND_Suspend));
10
+   if (res == -ENOTSUP)
11
+       res = spa_node_send_command(this->node,
12
+                   &SPA_NODE_COMMAND_INIT(SPA_NODE_COMMAND_Pause));
13
+   if (res < 0 && res != -EIO)
14
+       pw_log_warn("%p: suspend node error %s", this, spa_strerror(res));
15
+
16
    spa_list_for_each(p, &this->input_ports, link) {
17
        if ((res = pw_impl_port_set_param(p, SPA_PARAM_Format, 0, NULL)) < 0)
18
            pw_log_warn("%p: error unset format input: %s",
19
@@ -461,17 +472,6 @@
20
        p->state = PW_IMPL_PORT_STATE_CONFIGURE;
21
    }
22
 
23
-   pw_log_debug("%p: suspend node driving:%d driver:%d added:%d", this,
24
-           this->driving, this->driver, this->added);
25
-
26
-   res = spa_node_send_command(this->node,
27
-                   &SPA_NODE_COMMAND_INIT(SPA_NODE_COMMAND_Suspend));
28
-   if (res == -ENOTSUP)
29
-       res = spa_node_send_command(this->node,
30
-                   &SPA_NODE_COMMAND_INIT(SPA_NODE_COMMAND_Pause));
31
-   if (res < 0 && res != -EIO)
32
-       pw_log_warn("%p: suspend node error %s", this, spa_strerror(res));
33
-
34
    node_update_state(this, PW_NODE_STATE_SUSPENDED, 0, NULL);
35
 
36
    return res;
37
@@ -1796,7 +1796,12 @@
38
         * help drivers that don't support this yet */
39
        if (SPA_UNLIKELY(node->rt.position->clock.duration != node->rt.position->clock.target_duration ||
40
            node->rt.position->clock.rate.denom != node->rt.position->clock.target_rate.denom)) {
41
-           pw_log_warn("driver %s did not update duration/rate", node->name);
42
+           pw_log_warn("driver %s did not update duration/rate (%"PRIu64"/%"PRIu64" %u/%u)",
43
+                   node->name,
44
+                   node->rt.position->clock.duration,
45
+                   node->rt.position->clock.target_duration,
46
+                   node->rt.position->clock.rate.denom,
47
+                   node->rt.position->clock.target_rate.denom);
48
            node->rt.position->clock.duration = node->rt.position->clock.target_duration;
49
            node->rt.position->clock.rate = node->rt.position->clock.target_rate;
50
        }
51
pipewire-0.3.77.tar.gz/src/pipewire/pipewire.c -> pipewire-0.3.79.tar.gz/src/pipewire/pipewire.c Changed
15
 
1
@@ -598,8 +598,11 @@
2
        char *patterns = NULL;
3
 
4
        n_items = 0;
5
-       if (!support->no_color)
6
-           itemsn_items++ = SPA_DICT_ITEM_INIT(SPA_KEY_LOG_COLORS, "true");
7
+       if (!support->no_color) {
8
+           if ((str = getenv("PIPEWIRE_LOG_COLOR")) == NULL)
9
+               str = "true";
10
+           itemsn_items++ = SPA_DICT_ITEM_INIT(SPA_KEY_LOG_COLORS, str);
11
+       }
12
        itemsn_items++ = SPA_DICT_ITEM_INIT(SPA_KEY_LOG_TIMESTAMP, "true");
13
        if ((str = getenv("PIPEWIRE_LOG_LINE")) == NULL || spa_atob(str))
14
            itemsn_items++ = SPA_DICT_ITEM_INIT(SPA_KEY_LOG_LINE, "true");
15
pipewire-0.3.77.tar.gz/src/pipewire/private.h -> pipewire-0.3.79.tar.gz/src/pipewire/private.h Changed
9
 
1
@@ -676,6 +676,7 @@
2
    unsigned int trigger:1;     /**< has the TRIGGER property and needs an extra
3
                      *  trigger to start processing. */
4
    unsigned int can_suspend:1;
5
+   unsigned int checked;       /**< for sorting */
6
 
7
    uint32_t port_user_data_size;   /**< extra size for port user data */
8
 
9
pipewire-0.3.77.tar.gz/src/pipewire/stream.h -> pipewire-0.3.79.tar.gz/src/pipewire/stream.h Changed
44
 
1
@@ -226,10 +226,12 @@
2
  * value, and pw_time.ticks, were captured at pw_time.now and can be extrapolated
3
  * to the current time like this:
4
  *
5
+ *\code{.c}
6
  *    struct timespec ts;
7
  *    clock_gettime(CLOCK_MONOTONIC, &ts);
8
  *    int64_t diff = SPA_TIMESPEC_TO_NSEC(&ts) - pw_time.now;
9
  *    int64_t elapsed = (pw_time.rate.denom * diff) / (pw_time.rate.num * SPA_NSEC_PER_SEC);
10
+ *\endcode
11
  *
12
  * pw_time.delay contains the total delay that a signal will travel through the
13
  * graph. This includes the delay caused by filters in the graph as well as delays
14
@@ -255,15 +257,21 @@
15
  * in milliseconds for the first sample in the newly queued buffer to be played
16
  * by the hardware can be calculated as:
17
  *
18
+ *\code{.unparsed}
19
  *  (pw_time.buffered * 1000 / stream.samplerate) +
20
  *    (pw_time.queued * 1000 / app.rate) +
21
  *     ((pw_time.delay - elapsed) * 1000 * pw_time.rate.num / pw_time.rate.denom)
22
+ *\endcode
23
  *
24
  * The current extrapolated time (in ms) in the source or sink can be calculated as:
25
  *
26
+ *\code{.unparsed}
27
  *  (pw_time.ticks + elapsed) * 1000 * pw_time.rate.num / pw_time.rate.denom
28
+ *\endcode
29
  *
30
+ * Below is an overview of the different timing values:
31
  *
32
+ *\code{.unparsed}
33
  *           stream time domain           graph time domain
34
  *         /-----------------------\/-----------------------------\
35
  *
36
@@ -275,6 +283,7 @@
37
  *                                    latency             latency
38
  *         \--------/\-------------/\-----------------------------/
39
  *           queued      buffered            delay
40
+ *\endcode
41
  */
42
 struct pw_time {
43
    int64_t now;            /**< the monotonic time in nanoseconds. This is the time
44
pipewire-0.3.77.tar.gz/src/tools/pw-mon.c -> pipewire-0.3.79.tar.gz/src/tools/pw-mon.c Changed
10
 
1
@@ -757,7 +757,7 @@
2
 
3
    setlinebuf(stdout);
4
 
5
-   if (isatty(STDERR_FILENO) && getenv("NO_COLOR") == NULL)
6
+   if (isatty(STDOUT_FILENO) && getenv("NO_COLOR") == NULL)
7
        colors = true;
8
 
9
    while ((c = getopt_long(argc, argv, "hVr:NC", long_options, NULL)) != -1) {
10
pipewire-0.3.77.tar.gz/src/tools/pw-top.c -> pipewire-0.3.79.tar.gz/src/tools/pw-top.c Changed
315
 
1
@@ -82,6 +82,9 @@
2
    unsigned pending_refresh:1;
3
 
4
    WINDOW *win;
5
+
6
+   unsigned int batch_mode:1;
7
+   int iterations;
8
 };
9
 
10
 struct point {
11
@@ -89,6 +92,22 @@
12
    struct driver info;
13
 };
14
 
15
+static SPA_PRINTF_FUNC(4, 5) void print_mode_dependent(struct data *d, int y, int x, const char *fmt, ...)
16
+{
17
+   va_list argp;
18
+   if (!d->batch_mode)
19
+       mvwprintw(d->win, y, x, "%s", "");
20
+
21
+   va_start(argp, fmt);
22
+   if (d->batch_mode) {
23
+       vprintf(fmt, argp);
24
+       printf("\n");
25
+   } else
26
+       vw_printw(d->win, fmt, argp);
27
+   va_end(argp);
28
+}
29
+
30
+
31
 static int process_info(struct data *d, const struct spa_pod *pod, struct driver *info)
32
 {
33
    return spa_pod_parse_struct(pod,
34
@@ -144,7 +163,7 @@
35
    .destroy = on_node_destroy,
36
 };
37
 
38
-static void do_refresh(struct data *d);
39
+static void do_refresh(struct data *d, bool force_refresh);
40
 
41
 static void node_info(void *data, const struct pw_node_info *info)
42
 {
43
@@ -152,7 +171,7 @@
44
 
45
    if (n->state != info->state) {
46
        n->state = info->state;
47
-       do_refresh(n->data);
48
+       do_refresh(n->data, !n->data->batch_mode);
49
    }
50
 }
51
 
52
@@ -259,7 +278,7 @@
53
        break;
54
    }
55
 done:
56
-   do_refresh(n->data);
57
+   do_refresh(n->data, !n->data->batch_mode);
58
 }
59
 
60
 static const struct pw_node_events node_events = {
61
@@ -296,7 +315,8 @@
62
    }
63
    spa_list_append(&d->node_list, &n->link);
64
    d->n_nodes++;
65
-   d->pending_refresh = true;
66
+   if (!d->batch_mode)
67
+       d->pending_refresh = true;
68
 
69
    return n;
70
 }
71
@@ -307,7 +327,8 @@
72
        pw_proxy_destroy(n->proxy);
73
    spa_list_remove(&n->link);
74
    d->n_nodes--;
75
-   d->pending_refresh = true;
76
+   if (!d->batch_mode)
77
+       d->pending_refresh = true;
78
    free(n);
79
 }
80
 
81
@@ -462,7 +483,7 @@
82
    else
83
        busy = -1;
84
 
85
-   mvwprintw(d->win, y, 0, "%s %4.1u %6.1u %6.1u %s %s %s %s  %3.1u %16.16s %s%s",
86
+   print_mode_dependent(d, y, 0, "%s %4.1u %6.1u %6.1u %s %s %s %s  %3.1u %16.16s %s%s",
87
            state_as_string(n->state),
88
            n->id,
89
            frac.num, frac.denom,
90
@@ -484,23 +505,31 @@
91
    spa_zero(n->info);
92
 }
93
 
94
-static void do_refresh(struct data *d)
95
+#define HEADER "S   ID  QUANT   RATE    WAIT    BUSY   W/Q   B/Q  ERR FORMAT           NAME "
96
+
97
+static void do_refresh(struct data *d, bool force_refresh)
98
 {
99
    struct node *n, *t, *f;
100
    int y = 1;
101
 
102
-   wclear(d->win);
103
-   wattron(d->win, A_REVERSE);
104
-   wprintw(d->win, "%-*.*s", COLS, COLS, "S   ID  QUANT   RATE    WAIT    BUSY   W/Q   B/Q  ERR FORMAT           NAME ");
105
-   wattroff(d->win, A_REVERSE);
106
-   wprintw(d->win, "\n");
107
+   if (!d->pending_refresh && !force_refresh)
108
+       return;
109
+
110
+   if (!d->batch_mode) {
111
+       wclear(d->win);
112
+       wattron(d->win, A_REVERSE);
113
+       wprintw(d->win, "%-*.*s", COLS, COLS, HEADER);
114
+       wattroff(d->win, A_REVERSE);
115
+       wprintw(d->win, "\n");
116
+   } else
117
+       printf(HEADER "\n");
118
 
119
    spa_list_for_each_safe(n, t, &d->node_list, link) {
120
        if (n->driver != n)
121
            continue;
122
 
123
        print_node(d, &n->info, n, y++);
124
-       if(y > LINES)
125
+       if(!d->batch_mode && y > LINES)
126
            break;
127
 
128
        spa_list_for_each(f, &d->node_list, link) {
129
@@ -517,19 +546,28 @@
130
        }
131
    }
132
 
133
-   // Clear from last line to the end of the window to hide text wrapping from the last node
134
-   wmove(d->win, y, 0);
135
-   wclrtobot(d->win);
136
+   if (!d->batch_mode) {
137
+       // Clear from last line to the end of the window to hide text wrapping from the last node
138
+       wmove(d->win, y, 0);
139
+       wclrtobot(d->win);
140
+
141
+       wrefresh(d->win);
142
+   }
143
 
144
-   wrefresh(d->win);
145
    d->pending_refresh = false;
146
+
147
+   if (d->iterations > 0)
148
+       d->iterations--;
149
+
150
+   if (d->iterations == 0)
151
+       pw_main_loop_quit(d->loop);
152
 }
153
 
154
 static void do_timeout(void *data, uint64_t expirations)
155
 {
156
    struct data *d = data;
157
    d->generation++;
158
-   do_refresh(d);
159
+   do_refresh(d, true);
160
 }
161
 
162
 static void profiler_profile(void *data, const struct spa_pod *pod)
163
@@ -568,8 +606,8 @@
164
        if (res < 0)
165
            continue;
166
    }
167
-   if (d->pending_refresh)
168
-       do_refresh(d);
169
+
170
+   do_refresh(d, false);
171
 }
172
 
173
 static const struct pw_profiler_events profiler_events = {
174
@@ -608,8 +646,8 @@
175
        d->profiler = proxy;
176
        pw_proxy_add_object_listener(proxy, &d->profiler_listener, &profiler_events, d);
177
    }
178
-   if (d->pending_refresh)
179
-       do_refresh(d);
180
+
181
+   do_refresh(d, false);
182
    return;
183
 
184
 error_proxy:
185
@@ -623,8 +661,8 @@
186
    struct node *n;
187
    if ((n = find_node(d, id)) != NULL)
188
        remove_node(d, n);
189
-   if (d->pending_refresh)
190
-       do_refresh(d);
191
+
192
+   do_refresh(d, false);
193
 }
194
 
195
 static const struct pw_registry_events registry_events = {
196
@@ -662,7 +700,7 @@
197
            pw_log_error("no Profiler Interface found, please load one in the server");
198
            pw_main_loop_quit(d->loop);
199
        } else {
200
-           do_refresh(d);
201
+           do_refresh(d, true);
202
        }
203
    }
204
 }
205
@@ -681,10 +719,14 @@
206
 
207
 static void show_help(const char *name, bool error)
208
 {
209
-        fprintf(error ? stderr : stdout, "%s options\n"
210
+        fprintf(error ? stderr : stdout, "Usage:\n%s options\n\n"
211
+       "Options:\n"
212
+       "  -b, --batch-mode              run in non-interactive batch_mode mode\n"
213
+       "  -n, --iterations = NUMBER             exit on maximum iterations NUMBER\n"
214
+       "  -r, --remote                          Remote daemon name\n"
215
+       "\n"
216
        "  -h, --help                            Show this help\n"
217
-       "      --version                         Show version\n"
218
-       "  -r, --remote                          Remote daemon name\n",
219
+       "  -V  --version                         Show version\n",
220
        name);
221
 }
222
 
223
@@ -713,7 +755,7 @@
224
            pw_main_loop_quit(d->loop);
225
            break;
226
        default:
227
-           do_refresh(d);
228
+           do_refresh(d, !d->batch_mode);
229
            break;
230
        }
231
    }
232
@@ -725,9 +767,11 @@
233
    struct pw_loop *l;
234
    const char *opt_remote = NULL;
235
    static const struct option long_options = {
236
+       { "batch-mode", no_argument,        NULL, 'b' },
237
+       { "iterations", required_argument,  NULL, 'n' },
238
+       { "remote", required_argument,  NULL, 'r' },
239
        { "help",   no_argument,        NULL, 'h' },
240
        { "version",    no_argument,        NULL, 'V' },
241
-       { "remote", required_argument,  NULL, 'r' },
242
        { NULL, 0, NULL, 0}
243
    };
244
    int c;
245
@@ -737,9 +781,11 @@
246
    setlocale(LC_ALL, "");
247
    pw_init(&argc, &argv);
248
 
249
+   data.iterations = -1;
250
+
251
    spa_list_init(&data.node_list);
252
 
253
-   while ((c = getopt_long(argc, argv, "hVr:o:", long_options, NULL)) != -1) {
254
+   while ((c = getopt_long(argc, argv, "hVr:o:bn:", long_options, NULL)) != -1) {
255
        switch (c) {
256
        case 'h':
257
            show_help(argv0, false);
258
@@ -755,6 +801,12 @@
259
        case 'r':
260
            opt_remote = optarg;
261
            break;
262
+       case 'b':
263
+           data.batch_mode = 1;
264
+           break;
265
+       case 'n':
266
+           spa_atoi32(optarg, &data.iterations, 10);
267
+           break;
268
        default:
269
            show_help(argv0, true);
270
            return -1;
271
@@ -767,6 +819,9 @@
272
        return -1;
273
    }
274
 
275
+   if (!data.batch_mode)
276
+       data.iterations = -1;
277
+
278
    l = pw_main_loop_get_loop(data.loop);
279
    pw_loop_add_signal(l, SIGINT, do_quit, &data);
280
    pw_loop_add_signal(l, SIGTERM, do_quit, &data);
281
@@ -800,9 +855,10 @@
282
 
283
    data.check_profiler = pw_core_sync(data.core, 0, 0);
284
 
285
-   terminal_start();
286
-
287
-   data.win = newwin(LINES, COLS, 0, 0);
288
+   if (!data.batch_mode) {
289
+       terminal_start();
290
+       data.win = newwin(LINES, COLS, 0, 0);
291
+   }
292
 
293
    data.timer = pw_loop_add_timer(l, do_timeout, &data);
294
    value.tv_sec = 1;
295
@@ -811,15 +867,16 @@
296
    interval.tv_nsec = 0;
297
    pw_loop_update_timer(l, data.timer, &value, &interval, false);
298
 
299
-   pw_loop_add_io(l, fileno(stdin), SPA_IO_IN, false, do_handle_io, &data);
300
+   if (!data.batch_mode)
301
+       pw_loop_add_io(l, fileno(stdin), SPA_IO_IN, false, do_handle_io, &data);
302
 
303
    pw_main_loop_run(data.loop);
304
 
305
-   terminal_stop();
306
+   if (!data.batch_mode)
307
+       terminal_stop();
308
 
309
    spa_list_consume(n, &data.node_list, link)
310
        remove_node(&data, n);
311
-
312
    if (data.profiler) {
313
        spa_hook_remove(&data.profiler_listener);
314
        pw_proxy_destroy((struct pw_proxy*)data.profiler);
315
Refresh

No build results available

Refresh

No rpmlint results available

Request History
Bjørn Lie's avatar

zaitor created request over 1 year ago

New upstream rel, sync with Tw


Bjørn Lie's avatar

zaitor accepted request over 1 year ago

Xin