package audio import "time" // Ctrl allows for pausing and tracking a Streamer. // // Wrap a Streamer in a Ctrl. // // ctrl := &audio.Ctrl{Streamer: s} // // Then, we can pause the streaming (this will cause Ctrl to stream silence). // // ctrl.Paused = true // // And we can check how much has already been streamed. Position is not incremented when the Ctrl is // paused. // // fmt.Println(ctrl.Position) // // To completely stop a Ctrl before the wrapped Streamer is drained, just set the wrapped Streamer // to nil. // // ctrl.Streamer = nil // // If you're playing a Streamer wrapped in a Ctrl through the speaker, you need to lock and unlock // the speaker when modifying the Ctrl to avoid race conditions. // // speaker.Play(ctrl) // // ... // speaker.Lock() // ctrl.Paused = true // speaker.Unlock() // // ... // speaker.Lock() // fmt.Println(ctrl.Position) // speaker.Unlock() type Ctrl struct { Streamer Streamer Paused bool Position time.Duration } // Stream streams the wrapped Streamer, if not nil. If the Streamer is nil, Ctrl acts as drained. // When paused, Ctrl streams silence. func (c *Ctrl) Stream(samples [][2]float64) (n int, ok bool) { if c.Streamer == nil { return 0, false } if c.Paused { for i := range samples { samples[i] = [2]float64{} } return len(samples), true } n, ok = c.Streamer.Stream(samples) c.Position += time.Duration(n) * time.Second / time.Duration(SampleRate) return n, ok } // Err returns the error of the wrapped Streamer, if not nil. func (c *Ctrl) Err() error { if c.Streamer == nil { return nil } return c.Err() }