summaryrefslogtreecommitdiff
path: root/internal/gui/audio_paths.go
diff options
context:
space:
mode:
authorPaul Buetow <paul@buetow.org>2026-04-02 07:16:49 +0300
committerPaul Buetow <paul@buetow.org>2026-04-02 07:16:49 +0300
commite96cc2578595a0ec22a07819cd0eb1b0b0c711f7 (patch)
tree0df43845dedeb27ba2afaadfb5a821aeee7a713b /internal/gui/audio_paths.go
parentfaa2465955445ac1cb1461eb70a98280d32fbf9a (diff)
Harden GUI audio loading for Gemini
Diffstat (limited to 'internal/gui/audio_paths.go')
-rw-r--r--internal/gui/audio_paths.go74
1 files changed, 74 insertions, 0 deletions
diff --git a/internal/gui/audio_paths.go b/internal/gui/audio_paths.go
new file mode 100644
index 0000000..baee232
--- /dev/null
+++ b/internal/gui/audio_paths.go
@@ -0,0 +1,74 @@
+package gui
+
+import (
+ "os"
+ "path/filepath"
+ "strings"
+ "time"
+)
+
+var supportedAudioExtensions = map[string]struct{}{
+ ".aac": {},
+ ".flac": {},
+ ".mp3": {},
+ ".opus": {},
+ ".wav": {},
+}
+
+func (a *Application) resolveSingleAudioFile(wordDir string) string {
+ return resolveAudioFileByBaseName(wordDir, "audio")
+}
+
+func (a *Application) resolveBgBgAudioFiles(wordDir string) (string, string) {
+ return resolveAudioFileByBaseName(wordDir, "audio_front"), resolveAudioFileByBaseName(wordDir, "audio_back")
+}
+
+func (a *Application) hasAnyAudioFile(wordDir string) bool {
+ single := a.resolveSingleAudioFile(wordDir)
+ if single != "" {
+ return true
+ }
+
+ front, back := a.resolveBgBgAudioFiles(wordDir)
+ return front != "" || back != ""
+}
+
+func resolveAudioFileByBaseName(wordDir, baseName string) string {
+ entries, err := os.ReadDir(wordDir)
+ if err != nil {
+ return ""
+ }
+
+ prefix := baseName + "."
+ var resolved string
+ var resolvedModTime time.Time
+
+ for _, entry := range entries {
+ if entry.IsDir() {
+ continue
+ }
+
+ name := entry.Name()
+ if !strings.HasPrefix(name, prefix) {
+ continue
+ }
+
+ ext := strings.ToLower(filepath.Ext(name))
+ if _, ok := supportedAudioExtensions[ext]; !ok {
+ continue
+ }
+
+ info, err := entry.Info()
+ if err != nil {
+ continue
+ }
+
+ candidate := filepath.Join(wordDir, name)
+ if resolved == "" || info.ModTime().After(resolvedModTime) || (info.ModTime().Equal(resolvedModTime) && candidate < resolved) {
+ resolved = candidate
+ resolvedModTime = info.ModTime()
+ }
+ }
+
+ return resolved
+}