diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 8e981c19..50ba06a9 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -29,7 +29,7 @@ jobs: with: { name: go2rtc_win64, path: go2rtc.exe } - name: Build go2rtc_win32 - env: { GOOS: windows, GOARCH: 386 } + env: { GOOS: windows, GOARCH: 386, GOTOOLCHAIN: go1.20.14 } run: go build -ldflags "-s -w" -trimpath - name: Upload go2rtc_win32 uses: actions/upload-artifact@v4 @@ -85,7 +85,7 @@ jobs: with: { name: go2rtc_linux_mipsel, path: go2rtc } - name: Build go2rtc_mac_amd64 - env: { GOOS: darwin, GOARCH: amd64 } + env: { GOOS: darwin, GOARCH: amd64, GOTOOLCHAIN: go1.20.14 } run: go build -ldflags "-s -w" -trimpath - name: Upload go2rtc_mac_amd64 uses: actions/upload-artifact@v4 diff --git a/README.md b/README.md index c31ed748..70ad4712 100644 --- a/README.md +++ b/README.md @@ -115,8 +115,8 @@ Ultimate camera streaming application with support RTSP, WebRTC, HomeKit, FFmpeg Download binary for your OS from [latest release](https://github.com/AlexxIT/go2rtc/releases/): -- `go2rtc_win64.zip` - Windows 64-bit -- `go2rtc_win32.zip` - Windows 32-bit +- `go2rtc_win64.zip` - Windows 10+ 64-bit +- `go2rtc_win32.zip` - Windows 7+ 32-bit - `go2rtc_win_arm64.zip` - Windows ARM 64-bit - `go2rtc_linux_amd64` - Linux 64-bit - `go2rtc_linux_i386` - Linux 32-bit @@ -124,8 +124,8 @@ Download binary for your OS from [latest release](https://github.com/AlexxIT/go2 - `go2rtc_linux_arm` - Linux ARM 32-bit (ex. Raspberry 32-bit OS) - `go2rtc_linux_armv6` - Linux ARMv6 (for old Raspberry 1 and Zero) - `go2rtc_linux_mipsel` - Linux MIPS (ex. [Xiaomi Gateway 3](https://github.com/AlexxIT/XiaomiGateway3), [Wyze cameras](https://github.com/gtxaspec/wz_mini_hacks)) -- `go2rtc_mac_amd64.zip` - Mac Intel 64-bit -- `go2rtc_mac_arm64.zip` - Mac ARM 64-bit +- `go2rtc_mac_amd64.zip` - macOS 10.13+ Intel 64-bit +- `go2rtc_mac_arm64.zip` - macOS ARM 64-bit Don't forget to fix the rights `chmod +x go2rtc_xxx_xxx` on Linux and Mac. diff --git a/go.mod b/go.mod index d3cb791f..b038b110 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module github.com/AlexxIT/go2rtc -go 1.22 +go 1.20 require ( github.com/asticode/go-astits v1.13.0 diff --git a/internal/exec/exec.go b/internal/exec/exec.go index 035317d9..bce166e8 100644 --- a/internal/exec/exec.go +++ b/internal/exec/exec.go @@ -10,7 +10,6 @@ import ( "net/url" "os" "os/exec" - "slices" "strings" "sync" "time" @@ -230,7 +229,7 @@ func trimSpace(b []byte) []byte { func setRemoteInfo(info core.Info, source string, args []string) { info.SetSource(source) - if i := slices.Index(args, "-i"); i > 0 && i < len(args)-1 { + if i := core.Index(args, "-i"); i > 0 && i < len(args)-1 { rawURL := args[i+1] if u, err := url.Parse(rawURL); err == nil && u.Host != "" { info.SetRemoteAddr(u.Host) diff --git a/internal/ffmpeg/ffmpeg.go b/internal/ffmpeg/ffmpeg.go index 062e5aaf..12a9be83 100644 --- a/internal/ffmpeg/ffmpeg.go +++ b/internal/ffmpeg/ffmpeg.go @@ -2,7 +2,6 @@ package ffmpeg import ( "net/url" - "slices" "strings" "github.com/AlexxIT/go2rtc/internal/api" @@ -44,7 +43,7 @@ func Init() { return "", err } args := parseArgs(url[7:]) - if slices.Contains(args.Codecs, "auto") { + if core.Contains(args.Codecs, "auto") { return "", nil // force call streams.HandleFunc("ffmpeg") } return "exec:" + args.String(), nil diff --git a/internal/webrtc/candidates.go b/internal/webrtc/candidates.go index b92c4656..adbfb4a7 100644 --- a/internal/webrtc/candidates.go +++ b/internal/webrtc/candidates.go @@ -2,10 +2,10 @@ package webrtc import ( "net" - "slices" "strings" "github.com/AlexxIT/go2rtc/internal/api/ws" + "github.com/AlexxIT/go2rtc/pkg/core" "github.com/AlexxIT/go2rtc/pkg/webrtc" pion "github.com/pion/webrtc/v3" ) @@ -75,14 +75,14 @@ func FilterCandidate(candidate *pion.ICECandidate) bool { // host candidate should be in the hosts list if candidate.Typ == pion.ICECandidateTypeHost && filters.Candidates != nil { - if !slices.Contains(filters.Candidates, candidate.Address) { + if !core.Contains(filters.Candidates, candidate.Address) { return false } } if filters.Networks != nil { networkType := NetworkType(candidate.Protocol.String(), candidate.Address) - if !slices.Contains(filters.Networks, networkType) { + if !core.Contains(filters.Networks, networkType) { return false } } diff --git a/pkg/core/slices.go b/pkg/core/slices.go new file mode 100644 index 00000000..747d813f --- /dev/null +++ b/pkg/core/slices.go @@ -0,0 +1,43 @@ +package core + +// This code copied from go1.21 for backward support in go1.20. +// We need to support go1.20 for Windows 7 + +// Index returns the index of the first occurrence of v in s, +// or -1 if not present. +func Index[S ~[]E, E comparable](s S, v E) int { + for i := range s { + if v == s[i] { + return i + } + } + return -1 +} + +// Contains reports whether v is present in s. +func Contains[S ~[]E, E comparable](s S, v E) bool { + return Index(s, v) >= 0 +} + +type Ordered interface { + ~int | ~int8 | ~int16 | ~int32 | ~int64 | + ~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64 | ~uintptr | + ~float32 | ~float64 | + ~string +} + +// Max returns the maximal value in x. It panics if x is empty. +// For floating-point E, Max propagates NaNs (any NaN value in x +// forces the output to be NaN). +func Max[S ~[]E, E Ordered](x S) E { + if len(x) < 1 { + panic("slices.Max: empty list") + } + m := x[0] + for i := 1; i < len(x); i++ { + if x[i] > m { + m = x[i] + } + } + return m +} diff --git a/pkg/homekit/consumer.go b/pkg/homekit/consumer.go index 1c665233..ea83146f 100644 --- a/pkg/homekit/consumer.go +++ b/pkg/homekit/consumer.go @@ -3,7 +3,7 @@ package homekit import ( "fmt" "io" - "math/rand/v2" + "math/rand" "net" "time" diff --git a/pkg/homekit/helpers.go b/pkg/homekit/helpers.go index 89c63dc3..a1719671 100644 --- a/pkg/homekit/helpers.go +++ b/pkg/homekit/helpers.go @@ -2,7 +2,6 @@ package homekit import ( "encoding/hex" - "slices" "github.com/AlexxIT/go2rtc/pkg/aac" "github.com/AlexxIT/go2rtc/pkg/core" @@ -22,8 +21,8 @@ func videoToMedia(codecs []camera.VideoCodec) *core.Media { for _, codec := range codecs { for _, param := range codec.CodecParams { // get best profile and level - profileID := slices.Max(param.ProfileID) - level := slices.Max(param.Level) + profileID := core.Max(param.ProfileID) + level := core.Max(param.Level) profile := videoProfiles[profileID] + videoLevels[level] mediaCodec := &core.Codec{ Name: videoCodecs[codec.CodecType], diff --git a/pkg/webrtc/api.go b/pkg/webrtc/api.go index f63cabfd..0361e6b4 100644 --- a/pkg/webrtc/api.go +++ b/pkg/webrtc/api.go @@ -2,8 +2,8 @@ package webrtc import ( "net" - "slices" + "github.com/AlexxIT/go2rtc/pkg/core" "github.com/pion/interceptor" "github.com/pion/webrtc/v3" ) @@ -47,7 +47,7 @@ func NewServerAPI(network, address string, filters *Filters) (*webrtc.API, error if filters != nil && filters.Interfaces != nil { s.SetIncludeLoopbackCandidate(true) s.SetInterfaceFilter(func(name string) bool { - return slices.Contains(filters.Interfaces, name) + return core.Contains(filters.Interfaces, name) }) } else { // disable listen on Hassio docker interfaces @@ -59,7 +59,7 @@ func NewServerAPI(network, address string, filters *Filters) (*webrtc.API, error if filters != nil && filters.IPs != nil { s.SetIncludeLoopbackCandidate(true) s.SetIPFilter(func(ip net.IP) bool { - return slices.Contains(filters.IPs, ip.String()) + return core.Contains(filters.IPs, ip.String()) }) } diff --git a/scripts/README.md b/scripts/README.md index efcef154..eeb8c25d 100644 --- a/scripts/README.md +++ b/scripts/README.md @@ -1,3 +1,11 @@ +## Versions + +[Go 1.20](https://go.dev/doc/go1.20) is last version with support Windows 7 and macOS 10.13. +Go 1.21 support only Windows 10 and macOS 10.15. + +So we will set `go 1.20` (minimum version) inside `go.mod` file. And will use env `GOTOOLCHAIN=go1.20.14` for building +`win32` and `mac_amd64` binaries. All other binaries will use latest go version. + ## Build - UPX-3.96 pack broken bin for `linux_mipsel` diff --git a/scripts/build.cmd b/scripts/build.cmd index 54565b2d..4a54039d 100644 --- a/scripts/build.cmd +++ b/scripts/build.cmd @@ -1,15 +1,18 @@ @ECHO OFF +@SET GOTOOLCHAIN= @SET GOOS=windows @SET GOARCH=amd64 @SET FILENAME=go2rtc_win64.zip go build -ldflags "-s -w" -trimpath && 7z a -mx9 -sdel %FILENAME% go2rtc.exe +@SET GOTOOLCHAIN=go1.20.14 @SET GOOS=windows @SET GOARCH=386 @SET FILENAME=go2rtc_win32.zip go build -ldflags "-s -w" -trimpath && 7z a -mx9 -sdel %FILENAME% go2rtc.exe +@SET GOTOOLCHAIN= @SET GOOS=windows @SET GOARCH=arm64 @SET FILENAME=go2rtc_win_arm64.zip @@ -47,11 +50,13 @@ go build -ldflags "-s -w" -trimpath -o %FILENAME% && upx %FILENAME% @SET FILENAME=go2rtc_linux_mipsel go build -ldflags "-s -w" -trimpath -o %FILENAME% && upx %FILENAME% +@SET GOTOOLCHAIN=go1.20.14 @SET GOOS=darwin @SET GOARCH=amd64 @SET FILENAME=go2rtc_mac_amd64.zip go build -ldflags "-s -w" -trimpath && 7z a -mx9 -sdel %FILENAME% go2rtc +@SET GOTOOLCHAIN= @SET GOOS=darwin @SET GOARCH=arm64 @SET FILENAME=go2rtc_mac_arm64.zip