The BLOCKS SDK
BlockFinder

In order to compile and run this application you need to first download and compile the BLOCKS-SDK, which can be obtained from GitHub here.

If you need help with this step, please refer to The standalone BLOCKS SDK section.

An example application

The source code for this example can be found in the BLOCKS-SDK repository at examples/BlockFinder/, with the parts that are specific to different operating systems in the corresponding subdirectories.

The main functionality of the application is contained within the following class:

BlockFinder/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/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);
}
}

All this class does is create a PhysicalTopologySource and register for TopologySource::Listener::topologyChanged() callbacks — for more information about how this works you should see the Discovering BLOCKS section. When the topology changes we print some information about the available BLOCKS.

The main function of the macOS application is the easiest to understand.

BlockFinder/MacOS/main.mm:

/*
==============================================================================
This file is part of the JUCE examples.
Copyright (c) 2020 - Raw Material Software Limited
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.
==============================================================================
*/
#include "../BlockFinder.h"
#import <Cocoa/Cocoa.h>
int main (int argc, const char * argv[])
{
// Initialise the JUCE code.
juce::ScopedJuceInitialiser_GUI platform;
// Create our JUCE object.
BlockFinder finder;
// Run an event loop.
while ([[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]]);
return 0;
}

Here we simply perform some JUCE initialisation, instantiate a BlockFinder class, then run the event loop. Whilst in the event loop, the finder object receives TopologySource::Listener::topologyChanged() callbacks and we see output printed to stdout when BLOCKS are connected or disconnected.