// // rhctl // // Copyright (C) 2009-2016 Christian Pointner // // This file is part of rhctl. // // rhctl is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // any later version. // // rhctl is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with rhctl. If not, see . // package main import ( "errors" "os" "sort" "strings" "time" "github.com/naoina/toml" ) type ConfigSwitchInputs []struct { Number SwitchInputNum `toml:"number"` Server string `toml:"server"` Channel string `toml:"channel"` } func (p ConfigSwitchInputs) Len() int { return len(p) } func (p ConfigSwitchInputs) Swap(i, j int) { p[i], p[j] = p[j], p[i] } func (p ConfigSwitchInputs) Less(i, j int) bool { return p[i].Number < p[j].Number } func (p ConfigSwitchInputs) GetNumber(server, channel string) (SwitchInputNum, error) { for _, i := range p { if i.Server == server && i.Channel == channel { return i.Number, nil } } return SwitchInputNum(0), errors.New("no such server/channel") } func (p ConfigSwitchInputs) GetServerAndChannel(in SwitchInputNum) (string, string, error) { for _, i := range p { if i.Number == in { return i.Server, i.Channel, nil } } return "", "", errors.New("no such input") } type Config struct { Audioswitch struct { Device string `toml:"dev"` Baudrate Baudrate `toml:"baud"` Timeout Duration `toml:"timeout"` Unit SwitchUnitID `toml:"unit"` Inputs ConfigSwitchInputs `toml:"inputs"` } Servers map[string]struct { Device string `toml:"dev"` Baudrate Baudrate `toml:"baud"` HeartbeatTimeout Duration `toml:"heartbeat_timeout"` HeartbeatThreshold uint `toml:"heartbeat_threshold"` } Timing struct { Settling struct { Awakening Duration `toml:"awakening"` SelectServer Duration `toml:"select_server"` UpdateStates Duration `toml:"update_states"` } StaleStates struct { CheckInterval Duration `toml:"check_interval"` MaxAge Duration `toml:"max_age"` } } Clients struct { Web struct { Address string `toml:"addr"` StaticDir string `toml:"static_files"` } Telnet struct { Address string `toml:"addr"` } } } type Duration struct { time.Duration } func (d *Duration) UnmarshalTOML(data []byte) (err error) { ds := strings.Trim(string(data), "\"") d.Duration, err = time.ParseDuration(ds) if err == nil && d.Duration < 0 { err = errors.New("negative durations are not allowed") } return } func ReadConfig(configfile string) (conf *Config, err error) { conf = &Config{} var f *os.File if f, err = os.Open(configfile); err != nil { return } defer f.Close() decoder := toml.NewDecoder(f) if err = decoder.Decode(conf); err != nil { return } sort.Sort(conf.Audioswitch.Inputs) for i := 1; i < len(conf.Audioswitch.Inputs); i++ { if conf.Audioswitch.Inputs[i].Number == conf.Audioswitch.Inputs[i-1].Number { return nil, errors.New("audioswitch port assignments must be unique") } } return }