summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--muse2/ChangeLog7
-rw-r--r--muse2/muse/app.cpp515
-rw-r--r--muse2/muse/app.h23
-rw-r--r--muse2/muse/arranger/pcanvas.cpp872
-rw-r--r--muse2/muse/arranger/pcanvas.h18
-rw-r--r--muse2/muse/audio.h6
-rw-r--r--muse2/muse/ctrl/ctrlcanvas.cpp399
-rw-r--r--muse2/muse/event.cpp71
-rw-r--r--muse2/muse/event.h14
-rw-r--r--muse2/muse/functions.cpp252
-rw-r--r--muse2/muse/functions.h9
-rw-r--r--muse2/muse/keyevent.cpp54
-rw-r--r--muse2/muse/keyevent.h5
-rw-r--r--muse2/muse/liste/listedit.cpp14
-rw-r--r--muse2/muse/midiedit/dcanvas.cpp207
-rw-r--r--muse2/muse/midiedit/dcanvas.h6
-rw-r--r--muse2/muse/midiedit/dlist.cpp18
-rw-r--r--muse2/muse/midiedit/ecanvas.cpp46
-rw-r--r--muse2/muse/midiedit/ecanvas.h8
-rw-r--r--muse2/muse/midiedit/prcanvas.cpp205
-rw-r--r--muse2/muse/midiedit/prcanvas.h6
-rw-r--r--muse2/muse/midiedit/scoreedit.cpp26
-rw-r--r--muse2/muse/midiedit/scoreedit.h7
-rw-r--r--muse2/muse/miditransform.cpp20
-rw-r--r--muse2/muse/part.cpp295
-rw-r--r--muse2/muse/part.h15
-rw-r--r--muse2/muse/seqmsg.cpp22
-rw-r--r--muse2/muse/song.cpp68
-rw-r--r--muse2/muse/song.h20
-rw-r--r--muse2/muse/structure.cpp4
-rw-r--r--muse2/muse/undo.cpp198
-rw-r--r--muse2/muse/undo.h18
-rw-r--r--muse2/muse/widgets/canvas.cpp59
-rw-r--r--muse2/muse/widgets/canvas.h10
34 files changed, 686 insertions, 2831 deletions
diff --git a/muse2/ChangeLog b/muse2/ChangeLog
index af367344..260d7225 100644
--- a/muse2/ChangeLog
+++ b/muse2/ChangeLog
@@ -1,3 +1,6 @@
+27.06.2011:
+ - Massively speeded up muse by using operation groups (flo93)
+ - Changed behaviour of middle click in all canvases to "delete" (flo93)
21.06.2011:
- Fixed wave editor position and marker drawing corruption. (Tim)
- Updated Yamaha m06 IDF file to version 4 by Geoff King. (Tim)
@@ -13,10 +16,12 @@
- Fixed midi TrackInfo patch name not initializing at position 0 even when value stored, with FluidSynth (possibly others).
- Fixed some leaks, lack of dtors cleanup call when repeatedly loading songs. Should be a weee bit more stable now.
- EXPERIMENT: Midi track input routes can now come from any of the synthesizers! This is a WIP and might change or disappear.
+06.06.2011:
+ - removed (unused) support for disabling the keymap (flo93)
04.06.2011:
- fixed regression with switching ctrl/shift when manipulating
items in canvas. drag+shift limits movement, drag+ctrl copies (rj)
-
+ - changed behaviour of middle click in all canvases to "delete" (flo93)
02.06.2011:
- the score editor now allows batch-movements, that is,
you can transpose or move the whole selection and not
diff --git a/muse2/muse/app.cpp b/muse2/muse/app.cpp
index 89947102..fb07955f 100644
--- a/muse2/muse/app.cpp
+++ b/muse2/muse/app.cpp
@@ -54,6 +54,7 @@
#include "tools.h"
#include "visibletracks.h"
#include "widgets/unusedwavefiles.h"
+#include "functions.h"
#ifdef DSSI_SUPPORT
#include "dssihost.h"
@@ -105,13 +106,6 @@ int watchAudio, watchAudioPrefetch, watchMidi;
pthread_t splashThread;
-//PyScript *pyscript;
-// void MusE::runPythonScript()
-// {
-// QString script("test.py");
-// // pyscript->runPythonScript(script);
-// }
-
void MusE::clearScoreMenuMappers()
{
@@ -137,127 +131,12 @@ void microSleep(long msleep)
sleepOk=usleep(msleep);
}
-// Removed p3.3.17
-/*
-//---------------------------------------------------------
-// watchdog thread
-//---------------------------------------------------------
-
-static void* watchdog(void*)
- {
- doSetuid();
-
- struct sched_param rt_param;
- memset(&rt_param, 0, sizeof(rt_param));
- rt_param.sched_priority = sched_get_priority_max(SCHED_FIFO);
- int rv = pthread_setschedparam(pthread_self(), SCHED_FIFO, &rt_param);
- if (rv != 0)
- perror("Set realtime scheduler");
-
- int policy;
- if (pthread_getschedparam(pthread_self(), &policy, &rt_param)!= 0) {
- printf("Cannot get current client scheduler: %s\n", strerror(errno));
- }
- if (policy != SCHED_FIFO)
- printf("watchdog process %d _NOT_ running SCHED_FIFO\n", getpid());
- else if (debugMsg)
- printf("watchdog set to SCHED_FIFO priority %d\n",
- sched_get_priority_max(SCHED_FIFO));
-
- undoSetuid();
- int fatal = 0;
- for (;;) {
- watchAudio = 0;
- watchMidi = 0;
- static const int WD_TIMEOUT = 3;
-
- // sleep can be interrpted by signals:
- int to = WD_TIMEOUT;
- while (to > 0)
- to = sleep(to);
-
- bool timeout = false;
- if (midiSeqRunning && watchMidi == 0)
- {
- printf("midiSeqRunning = %i watchMidi %i\n", midiSeqRunning, watchMidi);
- timeout = true;
- }
- if (watchAudio == 0)
- timeout = true;
- if (watchAudio > 500000)
- timeout = true;
- if (timeout)
- ++fatal;
- else
- fatal = 0;
- if (fatal >= 3) {
- printf("WatchDog: fatal error, realtime task timeout\n");
- printf(" (%d,%d-%d) - stopping all services\n",
- watchMidi, watchAudio, fatal);
- break;
- }
-// printf("wd %d %d %d\n", watchMidi, watchAudio, fatal);
- }
- audio->stop(true);
- audioPrefetch->stop(true);
- printf("watchdog exit\n");
- exit(-1);
- }
-*/
-
//---------------------------------------------------------
// seqStart
//---------------------------------------------------------
bool MusE::seqStart()
{
- // Changed by Tim. p3.3.17
-
- /*
- if (audio->isRunning()) {
- printf("seqStart(): already running\n");
- return true;
- }
-
- if (realTimeScheduling) {
- //
- // create watchdog thread with max priority
- //
- doSetuid();
- struct sched_param rt_param;
- memset(&rt_param, 0, sizeof(rt_param));
- rt_param.sched_priority = realTimePriority +1;//sched_get_priority_max(SCHED_FIFO);
-
- pthread_attr_t* attributes = (pthread_attr_t*) malloc(sizeof(pthread_attr_t));
- pthread_attr_init(attributes);
-
-// if (pthread_attr_setschedpolicy(attributes, SCHED_FIFO)) {
-// printf("MusE: cannot set FIFO scheduling class for RT thread\n");
-// }
-// if (pthread_attr_setschedparam (attributes, &rt_param)) {
-// // printf("Cannot set scheduling priority for RT thread (%s)\n", strerror(errno));
-// }
-// if (pthread_attr_setscope (attributes, PTHREAD_SCOPE_SYSTEM)) {
-// printf("MusE: Cannot set scheduling scope for RT thread\n");
-// }
- if (pthread_create(&watchdogThread, attributes, ::watchdog, 0))
- perror("MusE: creating watchdog thread failed:");
- pthread_attr_destroy(attributes);
- undoSetuid();
- }
- audioPrefetch->start();
- audioPrefetch->msgSeek(0, true); // force
- midiSeqRunning = !midiSeq->start();
-
- if (!audio->start()) {
- QMessageBox::critical( muse, tr(QString("Failed to start audio!")),
- tr(QString("Was not able to start audio, check if jack is running.\n")));
- return false;
- }
-
- return true;
- */
-
if (audio->isRunning()) {
printf("seqStart(): already running\n");
return true;
@@ -274,12 +153,10 @@ bool MusE::seqStart()
//
for(int i = 0; i < 60; ++i)
{
- //if (audioState == AUDIO_START2)
if(audio->isRunning())
break;
sleep(1);
}
- //if (audioState != AUDIO_START2) {
if(!audio->isRunning())
{
QMessageBox::critical( muse, tr("Failed to start audio!"),
@@ -293,66 +170,6 @@ bool MusE::seqStart()
if(debugMsg)
printf("MusE::seqStart: getting audio driver realTimePriority:%d\n", realTimePriority);
- // Disabled by Tim. p3.3.22
- /*
- if(realTimeScheduling)
- {
- //
- // create watchdog thread with max priority
- //
- doSetuid();
- struct sched_param rt_param;
- memset(&rt_param, 0, sizeof(rt_param));
- rt_param.sched_priority = realTimePriority + 1;//sched_get_priority_max(SCHED_FIFO);
-
- pthread_attr_t* attributes = (pthread_attr_t*) malloc(sizeof(pthread_attr_t));
- pthread_attr_init(attributes);
-
-// if (pthread_attr_setschedpolicy(attributes, SCHED_FIFO)) {
-// printf("MusE: cannot set FIFO scheduling class for RT thread\n");
-// }
-// if (pthread_attr_setschedparam (attributes, &rt_param)) {
-// // printf("Cannot set scheduling priority for RT thread (%s)\n", strerror(errno));
-// }
-// if (pthread_attr_setscope (attributes, PTHREAD_SCOPE_SYSTEM)) {
-// printf("MusE: Cannot set scheduling scope for RT thread\n");
-// }
- if (pthread_create(&watchdogThread, attributes, ::watchdog, 0))
- perror("MusE: creating watchdog thread failed");
- pthread_attr_destroy(attributes);
- undoSetuid();
- }
- */
-
- //int policy;
- //if ((policy = sched_getscheduler (0)) < 0) {
- // printf("Cannot get current client scheduler: %s\n", strerror(errno));
- // }
- //if (policy != SCHED_FIFO)
- // printf("midi thread %d _NOT_ running SCHED_FIFO\n", getpid());
-
-
- //audioState = AUDIO_RUNNING;
- // Changed by Tim. p3.3.22
- /*
- //if(realTimePriority)
- if(realTimeScheduling)
- {
- int pr = realTimePriority;
- if(pr > 5)
- pr -= 5;
- else
- pr = 0;
- audioPrefetch->start(pr);
- //audioWriteback->start(realTimePriority - 5);
- }
- else
- {
- audioPrefetch->start(0);
- //audioWriteback->start(0);
- }
- */
-
int pfprio = 0;
int midiprio = 0;
@@ -362,52 +179,6 @@ bool MusE::seqStart()
// in JackAudioDevice::realtimePriority() which is a bit flawed - it reports there's no RT...
if(realTimeScheduling)
{
- //if(realTimePriority < 5)
- // printf("MusE: WARNING: Recommend setting audio realtime priority to a higher value!\n");
- /*
- if(realTimePriority == 0)
- {
- pfprio = 1;
- midiprio = 2;
- }
- else
- if(realTimePriority == 1)
- {
- pfprio = 2;
- midiprio = 3;
- }
- else
- if(realTimePriority == 2)
- {
- pfprio = 1;
- midiprio = 3;
- }
- else
- if(realTimePriority == 3)
- {
- pfprio = 1;
- //midiprio = 2;
- // p3.3.37
- midiprio = 4;
- }
- else
- if(realTimePriority == 4)
- {
- pfprio = 1;
- //midiprio = 3;
- // p3.3.37
- midiprio = 5;
- }
- else
- if(realTimePriority == 5)
- {
- pfprio = 1;
- //midiprio = 3;
- // p3.3.37
- midiprio = 6;
- }
- else
- */
{
//pfprio = realTimePriority - 5;
// p3.3.40
@@ -536,16 +307,6 @@ void addProject(const QString& name)
// populateAddSynth
//---------------------------------------------------------
-/*
-struct addSynth_cmp_str
-{
- bool operator()(std::string a, std::string b)
- {
- return (a < b);
- }
-};
-*/
-
// ORCAN - CHECK
QMenu* populateAddSynth(QWidget* parent)
{
@@ -977,6 +738,10 @@ MusE::MusE(int argc, char** argv) : QMainWindow()
editPaste2TrackAction = new QAction(QIcon(*editpaste2TrackIconSet), tr("Paste to &track"), this);
editPasteC2TAction = new QAction(QIcon(*editpasteClone2TrackIconSet), tr("Paste clone to trac&k"), this);
editDeleteSelectedAction = new QAction(QIcon(*edit_track_delIcon), tr("Delete Selected Tracks"), this);
+
+ editShrinkPartsAction = new QAction(tr("Shrink selected parts"), this); //FINDMICH TODO tooltips!
+ editExpandPartsAction = new QAction(tr("Expand selected parts"), this);
+ editCleanPartsAction = new QAction(tr("Clean selected parts"), this);
addTrack = new QMenu(tr("Add Track"), this);
@@ -1127,6 +892,10 @@ MusE::MusE(int argc, char** argv) : QMainWindow()
connect(editPasteC2TAction, SIGNAL(triggered()), editSignalMapper, SLOT(map()));
connect(editDeleteSelectedAction, SIGNAL(triggered()), editSignalMapper, SLOT(map()));
+ connect(editShrinkPartsAction, SIGNAL(triggered()), editSignalMapper, SLOT(map()));
+ connect(editExpandPartsAction, SIGNAL(triggered()), editSignalMapper, SLOT(map()));
+ connect(editCleanPartsAction, SIGNAL(triggered()), editSignalMapper, SLOT(map()));
+
connect(editSelectAllAction, SIGNAL(triggered()), editSignalMapper, SLOT(map()));
connect(editDeselectAllAction, SIGNAL(triggered()), editSignalMapper, SLOT(map()));
connect(editInvertSelectionAction, SIGNAL(triggered()), editSignalMapper, SLOT(map()));
@@ -1143,6 +912,9 @@ MusE::MusE(int argc, char** argv) : QMainWindow()
editSignalMapper->setMapping(editPasteC2TAction, CMD_PASTE_CLONE_TO_TRACK);
editSignalMapper->setMapping(editInsertEMAction, CMD_INSERTMEAS);
editSignalMapper->setMapping(editDeleteSelectedAction, CMD_DELETE_TRACK);
+ editSignalMapper->setMapping(editShrinkPartsAction, CMD_SHRINK_PART);
+ editSignalMapper->setMapping(editExpandPartsAction, CMD_EXPAND_PART);
+ editSignalMapper->setMapping(editCleanPartsAction, CMD_CLEAN_PART);
editSignalMapper->setMapping(editSelectAllAction, CMD_SELECT_ALL);
editSignalMapper->setMapping(editDeselectAllAction, CMD_SELECT_NONE);
editSignalMapper->setMapping(editInvertSelectionAction, CMD_SELECT_INVERT);
@@ -1314,12 +1086,6 @@ MusE::MusE(int argc, char** argv) : QMainWindow()
// Popups
//---------------------------------------------------
-// QPopupMenu *foo = new QPopupMenu(this);
-// testAction = new QAction(foo,"testPython");
-// testAction->addTo(foo);
-// menuBar()->insertItem(tr("&testpython"), foo);
-// connect(testAction, SIGNAL(activated()), this, SLOT(runPythonScript()));
-
//-------------------------------------------------------------
// popup File
@@ -1361,6 +1127,10 @@ MusE::MusE(int argc, char** argv) : QMainWindow()
menuEdit->addAction(editPaste2TrackAction);
menuEdit->addAction(editPasteC2TAction);
menuEdit->addSeparator();
+ menuEdit->addAction(editShrinkPartsAction);
+ menuEdit->addAction(editExpandPartsAction);
+ menuEdit->addAction(editCleanPartsAction);
+ menuEdit->addSeparator();
menuEdit->addAction(editDeleteSelectedAction);
// Moved below. Have to wait until synths are available...
@@ -1389,20 +1159,14 @@ MusE::MusE(int argc, char** argv) : QMainWindow()
menuEdit->addMenu(midiEdit);
-#if 0 // TODO
- midiEdit->insertItem(tr("Modify Gate Time"), this, SLOT(modifyGateTime()));
- midiEdit->insertItem(tr("Modify Velocity"), this, SLOT(modifyVelocity()));
- midiEdit->insertItem(tr("Crescendo"), this, SLOT(crescendo()));
- midiEdit->insertItem(tr("Thin Out"), this, SLOT(thinOut()));
- midiEdit->insertItem(tr("Erase Event"), this, SLOT(eraseEvent()));
- midiEdit->insertItem(tr("Note Shift"), this, SLOT(noteShift()));
- midiEdit->insertItem(tr("Move Clock"), this, SLOT(moveClock()));
- midiEdit->insertItem(tr("Copy Measure"), this, SLOT(copyMeasure()));
+/* commented out by flo: these are not implemented,
+ but maybe will be in future (state: revision 988)
+ midiEdit->insertItem(tr("Copy Measure"), this, SLOT(copyMeasure()));
midiEdit->insertItem(tr("Erase Measure"), this, SLOT(eraseMeasure()));
midiEdit->insertItem(tr("Delete Measure"), this, SLOT(deleteMeasure()));
midiEdit->insertItem(tr("Create Measure"), this, SLOT(createMeasure()));
midiEdit->insertItem(tr("Mix Track"), this, SLOT(mixTrack()));
-#endif
+*/
midiEdit->addAction(midiTransformerAction);
menuEdit->addAction(editSongInfoAction);
@@ -1622,9 +1386,6 @@ MusE::MusE(int argc, char** argv) : QMainWindow()
MusE::~MusE()
{
- //printf("MusE::~MusE\n");
- //if(transport)
- // delete transport;
}
//---------------------------------------------------------
@@ -1948,37 +1709,6 @@ void MusE::setUntitledProject()
void MusE::setConfigDefaults()
{
readConfiguration(); // used for reading midi files
-#if 0
- if (readConfiguration()) {
- //
- // failed to load config file
- // set buildin defaults
- //
- configTransportVisible = false;
- configBigTimeVisible = false;
-
- for (int channel = 0; channel < 2; ++channel)
- song->addTrack(Track::AUDIO_GROUP);
- AudioTrack* out = (AudioTrack*)song->addTrack(Track::AUDIO_OUTPUT);
- AudioTrack* in = (AudioTrack*)song->addTrack(Track::AUDIO_INPUT);
-
- // set some default routes
- std::list<QString> il = audioDevice->inputPorts();
- int channel = 0;
- for (std::list<QString>::iterator i = il.begin(); i != il.end(); ++i, ++channel) {
- if (channel == 2)
- break;
- audio->msgAddRoute(Route(out,channel), Route(*i,channel));
- }
- channel = 0;
- std::list<QString> ol = audioDevice->outputPorts();
- for (std::list<QString>::iterator i = ol.begin(); i != ol.end(); ++i, ++channel) {
- if (channel == 2)
- break;
- audio->msgAddRoute(Route(*i, channel), Route(in,channel));
- }
- }
-#endif
song->dirty = false;
}
@@ -2971,14 +2701,13 @@ void MusE::cmd(int cmd)
arranger->cmd(Arranger::CMD_INSERT_EMPTYMEAS);
break;
case CMD_DELETE:
- song->startUndo();
- if (song->msgRemoveParts()) {
- song->endUndo(SC_PART_REMOVED);
- break;
- }
- else
- audio->msgRemoveTracks();
- song->endUndo(SC_TRACK_REMOVED);
+ if (!song->msgRemoveParts()) //automatically does undo if neccessary and returns true then
+ {
+ //msgRemoveParts() returned false -> no parts to remove?
+ song->startUndo();
+ audio->msgRemoveTracks(); //TODO FINDME this could still be speeded up!
+ song->endUndo(SC_TRACK_REMOVED);
+ }
break;
case CMD_DELETE_TRACK:
song->startUndo();
@@ -3047,6 +2776,10 @@ void MusE::cmd(int cmd)
song->setFollow(Song::CONTINUOUS);
setFollow();
break;
+
+ case CMD_SHRINK_PART: shrink_parts(); break;
+ case CMD_EXPAND_PART: expand_parts(); break;
+ case CMD_CLEAN_PART: clean_parts(); break;
}
}
@@ -3056,37 +2789,12 @@ void MusE::cmd(int cmd)
void MusE::clipboardChanged()
{
-/*
- //Q3CString subtype("partlist");
- //QString subtype("partlist");
- QMimeSource* ms = QApplication::clipboard()->data(QClipboard::Clipboard);
- if (ms == 0)
- return;
- bool flag = false;
- for (int i = 0; ms->format(i); ++i) {
-// printf("Format <%s\n", ms->format(i));
- if ((strncmp(ms->format(i), "text/midipartlist", 17) == 0)
- || (strncmp(ms->format(i), "text/wavepartlist", 17) == 0)
- // Added by T356. Support mixed .mpt files.
- || (strncmp(ms->format(i), "text/mixedpartlist", 18) == 0)) {
- flag = true;
- break;
- }
- }
-*/
-
bool flag = false;
if(QApplication::clipboard()->mimeData()->hasFormat(QString("text/x-muse-midipartlist")) ||
QApplication::clipboard()->mimeData()->hasFormat(QString("text/x-muse-wavepartlist")) ||
QApplication::clipboard()->mimeData()->hasFormat(QString("text/x-muse-mixedpartlist")))
flag = true;
- //bool flag = false;
- //if(!QApplication::clipboard()->text(QString("x-muse-midipartlist"), QClipboard::Clipboard).isEmpty() ||
- // !QApplication::clipboard()->text(QString("x-muse-wavepartlist"), QClipboard::Clipboard).isEmpty() ||
- // !QApplication::clipboard()->text(QString("x-muse-mixedpartlist"), QClipboard::Clipboard).isEmpty())
- // flag = true;
-
editPasteAction->setEnabled(flag);
editInsertAction->setEnabled(flag);
editPasteCloneAction->setEnabled(flag);
@@ -3107,113 +2815,6 @@ void MusE::selectionChanged()
}
-//---------------------------------------------------------
-// modifyGateTime
-//---------------------------------------------------------
-
-void MusE::modifyGateTime()
- {
- printf("not implemented\n");
- }
-
-//---------------------------------------------------------
-// modifyVelocity
-//---------------------------------------------------------
-
-void MusE::modifyVelocity()
- {
- printf("not implemented\n");
- }
-
-//---------------------------------------------------------
-// crescendo
-//---------------------------------------------------------
-
-void MusE::crescendo()
- {
- printf("not implemented\n");
- }
-
-//---------------------------------------------------------
-// thinOut
-//---------------------------------------------------------
-
-void MusE::thinOut()
- {
- printf("not implemented\n");
- }
-
-//---------------------------------------------------------
-// eraseEvent
-//---------------------------------------------------------
-
-void MusE::eraseEvent()
- {
- printf("not implemented\n");
- }
-
-//---------------------------------------------------------
-// noteShift
-//---------------------------------------------------------
-
-void MusE::noteShift()
- {
- printf("not implemented\n");
- }
-
-//---------------------------------------------------------
-// moveClock
-//---------------------------------------------------------
-
-void MusE::moveClock()
- {
- printf("not implemented\n");
- }
-
-//---------------------------------------------------------
-// copyMeasure
-//---------------------------------------------------------
-
-void MusE::copyMeasure()
- {
- printf("not implemented\n");
- }
-
-//---------------------------------------------------------
-// eraseMeasure
-//---------------------------------------------------------
-
-void MusE::eraseMeasure()
- {
- printf("not implemented\n");
- }
-
-//---------------------------------------------------------
-// deleteMeasure
-//---------------------------------------------------------
-
-void MusE::deleteMeasure()
- {
- printf("not implemented\n");
- }
-
-//---------------------------------------------------------
-// createMeasure
-//---------------------------------------------------------
-
-void MusE::createMeasure()
- {
- printf("not implemented\n");
- }
-
-//---------------------------------------------------------
-// mixTrack
-//---------------------------------------------------------
-
-void MusE::mixTrack()
- {
- printf("not implemented\n");
- }
//---------------------------------------------------------
// configAppearance
@@ -3813,19 +3414,6 @@ void MusE::updateConfiguration()
//menuSettings->setAccel(shortcuts[SHRT_CONFIG_AUDIO_PORTS].key, menu_ids[CMD_CONFIG_AUDIO_PORTS]);
//menu_help->setAccel(menu_ids[CMD_START_WHATSTHIS], shortcuts[SHRT_START_WHATSTHIS].key);
- // Just in case, but no, app kb handler takes care of these.
- /*
- loopAction->setShortcut(shortcuts[].key);
- punchinAction->setShortcut(shortcuts[].key);
- punchoutAction->setShortcut(shortcuts[].key);
- startAction->setShortcut(shortcuts[].key);
- rewindAction->setShortcut(shortcuts[].key);
- forwardAction->setShortcut(shortcuts[].key);
- stopAction->setShortcut(shortcuts[].key);
- playAction->setShortcut(shortcuts[].key);
- recordAction->setShortcut(shortcuts[].key);
- panicAction->setShortcut(shortcuts[].key);
- */
}
//---------------------------------------------------------
@@ -3866,24 +3454,6 @@ void MusE::bigtimeClosed()
viewBigtimeAction->setChecked(false);
}
-//---------------------------------------------------------
-// showMixer
-//---------------------------------------------------------
-
-/*
-void MusE::showMixer(bool on)
- {
- if (on && audioMixer == 0) {
- audioMixer = new AudioMixerApp(this);
- connect(audioMixer, SIGNAL(closed()), SLOT(mixerClosed()));
- audioMixer->resize(config.geometryMixer.size());
- audioMixer->move(config.geometryMixer.topLeft());
- }
- if (audioMixer)
- audioMixer->setVisible(on);
- menuView->setItemChecked(aid1, on);
- }
-*/
//---------------------------------------------------------
// showMixer1
@@ -3920,17 +3490,6 @@ void MusE::showMixer2(bool on)
}
//---------------------------------------------------------
-// toggleMixer
-//---------------------------------------------------------
-
-/*
-void MusE::toggleMixer()
- {
- showMixer(!menuView->isItemChecked(aid1));
- }
-*/
-
-//---------------------------------------------------------
// toggleMixer1
//---------------------------------------------------------
@@ -3949,17 +3508,6 @@ void MusE::toggleMixer2(bool checked)
}
//---------------------------------------------------------
-// mixerClosed
-//---------------------------------------------------------
-
-/*
-void MusE::mixerClosed()
- {
- menuView->setItemChecked(aid1, false);
- }
-*/
-
-//---------------------------------------------------------
// mixer1Closed
//---------------------------------------------------------
@@ -3978,7 +3526,6 @@ void MusE::mixer2Closed()
}
-//QWidget* MusE::mixerWindow() { return audioMixer; }
QWidget* MusE::mixer1Window() { return mixer1; }
QWidget* MusE::mixer2Window() { return mixer2; }
diff --git a/muse2/muse/app.h b/muse2/muse/app.h
index 256154e2..3fd93fc8 100644
--- a/muse2/muse/app.h
+++ b/muse2/muse/app.h
@@ -11,7 +11,6 @@
#include "config.h"
#include "cobject.h"
-//#include "tools.h"
#include <QFileInfo>
@@ -80,7 +79,7 @@ class MusE : public QMainWindow
CMD_SELECT_ALL, CMD_SELECT_NONE, CMD_SELECT_INVERT,
CMD_SELECT_ILOOP, CMD_SELECT_OLOOP, CMD_SELECT_PARTS,
CMD_FOLLOW_NO, CMD_FOLLOW_JUMP, CMD_FOLLOW_CONTINUOUS ,
- CMD_DELETE_TRACK
+ CMD_DELETE_TRACK, CMD_EXPAND_PART, CMD_SHRINK_PART, CMD_CLEAN_PART
};
//File menu items:
@@ -97,8 +96,6 @@ class MusE : public QMainWindow
CMD_AUDIO_BOUNCE_TO_FILE, CMD_AUDIO_BOUNCE_TO_TRACK, CMD_AUDIO_RESTART,
CMD_LAST };
- //int menu_ids[CMD_LAST];
-
// File menu actions
QAction *fileSaveAction, *fileOpenAction, *fileNewAction, *testAction;
QAction *fileSaveAsAction, *fileImportMidiAction, *fileExportMidiAction;
@@ -113,6 +110,7 @@ class MusE : public QMainWindow
QAction *masterGraphicAction, *masterListAction;
QAction *midiTransformerAction;
QAction *editSongInfoAction;
+ QAction *editCleanPartsAction, *editShrinkPartsAction, *editExpandPartsAction;
public:
QAction *startScoreEditAction, *startPianoEditAction, *startDrumEditAction, *startListEditAction, *startWaveEditAction;
QMenu *scoreSubmenu, *scoreOneStaffPerTrackSubsubmenu, *scoreAllInOneSubsubmenu;
@@ -227,7 +225,6 @@ class MusE : public QMainWindow
void configChanged();
private slots:
- //void runPythonScript();
void loadProject();
bool save();
void configGlobalSettings();
@@ -247,7 +244,6 @@ class MusE : public QMainWindow
void toggleTransport(bool);
void toggleMarker(bool);
void toggleBigTime(bool);
- //void toggleMixer();
void toggleMixer1(bool);
void toggleMixer2(bool);
@@ -289,18 +285,12 @@ class MusE : public QMainWindow
void cmd(int);
void clipboardChanged();
void selectionChanged();
- void modifyGateTime();
- void modifyVelocity();
- void crescendo();
- void thinOut();
- void eraseEvent();
- void noteShift();
- void moveClock();
- void copyMeasure();
- void eraseMeasure();
+/* void copyMeasure(); // commented out by flo: these are not implemented,
+ void eraseMeasure(); // but maybe will be in future (state: revision 988)
void deleteMeasure();
void createMeasure();
void mixTrack();
+*/
void startMidiInputPlugin(int);
void hideMitPluginTranspose();
void hideMidiInputTransform();
@@ -322,7 +312,6 @@ class MusE : public QMainWindow
void takeAutomationSnapshot();
void clearAutomation();
void bigtimeClosed();
- //void mixerClosed();
void mixer1Closed();
void mixer2Closed();
void markerClosed();
@@ -344,7 +333,6 @@ class MusE : public QMainWindow
bool seqRestart();
void loadTemplate();
void showBigtime(bool);
- //void showMixer(bool);
void showMixer1(bool);
void showMixer2(bool);
void showMarker(bool);
@@ -368,7 +356,6 @@ class MusE : public QMainWindow
void setHeartBeat();
void importController(int, MidiPort*, int);
QString projectName() { return project.fileName(); }
- //QWidget* mixerWindow();
QWidget* mixer1Window();
QWidget* mixer2Window();
QWidget* transportWindow();
diff --git a/muse2/muse/arranger/pcanvas.cpp b/muse2/muse/arranger/pcanvas.cpp
index 8c7c89ad..f7a2abde 100644
--- a/muse2/muse/arranger/pcanvas.cpp
+++ b/muse2/muse/arranger/pcanvas.cpp
@@ -21,7 +21,6 @@
#include <QPainter>
#include <QUrl>
#include <QPoint>
-//#include <QLinearGradient>
#include "fastlog.h"
#include "widgets/tools.h"
@@ -44,55 +43,6 @@
#include "midictrl.h"
#include "utils.h"
-// Moved into global config by Tim.
-/*
-const char* partColorNames[] = {
- "Default",
- "Refrain",
- "Bridge",
- "Intro",
- "Coda",
- "Chorus",
- "Solo",
- "Brass",
- "Percussion",
- "Drums",
- "Guitar",
- "Bass",
- "Flute",
- "Strings",
- "Keyboard",
- "Piano",
- "Saxophon",
- };
-*/
-
-/*
-//---------------------------------------------------------
-// ColorListItem
-//---------------------------------------------------------
-
-class ColorListItem { //: public QCustomMenuItem { ddskrjo
- QColor color;
- int h;
- int fontheight;
- QString label;
- virtual QSize sizeHint() { return QSize(80, h); }
- virtual void paint(QPainter* p, const QColorGroup&, bool act, bool enabled, int x, int y, int w, int h)
- {
- p->fillRect(x+5, y+2, h-4, h-4, QBrush(color));
- p->drawText(x+5 + h - 4 + 3, y+(fontheight * 3) / 4, label);
- }
-
- public:
- ColorListItem(const QColor& c, int _h, int _fh, const char* txt)
- : color(c), h(_h), fontheight(_fh), label(txt) {
- }
- QString text() const { return QString("PartColor"); }
- };
-*/
-// ORCAN : colorRect does the same job as the above class.
-// Shall we get rid of the class?
//---------------------------------------------------------
// colorRect
@@ -119,7 +69,6 @@ NPart::NPart(Part* e) : CItem(Event(), e)
{
int th = track()->height();
int y = track()->y();
- //printf("NPart::NPart track name:%s, y:%d h:%d\n", track()->name().toLatin1().constData(), y, th);
///setPos(QPoint(e->tick(), y + 1));
setPos(QPoint(e->tick(), y));
@@ -214,9 +163,7 @@ void PartCanvas::returnPressed()
newPart->setName(lineEditor->text());
// Indicate do undo, and do port controller values but not clone parts.
- //audio->msgChangePart(oldPart, newPart);
audio->msgChangePart(oldPart, newPart, true, true, false);
- //printf("PartCanvas::returnPressed after msgChangePart oldPart refs:%d Arefs:%d newPart refs:%d Arefs:%d\n", oldPart->events()->refCount(), oldPart->events()->arefCount(), newPart->events()->refCount(), newPart->events()->arefCount());
editMode = false;
}
@@ -299,21 +246,12 @@ void PartCanvas::viewMouseDoubleClickEvent(QMouseEvent* event)
}
//---------------------------------------------------------
-// startUndo
-//---------------------------------------------------------
-
-void PartCanvas::startUndo(DragType)
- {
- song->startUndo();
- }
-
-//---------------------------------------------------------
-// endUndo
+// update
//---------------------------------------------------------
-void PartCanvas::endUndo(DragType t, int flags)
+void PartCanvas::updateSong(DragType t, int flags)
{
- song->endUndo(flags | ((t == MOVE_COPY || t == MOVE_CLONE)
+ song->update(flags | ((t == MOVE_COPY || t == MOVE_CLONE)
? SC_PART_INSERTED : SC_PART_MODIFIED));
}
@@ -321,103 +259,10 @@ void PartCanvas::endUndo(DragType t, int flags)
// moveCanvasItems
//---------------------------------------------------------
-void PartCanvas::moveCanvasItems(CItemList& items, int dp, int dx, DragType dtype, int*)
+void PartCanvas::moveCanvasItems(CItemList& items, int dp, int dx, DragType dtype)
{
- /*
- if(editor->parts()->empty())
- return;
-
- //struct p2c
- //{
- // Part* newp;
- // int xdiff;
- //}
+ Undo operations;
- //std::set<Part*> parts2change;
- //typedef std::set<Part*>::iterator iptc;
- std::map<Part*, Part*> parts2change;
- typedef std::map<Part*, Part*>::iterator iP2C;
-
- int modified = 0;
- for(iPart ip = editor->parts()->begin(); ip != editor->parts()->end(); ++ip)
- {
- Part* part = ip->second;
- if(!part)
- continue;
-
- int npartoffset = 0;
- for(iCItem ici = items.begin(); ici != items.end(); ++ici)
- {
- CItem* ci = ici->second;
- //Part* pt = ci->part();
- //if(!pt)
- if(ci->part() != part)
- continue;
-
- int x = ci->pos().x() + dx;
- int y = pitch2y(y2pitch(ci->pos().y()) + dp);
- QPoint newpos = raster(QPoint(x, y));
-
- // Test moving the item...
-
- //int offset = testMoveItem(ci, newpos, dragtype);
- NEvent* nevent = (NEvent*) ci;
- Event event = nevent->event();
- //int npitch = y2pitch(newpos.y());
- x = newpos.x();
- if (x < 0)
- x = 0;
-
- int ntick = editor->rasterVal(x) - part->tick();
- if (ntick < 0)
- ntick = 0;
- int diff = ntick + event.lenTick() - part->lenTick();
-
- // If moving the item would require a new part size...
- if(diff > npartoffset)
- npartoffset = diff;
- }
-
- if(npartoffset > 0)
- {
- // Create new part...
- // if there are several events that are moved outside the part, it will be recreated for each
- // so the part _in_ the event will not be valid, ask the authority.
- Part* newPart = part->clone();
- //Part* newPart = Canvas::part()->clone();
-
- newPart->setLenTick(newPart->lenTick() + npartoffset);
- audio->msgChangePart(part, newPart,false);
-
- modified = SC_PART_MODIFIED;
-
- // BUG FIX: #1650953
- // Added by T356.
- // Fixes posted "select and drag past end of part - crashing" bug
- for(iPart ip = editor->parts()->begin(); ip != editor->parts()->end(); ++ip)
- {
- if(ip->second == part)
- {
- editor->parts()->erase(ip);
- break;
- }
- }
-
- editor->parts()->add(newPart);
- if(parts2change.find(part) == parts2change.end())
- parts2change.insert(std::pair<Part*, Part*> (part, newPart));
-
-// part = newPart; // reassign
-// item->setPart(part);
-// item->setEvent(newEvent);
-// curPart = part;
-// curPartId = curPart->sn();
-
- }
- }
-*/
-
-// int modified = 0;
for(iCItem ici = items.begin(); ici != items.end(); ++ici)
{
CItem* ci = ici->second;
@@ -435,18 +280,21 @@ void PartCanvas::moveCanvasItems(CItemList& items, int dp, int dx, DragType dtyp
QPoint newpos = raster(QPoint(nx, ny));
selectItem(ci, true);
- if(moveItem(ci, newpos, dtype))
- ci->move(newpos);
+ UndoOp operation=moveItem(ci, newpos, dtype);
+ if (operation.type != UndoOp::DoNothing)
+ {
+ ci->move(newpos);
+ operations.push_back(operation);
+ }
+
if(moving.size() == 1) {
itemReleased(curItem, newpos);
}
if(dtype == MOVE_COPY || dtype == MOVE_CLONE)
selectItem(ci, false);
- }
-
+ }
- //if(pflags)
- // *pflags = modified;
+ song->applyOperationGroup(operations);
}
//---------------------------------------------------------
@@ -455,9 +303,9 @@ void PartCanvas::moveCanvasItems(CItemList& items, int dp, int dx, DragType dtyp
//---------------------------------------------------------
// Changed by T356.
-//bool PartCanvas::moveItem(CItem* item, const QPoint& newpos, DragType t, int*)
-bool PartCanvas::moveItem(CItem* item, const QPoint& newpos, DragType t)
+UndoOp PartCanvas::moveItem(CItem* item, const QPoint& newpos, DragType t)
{
+ UndoOp result;
NPart* npart = (NPart*) item;
Part* spart = npart->part();
Track* track = npart->track();
@@ -465,7 +313,7 @@ bool PartCanvas::moveItem(CItem* item, const QPoint& newpos, DragType t)
unsigned ntrack = y2pitch(item->mp().y());
Track::TrackType type = track->type();
if (tracks->index(track) == ntrack && (dtick == spart->tick())) {
- return false;
+ return UndoOp(UndoOp::DoNothing);
}
if (ntrack >= tracks->size()) {
ntrack = tracks->size();
@@ -483,12 +331,10 @@ bool PartCanvas::moveItem(CItem* item, const QPoint& newpos, DragType t)
if (dtrack->type() != type) {
QMessageBox::critical(this, QString("MusE"),
tr("Cannot copy/move/clone to different Track-Type"));
- return false;
+ return UndoOp(UndoOp::DoNothing);
}
Part* dpart;
- //bool clone = (t == MOVE_CLONE) || (spart->events()->arefCount() > 1);
- //bool clone = (t == MOVE_CLONE);
bool clone = (t == MOVE_CLONE || (t == MOVE_COPY && spart->events()->arefCount() > 1));
if(t == MOVE_MOVE)
@@ -506,12 +352,12 @@ bool PartCanvas::moveItem(CItem* item, const QPoint& newpos, DragType t)
dpart->setTick(dtick);
- //printf("PartCanvas::moveItem before add/changePart clone:%d spart:%p events:%p refs:%d Arefs:%d sn:%d dpart:%p events:%p refs:%d Arefs:%d sn:%d\n", clone, spart, spart->events(), spart->events()->refCount(), spart->events()->arefCount(), spart->sn(), dpart, dpart->events(), dpart->events()->refCount(), dpart->events()->arefCount(), dpart->sn());
-
if(t == MOVE_MOVE)
item->setPart(dpart);
- //if (!clone) {
if (t == MOVE_COPY && !clone) {
+ dpart->events()->incARef(-1); // the later song->applyOperationGroup() will increment it
+ // so we must decrement it first :/
+
//
// Copy Events
//
@@ -523,36 +369,27 @@ bool PartCanvas::moveItem(CItem* item, const QPoint& newpos, DragType t)
de->add(ev);
}
}
+
+
if (t == MOVE_COPY || t == MOVE_CLONE) {
- // These will not increment ref count, and will not chain clones...
- if (dtrack->type() == Track::WAVE)
- audio->msgAddPart((WavePart*)dpart,false);
- else
- audio->msgAddPart(dpart,false);
+ // These will not increment ref count, and will not chain clones...
+ // TODO: is this still correct (by flo93)?
+ result=UndoOp(UndoOp::AddPart,dpart);
}
else if (t == MOVE_MOVE) {
dpart->setSelected(spart->selected());
// These will increment ref count if not a clone, and will chain clones...
-
- if (dtrack->type() == Track::WAVE) {
- // Indicate no undo, and do not do port controller values and clone parts.
- //audio->msgChangePart((WavePart*)spart, (WavePart*)dpart,false);
- audio->msgChangePart((WavePart*)spart, (WavePart*)dpart, false, false, false);
- }
- else {
- // Indicate no undo, and do port controller values but not clone parts.
- //audio->msgChangePart(spart, dpart, false);
- audio->msgChangePart(spart, dpart, false, true, false);
- }
+ // TODO: is this still correct (by flo93)?
+ result=UndoOp(UndoOp::ModifyPart,spart, dpart, true, false);
+
spart->setSelected(false);
-
}
- //printf("PartCanvas::moveItem after add/changePart spart:%p events:%p refs:%d Arefs:%d dpart:%p events:%p refs:%d Arefs:%d\n", spart, spart->events(), spart->events()->refCount(), spart->events()->arefCount(), dpart, dpart->events(), dpart->events()->refCount(), dpart->events()->arefCount());
+ // else // will never happen -> result will always be defined
if (song->len() < (dpart->lenTick() + dpart->tick()))
song->setLen(dpart->lenTick() + dpart->tick());
- //endUndo(t);
- return true;
+
+ return result;
}
//---------------------------------------------------------
@@ -688,7 +525,7 @@ void PartCanvas::newItem(CItem* i, bool noSnap)
len = AL::sigmap.rasterStep(p->tick(), *_raster);
p->setLenTick(len);
p->setSelected(true);
- audio->msgAddPart(p);
+ audio->msgAddPart(p, true); //indicate undo
}
//---------------------------------------------------------
@@ -698,7 +535,7 @@ void PartCanvas::newItem(CItem* i, bool noSnap)
bool PartCanvas::deleteItem(CItem* i)
{
Part* p = ((NPart*)(i))->part();
- audio->msgRemovePart(p); //Invokes songChanged which calls partsChanged which makes it difficult to delete them there
+ audio->msgRemovePart(p, true); //Invokes songChanged which calls partsChanged which makes it difficult to delete them there
return true;
}
@@ -764,11 +601,7 @@ QMenu* PartCanvas::genItemPopup(CItem* item)
QMenu* colorPopup = partPopup->addMenu(tr("color"));
// part color selection
- //const QFontMetrics& fm = colorPopup->fontMetrics();
- //int h = fm.lineSpacing();
-
for (int i = 0; i < NUM_PARTCOLORS; ++i) {
- //ColorListItem* item = new ColorListItem(config.partColors[i], h, fontMetrics().height(), partColorNames[i]); //ddskrjo
QAction *act_color = colorPopup->addAction(colorRect(config.partColors[i], 80, 80), config.partColorNames[i]);
act_color->setData(20+i);
}
@@ -868,28 +701,13 @@ void PartCanvas::itemPopup(CItem* item, int n, const QPoint& pt)
break;
case 14: // wave edit
- {
- // Changed to allow multiple selected parts to be shown. By T356
- // Slightly inefficient to add (above), then clear here.
- // Should really only add npart->part() to pl only if NOT here.
- // Removed. Added wave editor menu item instead.
- //pl->clear();
- //PartList* ptl = npart->track()->parts();
- //for(ciPart pi = ptl->begin(); pi != ptl->end(); pi++)
- //{
- // if(pi->second->selected())
- // pl->add(pi->second);
- //}
emit startEditor(pl, 4);
- }
return;
case 15: // declone
{
Part* spart = npart->part();
Track* track = npart->track();
Part* dpart = track->newPart(spart, false);
- //printf("PartCanvas::itemPopup: #1 spart %s %p next:%s %p prev:%s %p\n", spart->name().toLatin1().constData(), spart, spart->nextClone()->name().toLatin1().constData(), spart->nextClone(), spart->prevClone()->name().toLatin1().constData(), spart->prevClone());
- //printf("PartCanvas::itemPopup: #1 dpart %s %p next:%s %p prev:%s %p\n", dpart->name().toLatin1().constData(), dpart, dpart->nextClone()->name().toLatin1().constData(), dpart->nextClone(), dpart->prevClone()->name().toLatin1().constData(), dpart->prevClone());
EventList* se = spart->events();
EventList* de = dpart->events();
@@ -898,27 +716,20 @@ void PartCanvas::itemPopup(CItem* item, int n, const QPoint& pt)
Event ev = oldEvent.clone();
de->add(ev);
}
- song->startUndo();
- // Indicate no undo, and do port controller values but not clone parts.
- //audio->msgChangePart(spart, dpart, false);
- audio->msgChangePart(spart, dpart, false, true, false);
- //printf("PartCanvas::itemPopup: #2 spart %s %p next:%s %p prev:%s %p\n", spart->name().toLatin1().constData(), spart, spart->nextClone()->name().toLatin1().constData(), spart->nextClone(), spart->prevClone()->name().toLatin1().constData(), spart->prevClone());
- //printf("PartCanvas::itemPopup: #2 dpart %s %p next:%s %p prev:%s %p\n", dpart->name().toLatin1().constData(), dpart, dpart->nextClone()->name().toLatin1().constData(), dpart->nextClone(), dpart->prevClone()->name().toLatin1().constData(), dpart->prevClone());
-
- song->endUndo(SC_PART_MODIFIED);
+ // Indicate undo, and do port controller values but not clone parts.
+ // changed by flo93: removed start and endUndo, instead changed first bool to true
+ audio->msgChangePart(spart, dpart, true, true, false);
break; // Has to be break here, right?
}
case 16: // Export to file
{
const Part* part = item->part();
bool popenFlag = false;
- //QString fn = getSaveFileName(QString(""), part_file_pattern, this, tr("MusE: save part"));
QString fn = getSaveFileName(QString(""), part_file_save_pattern, this, tr("MusE: save part"));
if (!fn.isEmpty()) {
FILE* fp = fileOpen(this, fn, ".mpt", "w", popenFlag, false, false);
if (fp) {
Xml tmpXml = Xml(fp);
- //part->write(0, tmpXml);
// Write the part. Indicate that it's a copy operation - to add special markers,
// and force full wave paths.
part->write(0, tmpXml, true, true);
@@ -939,7 +750,6 @@ void PartCanvas::itemPopup(CItem* item, int n, const QPoint& pt)
SndFileR f = event.sndFile();
if (f.isNull())
continue;
- //str.append("\n" + f.path());
str.append(QString("\n@") + QString().setNum(event.tick()) + QString(" len:") +
QString().setNum(event.lenTick()) + QString(" ") + f.path());
}
@@ -958,14 +768,11 @@ void PartCanvas::itemPopup(CItem* item, int n, const QPoint& pt)
{
for(int i = 0; i < j; ++i)
{
- //printf("PartCanvas::itemPopup i:%d %s %p events %p refs:%d arefs:%d\n", i, p->name().toLatin1().constData(), p, part->cevents(), part->cevents()->refCount(), j);
-
p->setSelected(true);
p = p->nextClone();
if(p == part)
break;
}
- //song->update();
song->update(SC_SELECTION);
}
@@ -1124,14 +931,10 @@ void PartCanvas::keyPress(QKeyEvent* event)
key += Qt::CTRL;
if (key == shortcuts[SHRT_DELETE].key) {
- if (getCurrentDrag()) {
- //printf("dragging!!\n");
+ if (getCurrentDrag())
return;
- }
- song->startUndo();
song->msgRemoveParts();
- song->endUndo(SC_PART_REMOVED);
return;
}
else if (key == shortcuts[SHRT_POS_DEC].key) {
@@ -1493,13 +1296,6 @@ void PartCanvas::drawItem(QPainter& p, const CItem* item, const QRect& rect)
QRect r = item->bbox();
- //printf("PartCanvas::drawItem %s evRefs:%d pTick:%d pLen:%d\nbb.x:%d bb.y:%d bb.w:%d bb.h:%d\n"
- // "rect.x:%d rect.y:%d rect.w:%d rect.h:%d\nr.x:%d r.y:%d r.w:%d r.h:%d\n",
- // part->name().toLatin1().constData(), part->events()->arefCount(), pTick, part->lenTick(),
- // bb.x(), bb.y(), bb.width(), bb.height(),
- // rect.x(), rect.y(), rect.width(), rect.height(),
- // r.x(), r.y(), r.width(), r.height());
-
int i = part->colorIndex();
p.setPen(Qt::black);
if (part->mute()) {
@@ -1513,7 +1309,6 @@ void PartCanvas::drawItem(QPainter& p, const CItem* item, const QRect& rect)
// NOTE: For one-pixel border use first line For two-pixel border use second.
p.drawRect(QRect(r.x(), r.y()-1, r.width(), r.height()));
- //p.drawRect(r);
return;
}
@@ -1528,11 +1323,7 @@ void PartCanvas::drawItem(QPainter& p, const CItem* item, const QRect& rect)
// NOTE: For one-pixel border use first line. For two-pixel border use second.
p.drawRect(QRect(r.x(), r.y()-1, r.width(), r.height()));
- //p.drawRect(r);
-
}
- //else if (part->mute())
- // return;
else if (part->selected()) {
bool clone = part->events()->arefCount() > 1;
@@ -1641,8 +1432,6 @@ void PartCanvas::drawItem(QPainter& p, const CItem* item, const QRect& rect)
void PartCanvas::drawMoving(QPainter& p, const CItem* item, const QRect&)
{
- //if(!item->isMoving())
- // return;
p.setPen( Qt::black);
//p.setBrush( Qt::NoBrush);
@@ -1669,7 +1458,6 @@ void PartCanvas::drawMoving(QPainter& p, const CItem* item, const QRect&)
void PartCanvas::drawMidiPart(QPainter& p, const QRect&, EventList* events, MidiTrack *mt, MidiPart *pt, const QRect& r, int pTick, int from, int to)
{
- //printf("x=%d y=%d h=%d w=%d\n",r.x(),r.y(),r.height(),r.width());
int color_brightness;
if(pt)
@@ -1894,9 +1682,6 @@ void PartCanvas::drawMidiPart(QPainter& p, const QRect&, EventList* events, Midi
void PartCanvas::drawWavePart(QPainter& p,
const QRect& bb, WavePart* wp, const QRect& _pr)
{
- //printf("PartCanvas::drawWavePart bb.x:%d bb.y:%d bb.w:%d bb.h:%d pr.x:%d pr.y:%d pr.w:%d pr.h:%d\n",
- // bb.x(), bb.y(), bb.width(), bb.height(), _pr.x(), _pr.y(), _pr.width(), _pr.height());
-
QRect rr = p.worldMatrix().mapRect(bb);
QRect pr = p.worldMatrix().mapRect(_pr);
@@ -2020,26 +1805,23 @@ void PartCanvas::cmd(int cmd)
}
switch (cmd) {
case CMD_CUT_PART:
+ {
copy(&pl);
- song->startUndo();
- bool loop;
- do
- {
- loop = false;
- for (iCItem i = items.begin(); i != items.end(); ++i) {
- if (!i->second->isSelected())
- continue;
- NPart* p = (NPart*)(i->second);
- Part* part = p->part();
- audio->msgRemovePart(part);
-
- loop = true;
- break;
- }
- } while (loop);
- song->endUndo(SC_PART_REMOVED);
+ Undo operations;
+
+ for (iCItem i = items.begin(); i != items.end(); ++i) {
+ if (i->second->isSelected()) {
+ NPart* p = (NPart*)(i->second);
+ Part* part = p->part();
+ operations.push_back(UndoOp(UndoOp::DeletePart, part));
+ }
+ }
+
+ song->applyOperationGroup(operations);
+
break;
+ }
case CMD_COPY_PART:
copy(&pl);
break;
@@ -2059,11 +1841,10 @@ void PartCanvas::cmd(int cmd)
paste(false, false, true);
break;
case CMD_INSERT_EMPTYMEAS:
- song->startUndo();
int startPos=song->vcpos();
int oneMeas=AL::sigmap.ticksMeasure(startPos);
- movePartsTotheRight(startPos,oneMeas);
- song->endUndo(SC_PART_INSERTED);
+ Undo temp=movePartsTotheRight(startPos,oneMeas);
+ song->applyOperationGroup(temp);
break;
}
}
@@ -2075,11 +1856,8 @@ void PartCanvas::cmd(int cmd)
void PartCanvas::copy(PartList* pl)
{
- //printf("void PartCanvas::copy(PartList* pl)\n");
if (pl->empty())
return;
- // Changed by T356. Support mixed .mpt files.
- //bool isWave = pl->begin()->second->track()->type() == Track::WAVE;
bool wave = false;
bool midi = false;
for(ciPart p = pl->begin(); p != pl->end(); ++p)
@@ -2109,13 +1887,11 @@ void PartCanvas::copy(PartList* pl)
// Clear the copy clone list.
cloneList.clear();
- //copyCloneList.clear();
int level = 0;
int tick = 0;
for (ciPart p = pl->begin(); p != pl->end(); ++p) {
// Indicate this is a copy operation. Also force full wave paths.
- //p->second->write(level, xml);
p->second->write(level, xml, true, true);
int endTick = p->second->endTick();
@@ -2165,21 +1941,20 @@ void PartCanvas::copy(PartList* pl)
// pasteAt
//---------------------------------------------------------
-int PartCanvas::pasteAt(const QString& pt, Track* track, unsigned int pos, bool clone, bool toTrack)
+Undo PartCanvas::pasteAt(const QString& pt, Track* track, unsigned int pos, bool clone, bool toTrack, int* finalPosPtr)
{
- //printf("int PartCanvas::pasteAt(const QString& pt, Track* track, int pos)\n");
+ Undo operations;
+
QByteArray ba = pt.toLatin1();
const char* ptxt = ba.constData();
Xml xml(ptxt);
bool firstPart=true;
int posOffset=0;
- //int finalPos=0;
unsigned int finalPos = pos;
int notDone = 0;
int done = 0;
bool end = false;
- //song->startUndo();
for (;;) {
Xml::Token token = xml.parse();
const QString& tag = xml.s1();
@@ -2189,29 +1964,11 @@ int PartCanvas::pasteAt(const QString& pt, Track* track, unsigned int pos, bool
end = true;
break;
case Xml::TagStart:
- if (tag == "part") {
- /*
- Part* p = 0;
- if(clone)
- {
- if(!(p = readClone(xml, track, toTrack)))
- break;
- }
- else
- {
- if (track->type() == Track::MIDI || track->type() == Track::DRUM)
- p = new MidiPart((MidiTrack*)track);
- else if (track->type() == Track::WAVE)
- p = new WavePart((WaveTrack*)track);
- else
- break;
- p->read(xml, 0, toTrack);
- }
- */
-
+ if (tag == "part") {
// Read the part.
Part* p = 0;
p = readXmlPart(xml, track, clone, toTrack);
+
// If it could not be created...
if(!p)
{
@@ -2219,6 +1976,9 @@ int PartCanvas::pasteAt(const QString& pt, Track* track, unsigned int pos, bool
++notDone;
break;
}
+
+ p->events()->incARef(-1); // the later song->applyOperationGroup() will increment it
+ // so we must decrement it first :/
// Increment the number of parts done.
++done;
@@ -2231,8 +1991,7 @@ int PartCanvas::pasteAt(const QString& pt, Track* track, unsigned int pos, bool
if (p->tick()+p->lenTick()>finalPos) {
finalPos=p->tick()+p->lenTick();
}
- //pos += p->lenTick();
- audio->msgAddPart(p,false);
+ operations.push_back(UndoOp(UndoOp::AddPart,p));
}
else
xml.unknown("PartCanvas::pasteAt");
@@ -2247,8 +2006,6 @@ int PartCanvas::pasteAt(const QString& pt, Track* track, unsigned int pos, bool
break;
}
- //song->endUndo(SC_PART_INSERTED);
- //return pos;
if(notDone)
{
@@ -2259,406 +2016,16 @@ int PartCanvas::pasteAt(const QString& pt, Track* track, unsigned int pos, bool
tr(" could not be pasted.\nLikely the selected track is the wrong type."));
}
- return finalPos;
+ if (finalPosPtr) *finalPosPtr=finalPos;
+ return operations;
}
-/*
-//---------------------------------------------------------
-// PartCanvas::readPart
-//---------------------------------------------------------
-
-Part* PartCanvas::readPart(Xml& xml, Track* track, bool doClone, bool toTrack)
- {
- int id = -1;
- Part* npart = 0;
- uuid_t uuid;
- uuid_clear(uuid);
- bool uuidvalid = false;
- bool clone = true;
-
- for (;;) {
- Xml::Token token = xml.parse();
- const QString& tag = xml.s1();
- switch (token) {
- case Xml::Error:
- case Xml::End:
- return npart;
- case Xml::TagStart:
- // If the part has not been created yet...
- if(!npart)
- {
- // Attribute section did not create a clone from any matching part. Create a non-clone part now.
- if(!track)
- {
- xml.skip("part");
- return 0;
- }
- if (track->type() == Track::MIDI || track->type() == Track::DRUM)
- npart = new MidiPart((MidiTrack*)track);
- else if (track->type() == Track::WAVE)
- npart = new WavePart((WaveTrack*)track);
- else
- {
- xml.skip("part");
- return 0;
- }
-
- // Signify a new non-clone part was created.
- // Even if the original part was itself a clone, clear this because the
- // attribute section did not create a clone from any matching part.
- clone = false;
-
- // If an id or uuid was found, add the part to the clone list
- // so that subsequent parts can look it up and clone from it...
- if(id != -1)
- {
- ClonePart ncp(npart, id);
- cloneList.push_back(ncp);
- }
- else
- if(uuidvalid)
- {
- ClonePart ncp(npart);
- // New ClonePart creates its own uuid, but we need to replace it.
- uuid_copy(ncp.uuid, uuid);
- cloneList.push_back(ncp);
- }
- }
-
- if (tag == "name")
- npart->setName(xml.parse1());
- else if (tag == "poslen") {
- ((PosLen*)npart)->read(xml, "poslen");
- }
- else if (tag == "pos") {
- Pos pos;
- pos.read(xml, "pos"); // obsolete
- npart->setTick(pos.tick());
- }
- else if (tag == "len") {
- Pos len;
- len.read(xml, "len"); // obsolete
- npart->setLenTick(len.tick());
- }
- else if (tag == "selected")
- npart->setSelected(xml.parseInt());
- else if (tag == "color")
- npart->setColorIndex(xml.parseInt());
- else if (tag == "mute")
- npart->setMute(xml.parseInt());
- else if (tag == "event")
- {
- // If a new non-clone part was created, accept the events...
- if(!clone)
- {
- EventType type = Wave;
- if(track->isMidiTrack())
- type = Note;
- Event e(type);
- e.read(xml);
- // stored tickpos for event has absolute value. However internally
- // tickpos is relative to start of part, we substract tick().
- // TODO: better handling for wave event
- e.move( -npart->tick() );
- int tick = e.tick();
-
- // Do not discard events belonging to clone parts,
- // at least not yet. A later clone might have a longer,
- // fully accommodating part length!
- //if ((tick < 0) || (tick >= (int) lenTick())) {
- //if ((tick < 0) || ( id == -1 && !clone && (tick >= (int)lenTick()) ))
- // No way to tell at the moment whether there will be clones referencing this...
- // No choice but to accept all events past 0.
- if(tick < 0)
- {
- //printf("readClone: warning: event not in part: %d - %d -%d, discarded\n",
- printf("readClone: warning: event at tick:%d not in part:%s, discarded\n",
- tick, npart->name().toLatin1().constData());
- }
- else
- {
- npart->events()->add(e);
- }
- }
- else
- // ...Otherwise a clone was created, so we don't need the events.
- xml.skip(tag);
- }
- else
- xml.unknown("PartCanvas::readClone");
- break;
- case Xml::Attribut:
- if (tag == "cloneId")
- {
- id = xml.s2().toInt();
- if(id != -1)
- {
- for(iClone i = cloneList.begin(); i != cloneList.end(); ++i)
- {
- // Is a matching part found in the clone list?
- if(i->id == id)
- {
- // If it's a regular paste (not paste clone), and the original part is
- // not a clone, defer so that a new copy is created in TagStart above.
- if(!doClone && i->cp->cevents()->arefCount() <= 1)
- break;
-
- // This makes a clone, chains the part, and increases ref counts.
- npart = track->newPart((Part*)i->cp, true);
- break;
- }
- }
- }
- }
- else if (tag == "uuid")
- {
- uuid_parse(xml.s2().toLatin1().constData(), uuid);
- if(!uuid_is_null(uuid))
- {
- uuidvalid = true;
- for(iClone i = cloneList.begin(); i != cloneList.end(); ++i)
- {
- // Is a matching part found in the clone list?
- if(uuid_compare(uuid, i->uuid) == 0)
- {
- Track* cpt = i->cp->track();
- // If we want to paste to the given track...
- if(toTrack)
- {
- // If the given track type is not the same as the part's
- // original track type, we can't continue. Just return.
- if(!track || cpt->type() != track->type())
- {
- xml.skip("part");
- return 0;
- }
- }
- else
- // ...else we want to paste to the part's original track.
- {
- // Make sure the track exists (has not been deleted).
- if((cpt->isMidiTrack() && song->midis()->find(cpt) != song->midis()->end()) ||
- (cpt->type() == Track::WAVE && song->waves()->find(cpt) != song->waves()->end()))
- track = cpt;
- else
- // Track was not found. Try pasting to the given track, as above...
- {
- if(!track || cpt->type() != track->type())
- {
- // No luck. Just return.
- xml.skip("part");
- return 0;
- }
- }
- }
-
- // If it's a regular paste (not paste clone), and the original part is
- // not a clone, defer so that a new copy is created in TagStart above.
- if(!doClone && i->cp->cevents()->arefCount() <= 1)
- break;
-
- // This makes a clone, chains the part, and increases ref counts.
- npart = track->newPart((Part*)i->cp, true);
- break;
- }
- }
- }
- }
- //else if(tag == "isclone") // Ignore
- // clone = xml.s2().toInt();
- break;
- case Xml::TagEnd:
- if (tag == "part")
- return npart;
- default:
- break;
- }
- }
- return npart;
-}
-*/
-
-/*
-//---------------------------------------------------------
-// PartCanvas::readClone
-//---------------------------------------------------------
-
-Part* PartCanvas::readClone(Xml& xml, Track* track, bool toTrack)
- {
- int id = -1;
- Part* npart = 0;
- uuid_t uuid;
- uuid_clear(uuid);
- bool uuidvalid = false;
- bool clone = true;
-
- for (;;) {
- Xml::Token token = xml.parse();
- const QString& tag = xml.s1();
- switch (token) {
- case Xml::Error:
- case Xml::End:
- return npart;
- case Xml::TagStart:
- // If the part has not been created yet...
- if(!npart)
- {
- // Attribute section did not create a clone from any matching part. Create a non-clone part now.
- if (track->type() == Track::MIDI || track->type() == Track::DRUM)
- npart = new MidiPart((MidiTrack*)track);
- else if (track->type() == Track::WAVE)
- npart = new WavePart((WaveTrack*)track);
- else
- return 0;
-
- // Signify a new non-clone part was created.
- // Even if the original part was itself a clone, clear this because the
- // attribute section did not create a clone from any matching part.
- clone = false;
-
- // If an id or uuid was found, add the part to the clone list
- // so that subsequent parts can look it up and clone from it...
- if(id != -1)
- {
- ClonePart ncp(npart, id);
- cloneList.push_back(ncp);
- }
- else
- if(uuidvalid)
- {
- ClonePart ncp(npart);
- // New ClonePart creates its own uuid, but we need to replace it.
- uuid_copy(ncp.uuid, uuid);
- cloneList.push_back(ncp);
- }
- }
-
- if (tag == "name")
- npart->setName(xml.parse1());
- else if (tag == "poslen") {
- ((PosLen*)npart)->read(xml, "poslen");
- }
- else if (tag == "pos") {
- Pos pos;
- pos.read(xml, "pos"); // obsolete
- npart->setTick(pos.tick());
- }
- else if (tag == "len") {
- Pos len;
- len.read(xml, "len"); // obsolete
- npart->setLenTick(len.tick());
- }
- else if (tag == "selected")
- npart->setSelected(xml.parseInt());
- else if (tag == "color")
- npart->setColorIndex(xml.parseInt());
- else if (tag == "mute")
- npart->setMute(xml.parseInt());
- else if (tag == "event")
- {
- // If a new non-clone part was created, accept the events...
- if(!clone)
- {
- EventType type = Wave;
- if(track->isMidiTrack())
- type = Note;
- Event e(type);
- e.read(xml);
- // stored tickpos for event has absolute value. However internally
- // tickpos is relative to start of part, we substract tick().
- // TODO: better handling for wave event
- e.move( -npart->tick() );
- int tick = e.tick();
-
- // Do not discard events belonging to clone parts,
- // at least not yet. A later clone might have a longer,
- // fully accommodating part length!
- //if ((tick < 0) || (tick >= (int) lenTick())) {
- //if ((tick < 0) || ( id == -1 && !clone && (tick >= (int)lenTick()) ))
- // No way to tell at the moment whether there will be clones referencing this...
- // No choice but to accept all events past 0.
- if(tick < 0)
- {
- //printf("readClone: warning: event not in part: %d - %d -%d, discarded\n",
- printf("readClone: warning: event at tick:%d not in part:%s, discarded\n",
- tick, npart->name().toLatin1().constData());
- }
- else
- {
- npart->events()->add(e);
- }
- }
- else
- // ...Otherwise a clone was created, so we don't need the events.
- xml.skip(tag);
- }
- else
- xml.unknown("PartCanvas::readClone");
- break;
- case Xml::Attribut:
- if (tag == "cloneId")
- {
- id = xml.s2().toInt();
- if(id != -1)
- {
- for(iClone i = cloneList.begin(); i != cloneList.end(); ++i)
- {
- // Is a matching part found in the clone list?
- if(i->id == id)
- {
- // This makes a clone, chains the part, and increases ref counts.
- npart = track->newPart((Part*)i->cp, true);
- break;
- }
- }
- }
- }
- else if (tag == "uuid")
- {
- uuid_parse(xml.s2().toLatin1().constData(), uuid);
- if(!uuid_is_null(uuid))
- {
- uuidvalid = true;
- for(iClone i = cloneList.begin(); i != cloneList.end(); ++i)
- {
- // Is a matching part found in the clone list?
- if(uuid_compare(uuid, i->uuid) == 0)
- {
- // If we want to paste to the part's original track...
- if(!toTrack)
- {
- // Make sure the track exists (has not been deleted).
- if((i->cp->track()->isMidiTrack() && song->midis()->find(i->cp->track()) != song->midis()->end()) ||
- (i->cp->track()->type() == Track::WAVE && song->waves()->find(i->cp->track()) != song->waves()->end()))
- track = i->cp->track();
- }
- // This makes a clone, chains the part, and increases ref counts.
- npart = track->newPart((Part*)i->cp, true);
- break;
- }
- }
- }
- }
- //else if(tag == "isclone") // Ignore
- // clone = xml.s2().toInt();
- break;
- case Xml::TagEnd:
- if (tag == "part")
- return npart;
- default:
- break;
- }
- }
- return npart;
-}
-*/
//---------------------------------------------------------
// paste
// paste part to current selected track at cpos
//---------------------------------------------------------
-//void PartCanvas::paste()
void PartCanvas::paste(bool clone, bool toTrack, bool doInsert)
{
Track* track = 0;
@@ -2740,44 +2107,39 @@ void PartCanvas::paste(bool clone, bool toTrack, bool doInsert)
return;
}
- int endPos=0;
- unsigned int startPos=song->vcpos();
if (!txt.isEmpty())
{
- song->startUndo();
- endPos=pasteAt(txt, track, startPos, clone, toTrack);
+ int endPos=0;
+ unsigned int startPos=song->vcpos();
+ Undo operations=pasteAt(txt, track, startPos, clone, toTrack, &endPos);
Pos p(endPos, true);
song->setPos(0, p);
- if (!doInsert)
- song->endUndo(SC_PART_INSERTED);
+ if (doInsert) {
+ int offset = endPos-startPos;
+ Undo temp=movePartsTotheRight(startPos, offset);
+ operations.insert(operations.end(), temp.begin(), temp.end());
+ }
+ song->applyOperationGroup(operations);
}
- if (doInsert) {
- int offset = endPos-startPos;
- movePartsTotheRight(startPos, offset);
- song->endUndo(SC_PART_INSERTED);
- }
}
//---------------------------------------------------------
// movePartsToTheRight
//---------------------------------------------------------
-void PartCanvas::movePartsTotheRight(unsigned int startTicks, int length)
+Undo PartCanvas::movePartsTotheRight(unsigned int startTicks, int length)
{
+ Undo operations;
+
// all parts that start after the pasted parts will be moved the entire length of the pasted parts
for (iCItem i = items.begin(); i != items.end(); ++i) {
if (!i->second->isSelected()) {
Part* part = i->second->part();
if (part->tick() >= startTicks) {
- //void Audio::msgChangePart(Part* oldPart, Part* newPart, bool doUndoFlag, bool doCtrls, bool doClones)
Part *newPart = part->clone();
newPart->setTick(newPart->tick()+length);
- if (part->track()->type() == Track::WAVE) {
- audio->msgChangePart((WavePart*)part,(WavePart*)newPart,false,false,false);
- } else {
- audio->msgChangePart(part,newPart,false,false,false);
- }
-
+
+ operations.push_back(UndoOp(UndoOp::ModifyPart,part,newPart,false,false));
}
}
}
@@ -2790,9 +2152,11 @@ void PartCanvas::movePartsTotheRight(unsigned int startTicks, int length)
Marker *oldMarker = new Marker();
*oldMarker = *m;
m->setTick(m->tick()+length);
- song->undoOp(UndoOp::ModifyMarker,oldMarker, m);
+ operations.push_back(UndoOp(UndoOp::ModifyMarker,oldMarker, m));
}
}
+
+ return operations;
}
//---------------------------------------------------------
// startDrag
@@ -2800,7 +2164,6 @@ void PartCanvas::movePartsTotheRight(unsigned int startTicks, int length)
void PartCanvas::startDrag(CItem* item, DragType t)
{
- //printf("PartCanvas::startDrag(CItem* item, DragType t)\n");
NPart* p = (NPart*)(item);
Part* part = p->part();
@@ -2861,7 +2224,6 @@ void PartCanvas::startDrag(CItem* item, DragType t)
void PartCanvas::dragEnterEvent(QDragEnterEvent* event)
{
- ///event->accept(Q3TextDrag::canDecode(event));
event->acceptProposedAction(); // TODO CHECK Tim.
}
@@ -2869,22 +2231,6 @@ void PartCanvas::dragEnterEvent(QDragEnterEvent* event)
// dragvent
//---------------------------------------------------------
-void PartCanvas::dragMoveEvent(QDragMoveEvent*)
- {
-// printf("drag move %x\n", this);
- //event->acceptProposedAction();
- }
-
-//---------------------------------------------------------
-// dragLeaveEvent
-//---------------------------------------------------------
-
-void PartCanvas::dragLeaveEvent(QDragLeaveEvent*)
- {
-// printf("drag leave\n");
- //event->acceptProposedAction();
- }
-
//---------------------------------------------------------
// dropEvent
//---------------------------------------------------------
@@ -2904,7 +2250,6 @@ void PartCanvas::viewDropEvent(QDropEvent* event)
if(event->mimeData()->hasFormat("text/partlist"))
type = 1;
else
- //if(event->mimeData()->hasFormat("text/uri-list"))
if(event->mimeData()->hasUrls())
type = 2;
else
@@ -2934,11 +2279,11 @@ void PartCanvas::viewDropEvent(QDropEvent* event)
Track* track = 0;
if (trackNo < tracks->size())
track = tracks->index(trackNo);
- if (track) {
- song->startUndo();
- pasteAt(text, track, x);
- song->endUndo(SC_PART_INSERTED);
- }
+ if (track)
+ {
+ Undo temp=pasteAt(text, track, x);
+ song->applyOperationGroup(temp);
+ }
}
else if (type == 2)
{
@@ -2946,7 +2291,7 @@ void PartCanvas::viewDropEvent(QDropEvent* event)
Track* track = 0;
if (trackNo < tracks->size())
track = tracks->index(trackNo);
- //printf("trackNo=%d\n, trackNo track=%d\n", trackNo, track);
+
int x = AL::sigmap.raster(event->pos().x(), *_raster);
if (x < 0)
x = 0;
@@ -3024,7 +2369,6 @@ void PartCanvas::drawCanvas(QPainter& p, const QRect& rect)
//--------------------------------
// vertical lines
//-------------------------------
- //printf("raster=%d\n", *_raster);
if (config.canvasShowGrid) {
int bar, beat;
unsigned tick;
@@ -3083,12 +2427,9 @@ void PartCanvas::drawCanvas(QPainter& p, const QRect& rect)
th = track->height();
if (!th)
continue;
- ///if (/*config.canvasShowGrid ||*/ !track->isMidiTrack()) {
if (config.canvasShowGrid && (track->isMidiTrack() || track->type() == Track::WAVE)) // Tim.
{
- //printf("PartCanvas::drawCanvas track name:%s, y:%d h:%d\n", track->name().toLatin1().constData(), yy, th);
p.setPen(baseColor.dark(130));
- ///p.drawLine(x, yy, x + w, yy);
p.drawLine(x, yy + th, x + w, yy + th); // Tim.
p.setPen(baseColor);
}
@@ -3195,7 +2536,6 @@ void PartCanvas::drawTopItem(QPainter& p, const QRect& rect)
MPEventList *el = mt->mpevents();
if (el->size()) {
- //printf("num events %d\n", mt->mpevents()->size());
for (iMPEvent i = el->begin(); i != el->end(); ++i) {
MidiPlayEvent pe = *i;
@@ -3213,7 +2553,6 @@ void PartCanvas::drawTopItem(QPainter& p, const QRect& rect)
if (e.pitch() == pe.dataA() && e.dataC() == 1) {
e.setLenTick(pe.time() - e.tick()- startPos);
e.setC(0); // reset the variable we borrowed for state handling
- //printf("editing event tick=%d startPos=%d\n",e.tick(), startPos);
continue;
}
}
@@ -3295,7 +2634,6 @@ void PartCanvas::drawAutomation(QPainter& p, const QRect& r, AudioTrack *t)
// prepare prevVal
if (cl->valueType() == VAL_LOG ) { // use db scale for volume
- //printf("volume cvval=%f\n", cvFirst.val);
prevVal = dbToVal(cvFirst.val); // represent volume between 0 and 1
if (prevVal < 0) prevVal = 0.0;
}
@@ -3334,13 +2672,11 @@ void PartCanvas::drawAutomation(QPainter& p, const QRect& r, AudioTrack *t)
(rr.bottom()-2)-prevVal*height,
currentPixel,
(rr.bottom()-2)-nextVal*height);
- ///(rr.bottom()-2)- (discrete?prevVal:nextVal)*height); // Tim
///if(discrete)
/// p.drawLine( currentPixel, (rr.bottom()-2)-prevVal*height, currentPixel, (rr.bottom()-2)-nextVal*height ); // Tim
firstRun=false;
- //printf("draw line: %d %f %d %f\n",tempomap.frame2tick(lastPos),rr.bottom()-lastVal*height,tempomap.frame2tick(cv.frame),rr.bottom()-curVal*height);
prevPosFrame=cv.frame;
prevVal=nextVal;
if (currentPixel > rr.x()+ rr.width())
@@ -3350,12 +2686,10 @@ void PartCanvas::drawAutomation(QPainter& p, const QRect& r, AudioTrack *t)
p.drawRect(mapx(tempomap.frame2tick(prevPosFrame))-2, (rr.bottom()-2)-prevVal*height-2, 5, 5);
p.drawRect(mapx(tempomap.frame2tick(prevPosFrame))-1, (rr.bottom()-1)-prevVal*height-2, 3, 3);
}
- //printf("outer draw %f\n", cvFirst.val );
p.drawLine(mapx(tempomap.frame2tick(prevPosFrame)),
(rr.bottom()-2)-prevVal*height,
rr.x()+rr.width(),
(rr.bottom()-2)-prevVal*height);
- //printf("draw last line: %d %f %d %f\n",tempomap.frame2tick(prevPosFrame),(rr.bottom()-2)-prevVal*height,tempomap.frame2tick(prevPosFrame)+rr.width(),(rr.bottom()-2)-prevVal*height);
}
}
quitDrawing:
@@ -3448,7 +2782,6 @@ void PartCanvas::checkAutomation(Track * t, const QPoint &pointer, bool addNewCt
continue; // not the right region
}
- //printf("firstX=%f lastX=%f firstY=%f lastY=%f proportion=%f currX=%d\n", firstX,lastX,firstY,lastY,proportion, currX);
// 10 X(15) 20
// proportion = 0.5
@@ -3473,7 +2806,6 @@ void PartCanvas::checkAutomation(Track * t, const QPoint &pointer, bool addNewCt
}
}
- //printf("point at x=%d xdiff=%d y=%d ydiff=%d\n", mapx(tempomap.frame2tick(cv.frame)), x1, mapx(ypixel), y1);
oldX = xpixel;
oldY = ypixel;
@@ -3527,7 +2859,6 @@ void PartCanvas::controllerChanged(Track* /* t */)
void PartCanvas::processAutomationMovements(QPoint pos, bool addPoint)
{
- //printf("processAutomationMovements %d %d %d %d %d %d\n", pos.x(), pos.y(),mapx(pos.x()), mapy(pos.y()), xpos, ypos);
if (_tool == AutomationTool) {
if (!automation.moveController) { // currently nothing going lets's check for some action.
@@ -3606,9 +2937,7 @@ void PartCanvas::processAutomationMovements(QPoint pos, bool addPoint)
if (cvval< min) cvval=min;
if (cvval>max) cvval=max;
automation.currentCtrl->val = cvval;
- //printf("calc cvval=%f yfraction=%f ", cvval, yfraction);
}
- //printf("mouseY=%d\n", mouseY);
controllerChanged(automation.currentTrack);
}
@@ -3623,3 +2952,28 @@ double PartCanvas::valToDb(double inV)
{
return exp10((inV*70.0-60.0)/20.0);
}
+
+//---------------------------------------------------------
+// endMoveItems
+// dir = 0 move in all directions
+// 1 move only horizontal
+// 2 move only vertical
+//---------------------------------------------------------
+
+void PartCanvas::endMoveItems(const QPoint& pos, DragType dragtype, int dir)
+ {
+ int dp = y2pitch(pos.y()) - y2pitch(start.y());
+ int dx = pos.x() - start.x();
+
+ if (dir == 1)
+ dp = 0;
+ else if (dir == 2)
+ dx = 0;
+
+ moveCanvasItems(moving, dp, dx, dragtype);
+
+ moving.clear();
+ updateSelection();
+ redraw();
+ }
+
diff --git a/muse2/muse/arranger/pcanvas.h b/muse2/muse/arranger/pcanvas.h
index 3145d034..acfe565e 100644
--- a/muse2/muse/arranger/pcanvas.h
+++ b/muse2/muse/arranger/pcanvas.h
@@ -12,9 +12,7 @@
#include "canvas.h"
#include "trackautomationview.h"
-class QDragMoveEvent;
class QDropEvent;
-class QDragLeaveEvent;
class QMouseEvent;
class QKeyEvent;
class QEvent;
@@ -84,19 +82,16 @@ class PartCanvas : public Canvas {
virtual int y2pitch(int y) const;
virtual int pitch2y(int p) const;
- virtual void moveCanvasItems(CItemList&, int, int, DragType, int*);
- virtual bool moveItem(CItem*, const QPoint&, DragType);
virtual CItem* newItem(const QPoint&, int);
virtual void resizeItem(CItem*,bool);
virtual void newItem(CItem*,bool);
virtual bool deleteItem(CItem*);
- virtual void startUndo(DragType);
-
- virtual void endUndo(DragType, int);
+ virtual void moveCanvasItems(CItemList&, int, int, DragType);
+ virtual UndoOp moveItem(CItem*, const QPoint&, DragType);
+
+ virtual void updateSong(DragType, int);
virtual void startDrag(CItem*, DragType);
virtual void dragEnterEvent(QDragEnterEvent*);
- virtual void dragMoveEvent(QDragMoveEvent*);
- virtual void dragLeaveEvent(QDragLeaveEvent*);
virtual void viewDropEvent(QDropEvent*);
virtual QMenu* genItemPopup(CItem*);
@@ -107,8 +102,8 @@ class PartCanvas : public Canvas {
void copy(PartList*);
void paste(bool clone = false, bool toTrack = true, bool doInsert=false);
- int pasteAt(const QString&, Track*, unsigned int, bool clone = false, bool toTrack = true);
- void movePartsTotheRight(unsigned int startTick, int length);
+ Undo pasteAt(const QString&, Track*, unsigned int, bool clone = false, bool toTrack = true, int* finalPosPtr = NULL);
+ Undo movePartsTotheRight(unsigned int startTick, int length);
//Part* readClone(Xml&, Track*, bool toTrack = true);
void drawWavePart(QPainter&, const QRect&, WavePart*, const QRect&);
//void drawMidiPart(QPainter&, const QRect& rect, EventList* events, MidiTrack*mt, const QRect& r, int pTick, int from, int to);
@@ -127,6 +122,7 @@ class PartCanvas : public Canvas {
protected:
virtual void drawCanvas(QPainter&, const QRect&);
+ virtual void endMoveItems(const QPoint&, DragType, int dir);
signals:
void timeChanged(unsigned);
diff --git a/muse2/muse/audio.h b/muse2/muse/audio.h
index 940dd2a5..e332f516 100644
--- a/muse2/muse/audio.h
+++ b/muse2/muse/audio.h
@@ -124,7 +124,6 @@ class Audio {
bool idle; // do nothing in idle mode
bool _freewheel;
bool _bounce;
- //bool loopPassed;
unsigned _loopFrame; // Startframe of loop if in LOOP mode. Not quite the same as left marker !
int _loopCount; // Number of times we have looped so far
@@ -202,13 +201,9 @@ class Audio {
void msgMoveTrack(int idx1, int dx2, bool u = true);
void msgAddPart(Part*, bool u = true);
void msgRemovePart(Part*, bool u = true);
- //void msgChangePart(Part* oldPart, Part* newPart, bool u = true);
void msgChangePart(Part* oldPart, Part* newPart, bool u = true, bool doCtrls = true, bool doClones = false);
- //void msgAddEvent(Event&, Part*, bool u = true);
void msgAddEvent(Event&, Part*, bool u = true, bool doCtrls = true, bool doClones = false);
- //void msgDeleteEvent(Event&, Part*, bool u = true);
void msgDeleteEvent(Event&, Part*, bool u = true, bool doCtrls = true, bool doClones = false);
- //void msgChangeEvent(Event&, Event&, Part*, bool u = true);
void msgChangeEvent(Event&, Event&, Part*, bool u = true, bool doCtrls = true, bool doClones = false);
void msgScanAlsaMidiPorts();
void msgAddTempo(int tick, int tempo, bool doUndoFlag = true);
@@ -250,7 +245,6 @@ class Audio {
void msgResetMidiDevices();
void msgIdle(bool);
void msgBounce();
- //void msgSetPluginCtrlVal(PluginI* /*plugin*/, int /*param*/, double /*val*/);
void msgSetPluginCtrlVal(AudioTrack*, int /*param*/, double /*val*/);
void msgSwapControllerIDX(AudioTrack*, int, int);
void msgClearControllerEvents(AudioTrack*, int);
diff --git a/muse2/muse/ctrl/ctrlcanvas.cpp b/muse2/muse/ctrl/ctrlcanvas.cpp
index ceffee68..678cd823 100644
--- a/muse2/muse/ctrl/ctrlcanvas.cpp
+++ b/muse2/muse/ctrl/ctrlcanvas.cpp
@@ -563,14 +563,6 @@ void CtrlCanvas::partControllers(const MidiPart* part, int num, int* dnum, int*
}
*mcvl = tmcvl;
- // Removed by T356.
- // MidiCtrlValList not found is now an acceptable state (for multiple part editing).
- //if (i == cvll->end()) {
- // printf("CtrlCanvas::setController(0x%x): not found\n", num);
- // for (i = cvll->begin(); i != cvll->end(); ++i)
- // printf(" 0x%x\n", i->second->num());
- // return;
- // }
}
}
}
@@ -584,98 +576,9 @@ void CtrlCanvas::updateItems()
selection.clear();
items.clearDelete();
- /*
- if(ctrl)
- {
- for(ciMidiCtrlVal imcv = ctrl->begin(); imcv != ctrl->end(); ++imcv)
- {
- MidiPart* part = (MidiPart*)imcv->part;
- int val = imcv->val;
-
- bool edpart = false;
- if(editor->parts()->index(part) != -1)
- edpart = true;
-
- MidiController* mc;
- MidiCtrlValList* mcvl;
- partControllers(part, _cnum, 0, 0, &mc, &mcvl);
-
- Event e(Controller);
-
- if(_cnum == CTRL_VELOCITY && e.type() == Note)
- {
- items.add(new CEvent(e, part, e.velo()));
-
- }
-
- }
- }
- */
-
- /*
- MidiTrackList* mtl = song->midis();
- for(ciMidiTrack imt = mtl->begin(); imt != mtl->end(); ++imt)
- {
- //MidiTrack* mt = *imt;
- PartList* pl = (*imt)->parts();
- for(ciPart p = pl->begin(); p != pl->end(); ++p)
- {
- MidiPart* part = (MidiPart*)(p->second);
-
- bool edpart = false;
- if(editor->parts()->index(part) != -1)
- edpart = true;
-
- EventList* el = part->events();
- MidiController* mc;
- MidiCtrlValList* mcvl;
- partControllers(part, _cnum, 0, 0, &mc, &mcvl);
-
- for(iEvent i = el->begin(); i != el->end(); ++i)
- {
- Event e = i->second;
- if(_cnum == CTRL_VELOCITY && e.type() == Note)
- {
- if(curDrumInstrument == -1)
- {
- items.add(new CEvent(e, part, e.velo()));
- }
- else if (e.dataA() == curDrumInstrument) //same note
- items.add(new CEvent(e, part, e.velo()));
- }
- else if (e.type() == Controller && e.dataA() == _didx)
- {
- if(mcvl && last.empty())
- {
- Event le(Controller);
- //le.setType(Controller);
- le.setA(_didx);
- //le.setB(e.dataB());
- le.setB(CTRL_VAL_UNKNOWN);
- //lastce = new CEvent(Event(), part, mcvl->value(part->tick(), part));
- //lastce = new CEvent(le, part, mcvl->value(part->tick(), part));
- lastce = new CEvent(le, part, mcvl->value(part->tick()));
- items.add(lastce);
- }
- if (lastce)
- lastce->setEX(e.tick());
- lastce = new CEvent(e, part, e.dataB());
- items.add(lastce);
- last = e;
- }
- }
- }
- }
- */
-
-
-
-
if(!editor->parts()->empty())
{
- //Event last;
- //CEvent* lastce = 0;
CEvent *newev = 0;
for (iPart p = editor->parts()->begin(); p != editor->parts()->end(); ++p)
@@ -812,7 +715,6 @@ void CtrlCanvas::viewMousePressEvent(QMouseEvent* event)
}
if(do_redraw)
redraw(); // Let songChanged handle the redraw upon SC_SELECTION.
- //song->update(SC_SELECTION); //
}
@@ -973,11 +875,8 @@ void CtrlCanvas::viewMouseReleaseEvent(QMouseEvent* event)
}
}
drag = DRAG_OFF;
- //if(do_redraw)
- // redraw(); // Let songChanged handle the redraw upon SC_SELECTION.
+ // Let songChanged handle the redraw upon SC_SELECTION.
song->update(SC_SELECTION); //
- //else
- // redraw();
}
break;
@@ -1024,7 +923,7 @@ void CtrlCanvas::newValRamp(int x1, int y1, int x2, int y2)
useRaster = true;
}
- song->startUndo();
+ Undo operations;
// delete existing events
@@ -1032,44 +931,29 @@ void CtrlCanvas::newValRamp(int x1, int y1, int x2, int y2)
int lastpv = CTRL_VAL_UNKNOWN;
for (ciCEvent i = items.begin(); i != items.end(); ++i) {
CEvent* ev = *i;
- if(ev->part() != curPart)
+ if (ev->part() != curPart)
continue;
Event event = ev->event();
if (event.empty())
continue;
int x = event.tick() + curPartTick;
- //printf("CtrlCanvas::newValRamp x:%d xx1:%d xx2:%d len:%d\n", x, xx1, xx2, curPart->lenTick());
if (x < xx1)
- {
- // if(event.dataB() != CTRL_VAL_UNKNOWN)
- // lastpv = event.dataB();
continue;
- }
- //if (x <= xx1)
- //{
- // if(type == CTRL_PROGRAM && event.dataB() != CTRL_VAL_UNKNOWN && ((event.dataB() & 0xffffff) != 0xffffff))
- // lastpv = event.dataB();
- // if (x < xx1)
- // continue;
- //}
+
if (x >= xx2)
break;
- // Indicate no undo, and do port controller values and clone parts.
- audio->msgDeleteEvent(event, curPart, false, true, true);
+ // Do port controller values and clone parts.
+ operations.push_back(UndoOp(UndoOp::DeleteEvent, event, curPart, true, true));
}
- //if(type == CTRL_PROGRAM && lastpv == CTRL_VAL_UNKNOWN)
- if(ctrl)
+ if (ctrl)
lastpv = ctrl->hwVal();
unsigned curPartLen = curPart->lenTick();
// insert new events
- //for (int x = xx1; x < xx2; x += raster) {
- // int y = (x2==x1) ? y1 : (((y2-y1)*(x-x1))/(x2-x1))+y1;
- // int nval = computeVal(_controller, y, height());
for (int x = xx1, step; x < xx2 ; x += step )
{
step = useRaster ? raster : editor->rasterVal2(x + 1) - x;
@@ -1077,21 +961,18 @@ void CtrlCanvas::newValRamp(int x1, int y1, int x2, int y2)
int y = x + step >= xx2 || x2 == x1 ? y2 : (x == xx1 ? y1 : (((y2 - y1) * (x + step/2 - x1)) / (x2 - x1)) + y1);
int nval = computeVal(_controller, y, height());
- //int tick = x - curPartTick;
unsigned tick = x - curPartTick;
- //printf("CtrlCanvas::newValRamp x:%d xx1:%d xx2:%d step:%d newtick:%d\n", x, xx1, xx2, step, tick);
// Do not add events which are past the end of the part.
- //if((unsigned)tick >= curPartLen)
- if(tick >= curPartLen)
+ if (tick >= curPartLen)
break;
Event event(Controller);
event.setTick(tick);
event.setA(_didx);
- if(type == CTRL_PROGRAM)
+ if (type == CTRL_PROGRAM)
{
- if(lastpv == CTRL_VAL_UNKNOWN)
+ if (lastpv == CTRL_VAL_UNKNOWN)
{
- if(song->mtype() == MT_GM)
+ if (song->mtype() == MT_GM)
event.setB(0xffff00 | (nval - 1));
else
event.setB(nval - 1);
@@ -1102,13 +983,11 @@ void CtrlCanvas::newValRamp(int x1, int y1, int x2, int y2)
else
event.setB(nval);
- // Indicate no undo, and do port controller values and clone parts.
- audio->msgAddEvent(event, curPart, false, true, true);
+ // Do port controller values and clone parts.
+ operations.push_back(UndoOp(UndoOp::AddEvent, event, curPart, true, true));
}
- ///song->update(0);
- ///redraw();
- song->endUndo(SC_EVENT_MODIFIED | SC_EVENT_INSERTED | SC_EVENT_REMOVED);
+ song->applyOperationGroup(operations);
}
//---------------------------------------------------------
@@ -1123,27 +1002,24 @@ void CtrlCanvas::changeValRamp(int x1, int y1, int x2, int y2)
int h = height();
bool changed = false;
int type = _controller->num();
- //int xx1 = editor->rasterVal1(x1);
- song->startUndo();
+ Undo operations;
for (ciCEvent i = items.begin(); i != items.end(); ++i) {
if ((*i)->contains(x1, x2)) {
- //if ((*i)->contains(xx1, x2)) {
CEvent* ev = *i;
- if(ev->part() != curPart)
+ if (ev->part() != curPart)
continue;
+
Event event = ev->event();
if (event.empty())
continue;
- //MidiPart* part = ev->part();
- //int x = event.tick() + ev->part()->tick();
int x = event.tick() + curPart->tick();
int y = (x2==x1) ? y1 : (((y2-y1)*(x-x1))/(x2-x1))+y1;
int nval = computeVal(_controller, y, h);
- if(type == CTRL_PROGRAM)
+ if (type == CTRL_PROGRAM)
{
- if(event.dataB() == CTRL_VAL_UNKNOWN)
+ if (event.dataB() == CTRL_VAL_UNKNOWN)
{
--nval;
if(song->mtype() == MT_GM)
@@ -1155,16 +1031,13 @@ void CtrlCanvas::changeValRamp(int x1, int y1, int x2, int y2)
ev->setVal(nval);
- //MidiController::ControllerType type = midiControllerType(_controller->num());
- //if (type == MidiController::Velo) {
if (type == CTRL_VELOCITY) {
if ((event.velo() != nval)) {
Event newEvent = event.clone();
newEvent.setVelo(nval);
ev->setEvent(newEvent);
- // Indicate no undo, and do not do port controller values and clone parts.
- audio->msgChangeEvent(event, newEvent, curPart, false, false, false);
- ///ev->setEvent(newEvent);
+ // Do not do port controller values and clone parts.
+ operations.push_back(UndoOp(UndoOp::ModifyEvent, newEvent, event, curPart, false, false));
changed = true;
}
}
@@ -1174,34 +1047,16 @@ void CtrlCanvas::changeValRamp(int x1, int y1, int x2, int y2)
Event newEvent = event.clone();
newEvent.setB(nval);
ev->setEvent(newEvent);
- // Indicate no undo, and do port controller values and clone parts.
- audio->msgChangeEvent(event, newEvent, curPart, false, true, true);
- ///ev->setEvent(newEvent);
+ // Do port controller values and clone parts.
+ operations.push_back(UndoOp(UndoOp::ModifyEvent, newEvent, event, curPart, true, true));
changed = true;
}
}
- else {
- //if(!ctrl)
- //{
- // ctrl =
- //}
-
- // Removed by T356. Never gets here? A good thing, don't wan't auto-create values.
- //int oval = ctrl->value(0);
- //if (oval != nval) {
- // Changed by T356.
- //ctrl->add(0, nval);
- // ctrl->add(0, nval, part);
- // changed = true;
- // }
-
- }
}
}
}
- ///if (changed)
- /// redraw();
- song->endUndo(SC_EVENT_MODIFIED);
+
+ song->applyOperationGroup(operations);
}
//---------------------------------------------------------
@@ -1216,7 +1071,6 @@ void CtrlCanvas::changeVal(int x1, int x2, int y)
bool changed = false;
int newval = computeVal(_controller, y, height());
int type = _controller->num();
- //int xx1 = editor->rasterVal1(x1);
for (ciCEvent i = items.begin(); i != items.end(); ++i) {
if (!(*i)->contains(x1, x2))
@@ -1226,26 +1080,7 @@ void CtrlCanvas::changeVal(int x1, int x2, int y)
if(ev->part() != curPart)
continue;
Event event = ev->event();
- //if(event.tick() >= curPart->lenTick())
- // break;
-
- //MidiPart* part = ev->part();
- //int nval = newval;
- //if(type == CTRL_PROGRAM)
- //{
- // if(event.dataB() == CTRL_VAL_UNKNOWN)
- // {
- // --nval;
- // if(song->mtype() == MT_GM)
- // nval |= 0xffff00;
- // }
- // else
- // nval = (event.dataB() & 0xffff00) | (nval - 1);
- //}
- //ev->setVal(nval);
-
- //MidiController::ControllerType type = midiControllerType(_controller->num());
- //if (type == MidiController::Velo) {
+
if (type == CTRL_VELOCITY) {
if ((event.velo() != newval)) {
ev->setVal(newval);
@@ -1284,160 +1119,12 @@ void CtrlCanvas::changeVal(int x1, int x2, int y)
changed = true;
}
}
- else {
- //if(!ctrl)
- //{
- // ctrl =
- //}
-
- // Removed by T356. Never gets here? A good thing, don't wan't auto-create values.
- //int oval = ctrl->value(0);
- //if (oval != nval) {
- // Changed by T356.
- //ctrl->add(0, nval);
- // ctrl->add(0, nval, part);
- // changed = true;
- // }
- }
}
}
if (changed)
redraw();
}
-/*
-//---------------------------------------------------------
-// newVal
-//---------------------------------------------------------
-
-void CtrlCanvas::newVal(int x1, int x2, int y)
- {
- int xx1 = editor->rasterVal1(x1);
- int xx2 = editor->rasterVal2(x2);
- int newval = computeVal(_controller, y, height());
- int type = _controller->num();
-
- bool found = false;
- bool song_changed = false;
-
- int lastpv = CTRL_VAL_UNKNOWN;
- if(ctrl)
- lastpv = ctrl->hwVal();
-
- for (ciCEvent i = items.begin(); i != items.end(); ++i) {
- CEvent* ev = *i;
- if(ev->part() != curPart)
- continue;
- //int partTick = ev->part()->tick();
- int partTick = curPart->tick();
- Event event = ev->event();
- if (event.empty())
- continue;
- int ax = event.tick() + partTick;
- //printf("CtrlCanvas::newVal ax:%d xx1:%d xx2:%d len:%d\n", ax, xx1, xx2, curPart->lenTick());
-
- if (ax < xx1)
- continue;
- //if(ax <= xx1)
- //{
- // if(type == CTRL_PROGRAM && event.dataB() != CTRL_VAL_UNKNOWN && ((event.dataB() & 0xffffff) != 0xffffff))
- // lastpv = event.dataB();
- // if(ax < xx1)
- // continue;
- //}
- if (ax >= xx2)
- break;
-
- // Added by T356. Do not add events which are past the end of the part.
- //if(event.tick() >= curPart->lenTick())
- // break;
-
- int nval = newval;
- if(type == CTRL_PROGRAM)
- {
- if(event.dataB() == CTRL_VAL_UNKNOWN)
- {
- //if(lastpv == CTRL_VAL_UNKNOWN)
- // lastpv = ctrl->hwVal();
-
- if(lastpv == CTRL_VAL_UNKNOWN)
- {
- --nval;
- if(song->mtype() == MT_GM)
- nval |= 0xffff00;
- }
- else
- nval = (lastpv & 0xffff00) | (nval - 1);
- }
- else
- nval = (event.dataB() & 0xffff00) | (nval - 1);
- }
-
- if (ax == xx1) {
- // change event
- found = true;
- ev->setVal(nval);
- if ((event.dataB() != nval)) {
- Event newEvent = event.clone();
- newEvent.setB(nval);
- // Indicate no undo, and do port controller values and clone parts.
- audio->msgChangeEvent(event, newEvent, curPart, false, true, true);
- ev->setEvent(newEvent);
- song_changed = true;
- }
- }
- else if (ax < xx2) {
- // delete event
-
- //printf("CtrlCanvas::newVal delete xx1:%d xx2:%d len:%d\n", xx1, xx2, curPart->lenTick());
-
- // Indicate no undo, and do port controller values and clone parts.
- audio->msgDeleteEvent(event, curPart, false, true, true);
-
- song_changed = true;
- }
- }
- if (!found) {
- // new event
- int tick = xx1 - curPart->tick();
- // Do not add events which are past the end of the part.
- if((unsigned)tick < curPart->lenTick())
- {
- Event event(Controller);
- event.setTick(tick);
- event.setA(_didx);
- if(type == CTRL_PROGRAM)
- {
- if(lastpv == CTRL_VAL_UNKNOWN)
- {
- if(song->mtype() == MT_GM)
- event.setB(0xffff00 | (newval - 1));
- else
- event.setB(newval - 1);
- }
- else
- event.setB((lastpv & 0xffff00) | (newval - 1));
- }
- else
- event.setB(newval);
-
- //printf("CtrlCanvas::newVal add tick:%d A:%d B:%d\n", tick, event.dataA(), event.dataB());
-
- // Indicate no undo, and do port controller values and clone parts.
- audio->msgAddEvent(event, curPart, false, true, true);
-
- song_changed = true;
- }
- }
- if (song_changed)
- {
- songChanged(0);
- return;
- }
- redraw();
- }
-*/
-
//---------------------------------------------------------
// newVal
//---------------------------------------------------------
@@ -1645,10 +1332,7 @@ void CtrlCanvas::newVal(int x1, int y)
}
}
- //if(do_selchanged)
- // song->update(SC_SELECTION); // Let songChanged handle the redraw upon SC_SELECTION.
- //else
- if(do_redraw) //
+ if(do_redraw) // Let songChanged handle the redraw upon SC_SELECTION.
redraw();
}
@@ -1678,12 +1362,8 @@ void CtrlCanvas::newVal(int x1, int y1, int x2, int y2)
// So I draw from the first x. (TODO The idea may work now since I wrote this - more work was done.) p4.0.18 Tim.
int xx1 = editor->rasterVal1(x1);
- // Grab the 'second' raster. Nudge by +1 and let rasterVal2 snap to the next raster.
- //int xn1 = editor->rasterVal2(xx1 + 1);
int xx2 = editor->rasterVal2(x2);
- // Grab the 'second last' raster. Nudge by -1 and let rasterVal1 snap to the previous raster.
- //int xn2 = editor->rasterVal1(xx2 - 1);
// If x1 and x2 happen to lie directly on the same raster, xx1 will equal xx2,
// which is not good - there should always be a spread. Nudge by +1 and recompute.
@@ -1702,7 +1382,6 @@ void CtrlCanvas::newVal(int x1, int y1, int x2, int y2)
}
bool do_redraw = false;
- //bool do_selchanged = false;
// delete existing events
@@ -1712,7 +1391,6 @@ void CtrlCanvas::newVal(int x1, int y1, int x2, int y2)
bool curPartFound = false;
int lastpv = CTRL_VAL_UNKNOWN;
int partTick = curPart->tick();
- //for (ciCEvent i = items.begin(); i != items.end(); ++i)
for (iCEvent i = items.begin(); i != items.end() ; )
{
CEvent* ev = *i;
@@ -1742,10 +1420,7 @@ void CtrlCanvas::newVal(int x1, int y1, int x2, int y2)
//printf("CtrlCanvas::newVal x:%d xx1:%d xx2:%d len:%d\n", x, xx1, xx2, curPart->lenTick());
if (x < xx1)
- //if (x < (xn1 >= xx2 ? xx1 : xn1))
{
- // if(event.dataB() != CTRL_VAL_UNKNOWN)
- // lastpv = event.dataB();
prev_ev = i;
++i;
continue;
@@ -1780,24 +1455,14 @@ void CtrlCanvas::newVal(int x1, int y1, int x2, int y2)
}
do_redraw = true; // Let songChanged handle the redraw upon SC_SELECTION.
- //do_selchanged = true; //
prev_ev = i;
}
- //if(type == CTRL_PROGRAM && lastpv == CTRL_VAL_UNKNOWN)
if(ctrl)
lastpv = ctrl->hwVal();
// insert new events
- //for (int x = xx1; x < xx2; x += raster) {
- // Nudge x by +1 and let rasterVal2 snap to the next raster.
- //for (int x = xx1; x < xx2; x = useRaster ? x + raster : editor->rasterVal2(x + 1))
- //for (int x = xn1; x < xx2; x = useRaster ? x + raster : editor->rasterVal2(x + 1))
- //for (int x = xn1, step; x < xx2 ; x += (step = useRaster ? raster : editor->rasterVal2(x + 1) - x) )
- // Start from the 'second' raster - the first raster is already set in mouseDown!
- //for (int x = xn1, step; x < xx2 ; x += step )
- //for (int x = xn1 >= xx2 ? xx1 : xn1, step; x < xx2 ; x += step )
for (int x = xx1, step; x < xx2 ; x += step )
{
step = useRaster ? raster : editor->rasterVal2(x + 1) - x;
@@ -1849,9 +1514,6 @@ void CtrlCanvas::newVal(int x1, int y1, int x2, int y2)
do_redraw = true;
}
- //if(do_selchanged)
- // song->update(SC_SELECTION); // Let songChanged handle the redraw upon SC_SELECTION.
- //else
if(do_redraw) //
redraw();
}
@@ -1885,10 +1547,8 @@ void CtrlCanvas::deleteVal(int x1, int x2, int)
iCEvent prev_ev = items.end();
bool curPartFound = false;
- //bool song_changed = false;
bool do_redraw = false;
- //for (ciCEvent i = items.begin(); i != items.end(); ++i)
for (iCEvent i = items.begin(); i != items.end() ;)
{
CEvent* ev = *i;
@@ -1939,13 +1599,8 @@ void CtrlCanvas::deleteVal(int x1, int x2, int)
prev_ev = i;
}
- //if (song_changed) {
- // songChanged(0);
- // return;
- // }
if(do_redraw)
redraw(); // Let songChanged handle the redraw upon SC_SELECTION.
- //song->update(SC_SELECTION); //
}
//---------------------------------------------------------
diff --git a/muse2/muse/event.cpp b/muse2/muse/event.cpp
index 5d16fde9..77b66359 100644
--- a/muse2/muse/event.cpp
+++ b/muse2/muse/event.cpp
@@ -7,16 +7,10 @@
//=========================================================
#include <stdio.h>
-// #include <memory.h>
-//#include "audioconvert.h"
#include "event.h"
#include "eventbase.h"
#include "waveevent.h"
#include "midievent.h"
-//#include "globals.h"
-
-// Added by Tim. p3.3.20
-//#define USE_SAMPLERATE
//---------------------------------------------------------
// Event
@@ -65,11 +59,6 @@ void EventBase::dump(int n) const
Event Event::clone()
{
- // p3.3.31
- //printf("Event::clone() this:%p\n", this);
-
- // p3.3.31
- //return Event(ev->clone());
#ifdef USE_SAMPLERATE
return Event(ev->clone(), _audConv);
#else
@@ -80,14 +69,9 @@ Event Event::clone()
Event::Event()
{
ev = 0;
- //_sfCurFrame = 0;
- //_audConv = 0;
}
Event::Event(EventType t) {
- //_sfCurFrame = 0;
- //_audConv = 0;
-
if (t == Wave)
ev = new WaveEventBase(t);
else
@@ -95,30 +79,21 @@ Event::Event(EventType t) {
++(ev->refCount);
}
Event::Event(const Event& e) {
- //_sfCurFrame = 0;
- //_audConv = 0;
-
ev = e.ev;
if(ev)
++(ev->refCount);
#ifdef USE_SAMPLERATE
- //_audConv = AudioConverter::getAudioConverter(e._audConv);
if(e._audConv)
_audConv = e._audConv->reference();
#endif
}
Event::Event(EventBase* eb) {
- //_sfCurFrame = 0;
- //_audConv = 0;
-
ev = eb;
++(ev->refCount);
#ifdef USE_SAMPLERATE
if(!ev->sndFile().isNull())
- //_audConv = AudioConverter::getAudioConverter(eb, SRC_SINC_MEDIUM_QUALITY);
- //_audConv = new AudioConverter(ev->sndFile().channels(), SRC_SINC_MEDIUM_QUALITY);
_audConv = new SRCAudioConverter(ev->sndFile().channels(), SRC_SINC_MEDIUM_QUALITY);
#endif
}
@@ -162,19 +137,6 @@ void Event::setType(EventType t) {
}
Event& Event::operator=(const Event& e) {
- /*
- if (ev == e.ev)
- return *this;
- if (ev && --(ev->refCount) == 0) {
- delete ev;
- ev = 0;
- }
- ev = e.ev;
- if (ev)
- ++(ev->refCount);
- return *this;
- */
-
if (ev != e.ev)
{
if (ev && --(ev->refCount) == 0) {
@@ -191,7 +153,6 @@ Event& Event::operator=(const Event& e) {
{
if(_audConv)
AudioConverter::release(_audConv);
- //_audConv = AudioConverter::getAudioConverter(e._audConv);
_audConv = e._audConv->reference();
}
#endif
@@ -207,7 +168,6 @@ bool Event::selected() const { return ev->_selected; }
void Event::setSelected(bool val) { ev->_selected = val; }
void Event::move(int offset) { ev->move(offset); }
-//void Event::read(Xml& xml) { ev->read(xml); }
void Event::read(Xml& xml)
{
ev->read(xml);
@@ -216,27 +176,14 @@ void Event::read(Xml& xml)
if(!ev->sndFile().isNull())
{
if(_audConv)
- {
_audConv->setChannels(ev->sndFile().channels());
- }
else
- {
- //int srcerr;
- //if(debugMsg)
- // printf("Event::read Creating samplerate converter with %d channels\n", ev->sndFile().channels());
- //_src_state = src_new(SRC_SINC_MEDIUM_QUALITY, ev->sndFile().channels(), &srcerr);
-// _audConv = new AudioConverter(ev->sndFile().channels(), SRC_SINC_MEDIUM_QUALITY);
_audConv = new SRCAudioConverter(ev->sndFile().channels(), SRC_SINC_MEDIUM_QUALITY);
- //if(!_src_state)
- //if(!_audConv)
- // printf("Event::read Creation of samplerate converter with %d channels failed:%s\n", ev->sndFile().channels(), src_strerror(srcerr));
- }
}
#endif
}
-//void Event::write(int a, Xml& xml, const Pos& o) const { ev->write(a, xml, o); }
void Event::write(int a, Xml& xml, const Pos& o, bool forceWavePaths) const { ev->write(a, xml, o, forceWavePaths); }
void Event::dump(int n) const { ev->dump(n); }
Event Event::mid(unsigned a, unsigned b) { return Event(ev->mid(a, b)); }
@@ -268,22 +215,11 @@ int Event::spos() const { return ev->spos(); }
void Event::setSpos(int s) { ev->setSpos(s); }
SndFileR Event::sndFile() const { return ev->sndFile(); }
-//void Event::setSndFile(SndFileR& sf) { ev->setSndFile(sf); }
void Event::setSndFile(SndFileR& sf)
{
ev->setSndFile(sf);
#ifdef USE_SAMPLERATE
- //if(_audConv)
-// if(_audConv && !sf.isNull())
-// {
- //_audConv->setSndFile(sf);
- //if(sf.isNull())
- // AudioConverter::release(_audConv);
- //else
-// _audConv->setChannels(sf.channels());
-// }
-
if(_audConv)
{
// Do we release? Or keep the converter around, while gaining speed since no rapid creation/destruction.
@@ -302,15 +238,8 @@ void Event::setSndFile(SndFileR& sf)
#endif
}
-//void Event::read(unsigned offset, float** bpp, int channels, int nn, bool overwrite)
-//void Event::readAudio(unsigned offset, float** bpp, int channels, int nn, bool doSeek, bool overwrite)
-// p3.3.33
void Event::readAudio(WavePart* part, unsigned offset, float** bpp, int channels, int nn, bool doSeek, bool overwrite)
{
- //ev->read(offset, bpp, channels, nn, overwrite);
- //ev->readAudio(offset, bpp, channels, nn, doSeek, overwrite);
- //_sfCurFrame = ev->readAudio(_src_state, _sfCurFrame, offset, bpp, channels, nn, doSeek, overwrite);
- // p3.3.33
ev->readAudio(part, offset, bpp, channels, nn, doSeek, overwrite);
}
void Event::setTick(unsigned val) { ev->setTick(val); }
diff --git a/muse2/muse/event.h b/muse2/muse/event.h
index 5a8a74f8..b450d1fd 100644
--- a/muse2/muse/event.h
+++ b/muse2/muse/event.h
@@ -10,7 +10,6 @@
#define __EVENT_H__
#include <map>
-//#include <samplerate.h>
#include <sys/types.h>
#include "wave.h" // wg. SndFile
@@ -23,7 +22,6 @@ class QString;
class Xml;
class EventBase;
-//class AudioConverter;
class WavePart;
//---------------------------------------------------------
@@ -33,20 +31,12 @@ class WavePart;
class Event {
EventBase* ev;
- //off_t _sfCurFrame;
- //AudioConverter* _audConv;
-
public:
- //Event() { ev = 0; }
Event();
Event(EventType t);
Event(const Event& e);
Event(EventBase* eb);
- //#ifdef USE_SAMPLERATE
- //Event(EventBase* eb, AudioConverter* cv);
- //#endif
-
virtual ~Event();
bool empty() const;
@@ -62,7 +52,6 @@ class Event {
void move(int offset);
void read(Xml& xml);
- //void write(int a, Xml& xml, const Pos& offset) const;
void write(int a, Xml& xml, const Pos& offset, bool ForceWavePaths = false) const;
void dump(int n = 0) const;
Event clone();
@@ -93,12 +82,9 @@ class Event {
void setName(const QString& s);
int spos() const;
void setSpos(int s);
- //AudioConverter* audioConverter() { return _audConv;}
SndFileR sndFile() const;
virtual void setSndFile(SndFileR& sf);
- //virtual void read(unsigned offset, float** bpp, int channels, int nn, bool overwrite = true);
- //virtual void readAudio(unsigned /*offset*/, float** /*bpp*/, int /*channels*/, int /*nn*/, bool /*doSeek*/, bool /*overwrite*/);
virtual void readAudio(WavePart* /*part*/, unsigned /*offset*/, float** /*bpp*/, int /*channels*/, int /*nn*/, bool /*doSeek*/, bool /*overwrite*/);
void setTick(unsigned val);
diff --git a/muse2/muse/functions.cpp b/muse2/muse/functions.cpp
index 6fab2ee4..b47874fd 100644
--- a/muse2/muse/functions.cpp
+++ b/muse2/muse/functions.cpp
@@ -7,6 +7,7 @@
#include "functions.h"
#include "song.h"
+#include "undo.h"
#include "event.h"
#include "audio.h"
@@ -19,6 +20,7 @@
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/mman.h>
+#include <math.h>
#include <QMimeData>
#include <QByteArray>
@@ -26,7 +28,6 @@
#include <QMessageBox>
#include <QClipboard>
-
using namespace std;
GateTime* gatetime_dialog=NULL;
@@ -216,11 +217,10 @@ bool legato(const set<Part*>& parts)
bool modify_velocity(const set<Part*>& parts, int range, int rate, int offset)
{
map<Event*, Part*> events = get_events(parts, range);
+ Undo operations;
if ( (!events.empty()) && ((rate!=100) || (offset!=0)) )
{
- song->startUndo();
-
for (map<Event*, Part*>::iterator it=events.begin(); it!=events.end(); it++)
{
Event& event=*(it->first);
@@ -240,13 +240,11 @@ bool modify_velocity(const set<Part*>& parts, int range, int rate, int offset)
{
Event newEvent = event.clone();
newEvent.setVelo(velo);
- // Indicate no undo, and do not do port controller values and clone parts.
- audio->msgChangeEvent(event, newEvent, part, false, false, false);
+ operations.push_back(UndoOp(UndoOp::ModifyEvent, newEvent, event, part, false, false));
}
}
- song->endUndo(SC_EVENT_MODIFIED);
- return true;
+ return song->applyOperationGroup(operations);
}
else
return false;
@@ -255,11 +253,10 @@ bool modify_velocity(const set<Part*>& parts, int range, int rate, int offset)
bool modify_off_velocity(const set<Part*>& parts, int range, int rate, int offset)
{
map<Event*, Part*> events = get_events(parts, range);
+ Undo operations;
if ( (!events.empty()) && ((rate!=100) || (offset!=0)) )
{
- song->startUndo();
-
for (map<Event*, Part*>::iterator it=events.begin(); it!=events.end(); it++)
{
Event& event=*(it->first);
@@ -279,13 +276,11 @@ bool modify_off_velocity(const set<Part*>& parts, int range, int rate, int offse
{
Event newEvent = event.clone();
newEvent.setVeloOff(velo);
- // Indicate no undo, and do not do port controller values and clone parts.
- audio->msgChangeEvent(event, newEvent, part, false, false, false);
+ operations.push_back(UndoOp(UndoOp::ModifyEvent, newEvent, event, part, false, false));
}
}
-
- song->endUndo(SC_EVENT_MODIFIED);
- return true;
+
+ return song->applyOperationGroup(operations);
}
else
return false;
@@ -294,11 +289,10 @@ bool modify_off_velocity(const set<Part*>& parts, int range, int rate, int offse
bool modify_notelen(const set<Part*>& parts, int range, int rate, int offset)
{
map<Event*, Part*> events = get_events(parts, range);
+ Undo operations;
if ( (!events.empty()) && ((rate!=100) || (offset!=0)) )
{
- song->startUndo();
-
for (map<Event*, Part*>::iterator it=events.begin(); it!=events.end(); it++)
{
Event& event=*(it->first);
@@ -316,13 +310,11 @@ bool modify_notelen(const set<Part*>& parts, int range, int rate, int offset)
{
Event newEvent = event.clone();
newEvent.setLenTick(len);
- // Indicate no undo, and do not do port controller values and clone parts.
- audio->msgChangeEvent(event, newEvent, part, false, false, false);
+ operations.push_back(UndoOp(UndoOp::ModifyEvent, newEvent, event, part, false, false));
}
}
- song->endUndo(SC_EVENT_MODIFIED);
- return true;
+ return song->applyOperationGroup(operations);
}
else
return false;
@@ -358,7 +350,7 @@ unsigned quantize_tick(unsigned tick, unsigned raster, int swing)
bool quantize_notes(const set<Part*>& parts, int range, int raster, bool quant_len, int strength, int swing, int threshold)
{
map<Event*, Part*> events = get_events(parts, range);
- bool undo_started=false;
+ Undo operations;
if (!events.empty())
{
@@ -388,59 +380,50 @@ bool quantize_notes(const set<Part*>& parts, int range, int raster, bool quant_l
if ( (event.lenTick() != len) || (event.tick() + part->tick() != begin_tick) )
{
- if (!undo_started)
- {
- song->startUndo();
- undo_started=true;
- }
-
Event newEvent = event.clone();
newEvent.setTick(begin_tick - part->tick());
newEvent.setLenTick(len);
- // Indicate no undo, and do not do port controller values and clone parts.
- audio->msgChangeEvent(event, newEvent, part, false, false, false);
+ operations.push_back(UndoOp(UndoOp::ModifyEvent, newEvent, event, part, false, false));
}
}
- if (undo_started) song->endUndo(SC_EVENT_MODIFIED);
+ return song->applyOperationGroup(operations);
}
-
- return undo_started;
+ else
+ return false;
}
bool erase_notes(const set<Part*>& parts, int range, int velo_threshold, bool velo_thres_used, int len_threshold, bool len_thres_used)
{
map<Event*, Part*> events = get_events(parts, range);
+ Undo operations;
if (!events.empty())
{
- song->startUndo();
-
for (map<Event*, Part*>::iterator it=events.begin(); it!=events.end(); it++)
{
Event& event=*(it->first);
Part* part=it->second;
+
if ( (!velo_thres_used && !len_thres_used) ||
(velo_thres_used && event.velo() < velo_threshold) ||
(len_thres_used && int(event.lenTick()) < len_threshold) )
- audio->msgDeleteEvent(event, part, false, false, false);
+ operations.push_back(UndoOp(UndoOp::DeleteEvent, event, part, false, false));
}
- song->endUndo(SC_EVENT_REMOVED);
- return true;
+ return song->applyOperationGroup(operations);
}
else
return false;
}
-bool transpose_notes(const set<Part*>& parts, int range, signed int halftonesteps, bool do_undo)
+bool transpose_notes(const set<Part*>& parts, int range, signed int halftonesteps)
{
map<Event*, Part*> events = get_events(parts, range);
+ Undo operations;
if ( (!events.empty()) && (halftonesteps!=0) )
{
- if (do_undo) song->startUndo();
-
for (map<Event*, Part*>::iterator it=events.begin(); it!=events.end(); it++)
{
Event& event=*(it->first);
@@ -451,12 +434,10 @@ bool transpose_notes(const set<Part*>& parts, int range, signed int halftonestep
if (pitch > 127) pitch=127;
if (pitch < 0) pitch=0;
newEvent.setPitch(pitch);
- // Indicate no undo, and do not do port controller values and clone parts.
- audio->msgChangeEvent(event, newEvent, part, false, false, false);
+ operations.push_back(UndoOp(UndoOp::ModifyEvent, newEvent, event, part, false, false));
}
- if (do_undo) song->endUndo(SC_EVENT_MODIFIED);
- return do_undo;
+ return song->applyOperationGroup(operations);
}
else
return false;
@@ -465,14 +446,13 @@ bool transpose_notes(const set<Part*>& parts, int range, signed int halftonestep
bool crescendo(const set<Part*>& parts, int range, int start_val, int end_val, bool absolute)
{
map<Event*, Part*> events = get_events(parts, range);
+ Undo operations;
int from=song->lpos();
int to=song->rpos();
if ( (!events.empty()) && (to>from) )
{
- song->startUndo();
-
for (map<Event*, Part*>::iterator it=events.begin(); it!=events.end(); it++)
{
Event& event=*(it->first);
@@ -492,25 +472,22 @@ bool crescendo(const set<Part*>& parts, int range, int start_val, int end_val, b
if (velo > 127) velo=127;
if (velo <= 0) velo=1;
newEvent.setVelo(velo);
- // Indicate no undo, and do not do port controller values and clone parts.
- audio->msgChangeEvent(event, newEvent, part, false, false, false);
+ operations.push_back(UndoOp(UndoOp::ModifyEvent, newEvent, event, part, false, false));
}
- song->endUndo(SC_EVENT_MODIFIED);
- return true;
+ return song->applyOperationGroup(operations);
}
else
return false;
}
-bool move_notes(const set<Part*>& parts, int range, signed int ticks, bool do_undo) //TODO: clipping
+bool move_notes(const set<Part*>& parts, int range, signed int ticks) //TODO: clipping
{
map<Event*, Part*> events = get_events(parts, range);
+ Undo operations;
if ( (!events.empty()) && (ticks!=0) )
{
- if (do_undo) song->startUndo();
-
for (map<Event*, Part*>::iterator it=events.begin(); it!=events.end(); it++)
{
Event& event=*(it->first);
@@ -532,24 +509,22 @@ bool move_notes(const set<Part*>& parts, int range, signed int ticks, bool do_un
}
if (del==false)
- // Indicate no undo, and do not do port controller values and clone parts.
- audio->msgChangeEvent(event, newEvent, part, false, false, false);
+ operations.push_back(UndoOp(UndoOp::ModifyEvent, newEvent, event, part, false, false));
else
- // Indicate no undo, and do not do port controller values and clone parts.
- audio->msgDeleteEvent(event, part, false, false, false);
+ operations.push_back(UndoOp(UndoOp::DeleteEvent, event, part, false, false));
}
- if (do_undo) song->endUndo(SC_EVENT_MODIFIED);
- return do_undo;
+ return song->applyOperationGroup(operations);
}
else
return false;
}
+
bool delete_overlaps(const set<Part*>& parts, int range)
{
map<Event*, Part*> events = get_events(parts, range);
- bool undo_started=false;
+ Undo operations;
set<Event*> deleted_events;
@@ -576,17 +551,11 @@ bool delete_overlaps(const set<Part*>& parts, int range)
(event1.tick() <= event2.tick()) &&
(event1.endTick() > event2.tick()) ) //they overlap
{
- if (undo_started==false)
- {
- song->startUndo();
- undo_started=true;
- }
-
int new_len = event2.tick() - event1.tick();
if (new_len==0)
{
- audio->msgDeleteEvent(event1, part1, false, false, false);
+ operations.push_back(UndoOp(UndoOp::DeleteEvent, event1, part1, false, false));
deleted_events.insert(&event1);
}
else
@@ -594,22 +563,23 @@ bool delete_overlaps(const set<Part*>& parts, int range)
Event new_event1 = event1.clone();
new_event1.setLenTick(new_len);
- audio->msgChangeEvent(event1, new_event1, part1, false, false, false);
+ operations.push_back(UndoOp(UndoOp::ModifyEvent, new_event1, event1, part1, false, false));
}
}
}
}
}
- if (undo_started) song->endUndo(SC_EVENT_MODIFIED);
+ return song->applyOperationGroup(operations);
}
- return undo_started;
+ else
+ return false;
}
bool legato(const set<Part*>& parts, int range, int min_len, bool dont_shorten)
{
map<Event*, Part*> events = get_events(parts, range);
- bool undo_started=false;
+ Undo operations;
if (min_len<=0) min_len=1;
@@ -643,22 +613,17 @@ bool legato(const set<Part*>& parts, int range, int min_len, bool dont_shorten)
if (event1.lenTick() != len)
{
- if (undo_started==false)
- {
- song->startUndo();
- undo_started=true;
- }
-
Event new_event1 = event1.clone();
new_event1.setLenTick(len);
- audio->msgChangeEvent(event1, new_event1, part1, false, false, false);
+ operations.push_back(UndoOp(UndoOp::ModifyEvent, new_event1, event1, part1, false, false));
}
}
- if (undo_started) song->endUndo(SC_EVENT_MODIFIED);
+ return song->applyOperationGroup(operations);
}
- return undo_started;
+ else
+ return false;
}
@@ -749,6 +714,8 @@ QMimeData* selected_events_to_mime(const set<Part*>& parts, int range)
void paste_at(Part* dest_part, const QString& pt, int pos)
{
+ Undo operations;
+
Xml xml(pt.toLatin1().constData());
for (;;)
{
@@ -763,10 +730,8 @@ void paste_at(Part* dest_part, const QString& pt, int pos)
case Xml::TagStart:
if (tag == "eventlist")
{
- song->startUndo();
EventList el;
el.read(xml, "eventlist", true);
- int modified = SC_EVENT_INSERTED;
for (iEvent i = el.begin(); i != el.end(); ++i)
{
Event e = i->second;
@@ -774,7 +739,6 @@ void paste_at(Part* dest_part, const QString& pt, int pos)
if (tick<0)
{
printf("ERROR: trying to add event before current part!\n");
- song->endUndo(SC_EVENT_INSERTED);
goto end_of_paste_at;
}
@@ -786,18 +750,17 @@ void paste_at(Part* dest_part, const QString& pt, int pos)
Part* newPart = dest_part->clone();
newPart->setLenTick(newPart->lenTick()+diff);
// Indicate no undo, and do port controller values but not clone parts.
- audio->msgChangePart(dest_part, newPart, false, true, false);
- modified=modified|SC_PART_MODIFIED;
+ operations.push_back(UndoOp(UndoOp::ModifyPart,dest_part, newPart, true, false));
dest_part = newPart; // reassign TODO FINDME does this work, or has dest_part to be a nonconst reference?
}
// Indicate no undo, and do not do port controller values and clone parts.
- audio->msgAddEvent(e, dest_part, false, false, false);
+ operations.push_back(UndoOp(UndoOp::AddEvent,e, dest_part, false, false));
}
- song->endUndo(modified);
+ song->applyOperationGroup(operations);
goto end_of_paste_at;
}
else
- xml.unknown("pasteAt");
+ xml.unknown("paste_at");
break;
case Xml::Attribut:
@@ -869,6 +832,119 @@ void select_not_in_loop(const std::set<Part*>& parts)
}
+void shrink_parts(int raster)
+{
+ Undo operations;
+
+ unsigned min_len;
+ if (raster<0) raster=config.division;
+ if (raster>=0) min_len=raster; else min_len=config.division;
+
+ TrackList* tracks = song->tracks();
+ for (iTrack track = tracks->begin(); track != tracks->end(); track++)
+ for (iPart part = (*track)->parts()->begin(); part != (*track)->parts()->end(); part++)
+ if (part->second->selected())
+ {
+ EventList* events=part->second->events();
+ unsigned len=0;
+
+ for (iEvent ev=events->begin(); ev!=events->end(); ev++)
+ if (ev->second.endTick() > len)
+ len=ev->second.endTick();
+
+ if (raster) len=ceil((float)len/raster)*raster;
+ if (len<min_len) len=min_len;
+
+ if (len < part->second->lenTick())
+ {
+ MidiPart* new_part = new MidiPart(*(MidiPart*)part->second);
+ new_part->setLenTick(len);
+ operations.push_back(UndoOp(UndoOp::ModifyPart, part->second, new_part, true, false));
+ }
+ }
+
+ song->applyOperationGroup(operations);
+}
+
+void expand_parts(int raster)
+{
+ Undo operations;
+
+ unsigned min_len;
+ if (raster<0) raster=config.division;
+ if (raster>=0) min_len=raster; else min_len=config.division;
+
+ TrackList* tracks = song->tracks();
+ for (iTrack track = tracks->begin(); track != tracks->end(); track++)
+ for (iPart part = (*track)->parts()->begin(); part != (*track)->parts()->end(); part++)
+ if (part->second->selected())
+ {
+ EventList* events=part->second->events();
+ unsigned len=part->second->lenTick();
+
+ for (iEvent ev=events->begin(); ev!=events->end(); ev++)
+ if (ev->second.endTick() > len)
+ len=ev->second.endTick();
+
+ if (raster) len=ceil((float)len/raster)*raster;
+ if (len<min_len) len=min_len;
+
+ if (len > part->second->lenTick())
+ {
+ MidiPart* new_part = new MidiPart(*(MidiPart*)part->second);
+ new_part->setLenTick(len);
+ operations.push_back(UndoOp(UndoOp::ModifyPart, part->second, new_part, true, false));
+ }
+ }
+
+ song->applyOperationGroup(operations);
+}
+
+void clean_parts()
+{
+ Undo operations;
+ set<Part*> already_processed;
+
+ TrackList* tracks = song->tracks();
+ for (iTrack track = tracks->begin(); track != tracks->end(); track++)
+ for (iPart part = (*track)->parts()->begin(); part != (*track)->parts()->end(); part++)
+ if ((part->second->selected()) && (already_processed.find(part->second)==already_processed.end()))
+ {
+ // find out the length of the longest clone of this part;
+ // avoid processing eventlist multiple times (because of
+ // multiple clones)
+ unsigned len=0;
+
+ Part* part_it=part->second;
+ do
+ {
+ if (part_it->lenTick() > len)
+ len=part_it->lenTick();
+
+ already_processed.insert(part_it);
+ part_it=part_it->nextClone();
+ } while ((part_it!=part->second) && (part_it!=NULL));
+
+
+ // erase all events exceeding the longest clone of this part
+ // (i.e., erase all hidden events) or shorten them
+ EventList* el = part->second->events();
+ for (iEvent ev=el->begin(); ev!=el->end(); ev++)
+ if (ev->second.tick() >= len)
+ operations.push_back(UndoOp(UndoOp::DeleteEvent, ev->second, part->second, true, true));
+ else if (ev->second.endTick() > len)
+ {
+ Event new_event = ev->second.clone();
+ new_event.setLenTick(len - ev->second.tick());
+
+ operations.push_back(UndoOp(UndoOp::ModifyEvent, new_event, ev->second, part->second, true, true));
+ }
+ }
+
+ song->applyOperationGroup(operations);
+}
+
+
void read_function_dialog_config(Xml& xml)
{
if (erase_dialog==NULL)
diff --git a/muse2/muse/functions.h b/muse2/muse/functions.h
index 226c43f7..633457a9 100644
--- a/muse2/muse/functions.h
+++ b/muse2/muse/functions.h
@@ -51,8 +51,8 @@ bool quantize_notes(const std::set<Part*>& parts, int range, int raster, bool le
bool erase_notes(const std::set<Part*>& parts, int range, int velo_threshold=0, bool velo_thres_used=false, int len_threshold=0, bool len_thres_used=false);
bool delete_overlaps(const std::set<Part*>& parts, int range);
bool set_notelen(const std::set<Part*>& parts, int range, int len);
-bool move_notes(const std::set<Part*>& parts, int range, signed int ticks, bool do_undo=true);
-bool transpose_notes(const std::set<Part*>& parts, int range, signed int halftonesteps, bool do_undo=true);
+bool move_notes(const std::set<Part*>& parts, int range, signed int ticks);
+bool transpose_notes(const std::set<Part*>& parts, int range, signed int halftonesteps);
bool crescendo(const std::set<Part*>& parts, int range, int start_val, int end_val, bool absolute);
bool legato(const std::set<Part*>& parts, int range, int min_len=1, bool dont_shorten=false);
@@ -84,6 +84,11 @@ void select_invert(const std::set<Part*>& parts);
void select_in_loop(const std::set<Part*>& parts);
void select_not_in_loop(const std::set<Part*>& parts);
+//functions for parts
+void shrink_parts(int raster=-1); //negative values mean "config.division"
+void expand_parts(int raster=-1);
+void clean_parts();
+
//functions for reading and writing default values
class Xml;
void read_function_dialog_config(Xml& xml);
diff --git a/muse2/muse/keyevent.cpp b/muse2/muse/keyevent.cpp
index 865aef01..5d55fef6 100644
--- a/muse2/muse/keyevent.cpp
+++ b/muse2/muse/keyevent.cpp
@@ -18,15 +18,15 @@
KeyList keymap;
+#define DEFAULT_KEY KEY_C
+
//---------------------------------------------------------
// KeyList
//---------------------------------------------------------
KeyList::KeyList()
{
- _key = KEY_C;
- insert(std::pair<const unsigned, KeyEvent> (MAX_TICK+1, KeyEvent(_key, 0)));
- useList = true;
+ insert(std::pair<const unsigned, KeyEvent> (MAX_TICK+1, KeyEvent(DEFAULT_KEY, 0)));
}
//---------------------------------------------------------
@@ -71,7 +71,7 @@ void KeyList::dump() const
void KeyList::clear()
{
KEYLIST::clear();
- insert(std::pair<const unsigned, KeyEvent> (MAX_TICK+1, KeyEvent(_key, 0)));
+ insert(std::pair<const unsigned, KeyEvent> (MAX_TICK+1, KeyEvent(DEFAULT_KEY, 0)));
}
//---------------------------------------------------------
@@ -80,16 +80,12 @@ void KeyList::clear()
key_enum KeyList::keyAtTick(unsigned tick) const
{
- if (useList) {
ciKeyEvent i = upper_bound(tick);
if (i == end()) {
printf("no key at tick %d,0x%x\n", tick, tick);
- return _key;
+ return DEFAULT_KEY;
}
return i->second.key;
- }
- else
- return _key;
}
//---------------------------------------------------------
@@ -129,20 +125,6 @@ void KeyList::change(unsigned tick, key_enum newkey)
e->second.key = newkey;
}
-//---------------------------------------------------------
-// setKey
-// called from transport window
-// & slave mode key changes
-//---------------------------------------------------------
-
-//void KeyList::setKey(unsigned tick, int newkey)
-// {
-// if (useList)
-// add(tick, newkey);
-// else
-// _key = newkey;
-// ++_keySN;
-// }
//---------------------------------------------------------
// addKey
@@ -162,29 +144,6 @@ void KeyList::delKey(unsigned tick)
del(tick);
}
-//---------------------------------------------------------
-// changeKey
-//---------------------------------------------------------
-
-//void KeyList::changeKey(unsigned tick, int newkey)
-// {
-// change(tick, newkey);
-// ++_keySN;
-// }
-
-//---------------------------------------------------------
-// setMasterFlag
-//---------------------------------------------------------
-
-bool KeyList::setMasterFlag(unsigned /*tick*/, bool val)
- {
- if (useList != val) {
- useList = val;
- return true;
- }
- return false;
- }
-
//---------------------------------------------------------
@@ -193,7 +152,6 @@ bool KeyList::setMasterFlag(unsigned /*tick*/, bool val)
void KeyList::write(int level, Xml& xml) const
{
- xml.put(level++, "<keylist fix=\"%d\">", _key);
for (ciKeyEvent i = begin(); i != end(); ++i)
i->second.write(level, xml, i->first);
xml.tag(level, "/keylist");
@@ -225,8 +183,6 @@ void KeyList::read(Xml& xml)
xml.unknown("keyList");
break;
case Xml::Attribut:
- if (tag == "fix")
- _key = key_enum(xml.s2().toInt());
break;
case Xml::TagEnd:
if (tag == "keylist") {
diff --git a/muse2/muse/keyevent.h b/muse2/muse/keyevent.h
index 4a7fc8f9..2d127a67 100644
--- a/muse2/muse/keyevent.h
+++ b/muse2/muse/keyevent.h
@@ -78,9 +78,6 @@ typedef KEYLIST::const_reverse_iterator criKeyEvent;
class KeyList : public KEYLIST {
- bool useList;
- key_enum _key; // key if not using key list
-
void add(unsigned tick, key_enum tempo);
void change(unsigned tick, key_enum newKey);
void del(iKeyEvent);
@@ -99,8 +96,6 @@ class KeyList : public KEYLIST {
void addKey(unsigned t, key_enum newKey);
void delKey(unsigned tick);
-// void changeKey(unsigned tick, key_enum newKey);
- bool setMasterFlag(unsigned tick, bool val);
};
extern KeyList keymap;
diff --git a/muse2/muse/liste/listedit.cpp b/muse2/muse/liste/listedit.cpp
index 080ee01c..5f73a3ba 100644
--- a/muse2/muse/liste/listedit.cpp
+++ b/muse2/muse/liste/listedit.cpp
@@ -852,7 +852,7 @@ void ListEdit::cmd(int cmd)
bool found = false;
for (int row = 0; row < liste->topLevelItemCount(); ++row)
{
- QTreeWidgetItem* i = liste->topLevelItem(row);
+ QTreeWidgetItem* i = liste->topLevelItem(row);
EventListItem *item = (EventListItem *) i;
if (i->isSelected() || item->event.selected())
{
@@ -862,7 +862,8 @@ void ListEdit::cmd(int cmd)
}
if(!found)
break;
- song->startUndo();
+
+ Undo operations;
EventListItem *deletedEvent=NULL;
for (int row = 0; row < liste->topLevelItemCount(); ++row) {
@@ -871,8 +872,8 @@ void ListEdit::cmd(int cmd)
if (i->isSelected() || item->event.selected()) {
deletedEvent=item;
- // Indicate no undo, and do port controller values and clone parts.
- audio->msgDeleteEvent(item->event, item->part, false, true, true);
+ // Port controller values and clone parts.
+ operations.push_back(UndoOp(UndoOp::DeleteEvent,item->event, item->part, true, true));
}
}
@@ -895,9 +896,8 @@ void ListEdit::cmd(int cmd)
}
}
selectedTick=nextTick;
- song->endUndo(SC_EVENT_MODIFIED);
- //printf("selected tick = %d\n", selectedTick);
- //emit selectionChanged();
+
+ song->applyOperationGroup(operations);
break;
}
}
diff --git a/muse2/muse/midiedit/dcanvas.cpp b/muse2/muse/midiedit/dcanvas.cpp
index 89cb1e4c..92e514af 100644
--- a/muse2/muse/midiedit/dcanvas.cpp
+++ b/muse2/muse/midiedit/dcanvas.cpp
@@ -100,14 +100,14 @@ DrumCanvas::DrumCanvas(MidiEditor* pr, QWidget* parent, int sx,
// moveCanvasItems
//---------------------------------------------------------
-void DrumCanvas::moveCanvasItems(CItemList& items, int dp, int dx, DragType dtype, int* pflags)
+Undo DrumCanvas::moveCanvasItems(CItemList& items, int dp, int dx, DragType dtype)
{
if(editor->parts()->empty())
- return;
+ return Undo(); //return empty list
PartsToChangeMap parts2change;
+ Undo operations;
- int modified = 0;
for(iPart ip = editor->parts()->begin(); ip != editor->parts()->end(); ++ip)
{
Part* part = ip->second;
@@ -143,34 +143,6 @@ void DrumCanvas::moveCanvasItems(CItemList& items, int dp, int dx, DragType dtyp
if(npartoffset > 0)
{
- // Create new part...
- // if there are several events that are moved outside the part, it will be recreated for each
- // so the part _in_ the event will not be valid, ask the authority.
-// Part* newPart = part->clone();
- //Part* newPart = Canvas::part()->clone();
-
-// newPart->setLenTick(newPart->lenTick() + npartoffset);
- //audio->msgChangePart(part, newPart,false);
-
-// modified = SC_PART_MODIFIED;
-
- // BUG FIX: #1650953
- // Added by T356.
- // Fixes posted "select and drag past end of part - crashing" bug
-// for(iPart ip = editor->parts()->begin(); ip != editor->parts()->end(); ++ip)
-// {
-// if(ip->second == part)
-// {
-// editor->parts()->erase(ip);
-// break;
-// }
-// }
-
-// editor->parts()->add(newPart);
-// audio->msgChangePart(part, newPart,false);
-
-// if(parts2change.find(part) == parts2change.end())
-// parts2change.insert(std::pair<Part*, Part*> (part, newPart));
iPartToChange ip2c = parts2change.find(part);
if(ip2c == parts2change.end())
{
@@ -179,14 +151,6 @@ void DrumCanvas::moveCanvasItems(CItemList& items, int dp, int dx, DragType dtyp
}
else
ip2c->second.xdiff = npartoffset;
-
-
- //part = newPart; // reassign
- //item->setPart(part);
- //item->setEvent(newEvent);
- //curPart = part;
- //curPartId = curPart->sn();
-
}
}
@@ -199,8 +163,6 @@ void DrumCanvas::moveCanvasItems(CItemList& items, int dp, int dx, DragType dtyp
newPart->setLenTick(newPart->lenTick() + diff);
- modified = SC_PART_MODIFIED;
-
// BUG FIX: #1650953
// Added by T356.
// Fixes posted "select and drag past end of part - crashing" bug
@@ -214,9 +176,8 @@ void DrumCanvas::moveCanvasItems(CItemList& items, int dp, int dx, DragType dtyp
}
editor->parts()->add(newPart);
- // Indicate no undo, and do port controller values but not clone parts.
- //audio->msgChangePart(opart, newPart, false);
- audio->msgChangePart(opart, newPart, false, true, false);
+ // Do port controller values but not clone parts.
+ operations.push_back(UndoOp(UndoOp::ModifyPart, opart, newPart, true, false));
ip2c->second.npart = newPart;
@@ -256,21 +217,12 @@ void DrumCanvas::moveCanvasItems(CItemList& items, int dp, int dx, DragType dtyp
break;
// Do not process if the event has already been processed (meaning it's an event in a clone part)...
- //if(moveItem(ci, newpos, dtype))
- if(idl != doneList.end())
- // Just move the canvas item.
- ci->move(newpos);
- else
+ if (idl == doneList.end())
{
- // Currently moveItem always returns true.
- if(moveItem(ci, newpos, dtype))
- {
- // Add the canvas item to the list of done items.
- doneList.push_back(ci);
- // Move the canvas item.
- ci->move(newpos);
- }
+ operations.push_back(moveItem(ci, newpos, dtype));
+ doneList.push_back(ci);
}
+ ci->move(newpos);
if(moving.size() == 1) {
itemReleased(curItem, newpos);
@@ -279,22 +231,17 @@ void DrumCanvas::moveCanvasItems(CItemList& items, int dp, int dx, DragType dtyp
selectItem(ci, false);
}
- if(pflags)
- *pflags = modified;
+ return operations;
}
//---------------------------------------------------------
// moveItem
//---------------------------------------------------------
-// Changed by T356.
-//bool DrumCanvas::moveItem(CItem* item, const QPoint& pos, DragType dtype, int* pflags)
-bool DrumCanvas::moveItem(CItem* item, const QPoint& pos, DragType dtype)
+UndoOp DrumCanvas::moveItem(CItem* item, const QPoint& pos, DragType dtype)
{
DEvent* nevent = (DEvent*) item;
- // Changed by T356.
- //MidiPart* part = (MidiPart*)Canvas::part(); // part can be dynamically recreated, ask the authority
MidiPart* part = (MidiPart*)nevent->part();
Event event = nevent->event();
@@ -310,40 +257,6 @@ bool DrumCanvas::moveItem(CItem* item, const QPoint& pos, DragType dtype)
newEvent.setPitch(npitch);
newEvent.setTick(ntick);
- // Removed by T356.
- /*
- // Added by T356.
- int modified = 0;
- //song->startUndo();
- int diff = newEvent.endTick()-part->lenTick();
- if (diff > 0) // too short part? extend it
- {
- // if there are several events that are moved outside the part, it will be recreated for each
- // so the part _in_ the event will not be valid, ask the authority.
- //Part* newPart = part->clone();
- MidiPart* newPart = (MidiPart*)Canvas::part()->clone();
- newPart->setLenTick(newPart->lenTick()+diff);
- audio->msgChangePart(Canvas::part(), newPart,false);
-
- modified = SC_PART_MODIFIED;
- part = newPart; // reassign
- for(iPart i = editor->parts()->begin(); i != editor->parts()->end(); ++i)
- {
- if(i->second == Canvas::part())
- {
- editor->parts()->erase(i);
- break;
- }
- }
- editor->parts()->add(part);
- item->setPart(part);
- item->setEvent(newEvent);
- curPart = part;
- curPartId = curPart->sn();
- }
- */
-
- // Added by T356.
// msgAddEvent and msgChangeEvent (below) will set these, but set them here first?
//item->setPart(part);
item->setEvent(newEvent);
@@ -352,22 +265,10 @@ bool DrumCanvas::moveItem(CItem* item, const QPoint& pos, DragType dtype)
if(((int)newEvent.endTick() - (int)part->lenTick()) > 0)
printf("DrumCanvas::moveItem Error! New event end:%d exceeds length:%d of part:%s\n", newEvent.endTick(), part->lenTick(), part->name().toLatin1().constData());
- if (dtype == MOVE_COPY || dtype == MOVE_CLONE) {
- // Indicate no undo, and do not do port controller values and clone parts.
- //audio->msgAddEvent(newEvent, part, false);
- audio->msgAddEvent(newEvent, part, false, false, false);
- }
- else {
- // Indicate no undo, and do not do port controller values and clone parts.
- //audio->msgChangeEvent(event, newEvent, part, false);
- audio->msgChangeEvent(event, newEvent, part, false, false, false);
- }
-
- // Removed by T356.
- //if(pflags)
- // *pflags = modified;
-
- return true;
+ if (dtype == MOVE_COPY || dtype == MOVE_CLONE)
+ return UndoOp(UndoOp::AddEvent, newEvent, part, false, false);
+ else
+ return UndoOp(UndoOp::ModifyEvent, newEvent, event, part, false, false);
}
//---------------------------------------------------------
@@ -412,7 +313,6 @@ void DrumCanvas::resizeItem(CItem* item, bool)
DEvent* nevent = (DEvent*) item;
Event ev = nevent->event();
// Indicate do undo, and do not do port controller values and clone parts.
- //audio->msgDeleteEvent(ev, nevent->part());
audio->msgDeleteEvent(ev, nevent->part(), true, false, false);
}
@@ -431,7 +331,6 @@ void DrumCanvas::newItem(CItem* item, bool noSnap, bool replace)
if (!noSnap)
x = editor->rasterVal(x);
event.setTick(x - nevent->part()->tick());
- //int npitch = drumMap[y2pitch(item->y())].enote;
int npitch = event.pitch();
event.setPitch(npitch);
@@ -451,7 +350,6 @@ void DrumCanvas::newItem(CItem* item, bool noSnap, bool replace)
if (ev.pitch() == npitch) {
// Indicate do undo, and do not do port controller values and clone parts.
- //audio->msgDeleteEvent(ev, nevent->part());
audio->msgDeleteEvent(ev, nevent->part(), true, false, false);
if (replace)
break;
@@ -470,16 +368,13 @@ void DrumCanvas::newItem(CItem* item, bool noSnap, bool replace)
Part* newPart = part->clone();
newPart->setLenTick(newPart->lenTick()+diff);
// Indicate no undo, and do port controller values but not clone parts.
- //audio->msgChangePart(part, newPart,false);
audio->msgChangePart(part, newPart, false, true, false);
modified=modified|SC_PART_MODIFIED;
part = newPart; // reassign
}
// Indicate no undo, and do not do port controller values and clone parts.
- //audio->msgAddEvent(event, part,false);
audio->msgAddEvent(event, part, false, false, false);
song->endUndo(modified);
-
}
//---------------------------------------------------------
@@ -490,7 +385,6 @@ bool DrumCanvas::deleteItem(CItem* item)
{
Event ev = ((DEvent*)item)->event();
// Indicate do undo, and do not do port controller values and clone parts.
- //audio->msgDeleteEvent(ev, ((DEvent*)item)->part());
audio->msgDeleteEvent(ev, ((DEvent*)item)->part(), true, false, false);
return false;
}
@@ -559,10 +453,6 @@ void DrumCanvas::drawItem(QPainter&p, const CItem*item, const QRect& rect)
void DrumCanvas::drawMoving(QPainter& p, const CItem* item, const QRect& rect)
{
- //if(((DEvent*)item)->part() != curPart)
- // return;
- //if(!item->isMoving())
- // return;
QPolygon pa(4);
QPoint pt = map(item->mp());
int x = pt.x();
@@ -745,7 +635,6 @@ void DrumCanvas::cmd(int cmd)
Event newEvent = event.clone();
newEvent.setLenTick(drumMap[event.pitch()].len);
// Indicate no undo, and do not do port controller values and clone parts.
- //audio->msgChangeEvent(event, newEvent, devent->part() , false);
audio->msgChangeEvent(event, newEvent, devent->part(), false, false, false);
}
}
@@ -785,8 +674,6 @@ void DrumCanvas::cmd(int cmd)
case CMD_RIGHT_NOSNAP:
{
Pos p(pos[0] + editor->rasterStep(pos[0]), true);
- //if (p > part->tick())
- // p = part->tick();
song->setPos(0, p, true, true, true); //CDW
}
break;
@@ -796,7 +683,6 @@ void DrumCanvas::cmd(int cmd)
}
-
//---------------------------------------------------------
// startDrag
//---------------------------------------------------------
@@ -806,10 +692,6 @@ void DrumCanvas::startDrag(CItem* /* item*/, bool copymode)
QMimeData* md = selected_events_to_mime(partlist_to_set(editor->parts()), 1);
if (md) {
-// QApplication::clipboard()->setData(drag, QClipboard::Clipboard); // This line NOT enabled in muse-1
- //QApplication::clipboard()->setMimeData(md); // TODO CHECK Tim.
- //QApplication::clipboard()->setMimeData(drag->mimeData()); //
-
// "Note that setMimeData() assigns ownership of the QMimeData object to the QDrag object.
// The QDrag must be constructed on the heap with a parent QWidget to ensure that Qt can
// clean up after the drag and drop operation has been completed. "
@@ -848,6 +730,7 @@ void DrumCanvas::dragLeaveEvent(QDragLeaveEvent*)
{
}
+
//---------------------------------------------------------
// keyPressed - called from DList
//---------------------------------------------------------
@@ -890,13 +773,7 @@ void DrumCanvas::keyReleased(int index, bool)
void DrumCanvas::mapChanged(int spitch, int dpitch)
{
- //TODO: Circumvent undo behaviour, since this isn't really a true change of the events,
- // but merely a change in pitch because the pitch relates to the order of the dlist.
- // Right now the sequencer spits out internalError: undoOp without startUndo() if start/stopundo is there, which is misleading
- // If start/stopundo is there, undo misbehaves since it doesn't undo but messes things up
- // Other solution: implement a specific undo-event for this (SC_DRUMMAP_MODIFIED or something) which undoes movement of
- // dlist-items (ml)
-
+ Undo operations;
std::vector< std::pair<Part*, Event*> > delete_events;
std::vector< std::pair<Part*, Event> > add_events;
@@ -951,16 +828,10 @@ void DrumCanvas::mapChanged(int spitch, int dpitch)
}
}
- song->startUndo();
for (idel_ev i = delete_events.begin(); i != delete_events.end(); i++) {
- //std::pair<Part*, Event*> pair = *i;
- //Part* thePart = pair.first;
- //Event* theEvent = pair.second;
Part* thePart = (*i).first;
Event* theEvent = (*i).second;
- // Indicate no undo, and do port controller values but not clone parts.
- //audio->msgDeleteEvent(*theEvent, thePart, false);
- audio->msgDeleteEvent(*theEvent, thePart, false, true, false);
+ operations.push_back(UndoOp(UndoOp::DeleteEvent, *theEvent, thePart, true, false));
}
DrumMap dm = drumMap[spitch];
@@ -972,18 +843,13 @@ void DrumCanvas::mapChanged(int spitch, int dpitch)
drumOutmap[int(drumMap[int(dpitch)].anote)] = dpitch;
for (iadd_ev i = add_events.begin(); i != add_events.end(); i++) {
- //std::pair<Part*, Event> pair = *i;
- //Part* thePart = pair.first;
- //Event& theEvent = pair.second;
Part* thePart = (*i).first;
Event& theEvent = (*i).second;
- // Indicate no undo, and do port controller values but not clone parts.
- //audio->msgAddEvent(theEvent, thePart, false);
- audio->msgAddEvent(theEvent, thePart, false, true, false);
+ operations.push_back(UndoOp(UndoOp::AddEvent, theEvent, thePart, true, false));
}
- song->endUndo(SC_EVENT_MODIFIED);
- song->update(SC_DRUMMAP);
+ song->applyOperationGroup(operations, false); // do not indicate undo
+ song->update(SC_DRUMMAP); //this update is neccessary, as it's not handled by applyOperationGroup()
}
//---------------------------------------------------------
@@ -1027,40 +893,12 @@ void DrumCanvas::modifySelected(NoteInfo::ValType type, int delta)
}
break;
case NoteInfo::VAL_LEN:
- /*
- {
- int len = event.lenTick() + delta;
- if (len < 1)
- len = 1;
- newEvent.setLenTick(len);
- }
- */
printf("DrumCanvas::modifySelected - NoteInfo::VAL_LEN not implemented\n");
break;
case NoteInfo::VAL_VELON:
- /*
- {
- int velo = event->velo() + delta;
- if (velo > 127)
- velo = 127;
- else if (velo < 0)
- velo = 0;
- newEvent.setVelo(velo);
- }
- */
printf("DrumCanvas::modifySelected - NoteInfo::VAL_VELON not implemented\n");
break;
case NoteInfo::VAL_VELOFF:
- /*
- {
- int velo = event.veloOff() + delta;
- if (velo > 127)
- velo = 127;
- else if (velo < 0)
- velo = 0;
- newEvent.setVeloOff(velo);
- }
- */
printf("DrumCanvas::modifySelected - NoteInfo::VAL_VELOFF not implemented\n");
break;
case NoteInfo::VAL_PITCH:
@@ -1076,8 +914,7 @@ void DrumCanvas::modifySelected(NoteInfo::ValType type, int delta)
}
song->changeEvent(event, newEvent, part);
// Indicate do not do port controller values and clone parts.
- //song->undoOp(UndoOp::ModifyEvent, newEvent, event, part);
- song->undoOp(UndoOp::ModifyEvent, newEvent, event, part, false, false);
+ song->addUndo(UndoOp(UndoOp::ModifyEvent, newEvent, event, part, false, false));
}
song->endUndo(SC_EVENT_MODIFIED);
audio->msgIdle(false);
diff --git a/muse2/muse/midiedit/dcanvas.h b/muse2/muse/midiedit/dcanvas.h
index fa087343..868113a6 100644
--- a/muse2/muse/midiedit/dcanvas.h
+++ b/muse2/muse/midiedit/dcanvas.h
@@ -54,10 +54,8 @@ class DrumCanvas : public EventCanvas {
virtual void drawItem(QPainter&, const CItem*, const QRect&);
void drawTopItem(QPainter& p, const QRect& rect);
virtual void drawMoving(QPainter&, const CItem*, const QRect&);
- virtual void moveCanvasItems(CItemList&, int, int, DragType, int*);
- // Changed by T356.
- //virtual bool moveItem(CItem*, const QPoint&, DragType, int*);
- virtual bool moveItem(CItem*, const QPoint&, DragType);
+ virtual Undo moveCanvasItems(CItemList&, int, int, DragType);
+ virtual UndoOp moveItem(CItem*, const QPoint&, DragType);
virtual CItem* newItem(const QPoint&, int);
virtual void resizeItem(CItem*, bool);
virtual void newItem(CItem*, bool);
diff --git a/muse2/muse/midiedit/dlist.cpp b/muse2/muse/midiedit/dlist.cpp
index ab2ed230..66922e83 100644
--- a/muse2/muse/midiedit/dlist.cpp
+++ b/muse2/muse/midiedit/dlist.cpp
@@ -47,7 +47,6 @@ void DList::draw(QPainter& p, const QRect& rect)
if (yy > y + h)
break;
DrumMap* dm = &drumMap[i];
-// if (dm->selected)
if (dm == currentlySelected)
p.fillRect(x, yy, w, TH, Qt::yellow);
// else
@@ -56,13 +55,11 @@ void DList::draw(QPainter& p, const QRect& rect)
for (int k = 0; k < h->count(); ++k) {
int x = h->sectionPosition(k);
int w = h->sectionSize(k);
- ///QRect r = p.xForm(QRect(x+2, yy, w-4, TH));
QRect r = p.combinedTransform().mapRect(QRect(x+2, yy, w-4, TH));
QString s;
int align = Qt::AlignVCenter | Qt::AlignHCenter;
p.save();
- ///p.setWorldXForm(false);
p.setWorldMatrixEnabled(false);
switch (k) {
case COL_VOL:
@@ -145,16 +142,13 @@ void DList::draw(QPainter& p, const QRect& rect)
// vertical Lines
//---------------------------------------------------
- ///p.setWorldXForm(false);
p.setWorldMatrixEnabled(false);
int n = header->count();
x = 0;
for (int i = 0; i < n; i++) {
- //x += header->sectionSize(i);
x += header->sectionSize(header->visualIndex(i));
p.drawLine(x, 0, x, height());
}
- ///p.setWorldXForm(true);
p.setWorldMatrixEnabled(true);
}
@@ -174,7 +168,6 @@ void DList::devicesPopupMenu(DrumMap* t, int x, int y, bool changeAll)
if(n != t->port)
{
audio->msgIdle(true);
- //audio->msgRemapPortDrumCtlEvents(getSelectedInstrument(), -1, -1, n);
song->remapPortDrumCtrlEvents(getSelectedInstrument(), -1, -1, n);
audio->msgIdle(false);
t->port = n;
@@ -184,13 +177,11 @@ void DList::devicesPopupMenu(DrumMap* t, int x, int y, bool changeAll)
else {
audio->msgIdle(true);
// Delete all port controller events.
- //audio->msgChangeAllPortDrumCtrlEvents(false);
song->changeAllPortDrumCtrlEvents(false);
for (int i = 0; i < DRUM_MAPSIZE; i++)
drumMap[i].port = n;
// Add all port controller events.
- //audio->msgChangeAllPortDrumCtrlEvents(true);
song->changeAllPortDrumCtrlEvents(true);
audio->msgIdle(false);
@@ -323,13 +314,11 @@ void DList::viewMousePressEvent(QMouseEvent* ev)
if (ev->modifiers() & Qt::ControlModifier) {
audio->msgIdle(true);
// Delete all port controller events.
- //audio->msgChangeAllPortDrumCtrlEvents(false);
song->changeAllPortDrumCtrlEvents(false, true);
for (int i = 0; i < DRUM_MAPSIZE; i++)
drumMap[i].channel = val;
// Add all port controller events.
- //audio->msgChangeAllPortDrumCtrlEvents(true);
song->changeAllPortDrumCtrlEvents(true, true);
audio->msgIdle(false);
song->update(SC_DRUMMAP);
@@ -339,7 +328,6 @@ void DList::viewMousePressEvent(QMouseEvent* ev)
if(val != dm->channel)
{
audio->msgIdle(true);
- //audio->msgRemapPortDrumCtlEvents(pitch, -1, val, -1);
song->remapPortDrumCtrlEvents(pitch, -1, val, -1);
audio->msgIdle(false);
dm->channel = val;
@@ -397,7 +385,6 @@ void DList::viewMouseDoubleClickEvent(QMouseEvent* ev)
{
int x = ev->x();
int y = ev->y();
-// int button = ev->button();
unsigned pitch = y / TH;
int section = header->logicalIndexAt(x);
@@ -474,7 +461,6 @@ void DList::lineEdit(int line, int section)
break;
}
- // editor->setText(dm->name);
editor->end(false);
editor->setGeometry(colx, coly, colw, colh);
// In all cases but the column name, select all text:
@@ -738,7 +724,7 @@ DList::DList(QHeaderView* h, QWidget* parent, int ymag)
{
setBg(Qt::white);
if (!h){
- h = new QHeaderView(Qt::Horizontal, parent);}
+ h = new QHeaderView(Qt::Horizontal, parent);}
header = h;
scroll = 0;
//ORCAN- CHECK if really needed: header->setTracking(true);
@@ -761,8 +747,6 @@ DList::DList(QHeaderView* h, QWidget* parent, int ymag)
DList::~DList()
{
-// if (currentlySelected != 0)
-// currentlySelected->selected = false; //Reset the global thingie
}
//---------------------------------------------------------
diff --git a/muse2/muse/midiedit/ecanvas.cpp b/muse2/muse/midiedit/ecanvas.cpp
index d41a383c..ef47e0d6 100644
--- a/muse2/muse/midiedit/ecanvas.cpp
+++ b/muse2/muse/midiedit/ecanvas.cpp
@@ -102,25 +102,6 @@ QPoint EventCanvas::raster(const QPoint& p) const
}
//---------------------------------------------------------
-// startUndo
-//---------------------------------------------------------
-
-void EventCanvas::startUndo(DragType)
- {
- song->startUndo();
- }
-
-//---------------------------------------------------------
-// endUndo
-//---------------------------------------------------------
-
-void EventCanvas::endUndo(DragType dtype, int flags)
- {
- song->endUndo(flags | ((dtype == MOVE_COPY || dtype == MOVE_CLONE)
- ? SC_EVENT_INSERTED : SC_EVENT_MODIFIED));
- }
-
-//---------------------------------------------------------
// mouseMove
//---------------------------------------------------------
@@ -414,3 +395,30 @@ void EventCanvas::viewDropEvent(QDropEvent* event)
}
}
+
+//---------------------------------------------------------
+// endMoveItems
+// dir = 0 move in all directions
+// 1 move only horizontal
+// 2 move only vertical
+//---------------------------------------------------------
+
+void EventCanvas::endMoveItems(const QPoint& pos, DragType dragtype, int dir)
+ {
+ int dp = y2pitch(pos.y()) - y2pitch(Canvas::start.y());
+ int dx = pos.x() - Canvas::start.x();
+
+ if (dir == 1)
+ dp = 0;
+ else if (dir == 2)
+ dx = 0;
+
+
+
+ Undo operations = moveCanvasItems(moving, dp, dx, dragtype);
+ song->applyOperationGroup(operations);
+
+ moving.clear();
+ updateSelection();
+ redraw();
+ }
diff --git a/muse2/muse/midiedit/ecanvas.h b/muse2/muse/midiedit/ecanvas.h
index 0ae970ab..b847f0f9 100644
--- a/muse2/muse/midiedit/ecanvas.h
+++ b/muse2/muse/midiedit/ecanvas.h
@@ -38,12 +38,7 @@ class EventCanvas : public Canvas {
Q_OBJECT
virtual void leaveEvent(QEvent*e);
virtual void enterEvent(QEvent*e);
- // Removed by T356.
- //virtual QPoint raster(const QPoint&) const;
- virtual void startUndo(DragType);
-
- virtual void endUndo(DragType, int flags = 0);
virtual void mouseMove(QMouseEvent* event);
protected:
@@ -58,6 +53,9 @@ class EventCanvas : public Canvas {
virtual void addItem(Part*, Event&) = 0;
// Added by T356.
virtual QPoint raster(const QPoint&) const;
+ virtual Undo moveCanvasItems(CItemList&, int, int, DragType) = 0;
+ virtual UndoOp moveItem(CItem*, const QPoint&, DragType) = 0;
+ virtual void endMoveItems(const QPoint&, DragType, int dir);
public slots:
void redrawGrid() { redraw(); }
diff --git a/muse2/muse/midiedit/prcanvas.cpp b/muse2/muse/midiedit/prcanvas.cpp
index 4e81b2e9..091582ef 100644
--- a/muse2/muse/midiedit/prcanvas.cpp
+++ b/muse2/muse/midiedit/prcanvas.cpp
@@ -38,6 +38,8 @@
#include "audio.h"
#include "functions.h"
+#define CHORD_TIMEOUT 75
+
//---------------------------------------------------------
// NEvent
//---------------------------------------------------------
@@ -254,14 +256,14 @@ void PianoCanvas::viewMouseDoubleClickEvent(QMouseEvent* event)
// moveCanvasItems
//---------------------------------------------------------
-void PianoCanvas::moveCanvasItems(CItemList& items, int dp, int dx, DragType dtype, int* pflags)
+Undo PianoCanvas::moveCanvasItems(CItemList& items, int dp, int dx, DragType dtype)
{
if(editor->parts()->empty())
- return;
-
+ return Undo(); //return empty list
+
+ Undo operations;
PartsToChangeMap parts2change;
- int modified = 0;
for(iPart ip = editor->parts()->begin(); ip != editor->parts()->end(); ++ip)
{
Part* part = ip->second;
@@ -297,34 +299,6 @@ void PianoCanvas::moveCanvasItems(CItemList& items, int dp, int dx, DragType dty
if(npartoffset > 0)
{
- // Create new part...
- // if there are several events that are moved outside the part, it will be recreated for each
- // so the part _in_ the event will not be valid, ask the authority.
-// Part* newPart = part->clone();
- //Part* newPart = Canvas::part()->clone();
-
-// newPart->setLenTick(newPart->lenTick() + npartoffset);
- //audio->msgChangePart(part, newPart,false);
-
-// modified = SC_PART_MODIFIED;
-
- // BUG FIX: #1650953
- // Added by T356.
- // Fixes posted "select and drag past end of part - crashing" bug
-// for(iPart ip = editor->parts()->begin(); ip != editor->parts()->end(); ++ip)
-// {
-// if(ip->second == part)
-// {
-// editor->parts()->erase(ip);
-// break;
-// }
-// }
-
-// editor->parts()->add(newPart);
-// audio->msgChangePart(part, newPart,false);
-
- //if(parts2change.find(part) == parts2change.end())
- // parts2change.insert(std::pair<Part*, Part*> (part, newPart));
iPartToChange ip2c = parts2change.find(part);
if(ip2c == parts2change.end())
{
@@ -333,13 +307,6 @@ void PianoCanvas::moveCanvasItems(CItemList& items, int dp, int dx, DragType dty
}
else
ip2c->second.xdiff = npartoffset;
-
- //part = newPart; // reassign
- //item->setPart(part);
- //item->setEvent(newEvent);
- //curPart = part;
- //curPartId = curPart->sn();
-
}
}
@@ -352,8 +319,6 @@ void PianoCanvas::moveCanvasItems(CItemList& items, int dp, int dx, DragType dty
newPart->setLenTick(newPart->lenTick() + diff);
- modified = SC_PART_MODIFIED;
-
// BUG FIX: #1650953
// Added by T356.
// Fixes posted "select and drag past end of part - crashing" bug
@@ -367,8 +332,8 @@ void PianoCanvas::moveCanvasItems(CItemList& items, int dp, int dx, DragType dty
}
editor->parts()->add(newPart);
- // Indicate no undo, and do port controller values but not clone parts.
- audio->msgChangePart(opart, newPart, false, true, false);
+ // Do port controller values but not clone parts.
+ operations.push_back(UndoOp(UndoOp::ModifyPart, opart, newPart, true, false));
ip2c->second.npart = newPart;
@@ -384,6 +349,7 @@ void PianoCanvas::moveCanvasItems(CItemList& items, int dp, int dx, DragType dty
std::vector< CItem* > doneList;
typedef std::vector< CItem* >::iterator iDoneList;
+
for(iCItem ici = items.begin(); ici != items.end(); ++ici)
{
CItem* ci = ici->second;
@@ -408,21 +374,12 @@ void PianoCanvas::moveCanvasItems(CItemList& items, int dp, int dx, DragType dty
break;
// Do not process if the event has already been processed (meaning it's an event in a clone part)...
- //if(moveItem(ci, newpos, dtype))
- if(idl != doneList.end())
- // Just move the canvas item.
- ci->move(newpos);
- else
+ if (idl == doneList.end())
{
- // Currently moveItem always returns true.
- if(moveItem(ci, newpos, dtype))
- {
- // Add the canvas item to the list of done items.
- doneList.push_back(ci);
- // Move the canvas item.
- ci->move(newpos);
- }
+ operations.push_back(moveItem(ci, newpos, dtype));
+ doneList.push_back(ci);
}
+ ci->move(newpos);
if(moving.size() == 1)
itemReleased(curItem, newpos);
@@ -430,8 +387,7 @@ void PianoCanvas::moveCanvasItems(CItemList& items, int dp, int dx, DragType dty
selectItem(ci, false);
}
- if(pflags)
- *pflags = modified;
+ return operations;
}
//---------------------------------------------------------
@@ -439,9 +395,7 @@ void PianoCanvas::moveCanvasItems(CItemList& items, int dp, int dx, DragType dty
// called after moving an object
//---------------------------------------------------------
-// Changed by T356.
-//bool PianoCanvas::moveItem(CItem* item, const QPoint& pos, DragType dtype, int* pflags)
-bool PianoCanvas::moveItem(CItem* item, const QPoint& pos, DragType dtype)
+UndoOp PianoCanvas::moveItem(CItem* item, const QPoint& pos, DragType dtype)
{
NEvent* nevent = (NEvent*) item;
Event event = nevent->event();
@@ -462,7 +416,7 @@ bool PianoCanvas::moveItem(CItem* item, const QPoint& pos, DragType dtype)
// Changed by T356.
Part* part = nevent->part(); //
- //Part * part = Canvas::part(); // part can be dynamically recreated, ask the authority
+ //Part* part = Canvas::part(); // part can be dynamically recreated, ask the authority
newEvent.setPitch(npitch);
int ntick = editor->rasterVal(x) - part->tick();
@@ -471,46 +425,6 @@ bool PianoCanvas::moveItem(CItem* item, const QPoint& pos, DragType dtype)
newEvent.setTick(ntick);
newEvent.setLenTick(event.lenTick());
- // Removed by T356.
- /*
- int modified=0;
- //song->startUndo();
- int diff = newEvent.endTick()-part->lenTick();
- if (diff > 0){// too short part? extend it
- // if there are several events that are moved outside the part, it will be recreated for each
- // so the part _in_ the event will not be valid, ask the authority.
- //Part* newPart = part->clone();
- Part* newPart = Canvas::part()->clone();
-
- newPart->setLenTick(newPart->lenTick()+diff);
- audio->msgChangePart(Canvas::part(), newPart,false);
-
- modified = SC_PART_MODIFIED;
- part = newPart; // reassign
-
- // BUG FIX: #1650953
- // Added by T356.
- // Fixes posted "select and drag past end of part - crashing" bug
- for(iPart i = editor->parts()->begin(); i != editor->parts()->end(); ++i)
- {
- if(i->second == Canvas::part())
- {
- editor->parts()->erase(i);
- break;
- }
- }
- editor->parts()->add(part);
- item->setPart(part);
- item->setEvent(newEvent);
- curPart = part;
- curPartId = curPart->sn();
-
- }
- */
-
- // Added by T356.
- // msgAddEvent and msgChangeEvent (below) will set these, but set them here first?
- //item->setPart(part);
item->setEvent(newEvent);
// Added by T356.
@@ -518,20 +432,9 @@ bool PianoCanvas::moveItem(CItem* item, const QPoint& pos, DragType dtype)
printf("PianoCanvas::moveItem Error! New event end:%d exceeds length:%d of part:%s\n", newEvent.endTick(), part->lenTick(), part->name().toLatin1().constData());
if (dtype == MOVE_COPY || dtype == MOVE_CLONE)
- // Indicate no undo, and do not do port controller values and clone parts.
- //audio->msgAddEvent(newEvent, part, false);
- audio->msgAddEvent(newEvent, part, false, false, false);
+ return UndoOp(UndoOp::AddEvent, newEvent, part, false, false);
else
- // Indicate no undo, and do not do port controller values and clone parts.
- //audio->msgChangeEvent(event, newEvent, part, false);
- audio->msgChangeEvent(event, newEvent, part, false, false, false);
- //song->endUndo(modified);
-
- // Removed by T356.
- //if(pflags)
- // *pflags = modified;
-
- return true;
+ return UndoOp(UndoOp::ModifyEvent, newEvent, event, part, false, false);
}
//---------------------------------------------------------
@@ -584,13 +487,11 @@ void PianoCanvas::newItem(CItem* item, bool noSnap)
Part* newPart = part->clone();
newPart->setLenTick(newPart->lenTick()+diff);
// Indicate no undo, and do port controller values but not clone parts.
- //audio->msgChangePart(part, newPart,false);
audio->msgChangePart(part, newPart, false, true, false);
modified=modified|SC_PART_MODIFIED;
part = newPart; // reassign
}
// Indicate no undo, and do not do port controller values and clone parts.
- //audio->msgAddEvent(event, part,false);
audio->msgAddEvent(event, part, false, false, false);
song->endUndo(modified);
}
@@ -620,14 +521,12 @@ void PianoCanvas::resizeItem(CItem* item, bool noSnap) // experimental c
}
song->startUndo();
int modified=SC_EVENT_MODIFIED;
- //printf("event.tick()=%d len=%d part->lenTick()=%d\n",event.endTick(),len,part->lenTick());
int diff = event.tick()+len-part->lenTick();
if (diff > 0) {// too short part? extend it
//printf("extend Part!\n");
Part* newPart = part->clone();
newPart->setLenTick(newPart->lenTick()+diff);
// Indicate no undo, and do port controller values but not clone parts.
- //audio->msgChangePart(part, newPart,false);
audio->msgChangePart(part, newPart, false, true, false);
modified=modified|SC_PART_MODIFIED;
part = newPart; // reassign
@@ -635,7 +534,6 @@ void PianoCanvas::resizeItem(CItem* item, bool noSnap) // experimental c
newEvent.setLenTick(len);
// Indicate no undo, and do not do port controller values and clone parts.
- //audio->msgChangeEvent(event, newEvent, nevent->part(),false);
audio->msgChangeEvent(event, newEvent, nevent->part(), false, false, false);
song->endUndo(modified);
}
@@ -650,7 +548,6 @@ bool PianoCanvas::deleteItem(CItem* item)
if (nevent->part() == curPart) {
Event ev = nevent->event();
// Indicate do undo, and do not do port controller values and clone parts.
- //audio->msgDeleteEvent(ev, curPart);
audio->msgDeleteEvent(ev, curPart, true, false, false);
return true;
}
@@ -697,8 +594,6 @@ void PianoCanvas::pianoCmd(int cmd)
case CMD_RIGHT_NOSNAP:
{
Pos p(pos[0] + editor->rasterStep(pos[0]), true);
- //if (p > part->tick())
- // p = part->tick();
song->setPos(0, p, true, true, true); //CDW
}
break;
@@ -710,8 +605,9 @@ void PianoCanvas::pianoCmd(int cmd)
if (part == 0)
break;
- song->startUndo();
+
EventList* el = part->events();
+ Undo operations;
std::list <Event> elist;
for (iEvent e = el->lower_bound(pos[0] - part->tick()); e != el->end(); ++e)
@@ -720,11 +616,11 @@ void PianoCanvas::pianoCmd(int cmd)
Event event = *i;
Event newEvent = event.clone();
newEvent.setTick(event.tick() + editor->raster());// - part->tick());
- // Indicate no undo, and do not do port controller values and clone parts.
- //audio->msgChangeEvent(event, newEvent, part, false);
- audio->msgChangeEvent(event, newEvent, part, false, false, false);
+ // Do not do port controller values and clone parts.
+ operations.push_back(UndoOp(UndoOp::ModifyEvent, newEvent, event, part, false, false));
}
- song->endUndo(SC_EVENT_MODIFIED);
+ song->applyOperationGroup(operations);
+
Pos p(editor->rasterVal(pos[0] + editor->rasterStep(pos[0])), true);
song->setPos(0, p, true, false, true);
}
@@ -736,7 +632,8 @@ void PianoCanvas::pianoCmd(int cmd)
MidiPart* part = (MidiPart*)curPart;
if (part == 0)
break;
- song->startUndo();
+
+ Undo operations;
EventList* el = part->events();
std::list<Event> elist;
@@ -746,11 +643,10 @@ void PianoCanvas::pianoCmd(int cmd)
Event event = *i;
Event newEvent = event.clone();
newEvent.setTick(event.tick() - editor->raster() - part->tick());
- // Indicate no undo, and do not do port controller values and clone parts.
- //audio->msgChangeEvent(event, newEvent, part, false);
- audio->msgChangeEvent(event, newEvent, part, false, false, false);
+ // Do not do port controller values and clone parts.
+ operations.push_back(UndoOp(UndoOp::ModifyEvent, newEvent, event, part, false, false));
}
- song->endUndo(SC_EVENT_MODIFIED);
+ song->applyOperationGroup(operations);
Pos p(editor->rasterVal(pos[0] - editor->rasterStep(pos[0])), true);
song->setPos(0, p, true, false, true);
}
@@ -769,14 +665,12 @@ void PianoCanvas::pianoPressed(int pitch, int velocity, bool shift)
pitch += track()->transposition;
// play note:
- //MidiPlayEvent e(0, port, channel, 0x90, pitch, 127);
MidiPlayEvent e(0, port, channel, 0x90, pitch, velocity);
audio->msgPlayMidiEvent(&e);
if (_steprec && pos[0] >= start_tick && pos[0] < end_tick && curPart) {
steprec->record(curPart,pitch,editor->raster(),editor->raster(),velocity,globalKeyState&Qt::ControlModifier,shift);
}
-
}
//---------------------------------------------------------
@@ -817,14 +711,6 @@ void drawTickRaster(QPainter& p, int x, int y, int w, int h, int raster)
int qq = raster;
if (q < 8) // grid too dense
qq *= 2;
- //switch (quant) {
- // case 32:
- // case 48:
- // case 64:
- // case 96:
- // case 192: // 8tel
- // case 128: // 8tel Triolen
- // case 288:
p.setPen(Qt::lightGray);
if (raster>=4) {
int xx = x + qq;
@@ -835,10 +721,6 @@ void drawTickRaster(QPainter& p, int x, int y, int w, int h, int raster)
}
xx = xxx;
}
- // break;
- // default:
- // break;
- // }
p.setPen(Qt::gray);
for (int beat = 1; beat < z; beat++) {
int xx = AL::sigmap.bar2tick(bar, beat, 0);
@@ -873,9 +755,7 @@ void PianoCanvas::drawCanvas(QPainter& p, const QRect& rect)
p.drawLine(x, yy, x + w, yy);
break;
default:
- //p.setPen(lightGray);
p.fillRect(x, yy-3, w, 6, QBrush(QColor(230,230,230)));
- //p.drawLine(x, yy, x + w, yy);
break;
}
--key;
@@ -971,24 +851,7 @@ void PianoCanvas::cmd(int cmd)
}
break;
- case CMD_FIXED_LEN: //Set notes to the length specified in the drummap
- if (!selectionSize())
- break;
- song->startUndo();
- for (iCItem k = items.begin(); k != items.end(); ++k) {
- if (k->second->isSelected()) {
- NEvent* nevent = (NEvent*)(k->second);
- Event event = nevent->event();
- Event newEvent = event.clone();
- newEvent.setLenTick(editor->raster());
- // Indicate no undo, and do not do port controller values and clone parts.
- //audio->msgChangeEvent(event, newEvent, nevent->part() , false);
- audio->msgChangeEvent(event, newEvent, nevent->part(), false, false, false);
- }
- }
- song->endUndo(SC_EVENT_MODIFIED);
- break;
-
+ case CMD_FIXED_LEN:
case CMD_CRESCENDO:
case CMD_TRANSPOSE:
case CMD_THIN_OUT:
@@ -1047,10 +910,6 @@ void PianoCanvas::startDrag(CItem* /* item*/, bool copymode)
QMimeData* md = selected_events_to_mime(partlist_to_set(editor->parts()), 1);
if (md) {
-// QApplication::clipboard()->setData(drag, QClipboard::Clipboard); // This line NOT enabled in muse-1
- //QApplication::clipboard()->setMimeData(md); // TODO CHECK Tim.
- //QApplication::clipboard()->setMimeData(drag->mimeData()); //
-
// "Note that setMimeData() assigns ownership of the QMimeData object to the QDrag object.
// The QDrag must be constructed on the heap with a parent QWidget to ensure that Qt can
// clean up after the drag and drop operation has been completed. "
@@ -1233,8 +1092,8 @@ void PianoCanvas::modifySelected(NoteInfo::ValType type, int delta)
}
song->changeEvent(event, newEvent, part);
// Indicate do not do port controller values and clone parts.
- //song->undoOp(UndoOp::ModifyEvent, newEvent, event, part);
- song->undoOp(UndoOp::ModifyEvent, newEvent, event, part, false, false);
+ //song->addUndo(UndoOp(UndoOp::ModifyEvent, newEvent, event, part));
+ song->addUndo(UndoOp(UndoOp::ModifyEvent, newEvent, event, part, false, false));
}
song->endUndo(SC_EVENT_MODIFIED);
audio->msgIdle(false);
diff --git a/muse2/muse/midiedit/prcanvas.h b/muse2/muse/midiedit/prcanvas.h
index 663b933a..c6e47c9e 100644
--- a/muse2/muse/midiedit/prcanvas.h
+++ b/muse2/muse/midiedit/prcanvas.h
@@ -54,10 +54,8 @@ class PianoCanvas : public EventCanvas {
virtual void drawItem(QPainter&, const CItem*, const QRect&);
void drawTopItem(QPainter &p, const QRect &rect);
virtual void drawMoving(QPainter&, const CItem*, const QRect&);
- virtual void moveCanvasItems(CItemList&, int, int, DragType, int*);
- // Changed by T356.
- //virtual bool moveItem(CItem*, const QPoint&, DragType, int*);
- virtual bool moveItem(CItem*, const QPoint&, DragType);
+ virtual Undo moveCanvasItems(CItemList&, int, int, DragType);
+ virtual UndoOp moveItem(CItem*, const QPoint&, DragType);
virtual CItem* newItem(const QPoint&, int);
virtual void resizeItem(CItem*, bool noSnap);
virtual void newItem(CItem*, bool noSnap);
diff --git a/muse2/muse/midiedit/scoreedit.cpp b/muse2/muse/midiedit/scoreedit.cpp
index d2fd7730..1a885d99 100644
--- a/muse2/muse/midiedit/scoreedit.cpp
+++ b/muse2/muse/midiedit/scoreedit.cpp
@@ -552,8 +552,6 @@ ScoreEdit::~ScoreEdit()
}
-
-
void ScoreEdit::velo_box_changed()
{
emit velo_changed(velo_spinbox->value());
@@ -592,10 +590,9 @@ void ScoreEdit::song_changed(int flags)
if (velo>=0) velo_spinbox->setValue(velo);
if (velo_off>=0) velo_off_spinbox->setValue(velo_off);
}
- }
-
- if (flags & SC_SELECTION)
+
selection_changed();
+ }
}
void ScoreEdit::canvas_width_changed(int width)
@@ -3533,7 +3530,7 @@ void ScoreCanvas::mousePressEvent (QMouseEvent* event)
int y=event->y() + y_pos - staff_it->y_draw;
int x=event->x()+x_pos-x_left;
int tick=flo_quantize_floor(x_to_tick(x), quant_ticks());
-
+
if (staff_it!=staves.end())
{
if (event->x() <= x_left) //clicked in the preamble?
@@ -4447,7 +4444,7 @@ void staff_t::update_part_indices()
-//hint: recalculating event- and itemlists "from zero"
+//note: recalculating event- and itemlists "from zero"
// could happen in realtime, as it is pretty fast.
// however, this adds unneccessary cpu usage.
// it is NO problem to recalc the stuff "from zero"
@@ -4460,14 +4457,20 @@ void staff_t::update_part_indices()
* between, for example, when a cis is tied to a des
*
* CURRENT TODO
- * o either remove these "hidden notes", or deal with them in the score editor
+ * o clones should have same size
+ * o insert empty measure should also work inside parts, that is,
+ * move notes _within_ parts
+ *
+ * IMPORTANT TODO
+ * o canvas editor: create clone via "alt+drag" moves window instead
* o investigate with valgrind
* o controller view in score editor
* o deal with expanding parts
* o fix sigedit boxes
- * o mid-click in pianoroll: change to "delete", or initiate drag and drop between windows?
- *
- * IMPORTANT TODO
+ * o solo button
+ * o grand staff brace
+ * o mastertrack editor: key-combobox is buggy
+ * o drum editor: channel-stuff
* o do partial recalculating; recalculating can take pretty long
* (0,5 sec) when displaying a whole song in scores
* o transpose etc. must also transpose key-pressure events
@@ -4488,6 +4491,7 @@ void staff_t::update_part_indices()
* keeping its own pos_add variable (which is only an optimisation)
* o support edge-scrolling when opening a lasso
* o save more configuration stuff (quant, color)
+ * o drum list: scroll while dragging (not important due to "reorder list")
*
* really unimportant nice-to-haves
* o support in-song clef-changes
diff --git a/muse2/muse/midiedit/scoreedit.h b/muse2/muse/midiedit/scoreedit.h
index 1c45f578..e7302a46 100644
--- a/muse2/muse/midiedit/scoreedit.h
+++ b/muse2/muse/midiedit/scoreedit.h
@@ -707,15 +707,14 @@ class ScoreCanvas : public View
int old_pitch;
unsigned old_dest_tick;
-
- bool undo_started;
- bool temp_undo;
bool have_lasso;
QPoint lasso_start;
QRect lasso;
-
+ bool undo_started;
+ bool temp_undo;
+
bool srec;
bool held_notes[128];
diff --git a/muse2/muse/miditransform.cpp b/muse2/muse/miditransform.cpp
index 1c73b7c2..9e9c87c0 100644
--- a/muse2/muse/miditransform.cpp
+++ b/muse2/muse/miditransform.cpp
@@ -662,14 +662,14 @@ void MidiTransformerDialog::transformEvent(Event& event, MidiPart* part,
// Indicate do clone parts.
addPortCtrlEvents(newEvent, part, true);
// Indicate do port controller values and clone parts.
- //song->undoOp(UndoOp::ModifyEvent, newEvent, event, part);
- song->undoOp(UndoOp::ModifyEvent, newEvent, event, part, true, true);
+ //song->addUndo(UndoOp(UndoOp::ModifyEvent, newEvent, event, part));
+ song->addUndo(UndoOp(UndoOp::ModifyEvent, newEvent, event, part, true, true));
song->addUpdateFlags(SC_EVENT_MODIFIED);
break;
case Insert:
// Indicate do port controller values and clone parts.
- //song->undoOp(UndoOp::AddEvent, dummy, newEvent, part);
- song->undoOp(UndoOp::AddEvent, dummy, newEvent, part, true, true);
+ //song->addUndo(UndoOp(UndoOp::AddEvent, dummy, newEvent, part));
+ song->addUndo(UndoOp(UndoOp::AddEvent, dummy, newEvent, part, true, true));
song->addEvent(newEvent, part);
// Indicate do clone parts.
addPortCtrlEvents(newEvent, part, true);
@@ -677,8 +677,8 @@ void MidiTransformerDialog::transformEvent(Event& event, MidiPart* part,
break;
case Extract:
// Indicate do port controller values and clone parts.
- //song->undoOp(UndoOp::DeleteEvent, dummy, event, part);
- song->undoOp(UndoOp::DeleteEvent, dummy, event, part, true, true);
+ //song->addUndo(UndoOp(UndoOp::DeleteEvent, dummy, event, part));
+ song->addUndo(UndoOp(UndoOp::DeleteEvent, dummy, event, part, true, true));
// Indicate do clone parts.
removePortCtrlEvents(event, part, true);
song->deleteEvent(event, part);
@@ -713,8 +713,8 @@ void MidiTransformerDialog::processEvent(Event& event, MidiPart* part, MidiPart*
// Indicate do clone parts.
addPortCtrlEvents(newEvent, part, true);
// Indicate do port controller values and clone parts.
- //song->undoOp(UndoOp::ModifyEvent, newEvent, event, part);
- song->undoOp(UndoOp::ModifyEvent, newEvent, event, part, true, true);
+ //song->addUndo(UndoOp(UndoOp::ModifyEvent, newEvent, event, part));
+ song->addUndo(UndoOp(UndoOp::ModifyEvent, newEvent, event, part, true, true));
song->addUpdateFlags(SC_EVENT_MODIFIED);
}
}
@@ -723,8 +723,8 @@ void MidiTransformerDialog::processEvent(Event& event, MidiPart* part, MidiPart*
{
Event ev;
// Indicate do port controller values and clone parts.
- //song->undoOp(UndoOp::DeleteEvent, ev, event, part, true, true);
- song->undoOp(UndoOp::DeleteEvent, ev, event, part, true, true);
+ //song->addUndo(UndoOp(UndoOp::DeleteEvent, ev, event, part, true, true));
+ song->addUndo(UndoOp(UndoOp::DeleteEvent, ev, event, part, true, true));
// Indicate do clone parts.
removePortCtrlEvents(event, part, true);
song->deleteEvent(event, part);
diff --git a/muse2/muse/part.cpp b/muse2/muse/part.cpp
index 99f070b2..398720af 100644
--- a/muse2/muse/part.cpp
+++ b/muse2/muse/part.cpp
@@ -85,9 +85,6 @@ void chainCloneInternal(Part* p)
const PartList* pl = mt->cparts();
for(ciPart ip = pl->begin(); ip != pl->end(); ++ip)
{
- // Added by Tim. p3.3.6
- //printf("chainCloneInternal track %p %s part %p %s evlist %p\n", (*imt), (*imt)->name().toLatin1().constData(), ip->second, ip->second->name().toLatin1().constData(), ip->second->cevents());
-
if(ip->second != p && ip->second->cevents() == p->cevents())
{
p1 = ip->second;
@@ -224,16 +221,9 @@ void replaceClone(Part* p1, Part* p2)
else
p2->setNextClone(p2);
- // Link the replacement...
- //p2->setPrevClone(p1->prevClone());
- //p2->setNextClone(p1->nextClone());
-
// Isolate the replaced part.
p1->setNextClone(p1);
p1->setPrevClone(p1);
- // Added by Tim. p3.3.6
- //printf("replaceClone p1: %s %p arefs:%d p2: %s %p arefs:%d\n", p1->name().toLatin1().constData(), p1, );
-
}
//---------------------------------------------------------
@@ -278,9 +268,6 @@ void chainTrackParts(Track* t, bool incRefCount)
if(incRefCount)
p->events()->incARef(1);
- // Added by Tim. p3.3.6
- //printf("chainTrackParts track %p %s part %p %s evlist %p\n", t, t->name().toLatin1().constData(), p, p->name().toLatin1().constData(), p->cevents());
-
Part* p1 = 0;
// Look for a part with the same event list, that we can chain to.
@@ -296,9 +283,6 @@ void chainTrackParts(Track* t, bool incRefCount)
const PartList* pl = mt->cparts();
for(ciPart ip = pl->begin(); ip != pl->end(); ++ip)
{
- // Added by Tim. p3.3.6
- //printf("chainTrackParts track %p %s part %p %s evlist %p\n", mt, mt->name().toLatin1().constData(), ip->second, ip->second->name().toLatin1().constData(), ip->second->cevents());
-
if(ip->second != p && ip->second->cevents() == p->cevents())
{
p1 = ip->second;
@@ -381,21 +365,12 @@ void addPortCtrlEvents(Event& event, Part* part, bool doClones)
//for(int i = 0; i < j; ++i)
while(1)
{
- // Added by Tim. p3.3.6
- //printf("addPortCtrlEvents i:%d %s %p events %p refs:%d arefs:%d\n", i, p->name().toLatin1().constData(), p, part->cevents(), part->cevents()->refCount(), j);
-
Track* t = p->track();
if(t && t->isMidiTrack())
{
MidiTrack* mt = (MidiTrack*)t;
int port = mt->outPort();
- //const EventList* el = p->cevents();
unsigned len = p->lenTick();
- //for(ciEvent ie = el->begin(); ie != el->end(); ++ie)
- //{
- //const Event& ev = ie->second;
- // Added by Tim. p3.3.6
- //printf("addPortCtrlEvents %s len:%d end:%d etick:%d\n", p->name().toLatin1().constData(), p->lenTick(), p->endTick(), event.tick());
// Do not add events which are past the end of the part.
if(event.tick() >= len)
@@ -425,7 +400,6 @@ void addPortCtrlEvents(Event& event, Part* part, bool doClones)
mp->setControllerVal(ch, tck, cntrl, val, p);
}
- //}
}
if(!doClones)
@@ -456,9 +430,6 @@ void addPortCtrlEvents(Part* part, bool doClones)
//for(int i = 0; i < j; ++i)
while(1)
{
- // Added by Tim. p3.3.6
- //printf("addPortCtrlEvents i:%d %s %p events %p refs:%d arefs:%d\n", i, p->name().toLatin1().constData(), p, part->cevents(), part->cevents()->refCount(), j);
-
Track* t = p->track();
if(t && t->isMidiTrack())
{
@@ -532,16 +503,6 @@ void removePortCtrlEvents(Event& event, Part* part, bool doClones)
{
MidiTrack* mt = (MidiTrack*)t;
int port = mt->outPort();
- //const EventList* el = p->cevents();
- //unsigned len = p->lenTick();
- //for(ciEvent ie = el->begin(); ie != el->end(); ++ie)
- //{
- //const Event& ev = ie->second;
- // Added by T356. Do not remove events which are past the end of the part.
- // No, actually, do remove ALL of them belonging to the part.
- // Just in case there are stray values left after the part end.
- //if(ev.tick() >= len)
- // break;
if(event.type() == Controller)
{
@@ -566,7 +527,6 @@ void removePortCtrlEvents(Event& event, Part* part, bool doClones)
mp->deleteController(ch, tck, cntrl, p);
}
- //}
}
if(!doClones)
@@ -734,14 +694,6 @@ MidiPart::MidiPart(const MidiPart& p) : Part(p)
{
_prevClone = this;
_nextClone = this;
- //setSn(newSn());
- //_sn = p._sn;
- //_name = p._name;
- //_selected = p._selected;
- //_mute = p._mute;
- //_colorIndex = p._colorIndex;
- //_track = p._track;
- //_events = p._events;
}
//---------------------------------------------------------
@@ -769,14 +721,6 @@ WavePart::WavePart(const WavePart& p) : Part(p)
{
_prevClone = this;
_nextClone = this;
- //setSn(newSn());
- //_sn = p._sn;
- //_name = p._name;
- //_selected = p._selected;
- //_mute = p._mute;
- //_colorIndex = p._colorIndex;
- //_track = p._track;
- //_events = p._events;
}
//---------------------------------------------------------
@@ -790,139 +734,6 @@ Part::~Part()
delete _events;
}
-/*
-//---------------------------------------------------------
-// unchainClone
-//---------------------------------------------------------
-
-void Part::unchainClone()
-{
- chainCheckErr();
-
- _prevClone->setNextClone(_nextClone);
- _nextClone->setPrevClone(_prevClone);
-
- _prevClone = this;
- _nextClone = this;
-}
-
-//---------------------------------------------------------
-// chainClone
-// The quick way - if part to chain to is known...
-//---------------------------------------------------------
-
-void Part::chainClone(const Part* p)
-{
- chainCheckErr();
-
- // Make sure the part is unchained first.
- p->prevClone()->setNextClone(p->nextClone());
- p->nextClone()->setPrevClone(p->prevClone());
-
- p->setPrevClone(this);
- p->setNextClone(_nextClone->prevClone());
-
- _nextClone->setPrevClone(p);
- _nextClone = (Part*)p;
-}
-
-//---------------------------------------------------------
-// chainClone
-// The slow way - if part to chain to is not known...
-//---------------------------------------------------------
-
-void Part::chainClone()
-{
- chainCheckErr();
-
- // Look for a part with the same event list, that we can chain to...
- Part* p = 0;
- if(!_track || (_track && _track->isMidiTrack()))
- {
- MidiTrackList* mtl = song->midis();
- for(ciMidiTrack imt = mtl->begin(); imt != mtl->end(); ++imt)
- {
- const PartList* pl = (*imt)->cparts();
- for(ciPart ip = pl->begin(); ip != pl->end(); ++ip)
- {
- if(ip->second != this && ip->second->events() == _events)
- {
- p = ip->second;
- break;
- }
- }
- }
- }
-
- if((!p && !_track) || (_track && _track->type() == Track::WAVE))
- {
- WaveTrackList* wtl = song->waves();
- for(ciWaveTrack iwt = wtl->begin(); iwt != wtl->end(); ++iwt)
- {
- const PartList* pl = (*iwt)->cparts();
- for(ciPart ip = pl->begin(); ip != pl->end(); ++ip)
- {
- if(ip->second != this && ip->second->events() == _events)
- {
- p = ip->second;
- break;
- }
- }
- }
- }
-
- // No part found with same event list? Done.
- if(!p)
- return;
-
- // Make sure this part is unchained first.
- _prevClone->setNextClone(_nextClone);
- _nextClone->setPrevClone(_prevClone);
-
- _prevClone = p;
- _nextClone = p->nextClone();
-
- p->nextClone()->setPrevClone(this);
- p->setNextClone(this);
-}
-
-//---------------------------------------------------------
-// replaceClone
-//---------------------------------------------------------
-
-void Part::replaceClone(const Part* p)
-{
- chainCheckErr();
-
- // Make sure the part is unchained first.
- p->prevClone()->setNextClone(p->nextClone());
- p->nextClone()->setPrevClone(p->prevClone());
-
- // If this part is a clone, not a single lone part...
- if(_prevClone != this)
- _prevClone->setNextClone(p);
- if(_nextClone != this)
- _nextClone->setPrevClone(p);
-
- p->setPrevClone(_prevClone);
- p->setNextClone(_nextClone);
-
- _nextClone = this;
- _prevClone = this;
-}
-
-//---------------------------------------------------------
-// chainCheckErr
-//---------------------------------------------------------
-
-void Part::chainCheckErr()
-{
- if(_nextClone->prevClone() != this)
- printf("Part::chainCheckErr Error! Next clone:%s %x prev clone:%s %x != this:%s %x\n", _nextClone->name().toLatin1().constData(), _nextClone, _nextClone->prevClone()->name().toLatin1().constData(), _nextClone->prevClone(), name().toLatin1().constData(), this);
- if(_prevClone->nextClone() != this)
- printf("Part::chainCheckErr Error! Prev clone:%s %x next clone:%s %x != this:%s %x\n", _prevClone->name().toLatin1().constData(), _prevClone, _prevClone->nextClone()->name().toLatin1().constData(), _prevClone->nextClone(), name().toLatin1().constData(), this);
-}
-*/
//---------------------------------------------------------
// findPart
@@ -988,7 +799,6 @@ void Song::addPart(Part* part)
_len = epos;
part->track()->addPart(part);
- //part->addPortCtrlEvents();
// Indicate do not do clones.
addPortCtrlEvents(part, false);
}
@@ -999,9 +809,7 @@ void Song::addPart(Part* part)
void Song::removePart(Part* part)
{
- //part->removePortCtrlEvents();
// Indicate do not do clones.
- //removePortCtrlEvents(part);
removePortCtrlEvents(part, false);
Track* track = part->track();
track->parts()->remove(part);
@@ -1019,47 +827,44 @@ void Song::cmdResizePart(Track* track, Part* oPart, unsigned int len)
WavePart* nPart = new WavePart(*(WavePart*)oPart);
EventList* el = nPart->events();
unsigned new_partlength = tempomap.deltaTick2frame(oPart->tick(), oPart->tick() + len);
- //printf("new partlength in frames: %d\n", new_partlength);
// If new nr of frames is less than previous what can happen is:
// - 0 or more events are beginning after the new final position. Those are removed from the part
// - The last event begins before new final position and ends after it. If so, it will be resized to end at new part length
if (new_partlength < oPart->lenFrame()) {
- startUndo();
+ Undo operations;
for (iEvent i = el->begin(); i != el->end(); i++) {
Event e = i->second;
unsigned event_startframe = e.frame();
unsigned event_endframe = event_startframe + e.lenFrame();
- //printf("Event frame=%d, length=%d\n", event_startframe, event_length);
if (event_endframe < new_partlength)
continue;
if (event_startframe > new_partlength) { // If event start was after the new length, remove it from part
- // Indicate no undo, and do not do port controller values and clone parts.
- //audio->msgDeleteEvent(e, nPart, false);
- audio->msgDeleteEvent(e, nPart, false, false, false);
+ // Do not do port controller values and clone parts.
+ operations.push_back(UndoOp(UndoOp::DeleteEvent, e, nPart, false, false));
continue;
}
if (event_endframe > new_partlength) { // If this event starts before new length and ends after, shrink it
Event newEvent = e.clone();
newEvent.setLenFrame(new_partlength - event_startframe);
- // Indicate no undo, and do not do port controller values and clone parts.
- //audio->msgChangeEvent(e, newEvent, nPart, false);
+ // Do not do port controller values and clone parts.
audio->msgChangeEvent(e, newEvent, nPart, false, false, false);
+ operations.push_back(UndoOp(UndoOp::ModifyEvent, newEvent, e, nPart, false,false));
}
}
nPart->setLenFrame(new_partlength);
- // Indicate no undo, and do not do port controller values and clone parts.
- //audio->msgChangePart(oPart, nPart, false);
- audio->msgChangePart(oPart, nPart, false, false, false);
+ // Do not do port controller values and clone parts.
+ operations.push_back(UndoOp(UndoOp::ModifyPart, oPart, nPart, false, false));
- endUndo(SC_PART_MODIFIED);
+ song->applyOperationGroup(operations);
}
// If the part is expanded there can be no additional events beginning after the previous final position
// since those are removed if the part has been shrunk at some time (see above)
// The only thing we need to check is the final event: If it has data after the previous final position,
// we'll expand that event
else {
+ Undo operations;
if(!el->empty())
{
iEvent i = el->end();
@@ -1072,40 +877,33 @@ void Song::cmdResizePart(Track* track, Part* oPart, unsigned int len)
unsigned clipframes = (file.samples() - last.spos());// / file.channels();
Event newEvent = last.clone();
- //printf("SndFileR samples=%d channels=%d event samplepos=%d clipframes=%d\n", file.samples(), file.channels(), last.spos(), clipframes);
unsigned new_eventlength = new_partlength - last_start;
if (new_eventlength > clipframes) // Shrink event length if new partlength exceeds last clip
new_eventlength = clipframes;
newEvent.setLenFrame(new_eventlength);
- startUndo();
- // Indicate no undo, and do not do port controller values and clone parts.
- //audio->msgChangeEvent(last, newEvent, nPart, false);
- audio->msgChangeEvent(last, newEvent, nPart, false, false, false);
- }
- else
- {
- startUndo();
+ // Do not do port controller values and clone parts.
+ operations.push_back(UndoOp(UndoOp::ModifyEvent, newEvent, last, nPart, false, false));
}
nPart->setLenFrame(new_partlength);
- // Indicate no undo, and do not do port controller values and clone parts.
- //audio->msgChangePart(oPart, nPart, false);
+ // Do not do port controller values and clone parts.
audio->msgChangePart(oPart, nPart, false, false, false);
- endUndo(SC_PART_MODIFIED);
+ operations.push_back(UndoOp(UndoOp::ModifyPart, oPart, nPart, false, false));
+ song->applyOperationGroup(operations);
}
}
break;
case Track::MIDI:
case Track::DRUM:
{
- startUndo();
+ Undo operations;
MidiPart* nPart = new MidiPart(*(MidiPart*)oPart);
nPart->setLenTick(len);
- // Indicate no undo, and do port controller values but not clone parts.
- audio->msgChangePart(oPart, nPart, false, true, false);
+ // Do port controller values but not clone parts.
+ operations.push_back(UndoOp(UndoOp::ModifyPart, oPart, nPart, true, false));
// cut Events in nPart
// Changed by T356. Don't delete events if this is a clone part.
@@ -1118,36 +916,13 @@ void Song::cmdResizePart(Track* track, Part* oPart, unsigned int len)
for (; ie != el->end();) {
iEvent i = ie;
++ie;
- // Indicate no undo, and do port controller values and clone parts.
- audio->msgDeleteEvent(i->second, nPart, false, true, true);
+ // Do port controller values and clone parts.
+ operations.push_back(UndoOp(UndoOp::DeleteEvent, i->second, nPart, true, true));
}
}
}
- /*
- // cut Events in nPart
- // Changed by T356. Don't delete events if this is a clone part.
- // The other clones might be longer than this one and need these events.
- if(oPart->cevents()->arefCount() <= 1)
- {
- if (oPart->lenTick() > len) {
- EventList* el = nPart->events();
- iEvent ie = el->lower_bound(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 but not clone parts.
- //audio->msgChangePart(oPart, nPart, false);
- audio->msgChangePart(oPart, nPart, false, true, false);
- */
-
- endUndo(SC_PART_MODIFIED);
+ song->applyOperationGroup(operations);
break;
}
default:
@@ -1189,7 +964,6 @@ void Track::splitPart(Part* part, int tickpos, Part*& p1, Part*& p2)
p2 = newPart(part); // new right part
// Added by Tim. p3.3.6
- //printf("Track::splitPart part ev %p sz:%d ref:%d p1 %p sz:%d ref:%d p2 %p sz:%d ref:%d\n", part->events(), part->events()->size(), part->events()->arefCount(), p1->events(), p1->events()->size(), p1->events()->arefCount(), p2->events(), p2->events()->size(), p2->events()->arefCount());
switch (type()) {
case WAVE:
@@ -1281,27 +1055,9 @@ void Song::changePart(Part* oPart, Part* nPart)
Track* oTrack = oPart->track();
Track* nTrack = nPart->track();
- // Added by Tim. p3.3.6
- //printf("Song::changePart before oPart->removePortCtrlEvents oldPart refs:%d Arefs:%d newPart refs:%d Arefs:%d\n", oPart->events()->refCount(), oPart->events()->arefCount(), nPart->events()->refCount(), nPart->events()->arefCount());
-
- // Removed. Port controller events will have to be add/removed separately from this routine.
- //oPart->removePortCtrlEvents();
- //removePortCtrlEvents(oPart);
-
- // Added by Tim. p3.3.6
- //printf("Song::changePart after oPart->removePortCtrlEvents oldPart refs:%d Arefs:%d newPart refs:%d Arefs:%d\n", oPart->events()->refCount(), oPart->events()->arefCount(), nPart->events()->refCount(), nPart->events()->arefCount());
-
oTrack->parts()->remove(oPart);
nTrack->parts()->add(nPart);
- // Added by Tim. p3.3.6
- //printf("Song::changePart after add(nPart) oldPart refs:%d Arefs:%d newPart refs:%d Arefs:%d\n", oPart->events()->refCount(), oPart->events()->arefCount(), nPart->events()->refCount(), nPart->events()->arefCount());
-
- //nPart->addPortCtrlEvents();
- //addPortCtrlEvents(nPart);
-
- // Added by Tim. p3.3.6
- //printf("Song::changePart after nPart->addPortCtrlEvents() oldPart refs:%d Arefs:%d newPart refs:%d Arefs:%d\n", oPart->events()->refCount(), oPart->events()->arefCount(), nPart->events()->refCount(), nPart->events()->arefCount());
// Added by T356.
// adjust song len:
@@ -1309,9 +1065,6 @@ void Song::changePart(Part* oPart, Part* nPart)
if (epos > len())
_len = epos;
- // Added by Tim. p3.3.6
- //printf("Song::changePart after len adjust oldPart refs:%d Arefs:%d newPart refs:%d Arefs:%d\n", oPart->events()->refCount(), oPart->events()->arefCount(), nPart->events()->refCount(), nPart->events()->arefCount());
-
}
//---------------------------------------------------------
@@ -1350,13 +1103,6 @@ void Song::cmdGluePart(Track* track, Part* oPart)
EventList* sl2 = nextPart->events();
- //int frameOffset = nextPart->frame() - oPart->frame();
- //for (iEvent ie = sl2->begin(); ie != sl2->end(); ++ie) {
- // Event event = ie->second.clone();
- // event.setFrame(event.frame() + frameOffset);
- // dl->add(event);
- // }
- // p3.3.54 Changed.
if(track->type() == Track::WAVE)
{
int frameOffset = nextPart->frame() - oPart->frame();
@@ -1382,7 +1128,6 @@ void Song::cmdGluePart(Track* track, Part* oPart)
startUndo();
audio->msgRemovePart(nextPart, false);
// Indicate no undo, and do port controller values but not clone parts.
- //audio->msgChangePart(oPart, nPart, false);
audio->msgChangePart(oPart, nPart, false, true, false);
endUndo(SC_PART_MODIFIED | SC_PART_REMOVED);
}
diff --git a/muse2/muse/part.h b/muse2/muse/part.h
index f7a864e5..9b037edd 100644
--- a/muse2/muse/part.h
+++ b/muse2/muse/part.h
@@ -24,17 +24,11 @@ class MidiTrack;
class WaveTrack;
class Xml;
class Part;
-//class AudioConvertMap;
-
-// typedef std::multimap<unsigned, Event*, std::less<unsigned> >::iterator iEvent;
struct ClonePart {
- //const EventList* el;
const Part* cp;
int id;
uuid_t uuid;
- //ClonePart(const EventList* e, int i) : el(e), id(i) {}
- //ClonePart(const Part* p, int i) : cp(p), id(i) {}
ClonePart(const Part*, int i = -1);
};
@@ -90,12 +84,8 @@ class Part : public PosLen {
iEvent addEvent(Event& p);
- //virtual void read(Xml&, int newPartOffset=0, bool toTrack = true);
- //virtual void write(int, Xml&) const;
- //virtual void write(int, Xml&, bool isCopy = false) const;
virtual void write(int, Xml&, bool isCopy = false, bool forceWavePaths = false) const;
-// virtual Event* newEvent() const = 0;
virtual void dump(int n = 0) const;
};
@@ -113,7 +103,6 @@ class MidiPart : public Part {
virtual MidiPart* clone() const;
MidiTrack* track() const { return (MidiTrack*)Part::track(); }
-// virtual Event* newEvent() const;
virtual void dump(int n = 0) const;
};
@@ -134,7 +123,6 @@ class WavePart : public Part {
virtual WavePart* clone() const;
WaveTrack* track() const { return (WaveTrack*)Part::track(); }
-// virtual Event* newEvent() const;
virtual void dump(int n = 0) const;
};
@@ -167,9 +155,6 @@ extern void addPortCtrlEvents(Event& event, Part* part, bool doClones);
extern void removePortCtrlEvents(Part* part, bool doClones);
extern void removePortCtrlEvents(Event& event, Part* part, bool doClones);
extern CloneList cloneList;
-//extern CloneList copyCloneList;
-//extern void updateCloneList(Part* oPart, Part* nPart);
-//extern void clearClipboardAndCloneList();
extern Part* readXmlPart(Xml&, Track*, bool doClone = false, bool toTrack = true);
#endif
diff --git a/muse2/muse/seqmsg.cpp b/muse2/muse/seqmsg.cpp
index b4d65148..57aadc18 100644
--- a/muse2/muse/seqmsg.cpp
+++ b/muse2/muse/seqmsg.cpp
@@ -751,7 +751,7 @@ void Song::msgInsertTrack(Track* track, int idx, bool doUndoFlag)
msg.ival = idx;
if (doUndoFlag) {
song->startUndo();
- undoOp(UndoOp::AddTrack, idx, track);
+ addUndo(UndoOp(UndoOp::AddTrack, idx, track));
}
audio->sendMsg(&msg);
if (doUndoFlag)
@@ -893,31 +893,23 @@ void Audio::msgRemovePart(Part* part, bool doUndoFlag)
bool Song::msgRemoveParts()
{
- bool loop;
+ Undo operations;
bool partSelected = false;
- do {
- loop = false;
+
TrackList* tl = song->tracks();
for (iTrack it = tl->begin(); it != tl->end(); ++it) {
PartList* pl = (*it)->parts();
for (iPart ip = pl->begin(); ip != pl->end(); ++ip) {
if (ip->second->selected()) {
- if ((*it)->type() == Track::WAVE) {
- audio->msgRemovePart((WavePart*)(ip->second));
- }
- else {
- audio->msgRemovePart(ip->second, false);
- }
- loop = true;
+ operations.push_back(UndoOp(UndoOp::DeletePart,ip->second));
partSelected = true;
- break;
}
}
- if (loop)
- break;
}
- } while (loop);
+
+ song->applyOperationGroup(operations);
+
return partSelected;
}
diff --git a/muse2/muse/song.cpp b/muse2/muse/song.cpp
index 6750203a..6d0541a3 100644
--- a/muse2/muse/song.cpp
+++ b/muse2/muse/song.cpp
@@ -350,7 +350,7 @@ Track* Song::addTrack(int t)
void Song::cmdRemoveTrack(Track* track)
{
int idx = _tracks.index(track);
- undoOp(UndoOp::DeleteTrack, idx, track);
+ addUndo(UndoOp(UndoOp::DeleteTrack, idx, track));
removeTrack2(track);
updateFlags |= SC_TRACK_REMOVED;
}
@@ -395,8 +395,8 @@ void Song::changeTrack(Track* oldTrack, Track* newTrack)
oldTrack->setSelected(false); //??
int idx = _tracks.index(newTrack);
- //undoOp(UndoOp::ModifyTrack, oldTrack, newTrack);
- undoOp(UndoOp::ModifyTrack, idx, oldTrack, newTrack);
+ //addUndo(UndoOp(UndoOp::ModifyTrack, oldTrack, newTrack));
+ addUndo(UndoOp(UndoOp::ModifyTrack, idx, oldTrack, newTrack));
updateFlags |= SC_TRACK_MODIFIED;
}
@@ -863,7 +863,7 @@ void Song::cmdAddRecordedEvents(MidiTrack* mt, EventList* events, unsigned start
// Now add all of the new part's port controller values. Indicate do not do clone parts.
addPortCtrlEvents(newPart, false);
// Create an undo op. Indicate do port controller values but not clone parts.
- undoOp(UndoOp::ModifyPart, part, newPart, true, false);
+ addUndo(UndoOp(UndoOp::ModifyPart, part, newPart, true, false));
updateFlags |= SC_PART_MODIFIED;
if (_recMode == REC_REPLACE)
@@ -874,7 +874,7 @@ void Song::cmdAddRecordedEvents(MidiTrack* mt, EventList* events, unsigned start
{
Event event = i->second;
// Create an undo op. Indicate do port controller values and clone parts.
- undoOp(UndoOp::DeleteEvent, event, newPart, true, true);
+ addUndo(UndoOp(UndoOp::DeleteEvent, event, newPart, true, true));
// Remove the event from the new part's port controller values, and do all clone parts.
removePortCtrlEvents(event, newPart, true);
}
@@ -886,7 +886,7 @@ void Song::cmdAddRecordedEvents(MidiTrack* mt, EventList* events, unsigned start
event.setTick(event.tick() - partTick);
Event e;
// Create an undo op. Indicate do port controller values and clone parts.
- undoOp(UndoOp::AddEvent, e, event, newPart, true, true);
+ addUndo(UndoOp(UndoOp::AddEvent, e, event, newPart, true, true));
if(newPart->events()->find(event) == newPart->events()->end())
newPart->events()->add(event);
@@ -906,8 +906,8 @@ void Song::cmdAddRecordedEvents(MidiTrack* mt, EventList* events, unsigned start
{
Event event = i->second;
// Create an undo op. Indicate do port controller values and clone parts.
- //undoOp(UndoOp::DeleteEvent, event, part);
- undoOp(UndoOp::DeleteEvent, event, part, true, true);
+ //addUndo(UndoOp(UndoOp::DeleteEvent, event, part));
+ addUndo(UndoOp(UndoOp::DeleteEvent, event, part, true, true));
//if (event.type() == Controller) {
// MidiTrack* track = (MidiTrack*)part->track();
@@ -938,8 +938,8 @@ void Song::cmdAddRecordedEvents(MidiTrack* mt, EventList* events, unsigned start
event.setTick(tick);
Event e;
// Create an undo op. Indicate do port controller values and clone parts.
- //undoOp(UndoOp::AddEvent, e, event, newPart);
- undoOp(UndoOp::AddEvent, e, event, newPart, true, true);
+ //addUndo(UndoOp(UndoOp::AddEvent, e, event, newPart));
+ addUndo(UndoOp(UndoOp::AddEvent, e, event, newPart, true, true));
// addEvent also adds port controller values. So does msgChangePart, below. Let msgChangePart handle them.
//addEvent(event, (MidiPart*)newPart);
@@ -965,9 +965,9 @@ void Song::cmdAddRecordedEvents(MidiTrack* mt, EventList* events, unsigned start
//printf("Song::cmdAddRecordedEvents after changePart part:%p events:%p refs:%d Arefs:%d newPart:%p events:%p refs:%d Arefs:%d\n", part, part->events(), part->events()->refCount(), part->events()->arefCount(), newPart, newPart->events(), newPart->events()->refCount(), newPart->events()->arefCount());
- //undoOp(UndoOp::ModifyPart, part, newPart);
+ //addUndo(UndoOp(UndoOp::ModifyPart, part, newPart));
// Create an undo op. Indicate do not do port controller values and clone parts.
- undoOp(UndoOp::ModifyPart, part, newPart, false, false);
+ addUndo(UndoOp(UndoOp::ModifyPart, part, newPart, false, false));
// Removed by T356.
//part->events()->incARef(-1);
@@ -985,8 +985,8 @@ void Song::cmdAddRecordedEvents(MidiTrack* mt, EventList* events, unsigned start
for (iEvent i = si; i != ei; ++i) {
Event event = i->second;
// Create an undo op. Indicate that controller values and clone parts were handled.
- //undoOp(UndoOp::DeleteEvent, event, part);
- undoOp(UndoOp::DeleteEvent, event, part, true, true);
+ //addUndo(UndoOp(UndoOp::DeleteEvent, event, part));
+ addUndo(UndoOp(UndoOp::DeleteEvent, event, part, true, true));
/*
if (event.type() == Controller) {
MidiTrack* track = (MidiTrack*)part->track();
@@ -1007,8 +1007,8 @@ void Song::cmdAddRecordedEvents(MidiTrack* mt, EventList* events, unsigned start
event.setTick(tick);
// Create an undo op. Indicate that controller values and clone parts were handled.
- //undoOp(UndoOp::AddEvent, event, part);
- undoOp(UndoOp::AddEvent, event, part, true, true);
+ //addUndo(UndoOp(UndoOp::AddEvent, event, part));
+ addUndo(UndoOp(UndoOp::AddEvent, event, part, true, true));
//addEvent(event, part);
if(part->events()->find(event) == part->events()->end())
@@ -1286,7 +1286,7 @@ void Song::setStopPlay(bool f)
void Song::swapTracks(int i1, int i2)
{
- undoOp(UndoOp::SwapTrack, i1, i2);
+ addUndo(UndoOp(UndoOp::SwapTrack, i1, i2));
Track* track = _tracks[i1];
_tracks[i1] = _tracks[i2];
_tracks[i2] = track;
@@ -1906,8 +1906,8 @@ void Song::processMsg(AudioMsg* msg)
updateFlags = SC_EVENT_INSERTED;
if (addEvent(msg->ev1, (MidiPart*)msg->p2)) {
Event ev;
- //undoOp(UndoOp::AddEvent, ev, msg->ev1, (Part*)msg->p2);
- undoOp(UndoOp::AddEvent, ev, msg->ev1, (Part*)msg->p2, msg->a, msg->b);
+ //addUndo(UndoOp(UndoOp::AddEvent, ev, msg->ev1, (Part*)msg->p2));
+ addUndo(UndoOp(UndoOp::AddEvent, ev, msg->ev1, (Part*)msg->p2, msg->a, msg->b));
}
else
updateFlags = 0;
@@ -1921,8 +1921,8 @@ void Song::processMsg(AudioMsg* msg)
if(msg->a)
removePortCtrlEvents(event, part, msg->b);
Event e;
- //undoOp(UndoOp::DeleteEvent, e, event, (Part*)part);
- undoOp(UndoOp::DeleteEvent, e, event, (Part*)part, msg->a, msg->b);
+ //addUndo(UndoOp(UndoOp::DeleteEvent, e, event, (Part*)part));
+ addUndo(UndoOp(UndoOp::DeleteEvent, e, event, (Part*)part, msg->a, msg->b));
deleteEvent(event, part);
updateFlags = SC_EVENT_REMOVED;
}
@@ -1933,21 +1933,21 @@ void Song::processMsg(AudioMsg* msg)
changeEvent(msg->ev1, msg->ev2, (MidiPart*)msg->p3);
if(msg->a)
addPortCtrlEvents(msg->ev2, (Part*)msg->p3, msg->b);
- //undoOp(UndoOp::ModifyEvent, msg->ev2, msg->ev1, (Part*)msg->p3);
- undoOp(UndoOp::ModifyEvent, msg->ev2, msg->ev1, (Part*)msg->p3, msg->a, msg->b);
+ //addUndo(UndoOp(UndoOp::ModifyEvent, msg->ev2, msg->ev1, (Part*)msg->p3));
+ addUndo(UndoOp(UndoOp::ModifyEvent, msg->ev2, msg->ev1, (Part*)msg->p3, msg->a, msg->b));
updateFlags = SC_EVENT_MODIFIED;
break;
case SEQM_ADD_TEMPO:
//printf("processMsg (SEQM_ADD_TEMPO) UndoOp::AddTempo. adding tempo at: %d with tempo=%d\n", msg->a, msg->b);
- undoOp(UndoOp::AddTempo, msg->a, msg->b);
+ addUndo(UndoOp(UndoOp::AddTempo, msg->a, msg->b));
tempomap.addTempo(msg->a, msg->b);
updateFlags = SC_TEMPO;
break;
case SEQM_SET_TEMPO:
//printf("processMsg (SEQM_SET_TEMPO) UndoOp::AddTempo. adding tempo at: %d with tempo=%d\n", msg->a, msg->b);
- undoOp(UndoOp::AddTempo, msg->a, msg->b);
+ addUndo(UndoOp(UndoOp::AddTempo, msg->a, msg->b));
tempomap.setTempo(msg->a, msg->b);
updateFlags = SC_TEMPO;
break;
@@ -1958,31 +1958,31 @@ void Song::processMsg(AudioMsg* msg)
case SEQM_REMOVE_TEMPO:
//printf("processMsg (SEQM_REMOVE_TEMPO) UndoOp::DeleteTempo. adding tempo at: %d with tempo=%d\n", msg->a, msg->b);
- undoOp(UndoOp::DeleteTempo, msg->a, msg->b);
+ addUndo(UndoOp(UndoOp::DeleteTempo, msg->a, msg->b));
tempomap.delTempo(msg->a);
updateFlags = SC_TEMPO;
break;
case SEQM_ADD_SIG:
- undoOp(UndoOp::AddSig, msg->a, msg->b, msg->c);
+ addUndo(UndoOp(UndoOp::AddSig, msg->a, msg->b, msg->c));
AL::sigmap.add(msg->a, AL::TimeSignature(msg->b, msg->c));
updateFlags = SC_SIG;
break;
case SEQM_REMOVE_SIG:
- undoOp(UndoOp::DeleteSig, msg->a, msg->b, msg->c);
+ addUndo(UndoOp(UndoOp::DeleteSig, msg->a, msg->b, msg->c));
AL::sigmap.del(msg->a);
updateFlags = SC_SIG;
break;
case SEQM_ADD_KEY:
- undoOp(UndoOp::AddKey, msg->a, msg->b);
+ addUndo(UndoOp(UndoOp::AddKey, msg->a, msg->b));
keymap.addKey(msg->a, (key_enum) msg->b);
updateFlags = SC_KEY;
break;
case SEQM_REMOVE_KEY:
- undoOp(UndoOp::DeleteKey, msg->a, msg->b);
+ addUndo(UndoOp(UndoOp::DeleteKey, msg->a, msg->b));
keymap.delKey(msg->a);
updateFlags = SC_KEY;
break;
@@ -2000,7 +2000,7 @@ void Song::processMsg(AudioMsg* msg)
void Song::cmdAddPart(Part* part)
{
addPart(part);
- undoOp(UndoOp::AddPart, part);
+ addUndo(UndoOp(UndoOp::AddPart, part));
updateFlags = SC_PART_INSERTED;
}
@@ -2011,7 +2011,7 @@ void Song::cmdAddPart(Part* part)
void Song::cmdRemovePart(Part* part)
{
removePart(part);
- undoOp(UndoOp::DeletePart, part);
+ addUndo(UndoOp(UndoOp::DeletePart, part));
part->events()->incARef(-1);
//part->unchainClone();
unchainClone(part);
@@ -2032,8 +2032,8 @@ void Song::cmdChangePart(Part* oldPart, Part* newPart, bool doCtrls, bool doClon
changePart(oldPart, newPart);
- //undoOp(UndoOp::ModifyPart, oldPart, newPart);
- undoOp(UndoOp::ModifyPart, oldPart, newPart, doCtrls, doClones);
+ //addUndo(UndoOp(UndoOp::ModifyPart, oldPart, newPart));
+ addUndo(UndoOp(UndoOp::ModifyPart, oldPart, newPart, doCtrls, doClones));
// Changed by T356. Do not decrement ref count if the new part is a clone of the old part, since the event list
// will still be active.
diff --git a/muse2/muse/song.h b/muse2/muse/song.h
index 47fd96d4..fd88b278 100644
--- a/muse2/muse/song.h
+++ b/muse2/muse/song.h
@@ -147,6 +147,8 @@ class Song : public QObject {
Song(const char* name = 0);
~Song();
+ bool applyOperationGroup(Undo& group, bool doUndo=true);
+
void putEvent(int pv);
void endMsgCmd();
void processMsg(AudioMsg* msg);
@@ -316,21 +318,9 @@ class Song : public QObject {
void startUndo();
void endUndo(int);
- //void undoOp(UndoOp::UndoType, Track* oTrack, Track* nTrack);
- void undoOp(UndoOp::UndoType, int n, Track* oTrack, Track* nTrack);
- void undoOp(UndoOp::UndoType, int, Track*);
- void undoOp(UndoOp::UndoType, int, int, int = 0);
- void undoOp(UndoOp::UndoType, Part*);
- //void undoOp(UndoOp::UndoType, Event& nevent, Part*);
- void undoOp(UndoOp::UndoType, Event& nevent, Part*, bool doCtrls, bool doClones);
- //void undoOp(UndoOp::UndoType, Event& oevent, Event& nevent, Part*);
- void undoOp(UndoOp::UndoType, Event& oevent, Event& nevent, Part*, bool doCtrls, bool doClones);
- void undoOp(UndoOp::UndoType, SigEvent* oevent, SigEvent* nevent);
- void undoOp(UndoOp::UndoType, int channel, int ctrl, int oval, int nval);
- //void undoOp(UndoOp::UndoType, Part* oPart, Part* nPart);
- void undoOp(UndoOp::UndoType, Part* oPart, Part* nPart, bool doCtrls, bool doClones);
+
void undoOp(UndoOp::UndoType type, const char* changedFile, const char* changeData, int startframe, int endframe);
- void undoOp(UndoOp::UndoType type, Marker* copyMarker, Marker* realMarker);
+
bool doUndo1();
void doUndo2();
void doUndo3();
@@ -338,7 +328,7 @@ class Song : public QObject {
void doRedo2();
void doRedo3();
- void addUndo(UndoOp& i);
+ void addUndo(UndoOp i);
//-----------------------------------------
// Configuration
diff --git a/muse2/muse/structure.cpp b/muse2/muse/structure.cpp
index f0a4308a..27246315 100644
--- a/muse2/muse/structure.cpp
+++ b/muse2/muse/structure.cpp
@@ -99,12 +99,12 @@ void MusE::adjustGlobalLists(int startPos, int diff)
Marker *oldMarker = new Marker();
*oldMarker = *m;
markerlist->remove(m);
- song->undoOp(UndoOp::ModifyMarker,oldMarker, 0);
+ song->addUndo(UndoOp(UndoOp::ModifyMarker,oldMarker, 0));
} else {
Marker *oldMarker = new Marker();
*oldMarker = *m;
m->setTick(tick + diff);
- song->undoOp(UndoOp::ModifyMarker,oldMarker, m);
+ song->addUndo(UndoOp(UndoOp::ModifyMarker,oldMarker, m));
}
}
}
diff --git a/muse2/muse/undo.cpp b/muse2/muse/undo.cpp
index a31b8e7a..0c05ef08 100644
--- a/muse2/muse/undo.cpp
+++ b/muse2/muse/undo.cpp
@@ -14,6 +14,8 @@
#include "song.h"
#include "globals.h"
+#include <QAction>
+
// iundo points to last Undo() in Undo-list
static bool undoMode = false; // for debugging
@@ -75,6 +77,7 @@ void UndoOp::dump()
case ModifyMarker:
case AddKey:
case DeleteKey:
+ case DoNothing:
break;
}
}
@@ -184,6 +187,9 @@ void UndoList::clearDelete()
void Song::startUndo()
{
+ redoList->clear(); // added by flo93: redo must be invalidated when
+ redoAction->setEnabled(false); // a new undo is started
+
undoList->push_back(Undo());
updateFlags = 0;
undoMode = true;
@@ -200,6 +206,34 @@ void Song::endUndo(int flags)
undoMode = false;
}
+
+bool Song::applyOperationGroup(Undo& group, bool doUndo)
+{
+ if (!group.empty())
+ {
+ //this is a HACK! but it works :) (added by flo93)
+ redoList->push_back(group);
+ redo();
+
+ if (!doUndo)
+ {
+ undoList->pop_back();
+ undoAction->setEnabled(!undoList->empty());
+ }
+ else
+ {
+ redoList->clear(); // added by flo93: redo must be invalidated when
+ redoAction->setEnabled(false); // a new undo is started
+ }
+
+ return doUndo;
+ }
+ else
+ return false;
+}
+
+
+
//---------------------------------------------------------
// doUndo2
// real time part
@@ -447,6 +481,7 @@ void Song::doUndo2()
break;
case UndoOp::ModifyClip:
case UndoOp::ModifyMarker:
+ case UndoOp::DoNothing:
break;
}
}
@@ -683,139 +718,120 @@ void Song::doRedo2()
break;
case UndoOp::ModifyClip:
case UndoOp::ModifyMarker:
+ case UndoOp::DoNothing:
break;
}
}
}
-void Song::undoOp(UndoOp::UndoType type, int a, int b, int c)
+UndoOp::UndoOp()
+{
+}
+
+UndoOp::UndoOp(UndoType type_)
+{
+ type = type_;
+}
+
+UndoOp::UndoOp(UndoType type_, int a_, int b_, int c_)
{
- UndoOp i;
- i.type = type;
- i.a = a;
- i.b = b;
- i.c = c;
- addUndo(i);
+ type = type_;
+ a = a_;
+ b = b_;
+ c = c_;
}
-//void Song::undoOp(UndoOp::UndoType type, Track* oldTrack, Track* newTrack)
-void Song::undoOp(UndoOp::UndoType type, int n, Track* oldTrack, Track* newTrack)
+UndoOp::UndoOp(UndoType type_, int n, Track* oldTrack, Track* newTrack)
{
- UndoOp i;
- i.type = type;
- i.trackno = n;
- i.oTrack = oldTrack;
- i.nTrack = newTrack;
- // Added by Tim. p3.3.6
- //printf("Song::undoOp ModifyTrack oTrack %p %s nTrack %p %s\n", i.oTrack, i.oTrack->name().toLatin1().constData(), i.nTrack, i.nTrack->name().toLatin1().constData());
-
- addUndo(i);
+ type = type_;
+ trackno = n;
+ oTrack = oldTrack;
+ nTrack = newTrack;
}
-void Song::undoOp(UndoOp::UndoType type, int n, Track* track)
+UndoOp::UndoOp(UndoType type_, int n, Track* track)
{
- UndoOp i;
- i.type = type;
- i.trackno = n;
- i.oTrack = track;
- if (type == UndoOp::AddTrack)
- updateFlags |= SC_TRACK_INSERTED;
- addUndo(i);
+ type = type_;
+ trackno = n;
+ oTrack = track;
}
-void Song::undoOp(UndoOp::UndoType type, Part* part)
+UndoOp::UndoOp(UndoType type_, Part* part)
{
- UndoOp i;
- i.type = type;
- i.oPart = part;
- addUndo(i);
+ type = type_;
+ oPart = part;
}
-//void Song::undoOp(UndoOp::UndoType type, Event& oev, Event& nev, Part* part)
-void Song::undoOp(UndoOp::UndoType type, Event& oev, Event& nev, Part* part, bool doCtrls, bool doClones)
+UndoOp::UndoOp(UndoType type_, Event& oev, Event& nev, Part* part_, bool doCtrls_, bool doClones_)
{
- UndoOp i;
- i.type = type;
- i.nEvent = nev;
- i.oEvent = oev;
- i.part = part;
- i.doCtrls = doCtrls;
- i.doClones = doClones;
- addUndo(i);
+ type = type_;
+ nEvent = nev;
+ oEvent = oev;
+ part = part_;
+ doCtrls = doCtrls_;
+ doClones = doClones_;
}
-void Song::undoOp(UndoOp::UndoType type, Event& nev, Part* part, bool doCtrls, bool doClones)
+UndoOp::UndoOp(UndoType type_, Event& nev, Part* part_, bool doCtrls_, bool doClones_)
{
- UndoOp i;
- i.type = type;
- i.nEvent = nev;
- i.part = part;
- i.doCtrls = doCtrls;
- i.doClones = doClones;
- addUndo(i);
+ type = type_;
+ nEvent = nev;
+ part = part_;
+ doCtrls = doCtrls_;
+ doClones = doClones_;
}
-//void Song::undoOp(UndoOp::UndoType type, Part* oPart, Part* nPart)
-void Song::undoOp(UndoOp::UndoType type, Part* oPart, Part* nPart, bool doCtrls, bool doClones)
+UndoOp::UndoOp(UndoType type_, Part* oPart_, Part* nPart_, bool doCtrls_, bool doClones_)
{
- UndoOp i;
- i.type = type;
- i.oPart = nPart;
- i.nPart = oPart;
- i.doCtrls = doCtrls;
- i.doClones = doClones;
- addUndo(i);
+ type = type_;
+ oPart = nPart_;
+ nPart = oPart_;
+ doCtrls = doCtrls_;
+ doClones = doClones_;
}
-void Song::undoOp(UndoOp::UndoType type, int c, int ctrl, int ov, int nv)
+UndoOp::UndoOp(UndoType type_, int c, int ctrl_, int ov, int nv)
{
- UndoOp i;
- i.type = type;
- i.channel = c;
- i.ctrl = ctrl;
- i.oVal = ov;
- i.nVal = nv;
- addUndo(i);
+ type = type_;
+ channel = c;
+ ctrl = ctrl_;
+ oVal = ov;
+ nVal = nv;
}
-void Song::undoOp(UndoOp::UndoType type, SigEvent* oevent, SigEvent* nevent)
+UndoOp::UndoOp(UndoType type_, SigEvent* oevent, SigEvent* nevent)
{
- UndoOp i;
- i.type = type;
- i.oSignature = oevent;
- i.nSignature = nevent;
- addUndo(i);
+ type = type_;
+ oSignature = oevent;
+ nSignature = nevent;
}
-
-void Song::undoOp(UndoOp::UndoType type, const char* changedFile, const char* changeData, int startframe, int endframe)
+UndoOp::UndoOp(UndoType type_, Marker* copyMarker_, Marker* realMarker_)
{
- UndoOp i;
- i.type = type;
- i.filename = changedFile;
- i.tmpwavfile = changeData;
- i.startframe = startframe;
- i.endframe = endframe;
- addUndo(i);
- temporaryWavFiles.push_back(QString(changeData));
-
- //printf("Adding ModifyClip undo-operation: origfile=%s tmpfile=%s sf=%d ef=%d\n", changedFile, changeData, startframe, endframe);
+ type = type_;
+ realMarker = realMarker_;
+ copyMarker = copyMarker_;
}
-void Song::undoOp(UndoOp::UndoType type, Marker* copyMarker, Marker* realMarker)
+UndoOp::UndoOp(UndoType type_, const char* changedFile, const char* changeData, int startframe_, int endframe_)
{
- UndoOp i;
- i.type = type;
- i.realMarker = realMarker;
- i.copyMarker = copyMarker;
+ type = type_;
+ filename = changedFile;
+ tmpwavfile = changeData;
+ startframe = startframe_;
+ endframe = endframe_;
+ }
- addUndo(i);
+void Song::undoOp(UndoOp::UndoType type, const char* changedFile, const char* changeData, int startframe, int endframe)
+ {
+ addUndo(UndoOp(type,changedFile,changeData,startframe,endframe));
+ temporaryWavFiles.push_back(QString(changeData));
}
//---------------------------------------------------------
// addUndo
//---------------------------------------------------------
-void Song::addUndo(UndoOp& i)
+void Song::addUndo(UndoOp i)
{
if (!undoMode) {
printf("internal error: undoOp without startUndo()\n");
diff --git a/muse2/muse/undo.h b/muse2/muse/undo.h
index eb5600ef..b8f69d9f 100644
--- a/muse2/muse/undo.h
+++ b/muse2/muse/undo.h
@@ -36,7 +36,8 @@ struct UndoOp {
AddKey, DeleteKey,
SwapTrack,
ModifyClip,
- ModifyMarker
+ ModifyMarker,
+ DoNothing
};
UndoType type;
@@ -83,8 +84,23 @@ struct UndoOp {
Event nEvent;
bool doCtrls;
bool doClones;
+
const char* typeName();
void dump();
+
+ UndoOp();
+ UndoOp(UndoType type, int a, int b, int c=0);
+ UndoOp(UndoType type, int n, Track* oldTrack, Track* newTrack);
+ UndoOp(UndoType type, int n, Track* track);
+ UndoOp(UndoType type, Part* part);
+ UndoOp(UndoType type, Event& oev, Event& nev, Part* part, bool doCtrls, bool doClones);
+ UndoOp(UndoType type, Event& nev, Part* part, bool doCtrls, bool doClones);
+ UndoOp(UndoType type, Part* oPart, Part* nPart, bool doCtrls, bool doClones);
+ UndoOp(UndoType type, int c, int ctrl, int ov, int nv);
+ UndoOp(UndoType type, SigEvent* oevent, SigEvent* nevent);
+ UndoOp(UndoType type, const char* changedFile, const char* changeData, int startframe, int endframe);
+ UndoOp(UndoType type, Marker* copyMarker, Marker* realMarker);
+ UndoOp(UndoType type);
};
class Undo : public std::list<UndoOp> {
diff --git a/muse2/muse/widgets/canvas.cpp b/muse2/muse/widgets/canvas.cpp
index eb89af1e..650b10b7 100644
--- a/muse2/muse/widgets/canvas.cpp
+++ b/muse2/muse/widgets/canvas.cpp
@@ -569,12 +569,9 @@ void Canvas::viewMousePressEvent(QMouseEvent* event)
}
if (curItem && (event->button() == Qt::MidButton)) {
- if (!curItem->isSelected()) {
- selectItem(curItem, true);
- updateSelection();
- redraw();
- }
- startDrag(curItem, ctrl);
+ deleteItem(start); // changed from "start drag" to "delete" by flo93
+ drag = DRAG_DELETE;
+ setCursor();
}
else if (event->button() == Qt::RightButton) {
if (curItem) {
@@ -1209,56 +1206,6 @@ void Canvas::selectLasso(bool toggle)
}
}
-//---------------------------------------------------------
-// endMoveItems
-// dir = 0 move in all directions
-// 1 move only horizontal
-// 2 move only vertical
-//---------------------------------------------------------
-
-void Canvas::endMoveItems(const QPoint& pos, DragType dragtype, int dir)
- {
- startUndo(dragtype);
-
- int dp = y2pitch(pos.y()) - y2pitch(start.y());
- int dx = pos.x() - start.x();
-
- if (dir == 1)
- dp = 0;
- else if (dir == 2)
- dx = 0;
-
-
-
- int modified = 0;
-
- // Removed by T356.
- /*
- for (iCItem i = moving.begin(); i != moving.end(); ++i) {
- int x = i->second->pos().x();
- int y = i->second->pos().y();
- int nx = x + dx;
- int ny = pitch2y(y2pitch(y) + dp);
- QPoint newpos = raster(QPoint(nx, ny));
- selectItem(i->second, true);
-
- if (moveItem(i->second, newpos, dragtype, &modified))
- i->second->move(newpos);
- if (moving.size() == 1) {
- itemReleased(curItem, newpos);
- }
- if (dragtype == MOVE_COPY || dragtype == MOVE_CLONE)
- selectItem(i->second, false);
- }
- */
-
- moveCanvasItems(moving, dp, dx, dragtype, &modified);
-
- endUndo(dragtype, modified);
- moving.clear();
- updateSelection();
- redraw();
- }
//---------------------------------------------------------
// getCurrentDrag
diff --git a/muse2/muse/widgets/canvas.h b/muse2/muse/widgets/canvas.h
index 6e8b9fa8..2eae3d03 100644
--- a/muse2/muse/widgets/canvas.h
+++ b/muse2/muse/widgets/canvas.h
@@ -11,6 +11,7 @@
#include "citem.h"
#include "view.h"
#include "tools.h"
+#include "undo.h"
#include <QWheelEvent>
#include <QMouseEvent>
@@ -100,17 +101,10 @@ class Canvas : public View {
virtual int y2pitch(int) const = 0; //CDW
virtual int pitch2y(int) const = 0; //CDW
- virtual void moveCanvasItems(CItemList&, int, int, DragType, int*) = 0;
- // Changed by T356.
- //virtual bool moveItem(CItem*, const QPoint&, DragType, int*) = 0;
- virtual bool moveItem(CItem*, const QPoint&, DragType) = 0;
virtual CItem* newItem(const QPoint&, int state) = 0;
virtual void resizeItem(CItem*, bool noSnap=false) = 0;
virtual void newItem(CItem*, bool noSnap=false) = 0;
virtual bool deleteItem(CItem*) = 0;
- virtual void startUndo(DragType) = 0;
-
- virtual void endUndo(DragType, int flags) = 0;
int getCurrentDrag();
/*!
@@ -153,7 +147,7 @@ class Canvas : public View {
void startMoving(const QPoint&, DragType);
void moveItems(const QPoint&, int dir, bool rasterize = true);
- void endMoveItems(const QPoint&, DragType, int dir);
+ virtual void endMoveItems(const QPoint&, DragType, int dir) = 0;
virtual void selectLasso(bool toggle);