Add url parameter to the servosrc gstreamer plugin

This commit is contained in:
Alan Jeffrey 2019-11-22 14:59:45 -06:00
parent 49841b8ce9
commit 82e7e457e7

View file

@ -16,11 +16,17 @@ use glib::glib_bool_error;
use glib::glib_object_impl; use glib::glib_object_impl;
use glib::glib_object_subclass; use glib::glib_object_subclass;
use glib::object::Cast; use glib::object::Cast;
use glib::object::Object;
use glib::subclass::object::ObjectClassSubclassExt;
use glib::subclass::object::ObjectImpl; use glib::subclass::object::ObjectImpl;
use glib::subclass::object::ObjectImplExt; use glib::subclass::object::ObjectImplExt;
use glib::subclass::object::Property;
use glib::subclass::simple::ClassStruct; use glib::subclass::simple::ClassStruct;
use glib::subclass::types::ObjectSubclass; use glib::subclass::types::ObjectSubclass;
use glib::value::Value;
use glib::ParamSpec;
use gstreamer::gst_element_error; use gstreamer::gst_element_error;
use gstreamer::gst_error_msg;
use gstreamer::gst_loggable_error; use gstreamer::gst_loggable_error;
use gstreamer::subclass::element::ElementClassSubclassExt; use gstreamer::subclass::element::ElementClassSubclassExt;
use gstreamer::subclass::element::ElementImpl; use gstreamer::subclass::element::ElementImpl;
@ -39,6 +45,7 @@ use gstreamer::LoggableError;
use gstreamer::PadDirection; use gstreamer::PadDirection;
use gstreamer::PadPresence; use gstreamer::PadPresence;
use gstreamer::PadTemplate; use gstreamer::PadTemplate;
use gstreamer::ResourceError;
use gstreamer_base::subclass::base_src::BaseSrcImpl; use gstreamer_base::subclass::base_src::BaseSrcImpl;
use gstreamer_base::BaseSrc; use gstreamer_base::BaseSrc;
use gstreamer_base::BaseSrcExt; use gstreamer_base::BaseSrcExt;
@ -81,6 +88,7 @@ use std::thread;
pub struct ServoSrc { pub struct ServoSrc {
sender: Sender<ServoSrcMsg>, sender: Sender<ServoSrcMsg>,
swap_chain: SwapChain, swap_chain: SwapChain,
url: Mutex<Option<String>>,
info: Mutex<Option<VideoInfo>>, info: Mutex<Option<VideoInfo>>,
} }
@ -175,10 +183,11 @@ thread_local! {
#[derive(Debug)] #[derive(Debug)]
enum ServoSrcMsg { enum ServoSrcMsg {
Start(ServoUrl),
GetSwapChain(Sender<SwapChain>), GetSwapChain(Sender<SwapChain>),
Resize(Size2D<i32, DevicePixel>), Resize(Size2D<i32, DevicePixel>),
Heartbeat, Heartbeat,
Quit, Stop,
} }
const DEFAULT_URL: &'static str = const DEFAULT_URL: &'static str =
@ -204,24 +213,23 @@ impl ServoThread {
} }
fn run(&mut self) { fn run(&mut self) {
self.new_browser();
while let Ok(msg) = self.receiver.recv() { while let Ok(msg) = self.receiver.recv() {
debug!("Servo thread handling message {:?}", msg); debug!("Servo thread handling message {:?}", msg);
match msg { match msg {
ServoSrcMsg::Start(url) => self.new_browser(url),
ServoSrcMsg::GetSwapChain(sender) => sender ServoSrcMsg::GetSwapChain(sender) => sender
.send(self.swap_chain.clone()) .send(self.swap_chain.clone())
.expect("Failed to send swap chain"), .expect("Failed to send swap chain"),
ServoSrcMsg::Resize(size) => self.resize(size), ServoSrcMsg::Resize(size) => self.resize(size),
ServoSrcMsg::Heartbeat => self.servo.handle_events(vec![]), ServoSrcMsg::Heartbeat => self.servo.handle_events(vec![]),
ServoSrcMsg::Quit => break, ServoSrcMsg::Stop => break,
} }
} }
self.servo.handle_events(vec![WindowEvent::Quit]); self.servo.handle_events(vec![WindowEvent::Quit]);
} }
fn new_browser(&mut self) { fn new_browser(&mut self, url: ServoUrl) {
let id = TopLevelBrowsingContextId::new(); let id = TopLevelBrowsingContextId::new();
let url = ServoUrl::parse(DEFAULT_URL).unwrap();
self.servo self.servo
.handle_events(vec![WindowEvent::NewBrowser(url, id)]); .handle_events(vec![WindowEvent::NewBrowser(url, id)]);
} }
@ -414,6 +422,16 @@ impl WindowMethods for ServoSrcWindow {
} }
} }
static PROPERTIES: [Property; 1] = [Property("url", |name| {
ParamSpec::string(
name,
"URL",
"Initial URL",
Some(DEFAULT_URL),
glib::ParamFlags::READWRITE,
)
})];
impl ObjectSubclass for ServoSrc { impl ObjectSubclass for ServoSrc {
const NAME: &'static str = "ServoSrc"; const NAME: &'static str = "ServoSrc";
// gstreamer-gl doesn't have support for GLBaseSrc yet // gstreamer-gl doesn't have support for GLBaseSrc yet
@ -429,10 +447,12 @@ impl ObjectSubclass for ServoSrc {
let _ = sender.send(ServoSrcMsg::GetSwapChain(acks)); let _ = sender.send(ServoSrcMsg::GetSwapChain(acks));
let swap_chain = ackr.recv().expect("Failed to get swap chain"); let swap_chain = ackr.recv().expect("Failed to get swap chain");
let info = Mutex::new(None); let info = Mutex::new(None);
let url = Mutex::new(None);
Self { Self {
sender, sender,
swap_chain, swap_chain,
info, info,
url,
} }
} }
@ -462,6 +482,7 @@ impl ObjectSubclass for ServoSrc {
let src_pad_template = let src_pad_template =
PadTemplate::new("src", PadDirection::Src, PadPresence::Always, &src_caps).unwrap(); PadTemplate::new("src", PadDirection::Src, PadPresence::Always, &src_caps).unwrap();
klass.add_pad_template(src_pad_template); klass.add_pad_template(src_pad_template);
klass.install_properties(&PROPERTIES);
} }
glib_object_subclass!(); glib_object_subclass!();
@ -477,6 +498,29 @@ impl ObjectImpl for ServoSrc {
basesrc.set_format(Format::Time); basesrc.set_format(Format::Time);
basesrc.set_do_timestamp(true); basesrc.set_do_timestamp(true);
} }
fn set_property(&self, _obj: &Object, id: usize, value: &Value) {
let prop = &PROPERTIES[id];
match *prop {
Property("url", ..) => {
let mut guard = self.url.lock().expect("Failed to lock mutex");
let url = value.get().expect("Failed to get url value");
*guard = Some(url);
},
_ => unimplemented!(),
}
}
fn get_property(&self, _obj: &Object, id: usize) -> Result<Value, ()> {
let prop = &PROPERTIES[id];
match *prop {
Property("url", ..) => {
let guard = self.url.lock().expect("Failed to lock mutex");
Ok(Value::from(guard.as_ref()))
},
_ => unimplemented!(),
}
}
} }
impl ElementImpl for ServoSrc {} impl ElementImpl for ServoSrc {}
@ -500,12 +544,20 @@ impl BaseSrcImpl for ServoSrc {
fn start(&self, _src: &BaseSrc) -> Result<(), ErrorMessage> { fn start(&self, _src: &BaseSrc) -> Result<(), ErrorMessage> {
info!("Starting"); info!("Starting");
let guard = self
.url
.lock()
.map_err(|_| gst_error_msg!(ResourceError::Settings, ["Failed to lock mutex"]))?;
let url = guard.as_ref().map(|s| &**s).unwrap_or(DEFAULT_URL);
let url = ServoUrl::parse(url)
.map_err(|_| gst_error_msg!(ResourceError::Settings, ["Failed to parse url"]))?;
let _ = self.sender.send(ServoSrcMsg::Start(url));
Ok(()) Ok(())
} }
fn stop(&self, _src: &BaseSrc) -> Result<(), ErrorMessage> { fn stop(&self, _src: &BaseSrc) -> Result<(), ErrorMessage> {
info!("Stopping"); info!("Stopping");
let _ = self.sender.send(ServoSrcMsg::Quit); let _ = self.sender.send(ServoSrcMsg::Stop);
Ok(()) Ok(())
} }