Add Rust client library fro GstD with examples#338
Add Rust client library fro GstD with examples#338
Conversation
| @@ -0,0 +1,211 @@ | |||
| /* | |||
| * This file is part of GStreamer Daemon | |||
| * Copyright 2015-2022 Ridgerun, LLC (http://www.ridgerun.com) | |||
There was a problem hiding this comment.
Change to:
Copyright 2015-2026 RidgeRun, LLC (http://www.ridgerun.com)
Apply this to all the files in the PR
| install: false) | ||
| endforeach | ||
|
|
||
| subdir('rust') |
There was a problem hiding this comment.
Add a README inside examples/libgstc/rust/ explaining what each example does and how to run them
e9fd940 to
1caf51e
Compare
| println!("Pipeline set to playing!"); | ||
|
|
||
| println!("Press enter to stop the pipeline..."); | ||
| let (tx, rx) = mpsc::channel::<()>(); |
There was a problem hiding this comment.
I honestly think mpsc is overkill here. I'd recommend a simple Atomic boolean for the exit flag.
|
|
||
| let abs_path = PathBuf::from(&video) | ||
| .canonicalize() | ||
| .unwrap_or_else(|_| PathBuf::from(video)); |
There was a problem hiding this comment.
Prefer borrowing here PathBuf::from(&video)
| println!("Pipeline set to playing!"); | ||
|
|
||
| println!("Press enter to stop the pipeline..."); | ||
| let (tx, rx) = mpsc::channel::<()>(); |
| if bus_message.status == Status::OK { | ||
| println!("received!"); | ||
| } else if bus_message.status == Status::BUS_TIMEOUT { | ||
| println!("timeout!"); | ||
| eprintln!("EOS not received, file may be unreadable"); | ||
| } else { | ||
| println!("error!"); | ||
| eprintln!( | ||
| "An error occurred waiting for EOS: {}", | ||
| bus_message.status.0 | ||
| ); | ||
| } |
There was a problem hiding this comment.
Prefer matching here.
| @@ -0,0 +1,45 @@ | |||
| /* | |||
There was a problem hiding this comment.
I don't like this example name. Maybe wait_on_bus or something like that.
| use std::fmt; | ||
|
|
||
| #[derive(Clone, Copy, Debug, PartialEq, Eq)] | ||
| pub struct Status(pub i32); |
There was a problem hiding this comment.
Why a struct and not an enum? An enum is the more intuitive option here.
| } | ||
|
|
||
| pub(crate) struct Transport { | ||
| settings: ConnectionSettings, |
There was a problem hiding this comment.
I suggest we make this public so the client can read our settings.
| if self.stream.is_none() { | ||
| let stream = self.open_socket()?; | ||
| self.stream = Some(stream); | ||
| } |
There was a problem hiding this comment.
To me, this overprotection is an antipattern. If this happens, this is an error and we don't want to silence it. Why would the stream be closed? If we opened with keep_connection_open the stream should be open, if not, something went wrong and we should react accordingly.
| if timeout_ms < 0 { | ||
| stream | ||
| .set_read_timeout(None) | ||
| .map_err(|_| Status::SOCKET_ERROR)?; | ||
| } else { | ||
| stream | ||
| .set_read_timeout(Some(Duration::from_millis(timeout_ms as u64))) | ||
| .map_err(|_| Status::SOCKET_ERROR)?; | ||
| } |
There was a problem hiding this comment.
Please refactor this to set the timeout instead of duplicating all the code.
| rust_enabled = add_languages('rust', required : false) | ||
|
|
||
| if rust_enabled | ||
| subdir('gstc') | ||
| else | ||
| message('Rust compiler not found; skipping libgstc Rust API') | ||
| endif |
There was a problem hiding this comment.
Please follow the same pattern we use with python.
The ConnectionSettings are accesible through some helper methods in client.rs.
|
|
||
| println!("EOS message received!"); | ||
|
|
||
| client.pipeline_seek("pipe", 1.0, 3, 1, 1, 0, 1, -1)?; |
There was a problem hiding this comment.
Can we make local constants for these magic numbers? to give us an idea of what they are.
| @@ -0,0 +1,25 @@ | |||
| if is_variable('lib_gstc_rust_dep') | |||
| rustc = find_program('rustc') | |||
There was a problem hiding this comment.
Meson supports rust by default. Don't build manually. Add rust as the list of project languages and it will do it on its own.
|
|
||
| foreach ex : rust_examples | ||
| executable(ex[0], ex[1], | ||
| rust_args : ['--edition=2021'], |
There was a problem hiding this comment.
Add this do the default options as rust_std=2021
|
|
||
| use crate::Status; | ||
|
|
||
| pub(crate) fn json_get_int(json: &str, name: &str) -> Result<i32, Status> { |
There was a problem hiding this comment.
I vote for using meson 1.11, pip already has meson 1.11.1. But creating a JSON parser from scratch is something i'm not interested in maintaining.
| println!("EOS sent!"); | ||
|
|
||
| print!("Waiting for EOS... "); | ||
| let bus_message = client.pipeline_bus_wait("pipe", "eos", 10_000_000_000)?; |
There was a problem hiding this comment.
I suggest we treat Status::BusTimeout as an error as well. This is counterintuitive., IMO.
match client.pipeline_bus_wait("pipe", "eos", 10_000_000_000) {
Ok(_bus_message) => {
println!("received!");
}
Err(Status::BusTimeout) => {
println!("timeout!");
eprintln!("EOS not received, file may be unreadable");
}
Err(status) => {
println!("error!");
eprintln!(
"An error occurred waiting for EOS: {}",
status.code()
);
}
}| let status = match json_is_null_field(&raw, "response") { | ||
| Ok(is_null) if is_null => Status::BusTimeout, | ||
| Ok(_) => Status::Ok, | ||
| Err(err) => err, | ||
| }; | ||
|
|
||
| Ok(BusMessage { | ||
| status, | ||
| raw_response: raw, | ||
| }) |
There was a problem hiding this comment.
Let's treat BusTimeout as an Err()
| self.cmd_update( | ||
| &format!("/pipelines/{}/bus/types", pipeline_name), | ||
| &message_name, | ||
| )?; | ||
| self.cmd_update( | ||
| &format!("/pipelines/{}/bus/timeout", pipeline_name), | ||
| &format!("{}", timeout_ns), | ||
| )?; |
There was a problem hiding this comment.
This values are already written by pipeline_bus_wait(), which you are already calling. Why write them twice?
| * Boston, MA 02110-1301, USA. | ||
| */ | ||
|
|
||
| use gstc_rust::{Client, Status}; |
There was a problem hiding this comment.
drop the rust in gstc_rust. Just gstc.
| ), | ||
| self.default_wait_time_ms()?, | ||
| )?; | ||
| Ok(()) |
| fn cmd_send(&self, request: &str) -> Result<(), Status> { | ||
| let response = self.send_request(request, self.default_wait_time_ms()?)?; | ||
| let code = json_get_int(&response, "code")?; | ||
| let status = Status::from_code(code); | ||
|
|
||
| if status.is_ok() { | ||
| Ok(()) | ||
| } else { | ||
| Err(status) | ||
| } | ||
| } |
There was a problem hiding this comment.
Rewrite this in terms of cmd_send_get_response
No description provided.