summaryrefslogtreecommitdiff
path: root/muse2/muse
diff options
context:
space:
mode:
authorFlorian Jung <flo@windfisch.org>2011-10-10 16:15:56 +0000
committerFlorian Jung <flo@windfisch.org>2011-10-10 16:15:56 +0000
commitb3280635650c81a718c1b93a2a3436d7bb35bab8 (patch)
treee22f0461b7af98ddfa54eb8ce01be36cb2c51e42 /muse2/muse
parent0b3e41f1bc7140de590d57f40df52412855c9099 (diff)
track's drumlists can be loaded, saved and copied around
Diffstat (limited to 'muse2/muse')
-rw-r--r--muse2/muse/arranger/tlist.cpp169
-rw-r--r--muse2/muse/arranger/tlist.h3
-rw-r--r--muse2/muse/midiedit/scoreedit.cpp2
-rw-r--r--muse2/muse/track.cpp35
-rw-r--r--muse2/muse/track.h13
5 files changed, 193 insertions, 29 deletions
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::set<MusECo
* o clearly state in the changelog: when having multiple drumeditors open,
* the mute-column may not work, because another editor is overriding this.
* o respect "_drummap_tied_to_patch": IMPLEMENT
- * o allow loading and saving track-drumlists to external files
- * o "copy drumlist" from one track to another
* o whenever changing the patch and maintained_automatically==true,
* the drumlist is replaced by the according one (for example, "jazz" drum kit's list)
* o whenever changing the drumlist and maintained_automatically==true,
diff --git a/muse2/muse/track.cpp b/muse2/muse/track.cpp
index 8f213616..2df8a718 100644
--- a/muse2/muse/track.cpp
+++ b/muse2/muse/track.cpp
@@ -820,14 +820,14 @@ void MidiTrack::writeOurDrumSettings(int level, Xml& xml) const
{
xml.tag(level++, "our_drum_settings");
- xml.intTag(level, "tied", _drummap_tied_to_patch);
+ writeOurDrumMap(level, xml, false);
- writeOurDrumMap(level, xml);
+ xml.intTag(level, "tied", _drummap_tied_to_patch);
xml.etag(level, "our_drum_settings");
}
-void MidiTrack::writeOurDrumMap(int level, Xml& xml) const
+void MidiTrack::writeOurDrumMap(int level, Xml& xml, bool full) const
{
xml.tag(level++, "our_drummap");
@@ -849,23 +849,23 @@ void MidiTrack::writeOurDrumMap(int level, Xml& xml) const
(dm->lv1 != 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