From 6745dba616a821ffcab2d6476aac9065571b61e9 Mon Sep 17 00:00:00 2001 From: Failure Date: Sat, 13 Dec 2025 00:58:52 -0800 Subject: [PATCH] feature: prefs, search, LF-ification --- threenis/ui.go | 268 ++++++++++++++++++++++++++----------------------- 1 file changed, 145 insertions(+), 123 deletions(-) diff --git a/threenis/ui.go b/threenis/ui.go index 589e5e7..2fbfd99 100644 --- a/threenis/ui.go +++ b/threenis/ui.go @@ -1,123 +1,145 @@ -package threenis - -import ( - "log" - "os/exec" - "strings" - - "fyne.io/fyne/v2" - "fyne.io/fyne/v2/app" - "fyne.io/fyne/v2/container" - "fyne.io/fyne/v2/layout" - "fyne.io/fyne/v2/widget" - "layeh.com/gumble/gumble" - "layeh.com/gumble/gumbleffmpeg" - "layeh.com/gumble/gumbleutil" - _ "layeh.com/gumble/opus" -) - -type Threenis struct { - stream *gumbleffmpeg.Stream - process *exec.Cmd -} - -type SourceStream string - -func ThreenisSource(filename string) gumbleffmpeg.Source { - return SourceStream(filename) -} - -func (s SourceStream) Arguments() []string { - return []string{"-fflags", "nobuffer", "-flags", "low_delay", "-f", "s16le", "-ac", "2", "-i", "udp://127.0.0.1:2888"} -} - -func (SourceStream) Start(*exec.Cmd) error { - return nil -} - -func (SourceStream) Done() { -} - -func (t *Threenis) Mumble(server string, username string, password string, channel string) { - MumbleClient(server, username, password, gumbleutil.AutoBitrate, gumbleutil.Listener{ - Connect: func(e *gumble.ConnectEvent) { - c := e.Client.Channels.Find(channel) - if c != nil { - e.Client.Self.Move(c) - } - t.stream = gumbleffmpeg.New(e.Client, ThreenisSource("")) - if err := t.stream.Play(); err != nil { - log.Println(err) - } - - }, - }) -} - -func Ui() { - myApp := app.New() - myWindow := myApp.NewWindow("Threenis") - myWindow.Resize(fyne.NewSize(800, 400)) - myWindow.SetFixedSize(true) - - processes := GetProcessStrings() - threenis := Threenis{} - - defer func() { - threenis.stream.Stop() - if threenis.process != nil && threenis.process.Process != nil { - threenis.process.Process.Kill() - } - }() - - list := widget.NewList( - func() int { - return len(processes) - }, - func() fyne.CanvasObject { - return widget.NewLabel("template") - }, - func(i widget.ListItemID, o fyne.CanvasObject) { - o.(*widget.Label).SetText(processes[i]) - }) - - list.OnSelected = func(id widget.ListItemID) { - if threenis.process != nil && threenis.process.Process != nil { - threenis.process.Process.Kill() - } - threenis.process = exec.Command("./ApplicationLoopback.exe", strings.Split(processes[id], " - ")[0], "includetree") - log.Println(strings.Split(processes[id], " - ")[0]) - err := threenis.process.Start() - if err != nil { - log.Println(err) - } - - } - - serverLabel := widget.NewLabel("Server") - server := widget.NewEntry() - - usernameLabel := widget.NewLabel("Username") - username := widget.NewEntry() - passwordLabel := widget.NewLabel("Password") - password := widget.NewEntry() - - channelLabel := widget.NewLabel("Channel") - channel := widget.NewEntry() - - refresh := widget.NewButton("Refresh", func() { - processes = GetProcessStrings() - list.Refresh() - }) - - connect := widget.NewButton("Connect", func() { - go threenis.Mumble(server.Text, username.Text, password.Text, channel.Text) - }) - - form := container.New(layout.NewFormLayout(), serverLabel, server, usernameLabel, username, passwordLabel, password, channelLabel, channel, refresh, connect) - - grid := container.New(layout.NewGridLayout(2), list, form) - - myWindow.SetContent(grid) - myWindow.ShowAndRun() -} +package threenis + +import ( + "log" + "os/exec" + "strings" + + "fyne.io/fyne/v2" + "fyne.io/fyne/v2/app" + "fyne.io/fyne/v2/container" + "fyne.io/fyne/v2/layout" + "fyne.io/fyne/v2/widget" + "layeh.com/gumble/gumble" + "layeh.com/gumble/gumbleffmpeg" + "layeh.com/gumble/gumbleutil" + _ "layeh.com/gumble/opus" +) + +type Threenis struct { + stream *gumbleffmpeg.Stream + process *exec.Cmd +} + +type SourceStream string + +func ThreenisSource(filename string) gumbleffmpeg.Source { + return SourceStream(filename) +} + +func (s SourceStream) Arguments() []string { + return []string{"-fflags", "nobuffer", "-flags", "low_delay", "-f", "s16le", "-ac", "2", "-i", "udp://127.0.0.1:2888"} +} + +func (SourceStream) Start(*exec.Cmd) error { + return nil +} + +func (SourceStream) Done() { +} + +func (t *Threenis) Mumble(server string, username string, password string, channel string) { + MumbleClient(server, username, password, gumbleutil.AutoBitrate, gumbleutil.Listener{ + Connect: func(e *gumble.ConnectEvent) { + c := e.Client.Channels.Find(channel) + if c != nil { + e.Client.Self.Move(c) + } + t.stream = gumbleffmpeg.New(e.Client, ThreenisSource("")) + if err := t.stream.Play(); err != nil { + log.Println(err) + } + + }, + }) +} + +func Ui() { + threenisApp := app.NewWithID("threenis") + window := threenisApp.NewWindow("Threenis") + window.Resize(fyne.NewSize(800, 400)) + + processes := GetProcessStrings() + threenis := Threenis{} + + defer func() { + threenis.stream.Stop() + if threenis.process != nil && threenis.process.Process != nil { + threenis.process.Process.Kill() + } + }() + + list := widget.NewList( + func() int { + return len(processes) + }, + func() fyne.CanvasObject { + return widget.NewLabel("template") + }, + func(i widget.ListItemID, o fyne.CanvasObject) { + o.(*widget.Label).SetText(processes[i]) + }) + + list.OnSelected = func(id widget.ListItemID) { + if threenis.process != nil && threenis.process.Process != nil { + threenis.process.Process.Kill() + } + threenis.process = exec.Command("./ApplicationLoopback.exe", strings.Split(processes[id], " - ")[0], "includetree") + log.Println(strings.Split(processes[id], " - ")[0]) + err := threenis.process.Start() + if err != nil { + log.Println(err) + } + + } + + serverLabel := widget.NewLabel("Server") + server := widget.NewEntry() + server.SetText(threenisApp.Preferences().StringWithFallback("server", "")) + + usernameLabel := widget.NewLabel("Username") + username := widget.NewEntry() + username.SetText(threenisApp.Preferences().StringWithFallback("username", "")) + + passwordLabel := widget.NewLabel("Password") + password := widget.NewEntry() + password.SetText(threenisApp.Preferences().StringWithFallback("password", "")) + + channelLabel := widget.NewLabel("Channel") + channel := widget.NewEntry() + channel.SetText(threenisApp.Preferences().StringWithFallback("channel", "")) + + refresh := widget.NewButton("Refresh", func() { + processes = GetProcessStrings() + list.Refresh() + }) + + connect := widget.NewButton("Connect", func() { + threenisApp.Preferences().SetString("server", server.Text) + threenisApp.Preferences().SetString("username", username.Text) + threenisApp.Preferences().SetString("password", password.Text) + threenisApp.Preferences().SetString("channel", channel.Text) + go threenis.Mumble(server.Text, username.Text, password.Text, channel.Text) + }) + + search := widget.NewEntry() + search.OnChanged = func(s string) { + procs := GetProcessStrings() + processes = make([]string, 0) + for _, proc := range procs { + if strings.Contains(strings.ToLower(proc), strings.ToLower(s)) { + processes = append(processes, proc) + } + } + list.Refresh() + } + + content := container.NewBorder(nil, search, nil, nil, list) + + form := container.New(layout.NewFormLayout(), serverLabel, server, usernameLabel, username, passwordLabel, password, channelLabel, channel, refresh, connect) + + grid := container.New(layout.NewGridLayout(2), content, form) + + window.SetContent(grid) + window.ShowAndRun() +}