1pub mod controllers;
39mod error;
40
41use pulse::{
42 context::{introspect::Introspector, Context},
43 mainloop::standard::{IterateResult, Mainloop},
44 operation::{Operation, State},
45 proplist::Proplist,
46};
47
48use std::cell::RefCell;
49use std::ops::Deref;
50use std::rc::Rc;
51
52pub use crate::controllers::error::ControllerError;
53pub use crate::error::Error;
54
55pub struct Handler {
57 pub mainloop: Rc<RefCell<Mainloop>>,
59 pub context: Rc<RefCell<Context>>,
61 pub introspect: Introspector,
63}
64
65impl Handler {
66 pub fn connect(name: &str) -> Result<Handler, Error> {
67 let mut proplist = Proplist::new().unwrap();
68 proplist
69 .set_str(pulse::proplist::properties::APPLICATION_NAME, name)
70 .unwrap();
71
72 let mainloop = match Mainloop::new() {
73 Some(mainloop) => Rc::new(RefCell::new(mainloop)),
74 None => return Err(Error::Connect("Failed to create mainloop".to_string())),
75 };
76
77 let context =
78 match Context::new_with_proplist(mainloop.borrow().deref(), "MainConn", &proplist) {
79 Some(context) => Rc::new(RefCell::new(context)),
80 None => return Err(Error::Connect("Failed to create new context".to_string())),
81 };
82
83 context
84 .borrow_mut()
85 .connect(None, pulse::context::FlagSet::NOFLAGS, None)
86 .map_err(|_| Error::Connect("Failed to connect context".to_string()))?;
87
88 loop {
89 match mainloop.borrow_mut().iterate(false) {
90 IterateResult::Err(e) => {
91 eprintln!("iterate state was not success, quitting...");
92 return Err(e.into());
93 }
94 IterateResult::Success(_) => {}
95 IterateResult::Quit(_) => {
96 eprintln!("iterate state was not success, quitting...");
97 return Err(Error::Connect(
98 "Iterate state quit without an error".to_string(),
99 ));
100 }
101 }
102
103 match context.borrow().get_state() {
104 pulse::context::State::Ready => break,
105 pulse::context::State::Failed | pulse::context::State::Terminated => {
106 eprintln!("context state failed/terminated, quitting...");
107 return Err(Error::Connect(
108 "Context state failed/terminated without an error".to_string(),
109 ));
110 }
111 _ => {}
112 }
113 }
114
115 let introspect = context.borrow_mut().introspect();
116 Ok(Handler {
117 mainloop,
118 context,
119 introspect,
120 })
121 }
122
123 pub fn wait_for_operation<G: ?Sized>(&mut self, op: Operation<G>) -> Result<(), Error> {
125 loop {
126 match self.mainloop.borrow_mut().iterate(false) {
127 IterateResult::Err(e) => return Err(e.into()),
128 IterateResult::Success(_) => {}
129 IterateResult::Quit(_) => {
130 return Err(Error::Operation(
131 "Iterate state quit without an error".to_string(),
132 ));
133 }
134 }
135 match op.get_state() {
136 State::Done => {
137 break;
138 }
139 State::Running => {}
140 State::Cancelled => {
141 return Err(Error::Operation(
142 "Operation cancelled without an error".to_string(),
143 ));
144 }
145 }
146 }
147 Ok(())
148 }
149}
150
151impl Drop for Handler {
152 fn drop(&mut self) {
153 self.context.borrow_mut().disconnect();
154 self.mainloop.borrow_mut().quit(pulse::def::Retval(0));
155 }
156}