@@ -1713,21 +1713,26 @@ out:
17131713 }
17141714
17151715 if nextURI == "" {
1716- if screen .tvdata == nil {
1716+ // Stop/skip actions clear these fields from another
1717+ // goroutine before this watcher's context is cancelled,
1718+ // so snapshot both and skip the tick if either is gone.
1719+ tvdata := screen .tvdata
1720+ srv := screen .httpserver
1721+ if tvdata == nil || srv == nil {
17171722 continue
17181723 }
17191724
17201725 // No need to check for the error as this is something
17211726 // that we did in previous steps in our workflow
1722- mPath , _ := url .Parse (screen . tvdata .MediaURL )
1723- sPath , _ := url .Parse (screen . tvdata .SubtitlesURL )
1727+ mPath , _ := url .Parse (tvdata .MediaURL )
1728+ sPath , _ := url .Parse (tvdata .SubtitlesURL )
17241729
17251730 // Make sure we clean up after ourselves and avoid
17261731 // leaving any dangling handlers. Given the nextURI is ""
17271732 // we know that the previously playing media entry was
17281733 // replaced by the one in the NextURI entry.
1729- screen . httpserver .RemoveHandler (mPath .Path )
1730- screen . httpserver .RemoveHandler (sPath .Path )
1734+ srv .RemoveHandler (mPath .Path )
1735+ srv .RemoveHandler (sPath .Path )
17311736
17321737 _ , mediaPath , err := getNextAutoPlayMediaOrError (screen )
17331738 if err != nil {
@@ -1869,17 +1874,20 @@ func skipToMediaPathAction(screen *FyneScreen, mediaPath string) {
18691874 // Set casting media type
18701875 screen .SetMediaType (mediaType )
18711876
1872- // Get server address
1873- whereToListen := screen .httpserver .GetAddr ()
1877+ // Get server address. A concurrent stop action may have already
1878+ // cleared the field, in which case there is nothing to skip to.
1879+ server := screen .httpserver
1880+ if server == nil {
1881+ return
1882+ }
1883+ whereToListen := server .GetAddr ()
18741884
18751885 var mediaURL string
18761886 var subtitleURL string
18771887
18781888 if transcode {
18791889 // TRANSCODING PATH: Stop server and restart with new file and transcode options
1880- if screen .httpserver != nil {
1881- screen .httpserver .StopServer ()
1882- }
1890+ server .StopServer ()
18831891
18841892 // Get actual media duration from ffprobe (Chromecast can't report it for transcoded streams)
18851893 if duration , err := utils .DurationForMediaSeconds (screen .ffmpegPath , screen .mediafile ); err == nil {
@@ -1901,15 +1909,16 @@ func skipToMediaPathAction(screen *FyneScreen, mediaPath string) {
19011909 }
19021910
19031911 // Create new HTTP server with transcoding
1904- screen .httpserver = httphandlers .NewServer (whereToListen )
1912+ server = httphandlers .NewServer (whereToListen )
1913+ screen .httpserver = server
19051914 serverStarted := make (chan error )
19061915 var serverCTXStop context.CancelFunc
19071916 serverStoppedCTX , serverCTXStop = context .WithCancel (context .Background ())
19081917 screen .serverStopCTX = serverStoppedCTX
19091918 screen .cancelServerStop = serverCTXStop
19101919
19111920 go func () {
1912- screen . httpserver .StartSimpleServerWithTranscode (serverStarted , screen .mediafile , tcOpts )
1921+ server .StartSimpleServerWithTranscode (serverStarted , screen .mediafile , tcOpts )
19131922 serverCTXStop ()
19141923 }()
19151924
@@ -1929,18 +1938,18 @@ func skipToMediaPathAction(screen *FyneScreen, mediaPath string) {
19291938 screen .mediaDuration = 0
19301939
19311940 // Get subtitle URL if needed (remove old handler first)
1932- screen . httpserver .RemoveHandler ("/subtitles.vtt" )
1941+ server .RemoveHandler ("/subtitles.vtt" )
19331942 if screen .subsfile != "" {
19341943 ext := strings .ToLower (filepath .Ext (screen .subsfile ))
19351944 switch ext {
19361945 case ".srt" :
19371946 webvttData , err := utils .ConvertSRTtoWebVTT (screen .subsfile )
19381947 if err == nil {
1939- screen . httpserver .AddHandler ("/subtitles.vtt" , nil , nil , webvttData )
1948+ server .AddHandler ("/subtitles.vtt" , nil , nil , webvttData )
19401949 subtitleURL = "http://" + whereToListen + "/subtitles.vtt"
19411950 }
19421951 case ".vtt" :
1943- screen . httpserver .AddHandler ("/subtitles.vtt" , nil , nil , screen .subsfile )
1952+ server .AddHandler ("/subtitles.vtt" , nil , nil , screen .subsfile )
19441953 subtitleURL = "http://" + whereToListen + "/subtitles.vtt"
19451954 }
19461955 }
@@ -1950,8 +1959,8 @@ func skipToMediaPathAction(screen *FyneScreen, mediaPath string) {
19501959 // URL uses ConvertFilename (encoded) for valid HTTP URL with special characters
19511960 oldHandlerPath := "/" + filepath .Base (oldMediaPath )
19521961 newHandlerPath := "/" + filepath .Base (screen .mediafile )
1953- screen . httpserver .RemoveHandler (oldHandlerPath )
1954- screen . httpserver .AddHandler (newHandlerPath , nil , nil , screen .mediafile )
1962+ server .RemoveHandler (oldHandlerPath )
1963+ server .AddHandler (newHandlerPath , nil , nil , screen .mediafile )
19551964
19561965 // Build media URL using URL-encoded filename (for special chars like brackets)
19571966 mediaURL = "http://" + whereToListen + "/" + utils .ConvertFilename (screen .mediafile )
0 commit comments