diff --git a/.gitignore b/.gitignore index 3cf3ecc3f6..8e66b1f076 100644 --- a/.gitignore +++ b/.gitignore @@ -6,3 +6,5 @@ moc_*.cc /libs/hydrogen/include/hydrogen/config.h /cmake_opts /hydrogen +*.cbp +*.layout diff --git a/data/img/gray/instrumentEditor/instrumentTab_new.png b/data/img/gray/instrumentEditor/instrumentTab_new.png new file mode 100644 index 0000000000..b7edbad710 Binary files /dev/null and b/data/img/gray/instrumentEditor/instrumentTab_new.png differ diff --git a/data/xsd/drumkit.xsd b/data/xsd/drumkit.xsd index f62038bfd4..94786ac9f5 100644 --- a/data/xsd/drumkit.xsd +++ b/data/xsd/drumkit.xsd @@ -61,6 +61,9 @@ + + + diff --git a/src/core/include/hydrogen/IO/MidiInput.h b/src/core/include/hydrogen/IO/MidiInput.h index 0f33ba064c..edfc5635bb 100644 --- a/src/core/include/hydrogen/IO/MidiInput.h +++ b/src/core/include/hydrogen/IO/MidiInput.h @@ -51,12 +51,13 @@ class MidiInput : public virtual Object void handleSysexMessage( const MidiMessage& msg ); void handleControlChangeMessage( const MidiMessage& msg ); void handleProgramChangeMessage( const MidiMessage& msg ); + void handlePolyphonicKeyPressureMessage( const MidiMessage& msg ); protected: bool m_bActive; void handleNoteOnMessage( const MidiMessage& msg ); - void handleNoteOffMessage( const MidiMessage& msg ); + void handleNoteOffMessage( const MidiMessage& msg, bool CymbalChoke ); private: @@ -64,6 +65,8 @@ class MidiInput : public virtual Object unsigned long __noteOffTick; unsigned long computeDeltaNoteOnOfftime(); + int __hihat_cc_openess; + }; diff --git a/src/core/include/hydrogen/basics/instrument.h b/src/core/include/hydrogen/basics/instrument.h index 5a6b5150c3..f09e7b8919 100644 --- a/src/core/include/hydrogen/basics/instrument.h +++ b/src/core/include/hydrogen/basics/instrument.h @@ -237,6 +237,15 @@ class Instrument : public H2Core::Object /** get the stop notes of the instrument */ bool is_stop_notes() const; + void set_hihat( bool ishihat ); + bool is_hihat() const; + + void set_lower_cc( int message ); + int get_lower_cc() const; + + void set_higher_cc( int message ); + int get_higher_cc() const; + ///< set the name of the related drumkit void set_drumkit_name( const QString& name ); ///< get the name of the related drumkits @@ -268,6 +277,9 @@ class Instrument : public H2Core::Object int __queued; ///< count the number of notes queued within Sampler::__playing_notes_queue or std::priority_queue m_songNoteQueue float __fx_level[MAX_FX]; ///< Ladspa FX level array InstrumentLayer* __layers[MAX_LAYERS]; ///< InstrumentLayer array + bool __hihat; ///< the instrument is a hihat + int __lower_cc; ///< lower cc level + int __higher_cc; ///< higher cc level }; // DEFINITIONS @@ -506,6 +518,36 @@ inline bool Instrument::is_stop_notes() const return __stop_notes; } +inline void Instrument::set_hihat( bool ishihat ) +{ + __hihat = ishihat; +} + +inline bool Instrument::is_hihat() const +{ + return __hihat; +} + +inline void Instrument::set_lower_cc( int message ) +{ + __lower_cc = message; +} + +inline int Instrument::get_lower_cc() const +{ + return __lower_cc; +} + +inline void Instrument::set_higher_cc( int message ) +{ + __higher_cc = message; +} + +inline int Instrument::get_higher_cc() const +{ + return __higher_cc; +} + inline InstrumentLayer* Instrument::operator[]( int idx ) { assert( idx>=0 && idx data.control.channel; break; + case SND_SEQ_EVENT_KEYPRESS: + msg.m_type = MidiMessage::POLYPHONIC_KEY_PRESSURE; + msg.m_nData1 = ev->data.note.note; + msg.m_nData2 = ev->data.note.velocity; + msg.m_nChannel = ev->data.control.channel; + break; + case SND_SEQ_EVENT_SYSEX: { msg.m_type = MidiMessage::SYSEX; snd_midi_event_t *seq_midi_parser; diff --git a/src/core/src/IO/jack_midi_driver.cpp b/src/core/src/IO/jack_midi_driver.cpp index 364a366faf..4cb5af7013 100644 --- a/src/core/src/IO/jack_midi_driver.cpp +++ b/src/core/src/IO/jack_midi_driver.cpp @@ -117,6 +117,13 @@ JackMidiDriver::JackMidiWrite(jack_nframes_t nframes) msg.m_nChannel = buffer[0] & 0xF; handleMidiMessage(msg); break; + case 0xA: /* aftertouch */ + msg.m_type = MidiMessage::POLYPHONIC_KEY_PRESSURE; + msg.m_nData1 = buffer[1]; + msg.m_nData2 = buffer[2]; + msg.m_nChannel = buffer[0] & 0xF; + handleMidiMessage(msg); + break; case 0xB: /* control change */ msg.m_type = MidiMessage::CONTROL_CHANGE; msg.m_nData1 = buffer[1]; diff --git a/src/core/src/IO/midi_input.cpp b/src/core/src/IO/midi_input.cpp index 6dc6d8d94d..5690a0729e 100644 --- a/src/core/src/IO/midi_input.cpp +++ b/src/core/src/IO/midi_input.cpp @@ -37,6 +37,7 @@ namespace H2Core MidiInput::MidiInput( const char* class_name ) : Object( class_name ) , m_bActive( false ) + , __hihat_cc_openess ( 127 ) { //INFOLOG( "INIT" ); @@ -94,11 +95,14 @@ void MidiInput::handleMidiMessage( const MidiMessage& msg ) case MidiMessage::NOTE_OFF: INFOLOG("This is a NOTE OFF message."); - handleNoteOffMessage( msg ); + handleNoteOffMessage( msg, false ); break; case MidiMessage::POLYPHONIC_KEY_PRESSURE: - ERRORLOG( "POLYPHONIC_KEY_PRESSURE event not handled yet" ); + //ERRORLOG( "POLYPHONIC_KEY_PRESSURE event not handled yet" ); + INFOLOG( QString( "[handleMidiMessage] POLYPHONIC_KEY_PRESSURE Parameter: %1, Value: %2") + .arg( msg.m_nData1 ).arg( msg.m_nData2 ) ); + handlePolyphonicKeyPressureMessage( msg ); break; case MidiMessage::CONTROL_CHANGE: @@ -177,6 +181,9 @@ void MidiInput::handleControlChangeMessage( const MidiMessage& msg ) aH->handleAction( pAction ); + if(msg.m_nData1 == 04) + __hihat_cc_openess = msg.m_nData2; + pEngine->lastMidiEvent = "CC"; pEngine->lastMidiEventParameter = msg.m_nData1; } @@ -205,7 +212,7 @@ void MidiInput::handleNoteOnMessage( const MidiMessage& msg ) float fVelocity = msg.m_nData2 / 127.0; if ( fVelocity == 0 ) { - handleNoteOffMessage( msg ); + handleNoteOffMessage( msg, false ); return; } @@ -251,18 +258,52 @@ void MidiInput::handleNoteOnMessage( const MidiMessage& msg ) nInstrument = MAX_INSTRUMENTS - 1; } + InstrumentList *instrList = pEngine->getSong()->get_instrument_list(); + Instrument *instr = instrList->get( nInstrument ); + /* + Only look to change instrument if the + current note is actually of hihat and + hihat openess is outside the instrument selected + */ + if ( instr != NULL && + instr->is_hihat() && + ( __hihat_cc_openess < instr->get_lower_cc() || __hihat_cc_openess > instr->get_higher_cc() ) ) + { + for(int i=0 ; i<=instrList->size() ; i++) + { + Instrument *instr_contestant = instrList->get( i ); + if( instr_contestant != NULL && + instr_contestant->is_hihat() && + __hihat_cc_openess >= instr_contestant->get_lower_cc() && + __hihat_cc_openess <= instr_contestant->get_higher_cc() ) + { + nInstrument = i; + break; + } + } + } + pEngine->addRealtimeNote( nInstrument, fVelocity, fPan_L, fPan_R, 0.0, false, true, nNote ); } __noteOnTick = pEngine->__getMidiRealtimeNoteTickPosition(); } +/* + EDrums (at least Roland TD-6V) uses PolyphonicKeyPressure + for cymbal choke. + If the message is 127 (choked) we send a NoteOff +*/ +void MidiInput::handlePolyphonicKeyPressureMessage( const MidiMessage& msg ) +{ + if( msg.m_nData2 == 127 ) + handleNoteOffMessage( msg, true ); +} - -void MidiInput::handleNoteOffMessage( const MidiMessage& msg ) +void MidiInput::handleNoteOffMessage( const MidiMessage& msg, bool CymbalChoke ) { // INFOLOG( "handleNoteOffMessage" ); - if ( Preferences::get_instance()->m_bMidiNoteOffIgnore ) { + if ( !CymbalChoke && Preferences::get_instance()->m_bMidiNoteOffIgnore ) { return; } diff --git a/src/core/src/basics/instrument.cpp b/src/core/src/basics/instrument.cpp index acbed8c7e8..a0aee7d4f5 100644 --- a/src/core/src/basics/instrument.cpp +++ b/src/core/src/basics/instrument.cpp @@ -63,6 +63,9 @@ Instrument::Instrument( const int id, const QString& name, ADSR* adsr ) , __muted( false ) , __mute_group( -1 ) , __queued( 0 ) + , __hihat( false ) + , __lower_cc( 0 ) + , __higher_cc( 127 ) { if ( __adsr==0 ) __adsr = new ADSR(); for ( int i=0; iis_muted() ) , __mute_group( other->get_mute_group() ) , __queued( other->is_queued() ) + , __hihat( other->is_hihat() ) + , __lower_cc( other->get_lower_cc() ) + , __higher_cc( other->get_higher_cc() ) { for ( int i=0; iget_fx_level( i ); @@ -173,6 +179,9 @@ void Instrument::load_from( Drumkit* drumkit, Instrument* instrument, bool is_li this->set_midi_out_channel( instrument->get_midi_out_channel() ); this->set_midi_out_note( instrument->get_midi_out_note() ); this->set_stop_notes( instrument->is_stop_notes() ); + this->set_hihat( instrument->is_hihat() ); + this->set_lower_cc( instrument->get_lower_cc() ); + this->set_higher_cc( instrument->get_higher_cc() ); if ( is_live ) AudioEngine::get_instance()->unlock(); } @@ -214,6 +223,10 @@ Instrument* Instrument::load_from( XMLNode* node, const QString& dk_path, const instrument->set_midi_out_channel( node->read_int( "midiOutChannel", -1, true, false ) ); instrument->set_midi_out_note( node->read_int( "midiOutNote", MIDI_MIDDLE_C, true, false ) ); instrument->set_stop_notes( node->read_bool( "isStopNote", true ,false ) ); + instrument->set_hihat( node->read_bool( "isHihat", false, true ) ); + instrument->set_lower_cc( node->read_int( "lower_cc", 0, true ) ); + instrument->set_higher_cc( node->read_int( "higher_cc", 127, true ) ); + for ( int i=0; iset_fx_level( node->read_float( QString( "FX%1Level" ).arg( i+1 ), 0.0 ), i ); } @@ -269,6 +282,9 @@ void Instrument::save_to( XMLNode* node ) instrument_node.write_int( "midiOutChannel", __midi_out_channel ); instrument_node.write_int( "midiOutNote", __midi_out_note ); instrument_node.write_bool( "isStopNote", __stop_notes ); + instrument_node.write_bool( "isHihat", __hihat ); + instrument_node.write_int( "lower_cc", __lower_cc ); + instrument_node.write_int( "higher_cc", __higher_cc ); for ( int i=0; iset_midi_out_channel( instrument_node.read_int( "midiOutChannel", -1, true, false ) ); instrument->set_midi_out_note( instrument_node.read_int( "midiOutNote", MIDI_MIDDLE_C, true, false ) ); instrument->set_stop_notes( instrument_node.read_bool( "isStopNote", true ,false ) ); + instrument->set_hihat( instrument_node.read_bool( "isHihat", false, true ) ); + instrument->set_lower_cc( instrument_node.read_int( "lower_cc", 0, true ) ); + instrument->set_higher_cc( instrument_node.read_int( "higher_cc", 127, true ) ); for ( int i=0; iset_fx_level( instrument_node.read_float( QString( "FX%1Level" ).arg( i+1 ), 0.0 ), i ); } diff --git a/src/gui/src/InstrumentEditor/InstrumentEditor.cpp b/src/gui/src/InstrumentEditor/InstrumentEditor.cpp index 8c20450432..e32e421dc8 100644 --- a/src/gui/src/InstrumentEditor/InstrumentEditor.cpp +++ b/src/gui/src/InstrumentEditor/InstrumentEditor.cpp @@ -95,16 +95,16 @@ InstrumentEditor::InstrumentEditor( QWidget* pParent ) // Instrument properties m_pInstrumentProp = new PixmapWidget( this ); m_pInstrumentProp->move(0, 31); - m_pInstrumentProp->setPixmap( "/instrumentEditor/instrumentTab.png" ); + m_pInstrumentProp->setPixmap( "/instrumentEditor/instrumentTab_new.png" ); m_pNameLbl = new ClickableLabel( m_pInstrumentProp ); m_pNameLbl->setGeometry( 8, 5, 275, 28 ); - + ///////////// //Midi Out - + m_pMidiOutChannelLCD = new LCDDisplay( m_pInstrumentProp, LCDDigit::SMALL_BLUE, 4 ); - m_pMidiOutChannelLCD->move( 67, 243 ); + m_pMidiOutChannelLCD->move( 67, 261 ); m_pAddMidiOutChannelBtn = new Button( m_pInstrumentProp, @@ -114,7 +114,7 @@ InstrumentEditor::InstrumentEditor( QWidget* pParent ) QSize( 16, 8 ) ); - m_pAddMidiOutChannelBtn->move( 109, 243 ); + m_pAddMidiOutChannelBtn->move( 109, 260 ); connect( m_pAddMidiOutChannelBtn, SIGNAL( clicked(Button*) ), this, SLOT( midiOutChannelBtnClicked(Button*) ) ); @@ -125,12 +125,12 @@ InstrumentEditor::InstrumentEditor( QWidget* pParent ) "/lcd/LCDSpinBox_down_over.png", QSize(16,8) ); - m_pDelMidiOutChannelBtn->move( 109, 251 ); + m_pDelMidiOutChannelBtn->move( 109, 269 ); connect( m_pDelMidiOutChannelBtn, SIGNAL( clicked(Button*) ), this, SLOT( midiOutChannelBtnClicked(Button*) ) ); - + /// m_pMidiOutNoteLCD = new LCDDisplay( m_pInstrumentProp, LCDDigit::SMALL_BLUE, 4 ); - m_pMidiOutNoteLCD->move( 160, 243 ); + m_pMidiOutNoteLCD->move( 160, 261 ); m_pAddMidiOutNoteBtn = new Button( m_pInstrumentProp, @@ -140,7 +140,7 @@ InstrumentEditor::InstrumentEditor( QWidget* pParent ) QSize( 16, 8 ) ); - m_pAddMidiOutNoteBtn->move( 202, 243 ); + m_pAddMidiOutNoteBtn->move( 202, 260 ); connect( m_pAddMidiOutNoteBtn, SIGNAL( clicked(Button*) ), this, SLOT( midiOutNoteBtnClicked(Button*) ) ); @@ -151,9 +151,9 @@ InstrumentEditor::InstrumentEditor( QWidget* pParent ) "/lcd/LCDSpinBox_down_over.png", QSize(16,8) ); - m_pDelMidiOutNoteBtn->move( 202, 251 ); + m_pDelMidiOutNoteBtn->move( 202, 269 ); connect( m_pDelMidiOutNoteBtn, SIGNAL( clicked(Button*) ), this, SLOT( midiOutNoteBtnClicked(Button*) ) ); - + ///////////// QFont boldFont; @@ -162,7 +162,7 @@ InstrumentEditor::InstrumentEditor( QWidget* pParent ) connect( m_pNameLbl, SIGNAL( labelClicked(ClickableLabel*) ), this, SLOT( labelClicked(ClickableLabel*) ) ); m_pRandomPitchRotary = new Rotary( m_pInstrumentProp, Rotary::TYPE_NORMAL, trUtf8( "Random pitch factor" ), false, true ); - m_pRandomPitchRotary->move( 117, 192 ); + m_pRandomPitchRotary->move( 117, 210 ); connect( m_pRandomPitchRotary, SIGNAL( valueChanged(Rotary*) ), this, SLOT( rotaryChanged(Rotary*) ) ); // Filter @@ -181,9 +181,9 @@ InstrumentEditor::InstrumentEditor( QWidget* pParent ) m_pResonanceRotary = new Rotary( m_pInstrumentProp, Rotary::TYPE_NORMAL, trUtf8( "Filter resonance" ), false, true ); connect( m_pResonanceRotary, SIGNAL( valueChanged(Rotary*) ), this, SLOT( rotaryChanged(Rotary*) ) ); - m_pFilterBypassBtn->move( 70, 152 ); - m_pCutoffRotary->move( 117, 146 ); - m_pResonanceRotary->move( 170, 146 ); + m_pFilterBypassBtn->move( 70, 170 ); + m_pCutoffRotary->move( 117, 164 ); + m_pResonanceRotary->move( 170, 164 ); //~ Filter // ADSR @@ -234,11 +234,70 @@ InstrumentEditor::InstrumentEditor( QWidget* pParent ) m_pDelMuteGroupBtn->move( 202, 113 ); connect( m_pDelMuteGroupBtn, SIGNAL( clicked(Button*) ), this, SLOT( muteGroupBtnClicked(Button*) ) ); - m_pIsStopNoteCheckBox = new QCheckBox ( trUtf8( "Auto-Stop-Note" ), m_pInstrumentProp ); - m_pIsStopNoteCheckBox->move( 15, 300 ); + m_pIsStopNoteCheckBox = new QCheckBox ( trUtf8( "" ), m_pInstrumentProp ); + m_pIsStopNoteCheckBox->move( 63, 138 ); m_pIsStopNoteCheckBox->setToolTip( trUtf8( "Stop the current playing instrument-note before trigger the next note sample." ) ); connect( m_pIsStopNoteCheckBox, SIGNAL( toggled( bool ) ), this, SLOT( onIsStopNoteCheckBoxClicked( bool ) ) ); + ////////////////////////// + // HiHat setup + + m_pIsHihat = new QCheckBox ( trUtf8( "" ), m_pInstrumentProp ); + m_pIsHihat->move( 63, 304 ); + m_pIsHihat->setToolTip( trUtf8( "Set the instrument as part of a hihat set." ) ); + connect( m_pIsHihat, SIGNAL( toggled( bool ) ), this, SLOT( pIsHihatCheckBoxClicked( bool ) ) ); + + + m_pHihatMinRangeLCD = new LCDDisplay( m_pInstrumentProp, LCDDigit::SMALL_BLUE, 4 ); + m_pHihatMinRangeLCD->move( 67, 320 ); + + m_pAddHihatMinRangeBtn = new Button( + m_pInstrumentProp, + "/lcd/LCDSpinBox_up_on.png", + "/lcd/LCDSpinBox_up_off.png", + "/lcd/LCDSpinBox_up_over.png", + QSize( 16, 8 ) + ); + m_pAddHihatMinRangeBtn->move( 109, 319 ); + connect( m_pAddHihatMinRangeBtn, SIGNAL( clicked(Button*) ), this, SLOT( hihatMinRangeBtnClicked(Button*) ) ); + + m_pDelHihatMinRangeBtn = new Button( + m_pInstrumentProp, + "/lcd/LCDSpinBox_down_on.png", + "/lcd/LCDSpinBox_down_off.png", + "/lcd/LCDSpinBox_down_over.png", + QSize(16,8) + ); + m_pDelHihatMinRangeBtn->move( 109, 328 ); + connect( m_pDelHihatMinRangeBtn, SIGNAL( clicked(Button*) ), this, SLOT( hihatMinRangeBtnClicked(Button*) ) ); + + + m_pHihatMaxRangeLCD = new LCDDisplay( m_pInstrumentProp, LCDDigit::SMALL_BLUE, 4 ); + m_pHihatMaxRangeLCD->move( 160, 320 ); + + m_pAddHihatMaxRangeBtn = new Button( + m_pInstrumentProp, + "/lcd/LCDSpinBox_up_on.png", + "/lcd/LCDSpinBox_up_off.png", + "/lcd/LCDSpinBox_up_over.png", + QSize( 16, 8 ) + ); + m_pAddHihatMaxRangeBtn->move( 202, 319 ); + connect( m_pAddHihatMaxRangeBtn, SIGNAL( clicked(Button*) ), this, SLOT( hihatMaxRangeBtnClicked(Button*) ) ); + + m_pDelHihatMaxRangeBtn = new Button( + m_pInstrumentProp, + "/lcd/LCDSpinBox_down_on.png", + "/lcd/LCDSpinBox_down_off.png", + "/lcd/LCDSpinBox_down_over.png", + QSize(16,8) + ); + m_pDelHihatMaxRangeBtn->move( 202, 328 ); + connect( m_pDelHihatMaxRangeBtn, SIGNAL( clicked(Button*) ), this, SLOT( hihatMaxRangeBtnClicked(Button*) ) ); + + // + + //~ Instrument properties @@ -255,7 +314,7 @@ InstrumentEditor::InstrumentEditor( QWidget* pParent ) // Layer preview m_pLayerPreview = new LayerPreview( NULL ); - + m_pLayerScrollArea = new QScrollArea( m_pLayerProp); m_pLayerScrollArea->setFrameShape( QFrame::NoFrame ); m_pLayerScrollArea->move( 6, 4 ); @@ -421,22 +480,29 @@ void InstrumentEditor::selectedInstrumentChangedEvent() if (m_pInstrument->get_mute_group() == -1 ) { sMuteGroup = "Off"; } - m_pMuteGroupLCD->setText( sMuteGroup ); - + m_pMuteGroupLCD->setText( sMuteGroup ); + // midi out QString sMidiOutChannel = QString("%1").arg( m_pInstrument->get_midi_out_channel()+1); if (m_pInstrument->get_midi_out_channel() == -1 ) { sMidiOutChannel = "Off"; } m_pMidiOutChannelLCD->setText( sMidiOutChannel ); - + + // hihat + m_pIsHihat->setChecked( m_pInstrument->is_hihat() ); + QString sHiHatMinRange = QString("%1").arg( m_pInstrument->get_lower_cc() ); + m_pHihatMinRangeLCD->setText( sHiHatMinRange ); + QString sHiHatMaxRange = QString("%1").arg( m_pInstrument->get_higher_cc() ); + m_pHihatMaxRangeLCD->setText( sHiHatMaxRange ); + //Convert note id into notation { int note = m_pInstrument->get_midi_out_note(); int octave = (note / 12) - 2; const char *noteStrs[12] = { "C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B" }; QString sMidiOutNote = QString(noteStrs[note % 12]) + QString::number(octave); - m_pMidiOutNoteLCD->setText( sMidiOutNote ); + m_pMidiOutNoteLCD->setText( sMidiOutNote ); } // select the last valid layer @@ -593,7 +659,7 @@ void InstrumentEditor::buttonClicked( Button* pButton ) HydrogenApp::get_instance()->showSampleEditor( name, m_nSelectedLayer ); } } - + } else { ERRORLOG( "[buttonClicked] unhandled button" ); @@ -620,7 +686,7 @@ void InstrumentEditor::loadLayer() if ( filename[2].isEmpty() ) return; - bool fnc = false; + bool fnc = false; if ( filename[0] == "true" ){ fnc = true; } @@ -630,36 +696,36 @@ void InstrumentEditor::loadLayer() int selectedLayer = m_nSelectedLayer; int firstSelection = selectedLayer; - - + + if (filename.size() > 2) { - - for(int i=2;i < filename.size();++i) + + for(int i=2;i < filename.size();++i) { selectedLayer = m_nSelectedLayer + i - 2; if( ( i-2 >= MAX_LAYERS ) || ( selectedLayer + 1 > MAX_LAYERS ) ) break; Sample *newSample = Sample::load( filename[i] ); - + H2Core::Instrument *pInstr = NULL; - + AudioEngine::get_instance()->lock( RIGHT_HERE ); Song *song = engine->getSong(); InstrumentList *instrList = song->get_instrument_list(); pInstr = instrList->get( engine->getSelectedInstrumentNumber() ); - - /* - if we're using multiple layers, we start inserting the first layer + + /* + if we're using multiple layers, we start inserting the first layer at m_nSelectedLayer and the next layer at m_nSelectedLayer+1 */ - + H2Core::InstrumentLayer *pLayer = pInstr->get_layer( selectedLayer ); if (pLayer != NULL) { // delete old sample Sample *oldSample = pLayer->get_sample(); delete oldSample; - + // insert new sample from newInstrument pLayer->set_sample( newSample ); } @@ -667,20 +733,20 @@ void InstrumentEditor::loadLayer() pLayer = new H2Core::InstrumentLayer(newSample); pInstr->set_layer( pLayer, selectedLayer ); } - + if ( fnc ){ QString newFilename = filename[i].section( '/', -1 ); newFilename.replace( "." + newFilename.section( '.', -1 ), ""); m_pInstrument->set_name( newFilename ); } - + //set automatic velocity if ( filename[1] == "true" ){ setAutoVelocity(); } - + //pInstr->set_drumkit_name( "" ); // external sample, no drumkit info - + AudioEngine::get_instance()->unlock(); } @@ -877,13 +943,13 @@ void InstrumentEditor::midiOutNoteBtnClicked(Button *pRef) ); if( !newSample ){ continue; - } + } delete pSample; // insert new sample from newInstrument AudioEngine::get_instance()->lock( RIGHT_HERE ); pLayer->set_sample( newSample ); AudioEngine::get_instance()->unlock(); - + } } } @@ -893,3 +959,35 @@ void InstrumentEditor::midiOutNoteBtnClicked(Button *pRef) } } + +void InstrumentEditor::pIsHihatCheckBoxClicked( bool on ) +{ + assert( m_pInstrument ); + + m_pInstrument->set_hihat( on ); + selectedInstrumentChangedEvent(); // force an update +} + +void InstrumentEditor::hihatMinRangeBtnClicked(Button *pRef) +{ + assert( m_pInstrument ); + + if ( pRef == m_pAddHihatMinRangeBtn && m_pInstrument->get_lower_cc() < 127 ) + m_pInstrument->set_lower_cc( m_pInstrument->get_lower_cc() + 1 ); + else if ( pRef == m_pDelHihatMinRangeBtn && m_pInstrument->get_lower_cc() > 0 ) + m_pInstrument->set_lower_cc( m_pInstrument->get_lower_cc() - 1 ); + + selectedInstrumentChangedEvent(); // force an update +} + +void InstrumentEditor::hihatMaxRangeBtnClicked(Button *pRef) +{ + assert( m_pInstrument ); + + if ( pRef == m_pAddHihatMaxRangeBtn && m_pInstrument->get_higher_cc() < 127 ) + m_pInstrument->set_higher_cc( m_pInstrument->get_higher_cc() + 1); + else if ( pRef == m_pDelHihatMaxRangeBtn && m_pInstrument->get_higher_cc() > 0 ) + m_pInstrument->set_higher_cc( m_pInstrument->get_higher_cc() - 1); + + selectedInstrumentChangedEvent(); // force an update +} diff --git a/src/gui/src/InstrumentEditor/InstrumentEditor.h b/src/gui/src/InstrumentEditor/InstrumentEditor.h index 3f0f31a55b..50edef746c 100644 --- a/src/gui/src/InstrumentEditor/InstrumentEditor.h +++ b/src/gui/src/InstrumentEditor/InstrumentEditor.h @@ -73,6 +73,10 @@ class InstrumentEditor : public QWidget, public H2Core::Object, public EventList void midiOutChannelBtnClicked(Button *pRef); void midiOutNoteBtnClicked(Button *pRef); + void pIsHihatCheckBoxClicked( bool on); + void hihatMinRangeBtnClicked(Button *pRef); + void hihatMaxRangeBtnClicked(Button *pRef); + private: H2Core::Instrument *m_pInstrument; int m_nSelectedLayer; @@ -107,15 +111,27 @@ class InstrumentEditor : public QWidget, public H2Core::Object, public EventList LCDDisplay *m_pMuteGroupLCD; Button *m_pAddMuteGroupBtn; Button *m_pDelMuteGroupBtn; - + // Instrument midi out LCDDisplay *m_pMidiOutChannelLCD; Button *m_pAddMidiOutChannelBtn; Button *m_pDelMidiOutChannelBtn; - + LCDDisplay *m_pMidiOutNoteLCD; Button *m_pAddMidiOutNoteBtn; - Button *m_pDelMidiOutNoteBtn; + Button *m_pDelMidiOutNoteBtn; + + // Instrument hihat + + QCheckBox *m_pIsHihat; + + LCDDisplay *m_pHihatMinRangeLCD; + Button *m_pAddHihatMinRangeBtn; + Button *m_pDelHihatMinRangeBtn; + + LCDDisplay *m_pHihatMaxRangeLCD; + Button *m_pAddHihatMaxRangeBtn; + Button *m_pDelHihatMaxRangeBtn; //~ Instrument properties @@ -123,7 +139,7 @@ class InstrumentEditor : public QWidget, public H2Core::Object, public EventList // Layer properties LayerPreview *m_pLayerPreview; QScrollArea *m_pLayerScrollArea; - + PixmapWidget *m_pLayerProp; Rotary *m_pLayerGainRotary; diff --git a/src/gui/src/widgets/Button.cpp b/src/gui/src/widgets/Button.cpp index eb65446ae0..c20611d61b 100644 --- a/src/gui/src/widgets/Button.cpp +++ b/src/gui/src/widgets/Button.cpp @@ -66,6 +66,10 @@ Button::Button( QWidget * pParent, const QString& sOnImage, const QString& sOffI } this->setStyleSheet("font-size: 9px; font-weight: bold;"); + + m_timerTimeout = 0; + m_timer = new QTimer(this); + connect(m_timer, SIGNAL(timeout()), this, SLOT(buttonPressed_timer_timeout())); } @@ -126,7 +130,14 @@ void Button::mousePressEvent(QMouseEvent*ev) { m_bPressed = true; update(); + emit mousePress(this); + + if ( ev->button() == Qt::LeftButton ) + { + m_timerTimeout = 2000; + buttonPressed_timer_timeout(); + } } @@ -136,12 +147,20 @@ void Button::mouseReleaseEvent(QMouseEvent* ev) setPressed( false ); if (ev->button() == Qt::LeftButton) { - emit clicked(this); + m_timer->stop(); } else if (ev->button() == Qt::RightButton) { emit rightClicked(this); } +} + +void Button::buttonPressed_timer_timeout() +{ + emit clicked(this); + if(m_timerTimeout > 50) + m_timerTimeout = m_timerTimeout / 2; + m_timer->start(m_timerTimeout); } void Button::setFontSize(int size) diff --git a/src/gui/src/widgets/Button.h b/src/gui/src/widgets/Button.h index 1452fbd8cf..4f28804527 100644 --- a/src/gui/src/widgets/Button.h +++ b/src/gui/src/widgets/Button.h @@ -64,6 +64,9 @@ class Button : public QWidget, public H2Core::Object, public MidiLearnable void rightClicked(Button *pBtn); void mousePress(Button *pBtn); + protected slots: + void buttonPressed_timer_timeout(); + protected: bool m_bPressed; @@ -84,6 +87,9 @@ class Button : public QWidget, public H2Core::Object, public MidiLearnable void leaveEvent(QEvent *ev); void paintEvent( QPaintEvent* ev); + QTimer *m_timer; + int m_timerTimeout; + bool loadImage( const QString& sFilename, QPixmap& pixmap ); };