annotate widgets/Fader.cpp @ 1065:85e49aa7fe77 spectrogram-minor-refactor

Fix possible crash when scrolling to end
author Chris Cannam
date Thu, 23 Jun 2016 08:46:20 +0100
parents 4a578a360011
children a34a2a25907c
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 * http://www.hydrogen-music.org
Chris@0 29 */
Chris@0 30
Chris@0 31
Chris@0 32 #include "Fader.h"
Chris@0 33
Chris@0 34 #include "base/AudioLevel.h"
Chris@0 35
Chris@0 36 #include <QMouseEvent>
Chris@0 37 #include <QPixmap>
Chris@0 38 #include <QWheelEvent>
Chris@0 39 #include <QPaintEvent>
Chris@0 40 #include <QPainter>
Chris@187 41 #include <QInputDialog>
Chris@187 42
Chris@187 43 #include <iostream>
Chris@0 44
Chris@0 45 Fader::Fader(QWidget *parent, bool withoutKnob) :
Chris@0 46 QWidget(parent),
Chris@0 47 m_withoutKnob(withoutKnob),
Chris@0 48 m_value(1.0),
Chris@0 49 m_peakLeft(0.0),
Chris@187 50 m_peakRight(0.0),
Chris@857 51 m_mousePressed(false),
Chris@857 52 m_mousePressX(0),
Chris@857 53 m_mousePressValue(0)
Chris@0 54 {
Chris@0 55 setMinimumSize(116, 23);
Chris@0 56 setMaximumSize(116, 23);
Chris@0 57 resize(116, 23);
Chris@0 58
Chris@0 59 QString background_path = ":/icons/fader_background.png";
Chris@0 60 bool ok = m_back.load(background_path);
Chris@0 61 if (ok == false) {
Chris@682 62 cerr << "Fader: Error loading pixmap" << endl;
Chris@0 63 }
Chris@0 64
Chris@0 65 QString leds_path = ":/icons/fader_leds.png";
Chris@0 66 ok = m_leds.load(leds_path);
Chris@0 67 if (ok == false) {
Chris@682 68 cerr << "Error loading pixmap" << endl;
Chris@0 69 }
Chris@0 70
Chris@0 71 QString knob_path = ":/icons/fader_knob.png";
Chris@0 72 ok = m_knob.load(knob_path);
Chris@0 73 if (ok == false) {
Chris@682 74 cerr << "Error loading pixmap" << endl;
Chris@0 75 }
Chris@0 76
Chris@0 77 QString clip_path = ":/icons/fader_knob_red.png";
Chris@0 78 ok = m_clip.load(clip_path);
Chris@0 79 if (ok == false) {
Chris@682 80 cerr << "Error loading pixmap" << endl;
Chris@0 81 }
Chris@0 82 }
Chris@0 83
Chris@0 84 Fader::~Fader()
Chris@0 85 {
Chris@0 86
Chris@0 87 }
Chris@0 88
Chris@0 89 void
Chris@0 90 Fader::mouseMoveEvent(QMouseEvent *ev)
Chris@0 91 {
Chris@141 92 if (ev->button() == Qt::MidButton) {
Chris@187 93 setValue(1.0);
Chris@187 94 emit valueChanged(1.0);
Chris@187 95 update();
Chris@144 96 ev->accept();
Chris@141 97 return;
Chris@141 98 }
Chris@187 99 if (!m_mousePressed) return;
Chris@141 100
Chris@187 101 int x = ev->x();
Chris@187 102 int diff = x - m_mousePressX;
Chris@187 103 if (diff == 0) return;
Chris@0 104
Chris@187 105 int vx = AudioLevel::multiplier_to_fader
Chris@187 106 (m_mousePressValue, getMaxX(), AudioLevel::LongFader);
Chris@0 107
Chris@187 108 vx += diff;
Chris@0 109
Chris@187 110 if (vx > getMaxX()) vx = getMaxX();
Chris@187 111 if (vx < 0) vx = 0;
Chris@187 112
Chris@908 113 float fval = (float)AudioLevel::fader_to_multiplier
Chris@187 114 (vx, getMaxX(), AudioLevel::LongFader);
Chris@0 115
Chris@0 116 setValue(fval);
Chris@0 117 emit valueChanged(fval);
Chris@187 118 ev->accept();
Chris@0 119 }
Chris@0 120
Chris@0 121
Chris@0 122 void
Chris@132 123 Fader::mouseReleaseEvent(QMouseEvent *ev)
Chris@132 124 {
Chris@187 125 if (m_mousePressed) {
Chris@187 126 mouseMoveEvent(ev);
Chris@187 127 m_mousePressed = false;
Chris@187 128 }
Chris@132 129 }
Chris@132 130
Chris@132 131 void
Chris@0 132 Fader::mouseDoubleClickEvent(QMouseEvent *)
Chris@0 133 {
Chris@187 134 bool ok = false;
Chris@908 135 float min = (float)AudioLevel::fader_to_dB
Chris@187 136 (0, getMaxX(), AudioLevel::LongFader);
Chris@908 137 float max = (float)AudioLevel::fader_to_dB
Chris@187 138 (getMaxX(), getMaxX(), AudioLevel::LongFader);
Chris@908 139 float deft = (float)AudioLevel::multiplier_to_dB(m_value);
Chris@187 140
Chris@908 141 float dB = (float)QInputDialog::getDouble
Chris@187 142 (this,
Chris@187 143 tr("Enter new fader level"),
Chris@187 144 tr("New fader level, from %1 to %2 dBFS:").arg(min).arg(max),
Chris@187 145 deft, min, max, 3, &ok);
Chris@187 146
Chris@187 147 if (ok) {
Chris@908 148 float value = (float)AudioLevel::dB_to_multiplier(dB);
Chris@187 149 setValue(value);
Chris@187 150 emit valueChanged(value);
Chris@187 151 update();
Chris@187 152 }
Chris@0 153 }
Chris@0 154
Chris@0 155 void
Chris@0 156 Fader::mousePressEvent(QMouseEvent *ev)
Chris@0 157 {
Chris@187 158 if (ev->button() == Qt::MidButton ||
Chris@187 159 ((ev->button() == Qt::LeftButton) &&
Chris@187 160 (ev->modifiers() & Qt::ControlModifier))) {
Chris@82 161 setValue(1.0);
Chris@82 162 emit valueChanged(1.0);
Chris@82 163 update();
Chris@82 164 return;
Chris@82 165 }
Chris@82 166
Chris@187 167 if (ev->button() != Qt::LeftButton) return;
Chris@187 168 m_mousePressed = true;
Chris@187 169 m_mousePressX = ev->x();
Chris@187 170 m_mousePressValue = getValue();
Chris@0 171 }
Chris@0 172
Chris@0 173
Chris@0 174 void
Chris@0 175 Fader::wheelEvent(QWheelEvent *ev)
Chris@0 176 {
Chris@0 177 ev->accept();
Chris@0 178
Chris@0 179 //!!! needs improvement
Chris@0 180
Chris@0 181 if (ev->delta() > 0) {
Chris@908 182 setValue(m_value * 1.f);
Chris@0 183 } else {
Chris@908 184 setValue(m_value / 1.f);
Chris@0 185 }
Chris@0 186
Chris@0 187 update();
Chris@0 188 emit valueChanged(getValue());
Chris@0 189 }
Chris@0 190
Chris@189 191 void
Chris@189 192 Fader::enterEvent(QEvent *)
Chris@189 193 {
Chris@189 194 emit mouseEntered();
Chris@189 195 }
Chris@189 196
Chris@189 197 void
Chris@189 198 Fader::leaveEvent(QEvent *)
Chris@189 199 {
Chris@189 200 emit mouseLeft();
Chris@189 201 }
Chris@0 202
Chris@0 203 void
Chris@0 204 Fader::setValue(float v)
Chris@0 205 {
Chris@908 206 float max = (float)AudioLevel::dB_to_multiplier(10.0);
Chris@0 207
Chris@0 208 if (v > max) {
Chris@0 209 v = max;
Chris@0 210 } else if (v < 0.0) {
Chris@0 211 v = 0.0;
Chris@0 212 }
Chris@0 213
Chris@0 214 if (m_value != v) {
Chris@0 215 m_value = v;
Chris@908 216 float db = (float)AudioLevel::multiplier_to_dB(m_value);
Chris@187 217 QString text;
Chris@0 218 if (db <= AudioLevel::DB_FLOOR) {
Chris@187 219 text = tr("Level: Off");
Chris@0 220 } else {
Chris@187 221 text = tr("Level: %1%2.%3%4 dB")
Chris@187 222 .arg(db < 0.0 ? "-" : "")
Chris@187 223 .arg(abs(int(db)))
Chris@187 224 .arg(abs(int(db * 10.0) % 10))
Chris@187 225 .arg(abs(int(db * 100.0) % 10));
Chris@0 226 }
Chris@682 227 cerr << "Fader: setting tooltip to \"" << text << "\"" << endl;
Chris@187 228 QWidget::setToolTip(text);
Chris@0 229 update();
Chris@0 230 }
Chris@0 231 }
Chris@0 232
Chris@0 233
Chris@0 234 float
Chris@0 235 Fader::getValue()
Chris@0 236 {
Chris@0 237 return m_value;
Chris@0 238 }
Chris@0 239
Chris@0 240
Chris@0 241
Chris@0 242 void
Chris@0 243 Fader::setPeakLeft(float peak)
Chris@0 244 {
Chris@0 245 if (this->m_peakLeft != peak) {
Chris@0 246 this->m_peakLeft = peak;
Chris@0 247 update();
Chris@0 248 }
Chris@0 249 }
Chris@0 250
Chris@0 251
Chris@0 252 void
Chris@0 253 Fader::setPeakRight(float peak)
Chris@0 254 {
Chris@0 255 if (this->m_peakRight != peak) {
Chris@0 256 this->m_peakRight = peak;
Chris@0 257 update();
Chris@0 258 }
Chris@0 259 }
Chris@0 260
Chris@0 261
Chris@0 262 void
Chris@0 263 Fader::paintEvent(QPaintEvent *)
Chris@0 264 {
Chris@0 265 QPainter painter(this);
Chris@0 266
Chris@0 267 // background
Chris@0 268 painter.drawPixmap(rect(), m_back, QRect(0, 0, 116, 23));
Chris@0 269
Chris@0 270 int offset_L = AudioLevel::multiplier_to_fader(m_peakLeft, 116,
Chris@0 271 AudioLevel::IEC268LongMeter);
Chris@0 272
Chris@0 273 painter.drawPixmap(QRect(0, 0, offset_L, 11), m_leds,
Chris@0 274 QRect(0, 0, offset_L, 11));
Chris@0 275
Chris@0 276 int offset_R = AudioLevel::multiplier_to_fader(m_peakRight, 116,
Chris@0 277 AudioLevel::IEC268LongMeter);
Chris@0 278
Chris@0 279 painter.drawPixmap(QRect(0, 11, offset_R, 11), m_leds,
Chris@0 280 QRect(0, 11, offset_R, 11));
Chris@0 281
Chris@0 282 if (m_withoutKnob == false) {
Chris@0 283
Chris@0 284 static const uint knob_width = 29;
Chris@0 285 static const uint knob_height = 9;
Chris@0 286
Chris@0 287 int x = AudioLevel::multiplier_to_fader(m_value, 116 - knob_width,
Chris@0 288 AudioLevel::LongFader);
Chris@0 289
Chris@0 290 bool clipping = (m_peakLeft > 1.0 || m_peakRight > 1.0);
Chris@0 291
Chris@0 292 painter.drawPixmap(QRect(x, 7, knob_width, knob_height),
Chris@0 293 clipping ? m_clip : m_knob,
Chris@0 294 QRect(0, 0, knob_width, knob_height));
Chris@0 295 }
Chris@0 296 }
Chris@0 297
Chris@187 298 int
Chris@187 299 Fader::getMaxX() const
Chris@187 300 {
Chris@187 301 return 116 - 12;
Chris@187 302 }