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:
parent
426d42eb71
commit
6b245ac9a0
|
@ -1,6 +1,8 @@
|
|||
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};
|
||||
|
||||
fn main() {
|
||||
|
@ -108,15 +110,14 @@ fn main() {
|
|||
// );
|
||||
/*
|
||||
*/
|
||||
/*
|
||||
std::thread::spawn({
|
||||
let bus = bus.clone();
|
||||
let pipeline = pipeline.clone();
|
||||
move || {
|
||||
std::thread::sleep(Duration::new(1, 0));
|
||||
println!("{:?}", pipeline);
|
||||
std::thread::sleep(Duration::from_secs(5));
|
||||
swap_audio_output(bus, pipeline, resample, defaultsink, btsink);
|
||||
}
|
||||
});
|
||||
*/
|
||||
|
||||
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();
|
||||
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;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue