![]() |
Mixxx
|
00001 00007 #include "vinylcontrolmanager.h" 00008 #include "vinylcontrolproxy.h" 00009 #include "vinylcontrolxwax.h" 00010 #include "soundmanager.h" 00011 #include "controlpushbutton.h" 00012 00013 const int kNumberOfDecks = 4; // set to 4 because it will ideally not be more 00014 // or less than the number of vinyl-controlled decks but will probably be 00015 // forgotten in any 2->4 deck switchover. Only real consequence is 00016 // sizeof(void*)*2 bytes of wasted memory if we're only using 2 decks -bkgood 00017 00018 const QString kVCProxyGroup = QString("[Channel%1]"); 00019 00020 VinylControlManager::VinylControlManager(QObject *pParent, 00021 ConfigObject<ConfigValue> *pConfig) 00022 : QObject(pParent) 00023 , m_pConfig(pConfig) 00024 , m_proxies(kNumberOfDecks, NULL) 00025 , m_pToggle(new ControlPushButton(ConfigKey("[VinylControl]", "Toggle"))) 00026 { 00027 // load a bunch of stuff 00028 ControlObject::getControl(ConfigKey("[Channel1]","vinylcontrol_enabled")) 00029 ->queueFromThread(0); 00030 ControlObject::getControl(ConfigKey("[Channel2]","vinylcontrol_enabled")) 00031 ->queueFromThread(0); 00032 ControlObject::getControl(ConfigKey("[Channel1]","vinylcontrol_mode")) 00033 ->queueFromThread(m_pConfig->getValueString( 00034 ConfigKey("[VinylControl]","mode")).toDouble()); 00035 ControlObject::getControl(ConfigKey("[Channel2]","vinylcontrol_mode")) 00036 ->queueFromThread(m_pConfig->getValueString( 00037 ConfigKey("[VinylControl]","mode")).toDouble()); 00038 ControlObject::getControl(ConfigKey("[Channel1]","vinylcontrol_cueing")) 00039 ->queueFromThread(m_pConfig->getValueString( 00040 ConfigKey("[VinylControl]","cueing_ch1")).toDouble()); 00041 ControlObject::getControl(ConfigKey("[Channel2]","vinylcontrol_cueing")) 00042 ->queueFromThread(m_pConfig->getValueString( 00043 ConfigKey("[VinylControl]","cueing_ch2")).toDouble()); 00044 connect(m_pToggle, SIGNAL(valueChanged(double)), SLOT(toggleDeck(double))); 00045 } 00046 00047 VinylControlManager::~VinylControlManager() { 00048 m_proxiesLock.lockForWrite(); 00049 for (int i = 0; i < m_proxies.size(); ++i) { 00050 if (m_proxies.at(i)) { 00051 delete m_proxies.at(i); 00052 m_proxies.replace(i, NULL); 00053 } 00054 } 00055 m_proxiesLock.unlock(); 00056 00057 // xwax has a global LUT that we need to free after we've shut down our 00058 // vinyl control threads because it's not thread-safe. 00059 VinylControlXwax::freeLUTs(); 00060 00061 // save a bunch of stuff to config 00062 // turn off vinyl control so it won't be enabled on load (this is redundant to mixxx.cpp) 00063 m_pConfig->set(ConfigKey("[Channel 1]","vinylcontrol_enabled"), false); 00064 m_pConfig->set(ConfigKey("[Channel 2]","vinylcontrol_enabled"), false); 00065 m_pConfig->set(ConfigKey("[VinylControl]","mode"), 00066 ConfigValue((int)ControlObject::getControl( 00067 ConfigKey("[Channel1]","vinylcontrol_mode"))->get())); 00068 m_pConfig->set(ConfigKey("[VinylControl]","mode"), 00069 ConfigValue((int)ControlObject::getControl( 00070 ConfigKey("[Channel2]","vinylcontrol_mode"))->get())); 00071 m_pConfig->set(ConfigKey("[VinylControl]","cueing_ch1"), 00072 ConfigValue((int)ControlObject::getControl( 00073 ConfigKey("[Channel1]","vinylcontrol_cueing"))->get())); 00074 m_pConfig->set(ConfigKey("[VinylControl]","cueing_ch2"), 00075 ConfigValue((int)ControlObject::getControl( 00076 ConfigKey("[Channel2]","vinylcontrol_cueing"))->get())); 00077 delete m_pToggle; 00078 } 00079 00080 void VinylControlManager::receiveBuffer(AudioInput input, 00081 const short *pBuffer, unsigned int nFrames) { 00082 Q_ASSERT(input.getType() == AudioInput::VINYLCONTROL); 00083 if (m_proxiesLock.tryLockForRead()) { 00084 Q_ASSERT(input.getIndex() < m_proxies.size()); 00085 VinylControlProxy *pProxy(m_proxies.at(input.getIndex())); 00086 Q_ASSERT(pProxy); 00087 pProxy->AnalyseSamples(pBuffer, nFrames); 00088 m_proxiesLock.unlock(); 00089 } 00090 } 00091 00092 void VinylControlManager::onInputConnected(AudioInput input) { 00093 Q_ASSERT(input.getType() == AudioInput::VINYLCONTROL); 00094 unsigned char index = input.getIndex(); 00095 VinylControlProxy *pNewVC = new VinylControlProxy(m_pConfig, 00096 kVCProxyGroup.arg(index + 1)); 00097 m_proxiesLock.lockForWrite(); 00098 if (index < m_proxies.size()) { 00099 if (m_proxies.at(index)) { 00100 delete m_proxies.at(index); 00101 } 00102 m_proxies.replace(index, pNewVC); 00103 } else { 00104 m_proxies.resize(index + 1); 00105 m_proxies.replace(index, pNewVC); 00106 } 00107 m_proxiesLock.unlock(); 00108 } 00109 00110 void VinylControlManager::onInputDisconnected(AudioInput input) { 00111 Q_ASSERT(input.getType() == AudioInput::VINYLCONTROL); 00112 m_proxiesLock.lockForWrite(); 00113 Q_ASSERT(input.getIndex() < m_proxies.size()); 00114 Q_ASSERT(m_proxies.at(input.getIndex())); 00115 00116 delete m_proxies.at(input.getIndex()); 00117 m_proxies.replace(input.getIndex(), NULL); 00118 m_proxiesLock.unlock(); 00119 } 00120 00121 void VinylControlManager::reloadConfig() { 00122 m_proxiesLock.lockForWrite(); 00123 for (int i = 0; i < m_proxies.size(); ++i) { 00124 if (!m_proxies.at(i)) continue; 00125 VinylControlProxy *pProxy = m_proxies.at(i); 00126 QString group = kVCProxyGroup.arg(i + 1); 00127 delete pProxy; 00128 pProxy = new VinylControlProxy(m_pConfig, group); 00129 m_proxies.replace(i, pProxy); 00130 } 00131 m_proxiesLock.unlock(); 00132 } 00133 00134 QList<VinylControlProxy*> VinylControlManager::vinylControlProxies() { 00135 m_proxiesLock.lockForRead(); 00136 QList<VinylControlProxy*> list(m_proxies.toList()); 00137 m_proxiesLock.unlock(); 00138 return list; 00139 } 00140 00141 bool VinylControlManager::vinylInputEnabled(int deck) { 00142 // a vinylcontrolproxy is only created if vinyl control is enabled for 00143 // a deck, so... 00144 m_proxiesLock.lockForRead(); 00145 bool ret = (deck - 1) < m_proxies.size() && m_proxies[deck-1]; 00146 m_proxiesLock.unlock(); 00147 return ret; 00148 } 00149 00150 VinylControlProxy* VinylControlManager::getVinylControlProxyForChannel(QString channel) 00151 { 00152 // TODO: will need update for n-deck 00153 if (channel == "[Channel1]") 00154 { 00155 return m_proxies.at(0); 00156 } 00157 else if (channel == "[Channel2]") 00158 { 00159 return m_proxies.at(1); 00160 } 00161 00162 return NULL; 00163 } 00164 00165 void VinylControlManager::toggleDeck(double value) { 00166 if (!value) return; 00178 m_proxiesLock.lockForRead(); 00179 int enabled(-1); // -1 means we haven't found a proxy that's enabled 00180 for (int i = 0; i < m_proxies.size(); ++i) { 00181 if (m_proxies[i] && m_proxies[i]->isEnabled()) { 00182 if (enabled > -1) goto bail; // case 3 00183 enabled = i; 00184 } 00185 } 00186 if (enabled > -1 && m_proxies.size() > 1) { 00187 // handle case 2 00188 int nextProxy((enabled + 1) % m_proxies.size()); 00189 while (!m_proxies[nextProxy]) { 00190 nextProxy = (nextProxy + 1) % m_proxies.size(); 00191 } // guaranteed to terminate as there's at least 1 non-null proxy 00192 if (nextProxy == enabled) goto bail; 00193 m_proxies[enabled]->ToggleVinylControl(false); 00194 m_proxies[nextProxy]->ToggleVinylControl(true); 00195 } else if (enabled == -1) { 00196 // handle case 1, or we just don't have any proxies 00197 foreach (VinylControlProxy *proxy, m_proxies) { 00198 if (proxy) { 00199 proxy->ToggleVinylControl(true); 00200 break; 00201 } 00202 } 00203 } 00204 bail: 00205 m_proxiesLock.unlock(); 00206 }