Mixxx

/home/maxime/Projets/Mixxx/1.10/mixxx/src/vinylcontrol/vinylcontrolmanager.cpp

Go to the documentation of this file.
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 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Defines