From 9b030103c9eaa98670d4989d2ad2b3faa5816d51 Mon Sep 17 00:00:00 2001
From: jsiegle <jsiegle@mit.edu>
Date: Thu, 1 Mar 2012 23:52:33 -0500
Subject: [PATCH] Created simple Splitter and Merger utilities

But they won't do anything useful until the ProcessorGraph is updated
---
 Builds/Linux/Makefile                         | 12 +++++
 .../open-ephys.xcodeproj/project.pbxproj      | 12 +++++
 Source/Processors/Editors/GenericEditor.cpp   |  2 +-
 Source/Processors/Editors/SplitterEditor.cpp  |  4 +-
 Source/Processors/Editors/SplitterEditor.h    |  2 -
 Source/Processors/GenericProcessor.cpp        | 49 +++++++++++--------
 Source/Processors/GenericProcessor.h          |  4 +-
 Source/Processors/ProcessorGraph.cpp          |  8 +++
 Source/Processors/Utilities/Splitter.cpp      | 26 +++++-----
 Source/Processors/Utilities/Splitter.h        |  7 ++-
 Source/UI/ProcessorList.cpp                   |  8 +--
 open-ephys.jucer                              |  5 ++
 12 files changed, 96 insertions(+), 43 deletions(-)

diff --git a/Builds/Linux/Makefile b/Builds/Linux/Makefile
index 1d08a5c08..03ddd617d 100644
--- a/Builds/Linux/Makefile
+++ b/Builds/Linux/Makefile
@@ -65,6 +65,7 @@ OBJECTS := \
   $(OBJDIR)/AudioComponent_521bd9c9.o \
   $(OBJDIR)/WiFiOutput_fa464ec5.o \
   $(OBJDIR)/LfpDisplayNode_30ef22fd.o \
+  $(OBJDIR)/Merger_2f90542e.o \
   $(OBJDIR)/Splitter_6e27a57b.o \
   $(OBJDIR)/DataWindow_83ce6754.o \
   $(OBJDIR)/LfpDisplayCanvas_4a58e87e.o \
@@ -73,6 +74,7 @@ OBJECTS := \
   $(OBJDIR)/FileReader_18023b0e.o \
   $(OBJDIR)/AudioNode_94606ff3.o \
   $(OBJDIR)/EventNode_95c842b7.o \
+  $(OBJDIR)/MergerEditor_d1fcc0df.o \
   $(OBJDIR)/ImageIcon_c89b23a6.o \
   $(OBJDIR)/WiFiOutputEditor_1d3ba5bb.o \
   $(OBJDIR)/EventNodeEditor_2198733b.o \
@@ -242,6 +244,11 @@ $(OBJDIR)/LfpDisplayNode_30ef22fd.o: ../../Source/Processors/LfpDisplayNode.cpp
 	@echo "Compiling LfpDisplayNode.cpp"
 	@$(CXX) $(CXXFLAGS) -o "$@" -c "$<"
 
+$(OBJDIR)/Merger_2f90542e.o: ../../Source/Processors/Utilities/Merger.cpp
+	-@mkdir -p $(OBJDIR)
+	@echo "Compiling Merger.cpp"
+	@$(CXX) $(CXXFLAGS) -o "$@" -c "$<"
+
 $(OBJDIR)/Splitter_6e27a57b.o: ../../Source/Processors/Utilities/Splitter.cpp
 	-@mkdir -p $(OBJDIR)
 	@echo "Compiling Splitter.cpp"
@@ -282,6 +289,11 @@ $(OBJDIR)/EventNode_95c842b7.o: ../../Source/Processors/EventNode.cpp
 	@echo "Compiling EventNode.cpp"
 	@$(CXX) $(CXXFLAGS) -o "$@" -c "$<"
 
+$(OBJDIR)/MergerEditor_d1fcc0df.o: ../../Source/Processors/Editors/MergerEditor.cpp
+	-@mkdir -p $(OBJDIR)
+	@echo "Compiling MergerEditor.cpp"
+	@$(CXX) $(CXXFLAGS) -o "$@" -c "$<"
+
 $(OBJDIR)/ImageIcon_c89b23a6.o: ../../Source/Processors/Editors/ImageIcon.cpp
 	-@mkdir -p $(OBJDIR)
 	@echo "Compiling ImageIcon.cpp"
diff --git a/Builds/MacOSX/open-ephys.xcodeproj/project.pbxproj b/Builds/MacOSX/open-ephys.xcodeproj/project.pbxproj
index d8feb6816..2461499be 100644
--- a/Builds/MacOSX/open-ephys.xcodeproj/project.pbxproj
+++ b/Builds/MacOSX/open-ephys.xcodeproj/project.pbxproj
@@ -39,6 +39,7 @@
 		4ACF816CB5CDB285D8005AB8 = { isa = PBXBuildFile; fileRef = F74662D3D82975EDB5AD42E0; };
 		B992DDBFF8928A985EEE1557 = { isa = PBXBuildFile; fileRef = 268005410FB62BCB9099A762; };
 		F1268EC5E783EC8ECEBCA5D3 = { isa = PBXBuildFile; fileRef = 5935F823A2EE45AC36A0201F; };
+		4A00153E1E69A74BC6B7D8A6 = { isa = PBXBuildFile; fileRef = 3973173C7FA07073B4F86B29; };
 		5F13B8FFB1584BFF6C05AD39 = { isa = PBXBuildFile; fileRef = 9A47B52E5E1CD17DC9C72B53; };
 		9D687F73F2FD2462C5D5588C = { isa = PBXBuildFile; fileRef = ED179D5A10DD051DDB3ECB8B; };
 		B13883377C9316B9603336B4 = { isa = PBXBuildFile; fileRef = 2E96DA81EE37A0ECE471A928; };
@@ -47,6 +48,7 @@
 		6656467170D2822949BD2F7F = { isa = PBXBuildFile; fileRef = 5AC4DD48CCB1AB4936A2DE4A; };
 		08B501E0D7764C6B613AF529 = { isa = PBXBuildFile; fileRef = B7750B27E4F3748ECCCCF69D; };
 		9CBA3837CC8CAA03A03F2D9C = { isa = PBXBuildFile; fileRef = FA57CE4F63FF1592D6B3F9B5; };
+		93A3E6284F2DAED3F491332B = { isa = PBXBuildFile; fileRef = AD73EA6B24378294003DC2D0; };
 		CB77C89226102EF30F85E3EC = { isa = PBXBuildFile; fileRef = 544DA1EF90EBBDB6FF2DE0A5; };
 		A126280FF39A61DEFD3ABFE5 = { isa = PBXBuildFile; fileRef = 2B11714BCE362D4EA7E377F5; };
 		2ADE508EC26B703176ED915C = { isa = PBXBuildFile; fileRef = 36393F2D58480F61ECDEB5E5; };
@@ -176,6 +178,8 @@
 		32959675287F77DD9B7FA96B = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = WiFiOutput.h; path = ../../Source/Processors/WiFiOutput.h; sourceTree = SOURCE_ROOT; };
 		5935F823A2EE45AC36A0201F = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = LfpDisplayNode.cpp; path = ../../Source/Processors/LfpDisplayNode.cpp; sourceTree = SOURCE_ROOT; };
 		B00F207EBEED525FB686AD98 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = LfpDisplayNode.h; path = ../../Source/Processors/LfpDisplayNode.h; sourceTree = SOURCE_ROOT; };
+		3973173C7FA07073B4F86B29 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = Merger.cpp; path = ../../Source/Processors/Utilities/Merger.cpp; sourceTree = SOURCE_ROOT; };
+		7977CAB4A151C41F4140FE1A = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = Merger.h; path = ../../Source/Processors/Utilities/Merger.h; sourceTree = SOURCE_ROOT; };
 		9A47B52E5E1CD17DC9C72B53 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = Splitter.cpp; path = ../../Source/Processors/Utilities/Splitter.cpp; sourceTree = SOURCE_ROOT; };
 		B92E8189F69E0B926C73B654 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = Splitter.h; path = ../../Source/Processors/Utilities/Splitter.h; sourceTree = SOURCE_ROOT; };
 		ED179D5A10DD051DDB3ECB8B = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = DataWindow.cpp; path = ../../Source/Processors/Visualization/DataWindow.cpp; sourceTree = SOURCE_ROOT; };
@@ -192,6 +196,8 @@
 		12866D44BE115E8837468F48 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = AudioNode.h; path = ../../Source/Processors/AudioNode.h; sourceTree = SOURCE_ROOT; };
 		FA57CE4F63FF1592D6B3F9B5 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = EventNode.cpp; path = ../../Source/Processors/EventNode.cpp; sourceTree = SOURCE_ROOT; };
 		32163C956C8A6F5C1DD7FE7F = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = EventNode.h; path = ../../Source/Processors/EventNode.h; sourceTree = SOURCE_ROOT; };
+		AD73EA6B24378294003DC2D0 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = MergerEditor.cpp; path = ../../Source/Processors/Editors/MergerEditor.cpp; sourceTree = SOURCE_ROOT; };
+		B7FD86B9DA02771D3519FAA0 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = MergerEditor.h; path = ../../Source/Processors/Editors/MergerEditor.h; sourceTree = SOURCE_ROOT; };
 		544DA1EF90EBBDB6FF2DE0A5 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = ImageIcon.cpp; path = ../../Source/Processors/Editors/ImageIcon.cpp; sourceTree = SOURCE_ROOT; };
 		04AD8DDD47597AE0875ACDD1 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = ImageIcon.h; path = ../../Source/Processors/Editors/ImageIcon.h; sourceTree = SOURCE_ROOT; };
 		2B11714BCE362D4EA7E377F5 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = WiFiOutputEditor.cpp; path = ../../Source/Processors/Editors/WiFiOutputEditor.cpp; sourceTree = SOURCE_ROOT; };
@@ -355,6 +361,8 @@
 				F74662D3D82975EDB5AD42E0,
 				FA55B9FDE138CCB1F16BA905 ); name = Audio; sourceTree = "<group>"; };
 		20FFF487B65BF8567EFE70F8 = { isa = PBXGroup; children = (
+				3973173C7FA07073B4F86B29,
+				7977CAB4A151C41F4140FE1A,
 				9A47B52E5E1CD17DC9C72B53,
 				B92E8189F69E0B926C73B654 ); name = Utilities; sourceTree = "<group>"; };
 		15543D7982B26B70879960F4 = { isa = PBXGroup; children = (
@@ -365,6 +373,8 @@
 				0C5335B0E57C9DC92FC57E5F,
 				7738F51AE0EC63D76EE0F761 ); name = Visualization; sourceTree = "<group>"; };
 		953CC35B9116404D6AA8D1C7 = { isa = PBXGroup; children = (
+				AD73EA6B24378294003DC2D0,
+				B7FD86B9DA02771D3519FAA0,
 				544DA1EF90EBBDB6FF2DE0A5,
 				04AD8DDD47597AE0875ACDD1,
 				2B11714BCE362D4EA7E377F5,
@@ -591,6 +601,7 @@
 				4ACF816CB5CDB285D8005AB8,
 				B992DDBFF8928A985EEE1557,
 				F1268EC5E783EC8ECEBCA5D3,
+				4A00153E1E69A74BC6B7D8A6,
 				5F13B8FFB1584BFF6C05AD39,
 				9D687F73F2FD2462C5D5588C,
 				B13883377C9316B9603336B4,
@@ -599,6 +610,7 @@
 				6656467170D2822949BD2F7F,
 				08B501E0D7764C6B613AF529,
 				9CBA3837CC8CAA03A03F2D9C,
+				93A3E6284F2DAED3F491332B,
 				CB77C89226102EF30F85E3EC,
 				A126280FF39A61DEFD3ABFE5,
 				2ADE508EC26B703176ED915C,
diff --git a/Source/Processors/Editors/GenericEditor.cpp b/Source/Processors/Editors/GenericEditor.cpp
index 28cd4a610..32ddcb11e 100644
--- a/Source/Processors/Editors/GenericEditor.cpp
+++ b/Source/Processors/Editors/GenericEditor.cpp
@@ -52,7 +52,7 @@ GenericEditor::GenericEditor (GenericProcessor* owner)//, FilterViewport* vp)
 	else if (owner->isSink())
 		backgroundColor = Colour(255, 149, 0);//Colour(int(0.06*255.0f),int(0.46*255.0f),int(0.9*255.0f));
 	else if (owner->isSplitter() || owner->isMerger())
-		backgroundColor = Colour(80, 80, 80);//Colour(int(0.7*255.0f),int(0.7*255.0f),int(0.7*255.0f));
+		backgroundColor = Colour(40, 40, 40);//Colour(int(0.7*255.0f),int(0.7*255.0f),int(0.7*255.0f));
 	else
 		backgroundColor = Colour(255, 89, 0);//Colour(int(1.0*255.0f),int(0.5*255.0f),int(0.0*255.0f));
 
diff --git a/Source/Processors/Editors/SplitterEditor.cpp b/Source/Processors/Editors/SplitterEditor.cpp
index 2745f4943..f8bef4c4b 100644
--- a/Source/Processors/Editors/SplitterEditor.cpp
+++ b/Source/Processors/Editors/SplitterEditor.cpp
@@ -73,7 +73,7 @@ SplitterEditor::SplitterEditor (GenericProcessor* parentNode)
 	pipelineSelectorA->addListener(this);
 	pipelineSelectorA->setBounds(-10,15,95,50);
 	pipelineSelectorA->setToggleState(true,false);
-	addAndMakeVisible(pipelineSelectorA);
+	//addAndMakeVisible(pipelineSelectorA);
 
 	pipelineSelectorB = new ImageButton("Pipeline B");
 
@@ -85,7 +85,7 @@ SplitterEditor::SplitterEditor (GenericProcessor* parentNode)
 	pipelineSelectorB->addListener(this);
 	pipelineSelectorB->setBounds(-10,65,95,50);
 	pipelineSelectorB->setToggleState(false,false);
-	addAndMakeVisible(pipelineSelectorB);
+	//addAndMakeVisible(pipelineSelectorB);
 
 }
 
diff --git a/Source/Processors/Editors/SplitterEditor.h b/Source/Processors/Editors/SplitterEditor.h
index e355168bd..03fb49c6a 100644
--- a/Source/Processors/Editors/SplitterEditor.h
+++ b/Source/Processors/Editors/SplitterEditor.h
@@ -28,8 +28,6 @@
 #include "../../../JuceLibraryCode/JuceHeader.h"
 #include "GenericEditor.h"
 
-class FilterViewport;
-
 // class PipelineSelectorButton : public DrawableButton
 // {
 // 	public:
diff --git a/Source/Processors/GenericProcessor.cpp b/Source/Processors/GenericProcessor.cpp
index a138d1acc..a5b37a046 100644
--- a/Source/Processors/GenericProcessor.cpp
+++ b/Source/Processors/GenericProcessor.cpp
@@ -144,42 +144,47 @@ int GenericProcessor::getNumSamples(MidiBuffer& midiMessages) {
 
 void GenericProcessor::setSourceNode(GenericProcessor* sn)
 {
-	std::cout << "My name is " << getName() << ". Setting source node." << std::endl;
+	//std::cout << "My name is " << getName() << ". Setting source node." << std::endl;
 
 	if (!isSource())
 	{
-		std::cout << " I am not a source." << std::endl;
+	//	std::cout << " I am not a source." << std::endl;
 
 		if (sn != 0)
 		{
 
-			std::cout << " The source is not blank." << std::endl;
+		//	std::cout << " The source is not blank." << std::endl;
 
 			if (!sn->isSink())
 			{
-				std::cout << " The source is not a sink." << std::endl;
+		//		std::cout << " The source is not a sink." << std::endl;
 
 				if (sourceNode != sn) {
 
-					std::cout << " The source is new and named " << sn->getName() << std::endl;
-					sourceNode = sn;
+		//			std::cout << " The source is new and named " << sn->getName() << std::endl;
+					
+					//if (this->isMerger())
+				//		setMergerSourceNode(sn);
+				//	else
+						sourceNode = sn;
+
 					sn->setDestNode(this);
 					//setNumInputs(sn->getNumOutputs());
 					//setSampleRate(sn->getSampleRate());
 				} else {
-					std::cout << "  The source node is not new." << std::endl;
+		//			std::cout << "  The source node is not new." << std::endl;
 				}
 			} else {
-				std::cout << " The source is a sink." << std::endl;
+		//		std::cout << " The source is a sink." << std::endl;
 				sourceNode = 0;
 			}
 
 		} else {
-			std::cout << " The source is blank." << std::endl;
+	//		std::cout << " The source is blank." << std::endl;
 			sourceNode = 0;
 		}
 	} else {
-		std::cout << " I am a source. I can't have a source node." << std::endl;
+	//	std::cout << " I am a source. I can't have a source node." << std::endl;
 
 		if (sn != 0)
 			sn->setDestNode(this);
@@ -191,46 +196,50 @@ void GenericProcessor::setDestNode(GenericProcessor* dn)
 {
 
 
-	std::cout << "My name is " << getName() << ". Setting dest node." << std::endl;
+//	std::cout << "My name is " << getName() << ". Setting dest node." << std::endl;
 
 	if (!isSink())
 	{
-		std::cout << "  I am not a sink." << std::endl;
+	//	std::cout << "  I am not a sink." << std::endl;
 
 		if (dn != 0)
 		{
-			std::cout << "  The dest node is not blank." << std::endl;
+	//		std::cout << "  The dest node is not blank." << std::endl;
 
 			if (!dn->isSource())
 			{
 
-				std::cout << "  The dest node is not a source." << std::endl;
+		//		std::cout << "  The dest node is not a source." << std::endl;
 
 				if (destNode != dn) 
 				{
-					std::cout << "  The dest node is new and named " << dn->getName() << std::endl;
+			//		std::cout << "  The dest node is new and named " << dn->getName() << std::endl;
+//
+				//	if (this->isSplitter())
+				//		setSplitterDestNode(dn);
+				//	else
+						destNode = dn;
 
-					destNode = dn;
 					dn->setSourceNode(this);
 					//dn->setNumInputs(getNumOutputs());
 					//dn->setSampleRate(getSampleRate());
 				} else {
-					std::cout << "  The dest node is not new." << std::endl;
+			//		std::cout << "  The dest node is not new." << std::endl;
 				}
 			} else {
 
-				std::cout << "  The dest node is a source." << std::endl;
+			//	std::cout << "  The dest node is a source." << std::endl;
 
 				destNode = 0;
 			}
 		} else {
-			std::cout << "  The dest node is blank." << std::endl;
+		//	std::cout << "  The dest node is blank." << std::endl;
 
 			destNode = 0;
 		}
 	} else {
 
-		std::cout << "  I am a sink, I can't have a dest node." << std::endl;
+		//std::cout << "  I am a sink, I can't have a dest node." << std::endl;
 		//if (dn != 0)
 		//	dn->setSourceNode(this);
 	}
diff --git a/Source/Processors/GenericProcessor.h b/Source/Processors/GenericProcessor.h
index cfc7cc352..348433b1a 100644
--- a/Source/Processors/GenericProcessor.h
+++ b/Source/Processors/GenericProcessor.h
@@ -68,7 +68,7 @@ public:
 	virtual void prepareToPlay (double sampleRate, int estimatedSamplesPerBlock);
 	void releaseResources();
 	
-	void setParameter (int parameterIndex, float newValue);
+	virtual void setParameter (int parameterIndex, float newValue);
 
 	virtual AudioProcessorEditor* createEditor();
 	bool hasEditor() const {return true;}
@@ -155,6 +155,8 @@ public:
 
 	virtual void setSourceNode(GenericProcessor* sn);
 	virtual void setDestNode(GenericProcessor* dn);
+	virtual void setMergerSourceNode(GenericProcessor* sn) { }
+	virtual void setSplitterDestNode(GenericProcessor* dn) { }
 
 	virtual bool isSource() {return false;}
 	virtual bool isSink() {return false;}
diff --git a/Source/Processors/ProcessorGraph.cpp b/Source/Processors/ProcessorGraph.cpp
index b9763704c..6cd2c98e8 100644
--- a/Source/Processors/ProcessorGraph.cpp
+++ b/Source/Processors/ProcessorGraph.cpp
@@ -38,6 +38,7 @@
 #include "SpikeDetector.h"
 #include "WiFiOutput.h"
 #include "Utilities/Splitter.h"
+#include "Utilities/Merger.h"
 #include "../UI/UIComponent.h"
 #include "../UI/Configuration.h"
 #include "../UI/EditorViewport.h"
@@ -323,6 +324,13 @@ GenericProcessor* ProcessorGraph::createProcessorFromDescription(String& descrip
 
 			sendActionMessage("New splitter created.");
 
+	 	} else if (subProcessorType.equalsIgnoreCase("Merger")) {
+	 		
+	 		std::cout << "Creating a new merger." << std::endl;
+			processor = new Merger();
+
+			sendActionMessage("New merger created.");
+
 	 	}
 
 	} else if (processorType.equalsIgnoreCase("Sinks")) {
diff --git a/Source/Processors/Utilities/Splitter.cpp b/Source/Processors/Utilities/Splitter.cpp
index 1109b059a..9010ab037 100644
--- a/Source/Processors/Utilities/Splitter.cpp
+++ b/Source/Processors/Utilities/Splitter.cpp
@@ -27,25 +27,29 @@
 Splitter::Splitter()
 	: GenericProcessor("Splitter"), 
 		destNodeA(0), destNodeB(0), activePath(0)
-	{
-		
-	}
+{
+
+	setNumOutputs(0);
+	setNumInputs(0);
+
+	setPlayConfigDetails(getNumInputs(), getNumOutputs(), 44100.0, 128);
+}
 
 Splitter::~Splitter()
 {
 	
 }
 
-AudioProcessorEditor* Splitter::createEditor()
-{
-	SplitterEditor* editor = new SplitterEditor(this);
-	setEditor(editor);
+// AudioProcessorEditor* Splitter::createEditor()
+// {
+// 	SplitterEditor* editor = new SplitterEditor(this);
+// 	setEditor(editor);
 	
-	std::cout << "Creating editor." << std::endl;
-	return editor;
-}
+// 	std::cout << "Creating editor." << std::endl;
+// 	return editor;
+// }
 
-void Splitter::setDestNode(GenericProcessor* dn)
+void Splitter::setSplitterDestNode(GenericProcessor* dn)
 {
 
 	destNode = dn;
diff --git a/Source/Processors/Utilities/Splitter.h b/Source/Processors/Utilities/Splitter.h
index b2ea691a3..644fff589 100644
--- a/Source/Processors/Utilities/Splitter.h
+++ b/Source/Processors/Utilities/Splitter.h
@@ -48,20 +48,23 @@ public:
 	Splitter();
 	~Splitter();
 
-	AudioProcessorEditor* createEditor();
+	//AudioProcessorEditor* createEditor();
 
 	void process(AudioSampleBuffer &buffer, MidiBuffer &midiMessages, int& nSamples) {}
+   // void setParameter (int parameterIndex, float newValue) {}
 
 	bool isSplitter() {return true;}
 
 	void switchDest(int);
-	void setDestNode(GenericProcessor* dn);
+	void setSplitterDestNode(GenericProcessor* dn);
 
 private:
 
 	GenericProcessor* destNodeA;
 	GenericProcessor* destNodeB;
 	int activePath;
+
+    JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (Splitter);
 	
 };
 
diff --git a/Source/UI/ProcessorList.cpp b/Source/UI/ProcessorList.cpp
index b4d87c648..6c2af6c89 100644
--- a/Source/UI/ProcessorList.cpp
+++ b/Source/UI/ProcessorList.cpp
@@ -53,15 +53,15 @@ ProcessorList::ProcessorList() : isDragging(false),
 	//sinks->addSubItem(new ProcessorListItem("Spike Display"));
 	sinks->addSubItem(new ProcessorListItem("WiFi Output"));
 
-	//ProcessorListItem* utilities = new ProcessorListItem("Utilities");
-	//utilities->addSubItem(new ProcessorListItem("Splitter"));
-	//utilities->addSubItem(new ProcessorListItem("Merger"));
+	ProcessorListItem* utilities = new ProcessorListItem("Utilities");
+	utilities->addSubItem(new ProcessorListItem("Splitter"));
+	utilities->addSubItem(new ProcessorListItem("Merger"));
 
 	baseItem = new ProcessorListItem("Processors");
 	baseItem->addSubItem(sources);
 	baseItem->addSubItem(filters);
 	baseItem->addSubItem(sinks);
-	//baseItem->addSubItem(utilities);
+	baseItem->addSubItem(utilities);
 
 	// set parent names / colors
 	baseItem->setParentName("Processors");
diff --git a/open-ephys.jucer b/open-ephys.jucer
index b3b52073b..952ef758b 100644
--- a/open-ephys.jucer
+++ b/open-ephys.jucer
@@ -137,6 +137,8 @@
         <FILE id="VynGpEg" name="LfpDisplayNode.h" compile="0" resource="0"
               file="Source/Processors/LfpDisplayNode.h"/>
         <GROUP id="Enz7QFy" name="Utilities">
+          <FILE id="qt6uLka" name="Merger.cpp" compile="1" resource="0" file="Source/Processors/Utilities/Merger.cpp"/>
+          <FILE id="XNRlWg8" name="Merger.h" compile="0" resource="0" file="Source/Processors/Utilities/Merger.h"/>
           <FILE id="YMFH4P2" name="Splitter.cpp" compile="1" resource="0" file="Source/Processors/Utilities/Splitter.cpp"/>
           <FILE id="DXYynnz" name="Splitter.h" compile="0" resource="0" file="Source/Processors/Utilities/Splitter.h"/>
         </GROUP>
@@ -162,6 +164,9 @@
         <FILE id="hGnGAjh" name="EventNode.cpp" compile="1" resource="0" file="Source/Processors/EventNode.cpp"/>
         <FILE id="dUtRN6" name="EventNode.h" compile="0" resource="0" file="Source/Processors/EventNode.h"/>
         <GROUP id="AqvwO6w" name="Editors">
+          <FILE id="bsIZbuu" name="MergerEditor.cpp" compile="1" resource="0"
+                file="Source/Processors/Editors/MergerEditor.cpp"/>
+          <FILE id="vfmEY5L" name="MergerEditor.h" compile="0" resource="0" file="Source/Processors/Editors/MergerEditor.h"/>
           <FILE id="i2MR4pC" name="ImageIcon.cpp" compile="1" resource="0" file="Source/Processors/Editors/ImageIcon.cpp"/>
           <FILE id="N8r8D18" name="ImageIcon.h" compile="0" resource="0" file="Source/Processors/Editors/ImageIcon.h"/>
           <FILE id="mLd64ww" name="WiFiOutputEditor.cpp" compile="1" resource="0"
-- 
GitLab