From 0ebc3adf4ae52c0c944440fdf5b59f3607fc9fd3 Mon Sep 17 00:00:00 2001 From: NeilClack Date: Sun, 31 May 2026 12:08:19 -0500 Subject: [PATCH] Proclamations change colors! --- internal/application/application.go | 1 + internal/db/newDb.go | 2 +- internal/db/schema.go | 6 ++ internal/page/proclamationOptions.go | 4 +- internal/page/scrollerPage.go | 118 +++++++++++++++++++++++---- internal/sync/sync.go | 28 ++++++- 6 files changed, 138 insertions(+), 21 deletions(-) diff --git a/internal/application/application.go b/internal/application/application.go index b00ec7a..424bd4f 100644 --- a/internal/application/application.go +++ b/internal/application/application.go @@ -157,6 +157,7 @@ func Run() { // Sync the proclamations from the API to the Database sync.SyncProclamations(DB) sync.SyncCategories(DB) + sync.SyncFrequencies(DB) app.runEventLoop() } diff --git a/internal/db/newDb.go b/internal/db/newDb.go index 21a3e1b..ddfc273 100644 --- a/internal/db/newDb.go +++ b/internal/db/newDb.go @@ -42,7 +42,7 @@ func Connect(dbpath string) (*gorm.DB, error) { // Migrate the database schema func Migrate(db *gorm.DB) error { // Pass all models to be migrated to this function call. - if err := db.AutoMigrate(&AppConfig{}, &Log{}, &Proclamation{}, &ProclamationCategory{}); err != nil { + if err := db.AutoMigrate(&AppConfig{}, &Log{}, &Proclamation{}, &ProclamationCategory{}, &SolfeggioFrequency{}); err != nil { return err } return nil diff --git a/internal/db/schema.go b/internal/db/schema.go index 89775d1..1b5437a 100644 --- a/internal/db/schema.go +++ b/internal/db/schema.go @@ -42,3 +42,9 @@ type ProclamationCategory struct { Name string ParentId int } + +type SolfeggioFrequency struct { + ID int `gorm:"primaryKey"` + Name string + Value int +} diff --git a/internal/page/proclamationOptions.go b/internal/page/proclamationOptions.go index 9f94f5c..9ec0592 100644 --- a/internal/page/proclamationOptions.go +++ b/internal/page/proclamationOptions.go @@ -82,7 +82,7 @@ func (p *ProclamationOptions) Init(ctx *PageCtx) error { p.scrollTrackWidth = 30 p.scrollTrackX = p.ScreenWidth - p.scrollTrackWidth var err error - + // Syncronize proclamations first var allProcs []db.Proclamation allProcs, err = sync.SyncProclamations(ctx.DbPtr) @@ -91,6 +91,8 @@ func (p *ProclamationOptions) Init(ctx *PageCtx) error { ctx.DbPtr.Find(&allProcs) } + sync.SyncFrequencies(ctx.DbPtr) + fm := fontManager.Get() font, _ := fm.GetFont("Roboto-Regular") p.font = font diff --git a/internal/page/scrollerPage.go b/internal/page/scrollerPage.go index dd8b2c3..80dfb74 100644 --- a/internal/page/scrollerPage.go +++ b/internal/page/scrollerPage.go @@ -24,18 +24,27 @@ const ( defaultProclamationPlayCount int = 1 ) +type ScrollerProclamation struct { + db.Proclamation + colorPattern.ColorPattern + ColorPalette []sdl.Color +} + type Line struct { words []StringItem width int32 + color sdl.Color // Color for the entire line } // proclamationStream tracks one proclamation and how many full loops it should play. type proclamationStream struct { - name string - words []string - repeat int - completed int - wordIndex int + name string + words []string + repeat int + completed int + wordIndex int + palette []sdl.Color // Color palette for this proclamation + colorIndex int // Track which color to use next } // LineDeque is a double-ended queue for Line values backed by a circular buffer. @@ -155,12 +164,16 @@ type ScrollerPage struct { velocityState int autoVelocity bool hold float32 + + // Color palette settings + useColorPalettes bool } func (p *ScrollerPage) Init(ctx *PageCtx) error { p.increment = 100.0 p.velocity = 800.0 p.SetAutoVelocity(true, -4000.0, 4000.0, 100.0, 2.5, 6.0) + p.useColorPalettes = true // Default to enabled sm := shaderManager.Get() fm := fontManager.Get() @@ -268,11 +281,36 @@ func (p *ScrollerPage) Init(ctx *PageCtx) error { func (p *ScrollerPage) loadProclamations() error { p.streams = p.streams[:0] + // Load all solfeggio frequencies + var frequencies []db.SolfeggioFrequency + if err := p.Context.DbPtr.Find(&frequencies).Error; err != nil { + return fmt.Errorf("failed to load solfeggio frequencies: %v", err) + } + + // Create a map of frequency ID to its value + frequencyMap := make(map[int]int) + for _, freq := range frequencies { + frequencyMap[freq.ID] = freq.Value + } + + // Map frequency values to their color palettes + frequencyPalettes := map[int][]sdl.Color{ + 396: colors.Freq_396_Colors[:], + 417: colors.Freq_417_Colors[:], + 528: colors.Freq_528_Colors[:], // Default proclamation + 639: colors.Freq_639_Colors[:], + 741: colors.Freq_741_Colors[:], + 852: colors.Freq_852_Colors[:], + 963: colors.Freq_963_Colors[:], + } + + // Load selected proclamations var selected []db.Proclamation if err := p.Context.DbPtr.Where("selected = ?", true).Find(&selected).Error; err != nil { return err } + // Load default proclamation var defaultProclamation db.Proclamation if err := p.Context.DbPtr.Where("ID = ?", defaultProclamationID).First(&defaultProclamation).Error; err != nil { return err @@ -282,7 +320,7 @@ func (p *ScrollerPage) loadProclamations() error { // Build interleaved stream: // each selected proclamation repeats N times, then default repeats once. for _, proclamation := range selected { - // Prevent default proclamation from being treated as a normal selected proclamation. + // Skip default proclamation if it's in the selected list if proclamation.ID == defaultProclamationID { continue } @@ -292,17 +330,35 @@ func (p *ScrollerPage) loadProclamations() error { continue } + // Get the frequency value for this proclamation + freqValue, ok := frequencyMap[proclamation.SolfeggioFrequencyID] + if !ok { + logger.Warning("No frequency found for proclamation %s, using default palette", proclamation.Name) + freqValue = 528 // Default to 528 if frequency not found + } + + // Get the palette for this frequency + palette, ok := frequencyPalettes[freqValue] + if !ok { + logger.Warning("No palette found for frequency %d, using default palette", freqValue) + palette = colors.Freq_528_Colors[:] // Fallback to default palette + } + p.streams = append(p.streams, proclamationStream{ - name: proclamation.Name, - words: words, - repeat: proclamationPlayCount, // 10 + name: proclamation.Name, + words: words, + repeat: proclamationPlayCount, + palette: palette, + colorIndex: 0, }) if len(defaultWords) > 0 { p.streams = append(p.streams, proclamationStream{ - name: defaultProclamation.Name, - words: defaultWords, - repeat: 1, // play once between selected proclamations + name: defaultProclamation.Name, + words: defaultWords, + repeat: 1, + palette: colors.Freq_528_Colors[:], // Default palette for default proclamation + colorIndex: 0, }) } } @@ -310,9 +366,11 @@ func (p *ScrollerPage) loadProclamations() error { // Fallback: if no non-default selected proclamations, at least play default. if len(p.streams) == 0 && len(defaultWords) > 0 { p.streams = append(p.streams, proclamationStream{ - name: defaultProclamation.Name, - words: defaultWords, - repeat: 1, + name: defaultProclamation.Name, + words: defaultWords, + repeat: 1, + palette: colors.Freq_528_Colors[:], + colorIndex: 0, }) } @@ -346,11 +404,13 @@ func (p *ScrollerPage) nextLineWords() []string { if targetRepeats <= 0 { targetRepeats = 1 } - logger.Debug("Now playing proclamation: %s", s.name) + logger.Info("Now playing proclamation: %s", s.name) if s.completed >= targetRepeats { s.completed = 0 s.wordIndex = 0 + s.colorIndex = 0 // Reset color index when proclamation restarts p.streamIndex = (p.streamIndex + 1) % len(p.streams) + fmt.Println("Now playing proclamation:", p.streams[p.streamIndex].name) } } @@ -377,6 +437,24 @@ func (p *ScrollerPage) getCachedWord(word string) (StringItem, error) { func (p *ScrollerPage) buildLineFromWords(words []string) (Line, error) { line := Line{words: []StringItem{}} + // Get the current proclamation's color palette + var lineColor sdl.Color + if p.useColorPalettes && len(p.streams) > 0 { + currentStream := &p.streams[p.streamIndex] + if len(currentStream.palette) > 0 { + // Use the current color from the palette + lineColor = currentStream.palette[currentStream.colorIndex] + // Increment color index for the next line + currentStream.colorIndex = (currentStream.colorIndex + 1) % len(currentStream.palette) + } else { + // Fallback to default color if no palette is found + lineColor = p.colorPattern.Color() + } + } else { + // Use the default color pattern if useColorPalettes is false + lineColor = p.colorPattern.Color() + } + for _, word := range words { if word == "" { continue @@ -388,7 +466,7 @@ func (p *ScrollerPage) buildLineFromWords(words []string) (Line, error) { } item := cached - item.Color = p.colorPattern.Color() + item.Color = lineColor // Assign the line color to all words in the line if len(line.words) > 0 { line.width += p.spaceWidth @@ -397,6 +475,7 @@ func (p *ScrollerPage) buildLineFromWords(words []string) (Line, error) { line.width += item.W } + line.color = lineColor // Store the line color return line, nil } @@ -607,6 +686,11 @@ func (p *ScrollerPage) SetAutoVelocity(enabled bool, floor, ceiling, step, delay p.velocity = p.velocityFloor } +// SetUseColorPalettes enables or disables the use of color palettes for lines. +func (p *ScrollerPage) SetUseColorPalettes(enabled bool) { + p.useColorPalettes = enabled +} + // updateAutoVelocity handles automatic velocity changes. func (p *ScrollerPage) updateAutoVelocity(dt float32) { if !p.autoVelocity { diff --git a/internal/sync/sync.go b/internal/sync/sync.go index 1d27636..3aa2d4c 100644 --- a/internal/sync/sync.go +++ b/internal/sync/sync.go @@ -15,7 +15,7 @@ var htmlRegex = regexp.MustCompile(`<[^>]*>`) // SyncProclamations fetches data from the API, cleans it, and updates the local DB. // It returns the slice of proclamations so the UI can update immediately. func SyncProclamations(database *gorm.DB) ([]db.Proclamation, error) { - fullURL := "https://portal.rhemawavetech.com/api/v1/proclamations" + fullURL := "https://portal.radiantwavetech.com/api/v1/proclamations" logger.Debug("Syncronizing proclamations. URL: %s", fullURL) proclamations, err := netreq.GetJSON[db.Proclamation](fullURL) @@ -93,7 +93,7 @@ func SyncProclamations(database *gorm.DB) ([]db.Proclamation, error) { } func SyncCategories(database *gorm.DB) ([]db.ProclamationCategory, error) { - fullURL := "https://portal.rhemawavetech.com/api/v1/categories" + fullURL := "https://portal.radiantwavetech.com/api/v1/categories" categories, err := netreq.GetJSON[db.ProclamationCategory](fullURL) if err != nil { logger.Error("Category sync failed, skipping update: %v", err) @@ -118,3 +118,27 @@ func SyncCategories(database *gorm.DB) ([]db.ProclamationCategory, error) { logger.Info("Successfully synced proclamation categories: %d", len(categories)) return categories, nil } + +func SyncFrequencies(database *gorm.DB) ([]db.SolfeggioFrequency, error) { + fullURL := "https://portal.radiantwavetech.com/api/v1/frequencies" + frequencies, err := netreq.GetJSON[db.SolfeggioFrequency](fullURL) + if err != nil { + logger.Error("Frequency sync failed, skipping update: %v", err) + return nil, err + } + err = database.Transaction(func(tx *gorm.DB) error { + if err := tx.Where("1 = 1").Delete(&db.SolfeggioFrequency{}).Error; err != nil { + return err + } + if err := tx.Save(&frequencies).Error; err != nil { + return err + } + return nil + }) + if err != nil { + logger.Error("failed to sync solfeggio frequencies: %v", err) + return nil, err + } + logger.Info("Succesfully synced solfeggio frequencies: %d", len(frequencies)) + return frequencies, nil +}