diff --git a/Source/AllKeysOverview.cpp b/Source/AllKeysOverview.cpp index 1aa688ce..b711460b 100644 --- a/Source/AllKeysOverview.cpp +++ b/Source/AllKeysOverview.cpp @@ -42,10 +42,12 @@ KeyMiniDisplayInsideAllKeysOverview::KeyMiniDisplayInsideAllKeysOverview(int new boardIndex = newBoardIndex; keyIndex = newKeyIndex; + TerpstraSysExApplication::getApp().getMidiDriver().addListener(this); } KeyMiniDisplayInsideAllKeysOverview::~KeyMiniDisplayInsideAllKeysOverview() { + TerpstraSysExApplication::getApp().getMidiDriver().removeListener(this); } void KeyMiniDisplayInsideAllKeysOverview::paint(Graphics& g) @@ -53,14 +55,21 @@ void KeyMiniDisplayInsideAllKeysOverview::paint(Graphics& g) jassert(getParentComponent() != nullptr); bool boardIsSelected = boardIndex == dynamic_cast(getParentComponent())->getCurrentSetSelection(); - Colour hexagonColour = findColour(TerpstraKeyEdit::backgroundColourId).overlaidWith(getKeyColour() - .withAlpha(boardIsSelected ? TERPSTRASINGLEKEYCOLOURALPHA : TERPSTRASINGLEKEYCOLOURUNSELECTEDMINIALPHA)); - // ToDo if highlighted: even different alpha? + float hexagonInteriorAlpha; + if (isHighlighted) + hexagonInteriorAlpha = TERPSTRASINGLEKEYCOLOURHIGHLIGHTEDALPHA; + else if (boardIsSelected) + hexagonInteriorAlpha = TERPSTRASINGLEKEYCOLOURALPHA; + else + hexagonInteriorAlpha = TERPSTRASINGLEKEYCOLOURUNSELECTEDMINIALPHA; + + Colour hexagonColour = findColour(TerpstraKeyEdit::backgroundColourId).overlaidWith( + getKeyColour().withAlpha(hexagonInteriorAlpha)); g.setColour(hexagonColour); g.fillPath(hexPath); // Key highlighted or not: color and thickness of the line - float lineWidth = isHighlighted ? 1.5 : 1; + float lineWidth = isHighlighted ? 2 : 1; Colour lineColour = findColour(isHighlighted ? TerpstraKeyEdit::selectedKeyOutlineId : TerpstraKeyEdit::outlineColourId); g.setColour(lineColour); g.strokePath(hexPath, PathStrokeType(1)); @@ -137,6 +146,20 @@ void KeyMiniDisplayInsideAllKeysOverview::mouseUp(const MouseEvent& e) } } +void KeyMiniDisplayInsideAllKeysOverview::midiMessageReceived(const MidiMessage& midiMessage) +{ + // ToDo If key is parametrized as controller? + if (midiMessage.isNoteOnOrOff()) + { + auto keyData = getKeyData(); + if (keyData != nullptr && midiMessage.getChannel() == keyData->channelNumber && midiMessage.getNoteNumber() == keyData->noteNumber) + { + isHighlighted = midiMessage.isNoteOn(); + repaint(); + } + } +} + const TerpstraKey* KeyMiniDisplayInsideAllKeysOverview::getKeyData() const { if (boardIndex >= 0 && boardIndex < NUMBEROFBOARDS && keyIndex >= 0 && keyIndex < TERPSTRABOARDSIZE) diff --git a/Source/AllKeysOverview.h b/Source/AllKeysOverview.h index 5c8460b9..5c3076ee 100644 --- a/Source/AllKeysOverview.h +++ b/Source/AllKeysOverview.h @@ -23,10 +23,11 @@ #include #include "KeyboardDataStructure.h" +#include "TerpstraMidiDriver.h" // Representation of a key inside the overview -class KeyMiniDisplayInsideAllKeysOverview : public Component +class KeyMiniDisplayInsideAllKeysOverview : public Component, public TerpstraMidiDriver::Listener { public: KeyMiniDisplayInsideAllKeysOverview(int newBoardIndex, int newKeyIndex); @@ -37,6 +38,12 @@ class KeyMiniDisplayInsideAllKeysOverview : public Component void mouseDown(const MouseEvent& e) override; void mouseUp(const juce::MouseEvent& e) override; + // Implementation of TerpstraNidiDriver::Listener + void midiMessageReceived(const MidiMessage& midiMessage) override; + void midiMessageSent(const MidiMessage& midiMessage) override {} + void midiSendQueueSize(int queueSize) override {} + void generalLogMessage(String textMessage, HajuErrorVisualizer::ErrorLevel errorLevel) override {} + private: JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(KeyMiniDisplayInsideAllKeysOverview) diff --git a/Source/MidiEditArea.cpp b/Source/MidiEditArea.cpp index 471d2269..6b781092 100644 --- a/Source/MidiEditArea.cpp +++ b/Source/MidiEditArea.cpp @@ -179,7 +179,7 @@ void MidiEditArea::comboBoxChanged (juce::ComboBox* comboBoxThatHasChanged) { //[UserComboBoxCode_cbMidiInput] -- add your combo box handling code here.. if (cbMidiInput->getSelectedItemIndex() >= 0) - TerpstraSysExApplication::getApp().getMidiDriver().setMidiInput(cbMidiInput->getSelectedItemIndex()+1); + TerpstraSysExApplication::getApp().getMidiDriver().setMidiInput(cbMidiInput->getSelectedItemIndex()); if (cbMidiInput->getSelectedItemIndex() < 0 || cbMidiOutput->getSelectedItemIndex() < 0) { diff --git a/Source/TerpstraMidiDriver.cpp b/Source/TerpstraMidiDriver.cpp index 7a8ecc9d..64766ecb 100644 --- a/Source/TerpstraMidiDriver.cpp +++ b/Source/TerpstraMidiDriver.cpp @@ -423,9 +423,11 @@ void TerpstraMidiDriver::sendMessageWithAcknowledge(const MidiMessage& message) else { // Add message to queue first. The oldest message in queue will be sent. - messageBuffer.add(message); - const MessageManagerLock mmLock; - this->listeners.call(&Listener::midiSendQueueSize, messageBuffer.size()); + { + messageBuffer.add(message); + const MessageManagerLock mmLock; + this->listeners.call(&Listener::midiSendQueueSize, messageBuffer.size()); + } // If there is no message waiting for acknowledge: send oldest message of queue if (!isTimerRunning()) @@ -445,8 +447,10 @@ void TerpstraMidiDriver::sendOldestMessageInQueue() currentMsgWaitingForAck = messageBuffer[0]; // oldest element in buffer hasMsgWaitingForAck = true; messageBuffer.remove(0); // remove from buffer - const MessageManagerLock mmLock; - this->listeners.call(&Listener::midiSendQueueSize, messageBuffer.size()); + { + const MessageManagerLock mmLock; + this->listeners.call(&Listener::midiSendQueueSize, messageBuffer.size()); + } sendCurrentMessage(); } @@ -460,8 +464,10 @@ void TerpstraMidiDriver::sendCurrentMessage() sendMessageNow(currentMsgWaitingForAck); // send it // Notify listeners - const MessageManagerLock mmLock; - this->listeners.call(&Listener::midiMessageSent, currentMsgWaitingForAck); + { + const MessageManagerLock mmLock; + this->listeners.call(&Listener::midiMessageSent, currentMsgWaitingForAck); + } timerType = waitForAnswer; startTimer(receiveTimeoutInMilliseconds); // Start waiting for answer @@ -470,8 +476,10 @@ void TerpstraMidiDriver::sendCurrentMessage() void TerpstraMidiDriver::handleIncomingMidiMessage(MidiInput* source, const MidiMessage& message) { // Notify listeners - const MessageManagerLock mmLock; - this->listeners.call(&Listener::midiMessageReceived, message); + { + const MessageManagerLock mmLock; + this->listeners.call(&Listener::midiMessageReceived, message); + } // Check whether received message is an answer to the previously sent one if (hasMsgWaitingForAck && messageIsResponseToMessage(message, currentMsgWaitingForAck)) @@ -511,8 +519,10 @@ void TerpstraMidiDriver::timerCallback() if (timerType == waitForAnswer) { // No answer came from MIDI input - const MessageManagerLock mmLock; - this->listeners.call(&Listener::generalLogMessage, "No answer from device", HajuErrorVisualizer::ErrorLevel::error); + { + const MessageManagerLock mmLock; + this->listeners.call(&Listener::generalLogMessage, "No answer from device", HajuErrorVisualizer::ErrorLevel::error); + } // For now: Remove from buffer, try to send next one hasMsgWaitingForAck = false; diff --git a/Source/ViewConstants.h b/Source/ViewConstants.h index d84bb537..f49f9165 100644 --- a/Source/ViewConstants.h +++ b/Source/ViewConstants.h @@ -31,6 +31,7 @@ #define TERPSTRASELECTEDKEYFLDLINEWIDTH 3.0f #define TERPSTRASINGLEKEYFLDMARGIN 1.5f #define TERPSTRASINGLEKEYROTATIONANGLE -0.25f +#define TERPSTRASINGLEKEYCOLOURHIGHLIGHTEDALPHA 0.9f #define TERPSTRASINGLEKEYCOLOURALPHA 0.8f #define TERPSTRASINGLEKEYCOLOURUNSELECTEDMINIALPHA 0.6f diff --git a/TerpstraSysEx.jucer b/TerpstraSysEx.jucer index 9d11138c..5bdf8576 100644 --- a/TerpstraSysEx.jucer +++ b/TerpstraSysEx.jucer @@ -1,6 +1,6 @@ -