summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--muse2/ChangeLog3
-rw-r--r--muse2/muse/arranger/pcanvas.cpp239
-rw-r--r--muse2/muse/arranger/pcanvas.h11
-rw-r--r--muse2/muse/audiotrack.cpp2
-rw-r--r--muse2/muse/midiedit/dcanvas.cpp7
-rw-r--r--muse2/muse/midiedit/dcanvas.h1
-rw-r--r--muse2/muse/midiedit/prcanvas.cpp5
-rw-r--r--muse2/muse/midiedit/prcanvas.h1
-rw-r--r--muse2/muse/widgets/canvas.cpp8
-rw-r--r--muse2/muse/widgets/canvas.h2
10 files changed, 182 insertions, 97 deletions
diff --git a/muse2/ChangeLog b/muse2/ChangeLog
index 4d6d7bee..eeb6024e 100644
--- a/muse2/ChangeLog
+++ b/muse2/ChangeLog
@@ -1,3 +1,6 @@
+26.01.2011:
+ - moved automation lines ontop of parts (rj)
+ - fixes to automation editing, still many bugs though (rj)
21.01.2011:
- Added: graphical editing of automation, also now stores which parameters are visible (rj)
Edit with new automation tool in arranger, to create new points hold down ctrl.
diff --git a/muse2/muse/arranger/pcanvas.cpp b/muse2/muse/arranger/pcanvas.cpp
index 95ceebd5..9c970c52 100644
--- a/muse2/muse/arranger/pcanvas.cpp
+++ b/muse2/muse/arranger/pcanvas.cpp
@@ -142,7 +142,8 @@ PartCanvas::PartCanvas(int* r, QWidget* parent, int sx, int sy)
drag = DRAG_OFF;
curColorIndex = 0;
automation.currentCtrl = 0;
- moveController = 0;
+ automation.controllerState = doNothing;
+ automation.moveController = false;
partsChanged();
}
@@ -1025,9 +1026,9 @@ void PartCanvas::mousePress(QMouseEvent* event)
break;
}
case AutomationTool:
- if (automation.currentCtrl || (automation.currentCtrlList && event->modifiers() & Qt::ControlModifier))
- moveController=true;
- break;
+ if (automation.controllerState != doNothing)
+ automation.moveController=true;
+ break;
}
}
@@ -1037,7 +1038,9 @@ void PartCanvas::mousePress(QMouseEvent* event)
void PartCanvas::mouseRelease(const QPoint&)
{
- moveController=false;
+ // clear all the automation parameters
+ automation.moveController=false;
+ automation.controllerState = doNothing;
automation.currentCtrl=0;
automation.currentTrack=0;
automation.currentCtrlList=0;
@@ -2868,9 +2871,39 @@ void PartCanvas::drawCanvas(QPainter& p, const QRect& rect)
}
//---------------------------------------------------------
-// drawAudioTrack
+// drawLast
//---------------------------------------------------------
+void PartCanvas::drawTopItem(QPainter& p, const QRect& rect)
+{
+ int x = rect.x();
+ int y = rect.y();
+ int w = rect.width();
+ int h = rect.height();
+
+ QColor baseColor(config.partCanvasBg.light(104));
+ p.setPen(baseColor);
+
+ TrackList* tl = song->tracks();
+ int yy = 0;
+ int th;
+ for (iTrack it = tl->begin(); it != tl->end(); ++it) {
+ if (yy > y + h)
+ break;
+ Track* track = *it;
+ th = track->height();
+ if (!track->isMidiTrack()) { // draw automation
+ QRect r = rect & QRect(x, yy, w, track->height());
+ drawAutomation(p, r, (AudioTrack*)track);
+ p.setPen(baseColor);
+
+ }
+ yy += track->height();
+ }
+}
+//---------------------------------------------------------
+// drawAudioTrack
+//---------------------------------------------------------
void PartCanvas::drawAudioTrack(QPainter& p, const QRect& r, AudioTrack* /* t */)
{
// NOTE: For one-pixel border use first line and don't bother with setCosmetic.
@@ -2927,7 +2960,8 @@ void PartCanvas::drawAutomation(QPainter& p, const QRect& r, AudioTrack *t)
// prepare prevVal
if (cl->id() == AC_VOLUME ) { // use db scale for volume
- prevVal = (20.0*log10(cvFirst.val)+60) / 70.0; // represent volume between 0 and 1
+ printf("volume cvval=%f\n", cvFirst.val);
+ prevVal = dbToVal(cvFirst.val); // represent volume between 0 and 1
if (prevVal < 0) prevVal = 0.0;
}
else {
@@ -2945,7 +2979,7 @@ void PartCanvas::drawAutomation(QPainter& p, const QRect& r, AudioTrack *t)
CtrlVal cv = ic->second;
double nextVal = cv.val; // was curVal
if (cl->id() == AC_VOLUME ) { // use db scale for volume
- nextVal = (20.0*log10(cv.val)+60) / 70.0; // represent volume between 0 and 1
+ nextVal = dbToVal(cv.val); // represent volume between 0 and 1
if (nextVal < 0) nextVal = 0.0;
}
else {
@@ -2985,9 +3019,21 @@ quitDrawing:
p.restore();
}
+
+//---------------------------------------------------------
+// checkAutomation
+// compares the current mouse pointer with the automation
+// lines on the track under it.
+// if there is a controller to be moved it is marked
+// in the automation object
+// if addNewCtrl is set and a valid line is found the
+// automation object will also be set but no
+// controller added.
+//---------------------------------------------------------
+
void PartCanvas::checkAutomation(Track * t, const QPoint &pointer, bool addNewCtrl)
{
- int circumference = 4;
+ int circumference = 5;
if (t->isMidiTrack())
return;
//printf("checkAutomation p.x()=%d p.y()=%d\n", mapx(pointer.x()), mapx(pointer.y()));
@@ -3009,6 +3055,7 @@ void PartCanvas::checkAutomation(Track * t, const QPoint &pointer, bool addNewCt
int oldY=-1;
int ypixel;
int xpixel;
+
// First check that there ARE automation, ic == cl->end means no automation
if (ic != cl->end()) {
for (; ic !=cl->end(); ic++)
@@ -3016,7 +3063,7 @@ void PartCanvas::checkAutomation(Track * t, const QPoint &pointer, bool addNewCt
CtrlVal &cv = ic->second;
double y;
if (cl->id() == AC_VOLUME ) { // use db scale for volume
- y = (20.0*log10(cv.val)+60) / 70.0; // represent volume between 0 and 1
+ y = dbToVal(cv.val); // represent volume between 0 and 1
if (y < 0) y = 0;
}
else {
@@ -3062,10 +3109,13 @@ void PartCanvas::checkAutomation(Track * t, const QPoint &pointer, bool addNewCt
if (foundIt) {
QWidget::setCursor(Qt::CrossCursor);
- if (addNewCtrl)
- automation.currentCtrl = 0; // the logic relies on this to be zero if a new controller is to be added
- else
+ if (addNewCtrl) {
+ automation.currentCtrl = 0;
+ automation.controllerState = addNewController;
+ }else {
automation.currentCtrl=&cv;
+ automation.controllerState = movingController;
+ }
automation.currentCtrlList = cl;
automation.currentTrack = t;
return;
@@ -3074,30 +3124,28 @@ void PartCanvas::checkAutomation(Track * t, const QPoint &pointer, bool addNewCt
} // if
if (addNewCtrl) {
- // check if we are reasonably close to a line, we only need to check Y as this is the line is straight after the last controller
- //printf("LAST ypixel=%d oldY=%d currY=%d\n", ypixel, oldY, currY);
+ // check if we are reasonably close to a line, we only need to check Y
+ // as the line is straight after the last controller
bool foundIt=false;
if ( ypixel == oldY && abs(currY-ypixel) < circumference) {
- //printf("found it!\n");
foundIt=true;
}
if (foundIt) {
QWidget::setCursor(Qt::CrossCursor);
+ automation.controllerState = addNewController;
automation.currentCtrlList = cl;
automation.currentTrack = t;
automation.currentCtrl = 0;
return;
}
-
-
}
-
}
+ // if there are no hits we default to clearing all the data
+ automation.controllerState = doNothing;
automation.currentCtrl = 0;
automation.currentCtrlList = 0;
automation.currentTrack = 0;
- //
setCursor();
}
@@ -3110,88 +3158,95 @@ void PartCanvas::processAutomationMovements(QMouseEvent *event)
{
if (_tool == AutomationTool) {
- bool addNewPoints=false;
- if (event->modifiers() & Qt::ControlModifier) {
- addNewPoints=true;
- }
- if (moveController) {
- //printf("update automation for controller=%d\n", automation.currentCtrl);
- // update currentController to this position
-
- int prevFrame = 0;
- int nextFrame = -1;
- if (addNewPoints && automation.currentCtrl == 0) // we don't have a controller, create one!
- {
- //printf("adding a new ctrler!\n");
- int frame = tempomap.tick2frame(event->pos().x());
- automation.currentCtrlList->add( frame, 1.0 /*dummy value */);
+ if (!automation.moveController) { // currently nothing going lets's check for some action.
+ Track * t = y2Track(event->pos().y());
+ if (t) {
+ bool addNewPoints=false;
+ if (event->modifiers() & Qt::ControlModifier)
+ addNewPoints=true;
+ checkAutomation(t, event->pos(), addNewPoints);
+ }
+ return;
+ }
- iCtrl ic=automation.currentCtrlList->begin();
- for (; ic !=automation.currentCtrlList->end(); ic++) {
- CtrlVal &cv = ic->second;
- if (cv.frame == frame) {
- automation.currentCtrl = &cv;
- break;
- }
- }
+ // automation.moveController is set, lets rock.
- }
+ int prevFrame = 0;
+ int nextFrame = -1;
- // get previous and next frame position to give x bounds for this event.
- iCtrl ic=automation.currentCtrlList->begin();
- for (; ic !=automation.currentCtrlList->end(); ic++)
- {
- CtrlVal &cv = ic->second;
- if (&cv == automation.currentCtrl)
- break;
- prevFrame = cv.frame;
- }
- if ( ++ic != automation.currentCtrlList->end()) {
- CtrlVal &cv = ic->second;
- nextFrame = cv.frame;
- }
- int currFrame = tempomap.tick2frame(event->pos().x());
- if (currFrame < prevFrame) currFrame=prevFrame+1;
- if (nextFrame!=-1 && currFrame > nextFrame) currFrame=nextFrame-1;
- automation.currentCtrl->frame = currFrame;
+ if (automation.controllerState == addNewController)
+ {
+ //printf("adding a new ctrler!\n");
+ int frame = tempomap.tick2frame(event->pos().x());
+ automation.currentCtrlList->add( frame, 1.0 /*dummy value */);
+
+ iCtrl ic=automation.currentCtrlList->begin();
+ for (; ic !=automation.currentCtrlList->end(); ic++) {
+ CtrlVal &cv = ic->second;
+ if (cv.frame == frame) {
+ automation.currentCtrl = &cv;
+ automation.controllerState = movingController;
+ break;
+ }
+ }
+ }
- int mouseY = automation.currentTrack->height() - (mapy(event->pos().y()) - automation.currentTrack->y())-2;
- double yfraction = ((double)mouseY)/automation.currentTrack->height();
+ // get previous and next frame position to give x bounds for this event.
+ iCtrl ic=automation.currentCtrlList->begin();
+ for (; ic !=automation.currentCtrlList->end(); ic++)
+ {
+ CtrlVal &cv = ic->second;
+ if (&cv == automation.currentCtrl)
+ break;
+ prevFrame = cv.frame;
+ }
+ if ( ++ic != automation.currentCtrlList->end()) {
+ CtrlVal &cv = ic->second;
+ nextFrame = cv.frame;
+ }
+ int currFrame = tempomap.tick2frame(event->pos().x());
+ if (currFrame < prevFrame) currFrame=prevFrame+1;
+ if (nextFrame!=-1 && currFrame > nextFrame) currFrame=nextFrame-1;
+ automation.currentCtrl->frame = currFrame;
- if (automation.currentCtrlList->id() == AC_VOLUME ) { // use db scale for volume
- //y = (20.0*log10(cv.val)+60) / 70.0; // represent volume between 0 and 1
+ int mouseY = automation.currentTrack->height() - (mapy(event->pos().y()) - automation.currentTrack->y())-2;
+ double yfraction = ((double)mouseY)/automation.currentTrack->height();
- double cvval = exp10((yfraction*70.0-60)/20.0);
- //printf("calc yfraction = %f v=%f ",yfraction,cvval);
- double min, max;
- automation.currentCtrlList->range(&min,&max);
- if (cvval< min) cvval=min;
- if (cvval>max) cvval=max;
- automation.currentCtrl->val=cvval;
+ if (automation.currentCtrlList->id() == AC_VOLUME ) { // use db scale for volume
- }
- else {
- // we need to set curVal between 0 and 1
- double min, max;
- automation.currentCtrlList->range(&min,&max);
- double cvval = yfraction * (max-min) + min;
-
- if (cvval< min) cvval=min;
- if (cvval>max) cvval=max;
- automation.currentCtrl->val = cvval;
- //printf("calc cvval=%f yfraction=%f ", cvval, yfraction);
- }
- //printf("mouseY=%d\n", mouseY);
- controllerChanged(automation.currentTrack);
+ double cvval = valToDb(yfraction);
+ //printf("calc yfraction = %f v=%f ",yfraction,cvval);
+ double min, max;
+ automation.currentCtrlList->range(&min,&max);
+ if (cvval< min) cvval=min;
+ if (cvval>max) cvval=max;
+ automation.currentCtrl->val=cvval;
- } else {
+ }
+ else {
+ // we need to set curVal between 0 and 1
+ double min, max;
+ automation.currentCtrlList->range(&min,&max);
+ double cvval = yfraction * (max-min) + min;
+
+ if (cvval< min) cvval=min;
+ if (cvval>max) cvval=max;
+ automation.currentCtrl->val = cvval;
+ //printf("calc cvval=%f yfraction=%f ", cvval, yfraction);
+ }
+ //printf("mouseY=%d\n", mouseY);
+ controllerChanged(automation.currentTrack);
- Track * t = y2Track(event->pos().y());
- if (t) {
- checkAutomation(t, event->pos(), addNewPoints);
- }
- }
}
}
+
+double PartCanvas::dbToVal(double inDb)
+{
+ return (20.0*log10(inDb)+60) / 70.0;
+}
+double PartCanvas::valToDb(double inV)
+{
+ return exp10((inV*70.0-60)/20.0);
+}
diff --git a/muse2/muse/arranger/pcanvas.h b/muse2/muse/arranger/pcanvas.h
index 6afe1dca..6a324770 100644
--- a/muse2/muse/arranger/pcanvas.h
+++ b/muse2/muse/arranger/pcanvas.h
@@ -37,10 +37,13 @@ class NPart : public CItem {
Track* track() const { return part()->track(); }
};
+enum ControllerVals { doNothing, movingController, addNewController };
struct AutomationObject {
CtrlVal *currentCtrl;
CtrlList *currentCtrlList;
Track *currentTrack;
+ bool moveController;
+ ControllerVals controllerState;
};
class QLineEdit;
@@ -64,9 +67,8 @@ class PartCanvas : public Canvas {
bool editMode;
AutomationObject automation;
- bool moveController;
- std::vector<TrackAutomationView*> automationViews;
+ //std::vector<TrackAutomationView*> automationViews;
Q_OBJECT
virtual void keyPress(QKeyEvent*);
virtual void mousePress(QMouseEvent*);
@@ -113,8 +115,13 @@ class PartCanvas : public Canvas {
Track* y2Track(int) const;
void drawAudioTrack(QPainter& p, const QRect& r, AudioTrack* track);
void drawAutomation(QPainter& p, const QRect& r, AudioTrack* track);
+ void drawTopItem(QPainter& p, const QRect& rect);
+
void checkAutomation(Track * t, const QPoint& pointer, bool addNewCtrl);
void processAutomationMovements(QMouseEvent *event);
+ double dbToVal(double inDb);
+ double valToDb(double inV);
+
protected:
diff --git a/muse2/muse/audiotrack.cpp b/muse2/muse/audiotrack.cpp
index 4be1a1a9..af066437 100644
--- a/muse2/muse/audiotrack.cpp
+++ b/muse2/muse/audiotrack.cpp
@@ -79,7 +79,7 @@ AudioTrack::AudioTrack(TrackType t)
_automationType = AUTO_OFF;
//setChannels(1);
setChannels(2);
- addController(new CtrlList(AC_VOLUME,"Volume",0.0,1.0));
+ addController(new CtrlList(AC_VOLUME,"Volume",0.0,3.16 /* roughly 10 db */));
addController(new CtrlList(AC_PAN, "Pan", -1.0, 1.0));
addController(new CtrlList(AC_MUTE,"Mute",0.0,1.0, true /*dont show in arranger */));
diff --git a/muse2/muse/midiedit/dcanvas.cpp b/muse2/muse/midiedit/dcanvas.cpp
index 34622296..fa89b8ad 100644
--- a/muse2/muse/midiedit/dcanvas.cpp
+++ b/muse2/muse/midiedit/dcanvas.cpp
@@ -588,6 +588,13 @@ void DrumCanvas::drawCanvas(QPainter& p, const QRect& rect)
}
//---------------------------------------------------------
+// drawTopItem
+//---------------------------------------------------------
+void DrumCanvas::drawTopItem(QPainter &, const QRect &)
+{
+
+}
+//---------------------------------------------------------
// y2pitch
//---------------------------------------------------------
diff --git a/muse2/muse/midiedit/dcanvas.h b/muse2/muse/midiedit/dcanvas.h
index 0b81df68..a5510b3c 100644
--- a/muse2/muse/midiedit/dcanvas.h
+++ b/muse2/muse/midiedit/dcanvas.h
@@ -44,6 +44,7 @@ class DrumCanvas : public EventCanvas {
Q_OBJECT
virtual void drawCanvas(QPainter&, const QRect&);
virtual void drawItem(QPainter&, const CItem*, const QRect&);
+ void drawTopItem(QPainter& p, const QRect& rect);
virtual void drawMoving(QPainter&, const CItem*, const QRect&);
virtual void moveCanvasItems(CItemList&, int, int, DragType, int*);
// Changed by T356.
diff --git a/muse2/muse/midiedit/prcanvas.cpp b/muse2/muse/midiedit/prcanvas.cpp
index 84e19e86..4b280a16 100644
--- a/muse2/muse/midiedit/prcanvas.cpp
+++ b/muse2/muse/midiedit/prcanvas.cpp
@@ -209,6 +209,11 @@ void PianoCanvas::drawItem(QPainter& p, const CItem* item,
p.drawRect(r);
}
+//---------------------------------------------------------
+// drawTopItem
+//---------------------------------------------------------
+void PianoCanvas::drawTopItem(QPainter& , const QRect&)
+{}
//---------------------------------------------------------
// drawMoving
diff --git a/muse2/muse/midiedit/prcanvas.h b/muse2/muse/midiedit/prcanvas.h
index 81acf426..bda22fc3 100644
--- a/muse2/muse/midiedit/prcanvas.h
+++ b/muse2/muse/midiedit/prcanvas.h
@@ -44,6 +44,7 @@ class PianoCanvas : public EventCanvas {
Q_OBJECT
virtual void viewMouseDoubleClickEvent(QMouseEvent*);
virtual void drawItem(QPainter&, const CItem*, const QRect&);
+ void drawTopItem(QPainter &p, const QRect &rect);
virtual void drawMoving(QPainter&, const CItem*, const QRect&);
virtual void moveCanvasItems(CItemList&, int, int, DragType, int*);
// Changed by T356.
diff --git a/muse2/muse/widgets/canvas.cpp b/muse2/muse/widgets/canvas.cpp
index 5b6dc453..ff9d0c3b 100644
--- a/muse2/muse/widgets/canvas.cpp
+++ b/muse2/muse/widgets/canvas.cpp
@@ -189,9 +189,12 @@ void Canvas::draw(QPainter& p, const QRect& rect)
to = moving.lower_bound(x2);
for (iCItem i = moving.begin(); i != to; ++i)
{
- drawItem(p, i->second, rect);
- }
+ drawItem(p, i->second, rect);
}
+
+ drawTopItem(p,rect);
+
+ }
else {
p.save();
setPainter(p);
@@ -266,6 +269,7 @@ void Canvas::draw(QPainter& p, const QRect& rect)
{
drawItem(p, i->second, rect);
}
+ drawTopItem(p, QRect(x,y,w,h));
p.save();
setPainter(p);
}
diff --git a/muse2/muse/widgets/canvas.h b/muse2/muse/widgets/canvas.h
index 2f9a3907..97392f1e 100644
--- a/muse2/muse/widgets/canvas.h
+++ b/muse2/muse/widgets/canvas.h
@@ -91,6 +91,8 @@ class Canvas : public View {
virtual void mouseMove(QMouseEvent* event) = 0;
virtual void mouseRelease(const QPoint&) {}
virtual void drawCanvas(QPainter&, const QRect&) = 0;
+ virtual void drawTopItem(QPainter& p, const QRect& rect) = 0;
+
virtual void drawItem(QPainter&, const CItem*, const QRect&) = 0;
virtual void drawMoving(QPainter&, const CItem*, const QRect&) = 0;
virtual void updateSelection() = 0;