Changes of Revision 9

pipewire-aptx.changes Changed
x
 
1
@@ -1,4 +1,9 @@
2
 -------------------------------------------------------------------
3
+Tue Jun 21 11:57:28 UTC 2022 - Bjørn Lie <zaitor@opensuse.org>
4
+
5
+- Update to version 0.3.52
6
+
7
+-------------------------------------------------------------------
8
 Tue May 10 14:06:03 UTC 2022 - Bjørn Lie <zaitor@opensuse.org>
9
 
10
 - Update to version 0.3.51
11
pipewire-aptx.spec Changed
10
 
1
@@ -7,7 +7,7 @@
2
 %define soversion 0_2
3
 
4
 Name:           pipewire-aptx
5
-Version:        0.3.51
6
+Version:        0.3.52
7
 Release:        0
8
 Summary:        PipeWire Bluetooth aptX codec plugin
9
 License:        MIT
10
pipewire-0.3.51.tar.gz/.gitlab-ci.yml -> pipewire-0.3.52.tar.gz/.gitlab-ci.yml Changed
13
 
1
@@ -268,9 +268,9 @@
2
   extends:
3
     - .build_on_fedora
4
   variables:
5
-    # Fedora doesn't have libfreeaptx or roc
6
+    # Fedora doesn't have libfreeaptx, lc3plus, or roc
7
     # libcamera has no stable API, so let's not chase that target
8
-    MESON_OPTIONS: "-Dauto_features=enabled -Dbluez5-codec-aptx=disabled -Droc=disabled -Dlibcamera=disabled"
9
+    MESON_OPTIONS: "-Dauto_features=enabled -Dbluez5-codec-aptx=disabled -Dbluez5-codec-lc3plus=disabled -Droc=disabled -Dlibcamera=disabled"
10
   parallel:
11
     matrix:
12
       - CC: gcc, clang
13
pipewire-0.3.51.tar.gz/INSTALL.md -> pipewire-0.3.52.tar.gz/INSTALL.md Changed
15
 
1
@@ -217,3 +217,13 @@
2
 
3
 You can also start additional PulseAudio servers listening on other
4
 sockets with the -a option. See `pipewire-pulse -h` for more info.
5
+
6
+
7
+## Uninstalling
8
+
9
+To uninstall, in the `builddir` directory run:
10
+
11
+```
12
+sudo ninja uninstall
13
+```
14
+
15
pipewire-0.3.51.tar.gz/NEWS -> pipewire-0.3.52.tar.gz/NEWS Changed
132
 
1
@@ -1,3 +1,120 @@
2
+# PipeWire 0.3.52 (2022-06-09)
3
+
4
+This is a bugfix release that is API and ABI compatible with previous
5
+0.3.x releases.
6
+
7
+## Highlights
8
+  - Add 44.1KHz to allowed samplerates. The server can now switch by
9
+    default between 48KHz and 44.1KHz.
10
+  - Streams now allocate less resources.
11
+  - Fix some bugs that could make the server crash.
12
+  - Bluetooth now supports the LC3plus vendor codec.
13
+  - Many bugfixes and improvements.
14
+
15
+
16
+## PipeWire
17
+  - Add 44.1KHz to allowed samplerates.
18
+  - Avoid setting the locale.
19
+  - Avoid use-after-free when destroying a node from spa-node-factory.
20
+  - Avoid using reallocarray when not available.
21
+  - Set port alias is not otherwise set.
22
+
23
+## Modules
24
+  - Improve filter-chain parsing and error reporting. Handle empty
25
+    nodes. (#1950)
26
+  - Handle destroy of globals and factory in most modules. (#565)
27
+  - Add refcounts to client and resources to handle destroy of the
28
+    protocol. (#565)
29
+  - Handle global node.name in filter-chain and loopback again, use
30
+    it to construct unique stream names.
31
+  - Avoid a wrapped pw-node in the adapter. This reduces resources
32
+    allocated for streams.
33
+  - Fix a crash when module-x11-bell was unloaded. (#2392)
34
+  - Add a new module-pipe-tunnel that can write/read data from a
35
+    UNIX pipe.
36
+
37
+## Tools
38
+  - Fix DSD playback again in pw-cat.
39
+  - Add -n option to pw-loopback to set node names.
40
+  - Add -P option to pw-cat to pass properties to the stream.
41
+  - Support stdin/stdout in pw-cat. (#2387)
42
+  - pw-dump now also dumps object removal when monitoring. (#2426)
43
+
44
+## SPA
45
+  - Avoid duplicate param results in pw-dump for ports.
46
+  - Avoid endless loops in audioconvert for badly behaving client.
47
+    (#2359)
48
+  - Scale max-error in alsa based on quantum and avoid logging a warning
49
+    when starting.
50
+  - Improve debug of failed format conversion. (#2383)
51
+  - Handle offset in the audio dsp mixer inputs and clamp to the max
52
+    buffer size.
53
+  - Add option to disable locale support for JSON number conversion.
54
+  - Add support for Astro A20 Gen2.
55
+  - Fix some of the test sources, the flags were not set correctly.
56
+  - Add camera location as property in libcamera and let the session manager
57
+    Generate a localized description.
58
+  - Fix some crashes due to wrong vargar types in v4l2 controls. (#2400)
59
+  - Improve ALSA resync behaviour. (#2257)
60
+  - Add support for Komplete Audio 6 MK2.
61
+  - Improve loop cancel while iterating.
62
+  - Try not to mix surround channels and AUX channels. Make card with many
63
+    ports look better when not using the Pro Audio profile.
64
+  - Vulkan filters were added.
65
+
66
+## Bluetooth
67
+  - Add LC3plus vendor codec.
68
+  - Handle unsupported indicators better.
69
+  - Ensure multiple devices on an adapter use different codecs because one
70
+    endpoint can only be used by one device at a time.
71
+  - Fix bitpool control as a follower.
72
+  - Handle bluetooth errors better.
73
+  - Speed up bluetooth connection by only waiting for the profiles
74
+    supported by the adapter.
75
+  - The dummy AVRCP player is disabled by default because it seems to break
76
+    more devices than it fixes.
77
+
78
+## pulse-server
79
+  - Add initial stream latency property so that devices can be started
80
+    with a resonably accurate latency.
81
+  - Fix ringbuffer underrun case. (#2366)
82
+  - module-native-protocol-tcp now has a auth-anonymous option to give
83
+    full access to the clients.
84
+  - Report a node as being moved when it is still moving. This improves
85
+    compatibility with pasystray.
86
+  - Avoid overallocating message memory.
87
+  - Don't export NETWORK nodes in zeroconf. (#2384)
88
+  - Fix stride for TrueHD and DTSHD passthrough. (#2284)
89
+  - Make sure we don't send too small audio fragments. Fixes capture
90
+    from multiple tabs in Chrome. (#2418)
91
+  - Rework module handling some more.
92
+  - Use the new native module-pipe-tunnel for pipe-sink and pipe-source.
93
+  - Implement the STREAM_MOVED message when a stream got moved. (#2407)
94
+  - Fix a potential segfault when stopping the server and a TCP module
95
+    as still loaded.
96
+
97
+## ALSA
98
+  - Add support for updating sw_params at runtime, mostly the min-avail
99
+    param.
100
+  - Capture and playback nodes are now assumed to use a different clock and
101
+    will activate the adaptive resampler when linked. This assumption is
102
+    removed in Pro Audio mode. This provide a better experience out of the
103
+    box with most devices.
104
+
105
+## JACK
106
+  - Fix setting properties with PIPEWIRE_PROPS again.
107
+  - Don't use 64 bits atomic operations for sync_timeout. (#1867)
108
+  - Cleanup in error cases was improved, avoiding some crashes. (#2394)
109
+
110
+## GStreamer
111
+  - Fix pipewiresink in mode=provide. (#1980)
112
+  - Share memory into a new buffer in pipewiresrc to avoid buffer corruption.
113
+  - Fixes to the source and fd use.
114
+  - It is now possible to set client properties as well. (#1573)
115
+
116
+
117
+Older versions:
118
+
119
 # PipeWire 0.3.51 (2022-04-28)
120
 
121
 This is a bugfix release that is API and ABI compatible with previous
122
@@ -93,9 +210,6 @@
123
     IPC thread is blocking on the data thread.
124
   - Allocation errors in metadata are handled better.
125
 
126
-
127
-Older versions:
128
-
129
 # PipeWire 0.3.50 (2022-04-13)
130
 
131
 This is a bugfix release that is API and ABI compatible with previous
132
pipewire-0.3.51.tar.gz/doc/Doxyfile.in -> pipewire-0.3.52.tar.gz/doc/Doxyfile.in Changed
10
 
1
@@ -34,7 +34,7 @@
2
                          spa_ \
3
                          SPA_
4
 GENERATE_TREEVIEW      = YES
5
-SEARCHENGINE           = NO
6
+SEARCHENGINE           = YES
7
 GENERATE_LATEX         = NO
8
 
9
 MACRO_EXPANSION        = YES
10
pipewire-0.3.51.tar.gz/doc/dma-buf.dox -> pipewire-0.3.52.tar.gz/doc/dma-buf.dox Changed
125
 
1
@@ -1,28 +1,28 @@
2
-/** \page page_dma_buf DMA-BUF sharing
3
+/** \page page_dma_buf DMA-BUF Sharing
4
 
5
 PipeWire supports sharing Direct Memory Access buffers (DMA-BUFs) between
6
 clients via the `SPA_DATA_DmaBuf` data type. However properly negotiating
7
 DMA-BUF support on both the producer and the consumer side require following
8
 a specific procedure. This page describes said procedure by using events and
9
 methods from the filter or stream API.
10
+
11
 Note: This article focuses mostly on DMA-BUF sharing from arbitrary devices,
12
 like discrete GPUs. For using DMA-BUFs created by v4l2 please refer to the
13
 corresponding paragraph.
14
 
15
-# Capability negotiations
16
+# Capability Negotiations
17
 
18
-The capability negotiation for DMA-BUFs is complicated by the fact, that a
19
+The capability negotiation for DMA-BUFs is complicated by the fact that a
20
 usable and preferred optimal modifier for a given format can only be
21
-determined by the allocator, which has to be invoked with the intersection
22
-of all supported modifiers of all clients. As a result the fixation of the
23
-modifier has to be delegated from PipeWire to the node responsible for
24
+determined by the allocator. This allocator has to be invoked with the intersection
25
+of all supported modifiers for every client. As a result, the fixation of the
26
+modifier is delegated from PipeWire to the node responsible for
27
 allocating the buffers.
28
 
29
 ## pw_stream_connect
30
 
31
 The stream parameters should contain two `SPA_PARAM_EnumFormat` objects for
32
-each format: the first one is used for DMA-BUFs, the second one for shared
33
-memory buffers as a fallback.
34
+each format: one for DMA-BUFs, one for shared memory buffers as a fallback.
35
 
36
 Query the list of all supported modifiers from your graphics API of choice.
37
 Add a `SPA_FORMAT_VIDEO_modifier` property to the first stream parameter with
38
@@ -40,7 +40,7 @@
39
 To prioritise DMA-BUFs place those `SPA_PARAM_EnumFormat` containing modifiers
40
 first, when emitting them to PipeWire.
41
 
42
-## param_changed hook
43
+## param_changed Hook
44
 
45
 When the `param_changed` hook is called for a `SPA_PARAM_Format` the client
46
 has to parse the `spa_pod` directly. Use
47
@@ -57,32 +57,32 @@
48
 announce sufficient capabilities or fallback to shared memory buffers when
49
 possible.
50
 
51
-### For consumers
52
+### For Consumers
53
 
54
 Use `spa_format_video_raw_parse` to get the format and modifier.
55
 
56
-### For producers
57
+### For Producers
58
 
59
 Producers have to handle two cases when it comes to modifiers wrt. to the
60
 previous announced capabilities: Using only the modifier-less API, only the
61
-modifier aware one, or supporting both.
62
+modifier-aware one, or supporting both.
63
 
64
 - modifier-less:
65
   In this case only the modifier `DRM_FORMAT_MOD_INVALID` was announced with
66
   the format.
67
   It is sufficient to check if the `SPA_PARAM_Format` contains the modifier
68
-  property as described above. Is that the case use DMA-BUFs for screen-sharing,
69
+  property as described above. If that is the case, use DMA-BUFs for screen-sharing,
70
   else fall back to SHM, if possible.
71
 - modifier-aware:
72
   In this case a list with all supported modifiers will be returned in the format.
73
   (using `DRM_FORMAT_MOD_INVALID` as the token for the modifier-less API).
74
   On the `param_changed` event check if the modifier key is present and has the flag
75
-  `SPA_POD_PROP_FLAG_DONT_FIXATE`. attached to it. In this case extract all modifiers
76
+  `SPA_POD_PROP_FLAG_DONT_FIXATE` attached to it. In this case, extract all modifiers
77
   from the list and do a test allocation with your allocator to choose the preferred
78
   modifier. Fixate on that `EnumFormat` by announcing a `SPA_PARAM_EnumFormat` with
79
   only one modifier in the `SPA_CHOICE_Enum` and without the
80
   `SPA_POD_PROP_FLAG_DONT_FIXATE` flag, followed by the previous announced
81
-  `EnumFormat`s. This will retrigger the `param_changed` event with an
82
+  `EnumFormat`. This will retrigger the `param_changed` event with an
83
   `SPA_PARAM_Format` as described below.
84
   If the `SPA_PARAM_Format` contains a modifier key, without the flag
85
   `SPA_POD_PROP_FLAG_DONT_FIXATE`, it should only contain one value in the
86
@@ -96,32 +96,32 @@
87
 possible modifiers contains `DRM_FORMAT_MOD_INVALID`, fall back to allocating
88
 without an explicit modifier if the graphics API allows it.
89
 
90
-## add_buffer hook
91
+## add_buffer Hook
92
 
93
 This is relevant for producers.
94
 
95
 Allocate a DMA-BUF only using the negotiated format and modifier.
96
 
97
-## on_event hook
98
+## on_event Hook
99
 
100
 This is relevant for consumers.
101
 
102
 Check the type of the dequeued buffer. If its `SPA_DATA_MemFd` or
103
 `SPA_DATA_MemPtr` use the fallback SHM import mechanism.
104
-If it's `SPA_DATA_DmaBuf`:
105
-Get the DMA-BUF FDs (the plane count is encoded in the `n_datas` variable of the
106
+If it's `SPA_DATA_DmaBuf` 
107
+get the DMA-BUF FDs (the plane count is encoded in the `n_datas` variable of the
108
 `spa_buffer` struct) and import them with the graphics API.
109
 
110
 Note: Some graphics APIs have separated functions for the modifier-less case
111
 (`DRM_FORMAT_MOD_INVALID`) or are omitting the modifier, since it might be used
112
 for error handling.
113
 
114
-## Example programs
115
+## Example Programs
116
 
117
 - \ref video-src-fixate.c "": \snippet{doc} video-src-fixate.c title
118
 - \ref video-play-fixate.c "": \snippet{doc} video-play-fixate.c title
119
 
120
-# DMA-BUF mapping warning
121
+# DMA-BUF Mapping Warning
122
 
123
 It's important to make sure all consumers of the PipeWire stream are prepared
124
 to deal with DMA-BUFs. Most DMA-BUFs cannot be treated like shared memory in general
125
pipewire-0.3.51.tar.gz/doc/index.dox -> pipewire-0.3.52.tar.gz/doc/index.dox Changed
61
 
1
@@ -1,37 +1,38 @@
2
 /** \mainpage PipeWire
3
 
4
 PipeWire is low-level multimedia framework that provides:
5
-  - Graph based processing
6
-  - Support for out-of-process processing graphs with minimal overhead
7
-  - Flexible and extensible media format negotiation and buffer allocation
8
-  - Hard real-time capable plugins
9
-  - Very low-latency for both audio and video processing
10
+
11
+- Graph based processing.
12
+- Support for out-of-process processing graphs with minimal overhead.
13
+- Flexible and extensible media format negotiation and buffer allocation.
14
+- Hard real-time capable plugins.
15
+- Very low-latency for both audio and video processing.
16
 
17
 See \ref page_overview for an overview of PipeWire and \ref page_design
18
 for the design principles guiding PipeWire.
19
 
20
-### Components
21
+# Components
22
 
23
 PipeWire ships with the following components:
24
 
25
-- a \ref page_daemon that implements the IPC and graph processing
26
-- an example \ref page_session_manager that manages objects in the \ref page_daemon
27
-- a set of \ref page_tools to introspect and use the \ref page_daemon
28
-- a \ref page_library to develop PipeWire applications and plugins (\ref
29
+- A \ref page_daemon that implements the IPC and graph processing.
30
+- An example \ref page_session_manager that manages objects in the \ref page_daemon.
31
+- A set of \ref page_tools to introspect and use the \ref page_daemon.
32
+- A \ref page_library to develop PipeWire applications and plugins (\ref
33
   page_tutorial "tutorial").
34
-- the \ref page_spa used by both the \ref page_daemon and in the \ref
35
+- The \ref page_spa used by both the \ref page_daemon and in the \ref
36
   page_library.
37
 
38
-### API Documentation
39
+# API Documentation
40
 
41
-See \ref page_api
42
+See \ref page_api.
43
 
44
-### More Documentation
45
+# More Documentation
46
 
47
 See our Wiki(https://gitlab.freedesktop.org/pipewire/pipewire/-/wikis/home) for
48
 More information on how to configure and use PipeWire.
49
 
50
-### Resources
51
+# Resources
52
 
53
 - PipeWire and AGL(https://wiki.automotivelinux.org/_media/pipewire_agl_20181206.pdf)
54
 - LAC 2020 Paper(https://lac2020.sciencesconf.org/307881/document)
55
@@ -39,4 +40,5 @@
56
 - PipeWire: The Linux audio/video bus (LWN)(https://lwn.net/Articles/847412)
57
 - PipeWire Wikipedia(https://en.wikipedia.org/wiki/PipeWire)
58
 - Bluetooth, PipeWire and Whatsapp calls(https://gjhenrique.com/pipewire.html)
59
+
60
 */
61
pipewire-0.3.51.tar.gz/doc/overview.dox -> pipewire-0.3.52.tar.gz/doc/overview.dox Changed
55
 
1
@@ -1,24 +1,24 @@
2
 /** \page page_overview Overview
3
 
4
 PipeWire is a new low-level multimedia framework designed from scratch that
5
-aims to provide
6
+aims to provide:
7
 
8
-- graph based processing
9
-- support for out-of-process processing graphs with minimal overhead
10
-- flexible and extensible media format negotiation and buffer allocation
11
-- Hard real-time capable plugins
12
-- achieve very low-latency for both audio and video processing
13
+- Graph based processing.
14
+- Support for out-of-process processing graphs with minimal overhead.
15
+- Flexible and extensible media format negotiation and buffer allocation.
16
+- Hard real-time capable plugins.
17
+- Achieve very low-latency for both audio and video processing.
18
 
19
 The framework is used to build a modular daemon that can be configured to:
20
 
21
-- be a low-latency audio server with features like pulseaudio and/or jack
22
-- a video capture server that can manage hardware video capture devices and
23
-  provide access to them
24
-- a central hub where video can be made available for other applications
25
+- Be a low-latency audio server with features like PulseAudio and/or JACK.
26
+- A video capture server that can manage hardware video capture devices and
27
+  provide access to them.
28
+- A central hub where video can be made available for other applications
29
   such as the gnome-shell screencast API.
30
 
31
 
32
-## Motivation
33
+# Motivation
34
 
35
 Linux has no unified framework for exchanging multimedia content between
36
 applications or even devices. In most cases, developers realized that
37
@@ -29,14 +29,14 @@
38
 - For video capture, we usually go directly to the hardware devices, with
39
   all security implications and inflexible routing that this brings.
40
 - For consumer audio, we use PulseAudio to manage and mix multiple streams
41
-  from clients
42
+  from clients.
43
 - For Pro audio, we use JACK to manage the graph of nodes.
44
 
45
-None of these solutions (except perhaps to some extent Wayland), however,
46
+None of these solutions (except perhaps to some extent Wayland) however 
47
 were designed to support the security features that are required when
48
 dealing with flatpaks or other containerized applications. PipeWire
49
 aims to solve this problem and provides a unified framework to run both
50
-consumer and Pro audio as well as video capture and processing in a
51
+consumer and pro audio as well as video capture and processing in a
52
 secure way.
53
 
54
 */
55
pipewire-0.3.51.tar.gz/doc/pipewire-access.dox -> pipewire-0.3.52.tar.gz/doc/pipewire-access.dox Changed
108
 
1
@@ -14,46 +14,47 @@
2
   Some of those methods will only query state, others will modify the object.
3
   As said above, modifying the object through one of these methods requires
4
   the `W` permission.
5
-- `M`: An object with M permission can be used as the subject in metadata.
6
+- `M`: An object with `M` permission can be used as the subject in metadata.
7
 
8
 Clients with all permissions set are referred to as "ALL" in the
9
 documentation.
10
 
11
-# Use cases
12
 
13
-### New clients need their permissions configured
14
+# Use Cases
15
+
16
+## New Clients Need Their Permissions Configured
17
 
18
 A new client is not allowed to communicate with the PipeWire daemon until
19
 it has been configured with permissions.
20
 
21
-### Flatpaks can't modify other stream/device volumes
22
+## Flatpaks Can't Modify Other Stream/Device Volumes
23
 
24
 An application running as Flatpak should not be able to modify the state of
25
 certain objects. Permissions of the relevant PipeWire objects should not have
26
 the `W` permission to avoid this.
27
 
28
-### Flatpaks can't move other streams to different devices
29
+## Flatpaks Can't Move Other Streams To Different Devices
30
 
31
-Streams are moved to another device by setting the "target.node" metadata
32
-on the node id. By not setting the `M` bit on the other objects, this can be
33
+Streams are moved to another device by setting the `target.node` metadata
34
+on the node ID. By not setting the `M` bit on the other objects, this can be
35
 avoided.
36
 
37
-### Application should be restricted in what they can see
38
+## Application Should Be Restricted In What They Can See
39
 
40
 In general, applications should only be able to see the objects that they are
41
 allowed to see. For example, a web browser that was given access to a camera
42
 should not be able to see (and thus receive input data from) audio devices.
43
 
44
-### "Manager" applications require full access
45
+## "Manager" Applications Require Full Access
46
 
47
 Some applications require full access to the PipeWire graph, including
48
 moving streams between nodes (by setting metadata) and modifying properties
49
-(e.g. volume). These applications must work even when running as Flatpak.
50
+(eg. volume). These applications must work even when running as Flatpak.
51
 
52
 
53
 # Design
54
 
55
-## The PipeWire daemon
56
+## The PipeWire Daemon
57
 
58
 Immediately after a new client connects to the PipeWire daemon and updates
59
 its properties, the client will be registered and made visible to other
60
@@ -71,8 +72,7 @@
61
 sets the core permissions to `R`. This other client is usually a session
62
 manager, see e.g. \ref page_session_manager.
63
 
64
-
65
-## The PipeWire access module
66
+## The PipeWire Access Module
67
 
68
 The \ref page_module_access hooks into the `check_access` event that is
69
 emitted when a new client is registered. The module checks the permissions of
70
@@ -80,23 +80,23 @@
71
 property on the client object. If this property is already set, the access
72
 module does nothing.
73
 
74
-If the property is not set, it will go through a set of checks to determine
75
-the permissions for a client, see the \ref page_module_access documentation
76
+If the property is not set it will go through a set of checks to determine
77
+the permissions for a client. See the \ref page_module_access documentation
78
 for details, particularly on the values documented below. Depending on the
79
 value of the \ref PW_KEY_ACCESS property one the following happens:
80
 
81
 - `"allowed"`, `"unrestricted"`:  ALL permissions are set on the core
82
     object and the client will be able to resume.
83
-- `"restricted"`, `"flatpak"`, `"$access.force"`:  no permissions are set on
84
+- `"restricted"`, `"flatpak"`, `"$access.force"`:  No permissions are set on
85
     the core object and the client will be suspended.
86
-- `"rejected"`: an error is sent to the client and the client is
87
+- `"rejected"`: An error is sent to the client and the client is
88
     suspended.
89
 
90
 As detailed above, the client may be suspended. In that case the session
91
 manager or another client is required to configure permissions on the object
92
 for it to resume.
93
 
94
-## The session manager
95
+## The Session Manager
96
 
97
 The session manager listens for new clients to appear. It will use the
98
 \ref PW_KEY_ACCESS property to determine what to do.
99
@@ -117,7 +117,7 @@
100
 permission store checks or ask the user if the application is allowed
101
 full access.
102
 
103
-Manager applications (i.e. applications that need to modify the graph) will
104
+Manager applications (ie. applications that need to modify the graph) will
105
 set the \ref PW_KEY_MEDIA_CATEGORY property in the client object to "Manager".
106
 
107
 For details on the pipewire-media-session implementation of access control,
108
pipewire-0.3.51.tar.gz/doc/pipewire-audio.dox -> pipewire-0.3.52.tar.gz/doc/pipewire-audio.dox Changed
133
 
1
@@ -2,19 +2,19 @@
2
 
3
 This document explains how Audio is implemented.
4
 
5
-# Use cases
6
+# Use Cases
7
 
8
-## Audio devices are made available as processing nodes/ports
9
+## Audio Devices Are Made Available As Processing Nodes/Ports
10
 
11
 Applications need to be able to see a port for each stream of an
12
-Audio device.
13
+audio device.
14
 
15
-### Audio devices can be plugged and unplugged
16
+## Audio Devices Can Be Plugged and Unplugged
17
 
18
 When devices are plugged and unplugged the associated nodes/ports
19
 need to be created and removed.
20
 
21
-### Audio port in canonical format
22
+## Audio Port In Canonical Format
23
 
24
 It must be possible to make individual audio channels available
25
 as a single mono stream with a fixed format and samplerate.
26
@@ -22,7 +22,7 @@
27
 This makes it possible to link any of the audio ports together
28
 without doing conversions.
29
 
30
-### Applications can connect to audio devices
31
+## Applications Can Connect To Audio Devices
32
 
33
 Applications can create ports that can connect to the audio ports
34
 so that data can be provided to or consumed from them.
35
@@ -30,19 +30,19 @@
36
 It should be possible to automatically connect an application to
37
 a sink/source when it requests this.
38
 
39
-### Default audio sink and sources
40
+## Default Audio Sink and Sources
41
 
42
 It should be possible to mark a source or sink as the default source
43
 and sink so that applications are routed to them by default.
44
 
45
 It should be possible to change the default audio sink/source.
46
 
47
-### Application should be able to move between sinks/sources
48
+## Application Should Be Able To Move Between Sinks/Sources
49
 
50
 It should be possible to move an application from one device to
51
 another dynamically.
52
 
53
-### Exclusive access
54
+## Exclusive Access
55
 
56
 Application should be able to connect to a device in exclusive mode.
57
 This allows the application to negotiate a specific format with the
58
@@ -62,13 +62,13 @@
59
 This object is then responsible for controlling the \ref spa_node "SPA Nodes" that
60
 provide the audio ports to interface with the device.
61
 
62
-The Nodes operate on the native audio formats supported by the device.
63
+The nodes operate on the native audio formats supported by the device.
64
 This includes the sample rate as well as the number of channels and
65
 the audio format.
66
 
67
 ## Audio Adapter
68
 
69
-An SPA Node called the "adapter" is usually used with the SPA device Node as
70
+An SPA Node called the "adapter" is usually used with the SPA device node as
71
 the internal node.
72
 
73
 The function of the adapter is to convert the device native format to
74
@@ -80,14 +80,14 @@
75
 
76
 The audio adapter can also be configured in passthrough mode when it
77
 will not do any conversions but simply pass through the port information
78
-of the internal Node. This can be used to implement exclusive access.
79
+of the internal node. This can be used to implement exclusive access.
80
 
81
 Setup of the different configurations of the adapter can be done with
82
 the PortConfig parameter.
83
 
84
-## The session manager
85
+## The Session Manager
86
 
87
-The session manager is responsible for creating Nodes and Ports for
88
+The session manager is responsible for creating nodes and ports for
89
 the various audio devices. It will need to wrap them into an audio
90
 adapter so that the specific configuration of the node can be
91
 decided by the policy mode.
92
@@ -96,33 +96,32 @@
93
 devices and nodes.
94
 
95
 The session manager is responsible for assigning priorities to the
96
-Nodes. At least \ref PW_KEY_PRIORITY_SESSION and \ref PW_KEY_PRIORITY_DRIVER
97
+nodes. At least \ref PW_KEY_PRIORITY_SESSION and \ref PW_KEY_PRIORITY_DRIVER
98
 need to be set.
99
 
100
 The session manager might need to work with other services to gain
101
-exclusive access to the device (e.g. DBus).
102
+exclusive access to the device (eg. DBus).
103
 
104
 
105
 # Implementation
106
 
107
-## pipewire-media-session (alsa-monitor)
108
+## PipeWire Media Session (alsa-monitor)
109
 
110
 PipeWire media session uses the \ref SPA_NAME_API_ALSA_ENUM_UDEV plugin
111
 for enumerating the ALSA devices. For each device it does:
112
 
113
 - Try to acquire the DBus device reservation object to gain exclusive
114
   access to the device.
115
-- Create an SPA Device instance for the device and monitor this device instance.
116
-- For each Node created by the device, create an adapter with
117
+- Create an SPA device instance for the device and monitor this device instance.
118
+- For each node created by the device, create an adapter with
119
   an ALSA PCM node in the context of the PipeWire daemon.
120
 
121
 The session manager will also create suitable names and descriptions
122
-for the Devices and Nodes that it creates as well as assign session
123
+for the devices and nodes that it creates as well as assign session
124
 and driver priorities.
125
 
126
 The session manager has the option to add extra properties on the
127
-Devices and Node that it creates to control their behavior. This
128
+devices and nodes that it creates to control their behavior. This
129
 is implemented with match rules.
130
 
131
-
132
 */
133
pipewire-0.3.51.tar.gz/doc/pipewire-daemon.dox -> pipewire-0.3.52.tar.gz/doc/pipewire-daemon.dox Changed
128
 
1
@@ -7,7 +7,7 @@
2
 connections and manages devices. Clients (including the \ref
3
 page_session_manager) are separate processes that talk to the daemon using the
4
 PipeWire socket (default: `$XDG_RUNTIME_DIR/pipewire-0`). This approach
5
-provides provides address-space separation between the privileged daemon and
6
+provides address-space separation between the privileged daemon and
7
 non-privileged clients.
8
 
9
 \dot
10
@@ -52,7 +52,7 @@
11
 page_module_protocol_native. From PipeWire's point-of-view this module is just
12
 another module.
13
 
14
-\section sec_config Configuration Files
15
+# Configuration Files
16
 
17
 On startup, the daemon reads a configuration file to configure itself.
18
 It executes a series of commands listed in the config file. The lookup order
19
@@ -75,14 +75,14 @@
20
 and array elements are appended. This makes it possible to make small custom customizations
21
 or additions to the main configuration file.
22
 
23
-The environment variables `PIPEWIRE_CONFIG_DIR`, `PIPEWIRE_CONFIG_PREFIX`
24
-and `PIPEWIRE_CONFIG_NAME` can be used to specify an alternative config
25
-directory, subdirectory and filename, respectively.
26
+The environment variables `PIPEWIRE_CONFIG_DIR`, `PIPEWIRE_CONFIG_PREFIX`, 
27
+and `PIPEWIRE_CONFIG_NAME`. Can be used to specify an alternative configuration
28
+directory, subdirectory, and filename respectively.
29
 
30
-\subsection sec_config_format Configuration File Format
31
+## Configuration File Format
32
 
33
-PipeWire's configuration file format is JSON. In addition to true JSON,
34
-PipeWire also understands a more compact JSON representation where
35
+PipeWire's configuration file format is JSON. In addition to true JSON 
36
+PipeWire also understands a more compact JSON representation. Where
37
 `"` can be omitted around strings, no trailing commas are required and
38
 `:` or `=` can be used to separate object keys from their values.
39
 Also, `#` can be used to start a comment until the end of the line.
40
@@ -117,63 +117,60 @@
41
 
42
 - **context.properties**  (dictionary):   These   properties  configure  the
43
   pipewire instance.
44
-
45
 - **context.spa-libs** (dictionary): Maps plugin features with globs to a
46
   spa library.
47
-
48
 - **context.modules** (array): Each entry in the array is a dictionary with
49
   the name of the module to load, including optional args and flags. Most
50
   modules support being loaded multiple times.
51
-
52
 - **context.objects** (array):  Each entry in the array is a dictionary con‐
53
   taining the factory to create an object from and optional  extra  argu‐
54
   ments specific to that factory.
55
-
56
 - **context.exec**  (array): Each entry in the array is dictionary containing
57
   the path of a program to execute on startup and optional args. This ar‐
58
   ray usually contains an entry to start the session manager.
59
 
60
 
61
-\section sec_logging Logging
62
+# Logging
63
 
64
 The `PIPEWIRE_DEBUG` environment variable can be used to enable
65
 more debugging. This variable supports one of two formats:
66
 
67
-- `PIPEWIRE_DEBUG=<level>` where `<level>` is either a numerical log level or it's
68
+- `PIPEWIRE_DEBUG=<level>` where `<level>` is either a numerical log level or its
69
    respective key, see below.
70
 - `PIPEWIRE_DEBUG=<glob1>:<level1>,<glob2>:<level2>,...` where the globs are
71
-  shell-globs to match on log topics and the levels are the respective
72
-  log level to set for that topic. Globs are applied in-order and a matching
73
+  shell globs to match on log topics and the levels are the respective
74
+  log level to set for that topic. Globs are applied in order and a matching
75
   glob overrides an earlier glob for that category. For example,
76
-  `PIPEWIRE_DEBUG=*:E,mod.*:D,mod.foo:X" enables global error messages,
77
+  `PIPEWIRE_DEBUG=*:E,mod.*:D,mod.foo:X` enables global error messages,
78
   debugging on all modules but no messages on the foo module.
79
-
80
 - `<level>` specifies the log level:
81
-  + `X` or `0`: no logging is enabled
82
-  + `E` or `1`: Error logging is enabled
83
-  + `W` or `2`: Warnings are enabled
84
-  + `I` or `3`: Informational messages are enabled
85
-  + `D` or `4`: Debug messages are enabled
86
+
87
+  + `X` or `0`: No logging is enabled.
88
+  + `E` or `1`: Error logging is enabled.
89
+  + `W` or `2`: Warnings are enabled.
90
+  + `I` or `3`: Informational messages are enabled.
91
+  + `D` or `4`: Debug messages are enabled.
92
   + `T` or `5`: Trace messages are enabled. These messages can be logged
93
        from the realtime threads.
94
 
95
-PipeWire uses a "category.topic" naming scheme, with the following categories:
96
-- `pw.*`: pipewire-internal topics
97
-- `mod.*`: module topics, for example `mod.foo` would usually refer to the
98
-  "foo" module
99
-- `ms.*`: media session topics
100
-- `ms.mod.*`: media session modules, for example `ms.foo` would usually refer
101
-   to the "media-session-foo" module
102
-- `conn.*`: connection-specific topics such as printing raw messages sent over
103
+PipeWire uses a `category.topic` naming scheme, with the following categories:
104
+
105
+- `pw.*`: PipeWire internal topics.
106
+- `mod.*`: Module topics, for example `mod.foo` would usually refer to the
107
+  `foo` module.
108
+- `ms.*`: Media session topics.
109
+- `ms.mod.*`: Media session modules, for example `ms.foo` would usually refer
110
+   to the `media-session-foo` module.
111
+- `conn.*`: Connection specific topics such as printing raw messages sent over
112
   a communication socket. These are in a separate namespace as they are
113
   usually vastly more verbose than the normal debugging topics.
114
   This namespace must be explicitly enabled with a `conn.<glob>` glob.
115
 
116
-
117
 The behavior of the logging can be further controlled with the following
118
 environment variables:
119
-- `PIPEWIRE_LOG_SYSTEMD=false`: disable logging to the systemd journal
120
-- `PIPEWIRE_LOG=<filename>`: redirect the log to the given filename
121
-- `PIPEWIRE_LOG_LINE=false`: don't log filename, function, and source code line
122
+
123
+- `PIPEWIRE_LOG_SYSTEMD=false`: Disable logging to the systemd journal.
124
+- `PIPEWIRE_LOG=<filename>`: Redirect the log to the given filename.
125
+- `PIPEWIRE_LOG_LINE=false`: Don't log filename, function, and source code line.
126
 
127
 */
128
pipewire-0.3.51.tar.gz/doc/pipewire-design.dox -> pipewire-0.3.52.tar.gz/doc/pipewire-design.dox Changed
96
 
1
@@ -6,13 +6,13 @@
2
 Nodes can run inside the server process or in separate processes,
3
 communicating with the server.
4
 
5
-PipeWire was designed to
6
+PipeWire was designed to:
7
 
8
- - be efficient for raw video using fd passing and audio with
9
-   shared ringbuffers
10
- - be able to provide/consume/process media from any process
11
- - provide policy to restrict access to devices and streams
12
- - be easily extensible
13
+- Be efficient for raw video using fd passing and audio with
14
+  shared ringbuffers.
15
+- Be able to provide/consume/process media from any process.
16
+- Provide policy to restrict access to devices and streams.
17
+- Be easily extensible.
18
 
19
 Although an initial goal, the design is not limited to raw video
20
 only and should be able to handle compressed video and other
21
@@ -23,36 +23,30 @@
22
 format. SPA also provides a number of helper utilities that are not available
23
 in the standard C library.
24
 
25
-Some of the application we intend to build
26
+Some of the application we intend to build:
27
 
28
- - v4l2 device provider: Provide controlled access to v4l2 devices
29
-   and share one device between multiple processes.
30
+- v4l2 device provider: Provide controlled access to v4l2 devices
31
+  and share one device between multiple processes.
32
+- gnome-shell video provider: GNOME Shell provides a node that
33
+  gives the contents of the frame buffer for screen sharing or
34
+  screen recording.
35
+- Audio server: Mix and playback multiple audio streams. The design
36
+  is more like CRAS (Chromium audio server) than PulseAudio and with
37
+  the added benefit that processing can be arranged in a graph.
38
+- Professional audio graph processing like JACK.
39
+- Media playback backend.
40
 
41
- - gnome-shell video provider: GNOME Shell provides a node that
42
-   gives the contents of the frame buffer for screen sharing or
43
-   screen recording.
44
 
45
- - audio server: Mix and playback multiple audio streams. The design
46
-   is more like CRAS (Chromium audio server) than PulseAudio and with
47
-   the added benefit that processing can be arranged in a graph.
48
-
49
- - Pro audio graph processing like JACK.
50
-
51
- - Media playback backend
52
-
53
-
54
-Protocol
55
---------
56
+# Protocol
57
 
58
 The native protocol and object model is similar to
59
 Wayland(https://wayland.freedesktop.org) but with custom
60
-serialization/deserialization of messages. This is because the datastructures
61
+serialization/deserialization of messages. This is because the data structures
62
 in the messages are more complicated and not easily expressible in XML.
63
 See \ref page_module_protocol_native for details.
64
 
65
 
66
-Extensibility
67
--------------
68
+# Extensibility
69
 
70
 The functionality of the server is implemented and extended with modules and
71
 extensions. Modules are server side bits of logic that hook into various
72
@@ -64,16 +58,13 @@
73
 both a client side and server side init function. New interfaces or new object
74
 implementation can easily be added with modules/extensions.
75
 
76
-Some of the extensions that can be written
77
-
78
- - protocol extensions: a client/server side API (.h) together with protocol
79
-   extensions and server/client side logic to implement a new object or
80
-   interface.
81
-
82
- - a module to check security of method calls
83
-
84
- - a module to automatically create, link or relink nodes
85
+Some of the extensions that can be written:
86
 
87
- - a module to suspend idle nodes
88
+- Protocol extensions: A client/server side API (.h) together with protocol
89
+  extensions and server/client side logic to implement a new object or
90
+  interface.
91
+- A module to check security of method calls.
92
+- A module to automatically create, link or relink nodes.
93
+- A module to suspend idle nodes.
94
 
95
 */
96
pipewire-0.3.51.tar.gz/doc/pipewire-library.dox -> pipewire-0.3.52.tar.gz/doc/pipewire-library.dox Changed
198
 
1
@@ -1,15 +1,15 @@
2
 /** \page page_library PipeWire Library
3
 
4
-There are 2 main components that make up the PipeWire library:
5
+There are two main components that make up the PipeWire library:
6
 
7
 1. An implementation of a graph based media processing engine.
8
 2. An asynchronous IPC mechanism to manipulate and introspect
9
-    a graph in another process.
10
+   a graph in another process.
11
 
12
 There is usually a daemon that implements the global graph and
13
 clients that operate on this graph.
14
 
15
-The IPC mechanism in PipeWire is inspired by wayland in that it
16
+The IPC mechanism in PipeWire is inspired by Wayland in that it
17
 follows the same design principles of objects and methods/events
18
 along with how this API is presented to the user.
19
 
20
@@ -18,7 +18,8 @@
21
 aspects of PipeWire and change the behaviour or number of
22
 features dynamically.
23
 
24
-## Principles
25
+
26
+# Principles
27
 
28
 The PipeWire API is an object oriented asynchronous protocol.
29
 All requests and replies are method invocations on some object.
30
@@ -51,7 +52,8 @@
31
 State about objects can be obtained by binding to them and listening
32
 for state changes.
33
 
34
-## Versioning
35
+
36
+# Versioning
37
 
38
 All interfaces have a version number. The maximum supported version
39
 number of an interface is advertized in the registry global event.
40
@@ -64,7 +66,8 @@
41
 are added. Methods or events should never be removed or changed for
42
 simplicity.
43
 
44
-## Proxies and resources
45
+
46
+# Proxies and Resources
47
 
48
 When a client connects to a PipeWire daemon, a new `struct pw_proxy`
49
 object is created with ID 0. The `struct pw_core` interface is
50
@@ -83,25 +86,22 @@
51
 proxy when it no longer wants to use it.
52
 
53
 
54
-## Interfaces
55
+# Interfaces
56
 
57
-### `struct pw_loop`
58
+## struct pw_loop
59
 
60
 An abstraction for a `poll(2)` loop. It is usually part of one of:
61
 
62
-* `struct pw_main_loop`: a helper that can run and stop a `pw_loop`.
63
-
64
-* `struct pw_thread_loop`: a helper that can run and stop a `pw_loop`
65
-       in a different thread. It also has some helper
66
-       functions for various thread related synchronization
67
-       issues.
68
-
69
-* `struct pw_data_loop`: a helper that can run and stop a `pw_loop`
70
-       in a real-time thread along with some useful helper
71
-       functions.
72
+- `struct pw_main_loop`: A helper that can run and stop a `pw_loop`.
73
+- `struct pw_thread_loop`: A helper that can run and stop a `pw_loop`
74
+  in a different thread. It also has some helper
75
+  functions for various thread related synchronization
76
+  issues.
77
+- `struct pw_data_loop`: A helper that can run and stop a `pw_loop`
78
+  in a real-time thread along with some useful helper
79
+  functions.
80
 
81
-
82
-### `struct pw_context`
83
+## struct pw_context
84
 
85
 The main context for PipeWire resources. It keeps track of the mainloop,
86
 loaded modules, the processing graph and proxies to remote PipeWire
87
@@ -113,8 +113,7 @@
88
 The context has methods to create the various objects you can use to
89
 build a server or client application.
90
 
91
-
92
-### `struct pw_core`
93
+## struct pw_core
94
 
95
 A proxy to a remote PipeWire instance. This is used to send messages
96
 to a remote PipeWire daemon and to receive events from it.
97
@@ -125,63 +124,63 @@
98
 Other core methods and events are used internally for the object
99
 life cycle management.
100
 
101
-### `struct pw_registry`
102
+## struct pw_registry
103
 
104
 A proxy to a PipeWire registry object. It emits events about the
105
 available objects on the server and can be used to bind to those
106
 objects in order to call methods or receive events from them.
107
 
108
-### `struct pw_module`
109
+## struct pw_module
110
 
111
 A proxy to a loadable module. Modules implement functionality such
112
 as provide new objects or policy.
113
 
114
-### `struct pw_factory`
115
+## struct pw_factory
116
 
117
 A proxy to an object that can create other objects.
118
 
119
-### `struct pw_device`
120
+## struct pw_device
121
 
122
 A proxy to a device object. Device objects model a physical hardware
123
 or software device in the system and can create other objects
124
 such as nodes or other devices.
125
 
126
-### `struct pw_node`
127
+## struct pw_node
128
 
129
 A Proxy to a processing node in the graph. Nodes can have input and
130
 output ports and the ports can be linked together to form a graph.
131
 
132
-### `struct pw_port`
133
+## struct pw_port
134
 
135
-A Proxy to an input or output port of a node.  They can be linked
136
+A Proxy to an input or output port of a node. They can be linked
137
 together to form a processing graph.
138
 
139
-### `struct pw_link`
140
+## struct pw_link
141
 
142
 A proxy to a link between in output and input port. A link negotiates
143
 a format and buffers between ports. A port can be linked to many other
144
 ports and PipeWire will manage mixing and duplicating the buffers.
145
 
146
 
147
-## High level helper objects
148
+# High Level Helper Objects
149
 
150
 Some high level objects are implemented to make it easier to interface
151
 with a PipeWire graph.
152
 
153
-### `struct pw_filter`
154
+## struct pw_filter
155
 
156
 A `struct pw_filter` allows you implement a processing filter that can
157
 be added to a PipeWire graph. It is comparable to a JACK client.
158
 
159
-### `struct pw_stream`
160
+## struct pw_stream
161
 
162
-a `struct pw_stream` makes it easy to implement a playback or capture
163
+A `struct pw_stream` makes it easy to implement a playback or capture
164
 client for the graph. It takes care of format conversion and buffer
165
 sizes. It is comparable to Core Audio AudioQueue or a PulseAudio
166
 stream.
167
 
168
 
169
-## Security
170
+# Security
171
 
172
 With the default native protocol, clients connect to PipeWire using
173
 a named socket. This results in a client socket that is used to
174
@@ -215,13 +214,14 @@
175
 and data between clients. Clients can thus not look at other clients
176
 data unless they can see the objects and connect to them.
177
 
178
-## Implementation
179
+
180
+# Implementation
181
 
182
 PipeWire also exposes an API to implement the server side objects in
183
 a graph.
184
 
185
 
186
-## Error reporting
187
+# Error Reporting
188
 
189
 Functions return either NULL with errno set or a negative int error
190
 code when an error occurs. Error codes are used from the SPA plugin
191
@@ -237,6 +237,4 @@
192
 callback). The sequence number can be used to see which operation
193
 completed.
194
 
195
-
196
 */
197
-
198
pipewire-0.3.51.tar.gz/doc/pipewire-midi.dox -> pipewire-0.3.52.tar.gz/doc/pipewire-midi.dox Changed
109
 
1
@@ -2,41 +2,43 @@
2
 
3
 This document explains how MIDI is implemented.
4
 
5
-# Use cases
6
 
7
-### MIDI devices are made available as processing nodes/ports
8
+# Use Cases
9
+
10
+## MIDI Devices Are Made Available As Processing Nodes/Ports
11
 
12
 Applications need to be able to see a port for each stream of a
13
 MIDI device.
14
 
15
-### MIDI devices can be plugged and unplugged
16
+## MIDI Devices Can Be Plugged and Unplugged
17
 
18
 When devices are plugged and unplugged the associated nodes/ports
19
 need to be created and removed.
20
 
21
-### Applications can connect to MIDI devices
22
+## Applications Can Connect To MIDI Devices
23
 
24
 Applications can create ports that can connect to the MIDI ports
25
 so that data can be provided to or consumed from them.
26
 
27
-### Some MIDI devices are sinks or sources for midi data
28
+## Some MIDI Devices Are Sinks Or Sources For MIDI Data
29
 
30
 It should be possible to create a MIDI sink or source that routes the
31
-midi events to specific midi ports.
32
+MIDI events to specific MIDI ports.
33
 
34
-One example of such a sink would be in front of a software midi
35
+One example of such a sink would be in front of a software MIDI
36
 renderer.
37
 
38
 An example of a MIDI source would be after a virtual keyboard or
39
-as a mix from many midi input devices.
40
+as a mix from many MIDI input devices.
41
 
42
-### Applications should autoconnect to MIDI sinks or sources
43
+## Applications Should Auto-connect To MIDI Sinks Or Sources
44
 
45
 An application should be able to be connected to a MIDI sink when
46
-it wants to play midi data.
47
+it wants to play MIDI data.
48
 
49
 An application should be able to connect to a MIDI source when it
50
-wants to capture midi data.
51
+wants to capture MIDI data.
52
+
53
 
54
 # Design
55
 
56
@@ -48,7 +50,7 @@
57
 are of type \ref spa_pod_sequence with the \ref spa_pod_control type set to
58
 \ref SPA_CONTROL_Midi.
59
 
60
-This means that every midi event is timestamped with the sample
61
+This means that every MIDI event is timestamped with the sample
62
 offset against the current graph clock cycle to get sample accurate
63
 midi events that can be aligned with the corresponding sample data.
64
 
65
@@ -56,13 +58,13 @@
66
 they can be interleaved with other control message types, such as
67
 property updates or OSC messages.
68
 
69
-## The PipeWire daemon
70
+## The PipeWire Daemon
71
 
72
 Nothing special is implemented for MIDI. Negotiation of formats
73
 happens between `"application/control"` media types and buffers are
74
 negotiated in the same way as any generic format.
75
 
76
-## The session manager
77
+## The Session Manager
78
 
79
 The session manager needs to create the MIDI nodes/ports for the available
80
 devices.
81
@@ -76,10 +78,10 @@
82
 
83
 # Implementation
84
 
85
-## pipewire-media-session
86
+## PipeWire Media Session
87
 
88
 PipeWire media session uses the \ref SPA_NAME_API_ALSA_SEQ_BRIDGE plugin for
89
-the midi features. This creates a single SPA Node with ports per
90
+the MIDI features. This creates a single SPA Node with ports per
91
 MIDI client/stream.
92
 
93
 The media session will check the permissions on `/dev/snd/seq` before
94
@@ -88,7 +90,7 @@
95
 
96
 ## JACK
97
 
98
-JACK assumes all `"application/control"` ports are midi ports.
99
+JACK assumes all `"application/control"` ports are MIDI ports.
100
 
101
 The control messages are converted to the JACK event format by
102
 filtering out the \ref SPA_CONTROL_Midi types. On output ports, the JACK
103
@@ -98,5 +100,4 @@
104
 messages so there is no information loss or need for complicated
105
 conversions.
106
 
107
-
108
 */
109
pipewire-0.3.51.tar.gz/doc/pipewire-modules.dox -> pipewire-0.3.52.tar.gz/doc/pipewire-modules.dox Changed
40
 
1
@@ -1,6 +1,4 @@
2
-/**
3
-
4
-\page page_pipewire_modules PipeWire Modules
5
+/** \page page_pipewire_modules PipeWire Modules
6
 
7
 A PipeWire module is effectively a PipeWire client in an `.so` file that
8
 shares the \ref pw_context with the loading entity. Usually modules are
9
@@ -28,7 +26,7 @@
10
     ...
11
 
12
 ```
13
-And the matching libraries are:
14
+The matching libraries are:
15
 ```
16
 $ ls -1 /usr/lib64/pipewire-0.3/libpipewire-module*
17
 ...
18
@@ -49,7 +47,6 @@
19
 See the \ref page_module_example_sink and \ref page_module_example_source
20
 modules for a general oveview of how modules look like.
21
 
22
-
23
 List of known modules:
24
 
25
 - \subpage page_module_access
26
@@ -64,6 +61,7 @@
27
 - \subpage page_module_link_factory
28
 - \subpage page_module_loopback
29
 - \subpage page_module_metadata
30
+- \subpage page_module_pipe_tunnel
31
 - \subpage page_module_portal
32
 - \subpage page_module_profiler
33
 - \subpage page_module_protocol_native
34
@@ -79,5 +77,4 @@
35
 - \subpage page_module_x11_bell
36
 - \subpage page_module_zeroconf_discover
37
 
38
-
39
 */
40
pipewire-0.3.51.tar.gz/doc/pipewire-objects-design.dox -> pipewire-0.3.52.tar.gz/doc/pipewire-objects-design.dox Changed
201
 
1
@@ -1,11 +1,12 @@
2
 /** \page page_objects_design Objects Design
3
 
4
 This document is a design reference on the various objects that exist
5
-in the PipeWire media and session management graphs, explaining what these
6
-objects are, how they are meant to be used and how they relate to other
7
+in the PipeWire media and session management graphs. Explaining what these
8
+objects are, how they are meant to be used, and how they relate to other
9
 kinds of objects and concepts that exist in subsystems or other libraries.
10
 
11
-## The media graph
12
+
13
+# The Media Graph
14
 
15
 The media graph represents and enables the media flow inside the PipeWire
16
 daemon and between the daemon and its clients. It consists of nodes, ports
17
@@ -21,7 +22,7 @@
18
 +------------+                    +------------+
19
 ```
20
 
21
-### Node
22
+## Node
23
 
24
 A **node** is a media processing element. It consumes and/or produces buffers
25
 that contain data, such as audio or video.
26
@@ -33,26 +34,28 @@
27
 In an analogy to GStreamer, a _node_ is similar (but not equal) to a
28
 GStreamer _element_.
29
 
30
-### Port
31
+## Port
32
 
33
 A **port** is attached on a **node** and provides an interface for input
34
 or output of media on the node. A node may have multiple ports.
35
 
36
 A port always has a direction, input or output:
37
+
38
 - Input: it allows media input into the node (in other terms, it is a _sink_)
39
 - Output: it outputs media out of the node (in other terms, it is a _source_)
40
 
41
 In an analogy to GStreamer, a _port_ is similar (but not equal) to a
42
 GStreamer _pad_.
43
 
44
-### Link
45
+## Link
46
 
47
-A **link** connects 2 ports of opposite direction, making media flow from
48
+A **link** connects two ports of opposite direction, making media flow from
49
 the output port to the input port.
50
 
51
-## The session management graph
52
 
53
-The session management graph is a virtual, higher-level representation of the
54
+# The Session Management Graph
55
+
56
+The session management graph is a virtual, higher level representation of the
57
 media flow. It is created entirely by the session manager and it can affect
58
 the routing on the media graph only through the session manager's actions.
59
 
60
@@ -70,28 +73,31 @@
61
 +---------------------+                                +----------------------+
62
 ```
63
 
64
-### Endpoint
65
+## Endpoint
66
 
67
 An **endpoint** is a session management object that provides a representation
68
-of user-conceivable places where media can be routed to/from.
69
+of user conceivable places where media can be routed to/from.
70
 
71
 Examples of endpoints associated with hardware on a desktop-like system:
72
- - Laptop speakers
73
- - USB webcam
74
- - Bluetooth headset microphone
75
- - Line out stereo jack port
76
+
77
+- Laptop speakers.
78
+- USB webcam.
79
+- Bluetooth headset microphone.
80
+- Line out stereo jack port.
81
 
82
 Examples of endpoints associated with hardware in a car:
83
- - Speakers amplifier
84
- - Front right seat microphone array
85
- - Rear left seat headphones
86
- - Bluetooth phone voice gateway
87
- - Hardware FM radio device
88
+
89
+- Speakers amplifier.
90
+- Front right seat microphone array.
91
+- Rear left seat headphones.
92
+- Bluetooth phone voice gateway.
93
+- Hardware FM radio device.
94
 
95
 Examples of endpoints associated with software:
96
- - Desktop screen capture source
97
- - Media player application
98
- - Camera application
99
+
100
+- Desktop screen capture source.
101
+- Media player application.
102
+- Camera application.
103
 
104
 In most cases an endpoint maps to a node on the media graph, but this is not
105
 always the case. An endpoint may be backed by several nodes or no nodes at all.
106
@@ -107,7 +113,7 @@
107
 it and the amplifier, so that it can apply audio policy that takes into account
108
 whether the CD player is playing or not.
109
 
110
-#### Target
111
+### Target
112
 
113
 An **endpoint** may be grouping together targets that can be reached by
114
 following the same route and they are mutually exclusive with each other.
115
@@ -121,7 +127,7 @@
116
 same endpoint, using a parameter on the _endpoint_ object to allow the user
117
 to choose the target (if the hardware allows configuring this at all).
118
 
119
-### Endpoint Stream
120
+## Endpoint Stream
121
 
122
 An **endpoint stream** is attached to an **endpoint** and represents a logical
123
 path that can be taken to reach this endpoint, often associated with
124
@@ -129,45 +135,48 @@
125
 
126
 For example, the "Speakers amplifier" endpoint in a car might have the
127
 following streams:
128
- - _Music_: a path to play music;
129
-       the implementation will output this to all speakers, using the volume
130
-       that has been configured for the "Music" use case
131
- - _Voice_: a path to play a voice message, such as a navigation message or
132
-       feedback from a voice assistant; the implementation will output this
133
-       to the front speakers only, lowering the volume of the music (if any)
134
-       on these speakers at the same time
135
- - _Emergency_: a path to play an emergency situation sound (a beep,
136
-       or equivalent); the implementation will output this on all speakers,
137
-       increasing the volume to a factory-defined value if necessary (to ensure
138
-       that it is audible) while muting audio from all other streams at the
139
-       same time
140
+
141
+- _Music_: A path to play music;
142
+  the implementation will output this to all speakers, using the volume
143
+  that has been configured for the "Music" use case.
144
+- _Voice_: A path to play a voice message; such as a navigation message or
145
+  feedback from a voice assistant, the implementation will output this
146
+  to the front speakers only. Lowering the volume of the music (if any)
147
+  on these speakers at the same time.
148
+- _Emergency_: A path to play an emergency situation sound (a beep,
149
+  or equivalent); the implementation will output this on all speakers.
150
+  Increasing the volume to a factory defined value if necessary (to ensure
151
+  that it is audible) while muting audio from all other streams at the
152
+  same time.
153
 
154
 In another example, a microphone that can be used for activating a voice
155
 assistant might have the following streams:
156
- - _Capture_: a path to capture directly from the microphone; this can be used
157
-       by an application that listens for the assistant's wake-word in order
158
-       to activate the full voice recognition engine
159
- - _CaptureDelayed_: a path to capture with a constant delay (meaning that
160
-       starting capturing now will actually capture something that was spoken
161
-       a little earlier); this can be used by the full voice recognition engine,
162
-       allowing it to start after the wake-word has been spoken while capturing
163
-       audio that also includes the wake-word
164
+
165
+- _Capture_: A path to capture directly from the microphone; this can be used
166
+  by an application that listens for the assistant's wake-word in order
167
+  to activate the full voice recognition engine.
168
+- _CaptureDelayed_: A path to capture with a constant delay (meaning that
169
+  starting capturing now will actually capture something that was spoken
170
+  a little earlier); this can be used by the full voice recognition engine,
171
+  allowing it to start after the wake-word has been spoken while capturing
172
+  audio that also includes the wake-word.
173
 
174
 Endpoint streams may be mutually exclusive or they may used simultaneously,
175
 depending on the implementation.
176
 
177
 Endpoint streams may be implemented in many ways:
178
- - By plugging additional nodes in the media graph that link to the device node
179
-   (ex. a simple buffering node linked to an alsa source node could implement
180
-   the _CaptureDelayed_ stream in the above microphone example)
181
- - By using a different device node (ex. different ALSA device on the same card)
182
-   that has a special meaning for the hardware
183
- - By triggering switches on the hardware (ex. modify ALSA controls on the
184
-   same device)
185
 
186
-### Endpoint Link
187
+- By plugging additional nodes in the media graph that link to the device node
188
+  (ex. a simple buffering node linked to an alsa source node could implement
189
+  the _CaptureDelayed_ stream in the above microphone example).
190
+- By using a different device node (ex. different ALSA device on the same card)
191
+  that has a special meaning for the hardware.
192
+- By triggering switches on the hardware (ex. modify ALSA controls on the
193
+  same device).
194
+
195
+## Endpoint Link
196
 
197
-An **endpoint link** connects 2 streams from 2 different endpoints, creating
198
+An **endpoint link** connects two streams from two different endpoints, creating
199
 a logical representation of media flow between the endpoints.
200
 
201
pipewire-0.3.51.tar.gz/doc/pipewire-portal.dox -> pipewire-0.3.52.tar.gz/doc/pipewire-portal.dox Changed
93
 
1
@@ -12,13 +12,14 @@
2
 client is a portal-managed client. PipeWire can detect and enforce
3
 extra permission checks on the portal managed clients.
4
 
5
-Once such portal is the Camera
6
+Once such portal is the camera
7
 portal(https://flatpak.github.io/xdg-desktop-portal/portal-docs.html#gdbus-org.freedesktop.portal.Camera)
8
 that provides a PipeWire session to stream video from a camera.
9
 
10
-# Use cases
11
 
12
-### new portal managed clients need device permissions configured
13
+# Use Cases
14
+
15
+## New Portal Managed Clients Need Device Permissions Configured
16
 
17
 When a new client is detected, the available objects need to be
18
 scanned and permissions configured for each of them.
19
@@ -26,7 +27,7 @@
20
 Only the devices belonging to the media_roles given by the
21
 portal are considered.
22
 
23
-### new devices need to be made visible to portal managed clients
24
+## New Devices Need To Be Made Visible To Portal Managed Clients
25
 
26
 Newly created objects are made visible to a client when the client
27
 is allowed to interact with it.
28
@@ -34,7 +35,7 @@
29
 Only the devices belonging to the media_roles given by the
30
 portal are considered.
31
 
32
-### permissions for a device need to be revoked
33
+## Permissions For A Device Need To Be Revoked
34
 
35
 The session manager listens to changes in the permissions of devices
36
 and will remove the client permissions accordingly.
37
@@ -46,7 +47,7 @@
38
 
39
 # Design
40
 
41
-## The portal
42
+## The Portal
43
 
44
 A sandboxed client cannot connect to PipeWire directly. Instead, it connects
45
 to the sandbox side of the portal which then connects the PipeWire daemon to
46
@@ -59,7 +60,7 @@
47
 
48
 - `"pipewire.access.portal.is_portal" = true` for the connection of the
49
   portal itself (as opposed to a client managed by the portal).
50
-- `"pipewire.access.portal.app_id"` the application id(https://docs.flatpak.org/en/latest/conventions.html#application-ids) of the client.
51
+- `"pipewire.access.portal.app_id"` the application ID(https://docs.flatpak.org/en/latest/conventions.html#application-ids) of the client.
52
 - `"pipewire.access.portal.media_roles"` media roles of the client.
53
   Currently only `"Camera"` is defined.
54
 
55
@@ -69,9 +70,9 @@
56
 visible, depending on the client's `media_roles` (see also \ref
57
 PW_KEY_MEDIA_ROLE).
58
 
59
-## The PipeWire portal module
60
+## The PipeWire Portal Module
61
 
62
-The pipewire daemon uses the \ref page_module_portal to find the PID of the
63
+The PipeWire daemon uses the \ref page_module_portal to find the PID of the
64
 processes that owns the DBus name `org.freedesktop.portal.Desktop`
65
 (see the XDG Desktop Portal(https://github.com/flatpak/xdg-desktop-portal)).
66
 
67
@@ -99,7 +100,7 @@
68
 }
69
 \enddot
70
 
71
-## The client
72
+## The Client
73
 
74
 A client can ask the portal for a connection to the PipeWire daemon.
75
 
76
@@ -145,7 +146,6 @@
77
 }
78
 \enddot
79
 
80
-
81
 The file descriptor for this restricted connection is passed back to the
82
 client which can now make use of the resources it has been permitted to
83
 access.
84
@@ -169,7 +169,7 @@
85
 }
86
 \enddot
87
 
88
-## The session manager
89
+## The Session Manager
90
 
91
 The session manager listens for new clients to appear. It will use the
92
 \ref PW_KEY_ACCESS property to find portal connections. For client connections
93
pipewire-0.3.51.tar.gz/doc/pipewire-session-manager.dox -> pipewire-0.3.52.tar.gz/doc/pipewire-session-manager.dox Changed
52
 
1
@@ -6,38 +6,41 @@
2
 It provides the mechanism to do so but the policy deciding which components
3
 can talk to each other and when is controlled by the session manager.  As
4
 outlined in \ref page_objects_design, PipeWire provides a media graph
5
-consistent of Devices, Nodes and Ports. The session manager is the one that
6
+consisting of devices, nodes and ports. The session manager is the one that
7
 decides on the links between those elements.
8
 
9
 Two prominent session managers currently exist:
10
+
11
 - PipeWire Media Session(https://gitlab.freedesktop.org/pipewire/media-session), the
12
-example session manager
13
+example session manager.
14
 - WirePlumber(https://gitlab.freedesktop.org/pipewire/wireplumber), a
15
-modular session manager based on GObject
16
+modular session manager based on GObject. 
17
+Documentation(https://pipewire.pages.freedesktop.org/wireplumber/)
18
 
19
 This page describes some of the requirements for session managers in general.
20
 
21
-## Client management
22
+
23
+# Client Management
24
 
25
 PipeWire provides a \ref page_access "permission system" to limit client's
26
 access to resources but only \ref page_module_access "basic permission
27
 handling". The session manager is expected to decide whether clients may
28
 access specific resources.
29
 
30
-## Device management
31
+
32
+# Device Management
33
 
34
 PipeWire's responsibility is to open devices, however the decision on which
35
 devices should be opened is the job of a session manager, including the
36
 configuration of those devices.
37
 
38
 
39
-## Endpoint grouping
40
+# Endpoint Grouping
41
 
42
-An endpoint is, effectively, a group of Nodes that are a logical unit that can
43
+An endpoint is, effectively, a group of nodes that are a logical unit that can
44
 consume or produce media data. For example, a Bluetooth speaker may present as
45
-several Nodes but is only one logical unit to stream audio to.
46
+several nodes but is only one logical unit to stream audio to.
47
 
48
 See \ref page_objects_design for details on Endpoints.
49
 
50
 */
51
-
52
pipewire-0.3.51.tar.gz/doc/pipewire.dox -> pipewire-0.3.52.tar.gz/doc/pipewire.dox Changed
27
 
1
@@ -1,6 +1,6 @@
2
 /** \page page_pipewire PipeWire Design
3
 
4
-## Internals
5
+# Internals
6
 
7
 - \subpage page_design
8
 - \subpage page_audio
9
@@ -11,13 +11,15 @@
10
 - \subpage page_library
11
 - \subpage page_dma_buf
12
 
13
-## Components
14
+
15
+# Components
16
 
17
 - \subpage page_daemon
18
 - \subpage page_tools
19
 - \subpage page_session_manager
20
 
21
-## Backends
22
+
23
+# Backends
24
 
25
 - \subpage page_pulseaudio
26
 
27
pipewire-0.3.51.tar.gz/doc/pulseaudio.dox -> pipewire-0.3.52.tar.gz/doc/pulseaudio.dox Changed
90
 
1
@@ -1,18 +1,18 @@
2
-/** \page page_pulseaudio  PulseAudio compatibility
3
+/** \page page_pulseaudio PulseAudio Compatibility
4
 
5
-# Internals - Mapping between ALSA and streams
6
+# Internals - Mapping Between ALSA and Streams
7
 
8
 This explains the mapping between alsa cards and streams and session manager
9
 objects.
10
 
11
-
12
 ## ALSA Cards
13
 
14
-An ALSA card is exposed as a PipeWire device
15
+An ALSA card is exposed as a PipeWire device.
16
 
17
 ## Streams
18
 
19
-Each alsa PCM is opened and a Node is created for each PCM stream.
20
+Each ALSA PCM is opened and a node is created for each PCM stream.
21
+
22
 
23
 # Session Manager
24
 
25
@@ -22,8 +22,8 @@
26
 
27
 One PipeWire device is created for every ALSA card.
28
 
29
-For each UCM verb, a Node is created for the associated PCM devices.
30
-For each UCM verb, an Endpoint is created.
31
+- For each UCM verb, a node is created for the associated PCM devices.
32
+- For each UCM verb, an endpoint is created.
33
 
34
 In a first step: For each available combination of UCM device and modifier,
35
 a stream is created. Streams are marked with compatible other streams.
36
@@ -31,26 +31,23 @@
37
 Streams with the same modifier and mutually exclusive devices are grouped
38
 into one stream and the UCM devices are exposed on the endpoint as destinations.
39
 
40
-
41
-## ALSA fallback
42
+## ALSA Fallback
43
 
44
 Each PCM stream (node) becomes an endpoint. The endpoint references the
45
-alsa device id
46
+ALSA device ID.
47
 
48
-Each endpoint has 1 stream (for now) called HiFi Playback / HiFi Capture.
49
+Each endpoint has one stream (for now) called HiFi Playback / HiFi Capture.
50
 
51
 More streams can be created depending on the format of the node.
52
 
53
+## ALSA Pulse UCM
54
 
55
-## ALSA pulse UCM
56
-
57
-Using the alsa backend of pulseaudio we can create the following streams
58
-
59
+Using the ALSA backend of PulseAudio we can create the following streams.
60
 
61
-## ALSA pulse fallback
62
+## ALSA Pulse Fallback
63
 
64
-The pulse alsa backend will use the mixer controls and some probing to
65
-create the following nodes and endpoints
66
+The pulse ALSA backend will use the mixer controls and some probing to
67
+create the following nodes and endpoints.
68
 
69
 
70
 # PulseAudio
71
@@ -58,14 +55,14 @@
72
 PulseAudio uses the session manager API to construct cards with profiles
73
 and sink/source with ports.
74
 
75
-If an Endpoint references a Device, a card object is created for the device.
76
+If an endpoint references a device, a card object is created for the device.
77
 
78
-Each Endpoint becomes a sink/source.
79
+Each endpoint becomes a sink/source.
80
 
81
 Each Stream in the endpoint becomes a profile on the PulseAudio card. Because
82
-only one profile is selected on the device, only 1 stream is visible on
83
+only one profile is selected on the device, only one stream is visible on
84
 the endpoint. This clashes with the notion that multiple streams can be
85
-active at the same time but is a pulseaudio limitation.
86
+active at the same time but is a PulseAudio limitation.
87
 
88
 Each Endpoint destination becomes a port on the sink/source.
89
 
90
pipewire-0.3.51.tar.gz/doc/spa-buffer.dox -> pipewire-0.3.52.tar.gz/doc/spa-buffer.dox Changed
10
 
1
@@ -6,7 +6,7 @@
2
 
3
 > What is the `void*` data pointer in `spa_data`?
4
 
5
-The data information either has a file descriptor or a data pointer. The type of the `spa_data` tells you what to expect. For a file descriptor, the data pointer can optionally be set when the fd is mapped into memory. Otherwise the user has to mmap the data herself.
6
+The data information either has a file descriptor or a data pointer. The type of the `spa_data` tells you what to expect. For a file descriptor, the data pointer can optionally be set when the FD is mapped into memory. Otherwise the user has to mmap the data themselves.
7
 
8
 Also associated with each `spa_data` is a chunk, which is read/write and contains the valid region in the `spa_data` (offset, size, stride and some flags).
9
 
10
pipewire-0.3.51.tar.gz/doc/spa-design.dox -> pipewire-0.3.52.tar.gz/doc/spa-design.dox Changed
31
 
1
@@ -7,7 +7,7 @@
2
 Types are generally divided into two categories:
3
 
4
 - String types: They identify interfaces and highlevel object types.
5
-- integer types: These are enumerations used in the parts where high
6
+- Integer types: These are enumerations used in the parts where high
7
                  performance/ease of use/low space overhead is needed.
8
 
9
 The SPA type is system is statis and very simple but still allows you
10
@@ -15,7 +15,7 @@
11
 
12
 See the type system docs for more info.
13
 
14
-## Error codes
15
+## Error Codes
16
 
17
 SPA uses negative integers as errno style error codes. Functions that return an
18
 int result code generated an error when < 0. `spa_strerror()` can be used to
19
@@ -27,9 +27,9 @@
20
 result code and the sequence number can later be matched to the completion
21
 event.
22
 
23
-## Useful macros
24
+## Useful Macros
25
 
26
 SPA comes with some useful macros defined in `<spa/utils/defs.h>` and a
27
-number of utility functions, see \ref spa_utils
28
+number of utility functions, see \ref spa_utils.
29
 
30
 */
31
pipewire-0.3.51.tar.gz/doc/spa-index.dox -> pipewire-0.3.52.tar.gz/doc/spa-index.dox Changed
64
 
1
@@ -5,30 +5,34 @@
2
 
3
 It is inspired by many other plugin APIs, mostly LV2 and
4
 GStreamer. SPA provides two parts:
5
-- a header-only API with no external dependencies
6
-- a set of support libraries ("plugins") for commonly used functionality
7
+
8
+- A header-only API with no external dependencies.
9
+- A set of support libraries ("plugins") for commonly used functionality.
10
 
11
 The usual approach is that PipeWire and PipeWire clients can use the
12
 header-only functions to interact with the plugins. Those plugins are
13
-usually loaded at runtime (through `dlopen(3)`.
14
+usually loaded at runtime (through `dlopen(3)`).
15
+
16
 
17
-## Motivation
18
+# Motivation
19
 
20
 SPA was designed with the following goals in mind:
21
-- No dependencies, SPA is shipped as a set of header files that have no dependencies except for the standard c library.
22
+
23
+- No dependencies, SPA is shipped as a set of header files that have no dependencies except for the standard C library.
24
 - Very efficient both in space and in time.
25
 - Very configurable and usable in many different environments. All aspects
26
   of the plugin environment can be configured and changed, like logging,
27
-  poll loops, system calls etc.
28
-- Consistent API
29
-- Extensible, new API can be added with minimal effort, existing API can be updated and versioned.
30
+  poll loops, system calls, etc.
31
+- Consistent API.
32
+- Extensible; new API can be added with minimal effort, existing API can be updated and versioned.
33
 
34
 The original user of SPA is PipeWire, which uses SPA to implement the
35
 low-level multimedia processing plugins, device detection, mainloops, CPU
36
-detection and logging, among other things. SPA however can be used outside
37
+detection, logging, among other things. SPA however can be used outside
38
 of PipeWire with minimal problems.
39
 
40
-## The SPA header-only API
41
+
42
+# The SPA Header-Only API
43
 
44
 A very simple example on how SPA headers work are the \ref spa_utils, a set
45
 of utilities commonly required by C projects. SPA functions use the `spa_`
46
@@ -53,7 +57,7 @@
47
 \endcode
48
 
49
 
50
-## SPA Plugins
51
+# SPA Plugins
52
 
53
 SPA plugins are shared libraries (`.so` files) that can be loaded at
54
 runtime. Each library provides one or more "factories", each of which may
55
@@ -68,7 +72,7 @@
56
 Please see \ref page_spa_plugins for the details on how to use SPA plugins.
57
 
58
 
59
-## Further details
60
+# Further details
61
 
62
 - \ref api_spa
63
 - \subpage page_spa_design
64
pipewire-0.3.51.tar.gz/doc/spa-plugins.dox -> pipewire-0.3.52.tar.gz/doc/spa-plugins.dox Changed
166
 
1
@@ -3,19 +3,21 @@
2
 \ref spa_handle "SPA plugins" are dynamically loadable objects that contain objects and interfaces that
3
 can be introspected and used at runtime in any application. This document
4
 introduces the basic concepts of SPA plugins. It first covers using the API
5
-and then talks about implementing new Plugins.
6
+and then talks about implementing new plugins.
7
 
8
 
9
-## Outline
10
+# Outline
11
 
12
 To use a plugin, the following steps are required:
13
-- **load** the shared library
14
-- **enumerate** the available factories
15
-- **enumerate** the interfaces in each factory
16
-- **instantiate** the desired interface
17
-- **use** the interface-specific functions
18
+
19
+- **Load** the shared library.
20
+- **Enumerate** the available factories.
21
+- **Enumerate** the interfaces in each factory.
22
+- **Instantiate** the desired interface.
23
+- **Use** the interface-specific functions.
24
 
25
 In pseudo-code, loading a logger interface looks like this:
26
+
27
 \code{.py}
28
 handle = dlopen("$SPA_PLUGIN_PATH/support/libspa-support.so")
29
 factory_enumeration_func = dlsym(handle, SPA_HANDLE_FACTORY_ENUM_FUNC_NAME)
30
@@ -71,18 +73,18 @@
31
 \endverbatim
32
 
33
 
34
-## Open a plugin
35
+# Open A Plugin
36
 
37
 A plugin is opened with a platform specific API. In this example we use
38
 `dlopen()` as the method used on Linux.
39
 
40
-A plugin always consists of 2 parts, the vendor path and then the .so file.
41
+A plugin always consists of two parts, the vendor path and then the .so file.
42
 
43
 As an example we will load the "support/libspa-support.so" plugin. You will
44
-usually use some mapping between functionality and plugin path, as we'll see
45
+usually use some mapping between functionality and plugin path as we'll see
46
 later, instead of hardcoding the plugin name.
47
 
48
-To dlopen a plugin we then need to prefix the plugin path like this:
49
+To `dlopen` a plugin we then need to prefix the plugin path like this:
50
 
51
 \code{.c}
52
 #define SPA_PLUGIN_PATH    /usr/lib64/spa-0.2/"
53
@@ -105,7 +107,8 @@
54
 
55
 If this symbol is not available, the library is not a valid SPA plugin.
56
 
57
-## Enumerating factories
58
+
59
+# Enumerating Factories
60
 
61
 With the `enum_func` we can now enumerate all the factories in the plugin:
62
 
63
@@ -126,7 +129,7 @@
64
 
65
 We can enumerate the interfaces that we will find on this new object with
66
 the `spa_handle_factory_enum_interface_info()` method. Interface types
67
-are simple strings that uniquely define the interface (See also the type
68
+are simple strings that uniquely define the interface (see also the type
69
 system).
70
 
71
 The name of the factory is a well-known name that describes the functionality
72
@@ -142,7 +145,8 @@
73
 Usually the name will be mapped to a specific plugin. This way an
74
 alternative compatible implementation can be made in a different library.
75
 
76
-## Making a handle
77
+
78
+# Making A Handle
79
 
80
 Once we have a suitable factory, we need to allocate memory for the object
81
 it can create. SPA usually does not allocate memory itself but relies on
82
@@ -173,10 +177,11 @@
83
 
84
 The support parameter is an array of `struct spa_support` items. They
85
 contain a string type and a pointer to extra support objects. This can
86
-be a logging API or a main loop API, for example. Some plugins require
87
+be a logging API or a main loop API for example. Some plugins require
88
 certain support libraries to function.
89
 
90
-## Retrieving an interface
91
+
92
+# Retrieving An Interface
93
 
94
 When a SPA handle is made, you can retrieve any of the interfaces that
95
 it provides:
96
@@ -195,7 +200,7 @@
97
 \endcode
98
 
99
 
100
-## Clearing an object
101
+# Clearing An Object
102
 
103
 After you are done with a handle you can clear it with
104
 `spa_handle_clear()` and you can unload the library with `dlclose()`.
105
@@ -215,7 +220,7 @@
106
 
107
 Interfaces are defined in a header file (for example see
108
 `<spa/support/log.h>` for the logger API). It is a self contained
109
-definition that you can just use in your application after you dlopen()
110
+definition that you can just use in your application after you `dlopen()`
111
 the plugin.
112
 
113
 Some interfaces also provide extra fields in the interface, like the
114
@@ -223,7 +228,8 @@
115
 
116
 See \ref spa_interface for some implementation details on interfaces.
117
 
118
-## SPA Events
119
+
120
+# SPA Events
121
 
122
 Some interfaces will also allow you to register a callback (a hook or
123
 listener) to be notified of events. This is usually when something
124
@@ -270,7 +276,8 @@
125
 spa_hook_remove(&listener);
126
 \endcode
127
 
128
-## API results
129
+
130
+# API Results
131
 
132
 Some interfaces provide API that gives you a list or enumeration of
133
 objects/values. To avoid allocation overhead and ownership problems,
134
@@ -280,8 +287,7 @@
135
 problems. The application can look at the pushed result and keep/copy
136
 only what it wants to keep.
137
 
138
-
139
-### Synchronous results
140
+## Synchronous Results
141
 
142
 Here is an example of enumerating parameters on a node interface.
143
 
144
@@ -319,8 +325,7 @@
145
 spa_hook_remove(&listener);
146
 \endcode
147
 
148
-
149
-### Asynchronous results
150
+## Asynchronous Results
151
 
152
 Asynchronous results are pushed to the application in the same way as
153
 synchronous results, they are just pushed later. You can check that
154
@@ -342,9 +347,9 @@
155
 expected_seq = SPA_RESULT_ASYNC_SEQ(res);
156
 \endcode
157
 
158
-# Implementing a new plugin
159
+# Implementing A New Plugin
160
 
161
-FIXME
162
+***FIXME***
163
 
164
 
165
 
166
pipewire-0.3.51.tar.gz/doc/spa-pod.dox -> pipewire-0.3.52.tar.gz/doc/spa-pod.dox Changed
201
 
1
@@ -3,52 +3,54 @@
2
 \ref spa_pod (plain old data) is a sort of data container. It is comparable to
3
 DBus Variant or LV2 Atom.
4
 
5
-A POD can express nested structures of Objects (with properties), Vectors,
6
-Arrays, sequences and various primitives types. All information in the POD
7
+A POD can express nested structures of objects (with properties), vectors,
8
+arrays, sequences and various primitives types. All information in the POD
9
 is laid out sequentially in memory and can be written directly to
10
 storage or exchanged between processes or threads without additional
11
 marshalling.
12
 
13
 Each POD is made of a 32 bits size followed by a 32 bits type field,
14
-followed by the pod contents. This makes it possible to skip over unknown
15
+followed by the POD contents. This makes it possible to skip over unknown
16
 POD types. The POD start is always aligned to 8 bytes.
17
 
18
-PODs can be efficiently constructed and parsed in real-time threads without
19
+POD's can be efficiently constructed and parsed in real-time threads without
20
 requiring memory allocations.
21
 
22
-PODs use the SPA type system for the basic types and containers. See
23
+POD's use the SPA type system for the basic types and containers. See
24
 the SPA types for more info.
25
 
26
-## Types
27
 
28
-PODs can contain a number of basic SPA types:
29
+# Types
30
 
31
- - `SPA_TYPE_None`: no value or a NULL pointer.
32
- - `SPA_TYPE_Bool`: a boolean value
33
- - `SPA_TYPE_Id`: an enumerated value
34
- - `SPA_TYPE_Int`, `SPA_TYPE_Long`, `SPA_TYPE_Float`, `SPA_TYPE_Double`:
35
- -         various numeral types, 32 and 64 bits.
36
- - `SPA_TYPE_String`: a string
37
- - `SPA_TYPE_Bytes`: a byte array
38
- - `SPA_TYPE_Rectangle`: a rectangle with width and height
39
- - `SPA_TYPE_Fraction`: a fraction with numerator and denominator
40
- - `SPA_TYPE_Bitmap`: an array of bits
41
+POD's can contain a number of basic SPA types:
42
 
43
-PODs can be grouped together in these container types:
44
+- `SPA_TYPE_None`: No value or a NULL pointer.
45
+- `SPA_TYPE_Bool`: A boolean value.
46
+- `SPA_TYPE_Id`: An enumerated value.
47
+- `SPA_TYPE_Int`, `SPA_TYPE_Long`, `SPA_TYPE_Float`, `SPA_TYPE_Double`:
48
+  various numeral types, 32 and 64 bits.
49
+- `SPA_TYPE_String`: A string.
50
+- `SPA_TYPE_Bytes`: A byte array.
51
+- `SPA_TYPE_Rectangle`: A rectangle with width and height.
52
+- `SPA_TYPE_Fraction`: A fraction with numerator and denominator.
53
+- `SPA_TYPE_Bitmap`: An array of bits.
54
 
55
- - `SPA_TYPE_Array`: an array of equal sized objects
56
- - `SPA_TYPE_Struct`: a collection of types and objects
57
- - `SPA_TYPE_Object`: an object with properties
58
- - `SPA_TYPE_Sequence`: a timed sequence of PODs
59
+POD's can be grouped together in these container types:
60
 
61
-PODs can also contain some extra types:
62
+- `SPA_TYPE_Array`: An array of equal sized objects.
63
+- `SPA_TYPE_Struct`: A collection of types and objects.
64
+- `SPA_TYPE_Object`: An object with properties.
65
+- `SPA_TYPE_Sequence`: A timed sequence of POD's.
66
 
67
- - `SPA_TYPE_Pointer`: a typed pointer in memory
68
- - `SPA_TYPE_Fd`: a file descriptor
69
- - `SPA_TYPE_Choice`: a choice of values
70
- - `SPA_TYPE_Pod`: a generic type for the POD itself
71
+POD's can also contain some extra types:
72
 
73
-# Constructing a POD
74
+- `SPA_TYPE_Pointer`: A typed pointer in memory.
75
+- `SPA_TYPE_Fd`: A file descriptor.
76
+- `SPA_TYPE_Choice`: A choice of values.
77
+- `SPA_TYPE_Pod`: A generic type for the POD itself.
78
+
79
+
80
+# Constructing A POD
81
 
82
 A POD is usually constructed with a `struct spa_pod_builder`. The builder
83
 needs to be initialized with a memory region to write into. It is
84
@@ -59,7 +61,7 @@
85
 estimated pretty easily and if the buffer is not large enough, an
86
 appropriate error will be generated.
87
 
88
-The code fragment below initializes a pod builder to write into
89
+The code fragment below initializes a POD builder to write into
90
 the stack allocated buffer.
91
 
92
 \code{.c}
93
@@ -96,7 +98,7 @@
94
 `spa_pod_builder_pop()` returns a reference to the object we completed
95
 on the stack.
96
 
97
-## Using varargs builder.
98
+## Using varargs Builder
99
 
100
 We can also use the following construct to make POD objects:
101
 
102
@@ -116,10 +118,10 @@
103
    SPA_POD_Float(3.1415f));
104
 \endcode
105
 
106
-It's not possible to use the varargs builder to make a Sequence or
107
-Array, use the normal builder methods for that.
108
+It's not possible to use the varargs builder to make a sequence or
109
+array, use the normal builder methods for that.
110
 
111
-## Making objects
112
+## Making Objects
113
 
114
 POD objects are containers for properties and are comparable to JSON
115
 objects.
116
@@ -131,7 +133,7 @@
117
 \endcode
118
 
119
 An object requires an object type (`SPA_TYPE_OBJECT_Props`) and a context
120
-id (`SPA_PARAM_Props`). The object type defines the properties that can be
121
+ID (`SPA_PARAM_Props`). The object type defines the properties that can be
122
 added to the object and their meaning. The SPA type system allows you to
123
 make this connection (See the type system).
124
 
125
@@ -163,23 +165,23 @@
126
    SPA_PROP_frequency, SPA_POD_Float(440.0f));
127
 \endcode
128
 
129
-## Choice values
130
+## Choice Values
131
 
132
 It is possible to express ranges or enumerations of possible
133
 values for properties (and to some extend structs). This is achieved
134
-with Choice values.
135
+with choice values.
136
 
137
 Choice values are really just a choice type and an array of choice values
138
 (of the same type). Depending on the choice type, the array values are
139
 interpreted in different ways:
140
 
141
- * `SPA_CHOICE_None`:   no choice, first value is current
142
- * `SPA_CHOICE_Range`:  range: default, min, max
143
- * `SPA_CHOICE_Step`:   range with step: default, min, max, step
144
- * `SPA_CHOICE_Enum`:   enum: default, alternative,...
145
- * `SPA_CHOICE_Flags`:  bitmask of flags
146
+- `SPA_CHOICE_None`: No choice, first value is current.
147
+- `SPA_CHOICE_Range`: Range: default, min, max.
148
+- `SPA_CHOICE_Step`: Range with step: default, min, max, step.
149
+- `SPA_CHOICE_Enum`: Enum: default, alternative,...
150
+- `SPA_CHOICE_Flags`: Bitmask of flags.
151
 
152
-Let's illustrate this with a Props object that specifies a range of
153
+Let's illustrate this with a props object that specifies a range of
154
 possible values for the frequency:
155
 
156
 \code{.c}
157
@@ -195,8 +197,8 @@
158
 pod = spa_pod_builder_pop(&b, &f);
159
 \endcode
160
 
161
-As you can see, first push the choice as a Range, then the values. A Range
162
-choice expects at least 3 values, the default value, minimum and maximum
163
+As you can see, first push the choice as a range, then the values. A range
164
+choice expects at least three values, the default value, minimum and maximum
165
 values. There is a shortcut for this as well using varargs:
166
 
167
 \code{.c}
168
@@ -205,7 +207,7 @@
169
    SPA_PROP_frequency, SPA_POD_CHOICE_RANGE_Float(440.0f, 110.0f, 880.0f));
170
 \endcode
171
 
172
-## Choice examples
173
+## Choice Examples
174
 
175
 This is a description of a possible `SPA_TYPE_OBJECT_Format` as used when
176
 enumerating allowed formats (`SPA_PARAM_EnumFormat`) in SPA objects:
177
@@ -253,16 +255,17 @@
178
    SPA_FORMAT_AUDIO_channels, SPA_POD_Int(2));
179
 \endcode
180
 
181
-# Parsing a POD
182
 
183
-Parsing a POD usually consists of
184
+# Parsing A POD
185
 
186
- * validating if raw bytes + size can contain a valid pod
187
- * inspecting the type of a pod
188
- * looping over the items in an object or struct
189
- * getting data out of PODs.
190
+Parsing a POD usually consists of:
191
 
192
-## Validating bytes
193
+- Validating if raw bytes + size can contain a valid POD.
194
+- Inspecting the type of a POD.
195
+- Looping over the items in an object or struct.
196
+- Getting data out of POD's.
197
+
198
+## Validating Bytes
199
 
200
 Use `spa_pod_from_data()` to check if maxsize of bytes in data contain
201
pipewire-0.3.51.tar.gz/doc/tutorial.dox -> pipewire-0.3.52.tar.gz/doc/tutorial.dox Changed
11
 
1
@@ -10,7 +10,8 @@
2
 - \subpage page_tutorial5
3
 - \subpage page_tutorial6
4
 
5
-## More example programs
6
+
7
+# More Example Programs
8
 
9
 - \ref audio-src.c "": \snippet{doc} audio-src.c title
10
 - \ref audio-dsp-filter.c "": \snippet{doc} audio-dsp-filter.c title
11
pipewire-0.3.51.tar.gz/doc/tutorial1.dox -> pipewire-0.3.52.tar.gz/doc/tutorial1.dox Changed
31
 
1
@@ -1,4 +1,4 @@
2
-/** \page page_tutorial1 Tutorial - Part 1: Getting started
3
+/** \page page_tutorial1 Tutorial - Part 1: Getting Started
4
 
5
 
6
 \ref page_tutorial "Index" | \ref page_tutorial2
7
@@ -7,7 +7,8 @@
8
 Use this tutorial to get started and help you set up your development
9
 environment.
10
 
11
-## Initialization
12
+
13
+# Initialization
14
 
15
 Let get started with the simplest application.
16
 
17
@@ -15,10 +16,11 @@
18
 
19
 Before you can use any PipeWire functions, you need to call `pw_init()`.
20
 
21
-## Compilation
22
+
23
+# Compilation
24
 
25
 PipeWire provides a pkg-config file named `libpipewire-0.3` (note: the version
26
-suffix may change with future releases of pipewire).
27
+suffix may change with future releases of PipeWire).
28
 To compile the simple test application, copy it into a test1.c file and
29
 use pkg-config to provide the required dependencies:
30
 
31
pipewire-0.3.51.tar.gz/doc/tutorial2.dox -> pipewire-0.3.52.tar.gz/doc/tutorial2.dox Changed
13
 
1
@@ -1,4 +1,4 @@
2
-/** \page page_tutorial2 Tutorial - Part 2: Enumerating objects
3
+/** \page page_tutorial2 Tutorial - Part 2: Enumerating Objects
4
 
5
 \ref page_tutorial1 | \ref page_tutorial "Index" | \ref page_tutorial3
6
 
7
@@ -125,4 +125,5 @@
8
 exit our application after we received all server objects.
9
 
10
 \ref page_tutorial1 | \ref page_tutorial "Index" | \ref page_tutorial3
11
+
12
 */
13
pipewire-0.3.51.tar.gz/doc/tutorial3.dox -> pipewire-0.3.52.tar.gz/doc/tutorial3.dox Changed
7
 
1
@@ -1,4 +1,4 @@
2
-/** \page page_tutorial3 Tutorial - Part 3: Forcing a roundtrip
3
+/** \page page_tutorial3 Tutorial - Part 3: Forcing A Roundtrip
4
 
5
 \ref page_tutorial2 | \ref page_tutorial "Index" | \ref page_tutorial4
6
 
7
pipewire-0.3.51.tar.gz/doc/tutorial4.dox -> pipewire-0.3.52.tar.gz/doc/tutorial4.dox Changed
67
 
1
@@ -1,4 +1,4 @@
2
-/** \page page_tutorial4 Tutorial - Part 4: Playing a tone
3
+/** \page page_tutorial4 Tutorial - Part 4: Playing A Tone
4
 
5
 \ref page_tutorial3 | \ref page_tutorial "Index" | \ref page_tutorial5
6
 
7
@@ -57,13 +57,12 @@
8
 
9
 In the properties we need to give as much information about the stream as we
10
 can so that the session manager can make good decisions about how and where
11
-to route this stream. There are 3 important properties to configure:
12
+to route this stream. There are three important properties to configure:
13
 
14
-* `PW_KEY_MEDIA_TYPE`      The media type, like Audio, Video, Midi
15
-* `pw_KEY_MEDIA_CATEGORY`  The category, like Playback, Capture, Duplex, Monitor
16
-* `PW_KEY_MEDIA_ROLE`      The media role, like Movie, Music, Camera, Screen,
17
-                   Communication, Game, Notification, DSP,
18
-                   Production, Accessibility, Test
19
+- `PW_KEY_MEDIA_TYPE`: The media type; like Audio, Video, MIDI.
20
+- `PW_KEY_MEDIA_CATEGORY`: The category; like Playback, Capture, Duplex, Monitor.
21
+- `PW_KEY_MEDIA_ROLE`: The media role; like Movie, Music, Camera, Screen,
22
+  Communication, Game, Notification, DSP, Production, Accessibility, Test.
23
 
24
 The properties are owned by the stream and freed when the stream is destroyed
25
 later.
26
@@ -122,15 +121,14 @@
27
 To connect we specify that we have a `PW_DIRECTION_OUTPUT` stream. `PW_ID_ANY`
28
 means that we are ok with connecting to any consumer. Next we set some flags:
29
 
30
-* `PW_STREAM_FLAG_AUTOCONNECT`  automatically connect this stream. This instructs
31
-                                the session manager to link us to some consumer.
32
-* `PW_STREAM_FLAG_MAP_BUFFERS` mmap the buffers for us so we can access the
33
-                                memory. If you don't set these flags you have
34
-               either work with the fd or mmap yourself.
35
-* `PW_STREAM_FLAG_RT_PROCESS`  Run the process function in the realtime thread.
36
-                       Only use this if the process function only
37
-               uses functions that are realtime safe, this means
38
-               no allocation or file access or any locking.
39
+- `PW_STREAM_FLAG_AUTOCONNECT`: Automatically connect this stream. This instructs
40
+  the session manager to link us to some consumer.
41
+- `PW_STREAM_FLAG_MAP_BUFFERS`:    mmap the buffers for us so we can access the
42
+  memory. If you don't set these flags you have either work with the fd or mmap 
43
+  yourself.
44
+- `PW_STREAM_FLAG_RT_PROCESS`: Run the process function in the realtime thread.
45
+  Only use this if the process function only uses functions that are realtime 
46
+  safe, this means no allocation or file access or any locking.
47
 
48
 And last we pass the extra parameters for our stream. Here we only have the
49
 allowed formats (`SPA_PARAM_EnumFormat`).
50
@@ -140,11 +138,11 @@
51
 
52
 The main program flow of the process function is:
53
 
54
-* `pw_stream_dequeue_buffer()` to obtain a buffer to write into.
55
-* Get pointers in buffer memory to write to
56
-* write data into buffer
57
-* adjust buffer with number of written bytes, offset, stride,
58
-* `pw_stream_queue_buffer()` to queue the buffer for playback.
59
+- `pw_stream_dequeue_buffer()` to obtain a buffer to write into.
60
+- Get pointers in buffer memory to write to.
61
+- Write data into buffer.
62
+- Adjust buffer with number of written bytes, offset, stride.
63
+- `pw_stream_queue_buffer()` to queue the buffer for playback.
64
 
65
 \snippet tutorial4.c on_process
66
 
67
pipewire-0.3.51.tar.gz/doc/tutorial5.dox -> pipewire-0.3.52.tar.gz/doc/tutorial5.dox Changed
24
 
1
@@ -1,4 +1,4 @@
2
-/** \page page_tutorial5 Tutorial - Part 5: Capturing video frames
3
+/** \page page_tutorial5 Tutorial - Part 5: Capturing Video Frames
4
 
5
 \ref page_tutorial4 | \ref page_tutorial "Index" | \ref page_tutorial6
6
 
7
@@ -141,7 +141,6 @@
8
 And last we pass the extra parameters for our stream. Here we only have the
9
 allowed formats (`SPA_PARAM_EnumFormat`).
10
 
11
-
12
 Running the mainloop will start the connection and negotiation process.
13
 First our `param_changed` event will be called with the format that was
14
 negotiated between our stream and the camera. This is always something that
15
@@ -160,7 +159,7 @@
16
        return;
17
 \endcode
18
 
19
-First check if there is a param. A NULL param means that it is cleared. The id
20
+First check if there is a param. A NULL param means that it is cleared. The ID
21
 of the param tells you what param it is. We are only interested in Format
22
 param (`SPA_PARAM_Format`).
23
 
24
pipewire-0.3.51.tar.gz/doc/tutorial6.dox -> pipewire-0.3.52.tar.gz/doc/tutorial6.dox Changed
7
 
1
@@ -1,4 +1,4 @@
2
-/** \page page_tutorial6 Tutorial - Part 6: Binding objects
3
+/** \page page_tutorial6 Tutorial - Part 6: Binding Objects
4
 
5
 \ref page_tutorial5 | \ref page_tutorial "Index"
6
 
7
pipewire-0.3.51.tar.gz/man/pw-cat.1.rst.in -> pipewire-0.3.52.tar.gz/man/pw-cat.1.rst.in Changed
71
 
1
@@ -11,11 +11,12 @@
2
 SYNOPSIS
3
 ========
4
 
5
-| **pw-cat** *options* *FILE*
6
-| **pw-play** *options* *FILE*
7
-| **pw-record** *options* *FILE*
8
-| **pw-midiplay** *options* *FILE*
9
-| **pw-midirecord** *options* *FILE*
10
+| **pw-cat** *options* *FILE* \| -
11
+| **pw-play** *options* *FILE* \| -
12
+| **pw-record** *options* *FILE* \| -
13
+| **pw-midiplay** *options* *FILE* \| -
14
+| **pw-midirecord** *options* *FILE* \| -
15
+| **pw-dsdplay** *options* *FILE* \| -
16
 
17
 DESCRIPTION
18
 ===========
19
@@ -23,7 +24,14 @@
20
 **pw-cat** is a simple tool for playing back or
21
 capturing raw or encoded media files on a PipeWire
22
 server. It understands all audio file formats supported by
23
-``libsndfile``.
24
+``libsndfile`` for PCM capture and playback.
25
+
26
+It understands standard MIDI files for playback and recording,
27
+
28
+DSD playback is supported with the DSF file format.
29
+
30
+When the *FILE* is - input and output will be from STDIN and
31
+STDOUT respectively.
32
 
33
 OPTIONS
34
 =======
35
@@ -53,6 +61,10 @@
36
   MIDI mode. *FILE* is a MIDI file. If the tool is called under the name
37
   **pw-midiplay** or **pw-midirecord** this is the default.
38
 
39
+-d | --dsd
40
+  DSD mode. *FILE* is a DSF file. If the tool is called under the name
41
+  **pw-dsdplay** this is the default.
42
+
43
 --media-type=VALUE
44
   Set the media type property (default Audio/Midi depending on mode).
45
   The media type is used by the session manager to select a suitable target
46
@@ -97,6 +109,9 @@
47
   If no units are given, the latency value is samples with the samplerate
48
   of the file.
49
 
50
+-P | --properties=VALUE
51
+  Set extra stream properties as a JSON object.
52
+
53
 -q | --quality=VALUE
54
   Resampler quality. When the samplerate of the source or
55
   destination file does not match the samplerate of the server, the
56
@@ -129,11 +144,13 @@
57
 
58
 --format=VALUE
59
   The sample format to use. One of:
60
-  **s8**, **s16** (default), **s24**, **s32**,
61
+  **u8**, **s8**, **s16** (default), **s24**, **s32**,
62
   **f32**, **f64**.
63
 
64
 --volume=VALUE
65
   The stream volume, default 1.000.
66
+  Depending on the locale you have configured, "," or "." may be
67
+  used as a decimal seperator. Check with **locale** command.
68
 
69
 AUTHORS
70
 =======
71
pipewire-0.3.51.tar.gz/meson.build -> pipewire-0.3.52.tar.gz/meson.build Changed
16
 
1
@@ -1,5 +1,5 @@
2
 project('pipewire', 'c' ,
3
-  version : '0.3.51',
4
+  version : '0.3.52',
5
   license :  'MIT', 'LGPL-2.1-or-later', 'GPL-2.0-only' ,
6
   meson_version : '>= 0.59.0',
7
   default_options :  'warning_level=3',
8
@@ -375,6 +375,7 @@
9
   'gettid', '#include <unistd.h>', '-D_GNU_SOURCE', ,
10
   'memfd_create', '#include <sys/mman.h>', '-D_GNU_SOURCE', ,
11
   'getrandom', '#include <stddef.h>\n#include <sys/random.h>', '-D_GNU_SOURCE', ,
12
+  'reallocarray', '#include <stdlib.h>', '-D_GNU_SOURCE', ,
13
   'sigabbrev_np', '#include <string.h>', '-D_GNU_SOURCE', ,
14
   'XSetIOErrorExitHandler', '#include <X11/Xlib.h>', , x11_dep,
15
 
16
pipewire-0.3.51.tar.gz/meson_options.txt -> pipewire-0.3.52.tar.gz/meson_options.txt Changed
12
 
1
@@ -112,6 +112,10 @@
2
         description: 'Enable Fraunhofer FDK AAC open source codec implementation',
3
         type: 'feature',
4
         value: 'auto')
5
+option('bluez5-codec-lc3plus',
6
+        description: 'Enable LC3plus open source codec implementation',
7
+        type: 'feature',
8
+        value: 'auto')
9
 option('control',
10
        description: 'Enable control spa plugin integration',
11
        type: 'feature',
12
pipewire-0.3.51.tar.gz/pipewire-alsa/alsa-plugins/pcm_pipewire.c -> pipewire-0.3.52.tar.gz/pipewire-alsa/alsa-plugins/pcm_pipewire.c Changed
45
 
1
@@ -721,6 +721,35 @@
2
    return 0;
3
 }
4
 
5
+static int snd_pcm_pipewire_sw_params(snd_pcm_ioplug_t * io,
6
+               snd_pcm_sw_params_t * sw_params)
7
+{
8
+   snd_pcm_pipewire_t *pw = io->private_data;
9
+
10
+   if (pw->stream) {
11
+       snd_pcm_uframes_t min_avail;
12
+       snd_pcm_sw_params_get_avail_min( sw_params, &min_avail);
13
+       snd_pcm_sw_params_get_boundary(sw_params, &pw->boundary);
14
+       if (min_avail != pw->min_avail) {
15
+           char latency64;
16
+           struct spa_dict_item item1;
17
+           uint32_t min_period = (MIN_PERIOD * io->rate / 48000);
18
+
19
+           pw->min_avail = SPA_MAX(min_avail, min_period);
20
+
21
+           spa_scnprintf(latency, sizeof(latency), "%lu/%u", pw->min_avail, io->rate);
22
+           item0 = SPA_DICT_ITEM_INIT(PW_KEY_NODE_LATENCY, latency);
23
+
24
+           pw_log_debug("%p: sw_params update props %p %ld", pw, pw->stream, pw->min_avail);
25
+           pw_stream_update_properties(pw->stream, &SPA_DICT_INIT(item, 1));
26
+       }
27
+   } else {
28
+       pw_log_debug("%p: sw_params pre-prepare noop", pw);
29
+   }
30
+
31
+   return 0;
32
+}
33
+
34
 struct chmap_info {
35
    enum snd_pcm_chmap_position pos;
36
    enum spa_audio_channel channel;
37
@@ -855,6 +884,7 @@
38
    .poll_descriptors = snd_pcm_pipewire_poll_descriptors,
39
    .poll_revents = snd_pcm_pipewire_poll_revents,
40
    .hw_params = snd_pcm_pipewire_hw_params,
41
+   .sw_params = snd_pcm_pipewire_sw_params,
42
    .set_chmap = snd_pcm_pipewire_set_chmap,
43
    .get_chmap = snd_pcm_pipewire_get_chmap,
44
    .query_chmaps = snd_pcm_pipewire_query_chmaps,
45
pipewire-0.3.51.tar.gz/pipewire-jack/src/metadata.c -> pipewire-0.3.52.tar.gz/pipewire-jack/src/metadata.c Changed
10
 
1
@@ -120,7 +120,7 @@
2
 
3
    if (desc->property_cnt == desc->property_size) {
4
        ns = desc->property_size > 0 ? desc->property_size * 2 : 8;
5
-       np = reallocarray(desc->properties, ns, sizeof(*prop));
6
+       np = pw_reallocarray(desc->properties, ns, sizeof(*prop));
7
        if (np == NULL)
8
            return NULL;
9
        desc->property_size = ns;
10
pipewire-0.3.51.tar.gz/pipewire-jack/src/pipewire-jack.c -> pipewire-0.3.52.tar.gz/pipewire-jack/src/pipewire-jack.c Changed
190
 
1
@@ -3205,6 +3205,30 @@
2
    varargs_parse(client, options, ap);
3
    va_end(ap);
4
 
5
+   snprintf(client->name, sizeof(client->name), "pw-%s", client_name);
6
+
7
+   pthread_mutex_init(&client->context.lock, NULL);
8
+   spa_list_init(&client->context.objects);
9
+
10
+   client->node_id = SPA_ID_INVALID;
11
+
12
+   client->buffer_frames = (uint32_t)-1;
13
+   client->sample_rate = (uint32_t)-1;
14
+   client->latency = SPA_FRACTION(-1, -1);
15
+
16
+   spa_list_init(&client->mix);
17
+   spa_list_init(&client->free_mix);
18
+
19
+   spa_list_init(&client->free_ports);
20
+   pw_map_init(&client->portsSPA_DIRECTION_INPUT, 32, 32);
21
+   pw_map_init(&client->portsSPA_DIRECTION_OUTPUT, 32, 32);
22
+
23
+   spa_list_init(&client->links);
24
+   client->driver_id = SPA_ID_INVALID;
25
+
26
+   spa_list_init(&client->rt.target_links);
27
+   pthread_mutex_init(&client->rt_lock, NULL);
28
+
29
    if (client->server_name != NULL &&
30
        spa_streq(client->server_name, "default"))
31
        client->server_name = NULL;
32
@@ -3219,8 +3243,6 @@
33
    if (client->props == NULL)
34
        goto no_props;
35
 
36
-   client->node_id = SPA_ID_INVALID;
37
-   snprintf(client->name, sizeof(client->name), "pw-%s", client_name);
38
    client->context.loop = pw_thread_loop_new(client->name, NULL);
39
    client->context.l = pw_thread_loop_get_loop(client->context.loop);
40
    client->context.context = pw_context_new(
41
@@ -3239,30 +3261,6 @@
42
    pw_context_conf_section_match_rules(client->context.context, "jack.rules",
43
            &client->props->dict, execute_match, client);
44
 
45
-   client->show_monitor = pw_properties_get_bool(client->props, "jack.show-monitor", true);
46
-   client->merge_monitor = pw_properties_get_bool(client->props, "jack.merge-monitor", false);
47
-   client->short_name = pw_properties_get_bool(client->props, "jack.short-name", false);
48
-   client->filter_name = pw_properties_get_bool(client->props, "jack.filter-name", false);
49
-   client->locked_process = pw_properties_get_bool(client->props, "jack.locked-process", true);
50
-   client->default_as_system = pw_properties_get_bool(client->props, "jack.default-as-system", false);
51
-
52
-   client->self_connect_mode = SELF_CONNECT_ALLOW;
53
-   if ((str = pw_properties_get(client->props, "jack.self-connect-mode")) != NULL) {
54
-       if (spa_streq(str, "fail-external"))
55
-           client->self_connect_mode = SELF_CONNECT_FAIL_EXT;
56
-       else if (spa_streq(str, "ignore-external"))
57
-           client->self_connect_mode = SELF_CONNECT_IGNORE_EXT;
58
-       else if (spa_streq(str, "fail-all"))
59
-           client->self_connect_mode = SELF_CONNECT_FAIL_ALL;
60
-       else if (spa_streq(str, "ignore-all"))
61
-           client->self_connect_mode = SELF_CONNECT_IGNORE_ALL;
62
-   }
63
-   client->rt_max = pw_properties_get_int32(client->props, "rt.prio", DEFAULT_RT_MAX);
64
-
65
-   pthread_mutex_init(&client->context.lock, NULL);
66
-   pthread_mutex_init(&client->rt_lock, NULL);
67
-   spa_list_init(&client->context.objects);
68
-
69
    support = pw_context_get_support(client->context.context, &n_support);
70
 
71
    mix2 = mix2_c;
72
@@ -3292,20 +3290,6 @@
73
            SPA_TYPE_INTERFACE_ThreadUtils,
74
            &client->context.thread_utils);
75
 
76
-   spa_list_init(&client->links);
77
-   spa_list_init(&client->rt.target_links);
78
-
79
-   client->buffer_frames = (uint32_t)-1;
80
-   client->sample_rate = (uint32_t)-1;
81
-   client->latency = SPA_FRACTION(-1, -1);
82
-
83
-        spa_list_init(&client->mix);
84
-        spa_list_init(&client->free_mix);
85
-
86
-   pw_map_init(&client->portsSPA_DIRECTION_INPUT, 32, 32);
87
-   pw_map_init(&client->portsSPA_DIRECTION_OUTPUT, 32, 32);
88
-   spa_list_init(&client->free_ports);
89
-
90
    pw_thread_loop_start(client->context.loop);
91
 
92
    pw_thread_loop_lock(client->context.loop);
93
@@ -3393,6 +3377,26 @@
94
            0, NULL, &client->info);
95
    client->info.change_mask = 0;
96
 
97
+   client->show_monitor = pw_properties_get_bool(client->props, "jack.show-monitor", true);
98
+   client->merge_monitor = pw_properties_get_bool(client->props, "jack.merge-monitor", false);
99
+   client->short_name = pw_properties_get_bool(client->props, "jack.short-name", false);
100
+   client->filter_name = pw_properties_get_bool(client->props, "jack.filter-name", false);
101
+   client->locked_process = pw_properties_get_bool(client->props, "jack.locked-process", true);
102
+   client->default_as_system = pw_properties_get_bool(client->props, "jack.default-as-system", false);
103
+
104
+   client->self_connect_mode = SELF_CONNECT_ALLOW;
105
+   if ((str = pw_properties_get(client->props, "jack.self-connect-mode")) != NULL) {
106
+       if (spa_streq(str, "fail-external"))
107
+           client->self_connect_mode = SELF_CONNECT_FAIL_EXT;
108
+       else if (spa_streq(str, "ignore-external"))
109
+           client->self_connect_mode = SELF_CONNECT_IGNORE_EXT;
110
+       else if (spa_streq(str, "fail-all"))
111
+           client->self_connect_mode = SELF_CONNECT_FAIL_ALL;
112
+       else if (spa_streq(str, "ignore-all"))
113
+           client->self_connect_mode = SELF_CONNECT_IGNORE_ALL;
114
+   }
115
+   client->rt_max = pw_properties_get_int32(client->props, "rt.prio", DEFAULT_RT_MAX);
116
+
117
    if (status)
118
        *status = 0;
119
 
120
@@ -3432,7 +3436,7 @@
121
 exit_unlock:
122
    pw_thread_loop_unlock(client->context.loop);
123
 exit:
124
-   free(client);
125
+   jack_client_close((jack_client_t *) client);
126
    return NULL;
127
 disabled:
128
    if (status)
129
@@ -3467,20 +3471,29 @@
130
 
131
    res = jack_deactivate(client);
132
 
133
-   pw_thread_loop_stop(c->context.loop);
134
+   if (c->context.loop)
135
+       pw_thread_loop_stop(c->context.loop);
136
 
137
    if (c->registry) {
138
        spa_hook_remove(&c->registry_listener);
139
        pw_proxy_destroy((struct pw_proxy*)c->registry);
140
    }
141
    if (c->metadata && c->metadata->proxy) {
142
+       spa_hook_remove(&c->metadata->listener);
143
+       spa_hook_remove(&c->metadata->proxy_listener);
144
        pw_proxy_destroy((struct pw_proxy*)c->metadata->proxy);
145
    }
146
-   spa_hook_remove(&c->core_listener);
147
-   pw_core_disconnect(c->core);
148
-   pw_context_destroy(c->context.context);
149
 
150
-   pw_thread_loop_destroy(c->context.loop);
151
+   if (c->core) {
152
+       spa_hook_remove(&c->core_listener);
153
+       pw_core_disconnect(c->core);
154
+   }
155
+
156
+   if (c->context.context)
157
+       pw_context_destroy(c->context.context);
158
+
159
+   if (c->context.loop)
160
+       pw_thread_loop_destroy(c->context.loop);
161
 
162
    pw_log_debug("%p: free", client);
163
 
164
@@ -5768,17 +5781,21 @@
165
 int jack_set_sync_timeout (jack_client_t *client,
166
               jack_time_t timeout)
167
 {
168
+   int res = 0;
169
    struct client *c = (struct client *) client;
170
    struct pw_node_activation *a;
171
 
172
    spa_return_val_if_fail(c != NULL, -EINVAL);
173
 
174
-   if ((a = c->activation) == NULL)
175
-       return -EIO;
176
+   pw_thread_loop_lock(c->context.loop);
177
 
178
-   ATOMIC_STORE(a->sync_timeout, timeout);
179
+   if ((a = c->activation) == NULL)
180
+       res = -EIO;
181
+   else
182
+       a->sync_timeout = timeout;
183
+   pw_thread_loop_unlock(c->context.loop);
184
 
185
-   return 0;
186
+   return res;
187
 }
188
 
189
 SPA_EXPORT
190
pipewire-0.3.51.tar.gz/po/pl.po -> pipewire-0.3.52.tar.gz/po/pl.po Changed
201
 
1
@@ -8,8 +8,8 @@
2
 "Project-Id-Version: pipewire\n"
3
 "Report-Msgid-Bugs-To: https://gitlab.freedesktop.org/pipewire/pipewire/-/"
4
 "issues\n"
5
-"POT-Creation-Date: 2022-02-13 15:33+0000\n"
6
-"PO-Revision-Date: 2022-03-13 12:05+0100\n"
7
+"POT-Creation-Date: 2022-05-20 15:26+0000\n"
8
+"PO-Revision-Date: 2022-05-21 12:49+0200\n"
9
 "Last-Translator: Piotr Drąg <piotrdrag@gmail.com>\n"
10
 "Language-Team: Polish <community-poland@mozilla.org>\n"
11
 "Language: pl\n"
12
@@ -19,7 +19,7 @@
13
 "Plural-Forms: nplurals=3; plural=n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 "
14
 "|| n%100>=20) ? 1 : 2;\n"
15
 
16
-#: src/daemon/pipewire.c:45
17
+#: src/daemon/pipewire.c:46
18
 #, c-format
19
 msgid ""
20
 "%s options\n"
21
@@ -41,8 +41,8 @@
22
 msgid "Start the PipeWire Media System"
23
 msgstr "Uruchomienie systemu multimediów PipeWire"
24
 
25
-#: src/modules/module-protocol-pulse/modules/module-tunnel-sink.c:188
26
-#: src/modules/module-protocol-pulse/modules/module-tunnel-source.c:188
27
+#: src/modules/module-protocol-pulse/modules/module-tunnel-sink.c:183
28
+#: src/modules/module-protocol-pulse/modules/module-tunnel-source.c:183
29
 #, c-format
30
 msgid "Tunnel to %s/%s"
31
 msgstr "Tunel do %s/%s"
32
@@ -51,7 +51,7 @@
33
 msgid "Dummy Output"
34
 msgstr "Głuche wyjście"
35
 
36
-#: src/modules/module-pulse-tunnel.c:536
37
+#: src/modules/module-pulse-tunnel.c:639
38
 #, c-format
39
 msgid "Tunnel for %s@%s"
40
 msgstr "Tunel dla %s@%s"
41
@@ -70,22 +70,22 @@
42
 msgid "%s on %s"
43
 msgstr "%s na %s"
44
 
45
-#: src/tools/pw-cat.c:1075
46
+#: src/tools/pw-cat.c:872
47
 #, c-format
48
 msgid ""
49
-"%s options <file>\n"
50
+"%s options <file>|-\n"
51
 "  -h, --help                            Show this help\n"
52
 "      --version                         Show version\n"
53
 "  -v, --verbose                         Enable verbose operations\n"
54
 "\n"
55
 msgstr ""
56
-"%s opcje <plik>\n"
57
+"%s opcje <plik>|-\n"
58
 "  -h, --help                            Wyświetla tę pomoc\n"
59
 "      --version                         Wyświetla wersję\n"
60
 "  -v, --verbose                         Wyświetla więcej komunikatów\n"
61
 "\n"
62
 
63
-#: src/tools/pw-cat.c:1082
64
+#: src/tools/pw-cat.c:879
65
 #, c-format
66
 msgid ""
67
 "  -R, --remote                          Remote daemon name\n"
68
@@ -99,7 +99,7 @@
69
 "                                          or direct samples (256)\n"
70
 "                                          the rate is the one of the source "
71
 "file\n"
72
-"      --list-targets                    List available targets for --target\n"
73
+"  -P  --properties                      Set node properties\n"
74
 "\n"
75
 msgstr ""
76
 "  -R, --remote                          Nazwa zdalnej usługi\n"
77
@@ -119,11 +119,10 @@
78
 "                                          lub bezpośrednie próbki (256)\n"
79
 "                                          częstotliwość jest z pliku "
80
 "źródłowego\n"
81
-"      --list-targets                    Wyświetla listę dostępnych elementów "
82
-"docelowych dla --target\n"
83
+"  -P  --properties                      Ustawia właściwości węzła\n"
84
 "\n"
85
 
86
-#: src/tools/pw-cat.c:1100
87
+#: src/tools/pw-cat.c:897
88
 #, c-format
89
 msgid ""
90
 "      --rate                            Sample rate (req. for rec) (default "
91
@@ -159,7 +158,7 @@
92
 "(domyślnie %d)\n"
93
 "\n"
94
 
95
-#: src/tools/pw-cat.c:1117
96
+#: src/tools/pw-cat.c:914
97
 msgid ""
98
 "  -p, --playback                        Playback mode\n"
99
 "  -r, --record                          Recording mode\n"
100
@@ -173,7 +172,7 @@
101
 "  -d, --dsd                             Tryb DSD\n"
102
 "\n"
103
 
104
-#: src/tools/pw-cli.c:3050
105
+#: src/tools/pw-cli.c:3139
106
 #, c-format
107
 msgid ""
108
 "%s options command\n"
109
@@ -196,7 +195,7 @@
110
 msgstr "Dźwięk w zastosowaniach profesjonalnych"
111
 
112
 #: spa/plugins/alsa/acp/acp.c:444 spa/plugins/alsa/acp/alsa-mixer.c:4648
113
-#: spa/plugins/bluez5/bluez5-device.c:1159
114
+#: spa/plugins/bluez5/bluez5-device.c:1161
115
 msgid "Off"
116
 msgstr "Wyłączone"
117
 
118
@@ -223,7 +222,7 @@
119
 
120
 #: spa/plugins/alsa/acp/alsa-mixer.c:2657
121
 #: spa/plugins/alsa/acp/alsa-mixer.c:2741
122
-#: spa/plugins/bluez5/bluez5-device.c:1328
123
+#: spa/plugins/bluez5/bluez5-device.c:1330
124
 msgid "Microphone"
125
 msgstr "Mikrofon"
126
 
127
@@ -289,7 +288,7 @@
128
 msgstr "Brak podbicia basów"
129
 
130
 #: spa/plugins/alsa/acp/alsa-mixer.c:2672
131
-#: spa/plugins/bluez5/bluez5-device.c:1333
132
+#: spa/plugins/bluez5/bluez5-device.c:1335
133
 msgid "Speaker"
134
 msgstr "Głośnik"
135
 
136
@@ -404,7 +403,7 @@
137
 
138
 #: spa/plugins/alsa/acp/alsa-mixer.c:4484
139
 #: spa/plugins/alsa/acp/alsa-mixer.c:4642
140
-#: spa/plugins/bluez5/bluez5-device.c:1318
141
+#: spa/plugins/bluez5/bluez5-device.c:1320
142
 msgid "Headset"
143
 msgstr "Słuchawki z mikrofonem"
144
 
145
@@ -518,12 +517,12 @@
146
 msgid "Mono Chat + 7.1 Surround"
147
 msgstr "Rozmowa mono + przestrzenne 7.1"
148
 
149
-#: spa/plugins/alsa/acp/alsa-mixer.c:4750
150
+#: spa/plugins/alsa/acp/alsa-mixer.c:4754
151
 #, c-format
152
 msgid "%s Output"
153
 msgstr "Wyjście %s"
154
 
155
-#: spa/plugins/alsa/acp/alsa-mixer.c:4757
156
+#: spa/plugins/alsa/acp/alsa-mixer.c:4761
157
 #, c-format
158
 msgid "%s Input"
159
 msgstr "Wejście %s"
160
@@ -628,61 +627,61 @@
161
 msgid "Modem"
162
 msgstr "Modem"
163
 
164
-#: spa/plugins/bluez5/bluez5-device.c:1170
165
+#: spa/plugins/bluez5/bluez5-device.c:1172
166
 msgid "Audio Gateway (A2DP Source & HSP/HFP AG)"
167
 msgstr "Bramka dźwięku (źródło A2DP i AG HSP/HFP)"
168
 
169
-#: spa/plugins/bluez5/bluez5-device.c:1195
170
+#: spa/plugins/bluez5/bluez5-device.c:1197
171
 #, c-format
172
 msgid "High Fidelity Playback (A2DP Sink, codec %s)"
173
 msgstr "Odtwarzanie o wysokiej dokładności (odpływ A2DP, kodek %s)"
174
 
175
-#: spa/plugins/bluez5/bluez5-device.c:1198
176
+#: spa/plugins/bluez5/bluez5-device.c:1200
177
 #, c-format
178
 msgid "High Fidelity Duplex (A2DP Source/Sink, codec %s)"
179
 msgstr "Dupleks o wysokiej dokładności (źródło/odpływ A2DP, kodek %s)"
180
 
181
-#: spa/plugins/bluez5/bluez5-device.c:1206
182
+#: spa/plugins/bluez5/bluez5-device.c:1208
183
 msgid "High Fidelity Playback (A2DP Sink)"
184
 msgstr "Odtwarzanie o wysokiej dokładności (odpływ A2DP)"
185
 
186
-#: spa/plugins/bluez5/bluez5-device.c:1208
187
+#: spa/plugins/bluez5/bluez5-device.c:1210
188
 msgid "High Fidelity Duplex (A2DP Source/Sink)"
189
 msgstr "Dupleks o wysokiej dokładności (źródło/odpływ A2DP)"
190
 
191
-#: spa/plugins/bluez5/bluez5-device.c:1236
192
+#: spa/plugins/bluez5/bluez5-device.c:1238
193
 #, c-format
194
 msgid "Headset Head Unit (HSP/HFP, codec %s)"
195
 msgstr "Jednostka główna słuchawek z mikrofonem (HSP/HFP, kodek %s)"
196
 
197
-#: spa/plugins/bluez5/bluez5-device.c:1241
198
+#: spa/plugins/bluez5/bluez5-device.c:1243
199
 msgid "Headset Head Unit (HSP/HFP)"
200
 msgstr "Jednostka główna słuchawek z mikrofonem (HSP/HFP)"
201
pipewire-0.3.51.tar.gz/po/sv.po -> pipewire-0.3.52.tar.gz/po/sv.po Changed
201
 
1
@@ -19,8 +19,8 @@
2
 "Project-Id-Version: pipewire\n"
3
 "Report-Msgid-Bugs-To: https://gitlab.freedesktop.org/pipewire/pipewire/-/"
4
 "issues\n"
5
-"POT-Creation-Date: 2022-04-13 15:28+0000\n"
6
-"PO-Revision-Date: 2022-04-15 22:03+0200\n"
7
+"POT-Creation-Date: 2022-05-20 15:26+0000\n"
8
+"PO-Revision-Date: 2022-05-23 11:01+0200\n"
9
 "Last-Translator: Anders Jonsson <anders.jonsson@norsjovallen.se>\n"
10
 "Language-Team: Swedish <tp-sv@listor.tp-sv.se>\n"
11
 "Language: sv\n"
12
@@ -38,7 +38,7 @@
13
 "      --version                         Show version\n"
14
 "  -c, --config                          Load config (Default %s)\n"
15
 msgstr ""
16
-"%s options\n"
17
+"%s flaggor\n"
18
 "  -h, --help                            Visa denna hjälp\n"
19
 "      --version                         Visa version\n"
20
 "  -c, --config                          Läs in konfig (Standard %s)\n"
21
@@ -61,41 +61,41 @@
22
 msgid "Dummy Output"
23
 msgstr "Attrapputgång"
24
 
25
-#: src/modules/module-pulse-tunnel.c:545
26
+#: src/modules/module-pulse-tunnel.c:639
27
 #, c-format
28
 msgid "Tunnel for %s@%s"
29
 msgstr "Tunnel för %s@%s"
30
 
31
-#: src/modules/module-zeroconf-discover.c:313
32
+#: src/modules/module-zeroconf-discover.c:332
33
 msgid "Unknown device"
34
 msgstr "Okänd enhet"
35
 
36
-#: src/modules/module-zeroconf-discover.c:325
37
+#: src/modules/module-zeroconf-discover.c:344
38
 #, c-format
39
 msgid "%s on %s@%s"
40
 msgstr "%s på %s@%s"
41
 
42
-#: src/modules/module-zeroconf-discover.c:329
43
+#: src/modules/module-zeroconf-discover.c:348
44
 #, c-format
45
 msgid "%s on %s"
46
 msgstr "%s på %s"
47
 
48
-#: src/tools/pw-cat.c:867
49
+#: src/tools/pw-cat.c:872
50
 #, c-format
51
 msgid ""
52
-"%s options <file>\n"
53
+"%s options <file>|-\n"
54
 "  -h, --help                            Show this help\n"
55
 "      --version                         Show version\n"
56
 "  -v, --verbose                         Enable verbose operations\n"
57
 "\n"
58
 msgstr ""
59
-"%s options <file>\n"
60
+"%s flaggor <fil>|-\n"
61
 "  -h, --help                            Visa denna hjälp\n"
62
 "      --version                         Visa version\n"
63
 "  -v, --verbose                         Aktivera utförliga operationer\n"
64
 "\n"
65
 
66
-#: src/tools/pw-cat.c:874
67
+#: src/tools/pw-cat.c:879
68
 #, c-format
69
 msgid ""
70
 "  -R, --remote                          Remote daemon name\n"
71
@@ -109,6 +109,7 @@
72
 "                                          or direct samples (256)\n"
73
 "                                          the rate is the one of the source "
74
 "file\n"
75
+"  -P  --properties                      Set node properties\n"
76
 "\n"
77
 msgstr ""
78
 "  -R, --remote                          Fjärrdemonnamn\n"
79
@@ -121,9 +122,10 @@
80
 "                                          Xenhet (enhet = s, ms, us, ns)\n"
81
 "                                          eller direkta samplar (256)\n"
82
 "                                          hastigheten är källfilens\n"
83
+"  -P  --properties                      Sätt nodegenskaper\n"
84
 "\n"
85
 
86
-#: src/tools/pw-cat.c:891
87
+#: src/tools/pw-cat.c:897
88
 #, c-format
89
 msgid ""
90
 "      --rate                            Sample rate (req. for rec) (default "
91
@@ -158,7 +160,7 @@
92
 "%d)\n"
93
 "\n"
94
 
95
-#: src/tools/pw-cat.c:908
96
+#: src/tools/pw-cat.c:914
97
 msgid ""
98
 "  -p, --playback                        Playback mode\n"
99
 "  -r, --record                          Recording mode\n"
100
@@ -172,7 +174,7 @@
101
 "  -d, --dsd                             DSD-läge\n"
102
 "\n"
103
 
104
-#: src/tools/pw-cli.c:3051
105
+#: src/tools/pw-cli.c:3139
106
 #, c-format
107
 msgid ""
108
 "%s options command\n"
109
@@ -194,7 +196,7 @@
110
 msgstr "Professionellt ljud"
111
 
112
 #: spa/plugins/alsa/acp/acp.c:444 spa/plugins/alsa/acp/alsa-mixer.c:4648
113
-#: spa/plugins/bluez5/bluez5-device.c:1159
114
+#: spa/plugins/bluez5/bluez5-device.c:1161
115
 msgid "Off"
116
 msgstr "Av"
117
 
118
@@ -221,7 +223,7 @@
119
 
120
 #: spa/plugins/alsa/acp/alsa-mixer.c:2657
121
 #: spa/plugins/alsa/acp/alsa-mixer.c:2741
122
-#: spa/plugins/bluez5/bluez5-device.c:1328
123
+#: spa/plugins/bluez5/bluez5-device.c:1330
124
 msgid "Microphone"
125
 msgstr "Mikrofon"
126
 
127
@@ -287,7 +289,7 @@
128
 msgstr "Ingen basökning"
129
 
130
 #: spa/plugins/alsa/acp/alsa-mixer.c:2672
131
-#: spa/plugins/bluez5/bluez5-device.c:1333
132
+#: spa/plugins/bluez5/bluez5-device.c:1335
133
 msgid "Speaker"
134
 msgstr "Högtalare"
135
 
136
@@ -402,7 +404,7 @@
137
 
138
 #: spa/plugins/alsa/acp/alsa-mixer.c:4484
139
 #: spa/plugins/alsa/acp/alsa-mixer.c:4642
140
-#: spa/plugins/bluez5/bluez5-device.c:1318
141
+#: spa/plugins/bluez5/bluez5-device.c:1320
142
 msgid "Headset"
143
 msgstr "Headset"
144
 
145
@@ -620,61 +622,61 @@
146
 msgid "Modem"
147
 msgstr "Modem"
148
 
149
-#: spa/plugins/bluez5/bluez5-device.c:1170
150
+#: spa/plugins/bluez5/bluez5-device.c:1172
151
 msgid "Audio Gateway (A2DP Source & HSP/HFP AG)"
152
 msgstr "Audio gateway (A2DP-källa & HSP/HFP AG)"
153
 
154
-#: spa/plugins/bluez5/bluez5-device.c:1195
155
+#: spa/plugins/bluez5/bluez5-device.c:1197
156
 #, c-format
157
 msgid "High Fidelity Playback (A2DP Sink, codec %s)"
158
 msgstr "High fidelity-uppspelning (A2DP-utgång, kodek %s)"
159
 
160
-#: spa/plugins/bluez5/bluez5-device.c:1198
161
+#: spa/plugins/bluez5/bluez5-device.c:1200
162
 #, c-format
163
 msgid "High Fidelity Duplex (A2DP Source/Sink, codec %s)"
164
 msgstr "High fidelity duplex (A2DP-källa/utgång, kodek %s)"
165
 
166
-#: spa/plugins/bluez5/bluez5-device.c:1206
167
+#: spa/plugins/bluez5/bluez5-device.c:1208
168
 msgid "High Fidelity Playback (A2DP Sink)"
169
 msgstr "High fidelity-uppspelning (A2DP-utgång)"
170
 
171
-#: spa/plugins/bluez5/bluez5-device.c:1208
172
+#: spa/plugins/bluez5/bluez5-device.c:1210
173
 msgid "High Fidelity Duplex (A2DP Source/Sink)"
174
 msgstr "High fidelity duplex (A2DP-källa/utgång)"
175
 
176
-#: spa/plugins/bluez5/bluez5-device.c:1236
177
+#: spa/plugins/bluez5/bluez5-device.c:1238
178
 #, c-format
179
 msgid "Headset Head Unit (HSP/HFP, codec %s)"
180
 msgstr "Headset-huvudenhet (HSP/HFP, kodek %s)"
181
 
182
-#: spa/plugins/bluez5/bluez5-device.c:1241
183
+#: spa/plugins/bluez5/bluez5-device.c:1243
184
 msgid "Headset Head Unit (HSP/HFP)"
185
 msgstr "Headset-huvudenhet (HSP/HFP)"
186
 
187
-#: spa/plugins/bluez5/bluez5-device.c:1323
188
+#: spa/plugins/bluez5/bluez5-device.c:1325
189
 msgid "Handsfree"
190
 msgstr "Handsfree"
191
 
192
-#: spa/plugins/bluez5/bluez5-device.c:1338
193
+#: spa/plugins/bluez5/bluez5-device.c:1340
194
 msgid "Headphone"
195
 msgstr "Hörlurar"
196
 
197
-#: spa/plugins/bluez5/bluez5-device.c:1343
198
+#: spa/plugins/bluez5/bluez5-device.c:1345
199
 msgid "Portable"
200
 msgstr "Bärbar"
201
pipewire-0.3.51.tar.gz/po/tr.po -> pipewire-0.3.52.tar.gz/po/tr.po Changed
201
 
1
@@ -4,16 +4,16 @@
2
 # Necdet Yücel <necdetyucel@gmail.com>, 2014.
3
 # Kaan Özdinçer <kaanozdincer@gmail.com>, 2014.
4
 # Muhammet Kara <muhammetk@gmail.com>, 2015, 2016, 2017.
5
-# Oğuz Ersen <oguzersen@protonmail.com>, 2021.
6
+# Oğuz Ersen <oguz@ersen.moe>, 2021-2022.
7
 #
8
 msgid ""
9
 msgstr ""
10
 "Project-Id-Version: PipeWire master\n"
11
 "Report-Msgid-Bugs-To: https://gitlab.freedesktop.org/pipewire/pipewire/"
12
 "issues/new\n"
13
-"POT-Creation-Date: 2021-11-17 15:06+0100\n"
14
-"PO-Revision-Date: 2021-12-06 21:31+0300\n"
15
-"Last-Translator: Oğuz Ersen <oguzersen@protonmail.com>\n"
16
+"POT-Creation-Date: 2022-04-03 12:56+0200\n"
17
+"PO-Revision-Date: 2022-05-14 18:35+0300\n"
18
+"Last-Translator: Oğuz Ersen <oguz@ersen.moe>\n"
19
 "Language-Team: Turkish <tr>\n"
20
 "Language: tr\n"
21
 "MIME-Version: 1.0\n"
22
@@ -22,7 +22,7 @@
23
 "Plural-Forms: nplurals=1; plural=0;\n"
24
 "X-Generator: Weblate 4.4.2\n"
25
 
26
-#: src/daemon/pipewire.c:45
27
+#: src/daemon/pipewire.c:46
28
 #, c-format
29
 msgid ""
30
 "%s options\n"
31
@@ -35,32 +35,36 @@
32
 "      --version                         Sürümü göster\n"
33
 "  -c, --config                          Yapılandırmayı yükle (Öntanımlı %s)\n"
34
 
35
-#: src/modules/module-protocol-pulse/modules/module-tunnel-sink.c:185
36
-#: src/modules/module-protocol-pulse/modules/module-tunnel-source.c:185
37
+#: src/modules/module-protocol-pulse/modules/module-tunnel-sink.c:190
38
+#: src/modules/module-protocol-pulse/modules/module-tunnel-source.c:190
39
 #, c-format
40
 msgid "Tunnel to %s/%s"
41
 msgstr "%s/%s tüneli"
42
 
43
-#: src/modules/module-pulse-tunnel.c:536
44
+#: src/modules/module-fallback-sink.c:51
45
+msgid "Dummy Output"
46
+msgstr "Temsili Çıkış"
47
+
48
+#: src/modules/module-pulse-tunnel.c:545
49
 #, c-format
50
 msgid "Tunnel for %s@%s"
51
 msgstr "%s@%s için tünel"
52
 
53
-#: src/modules/module-zeroconf-discover.c:332
54
+#: src/modules/module-zeroconf-discover.c:313
55
 msgid "Unknown device"
56
 msgstr "Bilinmeyen aygıt"
57
 
58
-#: src/modules/module-zeroconf-discover.c:344
59
+#: src/modules/module-zeroconf-discover.c:325
60
 #, c-format
61
 msgid "%s on %s@%s"
62
 msgstr "%s, %s@%s"
63
 
64
-#: src/modules/module-zeroconf-discover.c:348
65
+#: src/modules/module-zeroconf-discover.c:329
66
 #, c-format
67
 msgid "%s on %s"
68
 msgstr "%s, %s"
69
 
70
-#: src/tools/pw-cat.c:1058
71
+#: src/tools/pw-cat.c:1087
72
 #, c-format
73
 msgid ""
74
 "%s options <file>\n"
75
@@ -75,7 +79,7 @@
76
 "  -v, --verbose                         Ayrıntılı işlemleri etkinleştir\n"
77
 "\n"
78
 
79
-#: src/tools/pw-cat.c:1065
80
+#: src/tools/pw-cat.c:1094
81
 #, c-format
82
 msgid ""
83
 "  -R, --remote                          Remote daemon name\n"
84
@@ -109,7 +113,7 @@
85
 "hedefleri listele\n"
86
 "\n"
87
 
88
-#: src/tools/pw-cat.c:1083
89
+#: src/tools/pw-cat.c:1112
90
 #, c-format
91
 msgid ""
92
 "      --rate                            Sample rate (req. for rec) (default "
93
@@ -145,7 +149,7 @@
94
 "15) (öntanımlı %d)\n"
95
 "\n"
96
 
97
-#: src/tools/pw-cat.c:1100
98
+#: src/tools/pw-cat.c:1129
99
 msgid ""
100
 "  -p, --playback                        Playback mode\n"
101
 "  -r, --record                          Recording mode\n"
102
@@ -159,7 +163,7 @@
103
 "  -d, --dsd                             DSD modu\n"
104
 "\n"
105
 
106
-#: src/tools/pw-cli.c:3018
107
+#: src/tools/pw-cli.c:3051
108
 #, c-format
109
 msgid ""
110
 "%s options command\n"
111
@@ -182,7 +186,7 @@
112
 msgstr "Profesyonel Ses"
113
 
114
 #: spa/plugins/alsa/acp/acp.c:444 spa/plugins/alsa/acp/alsa-mixer.c:4648
115
-#: spa/plugins/bluez5/bluez5-device.c:1145
116
+#: spa/plugins/bluez5/bluez5-device.c:1159
117
 msgid "Off"
118
 msgstr "Kapalı"
119
 
120
@@ -209,7 +213,7 @@
121
 
122
 #: spa/plugins/alsa/acp/alsa-mixer.c:2657
123
 #: spa/plugins/alsa/acp/alsa-mixer.c:2741
124
-#: spa/plugins/bluez5/bluez5-device.c:1302
125
+#: spa/plugins/bluez5/bluez5-device.c:1328
126
 msgid "Microphone"
127
 msgstr "Mikrofon"
128
 
129
@@ -275,7 +279,7 @@
130
 msgstr "Bas Artırma Yok"
131
 
132
 #: spa/plugins/alsa/acp/alsa-mixer.c:2672
133
-#: spa/plugins/bluez5/bluez5-device.c:1307
134
+#: spa/plugins/bluez5/bluez5-device.c:1333
135
 msgid "Speaker"
136
 msgstr "Hoparlör"
137
 
138
@@ -390,7 +394,7 @@
139
 
140
 #: spa/plugins/alsa/acp/alsa-mixer.c:4484
141
 #: spa/plugins/alsa/acp/alsa-mixer.c:4642
142
-#: spa/plugins/bluez5/bluez5-device.c:1292
143
+#: spa/plugins/bluez5/bluez5-device.c:1318
144
 msgid "Headset"
145
 msgstr "Kulaklık"
146
 
147
@@ -504,12 +508,12 @@
148
 msgid "Mono Chat + 7.1 Surround"
149
 msgstr "Tek Kanallı Sohbet + 7.1 Çevresel Ses"
150
 
151
-#: spa/plugins/alsa/acp/alsa-mixer.c:4750
152
+#: spa/plugins/alsa/acp/alsa-mixer.c:4754
153
 #, c-format
154
 msgid "%s Output"
155
 msgstr "%s Çıkışı"
156
 
157
-#: spa/plugins/alsa/acp/alsa-mixer.c:4757
158
+#: spa/plugins/alsa/acp/alsa-mixer.c:4761
159
 #, c-format
160
 msgid "%s Input"
161
 msgstr "%s Girişi"
162
@@ -534,13 +538,13 @@
163
 #: spa/plugins/alsa/acp/alsa-util.c:1239
164
 #, c-format
165
 msgid ""
166
-"snd_pcm_delay() returned a value that is exceptionally large: %li byte (%s"
167
-"%lu ms).\n"
168
+"snd_pcm_delay() returned a value that is exceptionally large: %li byte "
169
+"(%s%lu ms).\n"
170
 "Most likely this is a bug in the ALSA driver '%s'. Please report this issue "
171
 "to the ALSA developers."
172
 msgid_plural ""
173
-"snd_pcm_delay() returned a value that is exceptionally large: %li bytes (%s"
174
-"%lu ms).\n"
175
+"snd_pcm_delay() returned a value that is exceptionally large: %li bytes "
176
+"(%s%lu ms).\n"
177
 "Most likely this is a bug in the ALSA driver '%s'. Please report this issue "
178
 "to the ALSA developers."
179
 msgstr0 ""
180
@@ -591,62 +595,62 @@
181
 msgid "Modem"
182
 msgstr "Modem"
183
 
184
-#: spa/plugins/bluez5/bluez5-device.c:1155
185
+#: spa/plugins/bluez5/bluez5-device.c:1170
186
 msgid "Audio Gateway (A2DP Source & HSP/HFP AG)"
187
 msgstr "Ses Geçidi (A2DP Kaynak & HSP/HFP AG)"
188
 
189
-#: spa/plugins/bluez5/bluez5-device.c:1178
190
+#: spa/plugins/bluez5/bluez5-device.c:1195
191
 #, c-format
192
 msgid "High Fidelity Playback (A2DP Sink, codec %s)"
193
 msgstr "Yüksek Kaliteli Çalma (A2DP Alıcı, çözücü %s)"
194
 
195
-#: spa/plugins/bluez5/bluez5-device.c:1181
196
+#: spa/plugins/bluez5/bluez5-device.c:1198
197
 #, c-format
198
 msgid "High Fidelity Duplex (A2DP Source/Sink, codec %s)"
199
 msgstr "Yüksek Kaliteli İkili (A2DP Kaynak/Alıcı, çözücü %s)"
200
 
201
pipewire-0.3.51.tar.gz/po/uk.po -> pipewire-0.3.52.tar.gz/po/uk.po Changed
201
 
1
@@ -1,23 +1,25 @@
2
 # Copyright (C) 2009 Free Software Foundation, Inc.
3
 # This file is distributed under the same license as the pipewire package.
4
 #
5
-# Yuri Chornoivan <yurchor@ukr.net>, 2009-2021.
6
+# Yuri Chornoivan <yurchor@ukr.net>, 2009-2021, 2022.
7
 msgid ""
8
 msgstr ""
9
 "Project-Id-Version: pipewire\n"
10
-"Report-Msgid-Bugs-To: https://gitlab.freedesktop.org/pipewire/pipewire/-/issues\n"
11
-"POT-Creation-Date: 2021-09-21 15:31+0000\n"
12
-"PO-Revision-Date: 2021-09-23 12:37+0300\n"
13
+"Report-Msgid-Bugs-To: https://gitlab.freedesktop.org/pipewire/pipewire/-/issue"
14
+"s\n"
15
+"POT-Creation-Date: 2022-05-05 03:28+0000\n"
16
+"PO-Revision-Date: 2022-05-05 21:06+0300\n"
17
 "Last-Translator: Yuri Chornoivan <yurchor@ukr.net>\n"
18
 "Language-Team: Ukrainian <trans-uk@lists.fedoraproject.org>\n"
19
 "Language: uk\n"
20
 "MIME-Version: 1.0\n"
21
 "Content-Type: text/plain; charset=UTF-8\n"
22
 "Content-Transfer-Encoding: 8bit\n"
23
-"Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n"
24
+"Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<"
25
+"=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n"
26
 "X-Generator: Lokalize 20.12.0\n"
27
 
28
-#: src/daemon/pipewire.c:45
29
+#: src/daemon/pipewire.c:46
30
 #, c-format
31
 msgid ""
32
 "%s options\n"
33
@@ -39,43 +41,37 @@
34
 msgid "Start the PipeWire Media System"
35
 msgstr "Запустити мультимедійну систему PipeWire"
36
 
37
-#: src/examples/media-session/alsa-monitor.c:656
38
-#: spa/plugins/alsa/acp/compat.c:189
39
-msgid "Built-in Audio"
40
-msgstr "Вбудоване аудіо"
41
-
42
-#: src/examples/media-session/alsa-monitor.c:660
43
-#: spa/plugins/alsa/acp/compat.c:194
44
-msgid "Modem"
45
-msgstr "Модем"
46
-
47
-#: src/examples/media-session/alsa-monitor.c:669
48
-#: src/modules/module-zeroconf-discover.c:296
49
-msgid "Unknown device"
50
-msgstr "Невідомий пристрій"
51
-
52
-#: src/modules/module-protocol-pulse/modules/module-tunnel-sink.c:173
53
-#: src/modules/module-protocol-pulse/modules/module-tunnel-source.c:173
54
+#: src/modules/module-protocol-pulse/modules/module-tunnel-sink.c:183
55
+#: src/modules/module-protocol-pulse/modules/module-tunnel-source.c:183
56
 #, c-format
57
 msgid "Tunnel to %s/%s"
58
 msgstr "Тунель до %s/%s"
59
 
60
-#: src/modules/module-pulse-tunnel.c:534
61
+#: src/modules/module-fallback-sink.c:51
62
+#| msgid "Game Output"
63
+msgid "Dummy Output"
64
+msgstr "Фіктивний вихід"
65
+
66
+#: src/modules/module-pulse-tunnel.c:639
67
 #, c-format
68
 msgid "Tunnel for %s@%s"
69
 msgstr "Тунель для %s@%s"
70
 
71
-#: src/modules/module-zeroconf-discover.c:308
72
+#: src/modules/module-zeroconf-discover.c:332
73
+msgid "Unknown device"
74
+msgstr "Невідомий пристрій"
75
+
76
+#: src/modules/module-zeroconf-discover.c:344
77
 #, c-format
78
 msgid "%s on %s@%s"
79
 msgstr "%s на %s@%s"
80
 
81
-#: src/modules/module-zeroconf-discover.c:312
82
+#: src/modules/module-zeroconf-discover.c:348
83
 #, c-format
84
 msgid "%s on %s"
85
 msgstr "%s на %s"
86
 
87
-#: src/tools/pw-cat.c:1055
88
+#: src/tools/pw-cat.c:871
89
 #, c-format
90
 msgid ""
91
 "%s options <file>\n"
92
@@ -91,8 +87,23 @@
93
 "інформації\n"
94
 "\n"
95
 
96
-#: src/tools/pw-cat.c:1062
97
+#: src/tools/pw-cat.c:878
98
 #, c-format
99
+#| msgid ""
100
+#| "  -R, --remote                          Remote daemon name\n"
101
+#| "      --media-type                      Set media type (default %s)\n"
102
+#| "      --media-category                  Set media category (default %s)\n"
103
+#| "      --media-role                      Set media role (default %s)\n"
104
+#| "      --target                          Set node target (default %s)\n"
105
+#| "                                          0 means don't link\n"
106
+#| "      --latency                         Set node latency (default %s)\n"
107
+#| "                                          Xunit (unit = s, ms, us, ns)\n"
108
+#| "                                          or direct samples (256)\n"
109
+#| "                                          the rate is the one of the "
110
+#| "source file\n"
111
+#| "      --list-targets                    List available targets for --"
112
+#| "target\n"
113
+#| "\n"
114
 msgid ""
115
 "  -R, --remote                          Remote daemon name\n"
116
 "      --media-type                      Set media type (default %s)\n"
117
@@ -105,7 +116,6 @@
118
 "                                          or direct samples (256)\n"
119
 "                                          the rate is the one of the source "
120
 "file\n"
121
-"      --list-targets                    List available targets for --target\n"
122
 "\n"
123
 msgstr ""
124
 "  -R, --remote                          назва віддаленої фонової служби\n"
125
@@ -123,11 +133,9 @@
126
 "ns)\n"
127
 "                                          або безпосередні семпли (256)\n"
128
 "                                          частота — частота з файла джерела\n"
129
-"      --list-targets                    перерахувати доступні цілі для --"
130
-"target\n"
131
 "\n"
132
 
133
-#: src/tools/pw-cat.c:1080
134
+#: src/tools/pw-cat.c:895
135
 #, c-format
136
 msgid ""
137
 "      --rate                            Sample rate (req. for rec) (default "
138
@@ -163,12 +171,7 @@
139
 "(типово, %d)\n"
140
 "\n"
141
 
142
-#: src/tools/pw-cat.c:1097
143
-#| msgid ""
144
-#| "  -p, --playback                        Playback mode\n"
145
-#| "  -r, --record                          Recording mode\n"
146
-#| "  -m, --midi                            Midi mode\n"
147
-#| "\n"
148
+#: src/tools/pw-cat.c:912
149
 msgid ""
150
 "  -p, --playback                        Playback mode\n"
151
 "  -r, --record                          Recording mode\n"
152
@@ -182,7 +185,7 @@
153
 "  -d, --dsd                             режим DSD\n"
154
 "\n"
155
 
156
-#: src/tools/pw-cli.c:2954
157
+#: src/tools/pw-cli.c:3139
158
 #, c-format
159
 msgid ""
160
 "%s options command\n"
161
@@ -200,12 +203,12 @@
162
 "  -r, --remote                          назва віддаленої фонової служби\n"
163
 "\n"
164
 
165
-#: spa/plugins/alsa/acp/acp.c:310
166
+#: spa/plugins/alsa/acp/acp.c:321
167
 msgid "Pro Audio"
168
 msgstr "Професійний звук"
169
 
170
-#: spa/plugins/alsa/acp/acp.c:433 spa/plugins/alsa/acp/alsa-mixer.c:4648
171
-#: spa/plugins/bluez5/bluez5-device.c:1135
172
+#: spa/plugins/alsa/acp/acp.c:444 spa/plugins/alsa/acp/alsa-mixer.c:4648
173
+#: spa/plugins/bluez5/bluez5-device.c:1161
174
 msgid "Off"
175
 msgstr "Вимкнено"
176
 
177
@@ -232,7 +235,7 @@
178
 
179
 #: spa/plugins/alsa/acp/alsa-mixer.c:2657
180
 #: spa/plugins/alsa/acp/alsa-mixer.c:2741
181
-#: spa/plugins/bluez5/bluez5-device.c:1292
182
+#: spa/plugins/bluez5/bluez5-device.c:1330
183
 msgid "Microphone"
184
 msgstr "Мікрофон"
185
 
186
@@ -298,7 +301,7 @@
187
 msgstr "Без підсилення"
188
 
189
 #: spa/plugins/alsa/acp/alsa-mixer.c:2672
190
-#: spa/plugins/bluez5/bluez5-device.c:1297
191
+#: spa/plugins/bluez5/bluez5-device.c:1335
192
 msgid "Speaker"
193
 msgstr "Динамік"
194
 
195
@@ -413,7 +416,7 @@
196
 
197
 #: spa/plugins/alsa/acp/alsa-mixer.c:4484
198
 #: spa/plugins/alsa/acp/alsa-mixer.c:4642
199
-#: spa/plugins/bluez5/bluez5-device.c:1282
200
+#: spa/plugins/bluez5/bluez5-device.c:1320
201
pipewire-0.3.51.tar.gz/spa/include/spa/param/bluetooth/audio.h -> pipewire-0.3.52.tar.gz/spa/include/spa/param/bluetooth/audio.h Changed
9
 
1
@@ -48,6 +48,7 @@
2
    SPA_BLUETOOTH_AUDIO_CODEC_APTX_LL_DUPLEX,
3
    SPA_BLUETOOTH_AUDIO_CODEC_FASTSTREAM,
4
    SPA_BLUETOOTH_AUDIO_CODEC_FASTSTREAM_DUPLEX,
5
+   SPA_BLUETOOTH_AUDIO_CODEC_LC3PLUS_HR,
6
 
7
    /* HFP */
8
    SPA_BLUETOOTH_AUDIO_CODEC_CVSD = 0x100,
9
pipewire-0.3.51.tar.gz/spa/include/spa/param/bluetooth/type-info.h -> pipewire-0.3.52.tar.gz/spa/include/spa/param/bluetooth/type-info.h Changed
9
 
1
@@ -52,6 +52,7 @@
2
    { SPA_BLUETOOTH_AUDIO_CODEC_APTX_LL_DUPLEX, SPA_TYPE_Int, SPA_TYPE_INFO_BLUETOOTH_AUDIO_CODEC_BASE "aptx_ll_duplex", NULL },
3
    { SPA_BLUETOOTH_AUDIO_CODEC_FASTSTREAM, SPA_TYPE_Int, SPA_TYPE_INFO_BLUETOOTH_AUDIO_CODEC_BASE "faststream", NULL },
4
    { SPA_BLUETOOTH_AUDIO_CODEC_FASTSTREAM_DUPLEX, SPA_TYPE_Int, SPA_TYPE_INFO_BLUETOOTH_AUDIO_CODEC_BASE "faststream_duplex", NULL },
5
+   { SPA_BLUETOOTH_AUDIO_CODEC_LC3PLUS_HR, SPA_TYPE_Int, SPA_TYPE_INFO_BLUETOOTH_AUDIO_CODEC_BASE "lc3plus_hr", NULL },
6
 
7
    { SPA_BLUETOOTH_AUDIO_CODEC_CVSD, SPA_TYPE_Int, SPA_TYPE_INFO_BLUETOOTH_AUDIO_CODEC_BASE "cvsd", NULL },
8
    { SPA_BLUETOOTH_AUDIO_CODEC_MSBC, SPA_TYPE_Int, SPA_TYPE_INFO_BLUETOOTH_AUDIO_CODEC_BASE "msbc", NULL },
9
pipewire-0.3.51.tar.gz/spa/include/spa/utils/keys.h -> pipewire-0.3.52.tar.gz/spa/include/spa/utils/keys.h Changed
10
 
1
@@ -93,6 +93,8 @@
2
 #define SPA_KEY_API_LIBCAMERA      "api.libcamera"         /**< key for the libcamera api */
3
 #define SPA_KEY_API_LIBCAMERA_PATH "api.libcamera.path"    /**< libcamera device path as can be
4
                                      *  used in open() */
5
+#define SPA_KEY_API_LIBCAMERA_LOCATION "api.libcamera.location"    /**< location of the camera:
6
+                                     * "front", "back" or "external" */
7
 
8
 /** info from libcamera_capability */
9
 #define SPA_KEY_API_LIBCAMERA_CAP_DRIVER   "api.libcamera.cap.driver"  /**< driver from capbility */
10
pipewire-0.3.51.tar.gz/spa/include/spa/utils/names.h -> pipewire-0.3.52.tar.gz/spa/include/spa/utils/names.h Changed
10
 
1
@@ -144,6 +144,8 @@
2
 /** keys for vulkan factory names */
3
 #define SPA_NAME_API_VULKAN_COMPUTE_SOURCE \
4
                    "api.vulkan.compute.source" /**< a vulkan compute source. */
5
+#define SPA_NAME_API_VULKAN_COMPUTE_FILTER \
6
+                   "api.vulkan.compute.filter" /**< a vulkan compute filter. */
7
 
8
 /**
9
  * \}
10
pipewire-0.3.51.tar.gz/spa/include/spa/utils/string.h -> pipewire-0.3.52.tar.gz/spa/include/spa/utils/string.h Changed
43
 
1
@@ -275,14 +275,20 @@
2
  */
3
 static inline float spa_strtof(const char *str, char **endptr)
4
 {
5
+#ifndef __LOCALE_C_ONLY
6
    static locale_t locale = NULL;
7
    locale_t prev;
8
+#endif
9
    float v;
10
+#ifndef __LOCALE_C_ONLY
11
    if (SPA_UNLIKELY(locale == NULL))
12
        locale = newlocale(LC_ALL_MASK, "C", NULL);
13
    prev = uselocale(locale);
14
+#endif
15
    v = strtof(str, endptr);
16
+#ifndef __LOCALE_C_ONLY
17
    uselocale(prev);
18
+#endif
19
    return v;
20
 }
21
 
22
@@ -319,14 +325,20 @@
23
  */
24
 static inline double spa_strtod(const char *str, char **endptr)
25
 {
26
+#ifndef __LOCALE_C_ONLY
27
    static locale_t locale = NULL;
28
    locale_t prev;
29
+#endif
30
    double v;
31
+#ifndef __LOCALE_C_ONLY
32
    if (SPA_UNLIKELY(locale == NULL))
33
        locale = newlocale(LC_ALL_MASK, "C", NULL);
34
    prev = uselocale(locale);
35
+#endif
36
    v = strtod(str, endptr);
37
+#ifndef __LOCALE_C_ONLY
38
    uselocale(prev);
39
+#endif
40
    return v;
41
 }
42
 
43
pipewire-0.3.51.tar.gz/spa/meson.build -> pipewire-0.3.52.tar.gz/spa/meson.build Changed
16
 
1
@@ -54,6 +54,14 @@
2
     summary({'aptX': aptx_dep.found()}, bool_yn: true, section: 'Bluetooth audio codecs')
3
     fdk_aac_dep = dependency('fdk-aac', required : get_option('bluez5-codec-aac'))
4
     summary({'AAC': fdk_aac_dep.found()}, bool_yn: true, section: 'Bluetooth audio codecs')
5
+    lc3plus_dep = dependency('lc3plus', required : false)
6
+    if not lc3plus_dep.found()
7
+      lc3plus_lc3plus_h_dep = cc.find_library('LC3plus', has_headers: 'lc3plus.h', required : get_option('bluez5-codec-lc3plus'))
8
+      if lc3plus_lc3plus_h_dep.found()
9
+        lc3plus_dep = declare_dependency(compile_args : '-DHAVE_LC3PLUS_H', dependencies :  lc3plus_lc3plus_h_dep )
10
+      endif
11
+    endif
12
+    summary({'LC3plus': lc3plus_dep.found()}, bool_yn: true, section: 'Bluetooth audio codecs')
13
   endif
14
   avcodec_dep = dependency('libavcodec', required: get_option('ffmpeg'))
15
   jack_dep = dependency('jack', version : '>= 1.9.10', required: get_option('jack'))
16
pipewire-0.3.51.tar.gz/spa/plugins/alsa/90-pipewire-alsa.rules -> pipewire-0.3.52.tar.gz/spa/plugins/alsa/90-pipewire-alsa.rules Changed
19
 
1
@@ -107,6 +107,8 @@
2
 
3
 
4
 ATTRS{idVendor}=="17cc", ATTRS{idProduct}=="1001", ENV{ACP_PROFILE_SET}="native-instruments-komplete-audio6.conf"
5
+# This entry is for the Komplete Audio 6 MK2, which has a different ID, but is functionally identical to the Komplete Audio 6.
6
+ATTRS{idVendor}=="17cc", ATTRS{idProduct}=="1870", ENV{ACP_PROFILE_SET}="native-instruments-komplete-audio6.conf"
7
 ATTRS{idVendor}=="17cc", ATTRS{idProduct}=="1021", ENV{ACP_PROFILE_SET}="native-instruments-traktor-audio10.conf"
8
 ATTRS{idVendor}=="0763", ATTRS{idProduct}=="2012", ENV{ACP_PROFILE_SET}="maudio-fasttrack-pro.conf"
9
 ATTRS{idVendor}=="045e", ATTRS{idProduct}=="02bb", ENV{ACP_PROFILE_SET}="kinect-audio.conf"
10
@@ -131,6 +133,8 @@
11
 ATTRS{idVendor}=="2f12", ATTRS{idProduct}=="0109", ENV{ACP_PROFILE_SET}="usb-gaming-headset.conf"
12
 # ID 9886:002c is for the Astro A50 Gen4
13
 ATTRS{idVendor}=="9886", ATTRS{idProduct}=="002c", ENV{ACP_PROFILE_SET}="usb-gaming-headset.conf"
14
+# ID 9886:0045 is for the Astro A20 Gen2
15
+ATTRS{idVendor}=="9886", ATTRS{idProduct}=="0045", ENV{ACP_PROFILE_SET}="usb-gaming-headset.conf"
16
 # ID 1532:0520 is for the Razer Kraken Tournament Edition
17
 ATTRS{idVendor}=="1532", ATTRS{idProduct}=="0520", ENV{ACP_PROFILE_SET}="usb-gaming-headset.conf"
18
 
19
pipewire-0.3.51.tar.gz/spa/plugins/alsa/acp/acp.c -> pipewire-0.3.52.tar.gz/spa/plugins/alsa/acp/acp.c Changed
17
 
1
@@ -381,6 +381,7 @@
2
                            &try_period_size, &try_buffer_size,
3
                            0, NULL, NULL, false))) {
4
                pa_alsa_init_proplist_pcm(NULL, m->output_proplist, m->output_pcm);
5
+               pa_proplist_setf(m->output_proplist, "clock.name", "api.alsa.%u", index);
6
                snd_pcm_close(m->output_pcm);
7
                m->output_pcm = NULL;
8
                m->supported = true;
9
@@ -411,6 +412,7 @@
10
                            &try_period_size, &try_buffer_size,
11
                            0, NULL, NULL, false))) {
12
                pa_alsa_init_proplist_pcm(NULL, m->input_proplist, m->input_pcm);
13
+               pa_proplist_setf(m->input_proplist, "clock.name", "api.alsa.%u", index);
14
                snd_pcm_close(m->input_pcm);
15
                m->input_pcm = NULL;
16
                m->supported = true;
17
pipewire-0.3.51.tar.gz/spa/plugins/alsa/acp/channelmap.h -> pipewire-0.3.52.tar.gz/spa/plugins/alsa/acp/channelmap.h Changed
32
 
1
@@ -186,7 +186,7 @@
2
    case PA_CHANNEL_MAP_AUX:
3
        for (i = 0; i < channels; i++)
4
        m->mapi = PA_CHANNEL_POSITION_AUX0 + (i & 31);
5
-       break;
6
+       return m;
7
    default:
8
        break;
9
    }
10
@@ -196,17 +196,10 @@
11
 static inline pa_channel_map* pa_channel_map_init_extend(pa_channel_map *m,
12
        unsigned channels, pa_channel_map_def_t def)
13
 {
14
-   unsigned i, c;
15
-   pa_channel_map_init(m);
16
-   for (c = channels; c > 0; c--) {
17
-       if (pa_channel_map_init_auto(m, c, def) == NULL)
18
-           continue;
19
-       for (i = 0; c < channels; c++, i++)
20
-           m->mapc = PA_CHANNEL_POSITION_AUX0 + (i & 31);
21
-       m->channels = (uint8_t) channels;
22
-       return m;
23
-   }
24
-   return NULL;
25
+   pa_channel_map *r;
26
+   if ((r = pa_channel_map_init_auto(m, channels, def)) != NULL)
27
+       return r;
28
+   return pa_channel_map_init_auto(m, channels, PA_CHANNEL_MAP_AUX);
29
 }
30
 
31
 typedef uint64_t pa_channel_position_mask_t;
32
pipewire-0.3.51.tar.gz/spa/plugins/alsa/alsa-pcm-sink.c -> pipewire-0.3.52.tar.gz/spa/plugins/alsa/alsa-pcm-sink.c Changed
34
 
1
@@ -353,7 +353,9 @@
2
    case SPA_PARAM_ProcessLatency:
3
    {
4
        struct spa_process_latency_info info;
5
-       if ((res = spa_process_latency_parse(param, &info)) < 0)
6
+       if (param == NULL)
7
+           spa_zero(info);
8
+       else if ((res = spa_process_latency_parse(param, &info)) < 0)
9
            return res;
10
 
11
        handle_process_latency(this, &info);
12
@@ -531,8 +533,8 @@
13
            SPA_PARAM_BUFFERS_buffers, SPA_POD_CHOICE_RANGE_Int(2, 1, MAX_BUFFERS),
14
            SPA_PARAM_BUFFERS_blocks,  SPA_POD_Int(this->blocks),
15
            SPA_PARAM_BUFFERS_size,    SPA_POD_CHOICE_RANGE_Int(
16
-                           this->quantum_limit * this->frame_size,
17
-                           16 * this->frame_size,
18
+                           this->quantum_limit * this->frame_size * this->frame_scale,
19
+                           16 * this->frame_size * this->frame_scale,
20
                            INT32_MAX),
21
            SPA_PARAM_BUFFERS_stride,  SPA_POD_Int(this->frame_size));
22
        break;
23
@@ -694,7 +696,9 @@
24
    case SPA_PARAM_Latency:
25
    {
26
        struct spa_latency_info info;
27
-       if ((res = spa_latency_parse(param, &info)) < 0)
28
+       if (param == NULL)
29
+           info = SPA_LATENCY_INFO(SPA_DIRECTION_REVERSE(direction));
30
+       else if ((res = spa_latency_parse(param, &info)) < 0)
31
            return res;
32
        if (direction == info.direction)
33
            return -EINVAL;
34
pipewire-0.3.51.tar.gz/spa/plugins/alsa/alsa-pcm-source.c -> pipewire-0.3.52.tar.gz/spa/plugins/alsa/alsa-pcm-source.c Changed
23
 
1
@@ -319,7 +319,9 @@
2
    case SPA_PARAM_ProcessLatency:
3
    {
4
        struct spa_process_latency_info info;
5
-       if ((res = spa_process_latency_parse(param, &info)) < 0)
6
+       if (param == NULL)
7
+           spa_zero(info);
8
+       else if ((res = spa_process_latency_parse(param, &info)) < 0)
9
            return res;
10
 
11
        handle_process_latency(this, &info);
12
@@ -631,7 +633,9 @@
13
    case SPA_PARAM_Latency:
14
    {
15
        struct spa_latency_info info;
16
-       if ((res = spa_latency_parse(param, &info)) < 0)
17
+       if (param == NULL)
18
+           info = SPA_LATENCY_INFO(SPA_DIRECTION_REVERSE(direction));
19
+       else if ((res = spa_latency_parse(param, &info)) < 0)
20
            return res;
21
        if (direction == info.direction)
22
            return -EINVAL;
23
pipewire-0.3.51.tar.gz/spa/plugins/alsa/alsa-pcm.c -> pipewire-0.3.52.tar.gz/spa/plugins/alsa/alsa-pcm.c Changed
172
 
1
@@ -466,7 +466,9 @@
2
    }
3
    if (state->clock_name0 == '\0')
4
        snprintf(state->clock_name, sizeof(state->clock_name),
5
-               "api.alsa.%u", state->card_index);
6
+               "api.alsa.%s-%u",
7
+               state->stream == SND_PCM_STREAM_PLAYBACK ? "p" : "c",
8
+               state->card_index);
9
 
10
    if (state->stream == SND_PCM_STREAM_PLAYBACK) {
11
        state->is_iec958 = spa_strstartswith(state->props.device, "iec958");
12
@@ -1235,7 +1237,7 @@
13
 
14
 int spa_alsa_set_format(struct state *state, struct spa_audio_info *fmt, uint32_t flags)
15
 {
16
-   unsigned int rrate, rchannels, val;
17
+   unsigned int rrate, rchannels, val, rscale = 1;
18
    snd_pcm_uframes_t period_size;
19
    int err, dir;
20
    snd_pcm_hw_params_t *params;
21
@@ -1322,21 +1324,26 @@
22
        case 4:
23
            rformat = SND_PCM_FORMAT_DSD_U32_BE;
24
            rrate /= 4;
25
+           rscale = 4;
26
            break;
27
        case -4:
28
            rformat = SND_PCM_FORMAT_DSD_U32_LE;
29
            rrate /= 4;
30
+           rscale = 4;
31
            break;
32
        case 2:
33
            rformat = SND_PCM_FORMAT_DSD_U16_BE;
34
            rrate /= 2;
35
+           rscale = 2;
36
            break;
37
        case -2:
38
            rformat = SND_PCM_FORMAT_DSD_U16_LE;
39
            rrate /= 2;
40
+           rscale = 2;
41
            break;
42
        case 1:
43
            rformat = SND_PCM_FORMAT_DSD_U8;
44
+           rscale = 1;
45
            break;
46
        default:
47
            return -ENOTSUP;
48
@@ -1430,6 +1437,7 @@
49
    state->channels = rchannels;
50
    state->rate = rrate;
51
    state->frame_size = snd_pcm_format_physical_width(rformat) / 8;
52
+   state->frame_scale = rscale;
53
    state->planar = planar;
54
    state->blocks = 1;
55
    if (planar)
56
@@ -1477,7 +1485,7 @@
57
    } else {
58
        CHECK(snd_pcm_hw_params_get_buffer_size_max(params, &state->buffer_frames), "get_buffer_size_max");
59
 
60
-       state->buffer_frames = SPA_MIN(state->buffer_frames, state->quantum_limit * 4);
61
+       state->buffer_frames = SPA_MIN(state->buffer_frames, state->quantum_limit * 4)* state->frame_scale;
62
 
63
        CHECK(snd_pcm_hw_params_set_buffer_size_min(hndl, params, &state->buffer_frames), "set_buffer_size_min");
64
        CHECK(snd_pcm_hw_params_set_buffer_size_near(hndl, params, &state->buffer_frames), "set_buffer_size_near");
65
@@ -1785,9 +1793,11 @@
66
    if (err > state->max_error) {
67
        err = state->max_error;
68
        state->alsa_sync = true;
69
+       state->alsa_sync_warning = (diff == 0);
70
    } else if (err < -state->max_error) {
71
        err = -state->max_error;
72
        state->alsa_sync = true;
73
+       state->alsa_sync_warning = (diff == 0);
74
    }
75
 
76
    if (!follower || state->matching)
77
@@ -1854,6 +1864,11 @@
78
        state->matching = false;
79
 
80
    state->resample = ((uint32_t)state->rate != state->rate_denom) || state->matching;
81
+
82
+   spa_log_info(state->log, "driver clock:'%s'@%d our clock:'%s'@%d matching:%d resample:%d",
83
+           state->position->clock.name, state->rate_denom,
84
+           state->clock_name, state->rate,
85
+           state->matching, state->resample);
86
    return 0;
87
 }
88
 
89
@@ -1867,6 +1882,7 @@
90
        state->duration = state->position->clock.duration;
91
        state->rate_denom = state->position->clock.rate.denom;
92
        state->threshold = (state->duration * state->rate + state->rate_denom-1) / state->rate_denom;
93
+       state->max_error = SPA_MAX(256.0f, state->threshold / 2.0f);
94
        state->resample = ((uint32_t)state->rate != state->rate_denom) || state->matching;
95
        state->alsa_sync = true;
96
    }
97
@@ -1893,9 +1909,18 @@
98
        if (SPA_UNLIKELY((res = get_status(state, current_time, &delay, &target)) < 0))
99
            return res;
100
 
101
+       if (SPA_UNLIKELY((res = update_time(state, current_time, delay, target, true)) < 0))
102
+           return res;
103
+
104
        if (SPA_UNLIKELY(state->alsa_sync)) {
105
-           spa_log_warn(state->log, "%s: follower delay:%ld target:%ld thr:%u, resync",
106
-                   state->props.device, delay, target, state->threshold);
107
+           if (SPA_UNLIKELY(state->alsa_sync_warning)) {
108
+               spa_log_warn(state->log, "%s: follower delay:%ld target:%ld thr:%u, resync",
109
+                       state->props.device, delay, target, state->threshold);
110
+               state->alsa_sync_warning = false;
111
+           } else
112
+               spa_log_info(state->log, "%s: follower delay:%ld target:%ld thr:%u, resync",
113
+                       state->props.device, delay, target, state->threshold);
114
+
115
            if (delay > target)
116
                snd_pcm_rewind(state->hndl, delay - target);
117
            else if (delay < target)
118
@@ -1903,8 +1928,6 @@
119
            delay = target;
120
            state->alsa_sync = false;
121
        }
122
-       if (SPA_UNLIKELY((res = update_time(state, current_time, delay, target, true)) < 0))
123
-           return res;
124
    }
125
 
126
    total_written = 0;
127
@@ -2131,9 +2154,18 @@
128
 
129
        avail = delay;
130
 
131
+       if (SPA_UNLIKELY((res = update_time(state, current_time, delay, target, true)) < 0))
132
+           return res;
133
+
134
        if (state->alsa_sync) {
135
-           spa_log_warn(state->log, "%s: follower delay:%lu target:%lu thr:%u, resync",
136
-                   state->props.device, delay, target, threshold);
137
+           if (SPA_UNLIKELY(state->alsa_sync_warning)) {
138
+               spa_log_warn(state->log, "%s: follower delay:%lu target:%lu thr:%u, resync",
139
+                       state->props.device, delay, target, threshold);
140
+               state->alsa_sync_warning = false;
141
+           } else
142
+               spa_log_info(state->log, "%s: follower delay:%lu target:%lu thr:%u, resync",
143
+                       state->props.device, delay, target, threshold);
144
+
145
            if (delay < target)
146
                max_read = target - delay;
147
            else if (delay > target)
148
@@ -2142,9 +2174,6 @@
149
            state->alsa_sync = false;
150
        }
151
 
152
-       if ((res = update_time(state, current_time, delay, target, true)) < 0)
153
-           return res;
154
-
155
        if (avail < state->read_size)
156
            max_read = 0;
157
    }
158
@@ -2406,11 +2435,10 @@
159
    state->following = is_following(state);
160
    setup_matching(state);
161
 
162
+   spa_dll_init(&state->dll);
163
    state->threshold = (state->duration * state->rate + state->rate_denom-1) / state->rate_denom;
164
    state->last_threshold = state->threshold;
165
-
166
-   spa_dll_init(&state->dll);
167
-   state->max_error = (256.0 * state->rate) / state->rate_denom;
168
+   state->max_error = SPA_MAX(256.0f, state->threshold / 2.0f);
169
 
170
    spa_log_debug(state->log, "%p: start %d duration:%d rate:%d follower:%d match:%d resample:%d",
171
            state, state->threshold, state->duration, state->rate_denom,
172
pipewire-0.3.51.tar.gz/spa/plugins/alsa/alsa-pcm.h -> pipewire-0.3.52.tar.gz/spa/plugins/alsa/alsa-pcm.h Changed
17
 
1
@@ -151,6 +151,7 @@
2
    int rate;
3
    int channels;
4
    size_t frame_size;
5
+   size_t frame_scale;
6
    int blocks;
7
    uint32_t rate_denom;
8
    uint32_t delay;
9
@@ -191,6 +192,7 @@
10
    uint32_t duration;
11
    unsigned int alsa_started:1;
12
    unsigned int alsa_sync:1;
13
+   unsigned int alsa_sync_warning:1;
14
    unsigned int alsa_recovering:1;
15
    unsigned int following:1;
16
    unsigned int matching:1;
17
pipewire-0.3.51.tar.gz/spa/plugins/alsa/mixer/profile-sets/native-instruments-komplete-audio6.conf -> pipewire-0.3.52.tar.gz/spa/plugins/alsa/mixer/profile-sets/native-instruments-komplete-audio6.conf Changed
28
 
1
@@ -39,7 +39,7 @@
2
 direction = output
3
 
4
 Mapping stereo-out-ef
5
-description = Analog Stereo 5/6
6
+description = Stereo 5/6 (S/PDIF)
7
 device-strings = hw:%f,0,0
8
 channel-map = aux0,aux1,aux2,aux3,left,right
9
 direction = output
10
@@ -51,7 +51,7 @@
11
 direction = input
12
 
13
 Mapping analog-mono-in-b
14
-description = Anlog Mono Input 2
15
+description = Analog Mono Input 2
16
 device-strings = hw:%f,0,0
17
 channel-map = aux0,mono,aux1,aux2,aux3,aux4
18
 direction = input
19
@@ -69,7 +69,7 @@
20
 direction = input
21
 
22
 Mapping stereo-in-ef
23
-description = Stereo Input 5/6
24
+description = Stereo Input 5/6 (S/PDIF)
25
 device-strings = hw:%f,0,0
26
 channel-map = aux0,aux1,aux2,aux3,left,right
27
 direction = input
28
pipewire-0.3.51.tar.gz/spa/plugins/alsa/mixer/profile-sets/texas-instruments-pcm2902.conf -> pipewire-0.3.52.tar.gz/spa/plugins/alsa/mixer/profile-sets/texas-instruments-pcm2902.conf Changed
18
 
1
@@ -16,14 +16,12 @@
2
 ; Texas Instruments PCM2902
3
 ;
4
 ; This is a generic chip used in multiple products, including at least
5
-; Behringer U-Phoria UMC22, Behringer U-Phoria UM2, Behringer Xenyx 302USB, 
6
-; Intopic Jazz-UB700 and some unbranded "usb mini microphone".
7
+; Behringer U-Phoria UMC22, Behringer Xenyx 302USB, Intopic Jazz-UB700 and
8
+; some unbranded "usb mini microphone".
9
 ;
10
 ; Behringer UMC22 has stereo input (representing two physical mono inputs),
11
 ; others have mono input.
12
 ;
13
-; (Behringer UMC22 and UM2 are "the same device" with different controls)
14
-;
15
 ; Some devices have a mic input path, but at least Behringer Xenyx 302USB
16
 ; doesn't have any input mixer controls.
17
 ;
18
pipewire-0.3.51.tar.gz/spa/plugins/alsa/test-timer.c -> pipewire-0.3.52.tar.gz/spa/plugins/alsa/test-timer.c Changed
64
 
1
@@ -32,15 +32,13 @@
2
 #include <alsa/asoundlib.h>
3
 
4
 #include <spa/utils/dll.h>
5
+#include <spa/utils/defs.h>
6
 
7
 #define DEFAULT_DEVICE "hw:0"
8
 
9
 #define M_PI_M2 (M_PI + M_PI)
10
 
11
-#define NSEC_PER_SEC   1000000000ll
12
-#define TIMESPEC_TO_NSEC(ts) ((ts)->tv_sec * NSEC_PER_SEC + (ts)->tv_nsec)
13
-
14
-#define BW_PERIOD  (NSEC_PER_SEC * 3)
15
+#define BW_PERIOD  (SPA_NSEC_PER_SEC * 3)
16
 
17
 struct state {
18
    const char *device;
19
@@ -65,8 +63,8 @@
20
 static int set_timeout(struct state *state, uint64_t time)
21
 {
22
    struct itimerspec ts;
23
-   ts.it_value.tv_sec = time / NSEC_PER_SEC;
24
-   ts.it_value.tv_nsec = time % NSEC_PER_SEC;
25
+   ts.it_value.tv_sec = time / SPA_NSEC_PER_SEC;
26
+   ts.it_value.tv_nsec = time % SPA_NSEC_PER_SEC;
27
    ts.it_interval.tv_sec = 0;
28
    ts.it_interval.tv_nsec = 0;
29
    return timerfd_settime(state->timerfd, TFD_TIMER_ABSTIME, &ts, NULL);
30
@@ -133,12 +131,12 @@
31
    CHECK(snd_pcm_htimestamp(state->hndl, &avail, &tstamp), "htimestamp");
32
    delay = state->buffer_frames - avail;
33
 
34
-   then = TIMESPEC_TO_NSEC(&tstamp);
35
+   then = SPA_TIMESPEC_TO_NSEC(&tstamp);
36
    if (then != 0) {
37
        if (then < state->next_time) {
38
-           delay -= (state->next_time - then) * state->rate / NSEC_PER_SEC;
39
+           delay -= (state->next_time - then) * state->rate / SPA_NSEC_PER_SEC;
40
        } else {
41
-           delay += (then - state->next_time) * state->rate / NSEC_PER_SEC;
42
+           delay += (then - state->next_time) * state->rate / SPA_NSEC_PER_SEC;
43
        }
44
    }
45
 #endif
46
@@ -278,7 +276,7 @@
47
 
48
    spa_dll_init(&state.dll);
49
    spa_dll_set_bw(&state.dll, SPA_DLL_BW_MAX, state.period, state.rate);
50
-   state.max_error = 256.0;
51
+   state.max_error = SPA_MAX(256.0, state.period / 2.0f);
52
 
53
    if ((state.timerfd = timerfd_create(CLOCK_MONOTONIC, 0)) < 0)
54
        perror("timerfd");
55
@@ -290,7 +288,7 @@
56
 
57
    /* set our first timeout for now */
58
    clock_gettime(CLOCK_MONOTONIC, &now);
59
-   state.prev_time = state.next_time = TIMESPEC_TO_NSEC(&now);
60
+   state.prev_time = state.next_time = SPA_TIMESPEC_TO_NSEC(&now);
61
    set_timeout(&state, state.next_time);
62
 
63
    /* and start playback */
64
pipewire-0.3.51.tar.gz/spa/plugins/audioconvert/audioadapter.c -> pipewire-0.3.52.tar.gz/spa/plugins/audioconvert/audioadapter.c Changed
201
 
1
@@ -257,6 +257,9 @@
2
    uint32_t i;
3
    uint64_t old = full ? this->info.change_mask : 0;
4
 
5
+   spa_log_debug(this->log, "%p: info full:%d change:%08"PRIx64,
6
+           this, full, this->info.change_mask);
7
+
8
    if (full)
9
        this->info.change_mask = this->info_all;
10
    if (this->info.change_mask) {
11
@@ -265,6 +268,8 @@
12
                if (this->paramsi.user > 0) {
13
                    this->paramsi.flags ^= SPA_PARAM_INFO_SERIAL;
14
                    this->paramsi.user = 0;
15
+                   spa_log_debug(this->log, "param %d flags:%08x",
16
+                           i, this->paramsi.flags);
17
                }
18
            }
19
        }
20
@@ -277,38 +282,45 @@
21
                 enum spa_direction direction, uint32_t port_id, uint32_t id, struct spa_pod *filter,
22
        const char *debug, int err)
23
 {
24
-        struct spa_pod_builder b = { 0 };
25
-        uint8_t buffer4096;
26
-        uint32_t state;
27
-        struct spa_pod *param;
28
-        int res;
29
+   struct spa_pod_builder b = { 0 };
30
+   uint8_t buffer4096;
31
+   uint32_t state;
32
+   struct spa_pod *param;
33
+   int res, count = 0;
34
 
35
-        spa_log_error(this->log, "params %s: %d:%d (%s) %s",
36
+   spa_log_error(this->log, "params %s: %d:%d (%s) %s",
37
            spa_debug_type_find_name(spa_type_param, id),
38
-           direction, port_id, debug, spa_strerror(err));
39
+           direction, port_id, debug, err ? spa_strerror(err) : "no matching params");
40
    if (err == -EBUSY)
41
        return 0;
42
 
43
-        state = 0;
44
-        while (true) {
45
-                spa_pod_builder_init(&b, buffer, sizeof(buffer));
46
-                res = spa_node_port_enum_params_sync(node,
47
-                                       direction, port_id,
48
-                                       id, &state,
49
-                                       NULL, &param, &b);
50
-                if (res != 1) {
51
+   if (filter) {
52
+       spa_log_error(this->log, "with this filter:");
53
+       spa_debug_pod(2, NULL, filter);
54
+   } else {
55
+       spa_log_error(this->log, "there was no filter");
56
+   }
57
+
58
+   state = 0;
59
+   while (true) {
60
+       spa_pod_builder_init(&b, buffer, sizeof(buffer));
61
+       res = spa_node_port_enum_params_sync(node,
62
+                   direction, port_id,
63
+                   id, &state,
64
+                   NULL, &param, &b);
65
+       if (res != 1) {
66
            if (res < 0)
67
                spa_log_error(this->log, "  error: %s", spa_strerror(res));
68
-                        break;
69
+           break;
70
        }
71
-                spa_debug_pod(2, NULL, param);
72
-        }
73
-
74
-        spa_log_error(this->log, "failed filter:");
75
-        if (filter)
76
-                spa_debug_pod(2, NULL, filter);
77
+       spa_log_error(this->log, "unmatched %s %d:", debug, count);
78
+       spa_debug_pod(2, NULL, param);
79
+       count++;
80
+   }
81
+   if (count == 0)
82
+       spa_log_error(this->log, "could not get any %s", debug);
83
 
84
-        return 0;
85
+   return 0;
86
 }
87
 
88
 static int negotiate_buffers(struct impl *this)
89
@@ -832,6 +844,9 @@
90
    struct impl *this = data;
91
    uint32_t i;
92
 
93
+   spa_log_debug(this->log, "%p: info change:%08"PRIx64, this,
94
+           info->change_mask);
95
+
96
    if (info->change_mask & SPA_NODE_CHANGE_MASK_PARAMS) {
97
        for (i = 0; i < info->n_params; i++) {
98
            uint32_t idx;
99
@@ -856,8 +871,10 @@
100
                (this->paramsidx.flags & SPA_PARAM_INFO_SERIAL) |
101
                (info->paramsi.flags & SPA_PARAM_INFO_READWRITE);
102
 
103
-           if (!this->add_listener)
104
+           if (!this->add_listener) {
105
                this->paramsidx.user++;
106
+               spa_log_debug(this->log, "param %d changed", info->paramsi.id);
107
+           }
108
        }
109
    }
110
    emit_node_info(this, false);
111
@@ -876,7 +893,7 @@
112
            port_id--;
113
    }
114
 
115
-   spa_log_trace(this->log, "%p: port info %d:%d", this,
116
+   spa_log_debug(this->log, "%p: port info %d:%d", this,
117
            direction, port_id);
118
 
119
    if (this->target != this->follower)
120
@@ -906,6 +923,9 @@
121
    struct impl *this = data;
122
    uint32_t i;
123
 
124
+   spa_log_debug(this->log, "%p: info change:%08"PRIx64, this,
125
+           info->change_mask);
126
+
127
    if (this->follower_removing)
128
        return;
129
 
130
@@ -959,11 +979,17 @@
131
                (this->paramsidx.flags & SPA_PARAM_INFO_SERIAL) |
132
                (info->paramsi.flags & SPA_PARAM_INFO_READWRITE);
133
 
134
-           if (!this->add_listener)
135
+           if (!this->add_listener) {
136
                this->paramsidx.user++;
137
+               spa_log_debug(this->log, "param %d changed", info->paramsi.id);
138
+           }
139
        }
140
    }
141
    emit_node_info(this, false);
142
+
143
+   spa_zero(this->info.props);
144
+   this->info.change_mask &= ~SPA_NODE_CHANGE_MASK_PROPS;
145
+
146
 }
147
 
148
 static int recalc_latency(struct impl *this, enum spa_direction direction, uint32_t port_id)
149
@@ -1044,12 +1070,15 @@
150
 
151
            if (idx == IDX_Latency) {
152
                res = recalc_latency(this, direction, port_id);
153
-               spa_log_debug(this->log, "latency: %d", res);
154
+               spa_log_debug(this->log, "latency: %d (%s)", res,
155
+                       spa_strerror(res));
156
            }
157
 
158
            this->info.change_mask |= SPA_NODE_CHANGE_MASK_PARAMS;
159
-           if (!this->add_listener)
160
+           if (!this->add_listener) {
161
                this->paramsidx.user++;
162
+               spa_log_debug(this->log, "param %d changed", info->paramsi.id);
163
+           }
164
        }
165
    }
166
    emit_node_info(this, false);
167
@@ -1069,11 +1098,29 @@
168
    spa_node_emit_result(&this->hooks, seq, res, type, result);
169
 }
170
 
171
+static void follower_event(void *data, const struct spa_event *event)
172
+{
173
+   struct impl *this = data;
174
+
175
+   spa_log_trace(this->log, "%p: event %d", this, SPA_EVENT_TYPE(event));
176
+
177
+   switch (SPA_NODE_EVENT_ID(event)) {
178
+   case SPA_NODE_EVENT_Error:
179
+       /* Forward errors */
180
+       spa_node_emit_event(&this->hooks, event);
181
+       break;
182
+   default:
183
+       /* Ignore other events */
184
+       break;
185
+   }
186
+}
187
+
188
 static const struct spa_node_events follower_node_events = {
189
    SPA_VERSION_NODE_EVENTS,
190
    .info = follower_info,
191
    .port_info = follower_port_info,
192
    .result = follower_result,
193
+   .event = follower_event,
194
 };
195
 
196
 static int follower_ready(void *data, int status)
197
@@ -1313,7 +1360,7 @@
198
 static int impl_node_process(void *object)
199
 {
200
    struct impl *this = object;
201
pipewire-0.3.51.tar.gz/spa/plugins/audioconvert/audioconvert.c -> pipewire-0.3.52.tar.gz/spa/plugins/audioconvert/audioconvert.c Changed
110
 
1
@@ -614,13 +614,6 @@
2
    return res;
3
 }
4
 
5
-static void on_node_result(void *data, int seq, int res, uint32_t type, const void *result)
6
-{
7
-   struct impl *this = data;
8
-   spa_log_trace(this->log, "%p: result %d %d", this, seq, res);
9
-   spa_node_emit_result(&this->hooks, seq, res, type, result);
10
-}
11
-
12
 static void fmt_input_port_info(void *data,
13
        enum spa_direction direction, uint32_t port,
14
        const struct spa_port_info *info)
15
@@ -642,7 +635,6 @@
16
 static const struct spa_node_events fmt_input_events = {
17
    SPA_VERSION_NODE_EVENTS,
18
    .port_info = fmt_input_port_info,
19
-   .result = on_node_result,
20
 };
21
 
22
 static void fmt_output_port_info(void *data,
23
@@ -663,7 +655,6 @@
24
 static const struct spa_node_events fmt_output_events = {
25
    SPA_VERSION_NODE_EVENTS,
26
    .port_info = fmt_output_port_info,
27
-   .result = on_node_result,
28
 };
29
 
30
 static void on_channelmix_info(void *data, const struct spa_node_info *info)
31
@@ -706,12 +697,6 @@
32
 static const struct spa_node_events channelmix_events = {
33
    SPA_VERSION_NODE_EVENTS,
34
    .info = on_channelmix_info,
35
-   .result = on_node_result,
36
-};
37
-
38
-static const struct spa_node_events proxy_events = {
39
-   SPA_VERSION_NODE_EVENTS,
40
-   .result = on_node_result,
41
 };
42
 
43
 static int reconfigure_mode(struct impl *this, enum spa_param_port_config_mode mode,
44
@@ -1020,6 +1005,7 @@
45
    uint8_t buffer4096;
46
    struct spa_result_node_params result;
47
    uint32_t count = 0;
48
+   int res;
49
 
50
    spa_return_val_if_fail(this != NULL, -EINVAL);
51
    spa_return_val_if_fail(num != 0, -EINVAL);
52
@@ -1029,24 +1015,11 @@
53
    result.id = id;
54
    result.next = start;
55
       next:
56
-   result.index = result.next++;
57
+   result.index = result.next;
58
 
59
    spa_pod_builder_init(&b, buffer, sizeof(buffer));
60
 
61
    switch (id) {
62
-   case SPA_PARAM_PropInfo:
63
-       switch (result.index) {
64
-       case 0:
65
-           param = spa_pod_builder_add_object(&b,
66
-               SPA_TYPE_OBJECT_PropInfo, id,
67
-               SPA_PROP_INFO_id,   SPA_POD_Id(SPA_PROP_volume),
68
-               SPA_PROP_INFO_type, SPA_POD_CHOICE_RANGE_Float(1.0, 0.0, 10.0));
69
-           break;
70
-       default:
71
-           return 0;
72
-       }
73
-       break;
74
-
75
    case SPA_PARAM_IO:
76
        switch (result.index) {
77
        case 0:
78
@@ -1064,6 +1037,7 @@
79
        default:
80
            return 0;
81
        }
82
+       result.next++;
83
        break;
84
    default:
85
    {
86
@@ -1074,8 +1048,12 @@
87
        else
88
            target = this->fmtdirection;
89
 
90
-       return spa_node_port_enum_params(target, seq, direction, port_id,
91
-           id, start, num, filter);
92
+       res = spa_node_port_enum_params_sync(target,
93
+                      direction, port_id,
94
+                      id, &result.next,
95
+                      NULL, &param, &b);
96
+       if (res != 1)
97
+           return res;
98
    }
99
    }
100
 
101
@@ -1424,8 +1402,6 @@
102
 
103
    spa_node_add_listener(this->channelmix,
104
            &this->listener0, &channelmix_events, this);
105
-   spa_node_add_listener(this->merger,
106
-           &this->listener1, &proxy_events, this);
107
 
108
    return 0;
109
 }
110
pipewire-0.3.51.tar.gz/spa/plugins/audioconvert/resample.c -> pipewire-0.3.52.tar.gz/spa/plugins/audioconvert/resample.c Changed
10
 
1
@@ -1068,7 +1068,7 @@
2
    if (passthrough) {
3
        uint32_t len = SPA_MIN(in_len, out_len);
4
        for (i = 0; i < sb->n_datas; i++)
5
-           memcpy(dst_datasi, src_datasi, len * sizeof(float));
6
+           spa_memcpy(dst_datasi, src_datasi, len * sizeof(float));
7
        out_len = in_len = len;
8
    } else {
9
        resample_process(&this->resample, src_datas, &in_len, dst_datas, &out_len);
10
pipewire-0.3.51.tar.gz/spa/plugins/audiomixer/mix-ops-avx.c -> pipewire-0.3.52.tar.gz/spa/plugins/audiomixer/mix-ops-avx.c Changed
10
 
1
@@ -126,7 +126,7 @@
2
    if (n_src == 0)
3
        memset(dst, 0, n_samples * ops->n_channels * sizeof(float));
4
    else if (dst != src0)
5
-       memcpy(dst, src0, n_samples * ops->n_channels * sizeof(float));
6
+       spa_memcpy(dst, src0, n_samples * ops->n_channels * sizeof(float));
7
 
8
    for (i = 1; i + 2 < n_src; i += 3)
9
        mix_4(dst, srci, srci + 1, srci + 2, n_samples);
10
pipewire-0.3.51.tar.gz/spa/plugins/audiomixer/mix-ops-c.c -> pipewire-0.3.52.tar.gz/spa/plugins/audiomixer/mix-ops-c.c Changed
109
 
1
@@ -40,7 +40,7 @@
2
    if (n_src == 0)
3
        memset(dst, 0, n_samples * ops->n_channels * sizeof(int8_t));
4
    else if (dst != src0)
5
-       memcpy(dst, src0, n_samples * ops->n_channels * sizeof(int8_t));
6
+       spa_memcpy(dst, src0, n_samples * ops->n_channels * sizeof(int8_t));
7
 
8
    for (i = 1; i < n_src; i++) {
9
        const int8_t *s = srci;
10
@@ -59,7 +59,7 @@
11
    if (n_src == 0)
12
        memset(dst, 0, n_samples * ops->n_channels * sizeof(uint8_t));
13
    else if (dst != src0)
14
-       memcpy(dst, src0, n_samples * ops->n_channels * sizeof(uint8_t));
15
+       spa_memcpy(dst, src0, n_samples * ops->n_channels * sizeof(uint8_t));
16
 
17
    for (i = 1; i < n_src; i++) {
18
        const uint8_t *s = srci;
19
@@ -78,7 +78,7 @@
20
    if (n_src == 0)
21
        memset(dst, 0, n_samples * ops->n_channels * sizeof(int16_t));
22
    else if (dst != src0)
23
-       memcpy(dst, src0, n_samples * ops->n_channels * sizeof(int16_t));
24
+       spa_memcpy(dst, src0, n_samples * ops->n_channels * sizeof(int16_t));
25
 
26
    for (i = 1; i < n_src; i++) {
27
        const int16_t *s = srci;
28
@@ -97,7 +97,7 @@
29
    if (n_src == 0)
30
        memset(dst, 0, n_samples * ops->n_channels * sizeof(uint16_t));
31
    else if (dst != src0)
32
-       memcpy(dst, src0, n_samples * ops->n_channels * sizeof(uint16_t));
33
+       spa_memcpy(dst, src0, n_samples * ops->n_channels * sizeof(uint16_t));
34
 
35
    for (i = 1; i < n_src; i++) {
36
        const uint16_t *s = srci;
37
@@ -116,7 +116,7 @@
38
    if (n_src == 0)
39
        memset(dst, 0, n_samples * ops->n_channels * sizeof(uint8_t) * 3);
40
    else if (dst != src0)
41
-       memcpy(dst, src0, n_samples * ops->n_channels * sizeof(uint8_t) * 3);
42
+       spa_memcpy(dst, src0, n_samples * ops->n_channels * sizeof(uint8_t) * 3);
43
 
44
    for (i = 1; i < n_src; i++) {
45
        const uint8_t *s = srci;
46
@@ -138,7 +138,7 @@
47
    if (n_src == 0)
48
        memset(dst, 0, n_samples * ops->n_channels * sizeof(uint8_t) * 3);
49
    else if (dst != src0)
50
-       memcpy(dst, src0, n_samples * ops->n_channels * sizeof(uint8_t) * 3);
51
+       spa_memcpy(dst, src0, n_samples * ops->n_channels * sizeof(uint8_t) * 3);
52
 
53
    for (i = 1; i < n_src; i++) {
54
        const uint8_t *s = srci;
55
@@ -160,7 +160,7 @@
56
    if (n_src == 0)
57
        memset(dst, 0, n_samples * ops->n_channels * sizeof(int32_t));
58
    else if (dst != src0)
59
-       memcpy(dst, src0, n_samples * ops->n_channels * sizeof(int32_t));
60
+       spa_memcpy(dst, src0, n_samples * ops->n_channels * sizeof(int32_t));
61
 
62
    for (i = 1; i < n_src; i++) {
63
        const int32_t *s = srci;
64
@@ -179,7 +179,7 @@
65
    if (n_src == 0)
66
        memset(dst, 0, n_samples * ops->n_channels * sizeof(uint32_t));
67
    else if (dst != src0)
68
-       memcpy(dst, src0, n_samples * ops->n_channels * sizeof(uint32_t));
69
+       spa_memcpy(dst, src0, n_samples * ops->n_channels * sizeof(uint32_t));
70
 
71
    for (i = 1; i < n_src; i++) {
72
        const uint32_t *s = srci;
73
@@ -198,7 +198,7 @@
74
    if (n_src == 0)
75
        memset(dst, 0, n_samples * ops->n_channels * sizeof(int32_t));
76
    else if (dst != src0)
77
-       memcpy(dst, src0, n_samples * ops->n_channels * sizeof(int32_t));
78
+       spa_memcpy(dst, src0, n_samples * ops->n_channels * sizeof(int32_t));
79
 
80
    for (i = 1; i < n_src; i++) {
81
        const int32_t *s = srci;
82
@@ -217,7 +217,7 @@
83
    if (n_src == 0)
84
        memset(dst, 0, n_samples * ops->n_channels * sizeof(uint32_t));
85
    else if (dst != src0)
86
-       memcpy(dst, src0, n_samples * ops->n_channels * sizeof(uint32_t));
87
+       spa_memcpy(dst, src0, n_samples * ops->n_channels * sizeof(uint32_t));
88
 
89
    for (i = 1; i < n_src; i++) {
90
        const uint32_t *s = srci;
91
@@ -236,7 +236,7 @@
92
    if (n_src == 0)
93
        memset(dst, 0, n_samples * ops->n_channels * sizeof(float));
94
    else if (dst != src0)
95
-       memcpy(dst, src0, n_samples * ops->n_channels * sizeof(float));
96
+       spa_memcpy(dst, src0, n_samples * ops->n_channels * sizeof(float));
97
 
98
    for (i = 1; i < n_src; i++) {
99
        const float *s = srci;
100
@@ -255,7 +255,7 @@
101
    if (n_src == 0)
102
        memset(dst, 0, n_samples * ops->n_channels * sizeof(double));
103
    else if (dst != src0)
104
-       memcpy(dst, src0, n_samples * ops->n_channels * sizeof(double));
105
+       spa_memcpy(dst, src0, n_samples * ops->n_channels * sizeof(double));
106
 
107
    for (i = 1; i < n_src; i++) {
108
        const double *s = srci;
109
pipewire-0.3.51.tar.gz/spa/plugins/audiomixer/mix-ops-sse.c -> pipewire-0.3.52.tar.gz/spa/plugins/audiomixer/mix-ops-sse.c Changed
10
 
1
@@ -81,7 +81,7 @@
2
    if (n_src == 0)
3
        memset(dst, 0, n_samples * ops->n_channels * sizeof(float));
4
    else if (dst != src0)
5
-       memcpy(dst, src0, n_samples * ops->n_channels * sizeof(float));
6
+       spa_memcpy(dst, src0, n_samples * ops->n_channels * sizeof(float));
7
 
8
    for (i = 1; i < n_src; i++) {
9
        mix_2(dst, srci, n_samples * ops->n_channels);
10
pipewire-0.3.51.tar.gz/spa/plugins/audiomixer/mix-ops-sse2.c -> pipewire-0.3.52.tar.gz/spa/plugins/audiomixer/mix-ops-sse2.c Changed
10
 
1
@@ -81,7 +81,7 @@
2
    if (n_src == 0)
3
        memset(dst, 0, n_samples * ops->n_channels * sizeof(double));
4
    else if (dst != src0)
5
-       memcpy(dst, src0, n_samples * ops->n_channels * sizeof(double));
6
+       spa_memcpy(dst, src0, n_samples * ops->n_channels * sizeof(double));
7
 
8
    for (i = 1; i < n_src; i++) {
9
        mix_2(dst, srci, n_samples * ops->n_channels);
10
pipewire-0.3.51.tar.gz/spa/plugins/audiomixer/mixer-dsp.c -> pipewire-0.3.52.tar.gz/spa/plugins/audiomixer/mixer-dsp.c Changed
67
 
1
@@ -690,9 +690,9 @@
2
        outio->buffer_id = SPA_ID_INVALID;
3
    }
4
 
5
-        buffers = alloca(MAX_PORTS * sizeof(struct buffer *));
6
-        datas = alloca(MAX_PORTS * sizeof(void *));
7
-        n_buffers = 0;
8
+   buffers = alloca(MAX_PORTS * sizeof(struct buffer *));
9
+   datas = alloca(MAX_PORTS * sizeof(void *));
10
+   n_buffers = 0;
11
 
12
    maxsize = UINT32_MAX;
13
 
14
@@ -700,6 +700,8 @@
15
        struct port *inport = GET_IN_PORT(this, i);
16
        struct spa_io_buffers *inio = NULL;
17
        struct buffer *inb;
18
+       struct spa_data *bd;
19
+       uint32_t size, offs;
20
 
21
        if (SPA_UNLIKELY(!PORT_VALID(inport) ||
22
            (inio = inport->io) == NULL ||
23
@@ -715,21 +717,26 @@
24
        }
25
 
26
        inb = &inport->buffersinio->buffer_id;
27
-       maxsize = SPA_MIN(inb->buffer->datas0.chunk->size, maxsize);
28
+       bd = &inb->buffer->datas0;
29
 
30
-       spa_log_trace_fp(this->log, "%p: mix input %d %p->%p %d %d %d", this,
31
-               i, inio, outio, inio->status, inio->buffer_id, maxsize);
32
+       offs = SPA_MIN(bd->chunk->offset, bd->maxsize);
33
+       size = SPA_MIN(bd->maxsize - offs, bd->chunk->size);
34
+       maxsize = SPA_MIN(maxsize, size);
35
 
36
-       datasn_buffers = inb->buffer->datas0.data;
37
+       spa_log_trace_fp(this->log, "%p: mix input %d %p->%p %d %d %d:%d", this,
38
+               i, inio, outio, inio->status, inio->buffer_id,
39
+               offs, size);
40
+
41
+       datasn_buffers = SPA_PTROFF(bd->data, offs, void);
42
        buffersn_buffers++ = inb;
43
        inio->status = SPA_STATUS_NEED_DATA;
44
    }
45
 
46
    outb = dequeue_buffer(this, outport);
47
-        if (SPA_UNLIKELY(outb == NULL)) {
48
-                spa_log_trace(this->log, "%p: out of buffers", this);
49
-                return -EPIPE;
50
-        }
51
+   if (SPA_UNLIKELY(outb == NULL)) {
52
+       spa_log_trace(this->log, "%p: out of buffers", this);
53
+       return -EPIPE;
54
+   }
55
 
56
    if (n_buffers == 1) {
57
        *outb->buffer = *buffers0->buffer;
58
@@ -743,6 +750,8 @@
59
        d0.chunk->size = maxsize;
60
        d0.chunk->stride = sizeof(float);
61
 
62
+       spa_log_trace_fp(this->log, "%p: %d mix %d", this, n_buffers, maxsize);
63
+
64
        mix_ops_process(&this->ops, d0.data,
65
                datas, n_buffers, maxsize / sizeof(float));
66
    }
67
pipewire-0.3.51.tar.gz/spa/plugins/audiotestsrc/audiotestsrc.c -> pipewire-0.3.52.tar.gz/spa/plugins/audiotestsrc/audiotestsrc.c Changed
30
 
1
@@ -277,6 +277,7 @@
2
 
3
    if (id == SPA_PARAM_Props) {
4
        struct props *p = &this->props;
5
+       struct port *port = &this->port;
6
 
7
        if (param == NULL) {
8
            reset_props(p);
9
@@ -290,9 +291,9 @@
10
            SPA_PROP_volume,    SPA_POD_OPT_Float(&p->volume));
11
 
12
        if (p->live)
13
-           this->info.flags |= SPA_PORT_FLAG_LIVE;
14
+           port->info.flags |= SPA_PORT_FLAG_LIVE;
15
        else
16
-           this->info.flags &= ~SPA_PORT_FLAG_LIVE;
17
+           port->info.flags &= ~SPA_PORT_FLAG_LIVE;
18
    }
19
    else
20
        return -ENOENT;
21
@@ -1081,7 +1082,7 @@
22
    port->info = SPA_PORT_INFO_INIT();
23
    port->info.flags = SPA_PORT_FLAG_NO_REF;
24
    if (this->props.live)
25
-       this->info.flags |= SPA_PORT_FLAG_LIVE;
26
+       port->info.flags |= SPA_PORT_FLAG_LIVE;
27
    port->params0 = SPA_PARAM_INFO(SPA_PARAM_EnumFormat, SPA_PARAM_INFO_READ);
28
    port->params1 = SPA_PARAM_INFO(SPA_PARAM_Meta, SPA_PARAM_INFO_READ);
29
    port->params2 = SPA_PARAM_INFO(SPA_PARAM_IO, SPA_PARAM_INFO_READ);
30
pipewire-0.3.51.tar.gz/spa/plugins/bluez5/a2dp-codec-aac.c -> pipewire-0.3.52.tar.gz/spa/plugins/bluez5/a2dp-codec-aac.c Changed
10
 
1
@@ -493,7 +493,7 @@
2
        return -EINVAL;
3
 
4
    *dst_out = out_args.numOutBytes;
5
-   *need_flush = 1;
6
+   *need_flush = NEED_FLUSH_ALL;
7
 
8
    /* RFC6416: It is set to 1 to indicate that the RTP packet contains a complete
9
         * audioMuxElement or the last fragment of an audioMuxElement */
10
pipewire-0.3.51.tar.gz/spa/plugins/bluez5/a2dp-codec-aptx.c -> pipewire-0.3.52.tar.gz/spa/plugins/bluez5/a2dp-codec-aptx.c Changed
19
 
1
@@ -404,7 +404,7 @@
2
 
3
    avail_dst_size = (this->max_frames - this->frame_count) * this->frame_length;
4
    if (SPA_UNLIKELY(dst_size < avail_dst_size)) {
5
-       *need_flush = 1;
6
+       *need_flush = NEED_FLUSH_ALL;
7
        return 0;
8
    }
9
 
10
@@ -414,7 +414,7 @@
11
        return -EINVAL;
12
 
13
    this->frame_count += *dst_out / this->frame_length;
14
-   *need_flush = this->frame_count >= this->max_frames;
15
+   *need_flush = (this->frame_count >= this->max_frames) ? NEED_FLUSH_ALL : NEED_FLUSH_NO;
16
    return res;
17
 }
18
 
19
pipewire-0.3.51.tar.gz/spa/plugins/bluez5/a2dp-codec-caps.h -> pipewire-0.3.52.tar.gz/spa/plugins/bluez5/a2dp-codec-caps.h Changed
52
 
1
@@ -202,6 +202,37 @@
2
 
3
 #define FASTSTREAM_SOURCE_SAMPLING_FREQ_16000   0x2
4
 
5
+#define LC3PLUS_HR_GET_FRAME_DURATION(a) ((a).frame_duration & 0xf0)
6
+#define LC3PLUS_HR_INIT_FRAME_DURATION(v) \
7
+   .frame_duration = ((v) & 0xf0),
8
+#define LC3PLUS_HR_SET_FRAME_DURATION(a, v)        \
9
+   do {                        \
10
+       (a).frame_duration = ((v) & 0xf0);  \
11
+   } while (0)
12
+
13
+#define LC3PLUS_HR_GET_FREQUENCY(a) (((a).frequency1 << 8) | (a).frequency2)
14
+#define LC3PLUS_HR_INIT_FREQUENCY(v)       \
15
+   .frequency1 = (((v) >> 8) & 0xff),  \
16
+   .frequency2 = ((v) & 0xff),
17
+#define LC3PLUS_HR_SET_FREQUENCY(a, v)         \
18
+   do {                        \
19
+       (a).frequency1 = ((v) >> 8) & 0xff; \
20
+       (a).frequency2 = (v) & 0xff;        \
21
+   } while (0)
22
+
23
+#define LC3PLUS_HR_VENDOR_ID       0x000008a9
24
+#define LC3PLUS_HR_CODEC_ID        0x0001
25
+
26
+#define LC3PLUS_HR_FRAME_DURATION_10MS (1 << 6)
27
+#define LC3PLUS_HR_FRAME_DURATION_5MS  (1 << 5)
28
+#define LC3PLUS_HR_FRAME_DURATION_2_5MS    (1 << 4)
29
+
30
+#define LC3PLUS_HR_CHANNELS_1      (1 << 7)
31
+#define LC3PLUS_HR_CHANNELS_2      (1 << 6)
32
+
33
+#define LC3PLUS_HR_SAMPLING_FREQ_48000 (1 << 8)
34
+#define LC3PLUS_HR_SAMPLING_FREQ_96000 (1 << 7)
35
+
36
 typedef struct {
37
    uint32_t vendor_id;
38
    uint16_t codec_id;
39
@@ -352,4 +383,12 @@
40
         uint8_t good_working_level1;
41
 } __attribute__ ((packed)) a2dp_aptx_ll_ext_t;
42
 
43
+typedef struct {
44
+        a2dp_vendor_codec_t info;
45
+   uint8_t frame_duration;
46
+   uint8_t channels;
47
+   uint8_t frequency1;
48
+   uint8_t frequency2;
49
+} __attribute__ ((packed)) a2dp_lc3plus_hr_t;
50
+
51
 #endif
52
pipewire-0.3.51.tar.gz/spa/plugins/bluez5/a2dp-codec-faststream.c -> pipewire-0.3.52.tar.gz/spa/plugins/bluez5/a2dp-codec-faststream.c Changed
10
 
1
@@ -316,7 +316,7 @@
2
    }
3
 
4
    this->frame_count += res / this->codesize;
5
-   *need_flush = this->frame_count >= this->max_frames;
6
+   *need_flush = (this->frame_count >= this->max_frames) ? NEED_FLUSH_ALL : NEED_FLUSH_NO;
7
    return res;
8
 }
9
 
10
pipewire-0.3.52.tar.gz/spa/plugins/bluez5/a2dp-codec-lc3plus.c Added
201
 
1
@@ -0,0 +1,788 @@
2
+/* Spa A2DP LC3plus HR codec
3
+ *
4
+ * Copyright © 2020 Wim Taymans
5
+ * Copyright © 2022 Pauli Virtanen
6
+ *
7
+ * Permission is hereby granted, free of charge, to any person obtaining a
8
+ * copy of this software and associated documentation files (the "Software"),
9
+ * to deal in the Software without restriction, including without limitation
10
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11
+ * and/or sell copies of the Software, and to permit persons to whom the
12
+ * Software is furnished to do so, subject to the following conditions:
13
+ *
14
+ * The above copyright notice and this permission notice (including the next
15
+ * paragraph) shall be included in all copies or substantial portions of the
16
+ * Software.
17
+ *
18
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
21
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
23
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
24
+ * DEALINGS IN THE SOFTWARE.
25
+ */
26
+
27
+#include <unistd.h>
28
+#include <stddef.h>
29
+#include <errno.h>
30
+#include <arpa/inet.h>
31
+#if __BYTE_ORDER != __LITTLE_ENDIAN
32
+#include <byteswap.h>
33
+#endif
34
+
35
+#include <spa/param/audio/format.h>
36
+#include <spa/param/audio/format-utils.h>
37
+
38
+#ifdef HAVE_LC3PLUS_H
39
+#include <lc3plus.h>
40
+#else
41
+#include <lc3.h>
42
+#endif
43
+
44
+#include "rtp.h"
45
+#include "a2dp-codecs.h"
46
+
47
+#define BITRATE_MIN 96000
48
+#define BITRATE_MAX 512000
49
+#define BITRATE_DEFAULT 160000
50
+
51
+struct dec_data {
52
+   int frame_size;
53
+   int fragment_size;
54
+   int fragment_count;
55
+   uint8_t fragmentLC3PLUS_MAX_BYTES;
56
+};
57
+
58
+struct enc_data {
59
+   struct rtp_header *header;
60
+   struct rtp_payload *payload;
61
+
62
+   int samples;
63
+   int codesize;
64
+
65
+   int packet_size;
66
+   int fragment_size;
67
+   int fragment_count;
68
+   void *fragment;
69
+
70
+   int bitrate;
71
+   int next_bitrate;
72
+};
73
+
74
+struct impl {
75
+   LC3PLUS_Enc *enc;
76
+   LC3PLUS_Dec *dec;
77
+
78
+   int mtu;
79
+   int samplerate;
80
+   int channels;
81
+   int frame_dms;
82
+   int bitrate;
83
+
84
+   struct dec_data d;
85
+   struct enc_data e;
86
+
87
+   int32_t buf2LC3PLUS_MAX_SAMPLES;
88
+};
89
+
90
+static int codec_fill_caps(const struct a2dp_codec *codec, uint32_t flags,
91
+       uint8_t capsA2DP_MAX_CAPS_SIZE)
92
+{
93
+   const a2dp_lc3plus_hr_t a2dp_lc3plus_hr = {
94
+       .info = codec->vendor,
95
+       LC3PLUS_HR_INIT_FRAME_DURATION(LC3PLUS_HR_FRAME_DURATION_10MS
96
+               | LC3PLUS_HR_FRAME_DURATION_5MS
97
+               | LC3PLUS_HR_FRAME_DURATION_2_5MS)
98
+       .channels = LC3PLUS_HR_CHANNELS_1 | LC3PLUS_HR_CHANNELS_2,
99
+       LC3PLUS_HR_INIT_FREQUENCY(LC3PLUS_HR_SAMPLING_FREQ_48000
100
+               | (lc3plus_samplerate_supported(96000) ? LC3PLUS_HR_SAMPLING_FREQ_96000 : 0))
101
+   };
102
+   memcpy(caps, &a2dp_lc3plus_hr, sizeof(a2dp_lc3plus_hr));
103
+   return sizeof(a2dp_lc3plus_hr);
104
+}
105
+
106
+static int codec_select_config(const struct a2dp_codec *codec, uint32_t flags,
107
+       const void *caps, size_t caps_size,
108
+       const struct a2dp_codec_audio_info *info,
109
+       const struct spa_dict *settings, uint8_t configA2DP_MAX_CAPS_SIZE)
110
+{
111
+   a2dp_lc3plus_hr_t conf;
112
+
113
+   if (caps_size < sizeof(conf))
114
+       return -EINVAL;
115
+
116
+   memcpy(&conf, caps, sizeof(conf));
117
+
118
+   if (codec->vendor.vendor_id != conf.info.vendor_id ||
119
+       codec->vendor.codec_id != conf.info.codec_id)
120
+       return -ENOTSUP;
121
+
122
+   if ((LC3PLUS_HR_GET_FREQUENCY(conf) & LC3PLUS_HR_SAMPLING_FREQ_48000)
123
+           && lc3plus_samplerate_supported(48000))
124
+       LC3PLUS_HR_SET_FREQUENCY(conf, LC3PLUS_HR_SAMPLING_FREQ_48000);
125
+   else if ((LC3PLUS_HR_GET_FREQUENCY(conf) & LC3PLUS_HR_SAMPLING_FREQ_96000)
126
+           && lc3plus_samplerate_supported(96000))
127
+       LC3PLUS_HR_SET_FREQUENCY(conf, LC3PLUS_HR_SAMPLING_FREQ_96000);
128
+   else
129
+       return -ENOTSUP;
130
+
131
+   if ((conf.channels & LC3PLUS_HR_CHANNELS_2) &&
132
+           lc3plus_channels_supported(2))
133
+       conf.channels = LC3PLUS_HR_CHANNELS_2;
134
+   else if ((conf.channels & LC3PLUS_HR_CHANNELS_1) &&
135
+           lc3plus_channels_supported(1))
136
+       conf.channels = LC3PLUS_HR_CHANNELS_1;
137
+   else
138
+       return -ENOTSUP;
139
+
140
+   if (LC3PLUS_HR_GET_FRAME_DURATION(conf) & LC3PLUS_HR_FRAME_DURATION_10MS)
141
+       LC3PLUS_HR_SET_FRAME_DURATION(conf, LC3PLUS_HR_FRAME_DURATION_10MS);
142
+   else if (LC3PLUS_HR_GET_FRAME_DURATION(conf) & LC3PLUS_HR_FRAME_DURATION_5MS)
143
+       LC3PLUS_HR_SET_FRAME_DURATION(conf, LC3PLUS_HR_FRAME_DURATION_5MS);
144
+   else if (LC3PLUS_HR_GET_FRAME_DURATION(conf) & LC3PLUS_HR_FRAME_DURATION_2_5MS)
145
+       LC3PLUS_HR_SET_FRAME_DURATION(conf, LC3PLUS_HR_FRAME_DURATION_2_5MS);
146
+   else
147
+       return -ENOTSUP;
148
+
149
+   memcpy(config, &conf, sizeof(conf));
150
+
151
+   return sizeof(conf);
152
+}
153
+
154
+static int codec_caps_preference_cmp(const struct a2dp_codec *codec, const void *caps1, size_t caps1_size,
155
+       const void *caps2, size_t caps2_size, const struct a2dp_codec_audio_info *info)
156
+{
157
+   a2dp_lc3plus_hr_t conf1, conf2;
158
+   a2dp_lc3plus_hr_t *conf;
159
+   int res1, res2;
160
+   int a, b;
161
+
162
+   /* Order selected configurations by preference */
163
+   res1 = codec->select_config(codec, 0, caps1, caps1_size, info, NULL, (uint8_t *)&conf1);
164
+   res2 = codec->select_config(codec, 0, caps2, caps2_size, info , NULL, (uint8_t *)&conf2);
165
+
166
+#define PREFER_EXPR(expr)          \
167
+       do {                \
168
+           conf = &conf1;      \
169
+           a = (expr);     \
170
+           conf = &conf2;      \
171
+           b = (expr);     \
172
+           if (a != b)     \
173
+               return b - a;   \
174
+       } while (0)
175
+
176
+#define PREFER_BOOL(expr)  PREFER_EXPR((expr) ? 1 : 0)
177
+
178
+   /* Prefer valid */
179
+   a = (res1 > 0 && (size_t)res1 == sizeof(a2dp_lc3plus_hr_t)) ? 1 : 0;
180
+   b = (res2 > 0 && (size_t)res2 == sizeof(a2dp_lc3plus_hr_t)) ? 1 : 0;
181
+   if (!a || !b)
182
+       return b - a;
183
+
184
+   PREFER_BOOL(conf->channels & LC3PLUS_HR_CHANNELS_2);
185
+   PREFER_BOOL(LC3PLUS_HR_GET_FREQUENCY(*conf) & (LC3PLUS_HR_SAMPLING_FREQ_48000 | LC3PLUS_HR_SAMPLING_FREQ_96000));
186
+   PREFER_BOOL(LC3PLUS_HR_GET_FREQUENCY(*conf) & LC3PLUS_HR_SAMPLING_FREQ_48000);
187
+
188
+   return 0;
189
+
190
+#undef PREFER_EXPR
191
+#undef PREFER_BOOL
192
+}
193
+
194
+static int codec_enum_config(const struct a2dp_codec *codec,
195
+       const void *caps, size_t caps_size, uint32_t id, uint32_t idx,
196
+       struct spa_pod_builder *b, struct spa_pod **param)
197
+{
198
+   a2dp_lc3plus_hr_t conf;
199
+   struct spa_pod_frame f2;
200
+   struct spa_pod_choice *choice;
201
pipewire-0.3.51.tar.gz/spa/plugins/bluez5/a2dp-codec-ldac.c -> pipewire-0.3.52.tar.gz/spa/plugins/bluez5/a2dp-codec-ldac.c Changed
10
 
1
@@ -565,7 +565,7 @@
2
    *dst_out = dst_used;
3
 
4
    this->payload->frame_count += frame_num;
5
-   *need_flush = this->payload->frame_count > 0;
6
+   *need_flush = (this->payload->frame_count > 0) ? NEED_FLUSH_ALL : NEED_FLUSH_NO;
7
 
8
    return src_used;
9
 }
10
pipewire-0.3.51.tar.gz/spa/plugins/bluez5/a2dp-codec-sbc.c -> pipewire-0.3.52.tar.gz/spa/plugins/bluez5/a2dp-codec-sbc.c Changed
10
 
1
@@ -605,7 +605,7 @@
2
    spa_assert(res == this->codesize);
3
 
4
    this->payload->frame_count += res / this->codesize;
5
-   *need_flush = this->payload->frame_count >= this->max_frames;
6
+   *need_flush = (this->payload->frame_count >= this->max_frames) ? NEED_FLUSH_ALL : NEED_FLUSH_NO;
7
    return res;
8
 }
9
 
10
pipewire-0.3.51.tar.gz/spa/plugins/bluez5/a2dp-codecs.h -> pipewire-0.3.52.tar.gz/spa/plugins/bluez5/a2dp-codecs.h Changed
14
 
1
@@ -66,6 +66,12 @@
2
 #define A2DP_CODEC_DEFAULT_RATE        48000
3
 #define A2DP_CODEC_DEFAULT_CHANNELS    2
4
 
5
+enum {
6
+   NEED_FLUSH_NO = 0,
7
+   NEED_FLUSH_ALL = 1,
8
+   NEED_FLUSH_FRAGMENT = 2,
9
+};
10
+
11
 struct a2dp_codec_audio_info {
12
    uint32_t rate;
13
    uint32_t channels;
14
pipewire-0.3.51.tar.gz/spa/plugins/bluez5/a2dp-sink.c -> pipewire-0.3.52.tar.gz/spa/plugins/bluez5/a2dp-sink.c Changed
162
 
1
@@ -157,6 +157,8 @@
2
    struct spa_audio_info codec_format;
3
 
4
    int need_flush;
5
+   bool fragment;
6
+   uint64_t fragment_timeout;
7
    uint32_t block_size;
8
    uint8_t bufferBUFFER_SIZE;
9
    uint32_t buffer_used;
10
@@ -436,6 +438,7 @@
11
    }
12
    this->need_flush = 0;
13
    this->frame_count = 0;
14
+   this->fragment = false;
15
    this->buffer_used = this->codec->start_encode(this->codec_data,
16
            this->buffer, sizeof(this->buffer),
17
            this->seqnum++, this->timestamp);
18
@@ -533,6 +536,37 @@
19
    return processed;
20
 }
21
 
22
+static int encode_fragment(struct impl *this)
23
+{
24
+   int res;
25
+   size_t out_encoded;
26
+   struct port *port = &this->port;
27
+
28
+   spa_log_trace(this->log, "%p: encode fragment used %d, %d %d %d",
29
+           this, this->buffer_used, port->frame_size, this->block_size,
30
+           this->frame_count);
31
+
32
+   if (this->need_flush)
33
+       return 0;
34
+
35
+   res = this->codec->encode(this->codec_data,
36
+               NULL, 0,
37
+               this->buffer + this->buffer_used,
38
+               sizeof(this->buffer) - this->buffer_used,
39
+               &out_encoded, &this->need_flush);
40
+   if (res < 0)
41
+       return res;
42
+   if (res != 0)
43
+       return -EINVAL;
44
+
45
+   this->buffer_used += out_encoded;
46
+
47
+   spa_log_trace(this->log, "%p: processed fragment %zd used %d",
48
+           this, out_encoded, this->buffer_used);
49
+
50
+   return 0;
51
+}
52
+
53
 static int flush_buffer(struct impl *this)
54
 {
55
    spa_log_trace(this->log, "%p: used:%d block_size:%d", this,
56
@@ -596,6 +630,15 @@
57
    total_frames = 0;
58
 again:
59
    written = 0;
60
+   if (this->fragment && !this->need_flush) {
61
+       int res;
62
+       this->fragment = false;
63
+       if ((res = encode_fragment(this)) < 0) {
64
+           /* Error */
65
+           reset_buffer(this);
66
+           return res;
67
+       }
68
+   }
69
    while (!spa_list_is_empty(&port->ready) && !this->need_flush) {
70
        uint8_t *src;
71
        uint32_t n_bytes, n_frames;
72
@@ -706,6 +749,17 @@
73
        uint64_t timeout = (quantum > max_excess) ?
74
            (packet_time * (quantum - max_excess) / quantum) : 0;
75
 
76
+       if (this->need_flush == NEED_FLUSH_FRAGMENT) {
77
+           reset_buffer(this);
78
+           this->fragment = true;
79
+           this->fragment_timeout = (packet_samples > 0) ? timeout : this->fragment_timeout;
80
+           goto again;
81
+       }
82
+       if (this->fragment_timeout > 0) {
83
+           timeout = this->fragment_timeout;
84
+           this->fragment_timeout = 0;
85
+       }
86
+
87
        reset_buffer(this);
88
        if (now_time - this->last_error > SPA_NSEC_PER_SEC) {
89
            if (get_transport_unused_size(this) == (int)this->fd_buffer_size) {
90
@@ -1406,6 +1460,11 @@
91
    io = port->io;
92
    spa_return_val_if_fail(io != NULL, -EIO);
93
 
94
+   if (this->position && this->position->clock.flags & SPA_IO_CLOCK_FLAG_FREEWHEEL) {
95
+       io->status = SPA_STATUS_NEED_DATA;
96
+       return SPA_STATUS_HAVE_DATA;
97
+   }
98
+
99
    if (io->status == SPA_STATUS_HAVE_DATA && io->buffer_id < port->n_buffers) {
100
        struct buffer *b = &port->buffersio->buffer_id;
101
 
102
@@ -1424,6 +1483,15 @@
103
        io->status = SPA_STATUS_OK;
104
    }
105
    if (!spa_list_is_empty(&port->ready)) {
106
+       if (this->following) {
107
+           if (this->position) {
108
+               this->current_time = this->position->clock.nsec;
109
+           } else {
110
+               struct timespec now;
111
+               spa_system_clock_gettime(this->data_system, CLOCK_MONOTONIC, &now);
112
+               this->current_time = SPA_TIMESPEC_TO_NSEC(&now);
113
+           }
114
+       }
115
        if (this->need_flush)
116
            reset_buffer(this);
117
        flush_data(this, this->current_time);
118
@@ -1477,9 +1545,43 @@
119
    spa_loop_invoke(this->data_loop, do_transport_destroy, 0, NULL, 0, true, this);
120
 }
121
 
122
+static void transport_state_changed(void *data,
123
+   enum spa_bt_transport_state old,
124
+   enum spa_bt_transport_state state)
125
+{
126
+   struct impl *this = data;
127
+
128
+   spa_log_debug(this->log, "%p: transport %p state %d->%d", this, this->transport, old, state);
129
+
130
+   if (state < SPA_BT_TRANSPORT_STATE_ACTIVE && old == SPA_BT_TRANSPORT_STATE_ACTIVE &&
131
+           this->started) {
132
+       uint8_t buffer1024;
133
+       struct spa_pod_builder b = { 0 };
134
+
135
+       spa_log_debug(this->log, "%p: transport %p becomes inactive: stop and indicate error",
136
+               this, this->transport);
137
+
138
+       /*
139
+        * If establishing connection fails due to remote end not activating
140
+        * the transport, we won't get a write error, but instead see a transport
141
+        * state change.
142
+        *
143
+        * Stop and emit a node error, to let upper levels handle it.
144
+        */
145
+
146
+       do_stop(this);
147
+
148
+       spa_pod_builder_init(&b, buffer, sizeof(buffer));
149
+       spa_node_emit_event(&this->hooks,
150
+               spa_pod_builder_add_object(&b,
151
+                       SPA_TYPE_EVENT_Node, SPA_NODE_EVENT_Error));
152
+   }
153
+}
154
+
155
 static const struct spa_bt_transport_events transport_events = {
156
    SPA_VERSION_BT_TRANSPORT_EVENTS,
157
    .delay_changed = transport_delay_changed,
158
+   .state_changed = transport_state_changed,
159
    .destroy = transport_destroy,
160
 };
161
 
162
pipewire-0.3.51.tar.gz/spa/plugins/bluez5/a2dp-source.c -> pipewire-0.3.52.tar.gz/spa/plugins/bluez5/a2dp-source.c Changed
40
 
1
@@ -154,6 +154,7 @@
2
    struct spa_audio_info codec_format;
3
 
4
    uint8_t buffer_read4096;
5
+   uint8_t buffer_decoded65536;
6
    struct timespec now;
7
    uint64_t sample_count;
8
    uint64_t skip_count;
9
@@ -472,7 +473,6 @@
10
    struct spa_data *datas;
11
    struct buffer *buffer;
12
    uint32_t min_data;
13
-   uint8_t read_decoded4096;
14
 
15
    /* make sure the source is an input */
16
    if ((source->rmask & SPA_IO_IN) == 0) {
17
@@ -507,10 +507,10 @@
18
 
19
    /* decode */
20
    decoded = decode_data(this, this->buffer_read, size_read,
21
-           read_decoded, sizeof (read_decoded));
22
+           this->buffer_decoded, sizeof (this->buffer_decoded));
23
    if (decoded < 0) {
24
-       spa_log_error(this->log, "failed to decode data: %d", decoded);
25
-       goto stop;
26
+       spa_log_debug(this->log, "failed to decode data: %d", decoded);
27
+       return;
28
    }
29
    if (decoded == 0)
30
        return;
31
@@ -557,7 +557,7 @@
32
    avail = SPA_MIN(decoded, (int32_t)(datas0.maxsize - port->ready_offset));
33
    if (avail < decoded)
34
        spa_log_warn(this->log, "buffer too small (%d > %d)", decoded, avail);
35
-   memcpy ((uint8_t *)datas0.data + port->ready_offset, read_decoded, avail);
36
+   memcpy ((uint8_t *)datas0.data + port->ready_offset, this->buffer_decoded, avail);
37
    port->ready_offset += avail;
38
    this->sample_count += decoded / port->frame_size;
39
 
40
pipewire-0.3.51.tar.gz/spa/plugins/bluez5/backend-native.c -> pipewire-0.3.52.tar.gz/spa/plugins/bluez5/backend-native.c Changed
49
 
1
@@ -623,15 +623,21 @@
2
 
3
    spa_log_debug(backend->log, "key:%u value:%u", key, value);
4
 
5
-   if (key == SPA_BT_HFP_HF_IPHONEACCEV_KEY_BATTERY_LEVEL) {
6
+   switch (key) {
7
+   case SPA_BT_HFP_HF_IPHONEACCEV_KEY_BATTERY_LEVEL: {
8
        // Battery level is reported in range of 0-9, convert to 10-100%
9
        uint8_t level = (SPA_CLAMP(value, 0u, 9u) + 1) * 10;
10
        spa_log_debug(backend->log, "battery level: %d%%", (int) level);
11
 
12
        // TODO: report without Battery Provider (using props)
13
        spa_bt_device_report_battery_level(rfcomm->device, level);
14
-   } else {
15
+       break;
16
+   }
17
+   case SPA_BT_HFP_HF_IPHONEACCEV_KEY_DOCK_STATE:
18
+       break;
19
+   default:
20
        spa_log_warn(backend->log, "unknown AT+IPHONEACCEV key:%u value:%u", key, value);
21
+       break;
22
    }
23
 }
24
 
25
@@ -641,7 +647,10 @@
26
 
27
    spa_log_debug(backend->log, "indicator:%u value:%u", indicator, value);
28
 
29
-   if (indicator == SPA_BT_HFP_HF_INDICATOR_BATTERY_LEVEL) {
30
+   switch (indicator) {
31
+   case SPA_BT_HFP_HF_INDICATOR_ENHANCED_SAFETY:
32
+       break;
33
+   case SPA_BT_HFP_HF_INDICATOR_BATTERY_LEVEL:
34
        // Battery level is reported in range 0-100
35
        spa_log_debug(backend->log, "battery level: %u%%", value);
36
 
37
@@ -651,8 +660,10 @@
38
        } else {
39
            spa_log_warn(backend->log, "battery HF indicator %u outside of range 0, 100: %u", indicator, value);
40
        }
41
-   } else {
42
+       break;
43
+   default:
44
        spa_log_warn(backend->log, "unknown HF indicator:%u value:%u", indicator, value);
45
+       break;
46
    }
47
 }
48
 
49
pipewire-0.3.51.tar.gz/spa/plugins/bluez5/bluez5-dbus.c -> pipewire-0.3.52.tar.gz/spa/plugins/bluez5/bluez5-dbus.c Changed
165
 
1
@@ -50,6 +50,7 @@
2
 #include <spa/utils/string.h>
3
 #include <spa/utils/json.h>
4
 
5
+#include "config.h"
6
 #include "codec-loader.h"
7
 #include "player.h"
8
 #include "defs.h"
9
@@ -819,6 +820,29 @@
10
    free(adapter);
11
 }
12
 
13
+static uint32_t adapter_connectable_profiles(struct spa_bt_adapter *adapter)
14
+{
15
+   const uint32_t profiles = adapter->profiles;
16
+   uint32_t mask = 0;
17
+
18
+   if (profiles & SPA_BT_PROFILE_A2DP_SINK)
19
+       mask |= SPA_BT_PROFILE_A2DP_SOURCE;
20
+   if (profiles & SPA_BT_PROFILE_A2DP_SOURCE)
21
+       mask |= SPA_BT_PROFILE_A2DP_SINK;
22
+
23
+   if (profiles & SPA_BT_PROFILE_HSP_AG)
24
+       mask |= SPA_BT_PROFILE_HSP_HS;
25
+   if (profiles & SPA_BT_PROFILE_HSP_HS)
26
+       mask |= SPA_BT_PROFILE_HSP_AG;
27
+
28
+   if (profiles & SPA_BT_PROFILE_HFP_AG)
29
+       mask |= SPA_BT_PROFILE_HFP_HF;
30
+   if (profiles & SPA_BT_PROFILE_HFP_HF)
31
+       mask |= SPA_BT_PROFILE_HFP_AG;
32
+
33
+   return mask;
34
+}
35
+
36
 struct spa_bt_device *spa_bt_device_find(struct spa_bt_monitor *monitor, const char *path)
37
 {
38
    struct spa_bt_device *d;
39
@@ -1144,6 +1168,10 @@
40
        }
41
    }
42
 
43
+   /* Connect only profiles the adapter has a counterpart for */
44
+   if (device->adapter)
45
+       reconnect &= adapter_connectable_profiles(device->adapter);
46
+
47
    if (!(device->connected_profiles & SPA_BT_PROFILE_HEADSET_HEAD_UNIT)) {
48
        if (reconnect & SPA_BT_PROFILE_HFP_HF) {
49
            SPA_FLAG_CLEAR(reconnect, SPA_BT_PROFILE_HSP_HS);
50
@@ -1257,9 +1285,12 @@
51
 {
52
    struct spa_bt_monitor *monitor = device->monitor;
53
    uint32_t connected_profiles = device->connected_profiles;
54
-   uint32_t direction_masks2 = {
55
-       SPA_BT_PROFILE_A2DP_SINK | SPA_BT_PROFILE_HEADSET_AUDIO,
56
-       SPA_BT_PROFILE_A2DP_SOURCE | SPA_BT_PROFILE_HEADSET_AUDIO_GATEWAY,
57
+   uint32_t connectable_profiles =
58
+       device->adapter ? adapter_connectable_profiles(device->adapter) : 0;
59
+   uint32_t direction_masks3 = {
60
+       SPA_BT_PROFILE_A2DP_SINK | SPA_BT_PROFILE_HEADSET_HEAD_UNIT,
61
+       SPA_BT_PROFILE_A2DP_SOURCE,
62
+       SPA_BT_PROFILE_HEADSET_AUDIO_GATEWAY,
63
    };
64
    bool direction_connected = false;
65
    bool all_connected;
66
@@ -1271,15 +1302,16 @@
67
        connected_profiles |= SPA_BT_PROFILE_HEADSET_AUDIO_GATEWAY;
68
 
69
    for (i = 0; i < SPA_N_ELEMENTS(direction_masks); ++i) {
70
-       uint32_t mask = direction_masksi & device->profiles;
71
+       uint32_t mask = direction_masksi & device->profiles & connectable_profiles;
72
        if (mask && (connected_profiles & mask) == mask)
73
            direction_connected = true;
74
    }
75
 
76
    all_connected = (device->profiles & connected_profiles) == device->profiles;
77
 
78
-   spa_log_debug(monitor->log, "device %p: profiles %08x %08x %d",
79
-           device, device->profiles, connected_profiles, device->added);
80
+   spa_log_debug(monitor->log, "device %p: profiles %08x %08x connectable:%08x added:%d all:%d dir:%d",
81
+           device, device->profiles, connected_profiles, connectable_profiles,
82
+           device->added, all_connected, direction_connected);
83
 
84
    if (connected_profiles == 0 && spa_list_is_empty(&device->codec_switch_list)) {
85
        device_stop_timer(device);
86
@@ -1579,7 +1611,11 @@
87
        if (j >= size) {
88
            const struct a2dp_codec **p;
89
            size = size * 2;
90
+#ifdef HAVE_REALLOCARRRAY
91
            p = reallocarray(supported_codecs, size, sizeof(const struct a2dp_codec *));
92
+#else
93
+           p = realloc(supported_codecs, size * sizeof(const struct a2dp_codec *));
94
+#endif
95
            if (p == NULL) {
96
                free(supported_codecs);
97
                return NULL;
98
@@ -1862,6 +1898,7 @@
99
    if (device && device->connected_profiles != prev_connected)
100
        spa_bt_device_emit_profiles_changed(device, device->profiles, prev_connected);
101
 
102
+   free(transport->endpoint_path);
103
    free(transport->path);
104
    free(transport);
105
 }
106
@@ -2525,6 +2562,7 @@
107
 static bool a2dp_codec_switch_process_current(struct spa_bt_a2dp_codec_switch *sw)
108
 {
109
    struct spa_bt_remote_endpoint *ep;
110
+   struct spa_bt_transport *t;
111
    const struct a2dp_codec *codec;
112
    uint8_t configA2DP_MAX_CAPS_SIZE;
113
    char *local_endpoint_base;
114
@@ -2579,6 +2617,19 @@
115
        goto next;
116
    }
117
 
118
+   /* Each endpoint can be used by only one device at a time (on each adapter) */
119
+   spa_list_for_each(t, &sw->device->monitor->transport_list, link) {
120
+       if (t->device == sw->device)
121
+           continue;
122
+       if (t->device->adapter != sw->device->adapter)
123
+           continue;
124
+       if (spa_streq(t->endpoint_path, local_endpoint)) {
125
+           spa_log_debug(sw->device->monitor->log, "a2dp codec switch %p: endpoint %s in use, try next",
126
+                   sw, local_endpoint);
127
+           goto next;
128
+       }
129
+   }
130
+
131
    res = codec->select_config(codec, 0, ep->capabilities, ep->capabilities_len,
132
                   &sw->device->monitor->default_audio_info,
133
                   sw->device->settings, config);
134
@@ -3026,6 +3077,8 @@
135
        transport->volumesi.hw_volume_max = SPA_BT_VOLUME_A2DP_MAX;
136
    }
137
 
138
+   free(transport->endpoint_path);
139
+   transport->endpoint_path = strdup(endpoint);
140
    transport->profile = profile;
141
    transport->a2dp_codec = codec;
142
    transport_update_props(transport, &it1, NULL);
143
@@ -3531,8 +3584,10 @@
144
        if (!is_a2dp_codec_enabled(monitor, codec))
145
            continue;
146
 
147
-       register_a2dp_endpoint(monitor, codec, A2DP_SOURCE_ENDPOINT);
148
-       register_a2dp_endpoint(monitor, codec, A2DP_SINK_ENDPOINT);
149
+       if (codec->encode != NULL)
150
+           register_a2dp_endpoint(monitor, codec, A2DP_SOURCE_ENDPOINT);
151
+       if (codec->decode != NULL)
152
+           register_a2dp_endpoint(monitor, codec, A2DP_SINK_ENDPOINT);
153
    }
154
 
155
    return 0;
156
@@ -4517,7 +4572,7 @@
157
        if ((str = spa_dict_lookup(info, "bluez5.dummy-avrcp-player")) != NULL)
158
            this->dummy_avrcp_player = spa_atob(str);
159
        else
160
-           this->dummy_avrcp_player = true;
161
+           this->dummy_avrcp_player = false;
162
    }
163
 
164
    register_media_application(this);
165
pipewire-0.3.51.tar.gz/spa/plugins/bluez5/codec-loader.c -> pipewire-0.3.52.tar.gz/spa/plugins/bluez5/codec-loader.c Changed
19
 
1
@@ -55,6 +55,7 @@
2
        SPA_BLUETOOTH_AUDIO_CODEC_APTX_HD,
3
        SPA_BLUETOOTH_AUDIO_CODEC_APTX,
4
        SPA_BLUETOOTH_AUDIO_CODEC_AAC,
5
+       SPA_BLUETOOTH_AUDIO_CODEC_LC3PLUS_HR,
6
        SPA_BLUETOOTH_AUDIO_CODEC_MPEG,
7
        SPA_BLUETOOTH_AUDIO_CODEC_SBC,
8
        SPA_BLUETOOTH_AUDIO_CODEC_SBC_XQ,
9
@@ -169,7 +170,8 @@
10
        A2DP_CODEC_FACTORY_LIB("aptx"),
11
        A2DP_CODEC_FACTORY_LIB("faststream"),
12
        A2DP_CODEC_FACTORY_LIB("ldac"),
13
-       A2DP_CODEC_FACTORY_LIB("sbc")
14
+       A2DP_CODEC_FACTORY_LIB("sbc"),
15
+       A2DP_CODEC_FACTORY_LIB("lc3plus")
16
 #undef A2DP_CODEC_FACTORY_LIB
17
    };
18
 
19
pipewire-0.3.51.tar.gz/spa/plugins/bluez5/defs.h -> pipewire-0.3.52.tar.gz/spa/plugins/bluez5/defs.h Changed
9
 
1
@@ -574,6 +574,7 @@
2
    unsigned int codec;
3
    void *configuration;
4
    int configuration_len;
5
+   char *endpoint_path;
6
 
7
    uint32_t n_channels;
8
    uint32_t channels64;
9
pipewire-0.3.51.tar.gz/spa/plugins/bluez5/meson.build -> pipewire-0.3.52.tar.gz/spa/plugins/bluez5/meson.build Changed
17
 
1
@@ -109,3 +109,15 @@
2
     install : true,
3
     install_dir : spa_plugindir / 'bluez5')
4
 endif
5
+
6
+if get_option('bluez5-codec-lc3plus').allowed() and lc3plus_dep.found()
7
+  lc3plus_args = codec_args
8
+  lc3plus_dep =  lc3plus_dep 
9
+  bluez_codec_lc3plus = shared_library('spa-codec-bluez5-lc3plus',
10
+     'a2dp-codec-lc3plus.c', 'a2dp-codecs.c' ,
11
+    include_directories :  configinc ,
12
+    c_args : ldac_args,
13
+    dependencies :  spa_dep, lc3plus_dep, mathlib ,
14
+    install : true,
15
+    install_dir : spa_plugindir / 'bluez5')
16
+endif
17
pipewire-0.3.51.tar.gz/spa/plugins/libcamera/libcamera-device.cpp -> pipewire-0.3.52.tar.gz/spa/plugins/libcamera/libcamera-device.cpp Changed
80
 
1
@@ -78,37 +78,37 @@
2
    std::shared_ptr<Camera> camera;
3
 };
4
 
5
-std::string cameraDesc(const Camera *camera)
6
+std::string cameraModel(const Camera *camera)
7
 {
8
    const ControlList &props = camera->properties();
9
-   bool addModel = true;
10
    std::string name;
11
+   if (props.contains(properties::Model))
12
+       name = props.get(properties::Model);
13
+   else
14
+       name = camera->id();
15
+        return name;
16
+}
17
 
18
-        if (props.contains(properties::Location)) {
19
+std::string cameraLoc(const Camera *camera)
20
+{
21
+   const ControlList &props = camera->properties();
22
+   std::string location;
23
+   if (props.contains(properties::Location)) {
24
        switch (props.get(properties::Location)) {
25
        case properties::CameraLocationFront:
26
-           addModel = false;
27
-           name = "Internal front camera ";
28
-       break;
29
+           location = "front";
30
+           break;
31
        case properties::CameraLocationBack:
32
-           addModel = false;
33
-           name = "Internal back camera ";
34
-       break;
35
+           location = "back";
36
+           break;
37
        case properties::CameraLocationExternal:
38
-           name = "External camera ";
39
+           location = "external";
40
            break;
41
        }
42
    }
43
-   if (addModel) {
44
-       if (props.contains(properties::Model))
45
-           name = "" + props.get(properties::Model);
46
-       else
47
-           name = "" + camera->id();
48
-   }
49
-        return name;
50
+   return location;
51
 }
52
 
53
-
54
 static int emit_info(struct impl *impl, bool full)
55
 {
56
    struct spa_dict_item items10;
57
@@ -116,7 +116,7 @@
58
    uint32_t n_items = 0;
59
    struct spa_device_info info;
60
    struct spa_param_info params2;
61
-   char path256, desc256, name256;
62
+   char path256, location10, model256, name256;
63
 
64
    info = SPA_DEVICE_INFO_INIT();
65
 
66
@@ -128,8 +128,11 @@
67
    ADD_ITEM(SPA_KEY_DEVICE_API, "libcamera");
68
    ADD_ITEM(SPA_KEY_MEDIA_CLASS, "Video/Device");
69
    ADD_ITEM(SPA_KEY_API_LIBCAMERA_PATH, (char *)impl->props.device);
70
-   snprintf(desc, sizeof(desc), "%s", cameraDesc(impl->camera.get()).c_str());
71
-   ADD_ITEM(SPA_KEY_DEVICE_DESCRIPTION, desc);
72
+   snprintf(location, sizeof(location), "%s", cameraLoc(impl->camera.get()).c_str());
73
+   ADD_ITEM(SPA_KEY_API_LIBCAMERA_LOCATION, location);
74
+   snprintf(model, sizeof(model), "%s", cameraModel(impl->camera.get()).c_str());
75
+   ADD_ITEM(SPA_KEY_DEVICE_PRODUCT_NAME, model);
76
+   ADD_ITEM(SPA_KEY_DEVICE_DESCRIPTION, model);
77
    snprintf(name, sizeof(name), "libcamera_device.%s", impl->props.device);
78
    ADD_ITEM(SPA_KEY_DEVICE_NAME, name);
79
 #undef ADD_ITEM
80
pipewire-0.3.51.tar.gz/spa/plugins/libcamera/libcamera-utils.cpp -> pipewire-0.3.52.tar.gz/spa/plugins/libcamera/libcamera-utils.cpp Changed
10
 
1
@@ -440,7 +440,7 @@
2
               uint32_t start, uint32_t num,
3
               const struct spa_pod *filter)
4
 {
5
-   return -ENOTSUP;
6
+   return 0;
7
 }
8
 
9
 static void libcamera_on_fd_events(struct spa_source *source)
10
pipewire-0.3.51.tar.gz/spa/plugins/support/loop.c -> pipewire-0.3.52.tar.gz/spa/plugins/support/loop.c Changed
51
 
1
@@ -370,6 +370,24 @@
2
    spa_list_init(&impl->destroy_list);
3
 }
4
 
5
+struct cancellation_handler_data {
6
+   struct spa_poll_event *ep;
7
+   int ep_count;
8
+};
9
+
10
+static void cancellation_handler(void *closure)
11
+{
12
+   const struct cancellation_handler_data *data = closure;
13
+
14
+   for (int i = 0; i < data->ep_count; i++) {
15
+       struct spa_source *s = data->epi.data;
16
+       if (SPA_LIKELY(s)) {
17
+           s->rmask = 0;
18
+           s->priv = NULL;
19
+       }
20
+   }
21
+}
22
+
23
 static int loop_iterate(void *object, int timeout)
24
 {
25
    struct impl *impl = object;
26
@@ -384,6 +402,9 @@
27
    spa_loop_control_hook_after(&impl->hooks_list);
28
    impl->polling = false;
29
 
30
+   struct cancellation_handler_data cdata = { ep, nfds };
31
+   pthread_cleanup_push(cancellation_handler, &cdata);
32
+
33
    /* first we set all the rmasks, then call the callbacks. The reason is that
34
     * some callback might also want to look at other sources it manages and
35
     * can then reset the rmask to suppress the callback */
36
@@ -409,13 +430,7 @@
37
            s->func(s);
38
    }
39
 
40
-   for (i = 0; i < nfds; i++) {
41
-       struct spa_source *s = epi.data;
42
-       if (SPA_LIKELY(s)) {
43
-           s->rmask = 0;
44
-           s->priv = NULL;
45
-       }
46
-   }
47
+   pthread_cleanup_pop(true);
48
 
49
    return nfds;
50
 }
51
pipewire-0.3.51.tar.gz/spa/plugins/test/fakesink.c -> pipewire-0.3.52.tar.gz/spa/plugins/test/fakesink.c Changed
29
 
1
@@ -168,8 +168,12 @@
2
 
3
    spa_return_val_if_fail(this != NULL, -EINVAL);
4
 
5
+
6
    switch (id) {
7
    case SPA_PARAM_Props:
8
+   {
9
+       struct port *port = &this->port;
10
+
11
        if (param == NULL) {
12
            reset_props(this, &this->props);
13
            return 0;
14
@@ -179,11 +183,11 @@
15
            SPA_PROP_live, SPA_POD_OPT_Bool(&this->props.live));
16
 
17
        if (this->props.live)
18
-           this->info.flags |= SPA_PORT_FLAG_LIVE;
19
+           port->info.flags |= SPA_PORT_FLAG_LIVE;
20
        else
21
-           this->info.flags &= ~SPA_PORT_FLAG_LIVE;
22
+           port->info.flags &= ~SPA_PORT_FLAG_LIVE;
23
        break;
24
-
25
+   }
26
    default:
27
        return -ENOENT;
28
    }
29
pipewire-0.3.51.tar.gz/spa/plugins/test/fakesrc.c -> pipewire-0.3.52.tar.gz/spa/plugins/test/fakesrc.c Changed
21
 
1
@@ -181,6 +181,7 @@
2
    case SPA_PARAM_Props:
3
    {
4
        struct props *p = &this->props;
5
+       struct port *port = &this->port;
6
 
7
        if (param == NULL) {
8
            reset_props(this, p);
9
@@ -192,9 +193,9 @@
10
            SPA_PROP_patternType, SPA_POD_OPT_Id(&p->pattern));
11
 
12
        if (p->live)
13
-           this->info.flags |= SPA_PORT_FLAG_LIVE;
14
+           port->info.flags |= SPA_PORT_FLAG_LIVE;
15
        else
16
-           this->info.flags &= ~SPA_PORT_FLAG_LIVE;
17
+           port->info.flags &= ~SPA_PORT_FLAG_LIVE;
18
        break;
19
    }
20
    default:
21
pipewire-0.3.51.tar.gz/spa/plugins/v4l2/v4l2-utils.c -> pipewire-0.3.52.tar.gz/spa/plugins/v4l2/v4l2-utils.c Changed
33
 
1
@@ -1156,17 +1156,17 @@
2
            SPA_TYPE_OBJECT_PropInfo, SPA_PARAM_PropInfo,
3
            SPA_PROP_INFO_id,   SPA_POD_Id(prop_id),
4
            SPA_PROP_INFO_type, SPA_POD_CHOICE_STEP_Int(
5
-                           queryctrl.default_value,
6
-                           queryctrl.minimum,
7
-                           queryctrl.maximum,
8
-                           queryctrl.step),
9
+                           (int32_t)queryctrl.default_value,
10
+                           (int32_t)queryctrl.minimum,
11
+                           (int32_t)queryctrl.maximum,
12
+                           (int32_t)queryctrl.step),
13
            SPA_PROP_INFO_description, SPA_POD_String(queryctrl.name));
14
        break;
15
    case V4L2_CTRL_TYPE_BOOLEAN:
16
        param = spa_pod_builder_add_object(&b,
17
            SPA_TYPE_OBJECT_PropInfo, SPA_PARAM_PropInfo,
18
            SPA_PROP_INFO_id,   SPA_POD_Id(prop_id),
19
-           SPA_PROP_INFO_type, SPA_POD_CHOICE_Bool(queryctrl.default_value),
20
+           SPA_PROP_INFO_type, SPA_POD_CHOICE_Bool((bool)queryctrl.default_value),
21
            SPA_PROP_INFO_description, SPA_POD_String(queryctrl.name));
22
        break;
23
    case V4L2_CTRL_TYPE_MENU:
24
@@ -1177,7 +1177,7 @@
25
        spa_pod_builder_push_object(&b, &f0, SPA_TYPE_OBJECT_PropInfo, SPA_PARAM_PropInfo);
26
        spa_pod_builder_add(&b,
27
            SPA_PROP_INFO_id,    SPA_POD_Id(prop_id),
28
-           SPA_PROP_INFO_type,  SPA_POD_CHOICE_ENUM_Int(1, queryctrl.default_value),
29
+           SPA_PROP_INFO_type,  SPA_POD_CHOICE_ENUM_Int(1, (int32_t)queryctrl.default_value),
30
            SPA_PROP_INFO_description,  SPA_POD_String(queryctrl.name),
31
            0);
32
 
33
pipewire-0.3.51.tar.gz/spa/plugins/videotestsrc/videotestsrc.c -> pipewire-0.3.52.tar.gz/spa/plugins/videotestsrc/videotestsrc.c Changed
30
 
1
@@ -229,6 +229,7 @@
2
    case SPA_PARAM_Props:
3
    {
4
        struct props *p = &this->props;
5
+       struct port *port = &this->port;
6
 
7
        if (param == NULL) {
8
            reset_props(p);
9
@@ -240,9 +241,9 @@
10
            SPA_PROP_patternType, SPA_POD_OPT_Int(&p->pattern));
11
 
12
        if (p->live)
13
-           this->info.flags |= SPA_PORT_FLAG_LIVE;
14
+           port->info.flags |= SPA_PORT_FLAG_LIVE;
15
        else
16
-           this->info.flags &= ~SPA_PORT_FLAG_LIVE;
17
+           port->info.flags &= ~SPA_PORT_FLAG_LIVE;
18
        break;
19
    }
20
    default:
21
@@ -928,7 +929,7 @@
22
    port->info = SPA_PORT_INFO_INIT();
23
    port->info.flags = SPA_PORT_FLAG_NO_REF;
24
    if (this->props.live)
25
-       this->info.flags |= SPA_PORT_FLAG_LIVE;
26
+       port->info.flags |= SPA_PORT_FLAG_LIVE;
27
    port->params0 = SPA_PARAM_INFO(SPA_PARAM_EnumFormat, SPA_PARAM_INFO_READ);
28
    port->params1 = SPA_PARAM_INFO(SPA_PARAM_Meta, SPA_PARAM_INFO_READ);
29
    port->params2 = SPA_PARAM_INFO(SPA_PARAM_IO, SPA_PARAM_INFO_READ);
30
pipewire-0.3.51.tar.gz/spa/plugins/vulkan/meson.build -> pipewire-0.3.52.tar.gz/spa/plugins/vulkan/meson.build Changed
8
 
1
@@ -1,5 +1,6 @@
2
 spa_vulkan_sources = 
3
   'plugin.c',
4
+  'vulkan-compute-filter.c',
5
   'vulkan-compute-source.c',
6
   'vulkan-utils.c'
7
 
8
pipewire-0.3.51.tar.gz/spa/plugins/vulkan/plugin.c -> pipewire-0.3.52.tar.gz/spa/plugins/vulkan/plugin.c Changed
19
 
1
@@ -26,6 +26,7 @@
2
 
3
 #include <spa/support/plugin.h>
4
 
5
+extern const struct spa_handle_factory spa_vulkan_compute_filter_factory;
6
 extern const struct spa_handle_factory spa_vulkan_compute_source_factory;
7
 
8
 SPA_EXPORT
9
@@ -38,6 +39,9 @@
10
    case 0:
11
        *factory = &spa_vulkan_compute_source_factory;
12
        break;
13
+   case 1:
14
+       *factory = &spa_vulkan_compute_filter_factory;
15
+       break;
16
    default:
17
        return 0;
18
    }
19
pipewire-0.3.52.tar.gz/spa/plugins/vulkan/shaders/filter-color.comp Added
41
 
1
@@ -0,0 +1,39 @@
2
+void mainImage( out vec4 fragColor, in vec2 fragCoord )
3
+{
4
+    vec2 p = fragCoord.xy/iResolution.xy;
5
+
6
+   vec4 col = texture(iChannel0, p);
7
+
8
+
9
+   //Desaturate
10
+    if(p.x<.25)
11
+   {
12
+       col = vec4( (col.r+col.g+col.b)/3. );
13
+   }
14
+   //Invert
15
+   else if (p.x<.5)
16
+   {
17
+       col = vec4(1.) - texture(iChannel0, p);
18
+   }
19
+   //Chromatic aberration
20
+   else if (p.x<.75)
21
+   {
22
+       vec2 offset = vec2(.01,.0);
23
+       col.r = texture(iChannel0, p+offset.xy).r;
24
+       col.g = texture(iChannel0, p          ).g;
25
+       col.b = texture(iChannel0, p+offset.yx).b;
26
+   }
27
+   //Color switching
28
+   else
29
+   {
30
+       col.rgb = texture(iChannel0, p).brg;
31
+   }
32
+
33
+
34
+   //Line
35
+   if( mod(abs(p.x+.5/iResolution.y),.25)<0.5/iResolution.y )
36
+       col = vec4(1.);
37
+
38
+
39
+    fragColor = col;
40
+}
41
pipewire-0.3.52.tar.gz/spa/plugins/vulkan/shaders/filter.comp Added
46
 
1
@@ -0,0 +1,44 @@
2
+#version 450
3
+#extension GL_ARB_separate_shader_objects : enable
4
+
5
+#define WORKGROUP_SIZE 32
6
+layout (local_size_x = WORKGROUP_SIZE, local_size_y = WORKGROUP_SIZE, local_size_z = 1 ) in;
7
+
8
+layout(rgba32f, set = 0, binding = 0) uniform image2D resultImage;
9
+layout(set = 0, binding = 1) uniform sampler2D iChannel0;
10
+
11
+layout( push_constant ) uniform Constants {
12
+  float time;
13
+  int frame;
14
+  int width;
15
+  int height;
16
+} PushConstant;
17
+
18
+float iTime;
19
+int iFrame;
20
+vec3 iResolution;
21
+vec4 iMouse;
22
+
23
+void mainImage( out vec4 fragColor, in vec2 fragCoord );
24
+
25
+void main()
26
+{
27
+   iTime = PushConstant.time;
28
+   iFrame = PushConstant.frame;
29
+   iResolution = vec3(float(PushConstant.width), float(PushConstant.height), 0.0);
30
+   iMouse = vec4(0.0, 0.0, 0.0, 0.0);
31
+   vec2 coord = vec2(float(gl_GlobalInvocationID.x),
32
+           iResolution.y - float(gl_GlobalInvocationID.y));
33
+   vec4 outColor;
34
+
35
+   if(coord.x >= iResolution.x || coord.y >= iResolution.y)
36
+       return;
37
+
38
+   mainImage(outColor, coord);
39
+
40
+   imageStore(resultImage, ivec2(gl_GlobalInvocationID.xy), outColor);
41
+}
42
+
43
+//#include "smearcam.comp"
44
+#include "filter-color.comp"
45
+//#include "filter-ripple.comp"
46
pipewire-0.3.52.tar.gz/spa/plugins/vulkan/shaders/filter.spv Added
pipewire-0.3.51.tar.gz/spa/plugins/vulkan/shaders/main.comp -> pipewire-0.3.52.tar.gz/spa/plugins/vulkan/shaders/main.comp Changed
27
 
1
@@ -4,14 +4,7 @@
2
 #define WORKGROUP_SIZE 32
3
 layout (local_size_x = WORKGROUP_SIZE, local_size_y = WORKGROUP_SIZE, local_size_z = 1 ) in;
4
 
5
-struct Pixel{
6
-  vec4 value;
7
-};
8
-
9
-layout(std140, binding = 0) buffer buf
10
-{
11
-   Pixel imageData;
12
-};
13
+layout(rgba32f, binding = 0) uniform image2D resultImage;
14
 
15
 layout( push_constant ) uniform Constants {
16
   float time;
17
@@ -42,8 +35,7 @@
18
 
19
    mainImage(outColor, coord);
20
 
21
-   imageDataPushConstant.width * gl_GlobalInvocationID.y +
22
-           gl_GlobalInvocationID.x.value = outColor;
23
+   imageStore(resultImage, ivec2(gl_GlobalInvocationID.xy), outColor);
24
 }
25
 
26
 //#include "plasma-globe.comp"
27
pipewire-0.3.51.tar.gz/spa/plugins/vulkan/shaders/main.spv -> pipewire-0.3.52.tar.gz/spa/plugins/vulkan/shaders/main.spv Changed
pipewire-0.3.52.tar.gz/spa/plugins/vulkan/vulkan-compute-filter.c Added
201
 
1
@@ -0,0 +1,806 @@
2
+/* Spa
3
+ *
4
+ * Copyright © 2019 Wim Taymans
5
+ *
6
+ * Permission is hereby granted, free of charge, to any person obtaining a
7
+ * copy of this software and associated documentation files (the "Software"),
8
+ * to deal in the Software without restriction, including without limitation
9
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10
+ * and/or sell copies of the Software, and to permit persons to whom the
11
+ * Software is furnished to do so, subject to the following conditions:
12
+ *
13
+ * The above copyright notice and this permission notice (including the next
14
+ * paragraph) shall be included in all copies or substantial portions of the
15
+ * Software.
16
+ *
17
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
20
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
23
+ * DEALINGS IN THE SOFTWARE.
24
+ */
25
+
26
+#include <errno.h>
27
+#include <stddef.h>
28
+#include <unistd.h>
29
+#include <string.h>
30
+#include <stdio.h>
31
+
32
+#include <spa/support/plugin.h>
33
+#include <spa/support/log.h>
34
+#include <spa/support/loop.h>
35
+#include <spa/utils/list.h>
36
+#include <spa/utils/keys.h>
37
+#include <spa/utils/names.h>
38
+#include <spa/utils/string.h>
39
+#include <spa/node/node.h>
40
+#include <spa/node/utils.h>
41
+#include <spa/node/io.h>
42
+#include <spa/node/keys.h>
43
+#include <spa/param/video/format-utils.h>
44
+#include <spa/param/param.h>
45
+#include <spa/pod/filter.h>
46
+
47
+#include "vulkan-utils.h"
48
+
49
+#define NAME "vulkan-compute-filter"
50
+
51
+struct buffer {
52
+   uint32_t id;
53
+#define BUFFER_FLAG_OUT (1<<0)
54
+   uint32_t flags;
55
+   struct spa_buffer *outbuf;
56
+   struct spa_meta_header *h;
57
+   struct spa_list link;
58
+};
59
+
60
+struct port {
61
+   uint64_t info_all;
62
+   struct spa_port_info info;
63
+
64
+   enum spa_direction direction;
65
+   struct spa_param_info params5;
66
+
67
+   struct spa_io_buffers *io;
68
+
69
+   bool have_format;
70
+   struct spa_video_info current_format;
71
+
72
+   struct buffer buffersMAX_BUFFERS;
73
+   uint32_t n_buffers;
74
+
75
+   struct spa_list empty;
76
+   struct spa_list ready;
77
+   uint32_t stream_id;
78
+};
79
+
80
+struct impl {
81
+   struct spa_handle handle;
82
+   struct spa_node node;
83
+
84
+   struct spa_log *log;
85
+
86
+   struct spa_io_position *position;
87
+
88
+   uint64_t info_all;
89
+   struct spa_node_info info;
90
+   struct spa_param_info params2;
91
+
92
+   struct spa_hook_list hooks;
93
+   struct spa_callbacks callbacks;
94
+
95
+   bool started;
96
+
97
+   struct vulkan_state state;
98
+   struct port port2;
99
+};
100
+
101
+#define CHECK_PORT(this,d,p)  ((p) < 1)
102
+
103
+static int impl_node_enum_params(void *object, int seq,
104
+                uint32_t id, uint32_t start, uint32_t num,
105
+                const struct spa_pod *filter)
106
+{
107
+   struct impl *this = object;
108
+   struct spa_pod *param;
109
+   struct spa_pod_builder b = { 0 };
110
+   uint8_t buffer1024;
111
+   struct spa_result_node_params result;
112
+   uint32_t count = 0;
113
+
114
+   spa_return_val_if_fail(this != NULL, -EINVAL);
115
+   spa_return_val_if_fail(num != 0, -EINVAL);
116
+
117
+   result.id = id;
118
+   result.next = start;
119
+      next:
120
+   result.index = result.next++;
121
+
122
+   spa_pod_builder_init(&b, buffer, sizeof(buffer));
123
+
124
+   switch (id) {
125
+   default:
126
+       return -ENOENT;
127
+   }
128
+
129
+   if (spa_pod_filter(&b, &result.param, param, filter) < 0)
130
+       goto next;
131
+
132
+   spa_node_emit_result(&this->hooks, seq, 0, SPA_RESULT_TYPE_NODE_PARAMS, &result);
133
+
134
+   if (++count != num)
135
+       goto next;
136
+
137
+   return 0;
138
+}
139
+
140
+static int impl_node_set_io(void *object, uint32_t id, void *data, size_t size)
141
+{
142
+   struct impl *this = object;
143
+
144
+   spa_return_val_if_fail(this != NULL, -EINVAL);
145
+
146
+   switch (id) {
147
+   case SPA_IO_Position:
148
+       if (size > 0 && size < sizeof(struct spa_io_position))
149
+           return -EINVAL;
150
+       this->position = data;
151
+       break;
152
+   default:
153
+       return -ENOENT;
154
+   }
155
+   return 0;
156
+}
157
+static int impl_node_set_param(void *object, uint32_t id, uint32_t flags,
158
+                  const struct spa_pod *param)
159
+{
160
+   struct impl *this = object;
161
+
162
+   spa_return_val_if_fail(this != NULL, -EINVAL);
163
+
164
+   switch (id) {
165
+   default:
166
+       return -ENOENT;
167
+   }
168
+   return 0;
169
+}
170
+
171
+static inline void reuse_buffer(struct impl *this, struct port *port, uint32_t id)
172
+{
173
+   struct buffer *b = &port->buffersid;
174
+
175
+   if (SPA_FLAG_IS_SET(b->flags, BUFFER_FLAG_OUT)) {
176
+       spa_log_debug(this->log, NAME " %p: reuse buffer %d", this, id);
177
+
178
+       SPA_FLAG_CLEAR(b->flags, BUFFER_FLAG_OUT);
179
+       spa_list_append(&port->empty, &b->link);
180
+   }
181
+}
182
+
183
+static int impl_node_send_command(void *object, const struct spa_command *command)
184
+{
185
+   struct impl *this = object;
186
+
187
+   spa_return_val_if_fail(this != NULL, -EINVAL);
188
+   spa_return_val_if_fail(command != NULL, -EINVAL);
189
+
190
+   switch (SPA_NODE_COMMAND_ID(command)) {
191
+   case SPA_NODE_COMMAND_Start:
192
+       if (this->started)
193
+           return 0;
194
+
195
+       this->started = true;
196
+       spa_vulkan_start(&this->state);
197
+       break;
198
+
199
+   case SPA_NODE_COMMAND_Suspend:
200
+   case SPA_NODE_COMMAND_Pause:
201
pipewire-0.3.51.tar.gz/spa/plugins/vulkan/vulkan-compute-source.c -> pipewire-0.3.52.tar.gz/spa/plugins/vulkan/vulkan-compute-source.c Changed
95
 
1
@@ -61,8 +61,6 @@
2
    props->live = DEFAULT_LIVE;
3
 }
4
 
5
-#define MAX_PORTS 1
6
-
7
 struct buffer {
8
    uint32_t id;
9
 #define BUFFER_FLAG_OUT (1<<0)
10
@@ -122,7 +120,7 @@
11
    struct port port;
12
 };
13
 
14
-#define CHECK_PORT(this,d,p)  ((d) == SPA_DIRECTION_OUTPUT && (p) < MAX_PORTS)
15
+#define CHECK_PORT(this,d,p)  ((d) == SPA_DIRECTION_OUTPUT && (p) < 1)
16
 
17
 static int impl_node_enum_params(void *object, int seq,
18
                 uint32_t id, uint32_t start, uint32_t num,
19
@@ -225,6 +223,7 @@
20
    case SPA_PARAM_Props:
21
    {
22
        struct props *p = &this->props;
23
+       struct port *port = &this->port;
24
 
25
        if (param == NULL) {
26
            reset_props(p);
27
@@ -235,9 +234,9 @@
28
            SPA_PROP_live,        SPA_POD_OPT_Bool(&p->live));
29
 
30
        if (p->live)
31
-           this->info.flags |= SPA_PORT_FLAG_LIVE;
32
+           port->info.flags |= SPA_PORT_FLAG_LIVE;
33
        else
34
-           this->info.flags &= ~SPA_PORT_FLAG_LIVE;
35
+           port->info.flags &= ~SPA_PORT_FLAG_LIVE;
36
        break;
37
    }
38
    default:
39
@@ -307,12 +306,13 @@
40
    this->state.constants.time = this->elapsed_time / (float) SPA_NSEC_PER_SEC;
41
    this->state.constants.frame = this->frame_count;
42
 
43
-   spa_vulkan_process(&this->state, b->id);
44
+   this->state.streams0.pending_buffer_id = b->id;
45
+   spa_vulkan_process(&this->state);
46
 
47
-   if (this->state.ready_buffer_id != SPA_ID_INVALID) {
48
-       struct buffer *b = &port->buffersthis->state.ready_buffer_id;
49
+   if (this->state.streams0.ready_buffer_id != SPA_ID_INVALID) {
50
+       struct buffer *b = &port->buffersthis->state.streams0.ready_buffer_id;
51
 
52
-       this->state.ready_buffer_id = SPA_ID_INVALID;
53
+       this->state.streams0.ready_buffer_id = SPA_ID_INVALID;
54
 
55
        spa_log_trace(this->log, NAME " %p: ready buffer %d", this, b->id);
56
 
57
@@ -635,7 +635,7 @@
58
 {
59
    if (port->n_buffers > 0) {
60
        spa_log_debug(this->log, NAME " %p: clear buffers", this);
61
-       spa_vulkan_use_buffers(&this->state, 0, 0, NULL);
62
+       spa_vulkan_use_buffers(&this->state, &this->state.streams0, 0, 0, NULL);
63
        port->n_buffers = 0;
64
        spa_list_init(&port->empty);
65
        spa_list_init(&port->ready);
66
@@ -748,7 +748,7 @@
67
 
68
        spa_list_append(&port->empty, &b->link);
69
    }
70
-   spa_vulkan_use_buffers(&this->state, flags, n_buffers, buffers);
71
+   spa_vulkan_use_buffers(&this->state, &this->state.streams0, flags, n_buffers, buffers);
72
    port->n_buffers = n_buffers;
73
 
74
    return 0;
75
@@ -945,7 +945,7 @@
76
    port->info = SPA_PORT_INFO_INIT();
77
    port->info.flags = SPA_PORT_FLAG_NO_REF | SPA_PORT_FLAG_CAN_ALLOC_BUFFERS;
78
    if (this->props.live)
79
-       this->info.flags |= SPA_PORT_FLAG_LIVE;
80
+       port->info.flags |= SPA_PORT_FLAG_LIVE;
81
    port->params0 = SPA_PARAM_INFO(SPA_PARAM_EnumFormat, SPA_PARAM_INFO_READ);
82
    port->params1 = SPA_PARAM_INFO(SPA_PARAM_Meta, SPA_PARAM_INFO_READ);
83
    port->params2 = SPA_PARAM_INFO(SPA_PARAM_IO, SPA_PARAM_INFO_READ);
84
@@ -957,6 +957,10 @@
85
    spa_list_init(&port->ready);
86
 
87
    this->state.log = this->log;
88
+   spa_vulkan_init_stream(&this->state, &this->state.streams0,
89
+           SPA_DIRECTION_OUTPUT, NULL);
90
+   this->state.shaderName = "spa/plugins/vulkan/shaders/main.spv";
91
+   this->state.n_streams = 1;
92
 
93
    return 0;
94
 }
95
pipewire-0.3.51.tar.gz/spa/plugins/vulkan/vulkan-utils.c -> pipewire-0.3.52.tar.gz/spa/plugins/vulkan/vulkan-utils.c Changed
201
 
1
@@ -16,11 +16,14 @@
2
 #include <time.h>
3
 
4
 #include <spa/utils/result.h>
5
+#include <spa/utils/string.h>
6
 #include <spa/support/log.h>
7
 #include <spa/debug/mem.h>
8
 
9
 #include "vulkan-utils.h"
10
 
11
+//#define ENABLE_VALIDATION
12
+
13
 #define VULKAN_INSTANCE_FUNCTION(name)                     \
14
    PFN_##name name = (PFN_##name)vkGetInstanceProcAddr(s->instance, #name)
15
 
16
@@ -91,12 +94,18 @@
17
 #define VK_CHECK_RESULT(f)                             \
18
 {                                          \
19
    VkResult _result = (f);                             \
20
-   int _res = -vkresult_to_errno(_result);                     \
21
+   int _r = -vkresult_to_errno(_result);                       \
22
    if (_result != VK_SUCCESS) {                            \
23
-       spa_log_debug(s->log, "error: %d (%s)", _result, spa_strerror(_res));   \
24
-       return _res;                                \
25
+       spa_log_error(s->log, "error: %d (%d %s)", _result, _r, spa_strerror(_r));  \
26
+       return _r;                              \
27
    }                                       \
28
 }
29
+#define CHECK(f)                                   \
30
+{                                          \
31
+   int _res = (f);                                 \
32
+   if (_res < 0)                                   \
33
+       return _res;                                \
34
+}
35
 
36
 static int createInstance(struct vulkan_state *s)
37
 {
38
@@ -111,12 +120,33 @@
39
    static const char * const extensions = {
40
        VK_KHR_EXTERNAL_MEMORY_CAPABILITIES_EXTENSION_NAME
41
    };
42
+   static const char * const checkLayers = {
43
+#ifdef ENABLE_VALIDATION
44
+       "VK_LAYER_KHRONOS_validation",
45
+#endif
46
+       NULL
47
+   };
48
+   uint32_t i, j, layerCount, n_layers = 0;
49
+   const char *layers1;
50
+   vkEnumerateInstanceLayerProperties(&layerCount, NULL);
51
+
52
+   VkLayerProperties availableLayerslayerCount;
53
+   vkEnumerateInstanceLayerProperties(&layerCount, availableLayers);
54
+
55
+   for (i = 0; i < layerCount; i++) {
56
+       for (j = 0; j < SPA_N_ELEMENTS(checkLayers); j++) {
57
+           if (spa_streq(availableLayersi.layerName, checkLayersj))
58
+               layersn_layers++ = checkLayersj;
59
+       }
60
+   }
61
 
62
    const VkInstanceCreateInfo createInfo = {
63
        .sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO,
64
        .pApplicationInfo = &applicationInfo,
65
        .enabledExtensionCount = 1,
66
        .ppEnabledExtensionNames = extensions,
67
+       .enabledLayerCount = n_layers,
68
+       .ppEnabledLayerNames = layers,
69
    };
70
 
71
    VK_CHECK_RESULT(vkCreateInstance(&createInfo, NULL, &s->instance));
72
@@ -217,31 +247,48 @@
73
 
74
 static int createDescriptors(struct vulkan_state *s)
75
 {
76
-   static const VkDescriptorPoolSize descriptorPoolSize = {
77
-       .type = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
78
-       .descriptorCount = 1
79
+   uint32_t i;
80
+
81
+   VkDescriptorPoolSize descriptorPoolSizes2 = {
82
+       {
83
+           .type = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE,
84
+           .descriptorCount = 1,
85
+       },
86
+       {
87
+           .type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
88
+           .descriptorCount = s->n_streams - 1,
89
+       },
90
    };
91
-   static const VkDescriptorPoolCreateInfo descriptorPoolCreateInfo = {
92
+   const VkDescriptorPoolCreateInfo descriptorPoolCreateInfo = {
93
        .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO,
94
-       .maxSets = 1,
95
-       .poolSizeCount = 1,
96
-       .pPoolSizes = &descriptorPoolSize,
97
+       .maxSets = s->n_streams,
98
+       .poolSizeCount = s->n_streams > 1 ? 2 : 1,
99
+       .pPoolSizes = descriptorPoolSizes,
100
    };
101
 
102
         VK_CHECK_RESULT(vkCreateDescriptorPool(s->device,
103
                &descriptorPoolCreateInfo, NULL,
104
                &s->descriptorPool));
105
 
106
-   static const VkDescriptorSetLayoutBinding descriptorSetLayoutBinding = {
107
+   VkDescriptorSetLayoutBinding descriptorSetLayoutBindings->n_streams;
108
+   descriptorSetLayoutBinding0 = (VkDescriptorSetLayoutBinding) {
109
        .binding = 0,
110
-       .descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
111
+       .descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE,
112
        .descriptorCount = 1,
113
        .stageFlags = VK_SHADER_STAGE_COMPUTE_BIT
114
    };
115
-   static const VkDescriptorSetLayoutCreateInfo descriptorSetLayoutCreateInfo = {
116
+   for (i = 1; i < s->n_streams; i++) {
117
+       descriptorSetLayoutBindingi = (VkDescriptorSetLayoutBinding) {
118
+           .binding = i,
119
+           .descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
120
+           .descriptorCount = 1,
121
+           .stageFlags = VK_SHADER_STAGE_COMPUTE_BIT
122
+       };
123
+   };
124
+   const VkDescriptorSetLayoutCreateInfo descriptorSetLayoutCreateInfo = {
125
        .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,
126
-       .bindingCount = 1,
127
-       .pBindings = &descriptorSetLayoutBinding
128
+       .bindingCount = s->n_streams,
129
+       .pBindings = descriptorSetLayoutBinding
130
    };
131
    VK_CHECK_RESULT(vkCreateDescriptorSetLayout(s->device,
132
                &descriptorSetLayoutCreateInfo, NULL,
133
@@ -257,62 +304,63 @@
134
    VK_CHECK_RESULT(vkAllocateDescriptorSets(s->device,
135
                &descriptorSetAllocateInfo,
136
                &s->descriptorSet));
137
-   return 0;
138
-}
139
-
140
-static int createBuffer(struct vulkan_state *s, uint32_t id)
141
-{
142
-   const VkBufferCreateInfo bufferCreateInfo = {
143
-       .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
144
-       .size = s->bufferSize,
145
-       .usage = VK_BUFFER_USAGE_STORAGE_BUFFER_BIT,
146
-       .sharingMode = VK_SHARING_MODE_EXCLUSIVE,
147
-   };
148
-   VkMemoryRequirements memoryRequirements;
149
-
150
-   VK_CHECK_RESULT(vkCreateBuffer(s->device,
151
-               &bufferCreateInfo, NULL, &s->buffersid.buffer));
152
 
153
-   vkGetBufferMemoryRequirements(s->device,
154
-           s->buffersid.buffer, &memoryRequirements);
155
-
156
-   const VkMemoryAllocateInfo allocateInfo = {
157
-       .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
158
-       .allocationSize = memoryRequirements.size,
159
-       .memoryTypeIndex = findMemoryType(s,
160
-                         memoryRequirements.memoryTypeBits,
161
-                         VK_MEMORY_PROPERTY_HOST_COHERENT_BIT |
162
-                         VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT),
163
+   const VkSamplerCreateInfo samplerInfo = {
164
+       .sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO,
165
+       .magFilter = VK_FILTER_LINEAR,
166
+       .minFilter = VK_FILTER_LINEAR,
167
+       .mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR,
168
+       .addressModeU = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,
169
+       .addressModeV = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,
170
+       .addressModeW = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,
171
+       .borderColor = VK_BORDER_COLOR_FLOAT_OPAQUE_BLACK,
172
+       .unnormalizedCoordinates = VK_FALSE,
173
+       .compareEnable = VK_FALSE,
174
+       .compareOp = VK_COMPARE_OP_ALWAYS,
175
+       .mipLodBias = 0.0f,
176
+       .minLod = 0,
177
+       .maxLod = 5,
178
    };
179
-
180
-   VK_CHECK_RESULT(vkAllocateMemory(s->device,
181
-               &allocateInfo, NULL, &s->buffersid.memory));
182
-   VK_CHECK_RESULT(vkBindBufferMemory(s->device,
183
-               s->buffersid.buffer, s->buffersid.memory, 0));
184
+   VK_CHECK_RESULT(vkCreateSampler(s->device, &samplerInfo, NULL, &s->sampler));
185
 
186
    return 0;
187
 }
188
 
189
-static int updateDescriptors(struct vulkan_state *s, uint32_t buffer_id)
190
+static int updateDescriptors(struct vulkan_state *s)
191
 {
192
-   if (s->current_buffer_id == buffer_id)
193
-       return 0;
194
+   uint32_t i;
195
+   VkDescriptorImageInfo descriptorImageInfos->n_streams;
196
+   VkWriteDescriptorSet writeDescriptorSets->n_streams;
197
 
198
-   const VkDescriptorBufferInfo descriptorBufferInfo = {
199
-       .buffer = s->buffersbuffer_id.buffer,
200
-       .offset = 0,
201
pipewire-0.3.51.tar.gz/spa/plugins/vulkan/vulkan-utils.h -> pipewire-0.3.52.tar.gz/spa/plugins/vulkan/vulkan-utils.h Changed
84
 
1
@@ -1,7 +1,9 @@
2
 #include <vulkan/vulkan.h>
3
 
4
 #include <spa/buffer/buffer.h>
5
+#include <spa/node/node.h>
6
 
7
+#define MAX_STREAMS 2
8
 #define MAX_BUFFERS 16
9
 #define WORKGROUP_SIZE 32
10
 
11
@@ -17,11 +19,24 @@
12
 };
13
 
14
 struct vulkan_buffer {
15
-   struct spa_buffer *buf;
16
-   VkBuffer buffer;
17
+   int fd;
18
+   VkImage image;
19
+   VkImageView view;
20
    VkDeviceMemory memory;
21
 };
22
 
23
+struct vulkan_stream {
24
+   enum spa_direction direction;
25
+
26
+   uint32_t pending_buffer_id;
27
+   uint32_t current_buffer_id;
28
+   uint32_t busy_buffer_id;
29
+   uint32_t ready_buffer_id;
30
+
31
+   struct vulkan_buffer buffersMAX_BUFFERS;
32
+   uint32_t n_buffers;
33
+};
34
+
35
 struct vulkan_state {
36
    struct spa_log *log;
37
 
38
@@ -34,6 +49,7 @@
39
 
40
    VkPipeline pipeline;
41
    VkPipelineLayout pipelineLayout;
42
+   const char *shaderName;
43
    VkShaderModule computeShaderModule;
44
 
45
    VkCommandPool commandPool;
46
@@ -43,27 +59,28 @@
47
    uint32_t queueFamilyIndex;
48
    VkFence fence;
49
    unsigned int prepared:1;
50
-   uint32_t busy_buffer_id;
51
-   uint32_t ready_buffer_id;
52
+   unsigned int started:1;
53
 
54
    VkDescriptorPool descriptorPool;
55
-   VkDescriptorSet descriptorSet;
56
    VkDescriptorSetLayout descriptorSetLayout;
57
-   uint32_t current_buffer_id;
58
 
59
-   uint32_t bufferSize;
60
-   struct vulkan_buffer buffersMAX_BUFFERS;
61
-   uint32_t n_buffers;
62
+   VkSampler sampler;
63
 
64
+   uint32_t n_streams;
65
+   VkDescriptorSet descriptorSet;
66
+   struct vulkan_stream streamsMAX_STREAMS;
67
 };
68
 
69
+int spa_vulkan_init_stream(struct vulkan_state *s, struct vulkan_stream *stream, enum spa_direction,
70
+       struct spa_dict *props);
71
+
72
 int spa_vulkan_prepare(struct vulkan_state *s);
73
-int spa_vulkan_use_buffers(struct vulkan_state *s, uint32_t flags,
74
+int spa_vulkan_use_buffers(struct vulkan_state *s, struct vulkan_stream *stream, uint32_t flags,
75
        uint32_t n_buffers, struct spa_buffer **buffers);
76
 int spa_vulkan_unprepare(struct vulkan_state *s);
77
 
78
 int spa_vulkan_start(struct vulkan_state *s);
79
 int spa_vulkan_stop(struct vulkan_state *s);
80
 int spa_vulkan_ready(struct vulkan_state *s);
81
-int spa_vulkan_process(struct vulkan_state *s, uint32_t buffer_id);
82
+int spa_vulkan_process(struct vulkan_state *s);
83
 int spa_vulkan_cleanup(struct vulkan_state *s);
84
pipewire-0.3.51.tar.gz/src/daemon/minimal.conf.in -> pipewire-0.3.52.tar.gz/src/daemon/minimal.conf.in Changed
10
 
1
@@ -27,7 +27,7 @@
2
 
3
     ## Properties for the DSP configuration.
4
     #default.clock.rate          = 48000
5
-    #default.clock.allowed-rates =  48000 
6
+    #default.clock.allowed-rates =  44100 48000 
7
     #default.clock.quantum       = 1024
8
     #default.clock.min-quantum   = 32
9
     #default.clock.max-quantum   = 2048
10
pipewire-0.3.51.tar.gz/src/daemon/pipewire.conf.in -> pipewire-0.3.52.tar.gz/src/daemon/pipewire.conf.in Changed
10
 
1
@@ -27,7 +27,7 @@
2
 
3
     ## Properties for the DSP configuration.
4
     #default.clock.rate          = 48000
5
-    #default.clock.allowed-rates =  48000 
6
+    #default.clock.allowed-rates =  44100 48000 
7
     #default.clock.quantum       = 1024
8
     default.clock.min-quantum   = 16
9
     #default.clock.max-quantum   = 2048
10
pipewire-0.3.51.tar.gz/src/examples/audio-src.c -> pipewire-0.3.52.tar.gz/src/examples/audio-src.c Changed
10
 
1
@@ -93,7 +93,7 @@
2
        return;
3
 
4
    stride = sizeof(float) * DEFAULT_CHANNELS;
5
-   n_frames = buf->datas0.maxsize / stride;
6
+   n_frames = SPA_MIN(b->requested, buf->datas0.maxsize / stride);
7
 
8
    fill_f32(data, p, n_frames);
9
 
10
pipewire-0.3.51.tar.gz/src/examples/video-play-fixate.c -> pipewire-0.3.52.tar.gz/src/examples/video-play-fixate.c Changed
43
 
1
@@ -45,6 +45,7 @@
2
 #define HEIGHT  480
3
 
4
 #define MAX_BUFFERS    64
5
+#define MAX_MOD        8
6
 
7
 #include "sdl.h"
8
 
9
@@ -61,7 +62,7 @@
10
 struct modifier_info {
11
         uint32_t spa_format;
12
         uint32_t n_modifiers;
13
-        uint64_t *modifiers;
14
+        uint64_t modifiersMAX_MOD;
15
 };
16
 
17
 struct data {
18
@@ -83,7 +84,7 @@
19
    struct spa_rectangle size;
20
 
21
    uint32_t n_mod_info;
22
-   struct modifier_info mod_info1;
23
+   struct modifier_info mod_info2;
24
 
25
    int counter;
26
 };
27
@@ -107,14 +108,12 @@
28
    data->n_mod_info = 1;
29
    data->mod_info0.spa_format = SPA_VIDEO_FORMAT_RGB;
30
    data->mod_info0.n_modifiers = 2;
31
-   data->mod_info0.modifiers = (uint64_t*)malloc(2*sizeof(uint32_t));
32
    data->mod_info0.modifiers0 = DRM_FORMAT_MOD_LINEAR;
33
-   data->mod_info0.modifiers0 = DRM_FORMAT_MOD_INVALID;
34
+   data->mod_info0.modifiers1 = DRM_FORMAT_MOD_INVALID;
35
 }
36
 
37
 static void destroy_modifiers(struct data *data)
38
 {
39
-   free(data->mod_info0.modifiers);
40
    data->mod_info0.n_modifiers = 0;
41
 }
42
 
43
pipewire-0.3.51.tar.gz/src/gst/gstpipewirepool.c -> pipewire-0.3.52.tar.gz/src/gst/gstpipewirepool.c Changed
32
 
1
@@ -89,24 +89,21 @@
2
 
3
     GST_LOG_OBJECT (pool, "wrap buffer %d %d", d->mapoffset, d->maxsize);
4
     if (d->type == SPA_DATA_MemFd) {
5
-      gmem = gst_fd_allocator_alloc (pool->fd_allocator, d->fd,
6
-                d->mapoffset + d->maxsize, GST_FD_MEMORY_FLAG_DONT_CLOSE);
7
+      gmem = gst_fd_allocator_alloc (pool->fd_allocator, dup(d->fd),
8
+                d->mapoffset + d->maxsize, GST_FD_MEMORY_FLAG_NONE);
9
       gst_memory_resize (gmem, d->mapoffset, d->maxsize);
10
-      data->offset = d->mapoffset;
11
     }
12
     else if(d->type == SPA_DATA_DmaBuf) {
13
-      gmem = gst_fd_allocator_alloc (pool->dmabuf_allocator, d->fd,
14
-                d->mapoffset + d->maxsize, GST_FD_MEMORY_FLAG_DONT_CLOSE);
15
+      gmem = gst_fd_allocator_alloc (pool->dmabuf_allocator, dup(d->fd),
16
+                d->mapoffset + d->maxsize, GST_FD_MEMORY_FLAG_NONE);
17
       gst_memory_resize (gmem, d->mapoffset, d->maxsize);
18
-      data->offset = d->mapoffset;
19
     }
20
     else if (d->type == SPA_DATA_MemPtr) {
21
-      gmem = gst_memory_new_wrapped (GST_MEMORY_FLAG_NO_SHARE, d->data, d->maxsize, 0,
22
+      gmem = gst_memory_new_wrapped (0, d->data, d->maxsize, 0,
23
                                      d->maxsize, NULL, NULL);
24
-      data->offset = 0;
25
     }
26
     if (gmem)
27
-      gst_buffer_append_memory (buf, gmem);
28
+      gst_buffer_insert_memory (buf, i, gmem);
29
   }
30
 
31
   data->pool = gst_object_ref (pool);
32
pipewire-0.3.51.tar.gz/src/gst/gstpipewirepool.h -> pipewire-0.3.52.tar.gz/src/gst/gstpipewirepool.h Changed
9
 
1
@@ -53,7 +53,6 @@
2
   void *owner;
3
   struct spa_meta_header *header;
4
   guint flags;
5
-  goffset offset;
6
   struct pw_buffer *b;
7
   GstBuffer *buf;
8
   gboolean queued;
9
pipewire-0.3.51.tar.gz/src/gst/gstpipewiresink.c -> pipewire-0.3.52.tar.gz/src/gst/gstpipewiresink.c Changed
149
 
1
@@ -62,6 +62,7 @@
2
   PROP_PATH,
3
   PROP_TARGET_OBJECT,
4
   PROP_CLIENT_NAME,
5
+  PROP_CLIENT_PROPERTIES,
6
   PROP_STREAM_PROPERTIES,
7
   PROP_MODE,
8
   PROP_FD
9
@@ -122,8 +123,10 @@
10
 
11
   g_object_unref (pwsink->pool);
12
 
13
-  if (pwsink->properties)
14
-    gst_structure_free (pwsink->properties);
15
+  if (pwsink->stream_properties)
16
+    gst_structure_free (pwsink->stream_properties);
17
+  if (pwsink->client_properties)
18
+    gst_structure_free (pwsink->client_properties);
19
   g_free (pwsink->path);
20
   g_free (pwsink->target_object);
21
   g_free (pwsink->client_name);
22
@@ -184,6 +187,15 @@
23
                                                         G_PARAM_STATIC_STRINGS));
24
 
25
    g_object_class_install_property (gobject_class,
26
+                                    PROP_CLIENT_PROPERTIES,
27
+                                    g_param_spec_boxed ("client-properties",
28
+                                                        "Client properties",
29
+                                                        "List of PipeWire client properties",
30
+                                                        GST_TYPE_STRUCTURE,
31
+                                                        G_PARAM_READWRITE |
32
+                                                        G_PARAM_STATIC_STRINGS));
33
+
34
+   g_object_class_install_property (gobject_class,
35
                                     PROP_STREAM_PROPERTIES,
36
                                     g_param_spec_boxed ("stream-properties",
37
                                                         "Stream properties",
38
@@ -361,10 +373,17 @@
39
       pwsink->client_name = g_value_dup_string (value);
40
       break;
41
 
42
+    case PROP_CLIENT_PROPERTIES:
43
+      if (pwsink->client_properties)
44
+        gst_structure_free (pwsink->client_properties);
45
+      pwsink->client_properties =
46
+          gst_structure_copy (gst_value_get_structure (value));
47
+      break;
48
+
49
     case PROP_STREAM_PROPERTIES:
50
-      if (pwsink->properties)
51
-        gst_structure_free (pwsink->properties);
52
-      pwsink->properties =
53
+      if (pwsink->stream_properties)
54
+        gst_structure_free (pwsink->stream_properties);
55
+      pwsink->stream_properties =
56
           gst_structure_copy (gst_value_get_structure (value));
57
       break;
58
 
59
@@ -401,8 +420,12 @@
60
       g_value_set_string (value, pwsink->client_name);
61
       break;
62
 
63
+    case PROP_CLIENT_PROPERTIES:
64
+      gst_value_set_structure (value, pwsink->client_properties);
65
+      break;
66
+
67
     case PROP_STREAM_PROPERTIES:
68
-      gst_value_set_structure (value, pwsink->properties);
69
+      gst_value_set_structure (value, pwsink->stream_properties);
70
       break;
71
 
72
     case PROP_MODE:
73
@@ -466,7 +489,7 @@
74
   for (i = 0; i < b->n_datas; i++) {
75
     struct spa_data *d = &b->datasi;
76
     GstMemory *mem = gst_buffer_peek_memory (buffer, i);
77
-    d->chunk->offset = mem->offset - data->offset;
78
+    d->chunk->offset = mem->offset;
79
     d->chunk->size = mem->size;
80
   }
81
 
82
@@ -495,7 +518,10 @@
83
     case PW_STREAM_STATE_UNCONNECTED:
84
     case PW_STREAM_STATE_CONNECTING:
85
     case PW_STREAM_STATE_PAUSED:
86
+      break;
87
     case PW_STREAM_STATE_STREAMING:
88
+      if (pw_stream_is_driving (pwsink->stream))
89
+        pw_stream_trigger_process (pwsink->stream);
90
       break;
91
     case PW_STREAM_STATE_ERROR:
92
       GST_ELEMENT_ERROR (pwsink, RESOURCE, FAILED,
93
@@ -679,6 +705,9 @@
94
   if (unref_buffer)
95
     gst_buffer_unref (buffer);
96
 
97
+  if (pw_stream_is_driving (pwsink->stream))
98
+    pw_stream_trigger_process (pwsink->stream);
99
+
100
 done_unlock:
101
   pw_thread_loop_unlock (pwsink->core->loop);
102
 done:
103
@@ -727,16 +756,17 @@
104
 
105
   pwsink->negotiated = FALSE;
106
 
107
+  pw_thread_loop_lock (pwsink->core->loop);
108
+
109
   props = pw_properties_new (NULL, NULL);
110
   if (pwsink->client_name) {
111
     pw_properties_set (props, PW_KEY_NODE_NAME, pwsink->client_name);
112
     pw_properties_set (props, PW_KEY_NODE_DESCRIPTION, pwsink->client_name);
113
   }
114
-  if (pwsink->properties) {
115
-    gst_structure_foreach (pwsink->properties, copy_properties, props);
116
+  if (pwsink->stream_properties) {
117
+    gst_structure_foreach (pwsink->stream_properties, copy_properties, props);
118
   }
119
 
120
-  pw_thread_loop_lock (pwsink->core->loop);
121
   if ((pwsink->stream = pw_stream_new (pwsink->core->core, pwsink->client_name, props)) == NULL)
122
     goto no_stream;
123
 
124
@@ -780,10 +810,24 @@
125
 static gboolean
126
 gst_pipewire_sink_open (GstPipeWireSink * pwsink)
127
 {
128
+  struct pw_properties *props;
129
+
130
+  GST_DEBUG_OBJECT (pwsink, "open");
131
+
132
   pwsink->core = gst_pipewire_core_get(pwsink->fd);
133
   if (pwsink->core == NULL)
134
       goto connect_error;
135
 
136
+  pw_thread_loop_lock (pwsink->core->loop);
137
+
138
+  props = pw_properties_new (NULL, NULL);
139
+  if (pwsink->client_properties) {
140
+    gst_structure_foreach (pwsink->client_properties, copy_properties, props);
141
+    pw_core_update_properties (pwsink->core->core, &props->dict);
142
+  }
143
+  pw_properties_free(props);
144
+  pw_thread_loop_unlock (pwsink->core->loop);
145
+
146
   return TRUE;
147
 
148
   /* ERRORS */
149
pipewire-0.3.51.tar.gz/src/gst/gstpipewiresink.h -> pipewire-0.3.52.tar.gz/src/gst/gstpipewiresink.h Changed
15
 
1
@@ -87,11 +87,12 @@
2
 
3
   GstPipeWireCore *core;
4
   struct spa_hook core_listener;
5
+  GstStructure *client_properties;
6
 
7
   struct pw_stream *stream;
8
   struct spa_hook stream_listener;
9
 
10
-  GstStructure *properties;
11
+  GstStructure *stream_properties;
12
   GstPipeWireSinkMode mode;
13
 
14
   GstPipeWirePool *pool;
15
pipewire-0.3.51.tar.gz/src/gst/gstpipewiresrc.c -> pipewire-0.3.52.tar.gz/src/gst/gstpipewiresrc.c Changed
201
 
1
@@ -69,6 +69,7 @@
2
   PROP_PATH,
3
   PROP_TARGET_OBJECT,
4
   PROP_CLIENT_NAME,
5
+  PROP_CLIENT_PROPERTIES,
6
   PROP_STREAM_PROPERTIES,
7
   PROP_ALWAYS_COPY,
8
   PROP_MIN_BUFFERS,
9
@@ -127,10 +128,17 @@
10
       pwsrc->client_name = g_value_dup_string (value);
11
       break;
12
 
13
+    case PROP_CLIENT_PROPERTIES:
14
+      if (pwsrc->client_properties)
15
+        gst_structure_free (pwsrc->client_properties);
16
+      pwsrc->client_properties =
17
+          gst_structure_copy (gst_value_get_structure (value));
18
+      break;
19
+
20
     case PROP_STREAM_PROPERTIES:
21
-      if (pwsrc->properties)
22
-        gst_structure_free (pwsrc->properties);
23
-      pwsrc->properties =
24
+      if (pwsrc->stream_properties)
25
+        gst_structure_free (pwsrc->stream_properties);
26
+      pwsrc->stream_properties =
27
           gst_structure_copy (gst_value_get_structure (value));
28
       break;
29
 
30
@@ -183,8 +191,12 @@
31
       g_value_set_string (value, pwsrc->client_name);
32
       break;
33
 
34
+    case PROP_CLIENT_PROPERTIES:
35
+      gst_value_set_structure (value, pwsrc->client_properties);
36
+      break;
37
+
38
     case PROP_STREAM_PROPERTIES:
39
-      gst_value_set_structure (value, pwsrc->properties);
40
+      gst_value_set_structure (value, pwsrc->stream_properties);
41
       break;
42
 
43
     case PROP_ALWAYS_COPY:
44
@@ -249,8 +261,10 @@
45
 {
46
   GstPipeWireSrc *pwsrc = GST_PIPEWIRE_SRC (object);
47
 
48
-  if (pwsrc->properties)
49
-    gst_structure_free (pwsrc->properties);
50
+  if (pwsrc->stream_properties)
51
+    gst_structure_free (pwsrc->stream_properties);
52
+  if (pwsrc->client_properties)
53
+    gst_structure_free (pwsrc->client_properties);
54
   if (pwsrc->clock)
55
     gst_object_unref (pwsrc->clock);
56
   g_free (pwsrc->path);
57
@@ -307,6 +321,15 @@
58
                                                         G_PARAM_STATIC_STRINGS));
59
 
60
   g_object_class_install_property (gobject_class,
61
+                                   PROP_CLIENT_PROPERTIES,
62
+                                   g_param_spec_boxed ("client-properties",
63
+                                                       "client properties",
64
+                                                       "list of PipeWire client properties",
65
+                                                       GST_TYPE_STRUCTURE,
66
+                                                       G_PARAM_READWRITE |
67
+                                                       G_PARAM_STATIC_STRINGS));
68
+
69
+  g_object_class_install_property (gobject_class,
70
                                    PROP_STREAM_PROPERTIES,
71
                                    g_param_spec_boxed ("stream-properties",
72
                                                        "stream properties",
73
@@ -497,14 +520,21 @@
74
           return NULL;
75
 
76
   data = b->user_data;
77
-  buf = data->buf;
78
 
79
-  GST_LOG_OBJECT (pwsrc, "got new buffer %p", buf);
80
+  if (!GST_IS_BUFFER (data->buf)) {
81
+    GST_ERROR_OBJECT (pwsrc, "stream buffer %p is missing", data->buf);
82
+    return NULL;
83
+  }
84
 
85
   if (!data->queued) {
86
-    GST_WARNING_OBJECT (pwsrc, "buffer %p was not recycled", buf);
87
-    gst_buffer_ref (buf);
88
+    GST_ERROR_OBJECT (pwsrc, "buffer %p was not recycled", data->buf);
89
+    return NULL;
90
   }
91
+
92
+  GST_LOG_OBJECT (pwsrc, "got new buffer %p", data->buf);
93
+
94
+  buf = gst_buffer_new ();
95
+
96
   data->queued = FALSE;
97
   GST_BUFFER_PTS (buf) = GST_CLOCK_TIME_NONE;
98
   GST_BUFFER_DTS (buf) = GST_CLOCK_TIME_NONE;
99
@@ -530,12 +560,16 @@
100
       meta->height = crop->region.size.height;
101
     }
102
   }
103
+  gst_buffer_add_parent_buffer_meta (buf, data->buf);
104
+  gst_buffer_unref (data->buf);
105
   for (i = 0; i < b->buffer->n_datas; i++) {
106
     struct spa_data *d = &b->buffer->datasi;
107
-    GstMemory *mem = gst_buffer_peek_memory (buf, i);
108
-    mem->offset = SPA_MIN(d->chunk->offset, d->maxsize);
109
-    mem->size = SPA_MIN(d->chunk->size, d->maxsize - mem->offset);
110
-    mem->offset += data->offset;
111
+    GstMemory *pmem = gst_buffer_peek_memory (data->buf, i);
112
+    if (pmem) {
113
+      GstMemory *mem = gst_memory_share (pmem, d->chunk->offset, d->chunk->size);
114
+      gst_buffer_insert_memory (buf, i, mem);
115
+      spa_assert_se(mem->size <= mem->maxsize);
116
+    }
117
     if (d->chunk->flags & SPA_CHUNK_FLAG_CORRUPTED)
118
       GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_CORRUPTED);
119
   }
120
@@ -604,7 +638,7 @@
121
   GST_DEBUG_OBJECT (pwsrc, "doing stream start");
122
 
123
   pw_thread_loop_get_time (pwsrc->core->loop, &abstime,
124
-         GST_PIPEWIRE_DEFAULT_TIMEOUT * SPA_NSEC_PER_SEC);
125
+                  GST_PIPEWIRE_DEFAULT_TIMEOUT * SPA_NSEC_PER_SEC);
126
 
127
   while (TRUE) {
128
     enum pw_stream_state state = pw_stream_get_state (pwsrc->stream, &error);
129
@@ -654,7 +688,7 @@
130
   pw_thread_loop_lock (this->core->loop);
131
 
132
   pw_thread_loop_get_time (this->core->loop, &abstime,
133
-         GST_PIPEWIRE_DEFAULT_TIMEOUT * SPA_NSEC_PER_SEC);
134
+                  GST_PIPEWIRE_DEFAULT_TIMEOUT * SPA_NSEC_PER_SEC);
135
 
136
   while (TRUE) {
137
     state = pw_stream_get_state (this->stream, &error);
138
@@ -679,7 +713,7 @@
139
     }
140
   }
141
   GST_DEBUG_OBJECT (this, "got started signal: %s",
142
-         pw_stream_state_as_string (state));
143
+                  pw_stream_state_as_string (state));
144
   pw_thread_loop_unlock (this->core->loop);
145
 
146
   return state;
147
@@ -782,7 +816,7 @@
148
   g_ptr_array_free (possible, TRUE);
149
 
150
   pw_thread_loop_get_time (pwsrc->core->loop, &abstime,
151
-         GST_PIPEWIRE_DEFAULT_TIMEOUT * SPA_NSEC_PER_SEC);
152
+                  GST_PIPEWIRE_DEFAULT_TIMEOUT * SPA_NSEC_PER_SEC);
153
 
154
   while (TRUE) {
155
     enum pw_stream_state state = pw_stream_get_state (pwsrc->stream, &error);
156
@@ -860,7 +894,7 @@
157
     return;
158
   }
159
   if (pwsrc->caps)
160
-     gst_caps_unref(pwsrc->caps);
161
+          gst_caps_unref(pwsrc->caps);
162
   pwsrc->caps = gst_caps_from_format (param);
163
   GST_DEBUG_OBJECT (pwsrc, "we got format %" GST_PTR_FORMAT, pwsrc->caps);
164
 
165
@@ -882,8 +916,8 @@
166
         SPA_PARAM_BUFFERS_size,    SPA_POD_CHOICE_RANGE_Int(0, 0, INT32_MAX),
167
         SPA_PARAM_BUFFERS_stride,  SPA_POD_CHOICE_RANGE_Int(0, 0, INT32_MAX),
168
         SPA_PARAM_BUFFERS_dataType, SPA_POD_CHOICE_FLAGS_Int(
169
-                       (1<<SPA_DATA_MemFd) |
170
-                       (1<<SPA_DATA_MemPtr)));
171
+                                                (1<<SPA_DATA_MemFd) |
172
+                                                (1<<SPA_DATA_MemPtr)));
173
 
174
     params1 = spa_pod_builder_add_object (&b,
175
         SPA_TYPE_OBJECT_ParamMeta, SPA_PARAM_Meta,
176
@@ -1031,7 +1065,7 @@
177
       buf = dequeue_buffer (pwsrc);
178
       GST_LOG_OBJECT (pwsrc, "popped buffer %p", buf);
179
       if (buf != NULL) {
180
-   if (pwsrc->resend_last || pwsrc->keepalive_time > 0)
181
+        if (pwsrc->resend_last || pwsrc->keepalive_time > 0)
182
           gst_buffer_replace (&pwsrc->last_buffer, buf);
183
         break;
184
       }
185
@@ -1040,7 +1074,7 @@
186
     if (pwsrc->keepalive_time > 0) {
187
       struct timespec abstime;
188
       pw_thread_loop_get_time(pwsrc->core->loop, &abstime,
189
-             pwsrc->keepalive_time * SPA_NSEC_PER_MSEC);
190
+                      pwsrc->keepalive_time * SPA_NSEC_PER_MSEC);
191
       if (pw_thread_loop_timed_wait_full (pwsrc->core->loop, &abstime) == -ETIMEDOUT)
192
         timeout = TRUE;
193
     } else {
194
@@ -1176,12 +1210,17 @@
195
   pw_thread_loop_lock (pwsrc->core->loop);
196
 
197
   props = pw_properties_new (NULL, NULL);
198
+  if (pwsrc->client_properties) {
199
+    gst_structure_foreach (pwsrc->client_properties, copy_properties, props);
200
+    pw_core_update_properties (pwsrc->core->core, &props->dict);
201
pipewire-0.3.51.tar.gz/src/gst/gstpipewiresrc.h -> pipewire-0.3.52.tar.gz/src/gst/gstpipewiresrc.h Changed
18
 
1
@@ -80,6 +80,7 @@
2
   GstClockTime min_latency;
3
   GstClockTime max_latency;
4
 
5
+  GstStructure *client_properties;
6
   GstPipeWireCore *core;
7
   struct spa_hook core_listener;
8
   int last_seq;
9
@@ -89,7 +90,7 @@
10
   struct spa_hook stream_listener;
11
 
12
   GstBuffer *last_buffer;
13
-  GstStructure *properties;
14
+  GstStructure *stream_properties;
15
 
16
   GstPipeWirePool *pool;
17
   GstClock *clock;
18
pipewire-0.3.51.tar.gz/src/modules/meson.build -> pipewire-0.3.52.tar.gz/src/modules/meson.build Changed
25
 
1
@@ -15,6 +15,7 @@
2
   'module-link-factory.c',
3
   'module-loopback.c',
4
   'module-metadata.c',
5
+  'module-pipe-tunnel.c',
6
   'module-portal.c',
7
   'module-profiler.c',
8
   'module-protocol-native.c',
9
@@ -298,6 +299,15 @@
10
 endif
11
 summary({'pulse-tunnel': build_module_pulse_tunnel}, bool_yn: true, section: 'Optional Modules')
12
 
13
+pipewire_module_pipe_tunnel = shared_library('pipewire-module-pipe-tunnel',
14
+   'module-pipe-tunnel.c' ,
15
+  include_directories : configinc,
16
+  install : true,
17
+  install_dir : modules_install_dir,
18
+  install_rpath: modules_install_dir,
19
+  dependencies : mathlib, dl_lib, pipewire_dep,
20
+)
21
+
22
 pipewire_module_protocol_simple = shared_library('pipewire-module-protocol-simple',
23
    'module-protocol-simple.c' ,
24
   include_directories : configinc,
25
pipewire-0.3.51.tar.gz/src/modules/module-adapter.c -> pipewire-0.3.52.tar.gz/src/modules/module-adapter.c Changed
201
 
1
@@ -56,7 +56,8 @@
2
 };
3
 
4
 struct factory_data {
5
-   struct pw_impl_factory *this;
6
+   struct pw_impl_factory *factory;
7
+   struct spa_hook factory_listener;
8
 
9
    struct spa_list node_list;
10
 
11
@@ -70,6 +71,7 @@
12
    struct spa_list link;
13
    struct pw_impl_node *adapter;
14
    struct pw_impl_node *follower;
15
+   struct spa_handle *handle;
16
    struct spa_hook adapter_listener;
17
    struct pw_resource *resource;
18
    struct pw_resource *bound_resource;
19
@@ -113,7 +115,10 @@
20
 
21
    spa_hook_remove(&nd->adapter_listener);
22
 
23
-   pw_impl_node_destroy(nd->follower);
24
+   if (nd->follower)
25
+       pw_impl_node_destroy(nd->follower);
26
+   if (nd->handle)
27
+       pw_unload_spa_handle(nd->handle);
28
 }
29
 
30
 static void node_initialized(void *data)
31
@@ -168,20 +173,27 @@
32
    struct factory_data *d = _data;
33
    struct pw_impl_client *client;
34
    struct pw_impl_node *adapter, *follower;
35
-   const char *str, *factory_name;
36
+   struct spa_node *spa_follower;
37
+   const char *str;
38
    int res;
39
    struct node_data *nd;
40
    bool linger, do_register;
41
+   struct spa_handle *handle = NULL;
42
+   const struct pw_properties *p;
43
 
44
    if (properties == NULL)
45
        goto error_properties;
46
 
47
    pw_properties_setf(properties, PW_KEY_FACTORY_ID, "%d",
48
-           pw_impl_factory_get_info(d->this)->id);
49
+           pw_impl_factory_get_info(d->factory)->id);
50
 
51
    linger = pw_properties_get_bool(properties, PW_KEY_OBJECT_LINGER, false);
52
    do_register = pw_properties_get_bool(properties, PW_KEY_OBJECT_REGISTER, true);
53
 
54
+   p = pw_context_get_properties(d->context);
55
+   pw_properties_set(properties, "clock.quantum-limit",
56
+           pw_properties_get(p, "default.clock.quantum-limit"));
57
+
58
    client = resource ? pw_resource_get_client(resource): NULL;
59
    if (client && !linger) {
60
        pw_properties_setf(properties, PW_KEY_CLIENT_ID, "%d",
61
@@ -189,29 +201,44 @@
62
    }
63
 
64
    follower = NULL;
65
+   spa_follower = NULL;
66
    str = pw_properties_get(properties, "adapt.follower.node");
67
    if (str != NULL) {
68
        if (sscanf(str, "pointer:%p", &follower) != 1)
69
            goto error_properties;
70
-
71
-       pw_properties_setf(properties, "audio.adapt.follower", "pointer:%p", follower);
72
+       spa_follower = pw_impl_node_get_implementation(follower);
73
+   }
74
+   str = pw_properties_get(properties, "adapt.follower.spa-node");
75
+   if (str != NULL) {
76
+       if (sscanf(str, "pointer:%p", &spa_follower) != 1)
77
+           goto error_properties;
78
    }
79
-   if (follower == NULL) {
80
+   if (spa_follower == NULL) {
81
+       void *iface;
82
+       const char *factory_name;
83
+
84
        factory_name = pw_properties_get(properties, SPA_KEY_FACTORY_NAME);
85
        if (factory_name == NULL)
86
            goto error_properties;
87
 
88
-       follower = pw_spa_node_load(d->context,
89
-                   factory_name,
90
-                   PW_SPA_NODE_FLAG_ACTIVATE |
91
-                   PW_SPA_NODE_FLAG_NO_REGISTER,
92
-                   pw_properties_copy(properties), 0);
93
-       if (follower == NULL)
94
+       handle = pw_context_load_spa_handle(d->context,
95
+               factory_name,
96
+               properties ? &properties->dict : NULL);
97
+       if (handle == NULL)
98
            goto error_errno;
99
+
100
+       if ((res = spa_handle_get_interface(handle, SPA_TYPE_INTERFACE_Node, &iface)) < 0)
101
+           goto error_res;
102
+
103
+       spa_follower = iface;
104
+   }
105
+   if (spa_follower == NULL) {
106
+       res = -EINVAL;
107
+       goto error_res;
108
    }
109
 
110
    adapter = pw_adapter_new(pw_impl_module_get_context(d->module),
111
-           follower,
112
+           spa_follower,
113
            properties,
114
            sizeof(struct node_data));
115
    properties = NULL;
116
@@ -227,6 +254,7 @@
117
    nd->data = d;
118
    nd->adapter = adapter;
119
    nd->follower = follower;
120
+   nd->handle = handle;
121
    nd->resource = resource;
122
    nd->new_id = new_id;
123
    nd->linger = linger;
124
@@ -247,6 +275,7 @@
125
    goto error_cleanup;
126
 error_errno:
127
    res = -errno;
128
+error_res:
129
    pw_resource_errorf_id(resource, new_id, res, "can't create node: %s", spa_strerror(res));
130
    goto error_cleanup;
131
 error_usage:
132
@@ -256,6 +285,8 @@
133
    goto error_cleanup;
134
 error_cleanup:
135
    pw_properties_free(properties);
136
+   if (handle)
137
+       pw_unload_spa_handle(handle);
138
    errno = -res;
139
    return NULL;
140
 }
141
@@ -265,25 +296,43 @@
142
    .create_object = create_object,
143
 };
144
 
145
-static void module_destroy(void *data)
146
+static void factory_destroy(void *data)
147
 {
148
    struct factory_data *d = data;
149
    struct node_data *nd;
150
 
151
-   pw_log_debug("%p: destroy", d);
152
-   spa_hook_remove(&d->module_listener);
153
+   spa_hook_remove(&d->factory_listener);
154
 
155
    spa_list_consume(nd, &d->node_list, link)
156
        pw_impl_node_destroy(nd->adapter);
157
 
158
-   pw_impl_factory_destroy(d->this);
159
+   d->factory = NULL;
160
+   if (d->module)
161
+       pw_impl_module_destroy(d->module);
162
+}
163
+
164
+static const struct pw_impl_factory_events factory_events = {
165
+   PW_VERSION_IMPL_FACTORY_EVENTS,
166
+   .destroy = factory_destroy,
167
+};
168
+
169
+static void module_destroy(void *data)
170
+{
171
+   struct factory_data *d = data;
172
+
173
+   pw_log_debug("%p: destroy", d);
174
+   spa_hook_remove(&d->module_listener);
175
+   d->module = NULL;
176
+
177
+   if (d->factory)
178
+       pw_impl_factory_destroy(d->factory);
179
 }
180
 
181
 static void module_registered(void *data)
182
 {
183
    struct factory_data *d = data;
184
    struct pw_impl_module *module = d->module;
185
-   struct pw_impl_factory *factory = d->this;
186
+   struct pw_impl_factory *factory = d->factory;
187
    struct spa_dict_item items1;
188
    char id16;
189
    int res;
190
@@ -324,13 +373,15 @@
191
        return -errno;
192
 
193
    data = pw_impl_factory_get_user_data(factory);
194
-   data->this = factory;
195
+   data->factory = factory;
196
    data->context = context;
197
    data->module = module;
198
    spa_list_init(&data->node_list);
199
 
200
    pw_log_debug("module %p: new", module);
201
pipewire-0.3.51.tar.gz/src/modules/module-adapter/adapter.c -> pipewire-0.3.52.tar.gz/src/modules/module-adapter/adapter.c Changed
145
 
1
@@ -67,7 +67,7 @@
2
    struct pw_impl_node *node;
3
    struct spa_hook node_listener;
4
 
5
-   struct pw_impl_node *follower;
6
+   struct spa_node *follower;
7
 
8
    void *user_data;
9
    enum pw_direction direction;
10
@@ -199,7 +199,7 @@
11
    return 0;
12
 }
13
 
14
-static int find_format(struct pw_impl_node *node, enum pw_direction direction,
15
+static int find_format(struct spa_node *node, enum pw_direction direction,
16
        uint32_t *media_type, uint32_t *media_subtype)
17
 {
18
    uint32_t state = 0;
19
@@ -209,7 +209,7 @@
20
    struct spa_pod *format;
21
 
22
    spa_pod_builder_init(&b, buffer, sizeof(buffer));
23
-   if ((res = spa_node_port_enum_params_sync(pw_impl_node_get_implementation(node),
24
+   if ((res = spa_node_port_enum_params_sync(node,
25
                direction == PW_DIRECTION_INPUT ?
26
                    SPA_DIRECTION_INPUT :
27
                    SPA_DIRECTION_OUTPUT, 0,
28
@@ -276,7 +276,7 @@
29
        uint32_t n_position = 0;
30
 
31
        spa_pod_builder_init(&b, buffer, sizeof(buffer));
32
-       if ((res = spa_node_port_enum_params_sync(pw_impl_node_get_implementation(n->follower),
33
+       if ((res = spa_node_port_enum_params_sync(n->follower,
34
                    n->direction == PW_DIRECTION_INPUT ?
35
                        SPA_DIRECTION_INPUT :
36
                        SPA_DIRECTION_OUTPUT, 0,
37
@@ -337,36 +337,75 @@
38
    return 0;
39
 }
40
 
41
+struct info_data {
42
+   struct spa_hook listener;
43
+   struct spa_node *node;
44
+   struct pw_properties *props;
45
+   uint32_t n_input_ports;
46
+   uint32_t max_input_ports;
47
+   uint32_t n_output_ports;
48
+   uint32_t max_output_ports;
49
+};
50
+
51
+static void info_event(void *data, const struct spa_node_info *info)
52
+{
53
+   struct info_data *d = data;
54
+
55
+   pw_properties_update(d->props, info->props);
56
+
57
+   d->max_input_ports = info->max_input_ports;
58
+   d->max_output_ports = info->max_output_ports;
59
+}
60
+
61
+static void port_info_event(void *data, enum spa_direction direction, uint32_t port,
62
+       const struct spa_port_info *info)
63
+{
64
+   struct info_data *d = data;
65
+
66
+   if (direction == SPA_DIRECTION_OUTPUT)
67
+       d->n_output_ports++;
68
+   else if (direction == SPA_DIRECTION_INPUT)
69
+       d->n_input_ports++;
70
+}
71
+
72
+static const struct spa_node_events node_info_events = {
73
+   .version = SPA_VERSION_NODE_EVENTS,
74
+   .info = info_event,
75
+   .port_info = port_info_event,
76
+};
77
+
78
 struct pw_impl_node *pw_adapter_new(struct pw_context *context,
79
-       struct pw_impl_node *follower,
80
+       struct spa_node *follower,
81
        struct pw_properties *props,
82
        size_t user_data_size)
83
 {
84
    struct pw_impl_node *node;
85
    struct node *n;
86
    const char *str, *factory_name;
87
-   const struct pw_node_info *info;
88
    enum pw_direction direction;
89
    int res;
90
    uint32_t media_type, media_subtype;
91
    const struct spa_dict_item *it;
92
    struct pw_properties *copy;
93
+   struct info_data info;
94
 
95
-   info = pw_impl_node_get_info(follower);
96
-   if (info == NULL) {
97
-       res = -EINVAL;
98
+   spa_zero(info);
99
+   info.node = follower;
100
+   info.props = props;
101
+
102
+   res = spa_node_add_listener(info.node, &info.listener, &node_info_events, &info);
103
+   if (res < 0)
104
        goto error;
105
-   }
106
 
107
-   pw_log_debug("%p: in %d/%d out %d/%d", follower,
108
-           info->n_input_ports, info->max_input_ports,
109
-           info->n_output_ports, info->max_output_ports);
110
+   spa_hook_remove(&info.listener);
111
 
112
-   pw_properties_update(props, info->props);
113
+   pw_log_debug("%p: in %d/%d out %d/%d", info.node,
114
+           info.n_input_ports, info.max_input_ports,
115
+           info.n_output_ports, info.max_output_ports);
116
 
117
-   if (info->n_output_ports > 0) {
118
+   if (info.n_output_ports > 0) {
119
        direction = PW_DIRECTION_OUTPUT;
120
-   } else if (info->n_input_ports > 0) {
121
+   } else if (info.n_input_ports > 0) {
122
        direction = PW_DIRECTION_INPUT;
123
    } else {
124
        res = -EINVAL;
125
@@ -388,8 +427,7 @@
126
        goto error;
127
 
128
    if (media_type == SPA_MEDIA_TYPE_audio) {
129
-       pw_properties_setf(props, "audio.adapt.follower", "pointer:%p",
130
-               pw_impl_node_get_implementation(follower));
131
+       pw_properties_setf(props, "audio.adapt.follower", "pointer:%p", follower);
132
        pw_properties_set(props, SPA_KEY_LIBRARY_NAME, "audioconvert/libspa-audioconvert");
133
        if (pw_properties_get(props, PW_KEY_MEDIA_CLASS) == NULL)
134
            pw_properties_setf(props, PW_KEY_MEDIA_CLASS, "Audio/%s",
135
@@ -397,8 +435,7 @@
136
        factory_name = SPA_NAME_AUDIO_ADAPT;
137
    }
138
    else if (media_type == SPA_MEDIA_TYPE_video) {
139
-       pw_properties_setf(props, "video.adapt.follower", "pointer:%p",
140
-               pw_impl_node_get_implementation(follower));
141
+       pw_properties_setf(props, "video.adapt.follower", "pointer:%p", follower);
142
        pw_properties_set(props, SPA_KEY_LIBRARY_NAME, "videoconvert/libspa-videoconvert");
143
        if (pw_properties_get(props, PW_KEY_MEDIA_CLASS) == NULL)
144
            pw_properties_setf(props, PW_KEY_MEDIA_CLASS, "Video/%s",
145
pipewire-0.3.51.tar.gz/src/modules/module-adapter/adapter.h -> pipewire-0.3.52.tar.gz/src/modules/module-adapter/adapter.h Changed
10
 
1
@@ -35,7 +35,7 @@
2
 
3
 struct pw_impl_node *
4
 pw_adapter_new(struct pw_context *context,
5
-       struct pw_impl_node *follower,
6
+       struct spa_node *follower,
7
        struct pw_properties *properties,
8
        size_t user_data_size);
9
 
10
pipewire-0.3.51.tar.gz/src/modules/module-client-device.c -> pipewire-0.3.52.tar.gz/src/modules/module-client-device.c Changed
94
 
1
@@ -56,7 +56,8 @@
2
 struct pw_protocol *pw_protocol_native_ext_client_device_init(struct pw_context *context);
3
 
4
 struct factory_data {
5
-   struct pw_impl_factory *this;
6
+   struct pw_impl_factory *factory;
7
+   struct spa_hook factory_listener;
8
 
9
    struct pw_impl_module *module;
10
    struct spa_hook module_listener;
11
@@ -72,7 +73,7 @@
12
               uint32_t new_id)
13
 {
14
    struct factory_data *data = _data;
15
-   struct pw_impl_factory *this = data->this;
16
+   struct pw_impl_factory *factory = data->factory;
17
    void *result;
18
    struct pw_resource *device_resource;
19
    struct pw_impl_client *client;
20
@@ -98,7 +99,7 @@
21
    }
22
 
23
    pw_properties_setf(properties, PW_KEY_FACTORY_ID, "%d",
24
-           pw_global_get_id(pw_impl_factory_get_global(this)));
25
+           pw_global_get_id(pw_impl_factory_get_global(factory)));
26
    pw_properties_setf(properties, PW_KEY_CLIENT_ID, "%d",
27
            pw_global_get_id(pw_impl_client_get_global(client)));
28
 
29
@@ -134,22 +135,35 @@
30
    .create_object = create_object,
31
 };
32
 
33
-static void module_destroy(void *data)
34
+static void factory_destroy(void *data)
35
 {
36
    struct factory_data *d = data;
37
+   spa_hook_remove(&d->factory_listener);
38
+   d->factory = NULL;
39
+   if (d->module)
40
+       pw_impl_module_destroy(d->module);
41
+}
42
 
43
-   spa_hook_remove(&d->module_listener);
44
+static const struct pw_impl_factory_events factory_events = {
45
+   PW_VERSION_IMPL_FACTORY_EVENTS,
46
+   .destroy = factory_destroy,
47
+};
48
 
49
+static void module_destroy(void *data)
50
+{
51
+   struct factory_data *d = data;
52
+   spa_hook_remove(&d->module_listener);
53
    spa_list_remove(&d->export_spadevice.link);
54
-
55
-   pw_impl_factory_destroy(d->this);
56
+   d->module = NULL;
57
+   if (d->factory)
58
+       pw_impl_factory_destroy(d->factory);
59
 }
60
 
61
 static void module_registered(void *data)
62
 {
63
    struct factory_data *d = data;
64
    struct pw_impl_module *module = d->module;
65
-   struct pw_impl_factory *factory = d->this;
66
+   struct pw_impl_factory *factory = d->factory;
67
    struct spa_dict_item items1;
68
    char id16;
69
    int res;
70
@@ -190,7 +204,7 @@
71
        return -errno;
72
 
73
    data = pw_impl_factory_get_user_data(factory);
74
-   data->this = factory;
75
+   data->factory = factory;
76
    data->module = module;
77
 
78
    pw_log_debug("module %p: new", module);
79
@@ -206,12 +220,13 @@
80
 
81
    pw_protocol_native_ext_client_device_init(context);
82
 
83
+   pw_impl_factory_add_listener(factory, &data->factory_listener, &factory_events, data);
84
    pw_impl_module_add_listener(module, &data->module_listener, &module_events, data);
85
 
86
    pw_impl_module_update_properties(module, &SPA_DICT_INIT_ARRAY(module_props));
87
 
88
    return 0;
89
 error:
90
-   pw_impl_factory_destroy(data->this);
91
+   pw_impl_factory_destroy(data->factory);
92
    return res;
93
 }
94
pipewire-0.3.51.tar.gz/src/modules/module-client-node.c -> pipewire-0.3.52.tar.gz/src/modules/module-client-node.c Changed
78
 
1
@@ -59,7 +59,8 @@
2
 struct pw_protocol *pw_protocol_native_ext_client_node0_init(struct pw_context *context);
3
 
4
 struct factory_data {
5
-   struct pw_impl_factory *this;
6
+   struct pw_impl_factory *factory;
7
+   struct spa_hook factory_listener;
8
 
9
    struct pw_impl_module *module;
10
    struct spa_hook module_listener;
11
@@ -121,23 +122,38 @@
12
    .create_object = create_object,
13
 };
14
 
15
+static void factory_destroy(void *data)
16
+{
17
+   struct factory_data *d = data;
18
+   spa_hook_remove(&d->factory_listener);
19
+   d->factory = NULL;
20
+   if (d->module)
21
+       pw_impl_module_destroy(d->module);
22
+}
23
+
24
+static const struct pw_impl_factory_events factory_events = {
25
+   PW_VERSION_IMPL_FACTORY_EVENTS,
26
+   .destroy = factory_destroy,
27
+};
28
+
29
 static void module_destroy(void *data)
30
 {
31
    struct factory_data *d = data;
32
 
33
    spa_hook_remove(&d->module_listener);
34
-
35
    spa_list_remove(&d->export_node.link);
36
    spa_list_remove(&d->export_spanode.link);
37
 
38
-   pw_impl_factory_destroy(d->this);
39
+   d->module = NULL;
40
+   if (d->factory)
41
+       pw_impl_factory_destroy(d->factory);
42
 }
43
 
44
 static void module_registered(void *data)
45
 {
46
    struct factory_data *d = data;
47
    struct pw_impl_module *module = d->module;
48
-   struct pw_impl_factory *factory = d->this;
49
+   struct pw_impl_factory *factory = d->factory;
50
    struct spa_dict_item items1;
51
    char id16;
52
    int res;
53
@@ -177,7 +193,7 @@
54
        return -errno;
55
 
56
    data = pw_impl_factory_get_user_data(factory);
57
-   data->this = factory;
58
+   data->factory = factory;
59
    data->module = module;
60
 
61
    pw_log_debug("module %p: new", module);
62
@@ -199,6 +215,7 @@
63
    pw_protocol_native_ext_client_node_init(context);
64
    pw_protocol_native_ext_client_node0_init(context);
65
 
66
+   pw_impl_factory_add_listener(factory, &data->factory_listener, &factory_events, data);
67
    pw_impl_module_add_listener(module, &data->module_listener, &module_events, data);
68
 
69
    pw_impl_module_update_properties(module, &SPA_DICT_INIT_ARRAY(module_props));
70
@@ -207,6 +224,6 @@
71
 error_remove:
72
    spa_list_remove(&data->export_node.link);
73
 error:
74
-   pw_impl_factory_destroy(data->this);
75
+   pw_impl_factory_destroy(data->factory);
76
    return res;
77
 }
78
pipewire-0.3.51.tar.gz/src/modules/module-client-node/client-node.c -> pipewire-0.3.52.tar.gz/src/modules/module-client-node/client-node.c Changed
10
 
1
@@ -191,7 +191,7 @@
2
        p->params = NULL;
3
    } else {
4
        struct spa_pod **np;
5
-       np = reallocarray(p->params, p->n_params, sizeof(struct spa_pod *));
6
+       np = pw_reallocarray(p->params, p->n_params, sizeof(struct spa_pod *));
7
        if (np == NULL) {
8
            pw_log_error("%p: can't realloc: %m", p);
9
            free(p->params);
10
pipewire-0.3.51.tar.gz/src/modules/module-client-node/remote-node.c -> pipewire-0.3.52.tar.gz/src/modules/module-client-node/remote-node.c Changed
19
 
1
@@ -318,7 +318,7 @@
2
                            id, &idx, NULL, &param, &b.b);
3
                if (res == 1) {
4
                    void *p;
5
-                   p = reallocarray(params, n_params + 1, sizeof(struct spa_pod *));
6
+                   p = pw_reallocarray(params, n_params + 1, sizeof(struct spa_pod *));
7
                    if (p == NULL) {
8
                        res = -errno;
9
                        pw_log_error("realloc failed: %m");
10
@@ -384,7 +384,7 @@
11
                            id, &idx, NULL, &param, &b.b);
12
                if (res == 1) {
13
                    void *p;
14
-                   p = reallocarray(params, n_params + 1, sizeof(struct spa_pod*));
15
+                   p = pw_reallocarray(params, n_params + 1, sizeof(struct spa_pod*));
16
                    if (p == NULL) {
17
                        res = -errno;
18
                        pw_log_error("realloc failed: %m");
19
pipewire-0.3.51.tar.gz/src/modules/module-client-node/v0/client-node.c -> pipewire-0.3.52.tar.gz/src/modules/module-client-node/v0/client-node.c Changed
19
 
1
@@ -476,7 +476,7 @@
2
            port->params = NULL;
3
        } else {
4
            void *p;
5
-           p = reallocarray(port->params, port->n_params, sizeof(struct spa_pod *));
6
+           p = pw_reallocarray(port->params, port->n_params, sizeof(struct spa_pod *));
7
            if (p == NULL) {
8
                pw_log_error("%p: port %u can't realloc: %m", this, port_id);
9
                free(port->params);
10
@@ -1049,7 +1049,7 @@
11
            this->params = NULL;
12
        } else {
13
            void *p;
14
-           p = reallocarray(this->params, this->n_params, sizeof(struct spa_pod *));
15
+           p = pw_reallocarray(this->params, this->n_params, sizeof(struct spa_pod *));
16
            if (p == NULL) {
17
                pw_log_error("%p: can't realloc: %m", this);
18
                free(this->params);
19
pipewire-0.3.51.tar.gz/src/modules/module-echo-cancel.c -> pipewire-0.3.52.tar.gz/src/modules/module-echo-cancel.c Changed
79
 
1
@@ -339,16 +339,20 @@
2
    struct impl *impl = data;
3
    struct pw_buffer *buf;
4
    struct spa_data *d;
5
-   uint32_t i, index, size;
6
+   uint32_t i, index, offs, size;
7
    int32_t avail;
8
 
9
    if ((buf = pw_stream_dequeue_buffer(impl->capture)) == NULL) {
10
        pw_log_debug("out of capture buffers: %m");
11
        return;
12
    }
13
+   d = &buf->buffer->datas0;
14
+
15
+   offs = SPA_MIN(d->chunk->offset, d->maxsize);
16
+   size = SPA_MIN(d->chunk->size, d->maxsize - offs);
17
 
18
    avail = spa_ringbuffer_get_write_index(&impl->rec_ring, &index);
19
-   size = buf->buffer->datas0.chunk->size;
20
+
21
    if (avail + size > impl->rec_ringsize) {
22
        uint32_t rindex, drop;
23
 
24
@@ -375,10 +379,12 @@
25
        /* captured samples, with echo from sink */
26
        d = &buf->buffer->datasi;
27
 
28
+       offs = SPA_MIN(d->chunk->offset, d->maxsize);
29
+       size = SPA_MIN(d->chunk->size, d->maxsize - offs);
30
+
31
        spa_ringbuffer_write_data(&impl->rec_ring, impl->rec_bufferi,
32
                impl->rec_ringsize, index % impl->rec_ringsize,
33
-               SPA_PTROFF(d->data, d->chunk->offset, void),
34
-               d->chunk->size);
35
+               SPA_PTROFF(d->data, offs, void), size);
36
    }
37
 
38
    spa_ringbuffer_write_update(&impl->rec_ring, index + size);
39
@@ -526,16 +532,20 @@
40
    struct impl *impl = data;
41
    struct pw_buffer *buf;
42
    struct spa_data *d;
43
-   uint32_t i, index, size;
44
+   uint32_t i, index, offs, size;
45
    int32_t avail;
46
 
47
    if ((buf = pw_stream_dequeue_buffer(impl->sink)) == NULL) {
48
        pw_log_debug("out of sink buffers: %m");
49
        return;
50
    }
51
+   d = &buf->buffer->datas0;
52
+
53
+   offs = SPA_MIN(d->chunk->offset, d->maxsize);
54
+   size = SPA_MIN(d->chunk->size, d->maxsize - offs);
55
 
56
    avail = spa_ringbuffer_get_write_index(&impl->play_ring, &index);
57
-   size = buf->buffer->datas0.chunk->size;
58
+
59
    if (avail + size > impl->play_ringsize) {
60
        uint32_t rindex, drop;
61
 
62
@@ -562,12 +572,13 @@
63
        /* echo from sink */
64
        d = &buf->buffer->datasi;
65
 
66
+       offs = SPA_MIN(d->chunk->offset, d->maxsize);
67
+       size = SPA_MIN(d->chunk->size, d->maxsize - offs);
68
+
69
        spa_ringbuffer_write_data(&impl->play_ring, impl->play_bufferi,
70
                impl->play_ringsize, index % impl->play_ringsize,
71
-               SPA_PTROFF(d->data, d->chunk->offset, void),
72
-               d->chunk->size);
73
+               SPA_PTROFF(d->data, offs, void), size);
74
    }
75
-
76
    spa_ringbuffer_write_update(&impl->play_ring, index + size);
77
 
78
    if (avail + size >= impl->aec_blocksize) {
79
pipewire-0.3.51.tar.gz/src/modules/module-example-sink.c -> pipewire-0.3.52.tar.gz/src/modules/module-example-sink.c Changed
53
 
1
@@ -99,15 +99,15 @@
2
 
3
 #define DEFAULT_FORMAT "S16"
4
 #define DEFAULT_RATE 48000
5
-#define DEFAULT_CHANNELS "2"
6
+#define DEFAULT_CHANNELS 2
7
 #define DEFAULT_POSITION " FL FR "
8
 
9
 #define MODULE_USAGE   " node.latency=<latency as fraction>  "             \
10
            " node.name=<name of the nodes>  "                  \
11
            " node.description=<description of the nodes>  "            \
12
            " audio.format=<format, default:"DEFAULT_FORMAT">  "            \
13
-           " audio.rate=<sample rate, default: 48000>  "               \
14
-           " audio.channels=<number of channels, default:"DEFAULT_CHANNELS">  "    \
15
+           " audio.rate=<sample rate, default: "SPA_STRINGIFY(DEFAULT_RATE)">  "           \
16
+           " audio.channels=<number of channels, default:"SPA_STRINGIFY(EFAULT_CHANNELS) ">  " \
17
            " audio.position=<channel map, default:"DEFAULT_POSITION">  "       \
18
            " stream.props=<properties>  "
19
 
20
@@ -187,7 +187,7 @@
21
    struct pw_buffer *buf;
22
    struct spa_data *bd;
23
    void *data;
24
-   uint32_t size;
25
+   uint32_t offs, size;
26
 
27
    if ((buf = pw_stream_dequeue_buffer(impl->stream)) == NULL) {
28
        pw_log_debug("out of buffers: %m");
29
@@ -195,8 +195,10 @@
30
    }
31
 
32
    bd = &buf->buffer->datas0;
33
-   data = SPA_PTROFF(bd->data, bd->chunk->offset, void);
34
-   size = bd->chunk->size;
35
+
36
+   offs = SPA_MIN(bd->chunk->offset, bd->maxsize);
37
+   size = SPA_MIN(bd->chunk->size, bd->maxsize - offs);
38
+   data = SPA_PTROFF(bd->data, offs, void);
39
 
40
    /* write buffer contents here */
41
    pw_log_info("got buffer of size %d and data %p", size, data);
42
@@ -377,9 +379,7 @@
43
        pw_log_error("invalid rate '%s'", str);
44
        return -EINVAL;
45
    }
46
-   if ((str = pw_properties_get(props, PW_KEY_AUDIO_CHANNELS)) == NULL)
47
-       str = DEFAULT_CHANNELS;
48
-   info->channels = atoi(str);
49
+   info->channels = pw_properties_get_uint32(props, PW_KEY_AUDIO_CHANNELS, DEFAULT_CHANNELS);
50
    if ((str = pw_properties_get(props, SPA_KEY_AUDIO_POSITION)) == NULL)
51
        str = DEFAULT_POSITION;
52
    parse_position(info, str, strlen(str));
53
pipewire-0.3.51.tar.gz/src/modules/module-example-source.c -> pipewire-0.3.52.tar.gz/src/modules/module-example-source.c Changed
31
 
1
@@ -99,15 +99,15 @@
2
 
3
 #define DEFAULT_FORMAT "S16"
4
 #define DEFAULT_RATE 48000
5
-#define DEFAULT_CHANNELS "2"
6
+#define DEFAULT_CHANNELS 2
7
 #define DEFAULT_POSITION " FL FR "
8
 
9
 #define MODULE_USAGE   " node.latency=<latency as fraction>  "             \
10
            " node.name=<name of the nodes>  "                  \
11
            " node.description=<description of the nodes>  "            \
12
            " audio.format=<format, default:"DEFAULT_FORMAT">  "            \
13
-           " audio.rate=<sample rate, default: 48000>  "               \
14
-           " audio.channels=<number of channels, default:"DEFAULT_CHANNELS">  "    \
15
+           " audio.rate=<sample rate, default: "SPA_STRINGIFY(DEFAULT_RATE)">  "           \
16
+           " audio.channels=<number of channels, default:"SPA_STRINGIFY(EFAULT_CHANNELS) ">  " \
17
            " audio.position=<channel map, default:"DEFAULT_POSITION">  "       \
18
            " stream.props=<properties>  "
19
 
20
@@ -383,9 +383,7 @@
21
        pw_log_error("invalid rate '%s'", str);
22
        return -EINVAL;
23
    }
24
-   if ((str = pw_properties_get(props, PW_KEY_AUDIO_CHANNELS)) == NULL)
25
-       str = DEFAULT_CHANNELS;
26
-   info->channels = atoi(str);
27
+   info->channels = pw_properties_get_uint32(props, PW_KEY_AUDIO_CHANNELS, DEFAULT_CHANNELS);
28
    if ((str = pw_properties_get(props, SPA_KEY_AUDIO_POSITION)) == NULL)
29
        str = DEFAULT_POSITION;
30
    parse_position(info, str, strlen(str));
31
pipewire-0.3.51.tar.gz/src/modules/module-filter-chain.c -> pipewire-0.3.52.tar.gz/src/modules/module-filter-chain.c Changed
201
 
1
@@ -288,11 +288,15 @@
2
  * - \ref PW_KEY_NODE_GROUP
3
  * - \ref PW_KEY_NODE_LINK_GROUP
4
  * - \ref PW_KEY_NODE_VIRTUAL
5
+ * - \ref PW_KEY_NODE_NAME: See notes below. If not specified, defaults to
6
+ *     'filter-chain-<pid>-<module-id>'.
7
  *
8
  * Stream only properties:
9
  *
10
  * - \ref PW_KEY_MEDIA_CLASS
11
- * - \ref PW_KEY_NODE_NAME
12
+ * - \ref PW_KEY_NODE_NAME:  if not given per stream, the global node.name will be
13
+ *         prefixed with 'input.' and 'output.' to generate a capture and playback
14
+ *         stream node.name respectively.
15
  *
16
  * ## Example configuration of a virtual source
17
  *
18
@@ -333,7 +337,7 @@
19
  *
20
  * ## Example configuration of a Dolby Surround encoder virtual Sink
21
  *
22
- * This example uses the ladpsa surrounf encoder to encode a 5.1 signal
23
+ * This example uses the ladpsa surround encoder to encode a 5.1 signal
24
  * to a stereo Dolby Surround signal.
25
  *
26
  *\code{.unparsed}
27
@@ -585,7 +589,7 @@
28
    struct impl *impl = d;
29
    struct pw_buffer *in, *out;
30
    struct graph *graph = &impl->graph;
31
-   uint32_t i, size = 0, n_hndl = graph->n_hndl;
32
+   uint32_t i, outsize = 0, n_hndl = graph->n_hndl;
33
    int32_t stride = 0;
34
 
35
    if ((in = pw_stream_dequeue_buffer(impl->capture)) == NULL)
36
@@ -600,10 +604,16 @@
37
    for (i = 0; i < in->buffer->n_datas; i++) {
38
        struct spa_data *ds = &in->buffer->datasi;
39
        struct graph_port *port = &graph->inputi;
40
+       uint32_t offs, size;
41
+
42
+       offs = SPA_MIN(ds->chunk->offset, ds->maxsize);
43
+       size = SPA_MIN(ds->chunk->size, ds->maxsize - offs);
44
+
45
        if (port->desc)
46
            port->desc->connect_port(port->hndl, port->port,
47
-               SPA_MEMBER(ds->data, ds->chunk->offset, void));
48
-       size = SPA_MAX(size, ds->chunk->size);
49
+               SPA_PTROFF(ds->data, offs, void));
50
+
51
+       outsize = SPA_MAX(outsize, size);
52
        stride = SPA_MAX(stride, ds->chunk->stride);
53
    }
54
    for (i = 0; i < out->buffer->n_datas; i++) {
55
@@ -612,14 +622,14 @@
56
        if (port->desc)
57
            port->desc->connect_port(port->hndl, port->port, dd->data);
58
        else
59
-           memset(dd->data, 0, size);
60
+           memset(dd->data, 0, outsize);
61
        dd->chunk->offset = 0;
62
-       dd->chunk->size = size;
63
+       dd->chunk->size = outsize;
64
        dd->chunk->stride = stride;
65
    }
66
    for (i = 0; i < n_hndl; i++) {
67
        struct graph_hndl *hndl = &graph->hndli;
68
-       hndl->desc->run(hndl->hndl, size / sizeof(float));
69
+       hndl->desc->run(hndl->hndl, outsize / sizeof(float));
70
    }
71
 
72
 done:
73
@@ -1298,8 +1308,10 @@
74
    if (spa_json_is_container(val, len))
75
        len = spa_json_container_len(config, val, len);
76
 
77
-   if ((node->config = malloc(len+1)) != NULL)
78
-       spa_json_parse_stringn(val, len, node->config, len+1);
79
+   if ((node->config = malloc(len+1)) == NULL)
80
+       return -errno;
81
+
82
+   spa_json_parse_stringn(val, len, node->config, len+1);
83
 
84
    return 0;
85
 }
86
@@ -1316,9 +1328,16 @@
87
 
88
    while (spa_json_get_string(control, key, sizeof(key)) > 0) {
89
        float fl;
90
-       if (spa_json_get_float(control, &fl) <= 0)
91
+       const char *val;
92
+       int len;
93
+
94
+       if ((len = spa_json_next(control, &val)) < 0)
95
            break;
96
-       set_control_value(node, key, &fl);
97
+
98
+       if (spa_json_parse_float(val, len, &fl) <= 0)
99
+           pw_log_warn("control '%s' expects a number, ignoring", key);
100
+       else
101
+           set_control_value(node, key, &fl);
102
    }
103
    return 0;
104
 }
105
@@ -1338,6 +1357,11 @@
106
    struct port *in_port, *out_port;
107
    struct link *link;
108
 
109
+   if (spa_list_is_empty(&graph->node_list)) {
110
+       pw_log_error("can't make links in graph without nodes");
111
+       return -EINVAL;
112
+   }
113
+
114
    while (spa_json_get_string(json, key, sizeof(key)) > 0) {
115
        if (spa_streq(key, "output")) {
116
            if (spa_json_get_string(json, output, sizeof(output)) <= 0) {
117
@@ -1430,6 +1454,7 @@
118
    bool have_control = false;
119
    bool have_config = false;
120
    uint32_t i;
121
+   int res;
122
 
123
    while (spa_json_get_string(json, key, sizeof(key)) > 0) {
124
        if (spa_streq("type", key)) {
125
@@ -1524,7 +1549,8 @@
126
        spa_list_init(&port->link_list);
127
    }
128
    if (have_config)
129
-       parse_config(node, &config);
130
+       if ((res = parse_config(node, &config)) < 0)
131
+           pw_log_warn("error parsing config: %s", spa_strerror(res));
132
    if (have_control)
133
        parse_control(node, &control);
134
 
135
@@ -1661,7 +1687,7 @@
136
        impl->playback_info.channels = n_output;
137
 
138
    /* compare to the requested number of channels and duplicate the
139
-    * graph m_hndl times when needed. */
140
+    * graph n_hndl times when needed. */
141
    n_hndl = impl->capture_info.channels / n_input;
142
    if (n_hndl != impl->playback_info.channels / n_output) {
143
        pw_log_error("invalid channels");
144
@@ -1888,8 +1914,9 @@
145
  */
146
 static int load_graph(struct graph *graph, struct pw_properties *props)
147
 {
148
-   struct spa_json it4;
149
+   struct spa_json it3;
150
    struct spa_json inputs, outputs, *pinputs = NULL, *poutputs = NULL;
151
+   struct spa_json nodes, *pnodes = NULL, links, *plinks = NULL;
152
    const char *json, *val;
153
    char key256;
154
    int res;
155
@@ -1910,36 +1937,49 @@
156
 
157
    while (spa_json_get_string(&it1, key, sizeof(key)) > 0) {
158
        if (spa_streq("nodes", key)) {
159
-           if (spa_json_enter_array(&it1, &it2) <= 0) {
160
-               pw_log_error("nodes expect an array");
161
+           if (spa_json_enter_array(&it1, &nodes) <= 0) {
162
+               pw_log_error("nodes expects an array");
163
                return -EINVAL;
164
            }
165
-           while (spa_json_enter_object(&it2, &it3) > 0) {
166
-               if ((res = load_node(graph, &it3)) < 0)
167
-                   return res;
168
-           }
169
+           pnodes = &nodes;
170
        }
171
        else if (spa_streq("links", key)) {
172
-           if (spa_json_enter_array(&it1, &it2) <= 0)
173
+           if (spa_json_enter_array(&it1, &links) <= 0) {
174
+               pw_log_error("links expects an array");
175
                return -EINVAL;
176
-
177
-           while (spa_json_enter_object(&it2, &it3) > 0) {
178
-               if ((res = parse_link(graph, &it3)) < 0)
179
-                   return res;
180
            }
181
+           plinks = &links;
182
        }
183
        else if (spa_streq("inputs", key)) {
184
-           if (spa_json_enter_array(&it1, &inputs) <= 0)
185
+           if (spa_json_enter_array(&it1, &inputs) <= 0) {
186
+               pw_log_error("inputs expects an array");
187
                return -EINVAL;
188
+           }
189
            pinputs = &inputs;
190
        }
191
        else if (spa_streq("outputs", key)) {
192
-           if (spa_json_enter_array(&it1, &outputs) <= 0)
193
+           if (spa_json_enter_array(&it1, &outputs) <= 0) {
194
+               pw_log_error("outputs expects an array");
195
                return -EINVAL;
196
+           }
197
            poutputs = &outputs;
198
        } else if (spa_json_next(&it1, &val) < 0)
199
            break;
200
    }
201
pipewire-0.3.51.tar.gz/src/modules/module-filter-chain/builtin_plugin.c -> pipewire-0.3.52.tar.gz/src/modules/module-filter-chain/builtin_plugin.c Changed
10
 
1
@@ -485,7 +485,7 @@
2
    spa_zero(info);
3
    f = sf_open(filename, SFM_READ, &info) ;
4
    if (f == NULL) {
5
-       fprintf(stderr, "can't open %s", filename);
6
+       pw_log_error("can't open %s", filename);
7
        return NULL;
8
    }
9
 
10
pipewire-0.3.51.tar.gz/src/modules/module-link-factory.c -> pipewire-0.3.52.tar.gz/src/modules/module-link-factory.c Changed
93
 
1
@@ -56,14 +56,16 @@
2
 };
3
 
4
 struct factory_data {
5
-   struct pw_impl_module *module;
6
    struct pw_context *context;
7
-   struct pw_impl_factory *this;
8
-
9
-   struct spa_list link_list;
10
 
11
+   struct pw_impl_module *module;
12
    struct spa_hook module_listener;
13
 
14
+   struct pw_impl_factory *factory;
15
+   struct spa_hook factory_listener;
16
+
17
+   struct spa_list link_list;
18
+
19
    struct pw_work_queue *work;
20
 };
21
 
22
@@ -407,7 +409,7 @@
23
    linger = pw_properties_get_bool(properties, PW_KEY_OBJECT_LINGER, false);
24
 
25
    pw_properties_setf(properties, PW_KEY_FACTORY_ID, "%d",
26
-           pw_impl_factory_get_info(d->this)->id);
27
+           pw_impl_factory_get_info(d->factory)->id);
28
 
29
    client = resource ? pw_resource_get_client(resource) : NULL;
30
    if (client && !linger)
31
@@ -467,24 +469,40 @@
32
    .create_object = create_object,
33
 };
34
 
35
-static void module_destroy(void *data)
36
+static void factory_destroy(void *data)
37
 {
38
    struct factory_data *d = data;
39
    struct link_data *ld, *t;
40
 
41
-   spa_hook_remove(&d->module_listener);
42
+   spa_hook_remove(&d->factory_listener);
43
 
44
    spa_list_for_each_safe(ld, t, &d->link_list, l)
45
        pw_impl_link_destroy(ld->link);
46
 
47
-   pw_impl_factory_destroy(d->this);
48
+   d->factory = NULL;
49
+   if (d->module)
50
+       pw_impl_module_destroy(d->module);
51
+}
52
+
53
+static const struct pw_impl_factory_events factory_events = {
54
+   PW_VERSION_IMPL_FACTORY_EVENTS,
55
+   .destroy = factory_destroy,
56
+};
57
+
58
+static void module_destroy(void *data)
59
+{
60
+   struct factory_data *d = data;
61
+   spa_hook_remove(&d->module_listener);
62
+   d->module = NULL;
63
+   if (d->factory)
64
+       pw_impl_factory_destroy(d->factory);
65
 }
66
 
67
 static void module_registered(void *data)
68
 {
69
    struct factory_data *d = data;
70
    struct pw_impl_module *module = d->module;
71
-   struct pw_impl_factory *factory = d->this;
72
+   struct pw_impl_factory *factory = d->factory;
73
    struct spa_dict_item items1;
74
    char id16;
75
    int res;
76
@@ -525,7 +543,7 @@
77
        return -errno;
78
 
79
    data = pw_impl_factory_get_user_data(factory);
80
-   data->this = factory;
81
+   data->factory = factory;
82
    data->module = module;
83
    data->context = context;
84
    data->work = pw_context_get_work_queue(context);
85
@@ -540,6 +558,7 @@
86
 
87
    pw_impl_module_update_properties(module, &SPA_DICT_INIT_ARRAY(module_props));
88
 
89
+   pw_impl_factory_add_listener(factory, &data->factory_listener, &factory_events, data);
90
    pw_impl_module_add_listener(module, &data->module_listener, &module_events, data);
91
 
92
    return 0;
93
pipewire-0.3.51.tar.gz/src/modules/module-loopback.c -> pipewire-0.3.52.tar.gz/src/modules/module-loopback.c Changed
79
 
1
@@ -72,11 +72,15 @@
2
  * - \ref PW_KEY_NODE_GROUP
3
  * - \ref PW_KEY_NODE_LINK_GROUP
4
  * - \ref PW_KEY_NODE_VIRTUAL
5
+ * - \ref PW_KEY_NODE_NAME: See notes below. If not specified, defaults to
6
+ *     'loopback-<pid>-<module-id>'.
7
  *
8
  * Stream only properties:
9
  *
10
  * - \ref PW_KEY_MEDIA_CLASS
11
- * - \ref PW_KEY_NODE_NAME
12
+ * - \ref PW_KEY_NODE_NAME:  if not given per stream, the global node.name will be
13
+ *         prefixed with 'input.' and 'output.' to generate a capture and playback
14
+ *         stream node.name respectively.
15
  *
16
  * ## Example configuration of a virtual sink
17
  *
18
@@ -184,28 +188,32 @@
19
        pw_log_debug("out of playback buffers: %m");
20
 
21
    if (in != NULL && out != NULL) {
22
-       uint32_t size = 0;
23
-       int32_t stride = 0;
24
 
25
        for (i = 0; i < out->buffer->n_datas; i++) {
26
            struct spa_data *ds, *dd;
27
+           uint32_t outsize = 0;
28
+           int32_t stride = 0;
29
 
30
            dd = &out->buffer->datasi;
31
 
32
            if (i < in->buffer->n_datas) {
33
+               uint32_t offs, size;
34
+
35
                ds = &in->buffer->datasi;
36
 
37
+               offs = SPA_MIN(ds->chunk->offset, ds->maxsize);
38
+               size = SPA_MIN(ds->chunk->size, ds->maxsize - offs);
39
+               stride = SPA_MAX(stride, stride);
40
+
41
                memcpy(dd->data,
42
-                   SPA_PTROFF(ds->data, ds->chunk->offset, void),
43
-                   ds->chunk->size);
44
+                   SPA_PTROFF(ds->data, offs, void), size);
45
 
46
-               size = SPA_MAX(size, ds->chunk->size);
47
-               stride = SPA_MAX(stride, ds->chunk->stride);
48
+               outsize = SPA_MAX(outsize, size);
49
            } else {
50
-               memset(dd->data, 0, size);
51
+               memset(dd->data, 0, outsize);
52
            }
53
            dd->chunk->offset = 0;
54
-           dd->chunk->size = size;
55
+           dd->chunk->size = outsize;
56
            dd->chunk->stride = stride;
57
        }
58
    }
59
@@ -526,12 +534,17 @@
60
    copy_props(impl, props, PW_KEY_NODE_VIRTUAL);
61
    copy_props(impl, props, PW_KEY_MEDIA_NAME);
62
 
63
+   if ((str = pw_properties_get(props, PW_KEY_NODE_NAME)) == NULL) {
64
+       pw_properties_setf(props, PW_KEY_NODE_NAME,
65
+               "loopback-%u-%u", pid, id);
66
+       str = pw_properties_get(props, PW_KEY_NODE_NAME);
67
+   }
68
    if (pw_properties_get(impl->capture_props, PW_KEY_NODE_NAME) == NULL)
69
        pw_properties_setf(impl->capture_props, PW_KEY_NODE_NAME,
70
-               "input.loopback-%u-%u", pid, id);
71
+               "input.%s", str);
72
    if (pw_properties_get(impl->playback_props, PW_KEY_NODE_NAME) == NULL)
73
        pw_properties_setf(impl->playback_props, PW_KEY_NODE_NAME,
74
-               "output.loopback-%u-%u", pid, id);
75
+               "output.%s", str);
76
 
77
    parse_audio_info(impl->capture_props, &impl->capture_info);
78
    parse_audio_info(impl->playback_props, &impl->playback_info);
79
pipewire-0.3.51.tar.gz/src/modules/module-metadata.c -> pipewire-0.3.52.tar.gz/src/modules/module-metadata.c Changed
85
 
1
@@ -58,7 +58,8 @@
2
 int pw_protocol_native_ext_metadata_init(struct pw_context *context);
3
 
4
 struct factory_data {
5
-   struct pw_impl_factory *this;
6
+   struct pw_impl_factory *factory;
7
+   struct spa_hook factory_listener;
8
 
9
    struct pw_impl_module *module;
10
    struct spa_hook module_listener;
11
@@ -86,7 +87,7 @@
12
        return NULL;
13
 
14
    pw_properties_setf(properties, PW_KEY_FACTORY_ID, "%d",
15
-           pw_impl_factory_get_info(data->this)->id);
16
+           pw_impl_factory_get_info(data->factory)->id);
17
    pw_properties_setf(properties, PW_KEY_MODULE_ID, "%d",
18
            pw_impl_module_get_info(data->module)->id);
19
 
20
@@ -143,22 +144,35 @@
21
    .create_object = create_object,
22
 };
23
 
24
-static void module_destroy(void *data)
25
+static void factory_destroy(void *data)
26
 {
27
    struct factory_data *d = data;
28
+   spa_hook_remove(&d->factory_listener);
29
+   d->factory = NULL;
30
+   if (d->module)
31
+       pw_impl_module_destroy(d->module);
32
+}
33
 
34
-   spa_hook_remove(&d->module_listener);
35
+static const struct pw_impl_factory_events factory_events = {
36
+   PW_VERSION_IMPL_FACTORY_EVENTS,
37
+   .destroy = factory_destroy,
38
+};
39
 
40
+static void module_destroy(void *data)
41
+{
42
+   struct factory_data *d = data;
43
+   spa_hook_remove(&d->module_listener);
44
    spa_list_remove(&d->export_metadata.link);
45
-
46
-   pw_impl_factory_destroy(d->this);
47
+   d->module = NULL;
48
+   if (d->factory)
49
+       pw_impl_factory_destroy(d->factory);
50
 }
51
 
52
 static void module_registered(void *data)
53
 {
54
    struct factory_data *d = data;
55
    struct pw_impl_module *module = d->module;
56
-   struct pw_impl_factory *factory = d->this;
57
+   struct pw_impl_factory *factory = d->factory;
58
    struct spa_dict_item items1;
59
    char id16;
60
    int res;
61
@@ -201,7 +215,7 @@
62
        return -errno;
63
 
64
    data = pw_impl_factory_get_user_data(factory);
65
-   data->this = factory;
66
+   data->factory = factory;
67
    data->module = module;
68
 
69
    pw_log_debug("module %p: new", module);
70
@@ -215,12 +229,13 @@
71
    if ((res = pw_context_register_export_type(context, &data->export_metadata)) < 0)
72
        goto error;
73
 
74
+   pw_impl_factory_add_listener(factory, &data->factory_listener, &factory_events, data);
75
    pw_impl_module_add_listener(module, &data->module_listener, &module_events, data);
76
 
77
    pw_impl_module_update_properties(module, &SPA_DICT_INIT_ARRAY(module_props));
78
 
79
    return 0;
80
 error:
81
-   pw_impl_factory_destroy(data->this);
82
+   pw_impl_factory_destroy(data->factory);
83
    return res;
84
 }
85
pipewire-0.3.52.tar.gz/src/modules/module-pipe-tunnel.c Added
201
 
1
@@ -0,0 +1,724 @@
2
+/* PipeWire
3
+ *
4
+ * Copyright © 2021 Sanchayan Maity <sanchayan@asymptotic.io>
5
+ * Copyright © 2022 Wim Taymans
6
+ *
7
+ * Permission is hereby granted, free of charge, to any person obtaining a
8
+ * copy of this software and associated documentation files (the "Software"),
9
+ * to deal in the Software without restriction, including without limitation
10
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11
+ * and/or sell copies of the Software, and to permit persons to whom the
12
+ * Software is furnished to do so, subject to the following conditions:
13
+ *
14
+ * The above copyright notice and this permission notice (including the next
15
+ * paragraph) shall be included in all copies or substantial portions of the
16
+ * Software.
17
+ *
18
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
21
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
23
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
24
+ * DEALINGS IN THE SOFTWARE.
25
+ */
26
+
27
+#include <string.h>
28
+#include <stdio.h>
29
+#include <errno.h>
30
+#include <sys/types.h>
31
+#include <sys/stat.h>
32
+#include <fcntl.h>
33
+#include <unistd.h>
34
+#include <stdlib.h>
35
+#include <signal.h>
36
+#include <limits.h>
37
+#include <math.h>
38
+
39
+#include "config.h"
40
+
41
+#include <spa/utils/result.h>
42
+#include <spa/utils/string.h>
43
+#include <spa/utils/json.h>
44
+#include <spa/utils/ringbuffer.h>
45
+#include <spa/utils/dll.h>
46
+#include <spa/debug/pod.h>
47
+#include <spa/pod/builder.h>
48
+#include <spa/param/audio/format-utils.h>
49
+#include <spa/param/latency-utils.h>
50
+#include <spa/param/audio/raw.h>
51
+
52
+#include <pipewire/impl.h>
53
+#include <pipewire/i18n.h>
54
+#include <pipewire/private.h>
55
+
56
+/** \page page_module_pipe_tunnel PipeWire Module: Unix Pipe Tunnel
57
+ *
58
+ * The pipe-tunnel module provides a source or sink that tunnels all audio to
59
+ * a unix pipe.
60
+ *
61
+ * ## Module Options
62
+ *
63
+ * - `tunnel.mode`: the desired tunnel to create. (Default `playback`)
64
+ * - `pipe.filename`: the filename of the pipe.
65
+ * - `stream.props`: Extra properties for the local stream.
66
+ *
67
+ * When `tunnel.mode` is `capture`, a capture stream on the default source is
68
+ * created. Samples read from the pipe will be the contents of the captured source.
69
+ *
70
+ * When `tunnel.mode` is `sink`, a sink node is created. Samples read from the
71
+ * pipe will be the samples played on the sink.
72
+ *
73
+ * When `tunnel.mode` is `playback`, a playback stream on the default sink is
74
+ * created. Samples written to the pipe will be played on the sink.
75
+ *
76
+ * When `tunnel.mode` is `source`, a source node is created. Samples written to
77
+ * the pipe will be made available to streams connected to the source.
78
+ *
79
+ * When `pipe.filename` is not given, a default fifo in `/tmp/fifo_input` or
80
+ * `/tmp/fifo_output` will be created that can be written and read respectively,
81
+ * depending on the selected `tunnel.mode`.
82
+ *
83
+ * ## General options
84
+ *
85
+ * Options with well-known behavior.
86
+ *
87
+ * - \ref PW_KEY_REMOTE_NAME
88
+ * - \ref PW_KEY_AUDIO_RATE
89
+ * - \ref PW_KEY_AUDIO_CHANNELS
90
+ * - \ref SPA_KEY_AUDIO_POSITION
91
+ * - \ref PW_KEY_NODE_LATENCY
92
+ * - \ref PW_KEY_NODE_NAME
93
+ * - \ref PW_KEY_NODE_DESCRIPTION
94
+ * - \ref PW_KEY_NODE_GROUP
95
+ * - \ref PW_KEY_NODE_VIRTUAL
96
+ * - \ref PW_KEY_MEDIA_CLASS
97
+ * - \ref PW_KEY_NODE_TARGET to specify the remote name or id to link to
98
+ *
99
+ * When not otherwise specified, the pipe will accept or produce a
100
+ * 16 bits, stereo, 48KHz sample stream.
101
+ *
102
+ * ## Example configuration of a pipe playback stream
103
+ *
104
+ *\code{.unparsed}
105
+ * context.modules = 
106
+ * {   name = libpipewire-module-pipe-tunnel
107
+ *     args = {
108
+ *         tunnel.mode = playback
109
+ *         # Set the pipe name to tunnel to
110
+ *         pipe.filename = "/tmp/fifo_output"
111
+ *         #audio.rate=<sample rate>
112
+ *         #audio.channels=<number of channels>
113
+ *         #audio.position=<channel map>
114
+ *         #node.target=<remote target node>
115
+ *         stream.props = {
116
+ *             # extra sink properties
117
+ *         }
118
+ *     }
119
+ * }
120
+ * 
121
+ *\endcode
122
+ */
123
+
124
+#define NAME "pipe-tunnel"
125
+
126
+#define DEFAULT_CAPTURE_FILENAME   "/tmp/fifo_input"
127
+#define DEFAULT_PLAYBACK_FILENAME  "/tmp/fifo_output"
128
+
129
+PW_LOG_TOPIC_STATIC(mod_topic, "mod." NAME);
130
+#define PW_LOG_TOPIC_DEFAULT mod_topic
131
+
132
+#define MODULE_USAGE   " remote.name=<remote>  "               \
133
+           " node.latency=<latency as fraction>  "     \
134
+           " node.name=<name of the nodes>  "          \
135
+           " node.description=<description of the nodes>  "    \
136
+           " node.target=<remote node target name>  "      \
137
+           " audio.rate=<sample rate>  "               \
138
+           " audio.channels=<number of channels>  "        \
139
+           " audio.position=<channel map>  "           \
140
+           " tunnel.mode=capture|playback|sink|source "        \
141
+           " pipe.filename=<filename> "                \
142
+           " stream.props=<properties>  "
143
+
144
+
145
+static const struct spa_dict_item module_props = {
146
+   { PW_KEY_MODULE_AUTHOR, "Wim Taymans <wim.taymans@gmail.com>" },
147
+   { PW_KEY_MODULE_DESCRIPTION, "Create a UNIX pipe tunnel" },
148
+   { PW_KEY_MODULE_USAGE, MODULE_USAGE },
149
+   { PW_KEY_MODULE_VERSION, PACKAGE_VERSION },
150
+};
151
+
152
+struct impl {
153
+   struct pw_context *context;
154
+
155
+#define MODE_PLAYBACK  0
156
+#define MODE_CAPTURE   1
157
+#define MODE_SINK  2
158
+#define MODE_SOURCE    3
159
+   uint32_t mode;
160
+   struct pw_properties *props;
161
+
162
+   struct pw_impl_module *module;
163
+
164
+   struct spa_hook module_listener;
165
+
166
+   struct pw_core *core;
167
+   struct spa_hook core_proxy_listener;
168
+   struct spa_hook core_listener;
169
+
170
+   char *filename;
171
+   unsigned int unlink_fifo;
172
+   int fd;
173
+
174
+   struct pw_properties *stream_props;
175
+   enum pw_direction direction;
176
+   struct pw_stream *stream;
177
+   struct spa_hook stream_listener;
178
+   struct spa_audio_info_raw info;
179
+   uint32_t frame_size;
180
+
181
+   unsigned int do_disconnect:1;
182
+   uint32_t leftover_count;
183
+   uint8_t *leftover;
184
+};
185
+
186
+static void stream_destroy(void *d)
187
+{
188
+   struct impl *impl = d;
189
+   spa_hook_remove(&impl->stream_listener);
190
+   impl->stream = NULL;
191
+}
192
+
193
+static void stream_state_changed(void *d, enum pw_stream_state old,
194
+       enum pw_stream_state state, const char *error)
195
+{
196
+   struct impl *impl = d;
197
+   switch (state) {
198
+   case PW_STREAM_STATE_ERROR:
199
+   case PW_STREAM_STATE_UNCONNECTED:
200
+       pw_impl_module_schedule_destroy(impl->module);
201
pipewire-0.3.51.tar.gz/src/modules/module-profiler.c -> pipewire-0.3.52.tar.gz/src/modules/module-profiler.c Changed
10
 
1
@@ -246,6 +246,8 @@
2
            latency.num = n->force_quantum;
3
        if (n->force_rate != 0)
4
            latency.denom = n->force_rate;
5
+       else if (n->rate.denom != 0)
6
+           latency.denom = n->rate.denom;
7
 
8
        na = n->rt.activation;
9
        spa_pod_builder_prop(&b, SPA_PROFILER_followerBlock, 0);
10
pipewire-0.3.51.tar.gz/src/modules/module-protocol-native.c -> pipewire-0.3.52.tar.gz/src/modules/module-protocol-native.c Changed
105
 
1
@@ -347,9 +347,12 @@
2
            continue;
3
        }
4
 
5
+       resource->refcount++;
6
        pw_protocol_native_connection_enter(conn);
7
        res = demarshalmsg->opcode.func(resource, msg);
8
        pw_protocol_native_connection_leave(conn);
9
+       pw_resource_unref(resource);
10
+
11
        if (res < 0) {
12
            pw_resource_errorf_id(resource, msg->id,
13
                    res, "invalid message id:%u op:%u (%s)",
14
@@ -360,6 +363,7 @@
15
    res = 0;
16
 done:
17
    context->current_client = NULL;
18
+
19
    return res;
20
 
21
 error:
22
@@ -387,14 +391,15 @@
23
        pw_loop_signal_event(s->loop, s->resume);
24
 }
25
 
26
-static void handle_client_error(struct pw_impl_client *client, int res)
27
+static void handle_client_error(struct pw_impl_client *client, int res, const char *msg)
28
 {
29
    if (res == -EPIPE || res == -ECONNRESET)
30
-       pw_log_info("%p: client %p disconnected", client->protocol, client);
31
+       pw_log_info("%p: %s: client %p disconnected", client->protocol, msg, client);
32
    else
33
-       pw_log_error("%p: client %p error %d (%s)", client->protocol,
34
+       pw_log_error("%p: %s: client %p error %d (%s)", client->protocol, msg,
35
                client, res, spa_strerror(res));
36
-   pw_impl_client_destroy(client);
37
+   if (!client->destroyed)
38
+       pw_impl_client_destroy(client);
39
 }
40
 
41
 static void
42
@@ -404,6 +409,8 @@
43
    struct pw_impl_client *client = this->client;
44
    int res;
45
 
46
+   client->refcount++;
47
+
48
    if (mask & SPA_IO_HUP) {
49
        res = -EPIPE;
50
        goto error;
51
@@ -425,9 +432,19 @@
52
        } else if (res != -EAGAIN)
53
            goto error;
54
    }
55
+done:
56
+   pw_impl_client_unref(client);
57
    return;
58
 error:
59
-   handle_client_error(client, res);
60
+   handle_client_error(client, res, "connection_data");
61
+   goto done;
62
+}
63
+
64
+static void client_destroy(void *data)
65
+{
66
+   struct client_data *this = data;
67
+   pw_log_debug("%p: destroy", this);
68
+   spa_list_remove(&this->protocol_link);
69
 }
70
 
71
 static void client_free(void *data)
72
@@ -436,8 +453,6 @@
73
    struct pw_impl_client *client = this->client;
74
 
75
    pw_log_debug("%p: free", this);
76
-   spa_list_remove(&this->protocol_link);
77
-
78
    spa_hook_remove(&this->client_listener);
79
 
80
    if (this->source)
81
@@ -450,6 +465,7 @@
82
 
83
 static const struct pw_impl_client_events client_events = {
84
    PW_VERSION_IMPL_CLIENT_EVENTS,
85
+   .destroy = client_destroy,
86
    .free = client_free,
87
    .busy_changed = client_busy_changed,
88
 };
89
@@ -1215,12 +1231,12 @@
90
    pw_log_debug("flush");
91
 
92
    spa_list_for_each_safe(data, tmp, &this->client_list, protocol_link) {
93
+       data->client->refcount++;
94
        if ((res = process_messages(data)) < 0)
95
-           goto error;
96
+           handle_client_error(data->client, res, "do_resume");
97
+       pw_impl_client_unref(data->client);
98
    }
99
    return;
100
-error:
101
-   handle_client_error(data->client, res);
102
 }
103
 
104
 static const char *
105
pipewire-0.3.51.tar.gz/src/modules/module-protocol-pulse/collect.c -> pipewire-0.3.52.tar.gz/src/modules/module-protocol-pulse/collect.c Changed
60
 
1
@@ -112,29 +112,41 @@
2
    return false;
3
 }
4
 
5
+struct pw_manager_object *find_peer_for_link(struct pw_manager *m,
6
+       struct pw_manager_object *o, uint32_t id, enum pw_direction direction)
7
+{
8
+   struct pw_manager_object *p;
9
+   uint32_t in_node, out_node;
10
+
11
+   if (o->props == NULL)
12
+       return NULL;
13
+
14
+   if (pw_properties_fetch_uint32(o->props, PW_KEY_LINK_OUTPUT_NODE, &out_node) != 0 ||
15
+       pw_properties_fetch_uint32(o->props, PW_KEY_LINK_INPUT_NODE, &in_node) != 0)
16
+       return NULL;
17
+
18
+   if (direction == PW_DIRECTION_OUTPUT && id == out_node) {
19
+       struct selector sel = { .id = in_node, .type = pw_manager_object_is_sink, };
20
+       if ((p = select_object(m, &sel)) != NULL)
21
+           return p;
22
+   }
23
+   if (direction == PW_DIRECTION_INPUT && id == in_node) {
24
+       struct selector sel = { .id = out_node, .type = pw_manager_object_is_recordable, };
25
+       if ((p = select_object(m, &sel)) != NULL)
26
+           return p;
27
+   }
28
+   return NULL;
29
+}
30
+
31
 struct pw_manager_object *find_linked(struct pw_manager *m, uint32_t id, enum pw_direction direction)
32
 {
33
    struct pw_manager_object *o, *p;
34
-   uint32_t in_node, out_node;
35
 
36
    spa_list_for_each(o, &m->object_list, link) {
37
-       if (o->props == NULL || !pw_manager_object_is_link(o))
38
+       if (!pw_manager_object_is_link(o))
39
            continue;
40
-
41
-       if (pw_properties_fetch_uint32(o->props, PW_KEY_LINK_OUTPUT_NODE, &out_node) != 0 ||
42
-                    pw_properties_fetch_uint32(o->props, PW_KEY_LINK_INPUT_NODE, &in_node) != 0)
43
-                        continue;
44
-
45
-       if (direction == PW_DIRECTION_OUTPUT && id == out_node) {
46
-           struct selector sel = { .id = in_node, .type = pw_manager_object_is_sink, };
47
-           if ((p = select_object(m, &sel)) != NULL)
48
-               return p;
49
-       }
50
-       if (direction == PW_DIRECTION_INPUT && id == in_node) {
51
-           struct selector sel = { .id = out_node, .type = pw_manager_object_is_recordable, };
52
-           if ((p = select_object(m, &sel)) != NULL)
53
-               return p;
54
-       }
55
+       if ((p = find_peer_for_link(m, o, id, direction)) != NULL)
56
+           return p;
57
    }
58
    return NULL;
59
 }
60
pipewire-0.3.51.tar.gz/src/modules/module-protocol-pulse/collect.h -> pipewire-0.3.52.tar.gz/src/modules/module-protocol-pulse/collect.h Changed
10
 
1
@@ -159,6 +159,8 @@
2
 struct spa_dict *collect_props(struct spa_pod *info, struct spa_dict *dict);
3
 uint32_t find_profile_index(struct pw_manager_object *card, const char *name);
4
 uint32_t find_port_index(struct pw_manager_object *card, uint32_t direction, const char *port_name);
5
+struct pw_manager_object *find_peer_for_link(struct pw_manager *m,
6
+       struct pw_manager_object *o, uint32_t id, enum pw_direction direction);
7
 struct pw_manager_object *find_linked(struct pw_manager *m, uint32_t id, enum pw_direction direction);
8
 bool collect_is_linked(struct pw_manager *m, uint32_t id, enum pw_direction direction);
9
 
10
pipewire-0.3.51.tar.gz/src/modules/module-protocol-pulse/format.c -> pipewire-0.3.52.tar.gz/src/modules/module-protocol-pulse/format.c Changed
26
 
1
@@ -480,9 +480,23 @@
2
 
3
        info.info.raw.format = SPA_AUDIO_FORMAT_S16;
4
        info.info.raw.rate = iec.rate;
5
-       info.info.raw.channels = 2;
6
        info.info.raw.position0 = SPA_AUDIO_CHANNEL_FL;
7
        info.info.raw.position1 = SPA_AUDIO_CHANNEL_FR;
8
+       switch (iec.codec) {
9
+       case SPA_AUDIO_IEC958_CODEC_TRUEHD:
10
+       case SPA_AUDIO_IEC958_CODEC_DTSHD:
11
+           info.info.raw.channels = 8;
12
+           info.info.raw.position2 = SPA_AUDIO_CHANNEL_FC;
13
+           info.info.raw.position3 = SPA_AUDIO_CHANNEL_LFE;
14
+           info.info.raw.position4 = SPA_AUDIO_CHANNEL_SL;
15
+           info.info.raw.position5 = SPA_AUDIO_CHANNEL_SR;
16
+           info.info.raw.position6 = SPA_AUDIO_CHANNEL_RL;
17
+           info.info.raw.position7 = SPA_AUDIO_CHANNEL_RR;
18
+           break;
19
+       default:
20
+           info.info.raw.channels = 2;
21
+           break;
22
+       }
23
        break;
24
    }
25
    default:
26
pipewire-0.3.51.tar.gz/src/modules/module-protocol-pulse/manager.c -> pipewire-0.3.52.tar.gz/src/modules/module-protocol-pulse/manager.c Changed
143
 
1
@@ -41,12 +41,15 @@
2
 #define manager_emit_removed(m,o) spa_hook_list_call(&m->hooks, struct pw_manager_events, removed, 0, o)
3
 #define manager_emit_metadata(m,o,s,k,t,v) spa_hook_list_call(&m->hooks, struct pw_manager_events, metadata,0,o,s,k,t,v)
4
 #define manager_emit_disconnect(m) spa_hook_list_call(&m->hooks, struct pw_manager_events, disconnect, 0)
5
+#define manager_emit_object_data_timeout(m,o,k) spa_hook_list_call(&m->hooks, struct pw_manager_events, object_data_timeout,0,o,k)
6
 
7
 struct object;
8
 
9
 struct manager {
10
    struct pw_manager this;
11
 
12
+   struct pw_loop *loop;
13
+
14
    struct spa_hook core_listener;
15
    struct spa_hook registry_listener;
16
    int sync_seq;
17
@@ -64,8 +67,10 @@
18
 
19
 struct object_data {
20
    struct spa_list link;
21
+   struct object *object;
22
    const char *key;
23
    size_t size;
24
+   struct spa_source *timer;
25
 };
26
 
27
 struct object {
28
@@ -188,6 +193,16 @@
29
    }
30
 }
31
 
32
+static void object_data_free(struct object_data *d)
33
+{
34
+   spa_list_remove(&d->link);
35
+   if (d->timer) {
36
+       pw_loop_destroy_source(d->object->manager->loop, d->timer);
37
+       d->timer = NULL;
38
+   }
39
+   free(d);
40
+}
41
+
42
 static void object_destroy(struct object *o)
43
 {
44
    struct manager *m = o->manager;
45
@@ -201,10 +216,8 @@
46
        free(o->this.message_object_path);
47
    clear_params(&o->this.param_list, SPA_ID_INVALID);
48
    clear_params(&o->pending_list, SPA_ID_INVALID);
49
-   spa_list_consume(d, &o->data_list, link) {
50
-       spa_list_remove(&d->link);
51
-       free(d);
52
-   }
53
+   spa_list_consume(d, &o->data_list, link)
54
+       object_data_free(d);
55
    free(o);
56
 }
57
 
58
@@ -716,6 +729,7 @@
59
 struct pw_manager *pw_manager_new(struct pw_core *core)
60
 {
61
    struct manager *m;
62
+   struct pw_context *context;
63
 
64
    m = calloc(1, sizeof(*m));
65
    if (m == NULL)
66
@@ -729,6 +743,9 @@
67
        return NULL;
68
    }
69
 
70
+   context = pw_core_get_context(core);
71
+   m->loop = pw_context_get_main_loop(context);
72
+
73
    spa_hook_list_init(&m->hooks);
74
 
75
    spa_list_init(&m->this.object_list);
76
@@ -847,11 +864,14 @@
77
    if (d != NULL) {
78
        if (d->size == size)
79
            goto done;
80
-       spa_list_remove(&d->link);
81
-       free(d);
82
+       object_data_free(d);
83
    }
84
 
85
    d = calloc(1, sizeof(struct object_data) + size);
86
+   if (d == NULL)
87
+       return NULL;
88
+
89
+   d->object = o;
90
    d->key = key;
91
    d->size = size;
92
 
93
@@ -861,6 +881,49 @@
94
    return SPA_PTROFF(d, sizeof(struct object_data), void);
95
 }
96
 
97
+static void object_data_timeout(void *data, uint64_t count)
98
+{
99
+   struct object_data *d = data;
100
+   struct object *o = d->object;
101
+   struct manager *m = o->manager;
102
+
103
+   pw_log_debug("manager:%p object id:%d data '%s' lifetime ends",
104
+           m, o->this.id, d->key);
105
+
106
+   if (d->timer) {
107
+       pw_loop_destroy_source(m->loop, d->timer);
108
+       d->timer = NULL;
109
+   }
110
+
111
+   manager_emit_object_data_timeout(m, &o->this, d->key);
112
+}
113
+
114
+void *pw_manager_object_add_temporary_data(struct pw_manager_object *obj, const char *key,
115
+       size_t size, uint64_t lifetime_nsec)
116
+{
117
+   struct object *o = SPA_CONTAINER_OF(obj, struct object, this);
118
+   struct object_data *d;
119
+   void *data;
120
+   struct timespec timeout = {0}, interval = {0};
121
+
122
+   data = pw_manager_object_add_data(obj, key, size);
123
+   if (data == NULL)
124
+       return NULL;
125
+
126
+   d = SPA_PTROFF(data, -sizeof(struct object_data), void);
127
+
128
+   if (d->timer == NULL)
129
+       d->timer = pw_loop_add_timer(o->manager->loop, object_data_timeout, d);
130
+   if (d->timer == NULL)
131
+       return NULL;
132
+
133
+   timeout.tv_sec = lifetime_nsec / SPA_NSEC_PER_SEC;
134
+   timeout.tv_nsec = lifetime_nsec % SPA_NSEC_PER_SEC;
135
+   pw_loop_update_timer(o->manager->loop, d->timer, &timeout, &interval, false);
136
+
137
+   return data;
138
+}
139
+
140
 void *pw_manager_object_get_data(struct pw_manager_object *obj, const char *id)
141
 {
142
    struct object *o = SPA_CONTAINER_OF(obj, struct object, this);
143
pipewire-0.3.51.tar.gz/src/modules/module-protocol-pulse/manager.h -> pipewire-0.3.52.tar.gz/src/modules/module-protocol-pulse/manager.h Changed
20
 
1
@@ -55,6 +55,9 @@
2
            const char *type, const char *value);
3
 
4
    void (*disconnect) (void *data);
5
+
6
+   void (*object_data_timeout) (void *data, struct pw_manager_object *object,
7
+           const char *key);
8
 };
9
 
10
 struct pw_manager {
11
@@ -115,6 +118,8 @@
12
 
13
 void *pw_manager_object_add_data(struct pw_manager_object *o, const char *key, size_t size);
14
 void *pw_manager_object_get_data(struct pw_manager_object *obj, const char *key);
15
+void *pw_manager_object_add_temporary_data(struct pw_manager_object *o, const char *key,
16
+       size_t size, uint64_t lifetime_nsec);
17
 
18
 bool pw_manager_object_is_client(struct pw_manager_object *o);
19
 bool pw_manager_object_is_module(struct pw_manager_object *o);
20
pipewire-0.3.51.tar.gz/src/modules/module-protocol-pulse/message.c -> pipewire-0.3.52.tar.gz/src/modules/module-protocol-pulse/message.c Changed
26
 
1
@@ -825,12 +825,12 @@
2
    if (!spa_list_is_empty(&impl->free_messages)) {
3
        msg = spa_list_first(&impl->free_messages, struct message, link);
4
        spa_list_remove(&msg->link);
5
-       pw_log_trace("using recycled message %p", msg);
6
+       pw_log_trace("using recycled message %p size:%d", msg, size);
7
    } else {
8
        if ((msg = calloc(1, sizeof(*msg))) == NULL)
9
            return NULL;
10
 
11
-       pw_log_trace("new message %p", msg);
12
+       pw_log_trace("new message %p size:%d", msg, size);
13
        msg->stat = &impl->stat;
14
        msg->stat->n_allocated++;
15
        msg->stat->n_accumulated++;
16
@@ -864,7 +864,8 @@
17
        free(msg->data);
18
        free(msg);
19
    } else {
20
-       pw_log_trace("recycle message %p size:%d", msg, msg->allocated);
21
+       pw_log_trace("recycle message %p size:%d/%d", msg, msg->length, msg->allocated);
22
        spa_list_append(&impl->free_messages, &msg->link);
23
+       msg->length = 0;
24
    }
25
 }
26
pipewire-0.3.51.tar.gz/src/modules/module-protocol-pulse/module.c -> pipewire-0.3.52.tar.gz/src/modules/module-protocol-pulse/module.c Changed
58
 
1
@@ -59,16 +59,17 @@
2
    module->unloading = true;
3
 }
4
 
5
-struct module *module_new(struct impl *impl, size_t user_data)
6
+static struct module *module_new(struct impl *impl, const struct module_info *info)
7
 {
8
    struct module *module;
9
 
10
-   module = calloc(1, sizeof(struct module) + user_data);
11
+   module = calloc(1, sizeof(*module) + info->data_size);
12
    if (module == NULL)
13
        return NULL;
14
 
15
    module->index = SPA_ID_INVALID;
16
    module->impl = impl;
17
+   module->info = info;
18
    spa_hook_list_init(&module->listener_list);
19
    module->user_data = SPA_PTROFF(module, sizeof(*module), void);
20
    module->loaded = false;
21
@@ -304,17 +305,34 @@
22
        }
23
    }
24
 
25
-   module = info->create(impl, args);
26
+   module = module_new(impl, info);
27
    if (module == NULL)
28
        return NULL;
29
 
30
-   module->info = info;
31
+   module->props = pw_properties_new(NULL, NULL);
32
+   if (module->props == NULL) {
33
+       module_free(module);
34
+       return NULL;
35
+   }
36
+
37
+   if (args)
38
+       module_args_add_props(module->props, args);
39
+
40
+   int res = module->info->prepare(module);
41
+   if (res < 0) {
42
+       module_free(module);
43
+       errno = -res;
44
+       return NULL;
45
+   }
46
+
47
    module->index = pw_map_insert_new(&impl->modules, module);
48
    if (module->index == SPA_ID_INVALID) {
49
        module_unload(module);
50
        return NULL;
51
    }
52
+
53
    module->args = args ? strdup(args) : NULL;
54
    module->index |= MODULE_FLAG;
55
+
56
    return module;
57
 }
58
pipewire-0.3.51.tar.gz/src/modules/module-protocol-pulse/module.h -> pipewire-0.3.52.tar.gz/src/modules/module-protocol-pulse/module.h Changed
23
 
1
@@ -40,9 +40,12 @@
2
 
3
    unsigned int load_once:1;
4
 
5
-   struct module *(*create) (struct impl *impl, const char *args);
6
+   int (*prepare) (struct module *module);
7
    int (*load) (struct client *client, struct module *module);
8
    int (*unload) (struct module *module);
9
+
10
+   const struct spa_dict *properties;
11
+   size_t data_size;
12
 };
13
 
14
 #define DEFINE_MODULE_INFO(name)                   \
15
@@ -77,7 +80,6 @@
16
 
17
 struct module *module_create(struct client *client, const char *name, const char *args);
18
 void module_free(struct module *module);
19
-struct module *module_new(struct impl *impl, size_t user_data);
20
 int module_load(struct client *client, struct module *module);
21
 int module_unload(struct module *module);
22
 void module_schedule_unload(struct module *module);
23
pipewire-0.3.51.tar.gz/src/modules/module-protocol-pulse/modules/module-always-sink.c -> pipewire-0.3.52.tar.gz/src/modules/module-protocol-pulse/modules/module-always-sink.c Changed
49
 
1
@@ -101,40 +101,22 @@
2
    { PW_KEY_MODULE_VERSION, PACKAGE_VERSION },
3
 };
4
 
5
-struct module *create_module_always_sink(struct impl *impl, const char *argument)
6
+static int module_always_sink_prepare(struct module * const module)
7
 {
8
-   struct module *module;
9
-   struct pw_properties *props = NULL;
10
-   int res;
11
-
12
    PW_LOG_TOPIC_INIT(mod_topic);
13
 
14
-   props = pw_properties_new_dict(&SPA_DICT_INIT_ARRAY(module_always_sink_info));
15
-   if (props == NULL) {
16
-       res = -EINVAL;
17
-       goto out;
18
-   }
19
-   if (argument)
20
-       module_args_add_props(props, argument);
21
-
22
-   module = module_new(impl, sizeof(struct module_always_sink_data));
23
-   if (module == NULL) {
24
-       res = -errno;
25
-       goto out;
26
-   }
27
-   module->props = props;
28
+   struct module_always_sink_data * const data = module->user_data;
29
+   data->module = module;
30
 
31
-   return module;
32
-out:
33
-   pw_properties_free(props);
34
-   errno = -res;
35
-   return NULL;
36
+   return 0;
37
 }
38
 
39
 DEFINE_MODULE_INFO(module_always_sink) = {
40
    .name = "module-always-sink",
41
    .load_once = true,
42
-   .create = create_module_always_sink,
43
+   .prepare = module_always_sink_prepare,
44
    .load = module_always_sink_load,
45
    .unload = module_always_sink_unload,
46
+   .properties = &SPA_DICT_INIT_ARRAY(module_always_sink_info),
47
+   .data_size = sizeof(struct module_always_sink_data),
48
 };
49
pipewire-0.3.51.tar.gz/src/modules/module-protocol-pulse/modules/module-combine-sink.c -> pipewire-0.3.52.tar.gz/src/modules/module-protocol-pulse/modules/module-combine-sink.c Changed
122
 
1
@@ -124,8 +124,7 @@
2
 
3
    for (i = 0; i < MAX_SINKS; i++) {
4
        struct pw_buffer *out;
5
-       uint32_t j, size = 0;
6
-       int32_t stride = 0;
7
+       uint32_t j;
8
 
9
        if (data->streamsi.stream == NULL || data->streamsi.cleanup)
10
            continue;
11
@@ -142,23 +141,29 @@
12
 
13
        for (j = 0; j < out->buffer->n_datas; j++) {
14
            struct spa_data *ds, *dd;
15
+           uint32_t outsize = 0;
16
+           int32_t stride = 0;
17
 
18
            dd = &out->buffer->datasj;
19
 
20
            if (j < in->buffer->n_datas) {
21
+               uint32_t offs, size;
22
+
23
                ds = &in->buffer->datasj;
24
 
25
+               offs = SPA_MIN(ds->chunk->offset, ds->maxsize);
26
+               size = SPA_MIN(ds->chunk->size, ds->maxsize - offs);
27
+
28
                memcpy(dd->data,
29
-                   SPA_PTROFF(ds->data, ds->chunk->offset, void),
30
-                   ds->chunk->size);
31
+                   SPA_PTROFF(ds->data, offs, void), size);
32
 
33
-               size = SPA_MAX(size, ds->chunk->size);
34
+               outsize = SPA_MAX(outsize, size);
35
                stride = SPA_MAX(stride, ds->chunk->stride);
36
            } else {
37
-               memset(dd->data, 0, size);
38
+               memset(dd->data, 0, outsize);
39
            }
40
            dd->chunk->offset = 0;
41
-           dd->chunk->size = size;
42
+           dd->chunk->size = outsize;
43
            dd->chunk->stride = stride;
44
        }
45
 
46
@@ -499,11 +504,10 @@
47
    return 0;
48
 }
49
 
50
-struct module *create_module_combine_sink(struct impl *impl, const char *argument)
51
+static int module_combine_sink_prepare(struct module * const module)
52
 {
53
-   struct module *module;
54
-   struct module_combine_sink_data *d;
55
-   struct pw_properties *props = NULL;
56
+   struct module_combine_sink_data * const d = module->user_data;
57
+   struct pw_properties * const props = module->props;
58
    const char *str;
59
    char *sink_name = NULL, **sink_names = NULL;
60
    struct spa_audio_info_raw info = { 0 };
61
@@ -512,14 +516,6 @@
62
 
63
    PW_LOG_TOPIC_INIT(mod_topic);
64
 
65
-   props = pw_properties_new_dict(&SPA_DICT_INIT_ARRAY(module_combine_sink_info));
66
-   if (!props) {
67
-       res = -EINVAL;
68
-       goto out;
69
-   }
70
-   if (argument)
71
-       module_args_add_props(props, argument);
72
-
73
    if ((str = pw_properties_get(props, "sink_name")) != NULL) {
74
        sink_name = strdup(str);
75
        pw_properties_set(props, "sink_name", NULL);
76
@@ -542,19 +538,11 @@
77
        pw_properties_set(props, "resample_method", NULL);
78
    }
79
 
80
-   if (module_args_to_audioinfo(impl, props, &info) < 0) {
81
+   if (module_args_to_audioinfo(module->impl, props, &info) < 0) {
82
        res = -EINVAL;
83
        goto out;
84
    }
85
 
86
-   module = module_new(impl, sizeof(*d));
87
-   if (module == NULL) {
88
-       res = -errno;
89
-       goto out;
90
-   }
91
-
92
-   module->props = props;
93
-   d = module->user_data;
94
    d->module = module;
95
    d->info = info;
96
    d->sink_name = sink_name;
97
@@ -565,18 +553,19 @@
98
        d->streamsi.cleanup = false;
99
    }
100
 
101
-   return module;
102
+   return 0;
103
 out:
104
-   pw_properties_free(props);
105
    free(sink_name);
106
    pw_free_strv(sink_names);
107
-   errno = -res;
108
-   return NULL;
109
+
110
+   return res;
111
 }
112
 
113
 DEFINE_MODULE_INFO(module_combine_sink) = {
114
    .name = "module-combine-sink",
115
-   .create = create_module_combine_sink,
116
+   .prepare = module_combine_sink_prepare,
117
    .load = module_combine_sink_load,
118
    .unload = module_combine_sink_unload,
119
+   .properties = &SPA_DICT_INIT_ARRAY(module_combine_sink_info),
120
+   .data_size = sizeof(struct module_combine_sink_data),
121
 };
122
pipewire-0.3.51.tar.gz/src/modules/module-protocol-pulse/modules/module-echo-cancel.c -> pipewire-0.3.52.tar.gz/src/modules/module-protocol-pulse/modules/module-echo-cancel.c Changed
83
 
1
@@ -155,27 +155,24 @@
2
    { PW_KEY_MODULE_VERSION, PACKAGE_VERSION },
3
 };
4
 
5
-struct module *create_module_echo_cancel(struct impl *impl, const char *argument)
6
+static int module_echo_cancel_prepare(struct module * const module)
7
 {
8
-   struct module *module;
9
-   struct module_echo_cancel_data *d;
10
-   struct pw_properties *props = NULL, *aec_props = NULL, *sink_props = NULL, *source_props = NULL;
11
+   struct module_echo_cancel_data * const d = module->user_data;
12
+   struct pw_properties * const props = module->props;
13
+   struct pw_properties *aec_props = NULL, *sink_props = NULL, *source_props = NULL;
14
    const char *str;
15
    struct spa_audio_info_raw info = { 0 };
16
    int res;
17
 
18
    PW_LOG_TOPIC_INIT(mod_topic);
19
 
20
-   props = pw_properties_new_dict(&SPA_DICT_INIT_ARRAY(module_echo_cancel_info));
21
    aec_props = pw_properties_new(NULL, NULL);
22
    source_props = pw_properties_new(NULL, NULL);
23
    sink_props = pw_properties_new(NULL, NULL);
24
-   if (!props ||!aec_props || !source_props || !sink_props) {
25
+   if (!aec_props || !source_props || !sink_props) {
26
        res = -EINVAL;
27
        goto out;
28
    }
29
-   if (argument)
30
-       module_args_add_props(props, argument);
31
 
32
    if ((str = pw_properties_get(props, "source_name")) != NULL) {
33
        pw_properties_set(source_props, PW_KEY_NODE_NAME, str);
34
@@ -208,7 +205,7 @@
35
        pw_properties_set(props, "sink_master", NULL);
36
    }
37
 
38
-   if (module_args_to_audioinfo(impl, props, &info) < 0) {
39
+   if (module_args_to_audioinfo(module->impl, props, &info) < 0) {
40
        res = -EINVAL;
41
        goto out;
42
    }
43
@@ -233,34 +230,26 @@
44
        pw_properties_set(props, "aec_args", NULL);
45
    }
46
 
47
-   module = module_new(impl, sizeof(*d));
48
-   if (module == NULL) {
49
-       res = -errno;
50
-       goto out;
51
-   }
52
-
53
-   module->props = props;
54
-   d = module->user_data;
55
    d->module = module;
56
    d->props = aec_props;
57
    d->source_props = source_props;
58
    d->sink_props = sink_props;
59
    d->info = info;
60
 
61
-   return module;
62
+   return 0;
63
 out:
64
-   pw_properties_free(props);
65
    pw_properties_free(aec_props);
66
    pw_properties_free(sink_props);
67
    pw_properties_free(source_props);
68
-   errno = -res;
69
 
70
-   return NULL;
71
+   return res;
72
 }
73
 
74
 DEFINE_MODULE_INFO(module_echo_cancel) = {
75
    .name = "module-echo-cancel",
76
-   .create = create_module_echo_cancel,
77
+   .prepare = module_echo_cancel_prepare,
78
    .load = module_echo_cancel_load,
79
    .unload = module_echo_cancel_unload,
80
+   .properties = &SPA_DICT_INIT_ARRAY(module_echo_cancel_info),
81
+   .data_size = sizeof(struct module_echo_cancel_data),
82
 };
83
pipewire-0.3.51.tar.gz/src/modules/module-protocol-pulse/modules/module-ladspa-sink.c -> pipewire-0.3.52.tar.gz/src/modules/module-protocol-pulse/modules/module-ladspa-sink.c Changed
80
 
1
@@ -177,11 +177,11 @@
2
    pw_properties_set(props, SPA_KEY_AUDIO_POSITION, s);
3
 }
4
 
5
-struct module *create_module_ladspa_sink(struct impl *impl, const char *argument)
6
+static int module_ladspa_sink_prepare(struct module * const module)
7
 {
8
-   struct module *module;
9
-   struct module_ladspa_sink_data *d;
10
-   struct pw_properties *props = NULL, *playback_props = NULL, *capture_props = NULL;
11
+   struct module_ladspa_sink_data * const d = module->user_data;
12
+   struct pw_properties * const props = module->props;
13
+   struct pw_properties *playback_props = NULL, *capture_props = NULL;
14
    const char *str;
15
    struct spa_audio_info_raw capture_info = { 0 };
16
    struct spa_audio_info_raw playback_info = { 0 };
17
@@ -189,15 +189,12 @@
18
 
19
    PW_LOG_TOPIC_INIT(mod_topic);
20
 
21
-   props = pw_properties_new_dict(&SPA_DICT_INIT_ARRAY(module_ladspa_sink_info));
22
    capture_props = pw_properties_new(NULL, NULL);
23
    playback_props = pw_properties_new(NULL, NULL);
24
-   if (!props || !capture_props || !playback_props) {
25
+   if (!capture_props || !playback_props) {
26
        res = -EINVAL;
27
        goto out;
28
    }
29
-   if (argument)
30
-       module_args_add_props(props, argument);
31
 
32
    if ((str = pw_properties_get(props, "sink_name")) != NULL) {
33
        pw_properties_set(capture_props, PW_KEY_NODE_NAME, str);
34
@@ -226,7 +223,7 @@
35
        pw_properties_set(props, "master", NULL);
36
    }
37
 
38
-   if (module_args_to_audioinfo(impl, props, &capture_info) < 0) {
39
+   if (module_args_to_audioinfo(module->impl, props, &capture_info) < 0) {
40
        res = -EINVAL;
41
        goto out;
42
    }
43
@@ -238,30 +235,23 @@
44
    if (pw_properties_get(playback_props, PW_KEY_NODE_PASSIVE) == NULL)
45
        pw_properties_set(playback_props, PW_KEY_NODE_PASSIVE, "true");
46
 
47
-   module = module_new(impl, sizeof(*d));
48
-   if (module == NULL) {
49
-       res = -errno;
50
-       goto out;
51
-   }
52
-
53
-   module->props = props;
54
-   d = module->user_data;
55
    d->module = module;
56
    d->capture_props = capture_props;
57
    d->playback_props = playback_props;
58
 
59
-   return module;
60
+   return 0;
61
 out:
62
-   pw_properties_free(props);
63
    pw_properties_free(playback_props);
64
    pw_properties_free(capture_props);
65
-   errno = -res;
66
-   return NULL;
67
+
68
+   return res;
69
 }
70
 
71
 DEFINE_MODULE_INFO(module_ladspa_sink) = {
72
    .name = "module-ladspa-sink",
73
-   .create = create_module_ladspa_sink,
74
+   .prepare = module_ladspa_sink_prepare,
75
    .load = module_ladspa_sink_load,
76
    .unload = module_ladspa_sink_unload,
77
+   .properties = &SPA_DICT_INIT_ARRAY(module_ladspa_sink_info),
78
+   .data_size = sizeof(struct module_ladspa_sink_data),
79
 };
80
pipewire-0.3.51.tar.gz/src/modules/module-protocol-pulse/modules/module-ladspa-source.c -> pipewire-0.3.52.tar.gz/src/modules/module-protocol-pulse/modules/module-ladspa-source.c Changed
80
 
1
@@ -177,11 +177,11 @@
2
    pw_properties_set(props, SPA_KEY_AUDIO_POSITION, s);
3
 }
4
 
5
-struct module *create_module_ladspa_source(struct impl *impl, const char *argument)
6
+static int module_ladspa_source_prepare(struct module * const module)
7
 {
8
-   struct module *module;
9
-   struct module_ladspa_source_data *d;
10
-   struct pw_properties *props = NULL, *playback_props = NULL, *capture_props = NULL;
11
+   struct module_ladspa_source_data * const d = module->user_data;
12
+   struct pw_properties * const props = module->props;
13
+   struct pw_properties *playback_props = NULL, *capture_props = NULL;
14
    const char *str;
15
    struct spa_audio_info_raw capture_info = { 0 };
16
    struct spa_audio_info_raw playback_info = { 0 };
17
@@ -189,15 +189,12 @@
18
 
19
    PW_LOG_TOPIC_INIT(mod_topic);
20
 
21
-   props = pw_properties_new_dict(&SPA_DICT_INIT_ARRAY(module_ladspa_source_info));
22
    capture_props = pw_properties_new(NULL, NULL);
23
    playback_props = pw_properties_new(NULL, NULL);
24
-   if (!props || !capture_props || !playback_props) {
25
+   if (!capture_props || !playback_props) {
26
        res = -EINVAL;
27
        goto out;
28
    }
29
-   if (argument)
30
-       module_args_add_props(props, argument);
31
 
32
    if ((str = pw_properties_get(props, "source_name")) != NULL) {
33
        pw_properties_set(playback_props, PW_KEY_NODE_NAME, str);
34
@@ -226,7 +223,7 @@
35
        pw_properties_set(props, "master", NULL);
36
    }
37
 
38
-   if (module_args_to_audioinfo(impl, props, &playback_info) < 0) {
39
+   if (module_args_to_audioinfo(module->impl, props, &playback_info) < 0) {
40
        res = -EINVAL;
41
        goto out;
42
    }
43
@@ -238,30 +235,23 @@
44
    if (pw_properties_get(capture_props, PW_KEY_NODE_PASSIVE) == NULL)
45
        pw_properties_set(capture_props, PW_KEY_NODE_PASSIVE, "true");
46
 
47
-   module = module_new(impl, sizeof(*d));
48
-   if (module == NULL) {
49
-       res = -errno;
50
-       goto out;
51
-   }
52
-
53
-   module->props = props;
54
-   d = module->user_data;
55
    d->module = module;
56
    d->capture_props = capture_props;
57
    d->playback_props = playback_props;
58
 
59
-   return module;
60
+   return 0;
61
 out:
62
-   pw_properties_free(props);
63
    pw_properties_free(playback_props);
64
    pw_properties_free(capture_props);
65
-   errno = -res;
66
-   return NULL;
67
+
68
+   return res;
69
 }
70
 
71
 DEFINE_MODULE_INFO(module_ladspa_source) = {
72
    .name = "module-ladspa-source",
73
-   .create = create_module_ladspa_source,
74
+   .prepare = module_ladspa_source_prepare,
75
    .load = module_ladspa_source_load,
76
    .unload = module_ladspa_source_unload,
77
+   .properties = &SPA_DICT_INIT_ARRAY(module_ladspa_source_info),
78
+   .data_size = sizeof(struct module_ladspa_source_data),
79
 };
80
pipewire-0.3.51.tar.gz/src/modules/module-protocol-pulse/modules/module-loopback.c -> pipewire-0.3.52.tar.gz/src/modules/module-protocol-pulse/modules/module-loopback.c Changed
80
 
1
@@ -143,26 +143,23 @@
2
    { PW_KEY_MODULE_VERSION, PACKAGE_VERSION },
3
 };
4
 
5
-struct module *create_module_loopback(struct impl *impl, const char *argument)
6
+static int module_loopback_prepare(struct module * const module)
7
 {
8
-   struct module *module;
9
-   struct module_loopback_data *d;
10
-   struct pw_properties *props = NULL, *playback_props = NULL, *capture_props = NULL;
11
+   struct module_loopback_data * const d = module->user_data;
12
+   struct pw_properties * const props = module->props;
13
+   struct pw_properties *playback_props = NULL, *capture_props = NULL;
14
    const char *str;
15
    struct spa_audio_info_raw info = { 0 };
16
    int res;
17
 
18
    PW_LOG_TOPIC_INIT(mod_topic);
19
 
20
-   props = pw_properties_new_dict(&SPA_DICT_INIT_ARRAY(module_loopback_info));
21
    capture_props = pw_properties_new(NULL, NULL);
22
    playback_props = pw_properties_new(NULL, NULL);
23
-   if (!props || !capture_props || !playback_props) {
24
+   if (!capture_props || !playback_props) {
25
        res = -EINVAL;
26
        goto out;
27
    }
28
-   if (argument)
29
-       module_args_add_props(props, argument);
30
 
31
    /* The following modargs are not implemented:
32
     * adjust_time, max_latency_msec, fast_adjust_threshold_msec: these are just not relevant
33
@@ -185,7 +182,7 @@
34
        pw_properties_set(props, "sink", NULL);
35
    }
36
 
37
-   if (module_args_to_audioinfo(impl, props, &info) < 0) {
38
+   if (module_args_to_audioinfo(module->impl, props, &info) < 0) {
39
        res = -EINVAL;
40
        goto out;
41
    }
42
@@ -227,32 +224,24 @@
43
        pw_properties_set(props, "source_output_properties", NULL);
44
    }
45
 
46
-   module = module_new(impl, sizeof(*d));
47
-   if (module == NULL) {
48
-       res = -errno;
49
-       goto out;
50
-   }
51
-
52
-   module->props = props;
53
-   d = module->user_data;
54
    d->module = module;
55
    d->capture_props = capture_props;
56
    d->playback_props = playback_props;
57
    d->info = info;
58
 
59
-   return module;
60
+   return 0;
61
 out:
62
-   pw_properties_free(props);
63
    pw_properties_free(playback_props);
64
    pw_properties_free(capture_props);
65
-   errno = -res;
66
 
67
-   return NULL;
68
+   return res;
69
 }
70
 
71
 DEFINE_MODULE_INFO(module_loopback) = {
72
    .name = "module-loopback",
73
-   .create = create_module_loopback,
74
+   .prepare = module_loopback_prepare,
75
    .load = module_loopback_load,
76
    .unload = module_loopback_unload,
77
+   .properties = &SPA_DICT_INIT_ARRAY(module_loopback_info),
78
+   .data_size = sizeof(struct module_loopback_data),
79
 };
80
pipewire-0.3.51.tar.gz/src/modules/module-protocol-pulse/modules/module-native-protocol-tcp.c -> pipewire-0.3.52.tar.gz/src/modules/module-protocol-pulse/modules/module-native-protocol-tcp.c Changed
85
 
1
@@ -74,56 +74,54 @@
2
    { PW_KEY_MODULE_AUTHOR, "Wim Taymans <wim.taymans@gmail.com>" },
3
    { PW_KEY_MODULE_DESCRIPTION, "Native protocol (TCP sockets)" },
4
    { PW_KEY_MODULE_USAGE, "port=<TCP port number> "
5
-               "listen=<address to listen on>" },
6
+               "listen=<address to listen on> "
7
+               "auth-anonymous=<don't check for cookies?>"},
8
    { PW_KEY_MODULE_VERSION, PACKAGE_VERSION },
9
 };
10
 
11
-struct module *create_module_native_protocol_tcp(struct impl *impl, const char *argument)
12
+static int module_native_protocol_tcp_prepare(struct module * const module)
13
 {
14
-   struct module *module;
15
-   struct module_native_protocol_tcp_data *d;
16
-   struct pw_properties *props = NULL;
17
-   const char *port, *listen;
18
-   int res;
19
+   struct module_native_protocol_tcp_data * const d = module->user_data;
20
+   struct pw_properties * const props = module->props;
21
+   const char *port, *listen, *auth;
22
+   FILE *f;
23
+   char *args;
24
+   size_t size;
25
 
26
    PW_LOG_TOPIC_INIT(mod_topic);
27
 
28
-   props = pw_properties_new_dict(&SPA_DICT_INIT_ARRAY(module_native_protocol_tcp_info));
29
-   if (props == NULL) {
30
-       res = -errno;
31
-       goto out;
32
-   }
33
-   if (argument)
34
-       module_args_add_props(props, argument);
35
-
36
    if ((port = pw_properties_get(props, "port")) == NULL)
37
        port = SPA_STRINGIFY(PW_PROTOCOL_PULSE_DEFAULT_PORT);
38
 
39
    listen = pw_properties_get(props, "listen");
40
 
41
-   pw_properties_setf(props, "pulse.tcp", " \"tcp:%s%s%s\" ",
42
+   auth = pw_properties_get(props, "auth-anonymous");
43
+
44
+   f = open_memstream(&args, &size);
45
+   if (f == NULL)
46
+       return -errno;
47
+
48
+   fprintf(f, " { ");
49
+   fprintf(f, " \"address\": \"tcp:%s%s%s\" ",
50
               listen ? listen : "", listen ? ":" : "", port);
51
+   if (auth && module_args_parse_bool(auth))
52
+       fprintf(f, " \"client.access\": \"unrestricted\" ");
53
+   fprintf(f, "} ");
54
+   fclose(f);
55
 
56
-   module = module_new(impl, sizeof(*d));
57
-   if (module == NULL) {
58
-       res = -errno;
59
-       goto out;
60
-   }
61
+   pw_properties_set(props, "pulse.tcp", args);
62
+   free(args);
63
 
64
-   module->props = props;
65
-   d = module->user_data;
66
    d->module = module;
67
 
68
-   return module;
69
-out:
70
-   pw_properties_free(props);
71
-   errno = -res;
72
-   return NULL;
73
+   return 0;
74
 }
75
 
76
 DEFINE_MODULE_INFO(module_native_protocol_tcp) = {
77
    .name = "module-native-protocol-tcp",
78
-   .create = create_module_native_protocol_tcp,
79
+   .prepare = module_native_protocol_tcp_prepare,
80
    .load = module_native_protocol_tcp_load,
81
    .unload = module_native_protocol_tcp_unload,
82
+   .properties = &SPA_DICT_INIT_ARRAY(module_native_protocol_tcp_info),
83
+   .data_size = sizeof(struct module_native_protocol_tcp_data),
84
 };
85
pipewire-0.3.51.tar.gz/src/modules/module-protocol-pulse/modules/module-null-sink.c -> pipewire-0.3.52.tar.gz/src/modules/module-protocol-pulse/modules/module-null-sink.c Changed
70
 
1
@@ -158,25 +158,15 @@
2
    { PW_KEY_MODULE_VERSION, PACKAGE_VERSION },
3
 };
4
 
5
-struct module *create_module_null_sink(struct impl *impl, const char *argument)
6
+static int module_null_sink_prepare(struct module * const module)
7
 {
8
-   struct module *module;
9
-   struct pw_properties *props = NULL;
10
+   struct pw_properties * const props = module->props;
11
    const char *str;
12
    struct spa_audio_info_raw info = { 0 };
13
    uint32_t i;
14
-   int res;
15
 
16
    PW_LOG_TOPIC_INIT(mod_topic);
17
 
18
-   props = pw_properties_new_dict(&SPA_DICT_INIT_ARRAY(module_null_sink_info));
19
-   if (props == NULL) {
20
-       res = -EINVAL;
21
-       goto out;
22
-   }
23
-   if (argument)
24
-       module_args_add_props(props, argument);
25
-
26
    if ((str = pw_properties_get(props, "sink_name")) != NULL) {
27
        pw_properties_set(props, PW_KEY_NODE_NAME, str);
28
        pw_properties_set(props, "sink_name", NULL);
29
@@ -190,10 +180,8 @@
30
        pw_properties_set(props, "sink_properties", NULL);
31
    }
32
 
33
-   if (module_args_to_audioinfo(impl, props, &info) < 0) {
34
-       res = -EINVAL;
35
-       goto out;
36
-   }
37
+   if (module_args_to_audioinfo(module->impl, props, &info) < 0)
38
+       return -EINVAL;
39
 
40
    if (info.rate)
41
        pw_properties_setf(props, SPA_KEY_AUDIO_RATE, "%u", info.rate);
42
@@ -227,23 +215,14 @@
43
    if (pw_properties_get(props, "monitor.channel-volumes") == NULL)
44
        pw_properties_set(props, "monitor.channel-volumes", "true");
45
 
46
-   module = module_new(impl, sizeof(struct module_null_sink_data));
47
-   if (module == NULL) {
48
-       res = -errno;
49
-       goto out;
50
-   }
51
-   module->props = props;
52
-
53
-   return module;
54
-out:
55
-   pw_properties_free(props);
56
-   errno = -res;
57
-   return NULL;
58
+   return 0;
59
 }
60
 
61
 DEFINE_MODULE_INFO(module_null_sink) = {
62
    .name = "module-null-sink",
63
-   .create = create_module_null_sink,
64
+   .prepare = module_null_sink_prepare,
65
    .load = module_null_sink_load,
66
    .unload = module_null_sink_unload,
67
+   .properties = &SPA_DICT_INIT_ARRAY(module_null_sink_info),
68
+   .data_size = sizeof(struct module_null_sink_data),
69
 };
70
pipewire-0.3.51.tar.gz/src/modules/module-protocol-pulse/modules/module-pipe-sink.c -> pipewire-0.3.52.tar.gz/src/modules/module-protocol-pulse/modules/module-pipe-sink.c Changed
201
 
1
@@ -40,149 +40,78 @@
2
 PW_LOG_TOPIC_STATIC(mod_topic, "mod." NAME);
3
 #define PW_LOG_TOPIC_DEFAULT mod_topic
4
 
5
-#define DEFAULT_FILE_NAME "/tmp/music.output"
6
-
7
 struct module_pipesink_data {
8
    struct module *module;
9
-   struct pw_core *core;
10
-
11
-   struct pw_stream *capture;
12
 
13
-   struct spa_hook core_listener;
14
-   struct spa_hook capture_listener;
15
+   struct spa_hook mod_listener;
16
+   struct pw_impl_module *mod;
17
 
18
    struct pw_properties *capture_props;
19
-
20
    struct spa_audio_info_raw info;
21
-
22
    char *filename;
23
-   int fd;
24
-   bool do_unlink_fifo;
25
-};
26
-
27
-static void capture_process(void *data)
28
-{
29
-   struct module_pipesink_data *impl = data;
30
-   struct pw_buffer *in;
31
-   struct spa_data *d;
32
-   uint32_t i, size, offset;
33
-   int written;
34
-
35
-   if ((in = pw_stream_dequeue_buffer(impl->capture)) == NULL) {
36
-       pw_log_warn("Out of capture buffers: %m");
37
-       return;
38
-   }
39
-
40
-   for (i = 0; i < in->buffer->n_datas; i++) {
41
-       d = &in->buffer->datasi;
42
-       size = d->chunk->size;
43
-       offset = d->chunk->offset;
44
-
45
-       while (size > 0) {
46
-           written = write(impl->fd, SPA_MEMBER(d->data, offset, void), size);
47
-           if (written < 0) {
48
-               if (errno == EINTR) {
49
-                   /* retry if interrupted */
50
-                   continue;
51
-               } else if (errno == EAGAIN || errno == EWOULDBLOCK) {
52
-                   /* Don't continue writing */
53
-                   break;
54
-               } else {
55
-                   pw_log_warn("Failed to write to pipe sink");
56
-               }
57
-           }
58
-
59
-           offset += written;
60
-           size -= written;
61
-       }
62
-   }
63
-   pw_stream_queue_buffer(impl->capture, in);
64
-}
65
-
66
-static void on_core_error(void *data, uint32_t id, int seq, int res, const char *message)
67
-{
68
-   struct module_pipesink_data *d = data;
69
-
70
-   pw_log_error("error id:%u seq:%d res:%d (%s): %s",
71
-           id, seq, res, spa_strerror(res), message);
72
-
73
-   if (id == PW_ID_CORE && res == -EPIPE)
74
-       module_schedule_unload(d->module);
75
-}
76
-
77
-static const struct pw_core_events core_events = {
78
-   PW_VERSION_CORE_EVENTS,
79
-   .error = on_core_error,
80
 };
81
 
82
-static void on_stream_state_changed(void *data, enum pw_stream_state old,
83
-       enum pw_stream_state state, const char *error)
84
+static void module_destroy(void *data)
85
 {
86
    struct module_pipesink_data *d = data;
87
-
88
-   switch (state) {
89
-       case PW_STREAM_STATE_UNCONNECTED:
90
-           pw_log_info("stream disconnected, unloading");
91
-           module_schedule_unload(d->module);
92
-           break;
93
-       case PW_STREAM_STATE_ERROR:
94
-           pw_log_error("stream error: %s", error);
95
-           break;
96
-       default:
97
-           break;
98
-   }
99
+   spa_hook_remove(&d->mod_listener);
100
+   d->mod = NULL;
101
+   module_schedule_unload(d->module);
102
 }
103
 
104
-static const struct pw_stream_events in_stream_events = {
105
-   PW_VERSION_STREAM_EVENTS,
106
-   .state_changed = on_stream_state_changed,
107
-   .process = capture_process
108
+static const struct pw_impl_module_events module_events = {
109
+   PW_VERSION_IMPL_MODULE_EVENTS,
110
+   .destroy = module_destroy
111
 };
112
 
113
 static int module_pipe_sink_load(struct client *client, struct module *module)
114
 {
115
    struct module_pipesink_data *data = module->user_data;
116
-   int res;
117
-   uint32_t n_params;
118
-   const struct spa_pod *params1;
119
-   uint8_t buffer1024;
120
-   struct spa_pod_builder b = SPA_POD_BUILDER_INIT(buffer, sizeof(buffer));
121
+   FILE *f;
122
+   char *args;
123
+   size_t size;
124
+   uint32_t i;
125
 
126
-   data->core = pw_context_connect(module->impl->context,
127
-           pw_properties_copy(client->props),
128
-           0);
129
-   if (data->core == NULL)
130
-       return -errno;
131
+   pw_properties_setf(data->capture_props, "pulse.module.id",
132
+           "%u", module->index);
133
 
134
-   pw_core_add_listener(data->core,
135
-           &data->core_listener,
136
-           &core_events, data);
137
-
138
-   pw_properties_setf(data->capture_props, "pulse.module.id", "%u", module->index);
139
-
140
-   data->capture = pw_stream_new(data->core,
141
-           "pipesink capture", data->capture_props);
142
-   data->capture_props = NULL;
143
-   if (data->capture == NULL)
144
+   if ((f = open_memstream(&args, &size)) == NULL)
145
        return -errno;
146
 
147
-   pw_stream_add_listener(data->capture,
148
-           &data->capture_listener,
149
-           &in_stream_events, data);
150
+   fprintf(f, "{");
151
+   fprintf(f, " \"tunnel.mode\" = \"sink\" ");
152
+   if (data->filename != NULL)
153
+       fprintf(f, " \"pipe.filename\": \"%s\"", data->filename);
154
+   if (data->info.format != 0)
155
+       fprintf(f, " \"audio.format\": \"%s\"", format_id2name(data->info.format));
156
+   if (data->info.rate != 0)
157
+       fprintf(f, " \"audio.rate\": %u,", data->info.rate);
158
+   if (data->info.channels != 0) {
159
+       fprintf(f, " \"audio.channels\": %u,", data->info.channels);
160
+       if (!(data->info.flags & SPA_AUDIO_FLAG_UNPOSITIONED)) {
161
+           fprintf(f, " \"audio.position\":  ");
162
+           for (i = 0; i < data->info.channels; i++)
163
+               fprintf(f, "%s\"%s\"", i == 0 ? "" : ",",
164
+                   channel_id2name(data->info.positioni));
165
+           fprintf(f, " ,");
166
+       }
167
+   }
168
+   pw_properties_serialize_dict(f, &data->capture_props->dict, 0);
169
+   fprintf(f, " }");
170
+   fclose(f);
171
+
172
+   data->mod = pw_context_load_module(module->impl->context,
173
+           "libpipewire-module-pipe-tunnel",
174
+           args, NULL);
175
 
176
-   n_params = 0;
177
-   paramsn_params++ = spa_format_audio_raw_build(&b, SPA_PARAM_EnumFormat,
178
-           &data->info);
179
+   free(args);
180
 
181
-   if ((res = pw_stream_connect(data->capture,
182
-           PW_DIRECTION_INPUT,
183
-           PW_ID_ANY,
184
-           PW_STREAM_FLAG_AUTOCONNECT |
185
-           PW_STREAM_FLAG_MAP_BUFFERS |
186
-           PW_STREAM_FLAG_RT_PROCESS,
187
-           params, n_params)) < 0)
188
-       return res;
189
+   if (data->mod == NULL)
190
+       return -errno;
191
 
192
+   pw_impl_module_add_listener(data->mod,
193
+           &data->mod_listener,
194
+           &module_events, data);
195
    return 0;
196
 }
197
 
198
@@ -190,19 +119,13 @@
199
 {
200
    struct module_pipesink_data *d = module->user_data;
201
pipewire-0.3.51.tar.gz/src/modules/module-protocol-pulse/modules/module-pipe-source.c -> pipewire-0.3.52.tar.gz/src/modules/module-protocol-pulse/modules/module-pipe-source.c Changed
201
 
1
@@ -40,171 +40,78 @@
2
 PW_LOG_TOPIC_STATIC(mod_topic, "mod." NAME);
3
 #define PW_LOG_TOPIC_DEFAULT mod_topic
4
 
5
-
6
-#define DEFAULT_FILE_NAME "/tmp/music.input"
7
-
8
 struct module_pipesrc_data {
9
    struct module *module;
10
-   struct pw_core *core;
11
-
12
-   struct pw_stream *playback;
13
 
14
-   struct spa_hook core_listener;
15
-   struct spa_hook playback_listener;
16
+   struct spa_hook mod_listener;
17
+   struct pw_impl_module *mod;
18
 
19
    struct pw_properties *playback_props;
20
-
21
    struct spa_audio_info_raw info;
22
-
23
-   bool do_unlink;
24
    char *filename;
25
-   int fd;
26
-
27
-   uint32_t stride;
28
-
29
-   uint32_t leftover_count;
30
-   uint8_t leftover; /* `stride` bytes for storing a partial sample */
31
 };
32
 
33
-static void playback_process(void *data)
34
-{
35
-   struct module_pipesrc_data *impl = data;
36
-   struct spa_chunk *chunk;
37
-   struct pw_buffer *buffer;
38
-   struct spa_data *d;
39
-   uint32_t left, leftover;
40
-   ssize_t bytes_read;
41
-
42
-   if ((buffer = pw_stream_dequeue_buffer(impl->playback)) == NULL) {
43
-       pw_log_warn("Out of playback buffers: %m");
44
-       return;
45
-   }
46
-
47
-   d = &buffer->buffer->datas0;
48
-   if (d->data == NULL)
49
-       return;
50
-
51
-   left = d->maxsize;
52
-   spa_assert(left >= impl->leftover_count);
53
-
54
-   chunk = d->chunk;
55
-
56
-   chunk->offset = 0;
57
-   chunk->stride = impl->stride;
58
-   chunk->size = impl->leftover_count;
59
-
60
-   memcpy(d->data, impl->leftover, impl->leftover_count);
61
-
62
-   left -= impl->leftover_count;
63
-
64
-   bytes_read = read(impl->fd, SPA_PTROFF(d->data, chunk->size, void), left);
65
-   if (bytes_read < 0) {
66
-       const bool important = !(errno == EINTR
67
-                    || errno == EAGAIN
68
-                    || errno == EWOULDBLOCK);
69
-
70
-       if (important)
71
-           pw_log_warn("failed to read from pipe (%s): %s",
72
-                   impl->filename, strerror(errno));
73
-   }
74
-   else {
75
-       chunk->size += bytes_read;
76
-   }
77
-
78
-   leftover = chunk->size % impl->stride;
79
-   chunk->size -= leftover;
80
-
81
-   memcpy(impl->leftover, SPA_PTROFF(d->data, chunk->size, void), leftover);
82
-   impl->leftover_count = leftover;
83
-
84
-   pw_stream_queue_buffer(impl->playback, buffer);
85
-}
86
-
87
-static void on_core_error(void *data, uint32_t id, int seq, int res, const char *message)
88
+static void module_destroy(void *data)
89
 {
90
    struct module_pipesrc_data *d = data;
91
-
92
-   pw_log_error("error id:%u seq:%d res:%d (%s): %s",
93
-           id, seq, res, spa_strerror(res), message);
94
-
95
-   if (id == PW_ID_CORE && res == -EPIPE)
96
-       module_schedule_unload(d->module);
97
+   spa_hook_remove(&d->mod_listener);
98
+   d->mod = NULL;
99
+   module_schedule_unload(d->module);
100
 }
101
 
102
-static const struct pw_core_events core_events = {
103
-   PW_VERSION_CORE_EVENTS,
104
-   .error = on_core_error,
105
-};
106
-
107
-static void on_stream_state_changed(void *data, enum pw_stream_state old,
108
-       enum pw_stream_state state, const char *error)
109
-{
110
-   struct module_pipesrc_data *d = data;
111
-
112
-   switch (state) {
113
-   case PW_STREAM_STATE_UNCONNECTED:
114
-       pw_log_info("stream disconnected, unloading");
115
-       module_schedule_unload(d->module);
116
-       break;
117
-   case PW_STREAM_STATE_ERROR:
118
-       pw_log_error("stream error: %s", error);
119
-       break;
120
-   default:
121
-       break;
122
-   }
123
-}
124
-
125
-static const struct pw_stream_events out_stream_events = {
126
-   PW_VERSION_STREAM_EVENTS,
127
-   .state_changed = on_stream_state_changed,
128
-   .process = playback_process
129
+static const struct pw_impl_module_events module_events = {
130
+   PW_VERSION_IMPL_MODULE_EVENTS,
131
+   .destroy = module_destroy
132
 };
133
 
134
 static int module_pipe_source_load(struct client *client, struct module *module)
135
 {
136
    struct module_pipesrc_data *data = module->user_data;
137
-   int res;
138
-   uint32_t n_params;
139
-   const struct spa_pod *params1;
140
-   uint8_t buffer1024;
141
-   struct spa_pod_builder b = SPA_POD_BUILDER_INIT(buffer, sizeof(buffer));
142
-
143
-   data->core = pw_context_connect(module->impl->context,
144
-           pw_properties_copy(client->props),
145
-           0);
146
-   if (data->core == NULL)
147
-       return -errno;
148
-
149
-   pw_core_add_listener(data->core,
150
-           &data->core_listener,
151
-           &core_events, data);
152
+   FILE *f;
153
+   char *args;
154
+   size_t size;
155
+   uint32_t i;
156
 
157
    pw_properties_setf(data->playback_props, "pulse.module.id",
158
            "%u", module->index);
159
 
160
-   data->playback = pw_stream_new(data->core,
161
-           "pipesource playback", data->playback_props);
162
-   data->playback_props = NULL;
163
-   if (data->playback == NULL)
164
+   if ((f = open_memstream(&args, &size)) == NULL)
165
        return -errno;
166
 
167
-   pw_stream_add_listener(data->playback,
168
-           &data->playback_listener,
169
-           &out_stream_events, data);
170
+   fprintf(f, "{");
171
+   fprintf(f, " \"tunnel.mode\" = \"source\" ");
172
+   if (data->filename != NULL)
173
+       fprintf(f, " \"pipe.filename\": \"%s\"", data->filename);
174
+   if (data->info.format != 0)
175
+       fprintf(f, " \"audio.format\": \"%s\"", format_id2name(data->info.format));
176
+   if (data->info.rate != 0)
177
+       fprintf(f, " \"audio.rate\": %u,", data->info.rate);
178
+   if (data->info.channels != 0) {
179
+       fprintf(f, " \"audio.channels\": %u,", data->info.channels);
180
+       if (!(data->info.flags & SPA_AUDIO_FLAG_UNPOSITIONED)) {
181
+           fprintf(f, " \"audio.position\":  ");
182
+           for (i = 0; i < data->info.channels; i++)
183
+               fprintf(f, "%s\"%s\"", i == 0 ? "" : ",",
184
+                   channel_id2name(data->info.positioni));
185
+           fprintf(f, " ,");
186
+       }
187
+   }
188
+   pw_properties_serialize_dict(f, &data->playback_props->dict, 0);
189
+   fprintf(f, " }");
190
+   fclose(f);
191
+
192
+   data->mod = pw_context_load_module(module->impl->context,
193
+           "libpipewire-module-pipe-tunnel",
194
+           args, NULL);
195
 
196
-   n_params = 0;
197
-   paramsn_params++ = spa_format_audio_raw_build(&b, SPA_PARAM_EnumFormat,
198
-           &data->info);
199
+   free(args);
200
 
201
pipewire-0.3.51.tar.gz/src/modules/module-protocol-pulse/modules/module-raop-discover.c -> pipewire-0.3.52.tar.gz/src/modules/module-protocol-pulse/modules/module-raop-discover.c Changed
53
 
1
@@ -92,44 +92,22 @@
2
    { PW_KEY_MODULE_VERSION, PACKAGE_VERSION },
3
 };
4
 
5
-struct module *create_module_raop_discover(struct impl *impl, const char *argument)
6
+static int module_raop_discover_prepare(struct module * const module)
7
 {
8
-   struct module *module;
9
-   struct module_raop_discover_data *d;
10
-   struct pw_properties *props = NULL;
11
-   int res;
12
-
13
    PW_LOG_TOPIC_INIT(mod_topic);
14
 
15
-   props = pw_properties_new_dict(&SPA_DICT_INIT_ARRAY(module_raop_discover_info));
16
-   if (props == NULL) {
17
-       res = -errno;
18
-       goto out;
19
-   }
20
-   if (argument != NULL)
21
-       module_args_add_props(props, argument);
22
+   struct module_raop_discover_data * const data = module->user_data;
23
+   data->module = module;
24
 
25
-   module = module_new(impl, sizeof(*d));
26
-   if (module == NULL) {
27
-       res = -errno;
28
-       goto out;
29
-   }
30
-
31
-   module->props = props;
32
-   d = module->user_data;
33
-   d->module = module;
34
-
35
-   return module;
36
-out:
37
-   pw_properties_free(props);
38
-   errno = -res;
39
-   return NULL;
40
+   return 0;
41
 }
42
 
43
 DEFINE_MODULE_INFO(module_raop_discover) = {
44
    .name = "module-raop-discover",
45
    .load_once = true,
46
-   .create = create_module_raop_discover,
47
+   .prepare = module_raop_discover_prepare,
48
    .load = module_raop_discover_load,
49
    .unload = module_raop_discover_unload,
50
+   .properties = &SPA_DICT_INIT_ARRAY(module_raop_discover_info),
51
+   .data_size = sizeof(struct module_raop_discover_data),
52
 };
53
pipewire-0.3.51.tar.gz/src/modules/module-protocol-pulse/modules/module-remap-sink.c -> pipewire-0.3.52.tar.gz/src/modules/module-protocol-pulse/modules/module-remap-sink.c Changed
80
 
1
@@ -143,11 +143,11 @@
2
    pw_properties_set(props, SPA_KEY_AUDIO_POSITION, s);
3
 }
4
 
5
-struct module *create_module_remap_sink(struct impl *impl, const char *argument)
6
+static int module_remap_sink_prepare(struct module * const module)
7
 {
8
-   struct module *module;
9
-   struct module_remap_sink_data *d;
10
-   struct pw_properties *props = NULL, *playback_props = NULL, *capture_props = NULL;
11
+   struct module_remap_sink_data * const d = module->user_data;
12
+   struct pw_properties * const props = module->props;
13
+   struct pw_properties *playback_props = NULL, *capture_props = NULL;
14
    const char *str, *master;
15
    struct spa_audio_info_raw capture_info = { 0 };
16
    struct spa_audio_info_raw playback_info = { 0 };
17
@@ -155,15 +155,12 @@
18
 
19
    PW_LOG_TOPIC_INIT(mod_topic);
20
 
21
-   props = pw_properties_new_dict(&SPA_DICT_INIT_ARRAY(module_remap_sink_info));
22
    capture_props = pw_properties_new(NULL, NULL);
23
    playback_props = pw_properties_new(NULL, NULL);
24
-   if (!props || !capture_props || !playback_props) {
25
+   if (!capture_props || !playback_props) {
26
        res = -EINVAL;
27
        goto out;
28
    }
29
-   if (argument)
30
-       module_args_add_props(props, argument);
31
 
32
    master = pw_properties_get(props, "master");
33
    if (pw_properties_get(props, "sink_name") == NULL) {
34
@@ -204,7 +201,7 @@
35
        pw_properties_set(props, "master", NULL);
36
    }
37
 
38
-   if (module_args_to_audioinfo(impl, props, &capture_info) < 0) {
39
+   if (module_args_to_audioinfo(module->impl, props, &capture_info) < 0) {
40
        res = -EINVAL;
41
        goto out;
42
    }
43
@@ -235,30 +232,23 @@
44
    if (pw_properties_get(playback_props, PW_KEY_NODE_PASSIVE) == NULL)
45
        pw_properties_set(playback_props, PW_KEY_NODE_PASSIVE, "true");
46
 
47
-   module = module_new(impl, sizeof(*d));
48
-   if (module == NULL) {
49
-       res = -errno;
50
-       goto out;
51
-   }
52
-
53
-   module->props = props;
54
-   d = module->user_data;
55
    d->module = module;
56
    d->capture_props = capture_props;
57
    d->playback_props = playback_props;
58
 
59
-   return module;
60
+   return 0;
61
 out:
62
-   pw_properties_free(props);
63
    pw_properties_free(playback_props);
64
    pw_properties_free(capture_props);
65
-   errno = -res;
66
-   return NULL;
67
+
68
+   return res;
69
 }
70
 
71
 DEFINE_MODULE_INFO(module_remap_sink) = {
72
    .name = "module-remap-sink",
73
-   .create = create_module_remap_sink,
74
+   .prepare = module_remap_sink_prepare,
75
    .load = module_remap_sink_load,
76
    .unload = module_remap_sink_unload,
77
+   .properties = &SPA_DICT_INIT_ARRAY(module_remap_sink_info),
78
+   .data_size = sizeof(struct module_remap_sink_data),
79
 };
80
pipewire-0.3.51.tar.gz/src/modules/module-protocol-pulse/modules/module-remap-source.c -> pipewire-0.3.52.tar.gz/src/modules/module-protocol-pulse/modules/module-remap-source.c Changed
80
 
1
@@ -143,11 +143,11 @@
2
    pw_properties_set(props, SPA_KEY_AUDIO_POSITION, s);
3
 }
4
 
5
-struct module *create_module_remap_source(struct impl *impl, const char *argument)
6
+static int module_remap_source_prepare(struct module * const module)
7
 {
8
-   struct module *module;
9
-   struct module_remap_source_data *d;
10
-   struct pw_properties *props = NULL, *playback_props = NULL, *capture_props = NULL;
11
+   struct module_remap_source_data * const d = module->user_data;
12
+   struct pw_properties * const props = module->props;
13
+   struct pw_properties *playback_props = NULL, *capture_props = NULL;
14
    const char *str, *master;
15
    struct spa_audio_info_raw capture_info = { 0 };
16
    struct spa_audio_info_raw playback_info = { 0 };
17
@@ -155,15 +155,12 @@
18
 
19
    PW_LOG_TOPIC_INIT(mod_topic);
20
 
21
-   props = pw_properties_new_dict(&SPA_DICT_INIT_ARRAY(module_remap_source_info));
22
    capture_props = pw_properties_new(NULL, NULL);
23
    playback_props = pw_properties_new(NULL, NULL);
24
-   if (!props || !capture_props || !playback_props) {
25
+   if (!capture_props || !playback_props) {
26
        res = -EINVAL;
27
        goto out;
28
    }
29
-   if (argument)
30
-       module_args_add_props(props, argument);
31
 
32
    master = pw_properties_get(props, "master");
33
    if (pw_properties_get(props, "source_name") == NULL) {
34
@@ -204,7 +201,7 @@
35
        pw_properties_set(props, "master", NULL);
36
    }
37
 
38
-   if (module_args_to_audioinfo(impl, props, &playback_info) < 0) {
39
+   if (module_args_to_audioinfo(module->impl, props, &playback_info) < 0) {
40
        res = -EINVAL;
41
        goto out;
42
    }
43
@@ -235,30 +232,23 @@
44
    if (pw_properties_get(capture_props, PW_KEY_NODE_PASSIVE) == NULL)
45
        pw_properties_set(capture_props, PW_KEY_NODE_PASSIVE, "true");
46
 
47
-   module = module_new(impl, sizeof(*d));
48
-   if (module == NULL) {
49
-       res = -errno;
50
-       goto out;
51
-   }
52
-
53
-   module->props = props;
54
-   d = module->user_data;
55
    d->module = module;
56
    d->capture_props = capture_props;
57
    d->playback_props = playback_props;
58
 
59
-   return module;
60
+   return 0;
61
 out:
62
-   pw_properties_free(props);
63
    pw_properties_free(playback_props);
64
    pw_properties_free(capture_props);
65
-   errno = -res;
66
-   return NULL;
67
+
68
+   return res;
69
 }
70
 
71
 DEFINE_MODULE_INFO(module_remap_source) = {
72
    .name = "module-remap-source",
73
-   .create = create_module_remap_source,
74
+   .prepare = module_remap_source_prepare,
75
    .load = module_remap_source_load,
76
    .unload = module_remap_source_unload,
77
+   .properties = &SPA_DICT_INIT_ARRAY(module_remap_source_info),
78
+   .data_size = sizeof(struct module_remap_source_data),
79
 };
80
pipewire-0.3.51.tar.gz/src/modules/module-protocol-pulse/modules/module-roc-sink-input.c -> pipewire-0.3.52.tar.gz/src/modules/module-protocol-pulse/modules/module-roc-sink-input.c Changed
71
 
1
@@ -124,27 +124,23 @@
2
    { PW_KEY_MODULE_VERSION, PACKAGE_VERSION },
3
 };
4
 
5
-struct module *create_module_roc_sink_input(struct impl *impl, const char *argument)
6
+static int module_roc_sink_input_prepare(struct module * const module)
7
 {
8
-   struct module *module;
9
-   struct module_roc_sink_input_data *d;
10
-   struct pw_properties *props = NULL, *source_props = NULL, *roc_props = NULL;
11
+   struct module_roc_sink_input_data * const d = module->user_data;
12
+   struct pw_properties * const props = module->props;
13
+   struct pw_properties *source_props = NULL, *roc_props = NULL;
14
    const char *str;
15
    int res;
16
 
17
    PW_LOG_TOPIC_INIT(mod_topic);
18
 
19
-   props = pw_properties_new_dict(&SPA_DICT_INIT_ARRAY(module_roc_sink_input_info));
20
    source_props = pw_properties_new(NULL, NULL);
21
    roc_props = pw_properties_new(NULL, NULL);
22
-   if (!props || !source_props || !roc_props) {
23
+   if (!source_props || !roc_props) {
24
        res = -errno;
25
        goto out;
26
    }
27
 
28
-   if (argument != NULL)
29
-       module_args_add_props(props, argument);
30
-
31
    if ((str = pw_properties_get(props, "sink")) != NULL) {
32
        pw_properties_set(source_props, PW_KEY_TARGET_OBJECT, str);
33
        pw_properties_set(props, "sink", NULL);
34
@@ -184,30 +180,23 @@
35
        pw_properties_set(props, "fec_code", NULL);
36
    }
37
 
38
-   module = module_new(impl, sizeof(*d));
39
-   if (module == NULL) {
40
-       res = -errno;
41
-       goto out;
42
-   }
43
-
44
-   module->props = props;
45
-   d = module->user_data;
46
    d->module = module;
47
    d->source_props = source_props;
48
    d->roc_props = roc_props;
49
 
50
-   return module;
51
+   return 0;
52
 out:
53
-   pw_properties_free(props);
54
    pw_properties_free(source_props);
55
    pw_properties_free(roc_props);
56
-   errno = -res;
57
-   return NULL;
58
+
59
+   return res;
60
 }
61
 
62
 DEFINE_MODULE_INFO(module_roc_sink_input) = {
63
    .name = "module-roc-sink-input",
64
-   .create = create_module_roc_sink_input,
65
+   .prepare = module_roc_sink_input_prepare,
66
    .load = module_roc_sink_input_load,
67
    .unload = module_roc_sink_input_unload,
68
+   .properties = &SPA_DICT_INIT_ARRAY(module_roc_sink_input_info),
69
+   .data_size = sizeof(struct module_roc_sink_input_data),
70
 };
71
pipewire-0.3.51.tar.gz/src/modules/module-protocol-pulse/modules/module-roc-sink.c -> pipewire-0.3.52.tar.gz/src/modules/module-protocol-pulse/modules/module-roc-sink.c Changed
69
 
1
@@ -123,25 +123,22 @@
2
    { PW_KEY_MODULE_VERSION, PACKAGE_VERSION },
3
 };
4
 
5
-struct module *create_module_roc_sink(struct impl *impl, const char *argument)
6
+static int module_roc_sink_prepare(struct module * const module)
7
 {
8
-   struct module *module;
9
-   struct module_roc_sink_data *d;
10
-   struct pw_properties *props = NULL, *sink_props = NULL, *roc_props = NULL;
11
+   struct module_roc_sink_data * const d = module->user_data;
12
+   struct pw_properties * const props = module->props;
13
+   struct pw_properties *sink_props = NULL, *roc_props = NULL;
14
    const char *str;
15
    int res;
16
 
17
    PW_LOG_TOPIC_INIT(mod_topic);
18
 
19
-   props = pw_properties_new_dict(&SPA_DICT_INIT_ARRAY(module_roc_sink_info));
20
    sink_props = pw_properties_new(NULL, NULL);
21
    roc_props = pw_properties_new(NULL, NULL);
22
-   if (!props || !sink_props || !roc_props) {
23
+   if (!sink_props || !roc_props) {
24
        res = -errno;
25
        goto out;
26
    }
27
-   if (argument != NULL)
28
-       module_args_add_props(props, argument);
29
 
30
    if ((str = pw_properties_get(props, "sink_name")) != NULL) {
31
        pw_properties_set(sink_props, PW_KEY_NODE_NAME, str);
32
@@ -185,30 +182,23 @@
33
        pw_properties_set(props, "fec_code", NULL);
34
    }
35
 
36
-   module = module_new(impl, sizeof(*d));
37
-   if (module == NULL) {
38
-       res = -errno;
39
-       goto out;
40
-   }
41
-
42
-   module->props = props;
43
-   d = module->user_data;
44
    d->module = module;
45
    d->sink_props = sink_props;
46
    d->roc_props = roc_props;
47
 
48
-   return module;
49
+   return 0;
50
 out:
51
-   pw_properties_free(props);
52
    pw_properties_free(sink_props);
53
    pw_properties_free(roc_props);
54
-   errno = -res;
55
-   return NULL;
56
+
57
+   return res;
58
 }
59
 
60
 DEFINE_MODULE_INFO(module_roc_sink) = {
61
    .name = "module-roc-sink",
62
-   .create = create_module_roc_sink,
63
+   .prepare = module_roc_sink_prepare,
64
    .load = module_roc_sink_load,
65
    .unload = module_roc_sink_unload,
66
+   .properties = &SPA_DICT_INIT_ARRAY(module_roc_sink_info),
67
+   .data_size = sizeof(struct module_roc_sink_data),
68
 };
69
pipewire-0.3.51.tar.gz/src/modules/module-protocol-pulse/modules/module-roc-source.c -> pipewire-0.3.52.tar.gz/src/modules/module-protocol-pulse/modules/module-roc-source.c Changed
71
 
1
@@ -124,27 +124,23 @@
2
    { PW_KEY_MODULE_VERSION, PACKAGE_VERSION },
3
 };
4
 
5
-struct module *create_module_roc_source(struct impl *impl, const char *argument)
6
+static int module_roc_source_prepare(struct module * const module)
7
 {
8
-   struct module *module;
9
-   struct module_roc_source_data *d;
10
-   struct pw_properties *props = NULL, *source_props = NULL, *roc_props = NULL;
11
+   struct module_roc_source_data * const d = module->user_data;
12
+   struct pw_properties * const props = module->props;
13
+   struct pw_properties *source_props = NULL, *roc_props = NULL;
14
    const char *str;
15
    int res;
16
 
17
    PW_LOG_TOPIC_INIT(mod_topic);
18
 
19
-   props = pw_properties_new_dict(&SPA_DICT_INIT_ARRAY(module_roc_source_info));
20
    source_props = pw_properties_new(NULL, NULL);
21
    roc_props = pw_properties_new(NULL, NULL);
22
-   if (!props || !source_props || !roc_props) {
23
+   if (!source_props || !roc_props) {
24
        res = -errno;
25
        goto out;
26
    }
27
 
28
-   if (argument != NULL)
29
-       module_args_add_props(props, argument);
30
-
31
    if ((str = pw_properties_get(props, "source_name")) != NULL) {
32
        pw_properties_set(source_props, PW_KEY_NODE_NAME, str);
33
        pw_properties_set(props, "source_name", NULL);
34
@@ -189,30 +185,23 @@
35
        pw_properties_set(props, "fec_code", NULL);
36
    }
37
 
38
-   module = module_new(impl, sizeof(*d));
39
-   if (module == NULL) {
40
-       res = -errno;
41
-       goto out;
42
-   }
43
-
44
-   module->props = props;
45
-   d = module->user_data;
46
    d->module = module;
47
    d->source_props = source_props;
48
    d->roc_props = roc_props;
49
 
50
-   return module;
51
+   return 0;
52
 out:
53
-   pw_properties_free(props);
54
    pw_properties_free(source_props);
55
    pw_properties_free(roc_props);
56
-   errno = -res;
57
-   return NULL;
58
+
59
+   return res;
60
 }
61
 
62
 DEFINE_MODULE_INFO(module_roc_source) = {
63
    .name = "module-roc-source",
64
-   .create = create_module_roc_source,
65
+   .prepare = module_roc_source_prepare,
66
    .load = module_roc_source_load,
67
    .unload = module_roc_source_unload,
68
+   .properties = &SPA_DICT_INIT_ARRAY(module_roc_source_info),
69
+   .data_size = sizeof(struct module_roc_source_data),
70
 };
71
pipewire-0.3.51.tar.gz/src/modules/module-protocol-pulse/modules/module-simple-protocol-tcp.c -> pipewire-0.3.52.tar.gz/src/modules/module-protocol-pulse/modules/module-simple-protocol-tcp.c Changed
76
 
1
@@ -130,25 +130,17 @@
2
    { PW_KEY_MODULE_VERSION, PACKAGE_VERSION },
3
 };
4
 
5
-struct module *create_module_simple_protocol_tcp(struct impl *impl, const char *argument)
6
+static int module_simple_protocol_tcp_prepare(struct module * const module)
7
 {
8
-   struct module *module;
9
-   struct module_simple_protocol_tcp_data *d;
10
-   struct pw_properties *props = NULL, *module_props = NULL;
11
+   struct module_simple_protocol_tcp_data * const d = module->user_data;
12
+   struct pw_properties * const props = module->props;
13
+   struct pw_properties *module_props = NULL;
14
    const char *str, *port, *listen;
15
    struct spa_audio_info_raw info = { 0 };
16
    int res;
17
 
18
    PW_LOG_TOPIC_INIT(mod_topic);
19
 
20
-   props = pw_properties_new_dict(&SPA_DICT_INIT_ARRAY(module_simple_protocol_tcp_info));
21
-   if (props == NULL) {
22
-       res = -errno;
23
-       goto out;
24
-   }
25
-   if (argument)
26
-       module_args_add_props(props, argument);
27
-
28
    module_props = pw_properties_new(NULL, NULL);
29
    if (module_props == NULL) {
30
        res = -errno;
31
@@ -160,7 +152,7 @@
32
                format_id2name(format_paname2id(str, strlen(str))));
33
        pw_properties_set(props, "format", NULL);
34
    }
35
-   if (module_args_to_audioinfo(impl, props, &info) < 0) {
36
+   if (module_args_to_audioinfo(module->impl, props, &info) < 0) {
37
        res = -EINVAL;
38
        goto out;
39
    }
40
@@ -197,29 +189,22 @@
41
    pw_properties_setf(module_props, "server.address", " \"tcp:%s%s%s\" ",
42
            listen ? listen : "", listen ? ":" : "", port);
43
 
44
-   module = module_new(impl, sizeof(*d));
45
-   if (module == NULL) {
46
-       res = -errno;
47
-       goto out;
48
-   }
49
-
50
-   module->props = props;
51
-   d = module->user_data;
52
    d->module = module;
53
    d->module_props = module_props;
54
    d->info = info;
55
 
56
-   return module;
57
+   return 0;
58
 out:
59
    pw_properties_free(module_props);
60
-   pw_properties_free(props);
61
-   errno = -res;
62
-   return NULL;
63
+
64
+   return res;
65
 }
66
 
67
 DEFINE_MODULE_INFO(module_simple_protocol_tcp) = {
68
    .name = "module-simple-protocol-tcp",
69
-   .create = create_module_simple_protocol_tcp,
70
+   .prepare = module_simple_protocol_tcp_prepare,
71
    .load = module_simple_protocol_tcp_load,
72
    .unload = module_simple_protocol_tcp_unload,
73
+   .properties = &SPA_DICT_INIT_ARRAY(module_simple_protocol_tcp_info),
74
+   .data_size = sizeof(struct module_simple_protocol_tcp_data),
75
 };
76
pipewire-0.3.51.tar.gz/src/modules/module-protocol-pulse/modules/module-switch-on-connect.c -> pipewire-0.3.52.tar.gz/src/modules/module-protocol-pulse/modules/module-switch-on-connect.c Changed
126
 
1
@@ -52,7 +52,7 @@
2
    struct spa_hook manager_listener;
3
    struct pw_manager_object *metadata_default;
4
 
5
-   regex_t *blocklist;
6
+   regex_t blocklist;
7
 
8
    int sync_seq;
9
 
10
@@ -122,7 +122,7 @@
11
        return;
12
    }
13
 
14
-   if (d->blocklist && regexec(d->blocklist, name, 0, NULL, 0) == 0) {
15
+   if (regexec(&d->blocklist, name, 0, NULL, 0) == 0) {
16
        pw_log_debug("not switching to blocklisted device");
17
        return;
18
    }
19
@@ -224,11 +224,7 @@
20
        d->core = NULL;
21
    }
22
 
23
-   if (d->blocklist) {
24
-       regfree(d->blocklist);
25
-       free(d->blocklist);
26
-       d->blocklist = NULL;
27
-   }
28
+   regfree(&d->blocklist);
29
 
30
    return 0;
31
 }
32
@@ -245,26 +241,15 @@
33
    { PW_KEY_MODULE_VERSION, PACKAGE_VERSION },
34
 };
35
 
36
-struct module *create_module_switch_on_connect(struct impl *impl, const char *argument)
37
+static int module_switch_on_connect_prepare(struct module * const module)
38
 {
39
-   struct module *module;
40
-   struct module_switch_on_connect_data *d;
41
-   struct pw_properties *props = NULL;
42
-   regex_t *blocklist = NULL;
43
+   struct module_switch_on_connect_data * const d = module->user_data;
44
+   struct pw_properties * const props = module->props;
45
    bool only_from_unavailable = false, ignore_virtual = true;
46
    const char *str;
47
-   int res;
48
 
49
    PW_LOG_TOPIC_INIT(mod_topic);
50
 
51
-   props = pw_properties_new_dict(&SPA_DICT_INIT_ARRAY(module_switch_on_connect_info));
52
-   if (!props) {
53
-       res = -EINVAL;
54
-       goto out;
55
-   }
56
-   if (argument)
57
-       module_args_add_props(props, argument);
58
-
59
    if ((str = pw_properties_get(props, "only_from_unavailable")) != NULL) {
60
        only_from_unavailable = module_args_parse_bool(str);
61
        pw_properties_set(props, "only_from_unavailable", NULL);
62
@@ -275,33 +260,15 @@
63
        pw_properties_set(props, "ignore_virtual", NULL);
64
    }
65
 
66
-   if ((blocklist = malloc(sizeof(regex_t))) == NULL) {
67
-       res = -ENOMEM;
68
-       goto out;
69
-   }
70
-
71
    if ((str = pw_properties_get(props, "blocklist")) == NULL)
72
        str = DEFAULT_BLOCKLIST;
73
 
74
-   if ((res = regcomp(blocklist, str, REG_NOSUB | REG_EXTENDED)) != 0) {
75
-       free(blocklist);
76
-       blocklist = NULL;
77
-       res = -EINVAL;
78
-       goto out;
79
-   }
80
+   if (regcomp(&d->blocklist, str, REG_NOSUB | REG_EXTENDED) != 0)
81
+       return -EINVAL;
82
 
83
    pw_properties_set(props, "blocklist", NULL);
84
 
85
-   module = module_new(impl, sizeof(*d));
86
-   if (module == NULL) {
87
-       res = -errno;
88
-       goto out;
89
-   }
90
-
91
-   module->props = props;
92
-   d = module->user_data;
93
    d->module = module;
94
-   d->blocklist = blocklist;
95
    d->ignore_virtual = ignore_virtual;
96
    d->only_from_unavailable = only_from_unavailable;
97
 
98
@@ -310,23 +277,15 @@
99
        pw_log_warn("only_from_unavailable is not implemented");
100
    }
101
 
102
-   return module;
103
-
104
-out:
105
-   pw_properties_free(props);
106
-   if (blocklist) {
107
-       regfree(blocklist);
108
-       free(blocklist);
109
-   }
110
-   errno = -res;
111
-
112
-   return NULL;
113
+   return 0;
114
 }
115
 
116
 DEFINE_MODULE_INFO(module_switch_on_connect) = {
117
    .name = "module-switch-on-connect",
118
    .load_once = true,
119
-   .create = create_module_switch_on_connect,
120
+   .prepare = module_switch_on_connect_prepare,
121
    .load = module_switch_on_connect_load,
122
    .unload = module_switch_on_connect_unload,
123
+   .properties = &SPA_DICT_INIT_ARRAY(module_switch_on_connect_info),
124
+   .data_size = sizeof(struct module_switch_on_connect_data),
125
 };
126
pipewire-0.3.51.tar.gz/src/modules/module-protocol-pulse/modules/module-tunnel-sink.c -> pipewire-0.3.52.tar.gz/src/modules/module-protocol-pulse/modules/module-tunnel-sink.c Changed
87
 
1
@@ -81,7 +81,7 @@
2
    fprintf(f, "{");
3
    pw_properties_serialize_dict(f, &module->props->dict, 0);
4
    fprintf(f, " pulse.server.address = \"%s\" ", server);
5
-   fprintf(f, " tunnel.mode = playback ");
6
+   fprintf(f, " tunnel.mode = sink ");
7
    if (data->latency_msec > 0)
8
        fprintf(f, " pulse.latency = %u ", data->latency_msec);
9
    fprintf(f, " stream.props = {");
10
@@ -149,25 +149,22 @@
11
    pw_properties_set(props, SPA_KEY_AUDIO_POSITION, s);
12
 }
13
 
14
-struct module *create_module_tunnel_sink(struct impl *impl, const char *argument)
15
+static int module_tunnel_sink_prepare(struct module * const module)
16
 {
17
-   struct module *module;
18
-   struct module_tunnel_sink_data *d;
19
-   struct pw_properties *props = NULL, *stream_props = NULL;
20
+   struct module_tunnel_sink_data * const d = module->user_data;
21
+   struct pw_properties * const props = module->props;
22
+   struct pw_properties *stream_props = NULL;
23
    const char *str, *server, *remote_sink_name;
24
    struct spa_audio_info_raw info = { 0 };
25
    int res;
26
 
27
    PW_LOG_TOPIC_INIT(mod_topic);
28
 
29
-   props = pw_properties_new_dict(&SPA_DICT_INIT_ARRAY(module_tunnel_sink_info));
30
    stream_props = pw_properties_new(NULL, NULL);
31
-   if (props == NULL || stream_props == NULL) {
32
+   if (stream_props == NULL) {
33
        res = -ENOMEM;
34
        goto out;
35
    }
36
-   if (argument)
37
-       module_args_add_props(props, argument);
38
 
39
    remote_sink_name = pw_properties_get(props, "sink");
40
    if (remote_sink_name)
41
@@ -196,7 +193,7 @@
42
        module_args_add_props(stream_props, str);
43
        pw_properties_set(props, "sink_properties", NULL);
44
    }
45
-   if (module_args_to_audioinfo(impl, props, &info) < 0) {
46
+   if (module_args_to_audioinfo(module->impl, props, &info) < 0) {
47
        res = -EINVAL;
48
        goto out;
49
    }
50
@@ -212,30 +209,23 @@
51
        pw_properties_set(stream_props, PW_KEY_AUDIO_FORMAT, format_id2name(id));
52
    }
53
 
54
-   module = module_new(impl, sizeof(*d));
55
-   if (module == NULL) {
56
-       res = -errno;
57
-       goto out;
58
-   }
59
-
60
-   module->props = props;
61
-   d = module->user_data;
62
    d->module = module;
63
    d->stream_props = stream_props;
64
 
65
    pw_properties_fetch_uint32(props, "latency_msec", &d->latency_msec);
66
 
67
-   return module;
68
+   return 0;
69
 out:
70
-   pw_properties_free(props);
71
    pw_properties_free(stream_props);
72
-   errno = -res;
73
-   return NULL;
74
+
75
+   return res;
76
 }
77
 
78
 DEFINE_MODULE_INFO(module_tunnel_sink) = {
79
    .name = "module-tunnel-sink",
80
-   .create = create_module_tunnel_sink,
81
+   .prepare = module_tunnel_sink_prepare,
82
    .load = module_tunnel_sink_load,
83
    .unload = module_tunnel_sink_unload,
84
+   .properties = &SPA_DICT_INIT_ARRAY(module_tunnel_sink_info),
85
+   .data_size = sizeof(struct module_tunnel_sink_data),
86
 };
87
pipewire-0.3.51.tar.gz/src/modules/module-protocol-pulse/modules/module-tunnel-source.c -> pipewire-0.3.52.tar.gz/src/modules/module-protocol-pulse/modules/module-tunnel-source.c Changed
86
 
1
@@ -81,7 +81,7 @@
2
    fprintf(f, "{");
3
    pw_properties_serialize_dict(f, &module->props->dict, 0);
4
    fprintf(f, " pulse.server.address = \"%s\" ", server);
5
-   fprintf(f, " tunnel.mode = capture ");
6
+   fprintf(f, " tunnel.mode = source ");
7
    if (data->latency_msec > 0)
8
        fprintf(f, " pulse.latency = %u ", data->latency_msec);
9
    fprintf(f, " stream.props = {");
10
@@ -149,25 +149,22 @@
11
    pw_properties_set(props, SPA_KEY_AUDIO_POSITION, s);
12
 }
13
 
14
-struct module *create_module_tunnel_source(struct impl *impl, const char *argument)
15
+static int module_tunnel_source_prepare(struct module * const module)
16
 {
17
-   struct module *module;
18
-   struct module_tunnel_source_data *d;
19
-   struct pw_properties *props = NULL, *stream_props = NULL;
20
+   struct module_tunnel_source_data * const d = module->user_data;
21
+   struct pw_properties * const props = module->props;
22
+   struct pw_properties *stream_props = NULL;
23
    const char *str, *server, *remote_source_name;
24
    struct spa_audio_info_raw info = { 0 };
25
    int res;
26
 
27
    PW_LOG_TOPIC_INIT(mod_topic);
28
 
29
-   props = pw_properties_new_dict(&SPA_DICT_INIT_ARRAY(module_tunnel_source_info));
30
    stream_props = pw_properties_new(NULL, NULL);
31
-   if (props == NULL || stream_props == NULL) {
32
+   if (stream_props == NULL) {
33
        res = -ENOMEM;
34
        goto out;
35
    }
36
-   if (argument)
37
-       module_args_add_props(props, argument);
38
 
39
    remote_source_name = pw_properties_get(props, "source");
40
    if (remote_source_name)
41
@@ -195,37 +192,30 @@
42
        module_args_add_props(stream_props, str);
43
        pw_properties_set(props, "source_properties", NULL);
44
    }
45
-   if (module_args_to_audioinfo(impl, props, &info) < 0) {
46
+   if (module_args_to_audioinfo(module->impl, props, &info) < 0) {
47
        res = -EINVAL;
48
        goto out;
49
    }
50
 
51
    audio_info_to_props(&info, stream_props);
52
 
53
-   module = module_new(impl, sizeof(*d));
54
-   if (module == NULL) {
55
-       res = -errno;
56
-       goto out;
57
-   }
58
-
59
-   module->props = props;
60
-   d = module->user_data;
61
    d->module = module;
62
    d->stream_props = stream_props;
63
 
64
    pw_properties_fetch_uint32(props, "latency_msec", &d->latency_msec);
65
 
66
-   return module;
67
+   return 0;
68
 out:
69
-   pw_properties_free(props);
70
    pw_properties_free(stream_props);
71
-   errno = -res;
72
-   return NULL;
73
+
74
+   return res;
75
 }
76
 
77
 DEFINE_MODULE_INFO(module_tunnel_source) = {
78
    .name = "module-tunnel-source",
79
-   .create = create_module_tunnel_source,
80
+   .prepare = module_tunnel_source_prepare,
81
    .load = module_tunnel_source_load,
82
    .unload = module_tunnel_source_unload,
83
+   .properties = &SPA_DICT_INIT_ARRAY(module_tunnel_source_info),
84
+   .data_size = sizeof(struct module_tunnel_source_data),
85
 };
86
pipewire-0.3.51.tar.gz/src/modules/module-protocol-pulse/modules/module-x11-bell.c -> pipewire-0.3.52.tar.gz/src/modules/module-protocol-pulse/modules/module-x11-bell.c Changed
61
 
1
@@ -100,6 +100,16 @@
2
    return 0;
3
 }
4
 
5
+static int module_x11_bell_prepare(struct module * const module)
6
+{
7
+   PW_LOG_TOPIC_INIT(mod_topic);
8
+
9
+   struct module_x11_bell_data * const data = module->user_data;
10
+   data->module = module;
11
+
12
+   return 0;
13
+}
14
+
15
 static const struct spa_dict_item module_x11_bell_info = {
16
    { PW_KEY_MODULE_AUTHOR, "Wim Taymans <wim.taymans@gmail.com>" },
17
    { PW_KEY_MODULE_DESCRIPTION, "X11 bell interceptor" },
18
@@ -110,39 +120,11 @@
19
    { PW_KEY_MODULE_VERSION, PACKAGE_VERSION },
20
 };
21
 
22
-struct module *create_module_x11_bell(struct impl *impl, const char *argument)
23
-{
24
-   struct module *module;
25
-   struct pw_properties *props = NULL;
26
-   int res;
27
-
28
-   PW_LOG_TOPIC_INIT(mod_topic);
29
-
30
-   props = pw_properties_new_dict(&SPA_DICT_INIT_ARRAY(module_x11_bell_info));
31
-   if (props == NULL) {
32
-       res = -EINVAL;
33
-       goto out;
34
-   }
35
-   if (argument)
36
-       module_args_add_props(props, argument);
37
-
38
-   module = module_new(impl, sizeof(struct module_x11_bell_data));
39
-   if (module == NULL) {
40
-       res = -errno;
41
-       goto out;
42
-   }
43
-   module->props = props;
44
-
45
-   return module;
46
-out:
47
-   pw_properties_free(props);
48
-   errno = -res;
49
-   return NULL;
50
-}
51
-
52
 DEFINE_MODULE_INFO(module_x11_bell) = {
53
    .name = "module-x11-bell",
54
-   .create = create_module_x11_bell,
55
+   .prepare = module_x11_bell_prepare,
56
    .load = module_x11_bell_load,
57
    .unload = module_x11_bell_unload,
58
+   .properties = &SPA_DICT_INIT_ARRAY(module_x11_bell_info),
59
+   .data_size = sizeof(struct module_x11_bell_data),
60
 };
61
pipewire-0.3.51.tar.gz/src/modules/module-protocol-pulse/modules/module-zeroconf-discover.c -> pipewire-0.3.52.tar.gz/src/modules/module-protocol-pulse/modules/module-zeroconf-discover.c Changed
53
 
1
@@ -92,44 +92,22 @@
2
    { PW_KEY_MODULE_VERSION, PACKAGE_VERSION },
3
 };
4
 
5
-struct module *create_module_zeroconf_discover(struct impl *impl, const char *argument)
6
+static int module_zeroconf_discover_prepare(struct module * const module)
7
 {
8
-   struct module *module;
9
-   struct module_zeroconf_discover_data *d;
10
-   struct pw_properties *props = NULL;
11
-   int res;
12
-
13
    PW_LOG_TOPIC_INIT(mod_topic);
14
 
15
-   props = pw_properties_new_dict(&SPA_DICT_INIT_ARRAY(module_zeroconf_discover_info));
16
-   if (props == NULL) {
17
-       res = -errno;
18
-       goto out;
19
-   }
20
-   if (argument != NULL)
21
-       module_args_add_props(props, argument);
22
+   struct module_zeroconf_discover_data * const data = module->user_data;
23
+   data->module = module;
24
 
25
-   module = module_new(impl, sizeof(*d));
26
-   if (module == NULL) {
27
-       res = -errno;
28
-       goto out;
29
-   }
30
-
31
-   module->props = props;
32
-   d = module->user_data;
33
-   d->module = module;
34
-
35
-   return module;
36
-out:
37
-   pw_properties_free(props);
38
-   errno = -res;
39
-   return NULL;
40
+   return 0;
41
 }
42
 
43
 DEFINE_MODULE_INFO(module_zeroconf_discover) = {
44
    .name = "module-zeroconf-discover",
45
    .load_once = true,
46
-   .create = create_module_zeroconf_discover,
47
+   .prepare = module_zeroconf_discover_prepare,
48
    .load = module_zeroconf_discover_load,
49
    .unload = module_zeroconf_discover_unload,
50
+   .properties = &SPA_DICT_INIT_ARRAY(module_zeroconf_discover_info),
51
+   .data_size = sizeof(struct module_zeroconf_discover_data),
52
 };
53
pipewire-0.3.51.tar.gz/src/modules/module-protocol-pulse/modules/module-zeroconf-publish.c -> pipewire-0.3.52.tar.gz/src/modules/module-protocol-pulse/modules/module-zeroconf-publish.c Changed
79
 
1
@@ -545,10 +545,20 @@
2
 static void manager_added(void *d, struct pw_manager_object *o)
3
 {
4
    struct service *s;
5
+   struct pw_node_info *info;
6
+   const char *str;
7
 
8
    if (!pw_manager_object_is_sink(o) && !pw_manager_object_is_source(o))
9
        return;
10
 
11
+   info = o->info;
12
+   if (info == NULL || info->props == NULL)
13
+       return;
14
+
15
+   if ((str = spa_dict_lookup(info->props, PW_KEY_NODE_NETWORK)) != NULL &&
16
+       spa_atob(str))
17
+       return;
18
+
19
    s = create_service(d, o);
20
    if (s == NULL)
21
        return;
22
@@ -637,46 +647,24 @@
23
    { PW_KEY_MODULE_VERSION, PACKAGE_VERSION },
24
 };
25
 
26
-struct module *create_module_zeroconf_publish(struct impl *impl, const char *argument)
27
+static int module_zeroconf_publish_prepare(struct module * const module)
28
 {
29
-   struct module *module;
30
-   struct module_zeroconf_publish_data *d;
31
-   struct pw_properties *props = NULL;
32
-   int res;
33
-
34
    PW_LOG_TOPIC_INIT(mod_topic);
35
 
36
-   props = pw_properties_new_dict(&SPA_DICT_INIT_ARRAY(module_zeroconf_publish_info));
37
-   if (!props) {
38
-       res = -errno;
39
-       goto out;
40
-   }
41
-   if (argument)
42
-       module_args_add_props(props, argument);
43
+   struct module_zeroconf_publish_data * const data = module->user_data;
44
+   data->module = module;
45
+   data->port = pw_properties_get_uint32(module->props, "port", PW_PROTOCOL_PULSE_DEFAULT_PORT);
46
+   spa_list_init(&data->pending);
47
+   spa_list_init(&data->published);
48
 
49
-   module = module_new(impl, sizeof(*d));
50
-   if (module == NULL) {
51
-       res = -errno;
52
-       goto out;
53
-   }
54
-
55
-   module->props = props;
56
-   d = module->user_data;
57
-   d->module = module;
58
-   d->port = pw_properties_get_uint32(props, "port", PW_PROTOCOL_PULSE_DEFAULT_PORT);
59
-   spa_list_init(&d->pending);
60
-   spa_list_init(&d->published);
61
-
62
-   return module;
63
-out:
64
-   pw_properties_free(props);
65
-   errno = -res;
66
-   return NULL;
67
+   return 0;
68
 }
69
 
70
 DEFINE_MODULE_INFO(module_zeroconf_publish) = {
71
    .name = "module-zeroconf-publish",
72
-   .create = create_module_zeroconf_publish,
73
+   .prepare = module_zeroconf_publish_prepare,
74
    .load = module_zeroconf_publish_load,
75
    .unload = module_zeroconf_publish_unload,
76
+   .properties = &SPA_DICT_INIT_ARRAY(module_zeroconf_publish_info),
77
+   .data_size = sizeof(struct module_zeroconf_publish_data),
78
 };
79
pipewire-0.3.51.tar.gz/src/modules/module-protocol-pulse/pulse-server.c -> pipewire-0.3.52.tar.gz/src/modules/module-protocol-pulse/pulse-server.c Changed
201
 
1
@@ -87,12 +87,22 @@
2
 #define DEFAULT_POSITION   " FL FR "
3
 
4
 #define MAX_FORMATS    32
5
+/* The max amount of data we send in one block when capturing. In PulseAudio this
6
+ * size is derived from the mempool PA_MEMPOOL_SLOT_SIZE */
7
+#define MAX_FRAGSIZE   (64*1024)
8
+
9
+#define TEMPORARY_MOVE_TIMEOUT (SPA_NSEC_PER_SEC)
10
 
11
 bool debug_messages = false;
12
 
13
 struct latency_offset_data {
14
    int64_t prev_latency_offset;
15
-   unsigned int initialized:1;
16
+   uint8_t initialized:1;
17
+};
18
+
19
+struct temporary_move_data {
20
+   uint32_t peer_index;
21
+   uint8_t used:1;
22
 };
23
 
24
 static struct sample *find_sample(struct impl *impl, uint32_t index, const char *name)
25
@@ -256,6 +266,75 @@
26
    return 0;
27
 }
28
 
29
+static uint32_t get_temporary_move_target(struct client *client, struct pw_manager_object *o)
30
+{
31
+   struct temporary_move_data *d;
32
+
33
+   d = pw_manager_object_get_data(o, "temporary_move_data");
34
+   if (d == NULL || d->peer_index == SPA_ID_INVALID)
35
+       return SPA_ID_INVALID;
36
+
37
+   pw_log_debug("%s using temporary move target for index:%d -> index:%d",
38
+           client->name, o->index, d->peer_index);
39
+   d->used = true;
40
+   return d->peer_index;
41
+}
42
+
43
+static void set_temporary_move_target(struct client *client, struct pw_manager_object *o, uint32_t index)
44
+{
45
+   struct temporary_move_data *d;
46
+
47
+   if (!pw_manager_object_is_sink_input(o) && !pw_manager_object_is_source_output(o))
48
+       return;
49
+
50
+   if (index == SPA_ID_INVALID) {
51
+       d = pw_manager_object_get_data(o, "temporary_move_data");
52
+       if (d == NULL)
53
+           return;
54
+       if (d->peer_index != SPA_ID_INVALID)
55
+           pw_log_debug("cleared temporary move target for index:%d", o->index);
56
+       d->peer_index = SPA_ID_INVALID;
57
+       d->used = false;
58
+       return;
59
+   }
60
+
61
+   d = pw_manager_object_add_temporary_data(o, "temporary_move_data",
62
+           sizeof(struct temporary_move_data),
63
+           TEMPORARY_MOVE_TIMEOUT);
64
+   if (d == NULL)
65
+       return;
66
+
67
+   pw_log_debug("%s set temporary move target for index:%d to index:%d",
68
+           client->name, o->index, index);
69
+   d->peer_index = index;
70
+   d->used = false;
71
+}
72
+
73
+static void temporary_move_target_timeout(struct client *client, struct pw_manager_object *o)
74
+{
75
+   struct temporary_move_data *d = pw_manager_object_get_data(o, "temporary_move_data");
76
+   struct pw_manager_object *peer;
77
+
78
+   /*
79
+    * Send change event if the temporary data was used, and the peer
80
+    * is not what we claimed.
81
+    */
82
+
83
+   if (d == NULL || d->peer_index == SPA_ID_INVALID || !d->used)
84
+       goto done;
85
+
86
+   peer = find_linked(client->manager, o->id, pw_manager_object_is_sink_input(o) ?
87
+           PW_DIRECTION_OUTPUT : PW_DIRECTION_INPUT);
88
+   if (peer == NULL || peer->index != d->peer_index) {
89
+       pw_log_debug("%s temporary move timeout for index:%d, send change event",
90
+               client->name, o->index);
91
+       send_object_event(client, o, SUBSCRIPTION_EVENT_CHANGE);
92
+   }
93
+
94
+done:
95
+   set_temporary_move_target(client, o, SPA_ID_INVALID);
96
+}
97
+
98
 static struct pw_manager_object *find_device(struct client *client,
99
        uint32_t index, const char *name, bool sink, bool *is_monitor);
100
 
101
@@ -371,7 +450,11 @@
102
    uint32_t frame_size, max_prebuf, minreq, latency, max_latency;
103
    struct defs *defs = &s->impl->defs;
104
 
105
-   frame_size = s->frame_size;
106
+   if ((frame_size = s->frame_size) == 0)
107
+       frame_size = sample_spec_frame_size(&s->ss);
108
+   if (frame_size == 0)
109
+       frame_size = 4;
110
+
111
    minreq = frac_to_bytes_round_up(s->min_req, &s->ss);
112
    max_latency = defs->quantum_limit * frame_size;
113
 
114
@@ -503,6 +586,7 @@
115
 
116
    missing = stream_pop_missing(stream);
117
    stream->index = id_to_index(manager, stream->id);
118
+   stream->lat_usec = lat_usec;
119
 
120
    pw_log_info("%s reply CREATE_PLAYBACK_STREAM tag:%u index:%u missing:%u lat:%"PRIu64,
121
            client->name, stream->create_tag, stream->index, missing, lat_usec);
122
@@ -562,7 +646,10 @@
123
 {
124
    uint32_t frame_size, minfrag, latency;
125
 
126
-   frame_size = s->frame_size;
127
+   if ((frame_size = s->frame_size) == 0)
128
+       frame_size = sample_spec_frame_size(&s->ss);
129
+   if (frame_size == 0)
130
+       frame_size = 4;
131
 
132
    if (attr->maxlength == (uint32_t) -1 || attr->maxlength > MAXLENGTH)
133
        attr->maxlength = MAXLENGTH;
134
@@ -646,6 +733,7 @@
135
    lat_usec = set_record_buffer_attr(stream, &stream->attr);
136
 
137
    stream->index = id_to_index(manager, stream->id);
138
+   stream->lat_usec = lat_usec;
139
 
140
    pw_log_info("%s reply CREATE_RECORD_STREAM tag:%u index:%u latency:%"PRIu64,
141
            client->name, stream->create_tag, stream->index, lat_usec);
142
@@ -710,6 +798,7 @@
143
 
144
 static int reply_create_stream(struct stream *stream, struct pw_manager_object *peer)
145
 {
146
+   stream->peer_index = peer->index;
147
    return stream->direction == PW_DIRECTION_OUTPUT ?
148
            reply_create_playback_stream(stream, peer) :
149
            reply_create_record_stream(stream, peer);
150
@@ -740,17 +829,36 @@
151
    }
152
 
153
    if (spa_streq(o->type, PW_TYPE_INTERFACE_Link)) {
154
-       struct stream *s;
155
+       struct stream *s, *t;
156
        struct pw_manager_object *peer = NULL;
157
-       spa_list_for_each(s, &client->pending_streams, link) {
158
-           peer = find_linked(manager, s->id, s->direction);
159
-           if (peer)
160
-               break;
161
-       }
162
-       if (peer) {
163
-           reply_create_stream(s, peer);
164
-           spa_list_remove(&s->link);
165
-           s->pending = false;
166
+       union pw_map_item *item;
167
+       pw_array_for_each(item, &client->streams.items) {
168
+           struct stream *s = item->data;
169
+           const char *peer_name;
170
+
171
+           if (pw_map_item_is_free(item) || s->pending)
172
+               continue;
173
+           if (s->peer_index == SPA_ID_INVALID)
174
+               continue;
175
+
176
+           peer = find_peer_for_link(manager, o, s->id, s->direction);
177
+           if (peer == NULL || peer->props == NULL ||
178
+               peer->index == s->peer_index)
179
+               continue;
180
+
181
+           s->peer_index = peer->index;
182
+
183
+           peer_name = pw_properties_get(peer->props, PW_KEY_NODE_NAME);
184
+           if (peer_name != NULL)
185
+               stream_send_moved(s, peer->index, peer_name);
186
+       }
187
+       spa_list_for_each_safe(s, t, &client->pending_streams, link) {
188
+           peer = find_peer_for_link(manager, o, s->id, s->direction);
189
+           if (peer) {
190
+               reply_create_stream(s, peer);
191
+               spa_list_remove(&s->link);
192
+               s->pending = false;
193
+           }
194
        }
195
    }
196
 
197
@@ -766,6 +874,8 @@
198
 
199
    send_object_event(client, o, SUBSCRIPTION_EVENT_CHANGE);
200
 
201
pipewire-0.3.51.tar.gz/src/modules/module-protocol-pulse/stream.c -> pipewire-0.3.52.tar.gz/src/modules/module-protocol-pulse/stream.c Changed
62
 
1
@@ -82,6 +82,8 @@
2
    stream->attr = *attr;
3
    spa_ringbuffer_init(&stream->ring);
4
 
5
+   stream->peer_index = SPA_ID_INVALID;
6
+
7
    parse_frac(client->props, "pulse.min.req", &defs->min_req, &stream->min_req);
8
    parse_frac(client->props, "pulse.min.frag", &defs->min_frag, &stream->min_frag);
9
    parse_frac(client->props, "pulse.min.quantum", &defs->min_quantum, &stream->min_quantum);
10
@@ -359,3 +361,51 @@
11
    }
12
    return 0;
13
 }
14
+
15
+int stream_send_moved(struct stream *stream, uint32_t peer_index, const char *peer_name)
16
+{
17
+   struct client *client = stream->client;
18
+   struct impl *impl = client->impl;
19
+   struct message *reply;
20
+   uint32_t command;
21
+
22
+   command = stream->direction == PW_DIRECTION_OUTPUT ?
23
+       COMMAND_PLAYBACK_STREAM_MOVED :
24
+       COMMAND_RECORD_STREAM_MOVED;
25
+
26
+   pw_log_info("client %p %s: stream %p %s channel:%u",
27
+           client, client->name, stream, commandscommand.name,
28
+           stream->channel);
29
+
30
+   if (client->version < 12)
31
+       return 0;
32
+
33
+   reply = message_alloc(impl, -1, 0);
34
+   message_put(reply,
35
+       TAG_U32, command,
36
+       TAG_U32, -1,
37
+       TAG_U32, stream->channel,
38
+       TAG_U32, peer_index,
39
+       TAG_STRING, peer_name,
40
+       TAG_BOOLEAN, false,     /* suspended */
41
+       TAG_INVALID);
42
+
43
+   if (client->version >= 13) {
44
+       if (command == COMMAND_PLAYBACK_STREAM_MOVED) {
45
+           message_put(reply,
46
+               TAG_U32, stream->attr.maxlength,
47
+               TAG_U32, stream->attr.tlength,
48
+               TAG_U32, stream->attr.prebuf,
49
+               TAG_U32, stream->attr.minreq,
50
+               TAG_USEC, stream->lat_usec,
51
+               TAG_INVALID);
52
+       } else {
53
+           message_put(reply,
54
+               TAG_U32, stream->attr.maxlength,
55
+               TAG_U32, stream->attr.fragsize,
56
+               TAG_USEC, stream->lat_usec,
57
+               TAG_INVALID);
58
+       }
59
+   }
60
+   return client_queue_message(client, reply);
61
+}
62
pipewire-0.3.51.tar.gz/src/modules/module-protocol-pulse/stream.h -> pipewire-0.3.52.tar.gz/src/modules/module-protocol-pulse/stream.h Changed
25
 
1
@@ -60,6 +60,8 @@
2
    uint32_t id;        /* id of global */
3
    uint32_t index;     /* index */
4
 
5
+   uint32_t peer_index;
6
+
7
    struct impl *impl;
8
    struct client *client;
9
    enum stream_type type;
10
@@ -97,6 +99,7 @@
11
    struct buffer_attr attr;
12
    uint32_t frame_size;
13
    uint32_t rate;
14
+   uint64_t lat_usec;
15
 
16
    struct volume volume;
17
    bool muted;
18
@@ -127,5 +130,6 @@
19
 int stream_send_started(struct stream *stream);
20
 int stream_send_request(struct stream *stream);
21
 int stream_update_minreq(struct stream *stream, uint32_t minreq);
22
+int stream_send_moved(struct stream *stream, uint32_t peer_index, const char *peer_name);
23
 
24
 #endif /* PULSER_SERVER_STREAM_H */
25
pipewire-0.3.51.tar.gz/src/modules/module-protocol-simple.c -> pipewire-0.3.52.tar.gz/src/modules/module-protocol-simple.c Changed
51
 
1
@@ -132,7 +132,7 @@
2
 #define DEFAULT_SERVER " \"tcp:"SPA_STRINGIFY(DEFAULT_PORT)"\" "
3
 
4
 #define DEFAULT_FORMAT "S16"
5
-#define DEFAULT_RATE "44100"
6
+#define DEFAULT_RATE 44100
7
 #define DEFAULT_CHANNELS 2
8
 #define DEFAULT_POSITION " FL FR "
9
 #define DEFAULT_LATENCY "1024/44100"
10
@@ -143,12 +143,12 @@
11
            " playback=<bool>  "                        \
12
            " remote.name=<remote>  "                   \
13
            " node.latency=<num/denom, default:"DEFAULT_LATENCY">  "    \
14
-           " node.rate=<1/rate, default:1/"DEFAULT_RATE">  "   \
15
+           " node.rate=<1/rate, default:1/"SPA_STRINGIFY(DEFAULT_RATE)">  "    \
16
            " capture.node=<source-target>  stream.capture.sink=true  " \
17
            " playback.node=<sink-target>  "                \
18
-           " audio.rate=<sample-rate, default:"DEFAULT_RATE">  "       \
19
+           " audio.rate=<sample-rate, default:"SPA_STRINGIFY(DEFAULT_RATE)">  "        \
20
            " audio.format=<format, default:"DEFAULT_FORMAT">  "        \
21
-           " audio.channels=<channels, default: 2>  "  \
22
+           " audio.channels=<channels, default: "SPA_STRINGIFY(DEFAULT_CHANNELS)">  "  \
23
            " audio.position=<position, default:"DEFAULT_POSITION">  "  \
24
            " server.address=< tcp:<ip>:<port>,... , default:"DEFAULT_SERVER">" \
25
 
26
@@ -310,11 +310,8 @@
27
    }
28
    d = &buf->buffer->datas0;
29
 
30
-   size = d->chunk->size;
31
-   offset = d->chunk->offset;
32
-
33
-   if (size + offset > d->maxsize)
34
-       size = d->maxsize - SPA_MIN(offset, d->maxsize);
35
+   offset = SPA_MIN(d->chunk->offset, d->maxsize);
36
+   size = SPA_MIN(d->chunk->size, d->maxsize - offset);
37
 
38
    while (size > 0) {
39
        res = send(client->source->fd,
40
@@ -807,9 +804,7 @@
41
        pw_log_error("invalid format '%s'", str);
42
        return -EINVAL;
43
    }
44
-   if ((str = pw_properties_get(impl->props, "audio.rate")) == NULL)
45
-       str = DEFAULT_RATE;
46
-   impl->info.rate = atoi(str);
47
+   impl->info.rate = pw_properties_get_uint32(impl->props, "audio.rate", DEFAULT_RATE);
48
    if (impl->info.rate == 0) {
49
        pw_log_error("invalid rate '%s'", str);
50
        return -EINVAL;
51
pipewire-0.3.51.tar.gz/src/modules/module-pulse-tunnel.c -> pipewire-0.3.52.tar.gz/src/modules/module-pulse-tunnel.c Changed
140
 
1
@@ -68,8 +68,8 @@
2
  *
3
  * ## Module Options
4
  *
5
- * - `tunnel.mode`: the desired tunnel to create, must be `capture` or `playback`.
6
- *                  (Default `playback`)
7
+ * - `tunnel.mode`: the desired tunnel to create, must be `source` or `sink`.
8
+ *                  (Default `sink`)
9
  * - `pulse.server.address`: the address of the PulseAudio server to tunnel to.
10
  * - `pulse.latency`: the latency to end-to-end latency in milliseconds to
11
  *                    maintain (Default 200ms).
12
@@ -97,7 +97,7 @@
13
  * context.modules = 
14
  * {   name = libpipewire-module-pulse-tunnel
15
  *     args = {
16
- *         tunnel.mode = playback
17
+ *         tunnel.mode = sink
18
  *         # Set the remote address to tunnel to
19
  *         pulse.server.address = "tcp:192.168.1.126"
20
  *         #audio.rate=<sample rate>
21
@@ -128,7 +128,7 @@
22
            " audio.position=<channel map>  "           \
23
            "pulse.server.address=<address> "           \
24
            "pulse.latency=<latency in msec> "          \
25
-           " tunnel.mode=capture|playback "            \
26
+           " tunnel.mode=source|sink "             \
27
            " stream.props=<properties>  "
28
 
29
 
30
@@ -147,8 +147,8 @@
31
 struct impl {
32
    struct pw_context *context;
33
 
34
-#define MODE_PLAYBACK  0
35
-#define MODE_CAPTURE   1
36
+#define MODE_SINK  0
37
+#define MODE_SOURCE    1
38
    uint32_t mode;
39
    struct pw_properties *props;
40
 
41
@@ -193,7 +193,7 @@
42
    pa_threaded_mainloop_lock(impl->pa_mainloop);
43
 
44
    pw_log_debug("corking: %d", cork);
45
-   if (cork && impl->mode == MODE_PLAYBACK) {
46
+   if (cork && impl->mode == MODE_SINK) {
47
        /* When the sink becomes suspended (which is the only case where we
48
         * cork the stream), we don't want to keep any old data around, because
49
         * the old data is most likely unrelated to the audio that will be
50
@@ -246,7 +246,7 @@
51
    struct pw_buffer *buf;
52
    struct spa_data *bd;
53
    int32_t filled;
54
-   uint32_t write_index, size;
55
+   uint32_t write_index, offs, size;
56
 
57
    if ((buf = pw_stream_dequeue_buffer(impl->stream)) == NULL) {
58
        pw_log_debug("out of buffers: %m");
59
@@ -254,7 +254,9 @@
60
    }
61
 
62
    bd = &buf->buffer->datas0;
63
-   size = SPA_MIN(bd->chunk->size, RINGBUFFER_SIZE);
64
+   offs = SPA_MIN(bd->chunk->offset, bd->maxsize);
65
+   size = SPA_MIN(bd->chunk->size, bd->maxsize - offs);
66
+   size = SPA_MIN(size, RINGBUFFER_SIZE);
67
 
68
    filled = spa_ringbuffer_get_write_index(&impl->ring, &write_index);
69
 
70
@@ -281,8 +283,8 @@
71
    }
72
    spa_ringbuffer_write_data(&impl->ring,
73
                impl->buffer, RINGBUFFER_SIZE,
74
-                                write_index & RINGBUFFER_MASK,
75
-                                SPA_PTROFF(bd->data, bd->chunk->offset, void),
76
+               write_index & RINGBUFFER_MASK,
77
+               SPA_PTROFF(bd->data, offs, void),
78
                size);
79
    write_index += size;
80
    spa_ringbuffer_write_update(&impl->ring, write_index);
81
@@ -376,7 +378,7 @@
82
    if (impl->stream == NULL)
83
        return -errno;
84
 
85
-   if (impl->mode == MODE_CAPTURE) {
86
+   if (impl->mode == MODE_SOURCE) {
87
        pw_stream_add_listener(impl->stream,
88
                &impl->stream_listener,
89
                &capture_stream_events, impl);
90
@@ -392,14 +394,14 @@
91
            SPA_PARAM_EnumFormat, &impl->info);
92
 
93
    spa_zero(latency);
94
-   latency.direction = impl->mode == MODE_CAPTURE ? PW_DIRECTION_OUTPUT : PW_DIRECTION_INPUT;
95
+   latency.direction = impl->mode == MODE_SOURCE ? PW_DIRECTION_OUTPUT : PW_DIRECTION_INPUT;
96
    latency.min_ns = latency.max_ns = impl->latency_msec * SPA_NSEC_PER_MSEC;
97
 
98
    paramsn_params++ = spa_latency_build(&b,
99
            SPA_PARAM_Latency, &latency);
100
 
101
    if ((res = pw_stream_connect(impl->stream,
102
-           impl->mode == MODE_CAPTURE ? PW_DIRECTION_OUTPUT : PW_DIRECTION_INPUT,
103
+           impl->mode == MODE_SOURCE ? PW_DIRECTION_OUTPUT : PW_DIRECTION_INPUT,
104
            PW_ID_ANY,
105
            PW_STREAM_FLAG_AUTOCONNECT |
106
            PW_STREAM_FLAG_MAP_BUFFERS |
107
@@ -665,7 +667,7 @@
108
    /* half in our buffer, half in the network + remote */
109
    impl->target_buffer = latency_bytes / 2;
110
 
111
-   if (impl->mode == MODE_CAPTURE) {
112
+   if (impl->mode == MODE_SOURCE) {
113
        bufferattr.fragsize = latency_bytes / 2;
114
 
115
        res = pa_stream_connect_record(impl->pa_stream,
116
@@ -931,10 +933,10 @@
117
    spa_dll_init(&impl->dll);
118
 
119
    if ((str = pw_properties_get(props, "tunnel.mode")) != NULL) {
120
-       if (spa_streq(str, "capture")) {
121
-           impl->mode = MODE_CAPTURE;
122
-       } else if (spa_streq(str, "playback")) {
123
-           impl->mode = MODE_PLAYBACK;
124
+       if (spa_streq(str, "source")) {
125
+           impl->mode = MODE_SOURCE;
126
+       } else if (spa_streq(str, "sink")) {
127
+           impl->mode = MODE_SINK;
128
        } else {
129
            pw_log_error("invalid tunnel.mode '%s'", str);
130
            res = -EINVAL;
131
@@ -952,7 +954,7 @@
132
 
133
    if (pw_properties_get(props, PW_KEY_MEDIA_CLASS) == NULL)
134
        pw_properties_set(props, PW_KEY_MEDIA_CLASS,
135
-               impl->mode == MODE_PLAYBACK ?
136
+               impl->mode == MODE_SINK ?
137
                    "Audio/Sink" : "Audio/Source");
138
 
139
    if ((str = pw_properties_get(props, "stream.props")) != NULL)
140
pipewire-0.3.51.tar.gz/src/modules/module-raop-discover.c -> pipewire-0.3.52.tar.gz/src/modules/module-raop-discover.c Changed
9
 
1
@@ -65,7 +65,6 @@
2
  * context.modules = 
3
  * {   name = libpipewire-raop-discover
4
  *     args = { }
5
- *     }
6
  * }
7
  * 
8
  *\endcode
9
pipewire-0.3.51.tar.gz/src/modules/module-raop-sink.c -> pipewire-0.3.52.tar.gz/src/modules/module-raop-sink.c Changed
54
 
1
@@ -101,7 +101,7 @@
2
 
3
 #define DEFAULT_FORMAT "S16"
4
 #define DEFAULT_RATE 44100
5
-#define DEFAULT_CHANNELS "2"
6
+#define DEFAULT_CHANNELS 2
7
 #define DEFAULT_POSITION " FL FR "
8
 
9
 #define DEFAULT_LATENCY (DEFAULT_RATE*2)
10
@@ -110,8 +110,8 @@
11
            " node.name=<name of the nodes>  "                  \
12
            " node.description=<description of the nodes>  "            \
13
            " audio.format=<format, default:"DEFAULT_FORMAT">  "            \
14
-           " audio.rate=<sample rate, default: 48000>  "               \
15
-           " audio.channels=<number of channels, default:"DEFAULT_CHANNELS">  "    \
16
+           " audio.rate=<sample rate, default: "SPA_STRINGIFY(DEFAuLT_RATE)">  "           \
17
+           " audio.channels=<number of channels, default:"SPA_STRINGIFY(DEFAULT_CHANNELS)">  " \
18
            " audio.position=<channel map, default:"DEFAULT_POSITION">  "       \
19
            " stream.props=<properties>  "
20
 
21
@@ -430,7 +430,7 @@
22
    struct pw_buffer *buf;
23
    struct spa_data *bd;
24
    uint8_t *data;
25
-   uint32_t size;
26
+   uint32_t offs, size;
27
 
28
    if ((buf = pw_stream_dequeue_buffer(impl->stream)) == NULL) {
29
        pw_log_debug("out of buffers: %m");
30
@@ -438,8 +438,10 @@
31
    }
32
 
33
    bd = &buf->buffer->datas0;
34
-   data = SPA_PTROFF(bd->data, bd->chunk->offset, uint8_t);
35
-   size = bd->chunk->size;
36
+
37
+   offs = SPA_MIN(bd->chunk->offset, bd->maxsize);
38
+   size = SPA_MIN(bd->chunk->size, bd->maxsize - offs);
39
+   data = SPA_PTROFF(bd->data, offs, uint8_t);
40
 
41
    while (size > 0 && impl->block_size > 0) {
42
        uint32_t avail, to_fill;
43
@@ -1521,9 +1523,7 @@
44
        pw_log_error("invalid rate '%s'", str);
45
        return -EINVAL;
46
    }
47
-   if ((str = pw_properties_get(props, PW_KEY_AUDIO_CHANNELS)) == NULL)
48
-       str = DEFAULT_CHANNELS;
49
-   info->channels = atoi(str);
50
+   info->channels = pw_properties_get_uint32(props, PW_KEY_AUDIO_CHANNELS, DEFAULT_CHANNELS);
51
    if ((str = pw_properties_get(props, SPA_KEY_AUDIO_POSITION)) == NULL)
52
        str = DEFAULT_POSITION;
53
    parse_position(info, str, strlen(str));
54
pipewire-0.3.51.tar.gz/src/modules/module-roc-sink.c -> pipewire-0.3.52.tar.gz/src/modules/module-roc-sink.c Changed
28
 
1
@@ -162,11 +162,12 @@
2
 
3
    for (i = 0; i < in->buffer->n_datas; i++) {
4
        d = &in->buffer->datasi;
5
-       size = d->chunk->size;
6
-       offset = d->chunk->offset;
7
+
8
+       offset = SPA_MIN(d->chunk->offset, d->maxsize);
9
+       size = SPA_MIN(d->maxsize - offset, d->chunk->size);
10
 
11
        while (size > 0) {
12
-           memset(&frame, 0, sizeof(frame));
13
+           spa_zero(frame);
14
 
15
            frame.samples = SPA_MEMBER(d->data, offset, void);
16
            frame.samples_size = size;
17
@@ -176,8 +177,8 @@
18
                break;
19
            }
20
 
21
-           offset += size;
22
-           size -= size;
23
+           offset += frame.samples_size;
24
+           size -= frame.samples_size;
25
        }
26
    }
27
    pw_stream_queue_buffer(impl->capture, in);
28
pipewire-0.3.51.tar.gz/src/modules/module-session-manager/client-endpoint/client-endpoint.c -> pipewire-0.3.52.tar.gz/src/modules/module-session-manager/client-endpoint/client-endpoint.c Changed
52
 
1
@@ -38,9 +38,11 @@
2
 #define NAME "client-endpoint"
3
 
4
 struct factory_data {
5
-   struct pw_impl_factory *factory;
6
    struct pw_impl_module *module;
7
    struct spa_hook module_listener;
8
+
9
+   struct pw_impl_factory *factory;
10
+   struct spa_hook factory_listener;
11
 };
12
 
13
 static struct endpoint_stream *find_stream(struct client_endpoint *this, uint32_t id)
14
@@ -219,12 +221,27 @@
15
    .create_object = create_object,
16
 };
17
 
18
-static void module_destroy(void *data)
19
+static void factory_destroy(void *data)
20
 {
21
    struct factory_data *d = data;
22
+   spa_hook_remove(&d->factory_listener);
23
+   d->factory = NULL;
24
+   if (d->module)
25
+       pw_impl_module_destroy(d->module);
26
+}
27
 
28
+static const struct pw_impl_factory_events factory_events = {
29
+   PW_VERSION_IMPL_FACTORY_EVENTS,
30
+   .destroy = factory_destroy,
31
+};
32
+
33
+static void module_destroy(void *data)
34
+{
35
+   struct factory_data *d = data;
36
    spa_hook_remove(&d->module_listener);
37
-   pw_impl_factory_destroy(d->factory);
38
+   d->module = NULL;
39
+   if (d->factory)
40
+       pw_impl_factory_destroy(d->factory);
41
 }
42
 
43
 static void module_registered(void *data)
44
@@ -271,6 +288,7 @@
45
    data->module = module;
46
 
47
    pw_impl_factory_set_implementation(factory, &impl_factory, data);
48
+   pw_impl_factory_add_listener(factory, &data->factory_listener, &factory_events, data);
49
 
50
    pw_impl_module_add_listener(module, &data->module_listener, &module_events, data);
51
 
52
pipewire-0.3.51.tar.gz/src/modules/module-session-manager/client-endpoint/endpoint-stream.c -> pipewire-0.3.52.tar.gz/src/modules/module-session-manager/client-endpoint/endpoint-stream.c Changed
19
 
1
@@ -196,7 +196,7 @@
2
            this->params = NULL;
3
        } else {
4
            void *p;
5
-           p = reallocarray(this->params, n_params, sizeof(struct spa_pod*));
6
+           p = pw_reallocarray(this->params, n_params, sizeof(struct spa_pod*));
7
            if (p == NULL) {
8
                free(this->params);
9
                this->params = NULL;
10
@@ -227,7 +227,7 @@
11
                this->info.params = NULL;
12
            } else {
13
                void *p;
14
-               p = reallocarray(this->info.params, info->n_params, sizeof(struct spa_param_info));
15
+               p = pw_reallocarray(this->info.params, info->n_params, sizeof(struct spa_param_info));
16
                if (p == NULL) {
17
                    free(this->info.params);
18
                    this->info.params = NULL;
19
pipewire-0.3.51.tar.gz/src/modules/module-session-manager/client-endpoint/endpoint.c -> pipewire-0.3.52.tar.gz/src/modules/module-session-manager/client-endpoint/endpoint.c Changed
19
 
1
@@ -213,7 +213,7 @@
2
            this->params = NULL;
3
        } else {
4
            void *p;
5
-           p = reallocarray(this->params, n_params, sizeof(struct spa_pod*));
6
+           p = pw_reallocarray(this->params, n_params, sizeof(struct spa_pod*));
7
            if (p == NULL) {
8
                free(this->params);
9
                this->params = NULL;
10
@@ -245,7 +245,7 @@
11
                this->info.params = NULL;
12
            } else {
13
                void *p;
14
-               p = reallocarray(this->info.params, info->n_params, sizeof(struct spa_param_info));
15
+               p = pw_reallocarray(this->info.params, info->n_params, sizeof(struct spa_param_info));
16
                if (p == NULL) {
17
                    free(this->info.params);
18
                    this->info.params = NULL;
19
pipewire-0.3.51.tar.gz/src/modules/module-session-manager/client-session/client-session.c -> pipewire-0.3.52.tar.gz/src/modules/module-session-manager/client-session/client-session.c Changed
52
 
1
@@ -38,9 +38,11 @@
2
 #define NAME "client-session"
3
 
4
 struct factory_data {
5
-   struct pw_impl_factory *factory;
6
    struct pw_impl_module *module;
7
    struct spa_hook module_listener;
8
+
9
+   struct pw_impl_factory *factory;
10
+   struct spa_hook factory_listener;
11
 };
12
 
13
 static struct endpoint_link *find_link(struct client_session *this, uint32_t id)
14
@@ -218,12 +220,27 @@
15
    .create_object = create_object,
16
 };
17
 
18
-static void module_destroy(void *data)
19
+static void factory_destroy(void *data)
20
 {
21
    struct factory_data *d = data;
22
+   spa_hook_remove(&d->factory_listener);
23
+   d->factory = NULL;
24
+   if (d->module)
25
+       pw_impl_module_destroy(d->module);
26
+}
27
 
28
+static const struct pw_impl_factory_events factory_events = {
29
+   PW_VERSION_IMPL_FACTORY_EVENTS,
30
+   .destroy = factory_destroy,
31
+};
32
+
33
+static void module_destroy(void *data)
34
+{
35
+   struct factory_data *d = data;
36
    spa_hook_remove(&d->module_listener);
37
-   pw_impl_factory_destroy(d->factory);
38
+   d->module = NULL;
39
+   if (d->factory)
40
+       pw_impl_factory_destroy(d->factory);
41
 }
42
 
43
 static void module_registered(void *data)
44
@@ -270,6 +287,7 @@
45
    data->module = module;
46
 
47
    pw_impl_factory_set_implementation(factory, &impl_factory, data);
48
+   pw_impl_factory_add_listener(factory, &data->factory_listener, &factory_events, data);
49
 
50
    pw_impl_module_add_listener(module, &data->module_listener, &module_events, data);
51
 
52
pipewire-0.3.51.tar.gz/src/modules/module-session-manager/client-session/endpoint-link.c -> pipewire-0.3.52.tar.gz/src/modules/module-session-manager/client-session/endpoint-link.c Changed
19
 
1
@@ -209,7 +209,7 @@
2
            this->params = NULL;
3
        } else {
4
            void *p;
5
-           p = reallocarray(this->params, n_params, sizeof(struct spa_pod*));
6
+           p = pw_reallocarray(this->params, n_params, sizeof(struct spa_pod*));
7
            if (p == NULL) {
8
                free(this->params);
9
                this->params = NULL;
10
@@ -241,7 +241,7 @@
11
                this->info.params = NULL;
12
            } else {
13
                void *p;
14
-               p = reallocarray(this->info.params, info->n_params, sizeof(struct spa_param_info));
15
+               p = pw_reallocarray(this->info.params, info->n_params, sizeof(struct spa_param_info));
16
                if (p == NULL) {
17
                    free(this->info.params);
18
                    this->info.params = NULL;
19
pipewire-0.3.51.tar.gz/src/modules/module-session-manager/client-session/session.c -> pipewire-0.3.52.tar.gz/src/modules/module-session-manager/client-session/session.c Changed
19
 
1
@@ -196,7 +196,7 @@
2
            this->params = NULL;
3
        } else {
4
            void *p;
5
-           p = reallocarray(this->params, n_params, sizeof(struct spa_pod*));
6
+           p = pw_reallocarray(this->params, n_params, sizeof(struct spa_pod*));
7
            if (p == NULL) {
8
                free(this->params);
9
                this->params = NULL;
10
@@ -222,7 +222,7 @@
11
                this->info.params = NULL;
12
            } else {
13
                void *p;
14
-               p = reallocarray(this->info.params, info->n_params, sizeof(struct spa_param_info));
15
+               p = pw_reallocarray(this->info.params, info->n_params, sizeof(struct spa_param_info));
16
                if (p == NULL) {
17
                    free(this->info.params);
18
                    this->info.params = NULL;
19
pipewire-0.3.51.tar.gz/src/modules/module-session-manager/endpoint-link.c -> pipewire-0.3.52.tar.gz/src/modules/module-session-manager/endpoint-link.c Changed
82
 
1
@@ -78,7 +78,8 @@
2
 
3
 struct factory_data
4
 {
5
-   struct pw_impl_factory *this;
6
+   struct pw_impl_factory *factory;
7
+   struct spa_hook factory_listener;
8
 
9
    struct pw_impl_module *module;
10
    struct spa_hook module_listener;
11
@@ -472,7 +473,7 @@
12
    pw_properties_setf(properties, PW_KEY_CLIENT_ID, "%d",
13
            pw_impl_client_get_info(client)->id);
14
    pw_properties_setf(properties, PW_KEY_FACTORY_ID, "%d",
15
-           pw_impl_factory_get_info(d->this)->id);
16
+           pw_impl_factory_get_info(d->factory)->id);
17
 
18
    result = link_new(pw_impl_client_get_context(client), impl_resource, properties);
19
    if (result == NULL) {
20
@@ -502,20 +503,37 @@
21
    .create_object = create_object,
22
 };
23
 
24
+static void factory_destroy(void *data)
25
+{
26
+   struct factory_data *d = data;
27
+   spa_hook_remove(&d->factory_listener);
28
+   d->factory = NULL;
29
+   if (d->module)
30
+       pw_impl_module_destroy(d->module);
31
+}
32
+
33
+static const struct pw_impl_factory_events factory_events = {
34
+   PW_VERSION_IMPL_FACTORY_EVENTS,
35
+   .destroy = factory_destroy,
36
+};
37
+
38
 static void module_destroy(void *data)
39
 {
40
    struct factory_data *d = data;
41
 
42
    spa_hook_remove(&d->module_listener);
43
    spa_list_remove(&d->export.link);
44
-   pw_impl_factory_destroy(d->this);
45
+   d->module = NULL;
46
+
47
+   if (d->factory)
48
+       pw_impl_factory_destroy(d->factory);
49
 }
50
 
51
 static void module_registered(void *data)
52
 {
53
    struct factory_data *d = data;
54
    struct pw_impl_module *module = d->module;
55
-   struct pw_impl_factory *factory = d->this;
56
+   struct pw_impl_factory *factory = d->factory;
57
    struct spa_dict_item items1;
58
    char id16;
59
    int res;
60
@@ -552,7 +570,7 @@
61
        return -errno;
62
 
63
    data = pw_impl_factory_get_user_data(factory);
64
-   data->this = factory;
65
+   data->factory = factory;
66
    data->module = module;
67
 
68
    pw_impl_factory_set_implementation(factory, &impl_factory, data);
69
@@ -562,10 +580,11 @@
70
    if ((res = pw_context_register_export_type(context, &data->export)) < 0)
71
        goto error;
72
 
73
+   pw_impl_factory_add_listener(factory, &data->factory_listener, &factory_events, data);
74
    pw_impl_module_add_listener(module, &data->module_listener, &module_events, data);
75
 
76
    return 0;
77
 error:
78
-   pw_impl_factory_destroy(data->this);
79
+   pw_impl_factory_destroy(data->factory);
80
    return res;
81
 }
82
pipewire-0.3.51.tar.gz/src/modules/module-session-manager/endpoint-stream.c -> pipewire-0.3.52.tar.gz/src/modules/module-session-manager/endpoint-stream.c Changed
87
 
1
@@ -78,11 +78,12 @@
2
 
3
 struct factory_data
4
 {
5
-   struct pw_impl_factory *this;
6
-
7
    struct pw_impl_module *module;
8
    struct spa_hook module_listener;
9
 
10
+   struct pw_impl_factory *factory;
11
+   struct spa_hook factory_listener;
12
+
13
    struct pw_export_type export;
14
 };
15
 
16
@@ -463,7 +464,7 @@
17
    pw_properties_setf(properties, PW_KEY_CLIENT_ID, "%d",
18
            pw_impl_client_get_info(client)->id);
19
    pw_properties_setf(properties, PW_KEY_FACTORY_ID, "%d",
20
-           pw_impl_factory_get_info(d->this)->id);
21
+           pw_impl_factory_get_info(d->factory)->id);
22
 
23
    result = stream_new(pw_impl_client_get_context(client), impl_resource, properties);
24
    if (result == NULL) {
25
@@ -493,20 +494,37 @@
26
    .create_object = create_object,
27
 };
28
 
29
+static void factory_destroy(void *data)
30
+{
31
+   struct factory_data *d = data;
32
+   spa_hook_remove(&d->factory_listener);
33
+   d->factory = NULL;
34
+   if (d->module)
35
+       pw_impl_module_destroy(d->module);
36
+}
37
+
38
+static const struct pw_impl_factory_events factory_events = {
39
+   PW_VERSION_IMPL_FACTORY_EVENTS,
40
+   .destroy = factory_destroy,
41
+};
42
+
43
 static void module_destroy(void *data)
44
 {
45
    struct factory_data *d = data;
46
 
47
    spa_hook_remove(&d->module_listener);
48
    spa_list_remove(&d->export.link);
49
-   pw_impl_factory_destroy(d->this);
50
+   d->module = NULL;
51
+
52
+   if (d->factory)
53
+       pw_impl_factory_destroy(d->factory);
54
 }
55
 
56
 static void module_registered(void *data)
57
 {
58
    struct factory_data *d = data;
59
    struct pw_impl_module *module = d->module;
60
-   struct pw_impl_factory *factory = d->this;
61
+   struct pw_impl_factory *factory = d->factory;
62
    struct spa_dict_item items1;
63
    char id16;
64
    int res;
65
@@ -543,7 +561,7 @@
66
        return -errno;
67
 
68
    data = pw_impl_factory_get_user_data(factory);
69
-   data->this = factory;
70
+   data->factory = factory;
71
    data->module = module;
72
 
73
    pw_impl_factory_set_implementation(factory, &impl_factory, data);
74
@@ -553,10 +571,11 @@
75
    if ((res = pw_context_register_export_type(context, &data->export)) < 0)
76
        goto error;
77
 
78
+   pw_impl_factory_add_listener(factory, &data->factory_listener, &factory_events, data);
79
    pw_impl_module_add_listener(module, &data->module_listener, &module_events, data);
80
 
81
    return 0;
82
 error:
83
-   pw_impl_factory_destroy(data->this);
84
+   pw_impl_factory_destroy(data->factory);
85
    return res;
86
 }
87
pipewire-0.3.51.tar.gz/src/modules/module-session-manager/endpoint.c -> pipewire-0.3.52.tar.gz/src/modules/module-session-manager/endpoint.c Changed
87
 
1
@@ -78,11 +78,12 @@
2
 
3
 struct factory_data
4
 {
5
-   struct pw_impl_factory *this;
6
-
7
    struct pw_impl_module *module;
8
    struct spa_hook module_listener;
9
 
10
+   struct pw_impl_factory *factory;
11
+   struct spa_hook factory_listener;
12
+
13
    struct pw_export_type export;
14
 };
15
 
16
@@ -472,7 +473,7 @@
17
    pw_properties_setf(properties, PW_KEY_CLIENT_ID, "%d",
18
            pw_impl_client_get_info(client)->id);
19
    pw_properties_setf(properties, PW_KEY_FACTORY_ID, "%d",
20
-           pw_impl_factory_get_info(d->this)->id);
21
+           pw_impl_factory_get_info(d->factory)->id);
22
 
23
    result = endpoint_new(pw_impl_client_get_context(client), impl_resource, properties);
24
    if (result == NULL) {
25
@@ -502,20 +503,37 @@
26
    .create_object = create_object,
27
 };
28
 
29
+static void factory_destroy(void *data)
30
+{
31
+   struct factory_data *d = data;
32
+   spa_hook_remove(&d->factory_listener);
33
+   d->factory = NULL;
34
+   if (d->module)
35
+       pw_impl_module_destroy(d->module);
36
+}
37
+
38
+static const struct pw_impl_factory_events factory_events = {
39
+   PW_VERSION_IMPL_FACTORY_EVENTS,
40
+   .destroy = factory_destroy,
41
+};
42
+
43
 static void module_destroy(void *data)
44
 {
45
    struct factory_data *d = data;
46
 
47
    spa_hook_remove(&d->module_listener);
48
    spa_list_remove(&d->export.link);
49
-   pw_impl_factory_destroy(d->this);
50
+
51
+   d->module = NULL;
52
+   if (d->factory)
53
+       pw_impl_factory_destroy(d->factory);
54
 }
55
 
56
 static void module_registered(void *data)
57
 {
58
    struct factory_data *d = data;
59
    struct pw_impl_module *module = d->module;
60
-   struct pw_impl_factory *factory = d->this;
61
+   struct pw_impl_factory *factory = d->factory;
62
    struct spa_dict_item items1;
63
    char id16;
64
    int res;
65
@@ -552,7 +570,7 @@
66
        return -errno;
67
 
68
    data = pw_impl_factory_get_user_data(factory);
69
-   data->this = factory;
70
+   data->factory = factory;
71
    data->module = module;
72
 
73
    pw_impl_factory_set_implementation(factory, &impl_factory, data);
74
@@ -562,10 +580,11 @@
75
    if ((res = pw_context_register_export_type(context, &data->export)) < 0)
76
        goto error;
77
 
78
+   pw_impl_factory_add_listener(factory, &data->factory_listener, &factory_events, data);
79
    pw_impl_module_add_listener(module, &data->module_listener, &module_events, data);
80
 
81
    return 0;
82
 error:
83
-   pw_impl_factory_destroy(data->this);
84
+   pw_impl_factory_destroy(data->factory);
85
    return res;
86
 }
87
pipewire-0.3.51.tar.gz/src/modules/module-session-manager/session.c -> pipewire-0.3.52.tar.gz/src/modules/module-session-manager/session.c Changed
86
 
1
@@ -78,11 +78,12 @@
2
 
3
 struct factory_data
4
 {
5
-   struct pw_impl_factory *this;
6
-
7
    struct pw_impl_module *module;
8
    struct spa_hook module_listener;
9
 
10
+   struct pw_impl_factory *factory;
11
+   struct spa_hook factory_listener;
12
+
13
    struct pw_export_type export;
14
 };
15
 
16
@@ -461,7 +462,7 @@
17
    pw_properties_setf(properties, PW_KEY_CLIENT_ID, "%d",
18
            pw_impl_client_get_info(client)->id);
19
    pw_properties_setf(properties, PW_KEY_FACTORY_ID, "%d",
20
-           pw_impl_factory_get_info(d->this)->id);
21
+           pw_impl_factory_get_info(d->factory)->id);
22
 
23
    result = session_new(pw_impl_client_get_context(client), impl_resource, properties);
24
    if (result == NULL) {
25
@@ -491,20 +492,36 @@
26
    .create_object = create_object,
27
 };
28
 
29
+static void factory_destroy(void *data)
30
+{
31
+   struct factory_data *d = data;
32
+   spa_hook_remove(&d->factory_listener);
33
+   d->factory = NULL;
34
+   if (d->module)
35
+       pw_impl_module_destroy(d->module);
36
+}
37
+
38
+static const struct pw_impl_factory_events factory_events = {
39
+   PW_VERSION_IMPL_FACTORY_EVENTS,
40
+   .destroy = factory_destroy,
41
+};
42
+
43
 static void module_destroy(void *data)
44
 {
45
    struct factory_data *d = data;
46
 
47
    spa_hook_remove(&d->module_listener);
48
    spa_list_remove(&d->export.link);
49
-   pw_impl_factory_destroy(d->this);
50
+   d->module = NULL;
51
+   if (d->factory)
52
+       pw_impl_factory_destroy(d->factory);
53
 }
54
 
55
 static void module_registered(void *data)
56
 {
57
    struct factory_data *d = data;
58
    struct pw_impl_module *module = d->module;
59
-   struct pw_impl_factory *factory = d->this;
60
+   struct pw_impl_factory *factory = d->factory;
61
    struct spa_dict_item items1;
62
    char id16;
63
    int res;
64
@@ -541,7 +558,7 @@
65
        return -errno;
66
 
67
    data = pw_impl_factory_get_user_data(factory);
68
-   data->this = factory;
69
+   data->factory = factory;
70
    data->module = module;
71
 
72
    pw_impl_factory_set_implementation(factory, &impl_factory, data);
73
@@ -551,10 +568,11 @@
74
    if ((res = pw_context_register_export_type(context, &data->export)) < 0)
75
        goto error;
76
 
77
+   pw_impl_factory_add_listener(factory, &data->factory_listener, &factory_events, data);
78
    pw_impl_module_add_listener(module, &data->module_listener, &module_events, data);
79
 
80
    return 0;
81
 error:
82
-   pw_impl_factory_destroy(data->this);
83
+   pw_impl_factory_destroy(data->factory);
84
    return res;
85
 }
86
pipewire-0.3.51.tar.gz/src/modules/module-zeroconf-discover.c -> pipewire-0.3.52.tar.gz/src/modules/module-zeroconf-discover.c Changed
23
 
1
@@ -195,10 +195,10 @@
2
        pw_properties_set(props, PW_KEY_NODE_TARGET, value);
3
    }
4
    else if (spa_streq(key, "rate")) {
5
-       pw_properties_setf(props, PW_KEY_AUDIO_RATE, "%u", atoi(value));
6
+       pw_properties_set(props, PW_KEY_AUDIO_RATE, value);
7
    }
8
    else if (spa_streq(key, "channels")) {
9
-       pw_properties_setf(props, PW_KEY_AUDIO_CHANNELS, "%u", atoi(value));
10
+       pw_properties_set(props, PW_KEY_AUDIO_CHANNELS, value);
11
    }
12
    else if (spa_streq(key, "channel_map")) {
13
        struct channel_map channel_map;
14
@@ -311,7 +311,7 @@
15
        pw_properties_setf(props, PW_KEY_NODE_NAME,
16
                "tunnel.%s", host_name);
17
 
18
-   str = strstr(type, "sink") ? "playback" : "capture";
19
+   str = strstr(type, "sink") ? "sink" : "source";
20
    pw_properties_set(props, "tunnel.mode", str);
21
 
22
    if (a->proto == AVAHI_PROTO_INET6 &&
23
pipewire-0.3.51.tar.gz/src/modules/spa/module-device-factory.c -> pipewire-0.3.52.tar.gz/src/modules/spa/module-device-factory.c Changed
85
 
1
@@ -51,11 +51,12 @@
2
 
3
 struct factory_data {
4
    struct pw_context *context;
5
+
6
    struct pw_impl_module *module;
7
-   struct pw_impl_factory *this;
8
+   struct spa_hook module_listener;
9
 
10
+   struct pw_impl_factory *factory;
11
    struct spa_hook factory_listener;
12
-   struct spa_hook module_listener;
13
 
14
    struct spa_list device_list;
15
 };
16
@@ -120,7 +121,7 @@
17
        goto error_properties;
18
 
19
    pw_properties_setf(properties, PW_KEY_FACTORY_ID, "%d",
20
-           pw_global_get_id(pw_impl_factory_get_global(data->this)));
21
+           pw_global_get_id(pw_impl_factory_get_global(data->factory)));
22
 
23
    client = resource ? pw_resource_get_client(resource) : NULL;
24
 
25
@@ -190,16 +191,19 @@
26
    .create_object = create_object,
27
 };
28
 
29
-static void factory_destroy(void *_data)
30
+static void factory_destroy(void *data)
31
 {
32
-   struct factory_data *data = _data;
33
+   struct factory_data *d = data;
34
    struct device_data *nd;
35
 
36
-   spa_hook_remove(&data->factory_listener);
37
-   spa_hook_remove(&data->module_listener);
38
+   spa_hook_remove(&d->factory_listener);
39
 
40
-   spa_list_consume(nd, &data->device_list, link)
41
+   spa_list_consume(nd, &d->device_list, link)
42
        pw_impl_device_destroy(nd->device);
43
+
44
+   d->factory = NULL;
45
+   if (d->module)
46
+       pw_impl_module_destroy(d->module);
47
 }
48
 
49
 static const struct pw_impl_factory_events factory_events = {
50
@@ -207,17 +211,21 @@
51
    .destroy = factory_destroy,
52
 };
53
 
54
-static void module_destroy(void *_data)
55
+static void module_destroy(void *data)
56
 {
57
-   struct factory_data *data = _data;
58
-   pw_impl_factory_destroy(data->this);
59
+   struct factory_data *d = data;
60
+
61
+   spa_hook_remove(&d->module_listener);
62
+   d->module = NULL;
63
+   if (d->factory)
64
+       pw_impl_factory_destroy(d->factory);
65
 }
66
 
67
 static void module_registered(void *data)
68
 {
69
    struct factory_data *d = data;
70
    struct pw_impl_module *module = d->module;
71
-   struct pw_impl_factory *factory = d->this;
72
+   struct pw_impl_factory *factory = d->factory;
73
    struct spa_dict_item items1;
74
    char id16;
75
    int res;
76
@@ -256,7 +264,7 @@
77
        return -errno;
78
 
79
    data = pw_impl_factory_get_user_data(factory);
80
-   data->this = factory;
81
+   data->factory = factory;
82
    data->module = module;
83
    data->context = context;
84
    spa_list_init(&data->device_list);
85
pipewire-0.3.51.tar.gz/src/modules/spa/module-node-factory.c -> pipewire-0.3.52.tar.gz/src/modules/spa/module-node-factory.c Changed
132
 
1
@@ -51,11 +51,12 @@
2
 
3
 struct factory_data {
4
    struct pw_context *context;
5
-   struct pw_impl_factory *this;
6
+
7
    struct pw_impl_module *module;
8
+   struct spa_hook module_listener;
9
 
10
+   struct pw_impl_factory *factory;
11
    struct spa_hook factory_listener;
12
-   struct spa_hook module_listener;
13
 
14
    struct spa_list node_list;
15
 };
16
@@ -65,6 +66,7 @@
17
    struct spa_list link;
18
    struct pw_impl_node *node;
19
    struct spa_hook node_listener;
20
+   struct pw_resource *resource;
21
    struct spa_hook resource_listener;
22
    unsigned int linger:1;
23
 };
24
@@ -74,6 +76,7 @@
25
    struct node_data *nd = data;
26
    pw_log_debug("node %p", nd);
27
    spa_hook_remove(&nd->resource_listener);
28
+   nd->resource = NULL;
29
    if (nd->node && !nd->linger)
30
        pw_impl_node_destroy(nd->node);
31
 }
32
@@ -90,6 +93,11 @@
33
    spa_list_remove(&nd->link);
34
    spa_hook_remove(&nd->node_listener);
35
    nd->node = NULL;
36
+
37
+   if (nd->resource) {
38
+       spa_hook_remove(&nd->resource_listener);
39
+       nd->resource = NULL;
40
+   }
41
 }
42
 
43
 static const struct pw_impl_node_events node_events = {
44
@@ -121,7 +129,7 @@
45
        goto error_properties;
46
 
47
    pw_properties_setf(properties, PW_KEY_FACTORY_ID, "%d",
48
-           pw_global_get_id(pw_impl_factory_get_global(data->this)));
49
+           pw_global_get_id(pw_impl_factory_get_global(data->factory)));
50
 
51
    linger = pw_properties_get_bool(properties, PW_KEY_OBJECT_LINGER, false);
52
 
53
@@ -147,17 +155,15 @@
54
    pw_impl_node_add_listener(node, &nd->node_listener, &node_events, nd);
55
 
56
    if (client) {
57
-       struct pw_resource *bound_resource;
58
-
59
        res = pw_global_bind(pw_impl_node_get_global(node),
60
                   client, PW_PERM_ALL, version, new_id);
61
        if (res < 0)
62
            goto error_bind;
63
 
64
-       if ((bound_resource = pw_impl_client_find_resource(client, new_id)) == NULL)
65
+       if ((nd->resource = pw_impl_client_find_resource(client, new_id)) == NULL)
66
            goto error_bind;
67
 
68
-       pw_resource_add_listener(bound_resource, &nd->resource_listener, &resource_events, nd);
69
+       pw_resource_add_listener(nd->resource, &nd->resource_listener, &resource_events, nd);
70
    }
71
    return node;
72
 
73
@@ -187,15 +193,17 @@
74
    .create_object = create_object,
75
 };
76
 
77
-static void factory_destroy(void *_data)
78
+static void factory_destroy(void *data)
79
 {
80
-   struct factory_data *data = _data;
81
+   struct factory_data *d = data;
82
    struct node_data *nd;
83
 
84
-   spa_hook_remove(&data->factory_listener);
85
-   spa_list_consume(nd, &data->node_list, link)
86
+   spa_hook_remove(&d->factory_listener);
87
+   spa_list_consume(nd, &d->node_list, link)
88
        pw_impl_node_destroy(nd->node);
89
-   data->this = NULL;
90
+   d->factory = NULL;
91
+   if (d->module)
92
+       pw_impl_module_destroy(d->module);
93
 }
94
 
95
 static const struct pw_impl_factory_events factory_events = {
96
@@ -203,19 +211,20 @@
97
    .destroy = factory_destroy,
98
 };
99
 
100
-static void module_destroy(void *_data)
101
+static void module_destroy(void *data)
102
 {
103
-   struct factory_data *data = _data;
104
-   spa_hook_remove(&data->module_listener);
105
-   if (data->this)
106
-       pw_impl_factory_destroy(data->this);
107
+   struct factory_data *d = data;
108
+   spa_hook_remove(&d->module_listener);
109
+   d->module = NULL;
110
+   if (d->factory)
111
+       pw_impl_factory_destroy(d->factory);
112
 }
113
 
114
 static void module_registered(void *data)
115
 {
116
    struct factory_data *d = data;
117
    struct pw_impl_module *module = d->module;
118
-   struct pw_impl_factory *factory = d->this;
119
+   struct pw_impl_factory *factory = d->factory;
120
    struct spa_dict_item items1;
121
    char id16;
122
    int res;
123
@@ -254,7 +263,7 @@
124
        return -errno;
125
 
126
    data = pw_impl_factory_get_user_data(factory);
127
-   data->this = factory;
128
+   data->factory = factory;
129
    data->context = context;
130
    data->module = module;
131
    spa_list_init(&data->node_list);
132
pipewire-0.3.51.tar.gz/src/pipewire/impl-client.c -> pipewire-0.3.52.tar.gz/src/pipewire/impl-client.c Changed
84
 
1
@@ -24,6 +24,7 @@
2
 
3
 #include <errno.h>
4
 #include <string.h>
5
+#include <assert.h>
6
 
7
 #include <spa/utils/string.h>
8
 
9
@@ -415,6 +416,7 @@
10
    this = &impl->this;
11
    pw_log_debug("%p: new", this);
12
 
13
+   this->refcount = 1;
14
    this->context = core->context;
15
    this->core = core;
16
    this->protocol = protocol;
17
@@ -584,6 +586,33 @@
18
 }
19
 
20
 
21
+SPA_EXPORT
22
+void pw_impl_client_unref(struct pw_impl_client *client)
23
+{
24
+   struct impl *impl = SPA_CONTAINER_OF(client, struct impl, this);
25
+
26
+   assert(client->refcount > 0);
27
+   if (--client->refcount > 0)
28
+       return;
29
+
30
+   pw_log_debug("%p: free", impl);
31
+   assert(client->destroyed);
32
+
33
+   pw_impl_client_emit_free(client);
34
+
35
+   spa_hook_list_clean(&client->listener_list);
36
+
37
+   pw_map_clear(&client->objects);
38
+   pw_array_clear(&impl->permissions);
39
+
40
+   spa_hook_remove(&impl->pool_listener);
41
+   pw_mempool_destroy(client->pool);
42
+
43
+   pw_properties_free(client->properties);
44
+
45
+   free(impl);
46
+}
47
+
48
 /** Destroy a client object
49
  *
50
  * \param client the client to destroy
51
@@ -595,6 +624,10 @@
52
    struct impl *impl = SPA_CONTAINER_OF(client, struct impl, this);
53
 
54
    pw_log_debug("%p: destroy", client);
55
+
56
+   assert(!client->destroyed);
57
+   client->destroyed = true;
58
+
59
    pw_impl_client_emit_destroy(client);
60
 
61
    spa_hook_remove(&impl->context_listener);
62
@@ -609,20 +642,7 @@
63
        pw_global_destroy(client->global);
64
    }
65
 
66
-   pw_log_debug("%p: free", impl);
67
-   pw_impl_client_emit_free(client);
68
-
69
-   spa_hook_list_clean(&client->listener_list);
70
-
71
-   pw_map_clear(&client->objects);
72
-   pw_array_clear(&impl->permissions);
73
-
74
-   spa_hook_remove(&impl->pool_listener);
75
-   pw_mempool_destroy(client->pool);
76
-
77
-   pw_properties_free(client->properties);
78
-
79
-   free(impl);
80
+   pw_impl_client_unref(client);
81
 }
82
 
83
 SPA_EXPORT
84
pipewire-0.3.51.tar.gz/src/pipewire/impl-module.c -> pipewire-0.3.52.tar.gz/src/pipewire/impl-module.c Changed
34
 
1
@@ -239,6 +239,8 @@
2
    filename = NULL;
3
    this->info.args = args ? strdup(args) : NULL;
4
 
5
+   spa_list_prepend(&context->module_list, &this->link);
6
+
7
    this->global = pw_global_new(context,
8
                     PW_TYPE_INTERFACE_Module,
9
                     PW_VERSION_MODULE,
10
@@ -249,8 +251,6 @@
11
    if (this->global == NULL)
12
        goto error_no_global;
13
 
14
-   spa_list_prepend(&context->module_list, &this->link);
15
-
16
    this->info.id = this->global->id;
17
    pw_properties_setf(this->properties, PW_KEY_OBJECT_ID, "%d", this->info.id);
18
    pw_properties_setf(this->properties, PW_KEY_OBJECT_SERIAL, "%"PRIu64,
19
@@ -320,11 +320,12 @@
20
 {
21
    struct impl *impl = SPA_CONTAINER_OF(module, struct impl, this);
22
 
23
-   pw_log_debug("%p: destroy", module);
24
+   pw_log_debug("%p: destroy %s", module, module->info.name);
25
    pw_impl_module_emit_destroy(module);
26
 
27
+   spa_list_remove(&module->link);
28
+
29
    if (module->global) {
30
-       spa_list_remove(&module->link);
31
        spa_hook_remove(&module->global_listener);
32
        pw_global_destroy(module->global);
33
    }
34
pipewire-0.3.51.tar.gz/src/pipewire/impl-port.c -> pipewire-0.3.52.tar.gz/src/pipewire/impl-port.c Changed
32
 
1
@@ -1005,6 +1005,21 @@
2
            pw_properties_setf(port->properties, PW_KEY_PORT_NAME, "%s_%d", dir, port->port_id);
3
        }
4
    }
5
+   if (pw_properties_get(port->properties, PW_KEY_PORT_ALIAS) == NULL) {
6
+       const struct pw_properties *nprops;
7
+       const char *node_name;
8
+
9
+       nprops = pw_impl_node_get_properties(node);
10
+       if ((node_name = pw_properties_get(nprops, PW_KEY_NODE_NICK)) == NULL &&
11
+           (node_name = pw_properties_get(nprops, PW_KEY_NODE_DESCRIPTION)) == NULL &&
12
+           (node_name = pw_properties_get(nprops, PW_KEY_NODE_NAME)) == NULL)
13
+           node_name = "node";
14
+
15
+       pw_properties_setf(port->properties, PW_KEY_PORT_ALIAS, "%s:%s",
16
+               node_name,
17
+               pw_properties_get(port->properties, PW_KEY_PORT_NAME));
18
+   }
19
+
20
    port->info.props = &port->properties->dict;
21
 
22
    if (control) {
23
@@ -1306,7 +1321,7 @@
24
        return res;
25
 
26
    if (fd.n_params == 0)
27
-       res = do_filter(&filter, seq, 0, 0, 0, NULL);
28
+       res = do_filter(&fd, seq, 0, 0, 0, NULL);
29
 
30
    return res;
31
 }
32
pipewire-0.3.51.tar.gz/src/pipewire/introspect.c -> pipewire-0.3.52.tar.gz/src/pipewire/introspect.c Changed
28
 
1
@@ -213,7 +213,7 @@
2
        uint32_t i, user, n_params = update->n_params;
3
        void *np;
4
 
5
-       np = reallocarray(info->params, n_params, sizeof(struct spa_param_info));
6
+       np = pw_reallocarray(info->params, n_params, sizeof(struct spa_param_info));
7
        if (np == NULL) {
8
            free(info->params);
9
            info->params = NULL;
10
@@ -283,7 +283,7 @@
11
        uint32_t i, user, n_params = update->n_params;
12
        void *np;
13
 
14
-       np = reallocarray(info->params, n_params, sizeof(struct spa_param_info));
15
+       np = pw_reallocarray(info->params, n_params, sizeof(struct spa_param_info));
16
        if (np == NULL) {
17
            free(info->params);
18
            info->params = NULL;
19
@@ -443,7 +443,7 @@
20
        uint32_t i, user, n_params = update->n_params;
21
        void *np;
22
 
23
-       np = reallocarray(info->params, n_params, sizeof(struct spa_param_info));
24
+       np = pw_reallocarray(info->params, n_params, sizeof(struct spa_param_info));
25
        if (np == NULL) {
26
            free(info->params);
27
            info->params = NULL;
28
pipewire-0.3.51.tar.gz/src/pipewire/pipewire.c -> pipewire-0.3.52.tar.gz/src/pipewire/pipewire.c Changed
11
 
1
@@ -413,9 +413,6 @@
2
 
3
 static void init_i18n(struct support *support)
4
 {
5
-   /* XXX: we should remove this setlocale() call, after wireplumber
6
-    * XXX: starts setting the locale */
7
-   setlocale(LC_MESSAGES, "");
8
    bindtextdomain(GETTEXT_PACKAGE, LOCALEDIR);
9
    bind_textdomain_codeset(GETTEXT_PACKAGE, "UTF-8");
10
    pw_set_domain(GETTEXT_PACKAGE);
11
pipewire-0.3.51.tar.gz/src/pipewire/private.h -> pipewire-0.3.52.tar.gz/src/pipewire/private.h Changed
31
 
1
@@ -308,6 +308,9 @@
2
    unsigned int registered:1;
3
    unsigned int ucred_valid:1; /**< if the ucred member is valid */
4
    unsigned int busy:1;
5
+   unsigned int destroyed:1;
6
+
7
+   int refcount;
8
 
9
    /* v2 compatibility data */
10
    void *compat_v2;
11
@@ -945,8 +948,10 @@
12
    const char *type;       /**< type of the client interface */
13
    uint32_t version;       /**< version of the client interface */
14
    uint32_t bound_id;      /**< global id we are bound to */
15
+   int refcount;
16
 
17
    unsigned int removed:1;     /**< resource was removed from server */
18
+   unsigned int destroyed:1;   /**< resource was destroyed */
19
 
20
    struct spa_hook_list listener_list;
21
    struct spa_hook_list object_listener_list;
22
@@ -1266,6 +1271,8 @@
23
 
24
 void pw_control_destroy(struct pw_control *control);
25
 
26
+void pw_impl_client_unref(struct pw_impl_client *client);
27
+
28
 #define PW_LOG_OBJECT_POD  (1<<0)
29
 void pw_log_log_object(enum spa_log_level level, const char *file, int line,
30
       const char *func, uint32_t flags, const void *object);
31
pipewire-0.3.51.tar.gz/src/pipewire/resource.c -> pipewire-0.3.52.tar.gz/src/pipewire/resource.c Changed
90
 
1
@@ -23,6 +23,7 @@
2
  */
3
 
4
 #include <string.h>
5
+#include <assert.h>
6
 
7
 #include "pipewire/private.h"
8
 #include "pipewire/protocol.h"
9
@@ -57,6 +58,7 @@
10
        return NULL;
11
 
12
    this = &impl->this;
13
+   this->refcount = 1;
14
    this->context = client->context;
15
    this->client = client;
16
    this->permissions = permissions;
17
@@ -279,16 +281,57 @@
18
 }
19
 
20
 SPA_EXPORT
21
+void pw_resource_ref(struct pw_resource *resource)
22
+{
23
+   assert(resource->refcount > 0);
24
+   resource->refcount++;
25
+}
26
+
27
+SPA_EXPORT
28
+void pw_resource_unref(struct pw_resource *resource)
29
+{
30
+   assert(resource->refcount > 0);
31
+   if (--resource->refcount > 0)
32
+       return;
33
+
34
+   pw_log_debug("%p: free %u", resource, resource->id);
35
+   assert(resource->destroyed);
36
+
37
+#if DEBUG_LISTENERS
38
+   {
39
+       struct spa_hook *h;
40
+       spa_list_for_each(h, &resource->object_listener_list.list, link) {
41
+           pw_log_warn("%p: resource %u: leaked object listener %p",
42
+                   resource, resource->id, h);
43
+           break;
44
+       }
45
+       spa_list_for_each(h, &resource->listener_list.list, link) {
46
+           pw_log_warn("%p: resource %u: leaked listener %p",
47
+                   resource, resource->id, h);
48
+           break;
49
+       }
50
+   }
51
+#endif
52
+   spa_hook_list_clean(&resource->listener_list);
53
+   spa_hook_list_clean(&resource->object_listener_list);
54
+
55
+   free(resource);
56
+}
57
+
58
+SPA_EXPORT
59
 void pw_resource_destroy(struct pw_resource *resource)
60
 {
61
    struct pw_impl_client *client = resource->client;
62
 
63
+   pw_log_debug("%p: destroy %u", resource, resource->id);
64
+   assert(!resource->destroyed);
65
+   resource->destroyed = true;
66
+
67
    if (resource->global) {
68
        spa_list_remove(&resource->link);
69
        resource->global = NULL;
70
    }
71
 
72
-   pw_log_debug("%p: destroy %u", resource, resource->id);
73
    pw_resource_emit_destroy(resource);
74
 
75
    pw_map_insert_at(&client->objects, resource->id, NULL);
76
@@ -297,12 +340,7 @@
77
    if (client->core_resource && !resource->removed)
78
        pw_core_resource_remove_id(client->core_resource, resource->id);
79
 
80
-   pw_log_debug("%p: free %u", resource, resource->id);
81
-
82
-   spa_hook_list_clean(&resource->listener_list);
83
-   spa_hook_list_clean(&resource->object_listener_list);
84
-
85
-   free(resource);
86
+   pw_resource_unref(resource);
87
 }
88
 
89
 SPA_EXPORT
90
pipewire-0.3.51.tar.gz/src/pipewire/resource.h -> pipewire-0.3.52.tar.gz/src/pipewire/resource.h Changed
12
 
1
@@ -121,6 +121,10 @@
2
  * with the same \a sequence number in the return value. */
3
 int pw_resource_ping(struct pw_resource *resource, int seq);
4
 
5
+/** ref/unref a resource, Since 0.3.52 */
6
+void pw_resource_ref(struct pw_resource *resource);
7
+void pw_resource_unref(struct pw_resource *resource);
8
+
9
 /** Notify global id this resource is bound to */
10
 int pw_resource_set_bound_id(struct pw_resource *resource, uint32_t global_id);
11
 
12
pipewire-0.3.51.tar.gz/src/pipewire/settings.c -> pipewire-0.3.52.tar.gz/src/pipewire/settings.c Changed
40
 
1
@@ -41,6 +41,7 @@
2
 #define NAME "settings"
3
 
4
 #define DEFAULT_CLOCK_RATE         48000u
5
+#define DEFAULT_CLOCK_RATES            " 44100 48000 "
6
 #define DEFAULT_CLOCK_QUANTUM          1024u
7
 #define DEFAULT_CLOCK_MIN_QUANTUM      32u
8
 #define DEFAULT_CLOCK_MAX_QUANTUM      2048u
9
@@ -126,16 +127,18 @@
10
 }
11
 
12
 static uint32_t parse_clock_rate(struct pw_properties *properties, const char *name,
13
-       uint32_t *rates, uint32_t def)
14
+       uint32_t *rates, const char *def_rates, uint32_t def)
15
 {
16
    const char *str;
17
    uint32_t count = 0;
18
 
19
    if ((str = pw_properties_get(properties, name)) == NULL)
20
-       return 0;
21
+       str = def_rates;
22
 
23
    count = parse_uint32_array(str, rates, MAX_RATES, def);
24
    if (count == 0)
25
+       count = parse_uint32_array(def_rates, rates, MAX_RATES, def);
26
+   if (count == 0)
27
        goto fallback;
28
 
29
    return count;
30
@@ -223,7 +226,8 @@
31
    struct settings *d = &this->defaults;
32
 
33
    d->clock_rate = get_default_int(p, "default.clock.rate", DEFAULT_CLOCK_RATE);
34
-   d->n_clock_rates = parse_clock_rate(p, "default.clock.allowed-rates", d->clock_rates, d->clock_rate);
35
+   d->n_clock_rates = parse_clock_rate(p, "default.clock.allowed-rates", d->clock_rates,
36
+           DEFAULT_CLOCK_RATES, d->clock_rate);
37
    d->clock_quantum = get_default_int(p, "default.clock.quantum", DEFAULT_CLOCK_QUANTUM);
38
    d->clock_min_quantum = get_default_int(p, "default.clock.min-quantum", DEFAULT_CLOCK_MIN_QUANTUM);
39
    d->clock_max_quantum = get_default_int(p, "default.clock.max-quantum", DEFAULT_CLOCK_MAX_QUANTUM);
40
pipewire-0.3.51.tar.gz/src/pipewire/stream.c -> pipewire-0.3.52.tar.gz/src/pipewire/stream.c Changed
89
 
1
@@ -172,6 +172,7 @@
2
    unsigned int driving:1;
3
    unsigned int using_trigger:1;
4
    unsigned int trigger:1;
5
+   int in_set_control;
6
 };
7
 
8
 static int get_param_index(uint32_t id)
9
@@ -543,7 +544,9 @@
10
    if (id != SPA_PARAM_Props)
11
        return -ENOTSUP;
12
 
13
-   pw_stream_emit_param_changed(stream, id, param);
14
+   if (impl->in_set_control == 0)
15
+       pw_stream_emit_param_changed(stream, id, param);
16
+
17
    return 0;
18
 }
19
 
20
@@ -1771,7 +1774,6 @@
21
    struct stream *impl = SPA_CONTAINER_OF(stream, struct stream, this);
22
    struct pw_impl_factory *factory;
23
    struct pw_properties *props = NULL;
24
-   struct pw_impl_node *follower;
25
    const char *str;
26
    uint32_t i;
27
    int res;
28
@@ -1920,14 +1922,6 @@
29
        pw_properties_set(props, "channelmix.normalize", "true");
30
    }
31
 
32
-   follower = pw_context_create_node(impl->context, pw_properties_copy(props), 0);
33
-   if (follower == NULL) {
34
-       res = -errno;
35
-       goto error_node;
36
-   }
37
-
38
-   pw_impl_node_set_implementation(follower, &impl->impl_node);
39
-
40
    if (impl->media_type == SPA_MEDIA_TYPE_audio) {
41
        factory = pw_context_find_factory(impl->context, "adapter");
42
        if (factory == NULL) {
43
@@ -1935,7 +1929,8 @@
44
            res = -ENOENT;
45
            goto error_node;
46
        }
47
-       pw_properties_setf(props, "adapt.follower.node", "pointer:%p", follower);
48
+       pw_properties_setf(props, "adapt.follower.spa-node", "pointer:%p",
49
+               &impl->impl_node);
50
        pw_properties_set(props, "object.register", "false");
51
        impl->node = pw_impl_factory_create_object(factory,
52
                NULL,
53
@@ -1949,9 +1944,13 @@
54
            goto error_node;
55
        }
56
    } else {
57
-       impl->node = follower;
58
-       pw_properties_free(props);
59
+       impl->node = pw_context_create_node(impl->context, props, 0);
60
        props = NULL;
61
+       if (impl->node == NULL) {
62
+           res = -errno;
63
+           goto error_node;
64
+       }
65
+       pw_impl_node_set_implementation(impl->node, &impl->impl_node);
66
    }
67
    pw_impl_node_set_active(impl->node,
68
            !SPA_FLAG_IS_SET(impl->flags, PW_STREAM_FLAG_INACTIVE));
69
@@ -2078,6 +2077,9 @@
70
    struct spa_pod *pod;
71
    struct control *c;
72
 
73
+   if (impl->node == NULL)
74
+       return -EIO;
75
+
76
    va_start(varargs, values);
77
 
78
    spa_pod_builder_push_object(&b, &f0, SPA_TYPE_OBJECT_Props, SPA_PARAM_Props);
79
@@ -2117,7 +2119,9 @@
80
 
81
    va_end(varargs);
82
 
83
+   impl->in_set_control++;
84
    pw_impl_node_set_param(impl->node, SPA_PARAM_Props, 0, pod);
85
+   impl->in_set_control--;
86
 
87
    return 0;
88
 }
89
pipewire-0.3.51.tar.gz/src/pipewire/stream.h -> pipewire-0.3.52.tar.gz/src/pipewire/stream.h Changed
33
 
1
@@ -50,6 +50,14 @@
2
  * inputs and/or outputs you will need to use the pw_filter or make
3
  * a pw_node yourself and export it with \ref pw_core_export.
4
  *
5
+ * Streams can also be used to:
6
+ *
7
+ * \li Implement a Sink in PipeWire. This is a PW_DIRECTION_INPUT stream.
8
+ * \li Implement a Source in PipeWire. This is a PW_DIRECTION_OUTPUT stream
9
+ *
10
+ * In this case, the PW_KEY_MEDIA_CLASS property needs to be set to
11
+ * "Audio/Sink" or "Audio/Source" respectively.
12
+ *
13
  * \section sec_create Create
14
  *
15
  * Make a new stream with \ref pw_stream_new(). You will need to specify
16
@@ -64,6 +72,16 @@
17
  * The stream is initially unconnected. To connect the stream, use
18
  * \ref pw_stream_connect(). Pass the desired direction as an argument.
19
  *
20
+ * The direction is:
21
+
22
+ * \li PW_DIRECTION_INPUT for a stream that *consumes* data. This can be a
23
+ * stream that captures from a Source or a when the stream is used to
24
+ * implement a Sink.
25
+ *
26
+ * \li PW_DIRECTION_OUTPUT for a stream that *produces* data. This can be a
27
+ * stream that plays to a Sink or when the stream is used to implement
28
+ * a Source.
29
+ *
30
  * \subsection ssec_stream_target Stream target
31
  *
32
  * To make the newly connected stream automatically connect to an existing
33
pipewire-0.3.51.tar.gz/src/pipewire/utils.c -> pipewire-0.3.52.tar.gz/src/pipewire/utils.c Changed
15
 
1
@@ -168,3 +168,13 @@
2
    close(fd);
3
    return bytes;
4
 }
5
+
6
+SPA_EXPORT
7
+void* pw_reallocarray(void *ptr, size_t nmemb, size_t size)
8
+{
9
+#ifdef HAVE_REALLOCARRAY
10
+   return reallocarray(ptr, nmemb, size);
11
+#else
12
+   return realloc(ptr, nmemb * size);
13
+#endif
14
+}
15
pipewire-0.3.51.tar.gz/src/pipewire/utils.h -> pipewire-0.3.52.tar.gz/src/pipewire/utils.h Changed
19
 
1
@@ -29,6 +29,7 @@
2
 extern "C" {
3
 #endif
4
 
5
+#include <stdlib.h>
6
 #include <string.h>
7
 #include <sys/un.h>
8
 #ifndef _POSIX_C_SOURCE
9
@@ -86,6 +87,9 @@
10
 #endif
11
 
12
 ssize_t pw_getrandom(void *buf, size_t buflen, unsigned int flags);
13
+
14
+void* pw_reallocarray(void *ptr, size_t nmemb, size_t size);
15
+
16
 /**
17
  * \}
18
  */
19
pipewire-0.3.51.tar.gz/src/tools/dsffile.c -> pipewire-0.3.52.tar.gz/src/tools/dsffile.c Changed
10
 
1
@@ -222,6 +222,8 @@
2
    offset = block * f->info.blocksize * f->info.channels;
3
    pos = f->offset % f->info.blocksize;
4
 
5
+   samples *= step;
6
+
7
    for (total = 0; total < samples && offset + pos < f->info.length; total++) {
8
        const uint8_t *s = f->p + offset + pos;
9
        uint32_t i;
10
pipewire-0.3.51.tar.gz/src/tools/pw-cat.c -> pipewire-0.3.52.tar.gz/src/tools/pw-cat.c Changed
201
 
1
@@ -709,10 +709,11 @@
2
    data->stride = data->dsf.layout.channels * SPA_ABS(data->dsf.layout.interleave);
3
 
4
    if (data->verbose) {
5
-       printf("DSD: channels:%d bitorder:%s interleave:%d\n",
6
+       printf("DSD: channels:%d bitorder:%s interleave:%d stride:%d\n",
7
                data->dsf.layout.channels,
8
                data->dsf.layout.lsb ? "lsb" : "msb",
9
-               data->dsf.layout.interleave);
10
+               data->dsf.layout.interleave,
11
+               data->stride);
12
    }
13
 }
14
 
15
@@ -849,6 +850,7 @@
16
    { "media-role",     required_argument, NULL, OPT_MEDIA_ROLE },
17
    { "target",     required_argument, NULL, OPT_TARGET },
18
    { "latency",        required_argument, NULL, OPT_LATENCY },
19
+   { "properties",     required_argument, NULL, 'P' },
20
 
21
    { "rate",       required_argument, NULL, OPT_RATE },
22
    { "channels",       required_argument, NULL, OPT_CHANNELS },
23
@@ -867,7 +869,7 @@
24
    fp = is_error ? stderr : stdout;
25
 
26
         fprintf(fp,
27
-      _("%s options <file>\n"
28
+      _("%s options <file>|-\n"
29
              "  -h, --help                            Show this help\n"
30
              "      --version                         Show version\n"
31
              "  -v, --verbose                         Enable verbose operations\n"
32
@@ -884,6 +886,7 @@
33
         "                                          Xunit (unit = s, ms, us, ns)\n"
34
         "                                          or direct samples (256)\n"
35
         "                                          the rate is the one of the source file\n"
36
+        "  -P  --properties                      Set node properties\n"
37
         "\n"),
38
         DEFAULT_MEDIA_TYPE,
39
         DEFAULT_MEDIA_CATEGORY_PLAYBACK,
40
@@ -1073,6 +1076,62 @@
41
    return 0;
42
 }
43
 
44
+struct format_info {
45
+   const char *name;
46
+   uint32_t spa_format;
47
+   uint32_t width;
48
+} format_info = {
49
+   {  "s8", SPA_AUDIO_FORMAT_S8, 1 },
50
+   {  "u8", SPA_AUDIO_FORMAT_U8, 1 },
51
+   {  "s16", SPA_AUDIO_FORMAT_S16, 2 },
52
+   {  "s24", SPA_AUDIO_FORMAT_S24, 3 },
53
+   {  "s32", SPA_AUDIO_FORMAT_S32, 4 },
54
+   {  "f32", SPA_AUDIO_FORMAT_F32, 4 },
55
+   {  "f64", SPA_AUDIO_FORMAT_F32, 8 },
56
+};
57
+
58
+static struct format_info *format_info_by_name(const char *str)
59
+{
60
+   uint32_t i;
61
+   for (i = 0; i < SPA_N_ELEMENTS(format_info); i++)
62
+       if (spa_streq(str, format_infoi.name))
63
+           return &format_infoi;
64
+   return NULL;
65
+}
66
+
67
+static int stdout_record(struct data *d, void *src, unsigned int n_frames)
68
+{
69
+   return fwrite(src, d->stride, n_frames, stdout);
70
+}
71
+
72
+static int stdin_play(struct data *d, void *src, unsigned int n_frames)
73
+{
74
+   return fread(src, d->stride, n_frames, stdin);
75
+}
76
+
77
+static int setup_pipe(struct data *data)
78
+{
79
+   struct format_info *info;
80
+
81
+   if (data->format == NULL)
82
+       data->format = DEFAULT_FORMAT;
83
+   if (data->channels == 0)
84
+       data->channels = DEFAULT_CHANNELS;
85
+   if (data->rate == 0)
86
+       data->rate = DEFAULT_RATE;
87
+   if (data->channelmap.n_channels == 0)
88
+       channelmap_default(&data->channelmap, data->channels);
89
+
90
+   info = format_info_by_name(data->format);
91
+   if (info == NULL)
92
+       return -EINVAL;
93
+
94
+   data->spa_format = info->spa_format;
95
+   data->stride = info->width * data->channels;
96
+   data->fill = data->mode == mode_playback ?  stdin_play : stdout_record;
97
+   return 0;
98
+}
99
+
100
 static int fill_properties(struct data *data)
101
 {
102
    static const char * const table = {
103
@@ -1350,8 +1409,17 @@
104
    /* negative means no volume adjustment */
105
    data.volume = -1.0;
106
    data.quality = -1;
107
+   data.props = pw_properties_new(
108
+           PW_KEY_APP_NAME, prog,
109
+           PW_KEY_NODE_NAME, prog,
110
+           NULL);
111
 
112
-   while ((c = getopt_long(argc, argv, "hvprmdR:q:", long_options, NULL)) != -1) {
113
+   if (data.props == NULL) {
114
+       fprintf(stderr, "error: pw_properties_new() failed: %m\n");
115
+       goto error_no_props;
116
+   }
117
+
118
+   while ((c = getopt_long(argc, argv, "hvprmdR:q:P:", long_options, NULL)) != -1) {
119
 
120
        switch (c) {
121
 
122
@@ -1408,6 +1476,10 @@
123
            data.media_role = optarg;
124
            break;
125
 
126
+       case 'P':
127
+           pw_properties_update_string(data.props, optarg, strlen(optarg));
128
+           break;
129
+
130
        case OPT_TARGET:
131
            data.target = optarg;
132
            if (spa_streq(data.target, "0")) {
133
@@ -1499,26 +1571,17 @@
134
        data.volume = DEFAULT_VOLUME;
135
 
136
    if (optind >= argc) {
137
-       fprintf(stderr, "error: filename argument missing\n");
138
+       fprintf(stderr, "error: filename or - argument missing\n");
139
        goto error_usage;
140
    }
141
    data.filename = argvoptind++;
142
 
143
-   data.props = pw_properties_new(
144
-           PW_KEY_MEDIA_TYPE, data.media_type,
145
-           PW_KEY_MEDIA_CATEGORY, data.media_category,
146
-           PW_KEY_MEDIA_ROLE, data.media_role,
147
-           PW_KEY_APP_NAME, prog,
148
-           PW_KEY_MEDIA_FILENAME, data.filename,
149
-           PW_KEY_MEDIA_NAME, data.filename,
150
-           PW_KEY_NODE_NAME, prog,
151
-           PW_KEY_TARGET_OBJECT, data.target,
152
-           NULL);
153
-
154
-   if (data.props == NULL) {
155
-       fprintf(stderr, "error: pw_properties_new() failed: %m\n");
156
-       goto error_no_props;
157
-   }
158
+   pw_properties_set(data.props, PW_KEY_MEDIA_TYPE, data.media_type);
159
+   pw_properties_set(data.props, PW_KEY_MEDIA_CATEGORY, data.media_category);
160
+   pw_properties_set(data.props, PW_KEY_MEDIA_ROLE, data.media_role);
161
+   pw_properties_set(data.props, PW_KEY_MEDIA_FILENAME, data.filename);
162
+   pw_properties_set(data.props, PW_KEY_MEDIA_NAME, data.filename);
163
+   pw_properties_set(data.props, PW_KEY_TARGET_OBJECT, data.target);
164
 
165
    /* make a main loop. If you already have another main loop, you can add
166
     * the fd of this pipewire mainloop to it. */
167
@@ -1553,19 +1616,23 @@
168
    }
169
    pw_core_add_listener(data.core, &data.core_listener, &core_events, &data);
170
 
171
-   switch (data.data_type) {
172
-   case TYPE_PCM:
173
-       ret = setup_sndfile(&data);
174
-       break;
175
-   case TYPE_MIDI:
176
-       ret = setup_midifile(&data);
177
-       break;
178
-   case TYPE_DSD:
179
-       ret = setup_dsffile(&data);
180
-       break;
181
-   default:
182
-       ret = -ENOTSUP;
183
-       break;
184
+   if (spa_streq(data.filename, "-")) {
185
+       ret = setup_pipe(&data);
186
+   } else {
187
+       switch (data.data_type) {
188
+       case TYPE_PCM:
189
+           ret = setup_sndfile(&data);
190
+           break;
191
+       case TYPE_MIDI:
192
+           ret = setup_midifile(&data);
193
+           break;
194
+       case TYPE_DSD:
195
+           ret = setup_dsffile(&data);
196
+           break;
197
+       default:
198
+           ret = -ENOTSUP;
199
+           break;
200
+       }
201
pipewire-0.3.51.tar.gz/src/tools/pw-dump.c -> pipewire-0.3.52.tar.gz/src/tools/pw-dump.c Changed
64
 
1
@@ -1332,23 +1332,6 @@
2
    return;
3
 }
4
 
5
-static void registry_event_global_remove(void *data, uint32_t id)
6
-{
7
-   struct data *d = data;
8
-   struct object *o;
9
-
10
-   if ((o = find_object(d, id)) == NULL)
11
-       return;
12
-
13
-   object_destroy(o);
14
-}
15
-
16
-static const struct pw_registry_events registry_events = {
17
-   PW_VERSION_REGISTRY_EVENTS,
18
-   .global = registry_event_global,
19
-   .global_remove = registry_event_global_remove,
20
-};
21
-
22
 static bool object_matches(struct object *o, const char *pattern)
23
 {
24
    uint32_t id;
25
@@ -1375,6 +1358,38 @@
26
    return false;
27
 }
28
 
29
+static void registry_event_global_remove(void *data, uint32_t id)
30
+{
31
+   struct data *d = data;
32
+   struct object *o;
33
+
34
+   if ((o = find_object(d, id)) == NULL)
35
+       return;
36
+
37
+   d->state = STATE_FIRST;
38
+   if (d->pattern != NULL && !object_matches(o, d->pattern))
39
+       return;
40
+   if (d->state == STATE_FIRST)
41
+       put_begin(d, NULL, "", 0);
42
+   put_begin(d, NULL, "{", 0);
43
+   put_int(d, "id", o->id);
44
+   if (o->class && o->class->dump)
45
+       put_value(d, "info", NULL);
46
+   else if (o->props)
47
+       put_value(d, "props", NULL);
48
+   put_end(d, "}", 0);
49
+   if (d->state != STATE_FIRST)
50
+       put_end(d, "\n", 0);
51
+
52
+   object_destroy(o);
53
+}
54
+
55
+static const struct pw_registry_events registry_events = {
56
+   PW_VERSION_REGISTRY_EVENTS,
57
+   .global = registry_event_global,
58
+   .global_remove = registry_event_global_remove,
59
+};
60
+
61
 static void dump_objects(struct data *d)
62
 {
63
    static const struct flags_info fl = {
64
pipewire-0.3.51.tar.gz/src/tools/pw-loopback.c -> pipewire-0.3.52.tar.gz/src/tools/pw-loopback.c Changed
69
 
1
@@ -51,6 +51,7 @@
2
    struct pw_impl_module *module;
3
    struct spa_hook module_listener;
4
 
5
+   const char *opt_node_name;
6
    const char *opt_group_name;
7
    const char *opt_channel_map;
8
 
9
@@ -87,6 +88,7 @@
10
        "  -h, --help                            Show this help\n"
11
        "      --version                         Show version\n"
12
        "  -r, --remote                          Remote daemon name\n"
13
+       "  -n, --name                            Node name (default '%s')\n"
14
        "  -g, --group                           Node group (default '%s')\n"
15
        "  -c, --channels                        Number of channels (default %d)\n"
16
        "  -m, --channel-map                     Channel map (default '%s')\n"
17
@@ -96,6 +98,7 @@
18
        "  -P  --playback                        Playback sink to connect to\n"
19
        "      --playback-props                  Playback stream properties\n",
20
        name,
21
+       data->opt_node_name,
22
        data->opt_group_name,
23
        data->channels,
24
        data->opt_channel_map);
25
@@ -115,6 +118,7 @@
26
        { "version",        no_argument,        NULL, 'V' },
27
        { "remote",     required_argument,  NULL, 'r' },
28
        { "group",      required_argument,  NULL, 'g' },
29
+       { "name",       required_argument,  NULL, 'n' },
30
        { "channels",       required_argument,  NULL, 'c' },
31
        { "latency",        required_argument,  NULL, 'l' },
32
        { "capture",        required_argument,  NULL, 'C' },
33
@@ -133,6 +137,7 @@
34
    data.opt_group_name = pw_get_client_name();
35
    if (snprintf(cname, sizeof(cname), "%s-%zd", argv0, (size_t) getpid()) > 0)
36
        data.opt_group_name = cname;
37
+   data.opt_node_name = data.opt_group_name;
38
 
39
    data.capture_props = pw_properties_new(NULL, NULL);
40
    data.playback_props = pw_properties_new(NULL, NULL);
41
@@ -141,7 +146,7 @@
42
        goto exit;
43
    }
44
 
45
-   while ((c = getopt_long(argc, argv, "hVr:g:c:m:l:C:P:i:o:", long_options, NULL)) != -1) {
46
+   while ((c = getopt_long(argc, argv, "hVr:n:g:c:m:l:C:P:i:o:", long_options, NULL)) != -1) {
47
        switch (c) {
48
        case 'h':
49
            show_help(&data, argv0, false);
50
@@ -157,6 +162,9 @@
51
        case 'r':
52
            opt_remote = optarg;
53
            break;
54
+       case 'n':
55
+           data.opt_node_name = optarg;
56
+           break;
57
        case 'g':
58
            data.opt_group_name = optarg;
59
            break;
60
@@ -219,6 +227,8 @@
61
        fprintf(f, " audio.channels = %u", data.channels);
62
    if (data.opt_channel_map != NULL)
63
        fprintf(f, " audio.position = %s", data.opt_channel_map);
64
+   if (data.opt_node_name != NULL)
65
+       fprintf(f, " node.name = %s", data.opt_node_name);
66
 
67
    if (data.opt_group_name != NULL) {
68
        pw_properties_set(data.capture_props, PW_KEY_NODE_GROUP, data.opt_group_name);
69
pipewire-0.3.51.tar.gz/test/test-loop.c -> pipewire-0.3.52.tar.gz/test/test-loop.c Changed
92
 
1
@@ -374,6 +374,82 @@
2
    return PWTEST_PASS;
3
 }
4
 
5
+struct ctwd_data {
6
+   struct spa_source source;
7
+   int handler_running_barrier;
8
+};
9
+
10
+static void ctwd_event_handler(struct spa_source *source)
11
+{
12
+   struct ctwd_data *data = source->data;
13
+
14
+   write_eventfd(data->handler_running_barrier);
15
+
16
+   for (;;)
17
+       pause(); /* the purpose of this is to block the loop */
18
+}
19
+
20
+static int ctwd_add_source(struct spa_loop *loop, bool async, uint32_t seq,
21
+              const void *d, size_t size, void *user_data)
22
+{
23
+   struct ctwd_data *data = user_data;
24
+
25
+   pwtest_neg_errno_ok(spa_loop_add_source(loop, &data->source));
26
+
27
+   return 0;
28
+}
29
+
30
+PWTEST(cancel_thread_while_dispatching)
31
+{
32
+   static const struct spa_dict_item data_loop_props_items = {
33
+       { "loop.cancel", "true" },
34
+   };
35
+   static const struct spa_dict data_loop_props = SPA_DICT_INIT_ARRAY(data_loop_props_items);
36
+
37
+   struct ctwd_data data = {
38
+       .source = {
39
+           .data = &data,
40
+           .func = ctwd_event_handler,
41
+           .mask = SPA_IO_IN,
42
+           .fd = eventfd(0, 0),
43
+       },
44
+       .handler_running_barrier = eventfd(0, 0),
45
+   };
46
+
47
+   pw_init(NULL, NULL);
48
+
49
+   struct pw_data_loop *dl = pw_data_loop_new(&data_loop_props);
50
+   pwtest_ptr_notnull(dl);
51
+
52
+   struct pw_loop *l = pw_data_loop_get_loop(dl);
53
+   pwtest_ptr_notnull(l);
54
+
55
+   pwtest_neg_errno_ok(pw_data_loop_start(dl));
56
+
57
+   pw_loop_invoke(l, ctwd_add_source, 0, NULL, 0, true, &data);
58
+   pwtest_ptr_notnull(data.source.loop);
59
+
60
+   write_eventfd(data.source.fd);
61
+   read_eventfd(data.handler_running_barrier);
62
+
63
+   pwtest_neg_errno_ok(pw_data_loop_stop(dl));
64
+
65
+   /* these are the important checks */
66
+   pwtest_ptr_null(data.source.priv);
67
+   pwtest_int_eq(data.source.rmask, UINT32_C(0));
68
+
69
+   pw_loop_remove_source(l, &data.source);
70
+
71
+   pw_data_loop_destroy(dl);
72
+
73
+   close(data.source.fd);
74
+   close(data.handler_running_barrier);
75
+
76
+   pw_deinit();
77
+
78
+   return PWTEST_PASS;
79
+}
80
+
81
 PWTEST_SUITE(support)
82
 {
83
    pwtest_add(pwtest_loop_destroy2, PWTEST_NOARG);
84
@@ -381,6 +457,7 @@
85
    pwtest_add(pwtest_loop_recurse2, PWTEST_NOARG);
86
    pwtest_add(destroy_managed_source_before_dispatch, PWTEST_NOARG);
87
    pwtest_add(destroy_managed_source_before_dispatch_recurse, PWTEST_NOARG);
88
+   pwtest_add(cancel_thread_while_dispatching, PWTEST_NOARG);
89
 
90
    return PWTEST_PASS;
91
 }
92