fix: Better management of stop and play behavior
Removed the need of cancelreader that didn't work on Windows as expected, so we did away with the silly pipe to return a ReadCloser of the output, and used the object directly from the RadioPlayer object itself. Now when we stop, we close the stream and the ffmpeg instance.
This commit is contained in:
parent
f5e585bfe6
commit
cd3a909e61
4 changed files with 37 additions and 59 deletions
3
go.mod
3
go.mod
|
@ -4,8 +4,7 @@ go 1.16
|
|||
|
||||
require (
|
||||
fyne.io/fyne/v2 v2.4.2
|
||||
github.com/ebitengine/oto/v3 v3.1.0 // indirect
|
||||
github.com/ebitengine/oto/v3 v3.1.0
|
||||
github.com/ebitengine/purego v0.5.1 // indirect
|
||||
github.com/muesli/cancelreader v0.2.2 // indirect
|
||||
golang.org/x/sys v0.15.0 // indirect
|
||||
)
|
||||
|
|
4
go.sum
4
go.sum
|
@ -243,8 +243,6 @@ github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RR
|
|||
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
||||
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
||||
github.com/muesli/cancelreader v0.2.2 h1:3I4Kt4BQjOR54NavqnDogx/MIoWBFa0StPA8ELUXHmA=
|
||||
github.com/muesli/cancelreader v0.2.2/go.mod h1:3XuTXfFS2VjM+HTLZY9Ak0l6eUKfijIfMUZ4EgX0QYo=
|
||||
github.com/neelance/astrewrite v0.0.0-20160511093645-99348263ae86/go.mod h1:kHJEU3ofeGjhHklVoIGuVj85JJwZ6kWPaJwCIxgnFmo=
|
||||
github.com/neelance/sourcemap v0.0.0-20200213170602-2833bce08e4c/go.mod h1:Qr6/a/Q4r9LP1IltGz7tA7iOK1WonHEYhu1HRBA7ZiM=
|
||||
github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646/go.mod h1:jpp1/29i3P1S/RLdc7JQKbRpFeM1dOBd8T9ki5s+AY8=
|
||||
|
@ -504,7 +502,6 @@ golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBc
|
|||
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220204135822-1c1b9b1eba6a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
|
@ -514,7 +511,6 @@ golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
|||
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE=
|
||||
golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc=
|
||||
golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
|
|
71
main.go
71
main.go
|
@ -49,8 +49,6 @@ import (
|
|||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/muesli/cancelreader"
|
||||
|
||||
"fyne.io/fyne/v2"
|
||||
"fyne.io/fyne/v2/app"
|
||||
"fyne.io/fyne/v2/canvas"
|
||||
|
@ -70,10 +68,6 @@ const (
|
|||
Stopped
|
||||
)
|
||||
|
||||
// Cancel Reader
|
||||
|
||||
var reader cancelreader.CancelReader
|
||||
|
||||
// helper
|
||||
func check(err error) {
|
||||
if err != nil {
|
||||
|
@ -159,10 +153,10 @@ func main() {
|
|||
log.Println("Starting the app")
|
||||
|
||||
// Create the status channel, to read from StreamPlayer and the pipe to send commands to it
|
||||
pipe_chan := make(chan io.ReadCloser)
|
||||
// pipe_chan := make(chan io.ReadCloser)
|
||||
|
||||
// Create our StreamPlayer instance
|
||||
streamPlayer := StreamPlayer{player_name: PLAYER_CMD, pipe_chan: pipe_chan}
|
||||
streamPlayer := StreamPlayer{player_name: PLAYER_CMD}
|
||||
|
||||
// Create our app and window
|
||||
app := app.New()
|
||||
|
@ -217,7 +211,7 @@ func main() {
|
|||
// Here we control each time the button is pressed and update its
|
||||
// appearance anytime it is clicked. We make the player start playing
|
||||
// or pause.
|
||||
if !streamPlayer.IsPlaying() && !streamPlayer.paused {
|
||||
if !streamPlayer.IsPlaying() {
|
||||
playButton.SetIcon(theme.MediaStopIcon())
|
||||
playButton.SetText("(Buffering)")
|
||||
streamPlayer.Load(RADIOSPIRAL_STREAM)
|
||||
|
@ -227,9 +221,8 @@ func main() {
|
|||
if playStatus == Playing {
|
||||
playStatus = Stopped
|
||||
playButton.SetIcon(theme.MediaPlayIcon())
|
||||
streamPlayer.Pause()
|
||||
streamPlayer.Stop()
|
||||
} else {
|
||||
reader.Cancel()
|
||||
playStatus = Loading
|
||||
playButton.SetText("(Buffering)")
|
||||
playButton.SetIcon(theme.MediaStopIcon())
|
||||
|
@ -242,37 +235,37 @@ func main() {
|
|||
// Process the output of ffmpeg here in a separate goroutine
|
||||
go func() {
|
||||
for {
|
||||
out_pipe := <-pipe_chan
|
||||
var err error
|
||||
reader, err = cancelreader.NewReader(out_pipe)
|
||||
if err != nil {
|
||||
log.Println("Error opening reader")
|
||||
}
|
||||
for {
|
||||
var data [255]byte
|
||||
_, err := reader.Read(data[:])
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
break
|
||||
}
|
||||
lines := strings.Split(string(data[:]), "\n")
|
||||
for _, line := range lines {
|
||||
// Log, if enabled, the output of StreamPlayer
|
||||
if *loggingToFilePtr {
|
||||
log.Print("[" + streamPlayer.player_name + "] " + line)
|
||||
if streamPlayer.out != nil {
|
||||
for {
|
||||
var data [255]byte
|
||||
_, err := streamPlayer.out.Read(data[:])
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
break
|
||||
}
|
||||
if strings.Contains(line, "Output #0") {
|
||||
playStatus = Playing
|
||||
playButton.SetText("")
|
||||
}
|
||||
// Check if there's an updated title and reflect it on the
|
||||
// GUI
|
||||
if strings.Contains(line, "StreamTitle: ") {
|
||||
log.Println("Found new stream title, updating GUI")
|
||||
newTitleParts := strings.Split(line, "StreamTitle: ")
|
||||
nowPlayingLabel.SetText(newTitleParts[1])
|
||||
lines := strings.Split(string(data[:]), "\n")
|
||||
for _, line := range lines {
|
||||
// Log, if enabled, the output of StreamPlayer
|
||||
if *loggingToFilePtr {
|
||||
log.Print("[" + streamPlayer.player_name + "] " + line)
|
||||
}
|
||||
if strings.Contains(line, "Output #0") {
|
||||
playStatus = Playing
|
||||
playButton.SetText("")
|
||||
}
|
||||
// Check if there's an updated title and reflect it on the
|
||||
// GUI
|
||||
if strings.Contains(line, "StreamTitle: ") {
|
||||
log.Println("Found new stream title, updating GUI")
|
||||
newTitleParts := strings.Split(line, "StreamTitle: ")
|
||||
nowPlayingLabel.SetText(newTitleParts[1])
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// To avoid high CPU usage, we wait some milliseconds before testing
|
||||
// again for the change in streamPlayer.out from nil to ReadCloser
|
||||
time.Sleep(200 * time.Millisecond)
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
|
|
@ -38,7 +38,7 @@ type RadioPlayer interface {
|
|||
IsPlaying() bool
|
||||
Play()
|
||||
Mute()
|
||||
Pause()
|
||||
Stop()
|
||||
IncVolume()
|
||||
DecVolume()
|
||||
Close()
|
||||
|
@ -52,11 +52,9 @@ type StreamPlayer struct {
|
|||
in io.WriteCloser
|
||||
out io.ReadCloser
|
||||
audio io.ReadCloser
|
||||
pipe_chan chan io.ReadCloser
|
||||
otoContext *oto.Context
|
||||
otoPlayer *oto.Player
|
||||
currentVolume float64
|
||||
paused bool
|
||||
}
|
||||
|
||||
func (player *StreamPlayer) IsPlaying() bool {
|
||||
|
@ -114,12 +112,6 @@ func (player *StreamPlayer) Load(stream_url string) {
|
|||
player.otoPlayer = player.otoContext.NewPlayer(player.audio)
|
||||
// Save current volume for the mute function
|
||||
player.currentVolume = player.otoPlayer.Volume()
|
||||
|
||||
player.paused = false
|
||||
|
||||
go func() {
|
||||
player.pipe_chan <- player.out
|
||||
}()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -146,6 +138,7 @@ func (player *StreamPlayer) Close() {
|
|||
player.in.Close()
|
||||
player.out.Close()
|
||||
player.audio.Close()
|
||||
player.out = nil
|
||||
|
||||
player.stream_url = ""
|
||||
}
|
||||
|
@ -162,12 +155,9 @@ func (player *StreamPlayer) Mute() {
|
|||
}
|
||||
}
|
||||
|
||||
func (player *StreamPlayer) Pause() {
|
||||
func (player *StreamPlayer) Stop() {
|
||||
if player.IsPlaying() {
|
||||
if !player.paused {
|
||||
player.paused = true
|
||||
player.otoPlayer.Pause()
|
||||
}
|
||||
player.Close()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue