package main import ( "fmt" "time" "github.com/charmbracelet/log" ) // HeadampCmdGroup defines the command group for controlling input gain and phantom power of a headamp, allowing users to specify the index of the headamp they want to control. type HeadampCmdGroup struct { Index struct { Index int `arg:"" help:"The index of the headamp."` Gain HeadampGainCmd `help:"Get or set the gain of the headamp." cmd:""` Phantom HeadampPhantomCmd `help:"Get or set the phantom power state of the headamp." cmd:""` } `arg:"" help:"Control a specific headamp by index."` } // HeadampGainCmd defines the command for getting or setting the gain of a headamp, allowing users to specify the gain in dB and an optional duration for a gradual fade when setting the gain. type HeadampGainCmd struct { Duration time.Duration `help:"The duration of the fade in/out when setting the gain." default:"5s"` Gain *float64 `help:"The gain of the headamp in dB." arg:"" optional:""` } // Run executes the HeadampGainCmd command, either retrieving the current gain of the headamp or setting it based on the provided argument, with an optional fade duration for smooth transitions. func (cmd *HeadampGainCmd) Run(ctx *context, headamp *HeadampCmdGroup) error { if cmd.Gain == nil { resp, err := ctx.Client.HeadAmp.Gain(headamp.Index.Index) if err != nil { return fmt.Errorf("failed to get headamp gain: %w", err) } fmt.Fprintf(ctx.Out, "Headamp %d gain: %.2f dB\n", headamp.Index.Index, resp) return nil } currentGain, err := ctx.Client.HeadAmp.Gain(headamp.Index.Index) if err != nil { return fmt.Errorf("failed to get current headamp gain: %w", err) } if err := gradualGainAdjust( ctx, headamp.Index.Index, currentGain, *cmd.Gain, cmd.Duration, ); err != nil { return fmt.Errorf("failed to set headamp gain: %w", err) } fmt.Fprintf(ctx.Out, "Headamp %d gain set to: %.2f dB\n", headamp.Index.Index, *cmd.Gain) return nil } // gradualGainAdjust gradually adjusts gain from current to target over specified duration. func gradualGainAdjust( ctx *context, index int, currentGain, targetGain float64, duration time.Duration, ) error { gainDiff := targetGain - currentGain stepInterval := 100 * time.Millisecond totalSteps := int(duration / stepInterval) if totalSteps < 1 { totalSteps = 1 stepInterval = duration } stepIncrement := gainDiff / float64(totalSteps) log.Debugf("Adjusting Headamp %d gain from %.2f dB to %.2f dB over %v...\n", index, currentGain, targetGain, duration) for step := 1; step <= totalSteps; step++ { newGain := currentGain + (stepIncrement * float64(step)) if step == totalSteps { newGain = targetGain } err := ctx.Client.HeadAmp.SetGain(index, newGain) if err != nil { return err } if step%10 == 0 || step == totalSteps { log.Debugf(" Step %d/%d: %.2f dB\n", step, totalSteps, newGain) } if step < totalSteps { time.Sleep(stepInterval) } } return nil } // HeadampPhantomCmd defines the command for getting or setting the phantom power state of a headamp, allowing users to specify the desired state as "true"/"on" or "false"/"off". type HeadampPhantomCmd struct { State *string `help:"The phantom power state of the headamp." arg:"" enum:"true,on,false,off" optional:""` } // Validate checks if the provided phantom power state is valid and normalises it to "true" or "false". func (cmd *HeadampPhantomCmd) Validate() error { if cmd.State != nil { switch *cmd.State { case "true", "on": *cmd.State = "true" case "false", "off": *cmd.State = "false" default: return fmt.Errorf("invalid phantom power state: %s", *cmd.State) } } return nil } // Run executes the HeadampPhantomCmd command, either retrieving the current phantom power state of the headamp or setting it based on the provided argument. func (cmd *HeadampPhantomCmd) Run(ctx *context, headamp *HeadampCmdGroup) error { if cmd.State == nil { resp, err := ctx.Client.HeadAmp.PhantomPower(headamp.Index.Index) if err != nil { return fmt.Errorf("failed to get headamp phantom power state: %w", err) } fmt.Fprintf(ctx.Out, "Headamp %d phantom power: %t\n", headamp.Index.Index, resp) return nil } if err := ctx.Client.HeadAmp.SetPhantomPower( headamp.Index.Index, *cmd.State == "true", ); err != nil { return fmt.Errorf("failed to set headamp phantom power state: %w", err) } fmt.Fprintf(ctx.Out, "Headamp %d phantom power set to: %s\n", headamp.Index.Index, *cmd.State) return nil }