1 //=========================================================
2 // MusE
3 // Linux Music Editor
4 // $Id: ./muse/widgets/bigtime.cpp $
5 //
6 // Copyright (C) 1999-2011 by Werner Schweer and others
7 //
8 // This program is free software; you can redistribute it and/or
9 // modify it under the terms of the GNU General Public License
10 // as published by the Free Software Foundation; version 2 of
11 // the License, or (at your option) any later version.
12 //
13 // This program is distributed in the hope that it will be useful,
14 // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 // GNU General Public License for more details.
17 //
18 // You should have received a copy of the GNU General Public License
19 // along with this program; if not, write to the Free Software
20 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
21 //
22 //=========================================================
23 //#include <stdio.h>
24 #include <limits.h>
25 #include "muse_math.h"
26
27 #include <QCheckBox>
28 #include <QLabel>
29 #include <QResizeEvent>
30 #include <QPainter>
31
32 #include "sync.h"
33 #include "sig.h"
34 #include "globals.h"
35 #include "bigtime.h"
36 #include "app.h"
37 #include "gconfig.h"
38 #include "audio.h"
39
40 namespace MusEGlobal {
41 extern int mtcType;
42 }
43
44 namespace MusEGui {
45
46 //
47 // the bigtime widget
48 // display is split into several parts to avoid flickering.
49 //
50
51 //---------------------------------------------------------
52 // BigTime
53 //---------------------------------------------------------
54
BigTime(QWidget * parent)55 BigTime::BigTime(QWidget* parent)
56 : QWidget(parent, Qt::Window | Qt::WindowStaysOnTopHint) // Possibly also Qt::X11BypassWindowManagerHint
57 {
58 _curPos = 0;
59 tickmode = true;
60 dwin = new QWidget(this, Qt::WindowStaysOnTopHint); // Possibly also Qt::X11BypassWindowManagerHint
61 dwin->setObjectName("bigtime-dwin");
62 dwin->setSizePolicy(QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding));
63 dwin->setStyleSheet("QWidget {font-size:10px; font-family:'Courier'}"); // Tim p4.0.8
64
65 fmtButton = new QCheckBox(QString(""), this);
66 fmtButton->resize(18,18);
67 fmtButton->setChecked(true);
68 fmtButton->setToolTip(tr("Format display"));
69 fmtButton->setFocusPolicy(Qt::NoFocus);
70 barLabel = new QLabel(dwin);
71 beatLabel = new QLabel(dwin);
72 tickLabel = new QLabel(dwin);
73 //hourLabel = new QLabel(dwin);
74 minLabel = new QLabel(dwin);
75 secLabel = new QLabel(dwin);
76 frameLabel = new QLabel(dwin);
77 subFrameLabel = new QLabel(dwin);
78 sep1 = new QLabel(QString("."), dwin);
79 sep2 = new QLabel(QString("."), dwin);
80 sep3 = new QLabel(QString(":"), dwin);
81 sep4 = new QLabel(QString(":"), dwin);
82 sep5 = new QLabel(QString(":"), dwin);
83 absTickLabel = new QLabel(dwin);
84 absFrameLabel = new QLabel(dwin);
85 barLabel->setToolTip(tr("Bar"));
86 beatLabel->setToolTip(tr("Beat"));
87 tickLabel->setToolTip(tr("Tick"));
88 //hourLabel->setToolTip(tr("hour"));
89 minLabel->setToolTip(tr("Minute"));
90 secLabel->setToolTip(tr("Second"));
91 frameLabel->setToolTip(tr("Frame"));
92 subFrameLabel->setToolTip(tr("Subframe"));
93 absTickLabel->setToolTip(tr("Tick"));
94 absFrameLabel->setToolTip(tr("Frame"));
95 fmtButtonToggled(true);
96 connect(fmtButton, SIGNAL(toggled(bool)), SLOT(fmtButtonToggled(bool)));
97 //oldbar = oldbeat = oldtick = oldhour = oldmin = oldsec = oldframe = -1;
98 oldbar = oldbeat = oldtick = oldmin = oldsec = oldframe = oldsubframe = -1;
99 oldAbsTick = oldAbsFrame = -1;
100 setString(INT_MAX);
101 metronome = new VerticalMetronomeWidget(dwin);
102
103 configChanged();
104
105 setWindowTitle(tr("MusE: Bigtime"));
106 }
107
108 //---------------------------------------------------------
109 // fmtButtonToggled
110 //---------------------------------------------------------
111
fmtButtonToggled(bool v)112 void BigTime::fmtButtonToggled(bool v)
113 {
114 if(v)
115 {
116 tickmode = true;
117
118 barLabel->setEnabled(true);
119 beatLabel->setEnabled(true);
120 tickLabel->setEnabled(true);
121 //hourLabel->setEnabled(true);
122 minLabel->setEnabled(true);
123 secLabel->setEnabled(true);
124 frameLabel->setEnabled(true);
125 subFrameLabel->setEnabled(true);
126 sep1->setEnabled(true);
127 sep2->setEnabled(true);
128 sep3->setEnabled(true);
129 sep4->setEnabled(true);
130 sep5->setEnabled(true);
131 absTickLabel->setEnabled(false);
132 absFrameLabel->setEnabled(false);
133
134 barLabel->show();
135 beatLabel->show();
136 tickLabel->show();
137 //hourLabel->show();
138 minLabel->show();
139 secLabel->show();
140 frameLabel->show();
141 subFrameLabel->show();
142 sep1->show();
143 sep2->show();
144 sep3->show();
145 sep4->show();
146 sep5->show();
147 absTickLabel->hide();
148 absFrameLabel->hide();
149 }
150 else
151 {
152 tickmode = false;
153
154 barLabel->setEnabled(false);
155 beatLabel->setEnabled(false);
156 tickLabel->setEnabled(false);
157 //hourLabel->setEnabled(false);
158 minLabel->setEnabled(false);
159 secLabel->setEnabled(false);
160 frameLabel->setEnabled(false);
161 subFrameLabel->setEnabled(false);
162 sep1->setEnabled(false);
163 sep2->setEnabled(false);
164 sep3->setEnabled(false);
165 sep4->setEnabled(false);
166 sep5->setEnabled(false);
167 absTickLabel->setEnabled(true);
168 absFrameLabel->setEnabled(true);
169
170 barLabel->hide();
171 beatLabel->hide();
172 tickLabel->hide();
173 //hourLabel->hide();
174 minLabel->hide();
175 secLabel->hide();
176 frameLabel->hide();
177 subFrameLabel->hide();
178 sep1->hide();
179 sep2->hide();
180 sep3->hide();
181 sep4->hide();
182 sep5->hide();
183 absTickLabel->show();
184 absFrameLabel->show();
185 }
186 }
187
188 //---------------------------------------------------------
189 // configChanged
190 //---------------------------------------------------------
191
configChanged()192 void BigTime::configChanged()
193 {
194 setBgColor(MusEGlobal::config.bigTimeBackgroundColor);
195 setFgColor(MusEGlobal::config.bigTimeForegroundColor);
196 }
197
198 //---------------------------------------------------------
199 // songChanged
200 //---------------------------------------------------------
201
songChanged(MusECore::SongChangedStruct_t flags)202 void BigTime::songChanged(MusECore::SongChangedStruct_t flags)
203 {
204 if (flags & (SC_MASTER | SC_TEMPO | SC_SIG))
205 updateValue();
206 }
207
208 //---------------------------------------------------------
209 // closeEvent
210 //---------------------------------------------------------
211
closeEvent(QCloseEvent * ev)212 void BigTime::closeEvent(QCloseEvent *ev)
213 {
214 emit closed();
215 QWidget::closeEvent(ev);
216 }
217
218 //---------------------------------------------------------
219 // setString
220 //---------------------------------------------------------
221
setString(unsigned v)222 bool BigTime::setString(unsigned v)
223 {
224 if (v == INT_MAX) {
225 barLabel->setText(QString("----"));
226 beatLabel->setText(QString("--"));
227 tickLabel->setText(QString("---"));
228 //hourLabel->setText(QString("--"));
229 //minLabel->setText(QString("--"));
230 minLabel->setText(QString("---"));
231 secLabel->setText(QString("--"));
232 frameLabel->setText(QString("--"));
233 subFrameLabel->setText(QString("--"));
234
235 absTickLabel->setText(QString("----------"));
236 absFrameLabel->setText(QString("----------"));
237 oldAbsTick = oldAbsFrame = -1;
238 //oldbar = oldbeat = oldtick = oldhour = oldmin = oldsec = oldframe = -1;
239 oldbar = oldbeat = oldtick = oldmin = oldsec = oldframe = oldsubframe = -1;
240 return true;
241 }
242
243 // Quick fix: Not much to do but ignore the supplied tick: We need the exact frame here.
244 unsigned absFrame = MusEGlobal::audio->pos().frame();
245
246 int bar, beat;
247 unsigned tick;
248 MusEGlobal::sigmap.tickValues(v, &bar, &beat, &tick);
249 double time = double(absFrame)/double(MusEGlobal::sampleRate);
250 //int hour = int(time) / 3600;
251 //int min = (int(time) / 60) % 60;
252 int min = int(time) / 60;
253 int sec = int(time) % 60;
254 double rest = time - (min * 60 + sec);
255 switch(MusEGlobal::mtcType) {
256 case 0: // 24 frames sec
257 rest *= 24;
258 break;
259 case 1: // 25
260 rest *= 25;
261 break;
262 case 2: // 30 drop frame
263 rest *= 30;
264 break;
265 case 3: // 30 non drop frame
266 rest *= 30;
267 break;
268 }
269 int frame = int(rest);
270 int subframe = int((rest-frame)*100);
271
272 QString s;
273
274 if(oldAbsTick != v) {
275 s = QString("%1").arg(v, 10, 10, QLatin1Char('0'));
276 absTickLabel->setText(s);
277 oldAbsTick = v;
278 }
279 if(oldAbsFrame != absFrame) {
280 s = QString("%1").arg(absFrame, 10, 10, QLatin1Char('0'));
281 absFrameLabel->setText(s);
282 oldAbsFrame = absFrame;
283 }
284 if(oldbar != bar) {
285 s = QString("%1").arg(bar + 1, 4, 10, QLatin1Char('0'));
286 barLabel->setText(s);
287 oldbar = bar;
288 }
289 if(oldbeat != beat) {
290 s = QString("%1").arg(beat + 1, 2, 10, QLatin1Char('0'));
291 beatLabel->setText(s);
292 oldbeat = beat;
293 }
294
295 if(oldtick != tick) {
296 s = QString("%1").arg(tick, 3, 10, QLatin1Char('0'));
297 tickLabel->setText(s);
298 oldtick = tick;
299 }
300
301 //if(oldhour != hour) {
302 // s = QString("%1").arg(hour, 2, 10, QLatin1Char('0'));
303 // hourLabel->setText(s);
304 // oldhour = hour;
305 //}
306
307 if(oldmin != min) {
308 s = QString("%1").arg(min, 3, 10, QLatin1Char('0'));
309 minLabel->setText(s);
310 oldmin = min;
311 }
312
313 if(oldsec != sec) {
314 s = QString("%1").arg(sec, 2, 10, QLatin1Char('0'));
315 secLabel->setText(s);
316 oldsec = sec;
317 }
318
319 if(oldframe != frame) {
320 s = QString("%1").arg(frame, 2, 10, QLatin1Char('0'));
321 frameLabel->setText(s);
322 oldframe = frame;
323 }
324
325 if(oldsubframe != subframe) {
326 s = QString("%1").arg(subframe, 2, 10, QLatin1Char('0'));
327 subFrameLabel->setText(s);
328 oldsubframe = subframe;
329 }
330
331 return false;
332 }
333
334 //---------------------------------------------------------
335 // setPos
336 //---------------------------------------------------------
337 #define PI 3.14159265
setPos(int idx,unsigned v,bool)338 void BigTime::setPos(int idx, unsigned v, bool)
339 {
340 if (idx == 0)
341 {
342 _curPos = v;
343 int calcV = v%(MusEGlobal::config.midiDivision*2);
344 double rangeAdjuster = PI/double(MusEGlobal::config.midiDivision);
345 metronome->setMetronome(sin(double(calcV)*rangeAdjuster));
346 //printf("calcV=%d rangeAdjuster %f metronomePosition=%f midiDivision=%d\n",v,rangeAdjuster, metronomePosition, MusEGlobal::config.midiDivision);
347 setString(v);
348 }
349 metronome->update();
350 }
351
352 //---------------------------------------------------------
353 // updateValue
354 //---------------------------------------------------------
355
updateValue()356 void BigTime::updateValue()
357 {
358 int calcV = _curPos%(MusEGlobal::config.midiDivision*2);
359 double rangeAdjuster = PI/double(MusEGlobal::config.midiDivision);
360 metronome->setMetronome(sin(double(calcV)*rangeAdjuster));
361 //printf("calcV=%d rangeAdjuster %f metronomePosition=%f midiDivision=%d\n",_curPos,rangeAdjuster, metronomePosition, MusEGlobal::config.midiDivision);
362 setString(_curPos);
363 update();
364 metronome->update();
365 }
366
367 //---------------------------------------------------------
368 // resizeEvent
369 //---------------------------------------------------------
370
resizeEvent(QResizeEvent * ev)371 void BigTime::resizeEvent(QResizeEvent *ev)
372 {
373 QWidget::resizeEvent(ev);
374 dwin->resize(ev->size());
375 QFont f = dwin->font();
376 QFontMetrics fm(f);
377 int fs = f.pixelSize();
378 int hspace = 20;
379 // Width() is obsolete. Qt >= 5.11 use horizontalAdvance().
380 #if QT_VERSION >= 0x050b00
381 int tw = fm.horizontalAdvance(QString("0000.00.00000"));
382 #else
383 int tw = fm.width(QString("0000.00.00000"));
384 #endif
385
386 fs = ((ev->size().width() - hspace*2)*fs) / tw;
387
388 // set min/max
389 if (fs < 10)
390 fs = 10;
391 else if (fs > 256)
392 fs = 256;
393
394 QString fstr = QString("QWidget {font-size:%1px; font-family:'Courier'}").arg(fs); // Tim p4.0.8
395 dwin->setStyleSheet(fstr);
396 setBgColor(MusEGlobal::config.bigTimeBackgroundColor);
397 setFgColor(MusEGlobal::config.bigTimeForegroundColor);
398
399 // Width() is obsolete. Qt >= 5.11 use horizontalAdvance().
400 #if QT_VERSION >= 0x050b00
401 int digitWidth = dwin->fontMetrics().horizontalAdvance(QString("0"));
402 #else
403 int digitWidth = dwin->fontMetrics().width(QString("0"));
404 #endif
405 int vspace = (ev->size().height() - (fs*2)) / 3;
406 int tickY = vspace;
407
408 int timeY = vspace*2 + fs;
409 int absTickY = tickY;
410 int absFrameY = timeY;
411 barLabel->resize(digitWidth*4, fs);
412 beatLabel->resize(digitWidth*2, fs);
413 tickLabel->resize(digitWidth*5, fs);
414 minLabel->resize(digitWidth*3, fs);
415 secLabel->resize(digitWidth*2, fs);
416 frameLabel->resize(digitWidth*2, fs);
417 subFrameLabel->resize(digitWidth*2, fs);
418
419 absTickLabel->resize(digitWidth*10, fs);
420 absFrameLabel->resize(digitWidth*10, fs);
421 sep1->resize(digitWidth, fs);
422 sep2->resize(digitWidth, fs);
423 sep3->resize(digitWidth, fs);
424 sep4->resize(digitWidth, fs);
425 sep5->resize(digitWidth, fs);
426
427 barLabel->move( hspace + (digitWidth*0), tickY);
428 sep1->move( hspace + (digitWidth*4), tickY);
429 beatLabel->move( hspace + (digitWidth*5), tickY);
430 sep2->move( hspace + (digitWidth*7), tickY);
431 tickLabel->move( hspace + (digitWidth*8), tickY);
432
433 minLabel->move( hspace + (digitWidth*0), timeY);
434 sep3->move( hspace + (digitWidth*3), timeY);
435 secLabel->move( hspace + (digitWidth*4), timeY);
436 sep4->move( hspace + (digitWidth*6), timeY);
437 frameLabel->move( hspace + (digitWidth*7), timeY);
438 sep5->move( hspace + (digitWidth*9), timeY);
439 subFrameLabel->move( hspace + (digitWidth*10), timeY);
440
441 absTickLabel->move( hspace + (digitWidth*0), absTickY);
442 absFrameLabel->move( hspace + (digitWidth*0), absFrameY);
443
444 metronome->move(0,dwin->height() - dwin->height()/10);
445 metronome->resize(dwin->width(),dwin->height()/10);
446 }
447
448 //---------------------------------------------------------
449 // setForegroundColor
450 //---------------------------------------------------------
451
setFgColor(QColor c)452 void BigTime::setFgColor(QColor c)
453 {
454 QPalette newpalette(palette());
455 newpalette.setColor(QPalette::Foreground, c);
456 setPalette(newpalette);
457
458 barLabel->setPalette(newpalette);
459 beatLabel->setPalette(newpalette);
460 tickLabel->setPalette(newpalette);
461 //hourLabel->setPalette(newpalette);
462 minLabel->setPalette(newpalette);
463 secLabel->setPalette(newpalette);
464 frameLabel->setPalette(newpalette);
465 subFrameLabel->setPalette(newpalette);
466
467 absTickLabel->setPalette(newpalette);
468 absFrameLabel->setPalette(newpalette);
469 sep1->setPalette(newpalette);
470 sep2->setPalette(newpalette);
471 sep3->setPalette(newpalette);
472 sep4->setPalette(newpalette);
473 sep5->setPalette(newpalette);
474 }
475
476 //---------------------------------------------------------
477 // setBackgroundColor
478 //---------------------------------------------------------
479
setBgColor(QColor c)480 void BigTime::setBgColor(QColor c)
481 {
482 QPalette newpalette(palette());
483 newpalette.setColor(QPalette::Window, c);
484 setPalette(newpalette);
485
486 barLabel->setPalette(newpalette);
487 beatLabel->setPalette(newpalette);
488 tickLabel->setPalette(newpalette);
489 //hourLabel->setPalette(newpalette);
490 minLabel->setPalette(newpalette);
491 secLabel->setPalette(newpalette);
492 frameLabel->setPalette(newpalette);
493 subFrameLabel->setPalette(newpalette);
494
495 absTickLabel->setPalette(newpalette);
496 absFrameLabel->setPalette(newpalette);
497 sep1->setPalette(newpalette);
498 sep2->setPalette(newpalette);
499 sep3->setPalette(newpalette);
500 sep4->setPalette(newpalette);
501 sep5->setPalette(newpalette);
502
503 setPalette(newpalette);
504 }
505
506
507 } // namespace MusEGui
508