summaryrefslogtreecommitdiff
path: root/muse2/muse
diff options
context:
space:
mode:
authorFlorian Jung <flo@windfisch.org>2011-05-11 16:41:11 +0000
committerFlorian Jung <flo@windfisch.org>2011-05-11 16:41:11 +0000
commit1c431bd67567104ba9e026ae75ba479f56d387a2 (patch)
tree953f7f708eefd8fbac23937a987ad2cce667dd19 /muse2/muse
parent56b1d339a4176c07d4d995bd8912f1eccddc5539 (diff)
parent4f2e54561260eb8382953d5723d5d111353a22c9 (diff)
some housekeeping:
- merged with trunk - removed note to myself - some code-cleanups
Diffstat (limited to 'muse2/muse')
-rw-r--r--muse2/muse/CMakeLists.txt1
-rw-r--r--muse2/muse/app.cpp280
-rw-r--r--muse2/muse/app.h5
-rw-r--r--muse2/muse/conf.cpp3
-rw-r--r--muse2/muse/dssihost.cpp27
-rw-r--r--muse2/muse/gconfig.cpp3
-rw-r--r--muse2/muse/gconfig.h1
-rw-r--r--muse2/muse/marker/marker.h2
-rw-r--r--muse2/muse/master/lmaster.cpp4
-rw-r--r--muse2/muse/midiedit/scoreedit.cpp80
-rw-r--r--muse2/muse/midiedit/scoreedit.h1
-rw-r--r--muse2/muse/part.h1
-rw-r--r--muse2/muse/plugin.cpp21
-rw-r--r--muse2/muse/song.cpp160
-rw-r--r--muse2/muse/song.h4
-rw-r--r--muse2/muse/songfile.cpp3
-rw-r--r--muse2/muse/structure.cpp368
-rw-r--r--muse2/muse/undo.cpp30
-rw-r--r--muse2/muse/widgets/genset.cpp19
-rw-r--r--muse2/muse/widgets/gensetbase.ui147
-rw-r--r--muse2/muse/widgets/musewidgetsplug.cpp4
-rw-r--r--muse2/muse/widgets/songinfo.ui7
22 files changed, 752 insertions, 419 deletions
diff --git a/muse2/muse/CMakeLists.txt b/muse2/muse/CMakeLists.txt
index 3117cf2f..d9ca7e3c 100644
--- a/muse2/muse/CMakeLists.txt
+++ b/muse2/muse/CMakeLists.txt
@@ -121,6 +121,7 @@ file (GLOB core_source_files
song.cpp
songfile.cpp
stringparam.cpp
+ structure.cpp
sync.cpp
synth.cpp
tempo.cpp
diff --git a/muse2/muse/app.cpp b/muse2/muse/app.cpp
index 7bf171e5..62651cc9 100644
--- a/muse2/muse/app.cpp
+++ b/muse2/muse/app.cpp
@@ -973,10 +973,10 @@ MusE::MusE(int argc, char** argv) : QMainWindow()
editCopyAction = new QAction(QIcon(*editcopyIconSet), tr("&Copy"), this);
editPasteAction = new QAction(QIcon(*editpasteIconSet), tr("&Paste"), this);
editInsertAction = new QAction(QIcon(*editpasteIconSet), tr("&Insert"), this);
+ editInsertEMAction = new QAction(QIcon(*editpasteIconSet), tr("&Insert Empty Measure"), this);
editPasteCloneAction = new QAction(QIcon(*editpasteCloneIconSet), tr("Paste c&lone"), this);
editPaste2TrackAction = new QAction(QIcon(*editpaste2TrackIconSet), tr("Paste to &track"), this);
editPasteC2TAction = new QAction(QIcon(*editpasteClone2TrackIconSet), tr("Paste clone to trac&k"), this);
- editInsertEMAction = new QAction(QIcon(*editpasteIconSet), tr("&Insert Empty Measure"), this);
editDeleteSelectedAction = new QAction(QIcon(*edit_track_delIcon), tr("Delete Selected Tracks"), this);
@@ -1122,10 +1122,10 @@ MusE::MusE(int argc, char** argv) : QMainWindow()
connect(editCopyAction, SIGNAL(triggered()), editSignalMapper, SLOT(map()));
connect(editPasteAction, SIGNAL(triggered()), editSignalMapper, SLOT(map()));
connect(editInsertAction, SIGNAL(triggered()), editSignalMapper, SLOT(map()));
+ connect(editInsertEMAction, SIGNAL(triggered()), editSignalMapper, SLOT(map()));
connect(editPasteCloneAction, SIGNAL(triggered()), editSignalMapper, SLOT(map()));
connect(editPaste2TrackAction, SIGNAL(triggered()), editSignalMapper, SLOT(map()));
connect(editPasteC2TAction, SIGNAL(triggered()), editSignalMapper, SLOT(map()));
- connect(editInsertEMAction, SIGNAL(triggered()), editSignalMapper, SLOT(map()));
connect(editDeleteSelectedAction, SIGNAL(triggered()), editSignalMapper, SLOT(map()));
connect(editSelectAllAction, SIGNAL(triggered()), editSignalMapper, SLOT(map()));
@@ -1182,7 +1182,7 @@ MusE::MusE(int argc, char** argv) : QMainWindow()
connect(strGlobalCutAction, SIGNAL(activated()), SLOT(globalCut()));
connect(strGlobalInsertAction, SIGNAL(activated()), SLOT(globalInsert()));
connect(strGlobalSplitAction, SIGNAL(activated()), SLOT(globalSplit()));
- connect(strCopyRangeAction, SIGNAL(activated()), SLOT(copyRange()));
+ connect(strCopyRangeAction, SIGNAL(activated()), SLOT(copyRange()));
connect(strCutEventsAction, SIGNAL(activated()), SLOT(cutEvents()));
//-------- Midi connections
@@ -1356,10 +1356,10 @@ MusE::MusE(int argc, char** argv) : QMainWindow()
menuEdit->addAction(editCopyAction);
menuEdit->addAction(editPasteAction);
menuEdit->addAction(editInsertAction);
+ menuEdit->addAction(editInsertEMAction);
menuEdit->addAction(editPasteCloneAction);
menuEdit->addAction(editPaste2TrackAction);
menuEdit->addAction(editPasteC2TAction);
- menuEdit->addAction(editInsertEMAction);
menuEdit->addSeparator();
menuEdit->addAction(editDeleteSelectedAction);
@@ -1737,14 +1737,16 @@ void MusE::loadProjectFile(const QString& name, bool songTemplate, bool loadAll)
if (restartSequencer)
seqStart();
- if (song->getSongInfo().length()>0)
- startSongInfo(false);
-
visTracks->updateVisibleTracksButtons();
progress->setValue(100);
delete progress;
progress=0;
+
QApplication::restoreOverrideCursor();
+
+ if (song->getSongInfo().length()>0 && song->showSongInfoOnStartup()) {
+ startSongInfo(false);
+ }
}
//---------------------------------------------------------
@@ -3377,7 +3379,7 @@ bool MusE::saveAs()
return false;
}
- song->setSongInfo(pci.getSongInfo());
+ song->setSongInfo(pci.getSongInfo(), true);
name = pci.getProjectPath();
} else {
name = getSaveFileName(QString(""), med_file_save_pattern, this, tr("MusE: Save As"));
@@ -3669,12 +3671,16 @@ void MusE::startWaveEditor(PartList* pl)
void MusE::startSongInfo(bool editable)
{
SongInfoWidget info;
+ info.viewCheckBox->setChecked(song->showSongInfoOnStartup());
+ info.viewCheckBox->setEnabled(editable);
info.songInfoText->setPlainText(song->getSongInfo());
info.songInfoText->setReadOnly(!editable);
+ info.setModal(true);
info.show();
if( info.exec() == QDialog::Accepted) {
- if (editable)
- song->setSongInfo(info.songInfoText->toPlainText());
+ if (editable) {
+ song->setSongInfo(info.songInfoText->toPlainText(), info.viewCheckBox->isChecked());
+ }
}
}
@@ -3690,7 +3696,7 @@ void MusE::showDidYouKnowDialog()
dyk.show();
if( dyk.exec()) {
if (dyk.dontShowCheckBox->isChecked()) {
- printf("disables dialog!\n");
+ //printf("disables dialog!\n");
config.showDidYouKnow=false;
muse->changeConfig(true); // save settings
}
@@ -4387,256 +4393,6 @@ void MusE::configShortCuts()
changeConfig(true);
}
-//---------------------------------------------------------
-// globalCut
-// - remove area between left and right locator
-// - do not touch muted track
-// - cut master track
-//---------------------------------------------------------
-
-void MusE::globalCut()
- {
- int lpos = song->lpos();
- int rpos = song->rpos();
- if ((lpos - rpos) >= 0)
- return;
-
- song->startUndo();
- TrackList* tracks = song->tracks();
- for (iTrack it = tracks->begin(); it != tracks->end(); ++it) {
- MidiTrack* track = dynamic_cast<MidiTrack*>(*it);
- if (track == 0 || track->mute())
- continue;
- PartList* pl = track->parts();
- for (iPart p = pl->begin(); p != pl->end(); ++p) {
- Part* part = p->second;
- int t = part->tick();
- int l = part->lenTick();
- if (t + l <= lpos)
- continue;
- if ((t >= lpos) && ((t+l) <= rpos)) {
- audio->msgRemovePart(part, false);
- }
- else if ((t < lpos) && ((t+l) > lpos) && ((t+l) <= rpos)) {
- // remove part tail
- int len = lpos - t;
- MidiPart* nPart = new MidiPart(*(MidiPart*)part);
- nPart->setLenTick(len);
- //
- // cut Events in nPart
- EventList* el = nPart->events();
- iEvent ie = el->lower_bound(t + len);
- for (; ie != el->end();) {
- iEvent i = ie;
- ++ie;
- // Indicate no undo, and do not do port controller values and clone parts.
- //audio->msgDeleteEvent(i->second, nPart, false);
- audio->msgDeleteEvent(i->second, nPart, false, false, false);
- }
- // Indicate no undo, and do port controller values and clone parts.
- //audio->msgChangePart(part, nPart, false);
- audio->msgChangePart(part, nPart, false, true, true);
- }
- else if ((t < lpos) && ((t+l) > lpos) && ((t+l) > rpos)) {
- //----------------------
- // remove part middle
- //----------------------
-
- MidiPart* nPart = new MidiPart(*(MidiPart*)part);
- EventList* el = nPart->events();
- iEvent is = el->lower_bound(lpos);
- iEvent ie = el->upper_bound(rpos);
- for (iEvent i = is; i != ie;) {
- iEvent ii = i;
- ++i;
- // Indicate no undo, and do not do port controller values and clone parts.
- //audio->msgDeleteEvent(ii->second, nPart, false);
- audio->msgDeleteEvent(ii->second, nPart, false, false, false);
- }
-
- ie = el->lower_bound(rpos);
- for (; ie != el->end();) {
- iEvent i = ie;
- ++ie;
- Event event = i->second;
- Event nEvent = event.clone();
- nEvent.setTick(nEvent.tick() - (rpos-lpos));
- // Indicate no undo, and do not do port controller values and clone parts.
- //audio->msgChangeEvent(event, nEvent, nPart, false);
- audio->msgChangeEvent(event, nEvent, nPart, false, false, false);
- }
- nPart->setLenTick(l - (rpos-lpos));
- // Indicate no undo, and do port controller values and clone parts.
- //audio->msgChangePart(part, nPart, false);
- audio->msgChangePart(part, nPart, false, true, true);
- }
- else if ((t >= lpos) && (t < rpos) && (t+l) > rpos) {
- // TODO: remove part head
- }
- else if (t >= rpos) {
- MidiPart* nPart = new MidiPart(*(MidiPart*)part);
- int nt = part->tick();
- nPart->setTick(nt - (rpos -lpos));
- // Indicate no undo, and do port controller values but not clone parts.
- //audio->msgChangePart(part, nPart, false);
- audio->msgChangePart(part, nPart, false, true, false);
- }
- }
- }
- // TODO: cut tempo track
- // TODO: process marker
- song->endUndo(SC_TRACK_MODIFIED | SC_PART_MODIFIED | SC_PART_REMOVED);
- }
-
-//---------------------------------------------------------
-// globalInsert
-// - insert empty space at left locator position upto
-// right locator
-// - do not touch muted track
-// - insert in master track
-//---------------------------------------------------------
-
-void MusE::globalInsert()
- {
- unsigned lpos = song->lpos();
- unsigned rpos = song->rpos();
- if (lpos >= rpos)
- return;
-
- song->startUndo();
- TrackList* tracks = song->tracks();
- for (iTrack it = tracks->begin(); it != tracks->end(); ++it) {
- MidiTrack* track = dynamic_cast<MidiTrack*>(*it);
- //
- // process only non muted midi tracks
- //
- if (track == 0 || track->mute())
- continue;
- PartList* pl = track->parts();
- for (iPart p = pl->begin(); p != pl->end(); ++p) {
- Part* part = p->second;
- unsigned t = part->tick();
- int l = part->lenTick();
- if (t + l <= lpos)
- continue;
- if (lpos >= t && lpos < (t+l)) {
- MidiPart* nPart = new MidiPart(*(MidiPart*)part);
- nPart->setLenTick(l + (rpos-lpos));
- EventList* el = nPart->events();
-
- iEvent i = el->end();
- while (i != el->begin()) {
- --i;
- if (i->first < lpos)
- break;
- Event event = i->second;
- Event nEvent = i->second.clone();
- nEvent.setTick(nEvent.tick() + (rpos-lpos));
- // Indicate no undo, and do not do port controller values and clone parts.
- //audio->msgChangeEvent(event, nEvent, nPart, false);
- audio->msgChangeEvent(event, nEvent, nPart, false, false, false);
- }
- // Indicate no undo, and do port controller values and clone parts.
- //audio->msgChangePart(part, nPart, false);
- audio->msgChangePart(part, nPart, false, true, true);
- }
- else if (t > lpos) {
- MidiPart* nPart = new MidiPart(*(MidiPart*)part);
- nPart->setTick(t + (rpos -lpos));
- // Indicate no undo, and do port controller values but not clone parts.
- //audio->msgChangePart(part, nPart, false);
- audio->msgChangePart(part, nPart, false, true, false);
- }
- }
- }
- // TODO: process tempo track
- // TODO: process marker
- song->endUndo(SC_TRACK_MODIFIED | SC_PART_MODIFIED | SC_PART_REMOVED);
- }
-
-//---------------------------------------------------------
-// globalSplit
-// - split all parts at the song position pointer
-// - do not touch muted track
-//---------------------------------------------------------
-
-void MusE::globalSplit()
- {
- int pos = song->cpos();
- song->startUndo();
- TrackList* tracks = song->tracks();
- for (iTrack it = tracks->begin(); it != tracks->end(); ++it) {
- Track* track = *it;
- PartList* pl = track->parts();
- for (iPart p = pl->begin(); p != pl->end(); ++p) {
- Part* part = p->second;
- int p1 = part->tick();
- int l0 = part->lenTick();
- if (pos > p1 && pos < (p1+l0)) {
- Part* p1;
- Part* p2;
- track->splitPart(part, pos, p1, p2);
- // Indicate no undo, and do port controller values but not clone parts.
- //audio->msgChangePart(part, p1, false);
- audio->msgChangePart(part, p1, false, true, false);
- audio->msgAddPart(p2, false);
- break;
- }
- }
- }
- song->endUndo(SC_TRACK_MODIFIED | SC_PART_MODIFIED | SC_PART_INSERTED);
- }
-
-//---------------------------------------------------------
-// copyRange
-// - copy space between left and right locator position
-// to song position pointer
-// - dont process muted tracks
-// - create a new part for every track containing the
-// copied events
-//---------------------------------------------------------
-
-void MusE::copyRange()
- {
- QMessageBox::critical(this,
- tr("MusE: Copy Range"),
- tr("not implemented")
- );
- }
-
-//---------------------------------------------------------
-// cutEvents
-// - make sure that all events in a part end where the
-// part ends
-// - process only marked parts
-//---------------------------------------------------------
-
-void MusE::cutEvents()
- {
- QMessageBox::critical(this,
- tr("MusE: Cut Events"),
- tr("not implemented")
- );
- }
-
-//---------------------------------------------------------
-// checkRegionNotNull
-// return true if (rPos - lPos) <= 0
-//---------------------------------------------------------
-
-bool MusE::checkRegionNotNull()
- {
- int start = song->lPos().frame();
- int end = song->rPos().frame();
- if (end - start <= 0) {
- QMessageBox::critical(this,
- tr("MusE: Bounce"),
- tr("set left/right marker for bounce range")
- );
- return true;
- }
- return false;
- }
#if 0
//---------------------------------------------------------
@@ -5048,10 +4804,10 @@ void MusE::updateConfiguration()
editCopyAction->setShortcut(shortcuts[SHRT_COPY].key);
editPasteAction->setShortcut(shortcuts[SHRT_PASTE].key);
editInsertAction->setShortcut(shortcuts[SHRT_INSERT].key);
+ editInsertEMAction->setShortcut(shortcuts[SHRT_INSERTMEAS].key);
editPasteCloneAction->setShortcut(shortcuts[SHRT_PASTE_CLONE].key);
editPaste2TrackAction->setShortcut(shortcuts[SHRT_PASTE_TO_TRACK].key);
editPasteC2TAction->setShortcut(shortcuts[SHRT_PASTE_CLONE_TO_TRACK].key);
- editInsertEMAction->setShortcut(shortcuts[SHRT_INSERTMEAS].key);
//editDeleteSelectedAction has no acceleration
diff --git a/muse2/muse/app.h b/muse2/muse/app.h
index 2fd83854..42aebf3b 100644
--- a/muse2/muse/app.h
+++ b/muse2/muse/app.h
@@ -108,7 +108,7 @@ class MusE : public QMainWindow
// Edit Menu actions
QAction *editCutAction, *editCopyAction, *editPasteAction, *editInsertAction, *editPasteCloneAction, *editPaste2TrackAction;
- QAction *editPasteC2TAction, *editInsertEMAction, *editDeleteSelectedAction, *editSelectAllAction, *editDeselectAllAction;
+ QAction *editInsertEMAction, *editPasteC2TAction, *editDeleteSelectedAction, *editSelectAllAction, *editDeselectAllAction;
QAction *editInvertSelectionAction, *editInsideLoopAction, *editOutsideLoopAction, *editAllPartsAction;
QAction *trackMidiAction, *trackDrumAction, *trackWaveAction, *trackAOutputAction, *trackAGroupAction;
QAction *trackAInputAction, *trackAAuxAction;
@@ -334,6 +334,9 @@ class MusE : public QMainWindow
void execDeliveredScript(int);
void execUserScript(int);
+ private:
+ void adjustGlobalLists(int startPos, int diff);
+
public slots:
bool saveAs();
diff --git a/muse2/muse/conf.cpp b/muse2/muse/conf.cpp
index c79c3928..2f391445 100644
--- a/muse2/muse/conf.cpp
+++ b/muse2/muse/conf.cpp
@@ -923,6 +923,8 @@ void readConfiguration(Xml& xml, bool readOnlySequencer)
config.dummyAudioSampleRate = xml.parseInt();
else if (tag == "dummyAudioBufSize")
config.dummyAudioBufSize = xml.parseInt();
+ else if (tag == "minControlProcessPeriod")
+ config.minControlProcessPeriod = xml.parseUInt();
else if (tag == "guiRefresh")
config.guiRefresh = xml.parseInt();
else if (tag == "userInstrumentsDir")
@@ -1182,6 +1184,7 @@ void MusE::writeGlobalConfiguration(int level, Xml& xml) const
xml.intTag(level, "vstInPlace", config.vstInPlace);
xml.intTag(level, "dummyAudioBufSize", config.dummyAudioBufSize);
xml.intTag(level, "dummyAudioSampleRate", config.dummyAudioSampleRate);
+ xml.uintTag(level, "minControlProcessPeriod", config.minControlProcessPeriod);
xml.intTag(level, "guiRefresh", config.guiRefresh);
xml.strTag(level, "userInstrumentsDir", config.userInstrumentsDir);
diff --git a/muse2/muse/dssihost.cpp b/muse2/muse/dssihost.cpp
index cbb908e6..49a63643 100644
--- a/muse2/muse/dssihost.cpp
+++ b/muse2/muse/dssihost.cpp
@@ -2342,6 +2342,9 @@ iMPEvent DssiSynthIF::getData(MidiPort* /*mp*/, MPEventList* el, iMPEvent i, uns
unsigned long sample = 0;
int loopcount = 0; // REMOVE Tim.
+ // To remember the last retrieved value of each AudioTrack controller.
+ //float prev_ctrl_values[synth->_controlInPorts];
+
// NOTE Tested: Variable run-lengths worked superbly for LADSPA and DSSI synths. But DSSI-VST definitely
// does NOT like changing sample run length. It crashes the plugin and Wine (but MusE keeps running!).
// Furthermore, it resizes the shared memory (mmap, remap) upon each run length DIFFERENT from the last.
@@ -2372,11 +2375,15 @@ iMPEvent DssiSynthIF::getData(MidiPort* /*mp*/, MPEventList* el, iMPEvent i, uns
if(fixedsize > n)
fixedsize = n;
+ unsigned long min_per = config.minControlProcessPeriod;
+ if(min_per > n)
+ min_per = n;
+
// Process automation control values now.
// TODO: This needs to be respect frame resolution. Put this inside the sample loop below.
- for(unsigned long k = 0; k < synth->_controlInPorts; ++k)
+ if(automation && synti && synti->automationType() != AUTO_OFF && id() != -1)
{
- if(automation && synti && synti->automationType() != AUTO_OFF && id() != -1)
+ for(unsigned long k = 0; k < synth->_controlInPorts; ++k)
{
if(controls[k].enCtrl && controls[k].en2Ctrl )
controls[k].val = synti->pluginCtrlVal(genACnum(id(), k));
@@ -2393,7 +2400,7 @@ iMPEvent DssiSynthIF::getData(MidiPort* /*mp*/, MPEventList* el, iMPEvent i, uns
unsigned long index = 0;
unsigned long evframe;
// Get all control ring buffer items valid for this time period...
- //for(int m = 0; m < cbsz; ++m)
+ //for(int m = 0; m < cbsz; ++m) // Doesn't like this. Why?
while(!_controlFifo.isEmpty())
{
//ControlValue v = _controlFifo.get();
@@ -2424,7 +2431,9 @@ iMPEvent DssiSynthIF::getData(MidiPort* /*mp*/, MPEventList* el, iMPEvent i, uns
if(evframe >= n
//|| (found && v.frame != frame)
//|| (!usefixedrate && found && !v.unique && v.frame != frame)
- || (found && !v.unique && evframe != frame)
+ //|| (found && !v.unique && evframe != frame)
+ // Not enough requested samples to satisfy minimum setting? Keep going.
+ || (found && !v.unique && (evframe - sample >= min_per))
// dssi-vst needs them serialized and accounted for, no matter what. This works with fixed rate
// because nsamp is constant. But with packets, we need to guarantee at least one-frame spacing.
// Although we likely won't be using packets with dssi-vst, so it's OK for now.
@@ -2443,6 +2452,16 @@ iMPEvent DssiSynthIF::getData(MidiPort* /*mp*/, MPEventList* el, iMPEvent i, uns
controls[v.idx].val = v.value;
}
+ // Process automation control values now.
+ //if(automation && synti && synti->automationType() != AUTO_OFF && id() != -1)
+ //{
+ // for(unsigned long k = 0; k < synth->_controlInPorts; ++k)
+ // {
+ // if(controls[k].enCtrl && controls[k].en2Ctrl )
+ // controls[k].val = synti->pluginCtrlVal(genACnum(id(), k));
+ // }
+ //}
+
//if(found)
if(found && !usefixedrate)
//nsamp = frame - sample + 1;
diff --git a/muse2/muse/gconfig.cpp b/muse2/muse/gconfig.cpp
index ee6123ef..4d22ad4c 100644
--- a/muse2/muse/gconfig.cpp
+++ b/muse2/muse/gconfig.cpp
@@ -167,6 +167,7 @@ GlobalConfigValues config = {
512, // Dummy audio buffer size
QString("./"), // projectBaseFolder
true, // projectStoreInFolder
- true // useProjectSaveDialog
+ true, // useProjectSaveDialog
+ 64 // minControlProcessPeriod
};
diff --git a/muse2/muse/gconfig.h b/muse2/muse/gconfig.h
index 6fb1bb17..cd236b36 100644
--- a/muse2/muse/gconfig.h
+++ b/muse2/muse/gconfig.h
@@ -142,6 +142,7 @@ struct GlobalConfigValues {
QString projectBaseFolder;
bool projectStoreInFolder;
bool useProjectSaveDialog;
+ unsigned long minControlProcessPeriod;
};
extern GlobalConfigValues config;
diff --git a/muse2/muse/marker/marker.h b/muse2/muse/marker/marker.h
index f1a587f7..012cce80 100644
--- a/muse2/muse/marker/marker.h
+++ b/muse2/muse/marker/marker.h
@@ -24,7 +24,7 @@ class Marker : public Pos {
bool _current;
public:
- Marker() : _current(false) {}
+ Marker() : _name(""),_current(false) {}
Marker(const QString& s, bool cur = false)
: _name(s), _current(cur) {}
void read(Xml&);
diff --git a/muse2/muse/master/lmaster.cpp b/muse2/muse/master/lmaster.cpp
index 21cadfdd..2f921cdc 100644
--- a/muse2/muse/master/lmaster.cpp
+++ b/muse2/muse/master/lmaster.cpp
@@ -207,13 +207,17 @@ LMaster::LMaster()
updateList();
tempo_editor = new QLineEdit(view->viewport());
+ tempo_editor->hide();
connect(tempo_editor, SIGNAL(returnPressed()), SLOT(returnPressed()));
sig_editor = new SigEdit(view->viewport());
+ sig_editor->hide();
connect(sig_editor, SIGNAL(returnPressed()), SLOT(returnPressed()));
pos_editor = new Awl::PosEdit(view->viewport());
+ pos_editor->hide();
connect(pos_editor, SIGNAL(returnPressed()), SLOT(returnPressed()));
key_editor = new QComboBox(view->viewport());
key_editor->addItems(keyStrs);
+ key_editor->hide();
connect(key_editor, SIGNAL(currentIndexChanged(int)), SLOT(returnPressed()));
connect(view, SIGNAL(currentItemChanged(QTreeWidgetItem*, QTreeWidgetItem*)), SLOT(select(QTreeWidgetItem*, QTreeWidgetItem*)));
diff --git a/muse2/muse/midiedit/scoreedit.cpp b/muse2/muse/midiedit/scoreedit.cpp
index 2bc87df8..e70e5310 100644
--- a/muse2/muse/midiedit/scoreedit.cpp
+++ b/muse2/muse/midiedit/scoreedit.cpp
@@ -341,7 +341,7 @@ ScoreEdit::ScoreEdit(QWidget* parent, const char* name, unsigned initPos)
menu_mapper->setMapping(func_velocity_action, CMD_VELOCITY);
- score_canvas->song_changed(SC_EVENT_INSERTED);
+ score_canvas->fully_recalculate();
score_canvas->goto_tick(initPos,true);
if (name!=NULL)
@@ -488,11 +488,10 @@ void ScoreEdit::menu_command(int cmd)
}
}
-//---------------------------------------------------------
-// readPart
-//---------------------------------------------------------
-Part* readPart(Xml& xml, QString tag_name="part") //TODO FINDMICH: duplicated from songfile.cpp; only difference: "none" is supported
+//duplicated from songfile.cpp's MusE::readPart(); the only differences:
+//"none" is supported and tag_name is settable
+Part* read_part(Xml& xml, QString tag_name="part")
{
Part* part = 0;
@@ -523,7 +522,7 @@ Part* readPart(Xml& xml, QString tag_name="part") //TODO FINDMICH: duplicated fr
break;
case Xml::TagStart:
- xml.unknown("readPart");
+ xml.unknown("read_part");
break;
case Xml::TagEnd:
@@ -555,7 +554,7 @@ void staff_t::read_status(Xml& xml)
clef = clef_t(xml.parseInt());
else if (tag == "part")
{
- Part* part=readPart(xml);
+ Part* part=read_part(xml);
if (part)
parts.insert(part);
else
@@ -750,7 +749,7 @@ void ScoreEdit::readStatus(Xml& xml)
else if (tag == "topwin")
TopWin::readStatus(xml);
else if (tag == "selectedPart")
- score_canvas->set_selected_part(readPart(xml, "selectedPart"));
+ score_canvas->set_selected_part(read_part(xml, "selectedPart"));
else if (tag == "staff")
{
staff_t staff(score_canvas);
@@ -862,7 +861,7 @@ void ScoreCanvas::add_staves(PartList* pl, bool all_in_one)
}
cleanup_staves();
- song_changed(SC_EVENT_INSERTED);
+ fully_recalculate();
recalc_staff_pos();
}
@@ -1000,7 +999,7 @@ void ScoreCanvas::set_staffmode(list<staff_t>::iterator it, staff_mode_t mode)
cerr << "ERROR: ILLEGAL FUNCTION CALL: invalid mode in set_staffmode" << endl;
}
- song_changed(SC_EVENT_INSERTED);
+ fully_recalculate();
recalc_staff_pos();
}
@@ -1026,7 +1025,7 @@ void ScoreCanvas::remove_staff(list<staff_t>::iterator it)
}
maybe_close_if_empty();
- song_changed(SC_EVENT_INSERTED);
+ fully_recalculate();
recalc_staff_pos();
}
@@ -1062,7 +1061,7 @@ void ScoreCanvas::merge_staves(list<staff_t>::iterator dest, list<staff_t>::iter
remove_staff(src);
- song_changed(SC_EVENT_INSERTED);
+ fully_recalculate();
recalc_staff_pos();
}
@@ -1093,7 +1092,7 @@ void ScoreCanvas::move_staff_above(list<staff_t>::iterator dest, list<staff_t>::
staves.splice(dest, staves, src, src_end);
- song_changed(SC_EVENT_INSERTED);
+ fully_recalculate();
recalc_staff_pos();
}
@@ -1121,6 +1120,11 @@ set<Part*> ScoreCanvas::get_all_parts()
return result;
}
+void ScoreCanvas::fully_recalculate()
+{
+ song_changed(SC_EVENT_MODIFIED);
+}
+
void ScoreCanvas::song_changed(int flags)
{
if (flags & (SC_PART_MODIFIED |
@@ -3395,7 +3399,7 @@ void ScoreCanvas::mousePressEvent (QMouseEvent* event)
mouse_operation=NO_OP;
mouse_x_drag_operation=LENGTH;
- song_changed(SC_EVENT_INSERTED);
+ fully_recalculate();
setMouseTracking(true);
dragging=true;
@@ -3547,7 +3551,7 @@ void ScoreCanvas::mouseMoveEvent (QMouseEvent* event)
audio->msgChangeEvent(dragged_event, tmp, dragged_event_part, false, false, false);
dragged_event=tmp;
- song_changed(SC_EVENT_INSERTED);
+ fully_recalculate();
}
break;
@@ -3590,7 +3594,7 @@ void ScoreCanvas::mouseMoveEvent (QMouseEvent* event)
audio->msgChangeEvent(dragged_event, tmp, dragged_event_part, false, false, false);
dragged_event=tmp;
- song_changed(SC_EVENT_INSERTED);
+ fully_recalculate();
}
break;
@@ -3626,7 +3630,7 @@ void ScoreCanvas::mouseMoveEvent (QMouseEvent* event)
audio->msgChangeEvent(dragged_event, tmp, dragged_event_part, false, false, false);
dragged_event=tmp;
- song_changed(SC_EVENT_INSERTED);
+ fully_recalculate();
}
break;
@@ -3922,7 +3926,7 @@ void ScoreCanvas::set_quant(int val)
set_pixels_per_whole(pixels_per_whole() * quant_len() / old_len );
- song_changed(SC_EVENT_INSERTED);
+ fully_recalculate();
}
else
{
@@ -4072,6 +4076,7 @@ void staff_t::apply_lasso(QRect rect, set<Event*>& already_processed)
}
}
+
//the following assertions are made:
// pix_quarter.width() == pix_half.width()
@@ -4083,7 +4088,6 @@ void staff_t::apply_lasso(QRect rect, set<Event*>& already_processed)
-
//hint: recalculating event- and itemlists "from zero"
// could happen in realtime, as it is pretty fast.
// however, this adds unneccessary cpu usage.
@@ -4098,8 +4102,7 @@ void staff_t::apply_lasso(QRect rect, set<Event*>& already_processed)
* between, for example, when a cis is tied to a des
*
* CURRENT TODO
- * o let the user select the distance between staves, or do this
- * automatically?
+ * x nothing atm
*
* IMPORTANT TODO
* o add a select-clef-toolbox for tracks
@@ -4108,11 +4111,10 @@ void staff_t::apply_lasso(QRect rect, set<Event*>& already_processed)
* (0,5 sec) when displaying a whole song in scores
* o save toolbar position also in the global window settings
* and provide sane defaults
+ * o support edge-scrolling when opening a lasso
*
* less important stuff
- * o support edge-scrolling when opening a lasso
* o deal with expanding parts
- * o do all the song_changed(SC_EVENT_INSERTED) properly
* o use bars instead of flags over groups of 8ths / 16ths etc
* o support different keys in different tracks at the same time
* calc_pos_add_list and calc_item_pos will be affected by this
@@ -4122,7 +4124,6 @@ void staff_t::apply_lasso(QRect rect, set<Event*>& already_processed)
* o save more configuration stuff (quant, color, to_init)
*
* really unimportant nice-to-haves
- * o clean up code (find TODOs)
* o support in-song clef-changes
* o draw measure numbers
* o use timesig_t in all timesig-stuff
@@ -4135,7 +4136,7 @@ void staff_t::apply_lasso(QRect rect, set<Event*>& already_processed)
* o update translations
* o remove ambiguous translation: "offset"="zeitversatz"
* this is ambigous in mod. note len and WRONG in mod. velo dialogs
-
+ *
* o process accurate timesignatures from muse's list (has to be implemented first in muse)
* ( (2+2+3)/4 or (3+2+2)/4 instead of 7/4 )
* o maybe do expanding parts inside the msgChangeEvent or
@@ -4149,35 +4150,6 @@ void staff_t::apply_lasso(QRect rect, set<Event*>& already_processed)
*/
-/* how to use the score editor with multiple tracks
- * ================================================
- *
- * select parts, right-click, "display in new score window" or "display per-track in new score window"
- * or "display in existing window -> 1,2,3,4" or "display per-track in existing..."
- *
- * ScoreCanvas has a list of note systems, consisting of the following:
- * * all parts included in that view
- * * eventlist, itemlist
- * * used clef, transposing/octave settings
- * * enum { NOT_GROUPED, I_AM_TOP, I_AM_BOTTOM } group_state
- * NOT_GROUPED means "single note system"
- * I_AM_TOP and I_AM_BOTTOM mean that the two systems belong
- * together
- *
- * when redrawing, we iterate through all systems.
- * we add a distance according to group_state
- * then we draw the system. if group_state is I_AM_BOTTOM, we
- * draw our beams longer/higher, and we draw a bracket
- *
- * when clicking around, we first determine which system has been clicked in
- * (the systems have enough space in between, so there won't be notes
- * from sys1 in sys2. if there are, they're ignored for simplicity)
- * then we proceed as usual (adding, removing, changing notes)
- *
- *
- * pos_add_list stays the same for each staff, so we only need one
- */
-
/* R O A D M A P
* =============
*
diff --git a/muse2/muse/midiedit/scoreedit.h b/muse2/muse/midiedit/scoreedit.h
index ceb41679..d664f139 100644
--- a/muse2/muse/midiedit/scoreedit.h
+++ b/muse2/muse/midiedit/scoreedit.h
@@ -690,6 +690,7 @@ class ScoreCanvas : public View
void x_scroll_event(int);
void y_scroll_event(int);
void song_changed(int);
+ void fully_recalculate();
void goto_tick(int,bool);
void pos_changed(int i, unsigned u, bool b);
void heartbeat_timer_event();
diff --git a/muse2/muse/part.h b/muse2/muse/part.h
index 11ff2fd4..f7a864e5 100644
--- a/muse2/muse/part.h
+++ b/muse2/muse/part.h
@@ -143,6 +143,7 @@ class WavePart : public Part {
//---------------------------------------------------------
typedef std::multimap<int, Part*, std::less<unsigned> >::iterator iPart;
+typedef std::multimap<int, Part*, std::less<unsigned> >::reverse_iterator riPart;
typedef std::multimap<int, Part*, std::less<unsigned> >::const_iterator ciPart;
class PartList : public std::multimap<int, Part*, std::less<unsigned> > {
diff --git a/muse2/muse/plugin.cpp b/muse2/muse/plugin.cpp
index 76ebeb1b..215a7844 100644
--- a/muse2/muse/plugin.cpp
+++ b/muse2/muse/plugin.cpp
@@ -2560,6 +2560,9 @@ void PluginI::apply(unsigned long n, unsigned long ports, float** bufIn, float**
// }
//}
+ // Grab the control ring buffer size now.
+ //const int cbsz = _controlFifo.getSize();
+
//unsigned endPos = pos + n;
//unsigned long frameOffset = audio->getFrameOffset();
unsigned long syncFrame = audio->curSyncFrame();
@@ -2581,12 +2584,16 @@ void PluginI::apply(unsigned long n, unsigned long ports, float** bufIn, float**
// so that users can select a small audio period but a larger control period.
if(fixedsize > n)
fixedsize = n;
+
+ unsigned long min_per = config.minControlProcessPeriod;
+ if(min_per > n)
+ min_per = n;
// Process automation control values now.
// TODO: This needs to be respect frame resolution. Put this inside the sample loop below.
- for(unsigned long k = 0; k < controlPorts; ++k)
+ if(automation && _track && _track->automationType() != AUTO_OFF && _id != -1)
{
- if(automation && _track && _track->automationType() != AUTO_OFF && _id != -1)
+ for(unsigned long k = 0; k < controlPorts; ++k)
{
if(controls[k].enCtrl && controls[k].en2Ctrl )
controls[k].tmpVal = _track->pluginCtrlVal(genACnum(_id, k));
@@ -2603,7 +2610,7 @@ void PluginI::apply(unsigned long n, unsigned long ports, float** bufIn, float**
unsigned long index = 0;
unsigned long evframe;
// Get all control ring buffer items valid for this time period...
- //for(int m = 0; m < cbsz; ++m)
+ //for(int m = 0; m < cbsz; ++m) // Doesn't like this. Why?
while(!_controlFifo.isEmpty())
{
//ControlValue v = _controlFifo.get();
@@ -2632,7 +2639,9 @@ void PluginI::apply(unsigned long n, unsigned long ports, float** bufIn, float**
if(evframe >= n
//|| (found && v.frame != frame)
//|| (!usefixedrate && found && !v.unique && v.frame != frame)
- || (found && !v.unique && evframe != frame)
+ //|| (found && !v.unique && evframe != frame)
+ // Not enough requested samples to satisfy minimum setting? Keep going.
+ || (found && !v.unique && (evframe - sample >= min_per))
// Protection. Observed this condition (dummy audio so far). Why? Supposed to be linear timestamps.
//|| (found && evframe < frame)
// dssi-vst needs them serialized and accounted for, no matter what. This works with fixed rate
@@ -2700,7 +2709,7 @@ void PluginI::apply(unsigned long n, unsigned long ports, float** bufIn, float**
//printf("PluginI::apply ports:%lu n:%lu frame:%lu sample:%lu nsamp:%lu syncFrame:%lu loopcount:%d\n",
// ports, n, frame, sample, nsamp, syncFrame, loopcount); // REMOVE Tim.
- // TODO: TESTING: Don't allow zero-length runs. This could/should be checked in the control loop instead.
+ // Don't allow zero-length runs. This could/should be checked in the control loop instead.
// Note this means it is still possible to get stuck in the top loop (at least for a while).
if(nsamp == 0)
continue;
@@ -2712,7 +2721,7 @@ void PluginI::apply(unsigned long n, unsigned long ports, float** bufIn, float**
//fprintf(stderr, "PluginI::apply handle %d\n", i);
_plugin->apply(handle[i], nsamp);
}
-
+
sample += nsamp;
loopcount++; // REMOVE Tim.
}
diff --git a/muse2/muse/song.cpp b/muse2/muse/song.cpp
index cf040348..e6fa9cab 100644
--- a/muse2/muse/song.cpp
+++ b/muse2/muse/song.cpp
@@ -17,6 +17,8 @@
#include <QPoint>
#include <QSignalMapper>
#include <QTextStream>
+#include <QProcess>
+#include <QByteArray>
#include "app.h"
#include "driver/jackmidi.h"
@@ -85,6 +87,7 @@ Song::Song(const char* name)
redoList = new UndoList;
_markerList = new MarkerList;
_globalPitchShift = 0;
+ showSongInfo=true;
clear(false);
}
@@ -1767,6 +1770,24 @@ Marker* Song::setMarkerLock(Marker* m, bool f)
return m;
}
+// kommer inte att gå göra undo på, kanske skulle fixa det.
+
+//void Song::moveMarkers(int startOffset, int ticks)
+//{
+// iMarker markerI;
+// for (markerI=_markerList->rbegin(); markerI != _markerList->rend(); ++markerI) {
+// if (markerI->second.tick() > startOffset) {
+// if (markerI-> )
+// }
+//
+//
+//
+// if (unsigned(t) == markerI->second.tick())//prevent of copmiler warning: comparison signed/unsigned
+// return &markerI->second;
+// }
+//
+//}
+
//---------------------------------------------------------
// setRecordFlag
//---------------------------------------------------------
@@ -3696,79 +3717,74 @@ void Song::executeScript(const char* scriptfile, PartList* parts, int quant, boo
}
fclose(fp);
- // Call external program, let it manipulate the file
- int pid = fork();
- if (pid == 0) {
- if (execlp(scriptfile, scriptfile, tmp, NULL) == -1) {
- perror("Failed to launch script!");
- // Get out of here
-
- // cannot report error through gui, we are in another fork!
- //@!TODO: Handle unsuccessful attempts
- exit(99);
- }
- exit(0);
- }
- else if (pid == -1) {
- perror("fork failed");
- }
- else {
- int status;
- waitpid(pid, &status, 0);
- if (WEXITSTATUS(status) != 0 ) {
- QMessageBox::warning(muse, tr("MusE - external script failed"),
- tr("MusE was unable to launch the script\n")
- );
- endUndo(SC_EVENT_REMOVED);
- return;
- }
- else { // d0 the fun55or5!
- // TODO: Create a new part, update the entire editor from it, hehh....
-
- QFile file(tmp);
- if ( file.open( QIODevice::ReadOnly ) ) {
- QTextStream stream( &file );
- QString line;
- while ( !stream.atEnd() ) {
- line = stream.readLine(); // line of text excluding '\n'
- if (line.startsWith("NOTE"))
- {
- QStringList sl = line.split(" ");
-
- Event e(Note);
- int tick = sl[1].toInt();
- int pitch = sl[2].toInt();
- int len = sl[3].toInt();
- int velo = sl[4].toInt();
- printf ("tick=%d pitch=%d velo=%d len=%d\n", tick,pitch,velo,len);
- e.setTick(tick);
- e.setPitch(pitch);
- e.setVelo(velo);
- e.setLenTick(len);
- // Indicate no undo, and do not do port controller values and clone parts.
- audio->msgAddEvent(e, part, false, false, false);
- }
- if (line.startsWith("CONTROLLER"))
- {
- QStringList sl = line.split(" ");
-
- Event e(Controller);
- int tick = sl[1].toInt();
- int a = sl[2].toInt();
- int b = sl[3].toInt();
- int c = sl[4].toInt();
- printf ("tick=%d a=%d b=%d c=%d\n", tick,a,b,c);
- e.setA(a);
- e.setB(b);
- e.setB(c);
- // Indicate no undo, and do not do port controller values and clone parts.
- audio->msgAddEvent(e, part, false, false, false);
- }
- }
- file.close();
- }
- }
+// QString program(scriptfile);
+ QStringList arguments;
+ arguments << tmp;
+
+ QProcess *myProcess = new QProcess(muse);
+ myProcess->start(scriptfile, arguments);
+ myProcess->waitForFinished();
+ QByteArray errStr = myProcess->readAllStandardError();
+ if (errStr.size()) {
+ QMessageBox::warning(muse, tr("MusE - external script failed"),
+ "Script returned the following error\n"+ QString(errStr));
+ endUndo(SC_EVENT_REMOVED);
+ return;
+
+ } else if (myProcess->exitCode()) {
+ QMessageBox::warning(muse, tr("MusE - external script failed"),
+ tr("MusE was unable to launch the script\n")
+ );
+ endUndo(SC_EVENT_REMOVED);
+ return;
}
+ else { // d0 the fun55or5!
+ // TODO: Create a new part, update the entire editor from it, hehh....
+
+ QFile file(tmp);
+ if ( file.open( QIODevice::ReadOnly ) ) {
+ QTextStream stream( &file );
+ QString line;
+ while ( !stream.atEnd() ) {
+ line = stream.readLine(); // line of text excluding '\n'
+ if (line.startsWith("NOTE"))
+ {
+ QStringList sl = line.split(" ");
+
+ Event e(Note);
+ int tick = sl[1].toInt();
+ int pitch = sl[2].toInt();
+ int len = sl[3].toInt();
+ int velo = sl[4].toInt();
+ //printf ("tick=%d pitch=%d velo=%d len=%d\n", tick,pitch,velo,len);
+ e.setTick(tick);
+ e.setPitch(pitch);
+ e.setVelo(velo);
+ e.setLenTick(len);
+ // Indicate no undo, and do not do port controller values and clone parts.
+ audio->msgAddEvent(e, part, false, false, false);
+ }
+ if (line.startsWith("CONTROLLER"))
+ {
+ QStringList sl = line.split(" ");
+
+ Event e(Controller);
+ int tick = sl[1].toInt();
+ int a = sl[2].toInt();
+ int b = sl[3].toInt();
+ int c = sl[4].toInt();
+ //printf ("tick=%d a=%d b=%d c=%d\n", tick,a,b,c);
+ e.setA(a);
+ e.setB(b);
+ e.setB(c);
+ // Indicate no undo, and do not do port controller values and clone parts.
+ audio->msgAddEvent(e, part, false, false, false);
+ }
+ }
+ file.close();
+ }
+ }
+
remove(tmp);
}
diff --git a/muse2/muse/song.h b/muse2/muse/song.h
index b097a5ee..e1378480 100644
--- a/muse2/muse/song.h
+++ b/muse2/muse/song.h
@@ -139,6 +139,7 @@ class Song : public QObject {
void readMarker(Xml&);
QString songInfoStr; // contains user supplied song information, stored in song file.
+ bool showSongInfo;
QStringList deliveredScriptNames;
QStringList userScriptNames;
@@ -167,7 +168,8 @@ class Song : public QObject {
const QFont& font) const;
QFont readFont(Xml& xml, const char* name);
QString getSongInfo() { return songInfoStr; }
- void setSongInfo(QString info) { songInfoStr = info; }
+ void setSongInfo(QString info, bool show) { songInfoStr = info; showSongInfo = show; }
+ bool showSongInfoOnStartup() { return showSongInfo; }
// If clear_all is false, it will not touch things like midi ports.
void clear(bool signal, bool clear_all = true);
diff --git a/muse2/muse/songfile.cpp b/muse2/muse/songfile.cpp
index 9a577308..a8134b1d 100644
--- a/muse2/muse/songfile.cpp
+++ b/muse2/muse/songfile.cpp
@@ -1232,6 +1232,8 @@ void Song::read(Xml& xml)
setMasterFlag(xml.parseInt());
else if (tag == "info")
songInfoStr = xml.parse1();
+ else if (tag == "showinfo")
+ showSongInfo = xml.parseInt();
else if (tag == "loop")
setLoop(xml.parseInt());
else if (tag == "punchin")
@@ -1437,6 +1439,7 @@ void Song::write(int level, Xml& xml) const
{
xml.tag(level++, "song");
xml.strTag(level, "info", songInfoStr);
+ xml.intTag(level, "showinfo", showSongInfo);
xml.intTag(level, "automation", automation);
xml.intTag(level, "cpos", song->cpos());
xml.intTag(level, "rpos", song->rpos());
diff --git a/muse2/muse/structure.cpp b/muse2/muse/structure.cpp
new file mode 100644
index 00000000..f0a4308a
--- /dev/null
+++ b/muse2/muse/structure.cpp
@@ -0,0 +1,368 @@
+//=========================================================
+// MusE
+// Linux Music Editor
+// $Id: app.cpp,v 1.113.2.68 2009/12/21 14:51:51 spamatica Exp $
+//
+// (C) Copyright 1999-2004 Werner Schweer (ws@seh.de)
+// (C) Copyright 2011 Robert Jonsson (rj@spamatica.se)
+//=========================================================
+
+#include <qmessagebox.h>
+#include "app.h"
+#include "track.h"
+#include "song.h"
+#include "tempo.h"
+#include "al/sig.h"
+#include "keyevent.h"
+#include "audio.h"
+#include "marker/marker.h"
+
+
+//---------------------------------------------------------
+// adjustGlobalLists
+// helper that adjusts tempo, sig, key and marker
+// lists everything from startPos is adjusted
+// 'diff' number of ticks.
+// function requires undo to be handled outside
+//---------------------------------------------------------
+
+void MusE::adjustGlobalLists(int startPos, int diff)
+{
+ const TempoList* t = &tempomap;
+ const AL::SigList* s = &AL::sigmap;
+ const KeyList* k = &keymap;
+
+ criTEvent it = t->rbegin();
+ AL::criSigEvent is = s->rbegin();
+ criKeyEvent ik = k->rbegin();
+
+ // key
+ for (; ik != k->rend(); ik++) {
+ const KeyEvent &ev = (KeyEvent)ik->second;
+ int tick = ev.tick;
+ int key = ev.key;
+ if (tick < startPos )
+ break;
+
+ if (tick > startPos && tick +diff < startPos ) { // remove
+ audio->msgRemoveKey(tick, key, false);
+ }
+ else {
+ audio->msgRemoveKey(tick, key, false);
+ audio->msgAddKey(tick+diff, key, false);
+ }
+ }
+
+ // tempo
+ for (; it != t->rend(); it++) {
+ const TEvent* ev = (TEvent*)it->second;
+ int tick = ev->tick;
+ int tempo = ev->tempo;
+ if (tick < startPos )
+ break;
+
+ if (tick > startPos && tick +diff < startPos ) { // remove
+ audio->msgDeleteTempo(tick, tempo, false);
+ }
+ else {
+ audio->msgDeleteTempo(tick, tempo, false);
+ audio->msgAddTempo(tick+diff, tempo, false);
+ }
+ }
+
+ // sig
+ for (; is != s->rend(); is++) {
+ const AL::SigEvent* ev = (AL::SigEvent*)is->second;
+ int tick = ev->tick;
+ if (tick < startPos )
+ break;
+
+ int z = ev->sig.z;
+ int n = ev->sig.n;
+ if (tick > startPos && tick +diff < startPos ) { // remove
+ audio->msgRemoveSig(tick, z, n, false);
+ }
+ else {
+ audio->msgRemoveSig(tick, z, n, false);
+ audio->msgAddSig(tick+diff, z, n, false);
+ }
+ }
+
+ MarkerList *markerlist = song->marker();
+ for(iMarker i = markerlist->begin(); i != markerlist->end(); ++i)
+ {
+ Marker* m = &i->second;
+ int tick = m->tick();
+ if (tick > startPos)
+ {
+ if (tick + diff < startPos ) { // these ticks should be removed
+ Marker *oldMarker = new Marker();
+ *oldMarker = *m;
+ markerlist->remove(m);
+ song->undoOp(UndoOp::ModifyMarker,oldMarker, 0);
+ } else {
+ Marker *oldMarker = new Marker();
+ *oldMarker = *m;
+ m->setTick(tick + diff);
+ song->undoOp(UndoOp::ModifyMarker,oldMarker, m);
+ }
+ }
+ }
+
+}
+
+//---------------------------------------------------------
+// globalCut
+// - remove area between left and right locator
+// - do not touch muted track
+// - cut master track
+//---------------------------------------------------------
+
+void MusE::globalCut()
+ {
+ int lpos = song->lpos();
+ int rpos = song->rpos();
+ if ((lpos - rpos) >= 0)
+ return;
+
+ song->startUndo();
+ TrackList* tracks = song->tracks();
+ for (iTrack it = tracks->begin(); it != tracks->end(); ++it) {
+ MidiTrack* track = dynamic_cast<MidiTrack*>(*it);
+ if (track == 0 || track->mute())
+ continue;
+ PartList* pl = track->parts();
+ for (iPart p = pl->begin(); p != pl->end(); ++p) {
+ Part* part = p->second;
+ int t = part->tick();
+ int l = part->lenTick();
+ if (t + l <= lpos)
+ continue;
+ if ((t >= lpos) && ((t+l) <= rpos)) {
+ audio->msgRemovePart(part, false);
+ }
+ else if ((t < lpos) && ((t+l) > lpos) && ((t+l) <= rpos)) {
+ // remove part tail
+ int len = lpos - t;
+ MidiPart* nPart = new MidiPart(*(MidiPart*)part);
+ nPart->setLenTick(len);
+ //
+ // cut Events in nPart
+ EventList* el = nPart->events();
+ iEvent ie = el->lower_bound(t + len);
+ for (; ie != el->end();) {
+ iEvent i = ie;
+ ++ie;
+ // Indicate no undo, and do not do port controller values and clone parts.
+ //audio->msgDeleteEvent(i->second, nPart, false);
+ audio->msgDeleteEvent(i->second, nPart, false, false, false);
+ }
+ // Indicate no undo, and do port controller values and clone parts.
+ //audio->msgChangePart(part, nPart, false);
+ audio->msgChangePart(part, nPart, false, true, true);
+ }
+ else if ((t < lpos) && ((t+l) > lpos) && ((t+l) > rpos)) {
+ //----------------------
+ // remove part middle
+ //----------------------
+
+ MidiPart* nPart = new MidiPart(*(MidiPart*)part);
+ EventList* el = nPart->events();
+ iEvent is = el->lower_bound(lpos);
+ iEvent ie = el->upper_bound(rpos);
+ for (iEvent i = is; i != ie;) {
+ iEvent ii = i;
+ ++i;
+ // Indicate no undo, and do not do port controller values and clone parts.
+ //audio->msgDeleteEvent(ii->second, nPart, false);
+ audio->msgDeleteEvent(ii->second, nPart, false, false, false);
+ }
+
+ ie = el->lower_bound(rpos);
+ for (; ie != el->end();) {
+ iEvent i = ie;
+ ++ie;
+ Event event = i->second;
+ Event nEvent = event.clone();
+ nEvent.setTick(nEvent.tick() - (rpos-lpos));
+ // Indicate no undo, and do not do port controller values and clone parts.
+ //audio->msgChangeEvent(event, nEvent, nPart, false);
+ audio->msgChangeEvent(event, nEvent, nPart, false, false, false);
+ }
+ nPart->setLenTick(l - (rpos-lpos));
+ // Indicate no undo, and do port controller values and clone parts.
+ //audio->msgChangePart(part, nPart, false);
+ audio->msgChangePart(part, nPart, false, true, true);
+ }
+ else if ((t >= lpos) && (t < rpos) && (t+l) > rpos) {
+ // TODO: remove part head
+ }
+ else if (t >= rpos) {
+ MidiPart* nPart = new MidiPart(*(MidiPart*)part);
+ int nt = part->tick();
+ nPart->setTick(nt - (rpos -lpos));
+ // Indicate no undo, and do port controller values but not clone parts.
+ //audio->msgChangePart(part, nPart, false);
+ audio->msgChangePart(part, nPart, false, true, false);
+ }
+ }
+ }
+ int diff = lpos - rpos;
+ adjustGlobalLists(lpos, diff);
+
+ song->endUndo(SC_TRACK_MODIFIED | SC_PART_MODIFIED | SC_PART_REMOVED | SC_TEMPO | SC_KEY | SC_SIG);
+ }
+
+//---------------------------------------------------------
+// globalInsert
+// - insert empty space at left locator position upto
+// right locator
+// - do not touch muted track
+// - insert in master track
+//---------------------------------------------------------
+
+void MusE::globalInsert()
+ {
+ unsigned lpos = song->lpos();
+ unsigned rpos = song->rpos();
+ if (lpos >= rpos)
+ return;
+
+ song->startUndo();
+ TrackList* tracks = song->tracks();
+ for (iTrack it = tracks->begin(); it != tracks->end(); ++it) {
+ MidiTrack* track = dynamic_cast<MidiTrack*>(*it);
+ //
+ // process only non muted midi tracks
+ //
+ if (track == 0 || track->mute())
+ continue;
+ PartList* pl = track->parts();
+ for (riPart p = pl->rbegin(); p != pl->rend(); ++p) {
+ Part* part = p->second;
+ unsigned t = part->tick();
+ int l = part->lenTick();
+ if (t + l <= lpos)
+ continue;
+ if (lpos >= t && lpos < (t+l)) {
+ MidiPart* nPart = new MidiPart(*(MidiPart*)part);
+ nPart->setLenTick(l + (rpos-lpos));
+ EventList* el = nPart->events();
+
+ iEvent i = el->end();
+ while (i != el->begin()) {
+ --i;
+ if (i->first < lpos)
+ break;
+ Event event = i->second;
+ Event nEvent = i->second.clone();
+ nEvent.setTick(nEvent.tick() + (rpos-lpos));
+ // Indicate no undo, and do not do port controller values and clone parts.
+ //audio->msgChangeEvent(event, nEvent, nPart, false);
+ audio->msgChangeEvent(event, nEvent, nPart, false, false, false);
+ }
+ // Indicate no undo, and do port controller values and clone parts.
+ //audio->msgChangePart(part, nPart, false);
+ audio->msgChangePart(part, nPart, false, true, true);
+ }
+ else if (t > lpos) {
+ MidiPart* nPart = new MidiPart(*(MidiPart*)part);
+ nPart->setTick(t + (rpos -lpos));
+ // Indicate no undo, and do port controller values but not clone parts.
+ //audio->msgChangePart(part, nPart, false);
+ audio->msgChangePart(part, nPart, false, true, false);
+ }
+ }
+ }
+
+ int diff = rpos - lpos;
+ adjustGlobalLists(lpos, diff);
+
+ song->endUndo(SC_TRACK_MODIFIED | SC_PART_MODIFIED | SC_PART_REMOVED | SC_TEMPO | SC_KEY | SC_SIG );
+ }
+
+
+//---------------------------------------------------------
+// globalSplit
+// - split all parts at the song position pointer
+// - do not touch muted track
+//---------------------------------------------------------
+
+void MusE::globalSplit()
+ {
+ int pos = song->cpos();
+ song->startUndo();
+ TrackList* tracks = song->tracks();
+ for (iTrack it = tracks->begin(); it != tracks->end(); ++it) {
+ Track* track = *it;
+ PartList* pl = track->parts();
+ for (iPart p = pl->begin(); p != pl->end(); ++p) {
+ Part* part = p->second;
+ int p1 = part->tick();
+ int l0 = part->lenTick();
+ if (pos > p1 && pos < (p1+l0)) {
+ Part* p1;
+ Part* p2;
+ track->splitPart(part, pos, p1, p2);
+ // Indicate no undo, and do port controller values but not clone parts.
+ //audio->msgChangePart(part, p1, false);
+ audio->msgChangePart(part, p1, false, true, false);
+ audio->msgAddPart(p2, false);
+ break;
+ }
+ }
+ }
+ song->endUndo(SC_TRACK_MODIFIED | SC_PART_MODIFIED | SC_PART_INSERTED);
+ }
+
+//---------------------------------------------------------
+// copyRange
+// - copy space between left and right locator position
+// to song position pointer
+// - dont process muted tracks
+// - create a new part for every track containing the
+// copied events
+//---------------------------------------------------------
+
+void MusE::copyRange()
+ {
+ QMessageBox::critical(this,
+ tr("MusE: Copy Range"),
+ tr("not implemented")
+ );
+ }
+
+//---------------------------------------------------------
+// cutEvents
+// - make sure that all events in a part end where the
+// part ends
+// - process only marked parts
+//---------------------------------------------------------
+
+void MusE::cutEvents()
+ {
+ QMessageBox::critical(this,
+ tr("MusE: Cut Events"),
+ tr("not implemented")
+ );
+ }
+
+//---------------------------------------------------------
+// checkRegionNotNull
+// return true if (rPos - lPos) <= 0
+//---------------------------------------------------------
+
+bool MusE::checkRegionNotNull()
+ {
+ int start = song->lPos().frame();
+ int end = song->rPos().frame();
+ if (end - start <= 0) {
+ QMessageBox::critical(this,
+ tr("MusE: Bounce"),
+ tr("set left/right marker for bounce range")
+ );
+ return true;
+ }
+ return false;
+ }
+
diff --git a/muse2/muse/undo.cpp b/muse2/muse/undo.cpp
index 44d37591..a31b8e7a 100644
--- a/muse2/muse/undo.cpp
+++ b/muse2/muse/undo.cpp
@@ -897,10 +897,18 @@ void Song::doUndo3()
break;
case UndoOp::ModifyMarker:
{
- //printf("performing undo for one marker at %d\n", i->realMarker->tick());
- Marker tmpMarker = *i->realMarker;
- *i->realMarker = *i->copyMarker; // swap them
- *i->copyMarker = tmpMarker;
+ //printf("performing undo for one marker at copy %d real %d\n", i->copyMarker, i->realMarker);
+ if (i->realMarker) {
+ Marker tmpMarker = *i->realMarker;
+ *i->realMarker = *i->copyMarker; // swap them
+ *i->copyMarker = tmpMarker;
+ }
+ else {
+ //printf("flipping marker\n");
+ i->realMarker = _markerList->add(*i->copyMarker);
+ delete i->copyMarker;
+ i->copyMarker = 0;
+ }
}
break;
default:
@@ -979,10 +987,16 @@ void Song::doRedo3()
break;
case UndoOp::ModifyMarker:
{
- //printf("performing redo for one marker at %d\n", i->realMarker->tick());
- Marker tmpMarker = *i->realMarker;
- *i->realMarker = *i->copyMarker; // swap them
- *i->copyMarker = tmpMarker;
+ //printf("performing redo for one marker at copy %d real %d\n", i->copyMarker, i->realMarker);
+ if (i->copyMarker) {
+ Marker tmpMarker = *i->realMarker;
+ *i->realMarker = *i->copyMarker; // swap them
+ *i->copyMarker = tmpMarker;
+ } else {
+ i->copyMarker = new Marker(*i->realMarker);
+ _markerList->remove(i->realMarker);
+ i->realMarker = 0;
+ }
}
break;
default:
diff --git a/muse2/muse/widgets/genset.cpp b/muse2/muse/widgets/genset.cpp
index 4a0550bb..edf3cfda 100644
--- a/muse2/muse/widgets/genset.cpp
+++ b/muse2/muse/widgets/genset.cpp
@@ -28,6 +28,9 @@ static int divisions[] = {
static int dummyAudioBufSizes[] = {
16, 32, 64, 128, 256, 512, 1024, 2048
};
+static unsigned long minControlProcessPeriods[] = {
+ 1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048
+ };
//---------------------------------------------------------
// GlobalSettingsConfig
@@ -66,6 +69,13 @@ GlobalSettingsConfig::GlobalSettingsConfig(QWidget* parent)
}
}
+ for (unsigned i = 0; i < sizeof(minControlProcessPeriods)/sizeof(*minControlProcessPeriods); ++i) {
+ if (minControlProcessPeriods[i] == config.minControlProcessPeriod) {
+ minControlProcessPeriodComboBox->setCurrentIndex(i);
+ break;
+ }
+ }
+
userInstrumentsPath->setText(config.userInstrumentsDir);
selectInstrumentsDirButton->setIcon(*openIcon);
defaultInstrumentsDirButton->setIcon(*undoIcon);
@@ -185,6 +195,13 @@ void GlobalSettingsConfig::updateSettings()
}
}
+ for (unsigned i = 0; i < sizeof(minControlProcessPeriods)/sizeof(*minControlProcessPeriods); ++i) {
+ if (minControlProcessPeriods[i] == config.minControlProcessPeriod) {
+ minControlProcessPeriodComboBox->setCurrentIndex(i);
+ break;
+ }
+ }
+
guiRefreshSelect->setValue(config.guiRefresh);
minSliderSelect->setValue(int(config.minSlider));
minMeterSelect->setValue(config.minMeter);
@@ -279,6 +296,8 @@ void GlobalSettingsConfig::apply()
int das = dummyAudioSize->currentIndex();
config.dummyAudioBufSize = dummyAudioBufSizes[das];
config.dummyAudioSampleRate = dummyAudioRate->value();
+ int mcp = minControlProcessPeriodComboBox->currentIndex();
+ config.minControlProcessPeriod = minControlProcessPeriods[mcp];
int div = midiDivisionSelect->currentIndex();
config.division = divisions[div];
diff --git a/muse2/muse/widgets/gensetbase.ui b/muse2/muse/widgets/gensetbase.ui
index a48dd3f0..ca4b97f8 100644
--- a/muse2/muse/widgets/gensetbase.ui
+++ b/muse2/muse/widgets/gensetbase.ui
@@ -6,8 +6,8 @@
<rect>
<x>0</x>
<y>0</y>
- <width>522</width>
- <height>528</height>
+ <width>526</width>
+ <height>506</height>
</rect>
</property>
<property name="windowTitle">
@@ -550,11 +550,20 @@
<string>Mixer</string>
</property>
<layout class="QGridLayout">
- <property name="margin">
+ <property name="leftMargin">
<number>11</number>
</property>
+ <property name="topMargin">
+ <number>2</number>
+ </property>
+ <property name="rightMargin">
+ <number>11</number>
+ </property>
+ <property name="bottomMargin">
+ <number>2</number>
+ </property>
<property name="spacing">
- <number>6</number>
+ <number>2</number>
</property>
<item row="0" column="1">
<widget class="QSpinBox" name="minSliderSelect">
@@ -617,8 +626,7 @@
<item row="2" column="0">
<widget class="QLabel" name="freewheelLabel">
<property name="text">
- <string>Use Jack freewheel mode if possible.
-(Speeds up bounce operations).</string>
+ <string>Try to use Jack Freewheel</string>
</property>
<property name="wordWrap">
<bool>false</bool>
@@ -634,6 +642,13 @@
</item>
<item row="2" column="1">
<widget class="QCheckBox" name="freewheelCheckBox">
+ <property name="toolTip">
+ <string>Speeds bounce operations</string>
+ </property>
+ <property name="whatsThis">
+ <string>Use Jack Freewheel mode if possible.
+This dramatically speeds bounce operations.</string>
+ </property>
<property name="text">
<string/>
</property>
@@ -669,8 +684,7 @@
<item row="5" column="0">
<widget class="QLabel" name="vstInPlaceTextLabel">
<property name="text">
- <string>Enable in-place processing for VST plugins.
-(Requires restart.)</string>
+ <string>VST in-place</string>
</property>
<property name="wordWrap">
<bool>false</bool>
@@ -679,14 +693,105 @@
</item>
<item row="5" column="1">
<widget class="QCheckBox" name="vstInPlaceCheckBox">
+ <property name="toolTip">
+ <string>Enable VST in-place processing (restart required)</string>
+ </property>
<property name="whatsThis">
- <string>Turn this off if VST Ladspa effect rack plugins do not work or feedback loudly, even if they are supposed to be in-place capable.</string>
+ <string>Enable VST in-place processing. Turn this off if
+ VST Ladspa effect rack plugins do not work or
+ feedback loudly, even if they are supposed to
+ be in-place capable. Setting requires a restart.</string>
</property>
<property name="text">
<string/>
</property>
</widget>
</item>
+ <item row="6" column="0">
+ <widget class="QLabel" name="minControlProcessPeriodLabel">
+ <property name="text">
+ <string>Minimum control period</string>
+ </property>
+ </widget>
+ </item>
+ <item row="6" column="1">
+ <widget class="QComboBox" name="minControlProcessPeriodComboBox">
+ <property name="toolTip">
+ <string>Minimum audio controller process period (samples).
+</string>
+ </property>
+ <property name="whatsThis">
+ <string>Minimum audio controller process period (samples).
+Adjusts responsiveness of audio controls and
+ controller graphs. Set a low value for fast, smooth
+ control. If it causes performance problems, set a
+ higher value. </string>
+ </property>
+ <property name="maxVisibleItems">
+ <number>15</number>
+ </property>
+ <item>
+ <property name="text">
+ <string>1</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>2</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>4</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>8</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>16</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>32</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>64</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>128</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>256</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>512</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>1024</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>2048</string>
+ </property>
+ </item>
+ </widget>
+ </item>
</layout>
</widget>
</item>
@@ -696,6 +801,15 @@
<string>External Waveditor</string>
</property>
<layout class="QGridLayout">
+ <property name="topMargin">
+ <number>2</number>
+ </property>
+ <property name="bottomMargin">
+ <number>2</number>
+ </property>
+ <property name="spacing">
+ <number>2</number>
+ </property>
<item row="0" column="0">
<layout class="QGridLayout">
<item row="0" column="0">
@@ -771,6 +885,21 @@
<string>Dummy Audio Driver (settings require restart)</string>
</property>
<layout class="QGridLayout">
+ <property name="leftMargin">
+ <number>11</number>
+ </property>
+ <property name="topMargin">
+ <number>2</number>
+ </property>
+ <property name="rightMargin">
+ <number>11</number>
+ </property>
+ <property name="bottomMargin">
+ <number>2</number>
+ </property>
+ <property name="spacing">
+ <number>2</number>
+ </property>
<item row="0" column="0">
<widget class="QLabel" name="dummyAudioRateLabel">
<property name="text">
diff --git a/muse2/muse/widgets/musewidgetsplug.cpp b/muse2/muse/widgets/musewidgetsplug.cpp
index 4b61cf2a..8cb0b57e 100644
--- a/muse2/muse/widgets/musewidgetsplug.cpp
+++ b/muse2/muse/widgets/musewidgetsplug.cpp
@@ -193,6 +193,10 @@ GlobalConfigValues config = {
false, // vstInPlace Enable VST in-place processing
44100, // Dummy audio preferred sample rate
512 // Dummy audio buffer size
+ QString("./"), // projectBaseFolder
+ true, // projectStoreInFolder
+ true, // useProjectSaveDialog
+ 64 // minControlProcessPeriod
};
//---------------------------------------------------------
diff --git a/muse2/muse/widgets/songinfo.ui b/muse2/muse/widgets/songinfo.ui
index 0944ce93..c313fd9f 100644
--- a/muse2/muse/widgets/songinfo.ui
+++ b/muse2/muse/widgets/songinfo.ui
@@ -25,6 +25,13 @@
<item>
<layout class="QHBoxLayout">
<item>
+ <widget class="QCheckBox" name="viewCheckBox">
+ <property name="text">
+ <string>Show on song load</string>
+ </property>
+ </widget>
+ </item>
+ <item>
<spacer name="spacer1">
<property name="orientation">
<enum>Qt::Horizontal</enum>