1 #include "controllers/controlpickermenu.h"
2
3 #include "effects/effectchainslot.h"
4 #include "effects/effectparameterslot.h"
5 #include "effects/effectrack.h"
6 #include "effects/effectslot.h"
7 #include "engine/controls/cuecontrol.h"
8 #include "engine/controls/loopingcontrol.h"
9 #include "mixer/playermanager.h"
10 #include "moc_controlpickermenu.cpp"
11 #include "recording/defs_recording.h"
12 #include "vinylcontrol/defs_vinylcontrol.h"
13
ControlPickerMenu(QWidget * pParent)14 ControlPickerMenu::ControlPickerMenu(QWidget* pParent)
15 : QMenu(pParent) {
16 m_effectMasterOutputStr = tr("Master Output");
17 m_effectHeadphoneOutputStr = tr("Headphone Output");
18 m_deckStr = tr("Deck %1");
19 m_samplerStr = tr("Sampler %1");
20 m_previewdeckStr = tr("Preview Deck %1");
21 m_microphoneStr = tr("Microphone %1");
22 m_auxStr = tr("Auxiliary %1");
23 m_resetStr = tr("Reset to default");
24 m_effectRackStr = tr("Effect Rack %1");
25 m_effectUnitStr = tr("Effect Unit %1");
26 m_effectStr = tr("Slot %1");
27 m_parameterStr = tr("Parameter %1");
28 m_libraryStr = tr("Library");
29
30 // Mixer Controls
31 QMenu* mixerMenu = addSubmenu(tr("Mixer"));
32 // Crossfader / Orientation
33 QMenu* crossfaderMenu = addSubmenu(tr("Crossfader / Orientation"), mixerMenu);
34 addControl("[Master]",
35 "crossfader",
36 tr("Crossfader"),
37 tr("Master crossfader"),
38 crossfaderMenu,
39 true);
40 addDeckAndSamplerControl("orientation",
41 tr("Orientation"),
42 tr("Mix orientation (e.g. left, right, center)"),
43 crossfaderMenu);
44 addDeckAndSamplerControl("orientation_left",
45 tr("Orient Left"),
46 tr("Set mix orientation to left"),
47 crossfaderMenu);
48 addDeckAndSamplerControl("orientation_center",
49 tr("Orient Center"),
50 tr("Set mix orientation to center"),
51 crossfaderMenu);
52 addDeckAndSamplerControl("orientation_right",
53 tr("Orient Right"),
54 tr("Set mix orientation to right"),
55 crossfaderMenu);
56 // Main Output
57 QMenu* mainOutputMenu = addSubmenu(tr("Main Output"), mixerMenu);
58 addControl("[Master]",
59 "gain",
60 tr("Main Output Gain"),
61 tr("Main Output gain"),
62 mainOutputMenu,
63 true);
64 addControl("[Master]",
65 "balance",
66 tr("Main Output Balance"),
67 tr("Main Output balance"),
68 mainOutputMenu,
69 true);
70 addControl("[Master]",
71 "delay",
72 tr("Main Output Delay"),
73 tr("Main Output delay"),
74 mainOutputMenu,
75 true);
76 // Headphone
77 QMenu* headphoneMenu = addSubmenu(tr("Headphone"), mixerMenu);
78 addControl("[Master]",
79 "headGain",
80 tr("Headphone Gain"),
81 tr("Headphone gain"),
82 headphoneMenu,
83 true);
84 addControl("[Master]",
85 "headMix",
86 tr("Headphone Mix"),
87 tr("Headphone mix (pre/main)"),
88 headphoneMenu,
89 true);
90 addControl("[Master]",
91 "headSplit",
92 tr("Headphone Split Cue"),
93 tr("Toggle headphone split cueing"),
94 headphoneMenu);
95 addControl("[Master]",
96 "headDelay",
97 tr("Headphone Delay"),
98 tr("Headphone delay"),
99 headphoneMenu,
100 true);
101 mixerMenu->addSeparator();
102 // EQs
103 QMenu* eqMenu = addSubmenu(tr("Equalizers"), mixerMenu);
104 constexpr int kNumEqRacks = 1;
105 const int iNumDecks = static_cast<int>(ControlObject::get(ConfigKey("[Master]", "num_decks")));
106 for (int iRackNumber = 0; iRackNumber < kNumEqRacks; ++iRackNumber) {
107 // TODO: Although there is a mode with 4-band EQs, it's not feasible
108 // right now to add support for learning both it and regular 3-band eqs.
109 // Since 3-band is by far the most common, stick with that.
110 const int kMaxEqs = 3;
111 QList<QString> eqNames;
112 eqNames.append(tr("Low EQ"));
113 eqNames.append(tr("Mid EQ"));
114 eqNames.append(tr("High EQ"));
115 for (int deck = 1; deck <= iNumDecks; ++deck) {
116 QMenu* deckMenu = addSubmenu(QString("Deck %1").arg(deck), eqMenu);
117 for (int effect = kMaxEqs - 1; effect >= 0; --effect) {
118 const QString group = EqualizerRack::formatEffectSlotGroupString(
119 iRackNumber, 0, QString("[Channel%1]").arg(deck));
120 QMenu* bandMenu = addSubmenu(eqNames[effect], deckMenu);
121 QString control = "parameter%1";
122 addControl(group,
123 control.arg(effect + 1),
124 tr("Adjust %1").arg(eqNames[effect]),
125 tr("Adjust %1").arg(eqNames[effect]),
126 bandMenu,
127 true,
128 tr("Deck %1").arg(deck));
129
130 control = "button_parameter%1";
131 addControl(group,
132 control.arg(effect + 1),
133 tr("Kill %1").arg(eqNames[effect]),
134 tr("Kill %1").arg(eqNames[effect]),
135 bandMenu,
136 false,
137 tr("Deck %1").arg(deck));
138 }
139 }
140 }
141 mixerMenu->addSeparator();
142 // Volume / Pfl controls
143 addDeckAndSamplerControl("volume", tr("Volume"), tr("Volume Fader"), mixerMenu, true);
144 addDeckAndSamplerControl("volume_set_one",
145 tr("Full Volume"),
146 tr("Set to full volume"),
147 mixerMenu);
148 addDeckAndSamplerControl("volume_set_zero",
149 tr("Zero Volume"),
150 tr("Set to zero volume"),
151 mixerMenu);
152 addDeckAndSamplerAndPreviewDeckControl("pregain",
153 tr("Track Gain"),
154 tr("Track Gain knob"),
155 mixerMenu,
156 true);
157 addDeckAndSamplerControl("mute", tr("Mute"), tr("Mute button"), mixerMenu);
158 mixerMenu->addSeparator();
159 addDeckAndSamplerControl("pfl",
160 tr("Headphone Listen"),
161 tr("Headphone listen (pfl) button"),
162 mixerMenu);
163
164 addSeparator();
165
166 // Transport
167 QMenu* transportMenu = addSubmenu(tr("Transport"));
168 addDeckAndSamplerAndPreviewDeckControl("play", tr("Play"), tr("Play button"), transportMenu);
169 addDeckAndSamplerAndPreviewDeckControl("back", tr("Fast Rewind"), tr("Fast Rewind button"), transportMenu);
170 addDeckAndSamplerAndPreviewDeckControl("fwd", tr("Fast Forward"), tr("Fast Forward button"), transportMenu);
171 addDeckAndSamplerAndPreviewDeckControl("playposition", tr("Strip Search"),
172 tr("Strip-search through track"), transportMenu);
173 addDeckAndSamplerAndPreviewDeckControl("reverse", tr("Play Reverse"), tr("Play Reverse button"), transportMenu);
174 addDeckAndSamplerAndPreviewDeckControl("reverseroll", tr("Reverse Roll (Censor)"),
175 tr("Reverse roll (Censor) button"), transportMenu);
176 addDeckAndSamplerAndPreviewDeckControl("start", tr("Jump To Start"), tr("Jumps to start of track"), transportMenu);
177 addDeckAndSamplerAndPreviewDeckControl("start_play", tr("Play From Start"),
178 tr("Jump to start of track and play"), transportMenu);
179 addDeckAndSamplerAndPreviewDeckControl("stop", tr("Stop"), tr("Stop button"), transportMenu);
180 addDeckAndSamplerAndPreviewDeckControl("start_stop", tr("Stop And Jump To Start"),
181 tr("Stop playback and jump to start of track"), transportMenu);
182 addDeckAndSamplerAndPreviewDeckControl("end", tr("Jump To End"), tr("Jump to end of track"), transportMenu);
183 transportMenu->addSeparator();
184 addDeckAndSamplerAndPreviewDeckControl("eject", tr("Eject"), tr("Eject track"), transportMenu);
185 addDeckAndSamplerControl("repeat", tr("Repeat Mode"), tr("Toggle repeat mode"), transportMenu);
186 addDeckAndSamplerControl("slip_enabled", tr("Slip Mode"), tr("Toggle slip mode"), transportMenu);
187
188 // BPM / Beatgrid
189 QMenu* bpmMenu = addSubmenu(tr("BPM / Beatgrid"));
190 addDeckAndSamplerControl("bpm", tr("BPM"), tr("BPM"), bpmMenu, true);
191 addDeckAndSamplerControl("bpm_up", tr("BPM +1"), tr("Increase BPM by 1"), bpmMenu);
192 addDeckAndSamplerControl("bpm_down", tr("BPM -1"), tr("Decrease BPM by 1"), bpmMenu);
193 addDeckAndSamplerControl("bpm_up_small", tr("BPM +0.1"), tr("Increase BPM by 0.1"), bpmMenu);
194 addDeckAndSamplerControl("bpm_down_small", tr("BPM -0.1"), tr("Decrease BPM by 0.1"), bpmMenu);
195 addDeckAndSamplerControl("bpm_tap", tr("BPM Tap"), tr("BPM tap button"), bpmMenu);
196 bpmMenu->addSeparator();
197 addDeckAndSamplerControl("beats_adjust_faster", tr("Adjust Beatgrid Faster +.01"), tr("Increase track's average BPM by 0.01"), bpmMenu);
198 addDeckAndSamplerControl("beats_adjust_slower", tr("Adjust Beatgrid Slower -.01"), tr("Decrease track's average BPM by 0.01"), bpmMenu);
199 addDeckAndSamplerControl("beats_translate_earlier", tr("Move Beatgrid Earlier"), tr("Adjust the beatgrid to the left"), bpmMenu);
200 addDeckAndSamplerControl("beats_translate_later", tr("Move Beatgrid Later"), tr("Adjust the beatgrid to the right"), bpmMenu);
201 addDeckControl("beats_translate_curpos", tr("Adjust Beatgrid"),
202 tr("Align beatgrid to current position"), bpmMenu);
203 addDeckControl("beats_translate_match_alignment", tr("Adjust Beatgrid - Match Alignment"),
204 tr("Adjust beatgrid to match another playing deck."), bpmMenu);
205 bpmMenu->addSeparator();
206 addDeckAndSamplerControl("quantize", tr("Quantize Mode"), tr("Toggle quantize mode"), bpmMenu);
207
208 QMenu* syncMenu = addSubmenu(tr("Sync"));
209 addDeckAndSamplerControl("sync_enabled",
210 tr("Sync / Sync Lock"),
211 tr("Tap to sync tempo (and phase with quantize enabled), hold to "
212 "enable permanent sync"),
213 syncMenu);
214 addDeckAndSamplerControl("beatsync",
215 tr("Beat Sync One-Shot"),
216 tr("One-time beat sync tempo (and phase with quantize enabled)"),
217 syncMenu);
218 addDeckAndSamplerControl("beatsync_tempo",
219 tr("Sync Tempo One-Shot"),
220 tr("One-time beat sync (tempo only)"),
221 syncMenu);
222 addDeckAndSamplerControl("beatsync_phase",
223 tr("Sync Phase One-Shot"),
224 tr("One-time beat sync (phase only)"),
225 syncMenu);
226 syncMenu->addSeparator();
227 addControl("[InternalClock]", "sync_master", tr("Internal Sync Master"),
228 tr("Toggle Internal Sync Master"), syncMenu);
229 addControl("[InternalClock]", "bpm", tr("Internal Master BPM"),
230 tr("Internal Master BPM"), syncMenu);
231 addControl("[InternalClock]", "bpm_up", tr("Internal Master BPM +1"),
232 tr("Increase internal master BPM by 1"), syncMenu);
233
234 addControl("[InternalClock]", "bpm_down", tr("Internal Master BPM -1"),
235 tr("Decrease internal master BPM by 1"), syncMenu);
236
237 addControl("[InternalClock]", "bpm_up_small", tr("Internal Master BPM +0.1"),
238 tr("Increase internal master BPM by 0.1"), syncMenu);
239 addControl("[InternalClock]", "bpm_down_small", tr("Internal Master BPM -0.1"),
240 tr("Decrease internal master BPM by 0.1"), syncMenu);
241 syncMenu->addSeparator();
242 addDeckAndSamplerControl("sync_master", tr("Sync Master"), tr("Toggle sync master"), syncMenu);
243 addDeckAndSamplerControl("sync_mode", tr("Sync Mode"),
244 tr("Sync mode 3-state toggle (OFF, FOLLOWER, MASTER)"), syncMenu);
245
246 // Speed
247 QMenu* speedMenu = addSubmenu(tr("Speed"));
248 addDeckAndSamplerControl("rate", tr("Playback Speed"),
249 tr("Playback speed control (Vinyl \"Pitch\" slider)"), speedMenu, true);
250 speedMenu->addSeparator();
251 addDeckAndSamplerControl("rate_perm_up", tr("Increase Speed"),
252 tr("Adjust speed faster (coarse)"), speedMenu);
253 addDeckAndSamplerControl("rate_perm_up_small", tr("Increase Speed (Fine)"),
254 tr("Adjust speed faster (fine)"), speedMenu);
255 addDeckAndSamplerControl("rate_perm_down", tr("Decrease Speed"),
256 tr("Adjust speed slower (coarse)"), speedMenu);
257 addDeckAndSamplerControl("rate_perm_down_small", tr("Increase Speed (Fine)"),
258 tr("Adjust speed slower (fine)"), speedMenu);
259 speedMenu->addSeparator();
260 addDeckAndSamplerControl("rate_temp_up", tr("Temporarily Increase Speed"),
261 tr("Temporarily increase speed (coarse)"), speedMenu);
262 addDeckAndSamplerControl("rate_temp_up_small", tr("Temporarily Increase Speed (Fine)"),
263 tr("Temporarily increase speed (fine)"), speedMenu);
264 addDeckAndSamplerControl("rate_temp_down", tr("Temporarily Decrease Speed"),
265 tr("Temporarily decrease speed (coarse)"), speedMenu);
266 addDeckAndSamplerControl("rate_temp_down_small", tr("Temporarily Decrease Speed (Fine)"),
267 tr("Temporarily decrease speed (fine)"), speedMenu);
268 // Pitch (Musical Key)
269 QMenu* pitchMenu = addSubmenu(tr("Pitch (Musical Key)"));
270 addDeckAndSamplerControl("pitch",
271 tr("Pitch (Musical key)"),
272 tr("Pitch control (does not affect tempo), center is original "
273 "pitch"),
274 pitchMenu,
275 true);
276 addDeckAndSamplerControl("pitch_up",
277 tr("Increase Pitch"),
278 tr("Increases the pitch by one semitone"),
279 pitchMenu);
280 addDeckAndSamplerControl("pitch_up_small",
281 tr("Increase Pitch (Fine)"),
282 tr("Increases the pitch by 10 cents"),
283 pitchMenu);
284 addDeckAndSamplerControl("pitch_down",
285 tr("Decrease Pitch"),
286 tr("Decreases the pitch by one semitone"),
287 pitchMenu);
288 addDeckAndSamplerControl("pitch_down_small",
289 tr("Decrease Pitch (Fine)"),
290 tr("Decreases the pitch by 10 cents"),
291 pitchMenu);
292 addDeckAndSamplerControl("pitch_adjust",
293 tr("Pitch Adjust"),
294 tr("Adjust pitch from speed slider pitch"),
295 pitchMenu,
296 true);
297 pitchMenu->addSeparator();
298 addDeckAndSamplerControl("sync_key", tr("Match Key"), tr("Match musical key"), pitchMenu);
299 addDeckAndSamplerControl("reset_key", tr("Reset Key"), tr("Resets key to original"), pitchMenu);
300 addDeckAndSamplerControl("keylock", tr("Keylock"), tr("Toggle keylock mode"), pitchMenu);
301
302 // Vinyl Control
303 QMenu* vinylControlMenu = addSubmenu(tr("Vinyl Control"));
304 addDeckControl("vinylcontrol_enabled", tr("Toggle Vinyl Control"),
305 tr("Toggle Vinyl Control (ON/OFF)"), vinylControlMenu);
306 addDeckControl("vinylcontrol_mode", tr("Vinyl Control Mode"),
307 tr("Toggle vinyl-control mode (ABS/REL/CONST)"), vinylControlMenu);
308 addDeckControl("vinylcontrol_cueing", tr("Vinyl Control Cueing Mode"),
309 tr("Toggle vinyl-control cueing mode (OFF/ONE/HOT)"), vinylControlMenu);
310 addDeckControl("passthrough", tr("Vinyl Control Passthrough"),
311 tr("Pass through external audio into the internal mixer"), vinylControlMenu);
312 addControl(VINYL_PREF_KEY, "Toggle", tr("Vinyl Control Next Deck"),
313 tr("Single deck mode - Switch vinyl control to next deck"), vinylControlMenu);
314
315 // Cues
316 QMenu* cueMenu = addSubmenu(tr("Cues"));
317 addDeckControl("cue_default", tr("Cue"), tr("Cue button"), cueMenu);
318 addDeckControl("cue_set", tr("Set Cue"), tr("Set cue point"), cueMenu);
319 addDeckControl("cue_goto", tr("Go-To Cue"), tr("Go to cue point"), cueMenu);
320 addDeckAndSamplerAndPreviewDeckControl("cue_gotoandplay", tr("Go-To Cue And Play"),
321 tr("Go to cue point and play"), cueMenu);
322 addDeckControl("cue_gotoandstop", tr("Go-To Cue And Stop"),
323 tr("Go to cue point and stop"), cueMenu);
324 addDeckControl("cue_preview", tr("Preview Cue"),
325 tr("Preview from cue point"), cueMenu);
326 addDeckControl("cue_cdj", tr("Cue (CDJ Mode)"),
327 tr("Cue button (CDJ mode)"), cueMenu);
328 addDeckControl("play_stutter", tr("Stutter Cue"),
329 tr("Stutter cue"), cueMenu);
330 addDeckControl("cue_play", tr("CUP (Cue + Play)"),
331 tr("Go to cue point and play after release"), cueMenu);
332
333 // Hotcues
334 QMenu* hotcueMainMenu = addSubmenu(tr("Hotcues"));
335 QString hotcueActivateTitle = tr("Hotcue %1");
336 QString hotcueClearTitle = tr("Clear Hotcue %1");
337 QString hotcueSetTitle = tr("Set Hotcue %1");
338 QString hotcueGotoTitle = tr("Jump To Hotcue %1");
339 QString hotcueGotoAndStopTitle = tr("Jump To Hotcue %1 And Stop");
340 QString hotcueGotoAndPlayTitle = tr("Jump To Hotcue %1 And Play");
341 QString hotcuePreviewTitle = tr("Preview Hotcue %1");
342 QString hotcueActivateDescription = tr("Set, preview from or jump to hotcue %1");
343 QString hotcueClearDescription = tr("Clear hotcue %1");
344 QString hotcueSetDescription = tr("Set hotcue %1");
345 QString hotcueGotoDescription = tr("Jump to hotcue %1");
346 QString hotcueGotoAndStopDescription = tr("Jump to hotcue %1 and stop");
347 QString hotcueGotoAndPlayDescription = tr("Jump to hotcue %1 and play");
348 QString hotcuePreviewDescription = tr("Preview from hotcue %1");
349 addDeckControl("shift_cues_earlier",
350 tr("Shift cue points earlier"),
351 tr("Shift cue points 10 milliseconds earlier"),
352 hotcueMainMenu);
353 addDeckControl("shift_cues_earlier_small",
354 tr("Shift cue points earlier (fine)"),
355 tr("Shift cue points 1 millisecond earlier"),
356 hotcueMainMenu);
357 addDeckControl("shift_cues_later",
358 tr("Shift cue points later"),
359 tr("Shift cue points 10 milliseconds later"),
360 hotcueMainMenu);
361 addDeckControl("shift_cues_later_small",
362 tr("Shift cue points later (fine)"),
363 tr("Shift cue points 1 millisecond later"),
364 hotcueMainMenu);
365 // add menus for hotcues 1-16.
366 // though, keep the menu small put additional hotcues in a separate menu,
367 // but don't create that submenu for less than 4 additional hotcues.
368 int preferredHotcuesVisible = 16;
369 int moreMenuThreshold = 4;
370 QMenu* parentMenu = hotcueMainMenu;
371 QMenu* hotcueMoreMenu = nullptr;
372 bool moreHotcues = NUM_HOT_CUES >= preferredHotcuesVisible + moreMenuThreshold;
373 if (moreHotcues) {
374 // populate menu here, add it below #preferredHotcuesVisible
375 hotcueMoreMenu = new QMenu(
376 tr("Hotcues %1-%2").arg(preferredHotcuesVisible + 1).arg(NUM_HOT_CUES),
377 hotcueMainMenu);
378 }
379 for (int i = 1; i <= NUM_HOT_CUES; ++i) {
380 if (moreHotcues && i > preferredHotcuesVisible) {
381 parentMenu = hotcueMoreMenu;
382 }
383 QMenu* hotcueSubMenu = addSubmenu(tr("Hotcue %1").arg(QString::number(i)), parentMenu);
384 addDeckAndSamplerControl(QString("hotcue_%1_activate").arg(i),
385 hotcueActivateTitle.arg(QString::number(i)),
386 hotcueActivateDescription.arg(QString::number(i)),
387 hotcueSubMenu);
388 addDeckAndSamplerControl(QString("hotcue_%1_clear").arg(i),
389 hotcueClearTitle.arg(QString::number(i)),
390 hotcueClearDescription.arg(QString::number(i)),
391 hotcueSubMenu);
392 addDeckAndSamplerControl(QString("hotcue_%1_set").arg(i),
393 hotcueSetTitle.arg(QString::number(i)),
394 hotcueSetDescription.arg(QString::number(i)),
395 hotcueSubMenu);
396 addDeckAndSamplerControl(QString("hotcue_%1_goto").arg(i),
397 hotcueGotoTitle.arg(QString::number(i)),
398 hotcueGotoDescription.arg(QString::number(i)),
399 hotcueSubMenu);
400 addDeckAndSamplerControl(QString("hotcue_%1_gotoandstop").arg(i),
401 hotcueGotoAndStopTitle.arg(QString::number(i)),
402 hotcueGotoAndStopDescription.arg(QString::number(i)),
403 hotcueSubMenu);
404 addDeckAndSamplerControl(QString("hotcue_%1_gotoandplay").arg(i),
405 hotcueGotoAndPlayTitle.arg(QString::number(i)),
406 hotcueGotoAndPlayDescription.arg(QString::number(i)),
407 hotcueSubMenu);
408 addDeckAndSamplerControl(QString("hotcue_%1_activate_preview").arg(i),
409 hotcuePreviewTitle.arg(QString::number(i)),
410 hotcuePreviewDescription.arg(QString::number(i)),
411 hotcueSubMenu);
412 }
413 if (moreHotcues) {
414 hotcueMainMenu->addSeparator();
415 hotcueMainMenu->addMenu(hotcueMoreMenu);
416 }
417
418 // Intro/outro range markers
419 QMenu* introOutroMenu = addSubmenu(tr("Intro / Outro Markers"));
420 const QStringList markerTitles = {
421 tr("Intro Start Marker"),
422 tr("Intro End Marker"),
423 tr("Outro Start Marker"),
424 tr("Outro End Marker")};
425 const QStringList markerNames = {
426 tr("intro start marker"),
427 tr("intro end marker"),
428 tr("outro start marker"),
429 tr("outro end marker")};
430 const QStringList markerCOs = {
431 "intro_start",
432 "intro_end",
433 "outro_start",
434 "outro_end"};
435
436 for (int i = 0; i < markerTitles.size(); ++i) {
437 QMenu* tempMenu = addSubmenu(markerTitles[i], introOutroMenu);
438 addDeckAndSamplerAndPreviewDeckControl(
439 QString("%1_activate").arg(markerCOs[i]),
440 tr("Activate %1", "[intro/outro marker").arg(markerTitles[i]),
441 tr("Jump to or set the %1", "[intro/outro marker").arg(markerNames[i]),
442 tempMenu);
443 addDeckAndSamplerAndPreviewDeckControl(
444 QString("%1_set").arg(markerCOs[i]),
445 tr("Set %1", "[intro/outro marker").arg(markerTitles[i]),
446 tr("Set or jump to the %1", "[intro/outro marker").arg(markerNames[i]),
447 tempMenu);
448 addDeckAndSamplerAndPreviewDeckControl(
449 QString("%1_clear").arg(markerCOs[i]),
450 tr("Clear %1", "[intro/outro marker").arg(markerTitles[i]),
451 tr("Clear the %1", "[intro/outro marker").arg(markerNames[i]),
452 tempMenu);
453 }
454
455 // Loops
456 QMenu* loopMenu = addSubmenu(tr("Looping"));
457 // add beatloop_activate and beatlooproll_activate to both the
458 // Loop and Beat-Loop menus to make sure users can find them.
459 QString beatloopActivateTitle = tr("Loop Selected Beats");
460 QString beatloopActivateDescription = tr("Create a beat loop of selected beat size");
461 QString beatloopRollActivateTitle = tr("Loop Roll Selected Beats");
462 QString beatloopRollActivateDescription = tr("Create a rolling beat loop of selected beat size");
463 QString beatLoopTitle = tr("Loop %1 Beats");
464 QString beatLoopRollTitle = tr("Loop Roll %1 Beats");
465 QString beatLoopDescription = tr("Create %1-beat loop");
466 QString beatLoopRollDescription = tr("Create temporary %1-beat loop roll");
467
468 QList<double> beatSizes = LoopingControl::getBeatSizes();
469
470 QMap<double, QString> humanBeatSizes;
471 humanBeatSizes[0.03125] = tr("1/32");
472 humanBeatSizes[0.0625] = tr("1/16");
473 humanBeatSizes[0.125] = tr("1/8");
474 humanBeatSizes[0.25] = tr("1/4");
475 humanBeatSizes[0.5] = tr("1/2");
476 humanBeatSizes[1] = tr("1");
477 humanBeatSizes[2] = tr("2");
478 humanBeatSizes[4] = tr("4");
479 humanBeatSizes[8] = tr("8");
480 humanBeatSizes[16] = tr("16");
481 humanBeatSizes[32] = tr("32");
482 humanBeatSizes[64] = tr("64");
483
484 // Beatloops
485 addDeckControl("beatloop_activate",
486 beatloopActivateTitle,
487 beatloopActivateDescription,
488 loopMenu);
489 QMenu* loopActivateMenu = addSubmenu(tr("Loop Beats"), loopMenu);
490 foreach (double beats, beatSizes) {
491 QString humanBeats = humanBeatSizes.value(beats, QString::number(beats));
492 addDeckControl(QString("beatloop_%1_toggle").arg(beats),
493 beatLoopTitle.arg(humanBeats),
494 beatLoopDescription.arg(humanBeats),
495 loopActivateMenu);
496 }
497 loopMenu->addSeparator();
498
499 addDeckControl("beatlooproll_activate",
500 beatloopRollActivateTitle,
501 beatloopRollActivateDescription,
502 loopMenu);
503 QMenu* looprollActivateMenu = addSubmenu(tr("Loop Roll Beats"), loopMenu);
504 foreach (double beats, beatSizes) {
505 QString humanBeats = humanBeatSizes.value(beats, QString::number(beats));
506 addDeckControl(QString("beatlooproll_%1_activate").arg(beats),
507 beatLoopRollTitle.arg(humanBeats),
508 beatLoopRollDescription.arg(humanBeats),
509 looprollActivateMenu);
510 }
511 loopMenu->addSeparator();
512
513 addDeckControl("loop_in", tr("Loop In"), tr("Loop In button"), loopMenu);
514 addDeckControl("loop_out", tr("Loop Out"), tr("Loop Out button"), loopMenu);
515 addDeckControl("loop_exit", tr("Loop Exit"), tr("Loop Exit button"), loopMenu);
516 addDeckControl("reloop_toggle",
517 tr("Reloop/Exit Loop"),
518 tr("Toggle loop on/off and jump to Loop In point if loop is behind "
519 "play position"),
520 loopMenu);
521 addDeckControl("reloop_andstop",
522 tr("Reloop And Stop"),
523 tr("Enable loop, jump to Loop In point, and stop"),
524 loopMenu);
525 addDeckControl("loop_halve", tr("Loop Halve"), tr("Halve the loop length"), loopMenu);
526 addDeckControl("loop_double", tr("Loop Double"), tr("Double the loop length"), loopMenu);
527
528 // Beat Jump / Loop Move
529 QMenu* beatJumpMenu = addSubmenu(tr("Beat Jump / Loop Move"));
530 QString beatJumpForwardTitle = tr("Jump / Move Loop Forward %1 Beats");
531 QString beatJumpBackwardTitle = tr("Jump / Move Loop Backward %1 Beats");
532 QString beatJumpForwardDescription = tr("Jump forward by %1 beats, or if a loop is enabled, move the loop forward %1 beats");
533 QString beatJumpBackwardDescription = tr("Jump backward by %1 beats, or if a loop is enabled, move the loop backward %1 beats");
534 addDeckControl("beatjump_forward", tr("Beat Jump / Loop Move Forward Selected Beats"), tr("Jump forward by the selected number of beats, or if a loop is enabled, move the loop forward by the selected number of beats"), beatJumpMenu);
535 addDeckControl("beatjump_backward", tr("Beat Jump / Loop Move Backward Selected Beats"), tr("Jump backward by the selected number of beats, or if a loop is enabled, move the loop backward by the selected number of beats"), beatJumpMenu);
536 beatJumpMenu->addSeparator();
537
538 QMenu* beatjumpFwdSubmenu = addSubmenu(tr("Beat Jump / Loop Move Forward"), beatJumpMenu);
539 foreach (double beats, beatSizes) {
540 QString humanBeats = humanBeatSizes.value(beats, QString::number(beats));
541 addDeckControl(QString("beatjump_%1_forward").arg(beats),
542 beatJumpForwardTitle.arg(humanBeats),
543 beatJumpForwardDescription.arg(humanBeats),
544 beatjumpFwdSubmenu);
545 }
546
547 QMenu* beatjumpBwdSubmenu = addSubmenu(tr("Beat Jump / Loop Move Backward"), beatJumpMenu);
548 foreach (double beats, beatSizes) {
549 QString humanBeats = humanBeatSizes.value(beats, QString::number(beats));
550 addDeckControl(QString("beatjump_%1_backward").arg(beats),
551 beatJumpBackwardTitle.arg(humanBeats),
552 beatJumpBackwardDescription.arg(humanBeats),
553 beatjumpBwdSubmenu);
554 }
555
556 // Loop moving
557 QString loopMoveForwardTitle = tr("Move Loop +%1 Beats");
558 QString loopMoveBackwardTitle = tr("Move Loop -%1 Beats");
559 QString loopMoveForwardDescription = tr("Move loop forward by %1 beats");
560 QString loopMoveBackwardDescription = tr("Move loop backward by %1 beats");
561
562 QMenu* loopmoveFwdSubmenu = addSubmenu(tr("Loop Move Forward"), beatJumpMenu);
563 foreach (double beats, beatSizes) {
564 QString humanBeats = humanBeatSizes.value(beats, QString::number(beats));
565 addDeckControl(QString("loop_move_%1_forward").arg(beats),
566 loopMoveForwardTitle.arg(humanBeats),
567 loopMoveForwardDescription.arg(humanBeats),
568 loopmoveFwdSubmenu);
569 }
570
571 QMenu* loopmoveBwdSubmenu = addSubmenu(tr("Loop Move Backward"), beatJumpMenu);
572 foreach (double beats, beatSizes) {
573 QString humanBeats = humanBeatSizes.value(beats, QString::number(beats));
574 addDeckControl(QString("loop_move_%1_backward").arg(beats),
575 loopMoveBackwardTitle.arg(humanBeats),
576 loopMoveBackwardDescription.arg(humanBeats),
577 loopmoveBwdSubmenu);
578 }
579
580 addSeparator();
581
582 // Library Controls
583 QMenu* libraryMenu = addSubmenu(tr("Library"));
584 QMenu* navigationMenu = addSubmenu(tr("Navigation"), libraryMenu);
585 addControl("[Library]",
586 "MoveUp",
587 tr("Move up"),
588 tr("Equivalent to pressing the UP key on the keyboard"),
589 navigationMenu,
590 false,
591 m_libraryStr);
592 addControl("[Library]",
593 "MoveDown",
594 tr("Move down"),
595 tr("Equivalent to pressing the DOWN key on the keyboard"),
596 navigationMenu,
597 false,
598 m_libraryStr);
599 addControl("[Library]",
600 "MoveVertical",
601 tr("Move up/down"),
602 tr("Move vertically in either direction using a knob, as if "
603 "pressing UP/DOWN keys"),
604 navigationMenu,
605 false,
606 m_libraryStr);
607 addControl("[Library]",
608 "ScrollUp",
609 tr("Scroll Up"),
610 tr("Equivalent to pressing the PAGE UP key on the keyboard"),
611 navigationMenu,
612 false,
613 m_libraryStr);
614 addControl("[Library]",
615 "ScrollDown",
616 tr("Scroll Down"),
617 tr("Equivalent to pressing the PAGE DOWN key on the keyboard"),
618 navigationMenu,
619 false,
620 m_libraryStr);
621 addControl("[Library]",
622 "ScrollVertical",
623 tr("Scroll up/down"),
624 tr("Scroll vertically in either direction using a knob, as if "
625 "pressing PGUP/PGDOWN keys"),
626 navigationMenu,
627 false,
628 m_libraryStr);
629 addControl("[Library]",
630 "MoveLeft",
631 tr("Move left"),
632 tr("Equivalent to pressing the LEFT key on the keyboard"),
633 navigationMenu,
634 false,
635 m_libraryStr);
636 addControl("[Library]",
637 "MoveRight",
638 tr("Move right"),
639 tr("Equivalent to pressing the RIGHT key on the keyboard"),
640 navigationMenu,
641 false,
642 m_libraryStr);
643 addControl("[Library]",
644 "MoveHorizontal",
645 tr("Move left/right"),
646 tr("Move horizontally in either direction using a knob, as if "
647 "pressing LEFT/RIGHT keys"),
648 navigationMenu,
649 false,
650 m_libraryStr);
651 navigationMenu->addSeparator();
652 addControl("[Library]",
653 "MoveFocusForward",
654 tr("Move focus to right pane"),
655 tr("Equivalent to pressing the TAB key on the keyboard"),
656 navigationMenu,
657 false,
658 m_libraryStr);
659 addControl("[Library]",
660 "MoveFocusBackward",
661 tr("Move focus to left pane"),
662 tr("Equivalent to pressing the SHIFT+TAB key on the keyboard"),
663 navigationMenu,
664 false,
665 m_libraryStr);
666 addControl("[Library]",
667 "MoveFocus",
668 tr("Move focus to right/left pane"),
669 tr("Move focus one pane to right or left using a knob, as if "
670 "pressing TAB/SHIFT+TAB keys"),
671 navigationMenu,
672 false,
673 m_libraryStr);
674 libraryMenu->addSeparator();
675 addControl("[Library]", "GoToItem",
676 tr("Go to the currently selected item"),
677 tr("Choose the currently selected item and advance forward one pane if appropriate"),
678 libraryMenu, false, m_libraryStr);
679 // Load track (these can be loaded into any channel)
680 addDeckAndSamplerControl("LoadSelectedTrack",
681 tr("Load Track"),
682 tr("Load selected track"),
683 libraryMenu);
684 addDeckAndSamplerAndPreviewDeckControl("LoadSelectedTrackAndPlay",
685 tr("Load Track and Play"),
686 tr("Load selected track and play"),
687 libraryMenu);
688 libraryMenu->addSeparator();
689 // Auto DJ
690 addControl("[Library]", "AutoDjAddBottom",
691 tr("Add to Auto DJ Queue (bottom)"),
692 tr("Append the selected track to the Auto DJ Queue"),
693 libraryMenu, false, m_libraryStr);
694 addControl("[Library]", "AutoDjAddTop",
695 tr("Add to Auto DJ Queue (top)"),
696 tr("Prepend selected track to the Auto DJ Queue"),
697 libraryMenu, false, m_libraryStr);
698 addControl("[Library]", "AutoDjAddReplace",
699 tr("Add to Auto DJ Queue (replace)"),
700 tr("Replace Auto DJ Queue with selected tracks"),
701 libraryMenu, false, m_libraryStr);
702 libraryMenu->addSeparator();
703 addControl("[Recording]", "toggle_recording",
704 tr("Record Mix"),
705 tr("Toggle mix recording"),
706 libraryMenu, false, m_libraryStr);
707
708 // Effect Controls
709 QMenu* effectsMenu = addSubmenu(tr("Effects"));
710
711 // Quick Effect Rack COs
712 QMenu* quickEffectMenu = addSubmenu(tr("Quick Effects"), effectsMenu);
713 for (int i = 1; i <= iNumDecks; ++i) {
714 addControl(QString("[QuickEffectRack1_[Channel%1]]").arg(i), "super1",
715 tr("Deck %1 Quick Effect Super Knob").arg(i),
716 tr("Quick Effect Super Knob (control linked effect parameters)"),
717 quickEffectMenu, false, tr("Quick Effect"));
718 addControl(QString("[QuickEffectRack1_[Channel%1]_Effect1]").arg(i), "enabled",
719 tr("Deck %1 Quick Effect Enable Button").arg(i),
720 tr("Quick Effect Enable Button"),
721 quickEffectMenu, false, tr("Quick Effect"));
722 }
723
724 effectsMenu->addSeparator();
725
726 // When kNumEffectRacks is changed to >1 put effect unit actions into
727 // separate "Effect Rack N" submenus.
728 const int kNumEffectRacks = 1;
729 for (int iRackNumber = 1; iRackNumber <= kNumEffectRacks; ++iRackNumber) {
730 const QString rackGroup = StandardEffectRack::formatGroupString(
731 iRackNumber - 1);
732 QString descriptionPrefix = m_effectRackStr.arg(iRackNumber);
733
734 const int numEffectUnits = static_cast<int>(ControlObject::get(
735 ConfigKey(rackGroup, "num_effectunits")));
736 for (int iEffectUnitNumber = 1; iEffectUnitNumber <= numEffectUnits;
737 ++iEffectUnitNumber) {
738 const QString effectUnitGroup =
739 StandardEffectRack::formatEffectChainSlotGroupString(
740 iRackNumber - 1, iEffectUnitNumber - 1);
741
742 descriptionPrefix = QString("%1").arg(m_effectUnitStr.arg(iEffectUnitNumber));
743
744 QMenu* effectUnitMenu = addSubmenu(m_effectUnitStr.arg(iEffectUnitNumber),
745 effectsMenu);
746 addControl(effectUnitGroup, "clear",
747 tr("Clear Unit"),
748 tr("Clear effect unit"),
749 effectUnitMenu, false, descriptionPrefix);
750 addControl(effectUnitGroup, "enabled",
751 tr("Toggle Unit"),
752 tr("Enable or disable effect processing"),
753 effectUnitMenu, false, descriptionPrefix);
754 addControl(effectUnitGroup, "mix",
755 tr("Dry/Wet"),
756 tr("Adjust the balance between the original (dry) and processed (wet) signal."),
757 effectUnitMenu, true, descriptionPrefix);
758 addControl(effectUnitGroup, "super1",
759 tr("Super Knob"),
760 tr("Super Knob (control effects' Meta Knobs)"),
761 effectUnitMenu, true, descriptionPrefix);
762 addControl(effectUnitGroup,
763 "mix_mode",
764 tr("Mix Mode Toggle"),
765 tr("Toggle effect unit between D/W and D+W modes"),
766 effectUnitMenu,
767 false,
768 descriptionPrefix);
769 addControl(effectUnitGroup, "next_chain",
770 tr("Next Chain"),
771 tr("Next chain preset"),
772 effectUnitMenu, false, descriptionPrefix);
773 addControl(effectUnitGroup, "prev_chain",
774 tr("Previous Chain"),
775 tr("Previous chain preset"),
776 effectUnitMenu, false, descriptionPrefix);
777 addControl(effectUnitGroup, "chain_selector",
778 tr("Next/Previous Chain"),
779 tr("Next or previous chain preset"),
780 effectUnitMenu, false, descriptionPrefix);
781 addControl(effectUnitGroup, "show_parameters",
782 tr("Show Effect Parameters"),
783 tr("Show Effect Parameters"),
784 effectUnitMenu, false, descriptionPrefix);
785
786 QString assignMenuTitle = tr("Effect Unit Assignment");
787 QString assignString = tr("Assign ");
788 QMenu* effectUnitGroups = addSubmenu(assignMenuTitle,
789 effectUnitMenu);
790
791 QString groupDescriptionPrefix = QString("%1").arg(
792 m_effectUnitStr.arg(iEffectUnitNumber));
793
794 addControl(effectUnitGroup, "group_[Master]_enable",
795 assignString + m_effectMasterOutputStr, // in ComboBox
796 assignString + m_effectMasterOutputStr, // description below
797 effectUnitGroups,
798 false,
799 groupDescriptionPrefix);
800 addControl(effectUnitGroup,
801 "group_[Headphone]_enable",
802 assignString + m_effectHeadphoneOutputStr,
803 assignString + m_effectHeadphoneOutputStr,
804 effectUnitGroups,
805 false,
806 groupDescriptionPrefix);
807
808 for (int iDeckNumber = 1; iDeckNumber <= iNumDecks; ++iDeckNumber) {
809 // PlayerManager::groupForDeck is 0-indexed.
810 QString playerGroup = PlayerManager::groupForDeck(iDeckNumber - 1);
811 // TODO(owen): Fix bad i18n here.
812 addControl(effectUnitGroup,
813 QString("group_%1_enable").arg(playerGroup),
814 assignString + m_deckStr.arg(iDeckNumber),
815 assignString + m_deckStr.arg(iDeckNumber),
816 effectUnitGroups,
817 false,
818 groupDescriptionPrefix);
819 }
820
821 const int iNumSamplers = static_cast<int>(ControlObject::get(
822 ConfigKey("[Master]", "num_samplers")));
823 for (int iSamplerNumber = 1; iSamplerNumber <= iNumSamplers;
824 ++iSamplerNumber) {
825 // PlayerManager::groupForSampler is 0-indexed.
826 QString playerGroup = PlayerManager::groupForSampler(iSamplerNumber - 1);
827 // TODO(owen): Fix bad i18n here.
828 addControl(effectUnitGroup,
829 QString("group_%1_enable").arg(playerGroup),
830 assignString + m_samplerStr.arg(iSamplerNumber),
831 assignString + m_samplerStr.arg(iSamplerNumber),
832 effectUnitGroups,
833 false,
834 groupDescriptionPrefix);
835 }
836
837 const int iNumMicrophones = static_cast<int>(ControlObject::get(
838 ConfigKey("[Master]", "num_microphones")));
839 for (int iMicrophoneNumber = 1; iMicrophoneNumber <= iNumMicrophones;
840 ++iMicrophoneNumber) {
841 QString micGroup = PlayerManager::groupForMicrophone(iMicrophoneNumber - 1);
842 // TODO(owen): Fix bad i18n here.
843 addControl(effectUnitGroup,
844 QString("group_%1_enable").arg(micGroup),
845 assignString + m_microphoneStr.arg(iMicrophoneNumber),
846 assignString + m_microphoneStr.arg(iMicrophoneNumber),
847 effectUnitGroups,
848 false,
849 groupDescriptionPrefix);
850 }
851
852 const int iNumAuxiliaries = static_cast<int>(ControlObject::get(
853 ConfigKey("[Master]", "num_auxiliaries")));
854 for (int iAuxiliaryNumber = 1; iAuxiliaryNumber <= iNumAuxiliaries;
855 ++iAuxiliaryNumber) {
856 QString auxGroup = PlayerManager::groupForAuxiliary(iAuxiliaryNumber - 1);
857 // TODO(owen): Fix bad i18n here.
858 addControl(effectUnitGroup,
859 QString("group_%1_enable").arg(auxGroup),
860 assignString + m_auxStr.arg(iAuxiliaryNumber),
861 assignString + m_auxStr.arg(iAuxiliaryNumber),
862 effectUnitGroups,
863 false,
864 groupDescriptionPrefix);
865 }
866
867 const int numEffectSlots = static_cast<int>(ControlObject::get(
868 ConfigKey(effectUnitGroup, "num_effectslots")));
869 for (int iEffectSlotNumber = 1; iEffectSlotNumber <= numEffectSlots;
870 ++iEffectSlotNumber) {
871 const QString effectSlotGroup =
872 StandardEffectRack::formatEffectSlotGroupString(
873 iRackNumber - 1, iEffectUnitNumber - 1,
874 iEffectSlotNumber - 1);
875
876 QMenu* effectSlotMenu = addSubmenu(m_effectStr.arg(iEffectSlotNumber),
877 effectUnitMenu);
878
879 QString slotDescriptionPrefix =
880 QString("%1, %2").arg(descriptionPrefix,
881 m_effectStr.arg(iEffectSlotNumber));
882
883 addControl(effectSlotGroup, "clear",
884 tr("Clear"), tr("Clear the current effect"),
885 effectSlotMenu, false, slotDescriptionPrefix);
886 addControl(effectSlotGroup, "meta",
887 tr("Meta Knob"), tr("Effect Meta Knob (control linked effect parameters)"),
888 effectSlotMenu, false, slotDescriptionPrefix);
889 addControl(effectSlotGroup, "enabled",
890 tr("Toggle"), tr("Toggle the current effect"),
891 effectSlotMenu, false, slotDescriptionPrefix);
892 addControl(effectSlotGroup, "next_effect",
893 tr("Next"), tr("Switch to next effect"),
894 effectSlotMenu, false, slotDescriptionPrefix);
895 addControl(effectSlotGroup, "prev_effect",
896 tr("Previous"), tr("Switch to the previous effect"),
897 effectSlotMenu, false, slotDescriptionPrefix);
898 addControl(effectSlotGroup, "effect_selector",
899 tr("Next or Previous"),
900 tr("Switch to either next or previous effect"),
901 effectSlotMenu, false, slotDescriptionPrefix);
902
903 // Effect parameter knobs
904 const int numParameterSlots = static_cast<int>(ControlObject::get(
905 ConfigKey(effectSlotGroup, "num_parameterslots")));
906 for (int iParameterSlotNumber = 1; iParameterSlotNumber <= numParameterSlots;
907 ++iParameterSlotNumber) {
908 // The parameter slot group is the same as the effect slot
909 // group on a standard effect rack.
910 const QString parameterSlotGroup =
911 StandardEffectRack::formatEffectSlotGroupString(
912 iRackNumber - 1, iEffectUnitNumber - 1,
913 iEffectSlotNumber - 1);
914 const QString parameterSlotItemPrefix = EffectParameterSlot::formatItemPrefix(
915 iParameterSlotNumber - 1);
916 QMenu* parameterSlotMenu = addSubmenu(
917 m_parameterStr.arg(iParameterSlotNumber),
918 effectSlotMenu);
919
920 QString parameterDescriptionPrefix =
921 QString("%1, %2").arg(slotDescriptionPrefix,
922 m_parameterStr.arg(iParameterSlotNumber));
923
924 // Likely to change soon.
925 addControl(parameterSlotGroup, parameterSlotItemPrefix,
926 tr("Parameter Value"),
927 tr("Parameter Value"),
928 parameterSlotMenu, true,
929 parameterDescriptionPrefix);
930 addControl(parameterSlotGroup, parameterSlotItemPrefix + "_link_type",
931 tr("Meta Knob Mode"),
932 tr("Set how linked effect parameters change when turning the Meta Knob."),
933 parameterSlotMenu, false,
934 parameterDescriptionPrefix);
935 addControl(parameterSlotGroup, parameterSlotItemPrefix + "_link_inverse",
936 tr("Meta Knob Mode Invert"),
937 tr("Invert how linked effect parameters change when turning the Meta Knob."),
938 parameterSlotMenu, false,
939 parameterDescriptionPrefix);
940 }
941
942 // Effect parameter buttons
943 const int numButtonParameterSlots = static_cast<int>(ControlObject::get(
944 ConfigKey(effectSlotGroup, "num_button_parameterslots")));
945 for (int iParameterSlotNumber = 1; iParameterSlotNumber <= numButtonParameterSlots;
946 ++iParameterSlotNumber) {
947 // The parameter slot group is the same as the effect slot
948 // group on a standard effect rack.
949 const QString parameterSlotGroup =
950 StandardEffectRack::formatEffectSlotGroupString(
951 iRackNumber - 1, iEffectUnitNumber - 1, iEffectSlotNumber - 1);
952 const QString parameterSlotItemPrefix =
953 EffectButtonParameterSlot::formatItemPrefix(
954 iParameterSlotNumber - 1);
955 QMenu* parameterSlotMenu = addSubmenu(
956 m_parameterStr.arg(iParameterSlotNumber),
957 effectSlotMenu);
958
959 QString parameterDescriptionPrefix =
960 QString("%1, %2").arg(slotDescriptionPrefix,
961 m_parameterStr.arg(iParameterSlotNumber));
962
963 // Likely to change soon.
964 addControl(parameterSlotGroup,
965 parameterSlotItemPrefix,
966 tr("Button Parameter Value"),
967 tr("Button Parameter Value"),
968 parameterSlotMenu,
969 true,
970 parameterDescriptionPrefix);
971 }
972 }
973 }
974 // Clear Effect Rack
975 addControl(rackGroup,
976 "clear",
977 tr("Clear Effect Rack"),
978 tr("Clear effect rack"),
979 effectsMenu,
980 false,
981 descriptionPrefix);
982 }
983
984 // Microphone Controls
985 QMenu* microphoneMenu = addSubmenu(tr("Microphone / Auxiliary"));
986
987 addMicrophoneAndAuxControl("talkover",
988 tr("Microphone On/Off"),
989 tr("Microphone on/off"), microphoneMenu,
990 true, false);
991 addControl("[Master]", "duckStrength",
992 tr("Microphone Ducking Strength"),
993 tr("Microphone Ducking Strength"),
994 microphoneMenu, true);
995 addControl("[Master]", "talkoverDucking",
996 tr("Microphone Ducking Mode"),
997 tr("Toggle microphone ducking mode (OFF, AUTO, MANUAL)"),
998 microphoneMenu);
999 addMicrophoneAndAuxControl("passthrough",
1000 tr("Auxiliary On/Off"),
1001 tr("Auxiliary on/off"),
1002 microphoneMenu,
1003 false, true);
1004 microphoneMenu->addSeparator();
1005 addMicrophoneAndAuxControl("pregain",
1006 tr("Gain"),
1007 tr("Gain knob"), microphoneMenu,
1008 true, true, true);
1009 addMicrophoneAndAuxControl("volume",
1010 tr("Volume Fader"),
1011 tr("Volume Fader"), microphoneMenu,
1012 true, true, true);
1013 addMicrophoneAndAuxControl("volume_set_one",
1014 tr("Full Volume"),
1015 tr("Set to full volume"), microphoneMenu,
1016 true, true);
1017 addMicrophoneAndAuxControl("volume_set_zero",
1018 tr("Zero Volume"),
1019 tr("Set to zero volume"), microphoneMenu,
1020 true, true);
1021 addMicrophoneAndAuxControl("mute",
1022 tr("Mute"),
1023 tr("Mute button"), microphoneMenu,
1024 true, true);
1025 addMicrophoneAndAuxControl("pfl",
1026 tr("Headphone Listen"),
1027 tr("Headphone listen button"),
1028 microphoneMenu,
1029 true,
1030 true);
1031 microphoneMenu->addSeparator();
1032 addMicrophoneAndAuxControl("orientation",
1033 tr("Orientation"),
1034 tr("Mix orientation (e.g. left, right, center)"),
1035 microphoneMenu, true, true);
1036 addMicrophoneAndAuxControl("orientation_left",
1037 tr("Orient Left"),
1038 tr("Set mix orientation to left"),
1039 microphoneMenu,
1040 true, true);
1041 addMicrophoneAndAuxControl("orientation_center",
1042 tr("Orient Center"),
1043 tr("Set mix orientation to center"), microphoneMenu,
1044 true, true);
1045 addMicrophoneAndAuxControl("orientation_right",
1046 tr("Orient Right"),
1047 tr("Set mix orientation to right"), microphoneMenu,
1048 true, true);
1049
1050 // AutoDJ Controls
1051 QMenu* autodjMenu = addSubmenu(tr("Auto DJ"));
1052 addControl("[AutoDJ]", "shuffle_playlist",
1053 tr("Auto DJ Shuffle"),
1054 tr("Shuffle the content of the Auto DJ queue"), autodjMenu);
1055 addControl("[AutoDJ]", "skip_next",
1056 tr("Auto DJ Skip Next"),
1057 tr("Skip the next track in the Auto DJ queue"), autodjMenu);
1058 addControl("[AutoDJ]", "fade_now",
1059 tr("Auto DJ Fade To Next"),
1060 tr("Trigger the transition to the next track"), autodjMenu);
1061 addControl("[AutoDJ]", "enabled",
1062 tr("Auto DJ Toggle"),
1063 tr("Toggle Auto DJ On/Off"), autodjMenu);
1064
1065 // Skin Controls
1066 QMenu* guiMenu = addSubmenu(tr("User Interface"));
1067 addControl("[Samplers]",
1068 "show_samplers",
1069 tr("Samplers Show/Hide"),
1070 tr("Show/hide the sampler section"),
1071 guiMenu);
1072 addControl("[Microphone]",
1073 "show_microphone",
1074 tr("Microphone & Auxiliary Show/Hide"),
1075 tr("Show/hide the microphone & auxiliary section"),
1076 guiMenu);
1077 addControl("[PreviewDeck]",
1078 "show_previewdeck",
1079 tr("Preview Deck Show/Hide"),
1080 tr("Show/hide the preview deck"),
1081 guiMenu);
1082 addControl("[EffectRack1]",
1083 "show",
1084 tr("Effect Rack Show/Hide"),
1085 tr("Show/hide the effect rack"),
1086 guiMenu);
1087 addControl("[Skin]",
1088 "show_4effectunits",
1089 tr("4 Effect Units Show/Hide"),
1090 tr("Switches between showing 2 and 4 effect units"),
1091 guiMenu);
1092 addControl("[Master]",
1093 "show_mixer",
1094 tr("Mixer Show/Hide"),
1095 tr("Show or hide the mixer."),
1096 guiMenu);
1097 addControl("[Library]",
1098 "show_coverart",
1099 tr("Cover Art Show/Hide (Library)"),
1100 tr("Show/hide cover art in the library"),
1101 guiMenu);
1102 addControl("[Master]",
1103 "maximize_library",
1104 tr("Library Maximize/Restore"),
1105 tr("Maximize the track library to take up all the available screen "
1106 "space."),
1107 guiMenu);
1108
1109 guiMenu->addSeparator();
1110
1111 addControl("[Skin]",
1112 "show_4decks",
1113 tr("Toggle 4 Decks"),
1114 tr("Switches between showing 2 decks and 4 decks."),
1115 guiMenu);
1116 addControl("[Skin]",
1117 "show_coverart",
1118 tr("Cover Art Show/Hide (Decks)"),
1119 tr("Show/hide cover art in the main decks"),
1120 guiMenu);
1121 addControl(VINYL_PREF_KEY,
1122 "show_vinylcontrol",
1123 tr("Vinyl Control Show/Hide"),
1124 tr("Show/hide the vinyl control section"),
1125 guiMenu);
1126
1127 QString spinnyTitle = tr("Vinyl Spinner Show/Hide");
1128 QString spinnyDescription = tr("Show/hide spinning vinyl widget");
1129 QMenu* spinnyMenu = addSubmenu(spinnyTitle, guiMenu);
1130 guiMenu->addSeparator();
1131 addControl("[Skin]",
1132 "show_spinnies",
1133 tr("Vinyl Spinners Show/Hide (All Decks)"),
1134 tr("Show/Hide all spinnies"),
1135 spinnyMenu);
1136 // TODO(ronso0) Add hint that this currently only affects the Shade skin
1137 for (int i = 1; i <= iNumDecks; ++i) {
1138 addControl(QString("[Spinny%1]").arg(i),
1139 "show_spinny",
1140 QString("%1: %2").arg(m_deckStr.arg(i), spinnyTitle),
1141 QString("%1: %2").arg(m_deckStr.arg(i), spinnyDescription),
1142 spinnyMenu);
1143 }
1144
1145 guiMenu->addSeparator();
1146
1147 addControl("[Skin]",
1148 "show_waveforms",
1149 tr("Toggle Waveforms"),
1150 tr("Show/hide the scrolling waveforms."),
1151 guiMenu);
1152 addDeckControl("waveform_zoom", tr("Waveform Zoom"), tr("Waveform zoom"), guiMenu);
1153 addDeckControl("waveform_zoom_down", tr("Waveform Zoom In"), tr("Zoom waveform in"), guiMenu);
1154 addDeckControl("waveform_zoom_up", tr("Waveform Zoom Out"), tr("Zoom waveform out"), guiMenu);
1155
1156 guiMenu->addSeparator();
1157
1158 // Controls to change a deck's star rating
1159 addDeckAndPreviewDeckControl("stars_up", tr("Star Rating Up"),
1160 tr("Increase the track rating by one star"), guiMenu);
1161 addDeckAndPreviewDeckControl("stars_down", tr("Star Rating Down"),
1162 tr("Decrease the track rating by one star"), guiMenu);
1163
1164 // Misc. controls
1165 addControl("[Shoutcast]",
1166 "enabled",
1167 tr("Start/Stop Live Broadcasting"),
1168 tr("Stream your mix over the Internet."),
1169 guiMenu);
1170 addControl(RECORDING_PREF_KEY,
1171 "toggle_recording",
1172 tr("Record Mix"),
1173 tr("Start/stop recording your mix."),
1174 guiMenu);
1175 }
1176
~ControlPickerMenu()1177 ControlPickerMenu::~ControlPickerMenu() {
1178 }
1179
addSingleControl(const QString & group,const QString & control,const QString & title,const QString & description,QMenu * pMenu,const QString & prefix,const QString & actionTitle)1180 void ControlPickerMenu::addSingleControl(const QString& group,
1181 const QString& control,
1182 const QString& title,
1183 const QString& description,
1184 QMenu* pMenu,
1185 const QString& prefix,
1186 const QString& actionTitle) {
1187 int controlIndex;
1188
1189 if (prefix.isEmpty()) {
1190 controlIndex = addAvailableControl(ConfigKey(group, control), title, description);
1191 } else {
1192 QString prefixedTitle = QString("%1: %2").arg(prefix, title);
1193 QString prefixedDescription = QString("%1: %2").arg(prefix, description);
1194 controlIndex = addAvailableControl(ConfigKey(group, control), prefixedTitle, prefixedDescription);
1195 }
1196
1197 auto pAction = make_parented<QAction>(actionTitle.isEmpty() ? title : actionTitle, pMenu);
1198 connect(pAction, &QAction::triggered,
1199 this, [this, controlIndex] { controlChosen(controlIndex); });
1200 pMenu->addAction(pAction);
1201 }
1202
addControl(const QString & group,const QString & control,const QString & title,const QString & description,QMenu * pMenu,bool addReset,const QString & prefix)1203 void ControlPickerMenu::addControl(const QString& group,
1204 const QString& control,
1205 const QString& title,
1206 const QString& description,
1207 QMenu* pMenu,
1208 bool addReset,
1209 const QString& prefix) {
1210 addSingleControl(group, control, title, description, pMenu, prefix);
1211
1212 if (addReset) {
1213 QString resetTitle = QString("%1 (%2)").arg(title, m_resetStr);
1214 QString resetDescription = QString("%1 (%2)").arg(description, m_resetStr);
1215 QString resetControl = QString("%1_set_default").arg(control);
1216
1217 addSingleControl(group, resetControl, resetTitle, resetDescription, pMenu, prefix);
1218 }
1219 }
1220
addPlayerControl(const QString & control,const QString & controlTitle,const QString & controlDescription,QMenu * pMenu,bool deckControls,bool samplerControls,bool previewdeckControls,bool addReset)1221 void ControlPickerMenu::addPlayerControl(const QString& control,
1222 const QString& controlTitle,
1223 const QString& controlDescription,
1224 QMenu* pMenu,
1225 bool deckControls,
1226 bool samplerControls,
1227 bool previewdeckControls,
1228 bool addReset) {
1229 const int iNumSamplers = static_cast<int>(
1230 ControlObject::get(ConfigKey("[Master]", "num_samplers")));
1231 const int iNumDecks = static_cast<int>(ControlObject::get(ConfigKey("[Master]", "num_decks")));
1232 const int iNumPreviewDecks = static_cast<int>(
1233 ControlObject::get(ConfigKey("[Master]", "num_preview_decks")));
1234
1235 parented_ptr<QMenu> controlMenu = make_parented<QMenu>(controlTitle, pMenu);
1236 pMenu->addMenu(controlMenu);
1237
1238 parented_ptr<QMenu> resetControlMenu = nullptr;
1239 QString resetControl = QString("%1_set_default").arg(control);
1240 if (addReset) {
1241 QString resetMenuTitle = QString("%1 (%2)").arg(controlTitle, m_resetStr);
1242 resetControlMenu = make_parented<QMenu>(resetMenuTitle, pMenu);
1243 pMenu->addMenu(resetControlMenu);
1244 }
1245
1246 for (int i = 1; deckControls && i <= iNumDecks; ++i) {
1247 // PlayerManager::groupForDeck is 0-indexed.
1248 QString prefix = m_deckStr.arg(i);
1249 QString group = PlayerManager::groupForDeck(i - 1);
1250 addSingleControl(group, control, controlTitle, controlDescription,
1251 controlMenu, prefix, prefix);
1252
1253 if (resetControlMenu) {
1254 QString resetTitle = QString("%1 (%2)").arg(controlTitle, m_resetStr);
1255 QString resetDescription = QString("%1 (%2)").arg(controlDescription, m_resetStr);
1256 addSingleControl(group, resetControl, resetTitle, resetDescription,
1257 resetControlMenu, prefix, prefix);
1258 }
1259 }
1260
1261 for (int i = 1; previewdeckControls && i <= iNumPreviewDecks; ++i) {
1262 // PlayerManager::groupForPreviewDeck is 0-indexed.
1263 QString prefix;
1264 if (iNumPreviewDecks == 1) {
1265 prefix = m_previewdeckStr.arg("");
1266 } else {
1267 prefix = m_previewdeckStr.arg(i);
1268 }
1269 QString group = PlayerManager::groupForPreviewDeck(i - 1);
1270 addSingleControl(group, control, controlTitle, controlDescription,
1271 controlMenu, prefix, prefix);
1272
1273 if (resetControlMenu) {
1274 QString resetTitle = QString("%1 (%2)").arg(controlTitle, m_resetStr);
1275 QString resetDescription = QString("%1 (%2)").arg(controlDescription, m_resetStr);
1276 addSingleControl(group, resetControl, resetTitle, resetDescription,
1277 resetControlMenu, prefix, prefix);
1278 }
1279 }
1280
1281 if (samplerControls) {
1282 QMenu* samplerControlMenu = new QMenu(tr("Samplers"), controlMenu);
1283 controlMenu->addMenu(samplerControlMenu);
1284 QMenu* samplerResetControlMenu = nullptr;
1285 if (resetControlMenu) {
1286 samplerResetControlMenu = new QMenu(tr("Samplers"), resetControlMenu);
1287 resetControlMenu->addMenu(samplerResetControlMenu);
1288 }
1289 for (int i = 1; i <= iNumSamplers; ++i) {
1290 // PlayerManager::groupForSampler is 0-indexed.
1291 QString prefix = m_samplerStr.arg(i);
1292 QString group = PlayerManager::groupForSampler(i - 1);
1293 addSingleControl(group,
1294 control,
1295 controlTitle,
1296 controlDescription,
1297 samplerControlMenu,
1298 prefix,
1299 prefix);
1300
1301 if (resetControlMenu) {
1302 QString resetTitle = QString("%1 (%2)").arg(controlTitle, m_resetStr);
1303 QString resetDescription = QString("%1 (%2)").arg(controlDescription, m_resetStr);
1304 addSingleControl(group,
1305 resetControl,
1306 resetTitle,
1307 resetDescription,
1308 samplerResetControlMenu,
1309 prefix,
1310 prefix);
1311 }
1312 }
1313 }
1314 }
1315
addMicrophoneAndAuxControl(const QString & control,const QString & controlTitle,const QString & controlDescription,QMenu * pMenu,bool microphoneControls,bool auxControls,bool addReset)1316 void ControlPickerMenu::addMicrophoneAndAuxControl(const QString& control,
1317 const QString& controlTitle,
1318 const QString& controlDescription,
1319 QMenu* pMenu,
1320 bool microphoneControls,
1321 bool auxControls,
1322 bool addReset) {
1323 parented_ptr<QMenu> controlMenu = make_parented<QMenu>(controlTitle, pMenu);
1324 pMenu->addMenu(controlMenu);
1325
1326 parented_ptr<QMenu> resetControlMenu = nullptr;
1327 QString resetControl = QString("%1_set_default").arg(control);
1328 if (addReset) {
1329 QString resetHelpText = QString("%1 (%2)").arg(controlTitle, m_resetStr);
1330 resetControlMenu = make_parented<QMenu>(resetHelpText, pMenu);
1331 pMenu->addMenu(resetControlMenu);
1332 }
1333
1334 if (microphoneControls) {
1335 const int kNumMicrophones = static_cast<int>(
1336 ControlObject::get(ConfigKey("[Master]", "num_microphones")));
1337 for (int i = 1; i <= kNumMicrophones; ++i) {
1338 QString prefix = m_microphoneStr.arg(i);
1339 QString group = PlayerManager::groupForMicrophone(i - 1);
1340 addSingleControl(group, control, controlTitle, controlDescription,
1341 controlMenu, prefix, prefix);
1342
1343 if (resetControlMenu) {
1344 QString resetTitle = QString("%1 (%2)").arg(controlTitle, m_resetStr);
1345 QString resetDescription = QString("%1 (%2)").arg(controlDescription, m_resetStr);
1346 addSingleControl(group, resetControl, resetTitle, resetDescription,
1347 resetControlMenu, prefix, prefix);
1348 }
1349 }
1350 }
1351
1352 const int kNumAuxiliaries = static_cast<int>(
1353 ControlObject::get(ConfigKey("[Master]", "num_auxiliaries")));
1354 if (auxControls) {
1355 for (int i = 1; i <= kNumAuxiliaries; ++i) {
1356 QString prefix = m_auxStr.arg(i);
1357 QString group = PlayerManager::groupForAuxiliary(i - 1);
1358 addSingleControl(group, control, controlTitle, controlDescription,
1359 controlMenu, prefix, prefix);
1360
1361 if (resetControlMenu) {
1362 QString resetTitle = QString("%1 (%2)").arg(controlTitle, m_resetStr);
1363 QString resetDescription = QString("%1 (%2)").arg(controlDescription, m_resetStr);
1364 addSingleControl(group, resetControl, resetTitle, resetDescription,
1365 resetControlMenu, prefix, prefix);
1366 }
1367 }
1368 }
1369 }
1370
addDeckAndSamplerControl(const QString & control,const QString & title,const QString & controlDescription,QMenu * pMenu,bool addReset)1371 void ControlPickerMenu::addDeckAndSamplerControl(const QString& control,
1372 const QString& title,
1373 const QString& controlDescription,
1374 QMenu* pMenu,
1375 bool addReset) {
1376 addPlayerControl(control, title, controlDescription, pMenu, true, true, false, addReset);
1377 }
1378
addDeckAndPreviewDeckControl(const QString & control,const QString & title,const QString & controlDescription,QMenu * pMenu,bool addReset)1379 void ControlPickerMenu::addDeckAndPreviewDeckControl(const QString& control,
1380 const QString& title,
1381 const QString& controlDescription,
1382 QMenu* pMenu,
1383 bool addReset) {
1384 addPlayerControl(control, title, controlDescription, pMenu, true, false, true, addReset);
1385 }
1386
addDeckAndSamplerAndPreviewDeckControl(const QString & control,const QString & title,const QString & controlDescription,QMenu * pMenu,bool addReset)1387 void ControlPickerMenu::addDeckAndSamplerAndPreviewDeckControl(const QString& control,
1388 const QString& title,
1389 const QString& controlDescription,
1390 QMenu* pMenu,
1391 bool addReset) {
1392 addPlayerControl(control, title, controlDescription, pMenu, true, true, true, addReset);
1393 }
1394
addDeckControl(const QString & control,const QString & title,const QString & controlDescription,QMenu * pMenu,bool addReset)1395 void ControlPickerMenu::addDeckControl(const QString& control,
1396 const QString& title,
1397 const QString& controlDescription,
1398 QMenu* pMenu,
1399 bool addReset) {
1400 addPlayerControl(control, title, controlDescription, pMenu, true, false, false, addReset);
1401 }
1402
addSamplerControl(const QString & control,const QString & title,const QString & controlDescription,QMenu * pMenu,bool addReset)1403 void ControlPickerMenu::addSamplerControl(const QString& control,
1404 const QString& title,
1405 const QString& controlDescription,
1406 QMenu* pMenu,
1407 bool addReset) {
1408 addPlayerControl(control, title, controlDescription, pMenu, false, true, false, addReset);
1409 }
1410
addPreviewDeckControl(const QString & control,const QString & title,const QString & controlDescription,QMenu * pMenu,bool addReset)1411 void ControlPickerMenu::addPreviewDeckControl(const QString& control,
1412 const QString& title,
1413 const QString& controlDescription,
1414 QMenu* pMenu,
1415 bool addReset) {
1416 addPlayerControl(control, title, controlDescription, pMenu, false, false, true, addReset);
1417 }
1418
addSubmenu(QString title,QMenu * pParent)1419 QMenu* ControlPickerMenu::addSubmenu(QString title, QMenu* pParent) {
1420 if (pParent == nullptr) {
1421 pParent = this;
1422 }
1423 auto subMenu = make_parented<QMenu>(title, pParent);
1424 pParent->addMenu(subMenu);
1425 return subMenu;
1426 }
1427
controlChosen(int controlIndex)1428 void ControlPickerMenu::controlChosen(int controlIndex) {
1429 if (controlIndex < 0 || controlIndex >= m_controlsAvailable.size()) {
1430 return;
1431 }
1432 emit controlPicked(m_controlsAvailable[controlIndex]);
1433 }
1434
addAvailableControl(const ConfigKey & key,const QString & title,const QString & description)1435 int ControlPickerMenu::addAvailableControl(const ConfigKey& key,
1436 const QString& title,
1437 const QString& description) {
1438 m_controlsAvailable.append(key);
1439 m_descriptionsByKey.insert(key, description);
1440 m_titlesByKey.insert(key, title);
1441 // return the index of the control which will be connected to the index
1442 // of the respective action in the menu
1443 return m_controlsAvailable.size() - 1;
1444 }
1445
controlExists(const ConfigKey & key) const1446 bool ControlPickerMenu::controlExists(const ConfigKey& key) const {
1447 return m_titlesByKey.contains(key);
1448 }
1449
descriptionForConfigKey(const ConfigKey & key) const1450 QString ControlPickerMenu::descriptionForConfigKey(const ConfigKey& key) const {
1451 return m_descriptionsByKey.value(key, QString());
1452 }
1453
controlTitleForConfigKey(const ConfigKey & key) const1454 QString ControlPickerMenu::controlTitleForConfigKey(const ConfigKey& key) const {
1455 return m_titlesByKey.value(key, QString());
1456 }
1457