-
jsiegle authored
Whenever files are needed for recording, the RecordNode opens them. When they are no longer necessary (either recording has stopped, or recording of a particular channel has stopped), the RecordNode closes them.
jsiegle authoredWhenever files are needed for recording, the RecordNode opens them. When they are no longer necessary (either recording has stopped, or recording of a particular channel has stopped), the RecordNode closes them.
ControlPanel.cpp 10.25 KiB
/*
------------------------------------------------------------------
This file is part of the Open Ephys GUI
Copyright (C) 2012 Open Ephys
------------------------------------------------------------------
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "ControlPanel.h"
#include <stdio.h>
#include <math.h>
PlayButton::PlayButton()
: DrawableButton (T("PlayButton"), DrawableButton::ImageFitted)
{
DrawablePath normal, over, down;
Path p;
p.addTriangle (0.0f, 0.0f, 0.0f, 20.0f, 18.0f, 10.0f);
normal.setPath (p);
normal.setFill (Colours::lightgrey);
normal.setStrokeThickness (0.0f);
over.setPath (p);
over.setFill (Colours::black);
over.setStrokeFill (Colours::black);
over.setStrokeThickness (5.0f);
down.setPath (p);
down.setFill (Colours::pink);
down.setStrokeFill (Colours::pink);
down.setStrokeThickness (5.0f);
setImages (&normal, &over, &over);
setBackgroundColours(Colours::darkgrey, Colours::yellow);
setClickingTogglesState (true);
setTooltip ("Start/stop acquisition");
}
PlayButton::~PlayButton()
{
}
RecordButton::RecordButton()
: DrawableButton (T("RecordButton"), DrawableButton::ImageFitted)
{
DrawablePath normal, over, down;
Path p;
p.addEllipse (0.0,0.0,20.0,20.0);
normal.setPath (p);
normal.setFill (Colours::lightgrey);
normal.setStrokeThickness (0.0f);
over.setPath (p);
over.setFill (Colours::black);
over.setStrokeFill (Colours::black);
over.setStrokeThickness (5.0f);
setImages (&normal, &over, &over);
setBackgroundColours(Colours::darkgrey, Colours::red);
setClickingTogglesState (true);
setTooltip ("Start/stop writing to disk");
}
RecordButton::~RecordButton()
{
}
CPUMeter::CPUMeter() : Label(T("CPU Meter"),"0.0"), cpu(0.0f), lastCpu(0.0f)
{
MemoryInputStream mis(BinaryData::silkscreenserialized, BinaryData::silkscreenserializedSize, false);
Typeface::Ptr typeface = new CustomTypeface(mis);
font = Font(typeface);
font.setHeight(12);
}
CPUMeter::~CPUMeter()
{
}
void CPUMeter::updateCPU(float usage) {
lastCpu = cpu;
cpu = usage;
}
void CPUMeter::paint(Graphics& g)
{
g.fillAll(Colours::grey);
g.setColour(Colours::yellow);
g.fillRect(0.0f,0.0f,getWidth()*cpu,float(getHeight()));
g.setColour(Colours::black);
g.drawRect(0,0,getWidth(),getHeight(),1);
g.setFont(font);
g.drawSingleLineText("CPU",65,12);
}
DiskSpaceMeter::DiskSpaceMeter()
{
MemoryInputStream mis(BinaryData::silkscreenserialized, BinaryData::silkscreenserializedSize, false);
Typeface::Ptr typeface = new CustomTypeface(mis);
font = Font(typeface);
font.setHeight(12);
}
DiskSpaceMeter::~DiskSpaceMeter()
{
}
void DiskSpaceMeter::updateDiskSpace(float percent)
{
diskFree = percent;
}
void DiskSpaceMeter::paint(Graphics& g)
{
g.fillAll(Colours::grey);
g.setColour(Colours::lightgrey);
if (diskFree > 0)
g.fillRect(0.0f,0.0f,getWidth()*diskFree,float(getHeight()));
g.setColour(Colours::black);
g.drawRect(0,0,getWidth(),getHeight(),1);
g.setFont(font);
g.drawSingleLineText("DF",75,12);
}
Clock::Clock() : isRunning(false), isRecording(false)
{
const unsigned char* buffer = reinterpret_cast<const unsigned char*>(BinaryData::cpmono_light_otf);
size_t bufferSize = BinaryData::cpmono_light_otfSize;
font = new FTPixmapFont(buffer, bufferSize);
totalTime = 0;
totalRecordTime = 0;
}
Clock::~Clock()
{
}
void Clock::newOpenGLContextCreated()
{
glMatrixMode (GL_PROJECTION);
glLoadIdentity();
glOrtho (0, 1, 1, 0, 0, 1);
glMatrixMode (GL_MODELVIEW);
glEnable(GL_TEXTURE_2D);
glClearColor(0.23f, 0.23f, 0.23f, 1.0f);
glHint(GL_LINE_SMOOTH_HINT, GL_NICEST);
glHint(GL_POINT_SMOOTH_HINT, GL_NICEST);
glHint(GL_POLYGON_SMOOTH_HINT, GL_NICEST);
glEnable(GL_LINE_SMOOTH);
glEnable(GL_POINT_SMOOTH);
glEnable(GL_POLYGON_SMOOTH);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
}
void Clock::renderOpenGL()
{
glClear(GL_COLOR_BUFFER_BIT);
drawTime();
}
void Clock::drawTime()
{
if (isRunning)
{
int64 now = Time::currentTimeMillis();
int64 diff = now - lastTime;
totalTime += diff;
if (isRecording)
{
totalRecordTime += diff;
}
lastTime = Time::currentTimeMillis();
}
int m;
int s;
if (isRecording)
{
glColor4f(1.0, 0.0, 0.0, 1.0);
m = floor(totalRecordTime/60000);
s = floor((totalRecordTime - m*60000)/1000);
} else {
if (isRunning)
glColor4f(1.0, 1.0, 0.0, 1.0);
else
glColor4f(1.0, 1.0, 1.0, 1.0);
m = floor(totalTime/60000);
s = floor((totalTime - m*60000)/1000);
}
String timeString = "";
// if (m < 10)
// String timeString = " ";
// else if (m < 100)
timeString += m;
timeString += " min ";
timeString += s;
timeString += " s";
glRasterPos2f(8.0/getWidth(),0.75f);
font->FaceSize(23);
font->Render(timeString);
}
void Clock::start()
{
if (!isRunning)
{
isRunning = true;
lastTime = Time::currentTimeMillis();
}
}
void Clock::startRecording()
{
if (!isRecording)
{
isRecording = true;
start();
}
}
void Clock::stop()
{
if (isRunning)
{
isRunning = false;
isRecording = false;
}
}
void Clock::stopRecording()
{
if (isRecording)
{
isRecording = false;
}
}
ControlPanel::ControlPanel(ProcessorGraph* graph_, AudioComponent* audio_) :
graph (graph_), audio(audio_)
{
audioEditor = (AudioEditor*) graph->getAudioNode()->createEditor();
addAndMakeVisible(audioEditor);
playButton = new PlayButton();
playButton->addListener (this);
addAndMakeVisible(playButton);
recordButton = new RecordButton();
recordButton->addListener (this);
addAndMakeVisible(recordButton);
masterClock = new Clock();
addAndMakeVisible(masterClock);
cpuMeter = new CPUMeter();
addAndMakeVisible(cpuMeter);
diskMeter = new DiskSpaceMeter();
addAndMakeVisible(diskMeter);
startTimer(100);
if (1) {
MemoryInputStream mis(BinaryData::misoserialized, BinaryData::misoserializedSize, false);
Typeface::Ptr typeface = new CustomTypeface(mis);
font = Font(typeface);
}
}
ControlPanel::~ControlPanel()
{
//deleteAllChildren() -> if this is used, audioEditor will be deleted
deleteAndZero(playButton);
deleteAndZero(recordButton);
deleteAndZero(masterClock);
deleteAndZero(cpuMeter);
deleteAndZero(diskMeter);
//audioEditor will delete itself
graph = 0;
}
void ControlPanel::paint(Graphics& g)
{
g.setColour(Colour(58,58,58));
g.fillRect(0,0,getWidth(),getHeight());
}
void ControlPanel::resized()
{
int w = getWidth();
int h = getHeight();
if (playButton != 0)
playButton->setBounds(w-h*9,5,h-5,h-10);
if (recordButton != 0)
recordButton->setBounds(w-h*8,5,h-5,h-10);
if (masterClock != 0)
masterClock->setBounds(w-h*6,0,h*6,h);
if (cpuMeter != 0)
cpuMeter->setBounds(8,h/4,h*3,h/2);
if (diskMeter != 0)
diskMeter->setBounds(16+h*3,h/4,h*3,h/2);
if (audioEditor != 0)
audioEditor->setBounds(h*7,5,h*8,h-10);
}
void ControlPanel::buttonClicked(Button* button)
{
if (button == recordButton)
{
std::cout << "Record button pressed." << std::endl;
if (recordButton->getToggleState())
{
playButton->setToggleState(true,false);
graph->getRecordNode()->setParameter(1,10.0f);
masterClock->startRecording(); // turn on recording
} else {
graph->getRecordNode()->setParameter(0,10.0f); // turn off recording
masterClock->stopRecording();
}
} else if (button == playButton) {
std::cout << "Play button pressed." << std::endl;
if (!playButton->getToggleState())
{
recordButton->setToggleState(false,false);
}
}
if (playButton->getToggleState())
{
if (!audio->callbacksAreActive()) {
if (graph->enableProcessors())
{
if (recordButton->getToggleState())
graph->getRecordNode()->setParameter(1,10.0f);
audio->beginCallbacks();
masterClock->start();
}
}
} else {
if (audio->callbacksAreActive()) {
audio->endCallbacks();
graph->disableProcessors();
cpuMeter->updateCPU(0.0f);
masterClock->stop();
}
}
}
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);
masterClock->stopRecording();
masterClock->stop();
}
void ControlPanel::actionListenerCallback(const String & msg)
{
//std::cout << "Message Received." << std::endl;
if (playButton->getToggleState()) {
cpuMeter->updateCPU(audio->deviceManager.getCpuUsage());
}
cpuMeter->repaint();
diskMeter->updateDiskSpace(graph->getRecordNode()->getFreeSpace());
diskMeter->repaint();
}
void ControlPanel::timerCallback()
{
//std::cout << "Message Received." << std::endl;
if (playButton->getToggleState()) {
cpuMeter->updateCPU(audio->deviceManager.getCpuUsage());
}
cpuMeter->repaint();
masterClock->repaint();
diskMeter->updateDiskSpace(graph->getRecordNode()->getFreeSpace());
diskMeter->repaint();
}