diff options
-rw-r--r-- | muse2/muse/app.cpp | 47 | ||||
-rw-r--r-- | muse2/muse/app.h | 3 | ||||
-rw-r--r-- | muse2/muse/functions.cpp | 104 | ||||
-rw-r--r-- | muse2/muse/functions.h | 5 | ||||
-rw-r--r-- | muse2/muse/midiedit/scoreedit.cpp | 2 |
5 files changed, 133 insertions, 28 deletions
diff --git a/muse2/muse/app.cpp b/muse2/muse/app.cpp index 9e2f6c9a..6b9f2b5b 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" @@ -977,6 +978,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 +1132,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 +1152,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); @@ -1361,6 +1373,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,7 +1405,7 @@ MusE::MusE(int argc, char** argv) : QMainWindow() menuEdit->addMenu(midiEdit); -#if 0 // TODO +#if 0 // TODO FINDMICH delete! midiEdit->insertItem(tr("Modify Gate Time"), this, SLOT(modifyGateTime())); midiEdit->insertItem(tr("Modify Velocity"), this, SLOT(modifyVelocity())); midiEdit->insertItem(tr("Crescendo"), this, SLOT(crescendo())); @@ -3046,6 +3062,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; } } @@ -3055,37 +3075,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); diff --git a/muse2/muse/app.h b/muse2/muse/app.h index 256154e2..3f539196 100644 --- a/muse2/muse/app.h +++ b/muse2/muse/app.h @@ -80,7 +80,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: @@ -113,6 +113,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; diff --git a/muse2/muse/functions.cpp b/muse2/muse/functions.cpp index a6c9c95a..3d10a878 100644 --- a/muse2/muse/functions.cpp +++ b/muse2/muse/functions.cpp @@ -749,7 +749,7 @@ 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. - operations.push_back(UndoOp(UndoOp::ModifyPart,dest_part, newPart, true, false)); //FINDMICHJETZT oder andersrum? + 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. @@ -831,6 +831,108 @@ void select_not_in_loop(const std::set<Part*>& parts) } +void shrink_parts() +{ + Undo operations; + + 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 (len > part->second->lenTick()) + len = part->second->lenTick(); + + 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() +{ + Undo operations; + + 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 (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 bc2bb8f4..8a1eb3ed 100644 --- a/muse2/muse/functions.h +++ b/muse2/muse/functions.h @@ -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(); +void expand_parts(); +void clean_parts(); + //functions for reading and writing default values class Xml; void read_function_dialog_config(Xml& xml); diff --git a/muse2/muse/midiedit/scoreedit.cpp b/muse2/muse/midiedit/scoreedit.cpp index f1c305d6..450d6f98 100644 --- a/muse2/muse/midiedit/scoreedit.cpp +++ b/muse2/muse/midiedit/scoreedit.cpp @@ -4452,6 +4452,8 @@ void staff_t::update_part_indices() /* BUGS and potential bugs + * o clones aren't marked as clones any more :( + * * o when the keymap is not used, this will probably lead to a bug * o tied notes don't work properly when there's a key-change in * between, for example, when a cis is tied to a des |