diff --git a/Builds/Linux/Makefile b/Builds/Linux/Makefile
index fed02a124cf915eb93054787d945aae751d76c86..3d4b14cdfbec4e3b1a6ce2403585f578992bcfe3 100644
--- a/Builds/Linux/Makefile
+++ b/Builds/Linux/Makefile
@@ -63,16 +63,29 @@ OBJECTS := \
   $(OBJDIR)/RootFinder_239a995f.o \
   $(OBJDIR)/State_22979684.o \
   $(OBJDIR)/AudioComponent_521bd9c9.o \
+  $(OBJDIR)/SpikeDisplayNode_9c52e4ad.o \
   $(OBJDIR)/WiFiOutput_fa464ec5.o \
   $(OBJDIR)/LfpDisplayNode_30ef22fd.o \
   $(OBJDIR)/Merger_2f90542e.o \
   $(OBJDIR)/Splitter_6e27a57b.o \
+  $(OBJDIR)/StereotrodePlot_4710b8f1.o \
+  $(OBJDIR)/ElectrodePlot_7a206ec4.o \
+  $(OBJDIR)/BaseUIElement_ec903c4d.o \
+  $(OBJDIR)/GenericAxes_d802ed92.o \
+  $(OBJDIR)/PlotUtils_9ef52686.o \
+  $(OBJDIR)/ProjectionAxes_7c67c3e8.o \
+  $(OBJDIR)/TetrodePlot_b42fd798.o \
+  $(OBJDIR)/TitleBox_c4a9cde7.o \
+  $(OBJDIR)/WaveAxes_8adc45d2.o \
+  $(OBJDIR)/SpikeObject_24e8c655.o \
+  $(OBJDIR)/SpikeDisplayCanvas_b208ff6e.o \
   $(OBJDIR)/DataWindow_83ce6754.o \
   $(OBJDIR)/LfpDisplayCanvas_4a58e87e.o \
   $(OBJDIR)/OpenGLCanvas_3c775a41.o \
   $(OBJDIR)/SpikeDetector_300d85e7.o \
   $(OBJDIR)/AudioNode_94606ff3.o \
   $(OBJDIR)/EventNode_95c842b7.o \
+  $(OBJDIR)/SpikeDisplayEditor_e1812c1.o \
   $(OBJDIR)/VisualizerEditor_3672b003.o \
   $(OBJDIR)/MergerEditor_d1fcc0df.o \
   $(OBJDIR)/ImageIcon_c89b23a6.o \
@@ -234,6 +247,11 @@ $(OBJDIR)/AudioComponent_521bd9c9.o: ../../Source/Audio/AudioComponent.cpp
 	@echo "Compiling AudioComponent.cpp"
 	@$(CXX) $(CXXFLAGS) -o "$@" -c "$<"
 
+$(OBJDIR)/SpikeDisplayNode_9c52e4ad.o: ../../Source/Processors/SpikeDisplayNode.cpp
+	-@mkdir -p $(OBJDIR)
+	@echo "Compiling SpikeDisplayNode.cpp"
+	@$(CXX) $(CXXFLAGS) -o "$@" -c "$<"
+
 $(OBJDIR)/WiFiOutput_fa464ec5.o: ../../Source/Processors/WiFiOutput.cpp
 	-@mkdir -p $(OBJDIR)
 	@echo "Compiling WiFiOutput.cpp"
@@ -254,6 +272,61 @@ $(OBJDIR)/Splitter_6e27a57b.o: ../../Source/Processors/Utilities/Splitter.cpp
 	@echo "Compiling Splitter.cpp"
 	@$(CXX) $(CXXFLAGS) -o "$@" -c "$<"
 
+$(OBJDIR)/StereotrodePlot_4710b8f1.o: ../../Source/Processors/Visualization/SpikePlotting/StereotrodePlot.cpp
+	-@mkdir -p $(OBJDIR)
+	@echo "Compiling StereotrodePlot.cpp"
+	@$(CXX) $(CXXFLAGS) -o "$@" -c "$<"
+
+$(OBJDIR)/ElectrodePlot_7a206ec4.o: ../../Source/Processors/Visualization/SpikePlotting/ElectrodePlot.cpp
+	-@mkdir -p $(OBJDIR)
+	@echo "Compiling ElectrodePlot.cpp"
+	@$(CXX) $(CXXFLAGS) -o "$@" -c "$<"
+
+$(OBJDIR)/BaseUIElement_ec903c4d.o: ../../Source/Processors/Visualization/SpikePlotting/BaseUIElement.cpp
+	-@mkdir -p $(OBJDIR)
+	@echo "Compiling BaseUIElement.cpp"
+	@$(CXX) $(CXXFLAGS) -o "$@" -c "$<"
+
+$(OBJDIR)/GenericAxes_d802ed92.o: ../../Source/Processors/Visualization/SpikePlotting/GenericAxes.cpp
+	-@mkdir -p $(OBJDIR)
+	@echo "Compiling GenericAxes.cpp"
+	@$(CXX) $(CXXFLAGS) -o "$@" -c "$<"
+
+$(OBJDIR)/PlotUtils_9ef52686.o: ../../Source/Processors/Visualization/SpikePlotting/PlotUtils.cpp
+	-@mkdir -p $(OBJDIR)
+	@echo "Compiling PlotUtils.cpp"
+	@$(CXX) $(CXXFLAGS) -o "$@" -c "$<"
+
+$(OBJDIR)/ProjectionAxes_7c67c3e8.o: ../../Source/Processors/Visualization/SpikePlotting/ProjectionAxes.cpp
+	-@mkdir -p $(OBJDIR)
+	@echo "Compiling ProjectionAxes.cpp"
+	@$(CXX) $(CXXFLAGS) -o "$@" -c "$<"
+
+$(OBJDIR)/TetrodePlot_b42fd798.o: ../../Source/Processors/Visualization/SpikePlotting/TetrodePlot.cpp
+	-@mkdir -p $(OBJDIR)
+	@echo "Compiling TetrodePlot.cpp"
+	@$(CXX) $(CXXFLAGS) -o "$@" -c "$<"
+
+$(OBJDIR)/TitleBox_c4a9cde7.o: ../../Source/Processors/Visualization/SpikePlotting/TitleBox.cpp
+	-@mkdir -p $(OBJDIR)
+	@echo "Compiling TitleBox.cpp"
+	@$(CXX) $(CXXFLAGS) -o "$@" -c "$<"
+
+$(OBJDIR)/WaveAxes_8adc45d2.o: ../../Source/Processors/Visualization/SpikePlotting/WaveAxes.cpp
+	-@mkdir -p $(OBJDIR)
+	@echo "Compiling WaveAxes.cpp"
+	@$(CXX) $(CXXFLAGS) -o "$@" -c "$<"
+
+$(OBJDIR)/SpikeObject_24e8c655.o: ../../Source/Processors/Visualization/SpikeObject.cpp
+	-@mkdir -p $(OBJDIR)
+	@echo "Compiling SpikeObject.cpp"
+	@$(CXX) $(CXXFLAGS) -o "$@" -c "$<"
+
+$(OBJDIR)/SpikeDisplayCanvas_b208ff6e.o: ../../Source/Processors/Visualization/SpikeDisplayCanvas.cpp
+	-@mkdir -p $(OBJDIR)
+	@echo "Compiling SpikeDisplayCanvas.cpp"
+	@$(CXX) $(CXXFLAGS) -o "$@" -c "$<"
+
 $(OBJDIR)/DataWindow_83ce6754.o: ../../Source/Processors/Visualization/DataWindow.cpp
 	-@mkdir -p $(OBJDIR)
 	@echo "Compiling DataWindow.cpp"
@@ -284,6 +357,11 @@ $(OBJDIR)/EventNode_95c842b7.o: ../../Source/Processors/EventNode.cpp
 	@echo "Compiling EventNode.cpp"
 	@$(CXX) $(CXXFLAGS) -o "$@" -c "$<"
 
+$(OBJDIR)/SpikeDisplayEditor_e1812c1.o: ../../Source/Processors/Editors/SpikeDisplayEditor.cpp
+	-@mkdir -p $(OBJDIR)
+	@echo "Compiling SpikeDisplayEditor.cpp"
+	@$(CXX) $(CXXFLAGS) -o "$@" -c "$<"
+
 $(OBJDIR)/VisualizerEditor_3672b003.o: ../../Source/Processors/Editors/VisualizerEditor.cpp
 	-@mkdir -p $(OBJDIR)
 	@echo "Compiling VisualizerEditor.cpp"
diff --git a/Builds/MacOSX/open-ephys.xcodeproj/project.pbxproj b/Builds/MacOSX/open-ephys.xcodeproj/project.pbxproj
index ee69144acc43aad435966f07e4be818c9e6e6d77..cbed92cd9f990ce2254ae56c92e253c6e77ccfed 100644
--- a/Builds/MacOSX/open-ephys.xcodeproj/project.pbxproj
+++ b/Builds/MacOSX/open-ephys.xcodeproj/project.pbxproj
@@ -3,7 +3,7 @@
 	archiveVersion = 1;
 	classes = {
 	};
-	objectVersion = 44;
+	objectVersion = 45;
 	objects = {
 
 		6125D1F24D314D771E3A350E = { isa = PBXBuildFile; fileRef = FAB58A8AE7DCBAC0CF311D14; };
@@ -37,16 +37,29 @@
 		8E138283FC265B58D252AAC3 = { isa = PBXBuildFile; fileRef = F4A53064BA75472765338C1D; };
 		EE1DC0B09AE0727BC7A5A99C = { isa = PBXBuildFile; fileRef = 0D20C3399D0492771F7A808A; };
 		4ACF816CB5CDB285D8005AB8 = { isa = PBXBuildFile; fileRef = F74662D3D82975EDB5AD42E0; };
+		1F67A9ACD509FB4DC5A633DF = { isa = PBXBuildFile; fileRef = 4AEDD076CCA918481C6F9CF2; };
 		B992DDBFF8928A985EEE1557 = { isa = PBXBuildFile; fileRef = 268005410FB62BCB9099A762; };
 		F1268EC5E783EC8ECEBCA5D3 = { isa = PBXBuildFile; fileRef = 5935F823A2EE45AC36A0201F; };
 		4A00153E1E69A74BC6B7D8A6 = { isa = PBXBuildFile; fileRef = 3973173C7FA07073B4F86B29; };
 		5F13B8FFB1584BFF6C05AD39 = { isa = PBXBuildFile; fileRef = 9A47B52E5E1CD17DC9C72B53; };
+		B11D72764B1B17BF2B8C6E67 = { isa = PBXBuildFile; fileRef = C92B3F413B0F24752ADE6730; };
+		938FC2F779C2CF4B8C7ECFFE = { isa = PBXBuildFile; fileRef = 3BB44F767E701E3642435FA0; };
+		55A240CCFCD604CA8DF8FC8C = { isa = PBXBuildFile; fileRef = 41591F74A761BAC908FA8AD8; };
+		8025F04ED261C7F7D2DC0F06 = { isa = PBXBuildFile; fileRef = 24C6D768C87E1C42C644C4BD; };
+		49F046C8BE137BF77338DD7B = { isa = PBXBuildFile; fileRef = B195AD6CEB9B6E3625C8D087; };
+		566E42D2B7105CFB4DB45170 = { isa = PBXBuildFile; fileRef = 2FA2FA826CBAD9C639A61E4A; };
+		0DDC562EC2B04A26AE6CBB2B = { isa = PBXBuildFile; fileRef = FBB9A423728922E96F55074F; };
+		39E2F4E31D24BED6E85C489D = { isa = PBXBuildFile; fileRef = 7A9571EBFAAD39E47DE12A10; };
+		BCD7C4797178C8EF65CDC2D7 = { isa = PBXBuildFile; fileRef = 9F208A66C09E80D14F087CB1; };
+		9145D84C7D665BCAFE698432 = { isa = PBXBuildFile; fileRef = E7247F5EE9588903C924994F; };
+		7659F31912D12C91E9554909 = { isa = PBXBuildFile; fileRef = 7A9A31FC1AE8FB238FAE995E; };
 		9D687F73F2FD2462C5D5588C = { isa = PBXBuildFile; fileRef = ED179D5A10DD051DDB3ECB8B; };
 		B13883377C9316B9603336B4 = { isa = PBXBuildFile; fileRef = 2E96DA81EE37A0ECE471A928; };
 		073B178E7EF1759BA0AACCCE = { isa = PBXBuildFile; fileRef = 0C5335B0E57C9DC92FC57E5F; };
 		4BE0DDA01B73223EF0BD934A = { isa = PBXBuildFile; fileRef = 3DD0741FCFBC7563EC722D9B; };
 		08B501E0D7764C6B613AF529 = { isa = PBXBuildFile; fileRef = B7750B27E4F3748ECCCCF69D; };
 		9CBA3837CC8CAA03A03F2D9C = { isa = PBXBuildFile; fileRef = FA57CE4F63FF1592D6B3F9B5; };
+		DD22A06702F4CF995893DD5C = { isa = PBXBuildFile; fileRef = F0B09605D4108F0F94EF3B57; };
 		F4CEF74DDCD7EFA0891249B5 = { isa = PBXBuildFile; fileRef = 9A3976537C96B39716B5312D; };
 		93A3E6284F2DAED3F491332B = { isa = PBXBuildFile; fileRef = AD73EA6B24378294003DC2D0; };
 		CB77C89226102EF30F85E3EC = { isa = PBXBuildFile; fileRef = 544DA1EF90EBBDB6FF2DE0A5; };
@@ -103,191 +116,218 @@
 		191441B631182A346D494BB5 = { isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuartzCore.framework; path = System/Library/Frameworks/QuartzCore.framework; sourceTree = SDKROOT; };
 		1CBCB9D2FE5B967D93785E75 = { isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QTKit.framework; path = System/Library/Frameworks/QTKit.framework; sourceTree = SDKROOT; };
 		BF41F256D0C244C2C02AE6E1 = { isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuickTime.framework; path = System/Library/Frameworks/QuickTime.framework; sourceTree = SDKROOT; };
-		0837481AD187A1E6CBCAC577 = { isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "open-ephys.app"; sourceTree = BUILT_PRODUCTS_DIR; };
-		D91BA61C12BFEBE59B577805 = { isa = PBXFileReference; lastKnownFileType = text.plist.xml; name = Info.plist; path = Info.plist; sourceTree = SOURCE_ROOT; };
-		79892A4E41809A09A4711AC3 = { isa = PBXFileReference; lastKnownFileType = file.otf; name = BebasNeue.otf; path = ../../Resources/Fonts/BebasNeue.otf; sourceTree = SOURCE_ROOT; };
-		1B2C20F6F1F1BCF9115F8D53 = { isa = PBXFileReference; lastKnownFileType = file.otf; name = cpmono_bold.otf; path = ../../Resources/Fonts/cpmono_bold.otf; sourceTree = SOURCE_ROOT; };
-		C586714DD22C96F569FDC716 = { isa = PBXFileReference; lastKnownFileType = file.otf; name = cpmono_extra_light.otf; path = ../../Resources/Fonts/cpmono_extra_light.otf; sourceTree = SOURCE_ROOT; };
-		8E7AA0EF1B95BC771FBB10A0 = { isa = PBXFileReference; lastKnownFileType = file.otf; name = cpmono_light.otf; path = ../../Resources/Fonts/cpmono_light.otf; sourceTree = SOURCE_ROOT; };
-		E79C104CD58BBBD5368EEF5A = { isa = PBXFileReference; lastKnownFileType = file.otf; name = cpmono_plain.otf; path = ../../Resources/Fonts/cpmono_plain.otf; sourceTree = SOURCE_ROOT; };
-		060C55E19A414F464C499A47 = { isa = PBXFileReference; lastKnownFileType = file.ttf; name = "miso-bold.ttf"; path = "../../Resources/Fonts/miso-bold.ttf"; sourceTree = SOURCE_ROOT; };
-		50F20268C4572493BB04D269 = { isa = PBXFileReference; lastKnownFileType = file.ttf; name = "miso-light.ttf"; path = "../../Resources/Fonts/miso-light.ttf"; sourceTree = SOURCE_ROOT; };
-		50D4782F4555FED294F40705 = { isa = PBXFileReference; lastKnownFileType = file.ttf; name = "miso-regular.ttf"; path = "../../Resources/Fonts/miso-regular.ttf"; sourceTree = SOURCE_ROOT; };
-		4974E0E46141648F106A818F = { isa = PBXFileReference; lastKnownFileType = file; name = "miso-serialized"; path = "../../Resources/Fonts/miso-serialized"; sourceTree = SOURCE_ROOT; };
-		35352AD0E7B59E35BC3B5F59 = { isa = PBXFileReference; lastKnownFileType = file.ttf; name = nordic.ttf; path = ../../Resources/Fonts/nordic.ttf; sourceTree = SOURCE_ROOT; };
-		44303AB487040AE4B60DCAD5 = { isa = PBXFileReference; lastKnownFileType = file.ttf; name = ostrich.ttf; path = ../../Resources/Fonts/ostrich.ttf; sourceTree = SOURCE_ROOT; };
-		C2A7939DF5ED600BBB2F30C4 = { isa = PBXFileReference; lastKnownFileType = file; name = "silkscreen-serialized"; path = "../../Resources/Fonts/silkscreen-serialized"; sourceTree = SOURCE_ROOT; };
-		F8CAE2412B173788F325BD8B = { isa = PBXFileReference; lastKnownFileType = file.ttf; name = silkscreen.ttf; path = ../../Resources/Fonts/silkscreen.ttf; sourceTree = SOURCE_ROOT; };
-		363B59958615D35C5C948300 = { isa = PBXFileReference; lastKnownFileType = file.otf; name = "unibody-8.otf"; path = "../../Resources/Fonts/unibody-8.otf"; sourceTree = SOURCE_ROOT; };
-		8E041C8C49F1A5B710CC812C = { isa = PBXFileReference; lastKnownFileType = image.png; name = wifi.png; path = ../../Resources/Images/Icons/wifi.png; sourceTree = SOURCE_ROOT; };
-		2A1D9144C59B92B32483924B = { isa = PBXFileReference; lastKnownFileType = image.png; name = SourceDrop.png; path = ../../Resources/Images/Icons/SourceDrop.png; sourceTree = SOURCE_ROOT; };
-		D99F56FB46F631F67AF23F2C = { isa = PBXFileReference; lastKnownFileType = image.png; name = DefaultDataSource.png; path = ../../Resources/Images/Icons/DefaultDataSource.png; sourceTree = SOURCE_ROOT; };
-		66C7E42D7FDE3600982A1F46 = { isa = PBXFileReference; lastKnownFileType = image.png; name = FileReaderIcon.png; path = ../../Resources/Images/Icons/FileReaderIcon.png; sourceTree = SOURCE_ROOT; };
-		A4C8AB3F5E7A708350F72E7C = { isa = PBXFileReference; lastKnownFileType = image.png; name = IntanIcon.png; path = ../../Resources/Images/Icons/IntanIcon.png; sourceTree = SOURCE_ROOT; };
-		BD0900C3A85F58C34FA91D16 = { isa = PBXFileReference; lastKnownFileType = image.png; name = muteoff.png; path = ../../Resources/Images/Buttons/muteoff.png; sourceTree = SOURCE_ROOT; };
-		1BDA9647E0AA33F642E162BE = { isa = PBXFileReference; lastKnownFileType = image.png; name = muteon.png; path = ../../Resources/Images/Buttons/muteon.png; sourceTree = SOURCE_ROOT; };
-		D2D308542534D043BB12C801 = { isa = PBXFileReference; lastKnownFileType = image.png; name = "MergerA-01.png"; path = "../../Resources/Images/Buttons/MergerA-01.png"; sourceTree = SOURCE_ROOT; };
-		9CD0E7C2C7E49A0DBF301B0F = { isa = PBXFileReference; lastKnownFileType = image.png; name = "MergerA-02.png"; path = "../../Resources/Images/Buttons/MergerA-02.png"; sourceTree = SOURCE_ROOT; };
-		BAAA02122ADD1D5D0670A684 = { isa = PBXFileReference; lastKnownFileType = image.png; name = "MergerB-01.png"; path = "../../Resources/Images/Buttons/MergerB-01.png"; sourceTree = SOURCE_ROOT; };
-		73A7E17FDD8DD717F99E0882 = { isa = PBXFileReference; lastKnownFileType = image.png; name = "MergerB-02.png"; path = "../../Resources/Images/Buttons/MergerB-02.png"; sourceTree = SOURCE_ROOT; };
-		2A54E3D28E10F5D50498BB77 = { isa = PBXFileReference; lastKnownFileType = image.png; name = "PipelineA-01.png"; path = "../../Resources/Images/Buttons/PipelineA-01.png"; sourceTree = SOURCE_ROOT; };
-		294B78ADA337603DE3C87BF9 = { isa = PBXFileReference; lastKnownFileType = image.png; name = "PipelineA-02.png"; path = "../../Resources/Images/Buttons/PipelineA-02.png"; sourceTree = SOURCE_ROOT; };
-		8AD9A0F023B727B34348B95E = { isa = PBXFileReference; lastKnownFileType = image.png; name = "PipelineB-01.png"; path = "../../Resources/Images/Buttons/PipelineB-01.png"; sourceTree = SOURCE_ROOT; };
-		89CF25CB48EEA21B226869E1 = { isa = PBXFileReference; lastKnownFileType = image.png; name = "PipelineB-02.png"; path = "../../Resources/Images/Buttons/PipelineB-02.png"; sourceTree = SOURCE_ROOT; };
-		CA0A1584725D21237DBCD70A = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = AccessClass.cpp; path = ../../Source/AccessClass.cpp; sourceTree = SOURCE_ROOT; };
-		63992CB3AC42F91A51135EAC = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = AccessClass.h; path = ../../Source/AccessClass.h; sourceTree = SOURCE_ROOT; };
-		673778A175624FC9F52E7A15 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = PracticalSocket.cpp; path = ../../Source/Network/PracticalSocket.cpp; sourceTree = SOURCE_ROOT; };
-		2EAE0475B719C3233AD8BB35 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = PracticalSocket.h; path = ../../Source/Network/PracticalSocket.h; sourceTree = SOURCE_ROOT; };
-		B30EF131FE61BAA4C1818102 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = Bessel.cpp; path = ../../Source/Dsp/Bessel.cpp; sourceTree = SOURCE_ROOT; };
-		D55947E71EB4AF25C1FC7089 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = Bessel.h; path = ../../Source/Dsp/Bessel.h; sourceTree = SOURCE_ROOT; };
-		07AE46453303977ED64E38ED = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = Biquad.cpp; path = ../../Source/Dsp/Biquad.cpp; sourceTree = SOURCE_ROOT; };
-		9EBBC43B9522EC9E6B607493 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = Biquad.h; path = ../../Source/Dsp/Biquad.h; sourceTree = SOURCE_ROOT; };
-		73C6FF74D6A31CA13C0D7C5C = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = Butterworth.cpp; path = ../../Source/Dsp/Butterworth.cpp; sourceTree = SOURCE_ROOT; };
-		8B70886CFCD13A761567DE7B = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = Butterworth.h; path = ../../Source/Dsp/Butterworth.h; sourceTree = SOURCE_ROOT; };
-		742284C84C72C882E02E7974 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = Cascade.cpp; path = ../../Source/Dsp/Cascade.cpp; sourceTree = SOURCE_ROOT; };
-		2B8E059E57EB92EAC589C6B4 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = Cascade.h; path = ../../Source/Dsp/Cascade.h; sourceTree = SOURCE_ROOT; };
-		D44DBE2FF15A98834F222766 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = ChebyshevI.cpp; path = ../../Source/Dsp/ChebyshevI.cpp; sourceTree = SOURCE_ROOT; };
-		553E92DB60C7D5104B780781 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = ChebyshevI.h; path = ../../Source/Dsp/ChebyshevI.h; sourceTree = SOURCE_ROOT; };
-		1F9836FC5A8FDF2293C9A232 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = ChebyshevII.cpp; path = ../../Source/Dsp/ChebyshevII.cpp; sourceTree = SOURCE_ROOT; };
-		833030703B66CDD9DA94155B = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = ChebyshevII.h; path = ../../Source/Dsp/ChebyshevII.h; sourceTree = SOURCE_ROOT; };
-		F7620D8D567CCE463ADDE0A6 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = Common.h; path = ../../Source/Dsp/Common.h; sourceTree = SOURCE_ROOT; };
-		93FACAE1DC7A236505359477 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = Custom.cpp; path = ../../Source/Dsp/Custom.cpp; sourceTree = SOURCE_ROOT; };
-		E4AEAC4AD1D1C6A80A2CD70A = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = Custom.h; path = ../../Source/Dsp/Custom.h; sourceTree = SOURCE_ROOT; };
-		3E8E2F9C583077B298525FD1 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = Design.cpp; path = ../../Source/Dsp/Design.cpp; sourceTree = SOURCE_ROOT; };
-		CD05957EC804348231739108 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = Design.h; path = ../../Source/Dsp/Design.h; sourceTree = SOURCE_ROOT; };
-		E8214D83845C25F39EEC13CD = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = Documentation.cpp; path = ../../Source/Dsp/Documentation.cpp; sourceTree = SOURCE_ROOT; };
-		21E5288817625724406FD3A1 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = Dsp.h; path = ../../Source/Dsp/Dsp.h; sourceTree = SOURCE_ROOT; };
-		293B003BD6E113C5AD1BB131 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = Elliptic.cpp; path = ../../Source/Dsp/Elliptic.cpp; sourceTree = SOURCE_ROOT; };
-		60F060DBD5ACF36E0A407BC1 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = Elliptic.h; path = ../../Source/Dsp/Elliptic.h; sourceTree = SOURCE_ROOT; };
-		A9AF10F6A89F85989C62F856 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = Filter.cpp; path = ../../Source/Dsp/Filter.cpp; sourceTree = SOURCE_ROOT; };
-		7C225F446A96BED7F585F66B = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = Filter.h; path = ../../Source/Dsp/Filter.h; sourceTree = SOURCE_ROOT; };
-		314D53C7C13C28A25588ABCF = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = Layout.h; path = ../../Source/Dsp/Layout.h; sourceTree = SOURCE_ROOT; };
-		706CBE9178440675868F2379 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = Legendre.cpp; path = ../../Source/Dsp/Legendre.cpp; sourceTree = SOURCE_ROOT; };
-		1EC547C25C29FE679BAF8B4D = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = Legendre.h; path = ../../Source/Dsp/Legendre.h; sourceTree = SOURCE_ROOT; };
-		4D63E86C8A9F721B9C0FA95E = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = MathSupplement.h; path = ../../Source/Dsp/MathSupplement.h; sourceTree = SOURCE_ROOT; };
-		BF8EB3483F66AA7F61E6D863 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = Param.cpp; path = ../../Source/Dsp/Param.cpp; sourceTree = SOURCE_ROOT; };
-		1E0F3076D1689E83422F6B4E = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = Params.h; path = ../../Source/Dsp/Params.h; sourceTree = SOURCE_ROOT; };
-		137CF1AB4144076D79D50975 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = PoleFilter.cpp; path = ../../Source/Dsp/PoleFilter.cpp; sourceTree = SOURCE_ROOT; };
-		5B1D08D98AD9F623962A38B2 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = PoleFilter.h; path = ../../Source/Dsp/PoleFilter.h; sourceTree = SOURCE_ROOT; };
-		E6FF4D4C70794123A52B9E82 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = RBJ.cpp; path = ../../Source/Dsp/RBJ.cpp; sourceTree = SOURCE_ROOT; };
-		E8503A3E123FCFBFA317EAE6 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = RBJ.h; path = ../../Source/Dsp/RBJ.h; sourceTree = SOURCE_ROOT; };
-		F4A53064BA75472765338C1D = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = RootFinder.cpp; path = ../../Source/Dsp/RootFinder.cpp; sourceTree = SOURCE_ROOT; };
-		1D1DF895F34C981407EDB8E8 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = RootFinder.h; path = ../../Source/Dsp/RootFinder.h; sourceTree = SOURCE_ROOT; };
-		1F5435604926FF2C06575DCC = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SmoothedFilter.h; path = ../../Source/Dsp/SmoothedFilter.h; sourceTree = SOURCE_ROOT; };
-		0D20C3399D0492771F7A808A = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = State.cpp; path = ../../Source/Dsp/State.cpp; sourceTree = SOURCE_ROOT; };
-		186F011C1ABC55DB39717105 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = State.h; path = ../../Source/Dsp/State.h; sourceTree = SOURCE_ROOT; };
-		92C241C7F87B5933B0E6E03F = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = Types.h; path = ../../Source/Dsp/Types.h; sourceTree = SOURCE_ROOT; };
-		E27B5891A52FDAB2B00901A0 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = Utilities.h; path = ../../Source/Dsp/Utilities.h; sourceTree = SOURCE_ROOT; };
-		F74662D3D82975EDB5AD42E0 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = AudioComponent.cpp; path = ../../Source/Audio/AudioComponent.cpp; sourceTree = SOURCE_ROOT; };
-		FA55B9FDE138CCB1F16BA905 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = AudioComponent.h; path = ../../Source/Audio/AudioComponent.h; sourceTree = SOURCE_ROOT; };
-		268005410FB62BCB9099A762 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = WiFiOutput.cpp; path = ../../Source/Processors/WiFiOutput.cpp; sourceTree = SOURCE_ROOT; };
-		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; };
-		9ACFB6A181D09434268CE006 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = Visualizer.h; path = ../../Source/Processors/Visualization/Visualizer.h; sourceTree = SOURCE_ROOT; };
-		ED179D5A10DD051DDB3ECB8B = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = DataWindow.cpp; path = ../../Source/Processors/Visualization/DataWindow.cpp; sourceTree = SOURCE_ROOT; };
-		63C18F4066C75D3C312877D8 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = DataWindow.h; path = ../../Source/Processors/Visualization/DataWindow.h; sourceTree = SOURCE_ROOT; };
-		2E96DA81EE37A0ECE471A928 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = LfpDisplayCanvas.cpp; path = ../../Source/Processors/Visualization/LfpDisplayCanvas.cpp; sourceTree = SOURCE_ROOT; };
-		A9C2C7AF037050228CD2E026 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = LfpDisplayCanvas.h; path = ../../Source/Processors/Visualization/LfpDisplayCanvas.h; sourceTree = SOURCE_ROOT; };
-		0C5335B0E57C9DC92FC57E5F = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = OpenGLCanvas.cpp; path = ../../Source/Processors/Visualization/OpenGLCanvas.cpp; sourceTree = SOURCE_ROOT; };
-		7738F51AE0EC63D76EE0F761 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = OpenGLCanvas.h; path = ../../Source/Processors/Visualization/OpenGLCanvas.h; sourceTree = SOURCE_ROOT; };
-		3DD0741FCFBC7563EC722D9B = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = SpikeDetector.cpp; path = ../../Source/Processors/SpikeDetector.cpp; sourceTree = SOURCE_ROOT; };
-		6E4B37AA4BFEB5A37E3AC250 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SpikeDetector.h; path = ../../Source/Processors/SpikeDetector.h; sourceTree = SOURCE_ROOT; };
-		B7750B27E4F3748ECCCCF69D = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = AudioNode.cpp; path = ../../Source/Processors/AudioNode.cpp; sourceTree = SOURCE_ROOT; };
-		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; };
-		9A3976537C96B39716B5312D = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = VisualizerEditor.cpp; path = ../../Source/Processors/Editors/VisualizerEditor.cpp; sourceTree = SOURCE_ROOT; };
-		C546D55EDE65ADDD95C6A6F5 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = VisualizerEditor.h; path = ../../Source/Processors/Editors/VisualizerEditor.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; };
-		4E67CFE458501E763FF3AE94 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = WiFiOutputEditor.h; path = ../../Source/Processors/Editors/WiFiOutputEditor.h; sourceTree = SOURCE_ROOT; };
-		36393F2D58480F61ECDEB5E5 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = EventNodeEditor.cpp; path = ../../Source/Processors/Editors/EventNodeEditor.cpp; sourceTree = SOURCE_ROOT; };
-		A80433BF9686B4E2542C580C = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = EventNodeEditor.h; path = ../../Source/Processors/Editors/EventNodeEditor.h; sourceTree = SOURCE_ROOT; };
-		087136FA6A7A0E01738EEF03 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = SignalGeneratorEditor.cpp; path = ../../Source/Processors/Editors/SignalGeneratorEditor.cpp; sourceTree = SOURCE_ROOT; };
-		10F82563E4A633BC234B2800 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SignalGeneratorEditor.h; path = ../../Source/Processors/Editors/SignalGeneratorEditor.h; sourceTree = SOURCE_ROOT; };
-		CF9878CE31A1B41406C3457B = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = LfpDisplayEditor.cpp; path = ../../Source/Processors/Editors/LfpDisplayEditor.cpp; sourceTree = SOURCE_ROOT; };
-		C02C160190E417B42F73680A = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = LfpDisplayEditor.h; path = ../../Source/Processors/Editors/LfpDisplayEditor.h; sourceTree = SOURCE_ROOT; };
-		FC5939F3D2A31BB43EA3E393 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = SourceNodeEditor.cpp; path = ../../Source/Processors/Editors/SourceNodeEditor.cpp; sourceTree = SOURCE_ROOT; };
-		62DA962299323A2FA134203D = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SourceNodeEditor.h; path = ../../Source/Processors/Editors/SourceNodeEditor.h; sourceTree = SOURCE_ROOT; };
-		C2ED801EA28FBA9764E76349 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = SplitterEditor.cpp; path = ../../Source/Processors/Editors/SplitterEditor.cpp; sourceTree = SOURCE_ROOT; };
-		C177B371A0CEC8E7B9131865 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SplitterEditor.h; path = ../../Source/Processors/Editors/SplitterEditor.h; sourceTree = SOURCE_ROOT; };
-		399CBACE291A425A2B9497EF = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = SpikeDetectorEditor.cpp; path = ../../Source/Processors/Editors/SpikeDetectorEditor.cpp; sourceTree = SOURCE_ROOT; };
-		7FC3C64A06A9FA2C828F8744 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SpikeDetectorEditor.h; path = ../../Source/Processors/Editors/SpikeDetectorEditor.h; sourceTree = SOURCE_ROOT; };
-		5DDBEE64DC706CE804E5F0AA = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = AudioEditor.cpp; path = ../../Source/Processors/Editors/AudioEditor.cpp; sourceTree = SOURCE_ROOT; };
-		303B2522EAC7CD3C33EF150C = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = AudioEditor.h; path = ../../Source/Processors/Editors/AudioEditor.h; sourceTree = SOURCE_ROOT; };
-		35AFD01064BF29D90EEDF413 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = FilterEditor.cpp; path = ../../Source/Processors/Editors/FilterEditor.cpp; sourceTree = SOURCE_ROOT; };
-		AD4BF1BC602902B20AEBF49C = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = FilterEditor.h; path = ../../Source/Processors/Editors/FilterEditor.h; sourceTree = SOURCE_ROOT; };
-		22FD0613BADE6C36A6A7A25C = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = GenericEditor.cpp; path = ../../Source/Processors/Editors/GenericEditor.cpp; sourceTree = SOURCE_ROOT; };
-		F0B8C75B1AA6E8D1BC620653 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = GenericEditor.h; path = ../../Source/Processors/Editors/GenericEditor.h; sourceTree = SOURCE_ROOT; };
-		0D2903C450AE862C2C0060AA = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = FileReaderThread.cpp; path = ../../Source/Processors/DataThreads/FileReaderThread.cpp; sourceTree = SOURCE_ROOT; };
-		BD07C36AC2ECF10942F0A229 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = FileReaderThread.h; path = ../../Source/Processors/DataThreads/FileReaderThread.h; sourceTree = SOURCE_ROOT; };
-		24616D6D2297C87D371B0363 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = okFrontPanelDLL.cpp; path = ../../Source/Processors/DataThreads/okFrontPanelDLL.cpp; sourceTree = SOURCE_ROOT; };
-		AA7B88F969CE43331035DE98 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = okFrontPanelDLL.h; path = ../../Source/Processors/DataThreads/okFrontPanelDLL.h; sourceTree = SOURCE_ROOT; };
-		6B156D132738F6C7C948378F = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = NetworkThread.cpp; path = ../../Source/Processors/DataThreads/NetworkThread.cpp; sourceTree = SOURCE_ROOT; };
-		7BD204C890F9A2F301B15128 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = NetworkThread.h; path = ../../Source/Processors/DataThreads/NetworkThread.h; sourceTree = SOURCE_ROOT; };
-		A9142BFEFE7EB34D919ED0A0 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = FPGAThread.cpp; path = ../../Source/Processors/DataThreads/FPGAThread.cpp; sourceTree = SOURCE_ROOT; };
-		46E436D1B9538DB8487F0D8D = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = FPGAThread.h; path = ../../Source/Processors/DataThreads/FPGAThread.h; sourceTree = SOURCE_ROOT; };
-		F20726FD9F586FDE2CB42901 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = DataBuffer.cpp; path = ../../Source/Processors/DataThreads/DataBuffer.cpp; sourceTree = SOURCE_ROOT; };
-		F062CCE0FB40E6C65A6493F4 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = DataBuffer.h; path = ../../Source/Processors/DataThreads/DataBuffer.h; sourceTree = SOURCE_ROOT; };
-		6D94C2733E967EC6A91B719A = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = IntanThread.cpp; path = ../../Source/Processors/DataThreads/IntanThread.cpp; sourceTree = SOURCE_ROOT; };
-		21C560B017F1C0A48B950155 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = IntanThread.h; path = ../../Source/Processors/DataThreads/IntanThread.h; sourceTree = SOURCE_ROOT; };
-		72123888A7DD78159AA032AF = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = DataThread.cpp; path = ../../Source/Processors/DataThreads/DataThread.cpp; sourceTree = SOURCE_ROOT; };
-		2164BFCDF57A5AA752CAA3A2 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = DataThread.h; path = ../../Source/Processors/DataThreads/DataThread.h; sourceTree = SOURCE_ROOT; };
-		B96BF02034F29DE033F16D89 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = RecordNode.cpp; path = ../../Source/Processors/RecordNode.cpp; sourceTree = SOURCE_ROOT; };
-		FC83C3CD6DC717911B2C3C20 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = RecordNode.h; path = ../../Source/Processors/RecordNode.h; sourceTree = SOURCE_ROOT; };
-		EBB0E5058615EA1FEDADF189 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = SignalGenerator.cpp; path = ../../Source/Processors/SignalGenerator.cpp; sourceTree = SOURCE_ROOT; };
-		E0883576683119727BD54A81 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SignalGenerator.h; path = ../../Source/Processors/SignalGenerator.h; sourceTree = SOURCE_ROOT; };
-		5AE7693391C43B4AE475789C = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = ResamplingNode.cpp; path = ../../Source/Processors/ResamplingNode.cpp; sourceTree = SOURCE_ROOT; };
-		C87B84BA79CB9EE547E8762C = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = ResamplingNode.h; path = ../../Source/Processors/ResamplingNode.h; sourceTree = SOURCE_ROOT; };
-		D2342EA3BD783D3A81006606 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = FilterNode.cpp; path = ../../Source/Processors/FilterNode.cpp; sourceTree = SOURCE_ROOT; };
-		2CCD3BBDF86EA8D149DAD758 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = FilterNode.h; path = ../../Source/Processors/FilterNode.h; sourceTree = SOURCE_ROOT; };
-		7EAD8082130C2384BA9E1206 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = SourceNode.cpp; path = ../../Source/Processors/SourceNode.cpp; sourceTree = SOURCE_ROOT; };
-		7BD1C1A7C30ED736F4816C31 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SourceNode.h; path = ../../Source/Processors/SourceNode.h; sourceTree = SOURCE_ROOT; };
-		CECE2AB5D5F36CADBC3219A2 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = GenericProcessor.cpp; path = ../../Source/Processors/GenericProcessor.cpp; sourceTree = SOURCE_ROOT; };
-		C4197FDA1B4D4F1D58F6A5A0 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = GenericProcessor.h; path = ../../Source/Processors/GenericProcessor.h; sourceTree = SOURCE_ROOT; };
-		C4DA9685E5637B03F00E5E79 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = ProcessorGraph.cpp; path = ../../Source/Processors/ProcessorGraph.cpp; sourceTree = SOURCE_ROOT; };
-		3B60787E97C74E78853DC90F = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = ProcessorGraph.h; path = ../../Source/Processors/ProcessorGraph.h; sourceTree = SOURCE_ROOT; };
-		E1C6E67757EC5D68093BD760 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = EditorViewportButtons.cpp; path = ../../Source/UI/EditorViewportButtons.cpp; sourceTree = SOURCE_ROOT; };
-		2BC65E923E245AE23AE7BB8B = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = EditorViewportButtons.h; path = ../../Source/UI/EditorViewportButtons.h; sourceTree = SOURCE_ROOT; };
-		6CD0D896FEB77B261C62447E = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = SignalChainManager.cpp; path = ../../Source/UI/SignalChainManager.cpp; sourceTree = SOURCE_ROOT; };
-		182F8F9073A2007403C10C51 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SignalChainManager.h; path = ../../Source/UI/SignalChainManager.h; sourceTree = SOURCE_ROOT; };
-		EB824B60F600C19193ADFA5F = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = EditorViewport.cpp; path = ../../Source/UI/EditorViewport.cpp; sourceTree = SOURCE_ROOT; };
-		54A33424E41D55153F6EB422 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = EditorViewport.h; path = ../../Source/UI/EditorViewport.h; sourceTree = SOURCE_ROOT; };
-		B28CC9409188C9A200AAAFFC = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = ProcessorList.cpp; path = ../../Source/UI/ProcessorList.cpp; sourceTree = SOURCE_ROOT; };
-		242E7E62B8641B1224E25442 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = ProcessorList.h; path = ../../Source/UI/ProcessorList.h; sourceTree = SOURCE_ROOT; };
-		A32D8455B95FD230EBFD7891 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = CustomLookAndFeel.cpp; path = ../../Source/UI/CustomLookAndFeel.cpp; sourceTree = SOURCE_ROOT; };
-		F70641473A3E7C0DC5168858 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = CustomLookAndFeel.h; path = ../../Source/UI/CustomLookAndFeel.h; sourceTree = SOURCE_ROOT; };
-		AA00883DC021E36B7EFDAC43 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = InfoLabel.cpp; path = ../../Source/UI/InfoLabel.cpp; sourceTree = SOURCE_ROOT; };
-		1561F28CD560AB8F2E177628 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = InfoLabel.h; path = ../../Source/UI/InfoLabel.h; sourceTree = SOURCE_ROOT; };
-		B977C2809B309C8038CB5D95 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = DataViewport.cpp; path = ../../Source/UI/DataViewport.cpp; sourceTree = SOURCE_ROOT; };
-		877F9F9DA7A1B51D3EDCBC07 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = DataViewport.h; path = ../../Source/UI/DataViewport.h; sourceTree = SOURCE_ROOT; };
-		2F53BB2693AA5F1C2F27AF7C = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = Configuration.cpp; path = ../../Source/UI/Configuration.cpp; sourceTree = SOURCE_ROOT; };
-		DE21954E89A302C554C403B3 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = Configuration.h; path = ../../Source/UI/Configuration.h; sourceTree = SOURCE_ROOT; };
-		EEDA71600D817BF9444FE3E7 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = MessageCenter.cpp; path = ../../Source/UI/MessageCenter.cpp; sourceTree = SOURCE_ROOT; };
-		4EE6CA70F229EDE04E7E320B = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = MessageCenter.h; path = ../../Source/UI/MessageCenter.h; sourceTree = SOURCE_ROOT; };
-		5AB4A3A63B9FDEAB09EEC9C8 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = ControlPanel.cpp; path = ../../Source/UI/ControlPanel.cpp; sourceTree = SOURCE_ROOT; };
-		3B70B21129D91B16A2F1CE80 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = ControlPanel.h; path = ../../Source/UI/ControlPanel.h; sourceTree = SOURCE_ROOT; };
-		2A78F719BAFBDCD63AE9A88A = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = UIComponent.cpp; path = ../../Source/UI/UIComponent.cpp; sourceTree = SOURCE_ROOT; };
-		DB605BA15852F367DF625300 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = UIComponent.h; path = ../../Source/UI/UIComponent.h; sourceTree = SOURCE_ROOT; };
-		77F2E2E7A2419CB172C0B1EA = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = MainWindow.cpp; path = ../../Source/MainWindow.cpp; sourceTree = SOURCE_ROOT; };
-		3E3E4F25C71B800C97AC63B9 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = MainWindow.h; path = ../../Source/MainWindow.h; sourceTree = SOURCE_ROOT; };
-		19D5134F99CC551B01D5A7EF = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = Main.cpp; path = ../../Source/Main.cpp; sourceTree = SOURCE_ROOT; };
-		BDB56CA7F08DC7EFABBF7846 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = AppConfig.h; path = ../../JuceLibraryCode/AppConfig.h; sourceTree = SOURCE_ROOT; };
-		753133530248EC4F00CBECA6 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = JuceHeader.h; path = ../../JuceLibraryCode/JuceHeader.h; sourceTree = SOURCE_ROOT; };
-		B56D08AB6374C811F59D760C = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = BinaryData.cpp; path = ../../JuceLibraryCode/BinaryData.cpp; sourceTree = SOURCE_ROOT; };
-		9BFC7532965901165C9DDB07 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = BinaryData.h; path = ../../JuceLibraryCode/BinaryData.h; sourceTree = SOURCE_ROOT; };
-		898385F65E64BF6D609B3BF2 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; name = JuceLibraryCode1.mm; path = ../../JuceLibraryCode/JuceLibraryCode1.mm; sourceTree = SOURCE_ROOT; };
-		C3B95EF26B5F3281447FCF42 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; name = JuceLibraryCode2.mm; path = ../../JuceLibraryCode/JuceLibraryCode2.mm; sourceTree = SOURCE_ROOT; };
-		1CD026FD773BB5A428624381 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; name = JuceLibraryCode3.mm; path = ../../JuceLibraryCode/JuceLibraryCode3.mm; sourceTree = SOURCE_ROOT; };
-		55F7FFF9942627D7FC46C6C1 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; name = JuceLibraryCode4.mm; path = ../../JuceLibraryCode/JuceLibraryCode4.mm; sourceTree = SOURCE_ROOT; };
+		0837481AD187A1E6CBCAC577 = { isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "open-ephys.app"; sourceTree = "BUILT_PRODUCTS_DIR"; };
+		D91BA61C12BFEBE59B577805 = { isa = PBXFileReference; lastKnownFileType = text.plist.xml; name = Info.plist; path = Info.plist; sourceTree = "SOURCE_ROOT"; };
+		79892A4E41809A09A4711AC3 = { isa = PBXFileReference; lastKnownFileType = file.otf; name = BebasNeue.otf; path = ../../Resources/Fonts/BebasNeue.otf; sourceTree = "SOURCE_ROOT"; };
+		1B2C20F6F1F1BCF9115F8D53 = { isa = PBXFileReference; lastKnownFileType = file.otf; name = "cpmono_bold.otf"; path = "../../Resources/Fonts/cpmono_bold.otf"; sourceTree = "SOURCE_ROOT"; };
+		C586714DD22C96F569FDC716 = { isa = PBXFileReference; lastKnownFileType = file.otf; name = "cpmono_extra_light.otf"; path = "../../Resources/Fonts/cpmono_extra_light.otf"; sourceTree = "SOURCE_ROOT"; };
+		8E7AA0EF1B95BC771FBB10A0 = { isa = PBXFileReference; lastKnownFileType = file.otf; name = "cpmono_light.otf"; path = "../../Resources/Fonts/cpmono_light.otf"; sourceTree = "SOURCE_ROOT"; };
+		E79C104CD58BBBD5368EEF5A = { isa = PBXFileReference; lastKnownFileType = file.otf; name = "cpmono_plain.otf"; path = "../../Resources/Fonts/cpmono_plain.otf"; sourceTree = "SOURCE_ROOT"; };
+		060C55E19A414F464C499A47 = { isa = PBXFileReference; lastKnownFileType = file.ttf; name = "miso-bold.ttf"; path = "../../Resources/Fonts/miso-bold.ttf"; sourceTree = "SOURCE_ROOT"; };
+		50F20268C4572493BB04D269 = { isa = PBXFileReference; lastKnownFileType = file.ttf; name = "miso-light.ttf"; path = "../../Resources/Fonts/miso-light.ttf"; sourceTree = "SOURCE_ROOT"; };
+		50D4782F4555FED294F40705 = { isa = PBXFileReference; lastKnownFileType = file.ttf; name = "miso-regular.ttf"; path = "../../Resources/Fonts/miso-regular.ttf"; sourceTree = "SOURCE_ROOT"; };
+		4974E0E46141648F106A818F = { isa = PBXFileReference; lastKnownFileType = file; name = "miso-serialized"; path = "../../Resources/Fonts/miso-serialized"; sourceTree = "SOURCE_ROOT"; };
+		35352AD0E7B59E35BC3B5F59 = { isa = PBXFileReference; lastKnownFileType = file.ttf; name = nordic.ttf; path = ../../Resources/Fonts/nordic.ttf; sourceTree = "SOURCE_ROOT"; };
+		44303AB487040AE4B60DCAD5 = { isa = PBXFileReference; lastKnownFileType = file.ttf; name = ostrich.ttf; path = ../../Resources/Fonts/ostrich.ttf; sourceTree = "SOURCE_ROOT"; };
+		C2A7939DF5ED600BBB2F30C4 = { isa = PBXFileReference; lastKnownFileType = file; name = "silkscreen-serialized"; path = "../../Resources/Fonts/silkscreen-serialized"; sourceTree = "SOURCE_ROOT"; };
+		F8CAE2412B173788F325BD8B = { isa = PBXFileReference; lastKnownFileType = file.ttf; name = silkscreen.ttf; path = ../../Resources/Fonts/silkscreen.ttf; sourceTree = "SOURCE_ROOT"; };
+		363B59958615D35C5C948300 = { isa = PBXFileReference; lastKnownFileType = file.otf; name = "unibody-8.otf"; path = "../../Resources/Fonts/unibody-8.otf"; sourceTree = "SOURCE_ROOT"; };
+		8E041C8C49F1A5B710CC812C = { isa = PBXFileReference; lastKnownFileType = image.png; name = wifi.png; path = ../../Resources/Images/Icons/wifi.png; sourceTree = "SOURCE_ROOT"; };
+		2A1D9144C59B92B32483924B = { isa = PBXFileReference; lastKnownFileType = image.png; name = SourceDrop.png; path = ../../Resources/Images/Icons/SourceDrop.png; sourceTree = "SOURCE_ROOT"; };
+		D99F56FB46F631F67AF23F2C = { isa = PBXFileReference; lastKnownFileType = image.png; name = DefaultDataSource.png; path = ../../Resources/Images/Icons/DefaultDataSource.png; sourceTree = "SOURCE_ROOT"; };
+		66C7E42D7FDE3600982A1F46 = { isa = PBXFileReference; lastKnownFileType = image.png; name = FileReaderIcon.png; path = ../../Resources/Images/Icons/FileReaderIcon.png; sourceTree = "SOURCE_ROOT"; };
+		A4C8AB3F5E7A708350F72E7C = { isa = PBXFileReference; lastKnownFileType = image.png; name = IntanIcon.png; path = ../../Resources/Images/Icons/IntanIcon.png; sourceTree = "SOURCE_ROOT"; };
+		BD0900C3A85F58C34FA91D16 = { isa = PBXFileReference; lastKnownFileType = image.png; name = muteoff.png; path = ../../Resources/Images/Buttons/muteoff.png; sourceTree = "SOURCE_ROOT"; };
+		1BDA9647E0AA33F642E162BE = { isa = PBXFileReference; lastKnownFileType = image.png; name = muteon.png; path = ../../Resources/Images/Buttons/muteon.png; sourceTree = "SOURCE_ROOT"; };
+		D2D308542534D043BB12C801 = { isa = PBXFileReference; lastKnownFileType = image.png; name = "MergerA-01.png"; path = "../../Resources/Images/Buttons/MergerA-01.png"; sourceTree = "SOURCE_ROOT"; };
+		9CD0E7C2C7E49A0DBF301B0F = { isa = PBXFileReference; lastKnownFileType = image.png; name = "MergerA-02.png"; path = "../../Resources/Images/Buttons/MergerA-02.png"; sourceTree = "SOURCE_ROOT"; };
+		BAAA02122ADD1D5D0670A684 = { isa = PBXFileReference; lastKnownFileType = image.png; name = "MergerB-01.png"; path = "../../Resources/Images/Buttons/MergerB-01.png"; sourceTree = "SOURCE_ROOT"; };
+		73A7E17FDD8DD717F99E0882 = { isa = PBXFileReference; lastKnownFileType = image.png; name = "MergerB-02.png"; path = "../../Resources/Images/Buttons/MergerB-02.png"; sourceTree = "SOURCE_ROOT"; };
+		2A54E3D28E10F5D50498BB77 = { isa = PBXFileReference; lastKnownFileType = image.png; name = "PipelineA-01.png"; path = "../../Resources/Images/Buttons/PipelineA-01.png"; sourceTree = "SOURCE_ROOT"; };
+		294B78ADA337603DE3C87BF9 = { isa = PBXFileReference; lastKnownFileType = image.png; name = "PipelineA-02.png"; path = "../../Resources/Images/Buttons/PipelineA-02.png"; sourceTree = "SOURCE_ROOT"; };
+		8AD9A0F023B727B34348B95E = { isa = PBXFileReference; lastKnownFileType = image.png; name = "PipelineB-01.png"; path = "../../Resources/Images/Buttons/PipelineB-01.png"; sourceTree = "SOURCE_ROOT"; };
+		89CF25CB48EEA21B226869E1 = { isa = PBXFileReference; lastKnownFileType = image.png; name = "PipelineB-02.png"; path = "../../Resources/Images/Buttons/PipelineB-02.png"; sourceTree = "SOURCE_ROOT"; };
+		CA0A1584725D21237DBCD70A = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = AccessClass.cpp; path = ../../Source/AccessClass.cpp; sourceTree = "SOURCE_ROOT"; };
+		63992CB3AC42F91A51135EAC = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = AccessClass.h; path = ../../Source/AccessClass.h; sourceTree = "SOURCE_ROOT"; };
+		673778A175624FC9F52E7A15 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = PracticalSocket.cpp; path = ../../Source/Network/PracticalSocket.cpp; sourceTree = "SOURCE_ROOT"; };
+		2EAE0475B719C3233AD8BB35 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = PracticalSocket.h; path = ../../Source/Network/PracticalSocket.h; sourceTree = "SOURCE_ROOT"; };
+		B30EF131FE61BAA4C1818102 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = Bessel.cpp; path = ../../Source/Dsp/Bessel.cpp; sourceTree = "SOURCE_ROOT"; };
+		D55947E71EB4AF25C1FC7089 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = Bessel.h; path = ../../Source/Dsp/Bessel.h; sourceTree = "SOURCE_ROOT"; };
+		07AE46453303977ED64E38ED = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = Biquad.cpp; path = ../../Source/Dsp/Biquad.cpp; sourceTree = "SOURCE_ROOT"; };
+		9EBBC43B9522EC9E6B607493 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = Biquad.h; path = ../../Source/Dsp/Biquad.h; sourceTree = "SOURCE_ROOT"; };
+		73C6FF74D6A31CA13C0D7C5C = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = Butterworth.cpp; path = ../../Source/Dsp/Butterworth.cpp; sourceTree = "SOURCE_ROOT"; };
+		8B70886CFCD13A761567DE7B = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = Butterworth.h; path = ../../Source/Dsp/Butterworth.h; sourceTree = "SOURCE_ROOT"; };
+		742284C84C72C882E02E7974 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = Cascade.cpp; path = ../../Source/Dsp/Cascade.cpp; sourceTree = "SOURCE_ROOT"; };
+		2B8E059E57EB92EAC589C6B4 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = Cascade.h; path = ../../Source/Dsp/Cascade.h; sourceTree = "SOURCE_ROOT"; };
+		D44DBE2FF15A98834F222766 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = ChebyshevI.cpp; path = ../../Source/Dsp/ChebyshevI.cpp; sourceTree = "SOURCE_ROOT"; };
+		553E92DB60C7D5104B780781 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = ChebyshevI.h; path = ../../Source/Dsp/ChebyshevI.h; sourceTree = "SOURCE_ROOT"; };
+		1F9836FC5A8FDF2293C9A232 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = ChebyshevII.cpp; path = ../../Source/Dsp/ChebyshevII.cpp; sourceTree = "SOURCE_ROOT"; };
+		833030703B66CDD9DA94155B = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = ChebyshevII.h; path = ../../Source/Dsp/ChebyshevII.h; sourceTree = "SOURCE_ROOT"; };
+		F7620D8D567CCE463ADDE0A6 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = Common.h; path = ../../Source/Dsp/Common.h; sourceTree = "SOURCE_ROOT"; };
+		93FACAE1DC7A236505359477 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = Custom.cpp; path = ../../Source/Dsp/Custom.cpp; sourceTree = "SOURCE_ROOT"; };
+		E4AEAC4AD1D1C6A80A2CD70A = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = Custom.h; path = ../../Source/Dsp/Custom.h; sourceTree = "SOURCE_ROOT"; };
+		3E8E2F9C583077B298525FD1 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = Design.cpp; path = ../../Source/Dsp/Design.cpp; sourceTree = "SOURCE_ROOT"; };
+		CD05957EC804348231739108 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = Design.h; path = ../../Source/Dsp/Design.h; sourceTree = "SOURCE_ROOT"; };
+		E8214D83845C25F39EEC13CD = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = Documentation.cpp; path = ../../Source/Dsp/Documentation.cpp; sourceTree = "SOURCE_ROOT"; };
+		21E5288817625724406FD3A1 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = Dsp.h; path = ../../Source/Dsp/Dsp.h; sourceTree = "SOURCE_ROOT"; };
+		293B003BD6E113C5AD1BB131 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = Elliptic.cpp; path = ../../Source/Dsp/Elliptic.cpp; sourceTree = "SOURCE_ROOT"; };
+		60F060DBD5ACF36E0A407BC1 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = Elliptic.h; path = ../../Source/Dsp/Elliptic.h; sourceTree = "SOURCE_ROOT"; };
+		A9AF10F6A89F85989C62F856 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = Filter.cpp; path = ../../Source/Dsp/Filter.cpp; sourceTree = "SOURCE_ROOT"; };
+		7C225F446A96BED7F585F66B = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = Filter.h; path = ../../Source/Dsp/Filter.h; sourceTree = "SOURCE_ROOT"; };
+		314D53C7C13C28A25588ABCF = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = Layout.h; path = ../../Source/Dsp/Layout.h; sourceTree = "SOURCE_ROOT"; };
+		706CBE9178440675868F2379 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = Legendre.cpp; path = ../../Source/Dsp/Legendre.cpp; sourceTree = "SOURCE_ROOT"; };
+		1EC547C25C29FE679BAF8B4D = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = Legendre.h; path = ../../Source/Dsp/Legendre.h; sourceTree = "SOURCE_ROOT"; };
+		4D63E86C8A9F721B9C0FA95E = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = MathSupplement.h; path = ../../Source/Dsp/MathSupplement.h; sourceTree = "SOURCE_ROOT"; };
+		BF8EB3483F66AA7F61E6D863 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = Param.cpp; path = ../../Source/Dsp/Param.cpp; sourceTree = "SOURCE_ROOT"; };
+		1E0F3076D1689E83422F6B4E = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = Params.h; path = ../../Source/Dsp/Params.h; sourceTree = "SOURCE_ROOT"; };
+		137CF1AB4144076D79D50975 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = PoleFilter.cpp; path = ../../Source/Dsp/PoleFilter.cpp; sourceTree = "SOURCE_ROOT"; };
+		5B1D08D98AD9F623962A38B2 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = PoleFilter.h; path = ../../Source/Dsp/PoleFilter.h; sourceTree = "SOURCE_ROOT"; };
+		E6FF4D4C70794123A52B9E82 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = RBJ.cpp; path = ../../Source/Dsp/RBJ.cpp; sourceTree = "SOURCE_ROOT"; };
+		E8503A3E123FCFBFA317EAE6 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = RBJ.h; path = ../../Source/Dsp/RBJ.h; sourceTree = "SOURCE_ROOT"; };
+		F4A53064BA75472765338C1D = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = RootFinder.cpp; path = ../../Source/Dsp/RootFinder.cpp; sourceTree = "SOURCE_ROOT"; };
+		1D1DF895F34C981407EDB8E8 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = RootFinder.h; path = ../../Source/Dsp/RootFinder.h; sourceTree = "SOURCE_ROOT"; };
+		1F5435604926FF2C06575DCC = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SmoothedFilter.h; path = ../../Source/Dsp/SmoothedFilter.h; sourceTree = "SOURCE_ROOT"; };
+		0D20C3399D0492771F7A808A = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = State.cpp; path = ../../Source/Dsp/State.cpp; sourceTree = "SOURCE_ROOT"; };
+		186F011C1ABC55DB39717105 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = State.h; path = ../../Source/Dsp/State.h; sourceTree = "SOURCE_ROOT"; };
+		92C241C7F87B5933B0E6E03F = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = Types.h; path = ../../Source/Dsp/Types.h; sourceTree = "SOURCE_ROOT"; };
+		E27B5891A52FDAB2B00901A0 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = Utilities.h; path = ../../Source/Dsp/Utilities.h; sourceTree = "SOURCE_ROOT"; };
+		F74662D3D82975EDB5AD42E0 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = AudioComponent.cpp; path = ../../Source/Audio/AudioComponent.cpp; sourceTree = "SOURCE_ROOT"; };
+		FA55B9FDE138CCB1F16BA905 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = AudioComponent.h; path = ../../Source/Audio/AudioComponent.h; sourceTree = "SOURCE_ROOT"; };
+		4AEDD076CCA918481C6F9CF2 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = SpikeDisplayNode.cpp; path = ../../Source/Processors/SpikeDisplayNode.cpp; sourceTree = "SOURCE_ROOT"; };
+		671CC5EA3DF4F21E9A7E392B = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SpikeDisplayNode.h; path = ../../Source/Processors/SpikeDisplayNode.h; sourceTree = "SOURCE_ROOT"; };
+		268005410FB62BCB9099A762 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = WiFiOutput.cpp; path = ../../Source/Processors/WiFiOutput.cpp; sourceTree = "SOURCE_ROOT"; };
+		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"; };
+		C92B3F413B0F24752ADE6730 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = StereotrodePlot.cpp; path = ../../Source/Processors/Visualization/SpikePlotting/StereotrodePlot.cpp; sourceTree = "SOURCE_ROOT"; };
+		FDD549F527C378CF36BDB8C7 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = StereotrodePlot.h; path = ../../Source/Processors/Visualization/SpikePlotting/StereotrodePlot.h; sourceTree = "SOURCE_ROOT"; };
+		3BB44F767E701E3642435FA0 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = ElectrodePlot.cpp; path = ../../Source/Processors/Visualization/SpikePlotting/ElectrodePlot.cpp; sourceTree = "SOURCE_ROOT"; };
+		1AAF672654B16469EFB41AC2 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = ElectrodePlot.h; path = ../../Source/Processors/Visualization/SpikePlotting/ElectrodePlot.h; sourceTree = "SOURCE_ROOT"; };
+		41591F74A761BAC908FA8AD8 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = BaseUIElement.cpp; path = ../../Source/Processors/Visualization/SpikePlotting/BaseUIElement.cpp; sourceTree = "SOURCE_ROOT"; };
+		9C8EA29582DBFF6E5A14B8A3 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = BaseUIElement.h; path = ../../Source/Processors/Visualization/SpikePlotting/BaseUIElement.h; sourceTree = "SOURCE_ROOT"; };
+		24C6D768C87E1C42C644C4BD = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = GenericAxes.cpp; path = ../../Source/Processors/Visualization/SpikePlotting/GenericAxes.cpp; sourceTree = "SOURCE_ROOT"; };
+		BCBB865ED53E8AFD278D1A53 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = GenericAxes.h; path = ../../Source/Processors/Visualization/SpikePlotting/GenericAxes.h; sourceTree = "SOURCE_ROOT"; };
+		B195AD6CEB9B6E3625C8D087 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = PlotUtils.cpp; path = ../../Source/Processors/Visualization/SpikePlotting/PlotUtils.cpp; sourceTree = "SOURCE_ROOT"; };
+		521FECC75E9DDB0D34B22AF8 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = PlotUtils.h; path = ../../Source/Processors/Visualization/SpikePlotting/PlotUtils.h; sourceTree = "SOURCE_ROOT"; };
+		2FA2FA826CBAD9C639A61E4A = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = ProjectionAxes.cpp; path = ../../Source/Processors/Visualization/SpikePlotting/ProjectionAxes.cpp; sourceTree = "SOURCE_ROOT"; };
+		B1CF7BFC5F1892735D4FA1EE = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = ProjectionAxes.h; path = ../../Source/Processors/Visualization/SpikePlotting/ProjectionAxes.h; sourceTree = "SOURCE_ROOT"; };
+		50E7B88E8140BB293B27ED67 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SimpleKeyEvent.h; path = ../../Source/Processors/Visualization/SpikePlotting/SimpleKeyEvent.h; sourceTree = "SOURCE_ROOT"; };
+		FBB9A423728922E96F55074F = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = TetrodePlot.cpp; path = ../../Source/Processors/Visualization/SpikePlotting/TetrodePlot.cpp; sourceTree = "SOURCE_ROOT"; };
+		6CFF95D08DB1000B1EDD1240 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = TetrodePlot.h; path = ../../Source/Processors/Visualization/SpikePlotting/TetrodePlot.h; sourceTree = "SOURCE_ROOT"; };
+		7A9571EBFAAD39E47DE12A10 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = TitleBox.cpp; path = ../../Source/Processors/Visualization/SpikePlotting/TitleBox.cpp; sourceTree = "SOURCE_ROOT"; };
+		180386FCFC4315DCB499E837 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = TitleBox.h; path = ../../Source/Processors/Visualization/SpikePlotting/TitleBox.h; sourceTree = "SOURCE_ROOT"; };
+		9F208A66C09E80D14F087CB1 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = WaveAxes.cpp; path = ../../Source/Processors/Visualization/SpikePlotting/WaveAxes.cpp; sourceTree = "SOURCE_ROOT"; };
+		A3F978AE6999903C47650173 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = WaveAxes.h; path = ../../Source/Processors/Visualization/SpikePlotting/WaveAxes.h; sourceTree = "SOURCE_ROOT"; };
+		E7247F5EE9588903C924994F = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = SpikeObject.cpp; path = ../../Source/Processors/Visualization/SpikeObject.cpp; sourceTree = "SOURCE_ROOT"; };
+		B0A6A0635113C4B4CD424BEC = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SpikeObject.h; path = ../../Source/Processors/Visualization/SpikeObject.h; sourceTree = "SOURCE_ROOT"; };
+		7A9A31FC1AE8FB238FAE995E = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = SpikeDisplayCanvas.cpp; path = ../../Source/Processors/Visualization/SpikeDisplayCanvas.cpp; sourceTree = "SOURCE_ROOT"; };
+		9E884AEDB6035FFC74886EE8 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SpikeDisplayCanvas.h; path = ../../Source/Processors/Visualization/SpikeDisplayCanvas.h; sourceTree = "SOURCE_ROOT"; };
+		9ACFB6A181D09434268CE006 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = Visualizer.h; path = ../../Source/Processors/Visualization/Visualizer.h; sourceTree = "SOURCE_ROOT"; };
+		ED179D5A10DD051DDB3ECB8B = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = DataWindow.cpp; path = ../../Source/Processors/Visualization/DataWindow.cpp; sourceTree = "SOURCE_ROOT"; };
+		63C18F4066C75D3C312877D8 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = DataWindow.h; path = ../../Source/Processors/Visualization/DataWindow.h; sourceTree = "SOURCE_ROOT"; };
+		2E96DA81EE37A0ECE471A928 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = LfpDisplayCanvas.cpp; path = ../../Source/Processors/Visualization/LfpDisplayCanvas.cpp; sourceTree = "SOURCE_ROOT"; };
+		A9C2C7AF037050228CD2E026 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = LfpDisplayCanvas.h; path = ../../Source/Processors/Visualization/LfpDisplayCanvas.h; sourceTree = "SOURCE_ROOT"; };
+		0C5335B0E57C9DC92FC57E5F = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = OpenGLCanvas.cpp; path = ../../Source/Processors/Visualization/OpenGLCanvas.cpp; sourceTree = "SOURCE_ROOT"; };
+		7738F51AE0EC63D76EE0F761 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = OpenGLCanvas.h; path = ../../Source/Processors/Visualization/OpenGLCanvas.h; sourceTree = "SOURCE_ROOT"; };
+		3DD0741FCFBC7563EC722D9B = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = SpikeDetector.cpp; path = ../../Source/Processors/SpikeDetector.cpp; sourceTree = "SOURCE_ROOT"; };
+		6E4B37AA4BFEB5A37E3AC250 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SpikeDetector.h; path = ../../Source/Processors/SpikeDetector.h; sourceTree = "SOURCE_ROOT"; };
+		B7750B27E4F3748ECCCCF69D = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = AudioNode.cpp; path = ../../Source/Processors/AudioNode.cpp; sourceTree = "SOURCE_ROOT"; };
+		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"; };
+		F0B09605D4108F0F94EF3B57 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = SpikeDisplayEditor.cpp; path = ../../Source/Processors/Editors/SpikeDisplayEditor.cpp; sourceTree = "SOURCE_ROOT"; };
+		2A46D8E3EC7207D969A2B202 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SpikeDisplayEditor.h; path = ../../Source/Processors/Editors/SpikeDisplayEditor.h; sourceTree = "SOURCE_ROOT"; };
+		9A3976537C96B39716B5312D = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = VisualizerEditor.cpp; path = ../../Source/Processors/Editors/VisualizerEditor.cpp; sourceTree = "SOURCE_ROOT"; };
+		C546D55EDE65ADDD95C6A6F5 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = VisualizerEditor.h; path = ../../Source/Processors/Editors/VisualizerEditor.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"; };
+		4E67CFE458501E763FF3AE94 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = WiFiOutputEditor.h; path = ../../Source/Processors/Editors/WiFiOutputEditor.h; sourceTree = "SOURCE_ROOT"; };
+		36393F2D58480F61ECDEB5E5 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = EventNodeEditor.cpp; path = ../../Source/Processors/Editors/EventNodeEditor.cpp; sourceTree = "SOURCE_ROOT"; };
+		A80433BF9686B4E2542C580C = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = EventNodeEditor.h; path = ../../Source/Processors/Editors/EventNodeEditor.h; sourceTree = "SOURCE_ROOT"; };
+		087136FA6A7A0E01738EEF03 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = SignalGeneratorEditor.cpp; path = ../../Source/Processors/Editors/SignalGeneratorEditor.cpp; sourceTree = "SOURCE_ROOT"; };
+		10F82563E4A633BC234B2800 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SignalGeneratorEditor.h; path = ../../Source/Processors/Editors/SignalGeneratorEditor.h; sourceTree = "SOURCE_ROOT"; };
+		CF9878CE31A1B41406C3457B = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = LfpDisplayEditor.cpp; path = ../../Source/Processors/Editors/LfpDisplayEditor.cpp; sourceTree = "SOURCE_ROOT"; };
+		C02C160190E417B42F73680A = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = LfpDisplayEditor.h; path = ../../Source/Processors/Editors/LfpDisplayEditor.h; sourceTree = "SOURCE_ROOT"; };
+		FC5939F3D2A31BB43EA3E393 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = SourceNodeEditor.cpp; path = ../../Source/Processors/Editors/SourceNodeEditor.cpp; sourceTree = "SOURCE_ROOT"; };
+		62DA962299323A2FA134203D = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SourceNodeEditor.h; path = ../../Source/Processors/Editors/SourceNodeEditor.h; sourceTree = "SOURCE_ROOT"; };
+		C2ED801EA28FBA9764E76349 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = SplitterEditor.cpp; path = ../../Source/Processors/Editors/SplitterEditor.cpp; sourceTree = "SOURCE_ROOT"; };
+		C177B371A0CEC8E7B9131865 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SplitterEditor.h; path = ../../Source/Processors/Editors/SplitterEditor.h; sourceTree = "SOURCE_ROOT"; };
+		399CBACE291A425A2B9497EF = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = SpikeDetectorEditor.cpp; path = ../../Source/Processors/Editors/SpikeDetectorEditor.cpp; sourceTree = "SOURCE_ROOT"; };
+		7FC3C64A06A9FA2C828F8744 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SpikeDetectorEditor.h; path = ../../Source/Processors/Editors/SpikeDetectorEditor.h; sourceTree = "SOURCE_ROOT"; };
+		5DDBEE64DC706CE804E5F0AA = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = AudioEditor.cpp; path = ../../Source/Processors/Editors/AudioEditor.cpp; sourceTree = "SOURCE_ROOT"; };
+		303B2522EAC7CD3C33EF150C = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = AudioEditor.h; path = ../../Source/Processors/Editors/AudioEditor.h; sourceTree = "SOURCE_ROOT"; };
+		35AFD01064BF29D90EEDF413 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = FilterEditor.cpp; path = ../../Source/Processors/Editors/FilterEditor.cpp; sourceTree = "SOURCE_ROOT"; };
+		AD4BF1BC602902B20AEBF49C = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = FilterEditor.h; path = ../../Source/Processors/Editors/FilterEditor.h; sourceTree = "SOURCE_ROOT"; };
+		22FD0613BADE6C36A6A7A25C = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = GenericEditor.cpp; path = ../../Source/Processors/Editors/GenericEditor.cpp; sourceTree = "SOURCE_ROOT"; };
+		F0B8C75B1AA6E8D1BC620653 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = GenericEditor.h; path = ../../Source/Processors/Editors/GenericEditor.h; sourceTree = "SOURCE_ROOT"; };
+		0D2903C450AE862C2C0060AA = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = FileReaderThread.cpp; path = ../../Source/Processors/DataThreads/FileReaderThread.cpp; sourceTree = "SOURCE_ROOT"; };
+		BD07C36AC2ECF10942F0A229 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = FileReaderThread.h; path = ../../Source/Processors/DataThreads/FileReaderThread.h; sourceTree = "SOURCE_ROOT"; };
+		24616D6D2297C87D371B0363 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = okFrontPanelDLL.cpp; path = ../../Source/Processors/DataThreads/okFrontPanelDLL.cpp; sourceTree = "SOURCE_ROOT"; };
+		AA7B88F969CE43331035DE98 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = okFrontPanelDLL.h; path = ../../Source/Processors/DataThreads/okFrontPanelDLL.h; sourceTree = "SOURCE_ROOT"; };
+		6B156D132738F6C7C948378F = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = NetworkThread.cpp; path = ../../Source/Processors/DataThreads/NetworkThread.cpp; sourceTree = "SOURCE_ROOT"; };
+		7BD204C890F9A2F301B15128 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = NetworkThread.h; path = ../../Source/Processors/DataThreads/NetworkThread.h; sourceTree = "SOURCE_ROOT"; };
+		A9142BFEFE7EB34D919ED0A0 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = FPGAThread.cpp; path = ../../Source/Processors/DataThreads/FPGAThread.cpp; sourceTree = "SOURCE_ROOT"; };
+		46E436D1B9538DB8487F0D8D = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = FPGAThread.h; path = ../../Source/Processors/DataThreads/FPGAThread.h; sourceTree = "SOURCE_ROOT"; };
+		F20726FD9F586FDE2CB42901 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = DataBuffer.cpp; path = ../../Source/Processors/DataThreads/DataBuffer.cpp; sourceTree = "SOURCE_ROOT"; };
+		F062CCE0FB40E6C65A6493F4 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = DataBuffer.h; path = ../../Source/Processors/DataThreads/DataBuffer.h; sourceTree = "SOURCE_ROOT"; };
+		6D94C2733E967EC6A91B719A = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = IntanThread.cpp; path = ../../Source/Processors/DataThreads/IntanThread.cpp; sourceTree = "SOURCE_ROOT"; };
+		21C560B017F1C0A48B950155 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = IntanThread.h; path = ../../Source/Processors/DataThreads/IntanThread.h; sourceTree = "SOURCE_ROOT"; };
+		72123888A7DD78159AA032AF = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = DataThread.cpp; path = ../../Source/Processors/DataThreads/DataThread.cpp; sourceTree = "SOURCE_ROOT"; };
+		2164BFCDF57A5AA752CAA3A2 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = DataThread.h; path = ../../Source/Processors/DataThreads/DataThread.h; sourceTree = "SOURCE_ROOT"; };
+		B96BF02034F29DE033F16D89 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = RecordNode.cpp; path = ../../Source/Processors/RecordNode.cpp; sourceTree = "SOURCE_ROOT"; };
+		FC83C3CD6DC717911B2C3C20 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = RecordNode.h; path = ../../Source/Processors/RecordNode.h; sourceTree = "SOURCE_ROOT"; };
+		EBB0E5058615EA1FEDADF189 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = SignalGenerator.cpp; path = ../../Source/Processors/SignalGenerator.cpp; sourceTree = "SOURCE_ROOT"; };
+		E0883576683119727BD54A81 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SignalGenerator.h; path = ../../Source/Processors/SignalGenerator.h; sourceTree = "SOURCE_ROOT"; };
+		5AE7693391C43B4AE475789C = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = ResamplingNode.cpp; path = ../../Source/Processors/ResamplingNode.cpp; sourceTree = "SOURCE_ROOT"; };
+		C87B84BA79CB9EE547E8762C = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = ResamplingNode.h; path = ../../Source/Processors/ResamplingNode.h; sourceTree = "SOURCE_ROOT"; };
+		D2342EA3BD783D3A81006606 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = FilterNode.cpp; path = ../../Source/Processors/FilterNode.cpp; sourceTree = "SOURCE_ROOT"; };
+		2CCD3BBDF86EA8D149DAD758 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = FilterNode.h; path = ../../Source/Processors/FilterNode.h; sourceTree = "SOURCE_ROOT"; };
+		7EAD8082130C2384BA9E1206 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = SourceNode.cpp; path = ../../Source/Processors/SourceNode.cpp; sourceTree = "SOURCE_ROOT"; };
+		7BD1C1A7C30ED736F4816C31 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SourceNode.h; path = ../../Source/Processors/SourceNode.h; sourceTree = "SOURCE_ROOT"; };
+		CECE2AB5D5F36CADBC3219A2 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = GenericProcessor.cpp; path = ../../Source/Processors/GenericProcessor.cpp; sourceTree = "SOURCE_ROOT"; };
+		C4197FDA1B4D4F1D58F6A5A0 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = GenericProcessor.h; path = ../../Source/Processors/GenericProcessor.h; sourceTree = "SOURCE_ROOT"; };
+		C4DA9685E5637B03F00E5E79 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = ProcessorGraph.cpp; path = ../../Source/Processors/ProcessorGraph.cpp; sourceTree = "SOURCE_ROOT"; };
+		3B60787E97C74E78853DC90F = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = ProcessorGraph.h; path = ../../Source/Processors/ProcessorGraph.h; sourceTree = "SOURCE_ROOT"; };
+		E1C6E67757EC5D68093BD760 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = EditorViewportButtons.cpp; path = ../../Source/UI/EditorViewportButtons.cpp; sourceTree = "SOURCE_ROOT"; };
+		2BC65E923E245AE23AE7BB8B = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = EditorViewportButtons.h; path = ../../Source/UI/EditorViewportButtons.h; sourceTree = "SOURCE_ROOT"; };
+		6CD0D896FEB77B261C62447E = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = SignalChainManager.cpp; path = ../../Source/UI/SignalChainManager.cpp; sourceTree = "SOURCE_ROOT"; };
+		182F8F9073A2007403C10C51 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SignalChainManager.h; path = ../../Source/UI/SignalChainManager.h; sourceTree = "SOURCE_ROOT"; };
+		EB824B60F600C19193ADFA5F = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = EditorViewport.cpp; path = ../../Source/UI/EditorViewport.cpp; sourceTree = "SOURCE_ROOT"; };
+		54A33424E41D55153F6EB422 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = EditorViewport.h; path = ../../Source/UI/EditorViewport.h; sourceTree = "SOURCE_ROOT"; };
+		B28CC9409188C9A200AAAFFC = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = ProcessorList.cpp; path = ../../Source/UI/ProcessorList.cpp; sourceTree = "SOURCE_ROOT"; };
+		242E7E62B8641B1224E25442 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = ProcessorList.h; path = ../../Source/UI/ProcessorList.h; sourceTree = "SOURCE_ROOT"; };
+		A32D8455B95FD230EBFD7891 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = CustomLookAndFeel.cpp; path = ../../Source/UI/CustomLookAndFeel.cpp; sourceTree = "SOURCE_ROOT"; };
+		F70641473A3E7C0DC5168858 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = CustomLookAndFeel.h; path = ../../Source/UI/CustomLookAndFeel.h; sourceTree = "SOURCE_ROOT"; };
+		AA00883DC021E36B7EFDAC43 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = InfoLabel.cpp; path = ../../Source/UI/InfoLabel.cpp; sourceTree = "SOURCE_ROOT"; };
+		1561F28CD560AB8F2E177628 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = InfoLabel.h; path = ../../Source/UI/InfoLabel.h; sourceTree = "SOURCE_ROOT"; };
+		B977C2809B309C8038CB5D95 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = DataViewport.cpp; path = ../../Source/UI/DataViewport.cpp; sourceTree = "SOURCE_ROOT"; };
+		877F9F9DA7A1B51D3EDCBC07 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = DataViewport.h; path = ../../Source/UI/DataViewport.h; sourceTree = "SOURCE_ROOT"; };
+		2F53BB2693AA5F1C2F27AF7C = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = Configuration.cpp; path = ../../Source/UI/Configuration.cpp; sourceTree = "SOURCE_ROOT"; };
+		DE21954E89A302C554C403B3 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = Configuration.h; path = ../../Source/UI/Configuration.h; sourceTree = "SOURCE_ROOT"; };
+		EEDA71600D817BF9444FE3E7 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = MessageCenter.cpp; path = ../../Source/UI/MessageCenter.cpp; sourceTree = "SOURCE_ROOT"; };
+		4EE6CA70F229EDE04E7E320B = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = MessageCenter.h; path = ../../Source/UI/MessageCenter.h; sourceTree = "SOURCE_ROOT"; };
+		5AB4A3A63B9FDEAB09EEC9C8 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = ControlPanel.cpp; path = ../../Source/UI/ControlPanel.cpp; sourceTree = "SOURCE_ROOT"; };
+		3B70B21129D91B16A2F1CE80 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = ControlPanel.h; path = ../../Source/UI/ControlPanel.h; sourceTree = "SOURCE_ROOT"; };
+		2A78F719BAFBDCD63AE9A88A = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = UIComponent.cpp; path = ../../Source/UI/UIComponent.cpp; sourceTree = "SOURCE_ROOT"; };
+		DB605BA15852F367DF625300 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = UIComponent.h; path = ../../Source/UI/UIComponent.h; sourceTree = "SOURCE_ROOT"; };
+		77F2E2E7A2419CB172C0B1EA = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = MainWindow.cpp; path = ../../Source/MainWindow.cpp; sourceTree = "SOURCE_ROOT"; };
+		3E3E4F25C71B800C97AC63B9 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = MainWindow.h; path = ../../Source/MainWindow.h; sourceTree = "SOURCE_ROOT"; };
+		19D5134F99CC551B01D5A7EF = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = Main.cpp; path = ../../Source/Main.cpp; sourceTree = "SOURCE_ROOT"; };
+		BDB56CA7F08DC7EFABBF7846 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = AppConfig.h; path = ../../JuceLibraryCode/AppConfig.h; sourceTree = "SOURCE_ROOT"; };
+		753133530248EC4F00CBECA6 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = JuceHeader.h; path = ../../JuceLibraryCode/JuceHeader.h; sourceTree = "SOURCE_ROOT"; };
+		B56D08AB6374C811F59D760C = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = BinaryData.cpp; path = ../../JuceLibraryCode/BinaryData.cpp; sourceTree = "SOURCE_ROOT"; };
+		9BFC7532965901165C9DDB07 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = BinaryData.h; path = ../../JuceLibraryCode/BinaryData.h; sourceTree = "SOURCE_ROOT"; };
+		898385F65E64BF6D609B3BF2 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; name = JuceLibraryCode1.mm; path = ../../JuceLibraryCode/JuceLibraryCode1.mm; sourceTree = "SOURCE_ROOT"; };
+		C3B95EF26B5F3281447FCF42 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; name = JuceLibraryCode2.mm; path = ../../JuceLibraryCode/JuceLibraryCode2.mm; sourceTree = "SOURCE_ROOT"; };
+		1CD026FD773BB5A428624381 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; name = JuceLibraryCode3.mm; path = ../../JuceLibraryCode/JuceLibraryCode3.mm; sourceTree = "SOURCE_ROOT"; };
+		55F7FFF9942627D7FC46C6C1 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; name = JuceLibraryCode4.mm; path = ../../JuceLibraryCode/JuceLibraryCode4.mm; sourceTree = "SOURCE_ROOT"; };
 		2D8E1C366F21D3C8FE662382 = { isa = PBXGroup; children = (
 				79892A4E41809A09A4711AC3,
 				1B2C20F6F1F1BCF9115F8D53,
@@ -379,7 +419,32 @@
 				7977CAB4A151C41F4140FE1A,
 				9A47B52E5E1CD17DC9C72B53,
 				B92E8189F69E0B926C73B654 ); name = Utilities; sourceTree = "<group>"; };
+		1255E9B28ADAA1A1CADC4A6E = { isa = PBXGroup; children = (
+				C92B3F413B0F24752ADE6730,
+				FDD549F527C378CF36BDB8C7,
+				3BB44F767E701E3642435FA0,
+				1AAF672654B16469EFB41AC2,
+				41591F74A761BAC908FA8AD8,
+				9C8EA29582DBFF6E5A14B8A3,
+				24C6D768C87E1C42C644C4BD,
+				BCBB865ED53E8AFD278D1A53,
+				B195AD6CEB9B6E3625C8D087,
+				521FECC75E9DDB0D34B22AF8,
+				2FA2FA826CBAD9C639A61E4A,
+				B1CF7BFC5F1892735D4FA1EE,
+				50E7B88E8140BB293B27ED67,
+				FBB9A423728922E96F55074F,
+				6CFF95D08DB1000B1EDD1240,
+				7A9571EBFAAD39E47DE12A10,
+				180386FCFC4315DCB499E837,
+				9F208A66C09E80D14F087CB1,
+				A3F978AE6999903C47650173 ); name = SpikePlotting; sourceTree = "<group>"; };
 		15543D7982B26B70879960F4 = { isa = PBXGroup; children = (
+				1255E9B28ADAA1A1CADC4A6E,
+				E7247F5EE9588903C924994F,
+				B0A6A0635113C4B4CD424BEC,
+				7A9A31FC1AE8FB238FAE995E,
+				9E884AEDB6035FFC74886EE8,
 				9ACFB6A181D09434268CE006,
 				ED179D5A10DD051DDB3ECB8B,
 				63C18F4066C75D3C312877D8,
@@ -388,6 +453,8 @@
 				0C5335B0E57C9DC92FC57E5F,
 				7738F51AE0EC63D76EE0F761 ); name = Visualization; sourceTree = "<group>"; };
 		953CC35B9116404D6AA8D1C7 = { isa = PBXGroup; children = (
+				F0B09605D4108F0F94EF3B57,
+				2A46D8E3EC7207D969A2B202,
 				9A3976537C96B39716B5312D,
 				C546D55EDE65ADDD95C6A6F5,
 				AD73EA6B24378294003DC2D0,
@@ -430,6 +497,8 @@
 				72123888A7DD78159AA032AF,
 				2164BFCDF57A5AA752CAA3A2 ); name = DataThreads; sourceTree = "<group>"; };
 		33A88A7C3FF426F051834D6A = { isa = PBXGroup; children = (
+				4AEDD076CCA918481C6F9CF2,
+				671CC5EA3DF4F21E9A7E392B,
 				268005410FB62BCB9099A762,
 				32959675287F77DD9B7FA96B,
 				5935F823A2EE45AC36A0201F,
@@ -526,9 +595,8 @@
 				F3C957A2F364B760F6959DE9,
 				0ECE243E52A42297D09AE145 ); name = Source; sourceTree = "<group>"; };
 		C3E8FB47D6069235EA9D6FD7 = { isa = XCBuildConfiguration; buildSettings = {
-				ARCHS = "$(ARCHS_STANDARD_32_BIT)";
 				PREBINDING = NO;
-				HEADER_SEARCH_PATHS = "/usr/local/include /usr/local/include/freetype2 $(inherited)";
+				HEADER_SEARCH_PATHS = " $(inherited)";
 				GCC_OPTIMIZATION_LEVEL = 0;
 				INFOPLIST_FILE = Info.plist;
 				INSTALL_PATH = "$(HOME)/Applications";
@@ -541,11 +609,11 @@
 				GCC_PREPROCESSOR_DEFINITIONS = (
 				"_DEBUG=1",
 				"DEBUG=1",
+				"JUCE_ObjCExtraSuffix=fea2mT",
 				"JUCER_XCODE_MAC_F6D2F4CF=1"); }; name = Debug; };
 		5D7484BAF16E272FF0E9EEAE = { isa = XCBuildConfiguration; buildSettings = {
-				ARCHS = "$(ARCHS_STANDARD_32_BIT)";
 				PREBINDING = NO;
-				HEADER_SEARCH_PATHS = "/usr/local/include /usr/local/include/freetype2 $(inherited)";
+				HEADER_SEARCH_PATHS = " $(inherited)";
 				GCC_OPTIMIZATION_LEVEL = 3;
 				INFOPLIST_FILE = Info.plist;
 				INSTALL_PATH = "$(HOME)/Applications";
@@ -556,6 +624,7 @@
 				GCC_PREPROCESSOR_DEFINITIONS = (
 				"_NDEBUG=1",
 				"NDEBUG=1",
+				"JUCE_ObjCExtraSuffix=fea2mT",
 				"JUCER_XCODE_MAC_F6D2F4CF=1"); }; name = Release; };
 		4E274274B609972E0988736B = { isa = XCBuildConfiguration; buildSettings = {
 				ALWAYS_SEARCH_USER_PATHS = NO;
@@ -615,16 +684,29 @@
 				8E138283FC265B58D252AAC3,
 				EE1DC0B09AE0727BC7A5A99C,
 				4ACF816CB5CDB285D8005AB8,
+				1F67A9ACD509FB4DC5A633DF,
 				B992DDBFF8928A985EEE1557,
 				F1268EC5E783EC8ECEBCA5D3,
 				4A00153E1E69A74BC6B7D8A6,
 				5F13B8FFB1584BFF6C05AD39,
+				B11D72764B1B17BF2B8C6E67,
+				938FC2F779C2CF4B8C7ECFFE,
+				55A240CCFCD604CA8DF8FC8C,
+				8025F04ED261C7F7D2DC0F06,
+				49F046C8BE137BF77338DD7B,
+				566E42D2B7105CFB4DB45170,
+				0DDC562EC2B04A26AE6CBB2B,
+				39E2F4E31D24BED6E85C489D,
+				BCD7C4797178C8EF65CDC2D7,
+				9145D84C7D665BCAFE698432,
+				7659F31912D12C91E9554909,
 				9D687F73F2FD2462C5D5588C,
 				B13883377C9316B9603336B4,
 				073B178E7EF1759BA0AACCCE,
 				4BE0DDA01B73223EF0BD934A,
 				08B501E0D7764C6B613AF529,
 				9CBA3837CC8CAA03A03F2D9C,
+				DD22A06702F4CF995893DD5C,
 				F4CEF74DDCD7EFA0891249B5,
 				93A3E6284F2DAED3F491332B,
 				CB77C89226102EF30F85E3EC,
@@ -686,7 +768,7 @@
 				7D11CCCE7B7FAA037837E9F0,
 				49B8C83C4A6BA460E2492EAD,
 				FDDDE8762356EE886B1C1C9E ); buildRules = ( ); dependencies = ( ); name = "open-ephys"; productName = "open-ephys"; productReference = 0837481AD187A1E6CBCAC577; productInstallPath = "$(HOME)/Applications"; productType = "com.apple.product-type.application"; };
-		CC82D4D2B9F0219708ACBEB3 = { isa = PBXProject; buildConfigurationList = FAAFAE9A22D4CD0A7BE65048; compatibilityVersion = "Xcode 3.0"; hasScannedForEncodings = 0; mainGroup = 4EC15B00A5B83F4BF29C25C5; projectDirPath = ""; projectRoot = ""; targets = ( C1E94289C8EA03969CA6896C ); };
+		CC82D4D2B9F0219708ACBEB3 = { isa = PBXProject; buildConfigurationList = FAAFAE9A22D4CD0A7BE65048; compatibilityVersion = "Xcode 3.1"; hasScannedForEncodings = 0; mainGroup = 4EC15B00A5B83F4BF29C25C5; projectDirPath = ""; projectRoot = ""; targets = ( C1E94289C8EA03969CA6896C ); };
 	};
 	rootObject = CC82D4D2B9F0219708ACBEB3;
 }
diff --git a/JuceLibraryCode/BinaryData.cpp b/JuceLibraryCode/BinaryData.cpp
index ab8f390247024fdd51802cc565d95c86cac9ee03..544723aab68b1b3fe23afd9618d314d6106342ef 100644
--- a/JuceLibraryCode/BinaryData.cpp
+++ b/JuceLibraryCode/BinaryData.cpp
@@ -1,6 +1,6 @@
 /* ==================================== JUCER_BINARY_RESOURCE ====================================
 
-   This is an auto-generated file, created by The Jucer V3.0.0
+   This is an auto-generated file, created by The Introjucer 3.0.0
    Do not edit anything in this file!
 
 */
@@ -54,7 +54,7 @@ const char* BinaryData::getNamedResource (const char* resourceNameUTF8, int& num
 
 
 //================== BebasNeue.otf ==================
-static const unsigned char temp_6bd12552[] =
+static const unsigned char temp_59bf0d54[] =
 { 79,84,84,79,0,11,0,128,0,3,0,48,67,70,70,32,57,136,64,140,0,0,39,76,0,0,70,154,71,80,79,83,223,12,110,56,0,0,116,248,0,0,73,16,71,83,85,66,114,203,114,178,0,0,116,0,0,0,0,246,79,83,47,50,102,169,27,20,0,0,1,32,0,0,0,96,99,109,97,112,211,17,247,228,0,
 0,35,232,0,0,3,68,104,101,97,100,243,84,238,113,0,0,0,188,0,0,0,54,104,104,101,97,6,215,3,186,0,0,0,244,0,0,0,36,104,109,116,120,67,128,39,22,0,0,109,232,0,0,6,24,109,97,120,112,1,134,80,0,0,0,1,24,0,0,0,6,110,97,109,101,230,56,31,140,0,0,1,128,0,0,34,
 101,112,111,115,116,255,184,0,50,0,0,39,44,0,0,0,32,0,1,0,0,0,1,0,131,131,184,68,27,95,15,60,245,0,3,3,232,0,0,0,0,200,111,85,40,0,0,0,0,200,111,85,40,255,119,255,60,3,232,3,130,0,0,0,3,0,2,0,0,0,0,0,0,0,1,0,0,2,188,254,212,0,185,3,232,255,119,255,119,
@@ -664,10 +664,10 @@ static const unsigned char temp_6bd12552[] =
 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3,0,10,0,3,0,10,0,3,0,10,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,22,0,24,0,22,0,24,0,22,0,24,0,22,0,24,0,4,0,11,0,4,0,11,0,4,0,11,0,23,0,25,0,23,0,25,0,23,0,25,0,23,0,25,0,23,0,25,0,23,0,25,0,5,0,12,0,6,0,13,0,6,0,19,
 0,21,0,19,0,21,0,19,0,21,0,15,0,17,0,3,0,10,0,22,0,24,0,4,0,11,0,20,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,22,0,24,0,4,0,11,0,5,0,12,0,5,0,12,0,5,0,12,0,6,0,13,0,0 };
 
-const char* BinaryData::BebasNeue_otf = (const char*) temp_6bd12552;
+const char* BinaryData::BebasNeue_otf = (const char*) temp_59bf0d54;
 
 //================== cpmono_bold.otf ==================
-static const unsigned char temp_9105132e[] =
+static const unsigned char temp_bb1902b0[] =
 { 79,84,84,79,0,10,0,128,0,3,0,32,67,70,70,32,35,187,57,254,0,0,10,112,0,0,84,205,71,83,85,66,106,18,122,98,0,0,98,20,0,0,5,216,79,83,47,50,104,215,98,101,0,0,1,16,0,0,0,96,99,109,97,112,38,198,129,33,0,0,5,56,0,0,5,24,104,101,97,100,237,187,124,213,0,
 0,0,172,0,0,0,54,104,104,101,97,6,229,0,115,0,0,0,228,0,0,0,36,104,109,116,120,58,11,56,208,0,0,95,64,0,0,2,212,109,97,120,112,1,105,80,0,0,0,1,8,0,0,0,6,110,97,109,101,226,66,147,104,0,0,1,112,0,0,3,198,112,111,115,116,255,181,0,161,0,0,10,80,0,0,0,
 32,0,1,0,0,0,1,0,0,64,149,238,152,95,15,60,245,0,3,3,232,0,0,0,0,198,13,28,168,0,0,0,0,198,13,28,168,255,7,255,16,3,131,3,149,0,0,0,3,0,2,0,0,0,0,0,0,0,1,0,0,3,144,254,224,0,200,2,138,255,7,255,7,3,131,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,80,0,1,105,
@@ -1011,10 +1011,10 @@ static const unsigned char temp_9105132e[] =
 0,2,0,21,0,4,0,12,0,0,0,14,0,19,0,9,0,21,0,23,0,15,0,28,0,28,0,18,0,36,0,51,0,19,0,53,0,54,0,35,0,57,0,60,0,37,0,63,0,66,0,41,0,71,0,72,0,45,0,82,0,82,0,47,0,92,0,92,0,48,0,99,0,99,0,49,0,103,0,106,0,50,0,140,0,162,0,54,0,165,0,168,0,77,0,179,0,184,0,
 81,0,208,0,209,0,87,0,214,0,214,0,89,0,224,1,6,0,90,1,8,1,8,0,129,1,13,1,13,0,130,0,1,0,26,0,3,0,13,0,20,0,24,0,25,0,26,0,27,0,52,0,55,0,56,0,61,0,62,0,67,0,68,0,69,0,70,0,134,0,135,0,136,0,137,0,138,0,139,0,163,0,164,0,169,1,7,0,0 };
 
-const char* BinaryData::cpmono_bold_otf = (const char*) temp_9105132e;
+const char* BinaryData::cpmono_bold_otf = (const char*) temp_bb1902b0;
 
 //================== cpmono_extra_light.otf ==================
-static const unsigned char temp_695ee124[] =
+static const unsigned char temp_4d28db62[] =
 { 79,84,84,79,0,10,0,128,0,3,0,32,67,70,70,32,248,217,201,134,0,0,10,164,0,0,78,103,71,83,85,66,106,18,122,98,0,0,91,224,0,0,5,216,79,83,47,50,104,210,98,59,0,0,1,16,0,0,0,96,99,109,97,112,38,198,129,33,0,0,5,108,0,0,5,24,104,101,97,100,237,187,115,86,
 0,0,0,172,0,0,0,54,104,104,101,97,6,229,0,179,0,0,0,228,0,0,0,36,104,109,116,120,81,57,79,54,0,0,89,12,0,0,2,212,109,97,120,112,1,105,80,0,0,0,1,8,0,0,0,6,110,97,109,101,101,109,217,12,0,0,1,112,0,0,3,252,112,111,115,116,255,181,0,161,0,0,10,132,0,0,
 0,32,0,1,0,0,0,1,0,0,97,176,60,66,95,15,60,245,0,3,3,232,0,0,0,0,198,13,23,248,0,0,0,0,198,13,23,248,255,71,255,16,3,67,3,118,0,0,0,3,0,2,0,0,0,0,0,0,0,1,0,0,3,144,254,224,0,200,2,138,255,71,255,71,3,67,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,80,0,1,
@@ -1339,10 +1339,10 @@ static const unsigned char temp_695ee124[] =
 0,55,0,61,0,62,0,70,0,2,0,21,0,4,0,12,0,0,0,14,0,19,0,9,0,21,0,23,0,15,0,28,0,28,0,18,0,36,0,51,0,19,0,53,0,54,0,35,0,57,0,60,0,37,0,63,0,66,0,41,0,71,0,72,0,45,0,82,0,82,0,47,0,92,0,92,0,48,0,99,0,99,0,49,0,103,0,106,0,50,0,140,0,162,0,54,0,165,0,168,
 0,77,0,179,0,184,0,81,0,208,0,209,0,87,0,214,0,214,0,89,0,224,1,6,0,90,1,8,1,8,0,129,1,13,1,13,0,130,0,1,0,26,0,3,0,13,0,20,0,24,0,25,0,26,0,27,0,52,0,55,0,56,0,61,0,62,0,67,0,68,0,69,0,70,0,134,0,135,0,136,0,137,0,138,0,139,0,163,0,164,0,169,1,7,0,0 };
 
-const char* BinaryData::cpmono_extra_light_otf = (const char*) temp_695ee124;
+const char* BinaryData::cpmono_extra_light_otf = (const char*) temp_4d28db62;
 
 //================== cpmono_light.otf ==================
-static const unsigned char temp_ed13a613[] =
+static const unsigned char temp_57da6d1[] =
 { 79,84,84,79,0,10,0,128,0,3,0,32,67,70,70,32,64,226,171,159,0,0,10,124,0,0,81,133,71,83,85,66,106,18,122,98,0,0,94,216,0,0,5,216,79,83,47,50,104,211,98,73,0,0,1,16,0,0,0,96,99,109,97,112,38,198,129,33,0,0,5,68,0,0,5,24,104,101,97,100,237,187,127,116,0,
 0,0,172,0,0,0,54,104,104,101,97,6,229,0,158,0,0,0,228,0,0,0,36,104,109,116,120,73,105,71,167,0,0,92,4,0,0,2,212,109,97,120,112,1,105,80,0,0,0,1,8,0,0,0,6,110,97,109,101,106,76,91,179,0,0,1,112,0,0,3,209,112,111,115,116,255,181,0,161,0,0,10,92,0,0,0,32,
 0,1,0,0,0,1,0,0,215,127,97,71,95,15,60,245,0,3,3,232,0,0,0,0,198,13,30,2,0,0,0,0,198,13,30,2,255,50,255,16,3,88,3,128,0,0,0,3,0,2,0,0,0,0,0,0,0,1,0,0,3,144,254,224,0,200,2,138,255,50,255,50,3,88,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,80,0,1,105,0,0,
@@ -1677,10 +1677,10 @@ static const unsigned char temp_ed13a613[] =
 0,4,0,12,0,0,0,14,0,19,0,9,0,21,0,23,0,15,0,28,0,28,0,18,0,36,0,51,0,19,0,53,0,54,0,35,0,57,0,60,0,37,0,63,0,66,0,41,0,71,0,72,0,45,0,82,0,82,0,47,0,92,0,92,0,48,0,99,0,99,0,49,0,103,0,106,0,50,0,140,0,162,0,54,0,165,0,168,0,77,0,179,0,184,0,81,0,208,
 0,209,0,87,0,214,0,214,0,89,0,224,1,6,0,90,1,8,1,8,0,129,1,13,1,13,0,130,0,1,0,26,0,3,0,13,0,20,0,24,0,25,0,26,0,27,0,52,0,55,0,56,0,61,0,62,0,67,0,68,0,69,0,70,0,134,0,135,0,136,0,137,0,138,0,139,0,163,0,164,0,169,1,7,0,0 };
 
-const char* BinaryData::cpmono_light_otf = (const char*) temp_ed13a613;
+const char* BinaryData::cpmono_light_otf = (const char*) temp_57da6d1;
 
 //================== cpmono_plain.otf ==================
-static const unsigned char temp_39c3d0c7[] =
+static const unsigned char temp_522dd185[] =
 { 79,84,84,79,0,10,0,128,0,3,0,32,67,70,70,32,153,52,71,27,0,0,10,124,0,0,81,49,71,83,85,66,106,18,122,98,0,0,94,132,0,0,5,216,79,83,47,50,104,213,98,87,0,0,1,16,0,0,0,96,99,109,97,112,38,198,129,33,0,0,5,68,0,0,5,24,104,101,97,100,237,186,121,35,0,0,0,
 172,0,0,0,54,104,104,101,97,6,228,0,137,0,0,0,228,0,0,0,36,104,109,116,120,65,179,64,52,0,0,91,176,0,0,2,212,109,97,120,112,1,105,80,0,0,0,1,8,0,0,0,6,110,97,109,101,95,80,74,175,0,0,1,112,0,0,3,209,112,111,115,116,255,181,0,161,0,0,10,92,0,0,0,32,0,
 1,0,0,0,1,0,0,76,64,104,233,95,15,60,245,0,3,3,232,0,0,0,0,198,13,26,212,0,0,0,0,198,13,26,212,255,28,255,16,3,109,3,139,0,0,0,3,0,2,0,0,0,0,0,0,0,1,0,0,3,144,254,224,0,200,2,138,255,28,255,29,3,109,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,80,0,1,105,
@@ -2014,10 +2014,10 @@ static const unsigned char temp_39c3d0c7[] =
 0,50,0,140,0,162,0,54,0,165,0,168,0,77,0,179,0,184,0,81,0,208,0,209,0,87,0,214,0,214,0,89,0,224,1,6,0,90,1,8,1,8,0,129,1,13,1,13,0,130,0,1,0,26,0,3,0,13,0,20,0,24,0,25,0,26,0,27,0,52,0,55,0,56,0,61,0,62,0,67,0,68,0,69,0,70,0,134,0,135,0,136,0,137,0,138,
 0,139,0,163,0,164,0,169,1,7,0,0 };
 
-const char* BinaryData::cpmono_plain_otf = (const char*) temp_39c3d0c7;
+const char* BinaryData::cpmono_plain_otf = (const char*) temp_522dd185;
 
 //================== miso-bold.ttf ==================
-static const unsigned char temp_6e43b659[] =
+static const unsigned char temp_5c319e5b[] =
 { 0,1,0,0,0,17,1,0,0,4,0,16,76,84,83,72,237,157,221,60,0,0,5,108,0,0,0,227,79,83,47,50,81,16,250,27,0,0,1,152,0,0,0,86,86,68,77,88,108,156,116,37,0,0,231,220,0,0,5,224,99,109,97,112,117,108,128,122,0,0,26,212,0,0,6,164,99,118,116,32,0,20,0,0,0,0,34,224,
 0,0,0,2,102,112,103,109,50,77,115,102,0,0,33,120,0,0,1,98,103,108,121,102,122,237,74,59,0,0,34,228,0,0,184,220,104,100,109,120,139,147,218,195,0,0,6,80,0,0,20,132,104,101,97,100,230,15,38,231,0,0,1,28,0,0,0,54,104,104,101,97,6,202,7,163,0,0,1,84,0,0,
 0,36,104,109,116,120,82,131,27,122,0,0,1,240,0,0,3,124,107,101,114,110,23,5,21,255,0,0,221,128,0,0,4,68,108,111,99,97,100,35,145,228,0,0,219,192,0,0,1,192,109,97,120,112,2,241,2,157,0,0,1,120,0,0,0,32,110,97,109,101,215,203,101,65,0,0,225,196,0,0,3,225,
@@ -2701,10 +2701,10 @@ static const unsigned char temp_6e43b659[] =
 255,203,0,239,0,212,255,203,0,240,0,213,255,203,0,241,0,214,255,202,0,242,0,215,255,202,0,243,0,216,255,202,0,244,0,217,255,202,0,245,0,218,255,202,0,246,0,218,255,201,0,247,0,219,255,201,0,248,0,220,255,201,0,249,0,221,255,201,0,250,0,222,255,201,0,
 251,0,223,255,200,0,252,0,224,255,200,0,253,0,225,255,200,0,254,0,226,255,200,0,255,0,226,255,199,0,0 };
 
-const char* BinaryData::misobold_ttf = (const char*) temp_6e43b659;
+const char* BinaryData::misobold_ttf = (const char*) temp_5c319e5b;
 
 //================== miso-light.ttf ==================
-static const unsigned char temp_b7a73532[] =
+static const unsigned char temp_87764d70[] =
 { 0,1,0,0,0,17,1,0,0,4,0,16,76,84,83,72,109,206,108,252,0,0,5,108,0,0,0,227,79,83,47,50,79,98,250,86,0,0,1,152,0,0,0,86,86,68,77,88,108,201,116,87,0,0,229,68,0,0,5,224,99,109,97,112,117,108,128,122,0,0,26,212,0,0,6,164,99,118,116,32,0,20,0,0,0,0,34,224,
 0,0,0,2,102,112,103,109,50,77,115,102,0,0,33,120,0,0,1,98,103,108,121,102,9,54,37,173,0,0,34,228,0,0,182,56,104,100,109,120,120,118,213,147,0,0,6,80,0,0,20,132,104,101,97,100,230,13,38,194,0,0,1,28,0,0,0,54,104,104,101,97,6,201,7,195,0,0,1,84,0,0,0,36,
 104,109,116,120,82,124,51,141,0,0,1,240,0,0,3,124,107,101,114,110,23,5,21,255,0,0,218,220,0,0,4,68,108,111,99,97,249,219,39,62,0,0,217,28,0,0,1,192,109,97,120,112,2,241,2,188,0,0,1,120,0,0,0,32,110,97,109,101,174,204,29,32,0,0,223,32,0,0,3,240,112,111,
@@ -3370,10 +3370,10 @@ static const unsigned char temp_b7a73532[] =
 203,0,243,0,216,255,203,0,244,0,217,255,203,0,245,0,218,255,202,0,246,0,218,255,202,0,247,0,219,255,202,0,248,0,220,255,202,0,249,0,221,255,201,0,250,0,222,255,201,0,251,0,223,255,201,0,252,0,224,255,201,0,253,0,225,255,201,0,254,0,226,255,200,0,255,
 0,226,255,200,0,0 };
 
-const char* BinaryData::misolight_ttf = (const char*) temp_b7a73532;
+const char* BinaryData::misolight_ttf = (const char*) temp_87764d70;
 
 //================== miso-regular.ttf ==================
-static const unsigned char temp_cedf3b8[] =
+static const unsigned char temp_2557f476[] =
 { 0,1,0,0,0,17,1,0,0,4,0,16,76,84,83,72,96,206,125,196,0,0,5,108,0,0,0,227,79,83,47,50,79,197,250,61,0,0,1,152,0,0,0,86,86,68,77,88,108,201,116,86,0,0,225,224,0,0,5,224,99,109,97,112,117,108,128,122,0,0,26,212,0,0,6,164,99,118,116,32,0,20,0,0,0,0,34,224,
 0,0,0,2,102,112,103,109,50,77,115,102,0,0,33,120,0,0,1,98,103,108,121,102,144,118,127,194,0,0,34,228,0,0,179,20,104,100,109,120,123,104,215,146,0,0,6,80,0,0,20,132,104,101,97,100,230,14,38,213,0,0,1,28,0,0,0,54,104,104,101,97,6,189,7,195,0,0,1,84,0,0,
 0,36,104,109,116,120,82,124,40,229,0,0,1,240,0,0,3,124,107,101,114,110,23,5,21,255,0,0,215,184,0,0,4,68,108,111,99,97,156,38,200,236,0,0,213,248,0,0,1,192,109,97,120,112,2,241,2,186,0,0,1,120,0,0,0,32,110,97,109,101,65,189,188,90,0,0,219,252,0,0,3,174,
@@ -4037,10 +4037,10 @@ static const unsigned char temp_cedf3b8[] =
 0,206,255,208,0,236,0,207,255,207,0,237,0,207,255,207,0,238,0,208,255,207,0,239,0,209,255,207,0,240,0,210,255,207,0,241,0,211,255,206,0,242,0,212,255,206,0,243,0,213,255,206,0,244,0,214,255,206,0,245,0,214,255,206,0,246,0,215,255,205,0,247,0,216,255,
 205,0,248,0,217,255,205,0,249,0,218,255,205,0,250,0,219,255,205,0,251,0,220,255,204,0,252,0,220,255,204,0,253,0,221,255,204,0,254,0,222,255,204,0,255,0,223,255,203,0,0 };
 
-const char* BinaryData::misoregular_ttf = (const char*) temp_cedf3b8;
+const char* BinaryData::misoregular_ttf = (const char*) temp_2557f476;
 
 //================== miso-serialized ==================
-static const unsigned char temp_28bba9e0[] =
+static const unsigned char temp_52cf9962[] =
 { 120,156,236,221,11,252,253,197,180,63,254,79,244,237,170,139,164,123,73,55,116,165,146,240,221,239,175,168,148,75,95,145,144,16,187,143,67,246,231,155,173,155,131,82,169,164,72,233,34,149,110,18,37,183,82,74,159,253,222,137,238,36,33,169,164,66,116,145,
 20,161,19,254,243,124,205,222,31,250,31,231,156,56,156,195,227,119,122,60,62,205,250,238,247,204,154,153,53,51,107,214,90,179,102,205,139,223,188,219,174,19,19,19,231,156,250,226,57,171,78,252,161,64,243,77,28,59,103,195,102,222,228,163,70,233,163,71,
 233,252,163,116,214,40,93,96,148,46,56,74,23,26,165,11,143,210,69,70,233,162,163,244,49,163,116,177,81,186,248,40,93,98,148,46,57,74,31,59,74,151,26,165,143,27,165,75,143,210,199,143,210,101,70,233,178,163,116,185,81,186,252,40,93,97,148,174,56,74,87,
@@ -5091,10 +5091,10 @@ static const unsigned char temp_28bba9e0[] =
 219,114,86,91,239,25,109,89,219,189,161,215,207,60,247,238,205,109,203,166,45,119,111,203,250,157,123,151,118,230,189,119,251,157,251,182,245,247,109,219,239,219,214,223,183,212,95,163,80,149,125,75,61,229,188,222,155,243,251,188,182,254,188,182,254,
 188,182,254,188,82,223,122,206,43,245,149,251,181,245,246,107,235,237,215,214,219,175,212,91,173,244,183,95,169,167,124,91,91,239,109,109,189,203,123,251,166,252,89,91,222,212,150,255,15,63,201,76,247,0,0 };
 
-const char* BinaryData::misoserialized = (const char*) temp_28bba9e0;
+const char* BinaryData::misoserialized = (const char*) temp_52cf9962;
 
 //================== nordic.ttf ==================
-static const unsigned char temp_607a5bbe[] =
+static const unsigned char temp_8dab42fc[] =
 { 0,1,0,0,0,14,0,128,0,3,0,96,79,83,47,50,123,137,164,77,0,0,1,136,0,0,0,86,99,109,97,112,54,197,178,209,0,0,31,240,0,0,1,202,99,118,116,32,15,192,16,0,0,0,26,184,0,0,2,0,102,112,103,109,1,82,156,24,0,0,28,184,0,0,0,179,103,97,115,112,0,23,0,6,0,0,26,168,
 0,0,0,16,103,108,121,102,108,103,13,174,0,0,40,168,0,0,51,44,104,101,97,100,98,133,67,155,0,0,0,236,0,0,0,54,104,104,101,97,6,68,3,192,0,0,1,36,0,0,0,36,104,109,116,120,180,81,19,127,0,0,37,52,0,0,3,116,108,111,99,97,0,33,207,92,0,0,33,188,0,0,3,120,
 109,97,120,112,24,248,0,170,0,0,1,72,0,0,0,32,110,97,109,101,185,229,179,231,0,0,1,224,0,0,24,198,112,111,115,116,255,163,0,48,0,0,1,104,0,0,0,32,112,114,101,112,15,37,62,165,0,0,29,108,0,0,2,130,0,1,0,0,0,5,0,0,166,84,57,97,95,15,60,245,0,1,4,0,0,0,
@@ -5335,10 +5335,10 @@ static const unsigned char temp_607a5bbe[] =
 6,7,6,39,53,54,55,51,22,23,185,30,74,27,4,1,23,86,22,3,204,31,74,27,4,2,22,86,22,4,2,126,88,56,12,28,214,22,3,3,22,86,88,56,12,28,214,22,3,3,22,0,0,0,2,0,50,1,226,1,133,2,237,0,10,0,21,0,3,0,48,49,19,6,7,6,39,53,54,55,51,22,31,1,6,7,6,39,53,54,55,51,
 22,23,185,30,74,27,4,1,23,86,22,3,204,31,74,27,4,2,22,86,22,4,2,126,88,56,12,28,214,22,3,3,22,86,88,56,12,28,214,22,3,3,22,0,0,0,0 };
 
-const char* BinaryData::nordic_ttf = (const char*) temp_607a5bbe;
+const char* BinaryData::nordic_ttf = (const char*) temp_8dab42fc;
 
 //================== ostrich.ttf ==================
-static const unsigned char temp_eec668cb[] =
+static const unsigned char temp_67b2694d[] =
 { 0,1,0,0,0,16,1,0,0,4,0,0,70,70,84,77,91,245,3,49,0,0,1,12,0,0,0,28,71,68,69,70,0,172,0,3,0,0,1,40,0,0,0,32,79,83,47,50,147,188,109,12,0,0,1,72,0,0,0,96,99,109,97,112,43,226,86,187,0,0,1,168,0,0,1,162,99,118,116,32,13,119,11,140,0,0,3,76,0,0,0,34,102,
 112,103,109,15,180,47,167,0,0,3,112,0,0,2,101,103,97,115,112,0,0,0,16,0,0,5,216,0,0,0,8,103,108,121,102,143,7,37,77,0,0,5,224,0,0,69,164,104,101,97,100,248,105,156,174,0,0,75,132,0,0,0,54,104,104,101,97,11,58,5,41,0,0,75,188,0,0,0,36,104,109,116,120,
 102,145,6,220,0,0,75,224,0,0,1,252,108,111,99,97,36,35,54,72,0,0,77,220,0,0,1,0,109,97,120,112,1,156,1,252,0,0,78,220,0,0,0,32,110,97,109,101,44,100,71,147,0,0,78,252,0,0,2,6,112,111,115,116,68,107,181,125,0,0,81,4,0,0,1,187,112,114,101,112,2,242,181,
@@ -5590,10 +5590,10 @@ static const unsigned char temp_eec668cb[] =
 32,69,176,3,43,68,176,12,32,69,186,0,11,127,255,0,2,43,177,3,70,118,43,68,176,13,32,69,178,12,9,2,43,177,3,70,118,43,68,176,14,32,69,178,13,8,2,43,177,3,70,118,43,68,176,15,32,69,186,0,14,1,56,0,2,43,177,3,70,118,43,68,176,16,32,69,178,15,7,2,43,177,
 3,70,118,43,68,89,176,20,43,0,0,0,0 };
 
-const char* BinaryData::ostrich_ttf = (const char*) temp_eec668cb;
+const char* BinaryData::ostrich_ttf = (const char*) temp_67b2694d;
 
 //================== silkscreen-serialized ==================
-static const unsigned char temp_bf72eaf7[] =
+static const unsigned char temp_9d81b0f9[] =
 { 120,156,237,155,7,148,20,69,16,134,215,156,48,39,80,84,204,57,160,120,162,48,123,42,98,206,120,230,132,99,171,200,238,170,140,162,24,49,97,206,57,231,128,57,158,1,238,206,132,1,195,153,21,207,128,17,179,232,138,138,9,39,117,119,245,116,207,78,47,252,
 199,221,170,188,199,123,205,78,239,215,213,85,213,85,93,53,203,128,65,133,193,158,59,132,177,82,46,151,235,217,165,95,125,143,220,20,127,52,131,255,55,87,95,42,246,26,57,185,175,63,26,94,8,6,254,227,150,66,145,77,204,139,65,240,200,45,142,27,59,62,239,
 63,31,93,8,6,19,242,125,90,252,217,195,28,49,8,30,185,108,70,56,113,38,56,113,102,56,113,22,56,113,86,56,113,54,56,113,118,56,113,14,56,113,78,56,113,46,56,177,11,156,56,55,156,56,15,156,56,47,156,56,31,156,56,63,156,184,0,156,184,32,156,184,16,156,184,
@@ -5628,10 +5628,10 @@ static const unsigned char temp_bf72eaf7[] =
 2,78,156,0,39,126,9,39,126,5,39,126,13,39,126,3,39,126,11,39,126,7,39,126,15,39,254,0,39,78,132,19,127,132,19,127,130,19,203,112,226,207,112,226,36,56,241,23,56,241,87,56,241,55,56,113,50,156,248,59,156,248,7,156,248,39,156,248,23,156,248,55,156,56,5,
 78,12,128,255,0,255,66,227,172,0,0 };
 
-const char* BinaryData::silkscreenserialized = (const char*) temp_bf72eaf7;
+const char* BinaryData::silkscreenserialized = (const char*) temp_9d81b0f9;
 
 //================== silkscreen.ttf ==================
-static const unsigned char temp_46c3ac32[] =
+static const unsigned char temp_1692c470[] =
 { 0,1,0,0,0,15,0,48,0,3,0,192,79,83,47,50,121,166,129,146,0,0,64,208,0,0,0,78,80,67,76,84,173,52,110,22,0,0,65,32,0,0,0,54,99,109,97,112,198,58,142,190,0,0,61,32,0,0,2,4,99,118,116,32,7,83,8,77,0,0,64,172,0,0,0,36,102,112,103,109,152,92,220,162,0,0,3,224,
 0,0,0,100,103,108,121,102,48,157,174,66,0,0,4,152,0,0,54,18,104,100,109,120,137,166,202,30,0,0,65,88,0,0,6,72,104,101,97,100,213,88,95,61,0,0,0,252,0,0,0,54,104,104,101,97,2,213,6,14,0,0,1,52,0,0,0,36,104,109,116,120,44,25,4,90,0,0,63,36,0,0,1,136,108,
 111,99,97,0,10,37,204,0,0,58,172,0,0,1,140,109,97,120,112,1,9,0,219,0,0,1,88,0,0,0,32,110,97,109,101,63,98,60,192,0,0,1,120,0,0,2,103,112,111,115,116,9,71,9,62,0,0,60,56,0,0,0,230,112,114,101,112,5,176,112,7,0,0,4,68,0,0,0,83,0,1,0,0,0,1,0,0,124,56,31,
@@ -5838,10 +5838,10 @@ static const unsigned char temp_46c3ac32[] =
 14,16,19,16,16,16,16,14,14,16,16,8,16,16,14,19,19,16,16,16,16,16,14,16,19,19,19,19,14,11,14,11,14,16,11,16,16,16,16,14,14,16,16,8,16,16,14,19,19,16,16,16,16,16,14,16,19,19,19,19,14,14,8,14,16,24,20,12,0,11,11,9,14,20,17,20,17,9,11,11,20,20,9,14,6,14,
 17,14,17,17,17,17,17,17,17,17,6,9,14,14,14,17,20,17,17,17,17,14,14,17,17,9,17,17,14,20,20,17,17,17,17,17,14,17,20,20,20,20,14,11,14,11,14,17,11,17,17,17,17,14,14,17,17,9,17,17,14,20,20,17,17,17,17,17,14,17,20,20,20,20,14,14,9,14,17,0,0 };
 
-const char* BinaryData::silkscreen_ttf = (const char*) temp_46c3ac32;
+const char* BinaryData::silkscreen_ttf = (const char*) temp_1692c470;
 
 //================== wifi.png ==================
-static const unsigned char temp_43e5b62e[] =
+static const unsigned char temp_6df9a5b0[] =
 { 137,80,78,71,13,10,26,10,0,0,0,13,73,72,68,82,0,0,1,64,0,0,0,247,8,6,0,0,0,108,40,141,211,0,0,0,9,112,72,89,115,0,0,46,35,0,0,46,35,1,120,165,63,118,0,0,0,25,116,69,88,116,83,111,102,116,119,97,114,101,0,65,100,111,98,101,32,73,109,97,103,101,82,101,
 97,100,121,113,201,101,60,0,0,12,225,73,68,65,84,120,218,236,221,139,117,27,199,21,128,225,81,5,102,7,70,7,70,7,130,43,8,58,8,84,65,144,10,12,87,0,167,2,56,21,192,169,128,84,5,164,42,32,93,1,169,10,28,236,209,64,130,104,62,0,98,95,51,247,251,207,185,
 135,142,148,248,132,187,51,255,222,59,51,187,55,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,109,242,206,37,64,75,92,236,98,250,196,159,79,243,223,157,202,205,46,30,30,253,217,67,254,115,128,0,209,57,123,121,77,114,52,
@@ -5891,10 +5891,10 @@ static const unsigned char temp_43e5b62e[] =
 242,3,16,82,130,228,7,32,164,4,201,15,64,72,9,146,31,128,144,18,36,63,0,33,37,72,126,0,66,74,144,252,0,132,148,32,249,1,8,41,65,242,3,16,82,130,228,7,32,164,4,201,15,64,72,9,146,31,128,144,18,36,63,0,33,37,72,126,0,66,74,144,252,0,0,0,0,0,0,0,0,0,0,0,
 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,64,45,252,95,128,1,0,166,155,18,218,219,72,225,153,0,0,0,0,73,69,78,68,174,66,96,130,0,0 };
 
-const char* BinaryData::wifi_png = (const char*) temp_43e5b62e;
+const char* BinaryData::wifi_png = (const char*) temp_6df9a5b0;
 
 //================== SourceDrop.png ==================
-static const unsigned char temp_e9da47e3[] =
+static const unsigned char temp_c7e90de5[] =
 { 137,80,78,71,13,10,26,10,0,0,0,13,73,72,68,82,0,0,0,154,0,0,2,209,8,6,0,0,0,163,255,186,145,0,0,0,9,112,72,89,115,0,0,46,35,0,0,46,35,1,120,165,63,118,0,0,0,25,116,69,88,116,83,111,102,116,119,97,114,101,0,65,100,111,98,101,32,73,109,97,103,101,82,101,
 97,100,121,113,201,101,60,0,0,24,15,73,68,65,84,120,218,236,157,49,118,219,58,155,64,225,252,234,199,59,120,76,55,93,244,78,154,233,66,173,192,206,10,34,55,108,99,175,64,210,10,226,180,106,44,175,32,206,10,68,151,83,228,68,89,65,152,106,202,167,233,166,
 203,224,139,32,255,50,4,82,36,69,144,50,113,239,57,140,98,218,164,36,232,234,3,64,2,31,206,212,137,144,36,201,185,126,24,234,45,214,219,95,122,139,244,38,251,190,206,231,243,105,195,207,181,52,207,211,36,35,253,58,211,6,95,163,188,190,101,133,67,178,
@@ -5984,10 +5984,10 @@ static const unsigned char temp_e9da47e3[] =
 26,164,75,209,72,34,211,28,63,74,138,38,66,201,96,214,123,31,215,202,78,82,52,153,53,99,58,3,113,133,118,4,84,67,196,90,153,246,239,131,61,5,46,8,209,140,108,43,83,16,183,166,173,177,173,50,183,237,162,119,53,170,131,166,73,95,128,80,217,182,35,165,183,
 255,53,143,89,151,98,217,252,191,0,3,0,92,224,0,25,78,103,130,40,0,0,0,0,73,69,78,68,174,66,96,130,0,0 };
 
-const char* BinaryData::SourceDrop_png = (const char*) temp_e9da47e3;
+const char* BinaryData::SourceDrop_png = (const char*) temp_c7e90de5;
 
 //================== DefaultDataSource.png ==================
-static const unsigned char temp_83d17403[] =
+static const unsigned char temp_527a47c1[] =
 { 137,80,78,71,13,10,26,10,0,0,0,13,73,72,68,82,0,0,2,14,0,0,2,14,8,6,0,0,0,208,187,133,57,0,0,0,9,112,72,89,115,0,0,46,35,0,0,46,35,1,120,165,63,118,0,0,0,25,116,69,88,116,83,111,102,116,119,97,114,101,0,65,100,111,98,101,32,73,109,97,103,101,82,101,97,
 100,121,113,201,101,60,0,0,54,204,73,68,65,84,120,218,236,221,219,113,27,71,211,198,241,33,234,187,55,51,240,58,2,193,55,46,251,74,171,8,76,69,32,40,2,137,17,144,140,64,100,4,130,34,16,20,129,86,87,118,249,198,80,4,239,58,3,58,131,15,35,244,90,16,5,146,
 56,236,244,116,207,252,127,85,44,218,239,129,0,22,187,179,207,246,156,78,2,0,247,254,248,243,175,118,227,95,167,171,159,211,141,127,255,65,254,179,109,78,31,248,239,182,185,93,253,44,31,248,239,63,221,249,247,165,252,127,190,252,127,127,251,245,151,37,
@@ -6186,10 +6186,10 @@ static const unsigned char temp_83d17403[] =
 124,222,248,247,158,65,139,0,193,1,192,126,193,98,168,90,68,177,106,209,200,63,55,193,126,229,98,168,20,12,255,252,175,252,243,80,45,88,50,72,17,32,56,0,200,27,52,54,181,59,252,95,159,110,249,207,134,39,255,135,220,74,24,248,166,114,64,133,0,40,207,255,
 11,48,0,82,9,189,51,228,54,205,183,0,0,0,0,73,69,78,68,174,66,96,130,0,0 };
 
-const char* BinaryData::DefaultDataSource_png = (const char*) temp_83d17403;
+const char* BinaryData::DefaultDataSource_png = (const char*) temp_527a47c1;
 
 //================== FileReaderIcon.png ==================
-static const unsigned char temp_a3ff92b1[] =
+static const unsigned char temp_b15787b3[] =
 { 137,80,78,71,13,10,26,10,0,0,0,13,73,72,68,82,0,0,2,43,0,0,2,165,8,6,0,0,0,10,20,172,128,0,0,0,9,112,72,89,115,0,0,46,35,0,0,46,35,1,120,165,63,118,0,0,0,25,116,69,88,116,83,111,102,116,119,97,114,101,0,65,100,111,98,101,32,73,109,97,103,101,82,101,97,
 100,121,113,201,101,60,0,0,13,207,73,68,65,84,120,218,236,221,193,109,219,102,24,199,97,167,224,189,217,160,26,33,39,130,60,69,222,32,27,68,217,160,157,64,244,6,217,32,242,4,237,6,97,78,36,120,202,8,234,6,206,4,233,171,194,45,138,130,110,42,231,179,244,
 138,126,30,224,3,115,50,132,191,232,234,87,17,65,94,12,227,244,245,234,219,250,171,60,62,37,122,45,159,227,220,101,121,45,109,83,223,93,1,192,194,188,248,159,177,2,23,27,113,113,190,216,69,220,2,98,5,96,9,17,183,143,243,123,162,215,178,207,242,90,34,
@@ -6235,10 +6235,10 @@ static const unsigned char temp_a3ff92b1[] =
 127,254,79,195,56,173,205,12,0,100,141,149,205,253,1,0,120,20,143,129,0,0,177,2,0,32,86,0,0,177,2,0,32,86,0,0,196,10,0,32,86,0,0,196,10,0,32,86,0,0,196,10,0,128,88,1,0,196,10,0,128,88,1,0,196,10,0,128,88,1,0,16,43,0,128,88,1,0,16,43,0,128,88,1,0,16,43,
 0,0,98,5,0,16,43,0,0,167,240,135,0,3,0,22,72,102,252,69,115,49,232,0,0,0,0,73,69,78,68,174,66,96,130,0,0 };
 
-const char* BinaryData::FileReaderIcon_png = (const char*) temp_a3ff92b1;
+const char* BinaryData::FileReaderIcon_png = (const char*) temp_b15787b3;
 
 //================== IntanIcon.png ==================
-static const unsigned char temp_1c931bf2[] =
+static const unsigned char temp_fa728db0[] =
 { 137,80,78,71,13,10,26,10,0,0,0,13,73,72,68,82,0,0,2,88,0,0,2,88,8,6,0,0,0,190,102,152,220,0,0,0,9,112,72,89,115,0,0,46,35,0,0,46,35,1,120,165,63,118,0,0,0,25,116,69,88,116,83,111,102,116,119,97,114,101,0,65,100,111,98,101,32,73,109,97,103,101,82,101,
 97,100,121,113,201,101,60,0,0,63,109,73,68,65,84,120,218,236,221,219,117,219,198,162,6,96,56,43,239,155,187,130,208,21,88,126,201,74,158,76,87,96,185,2,83,21,88,170,64,82,5,146,43,16,93,129,229,10,68,63,37,43,47,86,42,48,83,193,81,42,216,7,99,13,19,154,
 230,5,131,27,1,242,251,214,194,102,182,197,203,112,0,2,63,102,6,131,39,89,71,252,246,251,31,71,249,67,88,134,249,242,44,95,6,241,79,71,11,255,13,0,240,144,47,247,11,255,253,103,190,204,194,191,253,250,203,207,247,93,40,224,147,29,7,170,227,124,121,145,
@@ -6469,10 +6469,10 @@ static const unsigned char temp_1c931bf2[] =
 105,213,2,0,154,55,203,151,219,124,121,95,245,202,192,206,6,172,21,97,107,148,47,175,178,199,150,45,115,105,1,0,85,133,57,172,66,144,250,152,47,211,54,67,85,39,2,214,154,192,53,140,97,235,167,236,223,22,174,97,166,181,11,0,248,215,44,46,243,255,254,43,
 134,170,217,174,2,213,178,255,23,96,0,208,173,232,3,246,227,153,225,0,0,0,0,73,69,78,68,174,66,96,130,0,0 };
 
-const char* BinaryData::IntanIcon_png = (const char*) temp_1c931bf2;
+const char* BinaryData::IntanIcon_png = (const char*) temp_fa728db0;
 
 //================== muteoff.png ==================
-static const unsigned char temp_db8d15fa[] =
+static const unsigned char temp_b96c87b8[] =
 { 137,80,78,71,13,10,26,10,0,0,0,13,73,72,68,82,0,0,0,165,0,0,0,119,8,6,0,0,0,98,221,128,254,0,0,0,9,112,72,89,115,0,0,46,35,0,0,46,35,1,120,165,63,118,0,0,0,25,116,69,88,116,83,111,102,116,119,97,114,101,0,65,100,111,98,101,32,73,109,97,103,101,82,101,
 97,100,121,113,201,101,60,0,0,7,127,73,68,65,84,120,218,236,93,237,141,219,56,16,157,13,238,255,169,131,232,42,136,58,136,174,130,115,42,136,182,3,167,130,213,85,160,77,5,74,7,218,171,64,238,64,78,5,187,169,192,123,21,236,217,128,140,91,24,182,197,33,
 135,228,144,126,15,32,2,36,182,98,146,79,111,190,248,65,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,16,23,119,24,2,49,52,251,246,215,190,21,251,182,221,183,239,251,246,130,97,1,98,224,64,194,105,223,222,78,218,110,223,86,24,30,64,11,33,223,183,10,195,4,132,194,106,
@@ -6503,10 +6503,10 @@ static const unsigned char temp_db8d15fa[] =
 182,24,66,64,147,106,154,30,135,13,0,193,84,19,102,16,80,165,154,3,134,10,8,141,134,174,87,64,96,182,129,104,196,220,157,81,72,16,210,2,119,24,2,81,172,102,34,110,136,127,239,56,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,153,224,63,1,6,0,199,74,112,
 188,78,34,32,245,0,0,0,0,73,69,78,68,174,66,96,130,0,0 };
 
-const char* BinaryData::muteoff_png = (const char*) temp_db8d15fa;
+const char* BinaryData::muteoff_png = (const char*) temp_b96c87b8;
 
 //================== muteon.png ==================
-static const unsigned char temp_b4d8aaca[] =
+static const unsigned char temp_cc85094c[] =
 { 137,80,78,71,13,10,26,10,0,0,0,13,73,72,68,82,0,0,0,165,0,0,0,119,8,6,0,0,0,98,221,128,254,0,0,0,9,112,72,89,115,0,0,46,35,0,0,46,35,1,120,165,63,118,0,0,0,25,116,69,88,116,83,111,102,116,119,97,114,101,0,65,100,111,98,101,32,73,109,97,103,101,82,101,
 97,100,121,113,201,101,60,0,0,5,175,73,68,65,84,120,218,236,157,225,113,219,54,20,128,41,95,7,144,39,40,51,65,153,9,66,79,80,101,130,72,19,84,158,32,242,4,106,38,176,55,80,58,129,212,9,228,78,32,101,2,187,19,176,192,9,185,178,172,34,63,146,32,240,32,
 126,223,29,207,254,33,203,226,227,167,247,0,16,0,179,12,0,0,0,0,0,0,0,0,0,32,46,19,66,224,135,170,170,230,230,199,175,230,152,154,227,217,28,95,38,147,201,145,200,64,12,25,167,230,216,87,255,231,197,28,51,34,4,90,132,172,83,16,41,8,37,228,204,101,195,
@@ -6531,10 +6531,10 @@ static const unsigned char temp_b4d8aaca[] =
 38,65,91,214,228,14,14,168,202,154,60,228,30,130,203,121,233,105,25,123,202,54,196,20,179,57,87,115,131,144,221,96,31,27,191,114,218,182,163,21,113,215,246,185,227,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,112,61,252,35,192,0,171,7,136,102,133,179,227,147,0,0,0,
 0,73,69,78,68,174,66,96,130,0,0 };
 
-const char* BinaryData::muteon_png = (const char*) temp_b4d8aaca;
+const char* BinaryData::muteon_png = (const char*) temp_cc85094c;
 
 //================== MergerA-01.png ==================
-static const unsigned char temp_1d080779[] =
+static const unsigned char temp_b27d54fb[] =
 { 137,80,78,71,13,10,26,10,0,0,0,13,73,72,68,82,0,0,2,69,0,0,1,169,8,6,0,0,0,131,16,66,165,0,0,0,9,112,72,89,115,0,0,46,35,0,0,46,35,1,120,165,63,118,0,0,0,25,116,69,88,116,83,111,102,116,119,97,114,101,0,65,100,111,98,101,32,73,109,97,103,101,82,101,97,
 100,121,113,201,101,60,0,0,21,118,73,68,65,84,120,218,236,221,189,111,93,71,122,7,224,33,205,133,100,55,75,195,69,108,96,131,28,117,74,82,136,238,210,36,190,238,220,45,221,109,170,92,117,73,181,218,46,157,168,191,64,18,130,0,219,241,170,76,37,186,220,
 138,87,221,22,73,72,45,16,239,166,226,81,103,87,146,58,17,145,172,204,240,156,107,82,50,181,226,199,189,119,230,156,243,60,192,64,194,98,23,246,190,188,31,63,190,243,158,153,16,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
@@ -6612,10 +6612,10 @@ static const unsigned char temp_1d080779[] =
 248,195,31,30,43,12,66,17,148,105,26,154,109,180,127,89,116,32,18,138,24,98,32,26,159,252,207,126,241,139,191,60,90,127,252,246,219,240,242,229,255,41,18,66,17,148,97,18,215,111,98,24,186,179,204,71,246,189,163,25,108,32,154,249,139,79,63,13,127,253,
 55,127,27,254,251,191,254,83,48,66,40,130,124,82,39,232,183,113,253,99,12,67,15,114,28,238,248,255,2,12,0,160,41,104,168,212,59,220,159,0,0,0,0,73,69,78,68,174,66,96,130,0,0 };
 
-const char* BinaryData::MergerA01_png = (const char*) temp_1d080779;
+const char* BinaryData::MergerA01_png = (const char*) temp_b27d54fb;
 
 //================== MergerA-02.png ==================
-static const unsigned char temp_1d161efa[] =
+static const unsigned char temp_b28b6c7c[] =
 { 137,80,78,71,13,10,26,10,0,0,0,13,73,72,68,82,0,0,2,69,0,0,1,169,8,6,0,0,0,131,16,66,165,0,0,0,9,112,72,89,115,0,0,46,35,0,0,46,35,1,120,165,63,118,0,0,0,25,116,69,88,116,83,111,102,116,119,97,114,101,0,65,100,111,98,101,32,73,109,97,103,101,82,101,97,
 100,121,113,201,101,60,0,0,21,221,73,68,65,84,120,218,236,221,207,143,220,229,125,192,241,199,6,20,145,3,24,113,104,14,84,76,14,68,42,145,98,71,109,165,68,106,203,112,171,0,41,246,49,39,236,219,70,171,85,234,191,0,175,170,168,205,41,187,26,141,58,55,
 102,149,246,18,21,177,72,148,156,130,191,62,1,39,198,28,210,10,34,49,78,140,212,139,221,129,74,56,17,152,246,251,236,124,7,111,28,227,95,187,51,207,243,253,62,175,151,52,26,43,34,96,127,118,215,251,222,231,121,190,223,239,145,0,29,55,24,142,94,174,223,
@@ -6695,10 +6695,10 @@ static const unsigned char temp_1d161efa[] =
 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
 0,0,0,0,0,0,0,0,0,7,243,255,2,12,0,244,180,87,201,128,90,137,162,0,0,0,0,73,69,78,68,174,66,96,130,0,0 };
 
-const char* BinaryData::MergerA02_png = (const char*) temp_1d161efa;
+const char* BinaryData::MergerA02_png = (const char*) temp_b28b6c7c;
 
 //================== MergerB-01.png ==================
-static const unsigned char temp_84e93458[] =
+static const unsigned char temp_1a5e81da[] =
 { 137,80,78,71,13,10,26,10,0,0,0,13,73,72,68,82,0,0,2,69,0,0,1,169,8,6,0,0,0,131,16,66,165,0,0,0,9,112,72,89,115,0,0,46,35,0,0,46,35,1,120,165,63,118,0,0,0,25,116,69,88,116,83,111,102,116,119,97,114,101,0,65,100,111,98,101,32,73,109,97,103,101,82,101,97,
 100,121,113,201,101,60,0,0,22,71,73,68,65,84,120,218,236,221,193,110,92,215,125,192,225,35,195,64,150,97,158,160,147,39,16,253,4,30,111,219,2,161,159,32,163,29,1,130,144,252,4,146,94,160,148,58,24,100,18,47,56,68,187,106,211,74,6,28,103,149,112,180,106,
 187,210,72,221,217,5,60,130,232,165,108,102,99,67,128,1,245,156,185,119,68,202,162,109,82,26,206,57,247,222,239,67,47,168,4,110,98,255,69,101,126,60,231,220,123,67,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
@@ -6779,10 +6779,10 @@ static const unsigned char temp_84e93458[] =
 90,156,33,18,68,136,34,40,194,36,100,60,119,36,138,232,108,24,185,195,12,81,4,197,154,214,113,52,21,69,112,201,254,254,31,254,241,240,179,63,125,218,55,9,68,17,20,109,30,214,248,42,17,81,68,23,221,138,215,77,99,64,20,65,99,164,67,217,31,94,246,182,218,
 187,230,76,199,92,248,185,69,0,100,51,13,107,124,50,182,40,66,16,1,80,154,73,200,240,14,53,81,132,32,2,160,4,199,117,12,221,205,117,247,217,255,11,48,0,4,145,141,135,126,85,212,174,0,0,0,0,73,69,78,68,174,66,96,130,0,0 };
 
-const char* BinaryData::MergerB01_png = (const char*) temp_84e93458;
+const char* BinaryData::MergerB01_png = (const char*) temp_1a5e81da;
 
 //================== MergerB-02.png ==================
-static const unsigned char temp_84f74bd9[] =
+static const unsigned char temp_1a6c995b[] =
 { 137,80,78,71,13,10,26,10,0,0,0,13,73,72,68,82,0,0,2,69,0,0,1,169,8,6,0,0,0,131,16,66,165,0,0,0,9,112,72,89,115,0,0,46,35,0,0,46,35,1,120,165,63,118,0,0,0,25,116,69,88,116,83,111,102,116,119,97,114,101,0,65,100,111,98,101,32,73,109,97,103,101,82,101,97,
 100,121,113,201,101,60,0,0,18,109,73,68,65,84,120,218,236,221,253,109,28,199,25,192,225,161,97,88,127,90,174,192,231,10,76,87,224,77,5,145,42,48,85,129,237,10,44,86,16,177,2,31,43,200,165,2,175,42,200,169,2,173,42,200,249,207,0,1,156,27,237,94,72,43,
 148,248,117,119,243,238,204,243,0,7,25,65,128,216,175,201,240,199,249,216,253,60,65,253,126,221,126,206,140,129,154,125,254,228,137,33,48,87,203,237,231,242,63,255,254,119,95,252,251,200,191,11,4,17,0,71,182,153,98,232,98,27,67,67,152,95,46,252,123,65,
@@ -6849,10 +6849,10 @@ static const unsigned char temp_84f74bd9[] =
 0,0,68,17,0,128,40,2,0,16,69,0,0,162,8,0,64,20,1,0,136,34,0,0,81,4,0,32,138,0,0,68,17,0,128,40,2,0,16,69,0,0,162,8,0,64,20,1,0,136,34,0,0,81,4,0,32,138,0,0,68,17,0,128,40,2,0,16,69,0,0,162,8,0,64,20,1,0,136,34,0,0,81,4,0,32,138,0,0,68,17,0,128,40,2,0,
 16,69,0,0,162,8,0,64,20,1,0,136,34,0,0,81,4,0,32,138,0,0,68,17,0,128,40,2,0,16,69,0,0,181,248,175,0,3,0,94,88,236,111,126,120,246,51,0,0,0,0,73,69,78,68,174,66,96,130,0,0 };
 
-const char* BinaryData::MergerB02_png = (const char*) temp_84f74bd9;
+const char* BinaryData::MergerB02_png = (const char*) temp_1a6c995b;
 
 //================== PipelineA-01.png ==================
-static const unsigned char temp_d2682521[] =
+static const unsigned char temp_dfc01a23[] =
 { 137,80,78,71,13,10,26,10,0,0,0,13,73,72,68,82,0,0,2,49,0,0,1,169,8,6,0,0,0,124,178,103,71,0,0,0,9,112,72,89,115,0,0,46,35,0,0,46,35,1,120,165,63,118,0,0,0,25,116,69,88,116,83,111,102,116,119,97,114,101,0,65,100,111,98,101,32,73,109,97,103,101,82,101,
 97,100,121,113,201,101,60,0,0,20,161,73,68,65,84,120,218,236,221,77,118,220,198,213,6,224,82,236,121,232,89,102,129,87,96,122,5,106,175,192,202,10,212,90,129,153,21,136,90,1,165,21,176,51,250,134,162,71,223,80,240,10,68,205,50,19,178,2,209,179,204,148,
 174,3,180,217,110,145,84,55,8,116,85,1,207,115,78,29,57,63,199,150,47,33,246,203,91,183,80,33,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,64,22,190,81,2,128,193,124,92,175,39,235,245,239,245,250,175,114,0,0,165,248,220,173,79,235,
@@ -6927,10 +6927,10 @@ static const unsigned char temp_d2682521[] =
 0,132,24,40,73,28,224,125,17,12,242,2,8,49,80,88,128,137,91,72,6,121,1,132,24,40,138,147,72,0,66,12,20,25,96,174,148,1,64,136,129,210,2,204,74,25,0,132,24,40,201,107,1,6,96,222,188,39,134,18,197,240,242,66,25,0,230,77,39,6,1,6,0,33,6,4,24,0,132,24,16,
 96,0,16,98,16,96,0,152,154,111,149,128,204,57,70,13,192,157,116,98,16,96,0,40,210,255,4,24,0,27,12,93,110,21,245,184,159,0,0,0,0,73,69,78,68,174,66,96,130,0,0 };
 
-const char* BinaryData::PipelineA01_png = (const char*) temp_d2682521;
+const char* BinaryData::PipelineA01_png = (const char*) temp_dfc01a23;
 
 //================== PipelineA-02.png ==================
-static const unsigned char temp_d2763ca2[] =
+static const unsigned char temp_dfce31a4[] =
 { 137,80,78,71,13,10,26,10,0,0,0,13,73,72,68,82,0,0,2,49,0,0,1,169,8,6,0,0,0,124,178,103,71,0,0,0,9,112,72,89,115,0,0,46,35,0,0,46,35,1,120,165,63,118,0,0,0,25,116,69,88,116,83,111,102,116,119,97,114,101,0,65,100,111,98,101,32,73,109,97,103,101,82,101,
 97,100,121,113,201,101,60,0,0,25,18,73,68,65,84,120,218,236,221,191,114,28,199,157,192,241,214,149,67,178,12,101,167,75,52,10,200,84,36,93,133,2,18,97,121,14,233,42,83,145,228,72,96,157,157,185,78,160,99,203,36,66,251,2,146,137,47,228,224,94,64,240,19,
 104,20,1,133,132,208,19,104,239,9,4,63,1,111,154,59,123,128,36,252,217,157,253,51,221,51,159,79,213,214,74,182,69,139,63,146,139,47,122,122,166,67,8,225,173,151,87,74,175,91,183,111,191,125,93,254,207,15,71,199,39,247,2,0,92,225,189,230,11,7,36,225,206,
@@ -7022,10 +7022,10 @@ static const unsigned char temp_d2763ca2[] =
 25,5,136,24,128,212,157,133,243,243,140,198,198,1,34,6,32,117,49,88,28,9,0,34,6,32,27,85,152,172,186,28,26,5,136,24,128,28,148,77,188,156,26,5,136,24,128,212,77,143,4,40,237,119,1,17,3,144,131,24,44,251,110,145,6,17,3,144,139,170,137,151,202,40,64,196,
 0,228,160,12,142,4,0,17,3,144,137,24,44,142,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,210,240,127,2,12,0,195,72,32,13,219,83,201,41,0,0,0,0,73,69,78,68,174,66,96,130,0,0 };
 
-const char* BinaryData::PipelineA02_png = (const char*) temp_d2763ca2;
+const char* BinaryData::PipelineA02_png = (const char*) temp_dfce31a4;
 
 //================== PipelineB-01.png ==================
-static const unsigned char temp_3a495200[] =
+static const unsigned char temp_47a14702[] =
 { 137,80,78,71,13,10,26,10,0,0,0,13,73,72,68,82,0,0,2,49,0,0,1,169,8,6,0,0,0,124,178,103,71,0,0,0,9,112,72,89,115,0,0,46,35,0,0,46,35,1,120,165,63,118,0,0,0,25,116,69,88,116,83,111,102,116,119,97,114,101,0,65,100,111,98,101,32,73,109,97,103,101,82,101,
 97,100,121,113,201,101,60,0,0,23,202,73,68,65,84,120,218,236,221,191,111,164,199,125,192,225,177,99,56,141,4,159,75,167,241,186,184,107,69,157,1,130,108,196,85,107,5,208,165,58,5,72,34,30,98,215,186,75,109,231,142,165,227,66,199,198,46,245,242,47,16,
 13,196,85,18,248,149,155,93,108,99,10,112,106,189,174,148,146,130,221,43,239,104,223,21,87,247,131,183,187,220,221,153,217,247,121,128,5,37,69,145,229,239,209,224,231,102,230,125,39,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,200,
@@ -7112,10 +7112,10 @@ static const unsigned char temp_3a495200[] =
 175,127,249,203,162,231,100,4,12,0,223,240,55,237,231,137,49,144,218,31,254,240,73,248,235,95,255,18,14,14,14,5,12,0,34,134,178,252,239,159,254,20,254,239,243,207,195,221,31,223,13,223,253,238,223,206,254,114,124,140,250,196,116,0,120,145,47,125,124,
 114,250,220,190,115,231,203,255,250,239,255,249,114,52,158,28,251,159,39,0,47,243,255,2,12,0,38,140,193,224,172,166,247,238,0,0,0,0,73,69,78,68,174,66,96,130,0,0 };
 
-const char* BinaryData::PipelineB01_png = (const char*) temp_3a495200;
+const char* BinaryData::PipelineB01_png = (const char*) temp_47a14702;
 
 //================== PipelineB-02.png ==================
-static const unsigned char temp_3a576981[] =
+static const unsigned char temp_47af5e83[] =
 { 137,80,78,71,13,10,26,10,0,0,0,13,73,72,68,82,0,0,2,49,0,0,1,169,8,6,0,0,0,124,178,103,71,0,0,0,9,112,72,89,115,0,0,46,35,0,0,46,35,1,120,165,63,118,0,0,0,25,116,69,88,116,83,111,102,116,119,97,114,101,0,65,100,111,98,101,32,73,109,97,103,101,82,101,
 97,100,121,113,201,101,60,0,0,20,155,73,68,65,84,120,218,236,221,189,122,28,71,118,6,224,162,54,217,141,4,101,155,169,121,5,132,50,103,28,101,206,22,190,130,29,101,206,12,103,206,22,186,2,72,87,192,209,21,16,190,2,54,51,103,4,51,109,132,118,182,142,72,
 101,206,184,93,238,30,99,22,4,64,204,95,119,157,238,247,125,158,122,160,213,15,151,60,232,25,124,83,117,170,234,89,74,233,83,130,242,124,108,199,247,237,184,86,10,0,238,243,76,136,161,240,32,243,67,59,174,148,2,0,33,134,136,114,144,89,41,3,0,66,12,130,
@@ -7190,4 +7190,4 @@ static const unsigned char temp_3a576981[] =
 228,45,210,23,73,191,11,0,16,36,196,184,18,0,0,8,21,98,242,146,209,66,105,1,128,8,33,38,247,187,92,38,253,46,0,64,144,16,227,74,0,0,32,84,136,201,253,46,103,202,7,0,68,9,49,185,223,229,84,217,0,128,8,33,102,125,37,64,165,92,0,64,132,16,179,238,119,1,
 0,8,17,98,114,191,203,66,105,0,128,40,33,198,149,0,0,64,24,174,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,202,241,119,1,6,0,159,157,76,71,98,187,78,10,0,0,0,0,73,69,78,68,174,66,96,130,0,0 };
 
-const char* BinaryData::PipelineB02_png = (const char*) temp_3a576981;
+const char* BinaryData::PipelineB02_png = (const char*) temp_47af5e83;
diff --git a/JuceLibraryCode/BinaryData.h b/JuceLibraryCode/BinaryData.h
index d811f05d43fe17554b9690e2e075e8cebac80de0..06da7661577383b07f4d8558bf5ba8d212e2ffb7 100644
--- a/JuceLibraryCode/BinaryData.h
+++ b/JuceLibraryCode/BinaryData.h
@@ -1,6 +1,6 @@
 /* =========================================================================================
 
-   This is an auto-generated file, created by The Jucer V3.0.0
+   This is an auto-generated file, created by The Introjucer 3.0.0
    Do not edit anything in this file!
 
 */
diff --git a/JuceLibraryCode/JuceHeader.h b/JuceLibraryCode/JuceHeader.h
index deec28dd3f67863f3f3b52ee5caeb9b69861365d..4d6411485d29fcdaf7a21cf7c0cc67563545f361 100644
--- a/JuceLibraryCode/JuceHeader.h
+++ b/JuceLibraryCode/JuceHeader.h
@@ -10,8 +10,8 @@
 
 */
 
-#ifndef __APPHEADERFILE_DFAE8F6C__
-#define __APPHEADERFILE_DFAE8F6C__
+#ifndef __APPHEADERFILE_84429F2A__
+#define __APPHEADERFILE_84429F2A__
 
 #include "AppConfig.h"
 #include "juce_amalgamated.h"
@@ -24,4 +24,4 @@ namespace ProjectInfo
     const int          versionNumber  = 0x0;
 }
 
-#endif   // __APPHEADERFILE_DFAE8F6C__
+#endif   // __APPHEADERFILE_84429F2A__
diff --git a/Source/Processors/Editors/SpikeDisplayEditor.cpp b/Source/Processors/Editors/SpikeDisplayEditor.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..f73201e27d770f36a4bc2c7f12a25691e28cbc0e
--- /dev/null
+++ b/Source/Processors/Editors/SpikeDisplayEditor.cpp
@@ -0,0 +1,57 @@
+#include "SpikeDisplayEditor.h"
+
+
+
+SpikeDisplayEditor::SpikeDisplayEditor (GenericProcessor* parentNode) 
+	: VisualizerEditor(parentNode)
+
+{
+
+	desiredWidth = 250;
+
+	StringArray timeBaseValues;
+	timeBaseValues.add("100");
+	timeBaseValues.add("200");
+	timeBaseValues.add("500");
+	timeBaseValues.add("1000");
+
+	createRadioButtons(35, 50, 160, timeBaseValues, "Thresholds (s)");
+
+	StringArray displayGainValues;
+	displayGainValues.add("100");
+	displayGainValues.add("200");
+	displayGainValues.add("400");
+	displayGainValues.add("800");
+
+	createRadioButtons(35, 90, 160, displayGainValues, "Display Gain");
+
+
+}
+
+SpikeDisplayEditor::~SpikeDisplayEditor()
+{
+}
+
+
+Visualizer* SpikeDisplayEditor::createNewCanvas()
+{
+
+	SpikeDisplayNode* processor = (SpikeDisplayNode*) getProcessor();
+	return new SpikeDisplayCanvas(processor);
+
+}
+
+void SpikeDisplayEditor::buttonCallback(Button* button)
+{
+
+	int gId = button->getRadioGroupId();
+
+	if (gId > 0) {
+		if (canvas != 0)
+		{
+			canvas->setParameter(gId-1, button->getName().getFloatValue());
+		}
+
+	} 
+
+}
diff --git a/Source/Processors/Editors/SpikeDisplayEditor.h b/Source/Processors/Editors/SpikeDisplayEditor.h
new file mode 100644
index 0000000000000000000000000000000000000000..78e878c606878ca4b3d4a342d2558646cb2ff7e7
--- /dev/null
+++ b/Source/Processors/Editors/SpikeDisplayEditor.h
@@ -0,0 +1,55 @@
+/*
+    ------------------------------------------------------------------
+
+    This file is part of the Open Ephys GUI
+    Copyright (C) 2012 Open Ephys
+
+    ------------------------------------------------------------------
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#ifndef SPIKEDISPLAYEDITOR_H_
+#define SPIKEDISPLAYEDITOR_H_
+
+#include "../../../JuceLibraryCode/JuceHeader.h"
+#include "GenericEditor.h"
+#include "../../UI/UIComponent.h"
+#include "../../UI/DataViewport.h"
+#include "../Visualization/DataWindow.h"
+#include "../SpikeDisplayNode.h"
+#include "../Visualization/SpikeDisplayCanvas.h"
+#include "VisualizerEditor.h"
+
+class Visualizer;
+
+class SpikeDisplayEditor : public VisualizerEditor
+{
+public:
+	SpikeDisplayEditor (GenericProcessor*);
+	~SpikeDisplayEditor();
+
+	void buttonCallback (Button* button);
+
+	Visualizer* createNewCanvas();
+
+private:	
+
+
+	JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (SpikeDisplayEditor);
+
+};
+
+#endif  // SPIKEDISPLAYEDITOR_H_
diff --git a/Source/Processors/ProcessorGraph.cpp b/Source/Processors/ProcessorGraph.cpp
index a7d37ff6a3b1a8a13468e22d7159023caab118dd..e17aef5afd851a914737cbe4785448425dfb2c03 100644
--- a/Source/Processors/ProcessorGraph.cpp
+++ b/Source/Processors/ProcessorGraph.cpp
@@ -27,6 +27,7 @@
 
 #include "AudioNode.h"
 #include "LfpDisplayNode.h"
+#include "SpikeDisplayNode.h"
 #include "EventNode.h"
 #include "FilterNode.h"
 #include "GenericProcessor.h"
@@ -382,7 +383,12 @@ GenericProcessor* ProcessorGraph::createProcessorFromDescription(String& descrip
 		   // std::cout << "Graph data viewport: " << UI->getDataViewport() << std::endl;
 			// processor->setDataViewport(getDataViewport());
 			//processor->setUIComponent(UI);
-		} else if (subProcessorType.equalsIgnoreCase("WiFi Output")) {
+		} 
+		else if (subProcessorType.equalsIgnoreCase("Spike Viewer")) {
+			std::cout << "Creating an SpikeDisplayNode." << std::endl;
+			processor = new SpikeDisplayNode();	 
+		}
+		else if (subProcessorType.equalsIgnoreCase("WiFi Output")) {
 			std::cout << "Creating a WiFi node." << std::endl;
 			processor = new WiFiOutput();
 		}
@@ -409,6 +415,7 @@ bool ProcessorGraph::processorWithSameNameExists(const String& name)
 
 }
 
+
 void ProcessorGraph::removeProcessor(GenericProcessor* processor) {
 	
 	std::cout << "Removing processor with ID " << processor->getNodeId() << std::endl;
diff --git a/Source/Processors/SpikeDisplayNode.cpp b/Source/Processors/SpikeDisplayNode.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..7529f7ff51273e6786643f398a540f5edfdc3172
--- /dev/null
+++ b/Source/Processors/SpikeDisplayNode.cpp
@@ -0,0 +1,117 @@
+/*
+    ------------------------------------------------------------------
+
+    This file is part of the Open Ephys GUI
+    Copyright (C) 2012 Open Ephys
+
+    ------------------------------------------------------------------
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#include "SpikeDisplayNode.h"
+#include <stdio.h>
+
+SpikeDisplayNode::SpikeDisplayNode()
+	: GenericProcessor("SpikeDisplay Viewer"),
+	  bufferSize(0), abstractFifo(100)
+
+{
+//	displayBuffer = new AudioSampleBuffer(8, 100);
+	eventBuffer = new MidiBuffer();
+}
+
+SpikeDisplayNode::~SpikeDisplayNode()
+{
+	//deleteAndZero(displayBuffer);
+	//deleteAndZero(eventBuffer);
+}
+
+AudioProcessorEditor* SpikeDisplayNode::createEditor()
+{
+	std::cout<<"SpikeDisplayNode Created!"<<std::endl;
+
+	editor = new SpikeDisplayEditor(this);	
+	return editor;
+
+}
+
+void SpikeDisplayNode::updateSettings()
+{
+	std::cout << "Setting num inputs on SpikeDisplayNode to " << getNumInputs() << std::endl;
+}
+
+
+bool SpikeDisplayNode::enable()
+{
+	std::cout<<"SpikeDisplayNode::enable()"<<std::endl;
+	SpikeDisplayEditor* editor = (SpikeDisplayEditor*) getEditor();
+	editor->enable();
+	return true;
+		
+}
+
+bool SpikeDisplayNode::disable()
+{
+	std::cout<<"SpikeDisplayNode disabled!"<<std::endl;
+	SpikeDisplayEditor* editor = (SpikeDisplayEditor*) getEditor();
+	editor->disable();
+	return true;
+}
+
+int SpikeDisplayNode::getNumberOfChannelsForInput(int i){
+	std::cout<<"SpikeDisplayNode::getNumberOfChannelsForInput()"<<std::endl;
+	return 1;
+}
+
+
+void SpikeDisplayNode::setParameter (int parameterIndex, float newValue)
+{
+	std::cout<<"SpikeDisplayNode setParameter!"<<std::endl;
+}
+
+
+
+void SpikeDisplayNode::process(AudioSampleBuffer &buffer, MidiBuffer &midiMessages, int& nSamples)
+{
+	//std::cout<<"SpikeDisplayNode::process"<<std::endl;
+	/*
+	uint64_t ts =  00000; 
+	int noise = 10;
+	SpikeObject newSpike;
+
+	generateSimulatedSpike(&newSpike, ts, noise);
+	
+	spikebuffer.push(newSpike);
+	bufferSize++;
+	*/
+}
+
+bool SpikeDisplayNode::getNextSpike(SpikeObject *spike){
+	std::cout<<"SpikeDisplayNode::getNextSpike()"<<std::endl;
+	/*
+	if (bufferSize<1 || spikebuffer.empty())
+		return false;
+	else{
+		SpikeObject s = spikebuffer.front();
+		spikebuffer.pop();
+		bufferSize--;
+		*spike = s;
+		return true;
+	}
+	*/
+	return false;
+
+}
\ No newline at end of file
diff --git a/Source/Processors/SpikeDisplayNode.h b/Source/Processors/SpikeDisplayNode.h
new file mode 100644
index 0000000000000000000000000000000000000000..0f795a82c596c8a506685fc616159c1a8c808e40
--- /dev/null
+++ b/Source/Processors/SpikeDisplayNode.h
@@ -0,0 +1,87 @@
+/*
+    ------------------------------------------------------------------
+
+    This file is part of the Open Ephys GUI
+    Copyright (C) 2012 Open Ephys
+
+    ------------------------------------------------------------------
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#ifndef SPIKEDISPLAYNODE_H_
+#define SPIKEDISPLAYNODE_H_
+
+#include "../../JuceLibraryCode/JuceHeader.h"
+#include "Editors/SpikeDisplayEditor.h"
+#include "Editors/VisualizerEditor.h"
+#include "GenericProcessor.h"
+#include "Visualization/SpikeObject.h"
+
+/**
+  
+ Takes in MidiEvents and extracts SpikeObjects from the MidiEvent buffers. Those Events are then held in a queue until they are pulled by the spikeviewer
+
+  @see GenericProcessor, SpikeDisplayEditor, SpikeDisplayCanvas
+
+*/
+
+
+
+class DataViewport;
+
+class SpikeDisplayNode :  public GenericProcessor
+{
+public:
+
+	SpikeDisplayNode();
+	~SpikeDisplayNode();
+
+	AudioProcessorEditor* createEditor();
+
+	bool isSink() {return true;}
+
+	void process(AudioSampleBuffer &buffer, MidiBuffer &midiMessages, int& nSamples);
+
+	void setParameter(int, float);
+
+	void updateSettings();
+
+	bool enable();
+	bool disable();
+
+	int getNumberOfChannelsForInput(int i);
+
+	bool getNextSpike(SpikeObject *spike);
+	
+private:
+
+	int numberOfSources;
+	AbstractFifo abstractFifo;
+
+	ScopedPointer<AudioSampleBuffer> displayBuffer;
+	ScopedPointer<MidiBuffer> eventBuffer;
+
+	//std::queue<SpikeObject> spikebuffer;
+
+	int bufferSize;
+	//bool resizeBuffer();
+
+	JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (SpikeDisplayNode);
+
+};
+
+
+#endif  // SPIKEDISPLAYNODE_H_
diff --git a/Source/Processors/Visualization/OpenGLCanvas.cpp b/Source/Processors/Visualization/OpenGLCanvas.cpp
index 7b5ee046c90fcce38ac89dd19a123f14558f0176..1d8b338560686110da6e9d526bc49a4ae8d81a71 100644
--- a/Source/Processors/Visualization/OpenGLCanvas.cpp
+++ b/Source/Processors/Visualization/OpenGLCanvas.cpp
@@ -210,6 +210,7 @@ void OpenGLCanvas::stopCallbacks()
 
 void OpenGLCanvas::drawScrollBars()
 {
+	
 	float scrollBarY = float(getHeight())/float(getTotalHeight());
 	float timeSinceScroll = timer->getMillisecondCounter()-scrollTime;
 	
@@ -238,6 +239,7 @@ void OpenGLCanvas::drawScrollBars()
 		}
 		showScrollTrack = false;
 	}
+
 }
 
 void OpenGLCanvas::drawScrollBar(float y1, float y2, float alpha)
diff --git a/Source/Processors/Visualization/SpikeDisplayCanvas.cpp b/Source/Processors/Visualization/SpikeDisplayCanvas.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..ec856f57d00a79dd0e28a44e110c64099713e416
--- /dev/null
+++ b/Source/Processors/Visualization/SpikeDisplayCanvas.cpp
@@ -0,0 +1,243 @@
+/*
+    ------------------------------------------------------------------
+
+    This file is part of the Open Ephys GUI
+    Copyright (C) 2012 Open Ephys
+
+    ------------------------------------------------------------------
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#include "SpikeDisplayCanvas.h"
+
+SpikeDisplayCanvas::SpikeDisplayCanvas(SpikeDisplayNode* n) : processor(n),
+	 	xBuffer(25), yBuffer(25),  newSpike(false)
+{
+
+	
+
+	nSources = 0; //processor->getNumInputs();
+	std::cout<<"SpikeDisplayNode has :"<<nSources<<" outputs!"<<std::endl;
+	
+	//memset(nChannels, 0, sizeof(nChannels[0]) * MAX_NUMBER_OF_SPIKE_SOURCES);
+	for (int i=0; i<nSources; i++)
+		nChannels[i] = processor->getNumberOfChannelsForInput(i);
+
+	// sampleRate = processor->getSampleRate();
+	std::cout << "Setting num inputs on SpikeDisplayCanvas to " << nSources << std::endl;
+
+	//generateEmptySpike(&spike, 1);
+	
+	initializeSpikePlots();
+	
+	// displayBuffer = processor->getDisplayBufferAddress();
+	// displayBufferSize = displayBuffer->getNumSamples();
+	// std::cout << "Setting displayBufferSize on SpikeDisplayCanvas to " << displayBufferSize << std::endl;
+
+	// totalHeight = (plotHeight+yBuffer)*nChans + yBuffer;
+
+	// screenBuffer = new AudioSampleBuffer(nChans, 10000);	
+}
+
+SpikeDisplayCanvas::~SpikeDisplayCanvas()
+{
+	
+}
+
+void SpikeDisplayCanvas::initializeSpikePlots(){
+	std::cout<<"Initializing Plots"<<std::endl;
+
+	int nPlots = 8;
+	int nCols = 4;
+
+	int totalWidth = 1000; // This is a hack the width as the width isn't known before its drawn
+	
+	int plotWidth =  (totalWidth  - (nPlots + 1 ) * xBuffer) / nCols + .5;
+	int plotHeight = plotWidth / 2 + .5;
+	int rowCount = 0;
+	for (int i=0; i<nPlots; i++)
+	{
+		StereotrodePlot p = StereotrodePlot( 
+									xBuffer + i%nCols * (plotWidth + xBuffer) , 
+									yBuffer + rowCount * (plotHeight + yBuffer), 
+									plotWidth, 
+									plotHeight, ""); // deprecated conversion from string constant to char
+		plots.push_back(p);
+		if (i%nCols == nCols-1)
+			rowCount++;
+
+	
+	}
+	// Set the total height of the Canvas to the top of the top most plot
+	totalHeight = yBuffer + (rowCount + 1) * (plotHeight + yBuffer);
+
+}
+
+
+
+void SpikeDisplayCanvas::newOpenGLContextCreated()
+{
+
+	std::cout<<"SpikeDisplayCanvas::newOpenGLContextCreated()"<<std::endl;
+	setUp2DCanvas();
+	//activateAntiAliasing();
+
+	glClearColor (0.667, 0.698, 0.718, 1.0);
+	resized();
+	endAnimation();
+	//startTimer(50);
+
+}
+
+void SpikeDisplayCanvas::beginAnimation()
+{
+	std::cout << "Beginning animation." << std::endl;
+
+	// displayBufferSize = displayBuffer->getNumSamples();
+
+	// screenBuffer->clear();
+
+	//displayBufferIndex = 0;
+//	screenBufferIndex = 0;
+	
+	startCallbacks();
+}
+
+void SpikeDisplayCanvas::endAnimation()
+{
+	std::cout << "Ending animation." << std::endl;
+	stopCallbacks();
+}
+
+void SpikeDisplayCanvas::update()
+{
+	// nChans = processor->getNumInputs();
+	// sampleRate = processor->getSampleRate();
+
+	// std::cout << "Setting num inputs on SpikeDisplayCanvas to " << nChans << std::endl;
+	// if (nChans < 200 && nChans > 0)
+	// 	screenBuffer->setSize(nChans, 10000);
+	// //sampleRate = processor->getSampleRate();
+
+    // screenBuffer->clear();
+
+	repaint();
+
+	// totalHeight = (plotHeight+yBuffer)*nChans + yBuffer;
+}
+
+
+void SpikeDisplayCanvas::setParameter(int param, float val)
+{
+	// if (param == 0)
+	// 	timebase = val;
+	// else
+	// 	displayGain = val;
+	
+}
+
+void SpikeDisplayCanvas::refreshState()
+{
+	// called when the component's tab becomes visible again
+	// displayBufferIndex = processor->getDisplayBufferIndex();
+	// screenBufferIndex = 0;
+
+	//resized();
+
+}
+
+void SpikeDisplayCanvas::canvasWasResized()
+{
+	//std::cout << "Resized!" << std::endl;	
+}
+
+void SpikeDisplayCanvas::renderOpenGL()
+{
+	glClear(GL_COLOR_BUFFER_BIT); // clear buffers to preset values
+//	std::cout<<"SpikeDisplayCanvas::renderOpenGL"<<std::endl;
+	// Get Spikes from the processor
+	// Iterate through each spike, passing them individually to the appropriate plots and calling redraw before moving on to the next spike
+	
+	//while(processor->getNextSpike(&spike))
+	//{
+		
+	// Identify which plot the spike should go to
+	
+	// Distribute those spike to the appropriate plot object
+	
+	SpikeObject tmpSpike;
+
+	for (int i=0; i<plots.size(); i++){
+		generateSimulatedSpike(&tmpSpike, 0, 100);
+		plots[i].processSpikeObject(tmpSpike);
+		plots[i].redraw();
+	}
+	
+	//}
+	//std::cout << getHeight()<<" "<< getTotalHeight()<<" "<<std::endl;
+ 	drawScrollBars();
+}
+
+void SpikeDisplayCanvas::drawTicks()
+{
+	
+}
+
+int SpikeDisplayCanvas::getTotalHeight() 
+{
+	return totalHeight;
+}
+
+
+void SpikeDisplayCanvas::mouseDownInCanvas(const MouseEvent& e) 
+{
+
+	/*
+	Point<int> pos = e.getPosition();
+	int xcoord = pos.getX();
+
+	if (xcoord < getWidth()-getScrollBarWidth())
+	{
+		int chan = (e.getMouseDownY() + getScrollAmount())/(yBuffer+plotHeight);
+
+			selectedChan = chan;
+
+		repaint();
+	}*/
+
+}
+
+// void SpikeDisplayCanvas::mouseDrag(const MouseEvent& e) {mouseDragInCanvas(e);}
+// void SpikeDisplayCanvas::mouseMove(const MouseEvent& e) {mouseMoveInCanvas(e);}
+// void SpikeDisplayCanvas::mouseUp(const MouseEvent& e) 	{mouseUpInCanvas(e);}
+// void SpikeDisplayCanvas::mouseWheelMove(const MouseEvent& e, float a, float b) {mouseWheelMoveInCanvas(e,a,b);}
+
+// void SpikeDisplayCanvas::resized()
+// {
+// 	//screenBuffer = new AudioSampleBuffer(nChans, getWidth());
+
+// 	// glClear(GL_COLOR_BUFFER_BIT);
+
+// 	// //int h = getParentComponent()->getHeight();
+
+// 	// if (scrollPix + getHeight() > getTotalHeight() && getTotalHeight() > getHeight())
+// 	// 	scrollPix = getTotalHeight() - getHeight();
+// 	// else
+// 	// 	scrollPix = 0;
+
+// 	// showScrollBars();
+// 	canvasWasResized();
+// }
\ No newline at end of file
diff --git a/Source/Processors/Visualization/SpikeDisplayCanvas.h b/Source/Processors/Visualization/SpikeDisplayCanvas.h
new file mode 100644
index 0000000000000000000000000000000000000000..ac886696682fa8e2c5ac4e463ce014998a9e7766
--- /dev/null
+++ b/Source/Processors/Visualization/SpikeDisplayCanvas.h
@@ -0,0 +1,110 @@
+/*
+    ------------------------------------------------------------------
+
+    This file is part of the Open Ephys GUI
+    Copyright (C) 2012 Open Ephys
+
+    ------------------------------------------------------------------
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+*/
+#ifndef SPIKEDISPLAYCANVAS_H_
+#define SPIKEDISPLAYCANVAS_H_
+
+#include "../../../JuceLibraryCode/JuceHeader.h"
+
+#include "../SpikeDisplayNode.h"
+#include "SpikePlotting/ElectrodePlot.h"
+#include "SpikePlotting/StereotrodePlot.h"
+#include "SpikePlotting/TetrodePlot.h"
+#include "SpikeObject.h"
+
+#include "Visualizer.h"
+#include <vector>
+
+#define MAX_NUMBER_OF_SPIKE_SOURCES = 128;
+
+class SpikeDisplayNode;
+
+class SpikeDisplayCanvas : public Visualizer
+
+{
+public: 
+	SpikeDisplayCanvas(SpikeDisplayNode* n);
+	~SpikeDisplayCanvas();
+	void newOpenGLContextCreated();
+	void renderOpenGL();
+
+	void beginAnimation();
+	void endAnimation();
+
+	void refreshState();
+
+	void update();
+
+	void setParameter(int, float);
+
+private:
+
+	int xBuffer, yBuffer;
+
+	bool plotsInitialized;
+
+	bool newSpike;
+	SpikeObject spike;
+	SpikeDisplayNode* processor;
+	std::vector<StereotrodePlot> plots;
+	// AudioSampleBuffer* displayBuffer;
+	// ScopedPointer<AudioSampleBuffer> screenBuffer;
+	// MidiBuffer* eventBuffer;
+
+	// void setViewport(int chan);
+	// void drawBorder(bool isSelected);
+	// void drawChannelInfo(int chan, bool isSelected);
+	// void drawWaveform(int chan, bool isSelected);
+
+	void drawTicks();
+
+	// bool checkBounds(int chan);
+
+	// void updateScreenBuffer();
+	// int screenBufferIndex;
+	// int displayBufferIndex;
+	// int displayBufferSize;
+
+	int totalHeight;
+	// int selectedChan;
+
+	int getTotalHeight();
+
+	int nSources;
+	int nChannels[MAX_NUMBER_OF_SPIKE_CHANNELS];
+
+	void initializeSpikePlots();
+
+	void canvasWasResized();
+	void mouseDownInCanvas(const MouseEvent& e);
+	// void mouseDrag(const MouseEvent& e);
+	// void mouseMove(const MouseEvent& e);
+	// void mouseUp(const MouseEvent& e);
+	// void mouseWheelMove(const MouseEvent&, float, float);
+
+	JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (SpikeDisplayCanvas);
+	
+};
+
+
+
+#endif  // SPIKEDISPLAYCANVAS_H_
diff --git a/Source/Processors/Visualization/SpikeObject.cpp b/Source/Processors/Visualization/SpikeObject.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..dc8ff7f5ba029dec3cfa5ab55e0ae30467a6cacb
--- /dev/null
+++ b/Source/Processors/Visualization/SpikeObject.cpp
@@ -0,0 +1,217 @@
+/*
+    ------------------------------------------------------------------
+
+    This file is part of the Open Ephys GUI
+    Copyright (C) 2012 Open Ephys
+
+    ------------------------------------------------------------------
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#include "SpikeObject.h"
+#include <iostream>
+#include "memory.h"
+#include <stdlib.h>
+#include "time.h"
+      
+// Simple method for serializing a SpikeObject into a string of bytes
+bool packSpike(SpikeObject *s, char* buffer, int bufferSize){
+
+	int idx = 0;
+	memcpy(buffer+idx, &(s->timestamp), 4);
+	idx += 4;
+
+	memcpy(buffer+idx, &(s->source), 2);
+	idx +=2;
+
+	memcpy(buffer+idx, &(s->nChannels), 2);
+	idx +=2;
+
+	memcpy(buffer+idx, &(s->nSamples), 2);
+	idx +=2;
+
+	memcpy(buffer+idx, &(s->data), s->nChannels * s->nSamples * 2);
+	idx += s->nChannels * s->nSamples * 2;
+
+	memcpy(buffer+idx, &(s->gain), s->nChannels);
+	idx += s->nChannels;
+
+	memcpy(buffer+idx, &(s->threshold), s->nChannels);
+	idx += s->nChannels;
+
+if (idx>=bufferSize)
+		std::cout<<"Buffer Overrun! More data packaged than space provided!"<<std::endl;
+	// makeBufferValid(buffer, bufferSize);
+
+}
+
+// Simple method for deserializing a string of bytes into a Spike object
+bool unpackSpike(SpikeObject *s, char* buffer, int bufferSize){
+	// if !(isBufferValid(buffer, bufferSize));
+	// 	return false;
+
+	int idx = 0;
+	
+	memcpy( &(s->timestamp), buffer+idx, 4);
+	idx += 4;
+
+	memcpy( &(s->source), buffer+idx, 2);
+	idx += 2;
+
+	memcpy( &(s->nChannels), buffer+idx, 2);
+	idx +=2;
+
+	memcpy( &(s->nSamples), buffer+idx, 2);
+	idx +=2;
+
+	memcpy( &(s->data), buffer+idx, s->nChannels * s->nSamples * 2);
+	idx += s->nChannels * s->nSamples * 2;
+
+	memcpy( &(s->gain), buffer+idx, s->nChannels * 2);
+	idx += s->nChannels * 2;
+
+	memcpy( &(s->threshold), buffer+idx, s->nChannels *2);
+	idx += s->nChannels * 2;
+
+	if (idx>=bufferSize)
+		std::cout<<"Buffer Overrun! More data extracted than was given!"<<std::endl;
+	
+}
+
+// Checks the validity of the buffer, this should be run before unpacking and after packing the buffer
+bool isBufferValid(char *buffer, int bufferSize){
+
+	if (! CHECK_BUFFER_VALIDITY )
+		return true;
+
+	uint16_t runningSum = 0;
+	uint16_t value = 0;
+	
+	int idx = 0;
+
+	for (idx; idx<bufferSize-2; idx+=2){
+		memcpy(buffer + idx, &value, 2);
+		runningSum += value;
+	}
+
+	uint16_t integrityCheck = 0;
+	memcpy(buffer + idx, &integrityCheck, 2);
+
+	std::cout<<integrityCheck<<" == "<< runningSum <<std::endl;
+	return (integrityCheck == runningSum);
+}
+
+void makeBufferValid(char *buffer, int bufferSize){
+	if (! CHECK_BUFFER_VALIDITY )
+		return;
+
+	uint16_t runningSum = 0;
+	uint16_t value = 0;
+	
+	int idx = 0;
+
+	for (idx; idx<bufferSize-2; idx+=2){
+		memcpy(buffer + idx, &value, 2);
+		runningSum += value;
+	}
+
+	memcpy(&runningSum, buffer + idx, 2);
+
+}
+
+void generateSimulatedSpike(SpikeObject *s, uint64_t timestamp, int noise)
+{
+	//std::cout<<"generateSimulatedSpike()"<<std::endl;
+
+	uint16_t trace[][32] =
+	{
+	{ 	880,	900,	940,	1040,	1290,	1790,	2475,	2995, 	3110, 	2890,
+		2505,	2090,	1720,	1410, 	1155,  	945,	775,	635,	520, 	420,
+		340,	265,	205,	155,	115,	80,		50,		34,		10, 	34,  	50,		80},
+	{	1040,   1090,   1190,	1350,	1600,	1960,   2380,   2790,   3080,	3140,
+		2910,	2430,	1810,	1180,	680,	380,	270,	320,	460, 	630,
+		770,	870,	940,	970,	990,	1000,	1000,	1000,	1000,	1000,  1000,	1000},
+	{ 	1000,	1000,	1000,	1000,	1000,	1040,	1140,	1440,	2040,	2940,
+		3800,	4140,	3880,	3680,	1640,	920,	520,	300,	140,	040,
+		20,		20,		40,		100,	260,	500,	740,	900,	960,	1000,	1000,	1000}
+    };
+
+
+  //   uint16_t sineSpikeWave[32] = 
+  //   {	78, 	90, 	101, 	111,	120,	126,	129,	130,
+		// 129,	126,	120,	111,	101,	90,		78,		65,
+		// 52,		40,		29,		19,		11,		5,		2,		1,
+		// 2,		5,		11,		19,		29,		40,		52,		65};
+
+    // uint16_t trace[32] = {0};
+
+    uint16_t gain = 5;
+
+    s->timestamp = timestamp;
+    s->source = 0;
+    s->nChannels = 4;
+    s->nSamples = 32;
+    int idx=0;
+    
+    int waveType = rand()%3; // Pick one of the three predefined waveshapes to generate
+    double waveScaling = (double)(rand()%5 + 5) / 10.00; // Scale the wave between 50% and 150%
+    int shift = 1000;
+
+    for (int i=0; i<4; i++)
+    {
+        s->gain[i] = gain;
+        s->threshold[i] = 8000;
+
+		for (int j=0; j<32; j++){
+			
+			int n = 0;
+			if (noise>0){
+				n = rand() % noise - noise/2;
+			}
+
+            s->data[idx] = (trace[waveType][j] + n) * gain * waveScaling + shift;
+            idx = idx+1;
+        }
+    }
+    
+}
+void generateEmptySpike(SpikeObject *s, int nChannels){
+/*
+	std::cout<<"generateEmptySpike()"<<std::endl;
+	s->timestamp = 0;
+	s->source = 0;
+	s->nChannels = nChannels;
+	s->nSamples = 32;
+
+	memset(&(s->gain), 0, 2*nChannels);
+	memset(&(s->threshold), 0, 2*nChannels);
+	memset(&(s->data), 0, 2*nChannels*32);
+*/
+}
+
+
+// std::ostream& operator<<(std::ostream &strm, const SpikeObject s){
+
+// 	strm << " SpikeObject:\n";
+// 	strm << "\tTimestamp:" << s.timestamp;
+// 	strm << "\tSource:" << s.source;
+// 	strm << "\tnChannels:" <<s.nChannels;
+// 	strm <<"\tnSamples" << s.nSamples;
+// 	strm <<"\n\t 8 Data Samples:";
+// 	for (int i=0; i<8; i++)
+// 		strm << s.data[i]<<" ";
+// 	return strm;
+// }
diff --git a/Source/Processors/Visualization/SpikeObject.h b/Source/Processors/Visualization/SpikeObject.h
new file mode 100644
index 0000000000000000000000000000000000000000..b838960df5a9126e031c87eeda79a2e1f78a235c
--- /dev/null
+++ b/Source/Processors/Visualization/SpikeObject.h
@@ -0,0 +1,84 @@
+/*
+    ------------------------------------------------------------------
+
+    This file is part of the Open Ephys GUI
+    Copyright (C) 2012 Open Ephys
+
+    ------------------------------------------------------------------
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#ifndef SPIKEOBJECT_H_
+#define SPIKEOBJECT_H_
+
+#include <stdint.h>
+
+#define MAX_NUMBER_OF_SPIKE_CHANNELS 4
+#define MAX_NUMBER_OF_SPIKE_CHANNEL_SAMPLES 256
+#define CHECK_BUFFER_VALIDITY true
+
+struct SpikeObject{
+
+  uint64_t    timestamp;                                           
+  uint16_t    source;                                        
+  uint16_t    nChannels;                                      
+  uint16_t    nSamples;
+  uint16_t    data[MAX_NUMBER_OF_SPIKE_CHANNELS * MAX_NUMBER_OF_SPIKE_CHANNEL_SAMPLES]; 
+  uint16_t    gain[MAX_NUMBER_OF_SPIKE_CHANNELS];           
+  uint16_t    threshold[MAX_NUMBER_OF_SPIKE_CHANNELS];    
+
+};
+
+/*
+  For transmission between processors SpikeObjects must be packaged up into buffers that can fit into MidiEvents
+  The following two methods can be used to package the above spike object into a buffer and  unpackage a buffer
+  into a SpikeObject.  
+
+  The buffer is LittleEndian (thank Intel) and the byte order is the same as the SpikeObject definition. 
+  IE. the first 2 bytes are the timestamp, the next two bytes are the source identifier, etc... with the last
+  set of bytes corresponding to the thresholds of the different channels.
+
+  Finally the buffer will have an additional byte on the end that is used to check the integerity of the entire package.
+  The way this works is the buffer is divivded up into a series of 16 bit unsigned integers. The sum of all these integers
+  (except the last 16 bit integer) is taken and the sum should equal that 16 bit integer. If not then the data is corrupted 
+  and should be dropped or delt with another way.
+*/
+
+// Simple method for serializing a SpikeObject into a string of bytes, returns true is the packaged spike buffer is valid
+bool packSpike(SpikeObject *s, char* buffer, int bufferLength);
+
+// Simple method for deserializing a string of bytes into a Spike object, returns true is the provided spike buffer is valid
+bool unpackSpike(SpikeObject *s, char* buffer, int bufferLength);
+
+// Checks the validity of the buffer, this should be run before unpacking the buffer
+bool isBufferValid(char *buffer, int bufferLength);
+
+// Computes the validity value for the buffer, this should be called after packing the buffer
+void makeBufferValid(char *buffer, int bufferLength);
+
+// Help function for generating fake spikes in the absence of a real spike source. 
+// Can be used to generate a sign wave with a fixed Frequency of 1000 hz or a basic spike waveform
+// Additionally noise can be added to the waveform for help in diagnosing projection plots
+void generateSimulatedSpike(SpikeObject *s, uint64_t timestamp, int noise);
+
+// Define the << operator for the SpikeObject
+// std::ostream& operator<<(std::ostream &strm, const SpikeObject s);
+
+// Helper function for zeroing out a spike object with a specified number of channels
+void generateEmptySpike(SpikeObject *s, int nChannels);
+
+
+#endif //SPIKEOBJECT_H_
\ No newline at end of file
diff --git a/Source/Processors/Visualization/SpikePlotting/BaseUIElement.cpp b/Source/Processors/Visualization/SpikePlotting/BaseUIElement.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..88e7a8e98e00caf414ed647624a98f8ec3a3c069
--- /dev/null
+++ b/Source/Processors/Visualization/SpikePlotting/BaseUIElement.cpp
@@ -0,0 +1,86 @@
+#include "BaseUIElement.h"
+
+BaseUIElement::BaseUIElement():
+	xpos(0),  ypos(0), width(100), height(100), enabled(true), padding(0)
+{	
+	elementName = (char*) "BaseUIElement";
+	clearNextDraw = false;
+}
+
+BaseUIElement::BaseUIElement(int x, int y, double w, double h):
+	enabled(true), padding(0)
+{
+	xpos = x+padding;
+	ypos = y+padding;
+	width = w-padding*2;
+	height = h-padding*2;
+	elementName = (char*) "BaseUIElement";	
+	clearNextDraw = false;
+}
+BaseUIElement::BaseUIElement(int x, int y, double w, double h, int p):
+	enabled(true), padding(0)
+{
+	xpos = x+padding;
+	ypos = y+padding;	
+	width = w-padding*2;
+	height = h-padding*2;
+	elementName = (char*) "BaseUIElement";	
+	clearNextDraw = false;
+}
+
+void BaseUIElement::redraw(){
+//	std::cout<<"BaseUIElement::redraw(), Position:"<<xpos<<","<<ypos<<" : "<<width<<","<<height<<std::endl;
+	setGlViewport();
+	
+	if (clearNextDraw || !clearNextDraw){
+		clearNextDraw = false;
+		glColor3f(0.0, 0.0, 0.0);
+		glRecti(-1,-1,1,1);
+		
+		
+	}
+}
+void BaseUIElement::drawElementEdges(){
+	// std::cout<<"BaseUIElement::drawBaseUIElementEdges(), Position:"<<xpos<<","<<ypos<<" : "<<width<<","<<height<<std::endl;
+	glColor3f(1.0, 1.0, 1.0);
+	setGlViewport();
+	glLineWidth(2);
+	drawViewportEdge();
+}
+void BaseUIElement::setEnabled(bool e){
+	enabled = e;	
+}
+bool BaseUIElement::getEnabled(){
+	return enabled;
+}
+void BaseUIElement::setGlViewport(){
+	glViewport(xpos, ypos, width, height);
+	glLoadIdentity();
+	// std::cout<<xpos<<"x"<<ypos<<"-"<<width<<"x"<<height<<"\t"<<BaseUIElementName<<std::endl;
+}
+void BaseUIElement::setPosition(int x, int y, double w, double h){
+	xpos = x+padding;
+	ypos = y+padding;
+	width = w - padding*2;
+	height = h - padding*2;
+}
+void BaseUIElement::clearOnNextDraw(bool c){
+	clearNextDraw = c;
+}
+
+bool BaseUIElement::hitTest(int x, int y){
+    return (x>xpos && x<xpos+width) && (y>ypos && y<ypos+height);
+}
+
+double BaseUIElement::getHeight(){
+    return height;
+}
+double BaseUIElement::getWidth(){
+    return width;
+}
+int BaseUIElement::getX(){
+    return xpos;
+}
+int BaseUIElement::getY(){
+    return ypos;
+}
diff --git a/Source/Processors/Visualization/SpikePlotting/BaseUIElement.h b/Source/Processors/Visualization/SpikePlotting/BaseUIElement.h
new file mode 100644
index 0000000000000000000000000000000000000000..89536d8bf98ef8b9e654e579341653b166126ccd
--- /dev/null
+++ b/Source/Processors/Visualization/SpikePlotting/BaseUIElement.h
@@ -0,0 +1,40 @@
+#ifndef BASEUIELEMENT_H_
+#define BASEUIELEMENT_H_
+
+#include "PlotUtils.h"
+
+
+class BaseUIElement{
+
+protected:	
+	int xpos, ypos;
+	double height, width;
+	bool enabled;
+	double padding;
+	
+	void setGlViewport();
+		
+public:
+	BaseUIElement();
+	BaseUIElement(int x, int y, double w, double h);
+	BaseUIElement(int x, int y, double w, double h, int p);
+	void redraw();
+	void drawElementEdges();
+	void setEnabled(bool e);
+	bool getEnabled();
+	void setPosition(int x, int y, double w, double h);
+    double getHeight();
+    double getWidth();
+    int getX();
+    int getY();
+	
+	char *elementName;
+	void clearOnNextDraw(bool);
+	bool clearNextDraw;
+    bool hitTest(int x, int y);
+	
+};
+
+
+
+#endif // BaseUIElement_H_
diff --git a/Source/Processors/Visualization/SpikePlotting/ElectrodePlot.cpp b/Source/Processors/Visualization/SpikePlotting/ElectrodePlot.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..b86a8c5117e108ef01b93d6b4249dc95e763d6e3
--- /dev/null
+++ b/Source/Processors/Visualization/SpikePlotting/ElectrodePlot.cpp
@@ -0,0 +1,282 @@
+#include "ElectrodePlot.h"
+#include "../SpikeObject.h"
+#include "PlotUtils.h"
+
+ElectrodePlot::ElectrodePlot():
+	BaseUIElement(), titleHeight(0), enableTitle(true), limitsChanged(true)
+{
+    plotTitle = (char*) "Electrode Plot";
+
+}
+
+ElectrodePlot::ElectrodePlot(int x, int y, int w, int h, char *n):
+	BaseUIElement(x,y,w,h,1), titleHeight(0), enableTitle(true), limitsChanged(true)
+{
+	plotTitle = n;
+	titleBox = TitleBox(x, y+h-titleHeight-3, w, titleHeight+3, plotTitle);
+
+	initAxes();
+}
+
+ElectrodePlot::~ElectrodePlot(){
+}
+
+// Each plot needs to update its children axes when its redraw gets called.
+//  it also needs to call the parent plot  when children axes get added it
+//  should place them in the correct location because it KNOWS where WAVE1 and PROJ1x3
+//  should go by default. This isn't as general as it should be but its a good push in
+//  the right direction
+
+void ElectrodePlot::redraw(){
+	 //std::cout<<"ElectrodePlot() starting drawing"<<std::endl;\
+	BaseUIElement::clearNextDraw = true;
+	BaseUIElement::redraw();
+
+	axes.redraw();
+}
+
+// This would normally happen for collection of axes but an electrode plot doesn't have a collection instead its a single axes
+void ElectrodePlot::processSpikeObject(SpikeObject s){
+	//std::cout<<"ElectrdePlot::processSpikeObject()"<<std::endl;
+	axes.updateSpikeData(s);
+}
+void ElectrodePlot::setTitle(char *n){
+	plotTitle = n;
+}
+
+void ElectrodePlot::setEnabled(bool e){
+	BaseUIElement::enabled = e;
+
+	axes.setEnabled(e);
+}
+
+bool ElectrodePlot::getEnabled(){
+	return BaseUIElement::enabled;
+}
+
+
+void ElectrodePlot::initAxes(){
+	initLimits();
+    
+    int minX = BaseUIElement::xpos;
+	int minY = BaseUIElement::ypos;
+	
+	double axesWidth = BaseUIElement::width;
+	double axesHeight = (BaseUIElement::height - titleHeight);
+	
+	
+	axes = WaveAxes(minX, minY, axesWidth, axesHeight, WAVE1);
+	
+    //axes.setEnabled(false);
+	axes.setYLims(-1*pow(2,11), pow(2,14)*1.6);
+	axes.setWaveformColor(1.0, 1.0, 1.0);
+
+}
+
+void ElectrodePlot::setPosition(int x, int y, double w, double h){
+	BaseUIElement::setPosition(x,y,w,h);
+	int minX = BaseUIElement::xpos;
+	int minY = BaseUIElement::ypos;
+	
+	double axesWidth = BaseUIElement::width;
+	double axesHeight = BaseUIElement::height - titleHeight;
+	
+	axes.setPosition(minX, minY, axesWidth, axesHeight);
+	
+    titleBox.setPosition(x, y+h-titleHeight-3, w, titleHeight+3);
+}
+
+int ElectrodePlot::getNumberOfAxes(){
+	return 1;;
+}
+
+void ElectrodePlot::clearOnNextDraw(bool b){
+	BaseUIElement::clearNextDraw = b;
+}
+
+void ElectrodePlot::setTitleEnabled(bool e){
+
+    // if the new setting does not equal the old than clear on the next draw
+    clearNextDraw = !(e!=enableTitle);
+
+    enableTitle = e;
+    if (e)
+        titleHeight = 15;
+    else
+        titleHeight = 0;
+    
+    setPosition(BaseUIElement::xpos, BaseUIElement::ypos, 
+                BaseUIElement::width, BaseUIElement::height);
+}
+void ElectrodePlot::initLimits(){
+    for (int i=0; i<4; i++)
+    {
+        limits[i][0] = -1*pow(2,11);
+        limits[i][1] = pow(2,14);
+    }
+
+}
+
+void ElectrodePlot::getPreferredDimensions(double *w, double *h){
+    *w = 75;
+    *h = 75;
+}
+// void ElectrodePlot::mouseDown(int x, int y){
+
+// //     selectedAxesN = -1;
+// //     std::list<GenericAxes>::iterator i;
+// //     int idx=-1;
+// //     bool hit = false;
+
+// //     selectedAxes = NULL;
+// //     for (i=axesList.begin(); i!=axesList.end(); ++i)
+// //     {
+// //         if (i->hitTest(x,y))
+// //         {
+// //             selectedAxes = addressof(*i);
+// //             selectedAxesN = i->getType();
+// //             hit = true;
+// // //            break;
+// //         }
+// //         idx++;
+// //     }
+// //     if (!hit)
+// //         selectedAxes = NULL;
+// //     if (selectedAxes != NULL)
+// //         std::cout<<"ElectrodePlot::mouseDown() hit:"<<selectedAxes<<" AxesType:"<<selectedaxes.getType()<<std::endl;
+// //     else
+// //         std::cout<<"ElectrodePlot::mouseDown() NO HIT!"<<std::endl;
+    
+// }
+// void ElectrodePlot::mouseDragX(int dx, bool shift, bool ctrl){
+
+// //     if (selectedAxes == NULL || dx==0)
+// //         return;
+// // //    zoomAxes(selectedaxes.getType(), true, dx>0);
+// //     if (shift)
+// //         zoomAxes(selectedAxesN, true, dx);
+// //     if (ctrl)
+// //         panAxes(selectedAxesN, true, dx);
+
+// }
+// void ElectrodePlot::mouseDragY(int dy, bool shift, bool ctrl){
+//     if (selectedAxes == NULL || dy==0)
+//         return;
+//     if(shift)
+//         zoomAxes(selectedAxesN, false, dy);
+//     if(ctrl)
+//         panAxes(selectedAxesN, false, dy);
+// }
+
+// void ElectrodePlot::zoomAxes(int n, bool xdim, int zoom){
+// //    std::cout<<"ElectrodePlot::zoomAxes() n:"<< n<<" xdim"<< xdim<<" in:"<<zoomin<<std::endl;
+//     // If trying to zoom an invalid axes type
+//     if (n<WAVE1 || n>PROJ3x4)
+//         return;
+//     if (n<=WAVE4)
+//         zoomWaveform(n, xdim, zoom);
+//     else
+//         zoomProjection(n, xdim, zoom);
+// }
+
+// void ElectrodePlot::zoomWaveform(int n, bool xdim, int zoom){
+
+//     // waveform plots don't have a xlimits
+//     if (xdim)
+//         return;
+// //    std::cout<<"Zooming Waveform:"<<n<<" zoomin:"<<zoomin<<" ";
+//     double min, max;
+    
+//     if(xdim)
+//         return;
+
+//     min = limits[n][0];
+//     max = limits[n][1];
+    
+//     double mean = (max + min)/2.0f;
+//     double delta = max - mean;
+//     delta = delta / pow(.99, -1*zoom);
+
+//     min = mean - delta;
+//     max = mean + delta;
+
+//     limits[n][0] = min;
+//     limits[n][1] = max;
+    
+//     limitsChanged = true;
+// }
+
+// void ElectrodePlot::panAxes(int n, bool xdim, int panval){
+//     //    std::cout<<"ElectrodePlot::zoomAxes() n:"<< n<<" xdim"<< xdim<<" in:"<<zoomin<<std::endl;
+//     // If trying to zoom an invalid axes type
+//     if (n<WAVE1 || n>PROJ3x4)
+//         return;
+//     if (n<=WAVE4)
+//         panWaveform(n, xdim, panval);
+//     else
+//         panProjection(n, xdim, panval);
+// }
+
+// void ElectrodePlot::panWaveform(int n, bool xdim, int pan){
+    
+//     // waveform plots don't have a xlimits
+//     if (xdim)
+//         return;
+//     //    std::cout<<"Panning Waveform:"<<n<<" pan:"<<pan<<" "<<std::endl;
+//     double min, max;
+    
+//     if(xdim)
+//         return;
+    
+//     min = limits[n][0];
+//     max = limits[n][1];
+    
+//     double dy = max-min;
+    
+//     // Need to grab something if pan event is driven by the keyboard, which means that all the plots are getting panned so this should be okay
+//     if (selectedAxes == NULL)
+//         selectedAxes = &axesList.front();
+    
+//     double yPixels = (BaseUIElement::height - titleHeight)/2.0;
+    
+//     double pixelWidth = -1 * dy/yPixels;
+    
+//     double delta = pan * pixelWidth;
+//     min = min + delta;
+//     max = max + delta;
+    
+//     limits[n][0] = min;
+//     limits[n][1] = max;
+    
+//     limitsChanged = true;
+// }
+
+
+
+bool ElectrodePlot::processKeyEvent(SimpleKeyEvent k){
+    // std::cout<<"Key:"<<(char)k.key<<std::endl;
+    // switch(k.key)
+    // {
+    //     case '=':
+    //         for (int i=0; i<=WAVE4; i++)
+    //             zoomWaveform(i, false, 3);
+    //         break;        
+    //     case '+':
+    //         for (int i=0; i<=WAVE4; i++)
+    //             panWaveform(i, false, 3);
+    //         break;
+    //     case '-':
+    //         for (int i=0; i<=WAVE4; i++)
+    //             zoomWaveform(i, false, -3);
+    //         break;    
+    //     case '_':
+    //         for (int i=0; i<=WAVE4; i++)
+    //             panWaveform(i, false, -3);
+    //         break;
+    //     case 'C':
+    //         clearOnNextDraw(true);
+    //         break;
+    // }
+}
+
+
diff --git a/Source/Processors/Visualization/SpikePlotting/ElectrodePlot.h b/Source/Processors/Visualization/SpikePlotting/ElectrodePlot.h
new file mode 100644
index 0000000000000000000000000000000000000000..791ddbcc617b68f4514abab12687c5ef3abbc7c7
--- /dev/null
+++ b/Source/Processors/Visualization/SpikePlotting/ElectrodePlot.h
@@ -0,0 +1,79 @@
+#ifndef ELECTRODE_PLOT_H
+#define ELECTRODE_PLOT_H
+
+#if defined(__linux__)
+	#include <GL/glut.h>
+#else
+	#include <GLUT/glut.h>
+#endif
+#include <list>
+#include <math.h>
+
+#include "WaveAxes.h"
+#include "TitleBox.h"
+#include "BaseUIElement.h"
+#include "TetrodeSource.h"
+#include "PlotUtils.h"
+#include "SimpleKeyEvent.h"
+
+
+class ElectrodePlot : public BaseUIElement{
+	
+	char *plotTitle;
+	
+	TitleBox titleBox;
+
+	bool enabled;
+    bool enableTitle;
+	void drawTitle();
+	
+	double titleHeight;
+    
+    bool limitsChanged;
+    double limits[1][2];
+    
+    WaveAxes axes;
+    
+    
+    
+    // void zoomAxes(int n, bool xdim, int zoomval);
+    // void zoomProjection (int n, bool xdim, int zoomval);
+    // void zoomWaveform (int n, bool xdim, int zoomval);
+    
+    // void panAxes(int n, bool xdim, int panval);
+    // void panProjection (int n, bool xdim, int panval);
+    // void panWaveform(int n, bool xdim, int panval);
+    
+    void initLimits();
+	
+public:
+	ElectrodePlot();
+	ElectrodePlot(int x, int y,int w,int h, char *n);
+	~ElectrodePlot();
+
+	void initAxes();
+	void redraw();
+	void setTitle(char *n);
+	void setEnabled(bool enabled);
+	bool getEnabled();
+	void setPosition(int,int,double,double);
+
+	void getPreferredDimensions(double*, double*);
+
+	int getNumberOfAxes();
+	void clearOnNextDraw(bool c);
+    void setTitleEnabled(bool e);
+    
+    void mouseDown(int x, int y);
+    
+    void mouseDragX(int dx, bool shift, bool ctr);
+    void mouseDragY(int dy, bool shift, bool ctr);
+
+    bool processKeyEvent(SimpleKeyEvent k);
+
+    void processSpikeObject(SpikeObject s);
+};
+
+
+
+#endif
diff --git a/Source/Processors/Visualization/SpikePlotting/GenericAxes.cpp b/Source/Processors/Visualization/SpikePlotting/GenericAxes.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..db3904e49a80078dd2c0c5b9412a0c59962cc84a
--- /dev/null
+++ b/Source/Processors/Visualization/SpikePlotting/GenericAxes.cpp
@@ -0,0 +1,64 @@
+#include "GenericAxes.h"
+
+GenericAxes::GenericAxes():
+					BaseUIElement(),
+					type(0),
+					gotFirstSpike(false),
+					resizedFlag(false)
+{	
+	ylims[0] = 0;
+	ylims[1] = 1;
+}
+
+GenericAxes::GenericAxes(int x, int y, double w, double h, int t):
+					BaseUIElement(x,y,w,h),
+					gotFirstSpike(false),
+					resizedFlag(false)
+{
+	type = t;
+}
+void GenericAxes::updateSpikeData(SpikeObject newSpike){
+	if (!gotFirstSpike){
+		gotFirstSpike = true;	
+	}
+
+	s = newSpike;
+}
+
+
+void GenericAxes::setYLims(double ymin, double ymax){
+	ylims[0] = ymin;
+	ylims[1] = ymax;
+}
+void GenericAxes::getYLims(double *min, double *max){
+	*min = ylims[0];
+	*max = ylims[1];
+}
+void GenericAxes::setXLims(double xmin, double xmax){
+	xlims[0] = xmin;
+	xlims[1] = xmax;
+}
+void GenericAxes::getXLims(double *min, double *max){
+	*min = xlims[0];
+	*max = xlims[1];
+}
+
+void GenericAxes::setType(int t){
+	 if (t<WAVE1 || t>PROJ3x4){
+		std::cout<<"Invalid Axes type specified";
+		return;
+	}	
+	type = t;
+}
+
+int GenericAxes::getType(){
+    return type;
+}
+
+void GenericAxes::setPosition(int x, int y, double w, double h){
+	BaseUIElement::setPosition(x,y,w,h);	
+	resizedFlag = true;
+}
+void GenericAxes::clearOnNextDraw(bool b){
+	BaseUIElement::clearOnNextDraw(b);
+}
\ No newline at end of file
diff --git a/Source/Processors/Visualization/SpikePlotting/GenericAxes.h b/Source/Processors/Visualization/SpikePlotting/GenericAxes.h
new file mode 100644
index 0000000000000000000000000000000000000000..480a1a1135c76184e1e48a946313fa691a276914
--- /dev/null
+++ b/Source/Processors/Visualization/SpikePlotting/GenericAxes.h
@@ -0,0 +1,57 @@
+#ifndef GENERIC_AXES_H_
+#define GENERIC_AXES_H_
+
+
+#if defined(__linux__)
+	#include <GL/glut.h>
+#else
+	#include <GLUT/glut.h>
+#endif
+#include <stdlib.h>
+
+#include "../SpikeObject.h"
+
+#include "BaseUIElement.h"
+#include "PlotUtils.h"
+
+ 	
+class GenericAxes: public BaseUIElement{
+
+protected:
+	double xlims[2];
+	double ylims[2];
+	SpikeObject s;
+
+	bool gotFirstSpike;
+	bool resizedFlag;
+	
+	int type;
+	virtual void plot(){}
+
+	
+public:
+	GenericAxes();
+	GenericAxes(int x, int y, double w, double h, int t);
+
+	void updateSpikeData(SpikeObject s);
+
+	virtual void redraw(){}
+
+
+	void setXLims(double xmin, double xmax);
+	void getXLims(double *xmin, double *xmax);
+	void setYLims(double ymin, double ymax);
+	void getYLims(double *ymin, double *ymax);
+
+	void setType(int type);
+	int getType();
+    
+	
+	void setPosition(int,int,double,double);
+   	
+	void clearOnNextDraw(bool c);
+};
+
+
+
+#endif
diff --git a/Source/Processors/Visualization/SpikePlotting/Plot.cpp b/Source/Processors/Visualization/SpikePlotting/Plot.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..c52a9161dd32eee1d31019c7bcbd290c987c5776
--- /dev/null
+++ b/Source/Processors/Visualization/SpikePlotting/Plot.cpp
@@ -0,0 +1,16 @@
+#include "Plot.h"
+
+Plot::Plot(){
+	BaseUIElement();
+	plotTitle = (char*) "TetrodePlot";
+}
+Plot::Plot(int x, int y, int w, int h, char *n):
+BaseUIElement(x,y,x,h){
+	plotTitle = n;
+	
+}
+
+// Each plot needs to update its children axes when its redraw gets called. it also needs to call the parent plot
+// when children axes get added it should place them in the correct location because it KNOWS where WAVE1 and PROJ1x3
+// should go by default. This isn't as general as it should be but its a good push in the right direction
+
diff --git a/Source/Processors/Visualization/SpikePlotting/Plot.h b/Source/Processors/Visualization/SpikePlotting/Plot.h
new file mode 100644
index 0000000000000000000000000000000000000000..256467f5d7a82c04250bf8bc77e933579870e4a0
--- /dev/null
+++ b/Source/Processors/Visualization/SpikePlotting/Plot.h
@@ -0,0 +1,28 @@
+#ifndef PLOT_H_
+#define PLOT_H_
+
+#if defined(__linux__)
+	#include <GL/glut.h>
+#else
+	#include <GLUT/glut.h>
+#endif
+#include <list>
+#include "GenericAxes.h"
+
+class Plot: public BaseUIElement
+{
+	
+	char *plotTitle;
+	std::list<GenericAxes> axesList;
+	
+public:
+	Plot();
+	Plot(int x, int y,int w,int h, char *n);
+	void redraw();
+	void setTitle(char *n);
+	void setEnabled(bool enabled);
+	void addAxes(int axesType);
+};
+
+
+#endif
diff --git a/Source/Processors/Visualization/SpikePlotting/PlotUtils.cpp b/Source/Processors/Visualization/SpikePlotting/PlotUtils.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..766d2d5a3145bb23e7d247458cd3fb8f3cd8fb04
--- /dev/null
+++ b/Source/Processors/Visualization/SpikePlotting/PlotUtils.cpp
@@ -0,0 +1,153 @@
+#include "PlotUtils.h"
+
+
+void checkGlError(){
+	GLenum errCode;
+	const GLubyte *errString;
+	if ((errCode = glGetError()) != GL_NO_ERROR) {
+	    errString = gluErrorString(errCode);
+	   	fprintf (stderr, "OpenGL Error: %s\n", errString);
+		exit(1);
+	}
+	else
+		std::cout<<"OpenGL Okay!"<<std::endl;
+}
+void drawString(float x, float y, void *f, char *string){
+	// glRasterPos2f(x, y);
+	// int len = strlen(string);
+	// // glColor3f(1.0, 1.0, 1.0);
+	// for (int i = 0; i < len; i++) {
+ // 		glutBitmapCharacter(f, string[i]);
+	// }
+}
+
+void strokeString(void * font, char *message){
+	// // glPushMatrix();
+	//  glLoadIdentity();
+ //   	glTranslatef(-700, 0, 0);
+	// //glViewport(0,0,500,500);
+	// int len = (int) strlen(message);
+	// glColor3f(1.0, 1.0, 1.0);
+	// for (int i = 0; i < len; i++) {
+	// 	glutStrokeCharacter(font, message[i]);
+	// }
+
+	// glPopMatrix();
+}
+void drawViewportEdge(){
+	glPushMatrix();
+	glLoadIdentity();
+	
+	glBegin(GL_LINE_LOOP);
+		glVertex2f(-.995, -.995);
+		glVertex2f( .995, -.995);
+		glVertex2f( .995, .995);
+		glVertex2f(-.995, .995);
+	glEnd();
+	
+	glPopMatrix();
+}
+
+void drawViewportCross(){
+	glColor3f(0.0,1.0,1.0);
+	
+	glPushMatrix();
+	glLoadIdentity();
+	
+	glBegin(GL_LINE_LOOP);
+		glVertex2f(-.995, -.995);
+		glVertex2f( .995, .995);
+		glVertex2f( .995, -.995);
+		glVertex2f(-.995, .995);
+	glEnd();
+	
+	glPopMatrix();
+}
+
+void setViewportRange(int xMin,int yMin,int xMax,int yMax){
+	
+	float dx = xMax-xMin;
+	float dy = yMax-yMin;
+	
+//	printf("Setting viewport to:%d,%d %d,%d with dims%d,%d %d,%d\n", x,y,w,h, xMin, xMin, xMax,yMax);
+//	printf("Dx:%f Dy:%f, Scaling viewport by:%f,%f \n", dx,dy,2.0/dx, 2.0/dy);
+	glLoadIdentity();
+	glTranslatef(-1.0,-1.0,0.0); 
+	glScalef(2.0f/dx, 2.0f/dy, 1.0);
+	glTranslatef(0-xMin, 0-yMin, 0);
+	
+}
+int roundUp(int numToRound, int multiple) 
+{ 
+	if(multiple == 0) 
+ 	{ 
+  		return numToRound; 
+ 	} 
+
+ 	int remainder = numToRound % multiple;
+ 	if (remainder == 0)
+  		return numToRound;
+ 	return numToRound + multiple - remainder;
+}
+
+double ad16ToUv(int x, int gain){	
+	int result =  (double)(x * 20e6) / (double)(gain * pow(2,16));
+	return result;
+}
+void makeLabel(int val, int gain, bool convert, char * s){
+	if (convert){
+		val = ad16ToUv(val, gain);
+		if (abs(val)>1e6){
+			val = val/(1e6);
+			sprintf(s, "%dV", (int)val);
+		}
+		else if(abs(val)>1e3){
+			val = val/(1e3);
+			sprintf(s, "%dmV", (int)val);
+		}
+		else
+			sprintf(s, "%duV", (int)val);
+	}
+	else
+		sprintf(s,"%d", (int)val);		
+}
+
+void n2ProjIdx(int proj, int *p1, int *p2){
+    int d1, d2;
+	if (proj==PROJ1x2){
+		d1 = 0;
+		d2 = 1;
+	}
+	else if(proj==PROJ1x3){
+		d1 = 0;
+		d2 = 2;
+	}
+	else if(proj==PROJ1x4){
+		d1 = 0;
+		d2 = 3;
+	}
+	else if(proj==PROJ2x3){
+		d1 = 1;
+		d2 = 2;
+	}
+	else if(proj==PROJ2x4){
+		d1 = 1;
+		d2 = 3;
+	}
+	else if (proj==PROJ3x4){
+		d1 = 2;
+		d2 = 3;
+	}
+	else{
+		std::cout<<"ArteAxes::plotProjection() invalid projection specified cannot determine d1 and d2"<<std::endl;
+        *p1 = -1;
+        *p2 = -1;
+		return;
+	}
+    *p1 = d1;
+    *p2 = d2;
+}
+
+// std::addressof was introduced in C++11, an equivalent function is defined below
+// definition from http://en.cppreference.com/w/cpp/memory/addressof
+
diff --git a/Source/Processors/Visualization/SpikePlotting/PlotUtils.h b/Source/Processors/Visualization/SpikePlotting/PlotUtils.h
new file mode 100644
index 0000000000000000000000000000000000000000..43d7560e9ae340e8e469424ac43c93ebcbfe8a5b
--- /dev/null
+++ b/Source/Processors/Visualization/SpikePlotting/PlotUtils.h
@@ -0,0 +1,51 @@
+#ifndef PLOT_UTILS_H_
+#define PLOT_UTILS_H_
+
+
+#if defined(__linux__)
+	#include <GL/glut.h>
+#else // assume OS X
+	#include <GLUT/glut.h>
+	#include <OpenGL/glu.h>
+	#include <OpenGL/glext.h>
+#endif
+
+#include <stdio.h>
+#include <math.h>
+#include <cstring>
+#include <iostream>
+
+
+#define WAVE1 0
+#define WAVE2 1
+#define WAVE3 2
+#define WAVE4 3
+#define PROJ1x2 4
+#define PROJ1x3 5
+#define PROJ1x4 6
+#define PROJ2x3 7
+#define PROJ2x4 8
+#define PROJ3x4 9
+
+void checkGlError();
+void setViewportRange(int xMin,int xMax,int yMin,int yMax);
+void drawString(float x, float y, void *f, char *string);
+void strokeString(void*f, char *string);
+void drawViewportEdge();
+
+void drawViewportCross();
+
+int roundUp(int, int);
+
+double ad16ToUv(int ad, int gain);
+
+void makeLabel(int val, int gain, bool convert, char * s);
+
+void n2ProjIdx(int i, int *p1, int *p2);
+
+template< class T >
+T* addressof(T& arg) {
+    return (T*)&(char&)arg;
+}
+
+#endif
\ No newline at end of file
diff --git a/Source/Processors/Visualization/SpikePlotting/ProjectionAxes.cpp b/Source/Processors/Visualization/SpikePlotting/ProjectionAxes.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..1844d6aa9e95c4d2944f4097ee1234c0517c4265
--- /dev/null
+++ b/Source/Processors/Visualization/SpikePlotting/ProjectionAxes.cpp
@@ -0,0 +1,103 @@
+#include "ProjectionAxes.h"
+
+ProjectionAxes::ProjectionAxes():
+					GenericAxes(),
+					drawGrid(false),
+					overlay(false),
+					convertLabelUnits(true)
+{	
+	GenericAxes::gotFirstSpike = false;
+	GenericAxes::resizedFlag = false;
+
+	ylims[0] = 0;
+	ylims[1] = 1;
+	setPointColor(1.0,1.0,1.0);
+
+	BaseUIElement::elementName = (char*) "ProjectionAxes";
+}
+
+ProjectionAxes::ProjectionAxes(int x, int y, double w, double h, int t):
+					GenericAxes(x,y,w,h,t),
+					drawGrid(true),
+					overlay(false),
+					convertLabelUnits(true)
+{	
+	GenericAxes::gotFirstSpike = false;
+	GenericAxes::resizedFlag = false;
+
+	setPointColor(1.0,1.0,1.0);
+	
+	BaseUIElement::elementName = (char*) "ProjectionAxes";
+
+}
+
+void ProjectionAxes::updateSpikeData(SpikeObject newSpike){
+	//std::cout<<"ProjectionAxes::updateSpikeData()"<<std::endl;
+	GenericAxes::updateSpikeData(newSpike);
+
+}
+
+void ProjectionAxes::redraw(){
+	
+	BaseUIElement::redraw();
+	
+	plot();
+	
+	BaseUIElement::drawElementEdges();
+}
+
+
+void ProjectionAxes::plot(){
+
+	setViewportRange(xlims[0], ylims[0], xlims[1], ylims[1]);
+
+	int d1, d2;
+    n2ProjIdx(type, &d1, &d2);
+	
+	int idx1, idx2;
+	calcWaveformPeakIdx(d1,d2,&idx1, &idx2);
+
+	//if (drawGrid)
+	//	drawProjectionGrid(s.gain[d1], s.gain[d2]);
+
+	glColor3f(1.0, 1.0, 1.0);
+	glPointSize(1);
+
+	glBegin(GL_POINTS);
+        glVertex2f(s.data[idx1], s.data[idx2]);
+	glEnd();
+
+	// std::cout<<"ProjectionAxes Limits:"<<ylims[0]<<" "<<ylims[1]<<std::endl;
+	// std::cout<<"ProjectionAxes::plot()"<<s.data[idx1] << " " << s.data[idx2]<<std::endl;
+
+}
+
+ void ProjectionAxes::calcWaveformPeakIdx(int d1, int d2, int *idx1, int *idx2){
+
+	int max1 = -1*pow(2,15);
+	int max2 = max1;
+	
+	for (int i=0; i<s.nSamples ; i++){
+		if (s.data[d1*s.nSamples + i] > max1)
+		{	
+			*idx1 = d1*s.nSamples+i;
+			max1 = s.data[*idx1];
+		}
+		if (s.data[d2*s.nSamples+i] > max2)
+		{	
+			*idx2 = d2*s.nSamples+i;
+			max2 = s.data[*idx2];
+		}
+	}
+}
+
+void ProjectionAxes::setPointColor(GLfloat r, GLfloat g, GLfloat b){
+	pointColor[0] = r;
+	pointColor[1] = g;
+	pointColor[2] = b;
+}
+void ProjectionAxes::setGridColor(GLfloat r, GLfloat g, GLfloat b){
+	gridColor[0] = r;
+	gridColor[1] = g;
+	gridColor[2] = b;
+}
diff --git a/Source/Processors/Visualization/SpikePlotting/ProjectionAxes.h b/Source/Processors/Visualization/SpikePlotting/ProjectionAxes.h
new file mode 100644
index 0000000000000000000000000000000000000000..862075ca0fe243c32ba9c1313798cd381969b87d
--- /dev/null
+++ b/Source/Processors/Visualization/SpikePlotting/ProjectionAxes.h
@@ -0,0 +1,55 @@
+#ifndef PROJECTION_AXES_H_
+#define PROJECTION_AXES_H_
+
+#if defined(__linux__)
+	#include <GL/glut.h>
+#else
+	#include <GLUT/glut.h>
+#endif
+#include <stdlib.h>
+#include "BaseUIElement.h"
+#include "../SpikeObject.h"
+#include "PlotUtils.h"
+#include "GenericAxes.h"
+
+ 	
+class ProjectionAxes: public GenericAxes{
+	
+	GLfloat pointColor[3];
+	GLfloat gridColor[3];
+		
+	
+  	void drawProjectionGrid(int thold, int gain);
+  	void calcWaveformPeakIdx(int, int, int*, int*);
+
+protected:
+	void plot();
+
+
+public:
+	ProjectionAxes();
+	ProjectionAxes(int x, int y, double w, double h, int t);
+    
+   	void updateSpikeData(SpikeObject s);
+
+	void setPointColor(GLfloat r, GLfloat g, GLfloat b);
+	void setGridColor(GLfloat, GLfloat, GLfloat);
+	 
+	void redraw();
+	
+	
+	
+	bool overlay;
+	bool drawGrid;
+	bool convertLabelUnits;
+	
+};
+
+
+
+#endif  // PROJECTION_AXES_H_
+
+
+
+
+// #endif
diff --git a/Source/Processors/Visualization/SpikePlotting/SimpleKeyEvent.h b/Source/Processors/Visualization/SpikePlotting/SimpleKeyEvent.h
new file mode 100644
index 0000000000000000000000000000000000000000..1ce4277790e72b9f3d90dca14e4f187011adf23e
--- /dev/null
+++ b/Source/Processors/Visualization/SpikePlotting/SimpleKeyEvent.h
@@ -0,0 +1,25 @@
+#ifndef SIMPLE_KEY_EVENT_H
+#define SIMPLE_KEY_EVENT_H
+
+struct SimpleKeyEvent{
+    
+    int key;
+    bool shift;
+    bool ctrl;
+    bool alt;
+//    
+//    ArteKeyEvent(){
+//        key = 0;
+//        shift = false;
+//        ctrl = false;
+//        alt = false;
+//    }
+//    ArteKeyEvent(int k){
+//        key = k;
+//        shift = false;
+//        `ctrl = false;
+//        alt = false;
+//    }
+};
+
+#endif
\ No newline at end of file
diff --git a/Source/Processors/Visualization/SpikePlotting/SpikePlot.cpp b/Source/Processors/Visualization/SpikePlotting/SpikePlot.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/Source/Processors/Visualization/SpikePlotting/SpikePlot.h b/Source/Processors/Visualization/SpikePlotting/SpikePlot.h
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/Source/Processors/Visualization/SpikePlotting/StereotrodePlot.cpp b/Source/Processors/Visualization/SpikePlotting/StereotrodePlot.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..5579fad26bb53e5bb38c19927b73c53525af51ca
--- /dev/null
+++ b/Source/Processors/Visualization/SpikePlotting/StereotrodePlot.cpp
@@ -0,0 +1,298 @@
+#include "StereotrodePlot.h"
+#include "../SpikeObject.h"
+#include "PlotUtils.h"
+
+StereotrodePlot::StereotrodePlot():
+	BaseUIElement(), titleHeight(0), enableTitle(true), limitsChanged(true)
+{
+    plotTitle = (char*) "Stereotrode Plot";
+
+}
+
+StereotrodePlot::StereotrodePlot(int x, int y, int w, int h, char *n):
+	BaseUIElement(x,y,w,h,1), titleHeight(0), enableTitle(true), limitsChanged(true)
+{
+	plotTitle = n;
+	titleBox = TitleBox(x, y+h-titleHeight-3, w, titleHeight+3, plotTitle);
+
+	initAxes();
+}
+
+StereotrodePlot::~StereotrodePlot(){
+}
+
+// Each plot needs to update its children axes when its redraw gets called.
+//  it also needs to call the parent plot  when children axes get added it
+//  should place them in the correct location because it KNOWS where WAVE1 and PROJ1x3
+//  should go by default. This isn't as general as it should be but its a good push in
+//  the right direction
+
+void StereotrodePlot::redraw(){
+	 //std::cout<<"StereotrodePlot() starting drawing"<<std::endl;\
+	//BaseUIElement::clearNextDraw = true;
+	//BaseUIElement::redraw();
+
+	wAxes[0].redraw();
+    wAxes[1].redraw();
+    pAxes.redraw();
+}
+
+// This would normally happen for collection of axes but an electrode plot doesn't have a collection instead its a single axes
+void StereotrodePlot::processSpikeObject(SpikeObject s){
+	//std::cout<<"ElectrdePlot::processSpikeObject()"<<std::endl;
+	wAxes[0].updateSpikeData(s);
+    wAxes[1].updateSpikeData(s);
+    pAxes.updateSpikeData(s);
+}
+void StereotrodePlot::setTitle(char *n){
+	plotTitle = n;
+}
+
+void StereotrodePlot::setEnabled(bool e){
+	BaseUIElement::enabled = e;
+
+	wAxes[0].setEnabled(e);
+    wAxes[1].setEnabled(e);
+    pAxes.setEnabled(e);
+}
+
+bool StereotrodePlot::getEnabled(){
+	return BaseUIElement::enabled;
+}
+
+
+void StereotrodePlot::initAxes(){
+	initLimits();
+    
+    int minX = BaseUIElement::xpos;
+	int minY = BaseUIElement::ypos;
+	
+	double axesWidth = BaseUIElement::width/2;
+	double axesHeight = (BaseUIElement::height - titleHeight);
+	
+	
+	wAxes[0] = WaveAxes(minX, minY, axesWidth/2, axesHeight, WAVE1);
+    wAxes[1] = WaveAxes(minX + axesWidth/2, minY, axesWidth/2, axesHeight, WAVE2);
+    pAxes = ProjectionAxes(minX + axesWidth, minY, axesWidth, axesHeight, PROJ1x2);
+	
+    //axes.setEnabled(false);
+	wAxes[0].setYLims(-1*pow(2,11), pow(2,14)*1.6);
+    wAxes[1].setYLims(-1*pow(2,11), pow(2,14)*1.6);
+    pAxes.setYLims(-1*pow(2,11), pow(2,14)*1.6);
+    pAxes.setXLims(-1*pow(2,11), pow(2,14)*1.6);
+	
+    wAxes[0].setWaveformColor(1.0, 1.0, 1.0);
+    wAxes[1].setWaveformColor(1.0, 1.0, 1.0);
+    pAxes.setPointColor(1.0, 1.0, 1.0);
+
+}
+
+void StereotrodePlot::setPosition(int x, int y, double w, double h){
+	BaseUIElement::setPosition(x,y,w,h);
+	int minX = BaseUIElement::xpos;
+	int minY = BaseUIElement::ypos;
+	
+	double axesWidth = BaseUIElement::width;
+	double axesHeight = BaseUIElement::height - titleHeight;
+	
+    wAxes[0] = WaveAxes(minX, minY, axesWidth/2, axesHeight, WAVE1);
+    wAxes[1] = WaveAxes(minX + axesWidth/2, minY, axesWidth/2, axesHeight, WAVE2);	
+    pAxes = ProjectionAxes(minX + axesWidth, minY, axesWidth, axesHeight, PROJ1x2);
+
+    titleBox.setPosition(x, y+h-titleHeight-3, w, titleHeight+3);
+}
+
+int StereotrodePlot::getNumberOfAxes(){
+	return 1;;
+}
+
+void StereotrodePlot::clearOnNextDraw(bool b){
+	BaseUIElement::clearNextDraw = b;
+}
+
+void StereotrodePlot::setTitleEnabled(bool e){
+
+    // if the new setting does not equal the old than clear on the next draw
+    clearNextDraw = !(e!=enableTitle);
+
+    enableTitle = e;
+    if (e)
+        titleHeight = 15;
+    else
+        titleHeight = 0;
+    
+    setPosition(BaseUIElement::xpos, BaseUIElement::ypos, 
+                BaseUIElement::width, BaseUIElement::height);
+}
+void StereotrodePlot::initLimits(){
+    for (int i=0; i<4; i++)
+    {
+        limits[i][0] = -1*pow(2,11);
+        limits[i][1] = pow(2,14);
+    }
+
+}
+
+void StereotrodePlot::getPreferredDimensions(double *w, double *h){
+    *w = 75;
+    *h = 75;
+}
+// void StereotrodePlot::mouseDown(int x, int y){
+
+// //     selectedAxesN = -1;
+// //     std::list<GenericAxes>::iterator i;
+// //     int idx=-1;
+// //     bool hit = false;
+
+// //     selectedAxes = NULL;
+// //     for (i=axesList.begin(); i!=axesList.end(); ++i)
+// //     {
+// //         if (i->hitTest(x,y))
+// //         {
+// //             selectedAxes = addressof(*i);
+// //             selectedAxesN = i->getType();
+// //             hit = true;
+// // //            break;
+// //         }
+// //         idx++;
+// //     }
+// //     if (!hit)
+// //         selectedAxes = NULL;
+// //     if (selectedAxes != NULL)
+// //         std::cout<<"StereotrodePlot::mouseDown() hit:"<<selectedAxes<<" AxesType:"<<selectedaxes.getType()<<std::endl;
+// //     else
+// //         std::cout<<"StereotrodePlot::mouseDown() NO HIT!"<<std::endl;
+    
+// }
+// void StereotrodePlot::mouseDragX(int dx, bool shift, bool ctrl){
+
+// //     if (selectedAxes == NULL || dx==0)
+// //         return;
+// // //    zoomAxes(selectedaxes.getType(), true, dx>0);
+// //     if (shift)
+// //         zoomAxes(selectedAxesN, true, dx);
+// //     if (ctrl)
+// //         panAxes(selectedAxesN, true, dx);
+
+// }
+// void StereotrodePlot::mouseDragY(int dy, bool shift, bool ctrl){
+//     if (selectedAxes == NULL || dy==0)
+//         return;
+//     if(shift)
+//         zoomAxes(selectedAxesN, false, dy);
+//     if(ctrl)
+//         panAxes(selectedAxesN, false, dy);
+// }
+
+// void StereotrodePlot::zoomAxes(int n, bool xdim, int zoom){
+// //    std::cout<<"StereotrodePlot::zoomAxes() n:"<< n<<" xdim"<< xdim<<" in:"<<zoomin<<std::endl;
+//     // If trying to zoom an invalid axes type
+//     if (n<WAVE1 || n>PROJ3x4)
+//         return;
+//     if (n<=WAVE4)
+//         zoomWaveform(n, xdim, zoom);
+//     else
+//         zoomProjection(n, xdim, zoom);
+// }
+
+// void StereotrodePlot::zoomWaveform(int n, bool xdim, int zoom){
+
+//     // waveform plots don't have a xlimits
+//     if (xdim)
+//         return;
+// //    std::cout<<"Zooming Waveform:"<<n<<" zoomin:"<<zoomin<<" ";
+//     double min, max;
+    
+//     if(xdim)
+//         return;
+
+//     min = limits[n][0];
+//     max = limits[n][1];
+    
+//     double mean = (max + min)/2.0f;
+//     double delta = max - mean;
+//     delta = delta / pow(.99, -1*zoom);
+
+//     min = mean - delta;
+//     max = mean + delta;
+
+//     limits[n][0] = min;
+//     limits[n][1] = max;
+    
+//     limitsChanged = true;
+// }
+
+// void StereotrodePlot::panAxes(int n, bool xdim, int panval){
+//     //    std::cout<<"StereotrodePlot::zoomAxes() n:"<< n<<" xdim"<< xdim<<" in:"<<zoomin<<std::endl;
+//     // If trying to zoom an invalid axes type
+//     if (n<WAVE1 || n>PROJ3x4)
+//         return;
+//     if (n<=WAVE4)
+//         panWaveform(n, xdim, panval);
+//     else
+//         panProjection(n, xdim, panval);
+// }
+
+// void StereotrodePlot::panWaveform(int n, bool xdim, int pan){
+    
+//     // waveform plots don't have a xlimits
+//     if (xdim)
+//         return;
+//     //    std::cout<<"Panning Waveform:"<<n<<" pan:"<<pan<<" "<<std::endl;
+//     double min, max;
+    
+//     if(xdim)
+//         return;
+    
+//     min = limits[n][0];
+//     max = limits[n][1];
+    
+//     double dy = max-min;
+    
+//     // Need to grab something if pan event is driven by the keyboard, which means that all the plots are getting panned so this should be okay
+//     if (selectedAxes == NULL)
+//         selectedAxes = &axesList.front();
+    
+//     double yPixels = (BaseUIElement::height - titleHeight)/2.0;
+    
+//     double pixelWidth = -1 * dy/yPixels;
+    
+//     double delta = pan * pixelWidth;
+//     min = min + delta;
+//     max = max + delta;
+    
+//     limits[n][0] = min;
+//     limits[n][1] = max;
+    
+//     limitsChanged = true;
+// }
+
+
+
+bool StereotrodePlot::processKeyEvent(SimpleKeyEvent k){
+    // std::cout<<"Key:"<<(char)k.key<<std::endl;
+    // switch(k.key)
+    // {
+    //     case '=':
+    //         for (int i=0; i<=WAVE4; i++)
+    //             zoomWaveform(i, false, 3);
+    //         break;        
+    //     case '+':
+    //         for (int i=0; i<=WAVE4; i++)
+    //             panWaveform(i, false, 3);
+    //         break;
+    //     case '-':
+    //         for (int i=0; i<=WAVE4; i++)
+    //             zoomWaveform(i, false, -3);
+    //         break;    
+    //     case '_':
+    //         for (int i=0; i<=WAVE4; i++)
+    //             panWaveform(i, false, -3);
+    //         break;
+    //     case 'C':
+    //         clearOnNextDraw(true);
+    //         break;
+    // }
+}
+
+
diff --git a/Source/Processors/Visualization/SpikePlotting/StereotrodePlot.h b/Source/Processors/Visualization/SpikePlotting/StereotrodePlot.h
new file mode 100644
index 0000000000000000000000000000000000000000..dfbef07329239bf6f8e377f07b096c0f8632f954
--- /dev/null
+++ b/Source/Processors/Visualization/SpikePlotting/StereotrodePlot.h
@@ -0,0 +1,81 @@
+#ifndef STEROETRODE_PLOT_H_
+#define STEROETRODE_PLOT_H_
+
+#if defined(__linux__)
+	#include <GL/glut.h>
+#else
+	#include <GLUT/glut.h>
+#endif
+#include <list>
+#include <math.h>
+
+#include "WaveAxes.h"
+#include "ProjectionAxes.h"
+#include "TitleBox.h"
+#include "BaseUIElement.h"
+#include "TetrodeSource.h"
+#include "PlotUtils.h"
+#include "SimpleKeyEvent.h"
+
+
+class StereotrodePlot : public BaseUIElement{
+	
+	char *plotTitle;
+	
+	TitleBox titleBox;
+
+	bool enabled;
+    bool enableTitle;
+	void drawTitle();
+	
+	double titleHeight;
+    
+    bool limitsChanged;
+    double limits[1][2];
+    
+    WaveAxes wAxes[2];
+    ProjectionAxes pAxes;
+    
+    
+    
+    // void zoomAxes(int n, bool xdim, int zoomval);
+    // void zoomProjection (int n, bool xdim, int zoomval);
+    // void zoomWaveform (int n, bool xdim, int zoomval);
+    
+    // void panAxes(int n, bool xdim, int panval);
+    // void panProjection (int n, bool xdim, int panval);
+    // void panWaveform(int n, bool xdim, int panval);
+    
+    void initLimits();
+	
+public:
+	StereotrodePlot();
+	StereotrodePlot(int x, int y,int w,int h, char *n);
+	~StereotrodePlot();
+
+	void initAxes();
+	void redraw();
+	void setTitle(char *n);
+	void setEnabled(bool enabled);
+	bool getEnabled();
+	void setPosition(int,int,double,double);
+
+	void getPreferredDimensions(double*, double*);
+
+	int getNumberOfAxes();
+	void clearOnNextDraw(bool c);
+    void setTitleEnabled(bool e);
+    
+    void mouseDown(int x, int y);
+    
+    void mouseDragX(int dx, bool shift, bool ctr);
+    void mouseDragY(int dy, bool shift, bool ctr);
+
+    bool processKeyEvent(SimpleKeyEvent k);
+
+    void processSpikeObject(SpikeObject s);
+};
+
+
+
+#endif
diff --git a/Source/Processors/Visualization/SpikePlotting/TetrodePlot.cpp b/Source/Processors/Visualization/SpikePlotting/TetrodePlot.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..e2580437065c05d41f7243fe8bbc9cd5454e5036
--- /dev/null
+++ b/Source/Processors/Visualization/SpikePlotting/TetrodePlot.cpp
@@ -0,0 +1,331 @@
+#include "TetrodePlot.h"
+#include "../SpikeObject.h"
+#include "PlotUtils.h"
+
+TetrodePlot::TetrodePlot():
+    BaseUIElement(), titleHeight(0), enableTitle(true), limitsChanged(true)
+{
+    plotTitle = (char*) "Tetrode Plot";
+
+}
+
+TetrodePlot::TetrodePlot(int x, int y, int w, int h, char *n):
+    BaseUIElement(x,y,w,h,1), titleHeight(0), enableTitle(true), limitsChanged(true)
+{
+    plotTitle = n;
+    titleBox = TitleBox(x, y+h-titleHeight-3, w, titleHeight+3, plotTitle);
+
+    initAxes();
+}
+
+TetrodePlot::~TetrodePlot(){
+}
+
+// Each plot needs to update its children axes when its redraw gets called.
+//  it also needs to call the parent plot  when children axes get added it
+//  should place them in the correct location because it KNOWS where WAVE1 and PROJ1x3
+//  should go by default. This isn't as general as it should be but its a good push in
+//  the right direction
+
+void TetrodePlot::redraw(){
+     //std::cout<<"TetrodePlot() starting drawing"<<std::endl;\
+    BaseUIElement::clearNextDraw = true;
+   
+    BaseUIElement::redraw();
+   
+    for (int i=0; i<4; i++)
+        wAxes[i].redraw();
+
+    for (int i=0; i<6; i++)
+        pAxes[i].redraw();
+}
+
+// This would normally happen for collection of axes but an electrode plot doesn't have a collection instead its a single axes
+void TetrodePlot::processSpikeObject(SpikeObject s){
+    //std::cout<<"ElectrdePlot::processSpikeObject()"<<std::endl;
+    for (int i=0; i<4; i++)
+        wAxes[i].updateSpikeData(s);
+    for (int i=0; i<6; i++)
+        pAxes[i].updateSpikeData(s);
+}
+void TetrodePlot::setTitle(char *n){
+    plotTitle = n;
+}
+
+void TetrodePlot::setEnabled(bool e){
+    BaseUIElement::enabled = e;
+    for (int i=0; i<4; i++)
+        wAxes[i].setEnabled(e);
+    for (int i=0; i<6; i++)
+        pAxes[i].setEnabled(e);
+}
+
+bool TetrodePlot::getEnabled(){
+    return BaseUIElement::enabled;
+}
+
+
+void TetrodePlot::initAxes(){
+    initLimits();
+    
+    int minX = BaseUIElement::xpos;
+    int minY = BaseUIElement::ypos;
+    
+    // because axesWidth and axesHeight won't always divide evenly we'll add .5 to the ending value to round 
+    // to the nearest integer, this forces the box to draw to the next biggest pixel if needed. this prevents
+    // black borders from forming around the boxes
+    int axesWidth = BaseUIElement::width/4 + .5; 
+    int axesHeight = (BaseUIElement::height - titleHeight)/2 + .5;
+    
+    
+    wAxes[0] = WaveAxes(minX, minY, axesWidth/2, axesHeight, WAVE1);
+    wAxes[1] = WaveAxes(minX + axesWidth/2, minY, axesWidth/2, axesHeight, WAVE2);
+    wAxes[2] = WaveAxes(minX, minY + axesHeight, axesWidth/2, axesHeight, WAVE3);
+    wAxes[3] = WaveAxes(minX + axesWidth/2, minY + axesHeight, axesWidth/2, axesHeight, WAVE3);
+
+    pAxes[0] = ProjectionAxes(minX + axesWidth*1, minY, axesWidth, axesHeight, PROJ1x2);
+    pAxes[1] = ProjectionAxes(minX + axesWidth*2, minY, axesWidth, axesHeight, PROJ1x3);
+    pAxes[2] = ProjectionAxes(minX + axesWidth*3, minY, axesWidth, axesHeight, PROJ1x4);
+    pAxes[3] = ProjectionAxes(minX + axesWidth*1, minY + axesHeight, axesWidth, axesHeight, PROJ2x3);
+    pAxes[4] = ProjectionAxes(minX + axesWidth*2, minY + axesHeight, axesWidth, axesHeight, PROJ2x4);
+    pAxes[5] = ProjectionAxes(minX + axesWidth*3, minY + axesHeight, axesWidth, axesHeight, PROJ3x4);
+
+    
+    //axes.setEnabled(false);
+    for (int i=0; i<4; i++){
+        wAxes[i].setYLims(-1*pow(2,11), pow(2,14)*1.6);
+        wAxes[i].setWaveformColor(1.0, 1.0, 1.0);
+    }
+    for (int i=0; i<6; i++)
+    {
+        pAxes[i].setYLims(-1*pow(2,11), pow(2,14)*1.6);
+        pAxes[i].setPointColor(1.0, 1.0, 1.0);
+    }
+
+}
+
+void TetrodePlot::setPosition(int x, int y, double w, double h){
+    BaseUIElement::setPosition(x,y,w,h);
+    int minX = BaseUIElement::xpos;
+    int minY = BaseUIElement::ypos;
+    
+    int axesWidth = BaseUIElement::width/4;
+    int axesHeight = BaseUIElement::height - titleHeight/2;
+    
+    wAxes[0].setPosition(minX, minY, axesWidth/2, axesHeight);
+    wAxes[1].setPosition(minX + axesWidth/2, minY, axesWidth/2, axesHeight);
+    wAxes[2].setPosition(minX, minY + axesHeight, axesWidth/2, axesHeight);
+    wAxes[3].setPosition(minX + axesWidth/2, minY + axesHeight, axesWidth/2, axesHeight);
+
+    pAxes[0].setPosition(minX + axesWidth*1, minY, axesWidth, axesHeight);
+    pAxes[1].setPosition(minX + axesWidth*2, minY, axesWidth, axesHeight);
+    pAxes[2].setPosition(minX + axesWidth*3, minY, axesWidth, axesHeight);
+    pAxes[3].setPosition(minX + axesWidth*1, minY + axesHeight, axesWidth, axesHeight);
+    pAxes[4].setPosition(minX + axesWidth*2, minY + axesHeight, axesWidth, axesHeight);
+    pAxes[5].setPosition(minX + axesWidth*3, minY + axesHeight, axesWidth, axesHeight);
+
+    //titleBox.setPosition(x, y+h-titleHeight-3, w, titleHeight+3);
+}
+
+void TetrodePlot::setPosition(int x, int y){
+    setPosition(x,y, BaseUIElement::width, BaseUIElement::height );
+}
+
+void TetrodePlot::setDimensions(double w, double h){
+    setPosition(BaseUIElement::xpos, BaseUIElement::ypos, w, h);
+}
+
+int TetrodePlot::getNumberOfAxes(){
+    return 1;;
+}
+
+void TetrodePlot::clearOnNextDraw(bool b){
+    BaseUIElement::clearNextDraw = b;
+}
+
+void TetrodePlot::setTitleEnabled(bool e){
+
+    // if the new setting does not equal the old than clear on the next draw
+    clearNextDraw = !(e!=enableTitle);
+
+    enableTitle = e;
+    if (e)
+        titleHeight = 15;
+    else
+        titleHeight = 0;
+    
+    setPosition(BaseUIElement::xpos, BaseUIElement::ypos, 
+                BaseUIElement::width, BaseUIElement::height);
+}
+void TetrodePlot::initLimits(){
+    for (int i=0; i<4; i++)
+    {
+        limits[i][0] = -1*pow(2,11);
+        limits[i][1] = pow(2,14);
+    }
+
+}
+
+void TetrodePlot::getPreferredDimensions(double *w, double *h){
+    *w = 75;
+    *h = 75;
+}
+// void TetrodePlot::mouseDown(int x, int y){
+
+// //     selectedAxesN = -1;
+// //     std::list<GenericAxes>::iterator i;
+// //     int idx=-1;
+// //     bool hit = false;
+
+// //     selectedAxes = NULL;
+// //     for (i=axesList.begin(); i!=axesList.end(); ++i)
+// //     {
+// //         if (i->hitTest(x,y))
+// //         {
+// //             selectedAxes = addressof(*i);
+// //             selectedAxesN = i->getType();
+// //             hit = true;
+// // //            break;
+// //         }
+// //         idx++;
+// //     }
+// //     if (!hit)
+// //         selectedAxes = NULL;
+// //     if (selectedAxes != NULL)
+// //         std::cout<<"TetrodePlot::mouseDown() hit:"<<selectedAxes<<" AxesType:"<<selectedaxes.getType()<<std::endl;
+// //     else
+// //         std::cout<<"TetrodePlot::mouseDown() NO HIT!"<<std::endl;
+    
+// }
+// void TetrodePlot::mouseDragX(int dx, bool shift, bool ctrl){
+
+// //     if (selectedAxes == NULL || dx==0)
+// //         return;
+// // //    zoomAxes(selectedaxes.getType(), true, dx>0);
+// //     if (shift)
+// //         zoomAxes(selectedAxesN, true, dx);
+// //     if (ctrl)
+// //         panAxes(selectedAxesN, true, dx);
+
+// }
+// void TetrodePlot::mouseDragY(int dy, bool shift, bool ctrl){
+//     if (selectedAxes == NULL || dy==0)
+//         return;
+//     if(shift)
+//         zoomAxes(selectedAxesN, false, dy);
+//     if(ctrl)
+//         panAxes(selectedAxesN, false, dy);
+// }
+
+// void TetrodePlot::zoomAxes(int n, bool xdim, int zoom){
+// //    std::cout<<"TetrodePlot::zoomAxes() n:"<< n<<" xdim"<< xdim<<" in:"<<zoomin<<std::endl;
+//     // If trying to zoom an invalid axes type
+//     if (n<WAVE1 || n>PROJ3x4)
+//         return;
+//     if (n<=WAVE4)
+//         zoomWaveform(n, xdim, zoom);
+//     else
+//         zoomProjection(n, xdim, zoom);
+// }
+
+// void TetrodePlot::zoomWaveform(int n, bool xdim, int zoom){
+
+//     // waveform plots don't have a xlimits
+//     if (xdim)
+//         return;
+// //    std::cout<<"Zooming Waveform:"<<n<<" zoomin:"<<zoomin<<" ";
+//     double min, max;
+    
+//     if(xdim)
+//         return;
+
+//     min = limits[n][0];
+//     max = limits[n][1];
+    
+//     double mean = (max + min)/2.0f;
+//     double delta = max - mean;
+//     delta = delta / pow(.99, -1*zoom);
+
+//     min = mean - delta;
+//     max = mean + delta;
+
+//     limits[n][0] = min;
+//     limits[n][1] = max;
+    
+//     limitsChanged = true;
+// }
+
+// void TetrodePlot::panAxes(int n, bool xdim, int panval){
+//     //    std::cout<<"TetrodePlot::zoomAxes() n:"<< n<<" xdim"<< xdim<<" in:"<<zoomin<<std::endl;
+//     // If trying to zoom an invalid axes type
+//     if (n<WAVE1 || n>PROJ3x4)
+//         return;
+//     if (n<=WAVE4)
+//         panWaveform(n, xdim, panval);
+//     else
+//         panProjection(n, xdim, panval);
+// }
+
+// void TetrodePlot::panWaveform(int n, bool xdim, int pan){
+    
+//     // waveform plots don't have a xlimits
+//     if (xdim)
+//         return;
+//     //    std::cout<<"Panning Waveform:"<<n<<" pan:"<<pan<<" "<<std::endl;
+//     double min, max;
+    
+//     if(xdim)
+//         return;
+    
+//     min = limits[n][0];
+//     max = limits[n][1];
+    
+//     double dy = max-min;
+    
+//     // Need to grab something if pan event is driven by the keyboard, which means that all the plots are getting panned so this should be okay
+//     if (selectedAxes == NULL)
+//         selectedAxes = &axesList.front();
+    
+//     double yPixels = (BaseUIElement::height - titleHeight)/2.0;
+    
+//     double pixelWidth = -1 * dy/yPixels;
+    
+//     double delta = pan * pixelWidth;
+//     min = min + delta;
+//     max = max + delta;
+    
+//     limits[n][0] = min;
+//     limits[n][1] = max;
+    
+//     limitsChanged = true;
+// }
+
+
+
+bool TetrodePlot::processKeyEvent(SimpleKeyEvent k){
+    // std::cout<<"Key:"<<(char)k.key<<std::endl;
+    // switch(k.key)
+    // {
+    //     case '=':
+    //         for (int i=0; i<=WAVE4; i++)
+    //             zoomWaveform(i, false, 3);
+    //         break;        
+    //     case '+':
+    //         for (int i=0; i<=WAVE4; i++)
+    //             panWaveform(i, false, 3);
+    //         break;
+    //     case '-':
+    //         for (int i=0; i<=WAVE4; i++)
+    //             zoomWaveform(i, false, -3);
+    //         break;    
+    //     case '_':
+    //         for (int i=0; i<=WAVE4; i++)
+    //             panWaveform(i, false, -3);
+    //         break;
+    //     case 'C':
+    //         clearOnNextDraw(true);
+    //         break;
+    // }
+}
+
+
diff --git a/Source/Processors/Visualization/SpikePlotting/TetrodePlot.h b/Source/Processors/Visualization/SpikePlotting/TetrodePlot.h
new file mode 100644
index 0000000000000000000000000000000000000000..d7854246843188812274d80c3753bd1f26c01628
--- /dev/null
+++ b/Source/Processors/Visualization/SpikePlotting/TetrodePlot.h
@@ -0,0 +1,84 @@
+#ifndef TETRODE_PLOT_H_
+#define TETRODE_PLOT_H_
+
+#if defined(__linux__)
+	#include <GL/glut.h>
+#else
+	#include <GLUT/glut.h>
+#endif
+#include <list>
+#include <math.h>
+
+#include "WaveAxes.h"
+#include "ProjectionAxes.h"
+#include "TitleBox.h"
+#include "BaseUIElement.h"
+#include "TetrodeSource.h"
+#include "PlotUtils.h"
+#include "SimpleKeyEvent.h"
+
+
+class TetrodePlot : public BaseUIElement{
+	
+	char *plotTitle;
+	
+	TitleBox titleBox;
+
+	bool enabled;
+    bool enableTitle;
+	void drawTitle();
+	
+	double titleHeight;
+    
+    bool limitsChanged;
+    double limits[1][2];
+    
+    WaveAxes wAxes[4];
+    ProjectionAxes pAxes[6];
+    
+    
+    
+    // void zoomAxes(int n, bool xdim, int zoomval);
+    // void zoomProjection (int n, bool xdim, int zoomval);
+    // void zoomWaveform (int n, bool xdim, int zoomval);
+    
+    // void panAxes(int n, bool xdim, int panval);
+    // void panProjection (int n, bool xdim, int panval);
+    // void panWaveform(int n, bool xdim, int panval);
+    
+    void initLimits();
+	
+public:
+	TetrodePlot();
+	TetrodePlot(int x, int y,int w,int h, char *n);
+	~TetrodePlot();
+
+	void initAxes();
+	void redraw();
+	void setTitle(char *n);
+	void setEnabled(bool enabled);
+	bool getEnabled();
+	
+	void setPosition(int,int,double,double);
+	void setPosition(int, int);
+	void setDimensions(double,double);
+
+	void getPreferredDimensions(double*, double*);
+
+	int getNumberOfAxes();
+	void clearOnNextDraw(bool c);
+    void setTitleEnabled(bool e);
+    
+    void mouseDown(int x, int y);
+    
+    void mouseDragX(int dx, bool shift, bool ctr);
+    void mouseDragY(int dy, bool shift, bool ctr);
+
+    bool processKeyEvent(SimpleKeyEvent k);
+
+    void processSpikeObject(SpikeObject s);
+};
+
+
+
+#endif
diff --git a/Source/Processors/Visualization/SpikePlotting/TetrodeSource.cpp b/Source/Processors/Visualization/SpikePlotting/TetrodeSource.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..5399e90b475ed53cf7a7ea0c9cc551eb423faf51
--- /dev/null
+++ b/Source/Processors/Visualization/SpikePlotting/TetrodeSource.cpp
@@ -0,0 +1,105 @@
+
+// #include "TetrodeSource.h"
+// TetrodeSource::TetrodeSource():
+// 					nSpikesRead(0),
+// 					readingPackets(false){
+// 	port = NULL;
+// }
+// TetrodeSource::TetrodeSource(char *p):
+// 					nSpikesRead(0),
+// 					readingPackets(false){
+// 	port = p;
+// }
+
+// bool TetrodeSource::setPort(char *p){
+// 	if (readingPackets)
+// 		return false;
+// 	else
+// 		port = p;
+// 	return true;
+// }	
+// bool TetrodeSource::getNextSpike(spike_net_t *spike){
+// //	printf("size of spikebuffer:%d\n", (int)spikebuffer.size());
+// 	pthread_mutex_lock(&mtx);
+// 	if ( spikebuffer.empty()){
+// //		std::cout<<"TetrodeSource::getNextSpike(), spikebuffer is empty"<<std::endl;
+// 		pthread_mutex_unlock(&mtx);
+// 		return false;
+// 	}
+
+// 	else{
+// 		spike_net_t s;
+// 		s = spikebuffer.front();
+// 		*spike = s;
+// 		spikebuffer.pop();
+// //		std::cout<<"TetrodeSource::getNextSpike() popped spike from the buffer"<<std::endl;
+// 		pthread_mutex_unlock(&mtx);
+// 		return true;
+// 	}		
+// }
+
+// void TetrodeSource::enableSource(){
+// 	pthread_mutex_lock(&mtx);
+// 	spikebuffer = std::queue<spike_net_t>();
+// 	pthread_mutex_unlock(&mtx);
+
+// 	if (port==NULL)
+// 	{
+// 		std::cout<<"TetrodeSource::enableSource(), No port specified, it is currently NULL"<<std::endl;
+// 	}
+// 	std::cout<<"Initializing a new TetrodeSource on port:"<<port<<"\n"<<std::flush;
+
+// 	pthread_t netThread;
+// 	net = NetCom::initUdpRx(host,port);
+// 	pthread_create(&netThread, NULL, networkThreadFunc, this);
+// }
+// void TetrodeSource::disableSource(){
+// 	readingPackets = false;	
+// }
+
+// void TetrodeSource::getNetworkSpikePackets(){
+// 	readingPackets = true;
+// 	std::cout<<"TetrodeSource::getNetworkSpikePackets starting!"<<std::endl;
+// 	while(readingPackets){
+
+// 		spike_net_t newSpike;
+// 		NetCom::rxSpike(net, &newSpike);
+// 		pthread_mutex_lock(&mtx);
+
+// /*		
+// 		while (spikebuffer.size()>MAX_SPIKE_BUFF_SIZE){
+// 			std::cout<<"Too many spikes in the buffer, removing some. Spikes in buffer:"<<spikebuffer.size()<<std::endl;
+// 			spikebuffer.pop();
+// 		}
+// 		*/
+// 		spikebuffer.push(newSpike);
+// 		nSpikesRead++;
+// //		printf("Read %d spikes, %d in buffer\n", nSpikesRead, spikebuffer.size());
+// //		printf("\t New Spike timestamp:%d\n",newSpike.ts);
+// 		pthread_mutex_unlock(&mtx);
+		
+// 		if (nSpikesRead%100==0)
+// 			std::cout<<"TetrodeSource::getNetworkSpikePackets() read a total of:"<<nSpikesRead<<" spikes"<<std::endl;
+// 	}
+// 	std::cout<<"TetrodeSource::getNetworkSpikePackets ending!"<<std::endl;
+// }
+
+// int TetrodeSource::getBufferSize(){
+// 	pthread_mutex_lock(&mtx);
+// 	return spikebuffer.size();
+// 	pthread_mutex_unlock(&mtx);
+// }
+// void TetrodeSource::flush(){
+// 	pthread_mutex_lock(&mtx);
+// 	std::queue<spike_net_t> empty;
+// 	spikebuffer = empty;
+// 	pthread_mutex_unlock(&mtx);
+	
+// }
+// void *networkThreadFunc(void *ptr){
+// 	TetrodeSource *tp = (TetrodeSource*) ptr;
+// 	tp->getNetworkSpikePackets();
+// }
+
+
+
diff --git a/Source/Processors/Visualization/SpikePlotting/TetrodeSource.h b/Source/Processors/Visualization/SpikePlotting/TetrodeSource.h
new file mode 100644
index 0000000000000000000000000000000000000000..f9ada5a022d3afbcd0ea59b82f34119327cb1470
--- /dev/null
+++ b/Source/Processors/Visualization/SpikePlotting/TetrodeSource.h
@@ -0,0 +1,51 @@
+// #ifndef TETRODE_SOURCE_H_
+// #define TETRODE_SOURCE_H_
+
+// #include <iostream>
+// #include <queue>
+
+// #include <pthread.h>
+// #include <stdio.h>
+// #include <iostream>
+// #include <stdlib.h>
+// #include <assert.h>
+// #include <pthread.h>
+
+// //#include "netcom.h"
+// #include "../SpikeObject.h"
+
+
+// class TetrodeSource{
+	
+// 	char host[128];// = "127.0.0.1";
+// 	char * port;
+// 	NetComDat net; // = NetCom::initUdpRx(host,port);
+// 	static int const MAX_SPIKE_BUFF_SIZE = 4000;
+// 	std::queue<spike_net_t> spikebuffer;
+// 	uint32_t nSpikesRead;
+// 	pthread_mutex_t mtx;
+// 	spike_net_t tmpSpike;
+// 	bool readingPackets;
+
+
+// public:
+// 	double padLeft, padRight, padTop, padBottom;
+	
+// 	TetrodeSource();
+// 	TetrodeSource(char *p);
+	
+// 	bool setPort(char *p);
+// 	void enableSource();
+// 	void disableSource();
+// 	void getNetworkSpikePackets();
+// 	bool getNextSpike(spike_net_t * spike);	
+	
+// 	uint32_t getNSpikesRead();
+// 	int getBufferSize();
+// 	void flush();	
+// };
+
+
+// void* networkThreadFunc(void* arg);
+
+// #endif
diff --git a/Source/Processors/Visualization/SpikePlotting/TitleBox.cpp b/Source/Processors/Visualization/SpikePlotting/TitleBox.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..0f9a9ed813300f933f8ae7fabfd0b4315db45103
--- /dev/null
+++ b/Source/Processors/Visualization/SpikePlotting/TitleBox.cpp
@@ -0,0 +1,76 @@
+#include "TitleBox.h"
+#include "PlotUtils.h"
+
+TitleBox::TitleBox():
+BaseUIElement(0,0,15,100,0)
+{
+	setColor(.15, .15, .50);
+	setSelectedColor(.15, .50, .15);
+	selected = false;
+	BaseUIElement::elementName = (char*) "TitleBox - Un initialized";
+	title = (char *) "Tetrode:00 abcdefghijkl";
+}
+
+TitleBox::TitleBox(int x, int y,int w,int h, char *n):
+BaseUIElement(x,y,w,h,0)
+{
+	setColor(.15, .15, .50);
+	setSelectedColor(.15, .50, .15);
+	selected = false;
+	BaseUIElement::elementName = (char*) "TitleBox";
+	title = n;//(char *) "Tetrode:00 No Port or Label";
+}
+
+void TitleBox::redraw(){
+	BaseUIElement::redraw();
+	
+	if(selected)
+			glColor3fv(selectedColor);
+		else
+			glColor3fv(titleColor);
+
+	// draw the colored background for the plot
+	glRecti(-1,-1,1,1);
+
+	// Reset color to white so we can draw the title text in white
+	glColor3f(1.0, 1.0, 1.0);
+	void * font;// = GLUT_BITMAP_9_BY_15;
+	
+	// We want the title string to be centered in the box regardless of how 
+	// many chars are in the title. To do this we must compute the proper X offset
+	// for the title string. Using a 9x15 font each char is 9 pixels wide. 
+	// convert from chars to pixels and then normalize using the size of the window.
+	// We don't have to devide by two to center the string because the dynamic
+	// range of the viewport goes from -1 to 1 and the following equatition treats it as 1
+	// we would then have to multiply and divide by 2 which is redundant so we dont
+	float xOffset = -1*( (float) strlen(title) * 9.0) / ( BaseUIElement::width);
+	if (xOffset<-.95)
+		xOffset = -.95;
+
+	drawString(xOffset, -.6, font, title);
+	
+	BaseUIElement::drawElementEdges();
+}
+
+
+void TitleBox::setTitle(char *n){
+	title = n;
+}
+void TitleBox::setSelected(bool sel){
+	selected = sel;
+}
+
+void TitleBox::setColor(GLfloat r, GLfloat g, GLfloat b){
+	titleColor[0] = r;
+	titleColor[1] = g;
+	titleColor[2] = b;
+}
+void TitleBox::setSelectedColor(GLfloat r, GLfloat g, GLfloat b){
+	selectedColor[0] = r;
+	selectedColor[1] = g;
+	selectedColor[2] = b;
+}
+
+void TitleBox::setPosition(int x, int y, double w, double h){
+	BaseUIElement::setPosition(x,y,w,h);
+}
\ No newline at end of file
diff --git a/Source/Processors/Visualization/SpikePlotting/TitleBox.h b/Source/Processors/Visualization/SpikePlotting/TitleBox.h
new file mode 100644
index 0000000000000000000000000000000000000000..c3c35553a98fafdb95983487a2b5e9d3e62d26f1
--- /dev/null
+++ b/Source/Processors/Visualization/SpikePlotting/TitleBox.h
@@ -0,0 +1,35 @@
+#ifndef TITLE_BOX_H_
+#define TITLE_BOX_H_
+
+#if defined(__linux__)
+	#include <GL/glut.h>
+#else
+	#include <GLUT/glut.h>
+#endif
+
+#include "BaseUIElement.h"
+
+
+class TitleBox : public BaseUIElement{
+	
+	char *title;
+	bool selected;
+	void drawTitle();
+	
+	GLfloat titleColor[3];
+	GLfloat selectedColor[3];
+	
+public:
+	TitleBox();
+	TitleBox(int x, int y,int w,int h, char *n);
+
+	void redraw();
+	void setTitle(char *n);
+	void setSelected(bool sel);
+	void setColor(float, float, float);
+	void setSelectedColor(float, float, float);
+	void setPosition(int,int,double,double);
+};
+
+
+#endif
diff --git a/Source/Processors/Visualization/SpikePlotting/WaveAxes.cpp b/Source/Processors/Visualization/SpikePlotting/WaveAxes.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..1b1248df05fd30b09ce642f151fef6693c59f286
--- /dev/null
+++ b/Source/Processors/Visualization/SpikePlotting/WaveAxes.cpp
@@ -0,0 +1,204 @@
+#include "WaveAxes.h"
+
+WaveAxes::WaveAxes():
+					GenericAxes(),
+					drawWaveformLine(true),
+					drawWaveformPoints(false),
+					drawGrid(true),
+					overlay(false),
+					convertLabelUnits(true)
+{	
+	GenericAxes::gotFirstSpike = false;
+	GenericAxes::resizedFlag = false;
+
+	ylims[0] = 0;
+	ylims[1] = 1;
+	setWaveformColor(1.0,1.0,0.6);
+	setThresholdColor(1.0, 0.1, 0.1);
+	setGridColor(0.4, 0.2, 0.2);
+	
+	BaseUIElement::elementName = (char*) "WaveAxes";
+}
+
+WaveAxes::WaveAxes(int x, int y, double w, double h, int t):
+					GenericAxes(x,y,w,h,t),
+					drawWaveformLine(true),
+					drawWaveformPoints(false),
+					drawGrid(true),
+					overlay(false),
+					convertLabelUnits(true)
+{	
+	GenericAxes::gotFirstSpike = false;
+	GenericAxes::resizedFlag = false;
+
+	setWaveformColor(1.0,1.0,0.6);
+	setThresholdColor(1.0, 0.1, 0.1);
+	setGridColor(0.2, 0.2, 0.2);
+	BaseUIElement::elementName = (char*) "WaveAxes";
+
+}
+
+void WaveAxes::updateSpikeData(SpikeObject newSpike){
+	//std::cout<<"WaveAxes::updateSpikeData()"<<std::endl;
+	GenericAxes::updateSpikeData(newSpike);
+
+}
+
+void WaveAxes::redraw(){
+	
+	BaseUIElement::redraw();
+	
+	plot();
+	
+	BaseUIElement::drawElementEdges();
+}
+
+
+void WaveAxes::plot(){
+
+	int chan = 0;
+	// If no spikes have been received then don't plot anything
+	if (!gotFirstSpike)
+	{
+		std::cout<<"\tWaiting for the first spike"<<std::endl;
+		return;
+	}
+	
+	// Set the plotting range for the current axes the xlims member is ignored as the xdims are 0->number of samples per waveform minus one
+    // so the line goes all the way to the edges ydims are specified by the ylims vector		
+	setViewportRange(0, ylims[0], s.nSamples-1, ylims[1]);
+	
+	// draw the grid lines for the waveforms?
+	if(drawGrid)
+		drawWaveformGrid(s.threshold[chan], s.gain[chan]);
+	
+	//compute the spatial width for each wawveform sample	
+	float dx = 1;
+	float x = 0;
+
+	// type corresponds to channel so we need to calculate the starting
+	// sample based upon which channel is getting plotted
+	// type values are defined in PlotUtils.h 
+	int	sampIdx = s.nSamples * type; //  
+	//std::cout<<"Starting with idx:"<<sampIdx<<std::endl;
+
+	//Draw the individual waveform points connected with a line
+	glColor3fv(waveColor);
+	glLineWidth(1);
+	glBegin( GL_LINE_STRIP );
+	
+	int dSamples = 1;
+	for (int i=0; i<s.nSamples; i++)
+	{
+		//std::cout<<"\t"<<s.data[sampIdx];
+		glVertex2f(x, s.data[sampIdx]);
+		sampIdx += dSamples;
+		x +=dx; 
+	}
+	
+	glEnd();
+	// std::cout<<std::endl;
+	
+
+	// Draw the threshold line and label
+	
+	glColor3fv(thresholdColor);
+	glLineWidth(1); 
+	glLineStipple(4, 0xAAAA); // make a dashed line
+	glEnable(GL_LINE_STIPPLE);
+
+	glBegin( GL_LINE_STRIP );
+		glVertex2f(0, s.threshold[chan]);
+		glVertex2f(s.nSamples, s.threshold[chan]);
+	glEnd();		
+
+	glDisable(GL_LINE_STIPPLE);
+
+	char str[500] = {0};
+	
+	/*if(convertLabelUnits)
+		sprintf(str, "%duV", ad16ToUv(s.threshold[chan], s.gain[chan]));
+	else
+		sprintf(str, "%d", (int) s.threshold[chan]);*/
+	makeLabel(s.threshold[chan], s.gain[chan], convertLabelUnits, str);
+	
+//	printf(str);
+	
+	float yOffset = (ylims[1] - ylims[0])/BaseUIElement::height * 2;
+	//drawString(1 ,s.threshold[chan] + yOffset, GLUT_BITMAP_8_BY_13, str);
+}
+
+void WaveAxes::drawWaveformGrid(int thold, int gain){
+
+	double voltRange = ylims[1] - ylims[0];
+	double pixelRange = BaseUIElement::height;
+	//This is a totally arbitrary value that i'll mess around with and set as a macro when I figure out a value I like
+	int minPixelsPerTick = 25;
+	int MAX_N_TICKS = 10;
+
+	int nTicks = pixelRange / minPixelsPerTick;
+	while(nTicks>MAX_N_TICKS){
+		minPixelsPerTick += 5;
+		nTicks = pixelRange / minPixelsPerTick;
+	}
+	int voltPerTick = (voltRange / nTicks);
+	// Round to the nearest 200
+
+	
+	double meanRange = voltRange/2;
+	glColor3fv(gridColor);
+
+	glLineWidth(1);
+	char str[200] = {0}; 
+	
+	double tickVoltage = thold;
+	while(tickVoltage < ylims[1] - voltPerTick/2) // Draw the ticks above the thold line
+	{
+		tickVoltage = roundUp(tickVoltage + voltPerTick, 100);
+		
+		glBegin(GL_LINE_STRIP);
+		glVertex2i(0, tickVoltage);
+		glVertex2i(s.nSamples, tickVoltage);
+		glEnd();
+		
+		makeLabel(tickVoltage, gain, convertLabelUnits, str);
+		//drawString(1, tickVoltage+voltPerTick/10, GLUT_BITMAP_8_BY_13, str);
+	}
+	
+	tickVoltage = thold;
+	while(tickVoltage > ylims[0] + voltPerTick) // draw the ticks below the thold line
+	{
+		tickVoltage = roundUp(tickVoltage - voltPerTick, 100);
+
+		glBegin(GL_LINE_STRIP);
+		glVertex2i(0, tickVoltage);
+		glVertex2i(s.nSamples, tickVoltage);
+		glEnd();
+			
+		makeLabel(tickVoltage, gain, convertLabelUnits, str);
+		//drawString(1, tickVoltage+voltPerTick/10, GLUT_BITMAP_8_BY_13, str);
+	}
+	
+	
+}
+
+void WaveAxes::setWaveformColor(GLfloat r, GLfloat g, GLfloat b){
+	waveColor[0] = r;
+	waveColor[1] = g;
+	waveColor[2] = b;
+}
+void WaveAxes::setThresholdColor(GLfloat r, GLfloat g, GLfloat b){
+	thresholdColor[0] = r;
+	thresholdColor[1] = g;
+	thresholdColor[2] = b;
+}
+// void WaveAxes::setPointColor(GLfloat r, GLfloat g, GLfloat b){
+// 	pointColor[0] = r;
+// 	pointColor[1] = g;
+// 	pointColor[2] = b;
+// }
+void WaveAxes::setGridColor(GLfloat r, GLfloat g, GLfloat b){
+	gridColor[0] = r;
+	gridColor[1] = g;
+	gridColor[2] = b;
+}
\ No newline at end of file
diff --git a/Source/Processors/Visualization/SpikePlotting/WaveAxes.h b/Source/Processors/Visualization/SpikePlotting/WaveAxes.h
new file mode 100644
index 0000000000000000000000000000000000000000..56add88d8301374fe07b5dd0aa74388a117dd8cb
--- /dev/null
+++ b/Source/Processors/Visualization/SpikePlotting/WaveAxes.h
@@ -0,0 +1,51 @@
+#ifndef WAVE_AXES_H
+#define WAVE_AXES_H
+
+#if defined(__linux__)
+	#include <GL/glut.h>
+#else
+	#include <GLUT/glut.h>
+#endif
+#include <stdlib.h>
+#include "BaseUIElement.h"
+#include "../SpikeObject.h"
+#include "PlotUtils.h"
+#include "GenericAxes.h"
+
+ 	
+class WaveAxes: public GenericAxes{
+	
+	GLfloat waveColor[3];
+	GLfloat thresholdColor[3];
+	GLfloat gridColor[3];
+		
+	
+  	void drawWaveformGrid(int thold, int gain);
+
+protected:
+	void plot();
+
+
+public:
+	WaveAxes();
+	WaveAxes(int x, int y, double w, double h, int t);
+    
+   	void updateSpikeData(SpikeObject s);
+
+	void setWaveformColor(GLfloat r, GLfloat g, GLfloat b);
+	void setThresholdColor(GLfloat r, GLfloat g, GLfloat b);
+	void setGridColor(GLfloat, GLfloat, GLfloat);
+	 
+	void redraw();
+	
+	bool drawWaveformLine;
+	bool drawWaveformPoints;
+	bool overlay;
+	bool drawGrid;
+	bool convertLabelUnits;
+	
+};
+
+
+
+#endif
diff --git a/Source/Processors/Visualization/SpikeViewer.cpp b/Source/Processors/Visualization/SpikeViewer.cpp
deleted file mode 100644
index 3a06ca5fbad429b493c3a2473f4e0c6b0e864677..0000000000000000000000000000000000000000
--- a/Source/Processors/Visualization/SpikeViewer.cpp
+++ /dev/null
@@ -1,340 +0,0 @@
-/*
-    ------------------------------------------------------------------
-
-    This file is part of the Open Ephys GUI
-    Copyright (C) 2012 Open Ephys
-
-    ------------------------------------------------------------------
-
-    This program is free software: you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation, either version 3 of the License, or
-    (at your option) any later version.
-
-    This program is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-
-    You should have received a copy of the GNU General Public License
-    along with this program.  If not, see <http://www.gnu.org/licenses/>.
-
-*/
-
-#include "SpikeViewer.h"
-
-
-SpikeViewer::SpikeViewer(AudioSampleBuffer* sBuffer, MidiBuffer* eBuffer, UIComponent* ui)
-	: Renderer(sBuffer, eBuffer, ui)
-{
-
-}
-
-
-
-SpikeViewer::~SpikeViewer() {}
-
-void SpikeViewer::resized() 
-{
-	
-	xBox = getWidth()/4;
-	yBox = getHeight()/2;
-	yPadding = 5;
-	xPadding = 5;
-
-	glClear(GL_COLOR_BUFFER_BIT);
-
-	clearWaveforms();
-	clearProjections();
-
-}
-
-void SpikeViewer::newOpenGLContextCreated()
-{
-
-	glClearDepth (1.0);
-
-	glMatrixMode (GL_PROJECTION);
-	glLoadIdentity ();
-	glOrtho(0, 1, 1, 0, 0, 1);
-	glMatrixMode (GL_MODELVIEW);
-	
-	glClearColor(0.2f, 0.2f, 0.2f, 1.0f);
-
-	resized();
-
-	glFlush();
-
-}
-
-void SpikeViewer::clearWaveforms()
-{
-	
-	for (int n = 0; n < 4; n++)
-	{
-		setViewportForWaveN(n);
-		drawBorder();
-	}
-
-}
-
-void SpikeViewer::clearProjections()
-{
-	for (int n = 0; n < 6; n++)
-	{
-		setViewportForProjectionN(n);
-		drawBorder();
-	}
-
-}
-
-void SpikeViewer::renderOpenGL()
-{
-		
-	 if (eventBuffer->getNumEvents() > 0) {
-
-	   	glRasterPos2f(0.1,0.1);
-
-	   	//const char* str = "i";
-	  // 	void* font = GLUT_BITMAP_8_BY_13;
-
-	  // 	glutBitmapCharacter(font,54);
-	   //	drawBorder();
-
-		//std::cout << "Events received by Spike Viewer." << std::endl;
-
-		MidiBuffer::Iterator i (*eventBuffer);
-		MidiMessage message(0xf4);
-
-		int samplePosition;
-		i.setNextSamplePosition(samplePosition);
-
-		//Array<int> peaks;
-
-
-		clearWaveforms();
-
-		while (i.getNextEvent (message, samplePosition)) {
-
-			int numbytes = message.getRawDataSize();
-			int numSamples = (numbytes-2)/2;
-			uint8* dataptr = message.getRawData();
-
-			int chan = (*dataptr<<8) + *(dataptr+1);
-			int electrode = config->getSource(0)->getElectrodeNumberForChannel(chan);
-
-			//std::cout << chan << "::" << electrode << std::endl;
-
- 			dataptr += 2;
-
-			//glViewport(0,0,getWidth()/2,getHeight());
-
-			if (electrode == 0)
-			{
-			//for (int n = 0; n < 4; n++) {
-				setViewportForWaveN(chan);
-				float peak = drawWaveform(dataptr, numSamples);
-
-				peaks.set(chan,peak*1.25);
-				//peaks.set(chan,peak);
-				
-			}
-
-			if (peaks.size() == 4)
-			{
-				drawProjections();
-				peaks.clear();
-			}
-
-			//std::cout << " Bytes received: " << numbytes << std::endl;
-			//std::cout << " Message timestamp = " << message.getTimeStamp() << std::endl;
-			//std::cout << " Message channel: " << chan << std::endl;
-
- 			//std::cout << "   ";
-			
- 			//AudioDataConverters::convertInt16BEToFloat ( dataptr, // source
-    		//			spikeData, // dest
-    		//			numSamples, // numSamples
-    		//			2 ); // destBytesPerSample = 2
-
-			//for (int n = 0; n < numSamples; n++) {
-			//	std::cout << String(spikeData[n]) << " ";
-			//}
-					
-			//std::cout << std::endl << std::endl;
-		}
-
-		// for (int ch = 0; ch < 4; ch++)
-		// {
-			
-		// }
-
-		//eventBuffer->clear();
-
-	}
-
-	//glOrtho(0, 0.5, 0.5, 0, 0, 1);
-	glFlush();
-
-}
-
-void SpikeViewer::drawProjections() 
-{
-	
-	for (int i = 0; i < 6; i++)
-	{
-		setViewportForProjectionN(i);
-
-		int d1,d2;
-		
-		if (i == 0){
-			d1 = 0;
-			d2 = 1;	
-		} else if (i == 1) {
-			d1 = 0;
-			d2 = 2;
-		} else if (i == 2) {
-			d1 = 0;
-			d2 = 3;
-		} else if (i == 3) {
-			d1 = 1;
-			d2 = 2;
-		} else if (i == 4) {
-			d1 = 1;
-			d2 = 3;
-		} else if (i == 5) {
-			d1 = 2;
-			d2 = 3;
-		}
-
-		glColor3f(0.0, 0.0, 0.0);
-		glBegin(GL_POINTS);
-			glVertex2f(1-peaks[d1],peaks[d2]);
-		glEnd();
-
-	}
-
-}
-
-float SpikeViewer::drawWaveform(uint8* dataptr, int numSamples)
-{
-
-	glColor3f(0,0.0,0);
-	
-	glBegin(GL_LINE_STRIP);
-
-	float maxVal = 0;
-
- 	for (int n = 0; n < numSamples; n++)
- 	{
- 		uint16 sampleValue = (*dataptr << 8) + *(dataptr+1);
-
- 		float sampleVal = -float(sampleValue - 32768)/32768 + 0.6;
-
- 		(sampleVal > maxVal) ? maxVal = sampleVal : maxVal = maxVal;
-
- 		glVertex2f(float(n)/numSamples + 0.01, 
- 					sampleVal);
- 		dataptr += 2;
-
- 	}
-
-	glEnd();
-
-	return maxVal;
-
-}
-
-void SpikeViewer::drawBorder()
-{
-
-	 glColor3f(0.9,0.7,0.2);
-
-	 glRectf(0.01f,0.01f,0.99f,0.99f);
-
-    // glBegin(GL_LINE_STRIP);
- 	//  glVertex2f(0.01f, 0.01f);
- 	//  glVertex2f(0.99f, 0.01f);
- 	//  glVertex2f(0.99f, 0.99f);
- 	//  glVertex2f(0.01f, 0.99f);
- 	//  glVertex2f(0.01f, 0.01f);
- 	//  glEnd();
-}
-
-void SpikeViewer::setViewportForProjectionN(int n)
-{
-	//	std::cout<<"Setting viewport on projection:"<<n<<std::endl;
-    float viewDX = xBox;
-    float viewDY = yBox;
-    float viewX,viewY;
-
-    switch (n){
-    case 0:
-        viewX=xBox;
-        viewY=yBox;
-        break;
-    case 1:
-        viewX = xBox*2;
-        viewY = yBox;
-        break;
-    case 2:
-        viewX=xBox*3;
-        viewY=yBox;
-        break;
-    case 3:
-        viewX = xBox;
-        viewY = 0;
-        break;
-    case 4:
-        viewX = xBox*2;
-        viewY = 0;
-        break;
-    case 5:
-        viewX = xBox*3;
-        viewY = 0;
-        break;
-    default:
-        std::cout<<"drawing of more than 4 channels is not supported, returning! Requested:"<<n<<std::endl;
-        return;
-    }
-	viewX = viewX + xPadding;
-	viewY = viewY + yPadding;
-	viewDX = viewDX - 2*xPadding;
-	viewDY = viewDY - 2*yPadding;
-
-	glViewport(viewX, viewY, viewDX, viewDY);
-
-}
-
-
-void SpikeViewer::setViewportForWaveN(int n){
-	float viewDX = xBox/2;
-	float viewDY = yBox;
-	float viewX,viewY;
-	switch (n){
-	case 0:
-		viewX=0;
-		viewY=yBox;
-		break;
-	case 1:
-		viewX = xBox/2;
-		viewY = yBox;
-		break;
-	case 2:
-		viewX=0;
-		viewY=0;
-		break;
-	case 3:
-		viewX = xBox/2;
-		viewY = 0;
-		break;
-	default:
-		std::cout<<"drawing of more than 4 channels is not supported, returning! Requested:"<<n<<std::endl;
-		return;
-	}
-	viewX = viewX + xPadding;
-	viewY = viewY + yPadding;
-	viewDX = viewDX - 2*xPadding;
-	viewDY = viewDY - 2*yPadding;
-	glViewport(viewX,viewY,viewDX,viewDY);
-}
\ No newline at end of file
diff --git a/Source/Processors/Visualization/SpikeViewer.h b/Source/Processors/Visualization/SpikeViewer.h
deleted file mode 100644
index 0ab44684ebe17560d4fdd25ed7d3edfff4c4705c..0000000000000000000000000000000000000000
--- a/Source/Processors/Visualization/SpikeViewer.h
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
-    ------------------------------------------------------------------
-
-    This file is part of the Open Ephys GUI
-    Copyright (C) 2012 Open Ephys
-
-    ------------------------------------------------------------------
-
-    This program is free software: you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation, either version 3 of the License, or
-    (at your option) any later version.
-
-    This program is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-
-    You should have received a copy of the GNU General Public License
-    along with this program.  If not, see <http://www.gnu.org/licenses/>.
-
-*/
-
-#ifndef __SPIKEVIEWER_H_AF442416__
-#define __SPIKEVIEWER_H_AF442416__
-
-#include "../../../JuceLibraryCode/JuceHeader.h"
-#include "../Editors/Visualizer.h"
-
-#ifdef _WIN32
-#include <windows.h>
-#endif
-
-#if JUCE_WINDOWS
-#include <gl/gl.h>
-#include <gl/glu.h>
-#elif JUCE_LINUX
-#include <GL/gl.h>
-#include <GL/glut.h>
-#undef KeyPress
-#elif JUCE_IPHONE
-#include <OpenGLES/ES1/gl.h>
-#include <OpenGLES/ES1/glext.h>
-#elif JUCE_MAC
-#include <GLUT/glut.h>
-#endif
-
-#ifndef GL_BGRA_EXT
-#define GL_BGRA_EXT 0x80e1
-#endif
-
-/**
-  
-  --THIS FILE IS OBSOLETE, BUT REMAINS FOR REFERENCE PURPOSES--
-
-*/
-
-
-class SpikeViewer : public Renderer
-{
-public:
-	SpikeViewer(AudioSampleBuffer* streamBuffer, MidiBuffer* eventBuffer, UIComponent* ui);
-	~SpikeViewer();
-	void renderOpenGL();	
-	void newOpenGLContextCreated();
-
-	//void setViewportForProjection
-private:
-	int nTrodes;
-
-	Array<float> peaks;
-
-	float xBox, yBox, xPadding, yPadding;
-
-	void drawBorder();
-
-	void clearWaveforms();
-	void clearProjections();
-
-	void drawProjections();
-	float drawWaveform(uint8* dataptr, int numSamples);
-
-	void setViewportForWaveN(int n);
-	void setViewportForProjectionN(int n);
-
-	void resized();
-
-};
-
-
-#endif  // __SPIKEVIEWER_H_AF442416__
diff --git a/Source/UI/ProcessorList.cpp b/Source/UI/ProcessorList.cpp
index f25e9d97fb4facca5548024fe7ee2520098c0de9..52d898c79e57b3ee6ae0e3ce52832a751b50f2d2 100644
--- a/Source/UI/ProcessorList.cpp
+++ b/Source/UI/ProcessorList.cpp
@@ -50,7 +50,7 @@ ProcessorList::ProcessorList() : isDragging(false),
 
 	ProcessorListItem* sinks = new ProcessorListItem("Sinks");
 	sinks->addSubItem(new ProcessorListItem("LFP Viewer"));
-	//sinks->addSubItem(new ProcessorListItem("Spike Display"));
+	sinks->addSubItem(new ProcessorListItem("Spike Viewer"));
 	sinks->addSubItem(new ProcessorListItem("WiFi Output"));
 
 	ProcessorListItem* utilities = new ProcessorListItem("Utilities");
diff --git a/open-ephys.jucer b/open-ephys.jucer
index 78f67747a72f22c8c6a027b0607e293444fc1648..d3d03772943fc34428304c6316621f7c81b2a826 100644
--- a/open-ephys.jucer
+++ b/open-ephys.jucer
@@ -10,15 +10,16 @@
               pluginRTASCategory="" bundleIdentifier="" jucerVersion="3.0.0">
   <EXPORTFORMATS>
     <XCODE_MAC targetFolder="Builds/MacOSX" vstFolder="~/SDKs/vstsdk2.4" rtasFolder="~/SDKs/PT_80_SDK"
-               juceFolder="JuceLibraryCode" extraLinkerFlags="-lftdi -lftgl"/>
+               juceFolder="JuceLibraryCode" extraLinkerFlags="-lftdi -lftgl"
+               objCExtraSuffix="fea2mT"/>
     <LINUX_MAKE targetFolder="Builds/Linux" vstFolder="~/SDKs/vstsdk2.4" juceFolder="JuceLibraryCode"
                 extraLinkerFlags="-lftdi -lftgl" extraCompilerFlags="-export-dynamic"/>
   </EXPORTFORMATS>
   <CONFIGURATIONS>
     <CONFIGURATION name="Debug" isDebug="1" optimisation="1" targetName="open-ephys"
-                   osxSDK="default" osxCompatibility="default"/>
+                   osxSDK="default" osxCompatibility="default" osxArchitecture="default"/>
     <CONFIGURATION name="Release" isDebug="0" optimisation="3" targetName="open-ephys"
-                   osxSDK="default" osxCompatibility="default"/>
+                   osxSDK="default" osxCompatibility="default" osxArchitecture="default"/>
   </CONFIGURATIONS>
   <MAINGROUP id="h3HbSTV" name="open-ephys">
     <GROUP id="0wpTCpt" name="Resources">
@@ -137,6 +138,10 @@
               file="Source/Audio/AudioComponent.h"/>
       </GROUP>
       <GROUP id="yQmqZWk" name="Processors">
+        <FILE id="arRy5R" name="SpikeDisplayNode.cpp" compile="1" resource="0"
+              file="Source/Processors/SpikeDisplayNode.cpp"/>
+        <FILE id="VwDxj" name="SpikeDisplayNode.h" compile="0" resource="0"
+              file="Source/Processors/SpikeDisplayNode.h"/>
         <FILE id="Poqus0b" name="WiFiOutput.cpp" compile="1" resource="0" file="Source/Processors/WiFiOutput.cpp"/>
         <FILE id="IklsJpw" name="WiFiOutput.h" compile="0" resource="0" file="Source/Processors/WiFiOutput.h"/>
         <FILE id="ZuMpSio" name="LfpDisplayNode.cpp" compile="1" resource="0"
@@ -150,6 +155,40 @@
           <FILE id="DXYynnz" name="Splitter.h" compile="0" resource="0" file="Source/Processors/Utilities/Splitter.h"/>
         </GROUP>
         <GROUP id="W4eqkOy" name="Visualization">
+          <GROUP id="g8GOfh" name="SpikePlotting">
+            <FILE id="PzmX0I" name="StereotrodePlot.cpp" compile="1" resource="0"
+                  file="Source/Processors/Visualization/SpikePlotting/StereotrodePlot.cpp"/>
+            <FILE id="LPK6G1" name="StereotrodePlot.h" compile="0" resource="0"
+                  file="Source/Processors/Visualization/SpikePlotting/StereotrodePlot.h"/>
+            <FILE id="EgoljI" name="ElectrodePlot.cpp" compile="1" resource="0"
+                  file="Source/Processors/Visualization/SpikePlotting/ElectrodePlot.cpp"/>
+            <FILE id="oFUMq0" name="ElectrodePlot.h" compile="0" resource="0" file="Source/Processors/Visualization/SpikePlotting/ElectrodePlot.h"/>
+            <FILE id="Qq75l" name="BaseUIElement.cpp" compile="1" resource="0"
+                  file="Source/Processors/Visualization/SpikePlotting/BaseUIElement.cpp"/>
+            <FILE id="PZdkKU" name="BaseUIElement.h" compile="0" resource="0" file="Source/Processors/Visualization/SpikePlotting/BaseUIElement.h"/>
+            <FILE id="lFRVqc" name="GenericAxes.cpp" compile="1" resource="0" file="Source/Processors/Visualization/SpikePlotting/GenericAxes.cpp"/>
+            <FILE id="BP8BOa" name="GenericAxes.h" compile="0" resource="0" file="Source/Processors/Visualization/SpikePlotting/GenericAxes.h"/>
+            <FILE id="f7vOFh" name="PlotUtils.cpp" compile="1" resource="0" file="Source/Processors/Visualization/SpikePlotting/PlotUtils.cpp"/>
+            <FILE id="TQfHuh" name="PlotUtils.h" compile="0" resource="0" file="Source/Processors/Visualization/SpikePlotting/PlotUtils.h"/>
+            <FILE id="d3ducO" name="ProjectionAxes.cpp" compile="1" resource="0"
+                  file="Source/Processors/Visualization/SpikePlotting/ProjectionAxes.cpp"/>
+            <FILE id="BdHvyv" name="ProjectionAxes.h" compile="0" resource="0"
+                  file="Source/Processors/Visualization/SpikePlotting/ProjectionAxes.h"/>
+            <FILE id="RnnkTt" name="SimpleKeyEvent.h" compile="0" resource="0"
+                  file="Source/Processors/Visualization/SpikePlotting/SimpleKeyEvent.h"/>
+            <FILE id="dP2Ikw" name="TetrodePlot.cpp" compile="1" resource="0" file="Source/Processors/Visualization/SpikePlotting/TetrodePlot.cpp"/>
+            <FILE id="SH9Un2" name="TetrodePlot.h" compile="0" resource="0" file="Source/Processors/Visualization/SpikePlotting/TetrodePlot.h"/>
+            <FILE id="g5OQRR" name="TitleBox.cpp" compile="1" resource="0" file="Source/Processors/Visualization/SpikePlotting/TitleBox.cpp"/>
+            <FILE id="UTihqz" name="TitleBox.h" compile="0" resource="0" file="Source/Processors/Visualization/SpikePlotting/TitleBox.h"/>
+            <FILE id="yg1Xuq" name="WaveAxes.cpp" compile="1" resource="0" file="Source/Processors/Visualization/SpikePlotting/WaveAxes.cpp"/>
+            <FILE id="cZX4SM" name="WaveAxes.h" compile="0" resource="0" file="Source/Processors/Visualization/SpikePlotting/WaveAxes.h"/>
+          </GROUP>
+          <FILE id="ajAJi" name="SpikeObject.cpp" compile="1" resource="0" file="Source/Processors/Visualization/SpikeObject.cpp"/>
+          <FILE id="xqF5zL" name="SpikeObject.h" compile="0" resource="0" file="Source/Processors/Visualization/SpikeObject.h"/>
+          <FILE id="jGEqDp" name="SpikeDisplayCanvas.cpp" compile="1" resource="0"
+                file="Source/Processors/Visualization/SpikeDisplayCanvas.cpp"/>
+          <FILE id="LVHMu2" name="SpikeDisplayCanvas.h" compile="0" resource="0"
+                file="Source/Processors/Visualization/SpikeDisplayCanvas.h"/>
           <FILE id="yDPZGpt" name="Visualizer.h" compile="0" resource="0" file="Source/Processors/Visualization/Visualizer.h"/>
           <FILE id="BX1Vj3V" name="DataWindow.cpp" compile="1" resource="0" file="Source/Processors/Visualization/DataWindow.cpp"/>
           <FILE id="l2VKLuP" name="DataWindow.h" compile="0" resource="0" file="Source/Processors/Visualization/DataWindow.h"/>
@@ -170,6 +209,10 @@
         <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="s5YUmi" name="SpikeDisplayEditor.cpp" compile="1" resource="0"
+                file="Source/Processors/Editors/SpikeDisplayEditor.cpp"/>
+          <FILE id="EE43GV" name="SpikeDisplayEditor.h" compile="0" resource="0"
+                file="Source/Processors/Editors/SpikeDisplayEditor.h"/>
           <FILE id="2XqqPOS" name="VisualizerEditor.cpp" compile="1" resource="0"
                 file="Source/Processors/Editors/VisualizerEditor.cpp"/>
           <FILE id="CUHGPJF" name="VisualizerEditor.h" compile="0" resource="0"