From bdfc95e6e8402b614f0fee786628be97d3480201 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Dr=C3=B6ge?= Date: Fri, 27 Jul 2018 13:35:24 +0300 Subject: [PATCH] Get rid of send-cell dependency and fix reference cycles --- gst-plugin-togglerecord/Cargo.toml | 3 +- .../examples/gtk_recording.rs | 73 +++++++++++++------ 2 files changed, 51 insertions(+), 25 deletions(-) diff --git a/gst-plugin-togglerecord/Cargo.toml b/gst-plugin-togglerecord/Cargo.toml index ed46e3b3..eb99c2c9 100644 --- a/gst-plugin-togglerecord/Cargo.toml +++ b/gst-plugin-togglerecord/Cargo.toml @@ -12,7 +12,6 @@ gobject-subclass = { git = "https://github.com/sdroege/gobject-subclass" } gst-plugin = { path = "../gst-plugin" } gtk = { git = "https://github.com/gtk-rs/gtk", features = ["v3_6"], optional = true } gio = { git = "https://github.com/gtk-rs/gio", optional = true } -send-cell = { version = "0.1", optional = true } [dev-dependencies] either = "1.0" @@ -25,5 +24,5 @@ path = "src/lib.rs" [[example]] name = "gtk-recording" path = "examples/gtk_recording.rs" -required-features = ["gtk", "gio", "send-cell"] +required-features = ["gtk", "gio"] diff --git a/gst-plugin-togglerecord/examples/gtk_recording.rs b/gst-plugin-togglerecord/examples/gtk_recording.rs index be2b7cb9..28e11e44 100644 --- a/gst-plugin-togglerecord/examples/gtk_recording.rs +++ b/gst-plugin-togglerecord/examples/gtk_recording.rs @@ -26,10 +26,8 @@ use gst::prelude::*; extern crate gtk; use gtk::prelude::*; -extern crate send_cell; -use send_cell::SendCell; - use std::env; +use std::cell::RefCell; fn create_pipeline() -> ( gst::Pipeline, @@ -219,11 +217,18 @@ fn create_ui(app: >k::Application) { app.add_window(&window); - let video_sink_clone = video_sink.clone(); - let togglerecord_clone = togglerecord.clone(); - gtk::timeout_add(100, move || { - let video_sink = &video_sink_clone; - let togglerecord = &togglerecord_clone; + let video_sink_weak = video_sink.downgrade(); + let togglerecord_weak = togglerecord.downgrade(); + let timeout_id = gtk::timeout_add(100, move || { + let video_sink = match video_sink_weak.upgrade() { + Some(video_sink) => video_sink, + None => return glib::Continue(true), + }; + + let togglerecord = match togglerecord_weak.upgrade() { + Some(togglerecord) => togglerecord, + None => return glib::Continue(true), + }; let position = video_sink .query_position::() @@ -240,9 +245,12 @@ fn create_ui(app: >k::Application) { glib::Continue(true) }); - let togglerecord_clone = togglerecord.clone(); + let togglerecord_weak = togglerecord.downgrade(); record_button.connect_clicked(move |button| { - let togglerecord = &togglerecord_clone; + let togglerecord = match togglerecord_weak.upgrade() { + Some(togglerecord) => togglerecord, + None => return, + }; let recording = !togglerecord .get_property("record") @@ -254,9 +262,13 @@ fn create_ui(app: >k::Application) { button.set_label(if recording { "Stop" } else { "Record" }); }); - let record_button_clone = record_button.clone(); + let record_button_weak = record_button.downgrade(); finish_button.connect_clicked(move |button| { - let record_button = &record_button_clone; + let record_button = match record_button_weak.upgrade() { + Some(record_button) => record_button, + None => return, + }; + record_button.set_sensitive(false); button.set_sensitive(false); @@ -264,19 +276,27 @@ fn create_ui(app: >k::Application) { audio_pad.send_event(gst::Event::new_eos().build()); }); - let app_clone = app.clone(); + let app_weak = app.downgrade(); window.connect_delete_event(move |_, _| { - let app = &app_clone; + let app = match app_weak.upgrade() { + Some(app) => app, + None => return Inhibit(false), + }; + app.quit(); Inhibit(false) }); let bus = pipeline.get_bus().unwrap(); - let app_clone = SendCell::new(app.clone()); + let app_weak = glib::SendWeakRef::from(app.downgrade()); bus.add_watch(move |_, msg| { use gst::MessageView; - let app = app_clone.borrow(); + let app = match app_weak.upgrade() { + Some(app) => app, + None => return glib::Continue(false), + }; + match msg.view() { MessageView::Eos(..) => app.quit(), MessageView::Error(err) => { @@ -294,15 +314,22 @@ fn create_ui(app: >k::Application) { glib::Continue(true) }); - let pipeline_clone = pipeline.clone(); - app.connect_shutdown(move |_| { - let pipeline = &pipeline_clone; - let ret = pipeline.set_state(gst::State::Null); - assert_ne!(ret, gst::StateChangeReturn::Failure); - }); - let ret = pipeline.set_state(gst::State::Playing); assert_ne!(ret, gst::StateChangeReturn::Failure); + + // Pipeline reference is owned by the closure below, so will be + // destroyed once the app is destroyed + let timeout_id = RefCell::new(Some(timeout_id)); + app.connect_shutdown(move |_| { + let ret = pipeline.set_state(gst::State::Null); + assert_ne!(ret, gst::StateChangeReturn::Failure); + + bus.remove_watch(); + + if let Some(timeout_id) = timeout_id.borrow_mut().take() { + glib::source_remove(timeout_id); + } + }); } fn main() {