<commit_before>// Copyright (c) 2011-2013 The Bitcoin developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include "notificator.h"

#include <QMetaType>
#include <QVariant>
#include <QIcon>
#include <QApplication>
#include <QStyle>
#include <QByteArray>
#include <QSystemTrayIcon>
#include <QMessageBox>
#include <QTemporaryFile>
#include <QImageWriter>

#ifdef USE_DBUS
#include <QtDBus>
#include <stdint.h>
#endif

#ifdef Q_OS_MAC
#include <ApplicationServices/ApplicationServices.h>
#include "macnotificationhandler.h"
#endif

// https://wiki.ubuntu.com/NotificationDevelopmentGuidelines recommends at least 128
const int FREEDESKTOP_NOTIFICATION_ICON_SIZE = 128;

Notificator::Notificator(const QString &programName, QSystemTrayIcon *trayicon, QWidget *parent):
    QObject(parent),
    parent(parent),
    programName(programName),
    mode(None),
    trayIcon(trayicon)
#ifdef USE_DBUS
    ,interface(0)
#endif
{
    if(trayicon && trayicon->supportsMessages())
    {
        mode = QSystemTray;
    }
#ifdef USE_DBUS
    interface = new QDBusInterface("org.freedesktop.Notifications",
          "/org/freedesktop/Notifications", "org.freedesktop.Notifications");
    if(interface->isValid())
    {
        mode = Freedesktop;
    }
#endif
#ifdef Q_OS_MAC
    // check if users OS has support for NSUserNotification
    if( MacNotificationHandler::instance()->hasUserNotificationCenterSupport()) {
        mode = UserNotificationCenter;
    }
    else {
        // Check if Growl is installed (based on Qt's tray icon implementation)
        CFURLRef cfurl;
        OSStatus status = LSGetApplicationForInfo(kLSUnknownType, kLSUnknownCreator, CFSTR("growlTicket"), kLSRolesAll, 0, &cfurl);
        if (status != kLSApplicationNotFoundErr) {
            CFBundleRef bundle = CFBundleCreate(0, cfurl);
            if (CFStringCompare(CFBundleGetIdentifier(bundle), CFSTR("com.Growl.GrowlHelperApp"), kCFCompareCaseInsensitive | kCFCompareBackwards) == kCFCompareEqualTo) {
                if (CFStringHasSuffix(CFURLGetString(cfurl), CFSTR("/Growl.app/")))
                    mode = Growl13;
                else
                    mode = Growl12;
            }
            CFRelease(cfurl);
            CFRelease(bundle);
        }
    }
#endif
}

Notificator::~Notificator()
{
#ifdef USE_DBUS
    delete interface;
#endif
}

#ifdef USE_DBUS

// Loosely based on http://www.qtcentre.org/archive/index.php/t-25879.html
class FreedesktopImage
{
public:
    FreedesktopImage() {}
    FreedesktopImage(const QImage &img);

    static int metaType();

    // Image to variant that can be marshalled over DBus
    static QVariant toVariant(const QImage &img);

private:
    int width, height, stride;
    bool hasAlpha;
    int channels;
    int bitsPerSample;
    QByteArray image;

    friend QDBusArgument &operator<<(QDBusArgument &a, const FreedesktopImage &i);
    friend const QDBusArgument &operator>>(const QDBusArgument &a, FreedesktopImage &i);
};

Q_DECLARE_METATYPE(FreedesktopImage);

// Image configuration settings
const int CHANNELS = 4;
const int BYTES_PER_PIXEL = 4;
const int BITS_PER_SAMPLE = 8;

FreedesktopImage::FreedesktopImage(const QImage &img):
    width(img.width()),
    height(img.height()),
    stride(img.width() * BYTES_PER_PIXEL),
    hasAlpha(true),
    channels(CHANNELS),
    bitsPerSample(BITS_PER_SAMPLE)
{
    // Convert 00xAARRGGBB to RGBA bytewise (endian-independent) format
    QImage tmp = img.convertToFormat(QImage::Format_ARGB32);
    const uint32_t *data = reinterpret_cast<const uint32_t*>(tmp.bits());

    unsigned int num_pixels = width * height;
    image.resize(num_pixels * BYTES_PER_PIXEL);

    for(unsigned int ptr = 0; ptr < num_pixels; ++ptr)
    {
        image[ptr*BYTES_PER_PIXEL+0] = data[ptr] >> 16; // R
        image[ptr*BYTES_PER_PIXEL+1] = data[ptr] >> 8;  // G
        image[ptr*BYTES_PER_PIXEL+2] = data[ptr];       // B
        image[ptr*BYTES_PER_PIXEL+3] = data[ptr] >> 24; // A
    }
}

QDBusArgument &operator<<(QDBusArgument &a, const FreedesktopImage &i)
{
    a.beginStructure();
    a << i.width << i.height << i.stride << i.hasAlpha << i.bitsPerSample << i.channels << i.image;
    a.endStructure();
    return a;
}

const QDBusArgument &operator>>(const QDBusArgument &a, FreedesktopImage &i)
{
    a.beginStructure();
    a >> i.width >> i.height >> i.stride >> i.hasAlpha >> i.bitsPerSample >> i.channels >> i.image;
    a.endStructure();
    return a;
}

int FreedesktopImage::metaType()
{
    return qDBusRegisterMetaType<FreedesktopImage>();
}

QVariant FreedesktopImage::toVariant(const QImage &img)
{
    FreedesktopImage fimg(img);
    return QVariant(FreedesktopImage::metaType(), &fimg);
}

void Notificator::notifyDBus(Class cls, const QString &title, const QString &text, const QIcon &icon, int millisTimeout)
{
    Q_UNUSED(cls);
    // Arguments for DBus call:
    QList<QVariant> args;

    // Program Name:
    args.append(programName);

    // Unique ID of this notification type:
    args.append(0U);

    // Application Icon, empty string
    args.append(QString());

    // Summary
    args.append(title);

    // Body
    args.append(text);

    // Actions (none, actions are deprecated)
    QStringList actions;
    args.append(actions);

    // Hints
    QVariantMap hints;

    // If no icon specified, set icon based on class
    QIcon tmpicon;
    if(icon.isNull())
    {
        QStyle::StandardPixmap sicon = QStyle::SP_MessageBoxQuestion;
        switch(cls)
        {
        case Information: sicon = QStyle::SP_MessageBoxInformation; break;
        case Warning: sicon = QStyle::SP_MessageBoxWarning; break;
        case Critical: sicon = QStyle::SP_MessageBoxCritical; break;
        default: break;
        }
        tmpicon = QApplication::style()->standardIcon(sicon);
    }
    else
    {
        tmpicon = icon;
    }
    hints["icon_data"] = FreedesktopImage::toVariant(tmpicon.pixmap(FREEDESKTOP_NOTIFICATION_ICON_SIZE).toImage());
    args.append(hints);

    // Timeout (in msec)
    args.append(millisTimeout);

    // "Fire and forget"
    interface->callWithArgumentList(QDBus::NoBlock, "Notify", args);
}
#endif

void Notificator::notifySystray(Class cls, const QString &title, const QString &text, const QIcon &icon, int millisTimeout)
{
    Q_UNUSED(icon);
    QSystemTrayIcon::MessageIcon sicon = QSystemTrayIcon::NoIcon;
    switch(cls) // Set icon based on class
    {
    case Information: sicon = QSystemTrayIcon::Information; break;
    case Warning: sicon = QSystemTrayIcon::Warning; break;
    case Critical: sicon = QSystemTrayIcon::Critical; break;
    }
    trayIcon->showMessage(title, text, sicon, millisTimeout);
}

// Based on Qt's tray icon implementation
#ifdef Q_OS_MAC
void Notificator::notifyGrowl(Class cls, const QString &title, const QString &text, const QIcon &icon)
{
    const QString script(
        "tell application \"%5\"\n"
        "  set the allNotificationsList to {\"Notification\"}\n" // -- Make a list of all the notification types (all)
        "  set the enabledNotificationsList to {\"Notification\"}\n" // -- Make a list of the notifications (enabled)
        "  register as application \"%1\" all notifications allNotificationsList default notifications enabledNotificationsList\n" // -- Register our script with Growl
        "  notify with name \"Notification\" title \"%2\" description \"%3\" application name \"%1\"%4\n" // -- Send a Notification
        "end tell"
    );

    QString notificationApp(QApplication::applicationName());
    if (notificationApp.isEmpty())
        notificationApp = "Application";

    QPixmap notificationIconPixmap;
    if (icon.isNull()) { // If no icon specified, set icon based on class
        QStyle::StandardPixmap sicon = QStyle::SP_MessageBoxQuestion;
        switch (cls)
        {
        case Information: sicon = QStyle::SP_MessageBoxInformation; break;
        case Warning: sicon = QStyle::SP_MessageBoxWarning; break;
        case Critical: sicon = QStyle::SP_MessageBoxCritical; break;
        }
        notificationIconPixmap = QApplication::style()->standardPixmap(sicon);
    }
    else {
        QSize size = icon.actualSize(QSize(48, 48));
        notificationIconPixmap = icon.pixmap(size);
    }

    QString notificationIcon;
    QTemporaryFile notificationIconFile;
    if (!notificationIconPixmap.isNull() && notificationIconFile.open()) {
        QImageWriter writer(&notificationIconFile, "PNG");
        if (writer.write(notificationIconPixmap.toImage()))
            notificationIcon = QString(" image from location \"file://%1\"").arg(notificationIconFile.fileName());
    }

    QString quotedTitle(title), quotedText(text);
    quotedTitle.replace("\\", "\\\\").replace("\"", "\\");
    quotedText.replace("\\", "\\\\").replace("\"", "\\");
    QString growlApp(this->mode == Notificator::Growl13 ? "Growl" : "GrowlHelperApp");
    MacNotificationHandler::instance()->sendAppleScript(script.arg(notificationApp, quotedTitle, quotedText, notificationIcon, growlApp));
}

void Notificator::notifyMacUserNotificationCenter(Class cls, const QString &title, const QString &text, const QIcon &icon) {
    // icon is not supported by the user notification center yet. OSX will use the app icon.
    MacNotificationHandler::instance()->showNotification(title, text);
}

#endif

void Notificator::notify(Class cls, const QString &title, const QString &text, const QIcon &icon, int millisTimeout)
{
    switch(mode)
    {
#ifdef USE_DBUS
    case Freedesktop:
        notifyDBus(cls, title, text, icon, millisTimeout);
        break;
#endif
    case QSystemTray:
        notifySystray(cls, title, text, icon, millisTimeout);
        break;
#ifdef Q_OS_MAC
    case UserNotificationCenter:
        notifyMacUserNotificationCenter(cls, title, text, icon);
        break;
    case Growl12:
    case Growl13:
        notifyGrowl(cls, title, text, icon);
        break;
#endif
    default:
        if(cls == Critical)
        {
            // Fall back to old fashioned pop-up dialog if critical and no other notification available
            QMessageBox::critical(parent, title, text, QMessageBox::Ok, QMessageBox::Ok);
        }
        break;
    }
}
<commit_msg>Update notificator.cpp<commit_after>// Copyright (c) 2011-2013 The Bitcoin developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include "notificator.h"

#include <QMetaType>
#include <QVariant>
#include <QIcon>
#include <QApplication>
#include <QStyle>
#include <QByteArray>
#include <QSystemTrayIcon>
#include <QMessageBox>
#include <QTemporaryFile>
#include <QImageWriter>

#ifdef USE_DBUS
#include <QtDBus>
#include <stdint.h>
#endif

#ifdef Q_OS_MAC
#include <ApplicationServices/ApplicationServices.h>
#include "macnotificationhandler.h"
#endif

// https://wiki.ubuntu.com/NotificationDevelopmentGuidelines recommends at least 128
// const int FREEDESKTOP_NOTIFICATION_ICON_SIZE = 128;

Notificator::Notificator(const QString &programName, QSystemTrayIcon *trayicon, QWidget *parent):
    QObject(parent),
    parent(parent),
    programName(programName),
    mode(None),
    trayIcon(trayicon)
#ifdef USE_DBUS
    ,interface(0)
#endif
{
    if(trayicon && trayicon->supportsMessages())
    {
        mode = QSystemTray;
    }
#ifdef USE_DBUS
    interface = new QDBusInterface("org.freedesktop.Notifications",
          "/org/freedesktop/Notifications", "org.freedesktop.Notifications");
    if(interface->isValid())
    {
        mode = Freedesktop;
    }
#endif
#ifdef Q_OS_MAC
    // check if users OS has support for NSUserNotification
    if( MacNotificationHandler::instance()->hasUserNotificationCenterSupport()) {
        mode = UserNotificationCenter;
    }
    else {
        // Check if Growl is installed (based on Qt's tray icon implementation)
        CFURLRef cfurl;
        OSStatus status = LSGetApplicationForInfo(kLSUnknownType, kLSUnknownCreator, CFSTR("growlTicket"), kLSRolesAll, 0, &cfurl);
        if (status != kLSApplicationNotFoundErr) {
            CFBundleRef bundle = CFBundleCreate(0, cfurl);
            if (CFStringCompare(CFBundleGetIdentifier(bundle), CFSTR("com.Growl.GrowlHelperApp"), kCFCompareCaseInsensitive | kCFCompareBackwards) == kCFCompareEqualTo) {
                if (CFStringHasSuffix(CFURLGetString(cfurl), CFSTR("/Growl.app/")))
                    mode = Growl13;
                else
                    mode = Growl12;
            }
            CFRelease(cfurl);
            CFRelease(bundle);
        }
    }
#endif
}

Notificator::~Notificator()
{
#ifdef USE_DBUS
    delete interface;
#endif
}

#ifdef USE_DBUS

// Loosely based on http://www.qtcentre.org/archive/index.php/t-25879.html
class FreedesktopImage
{
public:
    FreedesktopImage() {}
    FreedesktopImage(const QImage &img);

    static int metaType();

    // Image to variant that can be marshalled over DBus
    static QVariant toVariant(const QImage &img);

private:
    int width, height, stride;
    bool hasAlpha;
    int channels;
    int bitsPerSample;
    QByteArray image;

    friend QDBusArgument &operator<<(QDBusArgument &a, const FreedesktopImage &i);
    friend const QDBusArgument &operator>>(const QDBusArgument &a, FreedesktopImage &i);
};

Q_DECLARE_METATYPE(FreedesktopImage);

// Image configuration settings
const int CHANNELS = 4;
const int BYTES_PER_PIXEL = 4;
const int BITS_PER_SAMPLE = 8;

FreedesktopImage::FreedesktopImage(const QImage &img):
    width(img.width()),
    height(img.height()),
    stride(img.width() * BYTES_PER_PIXEL),
    hasAlpha(true),
    channels(CHANNELS),
    bitsPerSample(BITS_PER_SAMPLE)
{
    // Convert 00xAARRGGBB to RGBA bytewise (endian-independent) format
    QImage tmp = img.convertToFormat(QImage::Format_ARGB32);
    const uint32_t *data = reinterpret_cast<const uint32_t*>(tmp.bits());

    unsigned int num_pixels = width * height;
    image.resize(num_pixels * BYTES_PER_PIXEL);

    for(unsigned int ptr = 0; ptr < num_pixels; ++ptr)
    {
        image[ptr*BYTES_PER_PIXEL+0] = data[ptr] >> 16; // R
        image[ptr*BYTES_PER_PIXEL+1] = data[ptr] >> 8;  // G
        image[ptr*BYTES_PER_PIXEL+2] = data[ptr];       // B
        image[ptr*BYTES_PER_PIXEL+3] = data[ptr] >> 24; // A
    }
}

QDBusArgument &operator<<(QDBusArgument &a, const FreedesktopImage &i)
{
    a.beginStructure();
    a << i.width << i.height << i.stride << i.hasAlpha << i.bitsPerSample << i.channels << i.image;
    a.endStructure();
    return a;
}

const QDBusArgument &operator>>(const QDBusArgument &a, FreedesktopImage &i)
{
    a.beginStructure();
    a >> i.width >> i.height >> i.stride >> i.hasAlpha >> i.bitsPerSample >> i.channels >> i.image;
    a.endStructure();
    return a;
}

int FreedesktopImage::metaType()
{
    return qDBusRegisterMetaType<FreedesktopImage>();
}

QVariant FreedesktopImage::toVariant(const QImage &img)
{
    FreedesktopImage fimg(img);
    return QVariant(FreedesktopImage::metaType(), &fimg);
}

void Notificator::notifyDBus(Class cls, const QString &title, const QString &text, const QIcon &icon, int millisTimeout)
{
    Q_UNUSED(cls);
    // Arguments for DBus call:
    QList<QVariant> args;

    // Program Name:
    args.append(programName);

    // Unique ID of this notification type:
    args.append(0U);

    // Application Icon, empty string
    args.append(QString());

    // Summary
    args.append(title);

    // Body
    args.append(text);

    // Actions (none, actions are deprecated)
    QStringList actions;
    args.append(actions);

    // Hints
    QVariantMap hints;

    // If no icon specified, set icon based on class
    QIcon tmpicon;
    if(icon.isNull())
    {
        QStyle::StandardPixmap sicon = QStyle::SP_MessageBoxQuestion;
        switch(cls)
        {
        case Information: sicon = QStyle::SP_MessageBoxInformation; break;
        case Warning: sicon = QStyle::SP_MessageBoxWarning; break;
        case Critical: sicon = QStyle::SP_MessageBoxCritical; break;
        default: break;
        }
        tmpicon = QApplication::style()->standardIcon(sicon);
    }
    else
    {
        tmpicon = icon;
    }
    hints["icon_data"] = FreedesktopImage::toVariant(tmpicon.pixmap(FREEDESKTOP_NOTIFICATION_ICON_SIZE).toImage());
    args.append(hints);

    // Timeout (in msec)
    args.append(millisTimeout);

    // "Fire and forget"
    interface->callWithArgumentList(QDBus::NoBlock, "Notify", args);
}
#endif

void Notificator::notifySystray(Class cls, const QString &title, const QString &text, const QIcon &icon, int millisTimeout)
{
    Q_UNUSED(icon);
    QSystemTrayIcon::MessageIcon sicon = QSystemTrayIcon::NoIcon;
    switch(cls) // Set icon based on class
    {
    case Information: sicon = QSystemTrayIcon::Information; break;
    case Warning: sicon = QSystemTrayIcon::Warning; break;
    case Critical: sicon = QSystemTrayIcon::Critical; break;
    }
    trayIcon->showMessage(title, text, sicon, millisTimeout);
}

// Based on Qt's tray icon implementation
#ifdef Q_OS_MAC
void Notificator::notifyGrowl(Class cls, const QString &title, const QString &text, const QIcon &icon)
{
    const QString script(
        "tell application \"%5\"\n"
        "  set the allNotificationsList to {\"Notification\"}\n" // -- Make a list of all the notification types (all)
        "  set the enabledNotificationsList to {\"Notification\"}\n" // -- Make a list of the notifications (enabled)
        "  register as application \"%1\" all notifications allNotificationsList default notifications enabledNotificationsList\n" // -- Register our script with Growl
        "  notify with name \"Notification\" title \"%2\" description \"%3\" application name \"%1\"%4\n" // -- Send a Notification
        "end tell"
    );

    QString notificationApp(QApplication::applicationName());
    if (notificationApp.isEmpty())
        notificationApp = "Application";

    QPixmap notificationIconPixmap;
    if (icon.isNull()) { // If no icon specified, set icon based on class
        QStyle::StandardPixmap sicon = QStyle::SP_MessageBoxQuestion;
        switch (cls)
        {
        case Information: sicon = QStyle::SP_MessageBoxInformation; break;
        case Warning: sicon = QStyle::SP_MessageBoxWarning; break;
        case Critical: sicon = QStyle::SP_MessageBoxCritical; break;
        }
        notificationIconPixmap = QApplication::style()->standardPixmap(sicon);
    }
    else {
        QSize size = icon.actualSize(QSize(48, 48));
        notificationIconPixmap = icon.pixmap(size);
    }

    QString notificationIcon;
    QTemporaryFile notificationIconFile;
    if (!notificationIconPixmap.isNull() && notificationIconFile.open()) {
        QImageWriter writer(&notificationIconFile, "PNG");
        if (writer.write(notificationIconPixmap.toImage()))
            notificationIcon = QString(" image from location \"file://%1\"").arg(notificationIconFile.fileName());
    }

    QString quotedTitle(title), quotedText(text);
    quotedTitle.replace("\\", "\\\\").replace("\"", "\\");
    quotedText.replace("\\", "\\\\").replace("\"", "\\");
    QString growlApp(this->mode == Notificator::Growl13 ? "Growl" : "GrowlHelperApp");
    MacNotificationHandler::instance()->sendAppleScript(script.arg(notificationApp, quotedTitle, quotedText, notificationIcon, growlApp));
}

void Notificator::notifyMacUserNotificationCenter(Class cls, const QString &title, const QString &text, const QIcon &icon) {
    // icon is not supported by the user notification center yet. OSX will use the app icon.
    MacNotificationHandler::instance()->showNotification(title, text);
}

#endif

void Notificator::notify(Class cls, const QString &title, const QString &text, const QIcon &icon, int millisTimeout)
{
    switch(mode)
    {
#ifdef USE_DBUS
    case Freedesktop:
        notifyDBus(cls, title, text, icon, millisTimeout);
        break;
#endif
    case QSystemTray:
        notifySystray(cls, title, text, icon, millisTimeout);
        break;
#ifdef Q_OS_MAC
    case UserNotificationCenter:
        notifyMacUserNotificationCenter(cls, title, text, icon);
        break;
    case Growl12:
    case Growl13:
        notifyGrowl(cls, title, text, icon);
        break;
#endif
    default:
        if(cls == Critical)
        {
            // Fall back to old fashioned pop-up dialog if critical and no other notification available
            QMessageBox::critical(parent, title, text, QMessageBox::Ok, QMessageBox::Ok);
        }
        break;
    }
}
<|endoftext|>


<commit_before>/* medStackedViewContainers.cpp ---
 *
 * Author: Julien Wintz
 * Copyright (C) 2008 - Julien Wintz, Inria.
 * Created: Thu May 13 12:39:09 2010 (+0200)
 * Version: $Id$
 * Last-Updated: Tue Jun 15 22:12:57 2010 (+0200)
 *           By: Julien Wintz
 *     Update #: 8
 */

/* Commentary:
 *
 */

/* Change log:
 *
 */

#include <QtCore>

#include "medStackedViewContainers.h"

#include "medViewContainer.h"
#include "medViewContainerCustom.h"
#include "medViewContainerMulti.h"
#include "medViewContainerSingle.h"

class medStackedViewContainersPrivate
{
public:
   QHash<QString, medViewContainer*> containers;
   QString currentName;

   QPushButton *addButton;
};

medStackedViewContainers::medStackedViewContainers(QWidget *parent) : QTabWidget(parent), d(new medStackedViewContainersPrivate)
{
    this->setTabsClosable(true);
    this->setMovable(true);

    connect(this,SIGNAL(tabCloseRequested(int)),this,SLOT(deleteContainerClicked(int)));
    connect(this,SIGNAL(currentChanged(int)),this,SLOT(onCurrentContainerChanged(int)));

    d->addButton = new QPushButton();
    d->addButton->setStyleSheet("background-image: url(:medGui/pixmaps/plus_button.png);background-position: center;background-repeat: no-repeat;");
    this->setCornerWidget(d->addButton);

    connect(d->addButton,SIGNAL(clicked()),this,SIGNAL(addTabButtonClicked()));
}

medStackedViewContainers::~medStackedViewContainers(void)
{
    delete d;

    d = NULL;
}

void medStackedViewContainers::lockTabs()
{
    this->setTabsClosable(false);
    this->setMovable(false);
    d->addButton->hide();
}

void medStackedViewContainers::unlockTabs()
{
    this->setTabsClosable(true);
    this->setMovable(true);
    d->addButton->show();
}

/*
void medStackedViewContainers::addNewTabContainer()
{
    // This slot should disappear, instead the creation signal should be sent to the parent who should call for the creation of a new tab
    QString name = "Tab ";
    name += QString::number(this->count());

    if (!this->container(name))
    {
        medViewContainer *new_container = new medViewContainerMulti();
        addContainer(name, new_container);
        this->setContainer(name);
    }
    else
        qDebug() << "Container" << name << "already exists in this configurations";
}
*/

void medStackedViewContainers::deleteContainerClicked(int index)
{
    if (this->count() > 1)
    {
        d->containers.remove(this->tabText(index));
        this->removeTab(index);
    }
}

void medStackedViewContainers::addContainer(const QString &name, medViewContainer *container)
{
    if (!container)
        return;

    d->containers[name] = container;

    connect(container, SIGNAL(focused(dtkAbstractView*)),    this, SIGNAL(focused(dtkAbstractView*)));
    connect(container, SIGNAL(dropped(const medDataIndex&)), this, SIGNAL(dropped(const medDataIndex&)));

    if (!this->count())
        d->currentName = name;
    this->addTab(container, name);
}

void medStackedViewContainers::insertContainer(int index, const QString &name, medViewContainer *container)
{
    if (!container)
        return;

    d->containers[name] = container;

    connect(container, SIGNAL(focused(dtkAbstractView*)),    this, SIGNAL(focused(dtkAbstractView*)));
    connect(container, SIGNAL(dropped(const medDataIndex&)), this, SIGNAL(dropped(const medDataIndex&)));

    if (!this->count())
        d->currentName = name;
    this->insertTab(index,container, name);
}

void medStackedViewContainers::changeCurrentContainerType(const QString &name)
{
    //qDebug() << "Changing container type to " << name << " from " << this->current()->description();
    //qDebug() << "Current index is " << this->currentIndex() << " and tab name " << this->tabText(this->currentIndex());

    if (name != this->current()->description())
    {
        medViewContainer *newTab = NULL;
        if (name == "Single")
            newTab = new medViewContainerSingle();
        else if (name == "Custom")
            newTab = new medViewContainerCustom();
        else if (name == "Multi")
            newTab = new medViewContainerMulti();

        if (newTab != NULL)
        {
            this->blockSignals(true);
            int index = this->currentIndex();
            QString tabName = this->tabText(index);
            this->removeTab(index);
            this->insertContainer(index,tabName,newTab);
            this->setCurrentIndex(index);
            this->blockSignals(false);
        }
    }
}

medViewContainer* medStackedViewContainers::container(const QString &name) const
{
    if (!d->containers.contains(name))
        return NULL;

    return d->containers[name];
}

void medStackedViewContainers::setContainer(const QString &name)
{
    if (!d->containers.contains(name))
    {
        qWarning()<<"container does not contain any container of name:" << name;
        return;
    }

    d->currentName = name;
    this->setCurrentWidget(d->containers[name]);
}

medViewContainer *medStackedViewContainers::current(void) const
{
    return dynamic_cast<medViewContainer*> (currentWidget());
}

QString medStackedViewContainers::currentName(void) const
{
    return d->currentName;
}

QList<QString> medStackedViewContainers::keys()
{
    return d->containers.keys();
}

void medStackedViewContainers::removeContainer(const QString& name)
{
    if (d->containers.contains(name))
    {
        medViewContainer* container = d->containers[name];
        //removeWidget(container);
        delete container;
        d->containers.remove(name);
    }
}

void medStackedViewContainers::onCurrentContainerChanged(int index)
{
    QString name = this->tabText(index);
    emit currentChanged(name);
}
<commit_msg>One more bug correction<commit_after>/* medStackedViewContainers.cpp ---
 *
 * Author: Julien Wintz
 * Copyright (C) 2008 - Julien Wintz, Inria.
 * Created: Thu May 13 12:39:09 2010 (+0200)
 * Version: $Id$
 * Last-Updated: Tue Jun 15 22:12:57 2010 (+0200)
 *           By: Julien Wintz
 *     Update #: 8
 */

/* Commentary:
 *
 */

/* Change log:
 *
 */

#include <QtCore>

#include "medStackedViewContainers.h"

#include "medViewContainer.h"
#include "medViewContainerCustom.h"
#include "medViewContainerMulti.h"
#include "medViewContainerSingle.h"

class medStackedViewContainersPrivate
{
public:
   QHash<QString, medViewContainer*> containers;
   QString currentName;

   QPushButton *addButton;
};

medStackedViewContainers::medStackedViewContainers(QWidget *parent) : QTabWidget(parent), d(new medStackedViewContainersPrivate)
{
    this->setTabsClosable(true);
    this->setMovable(true);

    connect(this,SIGNAL(tabCloseRequested(int)),this,SLOT(deleteContainerClicked(int)));
    connect(this,SIGNAL(currentChanged(int)),this,SLOT(onCurrentContainerChanged(int)));

    d->addButton = new QPushButton();
    d->addButton->setStyleSheet("background-image: url(:medGui/pixmaps/plus_button.png);background-position: center;background-repeat: no-repeat;");
    this->setCornerWidget(d->addButton);

    connect(d->addButton,SIGNAL(clicked()),this,SIGNAL(addTabButtonClicked()));
}

medStackedViewContainers::~medStackedViewContainers(void)
{
    delete d;

    d = NULL;
}

void medStackedViewContainers::lockTabs()
{
    this->setTabsClosable(false);
    this->setMovable(false);
    d->addButton->hide();
}

void medStackedViewContainers::unlockTabs()
{
    this->setTabsClosable(true);
    this->setMovable(true);
    d->addButton->show();
}

/*
void medStackedViewContainers::addNewTabContainer()
{
    // This slot should disappear, instead the creation signal should be sent to the parent who should call for the creation of a new tab
    QString name = "Tab ";
    name += QString::number(this->count());

    if (!this->container(name))
    {
        medViewContainer *new_container = new medViewContainerMulti();
        addContainer(name, new_container);
        this->setContainer(name);
    }
    else
        qDebug() << "Container" << name << "already exists in this configurations";
}
*/

void medStackedViewContainers::deleteContainerClicked(int index)
{
    if (this->count() > 1)
    {
        d->containers.remove(this->tabText(index));
        this->removeTab(index);
    }
}

void medStackedViewContainers::addContainer(const QString &name, medViewContainer *container)
{
    if (!container)
        return;

    d->containers[name] = container;

    connect(container, SIGNAL(focused(dtkAbstractView*)),    this, SIGNAL(focused(dtkAbstractView*)));
    connect(container, SIGNAL(dropped(const medDataIndex&)), this, SIGNAL(dropped(const medDataIndex&)));

    if (!this->count())
        d->currentName = name;
    this->addTab(container, name);
}

void medStackedViewContainers::insertContainer(int index, const QString &name, medViewContainer *container)
{
    if (!container)
        return;

    d->containers[name] = container;

    connect(container, SIGNAL(focused(dtkAbstractView*)),    this, SIGNAL(focused(dtkAbstractView*)));
    connect(container, SIGNAL(dropped(const medDataIndex&)), this, SIGNAL(dropped(const medDataIndex&)));

    if (!this->count())
        d->currentName = name;
    this->insertTab(index,container, name);
}

void medStackedViewContainers::changeCurrentContainerType(const QString &name)
{
    //qDebug() << "Changing container type to " << name << " from " << this->current()->description();
    //qDebug() << "Current index is " << this->currentIndex() << " and tab name " << this->tabText(this->currentIndex());

    if (name != this->current()->description())
    {
        medViewContainer *newTab = NULL;
        if (name == "Single")
            newTab = new medViewContainerSingle();
        else if (name == "Custom")
            newTab = new medViewContainerCustom();
        else if (name == "Multi")
            newTab = new medViewContainerMulti();

        if (newTab != NULL)
        {
            this->blockSignals(true);
            int index = this->currentIndex();
            QString tabName = this->tabText(index);
            this->removeTab(index);
            this->insertContainer(index,tabName,newTab);
            this->setCurrentIndex(index);
            this->blockSignals(false);

            this->onCurrentContainerChanged(index);
        }
    }
}

medViewContainer* medStackedViewContainers::container(const QString &name) const
{
    if (!d->containers.contains(name))
        return NULL;

    return d->containers[name];
}

void medStackedViewContainers::setContainer(const QString &name)
{
    if (!d->containers.contains(name))
    {
        qWarning()<<"container does not contain any container of name:" << name;
        return;
    }

    d->currentName = name;
    this->setCurrentWidget(d->containers[name]);
}

medViewContainer *medStackedViewContainers::current(void) const
{
    return dynamic_cast<medViewContainer*> (currentWidget());
}

QString medStackedViewContainers::currentName(void) const
{
    return d->currentName;
}

QList<QString> medStackedViewContainers::keys()
{
    return d->containers.keys();
}

void medStackedViewContainers::removeContainer(const QString& name)
{
    if (d->containers.contains(name))
    {
        medViewContainer* container = d->containers[name];
        //removeWidget(container);
        delete container;
        d->containers.remove(name);
    }
}

void medStackedViewContainers::onCurrentContainerChanged(int index)
{
    QString name = this->tabText(index);
    emit currentChanged(name);
}
<|endoftext|>


<commit_before>#include "statistics/StatisticalSerie1D.hpp"

StatisticalSerie1D::StatisticalSerie1D(Sample* sample)
        : sample(sample), dataSource(sample->getDataSource()) {
    this->computeMode();
    this->computeAverage();
    this->computeMedian();
    this->computeStandardDeviation();
    this->computeRange();
    this->computeCoefficientOfVariation();
}

void StatisticalSerie1D::computeMode() {
    Data1DIterator it(this->dataSource.getData());
    this->mode.fill(0);
    unsigned highestCount = 0;
    unsigned currentMode = 0;

    while(!it.end()) {
        if(it.getY() > highestCount) {
            this->mode.fill(0);
            this->mode[0] = it.getX();
            highestCount = it.getY();
            currentMode = 1;
        } else if(it.getY() == highestCount && currentMode < this->mode.size()) {
            this->mode[currentMode++] = it.getX();
        }
        ++it;
    }
}

void StatisticalSerie1D::computeAverage() {
    Data1DIterator it(this->dataSource.getData());
    float sum = 0;

    while(!it.end()){
        sum += it.getX() * it.getY();
        ++it;
    }

    this->average = sum / this->dataSource.getTotalCount();
}

void StatisticalSerie1D::computeMedian() {
    const List<Data*>& data(this->dataSource.getData());
    unsigned totalCount = this->dataSource.getTotalCount();
    unsigned middle = totalCount / 2;

    // Discrete stuff
    if(this->dataSource.getType() == DISCRETE) {
        // Rebuild value list
        List<float> values;
        Data1DIterator it(data);
        while(!it.end()) {
            for(unsigned i = 0; i < it.getY(); ++i) {
                values.add(it.getX());
            }
            ++it;
        }

        if(totalCount % 2 == 0) { // Odd
            this->median = (values.get(middle) + values.get(middle + 1)) / 2;
        } else {
            this->median = values.get(middle);
        }
        return;
    }

    // Continous stuff

    // Looking up the interval containing the median
    Data1DIterator it(data);
    unsigned count = 0;
    const Data1D* data1D = NULL;
    while(!it.end()) {
        data1D = it++.get();
        if(count + data1D->getCount() > middle) {
            break;
        }
        count += data1D->getCount(); // Accumulate counts in intervals
    }

    Sanity::truthness(data1D != NULL, "Middle interval of continous data not found when computing median");

    this->median = data1D->getValue() // Start of interval
        + static_cast<const ContinousDataSource&>(this->dataSource).getIntervalSizes() / data1D->getCount()
        * (data1D->getCount() - (middle - count)); // Position of the middle in the interval
}

void StatisticalSerie1D::computeStandardDeviation() {
    Data1DIterator it(this->dataSource.getData());
    float sum = 0;

    while(!it.end()) {
        sum += (it.getX() - this->average) * (it.getX() - this->average) * it.getY();
        ++it;
    }

    this->standardDeviation = sqrt(sum / this->dataSource.getTotalCount());
}

void StatisticalSerie1D::computeRange() {
    const List<Data*>& data(this->dataSource.getData());
    this->range = static_cast<Data1D*>(data.get(data.size() - 1))->getValue()
        - static_cast<Data1D*>(data.get(0))->getValue();
}

void StatisticalSerie1D::computeCoefficientOfVariation() {
    this->coefficientOfVariation = this->standardDeviation / this->average / 100;
}
<commit_msg>Modify median computation to take last commit into account<commit_after>#include "statistics/StatisticalSerie1D.hpp"

StatisticalSerie1D::StatisticalSerie1D(Sample* sample)
        : sample(sample), dataSource(sample->getDataSource()) {
    this->computeMode();
    this->computeAverage();
    this->computeMedian();
    this->computeStandardDeviation();
    this->computeRange();
    this->computeCoefficientOfVariation();
}

void StatisticalSerie1D::computeMode() {
    Data1DIterator it(this->dataSource.getData());
    this->mode.fill(0);
    unsigned highestCount = 0;
    unsigned currentMode = 0;

    while(!it.end()) {
        if(it.getY() > highestCount) {
            this->mode.fill(0);
            this->mode[0] = it.getX();
            highestCount = it.getY();
            currentMode = 1;
        } else if(it.getY() == highestCount && currentMode < this->mode.size()) {
            this->mode[currentMode++] = it.getX();
        }
        ++it;
    }
}

void StatisticalSerie1D::computeAverage() {
    Data1DIterator it(this->dataSource.getData());
    float sum = 0;

    while(!it.end()){
        sum += it.getX() * it.getY();
        ++it;
    }

    this->average = sum / this->dataSource.getTotalCount();
}

void StatisticalSerie1D::computeMedian() {
    const List<Data*>& data(this->dataSource.getData());
    unsigned totalCount = this->dataSource.getTotalCount();
    unsigned middle = totalCount / 2;

    // Discrete stuff
    if(this->dataSource.getType() == DISCRETE) {
        // Rebuild value list
        List<float> values;
        Data1DIterator it(data);
        while(!it.end()) {
            for(unsigned i = 0; i < it.getY(); ++i) {
                values.add(it.getX());
            }
            ++it;
        }

        if(totalCount % 2 == 0) { // Odd
            this->median = (values.get(middle) + values.get(middle + 1)) / 2;
        } else {
            this->median = values.get(middle);
        }
        return;
    }

    // Continous stuff

    // Looking up the interval containing the median
    Data1DIterator it(data);
    unsigned count = 0;
    const Data1D* data1D = NULL;
    while(!it.end()) {
        data1D = it++.get();
        if(count + data1D->getCount() > middle) {
            break;
        }
        count += data1D->getCount(); // Accumulate counts in intervals
    }

    Sanity::truthness(data1D != NULL, "Middle interval of continous data not found when computing median");

    float interval = static_cast<const ContinousDataSource&>(this->dataSource).getIntervalSizes();
    this->median = data1D->getValue() - interval / 2 // Start of interval
        + interval / data1D->getCount()
        * (data1D->getCount() - (middle - count)); // Position of the middle in the interval
}

void StatisticalSerie1D::computeStandardDeviation() {
    Data1DIterator it(this->dataSource.getData());
    float sum = 0;

    while(!it.end()) {
        sum += (it.getX() - this->average) * (it.getX() - this->average) * it.getY();
        ++it;
    }

    this->standardDeviation = sqrt(sum / this->dataSource.getTotalCount());
}

void StatisticalSerie1D::computeRange() {
    const List<Data*>& data(this->dataSource.getData());
    this->range = static_cast<Data1D*>(data.get(data.size() - 1))->getValue()
        - static_cast<Data1D*>(data.get(0))->getValue();
}

void StatisticalSerie1D::computeCoefficientOfVariation() {
    this->coefficientOfVariation = this->standardDeviation / this->average / 100;
}
<|endoftext|>


<commit_before>/*
 * robotStateRT.cpp
 *
 * ----------------------------------------------------------------------------
 * "THE BEER-WARE LICENSE" (Revision 42):
 * <thomas.timm.dk@gmail.com> wrote this file.  As long as you retain this notice you
 * can do whatever you want with this stuff. If we meet some day, and you think
 * this stuff is worth it, you can buy me a beer in return.   Thomas Timm Andersen
 * ----------------------------------------------------------------------------
 */

#include "ur_modern_driver/robot_state_RT.h"

RobotStateRT::RobotStateRT(std::condition_variable& msg_cond) {
	version_ = 0.0;
	time_ = 0.0;
	q_target_.assign(6, 0.0);
	qd_target_.assign(6, 0.0);
	qdd_target_.assign(6, 0.0);
	i_target_.assign(6, 0.0);
	m_target_.assign(6, 0.0);
	q_actual_.assign(6, 0.0);
	qd_actual_.assign(6, 0.0);
	i_actual_.assign(6, 0.0);
	i_control_.assign(6, 0.0);
	tool_vector_actual_.assign(6, 0.0);
	tcp_speed_actual_.assign(6, 0.0);
	tcp_force_.assign(6, 0.0);
	tool_vector_target_.assign(6, 0.0);
	tcp_speed_target_.assign(6, 0.0);
	digital_input_bits_.assign(64, false);
	motor_temperatures_.assign(6, 0.0);
	controller_timer_ = 0.0;
	robot_mode_ = 0.0;
	joint_modes_.assign(6, 0.0);
	safety_mode_ = 0.0;
	tool_accelerometer_values_.assign(3, 0.0);
	speed_scaling_ = 0.0;
	linear_momentum_norm_ = 0.0;
	v_main_ = 0.0;
	v_robot_ = 0.0;
	i_robot_ = 0.0;
	v_actual_.assign(6, 0.0);
	new_data_available_ = false;
	pMsg_cond_ = &msg_cond;
}

RobotStateRT::~RobotStateRT() {
	/* Make sure nobody is waiting after this thread is destroyed */
	new_data_available_ = true;
	pMsg_cond_->notify_all();
}

bool RobotStateRT::getNewDataAvailable() {
	return new_data_available_;
}

void RobotStateRT::finishedReading() {
	new_data_available_ = false;
}

double RobotStateRT::ntohd(uint64_t nf) {
	double x;
	nf = be64toh(nf);
	memcpy(&x, &nf, sizeof(x));
	return x;
}

std::vector<double> RobotStateRT::unpackVector(uint8_t * buf, int start_index,
		int nr_of_vals) {
	uint64_t q;
	std::vector<double> ret;
	for (int i = 0; i < nr_of_vals; i++) {
		memcpy(&q, &buf[start_index + i * sizeof(q)], sizeof(q));
		ret.push_back(ntohd(q));
	}
	return ret;
}

std::vector<bool> RobotStateRT::unpackDigitalInputBits(int64_t data) {
	std::vector<bool> ret;
	for (int i = 0; i < 64; i++) {
		ret.push_back((data & (1 << i)) >> i);
	}
	return ret;
}

void RobotStateRT::setVersion(double ver) {
	val_lock_.lock();
	version_ = ver;
	val_lock_.unlock();
}

double RobotStateRT::getVersion() {
	double ret;
	val_lock_.lock();
	ret = version_;
	val_lock_.unlock();
	return ret;
}
double RobotStateRT::getTime() {
	double ret;
	val_lock_.lock();
	ret = time_;
	val_lock_.unlock();
	return ret;
}
std::vector<double> RobotStateRT::getQTarget() {
	std::vector<double> ret;
	val_lock_.lock();
	ret = q_target_;
	val_lock_.unlock();
	return ret;
}
std::vector<double> RobotStateRT::getQdTarget() {
	std::vector<double> ret;
	val_lock_.lock();
	ret = q_target_;
	val_lock_.unlock();
	return ret;
}
std::vector<double> RobotStateRT::getQddTarget() {
	std::vector<double> ret;
	val_lock_.lock();
	ret = qdd_target_;
	val_lock_.unlock();
	return ret;
}
std::vector<double> RobotStateRT::getITarget() {
	std::vector<double> ret;
	val_lock_.lock();
	ret = i_target_;
	val_lock_.unlock();
	return ret;
}
std::vector<double> RobotStateRT::getMTarget() {
	std::vector<double> ret;
	val_lock_.lock();
	ret = m_target_;
	val_lock_.unlock();
	return ret;
}
std::vector<double> RobotStateRT::getQActual() {
	std::vector<double> ret;
	val_lock_.lock();
	ret = q_actual_;
	val_lock_.unlock();
	return ret;
}
std::vector<double> RobotStateRT::getQdActual() {
	std::vector<double> ret;
	val_lock_.lock();
	ret = qd_actual_;
	val_lock_.unlock();
	return ret;
}
std::vector<double> RobotStateRT::getIActual() {
	std::vector<double> ret;
	val_lock_.lock();
	ret = i_actual_;
	val_lock_.unlock();
	return ret;
}
std::vector<double> RobotStateRT::getIControl() {
	std::vector<double> ret;
	val_lock_.lock();
	ret = i_control_;
	val_lock_.unlock();
	return ret;
}
std::vector<double> RobotStateRT::getToolVectorActual() {
	std::vector<double> ret;
	val_lock_.lock();
	ret = tool_vector_actual_;
	val_lock_.unlock();
	return ret;
}
std::vector<double> RobotStateRT::getTcpSpeedActual() {
	std::vector<double> ret;
	val_lock_.lock();
	ret = tcp_speed_actual_;
	val_lock_.unlock();
	return ret;
}
std::vector<double> RobotStateRT::getTcpForce() {
	std::vector<double> ret;
	val_lock_.lock();
	ret = tcp_force_;
	val_lock_.unlock();
	return ret;
}
std::vector<double> RobotStateRT::getToolVectorTarget() {
	std::vector<double> ret;
	val_lock_.lock();
	ret = tool_vector_target_;
	val_lock_.unlock();
	return ret;
}
std::vector<double> RobotStateRT::getTcpSpeedTarget() {
	std::vector<double> ret;
	val_lock_.lock();
	ret = tcp_speed_target_;
	val_lock_.unlock();
	return ret;
}
std::vector<bool> RobotStateRT::getDigitalInputBits() {
	std::vector<bool> ret;
	val_lock_.lock();
	ret = digital_input_bits_;
	val_lock_.unlock();
	return ret;
}
std::vector<double> RobotStateRT::getMotorTemperatures() {
	std::vector<double> ret;
	val_lock_.lock();
	ret = motor_temperatures_;
	val_lock_.unlock();
	return ret;
}
double RobotStateRT::getControllerTimer() {
	double ret;
	val_lock_.lock();
	ret = controller_timer_;
	val_lock_.unlock();
	return ret;
}
double RobotStateRT::getRobotMode() {
	double ret;
	val_lock_.lock();
	ret = robot_mode_;
	val_lock_.unlock();
	return ret;
}
std::vector<double> RobotStateRT::getJointModes() {
	std::vector<double> ret;
	val_lock_.lock();
	ret = joint_modes_;
	val_lock_.unlock();
	return ret;
}
double RobotStateRT::getSafety_mode() {
	double ret;
	val_lock_.lock();
	ret = safety_mode_;
	val_lock_.unlock();
	return ret;
}
std::vector<double> RobotStateRT::getToolAccelerometerValues() {
	std::vector<double> ret;
	val_lock_.lock();
	ret = tool_accelerometer_values_;
	val_lock_.unlock();
	return ret;
}
double RobotStateRT::getSpeedScaling() {
	double ret;
	val_lock_.lock();
	ret = speed_scaling_;
	val_lock_.unlock();
	return ret;
}
double RobotStateRT::getLinearMomentumNorm() {
	double ret;
	val_lock_.lock();
	ret = linear_momentum_norm_;
	val_lock_.unlock();
	return ret;
}
double RobotStateRT::getVMain() {
	double ret;
	val_lock_.lock();
	ret = v_main_;
	val_lock_.unlock();
	return ret;
}
double RobotStateRT::getVRobot() {
	double ret;
	val_lock_.lock();
	ret = v_robot_;
	val_lock_.unlock();
	return ret;
}
double RobotStateRT::getIRobot() {
	double ret;
	val_lock_.lock();
	ret = i_robot_;
	val_lock_.unlock();
	return ret;
}
std::vector<double> RobotStateRT::getVActual() {
	std::vector<double> ret;
	val_lock_.lock();
	ret = v_actual_;
	val_lock_.unlock();
	return ret;
}
void RobotStateRT::unpack(uint8_t * buf) {
	int64_t digital_input_bits;
	uint64_t unpack_to;
	uint16_t offset = 0;
	val_lock_.lock();
	int len;
	memcpy(&len, &buf[offset], sizeof(len));

	offset += sizeof(len);
	len = ntohl(len);
	if (version_ < 3.1 & len != 1044) {
		//In 3.0, every 4th? package is malformed...?
		//printf("Len: %i\n", len);
		val_lock_.unlock();
		return;
	}
	memcpy(&unpack_to, &buf[offset], sizeof(unpack_to));
	time_ = RobotStateRT::ntohd(unpack_to);
	offset += sizeof(double);
	q_target_ = unpackVector(buf, offset, 6);
	offset += sizeof(double) * 6;
	qd_target_ = unpackVector(buf, offset, 6);
	offset += sizeof(double) * 6;
	qdd_target_ = unpackVector(buf, offset, 6);
	offset += sizeof(double) * 6;
	i_target_ = unpackVector(buf, offset, 6);
	offset += sizeof(double) * 6;
	m_target_ = unpackVector(buf, offset, 6);
	offset += sizeof(double) * 6;
	q_actual_ = unpackVector(buf, offset, 6);
	offset += sizeof(double) * 6;
	qd_actual_ = unpackVector(buf, offset, 6);
	offset += sizeof(double) * 6;
	i_actual_ = unpackVector(buf, offset, 6);
	offset += sizeof(double) * 6;
	if (version_ <= 1.8) {
		if (version_ != 1.6)
			tool_accelerometer_values_ = unpackVector(buf, offset, 3);
		offset += sizeof(double) * (3 + 15);
		tcp_force_ = unpackVector(buf, offset, 6);
		offset += sizeof(double) * 6;
		tool_vector_actual_ = unpackVector(buf, offset, 6);
		offset += sizeof(double) * 6;
		tcp_speed_actual_ = unpackVector(buf, offset, 6);
	} else {
		i_control_ = unpackVector(buf, offset, 6);
		offset += sizeof(double) * 6;
		tool_vector_actual_ = unpackVector(buf, offset, 6);
		offset += sizeof(double) * 6;
		tcp_speed_actual_ = unpackVector(buf, offset, 6);
		offset += sizeof(double) * 6;
		tcp_force_ = unpackVector(buf, offset, 6);
		offset += sizeof(double) * 6;
		tool_vector_target_ = unpackVector(buf, offset, 6);
		offset += sizeof(double) * 6;
		tcp_speed_target_ = unpackVector(buf, offset, 6);
	}
	offset += sizeof(double) * 6;

	memcpy(&digital_input_bits, &buf[offset], sizeof(digital_input_bits));
	digital_input_bits_ = unpackDigitalInputBits(be64toh(digital_input_bits));
	offset += sizeof(double);
	motor_temperatures_ = unpackVector(buf, offset, 6);
	offset += sizeof(double) * 6;
	memcpy(&unpack_to, &buf[offset], sizeof(unpack_to));
	controller_timer_ = ntohd(unpack_to);
	if (version_ > 1.6) {
		offset += sizeof(double) * 2;
		memcpy(&unpack_to, &buf[offset], sizeof(unpack_to));
		robot_mode_ = ntohd(unpack_to);
		if (version_ > 1.7) {
			offset += sizeof(double);
			joint_modes_ = unpackVector(buf, offset, 6);
		}
	}
	if (version_ > 1.8) {
		offset += sizeof(double) * 6;
		memcpy(&unpack_to, &buf[offset], sizeof(unpack_to));
		safety_mode_ = ntohd(unpack_to);
		offset += sizeof(double);
		tool_accelerometer_values_ = unpackVector(buf, offset, 3);
		offset += sizeof(double) * 3;
		memcpy(&unpack_to, &buf[offset], sizeof(unpack_to));
		speed_scaling_ = ntohd(unpack_to);
		offset += sizeof(double);
		memcpy(&unpack_to, &buf[offset], sizeof(unpack_to));
		linear_momentum_norm_ = ntohd(unpack_to);
		offset += sizeof(double);
		memcpy(&unpack_to, &buf[offset], sizeof(unpack_to));
		v_main_ = ntohd(unpack_to);
		offset += sizeof(double);
		memcpy(&unpack_to, &buf[offset], sizeof(unpack_to));
		v_robot_ = ntohd(unpack_to);
		offset += sizeof(double);
		memcpy(&unpack_to, &buf[offset], sizeof(unpack_to));
		i_robot_ = ntohd(unpack_to);
		offset += sizeof(double);
		v_actual_ = unpackVector(buf, offset, 6);
	}
	val_lock_.unlock();
	new_data_available_ = true;
	pMsg_cond_->notify_all();

}

<commit_msg>Fixed version bound check in RT message parsing<commit_after>/*
 * robotStateRT.cpp
 *
 * ----------------------------------------------------------------------------
 * "THE BEER-WARE LICENSE" (Revision 42):
 * <thomas.timm.dk@gmail.com> wrote this file.  As long as you retain this notice you
 * can do whatever you want with this stuff. If we meet some day, and you think
 * this stuff is worth it, you can buy me a beer in return.   Thomas Timm Andersen
 * ----------------------------------------------------------------------------
 */

#include "ur_modern_driver/robot_state_RT.h"

RobotStateRT::RobotStateRT(std::condition_variable& msg_cond) {
	version_ = 0.0;
	time_ = 0.0;
	q_target_.assign(6, 0.0);
	qd_target_.assign(6, 0.0);
	qdd_target_.assign(6, 0.0);
	i_target_.assign(6, 0.0);
	m_target_.assign(6, 0.0);
	q_actual_.assign(6, 0.0);
	qd_actual_.assign(6, 0.0);
	i_actual_.assign(6, 0.0);
	i_control_.assign(6, 0.0);
	tool_vector_actual_.assign(6, 0.0);
	tcp_speed_actual_.assign(6, 0.0);
	tcp_force_.assign(6, 0.0);
	tool_vector_target_.assign(6, 0.0);
	tcp_speed_target_.assign(6, 0.0);
	digital_input_bits_.assign(64, false);
	motor_temperatures_.assign(6, 0.0);
	controller_timer_ = 0.0;
	robot_mode_ = 0.0;
	joint_modes_.assign(6, 0.0);
	safety_mode_ = 0.0;
	tool_accelerometer_values_.assign(3, 0.0);
	speed_scaling_ = 0.0;
	linear_momentum_norm_ = 0.0;
	v_main_ = 0.0;
	v_robot_ = 0.0;
	i_robot_ = 0.0;
	v_actual_.assign(6, 0.0);
	new_data_available_ = false;
	pMsg_cond_ = &msg_cond;
}

RobotStateRT::~RobotStateRT() {
	/* Make sure nobody is waiting after this thread is destroyed */
	new_data_available_ = true;
	pMsg_cond_->notify_all();
}

bool RobotStateRT::getNewDataAvailable() {
	return new_data_available_;
}

void RobotStateRT::finishedReading() {
	new_data_available_ = false;
}

double RobotStateRT::ntohd(uint64_t nf) {
	double x;
	nf = be64toh(nf);
	memcpy(&x, &nf, sizeof(x));
	return x;
}

std::vector<double> RobotStateRT::unpackVector(uint8_t * buf, int start_index,
		int nr_of_vals) {
	uint64_t q;
	std::vector<double> ret;
	for (int i = 0; i < nr_of_vals; i++) {
		memcpy(&q, &buf[start_index + i * sizeof(q)], sizeof(q));
		ret.push_back(ntohd(q));
	}
	return ret;
}

std::vector<bool> RobotStateRT::unpackDigitalInputBits(int64_t data) {
	std::vector<bool> ret;
	for (int i = 0; i < 64; i++) {
		ret.push_back((data & (1 << i)) >> i);
	}
	return ret;
}

void RobotStateRT::setVersion(double ver) {
	val_lock_.lock();
	version_ = ver;
	val_lock_.unlock();
}

double RobotStateRT::getVersion() {
	double ret;
	val_lock_.lock();
	ret = version_;
	val_lock_.unlock();
	return ret;
}
double RobotStateRT::getTime() {
	double ret;
	val_lock_.lock();
	ret = time_;
	val_lock_.unlock();
	return ret;
}
std::vector<double> RobotStateRT::getQTarget() {
	std::vector<double> ret;
	val_lock_.lock();
	ret = q_target_;
	val_lock_.unlock();
	return ret;
}
std::vector<double> RobotStateRT::getQdTarget() {
	std::vector<double> ret;
	val_lock_.lock();
	ret = q_target_;
	val_lock_.unlock();
	return ret;
}
std::vector<double> RobotStateRT::getQddTarget() {
	std::vector<double> ret;
	val_lock_.lock();
	ret = qdd_target_;
	val_lock_.unlock();
	return ret;
}
std::vector<double> RobotStateRT::getITarget() {
	std::vector<double> ret;
	val_lock_.lock();
	ret = i_target_;
	val_lock_.unlock();
	return ret;
}
std::vector<double> RobotStateRT::getMTarget() {
	std::vector<double> ret;
	val_lock_.lock();
	ret = m_target_;
	val_lock_.unlock();
	return ret;
}
std::vector<double> RobotStateRT::getQActual() {
	std::vector<double> ret;
	val_lock_.lock();
	ret = q_actual_;
	val_lock_.unlock();
	return ret;
}
std::vector<double> RobotStateRT::getQdActual() {
	std::vector<double> ret;
	val_lock_.lock();
	ret = qd_actual_;
	val_lock_.unlock();
	return ret;
}
std::vector<double> RobotStateRT::getIActual() {
	std::vector<double> ret;
	val_lock_.lock();
	ret = i_actual_;
	val_lock_.unlock();
	return ret;
}
std::vector<double> RobotStateRT::getIControl() {
	std::vector<double> ret;
	val_lock_.lock();
	ret = i_control_;
	val_lock_.unlock();
	return ret;
}
std::vector<double> RobotStateRT::getToolVectorActual() {
	std::vector<double> ret;
	val_lock_.lock();
	ret = tool_vector_actual_;
	val_lock_.unlock();
	return ret;
}
std::vector<double> RobotStateRT::getTcpSpeedActual() {
	std::vector<double> ret;
	val_lock_.lock();
	ret = tcp_speed_actual_;
	val_lock_.unlock();
	return ret;
}
std::vector<double> RobotStateRT::getTcpForce() {
	std::vector<double> ret;
	val_lock_.lock();
	ret = tcp_force_;
	val_lock_.unlock();
	return ret;
}
std::vector<double> RobotStateRT::getToolVectorTarget() {
	std::vector<double> ret;
	val_lock_.lock();
	ret = tool_vector_target_;
	val_lock_.unlock();
	return ret;
}
std::vector<double> RobotStateRT::getTcpSpeedTarget() {
	std::vector<double> ret;
	val_lock_.lock();
	ret = tcp_speed_target_;
	val_lock_.unlock();
	return ret;
}
std::vector<bool> RobotStateRT::getDigitalInputBits() {
	std::vector<bool> ret;
	val_lock_.lock();
	ret = digital_input_bits_;
	val_lock_.unlock();
	return ret;
}
std::vector<double> RobotStateRT::getMotorTemperatures() {
	std::vector<double> ret;
	val_lock_.lock();
	ret = motor_temperatures_;
	val_lock_.unlock();
	return ret;
}
double RobotStateRT::getControllerTimer() {
	double ret;
	val_lock_.lock();
	ret = controller_timer_;
	val_lock_.unlock();
	return ret;
}
double RobotStateRT::getRobotMode() {
	double ret;
	val_lock_.lock();
	ret = robot_mode_;
	val_lock_.unlock();
	return ret;
}
std::vector<double> RobotStateRT::getJointModes() {
	std::vector<double> ret;
	val_lock_.lock();
	ret = joint_modes_;
	val_lock_.unlock();
	return ret;
}
double RobotStateRT::getSafety_mode() {
	double ret;
	val_lock_.lock();
	ret = safety_mode_;
	val_lock_.unlock();
	return ret;
}
std::vector<double> RobotStateRT::getToolAccelerometerValues() {
	std::vector<double> ret;
	val_lock_.lock();
	ret = tool_accelerometer_values_;
	val_lock_.unlock();
	return ret;
}
double RobotStateRT::getSpeedScaling() {
	double ret;
	val_lock_.lock();
	ret = speed_scaling_;
	val_lock_.unlock();
	return ret;
}
double RobotStateRT::getLinearMomentumNorm() {
	double ret;
	val_lock_.lock();
	ret = linear_momentum_norm_;
	val_lock_.unlock();
	return ret;
}
double RobotStateRT::getVMain() {
	double ret;
	val_lock_.lock();
	ret = v_main_;
	val_lock_.unlock();
	return ret;
}
double RobotStateRT::getVRobot() {
	double ret;
	val_lock_.lock();
	ret = v_robot_;
	val_lock_.unlock();
	return ret;
}
double RobotStateRT::getIRobot() {
	double ret;
	val_lock_.lock();
	ret = i_robot_;
	val_lock_.unlock();
	return ret;
}
std::vector<double> RobotStateRT::getVActual() {
	std::vector<double> ret;
	val_lock_.lock();
	ret = v_actual_;
	val_lock_.unlock();
	return ret;
}
void RobotStateRT::unpack(uint8_t * buf) {
	int64_t digital_input_bits;
	uint64_t unpack_to;
	uint16_t offset = 0;
	val_lock_.lock();
	int len;
	memcpy(&len, &buf[offset], sizeof(len));

	offset += sizeof(len);
	len = ntohl(len);
	if (version_ > 3. & version_ < 3.1 & len != 1044) {
		//In 3.0, every 4th? package is malformed...?
		//printf("Len: %i\n", len);
		val_lock_.unlock();
		return;
	}
	memcpy(&unpack_to, &buf[offset], sizeof(unpack_to));
	time_ = RobotStateRT::ntohd(unpack_to);
	offset += sizeof(double);
	q_target_ = unpackVector(buf, offset, 6);
	offset += sizeof(double) * 6;
	qd_target_ = unpackVector(buf, offset, 6);
	offset += sizeof(double) * 6;
	qdd_target_ = unpackVector(buf, offset, 6);
	offset += sizeof(double) * 6;
	i_target_ = unpackVector(buf, offset, 6);
	offset += sizeof(double) * 6;
	m_target_ = unpackVector(buf, offset, 6);
	offset += sizeof(double) * 6;
	q_actual_ = unpackVector(buf, offset, 6);
	offset += sizeof(double) * 6;
	qd_actual_ = unpackVector(buf, offset, 6);
	offset += sizeof(double) * 6;
	i_actual_ = unpackVector(buf, offset, 6);
	offset += sizeof(double) * 6;
	if (version_ <= 1.8) {
		if (version_ != 1.6)
			tool_accelerometer_values_ = unpackVector(buf, offset, 3);
		offset += sizeof(double) * (3 + 15);
		tcp_force_ = unpackVector(buf, offset, 6);
		offset += sizeof(double) * 6;
		tool_vector_actual_ = unpackVector(buf, offset, 6);
		offset += sizeof(double) * 6;
		tcp_speed_actual_ = unpackVector(buf, offset, 6);
	} else {
		i_control_ = unpackVector(buf, offset, 6);
		offset += sizeof(double) * 6;
		tool_vector_actual_ = unpackVector(buf, offset, 6);
		offset += sizeof(double) * 6;
		tcp_speed_actual_ = unpackVector(buf, offset, 6);
		offset += sizeof(double) * 6;
		tcp_force_ = unpackVector(buf, offset, 6);
		offset += sizeof(double) * 6;
		tool_vector_target_ = unpackVector(buf, offset, 6);
		offset += sizeof(double) * 6;
		tcp_speed_target_ = unpackVector(buf, offset, 6);
	}
	offset += sizeof(double) * 6;

	memcpy(&digital_input_bits, &buf[offset], sizeof(digital_input_bits));
	digital_input_bits_ = unpackDigitalInputBits(be64toh(digital_input_bits));
	offset += sizeof(double);
	motor_temperatures_ = unpackVector(buf, offset, 6);
	offset += sizeof(double) * 6;
	memcpy(&unpack_to, &buf[offset], sizeof(unpack_to));
	controller_timer_ = ntohd(unpack_to);
	if (version_ > 1.6) {
		offset += sizeof(double) * 2;
		memcpy(&unpack_to, &buf[offset], sizeof(unpack_to));
		robot_mode_ = ntohd(unpack_to);
		if (version_ > 1.7) {
			offset += sizeof(double);
			joint_modes_ = unpackVector(buf, offset, 6);
		}
	}
	if (version_ > 1.8) {
		offset += sizeof(double) * 6;
		memcpy(&unpack_to, &buf[offset], sizeof(unpack_to));
		safety_mode_ = ntohd(unpack_to);
		offset += sizeof(double);
		tool_accelerometer_values_ = unpackVector(buf, offset, 3);
		offset += sizeof(double) * 3;
		memcpy(&unpack_to, &buf[offset], sizeof(unpack_to));
		speed_scaling_ = ntohd(unpack_to);
		offset += sizeof(double);
		memcpy(&unpack_to, &buf[offset], sizeof(unpack_to));
		linear_momentum_norm_ = ntohd(unpack_to);
		offset += sizeof(double);
		memcpy(&unpack_to, &buf[offset], sizeof(unpack_to));
		v_main_ = ntohd(unpack_to);
		offset += sizeof(double);
		memcpy(&unpack_to, &buf[offset], sizeof(unpack_to));
		v_robot_ = ntohd(unpack_to);
		offset += sizeof(double);
		memcpy(&unpack_to, &buf[offset], sizeof(unpack_to));
		i_robot_ = ntohd(unpack_to);
		offset += sizeof(double);
		v_actual_ = unpackVector(buf, offset, 6);
	}
	val_lock_.unlock();
	new_data_available_ = true;
	pMsg_cond_->notify_all();

}

<|endoftext|>


<commit_before>#include "testApp.h"

//--------------------------------------------------------------
void testApp::setup(){
    ofBackground(0,0,0);
    ofSetBackgroundAuto(false);
    isFullScreen = false;
    ofSetFrameRate(30);

    masterCounter = 0;
    direction = 1; //count up

    // OSC STUFF
    receiver.setup(PORT);
    meters = new float[7];

    //RECT STUFF
    rectX = 0;
    rectY = 0;
    rectSize = 30;
    rectSpacing = 0;
    numYRects = ofGetWidth()/rectSize-rectSpacing;
    numXRects = ofGetHeight()/rectSize-rectSpacing;
    numRects = numYRects*numXRects;
    rectCount = 0;
    ofLogNotice("\n numYRects: "+ofToString(numYRects)+"\n numXRects: "+ofToString(numXRects)+"\n numRects: "+ofToString(numRects));
}

//--------------------------------------------------------------
void testApp::update(){

	parseOSCMessages();

    // FUN STUFF
    masterCounter+=direction;
    if (masterCounter > 2000) {
        direction = -1;
    }
    if (masterCounter < -2000) {
        direction = 1;
    }

}

//--------------------------------------------------------------
void testApp::draw(){

    //drawHorizon();

    // Structured rectangles

    int xPos = ofGetWidth()/2+ofGetWidth()/2*meters[4]; //percussion
    int yPos = ofGetHeight()/2;
    int rectSize = 100;
    ofSetColor(0, 255*meters[4], 0);
    ofRect(xPos, yPos, rectSize, rectSize);

}

//--------------------------------------------------------------
void testApp::drawHorizon() {
    //Abstract line stuff
    for (int i = 0; i < ofGetWidth(); i++) {

        // set the color for each line
        int r = meters[0]*255;
        int g = meters[1]*255;
        int b = meters[2]*255;

        // line start and destination
        int xStart = i;
        int yStart = ofGetHeight()/2;
        int xDest = i*sin(i)*400; //400 is arbitrary.
        int yDest = i*cos(i)*masterCounter*meters[1];

        //shake the signal
        if (masterCounter%2 == 0) {
            yStart += meters[1]*10;
            xDest += xDest*meters[1];
            yDest += yDest*meters[1];
        }
        else {
            yStart -= meters[1]*10;
            xDest -= xDest*meters[1];
            yDest -= yDest*meters[1];
        }

        ofSetColor(r, g, b); //Replace this with pixel colors from feed
        ofLine(xStart, yStart, xDest, yDest);
    }
}
//--------------------------------------------------------------
void testApp::parseOSCMessages() {
    // check for waiting messages
	while(receiver.hasWaitingMessages()){
		// get the next message
		ofxOscMessage m;
		receiver.getNextMessage(&m);

		// check for meter messages
        if(m.getAddress() == "/main/meter") {
            //Go through arguments, get them as floats
            for (int i = 0; i < m.getNumArgs(); i++) {
                meters[i] = m.getArgAsFloat(i);
               // ofLogNotice("meter0"+ofToString(i)+": "+ofToString(meters[i]));
            }
        }
	}
}

//--------------------------------------------------------------
void testApp::keyPressed(int key){
    if (key == 'f' || 'F') {
        isFullScreen = !isFullScreen;
        ofSetFullscreen(isFullScreen);
    }

}

//--------------------------------------------------------------
void testApp::keyReleased(int key){

}

//--------------------------------------------------------------
void testApp::mouseMoved(int x, int y ){

}

//--------------------------------------------------------------
void testApp::mouseDragged(int x, int y, int button){

}

//--------------------------------------------------------------
void testApp::mousePressed(int x, int y, int button){

}

//--------------------------------------------------------------
void testApp::mouseReleased(int x, int y, int button){

}

//--------------------------------------------------------------
void testApp::windowResized(int w, int h){

}

//--------------------------------------------------------------
void testApp::gotMessage(ofMessage msg){

}

//--------------------------------------------------------------
void testApp::dragEvent(ofDragInfo dragInfo){

}
<commit_msg>triggering<commit_after>#include "testApp.h"

//--------------------------------------------------------------
void testApp::setup(){
    ofBackground(0,0,0);
    ofSetBackgroundAuto(false);
    isFullScreen = false;
    ofSetFrameRate(30);

    masterCounter = 0;
    direction = 1; //count up

    // OSC STUFF
    receiver.setup(PORT);
    meters = new float[7];

    //RECT STUFF
    rectX = 0;
    rectY = 0;
    rectSize = 30;
    rectSpacing = 0;
    numYRects = ofGetWidth()/rectSize-rectSpacing;
    numXRects = ofGetHeight()/rectSize-rectSpacing;
    numRects = numYRects*numXRects;
    rectCount = 0;
    ofLogNotice("\n numYRects: "+ofToString(numYRects)+"\n numXRects: "+ofToString(numXRects)+"\n numRects: "+ofToString(numRects));
}

//--------------------------------------------------------------
void testApp::update(){

	parseOSCMessages();

    // FUN STUFF
    masterCounter+=direction;
    if (masterCounter > 2000) {
        direction = -1;
    }
    if (masterCounter < -2000) {
        direction = 1;
    }

}

//--------------------------------------------------------------
void testApp::draw(){

    //drawHorizon();

    // Structured rectangles
    if (meters[4] > 0) { //if percussion occurs
        rectCount++;
        rectX += rectSpacing;
        ofSetColor(0, 255*meters[4], 0);
        ofRect(rectX, rectY, rectSize, rectSize);
    }
}

//--------------------------------------------------------------
void testApp::drawHorizon() {
    //Abstract line stuff
    for (int i = 0; i < ofGetWidth(); i++) {

        // set the color for each line
        int r = meters[0]*255;
        int g = meters[1]*255;
        int b = meters[2]*255;

        // line start and destination
        int xStart = i;
        int yStart = ofGetHeight()/2;
        int xDest = i*sin(i)*400; //400 is arbitrary.
        int yDest = i*cos(i)*masterCounter*meters[1];

        //shake the signal
        if (masterCounter%2 == 0) {
            yStart += meters[1]*10;
            xDest += xDest*meters[1];
            yDest += yDest*meters[1];
        }
        else {
            yStart -= meters[1]*10;
            xDest -= xDest*meters[1];
            yDest -= yDest*meters[1];
        }

        ofSetColor(r, g, b); //Replace this with pixel colors from feed
        ofLine(xStart, yStart, xDest, yDest);
    }
}
//--------------------------------------------------------------
void testApp::parseOSCMessages() {
    // check for waiting messages
	while(receiver.hasWaitingMessages()){
		// get the next message
		ofxOscMessage m;
		receiver.getNextMessage(&m);

		// check for meter messages
        if(m.getAddress() == "/main/meter") {
            //Go through arguments, get them as floats
            for (int i = 0; i < m.getNumArgs(); i++) {
                meters[i] = m.getArgAsFloat(i);
               // ofLogNotice("meter0"+ofToString(i)+": "+ofToString(meters[i]));
            }
        }
	}
}

//--------------------------------------------------------------
void testApp::keyPressed(int key){
    if (key == 'f' || 'F') {
        isFullScreen = !isFullScreen;
        ofSetFullscreen(isFullScreen);
    }

}

//--------------------------------------------------------------
void testApp::keyReleased(int key){

}

//--------------------------------------------------------------
void testApp::mouseMoved(int x, int y ){

}

//--------------------------------------------------------------
void testApp::mouseDragged(int x, int y, int button){

}

//--------------------------------------------------------------
void testApp::mousePressed(int x, int y, int button){

}

//--------------------------------------------------------------
void testApp::mouseReleased(int x, int y, int button){

}

//--------------------------------------------------------------
void testApp::windowResized(int w, int h){

}

//--------------------------------------------------------------
void testApp::gotMessage(ofMessage msg){

}

//--------------------------------------------------------------
void testApp::dragEvent(ofDragInfo dragInfo){

}
<|endoftext|>


<commit_before>/*++
Copyright (c) 2011 Microsoft Corporation

Module Name:

    pdr_interpolant_provider.cpp

Abstract:

    Interface for obtaining interpolants.

    This file is Windows specific.

Author:

    Krystof Hoder (t-khoder) 2011-10-19.

Revision History:

--*/

//disables the warning on deprecation of fgets function -- didn't really find by what it should be replaced
#ifdef _WINDOWS
#pragma warning(disable: 4995)
#endif

#include <sstream>
#include "ast_smt_pp.h"
#include "cmd_context.h"
#include "for_each_expr.h"
#include "obj_hashtable.h"
#include "smt2parser.h"
#include "rewriter.h"
#include "rewriter_def.h"
#include "pdr_util.h"
#include "pdr_interpolant_provider.h"
#include "expr_context_simplifier.h"

#ifdef _WINDOWS
#include <windows.h>
#include <cstdio>
#include <strsafe.h>
#include <process.h>

/**
Requirements for the use of this object:

The directory where the expcutable is must contain also executable
PdrInterpolator.exe.

This executable takes one argument with a file name that contains
two SMTLIB problem instances, each terminated by string "\n##next##\n".

The output of the executable is given to the standard output and
is also terminated by the "\n##next##\n" string.

If formulas in the two input problems are unsatisfiable, they problem
is printed at the output in the format
(assert FORM)

If the formulas are satisfiable, "0" is output and if the result cannot
be determined, the output is "?". (Both are still followed by "\n##next##\n").

*/
class interpolant_provider_impl : public interpolant_provider
{
    static std::string s_terminator_str;
    static std::string s_satisfiable_str;
    static std::string s_unknown_str;

    std::string m_exec_name;
    params_ref const & m_params;

    /**
    If non-empty, contains name of a temporary file that is used for passing the
    interpolation problem to the interpolating engine.
    */
    std::string m_tmp_file_name;

    simplifier m_simpl;

    PROCESS_INFORMATION m_pi;
    STARTUPINFOA        m_si;
    HANDLE m_in_rd;
    HANDLE m_out_rd;
    HANDLE m_in_wr;
    HANDLE m_out_wr;

    class used_symbol_inserter {
        typedef obj_hashtable<func_decl> func_decl_set;
        typedef obj_hashtable<sort> sort_set;

        ast_manager& m;
        cmd_context& m_cctx;

        func_decl_set m_funcs;
        sort_set m_sorts;

        void handle_sort(sort * s) {
            if(s->get_family_id()!=null_family_id || m_sorts.contains(s)) {
                return;
            }
            m_sorts.insert(s);
            NOT_IMPLEMENTED_YET();
            //we should insert it into the context somehow, but now not sure how and
            //we don't deal with user defined sorts (yet)...
            //m_cctx.insert(s);
        }
        void handle_func_decl(func_decl * fn) {
            if(fn->get_family_id()!=null_family_id || m_funcs.contains(fn)) {
                return;
            }
            m_funcs.insert(fn);
            m_cctx.insert(fn);
        }

    public:

        used_symbol_inserter(cmd_context& cctx) : m(cctx.m()), m_cctx(cctx) {}

        void operator()(var * n) {
            handle_sort(n->get_sort());
        }
        void operator()(app * n)        {
            if (is_uninterp(n)) {
                handle_func_decl(n->get_decl());
            }
            handle_sort(n->get_decl()->get_range());
        }
        void operator()(quantifier * n) {
            unsigned sz = n->get_num_decls();
            for(unsigned i=0; i<sz; ++i) {
                handle_sort(n->get_decl_sort(i));
            }
        }
    };

    class form_fixer_cfg : public default_rewriter_cfg
    {
        ast_manager& m;
    public:
        form_fixer_cfg(ast_manager& m) : m(m) {}

        br_status reduce_app(func_decl * f, unsigned num, expr * const * args, expr_ref & result,
            proof_ref & result_pr)
        {
            if(m.is_or(f) && num==0) {
                result = m.mk_false();
                return BR_DONE;
            }
            return BR_FAILED;
        }
    };

    std::string get_tmp_file_name();

    std::string execute_interpolator(std::string input);

    void simplify_expr(expr* f, expr_ref& result);
    void output_interpolant_problem(std::ostream& out, expr * f1, expr * f2);

public:

    interpolant_provider_impl(ast_manager& m, params_ref const& params, std::string exec_name)
        : interpolant_provider(m),
          m_params(params),
          m_exec_name(exec_name),
          m_simpl(m) {
        memset(&m_si, 0, sizeof(m_si));
        memset(&m_pi, 0, sizeof(m_pi));
    }

    ~interpolant_provider_impl();

    /**
    If (f1 /\ f2) is unsatisfiable, return true and into res assign a formula
    I such that f1 --> I, I --> ~f2, and the language if I is in the intersection
    of languages of f1 and f2.

    If (f1 /\ f2) is satisfiable, return false.
    */
    virtual lbool get_interpolant(expr * f1, expr * f2, expr_ref& res);
};

std::string interpolant_provider_impl::s_terminator_str = ";##next##";
std::string interpolant_provider_impl::s_satisfiable_str = ";#sat#";
std::string interpolant_provider_impl::s_unknown_str = ";#unknown#";

interpolant_provider_impl::~interpolant_provider_impl() {
    if(m_tmp_file_name.size()!=0) {
        DeleteFileA(m_tmp_file_name.c_str());
    }
    CloseHandle(m_pi.hProcess);
    CloseHandle(m_pi.hThread);
    CloseHandle(m_in_rd);
    CloseHandle(m_in_wr);
    CloseHandle(m_out_rd);
    CloseHandle(m_out_wr);
}

void interpolant_provider_impl::simplify_expr(expr* f, expr_ref& result) {
    expr_ref rwr_f(m);
    form_fixer_cfg fixer(m);
    rewriter_tpl<form_fixer_cfg> rwr(m, false, fixer);
    rwr(f, rwr_f);
    proof_ref pr(m);
    m_simpl(rwr_f, result, pr);
}

std::string interpolant_provider_impl::get_tmp_file_name() {
    //return "c:\\test.txt";
    if(m_tmp_file_name.length()!=0) {
        return m_tmp_file_name;
    }
    char path[MAX_PATH];
    if(GetTempPathA(256, path)==0) {
        throw default_exception("cannot get temp directory");
    }

    std::stringstream name_prefix_builder;

    name_prefix_builder<<"pdr"<<GetCurrentProcessId();

    char file[MAX_PATH];
    if(GetTempFileNameA(path, name_prefix_builder.str().c_str(), 1, file)==0) {
        throw default_exception("cannot get temp file");
    }
    m_tmp_file_name = file;
    return m_tmp_file_name;
}

void interpolant_provider_impl::output_interpolant_problem(std::ostream& out, expr * f1, expr * f2) {
    expr_ref t1(m), t2(m);
    simplify_expr(f1, t1);
    simplify_expr(f2, t2);

    ast_smt_pp pp(m);
    pp.add_assumption(t1);
    pp.display(out, t2);
    out << "\n" << s_terminator_str << "\n";
}

std::string interpolant_provider_impl::execute_interpolator(std::string input)
{
    if (!m_pi.hProcess) {
        SECURITY_ATTRIBUTES sa;
        sa.nLength = sizeof(SECURITY_ATTRIBUTES);
        sa.bInheritHandle = TRUE;
        sa.lpSecurityDescriptor = NULL;
        if (!CreatePipe(&m_out_rd, &m_out_wr, &sa, 0)) {
            throw default_exception("Could not create pipe");
        }
        if (!CreatePipe(&m_in_rd, &m_in_wr, &sa, 0)) {
            throw default_exception("Could not create pipe");
        }
        m_si.cb = sizeof(m_si);
        m_si.hStdError = 0;
        m_si.hStdOutput = m_out_wr;
        m_si.hStdInput = m_in_rd;
        m_si.dwFlags |= STARTF_USESTDHANDLES;
        if(!CreateProcessA(
               NULL,
               (LPSTR)m_exec_name.c_str(), // command line
               NULL,          // process security attributes
               NULL,          // primary thread security attributes
               TRUE,          // handles are inherited
               0,             // creation flags
               NULL,          // use parent's environment
               NULL,          // use parent's current directory
               &m_si,         // STARTUPINFO pointer
               &m_pi)) {      // receives PROCESS_INFORMATION
            throw default_exception("Could not create process");
        }
    }
    DWORD wr = 0, rd = 0;
    if (!WriteFile(m_in_wr, input.c_str(), static_cast<unsigned>(input.size()), &wr, 0)) {
        throw default_exception("Cold not write to pipe");
    }

    std::string result;
    char line[256];
    while (true) {
        memset(line, 0, sizeof(line));
        if (!ReadFile(m_out_rd, line, sizeof(line)-1, &rd, 0)) {
            throw default_exception("Cold not write to pipe");
        }
        result += line;
        if (strstr(result.c_str(), s_terminator_str.c_str())) {
            return result;
        }
    }
}

lbool interpolant_provider_impl::get_interpolant(expr * f1, expr * f2, expr_ref& res) {
    std::ostringstream prb;
    output_interpolant_problem(prb, f1, f2);
    std::string res_text = execute_interpolator(prb.str());
    if(strstr(res_text.c_str(), s_satisfiable_str.c_str())) {
        return l_false;
    }
    if(strstr(res_text.c_str(), s_unknown_str.c_str())) {
        return l_undef;
    }

    smt_params dummy_params;
    cmd_context cctx(&dummy_params, false, &m);
    for_each_expr(used_symbol_inserter(cctx), f1);

    parse_smt2_commands(cctx, std::istringstream(res_text), false);

    ptr_vector<expr>::const_iterator ait = cctx.begin_assertions();
    ptr_vector<expr>::const_iterator aend = cctx.end_assertions();
    if(ait+1!=aend) {
        throw default_exception("invalid interpolator output");
    }
    res = *ait;
    if (m_params.get_bool("dump_interpolants", false)) {
        interpolant_provider::output_interpolant(m, f1, f2, res);
    }
    return l_true;
}

interpolant_provider * interpolant_provider::mk(ast_manager& m, params_ref const& p)
{
    char self_name[MAX_PATH];
    GetModuleFileNameA(NULL, self_name, MAX_PATH);
    char * last_backslash = strrchr(self_name,'\\');
    if(last_backslash==NULL) {
        throw default_exception("GetModuleFileNameA did not return full path to the executable");
    }
    //we cut the string at the last backslash
    *last_backslash = 0;

    std::string exec_name = self_name + std::string(".\\PdrInterpolator.exe");

    return alloc(interpolant_provider_impl, m, p, exec_name);
}

#else

interpolant_provider *
interpolant_provider::mk(ast_manager& m, params_ref const& p) {
    // interpolations are windows specific and private.
    return 0;
}

#endif

void interpolant_provider::output_interpolant(ast_manager& m, expr* A, expr* B, expr* I) {
    static unsigned file_num = 0;

    std::ostringstream filename;
    filename << "interpolation_" << file_num++ << ".smt";
    std::ofstream out(filename.str().c_str());

    ast_smt_pp pp(m);
    pp.add_assumption(A);
    pp.display(out, B);
    std::ostringstream strm;
    strm << ";" << mk_pp(I, m) << "\n";

    buffer<char> buff;
    std::string s = strm.str();
    char const* i_str = s.c_str();
    while (*i_str) {
        buff.push_back(*i_str);
        if (*i_str == '\n') {
            buff.push_back(';');
        }
        ++i_str;
    }
    buff.push_back(0);
    out << buff.c_ptr();
    out << "##next##\n";
    out.close();
}
<commit_msg>fixed win compilation bug<commit_after>/*++
Copyright (c) 2011 Microsoft Corporation

Module Name:

    pdr_interpolant_provider.cpp

Abstract:

    Interface for obtaining interpolants.

    This file is Windows specific.

Author:

    Krystof Hoder (t-khoder) 2011-10-19.

Revision History:

--*/

//disables the warning on deprecation of fgets function -- didn't really find by what it should be replaced
#ifdef _WINDOWS
#pragma warning(disable: 4995)
#endif

#include <sstream>
#include "ast_smt_pp.h"
#include "cmd_context.h"
#include "for_each_expr.h"
#include "obj_hashtable.h"
#include "smt2parser.h"
#include "rewriter.h"
#include "rewriter_def.h"
#include "pdr_util.h"
#include "pdr_interpolant_provider.h"
#include "expr_context_simplifier.h"

#ifdef _WINDOWS
#include <windows.h>
#include <cstdio>
#include <strsafe.h>
#include <process.h>

/**
Requirements for the use of this object:

The directory where the expcutable is must contain also executable
PdrInterpolator.exe.

This executable takes one argument with a file name that contains
two SMTLIB problem instances, each terminated by string "\n##next##\n".

The output of the executable is given to the standard output and
is also terminated by the "\n##next##\n" string.

If formulas in the two input problems are unsatisfiable, they problem
is printed at the output in the format
(assert FORM)

If the formulas are satisfiable, "0" is output and if the result cannot
be determined, the output is "?". (Both are still followed by "\n##next##\n").

*/
class interpolant_provider_impl : public interpolant_provider
{
    static std::string s_terminator_str;
    static std::string s_satisfiable_str;
    static std::string s_unknown_str;

    std::string m_exec_name;
    params_ref const & m_params;

    /**
    If non-empty, contains name of a temporary file that is used for passing the
    interpolation problem to the interpolating engine.
    */
    std::string m_tmp_file_name;

    simplifier m_simpl;

    PROCESS_INFORMATION m_pi;
    STARTUPINFOA        m_si;
    HANDLE m_in_rd;
    HANDLE m_out_rd;
    HANDLE m_in_wr;
    HANDLE m_out_wr;

    class used_symbol_inserter {
        typedef obj_hashtable<func_decl> func_decl_set;
        typedef obj_hashtable<sort> sort_set;

        ast_manager& m;
        cmd_context& m_cctx;

        func_decl_set m_funcs;
        sort_set m_sorts;

        void handle_sort(sort * s) {
            if(s->get_family_id()!=null_family_id || m_sorts.contains(s)) {
                return;
            }
            m_sorts.insert(s);
            NOT_IMPLEMENTED_YET();
            //we should insert it into the context somehow, but now not sure how and
            //we don't deal with user defined sorts (yet)...
            //m_cctx.insert(s);
        }
        void handle_func_decl(func_decl * fn) {
            if(fn->get_family_id()!=null_family_id || m_funcs.contains(fn)) {
                return;
            }
            m_funcs.insert(fn);
            m_cctx.insert(fn);
        }

    public:

        used_symbol_inserter(cmd_context& cctx) : m(cctx.m()), m_cctx(cctx) {}

        void operator()(var * n) {
            handle_sort(n->get_sort());
        }
        void operator()(app * n)        {
            if (is_uninterp(n)) {
                handle_func_decl(n->get_decl());
            }
            handle_sort(n->get_decl()->get_range());
        }
        void operator()(quantifier * n) {
            unsigned sz = n->get_num_decls();
            for(unsigned i=0; i<sz; ++i) {
                handle_sort(n->get_decl_sort(i));
            }
        }
    };

    class form_fixer_cfg : public default_rewriter_cfg
    {
        ast_manager& m;
    public:
        form_fixer_cfg(ast_manager& m) : m(m) {}

        br_status reduce_app(func_decl * f, unsigned num, expr * const * args, expr_ref & result,
            proof_ref & result_pr)
        {
            if(m.is_or(f) && num==0) {
                result = m.mk_false();
                return BR_DONE;
            }
            return BR_FAILED;
        }
    };

    std::string get_tmp_file_name();

    std::string execute_interpolator(std::string input);

    void simplify_expr(expr* f, expr_ref& result);
    void output_interpolant_problem(std::ostream& out, expr * f1, expr * f2);

public:

    interpolant_provider_impl(ast_manager& m, params_ref const& params, std::string exec_name)
        : interpolant_provider(m),
          m_params(params),
          m_exec_name(exec_name),
          m_simpl(m) {
        memset(&m_si, 0, sizeof(m_si));
        memset(&m_pi, 0, sizeof(m_pi));
    }

    ~interpolant_provider_impl();

    /**
    If (f1 /\ f2) is unsatisfiable, return true and into res assign a formula
    I such that f1 --> I, I --> ~f2, and the language if I is in the intersection
    of languages of f1 and f2.

    If (f1 /\ f2) is satisfiable, return false.
    */
    virtual lbool get_interpolant(expr * f1, expr * f2, expr_ref& res);
};

std::string interpolant_provider_impl::s_terminator_str = ";##next##";
std::string interpolant_provider_impl::s_satisfiable_str = ";#sat#";
std::string interpolant_provider_impl::s_unknown_str = ";#unknown#";

interpolant_provider_impl::~interpolant_provider_impl() {
    if(m_tmp_file_name.size()!=0) {
        DeleteFileA(m_tmp_file_name.c_str());
    }
    CloseHandle(m_pi.hProcess);
    CloseHandle(m_pi.hThread);
    CloseHandle(m_in_rd);
    CloseHandle(m_in_wr);
    CloseHandle(m_out_rd);
    CloseHandle(m_out_wr);
}

void interpolant_provider_impl::simplify_expr(expr* f, expr_ref& result) {
    expr_ref rwr_f(m);
    form_fixer_cfg fixer(m);
    rewriter_tpl<form_fixer_cfg> rwr(m, false, fixer);
    rwr(f, rwr_f);
    proof_ref pr(m);
    m_simpl(rwr_f, result, pr);
}

std::string interpolant_provider_impl::get_tmp_file_name() {
    //return "c:\\test.txt";
    if(m_tmp_file_name.length()!=0) {
        return m_tmp_file_name;
    }
    char path[MAX_PATH];
    if(GetTempPathA(256, path)==0) {
        throw default_exception("cannot get temp directory");
    }

    std::stringstream name_prefix_builder;

    name_prefix_builder<<"pdr"<<GetCurrentProcessId();

    char file[MAX_PATH];
    if(GetTempFileNameA(path, name_prefix_builder.str().c_str(), 1, file)==0) {
        throw default_exception("cannot get temp file");
    }
    m_tmp_file_name = file;
    return m_tmp_file_name;
}

void interpolant_provider_impl::output_interpolant_problem(std::ostream& out, expr * f1, expr * f2) {
    expr_ref t1(m), t2(m);
    simplify_expr(f1, t1);
    simplify_expr(f2, t2);

    ast_smt_pp pp(m);
    pp.add_assumption(t1);
    pp.display(out, t2);
    out << "\n" << s_terminator_str << "\n";
}

std::string interpolant_provider_impl::execute_interpolator(std::string input)
{
    if (!m_pi.hProcess) {
        SECURITY_ATTRIBUTES sa;
        sa.nLength = sizeof(SECURITY_ATTRIBUTES);
        sa.bInheritHandle = TRUE;
        sa.lpSecurityDescriptor = NULL;
        if (!CreatePipe(&m_out_rd, &m_out_wr, &sa, 0)) {
            throw default_exception("Could not create pipe");
        }
        if (!CreatePipe(&m_in_rd, &m_in_wr, &sa, 0)) {
            throw default_exception("Could not create pipe");
        }
        m_si.cb = sizeof(m_si);
        m_si.hStdError = 0;
        m_si.hStdOutput = m_out_wr;
        m_si.hStdInput = m_in_rd;
        m_si.dwFlags |= STARTF_USESTDHANDLES;
        if(!CreateProcessA(
               NULL,
               (LPSTR)m_exec_name.c_str(), // command line
               NULL,          // process security attributes
               NULL,          // primary thread security attributes
               TRUE,          // handles are inherited
               0,             // creation flags
               NULL,          // use parent's environment
               NULL,          // use parent's current directory
               &m_si,         // STARTUPINFO pointer
               &m_pi)) {      // receives PROCESS_INFORMATION
            throw default_exception("Could not create process");
        }
    }
    DWORD wr = 0, rd = 0;
    if (!WriteFile(m_in_wr, input.c_str(), static_cast<unsigned>(input.size()), &wr, 0)) {
        throw default_exception("Cold not write to pipe");
    }

    std::string result;
    char line[256];
    while (true) {
        memset(line, 0, sizeof(line));
        if (!ReadFile(m_out_rd, line, sizeof(line)-1, &rd, 0)) {
            throw default_exception("Cold not write to pipe");
        }
        result += line;
        if (strstr(result.c_str(), s_terminator_str.c_str())) {
            return result;
        }
    }
}

lbool interpolant_provider_impl::get_interpolant(expr * f1, expr * f2, expr_ref& res) {
    std::ostringstream prb;
    output_interpolant_problem(prb, f1, f2);
    std::string res_text = execute_interpolator(prb.str());
    if(strstr(res_text.c_str(), s_satisfiable_str.c_str())) {
        return l_false;
    }
    if(strstr(res_text.c_str(), s_unknown_str.c_str())) {
        return l_undef;
    }

    cmd_context cctx(false, &m);
    for_each_expr(used_symbol_inserter(cctx), f1);

    parse_smt2_commands(cctx, std::istringstream(res_text), false);

    ptr_vector<expr>::const_iterator ait = cctx.begin_assertions();
    ptr_vector<expr>::const_iterator aend = cctx.end_assertions();
    if(ait+1!=aend) {
        throw default_exception("invalid interpolator output");
    }
    res = *ait;
    if (m_params.get_bool("dump_interpolants", false)) {
        interpolant_provider::output_interpolant(m, f1, f2, res);
    }
    return l_true;
}

interpolant_provider * interpolant_provider::mk(ast_manager& m, params_ref const& p)
{
    char self_name[MAX_PATH];
    GetModuleFileNameA(NULL, self_name, MAX_PATH);
    char * last_backslash = strrchr(self_name,'\\');
    if(last_backslash==NULL) {
        throw default_exception("GetModuleFileNameA did not return full path to the executable");
    }
    //we cut the string at the last backslash
    *last_backslash = 0;

    std::string exec_name = self_name + std::string(".\\PdrInterpolator.exe");

    return alloc(interpolant_provider_impl, m, p, exec_name);
}

#else

interpolant_provider *
interpolant_provider::mk(ast_manager& m, params_ref const& p) {
    // interpolations are windows specific and private.
    return 0;
}

#endif

void interpolant_provider::output_interpolant(ast_manager& m, expr* A, expr* B, expr* I) {
    static unsigned file_num = 0;

    std::ostringstream filename;
    filename << "interpolation_" << file_num++ << ".smt";
    std::ofstream out(filename.str().c_str());

    ast_smt_pp pp(m);
    pp.add_assumption(A);
    pp.display(out, B);
    std::ostringstream strm;
    strm << ";" << mk_pp(I, m) << "\n";

    buffer<char> buff;
    std::string s = strm.str();
    char const* i_str = s.c_str();
    while (*i_str) {
        buff.push_back(*i_str);
        if (*i_str == '\n') {
            buff.push_back(';');
        }
        ++i_str;
    }
    buff.push_back(0);
    out << buff.c_ptr();
    out << "##next##\n";
    out.close();
}
<|endoftext|>