oto icon indicating copy to clipboard operation
oto copied to clipboard

Callback or Signal for Playback complete

Open JackMordaunt opened this issue 1 year ago • 4 comments

Instead of polling the player, perhaps it would be better to offer either a callback or a channel style API.

    // We can wait for the sound to finish playing using something like this
    for player.IsPlaying() {
        time.Sleep(time.Millisecond)
    }
// Channel style.
<-player.Done()

// Callback style.
player.OnDone(func() {...})

JackMordaunt avatar Jan 05 '24 06:01 JackMordaunt

You can get underneath the player with a custom io.Reader, but it is a bit annoying - but maybe a good route?

// TriggerReader invokes a callback when EOF is reached.
type TriggerReader struct {
	r  io.Reader
	cb func()
}

func (t *TriggerReader) Read(p []byte) (n int, err error) {
	n, err = t.r.Read(p)
	if err == io.EOF {
		t.Callback()
	}
	return n, err
}

func (t *TriggerReader) Callback() {
	if t.cb != nil {
		t.cb()
	}
}
done := make(chan struct{})
data := []byte{...}
src := bytes.NewReader(data)
src = &TriggerReader{r: src, cb: func() {close(done)}}
p := ctx.NewPlayer(src)
p.Play()
<-done

JackMordaunt avatar Jan 05 '24 06:01 JackMordaunt

I was wondering why you need to detect the timing when the player ends in the first place.

hajimehoshi avatar Jan 05 '24 14:01 hajimehoshi

I have a program that wants to exit once playback is finished, but you could also imagine advancing a track in a playlist, or similar.

JackMordaunt avatar Jan 08 '24 03:01 JackMordaunt

Another use case could be that we want to wait for the player to finish and all the samples be sent to the driver before suspending so that the last couple of samples don't get lost.

I was discussing this regarding Beep from this comment down: https://github.com/gopxl/beep/issues/137#issuecomment-1908810880

MarkKremer avatar Jan 24 '24 20:01 MarkKremer