| 
							- /*
 -   ==============================================================================
 - 
 -    This file is part of the JUCE examples.
 -    Copyright (c) 2017 - ROLI Ltd.
 - 
 -    The code included in this file is provided under the terms of the ISC license
 -    http://www.isc.org/downloads/software-support-policy/isc-license. Permission
 -    To use, copy, modify, and/or distribute this software for any purpose with or
 -    without fee is hereby granted provided that the above copyright notice and
 -    this permission notice appear in all copies.
 - 
 -    THE SOFTWARE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES,
 -    WHETHER EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR
 -    PURPOSE, ARE DISCLAIMED.
 - 
 -   ==============================================================================
 - */
 - 
 - /*******************************************************************************
 -  The block below describes the properties of this PIP. A PIP is a short snippet
 -  of code that can be read by the Projucer and used to generate a JUCE project.
 - 
 -  BEGIN_JUCE_PIP_METADATA
 - 
 -  name:             OSCDemo
 -  version:          1.0.0
 -  vendor:           juce
 -  website:          http://juce.com
 -  description:      Application using the OSC protocol.
 - 
 -  dependencies:     juce_core, juce_data_structures, juce_events, juce_graphics,
 -                    juce_gui_basics, juce_osc
 -  exporters:        xcode_mac, vs2017, linux_make
 - 
 -  type:             Component
 -  mainClass:        OSCDemo
 - 
 -  useLocalCopy:     1
 - 
 -  END_JUCE_PIP_METADATA
 - 
 - *******************************************************************************/
 - 
 - #pragma once
 - 
 - 
 - //==============================================================================
 - class OSCLogListBox    : public ListBox,
 -                          private ListBoxModel,
 -                          private AsyncUpdater
 - {
 - public:
 -     OSCLogListBox()
 -     {
 -         setModel (this);
 -     }
 - 
 -     ~OSCLogListBox() {}
 - 
 -     //==============================================================================
 -     int getNumRows() override
 -     {
 -         return oscLogList.size();
 -     }
 - 
 -     //==============================================================================
 -     void paintListBoxItem (int row, Graphics& g, int width, int height, bool rowIsSelected) override
 -     {
 -         ignoreUnused (rowIsSelected);
 - 
 -         if (isPositiveAndBelow (row, oscLogList.size()))
 -         {
 -             g.setColour (Colours::white);
 - 
 -             g.drawText (oscLogList[row],
 -                         Rectangle<int> (width, height).reduced (4, 0),
 -                         Justification::centredLeft, true);
 -         }
 -     }
 - 
 -     //==============================================================================
 -     void addOSCMessage (const OSCMessage& message, int level = 0)
 -     {
 -         oscLogList.add (getIndentationString (level)
 -                         + "- osc message, address = '"
 -                         + message.getAddressPattern().toString()
 -                         + "', "
 -                         + String (message.size())
 -                         + " argument(s)");
 - 
 -         if (! message.isEmpty())
 -         {
 -             for (auto& arg : message)
 -                 addOSCMessageArgument (arg, level + 1);
 -         }
 - 
 -         triggerAsyncUpdate();
 -     }
 - 
 -     //==============================================================================
 -     void addOSCBundle (const OSCBundle& bundle, int level = 0)
 -     {
 -         OSCTimeTag timeTag = bundle.getTimeTag();
 - 
 -         oscLogList.add (getIndentationString (level)
 -                         + "- osc bundle, time tag = "
 -                         + timeTag.toTime().toString (true, true, true, true));
 - 
 -         for (auto& element : bundle)
 -         {
 -             if (element.isMessage())
 -                 addOSCMessage (element.getMessage(), level + 1);
 -             else if (element.isBundle())
 -                 addOSCBundle (element.getBundle(), level + 1);
 -         }
 - 
 -         triggerAsyncUpdate();
 -     }
 - 
 -     //==============================================================================
 -     void addOSCMessageArgument (const OSCArgument& arg, int level)
 -     {
 -         String typeAsString;
 -         String valueAsString;
 - 
 -         if (arg.isFloat32())
 -         {
 -             typeAsString = "float32";
 -             valueAsString = String (arg.getFloat32());
 -         }
 -         else if (arg.isInt32())
 -         {
 -             typeAsString = "int32";
 -             valueAsString = String (arg.getInt32());
 -         }
 -         else if (arg.isString())
 -         {
 -             typeAsString = "string";
 -             valueAsString = arg.getString();
 -         }
 -         else if (arg.isBlob())
 -         {
 -             typeAsString = "blob";
 -             auto& blob = arg.getBlob();
 -             valueAsString = String::fromUTF8 ((const char*) blob.getData(), (int) blob.getSize());
 -         }
 -         else
 -         {
 -             typeAsString = "(unknown)";
 -         }
 - 
 -         oscLogList.add (getIndentationString (level + 1) + "- " + typeAsString.paddedRight(' ', 12) + valueAsString);
 -     }
 - 
 -     //==============================================================================
 -     void addInvalidOSCPacket (const char* /* data */, int dataSize)
 -     {
 -         oscLogList.add ("- (" + String(dataSize) + "bytes with invalid format)");
 -     }
 - 
 -     //==============================================================================
 -     void clear()
 -     {
 -         oscLogList.clear();
 -         triggerAsyncUpdate();
 -     }
 - 
 -     //==============================================================================
 -     void handleAsyncUpdate() override
 -     {
 -         updateContent();
 -         scrollToEnsureRowIsOnscreen (oscLogList.size() - 1);
 -         repaint();
 -     }
 - 
 - private:
 -     static String getIndentationString (int level)
 -     {
 -         return String().paddedRight (' ', 2 * level);
 -     }
 - 
 -     //==============================================================================
 -     StringArray oscLogList;
 - 
 -     JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (OSCLogListBox)
 - };
 - 
 - //==============================================================================
 - class OSCSenderDemo   : public Component
 - {
 - public:
 -     OSCSenderDemo()
 -     {
 -         addAndMakeVisible (senderLabel);
 -         senderLabel.attachToComponent (&rotaryKnob, false);
 - 
 -         rotaryKnob.setRange (0.0, 1.0);
 -         rotaryKnob.setSliderStyle (Slider::RotaryVerticalDrag);
 -         rotaryKnob.setTextBoxStyle (Slider::TextBoxBelow, true, 150, 25);
 -         rotaryKnob.setBounds (50, 50, 180, 180);
 -         addAndMakeVisible (rotaryKnob);
 -         rotaryKnob.onValueChange = [this]
 -         {
 -             // create and send an OSC message with an address and a float value:
 -             if (! sender1.send ("/juce/rotaryknob", (float) rotaryKnob.getValue()))
 -                 showConnectionErrorMessage ("Error: could not send OSC message.");
 -             if (! sender2.send ("/juce/rotaryknob", (float) rotaryKnob.getValue()))
 -                 showConnectionErrorMessage ("Error: could not send OSC message.");
 -         };
 - 
 -         // specify here where to send OSC messages to: host URL and UDP port number
 -         if (! sender1.connect ("127.0.0.1", 9001))
 -             showConnectionErrorMessage ("Error: could not connect to UDP port 9001.");
 -         if (! sender2.connect ("127.0.0.1", 9002))
 -             showConnectionErrorMessage ("Error: could not connect to UDP port 9002.");
 -     }
 - 
 - private:
 -     //==============================================================================
 -     void showConnectionErrorMessage (const String& messageText)
 -     {
 -         AlertWindow::showMessageBoxAsync (AlertWindow::WarningIcon,
 -                                           "Connection error",
 -                                           messageText,
 -                                           "OK");
 -     }
 - 
 -     //==============================================================================
 -     Slider rotaryKnob;
 -     OSCSender sender1, sender2;
 -     Label senderLabel { {}, "Sender" };
 - 
 -     JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (OSCSenderDemo)
 - };
 - 
 - //==============================================================================
 - class OSCReceiverDemo   : public Component,
 -                           private OSCReceiver,
 -                           private OSCReceiver::ListenerWithOSCAddress<OSCReceiver::MessageLoopCallback>
 - {
 - public:
 -     //==============================================================================
 -     OSCReceiverDemo()
 -     {
 -         addAndMakeVisible (receiverLabel);
 -         receiverLabel.attachToComponent (&rotaryKnob, false);
 - 
 -         rotaryKnob.setRange (0.0, 1.0);
 -         rotaryKnob.setSliderStyle (Slider::RotaryVerticalDrag);
 -         rotaryKnob.setTextBoxStyle (Slider::TextBoxBelow, true, 150, 25);
 -         rotaryKnob.setBounds (50, 50, 180, 180);
 -         rotaryKnob.setInterceptsMouseClicks (false, false);
 -         addAndMakeVisible (rotaryKnob);
 - 
 -         // specify here on which UDP port number to receive incoming OSC messages
 -         if (! connect (9001))
 -             showConnectionErrorMessage ("Error: could not connect to UDP port 9001.");
 - 
 -         // tell the component to listen for OSC messages matching this address:
 -         addListener (this, "/juce/rotaryknob");
 -     }
 - 
 - private:
 -     //==============================================================================
 -     void oscMessageReceived (const OSCMessage& message) override
 -     {
 -         if (message.size() == 1 && message[0].isFloat32())
 -             rotaryKnob.setValue (jlimit (0.0f, 10.0f, message[0].getFloat32()));
 -     }
 - 
 -     void showConnectionErrorMessage (const String& messageText)
 -     {
 -         AlertWindow::showMessageBoxAsync (AlertWindow::WarningIcon,
 -                                           "Connection error",
 -                                           messageText,
 -                                           "OK");
 -     }
 - 
 -     //==============================================================================
 -     Slider rotaryKnob;
 -     Label receiverLabel { {}, "Receiver" };
 - 
 -     JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (OSCReceiverDemo)
 - };
 - 
 - //==============================================================================
 - class OSCMonitorDemo   : public Component,
 -                          private OSCReceiver::Listener<OSCReceiver::MessageLoopCallback>
 - {
 - public:
 -     //==============================================================================
 -     OSCMonitorDemo()
 -     {
 -         portNumberLabel.setBounds (10, 18, 130, 25);
 -         addAndMakeVisible (portNumberLabel);
 - 
 -         portNumberField.setEditable (true, true, true);
 -         portNumberField.setBounds (140, 18, 50, 25);
 -         addAndMakeVisible (portNumberField);
 - 
 -         connectButton.setBounds (210, 18, 100, 25);
 -         addAndMakeVisible (connectButton);
 -         connectButton.onClick = [this] { connectButtonClicked(); };
 - 
 -         clearButton.setBounds (320, 18, 60, 25);
 -         addAndMakeVisible (clearButton);
 -         clearButton.onClick = [this] { clearButtonClicked(); };
 - 
 -         connectionStatusLabel.setBounds (450, 18, 240, 25);
 -         updateConnectionStatusLabel();
 -         addAndMakeVisible (connectionStatusLabel);
 - 
 -         oscLogListBox.setBounds (0, 60, 700, 340);
 -         addAndMakeVisible (oscLogListBox);
 - 
 -         oscReceiver.addListener (this);
 -         oscReceiver.registerFormatErrorHandler ([this] (const char* data, int dataSize)
 -                                                 {
 -                                                     oscLogListBox.addInvalidOSCPacket (data, dataSize);
 -                                                 });
 -     }
 - 
 - private:
 -     //==============================================================================
 -     Label portNumberLabel    { {}, "UDP Port Number: " };
 -     Label portNumberField    { {}, "9002" };
 -     TextButton connectButton { "Connect" };
 -     TextButton clearButton   { "Clear" };
 -     Label connectionStatusLabel;
 - 
 -     OSCLogListBox oscLogListBox;
 -     OSCReceiver oscReceiver;
 - 
 -     int currentPortNumber = -1;
 - 
 -     //==============================================================================
 -     void connectButtonClicked()
 -     {
 -         if (! isConnected())
 -             connect();
 -         else
 -             disconnect();
 - 
 -         updateConnectionStatusLabel();
 -     }
 - 
 -     //==============================================================================
 -     void clearButtonClicked()
 -     {
 -         oscLogListBox.clear();
 -     }
 - 
 -     //==============================================================================
 -     void oscMessageReceived (const OSCMessage& message) override
 -     {
 -         oscLogListBox.addOSCMessage (message);
 -     }
 - 
 -     void oscBundleReceived (const OSCBundle& bundle) override
 -     {
 -         oscLogListBox.addOSCBundle (bundle);
 -     }
 - 
 -     //==============================================================================
 -     void connect()
 -     {
 -         auto portToConnect = portNumberField.getText().getIntValue();
 - 
 -         if (! isValidOscPort (portToConnect))
 -         {
 -             handleInvalidPortNumberEntered();
 -             return;
 -         }
 - 
 -         if (oscReceiver.connect (portToConnect))
 -         {
 -             currentPortNumber = portToConnect;
 -             connectButton.setButtonText ("Disconnect");
 -         }
 -         else
 -         {
 -             handleConnectError (portToConnect);
 -         }
 -     }
 - 
 -     //==============================================================================
 -     void disconnect()
 -     {
 -         if (oscReceiver.disconnect())
 -         {
 -             currentPortNumber = -1;
 -             connectButton.setButtonText ("Connect");
 -         }
 -         else
 -         {
 -             handleDisconnectError();
 -         }
 -     }
 - 
 -     //==============================================================================
 -     void handleConnectError (int failedPort)
 -     {
 -         AlertWindow::showMessageBoxAsync (AlertWindow::WarningIcon,
 -                                           "OSC Connection error",
 -                                           "Error: could not connect to port " + String (failedPort),
 -                                           "OK");
 -     }
 - 
 -     //==============================================================================
 -     void handleDisconnectError()
 -     {
 -         AlertWindow::showMessageBoxAsync (AlertWindow::WarningIcon,
 -                                           "Unknown error",
 -                                           "An unknown error occured while trying to disconnect from UDP port.",
 -                                           "OK");
 -     }
 - 
 -     //==============================================================================
 -     void handleInvalidPortNumberEntered()
 -     {
 -         AlertWindow::showMessageBoxAsync (AlertWindow::WarningIcon,
 -                                           "Invalid port number",
 -                                           "Error: you have entered an invalid UDP port number.",
 -                                           "OK");
 -     }
 - 
 -     //==============================================================================
 -     bool isConnected() const
 -     {
 -         return currentPortNumber != -1;
 -     }
 - 
 -     //==============================================================================
 -     bool isValidOscPort (int port) const
 -     {
 -         return port > 0 && port < 65536;
 -     }
 - 
 -     //==============================================================================
 -     void updateConnectionStatusLabel()
 -     {
 -         String text = "Status: ";
 - 
 -         if (isConnected())
 -             text += "Connected to UDP port " + String (currentPortNumber);
 -         else
 -             text += "Disconnected";
 - 
 -         auto textColour = isConnected() ? Colours::green : Colours::red;
 - 
 -         connectionStatusLabel.setText (text, dontSendNotification);
 -         connectionStatusLabel.setFont (Font (15.00f, Font::bold));
 -         connectionStatusLabel.setColour (Label::textColourId, textColour);
 -         connectionStatusLabel.setJustificationType (Justification::centredRight);
 -     }
 - 
 -     JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (OSCMonitorDemo)
 - };
 - 
 - //==============================================================================
 - class OSCDemo   : public Component
 - {
 - public:
 -     OSCDemo()
 -     {
 -         addAndMakeVisible (monitor);
 -         addAndMakeVisible (receiver);
 -         addAndMakeVisible (sender);
 - 
 -         setSize (700, 400);
 -     }
 - 
 -     void resized() override
 -     {
 -         auto bounds = getLocalBounds();
 - 
 -         auto lowerBounds = bounds.removeFromBottom (getHeight() / 2);
 -         auto halfBounds  = bounds.removeFromRight  (getWidth()  / 2);
 - 
 -         sender  .setBounds (bounds);
 -         receiver.setBounds (halfBounds);
 -         monitor .setBounds (lowerBounds.removeFromTop (getHeight() / 2));
 -     }
 - 
 - private:
 -     OSCMonitorDemo  monitor;
 -     OSCReceiverDemo receiver;
 -     OSCSenderDemo   sender;
 - 
 -     JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (OSCDemo)
 - };
 
 
  |