From 213020165ad4b8f4b4e3c409ba3f4ce3bf4e93fc Mon Sep 17 00:00:00 2001 From: Bilal Elmoussaoui Date: Sat, 6 Nov 2021 18:09:27 +0100 Subject: [PATCH] manual changes post ObjectExt improvements --- examples/src/bin/decodebin.rs | 2 +- examples/src/bin/encodebin.rs | 10 +- examples/src/bin/gtksink.rs | 10 +- examples/src/bin/overlay-composition.rs | 276 ++++++++++++----------- examples/src/bin/pango-cairo.rs | 140 ++++++------ examples/src/bin/playbin.rs | 79 +++---- examples/src/bin/rtpfecclient.rs | 25 +- examples/src/bin/rtpfecserver.rs | 26 +-- examples/src/bin/rtsp-server-subclass.rs | 4 +- examples/src/bin/thumbnail.rs | 2 +- examples/src/bin/toc.rs | 2 +- examples/src/bin/transmux.rs | 101 ++++----- examples/src/bin/video_converter.rs | 12 +- examples/src/glupload.rs | 14 +- gstreamer-app/src/app_sink.rs | 2 +- gstreamer-app/src/app_src.rs | 18 +- gstreamer-app/src/lib.rs | 1 + gstreamer-audio/src/lib.rs | 1 + gstreamer-base/src/aggregator.rs | 24 +- gstreamer-base/src/lib.rs | 1 + gstreamer-check/src/lib.rs | 1 + gstreamer-controller/src/lib.rs | 1 + gstreamer-editing-services/src/lib.rs | 1 + gstreamer-gl/src/lib.rs | 1 + gstreamer-net/src/lib.rs | 1 + gstreamer-pbutils/src/discoverer.rs | 19 +- gstreamer-pbutils/src/lib.rs | 1 + gstreamer-player/src/lib.rs | 1 + gstreamer-rtsp-server/src/lib.rs | 1 + gstreamer-video/src/lib.rs | 1 + gstreamer-webrtc/src/lib.rs | 1 + gstreamer/src/gobject.rs | 4 +- gstreamer/src/lib.rs | 1 + gstreamer/src/object.rs | 3 +- gstreamer/src/pad.rs | 6 +- gstreamer/src/subclass/element.rs | 2 +- tutorials/src/bin/basic-tutorial-13.rs | 11 +- tutorials/src/bin/basic-tutorial-3.rs | 4 +- tutorials/src/bin/basic-tutorial-4.rs | 4 +- tutorials/src/bin/basic-tutorial-5.rs | 54 ++--- tutorials/src/bin/basic-tutorial-7.rs | 2 +- tutorials/src/bin/playback-tutorial-1.rs | 51 ++--- tutorials/src/bin/playback-tutorial-4.rs | 16 +- 43 files changed, 421 insertions(+), 516 deletions(-) diff --git a/examples/src/bin/decodebin.rs b/examples/src/bin/decodebin.rs index 3a1ea1335..7e7c6bec0 100644 --- a/examples/src/bin/decodebin.rs +++ b/examples/src/bin/decodebin.rs @@ -81,7 +81,7 @@ fn example_main() -> Result<(), Error> { gst::ElementFactory::make("decodebin", None).map_err(|_| MissingElement("decodebin"))?; // Tell the filesrc what file to load - src.set_property("location", uri)?; + src.set_property("location", uri); pipeline.add_many(&[&src, &decodebin])?; gst::Element::link_many(&[&src, &decodebin])?; diff --git a/examples/src/bin/encodebin.rs b/examples/src/bin/encodebin.rs index bb0f07149..aeba090a2 100644 --- a/examples/src/bin/encodebin.rs +++ b/examples/src/bin/encodebin.rs @@ -76,9 +76,7 @@ fn configure_encodebin(encodebin: &gst::Element) { .build(); // Finally, apply the EncodingProfile onto our encodebin element. - encodebin - .set_property("profile", &container_profile) - .expect("set profile property failed"); + encodebin.set_property("profile", &container_profile); } fn example_main() -> Result<(), Error> { @@ -104,10 +102,8 @@ fn example_main() -> Result<(), Error> { let sink = gst::ElementFactory::make("filesink", None).map_err(|_| MissingElement("filesink"))?; - src.set_property("uri", uri) - .expect("setting URI Property failed"); - sink.set_property("location", output_file) - .expect("setting location property failed"); + src.set_property("uri", uri); + sink.set_property("location", output_file); // Configure the encodebin. // Here we tell the bin what format we expect it to create at its output. diff --git a/examples/src/bin/gtksink.rs b/examples/src/bin/gtksink.rs index 70f072e6d..e9cec0a30 100644 --- a/examples/src/bin/gtksink.rs +++ b/examples/src/bin/gtksink.rs @@ -33,11 +33,11 @@ fn create_ui(app: >k::Application) { // video frames to our texture (if they are not already in the GPU). Now we tell the OpenGL-sink // about our gtkglsink element, form where it will retrieve the OpenGL texture to fill. let glsinkbin = gst::ElementFactory::make("glsinkbin", None).unwrap(); - glsinkbin.set_property("sink", >kglsink).unwrap(); + glsinkbin.set_property("sink", >kglsink); // The gtkglsink creates the gtk widget for us. This is accessible through a property. // So we get it and use it later to add it to our gui. - let widget = gtkglsink.property("widget").unwrap(); - (glsinkbin, widget.get::().unwrap()) + let widget = gtkglsink.property::("widget"); + (glsinkbin, widget) } else { // Unfortunately, using the OpenGL widget didn't work out, so we will have to render // our frames manually, using the CPU. An example why this may fail is, when @@ -45,8 +45,8 @@ fn create_ui(app: >k::Application) { let sink = gst::ElementFactory::make("gtksink", None).unwrap(); // The gtksink creates the gtk widget for us. This is accessible through a property. // So we get it and use it later to add it to our gui. - let widget = sink.property("widget").unwrap(); - (sink, widget.get::().unwrap()) + let widget = sink.property::("widget"); + (sink, widget) }; pipeline.add_many(&[&src, &sink]).unwrap(); diff --git a/examples/src/bin/overlay-composition.rs b/examples/src/bin/overlay-composition.rs index f14533d8f..324384745 100644 --- a/examples/src/bin/overlay-composition.rs +++ b/examples/src/bin/overlay-composition.rs @@ -85,7 +85,7 @@ fn create_pipeline() -> Result { .field("height", 800i32) .field("framerate", gst::Fraction::new(15, 1)) .build(); - capsfilter.set_property("caps", &caps).unwrap(); + capsfilter.set_property("caps", &caps); // The videotestsrc supports multiple test patterns. In this example, we will use the // pattern with a white ball moving around the video's center point. @@ -131,142 +131,146 @@ fn create_pipeline() -> Result { // // In this case, the signal passes the gst::Element and a gst::Sample with // the current buffer - overlay - .connect("draw", false, move |args| { - use std::f64::consts::PI; + overlay.connect("draw", false, move |args| { + use std::f64::consts::PI; - let drawer = &drawer_clone; - let drawer = drawer.lock().unwrap(); + let drawer = &drawer_clone; + let drawer = drawer.lock().unwrap(); - // Get the signal's arguments - let _overlay = args[0].get::().unwrap(); - let sample = args[1].get::().unwrap(); - let buffer = sample.buffer().unwrap(); - let timestamp = buffer.pts().unwrap(); + // Get the signal's arguments + let _overlay = args[0].get::().unwrap(); + let sample = args[1].get::().unwrap(); + let buffer = sample.buffer().unwrap(); + let timestamp = buffer.pts().unwrap(); - let info = drawer.info.as_ref().unwrap(); - let layout = drawer.layout.borrow(); + let info = drawer.info.as_ref().unwrap(); + let layout = drawer.layout.borrow(); - let angle = 2.0 - * PI - * (timestamp % (10 * gst::ClockTime::SECOND)).nseconds() as f64 - / (10.0 * gst::ClockTime::SECOND.nseconds() as f64); + let angle = 2.0 * PI * (timestamp % (10 * gst::ClockTime::SECOND)).nseconds() as f64 + / (10.0 * gst::ClockTime::SECOND.nseconds() as f64); - /* Create a gst::Buffer for Cairo to draw into */ - let frame_width = info.width() as usize; - let frame_height = info.height() as usize; - let stride = 4 * frame_width; - let frame_size = stride * frame_height; + /* Create a gst::Buffer for Cairo to draw into */ + let frame_width = info.width() as usize; + let frame_height = info.height() as usize; + let stride = 4 * frame_width; + let frame_size = stride * frame_height; - /* Create an RGBA buffer, and add a video meta that the videooverlaycomposition expects */ - let mut buffer = gst::Buffer::with_size(frame_size).unwrap(); + /* Create an RGBA buffer, and add a video meta that the videooverlaycomposition expects */ + let mut buffer = gst::Buffer::with_size(frame_size).unwrap(); - gst_video::VideoMeta::add( - buffer.get_mut().unwrap(), - gst_video::VideoFrameFlags::empty(), - gst_video::VideoFormat::Bgra, - frame_width as u32, - frame_height as u32, - ).unwrap(); - - let buffer = buffer.into_mapped_buffer_writable().unwrap(); - let buffer = { - let buffer_ptr = unsafe { buffer.buffer().as_ptr() }; - let surface = cairo::ImageSurface::create_for_data( - buffer, - cairo::Format::ARgb32, - frame_width as i32, - frame_height as i32, - stride as i32, - ) - .unwrap(); - - let cr = cairo::Context::new(&surface).expect("Failed to create cairo context"); - - cr.save().expect("Failed to save state"); - cr.set_operator(cairo::Operator::Clear); - cr.paint().expect("Failed to clear background"); - cr.restore().expect("Failed to restore state"); - - // The image we draw (the text) will be static, but we will change the - // transformation on the drawing context, which rotates and shifts everything - // that we draw afterwards. Like this, we have no complicated calulations - // in the actual drawing below. - // Calling multiple transformation methods after each other will apply the - // new transformation on top. If you repeat the cr.rotate(angle) line below - // this a second time, everything in the canvas will rotate twice as fast. - cr.translate( - f64::from(info.width()) / 2.0, - f64::from(info.height()) / 2.0, - ); - cr.rotate(angle); - - // This loop will render 10 times the string "GStreamer" in a circle - for i in 0..10 { - // Cairo, like most rendering frameworks, is using a stack for transformations - // with this, we push our current transformation onto this stack - allowing us - // to make temporary changes / render something / and then returning to the - // previous transformations. - cr.save().expect("Failed to save state"); - - let angle = (360. * f64::from(i)) / 10.0; - let red = (1.0 + f64::cos((angle - 60.0) * PI / 180.0)) / 2.0; - cr.set_source_rgb(red, 0.0, 1.0 - red); - cr.rotate(angle * PI / 180.0); - - // Update the text layout. This function is only updating pango's internal state. - // So e.g. that after a 90 degree rotation it knows that what was previously going - // to end up as a 200x100 rectangle would now be 100x200. - pangocairo::functions::update_layout(&cr, &**layout); - let (width, _height) = layout.size(); - // Using width and height of the text, we can properly possition it within - // our canvas. - cr.move_to( - -(f64::from(width) / f64::from(pango::SCALE)) / 2.0, - -(f64::from(info.height())) / 2.0, - ); - // After telling the layout object where to draw itself, we actually tell - // it to draw itself into our cairo context. - pangocairo::functions::show_layout(&cr, &**layout); - - // Here we go one step up in our stack of transformations, removing any - // changes we did to them since the last call to cr.save(); - cr.restore().expect("Failed to restore state"); - } - - // Safety: The surface still owns a mutable reference to the buffer but our reference - // to the surface here is the last one. After dropping the surface the buffer would be - // freed, so we keep an additional strong reference here before dropping the surface, - // which is then returned. As such it's guaranteed that nothing is using the buffer - // anymore mutably. - drop(cr); - unsafe { - assert_eq!( - cairo::ffi::cairo_surface_get_reference_count(surface.to_raw_none()), - 1 - ); - let buffer = glib::translate::from_glib_none(buffer_ptr); - drop(surface); - buffer - } - }; - - /* Turn the buffer into a VideoOverlayRectangle, then place - * that into a VideoOverlayComposition and return it. - * - * A VideoOverlayComposition can take a Vec of such rectangles - * spaced around the video frame, but we're just outputting 1 - * here */ - let rect = gst_video::VideoOverlayRectangle::new_raw( - &buffer, - 0, 0, frame_width as u32, frame_height as u32, - gst_video::VideoOverlayFormatFlags::PREMULTIPLIED_ALPHA, - ); - - Some(gst_video::VideoOverlayComposition::new(Some(&rect)).unwrap().to_value()) - }) + gst_video::VideoMeta::add( + buffer.get_mut().unwrap(), + gst_video::VideoFrameFlags::empty(), + gst_video::VideoFormat::Bgra, + frame_width as u32, + frame_height as u32, + ) .unwrap(); + let buffer = buffer.into_mapped_buffer_writable().unwrap(); + let buffer = { + let buffer_ptr = unsafe { buffer.buffer().as_ptr() }; + let surface = cairo::ImageSurface::create_for_data( + buffer, + cairo::Format::ARgb32, + frame_width as i32, + frame_height as i32, + stride as i32, + ) + .unwrap(); + + let cr = cairo::Context::new(&surface).expect("Failed to create cairo context"); + + cr.save().expect("Failed to save state"); + cr.set_operator(cairo::Operator::Clear); + cr.paint().expect("Failed to clear background"); + cr.restore().expect("Failed to restore state"); + + // The image we draw (the text) will be static, but we will change the + // transformation on the drawing context, which rotates and shifts everything + // that we draw afterwards. Like this, we have no complicated calulations + // in the actual drawing below. + // Calling multiple transformation methods after each other will apply the + // new transformation on top. If you repeat the cr.rotate(angle) line below + // this a second time, everything in the canvas will rotate twice as fast. + cr.translate( + f64::from(info.width()) / 2.0, + f64::from(info.height()) / 2.0, + ); + cr.rotate(angle); + + // This loop will render 10 times the string "GStreamer" in a circle + for i in 0..10 { + // Cairo, like most rendering frameworks, is using a stack for transformations + // with this, we push our current transformation onto this stack - allowing us + // to make temporary changes / render something / and then returning to the + // previous transformations. + cr.save().expect("Failed to save state"); + + let angle = (360. * f64::from(i)) / 10.0; + let red = (1.0 + f64::cos((angle - 60.0) * PI / 180.0)) / 2.0; + cr.set_source_rgb(red, 0.0, 1.0 - red); + cr.rotate(angle * PI / 180.0); + + // Update the text layout. This function is only updating pango's internal state. + // So e.g. that after a 90 degree rotation it knows that what was previously going + // to end up as a 200x100 rectangle would now be 100x200. + pangocairo::functions::update_layout(&cr, &**layout); + let (width, _height) = layout.size(); + // Using width and height of the text, we can properly possition it within + // our canvas. + cr.move_to( + -(f64::from(width) / f64::from(pango::SCALE)) / 2.0, + -(f64::from(info.height())) / 2.0, + ); + // After telling the layout object where to draw itself, we actually tell + // it to draw itself into our cairo context. + pangocairo::functions::show_layout(&cr, &**layout); + + // Here we go one step up in our stack of transformations, removing any + // changes we did to them since the last call to cr.save(); + cr.restore().expect("Failed to restore state"); + } + + // Safety: The surface still owns a mutable reference to the buffer but our reference + // to the surface here is the last one. After dropping the surface the buffer would be + // freed, so we keep an additional strong reference here before dropping the surface, + // which is then returned. As such it's guaranteed that nothing is using the buffer + // anymore mutably. + drop(cr); + unsafe { + assert_eq!( + cairo::ffi::cairo_surface_get_reference_count(surface.to_raw_none()), + 1 + ); + let buffer = glib::translate::from_glib_none(buffer_ptr); + drop(surface); + buffer + } + }; + + /* Turn the buffer into a VideoOverlayRectangle, then place + * that into a VideoOverlayComposition and return it. + * + * A VideoOverlayComposition can take a Vec of such rectangles + * spaced around the video frame, but we're just outputting 1 + * here */ + let rect = gst_video::VideoOverlayRectangle::new_raw( + &buffer, + 0, + 0, + frame_width as u32, + frame_height as u32, + gst_video::VideoOverlayFormatFlags::PREMULTIPLIED_ALPHA, + ); + + Some( + gst_video::VideoOverlayComposition::new(Some(&rect)) + .unwrap() + .to_value(), + ) + }); + // Add a signal handler to the overlay's "caps-changed" signal. This could e.g. // be called when the sink that we render to does not support resizing the image // itself - but the user just changed the window-size. The element after the overlay @@ -274,17 +278,15 @@ fn create_pipeline() -> Result { // resize our canvas's size. // Another possibility for when this might happen is, when our video is a network // stream that dynamically changes resolution when enough bandwith is available. - overlay - .connect("caps-changed", false, move |args| { - let _overlay = args[0].get::().unwrap(); - let caps = args[1].get::().unwrap(); + overlay.connect("caps-changed", false, move |args| { + let _overlay = args[0].get::().unwrap(); + let caps = args[1].get::().unwrap(); - let mut drawer = drawer.lock().unwrap(); - drawer.info = Some(gst_video::VideoInfo::from_caps(&caps).unwrap()); + let mut drawer = drawer.lock().unwrap(); + drawer.info = Some(gst_video::VideoInfo::from_caps(&caps).unwrap()); - None - }) - .unwrap(); + None + }); Ok(pipeline) } diff --git a/examples/src/bin/pango-cairo.rs b/examples/src/bin/pango-cairo.rs index 1f6a60c87..b5f558de2 100644 --- a/examples/src/bin/pango-cairo.rs +++ b/examples/src/bin/pango-cairo.rs @@ -83,7 +83,7 @@ fn create_pipeline() -> Result { .field("width", 800i32) .field("height", 800i32) .build(); - capsfilter.set_property("caps", &caps).unwrap(); + capsfilter.set_property("caps", &caps); // The videotestsrc supports multiple test patterns. In this example, we will use the // pattern with a white ball moving around the video's center point. @@ -125,76 +125,74 @@ fn create_pipeline() -> Result { // passed as array of glib::Value. For a documentation about the actual arguments // it is always a good idea to either check the element's signals using either // gst-inspect, or the online documentation. - overlay - .connect("draw", false, move |args| { - use std::f64::consts::PI; + overlay.connect("draw", false, move |args| { + use std::f64::consts::PI; - let drawer = &drawer_clone; - let drawer = drawer.lock().unwrap(); + let drawer = &drawer_clone; + let drawer = drawer.lock().unwrap(); - // Get the signal's arguments - let _overlay = args[0].get::().unwrap(); - // This is the cairo context. This is the root of all of cairo's - // drawing functionality. - let cr = args[1].get::().unwrap(); - let timestamp = args[2].get::().unwrap(); - let _duration = args[3].get::().unwrap(); + // Get the signal's arguments + let _overlay = args[0].get::().unwrap(); + // This is the cairo context. This is the root of all of cairo's + // drawing functionality. + let cr = args[1].get::().unwrap(); + let timestamp = args[2].get::().unwrap(); + let _duration = args[3].get::().unwrap(); - let info = drawer.info.as_ref().unwrap(); - let layout = drawer.layout.borrow(); + let info = drawer.info.as_ref().unwrap(); + let layout = drawer.layout.borrow(); - let angle = 2.0 * PI * (timestamp % (10 * gst::ClockTime::SECOND)).nseconds() as f64 - / (10.0 * gst::ClockTime::SECOND.nseconds() as f64); + let angle = 2.0 * PI * (timestamp % (10 * gst::ClockTime::SECOND)).nseconds() as f64 + / (10.0 * gst::ClockTime::SECOND.nseconds() as f64); - // The image we draw (the text) will be static, but we will change the - // transformation on the drawing context, which rotates and shifts everything - // that we draw afterwards. Like this, we have no complicated calulations - // in the actual drawing below. - // Calling multiple transformation methods after each other will apply the - // new transformation on top. If you repeat the cr.rotate(angle) line below - // this a second time, everything in the canvas will rotate twice as fast. - cr.translate( - f64::from(info.width()) / 2.0, - f64::from(info.height()) / 2.0, + // The image we draw (the text) will be static, but we will change the + // transformation on the drawing context, which rotates and shifts everything + // that we draw afterwards. Like this, we have no complicated calulations + // in the actual drawing below. + // Calling multiple transformation methods after each other will apply the + // new transformation on top. If you repeat the cr.rotate(angle) line below + // this a second time, everything in the canvas will rotate twice as fast. + cr.translate( + f64::from(info.width()) / 2.0, + f64::from(info.height()) / 2.0, + ); + cr.rotate(angle); + + // This loop will render 10 times the string "GStreamer" in a circle + for i in 0..10 { + // Cairo, like most rendering frameworks, is using a stack for transformations + // with this, we push our current transformation onto this stack - allowing us + // to make temporary changes / render something / and then returning to the + // previous transformations. + cr.save().expect("Failed to save state"); + + let angle = (360. * f64::from(i)) / 10.0; + let red = (1.0 + f64::cos((angle - 60.0) * PI / 180.0)) / 2.0; + cr.set_source_rgb(red, 0.0, 1.0 - red); + cr.rotate(angle * PI / 180.0); + + // Update the text layout. This function is only updating pango's internal state. + // So e.g. that after a 90 degree rotation it knows that what was previously going + // to end up as a 200x100 rectangle would now be 100x200. + pangocairo::functions::update_layout(&cr, &**layout); + let (width, _height) = layout.size(); + // Using width and height of the text, we can properly possition it within + // our canvas. + cr.move_to( + -(f64::from(width) / f64::from(pango::SCALE)) / 2.0, + -(f64::from(info.height())) / 2.0, ); - cr.rotate(angle); + // After telling the layout object where to draw itself, we actually tell + // it to draw itself into our cairo context. + pangocairo::functions::show_layout(&cr, &**layout); - // This loop will render 10 times the string "GStreamer" in a circle - for i in 0..10 { - // Cairo, like most rendering frameworks, is using a stack for transformations - // with this, we push our current transformation onto this stack - allowing us - // to make temporary changes / render something / and then returning to the - // previous transformations. - cr.save().expect("Failed to save state"); + // Here we go one step up in our stack of transformations, removing any + // changes we did to them since the last call to cr.save(); + cr.restore().expect("Failed to restore state"); + } - let angle = (360. * f64::from(i)) / 10.0; - let red = (1.0 + f64::cos((angle - 60.0) * PI / 180.0)) / 2.0; - cr.set_source_rgb(red, 0.0, 1.0 - red); - cr.rotate(angle * PI / 180.0); - - // Update the text layout. This function is only updating pango's internal state. - // So e.g. that after a 90 degree rotation it knows that what was previously going - // to end up as a 200x100 rectangle would now be 100x200. - pangocairo::functions::update_layout(&cr, &**layout); - let (width, _height) = layout.size(); - // Using width and height of the text, we can properly possition it within - // our canvas. - cr.move_to( - -(f64::from(width) / f64::from(pango::SCALE)) / 2.0, - -(f64::from(info.height())) / 2.0, - ); - // After telling the layout object where to draw itself, we actually tell - // it to draw itself into our cairo context. - pangocairo::functions::show_layout(&cr, &**layout); - - // Here we go one step up in our stack of transformations, removing any - // changes we did to them since the last call to cr.save(); - cr.restore().expect("Failed to restore state"); - } - - None - }) - .unwrap(); + None + }); // Add a signal handler to the overlay's "caps-changed" signal. This could e.g. // be called when the sink that we render to does not support resizing the image @@ -203,17 +201,15 @@ fn create_pipeline() -> Result { // resize our canvas's size. // Another possibility for when this might happen is, when our video is a network // stream that dynamically changes resolution when enough bandwith is available. - overlay - .connect("caps-changed", false, move |args| { - let _overlay = args[0].get::().unwrap(); - let caps = args[1].get::().unwrap(); + overlay.connect("caps-changed", false, move |args| { + let _overlay = args[0].get::().unwrap(); + let caps = args[1].get::().unwrap(); - let mut drawer = drawer.lock().unwrap(); - drawer.info = Some(gst_video::VideoInfo::from_caps(&caps).unwrap()); + let mut drawer = drawer.lock().unwrap(); + drawer.info = Some(gst_video::VideoInfo::from_caps(&caps).unwrap()); - None - }) - .unwrap(); + None + }); Ok(pipeline) } diff --git a/examples/src/bin/playbin.rs b/examples/src/bin/playbin.rs index 5bf48efe1..ed5c5c7a1 100644 --- a/examples/src/bin/playbin.rs +++ b/examples/src/bin/playbin.rs @@ -29,7 +29,7 @@ fn example_main() { // Create a new playbin element, and tell it what uri to play back. let playbin = gst::ElementFactory::make("playbin", None).unwrap(); - playbin.set_property("uri", uri).unwrap(); + playbin.set_property("uri", uri); // For flags handling // With flags, one can configure playbin's behavior such as whether it @@ -50,53 +50,48 @@ fn example_main() { // - Live streams (such as internet radios) update this metadata during the stream // Note that this signal will be emitted from the streaming threads usually, // not the application's threads! - playbin - .connect("audio-tags-changed", false, |values| { - // The metadata of any of the contained audio streams changed - // In the case of a live-stream from an internet radio, this could for example - // mark the beginning of a new track, or a new DJ. - let playbin = values[0] - .get::() - .expect("playbin \"audio-tags-changed\" signal values[1]"); - // This gets the index of the stream that changed. This is neccessary, since - // there could e.g. be multiple audio streams (english, spanish, ...). - let idx = values[1] - .get::() - .expect("playbin \"audio-tags-changed\" signal values[1]"); + playbin.connect("audio-tags-changed", false, |values| { + // The metadata of any of the contained audio streams changed + // In the case of a live-stream from an internet radio, this could for example + // mark the beginning of a new track, or a new DJ. + let playbin = values[0] + .get::() + .expect("playbin \"audio-tags-changed\" signal values[1]"); + // This gets the index of the stream that changed. This is neccessary, since + // there could e.g. be multiple audio streams (english, spanish, ...). + let idx = values[1] + .get::() + .expect("playbin \"audio-tags-changed\" signal values[1]"); - println!("audio tags of audio stream {} changed:", idx); + println!("audio tags of audio stream {} changed:", idx); - // HELP: is this correct? - // We were only notified about the change of metadata. If we want to do - // something with it, we first need to actually query the metadata from the playbin. - // We do this by facilliating the get-audio-tags action-signal on playbin. - // Sending an action-signal to an element essentially is a function call on the element. - // It is done that way, because elements do not have their own function API, they are - // relying on GStreamer and GLib's API. The only way an element can communicate with an - // application is via properties, signals or action signals (or custom messages, events, queries). - // So what the following code does, is essentially asking playbin to tell us its already - // internally stored tag list for this stream index. - let tags = playbin - .emit_by_name("get-audio-tags", &[&idx]) - .unwrap() - .unwrap(); - let tags = tags.get::().expect("tags"); + // HELP: is this correct? + // We were only notified about the change of metadata. If we want to do + // something with it, we first need to actually query the metadata from the playbin. + // We do this by facilliating the get-audio-tags action-signal on playbin. + // Sending an action-signal to an element essentially is a function call on the element. + // It is done that way, because elements do not have their own function API, they are + // relying on GStreamer and GLib's API. The only way an element can communicate with an + // application is via properties, signals or action signals (or custom messages, events, queries). + // So what the following code does, is essentially asking playbin to tell us its already + // internally stored tag list for this stream index. + let tags = playbin.emit_by_name("get-audio-tags", &[&idx]).unwrap(); + let tags = tags.get::().expect("tags"); - if let Some(artist) = tags.get::() { - println!(" Artist: {}", artist.get()); - } + if let Some(artist) = tags.get::() { + println!(" Artist: {}", artist.get()); + } - if let Some(title) = tags.get::() { - println!(" Title: {}", title.get()); - } + if let Some(title) = tags.get::() { + println!(" Title: {}", title.get()); + } - if let Some(album) = tags.get::() { - println!(" Album: {}", album.get()); - } + if let Some(album) = tags.get::() { + println!(" Album: {}", album.get()); + } - None - }) - .unwrap(); + None + }); // The playbin element itself is a playbin, so it can be used as one, despite being // created from an element factory. diff --git a/examples/src/bin/rtpfecclient.rs b/examples/src/bin/rtpfecclient.rs index 82bdd3189..653241507 100644 --- a/examples/src/bin/rtpfecclient.rs +++ b/examples/src/bin/rtpfecclient.rs @@ -87,12 +87,11 @@ fn make_fec_decoder(rtpbin: &gst::Element, sess_id: u32) -> Result() .unwrap(); - fecdec.set_property("storage", &internal_storage)?; - fecdec.set_property("pt", 100u32)?; + fecdec.set_property("storage", &internal_storage); + fecdec.set_property("pt", 100u32); Ok(fecdec) } @@ -134,7 +133,7 @@ fn example_main() -> Result<(), Error> { pipeline.add_many(&[&enc, &mux, &sink])?; gst::Element::link_many(&[&filter, &enc, &mux, &sink])?; - sink.set_property("location", "out.mkv")?; + sink.set_property("location", "out.mkv"); enc.set_property_from_str("tune", "zerolatency")?; eprintln!("Recording to out.mkv"); } @@ -147,10 +146,10 @@ fn example_main() -> Result<(), Error> { let storage = values[1] .get::() .expect("rtpbin \"new-storage\" signal values[1]"); - storage.set_property("size-time", 250_000_000u64).unwrap(); + storage.set_property("size-time", 250_000_000u64); None - })?; + }); rtpbin.connect("request-pt-map", false, |values| { let pt = values[2] @@ -175,7 +174,7 @@ fn example_main() -> Result<(), Error> { ), _ => None, } - })?; + }); rtpbin.connect("request-fec-decoder", false, |values| { let rtpbin = values[0] @@ -197,7 +196,7 @@ fn example_main() -> Result<(), Error> { None } } - })?; + }); let srcpad = static_pad(&netsim, "src")?; let sinkpad = request_pad(&rtpbin, "recv_rtp_sink_0")?; @@ -232,11 +231,11 @@ fn example_main() -> Result<(), Error> { .field("height", 1080i32) .build(); - src.set_property("address", "127.0.0.1")?; - src.set_property("caps", &rtp_caps)?; - netsim.set_property("drop-probability", drop_probability)?; - rtpbin.set_property("do-lost", true)?; - filter.set_property("caps", &video_caps)?; + src.set_property("address", "127.0.0.1"); + src.set_property("caps", &rtp_caps); + netsim.set_property("drop-probability", drop_probability); + rtpbin.set_property("do-lost", true); + filter.set_property("caps", &video_caps); let bus = pipeline .bus() diff --git a/examples/src/bin/rtpfecserver.rs b/examples/src/bin/rtpfecserver.rs index f0098a7f7..273cf845e 100644 --- a/examples/src/bin/rtpfecserver.rs +++ b/examples/src/bin/rtpfecserver.rs @@ -72,9 +72,9 @@ fn connect_decodebin_pad(src_pad: &gst::Pad, sink: &gst::Element) -> Result<(), fn make_fec_encoder(fec_percentage: u32) -> Result { let fecenc = make_element("rtpulpfecenc", None)?; - fecenc.set_property("pt", 100u32)?; - fecenc.set_property("multipacket", true)?; - fecenc.set_property("percentage", fec_percentage)?; + fecenc.set_property("pt", 100u32); + fecenc.set_property("multipacket", true); + fecenc.set_property("percentage", fec_percentage); Ok(fecenc) } @@ -125,7 +125,7 @@ fn example_main() -> Result<(), Error> { None } } - })?; + }); let srcpad = static_pad(&q2, "src")?; let sinkpad = request_pad(&rtpbin, "send_rtp_sink_0")?; @@ -152,16 +152,16 @@ fn example_main() -> Result<(), Error> { let video_caps = gst::Caps::builder("video/x-raw").build(); src.set_property_from_str("pattern", "ball")?; - sink.set_property("host", "127.0.0.1")?; - sink.set_property("sync", true)?; - enc.set_property("keyframe-max-dist", 30i32)?; - enc.set_property("threads", 12i32)?; - enc.set_property("cpu-used", -16i32)?; - enc.set_property("deadline", 1i64)?; + sink.set_property("host", "127.0.0.1"); + sink.set_property("sync", true); + enc.set_property("keyframe-max-dist", 30i32); + enc.set_property("threads", 12i32); + enc.set_property("cpu-used", -16i32); + enc.set_property("deadline", 1i64); enc.set_property_from_str("error-resilient", "default")?; - src.set_property("expose-all-streams", false)?; - src.set_property("caps", video_caps)?; - src.set_property("uri", uri)?; + src.set_property("expose-all-streams", false); + src.set_property("caps", video_caps); + src.set_property("uri", uri); let bus = pipeline .bus() diff --git a/examples/src/bin/rtsp-server-subclass.rs b/examples/src/bin/rtsp-server-subclass.rs index c5e026283..3feff83c9 100644 --- a/examples/src/bin/rtsp-server-subclass.rs +++ b/examples/src/bin/rtsp-server-subclass.rs @@ -130,10 +130,10 @@ mod media_factory { let pay = gst::ElementFactory::make("rtpvp8pay", Some("pay0")).unwrap(); // Configure the videotestsrc live - src.set_property("is-live", true).unwrap(); + src.set_property("is-live", true); // Produce encoded data as fast as possible - enc.set_property("deadline", 1i64).unwrap(); + enc.set_property("deadline", 1i64); bin.add_many(&[&src, &enc, &pay]).unwrap(); gst::Element::link_many(&[&src, &enc, &pay]).unwrap(); diff --git a/examples/src/bin/thumbnail.rs b/examples/src/bin/thumbnail.rs index 701dee3c8..b29a85372 100644 --- a/examples/src/bin/thumbnail.rs +++ b/examples/src/bin/thumbnail.rs @@ -47,7 +47,7 @@ fn create_pipeline(uri: String, out_path: std::path::PathBuf) -> Result Result<(), Error> { let sink = gst::ElementFactory::make("filesink", None).map_err(|_| MissingElement("filesink"))?; - sink.set_property("location", output_file) - .expect("setting location property failed"); + sink.set_property("location", output_file); // Increase the queue capacity to 100MB to avoid a stalling pipeline - queue - .set_property("max-size-buffers", 0u32) - .expect("changing capacity of multiqueue failed"); - queue - .set_property("max-size-time", 0u64) - .expect("changing capacity of multiqueue failed"); - queue - .set_property("max-size-bytes", 1024u32 * 1024 * 100) - .expect("changing capacity of multiqueue failed"); + queue.set_property("max-size-buffers", 0u32); + queue.set_property("max-size-time", 0u64); + queue.set_property("max-size-bytes", 1024u32 * 1024 * 100); pipeline .add_many(&[&src, &typefinder, &queue, &muxer, &sink]) @@ -90,55 +83,53 @@ fn example_main() -> Result<(), Error> { let pipeline_clone = pipeline.clone(); let typefinder_clone = typefinder.clone(); - typefinder - .connect("have-type", false, move |values| { - let (pipeline, typefinder) = (&pipeline_clone, &typefinder_clone); + typefinder.connect("have-type", false, move |values| { + let (pipeline, typefinder) = (&pipeline_clone, &typefinder_clone); - // Use the detected format to select between a small set of supported demuxers - // Hint: This should probably never be done manually, for stuff like this, - // the decodebin should be used, that does this stuff automatically and handles - // much more corner-cases. This is just for the sake of being an example. - let caps = values[2] - .get::() - .expect("typefinder \"have-type\" signal values[2]"); - let format_name = caps.structure(0).expect("Failed to get format name").name(); + // Use the detected format to select between a small set of supported demuxers + // Hint: This should probably never be done manually, for stuff like this, + // the decodebin should be used, that does this stuff automatically and handles + // much more corner-cases. This is just for the sake of being an example. + let caps = values[2] + .get::() + .expect("typefinder \"have-type\" signal values[2]"); + let format_name = caps.structure(0).expect("Failed to get format name").name(); - let demuxer = match format_name { - "video/x-matroska" | "video/webm" => { - gst::ElementFactory::make("matroskademux", None).expect("matroskademux missing") - } - "video/quicktime" => { - gst::ElementFactory::make("qtdemux", None).expect("qtdemux missing") - } - _ => { - eprintln!("Sorry, this format is not supported by this example."); - std::process::exit(-1); - } - }; + let demuxer = match format_name { + "video/x-matroska" | "video/webm" => { + gst::ElementFactory::make("matroskademux", None).expect("matroskademux missing") + } + "video/quicktime" => { + gst::ElementFactory::make("qtdemux", None).expect("qtdemux missing") + } + _ => { + eprintln!("Sorry, this format is not supported by this example."); + std::process::exit(-1); + } + }; - // We found a supported format and created the appropriate demuxer -> link it - pipeline - .add(&demuxer) - .expect("Failed to build remux pipeline"); - // We simply keep the typefinder element and pipe the data through it. - // Removing is non-trivial since it started reading data from the pipeline - // that the next element (the format specific demuxer) would need. - typefinder - .link(&demuxer) - .expect("Failed to build remux pipeline"); + // We found a supported format and created the appropriate demuxer -> link it + pipeline + .add(&demuxer) + .expect("Failed to build remux pipeline"); + // We simply keep the typefinder element and pipe the data through it. + // Removing is non-trivial since it started reading data from the pipeline + // that the next element (the format specific demuxer) would need. + typefinder + .link(&demuxer) + .expect("Failed to build remux pipeline"); - let queue_clone = queue.clone(); - let muxer_clone = muxer.clone(); - demuxer.connect_pad_added(move |demux, src_pad| { - handle_demux_pad_added(demux, src_pad, &queue_clone, &muxer_clone) - }); - demuxer - .sync_state_with_parent() - .expect("Failed to build remux pipeline"); + let queue_clone = queue.clone(); + let muxer_clone = muxer.clone(); + demuxer.connect_pad_added(move |demux, src_pad| { + handle_demux_pad_added(demux, src_pad, &queue_clone, &muxer_clone) + }); + demuxer + .sync_state_with_parent() + .expect("Failed to build remux pipeline"); - None - }) - .expect("Failed to register have-type signal of typefind"); + None + }); pipeline.set_state(gst::State::Playing)?; diff --git a/examples/src/bin/video_converter.rs b/examples/src/bin/video_converter.rs index 409f7796b..4b129c4da 100644 --- a/examples/src/bin/video_converter.rs +++ b/examples/src/bin/video_converter.rs @@ -24,10 +24,10 @@ fn example_main() { /* Completely contrived example that takes the 4:3 input video, cuts out a 5:4 frame * and then adds pillarbox borders to place it in a 16:9 target area */ /* The output will be the full frame: */ - sinkpad.set_property("xpos", 0i32).unwrap(); - sinkpad.set_property("ypos", 0i32).unwrap(); - sinkpad.set_property("width", 1280i32).unwrap(); - sinkpad.set_property("height", 720i32).unwrap(); + sinkpad.set_property("xpos", 0i32); + sinkpad.set_property("ypos", 0i32); + sinkpad.set_property("width", 1280i32); + sinkpad.set_property("height", 720i32); let mut converter_config = gst_video::VideoConverterConfig::new(); /* Crop the input frame to 5:4: */ @@ -41,9 +41,7 @@ fn example_main() { converter_config.set_dest_y(0); converter_config.set_dest_height(Some(720)); - sinkpad - .set_property("converter-config", &*converter_config) - .unwrap(); + sinkpad.set_property("converter-config", &*converter_config); pipeline .set_state(gst::State::Playing) .expect("Unable to set the pipeline to the `Playing` state"); diff --git a/examples/src/glupload.rs b/examples/src/glupload.rs index cc0f1fcb3..36ff104e3 100644 --- a/examples/src/glupload.rs +++ b/examples/src/glupload.rs @@ -543,9 +543,9 @@ impl App { .dynamic_cast::() .expect("Sink element is expected to be an appsink!"); - appsink.set_property("enable-last-sample", false)?; - appsink.set_property("emit-signals", false)?; - appsink.set_property("max-buffers", 1u32)?; + appsink.set_property("enable-last-sample", false); + appsink.set_property("emit-signals", false); + appsink.set_property("max-buffers", 1u32); let caps = gst::Caps::builder("video/x-raw") .features(&[&gst_gl::CAPS_FEATURE_MEMORY_GL_MEMORY]) @@ -571,7 +571,7 @@ impl App { let sink = gst::ElementFactory::make("glsinkbin", None) .map_err(|_| MissingElement("glsinkbin"))?; - sink.set_property("sink", &appsink)?; + sink.set_property("sink", &appsink); pipeline.add_many(&[&src, &sink])?; src.link(&sink)?; @@ -680,11 +680,7 @@ pub(crate) fn main_loop(app: App) -> Result<(), Error> { { if gst_gl_context.is_none() { - gst_gl_context = glupload - .property("context") - .unwrap() - .get::>() - .unwrap(); + gst_gl_context = glupload.property::>("context"); } let sync_meta = buffer.meta::().unwrap(); diff --git a/gstreamer-app/src/app_sink.rs b/gstreamer-app/src/app_sink.rs index 6536d3d83..9d2775321 100644 --- a/gstreamer-app/src/app_sink.rs +++ b/gstreamer-app/src/app_sink.rs @@ -1035,7 +1035,7 @@ mod tests { let videotestsrc = gst::ElementFactory::make("videotestsrc", None).unwrap(); let appsink = gst::ElementFactory::make("appsink", None).unwrap(); - videotestsrc.set_property("num-buffers", 5).unwrap(); + videotestsrc.set_property("num-buffers", 5); let pipeline = gst::Pipeline::new(None); pipeline.add(&videotestsrc).unwrap(); diff --git a/gstreamer-app/src/app_src.rs b/gstreamer-app/src/app_src.rs index 5d93323bb..2f8fdccf0 100644 --- a/gstreamer-app/src/app_src.rs +++ b/gstreamer-app/src/app_src.rs @@ -454,7 +454,7 @@ mod tests { let appsrc = gst::ElementFactory::make("appsrc", None).unwrap(); let fakesink = gst::ElementFactory::make("fakesink", None).unwrap(); - fakesink.set_property("signal-handoffs", true).unwrap(); + fakesink.set_property("signal-handoffs", true); let pipeline = gst::Pipeline::new(None); pipeline.add(&appsrc).unwrap(); @@ -475,17 +475,15 @@ mod tests { let handoff_count_reference = Arc::new(AtomicUsize::new(0)); - fakesink - .connect("handoff", false, { - let handoff_count_reference = Arc::clone(&handoff_count_reference); + fakesink.connect("handoff", false, { + let handoff_count_reference = Arc::clone(&handoff_count_reference); - move |_| { - handoff_count_reference.fetch_add(1, Ordering::AcqRel); + move |_| { + handoff_count_reference.fetch_add(1, Ordering::AcqRel); - None - } - }) - .unwrap(); + None + } + }); pipeline.set_state(gst::State::Playing).unwrap(); diff --git a/gstreamer-app/src/lib.rs b/gstreamer-app/src/lib.rs index eeb8ba67d..646ab8d5e 100644 --- a/gstreamer-app/src/lib.rs +++ b/gstreamer-app/src/lib.rs @@ -17,6 +17,7 @@ macro_rules! skip_assert_initialized { #[allow(clippy::too_many_arguments)] #[allow(clippy::match_same_arms)] #[allow(clippy::use_self)] +#[allow(unused_imports)] mod auto; pub use crate::auto::*; diff --git a/gstreamer-audio/src/lib.rs b/gstreamer-audio/src/lib.rs index b14bf5b99..98a64b950 100644 --- a/gstreamer-audio/src/lib.rs +++ b/gstreamer-audio/src/lib.rs @@ -26,6 +26,7 @@ macro_rules! skip_assert_initialized { #[allow(clippy::match_same_arms)] #[allow(clippy::use_self)] #[allow(clippy::needless_borrow)] +#[allow(unused_imports)] mod auto; pub use crate::auto::*; diff --git a/gstreamer-base/src/aggregator.rs b/gstreamer-base/src/aggregator.rs index 98d8369d0..db6a37caa 100644 --- a/gstreamer-base/src/aggregator.rs +++ b/gstreamer-base/src/aggregator.rs @@ -8,9 +8,6 @@ use glib::signal::{connect_raw, SignalHandlerId}; use glib::translate::*; #[cfg(any(feature = "v1_16", feature = "dox"))] #[cfg_attr(feature = "dox", doc(cfg(feature = "v1_16")))] -use glib::Value; -#[cfg(any(feature = "v1_16", feature = "dox"))] -#[cfg_attr(feature = "dox", doc(cfg(feature = "v1_16")))] use std::boxed::Box as Box_; use std::mem; #[cfg(any(feature = "v1_16", feature = "dox"))] @@ -129,29 +126,14 @@ impl> AggregatorExtManual for O { #[cfg(any(feature = "v1_16", feature = "dox"))] #[cfg_attr(feature = "dox", doc(cfg(feature = "v1_16")))] fn min_upstream_latency(&self) -> gst::ClockTime { - unsafe { - let mut value = Value::from_type(::static_type()); - glib::gobject_ffi::g_object_get_property( - self.to_glib_none().0 as *mut glib::gobject_ffi::GObject, - b"min-upstream-latency\0".as_ptr() as *const _, - value.to_glib_none_mut().0, - ); - value - .get() - .expect("AggregatorExtManual::min_upstream_latency") - } + self.as_ref().property("min-upstream-latency") } #[cfg(any(feature = "v1_16", feature = "dox"))] #[cfg_attr(feature = "dox", doc(cfg(feature = "v1_16")))] fn set_min_upstream_latency(&self, min_upstream_latency: gst::ClockTime) { - unsafe { - glib::gobject_ffi::g_object_set_property( - self.to_glib_none().0 as *mut glib::gobject_ffi::GObject, - b"min-upstream-latency\0".as_ptr() as *const _, - Value::from(&min_upstream_latency).to_glib_none().0, - ); - } + self.as_ref() + .set_property("min-upstream-latency", &min_upstream_latency); } #[cfg(any(feature = "v1_16", feature = "dox"))] diff --git a/gstreamer-base/src/lib.rs b/gstreamer-base/src/lib.rs index 98588d044..54d6e36df 100644 --- a/gstreamer-base/src/lib.rs +++ b/gstreamer-base/src/lib.rs @@ -25,6 +25,7 @@ macro_rules! skip_assert_initialized { #[allow(clippy::match_same_arms)] #[allow(clippy::type_complexity)] #[allow(clippy::use_self)] +#[allow(unused_imports)] mod auto; pub use crate::auto::functions::*; pub use crate::auto::*; diff --git a/gstreamer-check/src/lib.rs b/gstreamer-check/src/lib.rs index b570f1839..38016b741 100644 --- a/gstreamer-check/src/lib.rs +++ b/gstreamer-check/src/lib.rs @@ -21,6 +21,7 @@ macro_rules! assert_initialized_main_thread { #[allow(clippy::match_same_arms)] #[allow(clippy::type_complexity)] #[allow(clippy::use_self)] +#[allow(unused_imports)] mod auto; pub use crate::auto::*; diff --git a/gstreamer-controller/src/lib.rs b/gstreamer-controller/src/lib.rs index 5ff1be1bd..a0cb7497b 100644 --- a/gstreamer-controller/src/lib.rs +++ b/gstreamer-controller/src/lib.rs @@ -24,6 +24,7 @@ macro_rules! skip_assert_initialized { #[allow(clippy::too_many_arguments)] #[allow(clippy::match_same_arms)] #[allow(clippy::use_self)] +#[allow(unused_imports)] mod auto; mod control_point; pub use crate::auto::*; diff --git a/gstreamer-editing-services/src/lib.rs b/gstreamer-editing-services/src/lib.rs index f1feff0a1..3dc63db8c 100644 --- a/gstreamer-editing-services/src/lib.rs +++ b/gstreamer-editing-services/src/lib.rs @@ -57,6 +57,7 @@ macro_rules! skip_assert_initialized { #[allow(clippy::use_self)] #[allow(clippy::needless_borrow)] #[allow(deprecated)] +#[allow(unused_imports)] mod auto; pub use crate::auto::*; diff --git a/gstreamer-gl/src/lib.rs b/gstreamer-gl/src/lib.rs index 3c6450b3a..f1e2451b3 100644 --- a/gstreamer-gl/src/lib.rs +++ b/gstreamer-gl/src/lib.rs @@ -26,6 +26,7 @@ macro_rules! skip_assert_initialized { #[allow(clippy::too_many_arguments)] #[allow(clippy::match_same_arms)] #[allow(clippy::use_self)] +#[allow(unused_imports)] mod auto; pub use crate::auto::*; diff --git a/gstreamer-net/src/lib.rs b/gstreamer-net/src/lib.rs index 33567deaa..c6395ddf0 100644 --- a/gstreamer-net/src/lib.rs +++ b/gstreamer-net/src/lib.rs @@ -24,6 +24,7 @@ macro_rules! skip_assert_initialized { #[allow(clippy::too_many_arguments)] #[allow(clippy::match_same_arms)] #[allow(clippy::use_self)] +#[allow(unused_imports)] mod auto; pub use crate::auto::*; mod net_client_clock; diff --git a/gstreamer-pbutils/src/discoverer.rs b/gstreamer-pbutils/src/discoverer.rs index 5ba93d99c..cec984790 100644 --- a/gstreamer-pbutils/src/discoverer.rs +++ b/gstreamer-pbutils/src/discoverer.rs @@ -6,32 +6,17 @@ use glib::prelude::*; use glib::signal::connect_raw; use glib::signal::SignalHandlerId; use glib::translate::*; -use glib::Value; use std::boxed::Box as Box_; use std::mem::transmute; impl Discoverer { pub fn set_timeout(&self, timeout: gst::ClockTime) { - unsafe { - glib::gobject_ffi::g_object_set_property( - self.as_ptr() as *mut _, - "timeout".to_glib_none().0, - Value::from(&timeout).to_glib_none().0, - ); - } + self.set_property("timeout", &timeout); } pub fn timeout(&self) -> gst::ClockTime { - let mut value = Value::from(&0u64); - unsafe { - glib::gobject_ffi::g_object_get_property( - self.as_ptr() as *mut _, - "timeout".to_glib_none().0, - value.to_glib_none_mut().0, - ); - } - value.get().expect("undefined timeout") + self.property("timeout") } #[doc(alias = "timeout")] diff --git a/gstreamer-pbutils/src/lib.rs b/gstreamer-pbutils/src/lib.rs index bb5964f2d..d843f7c85 100644 --- a/gstreamer-pbutils/src/lib.rs +++ b/gstreamer-pbutils/src/lib.rs @@ -32,6 +32,7 @@ macro_rules! skip_assert_initialized { #[allow(clippy::match_same_arms)] #[allow(clippy::type_complexity)] #[allow(clippy::use_self)] +#[allow(unused_imports)] mod auto; pub use crate::auto::functions::*; pub use crate::auto::*; diff --git a/gstreamer-player/src/lib.rs b/gstreamer-player/src/lib.rs index a690d26a8..ef732e2c9 100644 --- a/gstreamer-player/src/lib.rs +++ b/gstreamer-player/src/lib.rs @@ -23,6 +23,7 @@ macro_rules! assert_initialized_main_thread { #[allow(clippy::cast_ptr_alignment)] #[allow(clippy::use_self)] #[allow(clippy::needless_borrow)] +#[allow(unused_imports)] mod auto; pub use crate::auto::*; diff --git a/gstreamer-rtsp-server/src/lib.rs b/gstreamer-rtsp-server/src/lib.rs index ac2957472..4ad2a1076 100644 --- a/gstreamer-rtsp-server/src/lib.rs +++ b/gstreamer-rtsp-server/src/lib.rs @@ -30,6 +30,7 @@ macro_rules! skip_assert_initialized { #[allow(clippy::type_complexity)] #[allow(clippy::let_and_return)] #[allow(clippy::use_self)] +#[allow(unused_imports)] mod auto; pub use crate::auto::*; diff --git a/gstreamer-video/src/lib.rs b/gstreamer-video/src/lib.rs index a53814614..6a20b5112 100644 --- a/gstreamer-video/src/lib.rs +++ b/gstreamer-video/src/lib.rs @@ -26,6 +26,7 @@ macro_rules! skip_assert_initialized { #[allow(clippy::match_same_arms)] #[allow(clippy::use_self)] #[allow(clippy::needless_borrow)] +#[allow(unused_imports)] mod auto; pub use crate::auto::*; diff --git a/gstreamer-webrtc/src/lib.rs b/gstreamer-webrtc/src/lib.rs index beb885a0e..0d1324de1 100644 --- a/gstreamer-webrtc/src/lib.rs +++ b/gstreamer-webrtc/src/lib.rs @@ -26,6 +26,7 @@ macro_rules! skip_assert_initialized { #[allow(clippy::match_same_arms)] #[allow(clippy::use_self)] #[allow(clippy::needless_borrow)] +#[allow(unused_imports)] mod auto; pub use crate::auto::*; diff --git a/gstreamer/src/gobject.rs b/gstreamer/src/gobject.rs index 47050c5d7..d873d6bd9 100644 --- a/gstreamer/src/gobject.rs +++ b/gstreamer/src/gobject.rs @@ -29,7 +29,7 @@ impl> GObjectExtManualGst for O { } }; - self.set_property_from_value(name, &value) + self.try_set_property_from_value(name, &value) } } @@ -45,7 +45,7 @@ mod tests { fakesink .set_property_from_str("state-error", "ready-to-paused") .unwrap(); - let v = fakesink.property("state-error").unwrap(); + let v = fakesink.property_value("state-error"); let e = glib::EnumValue::from_value(&v).unwrap(); assert_eq!(e.nick(), "ready-to-paused"); } diff --git a/gstreamer/src/lib.rs b/gstreamer/src/lib.rs index e2035c33d..31121b7b4 100644 --- a/gstreamer/src/lib.rs +++ b/gstreamer/src/lib.rs @@ -31,6 +31,7 @@ macro_rules! skip_assert_initialized { #[allow(clippy::type_complexity)] #[allow(clippy::use_self)] #[allow(clippy::needless_borrow)] +#[allow(unused_imports)] mod auto; pub use crate::auto::functions::*; pub use crate::auto::*; diff --git a/gstreamer/src/object.rs b/gstreamer/src/object.rs index f1f3bc36a..f4192baf9 100644 --- a/gstreamer/src/object.rs +++ b/gstreamer/src/object.rs @@ -74,7 +74,6 @@ impl> GstObjectExtManual for O { None }) - .unwrap() } fn set_object_flags(&self, flags: ObjectFlags) { @@ -145,7 +144,7 @@ mod tests { *notify_clone.lock().unwrap() = Some((id.clone(), prop.name())); }); - identity.set_property("silent", false).unwrap(); + identity.set_property("silent", false); assert_eq!( *notify.lock().unwrap(), Some((identity.upcast::(), "silent")) diff --git a/gstreamer/src/pad.rs b/gstreamer/src/pad.rs index bb8d119dc..425b6fb2e 100644 --- a/gstreamer/src/pad.rs +++ b/gstreamer/src/pad.rs @@ -1643,11 +1643,7 @@ impl + IsA + glib::object::IsClass> PadBuilder { // Since 1.14 templates can keep a pad GType with them, so we need to do some // additional checks here now if templ.has_property("gtype", Some(glib::Type::static_type())) { - let gtype = templ - .property("gtype") - .unwrap() - .get::() - .unwrap(); + let gtype = templ.property::("gtype"); if gtype == glib::Type::UNIT { // Nothing to be done, we can create any kind of pad diff --git a/gstreamer/src/subclass/element.rs b/gstreamer/src/subclass/element.rs index 4b76808af..8ee31ad64 100644 --- a/gstreamer/src/subclass/element.rs +++ b/gstreamer/src/subclass/element.rs @@ -806,7 +806,7 @@ mod tests { let src = ElementFactory::make("fakesrc", None).unwrap(); let sink = ElementFactory::make("fakesink", None).unwrap(); - src.set_property("num-buffers", 100i32).unwrap(); + src.set_property("num-buffers", 100i32); pipeline .add_many(&[&src, element.upcast_ref(), &sink]) diff --git a/tutorials/src/bin/basic-tutorial-13.rs b/tutorials/src/bin/basic-tutorial-13.rs index e0f99d6cb..3bf677b21 100644 --- a/tutorials/src/bin/basic-tutorial-13.rs +++ b/tutorials/src/bin/basic-tutorial-13.rs @@ -56,11 +56,7 @@ fn send_seek_event(pipeline: &Element, rate: f64) -> bool { }; // If we have not done so, obtain the sink through which we will send the seek events - if let Ok(Some(video_sink)) = pipeline - .property("video-sink") - .unwrap() - .get::>() - { + if let Ok(Some(video_sink)) = pipeline.try_property::>("video-sink") { println!("Current rate: {}\r", rate); // Send the event video_sink.send_event(seek_event) @@ -175,10 +171,7 @@ USAGE: Choose one of the following options, then press enter: } } Command::NextFrame => { - if let Ok(Some(video_sink)) = pipeline - .property("video-sink") - .unwrap() - .get::>() + if let Ok(Some(video_sink)) = pipeline.try_property::>("video-sink") { // Send the event let step = Step::new(gst::format::Buffers(1), rate.abs(), true, false); diff --git a/tutorials/src/bin/basic-tutorial-3.rs b/tutorials/src/bin/basic-tutorial-3.rs index 885ce64fb..e8de962b2 100644 --- a/tutorials/src/bin/basic-tutorial-3.rs +++ b/tutorials/src/bin/basic-tutorial-3.rs @@ -30,9 +30,7 @@ fn tutorial_main() { // Set the URI to play let uri = "https://www.freedesktop.org/software/gstreamer-sdk/data/media/sintel_trailer-480p.webm"; - source - .set_property("uri", uri) - .expect("Can't set uri property on uridecodebin"); + source.set_property("uri", uri); // Connect the pad-added signal source.connect_pad_added(move |src, src_pad| { diff --git a/tutorials/src/bin/basic-tutorial-4.rs b/tutorials/src/bin/basic-tutorial-4.rs index 21193c35e..372cf1c65 100644 --- a/tutorials/src/bin/basic-tutorial-4.rs +++ b/tutorials/src/bin/basic-tutorial-4.rs @@ -31,9 +31,7 @@ fn tutorial_main() { // Set the URI to play let uri = "https://www.freedesktop.org/software/gstreamer-sdk/data/media/sintel_trailer-480p.webm"; - playbin - .set_property("uri", uri) - .expect("Can't set uri property on playbin"); + playbin.set_property("uri", uri); // Start playing playbin diff --git a/tutorials/src/bin/basic-tutorial-5.rs b/tutorials/src/bin/basic-tutorial-5.rs index 40b998e73..e558ca9e7 100644 --- a/tutorials/src/bin/basic-tutorial-5.rs +++ b/tutorials/src/bin/basic-tutorial-5.rs @@ -40,9 +40,9 @@ mod tutorial5 { let propname: &str = &format!("n-{}", stype); let signame: &str = &format!("get-{}-tags", stype); - let x = playbin.property(propname).unwrap().get::().unwrap(); + let x = playbin.property::(propname); for i in 0..x { - let tags = playbin.emit_by_name(signame, &[&i]).unwrap().unwrap(); + let tags = playbin.emit_by_name(signame, &[&i]).unwrap(); if let Ok(Some(tags)) = tags.get::>() { textbuf.insert_at_cursor(&format!("{} stream {}:\n ", stype, i)); @@ -302,37 +302,31 @@ mod tutorial5 { let uri = "https://www.freedesktop.org/software/gstreamer-sdk/\ data/media/sintel_trailer-480p.webm"; let playbin = gst::ElementFactory::make("playbin", None).unwrap(); - playbin.set_property("uri", uri).unwrap(); + playbin.set_property("uri", uri); - playbin - .connect("video-tags-changed", false, |args| { - let pipeline = args[0] - .get::() - .expect("playbin \"video-tags-changed\" args[0]"); - post_app_message(&pipeline); - None - }) - .unwrap(); + playbin.connect("video-tags-changed", false, |args| { + let pipeline = args[0] + .get::() + .expect("playbin \"video-tags-changed\" args[0]"); + post_app_message(&pipeline); + None + }); - playbin - .connect("audio-tags-changed", false, |args| { - let pipeline = args[0] - .get::() - .expect("playbin \"audio-tags-changed\" args[0]"); - post_app_message(&pipeline); - None - }) - .unwrap(); + playbin.connect("audio-tags-changed", false, |args| { + let pipeline = args[0] + .get::() + .expect("playbin \"audio-tags-changed\" args[0]"); + post_app_message(&pipeline); + None + }); - playbin - .connect("text-tags-changed", false, move |args| { - let pipeline = args[0] - .get::() - .expect("playbin \"text-tags-changed\" args[0]"); - post_app_message(&pipeline); - None - }) - .unwrap(); + playbin.connect("text-tags-changed", false, move |args| { + let pipeline = args[0] + .get::() + .expect("playbin \"text-tags-changed\" args[0]"); + post_app_message(&pipeline); + None + }); let window = create_ui(&playbin); diff --git a/tutorials/src/bin/basic-tutorial-7.rs b/tutorials/src/bin/basic-tutorial-7.rs index 7d75a491f..567a2062f 100644 --- a/tutorials/src/bin/basic-tutorial-7.rs +++ b/tutorials/src/bin/basic-tutorial-7.rs @@ -24,7 +24,7 @@ fn tutorial_main() { let pipeline = gst::Pipeline::new(Some("test-pipeline")); - audio_source.set_property("freq", 215.0).unwrap(); + audio_source.set_property("freq", 215.0); visual.set_property_from_str("shader", "none").unwrap(); visual.set_property_from_str("style", "lines").unwrap(); diff --git a/tutorials/src/bin/playback-tutorial-1.rs b/tutorials/src/bin/playback-tutorial-1.rs index d8d306ef8..79c48447b 100644 --- a/tutorials/src/bin/playback-tutorial-1.rs +++ b/tutorials/src/bin/playback-tutorial-1.rs @@ -12,19 +12,16 @@ use std::{thread, time}; mod tutorials_common; fn analyze_streams(playbin: &gst::Element) { - let n_video = playbin.property("n-video").unwrap().get::().unwrap(); - let n_audio = playbin.property("n-audio").unwrap().get::().unwrap(); - let n_text = playbin.property("n-text").unwrap().get::().unwrap(); + let n_video = playbin.property::("n-video"); + let n_audio = playbin.property::("n-audio"); + let n_text = playbin.property::("n-text"); println!( "{} video stream(s), {} audio stream(s), {} text stream(s)", n_video, n_audio, n_text ); for i in 0..n_video { - let tags = playbin - .emit_by_name("get-video-tags", &[&i]) - .unwrap() - .unwrap(); + let tags = playbin.emit_by_name("get-video-tags", &[&i]).unwrap(); if let Ok(tags) = tags.get::() { println!("video stream {}:", i); @@ -35,10 +32,7 @@ fn analyze_streams(playbin: &gst::Element) { } for i in 0..n_audio { - let tags = playbin - .emit_by_name("get-audio-tags", &[&i]) - .unwrap() - .unwrap(); + let tags = playbin.emit_by_name("get-audio-tags", &[&i]).unwrap(); if let Ok(tags) = tags.get::() { println!("audio stream {}:", i); @@ -55,10 +49,7 @@ fn analyze_streams(playbin: &gst::Element) { } for i in 0..n_text { - let tags = playbin - .emit_by_name("get-text-tags", &[&i]) - .unwrap() - .unwrap(); + let tags = playbin.emit_by_name("get-text-tags", &[&i]).unwrap(); if let Ok(tags) = tags.get::() { println!("subtitle stream {}:", i); @@ -68,21 +59,9 @@ fn analyze_streams(playbin: &gst::Element) { } } - let current_video = playbin - .property("current-video") - .unwrap() - .get::() - .unwrap(); - let current_audio = playbin - .property("current-audio") - .unwrap() - .get::() - .unwrap(); - let current_text = playbin - .property("current-text") - .unwrap() - .get::() - .unwrap(); + let current_video = playbin.property::("current-video"); + let current_audio = playbin.property::("current-audio"); + let current_text = playbin.property::("current-text"); println!( "Currently playing video stream {}, audio stream {}, text stream {}", current_video, current_audio, current_text @@ -100,11 +79,11 @@ fn handle_keyboard(playbin: &gst::Element, main_loop: &glib::MainLoop) { if let Some(index) = index.to_digit(10) { // Here index can only be 0-9 let index = index as i32; - let n_audio = playbin.property("n-audio").unwrap().get::().unwrap(); + let n_audio = playbin.property::("n-audio"); if index < n_audio { println!("Setting current audio stream to {}", index); - playbin.set_property("current-audio", index).unwrap(); + playbin.set_property("current-audio", index); } else { eprintln!("Index out of bounds"); } @@ -134,10 +113,10 @@ fn tutorial_main() -> Result<(), Error> { // Set URI to play let uri = "https://www.freedesktop.org/software/gstreamer-sdk/data/media/sintel_cropped_multilingual.webm"; - playbin.set_property("uri", uri)?; + playbin.set_property("uri", uri); // Set flags to show Audio and Video but ignore Subtitles - let flags = playbin.property("flags")?; + let flags = playbin.property_value("flags"); let flags_class = FlagsClass::new(flags.type_()).unwrap(); let flags = flags_class @@ -148,10 +127,10 @@ fn tutorial_main() -> Result<(), Error> { .unset_by_nick("text") .build() .unwrap(); - playbin.set_property_from_value("flags", &flags)?; + playbin.set_property_from_value("flags", &flags); // Set connection speed. This will affect some internal decisions of playbin - playbin.set_property("connection-speed", 56u64)?; + playbin.set_property("connection-speed", 56u64); // Handle keyboard input let playbin_clone = playbin.clone(); diff --git a/tutorials/src/bin/playback-tutorial-4.rs b/tutorials/src/bin/playback-tutorial-4.rs index 754618643..a9caa10c9 100644 --- a/tutorials/src/bin/playback-tutorial-4.rs +++ b/tutorials/src/bin/playback-tutorial-4.rs @@ -20,10 +20,10 @@ fn tutorial_main() -> Result<(), Error> { let uri = "https://www.freedesktop.org/software/gstreamer-sdk/data/media/sintel_trailer-480p.webm"; let pipeline = gst::ElementFactory::make("playbin", None)?; - pipeline.set_property("uri", uri).unwrap(); + pipeline.set_property("uri", uri); // Set the download flag - let flags = pipeline.property("flags")?; + let flags = pipeline.property_value("flags"); let flags_class = FlagsClass::new(flags.type_()).unwrap(); let flags = flags_class .builder_with_value(flags) @@ -31,10 +31,10 @@ fn tutorial_main() -> Result<(), Error> { .set_by_nick("download") .build() .unwrap(); - pipeline.set_property_from_value("flags", &flags).unwrap(); + pipeline.set_property_from_value("flags", &flags); // Uncomment this line to limit the amount of downloaded data. - // pipeline.set_property("ring-buffer-max-size", 4_000_000u64)?; + // pipeline.set_property("ring-buffer-max-size", 4_000_000u64); // Start playing let mut is_live = false; @@ -103,16 +103,12 @@ fn tutorial_main() -> Result<(), Error> { let download_buffer = args[1].get::().unwrap(); println!( "Temporary file: {:?}", - download_buffer - .property("temp-location") - .unwrap() - .get::>() - .unwrap() + download_buffer.property::>("temp-location") ); // Uncomment this line to keep the temporary file after the program exists. // download_buffer.set_property("temp-remove", false).ok(); None - })?; + }); let pipeline_weak_ = pipeline.downgrade(); let timeout_id = glib::timeout_add_seconds(1, move || {