From 6b245ac9a03773b4994c7ec86128d996d6d49fd2 Mon Sep 17 00:00:00 2001 From: Savanni D'Gerinel Date: Wed, 28 Aug 2024 11:58:29 -0400 Subject: [PATCH] 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. --- gm-dash/server/src/bin/play-track.rs | 68 ++++++++++++++++++++++++++-- 1 file changed, 63 insertions(+), 5 deletions(-) diff --git a/gm-dash/server/src/bin/play-track.rs b/gm-dash/server/src/bin/play-track.rs index a2e0a63..f3f7d9b 100644 --- a/gm-dash/server/src/bin/play-track.rs +++ b/gm-dash/server/src/bin/play-track.rs @@ -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; +}