1 #include "vinylcontrol/vinylcontrolmanager.h"
2
3 #include "control/controlobject.h"
4 #include "control/controlproxy.h"
5 #include "mixer/playermanager.h"
6 #include "moc_vinylcontrolmanager.cpp"
7 #include "soundio/soundmanager.h"
8 #include "util/compatibility.h"
9 #include "util/timer.h"
10 #include "vinylcontrol/defs_vinylcontrol.h"
11 #include "vinylcontrol/vinylcontrol.h"
12 #include "vinylcontrol/vinylcontrolprocessor.h"
13 #include "vinylcontrol/vinylcontrolxwax.h"
14
VinylControlManager(QObject * pParent,UserSettingsPointer pConfig,SoundManager * pSoundManager)15 VinylControlManager::VinylControlManager(QObject* pParent,
16 UserSettingsPointer pConfig,
17 SoundManager* pSoundManager)
18 : QObject(pParent),
19 m_pConfig(pConfig),
20 m_pProcessor(new VinylControlProcessor(this, pConfig)),
21 m_iTimerId(-1),
22 m_pNumDecks(nullptr),
23 m_iNumConfiguredDecks(0) {
24 // Register every possible VC input with SoundManager to route to the
25 // VinylControlProcessor.
26 for (int i = 0; i < kMaximumVinylControlInputs; ++i) {
27 pSoundManager->registerInput(
28 AudioInput(AudioInput::VINYLCONTROL, 0, 2, i), m_pProcessor);
29 }
30 }
31
~VinylControlManager()32 VinylControlManager::~VinylControlManager() {
33 delete m_pProcessor;
34
35 // save a bunch of stuff to config
36 // turn off vinyl control so it won't be enabled on load (this is redundant to mixxx.cpp)
37 for (int i = 0; i < m_iNumConfiguredDecks; ++i) {
38 QString group = PlayerManager::groupForDeck(i);
39 m_pConfig->setValue(ConfigKey(group, "vinylcontrol_enabled"), false);
40 m_pConfig->set(ConfigKey(VINYL_PREF_KEY, QString("cueing_ch%1").arg(i + 1)),
41 ConfigValue(static_cast<int>(ControlObject::get(
42 ConfigKey(group, "vinylcontrol_cueing")))));
43 m_pConfig->set(ConfigKey(VINYL_PREF_KEY, QString("mode_ch%1").arg(i + 1)),
44 ConfigValue(static_cast<int>(ControlObject::get(
45 ConfigKey(group, "vinylcontrol_mode")))));
46 }
47 }
48
init()49 void VinylControlManager::init() {
50 m_pNumDecks = new ControlProxy("[Master]", "num_decks", this);
51 m_pNumDecks->connectValueChanged(this, &VinylControlManager::slotNumDecksChanged);
52 slotNumDecksChanged(m_pNumDecks->get());
53 }
54
toggleVinylControl(int deck)55 void VinylControlManager::toggleVinylControl(int deck) {
56 if (deck < 0 || deck >= m_pVcEnabled.size()) {
57 return;
58 }
59
60 ControlProxy* pEnabled = m_pVcEnabled[deck];
61 pEnabled->set(!pEnabled->toBool());
62 }
63
slotNumDecksChanged(double dNumDecks)64 void VinylControlManager::slotNumDecksChanged(double dNumDecks) {
65 int num_decks = static_cast<int>(dNumDecks);
66
67 // Complain if we try to create more decks than we can handle.
68 if (num_decks > kMaxNumberOfDecks) {
69 qWarning() << "Number of decks increased to " << num_decks << ", but Mixxx only supports "
70 << kMaxNumberOfDecks << " vinyl inputs. Decks above the maximum will not have "
71 << " vinyl control";
72 num_decks = kMaxNumberOfDecks;
73 }
74
75 if (num_decks <= m_iNumConfiguredDecks) {
76 // TODO(owilliams): If we implement deck deletion, shrink the size of configured decks.
77 return;
78 }
79
80 for (int i = m_iNumConfiguredDecks; i < num_decks; ++i) {
81 QString group = PlayerManager::groupForDeck(i);
82 ControlProxy* pEnabled = new ControlProxy(group, "vinylcontrol_enabled", this);
83 m_pVcEnabled.push_back(pEnabled);
84 pEnabled->connectValueChanged(this, [this, i] { slotVinylControlEnabledChanged(i); });
85
86 // Default cueing should be off.
87 ControlObject::set(ConfigKey(group, "vinylcontrol_cueing"),
88 m_pConfig->getValue(
89 ConfigKey(VINYL_PREF_KEY, QString("cueing_ch%1").arg(i + 1)),
90 0.0));
91 // Default mode should be relative.
92 ControlObject::set(ConfigKey(group, "vinylcontrol_mode"),
93 m_pConfig->getValue(
94 ConfigKey(VINYL_PREF_KEY, QString("mode_ch%1").arg(i + 1)),
95 MIXXX_VCMODE_RELATIVE));
96 }
97 m_iNumConfiguredDecks = num_decks;
98 }
99
slotVinylControlEnabledChanged(int deck)100 void VinylControlManager::slotVinylControlEnabledChanged(int deck) {
101 if (deck < 0 || deck >= m_pVcEnabled.size()) {
102 DEBUG_ASSERT(false);
103 return;
104 }
105
106 ControlProxy* pEnabled = m_pVcEnabled.at(deck);
107 emit vinylControlDeckEnabled(deck, pEnabled->toBool());
108 }
109
requestReloadConfig()110 void VinylControlManager::requestReloadConfig() {
111 m_pProcessor->requestReloadConfig();
112 }
113
vinylInputConnected(int deck)114 bool VinylControlManager::vinylInputConnected(int deck) {
115 if (deck < 0 || deck >= m_iNumConfiguredDecks) {
116 return false;
117 }
118 if (deck < 0 || deck >= m_pVcEnabled.length()) {
119 qDebug() << "WARNING, tried to get vinyl enabled status for non-existent deck " << deck;
120 return false;
121 }
122 return m_pProcessor->deckConfigured(deck);
123 }
124
vinylInputFromGroup(const QString & group)125 int VinylControlManager::vinylInputFromGroup(const QString& group) {
126 QRegExp channelMatcher("\\[Channel([1-9]\\d*)\\]");
127 if (channelMatcher.exactMatch(group)) {
128 bool ok = false;
129 int input = channelMatcher.cap(1).toInt(&ok);
130 return ok ? input - 1 : -1;
131 }
132 return -1;
133 }
134
addSignalQualityListener(VinylSignalQualityListener * pListener)135 void VinylControlManager::addSignalQualityListener(VinylSignalQualityListener* pListener) {
136 m_listeners.insert(pListener);
137 m_pProcessor->setSignalQualityReporting(true);
138
139 if (m_iTimerId == -1) {
140 m_iTimerId = startTimer(MIXXX_VINYL_SCOPE_UPDATE_LATENCY_MS);
141 }
142 }
143
removeSignalQualityListener(VinylSignalQualityListener * pListener)144 void VinylControlManager::removeSignalQualityListener(VinylSignalQualityListener* pListener) {
145 m_listeners.remove(pListener);
146 if (m_listeners.empty()) {
147 m_pProcessor->setSignalQualityReporting(false);
148 if (m_iTimerId != -1) {
149 killTimer(m_iTimerId);
150 m_iTimerId = -1;
151 }
152 }
153 }
154
updateSignalQualityListeners()155 void VinylControlManager::updateSignalQualityListeners() {
156 FIFO<VinylSignalQualityReport>* signalQualityFifo = m_pProcessor->getSignalQualityFifo();
157 if (signalQualityFifo == nullptr) {
158 return;
159 }
160
161 VinylSignalQualityReport report;
162 while (signalQualityFifo->read(&report, 1) == 1) {
163 foreach (VinylSignalQualityListener* pListener, m_listeners) {
164 pListener->onVinylSignalQualityUpdate(report);
165 }
166 }
167 }
168
timerEvent(QTimerEvent *)169 void VinylControlManager::timerEvent(QTimerEvent*) {
170 updateSignalQualityListeners();
171 }
172