/*
------------------------------------------------------------------

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/>.

*/

#include "ControlPanel.h"
#include "UIComponent.h"
#include <stdio.h>
#include <math.h>
#include "../Processors/RecordNode/RecordEngine.h"

PlayButton::PlayButton()
    : DrawableButton("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("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("CPU Meter","0.0"), cpu(0.0f), lastCpu(0.0f)
{

    font = Font("Small Text", 12, Font::plain);

    // MemoryInputStream mis(BinaryData::silkscreenserialized, BinaryData::silkscreenserializedSize, false);
    // Typeface::Ptr typeface = new CustomTypeface(mis);
    // font = Font(typeface);
    // font.setHeight(12);

    setTooltip("CPU usage");
}

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()

{

    font = Font("Small Text", 12, Font::plain);

    // MemoryInputStream mis(BinaryData::silkscreenserialized, BinaryData::silkscreenserializedSize, false);
    // Typeface::Ptr typeface = new CustomTypeface(mis);
    // font = Font(typeface);
    // font.setHeight(12);

    setTooltip("Disk space available");
}


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)
{

    clockFont = Font("Default Light", 30, Font::plain);

    // MemoryInputStream mis(BinaryData::cpmonolightserialized, BinaryData::cpmonolightserializedSize, false);
    // Typeface::Ptr typeface = new CustomTypeface(mis);
    // clockFont = Font(typeface);
    // clockFont.setHeight(30);

    totalTime = 0;
    totalRecordTime = 0;

}

Clock::~Clock()
{
}


void Clock::paint(Graphics& g)
{
    if (isRecording)
    {
        g.fillAll(Colour(255,0,0));
    }
    else
    {
        g.fillAll(Colour(58,58,58));
    }

    drawTime(g);
}

void Clock::drawTime(Graphics& g)
{

    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)
    {
        g.setColour(Colours::black);
        m = floor(totalRecordTime/60000.0);
        s = floor((totalRecordTime - m*60000.0)/1000.0);

    }
    else
    {

        if (isRunning)
            g.setColour(Colours::yellow);
        else
            g.setColour(Colours::white);

        m = floor(totalTime/60000.0);
        s = floor((totalTime - m*60000.0)/1000.0);
    }

    String timeString = "";

    timeString += m;
    timeString += " min ";
    timeString += s;
    timeString += " s";

    g.setFont(clockFont);
    //g.setFont(30);
    g.drawText(timeString, 0, 0, getWidth(), getHeight(), Justification::left, false);

}

void Clock::start()
{
    if (!isRunning)
    {
        isRunning = true;
        lastTime = Time::currentTimeMillis();
    }
}

void Clock::resetRecordTime()
{
    totalRecordTime = 0;
}

void Clock::startRecording()
{
    if (!isRecording)
    {
        isRecording = true;
        start();
    }
}

void Clock::stop()
{
    if (isRunning)
    {
        isRunning = false;
        isRecording = false;
    }
}

void Clock::stopRecording()
{
    if (isRecording)
    {
        isRecording = false;
    }

}


ControlPanelButton::ControlPanelButton(ControlPanel* cp_) : cp(cp_)
{
    open = false;

    setTooltip("Show/hide recording options");
}

ControlPanelButton::~ControlPanelButton()
{

}

void ControlPanelButton::paint(Graphics& g)
{
    //g.fillAll(Colour(58,58,58));

    g.setColour(Colours::white);

    Path p;

    float h = getHeight();
    float w = getWidth();

    if (open)
    {
        p.addTriangle(0.5f*w, 0.8f*h,
                      0.2f*w, 0.2f*h,
                      0.8f*w, 0.2f*h);
    }
    else
    {
        p.addTriangle(0.8f*w, 0.8f*h,
                      0.2f*w, 0.5f*h,
                      0.8f*w, 0.2f*h);
    }

    PathStrokeType pst = PathStrokeType(1.0f, PathStrokeType::curved, PathStrokeType::rounded);

    g.strokePath(p, pst);

}


void ControlPanelButton::mouseDown(const MouseEvent& e)
{
    open = !open;
    cp->openState(open);
    repaint();

}

void ControlPanelButton::toggleState()
{
    open = !open;
    repaint();
}

void ControlPanelButton::setState(bool b)
{
    open = b;
    repaint();
}




ControlPanel::ControlPanel(ProcessorGraph* graph_, AudioComponent* audio_)
    : graph(graph_), audio(audio_), initialize(true), open(false), lastEngineIndex(-1)
{

    if (1)
    {

        font = Font("Paragraph", 13, Font::plain);

        // MemoryInputStream mis(BinaryData::misoserialized, BinaryData::misoserializedSize, false);
        // Typeface::Ptr typeface = new CustomTypeface(mis);
        // font = Font(typeface);
        // font.setHeight(15);
    }

    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);

    cpb = new ControlPanelButton(this);
    addAndMakeVisible(cpb);

    recordSelector = new ComboBox();
    recordSelector->addListener(this);
    for (int i =0; i < RecordEngineManager::getNumOfBuiltInEngines(); i++)
    {
        RecordEngineManager* rem = RecordEngineManager::createBuiltInEngineManager(i);
        recordSelector->addItem(rem->getName(),i+1);
        recordEngines.add(rem);
    }
    addChildComponent(recordSelector);

    recordOptionsButton = new UtilityButton("R",Font("Small Text", 15, Font::plain));
    recordOptionsButton->setEnabledState(true);
    recordOptionsButton->addListener(this);
    recordOptionsButton->setTooltip("Configure options for selected record engine");
    addChildComponent(recordOptionsButton);

    newDirectoryButton = new UtilityButton("+", Font("Small Text", 15, Font::plain));
    newDirectoryButton->setEnabledState(false);
    newDirectoryButton->addListener(this);
    newDirectoryButton->setTooltip("Start a new data directory");
    addChildComponent(newDirectoryButton);


    File executable = File::getSpecialLocation(File::currentExecutableFile);

#if defined(__APPLE__)
    const String executableDirectory =
        executable.getParentDirectory().getParentDirectory().getParentDirectory().getParentDirectory().getFullPathName();
#else
    const String executableDirectory = executable.getParentDirectory().getFullPathName();
#endif

    filenameComponent = new FilenameComponent("folder selector",
                                              executableDirectory,
                                              true,
                                              true,
                                              true,
                                              "*",
                                              "",
                                              "");
    addChildComponent(filenameComponent);

    prependText = new Label("Prepend","");
    prependText->setEditable(true);
    prependText->addListener(this);
    prependText->setColour(Label::backgroundColourId, Colours::lightgrey);
    prependText->setTooltip("Prepend to name of data directory");

    addChildComponent(prependText);

    dateText = new Label("Date","YYYY-MM-DD_HH-MM-SS");
    dateText->setColour(Label::backgroundColourId, Colours::lightgrey);
    dateText->setColour(Label::textColourId, Colours::grey);
    addChildComponent(dateText);

    appendText = new Label("Append","");
    appendText->setEditable(true);
    appendText->addListener(this);
    appendText->setColour(Label::backgroundColourId, Colours::lightgrey);
    addChildComponent(appendText);
    appendText->setTooltip("Append to name of data directory");

    //diskMeter->updateDiskSpace(graph->getRecordNode()->getFreeSpace());
    //diskMeter->repaint();
    //refreshMeters();
    startTimer(10);

    setWantsKeyboardFocus(true);

    backgroundColour = Colour(58,58,58);

}

ControlPanel::~ControlPanel()
{

}

void ControlPanel::setRecordState(bool t)
{

    //MessageManager* mm = MessageManager::getInstance();

    recordButton->setToggleState(t, sendNotification);

}

void ControlPanel::updateChildComponents()
{

    filenameComponent->addListener(getProcessorGraph()->getRecordNode());
    getProcessorGraph()->getRecordNode()->filenameComponentChanged(filenameComponent);
    recordSelector->setSelectedId(1,sendNotificationSync);

}

void ControlPanel::createPaths()
{
    /*  int w = getWidth() - 325;
    if (w > 150)
    w = 150;*/

    int w = getWidth() - 435;
    if (w > 22)
        w = 22;

    int h1 = getHeight()-32;
    int h2 = getHeight();
    int indent = 5;

    p1.clear();
    p1.startNewSubPath(0, h1);
    p1.lineTo(w, h1);
    p1.lineTo(w + indent, h1 + indent);
    p1.lineTo(w + indent, h2 - indent);
    p1.lineTo(w + indent*2, h2);
    p1.lineTo(0, h2);
    p1.closeSubPath();

    p2.clear();
    p2.startNewSubPath(getWidth(), h2-indent);
    p2.lineTo(getWidth(), h2);
    p2.lineTo(getWidth()-indent, h2);
    p2.closeSubPath();

}

void ControlPanel::paint(Graphics& g)
{
    g.setColour(backgroundColour);
    g.fillRect(0,0,getWidth(),getHeight());

    if (open)
    {
        createPaths();
        g.setColour(Colours::black);
        g.fillPath(p1);
        g.fillPath(p2);
    }

}

void ControlPanel::resized()
{
    int w = getWidth();
    int h = 32; //getHeight();

    if (playButton != 0)
    {
        if (w > 330)
            playButton->setBounds(w-h*10,5,h-5,h-10);
        \
        else
            playButton->setBounds(5,5,h-5,h-10);
        \
    }

    if (recordButton != 0)
    {
        if (w > 330)
            recordButton->setBounds(w-h*9,5,h-5,h-10);
        else
            recordButton->setBounds(5+h,5,h-5,h-10);
    }

    if (masterClock != 0)
    {
        if (w > 330)
            masterClock->setBounds(w-h*7-15,0,h*7-15,h);
        else
            masterClock->setBounds(5+h*2+15,0,h*7-15,h);
    }

    int offset1 = 750 - getWidth();
    if (offset1 > h)
        offset1 = h;

    int offset2 = 570 - getWidth();
    if (offset2 > h)
        offset2 = h;

    if (cpuMeter != 0)
    {

        if (getWidth() < 750 && getWidth() >= 570)
            cpuMeter->setBounds(8,h/4+offset1,h*3,h/2);
        else if (getWidth() < 570)
            cpuMeter->setBounds(8,h/4+offset1+offset2,h*3,h/2);
        else
            cpuMeter->setBounds(8,h/4,h*3,h/2);
    }

    if (diskMeter != 0)
    {
        if (getWidth() < 750 && getWidth() >= 570)
            diskMeter->setBounds(16+h*3,h/4+offset1,h*3,h/2);
        else if (getWidth() < 570)
            diskMeter->setBounds(16+h*3,h/4+offset1+offset2,h*3,h/2);
        else
            diskMeter->setBounds(16+h*3,h/4,h*3,h/2);

    }

    if (audioEditor != 0)
    {
        if (getWidth() < 750 && getWidth() >= 570)
            audioEditor->setBounds(w-526,0,h*8,h);
        else if (getWidth() < 570)
            audioEditor->setBounds(8,0+offset2,h*8,h);
        else
            audioEditor->setBounds(h*7,0,h*8,h);
    }


    if (cpb != 0)
    {
        if (open)
            cpb->setBounds(w-28,getHeight()-5-h*2+10,h-10,h-10);
        else
            cpb->setBounds(w-28,getHeight()-5-h+10,h-10,h-10);
    }

    createPaths();

    if (open)
    {
        int topBound = getHeight()-h+10-5;

        recordSelector->setBounds((w - 435) > 40 ? 35 : w-450, topBound, 100, h-10);
        recordSelector->setVisible(true);

        recordOptionsButton->setBounds((w - 435) > 40 ? 140 : w-350,topBound, h-10, h-10);
        recordOptionsButton->setVisible(true);

        filenameComponent->setBounds(165, topBound, w-500, h-10);
        filenameComponent->setVisible(true);

        newDirectoryButton->setBounds(w-h+4, topBound, h-10, h-10);
        newDirectoryButton->setVisible(true);

        prependText->setBounds(165+w-490, topBound, 50, h-10);
        prependText->setVisible(true);

        dateText->setBounds(165+w-435, topBound, 175, h-10);
        dateText->setVisible(true);

        appendText->setBounds(165+w-255, topBound, 50, h-10);
        appendText->setVisible(true);

    }
    else
    {
        filenameComponent->setVisible(false);
        newDirectoryButton->setVisible(false);
        prependText->setVisible(false);
        dateText->setVisible(false);
        appendText->setVisible(false);
        recordSelector->setVisible(false);
        recordOptionsButton->setVisible(false);
    }

    repaint();


}

void ControlPanel::openState(bool os)
{
    open = os;

    cpb->setState(os);

    getUIComponent()->childComponentChanged();
}

void ControlPanel::labelTextChanged(Label* label)
{
    graph->getRecordNode()->newDirectoryNeeded = true;
    newDirectoryButton->setEnabledState(false);
    masterClock->resetRecordTime();

    dateText->setColour(Label::textColourId, Colours::grey);
}

void ControlPanel::startRecording()
{

    masterClock->startRecording(); // turn on recording
    backgroundColour = Colour(255,0,0);
    prependText->setEditable(false);
    appendText->setEditable(false);
    dateText->setColour(Label::textColourId, Colours::black);

    graph->setRecordState(true);

    repaint();
}

void ControlPanel::stopRecording()
{
    graph->setRecordState(false); // turn off recording in processor graph

    masterClock->stopRecording();
    newDirectoryButton->setEnabledState(true);
    backgroundColour = Colour(58,58,58);

    prependText->setEditable(true);
    appendText->setEditable(true);

    recordButton->setToggleState(false, dontSendNotification);

    repaint();
}

void ControlPanel::buttonClicked(Button* button)

{

    if (button == newDirectoryButton && newDirectoryButton->getEnabledState())
    {
        graph->getRecordNode()->newDirectoryNeeded = true;
        newDirectoryButton->setEnabledState(false);
        masterClock->resetRecordTime();

        dateText->setColour(Label::textColourId, Colours::grey);

        return;

    }

    if (button == playButton)
    {
        if (playButton->getToggleState())
        {

            if (graph->enableProcessors()) // start the processor graph
            {
                if (recordEngines[recordSelector->getSelectedId()-1]->isWindowOpen())
                    recordEngines[recordSelector->getSelectedId()-1]->toggleConfigWindow();

                audio->beginCallbacks();
                masterClock->start();
                audioEditor->disable();

                stopTimer();
                startTimer(250); // refresh every 250 ms

            }
            recordSelector->setEnabled(false);
            recordOptionsButton->setEnabled(false);
        }
        else
        {

            if (recordButton->getToggleState())
            {
                stopRecording();
            }

            audio->endCallbacks();
            graph->disableProcessors();
            refreshMeters();
            masterClock->stop();
            stopTimer();
            startTimer(60000); // back to refresh every minute
            audioEditor->enable();
            recordSelector->setEnabled(true);
            recordOptionsButton->setEnabled(true);

        }

        return;
    }

    if (button == recordButton)
    {
        if (recordButton->getToggleState())
        {
            if (playButton->getToggleState())
            {
                startRecording();
            }
            else
            {
                if (graph->enableProcessors()) // start the processor graph
                {
                    if (recordEngines[recordSelector->getSelectedId()-1]->isWindowOpen())
                        recordEngines[recordSelector->getSelectedId()-1]->toggleConfigWindow();

                    audio->beginCallbacks();
                    masterClock->start();
                    audioEditor->disable();

                    stopTimer();
                    startTimer(250); // refresh every 250 ms

                    startRecording();

                    playButton->setToggleState(true, dontSendNotification);
                    recordSelector->setEnabled(false);
                    recordOptionsButton->setEnabled(false);

                }
            }
        }
        else
        {
            stopRecording();
        }
    }

    if (button == recordOptionsButton)
    {
        int id = recordSelector->getSelectedId()-1;
        if (id < 0) return;

        recordEngines[id]->toggleConfigWindow();
    }

}

void ControlPanel::comboBoxChanged(ComboBox* combo)
{
    if (lastEngineIndex >= 0)
    {
        if (recordEngines[lastEngineIndex]->isWindowOpen())
            recordEngines[lastEngineIndex]->toggleConfigWindow();
    }
    RecordEngine* re;
    getProcessorGraph()->getRecordNode()->clearRecordEngines();
    if (combo->getSelectedId() > 0)
    {
        re = recordEngines[combo->getSelectedId()-1]->instantiateEngine();
    }
    else
    {
        std::cout << "Engine ComboBox: Bad ID" << std::endl;
        combo->setSelectedId(1,dontSendNotification);
        re = recordEngines[0]->instantiateEngine();
    }
    re->setUIComponent(getUIComponent());
    re->registerManager(recordEngines[combo->getSelectedId()-1]);
    getProcessorGraph()->getRecordNode()->registerRecordEngine(re);

    graph->getRecordNode()->newDirectoryNeeded = true;
    newDirectoryButton->setEnabledState(false);
    masterClock->resetRecordTime();

    dateText->setColour(Label::textColourId, Colours::grey);
    lastEngineIndex=combo->getSelectedId()-1;
}

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;
        refreshMeters();
        stopTimer();
        startTimer(60000); // back to refresh every 10 seconds

    }

    playButton->setToggleState(false, dontSendNotification);
    recordButton->setToggleState(false, dontSendNotification);
    recordSelector->setEnabled(true);
    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;
    refreshMeters();

}

void ControlPanel::refreshMeters()
{
    if (playButton->getToggleState())
    {
        cpuMeter->updateCPU(audio->deviceManager.getCpuUsage());
    }
    else
    {
        cpuMeter->updateCPU(0.0f);
    }

    cpuMeter->repaint();

    masterClock->repaint();

    diskMeter->updateDiskSpace(graph->getRecordNode()->getFreeSpace());
    diskMeter->repaint();

    if (initialize)
    {
        stopTimer();
        startTimer(60000); // check for disk updates every minute
        initialize = false;
    }
}

bool ControlPanel::keyPressed(const KeyPress& key)
{
    std::cout << "Control panel received" << key.getKeyCode() << std::endl;

    return false;

}

void ControlPanel::toggleState()
{
    open = !open;

    cpb->toggleState();
    getUIComponent()->childComponentChanged();
}

String ControlPanel::getTextToAppend()
{
    String t = appendText->getText();

    if (t.length() > 0)
    {
        return "_" + t;
    }
    else
    {
        return t;
    }
}

String ControlPanel::getTextToPrepend()
{
    String t = prependText->getText();

    if (t.length() > 0)
    {
        return t + "_";
    }
    else
    {
        return t;
    }
}

void ControlPanel::setDateText(String t)
{
    dateText->setText(t, dontSendNotification);
}


void ControlPanel::saveStateToXml(XmlElement* xml)
{

    XmlElement* controlPanelState = xml->createNewChildElement("CONTROLPANEL");
    controlPanelState->setAttribute("isOpen",open);
    controlPanelState->setAttribute("prependText",prependText->getText());
    controlPanelState->setAttribute("appendText",appendText->getText());
    controlPanelState->setAttribute("recordEngine",recordSelector->getSelectedId());

    audioEditor->saveStateToXml(xml);

    XmlElement* recordEnginesState = xml->createNewChildElement("RECORDENGINES");
    for (int i=0; i < recordEngines.size(); i++)
    {
        XmlElement* reState = recordEnginesState->createNewChildElement("ENGINE");
        reState->setAttribute("id",recordEngines[i]->getID());
        reState->setAttribute("name",recordEngines[i]->getName());
        recordEngines[i]->saveParametersToXml(reState);
    }

}

void ControlPanel::loadStateFromXml(XmlElement* xml)
{

    forEachXmlChildElement(*xml, xmlNode)
    {
        if (xmlNode->hasTagName("CONTROLPANEL"))
        {

            appendText->setText(xmlNode->getStringAttribute("appendText", ""), dontSendNotification);
            prependText->setText(xmlNode->getStringAttribute("prependText", ""), dontSendNotification);
            recordSelector->setSelectedId(xmlNode->getIntAttribute("recordEngine",1), sendNotificationSync);

            bool isOpen = xmlNode->getBoolAttribute("isOpen");
            openState(isOpen);

        }
        else if (xmlNode->hasTagName("RECORDENGINES"))
        {
            for (int i = 0; i < recordEngines.size(); i++)
            {
                forEachXmlChildElementWithTagName(*xmlNode,xmlEngine,"ENGINE")
                {
                    if (xmlEngine->getStringAttribute("id") == recordEngines[i]->getID())
                        recordEngines[i]->loadParametersFromXml(xmlEngine);
                }
            }
        }
    }

    audioEditor->loadStateFromXml(xml);

}


StringArray ControlPanel::getRecentlyUsedFilenames()
{
    return filenameComponent->getRecentlyUsedFilenames();
}


void ControlPanel::setRecentlyUsedFilenames(const StringArray& filenames)
{
    filenameComponent->setRecentlyUsedFilenames(filenames);
}