Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
7380ae5
feat(Controller): add support for settings
acolombier Feb 23, 2023
2c6f071
feat(Controller): basic concept of setting injection in JS engine
acolombier Feb 24, 2023
69a57d4
feat(Controller): settings persistence and HID support
acolombier Feb 25, 2023
0f01d3e
feat(Controller): UI improvement with custom layout support
acolombier Feb 26, 2023
298291a
feat(Controller): row layout support for vertical orientation
acolombier Feb 26, 2023
d8a925f
feat(Controller): adding tests for controller settings
acolombier Feb 28, 2023
e5b4ed8
PR Feedback
acolombier Sep 24, 2023
a4ce574
fix(controller): use smart pointer for mapping loader
acolombier Oct 23, 2023
e7f8e18
chore: various nit around var name and method modifiers
acolombier Oct 31, 2023
96ffded
chore: replace tuple with private struct
acolombier Nov 4, 2023
ac08328
chore: replace macros with explicit call in ctor
acolombier Nov 5, 2023
da49d94
fix: make controller path dynamic with system paths
acolombier Dec 19, 2023
c6484c9
Changed setting of variable to a getter function, consistent to the r…
JoergAtGithub Feb 18, 2024
0b52dad
Replace any with effective type union
acolombier Mar 3, 2024
64ca180
Shorten the ControllerSetting to Setting in the EngineAPI
acolombier Mar 3, 2024
a57332a
Support restore default action and various code style changes
acolombier Mar 23, 2024
48a936e
Fix memleak in setting preference
acolombier Mar 27, 2024
d72e012
Merge remote-tracking branch 'upstream/main' into feat/controller-cus…
acolombier Mar 28, 2024
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
5 changes: 5 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -731,10 +731,14 @@ add_library(mixxx-lib STATIC EXCLUDE_FROM_ALL
src/controllers/controllerlearningeventfilter.cpp
src/controllers/controllermanager.cpp
src/controllers/controllermappinginfo.cpp
src/controllers/legacycontrollersettings.cpp
src/controllers/legacycontrollersettingslayout.cpp
src/controllers/controllermappinginfoenumerator.cpp
src/controllers/controllermappingtablemodel.cpp
src/controllers/controlleroutputmappingtablemodel.cpp
src/controllers/controlpickermenu.cpp
src/controllers/legacycontrollermappingfilehandler.cpp
src/controllers/legacycontrollermapping.cpp
src/controllers/delegates/controldelegate.cpp
src/controllers/delegates/midibytedelegate.cpp
src/controllers/delegates/midichanneldelegate.cpp
Expand Down Expand Up @@ -2070,6 +2074,7 @@ add_executable(mixxx-test
src/test/colorpalette_test.cpp
src/test/configobject_test.cpp
src/test/controller_mapping_validation_test.cpp
src/test/controller_mapping_settings_test.cpp
src/test/controllerscriptenginelegacy_test.cpp
src/test/controlobjecttest.cpp
src/test/controlobjectaliastest.cpp
Expand Down
10 changes: 10 additions & 0 deletions res/controllers/engine-api.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,16 @@ declare interface ScriptConnection {
/** ControllerScriptInterfaceLegacy */

declare namespace engine {
type SettingValue = string | number | boolean;
/**
* Gets the value of a controller setting
* The value is either set in the preferences dialog,
* or got restored from file.
* @param name Name of the setting (as specified in the XML file of the mapping)
* @returns Value of the setting, or undefined in failure case
*/
function getSetting(name: string): SettingValue | undefined;

/**
* Gets the control value
*
Expand Down
2 changes: 2 additions & 0 deletions src/controllers/controller.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,8 @@ bool Controller::applyMapping() {
}

m_pScriptEngineLegacy->setScriptFiles(scriptFiles);

m_pScriptEngineLegacy->setSettings(pMapping->getSettings());
return m_pScriptEngineLegacy->initialize();
}

Expand Down
1 change: 1 addition & 0 deletions src/controllers/controllermanager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -282,6 +282,7 @@ void ControllerManager::slotSetUpDevices() {
if (!pMapping) {
continue;
}
pMapping->loadSettings(m_pConfig, pController->getName());

// This runs on the main thread but LegacyControllerMapping is not thread safe, so clone it.
pController->setMapping(pMapping->clone());
Expand Down
79 changes: 63 additions & 16 deletions src/controllers/dlgprefcontroller.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
#include "moc_dlgprefcontroller.cpp"
#include "preferences/usersettings.h"
#include "util/desktophelper.h"
#include "util/parented_ptr.h"
#include "util/string.h"

namespace {
Expand Down Expand Up @@ -410,6 +411,7 @@ QString DlgPrefController::mappingFileLinks(

void DlgPrefController::enumerateMappings(const QString& selectedMappingPath) {
m_ui.comboBoxMapping->blockSignals(true);
QString currentMappingFilePath = mappingFilePathFromIndex(m_ui.comboBoxMapping->currentIndex());
m_ui.comboBoxMapping->clear();

// qDebug() << "Enumerating mappings for controller" << m_pController->getName();
Expand Down Expand Up @@ -461,14 +463,18 @@ void DlgPrefController::enumerateMappings(const QString& selectedMappingPath) {
} else if (match.isValid()) {
index = m_ui.comboBoxMapping->findText(match.getName());
}
QString newMappingFilePath = mappingFilePathFromIndex(index);
if (index == -1) {
m_ui.chkEnabledDevice->setEnabled(false);
m_ui.groupBoxSettings->setVisible(false);
} else {
m_ui.comboBoxMapping->setCurrentIndex(index);
m_ui.chkEnabledDevice->setEnabled(true);
}
m_ui.comboBoxMapping->blockSignals(false);
slotMappingSelected(m_ui.comboBoxMapping->currentIndex());
if (newMappingFilePath != currentMappingFilePath) {
slotMappingSelected(index);
}
}

MappingInfo DlgPrefController::enumerateMappingsFromEnumerator(
Expand Down Expand Up @@ -498,6 +504,8 @@ MappingInfo DlgPrefController::enumerateMappingsFromEnumerator(
void DlgPrefController::slotUpdate() {
enumerateMappings(m_pControllerManager->getConfiguredMappingFileForDevice(
m_pController->getName()));
// Force updating the controller settings
slotMappingSelected(m_ui.comboBoxMapping->currentIndex());

// enumeratePresets calls slotPresetSelected which will check the m_ui.chkEnabledDevice
// checkbox if there is a valid mapping saved in the mixxx.cfg file. However, the
Expand All @@ -514,9 +522,10 @@ void DlgPrefController::slotUpdate() {
}

void DlgPrefController::slotResetToDefaults() {
m_ui.chkEnabledDevice->setChecked(false);
if (m_pMapping) {
m_pMapping->resetSettings();
}
enumerateMappings(QString());
slotMappingSelected(m_ui.comboBoxMapping->currentIndex());
}

void DlgPrefController::applyMappingChanges() {
Expand Down Expand Up @@ -557,9 +566,13 @@ void DlgPrefController::slotApply() {
return;
}

QString mappingPath = mappingPathFromIndex(m_ui.comboBoxMapping->currentIndex());
m_pMapping = LegacyControllerMappingFileHandler::loadMapping(
QFileInfo(mappingPath), QDir(resourceMappingsPath(m_pConfig)));
// If there is currently a mapping loaded, we save the new settings for it.
// Note that `m_pMapping`, `mappingFileInfo` and the setting on the screen
// will always match as the settings displayed are updated depending of the
// currently selected mapping in `slotMappingSelected`
if (m_pMapping) {
m_pMapping->saveSettings(m_pConfig, m_pController->getName());
}

// Load the resulting mapping (which has been mutated by the input/output
// table models). The controller clones the mapping so we aren't touching
Expand Down Expand Up @@ -593,7 +606,7 @@ void DlgPrefController::enableWizardAndIOTabs(bool enable) {
m_ui.outputMappingsTab->setEnabled(enable);
}

QString DlgPrefController::mappingPathFromIndex(int index) const {
QString DlgPrefController::mappingFilePathFromIndex(int index) const {
if (index == 0) {
// "No Mapping" item
return QString();
Expand All @@ -603,8 +616,8 @@ QString DlgPrefController::mappingPathFromIndex(int index) const {
}

void DlgPrefController::slotMappingSelected(int chosenIndex) {
QString mappingPath = mappingPathFromIndex(chosenIndex);
if (mappingPath.isEmpty()) { // User picked "No Mapping" item
QString mappingFilePath = mappingFilePathFromIndex(chosenIndex);
if (mappingFilePath.isEmpty()) { // User picked "No Mapping" item
m_ui.chkEnabledDevice->setEnabled(false);

if (m_ui.chkEnabledDevice->isChecked()) {
Expand All @@ -614,6 +627,8 @@ void DlgPrefController::slotMappingSelected(int chosenIndex) {
}
enableWizardAndIOTabs(false);
}

m_ui.groupBoxSettings->setVisible(false);
} else { // User picked a mapping
m_ui.chkEnabledDevice->setEnabled(true);

Expand All @@ -628,7 +643,7 @@ void DlgPrefController::slotMappingSelected(int chosenIndex) {
// Check if the mapping is different from the configured mapping
if (m_GuiInitialized &&
m_pControllerManager->getConfiguredMappingFileForDevice(
m_pController->getName()) != mappingPath) {
m_pController->getName()) != mappingFilePath) {
setDirty(true);
}

Expand All @@ -643,9 +658,10 @@ void DlgPrefController::slotMappingSelected(int chosenIndex) {
}
}

auto mappingFileInfo = QFileInfo(mappingFilePath);
std::shared_ptr<LegacyControllerMapping> pMapping =
LegacyControllerMappingFileHandler::loadMapping(
QFileInfo(mappingPath), QDir(resourceMappingsPath(m_pConfig)));
mappingFileInfo, QDir(resourceMappingsPath(m_pConfig)));

if (pMapping) {
DEBUG_ASSERT(!pMapping->isDirty());
Expand All @@ -654,7 +670,7 @@ void DlgPrefController::slotMappingSelected(int chosenIndex) {
if (previousMappingSaved) {
// We might have saved the previous preset with a new name, so update
// the preset combobox.
enumerateMappings(mappingPath);
enumerateMappings(mappingFilePath);
} else {
slotShowMapping(pMapping);
}
Expand Down Expand Up @@ -823,10 +839,41 @@ void DlgPrefController::slotShowMapping(std::shared_ptr<LegacyControllerMapping>
m_ui.labelLoadedMappingSupportLinks->setText(mappingSupportLinks(pMapping));
m_ui.labelLoadedMappingScriptFileLinks->setText(mappingFileLinks(pMapping));

// We mutate this mapping so keep a reference to it while we are using it.
// TODO(rryan): Clone it? Technically a waste since nothing else uses this
// copy but if someone did they might not expect it to change.
m_pMapping = pMapping;
if (pMapping) {
pMapping->loadSettings(m_pConfig, m_pController->getName());
auto settings = pMapping->getSettings();
auto* pLayout = pMapping->getSettingsLayout();

QLayoutItem* pItem;
while ((pItem = m_ui.groupBoxSettings->layout()->takeAt(0)) != nullptr) {
delete pItem->widget();
delete pItem;
}

if (pLayout != nullptr && !settings.isEmpty()) {
m_ui.groupBoxSettings->layout()->addWidget(pLayout->build(m_ui.groupBoxSettings));

for (const auto& setting : qAsConst(settings)) {
connect(setting.get(),
&AbstractLegacyControllerSetting::changed,
this,
[this] { setDirty(true); });
}
}

m_ui.groupBoxSettings->setVisible(!settings.isEmpty());
}

// If there is still settings that may be saved and no new mapping selected
// (e.g restored default), we keep the the dirty mapping live so it can be
// saved in apply slot. If there is a new mapping, then setting changes are
// discarded
if (pMapping || (m_pMapping && !m_pMapping->hasDirtySettings())) {
// We mutate this mapping so keep a reference to it while we are using it.
// TODO(rryan): Clone it? Technically a waste since nothing else uses this
// copy but if someone did they might not expect it to change.
m_pMapping = pMapping;
}

// Inputs tab
ControllerInputMappingTableModel* pInputModel =
Expand Down
2 changes: 1 addition & 1 deletion src/controllers/dlgprefcontroller.h
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ class DlgPrefController : public DlgPreferencePage {
QString mappingDescription(const std::shared_ptr<LegacyControllerMapping> pMapping) const;
QString mappingSupportLinks(const std::shared_ptr<LegacyControllerMapping> pMapping) const;
QString mappingFileLinks(const std::shared_ptr<LegacyControllerMapping> pMapping) const;
QString mappingPathFromIndex(int index) const;
QString mappingFilePathFromIndex(int index) const;
QString askForMappingName(const QString& prefilledName = QString()) const;
void applyMappingChanges();
bool saveMapping();
Expand Down
Loading