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