1 // playermanager.h
2 // Created 6/1/2010 by RJ Ryan (rryan@mit.edu)
3 
4 #ifndef MIXER_PLAYERMANAGER_H
5 #define MIXER_PLAYERMANAGER_H
6 
7 #include <QList>
8 #include <QMap>
9 #include <QMutex>
10 #include <QObject>
11 
12 #include "analyzer/trackanalysisscheduler.h"
13 #include "preferences/usersettings.h"
14 #include "track/track_decl.h"
15 #include "util/parented_ptr.h"
16 #include "util/performancetimer.h"
17 
18 class Auxiliary;
19 class BaseTrackPlayer;
20 class ControlObject;
21 class Deck;
22 class EffectsManager;
23 class EngineMaster;
24 class Library;
25 class Microphone;
26 class PreviewDeck;
27 class Sampler;
28 class SamplerBank;
29 class SoundManager;
30 class VisualsManager;
31 class ControlProxy;
32 
33 // For mocking PlayerManager.
34 class PlayerManagerInterface {
35   public:
36     virtual ~PlayerManagerInterface() = default;
37 
38     // Get a BaseTrackPlayer (i.e. a Deck or a Sampler) by its group
39     virtual BaseTrackPlayer* getPlayer(const QString& group) const = 0;
40 
41     // Get the deck by its deck number. Decks are numbered starting with 1.
42     virtual Deck* getDeck(unsigned int player) const = 0;
43 
44     // Returns the number of decks.
45     virtual unsigned int numberOfDecks() const = 0;
46 
47     // Get the preview deck by its deck number. Preview decks are numbered
48     // starting with 1.
49     virtual PreviewDeck* getPreviewDeck(unsigned int libPreviewPlayer) const = 0;
50 
51     // Returns the number of preview decks.
52     virtual unsigned int numberOfPreviewDecks() const = 0;
53 
54     // Get the sampler by its number. Samplers are numbered starting with 1.
55     virtual Sampler* getSampler(unsigned int sampler) const = 0;
56 
57     // Returns the number of sampler decks.
58     virtual unsigned int numberOfSamplers() const = 0;
59 };
60 
61 class PlayerManager : public QObject, public PlayerManagerInterface {
62     Q_OBJECT
63   public:
64     PlayerManager(UserSettingsPointer pConfig,
65                   SoundManager* pSoundManager,
66                   EffectsManager* pEffectsManager,
67                   VisualsManager* pVisualsManager,
68                   EngineMaster* pEngine);
69     ~PlayerManager() override;
70 
71     // Add a deck to the PlayerManager
72     // (currently unused, kept for consistency with other types)
73     void addDeck();
74 
75     // Add number of decks according to configuration.
76     void addConfiguredDecks();
77 
78     // Add a sampler to the PlayerManager
79     void addSampler();
80 
81     // Load samplers from samplers.xml file in config directory
82     void loadSamplers();
83 
84     // Add a PreviewDeck to the PlayerManager
85     void addPreviewDeck();
86 
87     // Add a microphone to the PlayerManager
88     void addMicrophone();
89 
90     // Add an auxiliary input to the PlayerManager
91     void addAuxiliary();
92 
93     // Return the number of players. Thread-safe.
94     static unsigned int numDecks();
95 
numberOfDecks()96     unsigned int numberOfDecks() const override {
97         return numDecks();
98     }
99 
100     // Returns true if the group is a deck group. If index is non-NULL,
101     // populates it with the deck number (1-indexed).
102     static bool isDeckGroup(const QString& group, int* number=NULL);
103 
104     // Returns true if the group is a sampler group. If index is non-NULL,
105     // populates it with the deck number (1-indexed).
106     static bool isSamplerGroup(const QString& group, int* number=nullptr);
107 
108     // Returns true if the group is a preview deck group. If index is non-NULL,
109     // populates it with the deck number (1-indexed).
110     static bool isPreviewDeckGroup(const QString& group, int* number=NULL);
111 
112     // Return the number of samplers. Thread-safe.
113     static unsigned int numSamplers();
114 
numberOfSamplers()115     unsigned int numberOfSamplers() const override {
116         return numSamplers();
117     }
118 
119     // Return the number of preview decks. Thread-safe.
120     static unsigned int numPreviewDecks();
121 
numberOfPreviewDecks()122     unsigned int numberOfPreviewDecks() const override {
123         return numPreviewDecks();
124     }
125 
126     // Get a BaseTrackPlayer (i.e. a Deck, Sampler or PreviewDeck) by its
127     // group. Auxiliaries and microphones are not players.
128     BaseTrackPlayer* getPlayer(const QString& group) const override;
129 
130     // Get the deck by its deck number. Decks are numbered starting with 1.
131     Deck* getDeck(unsigned int player) const override;
132 
133     PreviewDeck* getPreviewDeck(unsigned int libPreviewPlayer) const override;
134 
135     // Get the sampler by its number. Samplers are numbered starting with 1.
136     Sampler* getSampler(unsigned int sampler) const override;
137 
138     // Get the microphone by its number. Microphones are numbered starting with 1.
139     Microphone* getMicrophone(unsigned int microphone) const;
140 
141     // Get the auxiliary by its number. Auxiliaries are numbered starting with 1.
142     Auxiliary* getAuxiliary(unsigned int auxiliary) const;
143 
144     // Binds signals between PlayerManager and Library. The library
145     // must exist at least for the lifetime of this instance.
146     void bindToLibrary(Library* pLibrary);
147 
148     // Returns the group for the ith sampler where i is zero indexed
groupForSampler(int i)149     static QString groupForSampler(int i) {
150         DEBUG_ASSERT(i >= 0);
151         return QStringLiteral("[Sampler") + QString::number(i + 1) + ']';
152     }
153 
154     // Returns the group for the ith deck where i is zero indexed
groupForDeck(int i)155     static QString groupForDeck(int i) {
156         DEBUG_ASSERT(i >= 0);
157         return QStringLiteral("[Channel") + QString::number(i + 1) + ']';
158     }
159 
160     // Returns the group for the ith PreviewDeck where i is zero indexed
groupForPreviewDeck(int i)161     static QString groupForPreviewDeck(int i) {
162         DEBUG_ASSERT(i >= 0);
163         return QStringLiteral("[PreviewDeck") + QString::number(i + 1) + ']';
164     }
165 
166     // Returns the group for the ith Microphone where i is zero indexed
groupForMicrophone(int i)167     static QString groupForMicrophone(int i) {
168         DEBUG_ASSERT(i >= 0);
169         // Before Mixxx had multiple microphone support the first microphone had
170         // the group [Microphone]. For backwards compatibility we keep it that
171         // way.
172         if (i > 0) {
173             return QStringLiteral("[Microphone") + QString::number(i + 1) + ']';
174         } else {
175             return QStringLiteral("[Microphone]");
176         }
177     }
178 
179     // Returns the group for the ith Auxiliary where i is zero indexed
groupForAuxiliary(int i)180     static QString groupForAuxiliary(int i) {
181         DEBUG_ASSERT(i >= 0);
182         return QStringLiteral("[Auxiliary") + QString::number(i + 1) + ']';
183     }
184 
185     static QAtomicPointer<ControlProxy> m_pCOPNumDecks;
186     static QAtomicPointer<ControlProxy> m_pCOPNumSamplers;
187     static QAtomicPointer<ControlProxy> m_pCOPNumPreviewDecks;
188 
189   public slots:
190     // Slots for loading tracks into a Player, which is either a Sampler or a Deck
191     void slotLoadTrackToPlayer(TrackPointer pTrack, const QString& group, bool play = false);
192     void slotLoadToPlayer(const QString& location, const QString& group);
193     void slotCloneDeck(const QString& source_group, const QString& target_group);
194 
195     // Slots for loading tracks to decks
196     void slotLoadTrackIntoNextAvailableDeck(TrackPointer pTrack);
197     // Loads the location to the deck. deckNumber is 1-indexed
198     void slotLoadToDeck(const QString& location, int deckNumber);
199 
200     // Loads the location to the preview deck. previewDeckNumber is 1-indexed
201     void slotLoadToPreviewDeck(const QString& location, int previewDeckNumber);
202     // Slots for loading tracks to samplers
203     void slotLoadTrackIntoNextAvailableSampler(TrackPointer pTrack);
204     // Loads the location to the sampler. samplerNumber is 1-indexed
205     void slotLoadToSampler(const QString& location, int samplerNumber);
206 
207     void slotChangeNumDecks(double v);
208     void slotChangeNumSamplers(double v);
209     void slotChangeNumPreviewDecks(double v);
210     void slotChangeNumMicrophones(double v);
211     void slotChangeNumAuxiliaries(double v);
212 
213   private slots:
214     void slotAnalyzeTrack(TrackPointer track);
215 
216     void onTrackAnalysisProgress(TrackId trackId, AnalyzerProgress analyzerProgress);
217     void onTrackAnalysisFinished();
218 
219   signals:
220     void loadLocationToPlayer(const QString& location, const QString& group);
221 
222     // Emitted when the user tries to enable a microphone talkover control when
223     // there is no input configured.
224     void noMicrophoneInputConfigured();
225 
226     // Emitted when the user tries to enable an auxiliary master control when
227     // there is no input configured.
228     void noAuxiliaryInputConfigured();
229 
230     // Emitted when the user tries to enable deck passthrough when there is no
231     // input configured.
232     void noDeckPassthroughInputConfigured();
233 
234     // Emitted when the user tries to enable vinyl control when there is no
235     // input configured.
236     void noVinylControlInputConfigured();
237 
238     // Emitted when the number of decks changes.
239     void numberOfDecksChanged(int decks);
240 
241     void trackAnalyzerProgress(TrackId trackId, AnalyzerProgress analyzerProgress);
242     void trackAnalyzerIdle();
243 
244   private:
245     TrackPointer lookupTrack(QString location);
246     // Must hold m_mutex before calling this method. Internal method that
247     // creates a new deck.
248     void addDeckInner();
249     // Must hold m_mutex before calling this method. Internal method that
250     // creates a new sampler.
251     void addSamplerInner();
252     // Must hold m_mutex before calling this method. Internal method that
253     // creates a new preview deck.
254     void addPreviewDeckInner();
255     // Must hold m_mutex before calling this method. Internal method that
256     // creates a new microphone.
257     void addMicrophoneInner();
258     // Must hold m_mutex before calling this method. Internal method that
259     // creates a new auxiliary.
260     void addAuxiliaryInner();
261 
262     // Used to protect access to PlayerManager state across threads.
263 #if QT_VERSION >= QT_VERSION_CHECK(5, 14, 0)
264     mutable QRecursiveMutex m_mutex;
265 #else
266     mutable QMutex m_mutex;
267 #endif
268 
269     PerformanceTimer m_cloneTimer;
270     QString m_lastLoadedPlayer;
271 
272     UserSettingsPointer m_pConfig;
273     SoundManager* m_pSoundManager;
274     EffectsManager* m_pEffectsManager;
275     VisualsManager* m_pVisualsManager;
276     EngineMaster* m_pEngine;
277     SamplerBank* m_pSamplerBank;
278     ControlObject* m_pCONumDecks;
279     ControlObject* m_pCONumSamplers;
280     ControlObject* m_pCONumPreviewDecks;
281     ControlObject* m_pCONumMicrophones;
282     ControlObject* m_pCONumAuxiliaries;
283     parented_ptr<ControlProxy> m_pAutoDjEnabled;
284 
285     TrackAnalysisScheduler::Pointer m_pTrackAnalysisScheduler;
286 
287     QList<Deck*> m_decks;
288     QList<Sampler*> m_samplers;
289     QList<PreviewDeck*> m_preview_decks;
290     QList<Microphone*> m_microphones;
291     QList<Auxiliary*> m_auxiliaries;
292     QMap<QString, BaseTrackPlayer*> m_players;
293 };
294 
295 #endif // MIXER_PLAYERMANAGER_H
296