<commit_before>//#include <mavros/RCIn.h>
#include <mavros/mavros_plugin.h>
#include <pluginlib/class_list_macros.h>

#include "mavros/OverrideRCIn.h"

#include <guidance_node_amsl/Directive.h>
#include <guidance_node_amsl/Position.h>
#include <mms/Ack_arm.h>
#include <mms/Arm.h>
#include <mms/Sys_status.h>

namespace mavplugin {
/**
 * @brief Mavros plugin
 */
class UniboControllerAMSLPlugin : public MavRosPlugin {
public:
	UniboControllerAMSLPlugin() :
		nodeHandle(),
		uas(nullptr),
		safetyOn(true),
		v_xy_max(3.0),
		v_z_max(1.5),
		v_psi_max(3.14)
	{};

	void initialize(UAS &uas_)
	{
		uas = &uas_;

		directive_sub = nodeHandle.subscribe("/directive", 10, &UniboControllerAMSLPlugin::directive_cb, this);
		position_pub = nodeHandle.advertise<guidance_node_amsl::Position>("/position", 10);
		arm_sub = nodeHandle.subscribe("/arm", 10, &UniboControllerAMSLPlugin::arming, this);
		arm_ack_pub = nodeHandle.advertise<mms::Ack_arm>("acknowledge_arming", 10);
		//velocity_publisher_=nodeHandle.advertise<mavros::OverrideRCIn>("mavros/rc/override", 10);
		sys_status_pub = nodeHandle.advertise<mms::Sys_status>("/system_status", 10);

		nodeHandle.param("guidance_node_amsl/param/sat_xy", v_xy_max, 3.0);
		nodeHandle.param("guidance_node_amsl/param/sat_z", v_z_max, 1.5);
		nodeHandle.param("guidance_node_amsl/param/sat_yaw", v_psi_max, 3.14);

		//DEBUG
//		ROS_INFO("INITIALIZE UNIBO PLUGIN");
	}

	//should be logic mapping between id number and message type
	const message_map get_rx_handlers() {
		return {
			MESSAGE_HANDLER(MAVLINK_MSG_ID_GLOBAL_POSITION_INT, &UniboControllerAMSLPlugin::handle_global_position_int),
			MESSAGE_HANDLER(MAVLINK_MSG_ID_ATTITUDE, &UniboControllerAMSLPlugin::handle_attitude),
			MESSAGE_HANDLER(MAVLINK_MSG_ID_RC_CHANNELS_RAW, &UniboControllerAMSLPlugin::handle_rc_channels_raw),
			MESSAGE_HANDLER(MAVLINK_MSG_ID_COMMAND_ACK, &UniboControllerAMSLPlugin::handle_arm_ack),
			MESSAGE_HANDLER(MAVLINK_MSG_ID_HEARTBEAT, &UniboControllerAMSLPlugin::handle_heartbeat),
			MESSAGE_HANDLER(MAVLINK_MSG_ID_SYS_STATUS, &UniboControllerAMSLPlugin::handle_status)
		};
	}

private:
	ros::NodeHandle nodeHandle;
	UAS *uas;

	ros::Publisher position_pub;
	ros::Subscriber directive_sub;
	//ros::Publisher velocity_publisher_;
	ros::Subscriber arm_sub;
	ros::Publisher arm_ack_pub;
	ros::Publisher sys_status_pub;

	mms::Sys_status _system_status;

	//message to move the quadcopter
	mavros::OverrideRCIn velocity_;

	//common message to join data from handles
	guidance_node_amsl::Position commonMessage;

	//safety flag
	bool safetyOn;

	//saturation parameters
	/*
	 * Questi tipi di dato sono matlab per specifiche ros del param server.
	 * Nel nodo "guidance_node" sono convertiti a float perchè la legge di guida matlab ha come input
	 * dei float. Adesso non sono convertiti perchè tanto possono essere usati così
	 */
	double v_xy_max, v_z_max, v_psi_max;

	//check if safety is on
	void handle_rc_channels_raw(const mavlink_message_t *msg, uint8_t sysid, uint8_t compid) {

		mavlink_rc_channels_raw_t channels_raw;
		mavlink_msg_rc_channels_raw_decode(msg,&channels_raw);

		/*
		 * If safety is on, chan5_raw must be less than 1200
		 */
		//DEBUG
		//ROS_INFO("CHANNEL 6 IS: %u",channels_raw.chan6_raw);
		if(channels_raw.chan6_raw > 1800){
			safetyOn = false;
			commonMessage.Safety = 0;
		}
		else {
			safetyOn=true;
			commonMessage.Safety= 1;
		}

		//DEBUG
//		ROS_INFO("HANDLE RC RAW");

	}

	void handle_attitude(const mavlink_message_t *msg, uint8_t sysid, uint8_t compid) {

		mavlink_attitude_t attitude;
		mavlink_msg_attitude_decode(msg, &attitude);

		auto position_msg = boost::make_shared<guidance_node_amsl::Position>();

		//getting new data
		position_msg->Yawangle=attitude.yaw;

		//copying data from commonMessage
		position_msg->Timestamp=commonMessage.Timestamp;
		position_msg->AltitudeRelative=commonMessage.AltitudeRelative;
		position_msg->AltitudeAMSL=commonMessage.AltitudeAMSL;
		position_msg->Latitude=commonMessage.Latitude;
		position_msg->Longitude=commonMessage.Longitude;
		position_msg->Safety = commonMessage.Safety;

		//saving data
		commonMessage.Yawangle=attitude.yaw;

		//DEBUG
//		ROS_INFO("%f", commonMessage.Yawangle);

		position_pub.publish(position_msg);
	}

	void handle_heartbeat(const mavlink_message_t *msg, uint8_t sysid, uint8_t compid) {

		mavlink_heartbeat_t heart;
		mavlink_msg_heartbeat_decode(msg, &heart);

		//auto position_msg = boost::make_shared<guidance_node_amsl::Position>();
		//ROS_INFO("Heatbeat. Base Mode: %d - Sys Status: %d ",heart.base_mode, heart.system_status);
		if (heart.base_mode >= 128)	_system_status.armed = true;
		else	_system_status.armed = false;
		sys_status_pub.publish(_system_status);
	}

	void handle_status(const mavlink_message_t *msg, uint8_t sysid, uint8_t compid) {
		mavlink_sys_status_t status;
		mavlink_msg_sys_status_decode(msg, &status);
		//ROS_INFO("Received sys status mavlink. Battery: %d", status.voltage_battery);

		_system_status.voltage_battery = status.voltage_battery;
		sys_status_pub.publish(_system_status);
	}

	void handle_arm_ack(const mavlink_message_t *msg, uint8_t sysid, uint8_t compid) {

		mavlink_command_ack_t cmd_ack;
		mavlink_msg_command_ack_decode(msg, &cmd_ack);

		auto arm_ack_msg = boost::make_shared<mms::Ack_arm>();

		if (cmd_ack.command == 400){      //ARM_DISARM command
			ROS_INFO("Received arm_disarm");
			if (cmd_ack.result == MAV_RESULT_ACCEPTED){
				arm_ack_msg->mav_result = true;
				ROS_INFO("Arm-disarm: succsessful");
			} else {
				arm_ack_msg->mav_result = false;
				ROS_INFO("Arm-disarm: fail");
			}
			arm_ack_pub.publish(arm_ack_msg);
		}
	}

	void handle_global_position_int(const mavlink_message_t *msg, uint8_t sysid, uint8_t compid) {

		mavlink_global_position_int_t global_position;
		mavlink_msg_global_position_int_decode(msg, &global_position);

		auto position_msg = boost::make_shared<guidance_node_amsl::Position>();

		//getting new data
		position_msg->Timestamp=global_position.time_boot_ms;
		position_msg->AltitudeRelative=global_position.relative_alt;
		position_msg->AltitudeAMSL = global_position.alt;
		position_msg->Latitude=global_position.lat;
		position_msg->Longitude=global_position.lon;

		//copying data from commonMessage
		position_msg->Yawangle=commonMessage.Yawangle;
		position_msg->Safety = commonMessage.Safety;

		//saving data
		commonMessage.Timestamp=global_position.time_boot_ms;
		commonMessage.AltitudeRelative=global_position.relative_alt;
		commonMessage.AltitudeAMSL=global_position.alt;
		commonMessage.Latitude=global_position.lat;
		commonMessage.Longitude=global_position.lon;

		//DEBUG
//		ROS_INFO("HANDLE POSITION");

		position_pub.publish(position_msg);
	}

	/*
	 * From directive to RC
	 */
	void directive_cb(const guidance_node_amsl::Directive::ConstPtr msg){

		/*
		 * Initializing values, if safety is on, these values will remain
		 */
			velocity_.channels[0]=0;
			velocity_.channels[1]=0;
			velocity_.channels[2]=0;
			velocity_.channels[3]=0;
			velocity_.channels[4]=0;
			velocity_.channels[5]=0;
			velocity_.channels[6]=0;
			velocity_.channels[7]=0;

		if(!safetyOn){
			/*
			 * If safety is off, I translate velocity in RC values
			 */
			uint16_t vx_RC= (uint16_t)400.0f*(-msg->vxBody)/v_xy_max + 1520;         //New: 400 + 1520; Old:  500 + 1500
			uint16_t vy_RC=(uint16_t)400.0f*(msg->vyBody)/v_xy_max + 1520;		//New: 400 + 1520; Old:  500 + 1500
			/*
			 * it seems it loiters with 1420 instead of 1500...
			 */
			uint16_t vz_RC= 1420;
			if (msg->vzBody > 0){ //going down, mapped only in 420us
				vz_RC = vz_RC + (uint16_t)320.0f*(-msg->vzBody)/v_z_max;        //New: 320; Old:  420
			} else {        //going up, mapped in 580us
				vz_RC = vz_RC + (uint16_t)480.0f*(-msg->vzBody)/v_z_max;     //New: 480 Old: 580
			}
			uint16_t v_psi_RC = (uint16_t)400.0f*(msg->yawRate)/v_psi_max + 1520;		//New: 400 + 1520; Old:  500 + 1500

			velocity_.channels[0]=vy_RC;
			velocity_.channels[1]=vx_RC;
			velocity_.channels[2]=vz_RC;
			velocity_.channels[3]=v_psi_RC;

		}

		//DEBUG
		/*ROS_INFO("RC_OVERRIDE: [CH1:%u, CH2:%u, CH3:%u, CH4:%u, CH5:%u, CH6:%u, CH7:%u, CH8:%u]",
				velocity_.channels[0], velocity_.channels[1],
				velocity_.channels[2], velocity_.channels[3],
				velocity_.channels[4], velocity_.channels[5],
				velocity_.channels[6], velocity_.channels[7]);*/

		//velocity_publisher_.publish(velocity_);
		mavlink_message_t msg_mav;
		mavlink_msg_rc_channels_raw_pack_chan(UAS_PACK_CHAN(uas),&msg_mav,0,1,velocity_.channels[0],velocity_.channels[1],velocity_.channels[2],velocity_.channels[3],0,0,0,0,100);      //1 is the sequence that we are not considering right now
		UAS_FCU(uas)->send_message(&msg_mav);

	}

	/*
	 * Arming/disarming the UAV
	 */
	void arming(const mms::Arm::ConstPtr msg){
		mavlink_message_t msg_mav;
		if (msg->arm_disarm){
			enum MAV_CMD command = MAV_CMD_COMPONENT_ARM_DISARM;
			float param1 = 1;      //1-->arm 0-->disarm
			float param2 = 0;      //not used
			float param3 = 0;      //not used
			float param4 = 0;      //not used
			float param5 = 0;      //not used
			float param6 = 0;      //not used
			float param7 = 0;      //not used
			uint8_t confirmation = 1;
			mavlink_msg_command_long_pack_chan(UAS_PACK_CHAN(uas), &msg_mav,
								uas->get_tgt_system(),
								uas->get_tgt_component(),
								command,
								confirmation,
								param1, param2,
								param3, param4,
								param5, param6,
								param7);
			UAS_FCU(uas)->send_message(&msg_mav);
			ROS_INFO("Arming UAV");
		} else {
			enum MAV_CMD command = MAV_CMD_COMPONENT_ARM_DISARM;
			float param1 = 0;      //1-->arm 0-->disarm
			float param2 = 0;      //not used
			float param3 = 0;      //not used
			float param4 = 0;      //not used
			float param5 = 0;      //not used
			float param6 = 0;      //not used
			float param7 = 0;      //not used
			uint8_t confirmation = 1;
			mavlink_msg_command_long_pack_chan(UAS_PACK_CHAN(uas), &msg_mav,
								uas->get_tgt_system(),
								uas->get_tgt_component(),
								command,
								confirmation,
								param1, param2,
								param3, param4,
								param5, param6,
								param7);
			UAS_FCU(uas)->send_message(&msg_mav);                        //TODO decide if send or not disarm by software
			ROS_INFO("Disarming UAV");
		}
	}
};
};	// namespace mavplugin

PLUGINLIB_EXPORT_CLASS(mavplugin::UniboControllerAMSLPlugin, mavplugin::MavRosPlugin)
<commit_msg>added: software security check<commit_after>//#include <mavros/RCIn.h>
#include <mavros/mavros_plugin.h>
#include <pluginlib/class_list_macros.h>

#include "mavros/OverrideRCIn.h"

#include <guidance_node_amsl/Directive.h>
#include <guidance_node_amsl/Position.h>
#include <mms/Ack_arm.h>
#include <mms/Arm.h>
#include <mms/Sys_status.h>

namespace mavplugin {
/**
 * @brief Mavros plugin
 */
class UniboControllerAMSLPlugin : public MavRosPlugin {
public:
	UniboControllerAMSLPlugin() :
		nodeHandle(),
		uas(nullptr),
		safetyOn(true),
		v_xy_max(3.0),
		v_z_max(1.5),
		v_psi_max(3.14)
	{};

	void initialize(UAS &uas_)
	{
		uas = &uas_;

		directive_sub = nodeHandle.subscribe("/directive", 10, &UniboControllerAMSLPlugin::directive_cb, this);
		position_pub = nodeHandle.advertise<guidance_node_amsl::Position>("/position", 10);
		arm_sub = nodeHandle.subscribe("/arm", 10, &UniboControllerAMSLPlugin::arming, this);
		arm_ack_pub = nodeHandle.advertise<mms::Ack_arm>("acknowledge_arming", 10);
		//velocity_publisher_=nodeHandle.advertise<mavros::OverrideRCIn>("mavros/rc/override", 10);
		sys_status_pub = nodeHandle.advertise<mms::Sys_status>("/system_status", 10);

		nodeHandle.param("guidance_node_amsl/param/sat_xy", v_xy_max, 3.0);
		nodeHandle.param("guidance_node_amsl/param/sat_z", v_z_max, 1.5);
		nodeHandle.param("guidance_node_amsl/param/sat_yaw", v_psi_max, 3.14);

		//DEBUG
//		ROS_INFO("INITIALIZE UNIBO PLUGIN");
	}

	//should be logic mapping between id number and message type
	const message_map get_rx_handlers() {
		return {
			MESSAGE_HANDLER(MAVLINK_MSG_ID_GLOBAL_POSITION_INT, &UniboControllerAMSLPlugin::handle_global_position_int),
			MESSAGE_HANDLER(MAVLINK_MSG_ID_ATTITUDE, &UniboControllerAMSLPlugin::handle_attitude),
			MESSAGE_HANDLER(MAVLINK_MSG_ID_RC_CHANNELS_RAW, &UniboControllerAMSLPlugin::handle_rc_channels_raw),
			MESSAGE_HANDLER(MAVLINK_MSG_ID_COMMAND_ACK, &UniboControllerAMSLPlugin::handle_arm_ack),
			MESSAGE_HANDLER(MAVLINK_MSG_ID_HEARTBEAT, &UniboControllerAMSLPlugin::handle_heartbeat),
			MESSAGE_HANDLER(MAVLINK_MSG_ID_SYS_STATUS, &UniboControllerAMSLPlugin::handle_status)
		};
	}

private:
	ros::NodeHandle nodeHandle;
	UAS *uas;

	ros::Publisher position_pub;
	ros::Subscriber directive_sub;
	//ros::Publisher velocity_publisher_;
	ros::Subscriber arm_sub;
	ros::Publisher arm_ack_pub;
	ros::Publisher sys_status_pub;

	mms::Sys_status _system_status;

	//message to move the quadcopter
	mavros::OverrideRCIn velocity_;

	//common message to join data from handles
	guidance_node_amsl::Position commonMessage;

	//safety flag
	bool safetyOn;

	//saturation parameters
	/*
	 * Questi tipi di dato sono matlab per specifiche ros del param server.
	 * Nel nodo "guidance_node" sono convertiti a float perchè la legge di guida matlab ha come input
	 * dei float. Adesso non sono convertiti perchè tanto possono essere usati così
	 */
	double v_xy_max, v_z_max, v_psi_max;

	//check if safety is on
	void handle_rc_channels_raw(const mavlink_message_t *msg, uint8_t sysid, uint8_t compid) {

		mavlink_rc_channels_raw_t channels_raw;
		mavlink_msg_rc_channels_raw_decode(msg,&channels_raw);

		/*
		 * If safety is on, chan5_raw must be less than 1200
		 */
		//DEBUG
		//ROS_INFO("CHANNEL 6 IS: %u",channels_raw.chan6_raw);
		if(channels_raw.chan6_raw > 1700 && channels_raw.chan5_raw > 1300 && channels_raw.chan5_raw < 1700){
		//            ODROID_ON                 HIGHER THAN STABILIZE     &&            LOWER THAN RTL        -->      LOITER
			safetyOn = false;
			commonMessage.Safety = 0;
		}
		else {
			safetyOn=true;
			commonMessage.Safety= 1;
		}

		//DEBUG
//		ROS_INFO("HANDLE RC RAW");

	}

	void handle_attitude(const mavlink_message_t *msg, uint8_t sysid, uint8_t compid) {

		mavlink_attitude_t attitude;
		mavlink_msg_attitude_decode(msg, &attitude);

		auto position_msg = boost::make_shared<guidance_node_amsl::Position>();

		//getting new data
		position_msg->Yawangle=attitude.yaw;

		//copying data from commonMessage
		position_msg->Timestamp=commonMessage.Timestamp;
		position_msg->AltitudeRelative=commonMessage.AltitudeRelative;
		position_msg->AltitudeAMSL=commonMessage.AltitudeAMSL;
		position_msg->Latitude=commonMessage.Latitude;
		position_msg->Longitude=commonMessage.Longitude;
		position_msg->Safety = commonMessage.Safety;

		//saving data
		commonMessage.Yawangle=attitude.yaw;

		//DEBUG
//		ROS_INFO("%f", commonMessage.Yawangle);

		position_pub.publish(position_msg);
	}

	void handle_heartbeat(const mavlink_message_t *msg, uint8_t sysid, uint8_t compid) {

		mavlink_heartbeat_t heart;
		mavlink_msg_heartbeat_decode(msg, &heart);

		//auto position_msg = boost::make_shared<guidance_node_amsl::Position>();
		//ROS_INFO("Heatbeat. Base Mode: %d - Sys Status: %d ",heart.base_mode, heart.system_status);
		if (heart.base_mode >= 128)	_system_status.armed = true;
		else	_system_status.armed = false;
		sys_status_pub.publish(_system_status);
	}

	void handle_status(const mavlink_message_t *msg, uint8_t sysid, uint8_t compid) {
		mavlink_sys_status_t status;
		mavlink_msg_sys_status_decode(msg, &status);
		//ROS_INFO("Received sys status mavlink. Battery: %d", status.voltage_battery);

		_system_status.voltage_battery = status.voltage_battery;
		sys_status_pub.publish(_system_status);
	}

	void handle_arm_ack(const mavlink_message_t *msg, uint8_t sysid, uint8_t compid) {

		mavlink_command_ack_t cmd_ack;
		mavlink_msg_command_ack_decode(msg, &cmd_ack);

		auto arm_ack_msg = boost::make_shared<mms::Ack_arm>();

		if (cmd_ack.command == 400){      //ARM_DISARM command
			ROS_INFO("Received arm_disarm");
			if (cmd_ack.result == MAV_RESULT_ACCEPTED){
				arm_ack_msg->mav_result = true;
				ROS_INFO("Arm-disarm: succsessful");
			} else {
				arm_ack_msg->mav_result = false;
				ROS_INFO("Arm-disarm: fail");
			}
			arm_ack_pub.publish(arm_ack_msg);
		}
	}

	void handle_global_position_int(const mavlink_message_t *msg, uint8_t sysid, uint8_t compid) {

		mavlink_global_position_int_t global_position;
		mavlink_msg_global_position_int_decode(msg, &global_position);

		auto position_msg = boost::make_shared<guidance_node_amsl::Position>();

		//getting new data
		position_msg->Timestamp=global_position.time_boot_ms;
		position_msg->AltitudeRelative=global_position.relative_alt;
		position_msg->AltitudeAMSL = global_position.alt;
		position_msg->Latitude=global_position.lat;
		position_msg->Longitude=global_position.lon;

		//copying data from commonMessage
		position_msg->Yawangle=commonMessage.Yawangle;
		position_msg->Safety = commonMessage.Safety;

		//saving data
		commonMessage.Timestamp=global_position.time_boot_ms;
		commonMessage.AltitudeRelative=global_position.relative_alt;
		commonMessage.AltitudeAMSL=global_position.alt;
		commonMessage.Latitude=global_position.lat;
		commonMessage.Longitude=global_position.lon;

		//DEBUG
//		ROS_INFO("HANDLE POSITION");

		position_pub.publish(position_msg);
	}

	/*
	 * From directive to RC
	 */
	void directive_cb(const guidance_node_amsl::Directive::ConstPtr msg){

		/*
		 * Initializing values, if safety is on, these values will remain
		 */
			velocity_.channels[0]=0;
			velocity_.channels[1]=0;
			velocity_.channels[2]=0;
			velocity_.channels[3]=0;
			velocity_.channels[4]=0;
			velocity_.channels[5]=0;
			velocity_.channels[6]=0;
			velocity_.channels[7]=0;

		if(!safetyOn){
			/*
			 * If safety is off, I translate velocity in RC values
			 */
			uint16_t vx_RC= (uint16_t)400.0f*(-msg->vxBody)/v_xy_max + 1520;         //New: 400 + 1520; Old:  500 + 1500
			uint16_t vy_RC=(uint16_t)400.0f*(msg->vyBody)/v_xy_max + 1520;		//New: 400 + 1520; Old:  500 + 1500
			/*
			 * it seems it loiters with 1420 instead of 1500...
			 */
			uint16_t vz_RC= 1420;
			if (msg->vzBody > 0){ //going down, mapped only in 420us
				vz_RC = vz_RC + (uint16_t)320.0f*(-msg->vzBody)/v_z_max;        //New: 320; Old:  420
			} else {        //going up, mapped in 580us
				vz_RC = vz_RC + (uint16_t)480.0f*(-msg->vzBody)/v_z_max;     //New: 480 Old: 580
			}
			uint16_t v_psi_RC = (uint16_t)400.0f*(msg->yawRate)/v_psi_max + 1520;		//New: 400 + 1520; Old:  500 + 1500

			velocity_.channels[0]=vy_RC;
			velocity_.channels[1]=vx_RC;
			velocity_.channels[2]=vz_RC;
			velocity_.channels[3]=v_psi_RC;

		}

		//DEBUG
		/*ROS_INFO("RC_OVERRIDE: [CH1:%u, CH2:%u, CH3:%u, CH4:%u, CH5:%u, CH6:%u, CH7:%u, CH8:%u]",
				velocity_.channels[0], velocity_.channels[1],
				velocity_.channels[2], velocity_.channels[3],
				velocity_.channels[4], velocity_.channels[5],
				velocity_.channels[6], velocity_.channels[7]);*/

		//velocity_publisher_.publish(velocity_);
		mavlink_message_t msg_mav;
		mavlink_msg_rc_channels_raw_pack_chan(UAS_PACK_CHAN(uas),&msg_mav,0,1,velocity_.channels[0],velocity_.channels[1],velocity_.channels[2],velocity_.channels[3],0,0,0,0,100);      //1 is the sequence that we are not considering right now
		UAS_FCU(uas)->send_message(&msg_mav);

	}

	/*
	 * Arming/disarming the UAV
	 */
	void arming(const mms::Arm::ConstPtr msg){
		mavlink_message_t msg_mav;
		if (msg->arm_disarm){
			enum MAV_CMD command = MAV_CMD_COMPONENT_ARM_DISARM;
			float param1 = 1;      //1-->arm 0-->disarm
			float param2 = 0;      //not used
			float param3 = 0;      //not used
			float param4 = 0;      //not used
			float param5 = 0;      //not used
			float param6 = 0;      //not used
			float param7 = 0;      //not used
			uint8_t confirmation = 1;
			mavlink_msg_command_long_pack_chan(UAS_PACK_CHAN(uas), &msg_mav,
								uas->get_tgt_system(),
								uas->get_tgt_component(),
								command,
								confirmation,
								param1, param2,
								param3, param4,
								param5, param6,
								param7);
			UAS_FCU(uas)->send_message(&msg_mav);
			ROS_INFO("Arming UAV");
		} else {
			enum MAV_CMD command = MAV_CMD_COMPONENT_ARM_DISARM;
			float param1 = 0;      //1-->arm 0-->disarm
			float param2 = 0;      //not used
			float param3 = 0;      //not used
			float param4 = 0;      //not used
			float param5 = 0;      //not used
			float param6 = 0;      //not used
			float param7 = 0;      //not used
			uint8_t confirmation = 1;
			mavlink_msg_command_long_pack_chan(UAS_PACK_CHAN(uas), &msg_mav,
								uas->get_tgt_system(),
								uas->get_tgt_component(),
								command,
								confirmation,
								param1, param2,
								param3, param4,
								param5, param6,
								param7);
			UAS_FCU(uas)->send_message(&msg_mav);                        //TODO decide if send or not disarm by software
			ROS_INFO("Disarming UAV");
		}
	}
};
};	// namespace mavplugin

PLUGINLIB_EXPORT_CLASS(mavplugin::UniboControllerAMSLPlugin, mavplugin::MavRosPlugin)
<|endoftext|>


<commit_before>/*
 * NDC.hh
 *
 * Copyright 2000, LifeLine Networks BV (www.lifeline.nl). All rights reserved.
 * Copyright 2000, Bastiaan Bakker. All rights reserved.
 *
 * See the COPYING file for the terms of usage and distribution.
 */

#ifndef _LOG4CPP_NDC_HH
#define _LOG4CPP_NDC_HH

#include <string>
#include <vector>

namespace log4cpp {

    class NDC {
        public:

        struct DiagnosticContext {
            DiagnosticContext(const std::string& message);
            DiagnosticContext(const std::string& message,
                              const DiagnosticContext& parent);

            std::string message;
            std::string fullMessage;
        };

        typedef vector<DiagnosticContext> ContextStack;

        static void clear();
        static ContextStack* cloneStack();
        static const std::string& get();
        static int getDepth();
        static void inherit(ContextStack* stack);
        static std::string pop();
        static void push(const std::string& message);
        static void setMaxDepth(int maxDepth);
        static NDC& getNDC();

        protected:
        NDC();

#if defined(__GNUG__) && (__GNUC__ == 2) && (__GNUC_MINOR__ <= 95)
        public:
        virtual ~NDC();
#else
        protected:
        virtual ~NDC();
#endif
        protected:
        virtual void _clear();
        virtual ContextStack* _cloneStack();
        virtual const std::string& _get() const;
        virtual int _getDepth() const;
        virtual void _inherit(ContextStack* stack);
        virtual std::string _pop();
        virtual void _push(const std::string& message);
        virtual void _setMaxDepth(int maxDepth);

        ContextStack _stack;

        private:
        static NDC _nDC;

    };
}

#endif // _LOG4CPP_NDC_HH
<commit_msg>Making NDC() and ~NDC() protected was overly paranoid. They're public now.<commit_after>/*
 * NDC.hh
 *
 * Copyright 2000, LifeLine Networks BV (www.lifeline.nl). All rights reserved.
 * Copyright 2000, Bastiaan Bakker. All rights reserved.
 *
 * See the COPYING file for the terms of usage and distribution.
 */

#ifndef _LOG4CPP_NDC_HH
#define _LOG4CPP_NDC_HH

#include <string>
#include <vector>

namespace log4cpp {

    class NDC {
        public:

        struct DiagnosticContext {
            DiagnosticContext(const std::string& message);
            DiagnosticContext(const std::string& message,
                              const DiagnosticContext& parent);

            std::string message;
            std::string fullMessage;
        };

        typedef vector<DiagnosticContext> ContextStack;

        static void clear();
        static ContextStack* cloneStack();
        static const std::string& get();
        static int getDepth();
        static void inherit(ContextStack* stack);
        static std::string pop();
        static void push(const std::string& message);
        static void setMaxDepth(int maxDepth);
        static NDC& getNDC();

        NDC();
        virtual ~NDC();

        protected:
        virtual void _clear();
        virtual ContextStack* _cloneStack();
        virtual const std::string& _get() const;
        virtual int _getDepth() const;
        virtual void _inherit(ContextStack* stack);
        virtual std::string _pop();
        virtual void _push(const std::string& message);
        virtual void _setMaxDepth(int maxDepth);

        ContextStack _stack;

        private:
        static NDC _nDC;

    };
}

#endif // _LOG4CPP_NDC_HH
<|endoftext|>


<commit_before>#include "GameProcess.h"
#include "Object.h"
#include "Engine.h"
#include "World.h"
#include "App.h"
#include "ToolsCamera.h"
#include "ControlsApp.h"
#include "MathLib.h"

using namespace MathLib;

CGameProcess::CGameProcess(void)
{

}

CGameProcess::~CGameProcess(void)
{

}
int CGameProcess::Init()
{
	g_Engine.pFileSystem->CacheFilesFormExt("char");
	g_Engine.pFileSystem->CacheFilesFormExt("node");
	g_Engine.pFileSystem->CacheFilesFormExt("smesh");
	g_Engine.pFileSystem->CacheFilesFormExt("sanim");

	g_Engine.pWorld->LoadWorld("data/scene/terrain/test/test.world");
	//g_Engine.pWorld->LoadWorld("data/scene/terrain/cj/cj.world");
	g_Engine.pControls->SetKeyPressFunc(KeyPress);
	g_Engine.pControls->SetKeyReleaseFunc(KeyRelease);

	m_pRole = new CFPSRoleLocal();
	m_pRole->Init(10001, "data/role/hero/FpsRole/fps.char");		//ؽɫԴ

	m_pRole->SetActorPosition(vec3(0, 0, 0));	//ýɫʼλáŴΪԭ㣬άϵvec3
	m_pSkillSystem = new CSkillSystem(this);
	m_pCameraBase = new CCameraBase();
	m_pCameraBase->SetEnabled(1);
	g_pSysControl->SetMouseGrab(1);

}<commit_msg>Signed-off-by: mrlitong <litongtongxue@gmail.com><commit_after>#include "GameProcess.h"
#include "Object.h"
#include "Engine.h"
#include "World.h"
#include "App.h"
#include "ToolsCamera.h"
#include "ControlsApp.h"
#include "MathLib.h"

using namespace MathLib;

CGameProcess::CGameProcess(void)
{

}

CGameProcess::~CGameProcess(void)
{

}
int CGameProcess::Init()
{
	g_Engine.pFileSystem->CacheFilesFormExt("char");
	g_Engine.pFileSystem->CacheFilesFormExt("node");
	g_Engine.pFileSystem->CacheFilesFormExt("smesh");
	g_Engine.pFileSystem->CacheFilesFormExt("sanim");

	g_Engine.pWorld->LoadWorld("data/scene/terrain/test/test.world");
	//g_Engine.pWorld->LoadWorld("data/scene/terrain/cj/cj.world");
	g_Engine.pControls->SetKeyPressFunc(KeyPress);
	g_Engine.pControls->SetKeyReleaseFunc(KeyRelease);

	m_pRole = new CFPSRoleLocal();
	m_pRole->Init(10001, "data/role/hero/FpsRole/fps.char");		//ؽɫԴ

	m_pRole->SetActorPosition(vec3(0, 0, 0));	//ýɫʼλáŴΪԭ㣬άϵvec3
	m_pSkillSystem = new CSkillSystem(this);
	m_pCameraBase = new CCameraBase();
	m_pCameraBase->SetEnabled(1);
	g_pSysControl->SetMouseGrab(1);

	m_pStarControl = new CStarControl();

}<|endoftext|>


<commit_before>#define STR_EXPAND(tok) #tok
#define STR(tok) STR_EXPAND(tok)

#include "ros_visitor.hpp"

#include <QStandardPaths>
#include <algorithm>
#include <filesystem>
#include <memory>
#include <nlohmann/json_fwd.hpp>
#include <regex>
#include <string>

#include "label.hpp"
#include "inja/inja.hpp"
#include "node.hpp"

using namespace std;
namespace fs = std::filesystem;

vector<string> split(string s, const char separator) {
    istringstream ss;
    ss.str(s);
    string segment;
    std::vector<std::string> seglist;
    while (std::getline(ss, segment, separator)) {
        seglist.push_back(segment);
    }
    return seglist;
}

bool contains(const nlohmann::json& container, const nlohmann::json& value) {
    for (const auto& i : container) {
        if (i[0] == value[0] && i[1] == value[1]) {
            return true;
        }
    }
    return false;
}

tuple<string, string> prepareTopic(string topic_in) {
    string topic(topic_in);

    // ROS4HRI
    regex human_faces_regex("/h/f/\\*/(.*)", regex_constants::ECMAScript);
    smatch faces;
    if (regex_search(topic_in, faces, human_faces_regex)) {
        return {string("/humans/faces/<id>/") + string(faces[1]),
                string("face_") + string(faces[1])};
    }

    regex human_bodies_regex("/h/b/\\*/(.*)", regex_constants::ECMAScript);
    smatch bodies;
    if (regex_search(topic_in, bodies, human_bodies_regex)) {
        return {string("/humans/bodies/<id>/") + string(bodies[1]),
                string("body_") + string(bodies[1])};
    }

    regex human_voices_regex("/h/v/\\*/(.*)", regex_constants::ECMAScript);
    smatch voices;
    if (regex_search(topic_in, voices, human_voices_regex)) {
        return {string("/humans/voices/<id>/") + string(voices[1]),
                string("voice_") + string(voices[1])};
    }

    regex human_persons_regex("/h/f/\\*/(.*)", regex_constants::ECMAScript);
    smatch persons;
    if (regex_search(topic_in, persons, human_persons_regex)) {
        return {string("/humans/persons/<id>/") + string(persons[1]),
                string("person_") + string(persons[1])};
    }

    auto shortname = split(topic, '/').back();

    return {topic, shortname};
}

RosVisitor::RosVisitor(const Architecture& architecture, const string& ws_path)
    : Visitor(architecture), ws_path(ws_path) {
    fs::path tpl_path;

    for (auto p :
         QStandardPaths::standardLocations(QStandardPaths::AppDataLocation)) {
        tpl_path = fs::path(p.toStdString()) / "templates" / "ros";
        cout << "Looking for ROS templates in " << tpl_path << endl;

        if (fs::exists(tpl_path)) {
            break;
        }
    }

    if (!tpl_path.empty()) {
        cout << "Using ROS templates found at " << tpl_path << endl;
        env_ = make_unique<inja::Environment>(
            (tpl_path / "default").string() + fs::path::preferred_separator,
            ws_path + fs::path::preferred_separator);

        env_->set_line_statement("$$$$$");
        env_->set_trim_blocks(true);
        env_->set_lstrip_blocks(true);

        env_main_node_ = make_unique<inja::Environment>(
            (tpl_path / "main_node").string() + fs::path::preferred_separator,
            ws_path + fs::path::preferred_separator);

        env_main_node_->set_line_statement("$$$$$");
        env_main_node_->set_trim_blocks(true);
        env_main_node_->set_lstrip_blocks(true);
    } else {
        cout << "[EE] ROS templates not found! Can not generate ROS nodes."
             << endl;
    }
}

void RosVisitor::startUp() {
    data_["path"] = ws_path;
    data_["name"] = architecture.name;
    auto [id, id_capitalized] = make_id(architecture.name);
    data_["id"] = id;
    data_["boxology_version"] = STR(BOXOLOGY_VERSION);
    data_["version"] = architecture.version;
    data_["description"] = architecture.description;
}

void RosVisitor::tearDown() {
    if (!env_) return;

    ///////////////////////////////////////////////////////
    // Create parent node with main launchfile
    //
    vector<string> main_node_tpls{"package.xml", "CMakeLists.txt",
                                  "launch/start_all.launch"};

    auto [id, id_capitalized] = make_id(architecture.name);
    auto rel_path = fs::path("src") / id;
    auto abs_path = fs::path(ws_path) / rel_path;
    auto launch_path = abs_path / "launch";
    fs::create_directories(launch_path);  // will also create 'path'

    for (const auto& file : main_node_tpls) {
        auto tpl = env_main_node_->parse_template(file);
        env_main_node_->write(tpl, data_, (rel_path / file).string());
    }

    ///////////////////////////////////////////////////////
    // Create all the nodes
    //
    vector<string> default_tpls{"package.xml", "CMakeLists.txt",
                                "src/main.cpp"};

    for (auto node : data_["nodes"]) {
        string id(node["id"]);
        cout << "Generating " << node["name"] << " as node [" << id << "]..."
             << endl;

        auto rel_path = fs::path("src") / id;
        auto abs_path = fs::path(ws_path) / rel_path;
        auto src_path = abs_path / "src";
        fs::create_directories(src_path);  // will also create 'path'

        for (const auto& file : default_tpls) {
            auto tpl = env_->parse_template(file);
            // cout << "\t- " << (abs_path / file).string() << endl;
            env_->write(tpl, node, (rel_path / file).string());
        }
    }

    cout << "Generation of ROS nodes complete. The generated nodes can be "
            "found in "
         << ws_path << endl;
}

void RosVisitor::beginNodes() {}

void RosVisitor::onNode(shared_ptr<const Node> node) {
    // ignore TF nodes
    if (node->name() == "TF" || node->name() == "tf") return;

    nlohmann::json jnode;

    auto name = node->name().substr(0, node->name().find("["));

    auto [id, id_capitalized] = make_id(name);
    jnode["id"] = id;
    jnode["id_capitalized"] = id_capitalized;
    jnode["name"] = name;
    jnode["label"] = LABEL_NAMES.at(node->label());

    jnode["dependencies"] = nlohmann::json::array();

    jnode["boxology_version"] = STR(BOXOLOGY_VERSION);

    if (node->sub_architecture) {
        jnode["version"] = node->sub_architecture->version;
        jnode["description"] = node->sub_architecture->description;
    } else {
        jnode["version"] = "1.0.0";
        jnode["description"] = "";
    }

    //////////////////////////////////////////////
    // Ports
    //
    jnode["inputs"] = nlohmann::json::array();
    jnode["outputs"] = nlohmann::json::array();
    for (auto p : node->ports()) {
        nlohmann::json jport;

        bool isInput = (p->direction == Port::Direction::IN);

        auto name = p->name;
        jport["name"] = name;

        regex topic_regex("^(/.*) \\[(.*)\\]$", regex_constants::ECMAScript);
        smatch topic_matches;
        regex tf_regex("^tf: (.*)$", regex_constants::ECMAScript);
        smatch tf_matches;

        if (regex_search(name, topic_matches, topic_regex)) {
            jport["type"] = "topic";
            auto [topic, shortname] = prepareTopic(topic_matches[1]);
            jport["topic"] = topic;
            jport["short"] = shortname;
            auto type = split(topic_matches[2], '/');
            jport["datatype"] = {type.front(), type.back()};
            if (!contains(jnode["dependencies"], jport["datatype"])) {
                jnode["dependencies"].push_back(jport["datatype"]);
            }

            cout << "[II] Node " << jnode["id"] << ": "
                 << (isInput ? "subscribes to" : "publishes") << " topic "
                 << jport["topic"] << " (short: " << jport["short"]
                 << ") of type " << jport["type"] << endl;

        } else if (regex_search(name, tf_matches, tf_regex)) {
            jport["type"] = "tf";
            jport["frame"] = tf_matches[1];

            if (isInput) {
                jport["datatype"] = {"tf", "transform_listener"};
            } else {
                jport["datatype"] = {"tf", "transform_broadcaster"};
            }
            if (!contains(jnode["dependencies"], jport["datatype"])) {
                jnode["dependencies"].push_back(jport["datatype"]);
            }

            cout << "[II] Node " << jnode["id"] << ": "
                 << (isInput ? "listen to" : "broadcasts") << " TF frame "
                 << jport["frame"] << endl;
        } else {
            jport["type"] = "undefined";
            auto [id, id_capitalized] = make_id(name);
            jport["topic"] = id;
            jport["short"] = id;
            jport["datatype"] = {"std_msgs", "Empty"};
            if (!contains(jnode["dependencies"], jport["datatype"])) {
                jnode["dependencies"].push_back(jport["datatype"]);
            }
        }

        if (isInput) {
            jnode["inputs"].push_back(jport);
        } else {
            jnode["outputs"].push_back(jport);
        }
    }

    // ensure package dependencies are only listed *one* time
    // otherwise catkin complains.
    set<string> packages;
    for (const auto& dep : jnode["dependencies"]) {
        packages.insert(string(dep[0]));
    }
    for (const auto& p : packages) {
        jnode["packages"].push_back(p);
    }

    data_["nodes"].push_back(jnode);

    nodes_.push_back(node);
}

void RosVisitor::endNodes() {}

void RosVisitor::beginConnections() {}

void RosVisitor::onConnection(shared_ptr<const Connection> connection) {}

<commit_msg>remove 'DEPENDENCY: ' from node name if present<commit_after>#define STR_EXPAND(tok) #tok
#define STR(tok) STR_EXPAND(tok)

#include "ros_visitor.hpp"

#include <QStandardPaths>
#include <algorithm>
#include <filesystem>
#include <memory>
#include <nlohmann/json_fwd.hpp>
#include <regex>
#include <string>

#include "inja/inja.hpp"
#include "label.hpp"
#include "node.hpp"

using namespace std;
namespace fs = std::filesystem;

vector<string> split(string s, const char separator) {
    istringstream ss;
    ss.str(s);
    string segment;
    std::vector<std::string> seglist;
    while (std::getline(ss, segment, separator)) {
        seglist.push_back(segment);
    }
    return seglist;
}

bool contains(const nlohmann::json& container, const nlohmann::json& value) {
    for (const auto& i : container) {
        if (i[0] == value[0] && i[1] == value[1]) {
            return true;
        }
    }
    return false;
}

tuple<string, string> prepareTopic(string topic_in) {
    string topic(topic_in);

    // ROS4HRI
    regex human_faces_regex("/h/f/\\*/(.*)", regex_constants::ECMAScript);
    smatch faces;
    if (regex_search(topic_in, faces, human_faces_regex)) {
        return {string("/humans/faces/<id>/") + string(faces[1]),
                string("face_") + string(faces[1])};
    }

    regex human_bodies_regex("/h/b/\\*/(.*)", regex_constants::ECMAScript);
    smatch bodies;
    if (regex_search(topic_in, bodies, human_bodies_regex)) {
        return {string("/humans/bodies/<id>/") + string(bodies[1]),
                string("body_") + string(bodies[1])};
    }

    regex human_voices_regex("/h/v/\\*/(.*)", regex_constants::ECMAScript);
    smatch voices;
    if (regex_search(topic_in, voices, human_voices_regex)) {
        return {string("/humans/voices/<id>/") + string(voices[1]),
                string("voice_") + string(voices[1])};
    }

    regex human_persons_regex("/h/f/\\*/(.*)", regex_constants::ECMAScript);
    smatch persons;
    if (regex_search(topic_in, persons, human_persons_regex)) {
        return {string("/humans/persons/<id>/") + string(persons[1]),
                string("person_") + string(persons[1])};
    }

    auto shortname = split(topic, '/').back();

    return {topic, shortname};
}

RosVisitor::RosVisitor(const Architecture& architecture, const string& ws_path)
    : Visitor(architecture), ws_path(ws_path) {
    fs::path tpl_path;

    for (auto p :
         QStandardPaths::standardLocations(QStandardPaths::AppDataLocation)) {
        tpl_path = fs::path(p.toStdString()) / "templates" / "ros";
        cout << "Looking for ROS templates in " << tpl_path << endl;

        if (fs::exists(tpl_path)) {
            break;
        }
    }

    if (!tpl_path.empty()) {
        cout << "Using ROS templates found at " << tpl_path << endl;
        env_ = make_unique<inja::Environment>(
            (tpl_path / "default").string() + fs::path::preferred_separator,
            ws_path + fs::path::preferred_separator);

        env_->set_line_statement("$$$$$");
        env_->set_trim_blocks(true);
        env_->set_lstrip_blocks(true);

        env_main_node_ = make_unique<inja::Environment>(
            (tpl_path / "main_node").string() + fs::path::preferred_separator,
            ws_path + fs::path::preferred_separator);

        env_main_node_->set_line_statement("$$$$$");
        env_main_node_->set_trim_blocks(true);
        env_main_node_->set_lstrip_blocks(true);
    } else {
        cout << "[EE] ROS templates not found! Can not generate ROS nodes."
             << endl;
    }
}

void RosVisitor::startUp() {
    data_["path"] = ws_path;
    data_["name"] = architecture.name;
    auto [id, id_capitalized] = make_id(architecture.name);
    data_["id"] = id;
    data_["boxology_version"] = STR(BOXOLOGY_VERSION);
    data_["version"] = architecture.version;
    data_["description"] = architecture.description;
}

void RosVisitor::tearDown() {
    if (!env_) return;

    ///////////////////////////////////////////////////////
    // Create parent node with main launchfile
    //
    vector<string> main_node_tpls{"package.xml", "CMakeLists.txt",
                                  "launch/start_all.launch"};

    auto [id, id_capitalized] = make_id(architecture.name);
    auto rel_path = fs::path("src") / id;
    auto abs_path = fs::path(ws_path) / rel_path;
    auto launch_path = abs_path / "launch";
    fs::create_directories(launch_path);  // will also create 'path'

    for (const auto& file : main_node_tpls) {
        auto tpl = env_main_node_->parse_template(file);
        env_main_node_->write(tpl, data_, (rel_path / file).string());
    }

    ///////////////////////////////////////////////////////
    // Create all the nodes
    //
    vector<string> default_tpls{"package.xml", "CMakeLists.txt",
                                "src/main.cpp"};

    for (auto node : data_["nodes"]) {
        string id(node["id"]);
        cout << "Generating " << node["name"] << " as node [" << id << "]..."
             << endl;

        auto rel_path = fs::path("src") / id;
        auto abs_path = fs::path(ws_path) / rel_path;
        auto src_path = abs_path / "src";
        fs::create_directories(src_path);  // will also create 'path'

        for (const auto& file : default_tpls) {
            auto tpl = env_->parse_template(file);
            // cout << "\t- " << (abs_path / file).string() << endl;
            env_->write(tpl, node, (rel_path / file).string());
        }
    }

    cout << "Generation of ROS nodes complete. The generated nodes can be "
            "found in "
         << ws_path << endl;
}

void RosVisitor::beginNodes() {}

void RosVisitor::onNode(shared_ptr<const Node> node) {
    // ignore TF nodes
    if (node->name() == "TF" || node->name() == "tf") return;

    nlohmann::json jnode;

    auto name = node->name().substr(0, node->name().find("["));
    if (name.find("DEPENDENCY:") != string::npos) {
        name = name.substr(string("DEPENDENCY:").size());
    }

    auto [id, id_capitalized] = make_id(name);
    jnode["id"] = id;
    jnode["id_capitalized"] = id_capitalized;
    jnode["name"] = name;
    jnode["label"] = LABEL_NAMES.at(node->label());

    jnode["dependencies"] = nlohmann::json::array();

    jnode["boxology_version"] = STR(BOXOLOGY_VERSION);

    if (node->sub_architecture) {
        jnode["version"] = node->sub_architecture->version;
        jnode["description"] = node->sub_architecture->description;
    } else {
        jnode["version"] = "1.0.0";
        jnode["description"] = "";
    }

    //////////////////////////////////////////////
    // Ports
    //
    jnode["inputs"] = nlohmann::json::array();
    jnode["outputs"] = nlohmann::json::array();
    for (auto p : node->ports()) {
        nlohmann::json jport;

        bool isInput = (p->direction == Port::Direction::IN);

        auto name = p->name;
        jport["name"] = name;

        regex topic_regex("^(/.*) \\[(.*)\\]$", regex_constants::ECMAScript);
        smatch topic_matches;
        regex tf_regex("^tf: (.*)$", regex_constants::ECMAScript);
        smatch tf_matches;

        if (regex_search(name, topic_matches, topic_regex)) {
            jport["type"] = "topic";
            auto [topic, shortname] = prepareTopic(topic_matches[1]);
            jport["topic"] = topic;
            jport["short"] = shortname;
            auto type = split(topic_matches[2], '/');
            jport["datatype"] = {type.front(), type.back()};
            if (!contains(jnode["dependencies"], jport["datatype"])) {
                jnode["dependencies"].push_back(jport["datatype"]);
            }

            cout << "[II] Node " << jnode["id"] << ": "
                 << (isInput ? "subscribes to" : "publishes") << " topic "
                 << jport["topic"] << " (short: " << jport["short"]
                 << ") of type " << jport["type"] << endl;

        } else if (regex_search(name, tf_matches, tf_regex)) {
            jport["type"] = "tf";
            jport["frame"] = tf_matches[1];

            if (isInput) {
                jport["datatype"] = {"tf", "transform_listener"};
            } else {
                jport["datatype"] = {"tf", "transform_broadcaster"};
            }
            if (!contains(jnode["dependencies"], jport["datatype"])) {
                jnode["dependencies"].push_back(jport["datatype"]);
            }

            cout << "[II] Node " << jnode["id"] << ": "
                 << (isInput ? "listen to" : "broadcasts") << " TF frame "
                 << jport["frame"] << endl;
        } else {
            jport["type"] = "undefined";
            auto [id, id_capitalized] = make_id(name);
            jport["topic"] = id;
            jport["short"] = id;
            jport["datatype"] = {"std_msgs", "Empty"};
            if (!contains(jnode["dependencies"], jport["datatype"])) {
                jnode["dependencies"].push_back(jport["datatype"]);
            }
        }

        if (isInput) {
            jnode["inputs"].push_back(jport);
        } else {
            jnode["outputs"].push_back(jport);
        }
    }

    // ensure package dependencies are only listed *one* time
    // otherwise catkin complains.
    set<string> packages;
    for (const auto& dep : jnode["dependencies"]) {
        packages.insert(string(dep[0]));
    }
    for (const auto& p : packages) {
        jnode["packages"].push_back(p);
    }

    data_["nodes"].push_back(jnode);

    nodes_.push_back(node);
}

void RosVisitor::endNodes() {}

void RosVisitor::beginConnections() {}

void RosVisitor::onConnection(shared_ptr<const Connection> connection) {}

<|endoftext|>


<commit_before>// Each task has an entry in the ObjectArchive, which is described in this file.
//
// The entry is composed of a set of keys required to compute the task and get
// its value. Additionally, flags "should_save" and "run_locally", the same in
// ComputingUnit, are provided for faster and easier management, as the unit
// would have to be loaded otherwise.
//
// As the id of the computing unit is required to call it, a key to it is stored
// in the entry. This may lead to data duplication (all nodes can create
// differente keys for the same id), but allows faster lookup and transmission.

#ifndef __TASK_DISTRIBUTION__TASK_ENTRY_HPP__
#define __TASK_DISTRIBUTION__TASK_ENTRY_HPP__

#include "key.hpp"

namespace TaskDistribution {
  // Archive entry for a task, having all values required work with it.
  struct TaskEntry {
    Key task_key;              // Key to this entry
    Key computing_unit_key;    // Key to the computing unit
    Key arguments_key;         // Key to the tuple of arguments
    Key arguments_tasks_key;   // Key to the tuple of tasks as arguments
    Key result_key;            // Key to the result
    Key computing_unit_id_key; // Key to the unit id
    Key parents_key;           // Key to a list of keys of parent tasks
    Key children_key;          // Key to a list of keys of children tasks
    size_t active_parents;     // Number of parents that have to be computed
    bool run_locally;

    TaskEntry():
      active_parents(0),
      run_locally(false) { }

    template<class Archive>
    void serialize(Archive& ar, const unsigned int version) {
      ar & task_key;
      ar & computing_unit_key;
      ar & arguments_key;
      ar & arguments_tasks_key;
      ar & result_key;
      ar & computing_unit_id_key;
      ar & parents_key;
      ar & children_key;
      ar & active_parents;
      ar & run_locally;
    }
  };
};

// Enables faster MPI transmission.
#if ENABLE_MPI
BOOST_IS_MPI_DATATYPE(TaskDistribution::TaskEntry);
#endif

#endif
<commit_msg>Added documentation to task_entry.hpp.<commit_after>// Each task has an entry in the ObjectArchive, which is described in this file.
//
// The entry is composed of a set of keys required to compute the task and get
// its value. Additionally, a flag "run_locally", the same in ComputingUnit, is
// provided for faster and easier management, as the unit would have to be
// loaded otherwise.
//
// As the id of the computing unit is required to call it, a key to it is stored
// in the entry. This may lead to data duplication (all nodes can create
// different keys for the same id), but allows faster lookup and transmission.

#ifndef __TASK_DISTRIBUTION__TASK_ENTRY_HPP__
#define __TASK_DISTRIBUTION__TASK_ENTRY_HPP__

#include "key.hpp"

namespace TaskDistribution {
  // Archive entry for a task, having all values required work with it.
  struct TaskEntry {
    Key task_key;              // Key to this entry
    Key computing_unit_key;    // Key to the computing unit
    Key arguments_key;         // Key to the tuple of arguments
    Key arguments_tasks_key;   // Key to the tuple of tasks as arguments
    Key result_key;            // Key to the result
    Key computing_unit_id_key; // Key to the unit id
    Key parents_key;           // Key to a list of keys of parent tasks
    Key children_key;          // Key to a list of keys of children tasks
    size_t active_parents;     // Number of parents that have to be computed
    bool run_locally;

    TaskEntry():
      active_parents(0),
      run_locally(false) { }

    template<class Archive>
    void serialize(Archive& ar, const unsigned int version) {
      ar & task_key;
      ar & computing_unit_key;
      ar & arguments_key;
      ar & arguments_tasks_key;
      ar & result_key;
      ar & computing_unit_id_key;
      ar & parents_key;
      ar & children_key;
      ar & active_parents;
      ar & run_locally;
    }
  };
};

// Enables faster MPI transmission.
#if ENABLE_MPI
BOOST_IS_MPI_DATATYPE(TaskDistribution::TaskEntry);
#endif

#endif
<|endoftext|>


<commit_before>#ifndef INCLUDED_U5E_FILTER
#define INCLUDED_U5E_FILTER

namespace u5e {

  /**
   * \brief Walks an input iterator through a filter
   *
   * This will go from the begin to the end of the input iterator and
   * will execute the filter function once for every input element.
   *
   * Unlike std::transform, the filter function does not return the
   * output element, but it receives the output object and will do
   * whatever makes sense with the output object.
   *
   * That means that the type of filter will define what type of
   * object can be used as output. The filter function itself will not
   * touch the output object, but simply forward it to the operator
   * function.
   *
   * The operator function returns an int that is meant to indicate
   * how much output was produced. The filter function will accumulate
   * those values and return the sum.
   *
   * The filter is not required to produce a constant number of
   * outputs for each input. The function can be produce many outputs
   * or even none at all during the processing of each element.
   *
   * The value type for input and output is not required to be the
   * same. The input type is resolved by the value_type member type of
   * the input iterator type.
   *
   * \tparam InputIteratorType the type of the input iterator
   * \tparam OutputType the type of the output iterator
   * \tparam Functor the callback function type called for each element
   *
   * \param input_from starting position for the input iterator
   * \param input_to end position for the input iterator
   * \param output output container sent to the operator function
   * \param operation function that takes the element, the output
   * container and returns the number of outputted elements
   */
  template <typename InputIteratorType, typename OutputType,
            typename Functor >
  inline int
  filter(InputIteratorType input_from, InputIteratorType input_to,
         OutputType& output, Functor operation) {
    int counter = 0;
    while (input_from != input_to) {
      counter += operation(*input_from, output);
      input_from++;
    }
    return counter;
  }

}

#endif
<commit_msg>More explicit coding to make it easier to debug<commit_after>#ifndef INCLUDED_U5E_FILTER
#define INCLUDED_U5E_FILTER

namespace u5e {

  /**
   * \brief Walks an input iterator through a filter
   *
   * This will go from the begin to the end of the input iterator and
   * will execute the filter function once for every input element.
   *
   * Unlike std::transform, the filter function does not return the
   * output element, but it receives the output object and will do
   * whatever makes sense with the output object.
   *
   * That means that the type of filter will define what type of
   * object can be used as output. The filter function itself will not
   * touch the output object, but simply forward it to the operator
   * function.
   *
   * The operator function returns an int that is meant to indicate
   * how much output was produced. The filter function will accumulate
   * those values and return the sum.
   *
   * The filter is not required to produce a constant number of
   * outputs for each input. The function can be produce many outputs
   * or even none at all during the processing of each element.
   *
   * The value type for input and output is not required to be the
   * same. The input type is resolved by the value_type member type of
   * the input iterator type.
   *
   * \tparam InputIteratorType the type of the input iterator
   * \tparam OutputType the type of the output iterator
   * \tparam Functor the callback function type called for each element
   *
   * \param input_from starting position for the input iterator
   * \param input_to end position for the input iterator
   * \param output output container sent to the operator function
   * \param operation function that takes the element, the output
   * container and returns the number of outputted elements
   */
  template <typename InputIteratorType, typename OutputType,
            typename Functor >
  inline int
  filter(InputIteratorType input_from, InputIteratorType input_to,
         OutputType& output, Functor operation) {
    int counter = 0;
    while (input_from != input_to) {
      typename InputIteratorType::value_type item = *input_from;
      counter += operation(item, output);
      input_from++;
    }
    return counter;
  }

}

#endif
<|endoftext|>


<commit_before>/*****************************************************************************************
 *                                                                                *
 * OpenSpace                                                                             *
 *                                                                                *
 * Copyright (c) 2014-2022                                                               *
 *                                                                                *
 * Permission is hereby granted, free of charge, to any person obtaining a copy of this  *
 * software and associated documentation files (the "Software"), to deal in the Software *
 * without restriction, including without limitation the rights to use, copy, modify,    *
 * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to    *
 * permit persons to whom the Software is furnished to do so, subject to the following   *
 * conditions:                                                                           *
 *                                                                                *
 * The above copyright notice and this permission notice shall be included in all copies *
 * or substantial portions of the Software.                                              *
 *                                                                                *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,   *
 * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A         *
 * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT    *
 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF  *
 * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE  *
 * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                                         *
 ****************************************************************************************/

#include "sgctedit/filesupport.h"

FileSupport::FileSupport(QVBoxLayout* parentLayout,
                         UserConfigurationElements& cfgElements,
                         SgctConfigElements& sgctElements,
                         std::function<void(bool)> finishedCallback)
    : _displayWidget(cfgElements.display)
    , _orientationWidget(cfgElements.orientation)
    , _monitors(cfgElements.monitorList)
    , _cluster(sgctElements.cluster)
    , _windowList(sgctElements.windowList)
    , _finishedCallback(finishedCallback)
    , _userConfigPath(cfgElements.configSavePath)
{
    QVBoxLayout* layoutFullVertical = new QVBoxLayout;
    _saveButton = new QPushButton("Save As");
    _saveButton->setToolTip("Save configuration changes (opens file chooser dialog)");
    connect(_saveButton, &QPushButton::released, this, &FileSupport::save);
    _cancelButton = new QPushButton("Cancel");
    _cancelButton->setToolTip("Cancel changes");
    connect(_cancelButton, &QPushButton::released, this, &FileSupport::cancel);
    _applyButton = new QPushButton("Apply Without Saving");
    _applyButton->setToolTip("Apply configuration changes without saving to file");
    connect(_applyButton, &QPushButton::released, this, &FileSupport::apply);
    {
        QHBoxLayout* layoutButtonBox = new QHBoxLayout;
        layoutButtonBox->addStretch(1);
        layoutButtonBox->addWidget(_cancelButton);
        layoutButtonBox->addWidget(_saveButton);
        layoutButtonBox->addWidget(_applyButton);
        layoutFullVertical->addLayout(layoutButtonBox);
    }
    parentLayout->addLayout(layoutFullVertical);
}

void FileSupport::saveCluster() {
    if (_orientationWidget) {
        sgct::config::Scene initScene;
        initScene.orientation = _orientationWidget->orientationValue();
        _cluster.nodes.clear();
        sgct::config::Node tmpNode;
        tmpNode.address = "localhost";
        tmpNode.port = 20401;
        _cluster.nodes.push_back(tmpNode);
        _cluster.masterAddress = "localhost";
        _cluster.scene = std::move(initScene);
        _cluster.firmSync = _orientationWidget->vsyncValue();
    }
}

void FileSupport::saveUser() {
    if (_orientationWidget) {
        sgct::config::User user;
        user.eyeSeparation = 0.065f;
        user.position = {0.0f, 0.0f, 4.0f};
        _cluster.users.push_back(user);
    }
}

bool FileSupport::isWindowFullscreen(unsigned int monitorIdx, sgct::ivec2 wDims) {
    return (_monitors[monitorIdx].width() == wDims.x &&
            _monitors[monitorIdx].height() == wDims.y);
}

std::optional<unsigned int> FileSupport::findGuiWindow() {
    unsigned int windowIndex = 0;
    for (unsigned int w = 0; w < _displayWidget->nWindows(); ++w) {
        if (_displayWidget->windowControls()[w]->isGuiWindow()) {
            return std::optional<unsigned int>(windowIndex);
        }
        windowIndex++;
    }
    return std::nullopt;
}

void FileSupport::saveWindows() {
    unsigned int windowIndex = 0;
    for (unsigned int w = 0; w < _displayWidget->nWindows(); ++w) {
        std::shared_ptr<WindowControl> wCtrl = _displayWidget->windowControls()[w];
        sgct::config::Window tmpWindow = saveWindowsDimensions(wCtrl);
        tmpWindow.viewports.push_back(generateViewport());
        tmpWindow.viewports.back().projection = saveProjectionInformation(wCtrl);
        tmpWindow.isDecorated = wCtrl->isDecorated();
        tmpWindow.isFullScreen = isWindowFullscreen(
            wCtrl->monitorNum(),
            wCtrl->windowSize()
        );
        saveWindowsWebGui(windowIndex, tmpWindow);
        if (!wCtrl->windowName().empty()) {
            tmpWindow.name = wCtrl->windowName();
        }
        tmpWindow.id = windowIndex++;
        _windowList.push_back(tmpWindow);
    }
}

sgct::config::Viewport FileSupport::generateViewport() {
    sgct::config::Viewport vp;
    vp.isTracked = true;
    vp.position = {0.f, 0.f};
    vp.size = {1.f, 1.f};
    return vp;
}

sgct::config::Window FileSupport::saveWindowsDimensions(
                                                     std::shared_ptr<WindowControl> wCtrl)
{
    sgct::config::Window tmpWindow;
    tmpWindow.size = wCtrl->windowSize();
    tmpWindow.pos = {
        _monitors[wCtrl->monitorNum()].x() + wCtrl->windowPos().x,
        _monitors[wCtrl->monitorNum()].y() + wCtrl->windowPos().y,
    };
    return tmpWindow;
}

void FileSupport::saveWindowsWebGui(unsigned int wIdx, sgct::config::Window& win) {
    win.viewports.back().isTracked = true;
    std::optional<unsigned int> webGuiWindowIndex = findGuiWindow();
    bool isOneOfWindowsSetAsWebGui = webGuiWindowIndex.has_value();
    if (isOneOfWindowsSetAsWebGui) {
        if (wIdx == webGuiWindowIndex.value()) {
            win.viewports.back().isTracked = false;
            win.tags.push_back("GUI");
        }
        win.draw2D = (wIdx == webGuiWindowIndex.value());
        win.draw3D = !(win.draw2D.value());
    }
}

ProjectionOptions FileSupport::saveProjectionInformation(
                                                std::shared_ptr<WindowControl> winControl)
{
    if (winControl->isSpoutSelected()) {
        return saveProjectionSpout(winControl);
    }
    else {
        return saveProjectionNoSpout(winControl);
    }
}

ProjectionOptions FileSupport::saveProjectionSpout(
                                                std::shared_ptr<WindowControl> winControl)
{
    sgct::config::SpoutOutputProjection projection;
    switch(winControl->projectionSelectedIndex()) {
        case WindowControl::ProjectionIndeces::Fisheye:
            projection.mapping
                = sgct::config::SpoutOutputProjection::Mapping::Fisheye;
            break;

        case WindowControl::ProjectionIndeces::Equirectangular:
        default:
            projection.mapping
                = sgct::config::SpoutOutputProjection::Mapping::Equirectangular;
            break;
    }
    projection.quality = winControl->qualitySelectedValue();
    projection.mappingSpoutName = "OpenSpace";
    return projection;
}

ProjectionOptions FileSupport::saveProjectionNoSpout(
                                                std::shared_ptr<WindowControl> winControl)
{
    switch(winControl->projectionSelectedIndex()) {
        case WindowControl::ProjectionIndeces::Fisheye:
            {
                sgct::config::FisheyeProjection projection;
                projection.quality = winControl->qualitySelectedValue();
                projection.fov = 180.f;
                projection.tilt = 0.f;
                return projection;
            }
            break;

        case WindowControl::ProjectionIndeces::SphericalMirror:
            {
                sgct::config::SphericalMirrorProjection projection;
                projection.quality = winControl->qualitySelectedValue();
                return projection;
            }
            break;

        case WindowControl::ProjectionIndeces::Cylindrical:
            {
                sgct::config::CylindricalProjection projection;
                projection.quality = winControl->qualitySelectedValue();
                projection.heightOffset = winControl->heightOffset();
                return projection;
            }
            break;

        case WindowControl::ProjectionIndeces::Equirectangular:
            {
                sgct::config::EquirectangularProjection projection;
                projection.quality = winControl->qualitySelectedValue();
                return projection;
            }
            break;

        case WindowControl::ProjectionIndeces::Planar:
        default:
            {
                // The negative values for left & down are according to sgct's convention
                sgct::config::PlanarProjection projection;
                projection.fov.right = winControl->fovH() / 2.0;
                projection.fov.left = -projection.fov.right;
                projection.fov.up = winControl->fovV() / 2.0;
                projection.fov.down = -projection.fov.up;
                return projection;
            }
            break;
    }
}

std::string FileSupport::saveFilename() {
    return _saveTarget;
}

void FileSupport::save() {
    QString fileName = QFileDialog::getSaveFileName(this,
            "Save Window Configuration File", QString::fromStdString(_userConfigPath),
            "Window Configuration (*.json);;(*.json)", nullptr,
            QFileDialog::DontUseNativeDialog);
    if (fileName.length() != 0) {
        _saveTarget = fileName.toStdString();
        saveConfigToSgctFormat();
        _finishedCallback(true);
    }
}

void FileSupport::cancel() {
    _finishedCallback(false);
}

void FileSupport::apply() {
    std::string userCfgTempDir = _userConfigPath;
    if (userCfgTempDir.back() != '/') {
        userCfgTempDir += "/";
    }
    userCfgTempDir += "temp";
    if (!std::filesystem::is_directory(userCfgTempDir)) {
        std::filesystem::create_directories(absPath(userCfgTempDir));
    }
    _saveTarget = userCfgTempDir + "/" + "apply-without-saving.json";
    saveConfigToSgctFormat();
    _finishedCallback(true);
}

void FileSupport::saveConfigToSgctFormat() {
    saveCluster();
    saveWindows();
    saveUser();
}
<commit_msg>Change option for native OS file chooser dialog to linux only<commit_after>/*****************************************************************************************
 *                                                                                *
 * OpenSpace                                                                             *
 *                                                                                *
 * Copyright (c) 2014-2022                                                               *
 *                                                                                *
 * Permission is hereby granted, free of charge, to any person obtaining a copy of this  *
 * software and associated documentation files (the "Software"), to deal in the Software *
 * without restriction, including without limitation the rights to use, copy, modify,    *
 * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to    *
 * permit persons to whom the Software is furnished to do so, subject to the following   *
 * conditions:                                                                           *
 *                                                                                *
 * The above copyright notice and this permission notice shall be included in all copies *
 * or substantial portions of the Software.                                              *
 *                                                                                *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,   *
 * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A         *
 * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT    *
 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF  *
 * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE  *
 * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                                         *
 ****************************************************************************************/

#include "sgctedit/filesupport.h"

FileSupport::FileSupport(QVBoxLayout* parentLayout,
                         UserConfigurationElements& cfgElements,
                         SgctConfigElements& sgctElements,
                         std::function<void(bool)> finishedCallback)
    : _displayWidget(cfgElements.display)
    , _orientationWidget(cfgElements.orientation)
    , _monitors(cfgElements.monitorList)
    , _cluster(sgctElements.cluster)
    , _windowList(sgctElements.windowList)
    , _finishedCallback(finishedCallback)
    , _userConfigPath(cfgElements.configSavePath)
{
    QVBoxLayout* layoutFullVertical = new QVBoxLayout;
    _saveButton = new QPushButton("Save As");
    _saveButton->setToolTip("Save configuration changes (opens file chooser dialog)");
    connect(_saveButton, &QPushButton::released, this, &FileSupport::save);
    _cancelButton = new QPushButton("Cancel");
    _cancelButton->setToolTip("Cancel changes");
    connect(_cancelButton, &QPushButton::released, this, &FileSupport::cancel);
    _applyButton = new QPushButton("Apply Without Saving");
    _applyButton->setToolTip("Apply configuration changes without saving to file");
    connect(_applyButton, &QPushButton::released, this, &FileSupport::apply);
    {
        QHBoxLayout* layoutButtonBox = new QHBoxLayout;
        layoutButtonBox->addStretch(1);
        layoutButtonBox->addWidget(_cancelButton);
        layoutButtonBox->addWidget(_saveButton);
        layoutButtonBox->addWidget(_applyButton);
        layoutFullVertical->addLayout(layoutButtonBox);
    }
    parentLayout->addLayout(layoutFullVertical);
}

void FileSupport::saveCluster() {
    if (_orientationWidget) {
        sgct::config::Scene initScene;
        initScene.orientation = _orientationWidget->orientationValue();
        _cluster.nodes.clear();
        sgct::config::Node tmpNode;
        tmpNode.address = "localhost";
        tmpNode.port = 20401;
        _cluster.nodes.push_back(tmpNode);
        _cluster.masterAddress = "localhost";
        _cluster.scene = std::move(initScene);
        _cluster.firmSync = _orientationWidget->vsyncValue();
    }
}

void FileSupport::saveUser() {
    if (_orientationWidget) {
        sgct::config::User user;
        user.eyeSeparation = 0.065f;
        user.position = {0.0f, 0.0f, 4.0f};
        _cluster.users.push_back(user);
    }
}

bool FileSupport::isWindowFullscreen(unsigned int monitorIdx, sgct::ivec2 wDims) {
    return (_monitors[monitorIdx].width() == wDims.x &&
            _monitors[monitorIdx].height() == wDims.y);
}

std::optional<unsigned int> FileSupport::findGuiWindow() {
    unsigned int windowIndex = 0;
    for (unsigned int w = 0; w < _displayWidget->nWindows(); ++w) {
        if (_displayWidget->windowControls()[w]->isGuiWindow()) {
            return std::optional<unsigned int>(windowIndex);
        }
        windowIndex++;
    }
    return std::nullopt;
}

void FileSupport::saveWindows() {
    unsigned int windowIndex = 0;
    for (unsigned int w = 0; w < _displayWidget->nWindows(); ++w) {
        std::shared_ptr<WindowControl> wCtrl = _displayWidget->windowControls()[w];
        sgct::config::Window tmpWindow = saveWindowsDimensions(wCtrl);
        tmpWindow.viewports.push_back(generateViewport());
        tmpWindow.viewports.back().projection = saveProjectionInformation(wCtrl);
        tmpWindow.isDecorated = wCtrl->isDecorated();
        tmpWindow.isFullScreen = isWindowFullscreen(
            wCtrl->monitorNum(),
            wCtrl->windowSize()
        );
        saveWindowsWebGui(windowIndex, tmpWindow);
        if (!wCtrl->windowName().empty()) {
            tmpWindow.name = wCtrl->windowName();
        }
        tmpWindow.id = windowIndex++;
        _windowList.push_back(tmpWindow);
    }
}

sgct::config::Viewport FileSupport::generateViewport() {
    sgct::config::Viewport vp;
    vp.isTracked = true;
    vp.position = {0.f, 0.f};
    vp.size = {1.f, 1.f};
    return vp;
}

sgct::config::Window FileSupport::saveWindowsDimensions(
                                                     std::shared_ptr<WindowControl> wCtrl)
{
    sgct::config::Window tmpWindow;
    tmpWindow.size = wCtrl->windowSize();
    tmpWindow.pos = {
        _monitors[wCtrl->monitorNum()].x() + wCtrl->windowPos().x,
        _monitors[wCtrl->monitorNum()].y() + wCtrl->windowPos().y,
    };
    return tmpWindow;
}

void FileSupport::saveWindowsWebGui(unsigned int wIdx, sgct::config::Window& win) {
    win.viewports.back().isTracked = true;
    std::optional<unsigned int> webGuiWindowIndex = findGuiWindow();
    bool isOneOfWindowsSetAsWebGui = webGuiWindowIndex.has_value();
    if (isOneOfWindowsSetAsWebGui) {
        if (wIdx == webGuiWindowIndex.value()) {
            win.viewports.back().isTracked = false;
            win.tags.push_back("GUI");
        }
        win.draw2D = (wIdx == webGuiWindowIndex.value());
        win.draw3D = !(win.draw2D.value());
    }
}

ProjectionOptions FileSupport::saveProjectionInformation(
                                                std::shared_ptr<WindowControl> winControl)
{
    if (winControl->isSpoutSelected()) {
        return saveProjectionSpout(winControl);
    }
    else {
        return saveProjectionNoSpout(winControl);
    }
}

ProjectionOptions FileSupport::saveProjectionSpout(
                                                std::shared_ptr<WindowControl> winControl)
{
    sgct::config::SpoutOutputProjection projection;
    switch(winControl->projectionSelectedIndex()) {
        case WindowControl::ProjectionIndeces::Fisheye:
            projection.mapping
                = sgct::config::SpoutOutputProjection::Mapping::Fisheye;
            break;

        case WindowControl::ProjectionIndeces::Equirectangular:
        default:
            projection.mapping
                = sgct::config::SpoutOutputProjection::Mapping::Equirectangular;
            break;
    }
    projection.quality = winControl->qualitySelectedValue();
    projection.mappingSpoutName = "OpenSpace";
    return projection;
}

ProjectionOptions FileSupport::saveProjectionNoSpout(
                                                std::shared_ptr<WindowControl> winControl)
{
    switch(winControl->projectionSelectedIndex()) {
        case WindowControl::ProjectionIndeces::Fisheye:
            {
                sgct::config::FisheyeProjection projection;
                projection.quality = winControl->qualitySelectedValue();
                projection.fov = 180.f;
                projection.tilt = 0.f;
                return projection;
            }
            break;

        case WindowControl::ProjectionIndeces::SphericalMirror:
            {
                sgct::config::SphericalMirrorProjection projection;
                projection.quality = winControl->qualitySelectedValue();
                return projection;
            }
            break;

        case WindowControl::ProjectionIndeces::Cylindrical:
            {
                sgct::config::CylindricalProjection projection;
                projection.quality = winControl->qualitySelectedValue();
                projection.heightOffset = winControl->heightOffset();
                return projection;
            }
            break;

        case WindowControl::ProjectionIndeces::Equirectangular:
            {
                sgct::config::EquirectangularProjection projection;
                projection.quality = winControl->qualitySelectedValue();
                return projection;
            }
            break;

        case WindowControl::ProjectionIndeces::Planar:
        default:
            {
                // The negative values for left & down are according to sgct's convention
                sgct::config::PlanarProjection projection;
                projection.fov.right = winControl->fovH() / 2.0;
                projection.fov.left = -projection.fov.right;
                projection.fov.up = winControl->fovV() / 2.0;
                projection.fov.down = -projection.fov.up;
                return projection;
            }
            break;
    }
}

std::string FileSupport::saveFilename() {
    return _saveTarget;
}

void FileSupport::save() {
    QString fileName = QFileDialog::getSaveFileName(
        this,
        "Save Window Configuration File",
        QString::fromStdString(_userConfigPath),
        "Window Configuration (*.json);;(*.json)",
        nullptr
#ifdef __linux__
        , QFileDialog::DontUseNativeDialog
#endif
    );
    if (fileName.length() != 0) {
        _saveTarget = fileName.toStdString();
        saveConfigToSgctFormat();
        _finishedCallback(true);
    }
}

void FileSupport::cancel() {
    _finishedCallback(false);
}

void FileSupport::apply() {
    std::string userCfgTempDir = _userConfigPath;
    if (userCfgTempDir.back() != '/') {
        userCfgTempDir += "/";
    }
    userCfgTempDir += "temp";
    if (!std::filesystem::is_directory(userCfgTempDir)) {
        std::filesystem::create_directories(absPath(userCfgTempDir));
    }
    _saveTarget = userCfgTempDir + "/" + "apply-without-saving.json";
    saveConfigToSgctFormat();
    _finishedCallback(true);
}

void FileSupport::saveConfigToSgctFormat() {
    saveCluster();
    saveWindows();
    saveUser();
}
<|endoftext|>


<commit_before>/* dtkPluginManager.cpp ---
 *
 * Author: Julien Wintz
 * Copyright (C) 2008 - Julien Wintz, Inria.
 * Created: Tue Aug  4 12:20:59 2009 (+0200)
 * Version: $Id$
 * Last-Updated: Sun Jul 18 14:57:08 2010 (+0200)
 *           By: Julien Wintz
 *     Update #: 126
 */

/* Commentary:
 *
 */

/* Change log:
 *
 */

#include "dtkAbstractData.h"
#include "dtkPluginManager.h"

#include <dtkCore/dtkPlugin.h>
#include <dtkCore/dtkLog.h>

#define DTK_VERBOSE_LOAD false

class dtkPluginManagerPrivate
{
public:
    QString path;

    QHash<QString, QPluginLoader *> loaders;
};

dtkPluginManager *dtkPluginManager::instance(void)
{
    if(!s_instance) {
        s_instance = new dtkPluginManager;

        qRegisterMetaType<dtkAbstractData>("dtkAbstractData");
    }

    return s_instance;
}

void dtkPluginManager::initialize(void)
{
    if(d->path.isNull())
        this->readSettings();

	QString paths = "";

	if (!d->path.isEmpty())
		paths = d->path + ":";

	paths = paths +
#ifdef Q_WS_WIN
	qApp->applicationDirPath() + "\\..\\plugins";
#else
#ifdef Q_WS_MAC
	qApp->applicationDirPath() + "/../PlugIns";
#else
	qApp->applicationDirPath() + "/../plugins";
#endif
#endif

    foreach(QString path, paths.split(":", QString::SkipEmptyParts)) {

        QDir dir(path);
        dir.setFilter(QDir::AllEntries | QDir::NoDotAndDotDot);

        foreach (QFileInfo entry, dir.entryInfoList())
            loadPlugin(entry.absoluteFilePath());
    }
}

void dtkPluginManager::uninitialize(void)
{
    this->writeSettings();

    // foreach(QString path, d->loaders.keys())
    //     unloadPlugin(path);
}

void dtkPluginManager::readSettings(void)
{
    QSettings settings("inria", "dtk");
    settings.beginGroup("plugins");
#ifdef Q_WS_WIN
    d->path = settings.value("path", "C:\\Program Files\\inria\\plugins").toString();
#else
	d->path = settings.value("path", "/usr/local/inria/plugins").toString();
#endif

    settings.endGroup();

    if(d->path.isEmpty()) {
        dtkWarning() << "Your dtk config does not seem to be set correctly.";
        dtkWarning() << "Please set plugins.path.";
    }
}

void dtkPluginManager::writeSettings(void)
{
    QSettings settings("inria", "dtk");
    settings.beginGroup("plugins");
    settings.setValue("path", d->path);
    settings.endGroup();
}

void dtkPluginManager::printPlugins(void)
{
    foreach(QString path, d->loaders.keys())
        dtkOutput() << path;
}

dtkPlugin *dtkPluginManager::plugin(QString name)
{
    foreach(QPluginLoader *loader, d->loaders) {
        dtkPlugin *plugin = qobject_cast<dtkPlugin *>(loader->instance());

        if(plugin->name() == name)
            return plugin;
    }

    return NULL;
}

QList<dtkPlugin *> dtkPluginManager::plugins(void)
{
    QList<dtkPlugin *> list;

    foreach(QPluginLoader *loader, d->loaders)
        list << qobject_cast<dtkPlugin *>(loader->instance());

    return list;
}

void dtkPluginManager::setPath(const QString& path)
{
    d->path = path;
}

dtkPluginManager::dtkPluginManager(void) : d(new dtkPluginManagerPrivate)
{

}

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

    d = NULL;
}

void dtkPluginManager::loadPlugin(const QString& path)
{
    QPluginLoader *loader = new QPluginLoader(path);

    loader->setLoadHints (QLibrary::ExportExternalSymbolsHint);

    if(!loader->load()) {
        if(DTK_VERBOSE_LOAD) dtkDebug() << "Unable to load - " << loader->errorString();
        delete loader;
        return;
    }

    dtkPlugin *plugin = qobject_cast<dtkPlugin *>(loader->instance());

    if(!plugin) {
        if(DTK_VERBOSE_LOAD) dtkDebug() << "Unable to retrieve" << path;
        return;
    }

    if(!plugin->initialize()) {
        if(DTK_VERBOSE_LOAD) dtkOutput() << "Unable to initialize" << plugin->name() << "plugin";
        return;
    }

    d->loaders.insert(path, loader);

    emit loaded(plugin->name());
}

void dtkPluginManager::unloadPlugin(const QString& path)
{
    dtkPlugin *plugin = qobject_cast<dtkPlugin *>(d->loaders.value(path)->instance());

    if(!plugin) {
        if(DTK_VERBOSE_LOAD) dtkDebug() << "dtkPluginManager - Unable to retrieve" << plugin->name() << "plugin";
        return;
    }

    if(!plugin->uninitialize()) {
        if(DTK_VERBOSE_LOAD) dtkOutput() << "Unable to uninitialize" << plugin->name() << "plugin";
        return;
    }

    QPluginLoader *loader = d->loaders.value(path);

    if(!loader->unload()) {
        if(DTK_VERBOSE_LOAD) dtkDebug() << "dtkPluginManager - Unable to unload plugin:" << loader->errorString();
        return;
    }

    delete loader;

    d->loaders.remove(path);

    // emit unloaded(plugin->name());
}

dtkPluginManager *dtkPluginManager::s_instance = NULL;
<commit_msg>- uncommented the call to the unload operation when calling uninitialize.<commit_after>/* dtkPluginManager.cpp ---
 *
 * Author: Julien Wintz
 * Copyright (C) 2008 - Julien Wintz, Inria.
 * Created: Tue Aug  4 12:20:59 2009 (+0200)
 * Version: $Id$
 * Last-Updated: Sun Jul 18 14:57:08 2010 (+0200)
 *           By: Julien Wintz
 *     Update #: 126
 */

/* Commentary:
 *
 */

/* Change log:
 *
 */

#include "dtkAbstractData.h"
#include "dtkPluginManager.h"

#include <dtkCore/dtkPlugin.h>
#include <dtkCore/dtkLog.h>

#define DTK_VERBOSE_LOAD false

class dtkPluginManagerPrivate
{
public:
    QString path;

    QHash<QString, QPluginLoader *> loaders;
};

dtkPluginManager *dtkPluginManager::instance(void)
{
    if(!s_instance) {
        s_instance = new dtkPluginManager;

        qRegisterMetaType<dtkAbstractData>("dtkAbstractData");
    }

    return s_instance;
}

void dtkPluginManager::initialize(void)
{
    if(d->path.isNull())
        this->readSettings();

	QString paths = "";

	if (!d->path.isEmpty())
		paths = d->path + ":";

	paths = paths +
#ifdef Q_WS_WIN
	qApp->applicationDirPath() + "\\..\\plugins";
#else
#ifdef Q_WS_MAC
	qApp->applicationDirPath() + "/../PlugIns";
#else
	qApp->applicationDirPath() + "/../plugins";
#endif
#endif

    foreach(QString path, paths.split(":", QString::SkipEmptyParts)) {

        QDir dir(path);
        dir.setFilter(QDir::AllEntries | QDir::NoDotAndDotDot);

        foreach (QFileInfo entry, dir.entryInfoList())
            loadPlugin(entry.absoluteFilePath());
    }
}

void dtkPluginManager::uninitialize(void)
{
    this->writeSettings();

    foreach(QString path, d->loaders.keys())
        unloadPlugin(path);
}

void dtkPluginManager::readSettings(void)
{
    QSettings settings("inria", "dtk");
    settings.beginGroup("plugins");
#ifdef Q_WS_WIN
    d->path = settings.value("path", "C:\\Program Files\\inria\\plugins").toString();
#else
	d->path = settings.value("path", "/usr/local/inria/plugins").toString();
#endif

    settings.endGroup();

    if(d->path.isEmpty()) {
        dtkWarning() << "Your dtk config does not seem to be set correctly.";
        dtkWarning() << "Please set plugins.path.";
    }
}

void dtkPluginManager::writeSettings(void)
{
    QSettings settings("inria", "dtk");
    settings.beginGroup("plugins");
    settings.setValue("path", d->path);
    settings.endGroup();
}

void dtkPluginManager::printPlugins(void)
{
    foreach(QString path, d->loaders.keys())
        dtkOutput() << path;
}

dtkPlugin *dtkPluginManager::plugin(QString name)
{
    foreach(QPluginLoader *loader, d->loaders) {
        dtkPlugin *plugin = qobject_cast<dtkPlugin *>(loader->instance());

        if(plugin->name() == name)
            return plugin;
    }

    return NULL;
}

QList<dtkPlugin *> dtkPluginManager::plugins(void)
{
    QList<dtkPlugin *> list;

    foreach(QPluginLoader *loader, d->loaders)
        list << qobject_cast<dtkPlugin *>(loader->instance());

    return list;
}

void dtkPluginManager::setPath(const QString& path)
{
    d->path = path;
}

dtkPluginManager::dtkPluginManager(void) : d(new dtkPluginManagerPrivate)
{

}

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

    d = NULL;
}

void dtkPluginManager::loadPlugin(const QString& path)
{
    QPluginLoader *loader = new QPluginLoader(path);

    loader->setLoadHints (QLibrary::ExportExternalSymbolsHint);

    if(!loader->load()) {
        if(DTK_VERBOSE_LOAD) dtkDebug() << "Unable to load - " << loader->errorString();
        delete loader;
        return;
    }

    dtkPlugin *plugin = qobject_cast<dtkPlugin *>(loader->instance());

    if(!plugin) {
        if(DTK_VERBOSE_LOAD) dtkDebug() << "Unable to retrieve" << path;
        return;
    }

    if(!plugin->initialize()) {
        if(DTK_VERBOSE_LOAD) dtkOutput() << "Unable to initialize" << plugin->name() << "plugin";
        return;
    }

    d->loaders.insert(path, loader);

    emit loaded(plugin->name());
}

void dtkPluginManager::unloadPlugin(const QString& path)
{
    dtkPlugin *plugin = qobject_cast<dtkPlugin *>(d->loaders.value(path)->instance());

    if(!plugin) {
        if(DTK_VERBOSE_LOAD) dtkDebug() << "dtkPluginManager - Unable to retrieve" << plugin->name() << "plugin";
        return;
    }

    if(!plugin->uninitialize()) {
        if(DTK_VERBOSE_LOAD) dtkOutput() << "Unable to uninitialize" << plugin->name() << "plugin";
        return;
    }

    QPluginLoader *loader = d->loaders.value(path);

    if(!loader->unload()) {
        if(DTK_VERBOSE_LOAD) dtkDebug() << "dtkPluginManager - Unable to unload plugin:" << loader->errorString();
        return;
    }

    delete loader;

    d->loaders.remove(path);

    // emit unloaded(plugin->name());
}

dtkPluginManager *dtkPluginManager::s_instance = NULL;
<|endoftext|>


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

#include "application_manager/display_capabilities_builder.h"
#include "application_manager/message_helper.h"
#include "application_manager/smart_object_keys.h"
namespace application_manager {

CREATE_LOGGERPTR_GLOBAL(logger_, "DisplayCapabilitiesBuilder")

const WindowID kMainWindowID = 0;

DisplayCapabilitiesBuilder::DisplayCapabilitiesBuilder(Application& application)
    : owner_(application) {
  LOG4CXX_AUTO_TRACE(logger_);
}

void DisplayCapabilitiesBuilder::InitBuilder(
    DisplayCapabilitiesBuilder::ResumeCallback resume_callback,
    const smart_objects::SmartObject& windows_info) {
  LOG4CXX_AUTO_TRACE(logger_);
  sync_primitives::AutoLock lock(display_capabilities_lock_);
  resume_callback_ = resume_callback;
  window_ids_to_resume_.insert(kMainWindowID);
  for (size_t i = 0; i < windows_info.length(); ++i) {
    auto window_id = windows_info[i][strings::window_id].asInt();
    LOG4CXX_DEBUG(logger_,
                  "Inserting " << window_id << " to waiting container");
    window_ids_to_resume_.insert(window_id);
  }
}

void DisplayCapabilitiesBuilder::UpdateDisplayCapabilities(
    const smart_objects::SmartObject& incoming_display_capabilities) {
  LOG4CXX_AUTO_TRACE(logger_);
  using namespace smart_objects;
  sync_primitives::AutoLock lock(display_capabilities_lock_);

  if (!display_capabilities_) {
    display_capabilities_ = std::make_shared<SmartObject>(SmartType_Array);
  }

  // As per v6.0, only single display is supported
  auto cur_window_caps =
      (*display_capabilities_)[0][strings::window_capabilities];

  const auto& inc_window_caps =
      incoming_display_capabilities[0][strings::window_capabilities];

  for (size_t i = 0; i < inc_window_caps.length(); ++i) {
    const WindowID window_id =
        inc_window_caps[i].keyExists(strings::window_id)
            ? inc_window_caps[i][strings::window_id].asInt()
            : kMainWindowID;
    if (window_ids_to_resume_.end() != window_ids_to_resume_.find(window_id)) {
      cur_window_caps[cur_window_caps.length()] = inc_window_caps[i];
      LOG4CXX_DEBUG(logger_, "Stop waiting for: " << window_id);
      window_ids_to_resume_.erase(window_id);
    }
  }

  *display_capabilities_ = incoming_display_capabilities;
  (*display_capabilities_)[0][strings::window_capabilities] = cur_window_caps;

  if (window_ids_to_resume_.empty()) {
    LOG4CXX_TRACE(logger_, "Invoking resume callback");
    resume_callback_(owner_, *display_capabilities_);
    display_capabilities_.reset();
  }
}  // namespace application_manager

const smart_objects::SmartObjectSPtr
DisplayCapabilitiesBuilder::display_capabilities() const {
  LOG4CXX_AUTO_TRACE(logger_);
  return display_capabilities_;
}

void DisplayCapabilitiesBuilder::ResetDisplayCapabilities() {
  LOG4CXX_AUTO_TRACE(logger_);
  sync_primitives::AutoLock lock(display_capabilities_lock_);
  display_capabilities_.reset();
}

void DisplayCapabilitiesBuilder::StopWaitingForWindow(
    const WindowID window_id) {
  LOG4CXX_AUTO_TRACE(logger_);
  sync_primitives::AutoLock lock(display_capabilities_lock_);
  LOG4CXX_DEBUG(logger_,
                "Window id " << window_id << " will be erased due to failure");
  window_ids_to_resume_.erase(window_id);
  if (window_ids_to_resume_.empty()) {
    LOG4CXX_TRACE(logger_,
                  window_id << " was the last window pending resumption. "
                               "Invoking resume callback");
    resume_callback_(owner_, *display_capabilities_);
    display_capabilities_.reset();
  }
}
}  // namespace application_manager
<commit_msg>fixup! Send one OnSystemCapabilitiesUpdated on resumption<commit_after>/*
 * Copyright (c) 2019, Ford Motor Company
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * Redistributions of source code must retain the above copyright notice, this
 * list of conditions and the following disclaimer.
 *
 * Redistributions in binary form must reproduce the above copyright notice,
 * this list of conditions and the following
 * disclaimer in the documentation and/or other materials provided with the
 * distribution.
 *
 * Neither the name of the Ford Motor Company nor the names of its contributors
 * may be used to endorse or promote products derived from this software
 * without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

#include "application_manager/display_capabilities_builder.h"
#include "application_manager/message_helper.h"
#include "application_manager/smart_object_keys.h"
namespace application_manager {

CREATE_LOGGERPTR_GLOBAL(logger_, "DisplayCapabilitiesBuilder")

const WindowID kDefaultWindowID = 0;

DisplayCapabilitiesBuilder::DisplayCapabilitiesBuilder(Application& application)
    : owner_(application) {
  LOG4CXX_AUTO_TRACE(logger_);
}

void DisplayCapabilitiesBuilder::InitBuilder(
    DisplayCapabilitiesBuilder::ResumeCallback resume_callback,
    const smart_objects::SmartObject& windows_info) {
  LOG4CXX_AUTO_TRACE(logger_);
  sync_primitives::AutoLock lock(display_capabilities_lock_);
  resume_callback_ = resume_callback;
  window_ids_to_resume_.insert(kDefaultWindowID);
  for (size_t i = 0; i < windows_info.length(); ++i) {
    auto window_id = windows_info[i][strings::window_id].asInt();
    LOG4CXX_DEBUG(logger_,
                  "Inserting " << window_id << " to waiting container");
    window_ids_to_resume_.insert(window_id);
  }
}

void DisplayCapabilitiesBuilder::UpdateDisplayCapabilities(
    const smart_objects::SmartObject& incoming_display_capabilities) {
  LOG4CXX_AUTO_TRACE(logger_);
  using namespace smart_objects;
  sync_primitives::AutoLock lock(display_capabilities_lock_);

  if (!display_capabilities_) {
    display_capabilities_ = std::make_shared<SmartObject>(SmartType_Array);
  }

  // As per v6.0, only single display is supported
  auto cur_window_caps =
      (*display_capabilities_)[0][strings::window_capabilities];

  const auto& inc_window_caps =
      incoming_display_capabilities[0][strings::window_capabilities];

  for (size_t i = 0; i < inc_window_caps.length(); ++i) {
    const WindowID window_id =
        inc_window_caps[i].keyExists(strings::window_id)
            ? inc_window_caps[i][strings::window_id].asInt()
            : kDefaultWindowID;
    if (window_ids_to_resume_.end() != window_ids_to_resume_.find(window_id)) {
      cur_window_caps[cur_window_caps.length()] = inc_window_caps[i];
      LOG4CXX_DEBUG(logger_, "Stop waiting for: " << window_id);
      window_ids_to_resume_.erase(window_id);
    }
  }

  *display_capabilities_ = incoming_display_capabilities;
  (*display_capabilities_)[0][strings::window_capabilities] = cur_window_caps;

  if (window_ids_to_resume_.empty()) {
    LOG4CXX_TRACE(logger_, "Invoking resume callback");
    resume_callback_(owner_, *display_capabilities_);
    display_capabilities_.reset();
  }
}  // namespace application_manager

const smart_objects::SmartObjectSPtr
DisplayCapabilitiesBuilder::display_capabilities() const {
  LOG4CXX_AUTO_TRACE(logger_);
  return display_capabilities_;
}

void DisplayCapabilitiesBuilder::ResetDisplayCapabilities() {
  LOG4CXX_AUTO_TRACE(logger_);
  sync_primitives::AutoLock lock(display_capabilities_lock_);
  display_capabilities_.reset();
}

void DisplayCapabilitiesBuilder::StopWaitingForWindow(
    const WindowID window_id) {
  LOG4CXX_AUTO_TRACE(logger_);
  sync_primitives::AutoLock lock(display_capabilities_lock_);
  LOG4CXX_DEBUG(logger_,
                "Window id " << window_id << " will be erased due to failure");
  window_ids_to_resume_.erase(window_id);
  if (window_ids_to_resume_.empty()) {
    LOG4CXX_TRACE(logger_,
                  window_id << " was the last window pending resumption. "
                               "Invoking resume callback");
    resume_callback_(owner_, *display_capabilities_);
    display_capabilities_.reset();
  }
}
}  // namespace application_manager
<|endoftext|>


<commit_before>// main.cpp - Copyright 2013-2016 Will Cassella, All Rights Reserved

#include <Core/Application.h>
#include <Core/IO/Console.h>
#include "../include/AssetConverter/AssetConversion.h"

int main(int32 argCount, char** args)
{
	using namespace Willow;
	Application::Initialize();

	// If files were passed in via the command line
	if (argCount > 1)
	{
		AssetConversion::Convert(args[1], Array<String>());
		return 0;
	}

	Console::WriteLine("---Asset Converter---");
	Console::NewLine();
	Console::WriteLine("Enter the path to a file to convert:");

	while (true)
	{
		String path = Console::Prompt();
		Console::NewLine();

		if (path.IsEmpty())
		{
			break;
		}

		// @TODO: Parse options (setting compression level, renaming output)
		AssetConversion::Convert(path, Array<String>());
	}

	Application::Terminate();
}<commit_msg>Fixed some things that were bothering me with AssetConverter<commit_after>// main.cpp - Copyright 2013-2016 Will Cassella, All Rights Reserved

#include <Core/Application.h>
#include <Core/IO/Console.h>
#include "../include/AssetConverter/AssetConversion.h"

int main(int argCount, char** args)
{
	using namespace Willow;
	Application::Initialize();

	// If files were passed in via the command line
	if (argCount > 1)
	{
		AssetConversion::Convert(args[1], Array<String>());
		return 0;
	}

	Console::WriteLine("---Asset Converter---");
	Console::NewLine();
	Console::WriteLine("Enter the path to a file to convert:");

	while (true)
	{
		String path = Console::Prompt();
		Console::NewLine();

		if (path.IsEmpty())
		{
			break;
		}

		// @TODO: Parse options (setting compression level, renaming output)
		AssetConversion::Convert(path, Array<String>());
	}

	Application::Terminate();
}<|endoftext|>