Replacing videotestsrc for filesrc in gtk4paintablesink example

oh I got it working but using playbin

use gst::prelude::*;

use gtk::prelude::*;
use gtk::{gdk, gio, glib};

use std::cell::RefCell;

fn create_ui(app: &gtk::Application) {
    let _cwd = std::env::current_dir().unwrap();
    let cwd = _cwd.to_str().unwrap();

    let uri = format!("file://{}/{}", cwd, "/duck.mp4");

    println!("playing {}", uri);
    let playbin = gst::ElementFactory::make("playbin")
        .property("uri", uri)
        .build()
        .unwrap();

    let gtksink = gst::ElementFactory::make("gtk4paintablesink")
        .build()
        .unwrap();

    let paintable = gtksink.property::<gdk::Paintable>("paintable");

    // TODO: future plans to provide a bin-like element that works with less setup
    let sink = if paintable
        .property::<Option<gdk::GLContext>>("gl-context")
        .is_some()
    {
        println!("using glsink");
        let sink = gst::ElementFactory::make("glsinkbin")
            .property("sink", &gtksink)
            .build()
            .unwrap();
        sink
    } else {
        println!("using videoconvert");
        let sink = gst::Bin::default();
        let convert = gst::ElementFactory::make("videoconvert").build().unwrap();

        sink.add(&convert).unwrap();
        sink.add(&gtksink).unwrap();
        convert.link(&gtksink).unwrap();

        sink.add_pad(&gst::GhostPad::with_target(&convert.static_pad("sink").unwrap()).unwrap())
            .unwrap();

        sink.upcast()
    };

    playbin.set_property("video-sink", &gtksink);

    playbin
        .add_pad(&gst::GhostPad::with_target(&sink.static_pad("sink").unwrap()).unwrap())
        .unwrap();

    // playbin.link(&sink).unwrap();

    let window = gtk::ApplicationWindow::new(app);
    window.set_default_size(640, 480);

    let gst_widget = gstgtk4::RenderWidget::new(&gtksink);

    let overlay = gtk::Overlay::new();

    overlay.add_overlay(&gst_widget);

    window.set_child(Some(&overlay));
    window.present();
    // window.fullscreen();

    app.add_window(&window);

    let bus: gst::Bus = playbin.bus().unwrap();

    playbin
        .set_state(gst::State::Playing)
        .expect("Unable to set the playbin to the `Playing` state");

    let app_weak = app.downgrade();
    let bus_watch = bus
        .add_watch_local(move |_, msg| {
            use gst::MessageView;

            let Some(app) = app_weak.upgrade() else {
                return glib::ControlFlow::Break;
            };

            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::ControlFlow::Continue
        })
        .expect("Failed to add bus watch");

    let playbin = RefCell::new(Some(playbin));
    let bus_watch = RefCell::new(Some(bus_watch));
    app.connect_shutdown(move |_| {
        window.close();

        drop(bus_watch.borrow_mut().take());
        if let Some(playbin) = playbin.borrow_mut().take() {
            playbin
                .set_state(gst::State::Null)
                .expect("Unable to set the playbin to the `Null` state");
        }
    });
}

fn main() -> glib::ExitCode {
    gst::init().unwrap();

    gstgtk4::plugin_register_static().expect("Failed to register gstgtk4 plugin");

    let app = gtk::Application::new(None::<&str>, gio::ApplicationFlags::FLAGS_NONE);

    app.connect_activate(create_ui);
    let res = app.run();

    unsafe {
        gst::deinit();
    }

    res
}

was missing the playbin.set_property("video-sink", &gtksink); to make the playbin use the sink, found here