mirror of
https://gitlab.freedesktop.org/gstreamer/gst-plugins-rs.git
synced 2024-06-16 13:10:34 +00:00
Properly report errors when setting the URI fails
This commit is contained in:
parent
3d83de761f
commit
82c29d369d
|
@ -62,24 +62,24 @@ impl FileSink {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Sink for FileSink {
|
impl Sink for FileSink {
|
||||||
fn set_uri(&self, uri: Option<Url>) -> bool {
|
fn set_uri(&self, uri: Option<Url>) -> Result<(), (UriError, String)> {
|
||||||
let location = &mut self.settings.lock().unwrap().location;
|
let location = &mut self.settings.lock().unwrap().location;
|
||||||
|
|
||||||
match uri {
|
match uri {
|
||||||
None => {
|
None => {
|
||||||
*location = None;
|
*location = None;
|
||||||
true
|
Ok(())
|
||||||
}
|
}
|
||||||
Some(ref uri) => {
|
Some(ref uri) => {
|
||||||
match uri.to_file_path().ok() {
|
match uri.to_file_path().ok() {
|
||||||
Some(p) => {
|
Some(p) => {
|
||||||
*location = Some(p);
|
*location = Some(p);
|
||||||
true
|
Ok(())
|
||||||
}
|
}
|
||||||
None => {
|
None => {
|
||||||
*location = None;
|
*location = None;
|
||||||
println_err!("Unsupported file URI '{}'", uri.as_str());
|
Err((UriError::UnsupportedProtocol,
|
||||||
false
|
format!("Unsupported file URI '{}'", uri.as_str())))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -63,24 +63,24 @@ impl FileSrc {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Source for FileSrc {
|
impl Source for FileSrc {
|
||||||
fn set_uri(&self, uri: Option<Url>) -> bool {
|
fn set_uri(&self, uri: Option<Url>) -> Result<(), (UriError, String)> {
|
||||||
let location = &mut self.settings.lock().unwrap().location;
|
let location = &mut self.settings.lock().unwrap().location;
|
||||||
|
|
||||||
match uri {
|
match uri {
|
||||||
None => {
|
None => {
|
||||||
*location = None;
|
*location = None;
|
||||||
true
|
Ok(())
|
||||||
}
|
}
|
||||||
Some(ref uri) => {
|
Some(ref uri) => {
|
||||||
match uri.to_file_path().ok() {
|
match uri.to_file_path().ok() {
|
||||||
Some(p) => {
|
Some(p) => {
|
||||||
*location = Some(p);
|
*location = Some(p);
|
||||||
true
|
Ok(())
|
||||||
}
|
}
|
||||||
None => {
|
None => {
|
||||||
*location = None;
|
*location = None;
|
||||||
println_err!("Unsupported file URI '{}'", uri.as_str());
|
Err((UriError::UnsupportedProtocol,
|
||||||
false
|
format!("Unsupported file URI '{}'", uri.as_str())))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -141,22 +141,22 @@ impl HttpSrc {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Source for HttpSrc {
|
impl Source for HttpSrc {
|
||||||
fn set_uri(&self, uri: Option<Url>) -> bool {
|
fn set_uri(&self, uri: Option<Url>) -> Result<(), (UriError, String)> {
|
||||||
let url = &mut self.settings.lock().unwrap().url;
|
let url = &mut self.settings.lock().unwrap().url;
|
||||||
|
|
||||||
match uri {
|
match uri {
|
||||||
None => {
|
None => {
|
||||||
*url = None;
|
*url = None;
|
||||||
true
|
Ok(())
|
||||||
}
|
}
|
||||||
Some(uri) => {
|
Some(uri) => {
|
||||||
if uri.scheme() == "http" || uri.scheme() == "https" {
|
if uri.scheme() == "http" || uri.scheme() == "https" {
|
||||||
*url = Some(uri);
|
*url = Some(uri);
|
||||||
true
|
Ok(())
|
||||||
} else {
|
} else {
|
||||||
*url = None;
|
*url = None;
|
||||||
println_err!("Unsupported URI '{}'", uri.as_str());
|
Err((UriError::UnsupportedProtocol,
|
||||||
false
|
format!("Unsupported URI '{}'", uri.as_str())))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,7 +38,7 @@ static GHashTable *sinks;
|
||||||
extern gboolean sinks_register (void *plugin);
|
extern gboolean sinks_register (void *plugin);
|
||||||
extern void *sink_new (GstRsSink * sink, void *create_instance);
|
extern void *sink_new (GstRsSink * sink, void *create_instance);
|
||||||
extern GstFlowReturn sink_render (void *rssink, void *data, size_t data_len);
|
extern GstFlowReturn sink_render (void *rssink, void *data, size_t data_len);
|
||||||
extern gboolean sink_set_uri (void *rssink, const char *uri);
|
extern gboolean sink_set_uri (void *rssink, const char *uri, GError ** err);
|
||||||
extern char *sink_get_uri (void *rssink);
|
extern char *sink_get_uri (void *rssink);
|
||||||
extern gboolean sink_start (void *rssink);
|
extern gboolean sink_start (void *rssink);
|
||||||
extern gboolean sink_stop (void *rssink);
|
extern gboolean sink_stop (void *rssink);
|
||||||
|
@ -140,7 +140,7 @@ gst_rs_sink_set_property (GObject * object, guint prop_id,
|
||||||
|
|
||||||
switch (prop_id) {
|
switch (prop_id) {
|
||||||
case PROP_URI:
|
case PROP_URI:
|
||||||
sink_set_uri (sink->instance, g_value_get_string (value));
|
sink_set_uri (sink->instance, g_value_get_string (value), NULL);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||||
|
@ -229,11 +229,8 @@ gst_rs_sink_uri_set_uri (GstURIHandler * handler, const gchar * uri,
|
||||||
{
|
{
|
||||||
GstRsSink *sink = GST_RS_SINK (handler);
|
GstRsSink *sink = GST_RS_SINK (handler);
|
||||||
|
|
||||||
if (!sink_set_uri (sink->instance, uri)) {
|
if (!sink_set_uri (sink->instance, uri, err))
|
||||||
g_set_error (err, GST_URI_ERROR, GST_URI_ERROR_BAD_URI,
|
|
||||||
"Can't handle URI '%s'", uri);
|
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,7 +21,6 @@ use std::os::raw::c_void;
|
||||||
use std::ffi::{CStr, CString};
|
use std::ffi::{CStr, CString};
|
||||||
use std::slice;
|
use std::slice;
|
||||||
use std::ptr;
|
use std::ptr;
|
||||||
use std::io::Write;
|
|
||||||
|
|
||||||
use url::Url;
|
use url::Url;
|
||||||
|
|
||||||
|
@ -40,7 +39,7 @@ impl SinkController {
|
||||||
|
|
||||||
pub trait Sink: Sync + Send {
|
pub trait Sink: Sync + Send {
|
||||||
// Called from any thread at any time
|
// Called from any thread at any time
|
||||||
fn set_uri(&self, uri: Option<Url>) -> bool;
|
fn set_uri(&self, uri: Option<Url>) -> Result<(), (UriError, String)>;
|
||||||
fn get_uri(&self) -> Option<Url>;
|
fn get_uri(&self) -> Option<Url>;
|
||||||
|
|
||||||
// Called from the streaming thread only
|
// Called from the streaming thread only
|
||||||
|
@ -62,19 +61,37 @@ pub unsafe extern "C" fn sink_drop(ptr: *mut Box<Sink>) {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub unsafe extern "C" fn sink_set_uri(ptr: *mut Box<Sink>, uri_ptr: *const c_char) -> GBoolean {
|
pub unsafe extern "C" fn sink_set_uri(ptr: *mut Box<Sink>,
|
||||||
|
uri_ptr: *const c_char,
|
||||||
|
cerr: *mut c_void)
|
||||||
|
-> GBoolean {
|
||||||
let sink: &mut Box<Sink> = &mut *ptr;
|
let sink: &mut Box<Sink> = &mut *ptr;
|
||||||
|
|
||||||
if uri_ptr.is_null() {
|
if uri_ptr.is_null() {
|
||||||
GBoolean::from_bool(sink.set_uri(None))
|
if let Err((code, msg)) = sink.set_uri(None) {
|
||||||
|
code.into_gerror(cerr, Some(&msg));
|
||||||
|
GBoolean::False
|
||||||
|
} else {
|
||||||
|
GBoolean::True
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
let uri_str = CStr::from_ptr(uri_ptr).to_str().unwrap();
|
let uri_str = CStr::from_ptr(uri_ptr).to_str().unwrap();
|
||||||
|
|
||||||
match Url::parse(uri_str) {
|
match Url::parse(uri_str) {
|
||||||
Ok(uri) => GBoolean::from_bool(sink.set_uri(Some(uri))),
|
Ok(uri) => {
|
||||||
|
if let Err((code, msg)) = sink.set_uri(Some(uri)) {
|
||||||
|
code.into_gerror(cerr, Some(&msg));
|
||||||
|
GBoolean::False
|
||||||
|
} else {
|
||||||
|
GBoolean::True
|
||||||
|
}
|
||||||
|
}
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
sink.set_uri(None);
|
let _ = sink.set_uri(None);
|
||||||
println_err!("Failed to parse URI '{}': {}", uri_str, err);
|
UriError::BadUri.into_gerror(cerr,
|
||||||
|
Some(&format!("Failed to parse URI '{}': {}",
|
||||||
|
uri_str,
|
||||||
|
err)));
|
||||||
GBoolean::False
|
GBoolean::False
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -39,7 +39,7 @@ extern void source_drop (void *rssource);
|
||||||
extern GstFlowReturn source_fill (void *rssource,
|
extern GstFlowReturn source_fill (void *rssource,
|
||||||
uint64_t offset, void *data, size_t * data_len);
|
uint64_t offset, void *data, size_t * data_len);
|
||||||
extern gboolean source_do_seek (void *rssource, uint64_t start, uint64_t stop);
|
extern gboolean source_do_seek (void *rssource, uint64_t start, uint64_t stop);
|
||||||
extern gboolean source_set_uri (void *rssource, const char *uri);
|
extern gboolean source_set_uri (void *rssource, const char *uri, GError ** err);
|
||||||
extern char *source_get_uri (void *rssource);
|
extern char *source_get_uri (void *rssource);
|
||||||
extern uint64_t source_get_size (void *rssource);
|
extern uint64_t source_get_size (void *rssource);
|
||||||
extern gboolean source_is_seekable (void *rssource);
|
extern gboolean source_is_seekable (void *rssource);
|
||||||
|
@ -149,7 +149,7 @@ gst_rs_src_set_property (GObject * object, guint prop_id,
|
||||||
|
|
||||||
switch (prop_id) {
|
switch (prop_id) {
|
||||||
case PROP_URI:
|
case PROP_URI:
|
||||||
source_set_uri (src->instance, g_value_get_string (value));
|
source_set_uri (src->instance, g_value_get_string (value), NULL);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||||
|
@ -274,11 +274,8 @@ gst_rs_src_uri_set_uri (GstURIHandler * handler, const gchar * uri,
|
||||||
{
|
{
|
||||||
GstRsSrc *src = GST_RS_SRC (handler);
|
GstRsSrc *src = GST_RS_SRC (handler);
|
||||||
|
|
||||||
if (!source_set_uri (src->instance, uri)) {
|
if (!source_set_uri (src->instance, uri, err))
|
||||||
g_set_error (err, GST_URI_ERROR, GST_URI_ERROR_BAD_URI,
|
|
||||||
"Can't handle URI '%s'", uri);
|
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,7 +20,6 @@ use std::os::raw::c_void;
|
||||||
use std::ffi::{CStr, CString};
|
use std::ffi::{CStr, CString};
|
||||||
use std::slice;
|
use std::slice;
|
||||||
use std::ptr;
|
use std::ptr;
|
||||||
use std::io::Write;
|
|
||||||
|
|
||||||
use url::Url;
|
use url::Url;
|
||||||
|
|
||||||
|
@ -39,7 +38,7 @@ impl SourceController {
|
||||||
|
|
||||||
pub trait Source: Sync + Send {
|
pub trait Source: Sync + Send {
|
||||||
// Called from any thread at any time
|
// Called from any thread at any time
|
||||||
fn set_uri(&self, uri: Option<Url>) -> bool;
|
fn set_uri(&self, uri: Option<Url>) -> Result<(), (UriError, String)>;
|
||||||
fn get_uri(&self) -> Option<Url>;
|
fn get_uri(&self) -> Option<Url>;
|
||||||
|
|
||||||
// Called from any thread between start/stop
|
// Called from any thread between start/stop
|
||||||
|
@ -66,19 +65,37 @@ pub unsafe extern "C" fn source_drop(ptr: *mut Box<Source>) {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub unsafe extern "C" fn source_set_uri(ptr: *mut Box<Source>, uri_ptr: *const c_char) -> GBoolean {
|
pub unsafe extern "C" fn source_set_uri(ptr: *mut Box<Source>,
|
||||||
|
uri_ptr: *const c_char,
|
||||||
|
cerr: *mut c_void)
|
||||||
|
-> GBoolean {
|
||||||
let source: &mut Box<Source> = &mut *ptr;
|
let source: &mut Box<Source> = &mut *ptr;
|
||||||
|
|
||||||
if uri_ptr.is_null() {
|
if uri_ptr.is_null() {
|
||||||
GBoolean::from_bool(source.set_uri(None))
|
if let Err((code, msg)) = source.set_uri(None) {
|
||||||
|
code.into_gerror(cerr, Some(&msg));
|
||||||
|
GBoolean::False
|
||||||
|
} else {
|
||||||
|
GBoolean::True
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
let uri_str = CStr::from_ptr(uri_ptr).to_str().unwrap();
|
let uri_str = CStr::from_ptr(uri_ptr).to_str().unwrap();
|
||||||
|
|
||||||
match Url::parse(uri_str) {
|
match Url::parse(uri_str) {
|
||||||
Ok(uri) => GBoolean::from_bool(source.set_uri(Some(uri))),
|
Ok(uri) => {
|
||||||
|
if let Err((code, msg)) = source.set_uri(Some(uri)) {
|
||||||
|
code.into_gerror(cerr, Some(&msg));
|
||||||
|
GBoolean::False
|
||||||
|
} else {
|
||||||
|
GBoolean::True
|
||||||
|
}
|
||||||
|
}
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
source.set_uri(None);
|
let _ = source.set_uri(None);
|
||||||
println_err!("Failed to parse URI '{}': {}", uri_str, err);
|
UriError::BadUri.into_gerror(cerr,
|
||||||
|
Some(&format!("Failed to parse URI '{}': {}",
|
||||||
|
uri_str,
|
||||||
|
err)));
|
||||||
GBoolean::False
|
GBoolean::False
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
26
src/utils.rs
26
src/utils.rs
|
@ -17,7 +17,9 @@
|
||||||
//
|
//
|
||||||
//
|
//
|
||||||
use libc::c_char;
|
use libc::c_char;
|
||||||
|
use std::os::raw::c_void;
|
||||||
use std::ffi::CString;
|
use std::ffi::CString;
|
||||||
|
use std::ptr;
|
||||||
|
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! println_err(
|
macro_rules! println_err(
|
||||||
|
@ -54,3 +56,27 @@ impl GBoolean {
|
||||||
pub unsafe extern "C" fn cstring_drop(ptr: *mut c_char) {
|
pub unsafe extern "C" fn cstring_drop(ptr: *mut c_char) {
|
||||||
CString::from_raw(ptr);
|
CString::from_raw(ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[repr(C)]
|
||||||
|
pub enum UriError {
|
||||||
|
UnsupportedProtocol = 0,
|
||||||
|
BadUri,
|
||||||
|
BadState,
|
||||||
|
BadReference,
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
fn g_set_error_literal(err: *mut c_void, domain: u32, code: i32, message: *const c_char);
|
||||||
|
fn gst_uri_error_quark() -> u32;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl UriError {
|
||||||
|
pub unsafe fn into_gerror(self, err: *mut c_void, message: Option<&String>) {
|
||||||
|
if let Some(msg) = message {
|
||||||
|
let cmsg = CString::new(msg.as_str()).unwrap();
|
||||||
|
g_set_error_literal(err, gst_uri_error_quark(), self as i32, cmsg.as_ptr());
|
||||||
|
} else {
|
||||||
|
g_set_error_literal(err, gst_uri_error_quark(), self as i32, ptr::null());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue