Add GTK application implementation

This commit is contained in:
Olli 2026-02-26 10:41:33 +01:00
commit b7c0307f6b
29 changed files with 2564 additions and 266 deletions

115
internal/gui/serverpanel.go Normal file
View file

@ -0,0 +1,115 @@
package gui
import (
"fmt"
"strings"
"github.com/diamondburned/gotk4-adwaita/pkg/adw"
"github.com/diamondburned/gotk4/pkg/gtk/v4"
"suruatoel.xyz/mcg/data"
"suruatoel.xyz/mcg/internal/common"
)
type serverPanel struct {
*adw.Bin
toolbar *gtk.Box
statusFile *gtk.Label
statusAudio *gtk.Label
statusBitrate *gtk.Label
statusErrer *gtk.Label
statsArtist *gtk.Label
statsAlbums *gtk.Label
statsSongs *gtk.Label
statsDBPlaytime *gtk.Label
statsPlaytime *gtk.Label
statsUptime *gtk.Label
outputDevices *gtk.ListBox
outputDeviceChangeCB OutputDeviceChangeCB
}
type OutputDeviceChangeCB func(device *common.OutputDevice, enable bool)
func newServerPanel() *serverPanel {
panel := serverPanel{}
panel.loadWidgets()
return &panel
}
func (p *serverPanel) loadWidgets() {
builder := gtk.NewBuilderFromString(data.ServerPanelXML)
p.Bin = builder.GetObject("McgServerPanel").Cast().(*adw.Bin)
p.toolbar = builder.GetObject("toolbar").Cast().(*gtk.Box)
p.statusFile = builder.GetObject("status_file").Cast().(*gtk.Label)
p.statusAudio = builder.GetObject("status_audio").Cast().(*gtk.Label)
p.statusBitrate = builder.GetObject("status_bitrate").Cast().(*gtk.Label)
p.statusErrer = builder.GetObject("status_error").Cast().(*gtk.Label)
p.statsArtist = builder.GetObject("stats_artists").Cast().(*gtk.Label)
p.statsAlbums = builder.GetObject("stats_albums").Cast().(*gtk.Label)
p.statsSongs = builder.GetObject("stats_songs").Cast().(*gtk.Label)
p.statsDBPlaytime = builder.GetObject("stats_dbplaytime").Cast().(*gtk.Label)
p.statsPlaytime = builder.GetObject("stats_playtime").Cast().(*gtk.Label)
p.statsUptime = builder.GetObject("stats_uptime").Cast().(*gtk.Label)
p.outputDevices = builder.GetObject("output_devices").Cast().(*gtk.ListBox)
}
func (p *serverPanel) ReceiveOutputDeviceChange(callback OutputDeviceChangeCB) {
p.outputDeviceChangeCB = callback
}
func (p *serverPanel) Toolbar() gtk.Widgetter {
return p.toolbar
}
func (p *serverPanel) Status(file, audio, bitrate, errorMessage string) {
p.statusFile.SetText(file)
p.statusAudio.SetText(p.formatAudio(audio))
p.statusBitrate.SetText(p.formatBitrate(bitrate))
p.statusErrer.SetText(errorMessage)
}
func (p *serverPanel) formatAudio(audio string) string {
parts := strings.Split(audio, ":")
if len(parts) == 3 {
return fmt.Sprintf("%sHz, %sbit, %schannels", parts[0], parts[1], parts[2])
}
return ""
}
func (p *serverPanel) formatBitrate(bitrate string) string {
if bitrate != "" {
return bitrate + "kb/s"
}
return ""
}
func (p *serverPanel) Statistics(artists, albums, songs, dbplaytime, playtime, uptime string) {
p.statsArtist.SetText(artists)
p.statsAlbums.SetText(albums)
p.statsSongs.SetText(songs)
p.statsDBPlaytime.SetText(dbplaytime)
p.statsPlaytime.SetText(playtime)
p.statsUptime.SetText(uptime)
}
func (p *serverPanel) OutputDevices(devices []*common.OutputDevice) {
p.outputDevices.RemoveAll()
for _, device := range devices {
deviceButton := gtk.NewCheckButtonWithLabel(device.Name)
if device.Enabled {
deviceButton.SetActive(true)
}
deviceButton.ConnectToggled(func() {
if p.outputDeviceChangeCB != nil {
p.outputDeviceChangeCB(device, deviceButton.Active())
}
})
p.outputDevices.Insert(deviceButton, -1)
}
}