annotate widgets/Fader.cpp @ 192:fcc043f75c41

* Avoid unnecessary work and updates when an invisible thumbwheel changes
author Chris Cannam
date Wed, 24 Jan 2007 17:14:24 +0000
parents 5b7472db612b
children 8c00a4d4fc69
rev   line source
Chris@58 1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
Chris@0 2
Chris@0 3 /*
Chris@59 4 Sonic Visualiser
Chris@59 5 An audio file viewer and annotation editor.
Chris@59 6 Centre for Digital Music, Queen Mary, University of London.
Chris@0 7
Chris@59 8 This program is free software; you can redistribute it and/or
Chris@59 9 modify it under the terms of the GNU General Public License as
Chris@59 10 published by the Free Software Foundation; either version 2 of the
Chris@59 11 License, or (at your option) any later version. See the file
Chris@59 12 COPYING included with this distribution for more information.
Chris@0 13 */
Chris@0 14
Chris@0 15 /**
Chris@0 16 * Horizontal audio fader and meter widget.
Chris@0 17 *
Chris@0 18 * Based on the vertical fader and meter widget from the Hydrogen drum
Chris@0 19 * machine. (Any poor taste that has crept in during the
Chris@0 20 * modifications for this application is entirely my own, however.)
Chris@0 21 * The following copyright notice applies to code from this file, and
Chris@0 22 * also to the files in icons/fader_*.png (also modified by me). --cc
Chris@0 23 */
Chris@0 24
Chris@0 25 /**
Chris@0 26 * Hydrogen
Chris@0 27 * Copyright(c) 2002-2005 by Alex >Comix< Cominu [comix@users.sourceforge.net]
Chris@0 28 *
Chris@0 29 * http://www.hydrogen-music.org
Chris@0 30 *
Chris@0 31 * This program is free software; you can redistribute it and/or modify
Chris@0 32 * it under the terms of the GNU General Public License as published by
Chris@0 33 * the Free Software Foundation; either version 2 of the License, or
Chris@0 34 * (at your option) any later version.
Chris@0 35 *
Chris@0 36 * This program is distributed in the hope that it will be useful,
Chris@0 37 * but WITHOUT ANY WARRANTY, without even the implied warranty of
Chris@0 38 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
Chris@0 39 * GNU General Public License for more details.
Chris@0 40 *
Chris@0 41 * You should have received a copy of the GNU General Public License
Chris@0 42 * along with this program; if not, write to the Free Software
Chris@0 43 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Chris@0 44 */
Chris@0 45
Chris@0 46
Chris@0 47 #include "Fader.h"
Chris@0 48
Chris@0 49 #include "base/AudioLevel.h"
Chris@0 50
Chris@0 51 #include <QMouseEvent>
Chris@0 52 #include <QPixmap>
Chris@0 53 #include <QWheelEvent>
Chris@0 54 #include <QPaintEvent>
Chris@0 55 #include <QPainter>
Chris@187 56 #include <QInputDialog>
Chris@187 57
Chris@187 58 #include <iostream>
Chris@0 59
Chris@0 60 Fader::Fader(QWidget *parent, bool withoutKnob) :
Chris@0 61 QWidget(parent),
Chris@0 62 m_withoutKnob(withoutKnob),
Chris@0 63 m_value(1.0),
Chris@0 64 m_peakLeft(0.0),
Chris@187 65 m_peakRight(0.0),
Chris@187 66 m_mousePressed(false)
Chris@0 67 {
Chris@0 68 setMinimumSize(116, 23);
Chris@0 69 setMaximumSize(116, 23);
Chris@0 70 resize(116, 23);
Chris@0 71
Chris@0 72 QString background_path = ":/icons/fader_background.png";
Chris@0 73 bool ok = m_back.load(background_path);
Chris@0 74 if (ok == false) {
Chris@0 75 std::cerr << "Fader: Error loading pixmap" << std::endl;
Chris@0 76 }
Chris@0 77
Chris@0 78 QString leds_path = ":/icons/fader_leds.png";
Chris@0 79 ok = m_leds.load(leds_path);
Chris@0 80 if (ok == false) {
Chris@0 81 std::cerr << "Error loading pixmap" << std::endl;
Chris@0 82 }
Chris@0 83
Chris@0 84 QString knob_path = ":/icons/fader_knob.png";
Chris@0 85 ok = m_knob.load(knob_path);
Chris@0 86 if (ok == false) {
Chris@0 87 std::cerr << "Error loading pixmap" << std::endl;
Chris@0 88 }
Chris@0 89
Chris@0 90 QString clip_path = ":/icons/fader_knob_red.png";
Chris@0 91 ok = m_clip.load(clip_path);
Chris@0 92 if (ok == false) {
Chris@0 93 std::cerr << "Error loading pixmap" << std::endl;
Chris@0 94 }
Chris@0 95 }
Chris@0 96
Chris@0 97 Fader::~Fader()
Chris@0 98 {
Chris@0 99
Chris@0 100 }
Chris@0 101
Chris@0 102 void
Chris@0 103 Fader::mouseMoveEvent(QMouseEvent *ev)
Chris@0 104 {
Chris@141 105 if (ev->button() == Qt::MidButton) {
Chris@187 106 setValue(1.0);
Chris@187 107 emit valueChanged(1.0);
Chris@187 108 update();
Chris@144 109 ev->accept();
Chris@141 110 return;
Chris@141 111 }
Chris@187 112 if (!m_mousePressed) return;
Chris@141 113
Chris@187 114 int x = ev->x();
Chris@187 115 int diff = x - m_mousePressX;
Chris@187 116 if (diff == 0) return;
Chris@0 117
Chris@187 118 int vx = AudioLevel::multiplier_to_fader
Chris@187 119 (m_mousePressValue, getMaxX(), AudioLevel::LongFader);
Chris@0 120
Chris@187 121 vx += diff;
Chris@0 122
Chris@187 123 if (vx > getMaxX()) vx = getMaxX();
Chris@187 124 if (vx < 0) vx = 0;
Chris@187 125
Chris@0 126 float fval = AudioLevel::fader_to_multiplier
Chris@187 127 (vx, getMaxX(), AudioLevel::LongFader);
Chris@0 128
Chris@0 129 setValue(fval);
Chris@0 130 emit valueChanged(fval);
Chris@187 131 ev->accept();
Chris@0 132 }
Chris@0 133
Chris@0 134
Chris@0 135 void
Chris@132 136 Fader::mouseReleaseEvent(QMouseEvent *ev)
Chris@132 137 {
Chris@187 138 if (m_mousePressed) {
Chris@187 139 mouseMoveEvent(ev);
Chris@187 140 m_mousePressed = false;
Chris@187 141 }
Chris@132 142 }
Chris@132 143
Chris@132 144 void
Chris@0 145 Fader::mouseDoubleClickEvent(QMouseEvent *)
Chris@0 146 {
Chris@187 147 bool ok = false;
Chris@187 148 float min = AudioLevel::fader_to_dB
Chris@187 149 (0, getMaxX(), AudioLevel::LongFader);
Chris@187 150 float max = AudioLevel::fader_to_dB
Chris@187 151 (getMaxX(), getMaxX(), AudioLevel::LongFader);
Chris@187 152 float deft = AudioLevel::multiplier_to_dB(m_value);
Chris@187 153
Chris@187 154 float dB = QInputDialog::getDouble
Chris@187 155 (this,
Chris@187 156 tr("Enter new fader level"),
Chris@187 157 tr("New fader level, from %1 to %2 dBFS:").arg(min).arg(max),
Chris@187 158 deft, min, max, 3, &ok);
Chris@187 159
Chris@187 160 if (ok) {
Chris@187 161 float value = AudioLevel::dB_to_multiplier(dB);
Chris@187 162 setValue(value);
Chris@187 163 emit valueChanged(value);
Chris@187 164 update();
Chris@187 165 }
Chris@0 166 }
Chris@0 167
Chris@0 168 void
Chris@0 169 Fader::mousePressEvent(QMouseEvent *ev)
Chris@0 170 {
Chris@187 171 if (ev->button() == Qt::MidButton ||
Chris@187 172 ((ev->button() == Qt::LeftButton) &&
Chris@187 173 (ev->modifiers() & Qt::ControlModifier))) {
Chris@82 174 setValue(1.0);
Chris@82 175 emit valueChanged(1.0);
Chris@82 176 update();
Chris@82 177 return;
Chris@82 178 }
Chris@82 179
Chris@187 180 if (ev->button() != Qt::LeftButton) return;
Chris@187 181 m_mousePressed = true;
Chris@187 182 m_mousePressX = ev->x();
Chris@187 183 m_mousePressValue = getValue();
Chris@0 184 }
Chris@0 185
Chris@0 186
Chris@0 187 void
Chris@0 188 Fader::wheelEvent(QWheelEvent *ev)
Chris@0 189 {
Chris@0 190 ev->accept();
Chris@0 191
Chris@0 192 //!!! needs improvement
Chris@0 193
Chris@0 194 if (ev->delta() > 0) {
Chris@0 195 setValue(m_value * 1.1);
Chris@0 196 } else {
Chris@0 197 setValue(m_value / 1.1);
Chris@0 198 }
Chris@0 199
Chris@0 200 update();
Chris@0 201 emit valueChanged(getValue());
Chris@0 202 }
Chris@0 203
Chris@189 204 void
Chris@189 205 Fader::enterEvent(QEvent *)
Chris@189 206 {
Chris@189 207 emit mouseEntered();
Chris@189 208 }
Chris@189 209
Chris@189 210 void
Chris@189 211 Fader::leaveEvent(QEvent *)
Chris@189 212 {
Chris@189 213 emit mouseLeft();
Chris@189 214 }
Chris@0 215
Chris@0 216 void
Chris@0 217 Fader::setValue(float v)
Chris@0 218 {
Chris@0 219 float max = AudioLevel::dB_to_multiplier(10.0);
Chris@0 220
Chris@0 221 if (v > max) {
Chris@0 222 v = max;
Chris@0 223 } else if (v < 0.0) {
Chris@0 224 v = 0.0;
Chris@0 225 }
Chris@0 226
Chris@0 227 if (m_value != v) {
Chris@0 228 m_value = v;
Chris@0 229 float db = AudioLevel::multiplier_to_dB(m_value);
Chris@187 230 QString text;
Chris@0 231 if (db <= AudioLevel::DB_FLOOR) {
Chris@187 232 text = tr("Level: Off");
Chris@0 233 } else {
Chris@187 234 text = tr("Level: %1%2.%3%4 dB")
Chris@187 235 .arg(db < 0.0 ? "-" : "")
Chris@187 236 .arg(abs(int(db)))
Chris@187 237 .arg(abs(int(db * 10.0) % 10))
Chris@187 238 .arg(abs(int(db * 100.0) % 10));
Chris@0 239 }
Chris@187 240 std::cerr << "Fader: setting tooltip to \"" << text.toStdString() << "\"" << std::endl;
Chris@187 241 QWidget::setToolTip(text);
Chris@0 242 update();
Chris@0 243 }
Chris@0 244 }
Chris@0 245
Chris@0 246
Chris@0 247 float
Chris@0 248 Fader::getValue()
Chris@0 249 {
Chris@0 250 return m_value;
Chris@0 251 }
Chris@0 252
Chris@0 253
Chris@0 254
Chris@0 255 void
Chris@0 256 Fader::setPeakLeft(float peak)
Chris@0 257 {
Chris@0 258 if (this->m_peakLeft != peak) {
Chris@0 259 this->m_peakLeft = peak;
Chris@0 260 update();
Chris@0 261 }
Chris@0 262 }
Chris@0 263
Chris@0 264
Chris@0 265 void
Chris@0 266 Fader::setPeakRight(float peak)
Chris@0 267 {
Chris@0 268 if (this->m_peakRight != peak) {
Chris@0 269 this->m_peakRight = peak;
Chris@0 270 update();
Chris@0 271 }
Chris@0 272 }
Chris@0 273
Chris@0 274
Chris@0 275 void
Chris@0 276 Fader::paintEvent(QPaintEvent *)
Chris@0 277 {
Chris@0 278 QPainter painter(this);
Chris@0 279
Chris@0 280 // background
Chris@0 281 painter.drawPixmap(rect(), m_back, QRect(0, 0, 116, 23));
Chris@0 282
Chris@0 283 int offset_L = AudioLevel::multiplier_to_fader(m_peakLeft, 116,
Chris@0 284 AudioLevel::IEC268LongMeter);
Chris@0 285
Chris@0 286 painter.drawPixmap(QRect(0, 0, offset_L, 11), m_leds,
Chris@0 287 QRect(0, 0, offset_L, 11));
Chris@0 288
Chris@0 289 int offset_R = AudioLevel::multiplier_to_fader(m_peakRight, 116,
Chris@0 290 AudioLevel::IEC268LongMeter);
Chris@0 291
Chris@0 292 painter.drawPixmap(QRect(0, 11, offset_R, 11), m_leds,
Chris@0 293 QRect(0, 11, offset_R, 11));
Chris@0 294
Chris@0 295 if (m_withoutKnob == false) {
Chris@0 296
Chris@0 297 static const uint knob_width = 29;
Chris@0 298 static const uint knob_height = 9;
Chris@0 299
Chris@0 300 int x = AudioLevel::multiplier_to_fader(m_value, 116 - knob_width,
Chris@0 301 AudioLevel::LongFader);
Chris@0 302
Chris@0 303 bool clipping = (m_peakLeft > 1.0 || m_peakRight > 1.0);
Chris@0 304
Chris@0 305 painter.drawPixmap(QRect(x, 7, knob_width, knob_height),
Chris@0 306 clipping ? m_clip : m_knob,
Chris@0 307 QRect(0, 0, knob_width, knob_height));
Chris@0 308 }
Chris@0 309 }
Chris@0 310
Chris@187 311 int
Chris@187 312 Fader::getMaxX() const
Chris@187 313 {
Chris@187 314 return 116 - 12;
Chris@187 315 }