Skip to content

Commit

Permalink
Add tunnel delay line chart on gtk client
Browse files Browse the repository at this point in the history
  • Loading branch information
weilinfox committed Jan 10, 2023
1 parent 0f37d5e commit 94b6890
Show file tree
Hide file tree
Showing 4 changed files with 225 additions and 13 deletions.
141 changes: 131 additions & 10 deletions client-gtk3/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"time"

client "github.com/weilinfox/youmu-thlink/client/lib"
"github.com/weilinfox/youmu-thlink/glg-go"
"github.com/weilinfox/youmu-thlink/utils"

"github.com/gotk3/gotk3/gdk"
Expand All @@ -21,7 +22,7 @@ var icon *gdk.Pixbuf

const appName = "白玉楼製作所 ThLink"

type Status struct {
type status struct {
localPort int
serverHost string
tunnelType string
Expand All @@ -34,17 +35,30 @@ type Status struct {

brokerTVersion byte
brokerVersion string

delay [40]time.Duration
delayPos int
delayLen int
pluginDelay [40]time.Duration
pluginDelayPos int
pluginDelayLen int
pluginDelayShow bool
}

// clientStatus all of this client-gui
var clientStatus = Status{
var clientStatus = status{
localPort: client.DefaultLocalPort,
serverHost: client.DefaultServerHost,
tunnelType: client.DefaultTunnelType,
client: client.NewWithDefault(),
plugin: nil,
pluginNum: 0,
userConfigChange: false,
delayPos: 0,
delayLen: 0,
pluginDelayPos: 0,
pluginDelayLen: 0,
pluginDelayShow: false,
}

func main() {
Expand Down Expand Up @@ -103,11 +117,6 @@ func onAppActivate(app *gtk.Application) {
aAbout := glib.SimpleActionNew("about", nil)
aAbout.Connect("activate", showAboutDialog)
app.AddAction(aAbout)
aInfo := glib.SimpleActionNew("info", nil)
aInfo.Connect("activate", func() {

})
app.AddAction(aInfo)

appWindow.Connect("destroy", onAppDestroy)

Expand All @@ -123,7 +132,7 @@ func onAppActivate(app *gtk.Application) {
menu := glib.MenuNew()
menu.Append("Reset config", "app.reset")
menu.Append("Network discovery", "app.net-disc")
menu.Append("Tunnel info", "app.info")
menu.Append("Tunnel status", "app.t-status")
menu.Append("About thlink", "app.about")
menu.Append("Quit", "app.quit")
menuBtn.SetMenuModel(&menu.MenuModel)
Expand Down Expand Up @@ -186,6 +195,24 @@ func onAppActivate(app *gtk.Application) {
setPingLabel := func(delay time.Duration) {
logger.Debugf("Display new delay %.2f ms", float64(delay.Nanoseconds())/1000000)
pingLabel.SetText(fmt.Sprintf("%.2f ms", float64(delay.Nanoseconds())/1000000))

clientStatus.delay[clientStatus.delayPos] = delay
clientStatus.delayPos = (clientStatus.delayPos + 1) % 40
if clientStatus.delayLen < 40 {
clientStatus.delayLen++
}

switch p := clientStatus.plugin.(type) {
case *client.Hisoutensoku:
clientStatus.pluginDelayShow = true
if p.PeerStatus == client.BATTLE {
clientStatus.pluginDelay[clientStatus.pluginDelayPos] = delay
clientStatus.pluginDelayPos = (clientStatus.pluginDelayPos + 1) % 40
if clientStatus.pluginDelayLen < 40 {
clientStatus.pluginDelayLen++
}
}
}
}
pingBtn.Connect("clicked", func() {

Expand Down Expand Up @@ -601,6 +628,99 @@ func onAppActivate(app *gtk.Application) {
})
app.AddAction(aNetDisc)

// tunnel status
aTStatus := glib.SimpleActionNew("t-status", nil)
aTStatus.Connect("activate", func() {

showTStatusDialog := func() error {

// setup dialog with button
dialog, err := gtk.DialogNew()
if err != nil {
return err
}
dialog.SetIcon(icon)
dialog.SetTitle("Tunnel status")
btn, err := dialog.AddButton("Close", gtk.RESPONSE_CLOSE)
if err != nil {
return err
}
btn.Connect("clicked", func() {
dialog.Destroy()
})

glg, err := glgo.GlgLineGraphNew()
if err != nil {
return err
}

// setup dialog with glgLineGraph
dialogBox, err := dialog.GetContentArea()
if err != nil {
return err
}
glg.SetHExpand(true)
glg.SetVExpand(true)
dialogBox.Add(glg)

source := glib.TimeoutAdd(1000, func() bool {

pos := (clientStatus.delayPos + 39) % 40
glg.GlgLineGraphDataSeriesAddValue(0,
float64(clientStatus.delay[pos].Nanoseconds())/1000000)

if clientStatus.pluginDelayShow {
switch p := clientStatus.plugin.(type) {
case *client.Hisoutensoku:
if p.PeerStatus == client.BATTLE {
glg.GlgLineGraphDataSeriesAddValue(1, float64(p.GetReplayDelay().Nanoseconds())/1000000)
}
}
}

return true
})

dialog.Connect("destroy", func() {
glib.SourceRemove(source)
})

dialog.SetDefaultSize(500, 300)
dialog.ShowAll()

glg.GlgLineGraphDataSeriesAdd("Tunnel Delay", "blue")
glg.GlgLineGraphDataSeriesAdd("Peer Delay", "red")
pos, l := clientStatus.delayPos, clientStatus.delayLen
if l == 40 {
for i := pos; i < 40; i++ {
glg.GlgLineGraphDataSeriesAddValue(0, float64(clientStatus.delay[i].Nanoseconds())/1000000)
}
}
for i := 0; i < pos; i++ {
glg.GlgLineGraphDataSeriesAddValue(0, float64(clientStatus.delay[i].Nanoseconds())/1000000)
}
if clientStatus.pluginDelayShow {
pos, l = clientStatus.pluginDelayPos, clientStatus.pluginDelayLen
if l == 40 {
for i := pos; i < 40; i++ {
glg.GlgLineGraphDataSeriesAddValue(1, float64(clientStatus.pluginDelay[i].Nanoseconds())/1000000)
}
}
for i := 0; i < pos; i++ {
glg.GlgLineGraphDataSeriesAddValue(1, float64(clientStatus.pluginDelay[i].Nanoseconds())/1000000)
}
}

return nil
}

err = showTStatusDialog()
if err != nil {
showErrorDialog(appWindow, "Show tunnel status dialog error", err)
}
})
app.AddAction(aTStatus)

// add items to grid
mainGrid.Add(serverLabel)
mainGrid.Add(serverEntry)
Expand Down Expand Up @@ -660,7 +780,7 @@ func onAppActivate(app *gtk.Application) {
})
case client.BATTLE:
glib.IdleAdd(func() bool {
delay := float64(p.GetReplayDelay().Nanoseconds()) / 2000000
delay := float64(p.GetReplayDelay().Nanoseconds()) / 1000000
if delay > 9999 {
delay = 9999
}
Expand Down Expand Up @@ -773,8 +893,9 @@ func showAboutDialog() {
about.SetCopyright("https://github.com/gotk3/gotk3 ISC License\n" +
"https://github.com/lucas-clemente/quic-go MIT License\n" +
"https://github.com/sirupsen/logrus MIT License\n" +
"https://github.com/weilinfox/youmu-thlink/glg-go GPL-3.0 License\n" +
"https://github.com/weilinfox/youmu-thlink AGPL-3.0 License\n" +
"\n2022 weilinfox")
"\n2022-2023 weilinfox")
about.SetTitle("About ThLink")
if icon != nil {
about.SetIcon(icon)
Expand Down
4 changes: 4 additions & 0 deletions glg-go/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@

This is the original README file of GlgLineGraph library.

Visit [here](https://github.com/skoona/glinegraph-cairo) to fetch the origin repo released under LGPLv2.0.

Thanks [skoona](https://github.com/skoona) for his great work.

### (a.k.a cairo version of glinegraph ) July 2007/2016

![GLineGraph Widget](https://github.com/skoona/glinegraph-cairo/raw/master/images/glg_cairo3.png)
Expand Down
6 changes: 4 additions & 2 deletions glg-go/glg_cairo.c
Original file line number Diff line number Diff line change
Expand Up @@ -1870,7 +1870,7 @@ static gint glg_line_graph_draw_tooltip (GlgLineGraph *graph)
{ /* found */
g_snprintf (ch_work, sizeof (ch_work), "%s", ch_buffer);
g_snprintf (ch_buffer, sizeof (ch_buffer),
"%s{%3.1lf%% <span foreground=\"%s\">%s</span>}",
"%s{%3.2lf <span foreground=\"%s\">%s</span>}",
ch_work,
psd->lg_point_dvalue[v_index],
psd->ch_legend_color, psd->ch_legend_text);
Expand Down Expand Up @@ -2139,7 +2139,9 @@ extern gboolean glg_line_graph_data_series_add_value (GlgLineGraph *graph, gint
priv->lg_series_time = g_list_remove (priv->lg_series_time, gl_remove->data);
}
priv->lg_series_time =
g_list_append (priv->lg_series_time, GINT_TO_POINTER ((time_t) time (NULL))); /* TODO: Leaking Memory - NO time_t is a gint64 */
g_list_append (priv->lg_series_time, GINT_TO_POINTER ((time_t) time (NULL)));
/* TODO: Leaking Memory - NO time_t is a gint64
time always 1970 */
}

g_debug (" ==>DataSeriesAddValue: series=%d, value=%3.1lf, index=%d, count=%d, max_pts=%d",
Expand Down
87 changes: 86 additions & 1 deletion glg-go/glg_go.go
Original file line number Diff line number Diff line change
@@ -1 +1,86 @@
package glg_go
package glgo

import (
"errors"
"unsafe"

"github.com/gotk3/gotk3/glib"
"github.com/gotk3/gotk3/gtk"
)

/*
#cgo pkg-config: gtk+-3.0
#include <gtk/gtk.h>
#include "glg_cairo.h"
GlgLineGraph * my_glg_line_graph_new()
{
return glg_line_graph_new ("chart-set-elements",
GLG_TOOLTIP | GLG_TITLE_T | GLG_TITLE_X | GLG_TITLE_Y | GLG_GRID_MAJOR_X | GLG_GRID_MAJOR_Y | GLG_GRID_MINOR_X | GLG_GRID_MINOR_Y | GLG_GRID_LABELS_X | GLG_GRID_LABELS_Y,
"range-tick-minor-x", 1,
"range-tick-major-x", 10,
"range-scale-minor-x", 0,
"range-scale-major-x", 40,
"range-tick-minor-y", 2,
"range-tick-major-y", 10,
"range-scale-minor-y", 0,
"range-scale-major-y", 120,
"series-line-width", 2,
"graph-title-foreground", "black",
"graph-scale-foreground", "black",
"graph-chart-background", "light gray",
"graph-window-background", "white",
"text-title-main", "<big><b>Tunnel Delay Line Chart</b></big>",
"text-title-yaxis", "<span>delay(ms)</span>",
"text-title-xaxis", "<i>Click mouse button 1 to <span foreground=\"red\">toggle</span> popup legend.</i>",
NULL);
}
*/
import "C"

type GlgLineGraph struct {
gtk.Bin

// rangeScaleMajorY int
}

func GlgLineGraphNew() (*GlgLineGraph, error) {
glg := C.my_glg_line_graph_new()
if glg == nil {
return nil, errors.New("cgo returned unexpected nil pointer")
}

obj := glib.Take(unsafe.Pointer(glg))

return &GlgLineGraph{Bin: gtk.Bin{Container: gtk.Container{Widget: gtk.Widget{InitiallyUnowned: glib.InitiallyUnowned{Object: obj}}}}}, nil
}

func (g *GlgLineGraph) GlgLineGraphDataSeriesAdd(legend string, color string) bool {

cLegend := C.CString(legend)
cColor := C.CString(color)
defer C.free(unsafe.Pointer(cLegend))
defer C.free(unsafe.Pointer(cColor))

return C.glg_line_graph_data_series_add((*C.GlgLineGraph)(unsafe.Pointer(g.Native())), cLegend, cColor) == C.TRUE
}

func (g *GlgLineGraph) GlgLineGraphDataSeriesAddValue(series int, value float64) bool {
defer g.glgLineGraphRedraw()

// auto scale
/*if value > float64(g.rangeScaleMajorY) {
g.glgLineGraphChartSetYRanges((int(math.Floor(value/10)) + 1) * 10)
}*/

return C.glg_line_graph_data_series_add_value((*C.GlgLineGraph)(unsafe.Pointer(g.Native())), *(*C.int)(unsafe.Pointer(&series)), *(*C.double)(unsafe.Pointer(&value))) == C.TRUE
}

func (g *GlgLineGraph) glgLineGraphRedraw() {
C.glg_line_graph_redraw((*C.GlgLineGraph)(unsafe.Pointer(g.Native())))
}

// cannot set range more than once
/*func (g *GlgLineGraph) glgLineGraphChartSetYRanges(yScaleMax int) {
C.glg_line_graph_chart_set_y_ranges((*C.GlgLineGraph)(unsafe.Pointer(g.Native())), 2, 10, 0, *(*C.gint)(unsafe.Pointer(&yScaleMax)))
}*/

0 comments on commit 94b6890

Please sign in to comment.