1 #include "preferences/dialog/dlgprefdeck.h"
2
3 #include <QDir>
4 #include <QDoubleSpinBox>
5 #include <QList>
6 #include <QLocale>
7 #include <QToolTip>
8 #include <QWidget>
9
10 #include "control/controlobject.h"
11 #include "control/controlproxy.h"
12 #include "defs_urls.h"
13 #include "engine/controls/ratecontrol.h"
14 #include "engine/enginebuffer.h"
15 #include "mixer/basetrackplayer.h"
16 #include "mixer/playerinfo.h"
17 #include "mixer/playermanager.h"
18 #include "mixxx.h"
19 #include "moc_dlgprefdeck.cpp"
20 #include "preferences/usersettings.h"
21 #include "util/compatibility.h"
22 #include "util/duration.h"
23 #include "widget/wnumberpos.h"
24
25 namespace {
26 constexpr int kDefaultRateRangePercent = 8;
27 constexpr double kRateDirectionInverted = -1;
28 constexpr RateControl::RampMode kDefaultRampingMode = RateControl::RampMode::Stepping;
29 constexpr double kDefaultTemporaryRateChangeCoarse = 4.00; // percent
30 constexpr double kDefaultTemporaryRateChangeFine = 2.00;
31 constexpr double kDefaultPermanentRateChangeCoarse = 0.50;
32 constexpr double kDefaultPermanentRateChangeFine = 0.05;
33 constexpr int kDefaultRateRampSensitivity = 250;
34 // bool kDefaultCloneDeckOnLoad is defined in header file to make it available
35 // to playermanager.cpp
36 } // namespace
37
DlgPrefDeck(QWidget * parent,UserSettingsPointer pConfig)38 DlgPrefDeck::DlgPrefDeck(QWidget* parent,
39 UserSettingsPointer pConfig)
40 : DlgPreferencePage(parent),
41 m_pConfig(pConfig),
42 m_pControlTrackTimeDisplay(std::make_unique<ControlObject>(
43 ConfigKey("[Controls]", "ShowDurationRemaining"))),
44 m_pControlTrackTimeFormat(std::make_unique<ControlObject>(
45 ConfigKey("[Controls]", "TimeFormat"))),
46 m_pNumDecks(
47 make_parented<ControlProxy>("[Master]", "num_decks", this)),
48 m_pNumSamplers(make_parented<ControlProxy>(
49 "[Master]", "num_samplers", this)),
50 m_iNumConfiguredDecks(0),
51 m_iNumConfiguredSamplers(0) {
52 setupUi(this);
53 // Create text color for the cue mode link "?" to the manual
54 createLinkColor();
55
56 m_pNumDecks->connectValueChanged(this, [=](double value){slotNumDecksChanged(value);});
57 slotNumDecksChanged(m_pNumDecks->get(), true);
58
59 m_pNumSamplers->connectValueChanged(this, [=](double value){slotNumSamplersChanged(value);});
60 slotNumSamplersChanged(m_pNumSamplers->get(), true);
61
62 // Set default value in config file and control objects, if not present
63 // Default is "0" = Mixxx Mode
64 int cueDefaultValue = m_pConfig->getValue(
65 ConfigKey("[Controls]", "CueDefault"), 0);
66
67 // Update combo box
68 ComboBoxCueMode->addItem(tr("Mixxx mode"), static_cast<int>(CueMode::Mixxx));
69 ComboBoxCueMode->addItem(tr("Mixxx mode (no blinking)"), static_cast<int>(CueMode::MixxxNoBlinking));
70 ComboBoxCueMode->addItem(tr("Pioneer mode"), static_cast<int>(CueMode::Pioneer));
71 ComboBoxCueMode->addItem(tr("Denon mode"), static_cast<int>(CueMode::Denon));
72 ComboBoxCueMode->addItem(tr("Numark mode"), static_cast<int>(CueMode::Numark));
73 ComboBoxCueMode->addItem(tr("CUP mode"), static_cast<int>(CueMode::CueAndPlay));
74 const int cueModeIndex = cueDefaultIndexByData(cueDefaultValue);
75 ComboBoxCueMode->setCurrentIndex(cueModeIndex);
76 slotCueModeCombobox(cueModeIndex);
77 for (ControlProxy* pControl : qAsConst(m_cueControls)) {
78 pControl->set(static_cast<int>(m_cueMode));
79 }
80 connect(ComboBoxCueMode,
81 QOverload<int>::of(&QComboBox::currentIndexChanged),
82 this,
83 &DlgPrefDeck::slotCueModeCombobox);
84
85 // Track time display configuration
86 connect(m_pControlTrackTimeDisplay.get(),
87 &ControlObject::valueChanged,
88 this,
89 QOverload<double>::of(&DlgPrefDeck::slotSetTrackTimeDisplay));
90
91 double positionDisplayType = m_pConfig->getValue(
92 ConfigKey("[Controls]", "PositionDisplay"),
93 static_cast<double>(TrackTime::DisplayMode::ELAPSED_AND_REMAINING));
94 if (positionDisplayType ==
95 static_cast<double>(TrackTime::DisplayMode::REMAINING)) {
96 radioButtonRemaining->setChecked(true);
97 m_pControlTrackTimeDisplay->set(
98 static_cast<double>(TrackTime::DisplayMode::REMAINING));
99 } else if (positionDisplayType ==
100 static_cast<double>(TrackTime::DisplayMode::ELAPSED_AND_REMAINING)) {
101 radioButtonElapsedAndRemaining->setChecked(true);
102 m_pControlTrackTimeDisplay->set(
103 static_cast<double>(TrackTime::DisplayMode::ELAPSED_AND_REMAINING));
104 } else {
105 radioButtonElapsed->setChecked(true);
106 m_pControlTrackTimeDisplay->set(
107 static_cast<double>(TrackTime::DisplayMode::ELAPSED));
108 }
109 connect(buttonGroupTrackTime,
110 QOverload<QAbstractButton*>::of(&QButtonGroup::buttonClicked),
111 this,
112 QOverload<QAbstractButton*>::of(
113 &DlgPrefDeck::slotSetTrackTimeDisplay));
114
115 // display time format
116 connect(m_pControlTrackTimeFormat.get(),
117 &ControlObject::valueChanged,
118 this,
119 &DlgPrefDeck::slotTimeFormatChanged);
120
121 // Track Display model
122 comboBoxTimeFormat->clear();
123
124 comboBoxTimeFormat->addItem(tr("mm:ss%1zz - Traditional")
125 .arg(mixxx::DurationBase::kDecimalSeparator),
126 static_cast<int>
127 (TrackTime::DisplayFormat::TRADITIONAL));
128
129 comboBoxTimeFormat->addItem(tr("mm:ss - Traditional (Coarse)"),
130 static_cast<int>
131 (TrackTime::DisplayFormat::TRADITIONAL_COARSE));
132
133 comboBoxTimeFormat->addItem(tr("s%1zz - Seconds")
134 .arg(mixxx::DurationBase::kDecimalSeparator),
135 static_cast<int>
136 (TrackTime::DisplayFormat::SECONDS));
137
138 comboBoxTimeFormat->addItem(tr("sss%1zz - Seconds (Long)")
139 .arg(mixxx::DurationBase::kDecimalSeparator),
140 static_cast<int>
141 (TrackTime::DisplayFormat::SECONDS_LONG));
142
143 comboBoxTimeFormat->addItem(tr("s%1sss%2zz - Kiloseconds")
144 .arg(QString(mixxx::DurationBase::kDecimalSeparator),
145 QString(mixxx::DurationBase::kKiloGroupSeparator)),
146 static_cast<int>
147 (TrackTime::DisplayFormat::KILO_SECONDS));
148
149 double time_format = static_cast<double>(
150 m_pConfig->getValue(
151 ConfigKey("[Controls]", "TimeFormat"),
152 static_cast<int>(TrackTime::DisplayFormat::TRADITIONAL)));
153 m_pControlTrackTimeFormat->set(time_format);
154 comboBoxTimeFormat->setCurrentIndex(
155 comboBoxTimeFormat->findData(time_format));
156
157 // Override Playing Track on Track Load
158 // The check box reflects the opposite of the config value
159 m_bDisallowTrackLoadToPlayingDeck = !m_pConfig->getValue(
160 ConfigKey("[Controls]", "AllowTrackLoadToPlayingDeck"), false);
161 checkBoxDisallowLoadToPlayingDeck->setChecked(m_bDisallowTrackLoadToPlayingDeck);
162 connect(checkBoxDisallowLoadToPlayingDeck,
163 &QCheckBox::toggled,
164 this,
165 &DlgPrefDeck::slotDisallowTrackLoadToPlayingDeckCheckbox);
166
167 comboBoxLoadPoint->addItem(tr("Intro start"), static_cast<int>(SeekOnLoadMode::IntroStart));
168 comboBoxLoadPoint->addItem(tr("Main cue"), static_cast<int>(SeekOnLoadMode::MainCue));
169 comboBoxLoadPoint->addItem(tr("First sound (skip silence)"), static_cast<int>(SeekOnLoadMode::FirstSound));
170 comboBoxLoadPoint->addItem(tr("Beginning of track"), static_cast<int>(SeekOnLoadMode::Beginning));
171 bool seekModeExisted = m_pConfig->exists(ConfigKey("[Controls]", "CueRecall"));
172 int seekMode = m_pConfig->getValue(ConfigKey("[Controls]", "CueRecall"),
173 static_cast<int>(SeekOnLoadMode::IntroStart));
174 comboBoxLoadPoint->setCurrentIndex(
175 comboBoxLoadPoint->findData(seekMode));
176 m_seekOnLoadMode = static_cast<SeekOnLoadMode>(seekMode);
177 connect(comboBoxLoadPoint,
178 QOverload<int>::of(&QComboBox::currentIndexChanged),
179 this,
180 &DlgPrefDeck::slotSetTrackLoadMode);
181
182 // This option was introduced in Mixxx 2.3 with the intro & outro cues.
183 // If the user has set main cue points with the intention of starting tracks
184 // from those points, enable this option. With Denon and Numark CueModes,
185 // it is not safe to assume that the user wants to start tracks from the
186 // main cue point because it is very easy to move the main cue point without
187 // explicitly intending to in those modes (the main cue point moves whenever
188 // the deck is not at the main cue point and play is pressed).
189 bool introStartMoveDefault = (m_seekOnLoadMode == SeekOnLoadMode::MainCue ||
190 !seekModeExisted) &&
191 !(m_cueMode == CueMode::Denon ||
192 m_cueMode == CueMode::Numark);
193 m_bSetIntroStartAtMainCue = m_pConfig->getValue(ConfigKey("[Controls]", "SetIntroStartAtMainCue"),
194 introStartMoveDefault);
195 // This is an ugly hack to ensure AnalyzerSilence gets the correct default
196 // value because ConfigValue::getValue does not set the value of the ConfigValue
197 // in case no value had been set previously (when mixxx.cfg is empty).
198 m_pConfig->setValue(ConfigKey("[Controls]", "SetIntroStartAtMainCue"), m_bSetIntroStartAtMainCue);
199 checkBoxIntroStartMove->setChecked(m_bSetIntroStartAtMainCue);
200 connect(checkBoxIntroStartMove,
201 &QCheckBox::toggled,
202 this,
203 &DlgPrefDeck::slotMoveIntroStartCheckbox);
204
205 // Double-tap Load to clone a deck via keyboard or controller ([ChannelN],LoadSelectedTrack)
206 m_bCloneDeckOnLoadDoubleTap = m_pConfig->getValue(
207 ConfigKey("[Controls]", "CloneDeckOnLoadDoubleTap"), true);
208 checkBoxCloneDeckOnLoadDoubleTap->setChecked(m_bCloneDeckOnLoadDoubleTap);
209 connect(checkBoxCloneDeckOnLoadDoubleTap,
210 &QCheckBox::toggled,
211 this,
212 &DlgPrefDeck::slotCloneDeckOnLoadDoubleTapCheckbox);
213
214 m_bRateDownIncreasesSpeed = m_pConfig->getValue(ConfigKey("[Controls]", "RateDir"), true);
215 setRateDirectionForAllDecks(m_bRateDownIncreasesSpeed);
216 checkBoxInvertSpeedSlider->setChecked(m_bRateDownIncreasesSpeed);
217 connect(checkBoxInvertSpeedSlider,
218 &QCheckBox::toggled,
219 this,
220 &DlgPrefDeck::slotRateInversionCheckbox);
221
222 ComboBoxRateRange->clear();
223 ComboBoxRateRange->addItem(tr("4%"), 4);
224 ComboBoxRateRange->addItem(tr("6% (semitone)"), 6);
225 ComboBoxRateRange->addItem(tr("8% (Technics SL-1210)"), 8);
226 ComboBoxRateRange->addItem(tr("10%"), 10);
227 ComboBoxRateRange->addItem(tr("16%"), 16);
228 ComboBoxRateRange->addItem(tr("24%"), 24);
229 ComboBoxRateRange->addItem(tr("50%"), 50);
230 ComboBoxRateRange->addItem(tr("90%"), 90);
231 connect(ComboBoxRateRange,
232 QOverload<int>::of(&QComboBox::currentIndexChanged),
233 this,
234 &DlgPrefDeck::slotRateRangeComboBox);
235
236 // RateRange is the legacy ConfigKey. RateRangePercent is used now.
237 if (m_pConfig->exists(ConfigKey("[Controls]", "RateRange")) &&
238 !m_pConfig->exists(ConfigKey("[Controls]", "RateRangePercent"))) {
239 int legacyIndex = m_pConfig->getValueString(ConfigKey("[Controls]", "RateRange")).toInt();
240 if (legacyIndex == 0) {
241 m_iRateRangePercent = 6;
242 } else if (legacyIndex == 1) {
243 m_iRateRangePercent = 8;
244 } else {
245 m_iRateRangePercent = (legacyIndex-1) * 10;
246 }
247 } else {
248 m_iRateRangePercent = m_pConfig->getValue(ConfigKey("[Controls]", "RateRangePercent"),
249 kDefaultRateRangePercent);
250 }
251 if (!(m_iRateRangePercent > 0 && m_iRateRangePercent <= 90)) {
252 m_iRateRangePercent = kDefaultRateRangePercent;
253 }
254 setRateRangeForAllDecks(m_iRateRangePercent);
255
256 //
257 // Key lock mode
258 //
259 connect(buttonGroupKeyLockMode,
260 QOverload<QAbstractButton*>::of(&QButtonGroup::buttonClicked),
261 this,
262 &DlgPrefDeck::slotKeyLockModeSelected);
263
264 m_keylockMode = static_cast<KeylockMode>(
265 m_pConfig->getValue(ConfigKey("[Controls]", "keylockMode"),
266 static_cast<int>(KeylockMode::LockOriginalKey)));
267 for (ControlProxy* pControl : qAsConst(m_keylockModeControls)) {
268 pControl->set(static_cast<double>(m_keylockMode));
269 }
270
271 //
272 // Key unlock mode
273 //
274 connect(buttonGroupKeyUnlockMode,
275 QOverload<QAbstractButton*>::of(&QButtonGroup::buttonClicked),
276 this,
277 &DlgPrefDeck::slotKeyUnlockModeSelected);
278
279 m_keyunlockMode = static_cast<KeyunlockMode>(
280 m_pConfig->getValue(ConfigKey("[Controls]", "keyunlockMode"),
281 static_cast<int>(KeyunlockMode::ResetLockedKey)));
282 for (ControlProxy* pControl : qAsConst(m_keyunlockModeControls)) {
283 pControl->set(static_cast<int>(m_keyunlockMode));
284 }
285
286 //
287 // Cue Mode
288 //
289
290 // Add "(?)" with a manual link to the label
291 labelCueMode->setText(labelCueMode->text() + QStringLiteral(" ") +
292 coloredLinkString(
293 m_pLinkColor,
294 QStringLiteral("(?)"),
295 MIXXX_MANUAL_CUE_MODES_URL));
296
297 //
298 // Speed / Pitch reset configuration
299 //
300
301 // Update "reset speed" and "reset pitch" check boxes
302 // TODO: All defaults should only be set in slotResetToDefaults.
303 int configSPAutoReset = m_pConfig->getValue<int>(
304 ConfigKey("[Controls]", "SpeedAutoReset"),
305 BaseTrackPlayer::RESET_PITCH);
306
307 m_speedAutoReset = (configSPAutoReset==BaseTrackPlayer::RESET_SPEED ||
308 configSPAutoReset==BaseTrackPlayer::RESET_PITCH_AND_SPEED);
309 m_pitchAutoReset = (configSPAutoReset==BaseTrackPlayer::RESET_PITCH ||
310 configSPAutoReset==BaseTrackPlayer::RESET_PITCH_AND_SPEED);
311
312 checkBoxResetSpeed->setChecked(m_speedAutoReset);
313 checkBoxResetPitch->setChecked(m_pitchAutoReset);
314
315 connect(checkBoxResetSpeed, &QCheckBox::toggled, this, &DlgPrefDeck::slotUpdateSpeedAutoReset);
316 connect(checkBoxResetPitch, &QCheckBox::toggled, this, &DlgPrefDeck::slotUpdatePitchAutoReset);
317
318 //
319 // Ramping Temporary Rate Change configuration
320 //
321
322 // Rate Ramp Sensitivity slider & spinbox
323 connect(SliderRateRampSensitivity,
324 QOverload<int>::of(&QAbstractSlider::valueChanged),
325 SpinBoxRateRampSensitivity,
326 QOverload<int>::of(&QSpinBox::setValue));
327 connect(SpinBoxRateRampSensitivity,
328 QOverload<int>::of(&QSpinBox::valueChanged),
329 SliderRateRampSensitivity,
330 QOverload<int>::of(&QAbstractSlider::setValue));
331
332 m_iRateRampSensitivity =
333 m_pConfig->getValue(ConfigKey("[Controls]", "RateRampSensitivity"),
334 kDefaultRateRampSensitivity);
335 SliderRateRampSensitivity->setValue(m_iRateRampSensitivity);
336 connect(SliderRateRampSensitivity,
337 &QSlider::valueChanged,
338 this,
339 &DlgPrefDeck::slotRateRampSensitivitySlider);
340
341 // Enable/disable permanent rate spinboxes when smooth ramping is selected
342 connect(radioButtonRateRampModeLinear,
343 &QRadioButton::toggled,
344 labelSpeedRampSensitivity,
345 &QWidget::setEnabled);
346 connect(radioButtonRateRampModeLinear,
347 &QRadioButton::toggled,
348 SliderRateRampSensitivity,
349 &QWidget::setEnabled);
350 connect(radioButtonRateRampModeLinear,
351 &QRadioButton::toggled,
352 SpinBoxRateRampSensitivity,
353 &QWidget::setEnabled);
354 // Enable/disable temporary rate spinboxes when abrupt ramping is selected
355 connect(radioButtonRateRampModeStepping,
356 &QRadioButton::toggled,
357 labelSpeedTemporary,
358 &QWidget::setEnabled);
359 connect(radioButtonRateRampModeStepping,
360 &QRadioButton::toggled,
361 spinBoxTemporaryRateCoarse,
362 &QWidget::setEnabled);
363 connect(radioButtonRateRampModeStepping,
364 &QRadioButton::toggled,
365 spinBoxTemporaryRateFine,
366 &QWidget::setEnabled);
367 // Set Ramp Rate On or Off
368 connect(radioButtonRateRampModeLinear,
369 &QRadioButton::toggled,
370 this,
371 &DlgPrefDeck::slotRateRampingModeLinearButton);
372 m_bRateRamping = static_cast<RateControl::RampMode>(
373 m_pConfig->getValue(ConfigKey("[Controls]", "RateRamp"),
374 static_cast<int>(kDefaultRampingMode)));
375 if (m_bRateRamping == RateControl::RampMode::Linear) {
376 radioButtonRateRampModeLinear->setChecked(true);
377 } else {
378 radioButtonRateRampModeStepping->setChecked(true);
379 }
380
381 // Rate buttons configuration
382 connect(spinBoxTemporaryRateCoarse,
383 QOverload<double>::of(&QDoubleSpinBox::valueChanged),
384 this,
385 &DlgPrefDeck::slotRateTempCoarseSpinbox);
386 connect(spinBoxTemporaryRateFine,
387 QOverload<double>::of(&QDoubleSpinBox::valueChanged),
388 this,
389 &DlgPrefDeck::slotRateTempFineSpinbox);
390 connect(spinBoxPermanentRateCoarse,
391 QOverload<double>::of(&QDoubleSpinBox::valueChanged),
392 this,
393 &DlgPrefDeck::slotRatePermCoarseSpinbox);
394 connect(spinBoxPermanentRateFine,
395 QOverload<double>::of(&QDoubleSpinBox::valueChanged),
396 this,
397 &DlgPrefDeck::slotRatePermFineSpinbox);
398
399 m_dRateTempCoarse = m_pConfig->getValue(ConfigKey("[Controls]", "RateTempLeft"),
400 kDefaultTemporaryRateChangeCoarse);
401 m_dRateTempFine = m_pConfig->getValue(ConfigKey("[Controls]", "RateTempRight"),
402 kDefaultTemporaryRateChangeFine);
403 m_dRatePermCoarse = m_pConfig->getValue(ConfigKey("[Controls]", "RatePermLeft"),
404 kDefaultPermanentRateChangeCoarse);
405 m_dRatePermFine = m_pConfig->getValue(ConfigKey("[Controls]", "RatePermRight"),
406 kDefaultPermanentRateChangeFine);
407
408 spinBoxTemporaryRateCoarse->setValue(m_dRateTempCoarse);
409 spinBoxTemporaryRateFine->setValue(m_dRateTempFine);
410 spinBoxPermanentRateCoarse->setValue(m_dRatePermCoarse);
411 spinBoxPermanentRateFine->setValue(m_dRatePermFine);
412
413 RateControl::setTemporaryRateChangeCoarseAmount(m_dRateTempCoarse);
414 RateControl::setTemporaryRateChangeFineAmount(m_dRateTempFine);
415 RateControl::setPermanentRateChangeCoarseAmount(m_dRatePermCoarse);
416 RateControl::setPermanentRateChangeFineAmount(m_dRatePermFine);
417
418 slotUpdate();
419 }
420
~DlgPrefDeck()421 DlgPrefDeck::~DlgPrefDeck() {
422 qDeleteAll(m_rateControls);
423 qDeleteAll(m_rateDirectionControls);
424 qDeleteAll(m_cueControls);
425 qDeleteAll(m_rateRangeControls);
426 qDeleteAll(m_keylockModeControls);
427 qDeleteAll(m_keyunlockModeControls);
428 }
429
slotUpdate()430 void DlgPrefDeck::slotUpdate() {
431 checkBoxIntroStartMove->setChecked(m_pConfig->getValue(
432 ConfigKey("[Controls]", "SetIntroStartAtMainCue"), false));
433
434 slotSetTrackTimeDisplay(m_pControlTrackTimeDisplay->get());
435
436 checkBoxDisallowLoadToPlayingDeck->setChecked(!m_pConfig->getValue(
437 ConfigKey("[Controls]", "AllowTrackLoadToPlayingDeck"), false));
438
439 checkBoxCloneDeckOnLoadDoubleTap->setChecked(m_pConfig->getValue(
440 ConfigKey("[Controls]", "CloneDeckOnLoadDoubleTap"), true));
441
442 double rateRange = m_rateRangeControls[0]->get();
443 int index = ComboBoxRateRange->findData(static_cast<int>(rateRange * 100.0));
444 if (index == -1) {
445 ComboBoxRateRange->addItem(QString::number(rateRange * 100.).append("%"),
446 rateRange * 100.);
447 }
448 ComboBoxRateRange->setCurrentIndex(index);
449
450 double rateDirection = m_rateDirectionControls[0]->get();
451 checkBoxInvertSpeedSlider->setChecked(rateDirection == kRateDirectionInverted);
452
453 double cueMode = m_cueControls[0]->get();
454 index = ComboBoxCueMode->findData(static_cast<int>(cueMode));
455 ComboBoxCueMode->setCurrentIndex(index);
456
457 KeylockMode keylockMode =
458 static_cast<KeylockMode>(static_cast<int>(m_keylockModeControls[0]->get()));
459 if (keylockMode == KeylockMode::LockCurrentKey) {
460 radioButtonCurrentKey->setChecked(true);
461 } else {
462 radioButtonOriginalKey->setChecked(true);
463 }
464
465 KeyunlockMode keyunlockMode =
466 static_cast<KeyunlockMode>(static_cast<int>(m_keyunlockModeControls[0]->get()));
467 if (keyunlockMode == KeyunlockMode::KeepLockedKey) {
468 radioButtonKeepUnlockedKey->setChecked(true);
469 } else {
470 radioButtonResetUnlockedKey->setChecked(true);
471 }
472
473 int reset = m_pConfig->getValue(ConfigKey("[Controls]", "SpeedAutoReset"),
474 static_cast<int>(BaseTrackPlayer::RESET_PITCH));
475 if (reset == BaseTrackPlayer::RESET_PITCH) {
476 checkBoxResetPitch->setChecked(true);
477 checkBoxResetSpeed->setChecked(false);
478 } else if (reset == BaseTrackPlayer::RESET_SPEED) {
479 checkBoxResetPitch->setChecked(false);
480 checkBoxResetSpeed->setChecked(true);
481 } else if (reset == BaseTrackPlayer::RESET_PITCH_AND_SPEED) {
482 checkBoxResetPitch->setChecked(true);
483 checkBoxResetSpeed->setChecked(true);
484 } else if (reset == BaseTrackPlayer::RESET_NONE) {
485 checkBoxResetPitch->setChecked(false);
486 checkBoxResetSpeed->setChecked(false);
487 }
488
489 if (m_bRateRamping == RateControl::RampMode::Linear) {
490 radioButtonRateRampModeLinear->setChecked(true);
491 } else {
492 radioButtonRateRampModeStepping->setChecked(true);
493 }
494
495 SliderRateRampSensitivity->setValue(
496 m_pConfig->getValue(ConfigKey("[Controls]", "RateRampSensitivity"),
497 kDefaultRateRampSensitivity));
498
499 spinBoxTemporaryRateCoarse->setValue(RateControl::getTemporaryRateChangeCoarseAmount());
500 spinBoxTemporaryRateFine->setValue(RateControl::getTemporaryRateChangeFineAmount());
501 spinBoxPermanentRateCoarse->setValue(RateControl::getPermanentRateChangeCoarseAmount());
502 spinBoxPermanentRateFine->setValue(RateControl::getPermanentRateChangeFineAmount());
503 }
504
slotResetToDefaults()505 void DlgPrefDeck::slotResetToDefaults() {
506 // Track time display mode
507 radioButtonRemaining->setChecked(true);
508
509 // Up increases speed.
510 checkBoxInvertSpeedSlider->setChecked(false);
511
512 // 8% Rate Range
513 ComboBoxRateRange->setCurrentIndex(ComboBoxRateRange->findData(kDefaultRateRangePercent));
514
515 // Don't load tracks into playing decks.
516 checkBoxDisallowLoadToPlayingDeck->setChecked(true);
517
518 // Clone decks by double-tapping Load button.
519 checkBoxCloneDeckOnLoadDoubleTap->setChecked(kDefaultCloneDeckOnLoad);
520 // Mixxx cue mode
521 ComboBoxCueMode->setCurrentIndex(0);
522
523 // Load at intro start
524 comboBoxLoadPoint->setCurrentIndex(
525 comboBoxLoadPoint->findData(static_cast<int>(SeekOnLoadMode::IntroStart)));
526
527 // Rate-ramping default off.
528 radioButtonRateRampModeStepping->setChecked(true);
529
530 SliderRateRampSensitivity->setValue(kDefaultRateRampSensitivity);
531
532 // Permanent and temporary pitch adjust fine/coarse.
533 spinBoxTemporaryRateCoarse->setValue(4.0);
534 spinBoxTemporaryRateFine->setValue(2.0);
535 spinBoxPermanentRateCoarse->setValue(0.50);
536 spinBoxPermanentRateFine->setValue(0.05);
537
538 checkBoxResetSpeed->setChecked(false);
539 checkBoxResetPitch->setChecked(true);
540
541 radioButtonOriginalKey->setChecked(true);
542 radioButtonResetUnlockedKey->setChecked(true);
543 }
544
slotMoveIntroStartCheckbox(bool checked)545 void DlgPrefDeck::slotMoveIntroStartCheckbox(bool checked) {
546 m_bSetIntroStartAtMainCue = checked;
547 }
548
slotRateRangeComboBox(int index)549 void DlgPrefDeck::slotRateRangeComboBox(int index) {
550 m_iRateRangePercent = ComboBoxRateRange->itemData(index).toInt();
551 }
552
setRateRangeForAllDecks(int rangePercent)553 void DlgPrefDeck::setRateRangeForAllDecks(int rangePercent) {
554 for (ControlProxy* pControl : qAsConst(m_rateRangeControls)) {
555 pControl->set(rangePercent / 100.0);
556 }
557 }
558
slotRateInversionCheckbox(bool inverted)559 void DlgPrefDeck::slotRateInversionCheckbox(bool inverted) {
560 m_bRateDownIncreasesSpeed = inverted;
561 }
562
setRateDirectionForAllDecks(bool inverted)563 void DlgPrefDeck::setRateDirectionForAllDecks(bool inverted) {
564 double oldRateDirectionMultiplier = m_rateDirectionControls[0]->get();
565 double rateDirectionMultiplier = 1.0;
566 if (inverted) {
567 rateDirectionMultiplier = kRateDirectionInverted;
568 }
569 for (ControlProxy* pControl : qAsConst(m_rateDirectionControls)) {
570 pControl->set(rateDirectionMultiplier);
571 }
572
573 // If the rate slider direction setting has changed,
574 // multiply the rate by -1 so the current sound does not change.
575 if (rateDirectionMultiplier != oldRateDirectionMultiplier) {
576 for (ControlProxy* pControl : qAsConst(m_rateControls)) {
577 pControl->set(-1 * pControl->get());
578 }
579 }
580 }
581
slotKeyLockModeSelected(QAbstractButton * pressedButton)582 void DlgPrefDeck::slotKeyLockModeSelected(QAbstractButton* pressedButton) {
583 if (pressedButton == radioButtonCurrentKey) {
584 m_keylockMode = KeylockMode::LockCurrentKey;
585 } else {
586 m_keylockMode = KeylockMode::LockOriginalKey;
587 }
588 }
589
slotKeyUnlockModeSelected(QAbstractButton * pressedButton)590 void DlgPrefDeck::slotKeyUnlockModeSelected(QAbstractButton* pressedButton) {
591 if (pressedButton == radioButtonResetUnlockedKey) {
592 m_keyunlockMode = KeyunlockMode::ResetLockedKey;
593 } else {
594 m_keyunlockMode = KeyunlockMode::KeepLockedKey;
595 }
596 }
597
slotDisallowTrackLoadToPlayingDeckCheckbox(bool checked)598 void DlgPrefDeck::slotDisallowTrackLoadToPlayingDeckCheckbox(bool checked) {
599 m_bDisallowTrackLoadToPlayingDeck = checked;
600 }
601
slotCueModeCombobox(int index)602 void DlgPrefDeck::slotCueModeCombobox(int index) {
603 m_cueMode = static_cast<CueMode>(ComboBoxCueMode->itemData(index).toInt());
604 }
605
slotCloneDeckOnLoadDoubleTapCheckbox(bool checked)606 void DlgPrefDeck::slotCloneDeckOnLoadDoubleTapCheckbox(bool checked) {
607 m_bCloneDeckOnLoadDoubleTap = checked;
608 }
609
slotSetTrackTimeDisplay(QAbstractButton * b)610 void DlgPrefDeck::slotSetTrackTimeDisplay(QAbstractButton* b) {
611 if (b == radioButtonRemaining) {
612 m_timeDisplayMode = TrackTime::DisplayMode::REMAINING;
613 } else if (b == radioButtonElapsedAndRemaining) {
614 m_timeDisplayMode = TrackTime::DisplayMode::ELAPSED_AND_REMAINING;
615 } else {
616 m_timeDisplayMode = TrackTime::DisplayMode::ELAPSED;
617 }
618 }
619
slotSetTrackTimeDisplay(double v)620 void DlgPrefDeck::slotSetTrackTimeDisplay(double v) {
621 m_timeDisplayMode = static_cast<TrackTime::DisplayMode>(static_cast<int>(v));
622 m_pConfig->set(ConfigKey("[Controls]","PositionDisplay"), ConfigValue(v));
623 if (m_timeDisplayMode == TrackTime::DisplayMode::REMAINING) {
624 radioButtonRemaining->setChecked(true);
625 } else if (m_timeDisplayMode == TrackTime::DisplayMode::ELAPSED_AND_REMAINING) {
626 radioButtonElapsedAndRemaining->setChecked(true);
627 } else { // Elapsed
628 radioButtonElapsed->setChecked(true);
629 }
630 }
631
slotRateTempCoarseSpinbox(double value)632 void DlgPrefDeck::slotRateTempCoarseSpinbox(double value) {
633 m_dRateTempCoarse = value;
634 }
635
slotRateTempFineSpinbox(double value)636 void DlgPrefDeck::slotRateTempFineSpinbox(double value) {
637 m_dRateTempFine = value;
638 }
639
slotRatePermCoarseSpinbox(double value)640 void DlgPrefDeck::slotRatePermCoarseSpinbox(double value) {
641 m_dRatePermCoarse = value;
642 }
643
slotRatePermFineSpinbox(double value)644 void DlgPrefDeck::slotRatePermFineSpinbox(double value) {
645 m_dRatePermFine = value;
646 }
647
slotRateRampSensitivitySlider(int value)648 void DlgPrefDeck::slotRateRampSensitivitySlider(int value) {
649 m_iRateRampSensitivity = value;
650 }
651
slotRateRampingModeLinearButton(bool checked)652 void DlgPrefDeck::slotRateRampingModeLinearButton(bool checked) {
653 if (checked) {
654 m_bRateRamping = RateControl::RampMode::Linear;
655 } else {
656 m_bRateRamping = RateControl::RampMode::Stepping;
657 }
658 }
659
slotTimeFormatChanged(double v)660 void DlgPrefDeck::slotTimeFormatChanged(double v) {
661 int i = static_cast<int>(v);
662 m_pConfig->set(ConfigKey("[Controls]","TimeFormat"), ConfigValue(v));
663 comboBoxTimeFormat->setCurrentIndex(
664 comboBoxTimeFormat->findData(i));
665 }
666
slotSetTrackLoadMode(int comboboxIndex)667 void DlgPrefDeck::slotSetTrackLoadMode(int comboboxIndex) {
668 m_seekOnLoadMode = static_cast<SeekOnLoadMode>(
669 comboBoxLoadPoint->itemData(comboboxIndex).toInt());
670 }
671
slotApply()672 void DlgPrefDeck::slotApply() {
673 m_pConfig->set(ConfigKey("[Controls]", "SetIntroStartAtMainCue"),
674 ConfigValue(m_bSetIntroStartAtMainCue));
675
676 double timeDisplay = static_cast<double>(m_timeDisplayMode);
677 m_pConfig->set(ConfigKey("[Controls]","PositionDisplay"), ConfigValue(timeDisplay));
678 m_pControlTrackTimeDisplay->set(timeDisplay);
679
680 // time format
681 double timeFormat = comboBoxTimeFormat->itemData(comboBoxTimeFormat->currentIndex()).toDouble();
682 m_pControlTrackTimeFormat->set(timeFormat);
683 m_pConfig->setValue(ConfigKey("[Controls]", "TimeFormat"), timeFormat);
684
685 // Set cue mode for every deck
686 for (ControlProxy* pControl : qAsConst(m_cueControls)) {
687 pControl->set(static_cast<int>(m_cueMode));
688 }
689 m_pConfig->setValue(ConfigKey("[Controls]", "CueDefault"), static_cast<int>(m_cueMode));
690
691 m_pConfig->setValue(ConfigKey("[Controls]", "AllowTrackLoadToPlayingDeck"),
692 !m_bDisallowTrackLoadToPlayingDeck);
693
694 m_pConfig->setValue(ConfigKey("[Controls]", "CueRecall"), static_cast<int>(m_seekOnLoadMode));
695 m_pConfig->setValue(ConfigKey("[Controls]", "CloneDeckOnLoadDoubleTap"),
696 m_bCloneDeckOnLoadDoubleTap);
697
698 // Set rate range
699 setRateRangeForAllDecks(m_iRateRangePercent);
700 m_pConfig->setValue(ConfigKey("[Controls]", "RateRangePercent"),
701 m_iRateRangePercent);
702
703 setRateDirectionForAllDecks(m_bRateDownIncreasesSpeed);
704 m_pConfig->setValue(ConfigKey("[Controls]", "RateDir"),
705 static_cast<int>(m_bRateDownIncreasesSpeed));
706
707 int configSPAutoReset = BaseTrackPlayer::RESET_NONE;
708
709 if (m_speedAutoReset && m_pitchAutoReset) {
710 configSPAutoReset = BaseTrackPlayer::RESET_PITCH_AND_SPEED;
711 } else if (m_speedAutoReset) {
712 configSPAutoReset = BaseTrackPlayer::RESET_SPEED;
713 } else if (m_pitchAutoReset) {
714 configSPAutoReset = BaseTrackPlayer::RESET_PITCH;
715 }
716
717 m_pConfig->set(ConfigKey("[Controls]", "SpeedAutoReset"),
718 ConfigValue(configSPAutoReset));
719
720 m_pConfig->setValue(ConfigKey("[Controls]", "keylockMode"),
721 static_cast<int>(m_keylockMode));
722 // Set key lock behavior for every group
723 for (ControlProxy* pControl : qAsConst(m_keylockModeControls)) {
724 pControl->set(static_cast<double>(m_keylockMode));
725 }
726
727 m_pConfig->setValue(ConfigKey("[Controls]", "keyunlockMode"),
728 static_cast<int>(m_keyunlockMode));
729 // Set key un-lock behavior for every group
730 for (ControlProxy* pControl : qAsConst(m_keyunlockModeControls)) {
731 pControl->set(static_cast<double>(m_keyunlockMode));
732 }
733
734 RateControl::setRateRampMode(m_bRateRamping);
735 m_pConfig->setValue(ConfigKey("[Controls]", "RateRamp"), static_cast<int>(m_bRateRamping));
736
737 RateControl::setRateRampSensitivity(m_iRateRampSensitivity);
738 m_pConfig->setValue(ConfigKey("[Controls]", "RateRampSensitivity"), m_iRateRampSensitivity);
739
740 RateControl::setTemporaryRateChangeCoarseAmount(m_dRateTempCoarse);
741 RateControl::setTemporaryRateChangeFineAmount(m_dRateTempFine);
742 RateControl::setPermanentRateChangeCoarseAmount(m_dRatePermCoarse);
743 RateControl::setPermanentRateChangeFineAmount(m_dRatePermFine);
744
745 m_pConfig->setValue(ConfigKey("[Controls]", "RateTempLeft"), m_dRateTempCoarse);
746 m_pConfig->setValue(ConfigKey("[Controls]", "RateTempRight"), m_dRateTempFine);
747 m_pConfig->setValue(ConfigKey("[Controls]", "RatePermLeft"), m_dRatePermCoarse);
748 m_pConfig->setValue(ConfigKey("[Controls]", "RatePermRight"), m_dRatePermFine);
749 }
750
slotNumDecksChanged(double new_count,bool initializing)751 void DlgPrefDeck::slotNumDecksChanged(double new_count, bool initializing) {
752 int numdecks = static_cast<int>(new_count);
753 if (numdecks <= m_iNumConfiguredDecks) {
754 // TODO(owilliams): If we implement deck deletion, shrink the size of configured decks.
755 return;
756 }
757
758 for (int i = m_iNumConfiguredDecks; i < numdecks; ++i) {
759 QString group = PlayerManager::groupForDeck(i);
760 m_rateControls.push_back(new ControlProxy(
761 group, "rate"));
762 m_rateRangeControls.push_back(new ControlProxy(
763 group, "rateRange"));
764 m_rateDirectionControls.push_back(new ControlProxy(
765 group, "rate_dir"));
766 m_cueControls.push_back(new ControlProxy(
767 group, "cue_mode"));
768 m_keylockModeControls.push_back(new ControlProxy(
769 group, "keylockMode"));
770 m_keylockModeControls.last()->set(static_cast<double>(m_keylockMode));
771 m_keyunlockModeControls.push_back(new ControlProxy(
772 group, "keyunlockMode"));
773 m_keyunlockModeControls.last()->set(static_cast<double>(m_keyunlockMode));
774 }
775
776 m_iNumConfiguredDecks = numdecks;
777
778 // The rate range hasn't been read from the config file when this is first called.
779 if (!initializing) {
780 setRateDirectionForAllDecks(m_rateDirectionControls[0]->get() == kRateDirectionInverted);
781 setRateRangeForAllDecks(static_cast<int>(m_rateRangeControls[0]->get() * 100.0));
782 }
783 }
784
slotNumSamplersChanged(double new_count,bool initializing)785 void DlgPrefDeck::slotNumSamplersChanged(double new_count, bool initializing) {
786 int numsamplers = static_cast<int>(new_count);
787 if (numsamplers <= m_iNumConfiguredSamplers) {
788 return;
789 }
790
791 for (int i = m_iNumConfiguredSamplers; i < numsamplers; ++i) {
792 QString group = PlayerManager::groupForSampler(i);
793 m_rateControls.push_back(new ControlProxy(
794 group, "rate"));
795 m_rateRangeControls.push_back(new ControlProxy(
796 group, "rateRange"));
797 m_rateDirectionControls.push_back(new ControlProxy(
798 group, "rate_dir"));
799 m_cueControls.push_back(new ControlProxy(
800 group, "cue_mode"));
801 m_keylockModeControls.push_back(new ControlProxy(
802 group, "keylockMode"));
803 m_keylockModeControls.last()->set(static_cast<double>(m_keylockMode));
804 m_keyunlockModeControls.push_back(new ControlProxy(
805 group, "keyunlockMode"));
806 m_keyunlockModeControls.last()->set(static_cast<double>(m_keyunlockMode));
807 }
808
809 m_iNumConfiguredSamplers = numsamplers;
810
811 // The rate range hasn't been read from the config file when this is first called.
812 if (!initializing) {
813 setRateDirectionForAllDecks(m_rateDirectionControls[0]->get() == kRateDirectionInverted);
814 setRateRangeForAllDecks(static_cast<int>(m_rateRangeControls[0]->get() * 100.0));
815 }
816 }
817
slotUpdateSpeedAutoReset(bool b)818 void DlgPrefDeck::slotUpdateSpeedAutoReset(bool b) {
819 m_speedAutoReset = b;
820 }
821
slotUpdatePitchAutoReset(bool b)822 void DlgPrefDeck::slotUpdatePitchAutoReset(bool b) {
823 m_pitchAutoReset = b;
824 }
825
cueDefaultIndexByData(int userData) const826 int DlgPrefDeck::cueDefaultIndexByData(int userData) const {
827 for (int i = 0; i < ComboBoxCueMode->count(); ++i) {
828 if (ComboBoxCueMode->itemData(i).toInt() == userData) {
829 return i;
830 }
831 }
832 qWarning() << "No default cue behavior found for value" << userData
833 << "returning default";
834 return 0;
835 }
836