From ac72523a02b9010758082500478fc84c818a9a93 Mon Sep 17 00:00:00 2001 From: jsiegle <jsiegle@mit.edu> Date: Mon, 13 Feb 2012 11:19:48 -0500 Subject: [PATCH] Acquisition automatically stops if data source is lost Changes to the DataThread, SourceNode, and UIComponent classes allow data threads to disable callbacks if they are no longer receiving input. So far this has only been tested with the Intan Board, but it works really well. Unplugging the board in the middle of acquisition allows the thread to exit, and callbacks to be disabled, without any seg faults. --- Builds/Linux/build/windowState.xml | 2 +- Source/Processors/DataThreads/DataThread.cpp | 16 ++++++++-- Source/Processors/DataThreads/DataThread.h | 6 +++- Source/Processors/DataThreads/FPGAThread.cpp | 2 +- Source/Processors/DataThreads/FPGAThread.h | 5 +++- .../DataThreads/FileReaderThread.cpp | 2 +- .../Processors/DataThreads/FileReaderThread.h | 5 +++- Source/Processors/DataThreads/IntanThread.cpp | 29 +++++++++++++++---- Source/Processors/DataThreads/IntanThread.h | 4 ++- .../Processors/DataThreads/NetworkThread.cpp | 2 +- Source/Processors/DataThreads/NetworkThread.h | 2 +- Source/Processors/ProcessorGraph.cpp | 1 + Source/Processors/SourceNode.cpp | 15 ++++++++-- Source/Processors/SourceNode.h | 3 ++ Source/UI/ControlPanel.cpp | 18 ++++++++++++ Source/UI/ControlPanel.h | 2 ++ Source/UI/UIComponent.cpp | 7 +++++ Source/UI/UIComponent.h | 3 +- 18 files changed, 103 insertions(+), 21 deletions(-) diff --git a/Builds/Linux/build/windowState.xml b/Builds/Linux/build/windowState.xml index 38dad57e4..3488bf5bf 100644 --- a/Builds/Linux/build/windowState.xml +++ b/Builds/Linux/build/windowState.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8"?> <MAINWINDOW> - <BOUNDS x="1729" y="52" w="1161" h="968" fullscreen="0"/> + <BOUNDS x="1739" y="52" w="1181" h="831" fullscreen="0"/> </MAINWINDOW> diff --git a/Source/Processors/DataThreads/DataThread.cpp b/Source/Processors/DataThreads/DataThread.cpp index 0f31a883e..c165ad233 100644 --- a/Source/Processors/DataThreads/DataThread.cpp +++ b/Source/Processors/DataThreads/DataThread.cpp @@ -9,8 +9,13 @@ */ #include "DataThread.h" +#include "../SourceNode.h" -DataThread::DataThread() : Thread ("Data Thread"), dataBuffer(0) {} + +DataThread::DataThread(SourceNode* s) : Thread ("Data Thread"), dataBuffer(0) +{ + sn = s; +} DataThread::~DataThread() {} @@ -21,8 +26,15 @@ void DataThread::run() { const MessageManagerLock mml (Thread::getCurrentThread()); if (! mml.lockWasGained()) return; - if (!updateBuffer()) + if (!updateBuffer()) { + std::cout << "Aquisition error...stopping thread." << std::endl; signalThreadShouldExit(); + //stopAcquisition(); + std::cout << "Notifying source node to stop acqusition." << std::endl; + sn->acquisitionStopped(); + } + // + } } diff --git a/Source/Processors/DataThreads/DataThread.h b/Source/Processors/DataThreads/DataThread.h index 33d197573..9f269fbee 100644 --- a/Source/Processors/DataThreads/DataThread.h +++ b/Source/Processors/DataThreads/DataThread.h @@ -15,12 +15,14 @@ #include <stdio.h> #include "DataBuffer.h" +class SourceNode; + class DataThread : public Thread { public: - DataThread(); + DataThread(SourceNode* sn); ~DataThread(); void run(); @@ -37,6 +39,8 @@ public: virtual int getNumChannels() = 0; virtual float getSampleRate() = 0; + SourceNode* sn; + }; diff --git a/Source/Processors/DataThreads/FPGAThread.cpp b/Source/Processors/DataThreads/FPGAThread.cpp index 59b5b18ff..485e978bd 100644 --- a/Source/Processors/DataThreads/FPGAThread.cpp +++ b/Source/Processors/DataThreads/FPGAThread.cpp @@ -10,7 +10,7 @@ #include "FPGAThread.h" -FPGAThread::FPGAThread() : DataThread(), +FPGAThread::FPGAThread(SourceNode* sn) : DataThread(sn), isRunning(false), numchannels(32), m_u32SegmentSize(1048576) diff --git a/Source/Processors/DataThreads/FPGAThread.h b/Source/Processors/DataThreads/FPGAThread.h index bf68110a5..04e9f371b 100644 --- a/Source/Processors/DataThreads/FPGAThread.h +++ b/Source/Processors/DataThreads/FPGAThread.h @@ -22,11 +22,14 @@ #include "okFrontPanelDLL.h" #include "DataThread.h" + +class SourceNode; + class FPGAThread : public DataThread { public: - FPGAThread(); + FPGAThread(SourceNode* sn); ~FPGAThread(); bool foundInputSource() {return true;} diff --git a/Source/Processors/DataThreads/FileReaderThread.cpp b/Source/Processors/DataThreads/FileReaderThread.cpp index 905793497..09dace080 100644 --- a/Source/Processors/DataThreads/FileReaderThread.cpp +++ b/Source/Processors/DataThreads/FileReaderThread.cpp @@ -11,7 +11,7 @@ #include "FileReaderThread.h" -FileReaderThread::FileReaderThread() : DataThread(), +FileReaderThread::FileReaderThread(SourceNode* sn) : DataThread(sn), sampleRate(40000.0), numChannels(16), samplesPerBlock(1024) diff --git a/Source/Processors/DataThreads/FileReaderThread.h b/Source/Processors/DataThreads/FileReaderThread.h index d98afa06a..676167341 100644 --- a/Source/Processors/DataThreads/FileReaderThread.h +++ b/Source/Processors/DataThreads/FileReaderThread.h @@ -17,11 +17,14 @@ #include <stdio.h> #include "DataThread.h" + +class SourceNode; + class FileReaderThread : public DataThread { public: - FileReaderThread(); + FileReaderThread(SourceNode* sn); ~FileReaderThread(); bool foundInputSource() {return true;} diff --git a/Source/Processors/DataThreads/IntanThread.cpp b/Source/Processors/DataThreads/IntanThread.cpp index 607b4fe09..fec0ac7db 100644 --- a/Source/Processors/DataThreads/IntanThread.cpp +++ b/Source/Processors/DataThreads/IntanThread.cpp @@ -10,7 +10,7 @@ #include "IntanThread.h" -IntanThread::IntanThread() : DataThread(), +IntanThread::IntanThread(SourceNode* sn) : DataThread(sn), vendorID(0x0403), productID(0x6010), baudrate(115200), @@ -29,7 +29,7 @@ IntanThread::IntanThread() : DataThread(), IntanThread::~IntanThread() { - closeUSB(); + //closeUSB(); deleteAndZero(dataBuffer); } @@ -70,17 +70,33 @@ bool IntanThread::foundInputSource() bool IntanThread::startAcquisition() { + closeUSB(); + initializeUSB(false); ftdi_write_data(&ftdic, &startCode, 1); startThread(); + + return true; } bool IntanThread::stopAcquisition() { - stopThread(500); + std::cout << "Received signal to terminate thread." << std::endl; + + if (isThreadRunning()) { + signalThreadShouldExit(); + } + + std::cout << "Thread stopped successfully, stopping Intan Board." << std::endl; - ftdi_write_data(&ftdic, &stopCode, 1); - unsigned char buf[4097]; // has to be bigger than the on-chip buffer - ftdi_read_data(&ftdic, buf, sizeof(buf)); + int return_value; + + if ((return_value = ftdi_write_data(&ftdic, &stopCode, 1)) > 0) { + unsigned char buf[4097]; // has to be bigger than the on-chip buffer + ftdi_read_data(&ftdic, buf, sizeof(buf)); + closeUSB(); + } + + return true; } @@ -150,6 +166,7 @@ bool IntanThread::updateBuffer() // >0 : number of bytes read if ((bytes_read = ftdi_read_data(&ftdic, buffer, sizeof(buffer))) < 0) { + std::cout << "NO DATA FOUND!" << std::endl; return false; } diff --git a/Source/Processors/DataThreads/IntanThread.h b/Source/Processors/DataThreads/IntanThread.h index 557e08d95..6b9bb8ee4 100644 --- a/Source/Processors/DataThreads/IntanThread.h +++ b/Source/Processors/DataThreads/IntanThread.h @@ -16,11 +16,13 @@ #include <stdio.h> #include "DataThread.h" +class SourceNode; + class IntanThread : public DataThread { public: - IntanThread(); + IntanThread(SourceNode* sn); ~IntanThread(); bool foundInputSource(); diff --git a/Source/Processors/DataThreads/NetworkThread.cpp b/Source/Processors/DataThreads/NetworkThread.cpp index 25a1e7a42..d02538c25 100644 --- a/Source/Processors/DataThreads/NetworkThread.cpp +++ b/Source/Processors/DataThreads/NetworkThread.cpp @@ -10,7 +10,7 @@ #include "NetworkThread.h" -NetworkThread::NetworkThread() : DataThread() +NetworkThread::NetworkThread(SourceNode* sn) : DataThread(sn) { char host[] = "10.121.43.47"; char port[] = "5227"; diff --git a/Source/Processors/DataThreads/NetworkThread.h b/Source/Processors/DataThreads/NetworkThread.h index 65ab10c5c..e1989bdb8 100644 --- a/Source/Processors/DataThreads/NetworkThread.h +++ b/Source/Processors/DataThreads/NetworkThread.h @@ -25,7 +25,7 @@ class NetworkThread : public DataThread { public: - NetworkThread(); + NetworkThread(SourceNode* sn); ~NetworkThread(); bool foundInputSource() {return true;} diff --git a/Source/Processors/ProcessorGraph.cpp b/Source/Processors/ProcessorGraph.cpp index b478fa9d9..13e6d78b4 100644 --- a/Source/Processors/ProcessorGraph.cpp +++ b/Source/Processors/ProcessorGraph.cpp @@ -113,6 +113,7 @@ void* ProcessorGraph::createNewProcessor(String& description)//, processor->setFilterViewport(filterViewport); processor->setConfiguration(config); processor->addActionListener(messageCenter); + processor->setUIComponent(UI); addNode(processor,id); // have to add it so it can be deleted by the graph diff --git a/Source/Processors/SourceNode.cpp b/Source/Processors/SourceNode.cpp index 7b81329da..ef09b9c3c 100644 --- a/Source/Processors/SourceNode.cpp +++ b/Source/Processors/SourceNode.cpp @@ -19,11 +19,11 @@ SourceNode::SourceNode(const String& name_) sourceCheckInterval(1500) { if (getName().equalsIgnoreCase("Intan Demo Board")) { - dataThread = new IntanThread(); + dataThread = new IntanThread(this); } else if (getName().equalsIgnoreCase("Custom FPGA")) { - dataThread = new FPGAThread(); + dataThread = new FPGAThread(this); } else if (getName().equalsIgnoreCase("File Reader")) { - dataThread = new FileReaderThread(); + dataThread = new FileReaderThread(this); } setNumInputs(0); @@ -211,6 +211,15 @@ bool SourceNode::disable() { return true; } +void SourceNode::acquisitionStopped() +{ + std::cout << "Source node sending signal to UI." << std::endl; + UI->disableCallbacks(); + enabledState(false); + GenericEditor* ed = (GenericEditor*) getEditor(); + viewport->updateVisibleEditors(ed, 4); +} + void SourceNode::process(AudioSampleBuffer &outputBuffer, MidiBuffer &midiMessages, diff --git a/Source/Processors/SourceNode.h b/Source/Processors/SourceNode.h index 40cad49f4..5605d2c49 100644 --- a/Source/Processors/SourceNode.h +++ b/Source/Processors/SourceNode.h @@ -19,6 +19,7 @@ #include "DataThreads/FPGAThread.h" #include "DataThreads/FileReaderThread.h" #include "GenericProcessor.h" +#include "../UI/UIComponent.h" class SourceNode : public GenericProcessor, public Timer @@ -54,6 +55,8 @@ public: bool disable(); bool isSource() {return true;} + + void acquisitionStopped(); private: diff --git a/Source/UI/ControlPanel.cpp b/Source/UI/ControlPanel.cpp index 70167f3ae..acec62bad 100644 --- a/Source/UI/ControlPanel.cpp +++ b/Source/UI/ControlPanel.cpp @@ -268,6 +268,24 @@ void ControlPanel::buttonClicked(Button* button) } +void ControlPanel::disableCallbacks() +{ + + std::cout << "Control panel received signal to disable callbacks." << std::endl; + + if (audio->callbacksAreActive()) + { + std::cout << "Stopping audio." << std::endl; + audio->endCallbacks(); + std::cout << "Disabling processors." << std::endl; + graph->disableProcessors(); + std::cout << "Updating control panel." << std::endl; + cpuMeter->updateCPU(0.0f); + playButton->setToggleState(false,false); + recordButton->setToggleState(false,false); + } +} + void ControlPanel::actionListenerCallback(const String & msg) { //std::cout << "Message Received." << std::endl; diff --git a/Source/UI/ControlPanel.h b/Source/UI/ControlPanel.h index 32c37a627..5a2fbce0e 100644 --- a/Source/UI/ControlPanel.h +++ b/Source/UI/ControlPanel.h @@ -86,6 +86,8 @@ public: ControlPanel(ProcessorGraph* graph, AudioComponent* audio); ~ControlPanel(); + void disableCallbacks(); + private: PlayButton* playButton; RecordButton* recordButton; diff --git a/Source/UI/UIComponent.cpp b/Source/UI/UIComponent.cpp index 8e0259b9b..8a9879abf 100644 --- a/Source/UI/UIComponent.cpp +++ b/Source/UI/UIComponent.cpp @@ -45,6 +45,7 @@ UIComponent::UIComponent (ProcessorGraph* pgraph, AudioComponent* audio_) messageCenter = new MessageCenter(); processorGraph->addActionListener(messageCenter); + addActionListener(messageCenter); addAndMakeVisible(messageCenter); std::cout << "Created message center." << std::endl; @@ -100,4 +101,10 @@ void UIComponent::resized() if (messageCenter != 0) messageCenter->setBounds(40,h-40,w-160,30); +} + +void UIComponent::disableCallbacks() +{ + //sendActionMessage("Data acquisition terminated."); + controlPanel->disableCallbacks(); } \ No newline at end of file diff --git a/Source/UI/UIComponent.h b/Source/UI/UIComponent.h index 2a9ecf1e1..226cd657a 100644 --- a/Source/UI/UIComponent.h +++ b/Source/UI/UIComponent.h @@ -25,7 +25,7 @@ class UIComponent : public Component, - //public ActionBroadcaster, + public ActionBroadcaster, public DragAndDropContainer // required for // drag-and-drop // internal components @@ -40,6 +40,7 @@ public: Configuration* getConfiguration() {return config;} //void transmitMessage(const String& message); + void disableCallbacks(); private: -- GitLab