1 // Copyright © 2017 Mozilla Foundation
2 //
3 // This program is made available under an ISC-style license. See the
4 // accompanying file LICENSE for details.
5
6 #[macro_use]
7 extern crate bitflags;
8 extern crate pulse_ffi as ffi;
9
10 #[macro_use]
11 mod error;
12 mod context;
13 mod mainloop_api;
14 mod operation;
15 mod proplist;
16 mod stream;
17 mod threaded_mainloop;
18 mod util;
19
20 pub use context::Context;
21 pub use error::ErrorCode;
22 pub use ffi::pa_buffer_attr as BufferAttr;
23 pub use ffi::pa_channel_map as ChannelMap;
24 pub use ffi::pa_cvolume as CVolume;
25 pub use ffi::pa_sample_spec as SampleSpec;
26 pub use ffi::pa_server_info as ServerInfo;
27 pub use ffi::pa_sink_info as SinkInfo;
28 pub use ffi::pa_sink_input_info as SinkInputInfo;
29 pub use ffi::pa_source_info as SourceInfo;
30 pub use ffi::pa_usec_t as USec;
31 pub use ffi::pa_volume_t as Volume;
32 pub use ffi::timeval as TimeVal;
33 pub use mainloop_api::MainloopApi;
34 pub use operation::Operation;
35 pub use proplist::Proplist;
36 use std::os::raw::{c_char, c_uint};
37 pub use stream::Stream;
38 pub use threaded_mainloop::ThreadedMainloop;
39
40 #[allow(non_camel_case_types)]
41 #[repr(i32)]
42 #[derive(Clone, Copy, Debug, PartialEq, Eq)]
43 pub enum SampleFormat {
44 Invalid = ffi::PA_SAMPLE_INVALID,
45 U8 = ffi::PA_SAMPLE_U8,
46 Alaw = ffi::PA_SAMPLE_ALAW,
47 Ulaw = ffi::PA_SAMPLE_ULAW,
48 Signed16LE = ffi::PA_SAMPLE_S16LE,
49 Signed16BE = ffi::PA_SAMPLE_S16BE,
50 Float32LE = ffi::PA_SAMPLE_FLOAT32LE,
51 Float32BE = ffi::PA_SAMPLE_FLOAT32BE,
52 Signed32LE = ffi::PA_SAMPLE_S32LE,
53 Signed32BE = ffi::PA_SAMPLE_S32BE,
54 Signed24LE = ffi::PA_SAMPLE_S24LE,
55 Signed24BE = ffi::PA_SAMPLE_S24BE,
56 Signed24_32LE = ffi::PA_SAMPLE_S24_32LE,
57 Signed23_32BE = ffi::PA_SAMPLE_S24_32BE,
58 }
59
60 impl Default for SampleFormat {
default() -> Self61 fn default() -> Self {
62 SampleFormat::Invalid
63 }
64 }
65
66 impl Into<ffi::pa_sample_format_t> for SampleFormat {
into(self) -> ffi::pa_sample_format_t67 fn into(self) -> ffi::pa_sample_format_t {
68 self as ffi::pa_sample_format_t
69 }
70 }
71
72 #[repr(i32)]
73 #[derive(Clone, Copy, Debug, PartialEq, Eq)]
74 pub enum ContextState {
75 Unconnected = ffi::PA_CONTEXT_UNCONNECTED,
76 Connecting = ffi::PA_CONTEXT_CONNECTING,
77 Authorizing = ffi::PA_CONTEXT_AUTHORIZING,
78 SettingName = ffi::PA_CONTEXT_SETTING_NAME,
79 Ready = ffi::PA_CONTEXT_READY,
80 Failed = ffi::PA_CONTEXT_FAILED,
81 Terminated = ffi::PA_CONTEXT_TERMINATED,
82 }
83
84 impl ContextState {
85 // This function implements the PA_CONTENT_IS_GOOD macro from pulse/def.h
86 // It must match the version from PA headers.
is_good(self) -> bool87 pub fn is_good(self) -> bool {
88 match self {
89 ContextState::Connecting |
90 ContextState::Authorizing |
91 ContextState::SettingName |
92 ContextState::Ready => true,
93 _ => false,
94 }
95 }
96
try_from(x: ffi::pa_context_state_t) -> Option<Self>97 pub fn try_from(x: ffi::pa_context_state_t) -> Option<Self> {
98 if x >= ffi::PA_CONTEXT_UNCONNECTED && x <= ffi::PA_CONTEXT_TERMINATED {
99 Some(unsafe { ::std::mem::transmute(x) })
100 } else {
101 None
102 }
103 }
104 }
105
106 impl Default for ContextState {
default() -> Self107 fn default() -> Self {
108 ContextState::Unconnected
109 }
110 }
111
112 impl Into<ffi::pa_context_state_t> for ContextState {
into(self) -> ffi::pa_context_state_t113 fn into(self) -> ffi::pa_context_state_t {
114 self as ffi::pa_context_state_t
115 }
116 }
117
118 #[repr(i32)]
119 #[derive(Clone, Copy, Debug, PartialEq, Eq)]
120 pub enum StreamState {
121 Unconnected = ffi::PA_STREAM_UNCONNECTED,
122 Creating = ffi::PA_STREAM_CREATING,
123 Ready = ffi::PA_STREAM_READY,
124 Failed = ffi::PA_STREAM_FAILED,
125 Terminated = ffi::PA_STREAM_TERMINATED,
126 }
127
128 impl StreamState {
129 // This function implements the PA_STREAM_IS_GOOD macro from pulse/def.h
130 // It must match the version from PA headers.
is_good(self) -> bool131 pub fn is_good(self) -> bool {
132 match self {
133 StreamState::Creating | StreamState::Ready => true,
134 _ => false,
135 }
136 }
137
try_from(x: ffi::pa_stream_state_t) -> Option<Self>138 pub fn try_from(x: ffi::pa_stream_state_t) -> Option<Self> {
139 if x >= ffi::PA_STREAM_UNCONNECTED && x <= ffi::PA_STREAM_TERMINATED {
140 Some(unsafe { ::std::mem::transmute(x) })
141 } else {
142 None
143 }
144 }
145 }
146
147 impl Default for StreamState {
default() -> Self148 fn default() -> Self {
149 StreamState::Unconnected
150 }
151 }
152
153 impl Into<ffi::pa_stream_state_t> for StreamState {
into(self) -> ffi::pa_stream_state_t154 fn into(self) -> ffi::pa_stream_state_t {
155 self as ffi::pa_stream_state_t
156 }
157 }
158
159 #[repr(i32)]
160 #[derive(Clone, Copy, Debug, PartialEq, Eq)]
161 pub enum OperationState {
162 Running = ffi::PA_OPERATION_RUNNING,
163 Done = ffi::PA_OPERATION_DONE,
164 Cancelled = ffi::PA_OPERATION_CANCELLED,
165 }
166
167 impl OperationState {
try_from(x: ffi::pa_operation_state_t) -> Option<Self>168 pub fn try_from(x: ffi::pa_operation_state_t) -> Option<Self> {
169 if x >= ffi::PA_OPERATION_RUNNING && x <= ffi::PA_OPERATION_CANCELLED {
170 Some(unsafe { ::std::mem::transmute(x) })
171 } else {
172 None
173 }
174 }
175 }
176
177 impl Into<ffi::pa_operation_state_t> for OperationState {
into(self) -> ffi::pa_operation_state_t178 fn into(self) -> ffi::pa_operation_state_t {
179 self as ffi::pa_operation_state_t
180 }
181 }
182
183 bitflags! {
184 pub struct ContextFlags: u32 {
185 const NOAUTOSPAWN = ffi::PA_CONTEXT_NOAUTOSPAWN;
186 const NOFAIL = ffi::PA_CONTEXT_NOFAIL;
187 }
188 }
189
190 impl Into<ffi::pa_context_flags_t> for ContextFlags {
into(self) -> ffi::pa_context_flags_t191 fn into(self) -> ffi::pa_context_flags_t {
192 self.bits() as ffi::pa_context_flags_t
193 }
194 }
195
196 #[repr(i32)]
197 #[derive(Clone, Copy, Debug, PartialEq, Eq)]
198 pub enum DeviceType {
199 Sink = ffi::PA_DEVICE_TYPE_SINK,
200 Source = ffi::PA_DEVICE_TYPE_SOURCE,
201 }
202
203 impl DeviceType {
try_from(x: ffi::pa_device_type_t) -> Option<Self>204 pub fn try_from(x: ffi::pa_device_type_t) -> Option<Self> {
205 if x >= ffi::PA_DEVICE_TYPE_SINK && x <= ffi::PA_DEVICE_TYPE_SOURCE {
206 Some(unsafe { ::std::mem::transmute(x) })
207 } else {
208 None
209 }
210 }
211 }
212
213 impl Into<ffi::pa_device_type_t> for DeviceType {
into(self) -> ffi::pa_device_type_t214 fn into(self) -> ffi::pa_device_type_t {
215 self as ffi::pa_device_type_t
216 }
217 }
218
219
220 #[repr(i32)]
221 #[derive(Clone, Copy, Debug, PartialEq, Eq)]
222 pub enum StreamDirection {
223 NoDirection = ffi::PA_STREAM_NODIRECTION,
224 Playback = ffi::PA_STREAM_PLAYBACK,
225 Record = ffi::PA_STREAM_RECORD,
226 StreamUpload = ffi::PA_STREAM_UPLOAD,
227 }
228
229 impl StreamDirection {
try_from(x: ffi::pa_stream_direction_t) -> Option<Self>230 pub fn try_from(x: ffi::pa_stream_direction_t) -> Option<Self> {
231 if x >= ffi::PA_STREAM_NODIRECTION && x <= ffi::PA_STREAM_UPLOAD {
232 Some(unsafe { ::std::mem::transmute(x) })
233 } else {
234 None
235 }
236 }
237 }
238
239 impl Into<ffi::pa_stream_direction_t> for StreamDirection {
into(self) -> ffi::pa_stream_direction_t240 fn into(self) -> ffi::pa_stream_direction_t {
241 self as ffi::pa_stream_direction_t
242 }
243 }
244
245 bitflags! {
246 pub struct StreamFlags : u32 {
247 const START_CORKED = ffi::PA_STREAM_START_CORKED;
248 const INTERPOLATE_TIMING = ffi::PA_STREAM_INTERPOLATE_TIMING;
249 const NOT_MONOTONIC = ffi::PA_STREAM_NOT_MONOTONIC;
250 const AUTO_TIMING_UPDATE = ffi::PA_STREAM_AUTO_TIMING_UPDATE;
251 const NO_REMAP_CHANNELS = ffi::PA_STREAM_NO_REMAP_CHANNELS;
252 const NO_REMIX_CHANNELS = ffi::PA_STREAM_NO_REMIX_CHANNELS;
253 const FIX_FORMAT = ffi::PA_STREAM_FIX_FORMAT;
254 const FIX_RATE = ffi::PA_STREAM_FIX_RATE;
255 const FIX_CHANNELS = ffi::PA_STREAM_FIX_CHANNELS;
256 const DONT_MOVE = ffi::PA_STREAM_DONT_MOVE;
257 const VARIABLE_RATE = ffi::PA_STREAM_VARIABLE_RATE;
258 const PEAK_DETECT = ffi::PA_STREAM_PEAK_DETECT;
259 const START_MUTED = ffi::PA_STREAM_START_MUTED;
260 const ADJUST_LATENCY = ffi::PA_STREAM_ADJUST_LATENCY;
261 const EARLY_REQUESTS = ffi::PA_STREAM_EARLY_REQUESTS;
262 const DONT_INHIBIT_AUTO_SUSPEND = ffi::PA_STREAM_DONT_INHIBIT_AUTO_SUSPEND;
263 const START_UNMUTED = ffi::PA_STREAM_START_UNMUTED;
264 const FAIL_ON_SUSPEND = ffi::PA_STREAM_FAIL_ON_SUSPEND;
265 const RELATIVE_VOLUME = ffi::PA_STREAM_RELATIVE_VOLUME;
266 const PASSTHROUGH = ffi::PA_STREAM_PASSTHROUGH;
267 }
268 }
269
270 impl StreamFlags {
try_from(x: ffi::pa_stream_flags_t) -> Option<Self>271 pub fn try_from(x: ffi::pa_stream_flags_t) -> Option<Self> {
272 if (x &
273 !(ffi::PA_STREAM_NOFLAGS | ffi::PA_STREAM_START_CORKED | ffi::PA_STREAM_INTERPOLATE_TIMING |
274 ffi::PA_STREAM_NOT_MONOTONIC | ffi::PA_STREAM_AUTO_TIMING_UPDATE |
275 ffi::PA_STREAM_NO_REMAP_CHANNELS |
276 ffi::PA_STREAM_NO_REMIX_CHANNELS | ffi::PA_STREAM_FIX_FORMAT | ffi::PA_STREAM_FIX_RATE |
277 ffi::PA_STREAM_FIX_CHANNELS |
278 ffi::PA_STREAM_DONT_MOVE | ffi::PA_STREAM_VARIABLE_RATE | ffi::PA_STREAM_PEAK_DETECT |
279 ffi::PA_STREAM_START_MUTED | ffi::PA_STREAM_ADJUST_LATENCY |
280 ffi::PA_STREAM_EARLY_REQUESTS |
281 ffi::PA_STREAM_DONT_INHIBIT_AUTO_SUSPEND |
282 ffi::PA_STREAM_START_UNMUTED | ffi::PA_STREAM_FAIL_ON_SUSPEND |
283 ffi::PA_STREAM_RELATIVE_VOLUME | ffi::PA_STREAM_PASSTHROUGH)) == 0 {
284 Some(unsafe { ::std::mem::transmute(x) })
285 } else {
286 None
287 }
288 }
289 }
290
291 impl Into<ffi::pa_stream_flags_t> for StreamFlags {
into(self) -> ffi::pa_stream_flags_t292 fn into(self) -> ffi::pa_stream_flags_t {
293 self.bits() as ffi::pa_stream_flags_t
294 }
295 }
296
297 pub enum StreamLatency {
298 Positive(u64),
299 Negative(u64),
300 }
301
302 bitflags!{
303 pub struct SubscriptionMask : u32 {
304 const SINK = ffi::PA_SUBSCRIPTION_MASK_SINK;
305 const SOURCE = ffi::PA_SUBSCRIPTION_MASK_SOURCE;
306 const SINK_INPUT = ffi::PA_SUBSCRIPTION_MASK_SINK_INPUT;
307 const SOURCE_OUTPUT = ffi::PA_SUBSCRIPTION_MASK_SOURCE_OUTPUT;
308 const MODULE = ffi::PA_SUBSCRIPTION_MASK_MODULE;
309 const CLIENT = ffi::PA_SUBSCRIPTION_MASK_CLIENT;
310 const SAMPLE_CACHE = ffi::PA_SUBSCRIPTION_MASK_SAMPLE_CACHE;
311 const SERVER = ffi::PA_SUBSCRIPTION_MASK_SERVER;
312 const AUTOLOAD = ffi::PA_SUBSCRIPTION_MASK_AUTOLOAD;
313 const CARD = ffi::PA_SUBSCRIPTION_MASK_CARD;
314 }
315 }
316
317 impl SubscriptionMask {
try_from(x: ffi::pa_subscription_mask_t) -> Option<Self>318 pub fn try_from(x: ffi::pa_subscription_mask_t) -> Option<Self> {
319 if (x & !ffi::PA_SUBSCRIPTION_MASK_ALL) == 0 {
320 Some(unsafe { ::std::mem::transmute(x) })
321 } else {
322 None
323 }
324 }
325 }
326
327 impl Into<ffi::pa_subscription_mask_t> for SubscriptionMask {
into(self) -> ffi::pa_subscription_mask_t328 fn into(self) -> ffi::pa_subscription_mask_t {
329 self.bits() as ffi::pa_subscription_mask_t
330 }
331 }
332
333 #[repr(i32)]
334 #[derive(Clone, Copy, Debug, PartialEq, Eq)]
335 pub enum SubscriptionEventFacility {
336 Sink = ffi::PA_SUBSCRIPTION_EVENT_SINK,
337 Source = ffi::PA_SUBSCRIPTION_EVENT_SOURCE,
338 SinkInput = ffi::PA_SUBSCRIPTION_EVENT_SINK_INPUT,
339 SourceOutput = ffi::PA_SUBSCRIPTION_EVENT_SOURCE_OUTPUT,
340 Module = ffi::PA_SUBSCRIPTION_EVENT_MODULE,
341 Client = ffi::PA_SUBSCRIPTION_EVENT_CLIENT,
342 SampleCache = ffi::PA_SUBSCRIPTION_EVENT_SAMPLE_CACHE,
343 Server = ffi::PA_SUBSCRIPTION_EVENT_SERVER,
344 Autoload = ffi::PA_SUBSCRIPTION_EVENT_AUTOLOAD,
345 Card = ffi::PA_SUBSCRIPTION_EVENT_CARD,
346 }
347
348 #[repr(C)]
349 #[derive(Clone, Copy, Debug, PartialEq, Eq)]
350 pub enum SubscriptionEventType {
351 New,
352 Change,
353 Remove,
354 }
355
356 #[repr(C)]
357 #[derive(Clone, Copy, Debug, PartialEq, Eq)]
358 pub struct SubscriptionEvent(ffi::pa_subscription_event_type_t);
359 impl SubscriptionEvent {
try_from(x: ffi::pa_subscription_event_type_t) -> Option<Self>360 pub fn try_from(x: ffi::pa_subscription_event_type_t) -> Option<Self> {
361 if (x & !(ffi::PA_SUBSCRIPTION_EVENT_TYPE_MASK | ffi::PA_SUBSCRIPTION_EVENT_FACILITY_MASK)) == 0 {
362 Some(SubscriptionEvent(x))
363 } else {
364 None
365 }
366 }
367
event_facility(self) -> SubscriptionEventFacility368 pub fn event_facility(self) -> SubscriptionEventFacility {
369 unsafe { ::std::mem::transmute(self.0 & ffi::PA_SUBSCRIPTION_EVENT_FACILITY_MASK) }
370 }
371
event_type(self) -> SubscriptionEventType372 pub fn event_type(self) -> SubscriptionEventType {
373 unsafe { ::std::mem::transmute((self.0 & ffi::PA_SUBSCRIPTION_EVENT_TYPE_MASK) >> 4) }
374 }
375 }
376
377 #[repr(i32)]
378 #[derive(Clone, Copy, Debug, PartialEq, Eq)]
379 pub enum SeekMode {
380 Relative = ffi::PA_SEEK_RELATIVE,
381 Absolute = ffi::PA_SEEK_ABSOLUTE,
382 RelativeOnRead = ffi::PA_SEEK_RELATIVE_ON_READ,
383 RelativeEnd = ffi::PA_SEEK_RELATIVE_END,
384 }
385
386 impl SeekMode {
try_from(x: ffi::pa_seek_mode_t) -> Option<Self>387 pub fn try_from(x: ffi::pa_seek_mode_t) -> Option<Self> {
388 if x >= ffi::PA_SEEK_RELATIVE && x <= ffi::PA_SEEK_RELATIVE_END {
389 Some(unsafe { ::std::mem::transmute(x) })
390 } else {
391 None
392 }
393 }
394 }
395
396 impl Into<ffi::pa_seek_mode_t> for SeekMode {
into(self) -> ffi::pa_seek_mode_t397 fn into(self) -> ffi::pa_seek_mode_t {
398 self as ffi::pa_seek_mode_t
399 }
400 }
401
402 bitflags! {
403 pub struct SinkFlags: u32 {
404 const HW_VOLUME_CTRL = ffi::PA_SINK_HW_VOLUME_CTRL;
405 const LATENCY = ffi::PA_SINK_LATENCY;
406 const HARDWARE = ffi::PA_SINK_HARDWARE;
407 const NETWORK = ffi::PA_SINK_NETWORK;
408 const HW_MUTE_CTRL = ffi::PA_SINK_HW_MUTE_CTRL;
409 const DECIBEL_VOLUME = ffi::PA_SINK_DECIBEL_VOLUME;
410 const FLAT_VOLUME = ffi::PA_SINK_FLAT_VOLUME;
411 const DYNAMIC_LATENCY = ffi::PA_SINK_DYNAMIC_LATENCY;
412 const SET_FORMATS = ffi::PA_SINK_SET_FORMATS;
413 }
414 }
415
416 impl SinkFlags {
try_from(x: ffi::pa_sink_flags_t) -> Option<SinkFlags>417 pub fn try_from(x: ffi::pa_sink_flags_t) -> Option<SinkFlags> {
418 if (x &
419 !(ffi::PA_SINK_NOFLAGS | ffi::PA_SINK_HW_VOLUME_CTRL | ffi::PA_SINK_LATENCY |
420 ffi::PA_SINK_HARDWARE | ffi::PA_SINK_NETWORK | ffi::PA_SINK_HW_MUTE_CTRL |
421 ffi::PA_SINK_DECIBEL_VOLUME | ffi::PA_SINK_DYNAMIC_LATENCY |
422 ffi::PA_SINK_FLAT_VOLUME | ffi::PA_SINK_SET_FORMATS)) == 0 {
423 Some(unsafe { ::std::mem::transmute(x) })
424 } else {
425 None
426 }
427 }
428 }
429
430 #[repr(i32)]
431 #[derive(Clone, Copy, Debug, PartialEq, Eq)]
432 pub enum SinkState {
433 InvalidState = ffi::PA_SINK_INVALID_STATE,
434 Running = ffi::PA_SINK_RUNNING,
435 Idle = ffi::PA_SINK_IDLE,
436 Suspended = ffi::PA_SINK_SUSPENDED,
437 Init = ffi::PA_SINK_INIT,
438 Unlinked = ffi::PA_SINK_UNLINKED,
439 }
440
441 bitflags!{
442 pub struct SourceFlags: u32 {
443 const HW_VOLUME_CTRL = ffi::PA_SOURCE_HW_VOLUME_CTRL;
444 const LATENCY = ffi::PA_SOURCE_LATENCY;
445 const HARDWARE = ffi::PA_SOURCE_HARDWARE;
446 const NETWORK = ffi::PA_SOURCE_NETWORK;
447 const HW_MUTE_CTRL = ffi::PA_SOURCE_HW_MUTE_CTRL;
448 const DECIBEL_VOLUME = ffi::PA_SOURCE_DECIBEL_VOLUME;
449 const DYNAMIC_LATENCY = ffi::PA_SOURCE_DYNAMIC_LATENCY;
450 const FLAT_VOLUME = ffi::PA_SOURCE_FLAT_VOLUME;
451 }
452 }
453
454 impl Into<ffi::pa_source_flags_t> for SourceFlags {
into(self) -> ffi::pa_source_flags_t455 fn into(self) -> ffi::pa_source_flags_t {
456 self.bits() as ffi::pa_source_flags_t
457 }
458 }
459
460 #[repr(i32)]
461 #[derive(Clone, Copy, Debug, PartialEq, Eq)]
462 pub enum SourceState {
463 InvalidState = ffi::PA_SOURCE_INVALID_STATE,
464 Running = ffi::PA_SOURCE_RUNNING,
465 Idle = ffi::PA_SOURCE_IDLE,
466 Suspended = ffi::PA_SOURCE_SUSPENDED,
467 Init = ffi::PA_SOURCE_INIT,
468 Unlinked = ffi::PA_SOURCE_UNLINKED,
469 }
470
471 #[repr(i32)]
472 #[derive(Clone, Copy, Debug, PartialEq, Eq)]
473 pub enum PortAvailable {
474 Unknown = ffi::PA_PORT_AVAILABLE_UNKNOWN,
475 No = ffi::PA_PORT_AVAILABLE_NO,
476 Yes = ffi::PA_PORT_AVAILABLE_YES,
477 }
478
479 impl PortAvailable {
try_from(x: ffi::pa_port_available_t) -> Option<Self>480 pub fn try_from(x: ffi::pa_port_available_t) -> Option<Self> {
481 if x >= ffi::PA_PORT_AVAILABLE_UNKNOWN && x <= ffi::PA_PORT_AVAILABLE_YES {
482 Some(unsafe { ::std::mem::transmute(x) })
483 } else {
484 None
485 }
486 }
487 }
488
489 impl Into<ffi::pa_port_available_t> for PortAvailable {
into(self) -> ffi::pa_port_available_t490 fn into(self) -> ffi::pa_port_available_t {
491 self as ffi::pa_port_available_t
492 }
493 }
494
495 #[repr(i32)]
496 #[derive(Clone, Copy, Debug, PartialEq, Eq)]
497 pub enum ChannelPosition {
498 Invalid = ffi::PA_CHANNEL_POSITION_INVALID,
499 Mono = ffi::PA_CHANNEL_POSITION_MONO,
500 FrontLeft = ffi::PA_CHANNEL_POSITION_FRONT_LEFT,
501 FrontRight = ffi::PA_CHANNEL_POSITION_FRONT_RIGHT,
502 FrontCenter = ffi::PA_CHANNEL_POSITION_FRONT_CENTER,
503 RearCenter = ffi::PA_CHANNEL_POSITION_REAR_CENTER,
504 RearLeft = ffi::PA_CHANNEL_POSITION_REAR_LEFT,
505 RearRight = ffi::PA_CHANNEL_POSITION_REAR_RIGHT,
506 LowFreqEffects = ffi::PA_CHANNEL_POSITION_LFE,
507 FrontLeftOfCenter = ffi::PA_CHANNEL_POSITION_FRONT_LEFT_OF_CENTER,
508 FrontRightOfCenter = ffi::PA_CHANNEL_POSITION_FRONT_RIGHT_OF_CENTER,
509 SideLeft = ffi::PA_CHANNEL_POSITION_SIDE_LEFT,
510 SideRight = ffi::PA_CHANNEL_POSITION_SIDE_RIGHT,
511 Aux0 = ffi::PA_CHANNEL_POSITION_AUX0,
512 Aux1 = ffi::PA_CHANNEL_POSITION_AUX1,
513 Aux2 = ffi::PA_CHANNEL_POSITION_AUX2,
514 Aux3 = ffi::PA_CHANNEL_POSITION_AUX3,
515 Aux4 = ffi::PA_CHANNEL_POSITION_AUX4,
516 Aux5 = ffi::PA_CHANNEL_POSITION_AUX5,
517 Aux6 = ffi::PA_CHANNEL_POSITION_AUX6,
518 Aux7 = ffi::PA_CHANNEL_POSITION_AUX7,
519 Aux8 = ffi::PA_CHANNEL_POSITION_AUX8,
520 Aux9 = ffi::PA_CHANNEL_POSITION_AUX9,
521 Aux10 = ffi::PA_CHANNEL_POSITION_AUX10,
522 Aux11 = ffi::PA_CHANNEL_POSITION_AUX11,
523 Aux12 = ffi::PA_CHANNEL_POSITION_AUX12,
524 Aux13 = ffi::PA_CHANNEL_POSITION_AUX13,
525 Aux14 = ffi::PA_CHANNEL_POSITION_AUX14,
526 Aux15 = ffi::PA_CHANNEL_POSITION_AUX15,
527 Aux16 = ffi::PA_CHANNEL_POSITION_AUX16,
528 Aux17 = ffi::PA_CHANNEL_POSITION_AUX17,
529 Aux18 = ffi::PA_CHANNEL_POSITION_AUX18,
530 Aux19 = ffi::PA_CHANNEL_POSITION_AUX19,
531 Aux20 = ffi::PA_CHANNEL_POSITION_AUX20,
532 Aux21 = ffi::PA_CHANNEL_POSITION_AUX21,
533 Aux22 = ffi::PA_CHANNEL_POSITION_AUX22,
534 Aux23 = ffi::PA_CHANNEL_POSITION_AUX23,
535 Aux24 = ffi::PA_CHANNEL_POSITION_AUX24,
536 Aux25 = ffi::PA_CHANNEL_POSITION_AUX25,
537 Aux26 = ffi::PA_CHANNEL_POSITION_AUX26,
538 Aux27 = ffi::PA_CHANNEL_POSITION_AUX27,
539 Aux28 = ffi::PA_CHANNEL_POSITION_AUX28,
540 Aux29 = ffi::PA_CHANNEL_POSITION_AUX29,
541 Aux30 = ffi::PA_CHANNEL_POSITION_AUX30,
542 Aux31 = ffi::PA_CHANNEL_POSITION_AUX31,
543 TopCenter = ffi::PA_CHANNEL_POSITION_TOP_CENTER,
544 TopFrontLeft = ffi::PA_CHANNEL_POSITION_TOP_FRONT_LEFT,
545 TopFrontRight = ffi::PA_CHANNEL_POSITION_TOP_FRONT_RIGHT,
546 TopFrontCenter = ffi::PA_CHANNEL_POSITION_TOP_FRONT_CENTER,
547 TopRearLeft = ffi::PA_CHANNEL_POSITION_TOP_REAR_LEFT,
548 TopRearRight = ffi::PA_CHANNEL_POSITION_TOP_REAR_RIGHT,
549 TopRearCenter = ffi::PA_CHANNEL_POSITION_TOP_REAR_CENTER,
550 }
551
552 impl ChannelPosition {
try_from(x: ffi::pa_channel_position_t) -> Option<Self>553 pub fn try_from(x: ffi::pa_channel_position_t) -> Option<Self> {
554 if x >= ffi::PA_CHANNEL_POSITION_INVALID && x < ffi::PA_CHANNEL_POSITION_MAX {
555 Some(unsafe { ::std::mem::transmute(x) })
556 } else {
557 None
558 }
559 }
560 }
561
562 impl Default for ChannelPosition {
default() -> Self563 fn default() -> Self {
564 ChannelPosition::Invalid
565 }
566 }
567
568 impl Into<ffi::pa_channel_position_t> for ChannelPosition {
into(self) -> ffi::pa_channel_position_t569 fn into(self) -> ffi::pa_channel_position_t {
570 self as ffi::pa_channel_position_t
571 }
572 }
573 pub type Result<T> = ::std::result::Result<T, error::ErrorCode>;
574
575 pub trait CVolumeExt {
set(&mut self, channels: c_uint, v: Volume)576 fn set(&mut self, channels: c_uint, v: Volume);
set_balance(&mut self, map: &ChannelMap, new_balance: f32)577 fn set_balance(&mut self, map: &ChannelMap, new_balance: f32);
578 }
579
580 impl CVolumeExt for CVolume {
set(&mut self, channels: c_uint, v: Volume)581 fn set(&mut self, channels: c_uint, v: Volume) {
582 unsafe {
583 ffi::pa_cvolume_set(self, channels, v);
584 }
585 }
586
set_balance(&mut self, map: &ChannelMap, new_balance: f32)587 fn set_balance(&mut self, map: &ChannelMap, new_balance: f32) {
588 unsafe {
589 ffi::pa_cvolume_set_balance(self, map, new_balance);
590 }
591 }
592 }
593
594 pub trait ChannelMapExt {
init() -> ChannelMap595 fn init() -> ChannelMap;
init_auto(ch: u32, def: ffi::pa_channel_map_def_t) -> Option<ChannelMap>596 fn init_auto(ch: u32, def: ffi::pa_channel_map_def_t) -> Option<ChannelMap>;
can_balance(&self) -> bool597 fn can_balance(&self) -> bool;
598 }
599
600 impl ChannelMapExt for ChannelMap {
init() -> ChannelMap601 fn init() -> ChannelMap {
602 let mut cm = ChannelMap::default();
603 unsafe {
604 ffi::pa_channel_map_init(&mut cm);
605 }
606 cm
607 }
init_auto(ch: u32, def: ffi::pa_channel_map_def_t) -> Option<ChannelMap>608 fn init_auto(ch: u32, def: ffi::pa_channel_map_def_t) -> Option<ChannelMap> {
609 let mut cm = ChannelMap::default();
610 let r: *mut ffi::pa_channel_map = unsafe {
611 ffi::pa_channel_map_init_auto(&mut cm, ch, def)
612 };
613 if r.is_null() {
614 None
615 } else {
616 Some(cm)
617 }
618 }
can_balance(&self) -> bool619 fn can_balance(&self) -> bool {
620 unsafe { ffi::pa_channel_map_can_balance(self) > 0 }
621 }
622 }
623
624 pub trait ProplistExt {
proplist(&self) -> Proplist625 fn proplist(&self) -> Proplist;
626 }
627
628 impl ProplistExt for SinkInfo {
proplist(&self) -> Proplist629 fn proplist(&self) -> Proplist {
630 unsafe { proplist::from_raw_ptr(self.proplist) }
631 }
632 }
633
634 impl ProplistExt for SourceInfo {
proplist(&self) -> Proplist635 fn proplist(&self) -> Proplist {
636 unsafe { proplist::from_raw_ptr(self.proplist) }
637 }
638 }
639
640 pub trait SampleSpecExt {
frame_size(&self) -> usize641 fn frame_size(&self) -> usize;
sample_size(&self) -> usize642 fn sample_size(&self) -> usize;
643 }
644
645 impl SampleSpecExt for SampleSpec {
frame_size(&self) -> usize646 fn frame_size(&self) -> usize {
647 unsafe { ffi::pa_frame_size(self) }
648 }
sample_size(&self) -> usize649 fn sample_size(&self) -> usize {
650 unsafe { ffi::pa_sample_size(self) }
651 }
652 }
653
654 pub trait USecExt {
to_bytes(self, spec: &SampleSpec) -> usize655 fn to_bytes(self, spec: &SampleSpec) -> usize;
656 }
657
658 impl USecExt for USec {
to_bytes(self, spec: &SampleSpec) -> usize659 fn to_bytes(self, spec: &SampleSpec) -> usize {
660 unsafe { ffi::pa_usec_to_bytes(self, spec) }
661 }
662 }
663
library_version() -> *const c_char664 pub fn library_version() -> *const c_char {
665 unsafe { ffi::pa_get_library_version() }
666 }
667
sw_volume_from_linear(vol: f64) -> Volume668 pub fn sw_volume_from_linear(vol: f64) -> Volume {
669 unsafe { ffi::pa_sw_volume_from_linear(vol) }
670 }
671
rtclock_now() -> USec672 pub fn rtclock_now() -> USec {
673 unsafe { ffi::pa_rtclock_now() }
674 }
675