1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
// SPDX-License-Identifier: MIT
// SPDX-FileCopyrightText: Copyright (c) 2025 Asymptotic Inc.
// SPDX-FileCopyrightText: Copyright (c) 2025 Arun Raghavan
//! This library provides a Rust-native API to the [PipeWire](https://pipewire.org) audio server.
//! This includes a native implementation of the protocol, and FFI wrappers around the lower-level
//! SPA libraries used by PipeWire itself (which we try not to expose in the public API).
//!
//! <div class="warning">
//! <p>
//! The API is expected to change. Notably, performing audio/video processing is not yet
//! implemented, and the mechanism for setting up proxy events and defining closures can definitely
//! be improved.
//! </p>
//!
//! <p>
//! We will follow semantic versioning in order to avoid breaking existing API users.
//! </p>
//! </div>
//!
//! # Usage
//!
//! A typical client would use the following steps:
//!
//! * Create a [MainLoop](main_loop::MainLoop), and run it
//! * Configure and create a [Context](context::Context), optionally specifying client-specific
//! configuration
//! * [Connect](context::Context::connect()) to the server, which provides a [Core](core::Core)
//! * Request a [Registry](proxy::registry::Registry) via the core
//! * Listen for [global events](proxy::registry::RegistryEvents)
//! * [Bind](proxy::registry::Registry::bind()) to the global objects you wish to interact with
//! * For each object you bind to, you will get a proxy object which has methods you can call on
//! the object, as well as events you can subscribe to with an `add_listener()` call.
//!
//! # Examples
//!
//! Example usage of the library can be found in the source repository. The simple client test in
//! `tests/lib.rs` is a good starting point. The `pw-browse` utility in `tools/browse` can also
//! serve as a guide for writing clients.
use OnceLock;
use pipewire_native_spa as spa;
use Properties;
use Support;
/// The [Context](context::Context) holds local client configuration and support libraries. It is
/// the entry point to all other API.
/// The [Core](core::Core) object is the top-level singleton representing a connection to the
/// PipeWire server. The [Core](core::Core) can be used to query objects known to the PipeWire
/// server via the [Registry](proxy::registry::Registry). It can also be used to create objects on
/// the server on behalf of this client (this functionality has not yet been implemented).
/// Contains a number of well-known keys used in properties (such as application name, language,
/// process ID, etc.).
/// Provides an event loop for the library to communicate with the PipeWire server, as well as
/// primitives to managed mutually exclusive access to shared data structures.
/// Sructures for representing permissions.
/// Properties represent a key-value structure for various object properties. While the internal
/// representation is [String] pairs, helper methods are provided for interpreting values as
/// various primitives.
/// Proxy objects that represent objects exposed by the PipeWire server. This is the primary means
/// by which clients can interact with server-side objects.
/// Provides an event loop that runs in a separate thread.
/// List of well-known types and interfaces shared by PipeWire server and clients.
/// Logggng utilities for using the PipeWire logging system. Controlled via the `PIPEWIRE_DEBUG` and
/// `PIPEWIRE_LOG*` environment variables, as well as [Context](context::Context) properties.
pub use *;
// pub use so users of closure! don't need to import paste themselves
pub use paste;
/// Represents an object identifier
pub type Id = u32;
/// Represents an identifier for hooks added with objects' add_listener() method
pub type HookId = HookId;
pub const INVALID_ID: Id = MAX;
pub const ANY_ID: Id = 0xFFFF_FFFF;
pub static GLOBAL_SUPPORT: = new;
/// Must be called before using any other API from this crate. Initialises global support libraries
/// and sets up logging.
/// Utility macro to reduce closure-related boilerplate.
///
/// This closure allows creating a closure that captures [Refcounted] and [Clone] values without
/// having to manually manage the `downgrade()`/`upgrade()` cycle and `clone()` calls respectively.
/// The syntax is a little strange at first, but it adds a great deal of convenience. This is
/// expected to improve in the future, with less arcane syntax.
///
/// Example:
/// ```ignore
/// // We assume `AppContext` is `Clone` (maybe internally has an `Arc`)
/// fn setup_registry(app: AppContext, core: &Core) -> Registry {
/// let registry = core.registry();
///
/// // some_closure!() is the same as closure!(), but wrapped in a Some()
/// registry.add_listener(RegistryEvents {
/// // captured via Clone ----.
/// // | .---- callback
/// // captured via Refcounted \ | | arguments
/// // v v v
/// // |--------|------| |-----------------|
/// global: some_closure!([registry ^(app)] id, type_, version, {
/// // registry is made available here through a weak reference
/// let object = registry.bind(...);
/// app.add_object(id, object);
/// }),
/// global_remove: some_closure!([^(app)] id, {
/// // Without the macro, we would have to create and move two cloned copies of `app`
/// app.remove_object(id);
/// }),
/// });
/// }
/// ```
///
/// In addition to the `^` marker to capture via [Clone], there is also a `^mut` marker to capture
/// via [Clone] and make the capture value available as `mut`.
)
}
}
};
=> ;
}
/// Similar to [closure!], but returns a `Some(...)` for use with event callbacks.