Beispiel #1
0
void GenericProcessor::disableEditor()
{

	GenericEditor* ed = getEditor();

	if (ed != 0)
	 	ed->stopAcquisition();
}
Beispiel #2
0
void ProcessorGraph::refreshColors()
{
    for (int i = 0; i < getNumNodes(); i++)
    {
        Node* node = getNode(i);

        int nodeId = node->nodeId;

        if (nodeId != OUTPUT_NODE_ID &&
            nodeId != AUDIO_NODE_ID &&
            nodeId != RECORD_NODE_ID &&
            nodeId != MESSAGE_CENTER_ID)
        {
            GenericProcessor* p =(GenericProcessor*) node->getProcessor();
            GenericEditor* e = (GenericEditor*) p->getEditor();
            e->refreshColors();
        }
    }
}
Beispiel #3
0
void ProcessorGraph::changeListenerCallback(ChangeBroadcaster* source)
{

    for (int i = 0; i < getNumNodes(); i++)
    {
        Node* node = getNode(i);

        int nodeId = node->nodeId;

        if (nodeId != OUTPUT_NODE_ID &&
            nodeId != AUDIO_NODE_ID &&
            nodeId != RECORD_NODE_ID &&
            nodeId != RESAMPLING_NODE_ID)
        {
            GenericProcessor* p =(GenericProcessor*) node->getProcessor();
            GenericEditor* e = (GenericEditor*) p->getEditor();
            e->refreshColors();
        }
    }

}
Beispiel #4
0
void ProcessorGraph::updateConnections(Array<SignalChainTabButton*, CriticalSection> tabs)
{
    clearConnections(); // clear processor graph

    std::cout << "Updating connections:" << std::endl;

    Array<GenericProcessor*> splitters;

    for (int n = 0; n < tabs.size(); n++)
    {
        std::cout << "Signal chain " << n << std::endl;

        GenericEditor* sourceEditor = (GenericEditor*) tabs[n]->getEditor();
        GenericProcessor* source = (GenericProcessor*) sourceEditor->getProcessor();

        while (source != 0)// && destEditor->isEnabled())
        {
            std::cout << "Source node: " << source->getName() << ", ";
            GenericProcessor* dest = (GenericProcessor*) source->getDestNode();

            if (dest != 0)
            {
                std::cout << "Dest node: " << dest->getName() << std::endl;
                if (dest->isMerger()) // move it forward by one
                {
                    dest = dest->getDestNode();
                }
                else if (dest->isSplitter())
                {
                    if (!dest->wasConnected)
                        splitters.add(dest);

                    dest = dest->getDestNode();
                }

            }
            else
            {
                std::cout << "no dest node." << std::endl;
            }

            if (source->enabledState())
            {

                // add the connections to audio and record nodes if necessary
                if (!(source->isSink() ||
                      source->isSplitter() || source->isMerger() || source->isUtility()) && !(source->wasConnected))
                {
                    std::cout << "   Connecting to audio and record nodes." << std::endl;

                    //source->setStartChannel(getAudioNode()->getNextChannel(false));


                    for (int chan = 0; chan < source->getNumOutputs(); chan++)
                    {

                        getAudioNode()->addInputChannel(source, chan);

                        // std::cout << "Connecting to audio channel: " <<
                        // 	      getAudioNode()->getNextChannel(false) << std::endl;

                        //getAudioNode()->enableCurrentChannel(source->audioStatus(chan));

                        addConnection(source->getNodeId(), 		   // sourceNodeID
                                      chan, 						           // sourceNodeChannelIndex
                                      AUDIO_NODE_ID, 					       // destNodeID
                                      getAudioNode()->getNextChannel(true)); // destNodeChannelIndex
                        // add 2 to account for 2 output channels


                        //std::cout << getAudioNode()->getNextChannel(false) << " ";

                        getRecordNode()->addInputChannel(source, chan);

                        // std::cout << "Connecting to record channel: " <<
                        // 	      getRecordNode()->getNextChannel(false) << std::endl;


                        addConnection(source->getNodeId(),          // sourceNodeID
                                      chan,                                   // sourceNodeChannelIndex
                                      RECORD_NODE_ID, 					    // destNodeID
                                      getRecordNode()->getNextChannel(true)); // destNodeChannelIndex

                    }

                    // connect event channel
                    addConnection(source->getNodeId(), 				// sourceNodeID
                                  midiChannelIndex, 							// sourceNodeChannelIndex
                                  RECORD_NODE_ID, 							// destNodeID
                                  midiChannelIndex);							// destNodeChannelIndex

                    // connect event channel
                    addConnection(source->getNodeId(), 				// sourceNodeID
                                  midiChannelIndex, 							// sourceNodeChannelIndex
                                  AUDIO_NODE_ID, 							// destNodeID
                                  midiChannelIndex);							// destNodeChannelIndex


                    getRecordNode()->addInputChannel(source, midiChannelIndex);

                }

                std::cout << std::endl;

                if (dest != 0)
                {

                    if (dest->enabledState())
                        std::cout << "     OK." << std::endl;
                    else
                        std::cout << "     Not OK." << std::endl;

                    if (dest->enabledState())
                    {

                        std::cout << "     Connecting " << source->getName() << " channel ";

                        for (int chan = 0; chan < source->getNumOutputs(); chan++)
                        {
                            std::cout << chan << " ";

                            addConnection(source->getNodeId(), // sourceNodeID
                                          chan, // sourceNodeChannelIndex
                                          dest->getNodeId(), // destNodeID
                                          dest->getNextChannel(true)); // destNodeChannelIndex
                        }

                        std::cout << " to " << dest->getName() << std::endl;

                        std::cout << "     Connecting " << source->getName() <<
                                  " event channel to " <<
                                  dest->getName() << std::endl;

                        // connect event channel
                        addConnection(source->getNodeId(), // sourceNodeID
                                      midiChannelIndex, // sourceNodeChannelIndex
                                      dest->getNodeId(), // destNodeID
                                      midiChannelIndex); // destNodeChannelIndex

                    }

                }
            }

            source->wasConnected = true;
            source = dest; // switch source and dest

            if (source == 0 && splitters.size() > 0)
            {
                dest = splitters.getFirst(); // dest is now the splitter
                splitters.remove(0); // take it out of the
                dest->switchIO(); // switch to the other destination
                dest->wasConnected = true; // don't want to re-add splitter
                source = dest->getSourceNode(); // splitter is now source
            }

        } // end while source != 0
    } // end "tabs" for loop
} // end method
Beispiel #5
0
void ChannelSelector::buttonClicked(Button* button)
{
    //checkChannelSelectors();
    if (button == paramsButton)
    {
        // make sure param buttons are visible
        allButton->setState(true);
        desiredOffset = parameterOffset;
        startTimer(20);
        return;
    }
    else if (button == audioButton)
    {
        // make sure audio buttons are visible

        if (audioButton->getState())
        {
            allButton->setState(false);

            desiredOffset = audioOffset;
            startTimer(20);
        }
        else
        {
            paramsButton->setToggleState(true, false);
        }
        return;
    }
    else if (button == recordButton)
    {
        // make sure record buttons are visible;
        if (recordButton->getState())
        {
            allButton->setState(true);
            desiredOffset = recordOffset;
            startTimer(20);
        }
        else
        {
            paramsButton->setToggleState(true, false);
        }
        return;
    }
    else if (button == allButton)
    {
        // select all active buttons
        if (offsetLR == recordOffset)
        {


            for (int i = 0; i < recordButtons.size(); i++)
            {
                recordButtons[i]->setToggleState(true, true);
            }

        }
        else if (offsetLR == parameterOffset)
        {


            for (int i = 0; i < parameterButtons.size(); i++)
            {
                parameterButtons[i]->setToggleState(true, true);
            }
        }
        else if (offsetLR == audioOffset)
        {
            // do nothing--> button is disabled
        }
    }
    else if (button == noneButton)
    {
        // deselect all active buttons
        if (offsetLR == recordOffset)
        {
            for (int i = 0; i < recordButtons.size(); i++)
            {
                recordButtons[i]->setToggleState(false, true);
            }
        }
        else if (offsetLR == parameterOffset)
        {
            for (int i = 0; i < parameterButtons.size(); i++)
            {
                parameterButtons[i]->setToggleState(false, true);
            }
        }
        else if (offsetLR == audioOffset)
        {
            for (int i = 0; i < audioButtons.size(); i++)
            {
                audioButtons[i]->setToggleState(false, true);
            }
        }
    }
    else
    {

        ChannelSelectorButton* b = (ChannelSelectorButton*) button;

        if (b->getType() == AUDIO)
        {
            // get audio node, and inform it of the change
            GenericEditor* editor = (GenericEditor*) getParentComponent();

            Channel* ch = editor->getChannel(b->getChannel()-1);
            //int channelNum = editor->getStartChannel() + b->getChannel() - 1;
            bool status = b->getToggleState();

            if (acquisitionIsActive) // use setParameter to change parameter safely
            {
                editor->getProcessorGraph()->
                getAudioNode()->
                setChannelStatus(ch, status);
            }
            else     // change parameter directly
            {
                ch->isMonitored = status;
            }


        }
        else if (b->getType() == RECORD)
        {
            // get record node, and inform it of the change
            GenericEditor* editor = (GenericEditor*) getParentComponent();

            Channel* ch = editor->getChannel(b->getChannel()-1);
            //int channelNum = editor->getStartChannel() + b->getChannel() - 1;
            bool status = b->getToggleState();

            if (acquisitionIsActive) // use setParameter to change parameter safely
            {
                editor->getProcessorGraph()->
                getRecordNode()->
                setChannelStatus(ch, status);
            }
            else     // change parameter directly
            {
                ch->isRecording = status;
            }

        }
        else
        {
            // do nothing
            if (radioStatus) // if radio buttons are active
            {
                // send a message to parent
                GenericEditor* editor = (GenericEditor*) getParentComponent();
                editor->channelChanged(b->getChannel());
            }
        }

    }

}
void SignalChainManager::updateVisibleEditors(GenericEditor* activeEditor,
                                              int index, int insertionPoint, int action)

{

    enum actions {ADD, MOVE, REMOVE, ACTIVATE, UPDATE};

    // Step 1: update the editor array
    if (action == ADD)
    {
        std::cout << "    Adding editor." << std::endl;
        editorArray.insert(insertionPoint, activeEditor);

    }
    else if (action == MOVE)
    {
        std::cout << "    Moving editors." << std::endl;
        if (insertionPoint < index)
            editorArray.move(index, insertionPoint);
        else if (insertionPoint > index)
            editorArray.move(index, insertionPoint-1);

    }
    else if (action == REMOVE)
    {

        std::cout << "    Removing editor." << std::endl;

        GenericProcessor* p = (GenericProcessor*) editorArray[index]->getProcessor();

        // if the processor to be removed is a merger,
        // we need to inform the other source that its merger has disappeared
        if (p->isMerger())
        {
            p->switchIO();
            if (p->getSourceNode() != 0)
                p->getSourceNode()->setDestNode(0);
        }

        // if the processor to be removed is a splitter, we need to make sure 
        // there aren't any orphaned processors
        if (p->isSplitter())
        {
            p->switchIO();
            if (p->getDestNode() != 0)
            {
                std::cout << "Found an orphaned signal chain" << std::endl;
                p->getDestNode()->setSourceNode(0);
                createNewTab(p->getDestNode()->getEditor());
            }
        }

        editorArray.remove(index);

        int t = activeEditor->tabNumber();

        // std::cout << editorArray.size() << " " << t << std::endl;

        bool merger;

        if (editorArray.size() > 0)
        {
            GenericProcessor* p = (GenericProcessor*) editorArray[0]->getProcessor();
            merger = (p->isMerger() && p->stillHasSource());
            if (merger)
            {
                std::cout << "We've got a merger!" << std::endl;
                //p->switchSource();
            }
        }

        if (editorArray.size() > 0 && !merger) // if there are still editors in this chain
        {
            if (t > -1)  // pass on tab
            {
                //      std::cout << "passing on the tab." << std::endl;
                int nextEditor = jmax(0,0);//index-1);
                editorArray[nextEditor]->tabNumber(t);
                signalChainArray[t]->setEditor(editorArray[nextEditor]);
            }

            int nextEditor = jmin(index,editorArray.size()-1);
            activeEditor = editorArray[nextEditor];
            activeEditor->select();
            //activeEditor->grabKeyboardFocus();

        }
        else
        {

            std::cout << "Tab number " << t << std::endl;

            removeTab(t);

            if (signalChainArray.size() > 0) // if there are other chains
            {
                int nextTab = jmin(t,signalChainArray.size()-1);
                activeEditor = signalChainArray[nextTab]->getEditor();
                activeEditor->select();
                signalChainArray[nextTab]->setToggleState(true,false); // send it back to update connections
            }
            else
            {
                activeEditor = 0; // nothing is active
                //  signalChainNeedsSource = true;
            }
        }

    }
    else     //no change
    {

        std::cout << "Activating editor" << std::endl;
    }

    // Step 2: update connections
    if (action != ACTIVATE && action != UPDATE && editorArray.size() > 0)
    {

        std::cout << "Updating connections." << std::endl;

        GenericProcessor* source = 0;
        GenericProcessor* dest = (GenericProcessor*) editorArray[0]->getProcessor();

        dest->setSourceNode(source);

        for (int n = 1; n < editorArray.size(); n++)
        {

            dest = (GenericProcessor*) editorArray[n]->getProcessor();
            source = (GenericProcessor*) editorArray[n-1]->getProcessor();

            dest->setSourceNode(source);
        }

        dest->setDestNode(0);

    }

    // Step 3: check for new tabs
    if (action != ACTIVATE && action != UPDATE)
    {

        std::cout << "Checking for new tabs." << std::endl;

        for (int n = 0; n < editorArray.size(); n++)
        {
            GenericProcessor* p = (GenericProcessor*) editorArray[n]->getProcessor();

            if (p->getSourceNode() == 0)// && editorArray[n]->tabNumber() == -1)
            {

                if (editorArray[n]->tabNumber() == -1)

                {
                    if (!p->isMerger())
                    {
                        std::cout << p->getName() << " has no source node. Creating a new tab." << std::endl;
                        createNewTab(editorArray[n]);
                    }
                }

            }
            else
            {
                if (editorArray[n]->tabNumber() > -1)
                {
                    removeTab(editorArray[n]->tabNumber());
                }

                editorArray[n]->tabNumber(-1); // reset tab status
            }

            if (p->isMerger())
            {
                std::cout << "It's a merger!" << std::endl;
                //createNewTab(editorArray[n]);
            }
        }
    }

    // Step 4: Refresh editors in editor array, based on active editor
    for (int n = 0; n < editorArray.size(); n++)
    {
        editorArray[n]->setVisible(false);
    }

    editorArray.clear();
    std::cout << "Cleared editor array." << std::endl;

    GenericEditor* editorToAdd = activeEditor;

    while (editorToAdd != 0)
    {
        std::cout << "Inserting " << editorToAdd->getName() << " at point 0." << std::endl;

        editorArray.insert(0,editorToAdd);
        GenericProcessor* currentProcessor = (GenericProcessor*) editorToAdd->getProcessor();
        GenericProcessor* source = currentProcessor->getSourceNode();

        if (source != 0)
        {
            std::cout << "Source: " << source->getName() << std::endl;

            // need to switch the splitter somehow
            // if (action == ACTIVATE || action == UPDATE)
            // {
            //  if (source->isSplitter())
            //  {
            //      source->setPathToProcessor(currentProcessor);
            //  }
            // }

            editorToAdd = (GenericEditor*) source->getEditor();


        }
        else
        {

            if (editorToAdd->tabNumber() >= 0)
                signalChainArray[editorToAdd->tabNumber()]->setToggleState(true, false);
            std::cout << "No source found." << std::endl;
            editorToAdd = 0;

        }
    }

    editorToAdd = activeEditor;

    while (editorToAdd != 0)
    {

        GenericProcessor* currentProcessor = (GenericProcessor*) editorToAdd->getProcessor();
        GenericProcessor* dest = currentProcessor->getDestNode();

        if (dest != 0)
        {

            std::cout << "Destination: " << dest->getName() << std::endl;
            editorToAdd = (GenericEditor*) dest->getEditor();
            editorArray.add(editorToAdd);
            std::cout << "Inserting " << editorToAdd->getName() << " at the end." << std::endl;

            if (dest->isMerger())
            {
                std::cout << "It's a merger!" << std::endl;

                if (dest->getSourceNode() != currentProcessor)
                    editorToAdd->switchSource();

            }

        }
        else
        {
            std::cout << "No dest found." << std::endl;
            editorToAdd = 0;
        }


    }

    // Step 5: check the validity of the signal chain
    if (true)
    {
        //action != ACTIVATE) {
        bool enable = true;

        if (editorArray.size() == 1)
        {

            GenericProcessor* source = (GenericProcessor*) editorArray[0]->getProcessor();
            if (source->isSource())
                editorArray[0]->setEnabledState(true);
            else
                editorArray[0]->setEnabledState(false);

        }
        else
        {

            for (int n = 0; n < editorArray.size()-1; n++)
            {
                GenericProcessor* source = (GenericProcessor*) editorArray[n]->getProcessor();
                GenericProcessor* dest = (GenericProcessor*) editorArray[n+1]->getProcessor();

                if (n == 0 && !source->isSource())
                    enable = false;

                editorArray[n]->setEnabledState(enable);

                if (source->canSendSignalTo(dest) && source->enabledState())
                    enable = true;
                else
                    enable = false;

                if (source->isSplitter())
                {
                    if (source->getDestNode() != dest)
                    {
                        //source->switchIO();
                        editorArray[n]->switchDest();
                    }
                }

                if (enable)
                    std::cout << "Enabling node." << std::endl;
                else
                    std::cout << "Not enabling node." << std::endl;

                editorArray[n+1]->setEnabledState(enable);

            }
        }
    }

    // Step 6: inform the tabs that something has changed
    for (int n = 0; n < signalChainArray.size(); n++)
    {
        if (signalChainArray[n]->getToggleState())
        {
            signalChainArray[n]->hasNewConnections(true);
        }
    }

    // Step 7: update all settings
    if (action != ACTIVATE)
    {

        std::cout << "Updating settings." << std::endl;

        Array<GenericProcessor*> splitters;

        for (int n = 0; n < signalChainArray.size(); n++)
        {
            // iterate through signal chains

            GenericEditor* source = signalChainArray[n]->getEditor();
            GenericProcessor* p = source->getProcessor();

            p->update();

            if (p->isSplitter())
            {
                splitters.add(p);
            }

            GenericProcessor* dest = p->getDestNode();

            while (dest != 0)
            {
                // iterate through processors
                dest->update();
                dest = dest->getDestNode();

                if (dest == 0 && splitters.size() > 0)
                {
                    splitters.getFirst()->switchIO();
                    dest = splitters[0]->getDestNode();
                    splitters.remove(0);
                }
            }
        }
    }


    std::cout << "Finished adding new editor." << std::endl << std::endl << std::endl;

}
void ChannelSelector::buttonClicked(Button* button)
{
    //checkChannelSelectors();
    if (button == paramsButton)
    {
        // make sure param buttons are visible
        allButton->setState(true);
        desiredOffset = parameterOffset;
        startTimer(20);
        return;
    }
    else if (button == audioButton)
    {
        // make sure audio buttons are visible

        if (audioButton->getState())
        {
            allButton->setState(false);

            desiredOffset = audioOffset;
            startTimer(20);
        }
        else
        {
            paramsButton->setToggleState(true, dontSendNotification);
        }
        return;
    }
    else if (button == recordButton)
    {
        // make sure record buttons are visible;
        if (recordButton->getState())
        {
            allButton->setState(true);
            desiredOffset = recordOffset;
            startTimer(20);
        }
        else
        {
            paramsButton->setToggleState(true, dontSendNotification);
        }
        return;
    }
    else if (button == allButton)
    {
        // select all active buttons
        if (offsetLR == recordOffset)
        {
            for (int i = 0; i < recordButtonsManager.getNumButtons(); ++i)
            {
                recordButtonsManager.getButtonAt (i)->setToggleState (true, sendNotification);
            }

        }
        else if (offsetLR == parameterOffset)
        {
            for (int i = 0; i < parameterButtonsManager.getNumButtons(); ++i)
            {
                parameterButtonsManager.getButtonAt (i)->setToggleState (true, sendNotification);
            }
        }
        else if (offsetLR == audioOffset)
        {
            // do nothing--> button is disabled
        }
    }
    else if (button == noneButton)
    {
        // deselect all active buttons
        if (offsetLR == recordOffset)
        {
            for (int i = 0; i < recordButtonsManager.getNumButtons(); ++i)
            {
                recordButtonsManager.getButtonAt (i)->setToggleState (false, sendNotification);
            }
        }
        else if (offsetLR == parameterOffset)
        {
            for (int i = 0; i < parameterButtonsManager.getNumButtons(); ++i)
            {
                parameterButtonsManager.getButtonAt (i)->setToggleState (false, sendNotification);
            }
        }
        else if (offsetLR == audioOffset)
        {
            for (int i = 0; i < audioButtonsManager.getNumButtons(); ++i)
            {
                audioButtonsManager.getButtonAt (i)->setToggleState (false, sendNotification);
            }
        }

        if (radioStatus) // if radio buttons are active
        {
            // send a message to parent
            GenericEditor* editor = (GenericEditor*) getParentComponent();
            editor->channelChanged (-1, false);
        }
    }
    else
    {
        ChannelSelectorButton* b = (ChannelSelectorButton*)button;

        if (b->getType() == AUDIO)
        {
            // get audio node, and inform it of the change
            GenericEditor* editor = (GenericEditor*)getParentComponent();

            Channel* ch = editor->getChannel(b->getChannel() - 1);
            //int channelNum = editor->getStartChannel() + b->getChannel() - 1;
            bool status = b->getToggleState();

            std::cout << "Requesting audio monitor for channel " << ch->nodeIndex + 1 << std::endl;

            if (acquisitionIsActive) // use setParameter to change parameter safely
            {
                AccessClass::getProcessorGraph()->
                getAudioNode()->setChannelStatus(ch, status);
            }
            else     // change parameter directly
            {
                ch->isMonitored = status;
            }
        }
        else if (b->getType() == RECORD)
        {
            // get record node, and inform it of the change
            GenericEditor* editor = (GenericEditor*)getParentComponent();

            Channel* ch = editor->getChannel(b->getChannel() - 1);
            //int channelNum = editor->getStartChannel() + b->getChannel() - 1;
            bool status = b->getToggleState();

            if (acquisitionIsActive) // use setParameter to change parameter safely
            {
                AccessClass::getProcessorGraph()->
                getRecordNode()->
                setChannelStatus(ch, status);
            }
            else     // change parameter directly
            {
                //std::cout << "Setting record status for channel " << b->getChannel() << std::endl;
                ch->setRecordState(status);
            }

            AccessClass::getGraphViewer()->repaint();

        }
        else // parameter type
        {
            GenericEditor* editor = (GenericEditor*) getParentComponent();
            editor->channelChanged (b->getChannel() - 1, b->getToggleState());

            // do nothing
            if (radioStatus) // if radio buttons are active
            {
                // send a message to parent
                GenericEditor* editor = (GenericEditor*) getParentComponent();
                editor->channelChanged (b->getChannel(), b->getToggleState());
            }
        }

    }
    refreshParameterColors();
}
void ChannelSelector::refreshParameterColors()
{
    GenericEditor* p = dynamic_cast<GenericEditor*>(getParentComponent());
    p->updateParameterButtons(-1);
}
Beispiel #9
0
void ProcessorGraph::updateConnections(Array<SignalChainTabButton*, CriticalSection> tabs)
{
    clearConnections(); // clear processor graph

    std::cout << "Updating connections:" << std::endl;
    std::cout << std::endl;
    std::cout << std::endl;

    Array<GenericProcessor*> splitters;
    // GenericProcessor* activeSplitter = nullptr;

    for (int n = 0; n < tabs.size(); n++) // cycle through the tabs
    {
        std::cout << "Signal chain: " << n << std::endl;
        std::cout << std::endl;

        GenericEditor* sourceEditor = (GenericEditor*) tabs[n]->getEditor();
        GenericProcessor* source = (GenericProcessor*) sourceEditor->getProcessor();

        while (source != nullptr)// && destEditor->isEnabled())
        {
            std::cout << "Source node: " << source->getName() << "." << std::endl;
            GenericProcessor* dest = (GenericProcessor*) source->getDestNode();

            if (source->enabledState())
            {
                // add the connections to audio and record nodes if necessary
                if (!(source->isSink()     ||
                      source->isSplitter() ||
                      source->isMerger()   ||
                      source->isUtility())
                    && !(source->wasConnected))
                {
                    std::cout << "     Connecting to audio and record nodes." << std::endl;
                    connectProcessorToAudioAndRecordNodes(source);
                }
                else
                {
                    std::cout << "     NOT connecting to audio and record nodes." << std::endl;
                }

                if (dest != nullptr)
                {

                    while (dest->isMerger()) // find the next dest that's not a merger
                    {
                        dest = dest->getDestNode();

                        if (dest == nullptr)
                            break;
                    }

                    if (dest != nullptr)
                    {
                        while (dest->isSplitter())
                        {
                            if (!dest->wasConnected)
                            {
                                if (!splitters.contains(dest))
                                {
                                    splitters.add(dest);
                                    dest->switchIO(0); // go down first path
                                }
                                else
                                {
                                    int splitterIndex = splitters.indexOf(dest);
                                    splitters.remove(splitterIndex);
                                    dest->switchIO(1); // go down second path
                                    dest->wasConnected = true; // make sure we don't re-use this splitter
                                }
                            }

                            dest = dest->getDestNode();

                            if (dest == nullptr)
                                break;
                        }

                        if (dest != nullptr)
                        {

                            if (dest->enabledState())
                            {
                                connectProcessors(source, dest);
                            }
                        }

                    }
                    else
                    {
                        std::cout << "     No dest node." << std::endl;
                    }

                }
                else
                {
                    std::cout << "     No dest node." << std::endl;
                }
            }

            std::cout << std::endl;

            source->wasConnected = true;
            source = dest; // switch source and dest

            if (source == nullptr && splitters.size() > 0)
            {

                source = splitters.getLast();
                GenericProcessor* newSource;// = source->getSourceNode();

                while (source->isSplitter() || source->isMerger())
                {
                    newSource = source->getSourceNode();
                    newSource->setPathToProcessor(source);
                    source = newSource;
                }

            }

        } // end while source != 0
    } // end "tabs" for loop

} // end method