From 6a2076f473fb2079b5e5f3fbce0daec1806ac4d1 Mon Sep 17 00:00:00 2001 From: Luxferre Date: Sun, 15 Sep 2024 18:49:42 +0300 Subject: [PATCH] Added headless build support --- Makefile | 8 ++++++++ README.md | 6 ++++++ src/Makefile | 13 +++++++++++-- src/gui.go | 31 +++++++++++++++++++++++++++++++ src/server.go | 29 ++++++++++++++--------------- 5 files changed, 70 insertions(+), 17 deletions(-) create mode 100644 src/gui.go diff --git a/Makefile b/Makefile index 7890a00..b61df36 100644 --- a/Makefile +++ b/Makefile @@ -12,6 +12,10 @@ all: $(MAKE) -C $(SRC) unix $(MAKE) dist +headless: + $(MAKE) -C $(SRC) unix-headless + $(MAKE) dist + win64: $(MAKE) -C $(SRC) win64 $(MAKE) dist @@ -20,6 +24,10 @@ win64-cross: $(MAKE) -C $(SRC) CGO_ENABLED=1 CC=$(CROSSCC) CXX=$(CROSSCXX) win64 $(MAKE) dist +win64-headless: + $(MAKE) -C $(SRC) win64-headless + $(MAKE) dist + dist: mkdir -p $(DIST) mv $(SRC)/streamgoose* $(DIST)/ diff --git a/README.md b/README.md index def9d3f..de7ee20 100644 --- a/README.md +++ b/README.md @@ -119,6 +119,12 @@ Then rerun the command from step 2. **Note**: When testing the cross-compiled build under Wine, you must have Microsoft Edge WebView2 Runtime installed in order for the GUI to work at all. You can [download](https://developer.microsoft.com/en-us/microsoft-edge/webview2) this engine directly from the Microsoft website (select "Evergreen Standalone Installer") and install it into your Wine profile. Be sure to enable at least Windows 7 emulation in winecfg. +### Headless builds + +In case you don't want to build the GUI, you can run `make headless` and `make win64-headless` depending on the platform. In this case, a binary will be built where you'll be required to point any JS-enabled Web browser of your choice to `http://127.0.0.1:60053` to see the chat window. This can be useful when building StreamGoose on more exotic platforms not supported by the `webview_go` library. + +Note that the `make win64-headless` command can be run on both Linux and Windows, all cross-compilation is done transparently in this case. + ## Usage diff --git a/src/Makefile b/src/Makefile index 067f259..964e4ca 100644 --- a/src/Makefile +++ b/src/Makefile @@ -2,15 +2,24 @@ LDFLAGS = -s -w LDFLAGS_WIN = -H windowsgui -s -w GOFLAGS = -trimpath SOURCES = server.go twitch.go youtube.go owncast.go kick.go +SOURCES_GUI = $(SOURCES) gui.go BIN = streamgoose unix: go mod tidy - go build -o $(BIN) $(GOFLAGS) -ldflags "$(LDFLAGS)" $(SOURCES) + go build $(GOFLAGS) -ldflags "$(LDFLAGS)" -o $(BIN) $(SOURCES_GUI) + +unix-headless: + go mod tidy + go build $(GOFLAGS) -ldflags "$(LDFLAGS)" -o $(BIN) $(SOURCES) win64: go mod tidy - GOOS=windows GOARCH=amd64 go build -o $(BIN).exe $(GOFLAGS) -ldflags "$(LDFLAGS_WIN)" $(SOURCES) + GOOS=windows GOARCH=amd64 go build $(GOFLAGS) -ldflags "$(LDFLAGS_WIN)" -o $(BIN).exe $(SOURCES_GUI) + +win64-headless: + go mod tidy + GOOS=windows GOARCH=amd64 go build $(GOFLAGS) -ldflags "$(LDFLAGS)" -o $(BIN).exe $(SOURCES) clean: rm $(BIN) diff --git a/src/gui.go b/src/gui.go new file mode 100644 index 0000000..4aba129 --- /dev/null +++ b/src/gui.go @@ -0,0 +1,31 @@ +/* + StreamGoose UI — Go reference implementation + + Created by Luxferre in 2024, released into public domain +*/ +package main + +import ( + "fmt" + "centrifuge.hectabit.org/HectaBit/webview_go" /* for UI launch */ +) + +/* override GUI entry point */ +func init() { + goose_start_gui = func(config map[string]interface{}) { + /* target server listening address */ + target_addr := fmt.Sprintf("%s:%d", config["server_listen_ip"].(string), int(config["server_port"].(float64))) + + /* start the GUI */ + debug := false + if _, ok := config["debug"]; ok && config["debug"].(bool) == true { + debug = true + } + bro := webview.New(debug) /* create a browser instance */ + bro.SetSize(320, 720, webview.HintNone) + defer bro.Destroy() + bro.SetTitle("StreamGoose v0.0.1") + bro.Navigate("http://" + target_addr) + bro.Run() + } +} diff --git a/src/server.go b/src/server.go index 49e6cfa..29bf646 100644 --- a/src/server.go +++ b/src/server.go @@ -9,13 +9,12 @@ import ( "os" "fmt" "log" + "time" "strings" "slices" "encoding/json" "net/http" "io/ioutil" - /* external */ - "centrifuge.hectabit.org/HectaBit/webview_go" /* for UI launch */ ) /* main chat message structure */ @@ -31,7 +30,17 @@ type ChatMessage struct { var global_msg_id uint64 = 0 /* track global message ID */ var message_transport chan ChatMessage /* global message channel */ var sse_transports []chan string /* SSE output channels */ -var bro webview.WebView /* global browser instance handle */ + +/* headless behaviour by default */ +var goose_start_gui = func(config map[string]interface{}) { + /* target server listening address */ + const fmt_str = "[headless] Connect to http://%s:%d in any browser to see the chat window" + log.Printf(fmt_str, config["server_listen_ip"].(string), int(config["server_port"].(float64))) + /* just do nothing except sleep in the main thread */ + for { + time.Sleep(time.Duration(3600) * time.Second) + } +} /* escape HTML entities in JS parameters */ func esc(s string) string { @@ -157,7 +166,6 @@ func main() { log.Fatal(err) } }() - if _, ok := config["tw_backend_enabled"]; ok && config["tw_backend_enabled"].(bool) == true { go twitch_run(config) /* start the Twitch backend */ @@ -175,16 +183,7 @@ func main() { go kick_run(config) /* start the Kick backend */ } - /* start the GUI */ - debug := false - if _, ok := config["debug"]; ok && config["debug"].(bool) == true { - debug = true - } - bro = webview.New(debug) /* create a browser instance */ - bro.SetSize(320, 720, webview.HintNone) - defer bro.Destroy() - bro.SetTitle("StreamGoose v0.0.1") - bro.Navigate("http://" + target_addr) - bro.Run() + /* start the GUI from gui.go file */ + goose_start_gui(config) }