summaryrefslogtreecommitdiff
path: root/internal/display/net.go
blob: 7fc3a9d69db1a351d1a289fd10ee014e79ded44a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
package display

import (
	"strconv"
	"strings"

	"codeberg.org/snonux/loadbars/internal/config"
	"codeberg.org/snonux/loadbars/internal/constants"
	"codeberg.org/snonux/loadbars/internal/stats"
	"github.com/veandco/go-sdl2/sdl"
)

func netLinkBytesPerSec(cfg *config.Config) int64 {
	s := strings.ToLower(strings.TrimSpace(cfg.NetLink))
	switch s {
	case "gbit", "1gbit":
		return int64(constants.BytesGbit)
	case "10gbit":
		return int64(constants.Bytes10Gbit)
	case "mbit", "1mbit":
		return int64(constants.BytesMbit)
	case "10mbit":
		return int64(constants.Bytes10Mbit)
	case "100mbit":
		return int64(constants.Bytes100Mbit)
	case "":
		return int64(constants.BytesGbit)
	}
	if n, err := strconv.ParseInt(s, 10, 64); err == nil {
		return n * int64(constants.BytesMbit)
	}
	return int64(constants.BytesGbit)
}

func sumNonLoNet(h *stats.HostStats) (sum stats.NetStamp, hasIface bool) {
	if h.Net == nil {
		return sum, false
	}
	for iface, ns := range h.Net {
		if iface == "lo" {
			continue
		}
		hasIface = true
		sum.B += ns.B
		sum.Tb += ns.Tb
		if ns.Stamp > sum.Stamp {
			sum.Stamp = ns.Stamp
		}
	}
	return sum, hasIface
}

func drawNetBarSmoothed(renderer *sdl.Renderer, h *stats.HostStats, cfg *config.Config, smoothed *struct{ rxPct, txPct float64 }, prev stats.NetStamp, factor float64, barW int32, x, y, barH int32) stats.NetStamp {
	renderer.SetDrawColor(constants.Black.R, constants.Black.G, constants.Black.B, 255)
	renderer.FillRect(&sdl.Rect{X: x, Y: y, W: barW, H: barH})
	cur, hasIface := sumNonLoNet(h)
	if !hasIface {
		renderer.SetDrawColor(constants.Red.R, constants.Red.G, constants.Red.B, 255)
		renderer.FillRect(&sdl.Rect{X: x, Y: y, W: barW, H: barH})
		return prev
	}
	if cur.Stamp > prev.Stamp && prev.Stamp > 0 {
		prev = smoothNetUtilization(cur, prev, cfg, smoothed, factor)
	} else if prev.Stamp == 0 {
		prev = cur
	}
	drawNetHalves(renderer, smoothed, x, y, barW, barH)
	return prev
}

func smoothNetUtilization(cur, prev stats.NetStamp, cfg *config.Config, smoothed *struct{ rxPct, txPct float64 }, factor float64) stats.NetStamp {
	linkBps := netLinkBytesPerSec(cfg)
	if linkBps <= 0 {
		linkBps = int64(constants.BytesGbit)
	}
	dt := cur.Stamp - prev.Stamp
	if dt > 0 {
		deltaB := cur.B - prev.B
		deltaTb := cur.Tb - prev.Tb
		if deltaB < 0 {
			deltaB = 0
		}
		if deltaTb < 0 {
			deltaTb = 0
		}
		targetRx := 100 * float64(deltaB) / (float64(linkBps) * dt)
		targetTx := 100 * float64(deltaTb) / (float64(linkBps) * dt)
		smoothed.rxPct += (targetRx - smoothed.rxPct) * factor
		smoothed.txPct += (targetTx - smoothed.txPct) * factor
	}
	return cur
}

func drawNetHalves(renderer *sdl.Renderer, smoothed *struct{ rxPct, txPct float64 }, x, y, barW, barH int32) {
	halfW := barW / 2
	pxPerPct := float64(barH) / 100.0
	halfH := barH / 2
	rxH := int32(smoothed.rxPct * pxPerPct)
	if rxH > halfH {
		rxH = halfH
	}
	if rxH > 0 {
		renderer.SetDrawColor(constants.LightGreen.R, constants.LightGreen.G, constants.LightGreen.B, 255)
		renderer.FillRect(&sdl.Rect{X: x, Y: y, W: halfW, H: rxH})
	}
	if halfW > 0 && halfH-rxH > 0 {
		renderer.SetDrawColor(constants.Black.R, constants.Black.G, constants.Black.B, 255)
		renderer.FillRect(&sdl.Rect{X: x, Y: y + rxH, W: halfW, H: halfH - rxH})
	}
	txH := int32(smoothed.txPct * pxPerPct)
	if txH > halfH {
		txH = halfH
	}
	if txH > 0 {
		renderer.SetDrawColor(constants.LightGreen.R, constants.LightGreen.G, constants.LightGreen.B, 255)
		renderer.FillRect(&sdl.Rect{X: x + halfW, Y: y + barH - txH, W: halfW, H: txH})
	}
	if halfW > 0 && (barH-txH) > 0 {
		renderer.SetDrawColor(constants.Black.R, constants.Black.G, constants.Black.B, 255)
		renderer.FillRect(&sdl.Rect{X: x + halfW, Y: y, W: halfW, H: barH - txH})
	}
}