<commit_before>#include <iostream>
#include "Scheduler.hpp"

Scheduler::~Scheduler() {
  // delete eventual flows still scheduled but not completed
  handleMap.clear();
  pendingEvents.clear();
  delete terminate;
}

void Scheduler::schedule(Flow* event) {
  handleT handle = this->pendingEvents.push(event);
  if (handleMap.insert(std::make_pair(event, handle)).second != true)
  {
    BOOST_LOG_TRIVIAL(error) << "Scheduler::schedule() - could not insert new handle in "
            "handleMap";
    exit(ERR_HANDLEMAP_INSERT);
  }
}

Scheduler::Scheduler(TopologyOracle* oracle, po::variables_map vm)
{
  this->mode = (SimMode) vm["sim-mode"].as<uint>();
  if (this->mode == IPTV)
    this->roundDuration = 86400; // 1 day
  else if (this->mode == VoD)
    this->roundDuration = 604800; // 1 week
  else {
    BOOST_LOG_TRIVIAL(error) << "Scheduler::Scheduler() - unrecognized SimMode";
    abort();
  }
  this->oracle = oracle;
  this->currentRound = 0;
  this->roundDuration = roundDuration;
  simTime = 0;
  this->terminate = new Flow(nullptr, UNKNOWN, roundDuration);
  this->terminate->setFlowType(FlowType::TERMINATE);
  this->schedule(terminate);
  this->snapshotFreq = vm["snapshot-freq"].as<uint>();
  if (snapshotFreq > 0 && snapshotFreq <= roundDuration) {
    this->snapshot = new Flow(nullptr, UNKNOWN, snapshotFreq);
    snapshot->setFlowType(FlowType::SNAPSHOT);
    this->schedule(this->snapshot);
  } else {
    this->snapshot = nullptr;
  }
}

bool Scheduler::advanceClock() {
  if (pendingEvents.size() == 0) {
    BOOST_LOG_TRIVIAL(warning) << "Scheduler::advanceClock() - Empty event queue before "
            "reaching the termination event" << std::endl;
    return false;
  }
  Flow* nextEvent = const_cast<Flow*> (pendingEvents.top());
  // Check that the event is not scheduled in the past
  if (nextEvent->getSimTime() < this->getSimTime()) {
    BOOST_LOG_TRIVIAL(error) << "Scheduler::advanceClock() - Event scheduled in the past!";
    BOOST_LOG_TRIVIAL(error) << "Simulation time: " << this->getSimTime()
            << ", event time: " << nextEvent->getSimTime()
            << ", content: " << nextEvent->getContent()->getName();
    abort();
  }
  // Update the clock with the current event time (if > previous time)
  else if (nextEvent->getSimTime() > this->getSimTime()) {
    this->setSimTime(nextEvent->getSimTime());
    /* print current time on the screen at the current line (note: will mess up
     * printing with debug verbose
     */
    std::cout<<"Current simulation time: " << this->simTime << "/"
          << this->roundDuration << "\r" << std::flush;
  }
  handleMap.erase(pendingEvents.top());
  pendingEvents.pop();
  // Determine what kind of event is this
  switch(nextEvent->getFlowType()) {
    case FlowType::TERMINATE:
      BOOST_LOG_TRIVIAL(info) << std::endl
             << "Scheduler::advanceClock() - intercepted termination event";
      delete nextEvent;
      return false;

    case FlowType::SNAPSHOT:
      oracle->takeSnapshot(this->getSimTime(), this->getCurrentRound());
      delete nextEvent;
      if (this->getSimTime() + snapshotFreq <= roundDuration) {
        this->snapshot = new Flow(nullptr, UNKNOWN,
                this->getSimTime() + snapshotFreq);
        snapshot->setFlowType(FlowType::SNAPSHOT);
        this->schedule(this->snapshot);
      } else {
        this->snapshot = nullptr;
      }
      return true;

    case FlowType::REQUEST: {
      // Change the start time to now and the eta to INF_TIME until we know the
      // available bandwidth
      nextEvent->setStart(this->getSimTime());
      nextEvent->setEta(INF_TIME);
      nextEvent->setLastUpdate(this->getSimTime());
      // Ask the TopologyOracle to find a source for this content
      // TODO: reschedule request in case of congestion
      bool success = oracle->serveRequest(nextEvent, this);
      // Check that the flow wasn't "virtual" (i.e. content was cached at the dest)
      // also in that case we need to put the chunk in the watching buffer
      if (nextEvent->getSource() == nextEvent->getDestination()) {
        oracle->notifyCompletedFlow(nextEvent, this);
        delete nextEvent;
      }
      else if (!success) {
        //TODO: retry to fetch the content at a later time
        delete nextEvent;
      }
      return true;
    }
    case FlowType::TRANSFER:
    case FlowType::WATCH:
      // Notify the oracle, which will update the cache mapping and free resources
      // in the topology
      oracle->notifyCompletedFlow(nextEvent, this);
      delete nextEvent;
      return true;
  }

/*  if (nextEvent->getSource() == UNKNOWN) {
    // This is a request, as the source hasn't been assigned yet
    handleMap.erase(pendingEvents.top());
    pendingEvents.pop();
    // Check whether this is a special event
    if (nextEvent->getDestination() == UNKNOWN && nextEvent->getContent() == nullptr) {
      // termination event?
      if (nextEvent->getSizeRequested() == 0) {
      std::cout << std::endl
             << "Scheduler::advanceClock() - intercepted termination event"
              << std::endl;
      delete nextEvent;
      return false;
      } // snapshot event?
      else if (nextEvent->getFlowType() == FlowType::SNAPSHOT) {
        oracle->takeSnapshot(this->getSimTime(), this->getCurrentRound());
        delete nextEvent;
        if (this->getSimTime() + snapshotFreq <= roundDuration) {
          this->snapshot = new Flow(nullptr, UNKNOWN, 0,
                  this->getSimTime() + snapshotFreq);
          snapshot->setFlowType(FlowType::SNAPSHOT);
          this->schedule(this->snapshot);
        }
        else {
          this->snapshot = nullptr;
        }
        return true;
      }
    }

    // Change the start time to now and the eta to INF_TIME until we know the
    // available bandwidth
    nextEvent->setStart(this->getSimTime());
    nextEvent->setEta(INF_TIME);
    nextEvent->setLastUpdate(this->getSimTime());
    // Ask the TopologyOracle to find a source for this content
    // TODO: reschedule request in case of congestion
    bool success = oracle->serveRequest(nextEvent, this);
    // Check that the flow wasn't "virtual" (i.e. content was cached at the dest)
    if (!success || nextEvent->getSource() == nextEvent->getDestination()) {
      handleMap.erase(nextEvent);
      delete nextEvent;
    }
    return true;
  } else {
//    std::cout << this->getSimTime() << ": Completed transfer of content "
//            << flow->getContent()->getName()
//            << " from source " << flow->getSource().first
//            << " to destination " << flow->getDestination().first << std::endl;
    // Remove flow from top of the queue
    pendingEvents.pop();
    handleMap.erase(nextEvent);
    // Notify the oracle, which will update the cache mapping and free resources
    // in the topology
    oracle->notifyCompletedFlow(nextEvent, this);
    delete nextEvent;
    return true;
  }
 */
}

void Scheduler::updateSchedule(Flow* flow, SimTime oldEta) {
  if (handleMap.find(flow) != handleMap.end()) {
    if (flow->getEta() > oldEta)
      pendingEvents.decrease(handleMap[flow]);
    else if (flow->getEta() < oldEta)
      pendingEvents.increase(handleMap[flow]);
    else
      return;
  }
  else {
    BOOST_LOG_TRIVIAL(error) << "Scheduler::updateSchedule() - could not find handle for flow "
            << flow->getSource().first << "->" << flow->getDestination().first;
    exit(ERR_NO_EVENT_HANDLE);
  }
}

void Scheduler::startNewRound() {
  // update flows so that they can be moved to the new round
  std::vector<Flow*> flowVec;
  while (pendingEvents.empty() == false) {
    Flow* f = const_cast<Flow*> (pendingEvents.top());
    pendingEvents.pop();
    if (f->getFlowType() == FlowType::WATCH) {
      // there is no point in carrying over watch flows, as they will be discarded
      BOOST_LOG_TRIVIAL(trace) << "Deleting watch flow for chunk" << f->getChunkId()
              << " of content " << f->getContent()->getName() << " for user "
              << f->getDestination().first << "," << f->getDestination().second;
      delete f;
      continue;
    }
    f->updateSizeDownloaded(this->roundDuration);
    f->setLastUpdate(0);
    f->setStart(f->getStart() - this->roundDuration); // negative
    SimTime oldEta = f->getEta();
    if (oldEta < this->roundDuration) {
      BOOST_LOG_TRIVIAL(error) << "Scheduler::startNewRound() - unresolved event has eta "
              << oldEta << " < roundDuration";
      abort();
    }
    f->setEta(oldEta - this->roundDuration);
    if (this->mode == IPTV && f->getContent()->getReleaseDay() <= currentRound-6) {
      // expired contents in IPTV will be deleted so flows can't be completed,
      // this event should have been truncated last round
      f->setContent(nullptr);
      BOOST_LOG_TRIVIAL(info) << "Scheduler::startNewRound() - carried over flow "
              "with expired content will not be completed";
      if (f->getFlowType() == FlowType::TRANSFER) {
        // this is hacky, but needs to be done. Ideally we should not get here at all.
        oracle->getTopology()->updateCapacity(f, this, false);
      }
    } else
      flowVec.push_back(f);
  }
  handleMap.clear();
  BOOST_FOREACH (Flow* f, flowVec) {
    this->schedule(f);
  }
  flowVec.clear();
  this->simTime = 0;
  this->currentRound++;
  this->terminate = new Flow(nullptr, UNKNOWN, roundDuration);
  this->terminate->setFlowType(FlowType::TERMINATE);
  this->schedule(terminate);
  if (snapshotFreq > 0 && snapshotFreq <= roundDuration) {
    this->snapshot = new Flow(nullptr, UNKNOWN, snapshotFreq);
    snapshot->setFlowType(FlowType::SNAPSHOT);
    this->schedule(this->snapshot);
  } else {
    this->snapshot = nullptr;
  }
  return;
}<commit_msg>ETA for request flows that are being matched with a source and moved to transfers is now estimated at +1 second from current simTime. As chunks are pretty small compared to the bandwidth available, chances are this is correct, meaning we won't need to update the event queue.<commit_after>#include <iostream>
#include "Scheduler.hpp"

Scheduler::~Scheduler() {
  // delete eventual flows still scheduled but not completed
  handleMap.clear();
  pendingEvents.clear();
  delete terminate;
}

void Scheduler::schedule(Flow* event) {
  handleT handle = this->pendingEvents.push(event);
  if (handleMap.insert(std::make_pair(event, handle)).second != true)
  {
    BOOST_LOG_TRIVIAL(error) << "Scheduler::schedule() - could not insert new handle in "
            "handleMap";
    exit(ERR_HANDLEMAP_INSERT);
  }
}

Scheduler::Scheduler(TopologyOracle* oracle, po::variables_map vm)
{
  this->mode = (SimMode) vm["sim-mode"].as<uint>();
  if (this->mode == IPTV)
    this->roundDuration = 86400; // 1 day
  else if (this->mode == VoD)
    this->roundDuration = 604800; // 1 week
  else {
    BOOST_LOG_TRIVIAL(error) << "Scheduler::Scheduler() - unrecognized SimMode";
    abort();
  }
  this->oracle = oracle;
  this->currentRound = 0;
  this->roundDuration = roundDuration;
  simTime = 0;
  this->terminate = new Flow(nullptr, UNKNOWN, roundDuration);
  this->terminate->setFlowType(FlowType::TERMINATE);
  this->schedule(terminate);
  this->snapshotFreq = vm["snapshot-freq"].as<uint>();
  if (snapshotFreq > 0 && snapshotFreq <= roundDuration) {
    this->snapshot = new Flow(nullptr, UNKNOWN, snapshotFreq);
    snapshot->setFlowType(FlowType::SNAPSHOT);
    this->schedule(this->snapshot);
  } else {
    this->snapshot = nullptr;
  }
}

bool Scheduler::advanceClock() {
  if (pendingEvents.size() == 0) {
    BOOST_LOG_TRIVIAL(warning) << "Scheduler::advanceClock() - Empty event queue before "
            "reaching the termination event" << std::endl;
    return false;
  }
  Flow* nextEvent = const_cast<Flow*> (pendingEvents.top());
  // Check that the event is not scheduled in the past
  if (nextEvent->getSimTime() < this->getSimTime()) {
    BOOST_LOG_TRIVIAL(error) << "Scheduler::advanceClock() - Event scheduled in the past!";
    BOOST_LOG_TRIVIAL(error) << "Simulation time: " << this->getSimTime()
            << ", event time: " << nextEvent->getSimTime()
            << ", content: " << nextEvent->getContent()->getName();
    abort();
  }
  // Update the clock with the current event time (if > previous time)
  else if (nextEvent->getSimTime() > this->getSimTime()) {
    this->setSimTime(nextEvent->getSimTime());
    /* print current time on the screen at the current line (note: will mess up
     * printing with debug verbose
     */
    std::cout<<"Current simulation time: " << this->simTime << "/"
          << this->roundDuration << "\r" << std::flush;
  }
  handleMap.erase(pendingEvents.top());
  pendingEvents.pop();
  // Determine what kind of event is this
  switch(nextEvent->getFlowType()) {
    case FlowType::TERMINATE:
      BOOST_LOG_TRIVIAL(info) << std::endl
             << "Scheduler::advanceClock() - intercepted termination event";
      delete nextEvent;
      return false;

    case FlowType::SNAPSHOT:
      oracle->takeSnapshot(this->getSimTime(), this->getCurrentRound());
      delete nextEvent;
      if (this->getSimTime() + snapshotFreq <= roundDuration) {
        this->snapshot = new Flow(nullptr, UNKNOWN,
                this->getSimTime() + snapshotFreq);
        snapshot->setFlowType(FlowType::SNAPSHOT);
        this->schedule(this->snapshot);
      } else {
        this->snapshot = nullptr;
      }
      return true;

    case FlowType::REQUEST: {
      // Change the start time to now and the eta to +1s until we know the
      // available bandwidth
      nextEvent->setStart(this->getSimTime());
      nextEvent->setEta(this->getSimTime()+1);
      nextEvent->setLastUpdate(this->getSimTime());
      // Ask the TopologyOracle to find a source for this content
      // TODO: reschedule request in case of congestion
      bool success = oracle->serveRequest(nextEvent, this);
      // Check that the flow wasn't "virtual" (i.e. content was cached at the dest)
      // also in that case we need to put the chunk in the watching buffer
      if (nextEvent->getSource() == nextEvent->getDestination()) {
        oracle->notifyCompletedFlow(nextEvent, this);
        delete nextEvent;
      }
      else if (!success) {
        //TODO: retry to fetch the content at a later time
        delete nextEvent;
      }
      return true;
    }
    case FlowType::TRANSFER:
    case FlowType::WATCH:
      // Notify the oracle, which will update the cache mapping and free resources
      // in the topology
      oracle->notifyCompletedFlow(nextEvent, this);
      delete nextEvent;
      return true;
  }

/*  if (nextEvent->getSource() == UNKNOWN) {
    // This is a request, as the source hasn't been assigned yet
    handleMap.erase(pendingEvents.top());
    pendingEvents.pop();
    // Check whether this is a special event
    if (nextEvent->getDestination() == UNKNOWN && nextEvent->getContent() == nullptr) {
      // termination event?
      if (nextEvent->getSizeRequested() == 0) {
      std::cout << std::endl
             << "Scheduler::advanceClock() - intercepted termination event"
              << std::endl;
      delete nextEvent;
      return false;
      } // snapshot event?
      else if (nextEvent->getFlowType() == FlowType::SNAPSHOT) {
        oracle->takeSnapshot(this->getSimTime(), this->getCurrentRound());
        delete nextEvent;
        if (this->getSimTime() + snapshotFreq <= roundDuration) {
          this->snapshot = new Flow(nullptr, UNKNOWN, 0,
                  this->getSimTime() + snapshotFreq);
          snapshot->setFlowType(FlowType::SNAPSHOT);
          this->schedule(this->snapshot);
        }
        else {
          this->snapshot = nullptr;
        }
        return true;
      }
    }

    // Change the start time to now and the eta to INF_TIME until we know the
    // available bandwidth
    nextEvent->setStart(this->getSimTime());
    nextEvent->setEta(INF_TIME);
    nextEvent->setLastUpdate(this->getSimTime());
    // Ask the TopologyOracle to find a source for this content
    // TODO: reschedule request in case of congestion
    bool success = oracle->serveRequest(nextEvent, this);
    // Check that the flow wasn't "virtual" (i.e. content was cached at the dest)
    if (!success || nextEvent->getSource() == nextEvent->getDestination()) {
      handleMap.erase(nextEvent);
      delete nextEvent;
    }
    return true;
  } else {
//    std::cout << this->getSimTime() << ": Completed transfer of content "
//            << flow->getContent()->getName()
//            << " from source " << flow->getSource().first
//            << " to destination " << flow->getDestination().first << std::endl;
    // Remove flow from top of the queue
    pendingEvents.pop();
    handleMap.erase(nextEvent);
    // Notify the oracle, which will update the cache mapping and free resources
    // in the topology
    oracle->notifyCompletedFlow(nextEvent, this);
    delete nextEvent;
    return true;
  }
 */
}

void Scheduler::updateSchedule(Flow* flow, SimTime oldEta) {
  if (handleMap.find(flow) != handleMap.end()) {
    if (flow->getEta() > oldEta)
      pendingEvents.decrease(handleMap[flow]);
    else if (flow->getEta() < oldEta)
      pendingEvents.increase(handleMap[flow]);
    else
      return;
  }
  else {
    BOOST_LOG_TRIVIAL(error) << "Scheduler::updateSchedule() - could not find handle for flow "
            << flow->getSource().first << "->" << flow->getDestination().first;
    exit(ERR_NO_EVENT_HANDLE);
  }
}

void Scheduler::startNewRound() {
  // update flows so that they can be moved to the new round
  std::vector<Flow*> flowVec;
  while (pendingEvents.empty() == false) {
    Flow* f = const_cast<Flow*> (pendingEvents.top());
    pendingEvents.pop();
    if (f->getFlowType() == FlowType::WATCH) {
      // there is no point in carrying over watch flows, as they will be discarded
      BOOST_LOG_TRIVIAL(trace) << "Deleting watch flow for chunk" << f->getChunkId()
              << " of content " << f->getContent()->getName() << " for user "
              << f->getDestination().first << "," << f->getDestination().second;
      delete f;
      continue;
    }
    f->updateSizeDownloaded(this->roundDuration);
    f->setLastUpdate(0);
    f->setStart(f->getStart() - this->roundDuration); // negative
    SimTime oldEta = f->getEta();
    if (oldEta < this->roundDuration) {
      BOOST_LOG_TRIVIAL(error) << "Scheduler::startNewRound() - unresolved event has eta "
              << oldEta << " < roundDuration";
      abort();
    }
    f->setEta(oldEta - this->roundDuration);
    if (this->mode == IPTV && f->getContent()->getReleaseDay() <= currentRound-6) {
      // expired contents in IPTV will be deleted so flows can't be completed,
      // this event should have been truncated last round
      f->setContent(nullptr);
      BOOST_LOG_TRIVIAL(info) << "Scheduler::startNewRound() - carried over flow "
              "with expired content will not be completed";
      if (f->getFlowType() == FlowType::TRANSFER) {
        // this is hacky, but needs to be done. Ideally we should not get here at all.
        oracle->getTopology()->updateCapacity(f, this, false);
      }
    } else
      flowVec.push_back(f);
  }
  handleMap.clear();
  BOOST_FOREACH (Flow* f, flowVec) {
    this->schedule(f);
  }
  flowVec.clear();
  this->simTime = 0;
  this->currentRound++;
  this->terminate = new Flow(nullptr, UNKNOWN, roundDuration);
  this->terminate->setFlowType(FlowType::TERMINATE);
  this->schedule(terminate);
  if (snapshotFreq > 0 && snapshotFreq <= roundDuration) {
    this->snapshot = new Flow(nullptr, UNKNOWN, snapshotFreq);
    snapshot->setFlowType(FlowType::SNAPSHOT);
    this->schedule(this->snapshot);
  } else {
    this->snapshot = nullptr;
  }
  return;
}<|endoftext|>


<commit_before>/*********************************************************************************
 *
 * Inviwo - Interactive Visualization Workshop
 *
 * Copyright (c) 2013-2017 Inviwo Foundation
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * 1. Redistributions of source code must retain the above copyright notice, this
 * list of conditions and the following disclaimer.
 * 2. 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 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 <modules/qtwidgets/properties/texteditorwidgetqt.h>
#include <inviwo/core/common/inviwoapplication.h>
#include <inviwo/core/common/inviwomodule.h>
#include <inviwo/core/util/settings/systemsettings.h>
#include <inviwo/core/util/filesystem.h>
#include <inviwo/core/properties/property.h>

#include <modules/qtwidgets/inviwoqtutils.h>

#include <modules/qtwidgets/properties/syntaxhighlighter.h>
#include <modules/qtwidgets/qtwidgetsmoduledefine.h>
#include <modules/qtwidgets/properties/buttonpropertywidgetqt.h>
#include <modules/qtwidgets/properties/filepropertywidgetqt.h>
#include <modules/qtwidgets/properties/propertywidgetqt.h>
#include <modules/qtwidgets/properties/stringpropertywidgetqt.h>
#include <modules/qtwidgets/properties/propertyeditorwidgetqt.h>

#include <warn/push>
#include <warn/ignore/all>
#include <QTextDocument>
#include <QTextBlock>
#include <QFileInfo>
#include <QVBoxLayout>
#include <QToolButton>
#include <QToolBar>
#include <QTextEdit>
#include <QDesktopServices>
#include <QTextStream>
#include <QMessageBox>
#include <warn/pop>

namespace inviwo {

TextEditorDockWidget::TextEditorDockWidget(Property* property)
    : PropertyEditorWidgetQt(property, "Edit " + property->getDisplayName(), "TextEditorDockWidget")
    , fileProperty_{dynamic_cast<FileProperty*>(property)}
    , stringProperty_{dynamic_cast<StringProperty*>(property)} {

    QMainWindow* mainWindow = new QMainWindow();
    mainWindow->setContextMenuPolicy(Qt::NoContextMenu);
    QToolBar* toolBar = new QToolBar();
    mainWindow->addToolBar(toolBar);
    toolBar->setFloatable(false);
    toolBar->setMovable(false);
    setWidget(mainWindow);

    editor_ = new QTextEdit(nullptr);
    editor_->setReadOnly(false);
    editor_->setStyleSheet("font: 10pt \"Courier\";");
    editor_->setWordWrapMode(QTextOption::NoWrap);
    editor_->createStandardContextMenu();
    mainWindow->setCentralWidget(editor_);

    if (property->getSemantics() == PropertySemantics::ShaderEditor) {
        syntaxHighligther_ = SyntaxHighligther::createSyntaxHighligther<GLSL>(editor_->document());
    } else {
        syntaxHighligther_ = SyntaxHighligther::createSyntaxHighligther<None>(editor_->document());
    }

    {
        auto save = toolBar->addAction(QIcon(":/icons/save.png"), tr("&Save"));
        save->setShortcut(QKeySequence::Save);
        save->setShortcutContext(Qt::WidgetWithChildrenShortcut);
        mainWindow->addAction(save);
        connect(save, &QAction::triggered, this, [this]() {
            if (editor_->document()->isModified()) {
                if (fileProperty_) {
                    if (auto f = filesystem::ofstream(fileProperty_->get())) {
                        f << utilqt::fromQString(editor_->toPlainText());
                    }
                } else if (stringProperty_) {
                    stringProperty_->set(utilqt::fromQString(editor_->toPlainText()));
                }
            }
        });
    }

    {
        auto undo = toolBar->addAction(QIcon(":/icons/undo.png"), tr("Undo"));
        undo->setShortcut(QKeySequence::Undo);
        undo->setShortcutContext(Qt::WidgetWithChildrenShortcut);
        mainWindow->addAction(undo);
        connect(undo, &QAction::triggered, editor_, &QTextEdit::undo);
    }

    {
        auto redo = toolBar->addAction(QIcon(":/icons/redo.png"), tr("Redo"));
        redo->setShortcut(QKeySequence::Redo);
        redo->setShortcutContext(Qt::WidgetWithChildrenShortcut);
        mainWindow->addAction(redo);
        connect(redo, &QAction::triggered, editor_, &QTextEdit::redo);
    }

    {
        auto reload = toolBar->addAction(QIcon(":/icons/button_cancel-bw.png"), tr("Reload"));
        reload->setToolTip("Discard changes");
        reload->setShortcutContext(Qt::WidgetWithChildrenShortcut);
        mainWindow->addAction(reload);
        connect(reload, &QAction::triggered, [this]() { updateFromProperty(); });
    }

    resize(QSize(500, 500));  // default size
    setVisible(false);
    updateFromProperty();
    loadState();
}

SyntaxHighligther* TextEditorDockWidget::getSyntaxHighligther() { return syntaxHighligther_; }

void TextEditorDockWidget::updateFromProperty() {
    if (fileProperty_) {
        if (auto f = filesystem::ifstream(fileProperty_->get())) {
            std::stringstream ss;
            ss << f.rdbuf();
            editor_->setPlainText(utilqt::toQString(ss.str()));
        } else {
            editor_->setPlainText("");
        }
    } else if (stringProperty_) {
        editor_->setPlainText(utilqt::toQString(stringProperty_->get()));
    }
}

void TextEditorDockWidget::closeEvent(QCloseEvent* e) {
    if (stringProperty_->get() != utilqt::fromQString(editor_->toPlainText())) {
        auto ret = QMessageBox::warning(
            this, utilqt::toQString("Edit " + stringProperty_->getDisplayName()),
            tr("The document has been modified.\n"
               "Do you want to save your changes?"),
            QMessageBox::Save | QMessageBox::Discard);

        if (ret == QMessageBox::Save) {
            if (fileProperty_) {
                if (auto f = filesystem::ofstream(fileProperty_->get())) {
                    f << utilqt::fromQString(editor_->toPlainText());
                }
            } else if (stringProperty_) {
                stringProperty_->set(utilqt::fromQString(editor_->toPlainText()));
            }
        }
    }
    PropertyEditorWidgetQt::closeEvent(e);
}

void TextEditorDockWidget::onSetDisplayName(Property*, const std::string& displayName) {
    setWindowTitle(QString::fromStdString(displayName));
}

void TextEditorDockWidget::setReadOnly(bool readonly) { editor_->setReadOnly(readonly); }

}  // namespace inviwo
<commit_msg>QtWidgets: TextEditorWidgetQt fixes, inviwo/inviwo-dev#1785<commit_after>/*********************************************************************************
 *
 * Inviwo - Interactive Visualization Workshop
 *
 * Copyright (c) 2013-2017 Inviwo Foundation
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * 1. Redistributions of source code must retain the above copyright notice, this
 * list of conditions and the following disclaimer.
 * 2. 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 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 <modules/qtwidgets/properties/texteditorwidgetqt.h>
#include <inviwo/core/common/inviwoapplication.h>
#include <inviwo/core/common/inviwomodule.h>
#include <inviwo/core/util/settings/systemsettings.h>
#include <inviwo/core/util/filesystem.h>
#include <inviwo/core/properties/property.h>

#include <modules/qtwidgets/inviwoqtutils.h>

#include <modules/qtwidgets/properties/syntaxhighlighter.h>
#include <modules/qtwidgets/qtwidgetsmoduledefine.h>
#include <modules/qtwidgets/properties/buttonpropertywidgetqt.h>
#include <modules/qtwidgets/properties/filepropertywidgetqt.h>
#include <modules/qtwidgets/properties/propertywidgetqt.h>
#include <modules/qtwidgets/properties/stringpropertywidgetqt.h>
#include <modules/qtwidgets/properties/propertyeditorwidgetqt.h>

#include <warn/push>
#include <warn/ignore/all>
#include <QTextDocument>
#include <QTextBlock>
#include <QFileInfo>
#include <QVBoxLayout>
#include <QToolButton>
#include <QToolBar>
#include <QTextEdit>
#include <QDesktopServices>
#include <QTextStream>
#include <QMessageBox>
#include <QFont>
#include <warn/pop>

namespace inviwo {

TextEditorDockWidget::TextEditorDockWidget(Property* property)
    : PropertyEditorWidgetQt(property, "Edit " + property->getDisplayName(), "TextEditorDockWidget")
    , fileProperty_{dynamic_cast<FileProperty*>(property)}
    , stringProperty_{dynamic_cast<StringProperty*>(property)} {

    QMainWindow* mainWindow = new QMainWindow();
    mainWindow->setContextMenuPolicy(Qt::NoContextMenu);
    QToolBar* toolBar = new QToolBar();
    mainWindow->addToolBar(toolBar);
    toolBar->setFloatable(false);
    toolBar->setMovable(false);
    setWidget(mainWindow);

    editor_ = new QTextEdit(nullptr);
    editor_->setReadOnly(false);
    editor_->setWordWrapMode(QTextOption::NoWrap);
    editor_->createStandardContextMenu();
    mainWindow->setCentralWidget(editor_);

    QFont fixedFont("Monospace");
    fixedFont.setPointSize(10);
    fixedFont.setStyleHint(QFont::TypeWriter);
    editor_->setFont(fixedFont);

    QString bgString;
    if (property->getSemantics() == PropertySemantics::ShaderEditor) {
        syntaxHighligther_ = SyntaxHighligther::createSyntaxHighligther<GLSL>(editor_->document());
    } else {
        syntaxHighligther_ = SyntaxHighligther::createSyntaxHighligther<None>(editor_->document());
    }

    // set background of Text editor matching syntax highlighting
    QColor bgColor = syntaxHighligther_->getBackgroundColor();
    QString styleSheet(QString("QTextEdit { font-family: 'monospace'; background-color: %1; }")
                           .arg(bgColor.name()));
    editor_->setStyleSheet(styleSheet);

    {
        auto save = toolBar->addAction(QIcon(":/icons/save.png"), tr("&Save"));
        save->setShortcut(QKeySequence::Save);
        save->setShortcutContext(Qt::WidgetWithChildrenShortcut);
        mainWindow->addAction(save);
        connect(save, &QAction::triggered, this, [this]() {
            if (editor_->document()->isModified()) {
                if (fileProperty_) {
                    if (auto f = filesystem::ofstream(fileProperty_->get())) {
                        f << utilqt::fromQString(editor_->toPlainText());
                    }
                } else if (stringProperty_) {
                    stringProperty_->set(utilqt::fromQString(editor_->toPlainText()));
                }
            }
        });
    }

    {
        auto undo = toolBar->addAction(QIcon(":/icons/undo.png"), tr("Undo"));
        undo->setShortcut(QKeySequence::Undo);
        undo->setShortcutContext(Qt::WidgetWithChildrenShortcut);
        mainWindow->addAction(undo);
        connect(undo, &QAction::triggered, editor_, &QTextEdit::undo);
    }

    {
        auto redo = toolBar->addAction(QIcon(":/icons/redo.png"), tr("Redo"));
        redo->setShortcut(QKeySequence::Redo);
        redo->setShortcutContext(Qt::WidgetWithChildrenShortcut);
        mainWindow->addAction(redo);
        connect(redo, &QAction::triggered, editor_, &QTextEdit::redo);
    }

    {
        auto reload = toolBar->addAction(QIcon(":/icons/button_cancel-bw.png"), tr("Reload"));
        reload->setToolTip("Discard changes");
        reload->setShortcutContext(Qt::WidgetWithChildrenShortcut);
        mainWindow->addAction(reload);
        connect(reload, &QAction::triggered, [this]() { updateFromProperty(); });
    }

    resize(QSize(500, 500));  // default size
    setVisible(false);
    updateFromProperty();
    loadState();
}

SyntaxHighligther* TextEditorDockWidget::getSyntaxHighligther() { return syntaxHighligther_; }

void TextEditorDockWidget::updateFromProperty() {
    if (fileProperty_) {
        if (auto f = filesystem::ifstream(fileProperty_->get())) {
            std::stringstream ss;
            ss << f.rdbuf();
            editor_->setPlainText(utilqt::toQString(ss.str()));
        } else {
            editor_->setPlainText("");
        }
    } else if (stringProperty_) {
        editor_->setPlainText(utilqt::toQString(stringProperty_->get()));
    }
}

void TextEditorDockWidget::closeEvent(QCloseEvent* e) {
    if (stringProperty_->get() != utilqt::fromQString(editor_->toPlainText())) {
        auto ret = QMessageBox::warning(
            this, utilqt::toQString("Edit " + stringProperty_->getDisplayName()),
            tr("The document has been modified.\n"
               "Do you want to save your changes?"),
            QMessageBox::Save | QMessageBox::Discard);

        if (ret == QMessageBox::Save) {
            if (fileProperty_) {
                if (auto f = filesystem::ofstream(fileProperty_->get())) {
                    f << utilqt::fromQString(editor_->toPlainText());
                }
            } else if (stringProperty_) {
                stringProperty_->set(utilqt::fromQString(editor_->toPlainText()));
            }
        }
    }
    PropertyEditorWidgetQt::closeEvent(e);
}

void TextEditorDockWidget::onSetDisplayName(Property*, const std::string& displayName) {
    setWindowTitle(QString::fromStdString(displayName));
}

void TextEditorDockWidget::setReadOnly(bool readonly) { editor_->setReadOnly(readonly); }

}  // namespace inviwo
<|endoftext|>


<commit_before>#include <iostream>
#include <string>

#include <boost/program_options.hpp>
#include <boost/property_tree/ptree.hpp>
#include <boost/property_tree/json_parser.hpp>
#include <boost/algorithm/string/split.hpp>
#include <boost/algorithm/string/classification.hpp>
#include <boost/preprocessor/seq/for_each.hpp>

#if defined(SOLVER_BACKEND_VEXCL)
#  include <amgcl/backend/vexcl.hpp>
   typedef amgcl::backend::vexcl<double> Backend;
#elif defined(SOLVER_BACKEND_VIENNACL)
#  include <amgcl/backend/viennacl.hpp>
   typedef amgcl::backend::viennacl< viennacl::compressed_matrix<double> > Backend;
#elif defined(SOLVER_BACKEND_CUDA)
#  include <amgcl/backend/cuda.hpp>
#  include <amgcl/relaxation/cusparse_ilu0.hpp>
   typedef amgcl::backend::cuda<double> Backend;
#else
#  ifndef SOLVER_BACKEND_BUILTIN
#    define SOLVER_BACKEND_BUILTIN
#  endif
#  include <amgcl/backend/builtin.hpp>
#  include <amgcl/value_type/static_matrix.hpp>
#  include <amgcl/adapter/block_matrix.hpp>
#  include <amgcl/make_block_solver.hpp>
   typedef amgcl::backend::builtin<double> Backend;
#endif

#include <amgcl/make_solver.hpp>
#include <amgcl/amg.hpp>
#include <amgcl/solver/runtime.hpp>
#include <amgcl/coarsening/runtime.hpp>
#include <amgcl/relaxation/runtime.hpp>
#include <amgcl/preconditioner/schur_pressure_correction.hpp>
#include <amgcl/preconditioner/runtime.hpp>
#include <amgcl/adapter/crs_tuple.hpp>

#include <amgcl/io/mm.hpp>
#include <amgcl/io/binary.hpp>
#include <amgcl/profiler.hpp>

#ifndef AMGCL_BLOCK_SIZES
#  define AMGCL_BLOCK_SIZES (3)(4)
#endif

namespace amgcl { profiler<> prof; }
using amgcl::prof;
using amgcl::precondition;

typedef amgcl::scoped_tic< amgcl::profiler<> > tic;

template <class USolver, class PSolver, class Matrix>
typename std::enable_if<
    (
        amgcl::math::static_rows<
            typename amgcl::preconditioner::detail::common_backend<
                typename USolver::backend_type,
                typename PSolver::backend_type
            >::type::value_type
        >::value > 1
    ),
    void
    >::type
solve_schur(const Matrix&, const std::vector<double>&, boost::property_tree::ptree&)
{}

//---------------------------------------------------------------------------
template <class USolver, class PSolver, class Matrix>
typename std::enable_if<
    (
        amgcl::math::static_rows<
            typename amgcl::preconditioner::detail::common_backend<
                typename USolver::backend_type,
                typename PSolver::backend_type
            >::type::value_type
        >::value == 1
    ),
    void>::type
solve_schur(const Matrix &K, const std::vector<double> &rhs, boost::property_tree::ptree &prm)
{
    Backend::params bprm;

#if defined(SOLVER_BACKEND_VEXCL)
    vex::Context ctx(vex::Filter::Env);
    std::cout << ctx << std::endl;
    bprm.q = ctx;
#elif defined(SOLVER_BACKEND_VIENNACL)
    std::cout
        << viennacl::ocl::current_device().name()
        << " (" << viennacl::ocl::current_device().vendor() << ")\n\n";
#elif defined(SOLVER_BACKEND_CUDA)
    cusparseCreate(&bprm.cusparse_handle);
    {
        int dev;
        cudaGetDevice(&dev);

        cudaDeviceProp prop;
        cudaGetDeviceProperties(&prop, dev);
        std::cout << prop.name << std::endl << std::endl;
    }
#endif

    tic t1(prof, "schur_complement");

    prof.tic("setup");
    amgcl::make_solver<
        amgcl::preconditioner::schur_pressure_correction<USolver, PSolver>,
        amgcl::runtime::solver::wrapper<Backend>
        > solve(K, prm, bprm);
    prof.toc("setup");

    std::cout << solve.precond() << std::endl;

    auto f = Backend::copy_vector(rhs, bprm);
    auto x = Backend::create_vector(rhs.size(), bprm);
    amgcl::backend::clear(*x);

    size_t iters;
    double error;

    prof.tic("solve");
    std::tie(iters, error) = solve(*f, *x);
    prof.toc("solve");

    std::cout << "Iterations: " << iters << std::endl
              << "Error:      " << error << std::endl;
}

#define AMGCL_BLOCK_PSOLVER(z, data, B)                                        \
  case B: {                                                                    \
    typedef amgcl::backend::builtin<amgcl::static_matrix<double, B, B> >       \
        BBackend;                                                              \
    typedef amgcl::make_block_solver<                                          \
        amgcl::runtime::preconditioner<BBackend>,                              \
        amgcl::runtime::solver::wrapper<BBackend> >                            \
        PSolver;                                                               \
    solve_schur<USolver, PSolver>(K, rhs, prm);                                \
  } break;

//---------------------------------------------------------------------------
template <class USolver, class Matrix>
void solve_schur(int pb, const Matrix &K, const std::vector<double> &rhs, boost::property_tree::ptree &prm)
{
    switch (pb) {
        case 1:
            {
                typedef
                    amgcl::make_solver<
                        amgcl::runtime::preconditioner<Backend>,
                        amgcl::runtime::solver::wrapper<Backend>
                        >
                    PSolver;
                solve_schur<USolver, PSolver>(K, rhs, prm);
            }
            break;
#if defined(SOLVER_BACKEND_BUILTIN)
        BOOST_PP_SEQ_FOR_EACH(AMGCL_BLOCK_PSOLVER, ~, AMGCL_BLOCK_SIZES)
#endif
        default:
            precondition(false, "Unsupported block size for pressure");
    }
}

#define AMGCL_BLOCK_USOLVER(z, data, B)                                        \
  case B: {                                                                    \
    typedef amgcl::backend::builtin<amgcl::static_matrix<double, B, B> >       \
        BBackend;                                                              \
    typedef amgcl::make_block_solver<                                          \
        amgcl::runtime::preconditioner<BBackend>,                              \
        amgcl::runtime::solver::wrapper<BBackend> >                            \
        USolver;                                                               \
    solve_schur<USolver>(pb, K, rhs, prm);                                     \
  } break;

//---------------------------------------------------------------------------
template <class Matrix>
void solve_schur(int ub, int pb, const Matrix &K, const std::vector<double> &rhs, boost::property_tree::ptree &prm)
{
    precondition(ub == 1 || pb == 1,
            "At least one of the flow/pressure subproblems has to be scalar");

    switch (ub) {
        case 1:
            {
                typedef
                    amgcl::make_solver<
                        amgcl::runtime::preconditioner<Backend>,
                        amgcl::runtime::solver::wrapper<Backend>
                        >
                    USolver;
                solve_schur<USolver>(pb, K, rhs, prm);
            }
            break;
#if defined(SOLVER_BACKEND_BUILTIN)
        BOOST_PP_SEQ_FOR_EACH(AMGCL_BLOCK_USOLVER, ~, AMGCL_BLOCK_SIZES)
#endif
        default:
            precondition(false, "Unsupported block size for flow");
    }
}

//---------------------------------------------------------------------------
int main(int argc, char *argv[]) {
    using std::string;
    using std::vector;

    namespace po = boost::program_options;
    namespace io = amgcl::io;

    po::options_description desc("Options");

    desc.add_options()
        ("help,h", "show help")
        (
         "binary,B",
         po::bool_switch()->default_value(false),
         "When specified, treat input files as binary instead of as MatrixMarket. "
         "It is assumed the files were converted to binary format with mm2bin utility. "
        )
        (
         "matrix,A",
         po::value<string>()->required(),
         "The system matrix in MatrixMarket format"
        )
        (
         "rhs,f",
         po::value<string>(),
         "The right-hand side in MatrixMarket format"
        )
        (
         "pmask,m",
         po::value<string>(),
         "The pressure mask in MatrixMarket format. Or, if the parameter has "
         "the form '%n:m', then each (n+i*m)-th variable is treated as pressure."
        )
        (
         "ub",
         po::value<int>()->default_value(1),
         "Block-size of the 'flow'/'non-pressure' part of the matrix"
        )
        (
         "pb",
         po::value<int>()->default_value(1),
         "Block-size of the 'pressure' part of the matrix"
        )
        (
         "params,P",
         po::value<string>(),
         "parameter file in json format"
        )
        (
         "prm,p",
         po::value< vector<string> >()->multitoken(),
         "Parameters specified as name=value pairs. "
         "May be provided multiple times. Examples:\n"
         "  -p solver.tol=1e-3\n"
         "  -p precond.coarse_enough=300"
        )
        ;

    po::variables_map vm;
    po::store(po::parse_command_line(argc, argv, desc), vm);

    if (vm.count("help")) {
        std::cout << desc << std::endl;
        return 0;
    }

    po::notify(vm);

    boost::property_tree::ptree prm;
    if (vm.count("params")) read_json(vm["params"].as<string>(), prm);

    if (vm.count("prm")) {
        for(const string &v : vm["prm"].as<vector<string> >()) {
            amgcl::put(prm, v);
        }
    }

    size_t rows;
    vector<ptrdiff_t> ptr, col;
    vector<double> val, rhs;
    std::vector<char> pm;

    {
        tic t(prof, "reading");

        string Afile  = vm["matrix"].as<string>();
        bool   binary = vm["binary"].as<bool>();

        if (binary) {
            io::read_crs(Afile, rows, ptr, col, val);
        } else {
            size_t cols;
            std::tie(rows, cols) = io::mm_reader(Afile)(ptr, col, val);
            precondition(rows == cols, "Non-square system matrix");
        }

        if (vm.count("rhs")) {
            string bfile = vm["rhs"].as<string>();

            size_t n, m;

            if (binary) {
                io::read_dense(bfile, n, m, rhs);
            } else {
                std::tie(n, m) = io::mm_reader(bfile)(rhs);
            }

            precondition(n == rows && m == 1, "The RHS vector has wrong size");
        } else {
            rhs.resize(rows, 1.0);
        }

        if(vm.count("pmask")) {
            std::string pmask = vm["pmask"].as<string>();
            prm.put("precond.pmask_size", rows);

            switch (pmask[0]) {
                case '%':
                case '<':
                case '>':
                    prm.put("precond.pmask_pattern", pmask);
                    break;
                default:
                    {
                        size_t n, m;

                        if (binary) {
                            io::read_dense(pmask, n, m, pm);
                        } else {
                            std::tie(n, m) = amgcl::io::mm_reader(pmask)(pm);
                        }

                        precondition(n == rows && m == 1, "Mask file has wrong size");

                        prm.put("precond.pmask", static_cast<void*>(&pm[0]));
                    }
            }
        }
    }

    solve_schur(vm["ub"].as<int>(), vm["pb"].as<int>(),
            std::tie(rows, ptr, col, val), rhs, prm);

    std::cout << prof << std::endl;
}
<commit_msg>Remove unused headers<commit_after>#include <iostream>
#include <string>

#include <boost/program_options.hpp>
#include <boost/property_tree/ptree.hpp>
#include <boost/property_tree/json_parser.hpp>
#include <boost/preprocessor/seq/for_each.hpp>

#if defined(SOLVER_BACKEND_VEXCL)
#  include <amgcl/backend/vexcl.hpp>
   typedef amgcl::backend::vexcl<double> Backend;
#elif defined(SOLVER_BACKEND_VIENNACL)
#  include <amgcl/backend/viennacl.hpp>
   typedef amgcl::backend::viennacl< viennacl::compressed_matrix<double> > Backend;
#elif defined(SOLVER_BACKEND_CUDA)
#  include <amgcl/backend/cuda.hpp>
#  include <amgcl/relaxation/cusparse_ilu0.hpp>
   typedef amgcl::backend::cuda<double> Backend;
#else
#  ifndef SOLVER_BACKEND_BUILTIN
#    define SOLVER_BACKEND_BUILTIN
#  endif
#  include <amgcl/backend/builtin.hpp>
#  include <amgcl/value_type/static_matrix.hpp>
#  include <amgcl/adapter/block_matrix.hpp>
#  include <amgcl/make_block_solver.hpp>
   typedef amgcl::backend::builtin<double> Backend;
#endif

#include <amgcl/make_solver.hpp>
#include <amgcl/amg.hpp>
#include <amgcl/solver/runtime.hpp>
#include <amgcl/coarsening/runtime.hpp>
#include <amgcl/relaxation/runtime.hpp>
#include <amgcl/preconditioner/schur_pressure_correction.hpp>
#include <amgcl/preconditioner/runtime.hpp>
#include <amgcl/adapter/crs_tuple.hpp>

#include <amgcl/io/mm.hpp>
#include <amgcl/io/binary.hpp>
#include <amgcl/profiler.hpp>

#ifndef AMGCL_BLOCK_SIZES
#  define AMGCL_BLOCK_SIZES (3)(4)
#endif

namespace amgcl { profiler<> prof; }
using amgcl::prof;
using amgcl::precondition;

typedef amgcl::scoped_tic< amgcl::profiler<> > tic;

template <class USolver, class PSolver, class Matrix>
typename std::enable_if<
    (
        amgcl::math::static_rows<
            typename amgcl::preconditioner::detail::common_backend<
                typename USolver::backend_type,
                typename PSolver::backend_type
            >::type::value_type
        >::value > 1
    ),
    void
    >::type
solve_schur(const Matrix&, const std::vector<double>&, boost::property_tree::ptree&)
{}

//---------------------------------------------------------------------------
template <class USolver, class PSolver, class Matrix>
typename std::enable_if<
    (
        amgcl::math::static_rows<
            typename amgcl::preconditioner::detail::common_backend<
                typename USolver::backend_type,
                typename PSolver::backend_type
            >::type::value_type
        >::value == 1
    ),
    void>::type
solve_schur(const Matrix &K, const std::vector<double> &rhs, boost::property_tree::ptree &prm)
{
    Backend::params bprm;

#if defined(SOLVER_BACKEND_VEXCL)
    vex::Context ctx(vex::Filter::Env);
    std::cout << ctx << std::endl;
    bprm.q = ctx;
#elif defined(SOLVER_BACKEND_VIENNACL)
    std::cout
        << viennacl::ocl::current_device().name()
        << " (" << viennacl::ocl::current_device().vendor() << ")\n\n";
#elif defined(SOLVER_BACKEND_CUDA)
    cusparseCreate(&bprm.cusparse_handle);
    {
        int dev;
        cudaGetDevice(&dev);

        cudaDeviceProp prop;
        cudaGetDeviceProperties(&prop, dev);
        std::cout << prop.name << std::endl << std::endl;
    }
#endif

    tic t1(prof, "schur_complement");

    prof.tic("setup");
    amgcl::make_solver<
        amgcl::preconditioner::schur_pressure_correction<USolver, PSolver>,
        amgcl::runtime::solver::wrapper<Backend>
        > solve(K, prm, bprm);
    prof.toc("setup");

    std::cout << solve.precond() << std::endl;

    auto f = Backend::copy_vector(rhs, bprm);
    auto x = Backend::create_vector(rhs.size(), bprm);
    amgcl::backend::clear(*x);

    size_t iters;
    double error;

    prof.tic("solve");
    std::tie(iters, error) = solve(*f, *x);
    prof.toc("solve");

    std::cout << "Iterations: " << iters << std::endl
              << "Error:      " << error << std::endl;
}

#define AMGCL_BLOCK_PSOLVER(z, data, B)                                        \
  case B: {                                                                    \
    typedef amgcl::backend::builtin<amgcl::static_matrix<double, B, B> >       \
        BBackend;                                                              \
    typedef amgcl::make_block_solver<                                          \
        amgcl::runtime::preconditioner<BBackend>,                              \
        amgcl::runtime::solver::wrapper<BBackend> >                            \
        PSolver;                                                               \
    solve_schur<USolver, PSolver>(K, rhs, prm);                                \
  } break;

//---------------------------------------------------------------------------
template <class USolver, class Matrix>
void solve_schur(int pb, const Matrix &K, const std::vector<double> &rhs, boost::property_tree::ptree &prm)
{
    switch (pb) {
        case 1:
            {
                typedef
                    amgcl::make_solver<
                        amgcl::runtime::preconditioner<Backend>,
                        amgcl::runtime::solver::wrapper<Backend>
                        >
                    PSolver;
                solve_schur<USolver, PSolver>(K, rhs, prm);
            }
            break;
#if defined(SOLVER_BACKEND_BUILTIN)
        BOOST_PP_SEQ_FOR_EACH(AMGCL_BLOCK_PSOLVER, ~, AMGCL_BLOCK_SIZES)
#endif
        default:
            precondition(false, "Unsupported block size for pressure");
    }
}

#define AMGCL_BLOCK_USOLVER(z, data, B)                                        \
  case B: {                                                                    \
    typedef amgcl::backend::builtin<amgcl::static_matrix<double, B, B> >       \
        BBackend;                                                              \
    typedef amgcl::make_block_solver<                                          \
        amgcl::runtime::preconditioner<BBackend>,                              \
        amgcl::runtime::solver::wrapper<BBackend> >                            \
        USolver;                                                               \
    solve_schur<USolver>(pb, K, rhs, prm);                                     \
  } break;

//---------------------------------------------------------------------------
template <class Matrix>
void solve_schur(int ub, int pb, const Matrix &K, const std::vector<double> &rhs, boost::property_tree::ptree &prm)
{
    precondition(ub == 1 || pb == 1,
            "At least one of the flow/pressure subproblems has to be scalar");

    switch (ub) {
        case 1:
            {
                typedef
                    amgcl::make_solver<
                        amgcl::runtime::preconditioner<Backend>,
                        amgcl::runtime::solver::wrapper<Backend>
                        >
                    USolver;
                solve_schur<USolver>(pb, K, rhs, prm);
            }
            break;
#if defined(SOLVER_BACKEND_BUILTIN)
        BOOST_PP_SEQ_FOR_EACH(AMGCL_BLOCK_USOLVER, ~, AMGCL_BLOCK_SIZES)
#endif
        default:
            precondition(false, "Unsupported block size for flow");
    }
}

//---------------------------------------------------------------------------
int main(int argc, char *argv[]) {
    using std::string;
    using std::vector;

    namespace po = boost::program_options;
    namespace io = amgcl::io;

    po::options_description desc("Options");

    desc.add_options()
        ("help,h", "show help")
        (
         "binary,B",
         po::bool_switch()->default_value(false),
         "When specified, treat input files as binary instead of as MatrixMarket. "
         "It is assumed the files were converted to binary format with mm2bin utility. "
        )
        (
         "matrix,A",
         po::value<string>()->required(),
         "The system matrix in MatrixMarket format"
        )
        (
         "rhs,f",
         po::value<string>(),
         "The right-hand side in MatrixMarket format"
        )
        (
         "pmask,m",
         po::value<string>(),
         "The pressure mask in MatrixMarket format. Or, if the parameter has "
         "the form '%n:m', then each (n+i*m)-th variable is treated as pressure."
        )
        (
         "ub",
         po::value<int>()->default_value(1),
         "Block-size of the 'flow'/'non-pressure' part of the matrix"
        )
        (
         "pb",
         po::value<int>()->default_value(1),
         "Block-size of the 'pressure' part of the matrix"
        )
        (
         "params,P",
         po::value<string>(),
         "parameter file in json format"
        )
        (
         "prm,p",
         po::value< vector<string> >()->multitoken(),
         "Parameters specified as name=value pairs. "
         "May be provided multiple times. Examples:\n"
         "  -p solver.tol=1e-3\n"
         "  -p precond.coarse_enough=300"
        )
        ;

    po::variables_map vm;
    po::store(po::parse_command_line(argc, argv, desc), vm);

    if (vm.count("help")) {
        std::cout << desc << std::endl;
        return 0;
    }

    po::notify(vm);

    boost::property_tree::ptree prm;
    if (vm.count("params")) read_json(vm["params"].as<string>(), prm);

    if (vm.count("prm")) {
        for(const string &v : vm["prm"].as<vector<string> >()) {
            amgcl::put(prm, v);
        }
    }

    size_t rows;
    vector<ptrdiff_t> ptr, col;
    vector<double> val, rhs;
    std::vector<char> pm;

    {
        tic t(prof, "reading");

        string Afile  = vm["matrix"].as<string>();
        bool   binary = vm["binary"].as<bool>();

        if (binary) {
            io::read_crs(Afile, rows, ptr, col, val);
        } else {
            size_t cols;
            std::tie(rows, cols) = io::mm_reader(Afile)(ptr, col, val);
            precondition(rows == cols, "Non-square system matrix");
        }

        if (vm.count("rhs")) {
            string bfile = vm["rhs"].as<string>();

            size_t n, m;

            if (binary) {
                io::read_dense(bfile, n, m, rhs);
            } else {
                std::tie(n, m) = io::mm_reader(bfile)(rhs);
            }

            precondition(n == rows && m == 1, "The RHS vector has wrong size");
        } else {
            rhs.resize(rows, 1.0);
        }

        if(vm.count("pmask")) {
            std::string pmask = vm["pmask"].as<string>();
            prm.put("precond.pmask_size", rows);

            switch (pmask[0]) {
                case '%':
                case '<':
                case '>':
                    prm.put("precond.pmask_pattern", pmask);
                    break;
                default:
                    {
                        size_t n, m;

                        if (binary) {
                            io::read_dense(pmask, n, m, pm);
                        } else {
                            std::tie(n, m) = amgcl::io::mm_reader(pmask)(pm);
                        }

                        precondition(n == rows && m == 1, "Mask file has wrong size");

                        prm.put("precond.pmask", static_cast<void*>(&pm[0]));
                    }
            }
        }
    }

    solve_schur(vm["ub"].as<int>(), vm["pb"].as<int>(),
            std::tie(rows, ptr, col, val), rhs, prm);

    std::cout << prof << std::endl;
}
<|endoftext|>


<commit_before>/*
 *  Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */

#include "webrtc/engine_configurations.h"
#include "webrtc/modules/video_coding/main/source/encoded_frame.h"
#include "webrtc/modules/video_coding/main/source/generic_encoder.h"
#include "webrtc/modules/video_coding/main/source/media_optimization.h"
#include "webrtc/system_wrappers/interface/critical_section_wrapper.h"
#include "webrtc/system_wrappers/interface/logging.h"

namespace webrtc {
namespace {
// Map information from info into rtp. If no relevant information is found
// in info, rtp is set to NULL.
void CopyCodecSpecific(const CodecSpecificInfo* info, RTPVideoHeader** rtp) {
  if (!info) {
    *rtp = NULL;
    return;
  }
  switch (info->codecType) {
    case kVideoCodecVP8: {
      (*rtp)->codec = kRtpVideoVp8;
      (*rtp)->codecHeader.VP8.InitRTPVideoHeaderVP8();
      (*rtp)->codecHeader.VP8.pictureId = info->codecSpecific.VP8.pictureId;
      (*rtp)->codecHeader.VP8.nonReference =
          info->codecSpecific.VP8.nonReference;
      (*rtp)->codecHeader.VP8.temporalIdx = info->codecSpecific.VP8.temporalIdx;
      (*rtp)->codecHeader.VP8.layerSync = info->codecSpecific.VP8.layerSync;
      (*rtp)->codecHeader.VP8.tl0PicIdx = info->codecSpecific.VP8.tl0PicIdx;
      (*rtp)->codecHeader.VP8.keyIdx = info->codecSpecific.VP8.keyIdx;
      (*rtp)->simulcastIdx = info->codecSpecific.VP8.simulcastIdx;
      return;
    }
    case kVideoCodecH264:
      (*rtp)->codec = kRtpVideoH264;
      return;
    case kVideoCodecGeneric:
      (*rtp)->codec = kRtpVideoGeneric;
      (*rtp)->simulcastIdx = info->codecSpecific.generic.simulcast_idx;
      return;
    default:
      // No codec specific info. Change RTP header pointer to NULL.
      *rtp = NULL;
      return;
  }
}
}  // namespace

//#define DEBUG_ENCODER_BIT_STREAM

VCMGenericEncoder::VCMGenericEncoder(VideoEncoder& encoder, bool internalSource /*= false*/)
:
_encoder(encoder),
_codecType(kVideoCodecUnknown),
_VCMencodedFrameCallback(NULL),
_bitRate(0),
_frameRate(0),
_internalSource(internalSource)
{
}

VCMGenericEncoder::~VCMGenericEncoder()
{
}

int32_t VCMGenericEncoder::Release()
{
    _bitRate = 0;
    _frameRate = 0;
    _VCMencodedFrameCallback = NULL;
    return _encoder.Release();
}

int32_t
VCMGenericEncoder::InitEncode(const VideoCodec* settings,
                              int32_t numberOfCores,
                              size_t maxPayloadSize)
{
    _bitRate = settings->startBitrate * 1000;
    _frameRate = settings->maxFramerate;
    _codecType = settings->codecType;
    if (_encoder.InitEncode(settings, numberOfCores, maxPayloadSize) != 0) {
      LOG(LS_ERROR) << "Failed to initialize the encoder associated with "
                       "payload name: " << settings->plName;
      return -1;
    }
    return 0;
}

int32_t
VCMGenericEncoder::Encode(const I420VideoFrame& inputFrame,
                          const CodecSpecificInfo* codecSpecificInfo,
                          const std::vector<FrameType>& frameTypes) {
  std::vector<VideoFrameType> video_frame_types(frameTypes.size(),
                                                kDeltaFrame);
  VCMEncodedFrame::ConvertFrameTypes(frameTypes, &video_frame_types);
  return _encoder.Encode(inputFrame, codecSpecificInfo, &video_frame_types);
}

int32_t
VCMGenericEncoder::SetChannelParameters(int32_t packetLoss, int64_t rtt)
{
    return _encoder.SetChannelParameters(packetLoss, rtt);
}

int32_t
VCMGenericEncoder::SetRates(uint32_t newBitRate, uint32_t frameRate)
{
    uint32_t target_bitrate_kbps = (newBitRate + 500) / 1000;
    int32_t ret = _encoder.SetRates(target_bitrate_kbps, frameRate);
    if (ret < 0)
    {
        return ret;
    }
    _bitRate = newBitRate;
    _frameRate = frameRate;
    return VCM_OK;
}

int32_t
VCMGenericEncoder::CodecConfigParameters(uint8_t* buffer, int32_t size)
{
    int32_t ret = _encoder.CodecConfigParameters(buffer, size);
    if (ret < 0)
    {
        return ret;
    }
    return ret;
}

uint32_t VCMGenericEncoder::BitRate() const
{
    return _bitRate;
}

uint32_t VCMGenericEncoder::FrameRate() const
{
    return _frameRate;
}

int32_t
VCMGenericEncoder::SetPeriodicKeyFrames(bool enable)
{
    return _encoder.SetPeriodicKeyFrames(enable);
}

int32_t VCMGenericEncoder::RequestFrame(
    const std::vector<FrameType>& frame_types) {
  I420VideoFrame image;
  std::vector<VideoFrameType> video_frame_types(frame_types.size(),
                                                kDeltaFrame);
  VCMEncodedFrame::ConvertFrameTypes(frame_types, &video_frame_types);
  return _encoder.Encode(image, NULL, &video_frame_types);
}

int32_t
VCMGenericEncoder::RegisterEncodeCallback(VCMEncodedFrameCallback* VCMencodedFrameCallback)
{
   _VCMencodedFrameCallback = VCMencodedFrameCallback;
   _VCMencodedFrameCallback->SetInternalSource(_internalSource);
   return _encoder.RegisterEncodeCompleteCallback(_VCMencodedFrameCallback);
}

bool
VCMGenericEncoder::InternalSource() const
{
    return _internalSource;
}

 /***************************
  * Callback Implementation
  ***************************/
VCMEncodedFrameCallback::VCMEncodedFrameCallback(
    EncodedImageCallback* post_encode_callback):
_sendCallback(),
_mediaOpt(NULL),
_payloadType(0),
_internalSource(false),
post_encode_callback_(post_encode_callback)
#ifdef DEBUG_ENCODER_BIT_STREAM
, _bitStreamAfterEncoder(NULL)
#endif
{
#ifdef DEBUG_ENCODER_BIT_STREAM
    _bitStreamAfterEncoder = fopen("encoderBitStream.bit", "wb");
#endif
}

VCMEncodedFrameCallback::~VCMEncodedFrameCallback()
{
#ifdef DEBUG_ENCODER_BIT_STREAM
    fclose(_bitStreamAfterEncoder);
#endif
}

int32_t
VCMEncodedFrameCallback::SetTransportCallback(VCMPacketizationCallback* transport)
{
    _sendCallback = transport;
    return VCM_OK;
}

int32_t VCMEncodedFrameCallback::Encoded(
    const EncodedImage& encodedImage,
    const CodecSpecificInfo* codecSpecificInfo,
    const RTPFragmentationHeader* fragmentationHeader) {
  post_encode_callback_->Encoded(encodedImage, NULL, NULL);

  if (_sendCallback == NULL) {
    return VCM_UNINITIALIZED;
  }

#ifdef DEBUG_ENCODER_BIT_STREAM
  if (_bitStreamAfterEncoder != NULL) {
    fwrite(encodedImage._buffer, 1, encodedImage._length,
           _bitStreamAfterEncoder);
  }
#endif

  RTPVideoHeader rtpVideoHeader;
  RTPVideoHeader* rtpVideoHeaderPtr = &rtpVideoHeader;
  CopyCodecSpecific(codecSpecificInfo, &rtpVideoHeaderPtr);

  int32_t callbackReturn = _sendCallback->SendData(
      _payloadType, encodedImage, *fragmentationHeader, rtpVideoHeaderPtr);
  if (callbackReturn < 0) {
    return callbackReturn;
  }

  if (_mediaOpt != NULL) {
    _mediaOpt->UpdateWithEncodedData(encodedImage);
    if (_internalSource)
      return _mediaOpt->DropFrame();  // Signal to encoder to drop next frame.
  }
  return VCM_OK;
}

void
VCMEncodedFrameCallback::SetMediaOpt(
    media_optimization::MediaOptimization *mediaOpt)
{
    _mediaOpt = mediaOpt;
}

}  // namespace webrtc
<commit_msg>Initialize RTPVideoHeader fields to correctly set simulcastIdx for non VP8 codecs.<commit_after>/*
 *  Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */

#include "webrtc/engine_configurations.h"
#include "webrtc/modules/video_coding/main/source/encoded_frame.h"
#include "webrtc/modules/video_coding/main/source/generic_encoder.h"
#include "webrtc/modules/video_coding/main/source/media_optimization.h"
#include "webrtc/system_wrappers/interface/critical_section_wrapper.h"
#include "webrtc/system_wrappers/interface/logging.h"

namespace webrtc {
namespace {
// Map information from info into rtp. If no relevant information is found
// in info, rtp is set to NULL.
void CopyCodecSpecific(const CodecSpecificInfo* info, RTPVideoHeader** rtp) {
  if (!info) {
    *rtp = NULL;
    return;
  }
  switch (info->codecType) {
    case kVideoCodecVP8: {
      (*rtp)->codec = kRtpVideoVp8;
      (*rtp)->codecHeader.VP8.InitRTPVideoHeaderVP8();
      (*rtp)->codecHeader.VP8.pictureId = info->codecSpecific.VP8.pictureId;
      (*rtp)->codecHeader.VP8.nonReference =
          info->codecSpecific.VP8.nonReference;
      (*rtp)->codecHeader.VP8.temporalIdx = info->codecSpecific.VP8.temporalIdx;
      (*rtp)->codecHeader.VP8.layerSync = info->codecSpecific.VP8.layerSync;
      (*rtp)->codecHeader.VP8.tl0PicIdx = info->codecSpecific.VP8.tl0PicIdx;
      (*rtp)->codecHeader.VP8.keyIdx = info->codecSpecific.VP8.keyIdx;
      (*rtp)->simulcastIdx = info->codecSpecific.VP8.simulcastIdx;
      return;
    }
    case kVideoCodecH264:
      (*rtp)->codec = kRtpVideoH264;
      return;
    case kVideoCodecGeneric:
      (*rtp)->codec = kRtpVideoGeneric;
      (*rtp)->simulcastIdx = info->codecSpecific.generic.simulcast_idx;
      return;
    default:
      // No codec specific info. Change RTP header pointer to NULL.
      *rtp = NULL;
      return;
  }
}
}  // namespace

//#define DEBUG_ENCODER_BIT_STREAM

VCMGenericEncoder::VCMGenericEncoder(VideoEncoder& encoder, bool internalSource /*= false*/)
:
_encoder(encoder),
_codecType(kVideoCodecUnknown),
_VCMencodedFrameCallback(NULL),
_bitRate(0),
_frameRate(0),
_internalSource(internalSource)
{
}

VCMGenericEncoder::~VCMGenericEncoder()
{
}

int32_t VCMGenericEncoder::Release()
{
    _bitRate = 0;
    _frameRate = 0;
    _VCMencodedFrameCallback = NULL;
    return _encoder.Release();
}

int32_t
VCMGenericEncoder::InitEncode(const VideoCodec* settings,
                              int32_t numberOfCores,
                              size_t maxPayloadSize)
{
    _bitRate = settings->startBitrate * 1000;
    _frameRate = settings->maxFramerate;
    _codecType = settings->codecType;
    if (_encoder.InitEncode(settings, numberOfCores, maxPayloadSize) != 0) {
      LOG(LS_ERROR) << "Failed to initialize the encoder associated with "
                       "payload name: " << settings->plName;
      return -1;
    }
    return 0;
}

int32_t
VCMGenericEncoder::Encode(const I420VideoFrame& inputFrame,
                          const CodecSpecificInfo* codecSpecificInfo,
                          const std::vector<FrameType>& frameTypes) {
  std::vector<VideoFrameType> video_frame_types(frameTypes.size(),
                                                kDeltaFrame);
  VCMEncodedFrame::ConvertFrameTypes(frameTypes, &video_frame_types);
  return _encoder.Encode(inputFrame, codecSpecificInfo, &video_frame_types);
}

int32_t
VCMGenericEncoder::SetChannelParameters(int32_t packetLoss, int64_t rtt)
{
    return _encoder.SetChannelParameters(packetLoss, rtt);
}

int32_t
VCMGenericEncoder::SetRates(uint32_t newBitRate, uint32_t frameRate)
{
    uint32_t target_bitrate_kbps = (newBitRate + 500) / 1000;
    int32_t ret = _encoder.SetRates(target_bitrate_kbps, frameRate);
    if (ret < 0)
    {
        return ret;
    }
    _bitRate = newBitRate;
    _frameRate = frameRate;
    return VCM_OK;
}

int32_t
VCMGenericEncoder::CodecConfigParameters(uint8_t* buffer, int32_t size)
{
    int32_t ret = _encoder.CodecConfigParameters(buffer, size);
    if (ret < 0)
    {
        return ret;
    }
    return ret;
}

uint32_t VCMGenericEncoder::BitRate() const
{
    return _bitRate;
}

uint32_t VCMGenericEncoder::FrameRate() const
{
    return _frameRate;
}

int32_t
VCMGenericEncoder::SetPeriodicKeyFrames(bool enable)
{
    return _encoder.SetPeriodicKeyFrames(enable);
}

int32_t VCMGenericEncoder::RequestFrame(
    const std::vector<FrameType>& frame_types) {
  I420VideoFrame image;
  std::vector<VideoFrameType> video_frame_types(frame_types.size(),
                                                kDeltaFrame);
  VCMEncodedFrame::ConvertFrameTypes(frame_types, &video_frame_types);
  return _encoder.Encode(image, NULL, &video_frame_types);
}

int32_t
VCMGenericEncoder::RegisterEncodeCallback(VCMEncodedFrameCallback* VCMencodedFrameCallback)
{
   _VCMencodedFrameCallback = VCMencodedFrameCallback;
   _VCMencodedFrameCallback->SetInternalSource(_internalSource);
   return _encoder.RegisterEncodeCompleteCallback(_VCMencodedFrameCallback);
}

bool
VCMGenericEncoder::InternalSource() const
{
    return _internalSource;
}

 /***************************
  * Callback Implementation
  ***************************/
VCMEncodedFrameCallback::VCMEncodedFrameCallback(
    EncodedImageCallback* post_encode_callback):
_sendCallback(),
_mediaOpt(NULL),
_payloadType(0),
_internalSource(false),
post_encode_callback_(post_encode_callback)
#ifdef DEBUG_ENCODER_BIT_STREAM
, _bitStreamAfterEncoder(NULL)
#endif
{
#ifdef DEBUG_ENCODER_BIT_STREAM
    _bitStreamAfterEncoder = fopen("encoderBitStream.bit", "wb");
#endif
}

VCMEncodedFrameCallback::~VCMEncodedFrameCallback()
{
#ifdef DEBUG_ENCODER_BIT_STREAM
    fclose(_bitStreamAfterEncoder);
#endif
}

int32_t
VCMEncodedFrameCallback::SetTransportCallback(VCMPacketizationCallback* transport)
{
    _sendCallback = transport;
    return VCM_OK;
}

int32_t VCMEncodedFrameCallback::Encoded(
    const EncodedImage& encodedImage,
    const CodecSpecificInfo* codecSpecificInfo,
    const RTPFragmentationHeader* fragmentationHeader) {
  post_encode_callback_->Encoded(encodedImage, NULL, NULL);

  if (_sendCallback == NULL) {
    return VCM_UNINITIALIZED;
  }

#ifdef DEBUG_ENCODER_BIT_STREAM
  if (_bitStreamAfterEncoder != NULL) {
    fwrite(encodedImage._buffer, 1, encodedImage._length,
           _bitStreamAfterEncoder);
  }
#endif

  RTPVideoHeader rtpVideoHeader;
  memset(&rtpVideoHeader, 0, sizeof(RTPVideoHeader));
  RTPVideoHeader* rtpVideoHeaderPtr = &rtpVideoHeader;
  CopyCodecSpecific(codecSpecificInfo, &rtpVideoHeaderPtr);

  int32_t callbackReturn = _sendCallback->SendData(
      _payloadType, encodedImage, *fragmentationHeader, rtpVideoHeaderPtr);
  if (callbackReturn < 0) {
    return callbackReturn;
  }

  if (_mediaOpt != NULL) {
    _mediaOpt->UpdateWithEncodedData(encodedImage);
    if (_internalSource)
      return _mediaOpt->DropFrame();  // Signal to encoder to drop next frame.
  }
  return VCM_OK;
}

void
VCMEncodedFrameCallback::SetMediaOpt(
    media_optimization::MediaOptimization *mediaOpt)
{
    _mediaOpt = mediaOpt;
}

}  // namespace webrtc
<|endoftext|>


<commit_before>#include "kwm.h"
#include "helpers.h"
#include "daemon.h"
#include "display.h"
#include "space.h"
#include "window.h"
#include "keys.h"
#include "interpreter.h"
#include "border.h"

const std::string KwmCurrentVersion = "Kwm Version 1.1.1";
const std::string PlistFile = "com.koekeishiya.kwm.plist";

kwm_mach KWMMach = {};
kwm_path KWMPath = {};
kwm_screen KWMScreen = {};
kwm_toggles KWMToggles = {};
kwm_focus KWMFocus = {};
kwm_mode KWMMode = {};
kwm_tiling KWMTiling = {};
kwm_cache KWMCache = {};
kwm_thread KWMThread = {};
kwm_hotkeys KWMHotkeys = {};
kwm_border FocusedBorder = {};
kwm_border MarkedBorder = {};
kwm_border PrefixBorder = {};

CGEventRef CGEventCallback(CGEventTapProxy Proxy, CGEventType Type, CGEventRef Event, void *Refcon)
{
    pthread_mutex_lock(&KWMThread.Lock);

    switch(Type)
    {
        case kCGEventTapDisabledByTimeout:
        case kCGEventTapDisabledByUserInput:
        {
            DEBUG("Restarting Event Tap")
            CGEventTapEnable(KWMMach.EventTap, true);
        } break;
        case kCGEventKeyDown:
        {
            if(KWMToggles.UseBuiltinHotkeys && KwmMainHotkeyTrigger(&Event))
            {
                    pthread_mutex_unlock(&KWMThread.Lock);
                    return NULL;
            }

            if(KWMMode.Focus == FocusModeAutofocus &&
               !IsActiveSpaceFloating())
            {
                CGEventSetIntegerValueField(Event, kCGKeyboardEventAutorepeat, 0);
                CGEventPostToPSN(&KWMFocus.PSN, Event);
                pthread_mutex_unlock(&KWMThread.Lock);
                return NULL;
            }
        } break;
        case kCGEventKeyUp:
        {
            if(KWMMode.Focus == FocusModeAutofocus &&
               !IsActiveSpaceFloating())
            {
                CGEventSetIntegerValueField(Event, kCGKeyboardEventAutorepeat, 0);
                CGEventPostToPSN(&KWMFocus.PSN, Event);
                pthread_mutex_unlock(&KWMThread.Lock);
                return NULL;
            }
        } break;
        case kCGEventMouseMoved:
        {
            UpdateActiveScreen();

            if(KWMMode.Focus != FocusModeDisabled &&
               KWMMode.Focus != FocusModeStandby &&
               !IsActiveSpaceFloating())
                FocusWindowBelowCursor();
        } break;
        case kCGEventLeftMouseDown:
        {
            DEBUG("Left mouse button was pressed")
            if(!IsActiveSpaceFloating())
            {
                FocusWindowBelowCursor();
                if(KWMToggles.EnableDragAndDrop)
                    KWMToggles.DragInProgress = true;
            }
        } break;
        case kCGEventLeftMouseUp:
        {
            DEBUG("Left mouse button was released")
            if(!IsActiveSpaceFloating())
            {
                if(KWMToggles.EnableDragAndDrop && KWMToggles.DragInProgress)
                    KWMToggles.DragInProgress = false;

                if(KWMFocus.Window && FocusedBorder.Enabled)
                {
                    if(IsWindowFloating(KWMFocus.Window->WID, NULL))
                        UpdateBorder("focused");
                }
            }
        } break;
    }

    pthread_mutex_unlock(&KWMThread.Lock);
    return Event;
}

void KwmQuit()
{
    CloseBorder(&FocusedBorder);
    CloseBorder(&MarkedBorder);
    CloseBorder(&PrefixBorder);

    exit(0);
}

void * KwmWindowMonitor(void*)
{
    while(1)
    {
        pthread_mutex_lock(&KWMThread.Lock);
        CheckPrefixTimeout();
        UpdateWindowTree();
        pthread_mutex_unlock(&KWMThread.Lock);
        usleep(200000);
    }
}

void KwmReloadConfig()
{
    KwmClearSettings();
    KwmExecuteConfig();
}

void KwmClearSettings()
{
    std::map<std::string, std::vector<CFTypeRef> >::iterator It;
    for(It = KWMTiling.AllowedWindowRoles.begin(); It != KWMTiling.AllowedWindowRoles.end(); ++It)
    {
        std::vector<CFTypeRef> &WindowRoles = It->second;
        for(std::size_t RoleIndex = 0; RoleIndex < WindowRoles.size(); ++RoleIndex)
            CFRelease(WindowRoles[RoleIndex]);

        WindowRoles.clear();
    }

    KWMTiling.FloatingAppLst.clear();
    KWMHotkeys.List.clear();
    KWMHotkeys.Prefix.Enabled = false;
}

void KwmExecuteConfig()
{
    char *HomeP = std::getenv("HOME");
    if(!HomeP)
    {
        DEBUG("Failed to get environment variable 'HOME'")
        return;
    }

    KWMPath.EnvHome = HomeP;
    KWMPath.ConfigFolder = ".kwm";
    KwmExecuteFile(KWMPath.ConfigFile);
}

void KwmExecuteFile(std::string File)
{
    std::ifstream FileHandle(KWMPath.EnvHome + "/" + KWMPath.ConfigFolder + "/" + File);
    if(FileHandle.fail())
    {
        DEBUG("Could not open " << KWMPath.EnvHome << "/" << KWMPath.ConfigFolder << "/" << File
              << ", make sure the file exists." << std::endl)
        return;
    }

    std::string Line;
    while(std::getline(FileHandle, Line))
    {
        if(!Line.empty() && Line[0] != '#')
        {
            if(IsPrefixOfString(Line, "kwmc"))
                KwmInterpretCommand(Line, 0);
            else if(IsPrefixOfString(Line, "sys"))
                KwmExecuteThreadedSystemCommand(Line);
            else if(IsPrefixOfString(Line, "include"))
                KwmExecuteFile(Line);
        }
    }

    FileHandle.close();
}

void KwmExecuteSystemCommand(std::string Command)
{
    system(Command.c_str());
}

void KwmExecuteThreadedSystemCommand(std::string Command)
{
    std::string *HCommand = new std::string(Command);
    pthread_create(&KWMThread.SystemCommand, NULL, &KwmStartThreadedSystemCommand, HCommand);
}

void * KwmStartThreadedSystemCommand(void *Args)
{
    std::string Command = *((std::string*)Args);
    std::cout << Command << std::endl;
    KwmExecuteSystemCommand(Command);
    delete (std::string*)Args;
    return NULL;
}

bool IsKwmAlreadyAddedToLaunchd()
{
    std::string SymlinkFullPath = KWMPath.EnvHome + "/Library/LaunchAgents/" + PlistFile;

    struct stat attr;
    int Result = stat(SymlinkFullPath.c_str(), &attr);
    if(Result == -1)
        return false;

    return true;
}

void AddKwmToLaunchd()
{
    if(IsKwmAlreadyAddedToLaunchd())
        return;

    std::string SymlinkFullPath = KWMPath.EnvHome + "/Library/LaunchAgents/" + PlistFile;

    std::ifstream TemplateFD(KWMPath.FilePath + "/kwm_template.plist");
    if(TemplateFD.fail())
        return;

    std::ofstream OutFD(SymlinkFullPath);
    if(OutFD.fail())
        return;

    std::string Line;
    std::vector<std::string> PlistContents;
    while(std::getline(TemplateFD, Line))
        PlistContents.push_back(Line);

    DEBUG("AddKwmToLaunchd() Creating file: " << SymlinkFullPath)
    for(std::size_t LineNumber = 0; LineNumber < PlistContents.size(); ++LineNumber)
    {
        if(LineNumber == 8)
            OutFD << "    <string>" + KWMPath.FilePath + "/kwm</string>" << std::endl;
        else
            OutFD << PlistContents[LineNumber] << std::endl;
    }

    TemplateFD.close();
    OutFD.close();
}

void RemoveKwmFromLaunchd()
{
    if(!IsKwmAlreadyAddedToLaunchd())
        return;

    std::string SymlinkFullPath = KWMPath.EnvHome + "/Library/LaunchAgents/" + PlistFile;
    std::string RemoveSymlink = "rm " + SymlinkFullPath;

    system(RemoveSymlink.c_str());
    DEBUG("RemoveKwmFromLaunchd() Removing file: " << SymlinkFullPath)
}

bool GetKwmFilePath()
{
    bool Result = false;
    char PathBuf[PROC_PIDPATHINFO_MAXSIZE];
    pid_t Pid = getpid();
    int Ret = proc_pidpath(Pid, PathBuf, sizeof(PathBuf));
    if (Ret > 0)
    {
        KWMPath.FilePath = PathBuf;

        std::size_t Split = KWMPath.FilePath.find_last_of("/\\");
        KWMPath.FilePath = KWMPath.FilePath.substr(0, Split);
        KWMPath.HotkeySOFullPath = KWMPath.FilePath + "/hotkeys.so";
        Result = true;
    }

    return Result;
}

void KwmInit()
{
    if(!CheckPrivileges())
        Fatal("Could not access OSX Accessibility!");

    if (pthread_mutex_init(&KWMThread.Lock, NULL) != 0)
        Fatal("Could not create mutex!");

    if(KwmStartDaemon())
        pthread_create(&KWMThread.Daemon, NULL, &KwmDaemonHandleConnectionBG, NULL);
    else
        Fatal("Kwm: Could not start daemon..");

    signal(SIGSEGV, SignalHandler);

    KWMScreen.SplitRatio = 0.5;
    KWMScreen.SplitMode = -1;
    KWMScreen.MarkedWindow = -1;
    KWMScreen.PrevSpace = -1;
    KWMScreen.DefaultOffset = CreateDefaultScreenOffset();
    KWMScreen.MaxCount = 5;
    KWMScreen.ActiveCount = 0;
    KWMScreen.UpdateSpace = false;

    KWMToggles.EnableTilingMode = true;
    KWMToggles.UseBuiltinHotkeys = true;
    KWMToggles.EnableDragAndDrop = true;
    KWMToggles.UseMouseFollowsFocus = true;

    KWMMode.Space = SpaceModeBSP;
    KWMMode.Focus = FocusModeAutoraise;
    KWMMode.Cycle = CycleModeScreen;

    KWMHotkeys.Prefix.Enabled = false;
    KWMHotkeys.Prefix.Global = false;
    KWMHotkeys.Prefix.Active = false;
    KWMHotkeys.Prefix.Timeout = 0.75;

    KWMPath.ConfigFile = "kwmrc";
    GetKwmFilePath();

    KwmExecuteConfig();
    GetActiveDisplays();

    pthread_create(&KWMThread.WindowMonitor, NULL, &KwmWindowMonitor, NULL);
}

bool CheckPrivileges()
{
    bool Result = false;
    const void * Keys[] = { kAXTrustedCheckOptionPrompt };
    const void * Values[] = { kCFBooleanTrue };

    CFDictionaryRef Options;
    Options = CFDictionaryCreate(kCFAllocatorDefault,
            Keys, Values, sizeof(Keys) / sizeof(*Keys),
            &kCFCopyStringDictionaryKeyCallBacks,
            &kCFTypeDictionaryValueCallBacks);

    Result = AXIsProcessTrustedWithOptions(Options);
    CFRelease(Options);

    return Result;
}

bool CheckArguments(int argc, char **argv)
{
    bool Result = false;

    if(argc == 2)
    {
        std::string Arg = argv[1];
        if(Arg == "--version")
        {
            std::cout << KwmCurrentVersion << std::endl;
            Result = true;
        }
    }

    return Result;
}

void SignalHandler(int Signum)
{
    CloseBorder(&FocusedBorder);
    CloseBorder(&MarkedBorder);
    CloseBorder(&PrefixBorder);

    signal(Signum, SIG_DFL);
    kill(getpid(), Signum);
}

void Fatal(const std::string &Err)
{
    std::cout << Err << std::endl;
    exit(1);
}

int main(int argc, char **argv)
{
    if(CheckArguments(argc, argv))
        return 0;

    KwmInit();
    KWMMach.EventMask = ((1 << kCGEventKeyDown) |
                         (1 << kCGEventKeyUp) |
                         (1 << kCGEventMouseMoved) |
                         (1 << kCGEventLeftMouseDown) |
                         (1 << kCGEventLeftMouseUp));

    KWMMach.EventTap = CGEventTapCreate(kCGSessionEventTap, kCGHeadInsertEventTap, 0, KWMMach.EventMask, CGEventCallback, NULL);
    if(!KWMMach.EventTap || !CGEventTapIsEnabled(KWMMach.EventTap))
        Fatal("ERROR: Could not create event-tap!");

    CFRunLoopAddSource(CFRunLoopGetCurrent(),
                       CFMachPortCreateRunLoopSource(kCFAllocatorDefault, KWMMach.EventTap, 0),
                       kCFRunLoopCommonModes);

    CGEventTapEnable(KWMMach.EventTap, true);
    CreateWorkspaceWatcher(KWMMach.WorkspaceWatcher);

    NSApplicationLoad();
    CFRunLoopRun();
    return 0;
}
<commit_msg>prevent space-layout from breaking<commit_after>#include "kwm.h"
#include "helpers.h"
#include "daemon.h"
#include "display.h"
#include "space.h"
#include "window.h"
#include "keys.h"
#include "interpreter.h"
#include "border.h"

const std::string KwmCurrentVersion = "Kwm Version 1.1.1";
const std::string PlistFile = "com.koekeishiya.kwm.plist";

kwm_mach KWMMach = {};
kwm_path KWMPath = {};
kwm_screen KWMScreen = {};
kwm_toggles KWMToggles = {};
kwm_focus KWMFocus = {};
kwm_mode KWMMode = {};
kwm_tiling KWMTiling = {};
kwm_cache KWMCache = {};
kwm_thread KWMThread = {};
kwm_hotkeys KWMHotkeys = {};
kwm_border FocusedBorder = {};
kwm_border MarkedBorder = {};
kwm_border PrefixBorder = {};

CGEventRef CGEventCallback(CGEventTapProxy Proxy, CGEventType Type, CGEventRef Event, void *Refcon)
{
    pthread_mutex_lock(&KWMThread.Lock);

    switch(Type)
    {
        case kCGEventTapDisabledByTimeout:
        case kCGEventTapDisabledByUserInput:
        {
            DEBUG("Restarting Event Tap")
            CGEventTapEnable(KWMMach.EventTap, true);
        } break;
        case kCGEventKeyDown:
        {
            if(KWMToggles.UseBuiltinHotkeys && KwmMainHotkeyTrigger(&Event))
            {
                    pthread_mutex_unlock(&KWMThread.Lock);
                    return NULL;
            }

            if(KWMMode.Focus == FocusModeAutofocus &&
               !IsActiveSpaceFloating())
            {
                CGEventSetIntegerValueField(Event, kCGKeyboardEventAutorepeat, 0);
                CGEventPostToPSN(&KWMFocus.PSN, Event);
                pthread_mutex_unlock(&KWMThread.Lock);
                return NULL;
            }
        } break;
        case kCGEventKeyUp:
        {
            if(KWMMode.Focus == FocusModeAutofocus &&
               !IsActiveSpaceFloating())
            {
                CGEventSetIntegerValueField(Event, kCGKeyboardEventAutorepeat, 0);
                CGEventPostToPSN(&KWMFocus.PSN, Event);
                pthread_mutex_unlock(&KWMThread.Lock);
                return NULL;
            }
        } break;
        case kCGEventMouseMoved:
        {
            UpdateActiveScreen();

            if(KWMMode.Focus != FocusModeDisabled &&
               KWMMode.Focus != FocusModeStandby &&
               !IsActiveSpaceFloating())
                FocusWindowBelowCursor();
        } break;
        case kCGEventLeftMouseDown:
        {
            DEBUG("Left mouse button was pressed")
            if(!IsActiveSpaceFloating())
            {
                FocusWindowBelowCursor();
                if(KWMToggles.EnableDragAndDrop)
                    KWMToggles.DragInProgress = true;
            }
        } break;
        case kCGEventLeftMouseUp:
        {
            DEBUG("Left mouse button was released")
            if(!IsActiveSpaceFloating())
            {
                if(KWMToggles.EnableDragAndDrop && KWMToggles.DragInProgress)
                    KWMToggles.DragInProgress = false;

                if(KWMFocus.Window && FocusedBorder.Enabled)
                {
                    if(IsWindowFloating(KWMFocus.Window->WID, NULL))
                        UpdateBorder("focused");
                }
            }
        } break;
    }

    pthread_mutex_unlock(&KWMThread.Lock);
    return Event;
}

void KwmQuit()
{
    CloseBorder(&FocusedBorder);
    CloseBorder(&MarkedBorder);
    CloseBorder(&PrefixBorder);

    exit(0);
}

void * KwmWindowMonitor(void*)
{
    while(1)
    {
        pthread_mutex_lock(&KWMThread.Lock);
        CheckPrefixTimeout();

        if(!IsSpaceTransitionInProgress())
            UpdateWindowTree();

        pthread_mutex_unlock(&KWMThread.Lock);
        usleep(100000);
    }
}

void KwmReloadConfig()
{
    KwmClearSettings();
    KwmExecuteConfig();
}

void KwmClearSettings()
{
    std::map<std::string, std::vector<CFTypeRef> >::iterator It;
    for(It = KWMTiling.AllowedWindowRoles.begin(); It != KWMTiling.AllowedWindowRoles.end(); ++It)
    {
        std::vector<CFTypeRef> &WindowRoles = It->second;
        for(std::size_t RoleIndex = 0; RoleIndex < WindowRoles.size(); ++RoleIndex)
            CFRelease(WindowRoles[RoleIndex]);

        WindowRoles.clear();
    }

    KWMTiling.FloatingAppLst.clear();
    KWMHotkeys.List.clear();
    KWMHotkeys.Prefix.Enabled = false;
}

void KwmExecuteConfig()
{
    char *HomeP = std::getenv("HOME");
    if(!HomeP)
    {
        DEBUG("Failed to get environment variable 'HOME'")
        return;
    }

    KWMPath.EnvHome = HomeP;
    KWMPath.ConfigFolder = ".kwm";
    KwmExecuteFile(KWMPath.ConfigFile);
}

void KwmExecuteFile(std::string File)
{
    std::ifstream FileHandle(KWMPath.EnvHome + "/" + KWMPath.ConfigFolder + "/" + File);
    if(FileHandle.fail())
    {
        DEBUG("Could not open " << KWMPath.EnvHome << "/" << KWMPath.ConfigFolder << "/" << File
              << ", make sure the file exists." << std::endl)
        return;
    }

    std::string Line;
    while(std::getline(FileHandle, Line))
    {
        if(!Line.empty() && Line[0] != '#')
        {
            if(IsPrefixOfString(Line, "kwmc"))
                KwmInterpretCommand(Line, 0);
            else if(IsPrefixOfString(Line, "sys"))
                KwmExecuteThreadedSystemCommand(Line);
            else if(IsPrefixOfString(Line, "include"))
                KwmExecuteFile(Line);
        }
    }

    FileHandle.close();
}

void KwmExecuteSystemCommand(std::string Command)
{
    system(Command.c_str());
}

void KwmExecuteThreadedSystemCommand(std::string Command)
{
    std::string *HCommand = new std::string(Command);
    pthread_create(&KWMThread.SystemCommand, NULL, &KwmStartThreadedSystemCommand, HCommand);
}

void * KwmStartThreadedSystemCommand(void *Args)
{
    std::string Command = *((std::string*)Args);
    std::cout << Command << std::endl;
    KwmExecuteSystemCommand(Command);
    delete (std::string*)Args;
    return NULL;
}

bool IsKwmAlreadyAddedToLaunchd()
{
    std::string SymlinkFullPath = KWMPath.EnvHome + "/Library/LaunchAgents/" + PlistFile;

    struct stat attr;
    int Result = stat(SymlinkFullPath.c_str(), &attr);
    if(Result == -1)
        return false;

    return true;
}

void AddKwmToLaunchd()
{
    if(IsKwmAlreadyAddedToLaunchd())
        return;

    std::string SymlinkFullPath = KWMPath.EnvHome + "/Library/LaunchAgents/" + PlistFile;

    std::ifstream TemplateFD(KWMPath.FilePath + "/kwm_template.plist");
    if(TemplateFD.fail())
        return;

    std::ofstream OutFD(SymlinkFullPath);
    if(OutFD.fail())
        return;

    std::string Line;
    std::vector<std::string> PlistContents;
    while(std::getline(TemplateFD, Line))
        PlistContents.push_back(Line);

    DEBUG("AddKwmToLaunchd() Creating file: " << SymlinkFullPath)
    for(std::size_t LineNumber = 0; LineNumber < PlistContents.size(); ++LineNumber)
    {
        if(LineNumber == 8)
            OutFD << "    <string>" + KWMPath.FilePath + "/kwm</string>" << std::endl;
        else
            OutFD << PlistContents[LineNumber] << std::endl;
    }

    TemplateFD.close();
    OutFD.close();
}

void RemoveKwmFromLaunchd()
{
    if(!IsKwmAlreadyAddedToLaunchd())
        return;

    std::string SymlinkFullPath = KWMPath.EnvHome + "/Library/LaunchAgents/" + PlistFile;
    std::string RemoveSymlink = "rm " + SymlinkFullPath;

    system(RemoveSymlink.c_str());
    DEBUG("RemoveKwmFromLaunchd() Removing file: " << SymlinkFullPath)
}

bool GetKwmFilePath()
{
    bool Result = false;
    char PathBuf[PROC_PIDPATHINFO_MAXSIZE];
    pid_t Pid = getpid();
    int Ret = proc_pidpath(Pid, PathBuf, sizeof(PathBuf));
    if (Ret > 0)
    {
        KWMPath.FilePath = PathBuf;

        std::size_t Split = KWMPath.FilePath.find_last_of("/\\");
        KWMPath.FilePath = KWMPath.FilePath.substr(0, Split);
        KWMPath.HotkeySOFullPath = KWMPath.FilePath + "/hotkeys.so";
        Result = true;
    }

    return Result;
}

void KwmInit()
{
    if(!CheckPrivileges())
        Fatal("Could not access OSX Accessibility!");

    if (pthread_mutex_init(&KWMThread.Lock, NULL) != 0)
        Fatal("Could not create mutex!");

    if(KwmStartDaemon())
        pthread_create(&KWMThread.Daemon, NULL, &KwmDaemonHandleConnectionBG, NULL);
    else
        Fatal("Kwm: Could not start daemon..");

    signal(SIGSEGV, SignalHandler);

    KWMScreen.SplitRatio = 0.5;
    KWMScreen.SplitMode = -1;
    KWMScreen.MarkedWindow = -1;
    KWMScreen.PrevSpace = -1;
    KWMScreen.DefaultOffset = CreateDefaultScreenOffset();
    KWMScreen.MaxCount = 5;
    KWMScreen.ActiveCount = 0;
    KWMScreen.UpdateSpace = false;

    KWMToggles.EnableTilingMode = true;
    KWMToggles.UseBuiltinHotkeys = true;
    KWMToggles.EnableDragAndDrop = true;
    KWMToggles.UseMouseFollowsFocus = true;

    KWMMode.Space = SpaceModeBSP;
    KWMMode.Focus = FocusModeAutoraise;
    KWMMode.Cycle = CycleModeScreen;

    KWMHotkeys.Prefix.Enabled = false;
    KWMHotkeys.Prefix.Global = false;
    KWMHotkeys.Prefix.Active = false;
    KWMHotkeys.Prefix.Timeout = 0.75;

    KWMPath.ConfigFile = "kwmrc";
    GetKwmFilePath();

    KwmExecuteConfig();
    GetActiveDisplays();

    pthread_create(&KWMThread.WindowMonitor, NULL, &KwmWindowMonitor, NULL);
}

bool CheckPrivileges()
{
    bool Result = false;
    const void * Keys[] = { kAXTrustedCheckOptionPrompt };
    const void * Values[] = { kCFBooleanTrue };

    CFDictionaryRef Options;
    Options = CFDictionaryCreate(kCFAllocatorDefault,
            Keys, Values, sizeof(Keys) / sizeof(*Keys),
            &kCFCopyStringDictionaryKeyCallBacks,
            &kCFTypeDictionaryValueCallBacks);

    Result = AXIsProcessTrustedWithOptions(Options);
    CFRelease(Options);

    return Result;
}

bool CheckArguments(int argc, char **argv)
{
    bool Result = false;

    if(argc == 2)
    {
        std::string Arg = argv[1];
        if(Arg == "--version")
        {
            std::cout << KwmCurrentVersion << std::endl;
            Result = true;
        }
    }

    return Result;
}

void SignalHandler(int Signum)
{
    CloseBorder(&FocusedBorder);
    CloseBorder(&MarkedBorder);
    CloseBorder(&PrefixBorder);

    signal(Signum, SIG_DFL);
    kill(getpid(), Signum);
}

void Fatal(const std::string &Err)
{
    std::cout << Err << std::endl;
    exit(1);
}

int main(int argc, char **argv)
{
    if(CheckArguments(argc, argv))
        return 0;

    KwmInit();
    KWMMach.EventMask = ((1 << kCGEventKeyDown) |
                         (1 << kCGEventKeyUp) |
                         (1 << kCGEventMouseMoved) |
                         (1 << kCGEventLeftMouseDown) |
                         (1 << kCGEventLeftMouseUp));

    KWMMach.EventTap = CGEventTapCreate(kCGSessionEventTap, kCGHeadInsertEventTap, 0, KWMMach.EventMask, CGEventCallback, NULL);
    if(!KWMMach.EventTap || !CGEventTapIsEnabled(KWMMach.EventTap))
        Fatal("ERROR: Could not create event-tap!");

    CFRunLoopAddSource(CFRunLoopGetCurrent(),
                       CFMachPortCreateRunLoopSource(kCFAllocatorDefault, KWMMach.EventTap, 0),
                       kCFRunLoopCommonModes);

    CGEventTapEnable(KWMMach.EventTap, true);
    CreateWorkspaceWatcher(KWMMach.WorkspaceWatcher);

    NSApplicationLoad();
    CFRunLoopRun();
    return 0;
}
<|endoftext|>


<commit_before><commit_msg>aggresive use of paired-end reads<commit_after><|endoftext|>