changeset 940:77110abca8a1 tonioni

LevelPanWidget alternative without including muting
author Chris Cannam
date Tue, 31 Mar 2015 14:05:39 +0100
parents 8744bb5d9fd0
children d6acb8e36605
files widgets/LevelPanToolButton.cpp widgets/LevelPanToolButton.h widgets/LevelPanWidget.cpp widgets/LevelPanWidget.h
diffstat 4 files changed, 94 insertions(+), 11 deletions(-) [+]
line wrap: on
line diff
--- a/widgets/LevelPanToolButton.cpp	Tue Mar 31 13:06:29 2015 +0100
+++ b/widgets/LevelPanToolButton.cpp	Tue Mar 31 14:05:39 2015 +0100
@@ -68,6 +68,12 @@
     return m_lpw->getPan();
 }
 
+bool
+LevelPanToolButton::includesMute() const
+{
+    return m_lpw->includesMute();
+}
+
 void
 LevelPanToolButton::setImageSize(int pixels)
 {
@@ -96,6 +102,13 @@
 }
 
 void
+LevelPanToolButton::setIncludeMute(bool include)
+{
+    m_lpw->setIncludeMute(include);
+    update();
+}
+
+void
 LevelPanToolButton::setEnabled(bool enabled)
 {
     m_lpw->setEnabled(enabled);
--- a/widgets/LevelPanToolButton.h	Tue Mar 31 13:06:29 2015 +0100
+++ b/widgets/LevelPanToolButton.h	Tue Mar 31 14:05:39 2015 +0100
@@ -33,6 +33,9 @@
     /// Return pan as a value in the range [-1,1]
     float getPan() const;
 
+    /// Discover whether the level range includes muting or not
+    bool includesMute() const;
+
     void setImageSize(int pixels);
 			
 public slots:
@@ -42,8 +45,11 @@
     /// Set pan in the range [-1,1] -- will be rounded
     void setPan(float);
 
+    /// Specify whether the level range should include muting or not
+    void setIncludeMute(bool);
+
     void setEnabled(bool enabled);
-
+    
 signals:
     void levelChanged(float);
     void panChanged(float);
--- a/widgets/LevelPanWidget.cpp	Tue Mar 31 13:06:29 2015 +0100
+++ b/widgets/LevelPanWidget.cpp	Tue Mar 31 14:05:39 2015 +0100
@@ -23,18 +23,20 @@
 
 #include <iostream>
 #include <cmath>
+#include <cassert>
 
 using std::cerr;
 using std::endl;
 
-static const int maxLevel = 4;
+static const int maxLevel = 4; // min is 0, may be mute or not depending on m_includeMute
 static const int maxPan = 2; // range is -maxPan to maxPan
 
 LevelPanWidget::LevelPanWidget(QWidget *parent) :
     QWidget(parent),
     m_level(maxLevel),
     m_pan(0),
-    m_editable(true)
+    m_editable(true),
+    m_includeMute(true)
 {
 }
 
@@ -63,11 +65,42 @@
     return QSize(scaled, scaled);
 }
 
+static int
+db_to_level(double db)
+{
+    // Only if !m_includeMute, otherwise AudioLevel is used.
+    // Levels are: +6 0 -6 -12 -20
+    assert(maxLevel == 4);
+    if (db > 3.) return 4;
+    else if (db > -3.) return 3;
+    else if (db > -9.) return 2;
+    else if (db > -16.) return 1;
+    else return 0;
+}
+
+static double
+level_to_db(int level)
+{
+    // Only if !m_includeMute, otherwise AudioLevel is used.
+    // Levels are: +6 0 -6 -12 -20
+    assert(maxLevel == 4);
+    if (level >= 4) return 6.;
+    else if (level == 3) return 0.;
+    else if (level == 2) return -6.;
+    else if (level == 1) return -12.;
+    else return -20.;
+}
+
 void
 LevelPanWidget::setLevel(float flevel)
 {
-    int level = AudioLevel::multiplier_to_fader
-	(flevel, maxLevel, AudioLevel::ShortFader);
+    int level;
+    if (m_includeMute) {
+        level = AudioLevel::multiplier_to_fader
+            (flevel, maxLevel, AudioLevel::ShortFader);
+    } else {
+        level = db_to_level(AudioLevel::multiplier_to_dB(flevel));
+    }
     if (level < 0) level = 0;
     if (level > maxLevel) level = maxLevel;
     if (level != m_level) {
@@ -80,6 +113,17 @@
     }
 }
 
+float
+LevelPanWidget::getLevel() const
+{
+    if (m_includeMute) {
+        return float(AudioLevel::fader_to_multiplier
+                     (m_level, maxLevel, AudioLevel::ShortFader));
+    } else {
+        return float(AudioLevel::dB_to_multiplier(level_to_db(m_level)));
+    }
+}
+
 void
 LevelPanWidget::setPan(float pan)
 {
@@ -89,6 +133,18 @@
     update();
 }
 
+bool
+LevelPanWidget::isEditable() const
+{
+    return m_editable;
+}
+
+bool
+LevelPanWidget::includesMute() const
+{
+    return m_includeMute;
+}
+
 void
 LevelPanWidget::setEditable(bool editable)
 {
@@ -96,11 +152,12 @@
     update();
 }
 
-float
-LevelPanWidget::getLevel() const
+void
+LevelPanWidget::setIncludeMute(bool include)
 {
-    return float(AudioLevel::fader_to_multiplier
-		 (m_level, maxLevel, AudioLevel::ShortFader));
+    m_includeMute = include;
+    emitLevelChanged();
+    update();
 }
 
 float
@@ -282,7 +339,7 @@
 	pen.setColor(Qt::darkGray);
     }
 
-    if (!asIfEditable && m_level == 0) {
+    if (!asIfEditable && m_includeMute && m_level == 0) {
         pen.setWidthF(thin * 2);
         pen.setCapStyle(Qt::RoundCap);
         paint.setPen(pen);
@@ -302,7 +359,7 @@
 	    paint.setBrush(mapper.map(level));
 	}
 	QRectF clr = cellLightRect(rect, level, m_pan);
-	if (m_level == 0) {
+	if (m_includeMute && m_level == 0) {
 	    paint.drawLine(clr.topLeft(), clr.bottomRight());
 	    paint.drawLine(clr.bottomLeft(), clr.topRight());
 	} else {
--- a/widgets/LevelPanWidget.h	Tue Mar 31 13:06:29 2015 +0100
+++ b/widgets/LevelPanWidget.h	Tue Mar 31 14:05:39 2015 +0100
@@ -38,6 +38,9 @@
     /// Find out whether the widget is editable
     bool isEditable() const;
 
+    /// Discover whether the level range includes muting or not
+    bool includesMute() const;
+
     /// Draw a suitably sized copy of the widget's contents to the given device
     void renderTo(QPaintDevice *, QRectF, bool asIfEditable) const;
 
@@ -52,6 +55,9 @@
 
     /// Specify whether the widget is editable or read-only (default editable)
     void setEditable(bool);
+
+    /// Specify whether the level range should include muting or not
+    void setIncludeMute(bool);
     
 signals:
     void levelChanged(float);
@@ -70,6 +76,7 @@
     int m_level;
     int m_pan;
     bool m_editable;
+    bool m_includeMute;
 
     QSizeF cellSize(QRectF) const;
     QPointF cellCentre(QRectF, int level, int pan) const;