1 #pragma once
2
3 #include <QString>
4
5 class EngineChannel;
6
7 enum SyncMode {
8 SYNC_INVALID = -1,
9 SYNC_NONE = 0,
10 SYNC_FOLLOWER = 1,
11 // SYNC_MASTER_SOFT is a master that Mixxx has chosen automatically.
12 // depending on how decks stop and start, it may reassign soft master at will.
13 SYNC_MASTER_SOFT = 2,
14 // SYNC_MASTER_EXPLICIT represents an explicit request that the synacable be
15 // master. Mixxx will only remove a SYNC_MASTER_SOFT if the track is stopped or
16 // ejected.
17 SYNC_MASTER_EXPLICIT = 3,
18 SYNC_NUM_MODES
19 };
20
syncModeFromDouble(double value)21 inline SyncMode syncModeFromDouble(double value) {
22 // msvs does not allow to cast from double to an enum
23 SyncMode mode = static_cast<SyncMode>(int(value));
24 if (mode >= SYNC_NUM_MODES || mode < 0) {
25 return SYNC_NONE;
26 }
27 return mode;
28 }
29
toSynchronized(SyncMode mode)30 inline bool toSynchronized(SyncMode mode) {
31 return mode > SYNC_NONE;
32 }
33
isMaster(SyncMode mode)34 inline bool isMaster(SyncMode mode) {
35 return (mode == SYNC_MASTER_SOFT || mode == SYNC_MASTER_EXPLICIT);
36 }
37
38 /// Syncable is an abstract base class for any object that wants to participate
39 /// in Master Sync.
40 class Syncable {
41 public:
42 virtual ~Syncable() = default;
43 virtual const QString& getGroup() const = 0;
44 virtual EngineChannel* getChannel() const = 0;
45
46 // Notify a Syncable that their mode has changed. The Syncable must record
47 // this mode and return the latest mode in response to getMode().
48 virtual void setSyncMode(SyncMode mode) = 0;
49
50 // Notify a Syncable that it is now the only currently-playing syncable.
51 virtual void notifyOnlyPlayingSyncable() = 0;
52
53 // Notify a Syncable that they should sync phase.
54 virtual void requestSync() = 0;
55
56 // Must NEVER return a mode that was not set directly via
57 // notifySyncModeChanged.
58 virtual SyncMode getSyncMode() const = 0;
59
isSynchronized()60 inline bool isSynchronized() const {
61 return toSynchronized(getSyncMode());
62 }
63
64 // Only relevant for player Syncables.
65 virtual bool isPlaying() const = 0;
66 virtual bool isAudible() const = 0;
67
68 // Gets the current speed of the syncable in bpm (bpm * rate slider), doesn't
69 // include scratch or FF/REW values.
70 virtual double getBpm() const = 0;
71
72 // Gets the beat distance as a fraction from 0 to 1
73 virtual double getBeatDistance() const = 0;
74 // Gets the speed of the syncable if it was playing at 1.0 rate.
75 virtual double getBaseBpm() const = 0;
76
77 // The following functions are used to tell syncables about the state of the
78 // current Sync Master.
79 // Must never result in a call to
80 // SyncableListener::notifyBeatDistanceChanged or signal loops could occur.
81 virtual void setMasterBeatDistance(double beatDistance) = 0;
82
83 // Must never result in a call to SyncableListener::notifyBpmChanged or
84 // signal loops could occur.
85 virtual void setMasterBpm(double bpm) = 0;
86
87 // Combines the above three calls into one, since they are often set
88 // simultaneously. Avoids redundant recalculation that would occur by
89 // using the three calls separately.
90 virtual void setMasterParams(double beatDistance, double baseBpm, double bpm) = 0;
91
92 // Must never result in a call to
93 // SyncableListener::notifyInstantaneousBpmChanged or signal loops could
94 // occur.
95 virtual void setInstantaneousBpm(double bpm) = 0;
96 };
97
98 /// SyncableListener is an interface class used by EngineSync to receive
99 /// information about sync change requests.
100 class SyncableListener {
101 public:
102 virtual ~SyncableListener() = default;
103
104 // Used by Syncables to tell EngineSync it wants to be enabled in a
105 // specific mode. If the state change is accepted, EngineSync calls
106 // Syncable::notifySyncModeChanged.
107 virtual void requestSyncMode(Syncable* pSyncable, SyncMode mode) = 0;
108
109 // Used by Syncables to tell EngineSync it wants to be enabled in any mode
110 // (master/follower).
111 virtual void requestEnableSync(Syncable* pSyncable, bool enabled) = 0;
112
113 // A Syncable must never call notifyBpmChanged in response to a setMasterBpm()
114 // call.
115 virtual void notifyBpmChanged(Syncable* pSyncable, double bpm) = 0;
116 virtual void requestBpmUpdate(Syncable* pSyncable, double bpm) = 0;
117
118 // Syncables notify EngineSync directly about various events. EngineSync
119 // does not have a say in whether these succeed or not, they are simply
120 // notifications.
121 virtual void notifyInstantaneousBpmChanged(Syncable* pSyncable, double bpm) = 0;
122
123 // Notify Syncable that the Syncable's scratching state changed.
124 virtual void notifyScratching(Syncable* pSyncable, bool scratching) = 0;
125
126 // A Syncable must never call notifyBeatDistanceChanged in response to a
127 // setBeatDistance() call.
128 virtual void notifyBeatDistanceChanged(
129 Syncable* pSyncable, double beatDistance) = 0;
130
131 virtual void notifyPlayingAudible(Syncable* pSyncable, bool playingAudible) = 0;
132
133 virtual Syncable* getMasterSyncable() = 0;
134 };
135