summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--muse2/ChangeLog13
-rw-r--r--muse2/muse/app.cpp70
-rw-r--r--muse2/muse/arranger/pcanvas.cpp70
-rw-r--r--muse2/muse/arranger/pcanvas.h5
-rw-r--r--muse2/muse/osc.cpp19
-rw-r--r--muse2/muse/plugin.cpp19
-rw-r--r--muse2/muse/widgets/utils.cpp20
-rw-r--r--muse2/muse/widgets/utils.h5
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);