mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer-rs.git
synced 2024-11-25 02:51:10 +00:00
gstreamr: bus: Add BusWatchGuard to automatically remove watch
Previously, with add_watch()/add_watch_local() you had to remember calling remove_watch() in order not to leak the bus, the watch source and two associated file descriptors. Now these methods instead return an object of type BusWatchGuard that will automatically remove the bus watch when the object is dropped. Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer-rs/-/merge_requests/1248>
This commit is contained in:
parent
5c156737a4
commit
e026d922e4
15 changed files with 276 additions and 269 deletions
|
@ -133,33 +133,34 @@ fn example_main() {
|
|||
// Every message from the bus is passed through this function. Its returnvalue determines
|
||||
// whether the handler wants to be called again. If glib::Continue(false) is returned, the
|
||||
// handler is removed and will never be called again. The mainloop still runs though.
|
||||
bus.add_watch(move |_, msg| {
|
||||
use gst::MessageView;
|
||||
let _bus_watch = bus
|
||||
.add_watch(move |_, msg| {
|
||||
use gst::MessageView;
|
||||
|
||||
let main_loop = &main_loop_clone;
|
||||
match msg.view() {
|
||||
MessageView::Eos(..) => {
|
||||
println!("received eos");
|
||||
// An EndOfStream event was sent to the pipeline, so we tell our main loop
|
||||
// to stop execution here.
|
||||
main_loop.quit()
|
||||
}
|
||||
MessageView::Error(err) => {
|
||||
println!(
|
||||
"Error from {:?}: {} ({:?})",
|
||||
err.src().map(|s| s.path_string()),
|
||||
err.error(),
|
||||
err.debug()
|
||||
);
|
||||
main_loop.quit();
|
||||
}
|
||||
_ => (),
|
||||
};
|
||||
let main_loop = &main_loop_clone;
|
||||
match msg.view() {
|
||||
MessageView::Eos(..) => {
|
||||
println!("received eos");
|
||||
// An EndOfStream event was sent to the pipeline, so we tell our main loop
|
||||
// to stop execution here.
|
||||
main_loop.quit()
|
||||
}
|
||||
MessageView::Error(err) => {
|
||||
println!(
|
||||
"Error from {:?}: {} ({:?})",
|
||||
err.src().map(|s| s.path_string()),
|
||||
err.error(),
|
||||
err.debug()
|
||||
);
|
||||
main_loop.quit();
|
||||
}
|
||||
_ => (),
|
||||
};
|
||||
|
||||
// Tell the mainloop to continue executing this callback.
|
||||
glib::Continue(true)
|
||||
})
|
||||
.expect("Failed to add bus watch");
|
||||
// Tell the mainloop to continue executing this callback.
|
||||
glib::Continue(true)
|
||||
})
|
||||
.expect("Failed to add bus watch");
|
||||
|
||||
// Operate GStreamer's bus, facilitating GLib's mainloop here.
|
||||
// This function call will block until you tell the mainloop to quit
|
||||
|
@ -169,11 +170,6 @@ fn example_main() {
|
|||
pipeline
|
||||
.set_state(gst::State::Null)
|
||||
.expect("Unable to set the pipeline to the `Null` state");
|
||||
|
||||
// Remove the watch function from the bus.
|
||||
// Again: There can always only be one watch function.
|
||||
// Thus we don't have to tell him which function to remove.
|
||||
bus.remove_watch().unwrap();
|
||||
}
|
||||
|
||||
fn main() {
|
||||
|
|
|
@ -329,30 +329,31 @@ fn main() -> Result<()> {
|
|||
|
||||
let main_loop_clone = main_loop.clone();
|
||||
let bus = playbin.bus().unwrap();
|
||||
bus.add_watch(move |_, msg| {
|
||||
use gst::MessageView;
|
||||
let _bus_watch = bus
|
||||
.add_watch(move |_, msg| {
|
||||
use gst::MessageView;
|
||||
|
||||
let main_loop = &main_loop_clone;
|
||||
match msg.view() {
|
||||
MessageView::Eos(..) => {
|
||||
println!("received eos");
|
||||
main_loop.quit()
|
||||
}
|
||||
MessageView::Error(err) => {
|
||||
println!(
|
||||
"Error from {:?}: {} ({:?})",
|
||||
err.src().map(|s| s.path_string()),
|
||||
err.error(),
|
||||
err.debug()
|
||||
);
|
||||
main_loop.quit();
|
||||
}
|
||||
_ => (),
|
||||
};
|
||||
let main_loop = &main_loop_clone;
|
||||
match msg.view() {
|
||||
MessageView::Eos(..) => {
|
||||
println!("received eos");
|
||||
main_loop.quit()
|
||||
}
|
||||
MessageView::Error(err) => {
|
||||
println!(
|
||||
"Error from {:?}: {} ({:?})",
|
||||
err.src().map(|s| s.path_string()),
|
||||
err.error(),
|
||||
err.debug()
|
||||
);
|
||||
main_loop.quit();
|
||||
}
|
||||
_ => (),
|
||||
};
|
||||
|
||||
glib::Continue(true)
|
||||
})
|
||||
.unwrap();
|
||||
glib::Continue(true)
|
||||
})
|
||||
.unwrap();
|
||||
|
||||
playbin.set_state(gst::State::Playing).unwrap();
|
||||
|
||||
|
|
|
@ -87,33 +87,34 @@ fn example_main() {
|
|||
// Every message from the bus is passed through this function. Its returnvalue determines
|
||||
// whether the handler wants to be called again. If glib::Continue(false) is returned, the
|
||||
// handler is removed and will never be called again. The mainloop still runs though.
|
||||
bus.add_watch(move |_, msg| {
|
||||
use gst::MessageView;
|
||||
let _bus_watch = bus
|
||||
.add_watch(move |_, msg| {
|
||||
use gst::MessageView;
|
||||
|
||||
let main_loop = &main_loop_clone;
|
||||
match msg.view() {
|
||||
MessageView::Eos(..) => {
|
||||
println!("received eos");
|
||||
// An EndOfStream event was sent to the pipeline, so we tell our main loop
|
||||
// to stop execution here.
|
||||
main_loop.quit()
|
||||
}
|
||||
MessageView::Error(err) => {
|
||||
println!(
|
||||
"Error from {:?}: {} ({:?})",
|
||||
err.src().map(|s| s.path_string()),
|
||||
err.error(),
|
||||
err.debug()
|
||||
);
|
||||
main_loop.quit();
|
||||
}
|
||||
_ => (),
|
||||
};
|
||||
let main_loop = &main_loop_clone;
|
||||
match msg.view() {
|
||||
MessageView::Eos(..) => {
|
||||
println!("received eos");
|
||||
// An EndOfStream event was sent to the pipeline, so we tell our main loop
|
||||
// to stop execution here.
|
||||
main_loop.quit()
|
||||
}
|
||||
MessageView::Error(err) => {
|
||||
println!(
|
||||
"Error from {:?}: {} ({:?})",
|
||||
err.src().map(|s| s.path_string()),
|
||||
err.error(),
|
||||
err.debug()
|
||||
);
|
||||
main_loop.quit();
|
||||
}
|
||||
_ => (),
|
||||
};
|
||||
|
||||
// Tell the mainloop to continue executing this callback.
|
||||
glib::Continue(true)
|
||||
})
|
||||
.expect("Failed to add bus watch");
|
||||
// Tell the mainloop to continue executing this callback.
|
||||
glib::Continue(true)
|
||||
})
|
||||
.expect("Failed to add bus watch");
|
||||
|
||||
// Operate GStreamer's bus, facilliating GLib's mainloop here.
|
||||
// This function call will block until you tell the mainloop to quit
|
||||
|
@ -123,11 +124,6 @@ fn example_main() {
|
|||
pipeline
|
||||
.set_state(gst::State::Null)
|
||||
.expect("Unable to set the pipeline to the `Null` state");
|
||||
|
||||
// Remove the watch function from the bus.
|
||||
// Again: There can always only be one watch function.
|
||||
// Thus we don't have to tell him which function to remove.
|
||||
bus.remove_watch().unwrap();
|
||||
}
|
||||
|
||||
fn main() {
|
||||
|
|
|
@ -103,31 +103,32 @@ fn create_ui(app: >k::Application) {
|
|||
.expect("Unable to set the pipeline to the `Playing` state");
|
||||
|
||||
let app_weak = app.downgrade();
|
||||
bus.add_watch_local(move |_, msg| {
|
||||
use gst::MessageView;
|
||||
let _bus_watch = bus
|
||||
.add_watch_local(move |_, msg| {
|
||||
use gst::MessageView;
|
||||
|
||||
let app = match app_weak.upgrade() {
|
||||
Some(app) => app,
|
||||
None => return glib::Continue(false),
|
||||
};
|
||||
let app = match app_weak.upgrade() {
|
||||
Some(app) => app,
|
||||
None => return glib::Continue(false),
|
||||
};
|
||||
|
||||
match msg.view() {
|
||||
MessageView::Eos(..) => app.quit(),
|
||||
MessageView::Error(err) => {
|
||||
println!(
|
||||
"Error from {:?}: {} ({:?})",
|
||||
err.src().map(|s| s.path_string()),
|
||||
err.error(),
|
||||
err.debug()
|
||||
);
|
||||
app.quit();
|
||||
}
|
||||
_ => (),
|
||||
};
|
||||
match msg.view() {
|
||||
MessageView::Eos(..) => app.quit(),
|
||||
MessageView::Error(err) => {
|
||||
println!(
|
||||
"Error from {:?}: {} ({:?})",
|
||||
err.src().map(|s| s.path_string()),
|
||||
err.error(),
|
||||
err.debug()
|
||||
);
|
||||
app.quit();
|
||||
}
|
||||
_ => (),
|
||||
};
|
||||
|
||||
glib::Continue(true)
|
||||
})
|
||||
.expect("Failed to add bus watch");
|
||||
glib::Continue(true)
|
||||
})
|
||||
.expect("Failed to add bus watch");
|
||||
|
||||
// Pipeline reference is owned by the closure below, so will be
|
||||
// destroyed once the app is destroyed
|
||||
|
@ -149,7 +150,6 @@ fn create_ui(app: >k::Application) {
|
|||
pipeline
|
||||
.set_state(gst::State::Null)
|
||||
.expect("Unable to set the pipeline to the `Null` state");
|
||||
pipeline.bus().unwrap().remove_watch().unwrap();
|
||||
}
|
||||
|
||||
if let Some(timeout_id) = timeout_id.borrow_mut().take() {
|
||||
|
|
|
@ -204,31 +204,32 @@ fn create_ui(app: >k::Application) {
|
|||
.expect("Unable to set the pipeline to the `Playing` state");
|
||||
|
||||
let app_weak = app.downgrade();
|
||||
bus.add_watch_local(move |_, msg| {
|
||||
use gst::MessageView;
|
||||
let _bus_watch = bus
|
||||
.add_watch_local(move |_, msg| {
|
||||
use gst::MessageView;
|
||||
|
||||
let app = match app_weak.upgrade() {
|
||||
Some(app) => app,
|
||||
None => return glib::Continue(false),
|
||||
};
|
||||
let app = match app_weak.upgrade() {
|
||||
Some(app) => app,
|
||||
None => return glib::Continue(false),
|
||||
};
|
||||
|
||||
match msg.view() {
|
||||
MessageView::Eos(..) => app.quit(),
|
||||
MessageView::Error(err) => {
|
||||
println!(
|
||||
"Error from {:?}: {} ({:?})",
|
||||
err.src().map(|s| s.path_string()),
|
||||
err.error(),
|
||||
err.debug()
|
||||
);
|
||||
app.quit();
|
||||
}
|
||||
_ => (),
|
||||
};
|
||||
match msg.view() {
|
||||
MessageView::Eos(..) => app.quit(),
|
||||
MessageView::Error(err) => {
|
||||
println!(
|
||||
"Error from {:?}: {} ({:?})",
|
||||
err.src().map(|s| s.path_string()),
|
||||
err.error(),
|
||||
err.debug()
|
||||
);
|
||||
app.quit();
|
||||
}
|
||||
_ => (),
|
||||
};
|
||||
|
||||
glib::Continue(true)
|
||||
})
|
||||
.expect("Failed to add bus watch");
|
||||
glib::Continue(true)
|
||||
})
|
||||
.expect("Failed to add bus watch");
|
||||
|
||||
// Pipeline reference is owned by the closure below, so will be
|
||||
// destroyed once the app is destroyed
|
||||
|
@ -250,7 +251,6 @@ fn create_ui(app: >k::Application) {
|
|||
pipeline
|
||||
.set_state(gst::State::Null)
|
||||
.expect("Unable to set the pipeline to the `Null` state");
|
||||
pipeline.bus().unwrap().remove_watch().unwrap();
|
||||
}
|
||||
|
||||
if let Some(timeout_id) = timeout_id.borrow_mut().take() {
|
||||
|
|
|
@ -35,38 +35,34 @@ fn example_main() {
|
|||
|
||||
//bus.add_signal_watch();
|
||||
//bus.connect_message(None, move |_, msg| {
|
||||
bus.add_watch(move |_, msg| {
|
||||
use gst::MessageView;
|
||||
let _bus_watch = bus
|
||||
.add_watch(move |_, msg| {
|
||||
use gst::MessageView;
|
||||
|
||||
let main_loop = &main_loop_clone;
|
||||
match msg.view() {
|
||||
MessageView::Eos(..) => main_loop.quit(),
|
||||
MessageView::Error(err) => {
|
||||
println!(
|
||||
"Error from {:?}: {} ({:?})",
|
||||
err.src().map(|s| s.path_string()),
|
||||
err.error(),
|
||||
err.debug()
|
||||
);
|
||||
main_loop.quit();
|
||||
}
|
||||
_ => (),
|
||||
};
|
||||
let main_loop = &main_loop_clone;
|
||||
match msg.view() {
|
||||
MessageView::Eos(..) => main_loop.quit(),
|
||||
MessageView::Error(err) => {
|
||||
println!(
|
||||
"Error from {:?}: {} ({:?})",
|
||||
err.src().map(|s| s.path_string()),
|
||||
err.error(),
|
||||
err.debug()
|
||||
);
|
||||
main_loop.quit();
|
||||
}
|
||||
_ => (),
|
||||
};
|
||||
|
||||
glib::Continue(true)
|
||||
})
|
||||
.expect("Failed to add bus watch");
|
||||
glib::Continue(true)
|
||||
})
|
||||
.expect("Failed to add bus watch");
|
||||
|
||||
main_loop.run();
|
||||
|
||||
pipeline
|
||||
.set_state(gst::State::Null)
|
||||
.expect("Unable to set the pipeline to the `Null` state");
|
||||
|
||||
// Here we remove the bus watch we added above. This avoids a memory leak, that might
|
||||
// otherwise happen because we moved a strong reference (clone of main_loop) into the
|
||||
// callback closure above.
|
||||
bus.remove_watch().unwrap();
|
||||
}
|
||||
|
||||
fn main() {
|
||||
|
|
|
@ -94,27 +94,28 @@ fn example_main() {
|
|||
let main_loop_clone = main_loop.clone();
|
||||
//bus.add_signal_watch();
|
||||
//bus.connect_message(None, move |_, msg| {
|
||||
bus.add_watch(move |_, msg| {
|
||||
use gst::MessageView;
|
||||
let _bus_watch = bus
|
||||
.add_watch(move |_, msg| {
|
||||
use gst::MessageView;
|
||||
|
||||
let main_loop = &main_loop_clone;
|
||||
match msg.view() {
|
||||
MessageView::Eos(..) => main_loop.quit(),
|
||||
MessageView::Error(err) => {
|
||||
println!(
|
||||
"Error from {:?}: {} ({:?})",
|
||||
err.src().map(|s| s.path_string()),
|
||||
err.error(),
|
||||
err.debug()
|
||||
);
|
||||
main_loop.quit();
|
||||
}
|
||||
_ => (),
|
||||
};
|
||||
let main_loop = &main_loop_clone;
|
||||
match msg.view() {
|
||||
MessageView::Eos(..) => main_loop.quit(),
|
||||
MessageView::Error(err) => {
|
||||
println!(
|
||||
"Error from {:?}: {} ({:?})",
|
||||
err.src().map(|s| s.path_string()),
|
||||
err.error(),
|
||||
err.debug()
|
||||
);
|
||||
main_loop.quit();
|
||||
}
|
||||
_ => (),
|
||||
};
|
||||
|
||||
glib::Continue(true)
|
||||
})
|
||||
.expect("Failed to add bus watch");
|
||||
glib::Continue(true)
|
||||
})
|
||||
.expect("Failed to add bus watch");
|
||||
|
||||
main_loop.run();
|
||||
|
||||
|
@ -122,7 +123,6 @@ fn example_main() {
|
|||
.set_state(gst::State::Null)
|
||||
.expect("Unable to set the pipeline to the `Null` state");
|
||||
|
||||
bus.remove_watch().unwrap();
|
||||
timeout_id.remove();
|
||||
}
|
||||
|
||||
|
|
|
@ -586,6 +586,7 @@ final_type = true
|
|||
|
||||
[[object.function]]
|
||||
name = "remove_watch"
|
||||
visibility = "crate"
|
||||
[object.function.return]
|
||||
bool_return_is_error = "Bus has no event source"
|
||||
|
||||
|
|
|
@ -92,7 +92,8 @@ impl Bus {
|
|||
}
|
||||
|
||||
#[doc(alias = "gst_bus_remove_watch")]
|
||||
pub fn remove_watch(&self) -> Result<(), glib::error::BoolError> {
|
||||
#[allow(dead_code)]
|
||||
pub(crate) fn remove_watch(&self) -> Result<(), glib::error::BoolError> {
|
||||
unsafe {
|
||||
glib::result_from_gboolean!(
|
||||
ffi::gst_bus_remove_watch(self.to_glib_none().0),
|
||||
|
|
|
@ -13,7 +13,7 @@ use futures_util::{stream::FusedStream, StreamExt};
|
|||
use glib::{
|
||||
ffi::{gboolean, gpointer},
|
||||
prelude::*,
|
||||
source::{Continue, Priority, SourceId},
|
||||
source::{Continue, Priority},
|
||||
translate::*,
|
||||
};
|
||||
|
||||
|
@ -135,7 +135,7 @@ impl Bus {
|
|||
|
||||
#[doc(alias = "gst_bus_add_watch")]
|
||||
#[doc(alias = "gst_bus_add_watch_full")]
|
||||
pub fn add_watch<F>(&self, func: F) -> Result<SourceId, glib::BoolError>
|
||||
pub fn add_watch<F>(&self, func: F) -> Result<BusWatchGuard, glib::BoolError>
|
||||
where
|
||||
F: FnMut(&Bus, &Message) -> Continue + Send + 'static,
|
||||
{
|
||||
|
@ -151,14 +151,14 @@ impl Bus {
|
|||
if res == 0 {
|
||||
Err(glib::bool_error!("Bus already has a watch"))
|
||||
} else {
|
||||
Ok(from_glib(res))
|
||||
Ok(BusWatchGuard { bus: self.clone() })
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[doc(alias = "gst_bus_add_watch")]
|
||||
#[doc(alias = "gst_bus_add_watch_full")]
|
||||
pub fn add_watch_local<F>(&self, func: F) -> Result<SourceId, glib::BoolError>
|
||||
pub fn add_watch_local<F>(&self, func: F) -> Result<BusWatchGuard, glib::BoolError>
|
||||
where
|
||||
F: FnMut(&Bus, &Message) -> Continue + 'static,
|
||||
{
|
||||
|
@ -179,7 +179,7 @@ impl Bus {
|
|||
if res == 0 {
|
||||
Err(glib::bool_error!("Bus already has a watch"))
|
||||
} else {
|
||||
Ok(from_glib(res))
|
||||
Ok(BusWatchGuard { bus: self.clone() })
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -378,6 +378,22 @@ impl FusedStream for BusStream {
|
|||
}
|
||||
}
|
||||
|
||||
// rustdoc-stripper-ignore-next
|
||||
/// Manages ownership of the bus watch added to a bus with [`Bus::add_watch`] or [`Bus::add_watch_local`]
|
||||
///
|
||||
/// When dropped the bus watch is removed from the bus.
|
||||
#[derive(Debug)]
|
||||
#[must_use = "if unused the bus watch will immediately be removed"]
|
||||
pub struct BusWatchGuard {
|
||||
bus: Bus,
|
||||
}
|
||||
|
||||
impl Drop for BusWatchGuard {
|
||||
fn drop(&mut self) {
|
||||
let _ = self.bus.remove_watch();
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use std::sync::{Arc, Mutex};
|
||||
|
|
|
@ -23,62 +23,62 @@ fn tutorial_main() -> Result<(), Error> {
|
|||
let main_loop_clone = main_loop.clone();
|
||||
let pipeline_weak = pipeline.downgrade();
|
||||
let bus = pipeline.bus().expect("Pipeline has no bus");
|
||||
bus.add_watch(move |_, msg| {
|
||||
let pipeline = match pipeline_weak.upgrade() {
|
||||
Some(pipeline) => pipeline,
|
||||
None => return glib::Continue(true),
|
||||
};
|
||||
let main_loop = &main_loop_clone;
|
||||
match msg.view() {
|
||||
gst::MessageView::Error(err) => {
|
||||
println!(
|
||||
"Error from {:?}: {} ({:?})",
|
||||
err.src().map(|s| s.path_string()),
|
||||
err.error(),
|
||||
err.debug()
|
||||
);
|
||||
let _ = pipeline.set_state(gst::State::Ready);
|
||||
main_loop.quit();
|
||||
}
|
||||
gst::MessageView::Eos(..) => {
|
||||
// end-of-stream
|
||||
let _ = pipeline.set_state(gst::State::Ready);
|
||||
main_loop.quit();
|
||||
}
|
||||
gst::MessageView::Buffering(buffering) => {
|
||||
// If the stream is live, we do not care about buffering
|
||||
if is_live {
|
||||
return glib::Continue(true);
|
||||
let _bus_watch = bus
|
||||
.add_watch(move |_, msg| {
|
||||
let pipeline = match pipeline_weak.upgrade() {
|
||||
Some(pipeline) => pipeline,
|
||||
None => return glib::Continue(true),
|
||||
};
|
||||
let main_loop = &main_loop_clone;
|
||||
match msg.view() {
|
||||
gst::MessageView::Error(err) => {
|
||||
println!(
|
||||
"Error from {:?}: {} ({:?})",
|
||||
err.src().map(|s| s.path_string()),
|
||||
err.error(),
|
||||
err.debug()
|
||||
);
|
||||
let _ = pipeline.set_state(gst::State::Ready);
|
||||
main_loop.quit();
|
||||
}
|
||||
gst::MessageView::Eos(..) => {
|
||||
// end-of-stream
|
||||
let _ = pipeline.set_state(gst::State::Ready);
|
||||
main_loop.quit();
|
||||
}
|
||||
gst::MessageView::Buffering(buffering) => {
|
||||
// If the stream is live, we do not care about buffering
|
||||
if is_live {
|
||||
return glib::Continue(true);
|
||||
}
|
||||
|
||||
let percent = buffering.percent();
|
||||
print!("Buffering ({percent}%)\r");
|
||||
match std::io::stdout().flush() {
|
||||
Ok(_) => {}
|
||||
Err(err) => eprintln!("Failed: {err}"),
|
||||
};
|
||||
let percent = buffering.percent();
|
||||
print!("Buffering ({percent}%)\r");
|
||||
match std::io::stdout().flush() {
|
||||
Ok(_) => {}
|
||||
Err(err) => eprintln!("Failed: {err}"),
|
||||
};
|
||||
|
||||
// Wait until buffering is complete before start/resume playing
|
||||
if percent < 100 {
|
||||
// Wait until buffering is complete before start/resume playing
|
||||
if percent < 100 {
|
||||
let _ = pipeline.set_state(gst::State::Paused);
|
||||
} else {
|
||||
let _ = pipeline.set_state(gst::State::Playing);
|
||||
}
|
||||
}
|
||||
gst::MessageView::ClockLost(_) => {
|
||||
// Get a new clock
|
||||
let _ = pipeline.set_state(gst::State::Paused);
|
||||
} else {
|
||||
let _ = pipeline.set_state(gst::State::Playing);
|
||||
}
|
||||
_ => (),
|
||||
}
|
||||
gst::MessageView::ClockLost(_) => {
|
||||
// Get a new clock
|
||||
let _ = pipeline.set_state(gst::State::Paused);
|
||||
let _ = pipeline.set_state(gst::State::Playing);
|
||||
}
|
||||
_ => (),
|
||||
}
|
||||
glib::Continue(true)
|
||||
})
|
||||
.expect("Failed to add bus watch");
|
||||
glib::Continue(true)
|
||||
})
|
||||
.expect("Failed to add bus watch");
|
||||
|
||||
main_loop.run();
|
||||
|
||||
bus.remove_watch()?;
|
||||
pipeline.set_state(gst::State::Null)?;
|
||||
|
||||
Ok(())
|
||||
|
|
|
@ -135,7 +135,7 @@ fn tutorial_main() -> Result<(), Error> {
|
|||
let playbin_clone = playbin.clone();
|
||||
let main_loop_clone = main_loop.clone();
|
||||
let bus = playbin.bus().unwrap();
|
||||
bus.add_watch(move |_bus, message| {
|
||||
let _bus_watch = bus.add_watch(move |_bus, message| {
|
||||
use gst::MessageView;
|
||||
match message.view() {
|
||||
MessageView::Error(err) => {
|
||||
|
|
|
@ -140,7 +140,7 @@ fn tutorial_main() -> Result<(), Error> {
|
|||
let playbin_clone = playbin.clone();
|
||||
let main_loop_clone = main_loop.clone();
|
||||
let bus = playbin.bus().unwrap();
|
||||
bus.add_watch(move |_bus, message| {
|
||||
let _bus_watch = bus.add_watch(move |_bus, message| {
|
||||
use gst::MessageView;
|
||||
match message.view() {
|
||||
MessageView::Error(err) => {
|
||||
|
|
|
@ -52,54 +52,55 @@ fn tutorial_main() -> Result<(), Error> {
|
|||
let main_loop_clone = main_loop.clone();
|
||||
let pipeline_weak = pipeline.downgrade();
|
||||
let bus = pipeline.bus().unwrap();
|
||||
bus.add_watch(move |_, msg| {
|
||||
use gst::MessageView;
|
||||
let _bus_watch = bus
|
||||
.add_watch(move |_, msg| {
|
||||
use gst::MessageView;
|
||||
|
||||
let buffering_level = &buffering_level_clone;
|
||||
let pipeline = match pipeline_weak.upgrade() {
|
||||
Some(pipeline) => pipeline,
|
||||
None => return glib::Continue(false),
|
||||
};
|
||||
let main_loop = &main_loop_clone;
|
||||
match msg.view() {
|
||||
MessageView::Error(err) => {
|
||||
println!(
|
||||
"Error from {:?}: {} ({:?})",
|
||||
err.src().map(|s| s.path_string()),
|
||||
err.error(),
|
||||
err.debug()
|
||||
);
|
||||
main_loop.quit();
|
||||
}
|
||||
MessageView::Eos(..) => {
|
||||
main_loop.quit();
|
||||
}
|
||||
MessageView::Buffering(buffering) => {
|
||||
// If the stream is live, we do not care about buffering.
|
||||
if is_live {
|
||||
return glib::Continue(true);
|
||||
let buffering_level = &buffering_level_clone;
|
||||
let pipeline = match pipeline_weak.upgrade() {
|
||||
Some(pipeline) => pipeline,
|
||||
None => return glib::Continue(false),
|
||||
};
|
||||
let main_loop = &main_loop_clone;
|
||||
match msg.view() {
|
||||
MessageView::Error(err) => {
|
||||
println!(
|
||||
"Error from {:?}: {} ({:?})",
|
||||
err.src().map(|s| s.path_string()),
|
||||
err.error(),
|
||||
err.debug()
|
||||
);
|
||||
main_loop.quit();
|
||||
}
|
||||
MessageView::Eos(..) => {
|
||||
main_loop.quit();
|
||||
}
|
||||
MessageView::Buffering(buffering) => {
|
||||
// If the stream is live, we do not care about buffering.
|
||||
if is_live {
|
||||
return glib::Continue(true);
|
||||
}
|
||||
|
||||
// Wait until buffering is complete before start/resume playing.
|
||||
let percent = buffering.percent();
|
||||
if percent < 100 {
|
||||
// Wait until buffering is complete before start/resume playing.
|
||||
let percent = buffering.percent();
|
||||
if percent < 100 {
|
||||
let _ = pipeline.set_state(gst::State::Paused);
|
||||
} else {
|
||||
let _ = pipeline.set_state(gst::State::Playing);
|
||||
}
|
||||
*buffering_level.lock().unwrap() = percent;
|
||||
}
|
||||
MessageView::ClockLost(_) => {
|
||||
// Get a new clock.
|
||||
let _ = pipeline.set_state(gst::State::Paused);
|
||||
} else {
|
||||
let _ = pipeline.set_state(gst::State::Playing);
|
||||
}
|
||||
*buffering_level.lock().unwrap() = percent;
|
||||
}
|
||||
MessageView::ClockLost(_) => {
|
||||
// Get a new clock.
|
||||
let _ = pipeline.set_state(gst::State::Paused);
|
||||
let _ = pipeline.set_state(gst::State::Playing);
|
||||
}
|
||||
_ => (),
|
||||
};
|
||||
_ => (),
|
||||
};
|
||||
|
||||
glib::Continue(true)
|
||||
})
|
||||
.expect("Failed to add bus watch");
|
||||
glib::Continue(true)
|
||||
})
|
||||
.expect("Failed to add bus watch");
|
||||
|
||||
pipeline.connect("deep-notify::temp-location", false, |args| {
|
||||
let download_buffer = args[1].get::<gst::Object>().unwrap();
|
||||
|
@ -177,7 +178,6 @@ fn tutorial_main() -> Result<(), Error> {
|
|||
// Shutdown pipeline
|
||||
pipeline.set_state(gst::State::Null)?;
|
||||
|
||||
bus.remove_watch()?;
|
||||
timeout_id.remove();
|
||||
|
||||
Ok(())
|
||||
|
|
|
@ -145,7 +145,7 @@ fn tutorial_main() -> Result<(), Error> {
|
|||
let main_loop_clone = main_loop.clone();
|
||||
let bus = pipeline.bus().unwrap();
|
||||
let pipeline_weak = pipeline.downgrade();
|
||||
bus.add_watch(move |_bus, message| {
|
||||
let _bus_watch = bus.add_watch(move |_bus, message| {
|
||||
use gst::MessageView;
|
||||
|
||||
let pipeline = match pipeline_weak.upgrade() {
|
||||
|
|
Loading…
Reference in a new issue