lbajardsilogic@0: /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ lbajardsilogic@0: lbajardsilogic@0: /* lbajardsilogic@0: Sonic Visualiser lbajardsilogic@0: An audio file viewer and annotation editor. lbajardsilogic@0: Centre for Digital Music, Queen Mary, University of London. lbajardsilogic@0: lbajardsilogic@0: This program is free software; you can redistribute it and/or lbajardsilogic@0: modify it under the terms of the GNU General Public License as lbajardsilogic@0: published by the Free Software Foundation; either version 2 of the lbajardsilogic@0: License, or (at your option) any later version. See the file lbajardsilogic@0: COPYING included with this distribution for more information. lbajardsilogic@0: */ lbajardsilogic@0: lbajardsilogic@0: /** lbajardsilogic@0: * Horizontal audio fader and meter widget. lbajardsilogic@0: * lbajardsilogic@0: * Based on the vertical fader and meter widget from the Hydrogen drum lbajardsilogic@0: * machine. (Any poor taste that has crept in during the lbajardsilogic@0: * modifications for this application is entirely my own, however.) lbajardsilogic@0: * The following copyright notice applies to code from this file, and lbajardsilogic@0: * also to the files in icons/fader_*.png (also modified by me). --cc lbajardsilogic@0: */ lbajardsilogic@0: lbajardsilogic@0: /** lbajardsilogic@0: * Hydrogen lbajardsilogic@0: * Copyright(c) 2002-2005 by Alex >Comix< Cominu [comix@users.sourceforge.net] lbajardsilogic@0: * http://www.hydrogen-music.org lbajardsilogic@0: */ lbajardsilogic@0: lbajardsilogic@0: lbajardsilogic@0: #include "Fader.h" lbajardsilogic@0: lbajardsilogic@0: #include "base/AudioLevel.h" lbajardsilogic@0: lbajardsilogic@0: #include lbajardsilogic@0: #include lbajardsilogic@0: #include lbajardsilogic@0: #include lbajardsilogic@0: #include lbajardsilogic@0: #include lbajardsilogic@0: lbajardsilogic@0: #include lbajardsilogic@0: lbajardsilogic@0: Fader::Fader(QWidget *parent, bool withoutKnob) : lbajardsilogic@0: QWidget(parent), lbajardsilogic@0: m_withoutKnob(withoutKnob), lbajardsilogic@0: m_value(1.0), lbajardsilogic@0: m_peakLeft(0.0), lbajardsilogic@0: m_peakRight(0.0), lbajardsilogic@0: m_mousePressed(false) lbajardsilogic@0: { lbajardsilogic@0: setMinimumSize(116, 23); lbajardsilogic@0: setMaximumSize(116, 23); lbajardsilogic@0: resize(116, 23); lbajardsilogic@0: lbajardsilogic@0: QString background_path = ":/icons/fader_background.png"; lbajardsilogic@0: bool ok = m_back.load(background_path); lbajardsilogic@0: if (ok == false) { lbajardsilogic@0: std::cerr << "Fader: Error loading pixmap" << std::endl; lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: QString leds_path = ":/icons/fader_leds.png"; lbajardsilogic@0: ok = m_leds.load(leds_path); lbajardsilogic@0: if (ok == false) { lbajardsilogic@0: std::cerr << "Error loading pixmap" << std::endl; lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: QString knob_path = ":/icons/fader_knob.png"; lbajardsilogic@0: ok = m_knob.load(knob_path); lbajardsilogic@0: if (ok == false) { lbajardsilogic@0: std::cerr << "Error loading pixmap" << std::endl; lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: QString clip_path = ":/icons/fader_knob_red.png"; lbajardsilogic@0: ok = m_clip.load(clip_path); lbajardsilogic@0: if (ok == false) { lbajardsilogic@0: std::cerr << "Error loading pixmap" << std::endl; lbajardsilogic@0: } lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: Fader::~Fader() lbajardsilogic@0: { lbajardsilogic@0: lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: void lbajardsilogic@0: Fader::mouseMoveEvent(QMouseEvent *ev) lbajardsilogic@0: { lbajardsilogic@0: if (ev->button() == Qt::MidButton) { lbajardsilogic@0: setValue(1.0); lbajardsilogic@0: emit valueChanged(1.0); lbajardsilogic@0: update(); lbajardsilogic@0: ev->accept(); lbajardsilogic@0: return; lbajardsilogic@0: } lbajardsilogic@0: if (!m_mousePressed) return; lbajardsilogic@0: lbajardsilogic@0: int x = ev->x(); lbajardsilogic@0: int diff = x - m_mousePressX; lbajardsilogic@0: if (diff == 0) return; lbajardsilogic@0: lbajardsilogic@0: int vx = AudioLevel::multiplier_to_fader lbajardsilogic@0: (m_mousePressValue, getMaxX(), AudioLevel::LongFader); lbajardsilogic@0: lbajardsilogic@0: vx += diff; lbajardsilogic@0: lbajardsilogic@0: if (vx > getMaxX()) vx = getMaxX(); lbajardsilogic@0: if (vx < 0) vx = 0; lbajardsilogic@0: lbajardsilogic@0: float fval = AudioLevel::fader_to_multiplier lbajardsilogic@0: (vx, getMaxX(), AudioLevel::LongFader); lbajardsilogic@0: lbajardsilogic@0: setValue(fval); lbajardsilogic@0: emit valueChanged(fval); lbajardsilogic@0: ev->accept(); lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: lbajardsilogic@0: void lbajardsilogic@0: Fader::mouseReleaseEvent(QMouseEvent *ev) lbajardsilogic@0: { lbajardsilogic@0: if (m_mousePressed) { lbajardsilogic@0: mouseMoveEvent(ev); lbajardsilogic@0: m_mousePressed = false; lbajardsilogic@0: } lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: void lbajardsilogic@0: Fader::mouseDoubleClickEvent(QMouseEvent *) lbajardsilogic@0: { lbajardsilogic@0: bool ok = false; lbajardsilogic@0: float min = AudioLevel::fader_to_dB lbajardsilogic@0: (0, getMaxX(), AudioLevel::LongFader); lbajardsilogic@0: float max = AudioLevel::fader_to_dB lbajardsilogic@0: (getMaxX(), getMaxX(), AudioLevel::LongFader); lbajardsilogic@0: float deft = AudioLevel::multiplier_to_dB(m_value); lbajardsilogic@0: lbajardsilogic@0: float dB = QInputDialog::getDouble lbajardsilogic@0: (this, lbajardsilogic@0: tr("Enter new fader level"), lbajardsilogic@0: tr("New fader level, from %1 to %2 dBFS:").arg(min).arg(max), lbajardsilogic@0: deft, min, max, 3, &ok); lbajardsilogic@0: lbajardsilogic@0: if (ok) { lbajardsilogic@0: float value = AudioLevel::dB_to_multiplier(dB); lbajardsilogic@0: setValue(value); lbajardsilogic@0: emit valueChanged(value); lbajardsilogic@0: update(); lbajardsilogic@0: } lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: void lbajardsilogic@0: Fader::mousePressEvent(QMouseEvent *ev) lbajardsilogic@0: { lbajardsilogic@0: if (ev->button() == Qt::MidButton || lbajardsilogic@0: ((ev->button() == Qt::LeftButton) && lbajardsilogic@0: (ev->modifiers() & Qt::ControlModifier))) { lbajardsilogic@0: setValue(1.0); lbajardsilogic@0: emit valueChanged(1.0); lbajardsilogic@0: update(); lbajardsilogic@0: return; lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: if (ev->button() != Qt::LeftButton) return; lbajardsilogic@0: m_mousePressed = true; lbajardsilogic@0: m_mousePressX = ev->x(); lbajardsilogic@0: m_mousePressValue = getValue(); lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: lbajardsilogic@0: void lbajardsilogic@0: Fader::wheelEvent(QWheelEvent *ev) lbajardsilogic@0: { lbajardsilogic@0: ev->accept(); lbajardsilogic@0: lbajardsilogic@0: //!!! needs improvement lbajardsilogic@0: lbajardsilogic@0: if (ev->delta() > 0) { lbajardsilogic@0: setValue(m_value * 1.1); lbajardsilogic@0: } else { lbajardsilogic@0: setValue(m_value / 1.1); lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: update(); lbajardsilogic@0: emit valueChanged(getValue()); lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: void lbajardsilogic@0: Fader::enterEvent(QEvent *) lbajardsilogic@0: { lbajardsilogic@0: emit mouseEntered(); lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: void lbajardsilogic@0: Fader::leaveEvent(QEvent *) lbajardsilogic@0: { lbajardsilogic@0: emit mouseLeft(); lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: void lbajardsilogic@0: Fader::setValue(float v) lbajardsilogic@0: { lbajardsilogic@0: float max = AudioLevel::dB_to_multiplier(10.0); lbajardsilogic@0: lbajardsilogic@0: if (v > max) { lbajardsilogic@0: v = max; lbajardsilogic@0: } else if (v < 0.0) { lbajardsilogic@0: v = 0.0; lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: if (m_value != v) { lbajardsilogic@0: m_value = v; lbajardsilogic@0: float db = AudioLevel::multiplier_to_dB(m_value); lbajardsilogic@0: QString text; lbajardsilogic@0: if (db <= AudioLevel::DB_FLOOR) { lbajardsilogic@0: text = tr("Level: Off"); lbajardsilogic@0: } else { lbajardsilogic@0: text = tr("Level: %1%2.%3%4 dB") lbajardsilogic@0: .arg(db < 0.0 ? "-" : "") lbajardsilogic@0: .arg(abs(int(db))) lbajardsilogic@0: .arg(abs(int(db * 10.0) % 10)) lbajardsilogic@0: .arg(abs(int(db * 100.0) % 10)); lbajardsilogic@0: } lbajardsilogic@0: std::cerr << "Fader: setting tooltip to \"" << text.toStdString() << "\"" << std::endl; lbajardsilogic@0: QWidget::setToolTip(text); lbajardsilogic@0: update(); lbajardsilogic@0: } lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: lbajardsilogic@0: float lbajardsilogic@0: Fader::getValue() lbajardsilogic@0: { lbajardsilogic@0: return m_value; lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: lbajardsilogic@0: lbajardsilogic@0: void lbajardsilogic@0: Fader::setPeakLeft(float peak) lbajardsilogic@0: { lbajardsilogic@0: if (this->m_peakLeft != peak) { lbajardsilogic@0: this->m_peakLeft = peak; lbajardsilogic@0: update(); lbajardsilogic@0: } lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: lbajardsilogic@0: void lbajardsilogic@0: Fader::setPeakRight(float peak) lbajardsilogic@0: { lbajardsilogic@0: if (this->m_peakRight != peak) { lbajardsilogic@0: this->m_peakRight = peak; lbajardsilogic@0: update(); lbajardsilogic@0: } lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: lbajardsilogic@0: void lbajardsilogic@0: Fader::paintEvent(QPaintEvent *) lbajardsilogic@0: { lbajardsilogic@0: QPainter painter(this); lbajardsilogic@0: lbajardsilogic@0: // background lbajardsilogic@0: painter.drawPixmap(rect(), m_back, QRect(0, 0, 116, 23)); lbajardsilogic@0: lbajardsilogic@0: int offset_L = AudioLevel::multiplier_to_fader(m_peakLeft, 116, lbajardsilogic@0: AudioLevel::IEC268LongMeter); lbajardsilogic@0: lbajardsilogic@0: painter.drawPixmap(QRect(0, 0, offset_L, 11), m_leds, lbajardsilogic@0: QRect(0, 0, offset_L, 11)); lbajardsilogic@0: lbajardsilogic@0: int offset_R = AudioLevel::multiplier_to_fader(m_peakRight, 116, lbajardsilogic@0: AudioLevel::IEC268LongMeter); lbajardsilogic@0: lbajardsilogic@0: painter.drawPixmap(QRect(0, 11, offset_R, 11), m_leds, lbajardsilogic@0: QRect(0, 11, offset_R, 11)); lbajardsilogic@0: lbajardsilogic@0: if (m_withoutKnob == false) { lbajardsilogic@0: lbajardsilogic@0: static const uint knob_width = 29; lbajardsilogic@0: static const uint knob_height = 9; lbajardsilogic@0: lbajardsilogic@0: int x = AudioLevel::multiplier_to_fader(m_value, 116 - knob_width, lbajardsilogic@0: AudioLevel::LongFader); lbajardsilogic@0: lbajardsilogic@0: bool clipping = (m_peakLeft > 1.0 || m_peakRight > 1.0); lbajardsilogic@0: lbajardsilogic@0: painter.drawPixmap(QRect(x, 7, knob_width, knob_height), lbajardsilogic@0: clipping ? m_clip : m_knob, lbajardsilogic@0: QRect(0, 0, knob_width, knob_height)); lbajardsilogic@0: } lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: int lbajardsilogic@0: Fader::getMaxX() const lbajardsilogic@0: { lbajardsilogic@0: return 116 - 12; lbajardsilogic@0: }