Getting the reason for failed AudioProcessorGraph::addConnection

For internal debugging purposes, and possibly for future error messages to users, I’ve adapted the canConnect and addConnection classes to return a Result rather than a bool.
I realise this would break peoples code and its a quick + dirty solution, better addressed in the long term by the use of an enum to represent all the different reasons for failure, with an added parameter at the end of each method to store the result, e.g.

    enum ConnectionFailureReason 
    {
        sourceChannelIndexLessThanZero,
        // ...
    };

    // Overloaded versions
    bool canConnect (uint32 sourceNodeId, int sourceChannelIndex,
                     uint32 destNodeId, int destChannelIndex, ConnectionFailureReason& reason) const;

    bool addConnection (uint32 sourceNodeId, int sourceChannelIndex,
                        uint32 destNodeId, int destChannelIndex, ConnectionFailureReason& reason);

My quick & dirty code using the Result class, in case its useful to anyone…

Result AudioProcessorGraph::canConnect (const uint32 sourceNodeId,
                                      const int sourceChannelIndex,
                                      const uint32 destNodeId,
                                      const int destChannelIndex) const
{
    if (sourceChannelIndex < 0) return Result::fail ("sourceChannelIndex < 0");
    if (destChannelIndex < 0) return Result::fail ("destChannelIndex < 0");
    if (sourceNodeId == destNodeId) return Result::fail ("sourceNodeId == destNodeId");
    if ((destChannelIndex == midiChannelIndex) != (sourceChannelIndex == midiChannelIndex))
        return Result::fail ("attempting to connect audio to midi or vice versa");
    
    const Node* const source = getNodeForId (sourceNodeId);

    if (source == nullptr) return Result::fail ("source == nullptr");
    if (sourceChannelIndex != midiChannelIndex && sourceChannelIndex >= source->processor->getTotalNumOutputChannels())
        return Result::fail ("sourceChannelIndex >= source->processor->getTotalNumOutputChannels()");
    if (sourceChannelIndex == midiChannelIndex && ! source->processor->producesMidi())
        return Result::fail ("sourceChannelIndex == midiChannelIndex && ! source->processor->producesMidi()");

    const Node* const dest = getNodeForId (destNodeId);

    if (dest == nullptr) return Result::fail ("dest == nullptr");
    if (destChannelIndex != midiChannelIndex && destChannelIndex >= dest->processor->getTotalNumInputChannels())
        return Result::fail ("destChannelIndex >= dest->processor->getTotalNumInputChannels()");
    if (destChannelIndex == midiChannelIndex && ! dest->processor->acceptsMidi())
        return Result::fail ("destChannelIndex == midiChannelIndex && ! dest->processor->acceptsMidi()");

    if (getConnectionBetween (sourceNodeId, sourceChannelIndex,
                                 destNodeId, destChannelIndex) != nullptr)
        return Result::fail ("connection already exists");
    
    return Result::ok();
}

Result AudioProcessorGraph::addConnection (const uint32 sourceNodeId,
                                         const int sourceChannelIndex,
                                         const uint32 destNodeId,
                                         const int destChannelIndex)
{
    Result result = canConnect (sourceNodeId, sourceChannelIndex, destNodeId, destChannelIndex);
    if (result.failed())
        return result;

    GraphRenderingOps::ConnectionSorter sorter;
    connections.addSorted (sorter, new Connection (sourceNodeId, sourceChannelIndex,
                                                   destNodeId, destChannelIndex));

    if (isPrepared)
        triggerAsyncUpdate();

    return result;
}

That’s handy. Should save me dancing with the debugger each time a connection fails.

I’ll try and elaborate on the enum idea at some point when I get some time…

Curious to know if there’s an update on this? Having a more elaborate return on addConnection() and/or canConnect() would be amazing!!!

1 Like