From 76962b3eb00e613e2aeb88634fbb5dbc0bc75f52 Mon Sep 17 00:00:00 2001 From: Matjaz Debelak Date: Mon, 25 Mar 2024 14:29:00 +0100 Subject: [PATCH] Add rundimentary UI to reaper ctrl --- go.mod | 7 ++ go.sum | 28 +++++ reaper-control/control.go | 82 +++++++++++++ reaper-control/main.go | 158 +++++++------------------ reaper-control/templates/status.gohtml | 16 +++ reaper-control/ui.go | 44 +++++++ reaper-control/utils.go | 4 +- 7 files changed, 220 insertions(+), 119 deletions(-) create mode 100644 reaper-control/control.go create mode 100644 reaper-control/templates/status.gohtml create mode 100644 reaper-control/ui.go diff --git a/go.mod b/go.mod index 0b62f29..21ec88b 100644 --- a/go.mod +++ b/go.mod @@ -8,9 +8,12 @@ require ( cloud.google.com/go/monitoring v1.13.0 github.com/ansel1/merry/v2 v2.0.0-beta.12 github.com/bcc-code/mediabank-bridge v1.1.1 + github.com/davecgh/go-spew v1.1.1 github.com/gin-contrib/cors v1.4.0 github.com/gin-gonic/gin v1.9.1 github.com/golang/protobuf v1.5.3 + github.com/mattn/go-sqlite3 v1.14.22 + github.com/pingcap/log v1.1.0 github.com/rs/zerolog v1.26.0 github.com/samber/lo v1.38.1 google.golang.org/api v0.114.0 @@ -58,6 +61,9 @@ require ( github.com/ugorji/go/codec v1.2.11 // indirect github.com/zeebo/xxh3 v1.0.2 // indirect go.opencensus.io v0.24.0 // indirect + go.uber.org/atomic v1.9.0 // indirect + go.uber.org/multierr v1.7.0 // indirect + go.uber.org/zap v1.19.0 // indirect golang.org/x/arch v0.3.0 // indirect golang.org/x/crypto v0.17.0 // indirect golang.org/x/exp v0.0.0-20220827204233-334a2380cb91 // indirect @@ -73,5 +79,6 @@ require ( google.golang.org/appengine v1.6.7 // indirect google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1 // indirect google.golang.org/grpc v1.56.3 // indirect + gopkg.in/natefinch/lumberjack.v2 v2.0.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/go.sum b/go.sum index d9eaa81..cae56a0 100644 --- a/go.sum +++ b/go.sum @@ -18,6 +18,7 @@ cloud.google.com/go/longrunning v0.4.1/go.mod h1:4iWDqhBZ70CvZ6BfETbvam3T8FMvLK+ cloud.google.com/go/monitoring v1.13.0 h1:2qsrgXGVoRXpP7otZ14eE1I568zAa92sJSDPyOJvwjM= cloud.google.com/go/monitoring v1.13.0/go.mod h1:k2yMBAB1H9JT/QETjNkgdCGD9bPF712XiLTVr+cBrpw= cloud.google.com/go/storage v1.29.0 h1:6weCgzRvMg7lzuUurI4697AqIRPU1SvzHhynwpW31jI= +github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/JohnCGriffin/overflow v0.0.0-20211019200055-46fa312c352c h1:RGWPOewvKIROun94nF7v2cua9qP+thov/7M50KEoeSU= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= @@ -35,6 +36,8 @@ github.com/apache/thrift v0.16.0 h1:qEy6UW60iVOlUy+b9ZR0d5WzUWYGOo4HfopoyBaNmoY= github.com/apache/thrift v0.16.0/go.mod h1:PHK3hniurgQaNMZYaCLEqXKsYK8upmhPbmdP2FXSqgU= github.com/bcc-code/mediabank-bridge v1.1.1 h1:9nnoicJvAnIY0IeNamQwKnj0/LRS2jLYF8ZOcHYvzDM= github.com/bcc-code/mediabank-bridge v1.1.1/go.mod h1:q4CQKCNK/y0JnytZ8rTouRN2TVXOh0tJlz2U8qFHtNk= +github.com/benbjohnson/clock v1.1.0 h1:Q92kusRqC1XV2MjkWETPvjJVqKetz1OzxZB7mHJLju8= +github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= github.com/bytedance/sonic v1.5.0/go.mod h1:ED5hyg4y6t3/9Ku1R6dU/4KyJ48DZ4jPhfY1O2AihPM= github.com/bytedance/sonic v1.9.1 h1:6iJ6NqdoxCDr6mbY8h18oSO+cShGSMRGCEo7F2h0x8s= github.com/bytedance/sonic v1.9.1/go.mod h1:i736AoUSYt75HyZLoJW9ERYxcy6eaN6h4BZXU064P/U= @@ -162,6 +165,8 @@ github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNx github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA= github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/mattn/go-sqlite3 v1.14.22 h1:2gZY6PC6kBnID23Tichd1K+Z0oS6nE/XwU+Vz/5o4kU= +github.com/mattn/go-sqlite3 v1.14.22/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y= github.com/minio/asm2plan9s v0.0.0-20200509001527-cdd76441f9d8 h1:AMFGa4R4MiIpspGNG7Z948v4n35fFGB3RR3G/ry4FWs= github.com/minio/asm2plan9s v0.0.0-20200509001527-cdd76441f9d8/go.mod h1:mC1jAcsrzbxHt8iiaC+zU4b1ylILSosueou12R++wfY= github.com/minio/c2goasm v0.0.0-20190812172519-36a3d3bbc4f3 h1:+n/aFZefKZp7spd8DFdX7uMikMLXX4oubIzJF4kv/wI= @@ -176,7 +181,12 @@ github.com/pelletier/go-toml/v2 v2.0.8 h1:0ctb6s9mE31h0/lhu+J6OPmVeDxJn+kYnJc2jZ github.com/pelletier/go-toml/v2 v2.0.8/go.mod h1:vuYfssBdrU2XDZ9bYydBu6t+6a6PYNcZljzZR9VXg+4= github.com/pierrec/lz4/v4 v4.1.15 h1:MO0/ucJhngq7299dKLwIMtgTfbkoSPF6AoMYDd8Q4q0= github.com/pierrec/lz4/v4 v4.1.15/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4= +github.com/pingcap/errors v0.11.0 h1:DCJQB8jrHbQ1VVlMFIrbj2ApScNNotVmkSNplu2yUt4= +github.com/pingcap/errors v0.11.0/go.mod h1:Oi8TUi2kEtXXLMJk9l1cGmz20kV3TaQ0usTwv5KuLY8= +github.com/pingcap/log v1.1.0 h1:ELiPxACz7vdo1qAvvaWJg1NrYFoY6gqAh/+Uo6aXdD8= +github.com/pingcap/log v1.1.0/go.mod h1:DWQW5jICDR7UJh4HtxXSM20Churx4CQL0fwL/SoOSA4= github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= +github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= @@ -197,6 +207,7 @@ github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSS github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= @@ -219,6 +230,16 @@ github.com/zeebo/xxh3 v1.0.2/go.mod h1:5NWz9Sef7zIDm2JHfFlcQvNekmcEl9ekUZQQKCYaD go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0= go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo= go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= +go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= +go.uber.org/atomic v1.9.0 h1:ECmE8Bn/WFTYwEW/bpKD3M8VtR/zQVbavAoalC1PYyE= +go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= +go.uber.org/goleak v1.1.10 h1:z+mqJhf6ss6BSfSM671tgKyZBFPTTJM+HLxnhPC3wu0= +go.uber.org/goleak v1.1.10/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A= +go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= +go.uber.org/multierr v1.7.0 h1:zaiO/rmgFjbmCXdSYJWQcdvOCsthmdaHfr3Gm2Kx4Ec= +go.uber.org/multierr v1.7.0/go.mod h1:7EAYxJLBy9rStEaz58O2t4Uvip6FSURkq8/ppBp95ak= +go.uber.org/zap v1.19.0 h1:mZQZefskPPCMIBCSEH0v2/iUqqLrYtaeqwD6FUGUnFE= +go.uber.org/zap v1.19.0/go.mod h1:xg/QME4nWcxGxrpdeYfq7UvYrLh66cuVKdrbD1XF/NI= golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8= golang.org/x/arch v0.3.0 h1:02VY4/ZcO/gBOH6PUaoiptASxtXU10jazRCP865E97k= golang.org/x/arch v0.3.0/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8= @@ -234,6 +255,8 @@ golang.org/x/exp v0.0.0-20220827204233-334a2380cb91/go.mod h1:cyybsKvd6eL0RnXn6p golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190930215403-16217165b5de h1:5hukYrvBGR8/eNkX5mdUezrA6JiaEZDtJb9Ei+1LlBs= +golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.8.0 h1:LUYupSeNrTNCGzR/hVBk2NHZO4hXcVaW1k4Qx7rjPx8= @@ -296,6 +319,7 @@ golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGm golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20191108193012-7d206e10da11/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.1.7/go.mod h1:LGqMHiF4EqQNHR1JncWGqT5BVaXmza+X+BDGol+dOxo= golang.org/x/tools v0.6.0 h1:BOw41kyTf3PuCW1pVQf8+Cyg8pMlkYB1oo9iJ6D/lKM= @@ -352,8 +376,12 @@ gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8 gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= +gopkg.in/natefinch/lumberjack.v2 v2.0.0 h1:1Lc07Kr7qY4U2YPouBjpCLxpiyxIVoxqXgkXLknAOE8= +gopkg.in/natefinch/lumberjack.v2 v2.0.0/go.mod h1:l0ndWWf7gzL7RNwBG7wST/UCcT4T24xpD6X8LsfU/+k= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/reaper-control/control.go b/reaper-control/control.go new file mode 100644 index 0000000..b04453e --- /dev/null +++ b/reaper-control/control.go @@ -0,0 +1,82 @@ +package main + +import ( + "errors" + "net/http" + "os/exec" + "runtime" + "time" +) + +var ( + errAlreadyStarted = errors.New("Reaper already started") + errUnknownOS = errors.New("Unknown operating system") + errFailedToStart = errors.New("Failed to start Reaper") + errRecodingFailed = errors.New("Failed to start recording") + errRecordingStopFailed = errors.New("Failed to stop recording") + errFailedToStop = errors.New("Failed to stop Reaper") + errReaperNotStarted = errors.New("Reaper not started") +) + +func startReaper() error { + lock.Lock() + defer lock.Unlock() + + var cmd *exec.Cmd + + if reaperProcess != nil && !reaperProcess.ProcessState.Exited() { + return errAlreadyStarted + } + + mediaList = listFiles(MediaGlob) + + if runtime.GOOS == "windows" { + cmd = exec.Command("C:\\Program Files\\REAPER (x64)\\reaper.exe") + } else if runtime.GOOS == "darwin" { + cmd = exec.Command("/Applications/REAPER.app/Contents/MacOS/REAPER") + } + + if cmd == nil { + return errUnknownOS + } + + err := cmd.Start() + if err != nil { + return errFailedToStart + } + + reaperProcess = cmd + + if isReaperOn(40*time.Second) == false { + return errRecodingFailed + } + + _, err = http.Get(ReaperAddress + "/_/1013;TRANSPORT") + if err != nil { + return errRecodingFailed + } + + return nil +} + +func stopReaper() error { + lock.Lock() + defer lock.Unlock() + + if reaperProcess == nil { + return errReaperNotStarted + } + + _, err := http.Get(ReaperAddress + "/_/40667;TRANSPORT") + if err != nil { + return errRecordingStopFailed + } + + if err := stopProcess(reaperProcess.Process); err != nil { + return errFailedToStop + } + + reaperProcess = nil + + return nil +} diff --git a/reaper-control/main.go b/reaper-control/main.go index 32e02e4..4d75d64 100644 --- a/reaper-control/main.go +++ b/reaper-control/main.go @@ -1,17 +1,26 @@ package main import ( + "embed" + "html/template" "net/http" "os" "os/exec" - "runtime" - "time" + "sync" "github.com/gin-gonic/gin" "github.com/samber/lo" ) -var ReaperAddress string +var ( + ReaperAddress string + reaperProcess *exec.Cmd + mediaList []string + lock sync.Mutex +) + +//go:embed templates/*.gohtml +var templateFS embed.FS func main() { ReaperAddress = os.Getenv("REAPER_ADDRESS") @@ -19,66 +28,30 @@ func main() { ReaperAddress = "http://10.12.6.12:8080" } + parsedTemplates, err := template.ParseFS(templateFS, "templates/*.gohtml") + if err != nil { + panic(err) + } + router := gin.Default() + router.SetHTMLTemplate(parsedTemplates) router.GET("/ping", func(c *gin.Context) { c.String(200, "pong") }) router.GET("/start", start) + router.GET("/status", status) router.GET("/stop", stop) router.GET("/files", files) - /// *** LEGACY CODE *** /// - router.GET("/startReaper", startReaper) - router.GET("/stopReaper", stopReaper) - router.GET("/startReaperRecording", startReaperRecording) - router.GET("/stopReaperRecording", stopReaperRecording) - // *** END LEGACY CODE *** /// + router.Group("ui"). + GET("/start", startUI). + GET("/stop", stopUI) router.Run(":8081") } -var reaperProcess *os.Process -var mediaList []string - const MediaGlob = "D:\\ReaperMedia\\*.wav" -func start(c *gin.Context) { - var cmd *exec.Cmd - - mediaList = listFiles(MediaGlob) - - if runtime.GOOS == "windows" { - cmd = exec.Command("C:\\Program Files\\REAPER (x64)\\reaper.exe") - } else if runtime.GOOS == "darwin" { - cmd = exec.Command("/Applications/REAPER.app/Contents/MacOS/REAPER") - } - - if cmd == nil { - c.String(500, "Unsupported operating system") - return - } - - err := cmd.Start() - if err != nil { - c.String(500, "Failed to start Reaper: %v", err) - return - } - reaperProcess = cmd.Process - - if isReaperOn(40*time.Second) == false { - c.String(500, "Error requesting URL: %v", err) - return - } - - _, err = http.Get(ReaperAddress + "/_/1013;TRANSPORT") - if err != nil { - c.String(500, "Error requesting URL: %v", err) - return - } - - c.String(200, "Reaper started") -} - func files(c *gin.Context) { fileList := listFiles(MediaGlob) diff, _ := lo.Difference(fileList, mediaList) @@ -86,91 +59,42 @@ func files(c *gin.Context) { c.JSON(200, diff) } -func stop(c *gin.Context) { - _, err := http.Get(ReaperAddress + "/_/40667;TRANSPORT") - if err != nil { - c.String(500, "Error requesting URL: %v", err) - return - } - - fileList := listFiles(MediaGlob) - diff, _ := lo.Difference(fileList, mediaList) - - if reaperProcess == nil { - c.String(500, "Reaper not started") - return - } - - if err := stopProcess(reaperProcess); err != nil { - c.String(500, "Failed to stop Reaper: %v", err) - return - } - - c.JSON(200, diff) +type ReaperStatus struct { + Heading string + ProcessState string + Recording bool } -//// *** LEGACY CODE *** //// - -func startReaper(c *gin.Context) { - var cmd *exec.Cmd - - mediaList = listFiles(MediaGlob) - - if runtime.GOOS == "windows" { - cmd = exec.Command("C:\\Program Files\\REAPER (x64)\\reaper.exe") - } else if runtime.GOOS == "darwin" { - cmd = exec.Command("/Applications/REAPER.app/Contents/MacOS/REAPER") - } +func start(c *gin.Context) { + err := startReaper() - if cmd == nil { - c.String(500, "Unsupported operating system") + if err == errAlreadyStarted { + c.String(http.StatusConflict, "Reaper already started") return } - err := cmd.Start() - if err != nil { - c.String(500, "Failed to start Reaper: %v", err) + if err == errUnknownOS { + c.String(http.StatusInternalServerError, "Unknown operating system") return } - reaperProcess = cmd.Process - if isReaperOn(40*time.Second) == false { - c.String(500, "Error requesting URL: %v", err) + if err != nil { + c.String(http.StatusInternalServerError, "Failed to start Reaper: %v", err) return } - c.String(200, "Reaper started") + c.String(http.StatusOK, "Reaper started") } -func stopReaper(c *gin.Context) { - if reaperProcess == nil { - c.String(500, "Reaper not started") - return - } - - if err := stopProcess(reaperProcess); err != nil { - c.String(500, "Failed to stop Reaper: %v", err) - return - } - - c.String(200, "Reaper stopped") -} +func stop(c *gin.Context) { + fileList := listFiles(MediaGlob) + diff, _ := lo.Difference(fileList, mediaList) -func startReaperRecording(c *gin.Context) { - _, err := http.Get(ReaperAddress + "/_/1013;TRANSPORT") + err := stopReaper() if err != nil { - c.String(500, "Error requesting URL: %v", err) + c.String(http.StatusInternalServerError, "Failed to stop Reaper: %v", err) return } - c.String(200, "Reaper recording started") -} - -func stopReaperRecording(c *gin.Context) { - _, err := http.Get(ReaperAddress + "/_/40667;TRANSPORT") - if err != nil { - c.String(500, "Error requesting URL: %v", err) - return - } - c.String(200, "Reaper recording stopped") + c.JSON(http.StatusOK, diff) } diff --git a/reaper-control/templates/status.gohtml b/reaper-control/templates/status.gohtml new file mode 100644 index 0000000..cd3fecf --- /dev/null +++ b/reaper-control/templates/status.gohtml @@ -0,0 +1,16 @@ + + + + REAPER Status + + +

Reaper status: {{.ProcessState}}

+ {{ if .Recording }} +

Recording

+ Stop + {{ else }} +

Idle

+ Start + {{ end }} + + diff --git a/reaper-control/ui.go b/reaper-control/ui.go new file mode 100644 index 0000000..18d60a8 --- /dev/null +++ b/reaper-control/ui.go @@ -0,0 +1,44 @@ +package main + +import ( + "net/http" + "net/url" + + "github.com/gin-gonic/gin" +) + +func status(c *gin.Context) { + status := ReaperStatus{} + status.Recording = false + + if reaperProcess != nil && reaperProcess.ProcessState == nil { + status.ProcessState = "Running" + status.Recording = true + } else { + status.ProcessState = "Not Running" + } + + c.HTML(http.StatusOK, "status.gohtml", status) +} + +func startUI(c *gin.Context) { + err := startReaper() + if err != nil { + errString := url.QueryEscape(err.Error()) + c.Redirect(http.StatusFound, "/status?err="+errString) + return + } + + c.Redirect(http.StatusFound, "/status") +} + +func stopUI(c *gin.Context) { + err := stopReaper() + if err != nil { + errString := url.QueryEscape(err.Error()) + c.Redirect(http.StatusFound, "/status?err="+errString) + return + } + + c.Redirect(http.StatusFound, "/status") +} diff --git a/reaper-control/utils.go b/reaper-control/utils.go index 5d38729..d37afc1 100644 --- a/reaper-control/utils.go +++ b/reaper-control/utils.go @@ -31,8 +31,8 @@ func isReaperOn(timeout time.Duration) bool { func stopProcess(process *os.Process) error { if runtime.GOOS == "windows" { - process.Kill() - return nil + err := process.Kill() + return err } return process.Signal(syscall.SIGINT)