]> Sergey Matveev's repositories - vors.git/blob - cmd/client/stats.go
Working version
[vors.git] / cmd / client / stats.go
1 // VoRS -- Vo(IP) Really Simple
2 // Copyright (C) 2024 Sergey Matveev <stargrave@stargrave.org>
3 //
4 // This program is free software: you can redistribute it and/or modify
5 // it under the terms of the GNU Affero General Public License as
6 // published by the Free Software Foundation, version 3 of the License.
7 //
8 // This program is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11 // GNU General Public License for more details.
12 //
13 // You should have received a copy of the GNU General Public License
14 // along with this program.  If not, see <http://www.gnu.org/licenses/>.
15
16 package main
17
18 import (
19         "fmt"
20         "math"
21         "strings"
22         "sync/atomic"
23         "time"
24
25         "github.com/dustin/go-humanize"
26         "github.com/jroimartin/gocui"
27         vors "go.stargrave.org/vors/internal"
28 )
29
30 type Stats struct {
31         pkts    int64
32         bytes   uint64
33         lost    int64
34         reorder int64
35         last    time.Time
36         vol     uint64
37         volN    uint64
38         dead    chan struct{}
39 }
40
41 func (stats *Stats) AddRMS(pcm []int16) {
42         var vol uint64
43         for _, s := range pcm {
44                 vol += uint64(int64(s) * int64(s))
45         }
46         atomic.AddUint64(&stats.vol, vol)
47         atomic.AddUint64(&stats.volN, uint64(len(pcm)))
48 }
49
50 func statsDrawer(stats *Stats, name string) {
51         var err error
52         tick := time.Tick(vors.ScreenRefresh)
53         var now time.Time
54         var v *gocui.View
55         var vol, volN float64
56         var rep int
57         for {
58                 select {
59                 case <-stats.dead:
60                         GUI.DeleteView(name)
61                         GUI.DeleteView(name + "-vol")
62                         return
63                 case now = <-tick:
64                         s := fmt.Sprintf(
65                                 "%s  |  %s  |  L/R: %s / %s",
66                                 humanize.Comma(stats.pkts),
67                                 humanize.IBytes(stats.bytes),
68                                 humanize.Comma(stats.lost),
69                                 humanize.Comma(stats.reorder),
70                         )
71                         if name == *Name && Muted {
72                                 s += "  |  " + vors.CRed + "MUTE" + vors.CReset
73                         } else {
74                                 if stats.last.Add(time.Second).After(now) {
75                                         s += "  |  " + vors.CGreen + "TALK" + vors.CReset
76                                 }
77                         }
78                         v, err = GUI.View(name)
79                         if err == nil {
80                                 v.Clear()
81                                 v.Write([]byte(s))
82                         }
83                         vol = float64(atomic.SwapUint64(&stats.vol, 0))
84                         volN = float64(atomic.SwapUint64(&stats.volN, 0))
85                         v, err = GUI.View(name + "-vol")
86                         if err == nil {
87                                 v.Clear()
88                                 if volN == 0 {
89                                         continue
90                                 }
91                                 vol = math.Sqrt(vol / volN)
92                                 rep = int(float64(GUIMaxY) * vol / 5000)
93                                 v.Write([]byte(strings.Repeat("▒", rep)))
94                         }
95                 }
96         }
97 }