| 
							- /*
 -   ==============================================================================
 - 
 -    This file is part of the JUCE library - "Jules' Utility Class Extensions"
 -    Copyright 2004-12 by Raw Material Software Ltd.
 - 
 -   ------------------------------------------------------------------------------
 - 
 -    JUCE can be redistributed and/or modified under the terms of the GNU General
 -    Public License (Version 2), as published by the Free Software Foundation.
 -    A copy of the license is included in the JUCE distribution, or can be found
 -    online at www.gnu.org/licenses.
 - 
 -    JUCE 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.
 - 
 -   ------------------------------------------------------------------------------
 - 
 -    To release a closed-source product which uses JUCE, commercial licenses are
 -    available: visit www.rawmaterialsoftware.com/juce for more information.
 - 
 -   ==============================================================================
 - */
 - 
 - #include "../JuceDemoHeader.h"
 - 
 - static String getMidiMessageDescription (const MidiMessage& m)
 - {
 -     if (m.isNoteOn())           return "Note on "  + MidiMessage::getMidiNoteName (m.getNoteNumber(), true, true, 3);
 -     if (m.isNoteOff())          return "Note off " + MidiMessage::getMidiNoteName (m.getNoteNumber(), true, true, 3);
 -     if (m.isProgramChange())    return "Program change " + String (m.getProgramChangeNumber());
 -     if (m.isPitchWheel())       return "Pitch wheel " + String (m.getPitchWheelValue());
 -     if (m.isAftertouch())       return "After touch " + MidiMessage::getMidiNoteName (m.getNoteNumber(), true, true, 3) +  ": " + String (m.getAfterTouchValue());
 -     if (m.isChannelPressure())  return "Channel pressure " + String (m.getChannelPressureValue());
 -     if (m.isAllNotesOff())      return "All notes off";
 -     if (m.isAllSoundOff())      return "All sound off";
 -     if (m.isMetaEvent())        return "Meta event";
 - 
 -     if (m.isController())
 -     {
 -         String name (MidiMessage::getControllerName (m.getControllerNumber()));
 - 
 -         if (name.isEmpty())
 -             name = "[" + String (m.getControllerNumber()) + "]";
 - 
 -         return "Controler " + name + ": " + String (m.getControllerValue());
 -     }
 - 
 -     return String::toHexString (m.getRawData(), m.getRawDataSize());
 - }
 - 
 - //==============================================================================
 - /** Simple list box that just displays a StringArray. */
 - class MidiLogListBoxModel   : public ListBoxModel
 - {
 - public:
 -     MidiLogListBoxModel (const Array<MidiMessage>& list)
 -         : midiMessageList (list)
 -     {
 -     }
 - 
 -     int getNumRows() override    { return midiMessageList.size(); }
 - 
 -     void paintListBoxItem (int row, Graphics& g, int width, int height, bool rowIsSelected) override
 -     {
 -         if (rowIsSelected)
 -             g.fillAll (Colours::blue.withAlpha (0.2f));
 - 
 -         if (isPositiveAndBelow (row, midiMessageList.size()))
 -         {
 -             g.setColour (Colours::black);
 - 
 -             const MidiMessage& message = midiMessageList.getReference (row);
 -             double time = message.getTimeStamp();
 - 
 -             g.drawText (String::formatted ("%02d:%02d:%02d",
 -                                            ((int) (time / 3600.0)) % 24,
 -                                            ((int) (time / 60.0)) % 60,
 -                                            ((int) time) % 60)
 -                             + "  -  " + getMidiMessageDescription (message),
 -                         Rectangle<int> (width, height).reduced (4, 0),
 -                         Justification::centredLeft, true);
 -         }
 -     }
 - 
 - private:
 -     const Array<MidiMessage>& midiMessageList;
 - 
 -     JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (MidiLogListBoxModel)
 - };
 - 
 - //==============================================================================
 - class MidiDemo  : public Component,
 -                   private ComboBox::Listener,
 -                   private MidiInputCallback,
 -                   private MidiKeyboardStateListener,
 -                   private AsyncUpdater
 - {
 - public:
 -     MidiDemo()
 -         : deviceManager (MainAppWindow::getSharedAudioDeviceManager()),
 -           lastInputIndex (0), isAddingFromMidiInput (false),
 -           keyboardComponent (keyboardState, MidiKeyboardComponent::horizontalKeyboard),
 -           midiLogListBoxModel (midiMessageList)
 -     {
 -         setOpaque (true);
 - 
 -         addAndMakeVisible (midiInputListLabel);
 -         midiInputListLabel.setText ("MIDI Input:", dontSendNotification);
 -         midiInputListLabel.attachToComponent (&midiInputList, true);
 - 
 -         addAndMakeVisible (midiInputList);
 -         midiInputList.setTextWhenNoChoicesAvailable ("No MIDI Inputs Enabled");
 -         const StringArray midiInputs (MidiInput::getDevices());
 -         midiInputList.addItemList (midiInputs, 1);
 -         midiInputList.addListener (this);
 - 
 -         // find the first enabled device and use that bu default
 -         for (int i = 0; i < midiInputs.size(); ++i)
 -         {
 -             if (deviceManager.isMidiInputEnabled (midiInputs[i]))
 -             {
 -                 setMidiInput (i);
 -                 break;
 -             }
 -         }
 - 
 -         // if no enabled devices were found just use the first one in the list
 -         if (midiInputList.getSelectedId() == 0)
 -             setMidiInput (0);
 - 
 -         addAndMakeVisible (keyboardComponent);
 -         keyboardState.addListener (this);
 - 
 -         addAndMakeVisible (messageListBox);
 -         messageListBox.setModel (&midiLogListBoxModel);
 -         messageListBox.setColour (ListBox::backgroundColourId, Colour (0x32ffffff));
 -         messageListBox.setColour (ListBox::outlineColourId, Colours::black);
 -     }
 - 
 -     ~MidiDemo()
 -     {
 -         keyboardState.removeListener (this);
 -         deviceManager.removeMidiInputCallback (MidiInput::getDevices()[midiInputList.getSelectedItemIndex()], this);
 -         midiInputList.removeListener (this);
 -     }
 - 
 -     void paint (Graphics& g) override
 -     {
 -         fillTiledBackground (g);
 -     }
 - 
 -     void resized() override
 -     {
 -         Rectangle<int> area (getLocalBounds());
 -         midiInputList.setBounds (area.removeFromTop (36).removeFromRight (getWidth() - 150).reduced (8));
 -         keyboardComponent.setBounds (area.removeFromTop (80).reduced(8));
 -         messageListBox.setBounds (area.reduced (8));
 -     }
 - 
 - private:
 -     AudioDeviceManager& deviceManager;
 -     ComboBox midiInputList;
 -     Label midiInputListLabel;
 -     int lastInputIndex;
 -     bool isAddingFromMidiInput;
 - 
 -     MidiKeyboardState keyboardState;
 -     MidiKeyboardComponent keyboardComponent;
 - 
 -     ListBox messageListBox;
 -     Array<MidiMessage> midiMessageList;
 -     MidiLogListBoxModel midiLogListBoxModel;
 - 
 -     //==============================================================================
 -     /** Starts listening to a MIDI input device, enabling it if necessary. */
 -     void setMidiInput (int index)
 -     {
 -         const StringArray list (MidiInput::getDevices());
 - 
 -         deviceManager.removeMidiInputCallback (list[lastInputIndex], this);
 - 
 -         const String newInput (list[index]);
 - 
 -         if (! deviceManager.isMidiInputEnabled (newInput))
 -             deviceManager.setMidiInputEnabled (newInput, true);
 - 
 -         deviceManager.addMidiInputCallback (newInput, this);
 -         midiInputList.setSelectedId (index + 1, dontSendNotification);
 - 
 -         lastInputIndex = index;
 -     }
 - 
 -     void comboBoxChanged (ComboBox* box) override
 -     {
 -         if (box == &midiInputList)
 -             setMidiInput (midiInputList.getSelectedItemIndex());
 -     }
 - 
 -     // These methods handle callbacks from the midi device + on-screen keyboard..
 -     void handleIncomingMidiMessage (MidiInput*, const MidiMessage& message) override
 -     {
 -         const ScopedValueSetter<bool> scopedInputFlag (isAddingFromMidiInput, true);
 -         keyboardState.processNextMidiEvent (message);
 -         postMessageToList (message);
 -     }
 - 
 -     void handleNoteOn (MidiKeyboardState*, int midiChannel, int midiNoteNumber, float velocity) override
 -     {
 -         if (! isAddingFromMidiInput)
 -         {
 -             MidiMessage m (MidiMessage::noteOn (midiChannel, midiNoteNumber, velocity));
 -             m.setTimeStamp (Time::getMillisecondCounterHiRes() * 0.001);
 -             postMessageToList (m);
 -         }
 -     }
 - 
 -     void handleNoteOff (MidiKeyboardState*, int midiChannel, int midiNoteNumber) override
 -     {
 -         if (! isAddingFromMidiInput)
 -         {
 -             MidiMessage m (MidiMessage::noteOff (midiChannel, midiNoteNumber));
 -             m.setTimeStamp (Time::getMillisecondCounterHiRes() * 0.001);
 -             postMessageToList (m);
 -         }
 -     }
 - 
 -     // This is used to dispach an incoming message to the message thread
 -     struct IncomingMessageCallback   : public CallbackMessage
 -     {
 -         IncomingMessageCallback (MidiDemo* d, const MidiMessage& m)
 -             : demo (d), message (m) {}
 - 
 -         void messageCallback() override
 -         {
 -             if (demo != nullptr)
 -                 demo->addMessageToList (message);
 -         }
 - 
 -         Component::SafePointer<MidiDemo> demo;
 -         MidiMessage message;
 -     };
 - 
 -     void postMessageToList (const MidiMessage& message)
 -     {
 -         (new IncomingMessageCallback (this, message))->post();
 -     }
 - 
 -     void addMessageToList (const MidiMessage& message)
 -     {
 -         midiMessageList.add (message);
 -         triggerAsyncUpdate();
 -     }
 - 
 -     void handleAsyncUpdate() override
 -     {
 -         messageListBox.updateContent();
 -         messageListBox.scrollToEnsureRowIsOnscreen (midiMessageList.size() - 1);
 -         messageListBox.repaint();
 -     }
 - 
 -     JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (MidiDemo);
 - };
 - 
 - 
 - // This static object will register this demo type in a global list of demos..
 - static JuceDemoType<MidiDemo> demo ("32 Audio: MIDI i/o");
 
 
  |