Now all indicator updates properly

This commit is contained in:
eleksir
2024-09-23 19:05:45 +03:00
parent 1a4ab136dc
commit 5bb259a30c
15 changed files with 228 additions and 231 deletions

View File

@@ -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 = "<big>⚡</big> ??% •"
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 = "<big>⚡</big> ??% •"
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(
"<span color='%s' background='%s' font='%s' size='%s'>%s</span>",
Conf.Battery.Color,
Conf.Battery.Background,
@@ -47,7 +52,7 @@ func main() {
Conf.Battery.Symbol,
)
Batt += fmt.Sprintf(
Conf.Values.BatteryString += fmt.Sprintf(
"<span color='%s' background='%s' font='%s' size='%s'> ??%% •</span>",
Conf.Battery.Color,
Conf.Battery.Background,
@@ -55,7 +60,7 @@ func main() {
Conf.Battery.FontSize,
)
SoundVolume := fmt.Sprintf(
Conf.Values.SoundVolume = fmt.Sprintf(
"<span color='%s' background='%s' font='%s' size='%s'>🔊</span>",
Conf.SimpleVolumePa.Color,
Conf.SimpleVolumePa.Background,
@@ -63,7 +68,7 @@ func main() {
Conf.SimpleVolumePa.SymbolFontSize,
)
SoundVolume += fmt.Sprintf(
Conf.Values.SoundVolume += fmt.Sprintf(
"<span color='%s' background='%s' font='%s' size='%s'>:0%%</span>",
Conf.SimpleVolumePa.Color,
Conf.SimpleVolumePa.Background,
@@ -71,7 +76,7 @@ func main() {
Conf.SimpleVolumePa.FontSize,
)
Clock := fmt.Sprintf(
Conf.Values.ClockTime = fmt.Sprintf(
"<span color='%s' background='%s' font='%s' size='%s'>Thu, 1 Jan 1970 1:00</span>",
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)

View File

@@ -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(
"<span font='%s' size='%s'>%s</span><span font='%s' size='%s'> no batt</span>",
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(
"<span color='%s' background='%s' font='%s' size='%s'>% 3d%%</span>",
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(
`<span color='%s' background='%s' font='%s' size='%s'>% 3d%%</span>`,
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(
"<span color='%s' background='%s' font='%s' size='%s'>% 3d%%</span>",
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(
`<span color='%s' background='%s' font='%s' size='%s'>% 3d%%</span>`,
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(
"<span color='%s' background='%s' font='%s' size='%s'>% 3d%%</span>",
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(
`<span color='%s' background='%s' font='%s' size='%s'>% 3d%%</span>`,
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(
"<span color='%s' background='%s' font='%s' size='%s'>% 3d%%</span>",
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(
`<span color='%s' background='%s' font='%s' size='%s'>% 3d%%</span>`,
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(
"<span color='%s' background='%s' font='%s' size='%s'>%s</span><span color='%s' background='%s' font='%s' size='%s'>B%d </span>%s<span color='%s' background='%s' font='%s' size='%s'> %s</span>",
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)

View File

@@ -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)

View File

@@ -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 == "" {

View File

@@ -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)

View File

@@ -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
},

View File

@@ -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

View File

@@ -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("<span foreground=\"%s\">⍋</span>", Conf.NetIf.UpColor)
StatusStr := fmt.Sprintf("<span foreground=\"%s\">⍋</span>", c.NetIf.UpColor)
operstate = []byte(StatusStr)
case "down":
statusStr := fmt.Sprintf("<span foreground=\"%s\">⍒</span>", Conf.NetIf.DownColor)
statusStr := fmt.Sprintf("<span foreground=\"%s\">⍒</span>", 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)

View File

@@ -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)

View File

@@ -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
}
}

View File

@@ -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(
"<span color='%s' background='%s' font='%s' size='%s'>%s</span>",
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(
"<span color='%s' background='%s' font='%s' size='%s'>:%d%%</span>",
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(
"<span color='%s' background='%s' font='%s' size='%s'>%s</span>",
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(
"<span color='%s' background='%s' font='%s' size='%s'>:%d%%</span>",
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)
}
}

View File

@@ -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)

View File

@@ -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 {

View File

@@ -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
}
}
}

View File

@@ -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(`<span foreground="%s">⍋</span>`, c.Vpn.UpColor)
}
} else {
if Conf.Vpn.DownColor == "" {
if c.Vpn.DownColor == "" {
vpnCheck = `⍒`
} else {
vpnCheck = fmt.Sprintf(`<span foreground="%s">⍒</span>`, 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(`<span foreground="%s">✔</span>`, c.Vpn.UpColor)
}
} else {
if Conf.Vpn.DownColor == "" {
if c.Vpn.DownColor == "" {
tcpCheck = `✘`
} else {
tcpCheck = fmt.Sprintf(`<span foreground="%s">✘</span>`, 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