Add basic implementation of pulse mainloop

This commit is contained in:
GHOSCHT 2024-04-30 20:21:40 +02:00
parent 5ad5641aa0
commit cc2ff29def
Signed by: ghoscht
GPG key ID: 2C2C1C62A5388E82

View file

@ -1,13 +1,15 @@
extern crate libpulse_binding as pulse;
use pulse::context::{Context, FlagSet as ContextFlagSet};
use pulse::def::Retval;
use pulse::mainloop::standard::{IterateResult, Mainloop};
use pulse::mainloop::threaded::Mainloop;
use pulse::proplist::Proplist;
use regex::Regex;
use std::cell::RefCell;
use std::ops::Deref;
use std::rc::Rc;
use std::time;
pub fn set_default_sink<'a>(name: &'a str) {
pub fn run() {
let mut proplist = Proplist::new().unwrap();
proplist
.set_str(
@ -29,60 +31,80 @@ pub fn set_default_sink<'a>(name: &'a str) {
.expect("Failed to create new context"),
));
// Context state change callback
{
let ml_ref = Rc::clone(&mainloop);
let context_ref = Rc::clone(&context);
context
.borrow_mut()
.set_state_callback(Some(Box::new(move || {
let state = unsafe { (*context_ref.as_ptr()).get_state() };
match state {
pulse::context::State::Ready
| pulse::context::State::Failed
| pulse::context::State::Terminated => unsafe {
(*ml_ref.as_ptr()).signal(false);
},
_ => {}
}
})));
}
context
.borrow_mut()
.connect(None, ContextFlagSet::NOFLAGS, None)
.expect("Failed to connect context");
mainloop.borrow_mut().lock();
mainloop
.borrow_mut()
.start()
.expect("Failed to start mainloop");
// Wait for context to be ready
loop {
match mainloop.borrow_mut().iterate(false) {
IterateResult::Quit(_) | IterateResult::Err(_) => {
eprintln!("Iterate state was not success, quitting...");
return;
}
IterateResult::Success(_) => {}
}
match context.borrow().get_state() {
pulse::context::State::Ready => {
break;
}
pulse::context::State::Failed | pulse::context::State::Terminated => {
eprintln!("Context state failed/terminated, quitting...");
mainloop.borrow_mut().unlock();
mainloop.borrow_mut().stop();
return;
}
_ => {}
_ => {
mainloop.borrow_mut().wait();
}
}
}
context.borrow_mut().set_state_callback(None);
mainloop.borrow_mut().unlock();
let op = context
//---------------------
mainloop.borrow_mut().lock();
let sink_filter = Regex::new("USB_Audio_CODEC").expect("Creating RegEx failed");
let callback_context = context.clone();
context
.borrow_mut()
.set_default_sink(name, |was_successful| match was_successful {
true => {
println!("Successfully set default sink");
}
false => {
eprintln!("Failed to set default sink");
}
});
loop {
match mainloop.borrow_mut().iterate(false) {
IterateResult::Quit(_) | IterateResult::Err(_) => {
eprintln!("Iterate state was not success, quitting...");
return;
}
IterateResult::Success(_) => {}
}
match op.get_state() {
pulse::operation::State::Done => {
break;
}
pulse::operation::State::Cancelled => {
eprintln!("Setting default sink was cancelled...");
return;
.introspect()
.get_sink_info_list(move |items_result| match items_result {
pulse::callbacks::ListResult::Item(item) => {
let matches_regex = sink_filter.is_match(item.name.as_ref().unwrap());
if matches_regex {
let name = item.name.as_ref().unwrap();
println!("Setting default sink to: {}", name);
callback_context.borrow_mut().set_default_sink(name, |_| {});
}
}
_ => {}
}
}
});
mainloop.borrow_mut().quit(Retval(0));
mainloop.borrow_mut().unlock();
//---------------------
loop {
std::thread::sleep(time::Duration::from_secs(u64::MAX));
}
}