Skip to content

Commit

Permalink
Replace host_web_viewer method with `WebViewerConfig::host_web_view…
Browse files Browse the repository at this point in the history
…er` (#7553)

### What

This makes it easier to host Rerun webviewer.

Usage example
```rust
    rerun::web_viewer::WebViewerConfig {
        source_url: Some(
            "https://app.rerun.io/version/0.18.1/examples/arkit_scenes.rrd".to_owned(),
        ),
        force_wgpu_backend: Some("webgl".to_owned()),
        ..Default::default()
    }
    .host_web_viewer()?
    .block();
```

This is a followup of this comment
#7537 (comment)
Opted to not implement a builder as well since I felt it's not worth the
hassle here, above snippet looks perfectly fine without a builder.

### Checklist
* [x] I have read and agree to [Contributor
Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and
the [Code of
Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md)
* [x] I've included a screenshot or gif (if applicable)
* [x] I have tested the web demo (if applicable):
* Using examples from latest `main` build:
[rerun.io/viewer](https://rerun.io/viewer/pr/7553?manifest_url=https://app.rerun.io/version/main/examples_manifest.json)
* Using full set of examples from `nightly` build:
[rerun.io/viewer](https://rerun.io/viewer/pr/7553?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json)
* [x] The PR title and labels are set such as to maximize their
usefulness for the next release's CHANGELOG
* [x] If applicable, add a new check to the [release
checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)!
* [x] If have noted any breaking changes to the log API in
`CHANGELOG.md` and the migration guide

- [PR Build Summary](https://build.rerun.io/pr/7553)
- [Recent benchmark results](https://build.rerun.io/graphs/crates.html)
- [Wasm size tracking](https://build.rerun.io/graphs/sizes.html)

To run all checks from `main`, comment on the PR with `@rerun-bot
full-check`.
  • Loading branch information
Wumpf authored Oct 1, 2024
1 parent c4eb805 commit 45add8d
Show file tree
Hide file tree
Showing 2 changed files with 116 additions and 47 deletions.
128 changes: 97 additions & 31 deletions crates/top/re_sdk/src/web_viewer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -106,41 +106,107 @@ impl Drop for WebViewerSink {

// ----------------------------------------------------------------------------

/// Helper to spawn an instance of the [`WebViewerServer`].
/// This serves the HTTP+Wasm+JS files that make up the web-viewer.
///
/// Optionally opens a browser with the web-viewer and connects to the provided `target_url`.
/// This url could be a hosted RRD file or a `ws://` url to a running [`re_ws_comms::RerunServer`].
///
/// Note: this does not include the websocket server.
///
/// - `force_wgpu_backend` is an optional string to force a specific backend, either `webgl` or `webgpu`.
/// Helper to spawn an instance of the [`WebViewerServer`] and configure a webviewer url.
#[cfg(feature = "web_viewer")]
pub fn host_web_viewer(
bind_ip: &str,
web_port: WebViewerServerPort,
force_wgpu_backend: Option<String>,
video_decoder: Option<String>,
open_browser: bool,
source_url: &str,
) -> anyhow::Result<WebViewerServer> {
let web_server = WebViewerServer::new(bind_ip, web_port)?;
let http_web_viewer_url = web_server.server_url();

let mut viewer_url = format!("{http_web_viewer_url}?url={source_url}");
if let Some(force_graphics) = force_wgpu_backend {
viewer_url = format!("{viewer_url}&renderer={force_graphics}");
}
if let Some(video_decoder) = video_decoder {
viewer_url = format!("{viewer_url}&video_decoder={video_decoder}");
}
pub struct WebViewerConfig {
/// Ip to which the http server is bound.
///
/// Defaults to 0.0.0.0
pub bind_ip: String,

/// The port to which the webviewer should bind.
///
/// Defaults to [`WebViewerServerPort::AUTO`].
pub web_port: WebViewerServerPort,

/// The url from which a spawned webviewer should source
///
/// This url could be a hosted RRD file or a `ws://` url to a running [`re_ws_comms::RerunServer`].
/// Has no effect if [`Self::open_browser`] is false.
pub source_url: Option<String>,

/// If set, adjusts the browser url to force a specific backend, either `webgl` or `webgpu`.
///
/// Has no effect if [`Self::open_browser`] is false.
pub force_wgpu_backend: Option<String>,

/// If set, adjusts the browser url to set the video decoder setting, either `auto`, `prefer_software` or `prefer_hardware`.
///
/// Has no effect if [`Self::open_browser`] is false.
pub video_decoder: Option<String>,

/// If set to `true`, opens the default browser after hosting the webviewer.
///
/// Defaults to `true`.
pub open_browser: bool,
}

re_log::info!("Hosting a web-viewer at {viewer_url}");
if open_browser {
webbrowser::open(&viewer_url).ok();
#[cfg(feature = "web_viewer")]
impl Default for WebViewerConfig {
fn default() -> Self {
Self {
bind_ip: "0.0.0.0".to_owned(),
web_port: WebViewerServerPort::AUTO,
source_url: None,
force_wgpu_backend: None,
video_decoder: None,
open_browser: true,
}
}
}

Ok(web_server)
#[cfg(feature = "web_viewer")]
impl WebViewerConfig {
/// Helper to spawn an instance of the [`WebViewerServer`].
/// This serves the HTTP+Wasm+JS files that make up the web-viewer.
///
/// The server will immediately start listening for incoming connections
/// and stop doing so when the returned [`WebViewerServer`] is dropped.
///
/// Note: this does not include the websocket server.
pub fn host_web_viewer(self) -> Result<WebViewerServer, WebViewerServerError> {
let Self {
bind_ip,
source_url,
web_port,
force_wgpu_backend,
video_decoder,
open_browser,
} = self;

let web_server = WebViewerServer::new(&bind_ip, web_port)?;
let http_web_viewer_url = web_server.server_url();

let mut viewer_url = http_web_viewer_url;

let mut first_arg = true;
let mut append_argument = |arg| {
let arg_delimiter = if first_arg {
first_arg = false;
"?"
} else {
"&"
};
viewer_url = format!("{viewer_url}{arg_delimiter}{arg}");
};

if let Some(source_url) = source_url {
append_argument(format!("url={source_url}"));
}
if let Some(force_graphics) = force_wgpu_backend {
append_argument(format!("renderer={force_graphics}"));
}
if let Some(video_decoder) = video_decoder {
append_argument(format!("video_decoder={video_decoder}"));
}

re_log::info!("Hosting a web-viewer at {viewer_url}");
if open_browser {
webbrowser::open(&viewer_url).ok();
}

Ok(web_server)
}
}

// ----------------------------------------------------------------------------
Expand Down
35 changes: 19 additions & 16 deletions crates/top/rerun/src/commands/entrypoint.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use re_smart_channel::{ReceiveSet, Receiver, SmartMessagePayload};
use crate::{commands::RrdCommands, CallSource};

#[cfg(feature = "web_viewer")]
use re_sdk::web_viewer::host_web_viewer;
use re_sdk::web_viewer::WebViewerConfig;
#[cfg(feature = "web_viewer")]
use re_web_viewer_server::WebViewerServerPort;
#[cfg(feature = "server")]
Expand Down Expand Up @@ -680,14 +680,16 @@ fn run_impl(
if let DataSource::WebSocketAddr(rerun_server_ws_url) = data_sources[0].clone() {
// Special case! We are connecting a web-viewer to a web-socket address.
// Instead of piping, just host a web-viewer that connects to the web-socket directly:
host_web_viewer(
&args.bind,
args.web_viewer_port,
args.renderer,
args.video_decoder,
true,
&rerun_server_ws_url,
)?

WebViewerConfig {
bind_ip: args.bind,
web_port: args.web_viewer_port,
source_url: Some(rerun_server_ws_url),
force_wgpu_backend: args.renderer,
video_decoder: args.video_decoder,
open_browser: true,
}
.host_web_viewer()?
.block();

return Ok(());
Expand Down Expand Up @@ -755,14 +757,15 @@ fn run_impl(
let open_browser = args.web_viewer;

// This is the server that serves the Wasm+HTML:
host_web_viewer(
&args.bind,
args.web_viewer_port,
args.renderer,
args.video_decoder,
WebViewerConfig {
bind_ip: args.bind,
web_port: args.web_viewer_port,
source_url: Some(_ws_server.server_url()),
force_wgpu_backend: args.renderer,
video_decoder: args.video_decoder,
open_browser,
&_ws_server.server_url(),
)?
}
.host_web_viewer()?
.block(); // dropping should stop the server
}

Expand Down

0 comments on commit 45add8d

Please sign in to comment.