Add .Playing() function to Track interface

This commit is contained in:
Noah 2023-03-09 22:55:53 -08:00
parent 65068820cb
commit fa6eb3d3a0
4 changed files with 66 additions and 6 deletions

View File

@ -36,6 +36,7 @@ type Engine interface {
// Playable is a music or sound effect object that can be played and managed. // Playable is a music or sound effect object that can be played and managed.
type Playable interface { type Playable interface {
Play(loops int) error Play(loops int) error
Playing() bool
Pause() error Pause() error
Stop() error Stop() error

30
sdl/currently_playing.go Normal file
View File

@ -0,0 +1,30 @@
package sdl
import "errors"
// setPlaying associates a channel no. to the Track playing.
func (e *Engine) setPlaying(channel int, t *Track) {
e.channelMu.Lock()
defer e.channelMu.Unlock()
e.channelsPlaying[channel] = t
}
// unsetPlaying associates a channel no. to the Track playing.
func (e *Engine) unsetPlaying(channel int) error {
e.channelMu.Lock()
defer e.channelMu.Unlock()
if track, ok := e.channelsPlaying[channel]; ok {
track.channel = -1
delete(e.channelsPlaying, channel)
return nil
}
return errors.New("didn't even know channel %d was playing a sound")
}
// isPlaying checks if a sound effect is playing on a channel.
func (e *Engine) isPlaying(channel int) bool {
e.channelMu.RLock()
defer e.channelMu.RUnlock()
_, ok := e.channelsPlaying[channel]
return ok
}

View File

@ -9,6 +9,8 @@ import (
type Track struct { type Track struct {
isMusic bool // false = is sound effect isMusic bool // false = is sound effect
engine *Engine
// If isMusic // If isMusic
mus *mix.Music mus *mix.Music
@ -46,6 +48,7 @@ func (e *Engine) LoadSound(filename string) (Track, error) {
wav, err := mix.LoadWAV(filename) wav, err := mix.LoadWAV(filename)
return Track{ return Track{
isMusic: false, isMusic: false,
engine: e,
wav: wav, wav: wav,
channel: -1, channel: -1,
}, err }, err
@ -62,6 +65,7 @@ func (e *Engine) LoadSoundBin(data []byte) (Track, error) {
wav, err := mix.LoadWAVRW(rw, false) wav, err := mix.LoadWAVRW(rw, false)
return Track{ return Track{
isMusic: false, isMusic: false,
engine: e,
wav: wav, wav: wav,
channel: -1, channel: -1,
}, err }, err
@ -93,9 +97,18 @@ func (t *Track) Play(loops int) error {
} }
channel, err := t.wav.Play(-1, loops) channel, err := t.wav.Play(-1, loops)
t.channel = channel t.channel = channel
t.engine.setPlaying(channel, t)
return err return err
} }
// Playing tells if this sound is already playing.
func (t *Track) Playing() bool {
if t.isMusic {
return mix.PlayingMusic()
}
return t.channel >= 0 && t.engine.isPlaying(t.channel)
}
// Pause the track. // Pause the track.
func (t Track) Pause() error { func (t Track) Pause() error {
if t.isMusic { if t.isMusic {

View File

@ -1,17 +1,27 @@
// Package sdl implements an audio engine using libSDL2. // Package sdl implements an audio engine using libSDL2.
package sdl package sdl
import "github.com/veandco/go-sdl2/mix" import (
"sync"
"github.com/veandco/go-sdl2/mix"
)
// Engine is the SDL2 audio engine. // Engine is the SDL2 audio engine.
type Engine struct { type Engine struct {
initFlags int initFlags int
// Keep track of which SDL channel numbers are ACTUALLY playing sound
// effects right now, and watch for when the channels are finished.
channelMu sync.RWMutex
channelsPlaying map[int]*Track
} }
// New initializes an SDL2 Mixer for the audio engine. // New initializes an SDL2 Mixer for the audio engine.
// //
// Pass the SDL2 Mixer flags for its initialization. The flags are an OR'd // Pass the SDL2 Mixer flags for its initialization. The flags are an OR'd
// value made up of: // value made up of:
//
// mix.INIT_MP3 // mix.INIT_MP3
// mix.INIT_OGG // mix.INIT_OGG
// mix.INIT_FLAC // mix.INIT_FLAC
@ -19,6 +29,7 @@ type Engine struct {
func New(flags int) (*Engine, error) { func New(flags int) (*Engine, error) {
return &Engine{ return &Engine{
initFlags: flags, initFlags: flags,
channelsPlaying: map[int]*Track{},
}, nil }, nil
} }
@ -29,6 +40,11 @@ func (e *Engine) Setup() error {
return err return err
} }
// Subscribe to sound effect channels finishing.
mix.ChannelFinished(func(channel int) {
_ = e.unsetPlaying(channel)
})
// Open the audio mixer. // Open the audio mixer.
// the '2' is stereo (two channels), '1' would be mono. // the '2' is stereo (two channels), '1' would be mono.
// 4096 is the chunk size. // 4096 is the chunk size.