<commit_before>#include "deskicon.h"

#include <QVBoxLayout>
#include <QPainter>
#include <QFileInfo>
#include <QFileIconProvider>
#include <QMouseEvent>

#include <Windows.h>
#include <ShellAPI.h>

DeskIcon::DeskIcon(QWidget *parent,QString icon, int type) :
    QPushButton(parent),m_type(type)
{
    m_lb_icon = new QLabel(this);
    m_lb_icon->setAttribute(Qt::WA_TranslucentBackground);

    QVBoxLayout *vlay = new QVBoxLayout(this);

    if ( type != PATH_NAME)
    {
        m_icon.load(icon);
        m_icon = m_icon.scaled(40,40);
    }else
    {
        QFileInfo info(icon);
        QFileIconProvider provider;
        QIcon icon = provider.icon(info);
        m_icon = icon.pixmap(20,20);
    }
    QString sheet;
    sheet = "border-image: url(" + icon + ");";
    m_lb_icon->setStyleSheet(sheet);
    m_lb_icon->setPixmap(m_icon);
    vlay->setContentsMargins(0,0,0,0);
    vlay->setSpacing(5);

    vlay->addWidget(m_lb_icon,0,Qt::AlignHCenter);

    if  ( type == HAVE_TEXT )
    {
        m_lb_txt = new QLabel(this);
        m_lb_txt->setAttribute(Qt::WA_TranslucentBackground);
        m_lb_txt->setStyleSheet("color: rgb(255, 255, 255);");
        m_lb_txt->setWordWrap(true);

        vlay->addWidget(m_lb_txt,0,Qt::AlignHCenter);
        setMinimumSize(80,65);
    }else
        setMinimumSize(40,40);

    setLayout(vlay);

    setAttribute(Qt::WA_TranslucentBackground);

    m_color = QColor(0,0,0,0);

}

DeskIcon::~DeskIcon()
{

}

void DeskIcon::setTextStyle(QString style)
{
    m_lb_txt->setStyleSheet(style);
}

void DeskIcon::paintEvent(QPaintEvent *evt)
{
    QPainter painter(this);
    painter.setRenderHint(QPainter::Antialiasing,true);

    QPainterPath path;
    path.addRoundRect(rect(),20);
    painter.fillPath(path,QBrush(m_color));
}

void DeskIcon::enterEvent(QEvent *evt)
{
    m_color = QColor(255, 37, 246,40);

    setCursor(Qt::PointingHandCursor);
    update();

}
void DeskIcon::leaveEvent(QEvent *evt)
{
    m_color = QColor(0,0,0,0);

    setCursor(Qt::ArrowCursor);
    update();
}

void DeskIcon::mouseDoubleClickEvent(QMouseEvent *evt)
{
    if ( m_type == HAVE_TEXT)
    {
        QString txt = m_lb_txt->text();
        emit dbclick(txt);
        ShellExecuteA(this->winId(),"open",m_path.toLocal8Bit().data(),NULL,NULL,SW_SHOWNORMAL);
    }
}

void DeskIcon::mousePressEvent(QMouseEvent *evt)
{
    if ( Qt::LeftButton == evt->button())
    {

        m_pressed = true;
        m_movePoint = evt->globalPos() - pos();
    }
}

void DeskIcon::mouseReleaseEvent(QMouseEvent *evt)
{
    m_pressed = false;
    emit click(m_txt);
    emit clicked();
}

void DeskIcon::mouseMoveEvent(QMouseEvent *evt)
{
    if ( m_pressed)
    {
        move(evt->globalPos() - m_movePoint);
    }
}
<commit_msg>add dcode to bs url<commit_after>#include "deskicon.h"
#include "jsCore/qjscore.h"

#include <QVBoxLayout>
#include <QPainter>
#include <QFileInfo>
#include <QFileIconProvider>
#include <QMouseEvent>

#include <Windows.h>
#include <ShellAPI.h>

DeskIcon::DeskIcon(QWidget *parent,QString icon, int type) :
    QPushButton(parent),m_type(type)
{
    m_lb_icon = new QLabel(this);
    m_lb_icon->setAttribute(Qt::WA_TranslucentBackground);

    QVBoxLayout *vlay = new QVBoxLayout(this);

    if ( type != PATH_NAME)
    {
        m_icon.load(icon);
        m_icon = m_icon.scaled(40,40);
    }else
    {
        QFileInfo info(icon);
        QFileIconProvider provider;
        QIcon icon = provider.icon(info);
        m_icon = icon.pixmap(20,20);
    }
    QString sheet;
    sheet = "border-image: url(" + icon + ");";
    m_lb_icon->setStyleSheet(sheet);
    m_lb_icon->setPixmap(m_icon);
    vlay->setContentsMargins(0,0,0,0);
    vlay->setSpacing(5);

    vlay->addWidget(m_lb_icon,0,Qt::AlignHCenter);

    if  ( type == HAVE_TEXT )
    {
        m_lb_txt = new QLabel(this);
        m_lb_txt->setAttribute(Qt::WA_TranslucentBackground);
        m_lb_txt->setStyleSheet("color: rgb(255, 255, 255);");
        m_lb_txt->setWordWrap(true);

        vlay->addWidget(m_lb_txt,0,Qt::AlignHCenter);
        setMinimumSize(80,65);
    }else
        setMinimumSize(40,40);

    setLayout(vlay);

    setAttribute(Qt::WA_TranslucentBackground);

    m_color = QColor(0,0,0,0);

}

DeskIcon::~DeskIcon()
{

}

void DeskIcon::setTextStyle(QString style)
{
    m_lb_txt->setStyleSheet(style);
}

void DeskIcon::paintEvent(QPaintEvent *evt)
{
    QPainter painter(this);
    painter.setRenderHint(QPainter::Antialiasing,true);

    QPainterPath path;
    path.addRoundRect(rect(),20);
    painter.fillPath(path,QBrush(m_color));
}

void DeskIcon::enterEvent(QEvent *evt)
{
    m_color = QColor(255, 37, 246,40);

    setCursor(Qt::PointingHandCursor);
    update();

}
void DeskIcon::leaveEvent(QEvent *evt)
{
    m_color = QColor(0,0,0,0);

    setCursor(Qt::ArrowCursor);
    update();
}

void DeskIcon::mouseDoubleClickEvent(QMouseEvent *evt)
{
    if ( m_type == HAVE_TEXT)
    {
        QString txt = m_lb_txt->text();
        emit dbclick(txt);
        if (m_path.indexOf("http") >= 0)
        {
            m_path += "?code=" + QJSCore::ref()->getDCode();
            qDebug()<<"URL:"<<m_path;
        }
        ShellExecuteA(this->winId(),"open",m_path.toLocal8Bit().data(),NULL,NULL,SW_SHOWNORMAL);
    }
}

void DeskIcon::mousePressEvent(QMouseEvent *evt)
{
    if ( Qt::LeftButton == evt->button())
    {

        m_pressed = true;
        m_movePoint = evt->globalPos() - pos();
    }
}

void DeskIcon::mouseReleaseEvent(QMouseEvent *evt)
{
    m_pressed = false;
    emit click(m_txt);
    emit clicked();
}

void DeskIcon::mouseMoveEvent(QMouseEvent *evt)
{
    if ( m_pressed)
    {
        move(evt->globalPos() - m_movePoint);
    }
}
<|endoftext|>


<commit_before>#include <QAction>
#include <QTranslator>
#include <QMenu>

#include <coreplugin/icore.h>
#include <coreplugin/coreconstants.h>
#include <coreplugin/actionmanager/actionmanager.h>
#include <coreplugin/actionmanager/actioncontainer.h>
#include <coreplugin/editormanager/editormanager.h>
#include <projectexplorer/projectexplorer.h>

#include <QtPlugin>

#include "QtcGtestPlugin.h"
#include "Constants.h"
#include "Settings.h"
#include "OutputPane.h"
#include "TestProject.h"

using namespace QtcGtest::Internal;

using namespace Core;
using namespace ProjectExplorer;

QtcGtestPlugin::QtcGtestPlugin():
  IPlugin (),
  testProject_ (new TestProject (this))
{
  // Create your members
}

QtcGtestPlugin::~QtcGtestPlugin()
{
  // Unregister objects from the plugin manager's object pool
  // Delete members
}

bool QtcGtestPlugin::initialize(const QStringList &arguments, QString *errorString)
{
  // Register objects in the plugin manager's object pool
  // Load settings
  // Add actions to menus
  // Connect to other plugins' signals
  // In the initialize function, a plugin can be sure that the plugins it
  // depends on have initialized their members.

  Q_UNUSED(arguments)
  Q_UNUSED(errorString)

  initLanguage ();
  initMenus ();

  OutputPane* pane = new OutputPane;
  connect (ProjectExplorerPlugin::instance (), SIGNAL (runControlStarted(ProjectExplorer::RunControl *)),
           pane, SLOT (handleRunStart(ProjectExplorer::RunControl *)));
  connect (ProjectExplorerPlugin::instance (), SIGNAL (runControlFinished(ProjectExplorer::RunControl *)),
           pane, SLOT (handleRunFinish(ProjectExplorer::RunControl *)));
  addAutoReleasedObject (pane);

  connect (EditorManager::documentModel (),
           SIGNAL (dataChanged(const QModelIndex &, const QModelIndex &, const QVector<int> &)),
           testProject_,
           SLOT (handleDocumentsChange(const QModelIndex &, const QModelIndex &, const QVector<int> &)));
  connect (EditorManager::documentModel (),
           SIGNAL (rowsAboutToBeRemoved(const QModelIndex &, int, int)),
           testProject_,
           SLOT (handleDocumentsClose(const QModelIndex &, int, int)));

  return true;
}

void QtcGtestPlugin::initLanguage()
{
  const QString& language = Core::ICore::userInterfaceLanguage();
  if (!language.isEmpty())
  {
    QTranslator* translator = new QTranslator (this);
    const QString& creatorTrPath = ICore::resourcePath () + QLatin1String ("/translations");
    const QString& trFile = QLatin1String ("QtcGtest_") + language;
    if (translator->load (trFile, creatorTrPath))
    {
      qApp->installTranslator (translator);
    }
  }
}

void QtcGtestPlugin::initMenus()
{
  QAction *checkProjectAction = new QAction(tr("Check project"), this);
  Core::Command *checkProjectCmd = ActionManager::registerAction(
                                     checkProjectAction, Constants::ACTION_CHECK_PROJECT_ID,
                                     Context(Core::Constants::C_GLOBAL));
  checkProjectCmd->setDefaultKeySequence (QKeySequence (tr ("Alt+T,Alt+A")));
  connect(checkProjectAction, SIGNAL(triggered()), testProject_, SLOT(checkProject()));

  QAction *checkCurrentAction = new QAction(tr("Check current"), this);
  Core::Command *checkCurrentCmd = ActionManager::registerAction(
                                     checkCurrentAction, Constants::ACTION_CHECK_CURRENT_ID,
                                     Context(Core::Constants::C_GLOBAL));
  checkCurrentCmd->setDefaultKeySequence (QKeySequence (tr ("Alt+T,Alt+C")));
  connect(checkCurrentAction, SIGNAL(triggered()), testProject_, SLOT(checkCurrent()));

  QAction *checkChangedAction = new QAction(tr("Check changed"), this);
  Core::Command *checkChangedCmd = ActionManager::registerAction(
                                     checkChangedAction, Constants::ACTION_CHECK_CHANGED_ID,
                                     Context(Core::Constants::C_GLOBAL));
  checkChangedCmd->setDefaultKeySequence (QKeySequence (tr ("Alt+T,Alt+T")));
  connect(checkChangedAction, SIGNAL(triggered()), testProject_, SLOT(checkChanged()));

  ActionContainer *menu = ActionManager::createMenu(Constants::MENU_ID);
  menu->menu()->setTitle(tr("Google Test"));
  menu->addAction(checkProjectCmd);
  menu->addAction(checkCurrentCmd);
  menu->addAction(checkChangedCmd);
  ActionManager::actionContainer(Core::Constants::M_TOOLS)->addMenu(menu);
}

void QtcGtestPlugin::extensionsInitialized()
{
  // Retrieve objects from the plugin manager's object pool
  // In the extensionsInitialized function, a plugin can be sure that all
  // plugins that depend on it are completely initialized.
}

ExtensionSystem::IPlugin::ShutdownFlag QtcGtestPlugin::aboutToShutdown()
{
  // Save settings
  // Disconnect from signals that are not needed during shutdown
  // Hide UI (if you add UI that is not in the main window directly)
  return SynchronousShutdown;
}

Q_EXPORT_PLUGIN2(QtcGtest, QtcGtestPlugin)

<commit_msg>Load translations from several paths<commit_after>#include <QAction>
#include <QTranslator>
#include <QMenu>

#include <coreplugin/icore.h>
#include <coreplugin/coreconstants.h>
#include <coreplugin/actionmanager/actionmanager.h>
#include <coreplugin/actionmanager/actioncontainer.h>
#include <coreplugin/editormanager/editormanager.h>
#include <projectexplorer/projectexplorer.h>

#include <QtPlugin>

#include "QtcGtestPlugin.h"
#include "Constants.h"
#include "Settings.h"
#include "OutputPane.h"
#include "TestProject.h"

using namespace QtcGtest::Internal;

using namespace Core;
using namespace ProjectExplorer;

QtcGtestPlugin::QtcGtestPlugin():
  IPlugin (),
  testProject_ (new TestProject (this))
{
  // Create your members
}

QtcGtestPlugin::~QtcGtestPlugin()
{
  // Unregister objects from the plugin manager's object pool
  // Delete members
}

bool QtcGtestPlugin::initialize(const QStringList &arguments, QString *errorString)
{
  // Register objects in the plugin manager's object pool
  // Load settings
  // Add actions to menus
  // Connect to other plugins' signals
  // In the initialize function, a plugin can be sure that the plugins it
  // depends on have initialized their members.

  Q_UNUSED(arguments)
  Q_UNUSED(errorString)

  initLanguage ();
  initMenus ();

  OutputPane* pane = new OutputPane;
  connect (ProjectExplorerPlugin::instance (), SIGNAL (runControlStarted(ProjectExplorer::RunControl *)),
           pane, SLOT (handleRunStart(ProjectExplorer::RunControl *)));
  connect (ProjectExplorerPlugin::instance (), SIGNAL (runControlFinished(ProjectExplorer::RunControl *)),
           pane, SLOT (handleRunFinish(ProjectExplorer::RunControl *)));
  addAutoReleasedObject (pane);

  connect (EditorManager::documentModel (),
           SIGNAL (dataChanged(const QModelIndex &, const QModelIndex &, const QVector<int> &)),
           testProject_,
           SLOT (handleDocumentsChange(const QModelIndex &, const QModelIndex &, const QVector<int> &)));
  connect (EditorManager::documentModel (),
           SIGNAL (rowsAboutToBeRemoved(const QModelIndex &, int, int)),
           testProject_,
           SLOT (handleDocumentsClose(const QModelIndex &, int, int)));

  return true;
}

void QtcGtestPlugin::initLanguage()
{
  const QString& language = Core::ICore::userInterfaceLanguage();
  if (!language.isEmpty())
  {
    QStringList paths;
    paths << ICore::resourcePath () << ICore::userResourcePath();
    const QString& trFile = QLatin1String ("QtcCppcheck_") + language;
    QTranslator* translator = new QTranslator (this);
    foreach (const QString& path, paths)
    {
      if (translator->load (trFile, path + QLatin1String ("/translations")))
      {
        qApp->installTranslator (translator);
        break;
      }
    }
  }
}

void QtcGtestPlugin::initMenus()
{
  QAction *checkProjectAction = new QAction(tr("Check project"), this);
  Core::Command *checkProjectCmd = ActionManager::registerAction(
                                     checkProjectAction, Constants::ACTION_CHECK_PROJECT_ID,
                                     Context(Core::Constants::C_GLOBAL));
  checkProjectCmd->setDefaultKeySequence (QKeySequence (tr ("Alt+T,Alt+A")));
  connect(checkProjectAction, SIGNAL(triggered()), testProject_, SLOT(checkProject()));

  QAction *checkCurrentAction = new QAction(tr("Check current"), this);
  Core::Command *checkCurrentCmd = ActionManager::registerAction(
                                     checkCurrentAction, Constants::ACTION_CHECK_CURRENT_ID,
                                     Context(Core::Constants::C_GLOBAL));
  checkCurrentCmd->setDefaultKeySequence (QKeySequence (tr ("Alt+T,Alt+C")));
  connect(checkCurrentAction, SIGNAL(triggered()), testProject_, SLOT(checkCurrent()));

  QAction *checkChangedAction = new QAction(tr("Check changed"), this);
  Core::Command *checkChangedCmd = ActionManager::registerAction(
                                     checkChangedAction, Constants::ACTION_CHECK_CHANGED_ID,
                                     Context(Core::Constants::C_GLOBAL));
  checkChangedCmd->setDefaultKeySequence (QKeySequence (tr ("Alt+T,Alt+T")));
  connect(checkChangedAction, SIGNAL(triggered()), testProject_, SLOT(checkChanged()));

  ActionContainer *menu = ActionManager::createMenu(Constants::MENU_ID);
  menu->menu()->setTitle(tr("Google Test"));
  menu->addAction(checkProjectCmd);
  menu->addAction(checkCurrentCmd);
  menu->addAction(checkChangedCmd);
  ActionManager::actionContainer(Core::Constants::M_TOOLS)->addMenu(menu);
}

void QtcGtestPlugin::extensionsInitialized()
{
  // Retrieve objects from the plugin manager's object pool
  // In the extensionsInitialized function, a plugin can be sure that all
  // plugins that depend on it are completely initialized.
}

ExtensionSystem::IPlugin::ShutdownFlag QtcGtestPlugin::aboutToShutdown()
{
  // Save settings
  // Disconnect from signals that are not needed during shutdown
  // Hide UI (if you add UI that is not in the main window directly)
  return SynchronousShutdown;
}

Q_EXPORT_PLUGIN2(QtcGtest, QtcGtestPlugin)

<|endoftext|>


<commit_before>#include "stdafx.h"
#include "ResourceLoader.h"
#include <iostream>
#include "Logger.h"

std::string ResourceLoader::loadTextResource(HMODULE moduleHandle, int id, LPTSTR type)
{
    HRSRC resourceHandle = ::FindResource(moduleHandle, MAKEINTRESOURCE(id), type);

    if (!resourceHandle)
    {
        std::string msg("Unable to find resource with id: [");
        msg += std::to_string(id);
        msg += "] because of error with code: ";
        msg += std::to_string(::GetLastError());

        LOG_ERROR(msg);
        throw std::runtime_error(msg);
    }

    HGLOBAL resourceData = ::LoadResource(moduleHandle, resourceHandle);
    LPVOID dataFirstByte = ::LockResource(resourceData);

    return std::string(static_cast<const char*>(dataFirstByte));
}
<commit_msg>Now using the size of the resource when creating the std::string<commit_after>#include "stdafx.h"
#include "ResourceLoader.h"
#include <iostream>
#include "Logger.h"

std::string ResourceLoader::loadTextResource(HMODULE moduleHandle, int id, LPTSTR type)
{
    HRSRC resourceHandle = ::FindResource(moduleHandle, MAKEINTRESOURCE(id), type);

    if (!resourceHandle)
    {
        std::string msg("Unable to find resource with id: [");
        msg += std::to_string(id);
        msg += "] because of error with code: ";
        msg += std::to_string(::GetLastError());

        LOG_ERROR(msg);
        throw std::runtime_error(msg);
    }

    HGLOBAL resourceData = ::LoadResource(moduleHandle, resourceHandle);
    LPVOID dataFirstByte = ::LockResource(resourceData);
    DWORD dataSize = ::SizeofResource(moduleHandle, resourceHandle);

    return {static_cast<const char*>(dataFirstByte), dataSize};
}
<|endoftext|>


<commit_before>
/*
 *  SubtitleStream.cpp
 *  sfeMovie project
 *
 *  Copyright (C) 2010-2014 Stephan Vedder
 *  stephan.vedder@gmail.com
 *
 *  This program is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License as published by the Free Software Foundation; either
 *  version 2.1 of the License, or (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this program; if not, write to the Free Software
 *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 *
 */

extern "C"
{
#include <libavformat/avformat.h>
#include <libavcodec/avcodec.h>
}

#include <sfeMovie/Movie.hpp>
#include "SubtitleStream.hpp"
#include "Log.hpp"

#include <iostream>
#include <cassert>
#include <stdint.h>

namespace sfe
{
    const int RGBASize = 4;

    SubtitleStream::SubtitleStream(AVFormatContext*& formatCtx, AVStream*& stream, DataSource& dataSource, std::shared_ptr<Timer> timer, Delegate& delegate) :
        Stream(formatCtx, stream, dataSource, timer), m_delegate(delegate), m_library(nullptr), m_renderer(nullptr), m_track(nullptr)
    {
        const AVCodecDescriptor* desc = av_codec_get_codec_descriptor(m_stream->codec);
        CHECK(desc != NULL, "Could not get the codec descriptor!");

        if((desc->props & AV_CODEC_PROP_BITMAP_SUB)==0)
        {
			m_library  = ass_library_init();
            ass_set_message_cb(m_library, ass_log,nullptr);

			m_renderer = ass_renderer_init(m_library);
            m_track    = ass_new_track(m_library);

            ass_set_frame_size(m_renderer, m_stream->codec->width, m_stream->codec->height);
            ass_set_fonts(m_renderer, NULL, NULL, 1, NULL , 1);
            ass_set_font_scale(m_renderer, 5.0f);

            ass_process_codec_private(m_track, reinterpret_cast<char*>(m_stream->codec->subtitle_header), m_stream->codec->subtitle_header_size);
		}
    }

    /** Default destructor
     */
    SubtitleStream::~SubtitleStream()
    {
        if (m_track)
        {
            ass_free_track(m_track);
            m_track = nullptr;
        }

		if(m_renderer)
		{
			ass_renderer_done(m_renderer);
			m_renderer = nullptr;
		}

		if(m_library)
		{
			ass_library_done(m_library);
			m_library = nullptr;
		}

    }

    MediaType SubtitleStream::getStreamKind() const
    {
        return Subtitle;
    }

    void SubtitleStream::update()
    {
        //only get new subtitles if we are running low
        if (m_status == Playing && hasPackets())
        {
            if (!onGetData())
                setStatus(Stopped);
        }

        if (m_pendingSubtitles.size() > 0)
        {
            //activate subtitle
            if (m_pendingSubtitles.front()->start < m_timer->getOffset())
            {
                std::shared_ptr<SubtitleData> iter = m_pendingSubtitles.front();

                auto time = m_timer->getOffset().asMilliseconds();
                //this is the case for ass subtitles
                if (iter->sprites.size() < 1)
                {
                    int change = 0;
                    ASS_Image* img = ass_render_frame(m_renderer, m_track, m_timer->getOffset().asMilliseconds(), &change);
                    if (change)
                    {
                        while (img)
                        {
                            iter->sprites.push_back(sf::Sprite());
                            iter->textures.push_back(sf::Texture());
                            iter->positions.push_back(sf::Vector2i(img->dst_x, img->dst_y));

                            sf::Sprite& sprite = iter->sprites.back();
                            sf::Texture& texture = iter->textures.back();

                            texture.create(img->w, img->h);
                            texture.update(img->bitmap);
                            texture.setSmooth(true);

                            sprite.setTexture(texture);

                            img = img->next;
                        }
                    }
                }

                m_delegate.didUpdateSubtitle(*this, iter->sprites, iter->positions);
                m_visibleSubtitles.push_back(iter);
                m_pendingSubtitles.pop_front();
            }
        }

        if (m_visibleSubtitles.size()>0)
        {
            //remove subtitle
            if (m_visibleSubtitles.front()->end < m_timer->getOffset())
            {
                std::shared_ptr<SubtitleData> subtitle = m_visibleSubtitles.front();
                m_visibleSubtitles.pop_front();

                if (m_visibleSubtitles.size() == 0)
                {
                    m_delegate.didWipeOutSubtitles(*this);
                }
            }
        }
    }

    bool SubtitleStream::isPassive() const
    {
        return true;
    }

    bool SubtitleStream::onGetData()
    {
        AVPacket* packet = popEncodedData();
        AVSubtitle sub;
        int32_t gotSub = 0;
        int32_t goOn = 0;
        int64_t pts = 0;

        if (packet)
        {
            goOn = 1;

            while (!gotSub && packet && goOn)
            {
                bool needsMoreDecoding = false;

                CHECK(packet != nullptr, "inconsistency error");
                goOn = avcodec_decode_subtitle2(m_stream->codec, &sub, &gotSub, packet);

                pts = 0;
                if (packet->pts != AV_NOPTS_VALUE)
                    pts = packet->pts;

                if (gotSub && pts)
                {
                    bool succeeded = false;
                    std::shared_ptr<SubtitleData> sfeSub = std::make_shared<SubtitleData>(&sub, succeeded,m_track);

                    if (succeeded)
                        m_pendingSubtitles.push_back(sfeSub);
                }

                if (needsMoreDecoding)
                {
                    prependEncodedData(packet);
                }
                else
                {
                    av_free_packet(packet);
                    av_free(packet);
                }

                if (!gotSub && goOn)
                {
                    sfeLogDebug("no subtitle in this packet, reading further");
                    packet = popEncodedData();
                }
            }
        }
        return (goOn >= 0);
    }

    SubtitleStream::SubtitleData::SubtitleData(AVSubtitle* sub, bool& succeeded,ASS_Track* track)
    {
        assert(sub != nullptr);

        succeeded = false;
        start = sf::milliseconds(sub->start_display_time) + sf::microseconds(sub->pts);
        end = sf::milliseconds(sub->end_display_time) + sf::microseconds(sub->pts);

        for (unsigned int i = 0; i < sub->num_rects; ++i)
        {
            AVSubtitleRect* subItem = sub->rects[i];

            AVSubtitleType type = subItem->type;

            if (type == SUBTITLE_BITMAP)
            {
                sprites.push_back(sf::Sprite());
                textures.push_back(sf::Texture());

                sf::Sprite& sprite = sprites.back();
                sf::Texture& texture = textures.back();

                CHECK(subItem->pict.data != nullptr, "FFmpeg inconcistency error");
                CHECK(subItem->w * subItem->h > 0, "FFmpeg inconcistency error");

                positions.push_back(sf::Vector2i(subItem->x, subItem->y));

                std::unique_ptr<uint32_t[]> palette(new uint32_t[subItem->nb_colors]);
                for (int j = 0; j < subItem->nb_colors; j++)
                    palette[j] = *(uint32_t*)&subItem->pict.data[1][j * RGBASize];

                texture.create(subItem->w, subItem->h);
                texture.setSmooth(true);

                std::unique_ptr<uint32_t[]> data(new uint32_t[subItem->w* sub->rects[i]->h]);
                for (int j = 0; j < subItem->w * subItem->h; ++j)
                    data[j] = palette[subItem->pict.data[0][j]];

                texture.update((uint8_t*)data.get());
                sprite.setTexture(texture);

                succeeded = true;
            }
            else
            {
                ass_process_data(track, subItem->ass, strlen(subItem->ass));

                succeeded = true;
            }
        }
    }

    void SubtitleStream::flushBuffers()
    {
        m_delegate.didWipeOutSubtitles(*this);
        Stream::flushBuffers();
    }

    void SubtitleStream::ass_log(int ass_level, const char *fmt, va_list args, void *data)
    {
        char buffer[512];

        vsprintf(buffer, fmt, args);
        sfeLogDebug(buffer);
    }
}
<commit_msg>Set default font and changed rendering code<commit_after>
/*
 *  SubtitleStream.cpp
 *  sfeMovie project
 *
 *  Copyright (C) 2010-2014 Stephan Vedder
 *  stephan.vedder@gmail.com
 *
 *  This program is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License as published by the Free Software Foundation; either
 *  version 2.1 of the License, or (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this program; if not, write to the Free Software
 *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 *
 */

extern "C"
{
#include <libavformat/avformat.h>
#include <libavcodec/avcodec.h>
}

#include <sfeMovie/Movie.hpp>
#include "SubtitleStream.hpp"
#include "Log.hpp"

#include <iostream>
#include <cassert>
#include <stdint.h>

#define _r(c) ((c) >> 24)
#define _g(c) (((c) >> 16) & 0xFF)
#define _b(c) (((c) >> 8) & 0xFF)
#define _a(c) (255 - ((c) & 0xFF))

namespace sfe
{
    const int RGBASize = 4;

    SubtitleStream::SubtitleStream(AVFormatContext*& formatCtx, AVStream*& stream, DataSource& dataSource, std::shared_ptr<Timer> timer, Delegate& delegate) :
        Stream(formatCtx, stream, dataSource, timer), m_delegate(delegate), m_library(nullptr), m_renderer(nullptr), m_track(nullptr)
    {
        const AVCodecDescriptor* desc = av_codec_get_codec_descriptor(m_stream->codec);
        CHECK(desc != NULL, "Could not get the codec descriptor!");

        if((desc->props & AV_CODEC_PROP_BITMAP_SUB)==0)
        {
			m_library  = ass_library_init();
            ass_set_message_cb(m_library, ass_log,nullptr);

			m_renderer = ass_renderer_init(m_library);
            m_track    = ass_new_track(m_library);

            ass_set_frame_size(m_renderer, m_stream->codec->width, m_stream->codec->height);
            ass_set_fonts(m_renderer, NULL, "Sans", 1, NULL, 1);
            ass_set_font_scale(m_renderer, 10.0f);

            ass_process_codec_private(m_track, reinterpret_cast<char*>(m_stream->codec->subtitle_header), m_stream->codec->subtitle_header_size);
		}
    }

    /** Default destructor
     */
    SubtitleStream::~SubtitleStream()
    {
        if (m_track)
        {
            ass_free_track(m_track);
            m_track = nullptr;
        }

		if(m_renderer)
		{
			ass_renderer_done(m_renderer);
			m_renderer = nullptr;
		}

		if(m_library)
		{
			ass_library_done(m_library);
			m_library = nullptr;
		}

    }

    MediaType SubtitleStream::getStreamKind() const
    {
        return Subtitle;
    }

    void SubtitleStream::update()
    {
        //only get new subtitles if we are running low
        if (m_status == Playing && hasPackets())
        {
            if (!onGetData())
                setStatus(Stopped);
        }

        if (m_pendingSubtitles.size() > 0)
        {
            //activate subtitle
            if (m_pendingSubtitles.front()->start < m_timer->getOffset())
            {
                std::shared_ptr<SubtitleData> iter = m_pendingSubtitles.front();

                auto time = m_timer->getOffset().asMilliseconds();
                //this is the case for ass subtitles
                if (iter->sprites.size() < 1)
                {
                    int change = 0;
                    ASS_Image* img = ass_render_frame(m_renderer, m_track, m_timer->getOffset().asMilliseconds(), &change);

                    if (change)
                    {

                        while (img)
                        {
                            if (!img->w || !img->h) continue;

                            uint8_t     r = img->color >> 24,
                                        g = img->color >> 16 & 255,
                                        b = img->color >> 8 & 255,
                                        a = 255 - (img->color & 255);

                            sf::Image buffer;
                            buffer.create(img->w, img->h);

                            iter->positions.push_back(sf::Vector2i(img->dst_x, img->dst_y));

                            for (int y = 0; y < img->h; ++y)
                            {
                                const unsigned char *map = img->bitmap + y * img->stride;

                                for (int x = 0; x < img->w; ++x)
                                {
                                    uint8_t alpha = (unsigned)a * *map++;
                                    buffer.setPixel(x, y, sf::Color(r,g,b,alpha));
                                }
                            }

                            img = img->next;

                            iter->sprites.push_back(sf::Sprite());
                            iter->textures.push_back(sf::Texture());

                            sf::Sprite& sprite = iter->sprites.back();
                            sf::Texture& texture = iter->textures.back();

                            texture.create(buffer.getSize().x, buffer.getSize().y);
                            texture.update(buffer);
                            texture.setSmooth(true);

                            sprite.setTexture(texture);
                        }
                    }
                }

                m_delegate.didUpdateSubtitle(*this, iter->sprites, iter->positions);
                m_visibleSubtitles.push_back(iter);
                m_pendingSubtitles.pop_front();
            }
        }

        if (m_visibleSubtitles.size()>0)
        {
            //remove subtitle
            if (m_visibleSubtitles.front()->end < m_timer->getOffset())
            {
                std::shared_ptr<SubtitleData> subtitle = m_visibleSubtitles.front();
                m_visibleSubtitles.pop_front();

                if (m_visibleSubtitles.size() == 0)
                {
                    m_delegate.didWipeOutSubtitles(*this);
                }
            }
        }
    }

    bool SubtitleStream::isPassive() const
    {
        return true;
    }

    bool SubtitleStream::onGetData()
    {
        AVPacket* packet = popEncodedData();
        AVSubtitle sub;
        int32_t gotSub = 0;
        int32_t goOn = 0;
        int64_t pts = 0;

        if (packet)
        {
            goOn = 1;

            while (!gotSub && packet && goOn)
            {
                bool needsMoreDecoding = false;

                CHECK(packet != nullptr, "inconsistency error");
                goOn = avcodec_decode_subtitle2(m_stream->codec, &sub, &gotSub, packet);

                pts = 0;
                if (packet->pts != AV_NOPTS_VALUE)
                    pts = packet->pts;

                if (gotSub && pts)
                {
                    bool succeeded = false;
                    std::shared_ptr<SubtitleData> sfeSub = std::make_shared<SubtitleData>(&sub, succeeded,m_track);

                    if (succeeded)
                        m_pendingSubtitles.push_back(sfeSub);
                }

                if (needsMoreDecoding)
                {
                    prependEncodedData(packet);
                }
                else
                {
                    av_free_packet(packet);
                    av_free(packet);
                }

                if (!gotSub && goOn)
                {
                    sfeLogDebug("no subtitle in this packet, reading further");
                    packet = popEncodedData();
                }
            }
        }
        return (goOn >= 0);
    }

    SubtitleStream::SubtitleData::SubtitleData(AVSubtitle* sub, bool& succeeded,ASS_Track* track)
    {
        assert(sub != nullptr);

        succeeded = false;
        start = sf::milliseconds(sub->start_display_time) + sf::microseconds(sub->pts);
        end = sf::milliseconds(sub->end_display_time) + sf::microseconds(sub->pts);

        for (unsigned int i = 0; i < sub->num_rects; ++i)
        {
            AVSubtitleRect* subItem = sub->rects[i];

            AVSubtitleType type = subItem->type;

            if (type == SUBTITLE_BITMAP)
            {
                sprites.push_back(sf::Sprite());
                textures.push_back(sf::Texture());

                sf::Sprite& sprite = sprites.back();
                sf::Texture& texture = textures.back();

                CHECK(subItem->pict.data != nullptr, "FFmpeg inconcistency error");
                CHECK(subItem->w * subItem->h > 0, "FFmpeg inconcistency error");

                positions.push_back(sf::Vector2i(subItem->x, subItem->y));

                std::unique_ptr<uint32_t[]> palette(new uint32_t[subItem->nb_colors]);
                for (int j = 0; j < subItem->nb_colors; j++)
                    palette[j] = *(uint32_t*)&subItem->pict.data[1][j * RGBASize];

                texture.create(subItem->w, subItem->h);
                texture.setSmooth(true);

                std::unique_ptr<uint32_t[]> data(new uint32_t[subItem->w* sub->rects[i]->h]);
                for (int j = 0; j < subItem->w * subItem->h; ++j)
                    data[j] = palette[subItem->pict.data[0][j]];

                texture.update((uint8_t*)data.get());
                sprite.setTexture(texture);

                succeeded = true;
            }
            else
            {
                ass_process_data(track, subItem->ass, strlen(subItem->ass));

                succeeded = true;
            }
        }
    }

    void SubtitleStream::flushBuffers()
    {
        m_delegate.didWipeOutSubtitles(*this);
        Stream::flushBuffers();
    }

    void SubtitleStream::ass_log(int ass_level, const char *fmt, va_list args, void *data)
    {
        char buffer[512];

        vsprintf(buffer, fmt, args);
        sfeLogDebug(buffer);
    }
}
<|endoftext|>


<commit_before>//////////////////////////////////////////////////////////////////////////
//
//  Copyright (c) 2014, John Haddon. All rights reserved.
//
//  Redistribution and use in source and binary forms, with or without
//  modification, are permitted provided that the following conditions are
//  met:
//
//      * Redistributions of source code must retain the above
//        copyright notice, this list of conditions and the following
//        disclaimer.
//
//      * Redistributions in binary form must reproduce the above
//        copyright notice, this list of conditions and the following
//        disclaimer in the documentation and/or other materials provided with
//        the distribution.
//
//      * Neither the name of John Haddon nor the names of
//        any other contributors to this software may be used to endorse or
//        promote products derived from this software without specific prior
//        written permission.
//
//  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
//  IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
//  THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
//  PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
//  CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
//  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
//  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
//  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
//  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
//  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
//  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
//////////////////////////////////////////////////////////////////////////

#include "GafferScene/FreezeTransform.h"

#include "Gaffer/Context.h"

#include "IECoreScene/Primitive.h"
#include "IECoreScene/TransformOp.h"

#include "IECore/DespatchTypedData.h"

using namespace std;
using namespace Imath;
using namespace IECore;
using namespace IECoreScene;
using namespace Gaffer;
using namespace GafferScene;

IE_CORE_DEFINERUNTIMETYPED( FreezeTransform );

size_t FreezeTransform::g_firstPlugIndex = 0;

FreezeTransform::FreezeTransform( const std::string &name )
	:	FilteredSceneProcessor( name, IECore::PathMatcher::EveryMatch )
{
	storeIndexOfNextChild( g_firstPlugIndex );
	addChild( new M44fPlug( "__transform", Plug::Out ) );

	// pass through the things we don't want to change
	outPlug()->attributesPlug()->setInput( inPlug()->attributesPlug() );
	outPlug()->childNamesPlug()->setInput( inPlug()->childNamesPlug() );
	outPlug()->globalsPlug()->setInput( inPlug()->globalsPlug() );
	outPlug()->setNamesPlug()->setInput( inPlug()->setNamesPlug() );
	outPlug()->setPlug()->setInput( inPlug()->setPlug() );
}

FreezeTransform::~FreezeTransform()
{
}

Gaffer::M44fPlug *FreezeTransform::transformPlug()
{
	return getChild<M44fPlug>( g_firstPlugIndex );
}

const Gaffer::M44fPlug *FreezeTransform::transformPlug() const
{
	return getChild<M44fPlug>( g_firstPlugIndex );
}

void FreezeTransform::affects( const Gaffer::Plug *input, AffectedPlugsContainer &outputs ) const
{
	FilteredSceneProcessor::affects( input, outputs );

	if( input == inPlug()->transformPlug() )
	{
		outputs.push_back( transformPlug() );
	}
	else if( input == inPlug()->objectPlug() )
	{
		outputs.push_back( outPlug()->objectPlug() );
	}
	else if(
		input == transformPlug() ||
		input == filterPlug()
	)
	{
		outputs.push_back( outPlug()->transformPlug() );
		outputs.push_back( outPlug()->boundPlug() );
		outputs.push_back( outPlug()->objectPlug() );
	}
}

void FreezeTransform::hash( const Gaffer::ValuePlug *output, const Gaffer::Context *context, IECore::MurmurHash &h ) const
{
	FilteredSceneProcessor::hash( output, context, h );

	if( output == transformPlug() )
	{
		const ScenePath &scenePath = context->get<ScenePath>( ScenePlug::scenePathContextName );
		h.append( inPlug()->fullTransformHash( scenePath ) );
		h.append( outPlug()->fullTransformHash( scenePath ) );
	}
}

void FreezeTransform::compute( Gaffer::ValuePlug *output, const Gaffer::Context *context ) const
{
	if( output == transformPlug() )
	{
		/// \todo Would it speed things up if we computed this from the parent full transforms and
		/// the local transforms? So we don't traverse the full path at each location?
		const ScenePath &scenePath = context->get<ScenePath>( ScenePlug::scenePathContextName );
		const M44f inTransform = inPlug()->fullTransform( scenePath );
		const M44f outTransform = outPlug()->fullTransform( scenePath );
		const M44f transform = inTransform * outTransform.inverse();
		static_cast<M44fPlug *>( output )->setValue( transform );
		return;
	}

	FilteredSceneProcessor::compute( output, context );
}

void FreezeTransform::hashBound( const ScenePath &path, const Gaffer::Context *context, const ScenePlug *parent, IECore::MurmurHash &h ) const
{
	const unsigned m = filterPlug()->getValue();
	if( m & ( IECore::PathMatcher::AncestorMatch | IECore::PathMatcher::ExactMatch ) )
	{
		// if there's an ancestor match or an exact match here then we know
		// that we'll be baking in a transform into the objects below us, and
		// thus changing the bounds - so we must compute them properly from
		// children.
		SceneProcessor::hashBound( path, context, parent, h );
		h.append( hashOfTransformedChildBounds( path, outPlug() ) );
		// we may also be changing the bounds at this specific location.
		inPlug()->boundPlug()->hash( h );
		transformPlug()->hash( h );
	}
	else
	{
		// if there's no match, we can just pass through the bound
		// unchanged. additionally, if there's a descendant match we
		// can do the same - because the descendant will just be transferring
		// the descendant transform into the descendant bound, the overall
		// bound as we see it will actually be remaining the same.
		h = inPlug()->boundPlug()->hash();
	}
}

Imath::Box3f FreezeTransform::computeBound( const ScenePath &path, const Gaffer::Context *context, const ScenePlug *parent ) const
{
	const unsigned m = filterPlug()->getValue();
	if( m & ( IECore::PathMatcher::AncestorMatch | IECore::PathMatcher::ExactMatch ) )
	{
		Box3f result = unionOfTransformedChildBounds( path, outPlug() );
		Box3f b = inPlug()->boundPlug()->getValue();
		b = transform( b, transformPlug()->getValue() );
		result.extendBy( b );
		return result;
	}
	else
	{
		return inPlug()->boundPlug()->getValue();
	}
}

void FreezeTransform::hashTransform( const ScenePath &path, const Gaffer::Context *context, const ScenePlug *parent, IECore::MurmurHash &h ) const
{
	const unsigned m = filterPlug()->getValue();
	if( m & IECore::PathMatcher::ExactMatch )
	{
		SceneProcessor::hashTransform( path, context, parent, h );
	}
	else
	{
		h = inPlug()->transformPlug()->hash();
	}
}

Imath::M44f FreezeTransform::computeTransform( const ScenePath &path, const Gaffer::Context *context, const ScenePlug *parent ) const
{
	const unsigned m = filterPlug()->getValue();
	if( m & IECore::PathMatcher::ExactMatch )
	{
		return M44f();
	}
	else
	{
		return inPlug()->transformPlug()->getValue();
	}
}

void FreezeTransform::hashObject( const ScenePath &path, const Gaffer::Context *context, const ScenePlug *parent, IECore::MurmurHash &h ) const
{
	const unsigned m = filterPlug()->getValue();
	if( m & ( IECore::PathMatcher::AncestorMatch | IECore::PathMatcher::ExactMatch ) )
	{
		FilteredSceneProcessor::hashObject( path, context, parent, h );
		inPlug()->objectPlug()->hash( h );
		transformPlug()->hash( h );
	}
	else
	{
		h = inPlug()->objectPlug()->hash();
	}
}

IECore::ConstObjectPtr FreezeTransform::computeObject( const ScenePath &path, const Gaffer::Context *context, const ScenePlug *parent ) const
{
	const unsigned m = filterPlug()->getValue();
	if( m & ( IECore::PathMatcher::AncestorMatch | IECore::PathMatcher::ExactMatch ) )
	{
		ConstObjectPtr inputObject = inPlug()->objectPlug()->getValue();
		const Primitive *inputPrimitive = runTimeCast<const Primitive>( inputObject.get() );
		if( !inputPrimitive )
		{
			return inputObject;
		}

		PrimitivePtr outputPrimitive = inputPrimitive->copy();

		/// \todo This is a pain - we need functionality in Cortex to just automatically apply
		/// the transform to all appropriate primitive variables, without having to manually
		/// list them. At the same time, we could add a PrimitiveAlgo.h file to Cortex, allowing
		/// us to apply a transform without having to create an Op to do it.
		vector<string> primVarNames;
		for( PrimitiveVariableMap::const_iterator it = inputPrimitive->variables.begin(), eIt = inputPrimitive->variables.end(); it != eIt; ++it )
		{
			if( despatchTraitsTest<TypeTraits::IsFloatVec3VectorTypedData>( it->second.data.get() ) )
			{
				primVarNames.push_back( it->first );
			}
		}

		const M44f transform = transformPlug()->getValue();

		TransformOpPtr transformOp = new TransformOp;
		transformOp->inputParameter()->setValue( outputPrimitive );
		transformOp->copyParameter()->setTypedValue( false );
		transformOp->matrixParameter()->setValue( new M44fData( transform ) );
		transformOp->primVarsParameter()->setTypedValue( primVarNames );
		transformOp->operate();

		return outputPrimitive;
	}
	else
	{
		return inPlug()->objectPlug()->getValue();
	}
}
<commit_msg>FreezeTransform : Replace `despatchTraitsTest()` with `DataAlgo::trait()`<commit_after>//////////////////////////////////////////////////////////////////////////
//
//  Copyright (c) 2014, John Haddon. All rights reserved.
//
//  Redistribution and use in source and binary forms, with or without
//  modification, are permitted provided that the following conditions are
//  met:
//
//      * Redistributions of source code must retain the above
//        copyright notice, this list of conditions and the following
//        disclaimer.
//
//      * Redistributions in binary form must reproduce the above
//        copyright notice, this list of conditions and the following
//        disclaimer in the documentation and/or other materials provided with
//        the distribution.
//
//      * Neither the name of John Haddon nor the names of
//        any other contributors to this software may be used to endorse or
//        promote products derived from this software without specific prior
//        written permission.
//
//  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
//  IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
//  THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
//  PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
//  CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
//  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
//  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
//  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
//  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
//  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
//  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
//////////////////////////////////////////////////////////////////////////

#include "GafferScene/FreezeTransform.h"

#include "Gaffer/Context.h"

#include "IECoreScene/Primitive.h"
#include "IECoreScene/TransformOp.h"

#include "IECore/DataAlgo.h"
#include "IECore/TypeTraits.h"

using namespace std;
using namespace Imath;
using namespace IECore;
using namespace IECoreScene;
using namespace Gaffer;
using namespace GafferScene;

IE_CORE_DEFINERUNTIMETYPED( FreezeTransform );

size_t FreezeTransform::g_firstPlugIndex = 0;

FreezeTransform::FreezeTransform( const std::string &name )
	:	FilteredSceneProcessor( name, IECore::PathMatcher::EveryMatch )
{
	storeIndexOfNextChild( g_firstPlugIndex );
	addChild( new M44fPlug( "__transform", Plug::Out ) );

	// pass through the things we don't want to change
	outPlug()->attributesPlug()->setInput( inPlug()->attributesPlug() );
	outPlug()->childNamesPlug()->setInput( inPlug()->childNamesPlug() );
	outPlug()->globalsPlug()->setInput( inPlug()->globalsPlug() );
	outPlug()->setNamesPlug()->setInput( inPlug()->setNamesPlug() );
	outPlug()->setPlug()->setInput( inPlug()->setPlug() );
}

FreezeTransform::~FreezeTransform()
{
}

Gaffer::M44fPlug *FreezeTransform::transformPlug()
{
	return getChild<M44fPlug>( g_firstPlugIndex );
}

const Gaffer::M44fPlug *FreezeTransform::transformPlug() const
{
	return getChild<M44fPlug>( g_firstPlugIndex );
}

void FreezeTransform::affects( const Gaffer::Plug *input, AffectedPlugsContainer &outputs ) const
{
	FilteredSceneProcessor::affects( input, outputs );

	if( input == inPlug()->transformPlug() )
	{
		outputs.push_back( transformPlug() );
	}
	else if( input == inPlug()->objectPlug() )
	{
		outputs.push_back( outPlug()->objectPlug() );
	}
	else if(
		input == transformPlug() ||
		input == filterPlug()
	)
	{
		outputs.push_back( outPlug()->transformPlug() );
		outputs.push_back( outPlug()->boundPlug() );
		outputs.push_back( outPlug()->objectPlug() );
	}
}

void FreezeTransform::hash( const Gaffer::ValuePlug *output, const Gaffer::Context *context, IECore::MurmurHash &h ) const
{
	FilteredSceneProcessor::hash( output, context, h );

	if( output == transformPlug() )
	{
		const ScenePath &scenePath = context->get<ScenePath>( ScenePlug::scenePathContextName );
		h.append( inPlug()->fullTransformHash( scenePath ) );
		h.append( outPlug()->fullTransformHash( scenePath ) );
	}
}

void FreezeTransform::compute( Gaffer::ValuePlug *output, const Gaffer::Context *context ) const
{
	if( output == transformPlug() )
	{
		/// \todo Would it speed things up if we computed this from the parent full transforms and
		/// the local transforms? So we don't traverse the full path at each location?
		const ScenePath &scenePath = context->get<ScenePath>( ScenePlug::scenePathContextName );
		const M44f inTransform = inPlug()->fullTransform( scenePath );
		const M44f outTransform = outPlug()->fullTransform( scenePath );
		const M44f transform = inTransform * outTransform.inverse();
		static_cast<M44fPlug *>( output )->setValue( transform );
		return;
	}

	FilteredSceneProcessor::compute( output, context );
}

void FreezeTransform::hashBound( const ScenePath &path, const Gaffer::Context *context, const ScenePlug *parent, IECore::MurmurHash &h ) const
{
	const unsigned m = filterPlug()->getValue();
	if( m & ( IECore::PathMatcher::AncestorMatch | IECore::PathMatcher::ExactMatch ) )
	{
		// if there's an ancestor match or an exact match here then we know
		// that we'll be baking in a transform into the objects below us, and
		// thus changing the bounds - so we must compute them properly from
		// children.
		SceneProcessor::hashBound( path, context, parent, h );
		h.append( hashOfTransformedChildBounds( path, outPlug() ) );
		// we may also be changing the bounds at this specific location.
		inPlug()->boundPlug()->hash( h );
		transformPlug()->hash( h );
	}
	else
	{
		// if there's no match, we can just pass through the bound
		// unchanged. additionally, if there's a descendant match we
		// can do the same - because the descendant will just be transferring
		// the descendant transform into the descendant bound, the overall
		// bound as we see it will actually be remaining the same.
		h = inPlug()->boundPlug()->hash();
	}
}

Imath::Box3f FreezeTransform::computeBound( const ScenePath &path, const Gaffer::Context *context, const ScenePlug *parent ) const
{
	const unsigned m = filterPlug()->getValue();
	if( m & ( IECore::PathMatcher::AncestorMatch | IECore::PathMatcher::ExactMatch ) )
	{
		Box3f result = unionOfTransformedChildBounds( path, outPlug() );
		Box3f b = inPlug()->boundPlug()->getValue();
		b = transform( b, transformPlug()->getValue() );
		result.extendBy( b );
		return result;
	}
	else
	{
		return inPlug()->boundPlug()->getValue();
	}
}

void FreezeTransform::hashTransform( const ScenePath &path, const Gaffer::Context *context, const ScenePlug *parent, IECore::MurmurHash &h ) const
{
	const unsigned m = filterPlug()->getValue();
	if( m & IECore::PathMatcher::ExactMatch )
	{
		SceneProcessor::hashTransform( path, context, parent, h );
	}
	else
	{
		h = inPlug()->transformPlug()->hash();
	}
}

Imath::M44f FreezeTransform::computeTransform( const ScenePath &path, const Gaffer::Context *context, const ScenePlug *parent ) const
{
	const unsigned m = filterPlug()->getValue();
	if( m & IECore::PathMatcher::ExactMatch )
	{
		return M44f();
	}
	else
	{
		return inPlug()->transformPlug()->getValue();
	}
}

void FreezeTransform::hashObject( const ScenePath &path, const Gaffer::Context *context, const ScenePlug *parent, IECore::MurmurHash &h ) const
{
	const unsigned m = filterPlug()->getValue();
	if( m & ( IECore::PathMatcher::AncestorMatch | IECore::PathMatcher::ExactMatch ) )
	{
		FilteredSceneProcessor::hashObject( path, context, parent, h );
		inPlug()->objectPlug()->hash( h );
		transformPlug()->hash( h );
	}
	else
	{
		h = inPlug()->objectPlug()->hash();
	}
}

IECore::ConstObjectPtr FreezeTransform::computeObject( const ScenePath &path, const Gaffer::Context *context, const ScenePlug *parent ) const
{
	const unsigned m = filterPlug()->getValue();
	if( m & ( IECore::PathMatcher::AncestorMatch | IECore::PathMatcher::ExactMatch ) )
	{
		ConstObjectPtr inputObject = inPlug()->objectPlug()->getValue();
		const Primitive *inputPrimitive = runTimeCast<const Primitive>( inputObject.get() );
		if( !inputPrimitive )
		{
			return inputObject;
		}

		PrimitivePtr outputPrimitive = inputPrimitive->copy();

		/// \todo This is a pain - we need functionality in Cortex to just automatically apply
		/// the transform to all appropriate primitive variables, without having to manually
		/// list them. At the same time, we could add a PrimitiveAlgo.h file to Cortex, allowing
		/// us to apply a transform without having to create an Op to do it.
		vector<string> primVarNames;
		for( PrimitiveVariableMap::const_iterator it = inputPrimitive->variables.begin(), eIt = inputPrimitive->variables.end(); it != eIt; ++it )
		{
			if( trait<TypeTraits::IsFloatVec3VectorTypedData>( it->second.data.get() ) )
			{
				primVarNames.push_back( it->first );
			}
		}

		const M44f transform = transformPlug()->getValue();

		TransformOpPtr transformOp = new TransformOp;
		transformOp->inputParameter()->setValue( outputPrimitive );
		transformOp->copyParameter()->setTypedValue( false );
		transformOp->matrixParameter()->setValue( new M44fData( transform ) );
		transformOp->primVarsParameter()->setTypedValue( primVarNames );
		transformOp->operate();

		return outputPrimitive;
	}
	else
	{
		return inPlug()->objectPlug()->getValue();
	}
}
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2007, Michael Feathers, James Grenning and Bas Vodde
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *     * Redistributions of source code must retain the above copyright
 *       notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above copyright
 *       notice, this list of conditions and the following disclaimer in the
 *       documentation and/or other materials provided with the distribution.
 *     * Neither the name of the <organization> nor the
 *       names of its contributors may be used to endorse or promote products
 *       derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE EARLIER MENTIONED AUTHORS ``AS IS'' AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL <copyright holder> BE LIABLE FOR ANY
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

/* Un-comment to use buffer instead of std out */
// #define USE_BUFFER_OUTPUT 1
#include <cstdlib>

#include "CppUTest/TestHarness.h"
#undef malloc
#undef free
#undef calloc
#undef realloc

#define  far  // eliminate "meaningless type qualifier" warning
#include <time.h>
#include <stdio.h>
#include <stdarg.h>
#include <setjmp.h>
#include <string.h>
#include <math.h>
#include <ctype.h>
#undef far

#include "CppUTest/PlatformSpecificFunctions.h"

static jmp_buf test_exit_jmp_buf[10];
static int jmp_buf_index = 0;

TestOutput::WorkingEnvironment PlatformSpecificGetWorkingEnvironment()
{
    return TestOutput::eclipse;
}

static void DummyRunTestInASeperateProcess(UtestShell* shell, TestPlugin* plugin, TestResult* result)
{
    result->addFailure(TestFailure(shell, "-p doesn't work on this platform, as it is lacking fork.\b"));
}

void (*PlatformSpecificRunTestInASeperateProcess)(UtestShell*, TestPlugin*, TestResult*) =
    DummyRunTestInASeperateProcess;

extern "C" {

static int DosSetJmp(void (*function) (void* data), void* data)
{
    if (0 == setjmp(test_exit_jmp_buf[jmp_buf_index])) {
        jmp_buf_index++;
        function(data);
        jmp_buf_index--;
        return 1;
    }
    return 0;
}

static void  DosLongJmp()
{
    jmp_buf_index--;
    longjmp(test_exit_jmp_buf[jmp_buf_index], 1);
}

static void  DosRestoreJumpBuffer()
{
    jmp_buf_index--;
}

int (*PlatformSpecificSetJmp)(void (*function) (void*), void*) = DosSetJmp;
void (*PlatformSpecificLongJmp)(void) = DosLongJmp;
void (*PlatformSpecificRestoreJumpBuffer)(void) = DosRestoreJumpBuffer;

static long DosTimeInMillis()
{
    return clock() * 1000 / CLOCKS_PER_SEC;
}

static const char* TimeStringImplementation()
{
    time_t tm = time(NULL);
    return ctime(&tm);
}

long (*GetPlatformSpecificTimeInMillis)() = DosTimeInMillis;
const char* (*GetPlatformSpecificTimeString)() = TimeStringImplementation;

extern int (*PlatformSpecificVSNprintf)(char *, size_t, const char*, va_list) = vsnprintf;

PlatformSpecificFile DosFOpen(const char* filename, const char* flag)
{
    return fopen(filename, flag);
}

static void DosFPuts(const char* str, PlatformSpecificFile file)
{
   fputs(str, (FILE*)file);
}

static void DosFClose(PlatformSpecificFile file)
{
   fclose((FILE*)file);
}

PlatformSpecificFile (*PlatformSpecificFOpen)(const char* filename, const char* flag) = DosFOpen;
void (*PlatformSpecificFPuts)(const char* str, PlatformSpecificFile file) = DosFPuts;
void (*PlatformSpecificFClose)(PlatformSpecificFile file) = DosFClose;

static int DosPutchar(int c)
{
    return putchar(c);
}

static void DosFlush()
{
  fflush(stdout);
}

extern int (*PlatformSpecificPutchar)(int c) = DosPutchar;
extern void (*PlatformSpecificFlush)(void) = DosFlush;

static void* DosMalloc(size_t size)
{
   return malloc(size);
}

static void* DosRealloc (void* memory, size_t size)
{
    return realloc(memory, size);
}

static void DosFree(void* memory)
{
    free(memory);
}

static void* DosMemCpy(void* s1, const void* s2, size_t size)
{
    return memcpy(s1, s2, size);
}

static void* DosMemset(void* mem, int c, size_t size)
{
    return memset(mem, c, size);
}

void* (*PlatformSpecificMalloc)(size_t size) = DosMalloc;
void* (*PlatformSpecificRealloc)(void* memory, size_t size) = DosRealloc;
void (*PlatformSpecificFree)(void* memory) = DosFree;
void* (*PlatformSpecificMemCpy)(void* s1, const void* s2, size_t size) = DosMemCpy;
void* (*PlatformSpecificMemset)(void* mem, int c, size_t size) = DosMemset;

static int IsNanImplementation(double d)
{
    return isnan(d);
}

static int IsInfImplementation(double d)
{
    return isinf(d);
}

double (*PlatformSpecificFabs)(double) = fabs;
int (*PlatformSpecificIsNan)(double d) = IsNanImplementation;
int (*PlatformSpecificIsInf)(double d) = IsInfImplementation;

static PlatformSpecificMutex DummyMutexCreate(void)
{
    return 0;
}

static void DummyMutexLock(PlatformSpecificMutex mtx)
{
}

static void DummyMutexUnlock(PlatformSpecificMutex mtx)
{
}

static void DummyMutexDestroy(PlatformSpecificMutex mtx)
{
}

PlatformSpecificMutex (*PlatformSpecificMutexCreate)(void) = DummyMutexCreate;
void (*PlatformSpecificMutexLock)(PlatformSpecificMutex) = DummyMutexLock;
void (*PlatformSpecificMutexUnlock)(PlatformSpecificMutex) = DummyMutexUnlock;
void (*PlatformSpecificMutexDestroy)(PlatformSpecificMutex) = DummyMutexDestroy;

}
<commit_msg>remove superfluous extern<commit_after>/*
 * Copyright (c) 2007, Michael Feathers, James Grenning and Bas Vodde
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *     * Redistributions of source code must retain the above copyright
 *       notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above copyright
 *       notice, this list of conditions and the following disclaimer in the
 *       documentation and/or other materials provided with the distribution.
 *     * Neither the name of the <organization> nor the
 *       names of its contributors may be used to endorse or promote products
 *       derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE EARLIER MENTIONED AUTHORS ``AS IS'' AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL <copyright holder> BE LIABLE FOR ANY
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

/* Un-comment to use buffer instead of std out */
// #define USE_BUFFER_OUTPUT 1
#include <cstdlib>

#include "CppUTest/TestHarness.h"
#undef malloc
#undef free
#undef calloc
#undef realloc

#define  far  // eliminate "meaningless type qualifier" warning
#include <time.h>
#include <stdio.h>
#include <stdarg.h>
#include <setjmp.h>
#include <string.h>
#include <math.h>
#include <ctype.h>
#undef far

#include "CppUTest/PlatformSpecificFunctions.h"

static jmp_buf test_exit_jmp_buf[10];
static int jmp_buf_index = 0;

TestOutput::WorkingEnvironment PlatformSpecificGetWorkingEnvironment()
{
    return TestOutput::eclipse;
}

static void DummyRunTestInASeperateProcess(UtestShell* shell, TestPlugin* plugin, TestResult* result)
{
    result->addFailure(TestFailure(shell, "-p doesn't work on this platform, as it is lacking fork.\b"));
}

void (*PlatformSpecificRunTestInASeperateProcess)(UtestShell*, TestPlugin*, TestResult*) =
    DummyRunTestInASeperateProcess;

extern "C" {

static int DosSetJmp(void (*function) (void* data), void* data)
{
    if (0 == setjmp(test_exit_jmp_buf[jmp_buf_index])) {
        jmp_buf_index++;
        function(data);
        jmp_buf_index--;
        return 1;
    }
    return 0;
}

static void  DosLongJmp()
{
    jmp_buf_index--;
    longjmp(test_exit_jmp_buf[jmp_buf_index], 1);
}

static void  DosRestoreJumpBuffer()
{
    jmp_buf_index--;
}

int (*PlatformSpecificSetJmp)(void (*function) (void*), void*) = DosSetJmp;
void (*PlatformSpecificLongJmp)(void) = DosLongJmp;
void (*PlatformSpecificRestoreJumpBuffer)(void) = DosRestoreJumpBuffer;

static long DosTimeInMillis()
{
    return clock() * 1000 / CLOCKS_PER_SEC;
}

static const char* TimeStringImplementation()
{
    time_t tm = time(NULL);
    return ctime(&tm);
}

long (*GetPlatformSpecificTimeInMillis)() = DosTimeInMillis;
const char* (*GetPlatformSpecificTimeString)() = TimeStringImplementation;

int (*PlatformSpecificVSNprintf)(char *, size_t, const char*, va_list) = vsnprintf;

PlatformSpecificFile DosFOpen(const char* filename, const char* flag)
{
    return fopen(filename, flag);
}

static void DosFPuts(const char* str, PlatformSpecificFile file)
{
   fputs(str, (FILE*)file);
}

static void DosFClose(PlatformSpecificFile file)
{
   fclose((FILE*)file);
}

PlatformSpecificFile (*PlatformSpecificFOpen)(const char* filename, const char* flag) = DosFOpen;
void (*PlatformSpecificFPuts)(const char* str, PlatformSpecificFile file) = DosFPuts;
void (*PlatformSpecificFClose)(PlatformSpecificFile file) = DosFClose;

static int DosPutchar(int c)
{
    return putchar(c);
}

static void DosFlush()
{
  fflush(stdout);
}

extern int (*PlatformSpecificPutchar)(int c) = DosPutchar;
extern void (*PlatformSpecificFlush)(void) = DosFlush;

static void* DosMalloc(size_t size)
{
   return malloc(size);
}

static void* DosRealloc (void* memory, size_t size)
{
    return realloc(memory, size);
}

static void DosFree(void* memory)
{
    free(memory);
}

static void* DosMemCpy(void* s1, const void* s2, size_t size)
{
    return memcpy(s1, s2, size);
}

static void* DosMemset(void* mem, int c, size_t size)
{
    return memset(mem, c, size);
}

void* (*PlatformSpecificMalloc)(size_t size) = DosMalloc;
void* (*PlatformSpecificRealloc)(void* memory, size_t size) = DosRealloc;
void (*PlatformSpecificFree)(void* memory) = DosFree;
void* (*PlatformSpecificMemCpy)(void* s1, const void* s2, size_t size) = DosMemCpy;
void* (*PlatformSpecificMemset)(void* mem, int c, size_t size) = DosMemset;

static int IsNanImplementation(double d)
{
    return isnan(d);
}

static int IsInfImplementation(double d)
{
    return isinf(d);
}

double (*PlatformSpecificFabs)(double) = fabs;
int (*PlatformSpecificIsNan)(double d) = IsNanImplementation;
int (*PlatformSpecificIsInf)(double d) = IsInfImplementation;

static PlatformSpecificMutex DummyMutexCreate(void)
{
    return 0;
}

static void DummyMutexLock(PlatformSpecificMutex mtx)
{
}

static void DummyMutexUnlock(PlatformSpecificMutex mtx)
{
}

static void DummyMutexDestroy(PlatformSpecificMutex mtx)
{
}

PlatformSpecificMutex (*PlatformSpecificMutexCreate)(void) = DummyMutexCreate;
void (*PlatformSpecificMutexLock)(PlatformSpecificMutex) = DummyMutexLock;
void (*PlatformSpecificMutexUnlock)(PlatformSpecificMutex) = DummyMutexUnlock;
void (*PlatformSpecificMutexDestroy)(PlatformSpecificMutex) = DummyMutexDestroy;

}
<|endoftext|>


<commit_before>/*
 * Qumulus UML editor
 * Author: Frank Erens
 * Author: Randy Thiemann
 *
 */

#include "SideBar.h"
#include <Gui/Widgets/MainWindow.h>

#include <QtWidgets/QHeaderView>

#include <iostream>

QUML_BEGIN_NAMESPACE_GW

SideBar::SideBar(MainWindow* parent, QuGD::Diagram* d) :
        QTreeView(parent),
        mDiagram(d),
        mModel(new QuGC::SideBarModel(mDiagram)){
#ifdef Q_OS_MAC
    setStyleType(StyleType::Active);
    setAttribute(Qt::WA_MacShowFocusRect, false);
#endif
    setMinimumWidth(100);
    QSizePolicy sideBarSizePolicy = sizePolicy();
    sideBarSizePolicy.setHorizontalPolicy(QSizePolicy::Minimum);
    setSizePolicy(sideBarSizePolicy);
    setModel(mModel);
    header()->close();
    mDiagram->diagramChanged += [this] {
        collapseAll();
        expandAll();
    };
}

SideBar::~SideBar() {
    delete mModel;
}

MainWindow* SideBar::window() {
    return static_cast<MainWindow*>(parent());
}

#ifdef Q_OS_MAC
void SideBar::setStyleType(StyleType s) {
    switch(s) {
    case StyleType::Active:
        setStyleSheet(
            "background-color: qlineargradient("
                    "spread:pad, x1:0, y1:0, x2:0, y2:1,"
                    "stop:0 rgba(232, 236, 241, 255),"
                    "stop:1 rgba(209,216,226, 255));"
            "selection-color: white;"
            "selection-background-color: qlineargradient("
                    "x1: 0, y1: 0, x2: 0, y2: 1,"
                    "stop: 0 rgb(110, 165, 218),"
                    "stop: 1 rgb(33, 108, 183));"
            "border-top: 1px solid silver;"
            "border-bottom: 1px solid silver;"
            "font-size: 11pt;"
        );
        break;
    case StyleType::Inactive:
        setStyleSheet(
            "background-color: qlineargradient("
            "spread:pad, x1:0, y1:0, x2:0, y2:1,"
            "stop:0 rgba(247, 247, 247, 255),"
            "stop:1 rgba(235, 235, 235, 255));"
            "selection-color: white;"
            "selection-background-color: qlineargradient("
                    "x1: 0, y1: 0, x2: 0, y2: 1,"
                    "stop: 0 rgb(110, 165, 218),"
                    "stop: 1 rgb(33, 108, 183));"
            "border-top: 1px solid silver;"
            "border-bottom: 1px solid silver;"
            "font-size: 11pt;"
        );
        break;
    }

}
#endif

QUML_END_NAMESPACE_GW

<commit_msg>Debug: remove all autocollapse features.<commit_after>/*
 * Qumulus UML editor
 * Author: Frank Erens
 * Author: Randy Thiemann
 *
 */

#include "SideBar.h"
#include <Gui/Widgets/MainWindow.h>

#include <QtWidgets/QHeaderView>

#include <iostream>

QUML_BEGIN_NAMESPACE_GW

SideBar::SideBar(MainWindow* parent, QuGD::Diagram* d) :
        QTreeView(parent),
        mDiagram(d),
        mModel(new QuGC::SideBarModel(mDiagram)){
#ifdef Q_OS_MAC
    setStyleType(StyleType::Active);
    setAttribute(Qt::WA_MacShowFocusRect, false);
#endif
    setMinimumWidth(100);
    QSizePolicy sideBarSizePolicy = sizePolicy();
    sideBarSizePolicy.setHorizontalPolicy(QSizePolicy::Minimum);
    setSizePolicy(sideBarSizePolicy);
    setModel(mModel);
    header()->close();
    // mDiagram->diagramChanged += [this] {
    //     collapseAll();
    //     expandAll();
    // };
}

SideBar::~SideBar() {
    delete mModel;
}

MainWindow* SideBar::window() {
    return static_cast<MainWindow*>(parent());
}

#ifdef Q_OS_MAC
void SideBar::setStyleType(StyleType s) {
    switch(s) {
    case StyleType::Active:
        setStyleSheet(
            "background-color: qlineargradient("
                    "spread:pad, x1:0, y1:0, x2:0, y2:1,"
                    "stop:0 rgba(232, 236, 241, 255),"
                    "stop:1 rgba(209,216,226, 255));"
            "selection-color: white;"
            "selection-background-color: qlineargradient("
                    "x1: 0, y1: 0, x2: 0, y2: 1,"
                    "stop: 0 rgb(110, 165, 218),"
                    "stop: 1 rgb(33, 108, 183));"
            "border-top: 1px solid silver;"
            "border-bottom: 1px solid silver;"
            "font-size: 11pt;"
        );
        break;
    case StyleType::Inactive:
        setStyleSheet(
            "background-color: qlineargradient("
            "spread:pad, x1:0, y1:0, x2:0, y2:1,"
            "stop:0 rgba(247, 247, 247, 255),"
            "stop:1 rgba(235, 235, 235, 255));"
            "selection-color: white;"
            "selection-background-color: qlineargradient("
                    "x1: 0, y1: 0, x2: 0, y2: 1,"
                    "stop: 0 rgb(110, 165, 218),"
                    "stop: 1 rgb(33, 108, 183));"
            "border-top: 1px solid silver;"
            "border-bottom: 1px solid silver;"
            "font-size: 11pt;"
        );
        break;
    }

}
#endif

QUML_END_NAMESPACE_GW

<|endoftext|>


<commit_before>#ifndef STAN__MATH__PRIM__SCAL__PROB__NORMAL_SUFFICIENT_LOG_HPP
#define STAN__MATH__PRIM__SCAL__PROB__NORMAL_SUFFICIENT_LOG_HPP

#include <stan/math/prim/scal/meta/OperandsAndPartials.hpp>
#include <stan/math/prim/scal/err/check_consistent_sizes.hpp>
#include <stan/math/prim/scal/err/check_finite.hpp>
#include <stan/math/prim/scal/err/check_not_nan.hpp>
#include <stan/math/prim/scal/err/check_positive.hpp>
#include <stan/math/prim/scal/fun/constants.hpp>
#include <stan/math/prim/scal/fun/value_of.hpp>
#include <stan/math/prim/scal/meta/include_summand.hpp>
#include <stan/math/prim/scal/meta/VectorBuilder.hpp>
#include <stan/math/prim/scal/meta/max_size.hpp>

namespace stan {

  namespace math {

    /**
     * The log of the normal density for the specified scalar(s) given
     * the specified mean(s) and deviation(s). y, mu, or sigma can
     * each be either a scalar or a std vector. Any vector inputs
     * must be the same length.
     *
     *
The result log probability is defined to be the sum of the
     * log probabilities for each observation/mean/deviation triple.
     * @param y (Sequence of) scalar(s).
     * @param mu (Sequence of) location parameter(s)
     * for the normal distribution.
     * @param sigma (Sequence of) scale parameters for the normal
     * distribution.
     * @return The log of the product of the densities.
     * @throw std::domain_error if the scale is not positive.
     * @tparam T_y Underlying type of scalar in sequence.
     * @tparam T_loc Type of location parameter.
     */
    template <bool propto,
              typename T_y, typename T_s, typename T_n, typename T_loc,
              typename T_scale>
    typename return_type<T_y, T_s, T_loc, T_scale>::type
    normal_sufficient_log(const T_y& y_bar, const T_s& s_squared,
                          const T_n& n_obs, const T_loc& mu,
                          const T_scale& sigma) {
      static const char* function = "stan::math::normal_log(%1%)";
      typedef typename
        stan::partials_return_type<T_y, T_s, T_n, T_loc, T_scale>::type
        T_partials_return;

      using std::log;
      using stan::is_constant_struct;
      using stan::math::check_positive;
      using stan::math::check_finite;
      using stan::math::check_not_nan;
      using stan::math::check_consistent_sizes;
      using stan::math::value_of;
      using stan::math::include_summand;

      // check if any vectors are zero length
      if (!(stan::length(y_bar)
            && stan::length(s_squared)
            && stan::length(n_obs)
            && stan::length(mu)
            && stan::length(sigma)))
        return 0.0;

      // set up return value accumulator
      T_partials_return logp(0.0);

      // validate args (here done over var, which should be OK)
      check_not_nan(function,
                    "Location parameter sufficient statistic", y_bar);
      check_not_nan(function,
                    "Scale parameter sufficient statistic", s_squared);
      check_not_nan(function,
                    "Number of observations", n_obs);
      check_finite(function,
                    "Number of observations", n_obs);
      check_positive(function,
                    "Number of observations", n_obs);
      check_finite(function,
                    "Location parameter", mu);
      check_positive(function, "Scale parameter", sigma);
      check_consistent_sizes(function,
                             "Location parameter sufficient statistic",
                             y_bar,
                             "Scale parameter sufficient statistic",
                             s_squared,
                             "Number of observations", n_obs,
                             "Location parameter", mu,
                             "Scale parameter", sigma);
      // check if no variables are involved and prop-to
      if (!include_summand<propto, T_y, T_s, T_loc, T_scale>::value)
        return 0.0;

      // set up template expressions wrapping scalars into vector views
      OperandsAndPartials<T_y, T_s, T_loc, T_scale>
        operands_and_partials(y_bar, s_squared, mu, sigma);

      VectorView<const T_y> y_bar_vec(y_bar);
      VectorView<const T_s> s_squared_vec(s_squared);
      VectorView<const T_n> n_obs_vec(n_obs);
      VectorView<const T_loc> mu_vec(mu);
      VectorView<const T_scale> sigma_vec(sigma);
      size_t N = max_size(y_bar, s_squared, n_obs, mu, sigma);

      for (size_t i = 0; i < N; i++) {
        const T_partials_return y_bar_dbl = value_of(y_bar_vec[i]);
        const T_partials_return s_squared_dbl =
          value_of(s_squared_vec[i]);
        const T_partials_return n_obs_dbl = n_obs_vec[i];
        const T_partials_return mu_dbl = value_of(mu_vec[i]);
        const T_partials_return sigma_dbl = value_of(sigma_vec[i]);
        const T_partials_return sigma_squared = pow(sigma_dbl, 2);

        if (include_summand<propto>::value)
          logp += NEG_LOG_SQRT_TWO_PI * n_obs_dbl;

        if (include_summand<propto, T_scale>::value)
          logp -= n_obs_dbl*log(sigma_dbl);

        const T_partials_return cons_expr =
          (s_squared_dbl
           + n_obs_dbl * pow(y_bar_dbl - mu_dbl, 2));

        logp -= cons_expr / (2 * sigma_squared);

        // gradients
        if (!is_constant_struct<T_y>::value ||
            !is_constant_struct<T_loc>::value) {
          const T_partials_return common_derivative =
            n_obs_dbl * (mu_dbl - y_bar_dbl) / sigma_squared;
          if (!is_constant_struct<T_y>::value)
            operands_and_partials.d_x1[i] += common_derivative;
          if (!is_constant_struct<T_loc>::value)
            operands_and_partials.d_x3[i] -= common_derivative;
        }
        if (!is_constant_struct<T_s>::value)
          operands_and_partials.d_x2[i] -=
            1 / (2 * sigma_squared);
        if (!is_constant_struct<T_scale>::value)
          operands_and_partials.d_x4[i]
            += cons_expr / pow(sigma_dbl, 3) - n_obs_dbl / sigma_dbl;
      }
      return
        operands_and_partials.to_var(logp, y_bar, s_squared, mu, sigma);
    }

    template <typename T_y, typename T_s, typename T_n,
              typename T_loc, typename T_scale>
    inline
    typename return_type<T_y, T_s, T_loc, T_scale>::type
    normal_sufficient_log(const T_y& y_bar, const T_s& s_squared,
                          const T_n& n_obs, const T_loc& mu,
                          const T_scale& sigma) {
      return
        normal_sufficient_log<false>(y_bar, s_squared, n_obs, mu, sigma);
    }

  }
}
#endif
<commit_msg>822: remove double underscore<commit_after>#ifndef STAN_MATH_PRIM_SCAL_PROB_NORMAL_SUFFICIENT_LOG_HPP
#define STAN_MATH_PRIM_SCAL_PROB_NORMAL_SUFFICIENT_LOG_HPP

#include <stan/math/prim/scal/meta/OperandsAndPartials.hpp>
#include <stan/math/prim/scal/err/check_consistent_sizes.hpp>
#include <stan/math/prim/scal/err/check_finite.hpp>
#include <stan/math/prim/scal/err/check_not_nan.hpp>
#include <stan/math/prim/scal/err/check_positive.hpp>
#include <stan/math/prim/scal/fun/constants.hpp>
#include <stan/math/prim/scal/fun/value_of.hpp>
#include <stan/math/prim/scal/meta/include_summand.hpp>
#include <stan/math/prim/scal/meta/VectorBuilder.hpp>
#include <stan/math/prim/scal/meta/max_size.hpp>

namespace stan {

  namespace math {

    /**
     * The log of the normal density for the specified scalar(s) given
     * the specified mean(s) and deviation(s). y, mu, or sigma can
     * each be either a scalar or a std vector. Any vector inputs
     * must be the same length.
     *
     *
The result log probability is defined to be the sum of the
     * log probabilities for each observation/mean/deviation triple.
     * @param y (Sequence of) scalar(s).
     * @param mu (Sequence of) location parameter(s)
     * for the normal distribution.
     * @param sigma (Sequence of) scale parameters for the normal
     * distribution.
     * @return The log of the product of the densities.
     * @throw std::domain_error if the scale is not positive.
     * @tparam T_y Underlying type of scalar in sequence.
     * @tparam T_loc Type of location parameter.
     */
    template <bool propto,
              typename T_y, typename T_s, typename T_n, typename T_loc,
              typename T_scale>
    typename return_type<T_y, T_s, T_loc, T_scale>::type
    normal_sufficient_log(const T_y& y_bar, const T_s& s_squared,
                          const T_n& n_obs, const T_loc& mu,
                          const T_scale& sigma) {
      static const char* function = "stan::math::normal_log(%1%)";
      typedef typename
        stan::partials_return_type<T_y, T_s, T_n, T_loc, T_scale>::type
        T_partials_return;

      using std::log;
      using stan::is_constant_struct;
      using stan::math::check_positive;
      using stan::math::check_finite;
      using stan::math::check_not_nan;
      using stan::math::check_consistent_sizes;
      using stan::math::value_of;
      using stan::math::include_summand;

      // check if any vectors are zero length
      if (!(stan::length(y_bar)
            && stan::length(s_squared)
            && stan::length(n_obs)
            && stan::length(mu)
            && stan::length(sigma)))
        return 0.0;

      // set up return value accumulator
      T_partials_return logp(0.0);

      // validate args (here done over var, which should be OK)
      check_not_nan(function,
                    "Location parameter sufficient statistic", y_bar);
      check_not_nan(function,
                    "Scale parameter sufficient statistic", s_squared);
      check_not_nan(function,
                    "Number of observations", n_obs);
      check_finite(function,
                    "Number of observations", n_obs);
      check_positive(function,
                    "Number of observations", n_obs);
      check_finite(function,
                    "Location parameter", mu);
      check_positive(function, "Scale parameter", sigma);
      check_consistent_sizes(function,
                             "Location parameter sufficient statistic",
                             y_bar,
                             "Scale parameter sufficient statistic",
                             s_squared,
                             "Number of observations", n_obs,
                             "Location parameter", mu,
                             "Scale parameter", sigma);
      // check if no variables are involved and prop-to
      if (!include_summand<propto, T_y, T_s, T_loc, T_scale>::value)
        return 0.0;

      // set up template expressions wrapping scalars into vector views
      OperandsAndPartials<T_y, T_s, T_loc, T_scale>
        operands_and_partials(y_bar, s_squared, mu, sigma);

      VectorView<const T_y> y_bar_vec(y_bar);
      VectorView<const T_s> s_squared_vec(s_squared);
      VectorView<const T_n> n_obs_vec(n_obs);
      VectorView<const T_loc> mu_vec(mu);
      VectorView<const T_scale> sigma_vec(sigma);
      size_t N = max_size(y_bar, s_squared, n_obs, mu, sigma);

      for (size_t i = 0; i < N; i++) {
        const T_partials_return y_bar_dbl = value_of(y_bar_vec[i]);
        const T_partials_return s_squared_dbl =
          value_of(s_squared_vec[i]);
        const T_partials_return n_obs_dbl = n_obs_vec[i];
        const T_partials_return mu_dbl = value_of(mu_vec[i]);
        const T_partials_return sigma_dbl = value_of(sigma_vec[i]);
        const T_partials_return sigma_squared = pow(sigma_dbl, 2);

        if (include_summand<propto>::value)
          logp += NEG_LOG_SQRT_TWO_PI * n_obs_dbl;

        if (include_summand<propto, T_scale>::value)
          logp -= n_obs_dbl*log(sigma_dbl);

        const T_partials_return cons_expr =
          (s_squared_dbl
           + n_obs_dbl * pow(y_bar_dbl - mu_dbl, 2));

        logp -= cons_expr / (2 * sigma_squared);

        // gradients
        if (!is_constant_struct<T_y>::value ||
            !is_constant_struct<T_loc>::value) {
          const T_partials_return common_derivative =
            n_obs_dbl * (mu_dbl - y_bar_dbl) / sigma_squared;
          if (!is_constant_struct<T_y>::value)
            operands_and_partials.d_x1[i] += common_derivative;
          if (!is_constant_struct<T_loc>::value)
            operands_and_partials.d_x3[i] -= common_derivative;
        }
        if (!is_constant_struct<T_s>::value)
          operands_and_partials.d_x2[i] -=
            1 / (2 * sigma_squared);
        if (!is_constant_struct<T_scale>::value)
          operands_and_partials.d_x4[i]
            += cons_expr / pow(sigma_dbl, 3) - n_obs_dbl / sigma_dbl;
      }
      return
        operands_and_partials.to_var(logp, y_bar, s_squared, mu, sigma);
    }

    template <typename T_y, typename T_s, typename T_n,
              typename T_loc, typename T_scale>
    inline
    typename return_type<T_y, T_s, T_loc, T_scale>::type
    normal_sufficient_log(const T_y& y_bar, const T_s& s_squared,
                          const T_n& n_obs, const T_loc& mu,
                          const T_scale& sigma) {
      return
        normal_sufficient_log<false>(y_bar, s_squared, n_obs, mu, sigma);
    }

  }
}
#endif
<|endoftext|>


<commit_before>/** \copyright
 * Copyright (c) 2013, Balazs Racz
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are  permitted provided that the following conditions are met:
 *
 *  - Redistributions of source code must retain the above copyright notice,
 *    this list of conditions and the following disclaimer.
 *
 *  - Redistributions in binary form must reproduce the above copyright notice,
 *    this list of conditions and the following disclaimer in the documentation
 *    and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * \file main.cxx
 *
 * Main file for the io board application on the Tiva Launchpad board.
 *
 * @author Balazs Racz
 * @date 5 Jun 2015
 */

#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>

#include "os/os.h"
#include "can_frame.h"
#include "nmranet_config.h"

#include "os/TempFile.hxx"
#include "nmranet/SimpleStack.hxx"
#include "nmranet/SimpleNodeInfoMockUserFile.hxx"
#include "nmranet/EventHandlerTemplates.hxx"
#include "nmranet/ConfigRepresentation.hxx"
#include "utils/ConfigUpdateListener.hxx"

#include "freertos_drivers/ti/TivaGPIO.hxx"

extern const nmranet::NodeID NODE_ID;

OVERRIDE_CONST(gc_generate_newlines, 1);
OVERRIDE_CONST(main_thread_stack_size, 2500);
OVERRIDE_CONST(num_memory_spaces, 4);

nmranet::SimpleCanStack stack(NODE_ID);

nmranet::MockSNIPUserFile snip_user_file(
    "Default user name", "Default user description");
const char *const nmranet::SNIP_DYNAMIC_FILENAME =
    nmranet::MockSNIPUserFile::snip_user_file_path;

namespace nmranet
{
BEGIN_GROUP(ConsumerConfig, base);
EXTEND_GROUP(ConsumerConfig, base, event_on, EventConfigEntry);
EXTEND_GROUP(ConsumerConfig, event_on, event_off, EventConfigEntry);
END_GROUP(ConsumerConfig, event_off);

using AllConsumers = RepeatedGroup<ConsumerConfig, 3>;

BEGIN_GROUP(ProducerConfig, base);
EXTEND_GROUP(ProducerConfig, base, debounce, Uint8ConfigEntry);
EXTEND_GROUP(ProducerConfig, debounce, event_on, EventConfigEntry);
EXTEND_GROUP(ProducerConfig, event_on, event_off, EventConfigEntry);
END_GROUP(ProducerConfig, event_off);

using AllProducers = RepeatedGroup<ProducerConfig, 2>;

BEGIN_GROUP(ConfigDef, base);
EXTEND_GROUP(ConfigDef, base, snip_data, EmptyGroup<128>);
EXTEND_GROUP(ConfigDef, snip_data, consumers, AllConsumers);
EXTEND_GROUP(ConfigDef, consumers, producers, AllProducers);
END_GROUP(ConfigDef, consumers);

static_assert(ConfigDef::size() <= 256, "Need to adjust eeprom size");

typedef bool (*getter_fn_t)();
typedef void (*setter_fn_t)(bool);

class ConfiguredConsumer : public ConfigUpdateListener
{
public:
    class Impl : public BitEventInterface
    {
    public:
        Impl(EventId event_on, EventId event_off, getter_fn_t getter,
            setter_fn_t setter)
            : BitEventInterface(event_on, event_off)
            , getter_(getter)
            , setter_(setter)
        {
        }

        bool GetCurrentState() OVERRIDE
        {
            return getter_();
        }
        void SetState(bool new_value) OVERRIDE
        {
            setter_(new_value);
        }
        Node *node() OVERRIDE
        {
            return stack.node();
        }

    public:
        const getter_fn_t getter_;
        const setter_fn_t setter_;
    };

    template <class HW>
    ConfiguredConsumer(const ConsumerConfig &cfg, const HW &)
        : impl_(0, 0, &HW::get, &HW::set)
        , consumer_(&impl_)
        , cfg_(cfg)
    {
    }

    UpdateAction apply_configuration(
        int fd, bool initial_load, BarrierNotifiable *done)
    {
        AutoNotify n(done);
        EventId cfg_event_on = cfg_.event_on().read(fd);
        EventId cfg_event_off = cfg_.event_off().read(fd);
        if (cfg_event_off != impl_.event_off() ||
            cfg_event_on != impl_.event_on())
        {
            auto saved_setter = impl_.setter_;
            auto saved_getter = impl_.getter_;
            // Need to reinitialize the consumer. We do this with in-place
            // destruction and construction.
            consumer_.~BitEventConsumer();
            impl_.~Impl();
            new (&impl_)
                Impl(cfg_event_on, cfg_event_off, saved_getter, saved_setter);
            new (&consumer_) BitEventConsumer(&impl_);
            return REINIT_NEEDED;
        }
        return UPDATED;
    }

    ///@TODO(balazs.racz): implement
    void factory_reset(int fd) OVERRIDE
    {
    }

private:
    Impl impl_;
    BitEventConsumer consumer_;
    const ConsumerConfig cfg_;
};

} // namespace nmranet

GPIO_PIN(LED_RED, LedPin, F, 1);
GPIO_PIN(LED_GREEN, LedPin, F, 3);
GPIO_PIN(LED_BLUE, LedPin, F, 2);

GPIO_PIN(SW1, GpioInputPU, F, 4);

nmranet::ConfigDef cfg(0);

nmranet::ConfiguredConsumer consumer_red(
    cfg.consumers().entry<0>(), LED_RED_Pin());
nmranet::ConfiguredConsumer consumer_green(
    cfg.consumers().entry<1>(), LED_GREEN_Pin());
nmranet::ConfiguredConsumer consumer_blue(
    cfg.consumers().entry<2>(), LED_BLUE_Pin());

/** Entry point to application.
 * @param argc number of command line arguments
 * @param argv array of command line arguments
 * @return 0, should never return
 */
int appl_main(int argc, char *argv[])
{
#if defined(HAVE_PHYSICAL_CAN_PORT)
    stack.add_can_port_select("/dev/can0");
#endif

// Enable this to add sniffing through the usb or serial port.
#if defined(SNIFF_ON_USB)
    stack.add_gridconnect_port("/dev/serUSB0");
#endif
#if defined(SNIFF_ON_SERIAL)
    stack.add_gridconnect_port("/dev/ser0");
#endif

    stack.loop_executor();
    return 0;
}
<commit_msg>Adds explanation comment.<commit_after>/** \copyright
 * Copyright (c) 2013, Balazs Racz
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are  permitted provided that the following conditions are met:
 *
 *  - Redistributions of source code must retain the above copyright notice,
 *    this list of conditions and the following disclaimer.
 *
 *  - Redistributions in binary form must reproduce the above copyright notice,
 *    this list of conditions and the following disclaimer in the documentation
 *    and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * \file main.cxx
 *
 * Main file for the io board application on the Tiva Launchpad board.
 *
 * @author Balazs Racz
 * @date 5 Jun 2015
 */

#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>

#include "os/os.h"
#include "can_frame.h"
#include "nmranet_config.h"

#include "os/TempFile.hxx"
#include "nmranet/SimpleStack.hxx"
#include "nmranet/SimpleNodeInfoMockUserFile.hxx"
#include "nmranet/EventHandlerTemplates.hxx"
#include "nmranet/ConfigRepresentation.hxx"
#include "utils/ConfigUpdateListener.hxx"

#include "freertos_drivers/ti/TivaGPIO.hxx"

extern const nmranet::NodeID NODE_ID;

OVERRIDE_CONST(gc_generate_newlines, 1);
OVERRIDE_CONST(main_thread_stack_size, 2500);
OVERRIDE_CONST(num_memory_spaces, 4);

nmranet::SimpleCanStack stack(NODE_ID);

nmranet::MockSNIPUserFile snip_user_file(
    "Default user name", "Default user description");
const char *const nmranet::SNIP_DYNAMIC_FILENAME =
    nmranet::MockSNIPUserFile::snip_user_file_path;

namespace nmranet
{
BEGIN_GROUP(ConsumerConfig, base);
EXTEND_GROUP(ConsumerConfig, base, event_on, EventConfigEntry);
EXTEND_GROUP(ConsumerConfig, event_on, event_off, EventConfigEntry);
END_GROUP(ConsumerConfig, event_off);

using AllConsumers = RepeatedGroup<ConsumerConfig, 3>;

BEGIN_GROUP(ProducerConfig, base);
EXTEND_GROUP(ProducerConfig, base, debounce, Uint8ConfigEntry);
EXTEND_GROUP(ProducerConfig, debounce, event_on, EventConfigEntry);
EXTEND_GROUP(ProducerConfig, event_on, event_off, EventConfigEntry);
END_GROUP(ProducerConfig, event_off);

using AllProducers = RepeatedGroup<ProducerConfig, 2>;

BEGIN_GROUP(ConfigDef, base);
EXTEND_GROUP(ConfigDef, base, snip_data, EmptyGroup<128>);
EXTEND_GROUP(ConfigDef, snip_data, consumers, AllConsumers);
EXTEND_GROUP(ConfigDef, consumers, producers, AllProducers);
END_GROUP(ConfigDef, consumers);

static_assert(ConfigDef::size() <= 256, "Need to adjust eeprom size");

typedef bool (*getter_fn_t)();
typedef void (*setter_fn_t)(bool);

class ConfiguredConsumer : public ConfigUpdateListener
{
public:
    class Impl : public BitEventInterface
    {
    public:
        Impl(EventId event_on, EventId event_off, getter_fn_t getter,
            setter_fn_t setter)
            : BitEventInterface(event_on, event_off)
            , getter_(getter)
            , setter_(setter)
        {
        }

        bool GetCurrentState() OVERRIDE
        {
            return getter_();
        }
        void SetState(bool new_value) OVERRIDE
        {
            setter_(new_value);
        }
        Node *node() OVERRIDE
        {
            return stack.node();
        }

    public:
        const getter_fn_t getter_;
        const setter_fn_t setter_;
    };

    template <class HW>
    ConfiguredConsumer(const ConsumerConfig &cfg, const HW &)
        : impl_(0, 0, &HW::get, &HW::set)
        , consumer_(&impl_)
        , cfg_(cfg)
    {
    }

    UpdateAction apply_configuration(
        int fd, bool initial_load, BarrierNotifiable *done)
    {
        AutoNotify n(done);
        EventId cfg_event_on = cfg_.event_on().read(fd);
        EventId cfg_event_off = cfg_.event_off().read(fd);
        if (cfg_event_off != impl_.event_off() ||
            cfg_event_on != impl_.event_on())
        {
            auto saved_setter = impl_.setter_;
            auto saved_getter = impl_.getter_;
            // Need to reinitialize the consumer. We do this with in-place
            // destruction and construction.
            consumer_.~BitEventConsumer();
            impl_.~Impl();
            new (&impl_)
                Impl(cfg_event_on, cfg_event_off, saved_getter, saved_setter);
            new (&consumer_) BitEventConsumer(&impl_);
            return REINIT_NEEDED; // Causes events identify.
        }
        return UPDATED;
    }

    ///@TODO(balazs.racz): implement
    void factory_reset(int fd) OVERRIDE
    {
    }

private:
    Impl impl_;
    BitEventConsumer consumer_;
    const ConsumerConfig cfg_;
};

} // namespace nmranet

GPIO_PIN(LED_RED, LedPin, F, 1);
GPIO_PIN(LED_GREEN, LedPin, F, 3);
GPIO_PIN(LED_BLUE, LedPin, F, 2);

GPIO_PIN(SW1, GpioInputPU, F, 4);

nmranet::ConfigDef cfg(0);

nmranet::ConfiguredConsumer consumer_red(
    cfg.consumers().entry<0>(), LED_RED_Pin());
nmranet::ConfiguredConsumer consumer_green(
    cfg.consumers().entry<1>(), LED_GREEN_Pin());
nmranet::ConfiguredConsumer consumer_blue(
    cfg.consumers().entry<2>(), LED_BLUE_Pin());

/** Entry point to application.
 * @param argc number of command line arguments
 * @param argv array of command line arguments
 * @return 0, should never return
 */
int appl_main(int argc, char *argv[])
{
#if defined(HAVE_PHYSICAL_CAN_PORT)
    stack.add_can_port_select("/dev/can0");
#endif

// Enable this to add sniffing through the usb or serial port.
#if defined(SNIFF_ON_USB)
    stack.add_gridconnect_port("/dev/serUSB0");
#endif
#if defined(SNIFF_ON_SERIAL)
    stack.add_gridconnect_port("/dev/ser0");
#endif

    stack.loop_executor();
    return 0;
}
<|endoftext|>