diff options
Diffstat (limited to 'muse2')
40 files changed, 974 insertions, 406 deletions
diff --git a/muse2/ChangeLog b/muse2/ChangeLog index dca54595..f8c4da81 100644 --- a/muse2/ChangeLog +++ b/muse2/ChangeLog @@ -1,3 +1,9 @@ +27.10.2012: + * Improved: Velocity graphs. Icon for showing per-note or all velocities. Also found in Settings. (Tim) + * Improved: Piano KB has current selected note (yellow). For velocity/polyaftertouch/other per-note ctrls. (Tim) + - Bad timing warning now has "don't show again". (Tim) + - Added 'speaker' icon to drum edit. And drum list and piano keyboard now obey the 'speaker' icon. (Tim) + - TODO: Still W.I.P on the aftertouch stuff... 22.10.2012: - Oops, fixed regression: Re-add default managed controllers to midi ports at Song::clear. (Tim) - W.I.P. Preparations for Aftertouch and Poly Aftertouch (channel and key pressure) graph editing. (Tim) diff --git a/muse2/muse/arranger/tlist.cpp b/muse2/muse/arranger/tlist.cpp index b3be35ea..3bc13934 100644 --- a/muse2/muse/arranger/tlist.cpp +++ b/muse2/muse/arranger/tlist.cpp @@ -2497,181 +2497,186 @@ void TList::mouseReleaseEvent(QMouseEvent* ev) void TList::wheelEvent(QWheelEvent* ev) { - int x = ev->x(); - int y = ev->y(); - MusECore::Track* t = y2Track(y + ypos); - if (t == 0) { - emit redirectWheelEvent(ev); - return; - } - TrackColumn col = TrackColumn(header->logicalIndexAt(x)); - int delta = ev->delta() / WHEEL_DELTA; - ev->accept(); - - switch (col) { - case COL_RECORD: - case COL_NONE: - case COL_CLASS: - case COL_NAME: - case COL_AUTOMATION: - break; - case COL_MUTE: - // p3.3.29 - if (((QInputEvent*)ev)->modifiers() & Qt::ShiftModifier) - t->setOff(!t->off()); - else - { - if (t->off()) - t->setOff(false); - else - t->setMute(!t->mute()); - } - MusEGlobal::song->update(SC_MUTE); - break; - - case COL_SOLO: - MusEGlobal::audio->msgSetSolo(t, !t->solo()); - MusEGlobal::song->update(SC_SOLO); - break; - - case COL_TIMELOCK: - t->setLocked(!t->locked()); - break; - - case COL_OPORT: - if (t->isMidiTrack()) { - MusECore::MidiTrack* mt = (MusECore::MidiTrack*)t; - int port = mt->outPort() + delta; - - if (port >= MIDI_PORTS) - port = MIDI_PORTS-1; - else if (port < 0) - port = 0; - if (port != ((MusECore::MidiTrack*)t)->outPort()) { - MusEGlobal::audio->msgIdle(true); - mt->setOutPortAndUpdate(port); - MusEGlobal::audio->msgIdle(false); - - MusEGlobal::audio->msgUpdateSoloStates(); // p4.0.14 - MusEGlobal::song->update(SC_MIDI_TRACK_PROP); // p4.0.17 - } - } - break; - - case COL_OCHANNEL: - if (t->isMidiTrack()) { - MusECore::MidiTrack* mt = (MusECore::MidiTrack*)t; - if (mt && mt->type() == MusECore::Track::DRUM) - break; - - int channel = mt->outChannel() + delta; - - if (channel >= MIDI_CHANNELS) - channel = MIDI_CHANNELS-1; - else if (channel < 0) - channel = 0; - if (channel != ((MusECore::MidiTrack*)t)->outChannel()) { - MusEGlobal::audio->msgIdle(true); - mt->setOutChanAndUpdate(channel); - MusEGlobal::audio->msgIdle(false); - - // may result in adding/removing mixer strip: - //MusEGlobal::song->update(-1); - MusEGlobal::audio->msgUpdateSoloStates(); // p4.0.14 - MusEGlobal::song->update(SC_MIDI_TRACK_PROP); - } - } - else { - int n = t->channels() + delta; - if (n > MAX_CHANNELS) - n = MAX_CHANNELS; - else if (n < 1) - n = 1; - if (n != t->channels()) { - MusEGlobal::audio->msgSetChannels((MusECore::AudioTrack*)t, n); - MusEGlobal::song->update(SC_CHANNELS); - } - } - break; - default: - if (col>=COL_CUSTOM_MIDICTRL_OFFSET) - { - mode = START_DRAG; - - if (t->isMidiTrack()) - { - MusECore::MidiTrack* mt = dynamic_cast<MusECore::MidiTrack*>(t); - if (mt == 0) - break; - - int ctrl_num = Arranger::custom_columns[col-COL_CUSTOM_MIDICTRL_OFFSET].ctrl; - - MusECore::MidiPort* mp = &MusEGlobal::midiPorts[mt->outPort()]; - MusECore::MidiController* mctl = mp->midiController(ctrl_num); - - int minval=mctl->minVal()+mctl->bias(); - int maxval=mctl->maxVal()+mctl->bias(); - - int val = mt->getControllerChangeAtTick(0,ctrl_num); - int oldval=val; - - if (ctrl_num!=MusECore::CTRL_PROGRAM) - { - val += delta; - if(val > maxval) - val = maxval; - if(val < minval-1) // "-1" because of "off" - val = minval-1; - } - else - { - MusECore::MidiInstrument* instr = mp->instrument(); - if (delta>0) val=instr->getNextPatch(mt->outChannel(), val, false); - else if (delta<0) val=instr->getPrevPatch(mt->outChannel(), val, false); - } - - if (val != oldval) - { - if (val!=minval-1) - { - int at_tick; - if (Arranger::custom_columns[col-COL_CUSTOM_MIDICTRL_OFFSET].affected_pos == - Arranger::custom_col_t::AFFECT_BEGIN) - at_tick=0; - else - at_tick=MusEGlobal::song->cpos(); - - record_controller_change_and_maybe_send(at_tick, ctrl_num, val, mt); - } - else - { - MusECore::Undo operations; - for (MusECore::iPart p = mt->parts()->begin(); p!=mt->parts()->end(); p++) - { - if (p->second->tick()==0) - { - for (MusECore::iEvent ev=p->second->events()->begin(); ev!=p->second->events()->end(); ev++) - { - if (ev->second.tick()!=0) break; - else if (ev->second.type()==MusECore::Controller && ev->second.dataA()==ctrl_num) - { - using MusECore::UndoOp; - operations.push_back(UndoOp(UndoOp::DeleteEvent, ev->second, p->second, false, false)); - break; - } - } - } - } - MusEGlobal::song->applyOperationGroup(operations); - } - } - } - } - else - mode = START_DRAG; - - break; - } + emit redirectWheelEvent(ev); + +// REMOVE Tim. Hate to just kill all this, so remove later if all tests OK. +// int x = ev->x(); +// int y = ev->y(); +// MusECore::Track* t = y2Track(y + ypos); +// if (t == 0) { +// emit redirectWheelEvent(ev); +// return; +// } +// +// TrackColumn col = TrackColumn(header->logicalIndexAt(x)); +// int delta = ev->delta() / WHEEL_DELTA; +// ev->accept(); +// +// switch (col) { +// case COL_RECORD: +// case COL_NONE: +// case COL_CLASS: +// case COL_NAME: +// case COL_AUTOMATION: +// break; +// case COL_MUTE: +// // p3.3.29 +// if (((QInputEvent*)ev)->modifiers() & Qt::ShiftModifier) +// t->setOff(!t->off()); +// else +// { +// if (t->off()) +// t->setOff(false); +// else +// t->setMute(!t->mute()); +// } +// MusEGlobal::song->update(SC_MUTE); +// break; +// +// case COL_SOLO: +// MusEGlobal::audio->msgSetSolo(t, !t->solo()); +// MusEGlobal::song->update(SC_SOLO); +// break; +// +// case COL_TIMELOCK: +// t->setLocked(!t->locked()); +// break; +// +// case COL_OPORT: +// if (t->isMidiTrack()) { +// MusECore::MidiTrack* mt = (MusECore::MidiTrack*)t; +// int port = mt->outPort() + delta; +// +// if (port >= MIDI_PORTS) +// port = MIDI_PORTS-1; +// else if (port < 0) +// port = 0; +// if (port != ((MusECore::MidiTrack*)t)->outPort()) { +// MusEGlobal::audio->msgIdle(true); +// mt->setOutPortAndUpdate(port); +// MusEGlobal::audio->msgIdle(false); +// +// MusEGlobal::audio->msgUpdateSoloStates(); // p4.0.14 +// MusEGlobal::song->update(SC_MIDI_TRACK_PROP); // p4.0.17 +// } +// } +// break; +// +// case COL_OCHANNEL: +// if (t->isMidiTrack()) { +// MusECore::MidiTrack* mt = (MusECore::MidiTrack*)t; +// if (mt && mt->type() == MusECore::Track::DRUM) +// break; +// +// int channel = mt->outChannel() + delta; +// +// if (channel >= MIDI_CHANNELS) +// channel = MIDI_CHANNELS-1; +// else if (channel < 0) +// channel = 0; +// if (channel != ((MusECore::MidiTrack*)t)->outChannel()) { +// MusEGlobal::audio->msgIdle(true); +// mt->setOutChanAndUpdate(channel); +// MusEGlobal::audio->msgIdle(false); +// +// // may result in adding/removing mixer strip: +// //MusEGlobal::song->update(-1); +// MusEGlobal::audio->msgUpdateSoloStates(); // p4.0.14 +// MusEGlobal::song->update(SC_MIDI_TRACK_PROP); +// } +// } +// else { +// int n = t->channels() + delta; +// if (n > MAX_CHANNELS) +// n = MAX_CHANNELS; +// else if (n < 1) +// n = 1; +// if (n != t->channels()) { +// MusEGlobal::audio->msgSetChannels((MusECore::AudioTrack*)t, n); +// MusEGlobal::song->update(SC_CHANNELS); +// } +// } +// break; +// default: +// if (col>=COL_CUSTOM_MIDICTRL_OFFSET) +// { +// mode = START_DRAG; +// +// if (t->isMidiTrack()) +// { +// MusECore::MidiTrack* mt = dynamic_cast<MusECore::MidiTrack*>(t); +// if (mt == 0) +// break; +// +// int ctrl_num = Arranger::custom_columns[col-COL_CUSTOM_MIDICTRL_OFFSET].ctrl; +// +// MusECore::MidiPort* mp = &MusEGlobal::midiPorts[mt->outPort()]; +// MusECore::MidiController* mctl = mp->midiController(ctrl_num); +// +// int minval=mctl->minVal()+mctl->bias(); +// int maxval=mctl->maxVal()+mctl->bias(); +// +// int val = mt->getControllerChangeAtTick(0,ctrl_num); +// int oldval=val; +// +// if (ctrl_num!=MusECore::CTRL_PROGRAM) +// { +// val += delta; +// if(val > maxval) +// val = maxval; +// if(val < minval-1) // "-1" because of "off" +// val = minval-1; +// } +// else +// { +// MusECore::MidiInstrument* instr = mp->instrument(); +// if (delta>0) val=instr->getNextPatch(mt->outChannel(), val, false); +// else if (delta<0) val=instr->getPrevPatch(mt->outChannel(), val, false); +// } +// +// if (val != oldval) +// { +// if (val!=minval-1) +// { +// int at_tick; +// if (Arranger::custom_columns[col-COL_CUSTOM_MIDICTRL_OFFSET].affected_pos == +// Arranger::custom_col_t::AFFECT_BEGIN) +// at_tick=0; +// else +// at_tick=MusEGlobal::song->cpos(); +// +// record_controller_change_and_maybe_send(at_tick, ctrl_num, val, mt); +// } +// else +// { +// MusECore::Undo operations; +// for (MusECore::iPart p = mt->parts()->begin(); p!=mt->parts()->end(); p++) +// { +// if (p->second->tick()==0) +// { +// for (MusECore::iEvent ev=p->second->events()->begin(); ev!=p->second->events()->end(); ev++) +// { +// if (ev->second.tick()!=0) break; +// else if (ev->second.type()==MusECore::Controller && ev->second.dataA()==ctrl_num) +// { +// using MusECore::UndoOp; +// operations.push_back(UndoOp(UndoOp::DeleteEvent, ev->second, p->second, false, false)); +// break; +// } +// } +// } +// } +// MusEGlobal::song->applyOperationGroup(operations); +// } +// } +// } +// } +// else +// mode = START_DRAG; +// +// break; +// } + } diff --git a/muse2/muse/conf.cpp b/muse2/muse/conf.cpp index 4c14cff0..54a02265 100644 --- a/muse2/muse/conf.cpp +++ b/muse2/muse/conf.cpp @@ -894,6 +894,8 @@ void readConfiguration(Xml& xml, bool doReadMidiPortConfig, bool doReadGlobalCon MusEGlobal::config.warnInitPending = xml.parseInt(); else if (tag == "midiSendCtlDefaults") MusEGlobal::config.midiSendCtlDefaults = xml.parseInt(); + else if (tag == "warnIfBadTiming") + MusEGlobal::config.warnIfBadTiming = xml.parseInt(); else if (tag == "minMeter") MusEGlobal::config.minMeter = xml.parseInt(); else if (tag == "minSlider") @@ -946,6 +948,8 @@ void readConfiguration(Xml& xml, bool doReadMidiPortConfig, bool doReadGlobalCon MusEGlobal::config.unhideTracks = xml.parseInt(); else if (tag == "smartFocus") MusEGlobal::config.smartFocus = xml.parseInt(); + else if (tag == "velocityPerNote") + MusEGlobal::config.velocityPerNote = xml.parseInt(); else if (tag == "plugin_groups") MusEGlobal::readPluginGroupConfiguration(xml); @@ -1215,6 +1219,7 @@ void MusE::writeGlobalConfiguration(int level, MusECore::Xml& xml) const xml.intTag(level, "midiSendInit", MusEGlobal::config.midiSendInit); xml.intTag(level, "warnInitPending", MusEGlobal::config.warnInitPending); xml.intTag(level, "midiSendCtlDefaults", MusEGlobal::config.midiSendCtlDefaults); + xml.intTag(level, "warnIfBadTiming", MusEGlobal::config.warnIfBadTiming); xml.intTag(level, "minMeter", MusEGlobal::config.minMeter); xml.doubleTag(level, "minSlider", MusEGlobal::config.minSlider); xml.intTag(level, "freewheelMode", MusEGlobal::config.freewheelMode); @@ -1266,6 +1271,7 @@ void MusE::writeGlobalConfiguration(int level, MusECore::Xml& xml) const xml.intTag(level, "leftMouseButtonCanDecrease", MusEGlobal::config.leftMouseButtonCanDecrease); xml.intTag(level, "rangeMarkerWithoutMMB", MusEGlobal::config.rangeMarkerWithoutMMB); xml.intTag(level, "smartFocus", MusEGlobal::config.smartFocus); + xml.intTag(level, "velocityPerNote", MusEGlobal::config.velocityPerNote); xml.intTag(level, "unhideTracks", MusEGlobal::config.unhideTracks); xml.intTag(level, "addHiddenTracks", MusEGlobal::config.addHiddenTracks); diff --git a/muse2/muse/ctrl/ctrlcanvas.cpp b/muse2/muse/ctrl/ctrlcanvas.cpp index 1774174f..6e92f3c6 100644 --- a/muse2/muse/ctrl/ctrlcanvas.cpp +++ b/muse2/muse/ctrl/ctrlcanvas.cpp @@ -511,16 +511,14 @@ void CtrlCanvas::partControllers(const MusECore::MidiPart* part, int num, int* d int di; int n; - if(!mt->isDrumTrack() && curDrumPitch != -1) - printf("keyfilter != -1 in non drum track?\n"); - if((mt->type() == MusECore::Track::DRUM) && (curDrumPitch >= 0) && ((num & 0xff) == 0xff)) { di = (num & ~0xff) | curDrumPitch; n = (num & ~0xff) | MusEGlobal::drumMap[curDrumPitch].anote; // construct real controller number mp = &MusEGlobal::midiPorts[MusEGlobal::drumMap[curDrumPitch].port]; } - else if ((mt->type() == MusECore::Track::NEW_DRUM) && (curDrumPitch >= 0) && ((num & 0xff) == 0xff)) //FINDMICHJETZT does this work? + else if ((mt->type() == MusECore::Track::NEW_DRUM || mt->type() == MusECore::Track::MIDI) && + (curDrumPitch >= 0) && ((num & 0xff) == 0xff)) //FINDMICHJETZT does this work? { di = (num & ~0xff) | curDrumPitch; n = (num & ~0xff) | curDrumPitch; @@ -599,12 +597,8 @@ void CtrlCanvas::updateItems() if(_cnum == MusECore::CTRL_VELOCITY && e.type() == MusECore::Note) { newev = 0; - if (curDrumPitch == -1) // and NOT >=0 - { - // This is interesting - it would allow ALL drum note velocities to be shown. - // But currently the drum list ALWAYS has a selected item so this is not supposed to happen. + if (curDrumPitch == -1 || !MusEGlobal::config.velocityPerNote) // and NOT >=0 items.add(newev = new CEvent(e, part, e.velo())); - } else if (e.dataA() == curDrumPitch) //same note. if curDrumPitch==-2, this never is true items.add(newev = new CEvent(e, part, e.velo())); if(newev && e.selected()) @@ -615,32 +609,16 @@ void CtrlCanvas::updateItems() int ctl = e.dataA(); if(part->track() && part->track()->type() == MusECore::Track::DRUM && (_cnum & 0xff) == 0xff) { - //MusECore::MidiPort* port = &MusEGlobal::midiPorts[part->track()->outPort()]; if(curDrumPitch < 0) - //if(curDrumPitch >= 0) continue; - //{ - //MusECore::MidiPort* port = &MusEGlobal::midiPorts[MusEGlobal::drumMap[curDrumPitch].port]; - //MusECore::MidiPort* port = &MusEGlobal::midiPorts[MusEGlobal::drumMap[ctl & 0x7f].port]; - int port = MusEGlobal::drumMap[ctl & 0x7f].port; - int chan = MusEGlobal::drumMap[ctl & 0x7f].channel; - //MusECore::MidiPort* cur_port = &MusEGlobal::midiPorts[MusEGlobal::drumMap[curDrumPitch].port]; - int cur_port = MusEGlobal::drumMap[curDrumPitch].port; - int cur_chan = MusEGlobal::drumMap[curDrumPitch].channel; - if((port != cur_port) || (chan != cur_chan)) - continue; - // Is it a drum controller event, according to the track port's instrument? - //MusECore::MidiController *mc = port->drumController(ctl); - //if(!mc) - // continue; - //if(mc) - //{ - //if(MusEGlobal::drumMap[ctl & 0x7f].channel != e. - // continue; - ctl = (ctl & ~0xff) | MusEGlobal::drumMap[ctl & 0x7f].anote; - //} - //} + int port = MusEGlobal::drumMap[ctl & 0x7f].port; + int chan = MusEGlobal::drumMap[ctl & 0x7f].channel; + int cur_port = MusEGlobal::drumMap[curDrumPitch].port; + int cur_chan = MusEGlobal::drumMap[curDrumPitch].channel; + if((port != cur_port) || (chan != cur_chan)) + continue; + ctl = (ctl & ~0xff) | MusEGlobal::drumMap[ctl & 0x7f].anote; } if(ctl == _dnum) { diff --git a/muse2/muse/ctrl/ctrlpanel.cpp b/muse2/muse/ctrl/ctrlpanel.cpp index c6adc778..8e380356 100644 --- a/muse2/muse/ctrl/ctrlpanel.cpp +++ b/muse2/muse/ctrl/ctrlpanel.cpp @@ -57,6 +57,7 @@ #include "menutitleitem.h" #include "popupmenu.h" #include "helper.h" +#include "pixmap_button.h" namespace MusEGui { @@ -87,7 +88,7 @@ CtrlPanel::CtrlPanel(QWidget* parent, MidiEditor* e, CtrlCanvas* c, const char* kbox->setContentsMargins(0, 0, 0, 0); dbox->setContentsMargins(0, 0, 0, 0); - selCtrl = new QPushButton(tr("S")); + selCtrl = new QPushButton(tr("S"), this); selCtrl->setFocusPolicy(Qt::NoFocus); selCtrl->setFont(MusEGlobal::config.fonts[3]); selCtrl->setFixedHeight(20); @@ -96,7 +97,7 @@ CtrlPanel::CtrlPanel(QWidget* parent, MidiEditor* e, CtrlCanvas* c, const char* selCtrl->setToolTip(tr("select controller")); // destroy button - QPushButton* destroy = new QPushButton(tr("X")); + QPushButton* destroy = new QPushButton(tr("X"), this); destroy->setFocusPolicy(Qt::NoFocus); destroy->setFont(MusEGlobal::config.fonts[3]); destroy->setFixedHeight(20); @@ -112,7 +113,7 @@ CtrlPanel::CtrlPanel(QWidget* parent, MidiEditor* e, CtrlCanvas* c, const char* _val = MusECore::CTRL_VAL_UNKNOWN; _dnum = -1; - _knob = new MusEGui::Knob; + _knob = new Knob(this); _knob->setFixedWidth(25); _knob->setFixedHeight(25); _knob->setToolTip(tr("manual adjust")); @@ -122,7 +123,7 @@ CtrlPanel::CtrlPanel(QWidget* parent, MidiEditor* e, CtrlCanvas* c, const char* _knob->hide(); _knob->setAltFaceColor(Qt::red); - _dl = new MusEGui::DoubleLabel(-1.0, 0.0, +127.0); + _dl = new DoubleLabel(-1.0, 0.0, +127.0, this); _dl->setPrecision(0); _dl->setToolTip(tr("ctrl-double-click on/off")); _dl->setSpecialText(tr("off")); @@ -139,16 +140,28 @@ CtrlPanel::CtrlPanel(QWidget* parent, MidiEditor* e, CtrlCanvas* c, const char* connect(_dl, SIGNAL(valueChanged(double,int)), SLOT(ctrlChanged(double))); connect(_dl, SIGNAL(ctrlDoubleClicked(int)), SLOT(labelDoubleClicked())); + _veloPerNoteButton = new PixmapButton(veloPerNote_OnIcon, veloPerNote_OffIcon, 2, this); // Margin = 2 + _veloPerNoteButton->setFocusPolicy(Qt::NoFocus); + _veloPerNoteButton->setCheckable(true); + _veloPerNoteButton->setToolTip(tr("all/per-note velocity mode")); + _veloPerNoteButton->setEnabled(false); + _veloPerNoteButton->hide(); + connect(_veloPerNoteButton, SIGNAL(clicked()), SLOT(velPerNoteClicked())); + bbox->addStretch(); bbox->addWidget(selCtrl); bbox->addWidget(destroy); bbox->addStretch(); kbox->addStretch(); kbox->addWidget(_knob); + kbox->addWidget(_veloPerNoteButton); kbox->addStretch(); dbox->addStretch(); dbox->addWidget(_dl); dbox->addStretch(); + + connect(MusEGlobal::song, SIGNAL(songChanged(MusECore::SongChangedFlags_t)), SLOT(songChanged(MusECore::SongChangedFlags_t))); + connect(MusEGlobal::muse, SIGNAL(configChanged()), SLOT(configChanged())); connect(MusEGlobal::heartBeatTimer, SIGNAL(timeout()), SLOT(heartBeat())); inHeartBeat = false; setLayout(vbox); @@ -227,6 +240,35 @@ void CtrlPanel::heartBeat() } //--------------------------------------------------------- +// configChanged +//--------------------------------------------------------- + +void CtrlPanel::configChanged() +{ + songChanged(SC_CONFIG); +} + +//--------------------------------------------------------- +// songChanged +//--------------------------------------------------------- + +void CtrlPanel::songChanged(MusECore::SongChangedFlags_t type) +{ + if(editor->deleting()) // Ignore while while deleting to prevent crash. + return; + + // Is it simply a midi controller value adjustment? Forget it. + if(type == SC_MIDI_CONTROLLER) + return; + + if(type & SC_CONFIG) + { + if(_veloPerNoteButton->isChecked() != MusEGlobal::config.velocityPerNote) + _veloPerNoteButton->setChecked(MusEGlobal::config.velocityPerNote); + } +} + +//--------------------------------------------------------- // labelDoubleClicked //--------------------------------------------------------- @@ -424,7 +466,7 @@ void CtrlPanel::setHWController(MusECore::MidiTrack* t, MusECore::MidiController mp = &MusEGlobal::midiPorts[MusEGlobal::drumMap[cdp].port]; ch = MusEGlobal::drumMap[cdp].channel; } - else if(_track->type() == MusECore::Track::NEW_DRUM && ((_dnum & 0xff) == 0xff) && cdp != -1) + else if((_track->type() == MusECore::Track::NEW_DRUM || _track->type() == MusECore::Track::MIDI) && ((_dnum & 0xff) == 0xff) && cdp != -1) { _dnum = (_dnum & ~0xff) | cdp; //FINDMICHJETZT does that work? mp = &MusEGlobal::midiPorts[_track->outPort()]; @@ -442,11 +484,15 @@ void CtrlPanel::setHWController(MusECore::MidiTrack* t, MusECore::MidiController _dl->setEnabled(false); _knob->hide(); _dl->hide(); + _veloPerNoteButton->setEnabled(true); + _veloPerNoteButton->show(); } else { _knob->setEnabled(true); _dl->setEnabled(true); + _veloPerNoteButton->setEnabled(false); + _veloPerNoteButton->hide(); double dlv; int mn; int mx; int v; if(_dnum == MusECore::CTRL_PROGRAM) @@ -573,7 +619,7 @@ void CtrlPanel::ctrlPopupTriggered(QAction* act) MusECore::MidiPort* port = &MusEGlobal::midiPorts[track->outPort()]; int curDrumPitch = ctrlcanvas->getCurDrumPitch(); bool isDrum = track->type() == MusECore::Track::DRUM; - bool isNewDrum = track->type() == MusECore::Track::NEW_DRUM; + bool isNewDrum = (track->type() == MusECore::Track::NEW_DRUM) || (track->type() == MusECore::Track::MIDI); MusECore::MidiInstrument* instr = port->instrument(); MusECore::MidiControllerList* mcl = instr->controller(); @@ -586,20 +632,12 @@ void CtrlPanel::ctrlPopupTriggered(QAction* act) const int edit_ins = max + 3; const int velo = max + 0x101; - const int polyafter = max + 0x102; - const int after = max + 0x103; int rv = act->data().toInt(); if (rv == velo) { // special case velocity emit controllerChanged(MusECore::CTRL_VELOCITY); } - else if (rv == polyafter) { // special case - emit controllerChanged(MusECore::CTRL_POLYAFTER); - } - else if (rv == after) { // special case - emit controllerChanged(MusECore::CTRL_AFTERTOUCH); - } else if (rv == add_ins_def) { // add new instrument controller PopupMenu * ctrlSubPop = new PopupMenu(this, true); // true = enable stay open @@ -736,5 +774,18 @@ void CtrlPanel::ctrlRightClicked(const QPoint& p, int /*id*/) MusEGlobal::song->execMidiAutomationCtlPopup(0, part, p, ctlnum); } +//--------------------------------------------------------- +// velPerNoteClicked +//--------------------------------------------------------- + +void CtrlPanel::velPerNoteClicked() +{ + if(MusEGlobal::config.velocityPerNote != _veloPerNoteButton->isChecked()) + { + MusEGlobal::config.velocityPerNote = _veloPerNoteButton->isChecked(); + MusEGlobal::muse->changeConfig(false); // Save settings? No, wait till close. + } +} + } // namespace MusEGui diff --git a/muse2/muse/ctrl/ctrlpanel.h b/muse2/muse/ctrl/ctrlpanel.h index 58b8d8c7..261f982f 100644 --- a/muse2/muse/ctrl/ctrlpanel.h +++ b/muse2/muse/ctrl/ctrlpanel.h @@ -25,6 +25,8 @@ #include <QWidget> +#include "type_defs.h" + class QPushButton; class QAction; @@ -39,6 +41,7 @@ class DoubleLabel; class Knob; class MidiEditor; class CtrlCanvas; +class PixmapButton; //--------------------------------------------------------- // CtrlPanel @@ -58,8 +61,7 @@ class CtrlPanel: public QWidget { MusEGui::Knob* _knob; MusEGui::DoubleLabel* _dl; int _val; - - + PixmapButton* _veloPerNoteButton; signals: void destroyPanel(); @@ -70,6 +72,9 @@ class CtrlPanel: public QWidget { void labelDoubleClicked(); void ctrlRightClicked(const QPoint& p, int id); void ctrlPopupTriggered(QAction* act); + void velPerNoteClicked(); + void songChanged(MusECore::SongChangedFlags_t type); + void configChanged(); protected slots: virtual void heartBeat(); diff --git a/muse2/muse/driver/alsamidi.cpp b/muse2/muse/driver/alsamidi.cpp index 80595fb0..f140224c 100644 --- a/muse2/muse/driver/alsamidi.cpp +++ b/muse2/muse/driver/alsamidi.cpp @@ -327,6 +327,11 @@ bool MidiAlsaDevice::putMidiEvent(const MidiPlayEvent& e) snd_seq_ev_set_pitchbend(&event, chn, b); break; } + else if((a | 0xff) == CTRL_POLYAFTER) + { + snd_seq_ev_set_keypress(&event, chn, a & 0x7f, b & 0x7f); + break; + } else if(a == CTRL_AFTERTOUCH) { snd_seq_ev_set_chanpress(&event, chn, b); diff --git a/muse2/muse/driver/jackmidi.cpp b/muse2/muse/driver/jackmidi.cpp index a088290a..7306b93c 100644 --- a/muse2/muse/driver/jackmidi.cpp +++ b/muse2/muse/driver/jackmidi.cpp @@ -846,7 +846,13 @@ bool MidiJackDevice::processEvent(const MidiPlayEvent& event) } } - if(a == CTRL_AFTERTOUCH) + if((a | 0xff) == CTRL_POLYAFTER) + { + //printf("MidiJackDevice::processEvent CTRL_AFTERTOUCH v:%d time:%d type:%d ch:%d A:%d B:%d\n", v, event.time(), event.type(), event.channel(), event.dataA(), event.dataB()); + if(!queueEvent(MidiPlayEvent(t, port, chn, ME_POLYAFTER, a & 0x7f, b & 0x7f))) + return false; + } + else if(a == CTRL_AFTERTOUCH) { //printf("MidiJackDevice::processEvent CTRL_AFTERTOUCH v:%d time:%d type:%d ch:%d A:%d B:%d\n", v, event.time(), event.type(), event.channel(), event.dataA(), event.dataB()); if(!queueEvent(MidiPlayEvent(t, port, chn, ME_AFTERTOUCH, b & 0x7f, 0))) diff --git a/muse2/muse/gconfig.cpp b/muse2/muse/gconfig.cpp index c88c3fc5..0da8ccf7 100644 --- a/muse2/muse/gconfig.cpp +++ b/muse2/muse/gconfig.cpp @@ -26,7 +26,7 @@ namespace MusEGlobal { GlobalConfigValues config = { - 190, // globalAlphaBlend + 170, // globalAlphaBlend { QColor(0xff, 0xff, 0xff), // palette QColor(0xff, 0xff, 0xff), @@ -130,6 +130,8 @@ GlobalConfigValues config = { true, // midiSendInit Send instrument initialization sequences true, // warnInitPending Warn instrument initialization sequences pending false, // midiSendCtlDefaults Send instrument controller defaults at position 0 if none in song + true, // warnIfBadTiming Warn if timer res not good + false, // velocityPerNote Whether to show per-note or all velocities -60, // int minMeter; -60.0, // double minSlider; false, // use Jack freewheel diff --git a/muse2/muse/gconfig.h b/muse2/muse/gconfig.h index 6fa85846..af45ed92 100644 --- a/muse2/muse/gconfig.h +++ b/muse2/muse/gconfig.h @@ -139,6 +139,8 @@ struct GlobalConfigValues { bool midiSendInit; // Send instrument initialization sequences bool warnInitPending; // Warn instrument initialization sequences pending bool midiSendCtlDefaults; // Send instrument controller defaults at position 0 if none in song + bool warnIfBadTiming; // Warn if timer res not good + bool velocityPerNote; // Whether to show per-note or all velocities int minMeter; double minSlider; bool freewheelMode; diff --git a/muse2/muse/helper.cpp b/muse2/muse/helper.cpp index 986d38aa..e2186af9 100644 --- a/muse2/muse/helper.cpp +++ b/muse2/muse/helper.cpp @@ -888,7 +888,7 @@ int populateMidiCtrlMenu(PopupMenu* menu, MusECore::PartList* part_list, MusECor int channel = track->outChannel(); MusECore::MidiPort* port = &MusEGlobal::midiPorts[track->outPort()]; bool isDrum = track->type() == MusECore::Track::DRUM; - bool isNewDrum = track->type() == MusECore::Track::NEW_DRUM; + bool isNewDrum = (track->type() == MusECore::Track::NEW_DRUM) || (track->type() == MusECore::Track::MIDI); MusECore::MidiInstrument* instr = port->instrument(); MusECore::MidiControllerList* mcl = instr->controller(); @@ -1030,18 +1030,6 @@ int populateMidiCtrlMenu(PopupMenu* menu, MusECore::PartList* part_list, MusECor est_width = fmw; menu->addAction(stext)->setData(velo); -// stext = QWidget::tr("PolyAftertouch"); -// fmw = menu->fontMetrics().width(stext); -// if(fmw > est_width) -// est_width = fmw; -// menu->addAction(stext)->setData(polyafter); -// -// stext = QWidget::tr("Aftertouch"); -// fmw = menu->fontMetrics().width(stext); -// if(fmw > est_width) -// est_width = fmw; -// menu->addAction(stext)->setData(after); - // Add global default controllers (all controllers not found in instrument). for (isList i = sList.begin(); i != sList.end(); ++i) { diff --git a/muse2/muse/icons.cpp b/muse2/muse/icons.cpp index dab1067b..a3dfbf50 100644 --- a/muse2/muse/icons.cpp +++ b/muse2/muse/icons.cpp @@ -212,6 +212,8 @@ #include "xpm/initS.xpm" #include "xpm/delta_on.xpm" #include "xpm/delta_off.xpm" +#include "xpm/velo_all.xpm" +#include "xpm/velo_per_note.xpm" #include "xpm/addtrack_addmiditrack.xpm" #include "xpm/addtrack_audiogroup.xpm" @@ -294,6 +296,8 @@ QPixmap* mixerAudioSIcon; QPixmap* initSIcon; QPixmap* deltaOnIcon; QPixmap* deltaOffIcon; +QPixmap* veloPerNote_OnIcon; +QPixmap* veloPerNote_OffIcon; QPixmap* exitIcon; QPixmap* exit1Icon; @@ -678,6 +682,8 @@ void initIcons() initSIcon = new MPIXMAP(initS_xpm, NULL); deltaOnIcon = new MPIXMAP(delta_on_xpm, NULL); deltaOffIcon = new MPIXMAP(delta_off_xpm, NULL); + veloPerNote_OnIcon = new MPIXMAP(velo_per_note_xpm, NULL); + veloPerNote_OffIcon = new MPIXMAP(velo_all_xpm, NULL); addtrack_addmiditrackIcon = new MPIXMAP(addtrack_addmiditrack_xpm, NULL); addtrack_audiogroupIcon = new MPIXMAP(addtrack_audiogroup_xpm, NULL); @@ -917,6 +923,8 @@ void deleteIcons() delete initSIcon; delete deltaOnIcon; delete deltaOffIcon; + delete veloPerNote_OnIcon; + delete veloPerNote_OffIcon; delete addtrack_addmiditrackIcon; delete addtrack_audiogroupIcon; diff --git a/muse2/muse/icons.h b/muse2/muse/icons.h index a6c95577..36a780ae 100644 --- a/muse2/muse/icons.h +++ b/muse2/muse/icons.h @@ -195,6 +195,8 @@ extern QPixmap* mixerAudioSIcon; extern QPixmap* initSIcon; extern QPixmap* deltaOnIcon; extern QPixmap* deltaOffIcon; +extern QPixmap* veloPerNote_OnIcon; +extern QPixmap* veloPerNote_OffIcon; extern QPixmap* addtrack_addmiditrackIcon; extern QPixmap* addtrack_audiogroupIcon; diff --git a/muse2/muse/midictrl.cpp b/muse2/muse/midictrl.cpp index 2cf4f790..b87ea8d1 100644 --- a/muse2/muse/midictrl.cpp +++ b/muse2/muse/midictrl.cpp @@ -87,9 +87,6 @@ static MidiController programCtrl("Program", CTRL_PROGRAM, 0, 0xf static MidiController mastervolCtrl("MasterVolume", CTRL_MASTER_VOLUME, 0, 0x3fff, 0x3000); static MidiController volumeCtrl("MainVolume", CTRL_VOLUME, 0, 127, 100); static MidiController panCtrl("Pan", CTRL_PANPOT, -64, 63, 0); -static MidiController polyAfterCtrl("PolyAftertouch", CTRL_POLYAFTER, 0, 127, 0); -static MidiController afterCtrl("Aftertouch", CTRL_AFTERTOUCH, 0, 127, 0); - //--------------------------------------------------------- // ctrlType2Int @@ -149,8 +146,6 @@ const QString& int2ctrlType(int n) void initMidiController() { defaultMidiController.add(&veloCtrl); - defaultMidiController.add(&polyAfterCtrl); - defaultMidiController.add(&afterCtrl); defaultMidiController.add(&pitchCtrl); defaultMidiController.add(&programCtrl); defaultMidiController.add(&mastervolCtrl); @@ -432,7 +427,7 @@ void MidiController::updateBias() void MidiController::write(int level, Xml& xml) const { ControllerType t = midiControllerType(_num); - if(t == Velo || t == PolyAftertouch || t == Aftertouch) + if(t == Velo) return; QString type(int2ctrlType(t)); @@ -475,10 +470,16 @@ void MidiController::write(int level, Xml& xml) const mn = -8192; mx = 8191; break; - case Program: - case Velo: // Cannot happen case PolyAftertouch: + mn = 0; + mx = 127; + break; case Aftertouch: + mn = 0; + mx = 127; + break; + case Program: + case Velo: // Cannot happen break; } @@ -599,9 +600,21 @@ void MidiController::read(Xml& xml) _maxVal = 0xffffff; _num = CTRL_PROGRAM; break; - case Velo: // cannot happen case PolyAftertouch: + if (_maxVal == NOT_SET) + _maxVal = 127; + if (_minVal == NOT_SET) + _minVal = 0; + _num = CTRL_POLYAFTER; + break; case Aftertouch: + if (_maxVal == NOT_SET) + _maxVal = 127; + if (_minVal == NOT_SET) + _minVal = 0; + _num = CTRL_AFTERTOUCH; + break; + case Velo: // cannot happen break; } if (_minVal == NOT_SET) diff --git a/muse2/muse/midictrl.h b/muse2/muse/midictrl.h index 5e197dc0..5ff3f129 100644 --- a/muse2/muse/midictrl.h +++ b/muse2/muse/midictrl.h @@ -81,11 +81,13 @@ const int CTRL_LOCAL_OFF = 0x7a; // 122 const int CTRL_INTERNAL_OFFSET = 0x40000; const int CTRL_PITCH = CTRL_INTERNAL_OFFSET; -const int CTRL_PROGRAM = CTRL_INTERNAL_OFFSET + 1; -const int CTRL_VELOCITY = CTRL_INTERNAL_OFFSET + 2; -const int CTRL_MASTER_VOLUME = CTRL_INTERNAL_OFFSET + 3; -const int CTRL_POLYAFTER = CTRL_INTERNAL_OFFSET + 4; -const int CTRL_AFTERTOUCH = CTRL_INTERNAL_OFFSET + 5; +const int CTRL_PROGRAM = CTRL_INTERNAL_OFFSET + 0x01; +const int CTRL_VELOCITY = CTRL_INTERNAL_OFFSET + 0x02; +const int CTRL_MASTER_VOLUME = CTRL_INTERNAL_OFFSET + 0x03; +const int CTRL_AFTERTOUCH = CTRL_INTERNAL_OFFSET + 0x04; +// NOTE: The range from CTRL_INTERNAL_OFFSET + 0x100 to CTRL_INTERNAL_OFFSET + 0x1ff is reserved +// for this control. (The low byte is reserved because this is a per-note control.) +const int CTRL_POLYAFTER = CTRL_INTERNAL_OFFSET + 0x1FF; // 100 to 1FF ! const int CTRL_VAL_UNKNOWN = 0x10000000; // used as unknown hwVal diff --git a/muse2/muse/mididev.cpp b/muse2/muse/mididev.cpp index 96fee89a..3703def2 100644 --- a/muse2/muse/mididev.cpp +++ b/muse2/muse/mididev.cpp @@ -456,6 +456,9 @@ bool MidiDevice::putEvent(const MidiPlayEvent& ev) if (a == CTRL_PITCH) { return putMidiEvent(MidiPlayEvent(t, port, chn, ME_PITCHBEND, b, 0)); } + if ((a | 0xff) == CTRL_POLYAFTER) { + return putMidiEvent(MidiPlayEvent(t, port, chn, ME_POLYAFTER, a & 0x7f, b & 0x7f)); + } if (a == CTRL_AFTERTOUCH) { return putMidiEvent(MidiPlayEvent(t, port, chn, ME_AFTERTOUCH, b, 0)); } diff --git a/muse2/muse/midiedit/dcanvas.cpp b/muse2/muse/midiedit/dcanvas.cpp index 42eda0fd..9189b0d8 100644 --- a/muse2/muse/midiedit/dcanvas.cpp +++ b/muse2/muse/midiedit/dcanvas.cpp @@ -871,9 +871,11 @@ void DrumCanvas::keyPressed(int index, int velocity) int pitch = old_style_drummap_mode ? ourDrumMap[index].anote : instrument_map[index].pitch; // play note: - MusECore::MidiPlayEvent e(0, port, channel, 0x90, pitch, velocity); - MusEGlobal::audio->msgPlayMidiEvent(&e); - + if(_playEvents) + { + 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] */ { @@ -909,8 +911,11 @@ void DrumCanvas::keyReleased(int index, bool) int pitch = old_style_drummap_mode ? ourDrumMap[index].anote : instrument_map[index].pitch; // release note: - MusECore::MidiPlayEvent e(0, port, channel, 0x90, pitch, 0); - MusEGlobal::audio->msgPlayMidiEvent(&e); + if(_playEvents) + { + MusECore::MidiPlayEvent e(0, port, channel, 0x90, pitch, 0); + MusEGlobal::audio->msgPlayMidiEvent(&e); + } } //--------------------------------------------------------- diff --git a/muse2/muse/midiedit/dlist.cpp b/muse2/muse/midiedit/dlist.cpp index a77fb810..3222e278 100644 --- a/muse2/muse/midiedit/dlist.cpp +++ b/muse2/muse/midiedit/dlist.cpp @@ -1123,6 +1123,15 @@ void DList::viewMouseReleaseEvent(QMouseEvent* ev) } //--------------------------------------------------------- +// wheelEvent +//--------------------------------------------------------- + +void DList::wheelEvent(QWheelEvent* ev) + { + emit redirectWheelEvent(ev); + } + +//--------------------------------------------------------- // getSelectedInstrument //--------------------------------------------------------- diff --git a/muse2/muse/midiedit/dlist.h b/muse2/muse/midiedit/dlist.h index b4c757e8..28b4af27 100644 --- a/muse2/muse/midiedit/dlist.h +++ b/muse2/muse/midiedit/dlist.h @@ -137,6 +137,7 @@ class DList : public View { virtual void viewMouseReleaseEvent(QMouseEvent* event); virtual void viewMouseDoubleClickEvent(QMouseEvent*); virtual void viewMouseMoveEvent(QMouseEvent*); + virtual void wheelEvent(QWheelEvent* e); int x2col(int x) const; void devicesPopupMenu(MusECore::DrumMap* t, int x, int y, bool changeAll); @@ -155,6 +156,7 @@ class DList : public View { void keyPressed(int, int); void keyReleased(int, bool); void curDrumInstrumentChanged(int); + void redirectWheelEvent(QWheelEvent*); public slots: void tracklistChanged(); diff --git a/muse2/muse/midiedit/drumedit.cpp b/muse2/muse/midiedit/drumedit.cpp index 238b37fd..03f246cf 100644 --- a/muse2/muse/midiedit/drumedit.cpp +++ b/muse2/muse/midiedit/drumedit.cpp @@ -166,6 +166,7 @@ DrumEdit::DrumEdit(MusECore::PartList* pl, QWidget* parent, const char* name, un lastSelections = 0; split1w1 = 0; //selPart = 0; + _playEvents = false; QSignalMapper *signalMapper = new QSignalMapper(this); _group_mode = GROUP_SAME_CHANNEL; @@ -419,7 +420,13 @@ DrumEdit::DrumEdit(MusECore::PartList* pl, QWidget* parent, const char* name, un midiin->setFocusPolicy(Qt::NoFocus); tools->addWidget(midiin); - + speaker = new QToolButton(); + speaker->setToolTip(tr("Play Events")); + speaker->setIcon(*speakerIcon); + speaker->setCheckable(true); + speaker->setFocusPolicy(Qt::NoFocus); + tools->addWidget(speaker); + tools2 = new MusEGui::EditToolBar(this, drumeditTools); addToolBar(tools2); @@ -554,6 +561,7 @@ DrumEdit::DrumEdit(MusECore::PartList* pl, QWidget* parent, const char* name, un connect(dlist, SIGNAL(keyPressed(int, int)), canvas, SLOT(keyPressed(int, int))); connect(dlist, SIGNAL(keyReleased(int, bool)), canvas, SLOT(keyReleased(int, bool))); connect(dlist, SIGNAL(mapChanged(int, int)), canvas, SLOT(mapChanged(int, int))); + connect(dlist, SIGNAL(redirectWheelEvent(QWheelEvent*)), canvas, SLOT(redirectedWheelEvent(QWheelEvent*))); gridS1->setRowStretch(1, 100); gridS1->setColumnStretch(0, 100); @@ -568,11 +576,12 @@ DrumEdit::DrumEdit(MusECore::PartList* pl, QWidget* parent, const char* name, un connect(MusEGlobal::song, SIGNAL(songChanged(MusECore::SongChangedFlags_t)), dlist, SLOT(songChanged(MusECore::SongChangedFlags_t))); connect(vscroll, SIGNAL(scrollChanged(int)), canvas, SLOT(setYPos(int))); connect(vscroll, SIGNAL(scaleChanged(int)), canvas, SLOT(setYMag(int))); - connect(vscroll, SIGNAL(scaleChanged(int)), dlist, SLOT(setYMag(int))); + connect(vscroll, SIGNAL(scaleChanged(int)), dlist, SLOT(setYMag(int))); connect(hscroll, SIGNAL(scrollChanged(int)), canvas, SLOT(setXPos(int))); connect(hscroll, SIGNAL(scaleChanged(int)), canvas, SLOT(setXMag(int))); connect(srec, SIGNAL(toggled(bool)), canvas, SLOT(setSteprec(bool))); connect(midiin, SIGNAL(toggled(bool)), canvas, SLOT(setMidiin(bool))); + connect(speaker, SIGNAL(toggled(bool)), SLOT(setSpeaker(bool))); connect(vscroll, SIGNAL(scrollChanged(int)), dlist, SLOT(setYPos(int))); connect(hscroll, SIGNAL(scrollChanged(int)), time, SLOT(setXPos(int))); @@ -930,6 +939,7 @@ void DrumEdit::writeStatus(int level, MusECore::Xml& xml) const header->writeStatus(level, xml); xml.intTag(level, "steprec", canvas->steprec()); xml.intTag(level, "midiin", canvas->midiin()); + xml.intTag(level, "playEvents", _playEvents); xml.intTag(level, "xpos", hscroll->pos()); xml.intTag(level, "xmag", hscroll->mag()); xml.intTag(level, "ypos", vscroll->pos()); @@ -974,6 +984,11 @@ void DrumEdit::readStatus(MusECore::Xml& xml) MidiEditor::readStatus(xml); else if (tag == header->objectName()) header->readStatus(xml); + else if (tag == "playEvents") { + _playEvents = xml.parseInt(); + canvas->playEvents(_playEvents); + speaker->setChecked(_playEvents); + } else if (tag == "xmag") hscroll->setMag(xml.parseInt()); else if (tag == "xpos") @@ -1253,20 +1268,12 @@ void DrumEdit::ctrlPopupTriggered(QAction* act) const int edit_ins = max + 3; const int velo = max + 0x101; - const int polyafter = max + 0x102; - const int after = max + 0x103; int rv = act->data().toInt(); if (rv == velo) { // special case velocity newCtlNum = MusECore::CTRL_VELOCITY; } - else if (rv == polyafter) { // special case - newCtlNum = MusECore::CTRL_POLYAFTER; - } - else if (rv == after) { // special case - newCtlNum = MusECore::CTRL_AFTERTOUCH; - } else if (rv == add_ins_def) { // add new instrument controller PopupMenu * ctrlSubPop = new PopupMenu(this, true); // true = enable stay open @@ -1708,6 +1715,16 @@ void DrumEdit::keyPressEvent(QKeyEvent* event) //--------------------------------------------------------- +// setSpeaker +//--------------------------------------------------------- + +void DrumEdit::setSpeaker(bool val) + { + _playEvents = val; + canvas->playEvents(_playEvents); + } + +//--------------------------------------------------------- // initShortcuts //--------------------------------------------------------- diff --git a/muse2/muse/midiedit/drumedit.h b/muse2/muse/midiedit/drumedit.h index 63246e2e..4b9d391a 100644 --- a/muse2/muse/midiedit/drumedit.h +++ b/muse2/muse/midiedit/drumedit.h @@ -103,7 +103,9 @@ class DrumEdit : public MidiEditor { MusEGui::NoteInfo* info; QToolButton* srec; QToolButton* midiin; + QToolButton* speaker; MusEGui::EditToolBar* tools2; + bool _playEvents; MusEGui::Toolbar1* toolbar; MusEGui::Splitter* split1; @@ -152,6 +154,7 @@ class DrumEdit : public MidiEditor { void configChanged(); void songChanged1(MusECore::SongChangedFlags_t); void setStep(QString); + void setSpeaker(bool); void addCtrlClicked(); void ctrlPopupTriggered(QAction* act); diff --git a/muse2/muse/midiedit/piano.cpp b/muse2/muse/midiedit/piano.cpp index 1000ffe9..afbf8328 100644 --- a/muse2/muse/midiedit/piano.cpp +++ b/muse2/muse/midiedit/piano.cpp @@ -26,7 +26,11 @@ #include <stdio.h> #include "piano.h" +#include "globals.h" +#include "song.h" +namespace MusEGui { + static const char *oct_xpm[] = { // w h colors "40 91 2 1", @@ -120,134 +124,125 @@ static const char *oct_xpm[] = { ".........................#...#.........#", ".........................#.............#", ".........................#.............#", - ".........................#...#.........#", // 10 + ".........................#...#.........#", // 9 "..........................###..........#", ".......................................#", ".......................................#", - ".......................................#", }; static const char *mk1_xpmC1[] = { - "40 10 2 1", - ". c #c0c0c0", + "40 9 2 1", + ". c none", "# c #000000", ".......................................#", "..........................###.....#....#", ".........................#...#...##....#", ".........................#........#....#", ".........................#........#....#", - ".........................#...#....#....#", // 10 + ".........................#...#....#....#", // 9 "..........................###....###...#", ".......................................#", ".......................................#", - ".......................................#", }; static const char *mk1_xpmC2[] = { - "40 10 2 1", - ". c #c0c0c0", + "40 9 2 1", + ". c none", "# c #000000", ".......................................#", "..........................###....##....#", ".........................#...#..#..#...#", ".........................#........#....#", ".........................#.......#.....#", - ".........................#...#..#......#", // 10 + ".........................#...#..#......#", // 9 "..........................###...####...#", ".......................................#", ".......................................#", - ".......................................#", }; static const char *mk1_xpmC3[] = { - "40 10 2 1", - ". c #c0c0c0", + "40 9 2 1", + ". c none", "# c #000000", ".......................................#", "..........................###....##....#", ".........................#...#..#..#...#", ".........................#........#....#", ".........................#.........#...#", - ".........................#...#..#..#...#", // 10 + ".........................#...#..#..#...#", // 9 "..........................###....##....#", ".......................................#", ".......................................#", - ".......................................#", }; static const char *mk1_xpmC4[] = { - "40 10 2 1", - ". c #c0c0c0", + "40 9 2 1", + ". c none", "# c #000000", ".......................................#", "..........................###...#..#...#", ".........................#...#..#..#...#", ".........................#......####...#", ".........................#.........#...#", - ".........................#...#.....#...#", // 10 + ".........................#...#.....#...#", // 9 "..........................###......#...#", ".......................................#", ".......................................#", - ".......................................#", }; static const char *mk1_xpmC5[] = { - "40 10 2 1", - ". c #c0c0c0", + "40 9 2 1", + ". c none", "# c #000000", ".......................................#", "..........................###...####...#", ".........................#...#..#......#", ".........................#......###....#", ".........................#.........#...#", - ".........................#...#.....#...#", // 10 + ".........................#...#.....#...#", // 9 "..........................###...###....#", ".......................................#", ".......................................#", - ".......................................#", }; static const char *mk1_xpmC6[] = { - "40 10 2 1", - ". c #c0c0c0", + "40 9 2 1", + ". c none", "# c #000000", ".......................................#", "..........................###....###...#", ".........................#...#..#......#", ".........................#......###....#", ".........................#......#..#...#", - ".........................#...#..#..#...#", // 10 + ".........................#...#..#..#...#", // 9 "..........................###...###....#", ".......................................#", ".......................................#", - ".......................................#", }; static const char *mk1_xpmC7[] = { - "40 10 2 1", - ". c #c0c0c0", + "40 9 2 1", + ". c none", "# c #000000", ".......................................#", "..........................###...####...#", ".........................#...#.....#...#", ".........................#........#....#", ".........................#.......#.....#", - ".........................#...#..#......#", // 10 + ".........................#...#..#......#", // 9 "..........................###...#......#", ".......................................#", ".......................................#", - ".......................................#", }; static const char *mk1_xpmC8[] = { - "40 10 2 1", - ". c #c0c0c0", + "40 9 2 1", + ". c none", "# c #000000", ".......................................#", "..........................###....##....#", - ".........................#...#..#..#....#", + ".........................#...#..#..#...#", ".........................#.......##....#", ".........................#......#..#...#", - ".........................#...#..#..#...#", // 10 + ".........................#...#..#..#...#", // 9 "..........................###....##....#", ".......................................#", ".......................................#", - ".......................................#", }; static const char *mk1_xpm[] = { @@ -266,7 +261,7 @@ static const char *mk1_xpm[] = { "#######################................#", "########################...............#", "########################...............#", - "####################################### ", + "########################################", }; static const char *mk2_xpm[] = { @@ -285,7 +280,7 @@ static const char *mk2_xpm[] = { "#######################................#", "########################...............#", "########################...............#", // 7 - "####################################### ", + "########################################", }; static const char *mk3_xpm[] = { @@ -325,6 +320,83 @@ static const char *mk4_xpm[] = { "........................................", "........................................", }; + +static const char *mk5_xpm[] = { + "40 13 2 1", + ". c #ffff00", + "# c none", + ".......................................#", + ".......................................#", + ".......................................#", + ".......................................#", + ".......................................#", + ".......................................#", + ".......................................#", + ".......................................#", + ".......................................#", + "#######################................#", + "########################...............#", + "########################...............#", + "########################################", + }; + +static const char *mk6_xpm[] = { + "40 13 2 1", + ". c #ffff00", + "# c none", + "########################...............#", + "########################...............#", + "#######################................#", //------------------------ + ".......................................#", + ".......................................#", + ".......................................#", // 6 + ".......................................#", + ".......................................#", + ".......................................#", //-------------------------- + "#######################................#", + "########################...............#", + "########################...............#", // 7 + "########################################", + }; + +static const char *mk7_xpm[] = { + "40 13 2 1", + ". c #ffff00", + "# c none", + "########################...............#", + "########################...............#", + "#######################................#", + ".......................................#", + ".......................................#", + ".......................................#", + ".......................................#", + ".......................................#", + ".......................................#", + ".......................................#", + ".......................................#", + ".......................................#", + "########################################", + }; + +static const char *mk8_xpm[] = { + "40 13 2 1", + "# c #ffff00", + ". c none", + "........................................", + "........................................", + "........................................", + "#######################.................", + "########################................", + "########################................", + "########################................", + "########################................", + "########################................", + "#######################.................", + "........................................", + "........................................", + "........................................", + }; + /* 0 1 2 3 4 5 6 7 8 9 10 c-2 c-1 C0 C1 C2 C3 C4 C5 C6 C7 C8 - G8 @@ -367,10 +439,11 @@ static const char *mk4_xpm[] = { //--------------------------------------------------------- Piano::Piano(QWidget* parent, int ymag) - : MusEGui::View(parent, 1, ymag) + : View(parent, 1, ymag) { setMouseTracking(true); curPitch = -1; + _curSelectedPitch = 60; // Start with 'C3" octave = new QPixmap(oct_xpm); c_keys[0] = new QPixmap(mk1_xpmC8); c_keys[1] = new QPixmap(mk1_xpmC7); @@ -385,6 +458,12 @@ Piano::Piano(QWidget* parent, int ymag) mk2 = new QPixmap(mk2_xpm); mk3 = new QPixmap(mk3_xpm); mk4 = new QPixmap(mk4_xpm); + + mk5 = new QPixmap(mk5_xpm); + mk6 = new QPixmap(mk6_xpm); + mk7 = new QPixmap(mk7_xpm); + mk8 = new QPixmap(mk8_xpm); + keyDown = -1; button = Qt::NoButton; } @@ -398,39 +477,67 @@ void Piano::draw(QPainter& p, const QRect& r) QPoint offset(0, KH*2); p.drawTiledPixmap(r, *octave, r.topLeft()+offset); + if (_curSelectedPitch != -1 && _curSelectedPitch != curPitch) + { + int y = pitch2y(_curSelectedPitch); + QPixmap* pm; + switch(_curSelectedPitch % 12) { + case 0: + case 5: + pm = mk7; + break; + case 2: + case 7: + case 9: + pm = mk6; + break; + case 4: + case 11: + pm = mk5; + break; + default: + pm = mk8; + break; + } + p.drawPixmap(0, y, *pm); + } + + if (curPitch != -1) + { + int y = pitch2y(curPitch); + QPixmap* pm; + switch(curPitch % 12) { + case 0: + case 5: + pm = mk3; + break; + case 2: + case 7: + case 9: + pm = mk2; + break; + case 4: + case 11: + pm = mk1; + break; + default: + pm = mk4; + break; + } + p.drawPixmap(0, y, *pm); + } + // draw C notes for (int drawKey = 0; drawKey < 8;drawKey++) { int octaveSize=91; - int drawY = octaveSize * drawKey + 81 - KH*2; + int drawY = octaveSize * drawKey + 82 - KH*2; if (drawY > r.y() && drawY < r.y() + r.height()) { p.drawPixmap(0,drawY,*c_keys[drawKey]); } } - - if (curPitch == -1) - return; - int y = pitch2y(curPitch); - QPixmap* pm; - switch(curPitch % 12) { - case 0: - case 5: - pm = mk3; - break; - case 2: - case 7: - case 9: - pm = mk2; - break; - case 4: - case 11: - pm = mk1; - break; - default: - pm = mk4; - break; - } - p.drawPixmap(0, y, *pm); + + } //--------------------------------------------------------- @@ -547,6 +654,13 @@ void Piano::viewMousePressEvent(QMouseEvent* event) int velocity = event->x()*127/40; emit keyPressed(keyDown, velocity>127 ? 127 : velocity, shift); //emit keyPressed(keyDown, shift); } + + if (keyDown != -1 && keyDown != _curSelectedPitch) { + _curSelectedPitch = keyDown; + emit curSelectedPitchChanged(_curSelectedPitch); + redraw(); + MusEGlobal::song->update(SC_DRUMMAP); + } } //--------------------------------------------------------- @@ -563,3 +677,28 @@ void Piano::viewMouseReleaseEvent(QMouseEvent* event) } } +//--------------------------------------------------------- +// setCurSelectedPitch +//--------------------------------------------------------- + +void Piano::setCurSelectedPitch(int pitch) + { + if (pitch < 0 || pitch >= 128) + return; + if (pitch != _curSelectedPitch) { + _curSelectedPitch = pitch; + emit curSelectedPitchChanged(_curSelectedPitch); + redraw(); + } + } + +//--------------------------------------------------------- +// wheelEvent +//--------------------------------------------------------- + +void Piano::wheelEvent(QWheelEvent* ev) + { + emit redirectWheelEvent(ev); + } + +} // namespace MusEGui diff --git a/muse2/muse/midiedit/piano.h b/muse2/muse/midiedit/piano.h index ea032189..f42037ec 100644 --- a/muse2/muse/midiedit/piano.h +++ b/muse2/muse/midiedit/piano.h @@ -27,26 +27,34 @@ class QEvent; class QMouseEvent; +class QWheelEvent; class QPainter; class QPixmap; #define KH 13 +namespace MusEGui { + //--------------------------------------------------------- // Piano //--------------------------------------------------------- -class Piano : public MusEGui::View +class Piano : public View { Q_OBJECT int curPitch; + int _curSelectedPitch; QPixmap* octave; QPixmap* c_keys[10]; QPixmap* mk1; QPixmap* mk2; QPixmap* mk3; QPixmap* mk4; + QPixmap* mk5; + QPixmap* mk6; + QPixmap* mk7; + QPixmap* mk8; int keyDown; bool shift; int button; @@ -59,6 +67,7 @@ class Piano : public MusEGui::View virtual void viewMousePressEvent(QMouseEvent* event); virtual void viewMouseReleaseEvent(QMouseEvent*); + virtual void wheelEvent(QWheelEvent* e); protected: virtual void draw(QPainter&, const QRect&); @@ -67,13 +76,19 @@ class Piano : public MusEGui::View void pitchChanged(int); void keyPressed(int, int, bool); void keyReleased(int, bool); + void curSelectedPitchChanged(int); + void redirectWheelEvent(QWheelEvent*); public slots: void setPitch(int); public: Piano(QWidget*, int); + int curSelectedPitch() const { return _curSelectedPitch; } + void setCurSelectedPitch(int pitch); }; +} // namespace MusEGui + #endif diff --git a/muse2/muse/midiedit/pianoroll.cpp b/muse2/muse/midiedit/pianoroll.cpp index 1701f537..97c5ecc3 100644 --- a/muse2/muse/midiedit/pianoroll.cpp +++ b/muse2/muse/midiedit/pianoroll.cpp @@ -359,9 +359,10 @@ PianoRoll::PianoRoll(MusECore::PartList* pl, QWidget* parent, const char* name, gridS1->setSpacing(0); time = new MusEGui::MTScale(&_raster, split1, xscale); - Piano* piano = new Piano(split1, yscale); + piano = new Piano(split1, yscale); canvas = new PianoCanvas(this, split1, xscale, yscale); vscroll = new MusEGui::ScrollScale(-3, 7, yscale, KH * 75, Qt::Vertical, split1); + setCurDrumInstrument(piano->curSelectedPitch()); int offset = -(MusEGlobal::config.division/4); canvas->setOrigin(offset, 0); @@ -428,6 +429,7 @@ PianoRoll::PianoRoll(MusECore::PartList* pl, QWidget* parent, const char* name, connect(piano, SIGNAL(keyPressed(int, int, bool)), canvas, SLOT(pianoPressed(int, int, bool))); connect(piano, SIGNAL(keyReleased(int, bool)), canvas, SLOT(pianoReleased(int, bool))); + connect(piano, SIGNAL(redirectWheelEvent(QWheelEvent*)), canvas, SLOT(redirectedWheelEvent(QWheelEvent*))); connect(srec, SIGNAL(toggled(bool)), SLOT(setSteprec(bool))); connect(midiin, SIGNAL(toggled(bool)), canvas, SLOT(setMidiin(bool))); connect(speaker, SIGNAL(toggled(bool)), SLOT(setSpeaker(bool))); @@ -811,9 +813,7 @@ void PianoRoll::ctrlPopupTriggered(QAction* act) MusECore::MidiTrack* track = (MusECore::MidiTrack*)(part->track()); int channel = track->outChannel(); MusECore::MidiPort* port = &MusEGlobal::midiPorts[track->outPort()]; - int curDrumPitch = curDrumInstrument(); - bool isDrum = track->type() == MusECore::Track::DRUM; - bool isNewDrum = track->type() == MusECore::Track::NEW_DRUM; + int curPitch = curDrumInstrument(); MusECore::MidiInstrument* instr = port->instrument(); MusECore::MidiControllerList* mcl = instr->controller(); @@ -826,20 +826,12 @@ void PianoRoll::ctrlPopupTriggered(QAction* act) const int edit_ins = max + 3; const int velo = max + 0x101; - const int polyafter = max + 0x102; - const int after = max + 0x103; int rv = act->data().toInt(); if (rv == velo) { // special case velocity newCtlNum = MusECore::CTRL_VELOCITY; } - else if (rv == polyafter) { // special case - newCtlNum = MusECore::CTRL_POLYAFTER; - } - else if (rv == after) { // special case - newCtlNum = MusECore::CTRL_AFTERTOUCH; - } else if (rv == add_ins_def) { // add new instrument controller PopupMenu * ctrlSubPop = new PopupMenu(this, true); // true = enable stay open @@ -855,10 +847,11 @@ void PianoRoll::ctrlPopupTriggered(QAction* act) int num = ci->second->num(); if((num & 0xff) == 0xff) { - if (isDrum && curDrumPitch!=-1) - num = (num & ~0xff) + MusEGlobal::drumMap[curDrumPitch].anote; - else if (isNewDrum && curDrumPitch!=-1) - num = (num & ~0xff) + curDrumPitch; //FINDMICH does this work? + //if (curPitch!=-1) + // num = (num & ~0xff) + MusEGlobal::drumMap[curPitch].anote; + //else + if(curPitch!=-1) + num = (num & ~0xff) + curPitch; //FINDMICH does this work? else // dont show drum specific controller if not a drum track continue; } @@ -885,10 +878,11 @@ void PianoRoll::ctrlPopupTriggered(QAction* act) { c = ci->second; int num = c->num(); - if (isDrum && ((num & 0xff) == 0xff) && curDrumPitch!=-1) - num = (num & ~0xff) + MusEGlobal::drumMap[curDrumPitch].anote; - else if (isNewDrum && ((num & 0xff) == 0xff) && curDrumPitch!=-1) - num = (num & ~0xff) + curDrumPitch; //FINDMICHJETZT does this work? + //if (((num & 0xff) == 0xff) && curPitch!=-1) + // num = (num & ~0xff) + MusEGlobal::drumMap[curPitch].anote; + //else + if (((num & 0xff) == 0xff) && curPitch!=-1) + num = (num & ~0xff) + curPitch; //FINDMICHJETZT does this work? if(num != rv2) continue; @@ -923,10 +917,10 @@ void PianoRoll::ctrlPopupTriggered(QAction* act) if (act2) { int rv2 = act2->data().toInt(); int num = rv2; - if (isDrum && ((num & 0xff) == 0xff) && curDrumPitch!=-1) - num = (num & ~0xff) + MusEGlobal::drumMap[curDrumPitch].anote; - if (isNewDrum && ((num & 0xff) == 0xff) && curDrumPitch!=-1) - num = (num & ~0xff) + curDrumPitch; //FINDMICHJETZT does this work? + //if (((num & 0xff) == 0xff) && curPitch!=-1) + // num = (num & ~0xff) + MusEGlobal::drumMap[curPitch].anote; + if (((num & 0xff) == 0xff) && curPitch!=-1) + num = (num & ~0xff) + curPitch; //FINDMICHJETZT does this work? if(cll->find(channel, num) == cll->end()) { @@ -972,7 +966,7 @@ void PianoRoll::addCtrlClicked() PopupMenu* pup = new PopupMenu(true); // true = enable stay open. Don't bother with parent. connect(pup, SIGNAL(triggered(QAction*)), SLOT(ctrlPopupTriggered(QAction*))); - int est_width = populateMidiCtrlMenu(pup, parts(), curCanvasPart(), -1); // _curDrumInstrument); + int est_width = populateMidiCtrlMenu(pup, parts(), curCanvasPart(), curDrumInstrument()); QPoint ep = ctrl->mapToGlobal(QPoint(0,0)); //int newx = ep.x() - ctrlMainPop->width(); // Too much! Width says 640. Maybe because it hasn't been shown yet . @@ -1010,7 +1004,11 @@ void PianoRoll::setupNewCtrl(CtrlEdit* ctrlEdit) connect(ctrlEdit, SIGNAL(timeChanged(unsigned)), SLOT(setTime(unsigned))); connect(ctrlEdit, SIGNAL(destroyedCtrl(CtrlEdit*)), SLOT(removeCtrl(CtrlEdit*))); connect(ctrlEdit, SIGNAL(yposChanged(int)), toolbar, SLOT(setInt(int))); + connect(piano, SIGNAL(curSelectedPitchChanged(int)), SLOT(setCurDrumInstrument(int))); + //connect(piano, SIGNAL(curSelectedPitchChanged(int)), canvas, SLOT(setCurDrumInstrument(int))); + setCurDrumInstrument(piano->curSelectedPitch()); + ctrlEdit->setTool(tools2->curTool()); ctrlEdit->setXPos(hscroll->pos()); ctrlEdit->setXMag(hscroll->getScaleValue()); @@ -1275,6 +1273,17 @@ void PianoRoll::keyPressEvent(QKeyEvent* event) tools2->set(MusEGui::DrawTool); return; } + else if (key == shortcuts[SHRT_INSTRUMENT_STEP_UP].key) { + piano->setCurSelectedPitch(piano->curSelectedPitch()+1); + MusEGlobal::song->update(SC_DRUMMAP); + return; + } + else if (key == shortcuts[SHRT_INSTRUMENT_STEP_DOWN].key) { + piano->setCurSelectedPitch(piano->curSelectedPitch()-1); + MusEGlobal::song->update(SC_DRUMMAP); + return; + } + else if (key == shortcuts[SHRT_POS_INC].key) { pc->pianoCmd(CMD_RIGHT); return; diff --git a/muse2/muse/midiedit/pianoroll.h b/muse2/muse/midiedit/pianoroll.h index 75e3c9af..87ea1d3d 100644 --- a/muse2/muse/midiedit/pianoroll.h +++ b/muse2/muse/midiedit/pianoroll.h @@ -66,6 +66,7 @@ class ScrollScale; class Splitter; class TimeLabel; class Toolbar1; +class Piano; //--------------------------------------------------------- // PianoRoll @@ -126,6 +127,7 @@ class PianoRoll : public MidiEditor { QToolButton* srec; QToolButton* midiin; + Piano* piano; MusEGui::Toolbar1* toolbar; MusEGui::Splitter* splitter; MusEGui::Splitter* hsplitter; diff --git a/muse2/muse/midiedit/prcanvas.cpp b/muse2/muse/midiedit/prcanvas.cpp index 99c2ea8c..7670abb2 100644 --- a/muse2/muse/midiedit/prcanvas.cpp +++ b/muse2/muse/midiedit/prcanvas.cpp @@ -718,8 +718,11 @@ void PianoCanvas::pianoPressed(int pitch, int velocity, bool shift) pitch += track()->transposition; // play note: - MusECore::MidiPlayEvent e(0, port, channel, 0x90, pitch, velocity); - MusEGlobal::audio->msgPlayMidiEvent(&e); + if(_playEvents) + { + MusECore::MidiPlayEvent e(0, port, channel, 0x90, pitch, velocity); + MusEGlobal::audio->msgPlayMidiEvent(&e); + } if (_steprec && curPart) // && pos[0] >= start_tick && pos[0] < end_tick [removed by flo93: this is handled in steprec->record] steprec->record(curPart,pitch,editor->raster(),editor->raster(),velocity,MusEGlobal::globalKeyState&Qt::ControlModifier,shift, -1 /* anything which is != rcSteprecNote */); @@ -736,8 +739,11 @@ void PianoCanvas::pianoReleased(int pitch, bool) pitch += track()->transposition; // release key: - MusECore::MidiPlayEvent e(0, port, channel, 0x90, pitch, 0); - MusEGlobal::audio->msgPlayMidiEvent(&e); + if(_playEvents) + { + MusECore::MidiPlayEvent e(0, port, channel, 0x90, pitch, 0); + MusEGlobal::audio->msgPlayMidiEvent(&e); + } } //--------------------------------------------------------- diff --git a/muse2/muse/midiport.cpp b/muse2/muse/midiport.cpp index 2f3898ff..4365d698 100644 --- a/muse2/muse/midiport.cpp +++ b/muse2/muse/midiport.cpp @@ -742,8 +742,6 @@ void MidiPort::addDefaultControllers() addManagedController(i, CTRL_PROGRAM); addManagedController(i, CTRL_VOLUME); addManagedController(i, CTRL_PANPOT); - addManagedController(i, CTRL_POLYAFTER); - addManagedController(i, CTRL_AFTERTOUCH); _automationType[i] = AUTO_READ; } } diff --git a/muse2/muse/midiseq.cpp b/muse2/muse/midiseq.cpp index 32e9de4c..8e636658 100644 --- a/muse2/muse/midiseq.cpp +++ b/muse2/muse/midiseq.cpp @@ -46,6 +46,7 @@ #include "synth.h" #include "song.h" #include "gconfig.h" +#include "warn_bad_timing.h" namespace MusEGlobal { MusECore::MidiSeq* midiSeq; @@ -507,13 +508,23 @@ void MidiSeq::checkAndReportTimingResolution() { int freq = timer->getTimerFreq(); if (freq < 500) { - QMessageBox::warning( MusEGlobal::muse, - qApp->translate("@default", QT_TRANSLATE_NOOP("@default", "Bad timing")), - qApp->translate("@default", QT_TRANSLATE_NOOP("@default", - "Timing source frequency is %1hz, which is below the recommended minimum: 500hz!\n" \ - "This could lead to audible timing problems for MIDI.\n" \ - "Please see the FAQ on http://muse-sequencer.org for remedies.\n" \ + if(MusEGlobal::config.warnIfBadTiming) + { + MusEGui::WarnBadTimingDialog dlg; + dlg.setLabelText(qApp->translate("@default", QT_TRANSLATE_NOOP("@default", + "Timing source frequency is %1hz, which is below the recommended minimum: 500hz!\n" + "This could lead to audible timing problems for MIDI.\n" + "Please see the FAQ on http://muse-sequencer.org for remedies.\n" "Also please check console output for any further error messages.\n ")).arg(freq) ); + + dlg.exec(); + bool warn = !dlg.dontAsk(); + if(warn != MusEGlobal::config.warnIfBadTiming) + { + MusEGlobal::config.warnIfBadTiming = warn; + //MusEGlobal::muse->changeConfig(true); // Save settings? No, wait till close. + } + } } } diff --git a/muse2/muse/widgets/CMakeLists.txt b/muse2/muse/widgets/CMakeLists.txt index 3aad8b92..3808a99f 100644 --- a/muse2/muse/widgets/CMakeLists.txt +++ b/muse2/muse/widgets/CMakeLists.txt @@ -105,6 +105,7 @@ QT4_WRAP_CPP (widget_mocs view.h vscale.h visibletracks.h + warn_bad_timing.h ) ## @@ -142,6 +143,7 @@ file (GLOB widgets_ui_files tracks_duplicate_base.ui transformbase.ui unusedwavefiles.ui + warn_bad_timing.ui ) QT4_WRAP_UI (widget_ui_headers ${widgets_ui_files}) @@ -229,6 +231,7 @@ file (GLOB widgets_source_files view.cpp vscale.cpp visibletracks.cpp + warn_bad_timing.cpp ) ## diff --git a/muse2/muse/widgets/genset.cpp b/muse2/muse/widgets/genset.cpp index 5c4b2dfb..7063b960 100644 --- a/muse2/muse/widgets/genset.cpp +++ b/muse2/muse/widgets/genset.cpp @@ -153,6 +153,7 @@ void GlobalSettingsConfig::updateSettings() } } + warnIfBadTimingCheckBox->setChecked(MusEGlobal::config.warnIfBadTiming); midiSendInit->setChecked(MusEGlobal::config.midiSendInit); midiWarnInitPending->setChecked(MusEGlobal::config.warnInitPending); midiSendCtlDefaults->setChecked(MusEGlobal::config.midiSendCtlDefaults); @@ -220,6 +221,7 @@ void GlobalSettingsConfig::updateSettings() lmbDecreasesCheckBox->setChecked(MusEGlobal::config.leftMouseButtonCanDecrease); rangeMarkerWithoutMMBCheckBox->setChecked(MusEGlobal::config.rangeMarkerWithoutMMB); smartFocusCheckBox->setChecked(MusEGlobal::config.smartFocus); + velocityPerNoteCheckBox->setChecked(MusEGlobal::config.velocityPerNote); addHiddenCheckBox->setChecked(MusEGlobal::config.addHiddenTracks); unhideTracksCheckBox->setChecked(MusEGlobal::config.unhideTracks); @@ -272,6 +274,7 @@ void GlobalSettingsConfig::apply() MusEGlobal::config.useOutputLimiter = outputLimiterCheckBox->isChecked(); MusEGlobal::config.vstInPlace = vstInPlaceCheckBox->isChecked(); MusEGlobal::config.rtcTicks = rtcResolutions[rtcticks]; + MusEGlobal::config.warnIfBadTiming = warnIfBadTimingCheckBox->isChecked(); MusEGlobal::config.midiSendInit = midiSendInit->isChecked(); MusEGlobal::config.warnInitPending = midiWarnInitPending->isChecked(); MusEGlobal::config.midiSendCtlDefaults = midiSendCtlDefaults->isChecked(); @@ -335,6 +338,7 @@ void GlobalSettingsConfig::apply() MusEGlobal::config.leftMouseButtonCanDecrease = lmbDecreasesCheckBox->isChecked(); MusEGlobal::config.rangeMarkerWithoutMMB = rangeMarkerWithoutMMBCheckBox->isChecked(); MusEGlobal::config.smartFocus = smartFocusCheckBox->isChecked(); + MusEGlobal::config.velocityPerNote = velocityPerNoteCheckBox->isChecked(); MusEGlobal::config.addHiddenTracks = addHiddenCheckBox->isChecked(); MusEGlobal::config.unhideTracks = unhideTracksCheckBox->isChecked(); diff --git a/muse2/muse/widgets/gensetbase.ui b/muse2/muse/widgets/gensetbase.ui index 30d823ec..35c2d2b2 100644 --- a/muse2/muse/widgets/gensetbase.ui +++ b/muse2/muse/widgets/gensetbase.ui @@ -1116,7 +1116,7 @@ Adjusts responsiveness of audio controls and <string>Ticks</string> </property> <layout class="QGridLayout" name="gridLayout_2"> - <item row="0" column="0" rowspan="2"> + <item row="1" column="0" rowspan="2"> <widget class="QLabel" name="TextLabel3"> <property name="text"> <string>RTC Resolution @@ -1127,7 +1127,7 @@ Adjusts responsiveness of audio controls and </property> </widget> </item> - <item row="0" column="1"> + <item row="1" column="1"> <widget class="QComboBox" name="rtcResolutionSelect"> <property name="sizePolicy"> <sizepolicy hsizetype="Preferred" vsizetype="Fixed"> @@ -1167,7 +1167,7 @@ Adjusts responsiveness of audio controls and </item> </widget> </item> - <item row="1" column="1" rowspan="2"> + <item row="2" column="1" rowspan="2"> <widget class="QComboBox" name="midiDivisionSelect"> <property name="sizePolicy"> <sizepolicy hsizetype="Preferred" vsizetype="Fixed"> @@ -1225,7 +1225,7 @@ Adjusts responsiveness of audio controls and </item> </widget> </item> - <item row="2" column="0"> + <item row="3" column="0"> <widget class="QLabel" name="midiResLabel"> <property name="text"> <string>Midi Resolution @@ -1236,7 +1236,7 @@ Adjusts responsiveness of audio controls and </property> </widget> </item> - <item row="3" column="0"> + <item row="4" column="0"> <widget class="QLabel" name="TextLabel4"> <property name="text"> <string>Displayed Resolution @@ -1247,7 +1247,7 @@ Adjusts responsiveness of audio controls and </property> </widget> </item> - <item row="3" column="1"> + <item row="4" column="1"> <widget class="QComboBox" name="guiDivisionSelect"> <property name="sizePolicy"> <sizepolicy hsizetype="Preferred" vsizetype="Fixed"> @@ -1305,6 +1305,13 @@ Adjusts responsiveness of audio controls and </item> </widget> </item> + <item row="0" column="0"> + <widget class="QCheckBox" name="warnIfBadTimingCheckBox"> + <property name="text"> + <string>Warn if timer frequency is inadequate</string> + </property> + </widget> + </item> </layout> </widget> </item> @@ -1326,7 +1333,7 @@ Adjusts responsiveness of audio controls and <property name="title"> <string>Behavior</string> </property> - <layout class="QGridLayout"> + <layout class="QGridLayout" name="gridLayout7"> <item row="0" column="0"> <widget class="QLabel" name="TextLabel1"> <property name="text"> @@ -1337,7 +1344,7 @@ Adjusts responsiveness of audio controls and </property> </widget> </item> - <item row="0" column="1"> + <item row="0" column="2"> <widget class="QSpinBox" name="guiRefreshSelect"> <property name="suffix"> <string>/sec</string> @@ -1363,7 +1370,7 @@ Adjusts responsiveness of audio controls and </property> </widget> </item> - <item row="1" column="1"> + <item row="1" column="2"> <widget class="QCheckBox" name="oldStyleStopCheckBox"> <property name="sizePolicy"> <sizepolicy hsizetype="Fixed" vsizetype="Fixed"> @@ -1376,7 +1383,7 @@ Adjusts responsiveness of audio controls and </property> </widget> </item> - <item row="2" column="0"> + <item row="2" column="0" colspan="2"> <widget class="QLabel" name="textLabel1_4_2"> <property name="text"> <string>Move single armed track with selection</string> @@ -1386,7 +1393,7 @@ Adjusts responsiveness of audio controls and </property> </widget> </item> - <item row="2" column="1"> + <item row="2" column="2"> <widget class="QCheckBox" name="moveArmedCheckBox"> <property name="sizePolicy"> <sizepolicy hsizetype="Fixed" vsizetype="Fixed"> @@ -1409,7 +1416,7 @@ Adjusts responsiveness of audio controls and </property> </widget> </item> - <item row="3" column="1"> + <item row="3" column="2"> <widget class="QCheckBox" name="projectSaveCheckBox"> <property name="sizePolicy"> <sizepolicy hsizetype="Fixed" vsizetype="Fixed"> @@ -1422,7 +1429,7 @@ Adjusts responsiveness of audio controls and </property> </widget> </item> - <item row="4" column="0"> + <item row="4" column="0" colspan="2"> <widget class="QLabel" name="TextLabel1_3"> <property name="toolTip"> <string/> @@ -1432,7 +1439,7 @@ Adjusts responsiveness of audio controls and </property> </widget> </item> - <item row="4" column="1"> + <item row="4" column="2"> <widget class="QCheckBox" name="popsDefStayOpenCheckBox"> <property name="sizePolicy"> <sizepolicy hsizetype="Fixed" vsizetype="Fixed"> @@ -1449,7 +1456,7 @@ Otherwise, hold Ctrl to keep them open.</string> </property> </widget> </item> - <item row="5" column="0"> + <item row="5" column="0" colspan="2"> <widget class="QLabel" name="label_2"> <property name="toolTip"> <string>In some areas, the middle mouse button decreases @@ -1462,7 +1469,7 @@ left button behave like the middle button in such areas.</string> </property> </widget> </item> - <item row="5" column="1"> + <item row="5" column="2"> <widget class="QCheckBox" name="lmbDecreasesCheckBox"> <property name="sizePolicy"> <sizepolicy hsizetype="Fixed" vsizetype="Fixed"> @@ -1475,7 +1482,14 @@ left button behave like the middle button in such areas.</string> </property> </widget> </item> - <item row="6" column="1"> + <item row="6" column="0" colspan="2"> + <widget class="QLabel" name="label_3"> + <property name="text"> + <string>Shift + Right click sets left range marker</string> + </property> + </widget> + </item> + <item row="6" column="2"> <widget class="QCheckBox" name="rangeMarkerWithoutMMBCheckBox"> <property name="sizePolicy"> <sizepolicy hsizetype="Fixed" vsizetype="Fixed"> @@ -1488,42 +1502,35 @@ left button behave like the middle button in such areas.</string> </property> </widget> </item> - <item row="6" column="0"> - <widget class="QLabel" name="label_3"> + <item row="7" column="0" colspan="2"> + <widget class="QLabel" name="label_4"> <property name="text"> - <string>Shift + Right click sets left range marker</string> + <string>Allow adding hidden tracks in track list menu</string> </property> </widget> </item> - <item row="7" column="1"> + <item row="7" column="2"> <widget class="QCheckBox" name="addHiddenCheckBox"> <property name="text"> <string/> </property> </widget> </item> - <item row="7" column="0"> - <widget class="QLabel" name="label_4"> - <property name="text"> - <string>Allow adding hidden tracks in track list menu</string> - </property> - </widget> - </item> - <item row="8" column="0"> + <item row="8" column="0" colspan="2"> <widget class="QLabel" name="label_5"> <property name="text"> <string>Unhide tracks when adding hidden tracks</string> </property> </widget> </item> - <item row="8" column="1"> + <item row="8" column="2"> <widget class="QCheckBox" name="unhideTracksCheckBox"> <property name="text"> <string/> </property> </widget> </item> - <item row="9" column="0"> + <item row="9" column="0" colspan="2"> <widget class="QLabel" name="label5"> <property name="text"> <string>Smart focus</string> @@ -1533,7 +1540,7 @@ left button behave like the middle button in such areas.</string> </property> </widget> </item> - <item row="9" column="1"> + <item row="9" column="2"> <widget class="QCheckBox" name="smartFocusCheckBox"> <property name="sizePolicy"> <sizepolicy hsizetype="Fixed" vsizetype="Fixed"> @@ -1553,7 +1560,21 @@ left button behave like the middle button in such areas.</string> </property> </widget> </item> - <item row="10" column="0"> + <item row="10" column="0" colspan="2"> + <widget class="QLabel" name="label_6"> + <property name="text"> + <string>Show midi velocity graphs per-note</string> + </property> + </widget> + </item> + <item row="10" column="2"> + <widget class="QCheckBox" name="velocityPerNoteCheckBox"> + <property name="text"> + <string/> + </property> + </widget> + </item> + <item row="11" column="1"> <spacer name="verticalSpacer_2"> <property name="orientation"> <enum>Qt::Vertical</enum> @@ -1677,8 +1698,8 @@ left button behave like the middle button in such areas.</string> <rect> <x>0</x> <y>0</y> - <width>96</width> - <height>26</height> + <width>474</width> + <height>410</height> </rect> </property> <layout class="QHBoxLayout" name="horizontalLayout_3"> diff --git a/muse2/muse/widgets/midi_warn_init_pending_impl.h b/muse2/muse/widgets/midi_warn_init_pending_impl.h index d24ee129..3a4b8c50 100644 --- a/muse2/muse/widgets/midi_warn_init_pending_impl.h +++ b/muse2/muse/widgets/midi_warn_init_pending_impl.h @@ -37,4 +37,4 @@ public: } // namespace MusEGui -#endif
\ No newline at end of file +#endif diff --git a/muse2/muse/widgets/musewidgetsplug.cpp b/muse2/muse/widgets/musewidgetsplug.cpp index 70cdcd0f..967ab9ac 100644 --- a/muse2/muse/widgets/musewidgetsplug.cpp +++ b/muse2/muse/widgets/musewidgetsplug.cpp @@ -54,7 +54,7 @@ static const char* valu[] = { }; MusEGlobal::GlobalConfigValues config = { - 190, // globalAlphaBlend + 170, // globalAlphaBlend { QColor(0xff, 0xff, 0xff), // palette QColor(0xff, 0xff, 0xff), @@ -158,6 +158,8 @@ MusEGlobal::GlobalConfigValues config = { true, // midiSendInit Send instrument initialization sequences true, // warnInitPending Warn instrument initialization sequences pending false, // midiSendCtlDefaults Send instrument controller defaults at position 0 if none in song + true, // warnIfBadTiming Warn if timer res not good + false, // velocityPerNote Whether to show per-note or all velocities -60, // int minMeter; -60.0, // double minSlider; false, // use Jack freewheel diff --git a/muse2/muse/widgets/warn_bad_timing.cpp b/muse2/muse/widgets/warn_bad_timing.cpp new file mode 100644 index 00000000..38721d36 --- /dev/null +++ b/muse2/muse/widgets/warn_bad_timing.cpp @@ -0,0 +1,33 @@ +//========================================================= +// MusE +// Linux Music Editor +// warn_bad_timing.cpp +// (C) Copyright 2012 Tim E. Real (terminator356 on users dot sourceforge dot net) +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; version 2 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +// +//========================================================= + +#include "warn_bad_timing.h" + +namespace MusEGui { + +WarnBadTimingDialog::WarnBadTimingDialog() +{ + setupUi(this); +} + +} // namespace MusEGui + diff --git a/muse2/muse/widgets/warn_bad_timing.h b/muse2/muse/widgets/warn_bad_timing.h new file mode 100644 index 00000000..4e6ce77e --- /dev/null +++ b/muse2/muse/widgets/warn_bad_timing.h @@ -0,0 +1,41 @@ +//========================================================= +// MusE +// Linux Music Editor +// warn_bad_timing.h +// (C) Copyright 2012 Tim E. Real (terminator356 on users dot sourceforge dot net) +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; version 2 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +// +//========================================================= +#ifndef __WARN_BAD_TIMING_H__ +#define __WARN_BAD_TIMING_H__ + +#include "ui_warn_bad_timing.h" + +namespace MusEGui { + +class WarnBadTimingDialog : public QDialog, public Ui::warnBadTimingBase +{ + Q_OBJECT + +public: + WarnBadTimingDialog(); + bool dontAsk() const { return dontAskAgain->isChecked(); } + void setLabelText(const QString& s) { label->setText(s); } +}; + +} // namespace MusEGui + +#endif diff --git a/muse2/muse/widgets/warn_bad_timing.ui b/muse2/muse/widgets/warn_bad_timing.ui new file mode 100644 index 00000000..7c92850f --- /dev/null +++ b/muse2/muse/widgets/warn_bad_timing.ui @@ -0,0 +1,111 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>warnBadTimingBase</class> + <widget class="QDialog" name="warnBadTimingBase"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>371</width> + <height>207</height> + </rect> + </property> + <property name="sizePolicy"> + <sizepolicy hsizetype="Maximum" vsizetype="Maximum"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="windowTitle"> + <string>Bad timing</string> + </property> + <layout class="QVBoxLayout" name="verticalLayout"> + <item> + <widget class="QLabel" name="label"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Preferred" vsizetype="Preferred"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text"> + <string>Message here</string> + </property> + <property name="textFormat"> + <enum>Qt::AutoText</enum> + </property> + <property name="wordWrap"> + <bool>false</bool> + </property> + </widget> + </item> + <item> + <widget class="QCheckBox" name="dontAskAgain"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Preferred" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text"> + <string>Don't ask me again</string> + </property> + </widget> + </item> + <item> + <widget class="QDialogButtonBox" name="buttonBox"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Expanding" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="standardButtons"> + <set>QDialogButtonBox::Ok</set> + </property> + <property name="centerButtons"> + <bool>false</bool> + </property> + </widget> + </item> + </layout> + </widget> + <resources/> + <connections> + <connection> + <sender>buttonBox</sender> + <signal>accepted()</signal> + <receiver>warnBadTimingBase</receiver> + <slot>accept()</slot> + <hints> + <hint type="sourcelabel"> + <x>248</x> + <y>254</y> + </hint> + <hint type="destinationlabel"> + <x>157</x> + <y>274</y> + </hint> + </hints> + </connection> + <connection> + <sender>buttonBox</sender> + <signal>rejected()</signal> + <receiver>warnBadTimingBase</receiver> + <slot>reject()</slot> + <hints> + <hint type="sourcelabel"> + <x>316</x> + <y>260</y> + </hint> + <hint type="destinationlabel"> + <x>286</x> + <y>274</y> + </hint> + </hints> + </connection> + </connections> +</ui> diff --git a/muse2/share/instruments/gm.idf b/muse2/share/instruments/gm.idf index 6c346eb2..cdfff7e5 100644 --- a/muse2/share/instruments/gm.idf +++ b/muse2/share/instruments/gm.idf @@ -201,5 +201,7 @@ <Controller name="FineTuning" type="RPN" h="0" l="1" min="-64" max="63" init="0" /> <Controller name="Pitch" type="Pitch" /> <Controller name="Program" type="Program" /> + <Controller name="PolyAftertouch" type="PolyAftertouch" /> + <Controller name="Aftertouch" type="Aftertouch" /> </MidiInstrument> </muse> diff --git a/muse2/share/templates/MusE.cfg b/muse2/share/templates/MusE.cfg index 4d5840d6..7df28f44 100644 --- a/muse2/share/templates/MusE.cfg +++ b/muse2/share/templates/MusE.cfg @@ -3,6 +3,10 @@ <configuration> <division>384</division> <rtcTicks>1024</rtcTicks> + <midiSendInit>1</midiSendInit> + <warnInitPending>1</warnInitPending> + <midiSendCtlDefaults>0</midiSendCtlDefaults> + <warnIfBadTiming>1</warnIfBadTiming> <minMeter>-60</minMeter> <minSlider>-60</minSlider> <freewheelMode>0</freewheelMode> @@ -61,6 +65,7 @@ <outputTracksVisible>0</outputTracksVisible> <synthTracksVisible>0</synthTracksVisible> <smartFocus>1</smartFocus> + <velocityPerNote>0</velocityPerNote> <unhideTracks>1</unhideTracks> <addHiddenTracks>1</addHiddenTracks> <waveTracksVisible>1</waveTracksVisible> @@ -77,7 +82,7 @@ <font4>arial,8,-1,5,50,0,0,0,0,0</font4> <font5>arial,8,-1,5,75,0,0,0,0,0</font5> <font6>arial,8,-1,5,75,1,0,0,0,0</font6> - <globalAlphaBlend>190</globalAlphaBlend> + <globalAlphaBlend>170</globalAlphaBlend> <palette0 r="255" g="255" b="255"></palette0> <palette1 r="255" g="255" b="255"></palette1> <palette2 r="255" g="255" b="255"></palette2> diff --git a/muse2/xpm/velo_all.xpm b/muse2/xpm/velo_all.xpm new file mode 100644 index 00000000..4c8a509f --- /dev/null +++ b/muse2/xpm/velo_all.xpm @@ -0,0 +1,23 @@ +/* XPM */ +static const char * velo_all_xpm[] = { +"15 15 5 1", +" c None", +". c #58A8FF", +"+ c #000000", +"@ c #FFFFFF", +"# c #ED7700", +"...............", +".++++@.........", +".+++++.+.+.+##.", +".++++@......##.", +".@@@@@......##.", +".@@@@@......##.", +".++++@......##.", +".++++++.+##.##.", +".++++@...##.##.", +".@@@@@...##.##.", +".@@@@@...##.##.", +".++++@...##.##.", +".+++++##.##.##.", +".++++@##.##.##.", +"..............."}; diff --git a/muse2/xpm/velo_per_note.xpm b/muse2/xpm/velo_per_note.xpm new file mode 100644 index 00000000..1962f0e7 --- /dev/null +++ b/muse2/xpm/velo_per_note.xpm @@ -0,0 +1,25 @@ +/* XPM */ +static const char * velo_per_note_xpm[] = { +"15 15 7 1", +" c None", +". c #58A8FF", +"+ c #000000", +"@ c #FFFFFF", +"# c #D6D600", +"$ c #FFFF00", +"% c #ED7700", +"...............", +".++++@.........", +".+++++.........", +".++++@.........", +".@@@@@.........", +".@@@@@.........", +".####@.........", +".#$$$#+.+%%....", +".####@...%%....", +".@@@@@...%%....", +".@@@@@...%%....", +".++++@...%%....", +".+++++...%%....", +".++++@...%%....", +"..............."}; |