diff options
author | Tim E. Real <termtech@rogers.com> | 2011-08-29 22:44:24 +0000 |
---|---|---|
committer | Tim E. Real <termtech@rogers.com> | 2011-08-29 22:44:24 +0000 |
commit | d505c378bdf55445babb73e0ba4085702be35870 (patch) | |
tree | 40ccb82e5b27f118904a5298faedd10fe3b96d36 /muse2/muse | |
parent | 21e75f0c2d14010d060693c77fd3e22e1fccd65d (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/muse')
-rw-r--r-- | muse2/muse/arranger/arranger.cpp | 1 | ||||
-rw-r--r-- | muse2/muse/arranger/pcanvas.cpp | 393 | ||||
-rw-r--r-- | muse2/muse/arranger/pcanvas.h | 10 | ||||
-rw-r--r-- | muse2/muse/audio.cpp | 4 | ||||
-rw-r--r-- | muse2/muse/audio.h | 2 | ||||
-rw-r--r-- | muse2/muse/audiotrack.cpp | 41 | ||||
-rw-r--r-- | muse2/muse/cliplist/cliplist.cpp | 8 | ||||
-rw-r--r-- | muse2/muse/ctrl.cpp | 110 | ||||
-rw-r--r-- | muse2/muse/ctrl.h | 5 | ||||
-rw-r--r-- | muse2/muse/dssihost.cpp | 15 | ||||
-rw-r--r-- | muse2/muse/dssihost.h | 2 | ||||
-rw-r--r-- | muse2/muse/mixer/astrip.cpp | 43 | ||||
-rw-r--r-- | muse2/muse/mixer/panknob.cpp | 4 | ||||
-rw-r--r-- | muse2/muse/mplugins/rhythmbase.ui | 8 | ||||
-rw-r--r-- | muse2/muse/plugin.cpp | 92 | ||||
-rw-r--r-- | muse2/muse/plugin.h | 10 | ||||
-rw-r--r-- | muse2/muse/seqmsg.cpp | 27 | ||||
-rw-r--r-- | muse2/muse/song.cpp | 17 | ||||
-rw-r--r-- | muse2/muse/song.h | 7 | ||||
-rw-r--r-- | muse2/muse/track.cpp | 4 | ||||
-rw-r--r-- | muse2/muse/track.h | 1 |
21 files changed, 499 insertions, 305 deletions
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); }; //--------------------------------------------------------- |