@@ -419,6 +419,31 @@ void DeviceRackControllerTest::test_deviceMeterLevels_shouldReportPreInsertLevel
419419 QVERIFY (!device->meter ().active ());
420420}
421421
422+ void DeviceRackControllerTest::test_deviceMeterLevels_afterSlotChanged_shouldFollowTheActiveGate ()
423+ {
424+ // The gate is set when the rack goes on screen, but a device dropped into a slot afterwards is
425+ // born with its taps off, so replacing one used to leave a permanently dead meter.
426+ const auto audioEngine = std::make_shared<AudioEngine>();
427+ const auto deviceService = std::make_shared<DeviceService>(audioEngine, std::make_shared<DataService>());
428+ DeviceRackController controller { deviceService, {}, std::make_shared<MockEditorService>() };
429+
430+ controller.setMetersActive (true );
431+ controller.setDevice (0 , QString::fromStdString (Kick808Device::typeIdString ()));
432+ QVERIFY (deviceService->device (0 )->meter ().active ());
433+ QVERIFY (deviceService->device (0 )->loadMeter ().active ());
434+
435+ controller.clearDevice (0 );
436+ controller.setDevice (0 , QString::fromStdString (SynthDevice::typeIdString ()));
437+ QVERIFY (deviceService->device (0 )->meter ().active ());
438+ QVERIFY (deviceService->device (0 )->loadMeter ().active ());
439+
440+ // Off the screen, a device added into the rack must not silently switch the taps back on.
441+ controller.setMetersActive (false );
442+ controller.setDevice (1 , QString::fromStdString (SynthDevice::typeIdString ()));
443+ QVERIFY (!deviceService->device (1 )->meter ().active ());
444+ QVERIFY (!deviceService->device (1 )->loadMeter ().active ());
445+ }
446+
422447namespace {
423448// ! Emits a constant level so a test can put the engine's device path either side of full scale.
424449class ClippingDevice : public MockDevice
0 commit comments