diff --git a/build/depends.py b/build/depends.py index e015b0e72f13..6a96f21c6a06 100644 --- a/build/depends.py +++ b/build/depends.py @@ -545,6 +545,8 @@ def sources(self, build): "widget/wslider.cpp", "widget/wstatuslight.cpp", "widget/woverview.cpp", + "widget/woverviewlmh.cpp", + "widget/woverviewhsv.cpp", "widget/wspinny.cpp", "widget/wskincolor.cpp", "widget/wabstractcontrol.cpp", diff --git a/src/dlgprefcontrols.cpp b/src/dlgprefcontrols.cpp index e0168853ddea..097a1422d741 100644 --- a/src/dlgprefcontrols.cpp +++ b/src/dlgprefcontrols.cpp @@ -562,6 +562,11 @@ void DlgPrefControls::slotSetWaveformType(int index) { } } +void DlgPrefControls::slotSetWaveformOverviewType(int index) { + m_pConfig->set(ConfigKey("[Waveform]","WaveformOverviewType"), ConfigValue(index)); + m_mixxx->rebootMixxxView(); +} + void DlgPrefControls::slotSetDefaultZoom(int index) { WaveformWidgetFactory::instance()->setDefaultZoom( index + 1); } @@ -664,6 +669,15 @@ void DlgPrefControls::initWaveformControl() connect(normalizeOverviewCheckBox,SIGNAL(toggled(bool)), this,SLOT(slotSetNormalizeOverview(bool))); + // Waveform overview init + waveformOverviewComboBox->addItem( tr("Filtered") ); // "0" + waveformOverviewComboBox->addItem( tr("HSV") ); // "1" + + // By default we set filtered woverview = "0" + waveformOverviewComboBox->setCurrentIndex( + m_pConfig->getValueString(ConfigKey("[Waveform]","WaveformOverviewType"), "0").toInt()); + connect(waveformOverviewComboBox,SIGNAL(currentIndexChanged(int)), + this,SLOT(slotSetWaveformOverviewType(int))); } //Returns TRUE if skin fits to screen resolution, FALSE otherwise diff --git a/src/dlgprefcontrols.h b/src/dlgprefcontrols.h index b83140fdee5e..2e1240071d51 100644 --- a/src/dlgprefcontrols.h +++ b/src/dlgprefcontrols.h @@ -66,6 +66,7 @@ public slots: void slotSetFrameRate(int frameRate); void slotSetWaveformType(int index); + void slotSetWaveformOverviewType(int index); void slotSetDefaultZoom(int index); void slotSetZoomSynchronization(bool checked); void slotSetVisualGainAll(double gain); diff --git a/src/dlgprefcontrolsdlg.ui b/src/dlgprefcontrolsdlg.ui index f0731cf8c71b..834988548c3b 100644 --- a/src/dlgprefcontrolsdlg.ui +++ b/src/dlgprefcontrolsdlg.ui @@ -7,7 +7,7 @@ 0 0 519 - 728 + 729 @@ -598,29 +598,20 @@ false - - - - - 0 - 0 - + + + + Displays which OpenGL version is supported by the current platform. - Display type - - - Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter - - - waveformTypeComboBox + - + @@ -648,7 +639,7 @@ - + @@ -664,7 +655,7 @@ - + Visual gain of the high frequencies @@ -683,7 +674,7 @@ - + Visual gain of the middle frequencies @@ -702,7 +693,7 @@ - + Visual gain of the low frequencies @@ -721,7 +712,7 @@ - + Global visual gain @@ -740,7 +731,7 @@ - + Visual gain @@ -753,7 +744,7 @@ - + Frame rate @@ -766,10 +757,10 @@ - + - + Default zoom @@ -782,7 +773,7 @@ - + Synchronize zoom level across all waveform displays. @@ -792,7 +783,7 @@ - + @@ -805,17 +796,7 @@ - - - - Displays which OpenGL version is supported by the current platform. - - - - - - - + Displays the actual frame rate. @@ -825,20 +806,49 @@ - + - + Normalize Overview + + + + + 0 + 0 + + + + Display type + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter + + + waveformTypeComboBox + + + + + + + + + + Preview type + + + diff --git a/src/skin/legacyskinparser.cpp b/src/skin/legacyskinparser.cpp index 3dd9e3deb110..2c0a5c759f78 100644 --- a/src/skin/legacyskinparser.cpp +++ b/src/skin/legacyskinparser.cpp @@ -41,7 +41,8 @@ #include "widget/wnumber.h" #include "widget/wnumberpos.h" #include "widget/wnumberrate.h" -#include "widget/woverview.h" +#include "widget/woverviewlmh.h" +#include "widget/woverviewhsv.h" #include "widget/wspinny.h" #include "widget/wwaveformviewer.h" #include "waveform/waveformwidgetfactory.h" @@ -595,7 +596,15 @@ QWidget* LegacySkinParser::parseOverview(QDomElement node) { if (pPlayer == NULL) return NULL; - WOverview* overviewWidget = new WOverview(pSafeChannelStr, m_pConfig, m_pParent); + WOverview* overviewWidget = NULL; + + // HSV = "1" or "Filtered" = "0" (LMH) waveform overview type + if (m_pConfig->getValueString(ConfigKey("[Waveform]","WaveformOverviewType"), + "0").toInt() == 0) { + overviewWidget = new WOverviewLMH(pSafeChannelStr, m_pConfig, m_pParent); + } else { + overviewWidget = new WOverviewHSV(pSafeChannelStr, m_pConfig, m_pParent); + } connect(overviewWidget, SIGNAL(trackDropped(QString, QString)), m_pPlayerManager, SLOT(slotLoadToPlayer(QString, QString))); diff --git a/src/widget/woverview.cpp b/src/widget/woverview.cpp index 5545672df4f5..58e1d54f2dbe 100644 --- a/src/widget/woverview.cpp +++ b/src/widget/woverview.cpp @@ -248,109 +248,6 @@ void WOverview::onMarkRangeChange(double /*v*/) { update(); } -bool WOverview::drawNextPixmapPart() { - ScopedTimer t("WOverview::drawNextPixmapPart"); - - //qDebug() << "WOverview::drawNextPixmapPart() - m_waveform" << m_waveform; - - int currentCompletion; - - if (!m_pWaveform) { - return false; - } - - const int dataSize = m_pWaveform->getDataSize(); - if (dataSize == 0 ) { - return false; - } - - if (!m_pWaveformSourceImage) { - //waveform pixmap twice the height of the viewport to be scalable by total_gain - //we keep full range waveform data to scale it on paint - m_pWaveformSourceImage = new QImage(dataSize / 2, 2 * 255, QImage::Format_ARGB32_Premultiplied); - m_pWaveformSourceImage->fill(QColor(0,0,0,0).value()); - } - - const int waveformCompletion = m_pWaveform->getCompletion(); // always multiple of 2 - // test if there is some new to draw (at least of pixel width) - const int completionIncrement = waveformCompletion - m_actualCompletion; - - int visiblePixelIncrement = completionIncrement * width() / dataSize; - if (completionIncrement < 2 || visiblePixelIncrement == 0) { - return false; - } - - if (!m_pWaveform->getMutex()->tryLock()) { - return false; - } - - const int nextCompletion = m_actualCompletion + completionIncrement; - - //qDebug() << "WOverview::drawNextPixmapPart() - nextCompletion:" << nextCompletion - // << "m_actualCompletion:" << m_actualCompletion - // << "waveformCompletion:" << waveformCompletion - // << "completionIncrement:" << completionIncrement; - - - QPainter painter(m_pWaveformSourceImage); - painter.translate(0.0,(double)m_pWaveformSourceImage->height()/2.0); - - QColor lowColor = m_signalColors.getLowColor(); - QPen lowColorPen(QBrush(lowColor), 1); - - QColor midColor = m_signalColors.getMidColor(); - QPen midColorPen(QBrush(midColor), 1); - - QColor highColor = m_signalColors.getHighColor(); - QPen highColorPen(QBrush(highColor), 1); - - for (currentCompletion = m_actualCompletion; - currentCompletion < nextCompletion; currentCompletion += 2) { - unsigned char lowNeg = m_pWaveform->getLow(currentCompletion); - unsigned char lowPos = m_pWaveform->getLow(currentCompletion+1); - if (lowPos || lowNeg) { - painter.setPen(lowColorPen); - painter.drawLine(QPoint(currentCompletion / 2, -lowNeg), - QPoint(currentCompletion / 2, lowPos)); - } - } - - for (currentCompletion = m_actualCompletion; - currentCompletion < nextCompletion; currentCompletion += 2) { - painter.setPen(midColorPen); - painter.drawLine(QPoint(currentCompletion / 2, - m_pWaveform->getMid(currentCompletion)), - QPoint(currentCompletion / 2, m_pWaveform->getMid(currentCompletion+1))); - } - - for (currentCompletion = m_actualCompletion; - currentCompletion < nextCompletion; currentCompletion += 2) { - painter.setPen(highColorPen); - painter.drawLine(QPoint(currentCompletion / 2, - m_pWaveform->getHigh(currentCompletion)), - QPoint(currentCompletion / 2, m_pWaveform->getHigh(currentCompletion+1))); - } - - //evaluate waveform ratio peak - - for (currentCompletion = m_actualCompletion; - currentCompletion < nextCompletion; currentCompletion += 2) { - m_waveformPeak = math_max(m_waveformPeak, (float)m_pWaveform->getAll(currentCompletion)); - m_waveformPeak = math_max(m_waveformPeak, (float)m_pWaveform->getAll(currentCompletion+1)); - } - - m_actualCompletion = nextCompletion; - m_waveformImageScaled = QImage(); - m_diffGain = 0; - - //test if the complete waveform is done - if (m_actualCompletion >= dataSize - 2) { - m_pixmapDone = true; - //qDebug() << "m_waveformPeakRatio" << m_waveformPeak; - } - - m_pWaveform->getMutex()->unlock(); - return true; -} - void WOverview::mouseMoveEvent(QMouseEvent* e) { m_iPos = e->x(); m_iPos = math_max(0, math_min(m_iPos,width() - 1)); diff --git a/src/widget/woverview.h b/src/widget/woverview.h index a277e6a6938f..31d477e9c7d2 100644 --- a/src/widget/woverview.h +++ b/src/widget/woverview.h @@ -25,29 +25,19 @@ #include "waveform/renderers/waveformmarkset.h" #include "waveform/renderers/waveformmarkrange.h" -/** -Waveform overview display -@author Tue Haste Andersen -*/ +// Waveform overview display +// @author Tue Haste Andersen class ControlObjectThreadMain; class Waveform; -class WOverview : public WWidget -{ +class WOverview : public WWidget { Q_OBJECT public: WOverview(const char* pGroup, ConfigObject* pConfig, QWidget *parent=NULL); virtual ~WOverview(); void setup(QDomNode node); - protected: - void mouseMoveEvent(QMouseEvent *e); - void mouseReleaseEvent(QMouseEvent *e); - void mousePressEvent(QMouseEvent *e); - void paintEvent(QPaintEvent *); - void resizeEvent(QResizeEvent *); - public slots: void setValue(double); void slotLoadNewTrack(TrackPointer pTrack); @@ -58,9 +48,29 @@ class WOverview : public WWidget void trackDropped(QString filename, QString group); protected: + void mouseMoveEvent(QMouseEvent *e); + void mouseReleaseEvent(QMouseEvent *e); + void mousePressEvent(QMouseEvent *e); + void paintEvent(QPaintEvent *); + void resizeEvent(QResizeEvent *); virtual void dragEnterEvent(QDragEnterEvent* event); virtual void dropEvent(QDropEvent* event); + Waveform* m_pWaveform; + + QImage* m_pWaveformSourceImage; + QImage m_waveformImageScaled; + + WaveformSignalColors m_signalColors; + + // Hold the last visual sample processed to generate the pixmap + int m_actualCompletion; + + bool m_pixmapDone; + float m_waveformPeak; + + int m_diffGain; + private slots: void onEndOfTrackChange(double v); @@ -71,8 +81,8 @@ class WOverview : public WWidget void slotAnalyserProgress(int progress); private: - /** append the waveform overview pixmap according to available data in waveform */ - bool drawNextPixmapPart(); + // Append the waveform overview pixmap according to available data in waveform + virtual bool drawNextPixmapPart() = 0; void paintText(const QString &text, QPainter *painter); inline int valueToPosition(float value) const { return (int)(m_a * value - m_b + 0.5); @@ -89,22 +99,13 @@ class WOverview : public WWidget ControlObjectThreadMain* m_trackSamplesControl; ControlObjectThreadMain* m_playControl; - Waveform* m_pWaveform; - QImage* m_pWaveformSourceImage; - QImage m_waveformImageScaled; - - bool m_pixmapDone; - float m_waveformPeak; - - /** Hold the last visual sample processed to generate the pixmap*/ - int m_actualCompletion; // Current active track TrackPointer m_pCurrentTrack; - /** True if slider is dragged. Only used when m_bEventWhileDrag is false */ + // True if slider is dragged. Only used when m_bEventWhileDrag is false bool m_bDrag; - /** Internal storage of slider position in pixels */ + // Internal storage of slider position in pixels int m_iPos; QPixmap m_backgroundPixmap; @@ -112,17 +113,15 @@ class WOverview : public WWidget QColor m_qColorBackground; QColor m_endOfTrackColor; - WaveformSignalColors m_signalColors; WaveformMarkSet m_marks; std::vector m_markRanges; - /** coefficient value-position linear transposition */ + // Coefficient value-position linear transposition float m_a; float m_b; - int m_analyserProgress; // in 0.1% + int m_analyserProgress; // In 0.1% bool m_trackLoaded; - int m_diffGain; }; #endif diff --git a/src/widget/woverviewhsv.cpp b/src/widget/woverviewhsv.cpp new file mode 100644 index 000000000000..3253b419c2a1 --- /dev/null +++ b/src/widget/woverviewhsv.cpp @@ -0,0 +1,132 @@ +#include "woverviewhsv.h" + +#include "util/timer.h" + +#include "waveform/waveform.h" + +WOverviewHSV::WOverviewHSV(const char* pGroup, + ConfigObject* pConfig, QWidget * parent) + : WOverview(pGroup, pConfig, parent) { +} + +bool WOverviewHSV::drawNextPixmapPart() { + ScopedTimer t("WOverviewHSV::drawNextPixmapPart"); + + //qDebug() << "WOverview::drawNextPixmapPart() - m_waveform" << m_waveform; + + int currentCompletion; + + if (!m_pWaveform) { + return false; + } + + const int dataSize = m_pWaveform->getDataSize(); + if (dataSize == 0 ) { + return false; + } + + if (!m_pWaveformSourceImage) { + // Waveform pixmap twice the height of the viewport to be scalable + // by total_gain + // We keep full range waveform data to scale it on paint + m_pWaveformSourceImage = new QImage(dataSize / 2, 2 * 255, + QImage::Format_ARGB32_Premultiplied); + m_pWaveformSourceImage->fill(QColor(0,0,0,0).value()); + } + + // Always multiple of 2 + const int waveformCompletion = m_pWaveform->getCompletion(); + // Test if there is some new to draw (at least of pixel width) + const int completionIncrement = waveformCompletion - m_actualCompletion; + + int visiblePixelIncrement = completionIncrement * width() / dataSize; + if (completionIncrement < 2 || visiblePixelIncrement == 0) { + return false; + } + + if (!m_pWaveform->getMutex()->tryLock()) { + return false; + } + + const int nextCompletion = m_actualCompletion + completionIncrement; + + //qDebug() << "WOverview::drawNextPixmapPart() - nextCompletion:" + // << nextCompletion + // << "m_actualCompletion:" << m_actualCompletion + // << "waveformCompletion:" << waveformCompletion + // << "completionIncrement:" << completionIncrement; + + + QPainter painter(m_pWaveformSourceImage); + painter.translate(0.0,(double)m_pWaveformSourceImage->height()/2.0); + + // Get HSV of low color + double h,s,v; + m_signalColors.getLowColor().getHsvF(&h,&s,&v); + + QColor color; + float lo, hi, total; + + unsigned char maxLow[2] = {0, 0}; + unsigned char maxHigh[2] = {0, 0}; + unsigned char maxMid[2] = {0, 0}; + unsigned char maxAll[2] = {0, 0}; + + for (currentCompletion = m_actualCompletion; + currentCompletion < nextCompletion; currentCompletion += 2) { + maxAll[0] = m_pWaveform->getAll(currentCompletion); + maxAll[1] = m_pWaveform->getAll(currentCompletion+1); + if (maxAll[0] || maxAll[1]) { + maxLow[0] = m_pWaveform->getLow(currentCompletion); + maxLow[1] = m_pWaveform->getLow(currentCompletion+1); + maxMid[0] = m_pWaveform->getMid(currentCompletion); + maxMid[1] = m_pWaveform->getMid(currentCompletion+1); + maxHigh[0] = m_pWaveform->getHigh(currentCompletion); + maxHigh[1] = m_pWaveform->getHigh(currentCompletion+1); + + total = (maxLow[0] + maxLow[1] + maxMid[0] + maxMid[1] + + maxHigh[0] + maxHigh[1]) * 1.2; + + // Prevent division by zero + if( total > 0 ) + { + // Normalize low and high + // (mid not need, because it not change the color) + lo = (maxLow[0] + maxLow[1]) / total; + hi = (maxHigh[0] + maxHigh[1]) / total; + } + else + lo = hi = 0.0; + + // Set color + color.setHsvF(h, 1.0-hi, 1.0-lo); + + painter.setPen(color); + painter.drawLine(QPoint(currentCompletion / 2, -maxAll[0]), + QPoint(currentCompletion / 2, maxAll[1])); + } + } + + // Evaluate waveform ratio peak + + for (currentCompletion = m_actualCompletion; + currentCompletion < nextCompletion; currentCompletion += 2) { + m_waveformPeak = math_max(m_waveformPeak, + (float)m_pWaveform->getAll(currentCompletion)); + m_waveformPeak = math_max(m_waveformPeak, + (float)m_pWaveform->getAll(currentCompletion+1)); + } + + m_actualCompletion = nextCompletion; + m_waveformImageScaled = QImage(); + m_diffGain = 0; + + // Test if the complete waveform is done + if (m_actualCompletion >= dataSize - 2) { + m_pixmapDone = true; + //qDebug() << "m_waveformPeakRatio" << m_waveformPeak; + } + + m_pWaveform->getMutex()->unlock(); + return true; +} diff --git a/src/widget/woverviewhsv.h b/src/widget/woverviewhsv.h new file mode 100644 index 000000000000..537bcf34905f --- /dev/null +++ b/src/widget/woverviewhsv.h @@ -0,0 +1,15 @@ +#ifndef WOVERVIEWHSV_H +#define WOVERVIEWHSV_H + +#include "widget/woverview.h" + +class WOverviewHSV : public WOverview +{ + public: + WOverviewHSV(const char *pGroup, ConfigObject* pConfig, QWidget * parent); + + private: + virtual bool drawNextPixmapPart(); +}; + +#endif // WOVERVIEWHSV_H diff --git a/src/widget/woverviewlmh.cpp b/src/widget/woverviewlmh.cpp new file mode 100644 index 000000000000..67faa28d5bde --- /dev/null +++ b/src/widget/woverviewlmh.cpp @@ -0,0 +1,126 @@ +#include "woverviewlmh.h" + +#include "util/timer.h" + +#include "waveform/waveform.h" + + +WOverviewLMH::WOverviewLMH(const char *pGroup, + ConfigObject* pConfig, QWidget * parent) + : WOverview(pGroup, pConfig, parent) { +} + + +bool WOverviewLMH::drawNextPixmapPart() +{ + ScopedTimer t("WOverviewLMH::drawNextPixmapPart"); + + //qDebug() << "WOverview::drawNextPixmapPart() - m_waveform" << m_waveform; + + int currentCompletion; + + if (!m_pWaveform) { + return false; + } + + const int dataSize = m_pWaveform->getDataSize(); + if (dataSize == 0 ) { + return false; + } + + if (!m_pWaveformSourceImage) { + // Waveform pixmap twice the height of the viewport to be scalable + // by total_gain + // We keep full range waveform data to scale it on paint + m_pWaveformSourceImage = new QImage(dataSize / 2, 2 * 255, + QImage::Format_ARGB32_Premultiplied); + m_pWaveformSourceImage->fill(QColor(0,0,0,0).value()); + } + + // Always multiple of 2 + const int waveformCompletion = m_pWaveform->getCompletion(); + // Test if there is some new to draw (at least of pixel width) + const int completionIncrement = waveformCompletion - m_actualCompletion; + + int visiblePixelIncrement = completionIncrement * width() / dataSize; + if (completionIncrement < 2 || visiblePixelIncrement == 0) { + return false; + } + + if (!m_pWaveform->getMutex()->tryLock()) { + return false; + } + + const int nextCompletion = m_actualCompletion + completionIncrement; + + //qDebug() << "WOverview::drawNextPixmapPart() - nextCompletion:" + // << nextCompletion + // << "m_actualCompletion:" << m_actualCompletion + // << "waveformCompletion:" << waveformCompletion + // << "completionIncrement:" << completionIncrement; + + + QPainter painter(m_pWaveformSourceImage); + painter.translate(0.0,(double)m_pWaveformSourceImage->height()/2.0); + + QColor lowColor = m_signalColors.getLowColor(); + QPen lowColorPen(QBrush(lowColor), 1); + + QColor midColor = m_signalColors.getMidColor(); + QPen midColorPen(QBrush(midColor), 1); + + QColor highColor = m_signalColors.getHighColor(); + QPen highColorPen(QBrush(highColor), 1); + + for (currentCompletion = m_actualCompletion; + currentCompletion < nextCompletion; currentCompletion += 2) { + unsigned char lowNeg = m_pWaveform->getLow(currentCompletion); + unsigned char lowPos = m_pWaveform->getLow(currentCompletion+1); + if (lowPos || lowNeg) { + painter.setPen(lowColorPen); + painter.drawLine(QPoint(currentCompletion / 2, -lowNeg), + QPoint(currentCompletion / 2, lowPos)); + } + } + + for (currentCompletion = m_actualCompletion; + currentCompletion < nextCompletion; currentCompletion += 2) { + painter.setPen(midColorPen); + painter.drawLine(QPoint(currentCompletion / 2, + -m_pWaveform->getMid(currentCompletion)), + QPoint(currentCompletion / 2, + m_pWaveform->getMid(currentCompletion+1))); + } + + for (currentCompletion = m_actualCompletion; + currentCompletion < nextCompletion; currentCompletion += 2) { + painter.setPen(highColorPen); + painter.drawLine(QPoint(currentCompletion / 2, + -m_pWaveform->getHigh(currentCompletion)), + QPoint(currentCompletion / 2, + m_pWaveform->getHigh(currentCompletion+1))); + } + + // Evaluate waveform ratio peak + + for (currentCompletion = m_actualCompletion; + currentCompletion < nextCompletion; currentCompletion += 2) { + m_waveformPeak = math_max(m_waveformPeak, + (float)m_pWaveform->getAll(currentCompletion)); + m_waveformPeak = math_max(m_waveformPeak, + (float)m_pWaveform->getAll(currentCompletion+1)); + } + + m_actualCompletion = nextCompletion; + m_waveformImageScaled = QImage(); + m_diffGain = 0; + + // Test if the complete waveform is done + if (m_actualCompletion >= dataSize - 2) { + m_pixmapDone = true; + //qDebug() << "m_waveformPeakRatio" << m_waveformPeak; + } + + m_pWaveform->getMutex()->unlock(); + return true; +} diff --git a/src/widget/woverviewlmh.h b/src/widget/woverviewlmh.h new file mode 100644 index 000000000000..b0a433e77640 --- /dev/null +++ b/src/widget/woverviewlmh.h @@ -0,0 +1,15 @@ +#ifndef WOVERVIEWLMH_H +#define WOVERVIEWLMH_H + +#include "widget/woverview.h" + +class WOverviewLMH : public WOverview +{ + public: + WOverviewLMH(const char *pGroup, ConfigObject* pConfig, QWidget * parent); + + private: + virtual bool drawNextPixmapPart(); +}; + +#endif // WOVERVIEWLMH_H