Changes of Revision 17

pipewire-aptx.changes Changed
x
 
1
@@ -1,4 +1,9 @@
2
 -------------------------------------------------------------------
3
+Mon Nov 21 11:36:55 UTC 2022 - Bjørn Lie <zaitor@opensuse.org>
4
+
5
+- Update to version 0.3.60
6
+
7
+-------------------------------------------------------------------
8
 Sat Oct 15 16:39:17 UTC 2022 - Bjørn Lie <zaitor@opensuse.org>
9
 
10
 - Update to version 0.3.59
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.59
6
+Version:        0.3.60
7
 Release:        0
8
 Summary:        PipeWire Bluetooth aptX codec plugin
9
 License:        MIT
10
pipewire-0.3.59.tar.gz/.gitlab-ci.yml -> pipewire-0.3.60.tar.gz/.gitlab-ci.yml Changed
156
 
1
@@ -25,7 +25,7 @@
2
 .fedora:
3
   variables:
4
     # Update this tag when you want to trigger a rebuild
5
-    FDO_DISTRIBUTION_TAG: '2022-03-05.0'
6
+    FDO_DISTRIBUTION_TAG: '2022-11-07.0'
7
     FDO_DISTRIBUTION_VERSION: '35'
8
     FDO_DISTRIBUTION_PACKAGES: >-
9
       alsa-lib-devel
10
@@ -52,6 +52,7 @@
11
       libv4l-devel
12
       libva-devel
13
       libX11-devel
14
+      ModemManager-devel
15
       openssl-devel
16
       pulseaudio-libs-devel
17
       python3-docutils
18
@@ -68,6 +69,7 @@
19
       python3-pip
20
       pulseaudio-utils
21
       openal-soft
22
+      readline-devel
23
     FDO_DISTRIBUTION_EXEC: >-
24
       pip3 install meson
25
 
26
@@ -105,7 +107,7 @@
27
 .alpine:
28
   variables:
29
     # Update this tag when you want to trigger a rebuild
30
-    FDO_DISTRIBUTION_TAG: '2022-01-28.2'
31
+    FDO_DISTRIBUTION_TAG: '2022-09-07.0'
32
     FDO_DISTRIBUTION_VERSION: '3.15'
33
     FDO_DISTRIBUTION_PACKAGES: >-
34
       alsa-lib-dev
35
@@ -128,6 +130,7 @@
36
       libusb-dev
37
       libx11-dev
38
       meson
39
+      modemmanager-dev
40
       ncurses-dev
41
       pulseaudio-dev
42
       readline-dev
43
@@ -176,7 +179,6 @@
44
     - ninja $NINJA_ARGS -C "$BUILD_DIR"
45
     - ninja $NINJA_ARGS -C "$BUILD_DIR" test
46
     - ninja $NINJA_ARGS -C "$BUILD_DIR" install
47
-    - ./check_missing_headers.sh
48
   artifacts:
49
     name: pipewire-$CI_COMMIT_SHA
50
     when: always
51
@@ -223,6 +225,8 @@
52
     - .fdo.distribution-image@ubuntu
53
     - .build
54
   stage: build
55
+  variables:
56
+    MESON_OPTIONS: "-Dsession-managers="
57
 
58
 .build_on_fedora:
59
   extends:
60
@@ -248,6 +252,7 @@
61
         -Dvulkan=enabled
62
         -Dsdl2=enabled
63
         -Dsndfile=enabled
64
+        -Dsession-managers=
65
   artifacts:
66
     name: pipewire-$CI_COMMIT_SHA
67
     when: always
68
@@ -262,6 +267,8 @@
69
     - .fdo.distribution-image@alpine
70
     - .build
71
   stage: build
72
+  variables:
73
+    MESON_OPTIONS: "-Dsession-managers="
74
 
75
 # build with all auto() options enabled
76
 build_all:
77
@@ -270,7 +277,14 @@
78
   variables:
79
     # Fedora doesn't have libfreeaptx, lc3plus, lc3, or roc
80
     # libcamera has no stable API, so let's not chase that target
81
-    MESON_OPTIONS: "-Dauto_features=enabled -Dbluez5-codec-aptx=disabled -Dbluez5-codec-lc3plus=disabled -Dbluez5-codec-lc3=disabled -Droc=disabled -Dlibcamera=disabled"
82
+    MESON_OPTIONS: >-
83
+        -Dauto_features=enabled
84
+        -Dbluez5-codec-aptx=disabled
85
+        -Dbluez5-codec-lc3plus=disabled
86
+        -Dbluez5-codec-lc3=disabled
87
+        -Droc=disabled
88
+        -Dlibcamera=disabled
89
+        -Dsession-managers=
90
   parallel:
91
     matrix:
92
       - CC: gcc, clang
93
@@ -280,7 +294,7 @@
94
   extends:
95
     - .build_on_fedora
96
   variables:
97
-    MESON_OPTIONS: ""
98
+    MESON_OPTIONS: "-Dsession-managers="
99
   parallel:
100
     matrix:
101
       - CC: gcc, clang
102
@@ -296,7 +310,7 @@
103
         MESON_OPTION_VALUE: enabled, disabled
104
   script:
105
     - echo "Building with -D$MESON_OPTION=$MESON_OPTION_VALUE"
106
-    - meson "$BUILD_DIR" . --prefix="$PREFIX" "-D$MESON_OPTION=$MESON_OPTION_VALUE"
107
+    - meson "$BUILD_DIR" . --prefix="$PREFIX" "-D$MESON_OPTION=$MESON_OPTION_VALUE" -Dsession-managers=
108
     - ninja $NINJA_ARGS -C "$BUILD_DIR"
109
     - ninja $NINJA_ARGS -C "$BUILD_DIR" test
110
 
111
@@ -307,7 +321,7 @@
112
   extends:
113
     - .build_on_fedora
114
   variables:
115
-    MESON_OPTIONS: "-Dtest=enabled -Dbuildtype=release -Db_ndebug=true"
116
+    MESON_OPTIONS: "-Dtest=enabled -Dbuildtype=release -Db_ndebug=true -Dsession-managers="
117
   parallel:
118
     matrix:
119
       - CC: gcc, clang
120
@@ -363,6 +377,8 @@
121
     - echo "Building with meson options $MESON_OPTIONS"
122
     - meson "$BUILD_DIR" . --prefix="$PREFIX" $MESON_OPTIONS
123
     - meson test -C "$BUILD_DIR" --setup=valgrind
124
+  variables:
125
+    MESON_OPTIONS: "-Dsession-managers="
126
 
127
 build_with_coverity:
128
   extends:
129
@@ -383,6 +399,7 @@
130
         -Dvulkan=enabled
131
         -Dsdl2=enabled
132
         -Dsndfile=enabled
133
+        -Dsession-managers=
134
     - cov-configure --config coverity_conf.xml
135
         --comptype gcc --compiler cc --template
136
         --xml-option=append_arg@C:--ppp_translator
137
@@ -432,6 +449,18 @@
138
           git grep -q -e "\\\subpage $page" || (echo "\\page $page is missing \\subpage entry in doc/pipewire-modules.dox" && false)
139
       done
140
 
141
+check_missing_headers:
142
+  extends:
143
+    - .fedora
144
+    - .not_coverity
145
+    - .fdo.distribution-image@fedora
146
+  stage: analysis
147
+  dependencies:
148
+    - build_on_fedora
149
+  script:
150
+    - export PREFIX=`find -name prefix-*`
151
+    - ./.gitlab/ci/check_missing_headers.sh
152
+
153
 pages:
154
   extends:
155
     - .not_coverity
156
pipewire-0.3.60.tar.gz/.gitlab/ci Added
2
 
1
+(directory)
2
pipewire-0.3.60.tar.gz/.gitlab/ci/check_missing_headers.sh Changed
2
 
1
(renamed from check_missing_headers.sh)
2
pipewire-0.3.59.tar.gz/NEWS -> pipewire-0.3.60.tar.gz/NEWS Changed
163
 
1
@@ -1,3 +1,151 @@
2
+# PipeWire 0.3.60 (2022-11-10)
3
+
4
+This is a bugfix release that is API and ABI compatible with previous
5
+0.3.x releases.
6
+
7
+## Highlights
8
+  - The filter-chain now handles errors better and has fixes for many
9
+    crasher bugs.
10
+  - A new RTP module was added with a sender and receiver. It uses SAP
11
+    to announce and consume RTP streams and is compatible with the
12
+    PulseAudio RTP modules.
13
+  - Many small bluetooth improvements and fixes.
14
+  - The alsa plugin will now only start playback when there is data. This
15
+    results in better sync and lower latency between capture and playback.
16
+  - The v4l2 and libcamera plugins have seen a lot of improvements. They
17
+    support control properties now. Also pw-v4l2 has seen many improvements
18
+    and mostly passes the v4l2-compliance test now.
19
+  - Many more bugfixes and improvements.
20
+
21
+
22
+## PipeWire
23
+  - Code cleanups, compiler warning fixes.
24
+  - Add some extra checks to avoid scheduling an inactive node.
25
+  - Rework the sequence of events to start and stop nodes.
26
+  - Improve param enumeration.
27
+  - An option was added to give priority to the Buffer params of the
28
+    consumer. This makes it possible to use the default values of the
29
+    consumer (instead of the producer) when capturing from a source.
30
+  - The graph rate selection was improved to pick a rate closest to the
31
+    requested one (instead of picking the default).
32
+
33
+## Modules
34
+  - Fix some crashes in filter-chain. (#2737)
35
+  - X11 Bell module will now be loaded by default when available.
36
+  - A new RTP module was added with a sender and receiver. It uses SAP
37
+    to announce and consume RTP streams and is compatible with the
38
+    PulseAudio RTP modules.
39
+  - Improve RAOP compatibility.
40
+  - The echo-cancel module now uses the resampler prefill option to align
41
+    input and output samples without buffering. Better latency control
42
+    when starting and stopping has been implemented.
43
+  - The pulse tunnel will now write aligned samples to pulseaudio even
44
+    when the ringbuffer wraps around. This fixes playback issues with
45
+    multichannel sinks.
46
+  - Add a delay option to module-loopback using a ringbuffer.
47
+  - Implement echo-cancel params.
48
+  - The filter-chain module has better error reporting.
49
+  - The LADSPA search path was extended with some more common paths.
50
+  - The echo-canceler input can now also be a monitor of a sink. This
51
+    improves compatibility with some proton games that expect a real
52
+    sink instead of a virtual one.
53
+
54
+## Tools
55
+  - Better error reporting in pw-link.
56
+  - pw-top now also shows IEC958 passthrough formats and JPEG/H264 video
57
+    formats.
58
+  - pw-top refreshes the screen faster.
59
+  - pw-top now prints the state of the node and shows less info for
60
+    inactive nodes.
61
+  - pw-dump now uses the new seq field in the spa_param_info to discard
62
+    old param updates and avoid duplicate params in the output.
63
+
64
+## Bluetooth
65
+  - Add ModemManager support in the native backend.
66
+  - Clean up GetManagedObjects handling.
67
+  - Handle QoS from the endpoints in the codec.
68
+  - Increase the socket buffer to have more control over the rate and QoS.
69
+  - Simplify the packet flushing code.
70
+  - Stop processing nodes before destroying them.
71
+  - Fix timers when a source switches drivers.
72
+  - Codecs can now share endpoints. This reduces the amount of endpoints and
73
+    avoids problems with devices that can't handle a large amount of
74
+    codec endpoints.
75
+  - Report batery status to UPower for HFP AG.
76
+  - Fix bitpool increase.
77
+
78
+## SPA
79
+  - The audioresampler now avoids clicks and pops between activating and
80
+    deactivating the adaptive resampler when used by the stream API.
81
+  - Use default locale to parse float parameters.
82
+  - The upmix functions now have SSE optimizations.
83
+  - Avoid recalculating the complete channelmix setup when only the
84
+    volume changes.
85
+  - The alsa plugin will now only start playback when there is data. This
86
+    results in better sync and lower latency between capture and playback.
87
+  - The ALSA MIDI sequencer will now pull data from the graph even when it
88
+    did not output anything. Fixes some graph stalls with the sequencer in
89
+    some cases. (#2775)
90
+  - v4l2 and libcamera sources now recycle buffers when nothing is consuming
91
+    them. This avoids stalling the graph.
92
+  - libcamera now suggests a more appropriate frame size than the smallest
93
+    poster frame.
94
+  - Improve state changes in audioconvert. (#2764)
95
+  - A new seq field was added to spa_param_info to keep track of pending
96
+    param updates.
97
+  - Support speaker output only on RealTek ALC4080. (#2744)
98
+  - The v4l2 source now supports setting controls.
99
+  - The libcamera plugin now supports enumerating and setting controls.
100
+  - A new unit test for 6.1 channel mapping was added. (#2809) More debug
101
+    info was added to audioconvert for the channel matrix.
102
+  - Audioconvert will now also upmix a rear-center channel when needed.
103
+
104
+## pulse-server
105
+  - Add support for the RTP send and recv modules with the new native
106
+    RTP module.
107
+  - Add option to set latency for pulse-tunnel streams and
108
+    module-zeroconf-discover.
109
+  - The socket will now be given the same permissions as what pulseaudio
110
+    did (0777).
111
+  - Implement module-loopback latency_msec correctly with the new delay
112
+    parameter.
113
+  - sysfs.path is now filled with the same data as pulseaudio.
114
+  - The manager now uses the new seq field in the spa_param_info.
115
+  - Fix a bug where in some cases the read pointer would get out of sync
116
+    and cause too large requests. (#2799)
117
+
118
+## ALSA
119
+  - The alsa plugin now reuses the stream in prepare which results in
120
+    better performance.
121
+  - Some deadlocks have been fixed in the ALSA plugin.
122
+  - The ALSA plugin reports more accurate timing information in some cases.
123
+
124
+## V4l2
125
+  - The v4l2 compatibility layer has received a lot of updates.
126
+  - Improved node names and format enumeration.
127
+  - Support for multiple /dev/videoX devices, each mapped to a unique
128
+    PipeWire node.
129
+  - Passes the v4l2-compliance test now with both the v4l2 and libcamera
130
+    backend in PipeWire.
131
+  - Improved mmap support for inline buffer memory. This makes it possible to
132
+    consume PipeWire streams.
133
+  - Negotiation works more reliably now.
134
+
135
+## JACK
136
+  - Implement jack_acquire_real_time_scheduling() and
137
+    jack_drop_real_time_scheduling() by keeping the thread utils in a global
138
+    state.
139
+  - Fix jack_client_thread_id() to return NULL when the client is not active,
140
+    just like jack1 and jack2.
141
+  - An option was added to let the jack_set_buffer_size() function update the
142
+    global metadata. A quirk was added so that jack_bufsize uses this new feature
143
+    to make the buffer size settings persistent and global, just like jack.
144
+  - jack_port_register() and jack_port_unregister() can be called on an
145
+    active client so make this thread safe. (#2652)
146
+
147
+
148
+Older versions:
149
+
150
 # PipeWire 0.3.59 (2022-09-30)
151
 
152
 This is a bugfix release that is API and ABI compatible with previous
153
@@ -72,9 +220,6 @@
154
   - PIPEWIRE_ALSA can now be used as an environment variable to restrict the
155
     plugin formats and buffer size.
156
 
157
-Older versions:
158
-
159
-
160
 # PipeWire 0.3.58 (2022-09-15)
161
 
162
 This is a bugfix release that is API and ABI compatible with previous
163
pipewire-0.3.59.tar.gz/doc/pipewire-modules.dox -> pipewire-0.3.60.tar.gz/doc/pipewire-modules.dox Changed
10
 
1
@@ -73,6 +73,8 @@
2
 - \subpage page_module_raop_discover
3
 - \subpage page_module_roc_sink
4
 - \subpage page_module_roc_source
5
+- \subpage page_module_rtp_sink
6
+- \subpage page_module_rtp_source
7
 - \subpage page_module_rt
8
 - \subpage page_module_session_manager
9
 - \subpage page_module_x11_bell
10
pipewire-0.3.59.tar.gz/man/pw-top.1.rst.in -> pipewire-0.3.60.tar.gz/man/pw-top.1.rst.in Changed
31
 
1
@@ -27,13 +27,15 @@
2
 The columns presented are as follows:
3
 
4
 S
5
-  Measurement status.
6
-  ! representing inactive - no connections
7
-
8
-  Blank representing active
9
+  Node status.
10
+    E = ERROR
11
+    C = CREATING
12
+    S = SUSPENDED
13
+    I = IDLE
14
+    R = RUNNING
15
 
16
 ID
17
-  The ID of the pipewire node/device, as found in *pw-dump*
18
+  The ID of the pipewire node/device, as found in *pw-dump* and *pw-cli*
19
 
20
 QUANT
21
   The current quantum (for drivers) and the suggested quantum for follower
22
@@ -135,6 +137,8 @@
23
 
24
   For raw audio formats, the layout is <sampleformat> <channels> <samplerate>.
25
 
26
+  For IEC958 passthrough audio formats, the layout is IEC958 <codec> <samplerate>.
27
+
28
   For DSD formats, the layout is <dsd-rate> <channels>.
29
 
30
   For Video formats, the layout is <pixelformat> <width>x<height>.
31
pipewire-0.3.59.tar.gz/meson.build -> pipewire-0.3.60.tar.gz/meson.build Changed
38
 
1
@@ -1,5 +1,5 @@
2
 project('pipewire', 'c' ,
3
-  version : '0.3.59',
4
+  version : '0.3.60',
5
   license :  'MIT', 'LGPL-2.1-or-later', 'GPL-2.0-only' ,
6
   meson_version : '>= 0.59.0',
7
   default_options :  'warning_level=3',
8
@@ -67,6 +67,7 @@
9
 
10
 common_flags = 
11
   '-fvisibility=hidden',
12
+  '-fno-strict-aliasing',
13
   '-Werror=suggest-attribute=format',
14
   '-Wsign-compare',
15
   '-Wpointer-arith',
16
@@ -97,7 +98,7 @@
17
 
18
 if have_cpp
19
   cxx = meson.get_compiler('cpp')
20
-  cxx_flags = common_flags
21
+  cxx_flags = common_flags +  '-Wno-c99-designator' 
22
   add_project_arguments(cxx.get_supported_arguments(cxx_flags), language: 'cpp')
23
 endif
24
 
25
@@ -259,10 +260,10 @@
26
 sdl_dep = dependency('sdl2', required : get_option('sdl2'))
27
 summary({'SDL2 (video examples)': sdl_dep.found()}, bool_yn: true, section: 'Misc dependencies')
28
 drm_dep = dependency('libdrm', required : false)
29
-readline_dep = dependency('readline', required : false)
30
+readline_dep = dependency('readline', required : get_option('readline'))
31
 
32
 if not readline_dep.found()
33
-  readline_dep = cc.find_library('readline', required: false)
34
+  readline_dep = cc.find_library('readline', required : get_option('readline'))
35
 endif
36
 
37
 summary({'readline (for pw-cli)': readline_dep.found()}, bool_yn: true, section: 'Misc dependencies')
38
pipewire-0.3.59.tar.gz/meson_options.txt -> pipewire-0.3.60.tar.gz/meson_options.txt Changed
29
 
1
@@ -92,6 +92,10 @@
2
        description: 'Enable HFP in native backend in bluez5 spa plugin',
3
        type: 'feature',
4
        value: 'enabled')
5
+option('bluez5-backend-native-mm',
6
+       description: 'Enable ModemManager in native backend in bluez5 spa plugin',
7
+       type: 'feature',
8
+       value: 'disabled')
9
 option('bluez5-backend-ofono',
10
        description: 'Enable oFono HFP backend in bluez5 spa plugin (no dependency on oFono)',
11
        type: 'feature',
12
@@ -228,7 +232,7 @@
13
 option('session-managers',
14
        description : 'Session managers to build (can be  for none or an absolute path)',
15
        type : 'array',
16
-       value : 'media-session')
17
+       value : 'wireplumber')
18
 option('raop',
19
        description: 'Enable module for Remote Audio Output Protocol',
20
        type: 'feature',
21
@@ -261,3 +265,7 @@
22
        description: 'Enable Flatpak support',
23
        type: 'feature',
24
        value: 'enabled')
25
+option('readline',
26
+       description: 'Enable code that depends on libreadline',
27
+       type: 'feature',
28
+       value: 'auto')
29
pipewire-0.3.59.tar.gz/pipewire-alsa/alsa-plugins/pcm_pipewire.c -> pipewire-0.3.60.tar.gz/pipewire-alsa/alsa-plugins/pcm_pipewire.c Changed
143
 
1
@@ -123,7 +123,9 @@
2
    struct spa_hook stream_listener;
3
 
4
    int64_t delay;
5
-   uint64_t now;
6
+   uint64_t transfered;
7
+   uint64_t buffered;
8
+   int64_t now;
9
    uintptr_t seq;
10
 
11
    struct spa_audio_info_raw format;
12
@@ -163,21 +165,15 @@
13
 static int update_active(snd_pcm_ioplug_t *io)
14
 {
15
    snd_pcm_pipewire_t *pw = io->private_data;
16
-   bool active;
17
-
18
-   active = check_active(io);
19
-
20
-   if (pw->active != active) {
21
-       uint64_t val;
22
+   pw->active = check_active(io);
23
+   uint64_t val;
24
 
25
-       pw->active = active;
26
+   if (pw->active || pw->error < 0)
27
+       spa_system_eventfd_write(pw->system, io->poll_fd, 1);
28
+   else
29
+       spa_system_eventfd_read(pw->system, io->poll_fd, &val);
30
 
31
-       if (active)
32
-           spa_system_eventfd_write(pw->system, io->poll_fd, 1);
33
-       else
34
-           spa_system_eventfd_read(pw->system, io->poll_fd, &val);
35
-   }
36
-   return active;
37
+   return pw->active;
38
 }
39
 
40
 static void snd_pcm_pipewire_free(snd_pcm_pipewire_t *pw)
41
@@ -233,8 +229,10 @@
42
        return pw->error;
43
 
44
    *revents = pfds0.revents & ~(POLLIN | POLLOUT);
45
-   if (pfds0.revents & POLLIN && check_active(io))
46
+   if (pfds0.revents & POLLIN && check_active(io)) {
47
        *revents |= (io->stream == SND_PCM_STREAM_PLAYBACK) ? POLLOUT : POLLIN;
48
+       update_active(io);
49
+   }
50
 
51
    return 0;
52
 }
53
@@ -266,7 +264,7 @@
54
    do {
55
        seq1 = SEQ_READ(pw->seq);
56
 
57
-       delay = pw->delay;
58
+       delay = pw->delay + pw->transfered;
59
        now = pw->now;
60
        if (io->stream == SND_PCM_STREAM_PLAYBACK)
61
            avail = snd_pcm_ioplug_hw_avail(io, pw->hw_ptr, io->appl_ptr);
62
@@ -450,9 +448,8 @@
63
    pw_stream_get_time_n(pw->stream, &pwt, sizeof(pwt));
64
 
65
    delay = pwt.delay;
66
-   if (pwt.rate.num != 0) {
67
+   if (pwt.rate.num != 0)
68
        delay = delay * io->rate * pwt.rate.num / pwt.rate.denom;
69
-   }
70
 
71
    before = hw_avail = snd_pcm_ioplug_hw_avail(io, pw->hw_ptr, io->appl_ptr);
72
 
73
@@ -467,12 +464,20 @@
74
 
75
    SEQ_WRITE(pw->seq);
76
 
77
+   if (pw->now != pwt.now) {
78
+       pw->transfered = pw->buffered;
79
+       pw->buffered = 0;
80
+   }
81
+
82
    xfer = snd_pcm_pipewire_process(pw, b, &hw_avail, want);
83
 
84
    pw->delay = delay;
85
    /* the buffer is now queued in the stream and consumed */
86
    if (io->stream == SND_PCM_STREAM_PLAYBACK)
87
-       pw->delay += xfer;
88
+       pw->transfered += xfer;
89
+
90
+   /* more then requested data transfered, use them in next iteration */
91
+   pw->buffered = (want == 0 || pw->transfered < want) ?  0 : (pw->transfered % want);
92
 
93
    pw->now = pwt.now;
94
    SEQ_WRITE(pw->seq);
95
@@ -563,11 +568,6 @@
96
        goto done;
97
    pw->hw_params_changed = false;
98
 
99
-   if (pw->stream != NULL) {
100
-       pw_stream_destroy(pw->stream);
101
-       pw->stream = NULL;
102
-   }
103
-
104
    props = pw_properties_new(NULL, NULL);
105
    if (props == NULL)
106
        goto error;
107
@@ -593,13 +593,20 @@
108
        pw_properties_get(props, PW_KEY_MEDIA_ROLE) == NULL)
109
        pw_properties_setf(props, PW_KEY_MEDIA_ROLE, "%s", pw->role);
110
 
111
+   params0 = spa_format_audio_raw_build(&b, SPA_PARAM_EnumFormat, &pw->format);
112
+
113
+   if (pw->stream != NULL) {
114
+       pw_stream_update_properties(pw->stream, &props->dict);
115
+       pw_stream_update_params(pw->stream, params, 1);
116
+       goto done;
117
+   }
118
+
119
    pw->stream = pw_stream_new(pw->core, pw->node_name, props);
120
    if (pw->stream == NULL)
121
        goto error;
122
 
123
    pw_stream_add_listener(pw->stream, &pw->stream_listener, &stream_events, pw);
124
 
125
-   params0 = spa_format_audio_raw_build(&b, SPA_PARAM_EnumFormat, &pw->format);
126
    pw->error = 0;
127
 
128
    pw_stream_connect(pw->stream,
129
@@ -867,10 +874,9 @@
130
 
131
 static enum snd_pcm_chmap_position channel_to_chmap(enum spa_audio_channel channel)
132
 {
133
-   uint32_t i;
134
-   for (i = 0; i < SPA_N_ELEMENTS(chmap_info); i++)
135
-       if (chmap_infoi.channel == channel)
136
-           return chmap_infoi.pos;
137
+   SPA_FOR_EACH_ELEMENT_VAR(chmap_info, info)
138
+       if (info->channel == channel)
139
+           return info->pos;
140
    return SND_CHMAP_UNKNOWN;
141
 }
142
 
143
pipewire-0.3.59.tar.gz/pipewire-jack/jack/uuid.h -> pipewire-0.3.60.tar.gz/pipewire-jack/jack/uuid.h Changed
33
 
1
@@ -1,18 +1,18 @@
2
 /*
3
     Copyright (C) 2013 Paul Davis
4
-    
5
+
6
     This program is free software; you can redistribute it and/or modify
7
     it under the terms of the GNU Lesser General Public License as published by
8
     the Free Software Foundation; either version 2.1 of the License, or
9
     (at your option) any later version.
10
-    
11
+
12
     This program is distributed in the hope that it will be useful,
13
     but WITHOUT ANY WARRANTY; without even the implied warranty of
14
     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
     GNU Lesser General Public License for more details.
16
-    
17
+
18
     You should have received a copy of the GNU Lesser General Public License
19
-    along with this program; if not, write to the Free Software 
20
+    along with this program; if not, write to the Free Software
21
     Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22
 
23
 */
24
@@ -30,7 +30,7 @@
25
 #define JACK_UUID_STRING_SIZE (JACK_UUID_SIZE+1) /* includes trailing null */
26
 #define JACK_UUID_EMPTY_INITIALIZER 0
27
 
28
-extern jack_uuid_t jack_client_uuid_generate ();
29
+extern jack_uuid_t jack_client_uuid_generate (void);
30
 extern jack_uuid_t jack_port_uuid_generate (uint32_t port_id);
31
 
32
 extern uint32_t jack_uuid_to_index (jack_uuid_t);
33
pipewire-0.3.59.tar.gz/pipewire-jack/src/pipewire-jack.c -> pipewire-0.3.60.tar.gz/pipewire-jack/src/pipewire-jack.c Changed
201
 
1
@@ -98,6 +98,7 @@
2
    pthread_mutex_t lock;
3
    struct pw_array descriptions;
4
    struct spa_list free_objects;
5
+   struct spa_thread_utils *thread_utils;
6
 };
7
 
8
 static struct globals globals;
9
@@ -311,6 +312,7 @@
10
         struct spa_hook proxy_listener;
11
 
12
    struct metadata *metadata;
13
+   struct metadata *settings;
14
 
15
    uint32_t node_id;
16
    uint32_t serial;
17
@@ -401,6 +403,7 @@
18
    int self_connect_mode;
19
    int rt_max;
20
    unsigned int fix_midi_events:1;
21
+   unsigned int global_buffer_size:1;
22
 
23
    jack_position_t jack_position;
24
    jack_transport_state_t jack_state;
25
@@ -610,13 +613,9 @@
26
 {
27
    struct mix *m;
28
 
29
-   if (!p->valid)
30
-       return;
31
-
32
    spa_list_consume(m, &p->mix, port_link)
33
        free_mix(c, m);
34
 
35
-   p->valid = false;
36
    pw_map_remove(&c->portsp->direction, p->port_id);
37
    free_object(c, p->object);
38
    pw_properties_free(p->props);
39
@@ -1056,7 +1055,7 @@
40
    struct buffer *b;
41
    struct spa_data *d;
42
 
43
-   if (frames == 0)
44
+   if (frames == 0 || !p->valid)
45
        return NULL;
46
 
47
    if (SPA_UNLIKELY((mix = p->global_mix) == NULL))
48
@@ -2576,11 +2575,18 @@
49
    return spa_thread_utils_acquire_rt(c->context.old_thread_utils, thread, priority);
50
 }
51
 
52
+static int impl_drop_rt(void *object, struct spa_thread *thread)
53
+{
54
+   struct client *c = (struct client *) object;
55
+   return spa_thread_utils_drop_rt(c->context.old_thread_utils, thread);
56
+}
57
+
58
 static struct spa_thread_utils_methods thread_utils_impl = {
59
    SPA_VERSION_THREAD_UTILS_METHODS,
60
    .create = impl_create,
61
    .join = impl_join,
62
    .acquire_rt = impl_acquire_rt,
63
+   .drop_rt = impl_drop_rt,
64
 };
65
 
66
 static jack_port_type_id_t string_to_type(const char *port_type)
67
@@ -2721,6 +2727,24 @@
68
    .destroy = metadata_proxy_destroy,
69
 };
70
 
71
+static void settings_proxy_removed(void *data)
72
+{
73
+   struct client *c = data;
74
+   pw_proxy_destroy((struct pw_proxy*)c->settings->proxy);
75
+}
76
+
77
+static void settings_proxy_destroy(void *data)
78
+{
79
+   struct client *c = data;
80
+   spa_hook_remove(&c->settings->proxy_listener);
81
+   c->settings = NULL;
82
+}
83
+
84
+static const struct pw_proxy_events settings_proxy_events = {
85
+   PW_VERSION_PROXY_EVENTS,
86
+   .removed = settings_proxy_removed,
87
+   .destroy = settings_proxy_destroy,
88
+};
89
 static void proxy_removed(void *data)
90
 {
91
    struct object *o = data;
92
@@ -3033,24 +3057,34 @@
93
 
94
        if (c->metadata != NULL)
95
            goto exit;
96
-       if ((str = spa_dict_lookup(props, PW_KEY_METADATA_NAME)) != NULL &&
97
-           !spa_streq(str, "default"))
98
+       if ((str = spa_dict_lookup(props, PW_KEY_METADATA_NAME)) == NULL)
99
            goto exit;
100
 
101
-       proxy = pw_registry_bind(c->registry,
102
-               id, type, PW_VERSION_METADATA, sizeof(struct metadata));
103
-
104
-       c->metadata = pw_proxy_get_user_data(proxy);
105
-       c->metadata->proxy = (struct pw_metadata*)proxy;
106
-       c->metadata->default_audio_sink0 = '\0';
107
-       c->metadata->default_audio_source0 = '\0';
108
-
109
-       pw_proxy_add_listener(proxy,
110
-               &c->metadata->proxy_listener,
111
-               &metadata_proxy_events, c);
112
-       pw_metadata_add_listener(proxy,
113
-               &c->metadata->listener,
114
-               &metadata_events, c);
115
+       if (spa_streq(str, "default")) {
116
+           proxy = pw_registry_bind(c->registry,
117
+                   id, type, PW_VERSION_METADATA, sizeof(struct metadata));
118
+
119
+           c->metadata = pw_proxy_get_user_data(proxy);
120
+           c->metadata->proxy = (struct pw_metadata*)proxy;
121
+           c->metadata->default_audio_sink0 = '\0';
122
+           c->metadata->default_audio_source0 = '\0';
123
+
124
+           pw_proxy_add_listener(proxy,
125
+                   &c->metadata->proxy_listener,
126
+                   &metadata_proxy_events, c);
127
+           pw_metadata_add_listener(proxy,
128
+                   &c->metadata->listener,
129
+                   &metadata_events, c);
130
+       } else if (spa_streq(str, "settings")) {
131
+           proxy = pw_registry_bind(c->registry,
132
+                   id, type, PW_VERSION_METADATA, sizeof(struct metadata));
133
+
134
+           c->settings = pw_proxy_get_user_data(proxy);
135
+           c->settings->proxy = (struct pw_metadata*)proxy;
136
+           pw_proxy_add_listener(proxy,
137
+                   &c->settings->proxy_listener,
138
+                   &settings_proxy_events, c);
139
+       }
140
        goto exit;
141
    }
142
    else {
143
@@ -3303,6 +3337,8 @@
144
    if (client->context.old_thread_utils == NULL)
145
        client->context.old_thread_utils = pw_thread_utils_get();
146
 
147
+   globals.thread_utils = client->context.old_thread_utils;
148
+
149
    client->context.thread_utils.iface = SPA_INTERFACE_INIT(
150
            SPA_TYPE_INTERFACE_ThreadUtils,
151
            SPA_VERSION_THREAD_UTILS,
152
@@ -3411,6 +3447,7 @@
153
    client->locked_process = pw_properties_get_bool(client->props, "jack.locked-process", true);
154
    client->default_as_system = pw_properties_get_bool(client->props, "jack.default-as-system", false);
155
    client->fix_midi_events = pw_properties_get_bool(client->props, "jack.fix-midi-events", true);
156
+   client->global_buffer_size = pw_properties_get_bool(client->props, "jack.global-buffer-size", false);
157
 
158
    client->self_connect_mode = SELF_CONNECT_ALLOW;
159
    if ((str = pw_properties_get(client->props, "jack.self-connect-mode")) != NULL) {
160
@@ -3509,10 +3546,11 @@
161
        pw_proxy_destroy((struct pw_proxy*)c->registry);
162
    }
163
    if (c->metadata && c->metadata->proxy) {
164
-       spa_hook_remove(&c->metadata->listener);
165
-       spa_hook_remove(&c->metadata->proxy_listener);
166
        pw_proxy_destroy((struct pw_proxy*)c->metadata->proxy);
167
    }
168
+   if (c->settings && c->settings->proxy) {
169
+       pw_proxy_destroy((struct pw_proxy*)c->settings->proxy);
170
+   }
171
 
172
    if (c->core) {
173
        spa_hook_remove(&c->core_listener);
174
@@ -3773,14 +3811,10 @@
175
 jack_native_thread_t jack_client_thread_id (jack_client_t *client)
176
 {
177
    struct client *c = (struct client *) client;
178
-   void *thr;
179
 
180
    spa_return_val_if_fail(c != NULL, (pthread_t){0});
181
 
182
-   thr = pw_data_loop_get_thread(c->loop);
183
-   if (thr == NULL)
184
-       return pthread_self();
185
-   return (pthread_t) thr;
186
+   return (jack_native_thread_t)pw_data_loop_get_thread(c->loop);
187
 }
188
 
189
 SPA_EXPORT
190
@@ -4137,15 +4171,22 @@
191
    pw_log_info("%p: buffer-size %u", client, nframes);
192
 
193
    pw_thread_loop_lock(c->context.loop);
194
-   pw_properties_setf(c->props, PW_KEY_NODE_FORCE_QUANTUM, "%u", nframes);
195
+   if (c->global_buffer_size && c->settings && c->settings->proxy) {
196
+       char val256;
197
+       snprintf(val, sizeof(val), "%u", nframes == 1 ? 0: nframes);
198
+       pw_metadata_set_property(c->settings->proxy, 0,
199
+               "clock.force-quantum", "", val);
200
+   } else {
201
pipewire-0.3.59.tar.gz/pipewire-jack/src/uuid.c -> pipewire-0.3.60.tar.gz/pipewire-jack/src/uuid.c Changed
10
 
1
@@ -33,7 +33,7 @@
2
 #include <pipewire/pipewire.h>
3
 
4
 SPA_EXPORT
5
-jack_uuid_t jack_client_uuid_generate ()
6
+jack_uuid_t jack_client_uuid_generate (void)
7
 {
8
    static uint32_t uuid_cnt = 0;
9
    jack_uuid_t uuid = 0x2; /* JackUUIDClient */;
10
pipewire-0.3.59.tar.gz/pipewire-v4l2/src/pipewire-v4l2.c -> pipewire-0.3.60.tar.gz/pipewire-v4l2/src/pipewire-v4l2.c Changed
201
 
1
@@ -57,6 +57,7 @@
2
 #define DEFAULT_CARD       "PipeWire Camera"
3
 #define DEFAULT_BUS_INFO   "PipeWire"
4
 
5
+#define MAX_DEV        32
6
 struct file_map {
7
    void *addr;
8
    struct file *file;
9
@@ -64,6 +65,8 @@
10
 
11
 struct fd_map {
12
    int fd;
13
+#define FD_MAP_DUP (1<<0)
14
+   uint32_t flags;
15
    struct file *file;
16
 };
17
 
18
@@ -73,6 +76,7 @@
19
    pthread_mutex_t lock;
20
    struct pw_array fd_maps;
21
    struct pw_array file_maps;
22
+   uint32_t dev_mapMAX_DEV;
23
 };
24
 
25
 static struct globals globals;
26
@@ -93,6 +97,9 @@
27
 struct file {
28
    int ref;
29
 
30
+   uint32_t dev_id;
31
+   uint32_t serial;
32
+
33
    struct pw_properties *props;
34
    struct pw_thread_loop *loop;
35
    struct pw_loop *l;
36
@@ -114,23 +121,27 @@
37
    struct pw_stream *stream;
38
    struct spa_hook stream_listener;
39
 
40
+   enum v4l2_priority priority;
41
+
42
    struct v4l2_format v4l2_format;
43
    uint32_t reqbufs;
44
 
45
+   int reqbufs_fd;
46
    struct buffer buffersMAX_BUFFERS;
47
    uint32_t n_buffers;
48
    uint32_t size;
49
 
50
+   uint32_t sequence;
51
+
52
    struct pw_array buffer_maps;
53
 
54
    uint32_t last_fourcc;
55
 
56
    unsigned int running:1;
57
+   unsigned int closed:1;
58
    int fd;
59
 };
60
 
61
-#define MAX_PARAMS 32
62
-
63
 struct global_info {
64
    const char *type;
65
    uint32_t version;
66
@@ -156,8 +167,8 @@
67
 
68
    int changed;
69
    void *info;
70
+   struct spa_list pending_list;
71
    struct spa_list param_list;
72
-   int param_seqMAX_PARAMS;
73
 
74
    union {
75
        struct {
76
@@ -173,6 +184,7 @@
77
 struct param {
78
    struct spa_list link;
79
    uint32_t id;
80
+   int32_t seq;
81
    struct spa_pod *param;
82
 };
83
 
84
@@ -192,7 +204,7 @@
85
 }
86
 
87
 static struct param *add_param(struct spa_list *params,
88
-       int seq, int *param_seq, uint32_t id, const struct spa_pod *param)
89
+       int seq, uint32_t id, const struct spa_pod *param)
90
 {
91
    struct param *p;
92
 
93
@@ -204,24 +216,12 @@
94
        id = SPA_POD_OBJECT_ID(param);
95
    }
96
 
97
-   if (id >= MAX_PARAMS) {
98
-       pw_log_error("too big param id %d", id);
99
-       errno = EINVAL;
100
-       return NULL;
101
-   }
102
-
103
-   if (seq != param_seqid) {
104
-       pw_log_debug("ignoring param %d, seq:%d != current_seq:%d",
105
-               id, seq, param_seqid);
106
-       errno = EBUSY;
107
-       return NULL;
108
-   }
109
-
110
    p = malloc(sizeof(*p) + (param != NULL ? SPA_POD_SIZE(param) : 0));
111
    if (p == NULL)
112
        return NULL;
113
 
114
    p->id = id;
115
+   p->seq = seq;
116
    if (param != NULL) {
117
        p->param = SPA_PTROFF(p, sizeof(*p), struct spa_pod);
118
        memcpy(p->param, param, SPA_POD_SIZE(param));
119
@@ -234,6 +234,39 @@
120
    return p;
121
 }
122
 
123
+static void update_params(struct file *file)
124
+{
125
+   struct param *p, *t;
126
+   struct global *node;
127
+   struct pw_node_info *info;
128
+   uint32_t i;
129
+
130
+   if ((node = file->node) == NULL)
131
+       return;
132
+   if ((info = node->info) == NULL)
133
+       return;
134
+
135
+   for (i = 0; i < info->n_params; i++) {
136
+       spa_list_for_each_safe(p, t, &node->pending_list, link) {
137
+           if (p->id == info->paramsi.id &&
138
+               p->seq != info->paramsi.seq &&
139
+               p->param != NULL) {
140
+               spa_list_remove(&p->link);
141
+               free(p);
142
+           }
143
+       }
144
+   }
145
+
146
+   spa_list_consume(p, &node->pending_list, link) {
147
+       spa_list_remove(&p->link);
148
+       if (p->param == NULL) {
149
+           clear_params(&node->param_list, p->id);
150
+           free(p);
151
+       } else {
152
+           spa_list_append(&node->param_list, &p->link);
153
+       }
154
+   }
155
+}
156
 #define ATOMIC_DEC(s)                   __atomic_sub_fetch(&(s), 1, __ATOMIC_SEQ_CST)
157
 #define ATOMIC_INC(s)                   __atomic_add_fetch(&(s), 1, __ATOMIC_SEQ_CST)
158
 
159
@@ -247,6 +280,8 @@
160
 
161
    file->ref = 1;
162
    file->fd = -1;
163
+   file->reqbufs_fd = -1;
164
+   file->priority = V4L2_PRIORITY_DEFAULT;
165
    spa_list_init(&file->globals);
166
    pw_array_init(&file->buffer_maps, sizeof(struct buffer_map) * MAX_BUFFERS);
167
    return file;
168
@@ -254,6 +289,8 @@
169
 
170
 static void free_file(struct file *file)
171
 {
172
+   pw_log_info("file:%d", file->fd);
173
+
174
    if (file->loop)
175
        pw_thread_loop_stop(file->loop);
176
 
177
@@ -282,49 +319,99 @@
178
 
179
 static void unref_file(struct file *file)
180
 {
181
+   pw_log_debug("file:%d ref:%d", file->fd, file->ref);
182
    if (ATOMIC_DEC(file->ref) <= 0)
183
        free_file(file);
184
 }
185
 
186
-static int add_fd_map(int fd, struct file *file)
187
+static int add_fd_map(int fd, struct file *file, uint32_t flags)
188
 {
189
    struct fd_map *map;
190
    pthread_mutex_lock(&globals.lock);
191
    map = pw_array_add(&globals.fd_maps, sizeof(*map));
192
    if (map != NULL) {
193
        map->fd = fd;
194
+       map->flags = flags;
195
        map->file = file;
196
        ATOMIC_INC(file->ref);
197
+       pw_log_debug("fd:%d -> file:%d ref:%d", fd, file->fd, file->ref);
198
    }
199
    pthread_mutex_unlock(&globals.lock);
200
    return 0;
201
pipewire-0.3.59.tar.gz/pipewire-v4l2/src/pw-v4l2.in -> pipewire-0.3.60.tar.gz/pipewire-v4l2/src/pw-v4l2.in Changed
20
 
1
@@ -54,10 +54,16 @@
2
 
3
 shift $(( OPTIND - 1 ))
4
 
5
+if  "$PW_UNINSTALLED" = 1  ; then
6
+   PW_V4L2_LD_PRELOAD="$PW_BUILDDIR"'/pipewire-v4l2/src/libpw-v4l2.so'
7
+else
8
+   PW_V4L2_LD_PRELOAD='@LIBV4L2_PATH@/libpw-v4l2.so'
9
+fi
10
+
11
 if  "$LD_PRELOAD" = ""  ; then
12
-   LD_PRELOAD='@LIBV4L2_PATH@/libpw-v4l2.so'
13
+   LD_PRELOAD="$PW_V4L2_LD_PRELOAD"
14
 else
15
-   LD_PRELOAD="$LD_PRELOAD "'@LIBV4L2_PATH@/libpw-v4l2.so'
16
+   LD_PRELOAD="$LD_PRELOAD $PW_V4L2_LD_PRELOAD"
17
 fi
18
 
19
 export LD_PRELOAD
20
pipewire-0.3.59.tar.gz/po/cs.po -> pipewire-0.3.60.tar.gz/po/cs.po Changed
201
 
1
@@ -8,10 +8,10 @@
2
 msgid ""
3
 msgstr ""
4
 "Project-Id-Version: pipewire.master-tx\n"
5
-"Report-Msgid-Bugs-To: https://gitlab.freedesktop.org/pipewire/pipewire/"
6
-"issues/new\n"
7
-"POT-Creation-Date: 2021-04-18 16:54+0800\n"
8
-"PO-Revision-Date: 2021-10-12 14:18+0200\n"
9
+"Report-Msgid-Bugs-To: https://gitlab.freedesktop.org/pipewire/pipewire/-/"
10
+"issues\n"
11
+"POT-Creation-Date: 2022-09-15 15:26+0000\n"
12
+"PO-Revision-Date: 2022-10-21 16:44+0200\n"
13
 "Last-Translator: Daniel Rusek <mail@asciiwolf.com>\n"
14
 "Language-Team: čeština <gnome-cs-list@gnome.org>\n"
15
 "Language: cs\n"
16
@@ -19,9 +19,9 @@
17
 "Content-Type: text/plain; charset=UTF-8\n"
18
 "Content-Transfer-Encoding: 8bit\n"
19
 "Plural-Forms: nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;\n"
20
-"X-Generator: Poedit 3.0\n"
21
+"X-Generator: Poedit 3.1.1\n"
22
 
23
-#: src/daemon/pipewire.c:43
24
+#: src/daemon/pipewire.c:46
25
 #, c-format
26
 msgid ""
27
 "%s options\n"
28
@@ -42,36 +42,52 @@
29
 msgid "Start the PipeWire Media System"
30
 msgstr "Spustit multimediální systém PipeWire"
31
 
32
-#: src/examples/media-session/alsa-monitor.c:526
33
-#: spa/plugins/alsa/acp/compat.c:187
34
-msgid "Built-in Audio"
35
-msgstr "Vnitřní zvukový systém"
36
+#: src/modules/module-protocol-pulse/modules/module-tunnel-sink.c:180
37
+#: src/modules/module-protocol-pulse/modules/module-tunnel-source.c:180
38
+#, c-format
39
+msgid "Tunnel to %s/%s"
40
+msgstr "Tunel do %s/%s"
41
 
42
-#: src/examples/media-session/alsa-monitor.c:530
43
-#: spa/plugins/alsa/acp/compat.c:192
44
-msgid "Modem"
45
-msgstr "Modem"
46
+#: src/modules/module-fallback-sink.c:51
47
+#| msgid "Game Output"
48
+msgid "Dummy Output"
49
+msgstr "Předstíraný výstup"
50
 
51
-#: src/examples/media-session/alsa-monitor.c:539
52
+#: src/modules/module-pulse-tunnel.c:662
53
+#, c-format
54
+msgid "Tunnel for %s@%s"
55
+msgstr "Tunel pro %s@%s"
56
+
57
+#: src/modules/module-zeroconf-discover.c:332
58
 msgid "Unknown device"
59
 msgstr "Neznámé zařízení"
60
 
61
-#: src/tools/pw-cat.c:991
62
+#: src/modules/module-zeroconf-discover.c:344
63
+#, c-format
64
+msgid "%s on %s@%s"
65
+msgstr "%s na %s@%s"
66
+
67
+#: src/modules/module-zeroconf-discover.c:348
68
+#, c-format
69
+msgid "%s on %s"
70
+msgstr "%s na %s"
71
+
72
+#: src/tools/pw-cat.c:784
73
 #, c-format
74
 msgid ""
75
-"%s options <file>\n"
76
+"%s options <file>|-\n"
77
 "  -h, --help                            Show this help\n"
78
 "      --version                         Show version\n"
79
 "  -v, --verbose                         Enable verbose operations\n"
80
 "\n"
81
 msgstr ""
82
-"%s volby <soubor>\n"
83
+"%s volby <soubor>|-\n"
84
 "  -h, --help                            Zobrazit tuto nápovědu\n"
85
 "      --version                         Zobrazit verzi\n"
86
 "  -v, --verbose                         Povolit podrobné operace\n"
87
 "\n"
88
 
89
-#: src/tools/pw-cat.c:998
90
+#: src/tools/pw-cat.c:791
91
 #, c-format
92
 msgid ""
93
 "  -R, --remote                          Remote daemon name\n"
94
@@ -85,7 +101,7 @@
95
 "                                          or direct samples (256)\n"
96
 "                                          the rate is the one of the source "
97
 "file\n"
98
-"      --list-targets                    List available targets for --target\n"
99
+"  -P  --properties                      Set node properties\n"
100
 "\n"
101
 msgstr ""
102
 "  -R, --remote                          Název vzdáleného démonu\n"
103
@@ -102,10 +118,10 @@
104
 "                                          nebo přímé vzorky (256)\n"
105
 "                                          frekvence je stejná jako u "
106
 "zdrojového souboru\n"
107
-"      --list-targets                    Zobrazit dostupné cíle pro --target\n"
108
+"  -P  --properties                      Nastavit vlastnosti uzlu\n"
109
 "\n"
110
 
111
-#: src/tools/pw-cat.c:1016
112
+#: src/tools/pw-cat.c:809
113
 #, c-format
114
 msgid ""
115
 "      --rate                            Sample rate (req. for rec) (default "
116
@@ -141,19 +157,21 @@
117
 "je %d)\n"
118
 "\n"
119
 
120
-#: src/tools/pw-cat.c:1033
121
+#: src/tools/pw-cat.c:826
122
 msgid ""
123
 "  -p, --playback                        Playback mode\n"
124
 "  -r, --record                          Recording mode\n"
125
 "  -m, --midi                            Midi mode\n"
126
+"  -d, --dsd                             DSD mode\n"
127
 "\n"
128
 msgstr ""
129
 "  -p, --playback                        Playback mód\n"
130
 "  -r, --record                          Recording mód\n"
131
 "  -m, --midi                            Midi mód\n"
132
+"  -d, --dsd                             DSD mód\n"
133
 "\n"
134
 
135
-#: src/tools/pw-cli.c:2932
136
+#: src/tools/pw-cli.c:2255
137
 #, c-format
138
 msgid ""
139
 "%s options command\n"
140
@@ -171,199 +189,195 @@
141
 "  -r, --remote                          Název vzdáleného démonu\n"
142
 "\n"
143
 
144
-#: spa/plugins/alsa/acp/acp.c:290
145
+#: spa/plugins/alsa/acp/acp.c:321
146
 msgid "Pro Audio"
147
 msgstr "Pro Audio"
148
 
149
-#: spa/plugins/alsa/acp/acp.c:411 spa/plugins/alsa/acp/alsa-mixer.c:4704
150
-#: spa/plugins/bluez5/bluez5-device.c:1000
151
+#: spa/plugins/alsa/acp/acp.c:444 spa/plugins/alsa/acp/alsa-mixer.c:4648
152
+#: spa/plugins/bluez5/bluez5-device.c:1236
153
 msgid "Off"
154
 msgstr "Vypnuto"
155
 
156
-#: spa/plugins/alsa/acp/channelmap.h:466
157
-msgid "(invalid)"
158
-msgstr "(neplatné)"
159
-
160
-#: spa/plugins/alsa/acp/alsa-mixer.c:2709
161
+#: spa/plugins/alsa/acp/alsa-mixer.c:2652
162
 msgid "Input"
163
 msgstr "Vstup"
164
 
165
-#: spa/plugins/alsa/acp/alsa-mixer.c:2710
166
+#: spa/plugins/alsa/acp/alsa-mixer.c:2653
167
 msgid "Docking Station Input"
168
 msgstr "Vstup dokovací stanice"
169
 
170
-#: spa/plugins/alsa/acp/alsa-mixer.c:2711
171
+#: spa/plugins/alsa/acp/alsa-mixer.c:2654
172
 msgid "Docking Station Microphone"
173
 msgstr "Mikrofon dokovací stanice"
174
 
175
-#: spa/plugins/alsa/acp/alsa-mixer.c:2712
176
+#: spa/plugins/alsa/acp/alsa-mixer.c:2655
177
 msgid "Docking Station Line In"
178
 msgstr "Linkový vstup dokovací stanice"
179
 
180
-#: spa/plugins/alsa/acp/alsa-mixer.c:2713
181
-#: spa/plugins/alsa/acp/alsa-mixer.c:2804
182
+#: spa/plugins/alsa/acp/alsa-mixer.c:2656
183
+#: spa/plugins/alsa/acp/alsa-mixer.c:2747
184
 msgid "Line In"
185
 msgstr "Linkový vstup"
186
 
187
-#: spa/plugins/alsa/acp/alsa-mixer.c:2714
188
-#: spa/plugins/alsa/acp/alsa-mixer.c:2798
189
-#: spa/plugins/bluez5/bluez5-device.c:1145
190
+#: spa/plugins/alsa/acp/alsa-mixer.c:2657
191
+#: spa/plugins/alsa/acp/alsa-mixer.c:2741
192
+#: spa/plugins/bluez5/bluez5-device.c:1454
193
 msgid "Microphone"
194
 msgstr "Mikrofon"
195
 
196
-#: spa/plugins/alsa/acp/alsa-mixer.c:2715
197
-#: spa/plugins/alsa/acp/alsa-mixer.c:2799
198
+#: spa/plugins/alsa/acp/alsa-mixer.c:2658
199
+#: spa/plugins/alsa/acp/alsa-mixer.c:2742
200
 msgid "Front Microphone"
201
pipewire-0.3.59.tar.gz/po/hr.po -> pipewire-0.3.60.tar.gz/po/hr.po Changed
201
 
1
@@ -7,8 +7,8 @@
2
 msgstr ""
3
 "Project-Id-Version: pipewire\n"
4
 "Report-Msgid-Bugs-To: \n"
5
-"POT-Creation-Date: 2022-06-30 12:50+0200\n"
6
-"PO-Revision-Date: 2022-06-30 13:14+0200\n"
7
+"POT-Creation-Date: 2022-10-01 14:01+0200\n"
8
+"PO-Revision-Date: 2022-10-01 14:12+0200\n"
9
 "Last-Translator: gogo <trebelnik2@gmail.com>\n"
10
 "Language-Team: Croatian <https://translate.fedoraproject.org/projects/"
11
 "pipewire/pipewire/hr/>\n"
12
@@ -16,9 +16,9 @@
13
 "MIME-Version: 1.0\n"
14
 "Content-Type: text/plain; charset=UTF-8\n"
15
 "Content-Transfer-Encoding: 8bit\n"
16
-"Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && n"
17
-"%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n"
18
-"X-Generator: Poedit 2.3\n"
19
+"Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && "
20
+"n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n"
21
+"X-Generator: Poedit 3.0.1\n"
22
 "X-Launchpad-Export-Date: 2017-04-20 21:04+0000\n"
23
 
24
 #: src/daemon/pipewire.c:46
25
@@ -44,7 +44,7 @@
26
 msgid "Dummy Output"
27
 msgstr "Lažni izlaz"
28
 
29
-#: src/modules/module-pulse-tunnel.c:648
30
+#: src/modules/module-pulse-tunnel.c:662
31
 #, c-format
32
 msgid "Tunnel for %s@%s"
33
 msgstr "Tunel za %s@%s"
34
@@ -164,7 +164,7 @@
35
 "  -d, --dsd                             DSD način\n"
36
 "\n"
37
 
38
-#: src/tools/pw-cli.c:3165
39
+#: src/tools/pw-cli.c:2250
40
 #, c-format
41
 msgid ""
42
 "%s options command\n"
43
@@ -187,8 +187,8 @@
44
 msgid "Pro Audio"
45
 msgstr "Pro Audio"
46
 
47
-#: spa/plugins/alsa/acp/acp.c:446 spa/plugins/alsa/acp/alsa-mixer.c:4648
48
-#: spa/plugins/bluez5/bluez5-device.c:1161
49
+#: spa/plugins/alsa/acp/acp.c:444 spa/plugins/alsa/acp/alsa-mixer.c:4648
50
+#: spa/plugins/bluez5/bluez5-device.c:1236
51
 msgid "Off"
52
 msgstr "Isključeno"
53
 
54
@@ -215,7 +215,7 @@
55
 
56
 #: spa/plugins/alsa/acp/alsa-mixer.c:2657
57
 #: spa/plugins/alsa/acp/alsa-mixer.c:2741
58
-#: spa/plugins/bluez5/bluez5-device.c:1330
59
+#: spa/plugins/bluez5/bluez5-device.c:1454
60
 msgid "Microphone"
61
 msgstr "Mikrofon"
62
 
63
@@ -281,7 +281,7 @@
64
 msgstr "Bez pojačanja basa"
65
 
66
 #: spa/plugins/alsa/acp/alsa-mixer.c:2672
67
-#: spa/plugins/bluez5/bluez5-device.c:1335
68
+#: spa/plugins/bluez5/bluez5-device.c:1460
69
 msgid "Speaker"
70
 msgstr "Zvučnik"
71
 
72
@@ -396,7 +396,7 @@
73
 
74
 #: spa/plugins/alsa/acp/alsa-mixer.c:4484
75
 #: spa/plugins/alsa/acp/alsa-mixer.c:4642
76
-#: spa/plugins/bluez5/bluez5-device.c:1320
77
+#: spa/plugins/bluez5/bluez5-device.c:1442
78
 msgid "Headset"
79
 msgstr "Slušalice s mikrofonom"
80
 
81
@@ -520,7 +520,8 @@
82
 msgid "%s Input"
83
 msgstr "%s ulaz"
84
 
85
-#: spa/plugins/alsa/acp/alsa-util.c:1173 spa/plugins/alsa/acp/alsa-util.c:1267
86
+#: spa/plugins/alsa/acp/alsa-util.c:1187
87
+#: spa/plugins/alsa/acp/alsa-util.c:1281
88
 #, c-format
89
 msgid ""
90
 "snd_pcm_avail() returned a value that is exceptionally large: %lu byte (%lu "
91
@@ -548,16 +549,16 @@
92
 "Najvjerojatnije je ovo greška ALSA upravljačkog programa '%s'. Prijavite "
93
 "problem ALSA razvijateljima."
94
 
95
-#: spa/plugins/alsa/acp/alsa-util.c:1239
96
+#: spa/plugins/alsa/acp/alsa-util.c:1253
97
 #, c-format
98
 msgid ""
99
-"snd_pcm_delay() returned a value that is exceptionally large: %li byte (%s"
100
-"%lu ms).\n"
101
+"snd_pcm_delay() returned a value that is exceptionally large: %li byte "
102
+"(%s%lu ms).\n"
103
 "Most likely this is a bug in the ALSA driver '%s'. Please report this issue "
104
 "to the ALSA developers."
105
 msgid_plural ""
106
-"snd_pcm_delay() returned a value that is exceptionally large: %li bytes (%s"
107
-"%lu ms).\n"
108
+"snd_pcm_delay() returned a value that is exceptionally large: %li bytes "
109
+"(%s%lu ms).\n"
110
 "Most likely this is a bug in the ALSA driver '%s'. Please report this issue "
111
 "to the ALSA developers."
112
 msgstr0 ""
113
@@ -566,17 +567,17 @@
114
 "Najvjerojatnije je ovo greška ALSA upravljačkog programa '%s'. Prijavite "
115
 "problem ALSA razvijateljima."
116
 msgstr1 ""
117
-"snd_pcm_delay() je vratio vrijednost koja je iznimno velika: %li bajta (%s"
118
-"%lu ms).\n"
119
+"snd_pcm_delay() je vratio vrijednost koja je iznimno velika: %li bajta "
120
+"(%s%lu ms).\n"
121
 "Najvjerojatnije je ovo greška ALSA upravljačkog programa '%s'. Prijavite "
122
 "problem ALSA razvijateljima."
123
 msgstr2 ""
124
-"snd_pcm_delay() je vratio vrijednost koja je iznimno velika: %li bajta (%s"
125
-"%lu ms).\n"
126
+"snd_pcm_delay() je vratio vrijednost koja je iznimno velika: %li bajta "
127
+"(%s%lu ms).\n"
128
 "Najvjerojatnije je ovo greška ALSA upravljačkog programa '%s'. Prijavite "
129
 "problem ALSA razvijateljima."
130
 
131
-#: spa/plugins/alsa/acp/alsa-util.c:1286
132
+#: spa/plugins/alsa/acp/alsa-util.c:1300
133
 #, c-format
134
 msgid ""
135
 "snd_pcm_avail_delay() returned strange values: delay %lu is less than avail "
136
@@ -589,7 +590,7 @@
137
 "Najvjerojatnije je ovo greška ALSA upravljačkog programa '%s'. Prijavite "
138
 "problem ALSA razvijateljima."
139
 
140
-#: spa/plugins/alsa/acp/alsa-util.c:1329
141
+#: spa/plugins/alsa/acp/alsa-util.c:1343
142
 #, c-format
143
 msgid ""
144
 "snd_pcm_mmap_begin() returned a value that is exceptionally large: %lu byte "
145
@@ -629,65 +630,96 @@
146
 msgid "Modem"
147
 msgstr "Modem"
148
 
149
-#: spa/plugins/bluez5/bluez5-device.c:1172
150
+#: spa/plugins/bluez5/bluez5-device.c:1247
151
 msgid "Audio Gateway (A2DP Source & HSP/HFP AG)"
152
 msgstr "Zvučni pristupnik (A2DP izvor i HSP/HFP AG)"
153
 
154
-#: spa/plugins/bluez5/bluez5-device.c:1197
155
+#: spa/plugins/bluez5/bluez5-device.c:1272
156
 #, c-format
157
 msgid "High Fidelity Playback (A2DP Sink, codec %s)"
158
 msgstr "Reprodukcija visoke autentičnosti (A2DP slivnik, kôdek %s)"
159
 
160
-#: spa/plugins/bluez5/bluez5-device.c:1200
161
+#: spa/plugins/bluez5/bluez5-device.c:1275
162
 #, c-format
163
 msgid "High Fidelity Duplex (A2DP Source/Sink, codec %s)"
164
 msgstr "Telefonija visoke autentičnosti (A2DP slivnik, kôdek %s)"
165
 
166
-#: spa/plugins/bluez5/bluez5-device.c:1208
167
+#: spa/plugins/bluez5/bluez5-device.c:1283
168
 msgid "High Fidelity Playback (A2DP Sink)"
169
 msgstr "Reprodukcija visoke autentičnosti (A2DP slivnik)"
170
 
171
-#: spa/plugins/bluez5/bluez5-device.c:1210
172
+#: spa/plugins/bluez5/bluez5-device.c:1285
173
 msgid "High Fidelity Duplex (A2DP Source/Sink)"
174
 msgstr "Telefonija visoke autentičnosti (A2DP izvor/slivnik)"
175
 
176
-#: spa/plugins/bluez5/bluez5-device.c:1238
177
+#: spa/plugins/bluez5/bluez5-device.c:1322
178
+#, c-format
179
+msgid "High Fidelity Playback (BAP Sink, codec %s)"
180
+msgstr "Reprodukcija visoke autentičnosti (BAP slivnik, kôdek %s)"
181
+
182
+#: spa/plugins/bluez5/bluez5-device.c:1326
183
+#, c-format
184
+msgid "High Fidelity Input (BAP Source, codec %s)"
185
+msgstr "Ulaz visoke autentičnosti (BAP izvor, kôdek %s)"
186
+
187
+#: spa/plugins/bluez5/bluez5-device.c:1330
188
+#, c-format
189
+msgid "High Fidelity Duplex (BAP Source/Sink, codec %s)"
190
+msgstr "Telefonija visoke autentičnosti (BAP izvor/slivnik, kôdek %s)"
191
+
192
+#: spa/plugins/bluez5/bluez5-device.c:1359
193
 #, c-format
194
 msgid "Headset Head Unit (HSP/HFP, codec %s)"
195
 msgstr "Jedinica slušalice s mikrofonom (HSP/HFP, kôdek %s)"
196
 
197
-#: spa/plugins/bluez5/bluez5-device.c:1243
198
+#: spa/plugins/bluez5/bluez5-device.c:1364
199
 msgid "Headset Head Unit (HSP/HFP)"
200
 msgstr "Jedinica slušalice s mikrofonom (HSP/HFP)"
201
pipewire-0.3.59.tar.gz/po/pipewire.pot -> pipewire-0.3.60.tar.gz/po/pipewire.pot Changed
201
 
1
@@ -37,7 +37,7 @@
2
 msgid "Dummy Output"
3
 msgstr ""
4
 
5
-#: src/modules/module-pulse-tunnel.c:648
6
+#: src/modules/module-pulse-tunnel.c:662
7
 #, c-format
8
 msgid "Tunnel for %s@%s"
9
 msgstr ""
10
@@ -113,7 +113,7 @@
11
 "\n"
12
 msgstr ""
13
 
14
-#: src/tools/pw-cli.c:3165
15
+#: src/tools/pw-cli.c:2250
16
 #, c-format
17
 msgid ""
18
 "%s options command\n"
19
@@ -128,8 +128,8 @@
20
 msgid "Pro Audio"
21
 msgstr ""
22
 
23
-#: spa/plugins/alsa/acp/acp.c:446 spa/plugins/alsa/acp/alsa-mixer.c:4648
24
-#: spa/plugins/bluez5/bluez5-device.c:1161
25
+#: spa/plugins/alsa/acp/acp.c:444 spa/plugins/alsa/acp/alsa-mixer.c:4648
26
+#: spa/plugins/bluez5/bluez5-device.c:1236
27
 msgid "Off"
28
 msgstr ""
29
 
30
@@ -156,7 +156,7 @@
31
 
32
 #: spa/plugins/alsa/acp/alsa-mixer.c:2657
33
 #: spa/plugins/alsa/acp/alsa-mixer.c:2741
34
-#: spa/plugins/bluez5/bluez5-device.c:1330
35
+#: spa/plugins/bluez5/bluez5-device.c:1454
36
 msgid "Microphone"
37
 msgstr ""
38
 
39
@@ -222,7 +222,7 @@
40
 msgstr ""
41
 
42
 #: spa/plugins/alsa/acp/alsa-mixer.c:2672
43
-#: spa/plugins/bluez5/bluez5-device.c:1335
44
+#: spa/plugins/bluez5/bluez5-device.c:1460
45
 msgid "Speaker"
46
 msgstr ""
47
 
48
@@ -337,7 +337,7 @@
49
 
50
 #: spa/plugins/alsa/acp/alsa-mixer.c:4484
51
 #: spa/plugins/alsa/acp/alsa-mixer.c:4642
52
-#: spa/plugins/bluez5/bluez5-device.c:1320
53
+#: spa/plugins/bluez5/bluez5-device.c:1442
54
 msgid "Headset"
55
 msgstr ""
56
 
57
@@ -461,8 +461,8 @@
58
 msgid "%s Input"
59
 msgstr ""
60
 
61
-#: spa/plugins/alsa/acp/alsa-util.c:1173
62
-#: spa/plugins/alsa/acp/alsa-util.c:1267
63
+#: spa/plugins/alsa/acp/alsa-util.c:1187
64
+#: spa/plugins/alsa/acp/alsa-util.c:1281
65
 #, c-format
66
 msgid ""
67
 "snd_pcm_avail() returned a value that is exceptionally large: %lu byte (%lu "
68
@@ -477,22 +477,22 @@
69
 msgstr0 ""
70
 msgstr1 ""
71
 
72
-#: spa/plugins/alsa/acp/alsa-util.c:1239
73
+#: spa/plugins/alsa/acp/alsa-util.c:1253
74
 #, c-format
75
 msgid ""
76
-"snd_pcm_delay() returned a value that is exceptionally large: %li byte (%s"
77
-"%lu ms).\n"
78
+"snd_pcm_delay() returned a value that is exceptionally large: %li byte "
79
+"(%s%lu ms).\n"
80
 "Most likely this is a bug in the ALSA driver '%s'. Please report this issue "
81
 "to the ALSA developers."
82
 msgid_plural ""
83
-"snd_pcm_delay() returned a value that is exceptionally large: %li bytes (%s"
84
-"%lu ms).\n"
85
+"snd_pcm_delay() returned a value that is exceptionally large: %li bytes "
86
+"(%s%lu ms).\n"
87
 "Most likely this is a bug in the ALSA driver '%s'. Please report this issue "
88
 "to the ALSA developers."
89
 msgstr0 ""
90
 msgstr1 ""
91
 
92
-#: spa/plugins/alsa/acp/alsa-util.c:1286
93
+#: spa/plugins/alsa/acp/alsa-util.c:1300
94
 #, c-format
95
 msgid ""
96
 "snd_pcm_avail_delay() returned strange values: delay %lu is less than avail "
97
@@ -501,7 +501,7 @@
98
 "to the ALSA developers."
99
 msgstr ""
100
 
101
-#: spa/plugins/alsa/acp/alsa-util.c:1329
102
+#: spa/plugins/alsa/acp/alsa-util.c:1343
103
 #, c-format
104
 msgid ""
105
 "snd_pcm_mmap_begin() returned a value that is exceptionally large: %lu byte "
106
@@ -528,61 +528,92 @@
107
 msgid "Modem"
108
 msgstr ""
109
 
110
-#: spa/plugins/bluez5/bluez5-device.c:1172
111
+#: spa/plugins/bluez5/bluez5-device.c:1247
112
 msgid "Audio Gateway (A2DP Source & HSP/HFP AG)"
113
 msgstr ""
114
 
115
-#: spa/plugins/bluez5/bluez5-device.c:1197
116
+#: spa/plugins/bluez5/bluez5-device.c:1272
117
 #, c-format
118
 msgid "High Fidelity Playback (A2DP Sink, codec %s)"
119
 msgstr ""
120
 
121
-#: spa/plugins/bluez5/bluez5-device.c:1200
122
+#: spa/plugins/bluez5/bluez5-device.c:1275
123
 #, c-format
124
 msgid "High Fidelity Duplex (A2DP Source/Sink, codec %s)"
125
 msgstr ""
126
 
127
-#: spa/plugins/bluez5/bluez5-device.c:1208
128
+#: spa/plugins/bluez5/bluez5-device.c:1283
129
 msgid "High Fidelity Playback (A2DP Sink)"
130
 msgstr ""
131
 
132
-#: spa/plugins/bluez5/bluez5-device.c:1210
133
+#: spa/plugins/bluez5/bluez5-device.c:1285
134
 msgid "High Fidelity Duplex (A2DP Source/Sink)"
135
 msgstr ""
136
 
137
-#: spa/plugins/bluez5/bluez5-device.c:1238
138
+#: spa/plugins/bluez5/bluez5-device.c:1322
139
+#, c-format
140
+msgid "High Fidelity Playback (BAP Sink, codec %s)"
141
+msgstr ""
142
+
143
+#: spa/plugins/bluez5/bluez5-device.c:1326
144
+#, c-format
145
+msgid "High Fidelity Input (BAP Source, codec %s)"
146
+msgstr ""
147
+
148
+#: spa/plugins/bluez5/bluez5-device.c:1330
149
+#, c-format
150
+msgid "High Fidelity Duplex (BAP Source/Sink, codec %s)"
151
+msgstr ""
152
+
153
+#: spa/plugins/bluez5/bluez5-device.c:1359
154
 #, c-format
155
 msgid "Headset Head Unit (HSP/HFP, codec %s)"
156
 msgstr ""
157
 
158
-#: spa/plugins/bluez5/bluez5-device.c:1243
159
+#: spa/plugins/bluez5/bluez5-device.c:1364
160
 msgid "Headset Head Unit (HSP/HFP)"
161
 msgstr ""
162
 
163
-#: spa/plugins/bluez5/bluez5-device.c:1325
164
+#: spa/plugins/bluez5/bluez5-device.c:1443
165
+#: spa/plugins/bluez5/bluez5-device.c:1448
166
+#: spa/plugins/bluez5/bluez5-device.c:1455
167
+#: spa/plugins/bluez5/bluez5-device.c:1461
168
+#: spa/plugins/bluez5/bluez5-device.c:1467
169
+#: spa/plugins/bluez5/bluez5-device.c:1473
170
+#: spa/plugins/bluez5/bluez5-device.c:1479
171
+#: spa/plugins/bluez5/bluez5-device.c:1485
172
+#: spa/plugins/bluez5/bluez5-device.c:1491
173
 msgid "Handsfree"
174
 msgstr ""
175
 
176
-#: spa/plugins/bluez5/bluez5-device.c:1340
177
+#: spa/plugins/bluez5/bluez5-device.c:1449
178
+msgid "Handsfree (HFP)"
179
+msgstr ""
180
+
181
+#: spa/plugins/bluez5/bluez5-device.c:1466
182
 msgid "Headphone"
183
 msgstr ""
184
 
185
-#: spa/plugins/bluez5/bluez5-device.c:1345
186
+#: spa/plugins/bluez5/bluez5-device.c:1472
187
 msgid "Portable"
188
 msgstr ""
189
 
190
-#: spa/plugins/bluez5/bluez5-device.c:1350
191
+#: spa/plugins/bluez5/bluez5-device.c:1478
192
 msgid "Car"
193
 msgstr ""
194
 
195
-#: spa/plugins/bluez5/bluez5-device.c:1355
196
+#: spa/plugins/bluez5/bluez5-device.c:1484
197
 msgid "HiFi"
198
 msgstr ""
199
 
200
-#: spa/plugins/bluez5/bluez5-device.c:1360
201
pipewire-0.3.59.tar.gz/po/pt_BR.po -> pipewire-0.3.60.tar.gz/po/pt_BR.po Changed
201
 
1
@@ -1,18 +1,19 @@
2
 # Brazilian Portuguese translation for pipewire
3
-# Copyright (C) 2021 Rafael Fontenelle <rafaelff@gnome.org>
4
+# Copyright (C) 2022 Rafael Fontenelle <rafaelff@gnome.org>
5
 # This file is distributed under the same license as the pipewire package.
6
 # Fabian Affolter <fab@fedoraproject.org>, 2008.
7
 # Igor Pires Soares <igor@projetofedora.org>, 2009, 2012.
8
 # Rafael Fontenelle <rafaelff@gnome.org>, 2013-2021.
9
+# Matheus Barbosa <mdpb.matheus@gmail.com>, 2022.
10
 #
11
 msgid ""
12
 msgstr ""
13
 "Project-Id-Version: pipewire\n"
14
 "Report-Msgid-Bugs-To: https://gitlab.freedesktop.org/pipewire/pipewire/-/"
15
 "issues\n"
16
-"POT-Creation-Date: 2021-08-01 15:31+0000\n"
17
-"PO-Revision-Date: 2021-08-01 17:02-0300\n"
18
-"Last-Translator: Rafael Fontenelle <rafaelff@gnome.org>\n"
19
+"POT-Creation-Date: 2022-09-30 03:27+0000\n"
20
+"PO-Revision-Date: 2022-01-25 19:49-0300\n"
21
+"Last-Translator: Matheus Barbosa <mdpb.matheus@gmail.com>\n"
22
 "Language-Team: Brazilian Portuguese <gnome-pt_br-list@gnome.org>\n"
23
 "Language: pt_BR\n"
24
 "MIME-Version: 1.0\n"
25
@@ -21,7 +22,7 @@
26
 "Plural-Forms: nplurals=2; plural=(n > 1)\n"
27
 "X-Generator: Gtranslator 40.0\n"
28
 
29
-#: src/daemon/pipewire.c:45
30
+#: src/daemon/pipewire.c:46
31
 #, c-format
32
 msgid ""
33
 "%s options\n"
34
@@ -43,58 +44,51 @@
35
 msgid "Start the PipeWire Media System"
36
 msgstr "Inicia o Sistema de Mídia PipeWire"
37
 
38
-#: src/examples/media-session/alsa-monitor.c:586
39
-#: spa/plugins/alsa/acp/compat.c:189
40
-msgid "Built-in Audio"
41
-msgstr "Áudio interno"
42
-
43
-#: src/examples/media-session/alsa-monitor.c:590
44
-#: spa/plugins/alsa/acp/compat.c:194
45
-msgid "Modem"
46
-msgstr "Modem"
47
-
48
-#: src/examples/media-session/alsa-monitor.c:599
49
-#: src/modules/module-zeroconf-discover.c:296
50
-msgid "Unknown device"
51
-msgstr "Dispositivo desconhecido"
52
-
53
-#: src/modules/module-protocol-pulse/modules/module-tunnel-sink.c:173
54
-#: src/modules/module-protocol-pulse/modules/module-tunnel-source.c:173
55
+#: src/modules/module-protocol-pulse/modules/module-tunnel-sink.c:180
56
+#: src/modules/module-protocol-pulse/modules/module-tunnel-source.c:180
57
 #, c-format
58
 msgid "Tunnel to %s/%s"
59
 msgstr "Túnel para %s/%s"
60
 
61
-#: src/modules/module-pulse-tunnel.c:534
62
+#: src/modules/module-fallback-sink.c:51
63
+msgid "Dummy Output"
64
+msgstr "Saída de falsa"
65
+
66
+#: src/modules/module-pulse-tunnel.c:662
67
 #, c-format
68
 msgid "Tunnel for %s@%s"
69
 msgstr "Túnel para %s@%s"
70
 
71
-#: src/modules/module-zeroconf-discover.c:308
72
+#: src/modules/module-zeroconf-discover.c:332
73
+msgid "Unknown device"
74
+msgstr "Dispositivo desconhecido"
75
+
76
+#: src/modules/module-zeroconf-discover.c:344
77
 #, c-format
78
 msgid "%s on %s@%s"
79
 msgstr "%s em %s@%s"
80
 
81
-#: src/modules/module-zeroconf-discover.c:312
82
+#: src/modules/module-zeroconf-discover.c:348
83
 #, c-format
84
 msgid "%s on %s"
85
 msgstr "%s em %s"
86
 
87
-#: src/tools/pw-cat.c:1000
88
+#: src/tools/pw-cat.c:784
89
 #, c-format
90
 msgid ""
91
-"%s options <file>\n"
92
+"%s options <file>|-\n"
93
 "  -h, --help                            Show this help\n"
94
 "      --version                         Show version\n"
95
 "  -v, --verbose                         Enable verbose operations\n"
96
 "\n"
97
 msgstr ""
98
-"%s opções <arquivo>\n"
99
+"%s opções <arquivo>|-\n"
100
 "  -h, --help                            Mostra esta ajuda\n"
101
 "      --version                         Mostra a versão\n"
102
 "  -v, --verbose                         Habilita operações verbosas\n"
103
 "\n"
104
 
105
-#: src/tools/pw-cat.c:1007
106
+#: src/tools/pw-cat.c:791
107
 #, c-format
108
 msgid ""
109
 "  -R, --remote                          Remote daemon name\n"
110
@@ -108,7 +102,7 @@
111
 "                                          or direct samples (256)\n"
112
 "                                          the rate is the one of the source "
113
 "file\n"
114
-"      --list-targets                    List available targets for --target\n"
115
+"  -P  --properties                      Set node properties\n"
116
 "\n"
117
 msgstr ""
118
 "  -R, --remote                          Nome do daemon remoto\n"
119
@@ -124,11 +118,10 @@
120
 "                                          Xunit (unidade = s, ms, us, ns)\n"
121
 "                                          ou amostras diretas (256)\n"
122
 "                                          a taxa é um dos arquivos fontes\n"
123
-"      --list-targets                    Lista alvos disponíveis para --"
124
-"target\n"
125
+"      --properties                      Define as propriedades do nó\n"
126
 "\n"
127
 
128
-#: src/tools/pw-cat.c:1025
129
+#: src/tools/pw-cat.c:809
130
 #, c-format
131
 msgid ""
132
 "      --rate                            Sample rate (req. for rec) (default "
133
@@ -165,19 +158,21 @@
134
 "(padrão: %d)\n"
135
 "\n"
136
 
137
-#: src/tools/pw-cat.c:1042
138
+#: src/tools/pw-cat.c:826
139
 msgid ""
140
 "  -p, --playback                        Playback mode\n"
141
 "  -r, --record                          Recording mode\n"
142
 "  -m, --midi                            Midi mode\n"
143
+"  -d, --dsd                             DSD mode\n"
144
 "\n"
145
 msgstr ""
146
 "  -p, --playback                        Modo de reprodução\n"
147
 "  -r, --record                          Modo de gravação\n"
148
-"  -m, --midi                            Modo midi\n"
149
+"  -m, --midi                            Modo Midi\n"
150
+"  -d, --dsd                             Modo DSD\n"
151
 "\n"
152
 
153
-#: src/tools/pw-cli.c:2954
154
+#: src/tools/pw-cli.c:2255
155
 #, c-format
156
 msgid ""
157
 "%s options command\n"
158
@@ -194,12 +189,12 @@
159
 "  -r, --remote                          Nome do daemon remoto\n"
160
 "\n"
161
 
162
-#: spa/plugins/alsa/acp/acp.c:306
163
+#: spa/plugins/alsa/acp/acp.c:321
164
 msgid "Pro Audio"
165
 msgstr "Pro Audio"
166
 
167
-#: spa/plugins/alsa/acp/acp.c:429 spa/plugins/alsa/acp/alsa-mixer.c:4648
168
-#: spa/plugins/bluez5/bluez5-device.c:1043
169
+#: spa/plugins/alsa/acp/acp.c:444 spa/plugins/alsa/acp/alsa-mixer.c:4648
170
+#: spa/plugins/bluez5/bluez5-device.c:1236
171
 msgid "Off"
172
 msgstr "Desligado"
173
 
174
@@ -226,7 +221,7 @@
175
 
176
 #: spa/plugins/alsa/acp/alsa-mixer.c:2657
177
 #: spa/plugins/alsa/acp/alsa-mixer.c:2741
178
-#: spa/plugins/bluez5/bluez5-device.c:1198
179
+#: spa/plugins/bluez5/bluez5-device.c:1454
180
 msgid "Microphone"
181
 msgstr "Microfone"
182
 
183
@@ -298,7 +293,7 @@
184
 msgstr "Sem reforço de graves"
185
 
186
 #: spa/plugins/alsa/acp/alsa-mixer.c:2672
187
-#: spa/plugins/bluez5/bluez5-device.c:1203
188
+#: spa/plugins/bluez5/bluez5-device.c:1460
189
 msgid "Speaker"
190
 msgstr "Auto-falante"
191
 
192
@@ -414,7 +409,7 @@
193
 # Fone de ouvido não se encaixa como tradução aqui, pois há ou pode haver microfone junto.
194
 #: spa/plugins/alsa/acp/alsa-mixer.c:4484
195
 #: spa/plugins/alsa/acp/alsa-mixer.c:4642
196
-#: spa/plugins/bluez5/bluez5-device.c:1188
197
+#: spa/plugins/bluez5/bluez5-device.c:1442
198
 msgid "Headset"
199
 msgstr "Headset"
200
 
201
pipewire-0.3.59.tar.gz/po/sv.po -> pipewire-0.3.60.tar.gz/po/sv.po Changed
201
 
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: 2022-07-19 15:27+0000\n"
6
-"PO-Revision-Date: 2022-07-10 10:22+0200\n"
7
+"POT-Creation-Date: 2022-10-20 15:27+0000\n"
8
+"PO-Revision-Date: 2022-09-16 12:58+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
@@ -28,7 +28,7 @@
13
 "Content-Type: text/plain; charset=UTF-8\n"
14
 "Content-Transfer-Encoding: 8bit\n"
15
 "Plural-Forms: nplurals=2; plural=n != 1;\n"
16
-"X-Generator: Poedit 3.1\n"
17
+"X-Generator: Poedit 3.1.1\n"
18
 
19
 #: src/daemon/pipewire.c:46
20
 #, c-format
21
@@ -61,26 +61,26 @@
22
 msgid "Dummy Output"
23
 msgstr "Attrapputgång"
24
 
25
-#: src/modules/module-pulse-tunnel.c:648
26
+#: src/modules/module-pulse-tunnel.c:681
27
 #, c-format
28
 msgid "Tunnel for %s@%s"
29
 msgstr "Tunnel för %s@%s"
30
 
31
-#: src/modules/module-zeroconf-discover.c:332
32
+#: src/modules/module-zeroconf-discover.c:335
33
 msgid "Unknown device"
34
 msgstr "Okänd enhet"
35
 
36
-#: src/modules/module-zeroconf-discover.c:344
37
+#: src/modules/module-zeroconf-discover.c:347
38
 #, c-format
39
 msgid "%s on %s@%s"
40
 msgstr "%s på %s@%s"
41
 
42
-#: src/modules/module-zeroconf-discover.c:348
43
+#: src/modules/module-zeroconf-discover.c:351
44
 #, c-format
45
 msgid "%s on %s"
46
 msgstr "%s på %s"
47
 
48
-#: src/tools/pw-cat.c:784
49
+#: src/tools/pw-cat.c:782
50
 #, c-format
51
 msgid ""
52
 "%s options <file>|-\n"
53
@@ -95,7 +95,7 @@
54
 "  -v, --verbose                         Aktivera utförliga operationer\n"
55
 "\n"
56
 
57
-#: src/tools/pw-cat.c:791
58
+#: src/tools/pw-cat.c:789
59
 #, c-format
60
 msgid ""
61
 "  -R, --remote                          Remote daemon name\n"
62
@@ -125,7 +125,7 @@
63
 "  -P  --properties                      Sätt nodegenskaper\n"
64
 "\n"
65
 
66
-#: src/tools/pw-cat.c:809
67
+#: src/tools/pw-cat.c:807
68
 #, c-format
69
 msgid ""
70
 "      --rate                            Sample rate (req. for rec) (default "
71
@@ -160,7 +160,7 @@
72
 "%d)\n"
73
 "\n"
74
 
75
-#: src/tools/pw-cat.c:826
76
+#: src/tools/pw-cat.c:824
77
 msgid ""
78
 "  -p, --playback                        Playback mode\n"
79
 "  -r, --record                          Recording mode\n"
80
@@ -174,7 +174,7 @@
81
 "  -d, --dsd                             DSD-läge\n"
82
 "\n"
83
 
84
-#: src/tools/pw-cli.c:3165
85
+#: src/tools/pw-cli.c:2250
86
 #, c-format
87
 msgid ""
88
 "%s options command\n"
89
@@ -195,8 +195,8 @@
90
 msgid "Pro Audio"
91
 msgstr "Professionellt ljud"
92
 
93
-#: spa/plugins/alsa/acp/acp.c:446 spa/plugins/alsa/acp/alsa-mixer.c:4648
94
-#: spa/plugins/bluez5/bluez5-device.c:1188
95
+#: spa/plugins/alsa/acp/acp.c:444 spa/plugins/alsa/acp/alsa-mixer.c:4648
96
+#: spa/plugins/bluez5/bluez5-device.c:1237
97
 msgid "Off"
98
 msgstr "Av"
99
 
100
@@ -223,7 +223,7 @@
101
 
102
 #: spa/plugins/alsa/acp/alsa-mixer.c:2657
103
 #: spa/plugins/alsa/acp/alsa-mixer.c:2741
104
-#: spa/plugins/bluez5/bluez5-device.c:1360
105
+#: spa/plugins/bluez5/bluez5-device.c:1455
106
 msgid "Microphone"
107
 msgstr "Mikrofon"
108
 
109
@@ -289,7 +289,7 @@
110
 msgstr "Ingen basökning"
111
 
112
 #: spa/plugins/alsa/acp/alsa-mixer.c:2672
113
-#: spa/plugins/bluez5/bluez5-device.c:1366
114
+#: spa/plugins/bluez5/bluez5-device.c:1461
115
 msgid "Speaker"
116
 msgstr "Högtalare"
117
 
118
@@ -404,7 +404,7 @@
119
 
120
 #: spa/plugins/alsa/acp/alsa-mixer.c:4484
121
 #: spa/plugins/alsa/acp/alsa-mixer.c:4642
122
-#: spa/plugins/bluez5/bluez5-device.c:1348
123
+#: spa/plugins/bluez5/bluez5-device.c:1443
124
 msgid "Headset"
125
 msgstr "Headset"
126
 
127
@@ -528,7 +528,7 @@
128
 msgid "%s Input"
129
 msgstr "%s-ingång"
130
 
131
-#: spa/plugins/alsa/acp/alsa-util.c:1173 spa/plugins/alsa/acp/alsa-util.c:1267
132
+#: spa/plugins/alsa/acp/alsa-util.c:1187 spa/plugins/alsa/acp/alsa-util.c:1281
133
 #, c-format
134
 msgid ""
135
 "snd_pcm_avail() returned a value that is exceptionally large: %lu byte (%lu "
136
@@ -551,7 +551,7 @@
137
 "Förmodligen är detta ett fel i ALSA-drivrutinen ”%s”. Vänligen rapportera "
138
 "problemet till ALSA-utvecklarna."
139
 
140
-#: spa/plugins/alsa/acp/alsa-util.c:1239
141
+#: spa/plugins/alsa/acp/alsa-util.c:1253
142
 #, c-format
143
 msgid ""
144
 "snd_pcm_delay() returned a value that is exceptionally large: %li byte (%s"
145
@@ -574,7 +574,7 @@
146
 "Förmodligen är detta ett fel i ALSA-drivrutinen ”%s”. Vänligen rapportera "
147
 "problemet till ALSA-utvecklarna."
148
 
149
-#: spa/plugins/alsa/acp/alsa-util.c:1286
150
+#: spa/plugins/alsa/acp/alsa-util.c:1300
151
 #, c-format
152
 msgid ""
153
 "snd_pcm_avail_delay() returned strange values: delay %lu is less than avail "
154
@@ -587,7 +587,7 @@
155
 "Förmodligen är detta ett fel i ALSA-drivrutinen ”%s”. Vänligen rapportera "
156
 "problemet till ALSA-utvecklarna."
157
 
158
-#: spa/plugins/alsa/acp/alsa-util.c:1329
159
+#: spa/plugins/alsa/acp/alsa-util.c:1343
160
 #, c-format
161
 msgid ""
162
 "snd_pcm_mmap_begin() returned a value that is exceptionally large: %lu byte "
163
@@ -622,77 +622,92 @@
164
 msgid "Modem"
165
 msgstr "Modem"
166
 
167
-#: spa/plugins/bluez5/bluez5-device.c:1199
168
+#: spa/plugins/bluez5/bluez5-device.c:1248
169
 msgid "Audio Gateway (A2DP Source & HSP/HFP AG)"
170
 msgstr "Audio gateway (A2DP-källa & HSP/HFP AG)"
171
 
172
-#: spa/plugins/bluez5/bluez5-device.c:1224
173
+#: spa/plugins/bluez5/bluez5-device.c:1273
174
 #, c-format
175
 msgid "High Fidelity Playback (A2DP Sink, codec %s)"
176
 msgstr "High fidelity-uppspelning (A2DP-utgång, kodek %s)"
177
 
178
-#: spa/plugins/bluez5/bluez5-device.c:1227
179
+#: spa/plugins/bluez5/bluez5-device.c:1276
180
 #, c-format
181
 msgid "High Fidelity Duplex (A2DP Source/Sink, codec %s)"
182
 msgstr "High fidelity duplex (A2DP-källa/utgång, kodek %s)"
183
 
184
-#: spa/plugins/bluez5/bluez5-device.c:1235
185
+#: spa/plugins/bluez5/bluez5-device.c:1284
186
 msgid "High Fidelity Playback (A2DP Sink)"
187
 msgstr "High fidelity-uppspelning (A2DP-utgång)"
188
 
189
-#: spa/plugins/bluez5/bluez5-device.c:1237
190
+#: spa/plugins/bluez5/bluez5-device.c:1286
191
 msgid "High Fidelity Duplex (A2DP Source/Sink)"
192
 msgstr "High fidelity duplex (A2DP-källa/utgång)"
193
 
194
-#: spa/plugins/bluez5/bluez5-device.c:1265
195
+#: spa/plugins/bluez5/bluez5-device.c:1323
196
+#, c-format
197
+msgid "High Fidelity Playback (BAP Sink, codec %s)"
198
+msgstr "High fidelity-uppspelning (BAP-utgång, kodek %s)"
199
+
200
+#: spa/plugins/bluez5/bluez5-device.c:1327
201
pipewire-0.3.59.tar.gz/po/tr.po -> pipewire-0.3.60.tar.gz/po/tr.po Changed
201
 
1
@@ -11,8 +11,8 @@
2
 "Project-Id-Version: PipeWire master\n"
3
 "Report-Msgid-Bugs-To: https://gitlab.freedesktop.org/pipewire/pipewire/"
4
 "issues/new\n"
5
-"POT-Creation-Date: 2022-04-03 12:56+0200\n"
6
-"PO-Revision-Date: 2022-05-14 18:35+0300\n"
7
+"POT-Creation-Date: 2022-06-30 12:50+0200\n"
8
+"PO-Revision-Date: 2022-10-23 10:40+0300\n"
9
 "Last-Translator: Oğuz Ersen <oguz@ersen.moe>\n"
10
 "Language-Team: Turkish <tr>\n"
11
 "Language: tr\n"
12
@@ -35,8 +35,8 @@
13
 "      --version                         Sürümü göster\n"
14
 "  -c, --config                          Yapılandırmayı yükle (Öntanımlı %s)\n"
15
 
16
-#: src/modules/module-protocol-pulse/modules/module-tunnel-sink.c:190
17
-#: src/modules/module-protocol-pulse/modules/module-tunnel-source.c:190
18
+#: src/modules/module-protocol-pulse/modules/module-tunnel-sink.c:180
19
+#: src/modules/module-protocol-pulse/modules/module-tunnel-source.c:180
20
 #, c-format
21
 msgid "Tunnel to %s/%s"
22
 msgstr "%s/%s tüneli"
23
@@ -45,41 +45,41 @@
24
 msgid "Dummy Output"
25
 msgstr "Temsili Çıkış"
26
 
27
-#: src/modules/module-pulse-tunnel.c:545
28
+#: src/modules/module-pulse-tunnel.c:662
29
 #, c-format
30
 msgid "Tunnel for %s@%s"
31
 msgstr "%s@%s için tünel"
32
 
33
-#: src/modules/module-zeroconf-discover.c:313
34
+#: src/modules/module-zeroconf-discover.c:332
35
 msgid "Unknown device"
36
 msgstr "Bilinmeyen aygıt"
37
 
38
-#: src/modules/module-zeroconf-discover.c:325
39
+#: src/modules/module-zeroconf-discover.c:344
40
 #, c-format
41
 msgid "%s on %s@%s"
42
 msgstr "%s, %s@%s"
43
 
44
-#: src/modules/module-zeroconf-discover.c:329
45
+#: src/modules/module-zeroconf-discover.c:348
46
 #, c-format
47
 msgid "%s on %s"
48
 msgstr "%s, %s"
49
 
50
-#: src/tools/pw-cat.c:1087
51
+#: src/tools/pw-cat.c:784
52
 #, c-format
53
 msgid ""
54
-"%s options <file>\n"
55
+"%s options <file>|-\n"
56
 "  -h, --help                            Show this help\n"
57
 "      --version                         Show version\n"
58
 "  -v, --verbose                         Enable verbose operations\n"
59
 "\n"
60
 msgstr ""
61
-"%s seçenekler <dosya>\n"
62
+"%s seçenekler <dosya>|-\n"
63
 "  -h, --help                            Bu yardımı göster\n"
64
 "      --version                         Sürümü göster\n"
65
 "  -v, --verbose                         Ayrıntılı işlemleri etkinleştir\n"
66
 "\n"
67
 
68
-#: src/tools/pw-cat.c:1094
69
+#: src/tools/pw-cat.c:791
70
 #, c-format
71
 msgid ""
72
 "  -R, --remote                          Remote daemon name\n"
73
@@ -93,7 +93,7 @@
74
 "                                          or direct samples (256)\n"
75
 "                                          the rate is the one of the source "
76
 "file\n"
77
-"      --list-targets                    List available targets for --target\n"
78
+"  -P  --properties                      Set node properties\n"
79
 "\n"
80
 msgstr ""
81
 "  -R, --remote                          Uzak arka plan programı adı\n"
82
@@ -109,11 +109,10 @@
83
 "                                          Xbirim (birim = s, ms, us, ns)\n"
84
 "                                          veya doğrudan örneklemeler (256)\n"
85
 "                                          oran kaynak dosyadan biridir\n"
86
-"      --list-targets                    --target için kullanılabilir "
87
-"hedefleri listele\n"
88
+"  -P  --properties                      Düğüm özelliklerini ayarla\n"
89
 "\n"
90
 
91
-#: src/tools/pw-cat.c:1112
92
+#: src/tools/pw-cat.c:809
93
 #, c-format
94
 msgid ""
95
 "      --rate                            Sample rate (req. for rec) (default "
96
@@ -149,7 +148,7 @@
97
 "15) (öntanımlı %d)\n"
98
 "\n"
99
 
100
-#: src/tools/pw-cat.c:1129
101
+#: src/tools/pw-cat.c:826
102
 msgid ""
103
 "  -p, --playback                        Playback mode\n"
104
 "  -r, --record                          Recording mode\n"
105
@@ -163,7 +162,7 @@
106
 "  -d, --dsd                             DSD modu\n"
107
 "\n"
108
 
109
-#: src/tools/pw-cli.c:3051
110
+#: src/tools/pw-cli.c:2250
111
 #, c-format
112
 msgid ""
113
 "%s options command\n"
114
@@ -186,7 +185,7 @@
115
 msgstr "Profesyonel Ses"
116
 
117
 #: spa/plugins/alsa/acp/acp.c:444 spa/plugins/alsa/acp/alsa-mixer.c:4648
118
-#: spa/plugins/bluez5/bluez5-device.c:1159
119
+#: spa/plugins/bluez5/bluez5-device.c:1236
120
 msgid "Off"
121
 msgstr "Kapalı"
122
 
123
@@ -213,7 +212,7 @@
124
 
125
 #: spa/plugins/alsa/acp/alsa-mixer.c:2657
126
 #: spa/plugins/alsa/acp/alsa-mixer.c:2741
127
-#: spa/plugins/bluez5/bluez5-device.c:1328
128
+#: spa/plugins/bluez5/bluez5-device.c:1454
129
 msgid "Microphone"
130
 msgstr "Mikrofon"
131
 
132
@@ -279,7 +278,7 @@
133
 msgstr "Bas Artırma Yok"
134
 
135
 #: spa/plugins/alsa/acp/alsa-mixer.c:2672
136
-#: spa/plugins/bluez5/bluez5-device.c:1333
137
+#: spa/plugins/bluez5/bluez5-device.c:1460
138
 msgid "Speaker"
139
 msgstr "Hoparlör"
140
 
141
@@ -394,7 +393,7 @@
142
 
143
 #: spa/plugins/alsa/acp/alsa-mixer.c:4484
144
 #: spa/plugins/alsa/acp/alsa-mixer.c:4642
145
-#: spa/plugins/bluez5/bluez5-device.c:1318
146
+#: spa/plugins/bluez5/bluez5-device.c:1442
147
 msgid "Headset"
148
 msgstr "Kulaklık"
149
 
150
@@ -518,7 +517,7 @@
151
 msgid "%s Input"
152
 msgstr "%s Girişi"
153
 
154
-#: spa/plugins/alsa/acp/alsa-util.c:1173 spa/plugins/alsa/acp/alsa-util.c:1267
155
+#: spa/plugins/alsa/acp/alsa-util.c:1187 spa/plugins/alsa/acp/alsa-util.c:1281
156
 #, c-format
157
 msgid ""
158
 "snd_pcm_avail() returned a value that is exceptionally large: %lu byte (%lu "
159
@@ -535,7 +534,7 @@
160
 "Büyük ihtimalle bu bir ALSA sürücüsü '%s' hatasıdır. Lütfen bu sorunu ALSA "
161
 "geliştiricilerine bildirin."
162
 
163
-#: spa/plugins/alsa/acp/alsa-util.c:1239
164
+#: spa/plugins/alsa/acp/alsa-util.c:1253
165
 #, c-format
166
 msgid ""
167
 "snd_pcm_delay() returned a value that is exceptionally large: %li byte "
168
@@ -552,7 +551,7 @@
169
 "Büyük ihtimalle bu bir ALSA sürücüsü '%s' hatasıdır. Lütfen bu sorunu ALSA "
170
 "geliştiricilerine bildirin."
171
 
172
-#: spa/plugins/alsa/acp/alsa-util.c:1286
173
+#: spa/plugins/alsa/acp/alsa-util.c:1300
174
 #, c-format
175
 msgid ""
176
 "snd_pcm_avail_delay() returned strange values: delay %lu is less than avail "
177
@@ -565,7 +564,7 @@
178
 "Büyük ihtimalle bu bir ALSA sürücüsü '%s' hatasıdır. Lütfen bu sorunu ALSA "
179
 "geliştiricilerine bildirin."
180
 
181
-#: spa/plugins/alsa/acp/alsa-util.c:1329
182
+#: spa/plugins/alsa/acp/alsa-util.c:1343
183
 #, c-format
184
 msgid ""
185
 "snd_pcm_mmap_begin() returned a value that is exceptionally large: %lu byte "
186
@@ -583,7 +582,7 @@
187
 "Büyük ihtimalle bu bir ALSA sürücüsü '%s' hatasıdır. Lütfen bu sorunu ALSA "
188
 "geliştiricilerine bildirin."
189
 
190
-#: spa/plugins/alsa/acp/channelmap.h:464
191
+#: spa/plugins/alsa/acp/channelmap.h:457
192
 msgid "(invalid)"
193
 msgstr "(geçersiz)"
194
 
195
@@ -595,65 +594,96 @@
196
 msgid "Modem"
197
 msgstr "Modem"
198
 
199
-#: spa/plugins/bluez5/bluez5-device.c:1170
200
+#: spa/plugins/bluez5/bluez5-device.c:1247
201
pipewire-0.3.59.tar.gz/pw-uninstalled.sh -> pipewire-0.3.60.tar.gz/pw-uninstalled.sh Changed
18
 
1
@@ -41,7 +41,7 @@
2
 export SPA_DATA_DIR="${SCRIPT_DIR}/spa/plugins"
3
 # the directory with pipewire modules
4
 export PIPEWIRE_MODULE_DIR="${BUILDDIR}/src/modules"
5
-export PATH="${BUILDDIR}/src/daemon:${BUILDDIR}/src/tools:${BUILDDIR}/src/media-session:${BUILDDIR}/src/examples:${PATH}"
6
+export PATH="${BUILDDIR}/src/daemon:${BUILDDIR}/src/tools:${BUILDDIR}/src/media-session:${BUILDDIR}/src/examples:${BUILDDIR}/pipewire-v4l2/src:${PATH}"
7
 export LD_LIBRARY_PATH="${BUILDDIR}/src/pipewire/:${BUILDDIR}/pipewire-jack/src/${LD_LIBRARY_PATH+":$LD_LIBRARY_PATH"}"
8
 export GST_PLUGIN_PATH="${BUILDDIR}/src/gst/${GST_PLUGIN_PATH+":${GST_PLUGIN_PATH}"}"
9
 # the directory with card profiles and paths
10
@@ -50,6 +50,7 @@
11
 # ALSA plugin directory
12
 export ALSA_PLUGIN_DIR="${BUILDDIR}/pipewire-alsa/alsa-plugins"
13
 
14
+export PW_BUILDDIR=$BUILDDIR
15
 export PW_UNINSTALLED=1
16
 export PKG_CONFIG_PATH="${BUILDDIR}/meson-uninstalled/:${PKG_CONFIG_PATH}"
17
 
18
pipewire-0.3.59.tar.gz/spa/include/spa/interfaces/audio/aec.h -> pipewire-0.3.60.tar.gz/spa/include/spa/interfaces/audio/aec.h Changed
40
 
1
@@ -23,6 +23,7 @@
2
  */
3
 
4
 
5
+#include <spa/pod/builder.h>
6
 #include <spa/utils/dict.h>
7
 #include <spa/utils/hook.h>
8
 #include <spa/param/audio/raw.h>
9
@@ -60,7 +61,7 @@
10
 };
11
 
12
 struct spa_audio_aec_methods {
13
-#define SPA_VERSION_AUDIO_AEC_METHODS  1
14
+#define SPA_VERSION_AUDIO_AEC_METHODS  2
15
         uint32_t version;
16
 
17
    int (*add_listener) (void *object,
18
@@ -75,6 +76,11 @@
19
    int (*activate) (void *object);
20
    /* since 0.3.58, version 1:1 */
21
    int (*deactivate) (void *object);
22
+
23
+   /* version 1:2 */
24
+   int (*enum_props) (void* object, int index, struct spa_pod_builder* builder);
25
+   int (*get_params) (void* object, struct spa_pod_builder* builder);
26
+   int (*set_params) (void *object, const struct spa_pod *args);
27
 };
28
 
29
 #define spa_audio_aec_method(o,method,version,...)         \
30
@@ -93,6 +99,9 @@
31
 #define spa_audio_aec_set_props(o,...)     spa_audio_aec_method(o, set_props, 0, __VA_ARGS__)
32
 #define spa_audio_aec_activate(o)      spa_audio_aec_method(o, activate, 1)
33
 #define spa_audio_aec_deactivate(o)        spa_audio_aec_method(o, deactivate, 1)
34
+#define spa_audio_aec_enum_props(o,...)        spa_audio_aec_method(o, enum_props, 2, __VA_ARGS__)
35
+#define spa_audio_aec_get_params(o,...)        spa_audio_aec_method(o, get_params, 2, __VA_ARGS__)
36
+#define spa_audio_aec_set_params(o,...)        spa_audio_aec_method(o, set_params, 2, __VA_ARGS__)
37
 
38
 #ifdef __cplusplus
39
 }  /* extern "C" */
40
pipewire-0.3.59.tar.gz/spa/include/spa/param/audio/format-utils.h -> pipewire-0.3.60.tar.gz/spa/include/spa/param/audio/format-utils.h Changed
49
 
1
@@ -47,9 +47,9 @@
2
    info->flags = 0;
3
    res = spa_pod_parse_object(format,
4
            SPA_TYPE_OBJECT_Format, NULL,
5
-           SPA_FORMAT_AUDIO_format,    SPA_POD_Id(&info->format),
6
-           SPA_FORMAT_AUDIO_rate,      SPA_POD_Int(&info->rate),
7
-           SPA_FORMAT_AUDIO_channels,  SPA_POD_Int(&info->channels),
8
+           SPA_FORMAT_AUDIO_format,    SPA_POD_OPT_Id(&info->format),
9
+           SPA_FORMAT_AUDIO_rate,      SPA_POD_OPT_Int(&info->rate),
10
+           SPA_FORMAT_AUDIO_channels,  SPA_POD_OPT_Int(&info->channels),
11
            SPA_FORMAT_AUDIO_position,  SPA_POD_OPT_Pod(&position));
12
    if (position == NULL ||
13
        !spa_pod_copy_array(position, SPA_TYPE_Id, info->position, SPA_AUDIO_MAX_CHANNELS))
14
@@ -64,7 +64,7 @@
15
    int res;
16
    res = spa_pod_parse_object(format,
17
            SPA_TYPE_OBJECT_Format, NULL,
18
-           SPA_FORMAT_AUDIO_format,    SPA_POD_Id(&info->format));
19
+           SPA_FORMAT_AUDIO_format,    SPA_POD_OPT_Id(&info->format));
20
    return res;
21
 }
22
 
23
@@ -74,8 +74,8 @@
24
    int res;
25
    res = spa_pod_parse_object(format,
26
            SPA_TYPE_OBJECT_Format, NULL,
27
-           SPA_FORMAT_AUDIO_iec958Codec,   SPA_POD_Id(&info->codec),
28
-           SPA_FORMAT_AUDIO_rate,      SPA_POD_Int(&info->rate));
29
+           SPA_FORMAT_AUDIO_iec958Codec,   SPA_POD_OPT_Id(&info->codec),
30
+           SPA_FORMAT_AUDIO_rate,      SPA_POD_OPT_Int(&info->rate));
31
    return res;
32
 }
33
 
34
@@ -87,10 +87,10 @@
35
    info->flags = 0;
36
    res = spa_pod_parse_object(format,
37
            SPA_TYPE_OBJECT_Format, NULL,
38
-           SPA_FORMAT_AUDIO_bitorder,  SPA_POD_Id(&info->bitorder),
39
-           SPA_FORMAT_AUDIO_interleave,    SPA_POD_Int(&info->interleave),
40
-           SPA_FORMAT_AUDIO_rate,      SPA_POD_Int(&info->rate),
41
-           SPA_FORMAT_AUDIO_channels,  SPA_POD_Int(&info->channels),
42
+           SPA_FORMAT_AUDIO_bitorder,  SPA_POD_OPT_Id(&info->bitorder),
43
+           SPA_FORMAT_AUDIO_interleave,    SPA_POD_OPT_Int(&info->interleave),
44
+           SPA_FORMAT_AUDIO_rate,      SPA_POD_OPT_Int(&info->rate),
45
+           SPA_FORMAT_AUDIO_channels,  SPA_POD_OPT_Int(&info->channels),
46
            SPA_FORMAT_AUDIO_position,  SPA_POD_OPT_Pod(&position));
47
    if (position == NULL ||
48
        !spa_pod_copy_array(position, SPA_TYPE_Id, info->position, SPA_AUDIO_MAX_CHANNELS))
49
pipewire-0.3.59.tar.gz/spa/include/spa/param/param.h -> pipewire-0.3.60.tar.gz/spa/include/spa/param/param.h Changed
12
 
1
@@ -72,7 +72,9 @@
2
    uint32_t flags;
3
    uint32_t user;          /**< private user field. You can use this to keep
4
                      *  state. */
5
-   uint32_t padding5;
6
+   int32_t seq;            /**< private seq field. You can use this to keep
7
+                     *  state of a pending update. */
8
+   uint32_t padding4;
9
 };
10
 
11
 #define SPA_PARAM_INFO(id,flags) ((struct spa_param_info){ (id), (flags) })
12
pipewire-0.3.59.tar.gz/spa/include/spa/param/video/format-utils.h -> pipewire-0.3.60.tar.gz/spa/include/spa/param/video/format-utils.h Changed
24
 
1
@@ -44,10 +44,10 @@
2
 {
3
    return spa_pod_parse_object(format,
4
        SPA_TYPE_OBJECT_Format, NULL,
5
-       SPA_FORMAT_VIDEO_format,        SPA_POD_Id(&info->format),
6
+       SPA_FORMAT_VIDEO_format,        SPA_POD_OPT_Id(&info->format),
7
        SPA_FORMAT_VIDEO_modifier,      SPA_POD_OPT_Long(&info->modifier),
8
-       SPA_FORMAT_VIDEO_size,          SPA_POD_Rectangle(&info->size),
9
-       SPA_FORMAT_VIDEO_framerate,     SPA_POD_Fraction(&info->framerate),
10
+       SPA_FORMAT_VIDEO_size,          SPA_POD_OPT_Rectangle(&info->size),
11
+       SPA_FORMAT_VIDEO_framerate,     SPA_POD_OPT_Fraction(&info->framerate),
12
        SPA_FORMAT_VIDEO_maxFramerate,      SPA_POD_OPT_Fraction(&info->max_framerate),
13
        SPA_FORMAT_VIDEO_views,         SPA_POD_OPT_Int(&info->views),
14
        SPA_FORMAT_VIDEO_interlaceMode,     SPA_POD_OPT_Id(&info->interlace_mode),
15
@@ -67,7 +67,7 @@
16
 {
17
    return spa_pod_parse_object(format,
18
        SPA_TYPE_OBJECT_Format, NULL,
19
-       SPA_FORMAT_VIDEO_format,        SPA_POD_Id(&info->format),
20
+       SPA_FORMAT_VIDEO_format,        SPA_POD_OPT_Id(&info->format),
21
        SPA_FORMAT_VIDEO_modifier,      SPA_POD_OPT_Long(&info->modifier));
22
 }
23
 
24
pipewire-0.3.59.tar.gz/spa/include/spa/pod/event.h -> pipewire-0.3.60.tar.gz/spa/include/spa/pod/event.h Changed
14
 
1
@@ -49,9 +49,9 @@
2
 #define SPA_EVENT_ID(ev,type)  (SPA_EVENT_TYPE(ev) == (type) ? \
3
                    (ev)->body.body.id : SPA_ID_INVALID)
4
 
5
-#define SPA_EVENT_INIT_FULL(t,size,type,id,...) (t)            \
6
-   { { size, SPA_TYPE_OBJECT },                    \
7
-     { { type, id }, ##__VA_ARGS__ } }             \
8
+#define SPA_EVENT_INIT_FULL(t,size,type,id,...) ((t)           \
9
+   { { (size), SPA_TYPE_OBJECT },                  \
10
+     { { (type), (id) }, ##__VA_ARGS__ } })            \
11
 
12
 #define SPA_EVENT_INIT(type,id)                        \
13
    SPA_EVENT_INIT_FULL(struct spa_event,               \
14
pipewire-0.3.59.tar.gz/spa/include/spa/utils/defs.h -> pipewire-0.3.60.tar.gz/spa/include/spa/utils/defs.h Changed
88
 
1
@@ -82,7 +82,8 @@
2
 #endif
3
 
4
 #define SPA_FLAG_MASK(field,mask,flag) (((field) & (mask)) == (flag))
5
-#define SPA_FLAG_IS_SET(field,flag)    SPA_FLAG_MASK(field,flag,flag)
6
+#define SPA_FLAG_IS_SET(field,flag)    SPA_FLAG_MASK(field, flag, flag)
7
+
8
 #define SPA_FLAG_SET(field,flag)   ((field) |= (flag))
9
 #define SPA_FLAG_CLEAR(field, flag)                    \
10
 ({                                 \
11
@@ -140,21 +141,24 @@
12
 #define SPA_FOR_EACH_ELEMENT(arr, ptr) \
13
    for ((ptr) = arr; (void*)(ptr) < SPA_PTROFF(arr, sizeof(arr), void); (ptr)++)
14
 
15
+#define SPA_FOR_EACH_ELEMENT_VAR(arr, var) \
16
+   for (__typeof__((arr)0)* (var) = arr; (void*)(var) < SPA_PTROFF(arr, sizeof(arr), void); (var)++)
17
+
18
 #define SPA_ABS(a)         \
19
 ({                 \
20
    __typeof__(a) _a = (a);     \
21
    SPA_LIKELY(_a >= 0) ? _a : -_a; \
22
 })
23
-#define SPA_MIN(a,b)       \
24
-({             \
25
-   __typeof__(a) _min_a = (a); \
26
-   __typeof__(b) _min_b = (b); \
27
+#define SPA_MIN(a,b)                   \
28
+({                         \
29
+   __typeof__(a) _min_a = (a);         \
30
+   __typeof__(b) _min_b = (b);         \
31
    SPA_LIKELY(_min_a <= _min_b) ? _min_a : _min_b; \
32
 })
33
-#define SPA_MAX(a,b)       \
34
-({             \
35
-   __typeof__(a) _max_a = (a); \
36
-   __typeof__(b) _max_b = (b); \
37
+#define SPA_MAX(a,b)                   \
38
+({                         \
39
+   __typeof__(a) _max_a = (a);         \
40
+   __typeof__(b) _max_b = (b);         \
41
    SPA_LIKELY(_max_a >= _max_b) ? _max_a : _max_b; \
42
 })
43
 #define SPA_CLAMP(v,low,high)              \
44
@@ -174,7 +178,7 @@
45
 #define SPA_SWAP(a,b)                  \
46
 ({                         \
47
    __typeof__(a) _t = (a);             \
48
-   (a) = b; (b) = _t;                  \
49
+   (a) = b; (b) = _t;              \
50
 })
51
 
52
 #define SPA_TYPECHECK(type,x)      \
53
@@ -254,21 +258,21 @@
54
 #define SPA_RESTRICT
55
 #endif
56
 
57
-#define SPA_ROUND_DOWN(num,value)  ((num) - ((num) % (value)))
58
-#define SPA_ROUND_UP(num,value)        ((((num) + (value) - 1) / (value)) * (value))
59
-
60
-#define SPA_MASK_NEGATED(num1, num2)                   \
61
-({                                 \
62
-   SPA_STATIC_ASSERT(__builtin_constant_p(num2) ?          \
63
-                 (__typeof__(num2))(__typeof__(num1))(__typeof__(num2))(num2) == (num2) : \
64
-             sizeof(num1) >= sizeof(num2),         \
65
-           "truncation problem when masking " #num1    \
66
-           " with ~" #num2);               \
67
-   ((num1) & ~(__typeof__(num1))(num2));               \
68
+#define SPA_ROUND_DOWN(num,value)      \
69
+({                     \
70
+   __typeof__(num) _num = (num);       \
71
+   ((_num) - ((_num) % (value)));      \
72
 })
73
+#define SPA_ROUND_UP(num,value)            \
74
+({                     \
75
+   __typeof__(value) _v = (value);     \
76
+   ((((num) + (_v) - 1) / (_v)) * (_v));   \
77
+})
78
+
79
+#define SPA_ROUND_MASK(num,mask)   ((__typeof__(num))((mask)-1))
80
 
81
-#define SPA_ROUND_DOWN_N(num,align)    SPA_MASK_NEGATED((num), (align) - 1)
82
-#define SPA_ROUND_UP_N(num,align)  SPA_ROUND_DOWN_N((num) + ((align) - 1),align)
83
+#define SPA_ROUND_DOWN_N(num,align)    ((num) & ~SPA_ROUND_MASK(num, align))
84
+#define SPA_ROUND_UP_N(num,align)  ((((num)-1) | SPA_ROUND_MASK(num, align))+1)
85
 
86
 #define SPA_PTR_ALIGNMENT(p,align) ((intptr_t)(p) & ((align)-1))
87
 #define SPA_IS_ALIGNED(p,align)        (SPA_PTR_ALIGNMENT(p,align) == 0)
88
pipewire-0.3.59.tar.gz/spa/include/spa/utils/hook.h -> pipewire-0.3.60.tar.gz/spa/include/spa/utils/hook.h Changed
10
 
1
@@ -166,7 +166,7 @@
2
  *
3
  */
4
 #define SPA_INTERFACE_INIT(_type,_version,_funcs,_data) \
5
-   (struct spa_interface){ _type, _version, SPA_CALLBACKS_INIT(_funcs,_data), }
6
+   ((struct spa_interface){ (_type), (_version), SPA_CALLBACKS_INIT(_funcs,_data), })
7
 
8
 /**
9
  * Invoke method named \a method in the \a callbacks.
10
pipewire-0.3.59.tar.gz/spa/meson.build -> pipewire-0.3.60.tar.gz/spa/meson.build Changed
12
 
1
@@ -66,6 +66,10 @@
2
     summary({'Opus': opus_dep.found()}, bool_yn: true, section: 'Bluetooth audio codecs')
3
     lc3_dep = dependency('lc3', required : get_option('bluez5-codec-lc3'))
4
     summary({'LC3': lc3_dep.found()}, bool_yn: true, section: 'Bluetooth audio codecs')
5
+    if get_option('bluez5-backend-hsp-native').allowed() or get_option('bluez5-backend-hfp-native').allowed()
6
+      mm_dep = dependency('ModemManager', version : '>= 1.10.0', required : get_option('bluez5-backend-native-mm'))
7
+      summary({'ModemManager': mm_dep.found()}, bool_yn: true, section: 'Bluetooth backends')
8
+    endif
9
   endif
10
   avcodec_dep = dependency('libavcodec', required: get_option('ffmpeg'))
11
   jack_dep = dependency('jack', version : '>= 1.9.10', required: get_option('jack'))
12
pipewire-0.3.59.tar.gz/spa/plugins/alsa/acp/acp.c -> pipewire-0.3.60.tar.gz/spa/plugins/alsa/acp/acp.c Changed
51
 
1
@@ -624,7 +624,7 @@
2
    pa_card *impl = snd_mixer_elem_get_callback_private(melem);
3
    snd_hctl_elem_t *elem = snd_mixer_elem_get_private(melem);
4
    snd_ctl_elem_value_t *elem_value;
5
-   bool plugged_in;
6
+   bool plugged_in, any_input_port_available;
7
    void *state;
8
    pa_alsa_jack *jack;
9
    struct temp_port_avail *tp, *tports;
10
@@ -735,6 +735,31 @@
11
    if (impl->card.active_profile_index != ACP_INVALID_INDEX)
12
        active_available = impl->card.profilesimpl->card.active_profile_index->available;
13
 
14
+   /* First round - detect, if we have any input port available.
15
+      If the hardware can report the state for all I/O jacks, only speakers
16
+      may be plugged in. */
17
+   any_input_port_available = false;
18
+   PA_HASHMAP_FOREACH(profile, impl->profiles, state) {
19
+       pa_device_port *port;
20
+       void *state2;
21
+
22
+       if (profile->profile.flags & ACP_PROFILE_OFF)
23
+           continue;
24
+
25
+       PA_HASHMAP_FOREACH(port, impl->ports, state2) {
26
+           if (!pa_hashmap_get(port->profiles, profile->profile.name))
27
+               continue;
28
+
29
+           if (port->port.direction == ACP_DIRECTION_CAPTURE &&
30
+               port->port.available != ACP_AVAILABLE_NO) {
31
+               any_input_port_available = true;
32
+               goto input_port_found;
33
+           }
34
+       }
35
+   }
36
+input_port_found:
37
+
38
+   /* Second round */
39
    PA_HASHMAP_FOREACH(profile, impl->profiles, state) {
40
        pa_device_port *port;
41
        void *state2;
42
@@ -768,7 +793,7 @@
43
 
44
        if (has_input_port && !has_output_port && found_available_input_port)
45
            available = ACP_AVAILABLE_YES;
46
-       if (has_output_port && !has_input_port && found_available_output_port)
47
+       if (has_output_port && (!has_input_port || !any_input_port_available) && found_available_output_port)
48
            available = ACP_AVAILABLE_YES;
49
        if (has_output_port && has_input_port && found_available_output_port && found_available_input_port)
50
            available = ACP_AVAILABLE_YES;
51
pipewire-0.3.59.tar.gz/spa/plugins/alsa/alsa-acp-device.c -> pipewire-0.3.60.tar.gz/spa/plugins/alsa/alsa-acp-device.c Changed
25
 
1
@@ -216,7 +216,7 @@
2
 {
3
    int err = 0;
4
    struct spa_dict_item *items;
5
-   uint32_t i, n_items;
6
+   uint32_t n_items;
7
    const struct acp_dict_item *it;
8
    struct acp_card *card = this->card;
9
    char path128;
10
@@ -241,10 +241,10 @@
11
 #undef ADD_ITEM
12
 
13
        if (this->info.change_mask & SPA_DEVICE_CHANGE_MASK_PARAMS) {
14
-           for (i = 0; i < SPA_N_ELEMENTS(this->params); i++) {
15
-               if (this->paramsi.user > 0) {
16
-                   this->paramsi.flags ^= SPA_PARAM_INFO_SERIAL;
17
-                   this->paramsi.user = 0;
18
+           SPA_FOR_EACH_ELEMENT_VAR(this->params, p) {
19
+               if (p->user > 0) {
20
+                   p->flags ^= SPA_PARAM_INFO_SERIAL;
21
+                   p->user = 0;
22
                }
23
            }
24
        }
25
pipewire-0.3.59.tar.gz/spa/plugins/alsa/alsa-pcm.c -> pipewire-0.3.60.tar.gz/spa/plugins/alsa/alsa-pcm.c Changed
72
 
1
@@ -638,12 +638,10 @@
2
 
3
 static snd_pcm_format_t spa_format_to_alsa(uint32_t format, bool *planar)
4
 {
5
-   size_t i;
6
-
7
-   for (i = 0; i < SPA_N_ELEMENTS(format_info); i++) {
8
-       *planar = format_infoi.spa_pformat == format;
9
-       if (format_infoi.spa_format == format || *planar)
10
-           return format_infoi.format;
11
+   SPA_FOR_EACH_ELEMENT_VAR(format_info, i) {
12
+       *planar = i->spa_pformat == format;
13
+       if (i->spa_format == format || *planar)
14
+           return i->format;
15
    }
16
    return SND_PCM_FORMAT_UNKNOWN;
17
 }
18
@@ -969,7 +967,7 @@
19
        struct spa_pod **result, struct spa_pod_builder *b)
20
 {
21
    int res, err;
22
-   size_t i, j;
23
+   size_t j;
24
    snd_pcm_t *hndl;
25
    snd_pcm_hw_params_t *params;
26
    struct spa_pod_frame f2;
27
@@ -1020,8 +1018,10 @@
28
    spa_pod_builder_push_choice(b, &f1, SPA_CHOICE_None, 0);
29
    choice = (struct spa_pod_choice*)spa_pod_builder_frame(b, &f1);
30
 
31
-   for (i = 1, j = 0; i < SPA_N_ELEMENTS(format_info); i++) {
32
-       const struct format_info *fi = &format_infoi;
33
+   j = 0;
34
+   SPA_FOR_EACH_ELEMENT_VAR(format_info, fi) {
35
+       if (fi->format == SND_PCM_FORMAT_UNKNOWN)
36
+           continue;
37
 
38
        if (snd_pcm_format_mask_test(fmask, fi->format)) {
39
            if ((snd_pcm_access_mask_test(amask, SND_PCM_ACCESS_MMAP_NONINTERLEAVED) ||
40
@@ -1775,7 +1775,7 @@
41
    state->alsa_started = false;
42
 
43
    if (state->stream == SND_PCM_STREAM_PLAYBACK)
44
-       spa_alsa_silence(state, state->start_delay + state->threshold * 2 + state->headroom);
45
+       spa_alsa_silence(state, state->start_delay + state->threshold + state->headroom);
46
 
47
    return do_start(state);
48
 }
49
@@ -2355,7 +2355,7 @@
50
 {
51
    int res;
52
 
53
-   if (SPA_UNLIKELY(delay > target + state->max_error)) {
54
+   if (state->alsa_started && SPA_UNLIKELY(delay > target + state->max_error)) {
55
        spa_log_trace(state->log, "%p: early wakeup %lu %lu", state, delay, target);
56
        if (delay > target * 3)
57
            delay = target * 3;
58
@@ -2558,10 +2558,10 @@
59
    state->alsa_recovering = false;
60
    state->alsa_started = false;
61
 
62
+   /* start capture now, playback will start after first write */
63
    if (state->stream == SND_PCM_STREAM_PLAYBACK)
64
-       spa_alsa_silence(state, state->start_delay + state->threshold * 2 + state->headroom);
65
-
66
-   if ((err = do_start(state)) < 0)
67
+       spa_alsa_silence(state, state->start_delay + state->threshold + state->headroom);
68
+   else if ((err = do_start(state)) < 0)
69
        return err;
70
 
71
    set_timers(state);
72
pipewire-0.3.59.tar.gz/spa/plugins/alsa/alsa-seq-bridge.c -> pipewire-0.3.60.tar.gz/spa/plugins/alsa/alsa-seq-bridge.c Changed
10
 
1
@@ -566,7 +566,7 @@
2
        if (result.index > 0)
3
            return 0;
4
        param = spa_pod_builder_add_object(&b,
5
-           SPA_TYPE_OBJECT_Format, SPA_PARAM_EnumFormat,
6
+           SPA_TYPE_OBJECT_Format, SPA_PARAM_Format,
7
            SPA_FORMAT_mediaType,      SPA_POD_Id(SPA_MEDIA_TYPE_application),
8
            SPA_FORMAT_mediaSubtype,   SPA_POD_Id(SPA_MEDIA_SUBTYPE_control));
9
        break;
10
pipewire-0.3.59.tar.gz/spa/plugins/alsa/alsa-seq.c -> pipewire-0.3.60.tar.gz/spa/plugins/alsa/alsa-seq.c Changed
94
 
1
@@ -586,11 +586,11 @@
2
            continue;
3
 
4
        if (prepare_buffer(state, port) >= 0) {
5
-           port->buffer->buf->datas0.chunk->offset = 0;
6
-           port->buffer->buf->datas0.chunk->size = port->builder.state.offset,
7
-
8
            spa_pod_builder_pop(&port->builder, &port->frame);
9
 
10
+           port->buffer->buf->datas0.chunk->offset = 0;
11
+           port->buffer->buf->datas0.chunk->size = port->builder.state.offset;
12
+
13
            /* move buffer to ready queue */
14
            spa_list_remove(&port->buffer->link);
15
            SPA_FLAG_SET(port->buffer->flags, BUFFER_FLAG_OUT);
16
@@ -702,23 +702,28 @@
17
    return res;
18
 }
19
 
20
-static int update_time(struct seq_state *state, uint64_t nsec, bool follower)
21
+static void update_position(struct seq_state *state)
22
 {
23
-   snd_seq_queue_status_t *status;
24
-   const snd_seq_real_time_t* queue_time;
25
-   uint64_t queue_real;
26
-   double err, corr;
27
-   uint64_t queue_elapsed;
28
-
29
    if (state->position) {
30
        struct spa_io_clock *clock = &state->position->clock;
31
        state->rate = clock->rate;
32
+       if (state->rate.num == 0 || state->rate.denom == 0)
33
+           state->rate = SPA_FRACTION(1, 48000);
34
        state->duration = clock->duration;
35
    } else {
36
        state->rate = SPA_FRACTION(1, 48000);
37
        state->duration = 1024;
38
    }
39
    state->threshold = state->duration;
40
+}
41
+
42
+static int update_time(struct seq_state *state, uint64_t nsec, bool follower)
43
+{
44
+   snd_seq_queue_status_t *status;
45
+   const snd_seq_real_time_t* queue_time;
46
+   uint64_t queue_real;
47
+   double err, corr;
48
+   uint64_t queue_elapsed;
49
 
50
    corr = 1.0 - (state->dll.z2 + state->dll.z3);
51
 
52
@@ -776,6 +781,8 @@
53
 {
54
    int res;
55
 
56
+   update_position(state);
57
+
58
    res = process_recycle(state);
59
 
60
    if (state->following && state->position) {
61
@@ -800,11 +807,13 @@
62
 
63
    spa_log_trace(state->log, "timeout %"PRIu64, state->current_time);
64
 
65
+   update_position(state);
66
+
67
    update_time(state, state->current_time, false);
68
 
69
    res = process_read(state);
70
-   if (res > 0)
71
-       spa_node_call_ready(&state->callbacks, res);
72
+   if (res >= 0)
73
+       spa_node_call_ready(&state->callbacks, res | SPA_STATUS_NEED_DATA);
74
 
75
    set_timeout(state, state->next_time);
76
 }
77
@@ -878,15 +887,7 @@
78
    while (snd_seq_drain_output(state->event.hndl) > 0)
79
        sleep(1);
80
 
81
-   if (state->position) {
82
-       struct spa_io_clock *clock = &state->position->clock;
83
-       state->rate = clock->rate;
84
-       state->duration = clock->duration;
85
-   } else {
86
-       state->rate = SPA_FRACTION(1, 48000);
87
-       state->duration = 1024;
88
-   }
89
-   state->threshold = state->duration;
90
+   update_position(state);
91
 
92
    state->started = true;
93
 
94
pipewire-0.3.59.tar.gz/spa/plugins/alsa/alsa-udev.c -> pipewire-0.3.60.tar.gz/spa/plugins/alsa/alsa-udev.c Changed
45
 
1
@@ -465,7 +465,7 @@
2
    if (str && *str) {
3
        itemsn_items++ = SPA_DICT_ITEM_INIT(SPA_KEY_DEVICE_BUS_PATH, str);
4
    }
5
-   if ((str = udev_device_get_syspath(dev)) && *str) {
6
+   if ((str = udev_device_get_devpath(dev)) && *str) {
7
        itemsn_items++ = SPA_DICT_ITEM_INIT(SPA_KEY_DEVICE_SYSFS_PATH, str);
8
    }
9
    if ((str = udev_device_get_property_value(dev, "ID_ID")) && *str) {
10
@@ -651,9 +651,9 @@
11
 {
12
    bool deleted = false;
13
    struct impl *this = source->data;
14
-   struct {
15
+   union {
16
        struct inotify_event e;
17
-       char nameNAME_MAX+1;
18
+       char nameNAME_MAX+1+sizeof(struct inotify_event);
19
    } buf;
20
 
21
    while (true) {
22
@@ -670,17 +670,20 @@
23
        e = SPA_PTROFF(&buf, len, void);
24
 
25
        for (p = &buf; p < e;
26
-           p = SPA_PTROFF(p, sizeof(struct inotify_event) + event->len, void)) {
27
+            p = SPA_PTROFF(p, sizeof(struct inotify_event) + event->len, void)) {
28
            unsigned int id;
29
            struct device *device;
30
 
31
            event = (const struct inotify_event *) p;
32
+           spa_assert_se(SPA_PTRDIFF(e, p) >= (ptrdiff_t)sizeof(struct inotify_event) &&
33
+                         SPA_PTRDIFF(e, p) - sizeof(struct inotify_event) >= event->len &&
34
+                         "bad event from kernel");
35
 
36
            /* Device becomes accessible or not busy */
37
            if ((event->mask & (IN_ATTRIB | IN_CLOSE_WRITE))) {
38
                bool access;
39
                if (sscanf(event->name, "controlC%u", &id) != 1 &&
40
-                       sscanf(event->name, "pcmC%uD", &id) != 1)
41
+                   sscanf(event->name, "pcmC%uD", &id) != 1)
42
                    continue;
43
                if ((device = find_device(this, id)) == NULL)
44
                    continue;
45
pipewire-0.3.59.tar.gz/spa/plugins/audioconvert/audioadapter.c -> pipewire-0.3.60.tar.gz/spa/plugins/audioconvert/audioadapter.c Changed
112
 
1
@@ -556,30 +556,6 @@
2
    return 0;
3
 }
4
 
5
-static int format_audio_raw_parse_opt(const struct spa_pod *format, struct spa_audio_info_raw *info)
6
-{
7
-   struct spa_pod *position = NULL;
8
-   uint32_t media_type, media_subtype;
9
-   int res;
10
-   if ((res = spa_format_parse(format, &media_type, &media_subtype)) < 0)
11
-       return res;
12
-   if (media_type != SPA_MEDIA_TYPE_audio ||
13
-       media_subtype != SPA_MEDIA_SUBTYPE_raw)
14
-       return -ENOTSUP;
15
-
16
-   spa_zero(*info);
17
-   res = spa_pod_parse_object(format,
18
-           SPA_TYPE_OBJECT_Format, NULL,
19
-           SPA_FORMAT_AUDIO_format, SPA_POD_OPT_Id(&info->format),
20
-           SPA_FORMAT_AUDIO_channels, SPA_POD_OPT_Int(&info->channels),
21
-           SPA_FORMAT_AUDIO_position, SPA_POD_OPT_Pod(&position));
22
-   if (position == NULL ||
23
-       !spa_pod_copy_array(position, SPA_TYPE_Id, info->position, SPA_AUDIO_MAX_CHANNELS))
24
-       SPA_FLAG_SET(info->flags, SPA_AUDIO_FLAG_UNPOSITIONED);
25
-
26
-   return res;
27
-}
28
-
29
 static int impl_node_set_param(void *object, uint32_t id, uint32_t flags,
30
                   const struct spa_pod *param)
31
 {
32
@@ -627,8 +603,18 @@
33
 
34
        if (format) {
35
            struct spa_audio_info info;
36
-           if (format_audio_raw_parse_opt(format, &info.info.raw) >= 0)
37
+
38
+           spa_zero(info);
39
+           if ((res = spa_format_parse(format, &info.media_type, &info.media_subtype)) < 0)
40
+               return res;
41
+           if (info.media_type != SPA_MEDIA_TYPE_audio ||
42
+               info.media_subtype != SPA_MEDIA_SUBTYPE_raw)
43
+               return -ENOTSUP;
44
+
45
+           if (spa_format_audio_raw_parse(format, &info.info.raw) >= 0) {
46
+               info.info.raw.rate = 0;
47
                this->default_format = info;
48
+           }
49
        }
50
 
51
        switch (mode) {
52
@@ -814,21 +800,23 @@
53
 
54
    switch (SPA_NODE_COMMAND_ID(command)) {
55
    case SPA_NODE_COMMAND_Start:
56
+       spa_log_debug(this->log, "%p: starting %d", this, this->started);
57
        if (this->started)
58
            return 0;
59
        if ((res = negotiate_format(this)) < 0)
60
            return res;
61
        if ((res = negotiate_buffers(this)) < 0)
62
            return res;
63
+       this->started = true;
64
        break;
65
    case SPA_NODE_COMMAND_Suspend:
66
-       configure_format(this, 0, NULL);
67
-       SPA_FALLTHROUGH
68
+       spa_log_debug(this->log, "%p: suspending", this);
69
+       break;
70
    case SPA_NODE_COMMAND_Pause:
71
-       this->started = false;
72
-       spa_log_debug(this->log, "%p: stopped", this);
73
+       spa_log_debug(this->log, "%p: pausing", this);
74
        break;
75
    case SPA_NODE_COMMAND_Flush:
76
+       spa_log_debug(this->log, "%p: flushing", this);
77
        this->io_buffers.status = SPA_STATUS_OK;
78
        break;
79
    default:
80
@@ -852,9 +840,18 @@
81
    }
82
    switch (SPA_NODE_COMMAND_ID(command)) {
83
    case SPA_NODE_COMMAND_Start:
84
-       this->started = true;
85
        spa_log_debug(this->log, "%p: started", this);
86
        break;
87
+   case SPA_NODE_COMMAND_Suspend:
88
+       configure_format(this, 0, NULL);
89
+       SPA_FALLTHROUGH
90
+   case SPA_NODE_COMMAND_Pause:
91
+       this->started = false;
92
+       spa_log_debug(this->log, "%p: stopped", this);
93
+       break;
94
+   case SPA_NODE_COMMAND_Flush:
95
+       spa_log_debug(this->log, "%p: flushed", this);
96
+       break;
97
    }
98
    return res;
99
 }
100
@@ -1155,6 +1152,11 @@
101
 
102
    spa_log_trace_fp(this->log, "%p: ready %d", this, status);
103
 
104
+   if (!this->started) {
105
+       spa_log_warn(this->log, "%p: ready stopped node", this);
106
+       return -EIO;
107
+   }
108
+
109
    if (this->target != this->follower) {
110
        this->driver = true;
111
 
112
pipewire-0.3.59.tar.gz/spa/plugins/audioconvert/audioconvert.c -> pipewire-0.3.60.tar.gz/spa/plugins/audioconvert/audioconvert.c Changed
201
 
1
@@ -220,6 +220,7 @@
2
    unsigned int resample_peaks:1;
3
    unsigned int is_passthrough:1;
4
    unsigned int drained:1;
5
+   unsigned int rate_adjust:1;
6
 
7
    uint32_t empty_size;
8
    float *empty;
9
@@ -241,16 +242,15 @@
10
 static void emit_node_info(struct impl *this, bool full)
11
 {
12
    uint64_t old = full ? this->info.change_mask : 0;
13
-   uint32_t i;
14
 
15
    if (full)
16
        this->info.change_mask = this->info_all;
17
    if (this->info.change_mask) {
18
        if (this->info.change_mask & SPA_NODE_CHANGE_MASK_PARAMS) {
19
-           for (i = 0; i < SPA_N_ELEMENTS(this->params); i++) {
20
-               if (this->paramsi.user > 0) {
21
-                   this->paramsi.flags ^= SPA_PARAM_INFO_SERIAL;
22
-                   this->paramsi.user = 0;
23
+           SPA_FOR_EACH_ELEMENT_VAR(this->params, p) {
24
+               if (p->user > 0) {
25
+                   p->flags ^= SPA_PARAM_INFO_SERIAL;
26
+                   p->user = 0;
27
                }
28
            }
29
        }
30
@@ -262,7 +262,6 @@
31
 static void emit_port_info(struct impl *this, struct port *port, bool full)
32
 {
33
    uint64_t old = full ? port->info.change_mask : 0;
34
-   uint32_t i;
35
 
36
    if (full)
37
        port->info.change_mask = port->info_all;
38
@@ -282,10 +281,10 @@
39
        port->info.props = &SPA_DICT_INIT(items, n_items);
40
 
41
        if (port->info.change_mask & SPA_PORT_CHANGE_MASK_PARAMS) {
42
-           for (i = 0; i < SPA_N_ELEMENTS(port->params); i++) {
43
-               if (port->paramsi.user > 0) {
44
-                   port->paramsi.flags ^= SPA_PARAM_INFO_SERIAL;
45
-                   port->paramsi.user = 0;
46
+           SPA_FOR_EACH_ELEMENT_VAR(port->params, p) {
47
+               if (p->user > 0) {
48
+                   p->flags ^= SPA_PARAM_INFO_SERIAL;
49
+                   p->user = 0;
50
                }
51
            }
52
        }
53
@@ -432,7 +431,6 @@
54
    {
55
        struct props *p = &this->props;
56
        struct spa_pod_frame f2;
57
-       uint32_t i;
58
 
59
        switch (result.index) {
60
        case 0:
61
@@ -596,9 +594,9 @@
62
 
63
            spa_pod_builder_prop(&b, SPA_PROP_INFO_labels, 0);
64
            spa_pod_builder_push_struct(&b, &f1);
65
-           for (i = 0; i < SPA_N_ELEMENTS(channelmix_upmix_info); i++) {
66
-               spa_pod_builder_string(&b, channelmix_upmix_infoi.label);
67
-               spa_pod_builder_string(&b, channelmix_upmix_infoi.description);
68
+           SPA_FOR_EACH_ELEMENT_VAR(channelmix_upmix_info, i) {
69
+               spa_pod_builder_string(&b, i->label);
70
+               spa_pod_builder_string(&b, i->description);
71
            }
72
            spa_pod_builder_pop(&b, &f1);
73
            param = spa_pod_builder_pop(&b, &f0);
74
@@ -646,9 +644,9 @@
75
                0);
76
            spa_pod_builder_prop(&b, SPA_PROP_INFO_labels, 0);
77
            spa_pod_builder_push_struct(&b, &f1);
78
-           for (i = 0; i < SPA_N_ELEMENTS(dither_method_info); i++) {
79
-               spa_pod_builder_string(&b, dither_method_infoi.label);
80
-               spa_pod_builder_string(&b, dither_method_infoi.description);
81
+           SPA_FOR_EACH_ELEMENT_VAR(dither_method_info, i) {
82
+               spa_pod_builder_string(&b, i->label);
83
+               spa_pod_builder_string(&b, i->description);
84
            }
85
            spa_pod_builder_pop(&b, &f1);
86
            param = spa_pod_builder_pop(&b, &f0);
87
@@ -827,8 +825,11 @@
88
        if (spa_pod_is_string(pod)) {
89
            spa_pod_copy_string(pod, sizeof(value), value);
90
        } else if (spa_pod_is_float(pod)) {
91
-           snprintf(value, sizeof(value), "%f",
92
+           spa_dtoa(value, sizeof(value),
93
                    SPA_POD_VALUE(struct spa_pod_float, pod));
94
+       } else if (spa_pod_is_double(pod)) {
95
+           spa_dtoa(value, sizeof(value),
96
+                   SPA_POD_VALUE(struct spa_pod_double, pod));
97
        } else if (spa_pod_is_int(pod)) {
98
            snprintf(value, sizeof(value), "%d",
99
                    SPA_POD_VALUE(struct spa_pod_int, pod));
100
@@ -844,6 +845,9 @@
101
        spa_log_info(this->log, "key:'%s' val:'%s'", name, value);
102
        changed += audioconvert_set_param(this, name, value);
103
    }
104
+   if (changed) {
105
+       channelmix_init(&this->mix);
106
+   }
107
    return changed;
108
 }
109
 
110
@@ -911,6 +915,11 @@
111
            break;
112
        case SPA_PROP_rate:
113
            spa_pod_get_double(&prop->value, &p->rate);
114
+           if (!this->rate_adjust && p->rate != 1.0) {
115
+               this->rate_adjust = true;
116
+               spa_log_info(this->log, "%p: activating adaptive resampler",
117
+                       this);
118
+           }
119
            break;
120
        case SPA_PROP_params:
121
            changed += parse_prop_params(this, &prop->value);
122
@@ -925,7 +934,6 @@
123
        else if (have_channel_volume)
124
            p->have_soft_volume = false;
125
 
126
-       channelmix_init(&this->mix);
127
        set_volume(this);
128
    }
129
    return changed;
130
@@ -1064,7 +1072,10 @@
131
            if (spa_format_audio_raw_parse(format, &info.info.raw) < 0)
132
                return -EINVAL;
133
 
134
-           if (info.info.raw.channels > SPA_AUDIO_MAX_CHANNELS)
135
+           if (info.info.raw.format == 0 ||
136
+               info.info.raw.rate == 0 ||
137
+               info.info.raw.channels == 0 ||
138
+               info.info.raw.channels > SPA_AUDIO_MAX_CHANNELS)
139
                return -EINVAL;
140
 
141
            infop = &info;
142
@@ -1280,12 +1291,23 @@
143
    this->paramsIDX_Props.user++;
144
 }
145
 
146
+static char *format_position(char *str, size_t len, uint32_t channels, uint32_t *position)
147
+{
148
+   uint32_t i, idx = 0;
149
+   for (i = 0; i < channels; i++)
150
+       idx += snprintf(str + idx, len - idx, "%s%s", i == 0 ? "" : " ",
151
+               spa_debug_type_find_short_name(spa_type_audio_channel,
152
+                   positioni));
153
+   return str;
154
+}
155
+
156
 static int setup_channelmix(struct impl *this)
157
 {
158
    struct dir *in = &this->dirSPA_DIRECTION_INPUT;
159
    struct dir *out = &this->dirSPA_DIRECTION_OUTPUT;
160
    uint32_t i, src_chan, dst_chan, p;
161
    uint64_t src_mask, dst_mask;
162
+   char str1024;
163
    int res;
164
 
165
    src_chan = in->format.info.raw.channels;
166
@@ -1300,6 +1322,11 @@
167
        dst_mask |= 1ULL << (p < 64 ? p : 0);
168
    }
169
 
170
+   spa_log_info(this->log, "in  %s (%016"PRIx64")", format_position(str, sizeof(str),
171
+               src_chan, in->format.info.raw.position), src_mask);
172
+   spa_log_info(this->log, "out %s (%016"PRIx64")", format_position(str, sizeof(str),
173
+               dst_chan, out->format.info.raw.position), dst_mask);
174
+
175
    if (src_mask & 1)
176
        src_mask = default_mask(src_chan);
177
    if (dst_mask & 1)
178
@@ -1357,6 +1384,8 @@
179
    this->resample.quality = this->props.resample_quality;
180
    this->resample.cpu_flags = this->cpu_flags;
181
 
182
+   this->rate_adjust = this->props.rate != 1.0;
183
+
184
    if (this->resample_peaks)
185
        res = resample_peaks_init(&this->resample);
186
    else
187
@@ -1941,9 +1970,13 @@
188
                spa_log_error(this->log, "can't parse format %s", spa_strerror(res));
189
                return res;
190
            }
191
-           if (info.info.raw.channels > SPA_AUDIO_MAX_CHANNELS) {
192
-               spa_log_error(this->log, "too many channels %d > %d",
193
-                       info.info.raw.channels, SPA_AUDIO_MAX_CHANNELS);
194
+           if (info.info.raw.format == 0 ||
195
+               info.info.raw.rate == 0 ||
196
+               info.info.raw.channels == 0 ||
197
+               info.info.raw.channels > SPA_AUDIO_MAX_CHANNELS) {
198
+               spa_log_error(this->log, "invalid format:%d rate:%d channels:%d",
199
+                       info.info.raw.format, info.info.raw.rate,
200
+                       info.info.raw.channels);
201
pipewire-0.3.59.tar.gz/spa/plugins/audioconvert/benchmark-fmt-ops.c -> pipewire-0.3.60.tar.gz/spa/plugins/audioconvert/benchmark-fmt-ops.c Changed
28
 
1
@@ -105,21 +105,17 @@
2
 static void run_testc(const char *name, const char *impl, bool in_packed, bool out_packed, convert_func_t func,
3
        int channel_count)
4
 {
5
-   size_t i;
6
-   for (i = 0; i < SPA_N_ELEMENTS(sample_sizes); i++) {
7
+   SPA_FOR_EACH_ELEMENT_VAR(sample_sizes, s) {
8
        run_test1(name, impl, in_packed, out_packed, func, channel_count,
9
-               (sample_sizesi + (channel_count -1)) / channel_count);
10
+               (*s + (channel_count -1)) / channel_count);
11
    }
12
 }
13
 
14
 static void run_test(const char *name, const char *impl, bool in_packed, bool out_packed, convert_func_t func)
15
 {
16
-   size_t i, j;
17
-
18
-   for (i = 0; i < SPA_N_ELEMENTS(sample_sizes); i++) {
19
-       for (j = 0; j < SPA_N_ELEMENTS(channel_counts); j++) {
20
-           run_test1(name, impl, in_packed, out_packed, func, channel_countsj,
21
-               (sample_sizesi + (channel_countsj -1)) / channel_countsj);
22
+   SPA_FOR_EACH_ELEMENT_VAR(sample_sizes, s) {
23
+       SPA_FOR_EACH_ELEMENT_VAR(channel_counts, c) {
24
+           run_test1(name, impl, in_packed, out_packed, func, *c, (*s + (*c -1)) / *c);
25
        }
26
    }
27
 }
28
pipewire-0.3.59.tar.gz/spa/plugins/audioconvert/channelmix-ops-sse.c -> pipewire-0.3.60.tar.gz/spa/plugins/audioconvert/channelmix-ops-sse.c Changed
200
 
1
@@ -101,6 +101,64 @@
2
    }
3
 }
4
 
5
+static inline void avg_sse(float *d, const float *s0, const float *s1, uint32_t n_samples)
6
+{
7
+   uint32_t n, unrolled;
8
+   __m128 half = _mm_set1_ps(0.5f);
9
+
10
+   if (SPA_IS_ALIGNED(d, 16) &&
11
+       SPA_IS_ALIGNED(s0, 16) &&
12
+       SPA_IS_ALIGNED(s1, 16))
13
+       unrolled = n_samples & ~7;
14
+   else
15
+       unrolled = 0;
16
+
17
+   for (n = 0; n < unrolled; n += 8) {
18
+       _mm_store_ps(&dn + 0,
19
+               _mm_mul_ps(
20
+                   _mm_add_ps(
21
+                       _mm_load_ps(&s0n + 0),
22
+                       _mm_load_ps(&s1n + 0)),
23
+                   half));
24
+       _mm_store_ps(&dn + 4,
25
+               _mm_mul_ps(
26
+                   _mm_add_ps(
27
+                       _mm_load_ps(&s0n + 4),
28
+                       _mm_load_ps(&s1n + 4)),
29
+                   half));
30
+   }
31
+
32
+   for (; n < n_samples; n++)
33
+       _mm_store_ss(&dn,
34
+               _mm_mul_ss(
35
+                   _mm_add_ss(
36
+                       _mm_load_ss(&s0n),
37
+                       _mm_load_ss(&s1n)),
38
+                   half));
39
+}
40
+
41
+static inline void sub_sse(float *d, const float *s0, const float *s1, uint32_t n_samples)
42
+{
43
+   uint32_t n, unrolled;
44
+
45
+   if (SPA_IS_ALIGNED(d, 16) &&
46
+       SPA_IS_ALIGNED(s0, 16) &&
47
+       SPA_IS_ALIGNED(s1, 16))
48
+       unrolled = n_samples & ~7;
49
+   else
50
+       unrolled = 0;
51
+
52
+   for (n = 0; n < unrolled; n += 8) {
53
+       _mm_store_ps(&dn + 0,
54
+           _mm_sub_ps(_mm_load_ps(&s0n + 0), _mm_load_ps(&s1n + 0)));
55
+       _mm_store_ps(&dn + 4,
56
+           _mm_sub_ps(_mm_load_ps(&s0n + 4), _mm_load_ps(&s1n + 4)));
57
+   }
58
+   for (; n < n_samples; n++)
59
+       _mm_store_ss(&dn,
60
+           _mm_sub_ss(_mm_load_ss(&s0n), _mm_load_ss(&s1n)));
61
+}
62
+
63
 void channelmix_copy_sse(struct channelmix *mix, void * SPA_RESTRICT dst,
64
        const void * SPA_RESTRICT src, uint32_t n_samples)
65
 {
66
@@ -145,6 +203,133 @@
67
    }
68
 }
69
 
70
+void
71
+channelmix_f32_2_3p1_sse(struct channelmix *mix, void * SPA_RESTRICT dst,
72
+          const void * SPA_RESTRICT src, uint32_t n_samples)
73
+{
74
+   uint32_t i, n, unrolled, n_dst = mix->dst_chan;
75
+   float **d = (float **)dst;
76
+   const float **s = (const float **)src;
77
+   const float v0 = mix->matrix00;
78
+   const float v1 = mix->matrix11;
79
+   const float v2 = (mix->matrix20 + mix->matrix21) * 0.5f;
80
+   const float v3 = (mix->matrix30 + mix->matrix31) * 0.5f;
81
+
82
+   if (SPA_FLAG_IS_SET(mix->flags, CHANNELMIX_FLAG_ZERO)) {
83
+       for (i = 0; i < n_dst; i++)
84
+           clear_sse(di, n_samples);
85
+   }
86
+   else {
87
+       if (mix->widen == 0.0f) {
88
+           vol_sse(d0, s0, v0, n_samples);
89
+           vol_sse(d1, s1, v1, n_samples);
90
+           avg_sse(d2, s0, s1, n_samples);
91
+       } else {
92
+           const __m128 mv0 = _mm_set1_ps(mix->matrix00);
93
+           const __m128 mv1 = _mm_set1_ps(mix->matrix11);
94
+           const __m128 mw = _mm_set1_ps(mix->widen);
95
+           const __m128 mh = _mm_set1_ps(0.5f);
96
+           __m128 t01, t11, w1, c1;
97
+
98
+           if (SPA_IS_ALIGNED(s0, 16) &&
99
+               SPA_IS_ALIGNED(s1, 16) &&
100
+               SPA_IS_ALIGNED(d0, 16) &&
101
+               SPA_IS_ALIGNED(d1, 16) &&
102
+               SPA_IS_ALIGNED(d2, 16))
103
+               unrolled = n_samples & ~3;
104
+           else
105
+               unrolled = 0;
106
+
107
+           for(n = 0; n < unrolled; n += 4) {
108
+               t00 = _mm_load_ps(&s0n);
109
+               t10 = _mm_load_ps(&s1n);
110
+               c0 = _mm_add_ps(t00, t10);
111
+               w0 = _mm_mul_ps(c0, mw);
112
+               _mm_store_ps(&d0n, _mm_mul_ps(_mm_sub_ps(t00, w0), mv0));
113
+               _mm_store_ps(&d1n, _mm_mul_ps(_mm_sub_ps(t10, w0), mv1));
114
+               _mm_store_ps(&d2n, _mm_mul_ps(c0, mh));
115
+           }
116
+           for (; n < n_samples; n++) {
117
+               t00 = _mm_load_ss(&s0n);
118
+               t10 = _mm_load_ss(&s1n);
119
+               c0 = _mm_add_ss(t00, t10);
120
+               w0 = _mm_mul_ss(c0, mw);
121
+               _mm_store_ss(&d0n, _mm_mul_ss(_mm_sub_ss(t00, w0), mv0));
122
+               _mm_store_ss(&d1n, _mm_mul_ss(_mm_sub_ss(t10, w0), mv1));
123
+               _mm_store_ss(&d2n, _mm_mul_ss(c0, mh));
124
+           }
125
+       }
126
+       lr4_process(&mix->lr43, d3, d2, v3, n_samples);
127
+       lr4_process(&mix->lr42, d2, d2, v2, n_samples);
128
+   }
129
+}
130
+
131
+void
132
+channelmix_f32_2_5p1_sse(struct channelmix *mix, void * SPA_RESTRICT dst,
133
+          const void * SPA_RESTRICT src, uint32_t n_samples)
134
+{
135
+   uint32_t i, n_dst = mix->dst_chan;
136
+   float **d = (float **)dst;
137
+   const float **s = (const float **)src;
138
+   const float v4 = mix->matrix40;
139
+   const float v5 = mix->matrix51;
140
+
141
+   if (SPA_FLAG_IS_SET(mix->flags, CHANNELMIX_FLAG_ZERO)) {
142
+       for (i = 0; i < n_dst; i++)
143
+           clear_sse(di, n_samples);
144
+   }
145
+   else {
146
+       channelmix_f32_2_3p1_sse(mix, dst, src, n_samples);
147
+
148
+       if (mix->upmix != CHANNELMIX_UPMIX_PSD) {
149
+           vol_sse(d4, s0, v4, n_samples);
150
+           vol_sse(d5, s1, v5, n_samples);
151
+       } else {
152
+           sub_sse(d4, s0, s1, n_samples);
153
+
154
+           delay_convolve_run(mix->buffer1, &mix->pos1, BUFFER_SIZE, mix->delay,
155
+                   mix->taps, mix->n_taps, d5, d4, -v5, n_samples);
156
+           delay_convolve_run(mix->buffer0, &mix->pos0, BUFFER_SIZE, mix->delay,
157
+                   mix->taps, mix->n_taps, d4, d4, v4, n_samples);
158
+       }
159
+   }
160
+}
161
+
162
+void
163
+channelmix_f32_2_7p1_sse(struct channelmix *mix, void * SPA_RESTRICT dst,
164
+          const void * SPA_RESTRICT src, uint32_t n_samples)
165
+{
166
+   uint32_t i, n_dst = mix->dst_chan;
167
+   float **d = (float **)dst;
168
+   const float **s = (const float **)src;
169
+   const float v4 = mix->matrix40;
170
+   const float v5 = mix->matrix51;
171
+   const float v6 = mix->matrix60;
172
+   const float v7 = mix->matrix71;
173
+
174
+   if (SPA_FLAG_IS_SET(mix->flags, CHANNELMIX_FLAG_ZERO)) {
175
+       for (i = 0; i < n_dst; i++)
176
+           clear_sse(di, n_samples);
177
+   }
178
+   else {
179
+       channelmix_f32_2_3p1_sse(mix, dst, src, n_samples);
180
+
181
+       vol_sse(d4, s0, v4, n_samples);
182
+       vol_sse(d5, s1, v5, n_samples);
183
+
184
+       if (mix->upmix != CHANNELMIX_UPMIX_PSD) {
185
+           vol_sse(d6, s0, v6, n_samples);
186
+           vol_sse(d7, s1, v7, n_samples);
187
+       } else {
188
+           sub_sse(d6, s0, s1, n_samples);
189
+
190
+           delay_convolve_run(mix->buffer1, &mix->pos1, BUFFER_SIZE, mix->delay,
191
+                   mix->taps, mix->n_taps, d7, d6, -v7, n_samples);
192
+           delay_convolve_run(mix->buffer0, &mix->pos0, BUFFER_SIZE, mix->delay,
193
+                   mix->taps, mix->n_taps, d6, d6, v6, n_samples);
194
+       }
195
+   }
196
+}
197
 /* FL+FR+FC+LFE -> FL+FR */
198
 void
199
 channelmix_f32_3p1_2_sse(struct channelmix *mix, void * SPA_RESTRICT dst,
200
pipewire-0.3.59.tar.gz/spa/plugins/audioconvert/channelmix-ops.c -> pipewire-0.3.60.tar.gz/spa/plugins/audioconvert/channelmix-ops.c Changed
142
 
1
@@ -30,6 +30,7 @@
2
 #include <spa/support/cpu.h>
3
 #include <spa/support/log.h>
4
 #include <spa/utils/defs.h>
5
+#include <spa/debug/types.h>
6
 
7
 #include "channelmix-ops.h"
8
 #include "hilbert.h"
9
@@ -69,8 +70,17 @@
10
    MAKE(4, MASK_QUAD, 1, MASK_MONO, channelmix_f32_4_1_c),
11
    MAKE(4, MASK_3_1, 1, MASK_MONO, channelmix_f32_4_1_c),
12
    MAKE(2, MASK_STEREO, 4, MASK_QUAD, channelmix_f32_2_4_c),
13
+#if defined (HAVE_SSE)
14
+   MAKE(2, MASK_STEREO, 4, MASK_3_1, channelmix_f32_2_3p1_sse, SPA_CPU_FLAG_SSE),
15
+#endif
16
    MAKE(2, MASK_STEREO, 4, MASK_3_1, channelmix_f32_2_3p1_c),
17
+#if defined (HAVE_SSE)
18
+   MAKE(2, MASK_STEREO, 6, MASK_5_1, channelmix_f32_2_5p1_sse, SPA_CPU_FLAG_SSE),
19
+#endif
20
    MAKE(2, MASK_STEREO, 6, MASK_5_1, channelmix_f32_2_5p1_c),
21
+#if defined (HAVE_SSE)
22
+   MAKE(2, MASK_STEREO, 8, MASK_7_1, channelmix_f32_2_7p1_sse, SPA_CPU_FLAG_SSE),
23
+#endif
24
    MAKE(2, MASK_STEREO, 8, MASK_7_1, channelmix_f32_2_7p1_c),
25
 #if defined (HAVE_SSE)
26
    MAKE(4, MASK_3_1, 2, MASK_STEREO, channelmix_f32_3p1_2_sse, SPA_CPU_FLAG_SSE),
27
@@ -95,7 +105,7 @@
28
    MAKE(8, MASK_7_1, 4, MASK_3_1, channelmix_f32_7p1_3p1_c),
29
 
30
 #if defined (HAVE_SSE)
31
-   MAKE(ANY, 0, ANY, 0, channelmix_f32_n_m_sse),
32
+   MAKE(ANY, 0, ANY, 0, channelmix_f32_n_m_sse, SPA_CPU_FLAG_SSE),
33
 #endif
34
    MAKE(ANY, 0, ANY, 0, channelmix_f32_n_m_c),
35
 };
36
@@ -108,19 +118,18 @@
37
 static const struct channelmix_info *find_channelmix_info(uint32_t src_chan, uint64_t src_mask,
38
        uint32_t dst_chan, uint64_t dst_mask, uint32_t cpu_flags)
39
 {
40
-   size_t i;
41
-   for (i = 0; i < SPA_N_ELEMENTS(channelmix_table); i++) {
42
-       if (!MATCH_CPU_FLAGS(channelmix_tablei.cpu_flags, cpu_flags))
43
+   SPA_FOR_EACH_ELEMENT_VAR(channelmix_table, info) {
44
+       if (!MATCH_CPU_FLAGS(info->cpu_flags, cpu_flags))
45
            continue;
46
 
47
        if (src_chan == dst_chan && src_mask == dst_mask)
48
-           return &channelmix_tablei;
49
+           return info;
50
 
51
-       if (MATCH_CHAN(channelmix_tablei.src_chan, src_chan) &&
52
-           MATCH_CHAN(channelmix_tablei.dst_chan, dst_chan) &&
53
-           MATCH_MASK(channelmix_tablei.src_mask, src_mask) &&
54
-           MATCH_MASK(channelmix_tablei.dst_mask, dst_mask))
55
-           return &channelmix_tablei;
56
+       if (MATCH_CHAN(info->src_chan, src_chan) &&
57
+           MATCH_CHAN(info->dst_chan, dst_chan) &&
58
+           MATCH_MASK(info->src_mask, src_mask) &&
59
+           MATCH_MASK(info->dst_mask, dst_mask))
60
+           return info;
61
    }
62
    return NULL;
63
 }
64
@@ -302,6 +311,7 @@
65
                _MATRIX(SL,RL) += 1.0f;
66
                _MATRIX(SR,RR) += 1.0f;
67
            }
68
+           keep &= ~SIDE;
69
        } else if (dst_mask & STEREO) {
70
            spa_log_debug(mix->log, "assign RL+RR to FL+FR (%f)", slev);
71
            if (matrix_encoding == MATRIX_DOLBY) {
72
@@ -339,6 +349,7 @@
73
                _MATRIX(RL,SL) += 1.0f;
74
                _MATRIX(RR,SR) += 1.0f;
75
            }
76
+           keep &= ~REAR;
77
        } else if (dst_mask & _MASK(RC)) {
78
            spa_log_debug(mix->log, "assign SL+SR to RC (%f)", SQRT1_2);
79
            _MATRIX(RC,SL)+= SQRT1_2;
80
@@ -474,10 +485,33 @@
81
            spa_log_debug(mix->log, "won't produce SIDE");
82
        }
83
    }
84
+   if (unassigned & _MASK(RC)) {
85
+       if ((src_mask & REAR) == REAR) {
86
+           spa_log_debug(mix->log, "produce RC from REAR (%f)", 0.5f);
87
+           _MATRIX(RC,RL) += 0.5f;
88
+           _MATRIX(RC,RR) += 0.5f;
89
+       } else if ((src_mask & SIDE) == SIDE) {
90
+           spa_log_debug(mix->log, "produce RC from SIDE (%f)", 0.5f);
91
+           _MATRIX(RC,SL) += 0.5f;
92
+           _MATRIX(RC,SR) += 0.5f;
93
+       } else if ((src_mask & STEREO) == STEREO) {
94
+           spa_log_debug(mix->log, "produce RC from STEREO (%f)", 0.5f);
95
+           _MATRIX(RC,FL) += 0.5f;
96
+           _MATRIX(RC,FR) += 0.5f;
97
+       } else if ((src_mask & FRONT) == FRONT &&
98
+           mix->upmix == CHANNELMIX_UPMIX_SIMPLE) {
99
+           spa_log_debug(mix->log, "produce RC from FC (%f)", slev);
100
+           _MATRIX(RC,FC) += slev;
101
+       } else {
102
+           spa_log_debug(mix->log, "won't produce RC");
103
+       }
104
+   }
105
 
106
 done:
107
    for (jc = 0, ic = 0, i = 0; i < SPA_AUDIO_MAX_CHANNELS; i++) {
108
        float sum = 0.0f;
109
+       char str1024, str21024;
110
+       int idx = 0, idx2 = 0;
111
        if ((dst_mask & (1UL << i)) == 0)
112
            continue;
113
        for (jc = 0, j = 0; j < SPA_AUDIO_MAX_CHANNELS; j++) {
114
@@ -485,9 +519,27 @@
115
                continue;
116
            if (ic >= dst_chan || jc >= src_chan)
117
                continue;
118
+
119
+           if (i == 0)
120
+               idx2 += snprintf(str2 + idx2, sizeof(str2) - idx2, "%-4.4s  ",
121
+                       spa_debug_type_find_short_name(spa_type_audio_channel, j + 3));
122
+
123
            mix->matrix_origicjc++ = matrixij;
124
            sum += fabs(matrixij);
125
+
126
+           if (matrixij == 0.0f)
127
+               idx += snprintf(str + idx, sizeof(str) - idx, "      ");
128
+           else
129
+               idx += snprintf(str + idx, sizeof(str) - idx, "%1.3f ", matrixij);
130
        }
131
+       if (dst_mask != 0 && src_mask != 0 && sum > 0.0f) {
132
+           if (i == 0)
133
+               spa_log_info(mix->log, "     %s", str2);
134
+           spa_log_info(mix->log, "%-4.4s %s   %f",
135
+                   spa_debug_type_find_short_name(spa_type_audio_channel, i + 3),
136
+                   str, sum);
137
+       }
138
+
139
        maxsum = SPA_MAX(maxsum, sum);
140
        if (i == _CH(LFE) && mix->lfe_cutoff > 0.0f && filter_lfe) {
141
            spa_log_info(mix->log, "channel %d is LFE cutoff:%f", ic, mix->lfe_cutoff);
142
pipewire-0.3.59.tar.gz/spa/plugins/audioconvert/channelmix-ops.h -> pipewire-0.3.60.tar.gz/spa/plugins/audioconvert/channelmix-ops.h Changed
25
 
1
@@ -109,10 +109,9 @@
2
 
3
 static inline uint32_t channelmix_upmix_from_label(const char *label)
4
 {
5
-   uint32_t i;
6
-   for (i = 0; i < SPA_N_ELEMENTS(channelmix_upmix_info); i++) {
7
-       if (spa_streq(channelmix_upmix_infoi.label, label))
8
-           return channelmix_upmix_infoi.upmix;
9
+   SPA_FOR_EACH_ELEMENT_VAR(channelmix_upmix_info, i) {
10
+       if (spa_streq(i->label, label))
11
+           return i->upmix;
12
    }
13
    return CHANNELMIX_UPMIX_NONE;
14
 }
15
@@ -148,6 +147,9 @@
16
 #if defined (HAVE_SSE)
17
 DEFINE_FUNCTION(copy, sse);
18
 DEFINE_FUNCTION(f32_n_m, sse);
19
+DEFINE_FUNCTION(f32_2_3p1, sse);
20
+DEFINE_FUNCTION(f32_2_5p1, sse);
21
+DEFINE_FUNCTION(f32_2_7p1, sse);
22
 DEFINE_FUNCTION(f32_3p1_2, sse);
23
 DEFINE_FUNCTION(f32_5p1_2, sse);
24
 DEFINE_FUNCTION(f32_5p1_3p1, sse);
25
pipewire-0.3.59.tar.gz/spa/plugins/audioconvert/fmt-ops.c -> pipewire-0.3.60.tar.gz/spa/plugins/audioconvert/fmt-ops.c Changed
59
 
1
@@ -359,14 +359,13 @@
2
 static const struct conv_info *find_conv_info(uint32_t src_fmt, uint32_t dst_fmt,
3
        uint32_t n_channels, uint32_t cpu_flags, uint32_t conv_flags)
4
 {
5
-   size_t i;
6
-   for (i = 0; i < SPA_N_ELEMENTS(conv_table); i++) {
7
-       if (conv_tablei.src_fmt == src_fmt &&
8
-           conv_tablei.dst_fmt == dst_fmt &&
9
-           MATCH_CHAN(conv_tablei.n_channels, n_channels) &&
10
-           MATCH_CPU_FLAGS(conv_tablei.cpu_flags, cpu_flags) &&
11
-           MATCH_DITHER(conv_tablei.conv_flags, conv_flags))
12
-           return &conv_tablei;
13
+   SPA_FOR_EACH_ELEMENT_VAR(conv_table, c) {
14
+       if (c->src_fmt == src_fmt &&
15
+           c->dst_fmt == dst_fmt &&
16
+           MATCH_CHAN(c->n_channels, n_channels) &&
17
+           MATCH_CPU_FLAGS(c->cpu_flags, cpu_flags) &&
18
+           MATCH_DITHER(c->conv_flags, conv_flags))
19
+           return c;
20
    }
21
    return NULL;
22
 }
23
@@ -403,11 +402,10 @@
24
 static const struct noise_info *find_noise_info(uint32_t method,
25
        uint32_t cpu_flags)
26
 {
27
-   size_t i;
28
-   for (i = 0; i < SPA_N_ELEMENTS(noise_table); i++) {
29
-       if (noise_tablei.method == method &&
30
-           MATCH_CPU_FLAGS(noise_tablei.cpu_flags, cpu_flags))
31
-           return &noise_tablei;
32
+   SPA_FOR_EACH_ELEMENT_VAR(noise_table, t) {
33
+       if (t->method == method &&
34
+           MATCH_CPU_FLAGS(t->cpu_flags, cpu_flags))
35
+           return t;
36
    }
37
    return NULL;
38
 }
39
@@ -471,17 +469,14 @@
40
 
41
 static const struct dither_info *find_dither_info(uint32_t method, uint32_t rate)
42
 {
43
-   size_t i;
44
-
45
-   for (i = 0; i < SPA_N_ELEMENTS(dither_info); i++) {
46
-       const struct dither_info *di = &dither_infoi;
47
+   SPA_FOR_EACH_ELEMENT_VAR(dither_info, di) {
48
        if (di->method != method)
49
            continue;
50
        /* don't use shaped for too low rates, it moves the noise to
51
         * audible ranges */
52
        if (di->ns != NULL && rate < di->rate * 3 / 4)
53
            return find_dither_info(DITHER_METHOD_TRIANGULAR_HF, rate);
54
-       return &dither_infoi;
55
+       return di;
56
    }
57
    return NULL;
58
 }
59
pipewire-0.3.59.tar.gz/spa/plugins/audioconvert/fmt-ops.h -> pipewire-0.3.60.tar.gz/spa/plugins/audioconvert/fmt-ops.h Changed
15
 
1
@@ -271,10 +271,9 @@
2
 
3
 static inline uint32_t dither_method_from_label(const char *label)
4
 {
5
-   uint32_t i;
6
-   for (i = 0; i < SPA_N_ELEMENTS(dither_method_info); i++) {
7
-       if (spa_streq(dither_method_infoi.label, label))
8
-           return dither_method_infoi.method;
9
+   SPA_FOR_EACH_ELEMENT_VAR(dither_method_info, i) {
10
+       if (spa_streq(i->label, label))
11
+           return i->method;
12
    }
13
    return DITHER_METHOD_NONE;
14
 }
15
pipewire-0.3.59.tar.gz/spa/plugins/audioconvert/peaks-ops.c -> pipewire-0.3.60.tar.gz/spa/plugins/audioconvert/peaks-ops.c Changed
16
 
1
@@ -59,11 +59,9 @@
2
 
3
 static const struct peaks_info *find_peaks_info(uint32_t cpu_flags)
4
 {
5
-   size_t i;
6
-   for (i = 0; i < SPA_N_ELEMENTS(peaks_table); i++) {
7
-       if (!MATCH_CPU_FLAGS(peaks_tablei.cpu_flags, cpu_flags))
8
-           continue;
9
-       return &peaks_tablei;
10
+   SPA_FOR_EACH_ELEMENT_VAR(peaks_table, t) {
11
+       if (MATCH_CPU_FLAGS(t->cpu_flags, cpu_flags))
12
+           return t;
13
    }
14
    return NULL;
15
 }
16
pipewire-0.3.59.tar.gz/spa/plugins/audioconvert/resample-native.c -> pipewire-0.3.60.tar.gz/spa/plugins/audioconvert/resample-native.c Changed
34
 
1
@@ -66,6 +66,7 @@
2
        (alpha / 2.0) * cos(2.0 * x);
3
    return r;
4
 }
5
+
6
 static inline double window_cosh(double x, double n_taps)
7
 {
8
    double r;
9
@@ -80,7 +81,7 @@
10
    return r;
11
 }
12
 
13
-#define window window_cosh
14
+#define window (1 ? window_cosh : window_blackman)
15
 
16
 static int build_filter(float *taps, uint32_t stride, uint32_t n_taps, uint32_t n_phases, double cutoff)
17
 {
18
@@ -125,11 +126,10 @@
19
 #define MATCH_CPU_FLAGS(a,b)   ((a) == 0 || ((a) & (b)) == a)
20
 static const struct resample_info *find_resample_info(uint32_t format, uint32_t cpu_flags)
21
 {
22
-   size_t i;
23
-   for (i = 0; i < SPA_N_ELEMENTS(resample_table); i++) {
24
-       if (resample_tablei.format == format &&
25
-           MATCH_CPU_FLAGS(resample_tablei.cpu_flags, cpu_flags))
26
-           return &resample_tablei;
27
+   SPA_FOR_EACH_ELEMENT_VAR(resample_table, t) {
28
+       if (t->format == format &&
29
+           MATCH_CPU_FLAGS(t->cpu_flags, cpu_flags))
30
+           return t;
31
    }
32
    return NULL;
33
 }
34
pipewire-0.3.59.tar.gz/spa/plugins/audioconvert/test-audioconvert.c -> pipewire-0.3.60.tar.gz/spa/plugins/audioconvert/test-audioconvert.c Changed
201
 
1
@@ -681,9 +681,9 @@
2
 
3
            res = memcmp(b->datasj.data, out_data->datak, out_data->size);
4
            if (res != 0) {
5
-               fprintf(stderr, "error plane %d\n", j);
6
+               fprintf(stderr, "error port %d plane %d\n", i, j);
7
                spa_debug_mem(0, b->datasj.data, out_data->size);
8
-               spa_debug_mem(0, out_data->dataj, out_data->size);
9
+               spa_debug_mem(0, out_data->datak, out_data->size);
10
            }
11
            spa_assert_se(res == 0);
12
 
13
@@ -702,7 +702,9 @@
14
 static const float data_f32p_3 = { 0.3f, 0.3f, 0.3f, 0.3f };
15
 static const float data_f32p_4 = { 0.4f, 0.4f, 0.4f, 0.4f };
16
 static const float data_f32p_5 = { 0.5f, 0.5f, 0.5f, 0.5f };
17
+static const float data_f32p_5_6p1 = { 0.953553438f, 0.953553438f, 0.953553438f, 0.953553438f };
18
 static const float data_f32p_6 = { 0.6f, 0.6f, 0.6f, 0.6f };
19
+static const float data_f32p_6_6p1 = { 1.053553343f, 1.053553343f, 1.053553343f, 1.053553343f };
20
 static const float data_f32p_7 = { 0.7f, 0.7f, 0.7f, 0.7f };
21
 static const float data_f32p_8 = { 0.8f, 0.8f, 0.8f, 0.8f };
22
 
23
@@ -710,6 +712,14 @@
24
                      0.1f, 0.2f, 0.3f, 0.4f, 0.5f, 0.6f,
25
                      0.1f, 0.2f, 0.3f, 0.4f, 0.5f, 0.6f,
26
                      0.1f, 0.2f, 0.3f, 0.4f, 0.5f, 0.6f };
27
+static const float data_f32_6p1 = { 0.1f, 0.2f, 0.3f, 0.4f, 0.5f, 0.6f, 0.7f,
28
+                     0.1f, 0.2f, 0.3f, 0.4f, 0.5f, 0.6f, 0.7f,
29
+                     0.1f, 0.2f, 0.3f, 0.4f, 0.5f, 0.6f, 0.7f,
30
+                     0.1f, 0.2f, 0.3f, 0.4f, 0.5f, 0.6f, 0.7f };
31
+static const float data_f32_6p1_from_5p1 = { 0.1f, 0.2f, 0.3f, 0.4f, 0.55f, 0.5f, 0.6f,
32
+                     0.1f, 0.2f, 0.3f, 0.4f, 0.55f, 0.5f, 0.6f,
33
+                     0.1f, 0.2f, 0.3f, 0.4f, 0.55f, 0.5f, 0.6f,
34
+                     0.1f, 0.2f, 0.3f, 0.4f, 0.55f, 0.5f, 0.6f };
35
 
36
 static const float data_f32_7p1_remapped = { 0.1f, 0.2f, 0.5f, 0.6f, 0.7f, 0.8f, 0.3f, 0.4f,
37
                      0.1f, 0.2f, 0.5f, 0.6f, 0.7f, 0.8f, 0.3f, 0.4f,
38
@@ -740,6 +750,27 @@
39
    .size = sizeof(float) * 4
40
 };
41
 
42
+struct data dsp_5p1_from_6p1 = {
43
+   .mode = SPA_PARAM_PORT_CONFIG_MODE_dsp,
44
+   .info = SPA_AUDIO_INFO_RAW_INIT(
45
+       .format = SPA_AUDIO_FORMAT_F32,
46
+       .rate = 48000,
47
+       .channels = 6,
48
+       .position = {
49
+           SPA_AUDIO_CHANNEL_FL,
50
+           SPA_AUDIO_CHANNEL_FR,
51
+           SPA_AUDIO_CHANNEL_FC,
52
+           SPA_AUDIO_CHANNEL_LFE,
53
+           SPA_AUDIO_CHANNEL_RL,
54
+           SPA_AUDIO_CHANNEL_RR,
55
+       }),
56
+   .ports = 6,
57
+   .planes = 1,
58
+   .data = { data_f32p_1, data_f32p_2, data_f32p_3, data_f32p_4, data_f32p_5_6p1, data_f32p_6_6p1, },
59
+   .size = sizeof(float) * 4
60
+};
61
+
62
+
63
 struct data dsp_5p1_remapped = {
64
    .mode = SPA_PARAM_PORT_CONFIG_MODE_dsp,
65
    .info = SPA_AUDIO_INFO_RAW_INIT(
66
@@ -760,6 +791,68 @@
67
    .size = sizeof(float) * 4
68
 };
69
 
70
+struct data dsp_5p1_remapped_from_6p1 = {
71
+   .mode = SPA_PARAM_PORT_CONFIG_MODE_dsp,
72
+   .info = SPA_AUDIO_INFO_RAW_INIT(
73
+       .format = SPA_AUDIO_FORMAT_F32,
74
+       .rate = 48000,
75
+       .channels = 6,
76
+       .position = {
77
+           SPA_AUDIO_CHANNEL_FL,
78
+           SPA_AUDIO_CHANNEL_FR,
79
+           SPA_AUDIO_CHANNEL_RL,
80
+           SPA_AUDIO_CHANNEL_RR,
81
+           SPA_AUDIO_CHANNEL_FC,
82
+           SPA_AUDIO_CHANNEL_LFE,
83
+       }),
84
+   .ports = 6,
85
+   .planes = 1,
86
+   .data = { data_f32p_1, data_f32p_2, data_f32p_5_6p1, data_f32p_6_6p1, data_f32p_3, data_f32p_4, },
87
+   .size = sizeof(float) * 4
88
+};
89
+
90
+struct data dsp_6p1 = {
91
+   .mode = SPA_PARAM_PORT_CONFIG_MODE_dsp,
92
+   .info = SPA_AUDIO_INFO_RAW_INIT(
93
+       .format = SPA_AUDIO_FORMAT_F32,
94
+       .rate = 48000,
95
+       .channels = 7,
96
+       .position = {
97
+           SPA_AUDIO_CHANNEL_FL,
98
+           SPA_AUDIO_CHANNEL_FR,
99
+           SPA_AUDIO_CHANNEL_FC,
100
+           SPA_AUDIO_CHANNEL_LFE,
101
+           SPA_AUDIO_CHANNEL_RC,
102
+           SPA_AUDIO_CHANNEL_RL,
103
+           SPA_AUDIO_CHANNEL_RR,
104
+       }),
105
+   .ports = 7,
106
+   .planes = 1,
107
+   .data = { data_f32p_1, data_f32p_2, data_f32p_3, data_f32p_4, data_f32p_5, data_f32p_6, data_f32p_7 },
108
+   .size = sizeof(float) * 4
109
+};
110
+
111
+struct data dsp_6p1_side = {
112
+   .mode = SPA_PARAM_PORT_CONFIG_MODE_dsp,
113
+   .info = SPA_AUDIO_INFO_RAW_INIT(
114
+       .format = SPA_AUDIO_FORMAT_F32,
115
+       .rate = 48000,
116
+       .channels = 7,
117
+       .position = {
118
+           SPA_AUDIO_CHANNEL_FL,
119
+           SPA_AUDIO_CHANNEL_FR,
120
+           SPA_AUDIO_CHANNEL_FC,
121
+           SPA_AUDIO_CHANNEL_LFE,
122
+           SPA_AUDIO_CHANNEL_RC,
123
+           SPA_AUDIO_CHANNEL_SL,
124
+           SPA_AUDIO_CHANNEL_SR,
125
+       }),
126
+   .ports = 7,
127
+   .planes = 1,
128
+   .data = { data_f32p_1, data_f32p_2, data_f32p_3, data_f32p_4, data_f32p_5, data_f32p_6, data_f32p_7 },
129
+   .size = sizeof(float) * 4
130
+};
131
+
132
 struct data dsp_7p1_remapped = {
133
    .mode = SPA_PARAM_PORT_CONFIG_MODE_dsp,
134
    .info = SPA_AUDIO_INFO_RAW_INIT(
135
@@ -862,6 +955,90 @@
136
    .size = sizeof(float) * 4
137
 };
138
 
139
+struct data conv_f32_48000_6p1 = {
140
+   .mode = SPA_PARAM_PORT_CONFIG_MODE_convert,
141
+   .info = SPA_AUDIO_INFO_RAW_INIT(
142
+       .format = SPA_AUDIO_FORMAT_F32,
143
+       .rate = 48000,
144
+       .channels = 7,
145
+       .position = {
146
+           SPA_AUDIO_CHANNEL_FL,
147
+           SPA_AUDIO_CHANNEL_FR,
148
+           SPA_AUDIO_CHANNEL_FC,
149
+           SPA_AUDIO_CHANNEL_LFE,
150
+           SPA_AUDIO_CHANNEL_RC,
151
+           SPA_AUDIO_CHANNEL_RL,
152
+           SPA_AUDIO_CHANNEL_RR,
153
+       }),
154
+   .ports = 1,
155
+   .planes = 1,
156
+   .data = { data_f32_6p1 },
157
+   .size = sizeof(data_f32_6p1)
158
+};
159
+
160
+struct data conv_f32_48000_6p1_from_5p1 = {
161
+   .mode = SPA_PARAM_PORT_CONFIG_MODE_convert,
162
+   .info = SPA_AUDIO_INFO_RAW_INIT(
163
+       .format = SPA_AUDIO_FORMAT_F32,
164
+       .rate = 48000,
165
+       .channels = 7,
166
+       .position = {
167
+           SPA_AUDIO_CHANNEL_FL,
168
+           SPA_AUDIO_CHANNEL_FR,
169
+           SPA_AUDIO_CHANNEL_FC,
170
+           SPA_AUDIO_CHANNEL_LFE,
171
+           SPA_AUDIO_CHANNEL_RC,
172
+           SPA_AUDIO_CHANNEL_RL,
173
+           SPA_AUDIO_CHANNEL_RR,
174
+       }),
175
+   .ports = 1,
176
+   .planes = 1,
177
+   .data = { data_f32_6p1_from_5p1 },
178
+   .size = sizeof(data_f32_6p1_from_5p1)
179
+};
180
+
181
+struct data conv_f32_48000_6p1_side = {
182
+   .mode = SPA_PARAM_PORT_CONFIG_MODE_convert,
183
+   .info = SPA_AUDIO_INFO_RAW_INIT(
184
+       .format = SPA_AUDIO_FORMAT_F32,
185
+       .rate = 48000,
186
+       .channels = 7,
187
+       .position = {
188
+           SPA_AUDIO_CHANNEL_FL,
189
+           SPA_AUDIO_CHANNEL_FR,
190
+           SPA_AUDIO_CHANNEL_FC,
191
+           SPA_AUDIO_CHANNEL_LFE,
192
+           SPA_AUDIO_CHANNEL_RC,
193
+           SPA_AUDIO_CHANNEL_SL,
194
+           SPA_AUDIO_CHANNEL_SR,
195
+       }),
196
+   .ports = 1,
197
+   .planes = 1,
198
+   .data = { data_f32_6p1 },
199
+   .size = sizeof(data_f32_6p1)
200
+};
201
pipewire-0.3.59.tar.gz/spa/plugins/audioconvert/test-channelmix.c -> pipewire-0.3.60.tar.gz/spa/plugins/audioconvert/test-channelmix.c Changed
56
 
1
@@ -220,6 +220,46 @@
2
                   0.0, 0.0, 0.0, 0.0, 0.0, 1.0));
3
 }
4
 
5
+static void test_6p1_N(void)
6
+{
7
+   test_mix(7, _M(FL)|_M(FR)|_M(LFE)|_M(FC)|_M(RC)|_M(SL)|_M(SR), 1, _M(MONO), 0,
8
+           MATRIX(0.707107, 0.707107, 1.0, 0.0, 0.5, 0.5, 0.5));
9
+   test_mix(7, _M(FL)|_M(FR)|_M(LFE)|_M(FC)|_M(SL)|_M(SR)|_M(RC),
10
+        6, _M(FL)|_M(FR)|_M(LFE)|_M(FC)|_M(SL)|_M(SR), 0,
11
+           MATRIX(1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
12
+                  0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0,
13
+                  0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0,
14
+                  0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0,
15
+                  0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.707107,
16
+                  0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.707107));
17
+   test_mix(7, _M(FL)|_M(FR)|_M(LFE)|_M(FC)|_M(SL)|_M(SR)|_M(RC),
18
+        6, _M(FL)|_M(FR)|_M(LFE)|_M(FC)|_M(RL)|_M(RR), 0,
19
+           MATRIX(1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
20
+                  0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0,
21
+                  0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0,
22
+                  0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0,
23
+                  0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.707107,
24
+                  0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.707107));
25
+   test_mix(7, _M(FL)|_M(FR)|_M(LFE)|_M(FC)|_M(RC)|_M(RL)|_M(RR),
26
+        6, _M(FL)|_M(FR)|_M(LFE)|_M(FC)|_M(RL)|_M(RR), 0,
27
+           MATRIX(1.0, 0.0, 0.0, 0.0, 0.0,      0.0, 0.0,
28
+                  0.0, 1.0, 0.0, 0.0, 0.0,      0.0, 0.0,
29
+                  0.0, 0.0, 1.0, 0.0, 0.0,      0.0, 0.0,
30
+                  0.0, 0.0, 0.0, 1.0, 0.0,      0.0, 0.0,
31
+                  0.0, 0.0, 0.0, 0.0, 0.707107, 1.0, 0.0,
32
+                  0.0, 0.0, 0.0, 0.0, 0.707107, 0.0, 1.0));
33
+   test_mix(7, _M(FL)|_M(FR)|_M(LFE)|_M(FC)|_M(SL)|_M(SR)|_M(RC),
34
+        8, _M(FL)|_M(FR)|_M(LFE)|_M(FC)|_M(SL)|_M(SR)|_M(RL)|_M(RR), 0,
35
+           MATRIX(1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
36
+                  0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0,
37
+                  0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0,
38
+                  0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0,
39
+                  0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0,
40
+                  0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0,
41
+                  0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.707107,
42
+                  0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.707107));
43
+}
44
+
45
 static void test_7p1_N(void)
46
 {
47
    test_mix(8, _M(FL)|_M(FR)|_M(LFE)|_M(FC)|_M(SL)|_M(SR)|_M(RL)|_M(RR), 1, _M(MONO), 0,
48
@@ -316,6 +356,7 @@
49
    test_3p1_N();
50
    test_4_N();
51
    test_5p1_N();
52
+   test_6p1_N();
53
    test_7p1_N();
54
 
55
    test_n_m_impl();
56
pipewire-0.3.59.tar.gz/spa/plugins/audioconvert/test-source.c -> pipewire-0.3.60.tar.gz/spa/plugins/audioconvert/test-source.c Changed
28
 
1
@@ -535,8 +535,12 @@
2
    case SPA_AUDIO_FORMAT_S24:
3
    case SPA_AUDIO_FORMAT_S24_OE:
4
        return 3;
5
-   default:
6
+   case SPA_AUDIO_FORMAT_S32P:
7
+   case SPA_AUDIO_FORMAT_S32:
8
+   case SPA_AUDIO_FORMAT_S32_OE:
9
        return 4;
10
+   default:
11
+       return 0;
12
    }
13
 }
14
 
15
@@ -571,6 +575,12 @@
16
            return res;
17
 
18
        port->stride = calc_width(&info);
19
+       if (port->stride == 0)
20
+           return -EINVAL;
21
+       if (info.info.raw.rate == 0 ||
22
+           info.info.raw.channels == 0)
23
+           return -EINVAL;
24
+
25
        if (SPA_AUDIO_FORMAT_IS_PLANAR(info.info.raw.format)) {
26
            port->blocks = info.info.raw.channels;
27
        }
28
pipewire-0.3.59.tar.gz/spa/plugins/audioconvert/volume-ops.c -> pipewire-0.3.60.tar.gz/spa/plugins/audioconvert/volume-ops.c Changed
16
 
1
@@ -56,11 +56,9 @@
2
 
3
 static const struct volume_info *find_volume_info(uint32_t cpu_flags)
4
 {
5
-   size_t i;
6
-   for (i = 0; i < SPA_N_ELEMENTS(volume_table); i++) {
7
-       if (!MATCH_CPU_FLAGS(volume_tablei.cpu_flags, cpu_flags))
8
-           continue;
9
-       return &volume_tablei;
10
+   SPA_FOR_EACH_ELEMENT_VAR(volume_table, t) {
11
+       if (MATCH_CPU_FLAGS(t->cpu_flags, cpu_flags))
12
+           return t;
13
    }
14
    return NULL;
15
 }
16
pipewire-0.3.59.tar.gz/spa/plugins/audiomixer/audiomixer.c -> pipewire-0.3.60.tar.gz/spa/plugins/audiomixer/audiomixer.c Changed
12
 
1
@@ -566,6 +566,10 @@
2
            if (memcmp(&info, &this->format, sizeof(struct spa_audio_info)))
3
                return -EINVAL;
4
        } else {
5
+           if (info.info.raw.format == 0 ||
6
+               info.info.raw.channels == 0)
7
+               return -EINVAL;
8
+
9
            this->ops.fmt = info.info.raw.format;
10
            this->ops.n_channels = info.info.raw.channels;
11
            this->ops.cpu_flags = this->cpu_flags;
12
pipewire-0.3.59.tar.gz/spa/plugins/audiomixer/mix-ops-avx.c -> pipewire-0.3.60.tar.gz/spa/plugins/audiomixer/mix-ops-avx.c Changed
64
 
1
@@ -32,62 +32,6 @@
2
 
3
 #include <immintrin.h>
4
 
5
-static inline void mix_4(float * dst,
6
-       const float * SPA_RESTRICT src0,
7
-       const float * SPA_RESTRICT src1,
8
-       const float * SPA_RESTRICT src2,
9
-       uint32_t n_samples)
10
-{
11
-   uint32_t n, unrolled;
12
-
13
-   if (SPA_IS_ALIGNED(src0, 32) &&
14
-       SPA_IS_ALIGNED(src1, 32) &&
15
-       SPA_IS_ALIGNED(src2, 32) &&
16
-       SPA_IS_ALIGNED(dst, 32))
17
-       unrolled = n_samples & ~15;
18
-   else
19
-       unrolled = 0;
20
-
21
-   for (n = 0; n < unrolled; n += 16) {
22
-       __m256 in14, in24;
23
-
24
-       in10 = _mm256_load_ps(&dstn + 0);
25
-       in20 = _mm256_load_ps(&dstn + 8);
26
-       in11 = _mm256_load_ps(&src0n + 0);
27
-       in21 = _mm256_load_ps(&src0n + 8);
28
-       in12 = _mm256_load_ps(&src1n + 0);
29
-       in22 = _mm256_load_ps(&src1n + 8);
30
-       in13 = _mm256_load_ps(&src2n + 0);
31
-       in23 = _mm256_load_ps(&src2n + 8);
32
-
33
-       in10 = _mm256_add_ps(in10, in11);
34
-       in20 = _mm256_add_ps(in20, in21);
35
-       in12 = _mm256_add_ps(in12, in13);
36
-       in22 = _mm256_add_ps(in22, in23);
37
-       in10 = _mm256_add_ps(in10, in12);
38
-       in20 = _mm256_add_ps(in20, in22);
39
-
40
-       _mm256_store_ps(&dstn + 0, in10);
41
-       _mm256_store_ps(&dstn + 8, in20);
42
-   }
43
-   for (; n < n_samples; n++) {
44
-       __m128 in4;
45
-       in0 = _mm_load_ss(&dstn),
46
-       in1 = _mm_load_ss(&src0n),
47
-       in2 = _mm_load_ss(&src1n),
48
-       in3 = _mm_load_ss(&src2n),
49
-       in0 = _mm_add_ss(in0, in1);
50
-       in2 = _mm_add_ss(in2, in3);
51
-       in0 = _mm_add_ss(in0, in2);
52
-       _mm_store_ss(&dstn, in0);
53
-   }
54
-}
55
-
56
-
57
-static inline void mix_2(float * dst, const float * SPA_RESTRICT src, uint32_t n_samples)
58
-{
59
-}
60
-
61
 void
62
 mix_f32_avx(struct mix_ops *ops, void * SPA_RESTRICT dst, const void * SPA_RESTRICT src,
63
        uint32_t n_src, uint32_t n_samples)
64
pipewire-0.3.59.tar.gz/spa/plugins/audiomixer/mix-ops.c -> pipewire-0.3.60.tar.gz/spa/plugins/audiomixer/mix-ops.c Changed
20
 
1
@@ -98,13 +98,11 @@
2
 static const struct mix_info *find_mix_info(uint32_t fmt,
3
        uint32_t n_channels, uint32_t cpu_flags)
4
 {
5
-   size_t i;
6
-
7
-   for (i = 0; i < SPA_N_ELEMENTS(mix_table); i++) {
8
-       if (mix_tablei.fmt == fmt &&
9
-           MATCH_CHAN(mix_tablei.n_channels, n_channels) &&
10
-           MATCH_CPU_FLAGS(mix_tablei.cpu_flags, cpu_flags))
11
-           return &mix_tablei;
12
+   SPA_FOR_EACH_ELEMENT_VAR(mix_table, t) {
13
+       if (t->fmt == fmt &&
14
+           MATCH_CHAN(t->n_channels, n_channels) &&
15
+           MATCH_CPU_FLAGS(t->cpu_flags, cpu_flags))
16
+           return t;
17
    }
18
    return NULL;
19
 }
20
pipewire-0.3.59.tar.gz/spa/plugins/audiotestsrc/audiotestsrc.c -> pipewire-0.3.60.tar.gz/spa/plugins/audiotestsrc/audiotestsrc.c Changed
12
 
1
@@ -743,6 +743,10 @@
2
        if (spa_format_audio_raw_parse(format, &info.info.raw) < 0)
3
            return -EINVAL;
4
 
5
+       if (info.info.raw.rate == 0 ||
6
+           info.info.raw.channels == 0)
7
+           return -EINVAL;
8
+
9
        switch (info.info.raw.format) {
10
        case SPA_AUDIO_FORMAT_S16:
11
            idx = 0;
12
pipewire-0.3.59.tar.gz/spa/plugins/avb/avb-pcm.c -> pipewire-0.3.60.tar.gz/spa/plugins/avb/avb-pcm.c Changed
44
 
1
@@ -439,7 +439,7 @@
2
    }
3
 }
4
 
5
-static int frame_size(uint32_t format)
6
+static int calc_frame_size(uint32_t format)
7
 {
8
    switch(format) {
9
    case SPA_AUDIO_FORMAT_F32_BE:
10
@@ -647,7 +647,7 @@
11
        SPA_AVBTP_PACKET_AAF_SET_FORMAT(pdu, spa_format_to_aaf(state->format));
12
        SPA_AVBTP_PACKET_AAF_SET_NSR(pdu, spa_rate_to_aaf(state->rate));
13
        SPA_AVBTP_PACKET_AAF_SET_CHAN_PER_FRAME(pdu, state->channels);
14
-       SPA_AVBTP_PACKET_AAF_SET_BIT_DEPTH(pdu, frame_size(state->format)*8);
15
+       SPA_AVBTP_PACKET_AAF_SET_BIT_DEPTH(pdu, calc_frame_size(state->format)*8);
16
        SPA_AVBTP_PACKET_AAF_SET_DATA_LEN(pdu, payload_size);
17
        SPA_AVBTP_PACKET_AAF_SET_SP(pdu, SPA_AVBTP_AAF_PCM_SP_NORMAL);
18
    }
19
@@ -690,14 +690,22 @@
20
 
21
 int spa_avb_set_format(struct state *state, struct spa_audio_info *fmt, uint32_t flags)
22
 {
23
-   int res;
24
+   int res, frame_size;
25
    struct props *p = &state->props;
26
 
27
+   frame_size = calc_frame_size(fmt->info.raw.format);
28
+   if (frame_size == 0)
29
+       return -EINVAL;
30
+
31
+   if (fmt->info.raw.rate == 0 ||
32
+       fmt->info.raw.channels == 0)
33
+       return -EINVAL;
34
+
35
    state->format = fmt->info.raw.format;
36
    state->rate = fmt->info.raw.rate;
37
    state->channels = fmt->info.raw.channels;
38
    state->blocks = 1;
39
-   state->stride = state->channels * frame_size(state->format);
40
+   state->stride = state->channels * frame_size;
41
 
42
    if ((res = setup_socket(state)) < 0)
43
        return res;
44
pipewire-0.3.59.tar.gz/spa/plugins/bluez5/a2dp-codec-aac.c -> pipewire-0.3.60.tar.gz/spa/plugins/bluez5/a2dp-codec-aac.c Changed
47
 
1
@@ -206,11 +206,11 @@
2
    spa_pod_builder_push_choice(b, &f1, SPA_CHOICE_None, 0);
3
    choice = (struct spa_pod_choice*)spa_pod_builder_frame(b, &f1);
4
    i = 0;
5
-   for (size_t j = 0; j < SPA_N_ELEMENTS(aac_frequencies); j++) {
6
-       if (AAC_GET_FREQUENCY(conf) & aac_frequenciesj.config) {
7
+   SPA_FOR_EACH_ELEMENT_VAR(aac_frequencies, f) {
8
+       if (AAC_GET_FREQUENCY(conf) & f->config) {
9
            if (i++ == 0)
10
-               spa_pod_builder_int(b, aac_frequenciesj.value);
11
-           spa_pod_builder_int(b, aac_frequenciesj.value);
12
+               spa_pod_builder_int(b, f->value);
13
+           spa_pod_builder_int(b, f->value);
14
        }
15
    }
16
    if (i == 0)
17
@@ -272,14 +272,15 @@
18
    if (!(conf.object_type & (AAC_OBJECT_TYPE_MPEG2_AAC_LC |
19
                    AAC_OBJECT_TYPE_MPEG4_AAC_LC)))
20
        return -EINVAL;
21
-
22
-   for (j = 0; j < SPA_N_ELEMENTS(aac_frequencies); ++j) {
23
-       if (AAC_GET_FREQUENCY(conf) & aac_frequenciesj.config) {
24
-           info->info.raw.rate = aac_frequenciesj.value;
25
+   j = 0;
26
+   SPA_FOR_EACH_ELEMENT_VAR(aac_frequencies, f) {
27
+       if (AAC_GET_FREQUENCY(conf) & f->config) {
28
+           info->info.raw.rate = f->value;
29
+           j++;
30
            break;
31
        }
32
    }
33
-   if (j == SPA_N_ELEMENTS(aac_frequencies))
34
+   if (j == 0)
35
        return -EINVAL;
36
 
37
    if (conf.channels & AAC_CHANNELS_2) {
38
@@ -609,7 +610,7 @@
39
    if (res != AACENC_OK)
40
        return -EINVAL;
41
 
42
-   return 0;
43
+   return this->cur_bitrate;
44
 }
45
 
46
 static int codec_reduce_bitpool(void *data)
47
pipewire-0.3.59.tar.gz/spa/plugins/bluez5/a2dp-codec-lc3plus.c -> pipewire-0.3.60.tar.gz/spa/plugins/bluez5/a2dp-codec-lc3plus.c Changed
23
 
1
@@ -747,15 +747,17 @@
2
 static int codec_reduce_bitpool(void *data)
3
 {
4
    struct impl *this = data;
5
-   this->e.next_bitrate = this->bitrate * 3 / 4;
6
-   return 0;
7
+   this->e.next_bitrate = SPA_CLAMP(this->bitrate * 3 / 4,
8
+           BITRATE_MIN * this->channels, BITRATE_MAX * this->channels);
9
+   return this->e.next_bitrate;
10
 }
11
 
12
 static int codec_increase_bitpool(void *data)
13
 {
14
    struct impl *this = data;
15
-   this->e.next_bitrate = this->bitrate * 5 / 4;
16
-   return 0;
17
+   this->e.next_bitrate = SPA_CLAMP(this->bitrate * 5 / 4,
18
+           BITRATE_MIN * this->channels, BITRATE_MAX * this->channels);
19
+   return this->e.next_bitrate;
20
 }
21
 
22
 const struct media_codec a2dp_codec_lc3plus_hr = {
23
pipewire-0.3.59.tar.gz/spa/plugins/bluez5/a2dp-codec-opus.c -> pipewire-0.3.60.tar.gz/spa/plugins/bluez5/a2dp-codec-opus.c Changed
52
 
1
@@ -1360,7 +1360,6 @@
2
    .codec_id = A2DP_CODEC_VENDOR,              \
3
    .vendor = { .vendor_id = OPUS_05_VENDOR_ID,     \
4
            .codec_id = OPUS_05_CODEC_ID },     \
5
-   .fill_caps = codec_fill_caps,               \
6
    .select_config = codec_select_config,           \
7
    .enum_config = codec_enum_config,           \
8
    .validate_config = codec_validate_config,       \
9
@@ -1385,6 +1384,7 @@
10
    .id = SPA_BLUETOOTH_AUDIO_CODEC_OPUS_05,
11
    .name = "opus_05",
12
    .description = "Opus",
13
+   .fill_caps = codec_fill_caps,
14
 };
15
 
16
 const struct media_codec a2dp_codec_opus_05_51 = {
17
@@ -1392,6 +1392,8 @@
18
    .id = SPA_BLUETOOTH_AUDIO_CODEC_OPUS_05_51,
19
    .name = "opus_05_51",
20
    .description = "Opus 5.1 Surround",
21
+   .endpoint_name = "opus_05",
22
+   .fill_caps = NULL,
23
 };
24
 
25
 const struct media_codec a2dp_codec_opus_05_71 = {
26
@@ -1399,6 +1401,8 @@
27
    .id = SPA_BLUETOOTH_AUDIO_CODEC_OPUS_05_71,
28
    .name = "opus_05_71",
29
    .description = "Opus 7.1 Surround",
30
+   .endpoint_name = "opus_05",
31
+   .fill_caps = NULL,
32
 };
33
 
34
 /* Bidi return channel codec: doesn't have endpoints */
35
@@ -1415,6 +1419,7 @@
36
    .name = "opus_05_duplex",
37
    .description = "Opus Duplex",
38
    .duplex_codec = &a2dp_codec_opus_05_return,
39
+   .fill_caps = codec_fill_caps,
40
 };
41
 
42
 const struct media_codec a2dp_codec_opus_05_pro = {
43
@@ -1425,6 +1430,8 @@
44
    .init_props = codec_init_props,
45
    .clear_props = codec_clear_props,
46
    .duplex_codec = &a2dp_codec_opus_05_return,
47
+   .endpoint_name = "opus_05_duplex",
48
+   .fill_caps = NULL,
49
 };
50
 
51
 MEDIA_CODEC_EXPORT_DEF(
52
pipewire-0.3.59.tar.gz/spa/plugins/bluez5/backend-native.c -> pipewire-0.3.60.tar.gz/spa/plugins/bluez5/backend-native.c Changed
201
 
1
@@ -51,6 +51,9 @@
2
 #include <libusb.h>
3
 #endif
4
 
5
+#include "modemmanager.h"
6
+#include "upower.h"
7
+
8
 static struct spa_log_topic log_topic = SPA_LOG_TOPIC(0, "spa.bluez5.native");
9
 #undef SPA_LOG_TOPIC_DEFAULT
10
 #define SPA_LOG_TOPIC_DEFAULT &log_topic
11
@@ -60,12 +63,39 @@
12
 #define HFP_CODEC_SWITCH_INITIAL_TIMEOUT_MSEC 5000
13
 #define HFP_CODEC_SWITCH_TIMEOUT_MSEC 20000
14
 
15
+#define INTERNATIONAL_NUMBER 145
16
+#define NATIONAL_NUMBER 129
17
+
18
+#define MAX_HF_INDICATORS 16
19
+
20
 enum {
21
    HFP_AG_INITIAL_CODEC_SETUP_NONE = 0,
22
    HFP_AG_INITIAL_CODEC_SETUP_SEND,
23
    HFP_AG_INITIAL_CODEC_SETUP_WAIT
24
 };
25
 
26
+#define CIND_INDICATORS "(\"service\",(0-1)),(\"call\",(0-1)),(\"callsetup\",(0-3)),(\"callheld\",(0-2)),(\"signal\",(0-5)),(\"roam\",(0-1)),\"battchg\",(0-5))"
27
+enum {
28
+   CIND_SERVICE = 1,
29
+   CIND_CALL,
30
+   CIND_CALLSETUP,
31
+   CIND_CALLHELD,
32
+   CIND_SIGNAL,
33
+   CIND_ROAM,
34
+   CIND_BATTERY_LEVEL,
35
+   CIND_MAX
36
+};
37
+
38
+struct modem {
39
+   bool network_has_service;
40
+   unsigned int signal_strength;
41
+   bool network_is_roaming;
42
+   char *operator_name;
43
+   char *own_number;
44
+   bool active_call;
45
+   unsigned int call_setup;
46
+};
47
+
48
 struct impl {
49
    struct spa_bt_backend this;
50
 
51
@@ -87,6 +117,13 @@
52
 
53
    struct spa_list rfcomm_list;
54
    unsigned int defer_setup_enabled:1;
55
+
56
+   struct modem modem;
57
+   unsigned int battery_level;
58
+
59
+   void *modemmanager;
60
+   struct spa_source *ring_timer;
61
+   void *upower;
62
 };
63
 
64
 struct transport_data {
65
@@ -142,9 +179,13 @@
66
    unsigned int hfp_ag_initial_codec_setup:2;
67
    unsigned int cind_call_active:1;
68
    unsigned int cind_call_notify:1;
69
+   unsigned int extended_error_reporting:1;
70
+   unsigned int clip_notify:1;
71
    enum hfp_hf_state hf_state;
72
    enum hsp_hs_state hs_state;
73
    unsigned int codec;
74
+   uint32_t cind_enabled_indicators;
75
+   char *hf_indicatorsMAX_HF_INDICATORS;
76
 #endif
77
 };
78
 
79
@@ -233,6 +274,11 @@
80
 static void rfcomm_free(struct rfcomm *rfcomm)
81
 {
82
    codec_switch_stop_timer(rfcomm);
83
+   for (int i = 0; i < MAX_HF_INDICATORS; i++) {
84
+       if (rfcomm->hf_indicatorsi) {
85
+           free(rfcomm->hf_indicatorsi);
86
+       }
87
+   }
88
    spa_list_remove(&rfcomm->link);
89
    if (rfcomm->path)
90
        free(rfcomm->path);
91
@@ -351,6 +397,14 @@
92
    return len;
93
 }
94
 
95
+static void rfcomm_send_error(const struct rfcomm *rfcomm, enum cmee_error error)
96
+{
97
+   if (rfcomm->extended_error_reporting)
98
+       rfcomm_send_reply(rfcomm, "+CME ERROR: %d", error);
99
+   else
100
+       rfcomm_send_reply(rfcomm, "ERROR");
101
+}
102
+
103
 static bool rfcomm_volume_enabled(struct rfcomm *rfcomm)
104
 {
105
    return rfcomm->device != NULL
106
@@ -720,6 +774,7 @@
107
    unsigned int selected_codec;
108
    unsigned int indicator;
109
    unsigned int indicator_value;
110
+   unsigned int value;
111
    int xapl_vendor;
112
    int xapl_product;
113
    int xapl_features;
114
@@ -761,6 +816,7 @@
115
        }
116
 
117
        /* send reply to HF with the features supported by Audio Gateway (=computer) */
118
+       ag_features |= mm_supported_features();
119
        ag_features |= SPA_BT_HFP_AG_FEATURE_HF_INDICATORS;
120
        rfcomm_send_reply(rfcomm, "+BRSF: %u", ag_features);
121
        rfcomm_send_reply(rfcomm, "OK");
122
@@ -788,10 +844,12 @@
123
 
124
        rfcomm_send_reply(rfcomm, "OK");
125
    } else if (spa_strstartswith(buf, "AT+CIND=?")) {
126
-       rfcomm_send_reply(rfcomm, "+CIND:(\"service\",(0-1)),(\"call\",(0-1)),(\"callsetup\",(0-3)),(\"callheld\",(0-2))");
127
+       rfcomm_send_reply(rfcomm, "+CIND:%s", CIND_INDICATORS);
128
        rfcomm_send_reply(rfcomm, "OK");
129
    } else if (spa_strstartswith(buf, "AT+CIND?")) {
130
-       rfcomm_send_reply(rfcomm, "+CIND: 0,%d,0,0", rfcomm->cind_call_active);
131
+       rfcomm_send_reply(rfcomm, "+CIND: %d,%d,%d,0,%d,%d,%d", backend->modem.network_has_service,
132
+                         backend->modem.active_call, backend->modem.call_setup, backend->modem.signal_strength,
133
+                         backend->modem.network_is_roaming, backend->battery_level);
134
        rfcomm_send_reply(rfcomm, "OK");
135
    } else if (spa_strstartswith(buf, "AT+CMER")) {
136
        int mode, keyp, disp, ind;
137
@@ -824,8 +882,13 @@
138
        }
139
    } else if (!rfcomm->slc_configured) {
140
        spa_log_warn(backend->log, "RFCOMM receive command before SLC completed: %s", buf);
141
-       rfcomm_send_reply(rfcomm, "ERROR");
142
+       rfcomm_send_error(rfcomm, CMEE_AG_FAILURE);
143
        return true;
144
+
145
+   /* *****
146
+    * Following commands requires a Service Level Connection
147
+    * ***** */
148
+
149
    } else if (sscanf(buf, "AT+BCS=%u", &selected_codec) == 1) {
150
        /* parse BCS(=Bluetooth Codec Selection) reply */
151
        bool was_switching_codec = rfcomm->hfp_ag_switching_codec && (rfcomm->device != NULL);
152
@@ -836,7 +899,7 @@
153
 
154
        if (selected_codec != HFP_AUDIO_CODEC_CVSD && selected_codec != HFP_AUDIO_CODEC_MSBC) {
155
            spa_log_warn(backend->log, "unsupported codec negotiation: %d", selected_codec);
156
-           rfcomm_send_reply(rfcomm, "ERROR");
157
+           rfcomm_send_error(rfcomm, CMEE_AG_FAILURE);
158
            if (was_switching_codec)
159
                spa_bt_device_emit_codec_switched(rfcomm->device, -EIO);
160
            return true;
161
@@ -854,7 +917,7 @@
162
        if (rfcomm->transport == NULL) {
163
            spa_log_warn(backend->log, "can't create transport: %m");
164
            // TODO: We should manage the missing transport
165
-           rfcomm_send_reply(rfcomm, "ERROR");
166
+           rfcomm_send_error(rfcomm, CMEE_AG_FAILURE);
167
            if (was_switching_codec)
168
                spa_bt_device_emit_codec_switched(rfcomm->device, -ENOMEM);
169
            return true;
170
@@ -867,10 +930,105 @@
171
        if (was_switching_codec)
172
            spa_bt_device_emit_codec_switched(rfcomm->device, 0);
173
    } else if (spa_strstartswith(buf, "AT+BIA=")) {
174
-       /* We only support 'call' indicator, which HFP 4.35.1 defines as
175
-          always active (assuming CMER enabled it), so we don't need to
176
-          parse anything here. */
177
+       /* retrieve indicators activation
178
+        * form: AT+BIA=indrep1,indrep2,indrepx */
179
+       char *str = buf + 7;
180
+       unsigned int ind = 1;
181
+
182
+       while (*str && ind < CIND_MAX && *str != '\r' && *str != '\n') {
183
+           if (*str == ',') {
184
+               ind++;
185
+               goto next_indicator;
186
+           }
187
+
188
+           /* Ignore updates to mandantory indicators which are always ON */
189
+           if (ind == CIND_CALL || ind == CIND_CALLSETUP || ind == CIND_CALLHELD)
190
+               goto next_indicator;
191
+
192
+           switch (*str) {
193
+           case '0':
194
+               rfcomm->cind_enabled_indicators &= ~(1 << ind);
195
+               break;
196
+           case '1':
197
+               rfcomm->cind_enabled_indicators |= (1 << ind);
198
+               break;
199
+           default:
200
+               spa_log_warn(backend->log, "Unsupported entry in %s: %c", buf, *str);
201
pipewire-0.3.59.tar.gz/spa/plugins/bluez5/bap-codec-caps.h -> pipewire-0.3.60.tar.gz/spa/plugins/bluez5/bap-codec-caps.h Changed
35
 
1
@@ -110,4 +110,33 @@
2
    uint8_t n_blks;
3
 } __attribute__ ((packed)) bap_lc3_t;
4
 
5
+#define BT_ISO_QOS_CIG_UNSET    0xff
6
+#define BT_ISO_QOS_CIS_UNSET    0xff
7
+
8
+#define BT_ISO_QOS_TARGET_LATENCY_LOW      0x01
9
+#define BT_ISO_QOS_TARGET_LATENCY_BALANCED 0x02
10
+#define BT_ISO_QOS_TARGET_LATENCY_RELIABILITY  0x03
11
+
12
+struct bap_endpoint_qos {
13
+        uint8_t  framing;
14
+        uint8_t  phy;
15
+        uint8_t  retransmission;
16
+        uint16_t latency;
17
+        uint32_t delay_min;
18
+        uint32_t delay_max;
19
+        uint32_t preferred_delay_min;
20
+        uint32_t preferred_delay_max;
21
+};
22
+
23
+struct bap_codec_qos {
24
+   uint32_t interval;
25
+   uint8_t framing;
26
+   uint8_t phy;
27
+   uint16_t sdu;
28
+   uint8_t retransmission;
29
+   uint16_t latency;
30
+   uint32_t delay;
31
+   uint8_t target_latency;
32
+};
33
+
34
 #endif
35
pipewire-0.3.59.tar.gz/spa/plugins/bluez5/bap-codec-lc3.c -> pipewire-0.3.60.tar.gz/spa/plugins/bluez5/bap-codec-lc3.c Changed
67
 
1
@@ -501,24 +501,31 @@
2
    return 0;
3
 }
4
 
5
-static void codec_get_qos(const struct media_codec *codec,
6
-           const void *config, size_t config_size,
7
-           struct codec_qos *qos)
8
+static int codec_get_qos(const struct media_codec *codec,
9
+       const void *config, size_t config_size,
10
+       const struct bap_endpoint_qos *endpoint_qos,
11
+       struct bap_codec_qos *qos)
12
 {
13
    bap_lc3_t conf;
14
 
15
-   memset(qos, 0, sizeof(*qos));
16
+   spa_zero(*qos);
17
 
18
    if (!parse_conf(&conf, config, config_size))
19
-       return;
20
+       return -EINVAL;
21
 
22
    qos->framing = false;
23
-   qos->phy = "2M";
24
+   if (endpoint_qos->phy & 0x2)
25
+       qos->phy = 0x2;
26
+   else if (endpoint_qos->phy & 0x1)
27
+       qos->phy = 0x1;
28
+   else
29
+       qos->phy = 0x2;
30
    qos->retransmission = 2; /* default */
31
    qos->sdu = conf.framelen * conf.n_blks;
32
    qos->latency = 20; /* default */
33
    qos->delay = 40000U;
34
    qos->interval = (conf.frame_duration == LC3_CONFIG_DURATION_7_5 ? 7500 : 10000);
35
+   qos->target_latency = BT_ISO_QOS_TARGET_LATENCY_BALANCED;
36
 
37
    switch (conf.rate) {
38
        case LC3_CONFIG_FREQ_8KHZ:
39
@@ -533,6 +540,18 @@
40
            qos->latency = (conf.frame_duration == LC3_CONFIG_DURATION_7_5 ? 15 : 20);
41
            break;
42
    }
43
+
44
+   /* Clamp to ASE values */
45
+   if (endpoint_qos->latency >= 0x0005 && endpoint_qos->latency <= 0x0FA0)
46
+       /* Values outside the range are RFU */
47
+       qos->latency = SPA_MAX(qos->latency, endpoint_qos->latency);
48
+
49
+   if (endpoint_qos->delay_min)
50
+       qos->delay = SPA_MAX(qos->delay, endpoint_qos->delay_min);
51
+   if (endpoint_qos->delay_max)
52
+       qos->delay = SPA_MIN(qos->delay, endpoint_qos->delay_max);
53
+
54
+   return 0;
55
 }
56
 
57
 static void *codec_init(const struct media_codec *codec, uint32_t flags,
58
@@ -586,7 +605,7 @@
59
    }
60
    this->codesize = this->samples * this->channels * sizeof(int32_t);
61
 
62
-   if (flags & MEDIA_CODEC_FLAG_SINK) {
63
+   if (!(flags & MEDIA_CODEC_FLAG_SINK)) {
64
        for (ich = 0; ich < this->channels; ich++) {
65
            this->encich = lc3_setup_encoder(this->frame_dus, this->samplerate, 0, calloc(1, lc3_encoder_size(this->frame_dus, this->samplerate)));
66
            if (this->encich == NULL) {
67
pipewire-0.3.59.tar.gz/spa/plugins/bluez5/bluez5-dbus.c -> pipewire-0.3.60.tar.gz/spa/plugins/bluez5/bluez5-dbus.c Changed
201
 
1
@@ -113,6 +113,7 @@
2
 
3
    unsigned int filters_added:1;
4
    unsigned int objects_listed:1;
5
+   DBusPendingCall *get_managed_objects_call;
6
 
7
    struct spa_bt_backend *backend;
8
    struct spa_bt_backend *backendsBACKEND_NUM;
9
@@ -451,10 +452,11 @@
10
    return 0;
11
 }
12
 
13
-static const struct media_codec *media_endpoint_to_codec(struct spa_bt_monitor *monitor, const char *endpoint, bool *sink)
14
+static const struct media_codec *media_endpoint_to_codec(struct spa_bt_monitor *monitor, const char *endpoint, bool *sink, const struct media_codec *preferred)
15
 {
16
    const char *ep_name;
17
    const struct media_codec * const * const media_codecs = monitor->media_codecs;
18
+   const struct media_codec *found = NULL;
19
    int i;
20
 
21
    if (spa_strstartswith(endpoint, A2DP_SINK_ENDPOINT "/")) {
22
@@ -478,10 +480,20 @@
23
        const struct media_codec *codec = media_codecsi;
24
        const char *codec_ep_name =
25
            codec->endpoint_name ? codec->endpoint_name : codec->name;
26
-       if (spa_streq(ep_name, codec_ep_name))
27
-           return codec;
28
+
29
+       if (!spa_streq(ep_name, codec_ep_name))
30
+           continue;
31
+       if ((*sink && !codec->decode) || (!*sink && !codec->encode))
32
+           continue;
33
+
34
+       /* Same endpoint may be shared with multiple codec objects,
35
+        * which may e.g. correspond to different encoder settings.
36
+        * Look up which one we selected.
37
+        */
38
+       if ((preferred && codec == preferred) || found == NULL)
39
+           found = codec;
40
    }
41
-   return NULL;
42
+   return found;
43
 }
44
 
45
 static int media_endpoint_to_profile(const char *endpoint)
46
@@ -504,6 +516,30 @@
47
    return spa_dict_lookup(&monitor->enabled_codecs, codec->name) != NULL;
48
 }
49
 
50
+static bool codec_has_direction(const struct media_codec *codec, enum spa_bt_media_direction direction)
51
+{
52
+   switch (direction) {
53
+   case SPA_BT_MEDIA_SOURCE:
54
+       return codec->encode;
55
+   case SPA_BT_MEDIA_SINK:
56
+       return codec->decode;
57
+   default:
58
+       spa_assert_not_reached();
59
+   }
60
+}
61
+
62
+static bool endpoint_should_be_registered(struct spa_bt_monitor *monitor,
63
+                     const struct media_codec *codec,
64
+                     enum spa_bt_media_direction direction)
65
+{
66
+   /* Codecs with fill_caps == NULL share endpoint with another codec,
67
+    * and don't have their own endpoint
68
+    */
69
+   return is_media_codec_enabled(monitor, codec) &&
70
+       codec_has_direction(codec, direction) &&
71
+       codec->fill_caps;
72
+}
73
+
74
 static DBusHandlerResult endpoint_select_configuration(DBusConnection *conn, DBusMessage *m, void *userdata)
75
 {
76
    struct spa_bt_monitor *monitor = userdata;
77
@@ -529,7 +565,14 @@
78
    spa_log_info(monitor->log, "%p: %s select conf %d", monitor, path, size);
79
    spa_log_hexdump(monitor->log, SPA_LOG_LEVEL_DEBUG, 2, cap, (size_t)size);
80
 
81
-   codec = media_endpoint_to_codec(monitor, path, &sink);
82
+   /* For codecs sharing the same endpoint, BlueZ-initiated connections
83
+    * always pick the default one. The session manager will
84
+    * switch the codec to a saved value after connection, so this generally
85
+    * does not matter.
86
+    */
87
+   codec = media_endpoint_to_codec(monitor, path, &sink, NULL);
88
+   spa_log_debug(monitor->log, "%p: %s codec:%s", monitor, path, codec ? codec->name : "<null>");
89
+
90
    if (codec != NULL)
91
        /* FIXME: We can't determine which device the SelectConfiguration()
92
         * call is associated with, therefore device settings are not passed.
93
@@ -557,7 +600,7 @@
94
            DBUS_TYPE_BYTE, &pconf, size, DBUS_TYPE_INVALID))
95
        return DBUS_HANDLER_RESULT_NEED_MEMORY;
96
 
97
-      exit_send:
98
+exit_send:
99
    if (!dbus_connection_send(conn, r, NULL))
100
        return DBUS_HANDLER_RESULT_NEED_MEMORY;
101
 
102
@@ -574,12 +617,21 @@
103
 {
104
    struct spa_bt_monitor *monitor = userdata;
105
    const char *path;
106
-   const char *object_path;
107
    DBusMessageIter args, props, iter;
108
    DBusMessage *r = NULL;
109
-   int size, res;
110
+   int res;
111
    const struct media_codec *codec;
112
    bool sink;
113
+   const char *err_msg = "Unknown error";
114
+
115
+   const char *endpoint_path = NULL;
116
+   uint8_t capsA2DP_MAX_CAPS_SIZE;
117
+   uint8_t configA2DP_MAX_CAPS_SIZE;
118
+   int caps_size = 0;
119
+   DBusMessageIter dict;
120
+   struct bap_endpoint_qos endpoint_qos;
121
+
122
+   spa_zero(endpoint_qos);
123
 
124
    if (!dbus_message_iter_init(m, &args) || !spa_streq(dbus_message_get_signature(m), "a{sv}")) {
125
        spa_log_error(monitor->log, "Invalid signature for method SelectProperties()");
126
@@ -592,22 +644,24 @@
127
 
128
    path = dbus_message_get_path(m);
129
 
130
-   codec = media_endpoint_to_codec(monitor, path, &sink);
131
+   /* TODO: for codecs with shared endpoint, this currently always picks the default
132
+    * one. However, currently we don't have BAP codecs with shared endpoint, so
133
+    * this does not matter, but in case they are needed later we should pick the
134
+    * right one here.
135
+    */
136
+   codec = media_endpoint_to_codec(monitor, path, &sink, NULL);
137
+   spa_log_debug(monitor->log, "%p: %s codec:%s", monitor, path, codec ? codec->name : "<null>");
138
    if (!codec) {
139
-       res = -ENOTSUP;
140
-       spa_log_error(monitor->log, "Unsupported codec: %d (%s)",
141
-               res, spa_strerror(res));
142
-       if ((r = dbus_message_new_error(m, "org.bluez.Error.InvalidArguments",
143
-               "Unsupported codec")) == NULL)
144
-           return DBUS_HANDLER_RESULT_NEED_MEMORY;
145
-       goto exit_send;
146
+       spa_log_error(monitor->log, "Unsupported codec");
147
+       err_msg = "Unsupported codec";
148
+       goto error;
149
    }
150
 
151
-   /* Read transport properties */
152
+   /* Parse transport properties */
153
    while (dbus_message_iter_get_arg_type(&props) == DBUS_TYPE_DICT_ENTRY) {
154
        const char *key;
155
        DBusMessageIter value, entry;
156
-       int var;
157
+       int type;
158
 
159
        dbus_message_iter_recurse(&props, &entry);
160
        dbus_message_iter_get_basic(&entry, &key);
161
@@ -615,112 +669,156 @@
162
        dbus_message_iter_next(&entry);
163
        dbus_message_iter_recurse(&entry, &value);
164
 
165
-       var = dbus_message_iter_get_arg_type(&value);
166
+       type = dbus_message_iter_get_arg_type(&value);
167
 
168
        if (spa_streq(key, "Capabilities")) {
169
-           DBusMessageIter array, dict;
170
-           uint8_t configA2DP_MAX_CAPS_SIZE, *cap;
171
-           uint8_t *pconf = (uint8_t *) config;
172
-
173
-           if (r) {
174
-               spa_log_warn(monitor->log, "Multiple Capabilities entries, skipped");
175
-               goto next_entry;
176
-           }
177
+           DBusMessageIter array;
178
+           uint8_t *buf;
179
 
180
-           if (var != DBUS_TYPE_ARRAY) {
181
-               spa_log_error(monitor->log, "Property %s of wrong type %c", key, (char)var);
182
-               if ((r = dbus_message_new_error(m, "org.bluez.Error.InvalidArguments",
183
-                       "Invalid property")) == NULL)
184
-                   return DBUS_HANDLER_RESULT_NEED_MEMORY;
185
-               goto exit_send;
186
+           if (type != DBUS_TYPE_ARRAY) {
187
+               spa_log_error(monitor->log, "Property %s of wrong type %c", key, (char)type);
188
+               goto error_invalid;
189
            }
190
 
191
            dbus_message_iter_recurse(&value, &array);
192
-           var = dbus_message_iter_get_arg_type(&array);
193
-           if (var != DBUS_TYPE_BYTE) {
194
-               spa_log_error(monitor->log, "%s is an array of wrong type %c", key, (char)var);
195
-               if ((r = dbus_message_new_error(m, "org.bluez.Error.InvalidArguments",
196
-                       "Invalid property")) == NULL)
197
-                   return DBUS_HANDLER_RESULT_NEED_MEMORY;
198
-               goto exit_send;
199
-           }
200
-
201
pipewire-0.3.59.tar.gz/spa/plugins/bluez5/bluez5-device.c -> pipewire-0.3.60.tar.gz/spa/plugins/bluez5/bluez5-device.c Changed
48
 
1
@@ -74,6 +74,7 @@
2
    DEVICE_PROFILE_A2DP = 2,
3
    DEVICE_PROFILE_HSP_HFP = 3,
4
    DEVICE_PROFILE_BAP = 4,
5
+   DEVICE_PROFILE_LAST = DEVICE_PROFILE_BAP,
6
 };
7
 
8
 struct props {
9
@@ -1092,18 +1093,18 @@
10
    *codec = 0;
11
    *next = index + 1;
12
 
13
-   if (index <= 3) {
14
+   if (index <= DEVICE_PROFILE_LAST) {
15
        return index;
16
    } else if (index != SPA_ID_INVALID) {
17
        const struct spa_type_info *info;
18
        uint32_t profile;
19
 
20
-       *codec = index - 3;
21
+       *codec = index - DEVICE_PROFILE_LAST;
22
        *next = SPA_ID_INVALID;
23
 
24
        for (info = spa_type_bluetooth_audio_codec; info->type; ++info)
25
            if (info->type > *codec)
26
-               *next = SPA_MIN(info->type + 3, *next);
27
+               *next = SPA_MIN(info->type + DEVICE_PROFILE_LAST, *next);
28
 
29
        if (get_hfp_codec(*codec))
30
            profile = DEVICE_PROFILE_HSP_HFP;
31
@@ -1128,14 +1129,14 @@
32
        if (codec == 0 || (this->bt_dev->connected_profiles & SPA_BT_PROFILE_MEDIA_SOURCE))
33
            return profile;
34
 
35
-       return codec + 3;
36
+       return codec + DEVICE_PROFILE_LAST;
37
    }
38
 
39
    if (profile == DEVICE_PROFILE_HSP_HFP) {
40
        if (codec == 0 || (this->bt_dev->connected_profiles & SPA_BT_PROFILE_HFP_AG))
41
            return profile;
42
 
43
-       return codec + 3;
44
+       return codec + DEVICE_PROFILE_LAST;
45
    }
46
 
47
    return SPA_ID_INVALID;
48
pipewire-0.3.59.tar.gz/spa/plugins/bluez5/codec-loader.c -> pipewire-0.3.60.tar.gz/spa/plugins/bluez5/codec-loader.c Changed
34
 
1
@@ -126,8 +126,12 @@
2
 
3
    for (i = 0; bluez5_codec_a2dp->codecsi; ++i) {
4
        const struct media_codec *c = bluez5_codec_a2dp->codecsi;
5
+       const char *ep = c->endpoint_name ? c->endpoint_name : c->name;
6
        size_t j;
7
 
8
+       if (!ep)
9
+           goto next_codec;
10
+
11
        if (impl->n_codecs >= MAX_CODECS) {
12
            spa_log_error(impl->log, "too many A2DP codecs");
13
            break;
14
@@ -136,13 +140,16 @@
15
        /* Don't load duplicate endpoints */
16
        for (j = 0; j < impl->n_codecs; ++j) {
17
            const struct media_codec *c2 = impl->codecsj;
18
-           const char *ep1 = c->endpoint_name ? c->endpoint_name : c->name;
19
            const char *ep2 = c2->endpoint_name ? c2->endpoint_name : c2->name;
20
-           if (spa_streq(ep1, ep2))
21
+           if (spa_streq(ep, ep2) && c->fill_caps && c2->fill_caps) {
22
+               spa_log_debug(impl->log, "media codec %s from %s duplicate endpoint %s",
23
+                       c->name, factory_name, ep);
24
                goto next_codec;
25
+           }
26
        }
27
 
28
-       spa_log_debug(impl->log, "loaded media codec %s from %s", c->name, factory_name);
29
+       spa_log_debug(impl->log, "loaded media codec %s from %s, endpoint:%s",
30
+               c->name, factory_name, ep);
31
 
32
        if (c->set_log)
33
            c->set_log(impl->log);
34
pipewire-0.3.59.tar.gz/spa/plugins/bluez5/defs.h -> pipewire-0.3.60.tar.gz/spa/plugins/bluez5/defs.h Changed
22
 
1
@@ -459,6 +459,8 @@
2
    void (*destroy) (void *data);
3
 };
4
 
5
+struct media_codec;
6
+
7
 struct spa_bt_device {
8
    struct spa_list link;
9
    struct spa_bt_monitor *monitor;
10
@@ -507,9 +509,9 @@
11
    const struct spa_dict *settings;
12
 
13
    DBusPendingCall *battery_pending_call;
14
-};
15
 
16
-struct media_codec;
17
+   const struct media_codec *preferred_codec;
18
+};
19
 
20
 struct spa_bt_device *spa_bt_device_find(struct spa_bt_monitor *monitor, const char *path);
21
 struct spa_bt_device *spa_bt_device_find_by_address(struct spa_bt_monitor *monitor, const char *remote_address, const char *local_address);
22
pipewire-0.3.59.tar.gz/spa/plugins/bluez5/media-codecs.h -> pipewire-0.3.60.tar.gz/spa/plugins/bluez5/media-codecs.h Changed
59
 
1
@@ -36,6 +36,7 @@
2
 #include <spa/support/log.h>
3
 
4
 #include "a2dp-codec-caps.h"
5
+#include "bap-codec-caps.h"
6
 
7
 /*
8
  * The codec plugin SPA interface is private.  The version should be incremented
9
@@ -44,7 +45,7 @@
10
 
11
 #define SPA_TYPE_INTERFACE_Bluez5CodecMedia    SPA_TYPE_INFO_INTERFACE_BASE "Bluez5:Codec:Media:Private"
12
 
13
-#define SPA_VERSION_BLUEZ5_CODEC_MEDIA     5
14
+#define SPA_VERSION_BLUEZ5_CODEC_MEDIA     7
15
 
16
 struct spa_bluez5_codec_a2dp {
17
    struct spa_interface iface;
18
@@ -79,16 +80,6 @@
19
    uint32_t channels;
20
 };
21
 
22
-struct codec_qos {
23
-    uint32_t interval;
24
-    bool framing;
25
-    char *phy;
26
-    uint16_t sdu;
27
-    uint8_t retransmission;
28
-    uint16_t latency;
29
-    uint32_t delay;
30
-};
31
-
32
 struct media_codec {
33
    enum spa_bluetooth_audio_codec id;
34
    uint8_t codec_id;
35
@@ -107,8 +98,10 @@
36
 
37
    struct spa_log *log;
38
 
39
+   /** If fill_caps is NULL, no endpoint is registered (for sharing with another codec). */
40
    int (*fill_caps) (const struct media_codec *codec, uint32_t flags,
41
            uint8_t capsA2DP_MAX_CAPS_SIZE);
42
+
43
    int (*select_config) (const struct media_codec *codec, uint32_t flags,
44
            const void *caps, size_t caps_size,
45
            const struct media_codec_audio_info *info,
46
@@ -119,9 +112,10 @@
47
    int (*validate_config) (const struct media_codec *codec, uint32_t flags,
48
            const void *caps, size_t caps_size,
49
            struct spa_audio_info *info);
50
-   void (*get_qos)(const struct media_codec *codec,
51
+   int (*get_qos)(const struct media_codec *codec,
52
            const void *config, size_t config_size,
53
-           struct codec_qos *qos);
54
+           const struct bap_endpoint_qos *endpoint_qos,
55
+           struct bap_codec_qos *qos);
56
 
57
    /** qsort comparison sorting caps in order of preference for the codec.
58
     * Used in codec switching to select best remote endpoints.
59
pipewire-0.3.59.tar.gz/spa/plugins/bluez5/media-sink.c -> pipewire-0.3.60.tar.gz/spa/plugins/bluez5/media-sink.c Changed
201
 
1
@@ -62,17 +62,14 @@
2
 #define DEFAULT_CLOCK_NAME "clock.system.monotonic"
3
 
4
 struct props {
5
-   uint32_t min_latency;
6
-   uint32_t max_latency;
7
    int64_t latency_offset;
8
    char clock_name64;
9
 };
10
 
11
-#define FILL_FRAMES 2
12
+#define FILL_FRAMES 4
13
+#define MIN_BUFFERS 2
14
 #define MAX_BUFFERS 32
15
-#define MIN_LATENCY    128
16
-#define MAX_LATENCY    8192
17
-#define BUFFER_SIZE    (MAX_LATENCY*8)
18
+#define BUFFER_SIZE    (8192*8)
19
 
20
 struct buffer {
21
    uint32_t id;
22
@@ -121,6 +118,8 @@
23
    struct spa_hook_list hooks;
24
    struct spa_callbacks callbacks;
25
 
26
+   uint32_t quantum_limit;
27
+
28
    uint64_t info_all;
29
    struct spa_node_info info;
30
 #define IDX_PropInfo   0
31
@@ -137,6 +136,7 @@
32
    unsigned int started:1;
33
    unsigned int following:1;
34
    unsigned int is_output:1;
35
+   unsigned int flush_pending:1;
36
 
37
    unsigned int is_duplex:1;
38
 
39
@@ -152,6 +152,10 @@
40
    uint64_t current_time;
41
    uint64_t next_time;
42
    uint64_t last_error;
43
+   uint64_t process_time;
44
+
45
+   uint64_t prev_flush_time;
46
+   uint64_t next_flush_time;
47
 
48
    const struct media_codec *codec;
49
    bool codec_props_changed;
50
@@ -161,30 +165,23 @@
51
 
52
    int need_flush;
53
    bool fragment;
54
-   uint64_t fragment_timeout;
55
    uint32_t block_size;
56
    uint8_t bufferBUFFER_SIZE;
57
    uint32_t buffer_used;
58
    uint32_t header_size;
59
-   uint32_t frame_count;
60
+   uint32_t block_count;
61
    uint16_t seqnum;
62
    uint32_t timestamp;
63
    uint64_t sample_count;
64
    uint8_t tmp_bufferBUFFER_SIZE;
65
    uint32_t tmp_buffer_used;
66
    uint32_t fd_buffer_size;
67
-
68
-   /* Times */
69
-   uint64_t start_time;
70
-   uint64_t total_samples;
71
 };
72
 
73
-#define CHECK_PORT(this,d,p)    ((d) == SPA_DIRECTION_INPUT && (p) == 0)
74
+#define CHECK_PORT(this,d,p)   ((d) == SPA_DIRECTION_INPUT && (p) == 0)
75
 
76
 static void reset_props(struct impl *this, struct props *props)
77
 {
78
-   props->min_latency = MIN_LATENCY;
79
-   props->max_latency = MAX_LATENCY;
80
    props->latency_offset = 0;
81
    strncpy(props->clock_name, DEFAULT_CLOCK_NAME, sizeof(props->clock_name));
82
 }
83
@@ -214,33 +211,17 @@
84
    switch (id) {
85
    case SPA_PARAM_PropInfo:
86
    {
87
-       struct props *p = &this->props;
88
-
89
        switch (result.index) {
90
        case 0:
91
            param = spa_pod_builder_add_object(&b,
92
                SPA_TYPE_OBJECT_PropInfo, id,
93
-               SPA_PROP_INFO_id,   SPA_POD_Id(SPA_PROP_minLatency),
94
-               SPA_PROP_INFO_description, SPA_POD_String("The minimum latency"),
95
-               SPA_PROP_INFO_type, SPA_POD_CHOICE_RANGE_Int(p->min_latency, 1, INT32_MAX));
96
-           break;
97
-       case 1:
98
-           param = spa_pod_builder_add_object(&b,
99
-               SPA_TYPE_OBJECT_PropInfo, id,
100
-               SPA_PROP_INFO_id,   SPA_POD_Id(SPA_PROP_maxLatency),
101
-               SPA_PROP_INFO_description, SPA_POD_String("The maximum latency"),
102
-               SPA_PROP_INFO_type, SPA_POD_CHOICE_RANGE_Int(p->max_latency, 1, INT32_MAX));
103
-           break;
104
-       case 2:
105
-           param = spa_pod_builder_add_object(&b,
106
-               SPA_TYPE_OBJECT_PropInfo, id,
107
                SPA_PROP_INFO_id,   SPA_POD_Id(SPA_PROP_latencyOffsetNsec),
108
                SPA_PROP_INFO_description, SPA_POD_String("Latency offset (ns)"),
109
                SPA_PROP_INFO_type, SPA_POD_CHOICE_RANGE_Long(0LL, INT64_MIN, INT64_MAX));
110
            break;
111
        default:
112
            enum_codec = true;
113
-           index_offset = 3;
114
+           index_offset = 1;
115
        }
116
        break;
117
    }
118
@@ -252,8 +233,6 @@
119
        case 0:
120
            param = spa_pod_builder_add_object(&b,
121
                SPA_TYPE_OBJECT_Props, id,
122
-               SPA_PROP_minLatency, SPA_POD_Int(p->min_latency),
123
-               SPA_PROP_maxLatency, SPA_POD_Int(p->max_latency),
124
                SPA_PROP_latencyOffsetNsec, SPA_POD_Long(p->latency_offset));
125
            break;
126
        default:
127
@@ -391,8 +370,6 @@
128
    } else {
129
        spa_pod_parse_object(param,
130
                SPA_TYPE_OBJECT_Props, NULL,
131
-               SPA_PROP_minLatency, SPA_POD_OPT_Int(&new_props.min_latency),
132
-               SPA_PROP_maxLatency, SPA_POD_OPT_Int(&new_props.max_latency),
133
                SPA_PROP_latencyOffsetNsec, SPA_POD_OPT_Long(&new_props.latency_offset));
134
    }
135
 
136
@@ -444,7 +421,7 @@
137
        this->codec_props_changed = false;
138
    }
139
    this->need_flush = 0;
140
-   this->frame_count = 0;
141
+   this->block_count = 0;
142
    this->fragment = false;
143
    this->buffer_used = this->codec->start_encode(this->codec_data,
144
            this->buffer, sizeof(this->buffer),
145
@@ -469,20 +446,32 @@
146
 static int send_buffer(struct impl *this)
147
 {
148
    int written, unsent;
149
+
150
    unsent = get_transport_unused_size(this);
151
    if (unsent >= 0) {
152
        unsent = this->fd_buffer_size - unsent;
153
        this->codec->abr_process(this->codec_data, unsent);
154
    }
155
 
156
-   spa_log_trace(this->log, "%p: send %d %u %u %u %u",
157
-           this, this->frame_count, this->block_size, this->seqnum,
158
-           this->timestamp, this->buffer_used);
159
-
160
    written = send(this->flush_source.fd, this->buffer,
161
            this->buffer_used, MSG_DONTWAIT | MSG_NOSIGNAL);
162
 
163
-   spa_log_trace(this->log, "%p: send %d", this, written);
164
+   if (SPA_UNLIKELY(spa_log_level_topic_enabled(this->log, SPA_LOG_TOPIC_DEFAULT, SPA_LOG_LEVEL_TRACE))) {
165
+       struct timespec ts;
166
+       uint64_t now;
167
+       uint64_t dt;
168
+
169
+       spa_system_clock_gettime(this->data_system, CLOCK_MONOTONIC, &ts);
170
+       now = SPA_TIMESPEC_TO_NSEC(&ts);
171
+       dt = now - this->prev_flush_time;
172
+       this->prev_flush_time = now;
173
+
174
+       spa_log_trace(this->log,
175
+               "%p: send blocks:%d block:%u seq:%u ts:%u size:%u "
176
+               "wrote:%d dt:%"PRIu64,
177
+               this, this->block_count, this->block_size, this->seqnum,
178
+               this->timestamp, this->buffer_used, written, dt);
179
+   }
180
 
181
    if (written < 0) {
182
        spa_log_debug(this->log, "%p: %m", this);
183
@@ -502,7 +491,7 @@
184
 
185
    spa_log_trace(this->log, "%p: encode %d used %d, %d %d %d",
186
            this, size, this->buffer_used, port->frame_size, this->block_size,
187
-           this->frame_count);
188
+           this->block_count);
189
 
190
    if (this->need_flush)
191
        return 0;
192
@@ -530,7 +519,7 @@
193
        return processed;
194
 
195
    this->sample_count += processed / port->frame_size;
196
-   this->frame_count += processed / this->block_size;
197
+   this->block_count += processed / this->block_size;
198
    this->buffer_used += out_encoded;
199
 
200
    spa_log_trace(this->log, "%p: processed %d %zd used %d",
201
pipewire-0.3.59.tar.gz/spa/plugins/bluez5/media-source.c -> pipewire-0.3.60.tar.gz/spa/plugins/bluez5/media-source.c Changed
147
 
1
@@ -276,6 +276,7 @@
2
    struct impl *this = user_data;
3
    struct port *port = &this->port;
4
 
5
+   set_timers(this);
6
    spa_bt_decode_buffer_recover(&port->buffer);
7
    return 0;
8
 }
9
@@ -567,13 +568,14 @@
10
    return 0;
11
 }
12
 
13
+static int produce_buffer(struct impl *this);
14
+
15
 static void media_on_timeout(struct spa_source *source)
16
 {
17
    struct impl *this = source->data;
18
    struct port *port = &this->port;
19
    uint64_t exp, duration;
20
    uint32_t rate;
21
-   struct spa_io_buffers *io = port->io;
22
    uint64_t prev_time, now_time;
23
 
24
    if (this->transport == NULL)
25
@@ -608,8 +610,11 @@
26
        this->clock->next_nsec = this->next_time;
27
    }
28
 
29
-   spa_log_trace(this->log, "%p: %d", this, io->status);
30
-   io->status = SPA_STATUS_HAVE_DATA;
31
+   if (port->io) {
32
+       int status = produce_buffer(this);
33
+       spa_log_trace(this->log, "%p: io:%d status:%d", this, port->io->status, status);
34
+   }
35
+
36
    spa_node_call_ready(&this->callbacks, SPA_STATUS_HAVE_DATA);
37
 
38
    set_timeout(this, this->next_time);
39
@@ -631,10 +636,7 @@
40
 
41
    this->transport_acquired = true;
42
 
43
-   if (this->codec->bap)
44
-       flags = 0;
45
-   else
46
-       flags = this->is_duplex ? 0 : MEDIA_CODEC_FLAG_SINK;
47
+   flags = this->is_duplex ? 0 : MEDIA_CODEC_FLAG_SINK;
48
 
49
    this->codec_data = this->codec->init(this->codec,
50
            flags,
51
@@ -1099,6 +1101,11 @@
52
        if (spa_format_audio_raw_parse(format, &info.info.raw) < 0)
53
            return -EINVAL;
54
 
55
+       if (info.info.raw.rate == 0 ||
56
+           info.info.raw.channels == 0 ||
57
+           info.info.raw.channels > SPA_AUDIO_MAX_CHANNELS)
58
+           return -EINVAL;
59
+
60
        port->frame_size = info.info.raw.channels;
61
 
62
        switch (info.info.raw.format) {
63
@@ -1342,21 +1349,15 @@
64
    }
65
 }
66
 
67
-static int impl_node_process(void *object)
68
+static int produce_buffer(struct impl *this)
69
 {
70
-   struct impl *this = object;
71
-   struct port *port;
72
-   struct spa_io_buffers *io;
73
    struct buffer *buffer;
74
+   struct port *port = &this->port;
75
+   struct spa_io_buffers *io = port->io;
76
 
77
-   spa_return_val_if_fail(this != NULL, -EINVAL);
78
-
79
-   port = &this->port;
80
-   if ((io = port->io) == NULL)
81
+   if (io == NULL)
82
        return -EIO;
83
 
84
-   spa_log_trace(this->log, "%p status:%d", this, io->status);
85
-
86
    /* Return if we already have a buffer */
87
    if (io->status == SPA_STATUS_HAVE_DATA)
88
        return SPA_STATUS_HAVE_DATA;
89
@@ -1367,7 +1368,7 @@
90
        io->buffer_id = SPA_ID_INVALID;
91
    }
92
 
93
-   /* Handle buffering delay */
94
+   /* Handle buffering */
95
    process_buffering(this);
96
 
97
    /* Return if there are no buffers ready to be processed */
98
@@ -1387,6 +1388,37 @@
99
    return SPA_STATUS_HAVE_DATA;
100
 }
101
 
102
+static int impl_node_process(void *object)
103
+{
104
+   struct impl *this = object;
105
+   struct port *port;
106
+   struct spa_io_buffers *io;
107
+
108
+   spa_return_val_if_fail(this != NULL, -EINVAL);
109
+
110
+   port = &this->port;
111
+   if ((io = port->io) == NULL)
112
+       return -EIO;
113
+
114
+   spa_log_trace(this->log, "%p status:%d", this, io->status);
115
+
116
+   /* Return if we already have a buffer */
117
+   if (io->status == SPA_STATUS_HAVE_DATA)
118
+       return SPA_STATUS_HAVE_DATA;
119
+
120
+   /* Recycle */
121
+   if (io->buffer_id < port->n_buffers) {
122
+       recycle_buffer(this, port, io->buffer_id);
123
+       io->buffer_id = SPA_ID_INVALID;
124
+   }
125
+
126
+   /* Follower produces buffers here, driver in timeout */
127
+   if (this->following)
128
+       return produce_buffer(this);
129
+   else
130
+       return SPA_STATUS_OK;
131
+}
132
+
133
 static const struct spa_node_methods impl_node = {
134
    SPA_VERSION_NODE_METHODS,
135
    .add_listener = impl_node_add_listener,
136
@@ -1452,8 +1484,8 @@
137
 {
138
    struct impl *this = (struct impl *) handle;
139
    struct port *port = &this->port;
140
-   if (this->codec_data)
141
-       this->codec->deinit(this->codec_data);
142
+
143
+   do_stop(this);
144
    if (this->codec_props && this->codec->clear_props)
145
        this->codec->clear_props(this->codec_props);
146
    if (this->transport)
147
pipewire-0.3.59.tar.gz/spa/plugins/bluez5/meson.build -> pipewire-0.3.60.tar.gz/spa/plugins/bluez5/meson.build Changed
22
 
1
@@ -10,6 +10,7 @@
2
           get_option('bluez5-backend-hfp-native').allowed())
3
 cdata.set('HAVE_BLUEZ_5_BACKEND_HSP_NATIVE', get_option('bluez5-backend-hsp-native').allowed())
4
 cdata.set('HAVE_BLUEZ_5_BACKEND_HFP_NATIVE', get_option('bluez5-backend-hfp-native').allowed())
5
+cdata.set('HAVE_BLUEZ_5_BACKEND_NATIVE_MM', get_option('bluez5-backend-native-mm').allowed())
6
 cdata.set('HAVE_BLUEZ_5_BACKEND_OFONO', get_option('bluez5-backend-ofono').allowed())
7
 cdata.set('HAVE_BLUEZ_5_BACKEND_HSPHFPD', get_option('bluez5-backend-hsphfpd').allowed())
8
 cdata.set('HAVE_BLUEZ_5_HCI', dependency('bluez', version: '< 6', required: false).found())
9
@@ -38,7 +39,11 @@
10
   if libusb_dep.found()
11
     bluez5_deps += libusb_dep
12
   endif
13
-  bluez5_sources += 'backend-native.c'
14
+  if mm_dep.found()
15
+    bluez5_deps += mm_dep
16
+    bluez5_sources += 'modemmanager.c'
17
+  endif
18
+  bluez5_sources += 'backend-native.c', 'upower.c'
19
 endif
20
 
21
 if get_option('bluez5-backend-ofono').allowed()
22
pipewire-0.3.60.tar.gz/spa/plugins/bluez5/modemmanager.c Added
201
 
1
@@ -0,0 +1,1259 @@
2
+/* Spa Bluez5 ModemManager proxy
3
+ *
4
+ * Copyright © 2022 Collabora
5
+ *
6
+ * Permission is hereby granted, free of charge, to any person obtaining a
7
+ * copy of this software and associated documentation files (the "Software"),
8
+ * to deal in the Software without restriction, including without limitation
9
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10
+ * and/or sell copies of the Software, and to permit persons to whom the
11
+ * Software is furnished to do so, subject to the following conditions:
12
+ *
13
+ * The above copyright notice and this permission notice (including the next
14
+ * paragraph) shall be included in all copies or substantial portions of the
15
+ * Software.
16
+ *
17
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
20
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
23
+ * DEALINGS IN THE SOFTWARE.
24
+ */
25
+
26
+#include <errno.h>
27
+#include <spa/utils/string.h>
28
+
29
+#include <ModemManager.h>
30
+
31
+#include "modemmanager.h"
32
+
33
+#define DBUS_INTERFACE_OBJECTMANAGER "org.freedesktop.DBus.ObjectManager"
34
+
35
+struct modem {
36
+   char *path;
37
+   bool network_has_service;
38
+   unsigned int signal_strength;
39
+};
40
+
41
+struct impl {
42
+   struct spa_bt_monitor *monitor;
43
+
44
+   struct spa_log *log;
45
+   DBusConnection *conn;
46
+
47
+   char *allowed_modem_device;
48
+   bool filters_added;
49
+   DBusPendingCall *pending;
50
+   DBusPendingCall *voice_pending;
51
+
52
+   const struct mm_ops *ops;
53
+   void *user_data;
54
+
55
+   struct modem modem;
56
+   struct spa_list call_list;
57
+};
58
+
59
+struct dbus_cmd_data {
60
+   struct impl *this;
61
+   struct call *call;
62
+   void *user_data;
63
+};
64
+
65
+static bool mm_dbus_connection_send_with_reply(struct impl *this, DBusMessage *m, DBusPendingCall **pending_return,
66
+                                               DBusPendingCallNotifyFunction function, void *user_data)
67
+{
68
+   dbus_bool_t dbus_ret;
69
+
70
+   spa_assert(*pending_return == NULL);
71
+
72
+   dbus_ret = dbus_connection_send_with_reply(this->conn, m, pending_return, -1);
73
+   if (!dbus_ret || *pending_return == NULL) {
74
+       spa_log_debug(this->log, "dbus call failure");
75
+       return false;
76
+   }
77
+
78
+   dbus_ret = dbus_pending_call_set_notify(*pending_return, function, user_data, NULL);
79
+   if (!dbus_ret) {
80
+       spa_log_debug(this->log, "dbus set notify failure");
81
+       dbus_pending_call_cancel(*pending_return);
82
+       dbus_pending_call_unref(*pending_return);
83
+       *pending_return = NULL;
84
+       return false;
85
+   }
86
+
87
+   return true;
88
+}
89
+
90
+static int mm_state_to_clcc(struct impl *this, MMCallState state)
91
+{
92
+   switch (state) {
93
+   case MM_CALL_STATE_DIALING:
94
+       return CLCC_DIALING;
95
+   case MM_CALL_STATE_RINGING_OUT:
96
+       return CLCC_ALERTING;
97
+   case MM_CALL_STATE_RINGING_IN:
98
+       return CLCC_INCOMING;
99
+   case MM_CALL_STATE_ACTIVE:
100
+       return CLCC_ACTIVE;
101
+   case MM_CALL_STATE_HELD:
102
+       return CLCC_HELD;
103
+   case MM_CALL_STATE_WAITING:
104
+       return CLCC_WAITING;
105
+   case MM_CALL_STATE_TERMINATED:
106
+   case MM_CALL_STATE_UNKNOWN:
107
+   default:
108
+       return -1;
109
+   }
110
+}
111
+
112
+static void mm_call_state_changed(struct impl *this)
113
+{
114
+   struct call *call;
115
+   bool call_indicator = false;
116
+   enum call_setup call_setup_indicator = CIND_CALLSETUP_NONE;
117
+
118
+   spa_list_for_each(call, &this->call_list, link) {
119
+       call_indicator |= (call->state == CLCC_ACTIVE);
120
+
121
+       if (call->state == CLCC_INCOMING && call_setup_indicator < CIND_CALLSETUP_INCOMING)
122
+           call_setup_indicator = CIND_CALLSETUP_INCOMING;
123
+       else if (call->state == CLCC_DIALING && call_setup_indicator < CIND_CALLSETUP_DIALING)
124
+           call_setup_indicator = CIND_CALLSETUP_DIALING;
125
+       else if (call->state == CLCC_ALERTING && call_setup_indicator < CIND_CALLSETUP_ALERTING)
126
+           call_setup_indicator = CIND_CALLSETUP_ALERTING;
127
+   }
128
+
129
+   if (this->ops->set_call_active)
130
+       this->ops->set_call_active(call_indicator, this->user_data);
131
+
132
+   if (this->ops->set_call_setup)
133
+       this->ops->set_call_setup(call_setup_indicator, this->user_data);
134
+}
135
+
136
+static void mm_get_call_properties_reply(DBusPendingCall *pending, void *user_data)
137
+{
138
+   struct call *call = user_data;
139
+   struct impl *this = call->this;
140
+   DBusMessage *r;
141
+   DBusMessageIter arg_i, element_i;
142
+   MMCallDirection direction;
143
+   MMCallState state;
144
+
145
+   spa_assert(call->pending == pending);
146
+   dbus_pending_call_unref(pending);
147
+   call->pending = NULL;
148
+
149
+   r = dbus_pending_call_steal_reply(pending);
150
+   if (r == NULL)
151
+       return;
152
+
153
+   if (dbus_message_is_error(r, DBUS_ERROR_UNKNOWN_METHOD)) {
154
+       spa_log_warn(this->log, "ModemManager D-Bus Call not available");
155
+       goto finish;
156
+   }
157
+   if (dbus_message_get_type(r) == DBUS_MESSAGE_TYPE_ERROR) {
158
+       spa_log_error(this->log, "GetAll() failed: %s", dbus_message_get_error_name(r));
159
+       goto finish;
160
+   }
161
+
162
+   if (!dbus_message_iter_init(r, &arg_i) || !spa_streq(dbus_message_get_signature(r), "a{sv}")) {
163
+       spa_log_error(this->log, "Invalid arguments in GetAll() reply");
164
+       goto finish;
165
+   }
166
+
167
+   spa_log_debug(this->log, "Call path: %s", call->path);
168
+
169
+   dbus_message_iter_recurse(&arg_i, &element_i);
170
+   while (dbus_message_iter_get_arg_type(&element_i) != DBUS_TYPE_INVALID) {
171
+       DBusMessageIter i, value_i;
172
+       const char *key;
173
+
174
+       dbus_message_iter_recurse(&element_i, &i);
175
+
176
+       dbus_message_iter_get_basic(&i, &key);
177
+       dbus_message_iter_next(&i);
178
+       dbus_message_iter_recurse(&i, &value_i);
179
+
180
+       if (spa_streq(key, MM_CALL_PROPERTY_DIRECTION)) {
181
+           dbus_message_iter_get_basic(&value_i, &direction);
182
+           spa_log_debug(this->log, "Call direction: %u", direction);
183
+           call->direction = (direction == MM_CALL_DIRECTION_INCOMING) ? CALL_INCOMING : CALL_OUTGOING;
184
+       } else if (spa_streq(key, MM_CALL_PROPERTY_NUMBER)) {
185
+           char *number;
186
+
187
+           dbus_message_iter_get_basic(&value_i, &number);
188
+           spa_log_debug(this->log, "Call number: %s", number);
189
+           if (call->number)
190
+               free(call->number);
191
+           call->number = strdup(number);
192
+       } else if (spa_streq(key, MM_CALL_PROPERTY_STATE)) {
193
+           int clcc_state;
194
+
195
+           dbus_message_iter_get_basic(&value_i, &state);
196
+           spa_log_debug(this->log, "Call state: %u", state);
197
+           clcc_state = mm_state_to_clcc(this, state);
198
+           if (clcc_state < 0) {
199
+               spa_log_debug(this->log, "Unsupported modem state: %s, state=%d", call->path, call->state);
200
+           } else {
201
pipewire-0.3.60.tar.gz/spa/plugins/bluez5/modemmanager.h Added
163
 
1
@@ -0,0 +1,161 @@
2
+/* Spa Bluez5 ModemManager proxy
3
+ *
4
+ * Copyright © 2022 Collabora
5
+ *
6
+ * Permission is hereby granted, free of charge, to any person obtaining a
7
+ * copy of this software and associated documentation files (the "Software"),
8
+ * to deal in the Software without restriction, including without limitation
9
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10
+ * and/or sell copies of the Software, and to permit persons to whom the
11
+ * Software is furnished to do so, subject to the following conditions:
12
+ *
13
+ * The above copyright notice and this permission notice (including the next
14
+ * paragraph) shall be included in all copies or substantial portions of the
15
+ * Software.
16
+ *
17
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
20
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
23
+ * DEALINGS IN THE SOFTWARE.
24
+ */
25
+
26
+#ifndef SPA_BLUEZ5_MODEMMANAGER_H_
27
+#define SPA_BLUEZ5_MODEMMANAGER_H_
28
+
29
+#include <spa/utils/list.h>
30
+
31
+#include "defs.h"
32
+
33
+enum cmee_error {
34
+   CMEE_AG_FAILURE = 0,
35
+   CMEE_NO_CONNECTION_TO_PHONE = 1,
36
+   CMEE_OPERATION_NOT_ALLOWED = 3,
37
+   CMEE_OPERATION_NOT_SUPPORTED = 4,
38
+   CMEE_INVALID_CHARACTERS_TEXT_STRING = 25,
39
+   CMEE_INVALID_CHARACTERS_DIAL_STRING = 27,
40
+   CMEE_NO_NETWORK_SERVICE = 30
41
+};
42
+
43
+enum call_setup {
44
+   CIND_CALLSETUP_NONE = 0,
45
+   CIND_CALLSETUP_INCOMING,
46
+   CIND_CALLSETUP_DIALING,
47
+   CIND_CALLSETUP_ALERTING
48
+};
49
+
50
+enum call_direction {
51
+   CALL_OUTGOING,
52
+   CALL_INCOMING
53
+};
54
+
55
+enum call_state {
56
+   CLCC_ACTIVE,
57
+   CLCC_HELD,
58
+   CLCC_DIALING,
59
+   CLCC_ALERTING,
60
+   CLCC_INCOMING,
61
+   CLCC_WAITING,
62
+   CLCC_RESPONSE_AND_HOLD
63
+};
64
+
65
+struct call {
66
+   struct spa_list link;
67
+   unsigned int index;
68
+   struct impl *this;
69
+   DBusPendingCall *pending;
70
+
71
+   char *path;
72
+   char *number;
73
+   bool call_indicator;
74
+   enum call_direction direction;
75
+   enum call_state state;
76
+   bool multiparty;
77
+};
78
+
79
+struct mm_ops {
80
+   void (*send_cmd_result)(bool success, enum cmee_error error, void *user_data);
81
+   void (*set_modem_service)(bool available, void *user_data);
82
+   void (*set_modem_signal_strength)(unsigned int strength, void *user_data);
83
+   void (*set_modem_operator_name)(const char *name, void *user_data);
84
+   void (*set_modem_own_number)(const char *number, void *user_data);
85
+   void (*set_modem_roaming)(bool is_roaming, void *user_data);
86
+   void (*set_call_active)(bool active, void *user_data);
87
+   void (*set_call_setup)(enum call_setup value, void *user_data);
88
+};
89
+
90
+#ifdef HAVE_BLUEZ_5_BACKEND_NATIVE_MM
91
+void *mm_register(struct spa_log *log, void *dbus_connection, const struct spa_dict *info,
92
+                  const struct mm_ops *ops, void *user_data);
93
+void mm_unregister(void *data);
94
+bool mm_is_available(void *modemmanager);
95
+unsigned int mm_supported_features();
96
+bool mm_answer_call(void *modemmanager, void *user_data, enum cmee_error *error);
97
+bool mm_hangup_call(void *modemmanager, void *user_data, enum cmee_error *error);
98
+bool mm_do_call(void *modemmanager, const char* number, void *user_data, enum cmee_error *error);
99
+bool mm_send_dtmf(void *modemmanager, const char *dtmf, void *user_data, enum cmee_error *error);
100
+const char *mm_get_incoming_call_number(void *modemmanager);
101
+struct spa_list *mm_get_calls(void *modemmanager);
102
+#else
103
+void *mm_register(struct spa_log *log, void *dbus_connection, const struct spa_dict *info,
104
+                  const struct mm_ops *ops, void *user_data)
105
+{
106
+   return NULL;
107
+}
108
+
109
+void mm_unregister(void *data)
110
+{
111
+}
112
+
113
+bool mm_is_available(void *modemmanager)
114
+{
115
+   return false;
116
+}
117
+
118
+unsigned int mm_supported_features(void)
119
+{
120
+   return 0;
121
+}
122
+
123
+bool mm_answer_call(void *modemmanager, void *user_data, enum cmee_error *error)
124
+{
125
+   if (error)
126
+       *error = CMEE_OPERATION_NOT_SUPPORTED;
127
+   return false;
128
+}
129
+
130
+bool mm_hangup_call(void *modemmanager, void *user_data, enum cmee_error *error)
131
+{
132
+   if (error)
133
+       *error = CMEE_OPERATION_NOT_SUPPORTED;
134
+   return false;
135
+}
136
+
137
+bool mm_do_call(void *modemmanager, const char* number, void *user_data, enum cmee_error *error)
138
+{
139
+   if (error)
140
+       *error = CMEE_OPERATION_NOT_SUPPORTED;
141
+   return false;
142
+}
143
+
144
+bool mm_send_dtmf(void *modemmanager, const char *dtmf, void *user_data, enum cmee_error *error)
145
+{
146
+   if (error)
147
+       *error = CMEE_OPERATION_NOT_SUPPORTED;
148
+   return false;
149
+}
150
+
151
+const char *mm_get_incoming_call_number(void *modemmanager)
152
+{
153
+   return NULL;
154
+}
155
+
156
+struct spa_list *mm_get_calls(void *modemmanager)
157
+{
158
+   return NULL;
159
+}
160
+#endif
161
+
162
+#endif
163
pipewire-0.3.59.tar.gz/spa/plugins/bluez5/quirks.c -> pipewire-0.3.60.tar.gz/spa/plugins/bluez5/quirks.c Changed
15
 
1
@@ -88,10 +88,9 @@
2
        { "faststream", SPA_BT_FEATURE_FASTSTREAM },
3
        { "a2dp-duplex", SPA_BT_FEATURE_A2DP_DUPLEX },
4
    };
5
-   size_t i;
6
-   for (i = 0; i < SPA_N_ELEMENTS(feature_keys); ++i) {
7
-       if (spa_streq(str, feature_keysi.key))
8
-           return feature_keysi.value;
9
+   SPA_FOR_EACH_ELEMENT_VAR(feature_keys, f) {
10
+       if (spa_streq(str, f->key))
11
+           return f->value;
12
    }
13
    return 0;
14
 }
15
pipewire-0.3.59.tar.gz/spa/plugins/bluez5/sco-sink.c -> pipewire-0.3.60.tar.gz/spa/plugins/bluez5/sco-sink.c Changed
201
 
1
@@ -60,14 +60,10 @@
2
 #define DEFAULT_CLOCK_NAME "clock.system.monotonic"
3
 
4
 struct props {
5
-   uint32_t min_latency;
6
-   uint32_t max_latency;
7
    char clock_name64;
8
 };
9
 
10
 #define MAX_BUFFERS 32
11
-#define MIN_LATENCY    512
12
-#define MAX_LATENCY    1024
13
 
14
 struct buffer {
15
    uint32_t id;
16
@@ -130,6 +126,8 @@
17
    struct spa_param_info paramsN_NODE_PARAMS;
18
    struct props props;
19
 
20
+   uint32_t quantum_limit;
21
+
22
    /* Transport */
23
    struct spa_bt_transport *transport;
24
    struct spa_hook transport_listener;
25
@@ -140,38 +138,39 @@
26
    /* Flags */
27
    unsigned int started:1;
28
    unsigned int following:1;
29
+   unsigned int flush_pending:1;
30
 
31
    /* Sources */
32
    struct spa_source source;
33
+   struct spa_source flush_timer_source;
34
 
35
    /* Timer */
36
    int timerfd;
37
-   struct timespec now;
38
+   int flush_timerfd;
39
    struct spa_io_clock *clock;
40
    struct spa_io_position *position;
41
 
42
+   uint64_t current_time;
43
+   uint64_t next_time;
44
+   uint64_t process_time;
45
+   uint64_t prev_flush_time;
46
+   uint64_t next_flush_time;
47
+
48
    /* mSBC */
49
    sbc_t msbc;
50
    uint8_t *buffer;
51
    uint8_t *buffer_head;
52
    uint8_t *buffer_next;
53
    int buffer_size;
54
-
55
-   /* Times */
56
-   uint64_t start_time;
57
-   uint64_t total_samples;
58
+   int msbc_seq;
59
 };
60
 
61
 #define CHECK_PORT(this,d,p)   ((d) == SPA_DIRECTION_INPUT && (p) == 0)
62
 
63
-static const uint32_t default_min_latency = MIN_LATENCY;
64
-static const uint32_t default_max_latency = MAX_LATENCY;
65
 static const char sntable4 = { 0x08, 0x38, 0xC8, 0xF8 };
66
 
67
 static void reset_props(struct props *props)
68
 {
69
-   props->min_latency = default_min_latency;
70
-   props->max_latency = default_max_latency;
71
    strncpy(props->clock_name, DEFAULT_CLOCK_NAME, sizeof(props->clock_name));
72
 }
73
 
74
@@ -199,23 +198,7 @@
75
    switch (id) {
76
    case SPA_PARAM_PropInfo:
77
    {
78
-       struct props *p = &this->props;
79
-
80
        switch (result.index) {
81
-       case 0:
82
-           param = spa_pod_builder_add_object(&b,
83
-               SPA_TYPE_OBJECT_PropInfo, id,
84
-               SPA_PROP_INFO_id,   SPA_POD_Id(SPA_PROP_minLatency),
85
-               SPA_PROP_INFO_description, SPA_POD_String("The minimum latency"),
86
-               SPA_PROP_INFO_type, SPA_POD_CHOICE_RANGE_Int(p->min_latency, 1, INT32_MAX));
87
-           break;
88
-       case 1:
89
-           param = spa_pod_builder_add_object(&b,
90
-               SPA_TYPE_OBJECT_PropInfo, id,
91
-               SPA_PROP_INFO_id,   SPA_POD_Id(SPA_PROP_maxLatency),
92
-               SPA_PROP_INFO_description, SPA_POD_String("The maximum latency"),
93
-               SPA_PROP_INFO_type, SPA_POD_CHOICE_RANGE_Int(p->max_latency, 1, INT32_MAX));
94
-           break;
95
        default:
96
            return 0;
97
        }
98
@@ -223,14 +206,10 @@
99
    }
100
    case SPA_PARAM_Props:
101
    {
102
-       struct props *p = &this->props;
103
-
104
        switch (result.index) {
105
        case 0:
106
            param = spa_pod_builder_add_object(&b,
107
-               SPA_TYPE_OBJECT_Props, id,
108
-               SPA_PROP_minLatency, SPA_POD_Int(p->min_latency),
109
-               SPA_PROP_maxLatency, SPA_POD_Int(p->max_latency));
110
+               SPA_TYPE_OBJECT_Props, id);
111
            break;
112
        default:
113
            return 0;
114
@@ -260,28 +239,17 @@
115
    ts.it_interval.tv_sec = 0;
116
    ts.it_interval.tv_nsec = 0;
117
    return spa_system_timerfd_settime(this->data_system,
118
-           this->timerfd, 0, &ts, NULL);
119
+           this->timerfd, SPA_FD_TIMER_ABSTIME, &ts, NULL);
120
 }
121
 
122
 static int set_timers(struct impl *this)
123
 {
124
-   return set_timeout(this, this->following ? 0 : 1);
125
-}
126
-
127
-static uint64_t get_next_timeout(struct impl *this, uint64_t now_time, uint64_t processed_samples)
128
-{
129
-   struct port *port = &this->port;
130
-   uint64_t playback_time = 0, elapsed_time = 0, next_time = 0;
131
-
132
-   this->total_samples += processed_samples;
133
+   struct timespec now;
134
 
135
-   playback_time = (this->total_samples * SPA_NSEC_PER_SEC) / port->current_format.info.raw.rate;
136
-   if (now_time > this->start_time)
137
-       elapsed_time = now_time - this->start_time;
138
-   if (elapsed_time < playback_time)
139
-       next_time = playback_time - elapsed_time;
140
+   spa_system_clock_gettime(this->data_system, CLOCK_MONOTONIC, &now);
141
+   this->next_time = SPA_TIMESPEC_TO_NSEC(&now);
142
 
143
-   return next_time;
144
+   return set_timeout(this, this->following ? 0 : this->next_time);
145
 }
146
 
147
 static int do_reassign_follower(struct spa_loop *loop,
148
@@ -344,9 +312,7 @@
149
        reset_props(&new_props);
150
    } else {
151
        spa_pod_parse_object(param,
152
-               SPA_TYPE_OBJECT_Props, NULL,
153
-               SPA_PROP_minLatency, SPA_POD_OPT_Int(&new_props.min_latency),
154
-               SPA_PROP_maxLatency, SPA_POD_OPT_Int(&new_props.max_latency));
155
+               SPA_TYPE_OBJECT_Props, NULL);
156
    }
157
 
158
    changed = (memcmp(&new_props, &this->props, sizeof(struct props)) != 0);
159
@@ -378,22 +344,64 @@
160
    return 0;
161
 }
162
 
163
+static void enable_flush_timer(struct impl *this, bool enabled)
164
+{
165
+   struct itimerspec ts;
166
+
167
+   if (!enabled)
168
+       this->next_flush_time = 0;
169
+
170
+   ts.it_value.tv_sec = this->next_flush_time / SPA_NSEC_PER_SEC;
171
+   ts.it_value.tv_nsec = this->next_flush_time % SPA_NSEC_PER_SEC;
172
+   ts.it_interval.tv_sec = 0;
173
+   ts.it_interval.tv_nsec = 0;
174
+   spa_system_timerfd_settime(this->data_system,
175
+           this->flush_timerfd, SPA_FD_TIMER_ABSTIME, &ts, NULL);
176
+
177
+   this->flush_pending = enabled;
178
+}
179
+
180
+static uint32_t get_queued_frames(struct impl *this)
181
+{
182
+   struct port *port = &this->port;
183
+   uint32_t bytes = 0;
184
+   struct buffer *b;
185
+
186
+   spa_list_for_each(b, &port->ready, link) {
187
+       struct spa_data *d = b->buf->datas;
188
+
189
+       bytes += d0.chunk->size;
190
+   }
191
+
192
+   if (bytes > port->ready_offset)
193
+       bytes -= port->ready_offset;
194
+   else
195
+       bytes = 0;
196
+
197
+   return bytes / port->frame_size;
198
+}
199
+
200
 static void flush_data(struct impl *this)
201
pipewire-0.3.59.tar.gz/spa/plugins/bluez5/sco-source.c -> pipewire-0.3.60.tar.gz/spa/plugins/bluez5/sco-source.c Changed
127
 
1
@@ -248,6 +248,7 @@
2
    struct impl *this = user_data;
3
    struct port *port = &this->port;
4
 
5
+   set_timers(this);
6
    spa_bt_decode_buffer_recover(&port->buffer);
7
    return 0;
8
 }
9
@@ -590,13 +591,14 @@
10
    return 0;
11
 }
12
 
13
+static int produce_buffer(struct impl *this);
14
+
15
 static void sco_on_timeout(struct spa_source *source)
16
 {
17
    struct impl *this = source->data;
18
    struct port *port = &this->port;
19
    uint64_t exp, duration;
20
    uint32_t rate;
21
-   struct spa_io_buffers *io = port->io;
22
    uint64_t prev_time, now_time;
23
 
24
    if (this->transport == NULL)
25
@@ -631,8 +633,11 @@
26
        this->clock->next_nsec = this->next_time;
27
    }
28
 
29
-   spa_log_trace(this->log, "%p: %d", this, io->status);
30
-   io->status = SPA_STATUS_HAVE_DATA;
31
+   if (port->io) {
32
+       int status = produce_buffer(this);
33
+       spa_log_trace(this->log, "%p: io:%d status:%d", this, port->io->status, status);
34
+   }
35
+
36
    spa_node_call_ready(&this->callbacks, SPA_STATUS_HAVE_DATA);
37
 
38
    set_timeout(this, this->next_time);
39
@@ -1068,6 +1073,11 @@
40
        if (spa_format_audio_raw_parse(format, &info.info.raw) < 0)
41
            return -EINVAL;
42
 
43
+       if (info.info.raw.format != SPA_AUDIO_FORMAT_S16_LE ||
44
+           info.info.raw.rate == 0 ||
45
+           info.info.raw.channels != 1)
46
+           return -EINVAL;
47
+
48
        port->frame_size = info.info.raw.channels * 2;
49
        port->current_format = info;
50
        port->have_format = true;
51
@@ -1285,17 +1295,13 @@
52
    }
53
 }
54
 
55
-static int impl_node_process(void *object)
56
+static int produce_buffer(struct impl *this)
57
 {
58
-   struct impl *this = object;
59
-   struct port *port;
60
-   struct spa_io_buffers *io;
61
    struct buffer *buffer;
62
+   struct port *port = &this->port;
63
+   struct spa_io_buffers *io = port->io;
64
 
65
-   spa_return_val_if_fail(this != NULL, -EINVAL);
66
-
67
-   port = &this->port;
68
-   if ((io = port->io) == NULL)
69
+   if (io == NULL)
70
        return -EIO;
71
 
72
    /* Return if we already have a buffer */
73
@@ -1308,7 +1314,7 @@
74
        io->buffer_id = SPA_ID_INVALID;
75
    }
76
 
77
-   /* Produce data */
78
+   /* Handle buffering */
79
    process_buffering(this);
80
 
81
    /* Return if there are no buffers ready to be processed */
82
@@ -1328,6 +1334,35 @@
83
    return SPA_STATUS_HAVE_DATA;
84
 }
85
 
86
+static int impl_node_process(void *object)
87
+{
88
+   struct impl *this = object;
89
+   struct port *port;
90
+   struct spa_io_buffers *io;
91
+
92
+   spa_return_val_if_fail(this != NULL, -EINVAL);
93
+
94
+   port = &this->port;
95
+   if ((io = port->io) == NULL)
96
+       return -EIO;
97
+
98
+   /* Return if we already have a buffer */
99
+   if (io->status == SPA_STATUS_HAVE_DATA)
100
+       return SPA_STATUS_HAVE_DATA;
101
+
102
+   /* Recycle */
103
+   if (io->buffer_id < port->n_buffers) {
104
+       recycle_buffer(this, port, io->buffer_id);
105
+       io->buffer_id = SPA_ID_INVALID;
106
+   }
107
+
108
+   /* Follower produces buffers here, driver in timeout */
109
+   if (this->following)
110
+       return produce_buffer(this);
111
+   else
112
+       return SPA_STATUS_OK;
113
+}
114
+
115
 static const struct spa_node_methods impl_node = {
116
    SPA_VERSION_NODE_METHODS,
117
    .add_listener = impl_node_add_listener,
118
@@ -1391,6 +1426,8 @@
119
 static int impl_clear(struct spa_handle *handle)
120
 {
121
    struct impl *this = (struct impl *) handle;
122
+
123
+   do_stop(this);
124
    if (this->transport)
125
        spa_hook_remove(&this->transport_listener);
126
    spa_system_close(this->data_system, this->timerfd);
127
pipewire-0.3.60.tar.gz/spa/plugins/bluez5/upower.c Added
201
 
1
@@ -0,0 +1,311 @@
2
+/* Spa Bluez5 UPower proxy
3
+ *
4
+ * Copyright © 2022 Collabora
5
+ *
6
+ * Permission is hereby granted, free of charge, to any person obtaining a
7
+ * copy of this software and associated documentation files (the "Software"),
8
+ * to deal in the Software without restriction, including without limitation
9
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10
+ * and/or sell copies of the Software, and to permit persons to whom the
11
+ * Software is furnished to do so, subject to the following conditions:
12
+ *
13
+ * The above copyright notice and this permission notice (including the next
14
+ * paragraph) shall be included in all copies or substantial portions of the
15
+ * Software.
16
+ *
17
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
20
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
23
+ * DEALINGS IN THE SOFTWARE.
24
+ */
25
+
26
+#include <errno.h>
27
+#include <spa/utils/string.h>
28
+
29
+#include "upower.h"
30
+
31
+#define UPOWER_SERVICE "org.freedesktop.UPower"
32
+#define UPOWER_DEVICE_INTERFACE UPOWER_SERVICE ".Device"
33
+#define UPOWER_DISPLAY_DEVICE_OBJECT "/org/freedesktop/UPower/devices/DisplayDevice"
34
+
35
+struct impl {
36
+   struct spa_bt_monitor *monitor;
37
+
38
+   struct spa_log *log;
39
+   DBusConnection *conn;
40
+
41
+   bool filters_added;
42
+
43
+   void *user_data;
44
+   void (*set_battery_level)(unsigned int level, void *user_data);
45
+};
46
+
47
+static DBusHandlerResult upower_parse_percentage(struct impl *this, DBusMessageIter *variant_i)
48
+{
49
+   double percentage;
50
+   unsigned int battery_level;
51
+
52
+   dbus_message_iter_get_basic(variant_i, &percentage);
53
+   spa_log_debug(this->log, "Battery level: %f %%", percentage);
54
+
55
+   battery_level = (unsigned int) round(percentage / 20.0);
56
+   this->set_battery_level(battery_level, this->user_data);
57
+
58
+   return DBUS_HANDLER_RESULT_HANDLED;
59
+}
60
+
61
+static void upower_get_percentage_properties_reply(DBusPendingCall *pending, void *user_data)
62
+{
63
+   struct impl *backend = user_data;
64
+   DBusMessage *r;
65
+   DBusMessageIter i, variant_i;
66
+
67
+   r = dbus_pending_call_steal_reply(pending);
68
+   if (r == NULL)
69
+       return;
70
+
71
+   if (dbus_message_get_type(r) == DBUS_MESSAGE_TYPE_ERROR) {
72
+       spa_log_error(backend->log, "Failed to get percentage from UPower: %s",
73
+               dbus_message_get_error_name(r));
74
+       goto finish;
75
+   }
76
+
77
+   if (!dbus_message_iter_init(r, &i) || !spa_streq(dbus_message_get_signature(r), "v")) {
78
+       spa_log_error(backend->log, "Invalid arguments in Get() reply");
79
+       goto finish;
80
+   }
81
+
82
+   dbus_message_iter_recurse(&i, &variant_i);
83
+   upower_parse_percentage(backend, &variant_i);
84
+
85
+finish:
86
+   dbus_message_unref(r);
87
+}
88
+
89
+static void upower_clean(struct impl *this)
90
+{
91
+   this->set_battery_level(0, this->user_data);
92
+}
93
+
94
+static DBusHandlerResult upower_filter_cb(DBusConnection *bus, DBusMessage *m, void *user_data)
95
+{
96
+   struct impl *this = user_data;
97
+   DBusError err;
98
+
99
+   dbus_error_init(&err);
100
+
101
+   if (dbus_message_is_signal(m, "org.freedesktop.DBus", "NameOwnerChanged")) {
102
+       const char *name, *old_owner, *new_owner;
103
+
104
+       spa_log_debug(this->log, "Name owner changed %s", dbus_message_get_path(m));
105
+
106
+       if (!dbus_message_get_args(m, &err,
107
+                      DBUS_TYPE_STRING, &name,
108
+                      DBUS_TYPE_STRING, &old_owner,
109
+                      DBUS_TYPE_STRING, &new_owner,
110
+                      DBUS_TYPE_INVALID)) {
111
+           spa_log_error(this->log, "Failed to parse org.freedesktop.DBus.NameOwnerChanged: %s", err.message);
112
+           goto finish;
113
+       }
114
+
115
+       if (spa_streq(name, UPOWER_SERVICE)) {
116
+           if (old_owner && *old_owner) {
117
+               spa_log_debug(this->log, "UPower daemon disappeared (%s)", old_owner);
118
+               upower_clean(this);
119
+           }
120
+
121
+           if (new_owner && *new_owner) {
122
+               DBusPendingCall *call;
123
+               static const char* upower_device_interface = UPOWER_DEVICE_INTERFACE;
124
+               static const char* percentage_property = "Percentage";
125
+
126
+               spa_log_debug(this->log, "UPower daemon appeared (%s)", new_owner);
127
+
128
+               m = dbus_message_new_method_call(UPOWER_SERVICE, UPOWER_DISPLAY_DEVICE_OBJECT, DBUS_INTERFACE_PROPERTIES, "Get");
129
+               if (m == NULL)
130
+                   goto finish;
131
+               dbus_message_append_args(m, DBUS_TYPE_STRING, &upower_device_interface,
132
+                                DBUS_TYPE_STRING, &percentage_property, DBUS_TYPE_INVALID);
133
+               dbus_connection_send_with_reply(this->conn, m, &call, -1);
134
+               dbus_pending_call_set_notify(call, upower_get_percentage_properties_reply, this, NULL);
135
+               dbus_message_unref(m);
136
+           }
137
+       }
138
+   } else if (dbus_message_is_signal(m, DBUS_INTERFACE_PROPERTIES, DBUS_SIGNAL_PROPERTIES_CHANGED)) {
139
+       const char *path;
140
+       DBusMessageIter iface_i, props_i;
141
+       const char *interface;
142
+
143
+       if (!dbus_message_iter_init(m, &iface_i) || !spa_streq(dbus_message_get_signature(m), "sa{sv}as")) {
144
+               spa_log_error(this->log, "Invalid signature found in PropertiesChanged");
145
+               goto finish;
146
+       }
147
+
148
+       dbus_message_iter_get_basic(&iface_i, &interface);
149
+       dbus_message_iter_next(&iface_i);
150
+       spa_assert(dbus_message_iter_get_arg_type(&iface_i) == DBUS_TYPE_ARRAY);
151
+
152
+       dbus_message_iter_recurse(&iface_i, &props_i);
153
+
154
+       path = dbus_message_get_path(m);
155
+
156
+       if (spa_streq(interface, UPOWER_DEVICE_INTERFACE)) {
157
+           spa_log_debug(this->log, "Properties changed on %s", path);
158
+
159
+           while (dbus_message_iter_get_arg_type(&props_i) != DBUS_TYPE_INVALID) {
160
+               DBusMessageIter i, value_i;
161
+               const char *key;
162
+
163
+               dbus_message_iter_recurse(&props_i, &i);
164
+
165
+               dbus_message_iter_get_basic(&i, &key);
166
+               dbus_message_iter_next(&i);
167
+               dbus_message_iter_recurse(&i, &value_i);
168
+
169
+               if(spa_streq(key, "Percentage"))
170
+                   upower_parse_percentage(this, &value_i);
171
+
172
+               dbus_message_iter_next(&props_i);
173
+           }
174
+       }
175
+   }
176
+
177
+finish:
178
+   return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
179
+}
180
+
181
+static int add_filters(struct impl *this)
182
+{
183
+   DBusError err;
184
+
185
+   if (this->filters_added)
186
+       return 0;
187
+
188
+   dbus_error_init(&err);
189
+
190
+   if (!dbus_connection_add_filter(this->conn, upower_filter_cb, this, NULL)) {
191
+       spa_log_error(this->log, "failed to add filter function");
192
+       goto fail;
193
+   }
194
+
195
+   dbus_bus_add_match(this->conn,
196
+           "type='signal',sender='org.freedesktop.DBus',"
197
+           "interface='org.freedesktop.DBus',member='NameOwnerChanged'," "arg0='" UPOWER_SERVICE "'", &err);
198
+   dbus_bus_add_match(this->conn,
199
+           "type='signal',sender='" UPOWER_SERVICE "',"
200
+           "interface='" DBUS_INTERFACE_PROPERTIES "',member='" DBUS_SIGNAL_PROPERTIES_CHANGED "',"
201
pipewire-0.3.60.tar.gz/spa/plugins/bluez5/upower.h Added
39
 
1
@@ -0,0 +1,36 @@
2
+/* Spa Bluez5 UPower proxy
3
+ *
4
+ * Copyright © 2022 Collabora
5
+ *
6
+ * Permission is hereby granted, free of charge, to any person obtaining a
7
+ * copy of this software and associated documentation files (the "Software"),
8
+ * to deal in the Software without restriction, including without limitation
9
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10
+ * and/or sell copies of the Software, and to permit persons to whom the
11
+ * Software is furnished to do so, subject to the following conditions:
12
+ *
13
+ * The above copyright notice and this permission notice (including the next
14
+ * paragraph) shall be included in all copies or substantial portions of the
15
+ * Software.
16
+ *
17
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
20
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
23
+ * DEALINGS IN THE SOFTWARE.
24
+ */
25
+
26
+#ifndef SPA_BLUEZ5_UPOWER_H_
27
+#define SPA_BLUEZ5_UPOWER_H_
28
+
29
+#include "defs.h"
30
+
31
+void *upower_register(struct spa_log *log,
32
+                      void *dbus_connection,
33
+                      void (*set_battery_level)(unsigned int level, void *user_data),
34
+                      void *user_data);
35
+void upower_unregister(void *data);
36
+
37
+#endif
38
\ No newline at end of file
39
pipewire-0.3.59.tar.gz/spa/plugins/libcamera/libcamera-source.cpp -> pipewire-0.3.60.tar.gz/spa/plugins/libcamera/libcamera-source.cpp Changed
201
 
1
@@ -112,7 +112,14 @@
2
    struct spa_port_info info = SPA_PORT_INFO_INIT();
3
    struct spa_io_buffers *io = nullptr;
4
    struct spa_io_sequence *control = nullptr;
5
-   struct spa_param_info params8;
6
+#define PORT_PropInfo  0
7
+#define PORT_EnumFormat    1
8
+#define PORT_Meta  2
9
+#define PORT_IO        3
10
+#define PORT_Format    4
11
+#define PORT_Buffers   5
12
+#define N_PORT_PARAMS  6
13
+   struct spa_param_info paramsN_PORT_PARAMS;
14
 
15
    uint32_t fmt_index = 0;
16
    PixelFormat enum_fmt;
17
@@ -123,16 +130,16 @@
18
    {
19
        spa_list_init(&queue);
20
 
21
-       params0 = SPA_PARAM_INFO(SPA_PARAM_PropInfo, SPA_PARAM_INFO_READ);
22
-       params1 = SPA_PARAM_INFO(SPA_PARAM_EnumFormat, SPA_PARAM_INFO_READ);
23
-       params2 = SPA_PARAM_INFO(SPA_PARAM_Meta, SPA_PARAM_INFO_READ);
24
-       params3 = SPA_PARAM_INFO(SPA_PARAM_IO, SPA_PARAM_INFO_READ);
25
-       params4 = SPA_PARAM_INFO(SPA_PARAM_Format, SPA_PARAM_INFO_WRITE);
26
-       params5 = SPA_PARAM_INFO(SPA_PARAM_Buffers, 0);
27
+       paramsPORT_PropInfo = SPA_PARAM_INFO(SPA_PARAM_PropInfo, SPA_PARAM_INFO_READ);
28
+       paramsPORT_EnumFormat = SPA_PARAM_INFO(SPA_PARAM_EnumFormat, SPA_PARAM_INFO_READ);
29
+       paramsPORT_Meta = SPA_PARAM_INFO(SPA_PARAM_Meta, SPA_PARAM_INFO_READ);
30
+       paramsPORT_IO = SPA_PARAM_INFO(SPA_PARAM_IO, SPA_PARAM_INFO_READ);
31
+       paramsPORT_Format = SPA_PARAM_INFO(SPA_PARAM_Format, SPA_PARAM_INFO_WRITE);
32
+       paramsPORT_Buffers = SPA_PARAM_INFO(SPA_PARAM_Buffers, 0);
33
 
34
        info.flags = SPA_PORT_FLAG_LIVE | SPA_PORT_FLAG_PHYSICAL | SPA_PORT_FLAG_TERMINAL;
35
        info.params = params;
36
-       info.n_params = 6;
37
+       info.n_params = N_PORT_PARAMS;
38
    }
39
 };
40
 
41
@@ -149,7 +156,12 @@
42
        SPA_NODE_CHANGE_MASK_PROPS |
43
        SPA_NODE_CHANGE_MASK_PARAMS;
44
    struct spa_node_info info = SPA_NODE_INFO_INIT();
45
-   struct spa_param_info params8;
46
+#define NODE_PropInfo  0
47
+#define NODE_Props 1
48
+#define NODE_EnumFormat    2
49
+#define NODE_Format    3
50
+#define N_NODE_PARAMS  4
51
+   struct spa_param_info paramsN_NODE_PARAMS;
52
 
53
    std::string device_id;
54
    std::string device_name;
55
@@ -175,6 +187,7 @@
56
 
57
    struct spa_source source = {};
58
 
59
+   ControlList ctrls;
60
    bool active = false;
61
    bool acquired = false;
62
 
63
@@ -191,6 +204,55 @@
64
 
65
 #include "libcamera-utils.cpp"
66
 
67
+static int port_get_format(struct impl *impl, struct port *port,
68
+              uint32_t index,
69
+              const struct spa_pod *filter,
70
+              struct spa_pod **param,
71
+              struct spa_pod_builder *builder)
72
+{
73
+   struct spa_pod_frame f;
74
+
75
+   if (!port->current_format)
76
+       return -EIO;
77
+   if (index > 0)
78
+       return 0;
79
+
80
+   spa_pod_builder_push_object(builder, &f, SPA_TYPE_OBJECT_Format, SPA_PARAM_Format);
81
+   spa_pod_builder_add(builder,
82
+       SPA_FORMAT_mediaType,    SPA_POD_Id(port->current_format->media_type),
83
+       SPA_FORMAT_mediaSubtype, SPA_POD_Id(port->current_format->media_subtype),
84
+       0);
85
+
86
+   switch (port->current_format->media_subtype) {
87
+   case SPA_MEDIA_SUBTYPE_raw:
88
+       spa_pod_builder_add(builder,
89
+           SPA_FORMAT_VIDEO_format,    SPA_POD_Id(port->current_format->info.raw.format),
90
+           SPA_FORMAT_VIDEO_size,      SPA_POD_Rectangle(&port->current_format->info.raw.size),
91
+           SPA_FORMAT_VIDEO_framerate, SPA_POD_Fraction(&port->current_format->info.raw.framerate),
92
+           0);
93
+       break;
94
+   case SPA_MEDIA_SUBTYPE_mjpg:
95
+   case SPA_MEDIA_SUBTYPE_jpeg:
96
+       spa_pod_builder_add(builder,
97
+           SPA_FORMAT_VIDEO_size,      SPA_POD_Rectangle(&port->current_format->info.mjpg.size),
98
+           SPA_FORMAT_VIDEO_framerate, SPA_POD_Fraction(&port->current_format->info.mjpg.framerate),
99
+           0);
100
+       break;
101
+   case SPA_MEDIA_SUBTYPE_h264:
102
+       spa_pod_builder_add(builder,
103
+           SPA_FORMAT_VIDEO_size,      SPA_POD_Rectangle(&port->current_format->info.h264.size),
104
+           SPA_FORMAT_VIDEO_framerate, SPA_POD_Fraction(&port->current_format->info.h264.framerate),
105
+           0);
106
+       break;
107
+   default:
108
+       return -EIO;
109
+   }
110
+
111
+   *param = (struct spa_pod*)spa_pod_builder_pop(builder, &f);
112
+
113
+   return 1;
114
+}
115
+
116
 static int impl_node_enum_params(void *object, int seq,
117
                 uint32_t id, uint32_t start, uint32_t num,
118
                 const struct spa_pod *filter)
119
@@ -201,6 +263,7 @@
120
    uint8_t buffer1024;
121
    struct spa_result_node_params result;
122
    uint32_t count = 0;
123
+   int res;
124
 
125
    spa_return_val_if_fail(impl != NULL, -EINVAL);
126
    spa_return_val_if_fail(num != 0, -EINVAL);
127
@@ -231,7 +294,9 @@
128
                SPA_PROP_INFO_type, SPA_POD_String(impl->device_name.c_str()));
129
            break;
130
        default:
131
-           return 0;
132
+           return spa_libcamera_enum_controls(impl,
133
+                   GET_OUT_PORT(impl, 0),
134
+                   seq, result.index - 2, num, filter);
135
        }
136
        break;
137
    }
138
@@ -249,6 +314,13 @@
139
        }
140
        break;
141
    }
142
+   case SPA_PARAM_EnumFormat:
143
+       return spa_libcamera_enum_format(impl, GET_OUT_PORT(impl, 0),
144
+               seq, start, num, filter);
145
+   case SPA_PARAM_Format:
146
+       if ((res = port_get_format(impl, GET_OUT_PORT(impl, 0), result.index, filter, &param, &b)) <= 0)
147
+           return res;
148
+       break;
149
    default:
150
        return -ENOENT;
151
    }
152
@@ -275,22 +347,28 @@
153
    switch (id) {
154
    case SPA_PARAM_Props:
155
    {
156
+       struct spa_pod_object *obj = (struct spa_pod_object *) param;
157
+       struct spa_pod_prop *prop;
158
+
159
        if (param == NULL) {
160
            impl->device_id.clear();
161
            impl->device_name.clear();
162
            return 0;
163
        }
164
-
165
-       char device128;
166
-       int res = spa_pod_parse_object(param,
167
-           SPA_TYPE_OBJECT_Props, NULL,
168
-           SPA_PROP_device, SPA_POD_OPT_Stringn(device, sizeof(device)));
169
-
170
-       if (res < 0)
171
-           return res;
172
-
173
-       impl->device_id = device;
174
-
175
+       SPA_POD_OBJECT_FOREACH(obj, prop) {
176
+           char device128;
177
+
178
+           switch (prop->key) {
179
+           case SPA_PROP_device:
180
+               strncpy(device, (char *)SPA_POD_CONTENTS(struct spa_pod_string, &prop->value),
181
+                       sizeof(device)-1);
182
+               impl->device_id = device;
183
+               break;
184
+           default:
185
+               spa_libcamera_set_control(impl, prop);
186
+               break;
187
+           }
188
+       }
189
        break;
190
    }
191
    default:
192
@@ -356,7 +434,6 @@
193
    { SPA_KEY_DEVICE_API, "libcamera" },
194
    { SPA_KEY_MEDIA_CLASS, "Video/Source" },
195
    { SPA_KEY_MEDIA_ROLE, "Camera" },
196
-   { SPA_KEY_NODE_PAUSE_ON_IDLE, "false" },
197
    { SPA_KEY_NODE_DRIVER, "true" },
198
 };
199
 
200
@@ -444,55 +521,6 @@
201
pipewire-0.3.59.tar.gz/spa/plugins/libcamera/libcamera-utils.cpp -> pipewire-0.3.60.tar.gz/spa/plugins/libcamera/libcamera-utils.cpp Changed
201
 
1
@@ -32,6 +32,7 @@
2
 #include <errno.h>
3
 #include <sys/mman.h>
4
 #include <poll.h>
5
+#include <limits.h>
6
 
7
 #include <linux/media.h>
8
 
9
@@ -104,6 +105,8 @@
10
        impl->pendingRequests.push_back(request);
11
        return 0;
12
    } else {
13
+       request->controls().merge(impl->ctrls);
14
+       impl->ctrls.clear();
15
        if ((res = impl->camera->queueRequest(request)) < 0) {
16
            spa_log_warn(impl->log, "can't queue buffer %u: %s",
17
                buffer_id, spa_strerror(res));
18
@@ -238,6 +241,14 @@
19
    return NULL;
20
 }
21
 
22
+static int score_size(Size &a, Size &b)
23
+{
24
+   int x, y;
25
+   x = (int)a.width - (int)b.width;
26
+   y = (int)a.height - (int)b.height;
27
+   return x * x + y * y;
28
+}
29
+
30
 static int
31
 spa_libcamera_enum_format(struct impl *impl, struct port *port, int seq,
32
             uint32_t start, uint32_t num, const struct spa_pod *filter)
33
@@ -249,7 +260,7 @@
34
    struct spa_pod_frame f2;
35
    struct spa_result_node_params result;
36
    struct spa_pod *fmt;
37
-   uint32_t count = 0;
38
+   uint32_t i, count = 0, num_sizes;
39
    PixelFormat format;
40
    Size frameSize;
41
    SizeRange sizeRange = SizeRange();
42
@@ -284,8 +295,23 @@
43
        goto next_fmt;
44
    }
45
 
46
-   if (port->size_index < formats.sizes(format).size()) {
47
-       frameSize = formats.sizes(format)port->size_index;
48
+   num_sizes = formats.sizes(format).size();
49
+   if (num_sizes > 0 && port->size_index <= num_sizes) {
50
+       if (port->size_index == 0) {
51
+           Size wanted = Size(640, 480), test;
52
+           int score, best = INT_MAX;
53
+           for (i = 0; i < num_sizes; i++) {
54
+               test = formats.sizes(format)i;
55
+               score = score_size(wanted, test);
56
+               if (score < best) {
57
+                   best = score;
58
+                   frameSize = test;
59
+               }
60
+           }
61
+       }
62
+       else {
63
+           frameSize = formats.sizes(format)port->size_index - 1;
64
+       }
65
    } else if (port->size_index < 1) {
66
        sizeRange = formats.range(format);
67
        if (sizeRange.hStep == 0 || sizeRange.vStep == 0) {
68
@@ -437,9 +463,158 @@
69
               uint32_t start, uint32_t num,
70
               const struct spa_pod *filter)
71
 {
72
+   const ControlInfoMap &info = impl->camera->controls();
73
+   uint8_t buffer1024;
74
+   struct spa_pod_builder b = { 0 };
75
+   struct spa_pod_frame f2;
76
+   struct spa_result_node_params result;
77
+   struct spa_pod *ctrl;
78
+   uint32_t count = 0, skip;
79
+   int res;
80
+   const ControlId *ctrl_id;
81
+   ControlInfo ctrl_info;
82
+
83
+   result.id = SPA_PARAM_PropInfo;
84
+   result.next = start;
85
+
86
+   auto it = info.begin();
87
+   for (skip = result.next; skip; skip--)
88
+       it++;
89
+
90
+   if (false) {
91
+next:
92
+       it++;
93
+   }
94
+   result.index = result.next++;
95
+   if (it == info.end())
96
+       goto enum_end;
97
+
98
+   ctrl_id = it->first;
99
+   ctrl_info = it->second;
100
+
101
+   spa_pod_builder_init(&b, buffer, sizeof(buffer));
102
+   spa_pod_builder_push_object(&b, &f0, SPA_TYPE_OBJECT_PropInfo, SPA_PARAM_PropInfo);
103
+   spa_pod_builder_add(&b,
104
+           SPA_PROP_INFO_id,   SPA_POD_Id(ctrl_id->id()),
105
+           SPA_PROP_INFO_description, SPA_POD_String(ctrl_id->name().c_str()),
106
+           0);
107
+
108
+   switch (ctrl_id->type()) {
109
+   case ControlTypeBool:
110
+       spa_pod_builder_add(&b,
111
+               SPA_PROP_INFO_type, SPA_POD_CHOICE_Bool(
112
+                       (bool)ctrl_info.def().get<bool>()),
113
+               0);
114
+       break;
115
+   case ControlTypeFloat:
116
+       spa_pod_builder_add(&b,
117
+               SPA_PROP_INFO_type, SPA_POD_CHOICE_RANGE_Float(
118
+                       (float)ctrl_info.def().get<float>(),
119
+                       (float)ctrl_info.min().get<float>(),
120
+                       (float)ctrl_info.max().get<float>()),
121
+               0);
122
+       break;
123
+   case ControlTypeInteger32:
124
+       spa_pod_builder_add(&b,
125
+               SPA_PROP_INFO_type, SPA_POD_CHOICE_RANGE_Int(
126
+                       (int32_t)ctrl_info.def().get<int32_t>(),
127
+                       (int32_t)ctrl_info.min().get<int32_t>(),
128
+                       (int32_t)ctrl_info.max().get<int32_t>()),
129
+               0);
130
+       break;
131
+   default:
132
+       goto next;
133
+   }
134
+
135
+   ctrl = (struct spa_pod*) spa_pod_builder_pop(&b, &f0);
136
+
137
+   if (spa_pod_filter(&b, &result.param, ctrl, filter) < 0)
138
+       goto next;
139
+
140
+   spa_node_emit_result(&impl->hooks, seq, 0, SPA_RESULT_TYPE_NODE_PARAMS, &result);
141
+
142
+   if (++count != num)
143
+       goto next;
144
+
145
+enum_end:
146
+   res = 0;
147
+   return res;
148
+}
149
+
150
+struct val {
151
+   uint32_t type;
152
+   float f_val;
153
+   int32_t i_val;
154
+   bool b_val;
155
+   uint32_t id;
156
+};
157
+
158
+static int do_update_ctrls(struct spa_loop *loop,
159
+               bool async,
160
+               uint32_t seq,
161
+               const void *data,
162
+               size_t size,
163
+               void *user_data)
164
+{
165
+   struct impl *impl = (struct impl *)user_data;
166
+   const struct val *d = (const struct val *)data;
167
+   switch (d->type) {
168
+   case ControlTypeBool:
169
+       impl->ctrls.set(d->id, d->b_val);
170
+       break;
171
+   case ControlTypeFloat:
172
+       impl->ctrls.set(d->id, d->f_val);
173
+       break;
174
+   case ControlTypeInteger32:
175
+       //impl->ctrls.set(d->id, (int32_t)d->i_val);
176
+       break;
177
+   default:
178
+       break;
179
+   }
180
    return 0;
181
 }
182
 
183
+static int
184
+spa_libcamera_set_control(struct impl *impl, const struct spa_pod_prop *prop)
185
+{
186
+   const ControlInfoMap &info = impl->camera->controls();
187
+   const ControlId *ctrl_id;
188
+   int res;
189
+   struct val d;
190
+
191
+   auto v = info.idmap().find(prop->key);
192
+   if (v == info.idmap().end())
193
+       return -ENOENT;
194
+
195
+   ctrl_id = v->second;
196
+
197
+   d.type = ctrl_id->type();
198
+   d.id = ctrl_id->id();
199
+
200
+   switch (d.type) {
201
pipewire-0.3.59.tar.gz/spa/plugins/support/cpu-x86.c -> pipewire-0.3.60.tar.gz/spa/plugins/support/cpu-x86.c Changed
9
 
1
@@ -56,6 +56,7 @@
2
        } else if (family == 0x06)
3
            model += extended_model;
4
    }
5
+   (void)model;
6
 
7
    flags = 0;
8
    if (ecx & bit_SSE3)
9
pipewire-0.3.59.tar.gz/spa/plugins/support/cpu.c -> pipewire-0.3.60.tar.gz/spa/plugins/support/cpu.c Changed
27
 
1
@@ -171,19 +171,18 @@
2
        /* https://wiki.freebsd.org/bhyve */
3
        { "BHYVE",      SPA_CPU_VM_BHYVE },
4
         };
5
-   uint32_t i, j;
6
 
7
-   for (i = 0; i < SPA_N_ELEMENTS(dmi_vendors); i++) {
8
+   SPA_FOR_EACH_ELEMENT_VAR(dmi_vendors, dv) {
9
        char buffer256, *s;
10
 
11
-       if ((s = read_file(dmi_vendorsi, buffer, sizeof(buffer))) == NULL)
12
+       if ((s = read_file(*dv, buffer, sizeof(buffer))) == NULL)
13
            continue;
14
 
15
-       for (j = 0; j < SPA_N_ELEMENTS(dmi_vendor_table); j++) {
16
-           if (spa_strstartswith(s, dmi_vendor_tablej.vendor)) {
17
+       SPA_FOR_EACH_ELEMENT_VAR(dmi_vendor_table, t) {
18
+           if (spa_strstartswith(s, t->vendor)) {
19
                spa_log_debug(impl->log, "Virtualization %s found in DMI (%s)",
20
-                       s, dmi_vendorsi);
21
-               impl->vm_type = dmi_vendor_tablej.id;
22
+                       s, *dv);
23
+               impl->vm_type = t->id;
24
                goto done;
25
                         }
26
        }
27
pipewire-0.3.59.tar.gz/spa/plugins/support/loop.c -> pipewire-0.3.60.tar.gz/spa/plugins/support/loop.c Changed
89
 
1
@@ -186,8 +186,8 @@
2
 
3
        if (block) {
4
            if ((res = spa_system_eventfd_write(impl->system, impl->ack_fd, 1)) < 0)
5
-               spa_log_warn(impl->log, "%p: failed to write event fd: %s",
6
-                       impl, spa_strerror(res));
7
+               spa_log_warn(impl->log, "%p: failed to write event fd:%d: %s",
8
+                       impl, impl->ack_fd, spa_strerror(res));
9
        }
10
    }
11
    impl->flushing = false;
12
@@ -283,8 +283,8 @@
13
        spa_loop_control_hook_before(&impl->hooks_list);
14
 
15
        if ((res = spa_system_eventfd_read(impl->system, impl->ack_fd, &count)) < 0)
16
-           spa_log_warn(impl->log, "%p: failed to read event fd: %s",
17
-                   impl, spa_strerror(res));
18
+           spa_log_warn(impl->log, "%p: failed to read event fd:%d: %s",
19
+                   impl, impl->ack_fd, spa_strerror(res));
20
 
21
        spa_loop_control_hook_after(&impl->hooks_list);
22
 
23
@@ -526,12 +526,12 @@
24
 
25
    if (enabled && !s->enabled) {
26
        if ((res = spa_system_eventfd_write(s->impl->system, source->fd, 1)) < 0)
27
-           spa_log_warn(s->impl->log, "%p: failed to write idle fd %d: %s",
28
+           spa_log_warn(s->impl->log, "%p: failed to write idle fd:%d: %s",
29
                    source, source->fd, spa_strerror(res));
30
    } else if (!enabled && s->enabled) {
31
        uint64_t count;
32
        if ((res = spa_system_eventfd_read(s->impl->system, source->fd, &count)) < 0)
33
-           spa_log_warn(s->impl->log, "%p: failed to read idle fd %d: %s",
34
+           spa_log_warn(s->impl->log, "%p: failed to read idle fd:%d: %s",
35
                    source, source->fd, spa_strerror(res));
36
    }
37
    s->enabled = enabled;
38
@@ -586,7 +586,7 @@
39
    int res;
40
 
41
    if ((res = spa_system_eventfd_read(s->impl->system, source->fd, &count)) < 0)
42
-       spa_log_warn(s->impl->log, "%p: failed to read event fd %d: %s",
43
+       spa_log_warn(s->impl->log, "%p: failed to read event fd:%d: %s",
44
                source, source->fd, spa_strerror(res));
45
 
46
    s->func.event(source->data, count);
47
@@ -639,7 +639,7 @@
48
    spa_assert(source->func == source_event_func);
49
 
50
    if (SPA_UNLIKELY((res = spa_system_eventfd_write(s->impl->system, source->fd, 1)) < 0))
51
-       spa_log_warn(s->impl->log, "%p: failed to write event fd %d: %s",
52
+       spa_log_warn(s->impl->log, "%p: failed to write event fd:%d: %s",
53
                source, source->fd, spa_strerror(res));
54
    return res;
55
 }
56
@@ -652,7 +652,7 @@
57
 
58
    if (SPA_UNLIKELY((res = spa_system_timerfd_read(s->impl->system,
59
                source->fd, &expirations)) < 0))
60
-       spa_log_warn(s->impl->log, "%p: failed to read timer fd %d: %s",
61
+       spa_log_warn(s->impl->log, "%p: failed to read timer fd:%d: %s",
62
                source, source->fd, spa_strerror(res));
63
 
64
    s->func.timer(source->data, expirations);
65
@@ -732,7 +732,7 @@
66
    int res, signal_number = 0;
67
 
68
    if ((res = spa_system_signalfd_read(s->impl->system, source->fd, &signal_number)) < 0)
69
-       spa_log_warn(s->impl->log, "%p: failed to read signal fd %d: %s",
70
+       spa_log_warn(s->impl->log, "%p: failed to read signal fd:%d: %s",
71
                source, source->fd, spa_strerror(res));
72
 
73
    s->func.signal(source->data, signal_number);
74
@@ -865,11 +865,9 @@
75
 
76
    impl = (struct impl *) handle;
77
 
78
-   if (impl->enter_count != 0)
79
-       spa_log_warn(impl->log, "%p: loop is entered %d times",
80
-               impl, impl->enter_count);
81
-
82
-   spa_assert(!impl->polling);
83
+   if (impl->enter_count != 0 || impl->polling)
84
+       spa_log_warn(impl->log, "%p: loop is entered %d times polling:%d",
85
+               impl, impl->enter_count, impl->polling);
86
 
87
    spa_list_consume(source, &impl->source_list, link)
88
        loop_destroy_source(impl, &source->source);
89
pipewire-0.3.59.tar.gz/spa/plugins/support/null-audio-sink.c -> pipewire-0.3.60.tar.gz/spa/plugins/support/null-audio-sink.c Changed
13
 
1
@@ -610,6 +610,11 @@
2
        if (spa_format_audio_raw_parse(format, &info.info.raw) < 0)
3
            return -EINVAL;
4
 
5
+       if (info.info.raw.rate == 0 ||
6
+           info.info.raw.channels == 0 ||
7
+           info.info.raw.channels > SPA_AUDIO_MAX_CHANNELS)
8
+           return -EINVAL;
9
+
10
        if (info.info.raw.format == SPA_AUDIO_FORMAT_F32) {
11
            port->bpf = 4 * info.info.raw.channels;
12
            port->blocks = 1;
13
pipewire-0.3.59.tar.gz/spa/plugins/v4l2/v4l2-source.c -> pipewire-0.3.60.tar.gz/spa/plugins/v4l2/v4l2-source.c Changed
201
 
1
@@ -145,7 +145,8 @@
2
 #define NODE_PropInfo  0
3
 #define NODE_Props 1
4
 #define NODE_EnumFormat    2
5
-#define N_NODE_PARAMS  3
6
+#define NODE_Format    3
7
+#define N_NODE_PARAMS  4
8
    struct spa_param_info paramsN_NODE_PARAMS;
9
    struct props props;
10
 
11
@@ -167,6 +168,56 @@
12
 
13
 #include "v4l2-utils.c"
14
 
15
+static int port_get_format(struct port *port,
16
+              uint32_t index,
17
+              const struct spa_pod *filter,
18
+              struct spa_pod **param,
19
+              struct spa_pod_builder *builder)
20
+{
21
+   struct spa_pod_frame f;
22
+
23
+   if (!port->have_format)
24
+       return -EIO;
25
+   if (index > 0)
26
+       return 0;
27
+
28
+   spa_pod_builder_push_object(builder, &f, SPA_TYPE_OBJECT_Format, SPA_PARAM_Format);
29
+   spa_pod_builder_add(builder,
30
+       SPA_FORMAT_mediaType,    SPA_POD_Id(port->current_format.media_type),
31
+       SPA_FORMAT_mediaSubtype, SPA_POD_Id(port->current_format.media_subtype),
32
+       0);
33
+
34
+   switch (port->current_format.media_subtype) {
35
+   case SPA_MEDIA_SUBTYPE_raw:
36
+       spa_pod_builder_add(builder,
37
+           SPA_FORMAT_VIDEO_format,    SPA_POD_Id(port->current_format.info.raw.format),
38
+           SPA_FORMAT_VIDEO_size,      SPA_POD_Rectangle(&port->current_format.info.raw.size),
39
+           SPA_FORMAT_VIDEO_framerate, SPA_POD_Fraction(&port->current_format.info.raw.framerate),
40
+           0);
41
+       break;
42
+   case SPA_MEDIA_SUBTYPE_mjpg:
43
+   case SPA_MEDIA_SUBTYPE_jpeg:
44
+       spa_pod_builder_add(builder,
45
+           SPA_FORMAT_VIDEO_size,      SPA_POD_Rectangle(&port->current_format.info.mjpg.size),
46
+           SPA_FORMAT_VIDEO_framerate, SPA_POD_Fraction(&port->current_format.info.mjpg.framerate),
47
+           0);
48
+       break;
49
+   case SPA_MEDIA_SUBTYPE_h264:
50
+       spa_pod_builder_add(builder,
51
+           SPA_FORMAT_VIDEO_size,      SPA_POD_Rectangle(&port->current_format.info.h264.size),
52
+           SPA_FORMAT_VIDEO_framerate, SPA_POD_Fraction(&port->current_format.info.h264.framerate),
53
+           0);
54
+       break;
55
+   default:
56
+       return -EIO;
57
+   }
58
+
59
+   *param = spa_pod_builder_pop(builder, &f);
60
+
61
+   return 1;
62
+}
63
+
64
+
65
 static int impl_node_enum_params(void *object, int seq,
66
                 uint32_t id, uint32_t start, uint32_t num,
67
                 const struct spa_pod *filter)
68
@@ -177,6 +228,7 @@
69
    uint8_t buffer1024;
70
    struct spa_result_node_params result;
71
    uint32_t count = 0;
72
+   int res;
73
 
74
    spa_return_val_if_fail(this != NULL, -EINVAL);
75
    spa_return_val_if_fail(num != 0, -EINVAL);
76
@@ -216,9 +268,9 @@
77
                SPA_PROP_INFO_type, SPA_POD_Int(p->device_fd));
78
            break;
79
        default:
80
-           return 0;
81
+           return spa_v4l2_enum_controls(this, seq, result.index - 3, num, filter);
82
        }
83
-       return spa_v4l2_enum_controls(this, seq, start, num, filter);
84
+       break;
85
    }
86
    case SPA_PARAM_Props:
87
    {
88
@@ -239,6 +291,11 @@
89
    }
90
    case SPA_PARAM_EnumFormat:
91
        return spa_v4l2_enum_format(this, seq, start, num, filter);
92
+   case SPA_PARAM_Format:
93
+       if((res = port_get_format(GET_OUT_PORT(this, 0),
94
+                       result.index, filter, &param, &b)) <= 0)
95
+           return res;
96
+       break;
97
    default:
98
        return -ENOENT;
99
    }
100
@@ -266,14 +323,29 @@
101
    case SPA_PARAM_Props:
102
    {
103
        struct props *p = &this->props;
104
+       struct spa_pod_object *obj = (struct spa_pod_object *) param;
105
+       struct spa_pod_prop *prop;
106
+       int res = 0;
107
 
108
        if (param == NULL) {
109
            reset_props(p);
110
            return 0;
111
        }
112
-       spa_pod_parse_object(param,
113
-           SPA_TYPE_OBJECT_Props, NULL,
114
-           SPA_PROP_device, SPA_POD_OPT_Stringn(p->device, sizeof(p->device)));
115
+       SPA_POD_OBJECT_FOREACH(obj, prop) {
116
+           switch (prop->key) {
117
+           case SPA_PROP_device:
118
+               strncpy(p->device,
119
+                       (char *)SPA_POD_CONTENTS(struct spa_pod_string, &prop->value),
120
+                       sizeof(p->device)-1);
121
+               break;
122
+           default:
123
+               res = spa_v4l2_set_control(this, prop->key, prop);
124
+               break;
125
+           }
126
+           if (res < 0)
127
+               return res;
128
+       }
129
+
130
        break;
131
    }
132
    default:
133
@@ -440,58 +512,6 @@
134
    return -ENOTSUP;
135
 }
136
 
137
-static int port_get_format(void *object,
138
-              enum spa_direction direction, uint32_t port_id,
139
-              uint32_t index,
140
-              const struct spa_pod *filter,
141
-              struct spa_pod **param,
142
-              struct spa_pod_builder *builder)
143
-{
144
-   struct impl *this = object;
145
-   struct port *port = GET_PORT(this, direction, port_id);
146
-   struct spa_pod_frame f;
147
-
148
-   if (!port->have_format)
149
-       return -EIO;
150
-   if (index > 0)
151
-       return 0;
152
-
153
-   spa_pod_builder_push_object(builder, &f, SPA_TYPE_OBJECT_Format, SPA_PARAM_Format);
154
-   spa_pod_builder_add(builder,
155
-       SPA_FORMAT_mediaType,    SPA_POD_Id(port->current_format.media_type),
156
-       SPA_FORMAT_mediaSubtype, SPA_POD_Id(port->current_format.media_subtype),
157
-       0);
158
-
159
-   switch (port->current_format.media_subtype) {
160
-   case SPA_MEDIA_SUBTYPE_raw:
161
-       spa_pod_builder_add(builder,
162
-           SPA_FORMAT_VIDEO_format,    SPA_POD_Id(port->current_format.info.raw.format),
163
-           SPA_FORMAT_VIDEO_size,      SPA_POD_Rectangle(&port->current_format.info.raw.size),
164
-           SPA_FORMAT_VIDEO_framerate, SPA_POD_Fraction(&port->current_format.info.raw.framerate),
165
-           0);
166
-       break;
167
-   case SPA_MEDIA_SUBTYPE_mjpg:
168
-   case SPA_MEDIA_SUBTYPE_jpeg:
169
-       spa_pod_builder_add(builder,
170
-           SPA_FORMAT_VIDEO_size,      SPA_POD_Rectangle(&port->current_format.info.mjpg.size),
171
-           SPA_FORMAT_VIDEO_framerate, SPA_POD_Fraction(&port->current_format.info.mjpg.framerate),
172
-           0);
173
-       break;
174
-   case SPA_MEDIA_SUBTYPE_h264:
175
-       spa_pod_builder_add(builder,
176
-           SPA_FORMAT_VIDEO_size,      SPA_POD_Rectangle(&port->current_format.info.h264.size),
177
-           SPA_FORMAT_VIDEO_framerate, SPA_POD_Fraction(&port->current_format.info.h264.framerate),
178
-           0);
179
-       break;
180
-   default:
181
-       return -EIO;
182
-   }
183
-
184
-   *param = spa_pod_builder_pop(builder, &f);
185
-
186
-   return 1;
187
-}
188
-
189
 static int impl_node_port_enum_params(void *object, int seq,
190
                      enum spa_direction direction,
191
                      uint32_t port_id,
192
@@ -529,8 +549,7 @@
193
        return spa_v4l2_enum_format(this, seq, start, num, filter);
194
 
195
    case SPA_PARAM_Format:
196
-       if((res = port_get_format(this, direction, port_id,
197
-                       result.index, filter, &param, &b)) <= 0)
198
+       if((res = port_get_format(port, result.index, filter, &param, &b)) <= 0)
199
            return res;
200
        break;
201
pipewire-0.3.59.tar.gz/spa/plugins/v4l2/v4l2-udev.c -> pipewire-0.3.60.tar.gz/spa/plugins/v4l2/v4l2-udev.c Changed
10
 
1
@@ -266,7 +266,7 @@
2
    if (str && *str) {
3
        itemsn_items++ = SPA_DICT_ITEM_INIT(SPA_KEY_DEVICE_BUS_PATH, str);
4
    }
5
-   if ((str = udev_device_get_syspath(dev)) && *str) {
6
+   if ((str = udev_device_get_devpath(dev)) && *str) {
7
        itemsn_items++ = SPA_DICT_ITEM_INIT(SPA_KEY_DEVICE_SYSFS_PATH, str);
8
    }
9
    if ((str = udev_device_get_property_value(dev, "ID_ID")) && *str) {
10
pipewire-0.3.59.tar.gz/spa/plugins/v4l2/v4l2-utils.c -> pipewire-0.3.60.tar.gz/spa/plugins/v4l2/v4l2-utils.c Changed
201
 
1
@@ -30,7 +30,7 @@
2
 #include <sys/mman.h>
3
 #include <poll.h>
4
 
5
-static void v4l2_on_fd_events(struct spa_source *source);
6
+#include <spa/utils/result.h>
7
 
8
 static int xioctl(int fd, int request, void *arg)
9
 {
10
@@ -43,7 +43,6 @@
11
    return err;
12
 }
13
 
14
-
15
 int spa_v4l2_open(struct spa_v4l2_device *dev, const char *path)
16
 {
17
    struct stat st;
18
@@ -351,11 +350,9 @@
19
 
20
 static const struct format_info *fourcc_to_format_info(uint32_t fourcc)
21
 {
22
-   size_t i;
23
-
24
-   for (i = 0; i < SPA_N_ELEMENTS(format_info); i++) {
25
-       if (format_infoi.fourcc == fourcc)
26
-           return &format_infoi;
27
+   SPA_FOR_EACH_ELEMENT_VAR(format_info, i) {
28
+       if (i->fourcc == fourcc)
29
+           return i;
30
    }
31
    return NULL;
32
 }
33
@@ -363,11 +360,9 @@
34
 #if 0
35
 static const struct format_info *video_format_to_format_info(uint32_t format)
36
 {
37
-   int i;
38
-
39
-   for (i = 0; i < SPA_N_ELEMENTS(format_info); i++) {
40
-       if (format_infoi.format == format)
41
-           return &format_infoi;
42
+   SPA_FOR_EACH_ELEMENT_VAR(format_info, i) {
43
+       if (i->format == format)
44
+           return i;
45
    }
46
    return NULL;
47
 }
48
@@ -381,10 +376,11 @@
49
    size_t i;
50
 
51
    for (i = startidx; i < SPA_N_ELEMENTS(format_info); i++) {
52
-       if ((format_infoi.media_type == type) &&
53
-           (format_infoi.media_subtype == subtype) &&
54
-           (format == 0 || format_infoi.format == format))
55
-           return &format_infoi;
56
+       const struct format_info *fi = &format_infoi;
57
+       if ((fi->media_type == type) &&
58
+           (fi->media_subtype == subtype) &&
59
+           (format == 0 || fi->format == format))
60
+           return fi;
61
    }
62
    return NULL;
63
 }
64
@@ -895,8 +891,9 @@
65
    bool match;
66
 
67
    spa_zero(fmt);
68
-   spa_zero(streamparm);
69
    fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
70
+
71
+   spa_zero(streamparm);
72
    streamparm.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
73
 
74
    switch (format->media_subtype) {
75
@@ -929,7 +926,6 @@
76
        return -EINVAL;
77
    }
78
 
79
-
80
    fmt.fmt.pix.pixelformat = info->fourcc;
81
    fmt.fmt.pix.field = V4L2_FIELD_ANY;
82
    fmt.fmt.pix.width = size->width;
83
@@ -1046,28 +1042,38 @@
84
    return res;
85
 }
86
 
87
+static struct {
88
+   uint32_t v4l2_id;
89
+   uint32_t spa_id;
90
+} control_map = {
91
+   { V4L2_CID_BRIGHTNESS, SPA_PROP_brightness },
92
+   { V4L2_CID_CONTRAST, SPA_PROP_contrast },
93
+   { V4L2_CID_SATURATION, SPA_PROP_saturation },
94
+   { V4L2_CID_HUE, SPA_PROP_hue },
95
+   { V4L2_CID_GAMMA, SPA_PROP_gamma },
96
+   { V4L2_CID_EXPOSURE, SPA_PROP_exposure },
97
+   { V4L2_CID_GAIN, SPA_PROP_gain },
98
+   { V4L2_CID_SHARPNESS, SPA_PROP_sharpness },
99
+};
100
+
101
 static uint32_t control_to_prop_id(struct impl *impl, uint32_t control_id)
102
 {
103
-   switch (control_id) {
104
-   case V4L2_CID_BRIGHTNESS:
105
-       return SPA_PROP_brightness;
106
-   case V4L2_CID_CONTRAST:
107
-       return SPA_PROP_contrast;
108
-   case V4L2_CID_SATURATION:
109
-       return SPA_PROP_saturation;
110
-   case V4L2_CID_HUE:
111
-       return SPA_PROP_hue;
112
-   case V4L2_CID_GAMMA:
113
-       return SPA_PROP_gamma;
114
-   case V4L2_CID_EXPOSURE:
115
-       return SPA_PROP_exposure;
116
-   case V4L2_CID_GAIN:
117
-       return SPA_PROP_gain;
118
-   case V4L2_CID_SHARPNESS:
119
-       return SPA_PROP_sharpness;
120
-   default:
121
-       return SPA_PROP_START_CUSTOM + control_id;
122
+   SPA_FOR_EACH_ELEMENT_VAR(control_map, c) {
123
+       if (c->v4l2_id == control_id)
124
+           return c->spa_id;
125
+   }
126
+   return SPA_PROP_START_CUSTOM + control_id;
127
+}
128
+
129
+static uint32_t prop_id_to_control(struct impl *impl, uint32_t prop_id)
130
+{
131
+   SPA_FOR_EACH_ELEMENT_VAR(control_map, c) {
132
+       if (c->spa_id == prop_id)
133
+           return c->v4l2_id;
134
    }
135
+   if (prop_id >= SPA_PROP_START_CUSTOM)
136
+       return prop_id - SPA_PROP_START_CUSTOM;
137
+   return SPA_ID_INVALID;
138
 }
139
 
140
 static int
141
@@ -1231,6 +1237,56 @@
142
    return res;
143
 }
144
 
145
+static int
146
+spa_v4l2_set_control(struct impl *this, uint32_t id,
147
+              const struct spa_pod_prop *prop)
148
+{
149
+   struct port *port = &this->out_ports0;
150
+   struct spa_v4l2_device *dev = &port->dev;
151
+   struct v4l2_control control;
152
+   int res;
153
+
154
+   spa_zero(control);
155
+   control.id = prop_id_to_control(this, prop->key);
156
+   if (control.id == SPA_ID_INVALID)
157
+       return -ENOENT;
158
+
159
+   if ((res = spa_v4l2_open(dev, this->props.device)) < 0)
160
+       return res;
161
+
162
+   switch (SPA_POD_TYPE(&prop->value)) {
163
+   case SPA_TYPE_Bool:
164
+   {
165
+       bool val;
166
+       if ((res = spa_pod_get_bool(&prop->value, &val)) < 0)
167
+           goto done;
168
+       control.value = val;
169
+       break;
170
+   }
171
+   case SPA_TYPE_Int:
172
+   {
173
+       int32_t val;
174
+       if ((res = spa_pod_get_int(&prop->value, &val)) < 0)
175
+           goto done;
176
+       control.value = val;
177
+       break;
178
+   }
179
+   default:
180
+       res = -EINVAL;
181
+       goto done;
182
+   }
183
+   if (xioctl(dev->fd, VIDIOC_S_CTRL, &control) < 0) {
184
+       res = -errno;
185
+       goto done;
186
+   }
187
+
188
+   res = 0;
189
+
190
+done:
191
+   spa_v4l2_close(dev);
192
+   return res;
193
+}
194
+
195
 static int mmap_read(struct impl *this)
196
 {
197
    struct port *port = &this->out_ports0;
198
@@ -1310,7 +1366,13 @@
199
        return;
200
 
201
pipewire-0.3.59.tar.gz/spa/plugins/videoconvert/videoadapter.c -> pipewire-0.3.60.tar.gz/spa/plugins/videoconvert/videoadapter.c Changed
55
 
1
@@ -562,24 +562,6 @@
2
    return 0;
3
 }
4
 
5
-static int format_video_raw_parse_opt(const struct spa_pod *format, struct spa_video_info_raw *info)
6
-{
7
-   uint32_t media_type, media_subtype;
8
-   int res;
9
-   if ((res = spa_format_parse(format, &media_type, &media_subtype)) < 0)
10
-       return res;
11
-   if (media_type != SPA_MEDIA_TYPE_video ||
12
-       media_subtype != SPA_MEDIA_SUBTYPE_raw)
13
-       return -ENOTSUP;
14
-
15
-   spa_zero(*info);
16
-   res = spa_pod_parse_object(format,
17
-           SPA_TYPE_OBJECT_Format, NULL,
18
-           SPA_FORMAT_VIDEO_format, SPA_POD_OPT_Id(&info->format),
19
-           SPA_FORMAT_VIDEO_size, SPA_POD_OPT_Int(&info->size));
20
-   return res;
21
-}
22
-
23
 static int impl_node_set_param(void *object, uint32_t id, uint32_t flags,
24
                   const struct spa_pod *param)
25
 {
26
@@ -599,8 +581,9 @@
27
        if ((res = spa_format_parse(param, &info.media_type, &info.media_subtype)) < 0)
28
            return res;
29
        if (info.media_type != SPA_MEDIA_TYPE_video ||
30
-           info.media_subtype != SPA_MEDIA_SUBTYPE_raw)
31
-               return -EINVAL;
32
+           info.media_subtype != SPA_MEDIA_SUBTYPE_raw)
33
+           return -EINVAL;
34
+
35
        if (spa_format_video_raw_parse(param, &info.info.raw) < 0)
36
            return -EINVAL;
37
 
38
@@ -627,7 +610,15 @@
39
 
40
        if (format) {
41
            struct spa_video_info info;
42
-           if (format_video_raw_parse_opt(format, &info.info.raw) >= 0)
43
+
44
+           spa_zero(info);
45
+           if ((res = spa_format_parse(format, &info.media_type, &info.media_subtype)) < 0)
46
+               return res;
47
+           if (info.media_type != SPA_MEDIA_TYPE_video ||
48
+               info.media_subtype != SPA_MEDIA_SUBTYPE_raw)
49
+               return -ENOTSUP;
50
+
51
+           if (spa_format_video_raw_parse(format, &info.info.raw) >= 0)
52
                this->default_format = info;
53
        }
54
 
55
pipewire-0.3.59.tar.gz/spa/plugins/videotestsrc/videotestsrc.c -> pipewire-0.3.60.tar.gz/spa/plugins/videotestsrc/videotestsrc.c Changed
14
 
1
@@ -643,6 +643,12 @@
2
        else
3
            return -EINVAL;
4
 
5
+       if (info.info.raw.size.width == 0 ||
6
+           info.info.raw.size.height == 0 ||
7
+           info.info.raw.framerate.num == 0 ||
8
+           info.info.raw.framerate.denom == 0)
9
+           return -EINVAL;
10
+
11
        port->current_format = info;
12
        port->have_format = true;
13
    }
14
pipewire-0.3.59.tar.gz/spa/plugins/volume/volume.c -> pipewire-0.3.60.tar.gz/spa/plugins/volume/volume.c Changed
26
 
1
@@ -321,10 +321,9 @@
2
            SPA_TYPE_OBJECT_Format, SPA_PARAM_EnumFormat,
3
            SPA_FORMAT_mediaType,      SPA_POD_Id(SPA_MEDIA_TYPE_audio),
4
            SPA_FORMAT_mediaSubtype,   SPA_POD_Id(SPA_MEDIA_SUBTYPE_raw),
5
-           SPA_FORMAT_AUDIO_format,   SPA_POD_CHOICE_ENUM_Id(3,
6
+           SPA_FORMAT_AUDIO_format,   SPA_POD_CHOICE_ENUM_Id(2,
7
                            SPA_AUDIO_FORMAT_S16,
8
-                           SPA_AUDIO_FORMAT_S16,
9
-                           SPA_AUDIO_FORMAT_S32),
10
+                           SPA_AUDIO_FORMAT_S16),
11
            SPA_FORMAT_AUDIO_rate,     SPA_POD_CHOICE_RANGE_Int(
12
                            DEFAULT_RATE, 1, INT32_MAX),
13
            SPA_FORMAT_AUDIO_channels, SPA_POD_CHOICE_RANGE_Int(
14
@@ -472,6 +471,11 @@
15
        if (spa_format_audio_raw_parse(format, &info.info.raw) < 0)
16
            return -EINVAL;
17
 
18
+       if (info.info.raw.format != SPA_AUDIO_FORMAT_S16 ||
19
+           info.info.raw.channels == 0 ||
20
+           info.info.raw.channels > SPA_AUDIO_MAX_CHANNELS)
21
+           return -EINVAL;
22
+
23
        this->bpf = 2 * info.info.raw.channels;
24
        this->current_format = info;
25
        port->have_format = true;
26
pipewire-0.3.59.tar.gz/spa/tests/benchmark-dict.c -> pipewire-0.3.60.tar.gz/spa/tests/benchmark-dict.c Changed
10
 
1
@@ -39,7 +39,7 @@
2
 static struct spa_dict_item itemsMAX_ITEMS;
3
 static char valuesMAX_ITEMS32;
4
 
5
-static void gen_values()
6
+static void gen_values(void)
7
 {
8
    uint32_t i, j, idx;
9
    static const char chars = "abcdefghijklmnopqrstuvwxyz.:*ABCDEFGHIJKLMNOPQRSTUVWXYZ";
10
pipewire-0.3.59.tar.gz/spa/tests/benchmark-pod.c -> pipewire-0.3.60.tar.gz/spa/tests/benchmark-pod.c Changed
37
 
1
@@ -37,7 +37,7 @@
2
 
3
 #define MAX_COUNT 10000000
4
 
5
-static void test_builder()
6
+static void test_builder(void)
7
 {
8
    uint8_t buffer1024;
9
    struct spa_pod_builder b = { NULL, };
10
@@ -90,7 +90,7 @@
11
            t2 - t1, count, count * (uint64_t)SPA_NSEC_PER_SEC / (t2 - t1));
12
 }
13
 
14
-static void test_builder2()
15
+static void test_builder2(void)
16
 {
17
    uint8_t buffer1024;
18
    struct spa_pod_builder b = { NULL, };
19
@@ -131,7 +131,7 @@
20
            t2 - t1, count, count * (uint64_t)SPA_NSEC_PER_SEC / (t2 - t1));
21
 }
22
 
23
-static void test_parse()
24
+static void test_parse(void)
25
 {
26
    uint8_t buffer1024;
27
    struct spa_pod_builder b = { NULL, };
28
@@ -216,7 +216,7 @@
29
            t2 - t1, count, count * (uint64_t)SPA_NSEC_PER_SEC / (t2 - t1));
30
 }
31
 
32
-static void test_parser()
33
+static void test_parser(void)
34
 {
35
    uint8_t buffer1024;
36
    struct spa_pod_builder b = { NULL, };
37
pipewire-0.3.59.tar.gz/src/daemon/jack.conf.in -> pipewire-0.3.60.tar.gz/src/daemon/jack.conf.in Changed
26
 
1
@@ -83,6 +83,7 @@
2
      #jack.locked-process    = true
3
      #jack.default-as-system = false
4
      #jack.fix-midi-events   = true
5
+     #jack.global-buffer-size = false
6
 }
7
 
8
 # client specific properties
9
@@ -102,4 +103,16 @@
10
             }
11
         }
12
     }
13
+    {
14
+        matches = 
15
+            {
16
+                application.process.binary = "jack_bufsize"
17
+            }
18
+        
19
+        actions = {
20
+            update-props = {
21
+                jack.global-buffer-size = true
22
+            }
23
+        }
24
+    }
25
 
26
pipewire-0.3.59.tar.gz/src/daemon/pipewire.conf.in -> pipewire-0.3.60.tar.gz/src/daemon/pipewire.conf.in Changed
25
 
1
@@ -159,14 +159,15 @@
2
     { name = libpipewire-module-session-manager }
3
 
4
     # Use libcanberra to play X11 Bell
5
-    #{ name = libpipewire-module-x11-bell
6
-    #  args = {
7
-    #      #sink.name = "@DEFAULT_SINK@"
8
-    #      #sample.name = "bell-window-system"
9
-    #      #x11.display = null
10
-    #      #x11.xauthority = null
11
-    #  }
12
-    #}
13
+    { name = libpipewire-module-x11-bell
14
+        args = {
15
+            #sink.name = "@DEFAULT_SINK@"
16
+            #sample.name = "bell-window-system"
17
+            #x11.display = null
18
+            #x11.xauthority = null
19
+        }
20
+        flags =  ifexists nofail 
21
+    }
22
 
23
 
24
 context.objects = 
25
pipewire-0.3.59.tar.gz/src/examples/export-sink.c -> pipewire-0.3.60.tar.gz/src/examples/export-sink.c Changed
42
 
1
@@ -303,11 +303,10 @@
2
    Uint32 sdl_format;
3
    void *dest;
4
 
5
-   d->info.change_mask = SPA_PORT_CHANGE_MASK_PARAMS;
6
    if (format == NULL) {
7
+       spa_zero(d->format);
8
        SDL_DestroyTexture(d->texture);
9
-       d->params3 = SPA_PARAM_INFO(SPA_PARAM_Format, SPA_PARAM_INFO_WRITE);
10
-       d->params4 = SPA_PARAM_INFO(SPA_PARAM_Buffers, 0);
11
+       d->texture = NULL;
12
    } else {
13
        spa_debug_format(0, NULL, format);
14
 
15
@@ -316,6 +315,9 @@
16
        sdl_format = id_to_sdl_format(d->format.format);
17
        if (sdl_format == SDL_PIXELFORMAT_UNKNOWN)
18
            return -EINVAL;
19
+       if (d->format.size.width == 0 ||
20
+           d->format.size.height == 0)
21
+           return -EINVAL;
22
 
23
        d->texture = SDL_CreateTexture(d->renderer,
24
                          sdl_format,
25
@@ -325,9 +327,16 @@
26
        SDL_LockTexture(d->texture, NULL, &dest, &d->stride);
27
        SDL_UnlockTexture(d->texture);
28
 
29
+   }
30
+   d->info.change_mask = SPA_PORT_CHANGE_MASK_PARAMS;
31
+   if (format) {
32
        d->params3 = SPA_PARAM_INFO(SPA_PARAM_Format, SPA_PARAM_INFO_READWRITE);
33
        d->params4 = SPA_PARAM_INFO(SPA_PARAM_Buffers, SPA_PARAM_INFO_READ);
34
+   } else {
35
+       d->params3 = SPA_PARAM_INFO(SPA_PARAM_Format, SPA_PARAM_INFO_WRITE);
36
+       d->params4 = SPA_PARAM_INFO(SPA_PARAM_Buffers, 0);
37
    }
38
+
39
    spa_node_emit_port_info(&d->hooks, direction, port_id, &d->info);
40
    d->info.change_mask = 0;
41
 
42
pipewire-0.3.59.tar.gz/src/examples/export-source.c -> pipewire-0.3.60.tar.gz/src/examples/export-source.c Changed
49
 
1
@@ -275,26 +275,31 @@
2
 {
3
    struct data *d = object;
4
 
5
-   d->info.change_mask = SPA_PORT_CHANGE_MASK_PARAMS;
6
    if (format == NULL) {
7
-       d->format.format = 0;
8
-       d->params3 = SPA_PARAM_INFO(SPA_PARAM_Format, SPA_PARAM_INFO_WRITE);
9
-       d->params4 = SPA_PARAM_INFO(SPA_PARAM_Buffers, 0);
10
-       spa_node_emit_port_info(&d->hooks, SPA_DIRECTION_OUTPUT, 0, &d->info);
11
-       return 0;
12
-   }
13
+       spa_zero(d->format);
14
+   } else {
15
+       spa_debug_format(0, NULL, format);
16
 
17
-   spa_debug_format(0, NULL, format);
18
-
19
-   if (spa_format_audio_raw_parse(format, &d->format) < 0)
20
-       return -EINVAL;
21
+       if (spa_format_audio_raw_parse(format, &d->format) < 0)
22
+           return -EINVAL;
23
 
24
-   if (d->format.format != SPA_AUDIO_FORMAT_S16 &&
25
-       d->format.format != SPA_AUDIO_FORMAT_F32)
26
-       return -EINVAL;
27
+       if (d->format.format != SPA_AUDIO_FORMAT_S16 &&
28
+           d->format.format != SPA_AUDIO_FORMAT_F32)
29
+           return -EINVAL;
30
+       if (d->format.rate == 0 ||
31
+           d->format.channels == 0 ||
32
+           d->format.channels > SPA_AUDIO_MAX_CHANNELS)
33
+           return -EINVAL;
34
+   }
35
 
36
-   d->params3 = SPA_PARAM_INFO(SPA_PARAM_Format, SPA_PARAM_INFO_READWRITE);
37
-   d->params4 = SPA_PARAM_INFO(SPA_PARAM_Buffers, SPA_PARAM_INFO_READ);
38
+   d->info.change_mask = SPA_PORT_CHANGE_MASK_PARAMS;
39
+   if (format) {
40
+       d->params3 = SPA_PARAM_INFO(SPA_PARAM_Format, SPA_PARAM_INFO_READWRITE);
41
+       d->params4 = SPA_PARAM_INFO(SPA_PARAM_Buffers, SPA_PARAM_INFO_READ);
42
+   } else {
43
+       d->params3 = SPA_PARAM_INFO(SPA_PARAM_Format, SPA_PARAM_INFO_WRITE);
44
+       d->params4 = SPA_PARAM_INFO(SPA_PARAM_Buffers, 0);
45
+   }
46
    spa_node_emit_port_info(&d->hooks, SPA_DIRECTION_OUTPUT, 0, &d->info);
47
 
48
    return 0;
49
pipewire-0.3.59.tar.gz/src/examples/local-v4l2.c -> pipewire-0.3.60.tar.gz/src/examples/local-v4l2.c Changed
61
 
1
@@ -207,28 +207,39 @@
2
    Uint32 sdl_format;
3
    void *dest;
4
 
5
-   if (format == NULL)
6
-       return 0;
7
-
8
-   spa_debug_format(0, NULL, format);
9
-
10
-   spa_format_video_raw_parse(format, &d->format);
11
-
12
-   sdl_format = id_to_sdl_format(d->format.format);
13
-   if (sdl_format == SDL_PIXELFORMAT_UNKNOWN)
14
-       return -EINVAL;
15
-
16
-   d->texture = SDL_CreateTexture(d->renderer,
17
-                      sdl_format,
18
-                      SDL_TEXTUREACCESS_STREAMING,
19
-                      d->format.size.width,
20
-                      d->format.size.height);
21
-   SDL_LockTexture(d->texture, NULL, &dest, &d->stride);
22
-   SDL_UnlockTexture(d->texture);
23
+   if (format == NULL) {
24
+       spa_zero(d->format);
25
+       SDL_DestroyTexture(d->texture);
26
+       d->texture = NULL;
27
+   } else {
28
+       spa_debug_format(0, NULL, format);
29
+
30
+       spa_format_video_raw_parse(format, &d->format);
31
+
32
+       sdl_format = id_to_sdl_format(d->format.format);
33
+       if (sdl_format == SDL_PIXELFORMAT_UNKNOWN)
34
+           return -EINVAL;
35
+       if (d->format.size.width == 0 ||
36
+           d->format.size.height == 0)
37
+           return -EINVAL;
38
+
39
+       d->texture = SDL_CreateTexture(d->renderer,
40
+                          sdl_format,
41
+                          SDL_TEXTUREACCESS_STREAMING,
42
+                          d->format.size.width,
43
+                          d->format.size.height);
44
+       SDL_LockTexture(d->texture, NULL, &dest, &d->stride);
45
+       SDL_UnlockTexture(d->texture);
46
+   }
47
 
48
    d->info.change_mask = SPA_PORT_CHANGE_MASK_PARAMS;
49
-   d->params1 = SPA_PARAM_INFO(SPA_PARAM_Format, SPA_PARAM_INFO_READWRITE);
50
-   d->params2 = SPA_PARAM_INFO(SPA_PARAM_Buffers, SPA_PARAM_INFO_READ);
51
+   if (format) {
52
+       d->params1 = SPA_PARAM_INFO(SPA_PARAM_Format, SPA_PARAM_INFO_READWRITE);
53
+       d->params2 = SPA_PARAM_INFO(SPA_PARAM_Buffers, SPA_PARAM_INFO_READ);
54
+   } else {
55
+       d->params1 = SPA_PARAM_INFO(SPA_PARAM_Format, SPA_PARAM_INFO_WRITE);
56
+       d->params2 = SPA_PARAM_INFO(SPA_PARAM_Buffers, 0);
57
+   }
58
    spa_node_emit_port_info(&d->hooks, SPA_DIRECTION_INPUT, 0, &d->info);
59
 
60
    return 0;
61
pipewire-0.3.59.tar.gz/src/examples/sdl.h -> pipewire-0.3.60.tar.gz/src/examples/sdl.h Changed
44
 
1
@@ -130,25 +130,22 @@
2
 
3
 static inline uint32_t sdl_format_to_id(Uint32 format)
4
 {
5
-   size_t i;
6
-   for (i = 0; i < SPA_N_ELEMENTS(sdl_video_formats); i++) {
7
-       if (sdl_video_formatsi.format == format)
8
-           return sdl_video_formatsi.id;
9
+   SPA_FOR_EACH_ELEMENT_VAR(sdl_video_formats, f) {
10
+       if (f->format == format)
11
+           return f->id;
12
    }
13
    return SPA_VIDEO_FORMAT_UNKNOWN;
14
 }
15
 
16
 static inline Uint32 id_to_sdl_format(uint32_t id)
17
 {
18
-   size_t i;
19
-   for (i = 0; i < SPA_N_ELEMENTS(sdl_video_formats); i++) {
20
-       if (sdl_video_formatsi.id == id)
21
-           return sdl_video_formatsi.format;
22
+   SPA_FOR_EACH_ELEMENT_VAR(sdl_video_formats, f) {
23
+       if (f->id == id)
24
+           return f->format;
25
    }
26
    return SDL_PIXELFORMAT_UNKNOWN;
27
 }
28
 
29
-
30
 static inline struct spa_pod *sdl_build_formats(SDL_RendererInfo *info, struct spa_pod_builder *b)
31
 {
32
    uint32_t i, c;
33
@@ -178,8 +175,8 @@
34
        spa_pod_builder_id(b, id);
35
    }
36
    /* then all the other ones SDL can convert from/to */
37
-   for (i = 0; i < SPA_N_ELEMENTS(sdl_video_formats); i++) {
38
-       uint32_t id = sdl_video_formatsi.id;
39
+   SPA_FOR_EACH_ELEMENT_VAR(sdl_video_formats, f) {
40
+       uint32_t id = f->id;
41
        if (id != SPA_VIDEO_FORMAT_UNKNOWN)
42
            spa_pod_builder_id(b, id);
43
    }
44
pipewire-0.3.59.tar.gz/src/examples/video-play-fixate.c -> pipewire-0.3.60.tar.gz/src/examples/video-play-fixate.c Changed
12
 
1
@@ -340,6 +340,10 @@
2
        pw_stream_set_error(stream, -EINVAL, "unknown pixel format");
3
        return;
4
    }
5
+   if (data->size.width == 0 || data->size.height == 0) {
6
+       pw_stream_set_error(stream, -EINVAL, "invalid size");
7
+       return;
8
+   }
9
 
10
    data->texture = SDL_CreateTexture(data->renderer,
11
                      sdl_format,
12
pipewire-0.3.59.tar.gz/src/examples/video-play-pull.c -> pipewire-0.3.60.tar.gz/src/examples/video-play-pull.c Changed
12
 
1
@@ -388,6 +388,10 @@
2
        pw_stream_set_error(stream, -EINVAL, "unknown pixel format");
3
        return;
4
    }
5
+   if (data->size.width == 0 || data->size.height == 0) {
6
+       pw_stream_set_error(stream, -EINVAL, "invalid size");
7
+       return;
8
+   }
9
 
10
    data->texture = SDL_CreateTexture(data->renderer,
11
                      sdl_format,
12
pipewire-0.3.59.tar.gz/src/examples/video-play-reneg.c -> pipewire-0.3.60.tar.gz/src/examples/video-play-reneg.c Changed
12
 
1
@@ -233,6 +233,10 @@
2
        pw_stream_set_error(stream, -EINVAL, "unknown pixel format");
3
        return;
4
    }
5
+   if (data->size.width == 0 || data->size.height == 0) {
6
+       pw_stream_set_error(stream, -EINVAL, "invalid size");
7
+       return;
8
+   }
9
 
10
    data->texture = SDL_CreateTexture(data->renderer,
11
                      sdl_format,
12
pipewire-0.3.59.tar.gz/src/examples/video-play.c -> pipewire-0.3.60.tar.gz/src/examples/video-play.c Changed
12
 
1
@@ -336,6 +336,10 @@
2
        pw_stream_set_error(stream, -EINVAL, "unknown pixel format");
3
        return;
4
    }
5
+   if (data->size.width == 0 || data->size.height == 0) {
6
+       pw_stream_set_error(stream, -EINVAL, "invalid size");
7
+       return;
8
+   }
9
 
10
    data->texture = SDL_CreateTexture(data->renderer,
11
                      sdl_format,
12
pipewire-0.3.59.tar.gz/src/gst/gstpipewiredeviceprovider.c -> pipewire-0.3.60.tar.gz/src/gst/gstpipewiredeviceprovider.c Changed
10
 
1
@@ -491,6 +491,8 @@
2
           gst_device_provider_hide_provider (provider, "pulsedeviceprovider");
3
    else if (g_str_has_prefix(str, "v4l2:"))
4
           gst_device_provider_hide_provider (provider, "v4l2deviceprovider");
5
+   else if (g_str_has_prefix(str, "libcamera:"))
6
+          gst_device_provider_hide_provider (provider, "libcameraprovider");
7
       }
8
     }
9
 
10
pipewire-0.3.59.tar.gz/src/modules/meson.build -> pipewire-0.3.60.tar.gz/src/modules/meson.build Changed
44
 
1
@@ -26,6 +26,8 @@
2
   'module-rt.c',
3
   'module-raop-discover.c',
4
   'module-raop-sink.c',
5
+  'module-rtp-source.c',
6
+  'module-rtp-sink.c',
7
   'module-session-manager.c',
8
   'module-zeroconf-discover.c',
9
   'module-roc-source.c',
10
@@ -258,6 +260,8 @@
11
   'module-protocol-pulse/modules/module-roc-sink.c',
12
   'module-protocol-pulse/modules/module-roc-sink-input.c',
13
   'module-protocol-pulse/modules/module-roc-source.c',
14
+  'module-protocol-pulse/modules/module-rtp-recv.c',
15
+  'module-protocol-pulse/modules/module-rtp-send.c',
16
   'module-protocol-pulse/modules/module-simple-protocol-tcp.c',
17
   'module-protocol-pulse/modules/module-switch-on-connect.c',
18
   'module-protocol-pulse/modules/module-tunnel-sink.c',
19
@@ -482,6 +486,24 @@
20
 roc_lib = cc.find_library('roc', has_headers: 'roc/config.h' , required: get_option('roc'))
21
 summary({'ROC': roc_lib.found()}, bool_yn: true, section: 'Streaming between daemons')
22
 
23
+pipewire_module_rtp_source = shared_library('pipewire-module-rtp-source',
24
+   'module-rtp-source.c' ,
25
+  include_directories : configinc,
26
+  install : true,
27
+  install_dir : modules_install_dir,
28
+  install_rpath: modules_install_dir,
29
+  dependencies : mathlib, dl_lib, rt_lib, pipewire_dep,
30
+)
31
+
32
+pipewire_module_rtp_sink = shared_library('pipewire-module-rtp-sink',
33
+   'module-rtp-sink.c' ,
34
+  include_directories : configinc,
35
+  install : true,
36
+  install_dir : modules_install_dir,
37
+  install_rpath: modules_install_dir,
38
+  dependencies : mathlib, dl_lib, rt_lib, pipewire_dep,
39
+)
40
+
41
 build_module_roc = roc_lib.found()
42
 if build_module_roc
43
 pipewire_module_roc_sink = shared_library('pipewire-module-roc-sink',
44
pipewire-0.3.59.tar.gz/src/modules/module-avb/acmp.c -> pipewire-0.3.60.tar.gz/src/modules/module-avb/acmp.c Changed
17
 
1
@@ -345,11 +345,10 @@
2
 
3
 static inline const struct msg_info *find_msg_info(uint16_t type, const char *name)
4
 {
5
-   uint32_t i;
6
-   for (i = 0; i < SPA_N_ELEMENTS(msg_info); i++) {
7
-       if ((name == NULL && type == msg_infoi.type) ||
8
-           (name != NULL && spa_streq(name, msg_infoi.name)))
9
-           return &msg_infoi;
10
+   SPA_FOR_EACH_ELEMENT_VAR(msg_info, i) {
11
+       if ((name == NULL && type == i->type) ||
12
+           (name != NULL && spa_streq(name, i->name)))
13
+           return i;
14
    }
15
    return NULL;
16
 }
17
pipewire-0.3.59.tar.gz/src/modules/module-avb/aecp-aem.c -> pipewire-0.3.60.tar.gz/src/modules/module-avb/aecp-aem.c Changed
17
 
1
@@ -250,11 +250,10 @@
2
 
3
 static inline const struct cmd_info *find_cmd_info(uint16_t type, const char *name)
4
 {
5
-   uint32_t i;
6
-   for (i = 0; i < SPA_N_ELEMENTS(cmd_info); i++) {
7
-       if ((name == NULL && type == cmd_infoi.type) ||
8
-           (name != NULL && spa_streq(name, cmd_infoi.name)))
9
-           return &cmd_infoi;
10
+   SPA_FOR_EACH_ELEMENT_VAR(cmd_info, i) {
11
+       if ((name == NULL && type == i->type) ||
12
+           (name != NULL && spa_streq(name, i->name)))
13
+           return i;
14
    }
15
    return NULL;
16
 }
17
pipewire-0.3.59.tar.gz/src/modules/module-avb/aecp.c -> pipewire-0.3.60.tar.gz/src/modules/module-avb/aecp.c Changed
17
 
1
@@ -67,11 +67,10 @@
2
 
3
 static inline const struct msg_info *find_msg_info(uint16_t type, const char *name)
4
 {
5
-   uint32_t i;
6
-   for (i = 0; i < SPA_N_ELEMENTS(msg_info); i++) {
7
-       if ((name == NULL && type == msg_infoi.type) ||
8
-           (name != NULL && spa_streq(name, msg_infoi.name)))
9
-           return &msg_infoi;
10
+   SPA_FOR_EACH_ELEMENT_VAR(msg_info, i) {
11
+       if ((name == NULL && type == i->type) ||
12
+           (name != NULL && spa_streq(name, i->name)))
13
+           return i;
14
    }
15
    return NULL;
16
 }
17
pipewire-0.3.59.tar.gz/src/modules/module-client-node/v0/client-node.c -> pipewire-0.3.60.tar.gz/src/modules/module-client-node/v0/client-node.c Changed
19
 
1
@@ -1333,13 +1333,12 @@
2
        { "pipewire.target.node", PW_KEY_NODE_TARGET, }
3
    };
4
 
5
-   uint32_t i;
6
    const char *str;
7
 
8
-   for(i = 0; i < SPA_N_ELEMENTS(props); i++) {
9
-       if ((str = pw_properties_get(properties, propsi.from)) != NULL) {
10
-           pw_properties_set(properties, propsi.to, str);
11
-           pw_properties_set(properties, propsi.from, NULL);
12
+   SPA_FOR_EACH_ELEMENT_VAR(props, p) {
13
+       if ((str = pw_properties_get(properties, p->from)) != NULL) {
14
+           pw_properties_set(properties, p->to, str);
15
+           pw_properties_set(properties, p->from, NULL);
16
        }
17
    }
18
 }
19
pipewire-0.3.59.tar.gz/src/modules/module-echo-cancel.c -> pipewire-0.3.60.tar.gz/src/modules/module-echo-cancel.c Changed
201
 
1
@@ -43,6 +43,7 @@
2
 #include <spa/param/audio/raw.h>
3
 #include <spa/param/profiler.h>
4
 #include <spa/pod/builder.h>
5
+#include <spa/pod/dynamic.h>
6
 #include <spa/support/plugin.h>
7
 #include <spa/utils/json.h>
8
 #include <spa/utils/names.h>
9
@@ -196,15 +197,18 @@
10
 
11
    uint32_t max_buffer_size;
12
    uint32_t buffer_delay;
13
+   uint32_t current_delay;
14
 
15
    struct spa_handle *spa_handle;
16
    struct spa_plugin_loader *loader;
17
+
18
+   bool monitor_mode;
19
 };
20
 
21
 static void process(struct impl *impl)
22
 {
23
    struct pw_buffer *cout;
24
-   struct pw_buffer *pout;
25
+   struct pw_buffer *pout = NULL;
26
    float rec_bufimpl->info.channelsimpl->aec_blocksize / sizeof(float);
27
    float play_bufimpl->info.channelsimpl->aec_blocksize / sizeof(float);
28
    float play_delayed_bufimpl->info.channelsimpl->aec_blocksize / sizeof(float);
29
@@ -218,7 +222,7 @@
30
    uint32_t rindex, pindex, oindex, pdindex, avail;
31
    int32_t stride = 0;
32
 
33
-   if ((pout = pw_stream_dequeue_buffer(impl->playback)) == NULL) {
34
+   if (impl->playback != NULL && (pout = pw_stream_dequeue_buffer(impl->playback)) == NULL) {
35
        pw_log_debug("out of playback buffers: %m");
36
        goto done;
37
    }
38
@@ -256,23 +260,50 @@
39
                impl->play_ringsize, pdindex % impl->play_ringsize,
40
                (void *)play_delayedi, size);
41
 
42
-       /* output to sink, just copy */
43
-       dd = &pout->buffer->datasi;
44
-       memcpy(dd->data, playi, size);
45
+       if (pout != NULL) {
46
+           /* output to sink, just copy */
47
+           dd = &pout->buffer->datasi;
48
+           memcpy(dd->data, playi, size);
49
 
50
-       dd->chunk->offset = 0;
51
-       dd->chunk->size = size;
52
-       dd->chunk->stride = stride;
53
+           dd->chunk->offset = 0;
54
+           dd->chunk->size = size;
55
+           dd->chunk->stride = stride;
56
+       }
57
    }
58
 
59
    spa_ringbuffer_read_update(&impl->rec_ring, rindex + size);
60
    spa_ringbuffer_read_update(&impl->play_ring, pindex + size);
61
    spa_ringbuffer_read_update(&impl->play_delayed_ring, pdindex + size);
62
 
63
-   pw_stream_queue_buffer(impl->playback, pout);
64
+   if (impl->playback != NULL)
65
+       pw_stream_queue_buffer(impl->playback, pout);
66
 
67
-   /* Now run the canceller */
68
-   spa_audio_aec_run(impl->aec, rec, play_delayed, out, size / sizeof(float));
69
+   if (SPA_UNLIKELY (impl->current_delay < impl->buffer_delay)) {
70
+       uint32_t delay_left = impl->buffer_delay - impl->current_delay;
71
+       uint32_t silence_size;
72
+
73
+       /* don't run the canceller until play_buffer has been filled,
74
+        * copy silence to output in the meantime */
75
+       silence_size = SPA_MIN(size, delay_left * sizeof(float));
76
+       for (i = 0; i < impl->info.channels; i++)
77
+           memset(outi, 0, silence_size);
78
+       impl->current_delay += silence_size / sizeof(float);
79
+       pw_log_debug("current_delay %d", impl->current_delay);
80
+
81
+       if (silence_size != size) {
82
+           const float *pdimpl->info.channels;
83
+           float *oimpl->info.channels;
84
+
85
+           for (i = 0; i < impl->info.channels; i++) {
86
+               pdi = play_delayedi + delay_left;
87
+               oi = outi + delay_left;
88
+           }
89
+           spa_audio_aec_run(impl->aec, rec, pd, o, size / sizeof(float) - delay_left);
90
+       }
91
+   } else {
92
+       /* run the canceller */
93
+       spa_audio_aec_run(impl->aec, rec, play_delayed, out, size / sizeof(float));
94
+   }
95
 
96
    /* Next, copy over the output to the output ringbuffer */
97
    avail = spa_ringbuffer_get_write_index(&impl->out_ring, &oindex);
98
@@ -479,14 +510,55 @@
99
    else
100
        pw_stream_update_params(impl->capture, params, 1);
101
 }
102
+static struct spa_pod* get_props_param(struct impl* impl, struct spa_pod_builder* b)
103
+{
104
+   if (spa_audio_aec_get_params(impl->aec, NULL) > 0) {
105
+       struct spa_pod_frame f2;
106
+       spa_pod_builder_push_object(
107
+           b, &f0, SPA_TYPE_OBJECT_Props, SPA_PARAM_Props);
108
+       spa_pod_builder_prop(b, SPA_PROP_params, 0);
109
+       spa_pod_builder_push_struct(b, &f1);
110
+
111
+       spa_audio_aec_get_params(impl->aec, b);
112
+
113
+       spa_pod_builder_pop(b, &f1);
114
+       return spa_pod_builder_pop(b, &f0);
115
+   }
116
+   return NULL;
117
+}
118
 
119
-static void input_param_changed(void *data, uint32_t id, const struct spa_pod *param)
120
+static void input_param_changed(void *data, uint32_t id, const struct spa_pod* param)
121
 {
122
-   struct impl *impl = data;
123
+   struct spa_pod_object* obj = (struct spa_pod_object*)param;
124
+   const struct spa_pod_prop* prop;
125
+   struct impl* impl = data;
126
    switch (id) {
127
    case SPA_PARAM_Latency:
128
        input_param_latency_changed(impl, param);
129
        break;
130
+   case SPA_PARAM_Props:
131
+       if (param != NULL) {
132
+           uint8_t buffer1024;
133
+           struct spa_pod_dynamic_builder b;
134
+           const struct spa_pod* params1;
135
+           SPA_POD_OBJECT_FOREACH(obj, prop)
136
+           {
137
+               if (prop->key == SPA_PROP_params) {
138
+                   spa_audio_aec_set_params(impl->aec, &prop->value);
139
+               }
140
+           }
141
+
142
+           spa_pod_dynamic_builder_init(&b, buffer, sizeof(buffer), 4096);
143
+           params0 = get_props_param(impl, &b.b);
144
+           if (params0) {
145
+               pw_stream_update_params(impl->capture, params, 1);
146
+               pw_stream_update_params(impl->playback, params, 1);
147
+           }
148
+           spa_pod_dynamic_builder_clean(&b);
149
+       } else {
150
+           pw_log_warn("param is null");
151
+       }
152
+       break;
153
    }
154
 }
155
 
156
@@ -519,7 +591,11 @@
157
    switch (state) {
158
    case PW_STREAM_STATE_PAUSED:
159
        pw_stream_flush(impl->sink, false);
160
-       pw_stream_flush(impl->playback, false);
161
+       if (impl->playback != NULL)
162
+           pw_stream_flush(impl->playback, false);
163
+       if (old == PW_STREAM_STATE_STREAMING) {
164
+           impl->current_delay = 0;
165
+       }
166
        break;
167
    case PW_STREAM_STATE_UNCONNECTED:
168
        pw_log_info("%p: output unconnected", impl);
169
@@ -548,17 +624,40 @@
170
 
171
    if (latency.direction == SPA_DIRECTION_INPUT)
172
        pw_stream_update_params(impl->sink, params, 1);
173
-   else
174
+   else if (impl->playback != NULL)
175
        pw_stream_update_params(impl->playback, params, 1);
176
 }
177
 
178
 static void output_param_changed(void *data, uint32_t id, const struct spa_pod *param)
179
 {
180
+   struct spa_pod_object *obj = (struct spa_pod_object *) param;
181
+   const struct spa_pod_prop *prop;
182
    struct impl *impl = data;
183
    switch (id) {
184
    case SPA_PARAM_Latency:
185
        output_param_latency_changed(impl, param);
186
        break;
187
+   case SPA_PARAM_Props:
188
+       if (param != NULL) {
189
+           uint8_t buffer1024;
190
+           struct spa_pod_dynamic_builder b;
191
+           const struct spa_pod* params1;
192
+
193
+           SPA_POD_OBJECT_FOREACH(obj, prop)
194
+           {
195
+               if (prop->key == SPA_PROP_params) {
196
+                   spa_audio_aec_set_params(impl->aec, &prop->value);
197
+               }
198
+           }
199
+           spa_pod_dynamic_builder_init(&b, buffer, sizeof(buffer), 4096);
200
+           params0 = get_props_param(impl, &b.b);
201
pipewire-0.3.59.tar.gz/src/modules/module-filter-chain.c -> pipewire-0.3.60.tar.gz/src/modules/module-filter-chain.c Changed
194
 
1
@@ -785,10 +785,10 @@
2
    spa_pod_builder_prop(b, SPA_PROP_INFO_type, 0);
3
    if (p->hint & FC_HINT_BOOLEAN) {
4
        if (min == max) {
5
-           spa_pod_builder_bool(b, def <= 0.0 ? false : true);
6
+           spa_pod_builder_bool(b, def <= 0.0f ? false : true);
7
        } else  {
8
            spa_pod_builder_push_choice(b, &f1, SPA_CHOICE_Enum, 0);
9
-           spa_pod_builder_bool(b, def <= 0.0 ? false : true);
10
+           spa_pod_builder_bool(b, def <= 0.0f ? false : true);
11
            spa_pod_builder_bool(b, false);
12
            spa_pod_builder_bool(b, true);
13
            spa_pod_builder_pop(b, &f1);
14
@@ -844,7 +844,7 @@
15
 
16
        spa_pod_builder_string(b, name);
17
        if (p->hint & FC_HINT_BOOLEAN) {
18
-           spa_pod_builder_bool(b, port->control_data <= 0.0 ? false : true);
19
+           spa_pod_builder_bool(b, port->control_data <= 0.0f ? false : true);
20
        } else if (p->hint & FC_HINT_INTEGER) {
21
            spa_pod_builder_int(b, port->control_data);
22
        } else {
23
@@ -1002,6 +1002,7 @@
24
 {
25
    struct impl *impl = data;
26
    struct graph *graph = &impl->graph;
27
+   int res;
28
 
29
    switch (id) {
30
    case SPA_PARAM_Format:
31
@@ -1010,9 +1011,15 @@
32
        } else {
33
            struct spa_audio_info_raw info;
34
            spa_zero(info);
35
-           spa_format_audio_raw_parse(param, &info);
36
+           if ((res = spa_format_audio_raw_parse(param, &info)) < 0)
37
+               goto error;
38
+           if (info.rate == 0) {
39
+               res = -EINVAL;
40
+               goto error;
41
+           }
42
            impl->rate = info.rate;
43
-           graph_instantiate(graph);
44
+           if ((res = graph_instantiate(graph)) < 0)
45
+               goto error;
46
        }
47
        break;
48
    case SPA_PARAM_Props:
49
@@ -1023,6 +1030,11 @@
50
        param_latency_changed(impl, param);
51
        break;
52
    }
53
+   return;
54
+
55
+error:
56
+   pw_stream_set_error(impl->capture, res, "can't start graph: %s",
57
+           spa_strerror(res));
58
 }
59
 
60
 static const struct pw_stream_events in_stream_events = {
61
@@ -1172,16 +1184,19 @@
62
    else if (spa_streq(type, "ladspa")) {
63
        pl = load_ladspa_plugin(support, n_support, path, NULL);
64
    }
65
-#ifdef HAVE_LILV
66
    else if (spa_streq(type, "lv2")) {
67
+#ifdef HAVE_LILV
68
        pl = load_lv2_plugin(support, n_support, path, NULL);
69
-   }
70
+#else
71
+       pw_log_error("filter-chain is compiled without lv2 support");
72
+       pl = NULL;
73
+       errno = ENOTSUP;
74
 #endif
75
-   else {
76
+   } else {
77
+       pw_log_error("invalid plugin type '%s'", type);
78
        pl = NULL;
79
        errno = EINVAL;
80
    }
81
-
82
    if (pl == NULL)
83
        goto exit;
84
 
85
@@ -1501,7 +1516,6 @@
86
    bool have_config = false;
87
    uint32_t i;
88
    int res;
89
-   float *data;
90
 
91
    while (spa_json_get_string(json, key, sizeof(key)) > 0) {
92
        if (spa_streq("type", key)) {
93
@@ -1539,10 +1553,8 @@
94
            break;
95
    }
96
 
97
-   if (spa_streq(type, "builtin")) {
98
+   if (spa_streq(type, "builtin"))
99
        snprintf(plugin, sizeof(plugin), "%s", "builtin");
100
-   } else if (!spa_streq(type, "ladspa") && !spa_streq(type, "lv2"))
101
-       return -ENOTSUP;
102
 
103
    pw_log_info("loading type:%s plugin:%s label:%s", type, plugin, label);
104
 
105
@@ -1562,6 +1574,10 @@
106
    node->control_port = calloc(desc->n_control, sizeof(struct port));
107
    node->notify_port = calloc(desc->n_notify, sizeof(struct port));
108
 
109
+   pw_log_info("loaded n_input:%d n_output:%d n_control:%d n_notify:%d",
110
+           desc->n_input, desc->n_output,
111
+           desc->n_control, desc->n_notify);
112
+
113
    for (i = 0; i < desc->n_input; i++) {
114
        struct port *port = &node->input_porti;
115
        port->node = node;
116
@@ -1576,14 +1592,6 @@
117
        port->idx = i;
118
        port->external = SPA_ID_INVALID;
119
        port->p = desc->outputi;
120
-       if ((data = port->audio_datai) == NULL) {
121
-           data = calloc(1, MAX_SAMPLES * sizeof(float));
122
-           if (data == NULL) {
123
-               pw_log_error("cannot create port data: %m");
124
-               return -errno;
125
-           }
126
-       }
127
-       port->audio_datai = data;
128
        spa_list_init(&port->link_list);
129
    }
130
    for (i = 0; i < desc->n_control; i++) {
131
@@ -1629,6 +1637,26 @@
132
    }
133
 }
134
 
135
+static int port_ensure_data(struct port *port, uint32_t i)
136
+{
137
+   float *data;
138
+   if ((data = port->audio_datai) == NULL) {
139
+       data = calloc(1, MAX_SAMPLES * sizeof(float));
140
+       if (data == NULL) {
141
+           pw_log_error("cannot create port data: %m");
142
+           return -errno;
143
+       }
144
+   }
145
+   port->audio_datai = data;
146
+   return 0;
147
+}
148
+
149
+static void port_free_data(struct port *port, uint32_t i)
150
+{
151
+   free(port->audio_datai);
152
+   port->audio_datai = NULL;
153
+}
154
+
155
 static void node_free(struct node *node)
156
 {
157
    uint32_t i, j;
158
@@ -1636,7 +1664,7 @@
159
    spa_list_remove(&node->link);
160
    for (i = 0; i < node->n_hndl; i++) {
161
        for (j = 0; j < node->desc->n_output; j++)
162
-           free(node->output_portj.audio_datai);
163
+           port_free_data(&node->output_portj, i);
164
    }
165
    node_cleanup(node);
166
    descriptor_unref(node->desc);
167
@@ -1688,6 +1716,8 @@
168
 
169
                spa_list_for_each(link, &port->link_list, input_link) {
170
                    struct port *peer = link->output;
171
+                   if ((res = port_ensure_data(peer, i)) < 0)
172
+                       goto error;
173
                    pw_log_info("connect input port %s%d:%s %p",
174
                            node->name, i, d->portsport->p.name,
175
                            peer->audio_datai);
176
@@ -1696,6 +1726,8 @@
177
            }
178
            for (j = 0; j < desc->n_output; j++) {
179
                port = &node->output_portj;
180
+               if ((res = port_ensure_data(port, i)) < 0)
181
+                   goto error;
182
                pw_log_info("connect output port %s%d:%s %p",
183
                        node->name, i, d->portsport->p.name,
184
                        port->audio_datai);
185
@@ -1938,6 +1970,8 @@
186
            gh->hndl = &node->hndli;
187
            gh->desc = d;
188
 
189
+       }
190
+       for (i = 0; i < desc->n_output; i++) {
191
            spa_list_for_each(link, &node->output_porti.link_list, output_link)
192
                link->input->node->n_deps--;
193
        }
194
pipewire-0.3.59.tar.gz/src/modules/module-filter-chain/biquad.c -> pipewire-0.3.60.tar.gz/src/modules/module-filter-chain/biquad.c Changed
132
 
1
@@ -11,24 +11,6 @@
2
 #include <math.h>
3
 #include "biquad.h"
4
 
5
-#ifndef max
6
-#define max(a, b)                                                              \
7
-   ({                                                                     \
8
-       __typeof__(a) _a = (a);                                        \
9
-       __typeof__(b) _b = (b);                                        \
10
-       _a > _b ? _a : _b;                                             \
11
-   })
12
-#endif
13
-
14
-#ifndef min
15
-#define min(a, b)                                                              \
16
-   ({                                                                     \
17
-       __typeof__(a) _a = (a);                                        \
18
-       __typeof__(b) _b = (b);                                        \
19
-       _a < _b ? _a : _b;                                             \
20
-   })
21
-#endif
22
-
23
 #ifndef M_PI
24
 #define M_PI 3.14159265358979323846
25
 #endif
26
@@ -47,7 +29,7 @@
27
 static void biquad_lowpass(struct biquad *bq, double cutoff, double resonance)
28
 {
29
    /* Limit cutoff to 0 to 1. */
30
-   cutoff = max(0.0, min(cutoff, 1.0));
31
+   cutoff = fmax(0.0, fmin(cutoff, 1.0));
32
 
33
    if (cutoff == 1 || cutoff == 0) {
34
        /* When cutoff is 1, the z-transform is 1.
35
@@ -59,7 +41,7 @@
36
    }
37
 
38
    /* Compute biquad coefficients for lowpass filter */
39
-   resonance = max(0.0, resonance); /* can't go negative */
40
+   resonance = fmax(0.0, resonance); /* can't go negative */
41
    double g = pow(10.0, 0.05 * resonance);
42
    double d = sqrt((4 - sqrt(16 - 16 / (g * g))) / 2);
43
 
44
@@ -81,7 +63,7 @@
45
 static void biquad_highpass(struct biquad *bq, double cutoff, double resonance)
46
 {
47
    /* Limit cutoff to 0 to 1. */
48
-   cutoff = max(0.0, min(cutoff, 1.0));
49
+   cutoff = fmax(0.0, fmin(cutoff, 1.0));
50
 
51
    if (cutoff == 1 || cutoff == 0) {
52
        /* When cutoff is one, the z-transform is 0. */
53
@@ -95,7 +77,7 @@
54
    }
55
 
56
    /* Compute biquad coefficients for highpass filter */
57
-   resonance = max(0.0, resonance); /* can't go negative */
58
+   resonance = fmax(0.0, resonance); /* can't go negative */
59
    double g = pow(10.0, 0.05 * resonance);
60
    double d = sqrt((4 - sqrt(16 - 16 / (g * g))) / 2);
61
 
62
@@ -117,10 +99,10 @@
63
 static void biquad_bandpass(struct biquad *bq, double frequency, double Q)
64
 {
65
    /* No negative frequencies allowed. */
66
-   frequency = max(0.0, frequency);
67
+   frequency = fmax(0.0, frequency);
68
 
69
    /* Don't let Q go negative, which causes an unstable filter. */
70
-   Q = max(0.0, Q);
71
+   Q = fmax(0.0, Q);
72
 
73
    if (frequency <= 0 || frequency >= 1) {
74
        /* When the cutoff is zero, the z-transform approaches 0, if Q
75
@@ -158,7 +140,7 @@
76
 static void biquad_lowshelf(struct biquad *bq, double frequency, double db_gain)
77
 {
78
    /* Clip frequencies to between 0 and 1, inclusive. */
79
-   frequency = max(0.0, min(frequency, 1.0));
80
+   frequency = fmax(0.0, fmin(frequency, 1.0));
81
 
82
    double A = pow(10.0, db_gain / 40);
83
 
84
@@ -195,7 +177,7 @@
85
                 double db_gain)
86
 {
87
    /* Clip frequencies to between 0 and 1, inclusive. */
88
-   frequency = max(0.0, min(frequency, 1.0));
89
+   frequency = fmax(0.0, fmin(frequency, 1.0));
90
 
91
    double A = pow(10.0, db_gain / 40);
92
 
93
@@ -232,10 +214,10 @@
94
               double db_gain)
95
 {
96
    /* Clip frequencies to between 0 and 1, inclusive. */
97
-   frequency = max(0.0, min(frequency, 1.0));
98
+   frequency = fmax(0.0, fmin(frequency, 1.0));
99
 
100
    /* Don't let Q go negative, which causes an unstable filter. */
101
-   Q = max(0.0, Q);
102
+   Q = fmax(0.0, Q);
103
 
104
    double A = pow(10.0, db_gain / 40);
105
 
106
@@ -270,10 +252,10 @@
107
 static void biquad_notch(struct biquad *bq, double frequency, double Q)
108
 {
109
    /* Clip frequencies to between 0 and 1, inclusive. */
110
-   frequency = max(0.0, min(frequency, 1.0));
111
+   frequency = fmax(0.0, fmin(frequency, 1.0));
112
 
113
    /* Don't let Q go negative, which causes an unstable filter. */
114
-   Q = max(0.0, Q);
115
+   Q = fmax(0.0, Q);
116
 
117
    if (frequency <= 0 || frequency >= 1) {
118
        /* When frequency is 0 or 1, the z-transform is 1. */
119
@@ -306,10 +288,10 @@
120
 static void biquad_allpass(struct biquad *bq, double frequency, double Q)
121
 {
122
    /* Clip frequencies to between 0 and 1, inclusive. */
123
-   frequency = max(0.0, min(frequency, 1.0));
124
+   frequency = fmax(0.0, fmin(frequency, 1.0));
125
 
126
    /* Don't let Q go negative, which causes an unstable filter. */
127
-   Q = max(0.0, Q);
128
+   Q = fmax(0.0, Q);
129
 
130
    if (frequency <= 0 || frequency >= 1) {
131
        /* When frequency is 0 or 1, the z-transform is 1. */
132
pipewire-0.3.59.tar.gz/src/modules/module-filter-chain/builtin_plugin.c -> pipewire-0.3.60.tar.gz/src/modules/module-filter-chain/builtin_plugin.c Changed
122
 
1
@@ -590,6 +590,7 @@
2
    float gain = 1.0f;
3
    unsigned long rate;
4
 
5
+   errno = EINVAL;
6
    if (config == NULL)
7
        return NULL;
8
 
9
@@ -599,42 +600,60 @@
10
 
11
    while (spa_json_get_string(&it1, key, sizeof(key)) > 0) {
12
        if (spa_streq(key, "blocksize")) {
13
-           if (spa_json_get_int(&it1, &blocksize) <= 0)
14
+           if (spa_json_get_int(&it1, &blocksize) <= 0) {
15
+               pw_log_error("convolver:blocksize requires a number");
16
                return NULL;
17
+           }
18
        }
19
        else if (spa_streq(key, "tailsize")) {
20
-           if (spa_json_get_int(&it1, &tailsize) <= 0)
21
+           if (spa_json_get_int(&it1, &tailsize) <= 0) {
22
+               pw_log_error("convolver:tailsize requires a number");
23
                return NULL;
24
+           }
25
        }
26
        else if (spa_streq(key, "gain")) {
27
-           if (spa_json_get_float(&it1, &gain) <= 0)
28
+           if (spa_json_get_float(&it1, &gain) <= 0) {
29
+               pw_log_error("convolver:gain requires a number");
30
                return NULL;
31
+           }
32
        }
33
        else if (spa_streq(key, "delay")) {
34
-           if (spa_json_get_int(&it1, &delay) <= 0)
35
+           if (spa_json_get_int(&it1, &delay) <= 0) {
36
+               pw_log_error("convolver:delay requires a number");
37
                return NULL;
38
+           }
39
        }
40
        else if (spa_streq(key, "filename")) {
41
-           if (spa_json_get_string(&it1, filename, sizeof(filename)) <= 0)
42
+           if (spa_json_get_string(&it1, filename, sizeof(filename)) <= 0) {
43
+               pw_log_error("convolver:filename requires a string");
44
                return NULL;
45
+           }
46
        }
47
        else if (spa_streq(key, "offset")) {
48
-           if (spa_json_get_int(&it1, &offset) <= 0)
49
+           if (spa_json_get_int(&it1, &offset) <= 0) {
50
+               pw_log_error("convolver:offset requires a number");
51
                return NULL;
52
+           }
53
        }
54
        else if (spa_streq(key, "length")) {
55
-           if (spa_json_get_int(&it1, &length) <= 0)
56
+           if (spa_json_get_int(&it1, &length) <= 0) {
57
+               pw_log_error("convolver:length requires a number");
58
                return NULL;
59
+           }
60
        }
61
        else if (spa_streq(key, "channel")) {
62
-           if (spa_json_get_int(&it1, &channel) <= 0)
63
+           if (spa_json_get_int(&it1, &channel) <= 0) {
64
+               pw_log_error("convolver:channel requires a number");
65
                return NULL;
66
+           }
67
        }
68
        else if (spa_json_next(&it1, &val) < 0)
69
            break;
70
    }
71
-   if (!filename0)
72
+   if (!filename0) {
73
+       pw_log_error("convolver:filename was not given");
74
        return NULL;
75
+   }
76
 
77
    if (delay < 0)
78
        delay = 0;
79
@@ -656,15 +675,18 @@
80
                    "Consider forcing a filter rate.", rate, SampleRate);
81
        }
82
    }
83
-   if (samples == NULL)
84
+   if (samples == NULL) {
85
+       errno = ENOENT;
86
        return NULL;
87
+   }
88
 
89
    if (blocksize <= 0)
90
        blocksize = SPA_CLAMP(n_samples, 64, 256);
91
    if (tailsize <= 0)
92
-       tailsize = SPA_CLAMP(4096, blocksize, 4096);
93
+       tailsize = SPA_CLAMP(4096, blocksize, 32768);
94
 
95
-   pw_log_info("using %d:%d blocksize ir:%s", blocksize, tailsize, filename);
96
+   pw_log_info("using n_samples:%u %d:%d blocksize ir:%s", n_samples,
97
+           blocksize, tailsize, filename);
98
 
99
    impl = calloc(1, sizeof(*impl));
100
    if (impl == NULL)
101
@@ -775,8 +797,10 @@
102
 
103
    while (spa_json_get_string(&it1, key, sizeof(key)) > 0) {
104
        if (spa_streq(key, "max-delay")) {
105
-           if (spa_json_get_float(&it1, &max_delay) <= 0)
106
+           if (spa_json_get_float(&it1, &max_delay) <= 0) {
107
+               pw_log_error("delay:max-delay requires a number");
108
                return NULL;
109
+           }
110
        }
111
        else if (spa_json_next(&it1, &val) < 0)
112
            break;
113
@@ -790,7 +814,7 @@
114
 
115
    impl->rate = SampleRate;
116
    impl->buffer_samples = max_delay * impl->rate;
117
-   pw_log_info("%lu %d", impl->rate, impl->buffer_samples);
118
+   pw_log_info("max-delay:%f seconds rate:%lu samples:%d", max_delay, impl->rate, impl->buffer_samples);
119
 
120
    impl->buffer = calloc(impl->buffer_samples, sizeof(float));
121
    if (impl->buffer == NULL) {
122
pipewire-0.3.59.tar.gz/src/modules/module-filter-chain/convolver.c -> pipewire-0.3.60.tar.gz/src/modules/module-filter-chain/convolver.c Changed
10
 
1
@@ -251,7 +251,7 @@
2
 {
3
    int i, processed = 0;
4
 
5
-   if (conv->segCount == 0) {
6
+   if (conv == NULL || conv->segCount == 0) {
7
        fft_clear(output, len);
8
        return len;
9
    }
10
pipewire-0.3.59.tar.gz/src/modules/module-filter-chain/ladspa_plugin.c -> pipewire-0.3.60.tar.gz/src/modules/module-filter-chain/ladspa_plugin.c Changed
70
 
1
@@ -22,6 +22,8 @@
2
  * DEALINGS IN THE SOFTWARE.
3
  */
4
 
5
+#include "config.h"
6
+
7
 #include <dlfcn.h>
8
 #include <math.h>
9
 
10
@@ -80,39 +82,39 @@
11
        break;
12
    case LADSPA_HINT_DEFAULT_LOW:
13
        if (LADSPA_IS_HINT_LOGARITHMIC(hint))
14
-           def = (LADSPA_Data) exp(log(lower) * 0.75 + log(upper) * 0.25);
15
+           def = (LADSPA_Data) expf(logf(lower) * 0.75f + logf(upper) * 0.25f);
16
        else
17
-           def = (LADSPA_Data) (lower * 0.75 + upper * 0.25);
18
+           def = (LADSPA_Data) (lower * 0.75f + upper * 0.25f);
19
        break;
20
    case LADSPA_HINT_DEFAULT_MIDDLE:
21
        if (LADSPA_IS_HINT_LOGARITHMIC(hint))
22
-           def = (LADSPA_Data) exp(log(lower) * 0.5 + log(upper) * 0.5);
23
+           def = (LADSPA_Data) expf(logf(lower) * 0.5f + logf(upper) * 0.5f);
24
        else
25
-           def = (LADSPA_Data) (lower * 0.5 + upper * 0.5);
26
+           def = (LADSPA_Data) (lower * 0.5f + upper * 0.5f);
27
        break;
28
    case LADSPA_HINT_DEFAULT_HIGH:
29
        if (LADSPA_IS_HINT_LOGARITHMIC(hint))
30
-           def = (LADSPA_Data) exp(log(lower) * 0.25 + log(upper) * 0.75);
31
+           def = (LADSPA_Data) expf(logf(lower) * 0.25f + logf(upper) * 0.75f);
32
        else
33
-           def = (LADSPA_Data) (lower * 0.25 + upper * 0.75);
34
+           def = (LADSPA_Data) (lower * 0.25f + upper * 0.75f);
35
        break;
36
    case LADSPA_HINT_DEFAULT_0:
37
-       def = 0;
38
+       def = 0.0f;
39
        break;
40
    case LADSPA_HINT_DEFAULT_1:
41
-       def = 1;
42
+       def = 1.0f;
43
        break;
44
    case LADSPA_HINT_DEFAULT_100:
45
-       def = 100;
46
+       def = 100.0f;
47
        break;
48
    case LADSPA_HINT_DEFAULT_440:
49
-       def = 440;
50
+       def = 440.0f;
51
        break;
52
    default:
53
        if (upper == lower)
54
            def = upper;
55
        else
56
-           def = SPA_CLAMP(0.5 * upper, lower, upper);
57
+           def = SPA_CLAMPF(0.5f * upper, lower, upper);
58
        break;
59
    }
60
    if (LADSPA_IS_HINT_INTEGER(hint))
61
@@ -238,7 +240,7 @@
62
 
63
        search_dirs = getenv("LADSPA_PATH");
64
        if (!search_dirs)
65
-           search_dirs = "/usr/lib64/ladspa";
66
+           search_dirs = "/usr/lib64/ladspa:/usr/lib/ladspa:" LIBDIR;
67
 
68
        /*
69
         * set the errno for the case when `ladspa_handle_load_by_path()`
70
pipewire-0.3.59.tar.gz/src/modules/module-filter-chain/pffft.c -> pipewire-0.3.60.tar.gz/src/modules/module-filter-chain/pffft.c Changed
73
 
1
@@ -25,7 +25,7 @@
2
    Laboratory, the University Corporation for Atmospheric Research,
3
    nor the names of its sponsors or contributors may be used to
4
    endorse or promote products derived from this Software without
5
-   specific prior written permission.  
6
+   specific prior written permission.
7
 
8
    - Redistributions of source code must retain the above copyright
9
    notices, this list of conditions, and the disclaimer below.
10
@@ -52,7 +52,7 @@
11
 */
12
 
13
 /*
14
-  ChangeLog: 
15
+  ChangeLog:
16
   - 2011/10/02, version 1: This is the very first release of this file.
17
 */
18
 
19
@@ -243,7 +243,7 @@
20
 #define assertv4(v,f0,f1,f2,f3) assert(v.f0 == (f0) && v.f1 == (f1) && v.f2 == (f2) && v.f3 == (f3))
21
 
22
 /* detect bugs with the vector support macros */
23
-static void validate_pffft_simd()
24
+static void validate_pffft_simd(void)
25
 {
26
    float f16 = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 };
27
    v4sf_union a0, a1, a2, a3, t, u;
28
@@ -301,7 +301,7 @@
29
    assertv4(a3, 3, 7, 11, 15);
30
 }
31
 #else
32
-static void validate_pffft_simd()
33
+static void validate_pffft_simd(void)
34
 {
35
 }              // allow test_pffft.c to call this function even when simd is not available..
36
 #endif             //!PFFFT_SIMD_DISABLE
37
@@ -1421,7 +1421,7 @@
38
 {
39
    PFFFT_Setup *s = (PFFFT_Setup *) malloc(sizeof(PFFFT_Setup));
40
    int k, m;
41
-   /* unfortunately, the fft size must be a multiple of 16 for complex FFTs 
42
+   /* unfortunately, the fft size must be a multiple of 16 for complex FFTs
43
       and 32 for real FFTs -- a lot of stuff would need to be rewritten to
44
       handle other cases (or maybe just switch to a scalar fft, I don't know..) */
45
    if (transform == PFFFT_REAL) {
46
@@ -1615,7 +1615,7 @@
47
           0   0   0   0   1   1   1   1 * i0
48
           0   1   0  -1   1   0  -1   0   i1
49
           0   0   0   0   1  -1   1  -1   i2
50
-          0  -1   0   1   1   0  -1   0   i3    
51
+          0  -1   0   1   1   0  -1   0   i3
52
         */
53
 
54
        r0 = VADD(sr0, sr1);
55
@@ -1719,7 +1719,7 @@
56
       0   0   0   0   1   1   1   1 * i0
57
       0  -1   0   1  -1   0   1   0   i1
58
       0  -1   0   1   1   0  -1   0   i2
59
-      0   0   0   0  -1   1  -1   1   i3    
60
+      0   0   0   0  -1   1  -1   1   i3
61
     */
62
 
63
    //cerr << "matrix initial, before e , REAL:\n 1: " << r0 << "\n 1: " << r1 << "\n 1: " << r2 << "\n 1: " << r3 << "\n";
64
@@ -1832,7 +1832,7 @@
65
       0   0   0   0   1  -1   1  -1 * i0
66
       0  -1   1   0   1   0   0   1   i1
67
       0   0   0   0   1   1  -1  -1   i2
68
-      0   1  -1   0   1   0   0   1   i3    
69
+      0   1  -1   0   1   0   0   1   i3
70
     */
71
 
72
    v4sf sr0 = VADD(r0, r3), dr0 = VSUB(r0, r3);
73
pipewire-0.3.59.tar.gz/src/modules/module-filter-chain/pffft.h -> pipewire-0.3.60.tar.gz/src/modules/module-filter-chain/pffft.h Changed
17
 
1
@@ -165,13 +165,13 @@
2
   /*
3
     the float buffers must have the correct alignment (16-byte boundary
4
     on intel and powerpc). This function may be used to obtain such
5
-    correctly aligned buffers. 
6
+    correctly aligned buffers.
7
   */
8
   void *pffft_aligned_malloc(size_t nb_bytes);
9
   void pffft_aligned_free(void *);
10
 
11
   /* return 4 or 1 depending on whether support for SSE/Altivec instructions was enabled when building pffft.c */
12
-  int pffft_simd_size();
13
+  int pffft_simd_size(void);
14
 
15
   void pffft_select_cpu(int flags);
16
 
17
pipewire-0.3.59.tar.gz/src/modules/module-loopback.c -> pipewire-0.3.60.tar.gz/src/modules/module-loopback.c Changed
201
 
1
@@ -35,6 +35,7 @@
2
 #include <spa/utils/result.h>
3
 #include <spa/utils/string.h>
4
 #include <spa/utils/json.h>
5
+#include <spa/utils/ringbuffer.h>
6
 #include <spa/param/profiler.h>
7
 #include <spa/debug/pod.h>
8
 
9
@@ -54,6 +55,7 @@
10
  * ## Module Options
11
  *
12
  * - `node.description`: a human readable name for the loopback streams
13
+ * - `target.delay.sec`: delay in seconds as float (Since 0.3.60)
14
  * - `capture.props = {}`: properties to be passed to the input stream
15
  * - `playback.props = {}`: properties to be passed to the output stream
16
  *
17
@@ -91,6 +93,7 @@
18
  * {   name = libpipewire-module-loopback
19
  *     args = {
20
  *         node.description = "CM106 Stereo Pair 2"
21
+ *         #target.delay.sec = 1.5
22
  *         capture.props = {
23
  *             node.name = "CM106_stereo_pair_2"
24
  *             media.class = "Audio/Sink"
25
@@ -128,6 +131,7 @@
26
                " audio.rate=<sample rate>  "
27
                " audio.channels=<number of channels>  "
28
                " audio.position=<channel map>  "
29
+               " target.delay.sec=<delay as seconds in float>  "
30
                " capture.props=<properties>  "
31
                " playback.props=<properties>  " },
32
    { PW_KEY_MODULE_VERSION, PACKAGE_VERSION },
33
@@ -160,13 +164,21 @@
34
    struct pw_stream *capture;
35
    struct spa_hook capture_listener;
36
    struct spa_audio_info_raw capture_info;
37
+   struct spa_latency_info capture_latency;
38
 
39
    struct pw_properties *playback_props;
40
    struct pw_stream *playback;
41
    struct spa_hook playback_listener;
42
    struct spa_audio_info_raw playback_info;
43
+   struct spa_latency_info playback_latency;
44
 
45
    unsigned int do_disconnect:1;
46
+   unsigned int recalc_delay:1;
47
+
48
+   float target_delay;
49
+   struct spa_ringbuffer buffer;
50
+   uint8_t *buffer_data;
51
+   uint32_t buffer_size;
52
 };
53
 
54
 static void capture_destroy(void *d)
55
@@ -176,6 +188,28 @@
56
    impl->capture = NULL;
57
 }
58
 
59
+static void recalculate_delay(struct impl *impl)
60
+{
61
+   uint32_t target = impl->capture_info.rate * impl->target_delay, cdelay, pdelay;
62
+   uint32_t delay, w;
63
+   struct pw_time pwt;
64
+
65
+   pw_stream_get_time_n(impl->playback, &pwt, sizeof(pwt));
66
+   pdelay = pwt.delay;
67
+   pw_stream_get_time_n(impl->capture, &pwt, sizeof(pwt));
68
+   cdelay = pwt.delay;
69
+
70
+   delay = target - SPA_MIN(target, pdelay + cdelay);
71
+   delay = SPA_MIN(delay, impl->buffer_size / 4);
72
+
73
+   spa_ringbuffer_get_write_index(&impl->buffer, &w);
74
+   spa_ringbuffer_read_update(&impl->buffer, w - (delay * 4));
75
+
76
+   pw_log_info("target:%d c:%d + p:%d + delay:%d = (%d)",
77
+           target, cdelay, pdelay, delay,
78
+           cdelay + pdelay + delay);
79
+}
80
+
81
 static void capture_process(void *d)
82
 {
83
    struct impl *impl = d;
84
@@ -188,6 +222,11 @@
85
    struct pw_buffer *in, *out;
86
    uint32_t i;
87
 
88
+   if (impl->recalc_delay) {
89
+       recalculate_delay(impl);
90
+       impl->recalc_delay = false;
91
+   }
92
+
93
    if ((in = pw_stream_dequeue_buffer(impl->capture)) == NULL)
94
        pw_log_debug("out of capture buffers: %m");
95
 
96
@@ -199,6 +238,7 @@
97
        int32_t stride = 0;
98
        struct spa_data *d;
99
        const void *srcin->buffer->n_datas;
100
+       uint32_t r, w, buffer_size;
101
 
102
        for (i = 0; i < in->buffer->n_datas; i++) {
103
            uint32_t offs, size;
104
@@ -211,13 +251,33 @@
105
            outsize = SPA_MIN(outsize, size);
106
            stride = SPA_MAX(stride, d->chunk->stride);
107
        }
108
+       if (impl->buffer_size > 0) {
109
+           buffer_size = impl->buffer_size;
110
+           spa_ringbuffer_get_write_index(&impl->buffer, &w);
111
+           for (i = 0; i < in->buffer->n_datas; i++) {
112
+               void *buffer_data = &impl->buffer_datai * buffer_size;
113
+               spa_ringbuffer_write_data(&impl->buffer,
114
+                       buffer_data, buffer_size,
115
+                       w % buffer_size, srci, outsize);
116
+               srci = buffer_data;
117
+           }
118
+           w += outsize;
119
+           spa_ringbuffer_write_update(&impl->buffer, w);
120
+           spa_ringbuffer_get_read_index(&impl->buffer, &r);
121
+       } else {
122
+           r = 0;
123
+           buffer_size = outsize;
124
+       }
125
        for (i = 0; i < out->buffer->n_datas; i++) {
126
            d = &out->buffer->datasi;
127
 
128
            outsize = SPA_MIN(outsize, d->maxsize);
129
 
130
            if (i < in->buffer->n_datas)
131
-               memcpy(d->data, srci, outsize);
132
+               spa_ringbuffer_read_data(&impl->buffer,
133
+                       srci, buffer_size,
134
+                       r % buffer_size,
135
+                       d->data, outsize);
136
            else
137
                memset(d->data, 0, outsize);
138
 
139
@@ -225,6 +285,10 @@
140
            d->chunk->size = outsize;
141
            d->chunk->stride = stride;
142
        }
143
+       if (impl->buffer_size > 0) {
144
+           r += outsize;
145
+           spa_ringbuffer_read_update(&impl->buffer, r);
146
+       }
147
    }
148
 
149
    if (in != NULL)
150
@@ -234,7 +298,7 @@
151
 }
152
 
153
 static void param_latency_changed(struct impl *impl, const struct spa_pod *param,
154
-       struct pw_stream *other)
155
+       struct spa_latency_info *info, struct pw_stream *other)
156
 {
157
    struct spa_latency_info latency;
158
    uint8_t buffer1024;
159
@@ -244,9 +308,13 @@
160
    if (spa_latency_parse(param, &latency) < 0)
161
        return;
162
 
163
+   *info = latency;
164
+
165
    spa_pod_builder_init(&b, buffer, sizeof(buffer));
166
    params0 = spa_latency_build(&b, SPA_PARAM_Latency, &latency);
167
    pw_stream_update_params(other, params, 1);
168
+
169
+   impl->recalc_delay = true;
170
 }
171
 
172
 static void stream_state_changed(void *data, enum pw_stream_state old,
173
@@ -257,6 +325,7 @@
174
    case PW_STREAM_STATE_PAUSED:
175
        pw_stream_flush(impl->playback, false);
176
        pw_stream_flush(impl->capture, false);
177
+       impl->recalc_delay = true;
178
        break;
179
    case PW_STREAM_STATE_UNCONNECTED:
180
        pw_log_info("module %p: unconnected", impl);
181
@@ -270,13 +339,53 @@
182
    }
183
 }
184
 
185
+static void recalculate_buffer(struct impl *impl)
186
+{
187
+   if (impl->target_delay > 0.0f) {
188
+       uint32_t delay = impl->capture_info.rate * impl->target_delay;
189
+       void *data;
190
+
191
+       impl->buffer_size = (delay + (1u<<15)) * 4;
192
+       data = realloc(impl->buffer_data, impl->buffer_size * impl->capture_info.channels);
193
+       if (data == NULL) {
194
+           pw_log_warn("can't allocate delay buffer, delay disabled: %m");
195
+           impl->buffer_size = 0;
196
+           free(impl->buffer_data);
197
+       }
198
+       impl->buffer_data = data;
199
+       spa_ringbuffer_init(&impl->buffer);
200
+   } else {
201
pipewire-0.3.59.tar.gz/src/modules/module-pipe-tunnel.c -> pipewire-0.3.60.tar.gz/src/modules/module-pipe-tunnel.c Changed
27
 
1
@@ -55,7 +55,7 @@
2
 /** \page page_module_pipe_tunnel PipeWire Module: Unix Pipe Tunnel
3
  *
4
  * The pipe-tunnel module provides a source or sink that tunnels all audio to
5
- * a unix pipe.
6
+ * or from a unix pipe respectively.
7
  *
8
  * ## Module Options
9
  *
10
@@ -315,7 +315,7 @@
11
    .process = capture_stream_process
12
 };
13
 
14
-static int create_stream(struct impl *impl)
15
+static int  create_stream(struct impl *impl)
16
 {
17
    int res;
18
    uint32_t n_params;
19
@@ -664,6 +664,7 @@
20
    copy_props(impl, props, PW_KEY_NODE_LATENCY);
21
    copy_props(impl, props, PW_KEY_NODE_VIRTUAL);
22
    copy_props(impl, props, PW_KEY_MEDIA_CLASS);
23
+   copy_props(impl, props, PW_KEY_TARGET_OBJECT);
24
 
25
    parse_audio_info(impl->stream_props, &impl->info);
26
 
27
pipewire-0.3.59.tar.gz/src/modules/module-protocol-native.c -> pipewire-0.3.60.tar.gz/src/modules/module-protocol-native.c Changed
11
 
1
@@ -228,6 +228,9 @@
2
        hex = true;
3
    if (hex)
4
        spa_debug_mem(0, msg->data, msg->size);
5
+
6
+   pw_logt_debug(mod_topic_connection, "%s ****", prefix);
7
+
8
 }
9
 
10
 static void pre_demarshal(struct pw_protocol_native_connection *conn,
11
pipewire-0.3.59.tar.gz/src/modules/module-protocol-native/connection.c -> pipewire-0.3.60.tar.gz/src/modules/module-protocol-native/connection.c Changed
15
 
1
@@ -728,9 +728,12 @@
2
        buf->n_fds = buf->msg.n_fds;
3
 
4
    if (mod_topic_connection->level >= SPA_LOG_LEVEL_DEBUG) {
5
-       pw_log_debug(">>>>>>>>> out: id:%d op:%d size:%d seq:%d",
6
+       pw_logt_debug(mod_topic_connection,
7
+           ">>>>>>>>> out: id:%d op:%d size:%d seq:%d",
8
                buf->msg.id, buf->msg.opcode, size, buf->msg.seq);
9
            spa_debug_pod(0, NULL, SPA_PTROFF(p, impl->hdr_size, struct spa_pod));
10
+       pw_logt_debug(mod_topic_connection,
11
+           ">>>>>>>>> out: done");
12
    }
13
 
14
    buf->seq = (buf->seq + 1) & SPA_ASYNC_SEQ_MASK;
15
pipewire-0.3.59.tar.gz/src/modules/module-protocol-pulse/client.c -> pipewire-0.3.60.tar.gz/src/modules/module-protocol-pulse/client.c Changed
27
 
1
@@ -266,17 +266,12 @@
2
                int res = -errno;
3
                if (res == -EINTR)
4
                    continue;
5
-               if (res != -EAGAIN && res != -EWOULDBLOCK)
6
-                   pw_log_warn("client %p: send channel:%u %zu, error %d: %m",
7
-                           client, m->channel, size, res);
8
                return res;
9
            }
10
-
11
            client->out_index += sent;
12
            break;
13
        }
14
    }
15
-
16
    return 0;
17
 }
18
 
19
@@ -296,7 +291,6 @@
20
        if (res != -EAGAIN && res != -EWOULDBLOCK)
21
            return res;
22
    }
23
-
24
    return 0;
25
 }
26
 
27
pipewire-0.3.59.tar.gz/src/modules/module-protocol-pulse/extension.c -> pipewire-0.3.60.tar.gz/src/modules/module-protocol-pulse/extension.c Changed
15
 
1
@@ -37,12 +37,9 @@
2
 
3
 const struct extension *extension_find(uint32_t index, const char *name)
4
 {
5
-   const struct extension *ext;
6
-
7
-   SPA_FOR_EACH_ELEMENT(extensions, ext) {
8
+   SPA_FOR_EACH_ELEMENT_VAR(extensions, ext) {
9
        if (index == ext->index || spa_streq(name, ext->name))
10
            return ext;
11
    }
12
-
13
    return NULL;
14
 }
15
pipewire-0.3.59.tar.gz/src/modules/module-protocol-pulse/format.c -> pipewire-0.3.60.tar.gz/src/modules/module-protocol-pulse/format.c Changed
120
 
1
@@ -159,32 +159,28 @@
2
 
3
 uint32_t format_paname2id(const char *name, size_t size)
4
 {
5
-   size_t i;
6
-   for (i = 0; i < SPA_N_ELEMENTS(audio_formats); i++) {
7
-       if (audio_formatsi.name != NULL &&
8
-           strncmp(name, audio_formatsi.name, size) == 0)
9
-           return audio_formatsi.id;
10
+   SPA_FOR_EACH_ELEMENT_VAR(audio_formats, f) {
11
+       if (f->name != NULL &&
12
+           strncmp(name, f->name, size) == 0)
13
+           return f->id;
14
    }
15
    return SPA_AUDIO_FORMAT_UNKNOWN;
16
 }
17
 
18
 enum sample_format format_id2pa(uint32_t id)
19
 {
20
-   size_t i;
21
-   for (i = 0; i < SPA_N_ELEMENTS(audio_formats); i++) {
22
-       if (id == audio_formatsi.id)
23
-           return audio_formatsi.pa;
24
+   SPA_FOR_EACH_ELEMENT_VAR(audio_formats, f) {
25
+       if (id == f->id)
26
+           return f->pa;
27
    }
28
    return SAMPLE_INVALID;
29
 }
30
 
31
 const char *format_id2paname(uint32_t id)
32
 {
33
-   size_t i;
34
-   for (i = 0; i < SPA_N_ELEMENTS(audio_formats); i++) {
35
-       if (id == audio_formatsi.id &&
36
-           audio_formatsi.name != NULL)
37
-           return audio_formatsi.name;
38
+   SPA_FOR_EACH_ELEMENT_VAR(audio_formats, f) {
39
+       if (id == f->id && f->name != NULL)
40
+           return f->name;
41
    }
42
    return "invalid";
43
 }
44
@@ -266,21 +262,18 @@
45
 
46
 const char *channel_id2paname(uint32_t id, uint32_t *aux)
47
 {
48
-   size_t i;
49
-   for (i = 0; i < SPA_N_ELEMENTS(audio_channels); i++) {
50
-       if (id == audio_channelsi.channel &&
51
-           audio_channelsi.name != NULL)
52
-           return audio_channelsi.name;
53
+   SPA_FOR_EACH_ELEMENT_VAR(audio_channels, i) {
54
+       if (id == i->channel && i->name != NULL)
55
+           return i->name;
56
    }
57
    return audio_channelsCHANNEL_POSITION_AUX0 + ((*aux)++ & 31).name;
58
 }
59
 
60
 uint32_t channel_paname2id(const char *name, size_t size)
61
 {
62
-   size_t i;
63
-   for (i = 0; i < SPA_N_ELEMENTS(audio_channels); i++) {
64
-       if (strncmp(name, audio_channelsi.name, size) == 0)
65
-           return audio_channelsi.channel;
66
+   SPA_FOR_EACH_ELEMENT_VAR(audio_channels, i) {
67
+       if (strncmp(name, i->name, size) == 0)
68
+           return i->channel;
69
    }
70
    return SPA_AUDIO_CHANNEL_UNKNOWN;
71
 }
72
@@ -424,25 +417,6 @@
73
    return ENCODING_ANY;
74
 }
75
 
76
-static inline int
77
-audio_raw_parse_opt(const struct spa_pod *format, struct spa_audio_info_raw *info)
78
-{
79
-   struct spa_pod *position = NULL;
80
-   int res;
81
-   info->flags = 0;
82
-   res = spa_pod_parse_object(format,
83
-           SPA_TYPE_OBJECT_Format, NULL,
84
-           SPA_FORMAT_AUDIO_format,        SPA_POD_OPT_Id(&info->format),
85
-           SPA_FORMAT_AUDIO_rate,          SPA_POD_OPT_Int(&info->rate),
86
-           SPA_FORMAT_AUDIO_channels,      SPA_POD_OPT_Int(&info->channels),
87
-           SPA_FORMAT_AUDIO_position,      SPA_POD_OPT_Pod(&position));
88
-   if (position == NULL ||
89
-       !spa_pod_copy_array(position, SPA_TYPE_Id, info->position, SPA_AUDIO_MAX_CHANNELS))
90
-       SPA_FLAG_SET(info->flags, SPA_AUDIO_FLAG_UNPOSITIONED);
91
-
92
-   return res;
93
-}
94
-
95
 int format_parse_param(const struct spa_pod *param, bool collect,
96
        struct sample_spec *ss, struct channel_map *map,
97
        const struct sample_spec *def_ss, const struct channel_map *def_map)
98
@@ -458,14 +432,17 @@
99
 
100
    switch (info.media_subtype) {
101
    case SPA_MEDIA_SUBTYPE_raw:
102
+       if (spa_format_audio_raw_parse(param, &info.info.raw) < 0)
103
+                   return -ENOTSUP;
104
        if (def_ss != NULL) {
105
            if (ss != NULL)
106
                *ss = *def_ss;
107
-           if (audio_raw_parse_opt(param, &info.info.raw) < 0)
108
-                       return -ENOTSUP;
109
        } else {
110
-           if (spa_format_audio_raw_parse(param, &info.info.raw) < 0)
111
-                       return -ENOTSUP;
112
+           if (info.info.raw.format == 0 ||
113
+               info.info.raw.rate == 0 ||
114
+               info.info.raw.channels == 0 ||
115
+               info.info.raw.channels > SPA_AUDIO_MAX_CHANNELS)
116
+               return -ENOTSUP;
117
        }
118
        break;
119
    case SPA_MEDIA_SUBTYPE_iec958:
120
pipewire-0.3.59.tar.gz/src/modules/module-protocol-pulse/manager.c -> pipewire-0.3.60.tar.gz/src/modules/module-protocol-pulse/manager.c Changed
201
 
1
@@ -33,8 +33,6 @@
2
 #include "log.h"
3
 #include "module-protocol-pulse/server.h"
4
 
5
-#define MAX_PARAMS 32
6
-
7
 #define manager_emit_sync(m) spa_hook_list_call(&(m)->hooks, struct pw_manager_events, sync, 0)
8
 #define manager_emit_added(m,o) spa_hook_list_call(&(m)->hooks, struct pw_manager_events, added, 0, o)
9
 #define manager_emit_updated(m,o) spa_hook_list_call(&(m)->hooks, struct pw_manager_events, updated, 0, o)
10
@@ -85,8 +83,6 @@
11
    struct spa_hook proxy_listener;
12
    struct spa_hook object_listener;
13
 
14
-   int param_seqMAX_PARAMS;
15
-
16
    struct spa_list data_list;
17
 };
18
 
19
@@ -113,7 +109,7 @@
20
 }
21
 
22
 static struct pw_manager_param *add_param(struct spa_list *params,
23
-       int seq, int *param_seq, uint32_t id, const struct spa_pod *param)
24
+       int seq, uint32_t id, const struct spa_pod *param)
25
 {
26
    struct pw_manager_param *p;
27
 
28
@@ -125,24 +121,12 @@
29
        id = SPA_POD_OBJECT_ID(param);
30
    }
31
 
32
-   if (id >= MAX_PARAMS) {
33
-       pw_log_error("too big param id %d", id);
34
-       errno = EINVAL;
35
-       return NULL;
36
-   }
37
-
38
-   if (seq != param_seqid) {
39
-       pw_log_debug("ignoring param %d, seq:%d != current_seq:%d",
40
-               id, seq, param_seqid);
41
-       errno = EBUSY;
42
-       return NULL;
43
-   }
44
-
45
    p = malloc(sizeof(*p) + (param != NULL ? SPA_POD_SIZE(param) : 0));
46
    if (p == NULL)
47
        return NULL;
48
 
49
    p->id = id;
50
+   p->seq = seq;
51
    if (param != NULL) {
52
        p->param = SPA_PTROFF(p, sizeof(*p), struct spa_pod);
53
        memcpy(p->param, param, SPA_POD_SIZE(param));
54
@@ -167,7 +151,6 @@
55
    return false;
56
 }
57
 
58
-
59
 static struct object *find_object_by_id(struct manager *m, uint32_t id)
60
 {
61
    struct object *o;
62
@@ -180,7 +163,19 @@
63
 
64
 static void object_update_params(struct object *o)
65
 {
66
-   struct pw_manager_param *p;
67
+   struct pw_manager_param *p, *t;
68
+   uint32_t i;
69
+
70
+   for (i = 0; i < o->this.n_params; i++) {
71
+       spa_list_for_each_safe(p, t, &o->pending_list, link) {
72
+           if (p->id == o->this.paramsi.id &&
73
+               p->seq != o->this.paramsi.seq &&
74
+               p->param != NULL) {
75
+               spa_list_remove(&p->link);
76
+               free(p);
77
+           }
78
+       }
79
+   }
80
 
81
    spa_list_consume(p, &o->pending_list, link) {
82
        spa_list_remove(&p->link);
83
@@ -236,6 +231,8 @@
84
    pw_log_debug("object %p: id:%d change-mask:%08"PRIx64, o, o->this.id, info->change_mask);
85
 
86
    info = o->this.info = pw_client_info_merge(o->this.info, info, o->this.changed == 0);
87
+   if (info == NULL)
88
+       return;
89
 
90
    if (info->change_mask & PW_CLIENT_CHANGE_MASK_PROPS)
91
        changed++;
92
@@ -275,6 +272,8 @@
93
    pw_log_debug("object %p: id:%d change-mask:%08"PRIx64, o, o->this.id, info->change_mask);
94
 
95
    info = o->this.info = pw_module_info_merge(o->this.info, info, o->this.changed == 0);
96
+   if (info == NULL)
97
+       return;
98
 
99
    if (info->change_mask & PW_MODULE_CHANGE_MASK_PROPS)
100
        changed++;
101
@@ -314,6 +313,11 @@
102
    pw_log_debug("object %p: id:%d change-mask:%08"PRIx64, o, o->this.id, info->change_mask);
103
 
104
    info = o->this.info = pw_device_info_merge(o->this.info, info, o->this.changed == 0);
105
+   if (info == NULL)
106
+       return;
107
+
108
+   o->this.n_params = info->n_params;
109
+   o->this.params = info->params;
110
 
111
    if (info->change_mask & PW_DEVICE_CHANGE_MASK_PROPS)
112
        changed++;
113
@@ -327,11 +331,6 @@
114
                continue;
115
            info->paramsi.user = 0;
116
 
117
-           if (id >= MAX_PARAMS) {
118
-               pw_log_error("too big param id %d", id);
119
-               continue;
120
-           }
121
-
122
            switch (id) {
123
            case SPA_PARAM_EnumProfile:
124
            case SPA_PARAM_Profile:
125
@@ -341,14 +340,14 @@
126
            case SPA_PARAM_Route:
127
                break;
128
            }
129
-           add_param(&o->pending_list, o->param_seqid, o->param_seq, id, NULL);
130
+           add_param(&o->pending_list, info->paramsi.seq, id, NULL);
131
            if (!(info->paramsi.flags & SPA_PARAM_INFO_READ))
132
                continue;
133
 
134
            res = pw_device_enum_params((struct pw_device*)o->this.proxy,
135
-                   ++o->param_seqid, id, 0, -1, NULL);
136
+                   ++info->paramsi.seq, id, 0, -1, NULL);
137
            if (SPA_RESULT_IS_ASYNC(res))
138
-               o->param_seqid = res;
139
+               info->paramsi.seq = res;
140
        }
141
    }
142
    if (changed) {
143
@@ -385,7 +384,7 @@
144
    struct manager *m = o->manager;
145
    struct pw_manager_param *p;
146
 
147
-   p = add_param(&o->pending_list, seq, o->param_seq, id, param);
148
+   p = add_param(&o->pending_list, seq, id, param);
149
    if (p == NULL)
150
        return;
151
 
152
@@ -434,6 +433,11 @@
153
    pw_log_debug("object %p: id:%d change-mask:%08"PRIx64, o, o->this.id, info->change_mask);
154
 
155
    info = o->this.info = pw_node_info_merge(o->this.info, info, o->this.changed == 0);
156
+   if (info == NULL)
157
+       return;
158
+
159
+   o->this.n_params = info->n_params;
160
+   o->this.params = info->params;
161
 
162
    if (info->change_mask & PW_NODE_CHANGE_MASK_STATE)
163
        changed++;
164
@@ -450,20 +454,15 @@
165
                continue;
166
            info->paramsi.user = 0;
167
 
168
-           if (id >= MAX_PARAMS) {
169
-               pw_log_error("too big param id %d", id);
170
-               continue;
171
-           }
172
-
173
            changed++;
174
-           add_param(&o->pending_list, o->param_seqid, o->param_seq, id, NULL);
175
+           add_param(&o->pending_list, info->paramsi.seq, id, NULL);
176
            if (!(info->paramsi.flags & SPA_PARAM_INFO_READ))
177
                continue;
178
 
179
            res = pw_node_enum_params((struct pw_node*)o->this.proxy,
180
-                   ++o->param_seqid, id, 0, -1, NULL);
181
+                   ++info->paramsi.seq, id, 0, -1, NULL);
182
            if (SPA_RESULT_IS_ASYNC(res))
183
-               o->param_seqid = res;
184
+               info->paramsi.seq = res;
185
        }
186
    }
187
    if (changed) {
188
@@ -477,7 +476,7 @@
189
        const struct spa_pod *param)
190
 {
191
    struct object *o = data;
192
-   add_param(&o->pending_list, seq, o->param_seq, id, param);
193
+   add_param(&o->pending_list, seq, id, param);
194
 }
195
 
196
 static const struct pw_node_events node_events = {
197
@@ -553,11 +552,10 @@
198
 
199
 static const struct object_info *find_info(const char *type, uint32_t version)
200
 {
201
pipewire-0.3.59.tar.gz/src/modules/module-protocol-pulse/manager.h -> pipewire-0.3.60.tar.gz/src/modules/module-protocol-pulse/manager.h Changed
19
 
1
@@ -72,6 +72,7 @@
2
 
3
 struct pw_manager_param {
4
    uint32_t id;
5
+   int32_t seq;
6
    struct spa_list link;           /**< link in manager_object param_list */
7
    struct spa_pod *param;
8
 };
9
@@ -92,6 +93,9 @@
10
 
11
    int changed;
12
    void *info;
13
+   struct spa_param_info *params;
14
+   uint32_t n_params;
15
+
16
    struct spa_list param_list;
17
    unsigned int creating:1;
18
    unsigned int removing:1;
19
pipewire-0.3.59.tar.gz/src/modules/module-protocol-pulse/modules/module-loopback.c -> pipewire-0.3.60.tar.gz/src/modules/module-protocol-pulse/modules/module-loopback.c Changed
46
 
1
@@ -47,6 +47,7 @@
2
    struct pw_properties *playback_props;
3
 
4
    struct spa_audio_info_raw info;
5
+   uint32_t latency_msec;
6
 };
7
 
8
 static void module_destroy(void *data)
9
@@ -68,6 +69,7 @@
10
    FILE *f;
11
    char *args;
12
    size_t size, i;
13
+   char val256;
14
 
15
    pw_properties_setf(data->capture_props, PW_KEY_NODE_GROUP, "loopback-%u", module->index);
16
    pw_properties_setf(data->playback_props, PW_KEY_NODE_GROUP, "loopback-%u", module->index);
17
@@ -88,6 +90,10 @@
18
            fprintf(f, " ");
19
        }
20
    }
21
+   if (data->latency_msec != 0)
22
+       fprintf(f, " target.delay.sec = %s",
23
+               spa_json_format_float(val, sizeof(val),
24
+                   data->latency_msec / 1000.0f));
25
    fprintf(f, " capture.props = {");
26
    pw_properties_serialize_dict(f, &data->capture_props->dict, 0);
27
    fprintf(f, " } playback.props = {");
28
@@ -204,15 +210,8 @@
29
        pw_properties_set(props, "remix", NULL);
30
    }
31
 
32
-   if ((str = pw_properties_get(props, "latency_msec")) != NULL) {
33
-       /* Half the latency on each of the playback and capture streams */
34
-       pw_properties_setf(capture_props, PW_KEY_NODE_LATENCY, "%s/2000", str);
35
-       pw_properties_setf(playback_props, PW_KEY_NODE_LATENCY, "%s/2000", str);
36
-       pw_properties_set(props, "latency_msec", NULL);
37
-   } else {
38
-       pw_properties_set(capture_props, PW_KEY_NODE_LATENCY, "100/1000");
39
-       pw_properties_set(playback_props, PW_KEY_NODE_LATENCY, "100/1000");
40
-   }
41
+   if ((str = pw_properties_get(props, "latency_msec")) != NULL)
42
+       d->latency_msec = atoi(str);
43
 
44
    if ((str = pw_properties_get(props, "sink_input_properties")) != NULL) {
45
        module_args_add_props(playback_props, str);
46
pipewire-0.3.60.tar.gz/src/modules/module-protocol-pulse/modules/module-rtp-recv.c Added
167
 
1
@@ -0,0 +1,165 @@
2
+/* PipeWire
3
+ *
4
+ * Copyright © 2022 Wim Taymans <wim.taymans@gmail.com>
5
+ *
6
+ * Permission is hereby granted, free of charge, to any person obtaining a
7
+ * copy of this software and associated documentation files (the "Software"),
8
+ * to deal in the Software without restriction, including without limitation
9
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10
+ * and/or sell copies of the Software, and to permit persons to whom the
11
+ * Software is furnished to do so, subject to the following conditions:
12
+ *
13
+ * The above copyright notice and this permission notice (including the next
14
+ * paragraph) shall be included in all copies or substantial portions of the
15
+ * Software.
16
+ *
17
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
20
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
23
+ * DEALINGS IN THE SOFTWARE.
24
+ */
25
+
26
+#include <spa/utils/hook.h>
27
+#include <pipewire/pipewire.h>
28
+#include <pipewire/private.h>
29
+
30
+#include "../defs.h"
31
+#include "../module.h"
32
+
33
+#define NAME "rtp-recv"
34
+
35
+PW_LOG_TOPIC_STATIC(mod_topic, "mod." NAME);
36
+#define PW_LOG_TOPIC_DEFAULT mod_topic
37
+
38
+struct module_rtp_recv_data {
39
+   struct module *module;
40
+
41
+   struct spa_hook mod_listener;
42
+   struct pw_impl_module *mod;
43
+
44
+   struct pw_properties *stream_props;
45
+   struct pw_properties *global_props;
46
+};
47
+
48
+static void module_destroy(void *data)
49
+{
50
+   struct module_rtp_recv_data *d = data;
51
+   spa_hook_remove(&d->mod_listener);
52
+   d->mod = NULL;
53
+   module_schedule_unload(d->module);
54
+}
55
+
56
+static const struct pw_impl_module_events module_events = {
57
+   PW_VERSION_IMPL_MODULE_EVENTS,
58
+   .destroy = module_destroy
59
+};
60
+
61
+static int module_rtp_recv_load(struct client *client, struct module *module)
62
+{
63
+   struct module_rtp_recv_data *data = module->user_data;
64
+   FILE *f;
65
+   char *args;
66
+   size_t size;
67
+
68
+   pw_properties_setf(data->stream_props, "pulse.module.id",
69
+           "%u", module->index);
70
+
71
+   if ((f = open_memstream(&args, &size)) == NULL)
72
+       return -errno;
73
+
74
+   fprintf(f, "{");
75
+   pw_properties_serialize_dict(f, &data->global_props->dict, 0);
76
+   fprintf(f, " stream.props = {");
77
+   pw_properties_serialize_dict(f, &data->stream_props->dict, 0);
78
+   fprintf(f, " } }");
79
+   fclose(f);
80
+
81
+   data->mod = pw_context_load_module(module->impl->context,
82
+           "libpipewire-module-rtp-source",
83
+           args, NULL);
84
+
85
+   free(args);
86
+
87
+   if (data->mod == NULL)
88
+       return -errno;
89
+
90
+   pw_impl_module_add_listener(data->mod,
91
+           &data->mod_listener,
92
+           &module_events, data);
93
+
94
+   return 0;
95
+}
96
+
97
+static int module_rtp_recv_unload(struct module *module)
98
+{
99
+   struct module_rtp_recv_data *d = module->user_data;
100
+
101
+   if (d->mod) {
102
+       spa_hook_remove(&d->mod_listener);
103
+       pw_impl_module_destroy(d->mod);
104
+       d->mod = NULL;
105
+   }
106
+
107
+   pw_properties_free(d->global_props);
108
+   pw_properties_free(d->stream_props);
109
+
110
+   return 0;
111
+}
112
+
113
+static const struct spa_dict_item module_rtp_recv_info = {
114
+   { PW_KEY_MODULE_AUTHOR, "Wim Taymans <wim.taymans@gmail.com>" },
115
+   { PW_KEY_MODULE_DESCRIPTION, "Receive data from a network via RTP/SAP/SDP" },
116
+   { PW_KEY_MODULE_USAGE,  "sink=<name of the sink> "
117
+               "sap_address=<multicast address to listen on> "
118
+               "latency_msec=<latency in ms> " },
119
+   { PW_KEY_MODULE_VERSION, PACKAGE_VERSION },
120
+};
121
+
122
+static int module_rtp_recv_prepare(struct module * const module)
123
+{
124
+   struct module_rtp_recv_data * const d = module->user_data;
125
+   struct pw_properties * const props = module->props;
126
+   struct pw_properties *stream_props = NULL, *global_props = NULL;
127
+   const char *str;
128
+   int res;
129
+
130
+   PW_LOG_TOPIC_INIT(mod_topic);
131
+
132
+   stream_props = pw_properties_new(NULL, NULL);
133
+   global_props = pw_properties_new(NULL, NULL);
134
+   if (!stream_props || !global_props) {
135
+       res = -errno;
136
+       goto out;
137
+   }
138
+   if ((str = pw_properties_get(props, "sink")) != NULL)
139
+       pw_properties_set(stream_props, PW_KEY_NODE_TARGET, str);
140
+
141
+   if ((str = pw_properties_get(props, "sap_address")) != NULL)
142
+       pw_properties_set(global_props, "sap.ip", str);
143
+
144
+   if ((str = pw_properties_get(props, "latency_msec")) != NULL)
145
+       pw_properties_set(global_props, "sess.latency.msec", str);
146
+
147
+   d->module = module;
148
+   d->stream_props = stream_props;
149
+   d->global_props = global_props;
150
+
151
+   return 0;
152
+out:
153
+   pw_properties_free(stream_props);
154
+   pw_properties_free(global_props);
155
+
156
+   return res;
157
+}
158
+
159
+DEFINE_MODULE_INFO(module_rtp_recv) = {
160
+   .name = "module-rtp-recv",
161
+   .prepare = module_rtp_recv_prepare,
162
+   .load = module_rtp_recv_load,
163
+   .unload = module_rtp_recv_unload,
164
+   .properties = &SPA_DICT_INIT_ARRAY(module_rtp_recv_info),
165
+   .data_size = sizeof(struct module_rtp_recv_data),
166
+};
167
pipewire-0.3.60.tar.gz/src/modules/module-protocol-pulse/modules/module-rtp-send.c Added
201
 
1
@@ -0,0 +1,226 @@
2
+/* PipeWire
3
+ *
4
+ * Copyright © 2022 Wim Taymans <wim.taymans@gmail.com>
5
+ *
6
+ * Permission is hereby granted, free of charge, to any person obtaining a
7
+ * copy of this software and associated documentation files (the "Software"),
8
+ * to deal in the Software without restriction, including without limitation
9
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10
+ * and/or sell copies of the Software, and to permit persons to whom the
11
+ * Software is furnished to do so, subject to the following conditions:
12
+ *
13
+ * The above copyright notice and this permission notice (including the next
14
+ * paragraph) shall be included in all copies or substantial portions of the
15
+ * Software.
16
+ *
17
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
20
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
23
+ * DEALINGS IN THE SOFTWARE.
24
+ */
25
+
26
+#include <spa/utils/hook.h>
27
+#include <pipewire/pipewire.h>
28
+#include <pipewire/private.h>
29
+
30
+#include "../defs.h"
31
+#include "../module.h"
32
+
33
+#define NAME "rtp-send"
34
+
35
+PW_LOG_TOPIC_STATIC(mod_topic, "mod." NAME);
36
+#define PW_LOG_TOPIC_DEFAULT mod_topic
37
+
38
+struct module_rtp_send_data {
39
+   struct module *module;
40
+
41
+   struct spa_hook mod_listener;
42
+   struct pw_impl_module *mod;
43
+
44
+   struct pw_properties *stream_props;
45
+   struct pw_properties *global_props;
46
+   struct spa_audio_info_raw info;
47
+};
48
+
49
+static void module_destroy(void *data)
50
+{
51
+   struct module_rtp_send_data *d = data;
52
+   spa_hook_remove(&d->mod_listener);
53
+   d->mod = NULL;
54
+   module_schedule_unload(d->module);
55
+}
56
+
57
+static const struct pw_impl_module_events module_events = {
58
+   PW_VERSION_IMPL_MODULE_EVENTS,
59
+   .destroy = module_destroy
60
+};
61
+
62
+static int module_rtp_send_load(struct client *client, struct module *module)
63
+{
64
+   struct module_rtp_send_data *data = module->user_data;
65
+   FILE *f;
66
+   char *args;
67
+   size_t size;
68
+   uint32_t i;
69
+
70
+   pw_properties_setf(data->stream_props, "pulse.module.id",
71
+           "%u", module->index);
72
+
73
+   if ((f = open_memstream(&args, &size)) == NULL)
74
+       return -errno;
75
+
76
+   fprintf(f, "{");
77
+   pw_properties_serialize_dict(f, &data->global_props->dict, 0);
78
+   if (data->info.format != 0)
79
+       fprintf(f, " \"audio.format\": \"%s\"", format_id2name(data->info.format));
80
+   if (data->info.rate != 0)
81
+       fprintf(f, " \"audio.rate\": %u,", data->info.rate);
82
+   if (data->info.channels != 0) {
83
+       fprintf(f, " \"audio.channels\": %u,", data->info.channels);
84
+       if (!(data->info.flags & SPA_AUDIO_FLAG_UNPOSITIONED)) {
85
+           fprintf(f, " \"audio.position\":  ");
86
+           for (i = 0; i < data->info.channels; i++)
87
+               fprintf(f, "%s\"%s\"", i == 0 ? "" : ",",
88
+                   channel_id2name(data->info.positioni));
89
+           fprintf(f, " ,");
90
+       }
91
+   }
92
+   fprintf(f, " stream.props = {");
93
+   pw_properties_serialize_dict(f, &data->stream_props->dict, 0);
94
+   fprintf(f, " } }");
95
+   fclose(f);
96
+
97
+   data->mod = pw_context_load_module(module->impl->context,
98
+           "libpipewire-module-rtp-sink",
99
+           args, NULL);
100
+
101
+   free(args);
102
+
103
+   if (data->mod == NULL)
104
+       return -errno;
105
+
106
+   pw_impl_module_add_listener(data->mod,
107
+           &data->mod_listener,
108
+           &module_events, data);
109
+
110
+   return 0;
111
+}
112
+
113
+static int module_rtp_send_unload(struct module *module)
114
+{
115
+   struct module_rtp_send_data *d = module->user_data;
116
+
117
+   if (d->mod) {
118
+       spa_hook_remove(&d->mod_listener);
119
+       pw_impl_module_destroy(d->mod);
120
+       d->mod = NULL;
121
+   }
122
+
123
+   pw_properties_free(d->global_props);
124
+   pw_properties_free(d->stream_props);
125
+
126
+   return 0;
127
+}
128
+
129
+static const struct spa_dict_item module_rtp_send_info = {
130
+   { PW_KEY_MODULE_AUTHOR, "Wim Taymans <wim.taymans@gmail.com>" },
131
+   { PW_KEY_MODULE_DESCRIPTION, "Read data from source and send it to the network via RTP/SAP/SDP" },
132
+   { PW_KEY_MODULE_USAGE,  "source=<name of the source> "
133
+               "format=<sample format> "
134
+               "channels=<number of channels> "
135
+               "rate=<sample rate> "
136
+               "destination_ip=<destination IP address> "
137
+               "source_ip=<source IP address> "
138
+               "port=<port number> "
139
+               "mtu=<maximum transfer unit> "
140
+               "loop=<loopback to local host?> "
141
+               "ttl=<ttl value> "
142
+               "inhibit_auto_suspend=<always|never|only_with_non_monitor_sources> "
143
+               "stream_name=<name of the stream> "
144
+               "enable_opus=<enable OPUS codec>" },
145
+   { PW_KEY_MODULE_VERSION, PACKAGE_VERSION },
146
+};
147
+
148
+static int module_rtp_send_prepare(struct module * const module)
149
+{
150
+   struct module_rtp_send_data * const d = module->user_data;
151
+   struct pw_properties * const props = module->props;
152
+   struct pw_properties *stream_props = NULL, *global_props = NULL;
153
+   struct spa_audio_info_raw info = { 0 };
154
+   const char *str;
155
+   int res;
156
+
157
+   PW_LOG_TOPIC_INIT(mod_topic);
158
+
159
+   stream_props = pw_properties_new(NULL, NULL);
160
+   global_props = pw_properties_new(NULL, NULL);
161
+   if (!stream_props || !global_props) {
162
+       res = -errno;
163
+       goto out;
164
+   }
165
+
166
+   if ((str = pw_properties_get(props, "source")) != NULL) {
167
+       pw_properties_set(stream_props, PW_KEY_NODE_TARGET, str);
168
+       if (spa_strendswith(str, ".monitor")) {
169
+           pw_properties_setf(stream_props, PW_KEY_NODE_TARGET,
170
+                   "%.*s", (int)strlen(str)-8, str);
171
+           pw_properties_set(stream_props, PW_KEY_STREAM_CAPTURE_SINK,
172
+                   "true");
173
+       } else {
174
+           pw_properties_set(stream_props, PW_KEY_NODE_TARGET, str);
175
+       }
176
+   }
177
+   if (module_args_to_audioinfo(module->impl, props, &info) < 0) {
178
+       res = -EINVAL;
179
+       goto out;
180
+   }
181
+   info.format = 0;
182
+   if ((str = pw_properties_get(props, "format")) != NULL) {
183
+       if ((info.format = format_paname2id(str, strlen(str))) ==
184
+               SPA_AUDIO_FORMAT_UNKNOWN) {
185
+           pw_log_error("unknown format %s", str);
186
+           res = -EINVAL;
187
+           goto out;
188
+       }
189
+   }
190
+
191
+   if ((str = pw_properties_get(props, "destination_ip")) != NULL)
192
+       pw_properties_set(global_props, "destination.ip", str);
193
+   if ((str = pw_properties_get(props, "source_ip")) != NULL)
194
+       pw_properties_set(global_props, "source.ip", str);
195
+   if ((str = pw_properties_get(props, "port")) != NULL)
196
+       pw_properties_set(global_props, "destination.port", str);
197
+   if ((str = pw_properties_get(props, "mtu")) != NULL)
198
+       pw_properties_set(global_props, "net.mtu", str);
199
+   if ((str = pw_properties_get(props, "loop")) != NULL)
200
+       pw_properties_set(global_props, "net.loop",
201
pipewire-0.3.59.tar.gz/src/modules/module-protocol-pulse/modules/module-zeroconf-discover.c -> pipewire-0.3.60.tar.gz/src/modules/module-protocol-pulse/modules/module-zeroconf-discover.c Changed
60
 
1
@@ -40,6 +40,8 @@
2
 
3
    struct spa_hook mod_listener;
4
    struct pw_impl_module *mod;
5
+
6
+   uint32_t latency_msec;
7
 };
8
 
9
 static void module_destroy(void *data)
10
@@ -58,10 +60,25 @@
11
 static int module_zeroconf_discover_load(struct client *client, struct module *module)
12
 {
13
    struct module_zeroconf_discover_data *data = module->user_data;
14
+   FILE *f;
15
+   char *args;
16
+   size_t size;
17
+
18
+   if ((f = open_memstream(&args, &size)) == NULL)
19
+       return -errno;
20
+
21
+   fprintf(f, "{");
22
+   if (data->latency_msec > 0)
23
+       fprintf(f, " pulse.latency = %u ", data->latency_msec);
24
+   fprintf(f, "}");
25
+   fclose(f);
26
 
27
    data->mod = pw_context_load_module(module->impl->context,
28
            "libpipewire-module-zeroconf-discover",
29
-           NULL, NULL);
30
+           args, NULL);
31
+
32
+   free(args);
33
+
34
    if (data->mod == NULL)
35
        return -errno;
36
 
37
@@ -88,7 +105,8 @@
38
 static const struct spa_dict_item module_zeroconf_discover_info = {
39
    { PW_KEY_MODULE_AUTHOR, "Wim Taymans <wim.taymans@gmail.con>" },
40
    { PW_KEY_MODULE_DESCRIPTION, "mDNS/DNS-SD Service Discovery" },
41
-   { PW_KEY_MODULE_USAGE, "" },
42
+   { PW_KEY_MODULE_USAGE,
43
+       "latency_msec=<fixed latency in ms> " },
44
    { PW_KEY_MODULE_VERSION, PACKAGE_VERSION },
45
 };
46
 
47
@@ -96,9 +114,12 @@
48
 {
49
    PW_LOG_TOPIC_INIT(mod_topic);
50
 
51
+   struct pw_properties * const props = module->props;
52
    struct module_zeroconf_discover_data * const data = module->user_data;
53
    data->module = module;
54
 
55
+   pw_properties_fetch_uint32(props, "latency_msec", &data->latency_msec);
56
+
57
    return 0;
58
 }
59
 
60
pipewire-0.3.59.tar.gz/src/modules/module-protocol-pulse/modules/module-zeroconf-publish.c -> pipewire-0.3.60.tar.gz/src/modules/module-protocol-pulse/modules/module-zeroconf-publish.c Changed
11
 
1
@@ -380,8 +380,7 @@
2
    txt = avahi_string_list_add_pair(txt, "channel_map", channel_map_snprint(cm, sizeof(cm), &s->cm));
3
    txt = avahi_string_list_add_pair(txt, "subtype", subtype_texts->subtype);
4
 
5
-   const struct mapping *m;
6
-   SPA_FOR_EACH_ELEMENT(mappings, m) {
7
+   SPA_FOR_EACH_ELEMENT_VAR(mappings, m) {
8
        const char *value = pw_properties_get(s->props, m->pw_key);
9
        if (value != NULL)
10
            txt = avahi_string_list_add_pair(txt, m->txt_key, value);
11
pipewire-0.3.59.tar.gz/src/modules/module-protocol-pulse/pulse-server.c -> pipewire-0.3.60.tar.gz/src/modules/module-protocol-pulse/pulse-server.c Changed
21
 
1
@@ -1428,15 +1428,16 @@
2
            }
3
            if ((stream->attr.prebuf == 0 || do_flush) && !stream->corked) {
4
                if (avail > 0) {
5
+                   avail = SPA_MIN((uint32_t)avail, size);
6
                    spa_ringbuffer_read_data(&stream->ring,
7
                        stream->buffer, MAXLENGTH,
8
                        index % MAXLENGTH,
9
-                       p, SPA_MIN((uint32_t)avail, size));
10
+                       p, avail);
11
                    index += avail;
12
+                   pd.read_inc = avail;
13
+                   spa_ringbuffer_read_update(&stream->ring, index);
14
                }
15
                pd.playing_for = size;
16
-               pd.read_inc = size;
17
-               spa_ringbuffer_read_update(&stream->ring, index);
18
            }
19
            pw_log_debug("%p: %s underrun read:%u avail:%d max:%u",
20
                    stream, client->name, index, avail, minreq);
21
pipewire-0.3.59.tar.gz/src/modules/module-protocol-pulse/quirks.c -> pipewire-0.3.60.tar.gz/src/modules/module-protocol-pulse/quirks.c Changed
15
 
1
@@ -38,10 +38,9 @@
2
        { "force-s16-info", QUIRK_FORCE_S16_FORMAT },
3
        { "remove-capture-dont-move", QUIRK_REMOVE_CAPTURE_DONT_MOVE },
4
    };
5
-   size_t i;
6
-   for (i = 0; i < SPA_N_ELEMENTS(quirk_keys); ++i) {
7
-       if (spa_streq(str, quirk_keysi.key))
8
-           return quirk_keysi.value;
9
+   SPA_FOR_EACH_ELEMENT_VAR(quirk_keys, i) {
10
+       if (spa_streq(str, i->key))
11
+           return i->value;
12
    }
13
    return 0;
14
 }
15
pipewire-0.3.59.tar.gz/src/modules/module-protocol-pulse/server.c -> pipewire-0.3.60.tar.gz/src/modules/module-protocol-pulse/server.c Changed
20
 
1
@@ -616,7 +616,6 @@
2
            pw_log_warn("server %p: unlink('%s') failed: %m",
3
                    server, addr_un->sun_path);
4
    }
5
-
6
    if (bind(fd, (const struct sockaddr *) addr_un, SUN_LEN(addr_un)) < 0) {
7
        res = -errno;
8
        pw_log_warn("server %p: bind() to '%s' failed: %m",
9
@@ -624,6 +623,10 @@
10
        goto error_close;
11
    }
12
 
13
+   if (chmod(addr_un->sun_path, 0777) < 0)
14
+       pw_log_warn("server %p: chmod('%s') failed: %m",
15
+                   server, addr_un->sun_path);
16
+
17
    if (listen(fd, server->listen_backlog) < 0) {
18
        res = -errno;
19
        pw_log_warn("server %p: listen() on '%s' failed: %m",
20
pipewire-0.3.59.tar.gz/src/modules/module-pulse-tunnel.c -> pipewire-0.3.60.tar.gz/src/modules/module-pulse-tunnel.c Changed
152
 
1
@@ -183,6 +183,8 @@
2
    pa_context *pa_context;
3
    pa_stream *pa_stream;
4
 
5
+   struct ratelimit rate_limit;
6
+
7
    uint32_t target_latency;
8
    uint32_t current_latency;
9
    uint32_t target_buffer;
10
@@ -524,9 +526,10 @@
11
 {
12
    struct impl *impl = userdata;
13
    int32_t avail;
14
-   uint32_t index, len, offset, l0, l1;
15
+   uint32_t index;
16
+   size_t size;
17
    pa_usec_t latency;
18
-   int negative;
19
+   int negative, res;
20
 
21
    if (impl->resync) {
22
        impl->resync = false;
23
@@ -542,43 +545,54 @@
24
    impl->current_latency += avail / impl->frame_size;
25
 
26
    while (avail < (int32_t)length) {
27
+       uint32_t maxsize = SPA_ROUND_DOWN(sizeof(impl->empty), impl->frame_size);
28
        /* send silence for the data we don't have */
29
-       len = SPA_MIN(length - avail, sizeof(impl->empty));
30
-       pa_stream_write(impl->pa_stream,
31
-               impl->empty, len,
32
-               NULL, 0, PA_SEEK_RELATIVE);
33
-       length -= len;
34
+       size = SPA_MIN(length - avail, maxsize);
35
+       if ((res = pa_stream_write(impl->pa_stream,
36
+               impl->empty, size,
37
+               NULL, 0, PA_SEEK_RELATIVE)) != 0)
38
+           pw_log_warn("error writing stream: %s", pa_strerror(res));
39
+       length -= size;
40
    }
41
-   if (length > 0 && avail >= (int32_t)length) {
42
-       /* always send as much as is requested */
43
-       len = length;
44
-       offset = index & RINGBUFFER_MASK;
45
-       l0 = SPA_MIN(len, RINGBUFFER_SIZE - offset);
46
-       l1 = len - l0;
47
-
48
-       pa_stream_write(impl->pa_stream,
49
-               SPA_PTROFF(impl->buffer, offset, void), l0,
50
-               NULL, 0, PA_SEEK_RELATIVE);
51
-
52
-       if (SPA_UNLIKELY(l1 > 0)) {
53
-           pa_stream_write(impl->pa_stream,
54
-                   impl->buffer, l1,
55
-                   NULL, 0, PA_SEEK_RELATIVE);
56
-       }
57
-       index += len;
58
+   while (length > 0 && avail >= (int32_t)length) {
59
+       void *data;
60
+
61
+       size = length;
62
+       pa_stream_begin_write(impl->pa_stream, &data, &size);
63
+
64
+       spa_ringbuffer_read_data(&impl->ring,
65
+               impl->buffer, RINGBUFFER_SIZE,
66
+               index & RINGBUFFER_MASK,
67
+               data, size);
68
+
69
+       if ((res = pa_stream_write(impl->pa_stream,
70
+           data, size, NULL, 0, PA_SEEK_RELATIVE)) != 0)
71
+           pw_log_warn("error writing stream: %zd %s", size,
72
+                   pa_strerror(res));
73
+
74
+       index += size;
75
+       length -= size;
76
+       avail -= size;
77
        spa_ringbuffer_read_update(&impl->ring, index);
78
    }
79
 }
80
 static void stream_underflow_cb(pa_stream *s, void *userdata)
81
 {
82
    struct impl *impl = userdata;
83
-   pw_log_warn("underflow");
84
+   struct timespec ts;
85
+
86
+   clock_gettime(CLOCK_MONOTONIC, &ts);
87
+   if (ratelimit_test(&impl->rate_limit, SPA_TIMESPEC_TO_NSEC(&ts), SPA_LOG_LEVEL_WARN))
88
+       pw_log_warn("underflow");
89
    impl->resync = true;
90
 }
91
 static void stream_overflow_cb(pa_stream *s, void *userdata)
92
 {
93
    struct impl *impl = userdata;
94
-   pw_log_warn("overflow");
95
+   struct timespec ts;
96
+   clock_gettime(CLOCK_MONOTONIC, &ts);
97
+   if (ratelimit_test(&impl->rate_limit, SPA_TIMESPEC_TO_NSEC(&ts), SPA_LOG_LEVEL_WARN))
98
+       pw_log_warn("overflow");
99
    impl->resync = true;
100
 }
101
 
102
@@ -606,13 +620,14 @@
103
 static int create_pulse_stream(struct impl *impl)
104
 {
105
    pa_sample_spec ss;
106
+   pa_channel_map map;
107
    const char *server_address, *remote_node_target;
108
    pa_proplist *props = NULL;
109
    pa_mainloop_api *api;
110
    char stream_name1024;
111
    pa_buffer_attr bufferattr;
112
    int res = -EIO;
113
-   uint32_t latency_bytes;
114
+   uint32_t latency_bytes, i, aux = 0;
115
 
116
    if ((impl->pa_mainloop = pa_threaded_mainloop_new()) == NULL)
117
        goto error;
118
@@ -659,10 +674,14 @@
119
    ss.channels = impl->info.channels;
120
    ss.rate = impl->info.rate;
121
 
122
+   map.channels = impl->info.channels;
123
+   for (i = 0; i < map.channels; i++)
124
+       map.mapi = (pa_channel_position_t)channel_id2pa(impl->info.positioni, &aux);
125
+
126
    snprintf(stream_name, sizeof(stream_name), _("Tunnel for %s@%s"),
127
            pw_get_user_name(), pw_get_host_name());
128
 
129
-   if (!(impl->pa_stream = pa_stream_new(impl->pa_context, stream_name, &ss, NULL))) {
130
+   if (!(impl->pa_stream = pa_stream_new(impl->pa_context, stream_name, &ss, &map))) {
131
        res = pa_context_errno(impl->pa_context);
132
        goto error_unlock;
133
    }
134
@@ -701,6 +720,8 @@
135
                PA_STREAM_AUTO_TIMING_UPDATE);
136
    } else {
137
        bufferattr.tlength = latency_bytes / 2;
138
+       bufferattr.minreq = bufferattr.tlength / 4;
139
+       bufferattr.prebuf = bufferattr.tlength;
140
 
141
        res = pa_stream_connect_playback(impl->pa_stream,
142
                remote_node_target, &bufferattr,
143
@@ -951,6 +972,8 @@
144
    spa_ringbuffer_init(&impl->ring);
145
    impl->buffer = calloc(1, RINGBUFFER_SIZE);
146
    spa_dll_init(&impl->dll);
147
+   impl->rate_limit.interval = 2 * SPA_NSEC_PER_SEC;
148
+   impl->rate_limit.burst = 1;
149
 
150
    if ((str = pw_properties_get(props, "tunnel.mode")) != NULL) {
151
        if (spa_streq(str, "source")) {
152
pipewire-0.3.59.tar.gz/src/modules/module-raop-sink.c -> pipewire-0.3.60.tar.gz/src/modules/module-raop-sink.c Changed
201
 
1
@@ -108,12 +108,12 @@
2
  *         raop.hostname = "my-raop-device"
3
  *         raop.port = 8190
4
  *         #raop.transport = "udp"
5
- *         raop.encryption = "RSA"
6
+ *         raop.encryption.type = "RSA"
7
  *         #raop.audio.codec = "PCM"
8
  *         #raop.password = "****"
9
  *         #audio.format = "S16"
10
  *         #audio.rate = 44100
11
- *         #audio.channels = 22
12
+ *         #audio.channels = 2
13
  *         #audio.position =  FL FR 
14
  *         stream.props = {
15
  *             # extra sink properties
16
@@ -157,7 +157,7 @@
17
 #define DEFAULT_CHANNELS 2
18
 #define DEFAULT_POSITION " FL FR "
19
 
20
-#define DEFAULT_LATENCY (DEFAULT_RATE*2)
21
+#define DEFAULT_LATENCY 22050
22
 
23
 #define MODULE_USAGE   " raop.hostname=<name of host>  "                   \
24
            " raop.port=<remote port>  "                        \
25
@@ -429,7 +429,7 @@
26
        memset(dst, 0, len);
27
        break;
28
    }
29
-   if (impl->encryption != CRYPTO_NONE)
30
+   if (impl->encryption == CRYPTO_RSA)
31
        aes_encrypt(impl, dst, len);
32
 
33
    impl->rtptime += n_frames;
34
@@ -472,7 +472,7 @@
35
        memset(dst, 0, len);
36
        break;
37
    }
38
-   if (impl->encryption != CRYPTO_NONE)
39
+   if (impl->encryption == CRYPTO_RSA)
40
        aes_encrypt(impl, dst, len);
41
 
42
    pkt0 |= htonl((uint32_t) len + 12);
43
@@ -724,9 +724,10 @@
44
    }
45
 }
46
 
47
-static void rtsp_flush_reply(void *data, int status, const struct spa_dict *headers)
48
+static int rtsp_flush_reply(void *data, int status, const struct spa_dict *headers)
49
 {
50
    pw_log_info("reply %d", status);
51
+   return 0;
52
 }
53
 
54
 static int rtsp_do_flush(struct impl *impl)
55
@@ -751,7 +752,7 @@
56
    return res;
57
 }
58
 
59
-static void rtsp_record_reply(void *data, int status, const struct spa_dict *headers)
60
+static int rtsp_record_reply(void *data, int status, const struct spa_dict *headers)
61
 {
62
    struct impl *impl = data;
63
    const char *str;
64
@@ -760,6 +761,7 @@
65
    uint8_t buffer1024;
66
    struct spa_pod_builder b;
67
    struct spa_latency_info latency;
68
+   char progress128;
69
 
70
    pw_log_info("reply %d", status);
71
 
72
@@ -784,6 +786,10 @@
73
    impl->sync = 0;
74
    impl->sync_period = impl->info.rate / (impl->block_size / impl->frame_size);
75
    impl->recording = true;
76
+
77
+   snprintf(progress, sizeof(progress), "progress: %s/%s/%s\r\n", "0", "0", "0");
78
+   return pw_rtsp_client_send(impl->rtsp, "SET_PARAMETER", NULL,
79
+           "text/parameters", progress, NULL, NULL);
80
 }
81
 
82
 static int rtsp_do_record(struct impl *impl)
83
@@ -837,7 +843,7 @@
84
    pw_loop_update_io(impl->loop, impl->server_source, 0);
85
 }
86
 
87
-static void rtsp_setup_reply(void *data, int status, const struct spa_dict *headers)
88
+static int rtsp_setup_reply(void *data, int status, const struct spa_dict *headers)
89
 {
90
    struct impl *impl = data;
91
    const char *str, *state = NULL, *s;
92
@@ -849,13 +855,13 @@
93
 
94
    if ((str = spa_dict_lookup(headers, "Session")) == NULL) {
95
        pw_log_error("missing Session header");
96
-       return;
97
+       return 0;
98
    }
99
    pw_properties_set(impl->headers, "Session", str);
100
 
101
    if ((str = spa_dict_lookup(headers, "Transport")) == NULL) {
102
        pw_log_error("missing Transport header");
103
-       return;
104
+       return 0;
105
    }
106
 
107
    impl->server_port = control_port = timing_port = 0;
108
@@ -872,18 +878,21 @@
109
    }
110
    if (impl->server_port == 0) {
111
        pw_log_error("missing server port in Transport");
112
-       return;
113
+       return 0;
114
    }
115
 
116
-   pw_getrandom(&impl->seq, sizeof(impl->seq), 0);
117
-   pw_getrandom(&impl->rtptime, sizeof(impl->rtptime), 0);
118
+   if (pw_getrandom(&impl->seq, sizeof(impl->seq), 0) < 0 ||
119
+       pw_getrandom(&impl->rtptime, sizeof(impl->rtptime), 0) <  0) {
120
+       pw_log_error("error generating random seq and rtptime: %m");
121
+       return 0;
122
+   }
123
 
124
    pw_log_info("server port:%u", impl->server_port);
125
 
126
    switch (impl->protocol) {
127
    case PROTO_TCP:
128
-       if ((impl->server_fd = connect_socket(impl, SOCK_STREAM, -1, impl->server_port)) <= 0)
129
-           return;
130
+       if ((impl->server_fd = connect_socket(impl, SOCK_STREAM, -1, impl->server_port)) < 0)
131
+           return impl->server_fd;
132
 
133
        impl->server_source = pw_loop_add_io(impl->loop, impl->server_fd,
134
                SPA_IO_OUT, false, on_server_source_io, impl);
135
@@ -892,16 +901,16 @@
136
    case PROTO_UDP:
137
        if (control_port == 0 || timing_port == 0) {
138
            pw_log_error("missing UDP ports in Transport");
139
-           return;
140
+           return 0;
141
        }
142
        pw_log_info("control:%u timing:%u", control_port, timing_port);
143
 
144
-       if ((impl->server_fd = connect_socket(impl, SOCK_DGRAM, -1, impl->server_port)) <= 0)
145
-           return;
146
-       if ((impl->control_fd = connect_socket(impl, SOCK_DGRAM, impl->control_fd, control_port)) <= 0)
147
-           return;
148
-       if ((impl->timing_fd = connect_socket(impl, SOCK_DGRAM, impl->timing_fd, timing_port)) <= 0)
149
-           return;
150
+       if ((impl->server_fd = connect_socket(impl, SOCK_DGRAM, -1, impl->server_port)) < 0)
151
+           return impl->server_fd;
152
+       if ((impl->control_fd = connect_socket(impl, SOCK_DGRAM, impl->control_fd, control_port)) < 0)
153
+           return impl->control_fd;
154
+       if ((impl->timing_fd = connect_socket(impl, SOCK_DGRAM, impl->timing_fd, timing_port)) < 0)
155
+           return impl->timing_fd;
156
 
157
        ntp = ntp_now(CLOCK_MONOTONIC);
158
        send_udp_timing_packet(impl, ntp, ntp, NULL, 0);
159
@@ -914,8 +923,9 @@
160
            rtsp_do_record(impl);
161
        break;
162
    default:
163
-       return;
164
+       return 0;
165
    }
166
+   return 0;
167
 }
168
 
169
 static int rtsp_do_setup(struct impl *impl)
170
@@ -966,7 +976,7 @@
171
    return -EIO;
172
 }
173
 
174
-static void rtsp_announce_reply(void *data, int status, const struct spa_dict *headers)
175
+static int rtsp_announce_reply(void *data, int status, const struct spa_dict *headers)
176
 {
177
    struct impl *impl = data;
178
 
179
@@ -974,7 +984,7 @@
180
 
181
    pw_properties_set(impl->headers, "Apple-Challenge", NULL);
182
 
183
-   rtsp_do_setup(impl);
184
+   return rtsp_do_setup(impl);
185
 }
186
 
187
 static void base64_encode(const uint8_t *data, size_t len, char *enc, char pad)
188
@@ -1061,7 +1071,8 @@
189
    int res, frames, i, ip_version;
190
    char *sdp;
191
    char local_ip256;
192
-
193
+   int min_latency;
194
+   min_latency = DEFAULT_LATENCY;
195
    host = pw_properties_get(impl->props, "raop.hostname");
196
 
197
    if (impl->protocol == PROTO_TCP)
198
@@ -1088,10 +1099,26 @@
199
                ip_version, host, frames);
200
        break;
201
pipewire-0.3.59.tar.gz/src/modules/module-raop/rtsp-client.c -> pipewire-0.3.60.tar.gz/src/modules/module-raop/rtsp-client.c Changed
66
 
1
@@ -45,7 +45,7 @@
2
    size_t len;
3
    size_t offset;
4
    uint32_t cseq;
5
-   void (*reply) (void *user_data, int status, const struct spa_dict *headers);
6
+   int (*reply) (void *user_data, int status, const struct spa_dict *headers);
7
    void *user_data;
8
 };
9
 
10
@@ -133,6 +133,11 @@
11
    return client->user_data;
12
 }
13
 
14
+const char *pw_rtsp_client_get_url(struct pw_rtsp_client *client)
15
+{
16
+   return client->url;
17
+}
18
+
19
 void pw_rtsp_client_add_listener(struct pw_rtsp_client *client,
20
        struct spa_hook *listener,
21
        const struct pw_rtsp_client_events *events, void *data)
22
@@ -282,16 +287,23 @@
23
 static void dispatch_handler(struct pw_rtsp_client *client)
24
 {
25
    uint32_t cseq;
26
+   int res;
27
+   struct message *msg;
28
+
29
    if (pw_properties_fetch_uint32(client->headers, "CSeq", &cseq) < 0)
30
        return;
31
 
32
    pw_log_info("received reply to request with cseq:%" PRIu32, cseq);
33
 
34
-   struct message *msg = find_pending(client, cseq);
35
+   msg = find_pending(client, cseq);
36
    if (msg) {
37
-       msg->reply(msg->user_data, client->status, &client->headers->dict);
38
+       res = msg->reply(msg->user_data, client->status, &client->headers->dict);
39
        spa_list_remove(&msg->link);
40
        free(msg);
41
+
42
+       if (res < 0)
43
+           pw_log_warn("client %p: handle reply cseq:%u error: %s",
44
+                   client, cseq, spa_strerror(res));
45
    }
46
    else {
47
        pw_rtsp_client_emit_message(client, client->status, &client->headers->dict);
48
@@ -554,7 +566,7 @@
49
 int pw_rtsp_client_url_send(struct pw_rtsp_client *client, const char *url,
50
        const char *cmd, const struct spa_dict *headers,
51
        const char *content_type, const void *content, size_t content_length,
52
-       void (*reply) (void *user_data, int status, const struct spa_dict *headers),
53
+       int (*reply) (void *user_data, int status, const struct spa_dict *headers),
54
        void *user_data)
55
 {
56
    FILE *f;
57
@@ -608,7 +620,7 @@
58
 int pw_rtsp_client_send(struct pw_rtsp_client *client,
59
        const char *cmd, const struct spa_dict *headers,
60
        const char *content_type, const char *content,
61
-       void (*reply) (void *user_data, int status, const struct spa_dict *headers),
62
+       int (*reply) (void *user_data, int status, const struct spa_dict *headers),
63
        void *user_data)
64
 {
65
    const size_t content_length = content ? strlen(content) : 0;
66
pipewire-0.3.59.tar.gz/src/modules/module-raop/rtsp-client.h -> pipewire-0.3.60.tar.gz/src/modules/module-raop/rtsp-client.h Changed
25
 
1
@@ -57,6 +57,7 @@
2
 void pw_rtsp_client_destroy(struct pw_rtsp_client *client);
3
 
4
 void *pw_rtsp_client_get_user_data(struct pw_rtsp_client *client);
5
+const char *pw_rtsp_client_get_url(struct pw_rtsp_client *client);
6
 
7
 void pw_rtsp_client_add_listener(struct pw_rtsp_client *client,
8
        struct spa_hook *listener,
9
@@ -74,13 +75,13 @@
10
 int pw_rtsp_client_url_send(struct pw_rtsp_client *client, const char *url,
11
        const char *cmd, const struct spa_dict *headers,
12
        const char *content_type, const void *content, size_t content_length,
13
-       void (*reply) (void *user_data, int status, const struct spa_dict *headers),
14
+       int (*reply) (void *user_data, int status, const struct spa_dict *headers),
15
        void *user_data);
16
 
17
 int pw_rtsp_client_send(struct pw_rtsp_client *client,
18
        const char *cmd, const struct spa_dict *headers,
19
        const char *content_type, const char *content,
20
-       void (*reply) (void *user_data, int status, const struct spa_dict *headers),
21
+       int (*reply) (void *user_data, int status, const struct spa_dict *headers),
22
        void *user_data);
23
 
24
 
25
pipewire-0.3.60.tar.gz/src/modules/module-rtp Added
2
 
1
+(directory)
2
pipewire-0.3.60.tar.gz/src/modules/module-rtp-sink.c Added
201
 
1
@@ -0,0 +1,944 @@
2
+/* PipeWire
3
+ *
4
+ * Copyright © 2022 Wim Taymans <wim.taymans@gmail.com>
5
+ *
6
+ * Permission is hereby granted, free of charge, to any person obtaining a
7
+ * copy of this software and associated documentation files (the "Software"),
8
+ * to deal in the Software without restriction, including without limitation
9
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10
+ * and/or sell copies of the Software, and to permit persons to whom the
11
+ * Software is furnished to do so, subject to the following conditions:
12
+ *
13
+ * The above copyright notice and this permission notice (including the next
14
+ * paragraph) shall be included in all copies or substantial portions of the
15
+ * Software.
16
+ *
17
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
20
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
23
+ * DEALINGS IN THE SOFTWARE.
24
+ */
25
+
26
+#include "config.h"
27
+
28
+#include <limits.h>
29
+#include <unistd.h>
30
+#include <sys/stat.h>
31
+#include <sys/socket.h>
32
+#include <sys/ioctl.h>
33
+#include <arpa/inet.h>
34
+#include <netinet/ip.h>
35
+#include <net/if.h>
36
+#include <ctype.h>
37
+
38
+#include <spa/param/audio/format-utils.h>
39
+#include <spa/utils/hook.h>
40
+#include <spa/utils/ringbuffer.h>
41
+#include <spa/utils/json.h>
42
+#include <spa/debug/pod.h>
43
+
44
+#include <pipewire/pipewire.h>
45
+#include <pipewire/private.h>
46
+
47
+#include <module-rtp/sap.h>
48
+#include <module-rtp/rtp.h>
49
+
50
+
51
+/** \page page_module_rtp_sink PipeWire Module: RTP sink
52
+ *
53
+ * The `rtp-sink` module creates a PipeWire sink that sends audio
54
+ * RTP packets.
55
+ *
56
+ * ## Module Options
57
+ *
58
+ * Options specific to the behavior of this module
59
+ *
60
+ * - `sap.ip = <str>`: IP address of the SAP messages, default "224.0.0.56"
61
+ * - `sap.port = <int>`: port of the SAP messages, default 9875
62
+ * - `source.ip =<str>`: source IP address, default "0.0.0.0"
63
+ * - `destination.ip =<str>`: destination IP address, default "224.0.0.56"
64
+ * - `destination.port =<int>`: destination port, default random beteen 46000 and 47024
65
+ * - `local.ifname = <str>`: interface name to use
66
+ * - `net.mtu = <int>`: MTU to use, default 1280
67
+ * - `net.ttl = <int>`: TTL to use, default 1
68
+ * - `net.loop = <bool>`: loopback multicast, default false
69
+ * - `sess.name = <str>`: a session name
70
+ * - `stream.props = {}`: properties to be passed to the stream
71
+ *
72
+ * ## General options
73
+ *
74
+ * Options with well-known behavior:
75
+ *
76
+ * - \ref PW_KEY_REMOTE_NAME
77
+ * - \ref PW_KEY_AUDIO_FORMAT
78
+ * - \ref PW_KEY_AUDIO_RATE
79
+ * - \ref PW_KEY_AUDIO_CHANNELS
80
+ * - \ref SPA_KEY_AUDIO_POSITION
81
+ * - \ref PW_KEY_NODE_NAME
82
+ * - \ref PW_KEY_NODE_DESCRIPTION
83
+ * - \ref PW_KEY_MEDIA_NAME
84
+ * - \ref PW_KEY_NODE_GROUP
85
+ * - \ref PW_KEY_NODE_LATENCY
86
+ * - \ref PW_KEY_NODE_VIRTUAL
87
+ * - \ref PW_KEY_MEDIA_CLASS
88
+ *
89
+ * ## Example configuration
90
+ *\code{.unparsed}
91
+ * context.modules = 
92
+ * {   name = libpipewire-module-rtp-sink
93
+ *     args = {
94
+ *         #sap.ip = "224.0.0.56"
95
+ *         #sap.port = 9875
96
+ *         #source.ip = "0.0.0.0"
97
+ *         #destination.ip = "224.0.0.56"
98
+ *         #destination.port = 46000
99
+ *         #local.ifname = "eth0"
100
+ *         #net.mtu = 1280
101
+ *         #net.ttl = 1
102
+ *         #net.loop = false
103
+ *         #sess.name = "PipeWire RTP stream"
104
+ *         #audio.format = "S16BE"
105
+ *         #audio.rate = 48000
106
+ *         #audio.channels = 2
107
+ *         #audio.position =  FL FR 
108
+ *         stream.props = {
109
+ *             node.name = "rtp-sink"
110
+ *         }
111
+ *     }
112
+ *}
113
+ *
114
+ *\endcode
115
+ *
116
+ * \since 0.3.60
117
+ */
118
+
119
+#define NAME "rtp-sink"
120
+
121
+PW_LOG_TOPIC_STATIC(mod_topic, "mod." NAME);
122
+#define PW_LOG_TOPIC_DEFAULT mod_topic
123
+
124
+#define SAP_INTERVAL_SEC   5
125
+#define SAP_MIME_TYPE      "application/sdp"
126
+
127
+#define BUFFER_SIZE        (1u<<20)
128
+#define BUFFER_MASK        (BUFFER_SIZE-1)
129
+
130
+#define DEFAULT_SAP_IP     "224.0.0.56"
131
+#define DEFAULT_SAP_PORT   9875
132
+
133
+#define DEFAULT_FORMAT     "S16BE"
134
+#define DEFAULT_RATE       48000
135
+#define DEFAULT_CHANNELS   2
136
+#define DEFAULT_POSITION   " FL FR "
137
+
138
+#define DEFAULT_PORT       46000
139
+#define DEFAULT_SOURCE_IP  "0.0.0.0"
140
+#define DEFAULT_DESTINATION_IP "224.0.0.56"
141
+#define DEFAULT_TTL        1
142
+#define DEFAULT_MTU        1280
143
+#define DEFAULT_LOOP       false
144
+
145
+#define DEFAULT_MIN_PTIME  2
146
+#define DEFAULT_MAX_PTIME  20
147
+
148
+#define USAGE  "sap.ip=<SAP IP address to send announce, default:"DEFAULT_SAP_IP"> "       \
149
+       "sap.port=<SAP port to send on, default:"SPA_STRINGIFY(DEFAULT_SAP_PORT)"> "    \
150
+       "source.ip=<source IP address, default:"DEFAULT_SOURCE_IP"> "           \
151
+       "destination.ip=<destination IP address, default:"DEFAULT_DESTINATION_IP"> "    \
152
+       "local.ifname=<local interface name to use> "                   \
153
+       "net.mtu=<desired MTU, default:"SPA_STRINGIFY(DEFAULT_MTU)"> "          \
154
+       "net.ttl=<desired TTL, default:"SPA_STRINGIFY(DEFAULT_TTL)"> "          \
155
+       "net.loop=<desired loopback, default:"SPA_STRINGIFY(DEFAULT_LOOP)"> "       \
156
+       "sess.name=<a name for the session> "                       \
157
+       "audio.format=<format, default:"DEFAULT_FORMAT"> "              \
158
+       "audio.rate=<sample rate, default:"SPA_STRINGIFY(DEFAULT_RATE)"> "      \
159
+       "audio.channels=<number of channels, default:"SPA_STRINGIFY(DEFAULT_CHANNELS)"> "\
160
+       "audio.position=<channel map, default:"DEFAULT_POSITION"> "         \
161
+       "stream.props= { key=value ... }"
162
+
163
+static const struct spa_dict_item module_info = {
164
+   { PW_KEY_MODULE_AUTHOR, "Wim Taymans <wim.taymans@gmail.com>" },
165
+   { PW_KEY_MODULE_DESCRIPTION, "RTP Sink" },
166
+   { PW_KEY_MODULE_USAGE, USAGE },
167
+   { PW_KEY_MODULE_VERSION, PACKAGE_VERSION },
168
+};
169
+
170
+static const struct format_info {
171
+   uint32_t format;
172
+   uint32_t size;
173
+   const char *mime;
174
+} format_info = {
175
+   { SPA_AUDIO_FORMAT_U8, 1, "L8" },
176
+   { SPA_AUDIO_FORMAT_ALAW, 1, "PCMA" },
177
+   { SPA_AUDIO_FORMAT_ULAW, 1, "PCMU" },
178
+   { SPA_AUDIO_FORMAT_S16_BE, 2, "L16" },
179
+   { SPA_AUDIO_FORMAT_S24_BE, 3, "L24" },
180
+};
181
+
182
+static const struct format_info *find_format_info(uint32_t format)
183
+{
184
+   SPA_FOR_EACH_ELEMENT_VAR(format_info, f)
185
+       if (f->format == format)
186
+           return f;
187
+   return NULL;
188
+}
189
+
190
+struct impl {
191
+   struct pw_impl_module *module;
192
+   struct spa_hook module_listener;
193
+   struct pw_properties *props;
194
+   struct pw_context *module_context;
195
+
196
+   struct pw_loop *loop;
197
+
198
+   struct pw_core *core;
199
+   struct spa_hook core_listener;
200
+   struct spa_hook core_proxy_listener;
201
pipewire-0.3.60.tar.gz/src/modules/module-rtp-source.c Added
201
 
1
@@ -0,0 +1,1101 @@
2
+/* PipeWire
3
+ *
4
+ * Copyright © 2022 Wim Taymans <wim.taymans@gmail.com>
5
+ *
6
+ * Permission is hereby granted, free of charge, to any person obtaining a
7
+ * copy of this software and associated documentation files (the "Software"),
8
+ * to deal in the Software without restriction, including without limitation
9
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10
+ * and/or sell copies of the Software, and to permit persons to whom the
11
+ * Software is furnished to do so, subject to the following conditions:
12
+ *
13
+ * The above copyright notice and this permission notice (including the next
14
+ * paragraph) shall be included in all copies or substantial portions of the
15
+ * Software.
16
+ *
17
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
20
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
23
+ * DEALINGS IN THE SOFTWARE.
24
+ */
25
+
26
+#include "config.h"
27
+
28
+#include <limits.h>
29
+#include <unistd.h>
30
+#include <sys/stat.h>
31
+#include <sys/socket.h>
32
+#include <sys/ioctl.h>
33
+#include <arpa/inet.h>
34
+#include <netinet/in.h>
35
+#include <net/if.h>
36
+#include <ctype.h>
37
+
38
+#include <spa/param/audio/format-utils.h>
39
+#include <spa/utils/hook.h>
40
+#include <spa/utils/ringbuffer.h>
41
+#include <spa/utils/dll.h>
42
+#include <spa/debug/mem.h>
43
+
44
+#include <pipewire/pipewire.h>
45
+#include <pipewire/private.h>
46
+
47
+#include <module-rtp/sap.h>
48
+#include <module-rtp/rtp.h>
49
+
50
+
51
+/** \page page_module_rtp_source PipeWire Module: RTP source
52
+ *
53
+ * The `rtp-source` module creates a PipeWire source that receives audio
54
+ * RTP packets.
55
+ *
56
+ * ## Module Options
57
+ *
58
+ * Options specific to the behavior of this module
59
+ *
60
+ * - `sap.ip = <str>`: IP address of the SAP messages, default "224.0.0.56"
61
+ * - `sap.port = <str>`: port of the SAP messages, default 9875
62
+ * - `local.ifname = <str>`: interface name to use
63
+ * - `sess.latency.msec = <str>`: target network latency in milliseconds, default 100
64
+ * - `stream.props = {}`: properties to be passed to the stream
65
+ *
66
+ * ## General options
67
+ *
68
+ * Options with well-known behavior:
69
+ *
70
+ * - \ref PW_KEY_NODE_NAME
71
+ * - \ref PW_KEY_NODE_DESCRIPTION
72
+ * - \ref PW_KEY_MEDIA_NAME
73
+ * - \ref PW_KEY_MEDIA_CLASS
74
+ *
75
+ * ## Example configuration
76
+ *\code{.unparsed}
77
+ * context.modules = 
78
+ *  {   name = libpipewire-module-rtp-source
79
+ *      args = {
80
+ *          #sap.ip = 224.0.0.56
81
+ *          #sap.port = 9875
82
+ *          #local.ifname = eth0
83
+ *          sess.latency.msec = 100
84
+ *          stream.props = {
85
+ *             node.name = "rtp-source"
86
+ *             #media.class = "Audio/Source"
87
+ *          }
88
+ *      }
89
+ *  }
90
+ *
91
+ *\endcode
92
+ *
93
+ * \since 0.3.60
94
+ */
95
+
96
+#define NAME "rtp-source"
97
+
98
+PW_LOG_TOPIC_STATIC(mod_topic, "mod." NAME);
99
+#define PW_LOG_TOPIC_DEFAULT mod_topic
100
+
101
+#define SAP_MIME_TYPE      "application/sdp"
102
+
103
+#define ERROR_MSEC     2
104
+#define MAX_SESSIONS       16
105
+#define CLEANUP_INTERVAL_SEC   20
106
+
107
+#define DEFAULT_SAP_IP     "224.0.0.56"
108
+#define DEFAULT_SAP_PORT   9875
109
+#define DEFAULT_SESS_LATENCY   100
110
+
111
+#define BUFFER_SIZE        (1u<<22)
112
+#define BUFFER_MASK        (BUFFER_SIZE-1)
113
+
114
+#define USAGE  "sap.ip=<SAP IP address to listen on, default "DEFAULT_SAP_IP"> "               \
115
+       "sap.port=<SAP port to listen on, default "SPA_STRINGIFY(DEFAULT_SAP_PORT)"> "          \
116
+       "local.ifname=<local interface name to use> "                           \
117
+       "sess.latency.msec=<target network latency, default "SPA_STRINGIFY(DEFAULT_SESS_LATENCY)"> "    \
118
+       "stream.props= { key=value ... }"
119
+
120
+static const struct spa_dict_item module_info = {
121
+   { PW_KEY_MODULE_AUTHOR, "Wim Taymans <wim.taymans@gmail.com>" },
122
+   { PW_KEY_MODULE_DESCRIPTION, "RTP Source" },
123
+   { PW_KEY_MODULE_USAGE,  USAGE },
124
+   { PW_KEY_MODULE_VERSION, PACKAGE_VERSION },
125
+};
126
+
127
+struct impl {
128
+   struct pw_impl_module *module;
129
+   struct spa_hook module_listener;
130
+   struct pw_properties *props;
131
+   struct pw_context *module_context;
132
+
133
+   struct pw_loop *loop;
134
+   struct pw_loop *data_loop;
135
+
136
+   struct pw_core *core;
137
+   struct spa_hook core_listener;
138
+   struct spa_hook core_proxy_listener;
139
+
140
+   struct spa_source *timer;
141
+   struct spa_source *sap_source;
142
+
143
+   struct pw_properties *stream_props;
144
+
145
+   unsigned int do_disconnect:1;
146
+
147
+   char *ifname;
148
+   char *sap_ip;
149
+   int sap_port;
150
+   int sess_latency_msec;
151
+
152
+   struct spa_list sessions;
153
+   uint32_t n_sessions;
154
+};
155
+
156
+static const struct format_info {
157
+   uint32_t format;
158
+   uint32_t size;
159
+   const char *mime;
160
+} format_info = {
161
+   { SPA_AUDIO_FORMAT_U8, 1, "L8" },
162
+   { SPA_AUDIO_FORMAT_ALAW, 1, "PCMA" },
163
+   { SPA_AUDIO_FORMAT_ULAW, 1, "PCMU" },
164
+   { SPA_AUDIO_FORMAT_S16_BE, 2, "L16" },
165
+   { SPA_AUDIO_FORMAT_S24_BE, 3, "L24" },
166
+};
167
+
168
+static const struct format_info *find_format_info(const char *mime)
169
+{
170
+   SPA_FOR_EACH_ELEMENT_VAR(format_info, f)
171
+       if (spa_streq(f->mime, mime))
172
+           return f;
173
+   return NULL;
174
+}
175
+
176
+struct sdp_info {
177
+   uint16_t hash;
178
+
179
+   char origin128;
180
+   char session256;
181
+
182
+   struct sockaddr_storage sa;
183
+   socklen_t salen;
184
+
185
+   uint16_t port;
186
+   uint8_t payload;
187
+
188
+   const struct format_info *format_info;
189
+   struct spa_audio_info_raw info;
190
+   uint32_t stride;
191
+};
192
+
193
+struct session {
194
+   struct impl *impl;
195
+   struct spa_list link;
196
+
197
+   uint64_t timestamp;
198
+
199
+   struct sdp_info info;
200
+
201
pipewire-0.3.60.tar.gz/src/modules/module-rtp/rtp.h Added
80
 
1
@@ -0,0 +1,78 @@
2
+/* PipeWire
3
+ *
4
+ * Copyright © 2022 Wim Taymans <wim.taymans@gmail.com>
5
+ *
6
+ * Permission is hereby granted, free of charge, to any person obtaining a
7
+ * copy of this software and associated documentation files (the "Software"),
8
+ * to deal in the Software without restriction, including without limitation
9
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10
+ * and/or sell copies of the Software, and to permit persons to whom the
11
+ * Software is furnished to do so, subject to the following conditions:
12
+ *
13
+ * The above copyright notice and this permission notice (including the next
14
+ * paragraph) shall be included in all copies or substantial portions of the
15
+ * Software.
16
+ *
17
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
20
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
23
+ * DEALINGS IN THE SOFTWARE.
24
+ */
25
+
26
+#ifndef PIPEWIRE_RTP_H
27
+#define PIPEWIRE_RTP_H
28
+
29
+#ifdef __cplusplus
30
+extern "C" {
31
+#endif
32
+
33
+struct rtp_header {
34
+#if __BYTE_ORDER == __LITTLE_ENDIAN
35
+   unsigned cc:4;
36
+   unsigned x:1;
37
+   unsigned p:1;
38
+   unsigned v:2;
39
+
40
+   unsigned pt:7;
41
+   unsigned m:1;
42
+#elif __BYTE_ORDER == __BIG_ENDIAN
43
+   unsigned v:2;
44
+   unsigned p:1;
45
+   unsigned x:1;
46
+   unsigned cc:4;
47
+
48
+   unsigned m:1;
49
+   unsigned pt:7;
50
+#else
51
+#error "Unknown byte order"
52
+#endif
53
+   uint16_t sequence_number;
54
+   uint32_t timestamp;
55
+   uint32_t ssrc;
56
+   uint32_t csrc0;
57
+} __attribute__ ((packed));
58
+
59
+struct rtp_payload {
60
+#if __BYTE_ORDER == __LITTLE_ENDIAN
61
+   unsigned frame_count:4;
62
+   unsigned rfa0:1;
63
+   unsigned is_last_fragment:1;
64
+   unsigned is_first_fragment:1;
65
+   unsigned is_fragmented:1;
66
+#elif __BYTE_ORDER == __BIG_ENDIAN
67
+   unsigned is_fragmented:1;
68
+   unsigned is_first_fragment:1;
69
+   unsigned is_last_fragment:1;
70
+   unsigned rfa0:1;
71
+   unsigned frame_count:4;
72
+#endif
73
+} __attribute__ ((packed));
74
+
75
+#ifdef __cplusplus
76
+}
77
+#endif
78
+
79
+#endif /* PIPEWIRE_RTP_H */
80
pipewire-0.3.60.tar.gz/src/modules/module-rtp/sap.h Added
60
 
1
@@ -0,0 +1,58 @@
2
+/* PipeWire
3
+ *
4
+ * Copyright © 2022 Wim Taymans <wim.taymans@gmail.com>
5
+ *
6
+ * Permission is hereby granted, free of charge, to any person obtaining a
7
+ * copy of this software and associated documentation files (the "Software"),
8
+ * to deal in the Software without restriction, including without limitation
9
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10
+ * and/or sell copies of the Software, and to permit persons to whom the
11
+ * Software is furnished to do so, subject to the following conditions:
12
+ *
13
+ * The above copyright notice and this permission notice (including the next
14
+ * paragraph) shall be included in all copies or substantial portions of the
15
+ * Software.
16
+ *
17
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
20
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
23
+ * DEALINGS IN THE SOFTWARE.
24
+ */
25
+
26
+#ifndef PIPEWIRE_SAP_H
27
+#define PIPEWIRE_SAP_H
28
+
29
+#ifdef __cplusplus
30
+extern "C" {
31
+#endif
32
+
33
+struct sap_header {
34
+#if __BYTE_ORDER == __LITTLE_ENDIAN
35
+   unsigned c:1;
36
+   unsigned e:1;
37
+   unsigned t:1;
38
+   unsigned r:1;
39
+   unsigned a:1;
40
+   unsigned v:3;
41
+#elif __BYTE_ORDER == __BIG_ENDIAN
42
+   unsigned v:3;
43
+   unsigned a:1;
44
+   unsigned r:1;
45
+   unsigned t:1;
46
+   unsigned e:1;
47
+   unsigned c:1;
48
+#else
49
+#error "Unknown byte order"
50
+#endif
51
+   uint8_t auth_len;
52
+   uint16_t msg_id_hash;
53
+} __attribute__ ((packed));
54
+
55
+#ifdef __cplusplus
56
+}
57
+#endif
58
+
59
+#endif /* PIPEWIRE_SAP_H */
60
pipewire-0.3.59.tar.gz/src/modules/module-x11-bell.c -> pipewire-0.3.60.tar.gz/src/modules/module-x11-bell.c Changed
10
 
1
@@ -109,7 +109,7 @@
2
    if (sample == NULL)
3
        sample = "bell-window-system";
4
 
5
-   pw_log_debug("play sample %s", sample);
6
+   pw_log_info("play sample %s", sample);
7
 
8
    if ((res = ca_context_create(&ca)) < 0) {
9
        pw_log_error("canberra context create error: %s", ca_strerror(res));
10
pipewire-0.3.59.tar.gz/src/modules/module-zeroconf-discover.c -> pipewire-0.3.60.tar.gz/src/modules/module-zeroconf-discover.c Changed
32
 
1
@@ -54,7 +54,10 @@
2
  * audio to/from remote PulseAudio servers. It also works with
3
  * module-protocol-pulse.
4
  *
5
- * This module has no options.
6
+ * ## Module Options
7
+ *
8
+ * - `pulse.latency`: the latency to end-to-end latency in milliseconds to
9
+ *                    maintain (Default 200ms).
10
  *
11
  * ## Example configuration
12
  *
13
@@ -72,7 +75,7 @@
14
 PW_LOG_TOPIC_STATIC(mod_topic, "mod." NAME);
15
 #define PW_LOG_TOPIC_DEFAULT mod_topic
16
 
17
-#define MODULE_USAGE   " "
18
+#define MODULE_USAGE   "pulse.latency=<latency in msec> "
19
 
20
 static const struct spa_dict_item module_props = {
21
    { PW_KEY_MODULE_AUTHOR, "Wim Taymans <wim.taymans@gmail.com>" },
22
@@ -348,6 +351,9 @@
23
                _("%s on %s"), desc, fqdn);
24
    }
25
 
26
+   if ((str = pw_properties_get(impl->properties, "pulse.latency")) != NULL)
27
+       pw_properties_set(props, "pulse.latency", str);
28
+
29
    if ((f = open_memstream(&args, &size)) == NULL) {
30
        pw_log_error("Can't open memstream: %m");
31
        goto done;
32
pipewire-0.3.59.tar.gz/src/pipewire/buffers.c -> pipewire-0.3.60.tar.gz/src/pipewire/buffers.c Changed
14
 
1
@@ -255,6 +255,12 @@
2
    struct port input = { innode, SPA_DIRECTION_INPUT, in_port_id };
3
    int res;
4
 
5
+   if (flags & PW_BUFFERS_FLAG_IN_PRIORITY) {
6
+       struct port tmp = output;
7
+       output = input;
8
+       input = tmp;
9
+   }
10
+
11
    res = param_filter(result, &input, &output, SPA_PARAM_Buffers, &b);
12
    if (res < 0) {
13
        pw_context_debug_port_params(context, input.node, input.direction,
14
pipewire-0.3.59.tar.gz/src/pipewire/buffers.h -> pipewire-0.3.60.tar.gz/src/pipewire/buffers.h Changed
9
 
1
@@ -48,6 +48,7 @@
2
 #define PW_BUFFERS_FLAG_SHARED     (1<<1)  /**< buffers can be shared */
3
 #define PW_BUFFERS_FLAG_DYNAMIC        (1<<2)  /**< buffers have dynamic data */
4
 #define PW_BUFFERS_FLAG_SHARED_MEM (1<<3)  /**< buffers need shared memory */
5
+#define PW_BUFFERS_FLAG_IN_PRIORITY    (1<<4)  /**< input parameters have priority */
6
 
7
 struct pw_buffers {
8
    struct pw_memblock *mem;    /**< allocated buffer memory */
9
pipewire-0.3.59.tar.gz/src/pipewire/context.c -> pipewire-0.3.60.tar.gz/src/pipewire/context.c Changed
36
 
1
@@ -968,13 +968,15 @@
2
    return fa < fb ? -1 : (fa > fb ? 1 : 0);
3
 }
4
 
5
-static bool rates_contains(uint32_t *rates, uint32_t n_rates, uint32_t rate)
6
+static uint32_t find_best_rate(uint32_t *rates, uint32_t n_rates, uint32_t rate, uint32_t best)
7
 {
8
    uint32_t i;
9
-   for (i = 0; i < n_rates; i++)
10
-       if (ratesi == rate)
11
-           return true;
12
-   return false;
13
+   for (i = 0; i < n_rates; i++) {
14
+       if (SPA_ABS((int32_t)rate - (int32_t)ratesi) <
15
+           SPA_ABS((int32_t)rate - (int32_t)best))
16
+           best = ratesi;
17
+   }
18
+   return best;
19
 }
20
 
21
 /* here we evaluate the complete state of the graph.
22
@@ -1187,10 +1189,9 @@
23
             * Start with the default rate. If the desired rate is
24
             * allowed, switch to it */
25
            target_rate = def_rate;
26
-           if (rate.denom != 0 && rate.num == 1) {
27
-               if (rates_contains(rates, n_rates, rate.denom))
28
-                   target_rate = rate.denom;
29
-           }
30
+           if (rate.denom != 0 && rate.num == 1)
31
+               target_rate = find_best_rate(rates, n_rates,
32
+                       rate.denom, target_rate);
33
        }
34
 
35
        if (target_rate != current_rate) {
36
pipewire-0.3.59.tar.gz/src/pipewire/filter.c -> pipewire-0.3.60.tar.gz/src/pipewire/filter.c Changed
22
 
1
@@ -419,16 +419,16 @@
2
    spa_list_for_each(p, param_list, link) {
3
        struct spa_pod *param;
4
 
5
-       result.index = result.next++;
6
-       if (result.index < start)
7
-           continue;
8
-
9
        param = p->param;
10
        if (param == NULL || p->id != id)
11
            continue;
12
 
13
        found = true;
14
 
15
+       result.index = result.next++;
16
+       if (result.index < start)
17
+           continue;
18
+
19
        spa_pod_dynamic_builder_init(&b, buffer, sizeof(buffer), 4096);
20
        if (spa_pod_filter(&b.b, &result.param, param, filter) == 0) {
21
            spa_node_emit_result(&d->hooks, seq, 0, SPA_RESULT_TYPE_NODE_PARAMS, &result);
22
pipewire-0.3.59.tar.gz/src/pipewire/impl-device.c -> pipewire-0.3.60.tar.gz/src/pipewire/impl-device.c Changed
42
 
1
@@ -235,7 +235,7 @@
2
 
3
    if (d->end != -1) {
4
        if (d->pi && d->data.cache) {
5
-           pw_param_update(&impl->param_list, &impl->pending_list);
6
+           pw_param_update(&impl->param_list, &impl->pending_list, 0, NULL);
7
            d->pi->user = 1;
8
            d->pi = NULL;
9
        }
10
@@ -281,8 +281,8 @@
11
        if (d->cache) {
12
            pw_log_debug("%p: add param %d", impl, r->id);
13
            if (d->count++ == 0)
14
-               pw_param_add(&impl->pending_list, r->id, NULL);
15
-           pw_param_add(&impl->pending_list, r->id, r->param);
16
+               pw_param_add(&impl->pending_list, seq, r->id, NULL);
17
+           pw_param_add(&impl->pending_list, seq, r->id, r->param);
18
        }
19
        break;
20
    }
21
@@ -333,10 +333,10 @@
22
        result.next = 0;
23
 
24
        spa_list_for_each(p, &impl->param_list, link) {
25
-           result.index = result.next++;
26
            if (p->id != param_id)
27
                continue;
28
 
29
+           result.index = result.next++;
30
            if (result.index < index)
31
                continue;
32
 
33
@@ -364,7 +364,7 @@
34
        spa_hook_remove(&listener);
35
 
36
        if (!SPA_RESULT_IS_ASYNC(res) && user_data.cache) {
37
-           pw_param_update(&impl->param_list, &impl->pending_list);
38
+           pw_param_update(&impl->param_list, &impl->pending_list, 0, NULL);
39
            pi->user = 1;
40
        }
41
    }
42
pipewire-0.3.59.tar.gz/src/pipewire/impl-link.c -> pipewire-0.3.60.tar.gz/src/pipewire/impl-link.c Changed
21
 
1
@@ -517,6 +517,9 @@
2
        if (output->node->remote || input->node->remote)
3
            alloc_flags |= PW_BUFFERS_FLAG_SHARED_MEM;
4
 
5
+       if (output->node->driver)
6
+           alloc_flags |= PW_BUFFERS_FLAG_IN_PRIORITY;
7
+
8
        /* if output port can alloc buffers, alloc skeleton buffers */
9
        if (SPA_FLAG_IS_SET(out_flags, SPA_PORT_FLAG_CAN_ALLOC_BUFFERS)) {
10
            SPA_FLAG_SET(alloc_flags, PW_BUFFERS_FLAG_NO_MEM);
11
@@ -619,7 +622,8 @@
12
    pw_log_debug("%p: activate activated:%d state:%s", this, impl->activated,
13
            pw_link_state_as_string(this->info.state));
14
 
15
-   if (impl->activated || !this->prepared || !impl->inode->added || !impl->onode->active)
16
+   if (impl->activated || !this->prepared || !impl->inode->active ||
17
+           !impl->inode->added || !impl->onode->active)
18
        return 0;
19
 
20
    if (!impl->io_set) {
21
pipewire-0.3.59.tar.gz/src/pipewire/impl-node.c -> pipewire-0.3.60.tar.gz/src/pipewire/impl-node.c Changed
128
 
1
@@ -158,19 +158,6 @@
2
    this->rt.driver_target.node = NULL;
3
 }
4
 
5
-static int
6
-do_node_remove(struct spa_loop *loop,
7
-          bool async, uint32_t seq, const void *data, size_t size, void *user_data)
8
-{
9
-   struct pw_impl_node *this = user_data;
10
-   if (this->source.loop != NULL) {
11
-       spa_loop_remove_source(loop, &this->source);
12
-       remove_node(this);
13
-   }
14
-   this->added = false;
15
-   return 0;
16
-}
17
-
18
 static void node_deactivate(struct pw_impl_node *this)
19
 {
20
    struct pw_impl_port *port;
21
@@ -185,7 +172,6 @@
22
        spa_list_for_each(link, &port->links, output_link)
23
            pw_impl_link_deactivate(link);
24
    }
25
-   pw_loop_invoke(this->data_loop, do_node_remove, 1, NULL, 0, true, this);
26
 }
27
 
28
 static int idle_node(struct pw_impl_node *this)
29
@@ -354,6 +340,19 @@
30
    return 0;
31
 }
32
 
33
+static int
34
+do_node_remove(struct spa_loop *loop,
35
+          bool async, uint32_t seq, const void *data, size_t size, void *user_data)
36
+{
37
+   struct pw_impl_node *this = user_data;
38
+   if (this->source.loop != NULL) {
39
+       spa_loop_remove_source(loop, &this->source);
40
+       remove_node(this);
41
+   }
42
+   this->added = false;
43
+   return 0;
44
+}
45
+
46
 static void node_update_state(struct pw_impl_node *node, enum pw_node_state state, int res, char *error)
47
 {
48
    struct impl *impl = SPA_CONTAINER_OF(node, struct impl, this);
49
@@ -364,20 +363,29 @@
50
        pw_log_debug("%p: start node driving:%d driver:%d added:%d", node,
51
                node->driving, node->driver, node->added);
52
 
53
+       if (res >= 0) {
54
+           pw_loop_invoke(node->data_loop, do_node_add, 1, NULL, 0, true, node);
55
+       }
56
        if (node->driving && node->driver) {
57
            res = spa_node_send_command(node->node,
58
                &SPA_NODE_COMMAND_INIT(SPA_NODE_COMMAND_Start));
59
            if (res < 0) {
60
                state = PW_NODE_STATE_ERROR;
61
                error = spa_aprintf("Start error: %s", spa_strerror(res));
62
+               pw_loop_invoke(node->data_loop, do_node_remove, 1, NULL, 0, true, node);
63
            }
64
        }
65
        if (res >= 0) {
66
-           pw_loop_invoke(node->data_loop, do_node_add, 1, NULL, 0, true, node);
67
            /* now activate the inputs */
68
            node_activate_inputs(node);
69
        }
70
        break;
71
+   case PW_NODE_STATE_IDLE:
72
+   case PW_NODE_STATE_SUSPENDED:
73
+   case PW_NODE_STATE_ERROR:
74
+       if (state != PW_NODE_STATE_IDLE || impl->pause_on_idle)
75
+           pw_loop_invoke(node->data_loop, do_node_remove, 1, NULL, 0, true, node);
76
+       break;
77
    default:
78
        break;
79
    }
80
@@ -1624,8 +1632,13 @@
81
    struct pw_node_target *t;
82
    struct pw_impl_port *p;
83
 
84
-   pw_log_trace_fp("%p: ready driver:%d exported:%d %p status:%d", node,
85
-           node->driver, node->exported, driver, status);
86
+   pw_log_trace_fp("%p: ready driver:%d exported:%d %p status:%d added:%d", node,
87
+           node->driver, node->exported, driver, status, node->added);
88
+
89
+   if (!node->added) {
90
+       pw_log_warn("%p: ready non-active node", node);
91
+       return -EIO;
92
+   }
93
 
94
    if (SPA_UNLIKELY(node == driver)) {
95
        struct pw_node_activation *a = node->rt.activation;
96
@@ -1954,8 +1967,8 @@
97
            d->callback(d->data, seq, r->id, r->index, r->next, r->param);
98
            if (d->cache) {
99
                if (d->count++ == 0)
100
-                   pw_param_add(&impl->pending_list, r->id, NULL);
101
-               pw_param_add(&impl->pending_list, r->id, r->param);
102
+                   pw_param_add(&impl->pending_list, seq, r->id, NULL);
103
+               pw_param_add(&impl->pending_list, seq, r->id, r->param);
104
            }
105
        }
106
        break;
107
@@ -2007,10 +2020,10 @@
108
        result.next = 0;
109
 
110
        spa_list_for_each(p, &impl->param_list, link) {
111
-           result.index = result.next++;
112
            if (p->id != param_id)
113
                continue;
114
 
115
+           result.index = result.next++;
116
            if (result.index < index)
117
                continue;
118
 
119
@@ -2039,7 +2052,7 @@
120
        spa_hook_remove(&listener);
121
 
122
        if (user_data.cache) {
123
-           pw_param_update(&impl->param_list, &impl->pending_list);
124
+           pw_param_update(&impl->param_list, &impl->pending_list, 0, NULL);
125
            pi->user = 1;
126
        }
127
    }
128
pipewire-0.3.59.tar.gz/src/pipewire/impl-port.c -> pipewire-0.3.60.tar.gz/src/pipewire/impl-port.c Changed
33
 
1
@@ -1199,8 +1199,8 @@
2
            d->callback(d->data, seq, r->id, r->index, r->next, r->param);
3
            if (d->cache) {
4
                if (d->count++ == 0)
5
-                   pw_param_add(&impl->pending_list, r->id, NULL);
6
-               pw_param_add(&impl->pending_list, r->id, r->param);
7
+                   pw_param_add(&impl->pending_list, seq, r->id, NULL);
8
+               pw_param_add(&impl->pending_list, seq, r->id, r->param);
9
            }
10
        }
11
        break;
12
@@ -1253,10 +1253,10 @@
13
        result.next = 0;
14
 
15
        spa_list_for_each(p, &impl->param_list, link) {
16
-           result.index = result.next++;
17
            if (p->id != param_id)
18
                continue;
19
 
20
+           result.index = result.next++;
21
            if (result.index < index)
22
                continue;
23
 
24
@@ -1286,7 +1286,7 @@
25
        spa_hook_remove(&listener);
26
 
27
        if (user_data.cache) {
28
-           pw_param_update(&impl->param_list, &impl->pending_list);
29
+           pw_param_update(&impl->param_list, &impl->pending_list, 0, NULL);
30
            pi->user = 1;
31
        }
32
    }
33
pipewire-0.3.59.tar.gz/src/pipewire/introspect.c -> pipewire-0.3.60.tar.gz/src/pipewire/introspect.c Changed
103
 
1
@@ -210,7 +210,7 @@
2
        info->props = pw_spa_dict_copy(update->props);
3
    }
4
    if (update->change_mask & PW_NODE_CHANGE_MASK_PARAMS) {
5
-       uint32_t i, user, n_params = update->n_params;
6
+       uint32_t i, n_params = update->n_params;
7
        void *np;
8
 
9
        np = pw_reallocarray(info->params, n_params, sizeof(struct spa_param_info));
10
@@ -222,15 +222,18 @@
11
        info->params = np;
12
 
13
        for (i = 0; i < SPA_MIN(info->n_params, n_params); i++) {
14
-           user = reset ? 0 : info->paramsi.user;
15
-           if (info->paramsi.flags != update->paramsi.flags)
16
-               user++;
17
-           info->paramsi = update->paramsi;
18
-           info->paramsi.user = user;
19
+           info->paramsi.id = update->paramsi.id;
20
+           if (reset)
21
+               info->paramsi.user = 0;
22
+           if (info->paramsi.flags != update->paramsi.flags) {
23
+               info->paramsi.flags = update->paramsi.flags;
24
+               info->paramsi.user++;
25
+           }
26
        }
27
        info->n_params = n_params;
28
        for (; i < info->n_params; i++) {
29
-           info->paramsi = update->paramsi;
30
+           info->paramsi.id = update->paramsi.id;
31
+           info->paramsi.flags = update->paramsi.flags;
32
            info->paramsi.user = 1;
33
        }
34
    }
35
@@ -280,7 +283,7 @@
36
        info->props = pw_spa_dict_copy(update->props);
37
    }
38
    if (update->change_mask & PW_PORT_CHANGE_MASK_PARAMS) {
39
-       uint32_t i, user, n_params = update->n_params;
40
+       uint32_t i, n_params = update->n_params;
41
        void *np;
42
 
43
        np = pw_reallocarray(info->params, n_params, sizeof(struct spa_param_info));
44
@@ -292,15 +295,18 @@
45
        info->params = np;
46
 
47
        for (i = 0; i < SPA_MIN(info->n_params, n_params); i++) {
48
-           user = reset ? 0 : info->paramsi.user;
49
-           if (info->paramsi.flags != update->paramsi.flags)
50
-               user++;
51
-           info->paramsi = update->paramsi;
52
-           info->paramsi.user = user;
53
+           info->paramsi.id = update->paramsi.id;
54
+           if (reset)
55
+               info->paramsi.user = 0;
56
+           if (info->paramsi.flags != update->paramsi.flags) {
57
+               info->paramsi.flags = update->paramsi.flags;
58
+               info->paramsi.user++;
59
+           }
60
        }
61
        info->n_params = n_params;
62
        for (; i < info->n_params; i++) {
63
-           info->paramsi = update->paramsi;
64
+           info->paramsi.id = update->paramsi.id;
65
+           info->paramsi.flags = update->paramsi.flags;
66
            info->paramsi.user = 1;
67
        }
68
    }
69
@@ -440,7 +446,7 @@
70
        info->props = pw_spa_dict_copy(update->props);
71
    }
72
    if (update->change_mask & PW_DEVICE_CHANGE_MASK_PARAMS) {
73
-       uint32_t i, user, n_params = update->n_params;
74
+       uint32_t i, n_params = update->n_params;
75
        void *np;
76
 
77
        np = pw_reallocarray(info->params, n_params, sizeof(struct spa_param_info));
78
@@ -452,15 +458,18 @@
79
        info->params = np;
80
 
81
        for (i = 0; i < SPA_MIN(info->n_params, n_params); i++) {
82
-           user = reset ? 0 : info->paramsi.user;
83
-           if (info->paramsi.flags != update->paramsi.flags)
84
-               user++;
85
-           info->paramsi = update->paramsi;
86
-           info->paramsi.user = user;
87
+           info->paramsi.id = update->paramsi.id;
88
+           if (reset)
89
+               info->paramsi.user = 0;
90
+           if (info->paramsi.flags != update->paramsi.flags) {
91
+               info->paramsi.flags = update->paramsi.flags;
92
+               info->paramsi.user++;
93
+           }
94
        }
95
        info->n_params = n_params;
96
        for (; i < info->n_params; i++) {
97
-           info->paramsi = update->paramsi;
98
+           info->paramsi.id = update->paramsi.id;
99
+           info->paramsi.flags = update->paramsi.flags;
100
            info->paramsi.user = 1;
101
        }
102
    }
103
pipewire-0.3.59.tar.gz/src/pipewire/private.h -> pipewire-0.3.60.tar.gz/src/pipewire/private.h Changed
51
 
1
@@ -104,6 +104,7 @@
2
 
3
 struct pw_param {
4
    uint32_t id;
5
+   int32_t seq;
6
    struct spa_list link;
7
    struct spa_pod *param;
8
 };
9
@@ -123,7 +124,7 @@
10
    return count;
11
 }
12
 
13
-static inline struct pw_param *pw_param_add(struct spa_list *params,
14
+static inline struct pw_param *pw_param_add(struct spa_list *params, int32_t seq,
15
        uint32_t id, const struct spa_pod *param)
16
 {
17
    struct pw_param *p;
18
@@ -140,6 +141,7 @@
19
        return NULL;
20
 
21
    p->id = id;
22
+   p->seq = seq;
23
    if (param != NULL) {
24
        p->param = SPA_PTROFF(p, sizeof(*p), struct spa_pod);
25
        memcpy(p->param, param, SPA_POD_SIZE(param));
26
@@ -151,10 +153,22 @@
27
    return p;
28
 }
29
 
30
-static inline void pw_param_update(struct spa_list *param_list, struct spa_list *pending_list)
31
+static inline void pw_param_update(struct spa_list *param_list, struct spa_list *pending_list,
32
+           uint32_t n_params, struct spa_param_info *params)
33
 {
34
-   struct pw_param *p;
35
+   struct pw_param *p, *t;
36
+   uint32_t i;
37
 
38
+   for (i = 0; i < n_params; i++) {
39
+       spa_list_for_each_safe(p, t, pending_list, link) {
40
+           if (p->id == paramsi.id &&
41
+               p->seq != paramsi.seq &&
42
+               p->param != NULL) {
43
+               spa_list_remove(&p->link);
44
+               free(p);
45
+           }
46
+       }
47
+   }
48
    spa_list_consume(p, pending_list, link) {
49
        spa_list_remove(&p->link);
50
        if (p->param == NULL) {
51
pipewire-0.3.59.tar.gz/src/pipewire/stream.c -> pipewire-0.3.60.tar.gz/src/pipewire/stream.c Changed
31
 
1
@@ -544,16 +544,16 @@
2
    spa_list_for_each(p, &d->param_list, link) {
3
        struct spa_pod *param;
4
 
5
-       result.index = result.next++;
6
-       if (result.index < start)
7
-           continue;
8
-
9
        param = p->param;
10
        if (param == NULL || p->id != id)
11
            continue;
12
 
13
        found = true;
14
 
15
+       result.index = result.next++;
16
+       if (result.index < start)
17
+           continue;
18
+
19
        spa_pod_dynamic_builder_init(&b, buffer, sizeof(buffer), 4096);
20
        if (spa_pod_filter(&b.b, &result.param, param, filter) == 0) {
21
            spa_node_emit_result(&d->hooks, seq, 0, SPA_RESULT_TYPE_NODE_PARAMS, &result);
22
@@ -2330,7 +2330,7 @@
23
    struct stream *impl = SPA_CONTAINER_OF(stream, struct stream, this);
24
    pw_loop_invoke(impl->context->data_loop,
25
            drain ? do_drain : do_flush, 1, NULL, 0, true, impl);
26
-   if (!drain)
27
+   if (!drain && impl->node != NULL)
28
        spa_node_send_command(impl->node->node,
29
                &SPA_NODE_COMMAND_INIT(SPA_NODE_COMMAND_Flush));
30
    return 0;
31
pipewire-0.3.59.tar.gz/src/pipewire/thread.c -> pipewire-0.3.60.tar.gz/src/pipewire/thread.c Changed
30
 
1
@@ -116,6 +116,17 @@
2
        *max = sched_get_priority_max(SCHED_OTHER);
3
    return 0;
4
 }
5
+static int impl_acquire_rt(void *object, struct spa_thread *thread, int priority)
6
+{
7
+   pw_log_warn("acquire_rt thread:%p prio:%d not implemented", thread, priority);
8
+   return -ENOTSUP;
9
+}
10
+
11
+static int impl_drop_rt(void *object, struct spa_thread *thread)
12
+{
13
+   pw_log_warn("drop_rt thread:%p not implemented", thread);
14
+   return -ENOTSUP;
15
+}
16
 
17
 static struct {
18
    struct spa_thread_utils utils;
19
@@ -128,7 +139,9 @@
20
    { SPA_VERSION_THREAD_UTILS_METHODS,
21
        .create = impl_create,
22
        .join = impl_join,
23
-       .get_rt_range = impl_get_rt_range
24
+       .get_rt_range = impl_get_rt_range,
25
+       .acquire_rt = impl_acquire_rt,
26
+       .drop_rt = impl_drop_rt,
27
    }
28
 };
29
 
30
pipewire-0.3.59.tar.gz/src/tools/pw-cat.c -> pipewire-0.3.60.tar.gz/src/tools/pw-cat.c Changed
65
 
1
@@ -174,20 +174,18 @@
2
 
3
 static const struct format_info *format_info_by_name(const char *str)
4
 {
5
-   uint32_t i;
6
-   for (i = 0; i < SPA_N_ELEMENTS(format_info); i++)
7
-       if (spa_streq(str, format_infoi.name))
8
-           return &format_infoi;
9
+   SPA_FOR_EACH_ELEMENT_VAR(format_info, i)
10
+       if (spa_streq(str, i->name))
11
+           return i;
12
    return NULL;
13
 }
14
 
15
 static const struct format_info *format_info_by_sf_format(int format)
16
 {
17
-   uint32_t i;
18
    int sub_type = (format & SF_FORMAT_SUBMASK);
19
-   for (i = 0; i < SPA_N_ELEMENTS(format_info); i++)
20
-       if (format_infoi.sf_format == sub_type)
21
-           return &format_infoi;
22
+   SPA_FOR_EACH_ELEMENT_VAR(format_info, i)
23
+       if (i->sf_format == sub_type)
24
+           return i;
25
    return NULL;
26
 }
27
 
28
@@ -431,10 +429,10 @@
29
    int i, nch;
30
    char **ch;
31
 
32
-   for (i = 0; i < (int) SPA_N_ELEMENTS(maps); i++) {
33
-       if (spa_streq(mapsi.name, channel_map)) {
34
-           map->n_channels = mapsi.channels;
35
-           spa_memcpy(map->channels, &mapsi.values,
36
+   SPA_FOR_EACH_ELEMENT_VAR(maps, m) {
37
+       if (spa_streq(m->name, channel_map)) {
38
+           map->n_channels = m->channels;
39
+           spa_memcpy(map->channels, &m->values,
40
                    map->n_channels * sizeof(unsigned int));
41
            return 0;
42
        }
43
@@ -1589,17 +1587,16 @@
44
    case TYPE_DSD:
45
    {
46
        struct spa_audio_info_dsd info;
47
-       size_t i;
48
 
49
        spa_zero(info);
50
        info.channels = data.dsf.info.channels;
51
        info.rate = data.dsf.info.rate / 8;
52
 
53
-       for (i = 0; i < SPA_N_ELEMENTS(dsd_layouts); i++) {
54
-           if (dsd_layoutsi.type != data.dsf.info.channel_type)
55
+       SPA_FOR_EACH_ELEMENT_VAR(dsd_layouts, i) {
56
+           if (i->type != data.dsf.info.channel_type)
57
                continue;
58
-           info.channels = dsd_layoutsi.info.n_channels;
59
-           memcpy(info.position, dsd_layoutsi.info.position,
60
+           info.channels = i->info.n_channels;
61
+           memcpy(info.position, i->info.position,
62
                    info.channels * sizeof(uint32_t));
63
        }
64
        params0 = spa_format_audio_dsd_build(&b, SPA_PARAM_EnumFormat, &info);
65
pipewire-0.3.59.tar.gz/src/tools/pw-cli.c -> pipewire-0.3.60.tar.gz/src/tools/pw-cli.c Changed
74
 
1
@@ -262,14 +262,11 @@
2
 
3
 static bool do_help(struct data *data, const char *cmd, char *args, char **error)
4
 {
5
-   size_t i;
6
-
7
    printf("Available commands:\n");
8
-   for (i = 0; i < SPA_N_ELEMENTS(command_list); i++) {
9
+   SPA_FOR_EACH_ELEMENT_VAR(command_list, c) {
10
        char cmd256;
11
-       snprintf(cmd, sizeof(cmd), "%s | %s",
12
-               command_listi.name, command_listi.alias);
13
-       printf("\t%-20.20s\t%s\n", cmd, command_listi.description);
14
+       snprintf(cmd, sizeof(cmd), "%s | %s", c->name, c->alias);
15
+       printf("\t%-20.20s\t%s\n", cmd, c->description);
16
    }
17
    return true;
18
 }
19
@@ -1312,11 +1309,10 @@
20
 
21
 static const struct class *find_class(const char *type, uint32_t version)
22
 {
23
-   size_t i;
24
-   for (i = 0; i < SPA_N_ELEMENTS(classes); i++) {
25
-       if (spa_streq(classesi->type, type) &&
26
-           classesi->version <= version)
27
-           return classesi;
28
+   SPA_FOR_EACH_ELEMENT_VAR(classes, c) {
29
+       if (spa_streq((*c)->type, type) &&
30
+           (*c)->version <= version)
31
+           return *c;
32
    }
33
    return NULL;
34
 }
35
@@ -2110,7 +2106,6 @@
36
 {
37
    char *a2;
38
    int n;
39
-   size_t i;
40
    char *p, *cmd, *args;
41
 
42
    if ((p = strchr(buf, '#')))
43
@@ -2128,10 +2123,10 @@
44
    cmd = a0;
45
    args = n > 1 ? a1 : "";
46
 
47
-   for (i = 0; i < SPA_N_ELEMENTS(command_list); i++) {
48
-       if (spa_streq(command_listi.name, cmd) ||
49
-           spa_streq(command_listi.alias, cmd)) {
50
-           return command_listi.func(data, cmd, args, error);
51
+   SPA_FOR_EACH_ELEMENT_VAR(command_list, c) {
52
+       if (spa_streq(c->name, cmd) ||
53
+           spa_streq(c->alias, cmd)) {
54
+           return c->func(data, cmd, args, error);
55
        }
56
    }
57
         *error = spa_aprintf("Command \"%s\" does not exist. Type 'help' for usage.", cmd);
58
@@ -2231,13 +2226,13 @@
59
    return matches;
60
 }
61
 
62
-static void readline_init()
63
+static void readline_init(void)
64
 {
65
    rl_attempted_completion_function = readline_command_completion;
66
    rl_callback_handler_install(">> ", input_process_line);
67
 }
68
 
69
-static void readline_cleanup()
70
+static void readline_cleanup(void)
71
 {
72
    rl_callback_handler_remove();
73
 }
74
pipewire-0.3.59.tar.gz/src/tools/pw-dot.c -> pipewire-0.3.60.tar.gz/src/tools/pw-dot.c Changed
10
 
1
@@ -94,7 +94,7 @@
2
    struct spa_hook object_listener;
3
 };
4
 
5
-static char *dot_str_new()
6
+static char *dot_str_new(void)
7
 {
8
         return strdup("");
9
 }
10
pipewire-0.3.59.tar.gz/src/tools/pw-dump.c -> pipewire-0.3.60.tar.gz/src/tools/pw-dump.c Changed
201
 
1
@@ -88,6 +88,7 @@
2
 
3
 struct param {
4
    uint32_t id;
5
+   int32_t seq;
6
    struct spa_list link;
7
    struct spa_pod *param;
8
 };
9
@@ -116,6 +117,8 @@
10
 
11
    const struct class *class;
12
    void *info;
13
+   struct spa_param_info *params;
14
+   uint32_t n_params;
15
 
16
    int changed;
17
    struct spa_list param_list;
18
@@ -148,7 +151,8 @@
19
    return count;
20
 }
21
 
22
-static struct param *add_param(struct spa_list *params, uint32_t id, const struct spa_pod *param)
23
+static struct param *add_param(struct spa_list *params, int seq,
24
+       uint32_t id, const struct spa_pod *param)
25
 {
26
    struct param *p;
27
 
28
@@ -165,6 +169,7 @@
29
        return NULL;
30
 
31
    p->id = id;
32
+   p->seq = seq;
33
    if (param != NULL) {
34
        p->param = SPA_PTROFF(p, sizeof(*p), struct spa_pod);
35
        memcpy(p->param, param, SPA_POD_SIZE(param));
36
@@ -187,17 +192,30 @@
37
    return NULL;
38
 }
39
 
40
-static void object_update_params(struct object *o)
41
+static void object_update_params(struct spa_list *param_list, struct spa_list *pending_list,
42
+       uint32_t n_params, struct spa_param_info *params)
43
 {
44
-   struct param *p;
45
+   struct param *p, *t;
46
+   uint32_t i;
47
+
48
+   for (i = 0; i < n_params; i++) {
49
+       spa_list_for_each_safe(p, t, pending_list, link) {
50
+           if (p->id == paramsi.id &&
51
+               p->seq != paramsi.seq &&
52
+               p->param != NULL) {
53
+               spa_list_remove(&p->link);
54
+               free(p);
55
+           }
56
+       }
57
+   }
58
 
59
-   spa_list_consume(p, &o->pending_list, link) {
60
+   spa_list_consume(p, pending_list, link) {
61
        spa_list_remove(&p->link);
62
        if (p->param == NULL) {
63
-           clear_params(&o->param_list, p->id);
64
+           clear_params(param_list, p->id);
65
            free(p);
66
        } else {
67
-           spa_list_append(&o->param_list, &p->link);
68
+           spa_list_append(param_list, &p->link);
69
        }
70
    }
71
 }
72
@@ -587,9 +605,11 @@
73
    struct object *o = data;
74
    int changed = 0;
75
 
76
-        pw_log_debug("object %p: id:%d change-mask:%08"PRIx64, o, o->id, info->change_mask);
77
+   pw_log_debug("object %p: id:%d change-mask:%08"PRIx64, o, o->id, info->change_mask);
78
 
79
-        info = o->info = pw_client_info_update(o->info, info);
80
+   info = o->info = pw_client_info_update(o->info, info);
81
+   if (info == NULL)
82
+       return;
83
 
84
    if (info->change_mask & PW_CLIENT_CHANGE_MASK_PROPS)
85
        changed++;
86
@@ -644,12 +664,14 @@
87
 
88
 static void module_event_info(void *data, const struct pw_module_info *info)
89
 {
90
-        struct object *o = data;
91
+   struct object *o = data;
92
    int changed = 0;
93
 
94
-        pw_log_debug("object %p: id:%d change-mask:%08"PRIx64, o, o->id, info->change_mask);
95
+   pw_log_debug("object %p: id:%d change-mask:%08"PRIx64, o, o->id, info->change_mask);
96
 
97
-        info = o->info = pw_module_info_update(o->info, info);
98
+   info = o->info = pw_module_info_update(o->info, info);
99
+   if (info == NULL)
100
+       return;
101
 
102
    if (info->change_mask & PW_MODULE_CHANGE_MASK_PROPS)
103
        changed++;
104
@@ -704,12 +726,14 @@
105
 
106
 static void factory_event_info(void *data, const struct pw_factory_info *info)
107
 {
108
-        struct object *o = data;
109
+   struct object *o = data;
110
    int changed = 0;
111
 
112
-        pw_log_debug("object %p: id:%d change-mask:%08"PRIx64, o, o->id, info->change_mask);
113
+   pw_log_debug("object %p: id:%d change-mask:%08"PRIx64, o, o->id, info->change_mask);
114
 
115
-        info = o->info = pw_factory_info_update(o->info, info);
116
+   info = o->info = pw_factory_info_update(o->info, info);
117
+   if (info == NULL)
118
+       return;
119
 
120
    if (info->change_mask & PW_FACTORY_CHANGE_MASK_PROPS)
121
        changed++;
122
@@ -765,10 +789,16 @@
123
 {
124
    struct object *o = data;
125
    uint32_t i, changed = 0;
126
+   int res;
127
 
128
    pw_log_debug("object %p: id:%d change-mask:%08"PRIx64, o, o->id, info->change_mask);
129
 
130
    info = o->info = pw_device_info_update(o->info, info);
131
+   if (info == NULL)
132
+       return;
133
+
134
+   o->params = info->params;
135
+   o->n_params = info->n_params;
136
 
137
    if (info->change_mask & PW_DEVICE_CHANGE_MASK_PROPS)
138
        changed++;
139
@@ -782,12 +812,14 @@
140
            info->paramsi.user = 0;
141
 
142
            changed++;
143
-           clear_params(&o->pending_list, id);
144
+           add_param(&o->pending_list, 0, id, NULL);
145
            if (!(info->paramsi.flags & SPA_PARAM_INFO_READ))
146
                continue;
147
 
148
-           pw_device_enum_params((struct pw_device*)o->proxy,
149
-                   0, id, 0, -1, NULL);
150
+           res = pw_device_enum_params((struct pw_device*)o->proxy,
151
+                   ++info->paramsi.seq, id, 0, -1, NULL);
152
+           if (SPA_RESULT_IS_ASYNC(res))
153
+               info->paramsi.seq = res;
154
        }
155
    }
156
    if (changed) {
157
@@ -801,7 +833,7 @@
158
        const struct spa_pod *param)
159
 {
160
    struct object *o = data;
161
-   add_param(&o->pending_list, id, param);
162
+   add_param(&o->pending_list, seq, id, param);
163
 }
164
 
165
 static const struct pw_device_events device_events = {
166
@@ -859,10 +891,16 @@
167
 {
168
    struct object *o = data;
169
    uint32_t i, changed = 0;
170
+   int res;
171
 
172
    pw_log_debug("object %p: id:%d change-mask:%08"PRIx64, o, o->id, info->change_mask);
173
 
174
    info = o->info = pw_node_info_update(o->info, info);
175
+   if (info == NULL)
176
+       return;
177
+
178
+   o->params = info->params;
179
+   o->n_params = info->n_params;
180
 
181
    if (info->change_mask & PW_NODE_CHANGE_MASK_STATE)
182
        changed++;
183
@@ -879,12 +917,14 @@
184
            info->paramsi.user = 0;
185
 
186
            changed++;
187
-           add_param(&o->pending_list, id, NULL);
188
+           add_param(&o->pending_list, 0, id, NULL);
189
            if (!(info->paramsi.flags & SPA_PARAM_INFO_READ))
190
                continue;
191
 
192
-           pw_node_enum_params((struct pw_node*)o->proxy,
193
-                   0, id, 0, -1, NULL);
194
+           res = pw_node_enum_params((struct pw_node*)o->proxy,
195
+                   ++info->paramsi.seq, id, 0, -1, NULL);
196
+           if (SPA_RESULT_IS_ASYNC(res))
197
+               info->paramsi.seq = res;
198
        }
199
    }
200
    if (changed) {
201
pipewire-0.3.59.tar.gz/src/tools/pw-link.c -> pipewire-0.3.60.tar.gz/src/tools/pw-link.c Changed
30
 
1
@@ -400,8 +400,16 @@
2
            struct object *port_out = find_node_port(data, out_node, PW_DIRECTION_OUTPUT, port_id);
3
            struct object *port_in = find_node_port(data, in_node, PW_DIRECTION_INPUT, port_id);
4
 
5
-           if (!port_out || !port_in)
6
-               break;
7
+           if (!port_out && !port_in) {
8
+               fprintf(stderr, "Input & output port do not exist\n");
9
+               goto no_port;
10
+           } else if (!port_in) {
11
+               fprintf(stderr, "Input port does not exist\n");
12
+               goto no_port;
13
+           } else if (!port_out) {
14
+               fprintf(stderr, "Output port does not exist\n");
15
+               goto no_port;
16
+           }
17
 
18
            pw_properties_setf(data->props, PW_KEY_LINK_OUTPUT_PORT, "%u", port_out->id);
19
            pw_properties_setf(data->props, PW_KEY_LINK_INPUT_PORT, "%u", port_in->id);
20
@@ -422,6 +430,9 @@
21
    pw_properties_setf(data->props, PW_KEY_LINK_INPUT_PORT, "%u", in_port);
22
 
23
    return create_link(data);
24
+
25
+no_port:
26
+   return -ENOENT;
27
 }
28
 
29
 static int do_unlink_ports(struct data *data)
30
pipewire-0.3.59.tar.gz/src/tools/pw-loopback.c -> pipewire-0.3.60.tar.gz/src/tools/pw-loopback.c Changed
63
 
1
@@ -57,6 +57,7 @@
2
 
3
    uint32_t channels;
4
    uint32_t latency;
5
+   float delay;
6
 
7
    struct pw_properties *capture_props;
8
    struct pw_properties *playback_props;
9
@@ -93,6 +94,7 @@
10
        "  -c, --channels                        Number of channels (default %d)\n"
11
        "  -m, --channel-map                     Channel map (default '%s')\n"
12
        "  -l, --latency                         Desired latency in ms\n"
13
+       "  -d, --delay                           Desired delay in float s\n"
14
        "  -C  --capture                         Capture source to connect to\n"
15
        "      --capture-props                   Capture stream properties\n"
16
        "  -P  --playback                        Playback sink to connect to\n"
17
@@ -109,7 +111,7 @@
18
    struct data data = { 0 };
19
    struct pw_loop *l;
20
    const char *opt_remote = NULL;
21
-   char cname256;
22
+   char cname256, value256;
23
    char *args;
24
    size_t size;
25
    FILE *f;
26
@@ -121,6 +123,7 @@
27
        { "name",       required_argument,  NULL, 'n' },
28
        { "channels",       required_argument,  NULL, 'c' },
29
        { "latency",        required_argument,  NULL, 'l' },
30
+       { "delay",      required_argument,  NULL, 'd' },
31
        { "capture",        required_argument,  NULL, 'C' },
32
        { "playback",       required_argument,  NULL, 'P' },
33
        { "capture-props",  required_argument,  NULL, 'i' },
34
@@ -146,7 +149,7 @@
35
        goto exit;
36
    }
37
 
38
-   while ((c = getopt_long(argc, argv, "hVr:n:g:c:m:l:C:P:i:o:", long_options, NULL)) != -1) {
39
+   while ((c = getopt_long(argc, argv, "hVr:n:g:c:m:l:d:C:P:i:o:", long_options, NULL)) != -1) {
40
        switch (c) {
41
        case 'h':
42
            show_help(&data, argv0, false);
43
@@ -177,6 +180,9 @@
44
        case 'l':
45
            data.latency = atoi(optarg) * DEFAULT_RATE / SPA_MSEC_PER_SEC;
46
            break;
47
+       case 'd':
48
+           data.delay = atof(optarg);
49
+           break;
50
        case 'C':
51
            pw_properties_set(data.capture_props, PW_KEY_NODE_TARGET, optarg);
52
            break;
53
@@ -223,6 +229,9 @@
54
        fprintf(f, " remote.name = \"%s\"", opt_remote);
55
    if (data.latency != 0)
56
        fprintf(f, " node.latency = %u/%u", data.latency, DEFAULT_RATE);
57
+   if (data.delay != 0.0f)
58
+       fprintf(f, " target.delay.sec = %s",
59
+               spa_json_format_float(value, sizeof(value), data.delay));
60
    if (data.channels != 0)
61
        fprintf(f, " audio.channels = %u", data.channels);
62
    if (data.opt_channel_map != NULL)
63
pipewire-0.3.59.tar.gz/src/tools/pw-top.c -> pipewire-0.3.60.tar.gz/src/tools/pw-top.c Changed
201
 
1
@@ -62,8 +62,10 @@
2
 
3
 struct node {
4
    struct spa_list link;
5
+   struct data *data;
6
    uint32_t id;
7
    char nameMAX_NAME+1;
8
+   enum pw_node_state state;
9
    struct measurement measurement;
10
    struct driver info;
11
    struct node *driver;
12
@@ -73,6 +75,7 @@
13
    char formatMAX_FORMAT+1;
14
    struct pw_proxy *proxy;
15
    struct spa_hook proxy_listener;
16
+   unsigned int inactive:1;
17
    struct spa_hook object_listener;
18
 };
19
 
20
@@ -95,6 +98,7 @@
21
    int n_nodes;
22
    struct spa_list node_list;
23
    uint32_t generation;
24
+   unsigned pending_refresh:1;
25
 
26
    WINDOW *win;
27
 };
28
@@ -159,12 +163,29 @@
29
    .destroy = on_node_destroy,
30
 };
31
 
32
+static void do_refresh(struct data *d);
33
+
34
+static void node_info(void *data, const struct pw_node_info *info)
35
+{
36
+   struct node *n = data;
37
+
38
+   if (n->state != info->state) {
39
+       n->state = info->state;
40
+       do_refresh(n->data);
41
+   }
42
+}
43
+
44
 static void node_param(void *data, int seq,
45
            uint32_t id, uint32_t index, uint32_t next,
46
            const struct spa_pod *param)
47
 {
48
    struct node *n = data;
49
 
50
+   if (param == NULL) {
51
+       spa_zero(n->format);
52
+       goto done;
53
+   }
54
+
55
    switch (id) {
56
    case SPA_PARAM_Format:
57
    {
58
@@ -177,17 +198,18 @@
59
            switch(media_subtype) {
60
            case SPA_MEDIA_SUBTYPE_raw:
61
            {
62
-               struct spa_audio_info_raw info;
63
+               struct spa_audio_info_raw info = { 0 };
64
                if (spa_format_audio_raw_parse(param, &info) >= 0) {
65
                    snprintf(n->format, sizeof(n->format), "%6.6s %d %d",
66
-                       spa_debug_type_find_short_name(spa_type_audio_format, info.format),
67
+                       spa_debug_type_find_short_name(
68
+                           spa_type_audio_format, info.format),
69
                        info.channels, info.rate);
70
                }
71
                break;
72
            }
73
            case SPA_MEDIA_SUBTYPE_dsd:
74
            {
75
-               struct spa_audio_info_dsd info;
76
+               struct spa_audio_info_dsd info = { 0 };
77
                if (spa_format_audio_dsd_parse(param, &info) >= 0) {
78
                    snprintf(n->format, sizeof(n->format), "DSD%d %d ",
79
                        8 * info.rate / 44100, info.channels);
80
@@ -195,13 +217,25 @@
81
                }
82
                break;
83
            }
84
+           case SPA_MEDIA_SUBTYPE_iec958:
85
+           {
86
+               struct spa_audio_info_iec958 info = { 0 };
87
+               if (spa_format_audio_iec958_parse(param, &info) >= 0) {
88
+                   snprintf(n->format, sizeof(n->format), "IEC958 %s %d",
89
+                       spa_debug_type_find_short_name(
90
+                           spa_type_audio_iec958_codec, info.codec),
91
+                       info.rate);
92
+
93
+               }
94
+               break;
95
+           }
96
            }
97
            break;
98
        case SPA_MEDIA_TYPE_video:
99
            switch(media_subtype) {
100
            case SPA_MEDIA_SUBTYPE_raw:
101
            {
102
-               struct spa_video_info_raw info;
103
+               struct spa_video_info_raw info = { 0 };
104
                if (spa_format_video_raw_parse(param, &info) >= 0) {
105
                    snprintf(n->format, sizeof(n->format), "%6.6s %dx%d",
106
                        spa_debug_type_find_short_name(spa_type_video_format, info.format),
107
@@ -209,6 +243,24 @@
108
                }
109
                break;
110
            }
111
+           case SPA_MEDIA_SUBTYPE_mjpg:
112
+           {
113
+               struct spa_video_info_mjpg info = { 0 };
114
+               if (spa_format_video_mjpg_parse(param, &info) >= 0) {
115
+                   snprintf(n->format, sizeof(n->format), "MJPG %dx%d",
116
+                       info.size.width, info.size.height);
117
+               }
118
+               break;
119
+           }
120
+           case SPA_MEDIA_SUBTYPE_h264:
121
+           {
122
+               struct spa_video_info_h264 info = { 0 };
123
+               if (spa_format_video_h264_parse(param, &info) >= 0) {
124
+                   snprintf(n->format, sizeof(n->format), "H264 %dx%d",
125
+                       info.size.width, info.size.height);
126
+               }
127
+               break;
128
+           }
129
            }
130
            break;
131
        case SPA_MEDIA_TYPE_application:
132
@@ -224,10 +276,13 @@
133
    default:
134
        break;
135
    }
136
+done:
137
+   do_refresh(n->data);
138
 }
139
 
140
 static const struct pw_node_events node_events = {
141
    PW_VERSION_NODE,
142
+   .info = node_info,
143
    .param = node_param,
144
 };
145
 
146
@@ -242,6 +297,7 @@
147
        strncpy(n->name, name, MAX_NAME);
148
    else
149
        snprintf(n->name, sizeof(n->name), "%u", id);
150
+   n->data = d;
151
    n->id = id;
152
    n->driver = n;
153
    n->proxy = pw_registry_bind(d->registry, id, PW_TYPE_INTERFACE_Node, PW_VERSION_NODE, 0);
154
@@ -258,6 +314,7 @@
155
    }
156
    spa_list_append(&d->node_list, &n->link);
157
    d->n_nodes++;
158
+   d->pending_refresh = true;
159
 
160
    return n;
161
 }
162
@@ -268,6 +325,7 @@
163
        pw_proxy_destroy(n->proxy);
164
    spa_list_remove(&n->link);
165
    d->n_nodes--;
166
+   d->pending_refresh = true;
167
    free(n);
168
 }
169
 
170
@@ -332,7 +390,10 @@
171
        return -ENOENT;
172
 
173
    n->measurement = m;
174
-   n->driver = point->driver;
175
+   if (n->driver != point->driver) {
176
+       n->driver = point->driver;
177
+       d->pending_refresh = true;
178
+   }
179
    n->generation = d->generation;
180
    if (m.status != 3) {
181
        n->errors++;
182
@@ -342,9 +403,9 @@
183
    return 0;
184
 }
185
 
186
-static const char *print_time(char *buf, size_t len, uint64_t val)
187
+static const char *print_time(char *buf, bool active, size_t len, uint64_t val)
188
 {
189
-   if (val == (uint64_t)-1)
190
+   if (val == (uint64_t)-1 || !active)
191
        snprintf(buf, len, "   --- ");
192
    else if (val == (uint64_t)-2)
193
        snprintf(buf, len, "   +++ ");
194
@@ -357,9 +418,9 @@
195
    return buf;
196
 }
197
 
198
-static const char *print_perc(char *buf, size_t len, uint64_t val, float quantum)
199
+static const char *print_perc(char *buf, bool active, size_t len, uint64_t val, float quantum)
200
 {
201
pipewire-0.3.59.tar.gz/test/pwtest.c -> pipewire-0.3.60.tar.gz/test/pwtest.c Changed
20
 
1
@@ -358,16 +358,13 @@
2
 void
3
 pwtest_spa_plugin_destroy(struct pwtest_spa_plugin *plugin)
4
 {
5
-   void **dll;
6
-   struct spa_handle **hnd;
7
-
8
-   SPA_FOR_EACH_ELEMENT(plugin->handles, hnd) {
9
+   SPA_FOR_EACH_ELEMENT_VAR(plugin->handles, hnd) {
10
        if (*hnd) {
11
            spa_handle_clear(*hnd);
12
            free(*hnd);
13
        }
14
    }
15
-   SPA_FOR_EACH_ELEMENT(plugin->dlls, dll) {
16
+   SPA_FOR_EACH_ELEMENT_VAR(plugin->dlls, dll) {
17
        if (*dll)
18
            dlclose(*dll);
19
    }
20
pipewire-0.3.59.tar.gz/test/test-functional.c -> pipewire-0.3.60.tar.gz/test/test-functional.c Changed
25
 
1
@@ -29,10 +29,8 @@
2
 
3
 PWTEST(openal_info_test)
4
 {
5
-   int status;
6
-
7
 #ifdef OPENAL_INFO_PATH
8
-   status = pwtest_spawn(OPENAL_INFO_PATH, (char *){ "openal-info", NULL });
9
+   int status = pwtest_spawn(OPENAL_INFO_PATH, (char *){ "openal-info", NULL });
10
    pwtest_int_eq(WEXITSTATUS(status), 0);
11
    return PWTEST_PASS;
12
 #else
13
@@ -42,10 +40,8 @@
14
 
15
 PWTEST(pactl_test)
16
 {
17
-   int status;
18
-
19
 #ifdef PACTL_PATH
20
-   status = pwtest_spawn(PACTL_PATH, (char *){ "pactl", "info", NULL });
21
+   int status = pwtest_spawn(PACTL_PATH, (char *){ "pactl", "info", NULL });
22
    pwtest_int_eq(WEXITSTATUS(status), 0);
23
    return PWTEST_PASS;
24
 #else
25
pipewire-0.3.59.tar.gz/test/test-spa-utils.c -> pipewire-0.3.60.tar.gz/test/test-spa-utils.c Changed
12
 
1
@@ -184,9 +184,8 @@
2
 
3
 #define check_traversal(array_) \
4
    { \
5
-       __typeof__(array_0) *it; \
6
        int count = 0; \
7
-       SPA_FOR_EACH_ELEMENT(array_, it) \
8
+       SPA_FOR_EACH_ELEMENT_VAR(array_, it) \
9
            *it = count++; \
10
        for (size_t i = 0; i < SPA_N_ELEMENTS(array_); i++) \
11
            pwtest_int_eq(array_i, i); \
12
pipewire-0.3.59.tar.gz/test/test-utils.c -> pipewire-0.3.60.tar.gz/test/test-utils.c Changed
12
 
1
@@ -172,9 +172,7 @@
2
        },
3
    };
4
 
5
-   const struct test_case *tc;
6
-
7
-   SPA_FOR_EACH_ELEMENT(test_cases, tc) {
8
+   SPA_FOR_EACH_ELEMENT_VAR(test_cases, tc) {
9
        const char *str = tc->input, *s;
10
        const char *state = NULL;
11
        size_t j = 0, len;
12