diff options
Diffstat (limited to 'muse2')
49 files changed, 1499 insertions, 322 deletions
diff --git a/muse2/muse/app.cpp b/muse2/muse/app.cpp index 677743b3..386cf226 100644 --- a/muse2/muse/app.cpp +++ b/muse2/muse/app.cpp @@ -1794,6 +1794,7 @@ void MusE::startEditor(MusECore::Track* t) switch (t->type()) { case MusECore::Track::MIDI: startPianoroll(); break; case MusECore::Track::DRUM: startDrumEditor(); break; + case MusECore::Track::NEW_DRUM: startDrumEditor(); break; case MusECore::Track::WAVE: startWaveEditor(); break; default: break; diff --git a/muse2/muse/appearance.cpp b/muse2/muse/appearance.cpp index 178c6bd8..6c3ee2e4 100644 --- a/muse2/muse/appearance.cpp +++ b/muse2/muse/appearance.cpp @@ -1,5 +1,4 @@ //========================================================= -//========================================================= // MusE // Linux Music Editor // $Id: appearance.cpp,v 1.11.2.5 2009/11/14 03:37:48 terminator356 Exp $ @@ -843,7 +842,7 @@ void Appearance::colorItemSelectionChanged() case 0x300: color = &config->waveEditBackgroundColor; break; case 0x411: color = &config->trackBg; break; case 0x412: color = &config->midiTrackBg; break; - case 0x413: color = &config->drumTrackBg; break; + case 0x413: color = &config->drumTrackBg; break; //FINDMICHJETZT add newDrum... case 0x414: color = &config->waveTrackBg; break; case 0x415: color = &config->outputTrackBg; break; case 0x416: color = &config->inputTrackBg; break; @@ -857,7 +856,7 @@ void Appearance::colorItemSelectionChanged() case 0x500: color = &config->mixerBg; break; case 0x501: color = &config->midiTrackLabelBg; break; - case 0x502: color = &config->drumTrackLabelBg; break; + case 0x502: color = &config->drumTrackLabelBg; break; //FINDMICHJETZT add newDrum... case 0x503: color = &config->waveTrackLabelBg; break; case 0x504: color = &config->outputTrackLabelBg; break; case 0x505: color = &config->inputTrackLabelBg; break; diff --git a/muse2/muse/arranger/arrangerview.cpp b/muse2/muse/arranger/arrangerview.cpp index 9dc287ac..a565da13 100644 --- a/muse2/muse/arranger/arrangerview.cpp +++ b/muse2/muse/arranger/arrangerview.cpp @@ -634,11 +634,12 @@ void ArrangerView::populateAddTrack() trackMidiAction = grp->actions()[0]; trackDrumAction = grp->actions()[1]; - trackWaveAction = grp->actions()[2]; - trackAOutputAction = grp->actions()[3]; - trackAGroupAction = grp->actions()[4]; - trackAInputAction = grp->actions()[5]; - trackAAuxAction = grp->actions()[6]; + trackNewStyleDrumAction = grp->actions()[2]; + trackWaveAction = grp->actions()[3]; + trackAOutputAction = grp->actions()[4]; + trackAGroupAction = grp->actions()[5]; + trackAInputAction = grp->actions()[6]; + trackAAuxAction = grp->actions()[7]; } void ArrangerView::addNewTrack(QAction* action) @@ -662,6 +663,7 @@ void ArrangerView::updateShortcuts() trackMidiAction->setShortcut(shortcuts[SHRT_ADD_MIDI_TRACK].key); trackDrumAction->setShortcut(shortcuts[SHRT_ADD_DRUM_TRACK].key); + trackNewStyleDrumAction->setShortcut(shortcuts[SHRT_ADD_NEW_STYLE_DRUM_TRACK].key); trackWaveAction->setShortcut(shortcuts[SHRT_ADD_WAVE_TRACK].key); trackAOutputAction->setShortcut(shortcuts[SHRT_ADD_AUDIO_OUTPUT].key); trackAGroupAction->setShortcut(shortcuts[SHRT_ADD_AUDIO_GROUP].key); diff --git a/muse2/muse/arranger/arrangerview.h b/muse2/muse/arranger/arrangerview.h index de610bd6..d52c5cc4 100644 --- a/muse2/muse/arranger/arrangerview.h +++ b/muse2/muse/arranger/arrangerview.h @@ -89,7 +89,7 @@ class ArrangerView : public TopWin QMenu* master; QAction *strGlobalCutAction, *strGlobalInsertAction, *strGlobalSplitAction; - QAction *trackMidiAction, *trackDrumAction, *trackWaveAction, *trackAOutputAction, *trackAGroupAction; + QAction *trackMidiAction, *trackDrumAction, *trackNewStyleDrumAction, *trackWaveAction, *trackAOutputAction, *trackAGroupAction; QAction *trackAInputAction, *trackAAuxAction; QAction *editCutAction, *editCopyAction, *editCopyRangeAction; QAction *editPasteAction, *editPasteCloneAction, *editPasteDialogAction, *editPasteCloneDialogAction; diff --git a/muse2/muse/arranger/pcanvas.cpp b/muse2/muse/arranger/pcanvas.cpp index 0f2f4629..8226c440 100644 --- a/muse2/muse/arranger/pcanvas.cpp +++ b/muse2/muse/arranger/pcanvas.cpp @@ -238,6 +238,7 @@ void PartCanvas::viewMouseDoubleClickEvent(QMouseEvent* event) switch(track->type()) { case MusECore::Track::MIDI: case MusECore::Track::DRUM: + case MusECore::Track::NEW_DRUM: { MusECore::MidiPart* part = new MusECore::MidiPart((MusECore::MidiTrack*)track); part->setTick(pos[1]); @@ -521,6 +522,7 @@ CItem* PartCanvas::newItem(const QPoint& pos, int) switch(track->type()) { case MusECore::Track::MIDI: case MusECore::Track::DRUM: + case MusECore::Track::NEW_DRUM: pa = new MusECore::MidiPart((MusECore::MidiTrack*)track); pa->setTick(x); pa->setLenTick(0); @@ -659,6 +661,7 @@ QMenu* PartCanvas::genItemPopup(CItem* item) act_mexport->setData(16); } break; + case MusECore::Track::NEW_DRUM: case MusECore::Track::DRUM: { partPopup->addAction(MusEGlobal::muse->arranger()->parentWin->startDrumEditAction); partPopup->addAction(MusEGlobal::muse->arranger()->parentWin->startListEditAction); @@ -1259,6 +1262,7 @@ void PartCanvas::keyPress(QKeyEvent* event) // else track is midi switch (track->type()) { + case MusECore::Track::NEW_DRUM: case MusECore::Track::DRUM: type = 3; break; @@ -2302,7 +2306,7 @@ void PartCanvas::drawMidiPart(QPainter& p, const QRect&, MusECore::EventList* ev using std::pair; MusECore::iEvent ito(events->lower_bound(to)); - bool isdrum = (mt->type() == MusECore::Track::DRUM); + bool isdrum = (mt->type() == MusECore::Track::DRUM || mt->type() == MusECore::Track::NEW_DRUM); // draw controllers ------------------------------------------ p.setPen(QColor(192,192,color_brightness/2)); diff --git a/muse2/muse/arranger/tlist.cpp b/muse2/muse/arranger/tlist.cpp index 98c4a595..be33808e 100644 --- a/muse2/muse/arranger/tlist.cpp +++ b/muse2/muse/arranger/tlist.cpp @@ -226,6 +226,9 @@ void TList::paint(const QRect& r) case MusECore::Track::DRUM: bg = MusEGlobal::config.drumTrackBg; break; + case MusECore::Track::NEW_DRUM: + bg = MusEGlobal::config.newDrumTrackBg; + break; case MusECore::Track::WAVE: bg = MusEGlobal::config.waveTrackBg; break; @@ -281,6 +284,7 @@ void TList::paint(const QRect& r) case MusECore::Track::MIDI: pm = addtrack_addmiditrackIcon; break; + case MusECore::Track::NEW_DRUM: case MusECore::Track::DRUM: pm = addtrack_drumtrackIcon; break; @@ -585,6 +589,7 @@ void TList::portsPopupMenu(MusECore::Track* t, int x, int y) switch(t->type()) { case MusECore::Track::MIDI: case MusECore::Track::DRUM: + case MusECore::Track::NEW_DRUM: case MusECore::Track::AUDIO_SOFTSYNTH: { MusECore::MidiTrack* track = (MusECore::MidiTrack*)t; @@ -739,7 +744,7 @@ void TList::oportPropertyPopupMenu(MusECore::Track* t, int x, int y) } - if (t->type() != MusECore::Track::MIDI && t->type() != MusECore::Track::DRUM) + if (t->type() != MusECore::Track::MIDI && t->type() != MusECore::Track::DRUM && t->type() != MusECore::Track::NEW_DRUM) return; int oPort = ((MusECore::MidiTrack*)t)->outPort(); MusECore::MidiPort* port = &MusEGlobal::midiPorts[oPort]; @@ -923,7 +928,7 @@ MusECore::TrackList TList::getRecEnabledTracks() void TList::changeAutomation(QAction* act) { //printf("changeAutomation %d\n", act->data().toInt()); - if (editAutomation->type() == MusECore::Track::MIDI) { + if ( (editAutomation->type() == MusECore::Track::MIDI) || (editAutomation->type() == MusECore::Track::DRUM) || (editAutomation->type() == MusECore::Track::NEW_DRUM) ) { printf("this is wrong, we can't edit automation for midi tracks from arranger yet!\n"); return; } @@ -949,7 +954,7 @@ void TList::changeAutomation(QAction* act) //--------------------------------------------------------- void TList::changeAutomationColor(QAction* act) { - if (editAutomation->type() == MusECore::Track::MIDI) { + if ( (editAutomation->type() == MusECore::Track::MIDI) || (editAutomation->type() == MusECore::Track::DRUM) || (editAutomation->type() == MusECore::Track::NEW_DRUM) ) { printf("this is wrong, we can't edit automation for midi tracks from arranger yet!\n"); return; } @@ -1707,13 +1712,14 @@ void TList::classesPopupMenu(MusECore::Track* t, int x, int y) p.clear(); p.addAction(QIcon(*addtrack_addmiditrackIcon), tr("Midi"))->setData(MusECore::Track::MIDI); p.addAction(QIcon(*addtrack_drumtrackIcon), tr("Drum"))->setData(MusECore::Track::DRUM); + p.addAction(QIcon(*addtrack_drumtrackIcon), tr("New style drum"))->setData(MusECore::Track::NEW_DRUM); QAction* act = p.exec(mapToGlobal(QPoint(x, y)), 0); if (!act) return; int n = act->data().toInt(); - if (MusECore::Track::TrackType(n) == MusECore::Track::MIDI && t->type() == MusECore::Track::DRUM) { + if ((MusECore::Track::TrackType(n) == MusECore::Track::MIDI || MusECore::Track::TrackType(n) == MusECore::Track::NEW_DRUM) && t->type() == MusECore::Track::DRUM) { //FINDMICHJETZT passt das? // // Drum -> Midi // @@ -1747,11 +1753,11 @@ void TList::classesPopupMenu(MusECore::Track* t, int x, int y) } } - t->setType(MusECore::Track::MIDI); + t->setType(MusECore::Track::TrackType(n)); MusEGlobal::audio->msgIdle(false); MusEGlobal::song->update(SC_EVENT_MODIFIED); } - else if (MusECore::Track::TrackType(n) == MusECore::Track::DRUM && t->type() == MusECore::Track::MIDI) { + else if (MusECore::Track::TrackType(n) == MusECore::Track::DRUM && (t->type() == MusECore::Track::MIDI || t->type() == MusECore::Track::NEW_DRUM)) { //FINDMICHJETZT passt das? // // Midi -> Drum // @@ -1809,6 +1815,12 @@ void TList::classesPopupMenu(MusECore::Track* t, int x, int y) MusEGlobal::audio->msgIdle(false); MusEGlobal::song->update(SC_EVENT_MODIFIED); } + else // MIDI -> NEW_DRUM or vice versa. added by flo. FINDMICHJETZT does this work properly? + { + MusECore::Track* t2 = t->clone(false); + t->setType(MusECore::Track::TrackType(n)); + MusEGlobal::audio->msgChangeTrack(t2, t, true); + } } } // namespace MusEGui diff --git a/muse2/muse/conf.cpp b/muse2/muse/conf.cpp index c4df1f36..027ad431 100644 --- a/muse2/muse/conf.cpp +++ b/muse2/muse/conf.cpp @@ -788,6 +788,8 @@ void readConfiguration(Xml& xml, bool readOnlySequencer, bool doReadGlobalConfig MusEGlobal::config.midiTrackLabelBg = readColor(xml); else if (tag == "drumTrackLabelBg") MusEGlobal::config.drumTrackLabelBg = readColor(xml); + else if (tag == "newDrumTrackLabelBg") + MusEGlobal::config.newDrumTrackLabelBg = readColor(xml); else if (tag == "waveTrackLabelBg") MusEGlobal::config.waveTrackLabelBg = readColor(xml); else if (tag == "outputTrackLabelBg") @@ -807,6 +809,8 @@ void readConfiguration(Xml& xml, bool readOnlySequencer, bool doReadGlobalConfig MusEGlobal::config.ctrlGraphFg = readColor(xml); else if (tag == "drumTrackBg") MusEGlobal::config.drumTrackBg = readColor(xml); + else if (tag == "newDrumTrackBg") + MusEGlobal::config.newDrumTrackBg = readColor(xml); else if (tag == "waveTrackBg") MusEGlobal::config.waveTrackBg = readColor(xml); else if (tag == "outputTrackBg") @@ -1322,6 +1326,7 @@ void MusE::writeGlobalConfiguration(int level, MusECore::Xml& xml) const xml.colorTag(level, "mixerBg", MusEGlobal::config.mixerBg); xml.colorTag(level, "midiTrackLabelBg", MusEGlobal::config.midiTrackLabelBg); xml.colorTag(level, "drumTrackLabelBg", MusEGlobal::config.drumTrackLabelBg); + xml.colorTag(level, "newDrumTrackLabelBg",MusEGlobal::config.newDrumTrackLabelBg); xml.colorTag(level, "waveTrackLabelBg", MusEGlobal::config.waveTrackLabelBg); xml.colorTag(level, "outputTrackLabelBg", MusEGlobal::config.outputTrackLabelBg); xml.colorTag(level, "inputTrackLabelBg", MusEGlobal::config.inputTrackLabelBg); @@ -1332,6 +1337,7 @@ void MusE::writeGlobalConfiguration(int level, MusECore::Xml& xml) const xml.colorTag(level, "midiTrackBg", MusEGlobal::config.midiTrackBg); xml.colorTag(level, "ctrlGraphFg", MusEGlobal::config.ctrlGraphFg); xml.colorTag(level, "drumTrackBg", MusEGlobal::config.drumTrackBg); + xml.colorTag(level, "newDrumTrackBg",MusEGlobal::config.newDrumTrackBg); xml.colorTag(level, "waveTrackBg", MusEGlobal::config.waveTrackBg); xml.colorTag(level, "outputTrackBg", MusEGlobal::config.outputTrackBg); xml.colorTag(level, "inputTrackBg", MusEGlobal::config.inputTrackBg); @@ -1658,6 +1664,7 @@ void MixerConfig::write(int level, MusECore::Xml& xml) xml.intTag(level, "showMidiTracks", showMidiTracks); xml.intTag(level, "showDrumTracks", showDrumTracks); + xml.intTag(level, "showNewDrumTracks", showNewDrumTracks); xml.intTag(level, "showInputTracks", showInputTracks); xml.intTag(level, "showOutputTracks", showOutputTracks); xml.intTag(level, "showWaveTracks", showWaveTracks); @@ -1695,6 +1702,8 @@ void MixerConfig::read(MusECore::Xml& xml) showMidiTracks = xml.parseInt(); else if (tag == "showDrumTracks") showDrumTracks = xml.parseInt(); + else if (tag == "showNewDrumTracks") + showNewDrumTracks = xml.parseInt(); else if (tag == "showInputTracks") showInputTracks = xml.parseInt(); else if (tag == "showOutputTracks") diff --git a/muse2/muse/ctrl/ctrlcanvas.cpp b/muse2/muse/ctrl/ctrlcanvas.cpp index 486e279a..9c5d636f 100644 --- a/muse2/muse/ctrl/ctrlcanvas.cpp +++ b/muse2/muse/ctrl/ctrlcanvas.cpp @@ -537,10 +537,10 @@ void CtrlCanvas::partControllers(const MusECore::MidiPart* part, int num, int* d int di; int n; - if((mt->type() != MusECore::Track::DRUM) && curDrumInstrument != -1) + if((mt->type() != MusECore::Track::DRUM) && curDrumInstrument != -1) //FINDMICHJETZT was ist das? printf("keyfilter != -1 in non drum track?\n"); - if((mt->type() == MusECore::Track::DRUM) && (curDrumInstrument != -1) && ((num & 0xff) == 0xff)) + if((mt->type() == MusECore::Track::DRUM) && (curDrumInstrument != -1) && ((num & 0xff) == 0xff)) //FINDMICHJETZT was ist das? { di = (num & ~0xff) | curDrumInstrument; n = (num & ~0xff) | MusEGlobal::drumMap[curDrumInstrument].anote; // construct real controller number @@ -1690,7 +1690,7 @@ void CtrlCanvas::pdrawItems(QPainter& p, const QRect& rect, const MusECore::Midi MusECore::MidiTrack* mt = part->track(); MusECore::MidiPort* mp; - if((mt->type() == MusECore::Track::DRUM) && (curDrumInstrument != -1) && ((_cnum & 0xff) == 0xff)) + if((mt->type() == MusECore::Track::DRUM) && (curDrumInstrument != -1) && ((_cnum & 0xff) == 0xff)) //FINDMICHJETZT was ist das? mp = &MusEGlobal::midiPorts[MusEGlobal::drumMap[curDrumInstrument].port]; else mp = &MusEGlobal::midiPorts[mt->outPort()]; diff --git a/muse2/muse/ctrl/ctrlpanel.cpp b/muse2/muse/ctrl/ctrlpanel.cpp index 0d981fbd..88787c47 100644 --- a/muse2/muse/ctrl/ctrlpanel.cpp +++ b/muse2/muse/ctrl/ctrlpanel.cpp @@ -171,7 +171,7 @@ void CtrlPanel::heartBeat() int outport; int chan; int cdi = editor->curDrumInstrument(); - if(_track->type() == MusECore::Track::DRUM && ((_ctrl->num() & 0xff) == 0xff) && cdi != -1) + if(_track->type() == MusECore::Track::DRUM && ((_ctrl->num() & 0xff) == 0xff) && cdi != -1) //FINDMICHJETZT was ist das? und ähnliche dinger { outport = MusEGlobal::drumMap[cdi].port; chan = MusEGlobal::drumMap[cdi].channel; @@ -562,7 +562,7 @@ void CtrlPanel::ctrlPopup() int channel = track->outChannel(); MusECore::MidiPort* port = &MusEGlobal::midiPorts[track->outPort()]; int curDrumInstrument = editor->curDrumInstrument(); - bool isDrum = track->type() == MusECore::Track::DRUM; + bool isDrum = track->type() == MusECore::Track::DRUM; //FINDMICHJETZT ist das wichtig? QMenu* pop = new QMenu; //pop->clear(); @@ -720,7 +720,7 @@ void CtrlPanel::ctrlPopup() int channel = track->outChannel(); MusECore::MidiPort* port = &MusEGlobal::midiPorts[track->outPort()]; int curDrumInstrument = editor->curDrumInstrument(); - bool isDrum = track->type() == MusECore::Track::DRUM; + bool isDrum = track->type() == MusECore::Track::DRUM; //FINDMICHJETZT ist das wichtig? MusECore::MidiInstrument* instr = port->instrument(); MusECore::MidiControllerList* mcl = instr->controller(); diff --git a/muse2/muse/gconfig.cpp b/muse2/muse/gconfig.cpp index 337d7862..65397fe4 100644 --- a/muse2/muse/gconfig.cpp +++ b/muse2/muse/gconfig.cpp @@ -103,6 +103,7 @@ MusEGui::GlobalConfigValues config = { QColor(74, 150, 194), // midiTrackLabelBg; // Med blue QColor(74, 150, 194), // drumTrackLabelBg; // Med blue + QColor(74, 150, 194), // newDrumTrackLabelBg; // Med blue QColor(213, 128, 202), // waveTrackLabelBg; // magenta QColor(84, 185, 58), // outputTrackLabelBg; // green QColor(199, 75, 64), // inputTrackLabelBg; // red @@ -112,6 +113,7 @@ MusEGui::GlobalConfigValues config = { QColor(215, 220, 230), // midiTrackBg; QColor(215, 220, 230), // drumTrackBg; + QColor(215, 220, 230), // newDrumTrackBg; QColor(220, 209, 217), // waveTrackBg; QColor(197, 220, 206), // outputTrackBg; QColor(220, 214, 206), // inputTrackBg; @@ -149,13 +151,13 @@ MusEGui::GlobalConfigValues config = { QString("Mixer A"), QRect(0, 0, 300, 500), // Mixer1 true, true, true, true, - true, true, true, true + true, true, true, true, true }, { QString("Mixer B"), QRect(200, 200, 300, 500), // Mixer2 true, true, true, true, - true, true, true, true + true, true, true, true, true }, true, // TransportVisible; false, // BigTimeVisible; diff --git a/muse2/muse/gconfig.h b/muse2/muse/gconfig.h index df6739cf..a6b55557 100644 --- a/muse2/muse/gconfig.h +++ b/muse2/muse/gconfig.h @@ -47,6 +47,7 @@ struct MixerConfig { QRect geometry; bool showMidiTracks; bool showDrumTracks; + bool showNewDrumTracks; bool showInputTracks; bool showOutputTracks; bool showWaveTracks; @@ -83,6 +84,7 @@ struct GlobalConfigValues { QColor midiTrackLabelBg; QColor drumTrackLabelBg; + QColor newDrumTrackLabelBg; QColor waveTrackLabelBg; QColor outputTrackLabelBg; QColor inputTrackLabelBg; @@ -92,6 +94,7 @@ struct GlobalConfigValues { QColor midiTrackBg; QColor drumTrackBg; + QColor newDrumTrackBg; QColor waveTrackBg; QColor outputTrackBg; QColor inputTrackBg; diff --git a/muse2/muse/helper.cpp b/muse2/muse/helper.cpp index a3a4639c..e3cdee7e 100644 --- a/muse2/muse/helper.cpp +++ b/muse2/muse/helper.cpp @@ -98,6 +98,19 @@ bool any_event_selected(const set<Part*>& parts, bool in_range) return !get_events(parts, in_range ? 3 : 1).empty(); } +bool drummaps_almost_equal(DrumMap* one, DrumMap* two, int len) +{ + for (int i=0; i<len; i++) + { + DrumMap tmp = one[i]; + tmp.mute=two[i].mute; + if (tmp!=two[i]) + return false; + } + return true; +} + + } // namespace MusECore namespace MusEGui { @@ -293,26 +306,44 @@ QActionGroup* populateAddTrack(QMenu* addTrack) QT_TRANSLATE_NOOP("@default", "Add Midi Track")); midi->setData(MusECore::Track::MIDI); grp->addAction(midi); + + QAction* drum = addTrack->addAction(QIcon(*addtrack_drumtrackIcon), QT_TRANSLATE_NOOP("@default", "Add Drum Track")); drum->setData(MusECore::Track::DRUM); grp->addAction(drum); + + + QAction* newdrum = addTrack->addAction(QIcon(*addtrack_drumtrackIcon), + QT_TRANSLATE_NOOP("@default", "Add New Style Drum Track")); + newdrum->setData(MusECore::Track::NEW_DRUM); + grp->addAction(newdrum); + + QAction* wave = addTrack->addAction(QIcon(*addtrack_wavetrackIcon), QT_TRANSLATE_NOOP("@default", "Add Wave Track")); wave->setData(MusECore::Track::WAVE); grp->addAction(wave); + + QAction* aoutput = addTrack->addAction(QIcon(*addtrack_audiooutputIcon), QT_TRANSLATE_NOOP("@default", "Add Audio Output")); aoutput->setData(MusECore::Track::AUDIO_OUTPUT); grp->addAction(aoutput); + + QAction* agroup = addTrack->addAction(QIcon(*addtrack_audiogroupIcon), QT_TRANSLATE_NOOP("@default", "Add Audio Group")); agroup->setData(MusECore::Track::AUDIO_GROUP); grp->addAction(agroup); + + QAction* ainput = addTrack->addAction(QIcon(*addtrack_audioinputIcon), QT_TRANSLATE_NOOP("@default", "Add Audio Input")); ainput->setData(MusECore::Track::AUDIO_INPUT); grp->addAction(ainput); + + QAction* aaux = addTrack->addAction(QIcon(*addtrack_auxsendIcon), QT_TRANSLATE_NOOP("@default", "Add Aux Send")); aaux->setData(MusECore::Track::AUDIO_AUX); diff --git a/muse2/muse/helper.h b/muse2/muse/helper.h index a2361ab5..f014ee1e 100644 --- a/muse2/muse/helper.h +++ b/muse2/muse/helper.h @@ -25,6 +25,8 @@ #include <set> +#include "drummap.h" + class QActionGroup; class QString; class QMenu; @@ -36,6 +38,8 @@ class Part; QString pitch2string(int v); Part* partFromSerialNumber(int serial); bool any_event_selected(const std::set<Part*>&, bool in_range=false); + +bool drummaps_almost_equal(DrumMap* one, DrumMap* two, int drummap_size=128); } namespace MusEGui { diff --git a/muse2/muse/icons.cpp b/muse2/muse/icons.cpp index 6991eab8..67bb4827 100644 --- a/muse2/muse/icons.cpp +++ b/muse2/muse/icons.cpp @@ -120,6 +120,10 @@ #include "xpm/rec_echo_on.xpm" #include "xpm/rec_echo_off.xpm" +#include "xpm/eye.xpm" +#include "xpm/eye_gray.xpm" +#include "xpm/eye_crossed.xpm" + #include "xpm/up.xpm" #include "xpm/down.xpm" #include "xpm/bold.xpm" @@ -333,6 +337,9 @@ QPixmap* homeIcon; QPixmap* backIcon; QPixmap* forwardIcon; QPixmap* muteIcon; +QPixmap* eyeIcon; +QPixmap* eyeCrossedIcon; +QPixmap* eyeGrayIcon; QPixmap* upIcon; QPixmap* downIcon; QPixmap* boldIcon; @@ -536,6 +543,9 @@ void initIcons() backIcon = new MPIXMAP(back_xpm, "go-previous"); forwardIcon = new MPIXMAP(forward_xpm, "go-next"); muteIcon = new MPIXMAP(editmuteS_xpm, "audio-volume-muted"); + eyeIcon = new MPIXMAP(eye_xpm, NULL); + eyeCrossedIcon = new MPIXMAP(eye_crossed_xpm, NULL); + eyeGrayIcon = new MPIXMAP(eye_gray_xpm, NULL); upIcon = new MPIXMAP(up_xpm, "go-up"); downIcon = new MPIXMAP(down_xpm, "go-down"); boldIcon = new MPIXMAP(bold_xpm, "format-text-bold"); diff --git a/muse2/muse/icons.h b/muse2/muse/icons.h index 0c576ba4..32f08a58 100644 --- a/muse2/muse/icons.h +++ b/muse2/muse/icons.h @@ -87,6 +87,9 @@ extern QPixmap* homeIcon; extern QPixmap* backIcon; extern QPixmap* forwardIcon; extern QPixmap* muteIcon; +extern QPixmap* eyeIcon; +extern QPixmap* eyeCrossedIcon; +extern QPixmap* eyeGrayIcon; extern QPixmap* upIcon; extern QPixmap* downIcon; extern QPixmap* boldIcon; diff --git a/muse2/muse/importmidi.cpp b/muse2/muse/importmidi.cpp index e94a4ea8..593ddb79 100644 --- a/muse2/muse/importmidi.cpp +++ b/muse2/muse/importmidi.cpp @@ -181,7 +181,7 @@ bool MusE::importMidi(const QString name, bool merge) MusECore::MidiTrack* track = new MusECore::MidiTrack(); if ((*t)->isDrumTrack) - track->setType(MusECore::Track::DRUM); + track->setType(MusECore::Track::DRUM); //FINDMICHJETZT track->setOutChannel(channel); track->setOutPort(port); @@ -200,7 +200,7 @@ bool MusE::importMidi(const QString name, bool merge) // Hmm. buildMidiEventList already takes care of this. // But it seems to work. How? Must test. if (channel == 9 && MusEGlobal::song->mtype() != MT_UNKNOWN) { - track->setType(MusECore::Track::DRUM); + track->setType(MusECore::Track::DRUM); //FINDMICHJETZT // // remap drum pitch with drumInmap // diff --git a/muse2/muse/liste/editevent.cpp b/muse2/muse/liste/editevent.cpp index bca5729b..ce53069d 100644 --- a/muse2/muse/liste/editevent.cpp +++ b/muse2/muse/liste/editevent.cpp @@ -619,7 +619,7 @@ EditCtrlDialog::EditCtrlDialog(int tick, const MusECore::Event& event, MusECore::MidiTrack* track = part->track(); int portn = track->outPort(); MusECore::MidiPort* port = &MusEGlobal::midiPorts[portn]; - bool isDrum = track->type() == MusECore::Track::DRUM; + bool isDrum = track->type() == MusECore::Track::DRUM; //FINDMICHJETZT was soll das? MusECore::MidiCtrlValListList* cll = port->controller(); ctrlList->clear(); @@ -835,7 +835,7 @@ void EditCtrlDialog::updatePatch() int port = track->outPort(); int channel = track->outChannel(); MusECore::MidiInstrument* instr = MusEGlobal::midiPorts[port].instrument(); - patchName->setText(instr->getPatchName(channel, val, MusEGlobal::song->mtype(), track->type() == MusECore::Track::DRUM)); + patchName->setText(instr->getPatchName(channel, val, MusEGlobal::song->mtype(), track->type() == MusECore::Track::DRUM)); //FINDMICHJETZT was soll das? int hb = ((val >> 16) & 0xff) + 1; if (hb == 0x100) @@ -874,7 +874,7 @@ void EditCtrlDialog::instrPopup() ///instr->populatePatchPopup(pop, channel, MusEGlobal::song->mtype(), track->type() == MusECore::Track::DRUM); //QMenu* pup = new QMenu(this); MusEGui::PopupMenu* pup = new MusEGui::PopupMenu(this); - populatePatchPopup(instr, pup, channel, MusEGlobal::song->mtype(), track->type() == MusECore::Track::DRUM); + populatePatchPopup(instr, pup, channel, MusEGlobal::song->mtype(), track->type() == MusECore::Track::DRUM); //FINDMICHJETZT was soll das? ///if(pop->actions().count() == 0) /// return; diff --git a/muse2/muse/midi.cpp b/muse2/muse/midi.cpp index 0d81ff2c..65bccc70 100644 --- a/muse2/muse/midi.cpp +++ b/muse2/muse/midi.cpp @@ -257,7 +257,7 @@ void buildMidiEventList(EventList* del, const MPEventList* el, MidiTrack* track, case ME_NOTEON: e.setType(Note); - if (track->type() == Track::DRUM) { + if (track->type() == Track::DRUM) { //FINDMICHJETZT int instr = MusEGlobal::drumInmap[ev.dataA()]; e.setPitch(instr); } @@ -271,7 +271,7 @@ void buildMidiEventList(EventList* del, const MPEventList* el, MidiTrack* track, break; case ME_NOTEOFF: e.setType(Note); - if (track->type() == Track::DRUM) { + if (track->type() == Track::DRUM) { //FINDMICHJETZT int instr = MusEGlobal::drumInmap[ev.dataA()]; e.setPitch(instr); } @@ -373,7 +373,7 @@ void buildMidiEventList(EventList* del, const MPEventList* el, MidiTrack* track, int ctl = ev.dataA(); e.setA(ctl); - if(track->type() == Track::DRUM) + if(track->type() == Track::DRUM) //FINDMICHJETZT drum controller? { // Is it a drum controller event, according to the track port's instrument? MidiController *mc = MusEGlobal::midiPorts[track->outPort()].drumController(ctl); @@ -736,6 +736,12 @@ void Audio::collectEvents(MusECore::MidiTrack* track, unsigned int cts, unsigned if (ev.isNote() && MusEGlobal::drumMap[instr].mute) continue; } + else if (track->type() == Track::NEW_DRUM) { + int instr = ev.pitch(); + // ignore muted drums + if (ev.isNote() && track->drummap()[instr].mute) + continue; + } unsigned tick = ev.tick() + offset; unsigned frame = MusEGlobal::tempomap.tick2frame(tick) + frameOffset; switch (ev.type()) { @@ -754,7 +760,7 @@ void Audio::collectEvents(MusECore::MidiTrack* track, unsigned int cts, unsigned channel = MusEGlobal::drumMap[instr].channel; velo = int(double(velo) * (double(MusEGlobal::drumMap[instr].vol) / 100.0)) ; } - else { + else { //FINDMICHJETZT don't transpose for new style drum tracks // // transpose non drum notes // @@ -807,7 +813,7 @@ void Audio::collectEvents(MusECore::MidiTrack* track, unsigned int cts, unsigned case Controller: { - if (track->type() == Track::DRUM) + if (track->type() == Track::DRUM) //FINDMICHJETZT was ist das? drumcontroller -_- { int ctl = ev.dataA(); // Is it a drum controller event, according to the track port's instrument? @@ -979,7 +985,7 @@ void Audio::processMidi() // //Apply drum inkey: - if (track->type() == Track::DRUM) + if (track->type() == Track::DRUM) //FINDMICHJETZT schwierig... { int pitch = event.dataA(); //Map note that is played according to MusEGlobal::drumInmap @@ -1016,7 +1022,7 @@ void Audio::processMidi() else if(event.type() == MusECore::ME_CONTROLLER) { - if(track->type() == Track::DRUM) + if(track->type() == Track::DRUM) //FINDMICHJETZT was ist das? { ctl = event.dataA(); // Regardless of what port the event came from, is it a drum controller event @@ -1079,7 +1085,7 @@ void Audio::processMidi() // to the track port so buildMidiEventList will accept it. Even though // the port may have no device "<none>". // - if (track->type() == Track::DRUM) + if (track->type() == Track::DRUM) //FINDMICHJETZT was ist das? { // Is it a drum controller event? if(mc) diff --git a/muse2/muse/midiedit/dcanvas.cpp b/muse2/muse/midiedit/dcanvas.cpp index da94986b..22db70d0 100644 --- a/muse2/muse/midiedit/dcanvas.cpp +++ b/muse2/muse/midiedit/dcanvas.cpp @@ -34,12 +34,12 @@ #include <stdio.h> #include <values.h> #include <errno.h> -#include <set> //#include <sys/stat.h> //#include <sys/mman.h> #include "dcanvas.h" #include "midieditor.h" +#include "drumedit.h" #include "drummap.h" #include "event.h" #include "mpevent.h" @@ -50,20 +50,23 @@ #include "shortcuts.h" #include "icons.h" #include "functions.h" +#include "helper.h" #define CARET 10 #define CARET2 5 +using MusEGlobal::debugMsg; +using MusEGlobal::heavyDebugMsg; + namespace MusEGui { //--------------------------------------------------------- // DEvent //--------------------------------------------------------- -DEvent::DEvent(MusECore::Event e, MusECore::Part* p) +DEvent::DEvent(MusECore::Event e, MusECore::Part* p, int instr) : CItem(e, p) { - int instr = e.pitch(); int y = instr * TH + TH/2; int tick = e.tick() + p->tick(); setPos(QPoint(tick, y)); @@ -81,7 +84,14 @@ void DrumCanvas::addItem(MusECore::Part* part, MusECore::Event& event) return; } - DEvent* ev = new DEvent(event, part); + int instr=pitch_and_track_to_instrument(event.pitch(), part->track()); + if (instr<0) + { + if (heavyDebugMsg) printf("trying to add event which is hidden or not in any part known to me\n"); + return; + } + + DEvent* ev = new DEvent(event, part, instr); items.add(ev); int diff = event.endTick()-part->lenTick(); @@ -103,6 +113,35 @@ DrumCanvas::DrumCanvas(MidiEditor* pr, QWidget* parent, int sx, int sy, const char* name) : EventCanvas(pr, parent, sx, sy, name) { + drumEditor=dynamic_cast<DrumEdit*>(pr); + + old_style_drummap_mode = drumEditor->old_style_drummap_mode(); + + if (old_style_drummap_mode) + { + if (debugMsg) printf("DrumCanvas in old style drummap mode\n"); + ourDrumMap = MusEGlobal::drumMap; + must_delete_our_drum_map=false; + + instrument_number_mapping_t temp; + for (MusECore::ciPart it=drumEditor->parts()->begin(); it!=drumEditor->parts()->end(); it++) + temp.tracks.insert(it->second->track()); + + for (int i=0;i<DRUM_MAPSIZE;i++) + { + temp.pitch=i; + instrument_map.append(temp); + } + } + else + { + if (debugMsg) printf("DrumCanvas in new style drummap mode\n"); + ourDrumMap=NULL; + rebuildOurDrumMap(); + } + + + setVirt(false); cursorPos= QPoint(0,0); _stepSize=1; @@ -116,6 +155,10 @@ DrumCanvas::DrumCanvas(MidiEditor* pr, QWidget* parent, int sx, DrumCanvas::~DrumCanvas() { //items.clearDelete(); + + if (must_delete_our_drum_map && ourDrumMap!=NULL) + delete [] ourDrumMap; + delete steprec; } //--------------------------------------------------------- @@ -195,7 +238,7 @@ MusECore::Undo DrumCanvas::moveCanvasItems(CItemList& items, int dp, int dx, Dra for(iCItem ici = items.begin(); ici != items.end(); ++ici) { - CItem* ci = ici->second; + CItem* ci = ici->second; int x = ci->pos().x(); int y = ci->pos().y(); @@ -217,7 +260,7 @@ MusECore::Undo DrumCanvas::moveCanvasItems(CItemList& items, int dp, int dx, Dra doneList.push_back(ci); } ci->move(newpos); - + if(moving.size() == 1) itemReleased(curItem, newpos); @@ -258,10 +301,20 @@ MusECore::UndoOp DrumCanvas::moveItem(CItem* item, const QPoint& pos, DragType d int ntick = editor->rasterVal(x) - part->tick(); if (ntick < 0) ntick = 0; - int npitch = y2pitch(pos.y()); + int nheight = y2pitch(pos.y()); MusECore::Event newEvent = event.clone(); - - newEvent.setPitch(npitch); + + MusECore::Track* dest_track = part->track(); + if (!instrument_map[nheight].tracks.contains(dest_track)) + { + printf ("TODO FIXME: tried to move an event into a different track. this is not supported yet, but will be soon. ignoring this one...\n"); + //FINDMICH + return MusECore::UndoOp(); + } + + int ev_pitch = instrument_map[nheight].pitch; + + newEvent.setPitch(ev_pitch); newEvent.setTick(ntick); // Added by T356, removed by flo93: with operation groups, it happens that the @@ -282,13 +335,13 @@ MusECore::UndoOp DrumCanvas::moveItem(CItem* item, const QPoint& pos, DragType d CItem* DrumCanvas::newItem(const QPoint& p, int state) { int instr = y2pitch(p.y()); //MusEGlobal::drumInmap[y2pitch(p.y())]; - int velo = MusEGlobal::drumMap[instr].lv4; + int velo = ourDrumMap[instr].lv4; if (state == Qt::ShiftModifier) - velo = MusEGlobal::drumMap[instr].lv3; + velo = ourDrumMap[instr].lv3; else if (state == Qt::ControlModifier) - velo = MusEGlobal::drumMap[instr].lv2; + velo = ourDrumMap[instr].lv2; else if (state == (Qt::ControlModifier | Qt::ShiftModifier)) - velo = MusEGlobal::drumMap[instr].lv1; + velo = ourDrumMap[instr].lv1; int tick = editor->rasterVal(p.x()); return newItem(tick, instr, velo); } @@ -299,13 +352,22 @@ CItem* DrumCanvas::newItem(const QPoint& p, int state) CItem* DrumCanvas::newItem(int tick, int instrument, int velocity) { - tick -= curPart->tick(); - MusECore::Event e(MusECore::Note); - e.setTick(tick); - e.setPitch(instrument); - e.setVelo(velocity); - e.setLenTick(MusEGlobal::drumMap[instrument].len); - return new DEvent(e, curPart); + if (!old_style_drummap_mode && !instrument_map[instrument].tracks.contains(curPart->track())) + { + printf("FINDMICH: tried to create a new Item which cannot be inside the current track. returning NULL\n"); + return NULL; + } + else + { + tick -= curPart->tick(); + MusECore::Event e(MusECore::Note); + e.setTick(tick); + e.setPitch(instrument_map[instrument].pitch); + e.setVelo(velocity); + e.setLenTick(ourDrumMap[instrument].len); + + return new DEvent(e, curPart, instrument); + } } //--------------------------------------------------------- @@ -328,7 +390,9 @@ void DrumCanvas::newItem(CItem* item, bool noSnap) { } void DrumCanvas::newItem(CItem* item, bool noSnap, bool replace) - { +{ + if (item) + { DEvent* nevent = (DEvent*) item; MusECore::Event event = nevent->event(); int x = item->x(); @@ -336,7 +400,7 @@ void DrumCanvas::newItem(CItem* item, bool noSnap, bool replace) x = editor->rasterVal(x); event.setTick(x - nevent->part()->tick()); int npitch = event.pitch(); - event.setPitch(npitch); + //event.setPitch(npitch); // commented out by flo: has no effect // // check for existing event @@ -372,7 +436,7 @@ void DrumCanvas::newItem(CItem* item, bool noSnap, bool replace) { operations.push_back(MusECore::UndoOp(MusECore::UndoOp::AddEvent,event, part, false, false)); - if (diff > 0)// part must be extended? + if (diff > 0) // part must be extended? { schedule_resize_all_same_len_clone_parts(part, event.endTick(), operations); printf("newItem: extending\n"); @@ -382,7 +446,10 @@ void DrumCanvas::newItem(CItem* item, bool noSnap, bool replace) MusEGlobal::song->applyOperationGroup(operations); songChanged(SC_EVENT_INSERTED); //this forces an update of the itemlist, which is neccessary //to remove "forbidden" events from the list again - } + } + else + printf("THIS SHOULD NEVER HAPPEN: DrumCanvas::newItem called with NULL item!\n"); +} //--------------------------------------------------------- // deleteItem @@ -437,7 +504,7 @@ void DrumCanvas::drawItem(QPainter&p, const CItem*item, const QRect& rect) else { int velo = e->event().velo(); - MusECore::DrumMap* dm = &MusEGlobal::drumMap[y2pitch(y)]; //Get the drum item + MusECore::DrumMap* dm = &ourDrumMap[y2pitch(y)]; //Get the drum item QColor color; if (velo < dm->lv1) color.setRgb(240, 240, 255); @@ -528,8 +595,8 @@ void DrumCanvas::drawTopItem(QPainter& p, const QRect&) int DrumCanvas::y2pitch(int y) const { int pitch = y/TH; - if (pitch >= DRUM_MAPSIZE) - pitch = DRUM_MAPSIZE-1; + if (pitch >= instrument_map.size()) + pitch = instrument_map.size()-1; return pitch; } @@ -638,7 +705,8 @@ void DrumCanvas::cmd(int cmd) DEvent* devent = (DEvent*)(k->second); MusECore::Event event = devent->event(); MusECore::Event newEvent = event.clone(); - newEvent.setLenTick(MusEGlobal::drumMap[event.pitch()].len); + // newEvent.setLenTick(drumMap[event.pitch()].len); + newEvent.setLenTick(ourDrumMap[y2pitch(devent->y())].len); // Indicate no undo, and do not do port controller values and clone parts. MusEGlobal::audio->msgChangeEvent(event, newEvent, devent->part(), false, false, false); } @@ -740,19 +808,19 @@ void DrumCanvas::dragLeaveEvent(QDragLeaveEvent*) // keyPressed - called from DList //--------------------------------------------------------- -void DrumCanvas::keyPressed(int index, int velocity) +void DrumCanvas::keyPressed(int index, int velocity) //FINDMICH later { // called from DList - play event - int port = MusEGlobal::drumMap[index].port; - int channel = MusEGlobal::drumMap[index].channel; - int pitch = MusEGlobal::drumMap[index].anote; + int port = ourDrumMap[index].port; + int channel = ourDrumMap[index].channel; + int pitch = ourDrumMap[index].anote; // play note: MusECore::MidiPlayEvent e(0, port, channel, 0x90, pitch, velocity); MusEGlobal::audio->msgPlayMidiEvent(&e); if (_steprec && pos[0] >= start_tick /* && pos[0] < end_tick [removed by flo93: this is handled in steprec->record] */ && curPart) - steprec->record(curPart,index,MusEGlobal::drumMap[index].len,editor->raster(),velocity,MusEGlobal::globalKeyState&Qt::ControlModifier,MusEGlobal::globalKeyState&Qt::ShiftModifier); + steprec->record(curPart,index,ourDrumMap[index].len,editor->raster(),velocity,MusEGlobal::globalKeyState&Qt::ControlModifier,MusEGlobal::globalKeyState&Qt::ShiftModifier); } @@ -760,12 +828,12 @@ void DrumCanvas::keyPressed(int index, int velocity) // keyReleased //--------------------------------------------------------- -void DrumCanvas::keyReleased(int index, bool) +void DrumCanvas::keyReleased(int index, bool) //FINDMICH later { // called from DList - silence playing event - int port = MusEGlobal::drumMap[index].port; - int channel = MusEGlobal::drumMap[index].channel; - int pitch = MusEGlobal::drumMap[index].anote; + int port = ourDrumMap[index].port; + int channel = ourDrumMap[index].channel; + int pitch = ourDrumMap[index].anote; // release note: MusECore::MidiPlayEvent e(0, port, channel, 0x90, pitch, 0); @@ -777,7 +845,12 @@ void DrumCanvas::keyReleased(int index, bool) //--------------------------------------------------------- void DrumCanvas::mapChanged(int spitch, int dpitch) - { +{ + // spitch may be the same as dpitch! and something in here must be executed + // even if they're same (i assume it's song->update(SC_DRUMMAP)) (flo93) + + if (old_style_drummap_mode) + { MusECore::Undo operations; std::vector< std::pair<MusECore::Part*, MusECore::Event*> > delete_events; std::vector< std::pair<MusECore::Part*, MusECore::Event> > add_events; @@ -855,7 +928,74 @@ void DrumCanvas::mapChanged(int spitch, int dpitch) MusEGlobal::song->applyOperationGroup(operations, false); // do not indicate undo MusEGlobal::song->update(SC_DRUMMAP); //this update is neccessary, as it's not handled by applyOperationGroup() + } + else // if (!old_style_drummap_mode) + { + if (dpitch!=spitch) + { + using MusEGlobal::global_drum_ordering_t; + using MusEGlobal::global_drum_ordering; + + MusECore::DrumMap dm_temp = ourDrumMap[spitch]; + instrument_number_mapping_t im_temp = instrument_map[spitch]; + + global_drum_ordering_t order_temp; + for (global_drum_ordering_t::iterator it=global_drum_ordering.begin(); it!=global_drum_ordering.end();) + { + if (im_temp.pitch==it->second && im_temp.tracks.contains(it->first)) + { + order_temp.push_back(*it); + it=global_drum_ordering.erase(it); + } + else + it++; + } + + // the instrument represented by instrument_map[dpitch] is always the instrument + // which will be immediately AFTER our dragged instrument + for (global_drum_ordering_t::iterator it=global_drum_ordering.begin(); it!=global_drum_ordering.end(); it++) + if (instrument_map[dpitch].pitch==it->second && instrument_map[dpitch].tracks.contains(it->first)) + { + while (!order_temp.empty()) + it=global_drum_ordering.insert(it, order_temp.takeLast()); + + break; + } + + + + + + if (dpitch > spitch) + { + for (int i=spitch; i<dpitch-1; i++) + { + ourDrumMap[i]=ourDrumMap[i+1]; + instrument_map[i]=instrument_map[i+1]; + } + + ourDrumMap[dpitch-1] = dm_temp; + instrument_map[dpitch-1] = im_temp; + } + else if (spitch > dpitch) + { + for (int i=spitch; i>dpitch; i--) + { + ourDrumMap[i]=ourDrumMap[i-1]; + instrument_map[i]=instrument_map[i-1]; + } + + ourDrumMap[dpitch] = dm_temp; + instrument_map[dpitch] = im_temp; + } } + + + MusEGlobal::song->update(SC_DRUMMAP); // this causes a complete rebuild of ourDrumMap + // which also handles the changed order in all + // other drum editors + } +} //--------------------------------------------------------- // resizeEvent @@ -907,6 +1047,7 @@ void DrumCanvas::modifySelected(NoteInfo::ValType type, int delta) printf("DrumCanvas::modifySelected - NoteInfo::VAL_VELOFF not implemented\n"); break; case NoteInfo::VAL_PITCH: + if (old_style_drummap_mode) { int pitch = event.pitch() - delta; // Reversing order since the drumlist is displayed in increasing order if (pitch > 127) @@ -915,6 +1056,8 @@ void DrumCanvas::modifySelected(NoteInfo::ValType type, int delta) pitch = 0; newEvent.setPitch(pitch); } + else + printf("DrumCanvas::modifySelected - MusEWidget::NoteInfo::VAL_PITCH not implemented for new style drum editors\n"); break; } MusEGlobal::song->changeEvent(event, newEvent, part); @@ -992,8 +1135,8 @@ void DrumCanvas::keyPress(QKeyEvent* event) return; } else if (key == shortcuts[SHRT_ADDNOTE_1].key) { - newItem(newItem(cursorPos.x(), cursorPos.y(), MusEGlobal::drumMap[cursorPos.y()].lv1),false,true); - keyPressed(cursorPos.y(), MusEGlobal::drumMap[cursorPos.y()].lv1); + newItem(newItem(cursorPos.x(), cursorPos.y(), ourDrumMap[cursorPos.y()].lv1),false,true); + keyPressed(cursorPos.y(), ourDrumMap[cursorPos.y()].lv1); keyReleased(cursorPos.y(), false); cursorPos.setX(getNextStep(cursorPos.x(),1, _stepSize)); selectCursorEvent(getEventAtCursorPos()); @@ -1002,8 +1145,8 @@ void DrumCanvas::keyPress(QKeyEvent* event) return; } else if (key == shortcuts[SHRT_ADDNOTE_2].key) { - newItem(newItem(cursorPos.x(), cursorPos.y(), MusEGlobal::drumMap[cursorPos.y()].lv2),false,true); - keyPressed(cursorPos.y(), MusEGlobal::drumMap[cursorPos.y()].lv2); + newItem(newItem(cursorPos.x(), cursorPos.y(), ourDrumMap[cursorPos.y()].lv2),false,true); + keyPressed(cursorPos.y(), ourDrumMap[cursorPos.y()].lv2); keyReleased(cursorPos.y(), false); cursorPos.setX(getNextStep(cursorPos.x(),1, _stepSize)); selectCursorEvent(getEventAtCursorPos()); @@ -1012,8 +1155,8 @@ void DrumCanvas::keyPress(QKeyEvent* event) return; } else if (key == shortcuts[SHRT_ADDNOTE_3].key) { - newItem(newItem(cursorPos.x(), cursorPos.y(), MusEGlobal::drumMap[cursorPos.y()].lv3),false,true); - keyPressed(cursorPos.y(), MusEGlobal::drumMap[cursorPos.y()].lv3); + newItem(newItem(cursorPos.x(), cursorPos.y(), ourDrumMap[cursorPos.y()].lv3),false,true); + keyPressed(cursorPos.y(), ourDrumMap[cursorPos.y()].lv3); keyReleased(cursorPos.y(), false); cursorPos.setX(getNextStep(cursorPos.x(),1, _stepSize)); selectCursorEvent(getEventAtCursorPos()); @@ -1022,8 +1165,8 @@ void DrumCanvas::keyPress(QKeyEvent* event) return; } else if (key == shortcuts[SHRT_ADDNOTE_4].key) { - newItem(newItem(cursorPos.x(), cursorPos.y(), MusEGlobal::drumMap[cursorPos.y()].lv4),false,true); - keyPressed(cursorPos.y(), MusEGlobal::drumMap[cursorPos.y()].lv4); + newItem(newItem(cursorPos.x(), cursorPos.y(), ourDrumMap[cursorPos.y()].lv4),false,true); + keyPressed(cursorPos.y(), ourDrumMap[cursorPos.y()].lv4); keyReleased(cursorPos.y(), false); cursorPos.setX(getNextStep(cursorPos.x(),1, _stepSize)); selectCursorEvent(getEventAtCursorPos()); @@ -1071,17 +1214,19 @@ MusECore::Event *DrumCanvas::getEventAtCursorPos() { if (_tool != CursorTool) return 0; - MusECore::EventList* el = curPart->events(); - MusECore::iEvent lower = el->lower_bound(cursorPos.x()-curPart->tick()); - MusECore::iEvent upper = el->upper_bound(cursorPos.x()-curPart->tick()); - for (MusECore::iEvent i = lower; i != upper; ++i) { - MusECore::Event &ev = i->second; - if(!ev.isNote()) - continue; - if (ev.pitch() == cursorPos.y()) { - return &ev; + if (instrument_map[cursorPos.y()].tracks.contains(curPart->track())) + { + MusECore::EventList* el = curPart->events(); + MusECore::iEvent lower = el->lower_bound(cursorPos.x()-curPart->tick()); + MusECore::iEvent upper = el->upper_bound(cursorPos.x()-curPart->tick()); + int curPitch = instrument_map[cursorPos.y()].pitch; + for (MusECore::iEvent i = lower; i != upper; ++i) { + MusECore::Event &ev = i->second; + if (ev.isNote() && ev.pitch() == curPitch) + return &ev; } } + // else or if the for loop didn't find anything return 0; } //--------------------------------------------------------- @@ -1105,9 +1250,13 @@ void DrumCanvas::selectCursorEvent(MusECore::Event *ev) void DrumCanvas::moveAwayUnused() { - using std::set; + if (!old_style_drummap_mode) + { + printf("THIS SHOULD NEVER HAPPEN: DrumCanvas::moveAwayUnused() cannot be used in new style mode\n"); + return; + } - set<int> used; + QSet<int> used; for (iCItem it=items.begin(); it!=items.end(); it++) { const MusECore::Event& ev=it->second->event(); @@ -1117,7 +1266,7 @@ void DrumCanvas::moveAwayUnused() } int count=0; - for (set<int>::iterator it=used.begin(); it!=used.end();) + for (QSet<int>::iterator it=used.begin(); it!=used.end();) { while ((*it != count) && (used.find(count)!=used.end())) count++; @@ -1134,16 +1283,200 @@ void DrumCanvas::moveAwayUnused() //--------------------------------------------------------- // midiNote //--------------------------------------------------------- -void DrumCanvas::midiNote(int pitch, int velo) +void DrumCanvas::midiNote(int pitch, int velo) //FINDMICH later. { - if (MusEGlobal::debugMsg) printf("DrumCanvas::midiNote: pitch=%i, velo=%i\n", pitch, velo); + if (debugMsg) printf("DrumCanvas::midiNote: pitch=%i, velo=%i\n", pitch, velo); if (_midiin && _steprec && curPart && !MusEGlobal::audio->isPlaying() && velo && pos[0] >= start_tick - /* && pos[0] < end_tick [removed by flo93: this is handled in steprec->record] */ + /* && pos[0] < end_tick [removed by flo93: this is handled in steprec->record()] */ && !(MusEGlobal::globalKeyState & Qt::AltModifier)) { - steprec->record(curPart,MusEGlobal::drumInmap[pitch],MusEGlobal::drumMap[(int)MusEGlobal::drumInmap[pitch]].len,editor->raster(),velo,MusEGlobal::globalKeyState&Qt::ControlModifier,MusEGlobal::globalKeyState&Qt::ShiftModifier); + steprec->record(curPart,MusEGlobal::drumInmap[pitch],ourDrumMap[(int)MusEGlobal::drumInmap[pitch]].len,editor->raster(),velo,MusEGlobal::globalKeyState&Qt::ControlModifier,MusEGlobal::globalKeyState&Qt::ShiftModifier); } } + +int DrumCanvas::pitch_and_track_to_instrument(int pitch, MusECore::Track* track) +{ + for (int i=0; i<instrument_map.size(); i++) + if (instrument_map[i].tracks.contains(track) && instrument_map[i].pitch==pitch) + return i; + + printf("ERROR: DrumCanvas::pitch_and_track_to_instrument() called with invalid arguments!\n"); + return -1; +} + +void DrumCanvas::propagate_drummap_change(int instr) +{ + const QSet<MusECore::Track*>& tracks=instrument_map[instr].tracks; + int index=instrument_map[instr].pitch; + + for (QSet<MusECore::Track*>::const_iterator it = tracks.begin(); it != tracks.end(); it++) + dynamic_cast<MusECore::MidiTrack*>(*it)->drummap()[index] = ourDrumMap[instr]; +} + + +void DrumCanvas::rebuildOurDrumMap() +{ + using MusECore::drummaps_almost_equal; + using MusECore::Track; + using MusECore::MidiTrack; + using MusECore::TrackList; + using MusECore::ciTrack; + using MusECore::ciPart; + using MusECore::DrumMap; + using MusEGlobal::global_drum_ordering_t; + using MusEGlobal::global_drum_ordering; + + + if (!old_style_drummap_mode) + { + bool need_update = false; + + TrackList* tl=MusEGlobal::song->tracks(); + QList< QSet<Track*> > track_groups; + QVector<instrument_number_mapping_t> old_instrument_map = instrument_map; + + instrument_map.clear(); + + for (ciTrack track = tl->begin(); track!=tl->end(); track++) + { + ciPart p_it; + for (p_it=drumEditor->parts()->begin(); p_it!=drumEditor->parts()->end(); p_it++) + if (p_it->second->track() == *track) + break; + + if (p_it!=drumEditor->parts()->end()) // if *track is represented by some part in this editor + { + bool inserted=false; + + switch (drumEditor->group_mode()) + { + case DrumEdit::GROUP_SAME_CHANNEL: + for (QList< QSet<Track*> >::iterator group=track_groups.begin(); group!=track_groups.end(); group++) + if ( ((MidiTrack*)*group->begin())->outChannel() == ((MidiTrack*)*track)->outChannel() && + ((MidiTrack*)*group->begin())->outPort() == ((MidiTrack*)*track)->outPort() && + (drummaps_almost_equal(((MidiTrack*)*group->begin())->drummap(), ((MidiTrack*)*track)->drummap())) ) + { + group->insert(*track); + inserted=true; + break; + } + break; + + case DrumEdit::GROUP_MAX: + for (QList< QSet<Track*> >::iterator group=track_groups.begin(); group!=track_groups.end(); group++) + if (drummaps_almost_equal(((MidiTrack*)*group->begin())->drummap(), ((MidiTrack*)*track)->drummap())) + { + group->insert(*track); + inserted=true; + break; + } + break; + + case DrumEdit::DONT_GROUP: + inserted=false; + break; + + default: + printf("THIS SHOULD NEVER HAPPEN: group_mode() is invalid!\n"); + inserted=false; + } + + if (!inserted) + { + QSet<Track*> temp; + temp.insert(*track); + track_groups.push_back(temp); + } + } + } + + // from now, we assume that every track_group's entry only groups tracks with identical + // drum maps, but not necessarily identical hide-lists together. + QList< std::pair<MidiTrack*,int> > ignore_order_entries; + for (global_drum_ordering_t::iterator order_it=global_drum_ordering.begin(); order_it!=global_drum_ordering.end(); order_it++) + { + // if this entry should be ignored, ignore it. + if (ignore_order_entries.contains(*order_it)) + continue; + + // look if we have order_it->first (the MidiTrack*) in any of our track groups + QList< QSet<Track*> >::iterator group; + for (group=track_groups.begin(); group!=track_groups.end(); group++) + if (group->contains(order_it->first)) + break; + + if (group!=track_groups.end()) // we have + { + int pitch=order_it->second; + + bool mute=true; + bool hidden=true; + + if (drumEditor->ignore_hide()) hidden=false; + + for (QSet<Track*>::iterator track=group->begin(); track!=group->end() && (mute || hidden); track++) + { + if (dynamic_cast<MidiTrack*>(*track)->drummap()[pitch].mute == false) + mute=false; + + if (dynamic_cast<MidiTrack*>(*track)->drummap_hidden()[pitch] == false) + hidden=false; + } + + if (!hidden) + { + for (QSet<Track*>::iterator track=group->begin(); track!=group->end(); track++) + { + DrumMap* dm = &dynamic_cast<MidiTrack*>(*track)->drummap()[pitch]; + if (dm->mute != mute) + { + dm->mute=mute; + need_update = true; + } + } + + if (dynamic_cast<MidiTrack*>(*group->begin())->drummap()[pitch].anote != pitch) + printf("THIS SHOULD NEVER HAPPEN: track's_drummap[pitch].anote (%i)!= pitch (%i) !!!\n",dynamic_cast<MidiTrack*>(*group->begin())->drummap()[pitch].anote,pitch); + + instrument_map.append(instrument_number_mapping_t(*group, pitch)); + } + + for (QSet<Track*>::iterator track=group->begin(); track!=group->end(); track++) + ignore_order_entries.append(std::pair<MidiTrack*,int>(dynamic_cast<MidiTrack*>(*track), pitch)); + } + // else ignore it + } + + + // maybe delete and then populate ourDrumMap + + if (must_delete_our_drum_map && ourDrumMap!=NULL) + delete [] ourDrumMap; + + int size = instrument_map.size(); + ourDrumMap=new DrumMap[size]; + must_delete_our_drum_map=true; + + for (int i=0;i<size;i++) + ourDrumMap[i] = dynamic_cast<MidiTrack*>(*instrument_map[i].tracks.begin())->drummap()[instrument_map[i].pitch]; + + if (instrument_map!=old_instrument_map) + { + if (debugMsg) printf("rebuilt drummap and instrument map, size is now %i\n",size); + + songChanged(SC_EVENT_INSERTED); // force an update of the itemlist + emit ourDrumMapChanged(true); + } + else + emit ourDrumMapChanged(false); + + if (need_update) + MusEGlobal::song->update(SC_DRUMMAP, true); // i know, this causes a recursion, which possibly + // isn't the most elegant solution here. but it will + // never be an infinite recursion + } +} + } // namespace MusEGui diff --git a/muse2/muse/midiedit/dcanvas.h b/muse2/muse/midiedit/dcanvas.h index bc9dbdbc..581de9d7 100644 --- a/muse2/muse/midiedit/dcanvas.h +++ b/muse2/muse/midiedit/dcanvas.h @@ -26,6 +26,9 @@ #include "ecanvas.h" #include "song.h" #include "steprec.h" +#include <map> +#include <QList> +#include <QSet> #define TH 18 @@ -36,11 +39,11 @@ class QDropEvent; class QDragMoveEvent; class QDragLeaveEvent; +class DrumMap; namespace MusEGui { class MidiEditor; -class PianoRoll; -class ScrollScale; +class DrumEdit; //--------------------------------------------------------- // DEvent @@ -49,9 +52,38 @@ class ScrollScale; class DEvent : public CItem { public: - DEvent(MusECore::Event e, MusECore::Part* p); + DEvent(MusECore::Event e, MusECore::Part* p, int instr); }; + +struct instrument_number_mapping_t //FINDMICH TODO move into a suitable namespace! +{ + QSet<MusECore::Track*> tracks; + int pitch; + + instrument_number_mapping_t() + { + pitch=-1; + tracks.clear(); + } + + instrument_number_mapping_t(const QSet<MusECore::Track*>& tr, int p) + { + tracks=tr; + pitch=p; + } + + bool operator==(const instrument_number_mapping_t& that) //TODO maybe compare the Track* serial numbers, not the pointers themselves? + { + return (this->tracks == that.tracks && this->pitch==that.pitch); + } + + bool operator!=(const instrument_number_mapping_t& that) + { + return !operator==(that); + } +}; + //--------------------------------------------------------- // DrumCanvas //--------------------------------------------------------- @@ -59,6 +91,13 @@ class DEvent : public CItem { class DrumCanvas : public EventCanvas { Q_OBJECT + bool old_style_drummap_mode; + MusECore::DrumMap* ourDrumMap; + bool must_delete_our_drum_map; //FINDMICH really delete it! + QVector<instrument_number_mapping_t> instrument_map; + + DrumEdit* drumEditor; + MusECore::StepRec* steprec; // Cursor tool position @@ -89,9 +128,10 @@ class DrumCanvas : public EventCanvas { virtual void resizeEvent(QResizeEvent*); virtual void curPartChanged(); int getNextStep(unsigned int pos, int basicStep, int stepSize=1); - + signals: void newWidth(int); + void ourDrumMapChanged(bool /*instrumentMap changed as well?*/); private slots: void midiNote(int pitch, int velo); @@ -111,7 +151,8 @@ class DrumCanvas : public EventCanvas { CMD_SELECT_ALL, CMD_SELECT_NONE, CMD_SELECT_INVERT, CMD_SELECT_ILOOP, CMD_SELECT_OLOOP, CMD_SELECT_PREV_PART, CMD_SELECT_NEXT_PART, CMD_DEL, CMD_FIXED_LEN, CMD_RIGHT, CMD_LEFT, CMD_RIGHT_NOSNAP, CMD_LEFT_NOSNAP, CMD_MODIFY_VELOCITY, CMD_CRESCENDO, - CMD_QUANTIZE, CMD_ERASE_EVENT, CMD_NOTE_SHIFT, CMD_DELETE_OVERLAPS, CMD_REORDER_LIST + CMD_QUANTIZE, CMD_ERASE_EVENT, CMD_NOTE_SHIFT, CMD_DELETE_OVERLAPS, CMD_REORDER_LIST, + CMD_GROUP_NONE, CMD_GROUP_CHAN, CMD_GROUP_MAX }; DrumCanvas(MidiEditor*, QWidget*, int, int, const char* name = 0); @@ -121,7 +162,12 @@ class DrumCanvas : public EventCanvas { virtual void keyPress(QKeyEvent* event); MusECore::Event *getEventAtCursorPos(); void selectCursorEvent(MusECore::Event *ev); - + int pitch_and_track_to_instrument(int pitch, MusECore::Track* track); + MusECore::DrumMap* getOurDrumMap() { return ourDrumMap; } //FINDMICH UGLY + int getOurDrumMapSize() { return instrument_map.size(); } //FINDMICH UGLY + QVector<instrument_number_mapping_t>& get_instrument_map() { return instrument_map; } //FINDMICH UGLY + void propagate_drummap_change(int instrument); //FINDMICH move to drumedit + void rebuildOurDrumMap(); }; } // namespace MusEGui diff --git a/muse2/muse/midiedit/dlist.cpp b/muse2/muse/midiedit/dlist.cpp index c6cd9b2e..4ad971e7 100644 --- a/muse2/muse/midiedit/dlist.cpp +++ b/muse2/muse/midiedit/dlist.cpp @@ -33,11 +33,12 @@ #include "pitchedit.h" #include "midiport.h" #include "drummap.h" +#include "drumedit.h" #include "helper.h" #include "icons.h" #include "dlist.h" #include "song.h" -#include "scrollscale.h" +#include "dcanvas.h" namespace MusEGui { @@ -58,13 +59,13 @@ void DList::draw(QPainter& p, const QRect& rect) p.setPen(Qt::black); - for (int i = 0; i < DRUM_MAPSIZE; ++i) { - int yy = i * TH; + for (int instrument = 0; instrument < ourDrumMapSize; ++instrument) { + int yy = instrument * TH; if (yy+TH < y) continue; if (yy > y + h) break; - MusECore::DrumMap* dm = &MusEGlobal::drumMap[i]; + MusECore::DrumMap* dm = &ourDrumMap[instrument]; if (dm == currentlySelected) p.fillRect(x, yy, w, TH, Qt::yellow); // else @@ -73,6 +74,10 @@ void DList::draw(QPainter& p, const QRect& rect) p.save(); p.setWorldMatrixEnabled(false); for (int k = 0; k < h->count(); ++k) { + if (h->isSectionHidden(k)) + continue; + + int x = h->sectionPosition(k); int w = h->sectionSize(k); //QRect r = p.combinedTransform().mapRect(QRect(x+2, yy, w-4, TH)); // Gives inconsistent positions. Source shows wrong operation for our needs. @@ -83,33 +88,72 @@ void DList::draw(QPainter& p, const QRect& rect) //p.save(); //p.setWorldMatrixEnabled(false); switch (k) { - case COL_VOL: + case COL_VOLUME: s.setNum(dm->vol); break; - case COL_QNT: + case COL_QUANT: s.setNum(dm->quant); break; - case COL_LEN: + case COL_NOTELENGTH: s.setNum(dm->len); break; - case COL_ANOTE: + case COL_NOTE: s = MusECore::pitch2string(dm->anote); break; - case COL_ENOTE: + case COL_INPUTTRIGGER: s = MusECore::pitch2string(dm->enote); break; - case COL_LV1: + case COL_LEVEL1: s.setNum(dm->lv1); break; - case COL_LV2: + case COL_LEVEL2: s.setNum(dm->lv2); break; - case COL_LV3: + case COL_LEVEL3: s.setNum(dm->lv3); break; - case COL_LV4: + case COL_LEVEL4: s.setNum(dm->lv4); break; + case COL_HIDE: + { + bool hidden=false; + bool shown=false; + QSet<MusECore::Track*>* group = &dcanvas->get_instrument_map()[instrument].tracks; + int pitch = dcanvas->get_instrument_map()[instrument].pitch; + + for (QSet<MusECore::Track*>::iterator track=group->begin(); track!=group->end() && !(hidden&&shown); track++) + if (dynamic_cast<MusECore::MidiTrack*>(*track)->drummap_hidden()[pitch]) + hidden=true; + else + shown=true; + + if (!hidden && !shown) + printf("THIS SHOULD NEVER HAPPEN: in DList::draw(): instrument %i's track group is empty. strange...\n", instrument); + + const QPixmap* pm = NULL; + + if (shown && !hidden) + pm = eyeIcon; + else if (!shown && hidden) + pm = eyeCrossedIcon; + else if (shown && hidden) + pm = eyeGrayIcon; + else //if (!shown && !hidden) + pm = NULL; + + if (pm) + { + // p.setPen(Qt::red); + p.drawPixmap( + r.x() + r.width()/2 - pm->width()/2, + r.y() + r.height()/2 - pm->height()/2, + *pm); + // p.setPen(Qt::black); + } + + break; + } case COL_MUTE: if (dm->mute) { p.setPen(Qt::red); @@ -125,10 +169,10 @@ void DList::draw(QPainter& p, const QRect& rect) s = dm->name; align = Qt::AlignVCenter | Qt::AlignLeft; break; - case COL_CHANNEL: + case COL_OUTCHANNEL: s.setNum(dm->channel+1); break; - case COL_PORT: + case COL_OUTPORT: s.sprintf("%d:%s", dm->port+1, MusEGlobal::midiPorts[dm->port].portname().toLatin1().constData()); align = Qt::AlignVCenter | Qt::AlignLeft; break; @@ -180,6 +224,12 @@ void DList::draw(QPainter& p, const QRect& rect) void DList::devicesPopupMenu(MusECore::DrumMap* t, int x, int y, bool changeAll) { + if (!old_style_drummap_mode) + { + printf("THIS SHOULD NEVER HAPPEN: devicesPopupMenu() called in new style mode!\n"); + return; + } + QMenu* p = MusECore::midiPortsPopup(); QAction* act = p->exec(mapToGlobal(QPoint(x, y)), 0); bool doemit = false; @@ -201,8 +251,8 @@ void DList::devicesPopupMenu(MusECore::DrumMap* t, int x, int y, bool changeAll) // Delete all port controller events. MusEGlobal::song->changeAllPortDrumCtrlEvents(false); - for (int i = 0; i < DRUM_MAPSIZE; i++) - MusEGlobal::drumMap[i].port = n; + for (int i = 0; i < ourDrumMapSize; i++) + ourDrumMap[i].port = n; // Add all port controller events. MusEGlobal::song->changeAllPortDrumCtrlEvents(true); @@ -229,16 +279,17 @@ void DList::viewMousePressEvent(QMouseEvent* ev) int x = ev->x(); int y = ev->y(); int button = ev->button(); - unsigned pitch = y / TH; - MusECore::DrumMap* dm = &MusEGlobal::drumMap[pitch]; + unsigned instrument = y / TH; + MusECore::DrumMap* dm = &ourDrumMap[instrument]; + MusECore::DrumMap dm_old = *dm; - setCurDrumInstrument(pitch); + setCurDrumInstrument(instrument); startY = y; - sPitch = pitch; + sInstrument = instrument; drag = START_DRAG; - DCols col = DCols(x2col(x)); + DrumColumn col = DrumColumn(x2col(x)); int val; int incVal = 0; @@ -252,7 +303,7 @@ void DList::viewMousePressEvent(QMouseEvent* ev) // In that case, treat it as if a return was pressed if (button == Qt::LeftButton) { - if (((editEntry && editEntry != dm) || col != selectedColumn) && editEntry != 0) { + if (editEntry && (editEntry != dm || col != selectedColumn)) { returnPressed(); } } @@ -260,54 +311,77 @@ void DList::viewMousePressEvent(QMouseEvent* ev) switch (col) { case COL_NONE: break; + case COL_HIDE: + if (button == Qt::LeftButton) + { + bool hidden=true; + QSet<MusECore::Track*>* group = &dcanvas->get_instrument_map()[instrument].tracks; + int pitch = dcanvas->get_instrument_map()[instrument].pitch; + + for (QSet<MusECore::Track*>::iterator track=group->begin(); track!=group->end(); track++) + if (dynamic_cast<MusECore::MidiTrack*>(*track)->drummap_hidden()[pitch] == false) + { + hidden=false; + break; + } + + for (QSet<MusECore::Track*>::iterator track=group->begin(); track!=group->end(); track++) + dynamic_cast<MusECore::MidiTrack*>(*track)->drummap_hidden()[pitch] = !hidden; + } + break; case COL_MUTE: if (button == Qt::LeftButton) dm->mute = !dm->mute; break; - case COL_PORT: + case COL_OUTPORT: // this column isn't visible in new style drum mode if ((button == Qt::RightButton) || (button == Qt::LeftButton)) { bool changeAll = ev->modifiers() & Qt::ControlModifier; - devicesPopupMenu(dm, mapx(x), mapy(pitch * TH), changeAll); + devicesPopupMenu(dm, mapx(x), mapy(instrument * TH), changeAll); } break; - case COL_VOL: + case COL_VOLUME: val = dm->vol + incVal; if (val < 0) val = 0; - else if (val > 200) - val = 200; + else if (val > 999) //changed from 200 to 999 by flo93 + val = 999; dm->vol = (unsigned char)val; break; - case COL_QNT: + case COL_QUANT: dm->quant += incVal; // ?? range break; - case COL_ENOTE: + case COL_INPUTTRIGGER: val = dm->enote + incVal; if (val < 0) val = 0; else if (val > 127) val = 127; - //Check if there is any other MusEGlobal::drumMap with the same inmap value (there should be one (and only one):-) - //If so, switch the inmap between the instruments - for (int i=0; i<DRUM_MAPSIZE; i++) { - if (MusEGlobal::drumMap[i].enote == val && &MusEGlobal::drumMap[i] != dm) { - MusEGlobal::drumInmap[int(dm->enote)] = i; - MusEGlobal::drumMap[i].enote = dm->enote; - break; - } - } - //TODO: Set all the notes on the track with pitch=dm->enote to pitch=val + + if (old_style_drummap_mode) + { + //Check if there is any other drumMap with the same inmap value (there should be one (and only one):-) + //If so, switch the inmap between the instruments + for (int i=0; i<ourDrumMapSize; i++) { + if (ourDrumMap[i].enote == val && &ourDrumMap[i] != dm) { + MusEGlobal::drumInmap[int(dm->enote)] = i; + ourDrumMap[i].enote = dm->enote; + break; + } + } + //TODO: Set all the notes on the track with instrument=dm->enote to instrument=val + MusEGlobal::drumInmap[val] = instrument; + } dm->enote = val; - MusEGlobal::drumInmap[val] = pitch; break; - case COL_LEN: + case COL_NOTELENGTH: val = dm->len + incVal; if (val < 0) val = 0; dm->len = val; break; - case COL_ANOTE: + case COL_NOTE: + if (old_style_drummap_mode) //only allow changing in old style mode { val = dm->anote + incVal; if (val < 0) @@ -317,16 +391,16 @@ void DList::viewMousePressEvent(QMouseEvent* ev) if(val != dm->anote) { MusEGlobal::audio->msgIdle(true); - MusEGlobal::song->remapPortDrumCtrlEvents(pitch, val, -1, -1); + MusEGlobal::song->remapPortDrumCtrlEvents(instrument, val, -1, -1); MusEGlobal::audio->msgIdle(false); dm->anote = val; MusEGlobal::song->update(SC_DRUMMAP); } - - emit keyPressed(pitch, 100); } + + emit keyPressed(instrument, 100); break; - case COL_CHANNEL: + case COL_OUTCHANNEL: // this column isn't visible in new style drum mode val = dm->channel + incVal; if (val < 0) val = 0; @@ -338,8 +412,8 @@ void DList::viewMousePressEvent(QMouseEvent* ev) // Delete all port controller events. MusEGlobal::song->changeAllPortDrumCtrlEvents(false, true); - for (int i = 0; i < DRUM_MAPSIZE; i++) - MusEGlobal::drumMap[i].channel = val; + for (int i = 0; i < ourDrumMapSize; i++) + ourDrumMap[i].channel = val; // Add all port controller events. MusEGlobal::song->changeAllPortDrumCtrlEvents(true, true); MusEGlobal::audio->msgIdle(false); @@ -350,14 +424,14 @@ void DList::viewMousePressEvent(QMouseEvent* ev) if(val != dm->channel) { MusEGlobal::audio->msgIdle(true); - MusEGlobal::song->remapPortDrumCtrlEvents(pitch, -1, val, -1); + MusEGlobal::song->remapPortDrumCtrlEvents(instrument, -1, val, -1); MusEGlobal::audio->msgIdle(false); dm->channel = val; MusEGlobal::song->update(SC_DRUMMAP); } } break; - case COL_LV1: + case COL_LEVEL1: val = dm->lv1 + incVal; if (val < 0) val = 0; @@ -365,7 +439,7 @@ void DList::viewMousePressEvent(QMouseEvent* ev) val = 127; dm->lv1 = val; break; - case COL_LV2: + case COL_LEVEL2: val = dm->lv2 + incVal; if (val < 0) val = 0; @@ -373,7 +447,7 @@ void DList::viewMousePressEvent(QMouseEvent* ev) val = 127; dm->lv2 = val; break; - case COL_LV3: + case COL_LEVEL3: val = dm->lv3 + incVal; if (val < 0) val = 0; @@ -381,7 +455,7 @@ void DList::viewMousePressEvent(QMouseEvent* ev) val = 127; dm->lv3 = val; break; - case COL_LV4: + case COL_LEVEL4: val = dm->lv4 + incVal; if (val < 0) val = 0; @@ -390,17 +464,63 @@ void DList::viewMousePressEvent(QMouseEvent* ev) dm->lv4 = val; break; case COL_NAME: - { - int velo = 127 * (ev->x() - header->sectionPosition(COL_NAME)) / (header->sectionSize(COL_NAME) - 10); - if (velo < 0) velo = 0; - if (velo > 127 ) velo = 127; - emit keyPressed(pitch, velo); //Mapping done on other side, send index + if (button == Qt::LeftButton) + { + int velo = 127 * (ev->x() - header->sectionPosition(COL_NAME)) / (header->sectionSize(COL_NAME) - 10); + if (velo < 0) velo = 0; + if (velo > 127 ) velo = 127; + emit keyPressed(instrument, velo); //Mapping done on other side, send index + } + else if (button == Qt::MidButton) // hide that instrument + { + QSet<MusECore::Track*>* group = &dcanvas->get_instrument_map()[instrument].tracks; + int pitch = dcanvas->get_instrument_map()[instrument].pitch; + for (QSet<MusECore::Track*>::iterator track=group->begin(); track!=group->end(); track++) + dynamic_cast<MusECore::MidiTrack*>(*track)->drummap_hidden()[pitch] = true; + } + else if (button == Qt::RightButton) + { + bool hidden=false; + bool shown=false; + QSet<MusECore::Track*>* group = &dcanvas->get_instrument_map()[instrument].tracks; + int pitch = dcanvas->get_instrument_map()[instrument].pitch; + + for (QSet<MusECore::Track*>::iterator track=group->begin(); track!=group->end() && !(hidden&&shown); track++) + if (dynamic_cast<MusECore::MidiTrack*>(*track)->drummap_hidden()[pitch]) + hidden=true; + else + shown=true; + + QMenu* popup = new QMenu(NULL /* intendedly not "this" */); + QAction* hideAction = popup->addAction(tr("hide this instrument")); + QAction* showAction = popup->addAction(tr("show this instrument")); + showAction->setToolTip(tr("this turns a grayed out eye into a blue eye")); + + if (!hidden) + showAction->setEnabled(false); + if (!shown) + hideAction->setEnabled(false); + + QAction* result = popup->exec(ev->globalPos()); + if (result==hideAction) + for (QSet<MusECore::Track*>::iterator track=group->begin(); track!=group->end(); track++) + dynamic_cast<MusECore::MidiTrack*>(*track)->drummap_hidden()[pitch] = true; + else if (result==showAction) + for (QSet<MusECore::Track*>::iterator track=group->begin(); track!=group->end(); track++) + dynamic_cast<MusECore::MidiTrack*>(*track)->drummap_hidden()[pitch] = false; + + delete popup; + } break; - } default: break; } - redraw(); + + if (!old_style_drummap_mode && dm_old != *dm) //something changed and we're in new style mode? + dcanvas->propagate_drummap_change(dm-ourDrumMap); + + MusEGlobal::song->update(SC_DRUMMAP); + //redraw(); //this is done by the songChanged slot } //--------------------------------------------------------- @@ -411,18 +531,18 @@ void DList::viewMouseDoubleClickEvent(QMouseEvent* ev) { int x = ev->x(); int y = ev->y(); - unsigned pitch = y / TH; + unsigned instrument = y / TH; int section = header->logicalIndexAt(x); - if ((section == COL_NAME || section == COL_VOL || section == COL_LEN || section == COL_LV1 || - section == COL_LV2 || section == COL_LV3 || section == COL_LV4 || section == COL_CHANNEL || - section == COL_QNT) && (ev->button() == Qt::LeftButton)) + if ((section == COL_NAME || section == COL_VOLUME || section == COL_NOTELENGTH || section == COL_LEVEL1 || + section == COL_LEVEL2 || section == COL_LEVEL3 || section == COL_LEVEL4 || section == COL_QUANT || + (section == COL_OUTCHANNEL && old_style_drummap_mode) ) && (ev->button() == Qt::LeftButton)) { - lineEdit(pitch, section); + lineEdit(instrument, section); } - else if ((section == COL_ANOTE || section == COL_ENOTE) && (ev->button() == Qt::LeftButton)) - pitchEdit(pitch, section); + else if (((section == COL_NOTE && old_style_drummap_mode) || section == COL_INPUTTRIGGER) && (ev->button() == Qt::LeftButton)) + pitchEdit(instrument, section); else viewMousePressEvent(ev); } @@ -434,7 +554,7 @@ void DList::viewMouseDoubleClickEvent(QMouseEvent* ev) //--------------------------------------------------------- void DList::lineEdit(int line, int section) { - MusECore::DrumMap* dm = &MusEGlobal::drumMap[line]; + MusECore::DrumMap* dm = &ourDrumMap[line]; editEntry = dm; if (editor == 0) { editor = new DLineEdit(this); @@ -452,37 +572,37 @@ void DList::lineEdit(int line, int section) editor->setText(dm->name); break; - case COL_VOL: { + case COL_VOLUME: { editor->setText(QString::number(dm->vol)); break; } - case COL_LEN: { + case COL_NOTELENGTH: { editor->setText(QString::number(dm->len)); break; } - case COL_LV1: + case COL_LEVEL1: editor->setText(QString::number(dm->lv1)); break; - case COL_LV2: + case COL_LEVEL2: editor->setText(QString::number(dm->lv2)); break; - case COL_LV3: + case COL_LEVEL3: editor->setText(QString::number(dm->lv3)); break; - case COL_LV4: + case COL_LEVEL4: editor->setText(QString::number(dm->lv4)); break; - case COL_QNT: + case COL_QUANT: editor->setText(QString::number(dm->quant)); break; - case COL_CHANNEL: + case COL_OUTCHANNEL: editor->setText(QString::number(dm->channel+1)); break; } @@ -502,7 +622,7 @@ void DList::lineEdit(int line, int section) //--------------------------------------------------------- void DList::pitchEdit(int line, int section) { - MusECore::DrumMap* dm = &MusEGlobal::drumMap[line]; + MusECore::DrumMap* dm = &ourDrumMap[line]; editEntry = dm; if (pitch_editor == 0) { pitch_editor = new DPitchEdit(this); @@ -516,11 +636,11 @@ void DList::pitchEdit(int line, int section) int colh = rmapy(TH); selectedColumn = section; //Store selected column to have an idea of which one was selected when return is pressed switch (section) { - case COL_ENOTE: + case COL_INPUTTRIGGER: pitch_editor->setValue(dm->enote); break; - case COL_ANOTE: + case COL_NOTE: pitch_editor->setValue(dm->anote); break; } @@ -556,11 +676,11 @@ int DList::x2col(int x) const void DList::setCurDrumInstrument(int instr) { - if (instr < 0 || instr >= DRUM_MAPSIZE -1) + if (instr < 0 || instr >= ourDrumMapSize -1) return; // illegal instrument - MusECore::DrumMap* dm = &MusEGlobal::drumMap[instr]; + MusECore::DrumMap* dm = &ourDrumMap[instr]; if (currentlySelected != dm) { - currentlySelected = &MusEGlobal::drumMap[instr]; + currentlySelected = dm; emit curDrumInstrumentChanged(instr); MusEGlobal::song->update(SC_DRUMMAP); } @@ -581,32 +701,37 @@ void DList::sizeChange(int, int, int) void DList::returnPressed() { + if (editEntry==NULL) + { + printf("THIS SHOULD NEVER HAPPEN: editEntry is NULL in DList::returnPressed()!\n"); + return; + } + int val = -1; if (selectedColumn != COL_NAME) { - ///val = atoi(editor->text().ascii()); val = atoi(editor->text().toAscii().constData()); switch (selectedColumn) { - case COL_VOL: - if (val > 200) //Check bounds for volume - val = 200; + case COL_VOLUME: + if (val > 999) //changed from 200 to 999 by flo93 + val = 999; if (val < 0) val = 0; break; - case COL_LV1: - case COL_LV2: - case COL_LV3: - case COL_LV4: + case COL_LEVEL1: + case COL_LEVEL2: + case COL_LEVEL3: + case COL_LEVEL4: if (val > 127) //Check bounds for lv1-lv4 values val = 127; if (val < 0) val = 0; break; - case COL_CHANNEL: + case COL_OUTCHANNEL: val--; if (val >= 16) val = 15; @@ -617,42 +742,42 @@ void DList::returnPressed() default: break; } } - + + MusECore::DrumMap editEntryOld = *editEntry; switch(selectedColumn) { case COL_NAME: editEntry->name = editor->text(); break; - case COL_LEN: - ///editEntry->len = atoi(editor->text().ascii()); + case COL_NOTELENGTH: editEntry->len = atoi(editor->text().toAscii().constData()); break; - case COL_VOL: + case COL_VOLUME: editEntry->vol = val; break; - case COL_LV1: + case COL_LEVEL1: editEntry->lv1 = val; break; - case COL_LV2: + case COL_LEVEL2: editEntry->lv2 = val; break; - case COL_LV3: + case COL_LEVEL3: editEntry->lv3 = val; break; - case COL_LV4: + case COL_LEVEL4: editEntry->lv4 = val; break; - case COL_QNT: + case COL_QUANT: editEntry->quant = val; break; - case COL_CHANNEL: + case COL_OUTCHANNEL: editEntry->channel = val; break; @@ -660,11 +785,16 @@ void DList::returnPressed() printf("Return pressed in unknown column\n"); break; } + + if (editEntryOld != *editEntry) + dcanvas->propagate_drummap_change(editEntry-ourDrumMap); + selectedColumn = -1; editor->hide(); editEntry = 0; setFocus(); - redraw(); + MusEGlobal::song->update(SC_DRUMMAP); + //redraw(); //this is done by the songChanged slot } //--------------------------------------------------------- @@ -673,44 +803,65 @@ void DList::returnPressed() void DList::pitchEdited() { + if (editEntry==NULL) + { + printf("THIS SHOULD NEVER HAPPEN: editEntry is NULL in DList::pitchEdited()!\n"); + return; + } + int val=pitch_editor->value(); - int pitch=(editEntry-MusEGlobal::drumMap); + int instrument=(editEntry-ourDrumMap); + MusECore::DrumMap editEntryOld=*editEntry; switch(selectedColumn) { - case COL_ANOTE: + case COL_NOTE: + if (old_style_drummap_mode) //should actually be always true, but to be sure... + { if(val != editEntry->anote) { MusEGlobal::audio->msgIdle(true); - MusEGlobal::song->remapPortDrumCtrlEvents(pitch, val, -1, -1); + MusEGlobal::song->remapPortDrumCtrlEvents(instrument, val, -1, -1); MusEGlobal::audio->msgIdle(false); editEntry->anote = val; MusEGlobal::song->update(SC_DRUMMAP); } - break; - - case COL_ENOTE: + } + else + printf("ERROR: THIS SHOULD NEVER HAPPEN: pitch edited of anote in new style mode!\n"); + break; + + case COL_INPUTTRIGGER: + if (old_style_drummap_mode) + { //Check if there is any other MusEGlobal::drumMap with the same inmap value (there should be one (and only one):-) //If so, switch the inmap between the instruments - for (int i=0; i<DRUM_MAPSIZE; i++) { - if (MusEGlobal::drumMap[i].enote == val && &MusEGlobal::drumMap[i] != editEntry) { + for (int i=0; i<ourDrumMapSize; i++) { + if (ourDrumMap[i].enote == val && &ourDrumMap[i] != editEntry) { MusEGlobal::drumInmap[int(editEntry->enote)] = i; - MusEGlobal::drumMap[i].enote = editEntry->enote; + ourDrumMap[i].enote = editEntry->enote; break; } } - //TODO: Set all the notes on the track with pitch=dm->enote to pitch=val - editEntry->enote = val; - MusEGlobal::drumInmap[val] = pitch; - break; + //TODO: Set all the notes on the track with instrument=dm->enote to instrument=val + MusEGlobal::drumInmap[val] = instrument; + } + editEntry->enote = val; + break; + default: - printf("Value changed in unknown column\n"); + printf("ERROR: THIS SHOULD NEVER HAPPEN: Value changed in unknown column\n"); break; } + + if (editEntryOld != *editEntry) + dcanvas->propagate_drummap_change(editEntry-ourDrumMap); + selectedColumn = -1; pitch_editor->hide(); editEntry = 0; setFocus(); - redraw(); + MusEGlobal::song->update(SC_DRUMMAP); + //redraw(); //this is done by the songChanged slot } //--------------------------------------------------------- @@ -745,14 +896,20 @@ void DList::songChanged(int flags) // DList //--------------------------------------------------------- -DList::DList(QHeaderView* h, QWidget* parent, int ymag) +DList::DList(QHeaderView* h, QWidget* parent, int ymag, DrumCanvas* dcanvas_, bool oldstyle) : MusEGui::View(parent, 1, ymag) { setBg(Qt::white); + + dcanvas=dcanvas_; + ourDrumMap=dcanvas->getOurDrumMap(); + ourDrumMapSize=dcanvas->getOurDrumMapSize(); + old_style_drummap_mode=oldstyle; + connect(dcanvas, SIGNAL(ourDrumMapChanged(bool)), SLOT(ourDrumMapChanged(bool))); + if (!h){ h = new QHeaderView(Qt::Horizontal, parent);} header = h; - scroll = 0; //ORCAN- CHECK if really needed: header->setTracking(true); connect(header, SIGNAL(sectionResized(int,int,int)), SLOT(sizeChange(int,int,int))); @@ -763,7 +920,7 @@ DList::DList(QHeaderView* h, QWidget* parent, int ymag) pitch_editor = 0; editEntry = 0; // always select a drum instrument - currentlySelected = &MusEGlobal::drumMap[0]; + currentlySelected = &ourDrumMap[0]; selectedColumn = -1; } @@ -809,11 +966,21 @@ void DList::viewMouseReleaseEvent(QMouseEvent* ev) { if (drag == DRAG) { int y = ev->y(); - unsigned dPitch = y / TH; + int dInstrument; + if (old_style_drummap_mode) + dInstrument = y / TH; + else + dInstrument = (y+TH/2) / TH; + + if (dInstrument < 0) dInstrument=0; + if (dInstrument >= ourDrumMapSize) dInstrument=ourDrumMapSize-1; + + int cur_sel = (!old_style_drummap_mode && dInstrument>sInstrument) ? dInstrument-1 : dInstrument; + setCursor(QCursor(Qt::ArrowCursor)); - currentlySelected = &MusEGlobal::drumMap[int(dPitch)]; - emit curDrumInstrumentChanged(dPitch); - emit mapChanged(sPitch, dPitch); //Track pitch change done in canvas + currentlySelected = &ourDrumMap[cur_sel]; + emit curDrumInstrumentChanged((unsigned)cur_sel); + emit mapChanged(sInstrument, (unsigned)dInstrument); //Track instrument change done in canvas } drag = NORMAL; //?? redraw(); //commented out NOT by flo93; was already commented out @@ -822,16 +989,16 @@ void DList::viewMouseReleaseEvent(QMouseEvent* ev) int x = ev->x(); int y = ev->y(); bool shift = ev->modifiers() & Qt::ShiftModifier; - unsigned pitch = y / TH; + unsigned instrument = y / TH; - DCols col = DCols(x2col(x)); + DrumColumn col = DrumColumn(x2col(x)); switch (col) { case COL_NAME: - emit keyReleased(pitch, shift); + emit keyReleased(instrument, shift); break; - case COL_ANOTE: - emit keyReleased(pitch, shift); + case COL_NOTE: + emit keyReleased(instrument, shift); break; default: break; @@ -849,4 +1016,21 @@ int DList::getSelectedInstrument() return MusEGlobal::drumInmap[int(currentlySelected->enote)]; } + +void DList::ourDrumMapChanged(bool instrMapChanged) +{ + int selIdx = currentlySelected - ourDrumMap; + + ourDrumMap=dcanvas->getOurDrumMap(); + ourDrumMapSize=dcanvas->getOurDrumMapSize(); + + if (instrMapChanged) + editEntry=NULL; + + if (selIdx >= ourDrumMapSize) selIdx=ourDrumMapSize-1; + currentlySelected = &ourDrumMap[selIdx]; + + redraw(); +} + } // namespace MusEGui diff --git a/muse2/muse/midiedit/dlist.h b/muse2/muse/midiedit/dlist.h index 99e9460f..35a67023 100644 --- a/muse2/muse/midiedit/dlist.h +++ b/muse2/muse/midiedit/dlist.h @@ -35,6 +35,8 @@ class QHeaderView; class QLineEdit; class QMouseEvent; class QPainter; +class Device; +class QLineEdit; namespace MusECore { class DrumMap; @@ -43,6 +45,7 @@ class DrumMap; namespace MusEGui { class ScrollScale; +class DrumCanvas; //--------------------------------------------------------- // DLineEdit @@ -89,9 +92,13 @@ class DPitchEdit: public Awl::PitchEdit class DList : public View { Q_OBJECT - + + MusEGui::DrumCanvas* dcanvas; + MusECore::DrumMap* ourDrumMap; + int ourDrumMapSize; + bool old_style_drummap_mode; + QHeaderView* header; - ScrollScale* scroll; QLineEdit* editor; DPitchEdit* pitch_editor; MusECore::DrumMap* editEntry; @@ -101,7 +108,7 @@ class DList : public View { int startY; int curY; - int sPitch; + int sInstrument; enum { NORMAL, START_DRAG, DRAG } drag; virtual void draw(QPainter& p, const QRect&); @@ -131,18 +138,16 @@ class DList : public View { public slots: void tracklistChanged(); void songChanged(int); + void ourDrumMapChanged(bool); + public: void lineEdit(int line, int section); void pitchEdit(int line, int section); void setCurDrumInstrument(int n); - DList(QHeaderView*, QWidget* parent, int ymag); + DList(QHeaderView*, QWidget* parent, int ymag, MusEGui::DrumCanvas* dcanvas, bool oldstyle); ~DList(); - void setScroll(ScrollScale* s) { scroll = s; } int getSelectedInstrument(); -enum DCols { COL_MUTE=0, COL_NAME, COL_VOL, COL_QNT, COL_ENOTE, COL_LEN, - COL_ANOTE, COL_CHANNEL, COL_PORT, - COL_LV1, COL_LV2, COL_LV3, COL_LV4, COL_NONE=-1}; }; } // namespace MusEGui diff --git a/muse2/muse/midiedit/drumedit.cpp b/muse2/muse/midiedit/drumedit.cpp index 4a234481..3a75e32d 100644 --- a/muse2/muse/midiedit/drumedit.cpp +++ b/muse2/muse/midiedit/drumedit.cpp @@ -82,27 +82,12 @@ static const char* map_file_save_pattern[] = { int DrumEdit::_rasterInit = 96; int DrumEdit::_dlistWidthInit = 50; int DrumEdit::_dcanvasWidthInit = 300; +bool DrumEdit::_ignore_hide_init = false; static const int xscale = -10; static const int yscale = 1; static const int drumeditTools = MusEGui::PointerTool | MusEGui::PencilTool | MusEGui::RubberTool | MusEGui::CursorTool | MusEGui::DrawTool; -enum DrumColumn { - COL_MUTE = 0, - COL_NAME, - COL_VOLUME, - COL_QUANT, - COL_INPUTTRIGGER, - COL_NOTELENGTH, - COL_NOTE, - COL_OUTCHANNEL, - COL_OUTPORT, - COL_LEVEL1, - COL_LEVEL2, - COL_LEVEL3, - COL_LEVEL4, - COL_NONE = -1 -}; //--------------------------------------------------------- // setHeaderWhatsThis @@ -110,6 +95,7 @@ enum DrumColumn { void DrumEdit::setHeaderWhatsThis() { + header->setWhatsThis(COL_HIDE, tr("hide instrument")); header->setWhatsThis(COL_MUTE, tr("mute instrument")); header->setWhatsThis(COL_NAME, tr("sound name")); header->setWhatsThis(COL_VOLUME, tr("volume percent")); @@ -131,6 +117,7 @@ void DrumEdit::setHeaderWhatsThis() void DrumEdit::setHeaderToolTips() { + header->setToolTip(COL_HIDE, tr("hide instrument")); header->setToolTip(COL_MUTE, tr("mute instrument")); header->setToolTip(COL_NAME, tr("sound name")); header->setToolTip(COL_VOLUME, tr("volume percent")); @@ -179,6 +166,9 @@ DrumEdit::DrumEdit(MusECore::PartList* pl, QWidget* parent, const char* name, un selPart = 0; QSignalMapper *signalMapper = new QSignalMapper(this); + _group_mode = GROUP_SAME_CHANNEL; + _ignore_hide = _ignore_hide_init; + //---------Pulldown Menu---------------------------- menuFile = menuBar()->addMenu(tr("&File")); @@ -255,8 +245,14 @@ DrumEdit::DrumEdit(MusECore::PartList* pl, QWidget* parent, const char* name, un menuFunctions->setTearOffEnabled(true); - QAction* reorderListAction = menuFunctions->addAction(tr("Re-order list")); - menuFunctions->addSeparator(); + if (old_style_drummap_mode()) + { + QAction* reorderListAction = menuFunctions->addAction(tr("Re-order list")); + connect(reorderListAction, SIGNAL(triggered()), signalMapper, SLOT(map())); + signalMapper->setMapping(reorderListAction, DrumCanvas::CMD_REORDER_LIST); + menuFunctions->addSeparator(); + } + fixedAction = menuFunctions->addAction(tr("Set Fixed Length")); veloAction = menuFunctions->addAction(tr("Modify Velocity")); crescAction = menuFunctions->addAction(tr("Crescendo/Decrescendo")); @@ -265,7 +261,6 @@ DrumEdit::DrumEdit(MusECore::PartList* pl, QWidget* parent, const char* name, un QAction* noteShiftAction = menuFunctions->addAction(tr("Move Notes")); QAction* delOverlapsAction = menuFunctions->addAction(tr("Delete Overlaps")); - connect(reorderListAction, SIGNAL(triggered()), signalMapper, SLOT(map())); connect(fixedAction, SIGNAL(triggered()), signalMapper, SLOT(map())); connect(veloAction, SIGNAL(triggered()), signalMapper, SLOT(map())); connect(crescAction, SIGNAL(triggered()), signalMapper, SLOT(map())); @@ -274,7 +269,6 @@ DrumEdit::DrumEdit(MusECore::PartList* pl, QWidget* parent, const char* name, un connect(noteShiftAction, SIGNAL(triggered()), signalMapper, SLOT(map())); connect(delOverlapsAction, SIGNAL(triggered()), signalMapper, SLOT(map())); - signalMapper->setMapping(reorderListAction, DrumCanvas::CMD_REORDER_LIST); signalMapper->setMapping(fixedAction, DrumCanvas::CMD_FIXED_LEN); signalMapper->setMapping(veloAction, DrumCanvas::CMD_MODIFY_VELOCITY); signalMapper->setMapping(crescAction, DrumCanvas::CMD_CRESCENDO); @@ -283,10 +277,44 @@ DrumEdit::DrumEdit(MusECore::PartList* pl, QWidget* parent, const char* name, un signalMapper->setMapping(noteShiftAction, DrumCanvas::CMD_NOTE_SHIFT); signalMapper->setMapping(delOverlapsAction, DrumCanvas::CMD_DELETE_OVERLAPS); + + QMenu* menuScriptPlugins = menuBar()->addMenu(tr("&Plugins")); MusEGlobal::song->populateScriptMenu(menuScriptPlugins, this); QMenu* settingsMenu = menuBar()->addMenu(tr("Window &Config")); + if (!old_style_drummap_mode()) + { + QMenu* menuGrouping=settingsMenu->addMenu(tr("Group")); + groupNoneAction = menuGrouping->addAction(tr("Don't group")); + groupChanAction = menuGrouping->addAction(tr("Group by channel")); + groupMaxAction = menuGrouping->addAction(tr("Group maximally")); + QAction* ignoreHideAction = settingsMenu->addAction(tr("Also show hidden events")); + settingsMenu->addSeparator(); + + groupNoneAction->setCheckable(true); + groupChanAction->setCheckable(true); + groupMaxAction ->setCheckable(true); + ignoreHideAction->setCheckable(true); + ignoreHideAction->setChecked(_ignore_hide); + + connect(groupNoneAction, SIGNAL(triggered()), signalMapper, SLOT(map())); + connect(groupChanAction, SIGNAL(triggered()), signalMapper, SLOT(map())); + connect(groupMaxAction, SIGNAL(triggered()), signalMapper, SLOT(map())); + connect(ignoreHideAction, SIGNAL(toggled(bool)), SLOT(set_ignore_hide(bool))); + + signalMapper->setMapping(groupNoneAction, DrumCanvas::CMD_GROUP_NONE); + signalMapper->setMapping(groupChanAction, DrumCanvas::CMD_GROUP_CHAN); + signalMapper->setMapping(groupMaxAction, DrumCanvas::CMD_GROUP_MAX); + + updateGroupingActions(); + } + else + { + groupNoneAction=NULL; + groupChanAction=NULL; + groupMaxAction =NULL; + } settingsMenu->addAction(subwinAction); settingsMenu->addAction(shareAction); settingsMenu->addAction(fullscreenAction); @@ -408,7 +436,7 @@ DrumEdit::DrumEdit(MusECore::PartList* pl, QWidget* parent, const char* name, un gridS2->setSpacing(0); time = new MusEGui::MTScale(&_raster, split1w2, xscale); canvas = new DrumCanvas(this, split1w2, xscale, yscale); - vscroll = new MusEGui::ScrollScale(-4, 1, yscale, DRUM_MAPSIZE*TH, Qt::Vertical, split1w2); + vscroll = new MusEGui::ScrollScale(-4, 1, yscale, dynamic_cast<DrumCanvas*>(canvas)->getOurDrumMapSize()*TH, Qt::Vertical, split1w2); int offset = -(MusEGlobal::config.division/4); canvas->setOrigin(offset, 0); canvas->setCanvasTools(drumeditTools); @@ -416,6 +444,7 @@ DrumEdit::DrumEdit(MusECore::PartList* pl, QWidget* parent, const char* name, un connect(canvas, SIGNAL(toolChanged(int)), tools2, SLOT(set(int))); connect(canvas, SIGNAL(horizontalZoomIn()), SLOT(horizontalZoomIn())); connect(canvas, SIGNAL(horizontalZoomOut()), SLOT(horizontalZoomOut())); + connect(canvas, SIGNAL(ourDrumMapChanged(bool)), SLOT(ourDrumMapChanged(bool))); time->setOrigin(offset, 0); QList<int> mops; @@ -439,6 +468,7 @@ DrumEdit::DrumEdit(MusECore::PartList* pl, QWidget* parent, const char* name, un // header = new MusEGui::Header(split1w1, "header"); header->setFixedHeight(31); + header->setColumnLabel(tr("H"), COL_HIDE, 20); header->setColumnLabel(tr("M"), COL_MUTE, 20); header->setColumnLabel(tr("Sound"), COL_NAME, 120); header->setColumnLabel(tr("Vol"), COL_VOLUME); @@ -456,7 +486,18 @@ DrumEdit::DrumEdit(MusECore::PartList* pl, QWidget* parent, const char* name, un setHeaderToolTips(); setHeaderWhatsThis(); - dlist = new DList(header, split1w1, yscale); + if (!old_style_drummap_mode()) + { + header->hideSection(COL_OUTPORT); + header->hideSection(COL_OUTCHANNEL); + } + + if (!old_style_drummap_mode() && _ignore_hide) + header->showSection(COL_HIDE); + else + header->hideSection(COL_HIDE); + + dlist = new DList(header, split1w1, yscale, (DrumCanvas*)canvas, old_style_drummap_mode()); // p3.3.44 setCurDrumInstrument(dlist->getSelectedInstrument()); @@ -546,8 +587,12 @@ void DrumEdit::songChanged1(int bits) toolbar->setSolo(canvas->track()->solo()); return; } + if ( !old_style_drummap_mode() && + ( bits & (SC_DRUMMAP | SC_TRACK_INSERTED | SC_TRACK_REMOVED | SC_TRACK_MODIFIED | + SC_PART_INSERTED | SC_PART_REMOVED | SC_PART_MODIFIED) ) ) + ((DrumCanvas*)(canvas))->rebuildOurDrumMap(); + songChanged(bits); - } //--------------------------------------------------------- @@ -704,6 +749,7 @@ void DrumEdit::writeStatus(int level, MusECore::Xml& xml) const xml.intTag(level, "xmag", hscroll->mag()); xml.intTag(level, "ypos", vscroll->pos()); xml.intTag(level, "ymag", vscroll->mag()); + xml.intTag(level, "ignore_hide", _ignore_hide); xml.tag(level, "/drumedit"); } @@ -751,6 +797,8 @@ void DrumEdit::readStatus(MusECore::Xml& xml) vscroll->setMag(xml.parseInt()); else if (tag == "ypos") vscroll->setPos(xml.parseInt()); + else if (tag == "ignore_hide") + _ignore_hide=xml.parseInt(); else xml.unknown("DrumEdit"); break; @@ -787,6 +835,8 @@ void DrumEdit::readConfiguration(MusECore::Xml& xml) _dcanvasWidthInit = xml.parseInt(); else if (tag == "dlistwidth") _dlistWidthInit = xml.parseInt(); + else if (tag == "ignore_hide_init") + _ignore_hide_init = xml.parseInt(); else if (tag == "topwin") TopWin::readConfiguration(DRUM, xml); else @@ -812,6 +862,7 @@ void DrumEdit::writeConfiguration(int level, MusECore::Xml& xml) xml.intTag(level, "raster", _rasterInit); xml.intTag(level, "dlistwidth", _dlistWidthInit); xml.intTag(level, "dcanvaswidth", _dcanvasWidthInit); + xml.intTag(level, "ignore_hide_init", _ignore_hide_init); TopWin::writeConfiguration(DRUM, level,xml); xml.tag(level, "/drumedit"); } @@ -953,7 +1004,11 @@ void DrumEdit::cmd(int cmd) case DrumCanvas::CMD_REORDER_LIST: ((DrumCanvas*)(canvas))->moveAwayUnused(); break; //case DrumCanvas::CMD_FIXED_LEN: // this must be handled by the drum canvas, due to its // special nature (each drum has its own length) - + + case DrumCanvas::CMD_GROUP_NONE: _group_mode=DONT_GROUP; updateGroupingActions(); ((DrumCanvas*)(canvas))->rebuildOurDrumMap(); break; + case DrumCanvas::CMD_GROUP_CHAN: _group_mode=GROUP_SAME_CHANNEL; updateGroupingActions(); ((DrumCanvas*)(canvas))->rebuildOurDrumMap(); break; + case DrumCanvas::CMD_GROUP_MAX: _group_mode=GROUP_MAX; updateGroupingActions(); ((DrumCanvas*)(canvas))->rebuildOurDrumMap(); break; + default: ((DrumCanvas*)(canvas))->cmd(cmd); } } @@ -1128,7 +1183,7 @@ void DrumEdit::keyPressEvent(QKeyEvent* event) return; } else if (key == Qt::Key_F2) { - dlist->lineEdit(dlist->getSelectedInstrument(),(int)DList::COL_NAME); + dlist->lineEdit(dlist->getSelectedInstrument(),(int)COL_NAME); return; } else if (key == shortcuts[SHRT_INSTRUMENT_STEP_UP].key) { @@ -1325,4 +1380,51 @@ void DrumEdit::setStep(QString v) canvas->setFocus(); } +bool DrumEdit::old_style_drummap_mode() +{ + for (MusECore::ciPart p = parts()->begin(); p != parts()->end(); ++p) + if (p->second->track()->type()==MusECore::Track::DRUM) + return true; + + return false; +} + +void DrumEdit::ourDrumMapChanged(bool instrMapChanged) +{ + if (instrMapChanged) + { + int vmin,vmax; + vscroll->range(&vmin, &vmax); + vscroll->setRange(vmin, dynamic_cast<DrumCanvas*>(canvas)->getOurDrumMapSize()*TH); + } +} + +void DrumEdit::updateGroupingActions() +{ + if (groupNoneAction==NULL || groupChanAction==NULL || groupMaxAction==NULL) + { + printf("THIS SHOULD NEVER HAPPEN: DrumEdit::updateGroupingActions() called, but one of the actions is NULL!\n"); + return; + } + + groupNoneAction->setChecked(_group_mode==DONT_GROUP); + groupChanAction->setChecked(_group_mode==GROUP_SAME_CHANNEL); + groupMaxAction ->setChecked(_group_mode==GROUP_MAX); +} + +void DrumEdit::set_ignore_hide(bool val) +{ + _ignore_hide=val; + _ignore_hide_init=val; + // this may only called be from the action's toggled signal. + // if called otherwise, the action's checked state isn't updated! + + if (!old_style_drummap_mode() && _ignore_hide) + header->showSection(COL_HIDE); + else + header->hideSection(COL_HIDE); + + ((DrumCanvas*)(canvas))->rebuildOurDrumMap(); +} + } // namespace MusEGui diff --git a/muse2/muse/midiedit/drumedit.h b/muse2/muse/midiedit/drumedit.h index 1ca6f989..5603e449 100644 --- a/muse2/muse/midiedit/drumedit.h +++ b/muse2/muse/midiedit/drumedit.h @@ -64,6 +64,23 @@ class ScrollScale; class Splitter; class Toolbar1; +enum DrumColumn { + COL_HIDE = 0, + COL_MUTE, + COL_NAME, + COL_VOLUME, + COL_QUANT, + COL_INPUTTRIGGER, + COL_NOTELENGTH, + COL_NOTE, + COL_OUTCHANNEL, + COL_OUTPORT, + COL_LEVEL1, + COL_LEVEL2, + COL_LEVEL3, + COL_LEVEL4, + COL_NONE = -1 +}; //--------------------------------------------------------- // DrumEdit @@ -71,7 +88,14 @@ class Toolbar1; class DrumEdit : public MidiEditor { Q_OBJECT - + + public: + enum group_mode_t { DONT_GROUP, GROUP_SAME_CHANNEL, GROUP_MAX }; + + private: + group_mode_t _group_mode; + bool _ignore_hide; + MusECore::Event selEvent; MusECore::MidiPart* selPart; int selTick; @@ -93,13 +117,14 @@ class DrumEdit : public MidiEditor { static int _rasterInit; static int _dlistWidthInit, _dcanvasWidthInit; + static bool _ignore_hide_init; QAction *loadAction, *saveAction, *resetAction; QAction *cutAction, *copyAction, *copyRangeAction, *pasteAction, *pasteDialogAction, *deleteAction; QAction *fixedAction, *veloAction, *crescAction, *quantizeAction; QAction *sallAction, *snoneAction, *invAction, *inAction , *outAction; QAction *prevAction, *nextAction; - + QAction *groupNoneAction, *groupChanAction, *groupMaxAction; void initShortcuts(); @@ -127,6 +152,8 @@ class DrumEdit : public MidiEditor { void configChanged(); void songChanged1(int); void setStep(QString); + void updateGroupingActions(); + void set_ignore_hide(bool); public slots: void setSelection(int, MusECore::Event&, MusECore::Part*); @@ -134,8 +161,9 @@ class DrumEdit : public MidiEditor { void execDeliveredScript(int); void execUserScript(int); CtrlEdit* addCtrl(); - + void ourDrumMapChanged(bool); virtual void updateHScrollRange(); + signals: void deleted(MusEGui::TopWin*); @@ -146,6 +174,10 @@ class DrumEdit : public MidiEditor { virtual void writeStatus(int, MusECore::Xml&) const; static void readConfiguration(MusECore::Xml& xml); static void writeConfiguration(int, MusECore::Xml&); + + bool old_style_drummap_mode(); + group_mode_t group_mode() { return _group_mode; } + bool ignore_hide() { return _ignore_hide; } }; } // namespace MusEGui diff --git a/muse2/muse/midiedit/drummap.cpp b/muse2/muse/midiedit/drummap.cpp index aa7ce759..43e66345 100644 --- a/muse2/muse/midiedit/drummap.cpp +++ b/muse2/muse/midiedit/drummap.cpp @@ -26,10 +26,13 @@ #include "xml.h" #include "song.h" +#include <QSet> + namespace MusEGlobal { char drumOutmap[DRUM_MAPSIZE]; char drumInmap[128]; MusECore::DrumMap drumMap[DRUM_MAPSIZE]; +global_drum_ordering_t global_drum_ordering; } namespace MusECore { @@ -520,3 +523,137 @@ void readDrumMap(Xml& xml, bool external) } } // namespace MusECore + + +namespace MusEGlobal { + +void global_drum_ordering_t::cleanup() +{ + using MusEGlobal::song; + using MusECore::MidiTrack; + using MusECore::ciTrack; + + QSet<MidiTrack*> tracks; + for (ciTrack it = song->tracks()->begin(); it != song->tracks()->end(); it++) + tracks.insert( dynamic_cast<MidiTrack*>(*it) ); + + for (iterator it = begin(); it != end();) + { + if (!tracks.contains(it->first)) + it=erase(it); + else + it++; + } +} + +void global_drum_ordering_t::write(int level, MusECore::Xml& xml) +{ + cleanup(); + + xml.tag(level++, "drum_ordering"); + + for (iterator it = begin(); it != end(); it++) + write_single(level, xml, *it); + + xml.etag(level, "drum_ordering"); +} + +void global_drum_ordering_t::write_single(int level, MusECore::Xml& xml, const entry_t& entry) +{ + xml.tag(level++, "entry"); + xml.strTag(level, "track", entry.first->name()); + xml.intTag(level, "instrument", entry.second); + xml.etag(level, "entry"); +} + +void global_drum_ordering_t::read(MusECore::Xml& xml) +{ + using MusECore::Xml; + + clear(); + + for (;;) + { + Xml::Token token = xml.parse(); + if (token == Xml::Error || token == Xml::End) + break; + + const QString& tag = xml.s1(); + switch (token) + { + case Xml::TagStart: + if (tag == "entry") + append(read_single(xml)); + else + xml.unknown("global_drum_ordering_t"); + break; + + case Xml::TagEnd: + if (tag == "drum_ordering") + return; + + default: + break; + } + } +} + +global_drum_ordering_t::entry_t global_drum_ordering_t::read_single(MusECore::Xml& xml) +{ + using MusECore::Xml; + using MusEGlobal::song; + using MusECore::ciTrack; + + entry_t entry; + entry.first=NULL; + entry.second=-1; + + for (;;) + { + Xml::Token token = xml.parse(); + if (token == Xml::Error || token == Xml::End) + break; + + const QString& tag = xml.s1(); + switch (token) + { + case Xml::TagStart: + if (tag == "track") + { + QString track_name=xml.parse1(); + + ciTrack it; + for (it = song->tracks()->begin(); it != song->tracks()->end(); it++) + if (track_name == (*it)->name()) + break; + + if (it != song->tracks()->end()) + entry.first=dynamic_cast<MusECore::MidiTrack*>(*it); + } + else if (tag == "instrument") + entry.second=xml.parseInt(); + else + xml.unknown("global_drum_ordering_t (single entry)"); + break; + + case Xml::TagEnd: + if (tag == "entry") + goto end_of_read_single; + + default: + break; + } + } + + end_of_read_single: + + if (entry.first == NULL) + printf("ERROR: global_drum_ordering_t::read_single() couldn't find the specified track!\n"); + + if (entry.second < 0 || entry.second > 127) + printf("ERROR: global_drum_ordering_t::read_single(): instrument number is out of bounds (%i)!\n", entry.second); + + return entry; +} + +} // namespace MusEGlobal diff --git a/muse2/muse/midiedit/drummap.h b/muse2/muse/midiedit/drummap.h index 60a25fad..f3186afa 100644 --- a/muse2/muse/midiedit/drummap.h +++ b/muse2/muse/midiedit/drummap.h @@ -24,7 +24,8 @@ #ifndef __DRUMMAP_H__ #define __DRUMMAP_H__ -class QString; +#include <QString> +#include <QList> namespace MusECore { @@ -46,23 +47,43 @@ struct DrumMap { bool mute; // bool selected; - //bool const operator==(const DrumMap& map) const; bool operator==(const DrumMap& map) const; + bool operator!=(const DrumMap& map) const { return !operator==(map); } }; #define DRUM_MAPSIZE 128 +extern const DrumMap idrumMap[DRUM_MAPSIZE]; //FINDMICH dummy! extern void initDrumMap(); extern void writeDrumMap(int level, Xml& xml, bool external); extern void readDrumMap(Xml& xml, bool external); extern void resetGMDrumMap(); +class MidiTrack; } // namespace MusECore namespace MusEGlobal { extern char drumOutmap[DRUM_MAPSIZE]; extern char drumInmap[DRUM_MAPSIZE]; extern MusECore::DrumMap drumMap[DRUM_MAPSIZE]; + + +class global_drum_ordering_t : public QList< std::pair<MusECore::MidiTrack*,int> > +{ + public: + void cleanup(); + void write(int level, MusECore::Xml& xml); + void read(MusECore::Xml& xml); + + private: + typedef std::pair<MusECore::MidiTrack*,int> entry_t; + + void write_single(int level, MusECore::Xml& xml, const entry_t& entry); + entry_t read_single(MusECore::Xml& xml); +}; + +extern global_drum_ordering_t global_drum_ordering; + } #endif diff --git a/muse2/muse/midiedit/prcanvas.cpp b/muse2/muse/midiedit/prcanvas.cpp index a70c4a91..9acaf186 100644 --- a/muse2/muse/midiedit/prcanvas.cpp +++ b/muse2/muse/midiedit/prcanvas.cpp @@ -112,6 +112,10 @@ PianoCanvas::PianoCanvas(MidiEditor* pr, QWidget* parent, int sx, int sy) connect(MusEGlobal::song, SIGNAL(midiNote(int, int)), SLOT(midiNote(int,int))); } +PianoCanvas::~PianoCanvas() +{ + delete steprec; +} //--------------------------------------------------------- // pitch2y //--------------------------------------------------------- diff --git a/muse2/muse/midiedit/prcanvas.h b/muse2/muse/midiedit/prcanvas.h index 13effc19..18d4f130 100644 --- a/muse2/muse/midiedit/prcanvas.h +++ b/muse2/muse/midiedit/prcanvas.h @@ -120,6 +120,7 @@ class PianoCanvas : public EventCanvas { }; PianoCanvas(MidiEditor*, QWidget*, int, int); + virtual ~PianoCanvas(); void cmd(int cmd); void setColorMode(int mode) { colorMode = mode; diff --git a/muse2/muse/midiedit/scoreedit.cpp b/muse2/muse/midiedit/scoreedit.cpp index ab161946..5770ee6c 100644 --- a/muse2/muse/midiedit/scoreedit.cpp +++ b/muse2/muse/midiedit/scoreedit.cpp @@ -1258,6 +1258,11 @@ ScoreCanvas::ScoreCanvas(ScoreEdit* pr, QWidget* parent_widget) : View(parent_wi unsetCursor(); } +ScoreCanvas::~ScoreCanvas() +{ + delete steprec; +} + void ScoreCanvas::staffmode_treble_slot() { set_staffmode(current_staff, MODE_TREBLE); @@ -4584,16 +4589,43 @@ void ScoreCanvas::add_new_parts(const std::map< MusECore::Part*, std::set<MusECo * because after A (and B) got resized, the B-resize is invalid! * o when changing toolbarstate when sharing and immediately after that * changing "share" status, the changed state isn't stored + * o arranger state and mixer state aren't stored (says tim) * ? pasting in editors sometimes fails oO? ( ERROR: reading eventlist * from clipboard failed. ignoring this one... ) [ not reproducible ] * * CURRENT TODO - * ! o fix sigedit boxes (see also "important todo") + * o in appearance.cpp: add the new stuff for drumTrackLabelBg and drumTrackBg + * o find and fix FINDMICHJETZT + * o fix all segfaults and non-working stuff! + * - creating, changing types to and from, erasing NEW_DRUM tracks + * - move parts around + * - playing them. mute? + * - recording/echoing/steprec them + * - load, save them * o fix valgrind problems + * * > o drum editor: channel-stuff + * 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 save hide, ordering, track's drumlists + * 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, + * ask the user if he wants to proceed, and then set maintained_automatically to false + * o offer some way to set maintained_automatically to true again + * o move generation and deletion of ourDrumMap from DCanvas to DrumEditor and remove ugly wrapper functions + * + * x when playing back a flo-drum-track: treat as a MIDI track, + * EXCEPT that the drum list's mute entries are respected! + * o when recording or echoing a flo-drum-track: watch out for In-Notes! + * o update [midi]track::read/write, readproperties, writeprop... (drumlist etc), operator= * * IMPORTANT TODO - * ! o fix sigedit boxes (see also "current todo") + * o all places where i added doubleclick-edits: only react on left-click double clicks! + * o support "new style" reordering with old style drum tracks as well + * (not swapping but inserting!) * o add "dotted quarter" quantize option (for 6/8 beat) * o ticks-to-quarter spinboxes * o newly created windows have to be focussed! diff --git a/muse2/muse/midiedit/scoreedit.h b/muse2/muse/midiedit/scoreedit.h index 4e2ecf5d..0d1432b8 100644 --- a/muse2/muse/midiedit/scoreedit.h +++ b/muse2/muse/midiedit/scoreedit.h @@ -811,7 +811,7 @@ class ScoreCanvas : public MusEGui::View public: ScoreCanvas(ScoreEdit*, QWidget*); - ~ScoreCanvas(){}; + ~ScoreCanvas(); void add_staves(MusECore::PartList* pl, bool all_in_one); void push_back_staff(staff_t& staff) { staves.push_back(staff); } //FINDMICH dirty. very dirty. diff --git a/muse2/muse/mixer/amixer.cpp b/muse2/muse/mixer/amixer.cpp index 3a947945..64ebda11 100644 --- a/muse2/muse/mixer/amixer.cpp +++ b/muse2/muse/mixer/amixer.cpp @@ -183,6 +183,7 @@ AudioMixerApp::AudioMixerApp(QWidget* parent, MixerConfig* c) showMidiTracksId = new QAction(tr("Show Midi Tracks"), actionItems); showDrumTracksId = new QAction(tr("Show Drum Tracks"), actionItems); + showNewDrumTracksId = new QAction(tr("Show New Style Drum Tracks"), actionItems); showWaveTracksId = new QAction(tr("Show Wave Tracks"), actionItems); QAction *separator = new QAction(this); @@ -197,6 +198,7 @@ AudioMixerApp::AudioMixerApp(QWidget* parent, MixerConfig* c) showMidiTracksId->setCheckable(true); showDrumTracksId->setCheckable(true); + showNewDrumTracksId->setCheckable(true); showWaveTracksId->setCheckable(true); showInputTracksId->setCheckable(true); showOutputTracksId->setCheckable(true); @@ -208,6 +210,7 @@ AudioMixerApp::AudioMixerApp(QWidget* parent, MixerConfig* c) //connect(actionItems, SIGNAL(selected(QAction*)), this, SLOT(showTracksChanged(QAction*))); connect(showMidiTracksId, SIGNAL(triggered(bool)), SLOT(showMidiTracksChanged(bool))); connect(showDrumTracksId, SIGNAL(triggered(bool)), SLOT(showDrumTracksChanged(bool))); + connect(showNewDrumTracksId, SIGNAL(triggered(bool)), SLOT(showNewDrumTracksChanged(bool))); connect(showWaveTracksId, SIGNAL(triggered(bool)), SLOT(showWaveTracksChanged(bool))); connect(showInputTracksId, SIGNAL(triggered(bool)), SLOT(showInputTracksChanged(bool))); connect(showOutputTracksId, SIGNAL(triggered(bool)), SLOT(showOutputTracksChanged(bool))); @@ -349,6 +352,7 @@ void AudioMixerApp::updateMixer(UpdateAction action) showMidiTracksId->setChecked(cfg->showMidiTracks); showDrumTracksId->setChecked(cfg->showDrumTracks); + showNewDrumTracksId->setChecked(cfg->showNewDrumTracks); showInputTracksId->setChecked(cfg->showInputTracks); showOutputTracksId->setChecked(cfg->showOutputTracks); showWaveTracksId->setChecked(cfg->showWaveTracks); @@ -428,7 +432,7 @@ void AudioMixerApp::updateMixer(UpdateAction action) for (MusECore::iMidiTrack i = mtl->begin(); i != mtl->end(); ++i) { MusECore::MidiTrack* mt = *i; - if((mt->type() == MusECore::Track::MIDI && cfg->showMidiTracks) || (mt->type() == MusECore::Track::DRUM && cfg->showDrumTracks)) + if((mt->type() == MusECore::Track::MIDI && cfg->showMidiTracks) || (mt->type() == MusECore::Track::DRUM && cfg->showDrumTracks) || (mt->type() == MusECore::Track::NEW_DRUM && cfg->showNewDrumTracks)) addStrip(*i, idx++); } @@ -485,7 +489,7 @@ void AudioMixerApp::updateMixer(UpdateAction action) for (MusECore::iMidiTrack i = mtl->begin(); i != mtl->end(); ++i) { MusECore::MidiTrack* mt = *i; - if((mt->type() == MusECore::Track::MIDI && cfg->showMidiTracks) || (mt->type() == MusECore::Track::DRUM && cfg->showDrumTracks)) + if((mt->type() == MusECore::Track::MIDI && cfg->showMidiTracks) || (mt->type() == MusECore::Track::DRUM && cfg->showDrumTracks) || (mt->type() == MusECore::Track::NEW_DRUM && cfg->showNewDrumTracks)) addStrip(*i, idx++); } @@ -627,6 +631,8 @@ void AudioMixerApp::showTracksChanged(QAction* id) cfg->showMidiTracks = val; else if (id == showDrumTracksId) cfg->showDrumTracks = val; + else if (id == showNewDrumTracksId) + cfg->showNewDrumTracks = val; else if (id == showInputTracksId) cfg->showInputTracks = val; else if (id == showOutputTracksId) @@ -655,6 +661,12 @@ void AudioMixerApp::showDrumTracksChanged(bool v) updateMixer(UPDATE_ALL); } +void AudioMixerApp::showNewDrumTracksChanged(bool v) +{ + cfg->showNewDrumTracks = v; + updateMixer(UPDATE_ALL); +} + void AudioMixerApp::showWaveTracksChanged(bool v) { cfg->showWaveTracks = v; @@ -710,6 +722,7 @@ void AudioMixerApp::write(int level, MusECore::Xml& xml) xml.intTag(level, "showMidiTracks", cfg->showMidiTracks); xml.intTag(level, "showDrumTracks", cfg->showDrumTracks); + xml.intTag(level, "showNewDrumTracks", cfg->showNewDrumTracks); xml.intTag(level, "showInputTracks", cfg->showInputTracks); xml.intTag(level, "showOutputTracks", cfg->showOutputTracks); xml.intTag(level, "showWaveTracks", cfg->showWaveTracks); diff --git a/muse2/muse/mixer/amixer.h b/muse2/muse/mixer/amixer.h index cf856f22..1f29c693 100644 --- a/muse2/muse/mixer/amixer.h +++ b/muse2/muse/mixer/amixer.h @@ -96,6 +96,7 @@ class AudioMixerApp : public QMainWindow { QAction* showMidiTracksId; QAction* showDrumTracksId; + QAction* showNewDrumTracksId; QAction* showInputTracksId; QAction* showOutputTracksId; QAction* showWaveTracksId; @@ -129,6 +130,7 @@ class AudioMixerApp : public QMainWindow { //void showTracksChanged(QAction*); void showMidiTracksChanged(bool); void showDrumTracksChanged(bool); + void showNewDrumTracksChanged(bool); void showWaveTracksChanged(bool); void showInputTracksChanged(bool); void showOutputTracksChanged(bool); diff --git a/muse2/muse/mixer/strip.cpp b/muse2/muse/mixer/strip.cpp index b87c4629..5f5e5e39 100644 --- a/muse2/muse/mixer/strip.cpp +++ b/muse2/muse/mixer/strip.cpp @@ -150,6 +150,10 @@ void Strip::setLabelText() //c = QColor(0, 160, 255); // Med blue c = MusEGlobal::config.drumTrackLabelBg; break; + case MusECore::Track::NEW_DRUM: + //c = QColor(0, 160, 255); // Med blue + c = MusEGlobal::config.newDrumTrackLabelBg; + break; default: return; } diff --git a/muse2/muse/part.cpp b/muse2/muse/part.cpp index 693512c5..3601ff57 100644 --- a/muse2/muse/part.cpp +++ b/muse2/muse/part.cpp @@ -403,7 +403,7 @@ void addPortCtrlEvents(Event& event, Part* part, bool doClones) MidiPort* mp = &MusEGlobal::midiPorts[port]; // Is it a drum controller event, according to the track port's instrument? - if(mt->type() == Track::DRUM) + if(mt->type() == Track::DRUM) //FINDMICHJETZT was ist das? { MidiController* mc = mp->drumController(cntrl); if(mc) @@ -471,7 +471,7 @@ void addPortCtrlEvents(Part* part, bool doClones) MidiPort* mp = &MusEGlobal::midiPorts[port]; // Is it a drum controller event, according to the track port's instrument? - if(mt->type() == Track::DRUM) + if(mt->type() == Track::DRUM) //FINDMICHJETZT was ist das? { MidiController* mc = mp->drumController(cntrl); if(mc) @@ -530,7 +530,7 @@ void removePortCtrlEvents(Event& event, Part* part, bool doClones) MidiPort* mp = &MusEGlobal::midiPorts[port]; // Is it a drum controller event, according to the track port's instrument? - if(mt->type() == Track::DRUM) + if(mt->type() == Track::DRUM) //FINDMICHJETZT was ist das? { MidiController* mc = mp->drumController(cntrl); if(mc) @@ -599,7 +599,7 @@ void removePortCtrlEvents(Part* part, bool doClones) MidiPort* mp = &MusEGlobal::midiPorts[port]; // Is it a drum controller event, according to the track port's instrument? - if(mt->type() == Track::DRUM) + if(mt->type() == Track::DRUM) //FINDMICHJETZT was ist das? { MidiController* mc = mp->drumController(cntrl); if(mc) @@ -917,6 +917,7 @@ void Song::cmdResizePart(Track* track, Part* oPart, unsigned int len, bool doClo break; case Track::MIDI: case Track::DRUM: + case Track::NEW_DRUM: { Undo operations; @@ -963,6 +964,7 @@ void Track::splitPart(Part* part, int tickpos, Part*& p1, Part*& p2) break; case MIDI: case DRUM: + case NEW_DRUM: l1 = tickpos - part->tick(); l2 = part->lenTick() - l1; break; @@ -986,6 +988,7 @@ void Track::splitPart(Part* part, int tickpos, Part*& p1, Part*& p2) break; case MIDI: case DRUM: + case NEW_DRUM: p1->setLenTick(l1); p2->setTick(tickpos); p2->setLenTick(l2); diff --git a/muse2/muse/remote/pyapi.cpp b/muse2/muse/remote/pyapi.cpp index 645c639e..57b956ca 100644 --- a/muse2/muse/remote/pyapi.cpp +++ b/muse2/muse/remote/pyapi.cpp @@ -697,7 +697,8 @@ PyObject* getAudioTrackVolume(PyObject*, PyObject* args) if (t == NULL) return NULL; - if (t->type() == Track::DRUM || t->type() == Track::MIDI) + //if (t->type() == Track::DRUM || t->type() == Track::MIDI || t->type() == Track::NEW_DRUM) + if (t->isMidiTrack()) // changed by flo. should do the same thing and is better maintainable return NULL; AudioTrack* track = (AudioTrack*) t; @@ -1091,7 +1092,8 @@ bool Song::event(QEvent* _e) if (t == NULL) return false; - if (t->type() == Track::DRUM || t->type() == Track::MIDI) + if (t->isMidiTrack()) // changed by flo. is better maintainable + //if (t->type() == Track::DRUM || t->type() == Track::NEW_DRUM || t->type() == Track::MIDI) return false; AudioTrack* track = (AudioTrack*) t; diff --git a/muse2/muse/shortcuts.cpp b/muse2/muse/shortcuts.cpp index e6260749..7563fd93 100644 --- a/muse2/muse/shortcuts.cpp +++ b/muse2/muse/shortcuts.cpp @@ -99,6 +99,7 @@ void initShortCuts() defShrt(SHRT_OPEN_MIDI_TRANSFORM, Qt::CTRL + Qt::Key_T, "Open midi transformer", ARRANG_SHRT, "open_midi_transform"); defShrt(SHRT_ADD_MIDI_TRACK, Qt::CTRL + Qt::Key_J, "Add midi track", ARRANG_SHRT, "add_midi_track"); defShrt(SHRT_ADD_DRUM_TRACK, 0, "Add drum track", ARRANG_SHRT, "add_drum_track"); + defShrt(SHRT_ADD_NEW_STYLE_DRUM_TRACK, 0, "Add new style drum track", ARRANG_SHRT, "add_new_style_drum_track"); defShrt(SHRT_ADD_WAVE_TRACK, 0, "Add wave track", ARRANG_SHRT, "add_wave_track"); defShrt(SHRT_ADD_AUDIO_OUTPUT, 0, "Add audio output", ARRANG_SHRT, "add_audio_output"); defShrt(SHRT_ADD_AUDIO_GROUP, 0, "Add audio group", ARRANG_SHRT, "add_audio_group"); diff --git a/muse2/muse/shortcuts.h b/muse2/muse/shortcuts.h index 626c4fb8..dc2e6f22 100644 --- a/muse2/muse/shortcuts.h +++ b/muse2/muse/shortcuts.h @@ -174,6 +174,7 @@ enum { SHRT_ADD_MIDI_TRACK, //Default: Ctrl+J SHRT_ADD_DRUM_TRACK, //Default: undefined + SHRT_ADD_NEW_STYLE_DRUM_TRACK, //Default: undefined SHRT_ADD_WAVE_TRACK, //Default: undefined SHRT_ADD_AUDIO_OUTPUT, //Default: undefined SHRT_ADD_AUDIO_GROUP, //Default: undefined diff --git a/muse2/muse/song.cpp b/muse2/muse/song.cpp index 0f19c313..c9efe288 100644 --- a/muse2/muse/song.cpp +++ b/muse2/muse/song.cpp @@ -243,6 +243,11 @@ Track* Song::addTrack(Track::TrackType type, Track* insertAt) track = new MidiTrack(); track->setType(Track::MIDI); break; + case Track::NEW_DRUM: + track = new MidiTrack(); + track->setType(Track::NEW_DRUM); + ((MidiTrack*)track)->setOutChannel(9); + break; case Track::DRUM: track = new MidiTrack(); track->setType(Track::DRUM); @@ -320,7 +325,7 @@ Track* Song::addTrack(Track::TrackType type, Track* insertAt) { defOutFound = true; mt->setOutPort(i); - if(type != Track::DRUM) // p4.0.17 Leave drum tracks at channel 10. + if(type != Track::DRUM && type != Track::NEW_DRUM) // p4.0.17 Leave drum tracks at channel 10. mt->setOutChannel(ch); updateFlags |= SC_ROUTE; break; @@ -341,6 +346,7 @@ Track* Song::addTrack(Track::TrackType type, Track* insertAt) switch(type) { //case Track::MIDI: //case Track::DRUM: + //case Track::NEW_DRUM: //case Track::AUDIO_OUTPUT: // break; @@ -440,7 +446,7 @@ bool Song::addEvent(Event& event, Part* part) MidiPort* mp = &MusEGlobal::midiPorts[track->outPort()]; // Is it a drum controller event, according to the track port's instrument? - if(track->type() == Track::DRUM) + if(track->type() == Track::DRUM) //FINDMICHJETZT was ist das? { MidiController* mc = mp->drumController(cntrl); if(mc) @@ -513,7 +519,7 @@ void Song::changeEvent(Event& oldEvent, Event& newEvent, Part* part) int cntrl = oldEvent.dataA(); MidiPort* mp = &MusEGlobal::midiPorts[track->outPort()]; // Is it a drum controller event, according to the track port's instrument? - if(track->type() == Track::DRUM) + if(track->type() == Track::DRUM) //FINDMICHJETZT was ist das? { MidiController* mc = mp->drumController(cntrl); if(mc) @@ -540,7 +546,7 @@ void Song::changeEvent(Event& oldEvent, Event& newEvent, Part* part) int val = newEvent.dataB(); MidiPort* mp = &MusEGlobal::midiPorts[track->outPort()]; // Is it a drum controller event, according to the track port's instrument? - if(track->type() == Track::DRUM) + if(track->type() == Track::DRUM) //FINDMICHJETZT was ist das? { MidiController* mc = mp->drumController(cntrl); if(mc) @@ -574,7 +580,7 @@ void Song::deleteEvent(Event& event, Part* part) MidiPort* mp = &MusEGlobal::midiPorts[track->outPort()]; // Is it a drum controller event, according to the track port's instrument? - if(track->type() == Track::DRUM) + if(track->type() == Track::DRUM) //FINDMICHJETZT was ist das? { MidiController* mc = mp->drumController(cntrl); if(mc) @@ -615,7 +621,7 @@ void Song::remapPortDrumCtrlEvents(int mapidx, int newnote, int newchan, int new for(ciMidiTrack it = _midis.begin(); it != _midis.end(); ++it) { MidiTrack* mt = *it; - if(mt->type() != Track::DRUM) + if(mt->type() != Track::DRUM) //FINDMICHJETZT was ist das? drumcontroller? continue; MidiPort* trackmp = &MusEGlobal::midiPorts[mt->outPort()]; @@ -629,6 +635,7 @@ void Song::remapPortDrumCtrlEvents(int mapidx, int newnote, int newchan, int new { const Event& ev = ie->second; // Added by T356. Do not handle events which are past the end of the part. + //FINDMICHJETZT why not? if(ev.tick() >= len) break; @@ -685,7 +692,7 @@ void Song::changeAllPortDrumCtrlEvents(bool add, bool drumonly) for(ciMidiTrack it = _midis.begin(); it != _midis.end(); ++it) { MidiTrack* mt = *it; - if(mt->type() != Track::DRUM) + if(mt->type() != Track::DRUM) //FINDMICHJETZT was ist das? drumcontroller continue; trackmp = &MusEGlobal::midiPorts[mt->outPort()]; @@ -1473,11 +1480,13 @@ void Song::rewindStart() // update //--------------------------------------------------------- -void Song::update(int flags) +void Song::update(int flags, bool allowRecursion) { static int level = 0; // DEBUG - if (level) { - printf("Song::update %08x, level %d\n", flags, level); + if (level && !allowRecursion) { + printf("THIS SHOULD NEVER HAPPEN: unallowed recursion in Song::update(%08x), level %d!\n" + " the songChanged() signal is NOT emitted. this will\n" + " probably cause windows being not up-to-date.\n", flags, level); return; } ++level; @@ -3354,6 +3363,7 @@ void Song::insertTrack2(Track* track, int idx) switch(track->type()) { case Track::MIDI: case Track::DRUM: + case Track::NEW_DRUM: _midis.push_back((MidiTrack*)track); // Added by T356. //((MidiTrack*)track)->addPortCtrlEvents(); @@ -3604,6 +3614,7 @@ void Song::removeTrack2(Track* track) switch(track->type()) { case Track::MIDI: case Track::DRUM: + case Track::NEW_DRUM: // Added by T356. //((MidiTrack*)track)->removePortCtrlEvents(); removePortCtrlEvents(((MidiTrack*)track)); diff --git a/muse2/muse/song.h b/muse2/muse/song.h index 7bbd831d..d6d3628c 100644 --- a/muse2/muse/song.h +++ b/muse2/muse/song.h @@ -383,7 +383,9 @@ class Song : public QObject { public slots: void seekTo(int tick); - void update(int flags = -1); + void update(int flags = -1, bool allowRecursion=false); // use allowRecursion with care! this + // could lock up muse if you aren't sure + // that your recursion will be finite! void beat(); void undo(); diff --git a/muse2/muse/songfile.cpp b/muse2/muse/songfile.cpp index 07b03c5e..3096312e 100644 --- a/muse2/muse/songfile.cpp +++ b/muse2/muse/songfile.cpp @@ -725,7 +725,7 @@ void Part::read(Xml& xml, int, bool toTrack) // int newPartOffset newPartOffset=this->tick(); int ctl = e.dataA(); - if(mt->type() == Track::DRUM) + if(mt->type() == Track::DRUM) //FINDMICHJETZT commented out: was ist das? { // Is it a drum controller event, according to the track port's instrument? MidiController* mc = mp->drumController(ctl); @@ -1050,6 +1050,12 @@ void Song::read(Xml& xml, bool isTemplate) track->read(xml); insertTrack0(track, -1); } + else if (tag == "newdrumtrack") { + MidiTrack* track = new MidiTrack(); + track->setType(Track::NEW_DRUM); + track->read(xml); + insertTrack0(track, -1); + } else if (tag == "wavetrack") { MusECore::WaveTrack* track = new MusECore::WaveTrack(); track->read(xml); @@ -1115,6 +1121,8 @@ void Song::read(Xml& xml, bool isTemplate) } else if (tag == "drummap") readDrumMap(xml, false); + else if (tag == "drum_ordering") + MusEGlobal::global_drum_ordering.read(xml); else xml.unknown("Song"); break; @@ -1207,6 +1215,7 @@ void Song::write(int level, Xml& xml) const _markerList->write(level, xml); writeDrumMap(level, xml, false); + MusEGlobal::global_drum_ordering.write(level, xml); xml.tag(level, "/song"); // Restore backup of the clone list, to retain any 'copy' items, diff --git a/muse2/muse/track.cpp b/muse2/muse/track.cpp index 6fbe81c5..32344b6e 100644 --- a/muse2/muse/track.cpp +++ b/muse2/muse/track.cpp @@ -32,6 +32,7 @@ #include "audio.h" #include "globaldefs.h" #include "route.h" +#include "drummap.h" namespace MusECore { @@ -42,8 +43,8 @@ bool Track::_tmpSoloChainDoIns = false; bool Track::_tmpSoloChainNoDec = false; const char* Track::_cname[] = { - "Midi", "Drum", "Wave", "AudioOut", "AudioIn", "AudioGroup", - "AudioAux", "AudioSynth" + "Midi", "Drum", "NewStyleDrum", "Wave", + "AudioOut", "AudioIn", "AudioGroup", "AudioAux", "AudioSynth" }; @@ -77,7 +78,7 @@ void addPortCtrlEvents(MidiTrack* t) MidiPort* mp = &MusEGlobal::midiPorts[t->outPort()]; // Is it a drum controller event, according to the track port's instrument? - if(t->type() == Track::DRUM) + if(t->type() == Track::DRUM) //FINDMICHJETZT was soll das? drumcontroller -_- { MidiController* mc = mp->drumController(cntrl); if(mc) @@ -125,7 +126,7 @@ void removePortCtrlEvents(MidiTrack* t) MidiPort* mp = &MusEGlobal::midiPorts[t->outPort()]; // Is it a drum controller event, according to the track port's instrument? - if(t->type() == Track::DRUM) + if(t->type() == Track::DRUM) //FINDMICHJETZT was soll das? drumcontroller... { MidiController* mc = mp->drumController(cntrl); if(mc) @@ -243,7 +244,8 @@ Track::Track(const Track& t, bool cloneParts) // A couple of schemes were conceived to deal with cloneList being invalid, but the best way is // to not alter the part list here. It's a big headache because: Either the parts in the cloneList // need to be reliably looked up replaced with the new ones, or the clipboard and cloneList must be cleared. - // Fortunately the ONLY part of muse using this function is track rename (in TrackList and TrackInfo). + // Fortunately the ONLY parts of muse using this function are track rename (in TrackList and TrackInfo) and + // changing track type from MIDI to NEW_DRUM or vice versa (NOT something -> DRUM or vice versa). // So we can get away with leaving this out: //for (iPart ip = _parts.begin(); ip != _parts.end(); ++ip) // ip->second->setTrack(this); @@ -315,6 +317,7 @@ void Track::setDefaultName() switch(_type) { case MIDI: case DRUM: + case NEW_DRUM: case WAVE: base = QString("Track"); break; @@ -398,6 +401,23 @@ MidiTrack::MidiTrack() _events = new EventList; _mpevents = new MPEventList; clefType=trebleClef; + + _drummap=new DrumMap[128]; + _drummap_hidden=new bool[128]; + + for (int i=0;i<128;i++) + { + int idx=idrumMap[i].anote; + if (idx < 0 || idx >= 128) + printf ("ERROR: THIS SHOULD NEVER HAPPEN: idrumMap[%i].anote is not within 0..127!\n", idx); + else + _drummap[idx]=idrumMap[i]; + + MusEGlobal::global_drum_ordering.push_back(std::pair<MidiTrack*,int>(this,idx)); + } + for (int i=0;i<128;i++) + _drummap_hidden[i]=false; + } //MidiTrack::MidiTrack(const MidiTrack& mt) @@ -418,12 +438,36 @@ MidiTrack::MidiTrack(const MidiTrack& mt, bool cloneParts) compression = mt.compression; _recEcho = mt.recEcho(); clefType=trebleClef; + + _drummap=new DrumMap[128]; + _drummap_hidden=new bool[128]; + memcpy(_drummap, mt._drummap, 128*sizeof(*_drummap)); + memcpy(_drummap_hidden, mt._drummap_hidden, 128*sizeof(*_drummap_hidden)); + + for (MusEGlobal::global_drum_ordering_t::iterator it=MusEGlobal::global_drum_ordering.begin(); it!=MusEGlobal::global_drum_ordering.end(); it++) + if (it->first == &mt) + { + it=MusEGlobal::global_drum_ordering.insert(it, *it); // duplicates the entry at it, set it to the first entry of both + it++; // make it point to the second entry + it->first=this; + } } MidiTrack::~MidiTrack() { delete _events; delete _mpevents; + delete [] _drummap; + delete [] _drummap_hidden; + + // remove ourselves from the global_drum_ordering list + // this is not really necessary, but cleaner + for (MusEGlobal::global_drum_ordering_t::iterator it=MusEGlobal::global_drum_ordering.begin(); it!=MusEGlobal::global_drum_ordering.end();) + if (it->first == this) + it=MusEGlobal::global_drum_ordering.erase(it); + else + it++; + } //--------------------------------------------------------- @@ -433,7 +477,7 @@ MidiTrack::~MidiTrack() void MidiTrack::init() { _outPort = 0; - _outChannel = 0; + _outChannel = (type()==NEW_DRUM) ? 9 : 0; // Changed by Tim. p3.3.8 //_inPortMask = 0xffff; ///_inPortMask = 0xffffffff; @@ -607,7 +651,7 @@ void MidiTrack::addPortCtrlEvents() MidiPort* mp = &MusEGlobal::midiPorts[_outPort]; // Is it a drum controller event, according to the track port's instrument? - if(type() == DRUM) + if(type() == DRUM) //FINDMICHJETZT commented out. was soll das? { MidiController* mc = mp->drumController(cntrl); if(mc) @@ -648,7 +692,7 @@ void MidiTrack::removePortCtrlEvents() MidiPort* mp = &MusEGlobal::midiPorts[_outPort]; // Is it a drum controller event, according to the track port's instrument? - if(type() == DRUM) + if(type() == DRUM) //FINDMICHJETZT commented out: was soll das? { MidiController* mc = mp->drumController(cntrl); if(mc) @@ -720,8 +764,13 @@ void MidiTrack::write(int level, Xml& xml) const if (type() == DRUM) tag = "drumtrack"; - else + else if (type() == MIDI) tag = "miditrack"; + else if (type() == NEW_DRUM) + tag = "newdrumtrack"; + else + printf("THIS SHOULD NEVER HAPPEN: non-midi-type in MidiTrack::write()\n"); + xml.tag(level++, tag); Track::writeProperties(level, xml); @@ -813,7 +862,7 @@ void MidiTrack::read(Xml& xml) case Xml::Attribut: break; case Xml::TagEnd: - if (tag == "miditrack" || tag == "drumtrack") + if (tag == "miditrack" || tag == "drumtrack" || tag == "newdrumtrack") { setInPortAndChannelMask(portmask, chanmask); // p3.3.48: Support old files. return; diff --git a/muse2/muse/track.h b/muse2/muse/track.h index 46dfc59f..0911b4f1 100644 --- a/muse2/muse/track.h +++ b/muse2/muse/track.h @@ -44,6 +44,7 @@ class PluginI; class SndFile; class SynthI; class Xml; +class DrumMap; //--------------------------------------------------------- @@ -53,7 +54,7 @@ class Xml; class Track { public: enum TrackType { - MIDI=0, DRUM, WAVE, AUDIO_OUTPUT, AUDIO_INPUT, AUDIO_GROUP, + MIDI=0, DRUM, NEW_DRUM, WAVE, AUDIO_OUTPUT, AUDIO_INPUT, AUDIO_GROUP, AUDIO_AUX, AUDIO_SOFTSYNTH }; private: @@ -200,11 +201,11 @@ class Track { void setDefaultName(); int channels() const { return _channels; } virtual void setChannels(int n); - bool isMidiTrack() const { return type() == MIDI || type() == DRUM; } + bool isMidiTrack() const { return type() == MIDI || type() == DRUM || type() == NEW_DRUM; } virtual bool canRecord() const { return false; } virtual AutomationType automationType() const = 0; virtual void setAutomationType(AutomationType t) = 0; - static void setVisible(bool ) { } + static void setVisible(bool) { } }; @@ -227,6 +228,12 @@ class MidiTrack : public Track { MPEventList* _mpevents; // tmp Events druring recording static bool _isVisible; clefTypes clefType; + + DrumMap* _drummap; // _drummap[foo].anote is always equal to foo + bool _drummap_tied_to_patch; //if true, changing patch also changes drummap + bool* _drummap_hidden; + + void init(); public: MidiTrack(); @@ -234,7 +241,6 @@ class MidiTrack : public Track { MidiTrack(const MidiTrack&, bool cloneParts); virtual ~MidiTrack(); - void init(); virtual AutomationType automationType() const; virtual void setAutomationType(AutomationType); @@ -295,6 +301,9 @@ class MidiTrack : public Track { void setClef(clefTypes i) { clefType = i; } clefTypes getClef() { return clefType; } + + DrumMap* drummap() { return _drummap; } + bool* drummap_hidden() { return _drummap_hidden; } }; } // namespace MusECore diff --git a/muse2/muse/undo.cpp b/muse2/muse/undo.cpp index eb554495..5bbcfcd8 100644 --- a/muse2/muse/undo.cpp +++ b/muse2/muse/undo.cpp @@ -777,6 +777,7 @@ void Song::doRedo2() UndoOp::UndoOp() { + type=UndoOp::DoNothing; } UndoOp::UndoOp(UndoType type_) @@ -1075,4 +1076,16 @@ void Song::doRedo3() dirty = true; } + +bool Undo::empty() const +{ + if (std::list<UndoOp>::empty()) return true; + + for (const_iterator it=begin(); it!=end(); it++) + if (it->type!=UndoOp::DoNothing) + return false; + + return true; +} + } // namespace MusECore diff --git a/muse2/muse/undo.h b/muse2/muse/undo.h index 19c252bf..42a80763 100644 --- a/muse2/muse/undo.h +++ b/muse2/muse/undo.h @@ -121,7 +121,8 @@ struct UndoOp { }; class Undo : public std::list<UndoOp> { - void undoOp(UndoOp::UndoType, int data); + public: + bool empty() const; }; typedef Undo::iterator iUndoOp; diff --git a/muse2/muse/widgets/mtrackinfo.cpp b/muse2/muse/widgets/mtrackinfo.cpp index b5460447..33462d0c 100644 --- a/muse2/muse/widgets/mtrackinfo.cpp +++ b/muse2/muse/widgets/mtrackinfo.cpp @@ -216,6 +216,7 @@ void MidiTrackInfo::heartBeat() { case MusECore::Track::MIDI: case MusECore::Track::DRUM: + case MusECore::Track::NEW_DRUM: { MusECore::MidiTrack* track = (MusECore::MidiTrack*)selected; @@ -344,7 +345,7 @@ void MidiTrackInfo::heartBeat() else { MusECore::MidiInstrument* instr = mp->instrument(); - QString name = instr->getPatchName(outChannel, nprogram, MusEGlobal::song->mtype(), track->type() == MusECore::Track::DRUM); + QString name = instr->getPatchName(outChannel, nprogram, MusEGlobal::song->mtype(), track->type() == MusECore::Track::DRUM); //FINDMICHJETZT was soll das? if(name.isEmpty()) { const QString n("???"); @@ -390,7 +391,7 @@ void MidiTrackInfo::heartBeat() //else //{ MusECore::MidiInstrument* instr = mp->instrument(); - QString name = instr->getPatchName(outChannel, program, MusEGlobal::song->mtype(), track->type() == MusECore::Track::DRUM); + QString name = instr->getPatchName(outChannel, program, MusEGlobal::song->mtype(), track->type() == MusECore::Track::DRUM); //FINDMICHJETZT was soll das? if(iPatch->text() != name) iPatch->setText(name); @@ -567,8 +568,12 @@ void MidiTrackInfo::setLabelText() //pal.setColor(trackNameLabel->backgroundRole(), QColor(0, 160, 255)); // Med blue if(track->type() == MusECore::Track::DRUM) c = MusEGlobal::config.drumTrackLabelBg; - else + else if (track->type() == MusECore::Track::MIDI) c = MusEGlobal::config.midiTrackLabelBg; + else if (track->type() == MusECore::Track::NEW_DRUM) + c = MusEGlobal::config.newDrumTrackLabelBg; + else + printf("THIS SHOULD NEVER HAPPEN: track is not a MIDI track in MidiTrackInfo::setLabelText()!\n"); QLinearGradient gradient(trackNameLabel->geometry().topLeft(), trackNameLabel->geometry().bottomLeft()); //gradient.setColorAt(0, c.darker()); @@ -757,7 +762,7 @@ void MidiTrackInfo::iProgHBankChanged() MusEGlobal::audio->msgPlayMidiEvent(&ev); MusECore::MidiInstrument* instr = mp->instrument(); - iPatch->setText(instr->getPatchName(channel, program, MusEGlobal::song->mtype(), track->type() == MusECore::Track::DRUM)); + iPatch->setText(instr->getPatchName(channel, program, MusEGlobal::song->mtype(), track->type() == MusECore::Track::DRUM)); //FINDMICHJETZT was soll das? // updateTrackInfo(); } @@ -835,7 +840,7 @@ void MidiTrackInfo::iProgLBankChanged() MusEGlobal::audio->msgPlayMidiEvent(&ev); MusECore::MidiInstrument* instr = mp->instrument(); - iPatch->setText(instr->getPatchName(channel, program, MusEGlobal::song->mtype(), track->type() == MusECore::Track::DRUM)); + iPatch->setText(instr->getPatchName(channel, program, MusEGlobal::song->mtype(), track->type() == MusECore::Track::DRUM)); //FINDMICHJETZT was soll das? // updateTrackInfo(); } @@ -913,7 +918,7 @@ void MidiTrackInfo::iProgramChanged() MusEGlobal::audio->msgPlayMidiEvent(&ev); MusECore::MidiInstrument* instr = mp->instrument(); - iPatch->setText(instr->getPatchName(channel, program, MusEGlobal::song->mtype(), track->type() == MusECore::Track::DRUM)); + iPatch->setText(instr->getPatchName(channel, program, MusEGlobal::song->mtype(), track->type() == MusECore::Track::DRUM)); //FINDMICHJETZT was soll das? } // updateTrackInfo(); @@ -1082,7 +1087,7 @@ void MidiTrackInfo::instrPopup() PopupMenu* pup = new PopupMenu(true); //instr->populatePatchPopup(pop, channel, MusEGlobal::song->mtype(), track->type() == MusECore::Track::DRUM); - populatePatchPopup(instr, pup, channel, MusEGlobal::song->mtype(), track->type() == MusECore::Track::DRUM); + populatePatchPopup(instr, pup, channel, MusEGlobal::song->mtype(), track->type() == MusECore::Track::DRUM); //FINDMICHJETZT was soll das? //if(pop->actions().count() == 0) // return; @@ -1406,7 +1411,7 @@ void MidiTrackInfo::updateTrackInfo(int flags) else { MusECore::MidiInstrument* instr = mp->instrument(); - iPatch->setText(instr->getPatchName(outChannel, nprogram, MusEGlobal::song->mtype(), track->type() == MusECore::Track::DRUM)); + iPatch->setText(instr->getPatchName(outChannel, nprogram, MusEGlobal::song->mtype(), track->type() == MusECore::Track::DRUM)); //FINDMICHJETZT was soll das? } } else @@ -1422,7 +1427,7 @@ void MidiTrackInfo::updateTrackInfo(int flags) //else //{ MusECore::MidiInstrument* instr = mp->instrument(); - iPatch->setText(instr->getPatchName(outChannel, program, MusEGlobal::song->mtype(), track->type() == MusECore::Track::DRUM)); + iPatch->setText(instr->getPatchName(outChannel, program, MusEGlobal::song->mtype(), track->type() == MusECore::Track::DRUM)); //FINDMICHJETZT was soll das? int hb = ((program >> 16) & 0xff) + 1; if (hb == 0x100) diff --git a/muse2/muse/widgets/musewidgetsplug.cpp b/muse2/muse/widgets/musewidgetsplug.cpp index 8520a731..26a3054d 100644 --- a/muse2/muse/widgets/musewidgetsplug.cpp +++ b/muse2/muse/widgets/musewidgetsplug.cpp @@ -131,6 +131,7 @@ GlobalConfigValues config = { QColor(0, 160, 255), // midiTrackLabelBg; // Med blue QColor(0, 160, 255), // drumTrackLabelBg; // Med blue + QColor(0, 160, 255), // newDrumTrackLabelBg; // Med blue Qt::magenta, // waveTrackLabelBg; Qt::green, // outputTrackLabelBg; Qt::red, // inputTrackLabelBg; @@ -140,6 +141,7 @@ GlobalConfigValues config = { QColor(220, 220, 220), // midiTrackBg; QColor(220, 220, 220), // drumTrackBg; + QColor(220, 220, 220), // newDrumTrackBg; QColor(220, 220, 220), // waveTrackBg; QColor(189, 220, 193), // outputTrackBg; QColor(189, 220, 193), // inputTrackBg; @@ -178,13 +180,13 @@ GlobalConfigValues config = { QString("Mixer A"), QRect(0, 0, 300, 500), // Mixer1 true, true, true, true, - true, true, true, true + true, true, true, true, true }, { QString("Mixer B"), QRect(200, 200, 300, 500), // Mixer2 true, true, true, true, - true, true, true, true + true, true, true, true, true }, true, // TransportVisible; false, // BigTimeVisible; diff --git a/muse2/xpm/eye.xpm b/muse2/xpm/eye.xpm new file mode 100644 index 00000000..74e5bcc1 --- /dev/null +++ b/muse2/xpm/eye.xpm @@ -0,0 +1,22 @@ +/* XPM */ +static const char * eye_xpm[] = { +"16 16 3 1", +" c None", +". c #000000", +"+ c #0000FD", +" ", +" ", +" ", +" .... ", +" ........ ", +" ... ... ", +" ... ++++ ... ", +"... ++++++ ...", +".. ++++++ ..", +"... ++++++ ...", +" ... ++++ ... ", +" ... ... ", +" ........ ", +" .... ", +" ", +" "}; diff --git a/muse2/xpm/eye_crossed.xpm b/muse2/xpm/eye_crossed.xpm new file mode 100644 index 00000000..65dca19c --- /dev/null +++ b/muse2/xpm/eye_crossed.xpm @@ -0,0 +1,23 @@ +/* XPM */ +static const char * eye_crossed_xpm[] = { +"16 16 4 1", +" c None", +". c #E10E08", +"+ c #000000", +"@ c #0000FD", +" ", +" .. ", +" ....", +" ++++ .... ", +" ++++++.... ", +" +++ ....+ ", +" +++ @@....+++ ", +"+++ @@.... +++", +"++ @....@ ++", +"+++ ....@@ +++", +" +++....@@ +++ ", +" +.... +++ ", +" ....++++++ ", +" .... ++++ ", +" .. ", +" "}; diff --git a/muse2/xpm/eye_gray.xpm b/muse2/xpm/eye_gray.xpm new file mode 100644 index 00000000..8d5a7d9d --- /dev/null +++ b/muse2/xpm/eye_gray.xpm @@ -0,0 +1,22 @@ +/* XPM */ +static const char * eye_gray_xpm[] = { +"16 16 3 1", +" c None", +". c #292929", +"+ c #535353", +" ", +" ", +" ", +" .... ", +" ........ ", +" ... ... ", +" ... ++++ ... ", +"... ++++++ ...", +".. ++++++ ..", +"... ++++++ ...", +" ... ++++ ... ", +" ... ... ", +" ........ ", +" .... ", +" ", +" "}; |