![]() |
Mixxx
|
00001 /*************************************************************************** 00002 controlobject.cpp - description 00003 ------------------- 00004 begin : Wed Feb 20 2002 00005 copyright : (C) 2002 by Tue and Ken Haste Andersen 00006 email : 00007 ***************************************************************************/ 00008 00009 /*************************************************************************** 00010 * * 00011 * This program is free software; you can redistribute it and/or modify * 00012 * it under the terms of the GNU General Public License as published by * 00013 * the Free Software Foundation; either version 2 of the License, or * 00014 * (at your option) any later version. * 00015 * * 00016 ***************************************************************************/ 00017 00018 #include <qwidget.h> 00019 #include <QtDebug> 00020 #include <QHash> 00021 #include "controlobject.h" 00022 #include "controlevent.h" 00023 00024 // Static member variable definition 00025 QHash<ConfigKey,ControlObject*> ControlObject::m_sqCOHash; 00026 QMutex ControlObject::m_sqCOHashMutex; 00027 00028 QMutex ControlObject::m_sqQueueMutexMidi; 00029 QMutex ControlObject::m_sqQueueMutexThread; 00030 QMutex ControlObject::m_sqQueueMutexChanges; 00031 QQueue<QueueObjectMidi*> ControlObject::m_sqQueueMidi; 00032 QQueue<QueueObjectThread*> ControlObject::m_sqQueueThread; 00033 QQueue<ControlObject*> ControlObject::m_sqQueueChanges; 00034 00035 ControlObject::ControlObject() : 00036 m_dValue(0), 00037 m_bIgnoreNops(true) { 00038 } 00039 00040 ControlObject::ControlObject(ConfigKey key, bool bIgnoreNops) : 00041 m_dValue(0), 00042 m_Key(key), 00043 m_bIgnoreNops(bIgnoreNops) { 00044 m_sqCOHashMutex.lock(); 00045 m_sqCOHash.insert(key,this); 00046 m_sqCOHashMutex.unlock(); 00047 } 00048 00049 ControlObject::~ControlObject() 00050 { 00051 m_sqCOHashMutex.lock(); 00052 m_sqCOHash.remove(m_Key); 00053 m_sqCOHashMutex.unlock(); 00054 00055 ControlObjectThread * obj; 00056 m_qProxyListMutex.lock(); 00057 QListIterator<ControlObjectThread*> it(m_qProxyList); 00058 while (it.hasNext()) 00059 { 00060 obj = it.next(); 00061 obj->slotParentDead(); 00062 } 00063 m_qProxyListMutex.unlock(); 00064 00065 00066 m_sqQueueMutexThread.lock(); 00067 QMutableListIterator<QueueObjectThread*> tit(m_sqQueueThread); 00068 while (tit.hasNext()) { 00069 QueueObjectThread* tobj = tit.next(); 00070 if (tobj->pControlObject == this) { 00071 tit.remove(); 00072 delete tobj; 00073 } 00074 } 00075 m_sqQueueMutexThread.unlock(); 00076 00077 m_sqQueueMutexMidi.lock(); 00078 QMutableListIterator<QueueObjectMidi*> mit(m_sqQueueMidi); 00079 while (mit.hasNext()) { 00080 QueueObjectMidi* mobj = mit.next(); 00081 if (mobj->pControlObject == this) { 00082 mit.remove(); 00083 delete mobj; 00084 } 00085 } 00086 m_sqQueueMutexMidi.unlock(); 00087 00088 // Remove this control object from the changes queue, since we're being 00089 // deleted. 00090 m_sqQueueMutexChanges.lock(); 00091 m_sqQueueChanges.removeAll(this); 00092 m_sqQueueMutexChanges.unlock(); 00093 00094 } 00095 00096 bool ControlObject::connectControls(ConfigKey src, ConfigKey dest) 00097 { 00098 // Find src and dest objects 00099 ControlObject * pSrc = getControl(src); 00100 ControlObject * pDest = getControl(dest); 00101 00102 if (pSrc && pDest) 00103 { 00104 connect(pSrc, SIGNAL(valueChanged(double)), pDest, SLOT(set(double))); 00105 connect(pSrc, SIGNAL(valueChangedFromEngine(double)), pDest, SLOT(set(double))); 00106 return true; 00107 } 00108 else 00109 return false; 00110 } 00111 00112 bool ControlObject::disconnectControl(ConfigKey key) 00113 { 00114 // Find src and dest objects 00115 ControlObject * pSrc = getControl(key); 00116 00117 if (pSrc) 00118 { 00119 disconnect(pSrc, 0, 0, 0); 00120 return true; 00121 } 00122 else 00123 return false; 00124 } 00125 00126 void ControlObject::addProxy(ControlObjectThread * pControlObjectThread) 00127 { 00128 m_qProxyListMutex.lock(); 00129 m_qProxyList.append(pControlObjectThread); 00130 m_qProxyListMutex.unlock(); 00131 } 00132 00133 void ControlObject::removeProxy(ControlObjectThread * pControlObjectThread) { 00134 m_qProxyListMutex.lock(); 00135 m_qProxyList.removeAll(pControlObjectThread); 00136 m_qProxyListMutex.unlock(); 00137 } 00138 00139 bool ControlObject::updateProxies(ControlObjectThread * pProxyNoUpdate) 00140 { 00141 ControlObjectThread * obj; 00142 bool bUpdateSuccess = true; 00143 // qDebug() << "updateProxies: Group" << m_Key.group << "/ Item" << m_Key.item; 00144 m_qProxyListMutex.lock(); 00145 QListIterator<ControlObjectThread*> it(m_qProxyList); 00146 while (it.hasNext()) 00147 { 00148 obj = it.next(); 00149 if (obj!=pProxyNoUpdate) 00150 { 00151 // qDebug() << "upd" << this->getKey().item; 00152 bUpdateSuccess = bUpdateSuccess && obj->setExtern(m_dValue); 00153 } 00154 } 00155 m_qProxyListMutex.unlock(); 00156 return bUpdateSuccess; 00157 } 00158 00159 void ControlObject::getControls(QList<ControlObject*>* pControlList) { 00160 m_sqCOHashMutex.lock(); 00161 for (QHash<ConfigKey, ControlObject*>::const_iterator it = m_sqCOHash.constBegin(); 00162 it != m_sqCOHash.constEnd(); ++it) { 00163 pControlList->push_back(it.value()); 00164 } 00165 m_sqCOHashMutex.unlock(); 00166 } 00167 00168 ControlObject * ControlObject::getControl(ConfigKey key) 00169 { 00170 //qDebug() << "ControlObject::getControl for (" << key.group << "," << key.item << ")"; 00171 m_sqCOHashMutex.lock(); 00172 if(m_sqCOHash.contains(key)) { 00173 ControlObject *co = m_sqCOHash[key]; 00174 m_sqCOHashMutex.unlock(); 00175 return co; 00176 } 00177 m_sqCOHashMutex.unlock(); 00178 00179 qDebug() << "ControlObject::getControl returning NULL for (" << key.group << "," << key.item << ")"; 00180 return NULL; 00181 } 00182 00183 void ControlObject::queueFromThread(double dValue, ControlObjectThread * pControlObjectThread) 00184 { 00185 QueueObjectThread * p = new QueueObjectThread; 00186 p->pControlObjectThread = pControlObjectThread; 00187 p->pControlObject = this; 00188 p->value = dValue; 00189 00190 m_sqQueueMutexThread.lock(); 00191 m_sqQueueThread.enqueue(p); 00192 m_sqQueueMutexThread.unlock(); 00193 } 00194 00195 void ControlObject::queueFromMidi(MidiCategory c, double v) 00196 { 00197 QueueObjectMidi * p = new QueueObjectMidi; 00198 p->pControlObject = this; 00199 p->category = c; 00200 p->value = v; 00201 00202 m_sqQueueMutexMidi.lock(); 00203 m_sqQueueMidi.enqueue(p); 00204 m_sqQueueMutexMidi.unlock(); 00205 } 00206 00207 void ControlObject::setValueFromEngine(double dValue) 00208 { 00209 m_dValue = dValue; 00210 emit(valueChangedFromEngine(m_dValue)); 00211 } 00212 00213 void ControlObject::setValueFromMidi(MidiCategory, double v) 00214 { 00215 m_dValue = v; 00216 emit(valueChanged(m_dValue)); 00217 } 00218 00219 double ControlObject::GetMidiValue() 00220 { 00221 return m_dValue; 00222 } 00223 00224 void ControlObject::setValueFromThread(double dValue) 00225 { 00226 if (m_bIgnoreNops && m_dValue == dValue) 00227 return; 00228 00229 m_dValue = dValue; 00230 emit(valueChanged(m_dValue)); 00231 } 00232 00233 void ControlObject::set(double dValue) 00234 { 00235 if (m_bIgnoreNops && m_dValue == dValue) 00236 return; 00237 00238 setValueFromEngine(dValue); 00239 m_sqQueueMutexChanges.lock(); 00240 m_sqQueueChanges.enqueue(this); 00241 m_sqQueueMutexChanges.unlock(); 00242 } 00243 00244 void ControlObject::add(double dValue) 00245 { 00246 if (m_bIgnoreNops && !dValue) 00247 return; 00248 00249 setValueFromEngine(m_dValue+dValue); 00250 m_sqQueueMutexChanges.lock(); 00251 m_sqQueueChanges.enqueue(this); 00252 m_sqQueueMutexChanges.unlock(); 00253 } 00254 00255 void ControlObject::sub(double dValue) 00256 { 00257 if (m_bIgnoreNops && !dValue) 00258 return; 00259 00260 setValueFromEngine(m_dValue-dValue); 00261 m_sqQueueMutexChanges.lock(); 00262 m_sqQueueChanges.enqueue(this); 00263 m_sqQueueMutexChanges.unlock(); 00264 } 00265 00266 double ControlObject::getValueFromWidget(double v) 00267 { 00268 return v; 00269 } 00270 00271 double ControlObject::getValueToWidget(double v) 00272 { 00273 return v; 00274 } 00275 00276 void ControlObject::sync() 00277 { 00278 // Update control objects with values recieved from threads 00279 if (m_sqQueueMutexThread.tryLock()) 00280 { 00281 QueueObjectThread * obj; 00282 while(!m_sqQueueThread.isEmpty()) 00283 { 00284 obj = m_sqQueueThread.dequeue(); 00285 00286 if (obj->pControlObject) 00287 { 00288 obj->pControlObject->setValueFromThread(obj->value); 00289 obj->pControlObject->updateProxies(obj->pControlObjectThread); 00290 } 00291 delete obj; 00292 } 00293 00294 // 00295 // If the object is in m_sqQueueChanges, delete it from that queue. 00296 // 00297 00298 m_sqQueueMutexThread.unlock(); 00299 } 00300 00301 // Update control objects with values recieved from MIDI 00302 if (m_sqQueueMutexMidi.tryLock()) 00303 { 00304 QueueObjectMidi * obj; 00305 while(!m_sqQueueMidi.isEmpty()) 00306 { 00307 obj = m_sqQueueMidi.dequeue(); 00308 if (obj == NULL) { 00309 qDebug() << "Midi sent us a bad object!"; 00310 } else if (obj->pControlObject == NULL) { 00311 qDebug() << "Midi object with null control object!"; 00312 delete obj; 00313 } else if (!obj->category) { 00314 qDebug() << "Midi object with null category!"; 00315 delete obj; 00316 } else { 00317 obj->pControlObject->setValueFromMidi(obj->category, obj->value); 00318 obj->pControlObject->updateProxies(0); 00319 delete obj; 00320 } 00321 } 00322 00323 // 00324 // If the object is in m_sqQueueChanges, delete it from that queue. 00325 // 00326 00327 m_sqQueueMutexMidi.unlock(); 00328 } 00329 00330 // Update app threads (ControlObjectThread objects) with changes in the corresponding 00331 // ControlObjects. These updates should only occour if no changes has been in the object 00332 // from widgets, midi og application threads. 00333 ControlObject * obj; 00334 if(m_sqQueueMutexChanges.tryLock()) 00335 { 00336 while(!m_sqQueueChanges.isEmpty()) 00337 { 00338 obj = m_sqQueueChanges.dequeue(); 00339 00340 // If update is not successful, enqueue again 00341 if (!obj->updateProxies()) 00342 m_sqQueueChanges.enqueue(obj); 00343 00344 } 00345 m_sqQueueMutexChanges.unlock(); 00346 } 00347 }