123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380 |
- package main
- import (
- "encoding/json"
- "errors"
- "fmt"
- "io"
- "io/fs"
- "log"
- "net/http"
- "net/url"
- "fyne.io/fyne/v2"
- "fyne.io/fyne/v2/app"
- "fyne.io/fyne/v2/cmd/fyne_settings/settings"
- "fyne.io/fyne/v2/container"
- "fyne.io/fyne/v2/dialog"
- "fyne.io/fyne/v2/storage"
- "fyne.io/fyne/v2/theme"
- "fyne.io/fyne/v2/widget"
- )
- var TvStatus string = "Disconnected" // Need refresh
- var TvIp string = "192.168.254.75" // This isn't reliable but it works at least
- var TvMac string = "cc:a1:2b:46:7a:0b" // Used for WOL
- var WOLs map[string]string // IP = Mac
- func LoadWOLs(w fyne.Window) {
- WOLs = make(map[string]string)
- var file fyne.URI = storage.NewFileURI("wol.txt")
- if file == nil {
- dialog.ShowError(errors.New("failed obtaining WOL file"), w)
- return
- }
- var err error
- var wol_file fyne.URIReadCloser
- wol_file, err = storage.Reader(file)
- if err != nil {
- if !errors.Is(err, fs.ErrNotExist) {
- dialog.ShowError(err, w)
- }
- return
- }
- defer wol_file.Close()
- var data []byte
- data, err = io.ReadAll(wol_file)
- if err != nil {
- dialog.ShowError(err, w)
- return
- }
- err = json.Unmarshal(data, &WOLs)
- if err != nil {
- dialog.ShowError(err, w)
- return
- }
- }
- func SaveWOLs(w fyne.Window) {
- var file fyne.URI = storage.NewFileURI("wol.txt")
- if file == nil {
- dialog.ShowError(errors.New("failed obtaining WOL file"), w)
- return
- }
- var err error
- var wol_file fyne.URIWriteCloser
- wol_file, err = storage.Writer(file)
- if err != nil {
- dialog.ShowError(fmt.Errorf("save %v", err), w)
- return
- }
- defer wol_file.Close()
- var data []byte
- data, err = json.Marshal(WOLs)
- if err != nil {
- dialog.ShowError(err, w)
- return
- }
- var bytesWrote int
- bytesWrote, err = wol_file.Write(data)
- if err != nil {
- dialog.ShowError(err, w)
- return
- } else if bytesWrote != len(data) {
- dialog.ShowError(fmt.Errorf("failed completely writing WOL file, wrote %d bytes but needed to write %d bytes", bytesWrote, len(data)), w)
- }
- }
- func WOLString() []string {
- var result []string
- for ip := range WOLs {
- result = append(result, ip)
- }
- return result
- }
- // Depreciated as mobile users will use the settings button rather than the menu
- /*func make_mainMnu(a fyne.App, w fyne.Window) *fyne.MainMenu {
- var settingsItem *fyne.MenuItem = fyne.NewMenuItem("Settings", func() {
- var w2 fyne.Window = a.NewWindow("myRoku Settings")
- w2.SetContent(settings.NewSettings().LoadAppearanceScreen(w2))
- w2.CenterOnScreen()
- w2.Resize(fyne.NewSize(480, 480))
- w2.Show()
- })
- var mnu *fyne.MainMenu = fyne.NewMainMenu(fyne.NewMenu("File", settingsItem, fyne.NewMenuItemSeparator()))
- return mnu
- }*/
- func etherWake() {
- SendMagicPacket(TvIp, TvMac)
- }
- func main() {
- var a fyne.App = app.NewWithID("my-roku")
- var version = a.Metadata().Version
- log.Printf("myRoku v%s", version)
- var home fyne.Window = a.NewWindow("myRoku")
- /*if a.Driver().Device().HasKeyboard() { // Desktop only
- home.SetMainMenu(make_mainMnu(a, home))
- } */
- home.CenterOnScreen()
- home.SetMaster()
- home.Resize(fyne.NewSize(420, 620))
- var tvStatus *widget.Label = widget.NewLabel(TvStatus)
- home.SetContent(container.NewVBox(
- container.NewHBox(
- widget.NewLabel(fmt.Sprintf("myRoku - v%s", version)),
- widget.NewButtonWithIcon("", theme.SettingsIcon(), func() {
- var w2 fyne.Window = a.NewWindow("myRoku Settings")
- w2.SetContent(container.NewVBox(
- settings.NewSettings().LoadAppearanceScreen(w2),
- widget.NewButton("Quit", func() {
- w2.Close()
- }),
- ))
- w2.CenterOnScreen()
- w2.Resize(fyne.NewSize(480, 480))
- w2.Show()
- }),
- ),
- container.NewHBox(
- tvStatus,
- widget.NewButtonWithIcon("Connections", theme.ComputerIcon(), func() {
- var w2 fyne.Window = a.NewWindow("myRoku Connections")
- // Change this from text entries to a choice list
- var mac_entry *widget.Label = widget.NewLabel(TvMac)
- // Issue the command to find devices when the user presses a refresh button (updating the list of devices to choose)
- var ip_entry *widget.Select = widget.NewSelect(WOLString(), func(change string) {
- TvIp = change
- TvMac = WOLs[change]
- mac_entry.Text = TvMac
- mac_entry.Refresh()
- })
- if TvIp != "" {
- ip_entry.Selected = TvIp
- ip_entry.Refresh()
- TvMac = WOLs[TvIp]
- mac_entry.Text = TvMac
- mac_entry.Refresh()
- }
- /*ip_entry.OnSubmitted = func(s string) {
- if TvIp != s { // It's the same thing!?!
- log.Printf("TvIp='%s' Now '%s'", TvIp, s)
- TvIp = s
- ip_entry.Refresh()
- }
- ip_entry.FocusLost() // Lose focus so the user can enter the next field
- }
- var mac_entry *widget.Entry = widget.NewEntry()
- mac_entry.SetText(TvMac)
- mac_entry.OnSubmitted = func(s string) {
- if TvMac != s { // It's the same thing!?!
- log.Printf("TvMac='%s' Now '%s'", TvMac, s)
- TvMac = s
- mac_entry.Refresh()
- }
- mac_entry.FocusLost() // Lose focus so the user can enter the next field
- }*/
- w2.SetContent(container.NewVBox(
- widget.NewButtonWithIcon("Refresh", theme.ViewRefreshIcon(), func() {
- _, WOLs = GetDevices(WOLs, w2)
- ip_entry.Options = WOLString()
- ip_entry.Refresh()
- }),
- container.NewHBox(
- widget.NewLabel("Tv Ip Address"),
- widget.NewButtonWithIcon("", theme.HelpIcon(), func() {
- var u *url.URL
- var err error
- u, err = url.Parse("https://en.wikipedia.org/wiki/IP_address")
- if err != nil {
- log.Println("Failed sending the user to Wiki=IP_address", err)
- return
- }
- a.OpenURL(u)
- }),
- ),
- ip_entry,
- container.NewHBox(
- widget.NewLabel("Tv Mac Address"),
- widget.NewButtonWithIcon("", theme.HelpIcon(), func() {
- var u *url.URL
- var err error
- u, err = url.Parse("https://en.wikipedia.org/wiki/MAC_address")
- if err != nil {
- log.Println("Failed sending the user to Wiki=MAC_address", err)
- return
- }
- a.OpenURL(u)
- }),
- ),
- mac_entry,
- widget.NewButtonWithIcon("Back", theme.NavigateBackIcon(), func() {
- SaveWOLs(home)
- w2.Close()
- }),
- ))
- w2.CenterOnScreen()
- w2.Resize(fyne.NewSize(480, 480))
- w2.Show()
- }),
- ),
- container.NewHBox(
- widget.NewButton("Power", func() {
- var r bool = PerformKey(TvIp, "power")
- if !r {
- etherWake()
- PerformKey(TvIp, "power")
- }
- }),
- widget.NewButton("Display", func() {
- var stat string = DebugInfo(TvIp)
- if stat == "" {
- etherWake()
- stat = DebugInfo(TvIp)
- }
- TvStatus = stat
- tvStatus.Text = TvStatus
- tvStatus.Refresh()
- /*var device *DeviceInfo = GetDeviceInfo(TvIp)
- if device.PowerMode == "PowerOn" {
- // Tv's on
- } else {
- // Tv's off
- }*/
- }),
- // Connect moved to Connections above
- ),
- container.NewHBox(
- widget.NewButtonWithIcon("", theme.MailReplyIcon(), func() {
- var r bool = PerformKey(TvIp, "back")
- if !r {
- etherWake()
- PerformKey(TvIp, "back")
- }
- }),
- widget.NewButtonWithIcon("", theme.HomeIcon(), func() {
- var r bool = PerformKey(TvIp, "home")
- if !r {
- etherWake()
- PerformKey(TvIp, "home")
- }
- }),
- ),
- widget.NewButtonWithIcon("", theme.MoveUpIcon(), func() {
- var r bool = PerformKey(TvIp, "up")
- if !r {
- etherWake()
- PerformKey(TvIp, "up")
- }
- }),
- container.NewHBox(
- widget.NewButtonWithIcon("", theme.NavigateBackIcon(), func() {
- var r bool = PerformKey(TvIp, "left")
- if !r {
- etherWake()
- PerformKey(TvIp, "left")
- }
- }),
- widget.NewButton("Ok", func() {
- var r bool = PerformKey(TvIp, "select")
- if !r {
- etherWake()
- PerformKey(TvIp, "select")
- }
- }),
- widget.NewButtonWithIcon("", theme.NavigateNextIcon(), func() {
- var r bool = PerformKey(TvIp, "right")
- if !r {
- etherWake()
- PerformKey(TvIp, "right")
- }
- }),
- ),
- widget.NewButtonWithIcon("", theme.MoveDownIcon(), func() {
- var r bool = PerformKey(TvIp, "down")
- if !r {
- etherWake()
- PerformKey(TvIp, "down")
- }
- }),
- container.NewHBox(
- widget.NewButtonWithIcon("", theme.ViewRefreshIcon(), func() {
- var r bool = PerformKey(TvIp, "instantreplay")
- if !r {
- etherWake()
- PerformKey(TvIp, "instantreplay")
- }
- }),
- widget.NewButton("Info", func() {
- var r bool = PerformKey(TvIp, "info")
- if !r {
- etherWake()
- PerformKey(TvIp, "info")
- }
- }),
- ),
- container.NewHBox(
- widget.NewButtonWithIcon("", theme.MediaFastRewindIcon(), func() {
- var r bool = PerformKey(TvIp, "rev")
- if !r {
- etherWake()
- PerformKey(TvIp, "rev")
- }
- }),
- widget.NewButtonWithIcon("", theme.MediaPauseIcon(), func() {
- var r bool = PerformKey(TvIp, "play")
- if !r {
- etherWake()
- PerformKey(TvIp, "play")
- }
- }),
- widget.NewButtonWithIcon("", theme.MediaFastForwardIcon(), func() {
- var r bool = PerformKey(TvIp, "fwd")
- if !r {
- etherWake()
- PerformKey(TvIp, "fwd")
- }
- }),
- ),
- container.NewHBox(
- widget.NewButtonWithIcon("", theme.VolumeUpIcon(), func() {
- var r bool = PerformKey(TvIp, "volumeup")
- if !r {
- etherWake()
- PerformKey(TvIp, "volumeup")
- }
- }),
- widget.NewButtonWithIcon("", theme.VolumeMuteIcon(), func() {
- var r bool = PerformKey(TvIp, "volumemute")
- if !r {
- etherWake()
- PerformKey(TvIp, "volumemute")
- }
- }),
- widget.NewButtonWithIcon("", theme.VolumeDownIcon(), func() {
- var r bool = PerformKey(TvIp, "volumedown")
- if !r {
- etherWake()
- PerformKey(TvIp, "volumedown")
- }
- }),
- ),
- widget.NewButton("Pluto Tv", func() {
- var r *http.Response = Post(fmt.Sprintf("http://%s:8060/launch/%d", TvIp, 74519))
- if r == nil {
- etherWake()
- Post(fmt.Sprintf("http://%s:8060/launch/%d", TvIp, 74519))
- }
- }),
- /*widget.NewButton("Debug", func() {
- log.Printf("myRoku v%s wol=%t", version, UseWake)
- log.Printf("TvStatus='%s' TvIp='%s' TvMac='%s'", TvStatus, TvIp, TvMac)
- log.Printf("driver=(mobile:%t, desktop:%t, browser:%t)", a.Driver().Device().IsMobile(), a.Driver().Device().HasKeyboard(), a.Driver().Device().IsBrowser())
- }),*/
- ))
- home.Show()
- LoadWOLs(home)
- a.Run()
- }
|