Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add customizable max transition duration for settings changes #291

Merged
merged 7 commits into from
May 6, 2024
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions LightBulb/Services/SettingsService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,9 @@ public partial class SettingsService() : SettingsBase(GetFilePath())
[ObservableProperty]
private double _configurationTransitionOffset;

[ObservableProperty]
private TimeSpan _maxSettingsTransitionDuration = TimeSpan.FromSeconds(15);
LilithSilver marked this conversation as resolved.
Show resolved Hide resolved

// Location

[ObservableProperty]
Expand Down
62 changes: 58 additions & 4 deletions LightBulb/ViewModels/Components/DashboardViewModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,10 @@ ExternalApplicationService externalApplicationService
)
);

_updateConfigurationTimer = new Timer(TimeSpan.FromMilliseconds(50), UpdateConfiguration);
_updateConfigurationTimer = new Timer(
TimeSpan.FromMilliseconds(50),
() => UpdateConfiguration(1000 / (double)50)
);
_updateInstantTimer = new Timer(TimeSpan.FromMilliseconds(50), UpdateInstant);
_updateIsPausedTimer = new Timer(TimeSpan.FromSeconds(1), UpdateIsPaused);
}
Expand Down Expand Up @@ -285,12 +288,63 @@ private void UpdateInstant()
}
}

private void UpdateConfiguration()
private const double _brightnessDefaultStep = 0.08;
private const double _temperatureDefaultStep = 30;

private double _brightnessMaxStep = _brightnessDefaultStep;
private double _temperatureMaxStep = _temperatureDefaultStep;

private ColorConfiguration _lastTarget;

private void UpdateConfiguration(double stepsPerSecond)
LilithSilver marked this conversation as resolved.
Show resolved Hide resolved
{
var isSmooth = _settingsService.IsConfigurationSmoothingEnabled && !IsCyclePreviewEnabled;
if (CurrentConfiguration == TargetConfiguration)
return;

var isSmooth =
_settingsService.IsConfigurationSmoothingEnabled
&& !IsCyclePreviewEnabled
&& _settingsService.MaxSettingsTransitionDuration.TotalSeconds >= 0.1;
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this check required if we already have IsConfigurationSmoothingEnabled?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes -- this fixes an edge case where, if the calculated transition duration is very small, it can lead to 0s or NaNs being produced by the calculation and fed into the smoothing function (which causes my monitors to go black, so it's near impossible to debug).


// If we've changed targets, restart with default settings.
if (_lastTarget != TargetConfiguration && isSmooth)
{
_brightnessMaxStep = _brightnessDefaultStep;
_temperatureMaxStep = _temperatureDefaultStep;
_lastTarget = TargetConfiguration;

var tempDelta = Math.Abs(
TargetConfiguration.Temperature - CurrentConfiguration.Temperature
);
var brightnessDelta = Math.Abs(
TargetConfiguration.Brightness - CurrentConfiguration.Brightness
);
var expectedTemperatureDuration = tempDelta / (_temperatureMaxStep * stepsPerSecond);
var expectedBrightnessDuration =
brightnessDelta / (_brightnessMaxStep * stepsPerSecond);

// If the expected durations are longer than our duration limit, we adjust the step amount to stay at the max duration.
var goalDuration = Math.Max(expectedTemperatureDuration, expectedBrightnessDuration);
goalDuration = Math.Min(
goalDuration,
_settingsService.MaxSettingsTransitionDuration.TotalSeconds
);

// Calculate the step-rate needed to reach the goal.
_brightnessMaxStep = brightnessDelta / (goalDuration * stepsPerSecond);
_temperatureMaxStep = tempDelta / (goalDuration * stepsPerSecond);

// If we ended up slower on either of the durations, speed us up.
_brightnessMaxStep = Math.Max(_brightnessMaxStep, _brightnessDefaultStep);
_temperatureMaxStep = Math.Max(_temperatureMaxStep, _temperatureDefaultStep);
}

CurrentConfiguration = isSmooth
? CurrentConfiguration.StepTo(TargetConfiguration, 30, 0.008)
? CurrentConfiguration.StepTo(
TargetConfiguration,
_temperatureMaxStep,
_brightnessMaxStep
)
: TargetConfiguration;
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What about instead of configuring smoothing duration, you could configure the steps instead? You'd then be able to set arbitrary values instead of 30 and 0.008, which would let you speed up the transitions, but the code would end up a lot simpler (basically same as before).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I tried that, but it ended up leading to strobing in the case of small transitions at high speed. If a small configuration change was made, such as sliding a slider, it led to instant changes similar to gamma smoothing being disabled entirely. But if that's preferable behavior, I can change it to that.


_gammaService.SetGamma(CurrentConfiguration);
Expand Down