1
//=============================================================================
3
// Audio Widget Library
6
// Copyright (C) 2002-2006 by Werner Schweer and others
8
// This program is free software; you can redistribute it and/or modify
9
// it under the terms of the GNU General Public License version 2.
11
// This program is distributed in the hope that it will be useful,
12
// but WITHOUT ANY WARRANTY; without even the implied warranty of
13
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
// GNU General Public License for more details.
16
// You should have received a copy of the GNU General Public License
17
// along with this program; if not, write to the Free Software
18
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19
//=============================================================================
25
#include "../muse/gconfig.h"
26
#include "../muse/icons.h"
28
#include "metronom.xpm"
32
inline double exp10(double a) { return pow(10.0, a); }
35
static QIcon* clockIcon;
36
static QIcon* metronomIcon;
38
FollowMode TimeCanvas::followMode = FOLLOW_JUMP;
39
QPixmap* TimeCanvas::octave;
40
QPixmap* TimeCanvas::mk1;
41
QPixmap* TimeCanvas::mk2;
42
QPixmap* TimeCanvas::mk3;
43
QPixmap* TimeCanvas::mk4;
47
DRAG_CANVASA, DRAG_CANVAS_B,
48
DRAG_PANELA, DRAG_PANELB,
52
//---------------------------------------------------------
54
//---------------------------------------------------------
56
TimeCanvas::TimeCanvas(TimeCanvasType t)
59
setAttribute(Qt::WA_NoSystemBackground, true);
64
_timeType = AL::TICKS;
70
dragType = DRAG_OTHER;
74
canvasBackgroundColor = QColor(0x71, 0x8d, 0xbe);
77
clockIcon = new QIcon(QPixmap(clock_xpm));
78
metronomIcon = new QIcon(QPixmap(metronom_xpm));
80
button = Qt::NoButton;
81
grid = new QGridLayout;
86
_widget = new QWidget;
87
_widget->setAttribute(Qt::WA_NoSystemBackground);
88
_widget->setAttribute(Qt::WA_StaticContents);
89
_widget->installEventFilter(this);
90
_widget->setMouseTracking(true);
91
_widget->setAcceptDrops(true);
93
// allow to set slider position before slider range
97
pos2.setTick(INT_MAX);
99
hmag = new QSlider(Qt::Horizontal);
100
hmag->setRange(0, 100);
104
hmag->setValue(xmag2s(_xmag));
107
if (type != TIME_CANVAS_DRUMEDIT) {
108
vmag = new QSlider(Qt::Vertical);
109
vmag->setRange(0, 100);
110
vmag->setPageStep(1);
114
hbar = new QScrollBar(Qt::Horizontal);
115
hbar->setRange(0, INT_MAX);
116
vbar = new QScrollBar(Qt::Vertical);
117
timeTypeButton = new QToolButton;
118
timeTypeButton->setFixedSize(20, rulerHeight);
119
setTimeType1(AL::TICKS);
123
case TIME_CANVAS_PIANOROLL:
126
vmag->setValue(lrint((_ymag-_ymagMin)*100.0/(_ymagMax-_ymagMin)));
129
case TIME_CANVAS_DRUMEDIT:
132
yRange = drumHeight * 128;
134
case TIME_CANVAS_WAVEEDIT:
148
if (type == TIME_CANVAS_PIANOROLL || type == TIME_CANVAS_DRUMEDIT
149
|| type == TIME_CANVAS_WAVEEDIT) {
150
addCtrlButton = new QPushButton(tr("Ctrl"), _widget);
151
addCtrlButton->setGeometry(1, 1, rPanelA.width()-4, rulerHeight-4);
152
addCtrlButton->setToolTip(tr("Add Controller View"));
153
connect(addCtrlButton, SIGNAL(clicked()), SLOT(addCtrlClicked()));
156
grid->addWidget(_widget, 0, 0, 3, 2);
157
grid->addWidget(hbar, 3, 0, Qt::AlignVCenter);
158
grid->addWidget(hmag, 3, 1, Qt::AlignVCenter);
159
grid->addWidget(timeTypeButton, 0, 2);
160
grid->addWidget(vbar, 1, 2, Qt::AlignHCenter);
162
grid->addWidget(vmag, 2, 2, Qt::AlignHCenter);
164
grid->setColumnStretch(0, 100);
165
grid->setRowStretch(1, 100);
169
connect(hbar, SIGNAL(valueChanged(int)), SLOT(moveX(int)));
170
connect(vbar, SIGNAL(valueChanged(int)), SLOT(moveY(int)));
171
connect(hmag, SIGNAL(valueChanged(int)), SLOT(scaleX(int)));
173
connect(vmag, SIGNAL(valueChanged(int)), SLOT(scaleY(int)));
174
connect(timeTypeButton, SIGNAL(clicked()), SLOT(toggleTimeType()));
177
//---------------------------------------------------------
179
//---------------------------------------------------------
181
void TimeCanvas::resizeController(int h)
185
int updateH = h > ctrlHeight ? h : ctrlHeight;
189
widget()->update(0, widget()->height() - updateH, widget()->width(), updateH);
192
//---------------------------------------------------------
194
//---------------------------------------------------------
196
bool TimeCanvas::eventFilter(QObject* obj, QEvent* event)
199
return QFrame::eventFilter(obj, event);
201
switch(event->type()) {
205
canvasPaintEvent(((QPaintEvent*)event)->rect(), p);
215
case QEvent::MouseButtonDblClick:
217
QMouseEvent* me = (QMouseEvent*)event;
219
button = me->button();
220
keyState = me->modifiers();
221
mouseDoubleClick(me);
225
case QEvent::MouseButtonPress:
227
QMouseEvent* me = (QMouseEvent*)event;
228
keyState = me->modifiers();
229
button = me->button();
231
int x = p.x() - rRuler.x();
232
bool shift = keyState & Qt::ShiftModifier;
234
if (rRuler.contains(p)) {
235
dragType = DRAG_RULER;
237
AL::Pos pos(pix2pos(x));
238
if (button == Qt::LeftButton)
240
else if (button == Qt::RightButton)
241
emit removeMarker(pos);
246
dragType = DRAG_OTHER;
250
// go on with MouseMove
252
case QEvent::MouseMove:
254
QMouseEvent* me = (QMouseEvent*)event;
255
keyState = me->modifiers();
256
button = me->buttons();
258
AL::Pos pos(pix2pos(p.x()-rCanvasA.x()));
260
if (dragType == DRAG_OTHER) {
261
if (button == 0 && (rPanelB.contains(p) || rCanvasB.contains(p))) {
268
if (button == 0 && mouseInB) {
274
if (showCursor && p.x() < rCanvasA.x()) {
276
widget()->update(rRuler);
277
emit cursorPos(cursor, showCursor);
280
if (p.x() >= rCanvasA.x() && (cursor != pos)) {
281
int x1 = pos2pix(cursor) + rCanvasA.x();
282
int x2 = pos2pix(pos) + rCanvasA.x();
283
QRect r1(x1-1, 0, 2, rRuler.height());
284
QRect r2(x2-1, 0, 2, rRuler.height());
285
widget()->update(rRuler & (r1 | r2));
288
emit cursorPos(cursor, showCursor);
291
if (rRuler.contains(p)) {
292
int b = me->buttons();
296
if (b & Qt::MidButton)
298
else if (b & Qt::RightButton)
300
if (keyState & Qt::ShiftModifier)
302
emit posChanged(i, pos);
308
else if (dragType == DRAG_RULER) {
309
int b = me->buttons();
313
if (b & Qt::MidButton)
315
else if (b & Qt::RightButton)
317
if (keyState & Qt::ShiftModifier)
319
emit posChanged(i, pos);
324
case QEvent::MouseButtonRelease:
326
QMouseEvent* me = (QMouseEvent*)event;
327
button = Qt::NoButton;
328
keyState = me->modifiers();
330
dragType = DRAG_OTHER;
334
case QEvent::DragEnter:
335
dragEnter((QDragEnterEvent*)event);
339
drop((QDropEvent*)event);
342
case QEvent::DragMove:
343
dragMove((QDragMoveEvent*)event);
346
case QEvent::DragLeave:
347
dragLeave((QDragLeaveEvent*)event);
352
emit cursorPos(cursor, false);
354
emit pitchChanged(-1);
357
if (!rPanelA.isEmpty())
363
// button = ((QMouseEvent*)event)->buttons();
371
QWheelEvent* e = (QWheelEvent*)event;
372
if (e->orientation() != Qt::Vertical)
374
if ((e->modifiers() & Qt::ControlModifier) || (e->modifiers() & Qt::ShiftModifier)) {
378
int oldx = e->x() - rCanvasA.x();
379
AL::Pos pos(pix2pos(oldx));
380
int step = e->delta() / 120;
382
for (int i = 0; i< step; ++i)
386
for (int i = 0; i < -step; ++i)
389
if (_xmag < _xmagMin)
391
else if (_xmag > _xmagMax)
393
hmag->setValue(xmag2s(_xmag));
394
int newx = pos2pix(pos);
396
hbar->setValue(wpos.x() + (newx - oldx));
405
int step = qMin(QApplication::wheelScrollLines() * vbar->singleStep(), vbar->pageStep());
406
int offset = e->delta() * step / 120;
407
if (vbar->invertedControls())
409
if (qAbs(offset) < 1)
411
vbar->setValue(vbar->value() + offset);
416
// printf("event %d missed\n", event->type());
424
void TimeCanvas::keyPressEvent(QKeyEvent *e)
426
if (e->key() == Qt::Key_Up || e->key() == Qt::Key_Down ||
427
e->key() == Qt::Key_Left || e->key() == Qt::Key_Right)
431
//---------------------------------------------------------
433
//---------------------------------------------------------
435
void TimeCanvas::moveX(int x)
437
int dx = wpos.x() - x;
440
int wh = _widget->height();
442
if (type == TIME_CANVAS_PIANOROLL || type == TIME_CANVAS_DRUMEDIT
443
|| TIME_CANVAS_WAVEEDIT) {
444
_widget->scroll(dx, 0, QRect(rCanvasA.x(), 0, rCanvasA.width(), wh));
447
// update controller names
448
int w = 100 + ((dx > 0) ? dx : 0);
449
_widget->update(rCanvasB.x(), rCanvasB.y(), w, rCanvasB.height());
452
// repaint rounded line end (splitter handle for controller
454
int x = rCanvasB.x() + rCanvasB.width() - 1;
460
_widget->update(x, rCanvasB.y(), w, rCanvasB.height());
463
_widget->scroll(dx, 0);
464
emit contentsMoving(wpos.x(), wpos.y());
467
//---------------------------------------------------------
469
//---------------------------------------------------------
471
void TimeCanvas::moveY(int y)
473
int dy = wpos.y() - y;
480
int ww = _widget->width();
481
int wh = _widget->height();
483
QRect r(0, rulerHeight, ww, wh - rulerHeight - ctrlHeight);
485
_widget->scroll(0, dy, r);
486
emit contentsMoving(wpos.x(), wpos.y());
489
//---------------------------------------------------------
491
//---------------------------------------------------------
493
void TimeCanvas::setYPos(int y)
495
setWPos(QPoint(wpos.x(), y));
498
//---------------------------------------------------------
500
//---------------------------------------------------------
502
void TimeCanvas::setWPos(const QPoint& p)
506
hbar->setValue(wpos.x());
507
vbar->setValue(wpos.y());
509
// QCoreApplication::flush();
513
//---------------------------------------------------------
515
//---------------------------------------------------------
517
void TimeCanvas::paintClockRuler(QPainter& p, const QRect& r)
520
int x2 = x1 + r.width();
524
if (y1 < rulerHeight) {
525
rh -= rulerHeight - y1;
530
//---------------------------------------------------
532
//---------------------------------------------------
534
int y = rulerHeight - 16;
541
for (AL::iMarker m = marker->begin(); m != marker->end(); ++m) {
542
int xp = mapx(int(m->second.frame()));
548
if (mm != marker->end()) {
549
xe = mapx(mm->first);
551
QRect tr(xp, 0, x2 - xp, 11);
552
if (m->second.current()) {
553
p.fillRect(tr, Qt::white);
555
if (r.intersects(tr)) {
559
if (mm != marker->end())
560
x2 = mapx(mm->first);
563
QRect r = QRect(xp+10, 0, x2-xp, 12);
564
p.drawPixmap(xp, 0, *flagIconS);
565
p.drawText(r, Qt::AlignLeft|Qt::AlignVCenter, m->second.name());
572
int xp = pos2pix(cursor);
573
if (xp >= x1 && xp < x2)
574
p.drawLine(xp, 0, xp, rulerHeight);
577
AL::Pos p1(pix2pos(x1));
578
AL::Pos p2(pix2pos(x2));
580
int sec1 = p1.frame() / AL::sampleRate;
581
int sec2 = (p2.frame() + AL::sampleRate - 1) / AL::sampleRate;
583
int sw = lrint(AL::sampleRate * _xmag);
586
for (int sec = sec1; sec < sec2; ++sec) {
594
s.sprintf("%d:00", min);
599
s.sprintf("%02d", sr);
602
int xp = pos2pix(AL::Pos(sec * AL::sampleRate, AL::FRAMES));
603
// printf(" sec %d min %d sr %d xp %d\n", sec, min, sr, xp);
605
p.drawLine(xp, yy, xp, rulerHeight);
606
p.drawText(xp + 2, rulerHeight - 4, s);
607
p.setPen(sr == 0 ? Qt::lightGray : Qt::gray);
608
p.drawLine(xp, y1, xp, y2);
613
int min2 = (sec2+59)/60;
614
for (int min = min1; min < min2; ++min) {
617
s.sprintf("%d", min);
618
int xp = pos2pix(AL::Pos(min * AL::sampleRate * 60, AL::FRAMES));
620
p.drawLine(xp, y, xp, rulerHeight);
621
p.drawText(xp + 2, rulerHeight - 4, s);
622
p.setPen(Qt::lightGray);
623
p.drawLine(xp, y1, xp, y2);
628
//---------------------------------------------------------
630
//---------------------------------------------------------
632
void TimeCanvas::updateRulerMag()
634
int bar1, beat, tick;
635
pos1.mbt(&bar1, &beat, &tick);
636
AL::Pos stick(bar1, 0, 0);
637
AL::Pos ntick = AL::Pos(bar1 + 1, 0, 0);
638
int tpix = pos2pix(ntick) - pos2pix(stick);
639
metronomeRulerMag = 0;
641
metronomeRulerMag = 1;
643
metronomeRulerMag = 2;
645
metronomeRulerMag = 3;
647
metronomeRulerMag = 4;
649
metronomeRulerMag = 5;
651
metronomeRulerMag = 6;
654
//---------------------------------------------------------
655
// paintMetronomRuler
656
//---------------------------------------------------------
658
void TimeCanvas::paintMetronomRuler(QPainter& p, const QRect& r)
660
static const int mag[7] = {
661
1, 1, 2, 5, 10, 20, 50
666
int y = rulerHeight - 16;
673
if (y1 < rulerHeight) {
674
rh -= rulerHeight - y1;
679
if (x < (MAP_OFFSET - wpos.x()))
680
x = MAP_OFFSET - wpos.x();
681
AL::Pos pos1 = pix2pos(x);
682
AL::Pos pos2 = pix2pos(x+w);
685
AL::iMarker start = marker->lower_bound(pos1.tick());
686
if (start != marker->begin())
688
AL::iMarker end = marker->lower_bound(pos2.tick());
689
for (AL::iMarker m = start; m != end; ++m) {
690
AL::Pos pm1(m->second);
694
if (m2 != marker->end())
697
int x1 = pos2pix(pm1);
698
int x2 = pos2pix(pm2);
700
if (pos[0] >= pm1 && (m2 == marker->end() || pos[0] < pm2))
701
p.fillRect(x1, 0, x2 - x1, 11, Qt::white);
703
QRect r = QRect(x1 + 10, 0, x2 - x1, 12);
704
p.drawPixmap(x1, 0, *flagIconS);
705
p.drawText(r, Qt::AlignLeft|Qt::AlignVCenter, m->second.name());
709
//---------------------------------------------------
711
//---------------------------------------------------
713
int bar1, bar2, beat, tick;
714
pos1.mbt(&bar1, &beat, &tick);
715
pos2.mbt(&bar2, &beat, &tick);
717
int n = mag[metronomeRulerMag];
719
bar1 = (bar1 / n) * n; // round down
722
bar2 = ((bar2 + n - 1) / n) * n; // round up
724
for (int bar = bar1; bar <= bar2;) {
725
AL::Pos stick(bar, 0, 0);
726
if (metronomeRulerMag) {
728
int x = pos2pix(stick);
733
p.drawLine(x, y, x, y + h);
734
QRect r = QRect(x+2, y, 1000, h);
735
p.drawText(r, Qt::AlignLeft | Qt::AlignVCenter, s);
736
p.setPen(Qt::lightGray);
738
p.drawLine(x, y1, x, y2);
741
AL::TimeSignature sig = stick.timesig();
743
for (int beat = 0; beat < z; beat++) {
744
AL::Pos xx(bar, beat, 0);
745
int xp = pos2pix(xx);
749
QRect r(xp+2, y + 1, 1000, h);
761
r.moveTop(r.top() + 1);
765
p.drawLine(xp, y3, xp, y+h);
766
p.drawText(r, Qt::AlignLeft | Qt::AlignVCenter, s);
767
p.setPen(beat == 0 ? Qt::lightGray : Qt::gray);
769
p.drawLine(xp, y1, xp, y2);
772
if (bar == 0 && n >= 2)
778
// draw mouse cursor marker
782
int xp = pos2pix(cursor);
783
if (xp >= x && xp < x+w)
784
p.drawLine(xp, 0, xp, rulerHeight-1);
789
//---------------------------------------------------------
791
//---------------------------------------------------------
793
void TimeCanvas::tempoChanged()
795
widget()->update(rCanvasA.x(), 0, rCanvasA.width(), widget()->height());
798
//---------------------------------------------------------
800
//---------------------------------------------------------
802
void TimeCanvas::canvasPaintEvent(const QRect& r, QPainter& p)
804
if (r.intersects(rButton)) {
805
p.fillRect(rButton, QColor(0xe0, 0xe0, 0xe0));
806
p.setPen(QPen(Qt::black, 2));
807
int y = rButton.y() + rButton.height() - 1;
808
p.drawLine(rButton.x(), y, rButton.width(), y);
810
p.setRenderHint(QPainter::TextAntialiasing, true);
812
QRect par = r & rPanelA;
813
if (!(par.isEmpty() || rPanelA.isEmpty())) {
814
if (type == TIME_CANVAS_DRUMEDIT) {
815
paintDrumList(p, par);
817
else if (type == TIME_CANVAS_PIANOROLL) {
820
else if (type == TIME_CANVAS_WAVEEDIT) {
821
p.fillRect(par, QColor(0xe0, 0xe0, 0xe0));
825
QRect pbr(r & rPanelB);
826
QRect hor(r & (rRuler | rCanvasA | rCanvasB));
827
QRect car(r & rCanvasA);
828
QRect cbr(r & rCanvasB);
830
bool drawPanelB = !(pbr.isEmpty() || rPanelB.isEmpty());
831
bool drawRuler = !(hor.isEmpty() || (rRuler.isEmpty() && rCanvasA.isEmpty() && rCanvasB.isEmpty()));
832
bool drawCanvasA = !(car.isEmpty() || rCanvasA.isEmpty());
833
bool drawCanvasB = !(cbr.isEmpty() || rCanvasB.isEmpty());
836
// draw canvas background
840
p.setBrushOrigin(QPoint(car.x() + wpos.x(), car.y() + wpos.y()));
842
if (canvasBackgroundPixmap.isNull()) {
843
if (type == TIME_CANVAS_DRUMEDIT || type == TIME_CANVAS_PIANOROLL
844
|| type == TIME_CANVAS_WAVEEDIT) {
846
// paint inactive area different
848
QColor c = canvasBackgroundColor.darker(150);
849
int x1 = pos2pix(partPos1) + rCanvasA.x();
851
QRect r(rr.x(), rr.y(), x1-rr.x(), rr.height());
853
rr.adjust(x1-rr.x(), 0, 0, 0);
855
int x2 = pos2pix(partPos2) + rCanvasA.x();
856
int xx2 = rr.x() + rr.width();
860
QRect r(x2, rr.y(), xx2-x2, rr.height());
862
rr.adjust(0, 0, -(xx2-x2), 0);
865
p.fillRect(rr, canvasBackgroundColor);
869
p.fillRect(car, canvasBackgroundColor);
872
p.drawTiledPixmap(car, canvasBackgroundPixmap,
873
car.topLeft() + QPoint(wpos));
878
p.fillRect(cbr, canvasBackgroundColor);
880
//---------------------------------------------------
882
//---------------------------------------------------
885
QRect rrr(r & rRuler);
887
p.fillRect(rrr, QColor(0xe0, 0xe0, 0xe0));
889
int x2 = x1 + hor.width();
890
int y1 = rulerHeight - 17;
891
int y2 = rulerHeight - 1;
893
p.setPen(QPen(Qt::black, 1));
894
p.drawLine(x1, y1, x2, y1);
895
p.setPen(QPen(Qt::black, 2));
896
p.drawLine(x1, y2, x2, y2);
898
QPoint off(rRuler.topLeft());
900
if (_timeType == AL::TICKS)
901
paintMetronomRuler(p, hor.translated(-off));
903
paintClockRuler(p, hor.translated(-off));
911
p.setRenderHint(QPainter::Antialiasing, false);
914
QPoint off(rPanelB.topLeft());
916
paintControllerPanel(p, pbr.translated(-off));
921
QPoint off(rCanvasB.topLeft());
923
paintControllerCanvas(p, cbr.translated(-off));
926
//---------------------------------------------------
928
//---------------------------------------------------
931
int y2 = y1 + r.height();
936
int y = rulerHeight - 16;
937
QColor lcColors[3] = { Qt::red, Qt::blue, Qt::blue };
939
for (int i = 0; i < 3; ++i) {
940
p.setPen(lcColors[i]);
941
int xp = pos2pix(pos[i]) + rRuler.x();
942
QPixmap* pm = markIcon[i];
943
int pw = (pm->width() + 1) / 2;
946
if (xp >= x1 && xp < x2) {
947
p.drawPixmap(xp - pw, y-2, *pm);
948
p.drawLine(xp, y1, xp, y2);
954
if (yy1 < rCanvasA.x())
957
AL::iMarker start = marker->lower_bound(pos1.tick());
958
if (start != marker->begin())
960
AL::iMarker end = marker->lower_bound(pos2.tick());
961
if (end != marker->end())
963
for (AL::iMarker m = start; m != end; ++m) {
964
AL::Pos pm(m->second);
965
int x = pos2pix(pm) + rRuler.x();
966
p.drawLine(x, yy1, x, y2);
971
//---------------------------------------------------------
973
//---------------------------------------------------------
975
void TimeCanvas::paintCanvas(QPainter& p, const QRect& cr)
977
QPoint off(rCanvasA.topLeft());
979
if (type == TIME_CANVAS_PIANOROLL) {
980
paintPianorollHorizontalGrid(p, cr);
981
p.setRenderHint(QPainter::Antialiasing, true);
983
else if (type == TIME_CANVAS_DRUMEDIT) {
984
paintDrumeditHorizontalGrid(p, cr);
985
p.setRenderHint(QPainter::Antialiasing, true);
988
off = QPoint(rCanvasA.x(), rCanvasA.y() - wpos.y());
990
paint(p, cr.translated(-off));
994
//---------------------------------------------------------
996
//---------------------------------------------------------
998
void TimeCanvas::setLocatorPos(int idx, const AL::Pos& val, bool follow)
1000
if (pos[idx] == val)
1002
QFontMetrics fm(_font2);
1003
int fw = fm.width("123") + 2;
1004
int w = qMax(markIcon[idx]->width() + 2, fw);
1005
int h = widget()->height();
1007
int x = pos2pix(val);
1008
if (idx == 0 && follow && followPos && followMode != FOLLOW_NO) {
1010
if (followMode == FOLLOW_JUMP) {
1011
int x2 = rRuler.width() - 20;
1013
x2 = rRuler.width();
1016
if (x1 >= rRuler.width())
1021
scroll = x - MAP_OFFSET;
1024
else if (followMode == FOLLOW_CONTINUOUS) {
1025
int x1 = rRuler.width() / 2;
1027
scroll = x - (rRuler.width() / 2);
1031
moveX(wpos.x() + scroll);
1032
hbar->setValue(wpos.x());
1036
int offset = rRuler.x() - (w/2);
1037
int x1 = pos2pix(pos[idx]);
1038
int x2 = pos2pix(val);
1039
QRect oR(x1 + offset, 0, w, h);
1040
QRect nR(x2 + offset, 0, w, h);
1042
widget()->update(oR | nR);
1045
//---------------------------------------------------------
1047
//---------------------------------------------------------
1049
void TimeCanvas::setMag(double x, double y)
1051
if (_xmag == x && _ymag == y)
1056
vmag->setValue(lrint((_ymag-_ymagMin)*100.0/(_ymagMax-_ymagMin)));
1057
hmag->setValue(xmag2s(_xmag));
1064
//---------------------------------------------------------
1066
//---------------------------------------------------------
1068
void TimeCanvas::scaleX(int val)
1070
_xmag = s2xmag(val);
1077
//---------------------------------------------------------
1079
//---------------------------------------------------------
1081
void TimeCanvas::scaleY(int val)
1083
int y = lrint(wpos.y() / _ymag);
1084
_ymag = (_ymagMax - _ymagMin) / 100.0 * val + _ymagMin;
1085
y = lrint(y * _ymag);
1092
//---------------------------------------------------------
1094
// r = 1 - no raster
1095
// 0 - measure raster
1096
// > 1 - tick raster
1097
//---------------------------------------------------------
1099
void TimeCanvas::setRaster(int r)
1107
//---------------------------------------------------------
1109
//---------------------------------------------------------
1111
void TimeCanvas::setTimeRange(const AL::Pos& p1, const AL::Pos& p2)
1113
if (pos1 == p1 && pos2 == p2)
1121
//---------------------------------------------------------
1123
//---------------------------------------------------------
1125
void TimeCanvas::setEndPos(const AL::Pos& p2)
1134
//---------------------------------------------------------
1136
//---------------------------------------------------------
1138
void TimeCanvas::updateScrollBars()
1140
hbar->blockSignals(true);
1141
vbar->blockSignals(true);
1143
int ymax = lrint(yRange * _ymag) - rCanvasA.height();
1146
vbar->setRange(0, ymax);
1147
vbar->setPageStep(rCanvasA.height());
1149
int xmin = lrint(pos1.time(_timeType) * _xmag);
1150
unsigned x2 = pos2.time(_timeType);
1151
int xmax = lrint(x2 * _xmag) - rCanvasA.width();
1152
if (xmax - xmin < 0)
1154
hbar->setRange(xmin, xmax);
1155
hbar->setPageStep(rCanvasA.width());
1156
wpos.setX(hbar->value());
1157
wpos.setY(vbar->value());
1159
hbar->blockSignals(false);
1160
vbar->blockSignals(false);
1163
//---------------------------------------------------------
1165
//---------------------------------------------------------
1167
void TimeCanvas::setTimeType1(AL::TType t)
1170
if (t == AL::TICKS) {
1171
timeTypeButton->setIcon(*metronomIcon);
1172
if (_timeType == AL::FRAMES)
1173
conv = AL::sampleRate / double(AL::division * 120 / 60);
1176
timeTypeButton->setIcon(*clockIcon);
1177
if (_timeType == AL::TICKS)
1178
conv = double(AL::division * 120 / 60) / double(AL::sampleRate);
1189
//---------------------------------------------------------
1191
//---------------------------------------------------------
1193
void TimeCanvas::setTimeType(AL::TType t)
1201
//---------------------------------------------------------
1203
//---------------------------------------------------------
1205
void TimeCanvas::toggleTimeType()
1207
if (_timeType == AL::TICKS)
1208
setTimeType(AL::FRAMES);
1210
setTimeType(AL::TICKS);
1213
//---------------------------------------------------------
1215
//---------------------------------------------------------
1217
void TimeCanvas::setMarkerList(AL::MarkerList* ml)
1225
//---------------------------------------------------------
1227
//---------------------------------------------------------
1229
AL::Pos TimeCanvas::pix2pos(int x) const
1231
int val = lrint((x + wpos.x() - MAP_OFFSET)/_xmag);
1234
return AL::Pos(val, _timeType);
1237
//---------------------------------------------------------
1239
//---------------------------------------------------------
1241
int TimeCanvas::pos2pix(const AL::Pos& p) const
1243
return lrint(p.time(_timeType) * _xmag) + MAP_OFFSET - wpos.x();
1246
//---------------------------------------------------------
1248
//---------------------------------------------------------
1250
int TimeCanvas::mapx(int x) const
1252
return lrint(x * _xmag) + MAP_OFFSET - wpos.x();
1255
//---------------------------------------------------------
1257
//---------------------------------------------------------
1259
int TimeCanvas::mapxDev(int x) const
1261
int val = lrint((x + wpos.x() - MAP_OFFSET)/_xmag);
1267
//---------------------------------------------------------
1269
//---------------------------------------------------------
1271
void TimeCanvas::setCornerWidget(QWidget* w)
1273
grid->addWidget(w, 3, 2);
1276
//---------------------------------------------------------
1278
//---------------------------------------------------------
1281
0 1 2 3 4 5 6 7 8 9 10
1282
c-2 c-1 C0 C1 C2 C3 C4 C5 C6 C7 C8 - G8
1286
+------------+ ------------------------------
1290
10 | a# +-----+ ..............................
1294
8 | g# +-----+ ..............................
1298
6 | f# +-----+ ..............................
1302
+------------+ ------------------------------
1306
3 | d# +-----+ ..............................
1310
1 | c# +-----+ ..............................
1314
+------------+ ------------------------------
1317
void TimeCanvas::initPianoroll()
1319
static const char *oct_xpm[] = {
1325
"####################################### ",
1326
".......................................#",
1327
".......................................#",
1328
".......................................#",
1329
".......................................#",
1330
".......................................#", // 10
1331
".......................................#",
1332
".......................................#",
1333
".......................................#",
1334
".......................................#", //------------------------
1335
"#######################................#",
1336
"########################...............#",
1337
"########################...............#",
1338
"####################################### ", // 7
1339
"########################...............#",
1340
"########################...............#",
1341
"#######################................#", //------------------------
1342
".......................................#",
1343
".......................................#",
1344
".......................................#", // 6
1345
".......................................#",
1346
".......................................#",
1347
".......................................#", //------------------------
1348
"#######################................#",
1349
"########################...............#",
1350
"########################...............#", // 7
1351
"####################################### ",
1352
"########################...............#",
1353
"########################...............#",
1354
"#######################................#", //------------------------
1355
".......................................#",
1356
".......................................#",
1357
".......................................#", // 6
1358
".......................................#",
1359
".......................................#",
1360
".......................................#", //------------------------
1361
"#######################................#",
1362
"########################...............#",
1363
"########################...............#", // 7
1364
"####################################### ",
1365
"########################...............#",
1366
"########################...............#",
1367
"#######################................#", //------------------------
1368
".......................................#",
1369
".......................................#",
1370
".......................................#",
1371
".......................................#", // 10
1372
".......................................#",
1373
".......................................#",
1374
".......................................#",
1375
".......................................#",
1376
".......................................#",
1377
"####################################### ", //----------------------
1378
".......................................#",
1379
".......................................#",
1380
".......................................#",
1381
".......................................#", // 9
1382
".......................................#",
1383
".......................................#",
1384
".......................................#",
1385
".......................................#",
1386
".......................................#", //------------------------
1387
"#######################................#",
1388
"########################...............#",
1389
"########################...............#",
1390
"####################################### ", // 7
1391
"########################...............#",
1392
"########################...............#",
1393
"#######################................#", //------------------------
1394
".......................................#",
1395
".......................................#",
1396
".......................................#", // 6
1397
".......................................#",
1398
".......................................#",
1399
".......................................#", //--------------------------
1400
"#######################................#",
1401
"########################...............#",
1402
"########################...............#", // 7
1403
"####################################### ",
1404
"########################...............#",
1405
"########################...............#",
1406
"#######################................#", //------------------------
1407
".......................................#",
1408
".......................................#",
1409
".......................................#",
1410
".......................................#",
1411
".......................................#",
1412
".......................................#", // 10
1413
".......................................#",
1414
".......................................#",
1415
".......................................#",
1416
".......................................#",
1419
static const char *mk1_xpm[] = {
1423
".......................................#",
1424
".......................................#",
1425
".......................................#",
1426
".......................................#",
1427
".......................................#",
1428
".......................................#",
1429
".......................................#",
1430
".......................................#",
1431
".......................................#",
1432
"#######################................#",
1433
"########################...............#",
1434
"########################...............#",
1435
"####################################### ",
1438
static const char *mk2_xpm[] = {
1442
"########################...............#",
1443
"########################...............#",
1444
"#######################................#", //------------------------
1445
".......................................#",
1446
".......................................#",
1447
".......................................#", // 6
1448
".......................................#",
1449
".......................................#",
1450
".......................................#", //--------------------------
1451
"#######################................#",
1452
"########################...............#",
1453
"########################...............#", // 7
1454
"####################################### ",
1457
static const char *mk3_xpm[] = {
1461
"########################...............#",
1462
"########################...............#",
1463
"#######################................#",
1464
".......................................#",
1465
".......................................#",
1466
".......................................#",
1467
".......................................#",
1468
".......................................#",
1469
".......................................#",
1470
".......................................#",
1471
".......................................#",
1472
".......................................#",
1473
"########################################",
1476
static const char *mk4_xpm[] = {
1480
"........................................",
1481
"........................................",
1482
"........................................",
1483
"#######################.................",
1484
"########################................",
1485
"########################................",
1486
"########################................",
1487
"########################................",
1488
"########################................",
1489
"#######################.................",
1490
"........................................",
1491
"........................................",
1492
"........................................",
1496
octave = new QPixmap(oct_xpm);
1497
mk1 = new QPixmap(mk1_xpm);
1498
mk2 = new QPixmap(mk2_xpm);
1499
mk3 = new QPixmap(mk3_xpm);
1500
mk4 = new QPixmap(mk4_xpm);
1502
yRange = keyHeight * 75;
1505
//---------------------------------------------------------
1507
// y = 0 == origin of rCanvasA
1508
//---------------------------------------------------------
1510
int TimeCanvas::pitch2y(int pitch) const
1513
if (type == TIME_CANVAS_DRUMEDIT)
1514
y = pitch * drumHeight;
1517
12, 19, 25, 32, 38, 51, 58, 64, 71, 77, 84, 90
1519
y = (75 * keyHeight) - (tt[pitch % 12] + (7 * keyHeight) * (pitch / 12));
1523
return lrint(y - wpos.y() / _ymag);
1526
//---------------------------------------------------------
1528
// y = 0 == origin of rCanvasA
1529
//---------------------------------------------------------
1531
int TimeCanvas::y2pitch(int y) const
1533
y = lrint((y + wpos.y()) / _ymag);
1535
if (type == TIME_CANVAS_DRUMEDIT)
1536
pitch = y / drumHeight;
1538
const int total = (10 * 7 + 5) * keyHeight; // 75 Ganztonschritte
1540
int oct = (y / (7 * keyHeight)) * 12;
1542
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1543
1, 1, 1, 1, 1, 1, 1,
1545
3, 3, 3, 3, 3, 3, 3,
1546
4, 4, 4, 4, 4, 4, 4, 4, 4,
1547
5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
1548
6, 6, 6, 6, 6, 6, 6,
1550
8, 8, 8, 8, 8, 8, 8,
1552
10, 10, 10, 10, 10, 10, 10,
1553
11, 11, 11, 11, 11, 11, 11, 11, 11, 11
1555
pitch = kt[y % 91] + oct;
1556
if (pitch < 0 || pitch > 127)
1562
//---------------------------------------------------------
1564
//---------------------------------------------------------
1566
void TimeCanvas::paintPiano(QPainter& p, QRect r)
1568
int d = int(_ymag)+1;
1569
qreal x = qreal(r.x());
1570
qreal y = (r.y()-rulerHeight-d) / _ymag;
1573
qreal h = (r.height()+d) / _ymag;
1574
QPointF offset(x, wpos.y() / _ymag + keyHeight * 2 + y);
1576
p.translate(0.0, qreal(rulerHeight));
1577
p.scale(1.0, _ymag);
1578
p.drawTiledPixmap(QRectF(x, y, qreal(r.width()), h), *octave, offset);
1580
if (curPitch != -1) {
1581
int y = pitch2y(curPitch);
1583
switch(curPitch % 12) {
1601
p.drawPixmap(0, y, *pm);
1606
//---------------------------------------------------------
1607
// paintPianorollHorizontalGrid
1608
//---------------------------------------------------------
1610
void TimeCanvas::paintPianorollHorizontalGrid(QPainter& p, QRect r)
1612
qreal offset = rulerHeight - wpos.y();
1613
qreal kh = keyHeight * _ymag;
1616
int x2 = x1 + r.width();
1617
if (x1 < pianoWidth)
1619
qreal y = kh + offset;
1620
qreal y1 = r.y() - _ymag;
1621
qreal y2 = y1 + r.height() + _ymag;
1622
for (int key = 1; key < 75; ++key, y += kh) {
1630
p.setPen(QPen(Qt::lightGray));
1633
p.setPen(QPen(Qt::gray));
1636
p.drawLine(QLineF(x1, y, x2, y));
1640
//---------------------------------------------------------
1641
// paintDrumeditHorizontalGrid
1642
//---------------------------------------------------------
1644
void TimeCanvas::paintDrumeditHorizontalGrid(QPainter& p, QRect r)
1646
int offset = rulerHeight - wpos.y();
1648
p.setPen(QPen(Qt::lightGray));
1650
int x2 = x1 + r.width();
1654
p.setPen(QPen(Qt::lightGray));
1658
int y2 = y1 + r.height();
1659
for (int i = 0; i < 128; ++i, y += drumHeight) {
1664
p.drawLine(QLine(x1, y, x2, y));
1668
//---------------------------------------------------------
1670
//---------------------------------------------------------
1672
void TimeCanvas::addCtrlClicked()
1677
//---------------------------------------------------------
1679
//---------------------------------------------------------
1681
void TimeCanvas::updateGeometry()
1683
int wh = _widget->height();
1684
int ww = _widget->width();
1685
if (wh < ctrlHeight)
1689
if (type == TIME_CANVAS_PIANOROLL)
1691
else if (type == TIME_CANVAS_DRUMEDIT)
1693
else if (type == TIME_CANVAS_WAVEEDIT)
1695
int y2 = wh - ctrlHeight;
1697
rPanelA.setRect(0, rulerHeight, x1, wh - rulerHeight - ctrlHeight);
1698
rPanelB.setRect(0, y2, x1, ctrlHeight);
1701
rRuler.setRect( x1, 0, cw, rulerHeight);
1702
rCanvasA.setRect(x1, rulerHeight, cw, wh - rulerHeight - ctrlHeight);
1703
rCanvasB.setRect(x1, y2, cw, ctrlHeight);
1705
rButton.setRect(0, 0, rCanvasA.x(), rPanelA.y());
1707
if (yRange > 0 && _yFit) {
1708
_ymagMin = double(rCanvasA.height()) / double(yRange);
1709
if (_ymag < _ymagMin)
1712
vmag->setValue(lrint((_ymag-_ymagMin)*100.0/(_ymagMax-_ymagMin)));
1716
//---------------------------------------------------------
1718
//---------------------------------------------------------
1720
void TimeCanvas::setTool(int t)
1722
if (_tool == Tool(t))
1725
emit toolChanged(_tool);
1729
//---------------------------------------------------------
1731
//---------------------------------------------------------
1733
void TimeCanvas::setCursor()
1737
widget()->setCursor(QCursor(QPixmap(":/xpm/pencil.xpm"), 4, 15));
1740
widget()->setCursor(QCursor(QPixmap(":/xpm/delete.xpm"), 4, 15));
1743
widget()->setCursor(QCursor(QPixmap(":/xpm/glue.xpm"), 4, 15));
1746
widget()->setCursor(QCursor(QPixmap(":/xpm/cut.xpm"), 4, 15));
1749
widget()->setCursor(QCursor(QPixmap(":/xpm/editmute.xmp"), 4, 15));
1752
widget()->setCursor(QCursor(Qt::ArrowCursor));
1757
//---------------------------------------------------------
1758
// setCanvasBackground
1759
//---------------------------------------------------------
1761
void TimeCanvas::setCanvasBackground(const QColor& color)
1763
canvasBackgroundPixmap = QPixmap();
1764
canvasBackgroundColor = color;
1768
//---------------------------------------------------------
1769
// setCanvasBackground
1770
//---------------------------------------------------------
1772
void TimeCanvas::setCanvasBackground(const QPixmap& pm)
1774
canvasBackgroundPixmap = pm;
1778
//---------------------------------------------------------
1780
//---------------------------------------------------------
1782
void TimeCanvas::setYMagRange(double min, double max)
1787
vmag->setValue(lrint((_ymag-_ymagMin)*100.0/(_ymagMax-_ymagMin)));
1790
//---------------------------------------------------------
1792
//---------------------------------------------------------
1794
void TimeCanvas::setVSize(int val)
1800
_ymagMin = double(rCanvasA.height()) / double(yRange);
1801
if (_ymag < _ymagMin)
1804
vmag->setValue(lrint((_ymag-_ymagMin)*100.0/(_ymagMax-_ymagMin)));
1809
//---------------------------------------------------------
1811
// nonlinear xmag behaviour, feels better
1812
//---------------------------------------------------------
1814
double TimeCanvas::s2xmag(int val)
1817
double f = 1.0 - log10(val * val + 1) * 0.25;
1818
return (_xmagMax - _xmagMin) * f + _xmagMin;
1821
//---------------------------------------------------------
1823
//---------------------------------------------------------
1825
int TimeCanvas::xmag2s(double m)
1828
m /= (_xmagMax - _xmagMin);
1829
double val = sqrt(exp10((1.0 - m) * 4.0)-1.0);
1830
return lrint(100.0 - val);
1833
//---------------------------------------------------------
1835
//---------------------------------------------------------
1837
void TimeCanvas::setPart(const AL::Pos& p1, const AL::Pos& p2)
1844
//---------------------------------------------------------
1846
//---------------------------------------------------------
1848
void TimeCanvas::setFont1(const QFont& f)
1851
printf("TimeCanvas::setFont1\n");
1854
//---------------------------------------------------------
1856
//---------------------------------------------------------
1858
void TimeCanvas::setFont2(const QFont& f)
1863
//---------------------------------------------------------
1865
//---------------------------------------------------------
1867
void TimeCanvas::setFont3(const QFont& f)