This Custom Keyboard Slaps!
-
…or maybe just taps. But anyways…
Cleverly, I positioned the cursor right over the MIDI channel number readout, so you don't see anything change—and then suddenly, change 16. sigh
////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // // // // SETTINGS - DIAGNOSTICS [UI THREAD] // // // // BILL EVANS // // // ////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////// COLOUR THE KEYBOARD FUNCTION /////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////// inline function ColourMidiKeyboard (theContext) { local whiteKeyColour = null; local blackKeyColour = null; local upperKeyLimit = null; // Set enabled and visible states. switch (theContext) { case "init": local whiteKeyColour = Colours.withAlpha(0xFFEBECF3, 0.25); local blackKeyColour = Colours.withAlpha(0xFF212126, 0.25); upperKeyLimit = 127; break; case "ready": local whiteKeyColour = 0xFF212126; local blackKeyColour = 0xFFEBECF3; upperKeyLimit = g_NumOfSamples.notes; break; case "derivatives": local whiteKeyColour = 0xFF4c8d39; local blackKeyColour = 0xFF98c28c; upperKeyLimit = 127; break; } // Colour the keyboard. local whitekeys = [0, 2, 4, 5, 7, 9, 11]; // Colour the keys. for(keyNumber = 0; keyNumber < upperKeyLimit; keyNumber += 1) { if (whitekeys.contains(keyNumber % 12)) Engine.setKeyColour (keyNumber, blackKeyColour); else Engine.setKeyColour (keyNumber, whiteKeyColour); } } ////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////// DISPLAY MIDI INFO FUNCTIONS ////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // ================================================ Updating inline function UpdateDiagnosticMidiDisplay (dataFlow) { if (dataFlow.type == "note_on") { label_GLOBAL_Meter_MIDI_In_Channel_ART.set("text", "Channel: " + dataFlow.midiNoteChannel); label_GLOBAL_Meter_MIDI_In_NoteOn_ART.set("text", "Number: " + dataFlow.midiNoteNumber); label_GLOBAL_Meter_MIDI_In_Velocity_ART.set("text", "Velocity:" + dataFlow.midiNoteVelocity); } else { label_GLOBAL_Meter_MIDI_Out_Channel_ART.set("text", "Channel: " + dataFlow.midiNoteChannel); label_GLOBAL_Meter_MIDI_Out_NoteOn_ART.set("text", "Number: " + dataFlow.midiNoteNumber); label_GLOBAL_Meter_MIDI_Out_Velocity_ART.set("text", "Velocity: " + dataFlow.midiNoteVelocity); } } ////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////// GENERAL INFO PANE FUNCTIONS ////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // ================================================ Updating inline function UpdateDiagnosticReadouts () { local sampleRateText; switch(Engine.getSampleRate()) { case 44100: sampleRateText = "44.1"; break; case 48000: sampleRateText = "48"; break; case 88200: sampleRateText = "88.2"; break; case 96000: sampleRateText = "96"; break; case 176400: sampleRateText = "176.4"; break; case 192000: sampleRateText = "192"; break; default: sampleRateText = Engine.getSampleRate(); break; } // Set up the meters. label_GLOBAL_Meters_General_SampleRate_ART.set("text", "Rate: " + sampleRateText + " kHz"); label_GLOBAL_Meters_General_Latency_ART.set("text", "Latency: " + Engine.getLatencySamples() + " ms"); label_GLOBAL_Meters_General_NumChannels_ART.set("text", "Ouput Channels: " + Engine.getNumPluginChannels()); label_GLOBAL_Meters_General_MaxBufferSize_ART.set("text", "Maximum Buffer: " + Engine.getBufferSize()); label_GLOBAL_Meters_General_MpeEnabled_ART.set("text", "MPE Mode: " + (Engine.isMpeEnabled() ? 'Off' : 'On')) ; } // =========================================== Updating Diagnostics button_GLOBAL_ChooseOptions_UpdateSampleRate_GUI.setControlCallback(onbutton_GLOBAL_ChooseOptions_UpdateSampleRate_GUIControl); inline function onbutton_GLOBAL_ChooseOptions_UpdateSampleRate_GUIControl(component, value) { UpdateDiagnosticReadouts (); }; ////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////// KEYBOARD UTILITY FUNCTIONS /////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // =============================================== Get Keyboard Data inline function GetKeyboardData () { return tile_GLOBAL_Keyboard_TheKeyboard_ART.get("Data").parseAsJSON(); } // =============================================== Set Keyboard Data inline function SetKeyboardData (keyboardData) { keyboardData.Type = "Keyboard"; tile_GLOBAL_Keyboard_TheKeyboard_ART.set("Data", trace(keyboardData)); } // =============================================== Reset Keyboard inline function ResetMidiKeyboard (resetContext) { // Get a reference to the keyboard component. local keyboardData = GetKeyboardData (); // Change the values in the JSON records. keyboardData.LowKey = 0; keyboardData.HiKey = 23; keyboardData.MidiChannel = 1; // Set the values in the keyboard. SetKeyboardData(keyboardData); // Reset the text fields. label_GLOBAL_Keyboard_ChannelValue_ART.set("text", "1"); label_GLOBAL_Keyboard_OctaveValue_ART.set("text", "1"); // Set enabled and visible states. switch (resetContext) { case "init": // Disable/hide octave interface. button_GLOBAL_Keyboard_OctaveUp_GUI.set("enabled", false); button_GLOBAL_Keyboard_OctaveDown_GUI.set("enabled", false); label_GLOBAL_Keyboard_OctaveValue_ART.set("visible", false); // Disable/hide channel interface. button_GLOBAL_Keyboard_ChannelDown_GUI.set("enabled", false); button_GLOBAL_Keyboard_ChannelUp_GUI.set("enabled", false); label_GLOBAL_Keyboard_ChannelValue_ART.set("visible", false); break; case "ready": // Enable/show octave interface. button_GLOBAL_Keyboard_OctaveUp_GUI.set("enabled", true); button_GLOBAL_Keyboard_OctaveDown_GUI.set("enabled", true); label_GLOBAL_Keyboard_OctaveValue_ART.set("visible", true); // Enable/show channel interface. button_GLOBAL_Keyboard_ChannelDown_GUI.set("enabled", true); button_GLOBAL_Keyboard_ChannelUp_GUI.set("enabled", true); label_GLOBAL_Keyboard_ChannelValue_ART.set("visible", true); break; } } ////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////// KEYBOARD CHANNEL FUNCTIONS ////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // Registering all four buttons to a broadcaster, and making the callback function a receiver would be more elegant. // ================================================ Registration button_GLOBAL_Keyboard_OctaveDown_GUI.setControlCallback(MidiKeyboardParamButtonCallback); button_GLOBAL_Keyboard_ChannelDown_GUI.setControlCallback(MidiKeyboardParamButtonCallback); button_GLOBAL_Keyboard_ChannelUp_GUI.setControlCallback(MidiKeyboardParamButtonCallback); button_GLOBAL_Keyboard_OctaveUp_GUI.setControlCallback(MidiKeyboardParamButtonCallback); // =================================================== Callback inline function MidiKeyboardParamButtonCallback (component, value) { // The buttons are momentary, so only do something when they are pressed in. if (value) { // Get a reference to the keyboard component. local keyboardData = GetKeyboardData(); local newValue = null; // Create variables for the display component that will be updated, and the new display text. local displayComponent = null; local displayText = null; // This section could be much shorter. switch (component.get("id")) { case "button_GLOBAL_Keyboard_ChannelUp_GUI": if (keyboardData.MidiChannel == 16) { ColourMidiKeyboard ("init"); ColourMidiKeyboard ("ready"); } if (keyboardData.MidiChannel < 16) keyboardData.MidiChannel += 1; else keyboardData.MidiChannel = 1; displayComponent = label_GLOBAL_Keyboard_ChannelValue_ART; displayText = keyboardData.MidiChannel; if (keyboardData.MidiChannel == 16) ColourMidiKeyboard ("derivatives"); break; case "button_GLOBAL_Keyboard_ChannelDown_GUI": if (keyboardData.MidiChannel > 1) keyboardData.MidiChannel -= 1; else keyboardData.MidiChannel = 16; displayComponent = label_GLOBAL_Keyboard_ChannelValue_ART; displayText = keyboardData.MidiChannel; break; case "button_GLOBAL_Keyboard_OctaveUp_GUI": if (keyboardData.LowKey >= 96) { if (keyboardData.LowKey == 120) { keyboardData.LowKey = 0; keyboardData.HiKey = 23; } else { keyboardData.LowKey = 120; keyboardData.HiKey = 127; } } else { keyboardData.LowKey += 12; keyboardData.HiKey += 12; } displayComponent = label_GLOBAL_Keyboard_OctaveValue_ART; displayText = parseInt(keyboardData.HiKey/12)-1; break; case "button_GLOBAL_Keyboard_OctaveDown_GUI": if (keyboardData.LowKey < 24) { // There is a bug in HISE, so this won't be displayed correctly. keyboardData.LowKey = 120; keyboardData.HiKey = 127; } else { if (keyboardData.LowKey == 120) { keyboardData.LowKey = 96; keyboardData.HiKey = 120; } else { keyboardData.LowKey -= 12; keyboardData.HiKey -= 12; } } displayComponent = label_GLOBAL_Keyboard_OctaveValue_ART; displayText = parseInt(keyboardData.HiKey/12)-1; break; default: // Throw error. } // Set the new keyboard data. SetKeyboardData (keyboardData); // Update the label. if (isDefined(displayComponent)) displayComponent.set("text", displayText); else; // Throw error. } } ////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////// STANDARD LIBRARY: CORE FUNCTION //////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // This section implements my broadcaster system. You'd obviously change the implementation for your own plugin. // "init" is received during OnInit(), and "ready" is received after a SampleMap finishes loading. I've // omitted the other commands the function receives, as they're not relevant to this code example. inline function GLOBAL_CONFIGURE_Diagnostics (moduleState) { // ============================================== Reset Ops if (moduleState == "init" || moduleState == "ready") { // ------------- Diagnostic Info label_GLOBAL_Meter_MIDI_In_Channel_ART.set("text", "Channel: None"); label_GLOBAL_Meter_MIDI_In_NoteOn_ART.set("text", "Note On: None"); label_GLOBAL_Meter_MIDI_In_Velocity_ART.set("text","Velocity: None"); label_GLOBAL_Meter_MIDI_Out_Channel_ART.set("text", "Channel: None"); label_GLOBAL_Meter_MIDI_Out_NoteOn_ART.set("text", "Note On: None"); label_GLOBAL_Meter_MIDI_Out_Velocity_ART.set("text", "Velocity: None"); // ------------- Global // Enable the global? if (combo_GLOBAL_ChooseOptions_Hidden_DiagnosticMeters_HPS.getValue()==COMBO_ON) g_diagnosticKeyboardActive = true; else g_diagnosticKeyboardActive = false; // ------------- Keyboard // Reset it. ResetMidiKeyboard ("init"); ColourMidiKeyboard ("init"); // ------------- Displays UpdateDiagnosticReadouts(); } // =============================================== Specific Ops switch(moduleState) { case "init": // Cover it. panel_GLOBAL_Meters_Piano_Cover_ART.showControl(true); panel_GLOBAL_Meters_MIDI_Out_Cover_ART.showControl(true); panel_GLOBAL_Meters_MIDI_In_Cover_ART.showControl(true); break; case "ready": // ====================================== Showing MIDI Text label_GLOBAL_Meter_MIDI_In_NoteOn_ART.showControl(true); label_GLOBAL_Meter_MIDI_In_Channel_ART.showControl(true); label_GLOBAL_Meter_MIDI_In_Velocity_ART.showControl(true); label_GLOBAL_Meter_MIDI_Out_Channel_ART.showControl(true); label_GLOBAL_Meter_MIDI_Out_NoteOn_ART.showControl(true); label_GLOBAL_Meter_MIDI_Out_Velocity_ART.showControl(true); // ====================================== Keyboard // Reveal it. panel_GLOBAL_Meters_Piano_Cover_ART.fadeComponent(false, SUBMODULE_VISIBILITY_FADE_TIME); panel_GLOBAL_Meters_MIDI_Out_Cover_ART.fadeComponent(false, SUBMODULE_VISIBILITY_FADE_TIME); panel_GLOBAL_Meters_MIDI_In_Cover_ART.fadeComponent(false, SUBMODULE_VISIBILITY_FADE_TIME); // ------------- Keyboard // Reset it. ResetMidiKeyboard ("ready"); ColourMidiKeyboard ("ready"); // Set the display. UpdateDiagnosticReadouts(); break; case "update_display": if ( (combo_GLOBAL_ChooseOptions_Hidden_DiagnosticMeters_HPS.getValue()==COMBO_ON) && (panel_FRAME_GLOBAL.get("visible")) ){ UpdateDiagnosticReadouts(); } } };