Changes of Revision 48

pipewire-aptx.changes Changed
x
 
1
@@ -1,4 +1,9 @@
2
 -------------------------------------------------------------------
3
+Wed Nov 27 09:05:48 UTC 2024 - Bjørn Lie <zaitor@opensuse.org>
4
+
5
+- Update to version 1.2.7
6
+
7
+-------------------------------------------------------------------
8
 Thu Nov  7 09:26:42 UTC 2024 - Bjørn Lie <zaitor@opensuse.org>
9
 
10
 - Update to version 1.2.6
11
pipewire-aptx.spec Changed
10
 
1
@@ -8,7 +8,7 @@
2
 %define minimum_version 1.2.0
3
 
4
 Name:           pipewire-aptx
5
-Version:        1.2.6
6
+Version:        1.2.7
7
 Release:        0
8
 Summary:        PipeWire Bluetooth aptX codec plugin
9
 License:        MIT
10
_service Changed
10
 
1
@@ -2,6 +2,6 @@
2
   <service name="download_url">
3
     <param name="host">gitlab.freedesktop.org</param>
4
     <param name="protocol">https</param>
5
-    <param name="path">/pipewire/pipewire/-/archive/1.2.6/pipewire-1.2.6.tar.bz2</param>
6
+    <param name="path">/pipewire/pipewire/-/archive/1.2.7/pipewire-1.2.7.tar.bz2</param>
7
   </service>
8
 </services>
9
\ No newline at end of file
10
_service:download_url:pipewire-1.2.6.tar.bz2/NEWS -> _service:download_url:pipewire-1.2.7.tar.bz2/NEWS Changed
68
 
1
@@ -1,3 +1,56 @@
2
+# PipeWire 1.2.7 (2024-11-26)
3
+
4
+This is a bugfix release that is API and ABI compatible with the previous
5
+1.2.x and 1.0.x releases.
6
+
7
+## Highlights
8
+  - Backport support for lazy scheduling.
9
+  - Handle the case where processing would stop when an ALSA driver is
10
+    destroyed.
11
+  - Add support for v4l2loopback in the v4l2 plugin.
12
+  - Small bug fixes and improvements.
13
+
14
+## PipeWire
15
+  - Invalidate the proxy ID when removed.
16
+  - Backport support for lazy scheduling.
17
+  - Fix profiler stats for async nodes.
18
+  - Fix EARLY_PROCESS again in pw-stream. (#3480)
19
+
20
+## Modules
21
+  - Fix a crasher issue when nodes are created in the wrong order in
22
+    module-filter-chain.
23
+  - Fix unmap bug in lv2 uri tables.
24
+  - Add ratelimit to jack-tunnel xruns.
25
+  - Remove hardcoded limit in filter-chain sofa plugin.
26
+  - Handle the MTU size correctly in module-rtp and handle large MTUs.
27
+    (#4396)
28
+  - Fix JSON float parsing errors in equalizer module. (#4418)
29
+
30
+## SPA
31
+  - Fix crash in audiotestsrc when using spa-inspect (#4365).
32
+  - Improve JSON float infinity checks.
33
+  - Improve resampler performace a little.
34
+  - Make audioconvert only output when there is something to output.
35
+  - Fix regression in v4l2 port flags which would disable support for
36
+    EXPBUF.
37
+  - Handle the case where an ALSA driver is destroyed and the follower
38
+    becomes a driver. Processing would stop. (#4401)
39
+  - Add support for v4l2loopback in the v4l2 plugin.
40
+
41
+## Pulse-server
42
+  - Give a better error message when running out of fds.
43
+  - Ensure positive latency reporting.
44
+
45
+## GStreamer
46
+  - Fix memory leak in deviceprovider.
47
+  - Fix locking when emitting an error.
48
+
49
+## Tools
50
+  - Fix pw-dot link labels.
51
+
52
+Older versions:
53
+
54
+
55
 # PipeWire 1.2.6 (2024-10-23)
56
 
57
 This is a bugfix release that is API and ABI compatible with the previous
58
@@ -40,9 +93,6 @@
59
 ## Docs
60
   - Backport docs from master.
61
 
62
-Older versions:
63
-
64
-
65
 # PipeWire 1.2.5 (2024-09-27)
66
 
67
 This is an important bugfix release that is API and ABI compatible with the
68
_service:download_url:pipewire-1.2.6.tar.bz2/doc/dox/api/spa-pod.dox -> _service:download_url:pipewire-1.2.7.tar.bz2/doc/dox/api/spa-pod.dox Changed
78
 
1
@@ -219,11 +219,11 @@
2
    SPA_FORMAT_mediaType,      SPA_POD_Id(SPA_MEDIA_TYPE_audio),
3
    SPA_FORMAT_mediaSubtype,   SPA_POD_Id(SPA_MEDIA_SUBTYPE_raw),
4
    //  audio/raw properties
5
-   SPA_FORMAT_AUDIO_format,   SPA_POD_CHOICE_ENUM_Id(
6
+   SPA_FORMAT_AUDIO_format,   SPA_POD_CHOICE_ENUM_Id(4,  //  4 values follow
7
                    SPA_AUDIO_FORMAT_S16, //  default
8
                    SPA_AUDIO_FORMAT_S16, //  alternative1
9
                    SPA_AUDIO_FORMAT_S32, //  alternative2
10
-                   SPA_AUDIO_FORMAT_f32  //  alternative3
11
+                   SPA_AUDIO_FORMAT_F32  //  alternative3
12
                   ),
13
    SPA_FORMAT_AUDIO_rate,     SPA_POD_CHOICE_RANGE_Int(
14
                    44100,      //  default
15
@@ -383,9 +383,9 @@
16
 To parse properties in an object:
17
 
18
 \code{.c}
19
-uint32_t type, subtype, format, rate, channels;
20
+uint32_t id, type, subtype, format, rate, channels;
21
 spa_pod_parser_get_object(&p,
22
-   SPA_TYPE_OBJECT_Format, SPA_PARAM_EnumFormat,
23
+   SPA_TYPE_OBJECT_Format, &id,
24
    SPA_FORMAT_mediaType,      SPA_POD_Id(&type),
25
    SPA_FORMAT_mediaSubtype,   SPA_POD_Id(&subtype),
26
    SPA_FORMAT_AUDIO_format,   SPA_POD_Id(&format),
27
@@ -401,9 +401,9 @@
28
 and when they are not present, the variables will not be changed.
29
 
30
 \code{.c}
31
-uint32_t type, subtype, format, rate = 0, channels = 0;
32
+uint32_t id, type, subtype, format, rate = 0, channels = 0;
33
 spa_pod_parser_get_object(&p,
34
-   SPA_TYPE_OBJECT_Format, SPA_PARAM_EnumFormat,
35
+   SPA_TYPE_OBJECT_Format, &id,
36
    SPA_FORMAT_mediaType,      SPA_POD_Id(&type),
37
    SPA_FORMAT_mediaSubtype,   SPA_POD_Id(&subtype),
38
    SPA_FORMAT_AUDIO_format,   SPA_POD_Id(&format),
39
@@ -425,10 +425,10 @@
40
 Here is an example of parsing the format values as a POD:
41
 
42
 \code{.c}
43
-uint32_t type, subtype;
44
+uint32_t id, type, subtype;
45
 struct spa_pod *format;
46
 spa_pod_parser_get_object(&p,
47
-   SPA_TYPE_OBJECT_Format, SPA_PARAM_EnumFormat,
48
+   SPA_TYPE_OBJECT_Format, &id,
49
    SPA_FORMAT_mediaType,      SPA_POD_Id(&type),
50
    SPA_FORMAT_mediaSubtype,   SPA_POD_Id(&subtype),
51
    SPA_FORMAT_AUDIO_format,   SPA_POD_Pod(&format));
52
@@ -483,21 +483,21 @@
53
    SPA_TYPE_OBJECT_Format, SPA_PARAM_EnumFormat,
54
    SPA_FORMAT_mediaType,      SPA_POD_Id(SPA_MEDIA_TYPE_audio),
55
    SPA_FORMAT_mediaSubtype,   SPA_POD_Id(SPA_MEDIA_SUBTYPE_raw),
56
-   SPA_FORMAT_AUDIO_format,   SPA_POD_CHOICE_ENUM_Id(
57
+   SPA_FORMAT_AUDIO_format,   SPA_POD_CHOICE_ENUM_Id(4,  //  4 values follow
58
                    SPA_AUDIO_FORMAT_S16, //  default
59
                    SPA_AUDIO_FORMAT_S16, //  alternative1
60
                    SPA_AUDIO_FORMAT_S32, //  alternative2
61
-                   SPA_AUDIO_FORMAT_f32  //  alternative3
62
+                   SPA_AUDIO_FORMAT_F32  //  alternative3
63
                   ));
64
 
65
 filter = spa_pod_builder_add_object(&b,
66
    SPA_TYPE_OBJECT_Format, SPA_PARAM_EnumFormat,
67
    SPA_FORMAT_mediaType,      SPA_POD_Id(SPA_MEDIA_TYPE_audio),
68
    SPA_FORMAT_mediaSubtype,   SPA_POD_Id(SPA_MEDIA_SUBTYPE_raw),
69
-   SPA_FORMAT_AUDIO_format,   SPA_POD_CHOICE_ENUM_Id(
70
+   SPA_FORMAT_AUDIO_format,   SPA_POD_CHOICE_ENUM_Id(3,  //  3 values follow
71
                    SPA_AUDIO_FORMAT_S16, //  default
72
                    SPA_AUDIO_FORMAT_S16, //  alternative1
73
-                   SPA_AUDIO_FORMAT_f64  //  alternative2
74
+                   SPA_AUDIO_FORMAT_F64  //  alternative2
75
                   ));
76
 
77
 struct spa_pod *result;
78
_service:download_url:pipewire-1.2.6.tar.bz2/doc/dox/internals/scheduling.dox -> _service:download_url:pipewire-1.2.7.tar.bz2/doc/dox/internals/scheduling.dox Changed
145
 
1
@@ -206,4 +206,143 @@
2
 extra eventfd to signal the server that the graph completed. This is used by the
3
 server to generate the profiler info.
4
 
5
+## Lazy scheduling
6
+
7
+Normally, a driver will wake up the graph and all the followers need to process
8
+the data in sync. There are cases where:
9
+
10
+ 1. the follower might not be ready to process the data
11
+ 2. the driver rate is not ideal, the follower rate is better
12
+ 3. the driver might not know when new data is available in the follower and
13
+    might wake up the graph too often.
14
+
15
+In these cases, the driver and follower roles need to be reversed and a mechanism
16
+needs to be provided so that the follower can know when it is worth processing the
17
+graph.
18
+
19
+For notifying when the graph is ready to be processed, (non driver) nodes can send
20
+a RequestProcess event which will arrive as a RequestProcess command in the driver.
21
+The driver can then decide to run the graph or not.
22
+
23
+When the graph is started or partially controlled by RequestProcess events and
24
+commands we say we have lazy scheduling. The driver is not always scheduling according
25
+to its own rhythm but also depending on the follower.
26
+
27
+We can't just enable lazy scheduling when no follower will emit RequestProcess events
28
+or when no driver will listen for RequestProcess commands. Two new node properties are
29
+defined:
30
+
31
+  - node.supports-lazy = 0 | 1 | ...
32
+
33
+  0 means lazy scheduling as a driver is not supported
34
+  >1 means lazy scheduling as a driver is supported with increasing preference
35
+
36
+  - node.supports-request
37
+
38
+  0 means request events as a follower are not supported
39
+  >1 means request events as a follower are supported with increasing preference
40
+
41
+ We can only enable lazy scheduling when both the driver and (at least one) follower
42
+ has the node.supports-lazy and node.supports-request property respectively.
43
+
44
+ Node can end up as a driver (is_driver()) and lazy scheduling can be enabled (is_lazy()),
45
+ which results in the following cases:
46
+
47
+  driver producer
48
+    -> node.driver = true
49
+    ->  is_driving() && !is_lazy()
50
+    ->  calls trigger_process() to start the graph
51
+
52
+  lazy producer
53
+    ->  node.driver = true
54
+    ->  node.supports-lazy = 1
55
+    ->  is_driving() && is_lazy()
56
+    ->  listens for RequestProcess and calls trigger_process() to start the graph
57
+
58
+  requesting producer
59
+    ->  node.supports-request = 1
60
+    ->  !is_driving() && is_lazy()
61
+    ->  emits RequestProcess to suggest starting the graph
62
+
63
+  follower producer
64
+    ->  !is_driving() && !is_lazy()
65
+
66
+
67
+  driver consumer
68
+    -> node.driver = true
69
+    ->  is_driving() && !is_lazy()
70
+    ->  calls trigger_process() to start the graph
71
+
72
+  lazy consumer
73
+    ->  node.driver = true
74
+    ->  node.supports-lazy = 1
75
+    ->  is_driving() && is_lazy()
76
+    ->  listens for RequestProcess and calls trigger_process() to start the graph
77
+
78
+  requesting consumer
79
+    ->  node.supports-request = 1
80
+    ->  !is_driving() && is_lazy()
81
+    ->  emits RequestProcess to suggest starting the graph
82
+
83
+  follower consumer
84
+    ->  !is_driving() && !is_lazy()
85
+
86
+
87
+Some use cases:
88
+
89
+ 1. Screensharing - driver producer, follower consumer
90
+    - The producer starts the graph when a new frame is available.
91
+    - The consumer consumes the new frames.
92
+    -> throttles to the rate of the producer and idles when no frames
93
+       are available.
94
+
95
+    producer
96
+      - node.driver = true
97
+
98
+    consumer
99
+      - node.driver = false
100
+
101
+    -> producer selected as driver, consumer is simple follower.
102
+       lazy scheduling inactive (no lazy driver or no request follower)
103
+
104
+
105
+ 2. headless server - requesting producer, (semi) lazy driver consumer
106
+
107
+   - The producer emits RequestProcess when new frames are available.
108
+   - The consumer requests new frames from the producer according to its
109
+     refresh rate when there are RequestProcess commands.
110
+   -> this throttles the framerate to the consumer but idles when there is
111
+      no activity on the producer.
112
+
113
+    producer
114
+      - node.driver = true
115
+      - node.supports-request = 1
116
+
117
+    consumer
118
+      - node.driver = true
119
+      - node.supports-lazy = 2
120
+
121
+    -> consumer is selected as driver (lazy > request)
122
+       lazy scheduling active (1 lazy driver and at least 1 request follower)
123
+
124
+
125
+ 3. frame encoder - lazy driver producer, requesting follower consumer
126
+ 
127
+   - The consumer pulls a frame when it is ready to encode the next one.
128
+   - The producer produces the next frame on demand.
129
+   -> throttles the speed to the consumer without idle.
130
+
131
+    producer
132
+      - node.driver = true
133
+      - node.supports-lazy = 1
134
+
135
+    consumer
136
+      - node.driver = true
137
+      - node.supports-request = 1
138
+
139
+    -> producer is selected as driver (lazy <= request)
140
+       lazy scheduling active (1 lazy driver and at least 1 request follower)
141
+
142
+
143
+
144
 */
145
_service:download_url:pipewire-1.2.6.tar.bz2/meson.build -> _service:download_url:pipewire-1.2.7.tar.bz2/meson.build Changed
8
 
1
@@ -1,5 +1,5 @@
2
 project('pipewire', 'c' ,
3
-  version : '1.2.6',
4
+  version : '1.2.7',
5
   license :  'MIT', 'LGPL-2.1-or-later', 'GPL-2.0-only' ,
6
   meson_version : '>= 0.61.1',
7
   default_options :  'warning_level=3',
8
_service:download_url:pipewire-1.2.6.tar.bz2/pipewire-alsa/alsa-plugins/ctl_pipewire.c -> _service:download_url:pipewire-1.2.7.tar.bz2/pipewire-alsa/alsa-plugins/ctl_pipewire.c Changed
10
 
1
@@ -555,7 +555,7 @@
2
        param = spa_pod_builder_pop(&b, &f0);
3
 
4
        pw_log_debug("set device %d mute/volume for node %d", dg->id, g->id);
5
-       pw_device_set_param((struct pw_node*)dg->proxy,
6
+       pw_device_set_param((struct pw_device*)dg->proxy,
7
            SPA_PARAM_Route, 0, param);
8
    } else {
9
        if (!SPA_FLAG_IS_SET(g->permissions, PW_PERM_W | PW_PERM_X))
10
_service:download_url:pipewire-1.2.6.tar.bz2/pipewire-jack/src/pipewire-jack.c -> _service:download_url:pipewire-1.2.7.tar.bz2/pipewire-jack/src/pipewire-jack.c Changed
10
 
1
@@ -3859,7 +3859,7 @@
2
            pw_proxy_add_listener(proxy,
3
                    &c->metadata->proxy_listener,
4
                    &metadata_proxy_events, c);
5
-           pw_metadata_add_listener(proxy,
6
+           pw_metadata_add_listener(c->metadata->proxy,
7
                    &c->metadata->listener,
8
                    &metadata_events, c);
9
            do_sync = true;
10
_service:download_url:pipewire-1.2.6.tar.bz2/pipewire-v4l2/src/pipewire-v4l2.c -> _service:download_url:pipewire-1.2.7.tar.bz2/pipewire-v4l2/src/pipewire-v4l2.c Changed
10
 
1
@@ -2326,7 +2326,7 @@
2
            }
3
 
4
            param = spa_pod_builder_pop(&b, &f0);
5
-           pw_node_set_param(file->node->proxy, SPA_PARAM_Props, 0, param);
6
+           pw_node_set_param((struct pw_node*)file->node->proxy, SPA_PARAM_Props, 0, param);
7
 
8
            found = true;
9
            pw_log_info("ctrl 0x%08" PRIx32 " set ok", arg->id);
10
_service:download_url:pipewire-1.2.6.tar.bz2/spa/include/spa/node/io.h -> _service:download_url:pipewire-1.2.7.tar.bz2/spa/include/spa/node/io.h Changed
9
 
1
@@ -127,6 +127,7 @@
2
 struct spa_io_clock {
3
 #define SPA_IO_CLOCK_FLAG_FREEWHEEL    (1u<<0) /* graph is freewheeling */
4
 #define SPA_IO_CLOCK_FLAG_XRUN_RECOVER (1u<<1) /* recovering from xrun */
5
+#define SPA_IO_CLOCK_FLAG_LAZY     (1u<<2) /* lazy scheduling */
6
    uint32_t flags;         /**< Clock flags */
7
    uint32_t id;            /**< Unique clock id, set by host application */
8
    char name64;            /**< Clock name prefixed with API, set by node when it receives
9
_service:download_url:pipewire-1.2.6.tar.bz2/spa/include/spa/utils/json.h -> _service:download_url:pipewire-1.2.7.tar.bz2/spa/include/spa/utils/json.h Changed
14
 
1
@@ -457,10 +457,8 @@
2
 static inline char *spa_json_format_float(char *str, int size, float val)
3
 {
4
    if (SPA_UNLIKELY(!isnormal(val))) {
5
-       if (val == INFINITY)
6
-           val = FLT_MAX;
7
-       else if (val == -INFINITY)
8
-           val = FLT_MIN;
9
+       if (isinf(val))
10
+           val = signbit(val) ? FLT_MIN : FLT_MAX;
11
        else
12
            val = 0.0f;
13
    }
14
_service:download_url:pipewire-1.2.6.tar.bz2/spa/plugins/alsa/alsa-pcm-sink.c -> _service:download_url:pipewire-1.2.7.tar.bz2/spa/plugins/alsa/alsa-pcm-sink.c Changed
15
 
1
@@ -326,11 +326,13 @@
2
        if (this->n_buffers == 0)
3
            return -EIO;
4
 
5
+       this->want_started = true;
6
        if ((res = spa_alsa_start(this)) < 0)
7
            return res;
8
        break;
9
    case SPA_NODE_COMMAND_Suspend:
10
    case SPA_NODE_COMMAND_Pause:
11
+       this->want_started = false;
12
        if ((res = spa_alsa_pause(this)) < 0)
13
            return res;
14
        break;
15
_service:download_url:pipewire-1.2.6.tar.bz2/spa/plugins/alsa/alsa-pcm-source.c -> _service:download_url:pipewire-1.2.7.tar.bz2/spa/plugins/alsa/alsa-pcm-source.c Changed
15
 
1
@@ -292,11 +292,13 @@
2
        if (this->n_buffers == 0)
3
            return -EIO;
4
 
5
+       this->want_started = true;
6
        if ((res = spa_alsa_start(this)) < 0)
7
            return res;
8
        break;
9
    case SPA_NODE_COMMAND_Pause:
10
    case SPA_NODE_COMMAND_Suspend:
11
+       this->want_started = false;
12
        if ((res = spa_alsa_pause(this)) < 0)
13
            return res;
14
        break;
15
_service:download_url:pipewire-1.2.6.tar.bz2/spa/plugins/alsa/alsa-pcm.c -> _service:download_url:pipewire-1.2.7.tar.bz2/spa/plugins/alsa/alsa-pcm.c Changed
73
 
1
@@ -828,6 +828,7 @@
2
    char card_name256;
3
 
4
    snprintf(card_name, sizeof(card_name), "hw:%d", state->card_index);
5
+   spa_log_debug(state->log, "Trying to open ctl device '%s'", card_name);
6
 
7
    err = snd_ctl_open(&state->ctl, card_name, SND_CTL_NONBLOCK);
8
    if (err < 0) {
9
@@ -894,6 +895,8 @@
10
    state->multi_rate = true;
11
    state->htimestamp = false;
12
    state->htimestamp_max_errors = MAX_HTIMESTAMP_ERROR;
13
+   state->card_index = SPA_ID_INVALID;
14
+
15
    for (i = 0; info && i < info->n_items; i++) {
16
        const char *k = info->itemsi.key;
17
        const char *s = info->itemsi.value;
18
@@ -930,6 +933,17 @@
19
            alsa_set_param(state, k, s);
20
        }
21
    }
22
+
23
+   if (state->card_index == SPA_ID_INVALID) {
24
+       /* If we don't have a card index, see if we have a *:<idx> string */
25
+       sscanf(state->props.device, "%*^::%u", &state->card_index);
26
+       if (state->card_index == SPA_ID_INVALID) {
27
+           spa_log_error(state->log, "Could not determine card index, maybe set %s",
28
+                   SPA_KEY_API_ALSA_CARD);
29
+           return -EINVAL;
30
+       }
31
+   }
32
+
33
    if (state->clock_name0 == '\0')
34
        snprintf(state->clock_name, sizeof(state->clock_name),
35
                "api.alsa.%s-%u",
36
@@ -2481,7 +2495,6 @@
37
    reset_buffers(state);
38
    state->alsa_sync = true;
39
    state->alsa_sync_warning = false;
40
-   state->alsa_recovering = false;
41
    state->alsa_started = false;
42
 
43
    return 0;
44
@@ -2622,8 +2635,6 @@
45
            }
46
            avail = state->threshold * 2;
47
        }
48
-   } else {
49
-       state->alsa_recovering = false;
50
    }
51
    *delay = avail;
52
 
53
@@ -3508,9 +3519,8 @@
54
            rt->driver = state->driver;
55
            spa_log_debug(state->log, "state:%p -> driver:%p", state, state->driver);
56
 
57
-           if(state->linked && state->matching) {
58
+           if(state->linked && state->matching)
59
                try_unlink(state);
60
-           }
61
        }
62
        if (state->following) {
63
            remove_sources(state);
64
@@ -3682,6 +3692,8 @@
65
    setup_matching(state);
66
    if (state->started)
67
        spa_loop_invoke(state->data_loop, do_state_sync, 0, NULL, 0, true, state);
68
+   else if (state->want_started)
69
+       spa_alsa_start(state);
70
 
71
    freewheel = pos != NULL && SPA_FLAG_IS_SET(pos->clock.flags, SPA_IO_CLOCK_FLAG_FREEWHEEL);
72
    if (state->freewheel != freewheel) {
73
_service:download_url:pipewire-1.2.6.tar.bz2/spa/plugins/alsa/alsa-pcm.h -> _service:download_url:pipewire-1.2.7.tar.bz2/spa/plugins/alsa/alsa-pcm.h Changed
17
 
1
@@ -133,6 +133,7 @@
2
    unsigned int opened:1;
3
    unsigned int prepared:1;
4
    unsigned int started:1;
5
+   unsigned int want_started:1;
6
    snd_pcm_t *hndl;
7
 
8
    bool have_format;
9
@@ -211,7 +212,6 @@
10
    unsigned int alsa_started:1;
11
    unsigned int alsa_sync:1;
12
    unsigned int alsa_sync_warning:1;
13
-   unsigned int alsa_recovering:1;
14
    unsigned int following:1;
15
    unsigned int matching:1;
16
    unsigned int resample:1;
17
_service:download_url:pipewire-1.2.6.tar.bz2/spa/plugins/audioconvert/audioconvert.c -> _service:download_url:pipewire-1.2.7.tar.bz2/spa/plugins/audioconvert/audioconvert.c Changed
10
 
1
@@ -3272,7 +3272,7 @@
2
    }
3
 
4
    dir = &this->dirSPA_DIRECTION_OUTPUT;
5
-   if (SPA_LIKELY(n_samples > 0 && (this->out_offset >= max_out || flush_out))) {
6
+   if (SPA_LIKELY(this->out_offset > 0 && (this->out_offset >= max_out || flush_out))) {
7
        /* queue output buffers */
8
        for (i = 0; i < dir->n_ports; i++) {
9
            port = GET_OUT_PORT(this, i);
10
_service:download_url:pipewire-1.2.6.tar.bz2/spa/plugins/audioconvert/resample-native-impl.h -> _service:download_url:pipewire-1.2.7.tar.bz2/spa/plugins/audioconvert/resample-native-impl.h Changed
117
 
1
@@ -52,16 +52,13 @@
2
 {                                      \
3
    struct native_data *data = r->data;                 \
4
    uint32_t index, n_taps = data->n_taps, n_taps2 = n_taps/2;      \
5
-   uint32_t c, olen = *out_len, ilen = *in_len;                \
6
-                                       \
7
-   if (r->channels == 0)                           \
8
-       return;                             \
9
+   uint32_t c, olen = *out_len, ilen = *in_len, ch = r->channels;      \
10
                                        \
11
    index = ioffs;                              \
12
    if (ooffs < olen && index + n_taps <= ilen) {               \
13
        uint32_t to_copy = SPA_MIN(olen - ooffs,            \
14
                ilen - (index + n_taps) + 1);           \
15
-       for (c = 0; c < r->channels; c++) {             \
16
+       for (c = 0; c < ch; c++) {                  \
17
            const float *s = srcc;              \
18
            float *d = dstc;                    \
19
            spa_memcpy(&dooffs, &sindex + n_taps2,      \
20
@@ -74,12 +71,12 @@
21
    *out_len = ooffs;                           \
22
 }
23
 
24
-#define INC(index,phase,n_phases) \
25
-   index += inc;                       \
26
-   phase += frac;                      \
27
-   if (phase >= n_phases) {                \
28
-       phase -= n_phases;              \
29
-       index += 1;                 \
30
+#define INC(index,phase,n_phases)                      \
31
+   index += inc;                               \
32
+   phase += frac;                              \
33
+   if (phase >= n_phases) {                        \
34
+       phase -= n_phases;                      \
35
+       index += 1;                         \
36
    }
37
 
38
 #define MAKE_RESAMPLER_FULL(arch)                      \
39
@@ -89,24 +86,19 @@
40
    uint32_t n_taps = data->n_taps, stride = data->filter_stride_os;    \
41
    uint32_t index, phase, n_phases = data->out_rate;           \
42
    uint32_t c, o, olen = *out_len, ilen = *in_len;             \
43
-   uint32_t inc = data->inc, frac = data->frac;                \
44
-                                       \
45
-   if (r->channels == 0)                           \
46
-       return;                             \
47
-                                       \
48
-   for (c = 0; c < r->channels; c++) {                 \
49
-       const float *s = srcc;                  \
50
-       float *d = dstc;                        \
51
-                                       \
52
-       index = ioffs;                          \
53
-       phase = (uint32_t)data->phase;                  \
54
+   uint32_t inc = data->inc, frac = data->frac, ch = r->channels;      \
55
                                        \
56
-       for (o = ooffs; o < olen && index + n_taps <= ilen; o++) {  \
57
+   index = ioffs;                              \
58
+   phase = (uint32_t)data->phase;                      \
59
+   for (o = ooffs; o < olen && index + n_taps <= ilen; o++) {      \
60
+       float *filter = &data->filterphase * stride;            \
61
+       for (c = 0; c < ch; c++) {                  \
62
+           const float *s = srcc;              \
63
+           float *d = dstc;                    \
64
            inner_product_##arch(&do, &sindex,          \
65
-                   &data->filterphase * stride,        \
66
-                   n_taps);                \
67
-           INC(index, phase, n_phases);                \
68
+                   filter, n_taps);            \
69
        }                               \
70
+       INC(index, phase, n_phases);                    \
71
    }                                   \
72
    *in_len = index;                            \
73
    *out_len = o;                               \
74
@@ -121,28 +113,24 @@
75
    uint32_t n_phases = data->n_phases, out_rate = data->out_rate;      \
76
    uint32_t n_taps = data->n_taps;                     \
77
    uint32_t c, o, olen = *out_len, ilen = *in_len;             \
78
-   uint32_t inc = data->inc, frac = data->frac;                \
79
+   uint32_t inc = data->inc, frac = data->frac, ch = r->channels;          \
80
    float phase;                                \
81
                                        \
82
-   if (r->channels == 0)                           \
83
-       return;                             \
84
-                                       \
85
-   for (c = 0; c < r->channels; c++) {                 \
86
-       const float *s = srcc;                  \
87
-       float *d = dstc;                        \
88
-                                       \
89
-       index = ioffs;                          \
90
-       phase = data->phase;                        \
91
-                                       \
92
-       for (o = ooffs; o < olen && index + n_taps <= ilen; o++) {  \
93
-           float ph = phase * n_phases / out_rate;         \
94
-           uint32_t offset = (uint32_t)floorf(ph);         \
95
+   index = ioffs;                              \
96
+   phase = data->phase;                            \
97
+   for (o = ooffs; o < olen && index + n_taps <= ilen; o++) {      \
98
+       float ph = phase * n_phases / out_rate;             \
99
+       uint32_t offset = (uint32_t)floorf(ph);             \
100
+       float *filter0 = &data->filter(offset+0) * stride;      \
101
+       float *filter1 = &data->filter(offset+1) * stride;      \
102
+       float pho = ph - offset;                    \
103
+       for (c = 0; c < ch; c++) {                  \
104
+           const float *s = srcc;              \
105
+           float *d = dstc;                    \
106
            inner_product_ip_##arch(&do, &sindex,       \
107
-                   &data->filter(offset + 0) * stride, \
108
-                   &data->filter(offset + 1) * stride, \
109
-                   ph - offset, n_taps);           \
110
-           INC(index, phase, out_rate);                \
111
+                   filter0, filter1, pho, n_taps);     \
112
        }                               \
113
+       INC(index, phase, out_rate);                    \
114
    }                                   \
115
    *in_len = index;                            \
116
    *out_len = o;                               \
117
_service:download_url:pipewire-1.2.6.tar.bz2/spa/plugins/audiotestsrc/audiotestsrc.c -> _service:download_url:pipewire-1.2.7.tar.bz2/spa/plugins/audiotestsrc/audiotestsrc.c Changed
20
 
1
@@ -1046,8 +1046,18 @@
2
    this = (struct impl *) handle;
3
 
4
    this->log = spa_support_find(support, n_support, SPA_TYPE_INTERFACE_Log);
5
+
6
    this->data_loop = spa_support_find(support, n_support, SPA_TYPE_INTERFACE_DataLoop);
7
+   if (this->data_loop == NULL) {
8
+       spa_log_error(this->log, "%p: could not find a data loop", this);
9
+       return -EINVAL;
10
+   }
11
+
12
    this->data_system = spa_support_find(support, n_support, SPA_TYPE_INTERFACE_DataSystem);
13
+   if (this->data_system == NULL) {
14
+       spa_log_error(this->log, "%p: could not find a data system", this);
15
+       return -EINVAL;
16
+   }
17
 
18
    for (i = 0; info && i < info->n_items; i++) {
19
        const char *k = info->itemsi.key;
20
_service:download_url:pipewire-1.2.6.tar.bz2/spa/plugins/v4l2/v4l2-source.c -> _service:download_url:pipewire-1.2.7.tar.bz2/spa/plugins/v4l2/v4l2-source.c Changed
33
 
1
@@ -58,6 +58,7 @@
2
    struct spa_meta_videotransform *vt;
3
    struct v4l2_buffer v4l2_buffer;
4
    void *ptr;
5
+   void *mmap_ptr;
6
 };
7
 
8
 #define MAX_CONTROLS   64
9
@@ -75,6 +76,8 @@
10
    bool alloc_buffers;
11
    bool probed_expbuf;
12
    bool have_expbuf;
13
+   bool first_buffer;
14
+   uint32_t max_buffers;
15
 
16
    bool next_fmtdesc;
17
    struct v4l2_fmtdesc fmtdesc;
18
@@ -578,10 +581,13 @@
19
            return -EIO;
20
        if (result.index > 0)
21
            return 0;
22
+       if (port->max_buffers == 0)
23
+           return -EIO;
24
 
25
        param = spa_pod_builder_add_object(&b.b,
26
            SPA_TYPE_OBJECT_ParamBuffers, id,
27
-           SPA_PARAM_BUFFERS_buffers, SPA_POD_CHOICE_RANGE_Int(4, 1, MAX_BUFFERS),
28
+           SPA_PARAM_BUFFERS_buffers, SPA_POD_CHOICE_RANGE_Int(SPA_MIN(4u, port->max_buffers),
29
+               1, port->max_buffers),
30
            SPA_PARAM_BUFFERS_blocks,  SPA_POD_Int(1),
31
            SPA_PARAM_BUFFERS_size,    SPA_POD_Int(port->fmt.fmt.pix.sizeimage),
32
            SPA_PARAM_BUFFERS_stride,  SPA_POD_Int(port->fmt.fmt.pix.bytesperline));
33
_service:download_url:pipewire-1.2.6.tar.bz2/spa/plugins/v4l2/v4l2-utils.c -> _service:download_url:pipewire-1.2.7.tar.bz2/spa/plugins/v4l2/v4l2-utils.c Changed
182
 
1
@@ -120,7 +120,6 @@
2
        spa_log_error(this->log, "'%s' VIDIOC_QBUF: %m", this->props.device);
3
        return -err;
4
    }
5
-
6
    return 0;
7
 }
8
 
9
@@ -147,6 +146,8 @@
10
        if (SPA_FLAG_IS_SET(b->flags, BUFFER_FLAG_MAPPED)) {
11
            munmap(b->ptr, d0.maxsize);
12
        }
13
+       if (b->mmap_ptr)
14
+           munmap(b->mmap_ptr, b->v4l2_buffer.length);
15
        if (SPA_FLAG_IS_SET(b->flags, BUFFER_FLAG_ALLOCATED)) {
16
            spa_log_debug(this->log, "close %d", (int) d0.fd);
17
            close(d0.fd);
18
@@ -911,12 +912,13 @@
19
    spa_zero(reqbuf);
20
    reqbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
21
    reqbuf.memory = V4L2_MEMORY_MMAP;
22
-   reqbuf.count = 2;
23
+   reqbuf.count = port->max_buffers = MAX_BUFFERS;
24
 
25
    if (xioctl(dev->fd, VIDIOC_REQBUFS, &reqbuf) < 0) {
26
        spa_log_error(this->log, "'%s' VIDIOC_REQBUFS: %m", this->props.device);
27
        return -errno;
28
    }
29
+   port->max_buffers = reqbuf.count;
30
 
31
    spa_zero(expbuf);
32
    expbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
33
@@ -1048,6 +1050,8 @@
34
    size->width = fmt.fmt.pix.width;
35
    size->height = fmt.fmt.pix.height;
36
 
37
+   probe_expbuf(this);
38
+
39
    port->fmt = fmt;
40
    port->info.change_mask |= SPA_PORT_CHANGE_MASK_FLAGS | SPA_PORT_CHANGE_MASK_RATE;
41
    port->info.flags = (port->alloc_buffers ? SPA_PORT_FLAG_CAN_ALLOC_BUFFERS : 0) |
42
@@ -1057,8 +1061,6 @@
43
    port->info.rate.num = streamparm.parm.capture.timeperframe.numerator;
44
    port->info.rate.denom = streamparm.parm.capture.timeperframe.denominator;
45
 
46
-   probe_expbuf(this);
47
-
48
    return match ? 0 : 1;
49
 }
50
 
51
@@ -1406,15 +1408,18 @@
52
    if (xioctl(dev->fd, VIDIOC_DQBUF, &buf) < 0)
53
        return -errno;
54
 
55
+   spa_log_trace(this->log, "v4l2 %p: have output %d/%d", this, buf.index, buf.sequence);
56
+
57
    /* Drop the first frame in order to work around common firmware
58
     * timestamp issues */
59
-   if (buf.sequence == 0) {
60
-       xioctl(dev->fd, VIDIOC_QBUF, &buf);
61
+   if (port->first_buffer) {
62
+       port->first_buffer = false;
63
+       if (xioctl(dev->fd, VIDIOC_QBUF, &buf) < 0)
64
+           spa_log_warn(this->log, "v4l2 %p: error qbuf: %m", this);
65
        return 0;
66
    }
67
 
68
    pts = SPA_TIMEVAL_TO_NSEC(&buf.timestamp);
69
-   spa_log_trace(this->log, "v4l2 %p: have output %d", this, buf.index);
70
 
71
    if (this->clock) {
72
        /* FIXME, we should follow the driver clock and target_ values.
73
@@ -1447,12 +1452,15 @@
74
 
75
    d = b->outbuf->datas;
76
    d0.chunk->offset = 0;
77
-   d0.chunk->size = buf.bytesused;
78
+   d0.chunk->size = SPA_MIN(buf.bytesused, d0.maxsize);
79
    d0.chunk->stride = port->fmt.fmt.pix.bytesperline;
80
    d0.chunk->flags = 0;
81
    if (buf.flags & V4L2_BUF_FLAG_ERROR)
82
        d0.chunk->flags |= SPA_CHUNK_FLAG_CORRUPTED;
83
 
84
+   if (b->mmap_ptr && b->ptr)
85
+       memcpy(b->ptr, b->mmap_ptr, d0.chunk->size);
86
+
87
    spa_list_append(&port->queue, &b->link);
88
    return 0;
89
 }
90
@@ -1463,6 +1471,7 @@
91
    struct spa_io_buffers *io;
92
    struct port *port = &this->out_ports0;
93
    struct buffer *b;
94
+   int res;
95
 
96
    if (source->rmask & SPA_IO_ERR) {
97
        struct port *port = &this->out_ports0;
98
@@ -1477,8 +1486,10 @@
99
        return;
100
    }
101
 
102
-   if (mmap_read(this) < 0)
103
+   if ((res = mmap_read(this)) < 0) {
104
+       spa_log_warn(this->log, "v4l2 %p: mmap read error:%s", this, spa_strerror(res));
105
        return;
106
+   }
107
 
108
    if (spa_list_is_empty(&port->queue))
109
        return;
110
@@ -1534,8 +1545,22 @@
111
    reqbuf.count = n_buffers;
112
 
113
    if (xioctl(dev->fd, VIDIOC_REQBUFS, &reqbuf) < 0) {
114
-       spa_log_error(this->log, "'%s' VIDIOC_REQBUFS %m", this->props.device);
115
-       return -errno;
116
+       if (port->memtype != V4L2_MEMORY_USERPTR) {
117
+           spa_log_error(this->log, "'%s' VIDIOC_REQBUFS %m", this->props.device);
118
+           return -errno;
119
+       }
120
+       /* some drivers (v4l2loopback) don't support USERPTR
121
+        * and so we need to try again with MMAP and memcpy */
122
+       port->memtype = V4L2_MEMORY_MMAP;
123
+       spa_zero(reqbuf);
124
+       reqbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
125
+       reqbuf.memory = port->memtype;
126
+       reqbuf.count = n_buffers;
127
+
128
+       if (xioctl(dev->fd, VIDIOC_REQBUFS, &reqbuf) < 0) {
129
+           spa_log_error(this->log, "'%s' VIDIOC_REQBUFS %m", this->props.device);
130
+           return -errno;
131
+       }
132
    }
133
    spa_log_debug(this->log, "got %d buffers", reqbuf.count);
134
    if (reqbuf.count < n_buffers) {
135
@@ -1568,7 +1593,8 @@
136
        b->v4l2_buffer.memory = port->memtype;
137
        b->v4l2_buffer.index = i;
138
 
139
-       if (port->memtype == V4L2_MEMORY_USERPTR) {
140
+       if (port->memtype == V4L2_MEMORY_USERPTR ||
141
+           port->memtype == V4L2_MEMORY_MMAP) {
142
            if (d0.data == NULL) {
143
                void *data;
144
 
145
@@ -1586,8 +1612,24 @@
146
            else
147
                b->ptr = d0.data;
148
 
149
-           b->v4l2_buffer.m.userptr = (unsigned long) b->ptr;
150
-           b->v4l2_buffer.length = d0.maxsize;
151
+           if (port->memtype == V4L2_MEMORY_USERPTR) {
152
+               b->v4l2_buffer.m.userptr = (unsigned long) b->ptr;
153
+               b->v4l2_buffer.length = d0.maxsize;
154
+           }
155
+           else {
156
+               if (xioctl(dev->fd, VIDIOC_QUERYBUF, &b->v4l2_buffer) < 0) {
157
+                   spa_log_error(this->log, "'%s' VIDIOC_QUERYBUF: %m", this->props.device);
158
+                   return -errno;
159
+               }
160
+               b->mmap_ptr = mmap(NULL,
161
+                       b->v4l2_buffer.length,
162
+                       PROT_READ, MAP_PRIVATE,
163
+                       dev->fd, b->v4l2_buffer.m.offset);
164
+               if (b->mmap_ptr == MAP_FAILED) {
165
+                   spa_log_error(this->log, "'%s' mmap: %m", this->props.device);
166
+                   return -errno;
167
+               }
168
+           }
169
        }
170
        else if (port->memtype == V4L2_MEMORY_DMABUF) {
171
            b->v4l2_buffer.m.fd = d0.fd;
172
@@ -1798,6 +1840,9 @@
173
 
174
    spa_log_debug(this->log, "starting");
175
 
176
+   port->first_buffer = true;
177
+   mmap_read(this);
178
+
179
    type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
180
    if (xioctl(dev->fd, VIDIOC_STREAMON, &type) < 0) {
181
        spa_log_error(this->log, "'%s' VIDIOC_STREAMON: %m", this->props.device);
182
_service:download_url:pipewire-1.2.6.tar.bz2/src/examples/video-play-pull.c -> _service:download_url:pipewire-1.2.7.tar.bz2/src/examples/video-play-pull.c Changed
44
 
1
@@ -259,7 +259,11 @@
2
        enable_timeouts(data, false);
3
        break;
4
    case PW_STREAM_STATE_STREAMING:
5
-       enable_timeouts(data, true);
6
+       printf("driving:%d lazy:%d\n",
7
+               pw_stream_is_driving(data->stream),
8
+               pw_stream_is_lazy(data->stream));
9
+       if (pw_stream_is_driving(data->stream) != pw_stream_is_lazy(data->stream))
10
+           enable_timeouts(data, true);
11
        break;
12
    default:
13
        break;
14
@@ -288,8 +292,7 @@
15
 static void on_timeout(void *userdata, uint64_t expirations)
16
 {
17
    struct data *data = userdata;
18
-   if (!data->have_request_process)
19
-       pw_stream_trigger_process(data->stream);
20
+   pw_stream_trigger_process(data->stream);
21
 }
22
 
23
 static void
24
@@ -298,8 +301,7 @@
25
    struct data *data = _data;
26
    switch (SPA_NODE_COMMAND_ID(command)) {
27
    case SPA_NODE_COMMAND_RequestProcess:
28
-       data->have_request_process = true;
29
-       enable_timeouts(data, false);
30
+       pw_log_trace("%p trigger", data);
31
        pw_stream_trigger_process(data->stream);
32
        break;
33
    default:
34
@@ -507,7 +509,8 @@
35
    props = pw_properties_new(PW_KEY_MEDIA_TYPE, "Video",
36
            PW_KEY_MEDIA_CATEGORY, "Capture",
37
            PW_KEY_MEDIA_ROLE, "Camera",
38
-           PW_KEY_PRIORITY_DRIVER, "10000",
39
+           PW_KEY_NODE_SUPPORTS_LAZY, "1",
40
+           PW_KEY_NODE_SUPPORTS_REQUEST, "1",
41
            NULL),
42
    data.path = argc > 1 ? argv1 : NULL;
43
    if (data.path)
44
_service:download_url:pipewire-1.2.6.tar.bz2/src/examples/video-src.c -> _service:download_url:pipewire-1.2.7.tar.bz2/src/examples/video-src.c Changed
25
 
1
@@ -194,8 +194,13 @@
2
        interval.tv_sec = 0;
3
        interval.tv_nsec = 40 * SPA_NSEC_PER_MSEC;
4
 
5
-       pw_loop_update_timer(pw_main_loop_get_loop(data->loop),
6
-               data->timer, &timeout, &interval, false);
7
+       printf("driving:%d lazy:%d\n",
8
+               pw_stream_is_driving(data->stream),
9
+               pw_stream_is_lazy(data->stream));
10
+
11
+       if (pw_stream_is_driving(data->stream) != pw_stream_is_lazy(data->stream))
12
+           pw_loop_update_timer(pw_main_loop_get_loop(data->loop),
13
+                   data->timer, &timeout, &interval, false);
14
        break;
15
    }
16
    default:
17
@@ -305,6 +310,7 @@
18
    data.stream = pw_stream_new(data.core, "video-src",
19
        pw_properties_new(
20
            PW_KEY_MEDIA_CLASS, "Video/Source",
21
+           PW_KEY_NODE_SUPPORTS_REQUEST, "1",
22
            NULL));
23
 
24
    params0 = spa_pod_builder_add_object(&b,
25
_service:download_url:pipewire-1.2.6.tar.bz2/src/gst/gstpipewiredeviceprovider.c -> _service:download_url:pipewire-1.2.7.tar.bz2/src/gst/gstpipewiredeviceprovider.c Changed
10
 
1
@@ -277,7 +277,7 @@
2
 static void do_add_nodes(GstPipeWireDeviceProvider *self)
3
 {
4
   struct node_data *nd;
5
-  GList *new_devices = NULL;
6
+  g_autoptr (GList) new_devices = NULL;
7
   GList *l;
8
 
9
   spa_list_for_each(nd, &self->nodes, link) {
10
_service:download_url:pipewire-1.2.6.tar.bz2/src/gst/gstpipewiresrc.c -> _service:download_url:pipewire-1.2.7.tar.bz2/src/gst/gstpipewiresrc.c Changed
21
 
1
@@ -1004,7 +1004,9 @@
2
     GST_ELEMENT_ERROR (basesrc, STREAM, FORMAT,
3
         ("%s", error_string),
4
         ("This element did not produce valid caps"));
5
+    pw_thread_loop_lock (pwsrc->stream->core->loop);
6
     pw_stream_set_error (pwsrc->stream->pwstream, -EINVAL, "%s", error_string);
7
+    pw_thread_loop_unlock (pwsrc->stream->core->loop);
8
     return FALSE;
9
   }
10
 no_common_caps:
11
@@ -1014,7 +1016,9 @@
12
     GST_ELEMENT_ERROR (basesrc, STREAM, FORMAT,
13
         ("%s", error_string),
14
         ("This element does not have formats in common with the peer"));
15
+    pw_thread_loop_lock (pwsrc->stream->core->loop);
16
     pw_stream_set_error (pwsrc->stream->pwstream, -EPIPE, "%s", error_string);
17
+    pw_thread_loop_unlock (pwsrc->stream->core->loop);
18
     return FALSE;
19
   }
20
 connect_error:
21
_service:download_url:pipewire-1.2.6.tar.bz2/src/modules/module-filter-chain.c -> _service:download_url:pipewire-1.2.7.tar.bz2/src/modules/module-filter-chain.c Changed
126
 
1
@@ -620,9 +620,9 @@
2
 #define DEFAULT_RATE   48000
3
 
4
 struct fc_plugin *load_ladspa_plugin(const struct spa_support *support, uint32_t n_support,
5
-       struct dsp_ops *dsp, const char *path, const char *config);
6
+       struct dsp_ops *dsp, const char *path, const struct spa_dict *info);
7
 struct fc_plugin *load_builtin_plugin(const struct spa_support *support, uint32_t n_support,
8
-       struct dsp_ops *dsp, const char *path, const char *config);
9
+       struct dsp_ops *dsp, const char *path, const struct spa_dict *info);
10
 
11
 struct plugin {
12
    struct spa_list link;
13
@@ -762,6 +762,7 @@
14
    struct pw_context *context;
15
 
16
    struct pw_impl_module *module;
17
+   struct pw_properties *props;
18
 
19
    struct spa_hook module_listener;
20
 
21
@@ -1722,7 +1723,7 @@
22
        pw_log_error("can't load plugin type '%s': %m", type);
23
        pl = NULL;
24
    } else {
25
-       pl = plugin_func(support, n_support, &impl->dsp, path, NULL);
26
+       pl = plugin_func(support, n_support, &impl->dsp, path, &impl->props->dict);
27
    }
28
    if (pl == NULL)
29
        goto exit;
30
@@ -2339,6 +2340,7 @@
31
    struct link *link;
32
    struct descriptor *desc;
33
    const struct fc_descriptor *d;
34
+   const struct fc_plugin *p;
35
    uint32_t i, j, max_samples = impl->quantum_limit;
36
    int res;
37
    float *sd, *dd;
38
@@ -2348,28 +2350,37 @@
39
 
40
    graph->instantiated = true;
41
 
42
+   /* first make instances */
43
    spa_list_for_each(node, &graph->node_list, link) {
44
-
45
        node_cleanup(node);
46
 
47
        desc = node->desc;
48
        d = desc->desc;
49
-       if (d->flags & FC_DESCRIPTOR_SUPPORTS_NULL_DATA) {
50
-           sd = dd = NULL;
51
-       }
52
-       else {
53
-           sd = impl->silence_data;
54
-           dd = impl->discard_data;
55
-       }
56
+       p = desc->plugin->plugin;
57
 
58
        for (i = 0; i < node->n_hndl; i++) {
59
            pw_log_info("instantiate %s %d rate:%lu", d->name, i, impl->rate);
60
            errno = EINVAL;
61
-           if ((node->hndli = d->instantiate(d, impl->rate, i, node->config)) == NULL) {
62
+           if ((node->hndli = d->instantiate(p, d, impl->rate, i, node->config)) == NULL) {
63
                pw_log_error("cannot create plugin instance %d rate:%lu: %m", i, impl->rate);
64
                res = -errno;
65
                goto error;
66
            }
67
+       }
68
+   }
69
+
70
+   /* then link ports and activate */
71
+   spa_list_for_each(node, &graph->node_list, link) {
72
+       desc = node->desc;
73
+       d = desc->desc;
74
+       if (d->flags & FC_DESCRIPTOR_SUPPORTS_NULL_DATA) {
75
+           sd = dd = NULL;
76
+       }
77
+       else {
78
+           sd = impl->silence_data;
79
+           dd = impl->discard_data;
80
+       }
81
+       for (i = 0; i < node->n_hndl; i++) {
82
            for (j = 0; j < desc->n_input; j++) {
83
                port = &node->input_portj;
84
                d->connect_port(node->hndli, port->p, sd);
85
@@ -2898,6 +2909,7 @@
86
    spa_list_consume(pl, &impl->plugin_func_list, link)
87
        free_plugin_func(pl);
88
 
89
+   pw_properties_free(impl->props);
90
    free(impl->silence_data);
91
    free(impl->discard_data);
92
    free(impl);
93
@@ -2997,6 +3009,7 @@
94
        pw_log_error( "can't create properties: %m");
95
        goto error;
96
    }
97
+   impl->props = props;
98
 
99
    impl->capture_props = pw_properties_new(NULL, NULL);
100
    impl->playback_props = pw_properties_new(NULL, NULL);
101
@@ -3021,6 +3034,8 @@
102
            pw_context_get_properties(impl->context),
103
            "default.clock.quantum-limit", 8192u);
104
 
105
+   pw_properties_setf(props, "clock.quantum-limit", "%u", impl->quantum_limit);
106
+
107
    impl->silence_data = calloc(impl->quantum_limit, sizeof(float));
108
    if (impl->silence_data == NULL) {
109
        res = -errno;
110
@@ -3122,7 +3137,6 @@
111
        pw_log_error("can't connect: %m");
112
        goto error;
113
    }
114
-   pw_properties_free(props);
115
 
116
    pw_proxy_add_listener((struct pw_proxy*)impl->core,
117
            &impl->core_proxy_listener,
118
@@ -3140,7 +3154,6 @@
119
    return 0;
120
 
121
 error:
122
-   pw_properties_free(props);
123
    impl_destroy(impl);
124
    return res;
125
 }
126
_service:download_url:pipewire-1.2.6.tar.bz2/src/modules/module-filter-chain/builtin_plugin.c -> _service:download_url:pipewire-1.2.7.tar.bz2/src/modules/module-filter-chain/builtin_plugin.c Changed
197
 
1
@@ -28,9 +28,13 @@
2
 
3
 #define MAX_RATES  32u
4
 
5
-static struct dsp_ops *dsp_ops;
6
+struct plugin {
7
+   struct fc_plugin plugin;
8
+   struct dsp_ops *dsp_ops;
9
+};
10
 
11
 struct builtin {
12
+   struct plugin *plugin;
13
    unsigned long rate;
14
    float *port64;
15
 
16
@@ -44,7 +48,7 @@
17
    float accum;
18
 };
19
 
20
-static void *builtin_instantiate(const struct fc_descriptor * Descriptor,
21
+static void *builtin_instantiate(const struct fc_plugin *plugin, const struct fc_descriptor * Descriptor,
22
        unsigned long SampleRate, int index, const char *config)
23
 {
24
    struct builtin *impl;
25
@@ -53,6 +57,7 @@
26
    if (impl == NULL)
27
        return NULL;
28
 
29
+   impl->plugin = (struct plugin *) plugin;
30
    impl->rate = SampleRate;
31
 
32
    return impl;
33
@@ -75,7 +80,7 @@
34
 {
35
    struct builtin *impl = Instance;
36
    float *in = impl->port1, *out = impl->port0;
37
-   dsp_ops_copy(dsp_ops, out, in, SampleCount);
38
+   dsp_ops_copy(impl->plugin->dsp_ops, out, in, SampleCount);
39
 }
40
 
41
 static struct fc_port copy_ports = {
42
@@ -124,7 +129,7 @@
43
        srcn_src = in;
44
        gainsn_src++ = gain;
45
    }
46
-   dsp_ops_mix_gain(dsp_ops, out, src, gains, n_src, SampleCount);
47
+   dsp_ops_mix_gain(impl->plugin->dsp_ops, out, src, gains, n_src, SampleCount);
48
 }
49
 
50
 static struct fc_port mixer_ports = {
51
@@ -274,7 +279,7 @@
52
  *     
53
  * }
54
  */
55
-static void *bq_instantiate(const struct fc_descriptor * Descriptor,
56
+static void *bq_instantiate(const struct fc_plugin *plugin, const struct fc_descriptor * Descriptor,
57
        unsigned long SampleRate, int index, const char *config)
58
 {
59
    struct builtin *impl;
60
@@ -287,6 +292,7 @@
61
    if (impl == NULL)
62
        return NULL;
63
 
64
+   impl->plugin = (struct plugin *) plugin;
65
    impl->rate = SampleRate;
66
    impl->b0 = impl->a0 = 1.0f;
67
    impl->type = bq_type_from_name(Descriptor->name);
68
@@ -503,7 +509,7 @@
69
        if (impl->freq != freq || impl->Q != Q || impl->gain != gain)
70
            bq_freq_update(impl, impl->type, freq, Q, gain);
71
    }
72
-   dsp_ops_biquad_run(dsp_ops, bq, out, in, samples);
73
+   dsp_ops_biquad_run(impl->plugin->dsp_ops, bq, out, in, samples);
74
 }
75
 
76
 /** bq_lowpass */
77
@@ -635,6 +641,7 @@
78
 
79
 /** convolve */
80
 struct convolver_impl {
81
+   struct plugin *plugin;
82
    unsigned long rate;
83
    float *port64;
84
 
85
@@ -781,7 +788,7 @@
86
    return samples;
87
 }
88
 
89
-static float *resample_buffer(float *samples, int *n_samples,
90
+static float *resample_buffer(struct dsp_ops *dsp_ops, float *samples, int *n_samples,
91
        unsigned long in_rate, unsigned long out_rate, uint32_t quality)
92
 {
93
 #ifdef HAVE_SPA_PLUGINS
94
@@ -858,7 +865,7 @@
95
 #endif
96
 }
97
 
98
-static void * convolver_instantiate(const struct fc_descriptor * Descriptor,
99
+static void * convolver_instantiate(const struct fc_plugin *plugin, const struct fc_descriptor * Descriptor,
100
        unsigned long SampleRate, int index, const char *config)
101
 {
102
    struct convolver_impl *impl;
103
@@ -982,9 +989,11 @@
104
        rate = SampleRate;
105
        samples = read_closest(filenames, gain, delay, offset,
106
                length, channel, &rate, &n_samples);
107
-       if (samples != NULL && rate != SampleRate)
108
-           samples = resample_buffer(samples, &n_samples,
109
+       if (samples != NULL && rate != SampleRate) {
110
+           struct plugin *p = (struct plugin *) plugin;
111
+           samples = resample_buffer(p->dsp_ops, samples, &n_samples,
112
                    rate, SampleRate, resample_quality);
113
+       }
114
    }
115
 
116
    for (i = 0; i < MAX_RATES; i++)
117
@@ -1008,9 +1017,10 @@
118
    if (impl == NULL)
119
        goto error;
120
 
121
+   impl->plugin = (struct plugin *) plugin;
122
    impl->rate = SampleRate;
123
 
124
-   impl->conv = convolver_new(dsp_ops, blocksize, tailsize, samples, n_samples);
125
+   impl->conv = convolver_new(impl->plugin->dsp_ops, blocksize, tailsize, samples, n_samples);
126
    if (impl->conv == NULL)
127
        goto error;
128
 
129
@@ -1076,6 +1086,7 @@
130
 
131
 /** delay */
132
 struct delay_impl {
133
+   struct plugin *plugin;
134
    unsigned long rate;
135
    float *port4;
136
 
137
@@ -1093,7 +1104,7 @@
138
    free(impl);
139
 }
140
 
141
-static void *delay_instantiate(const struct fc_descriptor * Descriptor,
142
+static void *delay_instantiate(const struct fc_plugin *plugin, const struct fc_descriptor * Descriptor,
143
        unsigned long SampleRate, int index, const char *config)
144
 {
145
    struct delay_impl *impl;
146
@@ -1133,6 +1144,7 @@
147
    if (impl == NULL)
148
        return NULL;
149
 
150
+   impl->plugin = (struct plugin *) plugin;
151
    impl->rate = SampleRate;
152
    impl->buffer_samples = (uint32_t)(max_delay * impl->rate);
153
    pw_log_info("max-delay:%f seconds rate:%lu samples:%d", max_delay, impl->rate, impl->buffer_samples);
154
@@ -1311,7 +1323,7 @@
155
    float *ctrl = impl->port3, *notify = impl->port2;
156
 
157
    if (in != NULL && out != NULL)
158
-       dsp_ops_linear(dsp_ops, out, in, mult, add, SampleCount);
159
+       dsp_ops_linear(impl->plugin->dsp_ops, out, in, mult, add, SampleCount);
160
 
161
    if (ctrl != NULL && notify != NULL)
162
        notify0 = ctrl0 * mult + add;
163
@@ -1556,7 +1568,7 @@
164
 
165
        srcn_src++ = in;
166
    }
167
-   dsp_ops_mult(dsp_ops, out, src, n_src, SampleCount);
168
+   dsp_ops_mult(impl->plugin->dsp_ops, out, src, n_src, SampleCount);
169
 }
170
 
171
 static struct fc_port mult_ports = {
172
@@ -1742,14 +1754,18 @@
173
    return NULL;
174
 }
175
 
176
-static struct fc_plugin builtin_plugin = {
177
-   .make_desc = builtin_make_desc
178
-};
179
+static void builtin_plugin_unload(struct fc_plugin *p)
180
+{
181
+   free(p);
182
+}
183
 
184
 struct fc_plugin *load_builtin_plugin(const struct spa_support *support, uint32_t n_support,
185
-       struct dsp_ops *dsp, const char *plugin, const char *config)
186
+       struct dsp_ops *dsp, const char *plugin, const struct spa_dict *info)
187
 {
188
-   dsp_ops = dsp;
189
+   struct plugin *impl = calloc (1, sizeof (struct plugin));
190
+   impl->plugin.make_desc = builtin_make_desc;
191
+   impl->plugin.unload = builtin_plugin_unload;
192
+   impl->dsp_ops = dsp;
193
    pffft_select_cpu(dsp->cpu_flags);
194
-   return &builtin_plugin;
195
+   return (struct fc_plugin *) impl;
196
 }
197
_service:download_url:pipewire-1.2.6.tar.bz2/src/modules/module-filter-chain/convolver.c -> _service:download_url:pipewire-1.2.7.tar.bz2/src/modules/module-filter-chain/convolver.c Changed
201
 
1
@@ -10,9 +10,9 @@
2
 
3
 #include <math.h>
4
 
5
-static struct dsp_ops *dsp;
6
-
7
 struct convolver1 {
8
+   struct dsp_ops *dsp;
9
+
10
    int blockSize;
11
    int segSize;
12
    int segCount;
13
@@ -54,7 +54,7 @@
14
        free(*((void **)p - 1));
15
 }
16
 
17
-static inline void fft_cpx_clear(float *v, int size)
18
+static inline void fft_cpx_clear(struct dsp_ops *dsp, float *v, int size)
19
 {
20
    dsp_ops_clear(dsp, v, size * 2);
21
 }
22
@@ -80,16 +80,16 @@
23
 {
24
    int i;
25
    for (i = 0; i < conv->segCount; i++)
26
-       fft_cpx_clear(conv->segmentsi, conv->fftComplexSize);
27
-   dsp_ops_clear(dsp, conv->overlap, conv->blockSize);
28
-   dsp_ops_clear(dsp, conv->inputBuffer, conv->segSize);
29
-   fft_cpx_clear(conv->pre_mult, conv->fftComplexSize);
30
-   fft_cpx_clear(conv->conv, conv->fftComplexSize);
31
+       fft_cpx_clear(conv->dsp, conv->segmentsi, conv->fftComplexSize);
32
+   dsp_ops_clear(conv->dsp, conv->overlap, conv->blockSize);
33
+   dsp_ops_clear(conv->dsp, conv->inputBuffer, conv->segSize);
34
+   fft_cpx_clear(conv->dsp, conv->pre_mult, conv->fftComplexSize);
35
+   fft_cpx_clear(conv->dsp, conv->conv, conv->fftComplexSize);
36
    conv->inputBufferFill = 0;
37
    conv->current = 0;
38
 }
39
 
40
-static struct convolver1 *convolver1_new(int block, const float *ir, int irlen)
41
+static struct convolver1 *convolver1_new(struct dsp_ops *dsp, int block, const float *ir, int irlen)
42
 {
43
    struct convolver1 *conv;
44
    int i;
45
@@ -107,15 +107,16 @@
46
    if (irlen == 0)
47
        return conv;
48
 
49
+   conv->dsp = dsp;
50
    conv->blockSize = next_power_of_two(block);
51
    conv->segSize = 2 * conv->blockSize;
52
    conv->segCount = (irlen + conv->blockSize-1) / conv->blockSize;
53
    conv->fftComplexSize = (conv->segSize / 2) + 1;
54
 
55
-   conv->fft = dsp_ops_fft_new(dsp, conv->segSize, true);
56
+   conv->fft = dsp_ops_fft_new(conv->dsp, conv->segSize, true);
57
    if (conv->fft == NULL)
58
        goto error;
59
-   conv->ifft = dsp_ops_fft_new(dsp, conv->segSize, true);
60
+   conv->ifft = dsp_ops_fft_new(conv->dsp, conv->segSize, true);
61
    if (conv->ifft == NULL)
62
        goto error;
63
 
64
@@ -133,11 +134,11 @@
65
        conv->segmentsi = fft_cpx_alloc(conv->fftComplexSize);
66
        conv->segmentsIri = fft_cpx_alloc(conv->fftComplexSize);
67
 
68
-       dsp_ops_copy(dsp, conv->fft_buffer, &iri * conv->blockSize, copy);
69
+       dsp_ops_copy(conv->dsp, conv->fft_buffer, &iri * conv->blockSize, copy);
70
        if (copy < conv->segSize)
71
-           dsp_ops_clear(dsp, conv->fft_buffer + copy, conv->segSize - copy);
72
+           dsp_ops_clear(conv->dsp, conv->fft_buffer + copy, conv->segSize - copy);
73
 
74
-           dsp_ops_fft_run(dsp, conv->fft, 1, conv->fft_buffer, conv->segmentsIri);
75
+           dsp_ops_fft_run(conv->dsp, conv->fft, 1, conv->fft_buffer, conv->segmentsIri);
76
    }
77
    conv->pre_mult = fft_cpx_alloc(conv->fftComplexSize);
78
    conv->conv = fft_cpx_alloc(conv->fftComplexSize);
79
@@ -166,9 +167,9 @@
80
        fft_cpx_free(conv->segmentsIri);
81
    }
82
    if (conv->fft)
83
-       dsp_ops_fft_free(dsp, conv->fft);
84
+       dsp_ops_fft_free(conv->dsp, conv->fft);
85
    if (conv->ifft)
86
-       dsp_ops_fft_free(dsp, conv->ifft);
87
+       dsp_ops_fft_free(conv->dsp, conv->ifft);
88
    if (conv->fft_buffer)
89
        fft_free(conv->fft_buffer);
90
    free(conv->segments);
91
@@ -185,7 +186,7 @@
92
    int i, processed = 0;
93
 
94
    if (conv == NULL || conv->segCount == 0) {
95
-       dsp_ops_clear(dsp, output, len);
96
+       dsp_ops_clear(conv->dsp, output, len);
97
        return len;
98
    }
99
 
100
@@ -193,17 +194,17 @@
101
        const int processing = SPA_MIN(len - processed, conv->blockSize - conv->inputBufferFill);
102
        const int inputBufferPos = conv->inputBufferFill;
103
 
104
-       dsp_ops_copy(dsp, conv->inputBuffer + inputBufferPos, input + processed, processing);
105
+       dsp_ops_copy(conv->dsp, conv->inputBuffer + inputBufferPos, input + processed, processing);
106
        if (inputBufferPos == 0 && processing < conv->blockSize)
107
-           dsp_ops_clear(dsp, conv->inputBuffer + processing, conv->blockSize - processing);
108
+           dsp_ops_clear(conv->dsp, conv->inputBuffer + processing, conv->blockSize - processing);
109
 
110
-       dsp_ops_fft_run(dsp, conv->fft, 1, conv->inputBuffer, conv->segmentsconv->current);
111
+       dsp_ops_fft_run(conv->dsp, conv->fft, 1, conv->inputBuffer, conv->segmentsconv->current);
112
 
113
        if (conv->segCount > 1) {
114
            if (conv->inputBufferFill == 0) {
115
                int indexAudio = (conv->current + 1) % conv->segCount;
116
 
117
-               dsp_ops_fft_cmul(dsp, conv->fft, conv->pre_mult,
118
+               dsp_ops_fft_cmul(conv->dsp, conv->fft, conv->pre_mult,
119
                        conv->segmentsIr1,
120
                        conv->segmentsindexAudio,
121
                        conv->fftComplexSize, conv->scale);
122
@@ -211,7 +212,7 @@
123
                for (i = 2; i < conv->segCount; i++) {
124
                    indexAudio = (conv->current + i) % conv->segCount;
125
 
126
-                   dsp_ops_fft_cmuladd(dsp, conv->fft,
127
+                   dsp_ops_fft_cmuladd(conv->dsp, conv->fft,
128
                            conv->pre_mult,
129
                            conv->pre_mult,
130
                            conv->segmentsIri,
131
@@ -219,30 +220,30 @@
132
                            conv->fftComplexSize, conv->scale);
133
                }
134
            }
135
-           dsp_ops_fft_cmuladd(dsp, conv->fft,
136
+           dsp_ops_fft_cmuladd(conv->dsp, conv->fft,
137
                    conv->conv,
138
                    conv->pre_mult,
139
                    conv->segmentsconv->current,
140
                    conv->segmentsIr0,
141
                    conv->fftComplexSize, conv->scale);
142
        } else {
143
-           dsp_ops_fft_cmul(dsp, conv->fft,
144
+           dsp_ops_fft_cmul(conv->dsp, conv->fft,
145
                    conv->conv,
146
                    conv->segmentsconv->current,
147
                    conv->segmentsIr0,
148
                    conv->fftComplexSize, conv->scale);
149
        }
150
 
151
-       dsp_ops_fft_run(dsp, conv->ifft, -1, conv->conv, conv->fft_buffer);
152
+       dsp_ops_fft_run(conv->dsp, conv->ifft, -1, conv->conv, conv->fft_buffer);
153
 
154
-       dsp_ops_sum(dsp, output + processed, conv->fft_buffer + inputBufferPos,
155
+       dsp_ops_sum(conv->dsp, output + processed, conv->fft_buffer + inputBufferPos,
156
                conv->overlap + inputBufferPos, processing);
157
 
158
        conv->inputBufferFill += processing;
159
        if (conv->inputBufferFill == conv->blockSize) {
160
            conv->inputBufferFill = 0;
161
 
162
-           dsp_ops_copy(dsp, conv->overlap, conv->fft_buffer + conv->blockSize, conv->blockSize);
163
+           dsp_ops_copy(conv->dsp, conv->overlap, conv->fft_buffer + conv->blockSize, conv->blockSize);
164
 
165
            conv->current = (conv->current > 0) ? (conv->current - 1) : (conv->segCount - 1);
166
        }
167
@@ -254,6 +255,7 @@
168
 
169
 struct convolver
170
 {
171
+   struct dsp_ops *dsp;
172
    int headBlockSize;
173
    int tailBlockSize;
174
    struct convolver1 *headConvolver;
175
@@ -274,13 +276,13 @@
176
        convolver1_reset(conv->headConvolver);
177
    if (conv->tailConvolver0) {
178
        convolver1_reset(conv->tailConvolver0);
179
-       dsp_ops_clear(dsp, conv->tailOutput0, conv->tailBlockSize);
180
-       dsp_ops_clear(dsp, conv->tailPrecalculated0, conv->tailBlockSize);
181
+       dsp_ops_clear(conv->dsp, conv->tailOutput0, conv->tailBlockSize);
182
+       dsp_ops_clear(conv->dsp, conv->tailPrecalculated0, conv->tailBlockSize);
183
    }
184
    if (conv->tailConvolver) {
185
        convolver1_reset(conv->tailConvolver);
186
-       dsp_ops_clear(dsp, conv->tailOutput, conv->tailBlockSize);
187
-       dsp_ops_clear(dsp, conv->tailPrecalculated, conv->tailBlockSize);
188
+       dsp_ops_clear(conv->dsp, conv->tailOutput, conv->tailBlockSize);
189
+       dsp_ops_clear(conv->dsp, conv->tailPrecalculated, conv->tailBlockSize);
190
    }
191
    conv->tailInputFill = 0;
192
    conv->precalculatedPos = 0;
193
@@ -291,8 +293,6 @@
194
    struct convolver *conv;
195
    int head_ir_len;
196
 
197
-   dsp = dsp_ops;
198
-
199
    if (head_block == 0 || tail_block == 0)
200
        return NULL;
201
_service:download_url:pipewire-1.2.6.tar.bz2/src/modules/module-filter-chain/ladspa_plugin.c -> _service:download_url:pipewire-1.2.7.tar.bz2/src/modules/module-filter-chain/ladspa_plugin.c Changed
19
 
1
@@ -29,7 +29,7 @@
2
    const LADSPA_Descriptor *d;
3
 };
4
 
5
-static void *ladspa_instantiate(const struct fc_descriptor *desc,
6
+static void *ladspa_instantiate(const struct fc_plugin *plugin, const struct fc_descriptor *desc,
7
                         unsigned long SampleRate, int index, const char *config)
8
 {
9
    struct descriptor *d = (struct descriptor *)desc;
10
@@ -210,7 +210,7 @@
11
 }
12
 
13
 struct fc_plugin *load_ladspa_plugin(const struct spa_support *support, uint32_t n_support,
14
-       struct dsp_ops *dsp, const char *plugin, const char *config)
15
+       struct dsp_ops *dsp, const char *plugin, const struct spa_dict *info)
16
 {
17
    struct fc_plugin *pl = NULL;
18
 
19
_service:download_url:pipewire-1.2.6.tar.bz2/src/modules/module-filter-chain/lv2_plugin.c -> _service:download_url:pipewire-1.2.7.tar.bz2/src/modules/module-filter-chain/lv2_plugin.c Changed
28
 
1
@@ -80,7 +80,7 @@
2
    URITable *table = (URITable*)handle;
3
 
4
    if (urid > 0 && urid <= pw_array_get_len(&table->array, char*))
5
-       return *pw_array_get_unchecked(&table->array, urid, char*);
6
+       return *pw_array_get_unchecked(&table->array, urid - 1, char*);
7
    return NULL;
8
 }
9
 
10
@@ -278,7 +278,7 @@
11
    return LV2_WORKER_SUCCESS;
12
 }
13
 
14
-static void *lv2_instantiate(const struct fc_descriptor *desc,
15
+static void *lv2_instantiate(const struct fc_plugin *plugin, const struct fc_descriptor *desc,
16
                         unsigned long SampleRate, int index, const char *config)
17
 {
18
    struct descriptor *d = (struct descriptor*)desc;
19
@@ -460,7 +460,7 @@
20
 
21
 SPA_EXPORT
22
 struct fc_plugin *pipewire__filter_chain_plugin_load(const struct spa_support *support, uint32_t n_support,
23
-       struct dsp_ops *ops, const char *plugin_uri, const char *config)
24
+       struct dsp_ops *dsp, const char *plugin_uri, const struct spa_dict *info)
25
 {
26
    struct context *c;
27
    const LilvPlugins *plugins;
28
_service:download_url:pipewire-1.2.6.tar.bz2/src/modules/module-filter-chain/plugin.h -> _service:download_url:pipewire-1.2.7.tar.bz2/src/modules/module-filter-chain/plugin.h Changed
19
 
1
@@ -51,7 +51,7 @@
2
    uint32_t n_ports;
3
    struct fc_port *ports;
4
 
5
-   void *(*instantiate) (const struct fc_descriptor *desc,
6
+   void *(*instantiate) (const struct fc_plugin *plugin, const struct fc_descriptor *desc,
7
            unsigned long SampleRate, int index, const char *config);
8
 
9
    void (*cleanup) (void *instance);
10
@@ -80,7 +80,7 @@
11
 #define FC_PLUGIN_LOAD_FUNC "pipewire__filter_chain_plugin_load"
12
 
13
 typedef struct fc_plugin *(fc_plugin_load_func)(const struct spa_support *support, uint32_t n_support,
14
-       struct dsp_ops *dsp, const char *path, const char *config);
15
+       struct dsp_ops *dsp, const char *path, const struct spa_dict *info);
16
 
17
 
18
 #endif /* PLUGIN_H */
19
_service:download_url:pipewire-1.2.6.tar.bz2/src/modules/module-filter-chain/sofa_plugin.c -> _service:download_url:pipewire-1.2.7.tar.bz2/src/modules/module-filter-chain/sofa_plugin.c Changed
132
 
1
@@ -14,13 +14,16 @@
2
 
3
 #include <mysofa.h>
4
 
5
-#define MAX_SAMPLES    8192u
6
-
7
-static struct dsp_ops *dsp_ops;
8
-static struct spa_loop *data_loop;
9
-static struct spa_loop *main_loop;
10
+struct plugin {
11
+   struct fc_plugin plugin;
12
+   struct dsp_ops *dsp_ops;
13
+   struct spa_loop *data_loop;
14
+   struct spa_loop *main_loop;
15
+   uint32_t quantum_limit;
16
+};
17
 
18
 struct spatializer_impl {
19
+   struct plugin *plugin;
20
    unsigned long rate;
21
    float *port6;
22
    int n_samples, blocksize, tailsize;
23
@@ -32,7 +35,7 @@
24
    struct convolver *r_conv3;
25
 };
26
 
27
-static void * spatializer_instantiate(const struct fc_descriptor * Descriptor,
28
+static void * spatializer_instantiate(const struct fc_plugin *plugin, const struct fc_descriptor * Descriptor,
29
        unsigned long SampleRate, int index, const char *config)
30
 {
31
    struct spatializer_impl *impl;
32
@@ -58,6 +61,7 @@
33
        errno = ENOMEM;
34
        return NULL;
35
    }
36
+   impl->plugin = (struct plugin *) plugin;
37
 
38
    while (spa_json_get_string(&it1, key, sizeof(key)) > 0) {
39
        if (spa_streq(key, "blocksize")) {
40
@@ -175,8 +179,8 @@
41
    pw_log_info("using n_samples:%u %d:%d blocksize sofa:%s", impl->n_samples,
42
        impl->blocksize, impl->tailsize, filename);
43
 
44
-   impl->tmp0 = calloc(MAX_SAMPLES, sizeof(float));
45
-   impl->tmp1 = calloc(MAX_SAMPLES, sizeof(float));
46
+   impl->tmp0 = calloc(impl->plugin->quantum_limit, sizeof(float));
47
+   impl->tmp1 = calloc(impl->plugin->quantum_limit, sizeof(float));
48
    impl->rate = SampleRate;
49
    return impl;
50
 error:
51
@@ -239,9 +243,9 @@
52
    if (impl->r_conv2)
53
        convolver_free(impl->r_conv2);
54
 
55
-   impl->l_conv2 = convolver_new(dsp_ops, impl->blocksize, impl->tailsize,
56
+   impl->l_conv2 = convolver_new(impl->plugin->dsp_ops, impl->blocksize, impl->tailsize,
57
            left_ir, impl->n_samples);
58
-   impl->r_conv2 = convolver_new(dsp_ops, impl->blocksize, impl->tailsize,
59
+   impl->r_conv2 = convolver_new(impl->plugin->dsp_ops, impl->blocksize, impl->tailsize,
60
            right_ir, impl->n_samples);
61
 
62
    free(left_ir);
63
@@ -251,7 +255,7 @@
64
        pw_log_error("reloading left or right convolver failed");
65
        return;
66
    }
67
-   spa_loop_invoke(data_loop, do_switch, 1, NULL, 0, true, impl);
68
+   spa_loop_invoke(impl->plugin->data_loop, do_switch, 1, NULL, 0, true, impl);
69
 }
70
 
71
 struct free_data {
72
@@ -275,7 +279,7 @@
73
    struct spatializer_impl *impl = Instance;
74
 
75
    if (impl->interpolate) {
76
-       uint32_t len = SPA_MIN(SampleCount, MAX_SAMPLES);
77
+       uint32_t len = SPA_MIN(SampleCount, impl->plugin->quantum_limit);
78
        struct free_data free_data;
79
        float *l = impl->tmp0, *r = impl->tmp1;
80
 
81
@@ -296,7 +300,7 @@
82
        impl->l_conv1 = impl->r_conv1 = NULL;
83
        impl->interpolate = false;
84
 
85
-       spa_loop_invoke(main_loop, do_free, 1, &free_data, sizeof(free_data), false, impl);
86
+       spa_loop_invoke(impl->plugin->main_loop, do_free, 1, &free_data, sizeof(free_data), false, impl);
87
    } else if (impl->l_conv0 && impl->r_conv0) {
88
        convolver_run(impl->l_conv0, impl->port2, impl->port0, SampleCount);
89
        convolver_run(impl->r_conv0, impl->port2, impl->port1, SampleCount);
90
@@ -413,19 +417,33 @@
91
    return NULL;
92
 }
93
 
94
-static struct fc_plugin builtin_plugin = {
95
-   .make_desc = sofa_make_desc
96
-};
97
+static void sofa_plugin_unload(struct fc_plugin *p)
98
+{
99
+   free(p);
100
+}
101
 
102
 SPA_EXPORT
103
 struct fc_plugin *pipewire__filter_chain_plugin_load(const struct spa_support *support, uint32_t n_support,
104
-       struct dsp_ops *dsp, const char *plugin, const char *config)
105
+       struct dsp_ops *dsp, const char *plugin, const struct spa_dict *info)
106
 {
107
-   dsp_ops = dsp;
108
+   struct plugin *impl = calloc(1, sizeof (struct plugin));
109
+
110
+   impl->plugin.make_desc = sofa_make_desc;
111
+   impl->plugin.unload = sofa_plugin_unload;
112
+
113
+   impl->quantum_limit = 8192u;
114
+
115
+   for (uint32_t i = 0; info && i < info->n_items; i++) {
116
+       const char *k = info->itemsi.key;
117
+       const char *s = info->itemsi.value;
118
+       if (spa_streq(k, "clock.quantum-limit"))
119
+           spa_atou32(s, &impl->quantum_limit, 0);
120
+   }
121
+   impl->dsp_ops = dsp;
122
    pffft_select_cpu(dsp->cpu_flags);
123
 
124
-   data_loop = spa_support_find(support, n_support, SPA_TYPE_INTERFACE_DataLoop);
125
-   main_loop = spa_support_find(support, n_support, SPA_TYPE_INTERFACE_Loop);
126
+   impl->data_loop = spa_support_find(support, n_support, SPA_TYPE_INTERFACE_DataLoop);
127
+   impl->main_loop = spa_support_find(support, n_support, SPA_TYPE_INTERFACE_Loop);
128
 
129
-   return &builtin_plugin;
130
+   return (struct fc_plugin *) impl;
131
 }
132
_service:download_url:pipewire-1.2.6.tar.bz2/src/modules/module-jack-tunnel.c -> _service:download_url:pipewire-1.2.7.tar.bz2/src/modules/module-jack-tunnel.c Changed
108
 
1
@@ -19,6 +19,7 @@
2
 #include <spa/utils/result.h>
3
 #include <spa/utils/string.h>
4
 #include <spa/utils/json.h>
5
+#include <spa/utils/ratelimit.h>
6
 #include <spa/debug/types.h>
7
 #include <spa/pod/builder.h>
8
 #include <spa/param/audio/format-utils.h>
9
@@ -184,6 +185,8 @@
10
    struct spa_hook core_proxy_listener;
11
    struct spa_hook core_listener;
12
 
13
+   struct spa_ratelimit rate_limit;
14
+
15
    struct spa_io_position *position;
16
 
17
    struct stream source;
18
@@ -192,7 +195,7 @@
19
    uint32_t samplerate;
20
 
21
    jack_client_t *client;
22
-   jack_nframes_t frame_time;
23
+   jack_nframes_t current_frames;
24
 
25
    uint32_t pw_xrun;
26
    uint32_t jack_xrun;
27
@@ -355,7 +358,7 @@
28
        else
29
            do_volume(dst, src, &s->volume, i, n_samples);
30
    }
31
-   pw_log_trace_fp("done %u %u", impl->frame_time, n_samples);
32
+   pw_log_trace_fp("done %u %u", impl->current_frames, n_samples);
33
    if (impl->mode & MODE_SINK) {
34
        impl->done = true;
35
        jack.cycle_signal(impl->client, 0);
36
@@ -369,7 +372,7 @@
37
    uint32_t i, n_samples = position->clock.duration;
38
 
39
    if (impl->mode == MODE_SOURCE && !impl->triggered) {
40
-       pw_log_trace_fp("done %u", impl->frame_time);
41
+       pw_log_trace_fp("done %u", impl->current_frames);
42
        impl->done = true;
43
        jack.cycle_signal(impl->client, 0);
44
        return;
45
@@ -687,35 +690,40 @@
46
    jack_nframes_t nframes;
47
 
48
    while (true) {
49
+       jack_nframes_t current_frames;
50
+       jack_time_t current_usecs;
51
+       jack_time_t next_usecs;
52
+       float period_usecs;
53
+
54
        nframes = jack.cycle_wait (impl->client);
55
 
56
+       jack.get_cycle_times(impl->client,
57
+               &current_frames, &current_usecs,
58
+               &next_usecs, &period_usecs);
59
+
60
+       impl->current_frames = current_frames;
61
+
62
        source_running = impl->source.running;
63
        sink_running = impl->sink.running;
64
 
65
-       impl->frame_time = jack.frame_time(impl->client);
66
-
67
        pw_log_trace_fp("process %d %u %u %p %d", nframes, source_running,
68
-               sink_running, impl->position, impl->frame_time);
69
+               sink_running, impl->position, current_frames);
70
 
71
        if (impl->new_xrun) {
72
-           pw_log_warn("Xrun JACK:%u PipeWire:%u", impl->jack_xrun, impl->pw_xrun);
73
+           int suppressed;
74
+           if ((suppressed = spa_ratelimit_test(&impl->rate_limit, current_usecs)) >= 0) {
75
+               pw_log_warn("Xrun: current_frames:%u JACK:%u PipeWire:%u (%d suppressed)",
76
+                       current_frames, impl->jack_xrun, impl->pw_xrun, suppressed);
77
+           }
78
            impl->new_xrun = false;
79
        }
80
 
81
        if (impl->position) {
82
            struct spa_io_clock *c = &impl->position->clock;
83
-           jack_nframes_t current_frames;
84
-           jack_time_t current_usecs;
85
-           jack_time_t next_usecs;
86
-           float period_usecs;
87
            jack_position_t pos;
88
            uint64_t t1, t2, t3;
89
            int64_t d1;
90
 
91
-           jack.get_cycle_times(impl->client,
92
-                   &current_frames, &current_usecs,
93
-                   &next_usecs, &period_usecs);
94
-
95
            /* convert from JACK (likely MONOTONIC_RAW) to MONOTONIC */
96
            t1 = get_time_nsec(impl) / 1000;
97
            t2 = jack.get_time();
98
@@ -1081,6 +1089,9 @@
99
    impl->main_loop = pw_context_get_main_loop(context);
100
    impl->system = impl->main_loop->system;
101
 
102
+   impl->rate_limit.interval = 2 * SPA_USEC_PER_SEC;
103
+   impl->rate_limit.burst = 1;
104
+
105
    impl->source.impl = impl;
106
    impl->source.direction = PW_DIRECTION_OUTPUT;
107
    impl->sink.impl = impl;
108
_service:download_url:pipewire-1.2.6.tar.bz2/src/modules/module-parametric-equalizer.c -> _service:download_url:pipewire-1.2.7.tar.bz2/src/modules/module-parametric-equalizer.c Changed
60
 
1
@@ -8,6 +8,7 @@
2
 #include "config.h"
3
 
4
 #include <spa/utils/result.h>
5
+#include <spa/utils/json.h>
6
 #include <spa/param/audio/raw.h>
7
 
8
 #include <pipewire/impl.h>
9
@@ -147,7 +148,8 @@
10
    .destroy = filter_chain_module_destroy,
11
 };
12
 
13
-void init_eq_node(FILE *f, const char *node_desc) {
14
+void init_eq_node(FILE *f, const char *node_desc)
15
+{
16
    fprintf(f, "{\n");
17
    fprintf(f, "node.description = \"%s\"\n", node_desc);
18
    fprintf(f, "media.name = \"%s\"\n", node_desc);
19
@@ -155,7 +157,10 @@
20
    fprintf(f, "nodes = \n");
21
 }
22
 
23
-void add_eq_node(FILE *f, struct eq_node_param *param, uint32_t eq_band_idx) {
24
+void add_eq_node(FILE *f, struct eq_node_param *param, uint32_t eq_band_idx)
25
+{
26
+   char str164, str264;
27
+
28
    fprintf(f, "{\n");
29
    fprintf(f, "type = builtin\n");
30
    fprintf(f, "name = eq_band_%d\n", eq_band_idx);
31
@@ -170,12 +175,15 @@
32
        fprintf(f, "label = bq_peaking\n");
33
    }
34
 
35
-   fprintf(f, "control = { \"Freq\" = %d \"Q\" = %f \"Gain\" = %f }\n", param->freq, param->q_fact, param->gain);
36
+   fprintf(f, "control = { \"Freq\" = %d \"Q\" = %s \"Gain\" = %s }\n", param->freq,
37
+           spa_json_format_float(str1, sizeof(str1), param->q_fact),
38
+           spa_json_format_float(str2, sizeof(str2), param->gain));
39
 
40
    fprintf(f, "}\n");
41
 }
42
 
43
-void end_eq_node(struct impl *impl, FILE *f, uint32_t number_of_nodes) {
44
+void end_eq_node(struct impl *impl, FILE *f, uint32_t number_of_nodes)
45
+{
46
    fprintf(f, "\n");
47
 
48
    fprintf(f, "links = \n");
49
@@ -266,7 +274,9 @@
50
         * Use a field width of 6 for gain and Q to account for any
51
         * possible zeros.
52
         */
53
-       if (sscanf(line, "%*s %*d: %3s %3s %*s %5d %*s %*s %6f %*s %*c %6f", eq_param.filter, eq_param.filter_type, &eq_param.freq, &eq_param.gain, &eq_param.q_fact) == 5) {
54
+       if (sscanf(line, "%*s %*d: %3s %3s %*s %5d %*s %*s %6f %*s %*c %6f",
55
+                   eq_param.filter, eq_param.filter_type, &eq_param.freq,
56
+                   &eq_param.gain, &eq_param.q_fact) == 5) {
57
            if (strcmp(eq_param.filter, "ON") == 0) {
58
                add_eq_node(memstream, &eq_param, eq_band_idx);
59
 
60
_service:download_url:pipewire-1.2.6.tar.bz2/src/modules/module-profiler.c -> _service:download_url:pipewire-1.2.7.tar.bz2/src/modules/module-profiler.c Changed
16
 
1
@@ -245,10 +245,10 @@
2
        spa_pod_builder_add_struct(&b,
3
            SPA_POD_Int(t->id),
4
            SPA_POD_String(t->name),
5
-           SPA_POD_Long(a->signal_time),
6
-           SPA_POD_Long(na->signal_time),
7
-           SPA_POD_Long(na->awake_time),
8
-           SPA_POD_Long(na->finish_time),
9
+           SPA_POD_Long(a->prev_signal_time),
10
+           SPA_POD_Long(n->async ? na->prev_signal_time : na->signal_time),
11
+           SPA_POD_Long(n->async ? na->prev_awake_time : na->awake_time),
12
+           SPA_POD_Long(n->async ? na->prev_finish_time : na->finish_time),
13
            SPA_POD_Int(na->status),
14
            SPA_POD_Fraction(&latency),
15
            SPA_POD_Int(na->xrun_count));
16
_service:download_url:pipewire-1.2.6.tar.bz2/src/modules/module-protocol-pulse/manager.c -> _service:download_url:pipewire-1.2.7.tar.bz2/src/modules/module-protocol-pulse/manager.c Changed
10
 
1
@@ -809,7 +809,7 @@
2
        value = NULL;
3
    }
4
 
5
-   pw_metadata_set_property(metadata->proxy,
6
+   pw_metadata_set_property((struct pw_metadata*)metadata->proxy,
7
            subject, key, type, value);
8
    return 0;
9
 }
10
_service:download_url:pipewire-1.2.6.tar.bz2/src/modules/module-protocol-pulse/pulse-server.c -> _service:download_url:pipewire-1.2.7.tar.bz2/src/modules/module-protocol-pulse/pulse-server.c Changed
45
 
1
@@ -2161,6 +2161,7 @@
2
    uint32_t channel;
3
    struct timeval tv, now;
4
    struct stream *stream;
5
+   uint64_t delay;
6
    int res;
7
 
8
    if ((res = message_get(m,
9
@@ -2182,9 +2183,11 @@
10
 
11
    gettimeofday(&now, NULL);
12
 
13
+   delay = SPA_CLAMP(stream->delay, 0, INT64_MAX);
14
+
15
    reply = reply_new(client, tag);
16
    message_put(reply,
17
-       TAG_USEC, stream->delay,    /* sink latency + queued samples */
18
+       TAG_USEC, delay,    /* sink latency + queued samples */
19
        TAG_USEC, 0LL,          /* always 0 */
20
        TAG_BOOLEAN, stream->playing_for > 0 &&
21
                !stream->corked,    /* playing state */
22
@@ -2210,6 +2213,7 @@
23
    uint32_t channel;
24
    struct timeval tv, now;
25
    struct stream *stream;
26
+   uint64_t delay;
27
    int res;
28
 
29
    if ((res = message_get(m,
30
@@ -2229,10 +2233,13 @@
31
 
32
 
33
    gettimeofday(&now, NULL);
34
+
35
+   delay = SPA_CLAMP(stream->delay, 0, INT64_MAX);
36
+
37
    reply = reply_new(client, tag);
38
    message_put(reply,
39
        TAG_USEC, 0LL,          /* monitor latency */
40
-       TAG_USEC, stream->delay,    /* source latency + queued */
41
+       TAG_USEC, delay,    /* source latency + queued */
42
        TAG_BOOLEAN, !stream->corked,   /* playing state */
43
        TAG_TIMEVAL, &tv,
44
        TAG_TIMEVAL, &now,
45
_service:download_url:pipewire-1.2.6.tar.bz2/src/modules/module-protocol-pulse/server.c -> _service:download_url:pipewire-1.2.7.tar.bz2/src/modules/module-protocol-pulse/server.c Changed
28
 
1
@@ -356,6 +356,7 @@
2
    int client_fd, val;
3
    struct client *client = NULL;
4
    const char *client_access = NULL;
5
+   const char *error_reason = NULL;
6
    pid_t pid;
7
 
8
    length = sizeof(name);
9
@@ -374,6 +375,7 @@
10
 
11
    if (server->n_clients >= server->max_clients) {
12
        close(client_fd);
13
+       error_reason = "too many client application connections";
14
        errno = ECONNREFUSED;
15
        goto error;
16
    }
17
@@ -487,7 +489,9 @@
18
    return;
19
 
20
 error:
21
-   pw_log_error("server %p: failed to create client: %m", server);
22
+   pw_log_error("server %p: %s: %m", server,
23
+           error_reason ? error_reason : "failed to create client");
24
+
25
    if (client)
26
        client_free(client);
27
 }
28
_service:download_url:pipewire-1.2.6.tar.bz2/src/modules/module-rtp-source.c -> _service:download_url:pipewire-1.2.7.tar.bz2/src/modules/module-rtp-source.c Changed
63
 
1
@@ -162,6 +162,9 @@
2
    socklen_t src_len;
3
    struct spa_source *source;
4
 
5
+   uint8_t *buffer;
6
+   size_t buffer_size;
7
+
8
    unsigned receiving:1;
9
    unsigned last_receiving:1;
10
 };
11
@@ -171,17 +174,16 @@
12
 {
13
    struct impl *impl = data;
14
    ssize_t len;
15
-   uint8_t buffer2048;
16
 
17
    if (mask & SPA_IO_IN) {
18
-       if ((len = recv(fd, buffer, sizeof(buffer), 0)) < 0)
19
+       if ((len = recv(fd, impl->buffer, impl->buffer_size, 0)) < 0)
20
            goto receive_error;
21
 
22
        if (len < 12)
23
            goto short_packet;
24
 
25
        if (SPA_LIKELY(impl->stream)) {
26
-           if (rtp_stream_receive_packet(impl->stream, buffer, len) < 0)
27
+           if (rtp_stream_receive_packet(impl->stream, impl->buffer, len) < 0)
28
                goto receive_error;
29
        }
30
 
31
@@ -193,7 +195,7 @@
32
    pw_log_warn("recv error: %m");
33
    return;
34
 short_packet:
35
-   pw_log_warn("short packet received");
36
+   pw_log_warn("short packet of len %zd received", len);
37
    return;
38
 }
39
 
40
@@ -477,6 +479,7 @@
41
    pw_properties_free(impl->stream_props);
42
    pw_properties_free(impl->props);
43
 
44
+   free(impl->buffer);
45
    free(impl->ifname);
46
    free(impl);
47
 }
48
@@ -663,6 +666,14 @@
49
        goto out;
50
    }
51
 
52
+   impl->buffer_size = rtp_stream_get_mtu(impl->stream);
53
+   impl->buffer = calloc(1, impl->buffer_size);
54
+   if (impl->buffer == NULL) {
55
+       res = -errno;
56
+       pw_log_error("can't create packet buffer of size %zd: %m", impl->buffer_size);
57
+       goto out;
58
+   }
59
+
60
    pw_impl_module_add_listener(module, &impl->module_listener, &module_events, impl);
61
 
62
    pw_impl_module_update_properties(module, &SPA_DICT_INIT_ARRAY(module_info));
63
_service:download_url:pipewire-1.2.6.tar.bz2/src/modules/module-rtp/midi.c -> _service:download_url:pipewire-1.2.7.tar.bz2/src/modules/module-rtp/midi.c Changed
27
 
1
@@ -354,7 +354,7 @@
2
    struct rtp_header header;
3
    struct rtp_midi_header midi_header;
4
    struct iovec iov3;
5
-   uint32_t len, prev_offset, base;
6
+   uint32_t len, prev_offset, base, max_size;
7
 
8
    spa_zero(header);
9
    header.v = 2;
10
@@ -371,6 +371,7 @@
11
    iov2.iov_len = 0;
12
 
13
    prev_offset = len = base = 0;
14
+   max_size = impl->payload_size - sizeof(midi_header);
15
 
16
    SPA_POD_SEQUENCE_FOREACH(sequence, c) {
17
        void *ev;
18
@@ -384,7 +385,7 @@
19
 
20
        offset = c->offset * impl->rate / rate;
21
 
22
-       if (len > 0 && (len + size > impl->mtu ||
23
+       if (len > 0 && (len + size > max_size ||
24
            offset - base > impl->psamples)) {
25
            /* flush packet when we have one and when it's either
26
             * too large or has too much data. */
27
_service:download_url:pipewire-1.2.6.tar.bz2/src/modules/module-rtp/stream.c -> _service:download_url:pipewire-1.2.7.tar.bz2/src/modules/module-rtp/stream.c Changed
47
 
1
@@ -69,6 +69,7 @@
2
    uint32_t ts_offset;
3
    uint32_t psamples;
4
    uint32_t mtu;
5
+   uint32_t payload_size;
6
 
7
    struct spa_ringbuffer ring;
8
    uint8_t bufferBUFFER_SIZE;
9
@@ -439,6 +440,11 @@
10
 
11
    impl->payload = pw_properties_get_uint32(props, "rtp.payload", impl->payload);
12
    impl->mtu = pw_properties_get_uint32(props, "net.mtu", DEFAULT_MTU);
13
+   if (impl->mtu <= PACKET_HEADER_SIZE) {
14
+       pw_log_error("invalid MTU %d, using %d", impl->mtu, DEFAULT_MTU);
15
+       impl->mtu = DEFAULT_MTU;
16
+   }
17
+   impl->payload_size = impl->mtu - PACKET_HEADER_SIZE;
18
 
19
    impl->seq = pw_rand32();
20
 
21
@@ -476,7 +482,7 @@
22
            pw_log_warn("rtp.ptime doesn't match rtp.framecount. Choosing rtp.ptime");
23
        }
24
    } else {
25
-       impl->psamples = impl->mtu / impl->stride;
26
+       impl->psamples = impl->payload_size / impl->stride;
27
        impl->psamples = SPA_CLAMP(impl->psamples, min_samples, max_samples);
28
        if (direction == PW_DIRECTION_INPUT) {
29
            pw_properties_set(props, "rtp.ptime",
30
@@ -651,10 +657,15 @@
31
 uint16_t rtp_stream_get_seq(struct rtp_stream *s)
32
 {
33
    struct impl *impl = (struct impl*)s;
34
-
35
    return impl->seq;
36
 }
37
 
38
+size_t rtp_stream_get_mtu(struct rtp_stream *s)
39
+{
40
+   struct impl *impl = (struct impl*)s;
41
+   return impl->mtu;
42
+}
43
+
44
 void rtp_stream_set_first(struct rtp_stream *s)
45
 {
46
    struct impl *impl = (struct impl*)s;
47
_service:download_url:pipewire-1.2.6.tar.bz2/src/modules/module-rtp/stream.h -> _service:download_url:pipewire-1.2.7.tar.bz2/src/modules/module-rtp/stream.h Changed
20
 
1
@@ -19,6 +19,9 @@
2
 #define ERROR_MSEC     2.0f
3
 #define DEFAULT_SESS_LATENCY   100.0f
4
 
5
+/* 28 bytes IP/UDP, 12 bytes RTP header */
6
+#define PACKET_HEADER_SIZE (12+28)
7
+
8
 #define DEFAULT_MTU        1280
9
 #define DEFAULT_MIN_PTIME  2.0f
10
 #define DEFAULT_MAX_PTIME  20.0f
11
@@ -52,6 +55,8 @@
12
 
13
 uint16_t rtp_stream_get_seq(struct rtp_stream *s);
14
 
15
+size_t rtp_stream_get_mtu(struct rtp_stream *s);
16
+
17
 void rtp_stream_set_first(struct rtp_stream *s);
18
 
19
 void rtp_stream_set_error(struct rtp_stream *s, int res, const char *error);
20
_service:download_url:pipewire-1.2.6.tar.bz2/src/pipewire/context.c -> _service:download_url:pipewire-1.2.7.tar.bz2/src/pipewire/context.c Changed
29
 
1
@@ -1637,6 +1637,7 @@
2
        uint64_t quantum_stamp = 0, rate_stamp = 0;
3
        bool force_rate, force_quantum, restore_rate = false, restore_quantum = false;
4
        bool do_reconfigure = false, need_resume, was_target_pending;
5
+       bool have_request = false;
6
        const uint32_t *node_rates;
7
        uint32_t node_n_rates, node_def_rate;
8
        uint32_t node_max_quantum, node_min_quantum, node_def_quantum, node_rate_quantum;
9
@@ -1705,6 +1706,9 @@
10
                context, s, running, s->runnable, rate.num, rate.denom,
11
                latency.num, latency.denom, s->name);
12
 
13
+           if (running && s != n && s->supports_request > 0)
14
+               have_request = true;
15
+
16
            s->moved = false;
17
        }
18
 
19
@@ -1861,6 +1865,9 @@
20
            n->target_rate = n->rt.position->clock.target_rate;
21
        }
22
 
23
+       SPA_FLAG_UPDATE(n->rt.position->clock.flags,
24
+               SPA_IO_CLOCK_FLAG_LAZY, have_request && n->supports_lazy > 0);
25
+
26
        pw_log_debug("%p: driver %p running:%d runnable:%d quantum:%u rate:%u (%"PRIu64"/%u)'%s'",
27
                context, n, running, n->runnable, target_quantum, target_rate,
28
                n->rt.position->clock.target_duration,
29
_service:download_url:pipewire-1.2.6.tar.bz2/src/pipewire/filter.c -> _service:download_url:pipewire-1.2.7.tar.bz2/src/pipewire/filter.c Changed
14
 
1
@@ -2064,6 +2064,12 @@
2
    return filter->node->driving;
3
 }
4
 
5
+SPA_EXPORT
6
+bool pw_filter_is_lazy(struct pw_filter *filter)
7
+{
8
+   return filter->node->lazy;
9
+}
10
+
11
 static int
12
 do_trigger_process(struct spa_loop *loop,
13
                  bool async, uint32_t seq, const void *data, size_t size, void *user_data)
14
_service:download_url:pipewire-1.2.6.tar.bz2/src/pipewire/filter.h -> _service:download_url:pipewire-1.2.7.tar.bz2/src/pipewire/filter.h Changed
12
 
1
@@ -249,6 +249,10 @@
2
  * available (output) or needed (input). Since 0.3.66 */
3
 bool pw_filter_is_driving(struct pw_filter *filter);
4
 
5
+/** Check if the graph is using lazy scheduling.
6
+ * Since 1.2.7 */
7
+bool pw_filter_is_lazy(struct pw_filter *filter);
8
+
9
 /** Trigger a push/pull on the filter. One iteration of the graph will
10
  * be scheduled and process() will be called. Since 0.3.66 */
11
 int pw_filter_trigger_process(struct pw_filter *filter);
12
_service:download_url:pipewire-1.2.6.tar.bz2/src/pipewire/impl-node.c -> _service:download_url:pipewire-1.2.7.tar.bz2/src/pipewire/impl-node.c Changed
48
 
1
@@ -324,6 +324,9 @@
2
    pw_log_debug("%p: start node driving:%d driver:%d prepared:%d", this,
3
            this->driving, this->driver, this->rt.prepared);
4
 
5
+   this->lazy = this->rt.position && SPA_FLAG_IS_SET(this->rt.position->clock.flags,
6
+           SPA_IO_CLOCK_FLAG_LAZY);
7
+
8
    if (!(this->driving && this->driver)) {
9
        impl->pending_play = true;
10
        res = spa_node_send_command(this->node,
11
@@ -758,6 +761,14 @@
12
    spa_list_for_each_safe(n, t, &context->driver_list, driver_link) {
13
        if (n->priority_driver < node->priority_driver)
14
            break;
15
+       if (n->priority_driver == 0 && node->priority_driver == 0) {
16
+           /* no priority is set, we prefer the driver that does
17
+            * lazy scheduling. */
18
+           if (n->supports_request > 0 && node->supports_lazy > 0) {
19
+               if (n->supports_request <= node->supports_lazy)
20
+                   break;
21
+           }
22
+       }
23
    }
24
    spa_list_append(&n->driver_link, &node->driver_link);
25
    pw_context_emit_driver_added(context, node);
26
@@ -1122,6 +1133,8 @@
27
            }
28
        }
29
    }
30
+   node->supports_lazy = pw_properties_get_uint32(node->properties, PW_KEY_NODE_SUPPORTS_LAZY, 0);
31
+   node->supports_request = pw_properties_get_uint32(node->properties, PW_KEY_NODE_SUPPORTS_REQUEST, 0);
32
 
33
    if ((str = pw_properties_get(node->properties, PW_KEY_NODE_NAME)) &&
34
        (node->name == NULL || !spa_streq(node->name, str))) {
35
@@ -2149,9 +2162,11 @@
36
        } else {
37
            all_ready &= ta->pending_sync == false;
38
        }
39
+       ta->prev_signal_time = ta->signal_time;
40
+       ta->prev_awake_time = ta->awake_time;
41
+       ta->prev_finish_time = ta->finish_time;
42
    }
43
 
44
-   a->prev_signal_time = a->signal_time;
45
    node->driver_start = nsec;
46
 
47
    a->sync_timeout = SPA_MIN(min_timeout, DEFAULT_SYNC_TIMEOUT);
48
_service:download_url:pipewire-1.2.6.tar.bz2/src/pipewire/keys.h -> _service:download_url:pipewire-1.2.7.tar.bz2/src/pipewire/keys.h Changed
17
 
1
@@ -190,6 +190,15 @@
2
 #define PW_KEY_NODE_DRIVER     "node.driver"       /**< node can drive the graph. When the node is
3
                                  *  selected as the driver, it needs to start
4
                                  *  the graph periodically. */
5
+#define PW_KEY_NODE_SUPPORTS_LAZY  "node.supports-lazy"    /**< the node can be a lazy driver. It will listen
6
+                                 *  to RequestProcess commands and take them into
7
+                                 *  account when deciding to start the graph.
8
+                                 *  A value of 0 disables support, a value of > 0
9
+                                 *  enables with increasing preference. */
10
+#define PW_KEY_NODE_SUPPORTS_REQUEST   "node.supports-request" /**< The node supports emiting RequestProcess events
11
+                                 *  when it wants the graph to be scheduled.
12
+                                 *  A value of 0 disables support, a value of > 0
13
+                                 *  enables with increasing preference. */
14
 #define PW_KEY_NODE_DRIVER_ID      "node.driver-id"    /**< the node id of the node assigned as driver
15
                                  *   for this node */
16
 #define PW_KEY_NODE_ASYNC      "node.async"        /**< the node wants async scheduling */
17
_service:download_url:pipewire-1.2.6.tar.bz2/src/pipewire/private.h -> _service:download_url:pipewire-1.2.7.tar.bz2/src/pipewire/private.h Changed
31
 
1
@@ -608,7 +608,10 @@
2
    uint32_t segment_owner16;           /* id of owners for each segment info struct.
3
                             * nodes that want to update segment info need to
4
                             * CAS their node id in this array. */
5
-   uint32_t padding11;             /* must be 0 */
6
+   uint64_t prev_awake_time;
7
+   uint64_t prev_finish_time;
8
+   uint32_t padding7;              /* must be 0 */
9
+
10
    uint32_t client_version;            /* verions of client, see above */
11
    uint32_t server_version;            /* verions of server, see above */
12
 
13
@@ -740,6 +743,9 @@
14
 
15
    char *name;             /** for debug */
16
 
17
+   uint32_t supports_lazy;     /**< lazy driver preference */
18
+   uint32_t supports_request;  /**< request follower preference */
19
+
20
    uint32_t priority_driver;   /** priority for being driver */
21
    char **groups;          /** groups to schedule this node in */
22
    char **link_groups;     /** groups this node is linked to */
23
@@ -779,6 +785,7 @@
24
    unsigned int sync:1;        /**< the sync-groups are active */
25
    unsigned int transport:1;   /**< the transport is active */
26
    unsigned int async:1;       /**< async processing, one cycle latency */
27
+   unsigned int lazy:1;        /**< the graph is lazy scheduling */
28
 
29
    uint32_t port_user_data_size;   /**< extra size for port user data */
30
 
31
_service:download_url:pipewire-1.2.6.tar.bz2/src/pipewire/proxy.c -> _service:download_url:pipewire-1.2.7.tar.bz2/src/pipewire/proxy.c Changed
11
 
1
@@ -191,6 +191,9 @@
2
        if (proxy->core)
3
            pw_map_remove(&proxy->core->objects, proxy->id);
4
        proxy->in_map = false;
5
+
6
+       /* Make sure any future method calls fail */
7
+       proxy->id = SPA_ID_INVALID;
8
    }
9
 }
10
 
11
_service:download_url:pipewire-1.2.6.tar.bz2/src/pipewire/stream.c -> _service:download_url:pipewire-1.2.7.tar.bz2/src/pipewire/stream.c Changed
23
 
1
@@ -1057,6 +1057,8 @@
2
        if ((b = get_buffer(stream, io->buffer_id)) != NULL) {
3
            pw_log_trace_fp("%p: recycle buffer %d", stream, b->id);
4
            queue_push(impl, &impl->dequeued, b);
5
+           if (impl->early_process)
6
+               ask_more = true;
7
        }
8
 
9
        /* pop new buffer */
10
@@ -2523,6 +2525,12 @@
11
    return stream->node->driving;
12
 }
13
 
14
+SPA_EXPORT
15
+bool pw_stream_is_lazy(struct pw_stream *stream)
16
+{
17
+   return stream->node->lazy;
18
+}
19
+
20
 static int
21
 do_trigger_driver(struct spa_loop *loop,
22
                  bool async, uint32_t seq, const void *data, size_t size, void *user_data)
23
_service:download_url:pipewire-1.2.6.tar.bz2/src/pipewire/stream.h -> _service:download_url:pipewire-1.2.7.tar.bz2/src/pipewire/stream.h Changed
54
 
1
@@ -569,16 +569,33 @@
2
  * available (output) or needed (input). Since 0.3.34 */
3
 bool pw_stream_is_driving(struct pw_stream *stream);
4
 
5
+/** Check if the graph is using lazy scheduling. If the stream is
6
+ * driving according to \ref pw_stream_is_driving(), then it should
7
+ * consider taking into account the RequestProcess commands when
8
+ * driving the graph.
9
+ *
10
+ * If the stream is not driving, it should send out RequestProcess
11
+ * events with \ref pw_stream_emit_event() or indirectly with
12
+ * \ref pw_stream_trigger_process() to suggest a new graph cycle
13
+ * to the driver.
14
+ *
15
+ * It is not a requirement that all RequestProcess events/commands
16
+ * need to start a graph cycle.
17
+ * Since 1.2.7 */
18
+bool pw_stream_is_lazy(struct pw_stream *stream);
19
+
20
 /** Trigger a push/pull on the stream. One iteration of the graph will
21
- * be scheduled. If it successfully finishes, process() will be called.
22
- * It is possible for the graph iteration to not finish, so
23
+ * be scheduled when the stream is driving according to
24
+ * \ref pw_stream_is_driving(). If it successfully finishes, process()
25
+ * will be called and the trigger_done event will be emitted. It is
26
+ * possible for the graph iteration to not finish, so
27
  * pw_stream_trigger_process() needs to be called again even if process()
28
- * is not called.
29
+ * and trigger_done is not called.
30
  *
31
  * If there is a deadline after which the stream will have xrun,
32
  * pw_stream_trigger_process() should be called then, whether or not
33
- * process() has been called. Sound hardware will xrun if there is
34
- * any delay in audio processing, so the ALSA plugin triggers the
35
+ * process()/trigger_done has been called. Sound hardware will xrun if
36
+ * there is any delay in audio processing, so the ALSA plugin triggers the
37
  * graph every quantum to ensure audio keeps flowing. Drivers that
38
  * do not have a deadline, such as the freewheel driver, should
39
  * use a timeout to ensure that forward progress keeps being made.
40
@@ -586,6 +603,13 @@
41
  * the graph is taking 3x longer than normal, it is likely that it
42
  * is hung and should be retriggered.
43
  *
44
+ * Streams that are not drivers according to \ref pw_stream_is_driving()
45
+ * can also call this method. The result is that a RequestProcess event
46
+ * is sent to the driver. If the graph is lazy scheduling according to
47
+ * \ref pw_stream_is_lazy(), this might result in a graph cycle by the
48
+ * driver. If the graph is not lazy scheduling and the stream is not a
49
+ * driver, this method will have no effect.
50
+ *
51
  * Since 0.3.34 */
52
 int pw_stream_trigger_process(struct pw_stream *stream);
53
 
54
_service:download_url:pipewire-1.2.6.tar.bz2/src/tools/pw-dot.c -> _service:download_url:pipewire-1.2.7.tar.bz2/src/tools/pw-dot.c Changed
14
 
1
@@ -376,10 +376,10 @@
2
    dot_data_add_string(dd, "\\loutput_node_id: ");
3
    dot_data_add_uint32(dd, info->output_node_id);
4
    dot_data_add_string(dd, "\\linput_node_id: ");
5
-   dot_data_add_uint32(dd, info->output_node_id);
6
+   dot_data_add_uint32(dd, info->input_node_id);
7
    dot_data_add_string(dd, "\\loutput_port_id: ");
8
    dot_data_add_uint32(dd, info->output_port_id);
9
-   dot_data_add_string(dd, "\\linput_node_id: ");
10
+   dot_data_add_string(dd, "\\linput_port_id: ");
11
    dot_data_add_uint32(dd, info->input_port_id);
12
    dot_data_add_string(dd, "\\lstate: ");
13
    dot_data_add_string_escaped(dd, pw_link_state_as_string(info->state));
14
_service:download_url:pipewire-1.2.6.tar.bz2/src/tools/pw-dump.c -> _service:download_url:pipewire-1.2.7.tar.bz2/src/tools/pw-dump.c Changed
10
 
1
@@ -1396,7 +1396,7 @@
2
    if ((o = find_object(d, id)) == NULL)
3
        return;
4
 
5
-   if (!d->pattern || object_matches(o, d->pattern)) {
6
+   if (d->monitor && (!d->pattern || object_matches(o, d->pattern))) {
7
        d->state = STATE_FIRST;
8
        if (d->state == STATE_FIRST)
9
            put_begin(d, NULL, "", 0);
10