From c00e79dd68a68ab0ec30034612d3c8826107b8db Mon Sep 17 00:00:00 2001 From: Robert Jonsson Date: Sun, 8 May 2011 21:20:35 +0000 Subject: structure menu fixes --- muse2/ChangeLog | 2 + muse2/awl/posedit.cpp | 2 + muse2/muse/CMakeLists.txt | 1 + muse2/muse/app.cpp | 280 ++----------------------------- muse2/muse/app.h | 5 +- muse2/muse/marker/marker.h | 2 +- muse2/muse/master/lmaster.cpp | 4 + muse2/muse/part.h | 1 + muse2/muse/song.cpp | 160 ++++++++++-------- muse2/muse/song.h | 4 +- muse2/muse/songfile.cpp | 3 + muse2/muse/structure.cpp | 368 +++++++++++++++++++++++++++++++++++++++++ muse2/muse/undo.cpp | 30 +++- muse2/muse/widgets/songinfo.ui | 7 + 14 files changed, 524 insertions(+), 345 deletions(-) create mode 100644 muse2/muse/structure.cpp diff --git a/muse2/ChangeLog b/muse2/ChangeLog index ab11a07b..291bcd6f 100644 --- a/muse2/ChangeLog +++ b/muse2/ChangeLog @@ -1,5 +1,7 @@ 08.05.2011: - Draw event canvas notes if they extend past part end. (Tim) + - Added checkbox to select if songinfo should be displayed on song start (rj) + - fixups to structure functions, now inserts/cuts markers, and master track events with undo (rj) 06.05.2011: - MusE 2.0beta2 released (rj) - Added Yamaha-CS1x.idf instrument from Ernie Rymer Thanks! (Tim) diff --git a/muse2/awl/posedit.cpp b/muse2/awl/posedit.cpp index e9cddd44..6ca49566 100644 --- a/muse2/awl/posedit.cpp +++ b/muse2/awl/posedit.cpp @@ -433,6 +433,8 @@ QValidator::State PosEdit::validate(QString& s,int& /*i*/) const int tb = AL::sigmap.ticksBeat(_pos.tick()); unsigned tm = AL::sigmap.ticksMeasure(_pos.tick()); + if (tm==0) + return QValidator::Invalid; int bm = tm / tb; validator->setRange(1, 9999); diff --git a/muse2/muse/CMakeLists.txt b/muse2/muse/CMakeLists.txt index 2d2a9fe3..d89bb007 100644 --- a/muse2/muse/CMakeLists.txt +++ b/muse2/muse/CMakeLists.txt @@ -120,6 +120,7 @@ file (GLOB core_source_files song.cpp songfile.cpp stringparam.cpp + structure.cpp sync.cpp synth.cpp tempo.cpp diff --git a/muse2/muse/app.cpp b/muse2/muse/app.cpp index 052bb48b..59993911 100644 --- a/muse2/muse/app.cpp +++ b/muse2/muse/app.cpp @@ -974,10 +974,10 @@ MusE::MusE(int argc, char** argv) : QMainWindow() editCopyAction = new QAction(QIcon(*editcopyIconSet), tr("&Copy"), this); editPasteAction = new QAction(QIcon(*editpasteIconSet), tr("&Paste"), this); editInsertAction = new QAction(QIcon(*editpasteIconSet), tr("&Insert"), this); + editInsertEMAction = new QAction(QIcon(*editpasteIconSet), tr("&Insert Empty Measure"), this); editPasteCloneAction = new QAction(QIcon(*editpasteCloneIconSet), tr("Paste c&lone"), this); editPaste2TrackAction = new QAction(QIcon(*editpaste2TrackIconSet), tr("Paste to &track"), this); editPasteC2TAction = new QAction(QIcon(*editpasteClone2TrackIconSet), tr("Paste clone to trac&k"), this); - editInsertEMAction = new QAction(QIcon(*editpasteIconSet), tr("&Insert Empty Measure"), this); editDeleteSelectedAction = new QAction(QIcon(*edit_track_delIcon), tr("Delete Selected Tracks"), this); @@ -1123,10 +1123,10 @@ MusE::MusE(int argc, char** argv) : QMainWindow() connect(editCopyAction, SIGNAL(triggered()), editSignalMapper, SLOT(map())); connect(editPasteAction, SIGNAL(triggered()), editSignalMapper, SLOT(map())); connect(editInsertAction, SIGNAL(triggered()), editSignalMapper, SLOT(map())); + connect(editInsertEMAction, SIGNAL(triggered()), editSignalMapper, SLOT(map())); connect(editPasteCloneAction, SIGNAL(triggered()), editSignalMapper, SLOT(map())); connect(editPaste2TrackAction, SIGNAL(triggered()), editSignalMapper, SLOT(map())); connect(editPasteC2TAction, SIGNAL(triggered()), editSignalMapper, SLOT(map())); - connect(editInsertEMAction, SIGNAL(triggered()), editSignalMapper, SLOT(map())); connect(editDeleteSelectedAction, SIGNAL(triggered()), editSignalMapper, SLOT(map())); connect(editSelectAllAction, SIGNAL(triggered()), editSignalMapper, SLOT(map())); @@ -1183,7 +1183,7 @@ MusE::MusE(int argc, char** argv) : QMainWindow() connect(strGlobalCutAction, SIGNAL(activated()), SLOT(globalCut())); connect(strGlobalInsertAction, SIGNAL(activated()), SLOT(globalInsert())); connect(strGlobalSplitAction, SIGNAL(activated()), SLOT(globalSplit())); - connect(strCopyRangeAction, SIGNAL(activated()), SLOT(copyRange())); + connect(strCopyRangeAction, SIGNAL(activated()), SLOT(copyRange())); connect(strCutEventsAction, SIGNAL(activated()), SLOT(cutEvents())); //-------- Midi connections @@ -1357,10 +1357,10 @@ MusE::MusE(int argc, char** argv) : QMainWindow() menuEdit->addAction(editCopyAction); menuEdit->addAction(editPasteAction); menuEdit->addAction(editInsertAction); + menuEdit->addAction(editInsertEMAction); menuEdit->addAction(editPasteCloneAction); menuEdit->addAction(editPaste2TrackAction); menuEdit->addAction(editPasteC2TAction); - menuEdit->addAction(editInsertEMAction); menuEdit->addSeparator(); menuEdit->addAction(editDeleteSelectedAction); @@ -1738,14 +1738,16 @@ void MusE::loadProjectFile(const QString& name, bool songTemplate, bool loadAll) if (restartSequencer) seqStart(); - if (song->getSongInfo().length()>0) - startSongInfo(false); - visTracks->updateVisibleTracksButtons(); progress->setValue(100); delete progress; progress=0; + QApplication::restoreOverrideCursor(); + + if (song->getSongInfo().length()>0 && song->showSongInfoOnStartup()) { + startSongInfo(false); + } } //--------------------------------------------------------- @@ -3378,7 +3380,7 @@ bool MusE::saveAs() return false; } - song->setSongInfo(pci.getSongInfo()); + song->setSongInfo(pci.getSongInfo(), true); name = pci.getProjectPath(); } else { name = getSaveFileName(QString(""), med_file_save_pattern, this, tr("MusE: Save As")); @@ -3670,12 +3672,16 @@ void MusE::startWaveEditor(PartList* pl) void MusE::startSongInfo(bool editable) { SongInfoWidget info; + info.viewCheckBox->setChecked(song->showSongInfoOnStartup()); + info.viewCheckBox->setEnabled(editable); info.songInfoText->setPlainText(song->getSongInfo()); info.songInfoText->setReadOnly(!editable); + info.setModal(true); info.show(); if( info.exec() == QDialog::Accepted) { - if (editable) - song->setSongInfo(info.songInfoText->toPlainText()); + if (editable) { + song->setSongInfo(info.songInfoText->toPlainText(), info.viewCheckBox->isChecked()); + } } } @@ -3691,7 +3697,7 @@ void MusE::showDidYouKnowDialog() dyk.show(); if( dyk.exec()) { if (dyk.dontShowCheckBox->isChecked()) { - printf("disables dialog!\n"); + //printf("disables dialog!\n"); config.showDidYouKnow=false; muse->changeConfig(true); // save settings } @@ -4389,256 +4395,6 @@ void MusE::configShortCuts() changeConfig(true); } -//--------------------------------------------------------- -// globalCut -// - remove area between left and right locator -// - do not touch muted track -// - cut master track -//--------------------------------------------------------- - -void MusE::globalCut() - { - int lpos = song->lpos(); - int rpos = song->rpos(); - if ((lpos - rpos) >= 0) - return; - - song->startUndo(); - TrackList* tracks = song->tracks(); - for (iTrack it = tracks->begin(); it != tracks->end(); ++it) { - MidiTrack* track = dynamic_cast(*it); - if (track == 0 || track->mute()) - continue; - PartList* pl = track->parts(); - for (iPart p = pl->begin(); p != pl->end(); ++p) { - Part* part = p->second; - int t = part->tick(); - int l = part->lenTick(); - if (t + l <= lpos) - continue; - if ((t >= lpos) && ((t+l) <= rpos)) { - audio->msgRemovePart(part, false); - } - else if ((t < lpos) && ((t+l) > lpos) && ((t+l) <= rpos)) { - // remove part tail - int len = lpos - t; - MidiPart* nPart = new MidiPart(*(MidiPart*)part); - nPart->setLenTick(len); - // - // cut Events in nPart - EventList* el = nPart->events(); - iEvent ie = el->lower_bound(t + len); - for (; ie != el->end();) { - iEvent i = ie; - ++ie; - // Indicate no undo, and do not do port controller values and clone parts. - //audio->msgDeleteEvent(i->second, nPart, false); - audio->msgDeleteEvent(i->second, nPart, false, false, false); - } - // Indicate no undo, and do port controller values and clone parts. - //audio->msgChangePart(part, nPart, false); - audio->msgChangePart(part, nPart, false, true, true); - } - else if ((t < lpos) && ((t+l) > lpos) && ((t+l) > rpos)) { - //---------------------- - // remove part middle - //---------------------- - - MidiPart* nPart = new MidiPart(*(MidiPart*)part); - EventList* el = nPart->events(); - iEvent is = el->lower_bound(lpos); - iEvent ie = el->upper_bound(rpos); - for (iEvent i = is; i != ie;) { - iEvent ii = i; - ++i; - // Indicate no undo, and do not do port controller values and clone parts. - //audio->msgDeleteEvent(ii->second, nPart, false); - audio->msgDeleteEvent(ii->second, nPart, false, false, false); - } - - ie = el->lower_bound(rpos); - for (; ie != el->end();) { - iEvent i = ie; - ++ie; - Event event = i->second; - Event nEvent = event.clone(); - nEvent.setTick(nEvent.tick() - (rpos-lpos)); - // Indicate no undo, and do not do port controller values and clone parts. - //audio->msgChangeEvent(event, nEvent, nPart, false); - audio->msgChangeEvent(event, nEvent, nPart, false, false, false); - } - nPart->setLenTick(l - (rpos-lpos)); - // Indicate no undo, and do port controller values and clone parts. - //audio->msgChangePart(part, nPart, false); - audio->msgChangePart(part, nPart, false, true, true); - } - else if ((t >= lpos) && (t < rpos) && (t+l) > rpos) { - // TODO: remove part head - } - else if (t >= rpos) { - MidiPart* nPart = new MidiPart(*(MidiPart*)part); - int nt = part->tick(); - nPart->setTick(nt - (rpos -lpos)); - // Indicate no undo, and do port controller values but not clone parts. - //audio->msgChangePart(part, nPart, false); - audio->msgChangePart(part, nPart, false, true, false); - } - } - } - // TODO: cut tempo track - // TODO: process marker - song->endUndo(SC_TRACK_MODIFIED | SC_PART_MODIFIED | SC_PART_REMOVED); - } - -//--------------------------------------------------------- -// globalInsert -// - insert empty space at left locator position upto -// right locator -// - do not touch muted track -// - insert in master track -//--------------------------------------------------------- - -void MusE::globalInsert() - { - unsigned lpos = song->lpos(); - unsigned rpos = song->rpos(); - if (lpos >= rpos) - return; - - song->startUndo(); - TrackList* tracks = song->tracks(); - for (iTrack it = tracks->begin(); it != tracks->end(); ++it) { - MidiTrack* track = dynamic_cast(*it); - // - // process only non muted midi tracks - // - if (track == 0 || track->mute()) - continue; - PartList* pl = track->parts(); - for (iPart p = pl->begin(); p != pl->end(); ++p) { - Part* part = p->second; - unsigned t = part->tick(); - int l = part->lenTick(); - if (t + l <= lpos) - continue; - if (lpos >= t && lpos < (t+l)) { - MidiPart* nPart = new MidiPart(*(MidiPart*)part); - nPart->setLenTick(l + (rpos-lpos)); - EventList* el = nPart->events(); - - iEvent i = el->end(); - while (i != el->begin()) { - --i; - if (i->first < lpos) - break; - Event event = i->second; - Event nEvent = i->second.clone(); - nEvent.setTick(nEvent.tick() + (rpos-lpos)); - // Indicate no undo, and do not do port controller values and clone parts. - //audio->msgChangeEvent(event, nEvent, nPart, false); - audio->msgChangeEvent(event, nEvent, nPart, false, false, false); - } - // Indicate no undo, and do port controller values and clone parts. - //audio->msgChangePart(part, nPart, false); - audio->msgChangePart(part, nPart, false, true, true); - } - else if (t > lpos) { - MidiPart* nPart = new MidiPart(*(MidiPart*)part); - nPart->setTick(t + (rpos -lpos)); - // Indicate no undo, and do port controller values but not clone parts. - //audio->msgChangePart(part, nPart, false); - audio->msgChangePart(part, nPart, false, true, false); - } - } - } - // TODO: process tempo track - // TODO: process marker - song->endUndo(SC_TRACK_MODIFIED | SC_PART_MODIFIED | SC_PART_REMOVED); - } - -//--------------------------------------------------------- -// globalSplit -// - split all parts at the song position pointer -// - do not touch muted track -//--------------------------------------------------------- - -void MusE::globalSplit() - { - int pos = song->cpos(); - song->startUndo(); - TrackList* tracks = song->tracks(); - for (iTrack it = tracks->begin(); it != tracks->end(); ++it) { - Track* track = *it; - PartList* pl = track->parts(); - for (iPart p = pl->begin(); p != pl->end(); ++p) { - Part* part = p->second; - int p1 = part->tick(); - int l0 = part->lenTick(); - if (pos > p1 && pos < (p1+l0)) { - Part* p1; - Part* p2; - track->splitPart(part, pos, p1, p2); - // Indicate no undo, and do port controller values but not clone parts. - //audio->msgChangePart(part, p1, false); - audio->msgChangePart(part, p1, false, true, false); - audio->msgAddPart(p2, false); - break; - } - } - } - song->endUndo(SC_TRACK_MODIFIED | SC_PART_MODIFIED | SC_PART_INSERTED); - } - -//--------------------------------------------------------- -// copyRange -// - copy space between left and right locator position -// to song position pointer -// - dont process muted tracks -// - create a new part for every track containing the -// copied events -//--------------------------------------------------------- - -void MusE::copyRange() - { - QMessageBox::critical(this, - tr("MusE: Copy Range"), - tr("not implemented") - ); - } - -//--------------------------------------------------------- -// cutEvents -// - make sure that all events in a part end where the -// part ends -// - process only marked parts -//--------------------------------------------------------- - -void MusE::cutEvents() - { - QMessageBox::critical(this, - tr("MusE: Cut Events"), - tr("not implemented") - ); - } - -//--------------------------------------------------------- -// checkRegionNotNull -// return true if (rPos - lPos) <= 0 -//--------------------------------------------------------- - -bool MusE::checkRegionNotNull() - { - int start = song->lPos().frame(); - int end = song->rPos().frame(); - if (end - start <= 0) { - QMessageBox::critical(this, - tr("MusE: Bounce"), - tr("set left/right marker for bounce range") - ); - return true; - } - return false; - } #if 0 //--------------------------------------------------------- @@ -5050,10 +4806,10 @@ void MusE::updateConfiguration() editCopyAction->setShortcut(shortcuts[SHRT_COPY].key); editPasteAction->setShortcut(shortcuts[SHRT_PASTE].key); editInsertAction->setShortcut(shortcuts[SHRT_INSERT].key); + editInsertEMAction->setShortcut(shortcuts[SHRT_INSERTMEAS].key); editPasteCloneAction->setShortcut(shortcuts[SHRT_PASTE_CLONE].key); editPaste2TrackAction->setShortcut(shortcuts[SHRT_PASTE_TO_TRACK].key); editPasteC2TAction->setShortcut(shortcuts[SHRT_PASTE_CLONE_TO_TRACK].key); - editInsertEMAction->setShortcut(shortcuts[SHRT_INSERTMEAS].key); //editDeleteSelectedAction has no acceleration diff --git a/muse2/muse/app.h b/muse2/muse/app.h index 2fd83854..42aebf3b 100644 --- a/muse2/muse/app.h +++ b/muse2/muse/app.h @@ -108,7 +108,7 @@ class MusE : public QMainWindow // Edit Menu actions QAction *editCutAction, *editCopyAction, *editPasteAction, *editInsertAction, *editPasteCloneAction, *editPaste2TrackAction; - QAction *editPasteC2TAction, *editInsertEMAction, *editDeleteSelectedAction, *editSelectAllAction, *editDeselectAllAction; + QAction *editInsertEMAction, *editPasteC2TAction, *editDeleteSelectedAction, *editSelectAllAction, *editDeselectAllAction; QAction *editInvertSelectionAction, *editInsideLoopAction, *editOutsideLoopAction, *editAllPartsAction; QAction *trackMidiAction, *trackDrumAction, *trackWaveAction, *trackAOutputAction, *trackAGroupAction; QAction *trackAInputAction, *trackAAuxAction; @@ -334,6 +334,9 @@ class MusE : public QMainWindow void execDeliveredScript(int); void execUserScript(int); + private: + void adjustGlobalLists(int startPos, int diff); + public slots: bool saveAs(); diff --git a/muse2/muse/marker/marker.h b/muse2/muse/marker/marker.h index f1a587f7..012cce80 100644 --- a/muse2/muse/marker/marker.h +++ b/muse2/muse/marker/marker.h @@ -24,7 +24,7 @@ class Marker : public Pos { bool _current; public: - Marker() : _current(false) {} + Marker() : _name(""),_current(false) {} Marker(const QString& s, bool cur = false) : _name(s), _current(cur) {} void read(Xml&); diff --git a/muse2/muse/master/lmaster.cpp b/muse2/muse/master/lmaster.cpp index 21cadfdd..2f921cdc 100644 --- a/muse2/muse/master/lmaster.cpp +++ b/muse2/muse/master/lmaster.cpp @@ -207,13 +207,17 @@ LMaster::LMaster() updateList(); tempo_editor = new QLineEdit(view->viewport()); + tempo_editor->hide(); connect(tempo_editor, SIGNAL(returnPressed()), SLOT(returnPressed())); sig_editor = new SigEdit(view->viewport()); + sig_editor->hide(); connect(sig_editor, SIGNAL(returnPressed()), SLOT(returnPressed())); pos_editor = new Awl::PosEdit(view->viewport()); + pos_editor->hide(); connect(pos_editor, SIGNAL(returnPressed()), SLOT(returnPressed())); key_editor = new QComboBox(view->viewport()); key_editor->addItems(keyStrs); + key_editor->hide(); connect(key_editor, SIGNAL(currentIndexChanged(int)), SLOT(returnPressed())); connect(view, SIGNAL(currentItemChanged(QTreeWidgetItem*, QTreeWidgetItem*)), SLOT(select(QTreeWidgetItem*, QTreeWidgetItem*))); diff --git a/muse2/muse/part.h b/muse2/muse/part.h index 11ff2fd4..f7a864e5 100644 --- a/muse2/muse/part.h +++ b/muse2/muse/part.h @@ -143,6 +143,7 @@ class WavePart : public Part { //--------------------------------------------------------- typedef std::multimap >::iterator iPart; +typedef std::multimap >::reverse_iterator riPart; typedef std::multimap >::const_iterator ciPart; class PartList : public std::multimap > { diff --git a/muse2/muse/song.cpp b/muse2/muse/song.cpp index cf040348..e6fa9cab 100644 --- a/muse2/muse/song.cpp +++ b/muse2/muse/song.cpp @@ -17,6 +17,8 @@ #include #include #include +#include +#include #include "app.h" #include "driver/jackmidi.h" @@ -85,6 +87,7 @@ Song::Song(const char* name) redoList = new UndoList; _markerList = new MarkerList; _globalPitchShift = 0; + showSongInfo=true; clear(false); } @@ -1767,6 +1770,24 @@ Marker* Song::setMarkerLock(Marker* m, bool f) return m; } +// kommer inte att gå göra undo på, kanske skulle fixa det. + +//void Song::moveMarkers(int startOffset, int ticks) +//{ +// iMarker markerI; +// for (markerI=_markerList->rbegin(); markerI != _markerList->rend(); ++markerI) { +// if (markerI->second.tick() > startOffset) { +// if (markerI-> ) +// } +// +// +// +// if (unsigned(t) == markerI->second.tick())//prevent of copmiler warning: comparison signed/unsigned +// return &markerI->second; +// } +// +//} + //--------------------------------------------------------- // setRecordFlag //--------------------------------------------------------- @@ -3696,79 +3717,74 @@ void Song::executeScript(const char* scriptfile, PartList* parts, int quant, boo } fclose(fp); - // Call external program, let it manipulate the file - int pid = fork(); - if (pid == 0) { - if (execlp(scriptfile, scriptfile, tmp, NULL) == -1) { - perror("Failed to launch script!"); - // Get out of here - - // cannot report error through gui, we are in another fork! - //@!TODO: Handle unsuccessful attempts - exit(99); - } - exit(0); - } - else if (pid == -1) { - perror("fork failed"); - } - else { - int status; - waitpid(pid, &status, 0); - if (WEXITSTATUS(status) != 0 ) { - QMessageBox::warning(muse, tr("MusE - external script failed"), - tr("MusE was unable to launch the script\n") - ); - endUndo(SC_EVENT_REMOVED); - return; - } - else { // d0 the fun55or5! - // TODO: Create a new part, update the entire editor from it, hehh.... - - QFile file(tmp); - if ( file.open( QIODevice::ReadOnly ) ) { - QTextStream stream( &file ); - QString line; - while ( !stream.atEnd() ) { - line = stream.readLine(); // line of text excluding '\n' - if (line.startsWith("NOTE")) - { - QStringList sl = line.split(" "); - - Event e(Note); - int tick = sl[1].toInt(); - int pitch = sl[2].toInt(); - int len = sl[3].toInt(); - int velo = sl[4].toInt(); - printf ("tick=%d pitch=%d velo=%d len=%d\n", tick,pitch,velo,len); - e.setTick(tick); - e.setPitch(pitch); - e.setVelo(velo); - e.setLenTick(len); - // Indicate no undo, and do not do port controller values and clone parts. - audio->msgAddEvent(e, part, false, false, false); - } - if (line.startsWith("CONTROLLER")) - { - QStringList sl = line.split(" "); - - Event e(Controller); - int tick = sl[1].toInt(); - int a = sl[2].toInt(); - int b = sl[3].toInt(); - int c = sl[4].toInt(); - printf ("tick=%d a=%d b=%d c=%d\n", tick,a,b,c); - e.setA(a); - e.setB(b); - e.setB(c); - // Indicate no undo, and do not do port controller values and clone parts. - audio->msgAddEvent(e, part, false, false, false); - } - } - file.close(); - } - } +// QString program(scriptfile); + QStringList arguments; + arguments << tmp; + + QProcess *myProcess = new QProcess(muse); + myProcess->start(scriptfile, arguments); + myProcess->waitForFinished(); + QByteArray errStr = myProcess->readAllStandardError(); + if (errStr.size()) { + QMessageBox::warning(muse, tr("MusE - external script failed"), + "Script returned the following error\n"+ QString(errStr)); + endUndo(SC_EVENT_REMOVED); + return; + + } else if (myProcess->exitCode()) { + QMessageBox::warning(muse, tr("MusE - external script failed"), + tr("MusE was unable to launch the script\n") + ); + endUndo(SC_EVENT_REMOVED); + return; } + else { // d0 the fun55or5! + // TODO: Create a new part, update the entire editor from it, hehh.... + + QFile file(tmp); + if ( file.open( QIODevice::ReadOnly ) ) { + QTextStream stream( &file ); + QString line; + while ( !stream.atEnd() ) { + line = stream.readLine(); // line of text excluding '\n' + if (line.startsWith("NOTE")) + { + QStringList sl = line.split(" "); + + Event e(Note); + int tick = sl[1].toInt(); + int pitch = sl[2].toInt(); + int len = sl[3].toInt(); + int velo = sl[4].toInt(); + //printf ("tick=%d pitch=%d velo=%d len=%d\n", tick,pitch,velo,len); + e.setTick(tick); + e.setPitch(pitch); + e.setVelo(velo); + e.setLenTick(len); + // Indicate no undo, and do not do port controller values and clone parts. + audio->msgAddEvent(e, part, false, false, false); + } + if (line.startsWith("CONTROLLER")) + { + QStringList sl = line.split(" "); + + Event e(Controller); + int tick = sl[1].toInt(); + int a = sl[2].toInt(); + int b = sl[3].toInt(); + int c = sl[4].toInt(); + //printf ("tick=%d a=%d b=%d c=%d\n", tick,a,b,c); + e.setA(a); + e.setB(b); + e.setB(c); + // Indicate no undo, and do not do port controller values and clone parts. + audio->msgAddEvent(e, part, false, false, false); + } + } + file.close(); + } + } + remove(tmp); } diff --git a/muse2/muse/song.h b/muse2/muse/song.h index b097a5ee..e1378480 100644 --- a/muse2/muse/song.h +++ b/muse2/muse/song.h @@ -139,6 +139,7 @@ class Song : public QObject { void readMarker(Xml&); QString songInfoStr; // contains user supplied song information, stored in song file. + bool showSongInfo; QStringList deliveredScriptNames; QStringList userScriptNames; @@ -167,7 +168,8 @@ class Song : public QObject { const QFont& font) const; QFont readFont(Xml& xml, const char* name); QString getSongInfo() { return songInfoStr; } - void setSongInfo(QString info) { songInfoStr = info; } + void setSongInfo(QString info, bool show) { songInfoStr = info; showSongInfo = show; } + bool showSongInfoOnStartup() { return showSongInfo; } // If clear_all is false, it will not touch things like midi ports. void clear(bool signal, bool clear_all = true); diff --git a/muse2/muse/songfile.cpp b/muse2/muse/songfile.cpp index 9a577308..a8134b1d 100644 --- a/muse2/muse/songfile.cpp +++ b/muse2/muse/songfile.cpp @@ -1232,6 +1232,8 @@ void Song::read(Xml& xml) setMasterFlag(xml.parseInt()); else if (tag == "info") songInfoStr = xml.parse1(); + else if (tag == "showinfo") + showSongInfo = xml.parseInt(); else if (tag == "loop") setLoop(xml.parseInt()); else if (tag == "punchin") @@ -1437,6 +1439,7 @@ void Song::write(int level, Xml& xml) const { xml.tag(level++, "song"); xml.strTag(level, "info", songInfoStr); + xml.intTag(level, "showinfo", showSongInfo); xml.intTag(level, "automation", automation); xml.intTag(level, "cpos", song->cpos()); xml.intTag(level, "rpos", song->rpos()); diff --git a/muse2/muse/structure.cpp b/muse2/muse/structure.cpp new file mode 100644 index 00000000..f0a4308a --- /dev/null +++ b/muse2/muse/structure.cpp @@ -0,0 +1,368 @@ +//========================================================= +// MusE +// Linux Music Editor +// $Id: app.cpp,v 1.113.2.68 2009/12/21 14:51:51 spamatica Exp $ +// +// (C) Copyright 1999-2004 Werner Schweer (ws@seh.de) +// (C) Copyright 2011 Robert Jonsson (rj@spamatica.se) +//========================================================= + +#include +#include "app.h" +#include "track.h" +#include "song.h" +#include "tempo.h" +#include "al/sig.h" +#include "keyevent.h" +#include "audio.h" +#include "marker/marker.h" + + +//--------------------------------------------------------- +// adjustGlobalLists +// helper that adjusts tempo, sig, key and marker +// lists everything from startPos is adjusted +// 'diff' number of ticks. +// function requires undo to be handled outside +//--------------------------------------------------------- + +void MusE::adjustGlobalLists(int startPos, int diff) +{ + const TempoList* t = &tempomap; + const AL::SigList* s = &AL::sigmap; + const KeyList* k = &keymap; + + criTEvent it = t->rbegin(); + AL::criSigEvent is = s->rbegin(); + criKeyEvent ik = k->rbegin(); + + // key + for (; ik != k->rend(); ik++) { + const KeyEvent &ev = (KeyEvent)ik->second; + int tick = ev.tick; + int key = ev.key; + if (tick < startPos ) + break; + + if (tick > startPos && tick +diff < startPos ) { // remove + audio->msgRemoveKey(tick, key, false); + } + else { + audio->msgRemoveKey(tick, key, false); + audio->msgAddKey(tick+diff, key, false); + } + } + + // tempo + for (; it != t->rend(); it++) { + const TEvent* ev = (TEvent*)it->second; + int tick = ev->tick; + int tempo = ev->tempo; + if (tick < startPos ) + break; + + if (tick > startPos && tick +diff < startPos ) { // remove + audio->msgDeleteTempo(tick, tempo, false); + } + else { + audio->msgDeleteTempo(tick, tempo, false); + audio->msgAddTempo(tick+diff, tempo, false); + } + } + + // sig + for (; is != s->rend(); is++) { + const AL::SigEvent* ev = (AL::SigEvent*)is->second; + int tick = ev->tick; + if (tick < startPos ) + break; + + int z = ev->sig.z; + int n = ev->sig.n; + if (tick > startPos && tick +diff < startPos ) { // remove + audio->msgRemoveSig(tick, z, n, false); + } + else { + audio->msgRemoveSig(tick, z, n, false); + audio->msgAddSig(tick+diff, z, n, false); + } + } + + MarkerList *markerlist = song->marker(); + for(iMarker i = markerlist->begin(); i != markerlist->end(); ++i) + { + Marker* m = &i->second; + int tick = m->tick(); + if (tick > startPos) + { + if (tick + diff < startPos ) { // these ticks should be removed + Marker *oldMarker = new Marker(); + *oldMarker = *m; + markerlist->remove(m); + song->undoOp(UndoOp::ModifyMarker,oldMarker, 0); + } else { + Marker *oldMarker = new Marker(); + *oldMarker = *m; + m->setTick(tick + diff); + song->undoOp(UndoOp::ModifyMarker,oldMarker, m); + } + } + } + +} + +//--------------------------------------------------------- +// globalCut +// - remove area between left and right locator +// - do not touch muted track +// - cut master track +//--------------------------------------------------------- + +void MusE::globalCut() + { + int lpos = song->lpos(); + int rpos = song->rpos(); + if ((lpos - rpos) >= 0) + return; + + song->startUndo(); + TrackList* tracks = song->tracks(); + for (iTrack it = tracks->begin(); it != tracks->end(); ++it) { + MidiTrack* track = dynamic_cast(*it); + if (track == 0 || track->mute()) + continue; + PartList* pl = track->parts(); + for (iPart p = pl->begin(); p != pl->end(); ++p) { + Part* part = p->second; + int t = part->tick(); + int l = part->lenTick(); + if (t + l <= lpos) + continue; + if ((t >= lpos) && ((t+l) <= rpos)) { + audio->msgRemovePart(part, false); + } + else if ((t < lpos) && ((t+l) > lpos) && ((t+l) <= rpos)) { + // remove part tail + int len = lpos - t; + MidiPart* nPart = new MidiPart(*(MidiPart*)part); + nPart->setLenTick(len); + // + // cut Events in nPart + EventList* el = nPart->events(); + iEvent ie = el->lower_bound(t + len); + for (; ie != el->end();) { + iEvent i = ie; + ++ie; + // Indicate no undo, and do not do port controller values and clone parts. + //audio->msgDeleteEvent(i->second, nPart, false); + audio->msgDeleteEvent(i->second, nPart, false, false, false); + } + // Indicate no undo, and do port controller values and clone parts. + //audio->msgChangePart(part, nPart, false); + audio->msgChangePart(part, nPart, false, true, true); + } + else if ((t < lpos) && ((t+l) > lpos) && ((t+l) > rpos)) { + //---------------------- + // remove part middle + //---------------------- + + MidiPart* nPart = new MidiPart(*(MidiPart*)part); + EventList* el = nPart->events(); + iEvent is = el->lower_bound(lpos); + iEvent ie = el->upper_bound(rpos); + for (iEvent i = is; i != ie;) { + iEvent ii = i; + ++i; + // Indicate no undo, and do not do port controller values and clone parts. + //audio->msgDeleteEvent(ii->second, nPart, false); + audio->msgDeleteEvent(ii->second, nPart, false, false, false); + } + + ie = el->lower_bound(rpos); + for (; ie != el->end();) { + iEvent i = ie; + ++ie; + Event event = i->second; + Event nEvent = event.clone(); + nEvent.setTick(nEvent.tick() - (rpos-lpos)); + // Indicate no undo, and do not do port controller values and clone parts. + //audio->msgChangeEvent(event, nEvent, nPart, false); + audio->msgChangeEvent(event, nEvent, nPart, false, false, false); + } + nPart->setLenTick(l - (rpos-lpos)); + // Indicate no undo, and do port controller values and clone parts. + //audio->msgChangePart(part, nPart, false); + audio->msgChangePart(part, nPart, false, true, true); + } + else if ((t >= lpos) && (t < rpos) && (t+l) > rpos) { + // TODO: remove part head + } + else if (t >= rpos) { + MidiPart* nPart = new MidiPart(*(MidiPart*)part); + int nt = part->tick(); + nPart->setTick(nt - (rpos -lpos)); + // Indicate no undo, and do port controller values but not clone parts. + //audio->msgChangePart(part, nPart, false); + audio->msgChangePart(part, nPart, false, true, false); + } + } + } + int diff = lpos - rpos; + adjustGlobalLists(lpos, diff); + + song->endUndo(SC_TRACK_MODIFIED | SC_PART_MODIFIED | SC_PART_REMOVED | SC_TEMPO | SC_KEY | SC_SIG); + } + +//--------------------------------------------------------- +// globalInsert +// - insert empty space at left locator position upto +// right locator +// - do not touch muted track +// - insert in master track +//--------------------------------------------------------- + +void MusE::globalInsert() + { + unsigned lpos = song->lpos(); + unsigned rpos = song->rpos(); + if (lpos >= rpos) + return; + + song->startUndo(); + TrackList* tracks = song->tracks(); + for (iTrack it = tracks->begin(); it != tracks->end(); ++it) { + MidiTrack* track = dynamic_cast(*it); + // + // process only non muted midi tracks + // + if (track == 0 || track->mute()) + continue; + PartList* pl = track->parts(); + for (riPart p = pl->rbegin(); p != pl->rend(); ++p) { + Part* part = p->second; + unsigned t = part->tick(); + int l = part->lenTick(); + if (t + l <= lpos) + continue; + if (lpos >= t && lpos < (t+l)) { + MidiPart* nPart = new MidiPart(*(MidiPart*)part); + nPart->setLenTick(l + (rpos-lpos)); + EventList* el = nPart->events(); + + iEvent i = el->end(); + while (i != el->begin()) { + --i; + if (i->first < lpos) + break; + Event event = i->second; + Event nEvent = i->second.clone(); + nEvent.setTick(nEvent.tick() + (rpos-lpos)); + // Indicate no undo, and do not do port controller values and clone parts. + //audio->msgChangeEvent(event, nEvent, nPart, false); + audio->msgChangeEvent(event, nEvent, nPart, false, false, false); + } + // Indicate no undo, and do port controller values and clone parts. + //audio->msgChangePart(part, nPart, false); + audio->msgChangePart(part, nPart, false, true, true); + } + else if (t > lpos) { + MidiPart* nPart = new MidiPart(*(MidiPart*)part); + nPart->setTick(t + (rpos -lpos)); + // Indicate no undo, and do port controller values but not clone parts. + //audio->msgChangePart(part, nPart, false); + audio->msgChangePart(part, nPart, false, true, false); + } + } + } + + int diff = rpos - lpos; + adjustGlobalLists(lpos, diff); + + song->endUndo(SC_TRACK_MODIFIED | SC_PART_MODIFIED | SC_PART_REMOVED | SC_TEMPO | SC_KEY | SC_SIG ); + } + + +//--------------------------------------------------------- +// globalSplit +// - split all parts at the song position pointer +// - do not touch muted track +//--------------------------------------------------------- + +void MusE::globalSplit() + { + int pos = song->cpos(); + song->startUndo(); + TrackList* tracks = song->tracks(); + for (iTrack it = tracks->begin(); it != tracks->end(); ++it) { + Track* track = *it; + PartList* pl = track->parts(); + for (iPart p = pl->begin(); p != pl->end(); ++p) { + Part* part = p->second; + int p1 = part->tick(); + int l0 = part->lenTick(); + if (pos > p1 && pos < (p1+l0)) { + Part* p1; + Part* p2; + track->splitPart(part, pos, p1, p2); + // Indicate no undo, and do port controller values but not clone parts. + //audio->msgChangePart(part, p1, false); + audio->msgChangePart(part, p1, false, true, false); + audio->msgAddPart(p2, false); + break; + } + } + } + song->endUndo(SC_TRACK_MODIFIED | SC_PART_MODIFIED | SC_PART_INSERTED); + } + +//--------------------------------------------------------- +// copyRange +// - copy space between left and right locator position +// to song position pointer +// - dont process muted tracks +// - create a new part for every track containing the +// copied events +//--------------------------------------------------------- + +void MusE::copyRange() + { + QMessageBox::critical(this, + tr("MusE: Copy Range"), + tr("not implemented") + ); + } + +//--------------------------------------------------------- +// cutEvents +// - make sure that all events in a part end where the +// part ends +// - process only marked parts +//--------------------------------------------------------- + +void MusE::cutEvents() + { + QMessageBox::critical(this, + tr("MusE: Cut Events"), + tr("not implemented") + ); + } + +//--------------------------------------------------------- +// checkRegionNotNull +// return true if (rPos - lPos) <= 0 +//--------------------------------------------------------- + +bool MusE::checkRegionNotNull() + { + int start = song->lPos().frame(); + int end = song->rPos().frame(); + if (end - start <= 0) { + QMessageBox::critical(this, + tr("MusE: Bounce"), + tr("set left/right marker for bounce range") + ); + return true; + } + return false; + } + diff --git a/muse2/muse/undo.cpp b/muse2/muse/undo.cpp index 44d37591..a31b8e7a 100644 --- a/muse2/muse/undo.cpp +++ b/muse2/muse/undo.cpp @@ -897,10 +897,18 @@ void Song::doUndo3() break; case UndoOp::ModifyMarker: { - //printf("performing undo for one marker at %d\n", i->realMarker->tick()); - Marker tmpMarker = *i->realMarker; - *i->realMarker = *i->copyMarker; // swap them - *i->copyMarker = tmpMarker; + //printf("performing undo for one marker at copy %d real %d\n", i->copyMarker, i->realMarker); + if (i->realMarker) { + Marker tmpMarker = *i->realMarker; + *i->realMarker = *i->copyMarker; // swap them + *i->copyMarker = tmpMarker; + } + else { + //printf("flipping marker\n"); + i->realMarker = _markerList->add(*i->copyMarker); + delete i->copyMarker; + i->copyMarker = 0; + } } break; default: @@ -979,10 +987,16 @@ void Song::doRedo3() break; case UndoOp::ModifyMarker: { - //printf("performing redo for one marker at %d\n", i->realMarker->tick()); - Marker tmpMarker = *i->realMarker; - *i->realMarker = *i->copyMarker; // swap them - *i->copyMarker = tmpMarker; + //printf("performing redo for one marker at copy %d real %d\n", i->copyMarker, i->realMarker); + if (i->copyMarker) { + Marker tmpMarker = *i->realMarker; + *i->realMarker = *i->copyMarker; // swap them + *i->copyMarker = tmpMarker; + } else { + i->copyMarker = new Marker(*i->realMarker); + _markerList->remove(i->realMarker); + i->realMarker = 0; + } } break; default: diff --git a/muse2/muse/widgets/songinfo.ui b/muse2/muse/widgets/songinfo.ui index 0944ce93..c313fd9f 100644 --- a/muse2/muse/widgets/songinfo.ui +++ b/muse2/muse/widgets/songinfo.ui @@ -24,6 +24,13 @@ + + + + Show on song load + + + -- cgit v1.2.3