mirror of https://bitbucket.org/ausocean/av.git
Add speakerMode checking for treatment.
This commit is contained in:
parent
ee7cb57fe5
commit
701b1f6c3a
|
@ -35,7 +35,6 @@ import (
|
||||||
"io"
|
"io"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"strconv"
|
"strconv"
|
||||||
"sync"
|
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"bitbucket.org/ausocean/av/container/mts"
|
"bitbucket.org/ausocean/av/container/mts"
|
||||||
|
@ -78,16 +77,17 @@ const (
|
||||||
i2cPort = 1
|
i2cPort = 1
|
||||||
)
|
)
|
||||||
|
|
||||||
// Treatment modes.
|
// Channel modes.
|
||||||
const (
|
const (
|
||||||
modePaused = "Paused"
|
modeStereo = "Stereo"
|
||||||
modeTreatment = "Play"
|
modeLeft = "LeftMono"
|
||||||
modeCheck = "Check"
|
modeRight = "RightMono"
|
||||||
|
modeMute = "Mute"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Variable map to send to netreceiver/vidgrind.
|
// Variable map to send to netreceiver/vidgrind.
|
||||||
var varMap = map[string]string{
|
var varMap = map[string]string{
|
||||||
"mode": "enum:Paused,Play,Check",
|
"speakerMode": "enum:Stereo,LeftMono,RightMono,Mute",
|
||||||
"AudioFilePath": "string",
|
"AudioFilePath": "string",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -131,6 +131,10 @@ func main() {
|
||||||
log.Fatal("could not initialise revid", "error", err)
|
log.Fatal("could not initialise revid", "error", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Play the audio (audio will play even whilst muted).
|
||||||
|
log.Debug("Playing the audio")
|
||||||
|
go playAudio(filePtr, log)
|
||||||
|
|
||||||
// Start the control loop.
|
// Start the control loop.
|
||||||
log.Debug("starting control loop")
|
log.Debug("starting control loop")
|
||||||
run(rv, ns, filePtr, log, netLog)
|
run(rv, ns, filePtr, log, netLog)
|
||||||
|
@ -140,9 +144,6 @@ func main() {
|
||||||
// if var changes, changes current mode (paused,audio playback or soundcheck)
|
// if var changes, changes current mode (paused,audio playback or soundcheck)
|
||||||
func run(rv *revid.Revid, ns *netsender.Sender, file *string, l logging.Logger, nl *netlogger.Logger) {
|
func run(rv *revid.Revid, ns *netsender.Sender, file *string, l logging.Logger, nl *netlogger.Logger) {
|
||||||
var (
|
var (
|
||||||
wg sync.WaitGroup
|
|
||||||
audioQuit chan struct{}
|
|
||||||
treating bool
|
|
||||||
vs int
|
vs int
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -207,50 +208,76 @@ func run(rv *revid.Revid, ns *netsender.Sender, file *string, l logging.Logger,
|
||||||
}
|
}
|
||||||
|
|
||||||
l.Debug("checking mode")
|
l.Debug("checking mode")
|
||||||
switch ns.Mode() {
|
setChannels(vars["speakerMode"], l)
|
||||||
case modePaused:
|
// l.Info("revid updated with new mode")
|
||||||
stopAudio(&wg, &treating, audioQuit)
|
|
||||||
l.Info("mode is Paused, stopping revid")
|
|
||||||
rv.Stop()
|
|
||||||
case modeTreatment:
|
|
||||||
l.Debug("checking audio file path")
|
|
||||||
f := vars["AudioFilePath"]
|
|
||||||
if f != "" && *file != f {
|
|
||||||
file = &f
|
|
||||||
l.Info("updated audio file path, stopping audio", "AudioFilePath", f)
|
|
||||||
stopAudio(&wg, &treating, audioQuit)
|
|
||||||
}
|
|
||||||
if !treating {
|
|
||||||
l.Info("starting audio treatment")
|
|
||||||
rv.Stop()
|
|
||||||
audioQuit = make(chan struct{})
|
|
||||||
treating = true
|
|
||||||
wg.Add(1)
|
|
||||||
go playAudio(file, audioQuit, &wg, l)
|
|
||||||
}
|
|
||||||
case modeCheck:
|
|
||||||
stopAudio(&wg, &treating, audioQuit)
|
|
||||||
l.Info("sound checking")
|
|
||||||
err = rv.Start()
|
|
||||||
if err != nil {
|
|
||||||
l.Error("could not start revid", "error", err)
|
|
||||||
ns.SetMode(modePaused, &vs)
|
|
||||||
sleep(ns, l)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
l.Warning("mode is not valid", "mode", ns.Mode())
|
|
||||||
|
|
||||||
}
|
|
||||||
l.Info("revid updated with new mode")
|
|
||||||
sleep(ns, l)
|
sleep(ns, l)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// playAudio is intended to be run as a routine. It will repeatedly play an audio file until
|
// setChannels handles the muting of one, both, or neither of the channels. It takes in speakerMode
|
||||||
// a signal is received to return. The entire audio file is played before the termination
|
// and sets the relevant volumes.
|
||||||
// signal chan is checked.
|
func setChannels(mode string, l logging.Logger) {
|
||||||
func playAudio(file *string, quit chan struct{}, wg *sync.WaitGroup, l logging.Logger) {
|
vols := ""
|
||||||
|
|
||||||
|
l.Info("mode is", "mode", mode)
|
||||||
|
|
||||||
|
// Set the volume of each channel.
|
||||||
|
switch mode {
|
||||||
|
case modeStereo:
|
||||||
|
vols = "100%,100%"
|
||||||
|
case modeLeft:
|
||||||
|
vols = "0%,100%"
|
||||||
|
case modeRight:
|
||||||
|
vols = "100%,0%"
|
||||||
|
case modeMute:
|
||||||
|
vols = "0%,0%"
|
||||||
|
default:
|
||||||
|
// If an invalid option has been chosen, keep the previous setting.
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create the command to change the channel volumes.
|
||||||
|
cmd := exec.Command("amixer", "sset", "Speaker", vols)
|
||||||
|
|
||||||
|
// Pipe the output to stdout and stderr.
|
||||||
|
outPipe, err := cmd.StdoutPipe()
|
||||||
|
if err != nil {
|
||||||
|
l.Error("failed to pipe stdout", "error", err)
|
||||||
|
}
|
||||||
|
errPipe, err := cmd.StderrPipe()
|
||||||
|
if err != nil {
|
||||||
|
l.Error("failed to pipe stderr", "error", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Execute the channel setting command.
|
||||||
|
err = cmd.Start()
|
||||||
|
if err != nil {
|
||||||
|
l.Error("channel setting failed", "error", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Copy any std out to a buffer for logging.
|
||||||
|
var outBuff bytes.Buffer
|
||||||
|
go func() {
|
||||||
|
_, err = io.Copy(&outBuff, outPipe)
|
||||||
|
if err != nil {
|
||||||
|
l.Error("failed to copy out pipe", "error", err)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
// Copy any std error to a buffer for logging.
|
||||||
|
var errBuff bytes.Buffer
|
||||||
|
go func() {
|
||||||
|
_, err = io.Copy(&errBuff, errPipe)
|
||||||
|
if err != nil {
|
||||||
|
l.Error("failed to copy error pipe", "error", err)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
l.Info("mode set to", "mode", mode)
|
||||||
|
}
|
||||||
|
|
||||||
|
// playAudio is intended to be run as a routine. It will continuously run even whilst muted.
|
||||||
|
func playAudio(file *string, l logging.Logger) {
|
||||||
var numPlays int
|
var numPlays int
|
||||||
for {
|
for {
|
||||||
cmd := exec.Command(audioCmd, *file)
|
cmd := exec.Command(audioCmd, *file)
|
||||||
|
@ -303,28 +330,7 @@ func playAudio(file *string, quit chan struct{}, wg *sync.WaitGroup, l logging.L
|
||||||
if errBuff.Len() != 0 {
|
if errBuff.Len() != 0 {
|
||||||
l.Error("errors from stderr", "stderr", string(errBuff.Bytes()))
|
l.Error("errors from stderr", "stderr", string(errBuff.Bytes()))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check for audio signal halt.
|
|
||||||
// TODO: work out better way to do this. Doing it this way means we have to wait for
|
|
||||||
// the audio file to finish playing.
|
|
||||||
select {
|
|
||||||
case <-quit:
|
|
||||||
wg.Done()
|
|
||||||
return
|
|
||||||
default:
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// stopAudio signals to the playAudio routine to terminate and then waits for it to
|
|
||||||
// do so.
|
|
||||||
func stopAudio(wg *sync.WaitGroup, treating *bool, signal chan struct{}) {
|
|
||||||
if !*treating {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
close(signal)
|
|
||||||
wg.Wait()
|
|
||||||
*treating = false
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// sleep uses a delay to halt the program based on the monitoring period
|
// sleep uses a delay to halt the program based on the monitoring period
|
||||||
|
|
Loading…
Reference in New Issue