We truncated the diff of some files because they were too big.
If you want to see the full diff for every file, click here.
Changes of Revision 9
pipewire-aptx.changes
Changed
x
1
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
2
/** \page page_pipewire PipeWire Design
3
4
-## Internals
5
+# Internals
6
7
- \subpage page_design
8
- \subpage page_audio
9
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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, ¶m, &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, ¶m, &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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
79
default:
80
return 0;
81
}
82
+ result.next++;
83
break;
84
default:
85
{
86
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, ¶m, &b);
96
+ if (res != 1)
97
+ return res;
98
}
99
}
100
101
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
39
40
VkPipeline pipeline;
41
VkPipelineLayout pipelineLayout;
42
+ const char *shaderName;
43
VkShaderModule computeShaderModule;
44
45
VkCommandPool commandPool;
46
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
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
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
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
2
#define HEIGHT 480
3
4
#define MAX_BUFFERS 64
5
+#define MAX_MOD 8
6
7
#include "sdl.h"
8
9
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
2
id, &idx, NULL, ¶m, &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
11
id, &idx, NULL, ¶m, &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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
15
res = 0;
16
done:
17
context->current_client = NULL;
18
+
19
return res;
20
21
error:
22
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
2
3
#include <errno.h>
4
#include <string.h>
5
+#include <assert.h>
6
7
#include <spa/utils/string.h>
8
9
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
2
*/
3
4
#include <string.h>
5
+#include <assert.h>
6
7
#include "pipewire/private.h"
8
#include "pipewire/protocol.h"
9
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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