Skip to content

Commit 0ce25cf

Browse files
committed
Fix dead level meters on device slot changes
- Remember the meter gate in DeviceRackController instead of only pushing it onto the devices that existed when the dialog became visible
1 parent 1513c3d commit 0ce25cf

5 files changed

Lines changed: 48 additions & 3 deletions

File tree

CHANGELOG

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,9 @@ New features:
4343

4444
Bug fixes:
4545

46+
* Fix the level meters staying dead for a device added or replaced while the
47+
Device Rack or Mixer is open
48+
4649
* Fix the Piano
4750
- Let the top octaves speak and ring
4851
- Play in tune across the keyboard

src/unit_tests/device_rack_controller_test/device_rack_controller_test.cpp

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -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+
422447
namespace {
423448
//! Emits a constant level so a test can put the engine's device path either side of full scale.
424449
class ClippingDevice : public MockDevice

src/unit_tests/device_rack_controller_test/device_rack_controller_test.hpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ private slots:
3737
void test_addMethods_shouldAddDevicesToFirstEmptySlot();
3838
void test_availableDevices_shouldReturnCorrectList();
3939
void test_deviceMeterLevels_shouldReportPreInsertLevel();
40+
void test_deviceMeterLevels_afterSlotChanged_shouldFollowTheActiveGate();
4041
void test_deviceClipped_shouldLatchUntilCleared();
4142
void test_deviceClipped_afterClearing_shouldStayClearWhileBelowFullScale();
4243
void test_deviceSettings_shouldRoundTripThroughController();

src/view/controllers/device_rack_controller.cpp

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,8 @@ void DeviceRackController::refresh()
125125
m_devices = m_deviceService->internalDeviceNamesQt();
126126
}
127127
endResetModel();
128+
// Slots may have gained a device since the gate was last set, and a new device's taps start off.
129+
applyMetersActive();
128130
}
129131

130132
void DeviceRackController::openDevice(const QString & name)
@@ -232,14 +234,23 @@ QVariantList DeviceRackController::deviceMeterLevels(int slotIndex) const
232234

233235
void DeviceRackController::setMetersActive(bool active)
234236
{
237+
m_metersActive = active;
238+
applyMetersActive();
239+
}
240+
241+
void DeviceRackController::applyMetersActive()
242+
{
243+
if (!m_deviceService) {
244+
return;
245+
}
235246
for (int slotIndex = 0; slotIndex < deviceCount(); slotIndex++) {
236247
if (const auto device = m_deviceService->device(static_cast<size_t>(slotIndex))) {
237-
device->meter().setActive(active);
238-
device->loadMeter().setActive(active);
248+
device->meter().setActive(m_metersActive);
249+
device->loadMeter().setActive(m_metersActive);
239250
}
240251
}
241252
if (const auto engine = m_deviceService->audioEngine()) {
242-
engine->loadMeter().setActive(active);
253+
engine->loadMeter().setActive(m_metersActive);
243254
}
244255
}
245256

src/view/controllers/device_rack_controller.hpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -163,12 +163,17 @@ class DeviceRackController : public QAbstractListModel
163163
private:
164164
QString trackNames(const QString & deviceName) const;
165165

166+
//! Push the current gate onto every device's taps. Needed after any slot change, because a
167+
//! freshly created device starts with its meters off regardless of what is on screen.
168+
void applyMetersActive();
169+
166170
DeviceServiceS m_deviceService;
167171
ControllerList m_controllers;
168172
EditorServiceS m_editorService;
169173

170174
QStringList m_devices;
171175
int m_revision { 0 };
176+
bool m_metersActive { false };
172177
};
173178

174179
} // namespace noteahead

0 commit comments

Comments
 (0)