package page import ( "fmt" "github.com/go-gl/gl/v3.3-core/gl" "github.com/veandco/go-sdl2/sdl" "rhemawavetech.com/rhemawave/internal/colors" "rhemawavetech.com/rhemawave/internal/db" "rhemawavetech.com/rhemawave/internal/fontManager" "rhemawavetech.com/rhemawave/internal/logger" "rhemawavetech.com/rhemawave/internal/shaderManager" ) type AudioDevices struct { Base font *fontManager.FontEntry textShader *shaderManager.Shader solidShader *shaderManager.Shader title StringItem prompt StringItem AudioStatusToggle StringItem verticalMargin int32 ItemScale float32 CfgPtr *db.AppConfig } func (p *AudioDevices) Init(ctx *PageCtx) error { var err error p.verticalMargin = int32(20) // Get font fm := fontManager.Get() font, ok := fm.GetFont("Roboto-Regular") if !ok { return fmt.Errorf("failed to get font: %w", sdl.GetError()) } p.font = font // Get shaders sm := shaderManager.Get() p.textShader, ok = sm.Get("text") if !ok { return fmt.Errorf("failed to get text shader: %w", sdl.GetError()) } p.solidShader, ok = sm.Get("solid_color") if !ok { return fmt.Errorf("failed to get solid_color shader: %w", sdl.GetError()) } // Initialize base if err := p.Base.Init(ctx); err != nil { return fmt.Errorf("base init failed: %w", err) } // Get font size from database baseFontSize := p.Context.CfgPtr.StandardFontSize // Calculate scales titleScale := float32(64) / float32(baseFontSize) p.ItemScale = float32(32) / float32(baseFontSize) // Create title p.title, err = NewStringItem("Toggle Audio", p.font, colors.White) if err != nil { return fmt.Errorf("creating title: %w", err) } p.title.Scale(titleScale) // Create prompt p.prompt, err = NewStringItem("Switch On/Off with Enter. Setting saves immediately.", p.font, colors.White) if err != nil { return fmt.Errorf("creating prompt: %w", err) } p.prompt.Scale(p.ItemScale) if err = p.CreateAudioStatusItem(); err != nil { logger.Error("failed to create AudioStatusItem in AudioDevices.Init()") } p.layout() return nil } func (p *AudioDevices) CreateAudioStatusItem() error { on := p.Context.CfgPtr.AudioEnabled statusString := "Turn Audio Off" // The audio is ON color := colors.Green if !on { statusString = "Turn Audio on" color = colors.Red } audioStatusStringItem, err := NewStringItem(statusString, p.font, color) if err != nil { return fmt.Errorf("failed to create '%s' string item: %v", statusString, err) } fmt.Printf("AudioStatusToggle (%d)", audioStatusStringItem.ID) audioStatusStringItem.Scale(p.ItemScale) p.AudioStatusToggle = audioStatusStringItem // Position the audio toggle p.AudioStatusToggle.X = p.ScreenCenterX - p.AudioStatusToggle.W/2 // Horizontal Position p.AudioStatusToggle.Y = p.ScreenCenterY + (p.AudioStatusToggle.H / 2) // Vertical Position return nil } func (p *AudioDevices) layout() { // Position title at the top p.title.X = p.ScreenCenterX - p.title.W/2 p.title.Y = p.ScreenHeight - p.title.H - p.verticalMargin*2 // Position prompt below the title p.prompt.X = p.ScreenCenterX - p.prompt.W/2 p.prompt.Y = p.title.Y - p.verticalMargin*2 - p.prompt.H } func (p *AudioDevices) ToggleAudio() { // Toggle current setting p.Context.CfgPtr.AudioEnabled = !p.Context.CfgPtr.AudioEnabled // Update the database p.Context.DbPtr.Save(p.Context.CfgPtr) // Update the configuration p.Context.RefreshConfig() // Update AudioEnabled UI element p.CreateAudioStatusItem() } func (p *AudioDevices) HandleEvent(event *sdl.Event) error { e, ok := (*event).(*sdl.KeyboardEvent) if !ok || e.Type != sdl.KEYDOWN { return nil } switch e.Keysym.Sym { case sdl.K_RETURN: p.ToggleAudio() case sdl.K_BACKSPACE: p.Context.NavigateTo(SETTINGS) } return nil } func (p *AudioDevices) Render() error { if err := p.RenderTexture(p.textShader, p.title.ID, p.title.Position(), p.title.RawDimensions(), p.title.Color); err != nil { logger.Error("unable to render title texture: %v", err) return fmt.Errorf("unable to render title texture: %w", err) } if err := p.RenderTexture(p.textShader, p.prompt.ID, p.prompt.Position(), p.prompt.RawDimensions(), p.prompt.Color); err != nil { logger.Error("unable to render prompt texture: %v", err) return fmt.Errorf("unable to render prompt texture: %w", err) } if err := p.RenderTexture(p.textShader, p.AudioStatusToggle.ID, p.AudioStatusToggle.Position(), p.AudioStatusToggle.RawDimensions(), p.AudioStatusToggle.Color); err != nil { logger.Error("unable to render audioStatusToggle texture: %v", err) return fmt.Errorf("unable to render audioStatusToggle texture: %w", err) } return nil } func (p *AudioDevices) Destroy() error { gl.DeleteTextures(1, &p.title.ID) gl.DeleteTextures(1, &p.prompt.ID) return nil }