package config import ( "encoding/json" "log" "os" "path/filepath" ) // Config holds persistent application settings. type Config struct { Theme string `json:"theme"` PreferredAccel string `json:"preferredAccel"` OutputDir string `json:"outputDir"` NamingRule string `json:"namingRule"` FFmpegPath string `json:"ffmpegPath"` FFprobePath string `json:"ffprobePath"` dir string `json:"-"` // config directory path } var current *Config // Load reads config from AppData, creating defaults if needed. func Load() *Config { dir := appDataDir() _ = os.MkdirAll(dir, 0755) cfg := &Config{ Theme: "light", NamingRule: "{name}_{codec}", dir: dir, } path := filepath.Join(dir, "config.json") data, err := os.ReadFile(path) if err != nil { log.Printf("[config] read %s: %v (creating new)", path, err) cfg.Save() log.Printf("[config] created new config at %s", path) return cfg } if err := json.Unmarshal(data, cfg); err != nil { log.Printf("[config] corrupted config, resetting: %v", err) cfg = &Config{Theme: "light", NamingRule: "{name}_{codec}", dir: dir} cfg.Save() return cfg } cfg.dir = dir log.Printf("[config] loaded from %s: theme=%s accel=%s", path, cfg.Theme, cfg.PreferredAccel) current = cfg return cfg } // Save writes the current config to disk. func (c *Config) Save() { path := filepath.Join(c.dir, "config.json") data, err := json.MarshalIndent(c, "", " ") if err != nil { log.Printf("[config] marshal error: %v", err) return } if err := os.WriteFile(path, data, 0644); err != nil { log.Printf("[config] write error: %v", err) return } log.Printf("[config] saved: accel=%s out=%s", c.PreferredAccel, c.OutputDir) } // BinDir returns the directory where extracted ffmpeg binaries live. func (c *Config) BinDir() string { d := filepath.Join(c.dir, "bin") os.MkdirAll(d, 0755) return d } // Get returns the current global config, loading if needed. func Get() *Config { if current == nil { return Load() } return current }