summaryrefslogtreecommitdiff
path: root/muse2
diff options
context:
space:
mode:
authorTim E. Real <termtech@rogers.com>2011-08-29 22:44:24 +0000
committerTim E. Real <termtech@rogers.com>2011-08-29 22:44:24 +0000
commitd505c378bdf55445babb73e0ba4085702be35870 (patch)
tree40ccb82e5b27f118904a5298faedd10fe3b96d36 /muse2
parent21e75f0c2d14010d060693c77fd3e22e1fccd65d (diff)
Fixed audio automation graph editing. And now 'snaps' to discrete integer or bool types.
All control movements should update display now. Also slightly changed behaviour of Ctrl class. TODO: Fix some painting corruption, improve discrete display, add transparency etc. etc. Applied compilation patch to rhythmbase.ui by Jean-Damien Durand.
Diffstat (limited to 'muse2')
-rw-r--r--muse2/ChangeLog5
-rw-r--r--muse2/awl/posedit.cpp3
-rw-r--r--muse2/muse/arranger/arranger.cpp1
-rw-r--r--muse2/muse/arranger/pcanvas.cpp393
-rw-r--r--muse2/muse/arranger/pcanvas.h10
-rw-r--r--muse2/muse/audio.cpp4
-rw-r--r--muse2/muse/audio.h2
-rw-r--r--muse2/muse/audiotrack.cpp41
-rw-r--r--muse2/muse/cliplist/cliplist.cpp8
-rw-r--r--muse2/muse/ctrl.cpp110
-rw-r--r--muse2/muse/ctrl.h5
-rw-r--r--muse2/muse/dssihost.cpp15
-rw-r--r--muse2/muse/dssihost.h2
-rw-r--r--muse2/muse/mixer/astrip.cpp43
-rw-r--r--muse2/muse/mixer/panknob.cpp4
-rw-r--r--muse2/muse/mplugins/rhythmbase.ui8
-rw-r--r--muse2/muse/plugin.cpp92
-rw-r--r--muse2/muse/plugin.h10
-rw-r--r--muse2/muse/seqmsg.cpp27
-rw-r--r--muse2/muse/song.cpp17
-rw-r--r--muse2/muse/song.h7
-rw-r--r--muse2/muse/track.cpp4
-rw-r--r--muse2/muse/track.h1
23 files changed, 506 insertions, 306 deletions
diff --git a/muse2/ChangeLog b/muse2/ChangeLog
index 9eee3e8b..2505f901 100644
--- a/muse2/ChangeLog
+++ b/muse2/ChangeLog
@@ -1,3 +1,8 @@
+29.08.2011:
+ - Fixed audio automation graph editing. And now 'snaps' to discrete integer or bool types. (Tim p4.0.32)
+ All control movements should update display now. Also slightly changed behaviour of Ctrl class.
+ TODO: Fix some painting corruption, improve discrete display, add transparency etc. etc.
+ - Applied compilation patch to rhythmbase.ui by Jean-Damien Durand. (Tim)
28.08.2011:
- Fixed wierd column expansion for [rec] column by removing autoexpand of the last column. Still
something fishy with moving columns (rj)
diff --git a/muse2/awl/posedit.cpp b/muse2/awl/posedit.cpp
index 6ca49566..07741e58 100644
--- a/muse2/awl/posedit.cpp
+++ b/muse2/awl/posedit.cpp
@@ -70,7 +70,8 @@ PosEdit::~PosEdit()
QSize PosEdit::sizeHint() const
{
- QFontMetrics fm(font());
+ //QFontMetrics fm(font());
+ QFontMetrics fm = fontMetrics();
int fw = style()->pixelMetric(QStyle::PM_SpinBoxFrameWidth);
int h = fm.height() + fw * 2;
int w = fw * 4 + 10; // HACK: 10 = spinbox up/down arrows
diff --git a/muse2/muse/arranger/arranger.cpp b/muse2/muse/arranger/arranger.cpp
index e1205d6f..65a705e2 100644
--- a/muse2/muse/arranger/arranger.cpp
+++ b/muse2/muse/arranger/arranger.cpp
@@ -427,6 +427,7 @@ Arranger::Arranger(QMainWindow* parent, const char* name)
connect(canvas, SIGNAL(dropMidiFile(const QString&)), SIGNAL(dropMidiFile(const QString&)));
connect(canvas, SIGNAL(toolChanged(int)), SIGNAL(toolChanged(int)));
+ connect(song, SIGNAL(controllerChanged(Track*)), SLOT(controllerChanged(Track*)));
// connect(song, SIGNAL(posChanged(int, unsigned, bool)), SLOT(seek()));
// Removed p3.3.43
diff --git a/muse2/muse/arranger/pcanvas.cpp b/muse2/muse/arranger/pcanvas.cpp
index 82f2de45..57bf71ba 100644
--- a/muse2/muse/arranger/pcanvas.cpp
+++ b/muse2/muse/arranger/pcanvas.cpp
@@ -44,6 +44,10 @@
#include "midictrl.h"
#include "utils.h"
+//#define ABS(x) ((x) < 0) ? -(x) : (x))
+//#define ABS(x) (x>=0?x:-x)
+#define ABS(x) (abs(x))
+
//---------------------------------------------------------
// colorRect
// paints a rectangular icon with a given color
@@ -94,7 +98,8 @@ PartCanvas::PartCanvas(int* r, QWidget* parent, int sx, int sy)
setMouseTracking(true);
drag = DRAG_OFF;
curColorIndex = 0;
- automation.currentCtrl = 0;
+ //automation.currentCtrl = 0;
+ automation.currentCtrlValid = false;
automation.controllerState = doNothing;
automation.moveController = false;
partsChanged();
@@ -862,7 +867,8 @@ void PartCanvas::mouseRelease(const QPoint&)
// clear all the automation parameters
automation.moveController=false;
automation.controllerState = doNothing;
- automation.currentCtrl=0;
+ //automation.currentCtrl=0;
+ automation.currentCtrlValid = false;
automation.currentTrack=0;
automation.currentCtrlList=0;
}
@@ -3436,107 +3442,104 @@ void PartCanvas::drawAudioTrack(QPainter& p, const QRect& r, const QRect& bbox,
void PartCanvas::drawAutomation(QPainter& p, const QRect& rr, AudioTrack *t)
{
- ///QRect rr = p.worldMatrix().mapRect(r);
-
- ///p.save();
- ///p.resetTransform();
-
- int height=rr.bottom()-rr.top()-4; // limit height
-
- //printf("PartCanvas::drawAutomation x:%d y:%d w:%d h:%d height:%d\n", rr.x(), rr.y(), rr.width(), rr.height(), height);
-
- p.setBrush(Qt::NoBrush);
-
- CtrlListList* cll = t->controller();
- ///bool firstRun=true;
- for(CtrlListList::iterator icll =cll->begin();icll!=cll->end();++icll)
- {
- //iCtrlList *icl = icll->second;
- CtrlList *cl = icll->second;
- if (cl->dontShow())
- continue;
- double prevVal;
- iCtrl ic=cl->begin();
- if (!cl->isVisible())
- continue; // skip this iteration if this controller isn't in the visible list
- ///p.setPen(QPen(cl->color(),1,Qt::SolidLine));
- p.setPen(QPen(cl->color(), 0, Qt::SolidLine));
-
- // First check that there ARE automation, ic == cl->end means no automation
- if (ic != cl->end()) {
- CtrlVal cvFirst = ic->second;
- ic++;
- int prevPosFrame=cvFirst.frame;
- prevVal = cvFirst.val;
- ///bool discrete = cl->valueType() == VAL_BOOL || cl->mode() == CtrlList::DISCRETE; // Tim
-
- // prepare prevVal
- if (cl->valueType() == VAL_LOG ) { // use db scale for volume
- prevVal = dbToVal(cvFirst.val); // represent volume between 0 and 1
- if (prevVal < 0) prevVal = 0.0;
- }
- else {
- // we need to set curVal between 0 and 1
- double min, max;
- cl->range(&min,&max);
- prevVal = (prevVal- min)/(max-min);
- }
+ //QRect rr = p.worldMatrix().mapRect(r);
+ //p.save();
+ //p.resetTransform();
- // draw a square around the point
- p.drawRect(mapx(tempomap.frame2tick(prevPosFrame))-1, (rr.bottom()-2)-prevVal*height-1, 3, 3);
- p.drawRect(mapx(tempomap.frame2tick(prevPosFrame))-2, (rr.bottom()-2)-prevVal*height-2, 5, 5);
+ int bottom = rr.bottom() - 2;
+ int height = bottom - rr.top() - 2; // limit height
- bool firstRun=true;
- for (; ic !=cl->end(); ++ic)
- {
- CtrlVal cv = ic->second;
- double nextVal = cv.val; // was curVal
+ //printf("PartCanvas::drawAutomation x:%d y:%d w:%d h:%d height:%d\n", rr.x(), rr.y(), rr.width(), rr.height(), height);
+
+ p.setBrush(Qt::NoBrush);
+
+ CtrlListList* cll = t->controller();
+ for(CtrlListList::iterator icll =cll->begin();icll!=cll->end();++icll)
+ {
+ CtrlList *cl = icll->second;
+ if (cl->dontShow() || !cl->isVisible())
+ continue;
+ iCtrl ic=cl->begin();
+ int oldX = mapx(0);
+ if(rr.right() < oldX)
+ {
+ //p.restore();
+ return;
+ }
+ int xpixel = oldX;
+ int oldY = -1;
+ int ypixel = oldY;
+ double min, max;
+ cl->range(&min,&max);
+ //bool discrete = cl->valueType() == VAL_BOOL || cl->mode() == CtrlList::DISCRETE;
+ bool discrete = cl->mode() == CtrlList::DISCRETE;
+ QPen pen1(cl->color(), 0);
+ QPen pen2(cl->color(), 2);
+ pen2.setCosmetic(true);
+
+ // First check that there ARE automation, ic == cl->end means no automation
+ if (ic == cl->end())
+ {
+ double y;
+ if (cl->valueType() == VAL_LOG ) { // use db scale for volume
+ y = dbToVal(cl->curVal()); // represent volume between 0 and 1
+ if (y < 0) y = 0.0;
+ }
+ else
+ y = (cl->curVal() - min)/(max-min); // we need to set curVal between 0 and 1
+ ypixel = oldY = bottom - rmapy_f(y) * height;
+ }
+ else
+ {
+ for (; ic !=cl->end(); ++ic)
+ {
+ double y = ic->second.val;
if (cl->valueType() == VAL_LOG ) { // use db scale for volume
- nextVal = dbToVal(cv.val); // represent volume between 0 and 1
- if (nextVal < 0) nextVal = 0.0;
- }
- else {
- // we need to set curVal between 0 and 1
- double min, max;
- cl->range(&min,&max);
- nextVal = (nextVal- min)/(max-min);
+ y = dbToVal(y); // represent volume between 0 and 1
+ if (y < 0) y = 0.0;
}
- int leftX=mapx(tempomap.frame2tick(prevPosFrame));
- if (firstRun && leftX>rr.x()) {
- leftX=rr.x();
- }
- int currentPixel = mapx(tempomap.frame2tick(cv.frame));
+ else
+ y = (y-min)/(max-min); // we need to set curVal between 0 and 1
+
+ ypixel = bottom - rmapy_f(y) * height;
+ xpixel = mapx(tempomap.frame2tick(ic->second.frame));
+
+ if (oldY==-1) oldY = ypixel;
//printf(" line x1:%d x2:%d prevVal:%f nextVal:%f\n", leftX, currentPixel, prevVal, nextVal);
- p.drawLine( leftX,
- (rr.bottom()-2)-prevVal*height,
- currentPixel,
- (rr.bottom()-2)-nextVal*height);
-
- ///if(discrete)
- /// p.drawLine( currentPixel, (rr.bottom()-2)-prevVal*height, currentPixel, (rr.bottom()-2)-nextVal*height ); // Tim
-
- firstRun=false;
- prevPosFrame=cv.frame;
- prevVal=nextVal;
- if (currentPixel > rr.x()+ rr.width())
- ///goto quitDrawing;
- break;
+ p.setPen(pen1);
+ if(discrete)
+ {
+ p.drawLine(oldX, oldY, xpixel, oldY);
+ p.drawLine(xpixel, oldY, xpixel, ypixel);
+ }
+ else
+ p.drawLine(oldX, oldY, xpixel, ypixel);
+
+ if (xpixel > rr.right())
+ break;
// draw a square around the point
- p.drawRect(mapx(tempomap.frame2tick(prevPosFrame))-2, (rr.bottom()-2)-prevVal*height-2, 5, 5);
- p.drawRect(mapx(tempomap.frame2tick(prevPosFrame))-1, (rr.bottom()-1)-prevVal*height-2, 3, 3);
- }
- //printf(" endline prevVal:%f\n", prevVal);
- p.drawLine(mapx(tempomap.frame2tick(prevPosFrame)),
- (rr.bottom()-2)-prevVal*height,
- rr.x()+rr.width(),
- (rr.bottom()-2)-prevVal*height);
- }
- }
-///quitDrawing:
- ///p.restore();
- return;
+ //p.drawRect(mapx(tempomap.frame2tick(prevPosFrame))-2, (rr.bottom()-2)-prevVal*height-2, 5, 5);
+ //p.drawRect(mapx(tempomap.frame2tick(prevPosFrame))-1, (rr.bottom()-1)-prevVal*height-2, 3, 3);
+ pen2.setColor((automation.currentCtrlValid && automation.currentCtrlList == cl &&
+ automation.currentCtrlFrame == ic->second.frame) ?
+ Qt::white : cl->color());
+
+ p.setPen(pen2);
+ p.drawRect(xpixel-2, ypixel-2, 5, 5);
+ oldX = xpixel;
+ oldY = ypixel;
+ }
+ }
+ if (xpixel <= rr.right())
+ {
+ //printf(" endline prevVal:%f\n", prevVal);
+ p.setPen(pen1);
+ p.drawLine(xpixel, ypixel, rr.right(), ypixel);
+ }
+ }
+ //p.restore();
}
@@ -3553,60 +3556,68 @@ void PartCanvas::drawAutomation(QPainter& p, const QRect& rr, AudioTrack *t)
void PartCanvas::checkAutomation(Track * t, const QPoint &pointer, bool addNewCtrl)
{
- int circumference = 5;
if (t->isMidiTrack())
return;
+ int currY;
+ int trackY = t->y();
+ int trackH = t->height();
+
+ { int y = pointer.y();
+ if(y < trackY || y >= (trackY + trackH))
+ return;
+ currY = mapy(y); }
+
int currX = mapx(pointer.x());
- int currY = mapy(pointer.y());
-
+ int circumference = 5;
+
CtrlListList* cll = ((AudioTrack*) t)->controller();
for(CtrlListList::iterator icll =cll->begin();icll!=cll->end();++icll)
{
- //iCtrlList *icl = icll->second;
CtrlList *cl = icll->second;
if (cl->dontShow() || !cl->isVisible()) {
continue;
}
iCtrl ic=cl->begin();
- int oldX=-1;
- int oldY=-1;
- int ypixel=0;
- int xpixel=-1;
+ int oldX = mapx(0);
+ int xpixel = oldX;
+ int oldY = -1;
+ int ypixel = oldY;
+ double min, max;
+ cl->range(&min,&max);
+ //bool discrete = cl->valueType() == VAL_BOOL || cl->mode() == CtrlList::DISCRETE; // Tim
// First check that there IS automation, ic == cl->end means no automation
- if (ic != cl->end()) {
+ if (ic == cl->end())
+ {
+ double y;
+ if (cl->valueType() == VAL_LOG ) { // use db scale for volume
+ y = dbToVal(cl->curVal()); // represent volume between 0 and 1
+ if (y < 0) y = 0.0;
+ }
+ 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);
+ }
+ else
+ {
for (; ic !=cl->end(); ic++)
{
- CtrlVal &cv = ic->second;
- double y;
+ double y = ic->second.val;
if (cl->valueType() == VAL_LOG ) { // use db scale for volume
- y = dbToVal(cv.val); // represent volume between 0 and 1
+ y = dbToVal(y); // represent volume between 0 and 1
if (y < 0) y = 0;
}
- else {
- // we need to set curVal between 0 and 1
- double min, max;
- cl->range(&min,&max);
- y = ( cv.val - min)/(max-min);
- }
-
- TrackList* tl = song->tracks();
- int yy = 0;
- for (iTrack it = tl->begin(); it != tl->end(); ++it) {
- Track* track = *it;
- yy += track->height();
- if (track == t)
- break;
- }
+ else
+ y = (y-min)/(max-min); // we need to set curVal between 0 and 1
- ypixel = mapy(yy-2-y*t->height());
- xpixel = mapx(tempomap.frame2tick(cv.frame));
+ ypixel = mapy(trackY + trackH - 2 - y * trackH);
+ xpixel = mapx(tempomap.frame2tick(ic->second.frame));
- if (oldX==-1) oldX = xpixel;
if (oldY==-1) oldY = ypixel;
-
+ //printf(" oldX:%d oldY:%d xpixel:%d ypixel:%d\n", oldX, oldY, xpixel, ypixel);
+
bool foundIt=false;
if (addNewCtrl) {
// check if we are reasonably close to a line
@@ -3618,14 +3629,15 @@ void PartCanvas::checkAutomation(Track * t, const QPoint &pointer, bool addNewCt
double proportion = (currX-firstX)/(lastX-firstX);
- if ( (currX > lastX && firstY!=lastY) // omit special cases.
- || firstX==lastX ) {
+ //if ( (currX > lastX && firstY!=lastY) // omit special cases.
+ // || firstX==lastX ) {
+ if((currX < oldX) || (currX > lastX) || (firstX==lastX) )
+ {
oldX = xpixel;
oldY = ypixel;
continue; // not the right region
}
-
// 10 X(15) 20
// proportion = 0.5
// 10
@@ -3635,15 +3647,12 @@ void PartCanvas::checkAutomation(Track * t, const QPoint &pointer, bool addNewCt
// 1
double calcY = (lastY-firstY)*proportion+firstY;
//printf("calcY=%f currY=%d\n", calcY, currY);
- if ( abs(calcY-currY) < circumference*4)
- foundIt=true;
-
- if ( xpixel == oldX && abs(currX-xpixel) < circumference)
+ if(ABS(calcY-currY) < circumference || (xpixel == oldX && ABS(currX-xpixel) < circumference))
foundIt=true;
-
+
} else {
- int x1 = abs(currX - xpixel) ;
- int y1 = abs(currY - ypixel);
+ int x1 = ABS(currX - xpixel) ;
+ int y1 = ABS(currY - ypixel);
if (x1 < circumference && y1 < circumference && pointer.x() > 0 && pointer.y() > 0) {
foundIt=true;
}
@@ -3655,10 +3664,14 @@ void PartCanvas::checkAutomation(Track * t, const QPoint &pointer, bool addNewCt
if (foundIt) {
QWidget::setCursor(Qt::CrossCursor);
if (addNewCtrl) {
- automation.currentCtrl = 0;
+ //automation.currentCtrl = 0;
+ automation.currentCtrlValid = false;
automation.controllerState = addNewController;
}else {
- automation.currentCtrl=&cv;
+ //automation.currentCtrl=&ic->second;
+ automation.currentCtrlFrame = ic->second.frame;
+ //automation.currentCtrlVal = ic->second.val;
+ automation.currentCtrlValid = true;
automation.controllerState = movingController;
}
automation.currentCtrlList = cl;
@@ -3666,37 +3679,36 @@ void PartCanvas::checkAutomation(Track * t, const QPoint &pointer, bool addNewCt
return;
}
}
- } // if
+ }
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
- bool foundIt=false;
- if ( ypixel == oldY && abs(currY-ypixel) < circumference) {
- foundIt=true;
- }
-
- if (foundIt) {
+ // 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.currentCtrl = 0;
+ //automation.currentCtrl = 0;
+ automation.currentCtrlValid = false;
return;
}
}
}
// if there are no hits we default to clearing all the data
automation.controllerState = doNothing;
- automation.currentCtrl = 0;
+ //automation.currentCtrl = 0;
+ automation.currentCtrlValid = false;
automation.currentCtrlList = 0;
automation.currentTrack = 0;
setCursor();
}
-void PartCanvas::controllerChanged(Track* /* t */)
+void PartCanvas::controllerChanged(Track* t)
{
- redraw();
+ //redraw();
+ redraw((QRect(0, mapy(t->y()), width(), rmapy(t->height())))); // TODO Check this - correct?
}
void PartCanvas::processAutomationMovements(QPoint pos, bool addPoint)
@@ -3716,18 +3728,24 @@ void PartCanvas::processAutomationMovements(QPoint pos, bool addPoint)
int prevFrame = 0;
int nextFrame = -1;
+ int currFrame = 0;
if (automation.controllerState == addNewController)
{
//printf("adding a new ctrler!\n");
int frame = tempomap.tick2frame(pos.x());
- automation.currentCtrlList->add( frame, 1.0 /*dummy value */);
+ // FIXME Inefficient to add with wait here, then remove and add with wait again below. Tim.
+ audio->msgAddACEvent((AudioTrack*)automation.currentTrack, automation.currentCtrlList->id(), frame, 1.0 /*dummy value */);
+ //song->addACEvent((AudioTrack*)automation.currentTrack, automation.currentCtrlList->id(), frame, 1.0 /*dummy value */);
iCtrl ic=automation.currentCtrlList->begin();
- for (; ic !=automation.currentCtrlList->end(); ic++) {
+ for (; ic !=automation.currentCtrlList->end(); ++ic) {
CtrlVal &cv = ic->second;
if (cv.frame == frame) {
- automation.currentCtrl = &cv;
+ //automation.currentCtrl = &cv;
+ automation.currentCtrlFrame = cv.frame;
+ //automation.currentCtrlVal = cv.val;
+ automation.currentCtrlValid = true;
automation.controllerState = movingController;
break;
}
@@ -3736,22 +3754,38 @@ void PartCanvas::processAutomationMovements(QPoint pos, bool addPoint)
// get previous and next frame position to give x bounds for this event.
iCtrl ic=automation.currentCtrlList->begin();
- for (; ic !=automation.currentCtrlList->end(); ic++)
+ iCtrl iprev = ic;
+ for (; ic !=automation.currentCtrlList->end(); ++ic)
{
CtrlVal &cv = ic->second;
- if (&cv == automation.currentCtrl)
+ //if (&cv == automation.currentCtrl)
+ if (cv.frame == automation.currentCtrlFrame)
+ {
+ currFrame = cv.frame;
break;
+ }
prevFrame = cv.frame;
+ iprev = ic;
}
+
+ iCtrl icc = ic;
+
if ( ++ic != automation.currentCtrlList->end()) {
CtrlVal &cv = ic->second;
nextFrame = cv.frame;
}
- int currFrame = tempomap.tick2frame(pos.x());
- if (currFrame < prevFrame) currFrame=prevFrame+1;
- if (nextFrame!=-1 && currFrame > nextFrame) currFrame=nextFrame-1;
- automation.currentCtrl->frame = currFrame;
-
+
+ // A perfectly straight vertical line (two points with same frame) is impossible:
+ // there is only one value at t, and the next value at t+1, and so on.
+ // Also these are maps, not multimaps. p4.0.32 Tim.
+ int newFrame = tempomap.tick2frame(pos.x());
+ //if(currFrame == 0)
+ // newFrame = 0; // Force first item to stay at x = 0.
+ //else
+ if (newFrame <= prevFrame)
+ newFrame=prevFrame + (icc == automation.currentCtrlList->begin() ? 0: 1); // Only first item is allowed to go to zero x.
+ if (nextFrame!=-1 && newFrame >= nextFrame) newFrame=nextFrame-1;
+
int posy=mapy(pos.y());
int tracky = mapy(automation.currentTrack->y());
int trackHeight = automation.currentTrack->height();
@@ -3760,29 +3794,38 @@ void PartCanvas::processAutomationMovements(QPoint pos, bool addPoint)
int mouseY = trackHeight - (posy - tracky)-2;
double yfraction = ((double)mouseY)/automation.currentTrack->height();
+ double min, max;
+ automation.currentCtrlList->range(&min,&max);
+ double cvval;
if (automation.currentCtrlList->valueType() == VAL_LOG ) { // use db scale for volume
-
- double cvval = valToDb(yfraction);
+ 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 {
- // we need to set curVal between 0 and 1
- double min, max;
- automation.currentCtrlList->range(&min,&max);
- double cvval = yfraction * (max-min) + min;
-
+ // we need to set val between 0 and 1 (unless integer)
+ cvval = yfraction * (max-min) + min;
+ // 'Snap' to integer or boolean
+ if (automation.currentCtrlList->valueType() == VAL_INT || automation.currentCtrlList->valueType() == VAL_BOOL)
+ cvval = rint(cvval + 0.1); // LADSPA docs say add a slight bias to avoid rounding errors. Try this.
if (cvval< min) cvval=min;
if (cvval>max) cvval=max;
- automation.currentCtrl->val = cvval;
}
- controllerChanged(automation.currentTrack);
-
+
+ automation.currentCtrlFrame = newFrame;
+ //automation.currentCtrlVal = cvval;
+ automation.currentCtrlValid = true;
+
+ if(icc != automation.currentCtrlList->end())
+ audio->msgChangeACEvent((AudioTrack*)automation.currentTrack, automation.currentCtrlList->id(), icc->second.frame, newFrame, cvval);
+ //song->changeACEvent((AudioTrack*)automation.currentTrack, automation.currentCtrlList->id(), icc->second.frame, newFrame, cvval);
+ else
+ audio->msgAddACEvent((AudioTrack*)automation.currentTrack, automation.currentCtrlList->id(), newFrame, cvval);
+ //song->addACEvent((AudioTrack*)automation.currentTrack, automation.currentCtrlList->id(), newFrame, cvval);
+
+ // Not needed. Redraw is now handled by msgXXX().
+ //controllerChanged(automation.currentTrack);
}
}
diff --git a/muse2/muse/arranger/pcanvas.h b/muse2/muse/arranger/pcanvas.h
index 05f380e6..210557dc 100644
--- a/muse2/muse/arranger/pcanvas.h
+++ b/muse2/muse/arranger/pcanvas.h
@@ -43,7 +43,9 @@ class NPart : public CItem {
enum ControllerVals { doNothing, movingController, addNewController };
struct AutomationObject {
- CtrlVal *currentCtrl;
+ //CtrlVal *currentCtrl;
+ int currentCtrlFrame;
+ bool currentCtrlValid;
CtrlList *currentCtrlList;
Track *currentTrack;
bool moveController;
@@ -154,8 +156,10 @@ class PartCanvas : public Canvas {
PartCanvas(int* raster, QWidget* parent, int, int);
void partsChanged();
void cmd(int);
- void controllerChanged(Track *t);
public slots:
void redirKeypress(QKeyEvent* e) { keyPress(e); }
- };
+ void controllerChanged(Track *t);
+};
+
#endif
+
diff --git a/muse2/muse/audio.cpp b/muse2/muse/audio.cpp
index 975054b0..668c2a30 100644
--- a/muse2/muse/audio.cpp
+++ b/muse2/muse/audio.cpp
@@ -80,6 +80,7 @@ const char* seqMsgList[] = {
"AUDIO_ERASE_AC_EVENT",
"AUDIO_ERASE_RANGE_AC_EVENTS",
"AUDIO_ADD_AC_EVENT",
+ "AUDIO_CHANGE_AC_EVENT",
"AUDIO_SET_SOLO", "AUDIO_SET_SEND_METRONOME",
"MS_PROCESS", "MS_STOP", "MS_SET_RTC", "MS_UPDATE_POLL_FD",
"SEQM_IDLE", "SEQM_SEEK"
@@ -675,6 +676,9 @@ void Audio::processMsg(AudioMsg* msg)
case AUDIO_ADD_AC_EVENT:
msg->snode->addACEvent(msg->ival, msg->a, msg->dval);
break;
+ case AUDIO_CHANGE_AC_EVENT:
+ msg->snode->changeACEvent(msg->ival, msg->a, msg->b, msg->dval);
+ break;
case AUDIO_SET_SOLO:
msg->track->setSolo((bool)msg->ival);
break;
diff --git a/muse2/muse/audio.h b/muse2/muse/audio.h
index e332f516..ea9986c3 100644
--- a/muse2/muse/audio.h
+++ b/muse2/muse/audio.h
@@ -74,6 +74,7 @@ enum {
AUDIO_ERASE_AC_EVENT,
AUDIO_ERASE_RANGE_AC_EVENTS,
AUDIO_ADD_AC_EVENT,
+ AUDIO_CHANGE_AC_EVENT,
AUDIO_SET_SOLO, AUDIO_SET_SEND_METRONOME,
MS_PROCESS, MS_STOP, MS_SET_RTC, MS_UPDATE_POLL_FD,
SEQM_IDLE, SEQM_SEEK,
@@ -253,6 +254,7 @@ class Audio {
void msgEraseACEvent(AudioTrack*, int, int);
void msgEraseRangeACEvents(AudioTrack*, int, int, int);
void msgAddACEvent(AudioTrack*, int, int, double);
+ void msgChangeACEvent(AudioTrack* node, int acid, int frame, int newFrame, double val);
void msgSetSolo(Track*, bool);
void msgSetHwCtrlState(MidiPort*, int, int, int);
void msgSetHwCtrlStates(MidiPort*, int, int, int, int);
diff --git a/muse2/muse/audiotrack.cpp b/muse2/muse/audiotrack.cpp
index b004638f..42229111 100644
--- a/muse2/muse/audiotrack.cpp
+++ b/muse2/muse/audiotrack.cpp
@@ -253,16 +253,11 @@ void AudioTrack::addPlugin(PluginI* plugin, int idx)
const char* name = plugin->paramName(i);
float min, max;
plugin->range(i, &min, &max);
- CtrlValueType t = plugin->valueType();
CtrlList* cl = new CtrlList(id);
cl->setRange(min, max);
cl->setName(QString(name));
- cl->setValueType(t);
- LADSPA_PortRangeHint range = plugin->range(i);
- if(LADSPA_IS_HINT_TOGGLED(range.HintDescriptor))
- cl->setMode(CtrlList::DISCRETE);
- else
- cl->setMode(CtrlList::INTERPOLATE);
+ cl->setValueType(plugin->ctrlValueType(i));
+ cl->setMode(plugin->ctrlMode(i));
cl->setCurVal(plugin->param(i));
addController(cl);
}
@@ -700,6 +695,22 @@ void AudioTrack::addACEvent(int id, int frame, double val)
}
//---------------------------------------------------------
+// changeACEvent
+//---------------------------------------------------------
+
+void AudioTrack::changeACEvent(int id, int frame, int newframe, double newval)
+{
+ ciCtrlList icl = _controller.find(id);
+ if(icl == _controller.end())
+ return;
+ CtrlList* cl = icl->second;
+ iCtrl ic = cl->find(frame);
+ if(ic != cl->end())
+ cl->erase(ic);
+ cl->insert(std::pair<const int, CtrlVal> (newframe, CtrlVal(newframe, newval)));
+}
+
+//---------------------------------------------------------
// volume
//---------------------------------------------------------
@@ -1039,11 +1050,8 @@ bool AudioTrack::readProperties(Xml& xml, const QString& tag)
if(ctlfound)
{
l->setCurVal(p->param(m));
- LADSPA_PortRangeHint range = p->range(m);
- if(LADSPA_IS_HINT_TOGGLED(range.HintDescriptor))
- l->setMode(CtrlList::DISCRETE);
- else
- l->setMode(CtrlList::INTERPOLATE);
+ l->setValueType(p->ctrlValueType(m));
+ l->setMode(p->ctrlMode(m));
}
}
else
@@ -1139,15 +1147,10 @@ void AudioTrack::mapRackPluginsToControllers()
// 0.9pre1 med file with broken controller sections they may not be set correct.
float min, max;
p->range(i, &min, &max);
- CtrlValueType t = p->valueType();
l->setRange(min, max);
l->setName(QString(p->paramName(i)));
- l->setValueType(t);
- LADSPA_PortRangeHint rh = p->range(i);
- if(LADSPA_IS_HINT_TOGGLED(rh.HintDescriptor))
- l->setMode(CtrlList::DISCRETE);
- else
- l->setMode(CtrlList::INTERPOLATE);
+ l->setValueType(p->ctrlValueType(i));
+ l->setMode(p->ctrlMode(i));
l->setCurVal(p->param(i));
//l->setDefault(p->defaultValue(i));
}
diff --git a/muse2/muse/cliplist/cliplist.cpp b/muse2/muse/cliplist/cliplist.cpp
index 96636463..5a5796aa 100644
--- a/muse2/muse/cliplist/cliplist.cpp
+++ b/muse2/muse/cliplist/cliplist.cpp
@@ -26,7 +26,7 @@ enum { COL_NAME=0, COL_REFS, COL_POS, COL_LEN };
class ClipItem : public QTreeWidgetItem {
SndFileR _wf;
- virtual QString text(int) const;
+ //virtual QString text(int) const;
public:
ClipItem(QTreeWidget*, const SndFileR&);
@@ -36,6 +36,10 @@ class ClipItem : public QTreeWidgetItem {
ClipItem::ClipItem(QTreeWidget* parent, const SndFileR& w)
: QTreeWidgetItem(parent), _wf(w)
{
+ setText(COL_NAME, _wf.name());
+ setText(COL_REFS, QString().setNum(_wf.getRefCount()));
+ setText(COL_POS, QString().setNum(_wf.samplerate()));
+ setText(COL_LEN, QString().setNum(_wf.samples()));
}
//---------------------------------------------------------
@@ -71,6 +75,7 @@ static QString samples2smpte(int samples)
}
#endif
+/*
//---------------------------------------------------------
// text
//---------------------------------------------------------
@@ -91,6 +96,7 @@ QString ClipItem::text(int col) const
}
return s;
}
+*/
//---------------------------------------------------------
// ClipListEdit
diff --git a/muse2/muse/ctrl.cpp b/muse2/muse/ctrl.cpp
index 65a04ba1..0a863423 100644
--- a/muse2/muse/ctrl.cpp
+++ b/muse2/muse/ctrl.cpp
@@ -6,6 +6,7 @@
// controller handling for mixer automation
//
// (C) Copyright 2003 Werner Schweer (ws@seh.de)
+// (C) Copyright 2011 Time E. Real (terminator356 on users dot sourceforge dot net)
//=========================================================
@@ -83,66 +84,86 @@ CtrlList::CtrlList()
double CtrlList::value(int frame)
{
- if (!automation || empty()) {
- return _curVal;
- }
+ // Changed by Tim. p4.0.32...
+
+ ///if (!automation || empty())
+ /// return _curVal;
+ if(empty())
+ return _curVal;
+ double rv;
ciCtrl i = upper_bound(frame); // get the index after current frame
if (i == end()) { // if we are past all items just return the last value
- ciCtrl i = end();
+ ///ciCtrl i = end();
--i;
- const CtrlVal& val = i->second;
- _curVal = val.val;
+ ///const CtrlVal& val = i->second;
+ ///_curVal = val.val;
+ rv = i->second.val;
}
else if(_mode == DISCRETE)
{
if(i == begin())
- _curVal = _default;
+ {
+ ///_curVal = _default;
+ //if(i->second.frame == frame)
+ rv = i->second.val;
+ //else
+ // rv = _default;
+ }
else
{
--i;
- const CtrlVal& val = i->second;
- _curVal = val.val;
+ ///const CtrlVal& val = i->second;
+ ///_curVal = val.val;
+ rv = i->second.val;
}
}
else {
- int frame2 = i->second.frame;
- double val2 = i->second.val;
- int frame1;
- double val1;
+ ///int frame2 = i->second.frame;
+ ///double val2 = i->second.val;
+ ///int frame1;
+ ///double val1;
if (i == begin()) {
- frame1 = 0;
- val1 = _default;
+ ///frame1 = 0;
+ ///val1 = _default;
+ rv = i->second.val;
}
else {
+ int frame2 = i->second.frame;
+ double val2 = i->second.val;
--i;
- frame1 = i->second.frame;
- val1 = i->second.val;
- }
- //printf("before val1=%f val2=%f\n", val1,val2);
- if (_valueType == VAL_LOG) {
- val1 = 20.0*fast_log10(val1);
- if (val1 < config.minSlider)
- val1=config.minSlider;
- val2 = 20.0*fast_log10(val2);
- if (val2 < config.minSlider)
- val2=config.minSlider;
- }
- //printf("after val1=%f val2=%f\n", val1,val2);
- frame -= frame1;
- val2 -= val1;
- frame2 -= frame1;
- val1 += (double(frame) * val2)/double(frame2);
-
- if (_valueType == VAL_LOG) {
- val1 = exp10(val1/20.0);
- }
- //printf("after val1=%f\n", val1);
- _curVal = val1;
+ ///frame1 = i->second.frame;
+ ///val1 = i->second.val;
+ int frame1 = i->second.frame;
+ double val1 = i->second.val;
+ ///}
+ //printf("before val1=%f val2=%f\n", val1,val2);
+ if (_valueType == VAL_LOG) {
+ val1 = 20.0*fast_log10(val1);
+ if (val1 < config.minSlider)
+ val1=config.minSlider;
+ val2 = 20.0*fast_log10(val2);
+ if (val2 < config.minSlider)
+ val2=config.minSlider;
+ }
+ //printf("after val1=%f val2=%f\n", val1,val2);
+ frame -= frame1;
+ val2 -= val1;
+ frame2 -= frame1;
+ val1 += (double(frame) * val2)/double(frame2);
+
+ if (_valueType == VAL_LOG) {
+ val1 = exp10(val1/20.0);
+ }
+ //printf("after val1=%f\n", val1);
+ ///_curVal = val1;
+ rv = val1;
+ }
}
// printf("autoVal %d %f\n", frame, _curVal);
- return _curVal;
+ ///return _curVal;
+ return rv;
}
@@ -152,9 +173,8 @@ double CtrlList::value(int frame)
void CtrlList::setCurVal(double val)
{
_curVal = val;
- if (size() < 2) {
- add(0,val);
- }
+ //if (size() < 2) // Removed p4.0.32
+ // add(0,val);
}
//---------------------------------------------------------
@@ -175,16 +195,14 @@ void CtrlList::add(int frame, double val)
// del
//---------------------------------------------------------
-void CtrlList::del(int /* frame*/)
+void CtrlList::del(int frame)
{
- /*
iCtrl e = find(frame);
if (e == end()) {
- printf("CtrlList::del(%d): not found\n", frame);
+ //printf("CtrlList::del(%d): not found\n", frame);
return;
}
erase(e);
- */
}
//---------------------------------------------------------
diff --git a/muse2/muse/ctrl.h b/muse2/muse/ctrl.h
index 34a31211..14f23643 100644
--- a/muse2/muse/ctrl.h
+++ b/muse2/muse/ctrl.h
@@ -6,6 +6,7 @@
// controller for mixer automation
//
// (C) Copyright 2003-2004 Werner Schweer (ws@seh.de)
+// (C) Copyright 2011 Time E. Real (terminator356 on users dot sourceforge dot net)
//=========================================================
#ifndef __CTRL_H__
@@ -120,8 +121,8 @@ class CtrlList : public std::map<int, CtrlVal, std::less<int> > {
void setValueType(CtrlValueType t) { _valueType = t; }
double value(int frame);
- void add(int tick, double value);
- void del(int tick);
+ void add(int frame, double value);
+ void del(int frame);
void read(Xml& xml);
void setColor( QColor c ) { _displayColor = c;}
diff --git a/muse2/muse/dssihost.cpp b/muse2/muse/dssihost.cpp
index 850fc8b8..72456dd1 100644
--- a/muse2/muse/dssihost.cpp
+++ b/muse2/muse/dssihost.cpp
@@ -1092,17 +1092,8 @@ bool DssiSynthIF::init(DssiSynth* s)
}
cl->setRange(min, max);
cl->setName(QString(name));
- LADSPA_PortRangeHint range = ld->PortRangeHints[k];
- if(LADSPA_IS_HINT_TOGGLED(range.HintDescriptor))
- {
- cl->setMode(CtrlList::DISCRETE);
- cl->setValueType(VAL_BOOL);
- }
- else
- {
- cl->setMode(CtrlList::INTERPOLATE);
- cl->setValueType(VAL_LINEAR);
- }
+ cl->setValueType(ladspaCtrlValueType(ld, k));
+ cl->setMode(ladspaCtrlMode(ld, k));
ld->connect_port(handle, k, &controls[cip].val);
@@ -3627,6 +3618,8 @@ const char* DssiSynthIF::paramOutName(unsigned long i) { return (synth &&
//LADSPA_PortRangeHint DssiSynthIF::range(unsigned long i) { return (synth && synth->dssi) ? synth->dssi->LADSPA_Plugin->PortRangeHints[i] : 0; }
LADSPA_PortRangeHint DssiSynthIF::range(unsigned long i) { return synth->dssi->LADSPA_Plugin->PortRangeHints[controls[i].idx]; }
LADSPA_PortRangeHint DssiSynthIF::rangeOut(unsigned long i) { return synth->dssi->LADSPA_Plugin->PortRangeHints[controlsOut[i].idx]; }
+CtrlValueType DssiSynthIF::ctrlValueType(unsigned long i) const { return ladspaCtrlValueType(synth->dssi->LADSPA_Plugin, controls[i].idx); }
+CtrlList::Mode DssiSynthIF::ctrlMode(unsigned long i) const { return ladspaCtrlMode(synth->dssi->LADSPA_Plugin, controls[i].idx); };
#else //DSSI_SUPPORT
diff --git a/muse2/muse/dssihost.h b/muse2/muse/dssihost.h
index d46cb570..12be7b50 100644
--- a/muse2/muse/dssihost.h
+++ b/muse2/muse/dssihost.h
@@ -282,6 +282,8 @@ class DssiSynthIF : public SynthIF, public PluginIBase
const char* paramOutName(unsigned long /*i*/);
LADSPA_PortRangeHint range(unsigned long /*i*/);
LADSPA_PortRangeHint rangeOut(unsigned long /*i*/);
+ CtrlValueType ctrlValueType(unsigned long /*i*/) const;
+ CtrlList::Mode ctrlMode(unsigned long /*i*/) const;
friend class DssiSynth;
};
diff --git a/muse2/muse/mixer/astrip.cpp b/muse2/muse/mixer/astrip.cpp
index 658a4970..97ddc98c 100644
--- a/muse2/muse/mixer/astrip.cpp
+++ b/muse2/muse/mixer/astrip.cpp
@@ -209,15 +209,19 @@ void AudioStrip::songChanged(int val)
if (autoType && (val & SC_AUTOMATION)) {
autoType->blockSignals(true);
autoType->setCurrentItem(track->automationType());
+ QPalette palette;
if(track->automationType() == AUTO_TOUCH || track->automationType() == AUTO_WRITE)
{
- QPalette palette;
palette.setColor(QPalette::Button, QColor(Qt::red));
autoType->setPalette(palette);
}
+ else if(track->automationType() == AUTO_READ)
+ {
+ palette.setColor(QPalette::Button, QColor(Qt::green));
+ autoType->setPalette(palette);
+ }
else
{
- QPalette palette;
palette.setColor(QPalette::Button, qApp->palette().color(QPalette::Active, QPalette::Background));
autoType->setPalette(palette);
}
@@ -394,13 +398,14 @@ void AudioStrip::volumeChanged(double val)
else
vol = pow(10.0, val/20.0);
volume = vol;
- //audio->msgSetVolume((AudioTrack*)track, vol);
+ audio->msgSetVolume((AudioTrack*)track, vol);
// p4.0.21 audio->msgXXX waits. Do we really need to?
- ((AudioTrack*)track)->setVolume(vol);
+ //((AudioTrack*)track)->setVolume(vol);
((AudioTrack*)track)->recordAutomation(AC_VOLUME, vol);
- song->update(SC_TRACK_MODIFIED); // for graphical automation update
+ //song->update(SC_TRACK_MODIFIED); // for graphical automation update
+ //song->controllerChange(track);
}
//---------------------------------------------------------
@@ -422,9 +427,9 @@ void AudioStrip::volumePressed()
else
vol = pow(10.0, val/20.0);
volume = vol;
- //audio->msgSetVolume((AudioTrack*)track, volume);
+ audio->msgSetVolume((AudioTrack*)track, volume);
// p4.0.21 audio->msgXXX waits. Do we really need to?
- ((AudioTrack*)track)->setVolume(volume);
+ //((AudioTrack*)track)->setVolume(volume);
((AudioTrack*)track)->startAutoRecord(AC_VOLUME, volume);
}
@@ -468,9 +473,9 @@ void AudioStrip::volLabelChanged(double val)
vol = pow(10.0, val/20.0);
volume = vol;
slider->setValue(val);
- //audio->msgSetVolume((AudioTrack*)track, vol);
+ audio->msgSetVolume((AudioTrack*)track, vol);
// p4.0.21 audio->msgXXX waits. Do we really need to?
- ((AudioTrack*)track)->setVolume(vol);
+ //((AudioTrack*)track)->setVolume(vol);
((AudioTrack*)track)->startAutoRecord(AC_VOLUME, vol);
}
@@ -486,9 +491,9 @@ void AudioStrip::panChanged(double val)
track->enablePanController(false);
panVal = val;
- //audio->msgSetPan(((AudioTrack*)track), val);
+ audio->msgSetPan(((AudioTrack*)track), val);
// p4.0.21 audio->msgXXX waits. Do we really need to?
- ((AudioTrack*)track)->setPan(val);
+ //((AudioTrack*)track)->setPan(val);
((AudioTrack*)track)->recordAutomation(AC_PAN, val);
}
@@ -504,9 +509,9 @@ void AudioStrip::panPressed()
track->enablePanController(false);
panVal = pan->value();
- //audio->msgSetPan(((AudioTrack*)track), panVal);
+ audio->msgSetPan(((AudioTrack*)track), panVal);
// p4.0.21 audio->msgXXX waits. Do we really need to?
- ((AudioTrack*)track)->setPan(panVal);
+ //((AudioTrack*)track)->setPan(panVal);
((AudioTrack*)track)->startAutoRecord(AC_PAN, panVal);
}
@@ -541,9 +546,9 @@ void AudioStrip::panLabelChanged(double val)
panVal = val;
pan->setValue(val);
- //audio->msgSetPan((AudioTrack*)track, val);
+ audio->msgSetPan((AudioTrack*)track, val);
// p4.0.21 audio->msgXXX waits. Do we really need to?
- ((AudioTrack*)track)->setPan(val);
+ //((AudioTrack*)track)->setPan(val);
((AudioTrack*)track)->startAutoRecord(AC_PAN, val);
}
@@ -935,15 +940,19 @@ AudioStrip::AudioStrip(QWidget* parent, AudioTrack* at)
autoType->addAction(tr("Write"), AUTO_WRITE);
autoType->setCurrentItem(t->automationType());
+ QPalette palette;
if(t->automationType() == AUTO_TOUCH || t->automationType() == AUTO_WRITE)
{
- QPalette palette;
palette.setColor(QPalette::Button, QColor(Qt::red));
autoType->setPalette(palette);
}
+ else if(t->automationType() == AUTO_READ)
+ {
+ palette.setColor(QPalette::Button, QColor(Qt::green));
+ autoType->setPalette(palette);
+ }
else
{
- QPalette palette;
palette.setColor(QPalette::Button, qApp->palette().color(QPalette::Active, QPalette::Background));
autoType->setPalette(palette);
}
diff --git a/muse2/muse/mixer/panknob.cpp b/muse2/muse/mixer/panknob.cpp
index c99f0bd5..598bf5bf 100644
--- a/muse2/muse/mixer/panknob.cpp
+++ b/muse2/muse/mixer/panknob.cpp
@@ -27,9 +27,9 @@ PanKnob::PanKnob(QWidget* parent, AudioTrack* s)
void PanKnob::valueChanged(double val)
{
- //audio->msgSetPan(src, val);
+ audio->msgSetPan(src, val);
// p4.0.21 audio->msgXXX waits. Do we really need to?
- src->setPan(val);
+ //src->setPan(val);
}
diff --git a/muse2/muse/mplugins/rhythmbase.ui b/muse2/muse/mplugins/rhythmbase.ui
index 21373690..7d3458d1 100644
--- a/muse2/muse/mplugins/rhythmbase.ui
+++ b/muse2/muse/mplugins/rhythmbase.ui
@@ -542,9 +542,11 @@ Random Rhythm Generator is not enabled yet!</string>
<height>38</height>
</rect>
</property>
- <property name="label">
- <string>Tools</string>
- </property>
+ <widget class="QLabel">
+ <property name="text">
+ <string>Tools</string>
+ </property>
+ </widget>
<addaction name="fileNewAction"/>
<addaction name="fileOpenAction"/>
<addaction name="fileSaveAction"/>
diff --git a/muse2/muse/plugin.cpp b/muse2/muse/plugin.cpp
index 215a7844..e6027c6f 100644
--- a/muse2/muse/plugin.cpp
+++ b/muse2/muse/plugin.cpp
@@ -445,7 +445,44 @@ float midi2LadspaValue(const LADSPA_Descriptor* plugin, unsigned long port, int
return ret;
}
+//---------------------------------------------------------
+// ladspaCtrlValueType
+//---------------------------------------------------------
+CtrlValueType ladspaCtrlValueType(const LADSPA_Descriptor* plugin, int port)
+{
+ LADSPA_PortRangeHint range = plugin->PortRangeHints[port];
+ LADSPA_PortRangeHintDescriptor desc = range.HintDescriptor;
+
+ if(desc & LADSPA_HINT_INTEGER)
+ return VAL_INT;
+ else if(desc & LADSPA_HINT_LOGARITHMIC)
+ return VAL_LOG;
+ else if(desc & LADSPA_HINT_TOGGLED)
+ return VAL_BOOL;
+ else
+ return VAL_LINEAR;
+}
+
+//---------------------------------------------------------
+// ladspaCtrlMode
+//---------------------------------------------------------
+
+CtrlList::Mode ladspaCtrlMode(const LADSPA_Descriptor* plugin, int port)
+{
+ LADSPA_PortRangeHint range = plugin->PortRangeHints[port];
+ LADSPA_PortRangeHintDescriptor desc = range.HintDescriptor;
+
+ if(desc & LADSPA_HINT_INTEGER)
+ return CtrlList::DISCRETE;
+ else if(desc & LADSPA_HINT_LOGARITHMIC)
+ return CtrlList::INTERPOLATE;
+ else if(desc & LADSPA_HINT_TOGGLED)
+ return CtrlList::DISCRETE;
+ else
+ return CtrlList::INTERPOLATE;
+}
+
// Works but not needed.
/*
//---------------------------------------------------------
@@ -1003,6 +1040,24 @@ float Plugin::defaultValue(unsigned long port) const
}
//---------------------------------------------------------
+// ctrlValueType
+//---------------------------------------------------------
+
+CtrlValueType Plugin::ctrlValueType(unsigned long i) const
+ {
+ return ladspaCtrlValueType(plugin, i);
+ }
+
+//---------------------------------------------------------
+// ctrlMode
+//---------------------------------------------------------
+
+CtrlList::Mode Plugin::ctrlMode(unsigned long i) const
+ {
+ return ladspaCtrlMode(plugin, i);
+ }
+
+//---------------------------------------------------------
// loadPluginLib
//---------------------------------------------------------
@@ -1699,21 +1754,12 @@ void PluginI::updateControllers()
for(unsigned long i = 0; i < controlPorts; ++i)
//audio->msgSetPluginCtrlVal(this, genACnum(_id, i), controls[i].val);
// p3.3.43
- //audio->msgSetPluginCtrlVal(_track, genACnum(_id, i), controls[i].val);
+ audio->msgSetPluginCtrlVal(_track, genACnum(_id, i), controls[i].val);
// p4.0.21 audio->msgXXX waits. Do we really need to?
- _track->setPluginCtrlVal(genACnum(_id, i), controls[i].val);
+ //_track->setPluginCtrlVal(genACnum(_id, i), controls[i].val); // TODO A faster bulk message
}
//---------------------------------------------------------
-// valueType
-//---------------------------------------------------------
-
-CtrlValueType PluginI::valueType() const
- {
- return VAL_LINEAR;
- }
-
-//---------------------------------------------------------
// setChannel
//---------------------------------------------------------
@@ -3718,9 +3764,9 @@ void PluginGui::ctrlPressed(int param)
if(track)
{
// p3.3.43
- //audio->msgSetPluginCtrlVal(track, id, val);
+ audio->msgSetPluginCtrlVal(track, id, val);
// p4.0.21 audio->msgXXX waits. Do we really need to?
- track->setPluginCtrlVal(id, val);
+ //track->setPluginCtrlVal(id, val);
track->startAutoRecord(id, val);
}
@@ -3737,9 +3783,9 @@ void PluginGui::ctrlPressed(int param)
if(track)
{
// p3.3.43
- //audio->msgSetPluginCtrlVal(track, id, val);
+ audio->msgSetPluginCtrlVal(track, id, val);
// p4.0.21 audio->msgXXX waits. Do we really need to?
- track->setPluginCtrlVal(id, val);
+ //track->setPluginCtrlVal(id, val);
track->startAutoRecord(id, val);
}
@@ -3831,9 +3877,9 @@ void PluginGui::sliderChanged(double val, int param)
if(track)
{
// p3.3.43
- //audio->msgSetPluginCtrlVal(track, id, val);
+ audio->msgSetPluginCtrlVal(track, id, val);
// p4.0.21 audio->msgXXX waits. Do we really need to?
- track->setPluginCtrlVal(id, val);
+ //track->setPluginCtrlVal(id, val);
track->recordAutomation(id, val);
}
@@ -3875,9 +3921,9 @@ void PluginGui::labelChanged(double val, int param)
if(track)
{
// p3.3.43
- //audio->msgSetPluginCtrlVal(track, id, val);
+ audio->msgSetPluginCtrlVal(track, id, val);
// p4.0.21 audio->msgXXX waits. Do we really need to?
- track->setPluginCtrlVal(id, val);
+ //track->setPluginCtrlVal(id, val);
track->startAutoRecord(id, val);
}
@@ -4277,9 +4323,9 @@ void PluginGui::guiParamChanged(int idx)
//if(track)
//{
// p3.3.43
- //audio->msgSetPluginCtrlVal(track, id, val);
+ audio->msgSetPluginCtrlVal(track, id, val);
// p4.0.21 audio->msgXXX waits. Do we really need to?
- track->setPluginCtrlVal(id, val);
+ //track->setPluginCtrlVal(id, val);
switch(type)
{
@@ -4413,9 +4459,9 @@ void PluginGui::guiSliderPressed(int idx)
//audio->msgSetPluginCtrlVal(((PluginI*)plugin), id, val);
// p3.3.43
- //audio->msgSetPluginCtrlVal(track, id, val);
+ audio->msgSetPluginCtrlVal(track, id, val);
// p4.0.21 audio->msgXXX waits. Do we really need to?
- track->setPluginCtrlVal(id, val);
+ //track->setPluginCtrlVal(id, val);
track->startAutoRecord(id, val);
diff --git a/muse2/muse/plugin.h b/muse2/muse/plugin.h
index 30cc5912..dec77d2f 100644
--- a/muse2/muse/plugin.h
+++ b/muse2/muse/plugin.h
@@ -177,6 +177,8 @@ class Plugin {
//double defaultValue(unsigned long port) const;
float defaultValue(unsigned long port) const; // p4.0.21
void range(unsigned long i, float*, float*) const;
+ CtrlValueType ctrlValueType(unsigned long /*i*/) const;
+ CtrlList::Mode ctrlMode(unsigned long /*i*/) const;
const char* portName(unsigned long i) {
return plugin ? plugin->PortNames[i] : 0;
@@ -354,6 +356,9 @@ class PluginIBase
virtual const char* paramOutName(unsigned long /*i*/) = 0;
virtual LADSPA_PortRangeHint range(unsigned long /*i*/) = 0;
virtual LADSPA_PortRangeHint rangeOut(unsigned long /*i*/) = 0;
+
+ virtual CtrlValueType ctrlValueType(unsigned long /*i*/) const = 0;
+ virtual CtrlList::Mode ctrlMode(unsigned long /*i*/) const = 0;
QString dssi_ui_filename() const;
//virtual void showGui(bool) = 0; // p4.0.20
@@ -499,7 +504,6 @@ class PluginI : public PluginIBase {
QString pluginLabel() const { return _plugin->label(); }
QString label() const { return _label; }
QString name() const { return _name; }
- CtrlValueType valueType() const;
QString lib() const { return _plugin->lib(); }
QString dirPath() const { return _plugin->dirPath(); }
QString fileName() const { return _plugin->fileName(); }
@@ -560,6 +564,8 @@ class PluginI : public PluginIBase {
LADSPA_PortRangeHint range(unsigned long i) { return _plugin->range(controls[i].idx); }
LADSPA_PortRangeHint rangeOut(unsigned long i) { return _plugin->range(controlsOut[i].idx); }
bool inPlaceCapable() const { return _plugin->inPlaceCapable(); }
+ CtrlValueType ctrlValueType(unsigned long i) const { return _plugin->ctrlValueType(controls[i].idx); }
+ CtrlList::Mode ctrlMode(unsigned long i) const { return _plugin->ctrlMode(controls[i].idx); };
};
//---------------------------------------------------------
@@ -650,6 +656,8 @@ extern bool ladspaDefaultValue(const LADSPA_Descriptor* plugin, unsigned long po
extern void ladspaControlRange(const LADSPA_Descriptor* plugin, unsigned long port, float* min, float* max);
extern bool ladspa2MidiControlValues(const LADSPA_Descriptor* plugin, unsigned long port, int ctlnum, int* min, int* max, int* def);
extern float midi2LadspaValue(const LADSPA_Descriptor* plugin, unsigned long port, int ctlnum, int val);
+extern CtrlValueType ladspaCtrlValueType(const LADSPA_Descriptor* plugin, int port);
+extern CtrlList::Mode ladspaCtrlMode(const LADSPA_Descriptor* plugin, int port);
//extern MidiController* ladspa2MidiController(const LADSPA_Descriptor* plugin, unsigned long port, int ctlnum);
#endif
diff --git a/muse2/muse/seqmsg.cpp b/muse2/muse/seqmsg.cpp
index 57aadc18..035ee949 100644
--- a/muse2/muse/seqmsg.cpp
+++ b/muse2/muse/seqmsg.cpp
@@ -338,6 +338,7 @@ void Audio::msgSetVolume(AudioTrack* src, double val)
msg.dval = val;
sendMsg(&msg);
//muse->arranger->controllerChanged(src);
+ song->controllerChange(src);
}
//---------------------------------------------------------
@@ -352,6 +353,7 @@ void Audio::msgSetPan(AudioTrack* node, double val)
msg.dval = val;
sendMsg(&msg);
//muse->arranger->controllerChanged(node);
+ song->controllerChange(node);
}
//---------------------------------------------------------
@@ -513,6 +515,7 @@ void Audio::msgSetPluginCtrlVal(AudioTrack* track, int param, double val)
msg.snode = track;
sendMsg(&msg);
//muse->arranger->controllerChanged(track);
+ song->controllerChange(track);
}
//---------------------------------------------------------
@@ -529,6 +532,7 @@ void Audio::msgSwapControllerIDX(AudioTrack* node, int idx1, int idx2)
msg.b = idx2;
sendMsg(&msg);
//muse->arranger->controllerChanged(node);
+ song->controllerChange(node);
}
//---------------------------------------------------------
@@ -544,6 +548,7 @@ void Audio::msgClearControllerEvents(AudioTrack* node, int acid)
msg.ival = acid;
sendMsg(&msg);
//muse->arranger->controllerChanged(node);
+ song->controllerChange(node);
}
//---------------------------------------------------------
@@ -588,6 +593,7 @@ void Audio::msgEraseACEvent(AudioTrack* node, int acid, int frame)
msg.a = frame;
sendMsg(&msg);
//muse->arranger->controllerChanged(node);
+ song->controllerChange(node);
}
//---------------------------------------------------------
@@ -605,6 +611,7 @@ void Audio::msgEraseRangeACEvents(AudioTrack* node, int acid, int frame1, int fr
msg.b = frame2;
sendMsg(&msg);
//muse->arranger->controllerChanged(node);
+ song->controllerChange(node);
}
//---------------------------------------------------------
@@ -622,6 +629,26 @@ void Audio::msgAddACEvent(AudioTrack* node, int acid, int frame, double val)
msg.dval = val;
sendMsg(&msg);
//muse->arranger->controllerChanged(node);
+ song->controllerChange(node);
+}
+
+//---------------------------------------------------------
+// msgChangeACEvent
+//---------------------------------------------------------
+
+void Audio::msgChangeACEvent(AudioTrack* node, int acid, int frame, int newFrame, double val)
+{
+ AudioMsg msg;
+
+ msg.id = AUDIO_CHANGE_AC_EVENT;
+ msg.snode = node;
+ msg.ival = acid;
+ msg.a = frame;
+ msg.b = newFrame;
+ msg.dval = val;
+ sendMsg(&msg);
+ //muse->arranger->controllerChanged(node);
+ song->controllerChange(node);
}
//---------------------------------------------------------
diff --git a/muse2/muse/song.cpp b/muse2/muse/song.cpp
index 6d0541a3..9d1c3afb 100644
--- a/muse2/muse/song.cpp
+++ b/muse2/muse/song.cpp
@@ -714,6 +714,23 @@ void Song::changeAllPortDrumCtrlEvents(bool add, bool drumonly)
}
}
+void Song::addACEvent(AudioTrack* t, int acid, int frame, double val)
+{
+ audio->msgAddACEvent(t, acid, frame, val);
+ emit controllerChanged(t);
+}
+
+void Song::changeACEvent(AudioTrack* t, int acid, int frame, int newFrame, double val)
+{
+ audio->msgChangeACEvent(t, acid, frame, newFrame, val);
+ emit controllerChanged(t);
+}
+
+void Song::controllerChange(Track* t)
+{
+ emit controllerChanged(t);
+}
+
//---------------------------------------------------------
// cmdAddRecordedEvents
// add recorded Events into part
diff --git a/muse2/muse/song.h b/muse2/muse/song.h
index 45751418..bb96b619 100644
--- a/muse2/muse/song.h
+++ b/muse2/muse/song.h
@@ -248,6 +248,10 @@ class Song : public QObject {
void cmdChangeWave(QString original, QString tmpfile, unsigned sx, unsigned ex);
void remapPortDrumCtrlEvents(int mapidx, int newnote, int newchan, int newport);
void changeAllPortDrumCtrlEvents(bool add, bool drumonly = false);
+
+ void addACEvent(AudioTrack* t, int acid, int frame, double val);
+ void changeACEvent(AudioTrack* t, int acid, int frame, int newFrame, double val);
+ void controllerChange(Track* t);
//-----------------------------------------
// part manipulations
@@ -400,7 +404,8 @@ class Song : public QObject {
void quantizeChanged(bool);
void markerChanged(int);
void midiPortsChanged();
- void midiNote(int pitch, int velo);
+ void midiNote(int pitch, int velo);
+ void controllerChanged(Track* t);
};
extern Song* song;
diff --git a/muse2/muse/track.cpp b/muse2/muse/track.cpp
index 5f358375..eae74ccf 100644
--- a/muse2/muse/track.cpp
+++ b/muse2/muse/track.cpp
@@ -139,7 +139,9 @@ int Track::y() const
return yy;
yy += (*it)->height();
}
- printf("Track::y(%s): track not in tracklist\n", name().toLatin1().constData());
+ // FIXME Get this when loading a song with automation graphs showing. Benign. Likely song not fully loaded yet. p4.0.32
+ if(debugMsg)
+ printf("Track::y(%s): track not in tracklist\n", name().toLatin1().constData());
return -1;
}
diff --git a/muse2/muse/track.h b/muse2/muse/track.h
index 50870166..de766e32 100644
--- a/muse2/muse/track.h
+++ b/muse2/muse/track.h
@@ -428,6 +428,7 @@ class AudioTrack : public Track {
void eraseACEvent(int, int);
void eraseRangeACEvents(int, int, int);
void addACEvent(int, int, double);
+ void changeACEvent(int id, int frame, int newframe, double newval);
};
//---------------------------------------------------------