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