From a41789a74683d3e99135cdd49fec12ab5f20c800 Mon Sep 17 00:00:00 2001 From: James Shubin Date: Wed, 8 Feb 2023 12:14:11 -0500 Subject: [PATCH] examples, lang: funcs: core: example: Update vumeter This patch moves to use the sox package instead of arecord for getting microphone data, and it also validates that both sox and rec and installed. We also add a standalone example. --- examples/lang/vumeter.mcl | 8 +++++ lang/funcs/core/example/vumeter_func.go | 48 +++++++++++++++++++++++-- 2 files changed, 54 insertions(+), 2 deletions(-) create mode 100644 examples/lang/vumeter.mcl diff --git a/examples/lang/vumeter.mcl b/examples/lang/vumeter.mcl new file mode 100644 index 00000000..cdbc1eb2 --- /dev/null +++ b/examples/lang/vumeter.mcl @@ -0,0 +1,8 @@ +import "example" + +$vumeter = example.vumeter("====", 10, 0.9) + +file "/tmp/vumeter" { + state => $const.res.file.state.exists, + content => $vumeter, +} diff --git a/lang/funcs/core/example/vumeter_func.go b/lang/funcs/core/example/vumeter_func.go index dde0bea4..c4bdff95 100644 --- a/lang/funcs/core/example/vumeter_func.go +++ b/lang/funcs/core/example/vumeter_func.go @@ -18,9 +18,11 @@ package coreexample import ( + "context" "fmt" "math" "os/exec" + "path/filepath" "strconv" "strings" "sync" @@ -63,6 +65,43 @@ func (obj *VUMeterFunc) ArgGen(index int) (string, error) { // Validate makes sure we've built our struct properly. It is usually unused for // normal functions that users can use directly. func (obj *VUMeterFunc) Validate() error { + check := func(binary string) error { + args := []string{"--help"} + + prog := fmt.Sprintf("%s %s", binary, strings.Join(args, " ")) + + //obj.init.Logf("running: %s", prog) + + p, err := filepath.EvalSymlinks(binary) + if err != nil { + return err + } + // TODO: do we need to do the ^C handling? + // XXX: is the ^C context cancellation propagating into this correctly? + cmd := exec.CommandContext(context.TODO(), p, args...) + cmd.Dir = "" + cmd.Env = []string{} + cmd.SysProcAttr = &syscall.SysProcAttr{ + Setpgid: true, + Pgid: 0, + } + + if err := cmd.Run(); err != nil { + if e, ok := err.(*exec.Error); ok && e.Err == exec.ErrNotFound { + return fmt.Errorf("is %s in your $PATH ?", binary) + } + + return errwrap.Wrapf(err, "error running: %s", prog) + } + return nil + } + + // if rec is a symlink, this will error without the above EvalSymlinks! + for _, x := range []string{"/usr/bin/rec", "/usr/bin/sox"} { + if err := check(x); err != nil { + return err + } + } return nil } @@ -121,9 +160,14 @@ func (obj *VUMeterFunc) Stream() error { continue // still waiting for input values } + // record for one second to a shared memory file + // rec /dev/shm/mgmt_rec.wav trim 0 1 2>/dev/null + args1 := []string{"/dev/shm/mgmt_rec.wav", "trim", "0", "1"} + cmd1 := exec.Command("/usr/bin/rec", args1...) + // XXX: arecord stopped working on newer linux... // arecord -d 1 /dev/shm/mgmt_rec.wav 2>/dev/null - args1 := []string{"-d", "1", "/dev/shm/mgmt_rec.wav"} - cmd1 := exec.Command("/usr/bin/arecord", args1...) + //args1 := []string{"-d", "1", "/dev/shm/mgmt_rec.wav"} + //cmd1 := exec.Command("/usr/bin/arecord", args1...) cmd1.SysProcAttr = &syscall.SysProcAttr{ Setpgid: true, Pgid: 0,