StandaloneFilterWindow::~StandaloneFilterWindow()
{
    PropertySet* const globalSettings = getGlobalSettings();

    globalSettings->setValue (T("windowX"), getX());
    globalSettings->setValue (T("windowY"), getY());

    deleteAndZero (optionsButton);

    if (globalSettings != 0 && deviceManager != 0)
    {
        XmlElement* const xml = deviceManager->createStateXml();
        globalSettings->setValue (T("audioSetup"), xml);
        delete xml;
    }

    deleteAndZero (deviceManager);

    if (globalSettings != 0 && filter != 0)
    {
        JUCE_NAMESPACE::MemoryBlock data;
        filter->getStateInformation (data);

        globalSettings->setValue (T("filterState"), data.toBase64Encoding());
    }

    deleteFilter();
}
void AudioProcessor::copyXmlToBinary (const XmlElement& xml,
                                      JUCE_NAMESPACE::MemoryBlock& destData)
{
    const String xmlString (xml.createDocument (String::empty, true, false));
    const int stringLength = xmlString.length();

    destData.setSize (stringLength + 10);

    char* const d = (char*) destData.getData();
    *(uint32*) d = ByteOrder::swapIfBigEndian ((const uint32) magicXmlNumber);
    *(uint32*) (d + 4) = ByteOrder::swapIfBigEndian ((const uint32) stringLength);

    xmlString.copyToBuffer (d + 8, stringLength);
}
//==============================================================================
void StandaloneFilterWindow::saveState()
{
    PropertySet* const globalSettings = getGlobalSettings();

    FileChooser fc (TRANS("Save current state"),
                    globalSettings != 0 ? File (globalSettings->getValue (T("lastStateFile")))
                                        : File::nonexistent);

    if (fc.browseForFileToSave (true))
    {
        JUCE_NAMESPACE::MemoryBlock data;
        filter->getStateInformation (data);

        if (! fc.getResult().replaceWithData (data.getData(), data.getSize()))
        {
            AlertWindow::showMessageBox (AlertWindow::WarningIcon,
                                         TRANS("Error whilst saving"),
                                         TRANS("Couldn't write to the specified file!"));
        }
    }
}
void StandaloneFilterWindow::loadState()
{
    PropertySet* const globalSettings = getGlobalSettings();

    FileChooser fc (TRANS("Load a saved state"),
                    globalSettings != 0 ? File (globalSettings->getValue (T("lastStateFile")))
                                        : File::nonexistent);

    if (fc.browseForFileToOpen())
    {
        JUCE_NAMESPACE::MemoryBlock data;

        if (fc.getResult().loadFileAsData (data))
        {
            filter->setStateInformation (data.getData(), data.getSize());
        }
        else
        {
            AlertWindow::showMessageBox (AlertWindow::WarningIcon,
                                         TRANS("Error whilst loading"),
                                         TRANS("Couldn't read from the specified file!"));
        }
    }
}
//==============================================================================
StandaloneFilterWindow::StandaloneFilterWindow (const String& title,
                                                const Colour& backgroundColour)
    : DocumentWindow (title, backgroundColour,
                      DocumentWindow::minimiseButton
                       | DocumentWindow::closeButton),
      filter (0),
      deviceManager (0),
      optionsButton (0)
{
    setTitleBarButtonsRequired (DocumentWindow::minimiseButton | DocumentWindow::closeButton, false);

    PropertySet* const globalSettings = getGlobalSettings();

    optionsButton = new TextButton (T("options"));
    Component::addAndMakeVisible (optionsButton);
    optionsButton->addButtonListener (this);
    optionsButton->setTriggeredOnMouseDown (true);

    JUCE_TRY
    {
        filter = createPluginFilter();

        if (filter != 0)
        {
            deviceManager = new AudioFilterStreamingDeviceManager();
            deviceManager->setFilter (filter);

            XmlElement* savedState = 0;

            if (globalSettings != 0)
                savedState = globalSettings->getXmlValue (T("audioSetup"));

            deviceManager->initialise (filter->getNumInputChannels(),
                                       filter->getNumOutputChannels(),
                                       savedState,
                                       true);

            delete savedState;

            if (globalSettings != 0)
            {
                JUCE_NAMESPACE::MemoryBlock data;

                if (data.fromBase64Encoding (globalSettings->getValue (T("filterState")))
                     && data.getSize() > 0)
                {
                    filter->setStateInformation (data.getData(), data.getSize());
                }
            }

            setContentComponent (filter->createEditorIfNeeded(), true, true);

            const int x = globalSettings->getIntValue (T("windowX"), -100);
            const int y = globalSettings->getIntValue (T("windowY"), -100);

            if (x != -100 && y != -100)
                setBoundsConstrained (x, y, getWidth(), getHeight());
            else
                centreWithSize (getWidth(), getHeight());
        }
    }
    JUCE_CATCH_ALL

    if (deviceManager == 0)
    {
        jassertfalse    // Your filter didn't create correctly! In a standalone app that's not too great.
        JUCEApplication::quit();
    }
}