From b3280635650c81a718c1b93a2a3436d7bb35bab8 Mon Sep 17 00:00:00 2001 From: Florian Jung Date: Mon, 10 Oct 2011 16:15:56 +0000 Subject: track's drumlists can be loaded, saved and copied around --- muse2/muse/arranger/tlist.cpp | 169 ++++++++++++++++++++++++++++++++++++-- muse2/muse/arranger/tlist.h | 3 + muse2/muse/midiedit/scoreedit.cpp | 2 - muse2/muse/track.cpp | 35 ++++---- muse2/muse/track.h | 13 ++- 5 files changed, 193 insertions(+), 29 deletions(-) (limited to 'muse2') diff --git a/muse2/muse/arranger/tlist.cpp b/muse2/muse/arranger/tlist.cpp index be33808e..decd1a2e 100644 --- a/muse2/muse/arranger/tlist.cpp +++ b/muse2/muse/arranger/tlist.cpp @@ -62,6 +62,7 @@ #include "synth.h" #include "config.h" #include "popupmenu.h" +#include "filedialog.h" #ifdef DSSI_SUPPORT #include "dssihost.h" @@ -1261,9 +1262,21 @@ void TList::mousePressEvent(QMouseEvent* ev) QMenu* p = new QMenu; //p->clear(); // Leave room for normal track IDs - base these at AUDIO_SOFTSYNTH. - p->addAction(QIcon(*automation_clear_dataIcon), tr("Delete Track"))->setData(MusECore::Track::AUDIO_SOFTSYNTH + 1); - p->addAction(QIcon(*track_commentIcon), tr("Track Comment"))->setData(MusECore::Track::AUDIO_SOFTSYNTH + 2); + p->addAction(QIcon(*automation_clear_dataIcon), tr("Delete Track"))->setData(1001); + p->addAction(QIcon(*track_commentIcon), tr("Track Comment"))->setData(1002); p->addSeparator(); + + if (t->type()==MusECore::Track::NEW_DRUM) + { + p->addAction(tr("Save track's drumlist"))->setData(1010); + p->addAction(tr("Save track's drumlist differences to initial state"))->setData(1011); + p->addAction(tr("Load track's drumlist"))->setData(1012); + p->addAction(tr("Reset track's drumlist"))->setData(1013); + p->addAction(tr("Copy track's drumlist to all selected tracks"))->setData(1014); + p->addAction(tr("Copy track's drumlist's differences to all selected tracks"))->setData(1015); + p->addSeparator(); + } + QMenu* pnew = new QMenu(p); pnew->setTitle(tr("Insert Track")); pnew->setIcon(QIcon(*edit_track_addIcon)); @@ -1272,23 +1285,52 @@ void TList::mousePressEvent(QMouseEvent* ev) QAction* act = p->exec(ev->globalPos(), 0); if (act) { int n = act->data().toInt(); - if(n >= MusECore::Track::AUDIO_SOFTSYNTH && n < MENU_ADD_SYNTH_ID_BASE) + if(n >= 1000) { - n -= MusECore::Track::AUDIO_SOFTSYNTH; switch (n) { - case 1: // delete track + case 1001: // delete track MusEGlobal::song->removeTrack0(t); MusEGlobal::audio->msgUpdateSoloStates(); break; - case 2: // show track comment + case 1002: // show track comment { TrackComment* tc = new TrackComment(t, 0); tc->show(); //QToolTip::add( this, "FOOOOOOOOOOOOO" ); } break; - + + case 1010: + saveTrackDrummap((MusECore::MidiTrack*)t, true); + break; + + case 1011: + saveTrackDrummap((MusECore::MidiTrack*)t, false); + break; + + case 1012: + loadTrackDrummap((MusECore::MidiTrack*)t); + break; + + case 1013: + if (QMessageBox::warning(this, tr("Drum map"), + tr("Reset the track's drum map with GM defaults?"), + QMessageBox::Ok | QMessageBox::Cancel, QMessageBox::Ok) == QMessageBox::Ok) + { + ((MusECore::MidiTrack*)t)->init_drummap(); + MusEGlobal::song->update(SC_DRUMMAP); + } + break; + + case 1014: + copyTrackDrummap((MusECore::MidiTrack*)t, true); + break; + + case 1015: + copyTrackDrummap((MusECore::MidiTrack*)t, false); + break; + default: printf("action %d\n", n); break; @@ -1385,6 +1427,119 @@ void TList::mousePressEvent(QMouseEvent* ev) redraw(); } +void TList::loadTrackDrummap(MusECore::MidiTrack* t, const char* fn_) +{ + QString fn; + + if (fn_==NULL) + fn=MusEGui::getOpenFileName("drummaps", MusEGlobal::drum_map_file_pattern, + this, tr("Muse: Load Track's Drum Map"), 0); + else + fn=QString(fn_); + + if (fn.isEmpty()) + { + printf("ERROR: TList::loadTrackDrummap(): empty filename\n"); + return; + } + + bool popenFlag; + FILE* f = MusEGui::fileOpen(this, fn, QString(".map"), "r", popenFlag, true); + if (f == 0) + { + printf("ERROR: TList::loadTrackDrummap() could not open file %s!\n", fn.toAscii().data()); + return; + } + + MusECore::Xml xml(f); + int mode = 0; + for (;;) { + MusECore::Xml::Token token = xml.parse(); + const QString& tag = xml.s1(); + switch (token) { + case MusECore::Xml::Error: + case MusECore::Xml::End: + return; + case MusECore::Xml::TagStart: + if (mode == 0 && tag == "muse") + mode = 1; + else if (mode == 1 && tag == "our_drummap") { + t->readOurDrumMap(xml, true); + mode = 0; + } + else + xml.unknown("TList::loadTrackDrummap"); + break; + case MusECore::Xml::Attribut: + break; + case MusECore::Xml::TagEnd: + if (!mode && tag == "muse") + goto ende; + default: + break; + } + } + ende: + if (popenFlag) + pclose(f); + else + fclose(f); + + MusEGlobal::song->update(SC_DRUMMAP); +} + +void TList::saveTrackDrummap(MusECore::MidiTrack* t, bool full, const char* fn_) +{ + QString fn; + if (fn_==NULL) + fn = MusEGui::getSaveFileName(QString("drummaps"), MusEGlobal::drum_map_file_save_pattern, + this, tr("MusE: Store Track's Drum Map")); + else + fn = QString(fn_); + + if (fn.isEmpty()) + return; + + bool popenFlag; + FILE* f = MusEGui::fileOpen(this, fn, QString(".map"), "w", popenFlag, false, true); + if (f == 0) + return; + + MusECore::Xml xml(f); + xml.header(); + xml.tag(0, "muse version=\"1.0\""); + t->writeOurDrumMap(1, xml, full); + xml.tag(0, "/muse"); + + if (popenFlag) + pclose(f); + else + fclose(f); +} + +void TList::copyTrackDrummap(MusECore::MidiTrack* t, bool full) +{ + char* tmp1 = tmpnam(NULL); + char tmp2[1000]; + strcpy(tmp2, tmp1); + strcat(tmp2, ".map"); + if (MusEGlobal::debugMsg) + printf("in TList::copyTrackDrummap(); filename is %s\n",tmp2); + + saveTrackDrummap(t, full, tmp2); + + for (MusECore::iTrack it = MusEGlobal::song->tracks()->begin(); it!=MusEGlobal::song->tracks()->end(); it++) + if ((*it)->selected() && (*it)->type()==MusECore::Track::NEW_DRUM) + { + if (MusEGlobal::debugMsg) + printf(" processing track...\n"); + + loadTrackDrummap((MusECore::MidiTrack*)(*it), tmp2); + } + + remove(tmp2); +} + //--------------------------------------------------------- // selectTrack //--------------------------------------------------------- diff --git a/muse2/muse/arranger/tlist.h b/muse2/muse/arranger/tlist.h index 2aeae939..864e287b 100644 --- a/muse2/muse/arranger/tlist.h +++ b/muse2/muse/arranger/tlist.h @@ -118,6 +118,9 @@ class TList : public QWidget { void songChanged(int flags); void changeAutomation(QAction*); void changeAutomationColor(QAction*); + void loadTrackDrummap(MusECore::MidiTrack*, const char* filename=NULL); + void saveTrackDrummap(MusECore::MidiTrack*, bool full, const char* filename=NULL); + void copyTrackDrummap(MusECore::MidiTrack*, bool full); signals: ///void selectionChanged(); diff --git a/muse2/muse/midiedit/scoreedit.cpp b/muse2/muse/midiedit/scoreedit.cpp index 9965fd99..a9eba278 100644 --- a/muse2/muse/midiedit/scoreedit.cpp +++ b/muse2/muse/midiedit/scoreedit.cpp @@ -4610,8 +4610,6 @@ void ScoreCanvas::add_new_parts(const std::map< MusECore::Part*, std::setlv1 != idm->lv1) || (dm->lv2 != idm->lv2) || (dm->lv3 != idm->lv3) || (dm->lv4 != idm->lv4) || (dm->enote != idm->enote) || (dm->mute != idm->mute) || - _drummap_hidden[i] ) + _drummap_hidden[i] || full) { xml.tag(level++, "entry pitch=\"%d\"", i); // when any of these "if"s changes, also update the large "if" // above (this scope's parent) - if (dm->name != idm->name) xml.strTag(level, "name", dm->name); - if (dm->vol != idm->vol) xml.intTag(level, "vol", dm->vol); - if (dm->quant != idm->quant) xml.intTag(level, "quant", dm->quant); - if (dm->len != idm->len) xml.intTag(level, "len", dm->len); - if (dm->lv1 != idm->lv1) xml.intTag(level, "lv1", dm->lv1); - if (dm->lv2 != idm->lv2) xml.intTag(level, "lv2", dm->lv2); - if (dm->lv3 != idm->lv3) xml.intTag(level, "lv3", dm->lv3); - if (dm->lv4 != idm->lv4) xml.intTag(level, "lv4", dm->lv4); - if (dm->enote != idm->enote) xml.intTag(level, "enote", dm->enote); - if (dm->mute != idm->mute) xml.intTag(level, "mute", dm->mute); - if (_drummap_hidden[i]) xml.intTag(level, "hide", _drummap_hidden[i]); + if (full || dm->name != idm->name) xml.strTag(level, "name", dm->name); + if (full || dm->vol != idm->vol) xml.intTag(level, "vol", dm->vol); + if (full || dm->quant != idm->quant) xml.intTag(level, "quant", dm->quant); + if (full || dm->len != idm->len) xml.intTag(level, "len", dm->len); + if (full || dm->lv1 != idm->lv1) xml.intTag(level, "lv1", dm->lv1); + if (full || dm->lv2 != idm->lv2) xml.intTag(level, "lv2", dm->lv2); + if (full || dm->lv3 != idm->lv3) xml.intTag(level, "lv3", dm->lv3); + if (full || dm->lv4 != idm->lv4) xml.intTag(level, "lv4", dm->lv4); + if (full || dm->enote != idm->enote) xml.intTag(level, "enote", dm->enote); + if (full || dm->mute != idm->mute) xml.intTag(level, "mute", dm->mute); + if (full || _drummap_hidden[i]) xml.intTag(level, "hide", _drummap_hidden[i]); // anote is ignored anyway, as dm->anote == i, and this is // already stored in the begin tag (pitch=...) @@ -989,9 +989,10 @@ void MidiTrack::readOurDrumSettings(Xml& xml) } } -void MidiTrack::readOurDrumMap(Xml& xml) +void MidiTrack::readOurDrumMap(Xml& xml, bool dont_init) { - init_drummap(false); + if (!dont_init) init_drummap(false); + _drummap_tied_to_patch=false; for (;;) { diff --git a/muse2/muse/track.h b/muse2/muse/track.h index 73f18cc2..1826f081 100644 --- a/muse2/muse/track.h +++ b/muse2/muse/track.h @@ -235,13 +235,13 @@ class MidiTrack : public Track { int drum_in_map[128]; void init(); - void init_drummap(bool write_ordering=false); + void init_drummap(bool write_ordering); // function without argument in public void remove_ourselves_from_drum_ordering(); void writeOurDrumSettings(int level, Xml& xml) const; - void writeOurDrumMap(int level, Xml& xml) const; void readOurDrumSettings(Xml& xml); - void readOurDrumMap(Xml& xml); + //void writeOurDrumMap(int level, Xml& xml, bool full) const; //below in public: + //void readOurDrumMap(Xml& xml, bool dont_init=false); //below in public: public: MidiTrack(); @@ -314,6 +314,13 @@ class MidiTrack : public Track { bool* drummap_hidden() { return _drummap_hidden; } int map_drum_in(int enote) { return drum_in_map[enote]; } void update_drum_in_map(); + + void init_drummap() { init_drummap(false); } // function with argument in private + + //void writeOurDrumSettings(int level, Xml& xml) const; // above in private: + //void readOurDrumSettings(Xml& xml); // above in private: + void writeOurDrumMap(int level, Xml& xml, bool full) const; + void readOurDrumMap(Xml& xml, bool dont_init=false); }; } // namespace MusECore -- cgit v1.2.3