fix macOS build (following Projucer changes made in Windows, which removed /Applications/JUCE/modules from its headers). move JUCE headers under source control, so that Windows and macOS can both build against same version of JUCE. remove AUv3 target (I think it's an iOS thing, so it will never work with this macOS fluidsynth dylib).
This commit is contained in:
110
modules/juce_blocks_basics/blocks/juce_Block.cpp
Normal file
110
modules/juce_blocks_basics/blocks/juce_Block.cpp
Normal file
@ -0,0 +1,110 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library.
|
||||
Copyright (c) 2017 - ROLI Ltd.
|
||||
|
||||
JUCE is an open source library subject to commercial or open-source
|
||||
licensing.
|
||||
|
||||
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.
|
||||
|
||||
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
|
||||
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
|
||||
DISCLAIMED.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
namespace juce
|
||||
{
|
||||
|
||||
static Block::UID getBlockUIDFromSerialNumber (const uint8* serial) noexcept
|
||||
{
|
||||
Block::UID n = {};
|
||||
|
||||
for (int i = 0; i < (int) sizeof (BlocksProtocol::BlockSerialNumber); ++i)
|
||||
n += n * 127 + serial[i];
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
static Block::UID getBlockUIDFromSerialNumber (const BlocksProtocol::BlockSerialNumber& serial) noexcept
|
||||
{
|
||||
return getBlockUIDFromSerialNumber (serial.serial);
|
||||
}
|
||||
|
||||
static Block::UID getBlockUIDFromSerialNumber (const juce::String& serial) noexcept
|
||||
{
|
||||
if (serial.length() < (int) sizeof (BlocksProtocol::BlockSerialNumber))
|
||||
{
|
||||
jassertfalse;
|
||||
return getBlockUIDFromSerialNumber (serial.paddedRight ('0', sizeof (BlocksProtocol::BlockSerialNumber)));
|
||||
}
|
||||
|
||||
return getBlockUIDFromSerialNumber ((const uint8*) serial.toRawUTF8());
|
||||
}
|
||||
|
||||
Block::Block (const juce::String& serial)
|
||||
: serialNumber (serial), uid (getBlockUIDFromSerialNumber (serial))
|
||||
{
|
||||
}
|
||||
|
||||
Block::Block (const juce::String& serial, const juce::String& version, const juce::String& blockName)
|
||||
: serialNumber (serial), versionNumber (version), name (blockName), uid (getBlockUIDFromSerialNumber (serial))
|
||||
{
|
||||
}
|
||||
|
||||
Block::~Block() {}
|
||||
|
||||
void Block::addDataInputPortListener (DataInputPortListener* listener) { dataInputPortListeners.add (listener); }
|
||||
void Block::removeDataInputPortListener (DataInputPortListener* listener) { dataInputPortListeners.remove (listener); }
|
||||
|
||||
void Block::addProgramEventListener (ProgramEventListener* listener) { programEventListeners.add (listener); }
|
||||
void Block::removeProgramEventListener (ProgramEventListener* listener) { programEventListeners.remove (listener); }
|
||||
|
||||
|
||||
bool Block::ConnectionPort::operator== (const ConnectionPort& other) const noexcept { return edge == other.edge && index == other.index; }
|
||||
bool Block::ConnectionPort::operator!= (const ConnectionPort& other) const noexcept { return ! operator== (other); }
|
||||
|
||||
Block::Program::Program (Block& b) : block (b) {}
|
||||
Block::Program::~Program() {}
|
||||
|
||||
//==============================================================================
|
||||
TouchSurface::TouchSurface (Block& b) : block (b) {}
|
||||
TouchSurface::~TouchSurface() {}
|
||||
|
||||
TouchSurface::Listener::~Listener() {}
|
||||
|
||||
void TouchSurface::addListener (Listener* l) { listeners.add (l); }
|
||||
void TouchSurface::removeListener (Listener* l) { listeners.remove (l); }
|
||||
|
||||
//==============================================================================
|
||||
ControlButton::ControlButton (Block& b) : block (b) {}
|
||||
ControlButton::~ControlButton() {}
|
||||
|
||||
ControlButton::Listener::~Listener() {}
|
||||
|
||||
void ControlButton::addListener (Listener* l) { listeners.add (l); }
|
||||
void ControlButton::removeListener (Listener* l) { listeners.remove (l); }
|
||||
|
||||
|
||||
//==============================================================================
|
||||
LEDGrid::LEDGrid (Block& b) : block (b) {}
|
||||
LEDGrid::~LEDGrid() {}
|
||||
|
||||
LEDGrid::Renderer::~Renderer() {}
|
||||
|
||||
//==============================================================================
|
||||
LEDRow::LEDRow (Block& b) : block (b) {}
|
||||
LEDRow::~LEDRow() {}
|
||||
|
||||
//==============================================================================
|
||||
StatusLight::StatusLight (Block& b) : block (b) {}
|
||||
StatusLight::~StatusLight() {}
|
||||
|
||||
} // namespace juce
|
444
modules/juce_blocks_basics/blocks/juce_Block.h
Normal file
444
modules/juce_blocks_basics/blocks/juce_Block.h
Normal file
@ -0,0 +1,444 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library.
|
||||
Copyright (c) 2017 - ROLI Ltd.
|
||||
|
||||
JUCE is an open source library subject to commercial or open-source
|
||||
licensing.
|
||||
|
||||
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.
|
||||
|
||||
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
|
||||
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
|
||||
DISCLAIMED.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
namespace juce
|
||||
{
|
||||
|
||||
/**
|
||||
Represents an individual BLOCKS device.
|
||||
|
||||
@tags{Blocks}
|
||||
*/
|
||||
class Block : public juce::ReferenceCountedObject
|
||||
{
|
||||
public:
|
||||
//==============================================================================
|
||||
/** Destructor. */
|
||||
virtual ~Block();
|
||||
|
||||
/** The different block types.
|
||||
@see Block::getType()
|
||||
*/
|
||||
enum Type
|
||||
{
|
||||
unknown = 0, /**< Unknown block type. */
|
||||
lightPadBlock, /**< Lightpad block type. */
|
||||
liveBlock, /**< Live control block type. */
|
||||
loopBlock, /**< Loop control block type. */
|
||||
developerControlBlock, /**< Developer control block type. */
|
||||
touchBlock, /**< Touch control block type. */
|
||||
seaboardBlock /**< Seaboard block type. */
|
||||
};
|
||||
|
||||
/** The Block class is reference-counted, so always use a Block::Ptr when
|
||||
you are keeping references to them.
|
||||
*/
|
||||
using Ptr = juce::ReferenceCountedObjectPtr<Block>;
|
||||
|
||||
/** The Block class is reference-counted, so Block::Array is useful when
|
||||
you are storing lists of them.
|
||||
*/
|
||||
using Array = juce::ReferenceCountedArray<Block>;
|
||||
|
||||
/** The Block's serial number. */
|
||||
const juce::String serialNumber;
|
||||
|
||||
/** The Block's version number */
|
||||
juce::String versionNumber;
|
||||
|
||||
/** The Block's name */
|
||||
juce::String name;
|
||||
|
||||
/** This type is used for the unique block identifier. */
|
||||
using UID = uint64;
|
||||
|
||||
/** This Block's UID.
|
||||
This will be globally unique, and remains constant for a particular device.
|
||||
*/
|
||||
const UID uid;
|
||||
|
||||
//==============================================================================
|
||||
/** Two blocks are considered equal if they have the same UID. */
|
||||
bool operator== (const Block& other) const noexcept { return uid == other.uid; }
|
||||
/** Two blocks are considered equal if they have the same UID. */
|
||||
bool operator!= (const Block& other) const noexcept { return uid != other.uid; }
|
||||
|
||||
//==============================================================================
|
||||
/** Returns the type of this device.
|
||||
@see Block::Type
|
||||
*/
|
||||
virtual Type getType() const = 0;
|
||||
|
||||
/** Returns a human-readable description of this device type. */
|
||||
virtual juce::String getDeviceDescription() const = 0;
|
||||
|
||||
/** Returns the battery level in the range 0.0 to 1.0. */
|
||||
virtual float getBatteryLevel() const = 0;
|
||||
|
||||
/** Returns true if the battery is charging. */
|
||||
virtual bool isBatteryCharging() const = 0;
|
||||
|
||||
//==============================================================================
|
||||
/** Returns true if this block is connected and active. */
|
||||
virtual bool isConnected() const = 0;
|
||||
|
||||
/** Returns true if this block is directly connected to the application,
|
||||
as opposed to only being connected to a different block via a connection port.
|
||||
|
||||
@see ConnectionPort
|
||||
*/
|
||||
virtual bool isMasterBlock() const = 0;
|
||||
|
||||
//==============================================================================
|
||||
/** Returns the width of the device in logical device units. */
|
||||
virtual int getWidth() const = 0;
|
||||
|
||||
/** Returns the height of the device in logical device units. */
|
||||
virtual int getHeight() const = 0;
|
||||
|
||||
/** Returns true if the device is a physical hardware block (i.e. not a virtual block). */
|
||||
virtual bool isHardwareBlock() const = 0;
|
||||
|
||||
/** Returns the length of one logical device unit as physical millimeters. */
|
||||
virtual float getMillimetersPerUnit() const = 0;
|
||||
|
||||
//==============================================================================
|
||||
/** If this block has a grid of LEDs, this will return an object to control it.
|
||||
Note that the pointer that is returned belongs to this object, and the caller must
|
||||
neither delete it or use it after the lifetime of this Block object has finished.
|
||||
If there are no LEDs, then this method will return nullptr.
|
||||
*/
|
||||
virtual LEDGrid* getLEDGrid() const = 0;
|
||||
|
||||
/** If this block has a row of LEDs, this will return an object to control it.
|
||||
Note that the pointer that is returned belongs to this object, and the caller must
|
||||
neither delete it or use it after the lifetime of this Block object has finished.
|
||||
If there are no LEDs, then this method will return nullptr.
|
||||
*/
|
||||
virtual LEDRow* getLEDRow() const = 0;
|
||||
|
||||
/** If this block has any status LEDs, this will return an array of objects to control them.
|
||||
Note that the objects in the array belong to this Block object, and the caller must
|
||||
neither delete them or use them after the lifetime of this Block object has finished.
|
||||
*/
|
||||
virtual juce::Array<StatusLight*> getStatusLights() const = 0;
|
||||
|
||||
/** If this block has a pressure-sensitive surface, this will return an object to
|
||||
access its data.
|
||||
Note that the pointer returned does is owned by this object, and the caller must
|
||||
neither delete it or use it after the lifetime of this Block object has finished.
|
||||
If the device is not touch-sensitive, then this method will return nullptr.
|
||||
*/
|
||||
virtual TouchSurface* getTouchSurface() const = 0;
|
||||
|
||||
/** If this block has any control buttons, this will return an array of objects to control them.
|
||||
Note that the objects in the array belong to this Block object, and the caller must
|
||||
neither delete them or use them after the lifetime of this Block object has finished.
|
||||
*/
|
||||
virtual juce::Array<ControlButton*> getButtons() const = 0;
|
||||
|
||||
//==============================================================================
|
||||
/** This returns true if the block supports generating graphics by drawing into a JUCE
|
||||
Graphics context. This should only be true for virtual on-screen blocks; hardware
|
||||
blocks will instead use the LED Grid for visuals.
|
||||
*/
|
||||
virtual bool supportsGraphics() const = 0;
|
||||
|
||||
//==============================================================================
|
||||
/** These are the edge-connectors that a device may have. */
|
||||
struct ConnectionPort
|
||||
{
|
||||
enum class DeviceEdge
|
||||
{
|
||||
north,
|
||||
south,
|
||||
east,
|
||||
west
|
||||
};
|
||||
|
||||
/** The side of the device on which this port is located. */
|
||||
DeviceEdge edge;
|
||||
|
||||
/** The index of this port along the device edge.
|
||||
For north and south edges, index 0 is the left-most port.
|
||||
For east and west edges, index 0 is the top-most port.
|
||||
*/
|
||||
int index;
|
||||
|
||||
bool operator== (const ConnectionPort&) const noexcept;
|
||||
bool operator!= (const ConnectionPort&) const noexcept;
|
||||
};
|
||||
|
||||
/** Returns a list of the connectors that this device has. */
|
||||
virtual juce::Array<ConnectionPort> getPorts() const = 0;
|
||||
|
||||
//==============================================================================
|
||||
/** A program that can be loaded onto a block. */
|
||||
struct Program
|
||||
{
|
||||
/** Creates a Program for the corresponding LEDGrid. */
|
||||
Program (Block&);
|
||||
|
||||
/** Destructor. */
|
||||
virtual ~Program();
|
||||
|
||||
/** Returns the LittleFoot program to execute on the BLOCKS device. */
|
||||
virtual juce::String getLittleFootProgram() = 0;
|
||||
|
||||
Block& block;
|
||||
};
|
||||
|
||||
/** Sets the Program to run on this block.
|
||||
|
||||
The supplied Program's lifetime will be managed by this class, so do not
|
||||
use the Program in other places in your code.
|
||||
*/
|
||||
virtual juce::Result setProgram (Program*) = 0;
|
||||
|
||||
/** Returns a pointer to the currently loaded program. */
|
||||
virtual Program* getProgram() const = 0;
|
||||
|
||||
//==============================================================================
|
||||
/** A message that can be sent to the currently loaded program. */
|
||||
struct ProgramEventMessage
|
||||
{
|
||||
int32 values[3];
|
||||
};
|
||||
|
||||
/** Sends a message to the currently loaded program.
|
||||
|
||||
To receive the message the program must provide a littlefoot function called
|
||||
handleMessage with the following form:
|
||||
@code
|
||||
void handleMessage (int param1, int param2, int param3)
|
||||
{
|
||||
// Do something with the two integer parameters that the app has sent...
|
||||
}
|
||||
@endcode
|
||||
*/
|
||||
virtual void sendProgramEvent (const ProgramEventMessage&) = 0;
|
||||
|
||||
/** Interface for objects listening to custom program events. */
|
||||
struct ProgramEventListener
|
||||
{
|
||||
virtual ~ProgramEventListener() {}
|
||||
|
||||
/** Called whenever a message from a block is received. */
|
||||
virtual void handleProgramEvent (Block& source, const ProgramEventMessage&) = 0;
|
||||
};
|
||||
|
||||
/** Adds a new listener for custom program events from the block. */
|
||||
virtual void addProgramEventListener (ProgramEventListener*);
|
||||
|
||||
/** Removes a listener for custom program events from the block. */
|
||||
virtual void removeProgramEventListener (ProgramEventListener*);
|
||||
|
||||
//==============================================================================
|
||||
/** Returns the size of the data block that setDataByte and other functions can write to. */
|
||||
virtual uint32 getMemorySize() = 0;
|
||||
|
||||
/** Sets a single byte on the littlefoot heap. */
|
||||
virtual void setDataByte (size_t offset, uint8 value) = 0;
|
||||
|
||||
/** Sets multiple bytes on the littlefoot heap. */
|
||||
virtual void setDataBytes (size_t offset, const void* data, size_t num) = 0;
|
||||
|
||||
/** Sets multiple bits on the littlefoot heap. */
|
||||
virtual void setDataBits (uint32 startBit, uint32 numBits, uint32 value) = 0;
|
||||
|
||||
/** Gets a byte from the littlefoot heap. */
|
||||
virtual uint8 getDataByte (size_t offset) = 0;
|
||||
|
||||
/** Sets the current program as the block's default state. */
|
||||
virtual void saveProgramAsDefault() = 0;
|
||||
|
||||
//==============================================================================
|
||||
/** Metadata for a given config item */
|
||||
struct ConfigMetaData
|
||||
{
|
||||
static constexpr int32 numOptionNames = 8;
|
||||
|
||||
ConfigMetaData() {}
|
||||
|
||||
// Constructor to work around VS2015 bugs...
|
||||
ConfigMetaData (uint32 itemIndex,
|
||||
int32 itemValue,
|
||||
juce::Range<int32> rangeToUse,
|
||||
bool active,
|
||||
const char* itemName,
|
||||
uint32 itemType,
|
||||
const char* options[ConfigMetaData::numOptionNames],
|
||||
const char* groupName)
|
||||
: item (itemIndex),
|
||||
value (itemValue),
|
||||
range (rangeToUse),
|
||||
isActive (active),
|
||||
name (itemName),
|
||||
type (itemType),
|
||||
group (groupName)
|
||||
{
|
||||
for (int i = 0; i < numOptionNames; ++i)
|
||||
optionNames[i] = options[i];
|
||||
}
|
||||
|
||||
ConfigMetaData (const ConfigMetaData& other)
|
||||
{
|
||||
*this = other;
|
||||
}
|
||||
|
||||
const ConfigMetaData& operator= (const ConfigMetaData& other)
|
||||
{
|
||||
if (this != &other)
|
||||
{
|
||||
item = other.item;
|
||||
value = other.value;
|
||||
range = other.range;
|
||||
isActive = other.isActive;
|
||||
name = other.name;
|
||||
type = other.type;
|
||||
group = other.group;
|
||||
|
||||
for (int i = 0; i < numOptionNames; ++i)
|
||||
optionNames[i] = other.optionNames[i];
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool operator== (const ConfigMetaData& other) const
|
||||
{
|
||||
for (int32 optionIndex = 0; optionIndex < numOptionNames; ++optionIndex)
|
||||
if (optionNames[optionIndex] != other.optionNames[optionIndex])
|
||||
return false;
|
||||
|
||||
return item == other.item
|
||||
&& value == other.value
|
||||
&& range == other.range
|
||||
&& isActive == other.isActive
|
||||
&& name == other.name
|
||||
&& group == other.group;
|
||||
}
|
||||
|
||||
bool operator != (const ConfigMetaData& other) const
|
||||
{
|
||||
return ! (*this == other);
|
||||
}
|
||||
|
||||
uint32 item = 0;
|
||||
int32 value = 0;
|
||||
juce::Range<int32> range;
|
||||
bool isActive = false;
|
||||
juce::String name;
|
||||
uint32 type = 0;
|
||||
juce::String optionNames[numOptionNames] = {};
|
||||
juce::String group;
|
||||
};
|
||||
|
||||
/** Returns the maximum number of config items available */
|
||||
virtual uint32 getMaxConfigIndex() = 0;
|
||||
|
||||
/** Determine if this is a valid config item index */
|
||||
virtual bool isValidUserConfigIndex (uint32 item) = 0;
|
||||
|
||||
/** Get local config item value */
|
||||
virtual int32 getLocalConfigValue (uint32 item) = 0;
|
||||
|
||||
/** Set local config item value */
|
||||
virtual void setLocalConfigValue (uint32 item, int32 value) = 0;
|
||||
|
||||
/** Set local config item range */
|
||||
virtual void setLocalConfigRange (uint32 item, int32 min, int32 max) = 0;
|
||||
|
||||
/** Set if config item is active or not */
|
||||
virtual void setLocalConfigItemActive (uint32 item, bool isActive) = 0;
|
||||
|
||||
/** Determine if config item is active or not */
|
||||
virtual bool isLocalConfigItemActive (uint32 item) = 0;
|
||||
|
||||
/** Get config item metadata */
|
||||
virtual ConfigMetaData getLocalConfigMetaData (uint32 item) = 0;
|
||||
|
||||
/** Request sync of factory config with block */
|
||||
virtual void requestFactoryConfigSync() = 0;
|
||||
|
||||
/** Reset all items active status */
|
||||
virtual void resetConfigListActiveStatus() = 0;
|
||||
|
||||
/** Perform factory reset on Block */
|
||||
virtual void factoryReset() = 0;
|
||||
|
||||
/** Reset this Block */
|
||||
virtual void blockReset() = 0;
|
||||
|
||||
/** Set Block name */
|
||||
virtual bool setName (const juce::String& name) = 0;
|
||||
|
||||
//==============================================================================
|
||||
/** Allows the user to provide a function that will receive log messages from the block. */
|
||||
virtual void setLogger (std::function<void(const String&)> loggingCallback) = 0;
|
||||
|
||||
/** Sends a firmware update packet to a block, and waits for a reply. Returns an error code. */
|
||||
virtual bool sendFirmwareUpdatePacket (const uint8* data, uint8 size,
|
||||
std::function<void (uint8, uint32)> packetAckCallback) = 0;
|
||||
|
||||
/** Provides a callback that will be called when a config changes. */
|
||||
virtual void setConfigChangedCallback (std::function<void(Block&, const ConfigMetaData&, uint32)>) = 0;
|
||||
|
||||
//==============================================================================
|
||||
/** Interface for objects listening to input data port. */
|
||||
struct DataInputPortListener
|
||||
{
|
||||
virtual ~DataInputPortListener() {}
|
||||
|
||||
/** Called whenever a message from a block is received. */
|
||||
virtual void handleIncomingDataPortMessage (Block& source, const void* messageData, size_t messageSize) = 0;
|
||||
};
|
||||
|
||||
/** Adds a new listener for the data input port. */
|
||||
virtual void addDataInputPortListener (DataInputPortListener*);
|
||||
|
||||
/** Removes a listener for the data input port. */
|
||||
virtual void removeDataInputPortListener (DataInputPortListener*);
|
||||
|
||||
/** Sends a message to the block. */
|
||||
virtual void sendMessage (const void* messageData, size_t messageSize) = 0;
|
||||
|
||||
//==============================================================================
|
||||
/** This type is used for timestamping events. It represents a number of milliseconds since the block
|
||||
device was booted.
|
||||
*/
|
||||
using Timestamp = uint32;
|
||||
|
||||
protected:
|
||||
//==============================================================================
|
||||
Block (const juce::String& serialNumberToUse);
|
||||
Block (const juce::String& serial, const juce::String& version, const juce::String& name);
|
||||
|
||||
juce::ListenerList<DataInputPortListener> dataInputPortListeners;
|
||||
juce::ListenerList<ProgramEventListener> programEventListeners;
|
||||
|
||||
private:
|
||||
//==============================================================================
|
||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (Block)
|
||||
};
|
||||
|
||||
} // namespace juce
|
358
modules/juce_blocks_basics/blocks/juce_BlockConfigManager.h
Normal file
358
modules/juce_blocks_basics/blocks/juce_BlockConfigManager.h
Normal file
@ -0,0 +1,358 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library.
|
||||
Copyright (c) 2017 - ROLI Ltd.
|
||||
|
||||
Permission is granted to use this software 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" AND ISC DISCLAIMS ALL WARRANTIES WITH REGARD
|
||||
TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT,
|
||||
OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
|
||||
USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
|
||||
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
|
||||
OF THIS SOFTWARE.
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
|
||||
To release a closed-source product which uses other parts of JUCE not
|
||||
licensed under the ISC terms, commercial licenses are available: visit
|
||||
www.juce.com for more information.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
namespace juce
|
||||
{
|
||||
|
||||
// This file provides interfaces for managing the internal configuration of Blocks
|
||||
// and synchronises with the connected Block
|
||||
|
||||
using namespace BlocksProtocol;
|
||||
|
||||
/** Manages the configuration of blocks
|
||||
|
||||
@tags{Blocks}
|
||||
*/
|
||||
struct BlockConfigManager
|
||||
{
|
||||
void setDeviceIndex (TopologyIndex newDeviceIndex) { deviceIndex = newDeviceIndex; }
|
||||
void setDeviceComms (PhysicalTopologySource::DeviceConnection* newConn) { deviceConnection = newConn; }
|
||||
|
||||
enum ConfigType
|
||||
{
|
||||
integer,
|
||||
floating,
|
||||
boolean,
|
||||
colour,
|
||||
options
|
||||
};
|
||||
|
||||
static constexpr uint32 numConfigItems = 61;
|
||||
|
||||
/** Structure describing a configuration */
|
||||
struct ConfigDescription
|
||||
{
|
||||
ConfigItemId item;
|
||||
int32 value;
|
||||
int32 min;
|
||||
int32 max;
|
||||
bool isActive;
|
||||
const char* name;
|
||||
ConfigType type;
|
||||
const char* optionNames[configMaxOptions];
|
||||
const char* group;
|
||||
|
||||
static_assert (configMaxOptions == Block::ConfigMetaData::numOptionNames, "Config options size and config metadata size should be the same");
|
||||
|
||||
Block::ConfigMetaData toConfigMetaData() const
|
||||
{
|
||||
return Block::ConfigMetaData ((uint32) item, value, { min, max }, isActive, name, (uint32) type, (const char**) optionNames, group);
|
||||
}
|
||||
};
|
||||
|
||||
ConfigDescription configList[numConfigItems] =
|
||||
{
|
||||
{ midiStartChannel, 2, 1, 16, false, "MIDI Start Channel", ConfigType::integer, {}, "MIDI Settings" },
|
||||
{ midiEndChannel, 16, 1, 16, false, "MIDI End Channel", ConfigType::integer, {}, "MIDI Settings" },
|
||||
{ midiUseMPE, 1, 0, 1, false, "Use MPE", ConfigType::boolean, {}, "MIDI Settings" },
|
||||
{ pitchBendRange, 48, 1, 96, false, "Pitch Bend Range", ConfigType::integer, {}, "MIDI Settings" },
|
||||
{ octave, 0, -4, 6, false, "Octave", ConfigType::integer, {}, "Pitch" },
|
||||
{ transpose, 0, -11, 11, false, "Transpose", ConfigType::integer, {}, "Pitch" },
|
||||
{ slideCC, 74, 0, 127, false, "Slide CC", ConfigType::integer, {}, "Play mode" },
|
||||
{ slideMode, 0, 0, 2, false, "Slide Mode", ConfigType::options, { "Absolute",
|
||||
"Relative Unipolar",
|
||||
"Relative Bipolar" }, "Play mode" },
|
||||
{ velocitySensitivity, 100, 0, 127, false, "Strike Sensitivity", ConfigType::integer, {}, "5D Touch" },
|
||||
{ glideSensitivity, 100, 0, 127, false, "Glide Sensitivity", ConfigType::integer, {}, "5D Touch" },
|
||||
{ slideSensitivity, 100, 0, 127, false, "Slide Sensitivity", ConfigType::integer, {}, "5D Touch" },
|
||||
{ pressureSensitivity, 100, 0, 127, false, "Pressure Sensitivity", ConfigType::integer, {}, "5D Touch" },
|
||||
{ liftSensitivity, 100, 0, 127, false, "Lift Sensitivity", ConfigType::integer, {}, "5D Touch" },
|
||||
{ fixedVelocity, 0, 0, 1, false, "Fixed Velocity", ConfigType::boolean, {}, "5D Touch" },
|
||||
{ fixedVelocityValue, 127, 1, 127, false, "Fixed Velocity Value", ConfigType::integer, {}, "5D Touch" },
|
||||
{ pianoMode, 0, 0, 1, false, "Piano Mode", ConfigType::boolean, {}, "Play mode" },
|
||||
{ glideLock, 0, 0, 127, false, "Glide Rate", ConfigType::integer, {}, "Play mode" },
|
||||
{ glideLockEnable, 0, 0, 1, false, "Glide Lock Enable", ConfigType::boolean, {}, "Play mode" },
|
||||
{ mode, 4, 1, 5, false, "Mode", ConfigType::integer, {}, "Play mode" },
|
||||
{ volume, 100, 0, 127, false, "Volume", ConfigType::integer, {}, "Play mode" },
|
||||
{ scale, 0, 0, 18, false, "Scale", ConfigType::integer, {}, "Play mode" }, // NOTE: Should be options
|
||||
{ hideMode, 0, 0, 1, false, "Hide Mode", ConfigType::boolean, {}, "Play mode" },
|
||||
{ chord, 0, 0, 127, false, "Chord", ConfigType::integer, {}, "Play mode" }, // NOTE: Should be options
|
||||
{ arpPattern, 0, 0, 127, false, "Arp Pattern", ConfigType::integer, {}, "Play mode" },
|
||||
{ tempo, 120, 1, 300, false, "Tempo", ConfigType::integer, {}, "Rhythm" },
|
||||
{ xTrackingMode, 1, 0, 4, false, "Glide Tracking Mode", ConfigType::options, { "Multi-Channel",
|
||||
"Last Played",
|
||||
"Highest",
|
||||
"Lowest",
|
||||
"Disabled" }, "Play mode" },
|
||||
{ yTrackingMode, 1, 0, 4, false, "Slide Tracking Mode", ConfigType::options, { "Multi-Channel",
|
||||
"Last Played",
|
||||
"Highest",
|
||||
"Lowest",
|
||||
"Disabled" }, "Play mode" },
|
||||
{ zTrackingMode, 1, 0, 4, false, "Pressure Tracking Mode", ConfigType::options, { "Multi-Channel",
|
||||
"Last Played",
|
||||
"Highest",
|
||||
"Lowest",
|
||||
"Disabled",
|
||||
"Hardest" }, "Play mode" },
|
||||
|
||||
{ gammaCorrection, 0, 0, 1, false, "Gamma Correction", ConfigType::boolean, {}, {} },
|
||||
|
||||
// These can be defined for unique usage for a given Littlefoot script
|
||||
{ user0, 0, 0, 127, false, {}, ConfigType::integer, {}, {} },
|
||||
{ user1, 0, 0, 127, false, {}, ConfigType::integer, {}, {} },
|
||||
{ user2, 0, 0, 127, false, {}, ConfigType::integer, {}, {} },
|
||||
{ user3, 0, 0, 127, false, {}, ConfigType::integer, {}, {} },
|
||||
{ user4, 0, 0, 127, false, {}, ConfigType::integer, {}, {} },
|
||||
{ user5, 0, 0, 127, false, {}, ConfigType::integer, {}, {} },
|
||||
{ user6, 0, 0, 127, false, {}, ConfigType::integer, {}, {} },
|
||||
{ user7, 0, 0, 127, false, {}, ConfigType::integer, {}, {} },
|
||||
{ user8, 0, 0, 127, false, {}, ConfigType::integer, {}, {} },
|
||||
{ user9, 0, 0, 127, false, {}, ConfigType::integer, {}, {} },
|
||||
{ user10, 0, 0, 127, false, {}, ConfigType::integer, {}, {} },
|
||||
{ user11, 0, 0, 127, false, {}, ConfigType::integer, {}, {} },
|
||||
{ user12, 0, 0, 127, false, {}, ConfigType::integer, {}, {} },
|
||||
{ user13, 0, 0, 127, false, {}, ConfigType::integer, {}, {} },
|
||||
{ user14, 0, 0, 127, false, {}, ConfigType::integer, {}, {} },
|
||||
{ user15, 0, 0, 127, false, {}, ConfigType::integer, {}, {} },
|
||||
{ user16, 0, 0, 127, false, {}, ConfigType::integer, {}, {} },
|
||||
{ user17, 0, 0, 127, false, {}, ConfigType::integer, {}, {} },
|
||||
{ user18, 0, 0, 127, false, {}, ConfigType::integer, {}, {} },
|
||||
{ user19, 0, 0, 127, false, {}, ConfigType::integer, {}, {} },
|
||||
{ user20, 0, 0, 127, false, {}, ConfigType::integer, {}, {} },
|
||||
{ user21, 0, 0, 127, false, {}, ConfigType::integer, {}, {} },
|
||||
{ user22, 0, 0, 127, false, {}, ConfigType::integer, {}, {} },
|
||||
{ user23, 0, 0, 127, false, {}, ConfigType::integer, {}, {} },
|
||||
{ user24, 0, 0, 127, false, {}, ConfigType::integer, {}, {} },
|
||||
{ user25, 0, 0, 127, false, {}, ConfigType::integer, {}, {} },
|
||||
{ user26, 0, 0, 127, false, {}, ConfigType::integer, {}, {} },
|
||||
{ user27, 0, 0, 127, false, {}, ConfigType::integer, {}, {} },
|
||||
{ user28, 0, 0, 127, false, {}, ConfigType::integer, {}, {} },
|
||||
{ user29, 0, 0, 127, false, {}, ConfigType::integer, {}, {} },
|
||||
{ user30, 0, 0, 127, false, {}, ConfigType::integer, {}, {} },
|
||||
{ user31, 0, 0, 127, false, {}, ConfigType::integer, {}, {} }
|
||||
};
|
||||
|
||||
//==============================================================================
|
||||
int32 getItemValue (ConfigItemId item)
|
||||
{
|
||||
uint32 itemIndex;
|
||||
|
||||
if (getIndexForItem (item, itemIndex))
|
||||
return configList[itemIndex].value;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void setItemValue (ConfigItemId item, int32 value)
|
||||
{
|
||||
uint32 itemIndex;
|
||||
|
||||
if (getIndexForItem (item, itemIndex))
|
||||
configList[itemIndex].value = value;
|
||||
|
||||
setBlockConfig (item, value);
|
||||
}
|
||||
|
||||
int32 getItemMin (ConfigItemId item)
|
||||
{
|
||||
uint32 itemIndex;
|
||||
|
||||
if (getIndexForItem (item, itemIndex))
|
||||
return configList[itemIndex].min;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void setItemMin (ConfigItemId item, int32 min)
|
||||
{
|
||||
uint32 itemIndex;
|
||||
|
||||
if (getIndexForItem (item, itemIndex))
|
||||
configList[itemIndex].min = min;
|
||||
}
|
||||
|
||||
int32 getItemMax (ConfigItemId item)
|
||||
{
|
||||
uint32 itemIndex;
|
||||
|
||||
if (getIndexForItem (item, itemIndex))
|
||||
return configList[itemIndex].max;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void setItemMax (ConfigItemId item, int32 max)
|
||||
{
|
||||
uint32 itemIndex;
|
||||
|
||||
if (getIndexForItem (item, itemIndex))
|
||||
configList[itemIndex].max = max;
|
||||
|
||||
// Send updateConfig message to Block
|
||||
}
|
||||
|
||||
bool getItemActive (ConfigItemId item)
|
||||
{
|
||||
uint32 itemIndex;
|
||||
|
||||
if (getIndexForItem (item, itemIndex))
|
||||
return configList[itemIndex].isActive;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void setItemActive (ConfigItemId item, bool isActive)
|
||||
{
|
||||
uint32 itemIndex;
|
||||
|
||||
if (getIndexForItem (item, itemIndex))
|
||||
configList[itemIndex].isActive = isActive;
|
||||
|
||||
// Send setConfigState message to Block
|
||||
}
|
||||
|
||||
juce::String getOptionName (ConfigItemId item, uint8 optionIndex)
|
||||
{
|
||||
uint32 itemIndex;
|
||||
|
||||
if (getIndexForItem (item, itemIndex) && optionIndex < configMaxOptions)
|
||||
return configList[itemIndex].optionNames[optionIndex];
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
Block::ConfigMetaData getMetaData (ConfigItemId item)
|
||||
{
|
||||
uint32 itemIndex;
|
||||
|
||||
if (getIndexForItem (item, itemIndex))
|
||||
return configList[itemIndex].toConfigMetaData();
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
void resetConfigListActiveStatus()
|
||||
{
|
||||
for (auto& i : configList)
|
||||
i.isActive = false;
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
// Set Block Configuration
|
||||
void setBlockConfig (ConfigItemId item, int32 value)
|
||||
{
|
||||
HostPacketBuilder<32> packet;
|
||||
|
||||
packet.writePacketSysexHeaderBytes (deviceIndex);
|
||||
packet.addConfigSetMessage (item, value);
|
||||
packet.writePacketSysexFooter();
|
||||
|
||||
if (deviceConnection != nullptr)
|
||||
deviceConnection->sendMessageToDevice (packet.getData(), (size_t) packet.size());
|
||||
}
|
||||
|
||||
void requestBlockConfig (ConfigItemId item)
|
||||
{
|
||||
HostPacketBuilder<32> packet;
|
||||
|
||||
packet.writePacketSysexHeaderBytes (deviceIndex);
|
||||
packet.addRequestMessage (item);
|
||||
packet.writePacketSysexFooter();
|
||||
|
||||
if (deviceConnection != nullptr)
|
||||
deviceConnection->sendMessageToDevice(packet.getData(), (size_t) packet.size());
|
||||
}
|
||||
|
||||
void requestFactoryConfigSync()
|
||||
{
|
||||
HostPacketBuilder<32> packet;
|
||||
|
||||
packet.writePacketSysexHeaderBytes(deviceIndex);
|
||||
packet.addRequestFactorySyncMessage();
|
||||
packet.writePacketSysexFooter();
|
||||
|
||||
if (deviceConnection != nullptr)
|
||||
deviceConnection->sendMessageToDevice(packet.getData(), (size_t) packet.size());
|
||||
}
|
||||
|
||||
void requestUserConfigSync()
|
||||
{
|
||||
HostPacketBuilder<32> packet;
|
||||
|
||||
packet.writePacketSysexHeaderBytes(deviceIndex);
|
||||
packet.addRequestUserSyncMessage();
|
||||
packet.writePacketSysexFooter();
|
||||
|
||||
if (deviceConnection != nullptr)
|
||||
deviceConnection->sendMessageToDevice(packet.getData(), (size_t) packet.size());
|
||||
}
|
||||
|
||||
void handleConfigUpdateMessage (int32 item, int32 value, int32 min, int32 max)
|
||||
{
|
||||
uint32 index;
|
||||
|
||||
if (getIndexForItem ((ConfigItemId) item, index))
|
||||
{
|
||||
configList[index].value = value;
|
||||
configList[index].min = min;
|
||||
configList[index].max = max;
|
||||
configList[index].isActive = true;
|
||||
}
|
||||
}
|
||||
|
||||
void handleConfigSetMessage(int32 item, int32 value)
|
||||
{
|
||||
uint32 index;
|
||||
|
||||
if (getIndexForItem ((ConfigItemId) item, index))
|
||||
configList[index].value = value;
|
||||
}
|
||||
|
||||
private:
|
||||
bool getIndexForItem (ConfigItemId item, uint32& index)
|
||||
{
|
||||
for (uint32 i = 0; i < numConfigItems; ++i)
|
||||
{
|
||||
if (configList[i].item == item)
|
||||
{
|
||||
index = i;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
TopologyIndex deviceIndex;
|
||||
PhysicalTopologySource::DeviceConnection* deviceConnection;
|
||||
};
|
||||
|
||||
} // namespace juce
|
141
modules/juce_blocks_basics/blocks/juce_ControlButton.h
Normal file
141
modules/juce_blocks_basics/blocks/juce_ControlButton.h
Normal file
@ -0,0 +1,141 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library.
|
||||
Copyright (c) 2017 - ROLI Ltd.
|
||||
|
||||
JUCE is an open source library subject to commercial or open-source
|
||||
licensing.
|
||||
|
||||
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.
|
||||
|
||||
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
|
||||
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
|
||||
DISCLAIMED.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
namespace juce
|
||||
{
|
||||
|
||||
/**
|
||||
Represents a button on a block device.
|
||||
|
||||
@tags{Blocks}
|
||||
*/
|
||||
class ControlButton
|
||||
{
|
||||
public:
|
||||
ControlButton (Block&);
|
||||
|
||||
/** Destructor. */
|
||||
virtual ~ControlButton();
|
||||
|
||||
/** These are all known types of control buttons.
|
||||
You can find out which buttons a device has by calling getButtons(),
|
||||
and can get the name of a button type with getButtonName().
|
||||
*/
|
||||
enum ButtonFunction
|
||||
{
|
||||
mode, /**< The side button on a lightpad block and the first button on a live/loop block. */
|
||||
|
||||
volume, /**< The volume button on a live/loop block. */
|
||||
|
||||
// common to all types of block
|
||||
up, /**< The up button on a control block. */
|
||||
down, /**< The down button on a control block. */
|
||||
|
||||
// live block buttons
|
||||
scale, /**< The scale button on a live block. */
|
||||
chord, /**< The chord button on a live block. */
|
||||
arp, /**< The arp button on a live block. */
|
||||
sustain, /**< The sustain button on a live block. */
|
||||
octave, /**< The octave button on a live block. */
|
||||
love, /**< The love button on a live block. */
|
||||
|
||||
// loop block buttons
|
||||
click, /**< The click button on a loop block. */
|
||||
snap, /**< The snap button on a loop block. */
|
||||
back, /**< The back button on a loop block. */
|
||||
playOrPause, /**< The play or pause button on a loop block. */
|
||||
record, /**< The record button on a loop block. */
|
||||
learn, /**< The learn button on a loop block. */
|
||||
|
||||
// developer block buttons
|
||||
button0, /**< Button 0 on a developer block. */
|
||||
button1, /**< Button 1 on a developer block. */
|
||||
button2, /**< Button 2 on a developer block. */
|
||||
button3, /**< Button 3 on a developer block. */
|
||||
button4, /**< Button 4 on a developer block. */
|
||||
button5, /**< Button 5 on a developer block. */
|
||||
button6, /**< Button 6 on a developer block. */
|
||||
button7, /**< Button 7 on a developer block. */
|
||||
|
||||
// touch block buttons
|
||||
velocitySensitivity, /**< The velocity sensitivity button on a touch block. */
|
||||
glideSensitivity, /**< The glide sensitivity button on a touch block. */
|
||||
slideSensitivity, /**< The slide sensitivity button on a touch block. */
|
||||
pressSensitivity, /**< The press sensitivity button on a touch block. */
|
||||
liftSensitivity, /**< The lift sensitivity button on a touch block. */
|
||||
fixedVelocity, /**< The fixed velocity button on a touch block. */
|
||||
glideLock, /**< The glide lock button on a touch block. */
|
||||
pianoMode /**< The piano mode button on a touch block. */
|
||||
};
|
||||
|
||||
/** Returns the button's type. */
|
||||
virtual ButtonFunction getType() const = 0;
|
||||
|
||||
/** Returns the button's description. */
|
||||
virtual juce::String getName() const = 0;
|
||||
|
||||
/** Returns the position of this button on the device, in device units.
|
||||
For buttons that are on the side of the device, this may want to return a value that
|
||||
is beyond the phyiscal block size.
|
||||
*/
|
||||
virtual float getPositionX() const = 0;
|
||||
|
||||
/** Returns the position of this button on the device, in device units.
|
||||
For buttons that are on the side of the device, this may want to return a value that
|
||||
is beyond the phyiscal block size.
|
||||
*/
|
||||
virtual float getPositionY() const = 0;
|
||||
|
||||
/** Returns true if this button has a controllable light. */
|
||||
virtual bool hasLight() const = 0;
|
||||
|
||||
/** If the button can light-up, this sets its colour. */
|
||||
virtual bool setLightColour (LEDColour newColour) = 0;
|
||||
|
||||
/** A listener that can be attached to a ControlButton object so that it
|
||||
gets called when the button is pushed or released.
|
||||
*/
|
||||
struct Listener
|
||||
{
|
||||
virtual ~Listener();
|
||||
|
||||
/** Called when the button is pressed. */
|
||||
virtual void buttonPressed (ControlButton&, Block::Timestamp) = 0;
|
||||
/** Called when the button is released. */
|
||||
virtual void buttonReleased (ControlButton&, Block::Timestamp) = 0;
|
||||
};
|
||||
|
||||
/** Adds a listener to the control button. */
|
||||
void addListener (Listener*);
|
||||
/** Removes a listener from the control button. */
|
||||
void removeListener (Listener*);
|
||||
|
||||
/** The control block that this button belongs to. */
|
||||
Block& block;
|
||||
|
||||
protected:
|
||||
juce::ListenerList<Listener> listeners;
|
||||
|
||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ControlButton)
|
||||
};
|
||||
|
||||
} // namespace juce
|
105
modules/juce_blocks_basics/blocks/juce_LEDGrid.h
Normal file
105
modules/juce_blocks_basics/blocks/juce_LEDGrid.h
Normal file
@ -0,0 +1,105 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library.
|
||||
Copyright (c) 2017 - ROLI Ltd.
|
||||
|
||||
JUCE is an open source library subject to commercial or open-source
|
||||
licensing.
|
||||
|
||||
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.
|
||||
|
||||
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
|
||||
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
|
||||
DISCLAIMED.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
namespace juce
|
||||
{
|
||||
|
||||
/**
|
||||
A simple ARGB colour class for setting LEDs.
|
||||
|
||||
@tags{Blocks}
|
||||
*/
|
||||
struct LEDColour
|
||||
{
|
||||
LEDColour() noexcept = default;
|
||||
LEDColour (const LEDColour&) noexcept = default;
|
||||
LEDColour& operator= (const LEDColour&) noexcept = default;
|
||||
|
||||
LEDColour (uint32 argbColour) noexcept : argb (argbColour) {}
|
||||
|
||||
template <typename ColourType>
|
||||
LEDColour (const ColourType& colour) : LEDColour (colour.getARGB()) {}
|
||||
|
||||
uint8 getAlpha() const noexcept { return (uint8) (argb >> 24); }
|
||||
uint8 getRed() const noexcept { return (uint8) (argb >> 16); }
|
||||
uint8 getGreen() const noexcept { return (uint8) (argb >> 8); }
|
||||
uint8 getBlue() const noexcept { return (uint8) argb; }
|
||||
|
||||
uint32 getARGB() const noexcept { return argb; }
|
||||
|
||||
uint32 argb = 0;
|
||||
};
|
||||
|
||||
|
||||
//==============================================================================
|
||||
/**
|
||||
Represents a 2D grid of LEDs on a block device.
|
||||
|
||||
@tags{Blocks}
|
||||
*/
|
||||
class LEDGrid
|
||||
{
|
||||
public:
|
||||
LEDGrid (Block&);
|
||||
|
||||
/** Destructor. */
|
||||
virtual ~LEDGrid();
|
||||
|
||||
//==============================================================================
|
||||
/** Returns the number of columns in the LED grid. */
|
||||
virtual int getNumColumns() const = 0;
|
||||
|
||||
/** Returns the number of rows in the LED grid. */
|
||||
virtual int getNumRows() const = 0;
|
||||
|
||||
//==============================================================================
|
||||
/** An interface to use for LEDGrid rendering. */
|
||||
struct Renderer : public juce::ReferenceCountedObject
|
||||
{
|
||||
virtual ~Renderer();
|
||||
virtual void renderLEDGrid (LEDGrid&) = 0;
|
||||
|
||||
/** The Renderer class is reference-counted, so always use a Renderer::Ptr when
|
||||
you are keeping references to them.
|
||||
*/
|
||||
using Ptr = juce::ReferenceCountedObjectPtr<Renderer>;
|
||||
};
|
||||
|
||||
/** Set the visualiser that will create visuals for this block (nullptr for none).
|
||||
Note that the LEDGrid will NOT take ownership of this object, so the caller
|
||||
must ensure that it doesn't get deleted while in use here.
|
||||
*/
|
||||
void setRenderer (Renderer::Ptr newRenderer) noexcept { renderer = newRenderer; }
|
||||
|
||||
/** Returns the visualiser currently attached to this block (nullptr for none). */
|
||||
Renderer::Ptr getRenderer() const noexcept { return renderer; }
|
||||
|
||||
/** The device that this LEDGrid belongs to. */
|
||||
Block& block;
|
||||
|
||||
private:
|
||||
Renderer::Ptr renderer;
|
||||
|
||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (LEDGrid)
|
||||
};
|
||||
|
||||
} // namespace juce
|
64
modules/juce_blocks_basics/blocks/juce_LEDRow.h
Normal file
64
modules/juce_blocks_basics/blocks/juce_LEDRow.h
Normal file
@ -0,0 +1,64 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library.
|
||||
Copyright (c) 2017 - ROLI Ltd.
|
||||
|
||||
JUCE is an open source library subject to commercial or open-source
|
||||
licensing.
|
||||
|
||||
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.
|
||||
|
||||
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
|
||||
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
|
||||
DISCLAIMED.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
namespace juce
|
||||
{
|
||||
|
||||
/**
|
||||
Represents an LED strip on a device.
|
||||
|
||||
@tags{Blocks}
|
||||
*/
|
||||
class LEDRow
|
||||
{
|
||||
public:
|
||||
LEDRow (Block&);
|
||||
|
||||
/** Destructor. */
|
||||
virtual ~LEDRow();
|
||||
|
||||
//==============================================================================
|
||||
/** Return the number of LEDs in the row. */
|
||||
virtual int getNumLEDs() const = 0;
|
||||
|
||||
/** Sets the colour of the corresponding LED. */
|
||||
virtual void setLEDColour (int index, LEDColour newColour) = 0;
|
||||
|
||||
/** Overlays all LEDs with a single colour.
|
||||
|
||||
Whilst the overlay is set subsequent calls to setLEDColour will happen
|
||||
*behind* the overlay, and will be invisible to the user until the
|
||||
overlay is removed.
|
||||
*/
|
||||
virtual void setOverlayColour (LEDColour newColour) = 0;
|
||||
|
||||
/* Removes an overlay colour. */
|
||||
virtual void resetOverlayColour() = 0;
|
||||
|
||||
/** The device that these lights belong to. */
|
||||
Block& block;
|
||||
|
||||
private:
|
||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (LEDRow)
|
||||
};
|
||||
|
||||
} // namespace juce
|
53
modules/juce_blocks_basics/blocks/juce_StatusLight.h
Normal file
53
modules/juce_blocks_basics/blocks/juce_StatusLight.h
Normal file
@ -0,0 +1,53 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library.
|
||||
Copyright (c) 2017 - ROLI Ltd.
|
||||
|
||||
JUCE is an open source library subject to commercial or open-source
|
||||
licensing.
|
||||
|
||||
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.
|
||||
|
||||
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
|
||||
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
|
||||
DISCLAIMED.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
namespace juce
|
||||
{
|
||||
|
||||
/**
|
||||
Represents a status LED on a device.
|
||||
|
||||
@tags{Blocks}
|
||||
*/
|
||||
class StatusLight
|
||||
{
|
||||
public:
|
||||
StatusLight (Block&);
|
||||
|
||||
/** Destructor. */
|
||||
virtual ~StatusLight();
|
||||
|
||||
//==============================================================================
|
||||
/** Returns a name to describe this light. */
|
||||
virtual juce::String getName() const = 0;
|
||||
|
||||
/** Changes the light's colour. */
|
||||
virtual bool setColour (LEDColour newColour) = 0;
|
||||
|
||||
/** The device that this LED belongs to. */
|
||||
Block& block;
|
||||
|
||||
private:
|
||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (StatusLight)
|
||||
};
|
||||
|
||||
} // namespace juce
|
152
modules/juce_blocks_basics/blocks/juce_TouchList.h
Normal file
152
modules/juce_blocks_basics/blocks/juce_TouchList.h
Normal file
@ -0,0 +1,152 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library.
|
||||
Copyright (c) 2017 - ROLI Ltd.
|
||||
|
||||
JUCE is an open source library subject to commercial or open-source
|
||||
licensing.
|
||||
|
||||
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.
|
||||
|
||||
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
|
||||
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
|
||||
DISCLAIMED.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
namespace juce
|
||||
{
|
||||
|
||||
/**
|
||||
Utility class to hold a list of TouchSurface::Touch objects with different
|
||||
indices and blockUIDs, where each touch has a mapping to some kind of
|
||||
user-supplied data value.
|
||||
|
||||
The Type template is a user-defined type of object that will be stored for
|
||||
each touch element. The type must be default-constructable and copyable.
|
||||
|
||||
@tags{Blocks}
|
||||
*/
|
||||
template <typename Type>
|
||||
class TouchList
|
||||
{
|
||||
public:
|
||||
/** Creates an empty touch list. */
|
||||
TouchList() {}
|
||||
|
||||
/** Destructor. */
|
||||
~TouchList() {}
|
||||
|
||||
/** Returns the number of entries in the touch list. */
|
||||
int size() const noexcept { return touches.size(); }
|
||||
|
||||
/** Returns the user data object that corresponds to the given touch.
|
||||
This will also update the stored state of the TouchEntry::touch value
|
||||
for this touch index.
|
||||
*/
|
||||
Type& getValue (const TouchSurface::Touch& touch)
|
||||
{
|
||||
auto* t = find (touch);
|
||||
|
||||
if (t == nullptr)
|
||||
{
|
||||
touches.add ({ touch, {} });
|
||||
return touches.getReference (touches.size() - 1).value;
|
||||
}
|
||||
else
|
||||
{
|
||||
t->touch = touch;
|
||||
return t->value;
|
||||
}
|
||||
}
|
||||
|
||||
/** Returns true if a touch is already in the list. */
|
||||
bool contains (const TouchSurface::Touch& touch) const noexcept
|
||||
{
|
||||
return find (touch) != nullptr;
|
||||
}
|
||||
|
||||
/** Updates the entry for the given touch, copying in the new state.
|
||||
If no entry with the same index and blockUID exists then a new entry is
|
||||
created. If given a touch which is a touch-end, this will *remove* any
|
||||
corresponding entries from the list.
|
||||
*/
|
||||
void updateTouch (const TouchSurface::Touch& touch)
|
||||
{
|
||||
if (touch.isTouchEnd)
|
||||
{
|
||||
for (int i = touches.size(); --i >= 0;)
|
||||
if (matches (touches.getReference(i).touch, touch))
|
||||
touches.remove (i);
|
||||
|
||||
jassert (! contains (touch));
|
||||
}
|
||||
else
|
||||
{
|
||||
auto t = find (touch);
|
||||
|
||||
if (t == nullptr)
|
||||
touches.add ({ touch, {} });
|
||||
else
|
||||
t->touch = touch;
|
||||
}
|
||||
}
|
||||
|
||||
/** Holds the current state of a touch, along with the user-data associated with it. */
|
||||
struct TouchEntry
|
||||
{
|
||||
TouchSurface::Touch touch;
|
||||
Type value;
|
||||
};
|
||||
|
||||
/** If a touch is in the list, returns a pointer to the TouchEntry.
|
||||
Otherwise, returns nullptr.
|
||||
*/
|
||||
const TouchEntry* find (const TouchSurface::Touch& touch) const noexcept
|
||||
{
|
||||
for (auto& t : touches)
|
||||
if (matches (t.touch, touch))
|
||||
return &t;
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
TouchEntry* find (const TouchSurface::Touch& touch) noexcept
|
||||
{
|
||||
return const_cast<TouchEntry*> (static_cast<const TouchList&> (*this).find (touch));
|
||||
}
|
||||
|
||||
/** Allows iterator access to the list of touch entries. */
|
||||
TouchEntry* begin() noexcept { return touches.begin(); }
|
||||
const TouchEntry* begin() const noexcept { return touches.begin(); }
|
||||
|
||||
/** Allows iterator access to the list of touch entries. */
|
||||
TouchEntry* end() noexcept { return touches.end(); }
|
||||
const TouchEntry* end() const noexcept { return touches.end(); }
|
||||
|
||||
/** Retrieve a reference to particular item in the list of touch entires. */
|
||||
TouchEntry& operator[] (const int index) { return touches.getReference (index); }
|
||||
|
||||
/** Resets all contents, doest not generate any call-backs. */
|
||||
void clear() noexcept { touches.clear(); }
|
||||
|
||||
private:
|
||||
//==========================================================================
|
||||
static bool matches (const TouchSurface::Touch& t1,
|
||||
const TouchSurface::Touch& t2) noexcept
|
||||
{
|
||||
return t1.index == t2.index && t1.blockUID == t2.blockUID;
|
||||
}
|
||||
|
||||
juce::Array<TouchEntry> touches;
|
||||
|
||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (TouchList)
|
||||
};
|
||||
|
||||
} // namespace juce
|
138
modules/juce_blocks_basics/blocks/juce_TouchSurface.h
Normal file
138
modules/juce_blocks_basics/blocks/juce_TouchSurface.h
Normal file
@ -0,0 +1,138 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library.
|
||||
Copyright (c) 2017 - ROLI Ltd.
|
||||
|
||||
JUCE is an open source library subject to commercial or open-source
|
||||
licensing.
|
||||
|
||||
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.
|
||||
|
||||
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
|
||||
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
|
||||
DISCLAIMED.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
namespace juce
|
||||
{
|
||||
|
||||
/**
|
||||
Represents the touch surface of a BLOCKS device.
|
||||
|
||||
@tags{Blocks}
|
||||
*/
|
||||
class TouchSurface
|
||||
{
|
||||
public:
|
||||
TouchSurface (Block&);
|
||||
|
||||
/** Destructor. */
|
||||
virtual ~TouchSurface();
|
||||
|
||||
//==============================================================================
|
||||
/** Structure used to describe touch properties */
|
||||
struct Touch
|
||||
{
|
||||
/** A touch index, which will stay constant for each finger as it is tracked. */
|
||||
int index;
|
||||
|
||||
/** The X position of this touch on the device, in logical units starting from 0 (left).
|
||||
|
||||
See Block::getWidth() for the maximum X value on the device.
|
||||
*/
|
||||
float x;
|
||||
|
||||
/** An approximation of the velocity at which the X value is changing, measured in
|
||||
units/second. This is intended as a useful hint to help with gesture detection, but
|
||||
may be 0 if the device doesn't provide this data.
|
||||
*/
|
||||
float xVelocity;
|
||||
|
||||
/** The Y position of this touch on the device, in logical units starting from 0 (top).
|
||||
|
||||
See Block::getHeight() to find the maximum Y on the device.
|
||||
*/
|
||||
float y;
|
||||
|
||||
/** An approximation of the velocity at which the Y value is changing, measured in
|
||||
units/second. This is intended as a useful hint to help with gesture detection, but
|
||||
may be 0 if the device doesn't provide this data.
|
||||
*/
|
||||
float yVelocity;
|
||||
|
||||
/** The current pressure of this touch, in the range 0.0 (no pressure) to 1.0 (very hard). */
|
||||
float z;
|
||||
|
||||
/** The rate at which pressure is currently changing, measured in units/second. This is
|
||||
intended as a useful hint to help with gesture detection, but may be 0 if the device
|
||||
doesn't provide this data.
|
||||
*/
|
||||
float zVelocity;
|
||||
|
||||
/** The timestamp of this event, in milliseconds since the device was booted. */
|
||||
Block::Timestamp eventTimestamp;
|
||||
|
||||
/** True if this is the first event for this finger/index. */
|
||||
bool isTouchStart;
|
||||
|
||||
/** True if this is the final event as this finger/index is lifted off. */
|
||||
bool isTouchEnd;
|
||||
|
||||
/** The ID of the block that generated this touch. */
|
||||
Block::UID blockUID;
|
||||
|
||||
/** The initial X position of the touchStart event corresponding to this finger/index. */
|
||||
float startX;
|
||||
|
||||
/** The initial Y position of the touchStart event corresponding to this finger/index. */
|
||||
float startY;
|
||||
};
|
||||
|
||||
//==============================================================================
|
||||
/** Forces a touch-off message for all active touches. */
|
||||
virtual void cancelAllActiveTouches() noexcept = 0;
|
||||
|
||||
/** For the on-screen seaboard view, this will return the number of keys.
|
||||
For other types of touch-surface, it will return 0. */
|
||||
virtual int getNumberOfKeywaves() const = 0;
|
||||
|
||||
//==============================================================================
|
||||
/** Receives callbacks when a touch moves or changes pressure. */
|
||||
struct Listener
|
||||
{
|
||||
virtual ~Listener();
|
||||
|
||||
virtual void touchChanged (TouchSurface&, const Touch&) = 0;
|
||||
};
|
||||
|
||||
/** Testing feature: this allows you to inject touches onto a touch surface. */
|
||||
void callListenersTouchChanged (const TouchSurface::Touch& t)
|
||||
{
|
||||
listeners.call ([this, &t] (Listener& l) { l.touchChanged (*this, t); });
|
||||
}
|
||||
|
||||
/** Adds a listener to be called when the surface is touched. */
|
||||
void addListener (Listener*);
|
||||
|
||||
/** Removes a previously-registered listener. */
|
||||
void removeListener (Listener*);
|
||||
|
||||
//==============================================================================
|
||||
/** The block that owns this touch surface. */
|
||||
Block& block;
|
||||
|
||||
protected:
|
||||
//==============================================================================
|
||||
juce::ListenerList<Listener> listeners;
|
||||
|
||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (TouchSurface)
|
||||
};
|
||||
|
||||
} // namespace juce
|
Reference in New Issue
Block a user