diff options
-rw-r--r-- | muse2/ChangeLog | 13 | ||||
-rw-r--r-- | muse2/muse/app.cpp | 70 | ||||
-rw-r--r-- | muse2/muse/arranger/pcanvas.cpp | 70 | ||||
-rw-r--r-- | muse2/muse/arranger/pcanvas.h | 5 | ||||
-rw-r--r-- | muse2/muse/osc.cpp | 19 | ||||
-rw-r--r-- | muse2/muse/plugin.cpp | 19 | ||||
-rw-r--r-- | muse2/muse/widgets/utils.cpp | 20 | ||||
-rw-r--r-- | muse2/muse/widgets/utils.h | 5 |
8 files changed, 160 insertions, 61 deletions
diff --git a/muse2/ChangeLog b/muse2/ChangeLog index d42c3127..9d5e7237 100644 --- a/muse2/ChangeLog +++ b/muse2/ChangeLog @@ -1,3 +1,16 @@ +14.04.2011: + - Fixed notes 'sliver' drawing in arranger midi parts. Invert if too dark. (Tim) + - Gave arranger part name text drawing a shadow to help contrast with drawn events. + Also moved part name text out of the way, to top of part. + - Removed DSSI gui QProcess kill timers. In Qt4 they can only be used that way with threads started with QThread. + Kill is not nice anyway. On terminate, gui may prompt user to save work etc. App should check at close + if all these guis closed and ask to abort closing, or kill the guis, or leave them alone. + - Improved dark part colour gradients. Added gGradientFromQColor() in widgets/utils.cpp and called from PartCanvas draw. +12.04.2011: + - Another fix for FLAM GUI controls - 300ms delay before sending control values in PluginI::oscUpdate(). (Tim) + Good enough? How to make sure (any) gui is really ready? +11.04.2011: + - Possible fix for FLAM GUI controls - send current control values in PluginI::oscUpdate().(Tim) 10.04.2011: * Added: Expanded all routing choices: Synth to Wave track, Wave track to Wave track etc. (Tim) * Added: DSSI synths can now show generic LADSPA GUI as well as native. (Tim p4.0.20) diff --git a/muse2/muse/app.cpp b/muse2/muse/app.cpp index a96b7e9b..9f10a614 100644 --- a/muse2/muse/app.cpp +++ b/muse2/muse/app.cpp @@ -2459,7 +2459,7 @@ void MusE::routingPopupMenuActivated(Track* track, int n) if(n == -1) return; - if(n == 0) // p4.0.17 + if(!gIsOutRoutingPopupMenu && n == 0) // p4.0.17 { muse->configMidiPorts(); return; @@ -2857,43 +2857,51 @@ PopupMenu* MusE::prepareRoutingPopupMenu(Track* track, bool dst) if(port >= 0 && port < MIDI_PORTS) { MidiPort* mp = &midiPorts[port]; - RouteList* mprl = mp->outRoutes(); - int chbits = 1 << ((MidiTrack*)track)->outChannel(); - //MidiDevice* md = mp->device(); - //if(!md) - // continue; - - pup->addSeparator(); - pup->addAction(new MenuTitleItem(tr("Soloing chain"), pup)); - PopupMenu* subp = new PopupMenu(pup); - subp->setTitle(tr("Audio returns")); - pup->addMenu(subp); - InputList* al = song->inputs(); - for (iAudioInput i = al->begin(); i != al->end(); ++i) + // p4.0.17 Do not list synth devices! Requiring valid device is desirable, + // but could lead to 'hidden' routes unless we add more support + // such as removing the existing routes when user changes flags. + // So for now, just list all valid ports whether read or write. + if(mp->device() && !mp->device()->isSynti()) { - Track* t = *i; - QString s(t->name()); + RouteList* mprl = mp->outRoutes(); + int chbits = 1 << ((MidiTrack*)track)->outChannel(); + //MidiDevice* md = mp->device(); + //if(!md) + // continue; - act = subp->addAction(s); - act->setData(gid); - act->setCheckable(true); - - Route r(t, chbits); + pup->addSeparator(); + pup->addAction(new MenuTitleItem(tr("Soloing chain"), pup)); + PopupMenu* subp = new PopupMenu(pup); + subp->setTitle(tr("Audio returns")); + pup->addMenu(subp); - gRoutingMenuMap.insert( pRouteMenuMap(gid, r) ); - - for(iRoute ir = mprl->begin(); ir != mprl->end(); ++ir) + InputList* al = song->inputs(); + for (iAudioInput i = al->begin(); i != al->end(); ++i) { - if(ir->type == Route::TRACK_ROUTE && ir->track == t && (ir->channel & chbits)) + Track* t = *i; + QString s(t->name()); + + act = subp->addAction(s); + act->setData(gid); + act->setCheckable(true); + + Route r(t, chbits); + + gRoutingMenuMap.insert( pRouteMenuMap(gid, r) ); + + for(iRoute ir = mprl->begin(); ir != mprl->end(); ++ir) { - act->setChecked(true); - break; - } + if(ir->type == Route::TRACK_ROUTE && ir->track == t && (ir->channel & chbits)) + { + act->setChecked(true); + break; + } + } + ++gid; } - ++gid; - } - } + } + } } else { diff --git a/muse2/muse/arranger/pcanvas.cpp b/muse2/muse/arranger/pcanvas.cpp index 5747726f..ca2a16b0 100644 --- a/muse2/muse/arranger/pcanvas.cpp +++ b/muse2/muse/arranger/pcanvas.cpp @@ -20,7 +20,7 @@ #include <QPainter> #include <QUrl> #include <QPoint> -#include <QLinearGradient> +//#include <QLinearGradient> #include "fastlog.h" #include "widgets/tools.h" @@ -40,6 +40,7 @@ #include "mpevent.h" #include "midievent.h" #include "midi.h" +#include "utils.h" // Moved into global config by Tim. /* @@ -1552,10 +1553,18 @@ void PartCanvas::drawItem(QPainter& p, const CItem* item, const QRect& rect) // Hm, put some kind of lower limit? If so do that globally to the adjustment. QColor c(Qt::black); c.setAlpha(config.globalAlphaBlend); + QLinearGradient gradient(r.topLeft(), r.bottomLeft()); - gradient.setColorAt(0, c); - gradient.setColorAt(1, c.darker()); + //gradient.setColorAt(0, c); + //gradient.setColorAt(1, c.darker()); + // Use a colour only about 20% lighter than black, rather than the 50% we use in gGradientFromQColor + // and is used in darker()/lighter(), so that it is distinguished a bit better from grey non-part tracks. + //c.setRgba(64, 64, 64, c.alpha()); + gradient.setColorAt(0, QColor(51, 51, 51, config.globalAlphaBlend)); + gradient.setColorAt(1, c); QBrush cc(gradient); + //QBrush cc(gGradientFromQColor(c, r.topLeft(), r.bottomLeft())); + p.setBrush(cc); p.drawRect(r); } @@ -1570,10 +1579,11 @@ void PartCanvas::drawItem(QPainter& p, const CItem* item, const QRect& rect) p.setPen(pen); QColor c(config.partColors[i]); c.setAlpha(config.globalAlphaBlend); - QLinearGradient gradient(r.topLeft(), r.bottomLeft()); - gradient.setColorAt(0, c); - gradient.setColorAt(1, c.darker()); - QBrush cc(gradient); + //QLinearGradient gradient(r.topLeft(), r.bottomLeft()); + //gradient.setColorAt(0, c); + //gradient.setColorAt(1, c.darker()); + //QBrush cc(gradient); + QBrush cc(gGradientFromQColor(c, r.topLeft(), r.bottomLeft())); p.setBrush(cc); p.drawRect(r); @@ -1593,7 +1603,7 @@ void PartCanvas::drawItem(QPainter& p, const CItem* item, const QRect& rect) drawWavePart(p, rect, wp, r); else if (mp) { - drawMidiPart(p, rect, mp->events(),(MidiTrack*)part->track(), r, mp->tick(), from, to); + drawMidiPart(p, rect, mp->events(), (MidiTrack*)part->track(), mp, r, mp->tick(), from, to); } if (config.canvasShowPartType & 1) { // show names @@ -1602,16 +1612,26 @@ void PartCanvas::drawItem(QPainter& p, const CItem* item, const QRect& rect) int part_r, part_g, part_b, brightness; config.partColors[i].getRgb(&part_r, &part_g, &part_b); brightness = part_r*29 + part_g*59 + part_b*12; - if (brightness < 12000 || part->selected()) - p.setPen(Qt::white); /* too dark: use white for text color */ - else - p.setPen(Qt::black); /* otherwise use black */ + //if (brightness < 12000 || part->selected()) + // p.setPen(Qt::white); /* too dark: use white for text color */ + //else + // p.setPen(Qt::black); /* otherwise use black */ + bool rev = brightness < 12000 || part->selected(); QRect rr = map(r); rr.setX(rr.x() + 3); p.save(); p.setFont(config.fonts[1]); p.setWorldMatrixEnabled(false); - p.drawText(rr, Qt::AlignVCenter|Qt::AlignLeft, part->name()); + if (rev) + p.setPen(Qt::black); + else + p.setPen(Qt::white); + p.drawText(rr.translated(1, 1), Qt::AlignTop|Qt::AlignLeft, part->name()); + if (rev) + p.setPen(Qt::white); + else + p.setPen(Qt::black); + p.drawText(rr, Qt::AlignTop|Qt::AlignLeft, part->name()); p.restore(); } } @@ -1649,14 +1669,30 @@ void PartCanvas::drawMoving(QPainter& p, const CItem* item, const QRect&) // pr - part rectangle //--------------------------------------------------------- -void PartCanvas::drawMidiPart(QPainter& p, const QRect& bb, EventList* events, MidiTrack *mt, const QRect& r, int pTick, int from, int to) +void PartCanvas::drawMidiPart(QPainter& p, const QRect& bb, EventList* events, MidiTrack *mt, MidiPart *pt, const QRect& r, int pTick, int from, int to) { //printf("x=%d y=%d h=%d w=%d\n",r.x(),r.y(),r.height(),r.width()); + + if(pt) + { + int part_r, part_g, part_b, brightness; + config.partColors[pt->colorIndex()].getRgb(&part_r, &part_g, &part_b); + brightness = part_r*29 + part_g*59 + part_b*12; + if (brightness < 12000 || pt->selected()) + //p.setPen(Qt::white); // too dark: use white for color + p.setPen(QColor(192,192,192)); // too dark: use lighter color + else + //p.setPen(Qt::black); // otherwise use black + p.setPen(QColor(64,64,64)); // otherwise use dark color + } + else + p.setPen(QColor(80,80,80)); + if (config.canvasShowPartType & 2) { // show events // Do not allow this, causes segfault. if(from <= to) { - p.setPen(QColor(80,80,80)); + //p.setPen(QColor(80,80,80)); //EventList* events = mp->events(); iEvent ito(events->lower_bound(to)); @@ -1678,7 +1714,7 @@ void PartCanvas::drawMidiPart(QPainter& p, const QRect& bb, EventList* events, M } } else { // show Cakewalk Style - p.setPen(QColor(80,80,80)); + //p.setPen(QColor(80,80,80)); //EventList* events = mp->events(); iEvent ito(events->lower_bound(to)); //printf("PartCanvas::drawItem pTick:%d from:%d to:%d\n", pTick, from, to); @@ -3047,7 +3083,7 @@ void PartCanvas::drawTopItem(QPainter& p, const QRect& rect) } } } - drawMidiPart(p, rect, &myEventList, mt, partRect,startPos,0,song->cpos()-startPos); + drawMidiPart(p, rect, &myEventList, mt, 0, partRect,startPos,0,song->cpos()-startPos); } yPos+=track->height(); } diff --git a/muse2/muse/arranger/pcanvas.h b/muse2/muse/arranger/pcanvas.h index d3e835b0..a3dd7900 100644 --- a/muse2/muse/arranger/pcanvas.h +++ b/muse2/muse/arranger/pcanvas.h @@ -84,8 +84,6 @@ class PartCanvas : public Canvas { virtual int pitch2y(int p) const; virtual void moveCanvasItems(CItemList&, int, int, DragType, int*); - // Changed by T356. - //virtual bool moveItem(CItem*, const QPoint&, DragType, int*); virtual bool moveItem(CItem*, const QPoint&, DragType); virtual CItem* newItem(const QPoint&, int); virtual void resizeItem(CItem*,bool); @@ -112,7 +110,8 @@ class PartCanvas : public Canvas { void movePartsTotheRight(unsigned int startTick, int length); //Part* readClone(Xml&, Track*, bool toTrack = true); void drawWavePart(QPainter&, const QRect&, WavePart*, const QRect&); - void drawMidiPart(QPainter&, const QRect& rect, EventList* events, MidiTrack *mt, const QRect& r, int pTick, int from, int to); + //void drawMidiPart(QPainter&, const QRect& rect, EventList* events, MidiTrack*mt, const QRect& r, int pTick, int from, int to); + void drawMidiPart(QPainter&, const QRect& rect, EventList* events, MidiTrack*mt, MidiPart*pt, const QRect& r, int pTick, int from, int to); Track* y2Track(int) const; void drawAudioTrack(QPainter& p, const QRect& r, AudioTrack* track); void drawAutomation(QPainter& p, const QRect& r, AudioTrack* track); diff --git a/muse2/muse/osc.cpp b/muse2/muse/osc.cpp index 2b567856..66242e17 100644 --- a/muse2/muse/osc.cpp +++ b/muse2/muse/osc.cpp @@ -504,7 +504,13 @@ OscIF::~OscIF() // process needs to do all its cleanup: use a higher value if the process is likely to do a lot of // computation or I/O on cleanup." _oscGuiQProc->terminate(); - QTimer::singleShot( 5000, _oscGuiQProc, SLOT( kill() ) ); + // FIXME: In Qt4 this can only be used with threads started with QThread. + // Kill is bad anyway, app should check at close if all these guis closed or not + // and ask user if they really want to close, possibly with kill. + // Terminate might not terminate the thread. It is given a chance to prompt for saving etc. + // so kill is not desirable. + // We could wait until terminate finished but don't think that's good here. + ///QTimer::singleShot( 5000, _oscGuiQProc, SLOT( kill() ) ); } //delete _oscGuiQProc; } @@ -710,7 +716,13 @@ int OscIF::oscExiting(lo_arg**) // process needs to do all its cleanup: use a higher value if the process is likely to do a lot of // computation or I/O on cleanup." _oscGuiQProc->terminate(); - QTimer::singleShot( 5000, _oscGuiQProc, SLOT( kill() ) ); + // FIXME: In Qt4 this can only be used with threads started with QThread. + // Kill is bad anyway, app should check at close if all these guis closed or not + // and ask user if they really want to close, possibly with kill. + // Terminate might not terminate the thread. It is given a chance to prompt for saving etc. + // so kill is not desirable. + // We could wait until terminate finished but don't think that's good here. + ///QTimer::singleShot( 5000, _oscGuiQProc, SLOT( kill() ) ); } //delete _oscGuiQProc; } @@ -928,7 +940,8 @@ bool OscIF::oscInitGui(const QString& typ, const QString& baseName, const QStrin //{ // No QProcess created yet? Do it now. Only once per SynthIF instance. Exists until parent destroyed. if(_oscGuiQProc == 0) - _oscGuiQProc = new QProcess(muse); + //_oscGuiQProc = new QProcess(muse); + _oscGuiQProc = new QProcess(); //QString program(fi.filePath()); QString program(guiPath); diff --git a/muse2/muse/plugin.cpp b/muse2/muse/plugin.cpp index e1abbb5e..06e72e4e 100644 --- a/muse2/muse/plugin.cpp +++ b/muse2/muse/plugin.cpp @@ -2518,7 +2518,6 @@ int PluginI::oscUpdate() #ifdef DSSI_SUPPORT // Send project directory. _oscif.oscSendConfigure(DSSI_PROJECT_DIRECTORY_KEY, museProject.toLatin1().constData()); // song->projectPath() - #endif /* // Send current string configuration parameters. @@ -2537,19 +2536,25 @@ int PluginI::oscUpdate() unsigned long bank, prog; synti->currentProg(&prog, &bank, 0); _oscIF.oscSendProgram(prog, bank); + */ + // FIXME: TESTING FLAM: I have to put a delay because flammer hasn't opened yet. + // How to make sure gui is ready? + usleep(300000); + // Send current control values. - unsigned long ports = synth->_controlInPorts; - for(unsigned long i = 0; i < ports; ++i) + //unsigned long ports = controlPorts; + for(int i = 0; i < controlPorts; ++i) { - unsigned long k = synth->pIdx(i); - _oscIF.oscSendControl(k, controls[i]); + //unsigned long k = synth->pIdx(i); + //_oscIF.oscSendControl(k, controls[i]); + //printf("PluginI::oscUpdate() sending control:%d val:%f\n", i, controls[i].val); + _oscif.oscSendControl(controls[i].idx, controls[i].val); // Avoid overloading the GUI if there are lots and lots of ports. if((i+1) % 50 == 0) usleep(300000); } - - */ + #endif // DSSI_SUPPORT return 0; } diff --git a/muse2/muse/widgets/utils.cpp b/muse2/muse/widgets/utils.cpp index 1bf4ca64..38574d94 100644 --- a/muse2/muse/widgets/utils.cpp +++ b/muse2/muse/widgets/utils.cpp @@ -11,6 +11,10 @@ #include <sys/time.h> #include <QFrame> +#include <QColor> +#include <QGradient> +#include <QLinearGradient> +#include <QPointF> #include "utils.h" @@ -354,3 +358,19 @@ bool autoAdjustFontSize(QFrame* w, const QString& s, bool ignoreWidth, bool igno return true; } + +QGradient gGradientFromQColor(const QColor& c, const QPointF& start, const QPointF& finalStop) +{ + int h, s, v, a; + c.getHsv(&h, &s, &v, &a); + const int v0 = v + (255 - v)/2; + const int v1 = v - v/2; + const QColor c0 = QColor::fromHsv(h, s, v0, a); + const QColor c1 = QColor::fromHsv(h, s, v1, a); + + QLinearGradient gradient(start, finalStop); + gradient.setColorAt(0, c0); + gradient.setColorAt(1, c1); + + return gradient; +}
\ No newline at end of file diff --git a/muse2/muse/widgets/utils.h b/muse2/muse/widgets/utils.h index 654a7834..b6997023 100644 --- a/muse2/muse/widgets/utils.h +++ b/muse2/muse/widgets/utils.h @@ -11,6 +11,10 @@ class QFrame; class QString; class QWidget; +class QGradient; +class QCanvas; +class QPointF; +class QColor; extern QString bitmap2String(int bm); @@ -18,6 +22,7 @@ extern int string2bitmap(const QString& str); extern QString u32bitmap2String(unsigned int bm); extern unsigned int string2u32bitmap(const QString& str); extern bool autoAdjustFontSize(QFrame* w, const QString& s, bool ignoreWidth = false, bool ignoreHeight = false, int max = 10, int min = 4); +extern QGradient gGradientFromQColor(const QColor& c, const QPointF& start, const QPointF& finalStop); extern int num2cols(int min, int max); extern QFrame* hLine(QWidget* parent); |