diff options
author | Florian Jung <flo@windfisch.org> | 2011-05-11 16:41:11 +0000 |
---|---|---|
committer | Florian Jung <flo@windfisch.org> | 2011-05-11 16:41:11 +0000 |
commit | 1c431bd67567104ba9e026ae75ba479f56d387a2 (patch) | |
tree | 953f7f708eefd8fbac23937a987ad2cce667dd19 /muse2/muse | |
parent | 56b1d339a4176c07d4d995bd8912f1eccddc5539 (diff) | |
parent | 4f2e54561260eb8382953d5723d5d111353a22c9 (diff) |
some housekeeping:
- merged with trunk
- removed note to myself
- some code-cleanups
Diffstat (limited to 'muse2/muse')
-rw-r--r-- | muse2/muse/CMakeLists.txt | 1 | ||||
-rw-r--r-- | muse2/muse/app.cpp | 280 | ||||
-rw-r--r-- | muse2/muse/app.h | 5 | ||||
-rw-r--r-- | muse2/muse/conf.cpp | 3 | ||||
-rw-r--r-- | muse2/muse/dssihost.cpp | 27 | ||||
-rw-r--r-- | muse2/muse/gconfig.cpp | 3 | ||||
-rw-r--r-- | muse2/muse/gconfig.h | 1 | ||||
-rw-r--r-- | muse2/muse/marker/marker.h | 2 | ||||
-rw-r--r-- | muse2/muse/master/lmaster.cpp | 4 | ||||
-rw-r--r-- | muse2/muse/midiedit/scoreedit.cpp | 80 | ||||
-rw-r--r-- | muse2/muse/midiedit/scoreedit.h | 1 | ||||
-rw-r--r-- | muse2/muse/part.h | 1 | ||||
-rw-r--r-- | muse2/muse/plugin.cpp | 21 | ||||
-rw-r--r-- | muse2/muse/song.cpp | 160 | ||||
-rw-r--r-- | muse2/muse/song.h | 4 | ||||
-rw-r--r-- | muse2/muse/songfile.cpp | 3 | ||||
-rw-r--r-- | muse2/muse/structure.cpp | 368 | ||||
-rw-r--r-- | muse2/muse/undo.cpp | 30 | ||||
-rw-r--r-- | muse2/muse/widgets/genset.cpp | 19 | ||||
-rw-r--r-- | muse2/muse/widgets/gensetbase.ui | 147 | ||||
-rw-r--r-- | muse2/muse/widgets/musewidgetsplug.cpp | 4 | ||||
-rw-r--r-- | muse2/muse/widgets/songinfo.ui | 7 |
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> |