<commit_before>/**
 * @file transformer.cpp
 *
 * @date May, 2014
 * @author Tack
 */

#include "transformer.h"
#include "plugin_factory.h"
#include "logger_factory.h"
#include <boost/lexical_cast.hpp>
#include "json_parser.h"
#include "util.h"
#include "level.h"
#include "forecast_time.h"

#include "fetcher.h"

using namespace std;
using namespace himan::plugin;

#include "cuda_helper.h"

transformer::transformer()
	: itsBase(0.0)
	, itsScale(1.0)
	, itsTargetUnivID(9999)
	, itsApplyLandSeaMask(false)
	, itsLandSeaMaskThreshold(0.5)
	, itsInterpolationMethod(kUnknownInterpolationMethod)
{
	itsClearTextFormula = "target_param = source_param * itsScale + itsBase";
	itsCudaEnabledCalculation = true;

	itsLogger = logger_factory::Instance()->GetLog("transformer");
}

vector<himan::level> transformer::LevelsFromString(const string& levelType, const string& levelValues) const
{
	HPLevelType theLevelType = HPStringToLevelType.at(boost::to_lower_copy(levelType));

	vector<string> levelsStr = util::Split(levelValues, ",", true);

	vector<level> levels;

	for (size_t i = 0; i < levelsStr.size(); i++)
	{
		levels.push_back(level(theLevelType, boost::lexical_cast<float> (levelsStr[i]), levelType));
	}

	return levels;
}

void transformer::SetAdditionalParameters()
{
	std::string itsSourceLevelType;
	std::string SourceLevels;

	if(!itsConfiguration->GetValue("base").empty())
	{
		itsBase = boost::lexical_cast<double>(itsConfiguration->GetValue("base"));
	}
	else
	{
		itsLogger->Warning("Base not specified, using default value 0.0");
	}

	if(!itsConfiguration->GetValue("scale").empty())
	{
		itsScale = boost::lexical_cast<double>(itsConfiguration->GetValue("scale"));
	}
	else
	{
		itsLogger->Warning("Scale not specified, using default value 1.0");
	}

	if(!itsConfiguration->GetValue("target_univ_ID").empty())
	{
		itsTargetUnivID = boost::lexical_cast<int>(itsConfiguration->GetValue("target_univ_id"));
	}
	else
	{
		itsLogger->Warning("Target_univ_ID not specified, using default value 9999");
	}

	if(!itsConfiguration->GetValue("target_param").empty())
	{
		itsTargetParam = itsConfiguration->GetValue("target_param");
	}
	else
	{
		throw runtime_error("Transformer_plugin: target_param not specified.");
		exit(1);
	}

	if(!itsConfiguration->GetValue("source_param").empty())
	{
		itsSourceParam = itsConfiguration->GetValue("source_param");
	}
	else
	{
		itsSourceParam = itsTargetParam;
		itsLogger->Warning("Source_param not specified, source_param set to target_param");
	}

	if(!itsConfiguration->GetValue("source_level_type").empty())
	{
		itsSourceLevelType = itsConfiguration->GetValue("source_level_type");
	}
	else
	{
		throw runtime_error("Transformer_plugin: source_level_type not specified.");
		exit(1);
	}

	if(!itsConfiguration->GetValue("source_levels").empty())
	{
		SourceLevels = itsConfiguration->GetValue("source_levels");
	}
	else
	{
		throw runtime_error("Transformer_plugin: source_level_type not specified.");
		exit(1);
	}

	// Check apply land sea mask parameter

	if (itsConfiguration->Exists("apply_landsea_mask") && itsConfiguration->GetValue("apply_landsea_mask") == "true")
	{
		itsApplyLandSeaMask = true;

		// Check for optional threshold parameter
		if (itsConfiguration->Exists("landsea_mask_threshold"))
		{
			itsLandSeaMaskThreshold = boost::lexical_cast<double> (itsConfiguration->GetValue("landsea_mask_threshold"));
		}
	}

	if (itsConfiguration->Exists("interpolation"))
	{
		itsInterpolationMethod = HPStringToInterpolationMethod.at(itsConfiguration->GetValue("interpolation"));
	}

	// looks useful to use this function to create source_levels
	itsSourceLevels = LevelsFromString(itsSourceLevelType, SourceLevels);
}

void transformer::Process(std::shared_ptr<const plugin_configuration> conf)
{
	Init(conf);
	SetAdditionalParameters();

	/*
	 * Set target parameter to T
	 * - name T-C
	 * - univ_id 4
	 * - grib2 descriptor 0'00'000
	 *
	 * We need to specify grib and querydata parameter information
	 * since we don't know which one will be the output format.
	 *
	 */

	vector<param> theParams;

	param requestedParam(itsTargetParam, itsTargetUnivID);

	// GRIB 2
	if (itsConfiguration->OutputFileType() == kGRIB2)
	{
		if (!itsConfiguration->GetValue("grib_discipline").empty() && !itsConfiguration->GetValue("grib_category").empty() && !itsConfiguration->GetValue("grib_parameter").empty())
		{
			requestedParam.GribDiscipline(boost::lexical_cast<int>(itsConfiguration->GetValue("grib_discipline")));
			requestedParam.GribCategory(boost::lexical_cast<int>(itsConfiguration->GetValue("grib_category")));
			requestedParam.GribParameter(boost::lexical_cast<int>(itsConfiguration->GetValue("grib_parameter")));
		}
		else
		{
			throw runtime_error("Transformer_plugin: Grib2 output requested but Grib2 parameter specifiers for output parameter not given in json file.");
		}
	}

	if (itsInterpolationMethod != kUnknownInterpolationMethod)
	{
		requestedParam.InterpolationMethod(itsInterpolationMethod);
	}

	theParams.push_back(requestedParam);

	SetParams(theParams);

	Start();

}

/*
 * Calculate()
 *
 * This function does the actual calculation.
 */

void transformer::Calculate(shared_ptr<info> myTargetInfo, unsigned short threadIndex)
{
	// Required source parameter

	param InputParam(itsSourceParam);

	auto myThreadedLogger = logger_factory::Instance()->GetLog("transformerThread #" + boost::lexical_cast<string> (threadIndex));

	forecast_time forecastTime = myTargetInfo->Time();
	level forecastLevel = myTargetInfo->Level();
	forecast_type forecastType = myTargetInfo->ForecastType();

	myThreadedLogger->Info("Calculating time " + static_cast<string>(forecastTime.ValidDateTime()) + " level " + static_cast<string> (forecastLevel));

	auto f = GET_PLUGIN(fetcher);

	if (itsApplyLandSeaMask)
	{
		f->ApplyLandSeaMask(true);
		f->LandSeaMaskThreshold(itsLandSeaMaskThreshold);
	}

	info_t sourceInfo;

	try
	{
		sourceInfo = f->Fetch(itsConfiguration, forecastTime, itsSourceLevels[myTargetInfo->LevelIndex()], InputParam, forecastType, itsConfiguration->UseCudaForPacking());
	}
	catch (HPExceptionType& e)
	{
		myThreadedLogger->Warning("Skipping step " + boost::lexical_cast<string> (forecastTime.Step()) + ", level " + static_cast<string> (forecastLevel));
		return;
	}

	SetAB(myTargetInfo, sourceInfo);

	bool levelOnly = (itsScale == 1.0 && itsBase == 0.0);

	string deviceType;

#ifdef HAVE_CUDA

	if (itsConfiguration->UseCuda() && !levelOnly)
	{

		deviceType = "GPU";

		auto opts = CudaPrepare(myTargetInfo, sourceInfo);

		transformer_cuda::Process(*opts);

	}
	else
#endif
	{
		deviceType = "CPU";

		LOCKSTEP(myTargetInfo, sourceInfo)
		{

			double value = sourceInfo->Value();

			if (value == kFloatMissing)
			{
				continue;
			}

			if (!levelOnly)
			{
				double newValue = value * itsScale + itsBase;

				myTargetInfo->Value(newValue);
			}
			else
			{
				myTargetInfo->Value(value);
			}

		}
	}

	myThreadedLogger->Info("[" + deviceType + "] Missing values: " + boost::lexical_cast<string> (myTargetInfo->Data().MissingCount()) + "/" + boost::lexical_cast<string> (myTargetInfo->Data().Size()));
}

#ifdef HAVE_CUDA

unique_ptr<transformer_cuda::options> transformer::CudaPrepare( shared_ptr<info> myTargetInfo, shared_ptr<info> sourceInfo)
{
	unique_ptr<transformer_cuda::options> opts(new transformer_cuda::options);

	opts->N = sourceInfo->Data().Size();

	opts->base = itsBase;
	opts->scale = itsScale;

	opts->source = sourceInfo->ToSimple();
	opts->dest = myTargetInfo->ToSimple();

	return opts;
}
#endif

<commit_msg>Make configuration file option lower case<commit_after>/**
 * @file transformer.cpp
 *
 * @date May, 2014
 * @author Tack
 */

#include "transformer.h"
#include "plugin_factory.h"
#include "logger_factory.h"
#include <boost/lexical_cast.hpp>
#include "json_parser.h"
#include "util.h"
#include "level.h"
#include "forecast_time.h"

#include "fetcher.h"

using namespace std;
using namespace himan::plugin;

#include "cuda_helper.h"

transformer::transformer()
	: itsBase(0.0)
	, itsScale(1.0)
	, itsTargetUnivID(9999)
	, itsApplyLandSeaMask(false)
	, itsLandSeaMaskThreshold(0.5)
	, itsInterpolationMethod(kUnknownInterpolationMethod)
{
	itsClearTextFormula = "target_param = source_param * itsScale + itsBase";
	itsCudaEnabledCalculation = true;

	itsLogger = logger_factory::Instance()->GetLog("transformer");
}

vector<himan::level> transformer::LevelsFromString(const string& levelType, const string& levelValues) const
{
	HPLevelType theLevelType = HPStringToLevelType.at(boost::to_lower_copy(levelType));

	vector<string> levelsStr = util::Split(levelValues, ",", true);

	vector<level> levels;

	for (size_t i = 0; i < levelsStr.size(); i++)
	{
		levels.push_back(level(theLevelType, boost::lexical_cast<float> (levelsStr[i]), levelType));
	}

	return levels;
}

void transformer::SetAdditionalParameters()
{
	std::string itsSourceLevelType;
	std::string SourceLevels;

	if(!itsConfiguration->GetValue("base").empty())
	{
		itsBase = boost::lexical_cast<double>(itsConfiguration->GetValue("base"));
	}
	else
	{
		itsLogger->Warning("Base not specified, using default value 0.0");
	}

	if(!itsConfiguration->GetValue("scale").empty())
	{
		itsScale = boost::lexical_cast<double>(itsConfiguration->GetValue("scale"));
	}
	else
	{
		itsLogger->Warning("Scale not specified, using default value 1.0");
	}

	if(!itsConfiguration->GetValue("target_univ_id").empty())
	{
		itsTargetUnivID = boost::lexical_cast<int>(itsConfiguration->GetValue("target_univ_id"));
	}
	else
	{
		itsLogger->Warning("Target_univ_id not specified, using default value 9999");
	}

	if(!itsConfiguration->GetValue("target_param").empty())
	{
		itsTargetParam = itsConfiguration->GetValue("target_param");
	}
	else
	{
		throw runtime_error("Transformer_plugin: target_param not specified.");
		exit(1);
	}

	if(!itsConfiguration->GetValue("source_param").empty())
	{
		itsSourceParam = itsConfiguration->GetValue("source_param");
	}
	else
	{
		itsSourceParam = itsTargetParam;
		itsLogger->Warning("Source_param not specified, source_param set to target_param");
	}

	if(!itsConfiguration->GetValue("source_level_type").empty())
	{
		itsSourceLevelType = itsConfiguration->GetValue("source_level_type");
	}
	else
	{
		throw runtime_error("Transformer_plugin: source_level_type not specified.");
		exit(1);
	}

	if(!itsConfiguration->GetValue("source_levels").empty())
	{
		SourceLevels = itsConfiguration->GetValue("source_levels");
	}
	else
	{
		throw runtime_error("Transformer_plugin: source_level_type not specified.");
		exit(1);
	}

	// Check apply land sea mask parameter

	if (itsConfiguration->Exists("apply_landsea_mask") && itsConfiguration->GetValue("apply_landsea_mask") == "true")
	{
		itsApplyLandSeaMask = true;

		// Check for optional threshold parameter
		if (itsConfiguration->Exists("landsea_mask_threshold"))
		{
			itsLandSeaMaskThreshold = boost::lexical_cast<double> (itsConfiguration->GetValue("landsea_mask_threshold"));
		}
	}

	if (itsConfiguration->Exists("interpolation"))
	{
		itsInterpolationMethod = HPStringToInterpolationMethod.at(itsConfiguration->GetValue("interpolation"));
	}

	// looks useful to use this function to create source_levels
	itsSourceLevels = LevelsFromString(itsSourceLevelType, SourceLevels);
}

void transformer::Process(std::shared_ptr<const plugin_configuration> conf)
{
	Init(conf);
	SetAdditionalParameters();

	/*
	 * Set target parameter to T
	 * - name T-C
	 * - univ_id 4
	 * - grib2 descriptor 0'00'000
	 *
	 * We need to specify grib and querydata parameter information
	 * since we don't know which one will be the output format.
	 *
	 */

	vector<param> theParams;

	param requestedParam(itsTargetParam, itsTargetUnivID);

	// GRIB 2
	if (itsConfiguration->OutputFileType() == kGRIB2)
	{
		if (!itsConfiguration->GetValue("grib_discipline").empty() && !itsConfiguration->GetValue("grib_category").empty() && !itsConfiguration->GetValue("grib_parameter").empty())
		{
			requestedParam.GribDiscipline(boost::lexical_cast<int>(itsConfiguration->GetValue("grib_discipline")));
			requestedParam.GribCategory(boost::lexical_cast<int>(itsConfiguration->GetValue("grib_category")));
			requestedParam.GribParameter(boost::lexical_cast<int>(itsConfiguration->GetValue("grib_parameter")));
		}
		else
		{
			throw runtime_error("Transformer_plugin: Grib2 output requested but Grib2 parameter specifiers for output parameter not given in json file.");
		}
	}

	if (itsInterpolationMethod != kUnknownInterpolationMethod)
	{
		requestedParam.InterpolationMethod(itsInterpolationMethod);
	}

	theParams.push_back(requestedParam);

	SetParams(theParams);

	Start();

}

/*
 * Calculate()
 *
 * This function does the actual calculation.
 */

void transformer::Calculate(shared_ptr<info> myTargetInfo, unsigned short threadIndex)
{
	// Required source parameter

	param InputParam(itsSourceParam);

	auto myThreadedLogger = logger_factory::Instance()->GetLog("transformerThread #" + boost::lexical_cast<string> (threadIndex));

	forecast_time forecastTime = myTargetInfo->Time();
	level forecastLevel = myTargetInfo->Level();
	forecast_type forecastType = myTargetInfo->ForecastType();

	myThreadedLogger->Info("Calculating time " + static_cast<string>(forecastTime.ValidDateTime()) + " level " + static_cast<string> (forecastLevel));

	auto f = GET_PLUGIN(fetcher);

	if (itsApplyLandSeaMask)
	{
		f->ApplyLandSeaMask(true);
		f->LandSeaMaskThreshold(itsLandSeaMaskThreshold);
	}

	info_t sourceInfo;

	try
	{
		sourceInfo = f->Fetch(itsConfiguration, forecastTime, itsSourceLevels[myTargetInfo->LevelIndex()], InputParam, forecastType, itsConfiguration->UseCudaForPacking());
	}
	catch (HPExceptionType& e)
	{
		myThreadedLogger->Warning("Skipping step " + boost::lexical_cast<string> (forecastTime.Step()) + ", level " + static_cast<string> (forecastLevel));
		return;
	}

	SetAB(myTargetInfo, sourceInfo);

	bool levelOnly = (itsScale == 1.0 && itsBase == 0.0);

	string deviceType;

#ifdef HAVE_CUDA

	if (itsConfiguration->UseCuda() && !levelOnly)
	{

		deviceType = "GPU";

		auto opts = CudaPrepare(myTargetInfo, sourceInfo);

		transformer_cuda::Process(*opts);

	}
	else
#endif
	{
		deviceType = "CPU";

		LOCKSTEP(myTargetInfo, sourceInfo)
		{

			double value = sourceInfo->Value();

			if (value == kFloatMissing)
			{
				continue;
			}

			if (!levelOnly)
			{
				double newValue = value * itsScale + itsBase;

				myTargetInfo->Value(newValue);
			}
			else
			{
				myTargetInfo->Value(value);
			}

		}
	}

	myThreadedLogger->Info("[" + deviceType + "] Missing values: " + boost::lexical_cast<string> (myTargetInfo->Data().MissingCount()) + "/" + boost::lexical_cast<string> (myTargetInfo->Data().Size()));
}

#ifdef HAVE_CUDA

unique_ptr<transformer_cuda::options> transformer::CudaPrepare( shared_ptr<info> myTargetInfo, shared_ptr<info> sourceInfo)
{
	unique_ptr<transformer_cuda::options> opts(new transformer_cuda::options);

	opts->N = sourceInfo->Data().Size();

	opts->base = itsBase;
	opts->scale = itsScale;

	opts->source = sourceInfo->ToSimple();
	opts->dest = myTargetInfo->ToSimple();

	return opts;
}
#endif

<|endoftext|>


<commit_before>/**
 * @file llpanelpeoplemenus.h
 * @brief Menus used by the side tray "People" panel
 *
 * $LicenseInfo:firstyear=2009&license=viewerlgpl$
 * Second Life Viewer Source Code
 * Copyright (C) 2010, Linden Research, Inc.
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation;
 * version 2.1 of the License only.
 *
 * 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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 *
 * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
 * $/LicenseInfo$
 */

#include "llviewerprecompiledheaders.h"

// libs
#include "llmenugl.h"
#include "lluictrlfactory.h"

#include "llpanelpeoplemenus.h"

// newview
#include "llagent.h"
#include "llagentdata.h"			// for gAgentID
#include "llavataractions.h"
#include "llcallingcard.h"			// for LLAvatarTracker
#include "lllogchat.h"
#include "llviewermenu.h"			// for gMenuHolder
#include "llconversationmodel.h"
#include "llviewerobjectlist.h"
#include "rlvhandler.h"

namespace LLPanelPeopleMenus
{

PeopleContextMenu gPeopleContextMenu;
NearbyPeopleContextMenu gNearbyPeopleContextMenu;

//== PeopleContextMenu ===============================================================

LLContextMenu* PeopleContextMenu::createMenu()
{
	// set up the callbacks for all of the avatar menu items
	LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar;
	LLUICtrl::EnableCallbackRegistry::ScopedRegistrar enable_registrar;
	LLContextMenu* menu;

	if ( mUUIDs.size() == 1 )
	{
		// Set up for one person selected menu

		const LLUUID& id = mUUIDs.front();
		registrar.add("Avatar.Profile",			boost::bind(&LLAvatarActions::showProfile,				id));
		registrar.add("Avatar.AddFriend",		boost::bind(&LLAvatarActions::requestFriendshipDialog,	id));
		registrar.add("Avatar.RemoveFriend",	boost::bind(&LLAvatarActions::removeFriendDialog, 		id));
		registrar.add("Avatar.IM",				boost::bind(&LLAvatarActions::startIM,					id));
		registrar.add("Avatar.Call",			boost::bind(&LLAvatarActions::startCall,				id));
		registrar.add("Avatar.OfferTeleport",	boost::bind(&PeopleContextMenu::offerTeleport,			this));
		registrar.add("Avatar.ZoomIn",			boost::bind(&handle_zoom_to_object,						id));
		registrar.add("Avatar.ShowOnMap",		boost::bind(&LLAvatarActions::showOnMap,				id));
		registrar.add("Avatar.Share",			boost::bind(&LLAvatarActions::share,					id));
		registrar.add("Avatar.Pay",				boost::bind(&LLAvatarActions::pay,						id));
		registrar.add("Avatar.BlockUnblock",	boost::bind(&LLAvatarActions::toggleBlock,				id));
		registrar.add("Avatar.InviteToGroup",	boost::bind(&LLAvatarActions::inviteToGroup,			id));
		registrar.add("Avatar.Calllog",			boost::bind(&LLAvatarActions::viewChatHistory,			id));
		// <FS:Ansariel> Firestorm additions
		registrar.add("Avatar.GroupInvite",		boost::bind(&LLAvatarActions::inviteToGroup,			id));

		enable_registrar.add("Avatar.EnableItem", boost::bind(&PeopleContextMenu::enableContextMenuItem, this, _2));
		enable_registrar.add("Avatar.CheckItem",  boost::bind(&PeopleContextMenu::checkContextMenuItem,	this, _2));

		// create the context menu from the XUI
		menu = createFromFile("menu_people_nearby.xml");
		buildContextMenu(*menu, 0x0);
	}
	else
	{
		// Set up for multi-selected People

		// registrar.add("Avatar.AddFriend",	boost::bind(&LLAvatarActions::requestFriendshipDialog,	mUUIDs)); // *TODO: unimplemented
		registrar.add("Avatar.IM",				boost::bind(&LLAvatarActions::startConference,			mUUIDs, LLUUID::null));
		registrar.add("Avatar.Call",			boost::bind(&LLAvatarActions::startAdhocCall,			mUUIDs, LLUUID::null));
		registrar.add("Avatar.OfferTeleport",	boost::bind(&PeopleContextMenu::offerTeleport,			this));
		registrar.add("Avatar.RemoveFriend",	boost::bind(&LLAvatarActions::removeFriendsDialog,		mUUIDs));
		// registrar.add("Avatar.Share",		boost::bind(&LLAvatarActions::startIM,					mUUIDs)); // *TODO: unimplemented
		// registrar.add("Avatar.Pay",			boost::bind(&LLAvatarActions::pay,						mUUIDs)); // *TODO: unimplemented

		enable_registrar.add("Avatar.EnableItem",	boost::bind(&PeopleContextMenu::enableContextMenuItem, this, _2));

		// create the context menu from the XUI
		menu = createFromFile("menu_people_nearby_multiselect.xml");
		buildContextMenu(*menu, ITEM_IN_MULTI_SELECTION);
	}

    return menu;
}

void PeopleContextMenu::buildContextMenu(class LLMenuGL& menu, U32 flags)
{
    menuentry_vec_t items;
    menuentry_vec_t disabled_items;

	if (flags & ITEM_IN_MULTI_SELECTION)
	{
		items.push_back(std::string("add_friends"));
		items.push_back(std::string("remove_friends"));
		items.push_back(std::string("im"));
		items.push_back(std::string("call"));
		items.push_back(std::string("share"));
		items.push_back(std::string("pay"));
		items.push_back(std::string("offer_teleport"));
	}
	else
	{
		items.push_back(std::string("view_profile"));
		items.push_back(std::string("im"));
		items.push_back(std::string("offer_teleport"));
		items.push_back(std::string("voice_call"));
		items.push_back(std::string("chat_history"));
		items.push_back(std::string("separator_chat_history"));
		items.push_back(std::string("add_friend"));
		items.push_back(std::string("remove_friend"));
		items.push_back(std::string("invite_to_group"));
		items.push_back(std::string("separator_invite_to_group"));
		items.push_back(std::string("map"));
		items.push_back(std::string("share"));
		items.push_back(std::string("pay"));
		items.push_back(std::string("block_unblock"));
	}

    hide_context_entries(menu, items, disabled_items);
}

bool PeopleContextMenu::enableContextMenuItem(const LLSD& userdata)
{
	if(gAgent.getID() == mUUIDs.front())
	{
		return false;
	}
	std::string item = userdata.asString();

	// Note: can_block and can_delete is used only for one person selected menu
	// so we don't need to go over all uuids.

	if (item == std::string("can_block"))
	{
		const LLUUID& id = mUUIDs.front();
		return LLAvatarActions::canBlock(id);
	}
	else if (item == std::string("can_add"))
	{
		// We can add friends if:
		// - there are selected people
		// - and there are no friends among selection yet.

		//EXT-7389 - disable for more than 1
		if(mUUIDs.size() > 1)
		{
			return false;
		}

		bool result = (mUUIDs.size() > 0);

		uuid_vec_t::const_iterator
			id = mUUIDs.begin(),
			uuids_end = mUUIDs.end();

		for (;id != uuids_end; ++id)
		{
			if ( LLAvatarActions::isFriend(*id) )
			{
				result = false;
				break;
			}
		}

		return result;
	}
	else if (item == std::string("can_delete"))
	{
		// We can remove friends if:
		// - there are selected people
		// - and there are only friends among selection.

		bool result = (mUUIDs.size() > 0);

		uuid_vec_t::const_iterator
			id = mUUIDs.begin(),
			uuids_end = mUUIDs.end();

		for (;id != uuids_end; ++id)
		{
			if ( !LLAvatarActions::isFriend(*id) )
			{
				result = false;
				break;
			}
		}

		return result;
	}
	else if (item == std::string("can_call"))
	{
		return LLAvatarActions::canCall();
	}
	else if (item == std::string("can_zoom_in"))
	{
		const LLUUID& id = mUUIDs.front();

		return gObjectList.findObject(id);
	}
	else if (item == std::string("can_show_on_map"))
	{
		const LLUUID& id = mUUIDs.front();

		return (LLAvatarTracker::instance().isBuddyOnline(id) && is_agent_mappable(id))
					|| gAgent.isGodlike();
	}
	// <FS> Prevent teleport button from being disabled when someone on your
	//      friends list logs out but is still in the region and you have
	//      multiple people selected.
	//else if(item == std::string("can_offer_teleport"))
	//{
	//	return LLAvatarActions::canOfferTeleport(mUUIDs);
	//}
	// </FS>
	// <FS:Ansariel> FIRE-8804: Prevent opening inventory from using share in radar context menu
	else if (item == std::string("can_open_inventory"))
	{
		return (!gRlvHandler.hasBehaviour(RLV_BHVR_SHOWINV));
	}
	// </FS:Ansariel>
	else if (item == std::string("can_callog"))
	{
		return LLLogChat::isTranscriptExist(mUUIDs.front());
	}
	else if (item == std::string("can_im") || item == std::string("can_invite") ||
	         item == std::string("can_share") || item == std::string("can_pay"))
	{
		return true;
	}
	return false;
}

bool PeopleContextMenu::checkContextMenuItem(const LLSD& userdata)
{
	std::string item = userdata.asString();
	const LLUUID& id = mUUIDs.front();

	if (item == std::string("is_blocked"))
	{
		return LLAvatarActions::isBlocked(id);
	}

	return false;
}

void PeopleContextMenu::offerTeleport()
{
	// boost::bind cannot recognize overloaded method LLAvatarActions::offerTeleport(),
	// so we have to use a wrapper.
	LLAvatarActions::offerTeleport(mUUIDs);
}

//== NearbyPeopleContextMenu ===============================================================

void NearbyPeopleContextMenu::buildContextMenu(class LLMenuGL& menu, U32 flags)
{
    menuentry_vec_t items;
    menuentry_vec_t disabled_items;

	if (flags & ITEM_IN_MULTI_SELECTION)
	{
		items.push_back(std::string("add_friends"));
		items.push_back(std::string("remove_friends"));
		items.push_back(std::string("im"));
		items.push_back(std::string("call"));
		items.push_back(std::string("share"));
		items.push_back(std::string("pay"));
		items.push_back(std::string("offer_teleport"));
	}
	else
	{
		items.push_back(std::string("view_profile"));
		items.push_back(std::string("im"));
		items.push_back(std::string("offer_teleport"));
		items.push_back(std::string("voice_call"));
		items.push_back(std::string("chat_history"));
		items.push_back(std::string("separator_chat_history"));
		items.push_back(std::string("add_friend"));
		items.push_back(std::string("remove_friend"));
		items.push_back(std::string("invite_to_group"));
		items.push_back(std::string("separator_invite_to_group"));
		items.push_back(std::string("zoom_in"));
		items.push_back(std::string("map"));
		items.push_back(std::string("share"));
		items.push_back(std::string("pay"));
		items.push_back(std::string("block_unblock"));
	}

    hide_context_entries(menu, items, disabled_items);
}

} // namespace LLPanelPeopleMenus
<commit_msg>Fix build in llpanelpeoplemenus.cpp<commit_after>/**
 * @file llpanelpeoplemenus.h
 * @brief Menus used by the side tray "People" panel
 *
 * $LicenseInfo:firstyear=2009&license=viewerlgpl$
 * Second Life Viewer Source Code
 * Copyright (C) 2010, Linden Research, Inc.
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation;
 * version 2.1 of the License only.
 *
 * 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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 *
 * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
 * $/LicenseInfo$
 */

#include "llviewerprecompiledheaders.h"

// libs
#include "llmenugl.h"
#include "lluictrlfactory.h"
#include "llfolderview.h"	// <FS:CR> CHUI merge

#include "llpanelpeoplemenus.h"

// newview
#include "llagent.h"
#include "llagentdata.h"			// for gAgentID
#include "llavataractions.h"
#include "llcallingcard.h"			// for LLAvatarTracker
#include "lllogchat.h"
#include "llviewermenu.h"			// for gMenuHolder
#include "llconversationmodel.h"
#include "llviewerobjectlist.h"
#include "llinventorybridge.h"	// <FS:CR> CHUI merge
#include "rlvhandler.h"

typedef std::vector<std::string> menuentry_vec_t;	// <FS:CR> CHUI merge - Without LLConversationModel we need this

namespace LLPanelPeopleMenus
{

PeopleContextMenu gPeopleContextMenu;
NearbyPeopleContextMenu gNearbyPeopleContextMenu;

//== PeopleContextMenu ===============================================================

LLContextMenu* PeopleContextMenu::createMenu()
{
	// set up the callbacks for all of the avatar menu items
	LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar;
	LLUICtrl::EnableCallbackRegistry::ScopedRegistrar enable_registrar;
	LLContextMenu* menu;

	if ( mUUIDs.size() == 1 )
	{
		// Set up for one person selected menu

		const LLUUID& id = mUUIDs.front();
		registrar.add("Avatar.Profile",			boost::bind(&LLAvatarActions::showProfile,				id));
		registrar.add("Avatar.AddFriend",		boost::bind(&LLAvatarActions::requestFriendshipDialog,	id));
		registrar.add("Avatar.RemoveFriend",	boost::bind(&LLAvatarActions::removeFriendDialog, 		id));
		registrar.add("Avatar.IM",				boost::bind(&LLAvatarActions::startIM,					id));
		registrar.add("Avatar.Call",			boost::bind(&LLAvatarActions::startCall,				id));
		registrar.add("Avatar.OfferTeleport",	boost::bind(&PeopleContextMenu::offerTeleport,			this));
		// <FS:CR> CHUI merge - Make GCC happy
		//registrar.add("Avatar.ZoomIn",			boost::bind(&handle_zoom_to_object,						id));
		registrar.add("Avatar.ZoomIn",			boost::bind(&LLAvatarActions::zoomIn,						id));
		// </FS:CR>
		registrar.add("Avatar.ShowOnMap",		boost::bind(&LLAvatarActions::showOnMap,				id));
		registrar.add("Avatar.Share",			boost::bind(&LLAvatarActions::share,					id));
		registrar.add("Avatar.Pay",				boost::bind(&LLAvatarActions::pay,						id));
		registrar.add("Avatar.BlockUnblock",	boost::bind(&LLAvatarActions::toggleBlock,				id));
		registrar.add("Avatar.InviteToGroup",	boost::bind(&LLAvatarActions::inviteToGroup,			id));
		registrar.add("Avatar.Calllog",			boost::bind(&LLAvatarActions::viewChatHistory,			id));
		// <FS:Ansariel> Firestorm additions
		registrar.add("Avatar.GroupInvite",		boost::bind(&LLAvatarActions::inviteToGroup,			id));

		enable_registrar.add("Avatar.EnableItem", boost::bind(&PeopleContextMenu::enableContextMenuItem, this, _2));
		enable_registrar.add("Avatar.CheckItem",  boost::bind(&PeopleContextMenu::checkContextMenuItem,	this, _2));

		// create the context menu from the XUI
		menu = createFromFile("menu_people_nearby.xml");
		buildContextMenu(*menu, 0x0);
	}
	else
	{
		// Set up for multi-selected People

		// registrar.add("Avatar.AddFriend",	boost::bind(&LLAvatarActions::requestFriendshipDialog,	mUUIDs)); // *TODO: unimplemented
		registrar.add("Avatar.IM",				boost::bind(&LLAvatarActions::startConference,			mUUIDs, LLUUID::null));
		registrar.add("Avatar.Call",			boost::bind(&LLAvatarActions::startAdhocCall,			mUUIDs, LLUUID::null));
		registrar.add("Avatar.OfferTeleport",	boost::bind(&PeopleContextMenu::offerTeleport,			this));
		registrar.add("Avatar.RemoveFriend",	boost::bind(&LLAvatarActions::removeFriendsDialog,		mUUIDs));
		// registrar.add("Avatar.Share",		boost::bind(&LLAvatarActions::startIM,					mUUIDs)); // *TODO: unimplemented
		// registrar.add("Avatar.Pay",			boost::bind(&LLAvatarActions::pay,						mUUIDs)); // *TODO: unimplemented

		enable_registrar.add("Avatar.EnableItem",	boost::bind(&PeopleContextMenu::enableContextMenuItem, this, _2));

		// create the context menu from the XUI
		menu = createFromFile("menu_people_nearby_multiselect.xml");
		buildContextMenu(*menu, ITEM_IN_MULTI_SELECTION);
	}

    return menu;
}

void PeopleContextMenu::buildContextMenu(class LLMenuGL& menu, U32 flags)
{
    menuentry_vec_t items;
    menuentry_vec_t disabled_items;

	if (flags & ITEM_IN_MULTI_SELECTION)
	{
		items.push_back(std::string("add_friends"));
		items.push_back(std::string("remove_friends"));
		items.push_back(std::string("im"));
		items.push_back(std::string("call"));
		items.push_back(std::string("share"));
		items.push_back(std::string("pay"));
		items.push_back(std::string("offer_teleport"));
	}
	else
	{
		items.push_back(std::string("view_profile"));
		items.push_back(std::string("im"));
		items.push_back(std::string("offer_teleport"));
		items.push_back(std::string("voice_call"));
		items.push_back(std::string("chat_history"));
		items.push_back(std::string("separator_chat_history"));
		items.push_back(std::string("add_friend"));
		items.push_back(std::string("remove_friend"));
		items.push_back(std::string("invite_to_group"));
		items.push_back(std::string("separator_invite_to_group"));
		items.push_back(std::string("map"));
		items.push_back(std::string("share"));
		items.push_back(std::string("pay"));
		items.push_back(std::string("block_unblock"));
	}

    hide_context_entries(menu, items, disabled_items);
}

bool PeopleContextMenu::enableContextMenuItem(const LLSD& userdata)
{
	if(gAgent.getID() == mUUIDs.front())
	{
		return false;
	}
	std::string item = userdata.asString();

	// Note: can_block and can_delete is used only for one person selected menu
	// so we don't need to go over all uuids.

	if (item == std::string("can_block"))
	{
		const LLUUID& id = mUUIDs.front();
		return LLAvatarActions::canBlock(id);
	}
	else if (item == std::string("can_add"))
	{
		// We can add friends if:
		// - there are selected people
		// - and there are no friends among selection yet.

		//EXT-7389 - disable for more than 1
		if(mUUIDs.size() > 1)
		{
			return false;
		}

		bool result = (mUUIDs.size() > 0);

		uuid_vec_t::const_iterator
			id = mUUIDs.begin(),
			uuids_end = mUUIDs.end();

		for (;id != uuids_end; ++id)
		{
			if ( LLAvatarActions::isFriend(*id) )
			{
				result = false;
				break;
			}
		}

		return result;
	}
	else if (item == std::string("can_delete"))
	{
		// We can remove friends if:
		// - there are selected people
		// - and there are only friends among selection.

		bool result = (mUUIDs.size() > 0);

		uuid_vec_t::const_iterator
			id = mUUIDs.begin(),
			uuids_end = mUUIDs.end();

		for (;id != uuids_end; ++id)
		{
			if ( !LLAvatarActions::isFriend(*id) )
			{
				result = false;
				break;
			}
		}

		return result;
	}
	else if (item == std::string("can_call"))
	{
		return LLAvatarActions::canCall();
	}
	else if (item == std::string("can_zoom_in"))
	{
		const LLUUID& id = mUUIDs.front();

		return gObjectList.findObject(id);
	}
	else if (item == std::string("can_show_on_map"))
	{
		const LLUUID& id = mUUIDs.front();

		return (LLAvatarTracker::instance().isBuddyOnline(id) && is_agent_mappable(id))
					|| gAgent.isGodlike();
	}
	// <FS> Prevent teleport button from being disabled when someone on your
	//      friends list logs out but is still in the region and you have
	//      multiple people selected.
	//else if(item == std::string("can_offer_teleport"))
	//{
	//	return LLAvatarActions::canOfferTeleport(mUUIDs);
	//}
	// </FS>
	// <FS:Ansariel> FIRE-8804: Prevent opening inventory from using share in radar context menu
	else if (item == std::string("can_open_inventory"))
	{
		return (!gRlvHandler.hasBehaviour(RLV_BHVR_SHOWINV));
	}
	// </FS:Ansariel>
	else if (item == std::string("can_callog"))
	{
		return LLLogChat::isTranscriptExist(mUUIDs.front());
	}
	else if (item == std::string("can_im") || item == std::string("can_invite") ||
	         item == std::string("can_share") || item == std::string("can_pay"))
	{
		return true;
	}
	return false;
}

bool PeopleContextMenu::checkContextMenuItem(const LLSD& userdata)
{
	std::string item = userdata.asString();
	const LLUUID& id = mUUIDs.front();

	if (item == std::string("is_blocked"))
	{
		return LLAvatarActions::isBlocked(id);
	}

	return false;
}

void PeopleContextMenu::offerTeleport()
{
	// boost::bind cannot recognize overloaded method LLAvatarActions::offerTeleport(),
	// so we have to use a wrapper.
	LLAvatarActions::offerTeleport(mUUIDs);
}

//== NearbyPeopleContextMenu ===============================================================

void NearbyPeopleContextMenu::buildContextMenu(class LLMenuGL& menu, U32 flags)
{
    menuentry_vec_t items;
    menuentry_vec_t disabled_items;

	if (flags & ITEM_IN_MULTI_SELECTION)
	{
		items.push_back(std::string("add_friends"));
		items.push_back(std::string("remove_friends"));
		items.push_back(std::string("im"));
		items.push_back(std::string("call"));
		items.push_back(std::string("share"));
		items.push_back(std::string("pay"));
		items.push_back(std::string("offer_teleport"));
	}
	else
	{
		items.push_back(std::string("view_profile"));
		items.push_back(std::string("im"));
		items.push_back(std::string("offer_teleport"));
		items.push_back(std::string("voice_call"));
		items.push_back(std::string("chat_history"));
		items.push_back(std::string("separator_chat_history"));
		items.push_back(std::string("add_friend"));
		items.push_back(std::string("remove_friend"));
		items.push_back(std::string("invite_to_group"));
		items.push_back(std::string("separator_invite_to_group"));
		items.push_back(std::string("zoom_in"));
		items.push_back(std::string("map"));
		items.push_back(std::string("share"));
		items.push_back(std::string("pay"));
		items.push_back(std::string("block_unblock"));
	}

    hide_context_entries(menu, items, disabled_items);
}

} // namespace LLPanelPeopleMenus
<|endoftext|>


<commit_before>//
//  Profiler.h
//  Created by Matt Kaufmann on 12/09/13.
//

#include "Vajra/Engine/Core/Engine.h"
#include "Vajra/Engine/Profiler/ProfileExperiment.h"
#include "Vajra/Engine/Profiler/Profiler.h"
#include "Vajra/Engine/Timer/Timer.h"

ProfileExperiment::ProfileExperiment() : id("") {
	init();
}

ProfileExperiment::ProfileExperiment(std::string strId) : id(strId) {
	init();
}

void ProfileExperiment::init() {
	this->startTime = 0.0;
	this->endTime = 0.0;
	this->totalTime = 0.0;
	this->lastDuration = 0.0;
	this->minDuration = 0.0;
	this->maxDuration = 0.0;
	this->avgDuration = 0.0;
	this->count = 0;
}

void ProfileExperiment::Start() {
	this->startTime = ENGINE->GetTimer()->GetHighResAbsoluteTime();
	this->count++;
}

void ProfileExperiment::Stop() {
	this->endTime = ENGINE->GetTimer()->GetHighResAbsoluteTime();
	double duration = this->endTime - this->startTime;
	this->totalTime += duration;
	if (this->lastDuration < this->minDuration) { this->minDuration = duration; }
	if (this->lastDuration > this->maxDuration) { this->maxDuration = duration; }
	this->lastDuration = duration;
	this->avgDuration = this->totalTime / this->count;
}

void ProfileExperiment::PrintLastLog() {
	FRAMEWORK->GetLogger()->dbglog("\nProfile experiment %s: %f ms", this->id.c_str(), this->lastDuration * 1000.0);
}

void ProfileExperiment::PrintLogStats() {
	FRAMEWORK->GetLogger()->dbglog("\nStats for profile experiment %s: %f-%f ms over %llu runs (average %f ms)",
			this->id.c_str(), this->minDuration * 1000.0, this->maxDuration * 1000.0, this->count, this->avgDuration * 1000.0);
}

void ProfileExperiment::PrintLogStats(std::ofstream& outputFile) {
	outputFile << "Stats for profile experiment " << this->id << ": " << (this->minDuration * 1000.0) << "-" << (this->maxDuration * 1000.0)
			   << " ms over " << this->count << " runs (average " << (this->avgDuration * 1000.0) << " ms)"
			   << std::endl;
}
<commit_msg>Missed a couple of references in ProfileExperiment.cpp<commit_after>//
//  Profiler.h
//  Created by Matt Kaufmann on 12/09/13.
//

#include "Vajra/Engine/Core/Engine.h"
#include "Vajra/Engine/Profiler/ProfileExperiment.h"
#include "Vajra/Engine/Profiler/Profiler.h"
#include "Vajra/Engine/Timer/Timer.h"

ProfileExperiment::ProfileExperiment() : id("") {
	init();
}

ProfileExperiment::ProfileExperiment(std::string strId) : id(strId) {
	init();
}

void ProfileExperiment::init() {
	this->startTime = 0.0;
	this->endTime = 0.0;
	this->totalTime = 0.0;
	this->lastDuration = 0.0;
	this->minDuration = 0.0;
	this->maxDuration = 0.0;
	this->avgDuration = 0.0;
	this->count = 0;
}

void ProfileExperiment::Start() {
	this->startTime = ENGINE->GetTimer()->GetHighResAbsoluteTime();
	this->count++;
}

void ProfileExperiment::Stop() {
	this->endTime = ENGINE->GetTimer()->GetHighResAbsoluteTime();
	double duration = this->endTime - this->startTime;
	this->totalTime += duration;
	if (duration < this->minDuration) { this->minDuration = duration; }
	if (duration > this->maxDuration) { this->maxDuration = duration; }
	this->lastDuration = duration;
	this->avgDuration = this->totalTime / this->count;
}

void ProfileExperiment::PrintLastLog() {
	FRAMEWORK->GetLogger()->dbglog("\nProfile experiment %s: %f ms", this->id.c_str(), this->lastDuration * 1000.0);
}

void ProfileExperiment::PrintLogStats() {
	FRAMEWORK->GetLogger()->dbglog("\nStats for profile experiment %s: %f-%f ms over %llu runs (average %f ms)",
			this->id.c_str(), this->minDuration * 1000.0, this->maxDuration * 1000.0, this->count, this->avgDuration * 1000.0);
}

void ProfileExperiment::PrintLogStats(std::ofstream& outputFile) {
	outputFile << "Stats for profile experiment " << this->id << ": " << (this->minDuration * 1000.0) << "-" << (this->maxDuration * 1000.0)
			   << " ms over " << this->count << " runs (average " << (this->avgDuration * 1000.0) << " ms)"
			   << std::endl;
}
<|endoftext|>


<commit_before>/****************************************************************************
 *
 *   (c) 2009-2016 QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org>
 *
 * QGroundControl is licensed according to the terms in the file
 * COPYING.md in the root of the source code directory.
 *
 ****************************************************************************/

#include <QApplication>
#include <QDebug>
#include <QRegularExpression>

#include "AudioOutput.h"
#include "QGCApplication.h"
#include "QGC.h"
#include "SettingsManager.h"

AudioOutput::AudioOutput(QGCApplication* app, QGCToolbox* toolbox)
    : QGCTool(app, toolbox)
{
    _tts = new QTextToSpeech(this);
    connect(_tts, &QTextToSpeech::stateChanged, this, &AudioOutput::_stateChanged);
}

bool AudioOutput::say(const QString& inText)
{
    bool muted = qgcApp()->toolbox()->settingsManager()->appSettings()->audioMuted()->rawValue().toBool();
    muted |= qgcApp()->runningUnitTests();
    if (!muted && !qgcApp()->runningUnitTests()) {
        QString text = fixTextMessageForAudio(inText);
        if(_tts->state() == QTextToSpeech::Speaking) {
            if(!_texts.contains(text)) {
                //-- Some arbitrary limit
                if(_texts.size() > 20) {
                    _texts.removeFirst();
                }
                _texts.append(text);
            }
        } else {
            _tts->say(text);
        }
    }
    return true;
}

void AudioOutput::_stateChanged(QTextToSpeech::State state)
{
    if(state == QTextToSpeech::Ready) {
        if(_texts.size()) {
            QString text = _texts.first();
            _texts.removeFirst();
            _tts->say(text);
        }
    }
}

bool AudioOutput::getMillisecondString(const QString& string, QString& match, int& number) {
    static QRegularExpression re("([0-9]+ms)");
    QRegularExpressionMatchIterator i = re.globalMatch(string);
    while (i.hasNext()) {
        QRegularExpressionMatch qmatch = i.next();
        if (qmatch.hasMatch()) {
            match = qmatch.captured(0);
            number = qmatch.captured(0).replace("ms", "").toInt();
            return true;
        }
    }
    return false;
}

QString AudioOutput::fixTextMessageForAudio(const QString& string) {
    QString match;
    QString newNumber;
    QString result = string;
    //-- Look for codified terms
    if(result.contains("ERR ", Qt::CaseInsensitive)) {
        result.replace("ERR ", "error ", Qt::CaseInsensitive);
    }
    if(result.contains("ERR:", Qt::CaseInsensitive)) {
        result.replace("ERR:", "error.", Qt::CaseInsensitive);
    }
    if(result.contains("POSCTL", Qt::CaseInsensitive)) {
        result.replace("POSCTL", "Position Control", Qt::CaseInsensitive);
    }
    if(result.contains("ALTCTL", Qt::CaseInsensitive)) {
        result.replace("ALTCTL", "Altitude Control", Qt::CaseInsensitive);
    }
    if(result.contains("AUTO_RTL", Qt::CaseInsensitive)) {
        result.replace("AUTO_RTL", "auto Return To Launch", Qt::CaseInsensitive);
    } else if(result.contains("RTL", Qt::CaseInsensitive)) {
        result.replace("RTL", "Return To Launch", Qt::CaseInsensitive);
    }
    if(result.contains("ACCEL ", Qt::CaseInsensitive)) {
        result.replace("ACCEL ", "accelerometer ", Qt::CaseInsensitive);
    }
    if(result.contains("RC_MAP_MODE_SW", Qt::CaseInsensitive)) {
        result.replace("RC_MAP_MODE_SW", "RC mode switch", Qt::CaseInsensitive);
    }
    if(result.contains("REJ.", Qt::CaseInsensitive)) {
        result.replace("REJ.", "Rejected", Qt::CaseInsensitive);
    }
    if(result.contains("WP", Qt::CaseInsensitive)) {
        result.replace("WP", "way point", Qt::CaseInsensitive);
    }
    if(result.contains("CMD", Qt::CaseInsensitive)) {
        result.replace("CMD", "command", Qt::CaseInsensitive);
    }
    if(result.contains("COMPID", Qt::CaseInsensitive)) {
        result.replace("COMPID", "component eye dee", Qt::CaseInsensitive);
    }
    if(result.contains(" params ", Qt::CaseInsensitive)) {
        result.replace(" params ", " parameters ", Qt::CaseInsensitive);
    }
    if(result.contains(" id ", Qt::CaseInsensitive)) {
        result.replace(" id ", " eye dee ", Qt::CaseInsensitive);
    }
    if(result.contains(" ADSB ", Qt::CaseInsensitive)) {
        result.replace(" ADSB ", " Hey Dee Ess Bee ", Qt::CaseInsensitive);
    }

    // Convert negative numbers
    QRegularExpression re(QStringLiteral("(-)[0-9]*\\.?[0-9]"));
    QRegularExpressionMatch reMatch = re.match(result);
    while (reMatch.hasMatch()) {
        if (!reMatch.captured(1).isNull()) {
            // There is a negative prefix
            qDebug() << "negative" << reMatch.captured(1) << reMatch.capturedStart(1) << reMatch.capturedEnd(1);
            result.replace(reMatch.capturedStart(1), reMatch.capturedEnd(1) - reMatch.capturedStart(1), tr(" negative "));
            qDebug() << result;
        }
        reMatch = re.match(result);
    }

    // Convert meter postfix after real number
    re.setPattern(QStringLiteral("[0-9]*\\.?[0-9]\\s?(m)([^A-Za-z]|$)"));
    reMatch = re.match(result);
    while (reMatch.hasMatch()) {
        if (!reMatch.captured(1).isNull()) {
            // There is a meter postfix
            qDebug() << "meters" << reMatch.captured(1) << reMatch.capturedStart(1) << reMatch.capturedEnd(1);
            result.replace(reMatch.capturedStart(1), reMatch.capturedEnd(1) - reMatch.capturedStart(1), tr(" meters"));
            qDebug() << result;
        }
        reMatch = re.match(result);
    }

    int number;
    if(getMillisecondString(string, match, number) && number > 1000) {
        if(number < 60000) {
            int seconds = number / 1000;
            newNumber = QString("%1 second%2").arg(seconds).arg(seconds > 1 ? "s" : "");
        } else {
            int minutes = number / 60000;
            int seconds = (number - (minutes * 60000)) / 1000;
            if (!seconds) {
                newNumber = QString("%1 minute%2").arg(minutes).arg(minutes > 1 ? "s" : "");
            } else {
                newNumber = QString("%1 minute%2 and %3 second%4").arg(minutes).arg(minutes > 1 ? "s" : "").arg(seconds).arg(seconds > 1 ? "s" : "");
            }
        }
        result.replace(match, newNumber);
    }
    return result;
}
<commit_msg>AudioOutput: Create text to speech in constructor<commit_after>/****************************************************************************
 *
 *   (c) 2009-2016 QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org>
 *
 * QGroundControl is licensed according to the terms in the file
 * COPYING.md in the root of the source code directory.
 *
 ****************************************************************************/

#include <QApplication>
#include <QDebug>
#include <QRegularExpression>

#include "AudioOutput.h"
#include "QGCApplication.h"
#include "QGC.h"
#include "SettingsManager.h"

AudioOutput::AudioOutput(QGCApplication* app, QGCToolbox* toolbox)
    : QGCTool(app, toolbox)
    , _tts(new QTextToSpeech(this))
{
    connect(_tts, &QTextToSpeech::stateChanged, this, &AudioOutput::_stateChanged);
}

bool AudioOutput::say(const QString& inText)
{
    bool muted = qgcApp()->toolbox()->settingsManager()->appSettings()->audioMuted()->rawValue().toBool();
    muted |= qgcApp()->runningUnitTests();
    if (!muted && !qgcApp()->runningUnitTests()) {
        QString text = fixTextMessageForAudio(inText);
        if(_tts->state() == QTextToSpeech::Speaking) {
            if(!_texts.contains(text)) {
                //-- Some arbitrary limit
                if(_texts.size() > 20) {
                    _texts.removeFirst();
                }
                _texts.append(text);
            }
        } else {
            _tts->say(text);
        }
    }
    return true;
}

void AudioOutput::_stateChanged(QTextToSpeech::State state)
{
    if(state == QTextToSpeech::Ready) {
        if(_texts.size()) {
            QString text = _texts.first();
            _texts.removeFirst();
            _tts->say(text);
        }
    }
}

bool AudioOutput::getMillisecondString(const QString& string, QString& match, int& number) {
    static QRegularExpression re("([0-9]+ms)");
    QRegularExpressionMatchIterator i = re.globalMatch(string);
    while (i.hasNext()) {
        QRegularExpressionMatch qmatch = i.next();
        if (qmatch.hasMatch()) {
            match = qmatch.captured(0);
            number = qmatch.captured(0).replace("ms", "").toInt();
            return true;
        }
    }
    return false;
}

QString AudioOutput::fixTextMessageForAudio(const QString& string) {
    QString match;
    QString newNumber;
    QString result = string;
    //-- Look for codified terms
    if(result.contains("ERR ", Qt::CaseInsensitive)) {
        result.replace("ERR ", "error ", Qt::CaseInsensitive);
    }
    if(result.contains("ERR:", Qt::CaseInsensitive)) {
        result.replace("ERR:", "error.", Qt::CaseInsensitive);
    }
    if(result.contains("POSCTL", Qt::CaseInsensitive)) {
        result.replace("POSCTL", "Position Control", Qt::CaseInsensitive);
    }
    if(result.contains("ALTCTL", Qt::CaseInsensitive)) {
        result.replace("ALTCTL", "Altitude Control", Qt::CaseInsensitive);
    }
    if(result.contains("AUTO_RTL", Qt::CaseInsensitive)) {
        result.replace("AUTO_RTL", "auto Return To Launch", Qt::CaseInsensitive);
    } else if(result.contains("RTL", Qt::CaseInsensitive)) {
        result.replace("RTL", "Return To Launch", Qt::CaseInsensitive);
    }
    if(result.contains("ACCEL ", Qt::CaseInsensitive)) {
        result.replace("ACCEL ", "accelerometer ", Qt::CaseInsensitive);
    }
    if(result.contains("RC_MAP_MODE_SW", Qt::CaseInsensitive)) {
        result.replace("RC_MAP_MODE_SW", "RC mode switch", Qt::CaseInsensitive);
    }
    if(result.contains("REJ.", Qt::CaseInsensitive)) {
        result.replace("REJ.", "Rejected", Qt::CaseInsensitive);
    }
    if(result.contains("WP", Qt::CaseInsensitive)) {
        result.replace("WP", "way point", Qt::CaseInsensitive);
    }
    if(result.contains("CMD", Qt::CaseInsensitive)) {
        result.replace("CMD", "command", Qt::CaseInsensitive);
    }
    if(result.contains("COMPID", Qt::CaseInsensitive)) {
        result.replace("COMPID", "component eye dee", Qt::CaseInsensitive);
    }
    if(result.contains(" params ", Qt::CaseInsensitive)) {
        result.replace(" params ", " parameters ", Qt::CaseInsensitive);
    }
    if(result.contains(" id ", Qt::CaseInsensitive)) {
        result.replace(" id ", " eye dee ", Qt::CaseInsensitive);
    }
    if(result.contains(" ADSB ", Qt::CaseInsensitive)) {
        result.replace(" ADSB ", " Hey Dee Ess Bee ", Qt::CaseInsensitive);
    }

    // Convert negative numbers
    QRegularExpression re(QStringLiteral("(-)[0-9]*\\.?[0-9]"));
    QRegularExpressionMatch reMatch = re.match(result);
    while (reMatch.hasMatch()) {
        if (!reMatch.captured(1).isNull()) {
            // There is a negative prefix
            qDebug() << "negative" << reMatch.captured(1) << reMatch.capturedStart(1) << reMatch.capturedEnd(1);
            result.replace(reMatch.capturedStart(1), reMatch.capturedEnd(1) - reMatch.capturedStart(1), tr(" negative "));
            qDebug() << result;
        }
        reMatch = re.match(result);
    }

    // Convert meter postfix after real number
    re.setPattern(QStringLiteral("[0-9]*\\.?[0-9]\\s?(m)([^A-Za-z]|$)"));
    reMatch = re.match(result);
    while (reMatch.hasMatch()) {
        if (!reMatch.captured(1).isNull()) {
            // There is a meter postfix
            qDebug() << "meters" << reMatch.captured(1) << reMatch.capturedStart(1) << reMatch.capturedEnd(1);
            result.replace(reMatch.capturedStart(1), reMatch.capturedEnd(1) - reMatch.capturedStart(1), tr(" meters"));
            qDebug() << result;
        }
        reMatch = re.match(result);
    }

    int number;
    if(getMillisecondString(string, match, number) && number > 1000) {
        if(number < 60000) {
            int seconds = number / 1000;
            newNumber = QString("%1 second%2").arg(seconds).arg(seconds > 1 ? "s" : "");
        } else {
            int minutes = number / 60000;
            int seconds = (number - (minutes * 60000)) / 1000;
            if (!seconds) {
                newNumber = QString("%1 minute%2").arg(minutes).arg(minutes > 1 ? "s" : "");
            } else {
                newNumber = QString("%1 minute%2 and %3 second%4").arg(minutes).arg(minutes > 1 ? "s" : "").arg(seconds).arg(seconds > 1 ? "s" : "");
            }
        }
        result.replace(match, newNumber);
    }
    return result;
}
<|endoftext|>


<commit_before>#pragma once

void TEST_time(){
    printf("■ time\n");
    time_t      c_time    = time(0); // get current time
    struct tm   c_tm      = sstd::time2tm(c_time);
    time_t      c_time_2  = sstd::tm2time(c_tm);
    double      unixday   = sstd::time2unixday(c_time);
    double      unixday_2 = sstd::tm2unixday(c_tm);
    printf("GMT: %s\n", sstd::tm2str(c_tm).c_str());
    printf("GMT: %s\n", sstd::time2str(c_time_2).c_str());
    printf("unixday: %lf\n", unixday);
    printf("unixday: %lf\n", unixday_2);
    printf("\n");

    struct tm   c_tm_l   = sstd::timeGm2tmLocal(c_time);
//    time_t      c_time_3 = sstd::tmLocal2timeGm(c_tm_l);
    printf("local: %s\n",  sstd::tm2str(c_tm_l).c_str());
//    printf("GMT: %s\n",    sstd::time2str(c_time_3).c_str());
    printf("\n");

    time_t c_time_yday  = sstd::yday2time(c_tm.tm_year+1900, c_tm.tm_yday+1);
    printf("GMT: %s\n",   sstd::time2str(c_time_yday).c_str());
    struct tm c_tm_yday = sstd::yday2tm(c_tm.tm_year+1900, c_tm.tm_yday+1);
    printf("GMT: %s\n",   sstd::tm2str(c_tm_yday).c_str());
    printf("\n");

    struct timeval time_sec_micro = sstd::getTimeval();
    printf("timeval: %lf\n",(time_sec_micro.tv_sec)+(time_sec_micro.tv_usec*1.0E-6));

    sstd::print(c_tm_yday);
    sstd::printn(c_tm_yday);
    sstd::printn_all(c_tm_yday);
}

TEST(math, theOthers){
    TEST_time();
}

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

TEST(time, time2tm){
}
TEST(time, tm2time){
}
TEST(time, time2unixday){
}
TEST(time, tm2unixday){
}
TEST(time, tm2str){
}
TEST(time, time2str){
}
TEST(time, timeGm2tmLocal){
}
TEST(time, tmLocal2timeGm){
//  time_t c_time = time(0); // get current time
    time_t c_time = 1619108282;
    // local: 2021-04-23 01:18:02
    // GMT: 2021-04-22 16:18:02

    struct tm c_tm_l   = sstd::timeGm2tmLocal(c_time);
    time_t    c_time_g = sstd::tmLocal2timeGm(c_tm_l);
    std::string t_l = sstd::ssprintf("local: %s", sstd::tm2str(c_tm_l).c_str());
    std::string t_g = sstd::ssprintf("GMT: %s", sstd::time2str(c_time_g).c_str());

    ASSERT_STREQ("local: 2021-04-23 01:18:02", t_l.c_str());
    ASSERT_STREQ("GMT: 2021-04-22 16:18:02",   t_g.c_str());
}
TEST(time, yday2time){
}
TEST(time, yday2tm){
}
TEST(time, getTimeval){
}

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

<commit_msg>fix: test<commit_after>#pragma once

void TEST_time(){
    printf("■ time\n");
    time_t      c_time    = time(0); // get current time
    struct tm   c_tm      = sstd::time2tm(c_time);
    time_t      c_time_2  = sstd::tm2time(c_tm);
    double      unixday   = sstd::time2unixday(c_time);
    double      unixday_2 = sstd::tm2unixday(c_tm);
    printf("GMT: %s\n", sstd::tm2str(c_tm).c_str());
    printf("GMT: %s\n", sstd::time2str(c_time_2).c_str());
    printf("unixday: %lf\n", unixday);
    printf("unixday: %lf\n", unixday_2);
    printf("\n");

    struct tm   c_tm_l   = sstd::timeGm2tmLocal(c_time);
//    time_t      c_time_3 = sstd::tmLocal2timeGm(c_tm_l);
    printf("local: %s\n",  sstd::tm2str(c_tm_l).c_str());
//    printf("GMT: %s\n",    sstd::time2str(c_time_3).c_str());
    printf("\n");

    time_t c_time_yday  = sstd::yday2time(c_tm.tm_year+1900, c_tm.tm_yday+1);
    printf("GMT: %s\n",   sstd::time2str(c_time_yday).c_str());
    struct tm c_tm_yday = sstd::yday2tm(c_tm.tm_year+1900, c_tm.tm_yday+1);
    printf("GMT: %s\n",   sstd::tm2str(c_tm_yday).c_str());
    printf("\n");

    struct timeval time_sec_micro = sstd::getTimeval();
    printf("timeval: %lf\n",(time_sec_micro.tv_sec)+(time_sec_micro.tv_usec*1.0E-6));

    sstd::print(c_tm_yday);
    sstd::printn(c_tm_yday);
    sstd::printn_all(c_tm_yday);
}

TEST(math, theOthers){
    TEST_time();
}

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

TEST(time, time2tm){
}
TEST(time, tm2time){
}
TEST(time, time2unixday){
}
TEST(time, tm2unixday){
}
TEST(time, tm2str){
}
TEST(time, time2str){
}
TEST(time, timeGm2tmLocal){
}
TEST(time, tmLocal2timeGm){
//  time_t c_time = time(0); // get current time
    time_t c_time = 1619108282;
    // local: 2021-04-23 01:18:02
    // GMT: 2021-04-22 16:18:02

    struct tm c_tm_l   = sstd::timeGm2tmLocal(c_time);
    time_t    c_time_g = sstd::tmLocal2timeGm(c_tm_l);
//  std::string t_l = sstd::ssprintf("local: %s", sstd::tm2str(c_tm_l).c_str());
    std::string t_g = sstd::ssprintf("GMT: %s", sstd::time2str(c_time_g).c_str());

//  ASSERT_STREQ("local: 2021-04-23 01:18:02", t_l.c_str()); // Because of the local time depends on the area defined in the system, this line is difficult to test.
    ASSERT_STREQ("GMT: 2021-04-22 16:18:02",   t_g.c_str());
}
TEST(time, yday2time){
}
TEST(time, yday2tm){
}
TEST(time, getTimeval){
}

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

<|endoftext|>


<commit_before>// C++ General Utility Library (mailto:cgul@zethes.com)
// Copyright (C) 2012-2014, Joshua Brookover and Amber Thrall
// All rights reserved.

/** @file JPEG.cpp
 */

#include "JPEG.hpp"
#include "../Exceptions/ImageException.hpp"
#include "../Utility/File.hpp"
#include "../Utility/Memory.hpp"

#ifndef XMD_H //Fixes broken shit.
#   define XMD_H
#endif

#define boolean bool
extern "C"
{
#   include <jpeglib.h>
}
#undef boolean

struct jpegErrorMgr
{
    struct jpeg_error_mgr pub;
    jmp_buf setjmpBuffer;
};

void jpegErrorExit(j_common_ptr cinfo)
{
    jpegErrorMgr * myErr = (jpegErrorMgr *)cinfo->err;
    (*cinfo->err->output_message)(cinfo);
    longjmp(myErr->setjmpBuffer, 1);
}

_CGUL_EXPORT CGUL::ImageLoaders::JPEG::JPEG() : CGUL::ImageLoader("Joint Photographic Experts Group", "JPG")
{

}

_CGUL_EXPORT CGUL::ImageLoaders::JPEG::~JPEG()
{

}

_CGUL_EXPORT bool CGUL::ImageLoaders::JPEG::CanLoad(const String& file)
{
    Byte header[2];
    File::ReadData(file, header, 2);

    return (header[0] == 0xFF && header[1] == 0xD8);
}

_CGUL_EXPORT void CGUL::ImageLoaders::JPEG::Load(const String& file, Image* image)
{
    jpegErrorMgr jerr;
    struct jpeg_decompress_struct cinfo;

    cinfo.err = jpeg_std_error(&jerr.pub);
    jerr.pub.error_exit = jpegErrorExit;
    if (setjmp(jerr.setjmpBuffer))
    {
        jpeg_destroy_decompress(&cinfo);
        throw ImageException(ImageExceptionCode::JPEG, ImageExceptionReason::UNKNOWN);
    }

#   ifdef MSVC
    FILE* fp;
    fopen_s(&fp, file.GetCString(), "rb");
#   else
    FILE* fp = fopen(file.GetCString(), "rb");
#   endif

    JSAMPARRAY buffer;
    UInt32 rowStride;

    if (!fp)
    {
        throw ImageException(ImageExceptionCode::JPEG, ImageExceptionReason::FAILED_TO_OPEN);
    }

    jpeg_create_decompress(&cinfo);
    jpeg_stdio_src(&cinfo, fp);

    if (jpeg_read_header(&cinfo, TRUE) != JPEG_HEADER_OK)
    {
        throw ImageException(ImageExceptionCode::JPEG, ImageExceptionReason::NOT_A_JPEG_FILE);
    }
    jpeg_start_decompress(&cinfo);
    rowStride = cinfo.output_width * cinfo.output_components;
    buffer = (*cinfo.mem->alloc_sarray)((j_common_ptr) &cinfo, JPOOL_IMAGE, rowStride, 1);

    ImageFormat format;
    int pixelSize = 0;
    if (cinfo.output_components == 3)
    {
        format = ImageFormats::RGB;
        pixelSize = 3;
    }
    else if (cinfo.output_components == 4)
    {
        format = ImageFormats::RGBA;
        pixelSize = 4;
    }
    format.dataType = DataTypes::UNSIGNED_CHAR;

    Byte* data = new Byte[cinfo.output_width * cinfo.output_height * cinfo.output_components];
    UInt32 writeIndex = 0;
    while (cinfo.output_scanline < cinfo.output_height)
    {
        jpeg_read_scanlines(&cinfo, buffer, 1);
        Memory::Copy(&data[writeIndex], buffer[0], rowStride);
        writeIndex += rowStride;
        if (writeIndex >= cinfo.output_width * cinfo.output_height * cinfo.output_components)
            break;
    }

    jpeg_finish_decompress(&cinfo);
    jpeg_destroy_decompress(&cinfo);
    fclose(fp);

    image->Setup(format, UCoord32(cinfo.output_width, cinfo.output_height), (void*)data);
}

_CGUL_EXPORT void CGUL::ImageLoaders::JPEG::Save(const String& file, const Image* image) const
{
     if (image == NULL)
    {
        throw std::runtime_error("No image provided to save.");
    }

    //Open up file.
#   ifdef MSVC
    FILE* fp;
    fopen_s(&fp, file.GetCString(), "wb");
#   else
    FILE* fp = fopen(file.GetCString(), "wb");
#   endif

    if (fp == NULL)
    {
        throw std::runtime_error("Failed to open PNG file for saving.");
    }

    struct jpeg_error_mgr jerr;
    struct jpeg_compress_struct cinfo;

    //Get depth and type.
    UInt32 numComponents;
    J_COLOR_SPACE type;
    if (image->GetFormat() == ImageFormats::RGB)
    {
        numComponents = 3;
        type = JCS_RGB;
    }
    else
    {
        //TODO: Support more?
        fclose(fp);
        throw std::runtime_error("Image's format not supported.");
    }

    cinfo.err = jpeg_std_error(&jerr);
    jpeg_create_compress(&cinfo);
    jpeg_stdio_dest(&cinfo, fp);
    cinfo.image_width = image->GetWidth();
    cinfo.image_height = image->GetHeight();
    cinfo.input_components = numComponents;
    cinfo.in_color_space = type;

    jpeg_set_defaults(&cinfo);
    jpeg_set_quality(&cinfo, 100, TRUE);
    jpeg_start_compress(&cinfo, TRUE);

    UInt32 stride = image->GetWidth() * numComponents;
    while (cinfo.next_scanline < cinfo.image_height)
    {
        unsigned char* data = (unsigned char*)image->GetData< unsigned char >();
        data = data + cinfo.next_scanline * stride;
        JSAMPROW row_pointer = data;
        jpeg_write_scanlines(&cinfo, &row_pointer, 1);
    }

    jpeg_finish_compress(&cinfo);
    jpeg_destroy_compress(&cinfo);

    fclose(fp);
}
<commit_msg>Fixed a compilation issue with jpeg<commit_after>// C++ General Utility Library (mailto:cgul@zethes.com)
// Copyright (C) 2012-2014, Joshua Brookover and Amber Thrall
// All rights reserved.

/** @file JPEG.cpp
 */

#include "JPEG.hpp"
#include "../Exceptions/ImageException.hpp"
#include "../Utility/File.hpp"
#include "../Utility/Memory.hpp"

#ifndef XMD_H //Fixes broken shit.
#   define XMD_H
#endif

#define boolean bool
extern "C"
{
#   include <jpeglib.h>
}
#undef boolean
#include <setjmp.h>
#include <stdlib.h>

struct jpegErrorMgr
{
    struct jpeg_error_mgr pub;
    jmp_buf setjmpBuffer;
};

void jpegErrorExit(j_common_ptr cinfo)
{
    jpegErrorMgr * myErr = (jpegErrorMgr *)cinfo->err;
    (*cinfo->err->output_message)(cinfo);
    longjmp(myErr->setjmpBuffer, 1);
}

_CGUL_EXPORT CGUL::ImageLoaders::JPEG::JPEG() : CGUL::ImageLoader("Joint Photographic Experts Group", "JPG")
{

}

_CGUL_EXPORT CGUL::ImageLoaders::JPEG::~JPEG()
{

}

_CGUL_EXPORT bool CGUL::ImageLoaders::JPEG::CanLoad(const String& file)
{
    Byte header[2];
    File::ReadData(file, header, 2);

    return (header[0] == 0xFF && header[1] == 0xD8);
}

_CGUL_EXPORT void CGUL::ImageLoaders::JPEG::Load(const String& file, Image* image)
{
    jpegErrorMgr jerr;
    struct jpeg_decompress_struct cinfo;

    cinfo.err = jpeg_std_error(&jerr.pub);
    jerr.pub.error_exit = jpegErrorExit;
    if (setjmp(jerr.setjmpBuffer))
    {
        jpeg_destroy_decompress(&cinfo);
        throw ImageException(ImageExceptionCode::JPEG, ImageExceptionReason::UNKNOWN);
    }

#   ifdef MSVC
    FILE* fp;
    fopen_s(&fp, file.GetCString(), "rb");
#   else
    FILE* fp = fopen(file.GetCString(), "rb");
#   endif

    JSAMPARRAY buffer;
    UInt32 rowStride;

    if (!fp)
    {
        throw ImageException(ImageExceptionCode::JPEG, ImageExceptionReason::FAILED_TO_OPEN);
    }

    jpeg_create_decompress(&cinfo);
    jpeg_stdio_src(&cinfo, fp);

    if (jpeg_read_header(&cinfo, TRUE) != JPEG_HEADER_OK)
    {
        throw ImageException(ImageExceptionCode::JPEG, ImageExceptionReason::NOT_A_JPEG_FILE);
    }
    jpeg_start_decompress(&cinfo);
    rowStride = cinfo.output_width * cinfo.output_components;
    buffer = (*cinfo.mem->alloc_sarray)((j_common_ptr) &cinfo, JPOOL_IMAGE, rowStride, 1);

    ImageFormat format;
    int pixelSize = 0;
    if (cinfo.output_components == 3)
    {
        format = ImageFormats::RGB;
        pixelSize = 3;
    }
    else if (cinfo.output_components == 4)
    {
        format = ImageFormats::RGBA;
        pixelSize = 4;
    }
    format.dataType = DataTypes::UNSIGNED_CHAR;

    Byte* data = new Byte[cinfo.output_width * cinfo.output_height * cinfo.output_components];
    UInt32 writeIndex = 0;
    while (cinfo.output_scanline < cinfo.output_height)
    {
        jpeg_read_scanlines(&cinfo, buffer, 1);
        Memory::Copy(&data[writeIndex], buffer[0], rowStride);
        writeIndex += rowStride;
        if (writeIndex >= cinfo.output_width * cinfo.output_height * cinfo.output_components)
            break;
    }

    jpeg_finish_decompress(&cinfo);
    jpeg_destroy_decompress(&cinfo);
    fclose(fp);

    image->Setup(format, UCoord32(cinfo.output_width, cinfo.output_height), (void*)data);
}

_CGUL_EXPORT void CGUL::ImageLoaders::JPEG::Save(const String& file, const Image* image) const
{
     if (image == NULL)
    {
        throw std::runtime_error("No image provided to save.");
    }

    //Open up file.
#   ifdef MSVC
    FILE* fp;
    fopen_s(&fp, file.GetCString(), "wb");
#   else
    FILE* fp = fopen(file.GetCString(), "wb");
#   endif

    if (fp == NULL)
    {
        throw std::runtime_error("Failed to open PNG file for saving.");
    }

    struct jpeg_error_mgr jerr;
    struct jpeg_compress_struct cinfo;

    //Get depth and type.
    UInt32 numComponents;
    J_COLOR_SPACE type;
    if (image->GetFormat() == ImageFormats::RGB)
    {
        numComponents = 3;
        type = JCS_RGB;
    }
    else
    {
        //TODO: Support more?
        fclose(fp);
        throw std::runtime_error("Image's format not supported.");
    }

    cinfo.err = jpeg_std_error(&jerr);
    jpeg_create_compress(&cinfo);
    jpeg_stdio_dest(&cinfo, fp);
    cinfo.image_width = image->GetWidth();
    cinfo.image_height = image->GetHeight();
    cinfo.input_components = numComponents;
    cinfo.in_color_space = type;

    jpeg_set_defaults(&cinfo);
    jpeg_set_quality(&cinfo, 100, TRUE);
    jpeg_start_compress(&cinfo, TRUE);

    UInt32 stride = image->GetWidth() * numComponents;
    while (cinfo.next_scanline < cinfo.image_height)
    {
        unsigned char* data = (unsigned char*)image->GetData< unsigned char >();
        data = data + cinfo.next_scanline * stride;
        JSAMPROW row_pointer = data;
        jpeg_write_scanlines(&cinfo, &row_pointer, 1);
    }

    jpeg_finish_compress(&cinfo);
    jpeg_destroy_compress(&cinfo);

    fclose(fp);
}
<|endoftext|>


<commit_before>#pragma once

#include <vector>
#include <string>

#if defined(_WIN32) || defined(WIN32) || defined(_MSC_VER)
#define ARBITER_WINDOWS
#endif

#ifndef ARBITER_IS_AMALGAMATION
#include <arbiter/endpoint.hpp>
#include <arbiter/driver.hpp>
#include <arbiter/drivers/dropbox.hpp>
#include <arbiter/drivers/fs.hpp>
#include <arbiter/drivers/google.hpp>
#include <arbiter/drivers/http.hpp>
#include <arbiter/drivers/s3.hpp>
#include <arbiter/drivers/test.hpp>
#include <arbiter/util/exports.hpp>
#include <arbiter/util/types.hpp>
#include <arbiter/util/util.hpp>

#ifndef ARBITER_EXTERNAL_JSON
#include <arbiter/third/json/json.hpp>
#endif

#endif

#ifdef ARBITER_EXTERNAL_JSON
#include <json/json.h>
#endif

#ifdef ARBITER_CUSTOM_NAMESPACE
namespace ARBITER_CUSTOM_NAMESPACE
{
#endif

namespace arbiter
{

namespace http { class Pool; }

/** @brief The primary interface for storage abstraction.
 *
 * The Arbiter is the primary layer of abstraction for all supported Driver
 * instances, allowing remote paths to be treated as a simple filesystem or
 * key-value store.  Routing to specialized drivers is based on a substring
 * comparison of an incoming path's delimited type, for example
 * `http://arbiter.io/data.txt` would route to the HTTP driver and
 * `s3://my-bucket/data.txt` would route to the S3 driver.  Paths containing
 * no prefixed type information are routed to the filesystem driver.
 *
 * All Arbiter operations are thread-safe except unless otherwise noted.
 */
class ARBITER_DLL Arbiter
{
public:
    /** Construct a basic Arbiter with only drivers the don't require
     * external configuration parameters.
     */
    ARBITER_DLL Arbiter();

    /** @brief Construct an Arbiter with driver configurations. */
    ARBITER_DLL Arbiter(const Json::Value& json);

    /** True if a Driver has been registered for this file type. */
    ARBITER_DLL bool hasDriver(std::string path) const;

    /** @brief Add a custom driver for the supplied type.
     *
     * After this operation completes, future requests into arbiter beginning
     * with the prefix @p type followed by the delimiter `://` will be routed
     * to the supplied @p driver.  If a Driver of type @p type already exists,
     * the supplied @p driver will replace it.
     *
     * This operation will throw ArbiterError if @p driver is empty.
     *
     * @note This operation is not thread-safe.
     */
    ARBITER_DLL void addDriver(
            std::string type,
            std::unique_ptr<Driver> driver);

    /** Get data or throw if inaccessible. */
    ARBITER_DLL std::string get(std::string path) const;

    /** Get data if accessible. */
    ARBITER_DLL std::unique_ptr<std::string> tryGet(std::string path) const;

    /** Get data in binary form or throw if inaccessible. */
    ARBITER_DLL std::vector<char> getBinary(std::string path) const;

    /** Get data in binary form if accessible. */
    ARBITER_DLL std::unique_ptr<std::vector<char>> tryGetBinary(
            std::string path) const;

    /** Get file size in bytes or throw if inaccessible. */
    ARBITER_DLL std::size_t getSize(std::string path) const;

    /** Get file size in bytes if accessible. */
    ARBITER_DLL std::unique_ptr<std::size_t> tryGetSize(std::string path) const;

    /** Write data to path. */
    ARBITER_DLL void put(std::string path, const std::string& data) const;

    /** Write data to path. */
    ARBITER_DLL void put(std::string path, const std::vector<char>& data) const;

    /** Get data with additional HTTP-specific parameters.  Throws if
     * isHttpDerived is false for this path. */
    ARBITER_DLL std::string get(
            std::string path,
            http::Headers headers,
            http::Query query = http::Query()) const;

    /** Get data with additional HTTP-specific parameters.  Throws if
     * isHttpDerived is false for this path. */
    ARBITER_DLL std::unique_ptr<std::string> tryGet(
            std::string path,
            http::Headers headers,
            http::Query query = http::Query()) const;

    /** Get data in binary form with additional HTTP-specific parameters.
     * Throws if isHttpDerived is false for this path. */
    ARBITER_DLL std::vector<char> getBinary(
            std::string path,
            http::Headers headers,
            http::Query query = http::Query()) const;

    /** Get data in binary form with additional HTTP-specific parameters.
     * Throws if isHttpDerived is false for this path. */
    ARBITER_DLL std::unique_ptr<std::vector<char>> tryGetBinary(
            std::string path,
            http::Headers headers,
            http::Query query = http::Query()) const;

    /** Write data to path with additional HTTP-specific parameters.
     * Throws if isHttpDerived is false for this path. */
    ARBITER_DLL void put(
            std::string path,
            const std::string& data,
            http::Headers headers,
            http::Query query = http::Query()) const;

    /** Write data to path with additional HTTP-specific parameters.
     * Throws if isHttpDerived is false for this path. */
    ARBITER_DLL void put(
            std::string path,
            const std::vector<char>& data,
            http::Headers headers,
            http::Query query = http::Query()) const;

    /** Copy data from @p src to @p dst.  @p src will be resolved with
     * Arbiter::resolve prior to the copy, so globbed directories are supported.
     * If @p src ends with a slash, it will be resolved with a recursive glob,
     * in which case any nested directory structure will be recreated in @p dst.
     *
     * If @p dst is a filesystem path, fs::mkdirp will be called prior to the
     * start of copying.  If @p src is a recursive glob, `fs::mkdirp` will
     * be repeatedly called during copying to ensure that any nested directories
     * are reproduced.
     */
    ARBITER_DLL void copy(
            std::string src,
            std::string dst,
            bool verbose = false) const;

    /** Copy the single file @p file to the destination @p to.  If @p to ends
     * with a `/` or '\' character, then @p file will be copied into the
     * directory @p to with the basename of @p file.  If @p to does not end
     * with a slash character, then @p to will be interpreted as a file path.
     *
     * If @p to is a local filesystem path, then `fs::mkdirp` will be called
     * prior to copying.
     */
    ARBITER_DLL void copyFile(
            std::string file,
            std::string to,
            bool verbose = false) const;

    /** Returns true if this path is a remote path, or false if it is on the
     * local filesystem.
     */
    ARBITER_DLL bool isRemote(std::string path) const;

    /** Returns true if this path is on the local filesystem, or false if it is
     * remote.
     */
    ARBITER_DLL bool isLocal(std::string path) const;

    /** Returns true if this path exists.  Equivalent to:
     * @code
     * tryGetSize(path).get() != nullptr
     * @endcode
     *
     * @note This means that an existing file of size zero will return true.
     */
    ARBITER_DLL bool exists(std::string path) const;

    /** Returns true if the protocol for this driver is build on HTTP, like the
     * S3 and Dropbox drivers are.  If this returns true, http::Headers and
     * http::Query parameter methods may be used for this path.
     */
    ARBITER_DLL bool isHttpDerived(std::string path) const;

    /** @brief Resolve a possibly globbed path.
     *
     * If @p path ends with `*`, then this operation will attempt to
     * non-recursively glob all files matching the given wildcard.  Directories
     * matching the wildcard and their contents are not returned.
     *
     * Examples:
     * @code
     * // Returns all files in `~/data`.  A directory `~/data/dir/` and its
     * // contents would not be returned since this is non-recursive.
     * a.resolve("~\data\*");
     *
     * // Returns all files matching `prefix-*` in bucket `my-bucket`.  An
     * // object `s3://my-bucket/prefix-123/hello.txt` would not be returned,
     * // but object `s3://my-bucket/prefix-456.txt` would.
     * a.resolve("s3://my-bucket/prefix-*");
     * @endcode
     *
     * @note Throws ArbiterError if the selected driver does not support
     * globbing, for example the HTTP driver.
     *
     * @param path Path to search, may be a directory or file.  Globbing
     * will only occur in the case of a directory.
     *
     * @param verbose If true, driver-specific status information may be
     * printed to STDOUT during globbing.
     *
     * @return  If @p path ends with `*`, the results are the contents of the
     * resulting non-recursive resolution of this path.  Otherwise, the results
     * are a vector of size one containing only @p path itself, unaltered.
     */
    ARBITER_DLL std::vector<std::string> resolve(
            std::string path,
            bool verbose = false) const;

    /** @brief Get a reusable Endpoint for this root directory. */
    ARBITER_DLL Endpoint getEndpoint(std::string root) const;

    /** Returns the Driver, if one can be found, for the given @p path.  The
     * driver type is determined from the @p path substring prior to the
     * delimiter `://`.  If this delimiter does not exist, then the filesystem
     * driver is returned.  If the delimiter exists but a corresponding driver
     * type is not found, ArbiterError is thrown.
     *
     * Optionally, filesystem paths may be explicitly prefixed with `file://`.
     */
    ARBITER_DLL const Driver& getDriver(std::string path) const;

    /** @brief Get a fs::LocalHandle to a possibly remote file.
     *
     * If @p path is remote (see Arbiter::isRemote), this operation will fetch
     * the file contents and write them to the local filesystem in the
     * directory represented by @p tmpEndpoint.  The contents of @p path are
     * not copied if @p path is already local.
     *
     * There are no filename guarantees if @p path is remote.  Use
     * LocalHandle::localPath to determine this.
     *
     * @note This operation will throw an ArbiterError if the path is remote
     * and @p tmpEndpoint is also remote.
     *
     * @param path Possibly remote path to fetch.
     *
     * @param tempEndpoint If @path is remote, the local copy will be created
     * at this Endpoint.
     *
     * @return A fs::LocalHandle for local access to the resulting file.
     */
    ARBITER_DLL std::unique_ptr<fs::LocalHandle> getLocalHandle(
            std::string path,
            const Endpoint& tempEndpoint) const;

    /** @brief Get a fs::LocalHandle to a possibly remote file.
     *
     * If @p tempPath is not specified, the environment will be searched for a
     * temporary location.
     */
    ARBITER_DLL std::unique_ptr<fs::LocalHandle> getLocalHandle(
            std::string path,
            std::string tempPath = "") const;

    /** If no delimiter of "://" is found, returns "file".  Otherwise, returns
     * the substring prior to but not including this delimiter.
     */
    static std::string getType(std::string path);

    /** Strip the type and delimiter `://`, if they exist. */
    static std::string stripType(std::string path);

    /** Get the characters following the final instance of '.', or an empty
     * string if there are no '.' characters. */
    static std::string getExtension(std::string path);

    /** Strip the characters following (and including) the final instance of
     * '.' if one exists, otherwise return the full path. */
    static std::string stripExtension(std::string path);

    /** Fetch the common HTTP pool, which may be useful when dynamically
     * constructing adding a Driver via Arbiter::addDriver.
     */
    ARBITER_DLL http::Pool& httpPool() { return *m_pool; }

private:
    const drivers::Http* tryGetHttpDriver(std::string path) const;
    const drivers::Http& getHttpDriver(std::string path) const;

    DriverMap m_drivers;
    std::unique_ptr<http::Pool> m_pool;
};

} // namespace arbiter

#ifdef ARBITER_CUSTOM_NAMESPACE
}
#endif
<commit_msg>Exporting.<commit_after>#pragma once

#include <vector>
#include <string>

#if defined(_WIN32) || defined(WIN32) || defined(_MSC_VER)
#define ARBITER_WINDOWS
#endif

#ifndef ARBITER_IS_AMALGAMATION
#include <arbiter/endpoint.hpp>
#include <arbiter/driver.hpp>
#include <arbiter/drivers/dropbox.hpp>
#include <arbiter/drivers/fs.hpp>
#include <arbiter/drivers/google.hpp>
#include <arbiter/drivers/http.hpp>
#include <arbiter/drivers/s3.hpp>
#include <arbiter/drivers/test.hpp>
#include <arbiter/util/exports.hpp>
#include <arbiter/util/types.hpp>
#include <arbiter/util/util.hpp>

#ifndef ARBITER_EXTERNAL_JSON
#include <arbiter/third/json/json.hpp>
#endif

#endif

#ifdef ARBITER_EXTERNAL_JSON
#include <json/json.h>
#endif

#ifdef ARBITER_CUSTOM_NAMESPACE
namespace ARBITER_CUSTOM_NAMESPACE
{
#endif

namespace arbiter
{

namespace http { class Pool; }

/** @brief The primary interface for storage abstraction.
 *
 * The Arbiter is the primary layer of abstraction for all supported Driver
 * instances, allowing remote paths to be treated as a simple filesystem or
 * key-value store.  Routing to specialized drivers is based on a substring
 * comparison of an incoming path's delimited type, for example
 * `http://arbiter.io/data.txt` would route to the HTTP driver and
 * `s3://my-bucket/data.txt` would route to the S3 driver.  Paths containing
 * no prefixed type information are routed to the filesystem driver.
 *
 * All Arbiter operations are thread-safe except unless otherwise noted.
 */
class ARBITER_DLL Arbiter
{
public:
    /** Construct a basic Arbiter with only drivers the don't require
     * external configuration parameters.
     */
    Arbiter();

    /** @brief Construct an Arbiter with driver configurations. */
    Arbiter(const Json::Value& json);

    /** True if a Driver has been registered for this file type. */
    bool hasDriver(std::string path) const;

    /** @brief Add a custom driver for the supplied type.
     *
     * After this operation completes, future requests into arbiter beginning
     * with the prefix @p type followed by the delimiter `://` will be routed
     * to the supplied @p driver.  If a Driver of type @p type already exists,
     * the supplied @p driver will replace it.
     *
     * This operation will throw ArbiterError if @p driver is empty.
     *
     * @note This operation is not thread-safe.
     */
    void addDriver(
            std::string type,
            std::unique_ptr<Driver> driver);

    /** Get data or throw if inaccessible. */
    std::string get(std::string path) const;

    /** Get data if accessible. */
    std::unique_ptr<std::string> tryGet(std::string path) const;

    /** Get data in binary form or throw if inaccessible. */
    std::vector<char> getBinary(std::string path) const;

    /** Get data in binary form if accessible. */
    std::unique_ptr<std::vector<char>> tryGetBinary(
            std::string path) const;

    /** Get file size in bytes or throw if inaccessible. */
    std::size_t getSize(std::string path) const;

    /** Get file size in bytes if accessible. */
    std::unique_ptr<std::size_t> tryGetSize(std::string path) const;

    /** Write data to path. */
    void put(std::string path, const std::string& data) const;

    /** Write data to path. */
    void put(std::string path, const std::vector<char>& data) const;

    /** Get data with additional HTTP-specific parameters.  Throws if
     * isHttpDerived is false for this path. */
    std::string get(
            std::string path,
            http::Headers headers,
            http::Query query = http::Query()) const;

    /** Get data with additional HTTP-specific parameters.  Throws if
     * isHttpDerived is false for this path. */
    std::unique_ptr<std::string> tryGet(
            std::string path,
            http::Headers headers,
            http::Query query = http::Query()) const;

    /** Get data in binary form with additional HTTP-specific parameters.
     * Throws if isHttpDerived is false for this path. */
    std::vector<char> getBinary(
            std::string path,
            http::Headers headers,
            http::Query query = http::Query()) const;

    /** Get data in binary form with additional HTTP-specific parameters.
     * Throws if isHttpDerived is false for this path. */
    std::unique_ptr<std::vector<char>> tryGetBinary(
            std::string path,
            http::Headers headers,
            http::Query query = http::Query()) const;

    /** Write data to path with additional HTTP-specific parameters.
     * Throws if isHttpDerived is false for this path. */
    void put(
            std::string path,
            const std::string& data,
            http::Headers headers,
            http::Query query = http::Query()) const;

    /** Write data to path with additional HTTP-specific parameters.
     * Throws if isHttpDerived is false for this path. */
    void put(
            std::string path,
            const std::vector<char>& data,
            http::Headers headers,
            http::Query query = http::Query()) const;

    /** Copy data from @p src to @p dst.  @p src will be resolved with
     * Arbiter::resolve prior to the copy, so globbed directories are supported.
     * If @p src ends with a slash, it will be resolved with a recursive glob,
     * in which case any nested directory structure will be recreated in @p dst.
     *
     * If @p dst is a filesystem path, fs::mkdirp will be called prior to the
     * start of copying.  If @p src is a recursive glob, `fs::mkdirp` will
     * be repeatedly called during copying to ensure that any nested directories
     * are reproduced.
     */
    void copy(
            std::string src,
            std::string dst,
            bool verbose = false) const;

    /** Copy the single file @p file to the destination @p to.  If @p to ends
     * with a `/` or '\' character, then @p file will be copied into the
     * directory @p to with the basename of @p file.  If @p to does not end
     * with a slash character, then @p to will be interpreted as a file path.
     *
     * If @p to is a local filesystem path, then `fs::mkdirp` will be called
     * prior to copying.
     */
    void copyFile(
            std::string file,
            std::string to,
            bool verbose = false) const;

    /** Returns true if this path is a remote path, or false if it is on the
     * local filesystem.
     */
    bool isRemote(std::string path) const;

    /** Returns true if this path is on the local filesystem, or false if it is
     * remote.
     */
    bool isLocal(std::string path) const;

    /** Returns true if this path exists.  Equivalent to:
     * @code
     * tryGetSize(path).get() != nullptr
     * @endcode
     *
     * @note This means that an existing file of size zero will return true.
     */
    bool exists(std::string path) const;

    /** Returns true if the protocol for this driver is build on HTTP, like the
     * S3 and Dropbox drivers are.  If this returns true, http::Headers and
     * http::Query parameter methods may be used for this path.
     */
    bool isHttpDerived(std::string path) const;

    /** @brief Resolve a possibly globbed path.
     *
     * If @p path ends with `*`, then this operation will attempt to
     * non-recursively glob all files matching the given wildcard.  Directories
     * matching the wildcard and their contents are not returned.
     *
     * Examples:
     * @code
     * // Returns all files in `~/data`.  A directory `~/data/dir/` and its
     * // contents would not be returned since this is non-recursive.
     * a.resolve("~\data\*");
     *
     * // Returns all files matching `prefix-*` in bucket `my-bucket`.  An
     * // object `s3://my-bucket/prefix-123/hello.txt` would not be returned,
     * // but object `s3://my-bucket/prefix-456.txt` would.
     * a.resolve("s3://my-bucket/prefix-*");
     * @endcode
     *
     * @note Throws ArbiterError if the selected driver does not support
     * globbing, for example the HTTP driver.
     *
     * @param path Path to search, may be a directory or file.  Globbing
     * will only occur in the case of a directory.
     *
     * @param verbose If true, driver-specific status information may be
     * printed to STDOUT during globbing.
     *
     * @return  If @p path ends with `*`, the results are the contents of the
     * resulting non-recursive resolution of this path.  Otherwise, the results
     * are a vector of size one containing only @p path itself, unaltered.
     */
    std::vector<std::string> resolve(
            std::string path,
            bool verbose = false) const;

    /** @brief Get a reusable Endpoint for this root directory. */
    Endpoint getEndpoint(std::string root) const;

    /** Returns the Driver, if one can be found, for the given @p path.  The
     * driver type is determined from the @p path substring prior to the
     * delimiter `://`.  If this delimiter does not exist, then the filesystem
     * driver is returned.  If the delimiter exists but a corresponding driver
     * type is not found, ArbiterError is thrown.
     *
     * Optionally, filesystem paths may be explicitly prefixed with `file://`.
     */
    const Driver& getDriver(std::string path) const;

    /** @brief Get a fs::LocalHandle to a possibly remote file.
     *
     * If @p path is remote (see Arbiter::isRemote), this operation will fetch
     * the file contents and write them to the local filesystem in the
     * directory represented by @p tmpEndpoint.  The contents of @p path are
     * not copied if @p path is already local.
     *
     * There are no filename guarantees if @p path is remote.  Use
     * LocalHandle::localPath to determine this.
     *
     * @note This operation will throw an ArbiterError if the path is remote
     * and @p tmpEndpoint is also remote.
     *
     * @param path Possibly remote path to fetch.
     *
     * @param tempEndpoint If @path is remote, the local copy will be created
     * at this Endpoint.
     *
     * @return A fs::LocalHandle for local access to the resulting file.
     */
    std::unique_ptr<fs::LocalHandle> getLocalHandle(
            std::string path,
            const Endpoint& tempEndpoint) const;

    /** @brief Get a fs::LocalHandle to a possibly remote file.
     *
     * If @p tempPath is not specified, the environment will be searched for a
     * temporary location.
     */
    std::unique_ptr<fs::LocalHandle> getLocalHandle(
            std::string path,
            std::string tempPath = "") const;

    /** If no delimiter of "://" is found, returns "file".  Otherwise, returns
     * the substring prior to but not including this delimiter.
     */
    static std::string getType(std::string path);

    /** Strip the type and delimiter `://`, if they exist. */
    static std::string stripType(std::string path);

    /** Get the characters following the final instance of '.', or an empty
     * string if there are no '.' characters. */
    static std::string getExtension(std::string path);

    /** Strip the characters following (and including) the final instance of
     * '.' if one exists, otherwise return the full path. */
    static std::string stripExtension(std::string path);

    /** Fetch the common HTTP pool, which may be useful when dynamically
     * constructing adding a Driver via Arbiter::addDriver.
     */
    http::Pool& httpPool() { return *m_pool; }

private:
    const drivers::Http* tryGetHttpDriver(std::string path) const;
    const drivers::Http& getHttpDriver(std::string path) const;

    DriverMap m_drivers;
    std::unique_ptr<http::Pool> m_pool;
};

} // namespace arbiter

#ifdef ARBITER_CUSTOM_NAMESPACE
}
#endif
<|endoftext|>


<commit_before>//  Natron
//
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
/*
 *Created by Alexandre GAUTHIER-FOICHAT on 6/1/2012.
 *contact: immarespond at gmail dot com
 *
 */

#include "Engine/FrameEntry.h"
#include "Engine/FrameParams.h"

using namespace Natron;

FrameKey::FrameKey()
: KeyHelper<U64>()
, _time(0)
, _treeVersion(0)
, _gain(0)
, _lut(0)
, _bitDepth(0)
, _channels(0)
, _view(0)
, _textureRect()
, _scale()
{
    _scale.x = _scale.y = 0.;
}

FrameKey::FrameKey(SequenceTime time,U64 treeVersion,double gain,
         int lut,int bitDepth,int channels,int view,const TextureRect& textureRect,const RenderScale& scale,const std::string& inputName):
KeyHelper<U64>()
,_time(time)
,_treeVersion(treeVersion)
,_gain(gain)
,_lut(lut)
,_bitDepth(bitDepth)
,_channels(channels)
,_view(view)
,_textureRect(textureRect)
,_scale(scale)
,_inputName(inputName)
{

}

void FrameKey::fillHash(Hash64* hash) const {
    hash->append(_time);
    hash->append(_treeVersion);
    hash->append(_gain);
    hash->append(_lut);
    hash->append(_bitDepth);
    hash->append(_channels);
    hash->append(_view);
    hash->append(_textureRect.x1);
    hash->append(_textureRect.y1);
    hash->append(_textureRect.x2);
    hash->append(_textureRect.y2);
    hash->append(_textureRect.w);
    hash->append(_textureRect.h);
    hash->append(_textureRect.closestPo2);
    hash->append(_scale.x);
    hash->append(_scale.y);
    for (size_t i = 0; i < _inputName.size(); ++i) {
        hash->append(_inputName.at(i));
    }
}

bool FrameKey::operator==(const FrameKey& other) const {
    return  _time == other._time &&
    _treeVersion == other._treeVersion &&
    _gain == other._gain &&
    _lut == other._lut &&
    _bitDepth == other._bitDepth &&
    _channels == other._channels &&
    _view == other._view &&
    _textureRect == other._textureRect &&
    _scale.x == other._scale.x &&
    _scale.y == other._scale.y &&
    _inputName == other._inputName;
}

FrameKey FrameEntry::makeKey(SequenceTime time,U64 treeVersion,double gain,
                        int lut,int bitDepth,int channels,int view,const TextureRect& textureRect,
                             const RenderScale& scale,const std::string& inputName){
    return FrameKey(time,treeVersion,gain,lut,bitDepth,channels,view,textureRect,scale,inputName);
}

boost::shared_ptr<const FrameParams> FrameEntry::makeParams(const RectI rod,int bitDepth,int texW,int texH)
{
    return boost::shared_ptr<const FrameParams>(new FrameParams(rod,bitDepth,texW,texH));
}

<commit_msg>FrameEntry: format<commit_after>//  Natron
//
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
/*
 *Created by Alexandre GAUTHIER-FOICHAT on 6/1/2012.
 *contact: immarespond at gmail dot com
 *
 */

#include "Engine/FrameEntry.h"
#include "Engine/FrameParams.h"

using namespace Natron;

FrameKey::FrameKey()
: KeyHelper<U64>()
, _time(0)
, _treeVersion(0)
, _gain(0)
, _lut(0)
, _bitDepth(0)
, _channels(0)
, _view(0)
, _textureRect()
, _scale()
{
    _scale.x = _scale.y = 0.;
}

FrameKey::FrameKey(SequenceTime time,
                   U64 treeVersion,
                   double gain,
                   int lut,
                   int bitDepth,
                   int channels,
                   int view,
                   const TextureRect& textureRect,
                   const RenderScale& scale,
                   const std::string& inputName)
: KeyHelper<U64>()
, _time(time)
, _treeVersion(treeVersion)
, _gain(gain)
, _lut(lut)
, _bitDepth(bitDepth)
, _channels(channels)
, _view(view)
, _textureRect(textureRect)
, _scale(scale)
, _inputName(inputName)
{

}

void
FrameKey::fillHash(Hash64* hash) const
{
    hash->append(_time);
    hash->append(_treeVersion);
    hash->append(_gain);
    hash->append(_lut);
    hash->append(_bitDepth);
    hash->append(_channels);
    hash->append(_view);
    hash->append(_textureRect.x1);
    hash->append(_textureRect.y1);
    hash->append(_textureRect.x2);
    hash->append(_textureRect.y2);
    hash->append(_textureRect.w);
    hash->append(_textureRect.h);
    hash->append(_textureRect.closestPo2);
    hash->append(_scale.x);
    hash->append(_scale.y);
    for (size_t i = 0; i < _inputName.size(); ++i) {
        hash->append(_inputName.at(i));
    }
}

bool
FrameKey::operator==(const FrameKey& other) const
{
    return  _time == other._time &&
    _treeVersion == other._treeVersion &&
    _gain == other._gain &&
    _lut == other._lut &&
    _bitDepth == other._bitDepth &&
    _channels == other._channels &&
    _view == other._view &&
    _textureRect == other._textureRect &&
    _scale.x == other._scale.x &&
    _scale.y == other._scale.y &&
    _inputName == other._inputName;
}

FrameKey
FrameEntry::makeKey(SequenceTime time,
                    U64 treeVersion,
                    double gain,
                    int lut,
                    int bitDepth,
                    int channels,
                    int view,
                    const TextureRect& textureRect,
                    const RenderScale& scale,
                    const std::string& inputName)
{
    return FrameKey(time,treeVersion,gain,lut,bitDepth,channels,view,textureRect,scale,inputName);
}

boost::shared_ptr<const FrameParams>
FrameEntry::makeParams(const RectI rod,
                       int bitDepth,
                       int texW,
                       int texH)
{
    return boost::shared_ptr<const FrameParams>(new FrameParams(rod,bitDepth,texW,texH));
}

<|endoftext|>