summaryrefslogtreecommitdiff
path: root/muse2/muse/arranger/pcanvas.cpp
diff options
context:
space:
mode:
authorFlorian Jung <flo@windfisch.org>2012-05-28 14:15:52 +0000
committerFlorian Jung <flo@windfisch.org>2012-05-28 14:15:52 +0000
commitd2a88cfaad5ac385fc3c6212c09ad7fbc38e9454 (patch)
tree387da0b38255003e1a971629ea0de32273ac3d3c /muse2/muse/arranger/pcanvas.cpp
parent716f5a5b56a3b7ff59004ef0a1af5f98cb2a691c (diff)
merged with release_2_0
Diffstat (limited to 'muse2/muse/arranger/pcanvas.cpp')
-rw-r--r--muse2/muse/arranger/pcanvas.cpp262
1 files changed, 139 insertions, 123 deletions
diff --git a/muse2/muse/arranger/pcanvas.cpp b/muse2/muse/arranger/pcanvas.cpp
index f3e71916..cc23b59b 100644
--- a/muse2/muse/arranger/pcanvas.cpp
+++ b/muse2/muse/arranger/pcanvas.cpp
@@ -25,7 +25,7 @@
#include <sys/stat.h>
#include <sys/mman.h>
#include <errno.h>
-#include <values.h>
+#include <limits.h>
#include <uuid/uuid.h>
#include <math.h>
#include <map>
@@ -80,6 +80,8 @@ NPart::NPart(MusECore::Part* e) : CItem(MusECore::Event(), e)
leftBorderTouches = false;
rightBorderTouches = false;
+ _serial=e->sn();
+
int y = track()->y();
setPos(QPoint(e->tick(), y));
setBBox(QRect(e->tick(), y, e->lenTick(), track()->height()));
@@ -155,7 +157,7 @@ int PartCanvas::pitch2y(int p) const
void PartCanvas::leaveEvent(QEvent*)
{
- emit timeChanged(MAXINT);
+ emit timeChanged(INT_MAX);
}
//---------------------------------------------------------
@@ -215,7 +217,7 @@ void PartCanvas::viewMouseDoubleClickEvent(QMouseEvent* event)
emit dclickPart(((NPart*)(curItem))->track());
}
}
- //
+
// double click creates new part between left and
// right mark
@@ -226,7 +228,7 @@ void PartCanvas::viewMouseDoubleClickEvent(QMouseEvent* event)
int y = event->y();
for (it = tl->begin(); it != tl->end(); ++it) {
int h = (*it)->height();
- if (y >= yy && y < (yy + h))
+ if (y >= yy && y < (yy + h) && (*it)->isVisible())
break;
yy += h;
}
@@ -395,7 +397,7 @@ bool PartCanvas::moveItem(MusECore::Undo& operations, CItem* item, const QPoint&
// But just in case we ever have two different lists...
dpart->events()->incARef(-1); // the later MusEGlobal::song->applyOperationGroup() will increment it
// so we must decrement it first :/
- spart->events()->incARef(1); // the later MusEGlobal::song->applyOperationGroup() will decrement it
+ spart->events()->incARef(1); // the later MusEGlobal::song->applyOperationGroup() will decrement it
// so we must increment it first :/
dpart->setSelected(spart->selected());
// These will increment ref count if not a clone, and will chain clones...
@@ -444,23 +446,24 @@ void PartCanvas::songIsClearing()
void PartCanvas::partsChanged()
{
int sn = -1;
- if (curItem) sn=curItem->part()->sn();
- curItem=NULL;
+ if (curItem) sn=static_cast<NPart*>(curItem)->serial();
+ curItem=NULL;
items.clearDelete();
for (MusECore::iTrack t = tracks->begin(); t != tracks->end(); ++t) {
+ if ((*t)->isVisible()) //ignore parts from hidden tracks
+ {
MusECore::PartList* pl = (*t)->parts();
for (MusECore::iPart i = pl->begin(); i != pl->end(); ++i) {
MusECore::Part* part = i->second;
NPart* np = new NPart(part);
items.add(np);
- if (np->part()->sn() == sn)
+ if (np->serial() == sn)
curItem=np;
- if (i->second->selected()) {
+ if (i->second->selected())
selectItem(np, true);
- }
// Check for touching borders. p4.0.29
MusECore::Part* pp;
@@ -476,10 +479,11 @@ void PartCanvas::partsChanged()
if(pp->tick() == part->endTick())
np->rightBorderTouches = true;
}
- }
}
- redraw();
+ }
}
+ redraw();
+}
//---------------------------------------------------------
// updateSelection
@@ -868,10 +872,10 @@ void PartCanvas::itemPopup(CItem* item, int n, const QPoint& pt)
// viewMousePressEvent
//---------------------------------------------------------
-void PartCanvas::mousePress(QMouseEvent* event)
+bool PartCanvas::mousePress(QMouseEvent* event)
{
if (event->modifiers() & Qt::ControlModifier) {
- return;
+ return true;
}
QPoint pt = event->pos();
CItem* item = items.find(pt);
@@ -900,10 +904,26 @@ void PartCanvas::mousePress(QMouseEvent* event)
}
}
case AutomationTool:
- if (automation.controllerState != doNothing)
- automation.moveController=true;
- break;
+ if (event->button() & Qt::RightButton) {
+ QMenu *automationMenu = new QMenu(this);
+ QAction* act;
+ act = automationMenu->addAction(tr("Remove selected"));
+ act = automationMenu->exec(event->globalPos());
+ if (act && automation.currentTrack) {
+ foreach(int frame, automation.currentCtrlFrameList)
+ MusEGlobal::audio->msgEraseACEvent((MusECore::AudioTrack*)automation.currentTrack,
+ automation.currentCtrlList->id(), frame);
+ }
+
+ }
+ else {
+ if (automation.controllerState != doNothing)
+ automation.moveController=true;
+ }
+ return false;
+ break;
}
+ return true;
}
//---------------------------------------------------------
@@ -3317,11 +3337,9 @@ void PartCanvas::drawCanvas(QPainter& p, const QRect& rect)
//--------------------------------
MusECore::TrackList* tl = MusEGlobal::song->tracks();
- //int yy = 0;
int yy = -rmapy(yorg) - ypos;
int th;
for (MusECore::iTrack it = tl->begin(); it != tl->end(); ++it) {
- //if (yy > y + h)
if (yy > my + mh)
break;
MusECore::Track* track = *it;
@@ -3331,9 +3349,7 @@ void PartCanvas::drawCanvas(QPainter& p, const QRect& rect)
if (MusEGlobal::config.canvasShowGrid && (track->isMidiTrack() || track->type() == MusECore::Track::WAVE)) // Tim.
{
p.setPen(baseColor.dark(130));
- //p.drawLine(x, yy + th, x + w, yy + th);
p.drawLine(mx, yy + th, mx + mw, yy + th);
- //p.setPen(baseColor);
}
// The update rectangle (rect and mr etc) is clipped at x<0 and y<0 in View::pdraw().
@@ -3346,26 +3362,10 @@ void PartCanvas::drawCanvas(QPainter& p, const QRect& rect)
// does NOT depend on the update rectangle (except to check intersection). That's why this issue
// does not show up there. Should probably try to make that routine more efficient, just like here. Tim. p4.0.30
QRect r(mx, yy, mw, th);
- //if(r.intersects(mr)) DELETETHIS
{
if (!track->isMidiTrack() && (track->type() != MusECore::Track::WAVE)) {
- //QRect r = rect & QRect(x, yy, w, track->height());
drawAudioTrack(p, mr, r, (MusECore::AudioTrack*)track);
- //p.setPen(baseColor);
- }
-
- // DELETETHIS 13
- // This was redundant drawing. Not required, done via drawTopItem in Canvas::draw
- /*
- //p.setWorldMatrixEnabled(true);
- //if (!track->isMidiTrack()) { // draw automation
- if (!track->isMidiTrack() && (track->type() != MusECore::Track::WAVE)) {
- //QRect r = rect & QRect(x, yy, w, track->height());
- drawAutomation(p, r, (MusECore::AudioTrack*)track);
- //p.setPen(baseColor);
- }
- //p.setWorldMatrixEnabled(false);
- */
+ }
}
yy += th;
}
@@ -3378,8 +3378,7 @@ void PartCanvas::drawCanvas(QPainter& p, const QRect& rect)
//---------------------------------------------------------
void PartCanvas::drawTopItem(QPainter& p, const QRect& rect)
{
- //QRect mr = p.transform().mapRect(rect); // Gives inconsistent positions. Source shows wrong operation for our needs.
- QRect mr = map(rect); // Use our own map instead.
+ QRect mr = map(rect);
int mx = mr.x();
int my = mr.y();
@@ -3396,7 +3395,6 @@ void PartCanvas::drawTopItem(QPainter& p, const QRect& rect)
int yy = yoff;
int th;
for (MusECore::iTrack it = tl->begin(); it != tl->end(); ++it) {
- //if (yy > y + h) DELETETHIS
if (yy > my + mh)
break;
MusECore::Track* track = *it;
@@ -3404,15 +3402,12 @@ void PartCanvas::drawTopItem(QPainter& p, const QRect& rect)
if (!th)
continue;
if (!track->isMidiTrack()) { // draw automation
- //QRect r = rect & QRect(x, yy, w, track->height()); DELETETHIS
QRect r(mx, yy, mw, th);
if(r.intersects(mr))
{
drawAutomation(p, r, (MusECore::AudioTrack*)track);
- //p.setPen(baseColor); DELETETHIS
}
}
- //yy += track->height(); DELETETHIS
yy += th;
}
@@ -3631,13 +3626,25 @@ void PartCanvas::drawAutomation(QPainter& p, const QRect& rr, MusECore::AudioTra
//p.drawRect(mapx(MusEGlobal::tempomap.frame2tick(prevPosFrame))-2, (rr.bottom()-2)-prevVal*height-2, 5, 5);
//p.drawRect(mapx(MusEGlobal::tempomap.frame2tick(prevPosFrame))-1, (rr.bottom()-1)-prevVal*height-2, 3, 3);
pen2.setColor((automation.currentCtrlValid && automation.currentCtrlList == cl &&
- automation.currentCtrlFrame == ic->second.frame) ?
+ automation.currentCtrlFrameList.contains(ic->second.frame)) ?
Qt::white : cl->color());
p.setPen(pen2);
p.drawRect(xpixel-2, ypixel-2, 5, 5);
oldX = xpixel;
oldY = ypixel;
+ if (automation.currentCtrlValid && automation.currentCtrlList == cl &&
+ automation.currentCtrlFrameList.contains(ic->second.frame) &&
+ automation.currentCtrlFrameList.size() == 1) {
+ double val = ic->second.val;
+ QRect textRect = rr;
+ textRect.setX(xpixel + 20);
+ textRect.setY(ypixel);
+ if (cl->valueType() == MusECore::VAL_LOG) {
+ val = MusECore::fast_log10(ic->second.val) * 20.0;
+ }
+ p.drawText(textRect, QString("Value: %1").arg(val));
+ }
}
}
if (xpixel <= rr.right())
@@ -3648,6 +3655,42 @@ void PartCanvas::drawAutomation(QPainter& p, const QRect& rr, MusECore::AudioTra
}
}
+//---------------------------------------------------------
+// checkIfOnLine
+// check if our point is on the line defined by
+// by first/last X/Y
+//---------------------------------------------------------
+
+bool checkIfOnLine(double mouseX, double mouseY, double firstX, double lastX, double firstY, double lastY, int circumference)
+{
+ double proportion = (mouseX-firstX)/(lastX-firstX);
+
+ // 10 X(15) 20
+ // proportion = 0.5
+ // 10
+ // /
+ // Y(5)
+ // /
+ // 1
+ double calcY = (lastY-firstY)*proportion+firstY;
+ if(ABS(calcY-mouseY) < circumference || (lastX == firstX && ABS(mouseX-lastX) < circumference))
+ return true;
+ return false;
+}
+
+//---------------------------------------------------------
+// checkIfNearPoint
+//---------------------------------------------------------
+
+bool checkIfNearPoint(int mouseX, int mouseY, int eventX, int eventY, int circumference)
+{
+ int x1 = ABS(mouseX - eventX) ;
+ int y1 = ABS(mouseY - eventY);
+ if (x1 < circumference && y1 < circumference) {
+ return true;
+ }
+ return false;
+}
//---------------------------------------------------------
// checkAutomation
@@ -3660,22 +3703,22 @@ void PartCanvas::drawAutomation(QPainter& p, const QRect& rr, MusECore::AudioTra
// controller added.
//---------------------------------------------------------
-void PartCanvas::checkAutomation(MusECore::Track * t, const QPoint &pointer, bool addNewCtrl)
+void PartCanvas::checkAutomation(MusECore::Track * t, const QPoint &pointer, bool NOTaddNewCtrl)
{
if (t->isMidiTrack())
return;
- int currY;
+ int mouseY;
int trackY = t->y();
int trackH = t->height();
{ int y = pointer.y();
if(y < trackY || y >= (trackY + trackH))
return;
- currY = mapy(y); }
+ mouseY = mapy(y); }
- int currX = mapx(pointer.x());
- int circumference = 5;
+ int mouseX = mapx(pointer.x());
+ int circumference = 10;
MusECore::CtrlListList* cll = ((MusECore::AudioTrack*) t)->controller();
for(MusECore::CtrlListList::iterator icll =cll->begin();icll!=cll->end();++icll)
@@ -3686,15 +3729,15 @@ void PartCanvas::checkAutomation(MusECore::Track * t, const QPoint &pointer, boo
}
MusECore::iCtrl ic=cl->begin();
- int oldX = mapx(0);
- int xpixel = oldX;
- int oldY = -1;
- int ypixel = oldY;
+ int eventOldX = mapx(0);
+ int eventX = eventOldX;
+ int eventOldY = -1;
+ int eventY = eventOldY;
double min, max;
cl->range(&min,&max);
bool discrete = cl->mode() == MusECore::CtrlList::DISCRETE;
- // First check that there IS automation, ic == cl->end means no automation
+ // First check that there IS automation for this controller, ic == cl->end means no automation
if (ic == cl->end())
{
double y;
@@ -3704,93 +3747,65 @@ void PartCanvas::checkAutomation(MusECore::Track * t, const QPoint &pointer, boo
}
else
y = (cl->curVal() - min)/(max-min); // we need to set curVal between 0 and 1
- ypixel = oldY = mapy(trackY+trackH-1 - 2 - y * trackH);
+ eventY = eventOldY = mapy(trackY+trackH-1 - 2 - y * trackH);
}
- else
+ else // we have automation, loop through it
{
for (; ic !=cl->end(); ic++)
{
double y = ic->second.val;
if (cl->valueType() == MusECore::VAL_LOG ) { // use db scale for volume
- y = logToVal(y, min, max); // represent volume between 0 and 1
+ y = logToVal(y, min, max); // represent volume between 0 and 1
if (y < 0) y = 0;
}
else
y = (y-min)/(max-min); // we need to set curVal between 0 and 1
- ypixel = mapy(trackY + trackH - 2 - y * trackH);
- xpixel = mapx(MusEGlobal::tempomap.frame2tick(ic->second.frame));
+ eventY = mapy(trackY + trackH - 2 - y * trackH);
+ eventX = mapx(MusEGlobal::tempomap.frame2tick(ic->second.frame));
- if (oldY==-1) oldY = ypixel;
+ if (eventOldY==-1) eventOldY = eventY;
- bool foundIt=false;
- if (addNewCtrl) {
- double firstX=oldX;
- double lastX=xpixel;
- double firstY=oldY;
- double lastY = discrete ? oldY : ypixel;
-
- double proportion = (currX-firstX)/(lastX-firstX);
-
- if((currX < oldX) || (currX > lastX) || (firstX==lastX) )
- {
- oldX = xpixel;
- oldY = ypixel;
- continue; // not the right region
- }
-
- // 10 X(15) 20
- // proportion = 0.5
- // 10
- // /
- // Y(5)
- // /
- // 1
- double calcY = (lastY-firstY)*proportion+firstY;
- if(ABS(calcY-currY) < circumference || (xpixel == oldX && ABS(currX-xpixel) < circumference))
- foundIt=true;
-
- } else {
- int x1 = ABS(currX - xpixel) ;
- int y1 = ABS(currY - ypixel);
- if (x1 < circumference && y1 < circumference && pointer.x() > 0 && pointer.y() > 0) {
- foundIt=true;
- }
-
- }
- oldX = xpixel;
- oldY = ypixel;
-
- if (foundIt) {
- QWidget::setCursor(Qt::CrossCursor);
- if (addNewCtrl) {
- //automation.currentCtrl = 0;
+ //if (addNewCtrl) {
+ bool onLine = checkIfOnLine(mouseX, mouseY, eventOldX,eventX, eventOldY, discrete? eventOldY:eventY, circumference);
+ bool onPoint = false;
+ if ( pointer.x() > 0 && pointer.y() > 0)
+ onPoint = checkIfNearPoint(mouseX, mouseY, eventX, eventY, circumference);
+
+ eventOldX = eventX;
+ eventOldY = eventY;
+
+ if (onLine) {
+ if (!onPoint) {
+ QWidget::setCursor(Qt::CrossCursor);
automation.currentCtrlValid = false;
automation.controllerState = addNewController;
}else {
- automation.currentCtrlFrame = ic->second.frame;
+ QWidget::setCursor(Qt::OpenHandCursor);
+ automation.currentCtrlFrameList.clear();
+ automation.currentCtrlFrameList.append(ic->second.frame);
automation.currentCtrlValid = true;
automation.controllerState = movingController;
}
automation.currentCtrlList = cl;
automation.currentTrack = t;
+ update();
return;
}
}
}
- if (addNewCtrl) {
- // check if we are reasonably close to a line, we only need to check Y
- // as the line is straight after the last controller
- //printf("post oldX:%d oldY:%d xpixel:%d ypixel:%d currX:%d currY:%d\n", oldX, oldY, xpixel, ypixel, currX, currY);
- if(currX >= xpixel && ypixel == oldY && ABS(currY-ypixel) < circumference) {
- QWidget::setCursor(Qt::CrossCursor);
- automation.controllerState = addNewController;
- automation.currentCtrlList = cl;
- automation.currentTrack = t;
- automation.currentCtrlValid = false;
- return;
- }
+ // we are now after the last existing controller
+ // check if we are reasonably close to a line, we only need to check Y
+ // as the line is straight after the last controller
+ //printf("post oldX:%d oldY:%d xpixel:%d ypixel:%d currX:%d currY:%d\n", oldX, oldY, xpixel, ypixel, currX, currY);
+ if(mouseX >= eventX && eventY == eventOldY && ABS(mouseY-eventY) < circumference) {
+ QWidget::setCursor(Qt::CrossCursor);
+ automation.controllerState = addNewController;
+ automation.currentCtrlList = cl;
+ automation.currentTrack = t;
+ automation.currentCtrlValid = false;
+ return;
}
}
// if there are no hits we default to clearing all the data
@@ -3798,6 +3813,7 @@ void PartCanvas::checkAutomation(MusECore::Track * t, const QPoint &pointer, boo
automation.currentCtrlValid = false;
automation.currentCtrlList = 0;
automation.currentTrack = 0;
+ automation.currentCtrlFrameList.clear();
setCursor();
}
@@ -3820,10 +3836,8 @@ void PartCanvas::processAutomationMovements(QPoint pos, bool addPoint)
}
// automation.moveController is set, lets rock.
-
int prevFrame = 0;
int nextFrame = -1;
- int currFrame = 0;
if (automation.controllerState == addNewController)
{
@@ -3835,7 +3849,8 @@ void PartCanvas::processAutomationMovements(QPoint pos, bool addPoint)
for (; ic !=automation.currentCtrlList->end(); ++ic) {
MusECore::CtrlVal &cv = ic->second;
if (cv.frame == frame) {
- automation.currentCtrlFrame = cv.frame;
+ automation.currentCtrlFrameList.clear();
+ automation.currentCtrlFrameList.append(cv.frame);
automation.currentCtrlValid = true;
automation.controllerState = movingController;
break;
@@ -3849,9 +3864,9 @@ void PartCanvas::processAutomationMovements(QPoint pos, bool addPoint)
for (; ic !=automation.currentCtrlList->end(); ++ic)
{
MusECore::CtrlVal &cv = ic->second;
- if (cv.frame == automation.currentCtrlFrame)
+ if (automation.currentCtrlFrameList.contains(cv.frame))
{
- currFrame = cv.frame;
+ //currFrame = cv.frame;
break;
}
prevFrame = cv.frame;
@@ -3885,7 +3900,7 @@ void PartCanvas::processAutomationMovements(QPoint pos, bool addPoint)
automation.currentCtrlList->range(&min,&max);
double cvval;
if (automation.currentCtrlList->valueType() == MusECore::VAL_LOG ) { // use db scale for volume
- printf("log conversion val=%f min=%f max=%f\n", yfraction, min, max);
+ //printf("log conversion val=%f min=%f max=%f\n", yfraction, min, max);
cvval = valToLog(yfraction, min, max);
if (cvval< min) cvval=min;
if (cvval>max) cvval=max;
@@ -3900,7 +3915,8 @@ void PartCanvas::processAutomationMovements(QPoint pos, bool addPoint)
if (cvval>max) cvval=max;
}
- automation.currentCtrlFrame = newFrame;
+ automation.currentCtrlFrameList.clear();
+ automation.currentCtrlFrameList.append(newFrame);
automation.currentCtrlValid = true;
if(icc != automation.currentCtrlList->end())