Make calls command concurrent, also update README
This commit is contained in:
parent
0f3684223a
commit
2bfc87a36d
3 changed files with 59 additions and 13 deletions
|
@ -1,3 +1,10 @@
|
||||||
# stillbox
|
# stillbox
|
||||||
|
|
||||||
A Golang scanner call server, with the Calls webapp.
|
A Golang scanner call server (`gordio`), with the Calls webapp.
|
||||||
|
|
||||||
|
**NOTE**
|
||||||
|
|
||||||
|
If this message is still here, the database schema *initial migration* and protobuf definitions are **still subject to change**.
|
||||||
|
|
||||||
|
Once `gordio` is actually usable (but not necessarily feature-complete), I will remove this note, and start using DB migrations and
|
||||||
|
protobuf best practices (i.e. not changing field numbers).
|
||||||
|
|
|
@ -2,6 +2,7 @@ package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"log"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"dynatron.me/x/go-minimp3"
|
"dynatron.me/x/go-minimp3"
|
||||||
|
@ -9,17 +10,24 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
type Player struct {
|
type Player struct {
|
||||||
|
c chan playReq
|
||||||
ctx *oto.Context
|
ctx *oto.Context
|
||||||
sampleRate int
|
sampleRate int
|
||||||
channels int
|
channels int
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewPlayer() *Player {
|
func NewPlayer() *Player {
|
||||||
p := &Player{}
|
p := &Player{
|
||||||
|
c: make(chan playReq, 256),
|
||||||
|
}
|
||||||
|
|
||||||
return p
|
return p
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (p *Player) Queue() int {
|
||||||
|
return len(p.c)
|
||||||
|
}
|
||||||
|
|
||||||
func (p *Player) initOto(samp, channels int) error {
|
func (p *Player) initOto(samp, channels int) error {
|
||||||
if samp != p.sampleRate || channels != p.channels {
|
if samp != p.sampleRate || channels != p.channels {
|
||||||
if p.ctx != nil {
|
if p.ctx != nil {
|
||||||
|
@ -64,15 +72,45 @@ func (p *Player) playMP3(audio []byte) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *Player) Play(audio []byte, mimeType string) error {
|
type playReq struct {
|
||||||
switch mimeType {
|
audio []byte
|
||||||
|
mimeType string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *Player) Play(audio []byte, mimeType string) {
|
||||||
|
p.c <- playReq{audio, mimeType}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *Player) play(req playReq) error {
|
||||||
|
switch req.mimeType {
|
||||||
case "audio/mpeg":
|
case "audio/mpeg":
|
||||||
return p.playMP3(audio)
|
return p.playMP3(req.audio)
|
||||||
case "audio/wav":
|
case "audio/wav":
|
||||||
panic("wav not implemented yet")
|
panic("wav not implemented yet")
|
||||||
default:
|
default:
|
||||||
return fmt.Errorf("unknown format %s", mimeType)
|
return fmt.Errorf("unknown format %s", req.mimeType)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *Player) Go(done <-chan struct{}) {
|
||||||
|
for {
|
||||||
|
select {
|
||||||
|
case <-done:
|
||||||
|
close(p.c)
|
||||||
|
p.ctx.Close()
|
||||||
|
return
|
||||||
|
case r, ok := <-p.c:
|
||||||
|
if !ok {
|
||||||
|
p.ctx.Close()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Printf("> [Q: %d]\r", p.Queue())
|
||||||
|
err := p.play(r)
|
||||||
|
fmt.Printf("\033[2K")
|
||||||
|
if err != nil {
|
||||||
|
log.Println(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -81,6 +81,10 @@ func main() {
|
||||||
log.Printf("connected")
|
log.Printf("connected")
|
||||||
|
|
||||||
done := make(chan struct{})
|
done := make(chan struct{})
|
||||||
|
playDone := make(chan struct{})
|
||||||
|
|
||||||
|
go play.Go(playDone)
|
||||||
|
defer close(playDone)
|
||||||
|
|
||||||
go func() {
|
go func() {
|
||||||
defer close(done)
|
defer close(done)
|
||||||
|
@ -101,11 +105,8 @@ func main() {
|
||||||
|
|
||||||
switch v := m.ToClientMessage.(type) {
|
switch v := m.ToClientMessage.(type) {
|
||||||
case *pb.Message_Call:
|
case *pb.Message_Call:
|
||||||
log.Printf("call tg %d", v.Call.Talkgroup)
|
log.Printf("call tg %d [Q: %d]", v.Call.Talkgroup, play.Queue())
|
||||||
err := play.Play(v.Call.Audio, v.Call.AudioType)
|
play.Play(v.Call.Audio, v.Call.AudioType)
|
||||||
if err != nil {
|
|
||||||
log.Println(err)
|
|
||||||
}
|
|
||||||
case *pb.Message_Notification:
|
case *pb.Message_Notification:
|
||||||
log.Println(v.Notification.Msg)
|
log.Println(v.Notification.Msg)
|
||||||
default:
|
default:
|
||||||
|
|
Loading…
Reference in a new issue