<commit_before>#include <tiffio.h>
#include <FAST/Data/ImagePyramid.hpp>
#include <FAST/Data/Image.hpp>
#include <FAST/Algorithms/ImagePatch/PatchGenerator.hpp>
#include <QFile>
#include "TIFFImagePyramidExporter.hpp"

namespace fast {

void fast::TIFFImagePyramidExporter::loadAttributes() {
    FileExporter::loadAttributes();
}

void TIFFImagePyramidExporter::execute() {
    if(m_filename.empty())
        throw Exception("Must set filename in TIFFImagePyramidExporter");

    auto imagePyramid = getInputData<ImagePyramid>();

    if(imagePyramid->usesTIFF()) {
        // If image pyramid is using TIFF backend. It is already stored on disk, we just need to copy it..
        if(fileExists(m_filename)) {
            // If destination file already exists, we have to remove the existing file, or copy will not run.
            QFile::remove(m_filename.c_str());
        }
        QFile::copy(imagePyramid->getTIFFPath().c_str(), m_filename.c_str());
        return;
    }
    // If not, we need to do a patch based copy

    const Vector3f spacing = imagePyramid->getSpacing();

    ImageCompression compression = m_compression;
    if(!m_compressionSet || m_compression == ImageCompression::UNSPECIFIED) {
        // Default compression
        if(imagePyramid->getNrOfChannels() == 1) {
            compression = ImageCompression::LZW;
        } else if(imagePyramid->getNrOfChannels() == 3 || imagePyramid->getNrOfChannels() == 4) {
            compression = ImageCompression::JPEG;
        } else {
            throw Exception("Unexpected nr of channels in ImagePyramid: " + std::to_string(imagePyramid->getNrOfChannels()));
        }
    }

    uint photometric = PHOTOMETRIC_RGB;
    uint bitsPerSample = 8;
    uint samplesPerPixel = 3; // RGBA image pyramid is converted to RGB with getPatchAsImage
    if(imagePyramid->getNrOfChannels() == 1) {
        photometric = PHOTOMETRIC_MINISBLACK; // Photometric mask causes crash..
        samplesPerPixel = 1;
    }

    auto tiff = TIFFOpen(m_filename.c_str(), "w8");
    if(tiff == nullptr) {
        throw Exception("Unable to open file " + m_filename + " in TIFFImagePyramidExporter");
    }

    // For each level, we need to 1) write fields, 2) write tiles
    // We have to go from highest res level first
    for(int level = 0; level < imagePyramid->getNrOfLevels(); ++level) {
        reportInfo() << "Writing level " << level << reportEnd();

        // Write base tags
        TIFFSetField(tiff, TIFFTAG_PHOTOMETRIC, photometric);
        TIFFSetField(tiff, TIFFTAG_BITSPERSAMPLE, bitsPerSample);
        TIFFSetField(tiff, TIFFTAG_SAMPLEFORMAT, SAMPLEFORMAT_UINT);
        TIFFSetField(tiff, TIFFTAG_SAMPLESPERPIXEL, (uint16_t)samplesPerPixel);
        TIFFSetField(tiff, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG);
        TIFFSetField(tiff, TIFFTAG_ORIENTATION, ORIENTATION_TOPLEFT);

        if(level > 0) {
            // All levels except highest res level should have this tag?
            TIFFSetField(tiff, TIFFTAG_SUBFILETYPE, FILETYPE_REDUCEDIMAGE);
        }
        switch(compression) {
            case ImageCompression::RAW:
                TIFFSetField(tiff, TIFFTAG_COMPRESSION, COMPRESSION_NONE);
                break;
            case ImageCompression::LZW:
                TIFFSetField(tiff, TIFFTAG_COMPRESSION, COMPRESSION_LZW);
                break;
            case ImageCompression::JPEG:
                TIFFSetField(tiff, TIFFTAG_COMPRESSION, COMPRESSION_JPEG);
                break;
            case ImageCompression::JPEG2000:
                // TODO NOT IMPLEMENTED
                throw NotImplementedException();
                TIFFSetField(tiff, TIFFTAG_COMPRESSION, COMPRESSION_JP2000);
                break;
        }

        TIFFSetField(tiff, TIFFTAG_TILEWIDTH, imagePyramid->getLevelTileWidth(level));
        TIFFSetField(tiff, TIFFTAG_TILELENGTH, imagePyramid->getLevelTileHeight(level));
        TIFFSetField(tiff, TIFFTAG_IMAGEWIDTH, imagePyramid->getLevelWidth(level));
        TIFFSetField(tiff, TIFFTAG_IMAGELENGTH, imagePyramid->getLevelHeight(level));
        if(spacing.x() != 1 && spacing.y() != 1) { // Spacing == 1 means not set.
            TIFFSetField(tiff, TIFFTAG_RESOLUTIONUNIT, RESUNIT_CENTIMETER);
            float scaleX = (float) imagePyramid->getFullWidth() / imagePyramid->getLevelWidth(level);
            float scaleY = (float) imagePyramid->getFullHeight() / imagePyramid->getLevelHeight(level);
            TIFFSetField(tiff, TIFFTAG_XRESOLUTION,
                         1.0f / (spacing.x() / 10) * scaleX); // Convert to cm, and adjust for level
            TIFFSetField(tiff, TIFFTAG_YRESOLUTION,
                         1.0f / (spacing.y() / 10) * scaleY); // Convert to cm, and adjust for level
        }

        auto generator = PatchGenerator::New();
        generator->setInputData(imagePyramid);
        generator->setPatchLevel(level);
        generator->setPatchSize(imagePyramid->getLevelTileWidth(level), imagePyramid->getLevelTileHeight(level));
        auto port = generator->getOutputPort();

        Image::pointer image;
        int counter = 0;
        do {
            generator->update();
            image = port->getNextFrame<Image>();

            // Write tile to tiff level
            if(image->getWidth() != imagePyramid->getLevelTileWidth(level) || image->getHeight() != imagePyramid->getLevelTileHeight(level)) {
                // Have to pad the image, TIFF expects all tiles to be equal
                // TODO improve
                auto paddedImage = Image::create(imagePyramid->getLevelTileWidth(level), imagePyramid->getLevelTileHeight(level), image->getDataType(), image->getNrOfChannels());
                if(imagePyramid->getNrOfChannels() >= 3) {
                    paddedImage->fill(255);
                } else {
                    paddedImage->fill(0);
                }
                auto device = std::dynamic_pointer_cast<OpenCLDevice>(getMainDevice());
                {
                    auto dest = paddedImage->getOpenCLImageAccess(ACCESS_READ_WRITE, device);
                    auto src = image->getOpenCLImageAccess(ACCESS_READ, device);
                    device->getCommandQueue().enqueueCopyImage(*src->get2DImage(), *dest->get2DImage(),
                                                               createOrigoRegion(), createOrigoRegion(),
                                                               createRegion(image->getSize()));
                    device->getCommandQueue().finish();
                }
                if(image->isLastFrame())
                    paddedImage->setLastFrame("PatchGenerator");
                image = paddedImage;
            }
            auto data = image->getImageAccess(ACCESS_READ)->get();
            std::size_t byteSize = getSizeOfDataType(image->getDataType(), image->getNrOfChannels())*image->getNrOfVoxels();
            mRuntimeManager->startRegularTimer("TIFF write");
            TIFFWriteEncodedTile(tiff, counter, data, byteSize);
            mRuntimeManager->stopRegularTimer("TIFF write");
            ++counter;
            mRuntimeManager->printAll();
        } while(!image->isLastFrame());

        TIFFWriteDirectory(tiff);
    }

    TIFFClose(tiff);
}

TIFFImagePyramidExporter::TIFFImagePyramidExporter() : TIFFImagePyramidExporter("") {
}

TIFFImagePyramidExporter::TIFFImagePyramidExporter(std::string filename, ImageCompression compression) : FileExporter(filename) {
    createInputPort<ImagePyramid>(0);
    if(compression != ImageCompression::UNSPECIFIED)
        setCompression(compression);
}

void TIFFImagePyramidExporter::setCompression(ImageCompression compression) {
    m_compressionSet = true;
    m_compression = compression;
}

}<commit_msg>Enabled TIFFImagePyramidExporter to also accept regular images, and not just image pyramids<commit_after>#include <tiffio.h>
#include <FAST/Data/ImagePyramid.hpp>
#include <FAST/Data/Image.hpp>
#include <FAST/Algorithms/ImagePatch/PatchGenerator.hpp>
#include <QFile>
#include "TIFFImagePyramidExporter.hpp"

namespace fast {

void fast::TIFFImagePyramidExporter::loadAttributes() {
    FileExporter::loadAttributes();
}

void TIFFImagePyramidExporter::execute() {
    if(m_filename.empty())
        throw Exception("Must set filename in TIFFImagePyramidExporter");

    auto input = getInputData<DataObject>();
    auto imagePyramid = std::dynamic_pointer_cast<ImagePyramid>(input);
    if(imagePyramid == nullptr) {
        reportInfo() << "Data given to TIFFImagePyramidExporter was an Image, not an ImagePyramid, converting ..." << reportEnd();
        auto image = std::dynamic_pointer_cast<Image>(input);
        imagePyramid = ImagePyramid::create(image->getWidth(), image->getHeight(), image->getNrOfChannels(), 256, 256);
        imagePyramid->setSpacing(image->getSpacing());
        SceneGraph::setParentNode(imagePyramid, image);
        auto access = imagePyramid->getAccess(ACCESS_READ_WRITE);
        for(int y = 0; y < image->getHeight(); y += 256) {
            for(int x = 0; x < image->getWidth(); x += 256) {
                auto width = std::min(image->getWidth() - x - 1, 256);
                auto height = std::min(image->getHeight() - y - 1, 256);
                access->setPatch(0, x, y, image->crop(Vector2i(x, y), Vector2i(width, height)));
            }
        }
    }

    if(imagePyramid->usesTIFF()) {
        // If image pyramid is using TIFF backend. It is already stored on disk, we just need to copy it..
        if(fileExists(m_filename)) {
            // If destination file already exists, we have to remove the existing file, or copy will not run.
            QFile::remove(m_filename.c_str());
        }
        QFile::copy(imagePyramid->getTIFFPath().c_str(), m_filename.c_str());
        return;
    }
    // If not, we need to do a patch based copy

    const Vector3f spacing = imagePyramid->getSpacing();

    ImageCompression compression = m_compression;
    if(!m_compressionSet || m_compression == ImageCompression::UNSPECIFIED) {
        // Default compression
        if(imagePyramid->getNrOfChannels() == 1) {
            compression = ImageCompression::LZW;
        } else if(imagePyramid->getNrOfChannels() == 3 || imagePyramid->getNrOfChannels() == 4) {
            compression = ImageCompression::JPEG;
        } else {
            throw Exception("Unexpected nr of channels in ImagePyramid: " + std::to_string(imagePyramid->getNrOfChannels()));
        }
    }

    uint photometric = PHOTOMETRIC_RGB;
    uint bitsPerSample = 8;
    uint samplesPerPixel = 3; // RGBA image pyramid is converted to RGB with getPatchAsImage
    if(imagePyramid->getNrOfChannels() == 1) {
        photometric = PHOTOMETRIC_MINISBLACK; // Photometric mask causes crash..
        samplesPerPixel = 1;
    }

    auto tiff = TIFFOpen(m_filename.c_str(), "w8");
    if(tiff == nullptr) {
        throw Exception("Unable to open file " + m_filename + " in TIFFImagePyramidExporter");
    }

    // For each level, we need to 1) write fields, 2) write tiles
    // We have to go from highest res level first
    for(int level = 0; level < imagePyramid->getNrOfLevels(); ++level) {
        reportInfo() << "Writing level " << level << reportEnd();

        // Write base tags
        TIFFSetField(tiff, TIFFTAG_PHOTOMETRIC, photometric);
        TIFFSetField(tiff, TIFFTAG_BITSPERSAMPLE, bitsPerSample);
        TIFFSetField(tiff, TIFFTAG_SAMPLEFORMAT, SAMPLEFORMAT_UINT);
        TIFFSetField(tiff, TIFFTAG_SAMPLESPERPIXEL, (uint16_t)samplesPerPixel);
        TIFFSetField(tiff, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG);
        TIFFSetField(tiff, TIFFTAG_ORIENTATION, ORIENTATION_TOPLEFT);

        if(level > 0) {
            // All levels except highest res level should have this tag?
            TIFFSetField(tiff, TIFFTAG_SUBFILETYPE, FILETYPE_REDUCEDIMAGE);
        }
        switch(compression) {
            case ImageCompression::RAW:
                TIFFSetField(tiff, TIFFTAG_COMPRESSION, COMPRESSION_NONE);
                break;
            case ImageCompression::LZW:
                TIFFSetField(tiff, TIFFTAG_COMPRESSION, COMPRESSION_LZW);
                break;
            case ImageCompression::JPEG:
                TIFFSetField(tiff, TIFFTAG_COMPRESSION, COMPRESSION_JPEG);
                break;
            case ImageCompression::JPEG2000:
                // TODO NOT IMPLEMENTED
                throw NotImplementedException();
                TIFFSetField(tiff, TIFFTAG_COMPRESSION, COMPRESSION_JP2000);
                break;
        }

        TIFFSetField(tiff, TIFFTAG_TILEWIDTH, imagePyramid->getLevelTileWidth(level));
        TIFFSetField(tiff, TIFFTAG_TILELENGTH, imagePyramid->getLevelTileHeight(level));
        TIFFSetField(tiff, TIFFTAG_IMAGEWIDTH, imagePyramid->getLevelWidth(level));
        TIFFSetField(tiff, TIFFTAG_IMAGELENGTH, imagePyramid->getLevelHeight(level));
        if(spacing.x() != 1 && spacing.y() != 1) { // Spacing == 1 means not set.
            TIFFSetField(tiff, TIFFTAG_RESOLUTIONUNIT, RESUNIT_CENTIMETER);
            float scaleX = (float) imagePyramid->getFullWidth() / imagePyramid->getLevelWidth(level);
            float scaleY = (float) imagePyramid->getFullHeight() / imagePyramid->getLevelHeight(level);
            TIFFSetField(tiff, TIFFTAG_XRESOLUTION,
                         1.0f / (spacing.x() / 10) * scaleX); // Convert to cm, and adjust for level
            TIFFSetField(tiff, TIFFTAG_YRESOLUTION,
                         1.0f / (spacing.y() / 10) * scaleY); // Convert to cm, and adjust for level
        }

        auto generator = PatchGenerator::New();
        generator->setInputData(imagePyramid);
        generator->setPatchLevel(level);
        generator->setPatchSize(imagePyramid->getLevelTileWidth(level), imagePyramid->getLevelTileHeight(level));
        auto port = generator->getOutputPort();

        Image::pointer image;
        int counter = 0;
        do {
            generator->update();
            image = port->getNextFrame<Image>();

            // Write tile to tiff level
            if(image->getWidth() != imagePyramid->getLevelTileWidth(level) || image->getHeight() != imagePyramid->getLevelTileHeight(level)) {
                // Have to pad the image, TIFF expects all tiles to be equal
                // TODO improve
                auto paddedImage = Image::create(imagePyramid->getLevelTileWidth(level), imagePyramid->getLevelTileHeight(level), image->getDataType(), image->getNrOfChannels());
                if(imagePyramid->getNrOfChannels() >= 3) {
                    paddedImage->fill(255);
                } else {
                    paddedImage->fill(0);
                }
                auto device = std::dynamic_pointer_cast<OpenCLDevice>(getMainDevice());
                {
                    auto dest = paddedImage->getOpenCLImageAccess(ACCESS_READ_WRITE, device);
                    auto src = image->getOpenCLImageAccess(ACCESS_READ, device);
                    device->getCommandQueue().enqueueCopyImage(*src->get2DImage(), *dest->get2DImage(),
                                                               createOrigoRegion(), createOrigoRegion(),
                                                               createRegion(image->getSize()));
                    device->getCommandQueue().finish();
                }
                if(image->isLastFrame())
                    paddedImage->setLastFrame("PatchGenerator");
                image = paddedImage;
            }
            auto data = image->getImageAccess(ACCESS_READ)->get();
            std::size_t byteSize = getSizeOfDataType(image->getDataType(), image->getNrOfChannels())*image->getNrOfVoxels();
            mRuntimeManager->startRegularTimer("TIFF write");
            TIFFWriteEncodedTile(tiff, counter, data, byteSize);
            mRuntimeManager->stopRegularTimer("TIFF write");
            ++counter;
            mRuntimeManager->printAll();
        } while(!image->isLastFrame());

        TIFFWriteDirectory(tiff);
    }

    TIFFClose(tiff);
}

TIFFImagePyramidExporter::TIFFImagePyramidExporter() : TIFFImagePyramidExporter("") {
}

TIFFImagePyramidExporter::TIFFImagePyramidExporter(std::string filename, ImageCompression compression) : FileExporter(filename) {
    createInputPort<ImagePyramid>(0);
    if(compression != ImageCompression::UNSPECIFIED)
        setCompression(compression);
}

void TIFFImagePyramidExporter::setCompression(ImageCompression compression) {
    m_compressionSet = true;
    m_compression = compression;
}

}<|endoftext|>


<commit_before>/*
    This file is part of libkcal.

    Copyright (c) 2004 Cornelius Schumacher <schumacher@kde.org>

    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Library General Public
    License as published by the Free Software Foundation; either
    version 2 of the License, or (at your option) any later version.

    This library 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
    Library General Public License for more details.

    You should have received a copy of the GNU Library General Public License
    along with this library; see the file COPYING.LIB.  If not, write to
    the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
    Boston, MA 02111-1307, USA.
*/

#include <qbuttongroup.h>
#include <qlayout.h>
#include <qradiobutton.h>
#include <qspinbox.h>
#include <qhbox.h>
#include <qlabel.h>

#include <klocale.h>
#include <kdebug.h>

#include "resourcecached.h"

#include "resourcecachedconfig.h"

using namespace KCal;

ResourceCachedReloadConfig::ResourceCachedReloadConfig( QWidget *parent,
                                                        const char *name )
  : QWidget( parent, name )
{
  QBoxLayout *topLayout = new QVBoxLayout( this );

  mGroup = new QButtonGroup( 1, Horizontal, i18n("Automatic Reload"), this );
  topLayout->addWidget( mGroup );
  new QRadioButton( i18n("Never"), mGroup );
  new QRadioButton( i18n("On startup"), mGroup );

  QRadioButton *intervalRadio = new QRadioButton( i18n("Regular Interval"),
                                                  mGroup );
  connect( intervalRadio, SIGNAL( stateChanged( int ) ),
           SLOT( slotIntervalStateChanged( int ) ) );
  QHBox *intervalBox = new QHBox( mGroup );
  new QLabel( i18n("Interval in minutes"), intervalBox );
  mIntervalSpin = new QSpinBox( intervalBox );
  mIntervalSpin->setEnabled( false );
}

void ResourceCachedReloadConfig::loadSettings( ResourceCached *resource )
{
  mGroup->setButton( resource->reloadPolicy() );
}

void ResourceCachedReloadConfig::saveSettings( ResourceCached *resource )
{
  resource->setReloadPolicy( mGroup->selectedId() );
}

void ResourceCachedReloadConfig::slotIntervalStateChanged( int state )
{
  if ( state == QButton::On ) mIntervalSpin->setEnabled( true );
  else mIntervalSpin->setEnabled( false );
}

ResourceCachedSaveConfig::ResourceCachedSaveConfig( QWidget *parent,
                                                        const char *name )
  : QWidget( parent, name )
{
  QBoxLayout *topLayout = new QVBoxLayout( this );

  mGroup = new QButtonGroup( 1, Horizontal, i18n("Automatic Save"), this );
  topLayout->addWidget( mGroup );
  new QRadioButton( i18n("Never"), mGroup );
  new QRadioButton( i18n("On exit"), mGroup );

  QRadioButton *intervalRadio = new QRadioButton( i18n("Regular Interval"),
                                                  mGroup );
  connect( intervalRadio, SIGNAL( stateChanged( int ) ),
           SLOT( slotIntervalStateChanged( int ) ) );
  QHBox *intervalBox = new QHBox( mGroup );
  new QLabel( i18n("Interval in minutes"), intervalBox );
  mIntervalSpin = new QSpinBox( intervalBox );
  mIntervalSpin->setEnabled( false );

  new QRadioButton( i18n("Delayed after changes"), mGroup );
  new QRadioButton( i18n("On every change"), mGroup );
}

void ResourceCachedSaveConfig::loadSettings( ResourceCached *resource )
{
  mGroup->setButton( resource->savePolicy() );
}

void ResourceCachedSaveConfig::saveSettings( ResourceCached *resource )
{
  resource->setSavePolicy( mGroup->selectedId() );
}

void ResourceCachedSaveConfig::slotIntervalStateChanged( int state )
{
  if ( state == QButton::On ) mIntervalSpin->setEnabled( true );
  else mIntervalSpin->setEnabled( false );
}

#include "resourcecachedconfig.moc"
<commit_msg>Load and save interval settings.<commit_after>/*
    This file is part of libkcal.

    Copyright (c) 2004 Cornelius Schumacher <schumacher@kde.org>

    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Library General Public
    License as published by the Free Software Foundation; either
    version 2 of the License, or (at your option) any later version.

    This library 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
    Library General Public License for more details.

    You should have received a copy of the GNU Library General Public License
    along with this library; see the file COPYING.LIB.  If not, write to
    the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
    Boston, MA 02111-1307, USA.
*/

#include <qbuttongroup.h>
#include <qlayout.h>
#include <qradiobutton.h>
#include <qspinbox.h>
#include <qhbox.h>
#include <qlabel.h>

#include <klocale.h>
#include <kdebug.h>

#include "resourcecached.h"

#include "resourcecachedconfig.h"

using namespace KCal;

ResourceCachedReloadConfig::ResourceCachedReloadConfig( QWidget *parent,
                                                        const char *name )
  : QWidget( parent, name )
{
  QBoxLayout *topLayout = new QVBoxLayout( this );

  mGroup = new QButtonGroup( 1, Horizontal, i18n("Automatic Reload"), this );
  topLayout->addWidget( mGroup );
  new QRadioButton( i18n("Never"), mGroup );
  new QRadioButton( i18n("On startup"), mGroup );

  QRadioButton *intervalRadio = new QRadioButton( i18n("Regular Interval"),
                                                  mGroup );
  connect( intervalRadio, SIGNAL( stateChanged( int ) ),
           SLOT( slotIntervalStateChanged( int ) ) );
  QHBox *intervalBox = new QHBox( mGroup );
  new QLabel( i18n("Interval in minutes"), intervalBox );
  mIntervalSpin = new QSpinBox( intervalBox );
  mIntervalSpin->setEnabled( false );
}

void ResourceCachedReloadConfig::loadSettings( ResourceCached *resource )
{
  mGroup->setButton( resource->reloadPolicy() );
  mIntervalSpin->setValue( resource->reloadInterval() );
}

void ResourceCachedReloadConfig::saveSettings( ResourceCached *resource )
{
  resource->setReloadPolicy( mGroup->selectedId() );
  resource->setReloadInterval( mIntervalSpin->value() );
}

void ResourceCachedReloadConfig::slotIntervalStateChanged( int state )
{
  if ( state == QButton::On ) mIntervalSpin->setEnabled( true );
  else mIntervalSpin->setEnabled( false );
}

ResourceCachedSaveConfig::ResourceCachedSaveConfig( QWidget *parent,
                                                        const char *name )
  : QWidget( parent, name )
{
  QBoxLayout *topLayout = new QVBoxLayout( this );

  mGroup = new QButtonGroup( 1, Horizontal, i18n("Automatic Save"), this );
  topLayout->addWidget( mGroup );
  new QRadioButton( i18n("Never"), mGroup );
  new QRadioButton( i18n("On exit"), mGroup );

  QRadioButton *intervalRadio = new QRadioButton( i18n("Regular Interval"),
                                                  mGroup );
  connect( intervalRadio, SIGNAL( stateChanged( int ) ),
           SLOT( slotIntervalStateChanged( int ) ) );
  QHBox *intervalBox = new QHBox( mGroup );
  new QLabel( i18n("Interval in minutes"), intervalBox );
  mIntervalSpin = new QSpinBox( intervalBox );
  mIntervalSpin->setEnabled( false );

  new QRadioButton( i18n("Delayed after changes"), mGroup );
  new QRadioButton( i18n("On every change"), mGroup );
}

void ResourceCachedSaveConfig::loadSettings( ResourceCached *resource )
{
  mGroup->setButton( resource->savePolicy() );
  mIntervalSpin->setValue( resource->saveInterval() );
}

void ResourceCachedSaveConfig::saveSettings( ResourceCached *resource )
{
  resource->setSavePolicy( mGroup->selectedId() );
  resource->setSaveInterval( mIntervalSpin->value() );
}

void ResourceCachedSaveConfig::slotIntervalStateChanged( int state )
{
  if ( state == QButton::On ) mIntervalSpin->setEnabled( true );
  else mIntervalSpin->setEnabled( false );
}

#include "resourcecachedconfig.moc"
<|endoftext|>


<commit_before>/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
 * This file is part of the LibreOffice project.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 */
#include "BluetoothServer.hxx"
#include <stdio.h>

#ifdef LINUX
#include <gio/gio.h>
#include <sys/unistd.h>
#include <sys/socket.h>
#endif
#include <tools/debug.hxx>
#include <tools/stream.hxx>

#ifdef LINUX
#include "bluetooth/bluetooth.h"
#include "bluetooth/rfcomm.h"
#endif

#include "Communicator.hxx"

using namespace sd;

BluetoothServer::BluetoothServer( std::vector<Communicator*>* pCommunicators ):
    Thread( "BluetoothServer" ),
    mpCommunicators( pCommunicators )
{
}

BluetoothServer::~BluetoothServer()
{
}

struct oslSocketImpl {
    int                 m_Socket;
    int                 m_nLastError;
    void*    m_CloseCallback;
    void*               m_CallbackArg;
    oslInterlockedCount m_nRefCount;
#if defined(LINUX)
    sal_Bool            m_bIsAccepting;
    sal_Bool            m_bIsInShutdown;
#endif
};

void BluetoothServer::execute()
{
#ifdef LINUX
    g_type_init();
    GError* aError = NULL;
    GDBusConnection* aConnection = g_bus_get_sync( G_BUS_TYPE_SYSTEM, NULL, &aError );
    if ( aError )
    {
        g_error_free( aError );
    }

    GVariant *aAdapter = g_dbus_connection_call_sync( aConnection,
                                "org.bluez", "/", "org.bluez.Manager",
                                "DefaultAdapter", NULL,
                                G_VARIANT_TYPE_TUPLE,
                                G_DBUS_CALL_FLAGS_NONE, -1, NULL, &aError);
    GVariant *aAdapterName = g_variant_get_child_value( aAdapter, 0 );
    if ( aError )
    {
        g_error_free( aError );
    }
//     fprintf( stderr, (const char*) g_variant_get_string( aAdapterName, NULL ) );

//     GDBusObjectManager* aManager = g_dbus_object_manager_client_new_sync( aConnection,
//                     G_DBUS_OBJECT_MANAGER_CLIENT_FLAGS_NONE, "org.bluez.Manager", "/org/bluez",
//                     NULL, NULL, NULL, NULL, &aError );
//     if ( aError )
//     {
//         fprintf( stderr, aError->message );
//         g_error_free( aError );
//     }

    GVariant *aRecordHandle = g_dbus_connection_call_sync( aConnection,
                                "org.bluez", g_variant_get_string( aAdapterName, NULL ), "org.bluez.Service",
                                "AddRecord",
                                 g_variant_new("(s)",
                                            "<?xml version='1.0' encoding= 'UTF-8' ?><record><attribute id='0x0001'><sequence><uuid value='0x1101' /></sequence></attribute><attribute id='0x0004'><sequence><sequence><uuid value='0x0100' /></sequence><sequence><uuid value='0x0003' /><uint8 value='0x05' /></sequence></sequence></attribute><attribute id='0x0005'><sequence><uuid value='0x1002' /></sequence></attribute><attribute id='0x0006'><sequence><uint16 value='0x656e' /><uint16 value='0x006a' /><uint16 value='0x0100' /></sequence></attribute><attribute id='0x0009'><sequence><sequence><uuid value='0x1101' /><uint16 value='0x0100' /></sequence></sequence></attribute><attribute id='0x0100'><text value='Serial Port' /></attribute><attribute id='0x0101'><text value='COM Port' /></attribute></record>"),
                                G_VARIANT_TYPE_TUPLE,
                                G_DBUS_CALL_FLAGS_NONE, -1, NULL, &aError);
    if ( aError )
    {
        g_error_free( aError );
    }
    (void) aRecordHandle;
    // Remove handle again at some point
//     g_variant_unref( aRet );
//     fprintf( stderr, "Manager gotten\n" );
//
//     // Name for default adapter
//     GVariant *aAdapter = g_dbus_connection_call_sync( aConnection,
//                                 "org.bluez", "/", "org.bluez.Manager",
//                                 "DefaultAdapter", NULL,
//                                 G_VARIANT_TYPE_TUPLE,
//                                 G_DBUS_CALL_FLAGS_NONE, -1, NULL, &aError);
//     GVariant *aAdapterName = g_variant_get_child_value( aAdapter, 0 );
//     if ( aError )
//     {
//         fprintf( stderr, aError->message );
//         g_error_free( aError );
//     }
//     fprintf( stderr, (const char*) g_variant_get_string( aAdapterName, NULL ) );

//     g_type_init();
//     GError* aError = NULL;
//     GDBusConnection* aConnection = g_bus_get_sync( G_BUS_TYPE_SYSTEM, NULL, &aError );
//     fprintf( stderr, "Connection gotten\n" );
//     if ( aError )
//     {
//         fprintf( stderr, aError->message );
//         g_error_free( aError );
//     }
// //     GDBusObjectManager* aManager = g_dbus_object_manager_client_new_sync( aConnection,
// //                     G_DBUS_OBJECT_MANAGER_CLIENT_FLAGS_NONE, "org.bluez.Manager", "/org/bluez",
// //                     NULL, NULL, NULL, NULL, &aError );
// //     if ( aError )
// //     {
// //         fprintf( stderr, aError->message );
// //         g_error_free( aError );
// //     }
//     fprintf( stderr, "Manager gotten\n" );
//
//     // Name for default adapter
//     GVariant *aAdapter = g_dbus_connection_call_sync( aConnection,
//                                 "org.bluez", "/", "org.bluez.Manager",
//                                 "DefaultAdapter", NULL,
//                                 G_VARIANT_TYPE_TUPLE,
//                                 G_DBUS_CALL_FLAGS_NONE, -1, NULL, &aError);
//     GVariant *aAdapterName = g_variant_get_child_value( aAdapter, 0 );
//     if ( aError )
//     {
//         fprintf( stderr, aError->message );
//         g_error_free( aError );
//     }
//     fprintf( stderr, (const char*) g_variant_get_string( aAdapterName, NULL ) );

    // ---------------- DEVICE ADDRESS
    int aSocket;
    if ( (aSocket = socket( AF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM )) < 0 )
    {
        // Error
        return;
    }

    sockaddr_rc aAddr;
    aAddr.rc_family = AF_BLUETOOTH;
    aAddr.rc_bdaddr = {{0, 0, 0, 0, 0, 0}}; // BDADDR_ANY is broken
    aAddr.rc_channel = 5;

    if ( bind( aSocket, (sockaddr*) &aAddr, sizeof(aAddr)) < 0 ) {
        close( aSocket );
        return;
    }

    if ( listen( aSocket, 1 ) < 0 )
    {
        close( aSocket );
        return;
    }

    sockaddr_rc aRemoteAddr;
    socklen_t  aRemoteAddrLen = sizeof(aRemoteAddr);
    int bSocket;
    if ( (bSocket = accept(aSocket, (sockaddr*) &aRemoteAddr, &aRemoteAddrLen)) < 0 )
    {
        close( aSocket );
        return;
    } else {
//         fprintf( stderr, "Accepted Bluetooth\n" );

        Communicator* pCommunicator = new Communicator( new BufferedStreamSocket( bSocket) );
        mpCommunicators->push_back( pCommunicator );
        pCommunicator->launch();

    }

#endif

#ifdef WIN32

#endif

#ifdef MACOSX

#endif
}

BluetoothServer *sd::BluetoothServer::spServer = NULL;

void BluetoothServer::setup( std::vector<Communicator*>* pCommunicators )
{
    if (spServer)
        return;

    spServer = new BluetoothServer( pCommunicators );
    spServer->launch();
}

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */<commit_msg>Remove extended initializer list -- use memset for BDADDR_ANY.<commit_after>/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
 * This file is part of the LibreOffice project.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 */
#include "BluetoothServer.hxx"
#include <stdio.h>

#ifdef LINUX
#include <gio/gio.h>
#include <sys/unistd.h>
#include <sys/socket.h>
#endif
#include <tools/debug.hxx>
#include <tools/stream.hxx>

#ifdef LINUX
#include "bluetooth/bluetooth.h"
#include "bluetooth/rfcomm.h"
#endif

#include "Communicator.hxx"

using namespace sd;

BluetoothServer::BluetoothServer( std::vector<Communicator*>* pCommunicators ):
    Thread( "BluetoothServer" ),
    mpCommunicators( pCommunicators )
{
}

BluetoothServer::~BluetoothServer()
{
}

struct oslSocketImpl {
    int                 m_Socket;
    int                 m_nLastError;
    void*    m_CloseCallback;
    void*               m_CallbackArg;
    oslInterlockedCount m_nRefCount;
#if defined(LINUX)
    sal_Bool            m_bIsAccepting;
    sal_Bool            m_bIsInShutdown;
#endif
};

void BluetoothServer::execute()
{
#ifdef LINUX
    g_type_init();
    GError* aError = NULL;
    GDBusConnection* aConnection = g_bus_get_sync( G_BUS_TYPE_SYSTEM, NULL, &aError );
    if ( aError )
    {
        g_error_free( aError );
    }

    GVariant *aAdapter = g_dbus_connection_call_sync( aConnection,
                                "org.bluez", "/", "org.bluez.Manager",
                                "DefaultAdapter", NULL,
                                G_VARIANT_TYPE_TUPLE,
                                G_DBUS_CALL_FLAGS_NONE, -1, NULL, &aError);
    GVariant *aAdapterName = g_variant_get_child_value( aAdapter, 0 );
    if ( aError )
    {
        g_error_free( aError );
    }
//     fprintf( stderr, (const char*) g_variant_get_string( aAdapterName, NULL ) );

//     GDBusObjectManager* aManager = g_dbus_object_manager_client_new_sync( aConnection,
//                     G_DBUS_OBJECT_MANAGER_CLIENT_FLAGS_NONE, "org.bluez.Manager", "/org/bluez",
//                     NULL, NULL, NULL, NULL, &aError );
//     if ( aError )
//     {
//         fprintf( stderr, aError->message );
//         g_error_free( aError );
//     }

    GVariant *aRecordHandle = g_dbus_connection_call_sync( aConnection,
                                "org.bluez", g_variant_get_string( aAdapterName, NULL ), "org.bluez.Service",
                                "AddRecord",
                                 g_variant_new("(s)",
                                            "<?xml version='1.0' encoding= 'UTF-8' ?><record><attribute id='0x0001'><sequence><uuid value='0x1101' /></sequence></attribute><attribute id='0x0004'><sequence><sequence><uuid value='0x0100' /></sequence><sequence><uuid value='0x0003' /><uint8 value='0x05' /></sequence></sequence></attribute><attribute id='0x0005'><sequence><uuid value='0x1002' /></sequence></attribute><attribute id='0x0006'><sequence><uint16 value='0x656e' /><uint16 value='0x006a' /><uint16 value='0x0100' /></sequence></attribute><attribute id='0x0009'><sequence><sequence><uuid value='0x1101' /><uint16 value='0x0100' /></sequence></sequence></attribute><attribute id='0x0100'><text value='Serial Port' /></attribute><attribute id='0x0101'><text value='COM Port' /></attribute></record>"),
                                G_VARIANT_TYPE_TUPLE,
                                G_DBUS_CALL_FLAGS_NONE, -1, NULL, &aError);
    if ( aError )
    {
        g_error_free( aError );
    }
    (void) aRecordHandle;
    // Remove handle again at some point
//     g_variant_unref( aRet );
//     fprintf( stderr, "Manager gotten\n" );
//
//     // Name for default adapter
//     GVariant *aAdapter = g_dbus_connection_call_sync( aConnection,
//                                 "org.bluez", "/", "org.bluez.Manager",
//                                 "DefaultAdapter", NULL,
//                                 G_VARIANT_TYPE_TUPLE,
//                                 G_DBUS_CALL_FLAGS_NONE, -1, NULL, &aError);
//     GVariant *aAdapterName = g_variant_get_child_value( aAdapter, 0 );
//     if ( aError )
//     {
//         fprintf( stderr, aError->message );
//         g_error_free( aError );
//     }
//     fprintf( stderr, (const char*) g_variant_get_string( aAdapterName, NULL ) );

//     g_type_init();
//     GError* aError = NULL;
//     GDBusConnection* aConnection = g_bus_get_sync( G_BUS_TYPE_SYSTEM, NULL, &aError );
//     fprintf( stderr, "Connection gotten\n" );
//     if ( aError )
//     {
//         fprintf( stderr, aError->message );
//         g_error_free( aError );
//     }
// //     GDBusObjectManager* aManager = g_dbus_object_manager_client_new_sync( aConnection,
// //                     G_DBUS_OBJECT_MANAGER_CLIENT_FLAGS_NONE, "org.bluez.Manager", "/org/bluez",
// //                     NULL, NULL, NULL, NULL, &aError );
// //     if ( aError )
// //     {
// //         fprintf( stderr, aError->message );
// //         g_error_free( aError );
// //     }
//     fprintf( stderr, "Manager gotten\n" );
//
//     // Name for default adapter
//     GVariant *aAdapter = g_dbus_connection_call_sync( aConnection,
//                                 "org.bluez", "/", "org.bluez.Manager",
//                                 "DefaultAdapter", NULL,
//                                 G_VARIANT_TYPE_TUPLE,
//                                 G_DBUS_CALL_FLAGS_NONE, -1, NULL, &aError);
//     GVariant *aAdapterName = g_variant_get_child_value( aAdapter, 0 );
//     if ( aError )
//     {
//         fprintf( stderr, aError->message );
//         g_error_free( aError );
//     }
//     fprintf( stderr, (const char*) g_variant_get_string( aAdapterName, NULL ) );

    // ---------------- DEVICE ADDRESS
    int aSocket;
    if ( (aSocket = socket( AF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM )) < 0 )
    {
        // Error
        return;
    }

    sockaddr_rc aAddr;
    aAddr.rc_family = AF_BLUETOOTH;
//     aAddr.rc_bdaddr = {{0, 0, 0, 0, 0, 0}}; // BDADDR_ANY is broken
    memset( &aAddr.rc_bdaddr, 0, sizeof( aAddr.rc_bdaddr ) );
    aAddr.rc_channel = 5;

    if ( bind( aSocket, (sockaddr*) &aAddr, sizeof(aAddr)) < 0 ) {
        close( aSocket );
        return;
    }

    if ( listen( aSocket, 1 ) < 0 )
    {
        close( aSocket );
        return;
    }

    sockaddr_rc aRemoteAddr;
    socklen_t  aRemoteAddrLen = sizeof(aRemoteAddr);
    int bSocket;
    if ( (bSocket = accept(aSocket, (sockaddr*) &aRemoteAddr, &aRemoteAddrLen)) < 0 )
    {
        close( aSocket );
        return;
    } else {
//         fprintf( stderr, "Accepted Bluetooth\n" );

        Communicator* pCommunicator = new Communicator( new BufferedStreamSocket( bSocket) );
        mpCommunicators->push_back( pCommunicator );
        pCommunicator->launch();

    }

#endif

#ifdef WIN32

#endif

#ifdef MACOSX

#endif
}

BluetoothServer *sd::BluetoothServer::spServer = NULL;

void BluetoothServer::setup( std::vector<Communicator*>* pCommunicators )
{
    if (spServer)
        return;

    spServer = new BluetoothServer( pCommunicators );
    spServer->launch();
}

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */<|endoftext|>


<commit_before>/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2000, 2010 Oracle and/or its affiliates.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org 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 Lesser General Public License version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/

#ifndef _STGDIR_HXX
#define _STGDIR_HXX

#include "stgavl.hxx"
#include "stgelem.hxx"
#include "stgstrms.hxx"

class StgIo;
class StgEntry;
class StgDirEntry;
class StgDirStrm;

class BaseStorageStream;
class StgDirEntry : public StgAvlNode
{
    friend class StgIterator;
    friend class StgDirStrm;
    StgEntry     aSave;                     // original dir entry
    StgDirEntry*  pUp;                      // parent directory
    StgDirEntry*  pDown;                    // child directory for storages
    StgDirEntry** ppRoot;                   // root of TOC tree
    StgStrm*     pStgStrm;                  // storage stream
    StgTmpStrm*  pTmpStrm;                  // temporary stream
    StgTmpStrm*  pCurStrm;                  // temp stream after commit
    sal_Int32        nEntry;                    // entry # in TOC stream (temp)
    sal_Int32        nPos;                      // current position
    sal_Bool         bDirty;                    // dirty directory entry
    sal_Bool         bCreated;                  // newly created entry
    sal_Bool         bRemoved;                  // removed per Invalidate()
    sal_Bool         bRenamed;                  // renamed
    void         InitMembers();             // ctor helper
    virtual short Compare( const StgAvlNode* ) const;
    sal_Bool         StoreStream( StgIo& );     // store the stream
    sal_Bool         StoreStreams( StgIo& );    // store all streams
    void         RevertAll();               // revert the whole tree
    sal_Bool         Strm2Tmp();                // copy stgstream to temp file
    sal_Bool         Tmp2Strm();                // copy temp file to stgstream
public:
    StgEntry     aEntry;                    // entry data
    sal_Int32        nRefCnt;                   // reference count
    StreamMode   nMode;                     // open mode
    sal_Bool         bTemp;                     // sal_True: delete on dir flush
    sal_Bool         bDirect;                   // sal_True: direct mode
    sal_Bool         bZombie;                   // sal_True: Removed From StgIo
    sal_Bool         bInvalid;                  // sal_True: invalid entry
    StgDirEntry( const void*, sal_Bool * pbOk );
    StgDirEntry( const StgEntry& );
    ~StgDirEntry();

    void Invalidate( sal_Bool=sal_False );          // invalidate all open entries
    void Enum( sal_Int32& );                    // enumerate entries for iteration
    void DelTemp( sal_Bool );                   // delete temporary entries
    sal_Bool Store( StgDirStrm& );              // save entry into dir strm
    sal_Bool IsContained( StgDirEntry* );       // check if subentry

    void SetDirty()  { bDirty = sal_True;     }
    sal_Bool IsDirty();
    void ClearDirty();

    sal_Bool Commit();
    sal_Bool Revert();

    void  OpenStream( StgIo&, sal_Bool=sal_False );     // set up an approbiate stream
    void  Close();
    sal_Int32 GetSize();
    sal_Bool  SetSize( sal_Int32 );
    sal_Int32 Seek( sal_Int32 );
    sal_Int32 Tell() { return nPos; }
    sal_Int32 Read( void*, sal_Int32 );
    sal_Int32 Write( const void*, sal_Int32 );
    void  Copy( BaseStorageStream& );
};

class StgDirStrm : public StgDataStrm
{
    friend class StgIterator;
    StgDirEntry* pRoot;                         // root of dir tree
    short        nEntries;                      // entries per page
    void         SetupEntry( sal_Int32, StgDirEntry* );
public:
    StgDirStrm( StgIo& );
    ~StgDirStrm();
    virtual sal_Bool SetSize( sal_Int32 );              // change the size
    sal_Bool         Store();
    void*        GetEntry( sal_Int32 n, sal_Bool=sal_False );// get an entry
    StgDirEntry* GetRoot() { return pRoot; }
    StgDirEntry* Find( StgDirEntry&, const String& );
    StgDirEntry* Create( StgDirEntry&, const String&, StgEntryType );
    sal_Bool         Remove( StgDirEntry&, const String& );
    sal_Bool         Rename( StgDirEntry&, const String&, const String& );
    sal_Bool         Move( StgDirEntry&, StgDirEntry&, const String& );
};

class StgIterator : public StgAvlIterator
{
public:
    StgIterator( StgDirEntry& rStg ) : StgAvlIterator( rStg.pDown ) {}
    StgDirEntry* First() { return (StgDirEntry*) StgAvlIterator::First(); }
    StgDirEntry* Next()  { return (StgDirEntry*) StgAvlIterator::Next();  }
    StgDirEntry* Last()  { return (StgDirEntry*) StgAvlIterator::Last();  }
    StgDirEntry* Prev()  { return (StgDirEntry*) StgAvlIterator::Prev();  }
};

#endif

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
<commit_msg>unused inline<commit_after>/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2000, 2010 Oracle and/or its affiliates.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org 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 Lesser General Public License version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/

#ifndef _STGDIR_HXX
#define _STGDIR_HXX

#include "stgavl.hxx"
#include "stgelem.hxx"
#include "stgstrms.hxx"

class StgIo;
class StgEntry;
class StgDirEntry;
class StgDirStrm;

class BaseStorageStream;
class StgDirEntry : public StgAvlNode
{
    friend class StgIterator;
    friend class StgDirStrm;
    StgEntry     aSave;                     // original dir entry
    StgDirEntry*  pUp;                      // parent directory
    StgDirEntry*  pDown;                    // child directory for storages
    StgDirEntry** ppRoot;                   // root of TOC tree
    StgStrm*     pStgStrm;                  // storage stream
    StgTmpStrm*  pTmpStrm;                  // temporary stream
    StgTmpStrm*  pCurStrm;                  // temp stream after commit
    sal_Int32        nEntry;                    // entry # in TOC stream (temp)
    sal_Int32        nPos;                      // current position
    sal_Bool         bDirty;                    // dirty directory entry
    sal_Bool         bCreated;                  // newly created entry
    sal_Bool         bRemoved;                  // removed per Invalidate()
    sal_Bool         bRenamed;                  // renamed
    void         InitMembers();             // ctor helper
    virtual short Compare( const StgAvlNode* ) const;
    sal_Bool         StoreStream( StgIo& );     // store the stream
    sal_Bool         StoreStreams( StgIo& );    // store all streams
    void         RevertAll();               // revert the whole tree
    sal_Bool         Strm2Tmp();                // copy stgstream to temp file
    sal_Bool         Tmp2Strm();                // copy temp file to stgstream
public:
    StgEntry     aEntry;                    // entry data
    sal_Int32        nRefCnt;                   // reference count
    StreamMode   nMode;                     // open mode
    sal_Bool         bTemp;                     // sal_True: delete on dir flush
    sal_Bool         bDirect;                   // sal_True: direct mode
    sal_Bool         bZombie;                   // sal_True: Removed From StgIo
    sal_Bool         bInvalid;                  // sal_True: invalid entry
    StgDirEntry( const void*, sal_Bool * pbOk );
    StgDirEntry( const StgEntry& );
    ~StgDirEntry();

    void Invalidate( sal_Bool=sal_False );          // invalidate all open entries
    void Enum( sal_Int32& );                    // enumerate entries for iteration
    void DelTemp( sal_Bool );                   // delete temporary entries
    sal_Bool Store( StgDirStrm& );              // save entry into dir strm
    sal_Bool IsContained( StgDirEntry* );       // check if subentry

    void SetDirty()  { bDirty = sal_True;     }
    sal_Bool IsDirty();
    void ClearDirty();

    sal_Bool Commit();
    sal_Bool Revert();

    void  OpenStream( StgIo&, sal_Bool=sal_False );     // set up an approbiate stream
    void  Close();
    sal_Int32 GetSize();
    sal_Bool  SetSize( sal_Int32 );
    sal_Int32 Seek( sal_Int32 );
    sal_Int32 Tell() { return nPos; }
    sal_Int32 Read( void*, sal_Int32 );
    sal_Int32 Write( const void*, sal_Int32 );
    void  Copy( BaseStorageStream& );
};

class StgDirStrm : public StgDataStrm
{
    friend class StgIterator;
    StgDirEntry* pRoot;                         // root of dir tree
    short        nEntries;                      // entries per page
    void         SetupEntry( sal_Int32, StgDirEntry* );
public:
    StgDirStrm( StgIo& );
    ~StgDirStrm();
    virtual sal_Bool SetSize( sal_Int32 );              // change the size
    sal_Bool         Store();
    void*        GetEntry( sal_Int32 n, sal_Bool=sal_False );// get an entry
    StgDirEntry* GetRoot() { return pRoot; }
    StgDirEntry* Find( StgDirEntry&, const String& );
    StgDirEntry* Create( StgDirEntry&, const String&, StgEntryType );
    sal_Bool         Remove( StgDirEntry&, const String& );
    sal_Bool         Rename( StgDirEntry&, const String&, const String& );
    sal_Bool         Move( StgDirEntry&, StgDirEntry&, const String& );
};

class StgIterator : public StgAvlIterator
{
public:
    StgIterator( StgDirEntry& rStg ) : StgAvlIterator( rStg.pDown ) {}
    StgDirEntry* First() { return (StgDirEntry*) StgAvlIterator::First(); }
    StgDirEntry* Next()  { return (StgDirEntry*) StgAvlIterator::Next();  }
    StgDirEntry* Prev()  { return (StgDirEntry*) StgAvlIterator::Prev();  }
};

#endif

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
<|endoftext|>


<commit_before>#include <pybind11/pybind11.h>
#include <pybind11/stl.h>
#include <kms++.h>

namespace py = pybind11;

using namespace kms;
using namespace std;

void init_pykmsbase(py::module &m)
{
	py::class_<Card>(m, "Card")
			.def(py::init<>())
			.def_property_readonly("fd", &Card::fd)
			.def("get_first_connected_connector", &Card::get_first_connected_connector)
			.def_property_readonly("connectors", &Card::get_connectors)
			.def_property_readonly("crtcs", &Card::get_crtcs)
			.def_property_readonly("encoders", &Card::get_encoders)
			.def_property_readonly("planes", &Card::get_planes)
			.def_property_readonly("has_atomic", &Card::has_atomic)
			.def("call_page_flip_handlers", &Card::call_page_flip_handlers)
			.def("get_prop", (Property* (Card::*)(uint32_t) const)&Card::get_prop)
			.def("get_prop", (Property* (Card::*)(const string&) const)&Card::get_prop)
			;

	py::class_<DrmObject, DrmObject*>(m, "DrmObject")
			.def_property_readonly("id", &DrmObject::id)
			.def_property_readonly("card", &DrmObject::card)
			;

	py::class_<DrmPropObject, DrmPropObject*>(m, "DrmPropObject", py::base<DrmObject>())
			.def("refresh_props", &DrmPropObject::refresh_props)
			.def_property_readonly("prop_map", &DrmPropObject::get_prop_map)
			.def("get_prop_value", (uint64_t (DrmPropObject::*)(const string&) const)&DrmPropObject::get_prop_value)
			.def("set_prop_value",(int (DrmPropObject::*)(const string&, uint64_t)) &DrmPropObject::set_prop_value)
			.def("get_prop_value_as_blob", &DrmPropObject::get_prop_value_as_blob)
			;

	py::class_<Connector, Connector*>(m, "Connector",  py::base<DrmPropObject>())
			.def_property_readonly("fullname", &Connector::fullname)
			.def("get_default_mode", &Connector::get_default_mode)
			.def("get_current_crtc", &Connector::get_current_crtc)
			.def("get_modes", &Connector::get_modes)
			.def("__repr__", [](const Connector& o) { return "<pykms.Connector " + to_string(o.id()) + ">"; })
			;

	py::class_<Crtc, Crtc*>(m, "Crtc",  py::base<DrmPropObject>())
			.def("set_mode", &Crtc::set_mode)
			.def("page_flip", &Crtc::page_flip)
			.def("set_plane", &Crtc::set_plane)
			.def_property_readonly("possible_planes", &Crtc::get_possible_planes)
			.def_property_readonly("primary_plane", &Crtc::get_primary_plane)
			.def("__repr__", [](const Crtc& o) { return "<pykms.Crtc " + to_string(o.id()) + ">"; })
			;

	py::class_<Encoder, Encoder*>(m, "Encoder",  py::base<DrmPropObject>())
			;

	py::class_<Plane, Plane*>(m, "Plane",  py::base<DrmPropObject>())
			.def("supports_crtc", &Plane::supports_crtc)
			.def_property_readonly("plane_type", &Plane::plane_type)
			.def("__repr__", [](const Plane& o) { return "<pykms.Plane " + to_string(o.id()) + ">"; })
			;

	py::enum_<PlaneType>(m, "PlaneType")
			.value("Overlay", PlaneType::Overlay)
			.value("Primary", PlaneType::Primary)
			.value("Cursor", PlaneType::Cursor)
			;

	py::class_<Property, Property*>(m, "Property",  py::base<DrmObject>())
			.def_property_readonly("name", &Property::name)
			;

	py::class_<Blob>(m, "Blob", py::base<DrmObject>())
			.def("__init__", [](Blob& instance, Card& card, py::buffer buf) {
				py::buffer_info info = buf.request();
				if (info.ndim != 1)
					throw std::runtime_error("Incompatible buffer dimension!");

				new (&instance) Blob(card, info.ptr, info.size * info.itemsize);
			})
			.def_property_readonly("data", &Blob::data)
			;

	py::class_<Framebuffer>(m, "Framebuffer",  py::base<DrmObject>())
			;

	py::class_<DumbFramebuffer>(m, "DumbFramebuffer",  py::base<Framebuffer>())
			.def(py::init<Card&, uint32_t, uint32_t, const string&>(),
			     py::keep_alive<1, 2>())	// Keep Card alive until this is destructed
			.def_property_readonly("width", &DumbFramebuffer::width)
			.def_property_readonly("height", &DumbFramebuffer::height)
			;

	py::class_<Videomode>(m, "Videomode")
			.def(py::init<>())

			.def_readwrite("name", &Videomode::name)

			.def_readwrite("clock", &Videomode::clock)

			.def_readwrite("hdisplay", &Videomode::hdisplay)
			.def_readwrite("hsync_start", &Videomode::hsync_start)
			.def_readwrite("hsync_end", &Videomode::hsync_end)
			.def_readwrite("htotal", &Videomode::htotal)

			.def_readwrite("vdisplay", &Videomode::vdisplay)
			.def_readwrite("vsync_start", &Videomode::vsync_start)
			.def_readwrite("vsync_end", &Videomode::vsync_end)
			.def_readwrite("vtotal", &Videomode::vtotal)

			.def_readwrite("vrefresh", &Videomode::vrefresh)

			.def_readwrite("flags", &Videomode::flags)
			.def_readwrite("type", &Videomode::type)
			;

	py::class_<AtomicReq>(m, "AtomicReq")
			.def(py::init<Card&>(),
			     py::keep_alive<1, 2>())	// Keep Card alive until this is destructed
			.def("add", (void (AtomicReq::*)(DrmObject*, const string&, uint64_t)) &AtomicReq::add)
			.def("test", &AtomicReq::test)
			.def("commit", &AtomicReq::commit)
			.def("commit_sync", &AtomicReq::commit_sync)
			;
}
<commit_msg>py: fix AtomicReq bindings<commit_after>#include <pybind11/pybind11.h>
#include <pybind11/stl.h>
#include <kms++.h>

namespace py = pybind11;

using namespace kms;
using namespace std;

void init_pykmsbase(py::module &m)
{
	py::class_<Card>(m, "Card")
			.def(py::init<>())
			.def_property_readonly("fd", &Card::fd)
			.def("get_first_connected_connector", &Card::get_first_connected_connector)
			.def_property_readonly("connectors", &Card::get_connectors)
			.def_property_readonly("crtcs", &Card::get_crtcs)
			.def_property_readonly("encoders", &Card::get_encoders)
			.def_property_readonly("planes", &Card::get_planes)
			.def_property_readonly("has_atomic", &Card::has_atomic)
			.def("call_page_flip_handlers", &Card::call_page_flip_handlers)
			.def("get_prop", (Property* (Card::*)(uint32_t) const)&Card::get_prop)
			.def("get_prop", (Property* (Card::*)(const string&) const)&Card::get_prop)
			;

	py::class_<DrmObject, DrmObject*>(m, "DrmObject")
			.def_property_readonly("id", &DrmObject::id)
			.def_property_readonly("card", &DrmObject::card)
			;

	py::class_<DrmPropObject, DrmPropObject*>(m, "DrmPropObject", py::base<DrmObject>())
			.def("refresh_props", &DrmPropObject::refresh_props)
			.def_property_readonly("prop_map", &DrmPropObject::get_prop_map)
			.def("get_prop_value", (uint64_t (DrmPropObject::*)(const string&) const)&DrmPropObject::get_prop_value)
			.def("set_prop_value",(int (DrmPropObject::*)(const string&, uint64_t)) &DrmPropObject::set_prop_value)
			.def("get_prop_value_as_blob", &DrmPropObject::get_prop_value_as_blob)
			;

	py::class_<Connector, Connector*>(m, "Connector",  py::base<DrmPropObject>())
			.def_property_readonly("fullname", &Connector::fullname)
			.def("get_default_mode", &Connector::get_default_mode)
			.def("get_current_crtc", &Connector::get_current_crtc)
			.def("get_modes", &Connector::get_modes)
			.def("__repr__", [](const Connector& o) { return "<pykms.Connector " + to_string(o.id()) + ">"; })
			;

	py::class_<Crtc, Crtc*>(m, "Crtc",  py::base<DrmPropObject>())
			.def("set_mode", &Crtc::set_mode)
			.def("page_flip", &Crtc::page_flip)
			.def("set_plane", &Crtc::set_plane)
			.def_property_readonly("possible_planes", &Crtc::get_possible_planes)
			.def_property_readonly("primary_plane", &Crtc::get_primary_plane)
			.def("__repr__", [](const Crtc& o) { return "<pykms.Crtc " + to_string(o.id()) + ">"; })
			;

	py::class_<Encoder, Encoder*>(m, "Encoder",  py::base<DrmPropObject>())
			;

	py::class_<Plane, Plane*>(m, "Plane",  py::base<DrmPropObject>())
			.def("supports_crtc", &Plane::supports_crtc)
			.def_property_readonly("plane_type", &Plane::plane_type)
			.def("__repr__", [](const Plane& o) { return "<pykms.Plane " + to_string(o.id()) + ">"; })
			;

	py::enum_<PlaneType>(m, "PlaneType")
			.value("Overlay", PlaneType::Overlay)
			.value("Primary", PlaneType::Primary)
			.value("Cursor", PlaneType::Cursor)
			;

	py::class_<Property, Property*>(m, "Property",  py::base<DrmObject>())
			.def_property_readonly("name", &Property::name)
			;

	py::class_<Blob>(m, "Blob", py::base<DrmObject>())
			.def("__init__", [](Blob& instance, Card& card, py::buffer buf) {
				py::buffer_info info = buf.request();
				if (info.ndim != 1)
					throw std::runtime_error("Incompatible buffer dimension!");

				new (&instance) Blob(card, info.ptr, info.size * info.itemsize);
			})
			.def_property_readonly("data", &Blob::data)
			;

	py::class_<Framebuffer>(m, "Framebuffer",  py::base<DrmObject>())
			;

	py::class_<DumbFramebuffer>(m, "DumbFramebuffer",  py::base<Framebuffer>())
			.def(py::init<Card&, uint32_t, uint32_t, const string&>(),
			     py::keep_alive<1, 2>())	// Keep Card alive until this is destructed
			.def_property_readonly("width", &DumbFramebuffer::width)
			.def_property_readonly("height", &DumbFramebuffer::height)
			;

	py::class_<Videomode>(m, "Videomode")
			.def(py::init<>())

			.def_readwrite("name", &Videomode::name)

			.def_readwrite("clock", &Videomode::clock)

			.def_readwrite("hdisplay", &Videomode::hdisplay)
			.def_readwrite("hsync_start", &Videomode::hsync_start)
			.def_readwrite("hsync_end", &Videomode::hsync_end)
			.def_readwrite("htotal", &Videomode::htotal)

			.def_readwrite("vdisplay", &Videomode::vdisplay)
			.def_readwrite("vsync_start", &Videomode::vsync_start)
			.def_readwrite("vsync_end", &Videomode::vsync_end)
			.def_readwrite("vtotal", &Videomode::vtotal)

			.def_readwrite("vrefresh", &Videomode::vrefresh)

			.def_readwrite("flags", &Videomode::flags)
			.def_readwrite("type", &Videomode::type)
			;

	py::class_<AtomicReq>(m, "AtomicReq")
			.def(py::init<Card&>(),
			     py::keep_alive<1, 2>())	// Keep Card alive until this is destructed
			.def("add", (void (AtomicReq::*)(DrmObject*, const string&, uint64_t)) &AtomicReq::add)
			.def("test", &AtomicReq::test, py::arg("allow_modeset") = false)
			.def("commit", &AtomicReq::commit, py::arg("data"), py::arg("allow_modeset") = false)
			.def("commit_sync", &AtomicReq::commit_sync, py::arg("allow_modeset") = false)
			;
}
<|endoftext|>


<commit_before>/****************************************************************************
**
** The MIT License (MIT)
**
** Copyright (c) 2016 The University of Sheffield (www.sheffield.ac.uk)
**
** Permission is hereby granted, free of charge, to any person obtaining a copy
** of this software and associated documentation files (the "Software"), to deal
** in the Software without restriction, including without limitation the rights
** to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
** copies of the Software, and to permit persons to whom the Software is
** furnished to do so, subject to the following conditions:
**
** The above copyright notice and this permission notice shall be included in all
** copies or substantial portions of the Software.
**
** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
** OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
** SOFTWARE
**
****************************************************************************/
#include <core/RandomDistributions.h>
#include <core/utils/LinearInterpolator.h>
#include <random>
#include <complex>
#include <math.h>
#include <algorithm>

using CODeM::Utils::LinearInterpolator;
using namespace std;

namespace CODeM {

/// IDISTRIBUTION
IDistribution::IDistribution()
    : m_lb(0.0),
      m_ub(1.0),
      m_dz(1.0),
      m_nSamples(0),
      m_quantileInterpolator(0),
      m_updated(false)
{

}

IDistribution::~IDistribution()
{
    if(m_quantileInterpolator != 0) {
        delete m_quantileInterpolator;
    }
}

double IDistribution::sample()
{
    if(!m_updated) {
        computeDistribution();
    }

    // A value between 0-1: 0==>lb , 1==>ub
    double sample = m_quantileInterpolator->interpolate(randUni());
    return sample;
}

vector<double> IDistribution::zSamples()
{
    if(!m_updated) {
        computeDistribution();
    }

    return m_z;
}

vector<double> IDistribution::pdf()
{
    if(!m_updated) {
        computeDistribution();
    }

    return m_pdf;
}

vector<double> IDistribution::cdf()
{
    if(!m_updated) {
        computeDistribution();
    }

    return m_cdf;
}

void IDistribution::defineResolution(double dz)
{
    if(dz > 0) {
        // make sure the range is a multiple of m_dz, and m_dz <= dz
        m_dz = (m_ub-m_lb) / ceil((m_ub-m_lb)/dz);
    }

    m_updated = false;
}

double IDistribution::resolution() const
{
    return m_dz;
}

void IDistribution::defineBoundaries(double lb, double ub)
{
    if(lb >= ub) {
        if(lb == 0) {
            ub = DistMinInterval;
        } else if(lb > 0) {
            ub = lb * (1 + DistMinInterval);
        } else {
            lb = ub * (1 + DistMinInterval);
        }
    }

    double oldRange = m_ub - m_lb;
    double newRange = ub - lb;
    double ratio    = newRange / oldRange;

    m_lb = lb;
    m_ub = ub;

    defineResolution(m_dz * ratio);

    m_updated = false;
}

double IDistribution::lowerBound() const
{
    return m_lb;
}

double IDistribution::upperBound() const
{
    return m_ub;
}

void IDistribution::computeDistribution()
{
    m_z.clear();
    m_pdf.clear();
    m_cdf.clear();

    generateZ();
    generatePDF();
    calculateCDF();

    if(m_quantileInterpolator == 0) {
        m_quantileInterpolator = new LinearInterpolator(m_cdf, m_z);
    } else {
        m_quantileInterpolator->defineXY(m_cdf, m_z);
    }

    m_updated = true;
}

void IDistribution::calculateCDF()
{
    m_cdf.assign(m_nSamples, 0.0);
    double cur  = 0.0;
    double next = 0.0;
    for(int i=0; i<m_nSamples-1; i++) {
        cur  = m_pdf[i];
        next = m_pdf[i+1];
        m_cdf[i+1] = m_cdf[i] + (cur+next)/2.0 * (m_z[i+1] - m_z[i]);
    }

    // normalise
    double factor = *(m_cdf.end());
    if(factor == 1.0) {
        return;
    } else if(factor == 0.0) {
        double probability = 1.0/(m_ub - m_lb);
        m_pdf.assign(m_nSamples, probability);
        calculateCDF();
    } else {
//        for(int i=0; i<m_cdf.size(); i++) {
//            m_pdf[i] /= factor;
//            m_cdf[i] /= factor;
//        }
        // Try this instead. TODO: remove the comment if it works
        transform(m_pdf.begin(), m_pdf.end(), m_pdf.begin(),
                  [factor](double p){return p/factor;});
        transform(m_cdf.begin(), m_cdf.end(), m_cdf.begin(),
                  [factor](double p){return p/factor;});
    }
}

void IDistribution::generateEquallySpacedZ()
{
    m_nSamples = (int)((m_ub - m_lb) / m_dz) + 1;
    m_z.resize(m_nSamples);
    double zz = m_lb;
    for(int i = 0; i < m_z.size() - 1; i++) {
        m_z[i] = zz;
        zz += m_dz;
    }
    m_z[m_z.size() - 1] = m_ub;
}

/// UNIFORM DISTRIBUTION
UniformDistribution::UniformDistribution()
{

}

UniformDistribution::UniformDistribution(double lb, double ub)
{
    defineBoundaries(lb, ub);
    defineResolution(m_ub - m_lb);
}

UniformDistribution::~UniformDistribution()
{

}

double UniformDistribution::sample()
{
    return m_lb + randUni() * (m_ub - m_lb);
}

void UniformDistribution::generateZ()
{
    generateEquallySpacedZ();
}

void UniformDistribution::generatePDF()
{
    double probability = 1.0/(m_ub - m_lb);
    m_pdf.assign(m_nSamples, probability);
}

/// LINEAR DISTRIBUTION
LinearDistribution::LinearDistribution()
    : m_ascend(true)
{
    defineResolution((m_ub-m_lb) / 2.0);
}

LinearDistribution::LinearDistribution(double lb, double ub, bool ascend)
    : m_ascend(ascend)
{
    defineBoundaries(lb, ub);
    defineResolution((m_ub-m_lb) / 2.0);
}

LinearDistribution::~LinearDistribution()
{

}

double LinearDistribution::sample()
{
    double r = randUni();
    double samp;
    if(m_ascend) {
        samp = m_lb + sqrt(r) * (m_ub - m_lb);
    } else {
        samp = m_ub - sqrt(1 - r) * (m_ub - m_lb);
    }
    return samp;
}

void LinearDistribution::generateZ()
{
    generateEquallySpacedZ();
}

void LinearDistribution::generatePDF()
{
    if(m_z.empty()) {
        generateZ();
    }

    double maxProbability = 2/(m_ub - m_lb);
    m_pdf = vector<double>(m_nSamples);
    if(isAscend()) {
        for(int i=0; i<m_nSamples; i++) {
            m_pdf[i] = maxProbability * (m_z[i] - m_lb) / (m_ub - m_lb);
        }
    } else {
        for(int i=0; i<m_nSamples; i++) {
            m_pdf[i] = maxProbability * (m_ub - m_z[i]) / (m_ub - m_lb);
        }
    }
}

bool LinearDistribution::isAscend() const
{
    return m_ascend;
}

void LinearDistribution::defineAscend(bool a)
{
    if(m_ascend != a) {
        m_updated = false;
    }
    m_ascend = a;
}

/// PEAK DISTRIBUTION
PeakDistribution::PeakDistribution()
    : m_tendency(0.5),
      m_locality(1.0)
{
    defineResolution(1.0 / (DistNSamples - 1));
}

PeakDistribution::PeakDistribution(double tendency, double locality)
{
    defineTendencyAndLocality(tendency, locality);
}

PeakDistribution::~PeakDistribution()
{

}

void PeakDistribution::defineTendencyAndLocality(double tendency, double locality)
{
    if(tendency < 0.0) {
        tendency = 0.0;
    } else if(tendency > 1.0) {
        tendency = 1.0;
    }
    m_tendency = tendency;

    if(locality < 0.0) {
        locality = 0.0;
    } else if(locality > 1.0) {
        locality = 1.0;
    }

    m_locality = locality;

    defineResolution(1.0/(m_locality+0.1)/(DistNSamples-1));
}

double PeakDistribution::tendency() const
{
    return m_tendency;
}

double PeakDistribution::locality() const
{
    return m_locality;
}

void PeakDistribution::generateZ()
{
    generateEquallySpacedZ();
}

void PeakDistribution::generatePDF()
{
    m_pdf.resize(m_nSamples);

    double shift = PI * m_tendency;
    double N = DistPeakMinN + m_locality
            * (DistPeakMaxN - DistPeakMinN);
    vector<complex<double> > psiN(m_nSamples, complex<double>(0, 0));

    double nMax = max(3*N, DistPeakMinNBasisFunc);
    nMax = min(nMax, DistPeakMaxNBasisFunc);
    for(int n = 1; n <= nMax; n++) {
        double cNn = sqrt( (pow(N, n) * exp(-N) / factorial(n)));
        vector<double> psi = eigenFunction(n);
        for(int i=0; i<m_nSamples; i++) {
            complex<double> j(0.0, 1.0);
            psiN[i] += cNn * exp(-j * shift * (n + 0.5)) * psi[i];
        }
    }
    for(int i=0; i<m_nSamples; i++) {
        m_pdf[i] = real(conj(psiN[i]) * psiN[i]);
    }
}

vector<double> PeakDistribution::eigenFunction(int n)
{
    double Lz = m_ub - m_lb;
    double An = sqrt(2.0 / Lz);

    vector<double> psi(m_nSamples, 0.0);
    for(int i=1; i<m_nSamples-1; i++) {
        psi[i] = An * sin(PI * n * (m_z[i] - m_lb) / Lz);
    }
    return psi;
}

/// MERGED DISTRIBUTION
MergedDistribution::MergedDistribution()
{

}

MergedDistribution::~MergedDistribution()
{
    for(int i = 0; i < m_distributions.size(); i++) {
        delete m_distributions[i];
    }
}

void MergedDistribution::generateZ()
{
    int nDistributions = (int)m_distributions.size();

    if(nDistributions == 0) {
        return;
    }

    for(int i=0; i<nDistributions; i++) {
        addZSamplesOfOneDistribution(m_distributions[i]);
    }
}

void MergedDistribution::addZSamplesOfOneDistribution(IDistribution* d)
{
    vector<double> newZ = d->zSamples();
    if(newZ.empty())  {
        return;
    }
    vector<double>::iterator iNew = newZ.begin();
    vector<double>::iterator iExist = m_z.begin();
    // merge newZ and m_z into augZ
    vector<double> augZ;

//    int iNew = 0; // iterator for newZ
//    int iAug = 0; // iterator for m_z

    while((iNew != newZ.end()) && (iExist != m_z.end())) {
        if(*iNew == *iExist) {
            augZ.push_back(*iExist++);
            iNew++;
        }
        else if(*iNew < *iExist) {
            augZ.push_back(*iNew++);
        }
        else {
            augZ.push_back(*iExist++);
        }
    }

    while(iNew != newZ.end()) {
        augZ.push_back(*iNew++);
    }

    while(iExist != m_z.end()) {
        augZ.push_back(*iExist++);
    }

    m_z.swap(augZ);
    m_lb = m_z.front();
    m_ub = m_z.back();
    m_nSamples = (int)m_z.size();
    augZ.clear();
}

void MergedDistribution::generatePDF()
{
    size_t nDistributions = m_distributions.size();

    if(nDistributions == 0) {
        return;
    }

    m_pdf.resize(m_nSamples);

    for(int i=0; i<nDistributions; i++) {
        addOnePDF(m_distributions[i], m_ratios[i]);
    }
}

void MergedDistribution::addOnePDF(IDistribution* d, double ratio)
{
    // call this function only after the samples are integrated into m_z
    vector<double> newPDF = d->pdf();
    if(newPDF.empty()) {
        return;
    }
    vector<double> newZ   = d->zSamples();

    // find the range of the new pdf
    vector<double>::iterator first = m_z.begin();
    vector<double>::iterator last  = m_z.end();
    vector<double>::iterator pdfIter  = m_pdf.begin();

    while(newZ.front() > *first) {
        ++first;
        ++pdfIter;
    }
    while(newZ.back() < *last) {
        --last;
    }

    //Interpolate the new pdf over the new samples in its range
    LinearInterpolator pdfInterpolator(newZ, newPDF);
    vector<double> tmp = pdfInterpolator.interpolateV(vector<double>(first, last));
    newPDF.swap(tmp);

    // add the new pdf times its weight to the existing pdf
    vector<double>::iterator newIter;
    for(newIter = newPDF.begin(); newIter == newPDF.end(); ++newIter, ++pdfIter) {
        *pdfIter += (*newIter * ratio);
    }
}

void MergedDistribution::appendDistribution(IDistribution* d)
{
    appendDistribution(d, 1.0);
}

void MergedDistribution::appendDistribution(IDistribution* d, double ratio)
{
    m_distributions.push_back(d);
    m_ratios.push_back(max(ratio, 0.0));
    computeDistribution();
}

} // namespace CODeM
<commit_msg>bug fix<commit_after>/****************************************************************************
**
** The MIT License (MIT)
**
** Copyright (c) 2016 The University of Sheffield (www.sheffield.ac.uk)
**
** Permission is hereby granted, free of charge, to any person obtaining a copy
** of this software and associated documentation files (the "Software"), to deal
** in the Software without restriction, including without limitation the rights
** to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
** copies of the Software, and to permit persons to whom the Software is
** furnished to do so, subject to the following conditions:
**
** The above copyright notice and this permission notice shall be included in all
** copies or substantial portions of the Software.
**
** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
** OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
** SOFTWARE
**
****************************************************************************/
#include <core/RandomDistributions.h>
#include <core/utils/LinearInterpolator.h>
#include <random>
#include <complex>
#include <math.h>
#include <algorithm>

using CODeM::Utils::LinearInterpolator;
using namespace std;

namespace CODeM {

/// IDISTRIBUTION
IDistribution::IDistribution()
    : m_lb(0.0),
      m_ub(1.0),
      m_dz(1.0),
      m_nSamples(0),
      m_quantileInterpolator(0),
      m_updated(false)
{

}

IDistribution::~IDistribution()
{
    if(m_quantileInterpolator != 0) {
        delete m_quantileInterpolator;
    }
}

double IDistribution::sample()
{
    if(!m_updated) {
        computeDistribution();
    }

    // A value between 0-1: 0==>lb , 1==>ub
    double sample = m_quantileInterpolator->interpolate(randUni());
    return sample;
}

vector<double> IDistribution::zSamples()
{
    if(!m_updated) {
        computeDistribution();
    }

    return m_z;
}

vector<double> IDistribution::pdf()
{
    if(!m_updated) {
        computeDistribution();
    }

    return m_pdf;
}

vector<double> IDistribution::cdf()
{
    if(!m_updated) {
        computeDistribution();
    }

    return m_cdf;
}

void IDistribution::defineResolution(double dz)
{
    if(dz > 0) {
        // make sure the range is a multiple of m_dz, and m_dz <= dz
        m_dz = (m_ub-m_lb) / ceil((m_ub-m_lb)/dz);
    }

    m_updated = false;
}

double IDistribution::resolution() const
{
    return m_dz;
}

void IDistribution::defineBoundaries(double lb, double ub)
{
    if(lb >= ub) {
        if(lb == 0) {
            ub = DistMinInterval;
        } else if(lb > 0) {
            ub = lb * (1 + DistMinInterval);
        } else {
            lb = ub * (1 + DistMinInterval);
        }
    }

    double oldRange = m_ub - m_lb;
    double newRange = ub - lb;
    double ratio    = newRange / oldRange;

    m_lb = lb;
    m_ub = ub;

    defineResolution(m_dz * ratio);

    m_updated = false;
}

double IDistribution::lowerBound() const
{
    return m_lb;
}

double IDistribution::upperBound() const
{
    return m_ub;
}

void IDistribution::computeDistribution()
{
    m_z.clear();
    m_pdf.clear();
    m_cdf.clear();

    generateZ();
    generatePDF();
    calculateCDF();

    if(m_quantileInterpolator == 0) {
        m_quantileInterpolator = new LinearInterpolator(m_cdf, m_z);
    } else {
        m_quantileInterpolator->defineXY(m_cdf, m_z);
    }

    m_updated = true;
}

void IDistribution::calculateCDF()
{
    m_cdf.assign(m_nSamples, 0.0);
    double cur  = 0.0;
    double next = 0.0;
    for(int i=0; i<m_nSamples-1; i++) {
        cur  = m_pdf[i];
        next = m_pdf[i+1];
        m_cdf[i+1] = m_cdf[i] + (cur+next)/2.0 * (m_z[i+1] - m_z[i]);
    }

    // normalise
    double factor = m_cdf.back();
    if(factor == 1.0) {
        return;
    } else if(factor == 0.0) {
        double probability = 1.0/(m_ub - m_lb);
        m_pdf.assign(m_nSamples, probability);
        calculateCDF();
    } else {
//        for(int i=0; i<m_cdf.size(); i++) {
//            m_pdf[i] /= factor;
//            m_cdf[i] /= factor;
//        }
        // Try this instead. TODO: remove the comment if it works
        transform(m_pdf.begin(), m_pdf.end(), m_pdf.begin(),
                  [factor](double p){return p/factor;});
        transform(m_cdf.begin(), m_cdf.end(), m_cdf.begin(),
                  [factor](double p){return p/factor;});
    }
}

void IDistribution::generateEquallySpacedZ()
{
    m_nSamples = (int)((m_ub - m_lb) / m_dz) + 1;
    m_z.resize(m_nSamples);
    double zz = m_lb;
    for(int i = 0; i < m_z.size() - 1; i++) {
        m_z[i] = zz;
        zz += m_dz;
    }
    m_z[m_z.size() - 1] = m_ub;
}

/// UNIFORM DISTRIBUTION
UniformDistribution::UniformDistribution()
{

}

UniformDistribution::UniformDistribution(double lb, double ub)
{
    defineBoundaries(lb, ub);
    defineResolution(m_ub - m_lb);
}

UniformDistribution::~UniformDistribution()
{

}

double UniformDistribution::sample()
{
    return m_lb + randUni() * (m_ub - m_lb);
}

void UniformDistribution::generateZ()
{
    generateEquallySpacedZ();
}

void UniformDistribution::generatePDF()
{
    double probability = 1.0/(m_ub - m_lb);
    m_pdf.assign(m_nSamples, probability);
}

/// LINEAR DISTRIBUTION
LinearDistribution::LinearDistribution()
    : m_ascend(true)
{
    defineResolution((m_ub-m_lb) / 2.0);
}

LinearDistribution::LinearDistribution(double lb, double ub, bool ascend)
    : m_ascend(ascend)
{
    defineBoundaries(lb, ub);
    defineResolution((m_ub-m_lb) / 2.0);
}

LinearDistribution::~LinearDistribution()
{

}

double LinearDistribution::sample()
{
    double r = randUni();
    double samp;
    if(m_ascend) {
        samp = m_lb + sqrt(r) * (m_ub - m_lb);
    } else {
        samp = m_ub - sqrt(1 - r) * (m_ub - m_lb);
    }
    return samp;
}

void LinearDistribution::generateZ()
{
    generateEquallySpacedZ();
}

void LinearDistribution::generatePDF()
{
    if(m_z.empty()) {
        generateZ();
    }

    double maxProbability = 2/(m_ub - m_lb);
    m_pdf = vector<double>(m_nSamples);
    if(isAscend()) {
        for(int i=0; i<m_nSamples; i++) {
            m_pdf[i] = maxProbability * (m_z[i] - m_lb) / (m_ub - m_lb);
        }
    } else {
        for(int i=0; i<m_nSamples; i++) {
            m_pdf[i] = maxProbability * (m_ub - m_z[i]) / (m_ub - m_lb);
        }
    }
}

bool LinearDistribution::isAscend() const
{
    return m_ascend;
}

void LinearDistribution::defineAscend(bool a)
{
    if(m_ascend != a) {
        m_updated = false;
    }
    m_ascend = a;
}

/// PEAK DISTRIBUTION
PeakDistribution::PeakDistribution()
    : m_tendency(0.5),
      m_locality(1.0)
{
    defineResolution(1.0 / (DistNSamples - 1));
}

PeakDistribution::PeakDistribution(double tendency, double locality)
{
    defineTendencyAndLocality(tendency, locality);
}

PeakDistribution::~PeakDistribution()
{

}

void PeakDistribution::defineTendencyAndLocality(double tendency, double locality)
{
    if(tendency < 0.0) {
        tendency = 0.0;
    } else if(tendency > 1.0) {
        tendency = 1.0;
    }
    m_tendency = tendency;

    if(locality < 0.0) {
        locality = 0.0;
    } else if(locality > 1.0) {
        locality = 1.0;
    }

    m_locality = locality;

    defineResolution(1.0/(m_locality+0.1)/(DistNSamples-1));
}

double PeakDistribution::tendency() const
{
    return m_tendency;
}

double PeakDistribution::locality() const
{
    return m_locality;
}

void PeakDistribution::generateZ()
{
    generateEquallySpacedZ();
}

void PeakDistribution::generatePDF()
{
    m_pdf.resize(m_nSamples);

    double shift = PI * m_tendency;
    double N = DistPeakMinN + m_locality
            * (DistPeakMaxN - DistPeakMinN);
    vector<complex<double> > psiN(m_nSamples, complex<double>(0, 0));

    double nMax = max(3*N, DistPeakMinNBasisFunc);
    nMax = min(nMax, DistPeakMaxNBasisFunc);
    for(int n = 1; n <= nMax; n++) {
        double cNn = sqrt( (pow(N, n) * exp(-N) / factorial(n)));
        vector<double> psi = eigenFunction(n);
        for(int i=0; i<m_nSamples; i++) {
            complex<double> j(0.0, 1.0);
            psiN[i] += cNn * exp(-j * shift * (n + 0.5)) * psi[i];
        }
    }
    for(int i=0; i<m_nSamples; i++) {
        m_pdf[i] = real(conj(psiN[i]) * psiN[i]);
    }
}

vector<double> PeakDistribution::eigenFunction(int n)
{
    double Lz = m_ub - m_lb;
    double An = sqrt(2.0 / Lz);

    vector<double> psi(m_nSamples, 0.0);
    for(int i=1; i<m_nSamples-1; i++) {
        psi[i] = An * sin(PI * n * (m_z[i] - m_lb) / Lz);
    }
    return psi;
}

/// MERGED DISTRIBUTION
MergedDistribution::MergedDistribution()
{

}

MergedDistribution::~MergedDistribution()
{
    for(int i = 0; i < m_distributions.size(); i++) {
        delete m_distributions[i];
    }
}

void MergedDistribution::generateZ()
{
    int nDistributions = (int)m_distributions.size();

    if(nDistributions == 0) {
        return;
    }

    for(int i=0; i<nDistributions; i++) {
        addZSamplesOfOneDistribution(m_distributions[i]);
    }
}

void MergedDistribution::addZSamplesOfOneDistribution(IDistribution* d)
{
    vector<double> newZ = d->zSamples();
    if(newZ.empty())  {
        return;
    }
    vector<double>::iterator iNew = newZ.begin();
    vector<double>::iterator iExist = m_z.begin();
    // merge newZ and m_z into augZ
    vector<double> augZ;

//    int iNew = 0; // iterator for newZ
//    int iAug = 0; // iterator for m_z

    while((iNew != newZ.end()) && (iExist != m_z.end())) {
        if(*iNew == *iExist) {
            augZ.push_back(*iExist++);
            iNew++;
        }
        else if(*iNew < *iExist) {
            augZ.push_back(*iNew++);
        }
        else {
            augZ.push_back(*iExist++);
        }
    }

    while(iNew != newZ.end()) {
        augZ.push_back(*iNew++);
    }

    while(iExist != m_z.end()) {
        augZ.push_back(*iExist++);
    }

    m_z.swap(augZ);
    m_lb = m_z.front();
    m_ub = m_z.back();
    m_nSamples = (int)m_z.size();
    augZ.clear();
}

void MergedDistribution::generatePDF()
{
    size_t nDistributions = m_distributions.size();

    if(nDistributions == 0) {
        return;
    }

    m_pdf.resize(m_nSamples);

    for(int i=0; i<nDistributions; i++) {
        addOnePDF(m_distributions[i], m_ratios[i]);
    }
}

void MergedDistribution::addOnePDF(IDistribution* d, double ratio)
{
    // call this function only after the samples are integrated into m_z
    vector<double> newPDF = d->pdf();
    if(newPDF.empty()) {
        return;
    }
    vector<double> newZ   = d->zSamples();

    // find the range of the new pdf
    vector<double>::iterator first = m_z.begin();
    vector<double>::iterator last  = m_z.end();
    vector<double>::iterator pdfIter  = m_pdf.begin();

    while(newZ.front() > *first) {
        ++first;
        ++pdfIter;
    }
    while(newZ.back() < *last) {
        --last;
    }

    //Interpolate the new pdf over the new samples in its range
    LinearInterpolator pdfInterpolator(newZ, newPDF);
    vector<double> tmp = pdfInterpolator.interpolateV(vector<double>(first, last));
    newPDF.swap(tmp);

    // add the new pdf times its weight to the existing pdf
    vector<double>::iterator newIter;
    for(newIter = newPDF.begin(); newIter == newPDF.end(); ++newIter, ++pdfIter) {
        *pdfIter += (*newIter * ratio);
    }
}

void MergedDistribution::appendDistribution(IDistribution* d)
{
    appendDistribution(d, 1.0);
}

void MergedDistribution::appendDistribution(IDistribution* d, double ratio)
{
    m_distributions.push_back(d);
    m_ratios.push_back(max(ratio, 0.0));
    computeDistribution();
}

} // namespace CODeM
<|endoftext|>