<commit_before>#include <moveit/move_group_interface/move_group.h>
#include <moveit/planning_scene_interface/planning_scene_interface.h>

#include <moveit_msgs/DisplayRobotState.h>
#include <moveit_msgs/DisplayTrajectory.h>

#include <moveit_msgs/AttachedCollisionObject.h>
#include <moveit_msgs/CollisionObject.h>

#include "ros/ros.h"
#include "ur10_gripper_msgs/UR10.h"

#include <cmath>
#include <iostream>
#include <vector>

#define MOVETO 0
#define PUSH 1
#define TIMEDISTANCE 2
#define EXECUTE 3

std::vector<moveit::planning_interface::MoveGroup::Plan> plans;
int numPlans = 0;

double deg2rad(double d)
{
    double ratio = M_PI / 180.0;
    return d * ratio;
}

void setRPYGoal(geometry_msgs::Pose &goal, double roll, double pitch, double yaw)
{
    double y = yaw;
    double r = roll;
    double p = pitch;

    double t0 = std::cos(y * 0.5);
    double t1 = std::sin(y * 0.5);
    double t2 = std::cos(r * 0.5);
    double t3 = std::sin(r * 0.5);
    double t4 = std::cos(p * 0.5);
    double t5 = std::sin(p * 0.5);

    goal.orientation.w = t0 * t2 * t4 + t1 * t3 * t5;
    goal.orientation.x = t0 * t3 * t4 - t1 * t2 * t5;
    goal.orientation.y = t0 * t2 * t5 + t1 * t3 * t4;
    goal.orientation.z = t1 * t2 * t4 - t0 * t3 * t5;
    return;
}

bool moveTo(ur10_gripper_msgs::UR10::Request  &req,
            ur10_gripper_msgs::UR10::Response &res,
            moveit::planning_interface::MoveGroup &group)
{
    if(req.pose.size() < 6)
    {
        ROS_ERROR("Invalid Request Parameters:");
        ROS_ERROR("Provide X, Y, Z, R, P, Y in pose vector");
        return false;
    }
    ROS_INFO("Move Request Recieved");
    ROS_INFO_STREAM("X: " << req.pose.at(0) << " Y: " << req.pose.at(1)
                << " Z: " << req.pose.at(2) << " R: " << req.pose.at(3)
                << " P: " << req.pose.at(4) << " Y: " << req.pose.at(5));

    if(req.plan == true)
    {
        ROS_INFO("Planning Only Mode");
    }
    group.setPlanningTime(10.0);
    //group.setGoalPositionTolerance(0.1);
    geometry_msgs::Pose goal;

    goal.position.x = req.pose[0];
    goal.position.y = req.pose[1];
    goal.position.z = req.pose[2] - 1.43;
    setRPYGoal(goal, req.pose[3], req.pose[4], req.pose[5]);

    group.setPoseTarget(goal);

    moveit::planning_interface::MoveGroup::Plan my_plan;
    ROS_INFO_STREAM("Planning motion");
    res.success = group.plan(my_plan);

    sleep(3.0);
    //Actually Move if not a planning only request
    if(res.success)
    {
        if (req.plan == false)
        {
            ROS_INFO_STREAM("Moving to planned pose");
            res.success = group.execute(my_plan);
            sleep(5.0);
        }
        else
        {
            plans.push_back(my_plan);
            std::cout << "Plan stored as plan #" << plans.size() - 1 << std::endl;
        }
    }

    return true;
}

bool push(ur10_gripper_msgs::UR10::Request  &req,
          ur10_gripper_msgs::UR10::Response &res,
          moveit::planning_interface::MoveGroup &group)
{
    double leadDistance = 0.05;

    if(req.pose.size() < 4)
    {
        ROS_ERROR("Invalid Request Parameters:");
        ROS_ERROR("Provide X, Y, Z of object in pose vector");
        ROS_ERROR("followed by direction D that it should be pushed in degrees");
        return false;
    }
    ROS_INFO("Push Request Recieved");
    ROS_INFO_STREAM("X: " << req.pose.at(0) << " Y: " << req.pose.at(1)
                << " Z: " << req.pose.at(2));
    ROS_INFO_STREAM("Push Angle = " << req.pose.at(3));

    group.setPlanningTime(10.0);
    group.setNumPlanningAttempts(3);

    //Set object as collision

    //Move to Initial Pose
    geometry_msgs::Pose goal1;

    goal1.position.x = req.pose[0] - leadDistance * cos(req.pose[3]);
    goal1.position.y = req.pose[1] - leadDistance * sin(req.pose[3]);
    goal1.position.z = req.pose[2] - 1.43;
    setRPYGoal(goal1, 0.0, 0.0, req.pose[3]);

    group.setPoseTarget(goal1);

    moveit::planning_interface::MoveGroup::Plan my_plan;
    ROS_INFO_STREAM("Planning motion to initial Pose");
    res.success = group.plan(my_plan);
    sleep(3.0);
    if(res.success)
    {
        res.success = group.execute(my_plan);
        ROS_INFO_STREAM("Moving to initial Pose");
    }
    sleep(7.0);

    //Remove collision

    //Move with constraint
    /*
    moveit_msgs::OrientationConstraint ocm;
    ocm.link_name = group.getEndEffectorLink();
    ocm.orientation = goal1.orientation;
    ocm.absolute_x_axis_tolerance = 0.1;
    ocm.absolute_y_axis_tolerance = 0.1;
    ocm.absolute_z_axis_tolerance = 0.1;
    ocm.weight = 1.0;

    moveit_msgs::Constraints pushConstraint;
    pushConstraint.orientation_constraints.push_back(ocm);
    group.setPathConstraints(pushConstraint);
    */

    if(!res.success)
    {
        return true;
    }
    geometry_msgs::Pose goal2;

    goal2.position.x = req.pose[0] + leadDistance * cos(req.pose[3]);
    goal2.position.y = req.pose[1] + leadDistance * sin(req.pose[3]);
    goal2.position.z = req.pose[2] - 1.43;
    setRPYGoal(goal2, 0.0, 0.0, req.pose[3]);

    group.setPoseTarget(goal2);

    moveit::planning_interface::MoveGroup::Plan my_plan2;
    ROS_INFO_STREAM("Planning push");
    res.success = group.plan(my_plan2);
    sleep(3.0);
    if(res.success)
    {
        res.success = group.execute(my_plan2);
        ROS_INFO_STREAM("Pushing");
    }
    sleep(5.0);

    group.clearPathConstraints();

    return true;
}

void printStart(moveit::planning_interface::MoveGroup &group)
{
    std::cout << std::endl;
    std::cout << "Start Pose" << std::endl;
    std::cout << "X: " << group.getCurrentPose().pose.position.x
              << " Y: " << group.getCurrentPose().pose.position.y
              << " Z: " << group.getCurrentPose().pose.position.z + 1.43 << std::endl;

    std::cout << "Qx: " << group.getCurrentPose().pose.orientation.x
              << " Qy: " << group.getCurrentPose().pose.orientation.y
              << " Qz: " << group.getCurrentPose().pose.orientation.z
              << " Qw: " << group.getCurrentPose().pose.orientation.w << std::endl;

    for (int i = 0; i < 6; ++i)
    {
        std::cout << group.getJoints().at(i) << ": "
                  << group.getCurrentJointValues().at(i) << std::endl;
    }
    std::cout << std::endl;
}

void printGoal(geometry_msgs::Pose goal, moveit::planning_interface::MoveGroup &group,
                moveit::planning_interface::MoveGroup::Plan &plan)
{
    std::cout << "Goal Pose" << std::endl;
    std::cout << "X: " << goal.position.x
              << " Y: " << goal.position.y
              << " Z: " << goal.position.z + 1.43 << std::endl;

    std::cout << "Qx: " << goal.orientation.x
              << " Qy: " << goal.orientation.y
              << " Qz: " << goal.orientation.z
              << " Qw: " << goal.orientation.w << std::endl;

    std::vector<double> joints = plan.trajectory_.joint_trajectory.points.back().positions;
    for (int i = 0; i < 6; ++i)
    {
        std::cout << group.getJoints().at(i) << ": " << joints.at(i) << std::endl;
    }
    std::cout << std::endl;
    std::cout << "Time to Reach Goal State: "
              << plan.trajectory_.joint_trajectory.points.back().time_from_start
              << " Seconds " << std::endl;
}

bool timeDistance(ur10_gripper_msgs::UR10::Request  &req,
                  ur10_gripper_msgs::UR10::Response &res,
                  moveit::planning_interface::MoveGroup &group)
{
    if(req.pose.size() < 6)
    {
        ROS_ERROR("Invalid Request Parameters:");
        ROS_ERROR("Provide X, Y, Z, R, P, Y in pose vector");
        return false;
    }
    ROS_INFO("Time and Distance Request Recieved");
    ROS_INFO_STREAM("X: " << req.pose.at(0) << " Y: " << req.pose.at(1)
                << " Z: " << req.pose.at(2) << " R: " << req.pose.at(3)
                << " P: " << req.pose.at(4) << " Y: " << req.pose.at(5));

    group.setPlanningTime(10.0);
    //group.setGoalPositionTolerance(0.1);
    geometry_msgs::Pose goal;

    goal.position.x = req.pose[0];
    goal.position.y = req.pose[1];
    goal.position.z = req.pose[2] - 1.43;
    setRPYGoal(goal, req.pose[3], req.pose[4], req.pose[5]);

    group.setPoseTarget(goal);

    moveit::planning_interface::MoveGroup::Plan my_plan;
    ROS_INFO_STREAM("Planning motion");
    res.success = group.plan(my_plan);

    plans.push_back(my_plan);

    printStart(group);
    printGoal(goal, group, my_plan);

    std::cout << "Plan stored as plan #" << plans.size()-1 << std::endl;

    sleep(1.0);

    return true;
}

bool execute(ur10_gripper_msgs::UR10::Request  &req,
             ur10_gripper_msgs::UR10::Response &res,
             moveit::planning_interface::MoveGroup &group)
{
    if(req.pose.size() < 1)
    {
        ROS_ERROR("Invalid Request Parameters:");
        ROS_ERROR("Provide plan number in pose vector");
        return false;
    }
    ROS_INFO("Execution Request Recieved");
    int plan = (int)req.pose.at(0);
    if(plan > plans.size()-1)
    {
        ROS_ERROR("Invalid plan number, no plan with that number stored");
        return false;
    }
    ROS_INFO_STREAM("Executing Plan " << plan);
    group.execute(plans.at(plan));

    sleep(5.0);
}

bool action(ur10_gripper_msgs::UR10::Request  &req,
            ur10_gripper_msgs::UR10::Response &res)
{
    moveit::planning_interface::MoveGroup group("Arm");
    switch(req.request)
    {
        case MOVETO:
            moveTo(req, res, group);
            break;
        case PUSH:
            push(req, res, group);
            break;
        case TIMEDISTANCE:
            timeDistance(req, res, group);
            break;
        case EXECUTE:
            execute(req, res, group);
            break;
        default:
            ROS_ERROR("Invalid Request Recieved");
            break;
    }
    std::cout << std::endl;
    ROS_INFO("Ready to recieve commands");
    return true;
}

int main(int argc, char **argv)
{
	ros::init(argc, argv, "ur10_server");
  	ros::NodeHandle n;

    moveit::planning_interface::MoveGroup group("Arm");
    moveit::planning_interface::PlanningSceneInterface planning_scene_interface;

    //Checks if the frame has been loaded to prevent collision
    if(planning_scene_interface.getKnownObjectNames().size() < 6)
    {
        ROS_ERROR("Collision Objects not loaded!");
        ros::shutdown();
        return 1;
    }
    std::cout << std::endl;
    ROS_INFO("Ready to recieve commands");

    ros::ServiceServer service = n.advertiseService("UR10", action);
    ros::AsyncSpinner spinner(1);
    spinner.start();

    ros::Rate r(10);

    while (ros::ok())
    {
        ros::spinOnce();
        r.sleep();
    }

    ros::shutdown();
  	return 0;
}
<commit_msg>Change push to take push distance as an argument<commit_after>#include <moveit/move_group_interface/move_group.h>
#include <moveit/planning_scene_interface/planning_scene_interface.h>

#include <moveit_msgs/DisplayRobotState.h>
#include <moveit_msgs/DisplayTrajectory.h>

#include <moveit_msgs/AttachedCollisionObject.h>
#include <moveit_msgs/CollisionObject.h>

#include "ros/ros.h"
#include "ur10_gripper_msgs/UR10.h"

#include <cmath>
#include <iostream>
#include <vector>

#define MOVETO 0
#define PUSH 1
#define TIMEDISTANCE 2
#define EXECUTE 3

std::vector<moveit::planning_interface::MoveGroup::Plan> plans;
int numPlans = 0;

double deg2rad(double d)
{
    double ratio = M_PI / 180.0;
    return d * ratio;
}

void setRPYGoal(geometry_msgs::Pose &goal, double roll, double pitch, double yaw)
{
    double y = yaw;
    double r = roll;
    double p = pitch;

    double t0 = std::cos(y * 0.5);
    double t1 = std::sin(y * 0.5);
    double t2 = std::cos(r * 0.5);
    double t3 = std::sin(r * 0.5);
    double t4 = std::cos(p * 0.5);
    double t5 = std::sin(p * 0.5);

    goal.orientation.w = t0 * t2 * t4 + t1 * t3 * t5;
    goal.orientation.x = t0 * t3 * t4 - t1 * t2 * t5;
    goal.orientation.y = t0 * t2 * t5 + t1 * t3 * t4;
    goal.orientation.z = t1 * t2 * t4 - t0 * t3 * t5;
    return;
}

bool moveTo(ur10_gripper_msgs::UR10::Request  &req,
            ur10_gripper_msgs::UR10::Response &res,
            moveit::planning_interface::MoveGroup &group)
{
    if(req.pose.size() < 6)
    {
        ROS_ERROR("Invalid Request Parameters:");
        ROS_ERROR("Provide X, Y, Z, R, P, Y in pose vector");
        return false;
    }
    ROS_INFO("Move Request Recieved");
    ROS_INFO_STREAM("X: " << req.pose.at(0) << " Y: " << req.pose.at(1)
                << " Z: " << req.pose.at(2) << " R: " << req.pose.at(3)
                << " P: " << req.pose.at(4) << " Y: " << req.pose.at(5));

    if(req.plan == true)
    {
        ROS_INFO("Planning Only Mode");
    }
    group.setPlanningTime(10.0);
    //group.setGoalPositionTolerance(0.1);
    geometry_msgs::Pose goal;

    goal.position.x = req.pose[0];
    goal.position.y = req.pose[1];
    goal.position.z = req.pose[2] - 1.43;
    setRPYGoal(goal, req.pose[3], req.pose[4], req.pose[5]);

    group.setPoseTarget(goal);

    moveit::planning_interface::MoveGroup::Plan my_plan;
    ROS_INFO_STREAM("Planning motion");
    res.success = group.plan(my_plan);

    sleep(1.0);
    //Actually Move if not a planning only request
    if(res.success)
    {
        if (req.plan == false)
        {
            ROS_INFO_STREAM("Moving to planned pose");
            res.success = group.execute(my_plan);
            sleep(5.0);
        }
        /*
        else
        {
            plans.push_back(my_plan);
            std::cout << "Plan stored as plan #" << plans.size() - 1 << std::endl;
        }
        */
    }

    return true;
}

bool push(ur10_gripper_msgs::UR10::Request  &req,
          ur10_gripper_msgs::UR10::Response &res,
          moveit::planning_interface::MoveGroup &group)
{
    double leadDistance = 0.05;

    if(req.pose.size() < 5)
    {
        ROS_ERROR("Invalid Request Parameters:");
        ROS_ERROR("Provide X, Y, Z of object in pose vector");
        ROS_ERROR("followed by direction theta and distance d");
        return false;
    }
    ROS_INFO("Push Request Recieved");
    ROS_INFO_STREAM("X: " << req.pose.at(0) << " Y: " << req.pose.at(1)
                << " Z: " << req.pose.at(2));
    ROS_INFO_STREAM("Push Angle = " << req.pose.at(3));
    ROS_INFO_STREAM("Push Distance = " << req.pose.at(3));

    group.setPlanningTime(10.0);
    group.setNumPlanningAttempts(3);

    //Set object as collision

    //Move to Initial Pose
    geometry_msgs::Pose goal1;

    goal1.position.x = req.pose[0] - leadDistance * cos(req.pose[3]);
    goal1.position.y = req.pose[1] - leadDistance * sin(req.pose[3]);
    goal1.position.z = req.pose[2] - 1.43;
    setRPYGoal(goal1, 3.14, 0.0, req.pose[3]);

    group.setPoseTarget(goal1);

    moveit::planning_interface::MoveGroup::Plan my_plan;
    ROS_INFO_STREAM("Planning motion to initial Pose");
    res.success = group.plan(my_plan);
    sleep(3.0);
    if(res.success)
    {
        res.success = group.execute(my_plan);
        ROS_INFO_STREAM("Moving to initial Pose");
    }
    sleep(7.0);

    //Remove collision

    //Move with constraint
    /*
    moveit_msgs::OrientationConstraint ocm;
    ocm.link_name = group.getEndEffectorLink();
    ocm.orientation = goal1.orientation;
    ocm.absolute_x_axis_tolerance = 0.1;
    ocm.absolute_y_axis_tolerance = 0.1;
    ocm.absolute_z_axis_tolerance = 0.1;
    ocm.weight = 1.0;

    moveit_msgs::Constraints pushConstraint;
    pushConstraint.orientation_constraints.push_back(ocm);
    group.setPathConstraints(pushConstraint);
    */

    if(!res.success)
    {
        return true;
    }
    geometry_msgs::Pose goal2;

    goal2.position.x = req.pose[0] + req.pose[4] * cos(req.pose[3]);
    goal2.position.y = req.pose[1] + req.pose[4] * sin(req.pose[3]);
    goal2.position.z = req.pose[2] - 1.43;
    setRPYGoal(goal2, 3.14, 0.0, req.pose[3]);

    group.setPoseTarget(goal2);

    moveit::planning_interface::MoveGroup::Plan my_plan2;
    ROS_INFO_STREAM("Planning push");
    res.success = group.plan(my_plan2);
    sleep(3.0);
    if(res.success)
    {
        res.success = group.execute(my_plan2);
        ROS_INFO_STREAM("Pushing");
    }
    sleep(5.0);

    group.clearPathConstraints();

    return true;
}

void printStart(moveit::planning_interface::MoveGroup &group)
{
    std::cout << std::endl;
    std::cout << "Start Pose" << std::endl;
    std::cout << "X: " << group.getCurrentPose().pose.position.x
              << " Y: " << group.getCurrentPose().pose.position.y
              << " Z: " << group.getCurrentPose().pose.position.z + 1.43 << std::endl;

    std::cout << "Qx: " << group.getCurrentPose().pose.orientation.x
              << " Qy: " << group.getCurrentPose().pose.orientation.y
              << " Qz: " << group.getCurrentPose().pose.orientation.z
              << " Qw: " << group.getCurrentPose().pose.orientation.w << std::endl;

    for (int i = 0; i < 6; ++i)
    {
        std::cout << group.getJoints().at(i) << ": "
                  << group.getCurrentJointValues().at(i) << std::endl;
    }
    std::cout << std::endl;
}

void printGoal(geometry_msgs::Pose goal, moveit::planning_interface::MoveGroup &group,
                moveit::planning_interface::MoveGroup::Plan &plan)
{
    std::cout << "Goal Pose" << std::endl;
    std::cout << "X: " << goal.position.x
              << " Y: " << goal.position.y
              << " Z: " << goal.position.z + 1.43 << std::endl;

    std::cout << "Qx: " << goal.orientation.x
              << " Qy: " << goal.orientation.y
              << " Qz: " << goal.orientation.z
              << " Qw: " << goal.orientation.w << std::endl;

    std::vector<double> joints = plan.trajectory_.joint_trajectory.points.back().positions;
    for (int i = 0; i < 6; ++i)
    {
        std::cout << group.getJoints().at(i) << ": " << joints.at(i) << std::endl;
    }
    std::cout << std::endl;
    std::cout << "Time to Reach Goal State: "
              << plan.trajectory_.joint_trajectory.points.back().time_from_start
              << " Seconds " << std::endl;
}

bool timeDistance(ur10_gripper_msgs::UR10::Request  &req,
                  ur10_gripper_msgs::UR10::Response &res,
                  moveit::planning_interface::MoveGroup &group)
{
    if(req.pose.size() < 6)
    {
        ROS_ERROR("Invalid Request Parameters:");
        ROS_ERROR("Provide X, Y, Z, R, P, Y in pose vector");
        return false;
    }
    ROS_INFO("Time and Distance Request Recieved");
    ROS_INFO_STREAM("X: " << req.pose.at(0) << " Y: " << req.pose.at(1)
                << " Z: " << req.pose.at(2) << " R: " << req.pose.at(3)
                << " P: " << req.pose.at(4) << " Y: " << req.pose.at(5));

    group.setPlanningTime(10.0);
    //group.setGoalPositionTolerance(0.1);
    geometry_msgs::Pose goal;

    goal.position.x = req.pose[0];
    goal.position.y = req.pose[1];
    goal.position.z = req.pose[2] - 1.43;
    setRPYGoal(goal, req.pose[3], req.pose[4], req.pose[5]);

    group.setPoseTarget(goal);

    moveit::planning_interface::MoveGroup::Plan my_plan;
    ROS_INFO_STREAM("Planning motion");
    res.success = group.plan(my_plan);

    plans.push_back(my_plan);

    printStart(group);
    printGoal(goal, group, my_plan);

    std::cout << "Plan stored as plan #" << plans.size()-1 << std::endl;

    sleep(1.0);

    return true;
}

bool execute(ur10_gripper_msgs::UR10::Request  &req,
             ur10_gripper_msgs::UR10::Response &res,
             moveit::planning_interface::MoveGroup &group)
{
    if(req.pose.size() < 1)
    {
        ROS_ERROR("Invalid Request Parameters:");
        ROS_ERROR("Provide plan number in pose vector");
        return false;
    }
    ROS_INFO("Execution Request Recieved");
    int plan = (int)req.pose.at(0);
    if(plan > plans.size()-1)
    {
        ROS_ERROR("Invalid plan number, no plan with that number stored");
        return false;
    }
    ROS_INFO_STREAM("Executing Plan " << plan);
    group.execute(plans.at(plan));

    sleep(5.0);
}

bool action(ur10_gripper_msgs::UR10::Request  &req,
            ur10_gripper_msgs::UR10::Response &res)
{
    moveit::planning_interface::MoveGroup group("Arm");
    switch(req.request)
    {
        case MOVETO:
            moveTo(req, res, group);
            break;
        case PUSH:
            push(req, res, group);
            break;
        case TIMEDISTANCE:
            timeDistance(req, res, group);
            break;
        case EXECUTE:
            execute(req, res, group);
            break;
        default:
            ROS_ERROR("Invalid Request Recieved");
            break;
    }
    std::cout << std::endl;
    ROS_INFO("Ready to recieve commands");
    return true;
}

int main(int argc, char **argv)
{
	ros::init(argc, argv, "ur10_server");
  	ros::NodeHandle n;

    moveit::planning_interface::MoveGroup group("Arm");
    moveit::planning_interface::PlanningSceneInterface planning_scene_interface;

    //Checks if the frame has been loaded to prevent collision
    if(planning_scene_interface.getKnownObjectNames().size() < 6)
    {
        ROS_ERROR("Collision Objects not loaded!");
        ros::shutdown();
        return 1;
    }
    std::cout << std::endl;
    ROS_INFO("Ready to recieve commands");

    ros::ServiceServer service = n.advertiseService("UR10", action);
    ros::AsyncSpinner spinner(1);
    spinner.start();

    ros::Rate r(10);

    while (ros::ok())
    {
        ros::spinOnce();
        r.sleep();
    }

    ros::shutdown();
  	return 0;
}
<|endoftext|>


<commit_before>#include <iostream>
#include <memory>
#include <unistd.h>
#include <sys/param.h>
#include <dlfcn.h>
#include "AlarmSystemInterfaceProxy.h"
#include "asiConfigurationConstants.h"

using std::cout;
using std::cerr;
using namespace laserSource;
using asiConfigurationConstants::ALARM_SOURCE_NAME;

/*
 * Default no-args constructor.
 */
AlarmSystemInterfaceProxy::AlarmSystemInterfaceProxy()
{
	cout << "AlarmSystemInterfaceProxy::AlarmSystemInterfaceProxy(): entering...\n";
	init();
	cout << "AlarmSystemInterfaceProxy::AlarmSystemInterfaceProxy(): exiting...\n";
}

/*
 * Constructor.
 * @param theSourceName the name of the source. This should normally be the
 * one (and only one) source name defined in asiConfigurationConstants.h ALARM_SOURCE_NAME.
 */
AlarmSystemInterfaceProxy::AlarmSystemInterfaceProxy(string theSourceName)
{
	cout << "AlarmSystemInterfaceProxy::AlarmSystemInterfaceProxy(string): entering...\n";
	laserPublisher = NULL;
	setSourceName(theSourceName);
	string expectedSrcName(ALARM_SOURCE_NAME);
	if(theSourceName != expectedSrcName)
	{
		cout << "\n\nWARNING - source name: " << theSourceName << " will not work; all alarms should use: " << ALARM_SOURCE_NAME << "\n\n";
	}
	init();
	cout << "AlarmSystemInterfaceProxy::AlarmSystemInterfaceProxy(string): exiting...\n";
}

/*
 * Destructor.
 */
AlarmSystemInterfaceProxy::~AlarmSystemInterfaceProxy()
{
	cout << "AlarmSystemInterfaceProxy::~AlarmSystemInterfaceProxy(): entering...\n";
	delete laserPublisher;
	cout << "AlarmSystemInterfaceProxy::~AlarmSystemInterfaceProxy(): exiting...\n";
}

/**
 * Close and deallocate resources.
 */
void AlarmSystemInterfaceProxy::close()
{
}

/**
 * Push a collection of fault states.
 * @param states
 *
 * TODO later:
 * @throws ASIException if the fault state collection can not be pushed.
 */
void AlarmSystemInterfaceProxy::push(vector<FaultState> & states)
{
	cout << "AlarmSystemInterfaceProxy::push(vector): entering...\n";
	commonPush(states, true);
	cout << "AlarmSystemInterfaceProxy::push(vector): exiting...\n";
}

/**
 * Push a fault state.
 * @param state the fault state change to push.
 *
 * TODO later:
 * @throws ASIException if the fault state can not be pushed.
 */
void AlarmSystemInterfaceProxy::push(FaultState & state)
{
	cout << "AlarmSystemInterfaceProxy::push(FaultState): entering...\n";
	// create a vector and populate with the (single) fault state,
	// to be passed to the buildMessageXML method

	vector<FaultState> states;
	states.push_back(state);

	commonPush(states, false);
	cout << "AlarmSystemInterfaceProxy::push(FaultState): exiting...\n";
}

/**
 * Push the set of active fault states.
 * @param activeFaults the active fault states.
 *
 * TODO later:
 * @throws ASIException if the fault state active list can not be pushed.
 */
void AlarmSystemInterfaceProxy::pushActiveList(vector<FaultState> & activeFaults)
{
	cout << "AlarmSystemInterfaceProxy::pushActiveList(): entering...\n";
	push(activeFaults);
	cout << "AlarmSystemInterfaceProxy::pushActiveList(): exiting...\n";
}

/*
 * Sends a message to the alarm server, by loading a DLL that was specified in the configuration;
 * by doing this indirection, we facilitate the decoupling of the core laser cpp alarm source logic
 * from the actual communication mechanism, e.g. ACS/CORBA. Someone who wishes to use a different
 * communication mechanism need only implement their own DLL and the remainder of this code can be
 * reused as-is without any changes.
 *
 * The name of the shared library is configurable, currently in
 * asiConfigurationConstants.h, referenced through the Configuration class method
 * getPublisherDLLPath(), but eventually (TODO later:) to be moved to the CDB.
 * The name of the entry point to the DLL is well defined, not configurable, and is
 * referenced through the Configuration class method getPublisherFactoryFunctionPtr().
 *
 * TODO later: "syncbuffer" for maintaining active list, etc.
 */
bool AlarmSystemInterfaceProxy::publishMessageDLL(ASIMessage msg)
{
	cout << "AlarmSystemInterfaceProxy::publishMessageDLL(): entering...\n";
	bool retVal = false;

	// Instantiate the laserPublisher via the DLL, if it has not already been instantiated
	if(NULL == laserPublisher)
	{
		// create the topic on which to publish the alarm, by appending
		// the source name to the topic prefix provided by the configuration
		// (should look something like: CMW.ALARM_SYSTEM.ALARMS.SOURCES.ALARM_SYSTEM_SOURCES)
		string topicName(configuration.getAlarmsTopic());
		topicName.append(".");
		topicName.append(msg.getSourceName());

		// get the pointer to the publish function from the loaded DLL
		void *hndl = dlopen(configuration.getPublisherDLLPath().c_str(), RTLD_NOW|RTLD_GLOBAL);
		if(hndl == NULL)
		{
			cerr << "FATAL error: could not open DLL; error was:\n\n" << dlerror() << std::endl;
			exit(-1);
		}
		void * publisherFactoryFunctionPtr = dlsym(hndl, configuration.getPublisherFactoryFunctionName().c_str());
		laserPublisher = ((AlarmPublisher*(*)(string))(publisherFactoryFunctionPtr))(topicName);

		// check for success/failure
		if (NULL != laserPublisher)
		{
			retVal = true;
		}
		else
		{
			cerr << "FATAL error: could not get publisher from DLL; error was:\n\n" << dlerror() << std::endl;
			exit(-1);
		}
	}

	// publish the alarm via the class/method loaded from the DLL
	laserPublisher->publishAlarm(msg);

	cout << "AlarmSystemInterfaceProxy::publishMessageDLL(): exiting...\n";
	return retVal;
}

/**
 * Private method to push a collection of fault states, containing the
 * logic which is common to both the push() and pushActiveList() methods.
 *
 * @param states
 * @param backup whether we are sending 'backup' alarms or not. backup alarms
 *        are alarms in the active list that are sent on startup, when the source
 *        starts and periodically according to the expected backup frequency.
 *
 * TODO later:
 * @throws ASIException if the fault state collection can not be pushed.
 */
void AlarmSystemInterfaceProxy::commonPush(vector<FaultState> & states, bool backup)
{
	cout << "AlarmSystemInterfaceProxy::commonPush(): entering...\n";
	// create the ASIMessage, supplying the faults which are to be published to the alarm server
	vector<FaultState> * statesPtr = new vector<FaultState>(states);
	auto_ptr<vector<FaultState> > statesAutoPtr(statesPtr);
	ASIMessage asiMessage(statesAutoPtr);

	// populate the ASIMessage's source timestamp (with the current time)
	auto_ptr<Timestamp> timestampPtr(new Timestamp());
	asiMessage.setSourceTimestamp(timestampPtr);

	// populate the ASIMessage's source name
	asiMessage.setSourceName(sourceName);

	// populate the ASIMessage's source hostname
	asiMessage.setSourceHostname(hostname);

	// set the ASIMessage's backup flag
	asiMessage.setBackup(backup);

	// set the ASIMessage's version
	asiMessage.setVersion(configuration.getASIVersion());

	// publish the ASIMessage to the alarm server
	publishMessageDLL(asiMessage);
	//publishMessage(asiMessage);
	cout << "AlarmSystemInterfaceProxy::commonPush(): exiting...\n";
}

// initialization logic used by the constructors
void AlarmSystemInterfaceProxy::init()
{
	cout << "AlarmSystemInterfaceProxy::init(): entering...\n";
	// TODO later: portability/platform-specific issues with using gethostname()?
	char name[MAXHOSTNAMELEN + 1];
	gethostname(name, MAXHOSTNAMELEN);
	string nameStr(name);
	hostname = (nameStr);
	cout << "AlarmSystemInterfaceProxy::init(): exiting...\n";
}
<commit_msg>Added some debug messages<commit_after>#include <iostream>
#include <memory>
#include <unistd.h>
#include <sys/param.h>
#include <dlfcn.h>
#include "AlarmSystemInterfaceProxy.h"
#include "asiConfigurationConstants.h"

using std::cout;
using std::cerr;
using namespace laserSource;
using asiConfigurationConstants::ALARM_SOURCE_NAME;

/*
 * Default no-args constructor.
 */
AlarmSystemInterfaceProxy::AlarmSystemInterfaceProxy()
{
	cout << "AlarmSystemInterfaceProxy::AlarmSystemInterfaceProxy(): entering...\n";
	init();
	cout << "AlarmSystemInterfaceProxy::AlarmSystemInterfaceProxy(): exiting...\n";
}

/*
 * Constructor.
 * @param theSourceName the name of the source. This should normally be the
 * one (and only one) source name defined in asiConfigurationConstants.h ALARM_SOURCE_NAME.
 */
AlarmSystemInterfaceProxy::AlarmSystemInterfaceProxy(string theSourceName)
{
	cout << "AlarmSystemInterfaceProxy::AlarmSystemInterfaceProxy(string): entering...\n";
	laserPublisher = NULL;
	setSourceName(theSourceName);
	string expectedSrcName(ALARM_SOURCE_NAME);
	if(theSourceName != expectedSrcName)
	{
		cout << "\n\nWARNING - source name: " << theSourceName << " will not work; all alarms should use: " << ALARM_SOURCE_NAME << "\n\n";
	}
	init();
	cout << "AlarmSystemInterfaceProxy::AlarmSystemInterfaceProxy(string): exiting...\n";
}

/*
 * Destructor.
 */
AlarmSystemInterfaceProxy::~AlarmSystemInterfaceProxy()
{
	cout << "AlarmSystemInterfaceProxy::~AlarmSystemInterfaceProxy(): entering...\n";
	if (laserPublisher!=NULL) {
		delete laserPublisher;
		laserPublisher=NULL;
	}
	cout << "AlarmSystemInterfaceProxy::~AlarmSystemInterfaceProxy(): exiting...\n";
}

/**
 * Close and deallocate resources.
 */
void AlarmSystemInterfaceProxy::close()
{
}

/**
 * Push a collection of fault states.
 * @param states
 *
 * TODO later:
 * @throws ASIException if the fault state collection can not be pushed.
 */
void AlarmSystemInterfaceProxy::push(vector<FaultState> & states)
{
	cout << "AlarmSystemInterfaceProxy::push(vector): entering...\n";
	commonPush(states, true);
	cout << "AlarmSystemInterfaceProxy::push(vector): exiting...\n";
}

/**
 * Push a fault state.
 * @param state the fault state change to push.
 *
 * TODO later:
 * @throws ASIException if the fault state can not be pushed.
 */
void AlarmSystemInterfaceProxy::push(FaultState & state)
{
	cout << "AlarmSystemInterfaceProxy::push(FaultState): entering...\n";
	// create a vector and populate with the (single) fault state,
	// to be passed to the buildMessageXML method

	vector<FaultState> states;
	states.push_back(state);

	commonPush(states, false);
	cout << "AlarmSystemInterfaceProxy::push(FaultState): exiting...\n";
}

/**
 * Push the set of active fault states.
 * @param activeFaults the active fault states.
 *
 * TODO later:
 * @throws ASIException if the fault state active list can not be pushed.
 */
void AlarmSystemInterfaceProxy::pushActiveList(vector<FaultState> & activeFaults)
{
	cout << "AlarmSystemInterfaceProxy::pushActiveList(): entering...\n";
	push(activeFaults);
	cout << "AlarmSystemInterfaceProxy::pushActiveList(): exiting...\n";
}

/*
 * Sends a message to the alarm server, by loading a DLL that was specified in the configuration;
 * by doing this indirection, we facilitate the decoupling of the core laser cpp alarm source logic
 * from the actual communication mechanism, e.g. ACS/CORBA. Someone who wishes to use a different
 * communication mechanism need only implement their own DLL and the remainder of this code can be
 * reused as-is without any changes.
 *
 * The name of the shared library is configurable, currently in
 * asiConfigurationConstants.h, referenced through the Configuration class method
 * getPublisherDLLPath(), but eventually (TODO later:) to be moved to the CDB.
 * The name of the entry point to the DLL is well defined, not configurable, and is
 * referenced through the Configuration class method getPublisherFactoryFunctionPtr().
 *
 * TODO later: "syncbuffer" for maintaining active list, etc.
 */
bool AlarmSystemInterfaceProxy::publishMessageDLL(ASIMessage msg)
{
	cout << "AlarmSystemInterfaceProxy::publishMessageDLL(): entering...\n";
	bool retVal = false;

	// Instantiate the laserPublisher via the DLL, if it has not already been instantiated
	if(NULL == laserPublisher)
	{
		// create the topic on which to publish the alarm, by appending
		// the source name to the topic prefix provided by the configuration
		// (should look something like: CMW.ALARM_SYSTEM.ALARMS.SOURCES.ALARM_SYSTEM_SOURCES)
		string topicName(configuration.getAlarmsTopic());
		topicName.append(".");
		topicName.append(msg.getSourceName());

		// get the pointer to the publish function from the loaded DLL
		void *hndl = dlopen(configuration.getPublisherDLLPath().c_str(), RTLD_NOW|RTLD_GLOBAL);
		if(hndl == NULL)
		{
			cerr << "FATAL error: could not open DLL; error was:\n\n" << dlerror() << std::endl;
			exit(-1);
		}
		void * publisherFactoryFunctionPtr = dlsym(hndl, configuration.getPublisherFactoryFunctionName().c_str());
		laserPublisher = ((AlarmPublisher*(*)(string))(publisherFactoryFunctionPtr))(topicName);

		// check for success/failure
		if (NULL != laserPublisher)
		{
			retVal = true;
		}
		else
		{
			cerr << "FATAL error: could not get publisher from DLL; error was:\n\n" << dlerror() << std::endl;
			exit(-1);
		}
	}

	// publish the alarm via the class/method loaded from the DLL
	laserPublisher->publishAlarm(msg);

	cout << "AlarmSystemInterfaceProxy::publishMessageDLL(): exiting...\n";
	return retVal;
}

/**
 * Private method to push a collection of fault states, containing the
 * logic which is common to both the push() and pushActiveList() methods.
 *
 * @param states
 * @param backup whether we are sending 'backup' alarms or not. backup alarms
 *        are alarms in the active list that are sent on startup, when the source
 *        starts and periodically according to the expected backup frequency.
 *
 * TODO later:
 * @throws ASIException if the fault state collection can not be pushed.
 */
void AlarmSystemInterfaceProxy::commonPush(vector<FaultState> & states, bool backup)
{
	cout << "AlarmSystemInterfaceProxy::commonPush(): entering...\n";
	// create the ASIMessage, supplying the faults which are to be published to the alarm server
	vector<FaultState> * statesPtr = new vector<FaultState>(states);
	auto_ptr<vector<FaultState> > statesAutoPtr(statesPtr);
	ASIMessage asiMessage(statesAutoPtr);

	// populate the ASIMessage's source timestamp (with the current time)
	auto_ptr<Timestamp> timestampPtr(new Timestamp());
	asiMessage.setSourceTimestamp(timestampPtr);

	// populate the ASIMessage's source name
	asiMessage.setSourceName(sourceName);

	// populate the ASIMessage's source hostname
	asiMessage.setSourceHostname(hostname);

	// set the ASIMessage's backup flag
	asiMessage.setBackup(backup);

	// set the ASIMessage's version
	asiMessage.setVersion(configuration.getASIVersion());

	// publish the ASIMessage to the alarm server
	publishMessageDLL(asiMessage);
	//publishMessage(asiMessage);
	cout << "AlarmSystemInterfaceProxy::commonPush(): exiting...\n";
}

// initialization logic used by the constructors
void AlarmSystemInterfaceProxy::init()
{
	cout << "AlarmSystemInterfaceProxy::init(): entering...\n";
	// TODO later: portability/platform-specific issues with using gethostname()?
	char name[MAXHOSTNAMELEN + 1];
	gethostname(name, MAXHOSTNAMELEN);
	string nameStr(name);
	hostname = (nameStr);
	cout << "AlarmSystemInterfaceProxy::init(): exiting...\n";
}
<|endoftext|>


<commit_before>/*
 * CityManagementMenuComponent.cpp
 *
 *  Created on: Feb 12, 2012
 *      Author: xyborn
 */

#include "CityManagementMenuComponent.h"
#include "../CityRegion.h"
#include "server/zone/Zone.h"
#include "server/zone/packets/object/ObjectMenuResponse.h"
#include "server/zone/objects/creature/CreatureObject.h"
#include "server/zone/managers/city/CityManager.h"

void CityManagementMenuComponent::fillObjectMenuResponse(SceneObject* sceneObject, ObjectMenuResponse* menuResponse, CreatureObject* player) {
	CityRegion* city = sceneObject->getCityRegion();

	if (city == NULL)
		return;

	//City Information is available to anyone using the terminal and includes the options
		//Status Report, Citizenship Report, Structure Report, City Advancement, Maintenance Report, Treasury Report
	//and Treasury Deposit

	//

	menuResponse->addRadialMenuItem(211, 3, "@city/city:city_info"); //City Information
	menuResponse->addRadialMenuItemToRadialID(211, 212, 3, "@city/city:city_status"); //Status Report
	menuResponse->addRadialMenuItemToRadialID(211, 213, 3, "@city/city:city_citizens"); //Citizenship Report
	menuResponse->addRadialMenuItemToRadialID(211, 214, 3, "@city/city:city_structures"); //Structure Report
	menuResponse->addRadialMenuItemToRadialID(211, 223, 3, "@city/city:city_rank"); //City Advancement
	menuResponse->addRadialMenuItemToRadialID(211, 224, 3, "@city/city:city_maint"); //Maintenance Report
	menuResponse->addRadialMenuItemToRadialID(211, 215, 3, "@city/city:treasury_status"); //Treasury Report
	menuResponse->addRadialMenuItemToRadialID(211, 220, 3, "@city/city:treasury_deposit"); //Treasury Deposit

	if (!city->isMayor(player->getObjectID()))
		return;

	menuResponse->addRadialMenuItem(216, 3, "@city/city:city_management"); //City Management
	menuResponse->addRadialMenuItemToRadialID(216, 217, 3, "@city/city:city_name"); //Change City Name

	if (city->isRegistered()) {
		menuResponse->addRadialMenuItemToRadialID(216, 222, 3, "@city/city:city_unregister"); //Unregister City
	} else {
		menuResponse->addRadialMenuItemToRadialID(216, 222, 3, "@city/city:city_register"); //Register City
	}

	if (city->isZoningEnabled()) {
		menuResponse->addRadialMenuItemToRadialID(216, 226, 3, "@city/city:unzone"); //Disable Zoning
	} else {
		menuResponse->addRadialMenuItemToRadialID(216, 226, 3, "@city/city:zone"); //Enable Zoning
	}

	menuResponse->addRadialMenuItemToRadialID(216, 218, 3, "@city/city:city_militia"); //Manage Militia

	menuResponse->addRadialMenuItemToRadialID(216, 219, 3, "@city/city:treasury_taxes"); //Adjust Taxes

	menuResponse->addRadialMenuItemToRadialID(216, 221, 3, "@city/city:treasury_withdraw"); //Treasury Withdraw

	menuResponse->addRadialMenuItemToRadialID(216, 225, 3, "@city/city:city_specializations"); //City Specialization
}

int CityManagementMenuComponent::handleObjectMenuSelect(SceneObject* sceneObject, CreatureObject* player, byte selectID) {
	CityRegion* city = sceneObject->getCityRegion();

	if (city == NULL)
		return 1;

	Locker lock(city, player);

	Zone* zone = sceneObject->getZone();

	if (zone == NULL)
		return 1;

	CityManager* cityManager = zone->getCityManager();

	switch (selectID) {
	case 212: //Status Report
		cityManager->sendStatusReport(city, player, sceneObject);
		break;
	case 213: //Citizenship Report
		cityManager->sendCitizenshipReport(city, player, sceneObject);
		break;
	case 215: //Treasury Report
		cityManager->sendTreasuryReport(city, player, sceneObject);
		break;
	case 218: //Manage Militia
		cityManager->sendManageMilitia(city, player, sceneObject);
		break;
	case 220: //Treasury Deposit
		cityManager->promptDepositCityTreasury(city, player, sceneObject);
		break;
	case 221: //Withdraw Treasury
		cityManager->promptWithdrawCityTreasury(city, player, sceneObject);
		break;
	case 222: //Register/Unregister
		if (city->isRegistered())
			cityManager->promptRegisterCity(city, player, sceneObject);
		else
			cityManager->promptUnregisterCity(city, player, sceneObject);
	case 223: //City Advancement
		cityManager->sendCityAdvancement(city, player, sceneObject);
		break;
	case 225: //Set City Specialization
		cityManager->promptCitySpecialization(city, player, sceneObject);
		break;
	case 226: //Toggle Zoning Enabled
		cityManager->toggleZoningEnabled(city, player);
		break;
	}
	return 0;
}
<commit_msg>[added] strongref container on menucomponent<commit_after>/*
 * CityManagementMenuComponent.cpp
 *
 *  Created on: Feb 12, 2012
 *      Author: xyborn
 */

#include "CityManagementMenuComponent.h"
#include "../CityRegion.h"
#include "server/zone/Zone.h"
#include "server/zone/packets/object/ObjectMenuResponse.h"
#include "server/zone/objects/creature/CreatureObject.h"
#include "server/zone/managers/city/CityManager.h"

void CityManagementMenuComponent::fillObjectMenuResponse(SceneObject* sceneObject, ObjectMenuResponse* menuResponse, CreatureObject* player) {
	ManagedReference<CityRegion*> city = sceneObject->getCityRegion();

	if (city == NULL)
		return;

	//City Information is available to anyone using the terminal and includes the options
		//Status Report, Citizenship Report, Structure Report, City Advancement, Maintenance Report, Treasury Report
	//and Treasury Deposit

	//

	menuResponse->addRadialMenuItem(211, 3, "@city/city:city_info"); //City Information
	menuResponse->addRadialMenuItemToRadialID(211, 212, 3, "@city/city:city_status"); //Status Report
	menuResponse->addRadialMenuItemToRadialID(211, 213, 3, "@city/city:city_citizens"); //Citizenship Report
	menuResponse->addRadialMenuItemToRadialID(211, 214, 3, "@city/city:city_structures"); //Structure Report
	menuResponse->addRadialMenuItemToRadialID(211, 223, 3, "@city/city:city_rank"); //City Advancement
	menuResponse->addRadialMenuItemToRadialID(211, 224, 3, "@city/city:city_maint"); //Maintenance Report
	menuResponse->addRadialMenuItemToRadialID(211, 215, 3, "@city/city:treasury_status"); //Treasury Report
	menuResponse->addRadialMenuItemToRadialID(211, 220, 3, "@city/city:treasury_deposit"); //Treasury Deposit

	if (!city->isMayor(player->getObjectID()))
		return;

	menuResponse->addRadialMenuItem(216, 3, "@city/city:city_management"); //City Management
	menuResponse->addRadialMenuItemToRadialID(216, 217, 3, "@city/city:city_name"); //Change City Name

	if (city->isRegistered()) {
		menuResponse->addRadialMenuItemToRadialID(216, 222, 3, "@city/city:city_unregister"); //Unregister City
	} else {
		menuResponse->addRadialMenuItemToRadialID(216, 222, 3, "@city/city:city_register"); //Register City
	}

	if (city->isZoningEnabled()) {
		menuResponse->addRadialMenuItemToRadialID(216, 226, 3, "@city/city:unzone"); //Disable Zoning
	} else {
		menuResponse->addRadialMenuItemToRadialID(216, 226, 3, "@city/city:zone"); //Enable Zoning
	}

	menuResponse->addRadialMenuItemToRadialID(216, 218, 3, "@city/city:city_militia"); //Manage Militia

	menuResponse->addRadialMenuItemToRadialID(216, 219, 3, "@city/city:treasury_taxes"); //Adjust Taxes

	menuResponse->addRadialMenuItemToRadialID(216, 221, 3, "@city/city:treasury_withdraw"); //Treasury Withdraw

	menuResponse->addRadialMenuItemToRadialID(216, 225, 3, "@city/city:city_specializations"); //City Specialization
}

int CityManagementMenuComponent::handleObjectMenuSelect(SceneObject* sceneObject, CreatureObject* player, byte selectID) {
	ManagedReference<CityRegion*> city = sceneObject->getCityRegion();

	if (city == NULL)
		return 1;

	Locker lock(city, player);

	Zone* zone = sceneObject->getZone();

	if (zone == NULL)
		return 1;

	CityManager* cityManager = zone->getCityManager();

	switch (selectID) {
	case 212: //Status Report
		cityManager->sendStatusReport(city, player, sceneObject);
		break;
	case 213: //Citizenship Report
		cityManager->sendCitizenshipReport(city, player, sceneObject);
		break;
	case 215: //Treasury Report
		cityManager->sendTreasuryReport(city, player, sceneObject);
		break;
	case 218: //Manage Militia
		cityManager->sendManageMilitia(city, player, sceneObject);
		break;
	case 220: //Treasury Deposit
		cityManager->promptDepositCityTreasury(city, player, sceneObject);
		break;
	case 221: //Withdraw Treasury
		cityManager->promptWithdrawCityTreasury(city, player, sceneObject);
		break;
	case 222: //Register/Unregister
		if (city->isRegistered())
			cityManager->promptRegisterCity(city, player, sceneObject);
		else
			cityManager->promptUnregisterCity(city, player, sceneObject);
	case 223: //City Advancement
		cityManager->sendCityAdvancement(city, player, sceneObject);
		break;
	case 225: //Set City Specialization
		cityManager->promptCitySpecialization(city, player, sceneObject);
		break;
	case 226: //Toggle Zoning Enabled
		cityManager->toggleZoningEnabled(city, player);
		break;
	}
	return 0;
}
<|endoftext|>


<commit_before>#include "NotifyGVContactsTable.h"
#include "ContactsParserObject.h"

GVContactsTable::GVContactsTable (QObject *parent)
: QObject (parent)
, nwMgr (this)
, mutex(QMutex::Recursive)
, bLoggedIn(false)
, bRefreshRequested (false)
{
}//GVContactsTable::GVContactsTable

GVContactsTable::~GVContactsTable ()
{
}//GVContactsTable::~GVContactsTable

QNetworkReply *
GVContactsTable::postRequest (QString         strUrl,
                              QStringPairList arrPairs,
                              QObject        *receiver,
                              const char     *method)
{
    QStringList arrParams;
    foreach (QStringPair pairParam, arrPairs)
    {
        arrParams += QString("%1=%2")
                        .arg(pairParam.first)
                        .arg(pairParam.second);
    }
    QString strParams = arrParams.join ("&");

    QUrl url (strUrl);
    QNetworkRequest request(url);
    request.setHeader (QNetworkRequest::ContentTypeHeader,
                       "application/x-www-form-urlencoded");
    if (0 != strGoogleAuth.size ())
    {
        QByteArray byAuth = QString("GoogleLogin auth=%1")
                                    .arg(strGoogleAuth).toAscii ();
        request.setRawHeader ("Authorization", byAuth);
    }
    QByteArray byPostData = strParams.toAscii ();

    QObject::connect (&nwMgr   , SIGNAL (finished (QNetworkReply *)),
                       receiver, method);
    QNetworkReply *reply = nwMgr.post (request, byPostData);
    return (reply);
}//GVContactsTable::postRequest

QNetworkReply *
GVContactsTable::getRequest (QString         strUrl,
                             QObject        *receiver,
                             const char     *method)
{
    QUrl url (strUrl);
    QNetworkRequest request(url);
    request.setHeader (QNetworkRequest::ContentTypeHeader,
                       "application/x-www-form-urlencoded");
    if (0 != strGoogleAuth.size ())
    {
        QByteArray byAuth = QString("GoogleLogin auth=%1")
                                    .arg(strGoogleAuth).toAscii ();
        request.setRawHeader ("Authorization", byAuth);
    }

    QObject::connect (&nwMgr   , SIGNAL (finished (QNetworkReply *)),
                       receiver, method);
    QNetworkReply *reply = nwMgr.get (request);
    return (reply);
}//GVContactsTable::getRequest

void
GVContactsTable::refreshContacts ()
{
    QMutexLocker locker(&mutex);
    if (!bLoggedIn)
    {
        bRefreshRequested = true;
        return;
    }
    bRefreshRequested = false;
    bChangedSinceRefresh = false;

    QString strUrl = QString ("http://www.google.com/m8/feeds/contacts/%1/full"
                              "?max-results=10000")
                        .arg (strUser);

    bRefreshIsUpdate = false;
    if (dtUpdate.isValid ()) {
        QString strUpdate = dtUpdate.toString ("yyyy-MM-dd")
                          + "T"
                          + dtUpdate.toString ("hh:mm:ss");
        strUrl += QString ("&updated-min=%1&showdeleted=true").arg (strUpdate);
        bRefreshIsUpdate = true;
    }

    getRequest (strUrl, this , SLOT (onGotContacts (QNetworkReply *)));
}//GVContactsTable::refreshContacts

void
GVContactsTable::setUserPass (const QString &strU, const QString &strP)
{
    QMutexLocker locker(&mutex);
    strUser = strU;
    strPass = strP;
}//GVContactsTable::setUserPass

void
GVContactsTable::loginSuccess ()
{
    QMutexLocker locker(&mutex);

    QStringPairList arrPairs;
    arrPairs += QStringPair("accountType", "GOOGLE");
    arrPairs += QStringPair("Email"      , strUser);
    arrPairs += QStringPair("Passwd"     , strPass);
    arrPairs += QStringPair("service"    , "cp"); // name for contacts service
    arrPairs += QStringPair("source"     , "MyCompany-qgvdial-ver01");
    postRequest (GV_CLIENTLOGIN, arrPairs,
                 this , SLOT (onLoginResponse (QNetworkReply *)));
}//GVContactsTable::loginSuccess

void
GVContactsTable::loggedOut ()
{
    QMutexLocker locker(&mutex);
    bLoggedIn = false;

    strGoogleAuth.clear ();
}//GVContactsTable::loggedOut

void
GVContactsTable::onLoginResponse (QNetworkReply *reply)
{
    QObject::disconnect (&nwMgr, SIGNAL (finished (QNetworkReply *)),
                          this , SLOT   (onLoginResponse (QNetworkReply *)));

    QString msg;
    QString strReply = reply->readAll ();
    QString strCaptchaToken, strCaptchaUrl;

    strGoogleAuth.clear ();
    do // Begin cleanup block (not a loop)
    {
        QStringList arrParsed = strReply.split ('\n');
        foreach (QString strPair, arrParsed)
        {
            QStringList arrPair = strPair.split ('=');
            if (arrPair[0] == "Auth")
            {
                strGoogleAuth = arrPair[1];
            }
            else if (arrPair[0] == "CaptchaToken")
            {
                strCaptchaToken = arrPair[1];
            }
            else if (arrPair[0] == "CaptchaUrl")
            {
                strCaptchaUrl = arrPair[1];
            }
        }

        if (0 != strCaptchaUrl.size ())
        {
            qCritical ("Google requested CAPTCHA!!");
            qApp->quit ();

            break;
        }

        if (0 == strGoogleAuth.size ())
        {
            qWarning ("Failed to login!!");
            break;
        }

        QMutexLocker locker (&mutex);
        bLoggedIn = true;

        if (bRefreshRequested)
        {
            refreshContacts ();
        }
    } while (0); // End cleanup block (not a loop)
    reply->deleteLater ();
}//GVContactsTable::onLoginResponse

void
GVContactsTable::onGotContacts (QNetworkReply *reply)
{
    QObject::disconnect (&nwMgr, SIGNAL (finished (QNetworkReply *)),
                          this , SLOT   (onGotContacts (QNetworkReply *)));

    do // Begin cleanup block (not a loop)
    {
        QByteArray byData = reply->readAll ();
        if (byData.contains ("Authorization required"))
        {
            emit status("Authorization failed.");
            break;
        }

#if 0
        QFile temp("dump.txt");
        temp.open (QIODevice::ReadWrite);
        temp.write (byData);
        temp.close ();
#endif

        dtUpdate = QDateTime::currentDateTime().toUTC ();

        QThread *workerThread = new QThread(this);
        ContactsParserObject *pObj = new ContactsParserObject(byData);
        pObj->setEmitLog (false);
        pObj->moveToThread (workerThread);
        QObject::connect (workerThread, SIGNAL(started()),
                          pObj        , SLOT  (doWork()));
        QObject::connect (pObj, SIGNAL(done(bool)),
                          this, SLOT  (onContactsParsed(bool)));
        QObject::connect (pObj        , SIGNAL(done(bool)),
                          workerThread, SLOT  (quit()));
        QObject::connect (workerThread, SIGNAL(terminated()),
                          pObj        , SLOT  (deleteLater()));
        QObject::connect (workerThread, SIGNAL(terminated()),
                          workerThread, SLOT  (deleteLater()));
        QObject::connect (pObj, SIGNAL (status(const QString &, int)),
                          this, SIGNAL (status(const QString &, int)));
        QObject::connect (pObj, SIGNAL (gotOneContact (const ContactInfo &)),
                          this, SLOT   (gotOneContact (const ContactInfo &)));
        workerThread->start ();
    } while (0); // End cleanup block (not a loop)

    reply->deleteLater ();
}//GVContactsTable::onGotContacts

void
GVContactsTable::gotOneContact (const ContactInfo & /*contactInfo*/)
{
    QMutexLocker locker(&mutex);
    bChangedSinceRefresh = true;
}//GVContactsTable::gotOneContact

void
GVContactsTable::onContactsParsed (bool rv)
{
    emit allContacts (bChangedSinceRefresh, rv);
}//GVContactsTable::onContactsParsed
<commit_msg>fix notify signal slot to match the changes in qgvdial<commit_after>#include "NotifyGVContactsTable.h"
#include "ContactsParserObject.h"

GVContactsTable::GVContactsTable (QObject *parent)
: QObject (parent)
, nwMgr (this)
, mutex(QMutex::Recursive)
, bLoggedIn(false)
, bRefreshRequested (false)
{
}//GVContactsTable::GVContactsTable

GVContactsTable::~GVContactsTable ()
{
}//GVContactsTable::~GVContactsTable

QNetworkReply *
GVContactsTable::postRequest (QString         strUrl,
                              QStringPairList arrPairs,
                              QObject        *receiver,
                              const char     *method)
{
    QStringList arrParams;
    foreach (QStringPair pairParam, arrPairs)
    {
        arrParams += QString("%1=%2")
                        .arg(pairParam.first)
                        .arg(pairParam.second);
    }
    QString strParams = arrParams.join ("&");

    QUrl url (strUrl);
    QNetworkRequest request(url);
    request.setHeader (QNetworkRequest::ContentTypeHeader,
                       "application/x-www-form-urlencoded");
    if (0 != strGoogleAuth.size ())
    {
        QByteArray byAuth = QString("GoogleLogin auth=%1")
                                    .arg(strGoogleAuth).toAscii ();
        request.setRawHeader ("Authorization", byAuth);
    }
    QByteArray byPostData = strParams.toAscii ();

    QObject::connect (&nwMgr   , SIGNAL (finished (QNetworkReply *)),
                       receiver, method);
    QNetworkReply *reply = nwMgr.post (request, byPostData);
    return (reply);
}//GVContactsTable::postRequest

QNetworkReply *
GVContactsTable::getRequest (QString         strUrl,
                             QObject        *receiver,
                             const char     *method)
{
    QUrl url (strUrl);
    QNetworkRequest request(url);
    request.setHeader (QNetworkRequest::ContentTypeHeader,
                       "application/x-www-form-urlencoded");
    if (0 != strGoogleAuth.size ())
    {
        QByteArray byAuth = QString("GoogleLogin auth=%1")
                                    .arg(strGoogleAuth).toAscii ();
        request.setRawHeader ("Authorization", byAuth);
    }

    QObject::connect (&nwMgr   , SIGNAL (finished (QNetworkReply *)),
                       receiver, method);
    QNetworkReply *reply = nwMgr.get (request);
    return (reply);
}//GVContactsTable::getRequest

void
GVContactsTable::refreshContacts ()
{
    QMutexLocker locker(&mutex);
    if (!bLoggedIn)
    {
        bRefreshRequested = true;
        return;
    }
    bRefreshRequested = false;
    bChangedSinceRefresh = false;

    QString strUrl = QString ("http://www.google.com/m8/feeds/contacts/%1/full"
                              "?max-results=10000")
                        .arg (strUser);

    bRefreshIsUpdate = false;
    if (dtUpdate.isValid ()) {
        QString strUpdate = dtUpdate.toString ("yyyy-MM-dd")
                          + "T"
                          + dtUpdate.toString ("hh:mm:ss");
        strUrl += QString ("&updated-min=%1&showdeleted=true").arg (strUpdate);
        bRefreshIsUpdate = true;
    }

    getRequest (strUrl, this , SLOT (onGotContacts (QNetworkReply *)));
}//GVContactsTable::refreshContacts

void
GVContactsTable::setUserPass (const QString &strU, const QString &strP)
{
    QMutexLocker locker(&mutex);
    strUser = strU;
    strPass = strP;
}//GVContactsTable::setUserPass

void
GVContactsTable::loginSuccess ()
{
    QMutexLocker locker(&mutex);

    QStringPairList arrPairs;
    arrPairs += QStringPair("accountType", "GOOGLE");
    arrPairs += QStringPair("Email"      , strUser);
    arrPairs += QStringPair("Passwd"     , strPass);
    arrPairs += QStringPair("service"    , "cp"); // name for contacts service
    arrPairs += QStringPair("source"     , "MyCompany-qgvdial-ver01");
    postRequest (GV_CLIENTLOGIN, arrPairs,
                 this , SLOT (onLoginResponse (QNetworkReply *)));
}//GVContactsTable::loginSuccess

void
GVContactsTable::loggedOut ()
{
    QMutexLocker locker(&mutex);
    bLoggedIn = false;

    strGoogleAuth.clear ();
}//GVContactsTable::loggedOut

void
GVContactsTable::onLoginResponse (QNetworkReply *reply)
{
    QObject::disconnect (&nwMgr, SIGNAL (finished (QNetworkReply *)),
                          this , SLOT   (onLoginResponse (QNetworkReply *)));

    QString msg;
    QString strReply = reply->readAll ();
    QString strCaptchaToken, strCaptchaUrl;

    strGoogleAuth.clear ();
    do // Begin cleanup block (not a loop)
    {
        QStringList arrParsed = strReply.split ('\n');
        foreach (QString strPair, arrParsed)
        {
            QStringList arrPair = strPair.split ('=');
            if (arrPair[0] == "Auth")
            {
                strGoogleAuth = arrPair[1];
            }
            else if (arrPair[0] == "CaptchaToken")
            {
                strCaptchaToken = arrPair[1];
            }
            else if (arrPair[0] == "CaptchaUrl")
            {
                strCaptchaUrl = arrPair[1];
            }
        }

        if (0 != strCaptchaUrl.size ())
        {
            qCritical ("Google requested CAPTCHA!!");
            qApp->quit ();

            break;
        }

        if (0 == strGoogleAuth.size ())
        {
            qWarning ("Failed to login!!");
            break;
        }

        QMutexLocker locker (&mutex);
        bLoggedIn = true;

        if (bRefreshRequested)
        {
            refreshContacts ();
        }
    } while (0); // End cleanup block (not a loop)
    reply->deleteLater ();
}//GVContactsTable::onLoginResponse

void
GVContactsTable::onGotContacts (QNetworkReply *reply)
{
    QObject::disconnect (&nwMgr, SIGNAL (finished (QNetworkReply *)),
                          this , SLOT   (onGotContacts (QNetworkReply *)));

    do // Begin cleanup block (not a loop)
    {
        QByteArray byData = reply->readAll ();
        if (byData.contains ("Authorization required"))
        {
            emit status("Authorization failed.");
            break;
        }

#if 0
        QFile temp("dump.txt");
        temp.open (QIODevice::ReadWrite);
        temp.write (byData);
        temp.close ();
#endif

        dtUpdate = QDateTime::currentDateTime().toUTC ();

        QThread *workerThread = new QThread(this);
        ContactsParserObject *pObj = new ContactsParserObject(byData);
        pObj->setEmitLog (false);
        pObj->moveToThread (workerThread);
        QObject::connect (workerThread, SIGNAL(started()),
                          pObj        , SLOT  (doWork()));
        QObject::connect (pObj, SIGNAL(done(bool, quint32, quint32)),
                          this, SLOT  (onContactsParsed(bool)));
        QObject::connect (pObj        , SIGNAL(done(bool, quint32, quint32)),
                          workerThread, SLOT  (quit()));
        QObject::connect (workerThread, SIGNAL(terminated()),
                          pObj        , SLOT  (deleteLater()));
        QObject::connect (workerThread, SIGNAL(terminated()),
                          workerThread, SLOT  (deleteLater()));
        QObject::connect (pObj, SIGNAL (status(const QString &, int)),
                          this, SIGNAL (status(const QString &, int)));
        QObject::connect (pObj, SIGNAL (gotOneContact (const ContactInfo &)),
                          this, SLOT   (gotOneContact (const ContactInfo &)));
        workerThread->start ();
    } while (0); // End cleanup block (not a loop)

    reply->deleteLater ();
}//GVContactsTable::onGotContacts

void
GVContactsTable::gotOneContact (const ContactInfo & /*contactInfo*/)
{
    QMutexLocker locker(&mutex);
    bChangedSinceRefresh = true;
}//GVContactsTable::gotOneContact

void
GVContactsTable::onContactsParsed (bool rv)
{
    emit allContacts (bChangedSinceRefresh, rv);
}//GVContactsTable::onContactsParsed
<|endoftext|>


<commit_before>#include "Setup.h"

#include <gl/glew.h>
#include <SFML/OpenGL.hpp>

#include <random>

#include "../Engine/GEngine.h"
#include "../Engine/InputManager.h"
#include "../World/World.h"
#include "../Engine/Shader.h"
#include "../Engine/Mesh.h"
#include "../Logging/LogMacros.h"

#include "Player.h"
#include "FallingObject.h"

StaticMesh* Mesh = nullptr;
StaticMesh* Mesh2 = nullptr;
ShaderProgram* Program = nullptr;

void Input_Stop(const Input& Input)
{
	W_ENGINE.Stop();
}

void GameSetup()
{
	std::random_device rd;
	std::mt19937 gen(rd());
	std::uniform_real_distribution<> d(0, 1);

	// See Player.cpp for more explainations on the input system
	W_INPUT.Bind("Exit", INPUT_BIND(Keyboard, Released, Escape));
	W_INPUT.Event("Exit").Bind(&Input_Stop);

	// Make a single mesh for all to share
	Program = new ShaderProgram(ShaderProgram::LoadProgram("assets/shaders/basic.vert", "assets/shaders/basic.frag"));
	if (Program->GetProgram() == 0)
	{
		LOG_ERROR(GlobalLogger, "Something went wrong loading the shader program!");
	}

	GLint PositionAttr = glGetAttribLocation(Program->GetProgram(), "position");

	float Vertices[] = {
		-1, 0.0, 0.0,
		0.0, 2, 0.0,
		1, 0.0, 0.0,
	};

	GLuint vbo;
	GLuint vao;

	glGenBuffers(1, &vbo);
	glBindBuffer(GL_ARRAY_BUFFER, vbo);

	glGenVertexArrays(1, &vao);
	glBindVertexArray(vao);

	glBufferData(GL_ARRAY_BUFFER, sizeof(Vertices), Vertices, GL_STATIC_DRAW);
	glVertexAttribPointer(PositionAttr, 3, GL_FLOAT, GL_FALSE, 0, 0);
	glEnableVertexAttribArray(PositionAttr);

	Mesh = new StaticMesh(vbo, vao, 3, GL_TRIANGLES);

	float Vertices2[] = {
		-0.5, -0.5, 0.0,
		0.5, -0.5, 0.0,
		0.5, 0.5, 0.0,
		-0.5, 0.5, 0.0
	};

	glGenBuffers(1, &vbo);
	glBindBuffer(GL_ARRAY_BUFFER, vbo);

	glGenVertexArrays(1, &vao);
	glBindVertexArray(vao);

	glBufferData(GL_ARRAY_BUFFER, sizeof(Vertices2), Vertices2, GL_STATIC_DRAW);
	glVertexAttribPointer(PositionAttr, 3, GL_FLOAT, GL_FALSE, 0, 0);
	glEnableVertexAttribArray(PositionAttr);

	Mesh2 = new StaticMesh(vbo, vao, 4, GL_QUADS);

	auto p = W_WORLD.SpawnActor<Player>(true, Program, Mesh);
	p->SetScale(glm::vec3(0.2, 0.2, 1));

	for (int i = 0; i < 400; ++i)
	{
		auto o = W_WORLD.SpawnActor<FallingObject>(true, Program, Mesh2, p->GetActorID(), d(gen) * 2 - 1);
		o->SetScale(glm::vec3(0.02f, 0.08f, 1.0f));
		o->SetSpeed(d(gen) + 0.1f);
		o->SetPosition(o->GetPosition() + glm::vec3(0.f, d(gen) * 2 + 1, 0.f));
	}

	W_ENGINE.GetGameWindow().SetTitle("Rain Thing, use WASD+Space to move");
}

void GameTeardown()
{
	delete Mesh;
	delete Mesh2;
	delete Program;

	// Actors do not need to be deleted; they are automatically deleted by the world when the engine stops.
	// See Engine/Bootstrap.cpp and World/World.cpp
}<commit_msg>running slow lol<commit_after>#include "Setup.h"

#include <gl/glew.h>
#include <SFML/OpenGL.hpp>

#include <random>

#include "../Engine/GEngine.h"
#include "../Engine/InputManager.h"
#include "../World/World.h"
#include "../Engine/Shader.h"
#include "../Engine/Mesh.h"
#include "../Logging/LogMacros.h"

#include "Player.h"
#include "FallingObject.h"

StaticMesh* Mesh = nullptr;
StaticMesh* Mesh2 = nullptr;
ShaderProgram* Program = nullptr;

void Input_Stop(const Input& Input)
{
	W_ENGINE.Stop();
}

void GameSetup()
{
	std::random_device rd;
	std::mt19937 gen(rd());
	std::uniform_real_distribution<> d(0, 1);

	// See Player.cpp for more explainations on the input system
	W_INPUT.Bind("Exit", INPUT_BIND(Keyboard, Released, Escape));
	W_INPUT.Event("Exit").Bind(&Input_Stop);

	// Make a single mesh for all to share
	Program = new ShaderProgram(ShaderProgram::LoadProgram("assets/shaders/basic.vert", "assets/shaders/basic.frag"));
	if (Program->GetProgram() == 0)
	{
		LOG_ERROR(GlobalLogger, "Something went wrong loading the shader program!");
	}

	GLint PositionAttr = glGetAttribLocation(Program->GetProgram(), "position");

	float Vertices[] = {
		-1, 0.0, 0.0,
		0.0, 2, 0.0,
		1, 0.0, 0.0,
	};

	GLuint vbo;
	GLuint vao;

	glGenBuffers(1, &vbo);
	glBindBuffer(GL_ARRAY_BUFFER, vbo);

	glGenVertexArrays(1, &vao);
	glBindVertexArray(vao);

	glBufferData(GL_ARRAY_BUFFER, sizeof(Vertices), Vertices, GL_STATIC_DRAW);
	glVertexAttribPointer(PositionAttr, 3, GL_FLOAT, GL_FALSE, 0, 0);
	glEnableVertexAttribArray(PositionAttr);

	Mesh = new StaticMesh(vbo, vao, 3, GL_TRIANGLES);

	float Vertices2[] = {
		-0.5, -0.5, 0.0,
		0.5, -0.5, 0.0,
		0.5, 0.5, 0.0,
		-0.5, 0.5, 0.0
	};

	glGenBuffers(1, &vbo);
	glBindBuffer(GL_ARRAY_BUFFER, vbo);

	glGenVertexArrays(1, &vao);
	glBindVertexArray(vao);

	glBufferData(GL_ARRAY_BUFFER, sizeof(Vertices2), Vertices2, GL_STATIC_DRAW);
	glVertexAttribPointer(PositionAttr, 3, GL_FLOAT, GL_FALSE, 0, 0);
	glEnableVertexAttribArray(PositionAttr);

	Mesh2 = new StaticMesh(vbo, vao, 4, GL_QUADS);

	auto p = W_WORLD.SpawnActor<Player>(true, Program, Mesh);
	p->SetScale(glm::vec3(0.2, 0.2, 1));

	for (int i = 0; i < 400; ++i) // IF THIS RUNS SLOW, CHANGE 400 TO 200
	{
		auto o = W_WORLD.SpawnActor<FallingObject>(true, Program, Mesh2, p->GetActorID(), d(gen) * 2 - 1);
		o->SetScale(glm::vec3(0.02f, 0.08f, 1.0f));
		o->SetSpeed(d(gen) + 0.1f);
		o->SetPosition(o->GetPosition() + glm::vec3(0.f, d(gen) * 2 + 1, 0.f));
	}

	W_ENGINE.GetGameWindow().SetTitle("Rain Thing, use WASD+Space to move");
}

void GameTeardown()
{
	delete Mesh;
	delete Mesh2;
	delete Program;

	// Actors do not need to be deleted; they are automatically deleted by the world when the engine stops.
	// See Engine/Bootstrap.cpp and World/World.cpp
}<|endoftext|>


<commit_before>#include "stdafx.h"
#include "EventReceiverTest.h"
#include "Autowiring/Autowired.h"
#include "Autowiring/CoreThread.h"
#include <stdexcept>
#include <vector>

using namespace std;

class invalid_copycounter_exception:
  public runtime_error
{
public:
  invalid_copycounter_exception(void):
    runtime_error("Copy counter was moved, and incorrectly reused")
  {}
};

class CopyCounter {
public:
  CopyCounter(void):
    m_count(0)
  {}

  CopyCounter(const CopyCounter& rhs):
    m_count(rhs.m_count + 1)
  {
    rhs.Check();
  }

  /// <summary>
  /// Special case move ctor, which won't increment the count
  /// </summary>
  CopyCounter(CopyCounter&& rhs):
    m_count(rhs.m_count)
  {
    rhs.Check();
    rhs.m_count = -1;
  }

  /// <summary>
  /// Destructor, which invalidates the count in a specific way to indicate use-after-free
  /// </summary>
  ~CopyCounter(void) {
    m_count = -2;
  }

  // The actual count:
  int m_count;

  // Throws an exception if this copycounter is invalid
  void Check(void) const {
    if(m_count < 0)
      throw invalid_copycounter_exception();
  }

  // Copy and move overrides
  CopyCounter& operator=(const CopyCounter& rhs) {
    rhs.Check();
    m_count = rhs.m_count + 1;
    return *this;
  }

  CopyCounter& operator=(CopyCounter&& rhs) {
    rhs.Check();
    m_count = rhs.m_count;
    rhs.m_count = -1;
    return *this;
  }
};

class CallableInterface:
  public EventReceiver
{
public:
  virtual void ZeroArgs(void) = 0;
  virtual void OneArg(int arg) = 0;
  virtual void CopyVector(const vector<int>& vec) = 0;
  virtual void CopyVectorForwarded(vector<int>&& vec) = 0;
  virtual void TrackCopy(CopyCounter&& ctr) = 0;
  virtual void AllDone(void) = 0;
};

class SimpleSender:
  public EventManager<CallableInterface>
{
};

class SimpleReceiver:
  public CoreThread,
  public CallableInterface
{
public:
  SimpleReceiver(void):
    CoreThread("SimpleReceiver"),
    m_zero(false),
    m_one(false),
    m_oneArg(0),
    m_barrier(2),
    m_barrierDone(false)
  {
    Ready();
  }

private:
  // Continuity barrier, used to pause processing while in Run
  boost::barrier m_barrier;
  bool m_barrierDone;

public:
  // Manifest of functions called:
  bool m_zero;

  bool m_one;
  int m_oneArg;

  // Copy operation fields:
  vector<int> m_myVec;
  CopyCounter m_myCtr;

  ///
  // Interface utility methods:
  ///
  void ZeroArgs(void) override {
    m_zero = true;
  }

  void OneArg(int arg) override {
    m_one = true;
    m_oneArg = arg;
  }

  void CopyVector(const vector<int>& vec) override {
    // Copy out the argument:
    m_myVec = vec;
  }

  void CopyVectorForwarded(vector<int>&& vec) override {
    // Copy out the argument:
    m_myVec = vec;
  }

  void TrackCopy(CopyCounter&& ctr) override {
    m_myCtr = ctr;
  }

  // Trivial shutdown override
  void AllDone(void) override {
    Stop();
  }

  // Overridden here so we can hit the barrier if we're still waiting on it
  void Stop() override {
    Proceed();
    CoreThread::Stop();
  }

  /// <summary>
  /// Invoked to cause Run to continue its processing
  /// </summary>
  void Proceed(void) {
    if(!m_barrierDone)
      m_barrier.wait();
    m_barrierDone = true;
  }

  ///
  // Runs the thread
  ///
  void Run(void) override {
    m_barrier.wait();
    CoreThread::Run();
  }
};

EventReceiverTest::EventReceiverTest(void) {
  AutoCurrentContext ctxt;

  // Start up the context:
  ctxt->InitiateCoreThreads();
}

TEST_F(EventReceiverTest, SimpleMethodCall) {
  // Try firing the event first:
  sender->Fire(&CallableInterface::ZeroArgs)();
  sender->Fire(&CallableInterface::OneArg)(100);

  // Verify that stuff happens even when the thread isn't running:
  EXPECT_TRUE(receiver->m_zero);
  EXPECT_TRUE(receiver->m_one);
  EXPECT_EQ(100, receiver->m_oneArg);

  // Unblock:
  receiver->Proceed();
}

TEST_F(EventReceiverTest, DeferredInvoke) {
  // Deferred fire:
  sender->Defer(&CallableInterface::ZeroArgs)();
  sender->Defer(&CallableInterface::OneArg)(101);
  sender->Defer(&CallableInterface::AllDone)();

  // Verify that nothing is hit yet:
  EXPECT_FALSE(receiver->m_zero) << "Zero-argument call made prematurely";
  EXPECT_FALSE(receiver->m_one) << "One-argument call made prematurely";
  EXPECT_TRUE(receiver->IsRunning()) << "Receiver is terminated";

  // Unblock:
  receiver->Proceed();

  // Now wait until all events are processed:
  receiver->Wait();

  // Validate deferred firing:
  EXPECT_TRUE(receiver->m_zero);
  EXPECT_TRUE(receiver->m_one);
  EXPECT_EQ(101, receiver->m_oneArg) << "Argument was not correctly propagated through a deferred call";
}

TEST_F(EventReceiverTest, NontrivialCopy) {
  static const size_t sc_numElems = 10;

  // Create the vector we're going to copy over:
  vector<int> ascending;
  for(size_t i = 0; i < sc_numElems; i++)
    ascending.push_back(i);

  // Deferred fire:
  sender->Defer(&CallableInterface::CopyVector)(ascending);
  sender->Defer(&CallableInterface::AllDone)();

  // Verify that nothing is hit yet:
  EXPECT_TRUE(receiver->m_myVec.empty()) << "Event handler invoked before barrier was hit; it should have been deferred";
  EXPECT_TRUE(receiver->IsRunning()) << "Receiver is terminated";

  // Unblock:
  receiver->Proceed();

  // Now wait until all events are processed:
  receiver->Wait();

  // Validate our vectors:
  ASSERT_EQ(10, receiver->m_myVec.size()) << "Receiver was not populated correctly with a vector";
  for(size_t i = 0; i < sc_numElems; i++)
    EXPECT_EQ(i, ascending[i]) << "Element at offset " << i << " was incorrectly copied";
}

TEST_F(EventReceiverTest, VerifyNoUnnecessaryCopies) {
  // Verify the counter correctly tracks the number of times it was copied:
  {
    CopyCounter antiRecycle;
    CopyCounter base;

    CopyCounter myCopy1 = base;
    ASSERT_EQ(1, myCopy1.m_count) << "Copy counter appears to be broken; cannot run test";

    CopyCounter myCopy2 = myCopy1;
    ASSERT_EQ(2, myCopy2.m_count) << "Secondary counter appears to be broken; cannot run test";

    // Try move construction:
    CopyCounter myCopy3(std::move(myCopy2));
    ASSERT_EQ(2, myCopy3.m_count) << "Move ctor doesn't appear to be invoked correctly";

    // Verify antirecycle:
    ASSERT_THROW(antiRecycle = myCopy2, invalid_copycounter_exception);

    // Try a move copy
    CopyCounter myCopy4;
    myCopy4 = std::move(myCopy3);
    ASSERT_EQ(2, myCopy4.m_count) << "Move assignment didn't correctly propagate the current count";
    ASSERT_THROW(antiRecycle = myCopy3, invalid_copycounter_exception);

    // Try a trivial copy:
    CopyCounter myCopy5;
    myCopy5 = myCopy4;
    ASSERT_EQ(3, myCopy5.m_count) << "Assignment operator did not increment reference count";
  }

  // Make our copy counter:
  CopyCounter ctr;

  // Pass the field in:
  sender->Defer(&CallableInterface::TrackCopy)(
    ctr
  );

  // Signal stop:
  sender->Defer(&CallableInterface::AllDone)();

  // Let the sender process and then wait for it before we go on:
  receiver->Proceed();
  receiver->Wait();

  // Check to make sure we only copied the counter once:
  CopyCounter& finalCtr = receiver->m_myCtr;
  EXPECT_EQ(1, finalCtr.m_count) << "Transfer object was copied too many times";
}
<commit_msg>Total number of copies reduced to just two<commit_after>#include "stdafx.h"
#include "EventReceiverTest.h"
#include "Autowiring/Autowired.h"
#include "Autowiring/CoreThread.h"
#include <stdexcept>
#include <vector>

using namespace std;

class invalid_copycounter_exception:
  public runtime_error
{
public:
  invalid_copycounter_exception(void):
    runtime_error("Copy counter was moved, and incorrectly reused")
  {}
};

class CopyCounter {
public:
  CopyCounter(void):
    m_count(0)
  {}

  CopyCounter(const CopyCounter& rhs):
    m_count(rhs.m_count + 1)
  {
    rhs.Check();
  }

  /// <summary>
  /// Special case move ctor, which won't increment the count
  /// </summary>
  CopyCounter(CopyCounter&& rhs):
    m_count(rhs.m_count)
  {
    rhs.Check();
    rhs.m_count = -1;
  }

  /// <summary>
  /// Destructor, which invalidates the count in a specific way to indicate use-after-free
  /// </summary>
  ~CopyCounter(void) {
    m_count = -2;
  }

  // The actual count:
  int m_count;

  // Throws an exception if this copycounter is invalid
  void Check(void) const {
    if(m_count < 0)
      throw invalid_copycounter_exception();
  }

  // Copy and move overrides
  CopyCounter& operator=(const CopyCounter& rhs) {
    rhs.Check();
    m_count = rhs.m_count + 1;
    return *this;
  }

  CopyCounter& operator=(CopyCounter&& rhs) {
    rhs.Check();
    m_count = rhs.m_count;
    rhs.m_count = -1;
    return *this;
  }
};

class CallableInterface:
  public EventReceiver
{
public:
  virtual void ZeroArgs(void) = 0;
  virtual void OneArg(int arg) = 0;
  virtual void CopyVector(const vector<int>& vec) = 0;
  virtual void CopyVectorForwarded(vector<int>&& vec) = 0;
  virtual void TrackCopy(CopyCounter&& ctr) = 0;
  virtual void AllDone(void) = 0;
};

class SimpleSender:
  public EventManager<CallableInterface>
{
};

class SimpleReceiver:
  public CoreThread,
  public CallableInterface
{
public:
  SimpleReceiver(void):
    CoreThread("SimpleReceiver"),
    m_zero(false),
    m_one(false),
    m_oneArg(0),
    m_barrier(2),
    m_barrierDone(false)
  {
    Ready();
  }

private:
  // Continuity barrier, used to pause processing while in Run
  boost::barrier m_barrier;
  bool m_barrierDone;

public:
  // Manifest of functions called:
  bool m_zero;

  bool m_one;
  int m_oneArg;

  // Copy operation fields:
  vector<int> m_myVec;
  CopyCounter m_myCtr;

  ///
  // Interface utility methods:
  ///
  void ZeroArgs(void) override {
    m_zero = true;
  }

  void OneArg(int arg) override {
    m_one = true;
    m_oneArg = arg;
  }

  void CopyVector(const vector<int>& vec) override {
    // Copy out the argument:
    m_myVec = vec;
  }

  void CopyVectorForwarded(vector<int>&& vec) override {
    // Copy out the argument:
    m_myVec = vec;
  }

  void TrackCopy(CopyCounter&& ctr) override {
    m_myCtr = std::forward<CopyCounter>(ctr);
  }

  // Trivial shutdown override
  void AllDone(void) override {
    Stop();
  }

  // Overridden here so we can hit the barrier if we're still waiting on it
  void Stop() override {
    Proceed();
    CoreThread::Stop();
  }

  /// <summary>
  /// Invoked to cause Run to continue its processing
  /// </summary>
  void Proceed(void) {
    if(!m_barrierDone)
      m_barrier.wait();
    m_barrierDone = true;
  }

  ///
  // Runs the thread
  ///
  void Run(void) override {
    m_barrier.wait();
    CoreThread::Run();
  }
};

EventReceiverTest::EventReceiverTest(void) {
  AutoCurrentContext ctxt;

  // Start up the context:
  ctxt->InitiateCoreThreads();
}

TEST_F(EventReceiverTest, SimpleMethodCall) {
  // Try firing the event first:
  sender->Fire(&CallableInterface::ZeroArgs)();
  sender->Fire(&CallableInterface::OneArg)(100);

  // Verify that stuff happens even when the thread isn't running:
  EXPECT_TRUE(receiver->m_zero);
  EXPECT_TRUE(receiver->m_one);
  EXPECT_EQ(100, receiver->m_oneArg);

  // Unblock:
  receiver->Proceed();
}

TEST_F(EventReceiverTest, DeferredInvoke) {
  // Deferred fire:
  sender->Defer(&CallableInterface::ZeroArgs)();
  sender->Defer(&CallableInterface::OneArg)(101);
  sender->Defer(&CallableInterface::AllDone)();

  // Verify that nothing is hit yet:
  EXPECT_FALSE(receiver->m_zero) << "Zero-argument call made prematurely";
  EXPECT_FALSE(receiver->m_one) << "One-argument call made prematurely";
  EXPECT_TRUE(receiver->IsRunning()) << "Receiver is terminated";

  // Unblock:
  receiver->Proceed();

  // Now wait until all events are processed:
  receiver->Wait();

  // Validate deferred firing:
  EXPECT_TRUE(receiver->m_zero);
  EXPECT_TRUE(receiver->m_one);
  EXPECT_EQ(101, receiver->m_oneArg) << "Argument was not correctly propagated through a deferred call";
}

TEST_F(EventReceiverTest, NontrivialCopy) {
  static const size_t sc_numElems = 10;

  // Create the vector we're going to copy over:
  vector<int> ascending;
  for(size_t i = 0; i < sc_numElems; i++)
    ascending.push_back(i);

  // Deferred fire:
  sender->Defer(&CallableInterface::CopyVector)(ascending);
  sender->Defer(&CallableInterface::AllDone)();

  // Verify that nothing is hit yet:
  EXPECT_TRUE(receiver->m_myVec.empty()) << "Event handler invoked before barrier was hit; it should have been deferred";
  EXPECT_TRUE(receiver->IsRunning()) << "Receiver is terminated";

  // Unblock:
  receiver->Proceed();

  // Now wait until all events are processed:
  receiver->Wait();

  // Validate our vectors:
  ASSERT_EQ(10, receiver->m_myVec.size()) << "Receiver was not populated correctly with a vector";
  for(size_t i = 0; i < sc_numElems; i++)
    EXPECT_EQ(i, ascending[i]) << "Element at offset " << i << " was incorrectly copied";
}

TEST_F(EventReceiverTest, VerifyNoUnnecessaryCopies) {
  // Verify the counter correctly tracks the number of times it was copied:
  {
    CopyCounter antiRecycle;
    CopyCounter base;

    CopyCounter myCopy1 = base;
    ASSERT_EQ(1, myCopy1.m_count) << "Copy counter appears to be broken; cannot run test";

    CopyCounter myCopy2 = myCopy1;
    ASSERT_EQ(2, myCopy2.m_count) << "Secondary counter appears to be broken; cannot run test";

    // Try move construction:
    CopyCounter myCopy3(std::move(myCopy2));
    ASSERT_EQ(2, myCopy3.m_count) << "Move ctor doesn't appear to be invoked correctly";

    // Verify antirecycle:
    ASSERT_THROW(antiRecycle = myCopy2, invalid_copycounter_exception);

    // Try a move copy
    CopyCounter myCopy4;
    myCopy4 = std::move(myCopy3);
    ASSERT_EQ(2, myCopy4.m_count) << "Move assignment didn't correctly propagate the current count";
    ASSERT_THROW(antiRecycle = myCopy3, invalid_copycounter_exception);

    // Try a trivial copy:
    CopyCounter myCopy5;
    myCopy5 = myCopy4;
    ASSERT_EQ(3, myCopy5.m_count) << "Assignment operator did not increment reference count";
  }

  // Make our copy counter:
  CopyCounter ctr;

  // Pass the field in:
  sender->Defer(&CallableInterface::TrackCopy)(
    ctr
  );

  // Signal stop:
  sender->Defer(&CallableInterface::AllDone)();

  // Let the sender process and then wait for it before we go on:
  receiver->Proceed();
  receiver->Wait();

  // Check to make sure we only copied the counter once:
  CopyCounter& finalCtr = receiver->m_myCtr;
  EXPECT_EQ(1, finalCtr.m_count) << "Transfer object was copied too many times";
}
<|endoftext|>


<commit_before>#define _USE_MATH_DEFINES

#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
#include <tlhelp32.h>
#include <math.h>

#include "../mumble_plugin.h"

HANDLE h = NULL;

static DWORD getProcess(const wchar_t *exename) {
	PROCESSENTRY32 pe;
	DWORD pid = 0;

	pe.dwSize = sizeof(pe);
	HANDLE hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
	if (hSnap != INVALID_HANDLE_VALUE) {
		BOOL ok = Process32First(hSnap, &pe);

		while (ok) {
			if (wcscmp(pe.szExeFile, exename)==0) {
				pid = pe.th32ProcessID;
				break;
			}
			ok = Process32Next(hSnap, &pe);
		}
		CloseHandle(hSnap);
	}
	return pid;
}

static bool peekProc(VOID *base, VOID *dest, SIZE_T len) {
	SIZE_T r;
	BOOL ok=ReadProcessMemory(h, base, dest, len, &r);
	return (ok && (r == len));
}

static void about(HWND h) {
	::MessageBox(h, L"Reads audio position information from Call of Duty: Modern Warfare 2 Multiplayer v1.0.172). IP:Port context without team discriminator.", L"Mumble CoDMW2 MP Plugin", MB_OK);
}

static int fetch(float *avatar_pos, float *avatar_front, float *avatar_top, float *camera_pos, float *camera_front, float *camera_top, std::string &context, std::wstring &identity) {
	float viewHor, viewVer;
	char state;
	char ccontext[128];

	for (int i=0;i<3;i++)
		avatar_pos[i]=avatar_front[i]=avatar_top[i]=0.0f;

	bool ok;

	/*
		This plugin uses the following Variables:

			Address			Type	Description
			===================================
			0x0085C668		float	Z-Coordinate
			0x0085C66C		float	X-Coordinate
			0x0085C670		float	Y-Coordinate
			0x0085C654		float	Horizontal view (degrees)
			0x0085C650		float	Vertical view (degrees)

			0x007EE19D		byte	Magical state value
	*/
	ok = peekProc((BYTE *) 0x007EE19D, &state, 1); // Magical state value
	if (! ok)
		return false;
	/*
		state value is:
		0		while not in game
		4		while playing
		0		while spectating

		This value is used for disabling PA for spectators
		or people not on a server.
	*/
	if (state != 4)
		return true; // This results in all vectors beeing zero which tells mumble to ignore them.

	ok = peekProc((BYTE *) 0x008EA528, avatar_pos+2, 4) &&	//Z
	     peekProc((BYTE *) 0x008EA52C, avatar_pos, 4) &&	//X
	     peekProc((BYTE *) 0x008EA530, avatar_pos+1, 4) && //Y
	     peekProc((BYTE *) 0x008EA538, &viewHor, 4) && //Hor
	     peekProc((BYTE *) 0x008EA534, &viewVer, 4) && //Ver
	     peekProc((BYTE *) 0x00A7C950, ccontext, 128);

	if (! ok)
		return false;

	/*
	    Get context string; in this plugin this will be an
	    ip:port (char 256 bytes) string.
		If you start your own server, the string for this address will be "localhost".
	*/
	ccontext[127] = 0;
	context = std::string(ccontext);

	// Scale Coordinates
	/*
	   Z-Value is increasing when heading north
				  decreasing when heading south
	   X-Value is increasing when heading west
				  decreasing when heading east
	   Y-Value is increasing when going up
				  decreasing when going down
	   40 units = 1 meter (not confirmed)
	*/
	for (int i=0;i<3;i++)
		avatar_pos[i]/=40.0f; // Scale to meters
	avatar_pos[0]*=(-1.0f); // Convert right to left handed

	avatar_top[2] = -1; // Head movement is in front vector

	// Calculate view unit vector
	/*
	   Vertical view 0 when centered
					85	when looking down
				   275 when looking up
	   Decreasing when looking up.

	   Horizontal is 0 when facing North
					90 when facing West
				   180 when facing South
				   270 when facing East
	   Increasing when turning left.
	*/
	viewVer *= static_cast<float>(M_PI / 180.0f);
	viewHor *= static_cast<float>(M_PI / 180.0f);

	avatar_front[0] = -sin(viewHor) * cos(viewVer);
	avatar_front[1] = -sin(viewVer);
	avatar_front[2] = cos(viewHor) * cos(viewVer);

	for (int i=0;i<3;i++) {
		camera_pos[i] = avatar_pos[i];
		camera_front[i] = avatar_front[i];
		camera_top[i] = avatar_top[i];
	}

	return ok;
}

static int trylock() {
	h = NULL;
	DWORD pid=getProcess(L"iw4mp.exe");
	if (!pid)
		return false;

	h=OpenProcess(PROCESS_VM_READ, false, pid);
	if (!h)
		return false;

	float apos[3], afront[3], atop[3], cpos[3], cfront[3], ctop[3];
	std::string context;
	std::wstring identity;

	if (fetch(apos, afront, atop, cpos, cfront, ctop, context, identity))
		return true;

	CloseHandle(h);
	h = NULL;
	return false;
}

static void unlock() {
	if (h) {
		CloseHandle(h);
		h = NULL;
	}
}

static const std::wstring longdesc() {
	return std::wstring(L"Supports Call of Duty: Modern Warfare 2 MP v1.0.172 only. No identity support yet.");
}

static std::wstring description(L"Call of Duty: Modern Warfare 2 MP v1.0.172");
static std::wstring shortname(L"Call of Duty: Modern Warfare 2 MP");

static MumblePlugin codmw2plug = {
	MUMBLE_PLUGIN_MAGIC,
	description,
	shortname,
	about,
	NULL,
	trylock,
	unlock,
	longdesc,
	fetch
};

extern "C" __declspec(dllexport) MumblePlugin *getMumblePlugin() {
	return &codmw2plug;
}
<commit_msg>Update MW2; remove useless context<commit_after>#define _USE_MATH_DEFINES

#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
#include <tlhelp32.h>
#include <math.h>

#include "../mumble_plugin.h"

HANDLE h = NULL;

static DWORD getProcess(const wchar_t *exename) {
	PROCESSENTRY32 pe;
	DWORD pid = 0;

	pe.dwSize = sizeof(pe);
	HANDLE hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
	if (hSnap != INVALID_HANDLE_VALUE) {
		BOOL ok = Process32First(hSnap, &pe);

		while (ok) {
			if (wcscmp(pe.szExeFile, exename)==0) {
				pid = pe.th32ProcessID;
				break;
			}
			ok = Process32Next(hSnap, &pe);
		}
		CloseHandle(hSnap);
	}
	return pid;
}

static bool peekProc(VOID *base, VOID *dest, SIZE_T len) {
	SIZE_T r;
	BOOL ok=ReadProcessMemory(h, base, dest, len, &r);
	return (ok && (r == len));
}

static void about(HWND h) {
	::MessageBox(h, L"Reads audio position information from Call of Duty: Modern Warfare 2 Multiplayer v1.0.174). IP:Port context without team discriminator.", L"Mumble CoDMW2 MP Plugin", MB_OK);
}

static int fetch(float *avatar_pos, float *avatar_front, float *avatar_top, float *camera_pos, float *camera_front, float *camera_top, std::string &context, std::wstring &identity) {
	float viewHor, viewVer;
	char state;

	for (int i=0;i<3;i++)
		avatar_pos[i]=avatar_front[i]=avatar_top[i]=0.0f;

	bool ok;

	/*
		This plugin uses the following Variables:

			Address			Type	Description
			===================================
			0x0085C668		float	Z-Coordinate
			0x0085C66C		float	X-Coordinate
			0x0085C670		float	Y-Coordinate
			0x0085C654		float	Horizontal view (degrees)
			0x0085C650		float	Vertical view (degrees)

			0x007EE19D		byte	Magical state value
	*/
	ok = peekProc((BYTE *) 0x007EF19D, &state, 1); // Magical state value
	if (! ok)
		return false;
	/*
		state value is:
		0		while not in game
		4		while playing
		0		while spectating

		This value is used for disabling PA for spectators
		or people not on a server.
	*/
	if (state != 4)
		return true; // This results in all vectors beeing zero which tells mumble to ignore them.

	ok = peekProc((BYTE *) 0x00862E44, avatar_pos+2, 4) &&	//Z
	     peekProc((BYTE *) 0x00862E48, avatar_pos, 4) &&	//X
	     peekProc((BYTE *) 0x00862E4C, avatar_pos+1, 4) && //Y
	     peekProc((BYTE *) 0x00862E54, &viewHor, 4) && //Hor
	     peekProc((BYTE *) 0x00862E50, &viewVer, 4); //Ver

	if (! ok)
		return false;

	// Scale Coordinates
	/*
	   Z-Value is increasing when heading north
				  decreasing when heading south
	   X-Value is increasing when heading west
				  decreasing when heading east
	   Y-Value is increasing when going up
				  decreasing when going down
	   40 units = 1 meter (not confirmed)
	*/
	for (int i=0;i<3;i++)
		avatar_pos[i]/=40.0f; // Scale to meters
	avatar_pos[0]*=(-1.0f); // Convert right to left handed

	avatar_top[2] = -1; // Head movement is in front vector

	// Calculate view unit vector
	/*
	   Vertical view 0 when centered
					85	when looking down
				   275 when looking up
	   Decreasing when looking up.

	   Horizontal is 0 when facing North
					90 when facing West
				   180 when facing South
				   270 when facing East
	   Increasing when turning left.
	*/
	viewVer *= static_cast<float>(M_PI / 180.0f);
	viewHor *= static_cast<float>(M_PI / 180.0f);

	avatar_front[0] = -sin(viewHor) * cos(viewVer);
	avatar_front[1] = -sin(viewVer);
	avatar_front[2] = cos(viewHor) * cos(viewVer);

	for (int i=0;i<3;i++) {
		camera_pos[i] = avatar_pos[i];
		camera_front[i] = avatar_front[i];
		camera_top[i] = avatar_top[i];
	}

	return ok;
}

static int trylock() {
	h = NULL;
	DWORD pid=getProcess(L"iw4mp.exe");
	if (!pid)
		return false;

	h=OpenProcess(PROCESS_VM_READ, false, pid);
	if (!h)
		return false;

	float apos[3], afront[3], atop[3], cpos[3], cfront[3], ctop[3];
	std::string context;
	std::wstring identity;

	if (fetch(apos, afront, atop, cpos, cfront, ctop, context, identity))
		return true;

	CloseHandle(h);
	h = NULL;
	return false;
}

static void unlock() {
	if (h) {
		CloseHandle(h);
		h = NULL;
	}
}

static const std::wstring longdesc() {
	return std::wstring(L"Supports Call of Duty: Modern Warfare 2 MP v1.0.174 only. No identity support yet.");
}

static std::wstring description(L"Call of Duty: Modern Warfare 2 MP v1.0.174");
static std::wstring shortname(L"Call of Duty: Modern Warfare 2 MP");

static MumblePlugin codmw2plug = {
	MUMBLE_PLUGIN_MAGIC,
	description,
	shortname,
	about,
	NULL,
	trylock,
	unlock,
	longdesc,
	fetch
};

extern "C" __declspec(dllexport) MumblePlugin *getMumblePlugin() {
	return &codmw2plug;
}
<|endoftext|>


<commit_before>#include "drivers/ublox_neo7.hpp"

#include <cstdlib>
#include <cstring>

#include "chprintf.h"
#include "unit_config.hpp"

const char NMEA_LF = '\n';
const char *NMEA_DELIMS = ",\0";

struct GPGLLMessage {
  float lon;
  char lonDir;
  float lat;
  char latDir;
  float utc;
  char valid;
};

void UBloxNEO7::init() {
}

GPSReading UBloxNEO7::readGPS() {
  // Read all available bytes until the newline character. NMEA dictates that
  // messages should end with a CRLF, but we'll only look for the LF.
  std::size_t len = readUntil(NMEA_LF);

  //static int loop = 0;
  //if (loop % 100 == 0) {
  //  chprintf((BaseSequentialStream*)sd, "$PUBX,00*33\r\n");
  //}
  //loop = (loop+1) % 100;

  // Check if a full line is ready to be processed
  if(len > 0) {
    char *start = reinterpret_cast<char *>(rxbuf.data());
    //chprintf((BaseSequentialStream*)&SD4, "%s", rxbuf.data());

    // Skip over the leading "$"
    start += 1;

    char *token = std::strtok(start, NMEA_DELIMS);

    // Only care about GPGLL messages
    if(std::strcmp("GPGLL", token) == 0) {
      GPGLLMessage message;
      int position = 0;

      while((token = std::strtok(nullptr, NMEA_DELIMS)) != nullptr) {
        switch(position++) {
          case 0:
            message.lat = atof(token);
            break;
          case 1:
            message.latDir = token[0];
            break;
          case 2:
            message.lon = atof(token);
            break;
          case 3:
            message.lonDir = token[0];
            break;
          case 4:
            message.utc = atof(token);
            break;
          case 5:
            message.valid = token[0];
            break;
        };
      }

      return GPSReading {
        // Make sure we got all parts of the message. If fields are omitted in
        // the message then `strtok` will skip over repeated delimiters and the
        // above loop will complete before all delimiters were found.
        .valid = message.valid && position == 7,
        .lat = dmd2float(message.lat, message.latDir),
        .lon = dmd2float(message.lon, message.lonDir),
        .utc = message.utc
      };
    }
  }

  // TODO: Return previous message with old timestamp.
  return GPSReading {
    .valid = false,
      .lat = 10000.0,
      .lon = 10000.0,
      .utc = 0.0
  };
}

bool UBloxNEO7::healthy() {
  return true;
}
<commit_msg>Output old GPS coordinates.<commit_after>#include "drivers/ublox_neo7.hpp"

#include <cstdlib>
#include <cstring>

#include "chprintf.h"
#include "unit_config.hpp"

const char NMEA_LF = '\n';
const char *NMEA_DELIMS = ",\0";

struct GPGLLMessage {
  float lon;
  char lonDir;
  float lat;
  char latDir;
  float utc;
  char valid;
};

void UBloxNEO7::init() {
}

GPSReading UBloxNEO7::readGPS() {
  // Read all available bytes until the newline character. NMEA dictates that
  // messages should end with a CRLF, but we'll only look for the LF.
  std::size_t len = readUntil(NMEA_LF);

  //static int loop = 0;
  //if (loop % 100 == 0) {
  //  chprintf((BaseSequentialStream*)sd, "$PUBX,00*33\r\n");
  //}
  //loop = (loop+1) % 100;

  // Check if a full line is ready to be processed
  GPGLLMessage message;
  static int position = 0;
  if(len > 0) {
    char *start = reinterpret_cast<char *>(rxbuf.data());
    //chprintf((BaseSequentialStream*)&SD4, "%s", rxbuf.data());

    // Skip over the leading "$"
    start += 1;

    char *token = std::strtok(start, NMEA_DELIMS);

    // Only care about GPGLL messages
    if(std::strcmp("GPGLL", token) == 0) {
      position = 0;

      while((token = std::strtok(nullptr, NMEA_DELIMS)) != nullptr) {
        switch(position++) {
          case 0:
            message.lat = atof(token);
            break;
          case 1:
            message.latDir = token[0];
            break;
          case 2:
            message.lon = atof(token);
            break;
          case 3:
            message.lonDir = token[0];
            break;
          case 4:
            message.utc = atof(token);
            break;
          case 5:
            message.valid = token[0];
            break;
        };
      }
    }
  }

  return GPSReading {
    // Make sure we got all parts of the message. If fields are omitted in
    // the message then `strtok` will skip over repeated delimiters and the
    // above loop will complete before all delimiters were found.
    .valid = message.valid && position == 7,
    .lat = dmd2float(message.lat, message.latDir),
    .lon = dmd2float(message.lon, message.lonDir),
    .utc = message.utc
  };
}

bool UBloxNEO7::healthy() {
  return true;
}
<|endoftext|>