1 #pragma once
2 
3 #include <QList>
4 #include <QMutex>
5 
6 #include "control/controlproxy.h"
7 #include "engine/controls/enginecontrol.h"
8 #include "preferences/colorpalettesettings.h"
9 #include "preferences/usersettings.h"
10 #include "track/cue.h"
11 #include "track/track_decl.h"
12 
13 #define NUM_HOT_CUES 37
14 
15 class ControlObject;
16 class ControlPushButton;
17 class ControlIndicator;
18 
19 enum class CueMode {
20     Mixxx,
21     Pioneer,
22     Denon,
23     Numark,
24     MixxxNoBlinking,
25     CueAndPlay
26 };
27 
28 enum class SeekOnLoadMode {
29     MainCue = 0,    // Use main cue point
30     Beginning = 1,  // Use 0:00.000
31     FirstSound = 2, // Skip leading silence
32     IntroStart = 3, // Use intro start cue point
33 };
34 
seekOnLoadModeFromDouble(double value)35 inline SeekOnLoadMode seekOnLoadModeFromDouble(double value) {
36     return static_cast<SeekOnLoadMode>(int(value));
37 }
38 
39 class HotcueControl : public QObject {
40     Q_OBJECT
41   public:
42     HotcueControl(const QString& group, int hotcueIndex);
43     ~HotcueControl() override;
44 
getHotcueIndex()45     int getHotcueIndex() const {
46         return m_hotcueIndex;
47     }
48 
getCue()49     CuePointer getCue() const {
50         return m_pCue;
51     }
52     double getPosition() const;
53     void setCue(const CuePointer& pCue);
54     void resetCue();
55     void setPosition(double position);
56     void setColor(mixxx::RgbColor::optional_t newColor);
57     mixxx::RgbColor::optional_t getColor() const;
58 
59     // Used for caching the preview state of this hotcue control.
isPreviewing()60     bool isPreviewing() const {
61         return m_bPreviewing;
62     }
setPreviewing(bool bPreviewing)63     void setPreviewing(bool bPreviewing) {
64         m_bPreviewing = bPreviewing;
65     }
getPreviewingPosition()66     double getPreviewingPosition() const {
67         return m_previewingPosition;
68     }
setPreviewingPosition(double position)69     void setPreviewingPosition(double position) {
70         m_previewingPosition = position;
71     }
72 
73   private slots:
74     void slotHotcueSet(double v);
75     void slotHotcueGoto(double v);
76     void slotHotcueGotoAndPlay(double v);
77     void slotHotcueGotoAndStop(double v);
78     void slotHotcueActivate(double v);
79     void slotHotcueActivatePreview(double v);
80     void slotHotcueClear(double v);
81     void slotHotcuePositionChanged(double newPosition);
82     void slotHotcueColorChangeRequest(double newColor);
83     void slotHotcueColorChanged(double newColor);
84 
85   signals:
86     void hotcueSet(HotcueControl* pHotcue, double v);
87     void hotcueGoto(HotcueControl* pHotcue, double v);
88     void hotcueGotoAndPlay(HotcueControl* pHotcue, double v);
89     void hotcueGotoAndStop(HotcueControl* pHotcue, double v);
90     void hotcueActivate(HotcueControl* pHotcue, double v);
91     void hotcueActivatePreview(HotcueControl* pHotcue, double v);
92     void hotcueClear(HotcueControl* pHotcue, double v);
93     void hotcuePositionChanged(HotcueControl* pHotcue, double newPosition);
94     void hotcueColorChanged(HotcueControl* pHotcue, double newColor);
95     void hotcuePlay(double v);
96 
97   private:
98     ConfigKey keyForControl(const QString& name);
99 
100     const QString m_group;
101     const int m_hotcueIndex;
102     CuePointer m_pCue;
103 
104     // Hotcue state controls
105     std::unique_ptr<ControlObject> m_hotcuePosition;
106     std::unique_ptr<ControlObject> m_hotcueEnabled;
107     std::unique_ptr<ControlObject> m_hotcueColor;
108     // Hotcue button controls
109     std::unique_ptr<ControlPushButton> m_hotcueSet;
110     std::unique_ptr<ControlPushButton> m_hotcueGoto;
111     std::unique_ptr<ControlPushButton> m_hotcueGotoAndPlay;
112     std::unique_ptr<ControlPushButton> m_hotcueGotoAndStop;
113     std::unique_ptr<ControlPushButton> m_hotcueActivate;
114     std::unique_ptr<ControlPushButton> m_hotcueActivatePreview;
115     std::unique_ptr<ControlPushButton> m_hotcueClear;
116 
117     bool m_bPreviewing;
118     double m_previewingPosition;
119 };
120 
121 class CueControl : public EngineControl {
122     Q_OBJECT
123   public:
124     CueControl(const QString& group,
125             UserSettingsPointer pConfig);
126     ~CueControl() override;
127 
128     void hintReader(HintVector* pHintList) override;
129     bool updateIndicatorsAndModifyPlay(bool newPlay, bool oldPlay, bool playPossible);
130     void updateIndicators();
131     bool isTrackAtIntroCue();
132     void resetIndicators();
133     bool isPlayingByPlayButton();
134     bool getPlayFlashingAtPause();
135     SeekOnLoadMode getSeekOnLoadPreference();
136     void trackLoaded(TrackPointer pNewTrack) override;
137     void trackBeatsUpdated(mixxx::BeatsPointer pBeats) override;
138 
139   private slots:
140     void quantizeChanged(double v);
141 
142     void cueUpdated();
143     void trackAnalyzed();
144     void trackCuesUpdated();
145     void hotcueSet(HotcueControl* pControl, double v);
146     void hotcueGoto(HotcueControl* pControl, double v);
147     void hotcueGotoAndPlay(HotcueControl* pControl, double v);
148     void hotcueGotoAndStop(HotcueControl* pControl, double v);
149     void hotcueActivate(HotcueControl* pControl, double v);
150     void hotcueActivatePreview(HotcueControl* pControl, double v);
151     void hotcueClear(HotcueControl* pControl, double v);
152     void hotcuePositionChanged(HotcueControl* pControl, double newPosition);
153 
154     void hotcueFocusColorNext(double v);
155     void hotcueFocusColorPrev(double v);
156 
157     void cueSet(double v);
158     void cueClear(double v);
159     void cueGoto(double v);
160     void cueGotoAndPlay(double v);
161     void cueGotoAndStop(double v);
162     void cuePreview(double v);
163     void cueCDJ(double v);
164     void cueDenon(double v);
165     void cuePlay(double v);
166     void cueDefault(double v);
167     void pause(double v);
168     void playStutter(double v);
169 
170     void introStartSet(double v);
171     void introStartClear(double v);
172     void introStartActivate(double v);
173     void introEndSet(double v);
174     void introEndClear(double v);
175     void introEndActivate(double v);
176     void outroStartSet(double v);
177     void outroStartClear(double v);
178     void outroStartActivate(double v);
179     void outroEndSet(double v);
180     void outroEndClear(double v);
181     void outroEndActivate(double v);
182 
183   private:
184     enum class TrackAt {
185         Cue,
186         End,
187         ElseWhere
188     };
189 
190     // These methods are not thread safe, only call them when the lock is held.
191     void createControls();
192     void attachCue(const CuePointer& pCue, HotcueControl* pControl);
193     void detachCue(HotcueControl* pControl);
194     void loadCuesFromTrack();
195     double quantizeCuePoint(double position);
196     double getQuantizedCurrentPosition();
197     TrackAt getTrackAt() const;
198     void seekOnLoad(double seekOnLoadPosition);
199     void setHotcueFocusIndex(int hotcueIndex);
200     int getHotcueFocusIndex() const;
201 
202     UserSettingsPointer m_pConfig;
203     ColorPaletteSettings m_colorPaletteSettings;
204     bool m_bPreviewing;
205     ControlObject* m_pPlay;
206     ControlObject* m_pStopButton;
207     int m_iCurrentlyPreviewingHotcues;
208     ControlObject* m_pQuantizeEnabled;
209     ControlObject* m_pClosestBeat;
210     bool m_bypassCueSetByPlay;
211     ControlValueAtomic<double> m_usedSeekOnLoadPosition;
212 
213     const int m_iNumHotCues;
214     QList<HotcueControl*> m_hotcueControls;
215 
216     ControlObject* m_pTrackSamples;
217     ControlObject* m_pCuePoint;
218     ControlObject* m_pCueMode;
219     ControlPushButton* m_pCueSet;
220     ControlPushButton* m_pCueClear;
221     ControlPushButton* m_pCueCDJ;
222     ControlPushButton* m_pCueDefault;
223     ControlPushButton* m_pPlayStutter;
224     ControlIndicator* m_pCueIndicator;
225     ControlIndicator* m_pPlayIndicator;
226     ControlObject* m_pPlayLatched;
227     ControlPushButton* m_pCueGoto;
228     ControlPushButton* m_pCueGotoAndPlay;
229     ControlPushButton* m_pCuePlay;
230     ControlPushButton* m_pCueGotoAndStop;
231     ControlPushButton* m_pCuePreview;
232 
233     ControlObject* m_pIntroStartPosition;
234     ControlObject* m_pIntroStartEnabled;
235     ControlPushButton* m_pIntroStartSet;
236     ControlPushButton* m_pIntroStartClear;
237     ControlPushButton* m_pIntroStartActivate;
238 
239     ControlObject* m_pIntroEndPosition;
240     ControlObject* m_pIntroEndEnabled;
241     ControlPushButton* m_pIntroEndSet;
242     ControlPushButton* m_pIntroEndClear;
243     ControlPushButton* m_pIntroEndActivate;
244 
245     ControlObject* m_pOutroStartPosition;
246     ControlObject* m_pOutroStartEnabled;
247     ControlPushButton* m_pOutroStartSet;
248     ControlPushButton* m_pOutroStartClear;
249     ControlPushButton* m_pOutroStartActivate;
250 
251     ControlObject* m_pOutroEndPosition;
252     ControlObject* m_pOutroEndEnabled;
253     ControlPushButton* m_pOutroEndSet;
254     ControlPushButton* m_pOutroEndClear;
255     ControlPushButton* m_pOutroEndActivate;
256 
257     ControlProxy* m_pVinylControlEnabled;
258     ControlProxy* m_pVinylControlMode;
259 
260     ControlObject* m_pHotcueFocus;
261     ControlObject* m_pHotcueFocusColorNext;
262     ControlObject* m_pHotcueFocusColorPrev;
263 
264     TrackPointer m_pLoadedTrack; // is written from an engine worker thread
265 
266     // Tells us which controls map to which hotcue
267     QMap<QObject*, int> m_controlMap;
268 
269 #if QT_VERSION >= QT_VERSION_CHECK(5, 14, 0)
270     QRecursiveMutex m_mutex;
271 #else
272     QMutex m_mutex;
273 #endif
274 };
275