package modernzconf import ( "gitgud.io/mike/mpv-manager/internal/scriptopts" ) // Value types for Option.ValueType. const ( TypeBool = scriptopts.TypeBool TypeInt = scriptopts.TypeInt TypeFloat = scriptopts.TypeFloat TypeString = scriptopts.TypeString TypeChoice = scriptopts.TypeChoice ) // Option describes a curated, editable modernz.conf option. type Option struct { Key string Label string Default string Recommended string Description string ValueType string // "bool" | "int" | "float" | "string" | "choice" Choices []string // for ValueType == "choice" ChoiceLabels map[string]string Min, Max float64 // bounds for int/float } // Managed install defaults override the upstream ModernZ defaults where the // manager deliberately provides a more predictable cross-resolution setup. const ( ManagedVidscaleDefault = "no" ManagedScaleWindowedDefault = "1.0" ManagedScaleFullscreenDefault = "1.0" ) var managedInstallDefaults = []struct { key string value string }{ {key: "vidscale", value: ManagedVidscaleDefault}, {key: "scalewindowed", value: ManagedScaleWindowedDefault}, {key: "scalefullscreen", value: ManagedScaleFullscreenDefault}, } // knownOptions is the curated set of editable modernz.conf options, based on // the default modernz.conf shipped by ModernZ (and installed by mpv-manager). // Bool options use the file's native yes/no values. var knownOptions = []Option{ {Key: "language", Default: "default", Description: "Interface language ('default' or a ModernZ translation code)", ValueType: TypeString}, {Key: "layout", Default: "default", Description: "OSC layout style", ValueType: TypeChoice, Choices: []string{"default", "compact", "mini", "seekbar"}}, {Key: "icon_theme", Default: "fluent", Description: "Icon theme", ValueType: TypeChoice, Choices: []string{"fluent", "material"}}, { Key: "vidscale", Label: "Scaling behavior", Default: "auto", Recommended: ManagedVidscaleDefault, Description: "Choose whether ModernZ stays a consistent size or grows and shrinks with the player window", ValueType: TypeChoice, Choices: []string{"no", "auto", "yes"}, ChoiceLabels: map[string]string{ "no": "Consistent size (recommended)", "auto": "Follow mpv setting", "yes": "Scale with player window", }, }, { Key: "scalewindowed", Label: "Windowed UI size", Default: "1.0", Recommended: ManagedScaleWindowedDefault, Description: "Size multiplier while windowed (1.0 = 100%; try 1.25, 1.5, or 2.0 for HiDPI displays)", ValueType: TypeFloat, Min: 0.1, Max: 5.0, }, { Key: "scalefullscreen", Label: "Fullscreen UI size", Default: "1.0", Recommended: ManagedScaleFullscreenDefault, Description: "Size multiplier in fullscreen; keep this equal to Windowed UI size to avoid a size jump", ValueType: TypeFloat, Min: 0.1, Max: 5.0, }, {Key: "window_top_bar", Default: "auto", Description: "Show the top bar in borderless/fullscreen mode", ValueType: TypeChoice, Choices: []string{"auto", "yes", "no"}}, {Key: "idlescreen", Default: "yes", Description: "Show the mpv logo when idle", ValueType: TypeBool}, {Key: "showwindowed", Default: "yes", Description: "Show the OSC when windowed", ValueType: TypeBool}, {Key: "showfullscreen", Default: "yes", Description: "Show the OSC in fullscreen", ValueType: TypeBool}, {Key: "hidetimeout", Default: "1500", Description: "Milliseconds before the OSC hides without mouse movement", ValueType: TypeInt, Min: 0, Max: 60000}, {Key: "show_title", Default: "yes", Description: "Show the media title above the seekbar", ValueType: TypeBool}, {Key: "title_font_size", Default: "24", Description: "Font size of the title text", ValueType: TypeInt, Min: 8, Max: 72}, {Key: "time_format", Default: "dynamic", Description: "Time display format (dynamic MM:SS or fixed HH:MM:SS)", ValueType: TypeChoice, Choices: []string{"dynamic", "fixed"}}, {Key: "seekbar_height", Default: "medium", Description: "Seekbar height preset", ValueType: TypeChoice, Choices: []string{"small", "medium", "large", "xlarge"}}, {Key: "osc_color", Default: "#000000", Description: "Accent color of the OSC and title bar (hex)", ValueType: TypeString}, {Key: "seekbarfg_color", Default: "#FF8232", Description: "Color of the seekbar progress (hex)", ValueType: TypeString}, {Key: "volume_control", Default: "yes", Description: "Show the mute button and volume slider", ValueType: TypeBool}, {Key: "volume_control_type", Default: "linear", Description: "Volume slider scale type", ValueType: TypeChoice, Choices: []string{"linear", "logarithmic"}}, {Key: "speed_button", Default: "yes", Description: "Show the speed control button", ValueType: TypeBool}, {Key: "playlist_button", Default: "yes", Description: "Show the playlist button", ValueType: TypeBool}, {Key: "screenshot_button", Default: "yes", Description: "Show the screenshot button", ValueType: TypeBool}, {Key: "jump_buttons", Default: "yes", Description: "Show the jump backward/forward buttons", ValueType: TypeBool}, {Key: "tooltip_hints", Default: "yes", Description: "Show tooltips for buttons", ValueType: TypeBool}, } // spec configures the shared script-opts machinery with the ModernZ file // name and the core view of the curated catalog. var spec = &scriptopts.Spec{Name: confFileName, Options: specOptions()} // specOptions maps the curated catalog onto the shared core option shape; // the extra ModernZ metadata (Label, Recommended, ChoiceLabels) is // presentation-only and not needed by the core. func specOptions() []scriptopts.Option { options := make([]scriptopts.Option, len(knownOptions)) for i, opt := range knownOptions { options[i] = scriptopts.Option{ Key: opt.Key, Default: opt.Default, Description: opt.Description, ValueType: opt.ValueType, Choices: opt.Choices, Min: opt.Min, Max: opt.Max, } } return options } // KnownOptions returns the curated list of editable modernz.conf options. func KnownOptions() []Option { options := make([]Option, len(knownOptions)) for i, opt := range knownOptions { options[i] = opt options[i].Choices = append([]string(nil), opt.Choices...) if opt.ChoiceLabels != nil { options[i].ChoiceLabels = make(map[string]string, len(opt.ChoiceLabels)) for value, label := range opt.ChoiceLabels { options[i].ChoiceLabels[value] = label } } } return options } // ValidateValue checks value against the type and constraints of the known // option key. Unknown keys and values containing newlines are rejected. func ValidateValue(key, value string) error { return scriptopts.ValidateValue(spec, key, value) }