205 lines
4.8 KiB
Go
205 lines
4.8 KiB
Go
package main
|
|
|
|
import _ "net/http/pprof"
|
|
import (
|
|
"bufio"
|
|
"fmt"
|
|
"io"
|
|
"log"
|
|
"net/http"
|
|
"os"
|
|
"os/exec"
|
|
"strings"
|
|
"syscall"
|
|
//"gopkg.in/alessio/shellescape.v1"
|
|
//"github.com/google/shlex"
|
|
"crypto/tls"
|
|
"flag"
|
|
"github.com/alessio/shellescape"
|
|
"git.stormux.org/storm/barnard/config"
|
|
|
|
"git.stormux.org/storm/barnard/gumble/gumble"
|
|
_ "git.stormux.org/storm/barnard/gumble/opus"
|
|
"git.stormux.org/storm/barnard/uiterm"
|
|
"git.stormux.org/storm/barnard/gumble/go-openal/openal"
|
|
)
|
|
|
|
func show_devs(name string, args []string) {
|
|
if args == nil {
|
|
fmt.Printf("no items for %s\n", name)
|
|
}
|
|
fmt.Printf("%s\n", name)
|
|
for i := 0; i < len(args); i++ {
|
|
fmt.Printf("%s\n", args[i])
|
|
}
|
|
}
|
|
|
|
func do_list_devices() {
|
|
odevs := openal.GetStrings(openal.AllDevicesSpecifier)
|
|
if odevs != nil && len(odevs) > 0 {
|
|
show_devs("All outputs:", odevs)
|
|
} else {
|
|
odevs = openal.GetStrings(openal.DeviceSpecifier)
|
|
show_devs("All outputs:", odevs)
|
|
}
|
|
idevs := openal.GetStrings(openal.CaptureDeviceSpecifier)
|
|
show_devs("Inputs:", idevs)
|
|
}
|
|
|
|
func setup_notify_runner(notify_command string) chan []string {
|
|
t := make(chan []string)
|
|
var do_nothing = false
|
|
var err error
|
|
if err != nil {
|
|
}
|
|
if notify_command == "" {
|
|
do_nothing = true
|
|
}
|
|
go func(events chan []string, cmd_template string, dummy bool) {
|
|
for {
|
|
event := <-events
|
|
if !dummy {
|
|
t := string(cmd_template)
|
|
t = strings.ReplaceAll(t, "%event", shellescape.Quote(event[0]))
|
|
t = strings.ReplaceAll(t, "%who", shellescape.Quote(event[1]))
|
|
t = strings.ReplaceAll(t, "%what", shellescape.Quote(event[2]))
|
|
cmd := "/bin/sh"
|
|
args := []string{"-c", t}
|
|
x := exec.Command(cmd, args...)
|
|
x.Run()
|
|
} //if we actually have a command to run
|
|
} //for
|
|
}(t, notify_command, do_nothing)
|
|
return t
|
|
}
|
|
|
|
func setup_fifo(fn string) (chan string, error) {
|
|
t := make(chan string)
|
|
if fn == "" {
|
|
return t, nil
|
|
}
|
|
os.Remove(fn)
|
|
err := syscall.Mkfifo(fn, 0600)
|
|
if err != nil {
|
|
return t, err
|
|
}
|
|
file, err := os.OpenFile(fn, os.O_RDWR, os.ModeNamedPipe)
|
|
if err != nil {
|
|
return t, err
|
|
}
|
|
go func(fh io.Reader, out chan string) {
|
|
reader := bufio.NewReader(fh)
|
|
for {
|
|
line, err := reader.ReadBytes('\n')
|
|
if err == nil {
|
|
out <- strings.TrimSpace(string(line))
|
|
}
|
|
}
|
|
}(file, t)
|
|
return t, nil
|
|
}
|
|
|
|
func main() {
|
|
// Command line flags
|
|
server := flag.String("server", "localhost:64738", "the server to connect to")
|
|
username := flag.String("username", "", "the username of the client")
|
|
password := flag.String("password", "", "the password of the server")
|
|
insecure := flag.Bool("insecure", false, "skip server certificate verification")
|
|
certificate := flag.String("certificate", "", "PEM encoded certificate and private key")
|
|
cfgfn := flag.String("config", "~/.barnard.yaml", "Path to YAML formatted configuration file")
|
|
list_devices := flag.Bool("list_devices", false, "do not connect; instead, list available audio devices and exit")
|
|
fifo := flag.String("fifo", "", "path of a FIFO from which to read commands")
|
|
serverSet := false
|
|
usernameSet := false
|
|
buffers := flag.Int("buffers", 16, "number of audio buffers to use")
|
|
profile := flag.Bool("profile", false, "add http server to serve profiles")
|
|
|
|
flag.Parse()
|
|
|
|
if *profile == true {
|
|
go func() {
|
|
log.Println(http.ListenAndServe("localhost:6060", nil))
|
|
}()
|
|
}
|
|
|
|
userConfig := config.NewConfig(cfgfn)
|
|
|
|
flag.CommandLine.Visit(func(theFlag *flag.Flag) {
|
|
switch theFlag.Name {
|
|
case "server":
|
|
serverSet = true
|
|
case "username":
|
|
usernameSet = true
|
|
}
|
|
})
|
|
|
|
if !serverSet {
|
|
server = userConfig.GetDefaultServer()
|
|
}
|
|
if !usernameSet {
|
|
username = userConfig.GetUsername()
|
|
}
|
|
|
|
if os.Getenv("ALSOFT_LOGLEVEL") == "" {
|
|
os.Setenv("ALSOFT_LOGLEVEL", "0")
|
|
}
|
|
|
|
if *list_devices {
|
|
do_list_devices()
|
|
os.Exit(0)
|
|
}
|
|
|
|
if !strings.Contains(*server, ":") {
|
|
*server = (*server + ":64738")
|
|
}
|
|
|
|
// Initialize
|
|
b := Barnard{
|
|
Config: gumble.NewConfig(),
|
|
UserConfig: userConfig,
|
|
Address: *server,
|
|
MutedChannels: make(map[uint32]bool),
|
|
}
|
|
b.Config.Buffers = *buffers
|
|
|
|
b.Hotkeys = b.UserConfig.GetHotkeys()
|
|
b.UserConfig.SaveConfig()
|
|
b.Config.Username = *username
|
|
b.Config.Password = *password
|
|
|
|
if *insecure {
|
|
b.TLSConfig.InsecureSkipVerify = true
|
|
}
|
|
if *certificate != "" {
|
|
cert, err := tls.LoadX509KeyPair(*certificate, *certificate)
|
|
if err != nil {
|
|
fmt.Fprintf(os.Stderr, "%s\n", err)
|
|
os.Exit(1)
|
|
}
|
|
b.TLSConfig.Certificates = append(b.TLSConfig.Certificates, cert)
|
|
}
|
|
|
|
reader, err := setup_fifo(*fifo)
|
|
if err != nil {
|
|
b.exitMessage = err.Error()
|
|
b.exitStatus = 1
|
|
handle_error(b)
|
|
}
|
|
b.notifyChannel = setup_notify_runner(*b.UserConfig.GetNotifyCommand())
|
|
b.Ui = uiterm.New(&b)
|
|
b.Ui.Run(reader)
|
|
handle_error(b)
|
|
}
|
|
|
|
func handle_raw_error(e error) {
|
|
fmt.Fprintf(os.Stderr, "%s\n", e.Error())
|
|
os.Exit(1)
|
|
}
|
|
|
|
func handle_error(b Barnard) {
|
|
if b.exitMessage != "" {
|
|
fmt.Fprintf(os.Stderr, "%s\n", b.exitMessage)
|
|
}
|
|
os.Exit(b.exitStatus)
|
|
}
|