<commit_before>#include "LevelHandler.h"

LevelHandler::LevelHandler()
{
}

LevelHandler::~LevelHandler()
{
}

LevelHandler * LevelHandler::GetInstance()
{
	static LevelHandler instance;
	return &instance;
}

LevelData::LevelStatus LevelHandler::ExportLevelFile()
{
	std::string path = GetFilePathAndName(Operation::SAVE);
	if (path == "")
	{
		return LevelData::LevelStatus::L_FILE_SAVE_CANCELLED;
	}

	std::fstream file;
	file.open(path, std::fstream::out | std::fstream::binary);
	LevelData::MainLevelHeader header = this->GetMainHeader();				//Get the main header for the file
	char* data = (char*)&header;

	file.write(data, sizeof(LevelData::MainLevelHeader));					 //Write the main header first

	//Resource data
	size_t resSize = sizeof(LevelData::ResourceHeader)* header.resAmount;    //size of resource data
	char* resData  = new char[resSize];										 //Allocate for resource data
	GetResourceData(resData);												 //Get resource data
	file.write(resData, resSize);											 //Write resource data to file

	//Spawn Points
	LevelData::SpawnHeader spawns[2];
	GetSpawnData((char*)spawns);
	file.write((char*)spawns, sizeof(LevelData::SpawnHeader) * 2);

	//Model Entities
	size_t modelSize = sizeof(LevelData::EntityHeader) * header.entityAmount;
	char* modelData  = new char[modelSize];					//Allocate for modelEntity data
	GetEntityData(modelData);								//Get modelEntity data
	file.write(modelData, modelSize);						//Write all modelEntities

	file.close();

	delete resData;
	delete modelData;//Cleanup

	QFileInfo info(QString::fromStdString(path));
	m_currentLevel.SetName(info.baseName().toStdString()); //Set the new name to the level
	return LevelData::LevelStatus::L_OK;
}

LevelData::LevelStatus LevelHandler::ImportLevelFile()
{

	//Let the user pick a path and file name.
	std::string path = GetFilePathAndName(Operation::LOAD);
	if (path == "")
	{
		return LevelData::LevelStatus::L_FILE_SAVE_CANCELLED;
	}
	NewLevel();		//Empty the current level object

	std::fstream file;
	file.open(path, std::fstream::in | std::fstream::binary);

	LevelData::MainLevelHeader header;
	file.read((char*)&header, sizeof(LevelData::MainLevelHeader));				 //Read file header

	//Resource data
	size_t resSize = sizeof(LevelData::ResourceHeader)* header.resAmount;		  //size of resource data
	file.seekg(resSize, std::ios_base::cur);									  //Skip the resource data (only used by the game engine)

	//Spawn Points
	LevelData::SpawnHeader spawns[2];
	file.read((char*)spawns, sizeof(LevelData::SpawnHeader) * 2);
	m_currentLevel.SetSpawnPoint(spawns[0], 0);
	m_currentLevel.SetSpawnPoint(spawns[1], 1);

	//Model Entities
	size_t modelSize = sizeof(LevelData::EntityHeader) * header.entityAmount;	  //memsize
	char* modelData = new char[modelSize];										  //allocate for the entities
	file.read(modelData, modelSize);											  //Bulk read all the entity data
	this->LoadEntities((LevelData::EntityHeader*)modelData, header.entityAmount); //Load them into the level object

	file.close();
	delete modelData; //Cleanup
	QFileInfo info(QString::fromStdString(path));
	m_currentLevel.SetName(info.baseName().toStdString()); //Set the  name to the level

	return LevelData::LevelStatus::L_OK;
}

LevelData::LevelStatus LevelHandler::NewLevel()
{

	this->m_currentLevel.Destroy();
	return LevelData::LevelStatus::L_OK;
}

std::string LevelHandler::GetFilePathAndName(Operation flag)
{
	if (flag == Operation::SAVE)
	{
		QFileDialog dlg(NULL, "Save file");
		dlg.setAcceptMode(QFileDialog::AcceptSave);
		QString fullpath = filePath;
		fullpath.append(m_currentLevel.GetName()->c_str());
		fullpath.append(".level");

		dlg.setDirectory(fullpath);
		dlg.setNameFilter("Levels (*.level)");
		if (dlg.exec())
		{

			return dlg.selectedFiles().at(0).toStdString();
		}
		else
		{
			return "";
		}
	}

	else
	{
		QFileDialog dlg(NULL, "Load file");
		dlg.setAcceptMode(QFileDialog::AcceptOpen);
		//QFileDialog::ReadOnly

		dlg.setDirectory(filePath);
		dlg.setNameFilter("Levels (*.level)");
		if (dlg.exec())
		{
			return dlg.selectedFiles().at(0).toStdString(); //Return file path as string
		}
		else
		{
			return "";
		}

	}

}

LevelData::MainLevelHeader LevelHandler::GetMainHeader()
{
	LevelData::MainLevelHeader header;

	header.resAmount	     = m_currentLevel.GetUniqueModels()->size();
	header.entityAmount      = m_currentLevel.GetNumEntities();
	header.lightAmount       = m_currentLevel.GetNumLights();
	header.AiComponentAmount = (unsigned int) m_currentLevel.GetAiHandler()->GetAllPathComponents()->size();
	return header;
}

LevelData::LevelStatus LevelHandler::GetEntityData(char * dataPtr)
{
	unsigned int offset = 0;
	std::unordered_map<unsigned int, std::vector<Container>> *  map = m_currentLevel.GetModelEntities();
	for (auto iterator = map->begin(); iterator != map->end(); ++iterator)
	{
		std::vector<Container> * entityContainer = &iterator->second;

		for (size_t i = 0; i < entityContainer->size(); i++)
		{
			LevelData::EntityHeader entity;

			entity.EntityID = entityContainer->at(i).internalID;
			entity.modelID  = entityContainer->at(i).component.modelID;

			entity.position[0] = entityContainer->at(i).position.m128_f32[0];
			entity.position[1] = entityContainer->at(i).position.m128_f32[1];	//Convert from Vector to float3
			entity.position[2] = entityContainer->at(i).position.m128_f32[2];

			entity.rotation[0] = entityContainer->at(i).rotation.m128_f32[0];
			entity.rotation[1] = entityContainer->at(i).rotation.m128_f32[1];	//Convert from Vector to float3
			entity.rotation[2] = entityContainer->at(i).rotation.m128_f32[2];

			entity.isStatic	   = entityContainer->at(i).isStatic;
			memcpy(dataPtr + offset, (char*)&entity, sizeof(LevelData::EntityHeader));
			offset += sizeof(LevelData::EntityHeader);

		}

	}
	return LevelData::LevelStatus::L_OK;
}

LevelData::LevelStatus LevelHandler::GetResourceData(char * dataPtr)
{
	unsigned int offset = 0;
	for (size_t i = 0; i < this->m_currentLevel.GetUniqueModels()->size(); i++)
	{
		LevelData::ResourceHeader res;
		res.id = this->m_currentLevel.GetUniqueModels()->at(i);
		res.resourceType = Resources::ResourceType::RES_MODEL;
		memcpy(dataPtr + offset, (char*)&res, sizeof(LevelData::ResourceHeader));
		offset += sizeof(LevelData::ResourceHeader);
	}

	return LevelData::LevelStatus::L_OK;
}

LevelData::LevelStatus LevelHandler::GetSpawnData(char * dataPtr)
{

	for (size_t i = 0; i < 2; i++)
	{
		Container* spawn = m_currentLevel.GetSpawnPoint(i);
		LevelData::SpawnHeader spawnheader;

		spawnheader.position[0] = spawn->position.m128_f32[0];
		spawnheader.position[1] = spawn->position.m128_f32[1];	//Convert from Vector to float3
		spawnheader.position[2] = spawn->position.m128_f32[2];

		spawnheader.rotation[0] = spawn->rotation.m128_f32[0];
		spawnheader.rotation[1] = spawn->rotation.m128_f32[1];	//Convert from Vector to float3
		spawnheader.rotation[2] = spawn->rotation.m128_f32[2];

		memcpy(dataPtr + sizeof(LevelData::SpawnHeader)* i, (char*)&spawnheader,sizeof(LevelData::SpawnHeader));

	}
	return LevelData::LevelStatus::L_OK;
}

LevelData::LevelStatus LevelHandler::LoadEntities(LevelData::EntityHeader* dataPtr, size_t numEntities)
{
	for (size_t i = 0; i < numEntities; i++)
	{
		m_currentLevel.AddModelEntityFromLevelFile(dataPtr[i].modelID,
			dataPtr[i].EntityID,
			DirectX::XMVectorSet(dataPtr[i].position[0], dataPtr[i].position[1], dataPtr[i].position[2], 0.0),
			DirectX::XMVectorSet(dataPtr[i].rotation[0], dataPtr[i].rotation[1], dataPtr[i].rotation[2], 0.0));

	}

	return LevelData::LevelStatus::L_OK;
}
<commit_msg>UPDATE: Resetting global ids before loading new level<commit_after>#include "LevelHandler.h"

LevelHandler::LevelHandler()
{
}

LevelHandler::~LevelHandler()
{
}

LevelHandler * LevelHandler::GetInstance()
{
	static LevelHandler instance;
	return &instance;
}

LevelData::LevelStatus LevelHandler::ExportLevelFile()
{
	std::string path = GetFilePathAndName(Operation::SAVE);
	if (path == "")
	{
		return LevelData::LevelStatus::L_FILE_SAVE_CANCELLED;
	}

	std::fstream file;
	file.open(path, std::fstream::out | std::fstream::binary);
	LevelData::MainLevelHeader header = this->GetMainHeader();				//Get the main header for the file
	char* data = (char*)&header;

	file.write(data, sizeof(LevelData::MainLevelHeader));					 //Write the main header first

	//Resource data
	size_t resSize = sizeof(LevelData::ResourceHeader)* header.resAmount;    //size of resource data
	char* resData  = new char[resSize];										 //Allocate for resource data
	GetResourceData(resData);												 //Get resource data
	file.write(resData, resSize);											 //Write resource data to file

	//Spawn Points
	LevelData::SpawnHeader spawns[2];
	GetSpawnData((char*)spawns);
	file.write((char*)spawns, sizeof(LevelData::SpawnHeader) * 2);

	//Model Entities
	size_t modelSize = sizeof(LevelData::EntityHeader) * header.entityAmount;
	char* modelData  = new char[modelSize];					//Allocate for modelEntity data
	GetEntityData(modelData);								//Get modelEntity data
	file.write(modelData, modelSize);						//Write all modelEntities

	file.close();

	delete resData;
	delete modelData;//Cleanup

	QFileInfo info(QString::fromStdString(path));
	m_currentLevel.SetName(info.baseName().toStdString()); //Set the new name to the level
	return LevelData::LevelStatus::L_OK;
}

LevelData::LevelStatus LevelHandler::ImportLevelFile()
{

	//Let the user pick a path and file name.
	std::string path = GetFilePathAndName(Operation::LOAD);
	if (path == "")
	{
		return LevelData::LevelStatus::L_FILE_SAVE_CANCELLED;
	}
	NewLevel();		//Empty the current level object

	std::fstream file;
	file.open(path, std::fstream::in | std::fstream::binary);

	LevelData::MainLevelHeader header;
	file.read((char*)&header, sizeof(LevelData::MainLevelHeader));				 //Read file header

	//Resource data
	size_t resSize = sizeof(LevelData::ResourceHeader)* header.resAmount;		  //size of resource data
	file.seekg(resSize, std::ios_base::cur);									  //Skip the resource data (only used by the game engine)

	//Spawn Points
	LevelData::SpawnHeader spawns[2];
	file.read((char*)spawns, sizeof(LevelData::SpawnHeader) * 2);
	m_currentLevel.SetSpawnPoint(spawns[0], 0);
	m_currentLevel.SetSpawnPoint(spawns[1], 1);

	//Model Entities
	size_t modelSize = sizeof(LevelData::EntityHeader) * header.entityAmount;	  //memsize
	char* modelData = new char[modelSize];										  //allocate for the entities
	file.read(modelData, modelSize);											  //Bulk read all the entity data
	this->LoadEntities((LevelData::EntityHeader*)modelData, header.entityAmount); //Load them into the level object

	file.close();
	delete modelData; //Cleanup
	QFileInfo info(QString::fromStdString(path));
	m_currentLevel.SetName(info.baseName().toStdString()); //Set the  name to the level

	return LevelData::LevelStatus::L_OK;
}

LevelData::LevelStatus LevelHandler::NewLevel()
{

	this->m_currentLevel.Destroy();
	return LevelData::LevelStatus::L_OK;
}

std::string LevelHandler::GetFilePathAndName(Operation flag)
{
	if (flag == Operation::SAVE)
	{
		QFileDialog dlg(NULL, "Save file");
		dlg.setAcceptMode(QFileDialog::AcceptSave);
		QString fullpath = filePath;
		fullpath.append(m_currentLevel.GetName()->c_str());
		fullpath.append(".level");

		dlg.setDirectory(fullpath);
		dlg.setNameFilter("Levels (*.level)");
		if (dlg.exec())
		{

			return dlg.selectedFiles().at(0).toStdString();
		}
		else
		{
			return "";
		}
	}

	else
	{
		QFileDialog dlg(NULL, "Load file");
		dlg.setAcceptMode(QFileDialog::AcceptOpen);
		//QFileDialog::ReadOnly

		dlg.setDirectory(filePath);
		dlg.setNameFilter("Levels (*.level)");
		if (dlg.exec())
		{
			return dlg.selectedFiles().at(0).toStdString(); //Return file path as string
		}
		else
		{
			return "";
		}

	}

}

LevelData::MainLevelHeader LevelHandler::GetMainHeader()
{
	LevelData::MainLevelHeader header;

	header.resAmount	     = m_currentLevel.GetUniqueModels()->size();
	header.entityAmount      = m_currentLevel.GetNumEntities();
	header.lightAmount       = m_currentLevel.GetNumLights();
	header.AiComponentAmount = (unsigned int) m_currentLevel.GetAiHandler()->GetAllPathComponents()->size();
	return header;
}

LevelData::LevelStatus LevelHandler::GetEntityData(char * dataPtr)
{
	unsigned int offset = 0;
	std::unordered_map<unsigned int, std::vector<Container>> *  map = m_currentLevel.GetModelEntities();
	for (auto iterator = map->begin(); iterator != map->end(); ++iterator)
	{
		std::vector<Container> * entityContainer = &iterator->second;

		for (size_t i = 0; i < entityContainer->size(); i++)
		{
			LevelData::EntityHeader entity;

			entity.EntityID = entityContainer->at(i).internalID;
			entity.modelID  = entityContainer->at(i).component.modelID;

			entity.position[0] = entityContainer->at(i).position.m128_f32[0];
			entity.position[1] = entityContainer->at(i).position.m128_f32[1];	//Convert from Vector to float3
			entity.position[2] = entityContainer->at(i).position.m128_f32[2];

			entity.rotation[0] = entityContainer->at(i).rotation.m128_f32[0];
			entity.rotation[1] = entityContainer->at(i).rotation.m128_f32[1];	//Convert from Vector to float3
			entity.rotation[2] = entityContainer->at(i).rotation.m128_f32[2];

			entity.isStatic	   = entityContainer->at(i).isStatic;
			memcpy(dataPtr + offset, (char*)&entity, sizeof(LevelData::EntityHeader));
			offset += sizeof(LevelData::EntityHeader);

		}

	}
	return LevelData::LevelStatus::L_OK;
}

LevelData::LevelStatus LevelHandler::GetResourceData(char * dataPtr)
{
	unsigned int offset = 0;
	for (size_t i = 0; i < this->m_currentLevel.GetUniqueModels()->size(); i++)
	{
		LevelData::ResourceHeader res;
		res.id = this->m_currentLevel.GetUniqueModels()->at(i);
		res.resourceType = Resources::ResourceType::RES_MODEL;
		memcpy(dataPtr + offset, (char*)&res, sizeof(LevelData::ResourceHeader));
		offset += sizeof(LevelData::ResourceHeader);
	}

	return LevelData::LevelStatus::L_OK;
}

LevelData::LevelStatus LevelHandler::GetSpawnData(char * dataPtr)
{

	for (size_t i = 0; i < 2; i++)
	{
		Container* spawn = m_currentLevel.GetSpawnPoint(i);
		LevelData::SpawnHeader spawnheader;

		spawnheader.position[0] = spawn->position.m128_f32[0];
		spawnheader.position[1] = spawn->position.m128_f32[1];	//Convert from Vector to float3
		spawnheader.position[2] = spawn->position.m128_f32[2];

		spawnheader.rotation[0] = spawn->rotation.m128_f32[0];
		spawnheader.rotation[1] = spawn->rotation.m128_f32[1];	//Convert from Vector to float3
		spawnheader.rotation[2] = spawn->rotation.m128_f32[2];

		memcpy(dataPtr + sizeof(LevelData::SpawnHeader)* i, (char*)&spawnheader,sizeof(LevelData::SpawnHeader));

	}
	return LevelData::LevelStatus::L_OK;
}

LevelData::LevelStatus LevelHandler::LoadEntities(LevelData::EntityHeader* dataPtr, size_t numEntities)
{
	GlobalIDHandler::GetInstance()->ResetIDs();
	for (size_t i = 0; i < numEntities; i++)
	{
		m_currentLevel.AddModelEntityFromLevelFile(dataPtr[i].modelID,
			dataPtr[i].EntityID,
			DirectX::XMVectorSet(dataPtr[i].position[0], dataPtr[i].position[1], dataPtr[i].position[2], 0.0),
			DirectX::XMVectorSet(dataPtr[i].rotation[0], dataPtr[i].rotation[1], dataPtr[i].rotation[2], 0.0));

	}

	return LevelData::LevelStatus::L_OK;
}
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  $RCSfile: formsimp.cxx,v $
 *
 *  $Revision: 1.3 $
 *
 *  last change: $Author: thb $ $Date: 2001-07-25 11:45:09 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (the "License"); You may not use this file
 *  except in compliance with the License. You may obtain a copy of the
 *  License at http://www.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/

#ifndef _COM_SUN_STAR_XML_SAX_XATTRIBUTELIST_HPP_
#include <com/sun/star/xml/sax/XAttributeList.hpp>
#endif

#ifndef _XMLOFF_XMLIMP_HXX
#include "xmlimp.hxx"
#endif

#ifndef _XMLOFF_XMLNMSPE_HXX
#include "xmlnmspe.hxx"
#endif

#ifndef _XMLOFF_NMSPMAP_HXX
#include "nmspmap.hxx"
#endif

#ifndef _XMLOFF_ANIMIMP_HXX
#include "formsimp.hxx"
#endif

using namespace ::rtl;

TYPEINIT1( XMLFormsContext, SvXMLImportContext );

XMLFormsContext::XMLFormsContext( SvXMLImport& rImport, sal_uInt16 nPrfx, const rtl::OUString& rLocalName )
: SvXMLImportContext(rImport, nPrfx, rLocalName)
{
}

XMLFormsContext::~XMLFormsContext()
{
}

SvXMLImportContext * XMLFormsContext::CreateChildContext( USHORT nPrefix, const ::rtl::OUString& rLocalName,
        const com::sun::star::uno::Reference< com::sun::star::xml::sax::XAttributeList>& xAttrList )
{
    return GetImport().GetFormImport()->createContext( nPrefix, rLocalName, xAttrList );
}
<commit_msg>INTEGRATION: CWS ooo19126 (1.3.636); FILE MERGED 2005/09/05 14:38:59 rt 1.3.636.1: #i54170# Change license header: remove SISSL<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: formsimp.cxx,v $
 *
 *  $Revision: 1.4 $
 *
 *  last change: $Author: rt $ $Date: 2005-09-09 14:11:01 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

#ifndef _COM_SUN_STAR_XML_SAX_XATTRIBUTELIST_HPP_
#include <com/sun/star/xml/sax/XAttributeList.hpp>
#endif

#ifndef _XMLOFF_XMLIMP_HXX
#include "xmlimp.hxx"
#endif

#ifndef _XMLOFF_XMLNMSPE_HXX
#include "xmlnmspe.hxx"
#endif

#ifndef _XMLOFF_NMSPMAP_HXX
#include "nmspmap.hxx"
#endif

#ifndef _XMLOFF_ANIMIMP_HXX
#include "formsimp.hxx"
#endif

using namespace ::rtl;

TYPEINIT1( XMLFormsContext, SvXMLImportContext );

XMLFormsContext::XMLFormsContext( SvXMLImport& rImport, sal_uInt16 nPrfx, const rtl::OUString& rLocalName )
: SvXMLImportContext(rImport, nPrfx, rLocalName)
{
}

XMLFormsContext::~XMLFormsContext()
{
}

SvXMLImportContext * XMLFormsContext::CreateChildContext( USHORT nPrefix, const ::rtl::OUString& rLocalName,
        const com::sun::star::uno::Reference< com::sun::star::xml::sax::XAttributeList>& xAttrList )
{
    return GetImport().GetFormImport()->createContext( nPrefix, rLocalName, xAttrList );
}
<|endoftext|>


<commit_before>// Each task is composed of a computing unit, which performs the desired
// computation, and the arguments provided by the user. This file defines how
// the computing units are created.
//
// Each computing unit is identified by an id that should be unique, so that
// the class used to compute can be identified. Currently the id is given by the
// name provided by to the constructor. The class BaseComputingUnit is used only
// to provide abstract pointers to units and thus should NEVER be used directly.
//
// To create a new computing unit, inherit from ComputingUnit<T> like this:
// class MyUnit: public ComputingUnit<MyUnit>
// and provide the following inside the class:
// 1) a constructor without arguments must be provided;
// 2) the constructor must call ComputingUnit<MyUnit> with the desired unit's
// name as argument;
// 3) a const method operator() that performs the computation desired;
// 4) if the object has any internal parameters, they user must create the
// method serialize.
//
// Caveats:
// 1) Only the return of operator() is considered as the result, so any changes
// to the argument are ignored;
// 2) All arguments and the return of operator() must be serializable through
// boost;
// 3) operator() must be declared as const, to ensure no modifications are
// performed.
//
// Besides these requirements, the user has control over the following options:
// 1) whether the object must run on the master node, chosen through the method
// "run_locally()". This should be used in case there is some restriction, like
// file requirements or the operator() method is so fast that the communication
// overhead isn't worth. The unit is allowed to run anywhere by default;
// 2) whether the result should be saved to disk, through the method
// "should_save()". For very simple units, it may not be necessary or even
// desidered to save the result of the computation. The default is to save.
//
// If an unit doesn't save its result, it's called again each time its result is
// required. Therefore, an unit that must run locally must also save its result,
// as other nodes wouldn't be able to run it or load its result.
//
// For an example of how to implement an unit, check the IdentityComputingUnit
// below.

#ifndef __TASK_DISTRIBUTION__COMPUTING_UNIT_HPP__
#define __TASK_DISTRIBUTION__COMPUTING_UNIT_HPP__

#include "function_traits.hpp"
#include "object_archive.hpp"
#include "sequence.hpp"

#include <tuple>
#include <type_traits>
#include <unordered_map>

#include "computing_unit_manager.hpp"
#include "key.hpp"
#include "task_entry.hpp"

namespace TaskDistribution {
  // Abstract class to allow us to have pointers to units. Shouldn't be used
  // directly!
  class BaseComputingUnit {
    public:
      // Must the object be called on the master node? Defaults to false.
      virtual bool run_locally() const {
        return false;
      }

      // Should the computing results be saved? Defaults to true.
      virtual bool should_save() const {
        return true;
      }

      // Static method to fetch the correct kind of unit for an id. Returns NULL
      // if not found.
      static BaseComputingUnit const* get_by_id(std::string const& id);

      // Static method to fetch the correct kind of unit for a key. Returns NULL
      // if not found.
      static BaseComputingUnit const* get_by_key(Key const& key);

      // Binds a given id with a key. Multiple keys may be bound to the same id.
      // Returns true if the id was found.
      static bool bind_key(std::string const& id, Key const& key);

      // Gets the id associated with this kind of unit.
      std::string const& get_id() const {
        return *id_;
      }

      // Provides an invalid unit id.
      static std::string get_invalid_id() {
        return "";
      }

      // Callables need to be serializable. The default behavior is to transmit
      // nothing and may be overloaded.
      template<class Archive>
      void serialize(Archive& ar, const unsigned int version) { }

      // Loads the computing unit and arguments and stores the result in the
      // archive. Assumes every Key provided is valid.
      virtual void execute(ObjectArchive<Key>& archive,
          TaskEntry const& task, ComputingUnitManager& manager) const = 0;

    protected:
      // Expands the tuple and calls the functor
      template <class F, class Tuple, size_t... S>
      static typename CompileUtils::function_traits<F>::return_type
      apply(F&& f, Tuple&& args, CompileUtils::sequence<S...>) {
        return std::forward<F>(f)(std::get<S>(std::forward<Tuple>(args))...);
      }

      // Name of the computing unit given at construction
      std::string const* id_;

      // Map between ids and units.
      static std::unordered_map<std::string,BaseComputingUnit const*> id_map_;
      // Map between keys and units.
      static std::unordered_map<Key,BaseComputingUnit const*> key_map_;
  };

  // Class that should be inherited by the user's units. For an example on how
  // to do this, check the top of the file or the IdentityComputingUnit example.
  // Each kind of ComputingUnit used must be instantiated at least once and may
  // be destroyed before running the tasks.
  template <class T>
  class ComputingUnit: public BaseComputingUnit {
    public:
      // Registers the unit by placing a new copy into the units' map.
      explicit ComputingUnit(std::string const& name);

      virtual void execute(ObjectArchive<Key>& archive,
          TaskEntry const& task, ComputingUnitManager& manager) const;

    private:
      // Internal constructor to avoid deadlock during unit register.
      ComputingUnit() { }
  };

  // Example ComputingUnit that just returns its argument. Check that it
  // satisfies all the requirements for a valid unit.
  template <class T>
  class IdentityComputingUnit: public ComputingUnit<IdentityComputingUnit<T>> {
    public:
      IdentityComputingUnit():
        ComputingUnit<IdentityComputingUnit<T>>("identity") { }

      virtual bool run_locally() const {
        return false;
      }

      virtual bool should_save() const {
        return false;
      }

      T operator()(T const& arg) const {
        return arg;
      }
  };
};

#include "computing_unit_impl.hpp"

#endif
<commit_msg>Removed identity computing unit.<commit_after>// Each task is composed of a computing unit, which performs the desired
// computation, and the arguments provided by the user. This file defines how
// the computing units are created.
//
// Each computing unit is identified by an id that should be unique, so that
// the class used to compute can be identified. Currently the id is given by the
// name provided by to the constructor. The class BaseComputingUnit is used only
// to provide abstract pointers to units and thus should NEVER be used directly.
//
// To create a new computing unit, inherit from ComputingUnit<T> like this:
// class MyUnit: public ComputingUnit<MyUnit>
// and provide the following inside the class:
// 1) a constructor without arguments must be provided;
// 2) the constructor must call ComputingUnit<MyUnit> with the desired unit's
// name as argument;
// 3) a const method operator() that performs the computation desired;
// 4) if the object has any internal parameters, they user must create the
// method serialize.
//
// Caveats:
// 1) Only the return of operator() is considered as the result, so any changes
// to the argument are ignored;
// 2) All arguments and the return of operator() must be serializable through
// boost;
// 3) operator() must be declared as const, to ensure no modifications are
// performed.
//
// Besides these requirements, the user has control over the following options:
// 1) whether the object must run on the master node, chosen through the method
// "run_locally()". This should be used in case there is some restriction, like
// file requirements or the operator() method is so fast that the communication
// overhead isn't worth. The unit is allowed to run anywhere by default;
// 2) whether the result should be saved to disk, through the method
// "should_save()". For very simple units, it may not be necessary or even
// desidered to save the result of the computation. The default is to save.
//
// If an unit doesn't save its result, it's called again each time its result is
// required. Therefore, an unit that must run locally must also save its result,
// as other nodes wouldn't be able to run it or load its result.
//
// For an example of how to implement an unit, check the IdentityComputingUnit
// below.

#ifndef __TASK_DISTRIBUTION__COMPUTING_UNIT_HPP__
#define __TASK_DISTRIBUTION__COMPUTING_UNIT_HPP__

#include "function_traits.hpp"
#include "object_archive.hpp"
#include "sequence.hpp"

#include <tuple>
#include <type_traits>
#include <unordered_map>

#include "computing_unit_manager.hpp"
#include "key.hpp"
#include "task_entry.hpp"

namespace TaskDistribution {
  // Abstract class to allow us to have pointers to units. Shouldn't be used
  // directly!
  class BaseComputingUnit {
    public:
      // Must the object be called on the master node? Defaults to false.
      virtual bool run_locally() const {
        return false;
      }

      // Should the computing results be saved? Defaults to true.
      virtual bool should_save() const {
        return true;
      }

      // Static method to fetch the correct kind of unit for an id. Returns NULL
      // if not found.
      static BaseComputingUnit const* get_by_id(std::string const& id);

      // Static method to fetch the correct kind of unit for a key. Returns NULL
      // if not found.
      static BaseComputingUnit const* get_by_key(Key const& key);

      // Binds a given id with a key. Multiple keys may be bound to the same id.
      // Returns true if the id was found.
      static bool bind_key(std::string const& id, Key const& key);

      // Gets the id associated with this kind of unit.
      std::string const& get_id() const {
        return *id_;
      }

      // Provides an invalid unit id.
      static std::string get_invalid_id() {
        return "";
      }

      // Callables need to be serializable. The default behavior is to transmit
      // nothing and may be overloaded.
      template<class Archive>
      void serialize(Archive& ar, const unsigned int version) { }

      // Loads the computing unit and arguments and stores the result in the
      // archive. Assumes every Key provided is valid.
      virtual void execute(ObjectArchive<Key>& archive,
          TaskEntry const& task, ComputingUnitManager& manager) const = 0;

    protected:
      // Expands the tuple and calls the functor
      template <class F, class Tuple, size_t... S>
      static typename CompileUtils::function_traits<F>::return_type
      apply(F&& f, Tuple&& args, CompileUtils::sequence<S...>) {
        return std::forward<F>(f)(std::get<S>(std::forward<Tuple>(args))...);
      }

      // Name of the computing unit given at construction
      std::string const* id_;

      // Map between ids and units.
      static std::unordered_map<std::string,BaseComputingUnit const*> id_map_;
      // Map between keys and units.
      static std::unordered_map<Key,BaseComputingUnit const*> key_map_;
  };

  // Class that should be inherited by the user's units. For an example on how
  // to do this, check the top of the file or the IdentityComputingUnit example.
  // Each kind of ComputingUnit used must be instantiated at least once and may
  // be destroyed before running the tasks.
  template <class T>
  class ComputingUnit: public BaseComputingUnit {
    public:
      // Registers the unit by placing a new copy into the units' map.
      explicit ComputingUnit(std::string const& name);

      virtual void execute(ObjectArchive<Key>& archive,
          TaskEntry const& task, ComputingUnitManager& manager) const;

    private:
      // Internal constructor to avoid deadlock during unit register.
      ComputingUnit() { }
  };
};

#include "computing_unit_impl.hpp"

#endif
<|endoftext|>


<commit_before>/*
 * Copyright(c) Sophist Solutions, Inc. 1990-2021.  All rights reserved
 */
#include "Stroika/Frameworks/StroikaPreComp.h"

#include <iostream>

#include "Stroika/Foundation/Characters/String2Int.h"
#include "Stroika/Foundation/Characters/ToString.h"
#include "Stroika/Foundation/Common/Property.h"
#include "Stroika/Foundation/DataExchange/InternetMediaTypeRegistry.h"
#include "Stroika/Foundation/Execution/CommandLine.h"
#include "Stroika/Foundation/Execution/Module.h"
#include "Stroika/Foundation/Execution/SignalHandlers.h"
#include "Stroika/Foundation/Execution/TimeOutException.h"
#include "Stroika/Foundation/Execution/WaitableEvent.h"
#include "Stroika/Foundation/IO/Network/HTTP/Exception.h"
#include "Stroika/Foundation/IO/Network/HTTP/Headers.h"
#include "Stroika/Foundation/IO/Network/HTTP/Methods.h"
#include "Stroika/Foundation/Streams/TextReader.h"
#include "Stroika/Foundation/Time/Duration.h"

#include "Stroika/Frameworks/WebServer/ConnectionManager.h"
#include "Stroika/Frameworks/WebServer/FileSystemRequestHandler.h"
#include "Stroika/Frameworks/WebServer/Router.h"

#include "AppVersion.h"

using namespace std;

using namespace Stroika::Foundation;
using namespace Stroika::Foundation::Characters;
using namespace Stroika::Foundation::IO::Network;
using namespace Stroika::Frameworks::WebServer;

using Characters::String;
using Common::ConstantProperty;
using Memory::BLOB;

using Stroika::Frameworks::WebServer::FileSystemRequestHandler;
using Stroika::Frameworks::WebServer::Request;
using Stroika::Frameworks::WebServer::Response;
using Time::Duration;

namespace {

    /**
     *  You don't need to specify any of this, but it maybe helpful to specify caching control policies to
     *  get the best web-server performance.
     */
    const ConstantProperty<FileSystemRequestHandler::Options> kFileSystemRouterOptions_{[] () {
        Sequence<pair<RegularExpression, CacheControl>> cacheControlSettings_
        {
#if __cpp_designated_initializers
            {
                RegularExpression{L".*\\.gif", CompareOptions::eCaseInsensitive}, CacheControl { .fMaxAge = Duration{24h}.As<int32_t> () }
            }
#else
            {
                RegularExpression{L".*\\.gif", CompareOptions::eCaseInsensitive}, CacheControl { nullopt, Duration{24h}.As<int32_t> () }
            }
#endif
        };
        return FileSystemRequestHandler::Options{L"Files"_k, Sequence<String>{L"index.html"_k}, nullopt, cacheControlSettings_};
    }};

    /**
     *  You don't need to specify any of this, but its a good idea to propery identify your application.
     */
    const ConstantProperty<Headers> kDefaultResponseHeaders_{[] () {
        Headers h;
        h.server = L"Stroika-Sample-WebServer/"_k + AppVersion::kVersion.AsMajorMinorString ();
        return h;
    }};

    /*
     *  It's often helpful to structure together, routes, special interceptors, with your connection manager, to package up
     *  all the logic /options for HTTP interface.
     *
     *  This particular organization also makes it easy to save instance variables with the webserver (like a pointer to a handler)
     *  and accesss them from the Route handler functions.
     */
    struct MyWebServer_ {

        /**
         *  Routes specify the 'handlers' for the various web urls your webserver will support.
         */
        const Sequence<Route> kRoutes_;

        /**
         *  The connectionMgr specifies parameters that govenern the procedural behavior of your webserver.
         *  For example, caching settings go here, thread pool settings, network bindings, and so on.
         */
        ConnectionManager fConnectionMgr_;

        MyWebServer_ (uint16_t portNumber)
            // clang-format off
            : kRoutes_{
            Route{L""_RegEx, DefaultPage_},
                Route{HTTP::MethodsRegEx::kPost, L"SetAppState"_RegEx, SetAppState_},
                Route{L"FRED"_RegEx, [] (Request*, Response* response) {
                    response->contentType = DataExchange::InternetMediaTypes::kText_PLAIN;
                    response->write (L"FRED");
                }},
                Route{L"Files/.*"_RegEx, FileSystemRequestHandler { Execution::GetEXEDir () / L"html", kFileSystemRouterOptions_ }}
            }
            , fConnectionMgr_ {
                SocketAddresses (InternetAddresses_Any (), portNumber),
                kRoutes_,
#if __cpp_designated_initializers
                ConnectionManager::Options { .fBindFlags = Socket::BindFlags{}, .fDefaultResponseHeaders = kDefaultResponseHeaders_ }}
#else
                ConnectionManager::Options { nullopt, nullopt, Socket::BindFlags{}, kDefaultResponseHeaders_ }}
#endif
        // clang-format on
        {
        }
        // Can declare arguments as Request*,Response*
        static void DefaultPage_ (Request*, Response* response)
        {
            //constexpr bool kUseTransferCoding_ = true;
            constexpr bool kUseTransferCoding_ = false;
            if (kUseTransferCoding_) {
                response->rwHeaders ().transferEncoding = HTTP::TransferEncoding::eChunked;
            }
            response->contentType = DataExchange::InternetMediaTypes::kHTML;
            response->writeln (L"");
            response->writeln (L"
Hi Mom
");
            response->writeln (L"
");
            response->writeln (L"Run the service (under the debugger if you wish)");
            response->writeln (L"
curl http://localhost:8080/ OR
");
            response->writeln (L"
curl http://localhost:8080/FRED OR      (to see error handling)
");
            response->writeln (L"
curl -H \"Content-Type: application/json\" -X POST -d '{\"AppState\":\"Start\"}' http://localhost:8080/SetAppState
");
            response->writeln (L"
curl http://localhost:8080/Files/index.html -v
");
            response->writeln (L"
");
            response->writeln (L"");
        }
        // Can declare arguments as Message* message
        static void SetAppState_ (Message* message)
        {
            message->rwResponse ().contentType = DataExchange::InternetMediaTypes::kHTML;
            String argsAsString                = Streams::TextReader::New (message->rwRequest ().GetBody ()).ReadAll ();
            message->rwResponse ().writeln (L"
Hi SetAppState (" + argsAsString.As<wstring> () + L")
");
        }
    };
}

int main (int argc, const char* argv[])
{
    Debug::TraceContextBumper                            ctx{Stroika_Foundation_Debug_OptionalizeTraceArgs (L"main", L"argv=%s", Characters::ToString (vector<const char*>{argv, argv + argc}).c_str ())};
    Execution::SignalHandlerRegistry::SafeSignalsManager safeSignals;
#if qPlatform_POSIX
    Execution::SignalHandlerRegistry::Get ().SetSignalHandlers (SIGPIPE, Execution::SignalHandlerRegistry::kIGNORED);
#endif
    uint16_t                  portNumber = 8080;
    Time::DurationSecondsType quitAfter  = numeric_limits<Time::DurationSecondsType>::max ();

    Sequence<String> args = Execution::ParseCommandLine (argc, argv);
    for (auto argi = args.begin (); argi != args.end (); ++argi) {
        if (Execution::MatchesCommandLineArgument (*argi, L"port")) {
            ++argi;
            if (argi != args.end ()) {
                portNumber = Characters::String2Int<uint16_t> (*argi);
            }
            else {
                cerr << "Expected arg to -port" << endl;
                return EXIT_FAILURE;
            }
        }
        else if (Execution::MatchesCommandLineArgument (*argi, L"quit-after")) {
            ++argi;
            if (argi != args.end ()) {
                quitAfter = Characters::FloatConversion::ToFloat<Time::DurationSecondsType> (*argi);
            }
            else {
                cerr << "Expected arg to -quit-after" << endl;
                return EXIT_FAILURE;
            }
        }
    }

    try {
        MyWebServer_ myWebServer{portNumber};        // listen and dispatch while this object exists
        Execution::WaitableEvent{}.Wait (quitAfter); // wait forever - til user hits ctrl-c
    }
    catch (const Execution::TimeOutException&) {
        cerr << "Timed out - so - exiting..." << endl;
        return EXIT_SUCCESS;
    }
    catch (...) {
        cerr << "Error encountered: " << Characters::ToString (current_exception ()).AsNarrowSDKString () << " - terminating..." << endl;
        return EXIT_FAILURE;
    }
    return EXIT_SUCCESS;
}
<commit_msg>cosmetic<commit_after>/*
 * Copyright(c) Sophist Solutions, Inc. 1990-2021.  All rights reserved
 */
#include "Stroika/Frameworks/StroikaPreComp.h"

#include <iostream>

#include "Stroika/Foundation/Characters/String2Int.h"
#include "Stroika/Foundation/Characters/ToString.h"
#include "Stroika/Foundation/Common/Property.h"
#include "Stroika/Foundation/DataExchange/InternetMediaTypeRegistry.h"
#include "Stroika/Foundation/Execution/CommandLine.h"
#include "Stroika/Foundation/Execution/Module.h"
#include "Stroika/Foundation/Execution/SignalHandlers.h"
#include "Stroika/Foundation/Execution/TimeOutException.h"
#include "Stroika/Foundation/Execution/WaitableEvent.h"
#include "Stroika/Foundation/IO/Network/HTTP/Exception.h"
#include "Stroika/Foundation/IO/Network/HTTP/Headers.h"
#include "Stroika/Foundation/IO/Network/HTTP/Methods.h"
#include "Stroika/Foundation/Streams/TextReader.h"
#include "Stroika/Foundation/Time/Duration.h"

#include "Stroika/Frameworks/WebServer/ConnectionManager.h"
#include "Stroika/Frameworks/WebServer/FileSystemRequestHandler.h"
#include "Stroika/Frameworks/WebServer/Router.h"

#include "AppVersion.h"

using namespace std;

using namespace Stroika::Foundation;
using namespace Stroika::Foundation::Characters;
using namespace Stroika::Foundation::IO::Network;
using namespace Stroika::Frameworks::WebServer;

using Characters::String;
using Common::ConstantProperty;
using Memory::BLOB;

using Stroika::Frameworks::WebServer::FileSystemRequestHandler;
using Stroika::Frameworks::WebServer::Request;
using Stroika::Frameworks::WebServer::Response;
using Time::Duration;

namespace {

    /**
     *  You don't need to specify any of this, but it maybe helpful to specify caching control policies to
     *  get the best web-server performance.
     */
    const ConstantProperty<FileSystemRequestHandler::Options> kFileSystemRouterOptions_{[] () {
        // clang-format off
        Sequence<pair<RegularExpression, CacheControl>> cacheControlSettings_ {
#if __cpp_designated_initializers
            { RegularExpression{L".*\\.gif", CompareOptions::eCaseInsensitive}, CacheControl { .fMaxAge = Duration{24h}.As<int32_t> () } }
#else
            { RegularExpression{L".*\\.gif", CompareOptions::eCaseInsensitive}, CacheControl { nullopt, Duration{24h}.As<int32_t> () } }
#endif
        };
        // clang-format on
        return FileSystemRequestHandler::Options{L"Files"_k, Sequence<String>{L"index.html"_k}, nullopt, cacheControlSettings_};
    }};

    /**
     *  You don't need to specify any of this, but its a good idea to propery identify your application.
     */
    const ConstantProperty<Headers> kDefaultResponseHeaders_{[] () {
        Headers h;
        h.server = L"Stroika-Sample-WebServer/"_k + AppVersion::kVersion.AsMajorMinorString ();
        return h;
    }};

    /*
     *  It's often helpful to structure together, routes, special interceptors, with your connection manager, to package up
     *  all the logic /options for HTTP interface.
     *
     *  This particular organization also makes it easy to save instance variables with the webserver (like a pointer to a handler)
     *  and accesss them from the Route handler functions.
     */
    struct MyWebServer_ {

        /**
         *  Routes specify the 'handlers' for the various web urls your webserver will support.
         */
        const Sequence<Route> kRoutes_;

        /**
         *  The connectionMgr specifies parameters that govenern the procedural behavior of your webserver.
         *  For example, caching settings go here, thread pool settings, network bindings, and so on.
         */
        ConnectionManager fConnectionMgr_;

        MyWebServer_ (uint16_t portNumber)
            // clang-format off
            : kRoutes_{
                Route{L""_RegEx, DefaultPage_},
                Route{HTTP::MethodsRegEx::kPost, L"SetAppState"_RegEx, SetAppState_},
                Route{L"FRED"_RegEx, [] (Request*, Response* response) {
                    response->contentType = DataExchange::InternetMediaTypes::kText_PLAIN;
                    response->write (L"FRED");
                }},
                Route{L"Files/.*"_RegEx, FileSystemRequestHandler { Execution::GetEXEDir () / L"html", kFileSystemRouterOptions_ }}
            }
            , fConnectionMgr_ {
                SocketAddresses (InternetAddresses_Any (), portNumber),
                kRoutes_,
#if __cpp_designated_initializers
                ConnectionManager::Options { .fBindFlags = Socket::BindFlags{}, .fDefaultResponseHeaders = kDefaultResponseHeaders_ }}
#else
                ConnectionManager::Options { nullopt, nullopt, Socket::BindFlags{}, kDefaultResponseHeaders_ }}
#endif
            // clang-format on
        {
        }
        // Can declare arguments as Request*,Response*
        static void DefaultPage_ (Request*, Response* response)
        {
            //constexpr bool kUseTransferCoding_ = true;
            constexpr bool kUseTransferCoding_ = false;
            if (kUseTransferCoding_) {
                response->rwHeaders ().transferEncoding = HTTP::TransferEncoding::eChunked;
            }
            response->contentType = DataExchange::InternetMediaTypes::kHTML;
            response->writeln (L"");
            response->writeln (L"
Hi Mom
");
            response->writeln (L"
");
            response->writeln (L"Run the service (under the debugger if you wish)");
            response->writeln (L"
curl http://localhost:8080/ OR
");
            response->writeln (L"
curl http://localhost:8080/FRED OR      (to see error handling)
");
            response->writeln (L"
curl -H \"Content-Type: application/json\" -X POST -d '{\"AppState\":\"Start\"}' http://localhost:8080/SetAppState
");
            response->writeln (L"
curl http://localhost:8080/Files/index.html -v
");
            response->writeln (L"
");
            response->writeln (L"");
        }
        // Can declare arguments as Message* message
        static void SetAppState_ (Message* message)
        {
            message->rwResponse ().contentType = DataExchange::InternetMediaTypes::kHTML;
            String argsAsString                = Streams::TextReader::New (message->rwRequest ().GetBody ()).ReadAll ();
            message->rwResponse ().writeln (L"
Hi SetAppState (" + argsAsString.As<wstring> () + L")
");
        }
    };
}

int main (int argc, const char* argv[])
{
    Debug::TraceContextBumper                            ctx{Stroika_Foundation_Debug_OptionalizeTraceArgs (L"main", L"argv=%s", Characters::ToString (vector<const char*>{argv, argv + argc}).c_str ())};
    Execution::SignalHandlerRegistry::SafeSignalsManager safeSignals;
#if qPlatform_POSIX
    Execution::SignalHandlerRegistry::Get ().SetSignalHandlers (SIGPIPE, Execution::SignalHandlerRegistry::kIGNORED);
#endif
    uint16_t                  portNumber = 8080;
    Time::DurationSecondsType quitAfter  = numeric_limits<Time::DurationSecondsType>::max ();

    Sequence<String> args = Execution::ParseCommandLine (argc, argv);
    for (auto argi = args.begin (); argi != args.end (); ++argi) {
        if (Execution::MatchesCommandLineArgument (*argi, L"port")) {
            ++argi;
            if (argi != args.end ()) {
                portNumber = Characters::String2Int<uint16_t> (*argi);
            }
            else {
                cerr << "Expected arg to -port" << endl;
                return EXIT_FAILURE;
            }
        }
        else if (Execution::MatchesCommandLineArgument (*argi, L"quit-after")) {
            ++argi;
            if (argi != args.end ()) {
                quitAfter = Characters::FloatConversion::ToFloat<Time::DurationSecondsType> (*argi);
            }
            else {
                cerr << "Expected arg to -quit-after" << endl;
                return EXIT_FAILURE;
            }
        }
    }

    try {
        MyWebServer_ myWebServer{portNumber};        // listen and dispatch while this object exists
        Execution::WaitableEvent{}.Wait (quitAfter); // wait forever - til user hits ctrl-c
    }
    catch (const Execution::TimeOutException&) {
        cerr << "Timed out - so - exiting..." << endl;
        return EXIT_SUCCESS;
    }
    catch (...) {
        cerr << "Error encountered: " << Characters::ToString (current_exception ()).AsNarrowSDKString () << " - terminating..." << endl;
        return EXIT_FAILURE;
    }
    return EXIT_SUCCESS;
}
<|endoftext|>


<commit_before>/*
 * DISTRHO Plugin Framework (DPF)
 * Copyright (C) 2012-2021 Filipe Coelho <falktx@falktx.com>
 *
 * Permission to use, copy, modify, and/or distribute this software for any purpose with
 * or without fee is hereby granted, provided that the above copyright notice and this
 * permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
 * TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
 * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
 * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

#ifndef DISTRHO_EXTERNAL_WINDOW_HPP_INCLUDED
#define DISTRHO_EXTERNAL_WINDOW_HPP_INCLUDED

#include "String.hpp"

#ifdef DISTRHO_OS_WINDOWS
# error Unsupported platform!
#else
# include <cerrno>
# include <signal.h>
# include <sys/wait.h>
# include <unistd.h>
#endif

START_NAMESPACE_DISTRHO

// -----------------------------------------------------------------------
// ExternalWindow class

/**
   External Window class.

   This is a standalone TopLevelWidget-compatible class, but without any real event handling.
   Being compatible with TopLevelWidget, it allows to be used as DPF UI target.

   It can be used to embed non-DPF things or to run a tool in a new process as the "UI".
 */
class ExternalWindow
{
    struct PrivateData;

public:
   /**
      Constructor.
    */
    explicit ExternalWindow()
       : pData() {}

   /**
      Constructor.
    */
    explicit ExternalWindow(const PrivateData& data)
       : pData(data) {}

   /**
      Destructor.
    */
    virtual ~ExternalWindow()
    {
        DISTRHO_SAFE_ASSERT(!pData.visible);
    }

   /* --------------------------------------------------------------------------------------------------------
    * ExternalWindow specific calls */

    virtual bool isRunning() const
    {
        if (ext.inUse)
            return ext.isRunning();

        return isVisible();
    }

    virtual bool isQuiting() const
    {
        if (ext.inUse)
            return ext.isQuiting;

        return !isVisible();
    }

    uintptr_t getTransientWindowId() const noexcept
    {
        return pData.transientWinId;
    }

    virtual void setTransientWindowId(uintptr_t winId)
    {
        if (pData.transientWinId == winId)
            return;
        pData.transientWinId = winId;
        transientWindowChanged(winId);
    }

    void close()
    {
        hide();

        if (ext.inUse)
            terminateAndWaitForExternalProcess();
    }

#if DISTRHO_PLUGIN_HAS_EMBED_UI
   /**
      Whether this Window is embed into another (usually not DGL-controlled) Window.
    */
    bool isEmbed() const noexcept
    {
        return pData.parentWindowHandle != 0;
    }

   /**
      Get the "native" window handle.
      This can be reimplemented in order to pass the child window to hosts that can use such informaton.

      Returned value type depends on the platform:
       - HaikuOS: This is a pointer to a `BView`.
       - MacOS: This is a pointer to an `NSView*`.
       - Windows: This is a `HWND`.
       - Everything else: This is an [X11] `Window`.
    */
    virtual uintptr_t getNativeWindowHandle() const noexcept
    {
        return 0;
    }

   /**
      Get the "native" window handle that this window should embed itself into.
      Returned value type depends on the platform:
       - HaikuOS: This is a pointer to a `BView`.
       - MacOS: This is a pointer to an `NSView*`.
       - Windows: This is a `HWND`.
       - Everything else: This is an [X11] `Window`.
    */
    uintptr_t getParentWindowHandle() const noexcept
    {
        return pData.parentWindowHandle;
    }
#endif

   /* --------------------------------------------------------------------------------------------------------
    * TopLevelWidget-like calls */

   /**
      Check if this window is visible.
      @see setVisible(bool)
    */
    bool isVisible() const noexcept
    {
        return pData.visible;
    }

   /**
      Set window visible (or not) according to @a visible.
      @see isVisible(), hide(), show()
    */
    virtual void setVisible(bool visible)
    {
        if (pData.visible == visible)
            return;
        pData.visible = visible;
        visibilityChanged(visible);
    }

   /**
      Show window.
      This is the same as calling setVisible(true).
      @see isVisible(), setVisible(bool)
    */
    void show()
    {
        setVisible(true);
    }

   /**
      Hide window.
      This is the same as calling setVisible(false).
      @see isVisible(), setVisible(bool)
    */
    void hide()
    {
        setVisible(false);
    }

   /**
      Get width.
    */
    uint getWidth() const noexcept
    {
        return pData.width;
    }

   /**
      Get height.
    */
    uint getHeight() const noexcept
    {
        return pData.height;
    }

   /**
      Set width.
    */
    void setWidth(uint width)
    {
        setSize(width, getHeight());
    }

   /**
      Set height.
    */
    void setHeight(uint height)
    {
        setSize(getWidth(), height);
    }

   /**
      Set size using @a width and @a height values.
    */
    virtual void setSize(uint width, uint height)
    {
        DISTRHO_SAFE_ASSERT_UINT2_RETURN(width > 1 && height > 1, width, height,);

        if (pData.width == width || pData.height == height)
            return;

        pData.width = width;
        pData.height = height;
        onResize(width, height);
    }

   /**
      Get the title of the window previously set with setTitle().
    */
    const char* getTitle() const noexcept
    {
        return pData.title;
    }

   /**
      Set the title of the window, typically displayed in the title bar or in window switchers.
    */
    virtual void setTitle(const char* title)
    {
        if (pData.title == title)
            return;
        pData.title = title;
        titleChanged(title);
    }

   /**
      Get the scale factor requested for this window.
      This is purely informational, and up to developers to choose what to do with it.

      If you do not want to deal with this yourself,
      consider using setGeometryConstraints() where you can specify to automatically scale the window contents.
      @see setGeometryConstraints
    */
    double getScaleFactor() const noexcept
    {
        return pData.scaleFactor;
    }

   /**
      Grab the keyboard input focus.
    */
    virtual void focus() {}

protected:
   /* --------------------------------------------------------------------------------------------------------
    * ExternalWindow special calls for running externals tools */

    bool startExternalProcess(const char* args[])
    {
        ext.inUse = true;

        return ext.start(args);
    }

    void terminateAndWaitForExternalProcess()
    {
        ext.isQuiting = true;
        ext.terminateAndWait();
    }

   /* --------------------------------------------------------------------------------------------------------
    * ExternalWindow specific callbacks */

   /**
      A function called when the window is resized.
    */
    virtual void onResize(uint width, uint height)
    {
        // unused, meant for custom implementations
        return;
        (void)width;
        (void)height;
    }

    virtual void titleChanged(const char* title)
    {
        // unused, meant for custom implementations
        return; (void)title;
    }

    virtual void visibilityChanged(bool visible)
    {
        // unused, meant for custom implementations
        return; (void)visible;
    }

    virtual void transientWindowChanged(uintptr_t winId)
    {
        // unused, meant for custom implementations
        return; (void)winId;
    }

private:
    friend class PluginWindow;
    friend class UI;

    struct ExternalProcess {
        bool inUse;
        bool isQuiting;
        mutable pid_t pid;

        ExternalProcess()
            : inUse(false),
              isQuiting(false),
              pid(0) {}

        bool isRunning() const noexcept
        {
            if (pid <= 0)
                return false;

            const pid_t p = ::waitpid(pid, nullptr, WNOHANG);

            if (p == pid || (p == -1 && errno == ECHILD))
            {
                d_stdout("NOTICE: Child process exited while idle");
                pid = 0;
                return false;
            }

            return true;
        }

        bool start(const char* args[])
        {
            terminateAndWait();

            pid = vfork();

            switch (pid)
            {
            case 0:
                execvp(args[0], (char**)args);
                _exit(1);
                return false;

            case -1:
                d_stderr("Could not start external ui");
                return false;

            default:
                return true;
            }
        }

        void terminateAndWait()
        {
            if (pid <= 0)
                return;

            d_stdout("Waiting for external process to stop,,,");

            bool sendTerm = true;

            for (pid_t p;;)
            {
                p = ::waitpid(pid, nullptr, WNOHANG);

                switch (p)
                {
                case 0:
                    if (sendTerm)
                    {
                        sendTerm = false;
                        ::kill(pid, SIGTERM);
                    }
                    break;

                case -1:
                    if (errno == ECHILD)
                    {
                        d_stdout("Done! (no such process)");
                        pid = 0;
                        return;
                    }
                    break;

                default:
                    if (p == pid)
                    {
                        d_stdout("Done! (clean wait)");
                        pid = 0;
                        return;
                    }
                    break;
                }

                // 5 msec
                usleep(5*1000);
            }
        }
    } ext;

    struct PrivateData {
        uintptr_t parentWindowHandle;
        uintptr_t transientWinId;
        uint width;
        uint height;
        double scaleFactor;
        String title;
        bool visible;

        PrivateData()
            : parentWindowHandle(0),
              transientWinId(0),
              width(1),
              height(1),
              scaleFactor(1.0),
              title(),
              visible(false) {}
    } pData;

    DISTRHO_DECLARE_NON_COPYABLE(ExternalWindow)
};

// -----------------------------------------------------------------------

END_NAMESPACE_DISTRHO

#endif // DISTRHO_EXTERNAL_WINDOW_HPP_INCLUDED
<commit_msg>Remove some virtuals, cleanup<commit_after>/*
 * DISTRHO Plugin Framework (DPF)
 * Copyright (C) 2012-2021 Filipe Coelho <falktx@falktx.com>
 *
 * Permission to use, copy, modify, and/or distribute this software for any purpose with
 * or without fee is hereby granted, provided that the above copyright notice and this
 * permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
 * TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
 * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
 * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

#ifndef DISTRHO_EXTERNAL_WINDOW_HPP_INCLUDED
#define DISTRHO_EXTERNAL_WINDOW_HPP_INCLUDED

#include "String.hpp"

#ifdef DISTRHO_OS_WINDOWS
# error Unsupported platform!
#else
# include <cerrno>
# include <signal.h>
# include <sys/wait.h>
# include <unistd.h>
#endif

START_NAMESPACE_DISTRHO

// -----------------------------------------------------------------------
// ExternalWindow class

/**
   External Window class.

   This is a standalone TopLevelWidget-compatible class, but without any real event handling.
   Being compatible with TopLevelWidget, it allows to be used as DPF UI target.

   It can be used to embed non-DPF things or to run a tool in a new process as the "UI".
 */
class ExternalWindow
{
    struct PrivateData;

public:
   /**
      Constructor.
    */
    explicit ExternalWindow()
       : pData() {}

   /**
      Constructor.
    */
    explicit ExternalWindow(const PrivateData& data)
       : pData(data) {}

   /**
      Destructor.
    */
    virtual ~ExternalWindow()
    {
        DISTRHO_SAFE_ASSERT(!pData.visible);
    }

   /* --------------------------------------------------------------------------------------------------------
    * ExternalWindow specific calls */

    virtual bool isRunning() const
    {
        if (ext.inUse)
            return ext.isRunning();

        return isVisible();
    }

    virtual bool isQuiting() const
    {
        if (ext.inUse)
            return ext.isQuiting;

        return !isVisible();
    }

   /**
      Hide the UI and gracefully terminate.
    */
    virtual void close()
    {
        hide();

        if (ext.inUse)
            terminateAndWaitForExternalProcess();
    }

   /**
      Grab the keyboard input focus.
    */
    virtual void focus() {}

   /**
      Get the transient window that we should attach ourselves to.
      TODO what id? also NSView* on macOS, or NSWindow?
    */
    uintptr_t getTransientWindowId() const noexcept
    {
        return pData.transientWinId;
    }

   /**
      Called by the host to set the transient window that we should attach ourselves to.
      TODO what id? also NSView* on macOS, or NSWindow?
    */
    void setTransientWindowId(uintptr_t winId)
    {
        if (pData.transientWinId == winId)
            return;
        pData.transientWinId = winId;
        transientWindowChanged(winId);
    }

#if DISTRHO_PLUGIN_HAS_EMBED_UI
   /**
      Whether this Window is embed into another (usually not DGL-controlled) Window.
    */
    bool isEmbed() const noexcept
    {
        return pData.parentWindowHandle != 0;
    }

   /**
      Get the "native" window handle.
      This can be reimplemented in order to pass the child window to hosts that can use such informaton.

      Returned value type depends on the platform:
       - HaikuOS: This is a pointer to a `BView`.
       - MacOS: This is a pointer to an `NSView*`.
       - Windows: This is a `HWND`.
       - Everything else: This is an [X11] `Window`.
    */
    virtual uintptr_t getNativeWindowHandle() const noexcept
    {
        return 0;
    }

   /**
      Get the "native" window handle that this window should embed itself into.
      Returned value type depends on the platform:
       - HaikuOS: This is a pointer to a `BView`.
       - MacOS: This is a pointer to an `NSView*`.
       - Windows: This is a `HWND`.
       - Everything else: This is an [X11] `Window`.
    */
    uintptr_t getParentWindowHandle() const noexcept
    {
        return pData.parentWindowHandle;
    }
#endif

   /* --------------------------------------------------------------------------------------------------------
    * TopLevelWidget-like calls */

   /**
      Check if this window is visible.
      @see setVisible(bool)
    */
    bool isVisible() const noexcept
    {
        return pData.visible;
    }

   /**
      Set window visible (or not) according to @a visible.
      @see isVisible(), hide(), show()
    */
    void setVisible(bool visible)
    {
        if (pData.visible == visible)
            return;
        pData.visible = visible;
        visibilityChanged(visible);
    }

   /**
      Show window.
      This is the same as calling setVisible(true).
      @see isVisible(), setVisible(bool)
    */
    void show()
    {
        setVisible(true);
    }

   /**
      Hide window.
      This is the same as calling setVisible(false).
      @see isVisible(), setVisible(bool)
    */
    void hide()
    {
        setVisible(false);
    }

   /**
      Get width.
    */
    uint getWidth() const noexcept
    {
        return pData.width;
    }

   /**
      Get height.
    */
    uint getHeight() const noexcept
    {
        return pData.height;
    }

   /**
      Set width.
    */
    void setWidth(uint width)
    {
        setSize(width, getHeight());
    }

   /**
      Set height.
    */
    void setHeight(uint height)
    {
        setSize(getWidth(), height);
    }

   /**
      Set size using @a width and @a height values.
    */
    void setSize(uint width, uint height)
    {
        DISTRHO_SAFE_ASSERT_UINT2_RETURN(width > 1 && height > 1, width, height,);

        if (pData.width == width || pData.height == height)
            return;

        pData.width = width;
        pData.height = height;
        onResize(width, height);
    }

   /**
      Get the title of the window previously set with setTitle().
    */
    const char* getTitle() const noexcept
    {
        return pData.title;
    }

   /**
      Set the title of the window, typically displayed in the title bar or in window switchers.
    */
    void setTitle(const char* title)
    {
        if (pData.title == title)
            return;
        pData.title = title;
        titleChanged(title);
    }

   /**
      Get the scale factor requested for this window.
      This is purely informational, and up to developers to choose what to do with it.
    */
    double getScaleFactor() const noexcept
    {
        return pData.scaleFactor;
    }

protected:
   /* --------------------------------------------------------------------------------------------------------
    * ExternalWindow special calls for running externals tools */

    bool startExternalProcess(const char* args[])
    {
        ext.inUse = true;

        return ext.start(args);
    }

    void terminateAndWaitForExternalProcess()
    {
        ext.isQuiting = true;
        ext.terminateAndWait();
    }

   /* --------------------------------------------------------------------------------------------------------
    * ExternalWindow specific callbacks */

   /**
      A function called when the window is resized.
    */
    virtual void onResize(uint width, uint height)
    {
        // unused, meant for custom implementations
        return;
        (void)width;
        (void)height;
    }

    virtual void titleChanged(const char* title)
    {
        // unused, meant for custom implementations
        return; (void)title;
    }

    virtual void visibilityChanged(bool visible)
    {
        // unused, meant for custom implementations
        return; (void)visible;
    }

    virtual void transientWindowChanged(uintptr_t winId)
    {
        // unused, meant for custom implementations
        return; (void)winId;
    }

private:
    friend class PluginWindow;
    friend class UI;

    struct ExternalProcess {
        bool inUse;
        bool isQuiting;
        mutable pid_t pid;

        ExternalProcess()
            : inUse(false),
              isQuiting(false),
              pid(0) {}

        bool isRunning() const noexcept
        {
            if (pid <= 0)
                return false;

            const pid_t p = ::waitpid(pid, nullptr, WNOHANG);

            if (p == pid || (p == -1 && errno == ECHILD))
            {
                d_stdout("NOTICE: Child process exited while idle");
                pid = 0;
                return false;
            }

            return true;
        }

        bool start(const char* args[])
        {
            terminateAndWait();

            pid = vfork();

            switch (pid)
            {
            case 0:
                execvp(args[0], (char**)args);
                _exit(1);
                return false;

            case -1:
                d_stderr("Could not start external ui");
                return false;

            default:
                return true;
            }
        }

        void terminateAndWait()
        {
            if (pid <= 0)
                return;

            d_stdout("Waiting for external process to stop,,,");

            bool sendTerm = true;

            for (pid_t p;;)
            {
                p = ::waitpid(pid, nullptr, WNOHANG);

                switch (p)
                {
                case 0:
                    if (sendTerm)
                    {
                        sendTerm = false;
                        ::kill(pid, SIGTERM);
                    }
                    break;

                case -1:
                    if (errno == ECHILD)
                    {
                        d_stdout("Done! (no such process)");
                        pid = 0;
                        return;
                    }
                    break;

                default:
                    if (p == pid)
                    {
                        d_stdout("Done! (clean wait)");
                        pid = 0;
                        return;
                    }
                    break;
                }

                // 5 msec
                usleep(5*1000);
            }
        }
    } ext;

    struct PrivateData {
        uintptr_t parentWindowHandle;
        uintptr_t transientWinId;
        uint width;
        uint height;
        double scaleFactor;
        String title;
        bool visible;

        PrivateData()
            : parentWindowHandle(0),
              transientWinId(0),
              width(1),
              height(1),
              scaleFactor(1.0),
              title(),
              visible(false) {}
    } pData;

    DISTRHO_DECLARE_NON_COPYABLE(ExternalWindow)
};

// -----------------------------------------------------------------------

END_NAMESPACE_DISTRHO

#endif // DISTRHO_EXTERNAL_WINDOW_HPP_INCLUDED
<|endoftext|>


<commit_before>#include <string>
#include <stdio.h>
#include <stdlib.h>
#include <sstream>
#include "opencv2/opencv.hpp"

/*
This functions opens a video file and extracts the frames and put them into a std::vector of Mat(its the class for representing an img)
*/

void extract_frames(const std::string &videoFilePath, std::vector<cv::Mat> &frames)
{
	try
	{
		//open the video file
		cv::VideoCapture cap(videoFilePath); // open the video file
		if(!cap.isOpened())  // check if we succeeded
		CV_Error(CV_StsError, "Can not open Video file");

		//cap.get(CV_CAP_PROP_FRAME_COUNT) contains the number of frames in the video;
		std::cout << "Running for " << cap.get(CV_CAP_PROP_FRAME_COUNT) << " frames." << std::endl;
		for(int frameNum = 0; frameNum < cap.get(CV_CAP_PROP_FRAME_COUNT);frameNum++)
		{
			if (frameNum % 50 == 0) {
				cv::Mat frame;
				cap >> frame; // get the next frame from video
				frames.push_back(frame);
			}
		}
	}
	catch( cv::Exception& e )
	{
		std::cerr << e.msg << std::endl;
		exit(1);
	}
}

/*
It saves a std::vector of frames into jpg images into the outputDir as 1.jpg,2.jpg etc where 1,2 etc represents the frame number
*/
void save_frames(std::vector<cv::Mat>& frames, const std::string& outputDir)
{
	std::vector<int> compression_params;
	compression_params.push_back(CV_IMWRITE_JPEG_QUALITY);
	compression_params.push_back(100);

	int frameNumber=0;
	for (std::vector<cv::Mat>::iterator frame = frames.begin(); frame != frames.end(); ++frame)
	{
		std::stringstream ss;
		ss << frameNumber;
		std::string filePath = outputDir + ss.str() + ".jpg";
		frameNumber++;
		cv::imwrite(filePath, *frame, compression_params);
	}
}

int main(int argc, char** argv)
{
	std::vector<cv::Mat> frames;
	extract_frames("input.MOV", frames);
	save_frames(frames, "output/img");
    return 0;
}
<commit_msg>Frame Capturer working<commit_after>#include <string>
#include <stdio.h>
#include <stdlib.h>
#include <sstream>
#include "opencv2/opencv.hpp"

#define FRAME_STEP 50

/*
This functions opens a video file and extracts the frames and put them into a std::vector of Mat(its the class for representing an img)
*/

void extract_frames(const std::string &videoFilePath, std::vector<cv::Mat> &frames)
{
	try
	{
		//open the video file
		cv::VideoCapture cap(videoFilePath); // open the video file
		if(!cap.isOpened())  // check if we succeeded
		CV_Error(CV_StsError, "Can not open Video file");

		//cap.get(CV_CAP_PROP_FRAME_COUNT) contains the number of frames in the video;
		std::cout << "Running for " << cap.get(CV_CAP_PROP_FRAME_COUNT) << " frames." << std::endl;
		for(int frameNum = 0; frameNum < cap.get(CV_CAP_PROP_FRAME_COUNT);frameNum++)
		{
			if (frameNum % FRAME_STEP == 0) {
				cv::Mat frame;
				cap >> frame; // get the next frame from video
				frames.push_back(frame);
			}
		}
	}
	catch( cv::Exception& e )
	{
		std::cerr << e.msg << std::endl;
		exit(1);
	}
}

/*
It saves a std::vector of frames into jpg images into the outputDir as 1.jpg,2.jpg etc where 1,2 etc represents the frame number
*/
void save_frames(std::vector<cv::Mat>& frames, const std::string& outputDir)
{
	std::vector<int> compression_params;
	compression_params.push_back(CV_IMWRITE_JPEG_QUALITY);
	compression_params.push_back(100);

	int frameNumber=0;
	for (std::vector<cv::Mat>::iterator frame = frames.begin(); frame != frames.end(); ++frame)
	{
		std::stringstream ss;
		ss << frameNumber;
		std::string filePath = outputDir + ss.str() + ".jpg";
		frameNumber++;
		cv::imwrite(filePath, *frame, compression_params);
	}
}

int main(int argc, char** argv)
{
	std::vector<cv::Mat> frames;
	extract_frames("input.MOV", frames);
	save_frames(frames, "output/img");
    return 0;
}
<|endoftext|>


<commit_before>#include <iostream>
#include <iomanip> // << fixed << setprecision(xxx)
#include <algorithm> // do { } while ( next_permutation(A, A+xxx) ) ;
#include <vector>
#include <string> // to_string(nnn) // substr(m, n) // stoi(nnn)
#include <complex>
#include <tuple> // get<n>(xxx)
#include <queue>
#include <stack>
#include <map> // if (M.find(key) != M.end()) { }
#include <set> // S.insert(M);
// if (S.find(key) != S.end()) { }
// for (auto it=S.begin(); it != S.end(); it++) { }
// auto it = S.lower_bound(M);
#include <random> // random_device rd; mt19937 mt(rd());
#include <cctype>
#include <cassert>
#include <cmath>
#include <cstdio>
#include <cstdlib> // atoi(xxx)
using namespace std;

#define DEBUG 0 // change 0 -> 1 if we need debug.
// insert #if<tab> by my emacs. #if DEBUG == 1 ... #end

typedef long long ll;

// const int dx[4] = {1, 0, -1, 0};
// const int dy[4] = {0, 1, 0, -1};

// const int C = 1e6+10;
// const ll M = 1000000007;

typedef tuple<double, double> res; // time, atlas

int N;
ll L, T;
ll X[100010];
int W[100010];
int ans[100010];

vector<ll> V[2];

int main () {
  cin >> N >> L >> T;
  for (auto i = 0; i < N; ++i) {
    cin >> X[i] >> W[i];
    W[i]--;
    V[W[i]].push_back(X[i]);
  }
  for (auto i = 0; i < N; ++i) {
    if (W[i] == 0) {
      ans[i] = X[i] + T%L;
      ans[i] %= L;
    } else {
      ans[i] = X[i] + L - T%L;
      ans[i] %= L;
    }
  }
  int branch = 0;
  if (W[0] == 0) {
    int counter = V[1].size();
    branch += (T/L) * 2 * counter;
    branch %= N;
    int nokori = T%L;
    for (auto x : V[1]) {
      int kyori = (x + L - X[0])%L;
      if (kyori <= 2 * nokori) {
        branch++;
      }
      if (kyori + L <= 2 * nokori) {
        branch++;
      }
    }
    branch %= N;
  } else {
    int counter = V[0].size();
    branch += N - ((T/L) * 2 * counter)%N;
    branch %= N;
    int nokori = T%L;
    for (auto x : V[0]) {
      int kyori = (X[0] + L - x)%L;
      if (kyori <= 2 * nokori) {
        branch += (N-1);
      }
      if (kyori + L <= 2 * nokori) {
        branch += (N-1);
      }
    }
    branch %= N;
  }
  cerr << "branch = " << branch << endl;
  int memo = ans[0];
  cerr << "memo = " << memo << endl;
  sort(ans, ans+N);
  int zahyo = 0;
  if (W[0] == 0) {
    for (auto i = N-1; i >= 0; --i) {
      if (memo == ans[i]) {
        zahyo = (i + N - branch)%N;
        break;
      }
    }
  } else {
    for (auto i = 0; i < N; ++i) {
      if (memo == ans[i]) {
        zahyo = (i + N - branch)%N;
        break;
      }
    }
  }
  cerr << "zahyo = " << zahyo << endl;
  for (auto i = 0; i < N; ++i) {
    cout << ans[(zahyo + i)%N] << endl;
  }
}
<commit_msg>submit C2.cpp to 'C - Ants on a Circle' (agc013) [C++14 (GCC 5.4.1)]<commit_after>#include <iostream>
#include <iomanip> // << fixed << setprecision(xxx)
#include <algorithm> // do { } while ( next_permutation(A, A+xxx) ) ;
#include <vector>
#include <string> // to_string(nnn) // substr(m, n) // stoi(nnn)
#include <complex>
#include <tuple> // get<n>(xxx)
#include <queue>
#include <stack>
#include <map> // if (M.find(key) != M.end()) { }
#include <set> // S.insert(M);
// if (S.find(key) != S.end()) { }
// for (auto it=S.begin(); it != S.end(); it++) { }
// auto it = S.lower_bound(M);
#include <random> // random_device rd; mt19937 mt(rd());
#include <cctype>
#include <cassert>
#include <cmath>
#include <cstdio>
#include <cstdlib> // atoi(xxx)
using namespace std;

#define DEBUG 0 // change 0 -> 1 if we need debug.
// insert #if<tab> by my emacs. #if DEBUG == 1 ... #end

typedef long long ll;

// const int dx[4] = {1, 0, -1, 0};
// const int dy[4] = {0, 1, 0, -1};

// const int C = 1e6+10;
// const ll M = 1000000007;

typedef tuple<double, double> res; // time, atlas

int N;
ll L, T;
ll X[100010];
int W[100010];
int ans[100010];

vector<ll> V[2];

int main () {
  cin >> N >> L >> T;
  for (auto i = 0; i < N; ++i) {
    cin >> X[i] >> W[i];
    W[i]--;
    V[W[i]].push_back(X[i]);
  }
  for (auto i = 0; i < N; ++i) {
    if (W[i] == 0) {
      ans[i] = X[i] + T%L;
      ans[i] %= L;
    } else {
      ans[i] = X[i] + L - T%L;
      ans[i] %= L;
    }
  }
  int branch = 0;
  if (W[0] == 0) {
    int counter = V[1].size();
    branch += (T/L) * 2 * counter;
    branch %= N;
    int nokori = T%L;
    for (auto x : V[1]) {
      int kyori = (x + L - X[0])%L;
      if (kyori <= 2 * nokori) {
        branch++;
      }
      if (kyori + L <= 2 * nokori) {
        branch++;
      }
    }
    branch %= N;
  } else {
    int counter = V[0].size();
    branch += N - ((T/L) * 2 * counter)%N;
    branch %= N;
    int nokori = T%L;
    for (auto x : V[0]) {
      int kyori = (X[0] + L - x)%L;
      if (kyori <= 2 * nokori) {
        branch += (N-1);
        branch %= N;
      }
      if (kyori + L <= 2 * nokori) {
        branch += (N-1);
        branch %= N;
      }
    }
    branch %= N;
  }
  cerr << "branch = " << branch << endl;
  int memo = ans[0];
  cerr << "memo = " << memo << endl;
  sort(ans, ans+N);
  int zahyo = 0;
  if (W[0] == 0) {
    for (auto i = N-1; i >= 0; --i) {
      if (memo == ans[i]) {
        zahyo = (i + N - branch)%N;
        break;
      }
    }
  } else {
    for (auto i = 0; i < N; ++i) {
      if (memo == ans[i]) {
        zahyo = (i + N - branch)%N;
        break;
      }
    }
  }
  cerr << "zahyo = " << zahyo << endl;
  for (auto i = 0; i < N; ++i) {
    cout << ans[(zahyo + i)%N] << endl;
  }
}
<|endoftext|>