![]() |
Mixxx
|
00001 00002 #include <QGLWidget> 00003 #include <QDebug> 00004 #include <QDomNode> 00005 #include <QEvent> 00006 #include <QDragEnterEvent> 00007 #include <QUrl> 00008 #include <QPainter> 00009 #include <QGLContext> 00010 00011 #include "mixxx.h" 00012 #include "trackinfoobject.h" 00013 #include "wglwaveformviewer.h" 00014 #include "waveform/waveformrenderer.h" 00015 #include "controlobjectthreadmain.h" 00016 #include "sharedglcontext.h" 00017 00018 WGLWaveformViewer::WGLWaveformViewer( 00019 const char *group, 00020 WaveformRenderer *pWaveformRenderer, 00021 QWidget * pParent, 00022 const QGLWidget * pShareWidget, 00023 QGLContext *ctxt, 00024 Qt::WFlags f 00025 ) : 00026 QGLWidget(ctxt, pParent, pShareWidget) 00027 { 00028 m_pWaveformRenderer = pWaveformRenderer; 00029 Q_ASSERT(m_pWaveformRenderer); 00030 00031 m_pGroup = group; 00032 00033 m_bScratching = false; 00034 m_bBending = false; 00035 00036 m_pScratchEnable = new ControlObjectThreadMain( 00037 ControlObject::getControl(ConfigKey(group, "scratch_position_enable"))); 00038 m_pScratch = new ControlObjectThreadMain( 00039 ControlObject::getControl(ConfigKey(group, "scratch_position"))); 00040 m_pTrackSamples = new ControlObjectThreadMain( 00041 ControlObject::getControl(ConfigKey(group, "track_samples"))); 00042 m_pTrackSampleRate = new ControlObjectThreadMain( 00043 ControlObject::getControl(ConfigKey(group, "track_samplerate"))); 00044 m_pRate = new ControlObjectThreadMain( 00045 ControlObject::getControl(ConfigKey(m_pGroup, "rate"))); 00046 m_pRateRange = new ControlObjectThreadMain( 00047 ControlObject::getControl(ConfigKey(m_pGroup, "rateRange"))); 00048 m_pRateDir = new ControlObjectThreadMain( 00049 ControlObject::getControl(ConfigKey(m_pGroup, "rate_dir"))); 00050 00051 setAcceptDrops(true); 00052 00053 installEventFilter(this); 00054 00055 m_painting = false; 00056 00057 setSizePolicy(QSizePolicy::MinimumExpanding, 00058 QSizePolicy::MinimumExpanding); 00059 } 00060 00061 bool WGLWaveformViewer::directRendering() 00062 { 00063 return format().directRendering(); 00064 } 00065 00066 00067 WGLWaveformViewer::~WGLWaveformViewer() { 00068 delete m_pScratchEnable; 00069 delete m_pScratch; 00070 delete m_pTrackSamples; 00071 delete m_pTrackSampleRate; 00072 delete m_pRate; 00073 delete m_pRateRange; 00074 delete m_pRateDir; 00075 } 00076 00077 void WGLWaveformViewer::setup(QDomNode node) { 00078 int w = width(), h = height(); 00079 m_pWaveformRenderer->setup(node); 00080 m_pWaveformRenderer->resize(w, h); 00081 } 00082 00083 void WGLWaveformViewer::resizeEvent(QResizeEvent* e) 00084 { 00085 const QSize newSize = e->size(); 00086 m_pWaveformRenderer->resize(newSize.width(), 00087 newSize.height()); 00088 } 00089 00090 00091 void WGLWaveformViewer::paintEvent(QPaintEvent *event) { 00092 QPainter painter; 00093 painter.begin(this); 00094 00095 painter.setRenderHint(QPainter::Antialiasing); 00096 //painter.setRenderHint(QPainter::TextAntialiasing); 00097 00098 // HighQualityAntialiasing makes some CPUs go crazy 00099 //painter.setRenderHint(QPainter::HighQualityAntialiasing); 00100 00101 m_pWaveformRenderer->draw(&painter, event); 00102 00103 painter.end(); 00104 m_painting = false; 00105 // QPainter goes out of scope and is destructed 00106 } 00107 00108 void WGLWaveformViewer::refresh() { 00109 //m_paintMutex.lock(); 00110 if(!m_painting) { 00111 m_painting = true; 00112 00113 // The docs say update is better than repaint. 00114 update(); 00115 //updateGL(); 00116 } 00117 //m_paintMutex.unlock(); 00118 } 00119 00122 void WGLWaveformViewer::setValue(double) { 00123 // unused, stops a bad connect from happening 00124 } 00125 00126 bool WGLWaveformViewer::eventFilter(QObject *o, QEvent *e) { 00127 QMouseEvent* m = dynamic_cast<QMouseEvent*>(e); 00128 if(e->type() == QEvent::MouseButtonPress) { 00129 m_iMouseStart = m->x(); 00130 if(m->button() == Qt::LeftButton) { 00131 // If we are pitch-bending then disable and reset because the two 00132 // shouldn't be used at once. 00133 if (m_bBending) { 00134 emit(valueChangedRightDown(64)); 00135 m_bBending = false; 00136 } 00137 m_bScratching = true; 00138 m_pScratch->slotSet(0); 00139 m_pScratchEnable->slotSet(1.0f); 00140 00141 // Set the cursor to a hand while the mouse is down. 00142 setCursor(Qt::ClosedHandCursor); 00143 } else if (m->button() == Qt::RightButton) { 00144 emit(valueChangedRightDown(64)); 00145 m_bBending = true; 00146 } 00147 } else if(e->type() == QEvent::MouseMove) { 00148 // Only send signals for mouse moving if the left button is pressed 00149 if (m_iMouseStart != -1 && m_bScratching) { 00150 int curX = m->x(); 00151 00152 // Adjusts for one-to-one movement. Track sample rate in hundreds of 00153 // samples times two is the number of samples per pixel. rryan 00154 // 4/2011 00155 double samplesPerPixel = m_pTrackSampleRate->get() / 100.0 * 2; 00156 00157 // To take care of one one movement when zoom changes with pitch 00158 double rateAdjust = m_pRateDir->get() * 00159 math_min(0.99, m_pRate->get() * m_pRateRange->get()); 00160 double targetPosition = (m_iMouseStart - curX) * 00161 samplesPerPixel * (1 + rateAdjust); 00162 //qDebug() << "Target:" << targetPosition; 00163 m_pScratch->slotSet(targetPosition); 00164 } else if (m_iMouseStart != -1 && m_bBending) { 00165 // start at the middle of 0-127, and emit values based on 00166 // how far the mouse has travelled horizontally 00167 double v = 64 + (double)(m->x()-m_iMouseStart)/10; 00168 // clamp to 0-127 00169 if(v<0) 00170 v = 0; 00171 else if(v > 127) 00172 v = 127; 00173 emit(valueChangedRightDown(v)); 00174 } 00175 } else if(e->type() == QEvent::MouseButtonRelease) { 00176 if (m_bScratching) { 00177 m_pScratchEnable->slotSet(0.0f); 00178 m_bScratching = false; 00179 00180 // Set the cursor back to an arrow. 00181 setCursor(Qt::ArrowCursor); 00182 } 00183 if (m_bBending) { 00184 emit(valueChangedRightDown(64)); 00185 m_bBending = false; 00186 } 00187 m_iMouseStart = -1; 00188 } else { 00189 return QObject::eventFilter(o,e); 00190 } 00191 return true; 00192 } 00193 00197 void WGLWaveformViewer::dragEnterEvent(QDragEnterEvent * event) 00198 { 00199 // Accept the enter event if the thing is a filepath and nothing's playing 00200 // in this deck. 00201 if (event->mimeData()->hasUrls() && 00202 event->mimeData()->urls().size() > 0) { 00203 ControlObject *pPlayCO = ControlObject::getControl( 00204 ConfigKey(m_pGroup, "play")); 00205 if (pPlayCO && pPlayCO->get()) { 00206 event->ignore(); 00207 } else { 00208 event->acceptProposedAction(); 00209 } 00210 } 00211 } 00212 00213 void WGLWaveformViewer::dropEvent(QDropEvent * event) { 00214 if (event->mimeData()->hasUrls() && 00215 event->mimeData()->urls().size() > 0) { 00216 QList<QUrl> urls(event->mimeData()->urls()); 00217 QUrl url = urls.first(); 00218 QString name = url.toLocalFile(); 00219 //If the file is on a network share, try just converting the URL to a string... 00220 if (name == "") 00221 name = url.toString(); 00222 00223 event->accept(); 00224 emit(trackDropped(name, m_pGroup)); 00225 } else { 00226 event->ignore(); 00227 } 00228 }