80 lines
1.2 KiB
Go
80 lines
1.2 KiB
Go
package snapcast
|
|
|
|
import (
|
|
"context"
|
|
"io"
|
|
"log"
|
|
"os"
|
|
"os/exec"
|
|
"strconv"
|
|
"sync"
|
|
|
|
"github.com/gopxl/beep"
|
|
)
|
|
|
|
type Stream struct {
|
|
sync.Mutex
|
|
|
|
Out io.ReadCloser
|
|
Cancel context.CancelFunc
|
|
Cmd *exec.Cmd
|
|
|
|
f beep.Format
|
|
buf []byte
|
|
}
|
|
|
|
func New(host string, port int) (ff beep.Streamer, err error) {
|
|
st := new(Stream)
|
|
ctx, cancel := context.WithCancel(context.Background())
|
|
st.Cancel = cancel
|
|
|
|
st.Cmd = exec.CommandContext(
|
|
ctx,
|
|
"/usr/bin/snapclient",
|
|
"-h", host,
|
|
"-p", strconv.Itoa(port),
|
|
"--player", "file:filename=stderr",
|
|
"--logfilter", "*:error",
|
|
)
|
|
|
|
st.Cmd.Stdout = os.Stdin
|
|
|
|
st.Out, err = st.Cmd.StderrPipe()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
err = st.Cmd.Start()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
st.buf = make([]byte, 4)
|
|
st.f = beep.Format{
|
|
SampleRate: beep.SampleRate(48000),
|
|
NumChannels: 2,
|
|
Precision: 2,
|
|
}
|
|
|
|
return st, nil
|
|
}
|
|
|
|
func (d *Stream) Stream(samples [][2]float64) (n int, ok bool) {
|
|
for i := range samples {
|
|
_, err := d.Out.Read(d.buf)
|
|
if err != nil {
|
|
log.Println(err)
|
|
ok = false
|
|
break
|
|
}
|
|
samples[i], _ = d.f.DecodeSigned(d.buf)
|
|
ok = true
|
|
}
|
|
|
|
return len(samples), ok
|
|
}
|
|
|
|
func (d *Stream) Err() error {
|
|
return nil
|
|
}
|