Skip to content

Commit 63a3466

Browse files
Detach disabled devices after surface.Load (v4.1.33)
The pre-Load skip-attach in LoadDeviceProvider was moot: surface.Load calls provider.Initialize() which populates provider.Devices, then attaches every device in that collection to the surface unconditionally. The manual loop above iterates against an empty provider.Devices for async providers (Hue / LIFX) and is overridden by Load even when it isn't. Add a post-Load pass that walks provider.Devices, checks MappingLayers.IsDeviceDisabled, and detaches the disabled ones from the surface. _activeDevices is updated to false in the same pass so the rest of the codebase (effect dispatch, brightness writes) sees a consistent disabled state. Symptom: a device disabled in the Mappings tab persisted the disable state across restarts (v4.1.30 fix worked there), but layers and effects continued to render to the hardware after the restart because surface.Load had silently re-attached the device. This commit closes that loop. Build clean, 130/130 tests pass. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent 8d8f982 commit 63a3466

5 files changed

Lines changed: 28 additions & 7 deletions

File tree

CHANGELOG.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,12 @@
22

33
All notable changes to Chromatics are documented here.
44

5-
## 4.1.32
5+
## 4.1.33
66

77
- Added Auto-discovery for Hue bridges.
88
- Updated Hue light adoption. After pairing, Chromatics shows a picker so you can choose exactly which Hue lights it should control. Existing setups upgraded from earlier builds keep all their bulbs (one-time auto-adopt of whatever the bridge currently exposes); from then on you can deselect bulbs you don't want from the same dialog.
99
- Hue bulbs now restore their original colour and on/off state when Chromatics releases control — disabling Hue, disabling an individual bulb on the Mappings tab, or closing the app puts each bulb back the way you had it before adoption. Same UX as LIFX.
10-
- Disabling a device on the Mappings tab now sticks across restarts. Disabled devices still show in the Mappings list — re-enable from the same toggle and Chromatics will (re)take control.
10+
- Disabling a device on the Mappings tab now sticks across restarts.
1111
- Fixed an error that could appear in the log when disabling Hue (or any device provider) — "The device 'X' is not attached to this surface."
1212

1313

Chromatics/Chromatics.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
<OutputType>WinExe</OutputType>
55
<TargetFramework>net10.0-windows7.0</TargetFramework>
66
<StartupObject>Chromatics.Program</StartupObject>
7-
<Version>4.1.32.0</Version>
7+
<Version>4.1.33.0</Version>
88
<Authors>Danielle Thompson</Authors>
99
<ApplicationManifest>app.manifest</ApplicationManifest>
1010
<Copyright>logicallysynced 2026</Copyright>

Chromatics/Core/RGBController.cs

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -744,6 +744,29 @@ public static bool LoadDeviceProvider(IRGBDeviceProvider provider)
744744
surface.Load(provider);
745745
loadedDeviceProviders.Add(provider);
746746

747+
// surface.Load attaches every device in provider.Devices
748+
// unconditionally (the comment in DevicesChanged about
749+
// "startup attachment is owned by SurfaceExtensions.Load"
750+
// is the source of truth here). Our pre-Load skip-attach
751+
// loop above is moot for async providers (Hue/LIFX),
752+
// whose Devices collection is empty until Initialize
753+
// runs INSIDE Load. To honour the persisted disable
754+
// state we have to detach the disabled devices here,
755+
// AFTER Load has populated provider.Devices and put
756+
// them on the surface.
757+
foreach (var device in provider.Devices)
758+
{
759+
var guidProbe = Helpers.DeviceHelper.GenerateDeviceGuid(device.DeviceInfo.DeviceName);
760+
if (!Layers.MappingLayers.IsDeviceDisabled(guidProbe))
761+
continue;
762+
if (surface.Devices.Contains(device))
763+
surface.Detach(device);
764+
if (_activeDevices.ContainsKey(device))
765+
_activeDevices[device] = false;
766+
else
767+
_activeDevices.Add(device, false);
768+
}
769+
747770
if (_loaded)
748771
{
749772
StopEffects();

Chromatics/obj/Chromatics.csproj.nuget.dgspec.json

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
},
66
"projects": {
77
"D:\\Git Projects\\roxaskeyheart\\Chromatics Workbench\\Chromatics\\Chromatics\\Chromatics.csproj": {
8-
"version": "4.1.32",
8+
"version": "4.1.33",
99
"restore": {
1010
"projectUniqueName": "D:\\Git Projects\\roxaskeyheart\\Chromatics Workbench\\Chromatics\\Chromatics\\Chromatics.csproj",
1111
"projectName": "Chromatics",
@@ -31,7 +31,6 @@
3131
},
3232
"frameworks": {
3333
"net10.0-windows7.0": {
34-
"framework": "net10.0-windows7.0",
3534
"targetAlias": "net10.0-windows7.0",
3635
"projectReferences": {}
3736
}
@@ -50,7 +49,6 @@
5049
},
5150
"frameworks": {
5251
"net10.0-windows7.0": {
53-
"framework": "net10.0-windows7.0",
5452
"targetAlias": "net10.0-windows7.0",
5553
"dependencies": {
5654
"Avalonia": {

Chromatics/obj/project.assets.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3697,7 +3697,7 @@
36973697
"C:\\Program Files (x86)\\Microsoft Visual Studio\\Shared\\NuGetPackages": {}
36983698
},
36993699
"project": {
3700-
"version": "4.1.32",
3700+
"version": "4.1.33",
37013701
"restore": {
37023702
"projectUniqueName": "D:\\Git Projects\\roxaskeyheart\\Chromatics Workbench\\Chromatics\\Chromatics\\Chromatics.csproj",
37033703
"projectName": "Chromatics",

0 commit comments

Comments
 (0)