From 4cf9a2a58f784581e6a6726e6d7da3f704795f97 Mon Sep 17 00:00:00 2001 From: MassiveBox Date: Sat, 7 Jun 2025 22:43:22 +0200 Subject: [PATCH] Improve casting resume behavior --- app/controller.go | 15 ++++++--------- app/model.go | 32 +++++++++++++++++++++++++++++++- app/view.go | 21 ++++++++++++++++++++- 3 files changed, 57 insertions(+), 11 deletions(-) diff --git a/app/controller.go b/app/controller.go index baa2f68..9ad0438 100644 --- a/app/controller.go +++ b/app/controller.go @@ -39,16 +39,10 @@ func (c *Controller) StartCasting(selected string, mediaURL string) { return } - err := c.Model.ConnectToDevice(selected) - if err != nil { - c.LogAndShowError(fmt.Errorf("error connecting to device %v", err)) - return - } go func() { - err = c.Model.StartCast(mediaURL) + err := c.Model.Cast(selected, mediaURL) if err != nil { - c.LogAndShowError(fmt.Errorf("error starting cast %v", err)) - c.DiscoverDevices() + c.LogAndShowError(fmt.Errorf("error starting cast: %v", err)) return } }() @@ -56,6 +50,10 @@ func (c *Controller) StartCasting(selected string, mediaURL string) { } +func (c *Controller) ShowReconnecting(reconnecting bool) { + c.View.PopupReconnecting(reconnecting) +} + // Note: these are app codes, they are NOT related to fcast opcodes! const ( ActionPlay = 0 @@ -78,7 +76,6 @@ func (c *Controller) PlayerAction(action int, args ...float32) { } func (c *Controller) ExitCasting() { - c.PlayerAction(ActionStop) c.DiscoverDevices() } diff --git a/app/model.go b/app/model.go index 42bc090..52d6bb3 100644 --- a/app/model.go +++ b/app/model.go @@ -7,6 +7,8 @@ import ( "io" "math" "net/http" + "strings" + "time" ) type Model struct { @@ -14,9 +16,11 @@ type Model struct { DiscoveredDevices []fcast.DiscoveredHost Connection *fcast.Connection EventManager *fcast.EventManager + DeviceName string Time float32 Length float32 Volume float32 + IsReconnecting bool } func (m *Model) DiscoverDevices() ([]string, error) { @@ -47,10 +51,29 @@ func (m *Model) ConnectToDevice(name string) error { return err } m.Connection = connection + m.DeviceName = name return nil } -func (m *Model) StartCast(mediaURL string) error { +func (m *Model) Cast(selectedDevice, mediaURL string) error { + err := m.doCast(selectedDevice, mediaURL) + if err != nil { + if errors.Is(err, io.EOF) || strings.Contains(err.Error(), "software caused connection abort") { + m.Controller.ShowReconnecting(true) + time.Sleep(500 * time.Millisecond) + return m.Cast(selectedDevice, mediaURL) + } + } + m.Controller.ShowReconnecting(false) + return err +} + +func (m *Model) doCast(selectedDevice, mediaURL string) error { + + err := m.ConnectToDevice(selectedDevice) + if err != nil { + return fmt.Errorf("error connecting to device %v", err) + } m.EventManager = &fcast.EventManager{} @@ -81,6 +104,13 @@ func (m *Model) StartCast(mediaURL string) error { if err != nil { return err } + } else { + m.Volume = 1 + } + + err = m.Connection.SendMessage(&fcast.PingMessage{}) + if err == nil { + m.Controller.ShowReconnecting(false) } return m.Connection.ListenForMessages(m.EventManager) diff --git a/app/view.go b/app/view.go index e105359..279249e 100644 --- a/app/view.go +++ b/app/view.go @@ -18,10 +18,29 @@ type View struct { Controller *Controller Window fyne.Window CastingScreenElements CastingScreenElements + ReconnectingDialog *dialog.CustomDialog } func (v *View) PopupError(err error) { - dialog.ShowError(err, v.Window) + fyne.Do(func() { + dialog.ShowError(err, v.Window) + }) +} + +func (v *View) PopupReconnecting(show bool) { + if v.ReconnectingDialog != nil && !show { + fyne.DoAndWait(func() { + v.ReconnectingDialog.Dismiss() + v.ReconnectingDialog = nil + }) + return + } + if v.ReconnectingDialog == nil && show { + v.ReconnectingDialog = dialog.NewCustomWithoutButtons("Reconnecting to stream...", widget.NewProgressBarInfinite(), v.Window) + fyne.Do(func() { + v.ReconnectingDialog.Show() + }) + } } func NewView(controller *Controller) *View {