diff --git a/Builds/Linux/Makefile b/Builds/Linux/Makefile index 409cb90c355514e7503a4be9333320cad96441be..2db986c5351a9a85601b27513d2968153817bd2b 100644 --- a/Builds/Linux/Makefile +++ b/Builds/Linux/Makefile @@ -102,6 +102,7 @@ OBJECTS := \ $(OBJDIR)/SpikeDetector_300d85e7.o \ $(OBJDIR)/AudioNode_94606ff3.o \ $(OBJDIR)/EventNode_95c842b7.o \ + $(OBJDIR)/EcubeEditor_50eace99.o \ $(OBJDIR)/SpikeSorterEditor_30c3d470.o \ $(OBJDIR)/LfpTriggeredAverageEditor_101d75b.o \ $(OBJDIR)/SerialInputEditor_c00f31f5.o \ @@ -132,6 +133,7 @@ OBJECTS := \ $(OBJDIR)/AudioEditor_fb2c6555.o \ $(OBJDIR)/FilterEditor_dfe1f39d.o \ $(OBJDIR)/GenericEditor_becb2ad6.o \ + $(OBJDIR)/EcubeThread_d0477baf.o \ $(OBJDIR)/okFrontPanelDLL_87687880.o \ $(OBJDIR)/rhd2000datablock_722d8dae.o \ $(OBJDIR)/rhd2000evalboard_e0b412d5.o \ @@ -148,6 +150,7 @@ OBJECTS := \ $(OBJDIR)/SourceNode_c2d6336c.o \ $(OBJDIR)/GenericProcessor_733760aa.o \ $(OBJDIR)/ProcessorGraph_68b34a0b.o \ + $(OBJDIR)/EcubeDialogComponent_2ec3bd57.o \ $(OBJDIR)/CustomArrowButton_206e4278.o \ $(OBJDIR)/GraphViewer_e43fd2ce.o \ $(OBJDIR)/EditorViewportButtons_29af2a5c.o \ @@ -450,6 +453,11 @@ $(OBJDIR)/EventNode_95c842b7.o: ../../Source/Processors/EventNode.cpp @echo "Compiling EventNode.cpp" @$(CXX) $(CXXFLAGS) -o "$@" -c "$<" +$(OBJDIR)/EcubeEditor_50eace99.o: ../../Source/Processors/Editors/EcubeEditor.cpp + -@mkdir -p $(OBJDIR) + @echo "Compiling EcubeEditor.cpp" + @$(CXX) $(CXXFLAGS) -o "$@" -c "$<" + $(OBJDIR)/SpikeSorterEditor_30c3d470.o: ../../Source/Processors/Editors/SpikeSorterEditor.cpp -@mkdir -p $(OBJDIR) @echo "Compiling SpikeSorterEditor.cpp" @@ -600,6 +608,11 @@ $(OBJDIR)/GenericEditor_becb2ad6.o: ../../Source/Processors/Editors/GenericEdito @echo "Compiling GenericEditor.cpp" @$(CXX) $(CXXFLAGS) -o "$@" -c "$<" +$(OBJDIR)/EcubeThread_d0477baf.o: ../../Source/Processors/DataThreads/EcubeThread.cpp + -@mkdir -p $(OBJDIR) + @echo "Compiling EcubeThread.cpp" + @$(CXX) $(CXXFLAGS) -o "$@" -c "$<" + $(OBJDIR)/okFrontPanelDLL_87687880.o: ../../Source/Processors/DataThreads/rhythm-api/okFrontPanelDLL.cpp -@mkdir -p $(OBJDIR) @echo "Compiling okFrontPanelDLL.cpp" @@ -680,6 +693,11 @@ $(OBJDIR)/ProcessorGraph_68b34a0b.o: ../../Source/Processors/ProcessorGraph.cpp @echo "Compiling ProcessorGraph.cpp" @$(CXX) $(CXXFLAGS) -o "$@" -c "$<" +$(OBJDIR)/EcubeDialogComponent_2ec3bd57.o: ../../Source/UI/EcubeDialogComponent.cpp + -@mkdir -p $(OBJDIR) + @echo "Compiling EcubeDialogComponent.cpp" + @$(CXX) $(CXXFLAGS) -o "$@" -c "$<" + $(OBJDIR)/CustomArrowButton_206e4278.o: ../../Source/UI/CustomArrowButton.cpp -@mkdir -p $(OBJDIR) @echo "Compiling CustomArrowButton.cpp" diff --git a/Builds/MacOSX/open-ephys.xcodeproj/project.pbxproj b/Builds/MacOSX/open-ephys.xcodeproj/project.pbxproj index 4d18a78c470478c624d83d3434c52e7acc1a9bb2..53047b91eea1de9fbcac27d6176b81f53de1a5d2 100644 --- a/Builds/MacOSX/open-ephys.xcodeproj/project.pbxproj +++ b/Builds/MacOSX/open-ephys.xcodeproj/project.pbxproj @@ -72,6 +72,7 @@ ED8CB527B27C67E9E4DA027C = {isa = PBXBuildFile; fileRef = BC3B7E4E25505D9044BFACC7; }; DE758AF46844DF951655966C = {isa = PBXBuildFile; fileRef = B27F558F42AC78F0E564B5AF; }; 80E5365461A5A7A32C48C563 = {isa = PBXBuildFile; fileRef = F94DD42C7BBF81C101D3F605; }; + A005D7947A9FA8D2E73982C8 = {isa = PBXBuildFile; fileRef = B477BCF5AD76FBA478E4FA30; }; 96E000FFBED6B85F9DEB5494 = {isa = PBXBuildFile; fileRef = B8BDB9ED4D4E0D1882F94EE5; }; DD77A0AB68C932F294B753C2 = {isa = PBXBuildFile; fileRef = 7B7819A5759B54D91E334447; }; A3CF90DE56808A47519FC101 = {isa = PBXBuildFile; fileRef = 07BEF02C2B930DF7847C2921; }; @@ -102,6 +103,7 @@ BF3254F07C15D467D6DB3FEF = {isa = PBXBuildFile; fileRef = 10BE33089BA6F3468F36CD6C; }; 6029B20DF2BD523AC0F78896 = {isa = PBXBuildFile; fileRef = D90290A0AA2C36CE757E46D5; }; 6702EEA4E99D503C0EE933C4 = {isa = PBXBuildFile; fileRef = D3AE8303545E28D793312F46; }; + 5C597B1A42C8CB3940CBDDA9 = {isa = PBXBuildFile; fileRef = AFBAE04615D379A18B133090; }; 89FCE8890946693CD5FC4A70 = {isa = PBXBuildFile; fileRef = 235A8987D99A191D07208D2F; }; C9AC286A46B3A1318F298DEF = {isa = PBXBuildFile; fileRef = ECB5A75A81B90327F58CBD9E; }; DA836EC803E4FF4EDEBE6386 = {isa = PBXBuildFile; fileRef = 2D2BAC4320470CF68743F58E; }; @@ -118,6 +120,7 @@ 71111DE81104B1536ECB6DFB = {isa = PBXBuildFile; fileRef = ECA6FDB1366BE7EC30F1539B; }; 85A60568B3DC342C76B4E679 = {isa = PBXBuildFile; fileRef = 3AE038CACE48AF85C4FB1ED5; }; 8A5BACA019DA9B0EFAD5CE93 = {isa = PBXBuildFile; fileRef = 555D34D0CD8776EE5996CC3A; }; + 8F39AD3F7938EFE82D06E89F = {isa = PBXBuildFile; fileRef = AF28CAB9C7531EF7422602E1; }; BA608CEFC85F7AB9E30E0EB3 = {isa = PBXBuildFile; fileRef = F960CC94B136201BDA148EEA; }; D499273B65D901D0A101CAAA = {isa = PBXBuildFile; fileRef = E5C1D021C0FD6FAD082C5D75; }; 95AE939ADE096394CCD2526F = {isa = PBXBuildFile; fileRef = 9F3B3184EC6D42CEA35D6ED8; }; @@ -886,7 +889,9 @@ A0D768F1B92568344DAC9F0B = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_win32_Fonts.cpp"; path = "../../JuceLibraryCode/modules/juce_graphics/native/juce_win32_Fonts.cpp"; sourceTree = "SOURCE_ROOT"; }; A0E3B98412D88921BB0AA58E = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = AudioEditor.h; path = ../../Source/Processors/Editors/AudioEditor.h; sourceTree = "SOURCE_ROOT"; }; A15596CDCC27B86FC070D7FA = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_Desktop.cpp"; path = "../../JuceLibraryCode/modules/juce_gui_basics/components/juce_Desktop.cpp"; sourceTree = "SOURCE_ROOT"; }; + A166A3013C7AF1BCCA050367 = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = EcubeThread.h; path = ../../Source/Processors/DataThreads/EcubeThread.h; sourceTree = "SOURCE_ROOT"; }; A17E8162EC7A0E513DDEB23C = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_PluginDescription.cpp"; path = "../../JuceLibraryCode/modules/juce_audio_processors/processors/juce_PluginDescription.cpp"; sourceTree = "SOURCE_ROOT"; }; + A186E03EC7A6A7E657F38300 = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = EcubeDialogComponent.h; path = ../../Source/UI/EcubeDialogComponent.h; sourceTree = "SOURCE_ROOT"; }; A19C4BB4BD69D4351B344A17 = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_MenuBarComponent.cpp"; path = "../../JuceLibraryCode/modules/juce_gui_basics/menus/juce_MenuBarComponent.cpp"; sourceTree = "SOURCE_ROOT"; }; A234B2D091071A1B710E884B = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = ChannelMappingNode.h; path = ../../Source/Processors/ChannelMappingNode.h; sourceTree = "SOURCE_ROOT"; }; A252FE4E6A360CBC4AF694B3 = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = SpikeDetectorEditor.cpp; path = ../../Source/Processors/Editors/SpikeDetectorEditor.cpp; sourceTree = "SOURCE_ROOT"; }; @@ -943,11 +948,13 @@ AEC2DABFC0517B4BE0CD704C = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; name = "juce_mac_AudioCDReader.mm"; path = "../../JuceLibraryCode/modules/juce_audio_devices/native/juce_mac_AudioCDReader.mm"; sourceTree = "SOURCE_ROOT"; }; AEF53FD0FBBFF5242EDD7032 = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_Viewport.cpp"; path = "../../JuceLibraryCode/modules/juce_gui_basics/layout/juce_Viewport.cpp"; sourceTree = "SOURCE_ROOT"; }; AF1F3010721A6B29062E4838 = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_LowLevelGraphicsContext.h"; path = "../../JuceLibraryCode/modules/juce_graphics/contexts/juce_LowLevelGraphicsContext.h"; sourceTree = "SOURCE_ROOT"; }; + AF28CAB9C7531EF7422602E1 = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = EcubeDialogComponent.cpp; path = ../../Source/UI/EcubeDialogComponent.cpp; sourceTree = "SOURCE_ROOT"; }; AF3E3AE70160C3392B237316 = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_mac_CoreAudio.cpp"; path = "../../JuceLibraryCode/modules/juce_audio_devices/native/juce_mac_CoreAudio.cpp"; sourceTree = "SOURCE_ROOT"; }; AF7106E30ED950436CCEC712 = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_freetype_Fonts.cpp"; path = "../../JuceLibraryCode/modules/juce_graphics/native/juce_freetype_Fonts.cpp"; sourceTree = "SOURCE_ROOT"; }; AF8ADA74003E96998A5E4404 = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_Typeface.cpp"; path = "../../JuceLibraryCode/modules/juce_graphics/fonts/juce_Typeface.cpp"; sourceTree = "SOURCE_ROOT"; }; AF8B1228A9FDFA27E5F19011 = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_StringRef.h"; path = "../../JuceLibraryCode/modules/juce_core/text/juce_StringRef.h"; sourceTree = "SOURCE_ROOT"; }; AFB684CE06F9256324EE0B4C = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_FillType.cpp"; path = "../../JuceLibraryCode/modules/juce_graphics/colour/juce_FillType.cpp"; sourceTree = "SOURCE_ROOT"; }; + AFBAE04615D379A18B133090 = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = EcubeThread.cpp; path = ../../Source/Processors/DataThreads/EcubeThread.cpp; sourceTree = "SOURCE_ROOT"; }; AFE835E175F7159E1E7C6CC7 = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_CharacterFunctions.cpp"; path = "../../JuceLibraryCode/modules/juce_core/text/juce_CharacterFunctions.cpp"; sourceTree = "SOURCE_ROOT"; }; B00A9C0BAD3AF9F48E36A38F = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_MouseListener.cpp"; path = "../../JuceLibraryCode/modules/juce_gui_basics/mouse/juce_MouseListener.cpp"; sourceTree = "SOURCE_ROOT"; }; B021D393D0E2625741512320 = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_RenderingHelpers.h"; path = "../../JuceLibraryCode/modules/juce_graphics/native/juce_RenderingHelpers.h"; sourceTree = "SOURCE_ROOT"; }; @@ -979,6 +986,7 @@ B2FA9CC4754E136F22281176 = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_ImageEffectFilter.h"; path = "../../JuceLibraryCode/modules/juce_graphics/effects/juce_ImageEffectFilter.h"; sourceTree = "SOURCE_ROOT"; }; B3BAC48D01C49D8727D08097 = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_ListBox.cpp"; path = "../../JuceLibraryCode/modules/juce_gui_basics/widgets/juce_ListBox.cpp"; sourceTree = "SOURCE_ROOT"; }; B43C27BEC3AB681389FC5FC5 = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_RelativeCoordinate.h"; path = "../../JuceLibraryCode/modules/juce_gui_basics/positioning/juce_RelativeCoordinate.h"; sourceTree = "SOURCE_ROOT"; }; + B477BCF5AD76FBA478E4FA30 = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = EcubeEditor.cpp; path = ../../Source/Processors/Editors/EcubeEditor.cpp; sourceTree = "SOURCE_ROOT"; }; B47B3368AA1A182B0CA1AB26 = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = Butterworth.cpp; path = ../../Source/Dsp/Butterworth.cpp; sourceTree = "SOURCE_ROOT"; }; B4C52FC94D6C680C33ED85C9 = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_File.cpp"; path = "../../JuceLibraryCode/modules/juce_core/files/juce_File.cpp"; sourceTree = "SOURCE_ROOT"; }; B4F0C0B262654C4782B5AC49 = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_FileChooserDialogBox.h"; path = "../../JuceLibraryCode/modules/juce_gui_basics/filebrowser/juce_FileChooserDialogBox.h"; sourceTree = "SOURCE_ROOT"; }; @@ -997,6 +1005,7 @@ B7BEB7779860FE877E4D1BC8 = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_TextDiff.cpp"; path = "../../JuceLibraryCode/modules/juce_core/text/juce_TextDiff.cpp"; sourceTree = "SOURCE_ROOT"; }; B7D848E4F85AE11FDE4D164D = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_linux_AudioCDReader.cpp"; path = "../../JuceLibraryCode/modules/juce_audio_devices/native/juce_linux_AudioCDReader.cpp"; sourceTree = "SOURCE_ROOT"; }; B83EBFAE6306941F79044523 = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_DirectoryContentsDisplayComponent.cpp"; path = "../../JuceLibraryCode/modules/juce_gui_basics/filebrowser/juce_DirectoryContentsDisplayComponent.cpp"; sourceTree = "SOURCE_ROOT"; }; + B86153418B2ECB863398897F = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = EcubeEditor.h; path = ../../Source/Processors/Editors/EcubeEditor.h; sourceTree = "SOURCE_ROOT"; }; B87864B2D6A2E741D4B426A3 = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; name = "juce_mac_Threads.mm"; path = "../../JuceLibraryCode/modules/juce_core/native/juce_mac_Threads.mm"; sourceTree = "SOURCE_ROOT"; }; B87C1BD13762817BE27DC2F7 = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_FillType.h"; path = "../../JuceLibraryCode/modules/juce_graphics/colour/juce_FillType.h"; sourceTree = "SOURCE_ROOT"; }; B8A9063181FEE1920095F824 = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_ChangeBroadcaster.h"; path = "../../JuceLibraryCode/modules/juce_events/broadcasters/juce_ChangeBroadcaster.h"; sourceTree = "SOURCE_ROOT"; }; @@ -1253,7 +1262,7 @@ EE2C669B127D00C86B1B8CA8 = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_win32_Registry.cpp"; path = "../../JuceLibraryCode/modules/juce_core/native/juce_win32_Registry.cpp"; sourceTree = "SOURCE_ROOT"; }; EE4DD055D31F7D9DC718DBD8 = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_ComponentMovementWatcher.h"; path = "../../JuceLibraryCode/modules/juce_gui_basics/layout/juce_ComponentMovementWatcher.h"; sourceTree = "SOURCE_ROOT"; }; EEA51B7EF1CF19028C6672E0 = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_DocumentWindow.cpp"; path = "../../JuceLibraryCode/modules/juce_gui_basics/windows/juce_DocumentWindow.cpp"; sourceTree = "SOURCE_ROOT"; }; - EEFC66D2DF5FD66B4D83B22F = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_Component.h"; path = "../../JuceLibraryCode/modules/juce_gui_basics/components/juce_Component.h"; sourceTree = "SOURCE_ROOT"; }; + EF059B26886B32000BCF8CFF = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_MouseInputSource.h"; path = "../../JuceLibraryCode/modules/juce_gui_basics/mouse/juce_MouseInputSource.h"; sourceTree = "SOURCE_ROOT"; }; EF3F9AA8D70E1D4D55F13182 = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_AudioThumbnail.cpp"; path = "../../JuceLibraryCode/modules/juce_audio_utils/gui/juce_AudioThumbnail.cpp"; sourceTree = "SOURCE_ROOT"; }; EF4A6E0E1232071252ACCD7B = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_RelativeParallelogram.h"; path = "../../JuceLibraryCode/modules/juce_gui_basics/positioning/juce_RelativeParallelogram.h"; sourceTree = "SOURCE_ROOT"; }; EF610B2A17D9B1C0D24DCE67 = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_android_JNIHelpers.h"; path = "../../JuceLibraryCode/modules/juce_core/native/juce_android_JNIHelpers.h"; sourceTree = "SOURCE_ROOT"; }; @@ -1264,14 +1273,13 @@ F1A3975235880CAC1D5757F4 = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_MP3AudioFormat.cpp"; path = "../../JuceLibraryCode/modules/juce_audio_formats/codecs/juce_MP3AudioFormat.cpp"; sourceTree = "SOURCE_ROOT"; }; F230A4C0186379F9EB0B0F74 = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = ReferenceNode.h; path = ../../Source/Processors/ReferenceNode.h; sourceTree = "SOURCE_ROOT"; }; F28414731D9EE1F75D7B7043 = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_AudioFormat.h"; path = "../../JuceLibraryCode/modules/juce_audio_formats/format/juce_AudioFormat.h"; sourceTree = "SOURCE_ROOT"; }; - F2F11D7C596DAE5579610CCC = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_win32_AudioCDReader.cpp"; path = "../../JuceLibraryCode/modules/juce_audio_devices/native/juce_win32_AudioCDReader.cpp"; sourceTree = "SOURCE_ROOT"; }; F5A00ACFA3D76168F22F1205 = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = System/Library/Frameworks/Cocoa.framework; sourceTree = SDKROOT; }; 99E1BC08B886CFDD2CCFD462 = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "open-ephys.app"; sourceTree = "BUILT_PRODUCTS_DIR"; }; EBD8622EAEF10558809888B7 = {isa = PBXFileReference; lastKnownFileType = image.png; name = "RadioButtons_selected_over-01.png"; path = "../../Resources/Images/Icons/RadioButtons_selected_over-01.png"; sourceTree = "SOURCE_ROOT"; }; EC95A2CF4B33EA37DA5FC1AC = {isa = PBXFileReference; lastKnownFileType = file.ttf; name = nordic.ttf; path = ../../Resources/Fonts/nordic.ttf; sourceTree = "SOURCE_ROOT"; }; ECB5A75A81B90327F58CBD9E = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = rhd2000datablock.cpp; path = "../../Source/Processors/DataThreads/rhythm-api/rhd2000datablock.cpp"; sourceTree = "SOURCE_ROOT"; }; ED887A521EEB8F3EBA7DDB31 = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_AudioIODeviceType.h"; path = "../../JuceLibraryCode/modules/juce_audio_devices/audio_io/juce_AudioIODeviceType.h"; sourceTree = "SOURCE_ROOT"; }; - EF059B26886B32000BCF8CFF = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_MouseInputSource.h"; path = "../../JuceLibraryCode/modules/juce_gui_basics/mouse/juce_MouseInputSource.h"; sourceTree = "SOURCE_ROOT"; }; + EEFC66D2DF5FD66B4D83B22F = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_Component.h"; path = "../../JuceLibraryCode/modules/juce_gui_basics/components/juce_Component.h"; sourceTree = "SOURCE_ROOT"; }; EF8488936B3D3E9178C9099C = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = PulsePalOutput.h; path = ../../Source/Processors/PulsePalOutput.h; sourceTree = "SOURCE_ROOT"; }; EFC21F3CD0EB87D67E044E06 = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_MenuBarComponent.h"; path = "../../JuceLibraryCode/modules/juce_gui_basics/menus/juce_MenuBarComponent.h"; sourceTree = "SOURCE_ROOT"; }; F0CA3600E09054D7DB3B0067 = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SmoothedFilter.h; path = ../../Source/Dsp/SmoothedFilter.h; sourceTree = "SOURCE_ROOT"; }; @@ -1281,6 +1289,7 @@ F1DBAE92084D9D90234AC436 = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_AudioSourcePlayer.cpp"; path = "../../JuceLibraryCode/modules/juce_audio_devices/sources/juce_AudioSourcePlayer.cpp"; sourceTree = "SOURCE_ROOT"; }; F2A500BA3500C4A9D5792A54 = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_DrawableImage.h"; path = "../../JuceLibraryCode/modules/juce_gui_basics/drawables/juce_DrawableImage.h"; sourceTree = "SOURCE_ROOT"; }; F2EDB88302B8A9356F43B834 = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_Primes.h"; path = "../../JuceLibraryCode/modules/juce_cryptography/encryption/juce_Primes.h"; sourceTree = "SOURCE_ROOT"; }; + F2F11D7C596DAE5579610CCC = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_win32_AudioCDReader.cpp"; path = "../../JuceLibraryCode/modules/juce_audio_devices/native/juce_win32_AudioCDReader.cpp"; sourceTree = "SOURCE_ROOT"; }; F3D0224E4247BCB06A9E4DDF = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_KeyPressMappingSet.cpp"; path = "../../JuceLibraryCode/modules/juce_gui_basics/commands/juce_KeyPressMappingSet.cpp"; sourceTree = "SOURCE_ROOT"; }; F3F48717927A4E24F7373C09 = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_NamedValueSet.h"; path = "../../JuceLibraryCode/modules/juce_core/containers/juce_NamedValueSet.h"; sourceTree = "SOURCE_ROOT"; }; F463A19E6EFEB2837582B117 = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_audio_processors.h"; path = "../../JuceLibraryCode/modules/juce_audio_processors/juce_audio_processors.h"; sourceTree = "SOURCE_ROOT"; }; @@ -1474,6 +1483,8 @@ 4A94E809624F99387E600399, 12B5DDCB6E5ECD93A4C55BB5, ); name = Visualization; sourceTree = "<group>"; }; 9F16043BF599BCE0C02A00A5 = {isa = PBXGroup; children = ( + B477BCF5AD76FBA478E4FA30, + B86153418B2ECB863398897F, B8BDB9ED4D4E0D1882F94EE5, 27963A329403E0882D24ECF0, 7B7819A5759B54D91E334447, @@ -1544,6 +1555,8 @@ 5DB3B3197F8C1E5EE159D6FC, 8A989F74B1957BCB3B9BA398, ); name = "rhythm-api"; sourceTree = "<group>"; }; DEA24DC5AC8325310FB40395 = {isa = PBXGroup; children = ( + AFBAE04615D379A18B133090, + A166A3013C7AF1BCCA050367, EBA825AF6FDB51EBA368CB8D, A3FB0EA0264580F6B00D993B, 23A6BA852B71DAAF3F709428, @@ -1616,6 +1629,8 @@ 555D34D0CD8776EE5996CC3A, 0FDD7551AC98348D4A98ADC7, ); name = Processors; sourceTree = "<group>"; }; 1D78FCCF430CD91FD1DBD95B = {isa = PBXGroup; children = ( + AF28CAB9C7531EF7422602E1, + A186E03EC7A6A7E657F38300, F960CC94B136201BDA148EEA, C59B01C8DB5B3B4773032E12, E5C1D021C0FD6FAD082C5D75, @@ -2884,6 +2899,7 @@ ED8CB527B27C67E9E4DA027C, DE758AF46844DF951655966C, 80E5365461A5A7A32C48C563, + A005D7947A9FA8D2E73982C8, 96E000FFBED6B85F9DEB5494, DD77A0AB68C932F294B753C2, A3CF90DE56808A47519FC101, @@ -2914,6 +2930,7 @@ BF3254F07C15D467D6DB3FEF, 6029B20DF2BD523AC0F78896, 6702EEA4E99D503C0EE933C4, + 5C597B1A42C8CB3940CBDDA9, 89FCE8890946693CD5FC4A70, C9AC286A46B3A1318F298DEF, DA836EC803E4FF4EDEBE6386, @@ -2930,6 +2947,7 @@ 71111DE81104B1536ECB6DFB, 85A60568B3DC342C76B4E679, 8A5BACA019DA9B0EFAD5CE93, + 8F39AD3F7938EFE82D06E89F, BA608CEFC85F7AB9E30E0EB3, D499273B65D901D0A101CAAA, 95AE939ADE096394CCD2526F, diff --git a/Builds/VisualStudio2012/open-ephys.vcxproj b/Builds/VisualStudio2012/open-ephys.vcxproj index 8b03691616bcca793a13127956b2823b08b2c235..98e3de779bded57ccca310c876e2613b9d9dd01a 100644 --- a/Builds/VisualStudio2012/open-ephys.vcxproj +++ b/Builds/VisualStudio2012/open-ephys.vcxproj @@ -314,6 +314,7 @@ <ClCompile Include="..\..\Source\Processors\SpikeDetector.cpp"/> <ClCompile Include="..\..\Source\Processors\AudioNode.cpp"/> <ClCompile Include="..\..\Source\Processors\EventNode.cpp"/> + <ClCompile Include="..\..\Source\Processors\Editors\EcubeEditor.cpp"/> <ClCompile Include="..\..\Source\Processors\Editors\SpikeSorterEditor.cpp"/> <ClCompile Include="..\..\Source\Processors\Editors\LfpTriggeredAverageEditor.cpp"/> <ClCompile Include="..\..\Source\Processors\Editors\SerialInputEditor.cpp"/> @@ -344,6 +345,7 @@ <ClCompile Include="..\..\Source\Processors\Editors\AudioEditor.cpp"/> <ClCompile Include="..\..\Source\Processors\Editors\FilterEditor.cpp"/> <ClCompile Include="..\..\Source\Processors\Editors\GenericEditor.cpp"/> + <ClCompile Include="..\..\Source\Processors\DataThreads\EcubeThread.cpp"/> <ClCompile Include="..\..\Source\Processors\DataThreads\rhythm-api\okFrontPanelDLL.cpp"/> <ClCompile Include="..\..\Source\Processors\DataThreads\rhythm-api\rhd2000datablock.cpp"/> <ClCompile Include="..\..\Source\Processors\DataThreads\rhythm-api\rhd2000evalboard.cpp"/> @@ -360,6 +362,7 @@ <ClCompile Include="..\..\Source\Processors\SourceNode.cpp"/> <ClCompile Include="..\..\Source\Processors\GenericProcessor.cpp"/> <ClCompile Include="..\..\Source\Processors\ProcessorGraph.cpp"/> + <ClCompile Include="..\..\Source\UI\EcubeDialogComponent.cpp"/> <ClCompile Include="..\..\Source\UI\CustomArrowButton.cpp"/> <ClCompile Include="..\..\Source\UI\GraphViewer.cpp"/> <ClCompile Include="..\..\Source\UI\EditorViewportButtons.cpp"/> @@ -1557,6 +1560,7 @@ <ClInclude Include="..\..\Source\Processors\SpikeDetector.h"/> <ClInclude Include="..\..\Source\Processors\AudioNode.h"/> <ClInclude Include="..\..\Source\Processors\EventNode.h"/> + <ClInclude Include="..\..\Source\Processors\Editors\EcubeEditor.h"/> <ClInclude Include="..\..\Source\Processors\Editors\SpikeSorterEditor.h"/> <ClInclude Include="..\..\Source\Processors\Editors\LfpTriggeredAverageEditor.h"/> <ClInclude Include="..\..\Source\Processors\Editors\SerialInputEditor.h"/> @@ -1587,6 +1591,7 @@ <ClInclude Include="..\..\Source\Processors\Editors\AudioEditor.h"/> <ClInclude Include="..\..\Source\Processors\Editors\FilterEditor.h"/> <ClInclude Include="..\..\Source\Processors\Editors\GenericEditor.h"/> + <ClInclude Include="..\..\Source\Processors\DataThreads\EcubeThread.h"/> <ClInclude Include="..\..\Source\Processors\DataThreads\rhythm-api\okFrontPanelDLL.h"/> <ClInclude Include="..\..\Source\Processors\DataThreads\rhythm-api\rhd2000datablock.h"/> <ClInclude Include="..\..\Source\Processors\DataThreads\rhythm-api\rhd2000evalboard.h"/> @@ -1603,6 +1608,7 @@ <ClInclude Include="..\..\Source\Processors\SourceNode.h"/> <ClInclude Include="..\..\Source\Processors\GenericProcessor.h"/> <ClInclude Include="..\..\Source\Processors\ProcessorGraph.h"/> + <ClInclude Include="..\..\Source\UI\EcubeDialogComponent.h"/> <ClInclude Include="..\..\Source\UI\CustomArrowButton.h"/> <ClInclude Include="..\..\Source\UI\GraphViewer.h"/> <ClInclude Include="..\..\Source\UI\EditorViewportButtons.h"/> diff --git a/Builds/VisualStudio2012/open-ephys.vcxproj.filters b/Builds/VisualStudio2012/open-ephys.vcxproj.filters index 3f4d0a9f07504cdf83f78f141ac397833a99d864..edbdbb5c9f5f7238d025f1ee1e572d592336ba76 100644 --- a/Builds/VisualStudio2012/open-ephys.vcxproj.filters +++ b/Builds/VisualStudio2012/open-ephys.vcxproj.filters @@ -508,6 +508,9 @@ <ClCompile Include="..\..\Source\Processors\EventNode.cpp"> <Filter>open-ephys\Source\Processors</Filter> </ClCompile> + <ClCompile Include="..\..\Source\Processors\Editors\EcubeEditor.cpp"> + <Filter>open-ephys\Source\Processors\Editors</Filter> + </ClCompile> <ClCompile Include="..\..\Source\Processors\Editors\SpikeSorterEditor.cpp"> <Filter>open-ephys\Source\Processors\Editors</Filter> </ClCompile> @@ -598,6 +601,9 @@ <ClCompile Include="..\..\Source\Processors\Editors\GenericEditor.cpp"> <Filter>open-ephys\Source\Processors\Editors</Filter> </ClCompile> + <ClCompile Include="..\..\Source\Processors\DataThreads\EcubeThread.cpp"> + <Filter>open-ephys\Source\Processors\DataThreads</Filter> + </ClCompile> <ClCompile Include="..\..\Source\Processors\DataThreads\rhythm-api\okFrontPanelDLL.cpp"> <Filter>open-ephys\Source\Processors\DataThreads\rhythm-api</Filter> </ClCompile> @@ -646,6 +652,9 @@ <ClCompile Include="..\..\Source\Processors\ProcessorGraph.cpp"> <Filter>open-ephys\Source\Processors</Filter> </ClCompile> + <ClCompile Include="..\..\Source\UI\EcubeDialogComponent.cpp"> + <Filter>open-ephys\Source\UI</Filter> + </ClCompile> <ClCompile Include="..\..\Source\UI\CustomArrowButton.cpp"> <Filter>open-ephys\Source\UI</Filter> </ClCompile> @@ -2094,6 +2103,9 @@ <ClInclude Include="..\..\Source\Processors\EventNode.h"> <Filter>open-ephys\Source\Processors</Filter> </ClInclude> + <ClInclude Include="..\..\Source\Processors\Editors\EcubeEditor.h"> + <Filter>open-ephys\Source\Processors\Editors</Filter> + </ClInclude> <ClInclude Include="..\..\Source\Processors\Editors\SpikeSorterEditor.h"> <Filter>open-ephys\Source\Processors\Editors</Filter> </ClInclude> @@ -2184,6 +2196,9 @@ <ClInclude Include="..\..\Source\Processors\Editors\GenericEditor.h"> <Filter>open-ephys\Source\Processors\Editors</Filter> </ClInclude> + <ClInclude Include="..\..\Source\Processors\DataThreads\EcubeThread.h"> + <Filter>open-ephys\Source\Processors\DataThreads</Filter> + </ClInclude> <ClInclude Include="..\..\Source\Processors\DataThreads\rhythm-api\okFrontPanelDLL.h"> <Filter>open-ephys\Source\Processors\DataThreads\rhythm-api</Filter> </ClInclude> @@ -2232,6 +2247,9 @@ <ClInclude Include="..\..\Source\Processors\ProcessorGraph.h"> <Filter>open-ephys\Source\Processors</Filter> </ClInclude> + <ClInclude Include="..\..\Source\UI\EcubeDialogComponent.h"> + <Filter>open-ephys\Source\UI</Filter> + </ClInclude> <ClInclude Include="..\..\Source\UI\CustomArrowButton.h"> <Filter>open-ephys\Source\UI</Filter> </ClInclude> diff --git a/Resources/DLLs/InstallEcubeApi_0_10.exe b/Resources/DLLs/InstallEcubeApi_0_10.exe new file mode 100644 index 0000000000000000000000000000000000000000..3d202816e3fa54790c463b3441ed0d3d7a2c46b0 Binary files /dev/null and b/Resources/DLLs/InstallEcubeApi_0_10.exe differ diff --git a/Source/Processors/DataThreads/EcubeThread.cpp b/Source/Processors/DataThreads/EcubeThread.cpp new file mode 100644 index 0000000000000000000000000000000000000000..f0b0b956343fe46b3150253b763ee07ccd06da11 --- /dev/null +++ b/Source/Processors/DataThreads/EcubeThread.cpp @@ -0,0 +1,565 @@ +/* +------------------------------------------------------------------ + +This file is part of the Open Ephys GUI +Copyright (C) 2013 Michael Borisov + +------------------------------------------------------------------ + +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 "EcubeThread.h" +#include "../SourceNode.h" +#include "../../UI/EcubeDialogComponent.h" +#include <stdint.h> + +#if JUCE_WINDOWS +#import "libid:60C0AAC2-1E0B-4FE5-A921-AF9CEEAAA582" + +using namespace ecubeapiLib; + +class EcubeDevInt +{ +public: + + enum DataFormat + { + dfSeparateChannelsAnalog, + dfInterleavedChannelsAnalog, + dfDigital + }; + IEcubePtr pEcube; + IEcubeDevicePtr pDevice; + IEcubeModulePtr pModule; + unsigned n_channel_objects; + std::map<int, int> chid_map; + IEcubeAnalogAcquisitionPtr pStrmA; + IEcubeDigitalInputStreamingPtr pStrmD; + HeapBlock<float, true> interleaving_buffer; + bool buf_timestamp_locked; + unsigned long buf_timestamp; + uint64 buf_timestamp64; + unsigned long int_buf_size; + DataFormat data_format; +}; + +static const char bits_port0[16] = { 23, 22, -1, 14, 11, -1, -1, 28, 12, 10, 27, 26, -1, -1, -1, -1 }; +static const char bits_port1[16] = { 20, 21, 19, 18, 13, 6, 4, 5, 3, 2, -1, -1, 29, -1, 24, 25 }; +static const char bits_port2[16] = { 16, 17, 15, 8, 9, 7, 0, 1, 31, 30, -1, -1, -1, -1, -1, -1 }; + + + +static std::vector<std::wstring> SafeArrayToVecStr(SAFEARRAY* sa) +{ + HRESULT hr; + long lbound, ubound; + + if (SafeArrayGetElemsize(sa) != sizeof(BSTR*)) + _com_raise_error(E_FAIL); + if(SafeArrayGetDim(sa)!=1) + _com_raise_error(E_FAIL); + if (FAILED(hr = SafeArrayGetLBound(sa, 1, &lbound))) + _com_raise_error(hr); + if (FAILED(hr = SafeArrayGetUBound(sa, 1, &ubound))) + _com_raise_error(hr); + + std::vector<std::wstring> result; + for (long index = lbound; index <= ubound; index++) + { + BSTR raw_bstr; + if (FAILED(hr = SafeArrayGetElement(sa, &index, &raw_bstr))) + _com_raise_error(hr); + _bstr_t bstr(raw_bstr, false); + result.push_back(raw_bstr); + } + return result; +} + +static StringArray SafeArrayToStringArray(SAFEARRAY* sa) +{ + HRESULT hr; + long lbound, ubound; + VARTYPE vt; + + hr = SafeArrayGetVartype(sa, &vt); + if (FAILED(hr)) + _com_raise_error(hr); + if (vt!=VT_BSTR) + _com_raise_error(E_FAIL); + if (SafeArrayGetElemsize(sa) != sizeof(BSTR*)) + _com_raise_error(E_FAIL); + if (SafeArrayGetDim(sa) != 1) + _com_raise_error(E_FAIL); + if (FAILED(hr = SafeArrayGetLBound(sa, 1, &lbound))) + _com_raise_error(hr); + if (FAILED(hr = SafeArrayGetUBound(sa, 1, &ubound))) + _com_raise_error(hr); + + StringArray result; + for (long index = lbound; index <= ubound; index++) + { + BSTR raw_bstr; + if (FAILED(hr = SafeArrayGetElement(sa, &index, &raw_bstr))) + _com_raise_error(hr); + _bstr_t bstr(raw_bstr, false); + result.add(raw_bstr); + } + return result; +} + +std::vector<std::wstring> GetEcubeModuleChannels(IEcubeModulePtr& mp) +{ + std::vector<std::wstring> chnames; + { + SAFEARRAY *sa = mp->GetChannels(); + chnames = SafeArrayToVecStr(sa); + SafeArrayDestroy(sa); // ARTEM - Leaks a safearray if an exception is thrown here + } + return chnames; +} + +EcubeThread::EcubeThread(SourceNode* sn) : DataThread(sn), numberingScheme(1), acquisition_running(false) +{ + try + { + EcubeDialogComponent component; + DialogWindow::LaunchOptions opt; + opt.dialogTitle = "eCube parameters"; + opt.content = OptionalScopedPointer<Component>(&component, false); + opt.escapeKeyTriggersCloseButton = true; + + pDevInt = new EcubeDevInt; + pDevInt->pEcube.CreateInstance(__uuidof(Ecube)); + { + SAFEARRAY *sa = pDevInt->pEcube->DetectNetworkDevices(); + StringArray a(SafeArrayToStringArray(sa)); // ARTEM - Leaks a safearray if an exception is thrown here + SafeArrayDestroy(sa); + component.SetDeviceNames(a); + } + int dres = opt.runModal(); + if (dres != 1) + { + throw std::runtime_error("Operation cancelled"); + } + + pDevInt->pDevice = pDevInt->pEcube->OpenNetworkDevice(_bstr_t(component.GetAddressValue().toUTF16())); + pDevInt->n_channel_objects = 0; + { + String selmod = component.GetModuleName(); + if (selmod == "Headstage(s)") + { + m_samplerate = 25000.0f; + pDevInt->data_format = EcubeDevInt::dfSeparateChannelsAnalog; + // Get status of headstage selection + bool selhs[10]; + component.GetHeadstageSelection(selhs); + bool acq_created = false; + for (int i = 0; i < 10; i++) + { + if (selhs[i]) + { + String modname = "Headstage" + String(i + 1); + pDevInt->pModule = pDevInt->pDevice->OpenModule(_bstr_t(modname.toUTF16())); + std::vector<std::wstring> chnames = GetEcubeModuleChannels(pDevInt->pModule); + for (int j = 0; j < chnames.size(); j++) + { + IEcubeChannelPtr pch = pDevInt->pModule->OpenChannel(chnames[j].c_str()); + if (!acq_created) + { + pDevInt->pStrmA = pDevInt->pEcube->CreateAnalogAcquisition(pch); + acq_created = true; + } + else + pDevInt->pStrmA->AddChannel(pch); + pDevInt->chid_map[pch->GetID()] = pDevInt->n_channel_objects; + pDevInt->n_channel_objects++; + } + } + } + dataBuffer = new DataBuffer(pDevInt->n_channel_objects, 10000); + // Create the interleaving buffer based on the number of channels + pDevInt->interleaving_buffer.malloc(sizeof(float)* 1500 * pDevInt->n_channel_objects); + } + else if (selmod == "Panel Analog Input") + { + pDevInt->pModule = pDevInt->pDevice->OpenModule(_bstr_t(L"PanelAnalogInput")); + m_samplerate = 25000.0f;// 40.0e6 / 572 original samplerate; + pDevInt->data_format = EcubeDevInt::dfInterleavedChannelsAnalog; + bool acq_created = false; + std::vector<std::wstring> chnames = GetEcubeModuleChannels(pDevInt->pModule); + for (int j = 0; j < chnames.size(); j++) + { + IEcubeChannelPtr pch = pDevInt->pModule->OpenChannel(chnames[j].c_str()); + if (!acq_created) + { + pDevInt->pStrmA = pDevInt->pEcube->CreateAnalogAcquisition(pch); + acq_created = true; + } + else + pDevInt->pStrmA->AddChannel(pch); + pDevInt->chid_map[pch->GetID()] = pDevInt->n_channel_objects; + pDevInt->n_channel_objects++; + } + dataBuffer = new DataBuffer(32, 10000); + // The interleaving buffer is there just for short->float conversion + pDevInt->interleaving_buffer.malloc(sizeof(float)* 1500); + } + else if (selmod == "Panel Digital Input") + { + pDevInt->pModule = pDevInt->pDevice->OpenModule(_bstr_t(L"PanelDigitalIO")); + m_samplerate = 25000.0f; + pDevInt->data_format = EcubeDevInt::dfDigital; + + bool acq_created = false; + std::vector<std::wstring> chnames = GetEcubeModuleChannels(pDevInt->pModule); + for (int j = 0; j < chnames.size(); j++) + { + IEcubeChannelPtr pch = pDevInt->pModule->OpenChannel(chnames[j].c_str()); + if (!acq_created) + { + pDevInt->pStrmD = pDevInt->pEcube->CreateDigitalInputStreaming(pch); + acq_created = true; + } + else + pDevInt->pStrmD->AddChannel(pch); + pDevInt->chid_map[pch->GetID()] = pDevInt->n_channel_objects; + pDevInt->n_channel_objects++; + } + + dataBuffer = new DataBuffer(64, 10000); + // Create the interleaving buffer based on the number of digital ports + pDevInt->interleaving_buffer.malloc(sizeof(float)* 1500 * 64); + } + else + throw std::runtime_error("Invlid module selection"); + } + + pDevInt->buf_timestamp_locked = false; + + setDefaultChannelNamesAndType(); + + } + catch (_com_error& e) + { + // Convert COM errors to std::runtime_errors, to avoid making other files Windows-dependent + throw std::runtime_error(std::string(e.Description())); + } +} +void EcubeThread::getChannelsInfo(StringArray &Names_, Array<channelType> &type_, Array<int> &stream_, Array<int> &originalChannelNumber_, Array<float> &gains_) +{ + Names_ = Names; + type_ = type; + stream_ = stream; + originalChannelNumber_ = originalChannelNumber; + gains_ = gains; +} + +/* This will give default names & gains to channels, unless they were manually modified by the user +In that case, the query channelModified, will return the values that need to be put */ +void EcubeThread::setDefaultChannelNamesAndType() +{ + Names.clear(); + type.clear(); + stream.clear(); + gains.clear(); + originalChannelNumber.clear(); + String prefix; + channelType common_type; + + int numch = getNumChannels(); + + if (pDevInt->data_format == EcubeDevInt::dfSeparateChannelsAnalog) + { + prefix = "HS10_CH"; + common_type = DATA_CHANNEL; + } + else if (pDevInt->data_format == EcubeDevInt::dfInterleavedChannelsAnalog) + { + prefix = "PAI"; + common_type = AUX_CHANNEL; + } + else //if (pDevInt->data_format == EcubeDevInt::dfDigital) + { + prefix = "PDI"; + common_type = AUX_CHANNEL; + } + + if (numberingScheme != 1) + prefix += "_"; + + for (int i = 0; i < numch; i++) + { + Names.add(prefix + String(i)); + gains.add(getBitVolts()); + type.add(common_type); + originalChannelNumber.add(i); + } + + stream.add(0); +} + +void EcubeThread::setDefaultNamingScheme(int scheme) +{ + numberingScheme = scheme; + setDefaultChannelNamesAndType(); +} + + +EcubeThread::~EcubeThread() +{ + if (acquisition_running) + stopAcquisition(); + if (isThreadRunning()) + { + signalThreadShouldExit(); + } + waitForThreadToExit(-1); +} + +int EcubeThread::getNumChannels() +{ + if (pDevInt->data_format == EcubeDevInt::dfInterleavedChannelsAnalog) + return 32; + else if (pDevInt->data_format == EcubeDevInt::dfDigital) + return 64; + else + return pDevInt->n_channel_objects; +} + +float EcubeThread::getSampleRate() +{ + return m_samplerate; +} + +float EcubeThread::getBitVolts() +{ + return 10e3/32768; // For some reason the data is supposed to be in millivolts +} + +bool EcubeThread::foundInputSource() +{ + return true; +} + +bool EcubeThread::updateBuffer() +{ + unsigned long ba; + int16 eventcode = 0; + int nchan = pDevInt->n_channel_objects; + + if (pDevInt->data_format == EcubeDevInt::dfSeparateChannelsAnalog || pDevInt->data_format == EcubeDevInt::dfInterleavedChannelsAnalog) + ba = pDevInt->pStrmA->WaitForData(100); + else + ba = pDevInt->pStrmD->WaitForData(100); + while (ba) + { + for (unsigned long i = 0; i < ba; i++) + { + IEcubeDataBufferPtr ab; + if (pDevInt->data_format == EcubeDevInt::dfSeparateChannelsAnalog || pDevInt->data_format == EcubeDevInt::dfInterleavedChannelsAnalog) + ab = pDevInt->pStrmA->FetchNextBuffer(); + else + ab = pDevInt->pStrmD->FetchNextBuffer(); + unsigned long chid = ab->GetStreamID(); + std::map<int, int>::const_iterator chit = pDevInt->chid_map.find(chid); + if (chit != pDevInt->chid_map.end()) + { + unsigned long bts = ab->GetTimestamp(); + unsigned long datasize = ab->GetDataSize() / 2; // Data size is returned in bytes, not in samples + if (pDevInt->data_format == EcubeDevInt::dfSeparateChannelsAnalog) + { + if (!pDevInt->buf_timestamp_locked || bts != pDevInt->buf_timestamp || datasize != pDevInt->int_buf_size) + { + // The new buffer does not match interleaving buffer length, or has a different timestamp, + // or interleaving buffer is empty + if (pDevInt->buf_timestamp_locked) + { + // Interleaving buffer is not empty. + // Send its contents out to the application + int64 cts = pDevInt->buf_timestamp64 / 3200; // Convert eCube 80MHz timestamp into a 25kHz timestamp + for (unsigned long j = 0; j < pDevInt->int_buf_size; j++) + { + dataBuffer->addToBuffer(pDevInt->interleaving_buffer + j*nchan, &cts, &eventCode, 1); + cts++; + } + // Update the 64-bit timestamp, take account of its wrap-around + unsigned tsdif = bts - pDevInt->buf_timestamp; + pDevInt->buf_timestamp64 += tsdif; + } + else + { + // The interleaving buffer is empty + pDevInt->buf_timestamp64 = bts; + } + pDevInt->int_buf_size = datasize; + pDevInt->buf_timestamp = bts; + pDevInt->buf_timestamp_locked = true; + // Clear the interleaving buffer within the new packet's size + memset(pDevInt->interleaving_buffer, 0, sizeof(float)*datasize*nchan); + } + chid = chit->second; // Adjust the channel id to become the channel index + unsigned char* dp = ab->GetDataPointer(); + const short* pData = (const short*)dp; + for (unsigned long j = 0; j < datasize; j++) + { + pDevInt->interleaving_buffer[chid + nchan*j] = pData[j] * 10.0e3 / 32768; // OpenEphys uses 10e3 instead of just 10 + } + } + else if (pDevInt->data_format == EcubeDevInt::dfInterleavedChannelsAnalog) + { + if (pDevInt->buf_timestamp_locked) + { + // Update the 64-bit timestamp, take care of its wrap-around + unsigned tsdif = pDevInt->buf_timestamp - bts; + pDevInt->buf_timestamp64 += tsdif; + } + else + { + pDevInt->buf_timestamp64 = bts; + } + pDevInt->buf_timestamp = bts; + pDevInt->buf_timestamp_locked = true; + unsigned char* dp = ab->GetDataPointer(); + const short* pData = (const short*)dp; + for (unsigned j = 0; j < datasize; j++) + { + pDevInt->interleaving_buffer[j] = pData[j] * 10.0e3 / 32768; + } + unsigned long datasam = datasize / 32; + int64 cts = pDevInt->buf_timestamp64 / 3200; // Convert eCube's 80MHz timestamps into number of samples on the Panel Analog input (orig sample rate 1144) + for (unsigned long j = 0; j < datasam; j++) + { + dataBuffer->addToBuffer(pDevInt->interleaving_buffer+j*32, &cts, &eventCode, 1); + cts++; + } + } + else // Digital data + { + unsigned tsdif = bts - pDevInt->buf_timestamp; + if (!pDevInt->buf_timestamp_locked || (bts != pDevInt->buf_timestamp && tsdif!=5 && tsdif!=10 && tsdif!=0xFFFFFFFB && tsdif!=0xFFFFFFFA) || datasize != pDevInt->int_buf_size) + { + // The new buffer does not match interleaving buffer length, or has a different timestamp, + // or interleaving buffer is empty + if (pDevInt->buf_timestamp_locked) + { + // Interleaving buffer is not empty. + // Send its contents out to the application + int64 cts = pDevInt->buf_timestamp64 / 3200; // Convert eCube 80MHz timestamp into a 25kHz timestamp + for (unsigned long j = 0; j < pDevInt->int_buf_size; j++) + { + dataBuffer->addToBuffer(pDevInt->interleaving_buffer + j*64, &cts, &eventCode, 1); + cts++; + } + // Update the 64-bit timestamp, take account of its wrap-around + pDevInt->buf_timestamp64 += tsdif; + } + else + { + // The interleaving buffer is empty + pDevInt->buf_timestamp64 = bts; + } + pDevInt->buf_timestamp = bts; + pDevInt->int_buf_size = datasize; + pDevInt->buf_timestamp_locked = true; + // Clear the interleaving buffer within the new packet's size + memset(pDevInt->interleaving_buffer, 0, sizeof(float)*datasize*64); + } + // Convert data from ecube buffer into the interleaving buffer format + chid = chit->second; // Adjust the channel id to become the channel index + unsigned char* dp = ab->GetDataPointer(); + const uint16_t* pData = (const uint16_t*)dp; + const char* pbits; + switch (chid) + { + case 0: + case 3: + pbits = bits_port0; + break; + case 1: + case 4: + pbits = bits_port1; + break; + case 2: + case 5: + default: + pbits = bits_port2; + break; + } + int bitchn_offset = chid >= 3 ? 32 : 0; + for (unsigned long j = 0; j < datasize; j++) + { + uint16_t wrd = pData[j]; + uint16_t msk = 1; + for (unsigned long k = 0; k < 16; k++) + { + int bitchn = pbits[k]; + if (bitchn>=0) + { + float val = wrd&msk ? 1.0e3f : 0.0f; + pDevInt->interleaving_buffer[bitchn + bitchn_offset + 64*j] = val; + } + msk <<= 1; + } + } + } + } + } + if (pDevInt->data_format == EcubeDevInt::dfSeparateChannelsAnalog || pDevInt->data_format == EcubeDevInt::dfInterleavedChannelsAnalog) + ba = pDevInt->pStrmA->GetBuffersAcquired(); + else + ba = pDevInt->pStrmD->GetBuffersAcquired(); + } + return true; +} + +bool EcubeThread::startAcquisition() +{ + pDevInt->buf_timestamp_locked = false; + if (!isThreadRunning()) + startThread(); + + if (!acquisition_running) + { + if (pDevInt->data_format == EcubeDevInt::dfSeparateChannelsAnalog || pDevInt->data_format == EcubeDevInt::dfInterleavedChannelsAnalog) + pDevInt->pStrmA->Start(); + else + pDevInt->pStrmD->Start(); + acquisition_running = true; + } + + return true; +} + +bool EcubeThread::stopAcquisition() +{ + if (acquisition_running) + { + if (pDevInt->data_format == EcubeDevInt::dfSeparateChannelsAnalog || pDevInt->data_format == EcubeDevInt::dfInterleavedChannelsAnalog) + pDevInt->pStrmA->Stop(); + else + pDevInt->pStrmD->Stop(); + } + acquisition_running = false; + return true; +} + +void EcubeThread::run() +{ + // Call the base class's run + DataThread::run(); +} + + +#endif \ No newline at end of file diff --git a/Source/Processors/DataThreads/EcubeThread.h b/Source/Processors/DataThreads/EcubeThread.h new file mode 100644 index 0000000000000000000000000000000000000000..858c81db68ef58e94ace5cb88920d3ccf318045a --- /dev/null +++ b/Source/Processors/DataThreads/EcubeThread.h @@ -0,0 +1,116 @@ +/* +------------------------------------------------------------------ + +This file is part of the Open Ephys GUI +Copyright (C) 2013 Open Ephys +Copyright (C) 2013 Michael Borisov + +------------------------------------------------------------------ + +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 __ECUBETHREAD_H_EC4CAD67__ +#define __ECUBETHREAD_H_EC4CAD67__ + + +#include "../../../JuceLibraryCode/JuceHeader.h" + +#include <stdio.h> +#include <string.h> + +#include "DataThread.h" +#include "../GenericProcessor.h" + +#define MAX_NUM_DATA_STREAMS 8 + +class SourceNode; + +#if JUCE_WINDOWS +class EcubeDevInt; +#endif + +class EcubeThread : public DataThread + +{ +public: + +#if JUCE_WINDOWS + EcubeThread(SourceNode* sn); + ~EcubeThread(); + + void run(); // Overridden + + /** Fills the DataBuffer with incoming data. This is the most important + method for each DataThread.*/ + virtual bool updateBuffer(); + + /** Returns true if the data source is connected, false otherwise.*/ + virtual bool foundInputSource(); + + /** Initializes data transfer.*/ + virtual bool startAcquisition(); + + /** Stops data transfer.*/ + virtual bool stopAcquisition(); + + /** Returns the number of continuous channels the data source can provide.*/ + virtual int getNumChannels(); + + /** Returns the sample rate of the data source.*/ + virtual float getSampleRate(); + + /** Returns the volts per bit of the data source.*/ + virtual float getBitVolts(); + + virtual void getChannelsInfo(StringArray &Names, Array<channelType> &type, Array<int> &stream, Array<int> &originalChannelNumber, Array<float> &gains); + void setDefaultNamingScheme(int scheme); + + +private: + void setDefaultChannelNamesAndType(); + + // used for data stream names... + int numberingScheme; + StringArray Names; + Array<channelType> type; + Array<float> gains; + Array<int> stream; + Array<int> originalChannelNumber; + + ScopedPointer<EcubeDevInt> pDevInt; + + float m_samplerate; + bool acquisition_running; + +#else +/** Empty methods for non-Windows platforms **/ +bool updateBuffer() {} +bool foundInputSource() {} +bool startAcquisition() {} +bool stopAcquisition() {} +int getNumChannels() {} +float getSampleRate() {} +float getBitVolts() {} + +#endif + + + + JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(EcubeThread); +}; + +#endif // __RHD2000THREAD_H_2C4CBD67__ diff --git a/Source/Processors/Editors/EcubeEditor.cpp b/Source/Processors/Editors/EcubeEditor.cpp new file mode 100644 index 0000000000000000000000000000000000000000..0573ad09910d9d5c8d26420198c2d0bba1b9d6c3 --- /dev/null +++ b/Source/Processors/Editors/EcubeEditor.cpp @@ -0,0 +1,173 @@ +/* +------------------------------------------------------------------ + +This file is part of the Open Ephys GUI +Copyright (C) 2013 Open Ephys +Copyright (C) 2013 Michael Borisov + +------------------------------------------------------------------ + +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 "EcubeEditor.h" + +#include "../DataThreads/EcubeThread.h" + +#include <stdio.h> + +EcubeEditor::EcubeEditor(GenericProcessor* parentNode, bool useDefaultParameterEditors = true) +: GenericEditor(parentNode, useDefaultParameterEditors) + +{ + desiredWidth = 180; + + ipLabel = new Label("IP address label", "Address"); + ipLabel->setBounds(35, 80, 180, 20); + ipLabel->setFont(Font("Small Text", 12, Font::plain)); + addAndMakeVisible(ipLabel); + + ipValue = new Label("IP address value", "127.0.0.1"); + ipValue->setBounds(40, 50, 60, 20); + ipValue->setFont(Font("Default", 15, Font::plain)); + ipValue->setColour(Label::textColourId, Colours::white); + ipValue->setColour(Label::backgroundColourId, Colours::grey); + ipValue->setEditable(true); + ipValue->addListener(this); + addAndMakeVisible(ipValue); + +} + +EcubeEditor::~EcubeEditor() +{ + +} + +void EcubeEditor::labelTextChanged(Label* label) +{/* + FilterNode* fn = (FilterNode*)getProcessor(); + + Value val = label->getTextValue(); + double requestedValue = double(val.getValue()); + + if (requestedValue < 0.01 || requestedValue > 10000) + { + sendActionMessage("Value out of range."); + + if (label == highCutValue) + { + label->setText(lastHighCutString, dontSendNotification); + lastHighCutString = label->getText(); + } + else + { + label->setText(lastLowCutString, dontSendNotification); + lastLowCutString = label->getText(); + } + + return; + } + + Array<int> chans = getActiveChannels(); + + // This needs to change, since there's not enough feedback about whether + // or not individual channel settings were altered: + + for (int n = 0; n < chans.size(); n++) + { + + if (label == highCutValue) + { + double minVal = fn->getLowCutValueForChannel(n); + + if (requestedValue > minVal) + { + fn->setCurrentChannel(n); + fn->setParameter(1, requestedValue); + } + + lastHighCutString = label->getText(); + + } + else + { + double maxVal = fn->getHighCutValueForChannel(n); + + if (requestedValue < maxVal) + { + fn->setCurrentChannel(n); + fn->setParameter(0, requestedValue); + } + + lastLowCutString = label->getText(); + } + + } +*/ +} + + +void EcubeEditor::buttonEvent(Button* button) +{ + + if (!acquisitionIsActive) + { + +/* if (button == fileButton) + { + //std::cout << "Button clicked." << std::endl; + FileChooser chooseFileReaderFile("Please select the file you want to load...", + lastFilePath, + "*"); + + if (chooseFileReaderFile.browseForFileToOpen()) + { + // Use the selected file + setFile(chooseFileReaderFile.getResult().getFullPathName()); + + // lastFilePath = fileToRead.getParentDirectory(); + + // thread->setFile(fileToRead.getFullPathName()); + + // fileNameLabel->setText(fileToRead.getFileName(),false); + } + } + */ + } +} + +void EcubeEditor::saveEditorParameters(XmlElement* xml) +{ + + // XmlElement* fileName = xml->createNewChildElement("FILENAME"); + // fileName->addTextElement(lastFilePath.getFullPathName()); + +} + +void EcubeEditor::loadEditorParameters(XmlElement* xml) +{ + + // forEachXmlChildElement(*xml, xmlNode) + // { + // if (xmlNode->hasTagName("FILENAME")) + // { + + // lastFilePath = File(xmlNode->getText()); + // thread->setFile(lastFilePath.getFullPathName()); + // fileNameLabel->setText(lastFilePath.getFullPathName(),false); + // } + // } + +} diff --git a/Source/Processors/Editors/EcubeEditor.h b/Source/Processors/Editors/EcubeEditor.h new file mode 100644 index 0000000000000000000000000000000000000000..4cef4eff132fe8465dfabbba83efd5b5113b9e9f --- /dev/null +++ b/Source/Processors/Editors/EcubeEditor.h @@ -0,0 +1,65 @@ +/* +------------------------------------------------------------------ + +This file is part of the Open Ephys GUI +Copyright (C) 2013 Open Ephys +Copyright (C) 2013 Michael Borisov + +------------------------------------------------------------------ + +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 __ECUBEEDITOR_H_D3EC8BA8__ +#define __ECUBEEDITOR_H_D3EC8BA8__ + +#include "../../../JuceLibraryCode/JuceHeader.h" +#include "GenericEditor.h" + + + +/** + +User interface for the "eCube" source node. + +@see SourceNode, eCube + +*/ + +class EcubeEditor : public GenericEditor, + public Label::Listener +{ +public: + EcubeEditor(GenericProcessor* parentNode, bool useDefaultParameterEditors); + virtual ~EcubeEditor(); + + void buttonEvent(Button* button); + void labelTextChanged(Label* label); + + void saveEditorParameters(XmlElement*); + void loadEditorParameters(XmlElement*); + +private: + ScopedPointer<Label> ipLabel; + ScopedPointer<Label> ipValue; + + JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(EcubeEditor); + +}; + + + +#endif // __ECUBEEDITOR_H_D3EC8BA8__ diff --git a/Source/Processors/ProcessorGraph.cpp b/Source/Processors/ProcessorGraph.cpp index 41243fe9b8595e19484b328aea1cdd937358cbb2..b57ee2d7946530ef29ec103f91ecdcd7875a59c2 100644 --- a/Source/Processors/ProcessorGraph.cpp +++ b/Source/Processors/ProcessorGraph.cpp @@ -492,6 +492,7 @@ GenericProcessor* ProcessorGraph::createProcessorFromDescription(String& descrip if (subProcessorType.equalsIgnoreCase("RHA2000-EVAL") || // subProcessorType.equalsIgnoreCase("File Reader") || subProcessorType.equalsIgnoreCase("Custom FPGA") || + subProcessorType.equalsIgnoreCase("eCube") || // Added by Michael Borisov subProcessorType.equalsIgnoreCase("Rhythm FPGA")) { diff --git a/Source/Processors/SourceNode.cpp b/Source/Processors/SourceNode.cpp index 43d61844cbdaf262a4532d304e907f1ce086693a..6716b423e7a1deb08b68d6e648359db794a899d3 100755 --- a/Source/Processors/SourceNode.cpp +++ b/Source/Processors/SourceNode.cpp @@ -27,9 +27,11 @@ #include "DataThreads/FPGAThread.h" #include "DataThreads/FileReaderThread.h" #include "DataThreads/RHD2000Thread.h" +#include "DataThreads/EcubeThread.h" // Added by Michael Borisov #include "Editors/SourceNodeEditor.h" #include "Editors/FileReaderEditor.h" #include "Editors/RHD2000Editor.h" +#include "Editors/EcubeEditor.h" // Added by Michael Borisov #include "Channel.h" #include <stdio.h> @@ -57,6 +59,12 @@ SourceNode::SourceNode(const String& name_) { dataThread = new RHD2000Thread(this); } +#if JUCE_WINDOWS + else if (getName().equalsIgnoreCase("eCube")) + { + dataThread = new EcubeThread(this); + } +#endif if (dataThread != 0) { diff --git a/Source/UI/EcubeDialogComponent.cpp b/Source/UI/EcubeDialogComponent.cpp new file mode 100644 index 0000000000000000000000000000000000000000..8db0f41bcd338314cd6a8cfea3b2e4c2e9884d84 --- /dev/null +++ b/Source/UI/EcubeDialogComponent.cpp @@ -0,0 +1,419 @@ +/* + ============================================================================== + + This is an automatically generated GUI class created by the Introjucer! + + Be careful when adding custom code to these files, as only the code within + the "//[xyz]" and "//[/xyz]" sections will be retained when the file is loaded + and re-saved. + + Created with Introjucer version: 3.1.0 + + ------------------------------------------------------------------------------ + + The Introjucer is part of the JUCE library - "Jules' Utility Class Extensions" + Copyright 2004-13 by Raw Material Software Ltd. + + ============================================================================== +*/ + +//[Headers] You can add your own extra header files here... +//[/Headers] + +#include "EcubeDialogComponent.h" + + +//[MiscUserDefs] You can add your own user definitions and misc code here... +//[/MiscUserDefs] + +//============================================================================== +EcubeDialogComponent::EcubeDialogComponent () +{ + addAndMakeVisible (laAddressLabel = new Label ("Address Label", + TRANS("Network Address:"))); + laAddressLabel->setFont (Font (15.00f, Font::plain)); + laAddressLabel->setJustificationType (Justification::centredLeft); + laAddressLabel->setEditable (false, false, false); + laAddressLabel->setColour (TextEditor::textColourId, Colours::black); + laAddressLabel->setColour (TextEditor::backgroundColourId, Colour (0x00000000)); + + addAndMakeVisible (bnOK = new TextButton ("OK button")); + bnOK->setButtonText (TRANS("Connect")); + bnOK->addListener (this); + + addAndMakeVisible (bnCancel = new TextButton ("Cancel Button")); + bnCancel->setButtonText (TRANS("Cancel")); + bnCancel->addListener (this); + + addAndMakeVisible (comboModule = new ComboBox ("Module selection combobox")); + comboModule->setTooltip (TRANS("Choose eCube module")); + comboModule->setEditableText (false); + comboModule->setJustificationType (Justification::centredLeft); + comboModule->setTextWhenNothingSelected (String::empty); + comboModule->setTextWhenNoChoicesAvailable (TRANS("(no choices)")); + comboModule->addItem (TRANS("Headstage(s)"), 1); + comboModule->addItem (TRANS("Panel Analog Input"), 2); + comboModule->addItem (TRANS("Panel Digital Input"), 3); + comboModule->addListener (this); + + addAndMakeVisible (labelModule = new Label ("Module selection label", + TRANS("Module"))); + labelModule->setFont (Font (15.00f, Font::plain)); + labelModule->setJustificationType (Justification::centredLeft); + labelModule->setEditable (false, false, false); + labelModule->setColour (TextEditor::textColourId, Colours::black); + labelModule->setColour (TextEditor::backgroundColourId, Colour (0x00000000)); + + addAndMakeVisible (cbNetworkAddress = new ComboBox ("Network Address ComboBox")); + cbNetworkAddress->setEditableText (true); + cbNetworkAddress->setJustificationType (Justification::centredLeft); + cbNetworkAddress->setTextWhenNothingSelected (String::empty); + cbNetworkAddress->setTextWhenNoChoicesAvailable (TRANS("(no choices)")); + cbNetworkAddress->addListener (this); + + addAndMakeVisible (groupComponent = new GroupComponent ("headstage group", + TRANS("Headstage selection"))); + + addAndMakeVisible (toggleHeadstage1 = new ToggleButton ("Headstage1 button")); + toggleHeadstage1->setButtonText (TRANS("Headstage 1")); + toggleHeadstage1->addListener (this); + + addAndMakeVisible (toggleHeadstage2 = new ToggleButton ("Headstage2 button")); + toggleHeadstage2->setButtonText (TRANS("Headstage 2")); + toggleHeadstage2->addListener (this); + + addAndMakeVisible (toggleHeadstage3 = new ToggleButton ("Headstage3 button")); + toggleHeadstage3->setButtonText (TRANS("Headstage 3")); + toggleHeadstage3->addListener (this); + + addAndMakeVisible (toggleHeadstage4 = new ToggleButton ("Headstage4 button")); + toggleHeadstage4->setButtonText (TRANS("Headstage 4")); + toggleHeadstage4->addListener (this); + + addAndMakeVisible (toggleHeadstage5 = new ToggleButton ("Headstage5 button")); + toggleHeadstage5->setButtonText (TRANS("Headstage 5")); + toggleHeadstage5->addListener (this); + + addAndMakeVisible (toggleHeadstage6 = new ToggleButton ("Headstage6 button")); + toggleHeadstage6->setButtonText (TRANS("Headstage 6")); + toggleHeadstage6->addListener (this); + + addAndMakeVisible (toggleHeadstage7 = new ToggleButton ("Headstage7 button")); + toggleHeadstage7->setButtonText (TRANS("Headstage 7")); + toggleHeadstage7->addListener (this); + + addAndMakeVisible (toggleHeadstage8 = new ToggleButton ("Headstage8 button")); + toggleHeadstage8->setButtonText (TRANS("Headstage 8")); + toggleHeadstage8->addListener (this); + + addAndMakeVisible (toggleHeadstage9 = new ToggleButton ("Headstage9 button")); + toggleHeadstage9->setButtonText (TRANS("Headstage 9")); + toggleHeadstage9->addListener (this); + + addAndMakeVisible (toggleHeadstage10 = new ToggleButton ("Headstage10 button")); + toggleHeadstage10->setButtonText (TRANS("Headstage 10")); + toggleHeadstage10->addListener (this); + toggleHeadstage10->setToggleState (true, dontSendNotification); + + + //[UserPreSize] + //[/UserPreSize] + + setSize (310, 320); + + + //[Constructor] You can add your own custom stuff here.. + //[/Constructor] +} + +EcubeDialogComponent::~EcubeDialogComponent() +{ + //[Destructor_pre]. You can add your own custom destruction code here.. + //[/Destructor_pre] + + laAddressLabel = nullptr; + bnOK = nullptr; + bnCancel = nullptr; + comboModule = nullptr; + labelModule = nullptr; + cbNetworkAddress = nullptr; + groupComponent = nullptr; + toggleHeadstage1 = nullptr; + toggleHeadstage2 = nullptr; + toggleHeadstage3 = nullptr; + toggleHeadstage4 = nullptr; + toggleHeadstage5 = nullptr; + toggleHeadstage6 = nullptr; + toggleHeadstage7 = nullptr; + toggleHeadstage8 = nullptr; + toggleHeadstage9 = nullptr; + toggleHeadstage10 = nullptr; + + + //[Destructor]. You can add your own custom destruction code here.. + //[/Destructor] +} + +//============================================================================== +void EcubeDialogComponent::paint (Graphics& g) +{ + //[UserPrePaint] Add your own custom painting code here.. + //[/UserPrePaint] + + g.fillAll (Colours::white); + + //[UserPaint] Add your own custom painting code here.. + //[/UserPaint] +} + +void EcubeDialogComponent::resized() +{ + laAddressLabel->setBounds (16, 8, 150, 24); + bnOK->setBounds (24, 280, 112, 24); + bnCancel->setBounds (160, 280, 87, 24); + comboModule->setBounds (80, 72, 192, 24); + labelModule->setBounds (16, 72, 72, 24); + cbNetworkAddress->setBounds (24, 40, 248, 24); + groupComponent->setBounds (8, 104, 288, 160); + toggleHeadstage1->setBounds (24, 128, 112, 24); + toggleHeadstage2->setBounds (24, 152, 112, 24); + toggleHeadstage3->setBounds (24, 176, 112, 24); + toggleHeadstage4->setBounds (24, 200, 112, 24); + toggleHeadstage5->setBounds (24, 224, 112, 24); + toggleHeadstage6->setBounds (160, 128, 112, 24); + toggleHeadstage7->setBounds (160, 152, 112, 24); + toggleHeadstage8->setBounds (160, 176, 112, 24); + toggleHeadstage9->setBounds (160, 200, 112, 24); + toggleHeadstage10->setBounds (160, 224, 112, 24); + //[UserResized] Add your own custom resize handling here.. + //[/UserResized] +} + +void EcubeDialogComponent::buttonClicked (Button* buttonThatWasClicked) +{ + //[UserbuttonClicked_Pre] + //[/UserbuttonClicked_Pre] + + if (buttonThatWasClicked == bnOK) + { + //[UserButtonCode_bnOK] -- add your button handler code here.. + DialogWindow* dw = findParentComponentOfClass<DialogWindow>(); + if (dw != nullptr) + { + dw->exitModalState(1); + } + //[/UserButtonCode_bnOK] + } + else if (buttonThatWasClicked == bnCancel) + { + //[UserButtonCode_bnCancel] -- add your button handler code here.. + DialogWindow* dw = findParentComponentOfClass<DialogWindow>(); + if (dw != nullptr) + { + dw->exitModalState(0); + } + //[/UserButtonCode_bnCancel] + } + else if (buttonThatWasClicked == toggleHeadstage1) + { + //[UserButtonCode_toggleHeadstage1] -- add your button handler code here.. + //[/UserButtonCode_toggleHeadstage1] + } + else if (buttonThatWasClicked == toggleHeadstage2) + { + //[UserButtonCode_toggleHeadstage2] -- add your button handler code here.. + //[/UserButtonCode_toggleHeadstage2] + } + else if (buttonThatWasClicked == toggleHeadstage3) + { + //[UserButtonCode_toggleHeadstage3] -- add your button handler code here.. + //[/UserButtonCode_toggleHeadstage3] + } + else if (buttonThatWasClicked == toggleHeadstage4) + { + //[UserButtonCode_toggleHeadstage4] -- add your button handler code here.. + //[/UserButtonCode_toggleHeadstage4] + } + else if (buttonThatWasClicked == toggleHeadstage5) + { + //[UserButtonCode_toggleHeadstage5] -- add your button handler code here.. + //[/UserButtonCode_toggleHeadstage5] + } + else if (buttonThatWasClicked == toggleHeadstage6) + { + //[UserButtonCode_toggleHeadstage6] -- add your button handler code here.. + //[/UserButtonCode_toggleHeadstage6] + } + else if (buttonThatWasClicked == toggleHeadstage7) + { + //[UserButtonCode_toggleHeadstage7] -- add your button handler code here.. + //[/UserButtonCode_toggleHeadstage7] + } + else if (buttonThatWasClicked == toggleHeadstage8) + { + //[UserButtonCode_toggleHeadstage8] -- add your button handler code here.. + //[/UserButtonCode_toggleHeadstage8] + } + else if (buttonThatWasClicked == toggleHeadstage9) + { + //[UserButtonCode_toggleHeadstage9] -- add your button handler code here.. + //[/UserButtonCode_toggleHeadstage9] + } + else if (buttonThatWasClicked == toggleHeadstage10) + { + //[UserButtonCode_toggleHeadstage10] -- add your button handler code here.. + //[/UserButtonCode_toggleHeadstage10] + } + + //[UserbuttonClicked_Post] + //[/UserbuttonClicked_Post] +} + +void EcubeDialogComponent::comboBoxChanged (ComboBox* comboBoxThatHasChanged) +{ + //[UsercomboBoxChanged_Pre] + //[/UsercomboBoxChanged_Pre] + + if (comboBoxThatHasChanged == comboModule) + { + //[UserComboBoxCode_comboModule] -- add your combo box handling code here.. + //[/UserComboBoxCode_comboModule] + } + else if (comboBoxThatHasChanged == cbNetworkAddress) + { + //[UserComboBoxCode_cbNetworkAddress] -- add your combo box handling code here.. + //[/UserComboBoxCode_cbNetworkAddress] + } + + //[UsercomboBoxChanged_Post] + //[/UsercomboBoxChanged_Post] +} + + + +//[MiscUserCode] You can add your own definitions of your custom methods or any other code here... +String EcubeDialogComponent::GetAddressValue() +{ + return cbNetworkAddress->getText(); +} + +String EcubeDialogComponent::GetModuleName() +{ + return comboModule->getText(); +} + +void EcubeDialogComponent::SetDeviceNames(const StringArray& names) +{ + for (int i = 0; i < names.size(); i++) + { + cbNetworkAddress->addItem(names[i], i+1); + } +} + +void EcubeDialogComponent::GetHeadstageSelection(bool hs[10]) +{ + for (int i = 0; i < 10; i++) + hs[i] = false; + if (toggleHeadstage1->getToggleState()) + hs[0] = true; + if (toggleHeadstage2->getToggleState()) + hs[1] = true; + if (toggleHeadstage3->getToggleState()) + hs[2] = true; + if (toggleHeadstage4->getToggleState()) + hs[3] = true; + if (toggleHeadstage5->getToggleState()) + hs[4] = true; + if (toggleHeadstage6->getToggleState()) + hs[5] = true; + if (toggleHeadstage7->getToggleState()) + hs[6] = true; + if (toggleHeadstage8->getToggleState()) + hs[7] = true; + if (toggleHeadstage9->getToggleState()) + hs[8] = true; + if (toggleHeadstage10->getToggleState()) + hs[9] = true; +} + +//[/MiscUserCode] + + +//============================================================================== +#if 0 +/* -- Introjucer information section -- + + This is where the Introjucer stores the metadata that describe this GUI layout, so + make changes in here at your peril! + +BEGIN_JUCER_METADATA + +<JUCER_COMPONENT documentType="Component" className="EcubeDialogComponent" componentName="" + parentClasses="public Component" constructorParams="" variableInitialisers="" + snapPixels="8" snapActive="1" snapShown="1" overlayOpacity="0.330" + fixedSize="0" initialWidth="310" initialHeight="320"> + <BACKGROUND backgroundColour="ffffffff"/> + <LABEL name="Address Label" id="598e4f972ee19e11" memberName="laAddressLabel" + virtualName="" explicitFocusOrder="0" pos="16 8 150 24" edTextCol="ff000000" + edBkgCol="0" labelText="Network Address:" editableSingleClick="0" + editableDoubleClick="0" focusDiscardsChanges="0" fontname="Default font" + fontsize="15" bold="0" italic="0" justification="33"/> + <TEXTBUTTON name="OK button" id="d46371ace0e2731f" memberName="bnOK" virtualName="" + explicitFocusOrder="0" pos="24 280 112 24" buttonText="Connect" + connectedEdges="0" needsCallback="1" radioGroupId="0"/> + <TEXTBUTTON name="Cancel Button" id="e57f56c355a79a42" memberName="bnCancel" + virtualName="" explicitFocusOrder="0" pos="160 280 87 24" buttonText="Cancel" + connectedEdges="0" needsCallback="1" radioGroupId="0"/> + <COMBOBOX name="Module selection combobox" id="937bd3c2684c1901" memberName="comboModule" + virtualName="" explicitFocusOrder="0" pos="80 72 192 24" tooltip="Choose eCube module" + editable="0" layout="33" items="Headstage(s) Panel Analog Input Panel Digital Input" + textWhenNonSelected="" textWhenNoItems="(no choices)"/> + <LABEL name="Module selection label" id="8db8f9471da84061" memberName="labelModule" + virtualName="" explicitFocusOrder="0" pos="16 72 72 24" edTextCol="ff000000" + edBkgCol="0" labelText="Module" editableSingleClick="0" editableDoubleClick="0" + focusDiscardsChanges="0" fontname="Default font" fontsize="15" + bold="0" italic="0" justification="33"/> + <COMBOBOX name="Network Address ComboBox" id="40e24a76fea3653c" memberName="cbNetworkAddress" + virtualName="" explicitFocusOrder="0" pos="24 40 248 24" editable="1" + layout="33" items="" textWhenNonSelected="" textWhenNoItems="(no choices)"/> + <GROUPCOMPONENT name="headstage group" id="8dee2bbe073f0f63" memberName="groupComponent" + virtualName="" explicitFocusOrder="0" pos="8 104 288 160" title="Headstage selection"/> + <TOGGLEBUTTON name="Headstage1 button" id="c735dad1514586" memberName="toggleHeadstage1" + virtualName="" explicitFocusOrder="0" pos="24 128 112 24" buttonText="Headstage 1" + connectedEdges="0" needsCallback="1" radioGroupId="0" state="0"/> + <TOGGLEBUTTON name="Headstage2 button" id="24f215ce96874781" memberName="toggleHeadstage2" + virtualName="" explicitFocusOrder="0" pos="24 152 112 24" buttonText="Headstage 2" + connectedEdges="0" needsCallback="1" radioGroupId="0" state="0"/> + <TOGGLEBUTTON name="Headstage3 button" id="f035e57b5cc87d27" memberName="toggleHeadstage3" + virtualName="" explicitFocusOrder="0" pos="24 176 112 24" buttonText="Headstage 3" + connectedEdges="0" needsCallback="1" radioGroupId="0" state="0"/> + <TOGGLEBUTTON name="Headstage4 button" id="6abc75f398861c5f" memberName="toggleHeadstage4" + virtualName="" explicitFocusOrder="0" pos="24 200 112 24" buttonText="Headstage 4" + connectedEdges="0" needsCallback="1" radioGroupId="0" state="0"/> + <TOGGLEBUTTON name="Headstage5 button" id="3c5bb9c9db62f1bb" memberName="toggleHeadstage5" + virtualName="" explicitFocusOrder="0" pos="24 224 112 24" buttonText="Headstage 5" + connectedEdges="0" needsCallback="1" radioGroupId="0" state="0"/> + <TOGGLEBUTTON name="Headstage6 button" id="306515c3b3ea7522" memberName="toggleHeadstage6" + virtualName="" explicitFocusOrder="0" pos="160 128 112 24" buttonText="Headstage 6" + connectedEdges="0" needsCallback="1" radioGroupId="0" state="0"/> + <TOGGLEBUTTON name="Headstage7 button" id="704c88cd419204b0" memberName="toggleHeadstage7" + virtualName="" explicitFocusOrder="0" pos="160 152 112 24" buttonText="Headstage 7" + connectedEdges="0" needsCallback="1" radioGroupId="0" state="0"/> + <TOGGLEBUTTON name="Headstage8 button" id="ba85df2f98d869d9" memberName="toggleHeadstage8" + virtualName="" explicitFocusOrder="0" pos="160 176 112 24" buttonText="Headstage 8" + connectedEdges="0" needsCallback="1" radioGroupId="0" state="0"/> + <TOGGLEBUTTON name="Headstage9 button" id="16256502b9f60cd4" memberName="toggleHeadstage9" + virtualName="" explicitFocusOrder="0" pos="160 200 112 24" buttonText="Headstage 9" + connectedEdges="0" needsCallback="1" radioGroupId="0" state="0"/> + <TOGGLEBUTTON name="Headstage10 button" id="fab4cbe0a6d27a36" memberName="toggleHeadstage10" + virtualName="" explicitFocusOrder="0" pos="160 224 112 24" buttonText="Headstage 10" + connectedEdges="0" needsCallback="1" radioGroupId="0" state="1"/> +</JUCER_COMPONENT> + +END_JUCER_METADATA +*/ +#endif + + +//[EndFile] You can add extra defines here... +//[/EndFile] diff --git a/Source/UI/EcubeDialogComponent.h b/Source/UI/EcubeDialogComponent.h new file mode 100644 index 0000000000000000000000000000000000000000..2f2da1addbd43d822d87bebfcc8a4201d7cdb40f --- /dev/null +++ b/Source/UI/EcubeDialogComponent.h @@ -0,0 +1,92 @@ +/* + ============================================================================== + + This is an automatically generated GUI class created by the Introjucer! + + Be careful when adding custom code to these files, as only the code within + the "//[xyz]" and "//[/xyz]" sections will be retained when the file is loaded + and re-saved. + + Created with Introjucer version: 3.1.0 + + ------------------------------------------------------------------------------ + + The Introjucer is part of the JUCE library - "Jules' Utility Class Extensions" + Copyright 2004-13 by Raw Material Software Ltd. + + ============================================================================== +*/ + +#ifndef __JUCE_HEADER_CDBC0626D3EB7016__ +#define __JUCE_HEADER_CDBC0626D3EB7016__ + +//[Headers] -- You can add your own extra header files here -- +#include "JuceHeader.h" +//[/Headers] + + + +//============================================================================== +/** + //[Comments] + An auto-generated component, created by the Introjucer. + + Describe your class and how it works here! + //[/Comments] +*/ +class EcubeDialogComponent : public Component, + public ButtonListener, + public ComboBoxListener +{ +public: + //============================================================================== + EcubeDialogComponent (); + ~EcubeDialogComponent(); + + //============================================================================== + //[UserMethods] -- You can add your own custom methods in this section. + String GetAddressValue(); + String GetModuleName(); + void SetDeviceNames(const StringArray& names); + void GetHeadstageSelection(bool hs[10]); + //[/UserMethods] + + void paint (Graphics& g); + void resized(); + void buttonClicked (Button* buttonThatWasClicked); + void comboBoxChanged (ComboBox* comboBoxThatHasChanged); + + + +private: + //[UserVariables] -- You can add your own custom variables in this section. + //[/UserVariables] + + //============================================================================== + ScopedPointer<Label> laAddressLabel; + ScopedPointer<TextButton> bnOK; + ScopedPointer<TextButton> bnCancel; + ScopedPointer<ComboBox> comboModule; + ScopedPointer<Label> labelModule; + ScopedPointer<ComboBox> cbNetworkAddress; + ScopedPointer<GroupComponent> groupComponent; + ScopedPointer<ToggleButton> toggleHeadstage1; + ScopedPointer<ToggleButton> toggleHeadstage2; + ScopedPointer<ToggleButton> toggleHeadstage3; + ScopedPointer<ToggleButton> toggleHeadstage4; + ScopedPointer<ToggleButton> toggleHeadstage5; + ScopedPointer<ToggleButton> toggleHeadstage6; + ScopedPointer<ToggleButton> toggleHeadstage7; + ScopedPointer<ToggleButton> toggleHeadstage8; + ScopedPointer<ToggleButton> toggleHeadstage9; + ScopedPointer<ToggleButton> toggleHeadstage10; + + + //============================================================================== + JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (EcubeDialogComponent) +}; + +//[EndFile] You can add extra defines here... +//[/EndFile] + +#endif // __JUCE_HEADER_CDBC0626D3EB7016__ diff --git a/Source/UI/ProcessorList.cpp b/Source/UI/ProcessorList.cpp index 18a6cf0cbd9b68fd856c0cdb1101a71f92fac2c4..28c2817e235fa997b8e503cf55bbe3fc23b91eff 100755 --- a/Source/UI/ProcessorList.cpp +++ b/Source/UI/ProcessorList.cpp @@ -55,6 +55,9 @@ ProcessorList::ProcessorList() //sources->addSubItem(new ProcessorListItem("Signal Generator")); //sources->addSubItem(new ProcessorListItem("Custom FPGA")); sources->addSubItem(new ProcessorListItem("Rhythm FPGA")); +#if JUCE_WINDOWS // eCube module currently only available for Windows + sources->addSubItem(new ProcessorListItem("eCube")); // Added by Michael Borisov +#endif sources->addSubItem(new ProcessorListItem("File Reader")); //sources->addSubItem(new ProcessorListItem("Network Events")); sources->addSubItem(new ProcessorListItem("Serial Port")); diff --git a/open-ephys.jucer b/open-ephys.jucer index f3791847eae5b954987a0f92cc1e7d042035f0e7..ce7c632944877ae23e88f6370ddc31a107157b3f 100644 --- a/open-ephys.jucer +++ b/open-ephys.jucer @@ -381,6 +381,8 @@ <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="K24HnQ" name="EcubeEditor.cpp" compile="1" resource="0" file="Source/Processors/Editors/EcubeEditor.cpp"/> + <FILE id="lLjRJj" name="EcubeEditor.h" compile="0" resource="0" file="Source/Processors/Editors/EcubeEditor.h"/> <FILE id="Fs9xVR" name="SpikeSorterEditor.cpp" compile="1" resource="0" file="Source/Processors/Editors/SpikeSorterEditor.cpp"/> <FILE id="YnUVDV" name="SpikeSorterEditor.h" compile="0" resource="0" @@ -497,6 +499,8 @@ file="Source/Processors/Editors/GenericEditor.h"/> </GROUP> <GROUP id="ZgsuWxi" name="DataThreads"> + <FILE id="mbMbly" name="EcubeThread.cpp" compile="1" resource="0" file="Source/Processors/DataThreads/EcubeThread.cpp"/> + <FILE id="lKsc0T" name="EcubeThread.h" compile="0" resource="0" file="Source/Processors/DataThreads/EcubeThread.h"/> <GROUP id="LcWQtrg" name="rhythm-api"> <FILE id="hyM1EYD" name="okFrontPanelDLL.cpp" compile="1" resource="0" file="Source/Processors/DataThreads/rhythm-api/okFrontPanelDLL.cpp"/> @@ -554,6 +558,10 @@ file="Source/Processors/ProcessorGraph.h"/> </GROUP> <GROUP id="RNGb1yR" name="UI"> + <FILE id="PBkkUW" name="EcubeDialogComponent.cpp" compile="1" resource="0" + file="Source/UI/EcubeDialogComponent.cpp"/> + <FILE id="MFmxar" name="EcubeDialogComponent.h" compile="0" resource="0" + file="Source/UI/EcubeDialogComponent.h"/> <FILE id="gXswXJ" name="CustomArrowButton.cpp" compile="1" resource="0" file="Source/UI/CustomArrowButton.cpp"/> <FILE id="ECOEoc" name="CustomArrowButton.h" compile="0" resource="0"