annotate widgets/Fader.cpp @ 349:369a197737c7

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