diff options
-rw-r--r-- | muse2/ChangeLog | 3 | ||||
-rw-r--r-- | muse2/muse/arranger/tlist.cpp | 42 | ||||
-rw-r--r-- | muse2/muse/helper.cpp | 18 | ||||
-rw-r--r-- | muse2/muse/helper.h | 1 | ||||
-rw-r--r-- | muse2/muse/midiedit/scoreedit.cpp | 4 | ||||
-rw-r--r-- | muse2/muse/track.cpp | 32 | ||||
-rw-r--r-- | muse2/muse/track.h | 4 |
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; } |