Mixxx

/home/maxime/Projets/Mixxx/1.10/mixxx/src/widget/wglwaveformviewer.cpp

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