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@1266
|
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@1266
|
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@1266
|
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@1266
|
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@1266
|
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@1266
|
182 setValue(m_value * 1.f);
|
Chris@0
|
183 } else {
|
Chris@1266
|
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@1266
|
209 v = max;
|
Chris@0
|
210 } else if (v < 0.0) {
|
Chris@1266
|
211 v = 0.0;
|
Chris@0
|
212 }
|
Chris@0
|
213
|
Chris@0
|
214 if (m_value != v) {
|
Chris@1266
|
215 m_value = v;
|
Chris@1266
|
216 float db = (float)AudioLevel::multiplier_to_dB(m_value);
|
Chris@187
|
217 QString text;
|
Chris@1266
|
218 if (db <= AudioLevel::DB_FLOOR) {
|
Chris@187
|
219 text = tr("Level: Off");
|
Chris@1266
|
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@1266
|
226 }
|
Chris@682
|
227 cerr << "Fader: setting tooltip to \"" << text << "\"" << endl;
|
Chris@187
|
228 QWidget::setToolTip(text);
|
Chris@1266
|
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@1266
|
246 this->m_peakLeft = peak;
|
Chris@1266
|
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@1266
|
256 this->m_peakRight = peak;
|
Chris@1266
|
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@1266
|
271 AudioLevel::IEC268LongMeter);
|
Chris@0
|
272
|
Chris@0
|
273 painter.drawPixmap(QRect(0, 0, offset_L, 11), m_leds,
|
Chris@1266
|
274 QRect(0, 0, offset_L, 11));
|
Chris@0
|
275
|
Chris@0
|
276 int offset_R = AudioLevel::multiplier_to_fader(m_peakRight, 116,
|
Chris@1266
|
277 AudioLevel::IEC268LongMeter);
|
Chris@0
|
278
|
Chris@0
|
279 painter.drawPixmap(QRect(0, 11, offset_R, 11), m_leds,
|
Chris@1266
|
280 QRect(0, 11, offset_R, 11));
|
Chris@0
|
281
|
Chris@0
|
282 if (m_withoutKnob == false) {
|
Chris@0
|
283
|
Chris@1266
|
284 static const uint knob_width = 29;
|
Chris@1266
|
285 static const uint knob_height = 9;
|
Chris@0
|
286
|
Chris@1266
|
287 int x = AudioLevel::multiplier_to_fader(m_value, 116 - knob_width,
|
Chris@1266
|
288 AudioLevel::LongFader);
|
Chris@0
|
289
|
Chris@1266
|
290 bool clipping = (m_peakLeft > 1.0 || m_peakRight > 1.0);
|
Chris@0
|
291
|
Chris@1266
|
292 painter.drawPixmap(QRect(x, 7, knob_width, knob_height),
|
Chris@1266
|
293 clipping ? m_clip : m_knob,
|
Chris@1266
|
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 }
|