2020-11-15 17:05:46 +00:00
|
|
|
package player
|
|
|
|
|
|
|
|
|
|
import (
|
|
|
|
|
"io"
|
|
|
|
|
|
|
|
|
|
"github.com/acaloiaro/di-tui/context"
|
|
|
|
|
"github.com/hajimehoshi/go-mp3"
|
|
|
|
|
"github.com/jfreymuth/pulse"
|
|
|
|
|
"github.com/jfreymuth/pulse/proto"
|
|
|
|
|
)
|
|
|
|
|
|
2023-06-02 00:04:01 +00:00
|
|
|
func Play(ctx *context.AppContext, stream io.ReadWriter, playbackLatency int) (err error) {
|
|
|
|
|
var d *mp3.Decoder
|
|
|
|
|
d, err = mp3.NewDecoder(stream)
|
2020-11-15 17:05:46 +00:00
|
|
|
if err != nil {
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
2023-06-02 00:04:01 +00:00
|
|
|
var c *pulse.Client
|
|
|
|
|
c, err = pulse.NewClient()
|
2020-11-15 17:05:46 +00:00
|
|
|
if err != nil {
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
defer c.Close()
|
|
|
|
|
|
2023-06-02 00:04:01 +00:00
|
|
|
ctx.Player, err = c.NewPlayback(
|
2020-11-15 17:05:46 +00:00
|
|
|
// proto.FormatInt16LE convinces `pulse` to expect 2 bytes per sample; the format that go-mp3 lays out bytes
|
|
|
|
|
pulse.NewReader(d, proto.FormatInt16LE),
|
|
|
|
|
pulse.PlaybackSampleRate(d.SampleRate()),
|
|
|
|
|
pulse.PlaybackStereo,
|
2023-06-02 00:04:01 +00:00
|
|
|
pulse.PlaybackLatency(float64(playbackLatency)),
|
2020-11-15 17:05:46 +00:00
|
|
|
)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
2023-06-02 00:04:01 +00:00
|
|
|
ctx.Player.Start()
|
|
|
|
|
ctx.Player.Drain()
|
|
|
|
|
|
|
|
|
|
err = ctx.Player.Error()
|
2020-11-15 17:05:46 +00:00
|
|
|
|
|
|
|
|
return
|
|
|
|
|
}
|
2023-06-02 00:04:01 +00:00
|
|
|
|
|
|
|
|
func Stop(ctx *context.AppContext) {
|
|
|
|
|
ctx.IsPlaying = false
|
2026-04-20 02:53:34 +00:00
|
|
|
if ctx.StreamCancel != nil {
|
|
|
|
|
ctx.StreamCancel()
|
|
|
|
|
}
|
2023-06-02 00:04:01 +00:00
|
|
|
if ctx.Player != nil {
|
2023-06-20 22:26:48 +00:00
|
|
|
ctx.AudioStream.Close()
|
2023-06-02 00:04:01 +00:00
|
|
|
ctx.Player.Close()
|
|
|
|
|
}
|
|
|
|
|
}
|