Use standard port for ssdp discovery. Also try to fix CLI issue on windows

This commit is contained in:
Alex Ballas
2024-12-22 02:22:53 +02:00
parent 95006960a7
commit a4cd63f512
15 changed files with 160 additions and 67 deletions

View File

@@ -1,11 +1,10 @@
LDFLAGS="-s -w" LDFLAGS="-s -w"
WINLDFLAGS="-H=windowsgui -s -w"
build: clean build: clean
go build -trimpath -ldflags $(LDFLAGS) -o build/go2tv cmd/go2tv/go2tv.go go build -trimpath -ldflags $(LDFLAGS) -o build/go2tv cmd/go2tv/go2tv.go
windows: clean windows: clean
env CGO_ENABLED=1 CC=x86_64-w64-mingw32-gcc CXX=x86_64-w64-mingw32-g++ GOOS=windows GOARCH=amd64 go build -trimpath -ldflags $(WINLDFLAGS) -o build/go2tv.exe cmd/go2tv/go2tv.go env CGO_ENABLED=1 CC=x86_64-w64-mingw32-gcc CXX=x86_64-w64-mingw32-g++ GOOS=windows GOARCH=amd64 go build -trimpath -ldflags $(LDFLAGS) -o build/go2tv.exe cmd/go2tv/go2tv.go
install: build install: build
mkdir -vp /usr/local/bin/ mkdir -vp /usr/local/bin/

View File

@@ -106,7 +106,7 @@ func run() error {
} }
if flagRes.gui { if flagRes.gui {
scr := gui.InitFyneNewScreen(version) scr := gui.NewFyneScreen(version)
gui.Start(exitCTX, scr) gui.Start(exitCTX, scr)
return nil return nil
} }

View File

@@ -21,7 +21,7 @@ var (
func LoadSSDPservices(delay int) (map[string]string, error) { func LoadSSDPservices(delay int) (map[string]string, error) {
// Reset device list every time we call this. // Reset device list every time we call this.
urlList := make(map[string]string) urlList := make(map[string]string)
list, err := ssdp.Search(ssdp.All, delay, "") list, err := ssdp.Search(ssdp.All, delay, "239.255.255.250:1900")
if err != nil { if err != nil {
return nil, fmt.Errorf("LoadSSDPservices search error: %w", err) return nil, fmt.Errorf("LoadSSDPservices search error: %w", err)
} }

12
go.mod
View File

@@ -3,7 +3,7 @@ module github.com/alexballas/go2tv
go 1.23.3 go 1.23.3
require ( require (
fyne.io/fyne/v2 v2.5.2 fyne.io/fyne/v2 v2.5.3
github.com/alexballas/go-ssdp v0.0.3 github.com/alexballas/go-ssdp v0.0.3
github.com/gdamore/tcell/v2 v2.7.4 github.com/gdamore/tcell/v2 v2.7.4
github.com/h2non/filetype v1.1.3 github.com/h2non/filetype v1.1.3
@@ -14,6 +14,7 @@ require (
github.com/rs/zerolog v1.33.0 github.com/rs/zerolog v1.33.0
github.com/saintfish/chardet v0.0.0-20230101081208-5e3ef4b5456d github.com/saintfish/chardet v0.0.0-20230101081208-5e3ef4b5456d
github.com/skratchdot/open-golang v0.0.0-20200116055534-eef842397966 github.com/skratchdot/open-golang v0.0.0-20200116055534-eef842397966
golang.org/x/sys v0.28.0
golang.org/x/time v0.8.0 golang.org/x/time v0.8.0
) )
@@ -30,11 +31,11 @@ require (
github.com/go-gl/gl v0.0.0-20231021071112-07e5d0ea2e71 // indirect github.com/go-gl/gl v0.0.0-20231021071112-07e5d0ea2e71 // indirect
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20240506104042-037f3cc74f2a // indirect github.com/go-gl/glfw/v3.3/glfw v0.0.0-20240506104042-037f3cc74f2a // indirect
github.com/go-text/render v0.2.0 // indirect github.com/go-text/render v0.2.0 // indirect
github.com/go-text/typesetting v0.2.0 // indirect github.com/go-text/typesetting v0.2.1 // indirect
github.com/godbus/dbus/v5 v5.1.0 // indirect github.com/godbus/dbus/v5 v5.1.0 // indirect
github.com/gopherjs/gopherjs v1.17.2 // indirect github.com/gopherjs/gopherjs v1.17.2 // indirect
github.com/hashicorp/go-cleanhttp v0.5.2 // indirect github.com/hashicorp/go-cleanhttp v0.5.2 // indirect
github.com/jeandeaual/go-locale v0.0.0-20241204123234-32dda1c00a20 // indirect github.com/jeandeaual/go-locale v0.0.0-20241217141322-fcc2cadd6f08 // indirect
github.com/jsummers/gobmp v0.0.0-20230614200233-a9de23ed2e25 // indirect github.com/jsummers/gobmp v0.0.0-20230614200233-a9de23ed2e25 // indirect
github.com/lucasb-eyer/go-colorful v1.2.0 // indirect github.com/lucasb-eyer/go-colorful v1.2.0 // indirect
github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-colorable v0.1.13 // indirect
@@ -48,9 +49,8 @@ require (
github.com/stretchr/testify v1.10.0 // indirect github.com/stretchr/testify v1.10.0 // indirect
github.com/yuin/goldmark v1.7.8 // indirect github.com/yuin/goldmark v1.7.8 // indirect
golang.org/x/image v0.23.0 // indirect golang.org/x/image v0.23.0 // indirect
golang.org/x/mobile v0.0.0-20241204233305-ce44b2716d33 // indirect golang.org/x/mobile v0.0.0-20241213221354-a87c1cf6cf46 // indirect
golang.org/x/net v0.32.0 // indirect golang.org/x/net v0.33.0 // indirect
golang.org/x/sys v0.28.0 // indirect
golang.org/x/term v0.27.0 // indirect golang.org/x/term v0.27.0 // indirect
golang.org/x/text v0.21.0 // indirect golang.org/x/text v0.21.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect

24
go.sum
View File

@@ -37,8 +37,8 @@ cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohl
cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs= cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs=
cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0=
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
fyne.io/fyne/v2 v2.5.2 h1:eSyGTmSkv10yAdAeHpDet6u2KkKxOGFc14kQu81We7Q= fyne.io/fyne/v2 v2.5.3 h1:k6LjZx6EzRZhClsuzy6vucLZBstdH2USDGHSGWq8ly8=
fyne.io/fyne/v2 v2.5.2/go.mod h1:26gqPDvtaxHeyct+C0BBjuGd2zwAJlPkUGSBrb+d7Ug= fyne.io/fyne/v2 v2.5.3/go.mod h1:0GOXKqyvNwk3DLmsFu9v0oYM0ZcD1ysGnlHCerKoAmo=
fyne.io/systray v1.11.0 h1:D9HISlxSkx+jHSniMBR6fCFOUjk1x/OOOJLa9lJYAKg= fyne.io/systray v1.11.0 h1:D9HISlxSkx+jHSniMBR6fCFOUjk1x/OOOJLa9lJYAKg=
fyne.io/systray v1.11.0/go.mod h1:RVwqP9nYMo7h5zViCBHri2FgjXF7H2cub7MAq4NSoLs= fyne.io/systray v1.11.0/go.mod h1:RVwqP9nYMo7h5zViCBHri2FgjXF7H2cub7MAq4NSoLs=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
@@ -107,10 +107,10 @@ github.com/go-gl/glfw/v3.3/glfw v0.0.0-20240506104042-037f3cc74f2a h1:vxnBhFDDT+
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20240506104042-037f3cc74f2a/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20240506104042-037f3cc74f2a/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
github.com/go-text/render v0.2.0 h1:LBYoTmp5jYiJ4NPqDc2pz17MLmA3wHw1dZSVGcOdeAc= github.com/go-text/render v0.2.0 h1:LBYoTmp5jYiJ4NPqDc2pz17MLmA3wHw1dZSVGcOdeAc=
github.com/go-text/render v0.2.0/go.mod h1:CkiqfukRGKJA5vZZISkjSYrcdtgKQWRa2HIzvwNN5SU= github.com/go-text/render v0.2.0/go.mod h1:CkiqfukRGKJA5vZZISkjSYrcdtgKQWRa2HIzvwNN5SU=
github.com/go-text/typesetting v0.2.0 h1:fbzsgbmk04KiWtE+c3ZD4W2nmCRzBqrqQOvYlwAOdho= github.com/go-text/typesetting v0.2.1 h1:x0jMOGyO3d1qFAPI0j4GSsh7M0Q3Ypjzr4+CEVg82V8=
github.com/go-text/typesetting v0.2.0/go.mod h1:2+owI/sxa73XA581LAzVuEBZ3WEEV2pXeDswCH/3i1I= github.com/go-text/typesetting v0.2.1/go.mod h1:mTOxEwasOFpAMBjEQDhdWRckoLLeI/+qrQeBCTGEt6M=
github.com/go-text/typesetting-utils v0.0.0-20240317173224-1986cbe96c66 h1:GUrm65PQPlhFSKjLPGOZNPNxLCybjzjYBzjfoBGaDUY= github.com/go-text/typesetting-utils v0.0.0-20241103174707-87a29e9e6066 h1:qCuYC+94v2xrb1PoS4NIDe7DGYtLnU2wWiQe9a1B1c0=
github.com/go-text/typesetting-utils v0.0.0-20240317173224-1986cbe96c66/go.mod h1:DDxDdQEnB70R8owOx3LVpEFvpMK9eeH1o2r0yZhFI9o= github.com/go-text/typesetting-utils v0.0.0-20241103174707-87a29e9e6066/go.mod h1:DDxDdQEnB70R8owOx3LVpEFvpMK9eeH1o2r0yZhFI9o=
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
github.com/godbus/dbus/v5 v5.1.0 h1:4KLkAxT3aOY8Li4FRJe/KvhoNFFxo0m6fNuFUO8QJUk= github.com/godbus/dbus/v5 v5.1.0 h1:4KLkAxT3aOY8Li4FRJe/KvhoNFFxo0m6fNuFUO8QJUk=
github.com/godbus/dbus/v5 v5.1.0/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/godbus/dbus/v5 v5.1.0/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
@@ -216,8 +216,8 @@ github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/J
github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
github.com/jeandeaual/go-locale v0.0.0-20241204123234-32dda1c00a20 h1:S6sn9jRW3oq1k/Qiwa20F+E57ZVJ2+KB1Vp5xiJ1FlI= github.com/jeandeaual/go-locale v0.0.0-20241217141322-fcc2cadd6f08 h1:wMeVzrPO3mfHIWLZtDcSaGAe2I4PW9B/P5nMkRSwCAc=
github.com/jeandeaual/go-locale v0.0.0-20241204123234-32dda1c00a20/go.mod h1:pYcXQtDPRThfL37oZEzUVo2Jb8ua0NEC7rZqrxXyuhA= github.com/jeandeaual/go-locale v0.0.0-20241217141322-fcc2cadd6f08/go.mod h1:ZDXo8KHryOWSIqnsb/CiDq7hQUYryCgdVnxbj8tDG7o=
github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk=
@@ -382,8 +382,8 @@ golang.org/x/lint v0.0.0-20210508222113-6edffad5e616/go.mod h1:3xt1FjdF8hUf6vQPI
golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE=
golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o=
golang.org/x/mobile v0.0.0-20211207041440-4e6c2922fdee/go.mod h1:pe2sM7Uk+2Su1y7u/6Z8KJ24D7lepUjFZbhFOrmDfuQ= golang.org/x/mobile v0.0.0-20211207041440-4e6c2922fdee/go.mod h1:pe2sM7Uk+2Su1y7u/6Z8KJ24D7lepUjFZbhFOrmDfuQ=
golang.org/x/mobile v0.0.0-20241204233305-ce44b2716d33 h1:MeYjBsMjR6w9aXA3oHEJWCQ5bnD5fOjesYMOn52ovQY= golang.org/x/mobile v0.0.0-20241213221354-a87c1cf6cf46 h1:E+R1qmJL8cmWTyWXBHVtmqRxr7FdiTwntffsba1F1Tg=
golang.org/x/mobile v0.0.0-20241204233305-ce44b2716d33/go.mod h1:Sf9LBimL0mWKEdgAjRmJ6iu7Z34osHQTK/devqFbM2I= golang.org/x/mobile v0.0.0-20241213221354-a87c1cf6cf46/go.mod h1:Sf9LBimL0mWKEdgAjRmJ6iu7Z34osHQTK/devqFbM2I=
golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc=
golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY=
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
@@ -434,8 +434,8 @@ golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96b
golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
golang.org/x/net v0.32.0 h1:ZqPmj8Kzc+Y6e0+skZsuACbx+wzMgo5MQsJh9Qd6aYI= golang.org/x/net v0.33.0 h1:74SYHlV8BIgHIFC/LrYkOGIwL19eTYXQ5wc6TBuO36I=
golang.org/x/net v0.32.0/go.mod h1:CwU0IoeOlnQQWJ6ioyFrfRuomB8GKF6KbYXZVyeXNfs= golang.org/x/net v0.33.0/go.mod h1:HXLR5J+9DxmrqMwG9qjGCxZ+zKXxBru04zlTvWlWuN4=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=

View File

@@ -20,7 +20,7 @@ import (
"fyne.io/fyne/v2/widget" "fyne.io/fyne/v2/widget"
) )
func aboutWindow(s *NewScreen) fyne.CanvasObject { func aboutWindow(s *FyneScreen) fyne.CanvasObject {
sr := fyne.NewStaticResource("Go2TV Icon", go2TVSmallIcon) sr := fyne.NewStaticResource("Go2TV Icon", go2TVSmallIcon)
go2tvImage := canvas.NewImageFromResource(sr) go2tvImage := canvas.NewImageFromResource(sr)
richhead := widget.NewRichTextFromMarkdown(` richhead := widget.NewRichTextFromMarkdown(`
@@ -70,7 +70,7 @@ MIT
return container.NewPadded(cont) return container.NewPadded(cont)
} }
func checkVersion(s *NewScreen) { func checkVersion(s *FyneScreen) {
s.CheckVersion.Disable() s.CheckVersion.Disable()
defer s.CheckVersion.Enable() defer s.CheckVersion.Enable()
errRedirectChecker := errors.New("redirect") errRedirectChecker := errors.New("redirect")

View File

@@ -30,7 +30,7 @@ import (
"github.com/skratchdot/open-golang/open" "github.com/skratchdot/open-golang/open"
) )
func muteAction(screen *NewScreen) { func muteAction(screen *FyneScreen) {
if screen.renderingControlURL == "" { if screen.renderingControlURL == "" {
check(screen, errors.New(lang.L("please select a device"))) check(screen, errors.New(lang.L("please select a device")))
return return
@@ -56,7 +56,7 @@ func muteAction(screen *NewScreen) {
setMuteUnmuteView("Unmute", screen) setMuteUnmuteView("Unmute", screen)
} }
func unmuteAction(screen *NewScreen) { func unmuteAction(screen *FyneScreen) {
if screen.renderingControlURL == "" { if screen.renderingControlURL == "" {
check(screen, errors.New(lang.L("please select a device"))) check(screen, errors.New(lang.L("please select a device")))
return return
@@ -78,7 +78,7 @@ func unmuteAction(screen *NewScreen) {
setMuteUnmuteView("Mute", screen) setMuteUnmuteView("Mute", screen)
} }
func selectMediaFile(screen *NewScreen, f fyne.URI) { func selectMediaFile(screen *FyneScreen, f fyne.URI) {
mfile := f.Path() mfile := f.Path()
absMediaFile, err := filepath.Abs(mfile) absMediaFile, err := filepath.Abs(mfile)
check(screen, err) check(screen, err)
@@ -116,7 +116,7 @@ func selectMediaFile(screen *NewScreen, f fyne.URI) {
screen.SelectInternalSubs.Enable() screen.SelectInternalSubs.Enable()
} }
func selectSubsFile(screen *NewScreen, f fyne.URI) { func selectSubsFile(screen *FyneScreen, f fyne.URI) {
sfile := f.Path() sfile := f.Path()
absSubtitlesFile, err := filepath.Abs(sfile) absSubtitlesFile, err := filepath.Abs(sfile)
check(screen, err) check(screen, err)
@@ -131,7 +131,7 @@ func selectSubsFile(screen *NewScreen, f fyne.URI) {
screen.SubsText.Refresh() screen.SubsText.Refresh()
} }
func mediaAction(screen *NewScreen) { func mediaAction(screen *FyneScreen) {
w := screen.Current w := screen.Current
fd := dialog.NewFileOpen(func(reader fyne.URIReadCloser, err error) { fd := dialog.NewFileOpen(func(reader fyne.URIReadCloser, err error) {
check(screen, err) check(screen, err)
@@ -157,7 +157,7 @@ func mediaAction(screen *NewScreen) {
fd.Show() fd.Show()
} }
func subsAction(screen *NewScreen) { func subsAction(screen *FyneScreen) {
w := screen.Current w := screen.Current
fd := dialog.NewFileOpen(func(reader fyne.URIReadCloser, err error) { fd := dialog.NewFileOpen(func(reader fyne.URIReadCloser, err error) {
check(screen, err) check(screen, err)
@@ -185,7 +185,7 @@ func subsAction(screen *NewScreen) {
fd.Show() fd.Show()
} }
func playAction(screen *NewScreen) { func playAction(screen *FyneScreen) {
var mediaFile interface{} var mediaFile interface{}
screen.PlayPause.Disable() screen.PlayPause.Disable()
@@ -422,7 +422,7 @@ func playAction(screen *NewScreen) {
} }
func startAfreshPlayButton(screen *NewScreen) { func startAfreshPlayButton(screen *FyneScreen) {
if screen.cancelEnablePlay != nil { if screen.cancelEnablePlay != nil {
screen.cancelEnablePlay() screen.cancelEnablePlay()
} }
@@ -431,7 +431,7 @@ func startAfreshPlayButton(screen *NewScreen) {
screen.updateScreenState("Stopped") screen.updateScreenState("Stopped")
} }
func gaplessMediaWatcher(ctx context.Context, screen *NewScreen, payload *soapcalls.TVPayload) { func gaplessMediaWatcher(ctx context.Context, screen *FyneScreen, payload *soapcalls.TVPayload) {
t := time.NewTicker(1 * time.Second) t := time.NewTicker(1 * time.Second)
out: out:
for { for {
@@ -489,12 +489,12 @@ out:
} }
} }
func pauseAction(screen *NewScreen) { func pauseAction(screen *FyneScreen) {
err := screen.tvdata.SendtoTV("Pause") err := screen.tvdata.SendtoTV("Pause")
check(screen, err) check(screen, err)
} }
func clearmediaAction(screen *NewScreen) { func clearmediaAction(screen *FyneScreen) {
screen.MediaText.Text = "" screen.MediaText.Text = ""
screen.mediafile = "" screen.mediafile = ""
screen.MediaText.Refresh() screen.MediaText.Refresh()
@@ -504,14 +504,14 @@ func clearmediaAction(screen *NewScreen) {
screen.SelectInternalSubs.Disable() screen.SelectInternalSubs.Disable()
} }
func clearsubsAction(screen *NewScreen) { func clearsubsAction(screen *FyneScreen) {
screen.SelectInternalSubs.ClearSelected() screen.SelectInternalSubs.ClearSelected()
screen.SubsText.Text = "" screen.SubsText.Text = ""
screen.subsfile = "" screen.subsfile = ""
screen.SubsText.Refresh() screen.SubsText.Refresh()
} }
func skipNextAction(screen *NewScreen) { func skipNextAction(screen *FyneScreen) {
if screen.controlURL == "" { if screen.controlURL == "" {
check(screen, errors.New(lang.L("please select a device"))) check(screen, errors.New(lang.L("please select a device")))
return return
@@ -536,7 +536,7 @@ func skipNextAction(screen *NewScreen) {
playAction(screen) playAction(screen)
} }
func previewmedia(screen *NewScreen) { func previewmedia(screen *FyneScreen) {
if screen.mediafile == "" { if screen.mediafile == "" {
check(screen, errors.New(lang.L("please select a media file"))) check(screen, errors.New(lang.L("please select a media file")))
return return
@@ -571,7 +571,7 @@ func previewmedia(screen *NewScreen) {
} }
} }
func stopAction(screen *NewScreen) { func stopAction(screen *FyneScreen) {
screen.PlayPause.Enable() screen.PlayPause.Enable()
if screen.tvdata == nil || screen.tvdata.ControlURL == "" { if screen.tvdata == nil || screen.tvdata.ControlURL == "" {
@@ -610,7 +610,7 @@ func getDevices(delay int) ([]devType, error) {
return guiDeviceList, nil return guiDeviceList, nil
} }
func volumeAction(screen *NewScreen, up bool) { func volumeAction(screen *FyneScreen, up bool) {
if screen.renderingControlURL == "" { if screen.renderingControlURL == "" {
check(screen, errors.New(lang.L("please select a device"))) check(screen, errors.New(lang.L("please select a device")))
return return
@@ -646,7 +646,7 @@ func volumeAction(screen *NewScreen, up bool) {
} }
} }
func queueNext(screen *NewScreen, clear bool) (*soapcalls.TVPayload, error) { func queueNext(screen *FyneScreen, clear bool) (*soapcalls.TVPayload, error) {
if screen.tvdata == nil { if screen.tvdata == nil {
return nil, errors.New("queueNext, nil tvdata") return nil, errors.New("queueNext, nil tvdata")
} }

View File

@@ -27,8 +27,8 @@ import (
"github.com/alexballas/go2tv/soapcalls/utils" "github.com/alexballas/go2tv/soapcalls/utils"
) )
// NewScreen . // FyneScreen .
type NewScreen struct { type FyneScreen struct {
tempFiles []string tempFiles []string
SelectInternalSubs *widget.Select SelectInternalSubs *widget.Select
CurrentPos binding.String CurrentPos binding.String
@@ -51,7 +51,7 @@ type NewScreen struct {
httpserver *httphandlers.HTTPserver httpserver *httphandlers.HTTPserver
MediaText *widget.Entry MediaText *widget.Entry
ExternalMediaURL *widget.Check ExternalMediaURL *widget.Check
GaplessMediaWatcher func(context.Context, *NewScreen, *soapcalls.TVPayload) GaplessMediaWatcher func(context.Context, *FyneScreen, *soapcalls.TVPayload)
SlideBar *tappedSlider SlideBar *tappedSlider
MuteUnmute *widget.Button MuteUnmute *widget.Button
VolumeDown *widget.Button VolumeDown *widget.Button
@@ -102,7 +102,7 @@ func (f *debugWriter) Write(b []byte) (int, error) {
var translations embed.FS var translations embed.FS
// Start . // Start .
func Start(ctx context.Context, s *NewScreen) { func Start(ctx context.Context, s *FyneScreen) {
if s == nil { if s == nil {
return return
} }
@@ -174,7 +174,7 @@ func Start(ctx context.Context, s *NewScreen) {
} }
func onDropFiles(screen *NewScreen) func(p fyne.Position, u []fyne.URI) { func onDropFiles(screen *FyneScreen) func(p fyne.Position, u []fyne.URI) {
return func(p fyne.Position, u []fyne.URI) { return func(p fyne.Position, u []fyne.URI) {
var mfiles, sfiles []fyne.URI var mfiles, sfiles []fyne.URI
@@ -205,7 +205,7 @@ func onDropFiles(screen *NewScreen) func(p fyne.Position, u []fyne.URI) {
} }
// EmitMsg Method to implement the screen interface // EmitMsg Method to implement the screen interface
func (p *NewScreen) EmitMsg(a string) { func (p *FyneScreen) EmitMsg(a string) {
switch a { switch a {
case "Playing": case "Playing":
setPlayPauseView("Pause", p) setPlayPauseView("Pause", p)
@@ -225,7 +225,7 @@ func (p *NewScreen) EmitMsg(a string) {
// Fini Method to implement the screen interface. // Fini Method to implement the screen interface.
// Will only be executed when we receive a callback message, // Will only be executed when we receive a callback message,
// not when we explicitly click the Stop button. // not when we explicitly click the Stop button.
func (p *NewScreen) Fini() { func (p *FyneScreen) Fini() {
gaplessOption := fyne.CurrentApp().Preferences().StringWithFallback("Gapless", "Disabled") gaplessOption := fyne.CurrentApp().Preferences().StringWithFallback("Gapless", "Disabled")
if p.NextMediaCheck.Checked && gaplessOption == "Disabled" { if p.NextMediaCheck.Checked && gaplessOption == "Disabled" {
@@ -244,8 +244,7 @@ func (p *NewScreen) Fini() {
} }
} }
// InitFyneNewScreen . func InitFyneNewScreen(version string) *FyneScreen {
func InitFyneNewScreen(version string) *NewScreen {
go2tv := app.NewWithID("app.go2tv.go2tv") go2tv := app.NewWithID("app.go2tv.go2tv")
switch go2tv.Preferences().String("Language") { switch go2tv.Preferences().String("Language") {
@@ -268,7 +267,7 @@ func InitFyneNewScreen(version string) *NewScreen {
ring: ring.New(1000), ring: ring.New(1000),
} }
return &NewScreen{ return &FyneScreen{
Current: w, Current: w,
currentmfolder: currentDir, currentmfolder: currentDir,
mediaFormats: []string{".mp4", ".avi", ".mkv", ".mpeg", ".mov", ".webm", ".m4v", ".mpv", ".dv", ".mp3", ".flac", ".wav", ".m4a", ".jpg", ".jpeg", ".png"}, mediaFormats: []string{".mp4", ".avi", ".mkv", ".mpeg", ".mov", ".webm", ".m4v", ".mpv", ".dv", ".mp3", ".flac", ".wav", ".m4a", ".jpg", ".jpeg", ".png"},
@@ -277,7 +276,7 @@ func InitFyneNewScreen(version string) *NewScreen {
} }
} }
func check(s *NewScreen, err error) { func check(s *FyneScreen, err error) {
s.muError.Lock() s.muError.Lock()
defer s.muError.Unlock() defer s.muError.Unlock()
@@ -292,7 +291,7 @@ func check(s *NewScreen, err error) {
} }
} }
func getNextMedia(screen *NewScreen) (string, string) { func getNextMedia(screen *FyneScreen) (string, string) {
filedir := filepath.Dir(screen.mediafile) filedir := filepath.Dir(screen.mediafile)
filelist, err := os.ReadDir(filedir) filelist, err := os.ReadDir(filedir)
check(screen, err) check(screen, err)
@@ -358,7 +357,7 @@ func getNextMedia(screen *NewScreen) (string, string) {
return resName, resPath return resName, resPath
} }
func autoSelectNextSubs(v string, screen *NewScreen) { func autoSelectNextSubs(v string, screen *FyneScreen) {
name, path := getNextPossibleSubs(v) name, path := getNextPossibleSubs(v)
screen.SubsText.Text = name screen.SubsText.Text = name
screen.subsfile = path screen.subsfile = path
@@ -379,7 +378,7 @@ func getNextPossibleSubs(v string) (string, string) {
return name, path return name, path
} }
func setPlayPauseView(s string, screen *NewScreen) { func setPlayPauseView(s string, screen *FyneScreen) {
if screen.cancelEnablePlay != nil { if screen.cancelEnablePlay != nil {
screen.cancelEnablePlay() screen.cancelEnablePlay()
} }
@@ -397,7 +396,7 @@ func setPlayPauseView(s string, screen *NewScreen) {
} }
} }
func setMuteUnmuteView(s string, screen *NewScreen) { func setMuteUnmuteView(s string, screen *FyneScreen) {
switch s { switch s {
case "Mute": case "Mute":
screen.MuteUnmute.Icon = theme.VolumeUpIcon() screen.MuteUnmute.Icon = theme.VolumeUpIcon()
@@ -411,14 +410,14 @@ func setMuteUnmuteView(s string, screen *NewScreen) {
// updateScreenState updates the screen state based on // updateScreenState updates the screen state based on
// the emitted messages. The State variable is used across // the emitted messages. The State variable is used across
// the GUI interface to control certain flows. // the GUI interface to control certain flows.
func (p *NewScreen) updateScreenState(a string) { func (p *FyneScreen) updateScreenState(a string) {
p.mu.Lock() p.mu.Lock()
p.State = a p.State = a
p.mu.Unlock() p.mu.Unlock()
} }
// getScreenState returns the current screen state // getScreenState returns the current screen state
func (p *NewScreen) getScreenState() string { func (p *FyneScreen) getScreenState() string {
p.mu.RLock() p.mu.RLock()
defer p.mu.RUnlock() defer p.mu.RUnlock()
return p.State return p.State

View File

@@ -28,7 +28,7 @@ import (
type tappedSlider struct { type tappedSlider struct {
*widget.Slider *widget.Slider
screen *NewScreen screen *FyneScreen
end string end string
mu sync.Mutex mu sync.Mutex
} }
@@ -59,7 +59,7 @@ func newDeviceList(dd *[]devType) *deviceList {
return list return list
} }
func newTappableSlider(s *NewScreen) *tappedSlider { func newTappableSlider(s *FyneScreen) *tappedSlider {
slider := &tappedSlider{ slider := &tappedSlider{
Slider: &widget.Slider{ Slider: &widget.Slider{
Max: 100, Max: 100,
@@ -207,7 +207,7 @@ func (t *tappedSlider) Tapped(p *fyne.PointEvent) {
} }
} }
func mainWindow(s *NewScreen) fyne.CanvasObject { func mainWindow(s *FyneScreen) fyne.CanvasObject {
w := s.Current w := s.Current
var data []devType var data []devType
list := newDeviceList(&data) list := newDeviceList(&data)
@@ -561,7 +561,7 @@ func mainWindow(s *NewScreen) fyne.CanvasObject {
return content return content
} }
func refreshDevList(s *NewScreen, data *[]devType) { func refreshDevList(s *FyneScreen, data *[]devType) {
refreshDevices := time.NewTicker(5 * time.Second) refreshDevices := time.NewTicker(5 * time.Second)
_, err := getDevices(2) _, err := getDevices(2)
@@ -625,7 +625,7 @@ func refreshDevList(s *NewScreen, data *[]devType) {
} }
} }
func checkMutefunc(s *NewScreen) { func checkMutefunc(s *FyneScreen) {
checkMute := time.NewTicker(2 * time.Second) checkMute := time.NewTicker(2 * time.Second)
var checkMuteCounter int var checkMuteCounter int
@@ -662,7 +662,7 @@ func checkMutefunc(s *NewScreen) {
} }
} }
func sliderUpdate(s *NewScreen) { func sliderUpdate(s *FyneScreen) {
t := time.NewTicker(time.Second) t := time.NewTicker(time.Second)
for range t.C { for range t.C {
if s.sliderActive { if s.sliderActive {

9
internal/gui/newGUI.go Normal file
View File

@@ -0,0 +1,9 @@
//go:build !windows
// +build !windows
package gui
// NewFyneScreen .
func NewFyneScreen(version string) *FyneScreen {
return InitFyneNewScreen(version)
}

View File

@@ -0,0 +1,23 @@
package gui
import (
"golang.org/x/sys/windows"
)
// NewFyneScreen .
func NewFyneScreen(version string) *FyneScreen {
hideConsole()
return InitFyneNewScreen(version)
}
func hideConsole() {
kernel32 := windows.NewLazySystemDLL("kernel32.dll")
getConsoleWindow := kernel32.NewProc("GetConsoleWindow")
showWindow := windows.NewLazySystemDLL("user32.dll").NewProc("ShowWindow")
hwnd, _, _ := getConsoleWindow.Call()
if hwnd != 0 {
const SW_HIDE = 0
showWindow.Call(hwnd, SW_HIDE)
}
}

View File

@@ -16,7 +16,7 @@ import (
"fyne.io/fyne/v2/widget" "fyne.io/fyne/v2/widget"
) )
func settingsWindow(s *NewScreen) fyne.CanvasObject { func settingsWindow(s *FyneScreen) fyne.CanvasObject {
w := s.Current w := s.Current
themeText := widget.NewLabel(lang.L("Theme")) themeText := widget.NewLabel(lang.L("Theme"))
@@ -147,7 +147,7 @@ func settingsWindow(s *NewScreen) fyne.CanvasObject {
return container.New(layout.NewFormLayout(), themeText, dropdownTheme, languageText, dropdownLanguage, gaplessText, gaplessdropdown, ffmpegText, ffmpegTextEntry, debugText, debugExport) return container.New(layout.NewFormLayout(), themeText, dropdownTheme, languageText, dropdownLanguage, gaplessText, gaplessdropdown, ffmpegText, ffmpegTextEntry, debugText, debugExport)
} }
func saveDebugLogs(f fyne.URIWriteCloser, s *NewScreen) { func saveDebugLogs(f fyne.URIWriteCloser, s *FyneScreen) {
w := s.Current w := s.Current
defer f.Close() defer f.Close()
@@ -176,7 +176,7 @@ func parseTheme(t string) {
}() }()
} }
func parseLanguage(s *NewScreen) func(string) { func parseLanguage(s *FyneScreen) func(string) {
w := s.Current w := s.Current
return func(t string) { return func(t string) {
if t != fyne.CurrentApp().Preferences().StringWithFallback("Language", "System Default") { if t != fyne.CurrentApp().Preferences().StringWithFallback("Language", "System Default") {

View File

@@ -0,0 +1,55 @@
package utils
import (
"testing"
"time"
)
// TestFormatDuration - test formatDuration
func TestFormatDuration(t *testing.T) {
tests := []struct {
name string
input time.Duration
expected string
}{
{
name: "Zero duration",
input: 0,
expected: "00:00:00.000",
},
{
name: "Milliseconds only",
input: 123 * time.Millisecond,
expected: "00:00:00.123",
},
{
name: "Seconds and milliseconds",
input: 12*time.Second + 345*time.Millisecond,
expected: "00:00:12.345",
},
{
name: "Minutes, seconds, and milliseconds",
input: 5*time.Minute + 23*time.Second + 789*time.Millisecond,
expected: "00:05:23.789",
},
{
name: "Hours, minutes, seconds, and milliseconds",
input: 2*time.Hour + 15*time.Minute + 9*time.Second + 56*time.Millisecond,
expected: "02:15:09.056",
},
{
name: "More than a day",
input: 26*time.Hour + 45*time.Minute + 33*time.Second + 1*time.Millisecond,
expected: "26:45:33.001",
},
}
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
result := formatDuration(test.input)
if result != test.expected {
t.Fatalf("for input %v, expected %q but got %q", test.input, test.expected, result)
}
})
}
}

View File

@@ -29,8 +29,10 @@ type tags struct {
Language string `mapstructure:"language"` Language string `mapstructure:"language"`
} }
// ErrNoSubs - No subs detected
var ErrNoSubs = errors.New("no subs") var ErrNoSubs = errors.New("no subs")
// GetSubs - List all subs in our video file.
func GetSubs(ffmpeg string, f string) ([]string, error) { func GetSubs(ffmpeg string, f string) ([]string, error) {
_, err := os.Stat(f) _, err := os.Stat(f)
if err != nil { if err != nil {
@@ -93,6 +95,8 @@ func GetSubs(ffmpeg string, f string) ([]string, error) {
return out, nil return out, nil
} }
// ExtractSub - Save the extracted sub into a temp file.
// Return the path of that file.
func ExtractSub(ffmpeg string, n int, f string) (string, error) { func ExtractSub(ffmpeg string, n int, f string) (string, error) {
_, err := os.Stat(f) _, err := os.Stat(f)
if err != nil { if err != nil {

View File

@@ -27,8 +27,10 @@ type tags struct {
Language string `mapstructure:"language"` Language string `mapstructure:"language"`
} }
// ErrNoSubs - No subs detected
var ErrNoSubs = errors.New("no subs") var ErrNoSubs = errors.New("no subs")
// GetSubs - List all subs in our video file.
func GetSubs(ffmpeg string, f string) ([]string, error) { func GetSubs(ffmpeg string, f string) ([]string, error) {
_, err := os.Stat(f) _, err := os.Stat(f)
if err != nil { if err != nil {
@@ -90,6 +92,8 @@ func GetSubs(ffmpeg string, f string) ([]string, error) {
return out, nil return out, nil
} }
// ExtractSub - Save the extracted sub into a temp file.
// Return the path of that file.
func ExtractSub(ffmpeg string, n int, f string) (string, error) { func ExtractSub(ffmpeg string, n int, f string) (string, error) {
_, err := os.Stat(f) _, err := os.Stat(f)
if err != nil { if err != nil {