Skip to content

Commit 1b832f6

Browse files
committed
Few fixes as result of a test in the field
1 parent 3a46483 commit 1b832f6

File tree

7 files changed

+129
-22
lines changed

7 files changed

+129
-22
lines changed

cmd/streampanel/FyneApp.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,4 +5,4 @@ Website = "https://github.com/xaionaro/streamctl"
55
Name = "streampanel"
66
ID = "center.dx.streampanel"
77
Version = "0.1.0"
8-
Build = 368
8+
Build = 372

cmd/streampanel/runtime_android.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,13 @@
11
package main
22

33
import (
4+
"time"
5+
46
"github.com/xaionaro-go/xpath"
7+
"github.com/xaionaro-go/xsync"
58
)
69

710
func init() {
811
xpath.HomeDirOverride = "/data/user/0/center.dx.streampanel/files"
12+
xsync.DefaultDeadlockTimeout = time.Hour
913
}

go.mod

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -233,10 +233,10 @@ require (
233233
golang.org/x/image v0.18.0 // indirect
234234
golang.org/x/mobile v0.0.0-20240404231514-09dbf07665ed // indirect
235235
golang.org/x/net v0.39.0 // indirect
236-
golang.org/x/sync v0.13.0 // indirect
237-
golang.org/x/sys v0.32.0 // indirect
238-
golang.org/x/term v0.31.0 // indirect
239-
golang.org/x/text v0.24.0 // indirect
236+
golang.org/x/sync v0.14.0 // indirect
237+
golang.org/x/sys v0.33.0 // indirect
238+
golang.org/x/term v0.32.0 // indirect
239+
golang.org/x/text v0.25.0 // indirect
240240
golang.org/x/time v0.9.0 // indirect
241241
golang.org/x/xerrors v0.0.0-20240716161551-93cc26a95ae9 // indirect
242242
google.golang.org/genproto/googleapis/rpc v0.0.0-20250409194420-de1ac958c67a // indirect
@@ -313,9 +313,9 @@ require (
313313
github.com/xaionaro-go/xfyne v0.0.0-20241018233531-26123724a6c6
314314
github.com/xaionaro-go/xlogrus v0.0.0-20250111150201-60557109545a
315315
github.com/xaionaro-go/xpath v0.0.0-20250111145115-55f5728f643f
316-
github.com/xaionaro-go/xsync v0.0.0-20250420144932-1e27f4332d4d
316+
github.com/xaionaro-go/xsync v0.0.0-20250614210231-b74f647f859f
317317
github.com/yutopp/go-flv v0.3.1
318-
golang.org/x/crypto v0.37.0
318+
golang.org/x/crypto v0.38.0
319319
google.golang.org/grpc v1.71.1
320320
google.golang.org/protobuf v1.36.6
321321
gopkg.in/yaml.v2 v2.4.0

go.sum

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1184,8 +1184,8 @@ github.com/xaionaro-go/xlogrus v0.0.0-20250111150201-60557109545a h1:EoNRdOtBMnZ
11841184
github.com/xaionaro-go/xlogrus v0.0.0-20250111150201-60557109545a/go.mod h1:RPfWNuwqJykkA2TEvisXqHgy1ypA/1H2HBdIRSeVJ9o=
11851185
github.com/xaionaro-go/xpath v0.0.0-20250111145115-55f5728f643f h1:ofxY1akRlVdJ/AEDj0EakK4Aez8fzeWTTe2mCAZiJ0A=
11861186
github.com/xaionaro-go/xpath v0.0.0-20250111145115-55f5728f643f/go.mod h1:f0DVcqddOy1RALOgXJHwpQnkp1u1yeBX/+A2+Bf4EGc=
1187-
github.com/xaionaro-go/xsync v0.0.0-20250420144932-1e27f4332d4d h1:paN6zI8tpStL7gEbt4m24vbOFdkNUwnDqXtT3B2dzSo=
1188-
github.com/xaionaro-go/xsync v0.0.0-20250420144932-1e27f4332d4d/go.mod h1:FCpywNAl4a4hgzE8j7Z+TpdhBQi5WHxnI35jOrFpoQw=
1187+
github.com/xaionaro-go/xsync v0.0.0-20250614210231-b74f647f859f h1:Yn/hgHYgZ05zaTo6cK+Fmx46ah0O8ey0JMsWQ4TsgnY=
1188+
github.com/xaionaro-go/xsync v0.0.0-20250614210231-b74f647f859f/go.mod h1:FCpywNAl4a4hgzE8j7Z+TpdhBQi5WHxnI35jOrFpoQw=
11891189
github.com/xaionaro-go/zerolog2belt v0.0.0-20241103164018-a3bc1ea487e5 h1:jAy7VLg8y8XE1R8jBte4PRDJzOaAE+sUfmttfB9ZcAY=
11901190
github.com/xaionaro-go/zerolog2belt v0.0.0-20241103164018-a3bc1ea487e5/go.mod h1:KJuX7yl27vU+KV6CpsWOe5ZMY4zSg70hvEhwoYdr17w=
11911191
github.com/xanzy/ssh-agent v0.3.3 h1:+/15pJfg/RsTxqYcX6fHqOXZwwMP+2VyYWJeWM2qQFM=
@@ -1284,8 +1284,8 @@ golang.org/x/crypto v0.4.0/go.mod h1:3quD/ATkf6oY+rnes5c3ExXTbLc8mueNue5/DoinL80
12841284
golang.org/x/crypto v0.8.0/go.mod h1:mRqEX+O9/h5TFCrQhkgjo2yKi0yYA+9ecGkdQoHrywE=
12851285
golang.org/x/crypto v0.12.0/go.mod h1:NF0Gs7EO5K4qLn+Ylc+fih8BSTeIjAP05siRnAh98yw=
12861286
golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg=
1287-
golang.org/x/crypto v0.37.0 h1:kJNSjF/Xp7kU0iB2Z+9viTPMW4EqqsrywMXLJOOsXSE=
1288-
golang.org/x/crypto v0.37.0/go.mod h1:vg+k43peMZ0pUMhYmVAWysMK35e6ioLh3wB8ZCAfbVc=
1287+
golang.org/x/crypto v0.38.0 h1:jt+WWG8IZlBnVbomuhg2Mdq0+BBQaHbtqHEFEigjUV8=
1288+
golang.org/x/crypto v0.38.0/go.mod h1:MvrbAqul58NNYPKnOra203SB9vpuZW0e+RRZV+Ggqjw=
12891289
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
12901290
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
12911291
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
@@ -1451,8 +1451,8 @@ golang.org/x/sync v0.0.0-20220513210516-0976fa681c29/go.mod h1:RxMgew5VJxzue5/jJ
14511451
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
14521452
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
14531453
golang.org/x/sync v0.2.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
1454-
golang.org/x/sync v0.13.0 h1:AauUjRAJ9OSnvULf/ARrrVywoJDy0YS2AwQ98I37610=
1455-
golang.org/x/sync v0.13.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
1454+
golang.org/x/sync v0.14.0 h1:woo0S4Yywslg6hp4eUFjTVOyKt0RookbpAHG4c1HmhQ=
1455+
golang.org/x/sync v0.14.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
14561456
golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
14571457
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
14581458
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
@@ -1565,8 +1565,8 @@ golang.org/x/sys v0.9.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
15651565
golang.org/x/sys v0.10.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
15661566
golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
15671567
golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
1568-
golang.org/x/sys v0.32.0 h1:s77OFDvIQeibCmezSnk/q6iAfkdiQaJi4VzroCFrN20=
1569-
golang.org/x/sys v0.32.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
1568+
golang.org/x/sys v0.33.0 h1:q3i8TbbEz+JRD9ywIRlyRAQbM0qF7hu24q3teo2hbuw=
1569+
golang.org/x/sys v0.33.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
15701570
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
15711571
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
15721572
golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
@@ -1579,8 +1579,8 @@ golang.org/x/term v0.7.0/go.mod h1:P32HKFT3hSsZrRxla30E9HqToFYAQPCMs/zFMBUFqPY=
15791579
golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo=
15801580
golang.org/x/term v0.11.0/go.mod h1:zC9APTIj3jG3FdV/Ons+XE1riIZXG4aZ4GTHiPZJPIU=
15811581
golang.org/x/term v0.16.0/go.mod h1:yn7UURbUtPyrVJPGPq404EukNFxcm/foM+bV/bfcDsY=
1582-
golang.org/x/term v0.31.0 h1:erwDkOK1Msy6offm1mOgvspSkslFnIGsFnxOKoufg3o=
1583-
golang.org/x/term v0.31.0/go.mod h1:R4BeIy7D95HzImkxGkTW1UQTtP54tio2RyHz7PwK0aw=
1582+
golang.org/x/term v0.32.0 h1:DR4lr0TjUs3epypdhTOkMmuF5CDFJ/8pOnbzMZPQ7bg=
1583+
golang.org/x/term v0.32.0/go.mod h1:uZG1FhGx848Sqfsq4/DlJr3xGGsYMu/L5GW4abiaEPQ=
15841584
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
15851585
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
15861586
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
@@ -1598,8 +1598,8 @@ golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
15981598
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
15991599
golang.org/x/text v0.12.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
16001600
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
1601-
golang.org/x/text v0.24.0 h1:dd5Bzh4yt5KYA8f9CJHCP4FB4D51c2c6JvN37xJJkJ0=
1602-
golang.org/x/text v0.24.0/go.mod h1:L8rBsPeo2pSS+xqN0d5u2ikmjtmoJbDBT1b7nHvFCdU=
1601+
golang.org/x/text v0.25.0 h1:qVyWApTSYLk/drJRO5mDlNYskwQznZmkpV2c8q9zls4=
1602+
golang.org/x/text v0.25.0/go.mod h1:WEdwpYrmk1qmdHvhkSTNPm3app7v4rsT8F2UD6+VHIA=
16031603
golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
16041604
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
16051605
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=

pkg/streampanel/dashboard.go

Lines changed: 103 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,12 @@ import (
77
"image/color"
88
"image/draw"
99
"math"
10+
"os"
1011
"runtime"
1112
"slices"
1213
"sort"
1314
"strconv"
15+
"strings"
1416
"sync"
1517
"sync/atomic"
1618

@@ -42,6 +44,7 @@ import (
4244
"github.com/xaionaro-go/streamctl/pkg/streampanel/consts"
4345
"github.com/xaionaro-go/streamctl/pkg/ximage"
4446
xfyne "github.com/xaionaro-go/xfyne/widget"
47+
"github.com/xaionaro-go/xpath"
4548
"github.com/xaionaro-go/xsync"
4649
)
4750

@@ -50,6 +53,9 @@ const (
5053
dashboardFullUpdatesInterval = 2 * time.Second
5154
)
5255

56+
// TODO: DELETE ME:
57+
var qualityFilePath = must(xpath.Expand(`~/quality`))
58+
5359
func (p *Panel) focusDashboardWindow(
5460
ctx context.Context,
5561
) {
@@ -92,6 +98,82 @@ type imageInfo struct {
9298
Image *image.NRGBA
9399
}
94100

101+
func (w *dashboardWindow) renderLocalStatus(ctx context.Context) {
102+
// TODO: remove the ugly hardcode above, and make it generic (support different use cases)
103+
104+
b, err := os.ReadFile(qualityFilePath)
105+
if err != nil {
106+
logger.Debugf(ctx, "unable to open the 'quality' file: %v", err)
107+
return
108+
}
109+
words := strings.Split(strings.Trim(string(b), "\n\r\t"), " ")
110+
if len(words) != 3 {
111+
logger.Debugf(ctx, "expected 3 words, but received %d", len(words))
112+
return
113+
}
114+
115+
aQ, err := strconv.ParseInt(words[0], 10, 64)
116+
if err != nil {
117+
logger.Debugf(ctx, "unable to parse aQ '%s': %v", words[0], err)
118+
return
119+
}
120+
121+
pQ, err := strconv.ParseInt(words[1], 10, 64)
122+
if err != nil {
123+
logger.Debugf(ctx, "unable to parse pQ '%s': %v", words[0], err)
124+
return
125+
}
126+
127+
wQ, err := strconv.ParseInt(words[2], 10, 64)
128+
if err != nil {
129+
logger.Debugf(ctx, "unable to parse wQ '%s': %v", words[0], err)
130+
return
131+
}
132+
133+
qToImportance := func(in int64) widget.Importance {
134+
switch {
135+
case in <= -5:
136+
return widget.DangerImportance
137+
case in <= 0:
138+
return widget.MediumImportance
139+
default:
140+
return widget.SuccessImportance
141+
}
142+
}
143+
144+
qToStr := func(in int64) string {
145+
if in <= -30 {
146+
return "DEAD"
147+
}
148+
if in <= -5 {
149+
return "BAD"
150+
}
151+
if in <= 0 {
152+
return "SO-SO"
153+
}
154+
if in > 0 {
155+
return "GOOD"
156+
}
157+
return "UNKNOWN"
158+
}
159+
160+
qToLabel := func(name string, q int64) *widget.Label {
161+
l := widget.NewLabel(name + ":" + qToStr(q))
162+
l.Importance = qToImportance(q)
163+
l.TextStyle.Bold = true
164+
return l
165+
}
166+
167+
w.localStatus.Objects = []fyne.CanvasObject{
168+
container.NewHBox(
169+
layout.NewSpacer(),
170+
qToLabel("A", aQ),
171+
qToLabel("P", pQ),
172+
qToLabel("W", wQ),
173+
),
174+
}
175+
}
176+
95177
func (w *dashboardWindow) renderStreamStatus(ctx context.Context) {
96178
w.streamStatusLocker.Do(ctx, func() {
97179
streamDClient, ok := w.StreamD.(*client.Client)
@@ -180,6 +262,7 @@ func (p *Panel) newDashboardWindow(
180262
bgFyne := canvas.NewImageFromImage(bg)
181263
bgFyne.FillMode = canvas.ImageFillStretch
182264

265+
p.localStatus = container.NewStack()
183266
p.appStatus = widget.NewLabel("")
184267
obsLabel := widget.NewLabel("OBS:")
185268
obsLabel.Importance = widget.HighImportance
@@ -197,8 +280,13 @@ func (p *Panel) newDashboardWindow(
197280
if _, ok := p.StreamD.(*client.Client); ok {
198281
appLabel := widget.NewLabel("App:")
199282
appLabel.Importance = widget.HighImportance
200-
streamInfoItems.Add(container.NewHBox(layout.NewSpacer(), appLabel, p.appStatus))
283+
streamInfoItems.Add(container.NewHBox(
284+
layout.NewSpacer(),
285+
appLabel,
286+
p.appStatus,
287+
))
201288
}
289+
streamInfoItems.Add(container.NewHBox(layout.NewSpacer(), p.localStatus))
202290
streamInfoItems.Add(container.NewHBox(layout.NewSpacer(), obsLabel, w.streamStatus[obs.ID]))
203291
streamInfoItems.Add(container.NewHBox(layout.NewSpacer(), twLabel, w.streamStatus[twitch.ID]))
204292
streamInfoItems.Add(container.NewHBox(layout.NewSpacer(), kcLabel, w.streamStatus[kick.ID]))
@@ -575,6 +663,20 @@ func (w *dashboardWindow) startUpdatingNoLock(
575663
ctx, cancelFunc := context.WithCancel(ctx)
576664
w.stopUpdatingFunc = cancelFunc
577665

666+
w.renderLocalStatus(ctx)
667+
observability.Go(ctx, func() {
668+
t := time.NewTicker(2 * time.Second)
669+
for {
670+
select {
671+
case <-ctx.Done():
672+
return
673+
case <-t.C:
674+
}
675+
676+
w.renderLocalStatus(ctx)
677+
}
678+
})
679+
578680
cfg, err := w.GetStreamDConfig(ctx)
579681
if err != nil {
580682
w.DisplayError(fmt.Errorf("unable to get the current config: %w", err))

pkg/streampanel/panel.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,7 @@ type Panel struct {
9292
dashboardLocker xsync.Mutex
9393
dashboardShowHideButton *widget.Button
9494

95+
localStatus *fyne.Container
9596
appStatus *widget.Label
9697
appStatusData struct {
9798
prevUpdateTS time.Time

pkg/streamplayer/stream_player.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -909,8 +909,8 @@ func (p *StreamPlayerHandler) controllerLoop(
909909
return
910910
}
911911
speed = float64(uint(speed*10)) / 10 // to avoid flickering (for example between 1.0001 and 1.0)
912-
if speed < 0.5 {
913-
speed = 0.5
912+
if speed < 0.8 {
913+
speed = 0.8
914914
}
915915
if speed == curSpeed {
916916
return

0 commit comments

Comments
 (0)