/* ------------------------------------------------------------------ This file is part of the Open Ephys GUI Copyright (C) 2013 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 __RECORDNODE_H_FB9B1CA7__ #define __RECORDNODE_H_FB9B1CA7__ #include "../../JuceLibraryCode/JuceHeader.h" #include <stdio.h> #include <map> #include "GenericProcessor.h" #include "Channel.h" #include "RecordEngine.h" #define HEADER_SIZE 1024 #define BLOCK_LENGTH 1024 /** Receives inputs from all processors that want to save their data. Writes data to disk using fwrite. Receives a signal from the ControlPanel to begin recording. @see GenericProcessor, ControlPanel */ class RecordNode : public GenericProcessor, public FilenameComponentListener { public: RecordNode(); ~RecordNode(); /** Handle incoming data and decide which files and events to write to disk. */ void process(AudioSampleBuffer& buffer, MidiBuffer& eventBuffer, int& nSamples); /** Overrides implementation in GenericProcessor; used to change recording parameters on the fly. parameterIndex = 0: stop recording parameterIndex = 1: start recording parameterIndex = 2: newValue = 0: turn off recording for current channel newValue = 1: turn on recording for current channel */ void setParameter(int parameterIndex, float newValue); /** Called by the processor graph for each processor that could record data */ void registerProcessor(GenericProcessor* sourceNode); /** Called by the processor graph for each recordable channel */ void addInputChannel(GenericProcessor* sourceNode, int chan); bool enable(); bool disable(); /** returns channel names and whether we record them */ void getChannelNamesAndRecordingStatus(StringArray &names, Array<bool> &recording); /** update channel name */ void updateChannelName(int channelIndex, String newname); /** Get channel stored in channelPointers array */ Channel* getDataChannel(int index); /** Called by the ControlPanel to determine the amount of space left in the current dataDirectory. */ float getFreeSpace(); /** Selects a channel relative to a particular processor with ID = id */ void setChannel(Channel* ch); /** Turns recording on and off for a particular channel. Channel numbers are absolute (based on RecordNode channel mapping). */ void setChannelStatus(Channel* ch, bool status); /** Used to clear all connections prior to the start of acquisition. */ void resetConnections(); /** Callback to indicate when user has chosen a new data directory. */ void filenameComponentChanged(FilenameComponent*); /** Creates a new data directory in the location specified by the fileNameComponent. */ void createNewDirectory(); File getDataDirectory() { return rootFolder; } void appendTrialNumber(bool); void updateTrialNumber(); /** Adds a Record Engine to use */ void registerRecordEngine(RecordEngine* engine); /** Clears the list of active Record Engines */ void clearRecordEngines(); /** Must be called by a spike recording source on the "enable" method */ void registerSpikeSource(GenericProcessor* processor); /** Registers an electrode group for spike recording Must be called by a spike recording source on the "enable" method after the call to registerSpikeSource */ int addSpikeElectrode(SpikeRecordInfo* elec); /** Called by a spike recording source to write a spike to file */ void writeSpike(SpikeObject& spike, int electrodeIndex); SpikeRecordInfo* getSpikeElectrode(int index); /** Signals when to create a new data directory when recording starts.*/ bool newDirectoryNeeded; bool isRecording; bool allFilesOpened; /** Generate a Matlab-compatible datestring */ String generateDateString(); private: /** Keep the RecordNode informed of acquisition and record states. */ bool isProcessing, signalFilesShouldClose; /** User-selectable directory for saving data files. Currently defaults to the user's home directory. */ File dataDirectory; /** Automatically generated folder for each recording session. */ File rootFolder; /** Integer timestamp saved for each buffer. */ int64 timestamp; /** Integer to keep track of number of recording sessions in the same file */ uint16 recordingNumber; /** Used to generate timestamps if none are given. */ Time timer; /** Closes all open files after recording has finished. */ void closeAllFiles(); /** Pointers to all continuous channels */ Array<Channel*> channelPointers; /** Pointers to all event channels */ Array<Channel*> eventChannelPointers; OwnedArray<SpikeRecordInfo> spikeElectrodePointers; int spikeElectrodeIndex; int experimentNumber; bool hasRecorded; /** Generates a default directory name, based on the current date and time */ String generateDirectoryName(); /** Cycle through the event buffer, looking for data to save */ void handleEvent(int eventType, MidiMessage& event, int samplePos); /** Object for holding information about the events file */ Channel* eventChannel; /** Method for writing continuous buffers to disk. */ void writeContinuousBuffer(const float* data, int nSamples, int channel); /** Method for writing event buffers to disk. */ void writeEventBuffer(MidiMessage& event, int samplePos); void writeRecordMarker(FILE*); void writeTimestampAndSampleCount(FILE*); /** Used to indicate the end of each record */ char* recordMarker; CriticalSection diskWriteLock; Array<String> modifiedChannelNames; Array<int> modifiedChannelInd; bool appendTrialNum; int trialNum; /**RecordEngines loaded**/ OwnedArray<RecordEngine> engineArray; JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(RecordNode); }; #endif // __RECORDNODE_H_FB9B1CA7__