1use crate::buffer::Buffer;
9use crate::{error::Error, properties::Properties};
10use bitflags::bitflags;
11use spa::utils::result::SpaResult;
12use std::{
13 ffi::{self, CStr, CString},
14 fmt::Debug,
15 mem, os,
16 pin::Pin,
17 ptr,
18};
19
20mod box_;
21pub use box_::*;
22mod rc;
23pub use rc::*;
24
25#[derive(Debug, PartialEq)]
26pub enum StreamState {
27 Error(String),
28 Unconnected,
29 Connecting,
30 Paused,
31 Streaming,
32}
33
34impl StreamState {
35 pub(crate) fn from_raw(state: pw_sys::pw_stream_state, error: *const os::raw::c_char) -> Self {
36 match state {
37 pw_sys::pw_stream_state_PW_STREAM_STATE_UNCONNECTED => StreamState::Unconnected,
38 pw_sys::pw_stream_state_PW_STREAM_STATE_CONNECTING => StreamState::Connecting,
39 pw_sys::pw_stream_state_PW_STREAM_STATE_PAUSED => StreamState::Paused,
40 pw_sys::pw_stream_state_PW_STREAM_STATE_STREAMING => StreamState::Streaming,
41 _ => {
42 let error = if error.is_null() {
43 "".to_string()
44 } else {
45 unsafe { ffi::CStr::from_ptr(error).to_string_lossy().to_string() }
46 };
47
48 StreamState::Error(error)
49 }
50 }
51 }
52}
53
54#[repr(transparent)]
65pub struct Time(pw_sys::pw_time);
66
67impl Clone for Time {
68 fn clone(&self) -> Self {
69 Self(pw_sys::pw_time { ..self.0 })
70 }
71}
72
73impl Time {
74 pub fn as_raw(&self) -> &pw_sys::pw_time {
75 &self.0
76 }
77
78 pub fn now(&self) -> i64 {
80 self.0.now
81 }
82
83 pub fn rate(&self) -> spa::utils::Fraction {
85 self.0.rate
86 }
87
88 pub fn ticks(&self) -> u64 {
90 self.0.ticks
91 }
92
93 pub fn delay(&self) -> i64 {
98 self.0.delay
99 }
100
101 pub fn queued(&self) -> u64 {
103 self.0.queued
104 }
105
106 #[cfg(feature = "v0_3_50")]
108 pub fn buffered(&self) -> u64 {
109 self.0.buffered
110 }
111
112 #[cfg(feature = "v0_3_50")]
114 pub fn queued_buffers(&self) -> u32 {
115 self.0.queued_buffers
116 }
117
118 #[cfg(feature = "v0_3_50")]
120 pub fn avail_buffers(&self) -> u32 {
121 self.0.avail_buffers
122 }
123}
124
125impl Debug for Time {
126 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
127 let mut s = f.debug_struct("Time");
128 s.field("now", &self.now())
129 .field("rate", &self.rate())
130 .field("ticks", &self.ticks())
131 .field("delay", &self.delay())
132 .field("queued", &self.queued());
133
134 #[cfg(feature = "v0_3_50")]
135 s.field("buffered", &self.buffered())
136 .field("queued_buffers", &self.queued_buffers())
137 .field("avail_buffers", &self.avail_buffers());
138
139 s.finish()
140 }
141}
142
143#[repr(transparent)]
152pub struct Stream(pw_sys::pw_stream);
153
154impl Stream {
155 pub fn as_raw(&self) -> &pw_sys::pw_stream {
156 &self.0
157 }
158
159 pub fn as_raw_ptr(&self) -> *mut pw_sys::pw_stream {
160 ptr::addr_of!(self.0).cast_mut()
161 }
162
163 #[must_use = "Use the builder to register event callbacks"]
165 pub fn add_local_listener_with_user_data<D>(
166 &self,
167 user_data: D,
168 ) -> ListenerLocalBuilder<'_, D> {
169 let mut callbacks = ListenerLocalCallbacks::with_user_data(user_data);
170 callbacks.stream =
171 Some(ptr::NonNull::new(self.as_raw_ptr()).expect("Pointer should be nonnull"));
172 ListenerLocalBuilder {
173 stream: self,
174 callbacks,
175 }
176 }
177
178 #[must_use = "Use the builder to register event callbacks"]
180 pub fn add_local_listener<D: Default>(&self) -> ListenerLocalBuilder<'_, D> {
181 self.add_local_listener_with_user_data(Default::default())
182 }
183
184 pub fn connect(
190 &self,
191 direction: spa::utils::Direction,
192 id: Option<u32>,
193 flags: StreamFlags,
194 params: &mut [&spa::pod::Pod],
195 ) -> Result<(), Error> {
196 let r = unsafe {
197 pw_sys::pw_stream_connect(
198 self.as_raw_ptr(),
199 direction.as_raw(),
200 id.unwrap_or(crate::constants::ID_ANY),
201 flags.bits(),
202 params.as_mut_ptr().cast(),
205 params.len() as u32,
206 )
207 };
208
209 SpaResult::from_c(r).into_sync_result()?;
210 Ok(())
211 }
212
213 pub fn update_params(&self, params: &mut [&spa::pod::Pod]) -> Result<(), Error> {
219 let r = unsafe {
220 pw_sys::pw_stream_update_params(
221 self.as_raw_ptr(),
222 params.as_mut_ptr().cast(),
223 params.len() as u32,
224 )
225 };
226
227 SpaResult::from_c(r).into_sync_result()?;
228 Ok(())
229 }
230
231 pub fn set_active(&self, active: bool) -> Result<(), Error> {
233 let r = unsafe { pw_sys::pw_stream_set_active(self.as_raw_ptr(), active) };
234
235 SpaResult::from_c(r).into_sync_result()?;
236 Ok(())
237 }
238
239 pub unsafe fn dequeue_raw_buffer(&self) -> *mut pw_sys::pw_buffer {
250 pw_sys::pw_stream_dequeue_buffer(self.as_raw_ptr())
251 }
252
253 pub fn dequeue_buffer(&self) -> Option<Buffer<'_>> {
254 unsafe { Buffer::from_raw(self.dequeue_raw_buffer(), self) }
255 }
256
257 pub unsafe fn queue_raw_buffer(&self, buffer: *mut pw_sys::pw_buffer) {
268 pw_sys::pw_stream_queue_buffer(self.as_raw_ptr(), buffer);
269 }
270
271 pub fn disconnect(&self) -> Result<(), Error> {
273 let r = unsafe { pw_sys::pw_stream_disconnect(self.as_raw_ptr()) };
274
275 SpaResult::from_c(r).into_sync_result()?;
276 Ok(())
277 }
278
279 pub fn set_error(&mut self, res: i32, error: &str) {
285 let error = CString::new(error).expect("failed to convert error to CString");
286 let error_cstr = error.as_c_str();
287 Stream::set_error_cstr(self, res, error_cstr)
288 }
289
290 pub fn set_error_cstr(&mut self, res: i32, error: &CStr) {
296 unsafe {
297 pw_sys::pw_stream_set_error(self.as_raw_ptr(), res, error.as_ptr());
298 }
299 }
300
301 pub fn flush(&self, drain: bool) -> Result<(), Error> {
304 let r = unsafe { pw_sys::pw_stream_flush(self.as_raw_ptr(), drain) };
305
306 SpaResult::from_c(r).into_sync_result()?;
307 Ok(())
308 }
309
310 pub fn set_control(&self, id: u32, values: &[f32]) -> Result<(), Error> {
311 let r = unsafe {
312 pw_sys::pw_stream_set_control(
313 self.as_raw_ptr(),
314 id,
315 values.len() as u32,
316 values.as_ptr() as *mut f32,
317 )
318 };
319 SpaResult::from_c(r).into_sync_result()?;
320 Ok(())
321 }
322
323 pub fn name(&self) -> String {
327 let name = unsafe {
328 let name = pw_sys::pw_stream_get_name(self.as_raw_ptr());
329 CStr::from_ptr(name)
330 };
331
332 name.to_string_lossy().to_string()
333 }
334
335 pub fn state(&self) -> StreamState {
337 let mut error: *const std::os::raw::c_char = ptr::null();
338 let state = unsafe {
339 pw_sys::pw_stream_get_state(self.as_raw_ptr(), (&mut error) as *mut *const _)
340 };
341 StreamState::from_raw(state, error)
342 }
343
344 pub fn properties(&self) -> &Properties {
346 unsafe {
347 let props = pw_sys::pw_stream_get_properties(self.as_raw_ptr());
348 let props = ptr::NonNull::new(props.cast_mut()).expect("stream properties is NULL");
349 props.cast().as_ref()
350 }
351 }
352
353 pub fn node_id(&self) -> u32 {
355 unsafe { pw_sys::pw_stream_get_node_id(self.as_raw_ptr()) }
356 }
357
358 #[cfg(feature = "v0_3_34")]
359 pub fn is_driving(&self) -> bool {
360 unsafe { pw_sys::pw_stream_is_driving(self.as_raw_ptr()) }
361 }
362
363 #[cfg(feature = "v0_3_34")]
364 pub fn trigger_process(&self) -> Result<(), Error> {
365 let r = unsafe { pw_sys::pw_stream_trigger_process(self.as_raw_ptr()) };
366
367 SpaResult::from_c(r).into_result()?;
368 Ok(())
369 }
370
371 pub fn time(&self) -> Result<Time, Error> {
384 unsafe {
385 let mut time = mem::MaybeUninit::<pw_sys::pw_time>::zeroed();
386
387 #[cfg(feature = "v0_3_50")]
388 let r = pw_sys::pw_stream_get_time_n(
389 self.as_raw_ptr(),
390 time.as_mut_ptr(),
391 mem::size_of::<pw_sys::pw_time>(),
392 );
393
394 #[cfg(not(feature = "v0_3_50"))]
395 let r = pw_sys::pw_stream_get_time(self.as_raw_ptr(), time.as_mut_ptr());
396
397 SpaResult::from_c(r).into_result()?;
398 Ok(Time(time.assume_init()))
399 }
400 }
401
402 #[cfg(feature = "v1_1_0")]
410 pub fn nsec(&self) -> u64 {
411 unsafe { pw_sys::pw_stream_get_nsec(self.as_raw_ptr()) }
412 }
413
414 }
417
418type ParamChangedCB<D> = dyn FnMut(&Stream, &mut D, u32, Option<&spa::pod::Pod>);
419type ProcessCB<D> = dyn FnMut(&Stream, &mut D);
420
421#[allow(clippy::type_complexity)]
422pub struct ListenerLocalCallbacks<D> {
423 pub state_changed: Option<Box<dyn FnMut(&Stream, &mut D, StreamState, StreamState)>>,
424 pub control_info:
425 Option<Box<dyn FnMut(&Stream, &mut D, u32, *const pw_sys::pw_stream_control)>>,
426 pub io_changed: Option<Box<dyn FnMut(&Stream, &mut D, u32, *mut os::raw::c_void, u32)>>,
427 pub param_changed: Option<Box<ParamChangedCB<D>>>,
428 pub add_buffer: Option<Box<dyn FnMut(&Stream, &mut D, *mut pw_sys::pw_buffer)>>,
429 pub remove_buffer: Option<Box<dyn FnMut(&Stream, &mut D, *mut pw_sys::pw_buffer)>>,
430 pub process: Option<Box<ProcessCB<D>>>,
431 pub drained: Option<Box<dyn FnMut(&Stream, &mut D)>>,
432 #[cfg(feature = "v0_3_39")]
433 pub command: Option<Box<dyn FnMut(&Stream, &mut D, *const spa_sys::spa_command)>>,
434 #[cfg(feature = "v0_3_40")]
435 pub trigger_done: Option<Box<dyn FnMut(&Stream, &mut D)>>,
436 pub user_data: D,
437 stream: Option<ptr::NonNull<pw_sys::pw_stream>>,
438}
439
440unsafe fn unwrap_stream_ptr<'a>(stream: Option<ptr::NonNull<pw_sys::pw_stream>>) -> &'a Stream {
441 stream
442 .map(|ptr| ptr.cast::<Stream>().as_ref())
443 .expect("stream cannot be null")
444}
445
446impl<D> ListenerLocalCallbacks<D> {
447 fn with_user_data(user_data: D) -> Self {
448 ListenerLocalCallbacks {
449 process: Default::default(),
450 stream: Default::default(),
451 drained: Default::default(),
452 add_buffer: Default::default(),
453 control_info: Default::default(),
454 io_changed: Default::default(),
455 param_changed: Default::default(),
456 remove_buffer: Default::default(),
457 state_changed: Default::default(),
458 #[cfg(feature = "v0_3_39")]
459 command: Default::default(),
460 #[cfg(feature = "v0_3_40")]
461 trigger_done: Default::default(),
462 user_data,
463 }
464 }
465
466 pub(crate) fn into_raw(
467 self,
468 ) -> (
469 Pin<Box<pw_sys::pw_stream_events>>,
470 Box<ListenerLocalCallbacks<D>>,
471 ) {
472 let callbacks = Box::new(self);
473
474 unsafe extern "C" fn on_state_changed<D>(
475 data: *mut os::raw::c_void,
476 old: pw_sys::pw_stream_state,
477 new: pw_sys::pw_stream_state,
478 error: *const os::raw::c_char,
479 ) {
480 if let Some(state) = (data as *mut ListenerLocalCallbacks<D>).as_mut() {
481 if let Some(cb) = &mut state.state_changed {
482 let stream = unwrap_stream_ptr(state.stream);
483 let old = StreamState::from_raw(old, error);
484 let new = StreamState::from_raw(new, error);
485 cb(stream, &mut state.user_data, old, new)
486 };
487 }
488 }
489
490 unsafe extern "C" fn on_control_info<D>(
491 data: *mut os::raw::c_void,
492 id: u32,
493 control: *const pw_sys::pw_stream_control,
494 ) {
495 if let Some(state) = (data as *mut ListenerLocalCallbacks<D>).as_mut() {
496 if let Some(cb) = &mut state.control_info {
497 let stream = unwrap_stream_ptr(state.stream);
498 cb(stream, &mut state.user_data, id, control);
499 }
500 }
501 }
502
503 unsafe extern "C" fn on_io_changed<D>(
504 data: *mut os::raw::c_void,
505 id: u32,
506 area: *mut os::raw::c_void,
507 size: u32,
508 ) {
509 if let Some(state) = (data as *mut ListenerLocalCallbacks<D>).as_mut() {
510 if let Some(cb) = &mut state.io_changed {
511 let stream = unwrap_stream_ptr(state.stream);
512 cb(stream, &mut state.user_data, id, area, size);
513 }
514 }
515 }
516
517 unsafe extern "C" fn on_param_changed<D>(
518 data: *mut os::raw::c_void,
519 id: u32,
520 param: *const spa_sys::spa_pod,
521 ) {
522 if let Some(state) = (data as *mut ListenerLocalCallbacks<D>).as_mut() {
523 if let Some(cb) = &mut state.param_changed {
524 let stream = unwrap_stream_ptr(state.stream);
525 let param = if !param.is_null() {
526 Some(spa::pod::Pod::from_raw(param))
527 } else {
528 None
529 };
530
531 cb(stream, &mut state.user_data, id, param);
532 }
533 }
534 }
535
536 unsafe extern "C" fn on_add_buffer<D>(
537 data: *mut ::std::os::raw::c_void,
538 buffer: *mut pw_sys::pw_buffer,
539 ) {
540 if let Some(state) = (data as *mut ListenerLocalCallbacks<D>).as_mut() {
541 if let Some(cb) = &mut state.add_buffer {
542 let stream = unwrap_stream_ptr(state.stream);
543 cb(stream, &mut state.user_data, buffer);
544 }
545 }
546 }
547
548 unsafe extern "C" fn on_remove_buffer<D>(
549 data: *mut ::std::os::raw::c_void,
550 buffer: *mut pw_sys::pw_buffer,
551 ) {
552 if let Some(state) = (data as *mut ListenerLocalCallbacks<D>).as_mut() {
553 if let Some(cb) = &mut state.remove_buffer {
554 let stream = unwrap_stream_ptr(state.stream);
555 cb(stream, &mut state.user_data, buffer);
556 }
557 }
558 }
559
560 unsafe extern "C" fn on_process<D>(data: *mut ::std::os::raw::c_void) {
561 if let Some(state) = (data as *mut ListenerLocalCallbacks<D>).as_mut() {
562 if let Some(cb) = &mut state.process {
563 let stream = unwrap_stream_ptr(state.stream);
564 cb(stream, &mut state.user_data);
565 }
566 }
567 }
568
569 unsafe extern "C" fn on_drained<D>(data: *mut ::std::os::raw::c_void) {
570 if let Some(state) = (data as *mut ListenerLocalCallbacks<D>).as_mut() {
571 if let Some(cb) = &mut state.drained {
572 let stream = unwrap_stream_ptr(state.stream);
573 cb(stream, &mut state.user_data);
574 }
575 }
576 }
577
578 #[cfg(feature = "v0_3_39")]
579 unsafe extern "C" fn on_command<D>(
580 data: *mut ::std::os::raw::c_void,
581 command: *const spa_sys::spa_command,
582 ) {
583 if let Some(state) = (data as *mut ListenerLocalCallbacks<D>).as_mut() {
584 if let Some(cb) = &mut state.command {
585 let stream = unwrap_stream_ptr(state.stream);
586 cb(stream, &mut state.user_data, command);
587 }
588 }
589 }
590
591 #[cfg(feature = "v0_3_40")]
592 unsafe extern "C" fn on_trigger_done<D>(data: *mut ::std::os::raw::c_void) {
593 if let Some(state) = (data as *mut ListenerLocalCallbacks<D>).as_mut() {
594 if let Some(cb) = &mut state.trigger_done {
595 let stream = unwrap_stream_ptr(state.stream);
596 cb(stream, &mut state.user_data);
597 }
598 }
599 }
600
601 let events = unsafe {
602 let mut events: Pin<Box<pw_sys::pw_stream_events>> = Box::pin(mem::zeroed());
603 events.version = pw_sys::PW_VERSION_STREAM_EVENTS;
604
605 if callbacks.state_changed.is_some() {
606 events.state_changed = Some(on_state_changed::<D>);
607 }
608 if callbacks.control_info.is_some() {
609 events.control_info = Some(on_control_info::<D>);
610 }
611 if callbacks.io_changed.is_some() {
612 events.io_changed = Some(on_io_changed::<D>);
613 }
614 if callbacks.param_changed.is_some() {
615 events.param_changed = Some(on_param_changed::<D>);
616 }
617 if callbacks.add_buffer.is_some() {
618 events.add_buffer = Some(on_add_buffer::<D>);
619 }
620 if callbacks.remove_buffer.is_some() {
621 events.remove_buffer = Some(on_remove_buffer::<D>);
622 }
623 if callbacks.process.is_some() {
624 events.process = Some(on_process::<D>);
625 }
626 if callbacks.drained.is_some() {
627 events.drained = Some(on_drained::<D>);
628 }
629 #[cfg(feature = "v0_3_39")]
630 if callbacks.command.is_some() {
631 events.command = Some(on_command::<D>);
632 }
633 #[cfg(feature = "v0_3_40")]
634 if callbacks.trigger_done.is_some() {
635 events.trigger_done = Some(on_trigger_done::<D>);
636 }
637
638 events
639 };
640
641 (events, callbacks)
642 }
643}
644
645pub struct ListenerLocalBuilder<'a, D> {
674 stream: &'a Stream,
675 callbacks: ListenerLocalCallbacks<D>,
676}
677
678impl<'a, D> ListenerLocalBuilder<'a, D> {
679 #[must_use = "Call `.register()` to start receiving events"]
699 pub fn state_changed<F>(mut self, callback: F) -> Self
700 where
701 F: FnMut(&Stream, &mut D, StreamState, StreamState) + 'static,
702 {
703 self.callbacks.state_changed = Some(Box::new(callback));
704 self
705 }
706
707 #[must_use = "Call `.register()` to start receiving events"]
727 pub fn control_info<F>(mut self, callback: F) -> Self
728 where
729 F: FnMut(&Stream, &mut D, u32, *const pw_sys::pw_stream_control) + 'static,
730 {
731 self.callbacks.control_info = Some(Box::new(callback));
732 self
733 }
734
735 #[must_use = "Call `.register()` to start receiving events"]
756 pub fn io_changed<F>(mut self, callback: F) -> Self
757 where
758 F: FnMut(&Stream, &mut D, u32, *mut os::raw::c_void, u32) + 'static,
759 {
760 self.callbacks.io_changed = Some(Box::new(callback));
761 self
762 }
763
764 #[must_use = "Call `.register()` to start receiving events"]
786 pub fn param_changed<F>(mut self, callback: F) -> Self
787 where
788 F: FnMut(&Stream, &mut D, u32, Option<&spa::pod::Pod>) + 'static,
789 {
790 self.callbacks.param_changed = Some(Box::new(callback));
791 self
792 }
793
794 #[must_use = "Call `.register()` to start receiving events"]
813 pub fn add_buffer<F>(mut self, callback: F) -> Self
814 where
815 F: FnMut(&Stream, &mut D, *mut pw_sys::pw_buffer) + 'static,
816 {
817 self.callbacks.add_buffer = Some(Box::new(callback));
818 self
819 }
820
821 #[must_use = "Call `.register()` to start receiving events"]
840 pub fn remove_buffer<F>(mut self, callback: F) -> Self
841 where
842 F: FnMut(&Stream, &mut D, *mut pw_sys::pw_buffer) + 'static,
843 {
844 self.callbacks.remove_buffer = Some(Box::new(callback));
845 self
846 }
847
848 #[must_use = "Call `.register()` to start receiving events"]
873 pub fn process<F>(mut self, callback: F) -> Self
874 where
875 F: FnMut(&Stream, &mut D) + 'static,
876 {
877 self.callbacks.process = Some(Box::new(callback));
878 self
879 }
880
881 #[must_use = "Call `.register()` to start receiving events"]
899 pub fn drained<F>(mut self, callback: F) -> Self
900 where
901 F: FnMut(&Stream, &mut D) + 'static,
902 {
903 self.callbacks.drained = Some(Box::new(callback));
904 self
905 }
906
907 pub fn register(self) -> Result<StreamListener<D>, Error> {
909 let (events, data) = self.callbacks.into_raw();
910 let (listener, data) = unsafe {
911 let listener: Box<spa_sys::spa_hook> = Box::new(mem::zeroed());
912 let raw_listener = Box::into_raw(listener);
913 let raw_data = Box::into_raw(data);
914 pw_sys::pw_stream_add_listener(
915 self.stream.as_raw_ptr(),
916 raw_listener,
917 events.as_ref().get_ref(),
918 raw_data as *mut _,
919 );
920 (Box::from_raw(raw_listener), Box::from_raw(raw_data))
921 };
922 Ok(StreamListener {
923 listener,
924 _events: events,
925 _data: data,
926 })
927 }
928}
929
930#[must_use = "Listeners unregister themselves when dropped. Keep the listener alive in order to receive events."]
935pub struct StreamListener<D> {
936 listener: Box<spa_sys::spa_hook>,
937 _events: Pin<Box<pw_sys::pw_stream_events>>,
939 _data: Box<ListenerLocalCallbacks<D>>,
940}
941
942impl<D> StreamListener<D> {
943 pub fn unregister(self) {
947 }
949}
950
951impl<D> std::ops::Drop for StreamListener<D> {
952 fn drop(&mut self) {
953 spa::utils::hook::remove(*self.listener);
954 }
955}
956
957bitflags! {
958 #[derive(Debug, PartialEq, Eq, Clone, Copy)]
960 pub struct StreamFlags: pw_sys::pw_stream_flags {
961 const AUTOCONNECT = pw_sys::pw_stream_flags_PW_STREAM_FLAG_AUTOCONNECT;
962 const INACTIVE = pw_sys::pw_stream_flags_PW_STREAM_FLAG_INACTIVE;
963 const MAP_BUFFERS = pw_sys::pw_stream_flags_PW_STREAM_FLAG_MAP_BUFFERS;
964 const DRIVER = pw_sys::pw_stream_flags_PW_STREAM_FLAG_DRIVER;
965 const RT_PROCESS = pw_sys::pw_stream_flags_PW_STREAM_FLAG_RT_PROCESS;
966 const NO_CONVERT = pw_sys::pw_stream_flags_PW_STREAM_FLAG_NO_CONVERT;
967 const EXCLUSIVE = pw_sys::pw_stream_flags_PW_STREAM_FLAG_EXCLUSIVE;
968 const DONT_RECONNECT = pw_sys::pw_stream_flags_PW_STREAM_FLAG_DONT_RECONNECT;
969 const ALLOC_BUFFERS = pw_sys::pw_stream_flags_PW_STREAM_FLAG_ALLOC_BUFFERS;
970 #[cfg(feature = "v0_3_41")]
971 const TRIGGER = pw_sys::pw_stream_flags_PW_STREAM_FLAG_TRIGGER;
972 }
973}