Fundamentals
Export Targets
Code Export
Patcher UI
Special Topics
RNBO Raspberry Pi OSCQuery Runner
RNBO Helper Types
Before working with RNBO, there's a handful of helper types that deserve special mention. Having some familiarity with these types will make working with RNBO much easier.
UniquePtr
The notion of a unique pointer is borrowed heavily from the c++11 std::unique_ptr structure. The core concept is essentially the same: UniquePtr is a smart pointer that manages another object. When the UniquePtr goes out of scope, the object itself is destroyed. UniquePtr comes with a convenience function make_unique, a templated function that constructs a new object and a UniquePtr to manage that object at the same time.
using namespace RNBO;
std::cout << "Starting the program\n";
CoreObject rnboObject;
if (true) {
ConstPresetPtr newPreset = rnboObject.getPresetSync();
// This creates a new Preset, as well as a UniquePtr to manage that preset
UniquePtr<Preset> uniquePreset = make_unique<Preset>();
copyPreset(*newPreset, *uniquePreset);
// No need to worry about deleting the Preset. As soon as the uniquePreset pointer
// goes out of scope, it will delete the managed Preset object as well.
// Or, we could call std::move on the uniquePreset, handing off management of the
// pointer to another part of the program
rnboObject.setPreset(std::move(uniquePreset));
}
// In any case, uniquePreset is no longer memory that this part of the program
// needs to manageOne important thing to keep in mind is that because a UniquePtr deletes its managed object as soon as the UniquePtr goes out of scope, any function that returns a UniquePtr will delete its return value immediately if the return value is unused. Occasionally this can cause some slightly surprising results. Consider the case where the user calls createParameterInterface to attach an EventHandler to a RNBO core object.
ConcreteEventHandler handler;
if (true) {
// interface is a UniquePtr. When it goes out of scope, the managed
// ParameterInterface object will be deleted.
auto interface = rnboObject.createParameterInterface(
ParameterEventInterface::MultiProducer,
(EventHandler *) &handler
);
}
// Now that UniquePtr is out of scope, the ParameterInterface has been deleted.
// The EventHandler will no longer receive events.Even if the returned interface value is unused, it must be assigned to a variable or kept in scope for the EventHandler to receive events. It's a subtle point, but helpful to keep in mind, in case you're not receiving events when you expect to.
There are some key differences between std::unique_ptr and UniquePtr. There's no copy constructor or assignment operator for UniquePtr, which makes UniquePtr a more limited, but also much simpler alternative. In most cases, it's enough to understand what a UniquePtr is trying to achieve, and to know how to interface with RNBO API functions that require a UniquePtr instead of an unmanaged pointer (RNBO::CoreObject::setPreset is a perfect example).
RNBO::list
Similar to Max, RNBO has a notion of a list. Lists in RNBO consist of numbers only, but it's possible to treat them somewhat similar to a std::vector in the C++ standard library. You can create, iterate, and modify a RNBO::list as you'd expect.
RNBO::list mylist;
mylist.push(1);
mylist.push(2);
mylist.push(3);
for (int i = 0; i < mylist.length; i++) {
if (i != 0) std::cout << ", ";
std::cout << mylist[i];
}
std::cout << "\n";
// Prints 1, 2, 3
mylist[0] = 4;
mylist = mylist.reverse();
for (int i = 0; i < mylist.length; i++) {
if (i != 0) std::cout << ", ";
std::cout << mylist[i];
}
std::cout << "\n";
// Prints 3, 2, 4Probably the most common way to use lists is to send messages to a RNBO inport or in object. In this case, the list must be wrapped in a UniquePtr and then handed off to the RNBO core object using std::move.
using namespace RNBO;
auto mylist = make_unique<list>();
(*mylist).push(1);
(*mylist).push(2);
(*mylist).push(3);
rnboObject.sendMessage(TAG("in1"), std::move(mylist), TAG(""));