From 671b944ca26662be98716b3d7f883d399cbe8d5d Mon Sep 17 00:00:00 2001 From: jsiegle <jsiegle@mit.edu> Date: Wed, 22 Jan 2014 20:30:05 -0500 Subject: [PATCH] Update ProcessorGraph from spikesorting branch --- Source/Processors/ProcessorGraph.cpp | 320 ++++++++++++++++----------- Source/Processors/ProcessorGraph.h | 7 +- 2 files changed, 189 insertions(+), 138 deletions(-) diff --git a/Source/Processors/ProcessorGraph.cpp b/Source/Processors/ProcessorGraph.cpp index bcd2a84a1..c89094074 100644 --- a/Source/Processors/ProcessorGraph.cpp +++ b/Source/Processors/ProcessorGraph.cpp @@ -27,7 +27,6 @@ #include "AudioNode.h" #include "LfpDisplayNode.h" -#include "LfpTriggeredAverageNode.h" #include "SpikeDisplayNode.h" #include "EventNode.h" #include "FilterNode.h" @@ -68,8 +67,10 @@ ProcessorGraph::ProcessorGraph() : currentNodeId(100) } -ProcessorGraph::~ProcessorGraph() { } - +ProcessorGraph::~ProcessorGraph() +{ + +} void ProcessorGraph::createDefaultNodes() { @@ -123,12 +124,13 @@ void ProcessorGraph::updatePointers() getRecordNode()->setUIComponent(getUIComponent()); } -void* ProcessorGraph::createNewProcessor(String& description, int id) +void* ProcessorGraph::createNewProcessor(String& description, int id)//, + { GenericProcessor* processor = createProcessorFromDescription(description); - //int id = currentNodeId++; + // int id = currentNodeId++; if (processor != 0) { @@ -156,33 +158,18 @@ void* ProcessorGraph::createNewProcessor(String& description, int id) void ProcessorGraph::clearSignalChain() { - int n = 0; + Array<GenericProcessor*> processors = getListOfProcessors(); - while (getNumNodes() > 4) + for (int i = 0; i < processors.size(); i++) { - Node* node = getNode(n); - 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(); - removeProcessor(p); - } - else - { - n++; - } + removeProcessor(processors[i]); } } void ProcessorGraph::changeListenerCallback(ChangeBroadcaster* source) { - - refreshColors(); + refreshColors(); } @@ -290,162 +277,201 @@ void ProcessorGraph::updateConnections(Array<SignalChainTabButton*, CriticalSect 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++) + for (int n = 0; n < tabs.size(); n++) // cycle through the tabs { - std::cout << "Signal chain " << n << std::endl; + std::cout << "Signal chain: " << n << std::endl; + std::cout << std::endl; GenericEditor* sourceEditor = (GenericEditor*) tabs[n]->getEditor(); GenericProcessor* source = (GenericProcessor*) sourceEditor->getProcessor(); - while (source != 0)// && destEditor->isEnabled()) + while (source != nullptr)// && destEditor->isEnabled()) { - std::cout << "Source node: " << source->getName() << ", "; + std::cout << "Source node: " << source->getName() << "." << std::endl; GenericProcessor* dest = (GenericProcessor*) source->getDestNode(); - if (dest != 0) + if (source->enabledState()) { - std::cout << "Dest node: " << dest->getName() << std::endl; - if (dest->isMerger()) // move it forward by one - { - dest = dest->getDestNode(); - } - else if (dest->isSplitter()) + // add the connections to audio and record nodes if necessary + if (!(source->isSink() || + source->isSplitter() || + source->isMerger() || + source->isUtility()) + && !(source->wasConnected)) { - if (!dest->wasConnected) - splitters.add(dest); - - dest = dest->getDestNode(); + std::cout << " Connecting to audio and record nodes." << std::endl; + connectProcessorToAudioAndRecordNodes(source); + } else { + std::cout << " NOT connecting to audio and record nodes." << std::endl; } - } - 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)) + if (dest != nullptr) { - std::cout << " Connecting to audio and record nodes." << std::endl; - //source->setStartChannel(getAudioNode()->getNextChannel(false)); + while (dest->isMerger()) // find the next dest that's not a merger + { + dest = dest->getDestNode(); + if (dest == nullptr) + break; + } - for (int chan = 0; chan < source->getNumOutputs(); chan++) + 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; + } - getAudioNode()->addInputChannel(source, chan); - getAudioNode()->settings.sampleRate = source->getSampleRate(); // THIS IS A HACK TO MAKE SURE AUDIO NODE KNOWS WHAT THE SAMPLE RATE SHOULD BE + if (dest != nullptr) + { - // std::cout << "Connecting to audio channel: " << - // getAudioNode()->getNextChannel(false) << std::endl; + if (dest->enabledState()) + { + connectProcessors(source, dest); + } + } - //getAudioNode()->enableCurrentChannel(source->audioStatus(chan)); + } else { + std::cout << " No dest node." << std::endl; + } - addConnection(source->getNodeId(), // sourceNodeID - chan, // sourceNodeChannelIndex - AUDIO_NODE_ID, // destNodeID - getAudioNode()->getNextChannel(true)); // destNodeChannelIndex - // add 2 to account for 2 output channels + } else { + std::cout << " No dest node." << std::endl; + } + } + std::cout << std::endl; - //std::cout << getAudioNode()->getNextChannel(false) << " "; + source->wasConnected = true; + source = dest; // switch source and dest - getRecordNode()->addInputChannel(source, chan); + if (source == nullptr && splitters.size() > 0) + { - // std::cout << "Connecting to record channel: " << - // getRecordNode()->getNextChannel(false) << std::endl; + source = splitters.getLast(); + GenericProcessor* newSource;// = source->getSourceNode(); + while (source->isSplitter() || source->isMerger()) + { + newSource = source->getSourceNode(); + newSource->setPathToProcessor(source); + source = newSource; + } + - addConnection(source->getNodeId(), // sourceNodeID - chan, // sourceNodeChannelIndex - RECORD_NODE_ID, // destNodeID - getRecordNode()->getNextChannel(true)); // destNodeChannelIndex + // source = splitters.getFirst()->getSourceNode(); // dest is now the splitter + //splitters.remove(0); // take it out of the array + //dest->switchIO(1); // 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 - // connect event channel - addConnection(source->getNodeId(), // sourceNodeID - midiChannelIndex, // sourceNodeChannelIndex - RECORD_NODE_ID, // destNodeID - midiChannelIndex); // destNodeChannelIndex +} // end method - // connect event channel - addConnection(source->getNodeId(), // sourceNodeID - midiChannelIndex, // sourceNodeChannelIndex - AUDIO_NODE_ID, // destNodeID - midiChannelIndex); // destNodeChannelIndex +void ProcessorGraph::connectProcessors(GenericProcessor* source, GenericProcessor* dest) +{ + if (source == nullptr || dest == nullptr) + return; - getRecordNode()->addInputChannel(source, midiChannelIndex); + std::cout << " Connecting " << source->getName() << " " << source->getNodeId(); //" channel "; + std::cout << " to " << dest->getName() << " " << dest->getNodeId() << std::endl; - } + // 1. connect continuous channels + for (int chan = 0; chan < source->getNumOutputs(); chan++) + { + //std::cout << chan << " "; - std::cout << std::endl; + addConnection(source->getNodeId(), // sourceNodeID + chan, // sourceNodeChannelIndex + dest->getNodeId(), // destNodeID + dest->getNextChannel(true)); // destNodeChannelIndex + } - if (dest != 0) - { + // std::cout << " Connecting " << source->getName() << + // " event channel to " << + // dest->getName() << std::endl; - if (dest->enabledState()) - std::cout << " OK." << std::endl; - else - std::cout << " Not OK." << std::endl; + // 2. connect event channel + addConnection(source->getNodeId(), // sourceNodeID + midiChannelIndex, // sourceNodeChannelIndex + dest->getNodeId(), // destNodeID + midiChannelIndex); // destNodeChannelIndex - if (dest->enabledState()) - { +} - std::cout << " Connecting " << source->getName() << " channel "; +void ProcessorGraph::connectProcessorToAudioAndRecordNodes(GenericProcessor* source) +{ - for (int chan = 0; chan < source->getNumOutputs(); chan++) - { - std::cout << chan << " "; + if (source == nullptr) + return; - addConnection(source->getNodeId(), // sourceNodeID - chan, // sourceNodeChannelIndex - dest->getNodeId(), // destNodeID - dest->getNextChannel(true)); // destNodeChannelIndex - } + for (int chan = 0; chan < source->getNumOutputs(); chan++) + { - std::cout << " to " << dest->getName() << std::endl; + getAudioNode()->addInputChannel(source, chan); - std::cout << " Connecting " << source->getName() << - " event channel to " << - dest->getName() << std::endl; + // THIS IS A HACK TO MAKE SURE AUDIO NODE KNOWS WHAT THE SAMPLE RATE SHOULD BE + // IT CAN CAUSE PROBLEMS IF THE SAMPLE RATE VARIES ACROSS PROCESSORS + getAudioNode()->settings.sampleRate = source->getSampleRate(); - // connect event channel - addConnection(source->getNodeId(), // sourceNodeID - midiChannelIndex, // sourceNodeChannelIndex - dest->getNodeId(), // destNodeID - midiChannelIndex); // destNodeChannelIndex + addConnection(source->getNodeId(), // sourceNodeID + chan, // sourceNodeChannelIndex + AUDIO_NODE_ID, // destNodeID + getAudioNode()->getNextChannel(true)); // destNodeChannelIndex - } + getRecordNode()->addInputChannel(source, chan); - } - } + addConnection(source->getNodeId(), // sourceNodeID + chan, // sourceNodeChannelIndex + RECORD_NODE_ID, // destNodeID + getRecordNode()->getNextChannel(true)); // 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 - } + // 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 - } // end while source != 0 - } // end "tabs" for loop -} // end method + getRecordNode()->addInputChannel(source, midiChannelIndex); + +} GenericProcessor* ProcessorGraph::createProcessorFromDescription(String& description) { @@ -491,7 +517,12 @@ GenericProcessor* ProcessorGraph::createProcessorFromDescription(String& descrip { processor = new FileReader(); std::cout << "Creating a new file reader." << std::endl; - } + } + else if (subProcessorType.equalsIgnoreCase("Network Events")) + { + std::cout << "Creating a new network events source." << std::endl; + processor = new NetworkEvents(zmqcontext); + } else if (subProcessorType.equalsIgnoreCase("Serial Port")) { processor = new SerialInput(); @@ -499,6 +530,7 @@ GenericProcessor* ProcessorGraph::createProcessorFromDescription(String& descrip } + sendActionMessage("New source node created."); @@ -543,8 +575,13 @@ GenericProcessor* ProcessorGraph::createProcessorFromDescription(String& descrip { std::cout << "Creating a new channel mapping node." << std::endl; processor = new ChannelMappingNode(); + } else if (subProcessorType.equalsIgnoreCase("Eye Tracking")) + { + std::cout << "Creating a ISCAN source." << std::endl; + processor = new ISCANnode(); } + sendActionMessage("New filter node created."); } @@ -577,6 +614,10 @@ GenericProcessor* ProcessorGraph::createProcessorFromDescription(String& descrip sendActionMessage("New record controller created."); + }else if (subProcessorType.equalsIgnoreCase("Advancers")) + { + std::cout << "Creating a new advancers node." << std::endl; + processor = new AdvancerNode(); } } @@ -592,16 +633,25 @@ GenericProcessor* ProcessorGraph::createProcessorFromDescription(String& descrip // processor->setDataViewport(getDataViewport()); //processor->setUIComponent(UI); } - else if (subProcessorType.equalsIgnoreCase("LFP Trig. Avg.")) - { - std::cout << "Creating an LfpTrigAvgNode." << std::endl; - processor = new LfpTriggeredAverageNode(); - } + // else if (subProcessorType.equalsIgnoreCase("LFP Trig. Avg.")) + // { + // std::cout << "Creating an LfpTrigAvgNode." << std::endl; + // processor = new LfpTriggeredAverageNode(); + // } else if (subProcessorType.equalsIgnoreCase("Spike Viewer")) { std::cout << "Creating a SpikeDisplayNode." << std::endl; processor = new SpikeDisplayNode(); + } + else if (subProcessorType.equalsIgnoreCase("PSTH")) + { + std::cout << "Creating a PSTH sink." << std::endl; + processor = new PeriStimulusTimeHistogramNode(); + } else if (subProcessorType.equalsIgnoreCase("Network Sink")) + { + std::cout << "Creating a Network sink." << std::endl; + processor = new NetworkSinkNode(zmqcontext); } else if (subProcessorType.equalsIgnoreCase("WiFi Output")) { @@ -789,4 +839,4 @@ RecordNode* ProcessorGraph::getRecordNode() Node* node = getNodeForId(RECORD_NODE_ID); return (RecordNode*) node->getProcessor(); -} \ No newline at end of file +} diff --git a/Source/Processors/ProcessorGraph.h b/Source/Processors/ProcessorGraph.h index 3ea84eb4d..e8a4b04d4 100644 --- a/Source/Processors/ProcessorGraph.h +++ b/Source/Processors/ProcessorGraph.h @@ -61,7 +61,7 @@ public: GenericProcessor* createProcessorFromDescription(String& description); void removeProcessor(GenericProcessor* processor); - + Array<GenericProcessor*> getListOfProcessors(); void clearSignalChain(); bool enableProcessors(); @@ -83,8 +83,6 @@ public: void setRecordState(bool); - Array<GenericProcessor*> getListOfProcessors(); - void refreshColors(); private: @@ -103,6 +101,9 @@ private: void clearConnections(); + void connectProcessors(GenericProcessor* source, GenericProcessor* dest); + void connectProcessorToAudioAndRecordNodes(GenericProcessor* source); + }; -- GitLab