Skip to content

Commit 45add8d

Browse files
authored
Replace host_web_viewer method with WebViewerConfig::host_web_viewer (#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`.
1 parent c4eb805 commit 45add8d

File tree

2 files changed

+116
-47
lines changed

2 files changed

+116
-47
lines changed

crates/top/re_sdk/src/web_viewer.rs

+97-31
Original file line numberDiff line numberDiff line change
@@ -106,41 +106,107 @@ impl Drop for WebViewerSink {
106106

107107
// ----------------------------------------------------------------------------
108108

109-
/// Helper to spawn an instance of the [`WebViewerServer`].
110-
/// This serves the HTTP+Wasm+JS files that make up the web-viewer.
111-
///
112-
/// Optionally opens a browser with the web-viewer and connects to the provided `target_url`.
113-
/// This url could be a hosted RRD file or a `ws://` url to a running [`re_ws_comms::RerunServer`].
114-
///
115-
/// Note: this does not include the websocket server.
116-
///
117-
/// - `force_wgpu_backend` is an optional string to force a specific backend, either `webgl` or `webgpu`.
109+
/// Helper to spawn an instance of the [`WebViewerServer`] and configure a webviewer url.
118110
#[cfg(feature = "web_viewer")]
119-
pub fn host_web_viewer(
120-
bind_ip: &str,
121-
web_port: WebViewerServerPort,
122-
force_wgpu_backend: Option<String>,
123-
video_decoder: Option<String>,
124-
open_browser: bool,
125-
source_url: &str,
126-
) -> anyhow::Result<WebViewerServer> {
127-
let web_server = WebViewerServer::new(bind_ip, web_port)?;
128-
let http_web_viewer_url = web_server.server_url();
129-
130-
let mut viewer_url = format!("{http_web_viewer_url}?url={source_url}");
131-
if let Some(force_graphics) = force_wgpu_backend {
132-
viewer_url = format!("{viewer_url}&renderer={force_graphics}");
133-
}
134-
if let Some(video_decoder) = video_decoder {
135-
viewer_url = format!("{viewer_url}&video_decoder={video_decoder}");
136-
}
111+
pub struct WebViewerConfig {
112+
/// Ip to which the http server is bound.
113+
///
114+
/// Defaults to 0.0.0.0
115+
pub bind_ip: String,
116+
117+
/// The port to which the webviewer should bind.
118+
///
119+
/// Defaults to [`WebViewerServerPort::AUTO`].
120+
pub web_port: WebViewerServerPort,
121+
122+
/// The url from which a spawned webviewer should source
123+
///
124+
/// This url could be a hosted RRD file or a `ws://` url to a running [`re_ws_comms::RerunServer`].
125+
/// Has no effect if [`Self::open_browser`] is false.
126+
pub source_url: Option<String>,
127+
128+
/// If set, adjusts the browser url to force a specific backend, either `webgl` or `webgpu`.
129+
///
130+
/// Has no effect if [`Self::open_browser`] is false.
131+
pub force_wgpu_backend: Option<String>,
132+
133+
/// If set, adjusts the browser url to set the video decoder setting, either `auto`, `prefer_software` or `prefer_hardware`.
134+
///
135+
/// Has no effect if [`Self::open_browser`] is false.
136+
pub video_decoder: Option<String>,
137+
138+
/// If set to `true`, opens the default browser after hosting the webviewer.
139+
///
140+
/// Defaults to `true`.
141+
pub open_browser: bool,
142+
}
137143

138-
re_log::info!("Hosting a web-viewer at {viewer_url}");
139-
if open_browser {
140-
webbrowser::open(&viewer_url).ok();
144+
#[cfg(feature = "web_viewer")]
145+
impl Default for WebViewerConfig {
146+
fn default() -> Self {
147+
Self {
148+
bind_ip: "0.0.0.0".to_owned(),
149+
web_port: WebViewerServerPort::AUTO,
150+
source_url: None,
151+
force_wgpu_backend: None,
152+
video_decoder: None,
153+
open_browser: true,
154+
}
141155
}
156+
}
142157

143-
Ok(web_server)
158+
#[cfg(feature = "web_viewer")]
159+
impl WebViewerConfig {
160+
/// Helper to spawn an instance of the [`WebViewerServer`].
161+
/// This serves the HTTP+Wasm+JS files that make up the web-viewer.
162+
///
163+
/// The server will immediately start listening for incoming connections
164+
/// and stop doing so when the returned [`WebViewerServer`] is dropped.
165+
///
166+
/// Note: this does not include the websocket server.
167+
pub fn host_web_viewer(self) -> Result<WebViewerServer, WebViewerServerError> {
168+
let Self {
169+
bind_ip,
170+
source_url,
171+
web_port,
172+
force_wgpu_backend,
173+
video_decoder,
174+
open_browser,
175+
} = self;
176+
177+
let web_server = WebViewerServer::new(&bind_ip, web_port)?;
178+
let http_web_viewer_url = web_server.server_url();
179+
180+
let mut viewer_url = http_web_viewer_url;
181+
182+
let mut first_arg = true;
183+
let mut append_argument = |arg| {
184+
let arg_delimiter = if first_arg {
185+
first_arg = false;
186+
"?"
187+
} else {
188+
"&"
189+
};
190+
viewer_url = format!("{viewer_url}{arg_delimiter}{arg}");
191+
};
192+
193+
if let Some(source_url) = source_url {
194+
append_argument(format!("url={source_url}"));
195+
}
196+
if let Some(force_graphics) = force_wgpu_backend {
197+
append_argument(format!("renderer={force_graphics}"));
198+
}
199+
if let Some(video_decoder) = video_decoder {
200+
append_argument(format!("video_decoder={video_decoder}"));
201+
}
202+
203+
re_log::info!("Hosting a web-viewer at {viewer_url}");
204+
if open_browser {
205+
webbrowser::open(&viewer_url).ok();
206+
}
207+
208+
Ok(web_server)
209+
}
144210
}
145211

146212
// ----------------------------------------------------------------------------

crates/top/rerun/src/commands/entrypoint.rs

+19-16
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ use re_smart_channel::{ReceiveSet, Receiver, SmartMessagePayload};
88
use crate::{commands::RrdCommands, CallSource};
99

1010
#[cfg(feature = "web_viewer")]
11-
use re_sdk::web_viewer::host_web_viewer;
11+
use re_sdk::web_viewer::WebViewerConfig;
1212
#[cfg(feature = "web_viewer")]
1313
use re_web_viewer_server::WebViewerServerPort;
1414
#[cfg(feature = "server")]
@@ -680,14 +680,16 @@ fn run_impl(
680680
if let DataSource::WebSocketAddr(rerun_server_ws_url) = data_sources[0].clone() {
681681
// Special case! We are connecting a web-viewer to a web-socket address.
682682
// Instead of piping, just host a web-viewer that connects to the web-socket directly:
683-
host_web_viewer(
684-
&args.bind,
685-
args.web_viewer_port,
686-
args.renderer,
687-
args.video_decoder,
688-
true,
689-
&rerun_server_ws_url,
690-
)?
683+
684+
WebViewerConfig {
685+
bind_ip: args.bind,
686+
web_port: args.web_viewer_port,
687+
source_url: Some(rerun_server_ws_url),
688+
force_wgpu_backend: args.renderer,
689+
video_decoder: args.video_decoder,
690+
open_browser: true,
691+
}
692+
.host_web_viewer()?
691693
.block();
692694

693695
return Ok(());
@@ -755,14 +757,15 @@ fn run_impl(
755757
let open_browser = args.web_viewer;
756758

757759
// This is the server that serves the Wasm+HTML:
758-
host_web_viewer(
759-
&args.bind,
760-
args.web_viewer_port,
761-
args.renderer,
762-
args.video_decoder,
760+
WebViewerConfig {
761+
bind_ip: args.bind,
762+
web_port: args.web_viewer_port,
763+
source_url: Some(_ws_server.server_url()),
764+
force_wgpu_backend: args.renderer,
765+
video_decoder: args.video_decoder,
763766
open_browser,
764-
&_ws_server.server_url(),
765-
)?
767+
}
768+
.host_web_viewer()?
766769
.block(); // dropping should stop the server
767770
}
768771

0 commit comments

Comments
 (0)