Add .Playing() function to Track interface

master
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.
type Playable interface {
Play(loops int) error
Playing() bool
Pause() 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 {
isMusic bool // false = is sound effect
engine *Engine
// If isMusic
mus *mix.Music
@ -46,6 +48,7 @@ func (e *Engine) LoadSound(filename string) (Track, error) {
wav, err := mix.LoadWAV(filename)
return Track{
isMusic: false,
engine: e,
wav: wav,
channel: -1,
}, err
@ -62,6 +65,7 @@ func (e *Engine) LoadSoundBin(data []byte) (Track, error) {
wav, err := mix.LoadWAVRW(rw, false)
return Track{
isMusic: false,
engine: e,
wav: wav,
channel: -1,
}, err
@ -93,9 +97,18 @@ func (t *Track) Play(loops int) error {
}
channel, err := t.wav.Play(-1, loops)
t.channel = channel
t.engine.setPlaying(channel, t)
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.
func (t Track) Pause() error {
if t.isMusic {

View File

@ -1,24 +1,35 @@
// Package sdl implements an audio engine using libSDL2.
package sdl
import "github.com/veandco/go-sdl2/mix"
import (
"sync"
"github.com/veandco/go-sdl2/mix"
)
// Engine is the SDL2 audio engine.
type Engine struct {
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.
//
// Pass the SDL2 Mixer flags for its initialization. The flags are an OR'd
// value made up of:
// mix.INIT_MP3
// mix.INIT_OGG
// mix.INIT_FLAC
// mix.INIT_MOD
//
// mix.INIT_MP3
// mix.INIT_OGG
// mix.INIT_FLAC
// mix.INIT_MOD
func New(flags int) (*Engine, error) {
return &Engine{
initFlags: flags,
initFlags: flags,
channelsPlaying: map[int]*Track{},
}, nil
}
@ -29,6 +40,11 @@ func (e *Engine) Setup() error {
return err
}
// Subscribe to sound effect channels finishing.
mix.ChannelFinished(func(channel int) {
_ = e.unsetPlaying(channel)
})
// Open the audio mixer.
// the '2' is stereo (two channels), '1' would be mono.
// 4096 is the chunk size.