From b1c6b40ebf9b93d368ca2f9487fea6f27bbe4e84 Mon Sep 17 00:00:00 2001 From: Robin Deits Date: Mon, 11 Jun 2018 14:20:30 -0400 Subject: [PATCH] refactor out servers components to keep working around https://github.com/JuliaLang/julia/issues/21653 --- src/MeshCat.jl | 60 +------------------------- src/servers.jl | 114 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 116 insertions(+), 58 deletions(-) create mode 100644 src/servers.jl diff --git a/src/MeshCat.jl b/src/MeshCat.jl index c04df4e..e1f3229 100644 --- a/src/MeshCat.jl +++ b/src/MeshCat.jl @@ -12,9 +12,7 @@ using GeometryTypes: raw using Parameters: @with_kw using Base.Random: UUID, uuid1 using DocStringExtensions -using Requires: @require -using Mux: page -using JSExpr +using JSExpr: @js, @new, @var using Base.Filesystem: rm using BinDeps: download_cmd, unpack_cmd @@ -57,9 +55,6 @@ export PointsMaterial, export Animation, atframe - - - include("trees.jl") using .SceneTrees include("geometry.jl") @@ -71,61 +66,10 @@ include("lowering.jl") include("msgpack.jl") include("visualizer.jl") include("animation_visualizer.jl") +include("servers.jl") const VIEWER_ROOT = joinpath(@__DIR__, "..", "assets", "meshcat", "dist") -Base.open(vis::Visualizer, args...; kw...) = open(vis.core, args...; kw...) - -function Base.open(core::CoreVisualizer, port::Integer) - WebIO.webio_serve(page("/", req -> core.scope), port) - url = "http://127.0.0.1:$port" - info("Serving MeshCat visualizer at $url") - open_url(url) -end - -function open_url(url) - try - if is_windows() - run(`start $url`) - elseif is_apple() - run(`open $url`) - elseif is_linux() - run(`xdg-open $url`) - end - catch e - println("Could not open browser automatically: $e") - println("Please open the following URL in your browser:") - println(url) - end -end - -function Base.open(core::CoreVisualizer; default_port=8700, max_retries=500) - for port in default_port + (0:max_retries) - server = try - listen(port) - catch e - if e isa Base.UVError - continue - end - end - close(server) - # It is *possible* that a race condition could occur here, in which - # some other process grabs the given port in between the close() above - # and the open() below. But it's unlikely and would not be terribly - # damaging (the user would just have to call open() again). - return open(core, port) - end -end - -@require Blink begin - function Base.open(core::CoreVisualizer, w::Blink.AtomShell.Window) - # Ensure the window is ready - Blink.js(w, "ok") - # Set its contents - Blink.body!(w, core.scope) - w - end -end function develop_meshcat_assets(skip_confirmation=false) meshcat_dir = abspath(joinpath(@__DIR__, "..", "assets", "meshcat")) diff --git a/src/servers.jl b/src/servers.jl new file mode 100644 index 0000000..1915457 --- /dev/null +++ b/src/servers.jl @@ -0,0 +1,114 @@ +module Servers + module MuxProvider + using Mux + using WebIO + using JSON + + # This module was copied over from + # https://github.com/JuliaGizmos/WebIO.jl/blob/8e25ed2f9cf3158652907735bd44420205a105d9/src/providers/mux.jl + # to attempt to avoid inference issues described in: + # https://github.com/JuliaLang/julia/issues/21653 + function webio_serve(app, port=8000) + http = Mux.App(Mux.mux( + Mux.defaults, + app, + Mux.notfound() + )) + + websock = Mux.App(Mux.mux( + Mux.wdefaults, + route("/webio-socket", create_socket), + Mux.wclose, + Mux.notfound(), + )) + + serve(http, websock, port) + end + + struct WebSockConnection <: AbstractConnection + sock + end + + function create_socket(req) + sock = req[:socket] + conn = WebSockConnection(sock) + + t = @async while isopen(sock) + data = read(sock) + + msg = JSON.parse(String(data)) + WebIO.dispatch(conn, msg) + end + + wait(t) + end + + function Base.send(p::WebSockConnection, data) + write(p.sock, sprint(io->JSON.print(io,data))) + end + + Base.isopen(p::WebSockConnection) = isopen(p.sock) + end + + using .MuxProvider: webio_serve + using MeshCat: CoreVisualizer, Visualizer + using Mux: page + + Base.open(vis::Visualizer, args...; kw...) = open(vis.core, args...; kw...) + + function Base.open(core::CoreVisualizer, port::Integer) + webio_serve(page("/", req -> core.scope), port) + url = "http://127.0.0.1:$port" + info("Serving MeshCat visualizer at $url") + open_url(url) + end + + function open_url(url) + try + if is_windows() + run(`start $url`) + elseif is_apple() + run(`open $url`) + elseif is_linux() + run(`xdg-open $url`) + end + catch e + println("Could not open browser automatically: $e") + println("Please open the following URL in your browser:") + println(url) + end + end + + function Base.open(core::CoreVisualizer; default_port=8700, max_retries=500) + for port in default_port + (0:max_retries) + server = try + listen(port) + catch e + if e isa Base.UVError + continue + end + end + close(server) + # It is *possible* that a race condition could occur here, in which + # some other process grabs the given port in between the close() above + # and the open() below. But it's unlikely and would not be terribly + # damaging (the user would just have to call open() again). + return open(core, port) + end + end +end + +module BlinkInterface + using Requires + using MeshCat: CoreVisualizer + + @require Blink begin + function Base.open(core::CoreVisualizer, w::Blink.AtomShell.Window) + # Ensure the window is ready + Blink.js(w, "ok") + # Set its contents + Blink.body!(w, core.scope) + w + end + end +end