mirror of
https://github.com/hajimehoshi/ebiten.git
synced 2024-12-26 11:48:55 +01:00
audio: Define playerImpl interface
This commit is contained in:
parent
7cf32efcd5
commit
e77beac235
@ -66,7 +66,7 @@ type Context struct {
|
|||||||
err error
|
err error
|
||||||
ready bool
|
ready bool
|
||||||
|
|
||||||
players map[*writerContextPlayerImpl]struct{}
|
players map[playerImpl]struct{}
|
||||||
|
|
||||||
m sync.Mutex
|
m sync.Mutex
|
||||||
semaphore chan struct{}
|
semaphore chan struct{}
|
||||||
@ -97,7 +97,7 @@ func NewContext(sampleRate int) *Context {
|
|||||||
c := &Context{
|
c := &Context{
|
||||||
sampleRate: sampleRate,
|
sampleRate: sampleRate,
|
||||||
c: newWriterContext(sampleRate),
|
c: newWriterContext(sampleRate),
|
||||||
players: map[*writerContextPlayerImpl]struct{}{},
|
players: map[playerImpl]struct{}{},
|
||||||
inited: make(chan struct{}),
|
inited: make(chan struct{}),
|
||||||
semaphore: make(chan struct{}, 1),
|
semaphore: make(chan struct{}, 1),
|
||||||
}
|
}
|
||||||
@ -158,7 +158,7 @@ func (c *Context) setReady() {
|
|||||||
c.m.Unlock()
|
c.m.Unlock()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Context) addPlayer(p *writerContextPlayerImpl) {
|
func (c *Context) addPlayer(p playerImpl) {
|
||||||
c.m.Lock()
|
c.m.Lock()
|
||||||
defer c.m.Unlock()
|
defer c.m.Unlock()
|
||||||
c.players[p] = struct{}{}
|
c.players[p] = struct{}{}
|
||||||
@ -174,7 +174,7 @@ func (c *Context) addPlayer(p *writerContextPlayerImpl) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Context) removePlayer(p *writerContextPlayerImpl) {
|
func (c *Context) removePlayer(p playerImpl) {
|
||||||
c.m.Lock()
|
c.m.Lock()
|
||||||
delete(c.players, p)
|
delete(c.players, p)
|
||||||
c.m.Unlock()
|
c.m.Unlock()
|
||||||
@ -220,7 +220,22 @@ func (c *Context) SampleRate() int {
|
|||||||
// This means that if a Player plays an infinite stream,
|
// This means that if a Player plays an infinite stream,
|
||||||
// the object is never GCed unless Close is called.
|
// the object is never GCed unless Close is called.
|
||||||
type Player struct {
|
type Player struct {
|
||||||
p *writerContextPlayerImpl
|
p playerImpl
|
||||||
|
}
|
||||||
|
|
||||||
|
type playerImpl interface {
|
||||||
|
io.Closer
|
||||||
|
|
||||||
|
Play()
|
||||||
|
IsPlaying() bool
|
||||||
|
Pause()
|
||||||
|
Volume() float64
|
||||||
|
SetVolume(volume float64)
|
||||||
|
Current() time.Duration
|
||||||
|
Rewind() error
|
||||||
|
Seek(offset time.Duration) error
|
||||||
|
|
||||||
|
source() io.Reader
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewPlayer creates a new player with the given stream.
|
// NewPlayer creates a new player with the given stream.
|
||||||
@ -240,22 +255,13 @@ type Player struct {
|
|||||||
// A Player doesn't close src even if src implements io.Closer.
|
// A Player doesn't close src even if src implements io.Closer.
|
||||||
// Closing the source is src owner's responsibility.
|
// Closing the source is src owner's responsibility.
|
||||||
func NewPlayer(context *Context, src io.Reader) (*Player, error) {
|
func NewPlayer(context *Context, src io.Reader) (*Player, error) {
|
||||||
p := &Player{
|
pi, err := newWriterContextPlayerImpl(context, src)
|
||||||
&writerContextPlayerImpl{
|
|
||||||
context: context,
|
|
||||||
src: src,
|
|
||||||
sampleRate: context.sampleRate,
|
|
||||||
volume: 1,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
if seeker, ok := p.p.src.(io.Seeker); ok {
|
|
||||||
// Get the current position of the source.
|
|
||||||
pos, err := seeker.Seek(0, io.SeekCurrent)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
p.p.pos = pos
|
|
||||||
}
|
p := &Player{pi}
|
||||||
|
|
||||||
runtime.SetFinalizer(p, (*Player).finalize)
|
runtime.SetFinalizer(p, (*Player).finalize)
|
||||||
|
|
||||||
return p, nil
|
return p, nil
|
||||||
|
@ -64,6 +64,24 @@ type writerContextPlayerImpl struct {
|
|||||||
m sync.Mutex
|
m sync.Mutex
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func newWriterContextPlayerImpl(context *Context, src io.Reader) (*writerContextPlayerImpl, error) {
|
||||||
|
p := &writerContextPlayerImpl{
|
||||||
|
context: context,
|
||||||
|
src: src,
|
||||||
|
sampleRate: context.sampleRate,
|
||||||
|
volume: 1,
|
||||||
|
}
|
||||||
|
if seeker, ok := p.src.(io.Seeker); ok {
|
||||||
|
// Get the current position of the source.
|
||||||
|
pos, err := seeker.Seek(0, io.SeekCurrent)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
p.pos = pos
|
||||||
|
}
|
||||||
|
return p, nil
|
||||||
|
}
|
||||||
|
|
||||||
func (p *writerContextPlayerImpl) Close() error {
|
func (p *writerContextPlayerImpl) Close() error {
|
||||||
p.m.Lock()
|
p.m.Lock()
|
||||||
defer p.m.Unlock()
|
defer p.m.Unlock()
|
||||||
|
Loading…
Reference in New Issue
Block a user