Try dynamically relinking the audio sink device

All of the examples are for switching out elements in the middle of a
pipeline. In this case I am trying to switch out the trailing element.
The element refuses to be removed, and a new one can't be added until
the old audio sink is removed. I think that the audio sink can't be
removed because it is still holding on to data, and I don't know how to
detect the EOS signal as it passes through.
This commit is contained in:
Savanni D'Gerinel 2024-08-28 11:58:29 -04:00
parent 426d42eb71
commit 6b245ac9a0
1 changed files with 63 additions and 5 deletions

View File

@ -1,6 +1,8 @@
use std::time::Duration; use std::time::Duration;
use gstreamer::{prelude::*, Element, MessageType, MessageView, Pad}; use gstreamer::{
prelude::*, Bus, Element, EventType, MessageType, MessageView, Pad, PadProbeData, PadProbeInfo, PadProbeReturn, Pipeline
};
use pipewire::{context::Context, main_loop::MainLoop}; use pipewire::{context::Context, main_loop::MainLoop};
fn main() { fn main() {
@ -108,15 +110,14 @@ fn main() {
// ); // );
/* /*
*/ */
/*
std::thread::spawn({ std::thread::spawn({
let bus = bus.clone();
let pipeline = pipeline.clone(); let pipeline = pipeline.clone();
move || { move || {
std::thread::sleep(Duration::new(1, 0)); std::thread::sleep(Duration::from_secs(5));
println!("{:?}", pipeline); swap_audio_output(bus, pipeline, resample, defaultsink, btsink);
} }
}); });
*/
let mut playing = false; let mut playing = false;
@ -169,3 +170,60 @@ fn handle_pad_added(element: &Element, pad: &Pad, converter: &Element) {
let converter_pad = converter.static_pad("sink").unwrap(); let converter_pad = converter.static_pad("sink").unwrap();
pad.link(&converter_pad).unwrap(); pad.link(&converter_pad).unwrap();
} }
fn swap_audio_output(
bus: Bus,
pipeline: Pipeline,
upstream: Element,
oldoutput: Element,
newoutput: Element,
) {
let source_pad = upstream.static_pad("src").unwrap();
source_pad.add_probe(gstreamer::PadProbeType::BLOCK, move |pad, info| {
println!("upstream pad blocked");
/*
if let Some(probe_id) = info.id {
pad.remove_probe(probe_id);
}
*/
/*
if let Some(old_element_output) = oldelement.static_pad("src") {
old_element_output.add_probe(gstreamer::PadProbeType::BLOCK, wait_for_eos);
let old_element_input = oldelement.static_pad("sink").unwrap();
old_element_input.send_event(gstreamer::event::Eos::new());
} else {
/* This is a final sink, so we don't have to wait for EOS to go through. */
}
*/
let oldoutput_pad = oldoutput.static_pad("sink").unwrap();
// oldoutput_pad.send_event(gstreamer::event::Eos::new());
// oldoutput.set_state(gstreamer::State::Null).unwrap();
pipeline.remove(&oldoutput).unwrap();
pipeline.add(&newoutput).unwrap();
upstream.link(&newoutput).unwrap();
PadProbeReturn::Remove
});
}
fn wait_for_eos(pad: &Pad, info: &mut PadProbeInfo) -> PadProbeReturn {
/*
match &info.data {
Some(PadProbeData::Event(event)) if event.type_() == EventType::Eos => {
/* Do a lot of things now that this pad is empty of data. */
element.set_state(gstreamer::State::Null);
pipeline.remove(element);
pipeline.add(new_element);
let new_pad = new_element.static_pad("src");
pad.link(new_pad);
println!("EOS detected");
}
_ => return PadProbeReturn::Ok,
};
*/
return PadProbeReturn::Ok;
}