The BLOCKS SDK
Discovering BLOCKS

Any BLOCKS application would be pretty limited without the ability to discover the BLOCKS that are connected to your computer.

This page gives an overview of the classes and methods available to aid BLOCKS discovery and provides sample code for getting notifications of any connections or disconnections.

The BlockTopology object

Groups of connected Lightpad and Control Blocks are described by a BlockTopology.

A BlockTopology contains an array of references to Block objects, which provide access to Lightpad and Control Block functionality, and an array of BlockDeviceConnection objects, which describe the connections between devices. Once you have a BlockTopology you have all the information required to visualise and interact with your Lightpads and Control Blocks. For more information about using Block objects see The Block object section.

For Lightpads and Control Blocks, a BlockTopology can be obtained from a PhysicalTopologySource.

The PhysicalTopologySource object

The current topology is provided by a PhysicalTopologySource. When instantiated, a PhysicalTopologySource monitors for any connections from your computer to any Lightpad and Control Blocks and the PhysicalTopologySource::getCurrentTopology() method returns the current BlockTopology.

In an environment where Lightpad and Control Blocks can be connected and disconnected dynamically it is convenient to register your code for topologyChanged() callbacks from a PhysicalTopologySource. Then, when the current BlockTopology changes, your application is able to react to the new configuration. You can do this by inheriting from the TopologySource::Listener class and registering as a listener to a PhysicalTopologySource object. When you inherit from TopologySource::Listener you must override the pure virtual method TopologySource::Listener::topologyChanged(), which is then called by a PhysicalTopologySource on topology changes when you register as a listener.

A simple example is shown below.

BlockFinder.h:

/*
==============================================================================
Copyright (c) 2021 - ROLI Ltd
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 ROLI LTD DISCLAIMS ALL WARRANTIES WITH
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
AND FITNESS. IN NO EVENT SHALL ROLI LTD 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.
==============================================================================
*/
#pragma once
#include <BlocksHeader.h>
// Monitors a PhysicalTopologySource for changes to the connected BLOCKS and
// prints some information about the BLOCKS that are available.
class BlockFinder : private juce::TopologySource::Listener
{
public:
// Register as a listener to the PhysicalTopologySource, so that we receive
// callbacks in topologyChanged().
BlockFinder();
private:
// Called by the PhysicalTopologySource when the BLOCKS topology changes.
void topologyChanged() override;
// The PhysicalTopologySource member variable which reports BLOCKS changes.
juce::PhysicalTopologySource pts;
};

BlockFinder.cpp:

/*
==============================================================================
Copyright (c) 2021 - ROLI Ltd
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 ROLI LTD DISCLAIMS ALL WARRANTIES WITH
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
AND FITNESS. IN NO EVENT SHALL ROLI LTD 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.
==============================================================================
*/
#include "BlockFinder.h"
using namespace juce;
BlockFinder::BlockFinder()
{
// Register to receive topologyChanged() callbacks from pts.
pts.addListener (this);
}
void BlockFinder::topologyChanged()
{
// We have a new topology, so find out what it isand store it in a local
// variable.
auto currentTopology = pts.getCurrentTopology();
Logger::writeToLog ("\nNew BLOCKS topology.");
// The blocks member of a BlockTopology contains an array of blocks. Here we
// loop over them and print some information.
Logger::writeToLog ("Detected " + String (currentTopology.blocks.size()) + " blocks:");
for (auto& block : currentTopology.blocks)
{
Logger::writeToLog ("");
Logger::writeToLog (" Description: " + block->getDeviceDescription());
Logger::writeToLog (" Battery level: " + String (block->getBatteryLevel()));
Logger::writeToLog (" UID: " + String (block->uid));
Logger::writeToLog (" Serial number: " + block->serialNumber);
}
}

When instantiated this class simply monitors for changes to the connected Lightpad and Control Blocks and prints some information about them to stdout. Once you have the current BlockTopology object you have access to the available Block objects and can start to interact with them. A more complex application would probably do much more in the topologyChanged() method—see the Example JUCE Applications page.

You can find this simple example in the examples/BlockFinder/ directory of the BLOCKS-SDK and the following sections will build on top of this project. If you need help with downloading and installing the BLOCKS-SDK, please refer to The standalone BLOCKS SDK section.

The Block object

A Block object is the main entry point for communicating between your application and any Lightpad and Control Blocks that are connected to your computer.

All the different Block types are subclasses of Block so they provide the same interface (see the Block class documentation). About half of the Block public member functions return information about the physical device it represents. In the example code above you can see that we use some of these methods to query each Block about its current status. The more interesting Block methods return pointers to objects you can use to control and receive events from individual BLOCKS. More detail about these methods can be obtained from the following pages:

Getting touch events

Getting control button events

Controlling LED grids

Controlling LED strips

Controlling control buttons