summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--muse2/ChangeLog3
-rw-r--r--muse2/muse/arranger/tlist.cpp42
-rw-r--r--muse2/muse/helper.cpp18
-rw-r--r--muse2/muse/helper.h1
-rw-r--r--muse2/muse/midiedit/scoreedit.cpp4
-rw-r--r--muse2/muse/track.cpp32
-rw-r--r--muse2/muse/track.h4
7 files changed, 65 insertions, 39 deletions
diff --git a/muse2/ChangeLog b/muse2/ChangeLog
index 2a3b57fd..219ea5ed 100644
--- a/muse2/ChangeLog
+++ b/muse2/ChangeLog
@@ -1,3 +1,6 @@
+16.03.2012:
+ - Custom columns now send their controller changes to the device
+ automatically if appropriate (flo)
10.03.2012:
- Track routing: Fixed duplicate routes: Reverted usage of operation group in Song::addTrack. (Tim)
- Templates: Default routing: Restored default Jack out/in routes in audio.med, synti.med, default.med, monorecord.med. (Tim)
diff --git a/muse2/muse/arranger/tlist.cpp b/muse2/muse/arranger/tlist.cpp
index 77686ff2..0c14bf7b 100644
--- a/muse2/muse/arranger/tlist.cpp
+++ b/muse2/muse/arranger/tlist.cpp
@@ -425,7 +425,7 @@ void TList::paint(const QRect& r)
MusECore::MidiTrack* mt=dynamic_cast<MusECore::MidiTrack*>(track);
MusECore::MidiPort* mp = &MusEGlobal::midiPorts[mt->outPort()];
MusECore::MidiController* mctl = mp->midiController(col_ctrl_no);
- int val=mt->getControllerValueAtTick(0,col_ctrl_no,MusECore::CTRL_VAL_UNKNOWN);
+ int val=mt->getControllerChangeAtTick(0,col_ctrl_no,MusECore::CTRL_VAL_UNKNOWN);
if (val!=MusECore::CTRL_VAL_UNKNOWN)
val-=mctl->bias();
@@ -627,11 +627,7 @@ void TList::ctrlValueFinished()
if (val!=MusECore::CTRL_VAL_UNKNOWN)
{
- MusECore::Event a(MusECore::Controller);
- a.setTick(0);
- a.setA(ctrl_num);
- a.setB(val);
- MusEGlobal::song->recordEvent(mt, a);
+ record_controller_change_and_maybe_send(0, ctrl_num, val, mt);
}
else
{
@@ -810,7 +806,7 @@ void TList::mouseDoubleClickEvent(QMouseEvent* ev)
ctrl_edit->setMinimum(mctl->minVal()-1); // -1 because of the specialValueText
ctrl_edit->setMaximum(mctl->maxVal());
- ctrl_edit->setValue(((MusECore::MidiTrack*)editTrack)->getControllerValueAtTick(0,ctrl_num)-mctl->bias());
+ ctrl_edit->setValue(((MusECore::MidiTrack*)editTrack)->getControllerChangeAtTick(0,ctrl_num)-mctl->bias());
int w=colw;
if (w < ctrl_edit->sizeHint().width()) w=ctrl_edit->sizeHint().width();
ctrl_edit->setGeometry(colx, coly, w, colh);
@@ -1858,7 +1854,7 @@ void TList::mousePressEvent(QMouseEvent* ev)
int minval=mctl->minVal()+mctl->bias();
int maxval=mctl->maxVal()+mctl->bias();
- int val = mt->getControllerValueAtTick(0,ctrl_num);
+ int val = mt->getControllerChangeAtTick(0,ctrl_num);
int oldval=val;
if (ctrl_num!=MusECore::CTRL_PROGRAM)
@@ -1880,11 +1876,7 @@ void TList::mousePressEvent(QMouseEvent* ev)
{
if (val!=minval-1)
{
- MusECore::Event a(MusECore::Controller);
- a.setTick(0);
- a.setA(ctrl_num);
- a.setB(val);
- MusEGlobal::song->recordEvent(mt, a);
+ record_controller_change_and_maybe_send(0, ctrl_num, val, mt);
}
else
{
@@ -1937,13 +1929,7 @@ void TList::mousePressEvent(QMouseEvent* ev)
{
int val = act->data().toInt();
if(val != -1)
- {
- MusECore::Event a(MusECore::Controller);
- a.setTick(0);
- a.setA(MusECore::CTRL_PROGRAM);
- a.setB(val);
- MusEGlobal::song->recordEvent(mt, a);
- }
+ record_controller_change_and_maybe_send(0, MusECore::CTRL_PROGRAM, val, mt);
}
delete pup;
@@ -2334,7 +2320,7 @@ void TList::wheelEvent(QWheelEvent* ev)
int minval=mctl->minVal()+mctl->bias();
int maxval=mctl->maxVal()+mctl->bias();
- int val = mt->getControllerValueAtTick(0,ctrl_num);
+ int val = mt->getControllerChangeAtTick(0,ctrl_num);
int oldval=val;
if (ctrl_num!=MusECore::CTRL_PROGRAM)
@@ -2356,11 +2342,7 @@ void TList::wheelEvent(QWheelEvent* ev)
{
if (val!=minval-1)
{
- MusECore::Event a(MusECore::Controller);
- a.setTick(0);
- a.setA(ctrl_num);
- a.setB(val);
- MusEGlobal::song->recordEvent(mt, a);
+ record_controller_change_and_maybe_send(0, ctrl_num, val, mt);
}
else
{
@@ -2532,13 +2514,7 @@ void TList::instrPopupActivated(QAction* act)
{
int val = act->data().toInt();
if(val != -1)
- {
- MusECore::Event a(MusECore::Controller);
- a.setTick(0);
- a.setA(MusECore::CTRL_PROGRAM);
- a.setB(val);
- MusEGlobal::song->recordEvent(mt, a);
- }
+ record_controller_change_and_maybe_send(0, MusECore::CTRL_PROGRAM, val, mt);
}
}
diff --git a/muse2/muse/helper.cpp b/muse2/muse/helper.cpp
index 89b0b641..c5f9eca1 100644
--- a/muse2/muse/helper.cpp
+++ b/muse2/muse/helper.cpp
@@ -38,6 +38,7 @@
#include "globaldefs.h"
#include "audio.h"
#include "audiodev.h"
+#include "midi.h"
#include "midiseq.h"
#include <QMenu>
@@ -352,6 +353,23 @@ void read_new_style_drummap(Xml& xml, const char* tagname,
}
}
+void record_controller_change_and_maybe_send(unsigned tick, int ctrl_num, int val, MidiTrack* mt)
+{
+ MusECore::Event a(MusECore::Controller);
+ a.setTick(tick);
+ a.setA(ctrl_num);
+ a.setB(val);
+ MusEGlobal::song->recordEvent(mt, a);
+
+ if (MusEGlobal::song->cpos() < mt->getControllerValueLifetime(tick, ctrl_num))
+ {
+ // this CC has an immediate effect? so send it out to the device.
+ MusECore::MidiPlayEvent ev(0, mt->outPort(), mt->outChannel(), MusECore::ME_CONTROLLER, ctrl_num, val);
+ MusEGlobal::audio->msgPlayMidiEvent(&ev);
+ }
+}
+
+
} // namespace MusECore
namespace MusEGui {
diff --git a/muse2/muse/helper.h b/muse2/muse/helper.h
index 2a26c08e..8671dce3 100644
--- a/muse2/muse/helper.h
+++ b/muse2/muse/helper.h
@@ -59,6 +59,7 @@ QSet<Part*> parts_at_tick(unsigned tick, const QSet<Track*>& tracks);
bool parse_range(const QString& str, int* from, int* to); // returns true if successful, false on error
+void record_controller_change_and_maybe_send(unsigned tick, int ctrl_num, int val, MidiTrack* mt);
}
namespace MusEGui {
diff --git a/muse2/muse/midiedit/scoreedit.cpp b/muse2/muse/midiedit/scoreedit.cpp
index f06c2ad7..11ccf445 100644
--- a/muse2/muse/midiedit/scoreedit.cpp
+++ b/muse2/muse/midiedit/scoreedit.cpp
@@ -4704,10 +4704,6 @@ void ScoreCanvas::add_new_parts(const std::map< MusECore::Part*, std::set<MusECo
* o test old- and new drumtrack recording, steprecording
*
* CURRENT TODO
- * o automatically send controller changes by the arranger columns
- * if necessary (i.e., if no later controller overrides this)
- * o make custom columns only look at CCs at tick0, not at "the firstCC"
- * beacuse this probably causes confusion.
* o custom columns should also be able to store at cpos, not only at tick0
*
* o column's widths aren't stored into configuration. fix that.
diff --git a/muse2/muse/track.cpp b/muse2/muse/track.cpp
index 26ac101b..842afbb3 100644
--- a/muse2/muse/track.cpp
+++ b/muse2/muse/track.cpp
@@ -36,6 +36,7 @@
#include "drummap.h"
#include "midictrl.h"
#include "helper.h"
+#include "limits.h"
namespace MusECore {
@@ -1293,6 +1294,7 @@ int MidiTrack::getFirstControllerValue(int ctrl, int def)
for (iEvent eit=part->events()->begin(); eit!=part->events()->end(); eit++)
{
if (eit->first+part->tick() >= tick) break;
+ if (eit->first > part->lenTick()) break; // ignore events past the end of the part
// else if (eit->first+part->tick() < tick) and
if (eit->second.type()==Controller && eit->second.dataA()==ctrl)
{
@@ -1306,7 +1308,7 @@ int MidiTrack::getFirstControllerValue(int ctrl, int def)
return val;
}
-int MidiTrack::getControllerValueAtTick(int tick, int ctrl, int def)
+int MidiTrack::getControllerChangeAtTick(int tick, int ctrl, int def)
{
for (iPart pit=parts()->begin(); pit!=parts()->end(); pit++)
{
@@ -1316,6 +1318,7 @@ int MidiTrack::getControllerValueAtTick(int tick, int ctrl, int def)
for (iEvent eit=part->events()->begin(); eit!=part->events()->end(); eit++)
{
if (eit->first+part->tick() > tick) break; // we won't find anything in this part from now on.
+ if (eit->first > part->lenTick()) break; // ignore events past the end of the part
if (eit->first+part->tick() < tick) continue; // ignore only this
// else if (eit->first+part->tick() == tick) and
@@ -1327,6 +1330,33 @@ int MidiTrack::getControllerValueAtTick(int tick, int ctrl, int def)
return def;
}
+// returns the tick where this CC gets overriden by a new one
+// returns -1 for "never"
+unsigned MidiTrack::getControllerValueLifetime(int tick, int ctrl)
+{
+ unsigned result=UINT_MAX;
+
+ for (iPart pit=parts()->begin(); pit!=parts()->end(); pit++)
+ {
+ Part* part=pit->second;
+ if (part->tick() > result) break; // ignore this and the rest. we won't find anything new.
+ if (part->endTick() < tick) continue; // ignore only this part, we won't find anything there.
+ for (iEvent eit=part->events()->begin(); eit!=part->events()->end(); eit++)
+ {
+ if (eit->first+part->tick() >= result) break;
+ if (eit->first > part->lenTick()) break; // ignore events past the end of the part
+ // else if (eit->first+part->tick() < result) and
+ if (eit->first+part->tick() > tick &&
+ eit->second.type()==Controller && eit->second.dataA()==ctrl)
+ {
+ result = eit->first+part->tick();
+ break;
+ }
+ }
+ }
+
+ return result;
+}
// returns true if the autoupdate changed something
bool MidiTrack::auto_update_drummap()
diff --git a/muse2/muse/track.h b/muse2/muse/track.h
index b92f2146..5e3319a2 100644
--- a/muse2/muse/track.h
+++ b/muse2/muse/track.h
@@ -304,7 +304,9 @@ class MidiTrack : public Track {
static bool visible() { return _isVisible; }
int getFirstControllerValue(int ctrl, int def=-1);
- int getControllerValueAtTick(int tick, int ctrl, int def=-1);
+ int getControllerChangeAtTick(int tick, int ctrl, int def=-1);
+ unsigned getControllerValueLifetime(int tick, int ctrl); // returns the tick where this CC gets overriden by a new one
+ // returns UINT_MAX for "never"
void setClef(clefTypes i) { clefType = i; }
clefTypes getClef() { return clefType; }