From 8ebb5df547385a16998e0c5eb24cca6b8742c52a Mon Sep 17 00:00:00 2001 From: Clement Rey Date: Wed, 6 Mar 2024 09:46:25 +0100 Subject: [PATCH] SDK `DataLoader`s 9: polish, docs, etc (#5388) I guess that's good enough :shrug:. I don't know, my brain has been completely friend by C++ non-sense all day. This includes a fix to make sure that a viewer that was spawned from the python SDK is still allowed to spawn dataloaders implemented in python (`RERUN_APP_ONLY` shenaniganeries). - Fixes #4526 --- Part of series of PR to expose configurable `DataLoader`s to our SDKs: - #5327 - #5328 - #5330 - #5337 - #5351 - #5355 - #5379 - #5361 - #5388 --- .../src/data_loader/loader_external.rs | 3 ++ docs/code-examples/all/log-file/example.cpp | 4 +++ docs/code-examples/all/log-file/example.py | 7 ++++ docs/code-examples/all/log-file/example.rs | 5 +++ docs/content/howto/open-any-file.md | 32 ++++++++++++------- examples/rust/log_file/src/main.rs | 3 -- 6 files changed, 39 insertions(+), 15 deletions(-) create mode 100644 docs/code-examples/all/log-file/example.cpp create mode 100644 docs/code-examples/all/log-file/example.py create mode 100644 docs/code-examples/all/log-file/example.rs diff --git a/crates/re_data_source/src/data_loader/loader_external.rs b/crates/re_data_source/src/data_loader/loader_external.rs index 893d21e7749f..e3592e23363d 100644 --- a/crates/re_data_source/src/data_loader/loader_external.rs +++ b/crates/re_data_source/src/data_loader/loader_external.rs @@ -139,6 +139,9 @@ impl crate::DataLoader for ExternalLoader { re_tracing::profile_function!(exe.to_string_lossy()); let child = Command::new(exe) + // Make sure the child dataloader doesn't think it's a Rerun Viewer, otherwise + // it's never gonna be able to log anything. + .env_remove("RERUN_APP_ONLY") .arg(filepath.clone()) .args(args) .stdout(Stdio::piped()) diff --git a/docs/code-examples/all/log-file/example.cpp b/docs/code-examples/all/log-file/example.cpp new file mode 100644 index 000000000000..2da499b3f01e --- /dev/null +++ b/docs/code-examples/all/log-file/example.cpp @@ -0,0 +1,4 @@ +const auto rec = rerun::RecordingStream("rerun_example_log_file"); +rec.spawn().exit_on_failure(); + +rec.log_file_from_path(argv[1]); diff --git a/docs/code-examples/all/log-file/example.py b/docs/code-examples/all/log-file/example.py new file mode 100644 index 000000000000..89a7763e1cbc --- /dev/null +++ b/docs/code-examples/all/log-file/example.py @@ -0,0 +1,7 @@ +import sys + +import rerun as rr + +rr.init("rerun_example_log_file", spawn=True) + +rr.log_file_from_path(sys.argv[1]) diff --git a/docs/code-examples/all/log-file/example.rs b/docs/code-examples/all/log-file/example.rs new file mode 100644 index 000000000000..5d8776510fc8 --- /dev/null +++ b/docs/code-examples/all/log-file/example.rs @@ -0,0 +1,5 @@ + let args = std::env::args().collect::>(); + + let rec = rerun::RecordingStreamBuilder::new("rerun_example_log_file").spawn()?; + + rec.log_file_from_path(&args[1], None /* prefix */, true /* timeless */)?; diff --git a/docs/content/howto/open-any-file.md b/docs/content/howto/open-any-file.md index 8d07bf8149aa..380bb427d1ce 100644 --- a/docs/content/howto/open-any-file.md +++ b/docs/content/howto/open-any-file.md @@ -3,9 +3,9 @@ title: Open any file order: -10 --- -The Rerun Viewer has built-in support for opening many kinds of files, and can be extended to open any other file type without needing to modify the Rerun codebase itself. +The Rerun Viewer and SDK have built-in support for opening many kinds of files, and can be extended to support any other file type without needing to modify the Rerun codebase itself. -The viewer can load files in 3 different ways: +The Viewer can load files in 3 different ways: - via CLI arguments (e.g. `rerun myfile.jpeg`), - using drag-and-drop, - using the open dialog in the Rerun Viewer. @@ -14,27 +14,35 @@ All these file loading methods support loading a single file, many files at once ⚠ Drag-and-drop of folders does [not yet work](https://github.com/rerun-io/rerun/issues/4528) on the web version of the Rerun Viewer ⚠ -The following file types have built-in support in the Rerun Viewer: +The following file types have built-in support in the Rerun Viewer and SDK: - Native Rerun files: `rrd` -- 3D models: `gltf`, `glb`, `obj` +- 3D models: `gltf`, `glb`, `obj`, `stl` - Images: `avif`, `bmp`, `dds`, `exr`, `farbfeld`, `ff`, `gif`, `hdr`, `ico`, `jpeg`, `jpg`, `pam`, `pbm`, `pgm`, `png`, `ppm`, `tga`, `tif`, `tiff`, `webp`. - Point clouds: `ply`. - Text files: `md`, `txt`. With the exception of `rrd` files that can be streamed from an HTTP URL (e.g. `rerun https://demo.rerun.io/version/latest/examples/dna/data.rrd`), we only support loading files from the local filesystem for now, with [plans to make this generic over any URI and protocol in the future](https://github.com/rerun-io/rerun/issues/4525). +## Logging file contents from the SDK + +To log the contents of a file from the SDK you can use the `log_file_from_path` and `log_file_from_contents` methods ([C++](https://ref.rerun.io/docs/cpp/stable/classrerun_1_1RecordingStream.html#SOME_HASH_TBD?speculative-link), [Python](https://ref.rerun.io/docs/python/stable/common/other_classes_and_functions/#rerun.log_file_from_path?speculative-link), [Rust](https://docs.rs/rerun/latest/rerun/struct.RecordingStream.html#method.log_file_from_path)) and the associated examples ([C++](https://github.com/rerun-io/rerun/blob/main/examples/cpp/log_file/main.cpp), [Python](https://github.com/rerun-io/rerun/blob/main/examples/python/log_file/main.py), [Rust](https://github.com/rerun-io/rerun/blob/main/examples/rust/log_file/src/main.rs)). + +Note: when calling these APIs from the SDK, the data will be loaded by the process running the SDK, not the Viewer! + +code-example: log-file + ## Adding support for arbitrary filetypes -Internally, the [`DataLoader`](https://docs.rs/re_data_source/latest/re_data_source/trait.DataLoader.html) trait takes care of loading files into the Viewer. +Internally, the [`DataLoader`](https://docs.rs/re_data_source/latest/re_data_source/trait.DataLoader.html) trait takes care of loading files into the Viewer and/or SDK. There are 3 broad kinds of `DataLoader`s: _builtin_, _external_ and _custom_. _External_ and _custom_ are the two ways of extending the file loading system that we'll describe below. -When a user attempts to open a file in the Viewer, **all** known `DataLoader`s are notified of the path to be opened, unconditionally. +When a user attempts to open a file in the Viewer/SDK, **all** known `DataLoader`s are notified of the path to be opened, unconditionally. This gives `DataLoader`s maximum flexibility to decide what files they are interested in, as opposed to e.g. only being able to look at a file's extension. Once notified, a `DataLoader` can return a [`DataLoaderError::Incompatible`](https://docs.rs/re_data_source/latest/re_data_source/enum.DataLoaderError.html#variant.Incompatible) error to indicate that it doesn't support a given file type. -If, and only if, all loaders known to the Viewer return an `Incompatible` error code, then an error message is shown to the user indicating that this file type is not (_yet_) supported. +If, and only if, all loaders known to the Viewer/SDK return an `Incompatible` error code, then an error message is shown to the user indicating that this file type is not (_yet_) supported. In these instances of unsupported files, we expose two ways of implementing and registering your `DataLoader`s, explained below. @@ -43,10 +51,10 @@ In these instances of unsupported files, we expose two ways of implementing and The easiest way to create your own `DataLoader` is by implementing what we call an "external loader": a stand alone executable written in any language that the Rerun SDK ships for. Any executable on your `$PATH` with a name that starts with `rerun-loader-` will be treated as a `DataLoader`. This executable takes a file path as a command line argument and outputs Rerun logs on `stdout`. -It will be called by the Rerun Viewer when the user opens a file, and be passed the path to that file. +It will be called by the Rerun Viewer/SDK when the user opens a file, and be passed the path to that file. From there, it can log data as usual, using the [`stdout` logging sink](../reference/sdk-operating-modes.md#standard-inputoutput). -The Rerun Viewer will then automatically load the data streamed to the external loader's standard output. +The Rerun Viewer/SDK will then automatically load the data streamed to the external loader's standard output. @@ -61,10 +69,10 @@ To indicate that it does not support a given file, the loader has to exit with a Check out our examples for [C++](https://github.com/rerun-io/rerun/tree/main/examples/cpp/external_data_loader), [Python](https://github.com/rerun-io/rerun/tree/main/examples/python/external_data_loader) and [Rust](https://github.com/rerun-io/rerun/tree/main/examples/rust/external_data_loader) that cover every steps in details. -### Custom data-loaders +### Custom Rust data-loaders -Another Rust-specific approach is to implement the `DataLoader` trait yourself and register it in the Rerun Viewer. +Another Rust-specific approach is to implement the `DataLoader` trait yourself and register it in the Rerun Viewer/SDK. -To do so, you'll need to import `rerun` as a library, register your `DataLoader` and then start the viewer from code. +To do so, you'll need to import `rerun` as a library, register your `DataLoader` and then start the Viewer/SDK from code. Check out our [example](https://github.com/rerun-io/rerun/tree/main/examples/rust/custom_data_loader) that cover all these steps in details. diff --git a/examples/rust/log_file/src/main.rs b/examples/rust/log_file/src/main.rs index ef183a228826..e8479b0b607a 100644 --- a/examples/rust/log_file/src/main.rs +++ b/examples/rust/log_file/src/main.rs @@ -36,9 +36,6 @@ fn main() -> anyhow::Result<()> { } fn run(rec: &rerun::RecordingStream, args: &Args) -> anyhow::Result<()> { - let mut settings = rerun::DataLoaderSettings::recommended(rec.store_info().unwrap().store_id); - settings.entity_path_prefix = Some("log_file_example".into()); - let prefix = Some("log_file_example".into()); for filepath in &args.filepaths {