diff --git a/cmd/i3status-go/main.go b/cmd/i3status-go/main.go index 22c8fc7..17e7a2a 100644 --- a/cmd/i3status-go/main.go +++ b/cmd/i3status-go/main.go @@ -25,20 +25,25 @@ func main() { log.Panicf("Unable to read config: %s", err) } - Conf.UpdateReady = make(chan bool) - Conf.MsgChan = make(chan []lib.I3BarOutBlock, 64) - Conf.SigChan = make(chan os.Signal, 1) - Conf.BatteryString = "⚡ ??% •" - Conf.ClockTime = "Thu, 1 Jan 1970 1:00" - Conf.IfStatus = "" - Conf.VPNStatus = "" - Conf.Memory.Shared = 0 - Conf.Memory.Usedpct = 0 - Conf.Memory.Swap = 0 - Conf.La = "-1" + Conf.Channels.UpdateReady = make(chan bool) + Conf.Channels.SVPAHandlerChan = make(chan lib.ClickEvent, 256) + Conf.Channels.MsgChan = make(chan []lib.I3BarOutBlock, 64) + Conf.Channels.SigChan = make(chan os.Signal, 1) + Conf.Channels.RunChan = make(chan []string, 128) + Conf.Values.PrintOutput = true + Conf.Values.BatteryString = "⚡ ??% •" + Conf.Values.ClockTime = "Thu, 1 Jan 1970 1:00" + Conf.Values.IfStatus = "" + Conf.Values.VPNStatus = "" + Conf.Values.Memory.Shared = 0 + Conf.Values.Memory.Usedpct = 0 + Conf.Values.Memory.Swap = 0 + Conf.Values.La = "-1" + // Conf.Values.PA + Conf.Values.SoundVolume = "🔊:0%" // TODO: Проставить дефолтные значения для глобальных переменных модулей. - Batt := fmt.Sprintf( + Conf.Values.BatteryString = fmt.Sprintf( "%s", Conf.Battery.Color, Conf.Battery.Background, @@ -47,7 +52,7 @@ func main() { Conf.Battery.Symbol, ) - Batt += fmt.Sprintf( + Conf.Values.BatteryString += fmt.Sprintf( " ??%% •", Conf.Battery.Color, Conf.Battery.Background, @@ -55,7 +60,7 @@ func main() { Conf.Battery.FontSize, ) - SoundVolume := fmt.Sprintf( + Conf.Values.SoundVolume = fmt.Sprintf( "🔊", Conf.SimpleVolumePa.Color, Conf.SimpleVolumePa.Background, @@ -63,7 +68,7 @@ func main() { Conf.SimpleVolumePa.SymbolFontSize, ) - SoundVolume += fmt.Sprintf( + Conf.Values.SoundVolume += fmt.Sprintf( ":0%%", Conf.SimpleVolumePa.Color, Conf.SimpleVolumePa.Background, @@ -71,7 +76,7 @@ func main() { Conf.SimpleVolumePa.FontSize, ) - Clock := fmt.Sprintf( + Conf.Values.ClockTime = fmt.Sprintf( "Thu, 1 Jan 1970 1:00", Conf.Clock.Color, Conf.Clock.Background, @@ -91,7 +96,7 @@ func main() { // Kick signal handler go Conf.SigHandler() - signal.Notify(Conf.SigChan, + signal.Notify(Conf.Channels.SigChan, syscall.SIGUSR1, syscall.SIGUSR2, syscall.SIGQUIT, @@ -131,7 +136,7 @@ func main() { } if Conf.Cron.Enabled { - go lib.RunCron() + go Conf.RunCron() } if Conf.Vpn.Enabled { @@ -156,7 +161,7 @@ func main() { fmt.Println("[ [],") for { - if <-Conf.UpdateReady { + if <-Conf.Channels.UpdateReady { // Actually build json struct, marshal it and print result var j []lib.I3BarOutBlock @@ -235,7 +240,7 @@ func main() { Conf.CPUTemp.Background, Conf.CPUTemp.Font, Conf.CPUTemp.FontSize, - Conf.CPUTemperature, + Conf.Values.CPUTemperature, ) if Conf.CPUTemp.Separator.Right.Enabled { @@ -279,9 +284,9 @@ func main() { Conf.Mem.Background, Conf.Mem.Font, Conf.Mem.FontSize, - Conf.Memory.Usedpct, - Conf.Memory.Shared, - Conf.Memory.Swap, + Conf.Values.Memory.Usedpct, + Conf.Values.Memory.Shared, + Conf.Values.Memory.Swap, ) } else { b.FullText += fmt.Sprintf( @@ -290,8 +295,8 @@ func main() { Conf.Mem.Background, Conf.Mem.Font, Conf.Mem.FontSize, - Conf.Memory.Usedpct, - Conf.Memory.Shared, + Conf.Values.Memory.Usedpct, + Conf.Values.Memory.Shared, ) } @@ -335,7 +340,7 @@ func main() { Conf.LA.Background, Conf.LA.Font, Conf.LA.FontSize, - Conf.La, + Conf.Values.La, ) if Conf.LA.Separator.Right.Enabled { @@ -378,7 +383,7 @@ func main() { Conf.NetIf.Background, Conf.NetIf.Font, Conf.NetIf.FontSize, - Conf.IfStatus, + Conf.Values.IfStatus, ) if Conf.NetIf.Separator.Right.Enabled { @@ -421,7 +426,7 @@ func main() { Conf.Vpn.Background, Conf.Vpn.Font, Conf.Vpn.FontSize, - Conf.VPNStatus, + Conf.Values.VPNStatus, ) if Conf.Vpn.Separator.Right.Enabled { @@ -458,7 +463,7 @@ func main() { ) } - b.FullText += Conf.BatteryString + b.FullText += Conf.Values.BatteryString if Conf.Battery.Separator.Right.Enabled { b.FullText += fmt.Sprintf( @@ -496,7 +501,7 @@ func main() { } // Pango format is already applied in plugin src. - b.FullText += SoundVolume + b.FullText += Conf.Values.SoundVolume if Conf.SimpleVolumePa.Separator.Right.Enabled { b.FullText += fmt.Sprintf( @@ -539,7 +544,7 @@ func main() { Conf.Clock.Background, Conf.Clock.Font, Conf.Clock.FontSize, - Clock, + Conf.Values.ClockTime, ) if Conf.Clock.Separator.Right.Enabled { @@ -559,16 +564,16 @@ func main() { j = append(j, b) } - if Conf.PrintOutput && len(j) > 0 { - Conf.MsgChan <- j + if Conf.Values.PrintOutput && len(j) > 0 { + Conf.Channels.MsgChan <- j } } } } // PrintToI3bar prints info to stdout according to ipc docs (https://i3wm.org/docs/i3bar-protocol.html) -func PrintToI3bar(c lib.MyConfig) { - for message := range c.MsgChan { +func PrintToI3bar(c *lib.MyConfig) { + for message := range c.Channels.MsgChan { // we do not need to html-encode output, json.Marshal does this forcefully, so invent our own Marshal buf := new(bytes.Buffer) encoder := json.NewEncoder(buf) diff --git a/internal/lib/batteries.go b/internal/lib/batteries.go index 42e3d17..f4f6a31 100644 --- a/internal/lib/batteries.go +++ b/internal/lib/batteries.go @@ -9,7 +9,7 @@ import ( ) // UpdateBatteryInfo updates info about battery charge. -func (c MyConfig) UpdateBatteryInfo() { +func (c *MyConfig) UpdateBatteryInfo() { var ( ch int status string @@ -22,11 +22,11 @@ func (c MyConfig) UpdateBatteryInfo() { if err != nil { Batts = fmt.Sprintf( "%s no batt", - Conf.Battery.SymbolFont, - Conf.Battery.SymbolFontSize, - Conf.Battery.Symbol, - Conf.Battery.Font, - Conf.Battery.FontSize, + c.Battery.SymbolFont, + c.Battery.SymbolFontSize, + c.Battery.Symbol, + c.Battery.Font, + c.Battery.FontSize, ) } else { var ( @@ -52,85 +52,85 @@ func (c MyConfig) UpdateBatteryInfo() { switch { case ch > 85: - if Conf.Battery.ChargeColor.Full == "" { + if c.Battery.ChargeColor.Full == "" { chStr = fmt.Sprintf( "% 3d%%", - Conf.Battery.Color, - Conf.Battery.Background, - Conf.Battery.Font, - Conf.Battery.FontSize, + c.Battery.Color, + c.Battery.Background, + c.Battery.Font, + c.Battery.FontSize, ch, ) } else { chStr = fmt.Sprintf( `% 3d%%`, - Conf.Battery.ChargeColor.Full, - Conf.Battery.Background, - Conf.Battery.Font, - Conf.Battery.FontSize, + c.Battery.ChargeColor.Full, + c.Battery.Background, + c.Battery.Font, + c.Battery.FontSize, ch, ) } case ch < 85 && ch > 40: - if Conf.Battery.ChargeColor.AlmostFull == "" { + if c.Battery.ChargeColor.AlmostFull == "" { chStr = fmt.Sprintf( "% 3d%%", - Conf.Battery.Color, - Conf.Battery.Background, - Conf.Battery.Font, - Conf.Battery.FontSize, + c.Battery.Color, + c.Battery.Background, + c.Battery.Font, + c.Battery.FontSize, ch, ) } else { chStr = fmt.Sprintf( `% 3d%%`, - Conf.Battery.ChargeColor.AlmostFull, - Conf.Battery.Background, - Conf.Battery.Font, - Conf.Battery.FontSize, + c.Battery.ChargeColor.AlmostFull, + c.Battery.Background, + c.Battery.Font, + c.Battery.FontSize, ch, ) } case ch <= 40 && ch >= 10: - if Conf.Battery.ChargeColor.AlmostEmpty == "" { + if c.Battery.ChargeColor.AlmostEmpty == "" { chStr = fmt.Sprintf( "% 3d%%", - Conf.Battery.Color, - Conf.Battery.Background, - Conf.Battery.Font, - Conf.Battery.FontSize, + c.Battery.Color, + c.Battery.Background, + c.Battery.Font, + c.Battery.FontSize, ch, ) } else { chStr = fmt.Sprintf( `% 3d%%`, - Conf.Battery.ChargeColor.AlmostEmpty, - Conf.Battery.Background, - Conf.Battery.Font, - Conf.Battery.FontSize, + c.Battery.ChargeColor.AlmostEmpty, + c.Battery.Background, + c.Battery.Font, + c.Battery.FontSize, ch, ) } case ch < 10: - if Conf.Battery.ChargeColor.Empty == "" { + if c.Battery.ChargeColor.Empty == "" { chStr = fmt.Sprintf( "% 3d%%", - Conf.Battery.Color, - Conf.Battery.Background, - Conf.Battery.Font, - Conf.Battery.FontSize, + c.Battery.Color, + c.Battery.Background, + c.Battery.Font, + c.Battery.FontSize, ch, ) } else { chStr = fmt.Sprintf( `% 3d%%`, - Conf.Battery.ChargeColor.Empty, - Conf.Battery.Background, - Conf.Battery.Font, - Conf.Battery.FontSize, + c.Battery.ChargeColor.Empty, + c.Battery.Background, + c.Battery.Font, + c.Battery.FontSize, ch, ) } @@ -138,21 +138,21 @@ func (c MyConfig) UpdateBatteryInfo() { battsInfo += fmt.Sprintf( "%sB%d %s %s", - Conf.Battery.Color, - Conf.Battery.Background, - Conf.Battery.SymbolFont, - Conf.Battery.SymbolFontSize, - Conf.Battery.Symbol, - Conf.Battery.Color, - Conf.Battery.Background, - Conf.Battery.Font, - Conf.Battery.FontSize, + c.Battery.Color, + c.Battery.Background, + c.Battery.SymbolFont, + c.Battery.SymbolFontSize, + c.Battery.Symbol, + c.Battery.Color, + c.Battery.Background, + c.Battery.Font, + c.Battery.FontSize, i, chStr, - Conf.Battery.Color, - Conf.Battery.Background, - Conf.Battery.Font, - Conf.Battery.FontSize, + c.Battery.Color, + c.Battery.Background, + c.Battery.Font, + c.Battery.FontSize, status, ) } @@ -162,9 +162,9 @@ func (c MyConfig) UpdateBatteryInfo() { } } - if c.BatteryString == Batts { - c.BatteryString = Batts - c.UpdateReady <- true + if c.Values.BatteryString == Batts { + c.Values.BatteryString = Batts + c.Channels.UpdateReady <- true } time.Sleep(5 * time.Second) diff --git a/internal/lib/clock.go b/internal/lib/clock.go index 4f9b986..97042fc 100644 --- a/internal/lib/clock.go +++ b/internal/lib/clock.go @@ -6,7 +6,7 @@ import ( ) // UpdateClock get and updates (on i3bar) info about system clock. -func (c MyConfig) UpdateClock() { +func (c *MyConfig) UpdateClock() { for { currentTime := time.Now() hours, minutes, _ := currentTime.Clock() @@ -17,9 +17,9 @@ func (c MyConfig) UpdateClock() { myclock := fmt.Sprintf(" %s, %d %s %d % 2d:%02d ", rdow[dow], day, rmonth[month-1], year, hours, minutes) - if myclock != c.ClockTime { - c.ClockTime = myclock - c.UpdateReady <- true + if myclock != c.Values.ClockTime { + c.Values.ClockTime = myclock + c.Channels.UpdateReady <- true } time.Sleep(1 * time.Second) diff --git a/internal/lib/config.go b/internal/lib/config.go index 32979b0..87ff9bd 100644 --- a/internal/lib/config.go +++ b/internal/lib/config.go @@ -11,6 +11,7 @@ import ( "github.com/adrg/xdg" "github.com/hjson/hjson-go" + p "github.com/mafik/pulseaudio" ) // I3BarOutBlock is structure element for I3BarOut, it represents i3bar output json block format. @@ -57,17 +58,26 @@ type Separator struct { } type MyConfig struct { - UpdateReady chan bool - PrintOutput bool - MsgChan chan []I3BarOutBlock - SigChan chan os.Signal - CPUTemperature int64 - BatteryString string - ClockTime string - IfStatus string - VPNStatus string - Memory Mem - La string + Values struct { + PrintOutput bool + CPUTemperature int64 + BatteryString string + ClockTime string + IfStatus string + VPNStatus string + Memory Mem + La string + PA *p.Client + SoundVolume string + } + + Channels struct { + UpdateReady chan bool + MsgChan chan []I3BarOutBlock + SigChan chan os.Signal + SVPAHandlerChan chan ClickEvent + RunChan chan []string + } // Default text color Color string `json:"color,omitempty"` @@ -240,15 +250,12 @@ type MyConfig struct { } `json:"apps,omitempty"` } -// Conf global variable with application config. -var Conf MyConfig - // readConf reads and validates config if config does not exist, it puts default config to the same dir where i3 config // is located. -func ReadConf(DefaultConfig []byte) (MyConfig, error) { +func ReadConf(DefaultConfig []byte) (*MyConfig, error) { var ( path string - config MyConfig + config *MyConfig err error buf []byte ) @@ -294,7 +301,7 @@ func ReadConf(DefaultConfig []byte) (MyConfig, error) { // We interested in struct as output product: so we parse config to intermediate map then marshal it to json and // then produced json unmarshal to struct. Not very effective way, but in app lifetime it happens only once. var ( - sampleConfig MyConfig + sampleConfig *MyConfig tmp map[string]interface{} ) @@ -1527,19 +1534,19 @@ func ReadConf(DefaultConfig []byte) (MyConfig, error) { } if app.Color == "" { - app.Color = Conf.Color + app.Color = sampleConfig.Color } if app.Background == "" { - app.Background = Conf.Background + app.Background = sampleConfig.Background } if app.Border == "" { - app.Border = Conf.Color + app.Border = sampleConfig.Color } if app.BorderActive == "" { - app.BorderActive = Conf.Color + app.BorderActive = sampleConfig.Color } if app.FullText == "" { diff --git a/internal/lib/cputemp.go b/internal/lib/cputemp.go index 306939e..e4290c0 100644 --- a/internal/lib/cputemp.go +++ b/internal/lib/cputemp.go @@ -9,8 +9,8 @@ import ( ) // UpdateCPUTemperature gets and updates average CPU cores temperature. -func (c MyConfig) UpdateCPUTemperature() { - n := len(Conf.CPUTemp.File) +func (c *MyConfig) UpdateCPUTemperature() { + n := len(c.CPUTemp.File) for { var ( @@ -19,7 +19,7 @@ func (c MyConfig) UpdateCPUTemperature() { tAvg int64 ) - for i, filename := range Conf.CPUTemp.File { + for i, filename := range c.CPUTemp.File { file, err := os.Open(filename) if err != nil { @@ -67,9 +67,9 @@ func (c MyConfig) UpdateCPUTemperature() { tAvg = tSum / int64(len(temperature)) } - if c.CPUTemperature != tAvg { - c.CPUTemperature = tAvg - c.UpdateReady <- true + if c.Values.CPUTemperature != tAvg { + c.Values.CPUTemperature = tAvg + c.Channels.UpdateReady <- true } time.Sleep(3 * time.Second) diff --git a/internal/lib/cron.go b/internal/lib/cron.go index 2cbce41..0943814 100644 --- a/internal/lib/cron.go +++ b/internal/lib/cron.go @@ -10,7 +10,7 @@ import ( var myCron gocron.Scheduler // RunCron parses config part, related to cron tasks and kicks cron to run. -func RunCron() { +func (c MyConfig) RunCron() { var err error myCron, err = gocron.NewScheduler() @@ -21,14 +21,14 @@ func RunCron() { return } - for _, job := range Conf.Cron.Tasks { + for _, job := range c.Cron.Tasks { _, err := myCron.NewJob( gocron.CronJob(job.Time, false), gocron.NewTask( // Сука, просто заспавнить бинарь, ну почему это надо делать через жопу-то? any( func() bool { - RunChan <- job.Cmd + c.Channels.RunChan <- job.Cmd return true }, diff --git a/internal/lib/i3.go b/internal/lib/i3.go index 83d50aa..a6c0a18 100644 --- a/internal/lib/i3.go +++ b/internal/lib/i3.go @@ -18,7 +18,7 @@ type WinList struct { var WL WinList // UpdateI3WinList subsribes to all window-related events and send them to I3EventParser() for more detailed parsing. -func (c MyConfig) UpdateI3WinList() { +func (c *MyConfig) UpdateI3WinList() { // TODO: Здесь получить начальный список окон, управляемых i3wm (через GetTree()) и сложить их атрибутику в переменную WL Tree, err := i3.GetTree() @@ -39,7 +39,7 @@ func (c MyConfig) UpdateI3WinList() { } // I3EventParser parses i3wm events and updates WL (aka Windows List). -func (c MyConfig) I3EventParser(e *i3.WindowEvent) { +func (c *MyConfig) I3EventParser(e *i3.WindowEvent) { switch e.Change { case "new": var ( @@ -68,7 +68,7 @@ func (c MyConfig) I3EventParser(e *i3.WindowEvent) { count++ WL.Instance.Set(e.Container.WindowProperties.Instance, count) - c.UpdateReady <- true + c.Channels.UpdateReady <- true case "close": countI, exist := WL.Class.Get(e.Container.WindowProperties.Class) @@ -99,7 +99,7 @@ func (c MyConfig) I3EventParser(e *i3.WindowEvent) { } } - c.UpdateReady <- true + c.Channels.UpdateReady <- true } } @@ -210,7 +210,7 @@ func FindWindowClass(regexpStr string) bool { } // ExtractProps fills WL stricture collections with instance name and class name of given node (x11, that is). -func (c MyConfig) ExtractProps(n *i3.Node) { +func (c *MyConfig) ExtractProps(n *i3.Node) { var e i3.WindowEvent e.Change = "new" e.Container = *n diff --git a/internal/lib/ifmon.go b/internal/lib/ifmon.go index a1434d3..d975d38 100644 --- a/internal/lib/ifmon.go +++ b/internal/lib/ifmon.go @@ -9,15 +9,12 @@ import ( "time" ) -// IfStatus global var conaining cumulative status of all monitored net intefaces. -var IfStatus string - // UpdateIfStatus updates network interfaces status for i3bar. -func (c MyConfig) UpdateIfStatus() { +func (c *MyConfig) UpdateIfStatus() { for { var statusSum string - for _, item := range Conf.NetIf.If { + for _, item := range c.NetIf.If { var ( name = item.Name ) @@ -35,10 +32,10 @@ func (c MyConfig) UpdateIfStatus() { } else { switch strings.TrimSpace(string(operstate)) { case "up": - StatusStr := fmt.Sprintf("⍋", Conf.NetIf.UpColor) + StatusStr := fmt.Sprintf("⍋", c.NetIf.UpColor) operstate = []byte(StatusStr) case "down": - statusStr := fmt.Sprintf("⍒", Conf.NetIf.DownColor) + statusStr := fmt.Sprintf("⍒", c.NetIf.DownColor) operstate = []byte(statusStr) default: operstate = []byte(`?`) @@ -52,9 +49,9 @@ func (c MyConfig) UpdateIfStatus() { statusSum += fmt.Sprintf("%s:%s", name, operstate) } - if c.IfStatus != statusSum { - c.IfStatus = statusSum - c.UpdateReady <- true + if c.Values.IfStatus != statusSum { + c.Values.IfStatus = statusSum + c.Channels.UpdateReady <- true } time.Sleep(3 * time.Second) diff --git a/internal/lib/la.go b/internal/lib/la.go index 6d8308e..88c7456 100644 --- a/internal/lib/la.go +++ b/internal/lib/la.go @@ -8,15 +8,15 @@ import ( ) // UpdateLaStats вытаскивает показание LA за последнюю минуту. -func (c MyConfig) UpdateLaStats() { +func (c *MyConfig) UpdateLaStats() { for { l, _ := load.Avg() lav := fmt.Sprintf("%.2f", l.Load1) - if c.La != lav { - c.La = lav - c.UpdateReady <- true + if c.Values.La != lav { + c.Values.La = lav + c.Channels.UpdateReady <- true } time.Sleep(3 * time.Second) diff --git a/internal/lib/memory.go b/internal/lib/memory.go index 2abe03e..148cc7b 100644 --- a/internal/lib/memory.go +++ b/internal/lib/memory.go @@ -14,11 +14,8 @@ type Mem struct { Swap uint64 } -// Memory stores string with mem stats for i3bar. -var Memory Mem - // UpdateMemStats parses mem info stats. -func (c MyConfig) UpdateMemStats() { +func (c *MyConfig) UpdateMemStats() { for { v, err := mem.VirtualMemory() @@ -38,19 +35,18 @@ func (c MyConfig) UpdateMemStats() { continue } - if Conf.Mem.ShowSwap { - if Memory.Usedpct != uint64(v.UsedPercent) || Memory.Shared != v.Shared/1024/1024 || - Memory.Swap != v.SwapTotal-v.SwapFree { - Memory.Usedpct = uint64(v.UsedPercent) - Memory.Shared = v.Shared / 1024 / 1024 - Memory.Swap = sw.Used - c.UpdateReady <- true + if c.Mem.ShowSwap { + if c.Values.Memory.Usedpct != uint64(v.UsedPercent) || c.Values.Memory.Shared != v.Shared/1024/1024 || c.Values.Memory.Swap != v.SwapTotal-v.SwapFree { + c.Values.Memory.Usedpct = uint64(v.UsedPercent) + c.Values.Memory.Shared = v.Shared / 1024 / 1024 + c.Values.Memory.Swap = sw.Used + c.Channels.UpdateReady <- true } } else { - if Memory.Usedpct != uint64(v.UsedPercent) || Memory.Shared != v.Shared/1024/1024 { - Memory.Usedpct = uint64(v.UsedPercent) - Memory.Shared = v.Shared / 1024 / 1024 - c.UpdateReady <- true + if c.Values.Memory.Usedpct != uint64(v.UsedPercent) || c.Values.Memory.Shared != v.Shared/1024/1024 { + c.Values.Memory.Usedpct = uint64(v.UsedPercent) + c.Values.Memory.Shared = v.Shared / 1024 / 1024 + c.Channels.UpdateReady <- true } } diff --git a/internal/lib/pulseaudio.go b/internal/lib/pulseaudio.go index 0f45be1..b289740 100644 --- a/internal/lib/pulseaudio.go +++ b/internal/lib/pulseaudio.go @@ -10,30 +10,25 @@ import ( p "github.com/mafik/pulseaudio" ) -var SoundVolume = "🔊:0%" -var pa *p.Client - -var SVPAHandlerChan = make(chan ClickEvent, 256) - // TODO: https://twin.sh/articles/44/add-a-timeout-to-any-function-in-go timeout pulseaudio calls // UpdateVolumeInfo updates info about current Sound Volume. -func (c MyConfig) UpdateVolumeInfo() { +func (c *MyConfig) UpdateVolumeInfo() { var err error - pa, err = p.NewClient() + c.Values.PA, err = p.NewClient() // It can happen if no pulseaudio server running for current user. // If no server running we have to run one. if err != nil { - if err := PaReinit(); err != nil { + if err := c.PaReinit(); err != nil { log.Print(err) return } } - vol, err := pa.Volume() + vol, err := c.Values.PA.Volume() if err != nil { log.Printf("Unable get volume from pulseaudio server: %s", err) @@ -41,7 +36,7 @@ func (c MyConfig) UpdateVolumeInfo() { return } - SoundVolume = fmt.Sprintf( + c.Values.SoundVolume = fmt.Sprintf( "%s", c.SimpleVolumePa.Color, c.SimpleVolumePa.Background, @@ -50,7 +45,7 @@ func (c MyConfig) UpdateVolumeInfo() { c.SimpleVolumePa.Symbol, ) - SoundVolume += fmt.Sprintf( + c.Values.SoundVolume += fmt.Sprintf( ":%d%%", c.SimpleVolumePa.Color, c.SimpleVolumePa.Background, @@ -59,11 +54,11 @@ func (c MyConfig) UpdateVolumeInfo() { int64(vol*100), ) - c.UpdateReady <- true + c.Channels.UpdateReady <- true for { // Subscribe to update notification channel, to get info that volume changed. - pulseUpdate, err := pa.Updates() + pulseUpdate, err := c.Values.PA.Updates() if err != nil { log.Printf("Unable to subscribe to pulseaudio updates: %s", err) @@ -73,7 +68,7 @@ func (c MyConfig) UpdateVolumeInfo() { // Rake update events. for range pulseUpdate { - vol, err = pa.Volume() + vol, err = c.Values.PA.Volume() if err != nil { log.Printf("Unable get volume from pulseaudio server: %s", err) @@ -81,7 +76,7 @@ func (c MyConfig) UpdateVolumeInfo() { return } - SoundVolume = fmt.Sprintf( + c.Values.SoundVolume = fmt.Sprintf( "%s", c.SimpleVolumePa.Color, c.SimpleVolumePa.Background, @@ -90,7 +85,7 @@ func (c MyConfig) UpdateVolumeInfo() { c.SimpleVolumePa.Symbol, ) - SoundVolume += fmt.Sprintf( + c.Values.SoundVolume += fmt.Sprintf( ":%d%%", c.SimpleVolumePa.Color, c.SimpleVolumePa.Background, @@ -99,10 +94,10 @@ func (c MyConfig) UpdateVolumeInfo() { int64(vol*100), ) - c.UpdateReady <- true + c.Channels.UpdateReady <- true } - if err := PaReinit(); err != nil { + if err := c.PaReinit(); err != nil { log.Print(err) return @@ -110,11 +105,11 @@ func (c MyConfig) UpdateVolumeInfo() { } // This code is unreachable :( - pa.Close() //nolint:govet + c.Values.PA.Close() //nolint:govet } // PaReinit re-inits pulseaudio and connection to it. -func PaReinit() error { +func (c *MyConfig) PaReinit() error { var err error // If we out of updates, seems someone killed pulseaudio server. Restart it. @@ -157,7 +152,7 @@ func PaReinit() error { // This setting defines if pulseaudio will be run in manner that allows it to exit is other login detected (how // they guess it - I do not know). In general case we do not want to allow pa to exit and leave our session without // audio. - if Conf.SimpleVolumePa.DontExitOnLogin { + if c.SimpleVolumePa.DontExitOnLogin { // Do not exit on any kind of login/logout events. cmd = exec.Command("pulseaudio", "--exit-idle-time=-1", "--start") } else { @@ -169,7 +164,7 @@ func PaReinit() error { return fmt.Errorf("unable to initialize pulseaudio server instance: %w", err) } - pa, err = p.NewClient() + c.Values.PA, err = p.NewClient() if err != nil { return fmt.Errorf("unable to make client connection to pulseaudio: %w", err) @@ -178,21 +173,21 @@ func PaReinit() error { return err } -func (c MyConfig) SVPAHandler() { - for e := range SVPAHandlerChan { +func (c *MyConfig) SVPAHandler() { + for e := range c.Channels.SVPAHandlerChan { if e.Button == 3 { - RunChan <- Conf.SimpleVolumePa.RightClickCmd + c.Channels.RunChan <- c.SimpleVolumePa.RightClickCmd continue } - vol, err := pa.Volume() + vol, err := c.Values.PA.Volume() if err != nil { - if err := PaReinit(); err != nil { + if err := c.PaReinit(); err != nil { log.Printf("Unable to get pulseaudio volume: %s", err) } else { - vol, err = pa.Volume() + vol, err = c.Values.PA.Volume() if err != nil { log.Printf("Unable to get volume pulseaudio server behaves weirdly: %s", err) @@ -201,25 +196,25 @@ func (c MyConfig) SVPAHandler() { } switch e.Button { - case Conf.SimpleVolumePa.WheelUp: - vol += float32(Conf.SimpleVolumePa.Step) / 100 + case c.SimpleVolumePa.WheelUp: + vol += float32(c.SimpleVolumePa.Step) / 100 - if vol > (float32(Conf.SimpleVolumePa.MaxVolumeLimit) / 100) { - vol = float32(Conf.SimpleVolumePa.MaxVolumeLimit) / 100 + if vol > (float32(c.SimpleVolumePa.MaxVolumeLimit) / 100) { + vol = float32(c.SimpleVolumePa.MaxVolumeLimit) / 100 } - if err := pa.SetVolume(vol); err != nil { + if err := c.Values.PA.SetVolume(vol); err != nil { log.Printf("Unable to set pulseaudio volume: %s", err) } - case Conf.SimpleVolumePa.WheelDown: - vol -= float32(Conf.SimpleVolumePa.Step) / 100 + case c.SimpleVolumePa.WheelDown: + vol -= float32(c.SimpleVolumePa.Step) / 100 if vol < 0 { vol = 0 } - if err := pa.SetVolume(vol); err != nil { + if err := c.Values.PA.SetVolume(vol); err != nil { log.Printf("Unable to set pulseaudio volume: %s", err) } } diff --git a/internal/lib/signal.go b/internal/lib/signal.go index 857c890..0d787c1 100644 --- a/internal/lib/signal.go +++ b/internal/lib/signal.go @@ -9,20 +9,20 @@ import ( var PrintOutput = true // SigHandler OS signal handler. -func (c MyConfig) SigHandler() { - for s := range c.SigChan { +func (c *MyConfig) SigHandler() { + for s := range c.Channels.SigChan { switch s { case syscall.SIGUSR1: log.Print("Got SIGUSR1, stopping output") - PrintOutput = false + c.Values.PrintOutput = false case syscall.SIGUSR2: log.Print("Got SIGUSR2, resuming output") - PrintOutput = true + c.Values.PrintOutput = true - c.UpdateReady <- true + c.Channels.UpdateReady <- true case syscall.SIGQUIT, syscall.SIGTERM, syscall.SIGINT: os.Exit(0) diff --git a/internal/lib/spawn.go b/internal/lib/spawn.go index 0a9a136..89f5555 100644 --- a/internal/lib/spawn.go +++ b/internal/lib/spawn.go @@ -8,12 +8,9 @@ import ( "time" ) -// RunChan to this channel we send command and its argv to execute as separate process. -var RunChan = make(chan []string, 128) - // Spawner forks and execs given program, and also detaches form its control tty. -func (c MyConfig) Spawner() { - for prg := range RunChan { +func (c *MyConfig) Spawner() { + for prg := range c.Channels.RunChan { devnullR, _ := os.Open(os.DevNull) devnullW, _ := os.OpenFile(os.DevNull, os.O_WRONLY|os.O_APPEND, 0644) @@ -48,7 +45,7 @@ func (c MyConfig) Spawner() { } // CleanZombies reaps processes spawned by Spawner() and already exited. -func (c MyConfig) CleanZombies() { +func (c *MyConfig) CleanZombies() { r := syscall.Rusage{} for { diff --git a/internal/lib/stdin.go b/internal/lib/stdin.go index 401bf10..f6b69ec 100644 --- a/internal/lib/stdin.go +++ b/internal/lib/stdin.go @@ -26,7 +26,7 @@ type ClickEvent struct { // ParseStdin tries to parse text that i3bar prints to our stdin. Currently - it is mouse click events on different // area names of i3bar. -func (c MyConfig) ParseStdin() { +func (c *MyConfig) ParseStdin() { reader := bufio.NewReader(os.Stdin) // De-facto it is jsonl, except first line is garbage. Also, first symbol in each strint garbage too. @@ -84,35 +84,35 @@ func (c MyConfig) ParseStdin() { // Clock clicks parse. if e.Name == "wallclock" { - if Conf.Clock.LeftClick.Enabled && e.Button == 1 { - RunChan <- Conf.Clock.LeftClick.Cmd - } else if Conf.Clock.RightClick.Enabled && e.Button == 3 { - RunChan <- Conf.Clock.RightClick.Cmd + if c.Clock.LeftClick.Enabled && e.Button == 1 { + c.Channels.RunChan <- c.Clock.LeftClick.Cmd + } else if c.Clock.RightClick.Enabled && e.Button == 3 { + c.Channels.RunChan <- c.Clock.RightClick.Cmd } continue } if e.Name == "simple-volume-pa" { - if Conf.SimpleVolumePa.Enabled { - SVPAHandlerChan <- e + if c.SimpleVolumePa.Enabled { + c.Channels.SVPAHandlerChan <- e } continue } - if !Conf.AppButtons.Enabled { + if !c.AppButtons.Enabled { continue } - for _, app := range Conf.Apps { + for _, app := range c.Apps { switch { case app.Name != "" && app.Instance != "": if app.Name == e.Name && app.Instance == e.Instance { prg := append([]string{}, app.Cmd) prg = append(prg, app.Args...) - RunChan <- prg + c.Channels.RunChan <- prg break } @@ -120,13 +120,13 @@ func (c MyConfig) ParseStdin() { prg := append([]string{}, app.Cmd) prg = append(prg, app.Args...) - RunChan <- prg + c.Channels.RunChan <- prg case app.Instance != "" && e.Instance == app.Instance: prg := append([]string{}, app.Cmd) prg = append(prg, app.Args...) - RunChan <- prg + c.Channels.RunChan <- prg } } } diff --git a/internal/lib/vpn.go b/internal/lib/vpn.go index fb55f3c..9e8add9 100644 --- a/internal/lib/vpn.go +++ b/internal/lib/vpn.go @@ -8,7 +8,7 @@ import ( ) // UpdateVPNStatus periodically update status of openvpn daemon. -func (c MyConfig) UpdateVPNStatus() { +func (c *MyConfig) UpdateVPNStatus() { var ( vpnCStatus string tcpCheck string @@ -17,28 +17,28 @@ func (c MyConfig) UpdateVPNStatus() { for { if c.VPNFileCheck() { - if Conf.Vpn.UpColor == "" { + if c.Vpn.UpColor == "" { vpnCheck = `⍋` } else { vpnCheck = fmt.Sprintf(`⍋`, c.Vpn.UpColor) } } else { - if Conf.Vpn.DownColor == "" { + if c.Vpn.DownColor == "" { vpnCheck = `⍒` } else { vpnCheck = fmt.Sprintf(`⍒`, c.Vpn.DownColor) } } - if Conf.Vpn.TCPCheck.Enabled { + if c.Vpn.TCPCheck.Enabled { if c.VPNTCPCheck() { - if Conf.Vpn.UpColor == "" { + if c.Vpn.UpColor == "" { tcpCheck = `✔` } else { tcpCheck = fmt.Sprintf(`✔`, c.Vpn.UpColor) } } else { - if Conf.Vpn.DownColor == "" { + if c.Vpn.DownColor == "" { tcpCheck = `✘` } else { tcpCheck = fmt.Sprintf(`✘`, c.Vpn.DownColor) @@ -50,9 +50,9 @@ func (c MyConfig) UpdateVPNStatus() { vpnCStatus = fmt.Sprintf("VPN:%s", vpnCheck) } - if c.VPNStatus != vpnCStatus { - c.VPNStatus = vpnCStatus - c.UpdateReady <- true + if c.Values.VPNStatus != vpnCStatus { + c.Values.VPNStatus = vpnCStatus + c.Channels.UpdateReady <- true } time.Sleep(3 * time.Second) @@ -60,7 +60,7 @@ func (c MyConfig) UpdateVPNStatus() { } // VPNTCPCheck intended to check arbitrary service inside vpn segment, to indicate that openvpn sevice not stoned. -func (c MyConfig) VPNTCPCheck() bool { +func (c *MyConfig) VPNTCPCheck() bool { conn, err := net.DialTimeout( "tcp", fmt.Sprintf("%s:%d", c.Vpn.TCPCheck.Host, c.Vpn.TCPCheck.Port), @@ -76,7 +76,7 @@ func (c MyConfig) VPNTCPCheck() bool { } // VPNFileCheck checks modification time of openvpn-status file. -func (c MyConfig) VPNFileCheck() bool { +func (c *MyConfig) VPNFileCheck() bool { var ( fi os.FileInfo err error