<commit_before>#include <boost/python.hpp>
namespace bp = boost::python;

#include "rcs.hh"		// NML classes, nmlErrorFormat()
#include "emc.hh"		// EMC NML
#include "emc_nml.hh"

extern EMC_STAT *emcStatus;

BOOST_PYTHON_MODULE(emctask) {
    using namespace boost::python;
    using namespace boost;

    scope().attr("__doc__") =
        "Task introspection\n"
        ;

    class_<PmCartesian, noncopyable>("PmCartesian","EMC cartesian postition",no_init)
	.def_readwrite("x",&PmCartesian::x)
	.def_readwrite("y",&PmCartesian::y)
	.def_readwrite("z",&PmCartesian::z)
	;

    class_<EmcPose, noncopyable>("EmcPose","EMC pose",no_init)
	.def_readwrite("tran",&EmcPose::tran)
	// .def_readwrite("x",&EmcPose::tran.x)
	// .def_readwrite("y",&EmcPose::tran.y)
	// .def_readwrite("x",&EmcPose::tran.z)
	.def_readwrite("a",&EmcPose::a)
	.def_readwrite("b",&EmcPose::b)
	.def_readwrite("c",&EmcPose::c)
	.def_readwrite("u",&EmcPose::u)
	.def_readwrite("v",&EmcPose::v)
	.def_readwrite("w",&EmcPose::w)
	;

    class_ <EMC_TRAJ_STAT, noncopyable>("EMC_TRAJ_STAT",no_init)
	.def_readwrite("linearUnits", &emcStatus->motion.traj.linearUnits )
	.def_readwrite("angularUnits", &emcStatus->motion.traj.angularUnits )
	.def_readwrite("cycleTime", &emcStatus->motion.traj.cycleTime )
	.def_readwrite("axes", &emcStatus->motion.traj.axes )
	.def_readwrite("axis_mask", &emcStatus->motion.traj.axis_mask )
	.def_readwrite("mode", &emcStatus->motion.traj.mode )
	.def_readwrite("enabled", &emcStatus->motion.traj.enabled )
	.def_readwrite("inpos", &emcStatus->motion.traj.inpos )
	.def_readwrite("queue", &emcStatus->motion.traj.queue )
	.def_readwrite("activeQueue", &emcStatus->motion.traj.activeQueue )
	.def_readwrite("queueFull", &emcStatus->motion.traj.queueFull )
	.def_readwrite("id", &emcStatus->motion.traj.id )
	.def_readwrite("paused", &emcStatus->motion.traj.paused )
	.def_readwrite("scale", &emcStatus->motion.traj.scale )
	.def_readwrite("spindle_scale", &emcStatus->motion.traj.spindle_scale )
	.def_readwrite("position", &emcStatus->motion.traj.position )
	.def_readwrite("actualPosition", &emcStatus->motion.traj.actualPosition )
	.def_readwrite("velocity", &emcStatus->motion.traj.velocity )
	.def_readwrite("acceleration", &emcStatus->motion.traj.acceleration)
	.def_readwrite("maxVelocity", &emcStatus->motion.traj.maxVelocity )
	.def_readwrite("maxAcceleration", &emcStatus->motion.traj.maxAcceleration )
	.def_readwrite("probedPosition", &emcStatus->motion.traj.probedPosition )
	.def_readwrite("probe_tripped", &emcStatus->motion.traj.probe_tripped )
	.def_readwrite("probing", &emcStatus->motion.traj.probing )
	.def_readwrite("probeval", &emcStatus->motion.traj.probeval )
	.def_readwrite("kinematics_type", &emcStatus->motion.traj.kinematics_type )
	.def_readwrite("motion_type", &emcStatus->motion.traj.motion_type )
	.def_readwrite("distance_to_go", &emcStatus->motion.traj.distance_to_go )
	.def_readwrite("dtg", &emcStatus->motion.traj.dtg )
	.def_readwrite("current_vel", &emcStatus->motion.traj.current_vel )
	.def_readwrite("feed_override_enabled", &emcStatus->motion.traj.feed_override_enabled )
	.def_readwrite("spindle_override_enabled", &emcStatus->motion.traj.spindle_override_enabled )
	.def_readwrite("adaptive_feed_enabled", &emcStatus->motion.traj.adaptive_feed_enabled )
	.def_readwrite("feed_hold_enabled", &emcStatus->motion.traj.feed_hold_enabled )
	;

    // class_ <EMC_AXIS_STAT, noncopyable>("EMC_AXIS_STAT",no_init)
    // .def_readwrite("", &EmcStatus-> )

    // 	;
    class_ <EMC_SPINDLE_STAT, noncopyable>("EMC_SPINDLE_STAT",no_init)
	.def_readwrite("speed", &emcStatus->motion.spindle.speed )
	.def_readwrite("direction", &emcStatus->motion.spindle.direction )
	.def_readwrite("brake", &emcStatus->motion.spindle.brake )
	.def_readwrite("increasing", &emcStatus->motion.spindle.increasing )
	.def_readwrite("enabled", &emcStatus->motion.spindle.enabled )
	;

    class_ <EMC_COOLANT_STAT , noncopyable>("EMC_COOLANT_STAT ",no_init)
	.def_readwrite("mist", &emcStatus->motion.coolant.mist )
	.def_readwrite("flood", &emcStatus->motion.coolant.flood )
	;

    class_ <EMC_LUBE_STAT, noncopyable>("EMC_LUBE_STAT",no_init)
	.def_readwrite("on", &emcStatus->motion.lube.on )
	.def_readwrite("level", &emcStatus->motion.lube.level )
	;

    class_ <EMC_MOTION_STAT, noncopyable>("EMC_MOTION_STAT",no_init)
	.def_readwrite("traj", &emcStatus->motion.traj)
	// .def_readwrite("axis", &emcStatus->motion.axis)   // FIXME wrap this
	// .def_readwrite("spindle", &emcStatus->motion.spindle)
	// .def_readwrite("synch_di", &emcStatus->motion.synch_di)
	// .def_readwrite("analog_input", &emcStatus->motion.analog_input)
	// .def_readwrite("analog_output", &emcStatus->motion.analog_output)
	.def_readwrite("estop", &emcStatus->motion.estop)
	.def_readwrite("coolant", &emcStatus->motion.coolant)
	.def_readwrite("lube", &emcStatus->motion.lube)
	.def_readwrite("debug", &emcStatus->motion.debug)
	;

    class_ <EMC_TASK_STAT, noncopyable>("EMC_TASK_STAT",no_init)
	.def_readwrite("mode", (int *) &emcStatus->task.mode)
	.def_readwrite("state", (int *) &emcStatus->task.state)
	.def_readwrite("execState", (int *) &emcStatus->task.execState)
	.def_readwrite("interpState", (int *) &emcStatus->task.interpState)
	.def_readwrite("motionLine", &emcStatus->task.motionLine)
	.def_readwrite("currentLine", &emcStatus->task.currentLine)
	.def_readwrite("readLine", &emcStatus->task.readLine)
	.def_readwrite("optional_stop_state", &emcStatus->task.optional_stop_state)
	.def_readwrite("block_delete_state", &emcStatus->task.block_delete_state)
	.def_readwrite("input_timeout", &emcStatus->task.input_timeout)
	.def_readwrite("file", (char *) &emcStatus->task.file)
	.def_readwrite("command", (char *) &emcStatus->task.command)
	.def_readwrite("g5x_offset", &emcStatus->task.g5x_offset)
	.def_readwrite("g5x_index", &emcStatus->task.g5x_index)
	.def_readwrite("g92_offset", &emcStatus->task.g92_offset)
	.def_readwrite("rotation_xy", &emcStatus->task.rotation_xy)
	.def_readwrite("toolOffset", &emcStatus->task.toolOffset)

	// int activeGCodes[ACTIVE_G_CODES];  // FIXME wrap this
	// int activeMCodes[ACTIVE_M_CODES];
	// double activeSettings[ACTIVE_SETTINGS];

	.def_readwrite("programUnits", &emcStatus->task.programUnits)
	.def_readwrite("interpreter_errcode", &emcStatus->task.interpreter_errcode)
	.def_readwrite("task_paused", &emcStatus->task.task_paused)
	.def_readwrite("delayLeft", &emcStatus->task.delayLeft)
	;

    class_ <EMC_TOOL_STAT, noncopyable>("EMC_TOOL_STAT",no_init)
	.def_readwrite("pocketPrepped", &emcStatus->io.tool.pocketPrepped )
	.def_readwrite("toolInSpindle", &emcStatus->io.tool.toolInSpindle )
	//	.def_readwrite("toolTable", &emcStatus->io.tool.toolTable )  // FIXME wrap this
	;

    class_ <EMC_AUX_STAT, noncopyable>("EMC_AUX_STAT",no_init)
	// .def_readwrite("", &emcStatus->io.aux. ) // empty NML msg?
	;

   class_ <EMC_IO_STAT, noncopyable>("EMC_IO_STAT",no_init)
	.def_readwrite("cycleTime", &emcStatus->io.cycleTime )
	.def_readwrite("debug", &emcStatus->io.debug )
	.def_readwrite("reason", &emcStatus->io.reason )
	.def_readwrite("fault", &emcStatus->io.fault )
	.def_readwrite("tool", &emcStatus->io.tool)
	.def_readwrite("aux", &emcStatus->io.aux )
	;

    class_ <EMC_STAT, noncopyable>("EMC_STAT",no_init)
	.def_readwrite("task",&emcStatus->task)
	.def_readwrite("motion",&emcStatus->motion)
	.def_readwrite("io",&emcStatus->io)
	.def_readwrite("debug",&emcStatus->debug)
	;

}
<commit_msg>WIP on completing taskmodule<commit_after>    // EMC_AXIS_STAT axis[EMC_AXIS_MAX];
    // int synch_di[EMC_MAX_DIO];  // motion inputs queried by interp
    // int synch_do[EMC_MAX_DIO];  // motion outputs queried by interp
    // double analog_input[EMC_MAX_AIO]; //motion analog inputs queried by interp
    // double analog_output[EMC_MAX_AIO]; //motion analog outputs queried by interp
//task_stat:

// reuse interp converters

#include <boost/python.hpp>
#include "rs274ngc.hh"
#include "interp_internal.hh"

namespace bp = boost::python;

#include "array1.hh"

namespace pp = pyplusplus::containers::static_sized;

#include "interp_array_types.hh"  // import activeMCodes,activeGCodes,activeSettings, toolTable

#include "rcs.hh"		// NML classes, nmlErrorFormat()
#include "emc.hh"		// EMC NML
#include "emc_nml.hh"

extern EMC_STAT *emcStatus;

typedef pp::array_1_t< EMC_AXIS_STAT, EMC_AXIS_MAX> axis_array, (*axis_w)( EMC_MOTION_STAT &m );
typedef pp::array_1_t< int, EMC_MAX_DIO> synch_dio_array, (*synch_dio_w)( EMC_MOTION_STAT &m );
typedef pp::array_1_t< double, EMC_MAX_AIO> analog_io_array, (*analog_io_w)( EMC_MOTION_STAT &m );

typedef pp::array_1_t< int, ACTIVE_G_CODES> active_g_codes_array, (*active_g_codes_tw)( EMC_TASK_STAT &t );
typedef pp::array_1_t< int, ACTIVE_M_CODES> active_m_codes_array, (*active_m_codes_tw)( EMC_TASK_STAT &t );
typedef pp::array_1_t< double, ACTIVE_SETTINGS> active_settings_array, (*active_settings_tw)( EMC_TASK_STAT &t );

static  axis_array axis_wrapper ( EMC_MOTION_STAT & m) {
    return axis_array(m.axis);
}

static  synch_dio_array synch_di_wrapper ( EMC_MOTION_STAT & m) {
    return synch_dio_array(m.synch_di);
}

static  synch_dio_array synch_do_wrapper ( EMC_MOTION_STAT & m) {
    return synch_dio_array(m.synch_do);
}

static  analog_io_array analog_input_wrapper ( EMC_MOTION_STAT & m) {
    return analog_io_array(m.analog_input);
}

static  analog_io_array analog_output_wrapper ( EMC_MOTION_STAT & m) {
    return analog_io_array(m.analog_output);
}

static  active_g_codes_array activeGCodes_wrapper (  EMC_TASK_STAT & m) {
    return active_g_codes_array(m.activeGCodes);
}

static  active_m_codes_array activeMCodes_wrapper ( EMC_TASK_STAT & m) {
    return active_m_codes_array(m.activeMCodes);
}

static  active_settings_array activeSettings_wrapper ( EMC_TASK_STAT & m) {
    return active_settings_array(m.activeSettings);
}

BOOST_PYTHON_MODULE(emctask) {
    using namespace boost::python;
    using namespace boost;

    scope().attr("__doc__") =
        "Task introspection\n"
        ;

    class_<PmCartesian, noncopyable>("PmCartesian","EMC cartesian postition",no_init)
	.def_readwrite("x",&PmCartesian::x)
	.def_readwrite("y",&PmCartesian::y)
	.def_readwrite("z",&PmCartesian::z)
	;

    class_<EmcPose, noncopyable>("EmcPose","EMC pose",no_init)
	.def_readwrite("tran",&EmcPose::tran)
	// .def_readwrite("x",&EmcPose::tran.x)
	// .def_readwrite("y",&EmcPose::tran.y)
	// .def_readwrite("x",&EmcPose::tran.z)
	.def_readwrite("a",&EmcPose::a)
	.def_readwrite("b",&EmcPose::b)
	.def_readwrite("c",&EmcPose::c)
	.def_readwrite("u",&EmcPose::u)
	.def_readwrite("v",&EmcPose::v)
	.def_readwrite("w",&EmcPose::w)
	;

    class_ <EMC_TRAJ_STAT, noncopyable>("EMC_TRAJ_STAT",no_init)
	.def_readwrite("linearUnits", &emcStatus->motion.traj.linearUnits )
	.def_readwrite("angularUnits", &emcStatus->motion.traj.angularUnits )
	.def_readwrite("cycleTime", &emcStatus->motion.traj.cycleTime )
	.def_readwrite("axes", &emcStatus->motion.traj.axes )
	.def_readwrite("axis_mask", &emcStatus->motion.traj.axis_mask )
	.def_readwrite("mode", &emcStatus->motion.traj.mode )
	.def_readwrite("enabled", &emcStatus->motion.traj.enabled )
	.def_readwrite("inpos", &emcStatus->motion.traj.inpos )
	.def_readwrite("queue", &emcStatus->motion.traj.queue )
	.def_readwrite("activeQueue", &emcStatus->motion.traj.activeQueue )
	.def_readwrite("queueFull", &emcStatus->motion.traj.queueFull )
	.def_readwrite("id", &emcStatus->motion.traj.id )
	.def_readwrite("paused", &emcStatus->motion.traj.paused )
	.def_readwrite("scale", &emcStatus->motion.traj.scale )
	.def_readwrite("spindle_scale", &emcStatus->motion.traj.spindle_scale )
	.def_readwrite("position", &emcStatus->motion.traj.position )
	.def_readwrite("actualPosition", &emcStatus->motion.traj.actualPosition )
	.def_readwrite("velocity", &emcStatus->motion.traj.velocity )
	.def_readwrite("acceleration", &emcStatus->motion.traj.acceleration)
	.def_readwrite("maxVelocity", &emcStatus->motion.traj.maxVelocity )
	.def_readwrite("maxAcceleration", &emcStatus->motion.traj.maxAcceleration )
	.def_readwrite("probedPosition", &emcStatus->motion.traj.probedPosition )
	.def_readwrite("probe_tripped", &emcStatus->motion.traj.probe_tripped )
	.def_readwrite("probing", &emcStatus->motion.traj.probing )
	.def_readwrite("probeval", &emcStatus->motion.traj.probeval )
	.def_readwrite("kinematics_type", &emcStatus->motion.traj.kinematics_type )
	.def_readwrite("motion_type", &emcStatus->motion.traj.motion_type )
	.def_readwrite("distance_to_go", &emcStatus->motion.traj.distance_to_go )
	.def_readwrite("dtg", &emcStatus->motion.traj.dtg )
	.def_readwrite("current_vel", &emcStatus->motion.traj.current_vel )
	.def_readwrite("feed_override_enabled", &emcStatus->motion.traj.feed_override_enabled )
	.def_readwrite("spindle_override_enabled", &emcStatus->motion.traj.spindle_override_enabled )
	.def_readwrite("adaptive_feed_enabled", &emcStatus->motion.traj.adaptive_feed_enabled )
	.def_readwrite("feed_hold_enabled", &emcStatus->motion.traj.feed_hold_enabled )
	;

    class_ <EMC_AXIS_STAT, noncopyable>("EMC_AXIS_STAT",no_init)
    // // .def_readwrite("", &EmcStatus-> )

    // 	.def("axisType", &EmcStatus-> ;	// EMC_AXIS_LINEAR, EMC_AXIS_ANGULAR
    // double units;		// units per mm, deg for linear, angular
    // double backlash;
    // double minPositionLimit;
    // double maxPositionLimit;
    // double maxFerror;
    // double minFerror;

    // // dynamic status
    // double ferrorCurrent;	// current following error
    // double ferrorHighMark;	// magnitude of max following error
    // /*! \todo FIXME - is this really position, or the DAC output? */
    // double output;		// commanded output position
    // double input;		// current input position
    // double velocity;		// current velocity
    // unsigned char inpos;	// non-zero means in position
    // unsigned char homing;	// non-zero means homing
    // unsigned char homed;	// non-zero means has been homed
    // unsigned char fault;	// non-zero means axis amp fault
    // unsigned char enabled;	// non-zero means enabled
    // unsigned char minSoftLimit;	// non-zero means min soft limit exceeded
    // unsigned char maxSoftLimit;	// non-zero means max soft limit exceeded
    // unsigned char minHardLimit;	// non-zero means min hard limit exceeded
    // unsigned char maxHardLimit;	// non-zero means max hard limit exceeded
    // unsigned char overrideLimits; // non-zero means limits are overridden

    //
	;
    class_ <EMC_SPINDLE_STAT, noncopyable>("EMC_SPINDLE_STAT",no_init)
	.def_readwrite("speed", &emcStatus->motion.spindle.speed )
	.def_readwrite("direction", &emcStatus->motion.spindle.direction )
	.def_readwrite("brake", &emcStatus->motion.spindle.brake )
	.def_readwrite("increasing", &emcStatus->motion.spindle.increasing )
	.def_readwrite("enabled", &emcStatus->motion.spindle.enabled )
	;

    class_ <EMC_COOLANT_STAT , noncopyable>("EMC_COOLANT_STAT ",no_init)
	.def_readwrite("mist", &emcStatus->motion.coolant.mist )
	.def_readwrite("flood", &emcStatus->motion.coolant.flood )
	;

    class_ <EMC_LUBE_STAT, noncopyable>("EMC_LUBE_STAT",no_init)
	.def_readwrite("on", &emcStatus->motion.lube.on )
	.def_readwrite("level", &emcStatus->motion.lube.level )
	;

    class_ <EMC_MOTION_STAT, noncopyable>("EMC_MOTION_STAT",no_init)
	.def_readwrite("traj", &emcStatus->motion.traj)
	.add_property( "axis",
		       bp::make_function( axis_w(&axis_wrapper),
					  bp::with_custodian_and_ward_postcall< 0, 1 >()))

	// .def_readwrite("spindle", &emcStatus->motion.spindle)
	.add_property( "synch_di",
		       bp::make_function( synch_dio_w(&synch_di_wrapper),
					  bp::with_custodian_and_ward_postcall< 0, 1 >()))
	.add_property( "synch_do",
		       bp::make_function( synch_dio_w(&synch_do_wrapper),
					  bp::with_custodian_and_ward_postcall< 0, 1 >()))
	.add_property( "analog_input",
		       bp::make_function( analog_io_w(&analog_input_wrapper),
					  bp::with_custodian_and_ward_postcall< 0, 1 >()))
	.add_property( "analog_output",
		       bp::make_function( analog_io_w(&analog_output_wrapper),
					  bp::with_custodian_and_ward_postcall< 0, 1 >()))
	.def_readwrite("estop", &emcStatus->motion.estop)
	.def_readwrite("coolant", &emcStatus->motion.coolant)
	.def_readwrite("lube", &emcStatus->motion.lube)
	.def_readwrite("debug", &emcStatus->motion.debug)
	;

    class_ <EMC_TASK_STAT, noncopyable>("EMC_TASK_STAT",no_init)
	.def_readwrite("mode", (int *) &emcStatus->task.mode)
	.def_readwrite("state", (int *) &emcStatus->task.state)
	.def_readwrite("execState", (int *) &emcStatus->task.execState)
	.def_readwrite("interpState", (int *) &emcStatus->task.interpState)
	.def_readwrite("motionLine", &emcStatus->task.motionLine)
	.def_readwrite("currentLine", &emcStatus->task.currentLine)
	.def_readwrite("readLine", &emcStatus->task.readLine)
	.def_readwrite("optional_stop_state", &emcStatus->task.optional_stop_state)
	.def_readwrite("block_delete_state", &emcStatus->task.block_delete_state)
	.def_readwrite("input_timeout", &emcStatus->task.input_timeout)
	.def_readwrite("file", (char *) &emcStatus->task.file)
	.def_readwrite("command", (char *) &emcStatus->task.command)
	.def_readwrite("g5x_offset", &emcStatus->task.g5x_offset)
	.def_readwrite("g5x_index", &emcStatus->task.g5x_index)
	.def_readwrite("g92_offset", &emcStatus->task.g92_offset)
	.def_readwrite("rotation_xy", &emcStatus->task.rotation_xy)
	.def_readwrite("toolOffset", &emcStatus->task.toolOffset)
	.add_property( "activeGCodes",
		       bp::make_function( active_g_codes_tw(&activeGCodes_wrapper),
					  bp::with_custodian_and_ward_postcall< 0, 1 >()))
	.add_property( "activeMCodes",
		       bp::make_function( active_m_codes_tw(&activeMCodes_wrapper),
					  bp::with_custodian_and_ward_postcall< 0, 1 >()))
	.add_property( "activeSettings",
		       bp::make_function( active_settings_tw(&activeSettings_wrapper),
					  bp::with_custodian_and_ward_postcall< 0, 1 >()))
	.def_readwrite("programUnits", &emcStatus->task.programUnits)
	.def_readwrite("interpreter_errcode", &emcStatus->task.interpreter_errcode)
	.def_readwrite("task_paused", &emcStatus->task.task_paused)
	.def_readwrite("delayLeft", &emcStatus->task.delayLeft)
	;

    class_ <EMC_TOOL_STAT, noncopyable>("EMC_TOOL_STAT",no_init)
	.def_readwrite("pocketPrepped", &emcStatus->io.tool.pocketPrepped )
	.def_readwrite("toolInSpindle", &emcStatus->io.tool.toolInSpindle )
	//	.def_readwrite("toolTable", &emcStatus->io.tool.toolTable )  // FIXME wrap this
	;

    class_ <EMC_AUX_STAT, noncopyable>("EMC_AUX_STAT",no_init)
	// .def_readwrite("", &emcStatus->io.aux. ) // empty NML msg?
	;

   class_ <EMC_IO_STAT, noncopyable>("EMC_IO_STAT",no_init)
	.def_readwrite("cycleTime", &emcStatus->io.cycleTime )
	.def_readwrite("debug", &emcStatus->io.debug )
	.def_readwrite("reason", &emcStatus->io.reason )
	.def_readwrite("fault", &emcStatus->io.fault )
	.def_readwrite("tool", &emcStatus->io.tool)
	.def_readwrite("aux", &emcStatus->io.aux )
	;

    class_ <EMC_STAT, noncopyable>("EMC_STAT",no_init)
	.def_readwrite("task",&emcStatus->task)
	.def_readwrite("motion",&emcStatus->motion)
	.def_readwrite("io",&emcStatus->io)
	.def_readwrite("debug",&emcStatus->debug)
	;

    pp::register_array_1< double, EMC_MAX_AIO> ("AnalogIoArray");
    pp::register_array_1< int, EMC_MAX_DIO> ("DigitalIoArray");
    pp::register_array_1< EMC_AXIS_STAT,EMC_AXIS_MAX,
	bp::return_internal_reference< 1, bp::default_call_policies > > ("AxisArray");
}
<|endoftext|>


<commit_before>/* Copyright 2018 The TensorFlow Authors. All Rights Reserved.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==============================================================================*/

#include "tensorflow/core/platform/file_system_helper.h"

#include <deque>
#include <string>
#include <vector>

#include "tensorflow/core/platform/env.h"
#include "tensorflow/core/platform/file_system.h"
#include "tensorflow/core/platform/path.h"
#include "tensorflow/core/platform/platform.h"
#include "tensorflow/core/platform/status.h"
#include "tensorflow/core/platform/str_util.h"
#include "tensorflow/core/platform/threadpool.h"

namespace tensorflow {
namespace internal {

namespace {

constexpr int kNumThreads = 8;

// Run a function in parallel using a ThreadPool, but skip the ThreadPool
// on the iOS platform due to its problems with more than a few threads.
void ForEach(int first, int last, const std::function<void(int)>& f) {
#if TARGET_OS_IPHONE
  for (int i = first; i < last; i++) {
    f(i);
  }
#else
  int num_threads = std::min(kNumThreads, last - first);
  thread::ThreadPool threads(Env::Default(), "ForEach", num_threads);
  for (int i = first; i < last; i++) {
    threads.Schedule([f, i] { f(i); });
  }
#endif
}

}  // namespace

Status GetMatchingPaths(FileSystem* fs, Env* env, const string& pattern,
                        std::vector<string>* results) {
  results->clear();
  // Find the fixed prefix by looking for the first wildcard.
  string fixed_prefix = pattern.substr(0, pattern.find_first_of("*?[\\"));
  string eval_pattern = pattern;
  std::vector<string> all_files;
  string dir(io::Dirname(fixed_prefix));
  // If dir is empty then we need to fix up fixed_prefix and eval_pattern to
  // include . as the top level directory.
  if (dir.empty()) {
    dir = ".";
    fixed_prefix = io::JoinPath(dir, fixed_prefix);
    eval_pattern = io::JoinPath(dir, pattern);
  }

  // Setup a BFS to explore everything under dir.
  std::deque<string> dir_q;
  dir_q.push_back(dir);
  Status ret;  // Status to return.
  // children_dir_status holds is_dir status for children. It can have three
  // possible values: OK for true; FAILED_PRECONDITION for false; CANCELLED
  // if we don't calculate IsDirectory (we might do that because there isn't
  // any point in exploring that child path).
  std::vector<Status> children_dir_status;
  while (!dir_q.empty()) {
    string current_dir = dir_q.front();
    dir_q.pop_front();
    std::vector<string> children;
    Status s = fs->GetChildren(current_dir, &children);
    // In case PERMISSION_DENIED is encountered, we bail here.
    if (s.code() == tensorflow::error::PERMISSION_DENIED) {
      continue;
    }
    ret.Update(s);
    if (children.empty()) continue;
    // This IsDirectory call can be expensive for some FS. Parallelizing it.
    children_dir_status.resize(children.size());
    ForEach(0, children.size(),
            [fs, &current_dir, &children, &fixed_prefix,
             &children_dir_status](int i) {
              const string child_path = io::JoinPath(current_dir, children[i]);
              // In case the child_path doesn't start with the fixed_prefix then
              // we don't need to explore this path.
              if (!absl::StartsWith(child_path, fixed_prefix)) {
                children_dir_status[i] = Status(tensorflow::error::CANCELLED,
                                                "Operation not needed");
              } else {
                children_dir_status[i] = fs->IsDirectory(child_path);
              }
            });
    for (size_t i = 0; i < children.size(); ++i) {
      const string child_path = io::JoinPath(current_dir, children[i]);
      // If the IsDirectory call was cancelled we bail.
      if (children_dir_status[i].code() == tensorflow::error::CANCELLED) {
        continue;
      }
      // If the child is a directory add it to the queue.
      if (children_dir_status[i].ok()) {
        dir_q.push_back(child_path);
      }
      all_files.push_back(child_path);
    }
  }

  // Match all obtained files to the input pattern.
  for (const auto& f : all_files) {
    if (fs->Match(f, eval_pattern)) {
      results->push_back(f);
    }
  }
  return ret;
}

}  // namespace internal
}  // namespace tensorflow
<commit_msg>change GetMatchingPaths to speed it up<commit_after>/* Copyright 2018 The TensorFlow Authors. All Rights Reserved.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==============================================================================*/

#include "tensorflow/core/platform/file_system_helper.h"

#include <deque>
#include <string>
#include <vector>

#include "tensorflow/core/platform/env.h"
#include "tensorflow/core/platform/file_system.h"
#include "tensorflow/core/platform/path.h"
#include "tensorflow/core/platform/platform.h"
#include "tensorflow/core/platform/status.h"
#include "tensorflow/core/platform/str_util.h"
#include "tensorflow/core/platform/threadpool.h"

namespace tensorflow {
namespace internal {

namespace {

constexpr int kNumThreads = 8;

// Run a function in parallel using a ThreadPool, but skip the ThreadPool
// on the iOS platform due to its problems with more than a few threads.
void ForEach(int first, int last, const std::function<void(int)>& f) {
#if TARGET_OS_IPHONE
  for (int i = first; i < last; i++) {
    f(i);
  }
#else
  int num_threads = std::min(kNumThreads, last - first);
  thread::ThreadPool threads(Env::Default(), "ForEach", num_threads);
  for (int i = first; i < last; i++) {
    threads.Schedule([f, i] { f(i); });
  }
#endif
}

}  // namespace

Status GetMatchingPaths(FileSystem* fs, Env* env, const string& pattern,
                        std::vector<string>* results) {
  results->clear();
  if (pattern.empty()) {
    return Status::OK();
  }

  string eval_pattern = pattern;
  bool is_directory = pattern[pattern.size() - 1] == '/';
#ifdef PLATFORM_WINDOWS
  is_directory = is_directory || pattern[pattern.size() - 1] == '\\';
#endif
  if (!io::IsAbsolutePath(pattern)) {
    eval_pattern = io::JoinPath(".", pattern);
  }
  std::vector<string> dirs;
  if (!is_directory) {
    dirs.push_back(eval_pattern);
  }
  StringPiece dir(io::Dirname(eval_pattern));
  while (!dir.empty() && dir != "/") {
    dirs.push_back(string(dir));
    dir = io::Dirname(dir);
  }
  if (dir == "/") {
    dirs.push_back(string(dir));
  }
  std::reverse(dirs.begin(), dirs.end());
  // Setup a BFS to explore everything under dir.
  std::deque<std::pair<string, int>> dir_q;
  dir_q.push_back({dirs[0], 0});
  Status ret;  // Status to return.
  // children_dir_status holds is_dir status for children. It can have three
  // possible values: OK for true; FAILED_PRECONDITION for false; CANCELLED
  // if we don't calculate IsDirectory (we might do that because there isn't
  // any point in exploring that child path).
  std::vector<Status> children_dir_status;
  while (!dir_q.empty()) {
    string current_dir = dir_q.front().first;
    int dir_index = dir_q.front().second;
    dir_index++;
    dir_q.pop_front();
    std::vector<string> children;
    Status s = fs->GetChildren(current_dir, &children);
    // In case PERMISSION_DENIED is encountered, we bail here.
    if (s.code() == tensorflow::error::PERMISSION_DENIED) {
      continue;
    }
    ret.Update(s);
    if (children.empty()) continue;
    // This IsDirectory call can be expensive for some FS. Parallelizing it.
    children_dir_status.resize(children.size());
    ForEach(0, children.size(),
            [fs, &current_dir, &children, &dirs, dir_index,
             is_directory, &children_dir_status](int i) {
              const string child_path = io::JoinPath(current_dir, children[i]);
              if (!fs->Match(child_path, dirs[dir_index])) {
                children_dir_status[i] = Status(tensorflow::error::CANCELLED,
                                                "Operation not needed");
              } else if (dir_index != dirs.size() - 1){
                children_dir_status[i] = fs->IsDirectory(child_path);Status::OK();
              } else {
                children_dir_status[i] = is_directory ?
                    fs->IsDirectory(child_path) : Status::OK();
              }
            });
    for (size_t i = 0; i < children.size(); ++i) {
      const string child_path = io::JoinPath(current_dir, children[i]);
      // If the IsDirectory call was cancelled we bail.
      if (children_dir_status[i].code() == tensorflow::error::CANCELLED) {
        continue;
      }
      if (children_dir_status[i].ok()) {
        if (dir_index != dirs.size() - 1) {
          dir_q.push_back({child_path, dir_index});
        } else {
          results->push_back(child_path);
        }
      }
    }
  }
  return ret;
}

}  // namespace internal
}  // namespace tensorflow
<|endoftext|>


<commit_before>/*
===========================================================================

daemon gpl source code
copyright (c) 2013 unvanquished developers

this file is part of the daemon gpl source code (daemon source code).

daemon source code is free software: you can redistribute it and/or modify
it under the terms of the gnu general public license as published by
the free software foundation, either version 3 of the license, or
(at your option) any later version.

daemon source code is distributed in the hope that it will be useful,
but without any warranty; without even the implied warranty of
merchantability or fitness for a particular purpose.  see the
gnu general public license for more details.

you should have received a copy of the gnu general public license
along with daemon source code.  if not, see <http://www.gnu.org/licenses/>.

===========================================================================
*/

#include "AudioPrivate.h"

namespace Audio {

    //TODO nice usecase for Cvar::Range
    //TODO lazily check for the values
    static Cvar::Cvar<float> effectsVolume("audio.volume.effects", "the volume of the effects", Cvar::ARCHIVE, 0.8f);
    static Cvar::Cvar<float> musicVolume("audio.volume.music", "the volume of the music", Cvar::ARCHIVE, 0.8f);

    // We have a big, fixed number of source to avoid rendering too many sounds and slowing down the rest of the engine.
    struct sourceRecord_t {
        AL::Source source;
        std::shared_ptr<Sound> usingSound;
        bool active;
        int priority;
    };

    static sourceRecord_t* sources = nullptr;
    static constexpr int nSources = 128; //TODO see what's the limit for OpenAL soft

    sourceRecord_t* GetSource(int priority);

    static bool initialized = false;

    void InitSounds() {
        if (initialized) {
            return;
        }

        sources = new sourceRecord_t[nSources];

        for (int i = 0; i < nSources; i++) {
            sources[i].active = false;
        }

        initialized = true;
    }

    void ShutdownSounds() {
        if (not initialized) {
            return;
        }

        delete[] sources;
        sources = nullptr;

        initialized = false;
    }

    void UpdateSounds() {
        for (int i = 0; i < nSources; i++) {
            if (sources[i].active) {
                auto sound = sources[i].usingSound;

                // Update and Emitter::UpdateSound can call Sound::Stop
                if (not sound->IsStopped()) {
                    sound->Update();
                }

                if (not sound->IsStopped()) {
                    sound->GetEmitter()->UpdateSound(*sound);
                }

                if (sound->IsStopped()) {
                    sources[i].active = false;
                    sources[i].usingSound = nullptr;
                }
            }
        }
    }

    void AddSound(std::shared_ptr<Emitter> emitter, std::shared_ptr<Sound> sound, int priority) {
        sourceRecord_t* source = GetSource(priority);

        if (source) {
            // Make the source forget if it was a "static" or a "streaming" source.
            source->source.ResetBuffer();
            sound->SetEmitter(emitter);
            sound->AcquireSource(source->source);
            source->usingSound = sound;
            source->priority = priority;
            source->active = true;

            sound->FinishSetup();
            sound->Play();
        }
    }

    // Finds a inactive or low-priority source to play a new sound.
    sourceRecord_t* GetSource(int priority) {
        //TODO make a better heuristic? (take into account the distance / the volume /... ?)
        int best = -1;
        int bestPriority = priority;

        // Gets the minimum sound by comparing activity first then priority
        for (int i = 0; i < nSources; i++) {
            sourceRecord_t& source = sources[i];

            if (not source.active) {
                return &source;
            }

            if (best < 0 && source.priority <= priority) {
                best = i;
                bestPriority = source.priority;
                continue;
            }

            if (source.priority < bestPriority) {
                best = i;
                bestPriority = source.priority;
                continue;
            }
        }

        if (best >= 0) {
            sourceRecord_t& source = sources[best];

            source.source.Stop();
            source.source.RemoveAllQueuedBuffers();

            source.usingSound = nullptr;
            return &source;
        } else {
            return nullptr;
        }
    }

    // Implementation of Sound

    Sound::Sound(): positionalGain(1.0f), soundGain(1.0f), currentGain(1.0f) {
    }

    Sound::~Sound() {
    }

    void Sound::Play() {
        source->Play();
        playing = true;
    }

    void Sound::Stop() {
        source->Stop();
        playing = false;
    }

    bool Sound::IsStopped() {
        return not playing;
    }

    void Sound::SetPositionalGain(float gain) {
        positionalGain = gain;
    }

    void Sound::SetSoundGain(float gain) {
        soundGain = gain;
    }

    float Sound::GetCurrentGain() {
        return currentGain;
    }

    void Sound::SetEmitter(std::shared_ptr<Emitter> emitter) {
        this->emitter = emitter;
    }

    std::shared_ptr<Emitter> Sound::GetEmitter() {
        return emitter;
    }

    void Sound::AcquireSource(AL::Source& source) {
        this->source = &source;

        source.SetLooping(false);

        SetupSource(source);
        emitter->SetupSound(*this);
    }

    AL::Source& Sound::GetSource() {
        return *source;
    }

    // Set the gain before the source is started to avoid having a few milliseconds of very lound sound
    void Sound::FinishSetup() {
        currentGain = positionalGain * soundGain * effectsVolume.Get();
        source->SetGain(currentGain);
    }

    void Sound::Update() {
        // Fade the Gain update to avoid "ticking" sounds when there is a gain discontinuity
        float targetGain = positionalGain * soundGain * effectsVolume.Get();

        //TODO make it framerate independant and fade out in about 1/8 seconds ?
        if (currentGain > targetGain) {
            currentGain = std::max(currentGain - 0.02f, targetGain);
            //currentGain = std::max(currentGain * 1.05f, targetGain);
        } else if (currentGain < targetGain) {
            currentGain = std::min(currentGain + 0.02f, targetGain);
            //currentGain = std::min(currentGain / 1.05f - 0.01f, targetGain);
        }

        source->SetGain(currentGain);

        InternalUpdate();
    }
    // Implementation of OneShotSound

    OneShotSound::OneShotSound(Sample* sample): sample(sample) {
    }

    OneShotSound::~OneShotSound() {
    }

    void OneShotSound::SetupSource(AL::Source& source) {
        source.SetBuffer(sample->GetBuffer());
        SetSoundGain(effectsVolume.Get());
    }

    void OneShotSound::InternalUpdate() {
        if (GetSource().IsStopped()) {
            Stop();
            return;
        }
        SetSoundGain(effectsVolume.Get());
    }

    // Implementation of LoopingSound

    LoopingSound::LoopingSound(Sample* sample): sample(sample), fadingOut(false) {
    }

    LoopingSound::~LoopingSound() {
    }

    void LoopingSound::FadeOutAndDie() {
        fadingOut = true;
        SetSoundGain(0.0f);
    }

    void LoopingSound::SetupSource(AL::Source& source) {
        source.SetLooping(true);
        source.SetBuffer(sample->GetBuffer());
        SetSoundGain(effectsVolume.Get());
    }

    void LoopingSound::InternalUpdate() {
        if (fadingOut and GetCurrentGain() == 0.0f) {
            Stop();
        }

        if (not fadingOut) {
            SetSoundGain(effectsVolume.Get());
        }
    }

    // Implementation of MusicSound

    MusicSound::MusicSound(Str::StringRef leadingStreamName, Str::StringRef loopStreamName)
        : leadingStream(S_CodecOpenStream(leadingStreamName.c_str())),
          loopStreamName(loopStreamName), loopStream(nullptr), playingLeadingSound(true){
    }

    MusicSound::~MusicSound() {
        if (leadingStream) {
            S_CodecCloseStream(leadingStream);
        }
        if (loopStream) {
            S_CodecCloseStream(loopStream);
        }
    }

    void MusicSound::SetupSource(AL::Source& source) {
        for (int i = 0; i < NUM_BUFFERS; i++) {
            AppendBuffer(source, std::move(AL::Buffer()));
        }
        SetSoundGain(musicVolume.Get());
    }

    void MusicSound::InternalUpdate() {
        AL::Source& source = GetSource();

        // Fill processed buffers and queue them back in the source
        while (source.GetNumProcessedBuffers() > 0) {
            AppendBuffer(source, std::move(source.PopBuffer()));
        }

        // If we don't have any more buffers queued it means we have to stop the music
        if (source.GetNumQueuedBuffers() == 0) {
            Stop();

        // If the source stopped because of a lack of buffer but we still have data to play we start the source again
        } else if (source.IsStopped()) {
            Play();
        }

        SetSoundGain(musicVolume.Get());
    }

    void MusicSound::AppendBuffer(AL::Source& source, AL::Buffer buffer) {
        snd_stream_t* streamToRead;
        if (playingLeadingSound and leadingStream) {
            streamToRead = leadingStream;
        } else if (loopStream) {
            streamToRead = loopStream;
        } else {
            return;
        }

        static char tempBuffer[CHUNK_SIZE];
        int lengthRead = S_CodecReadStream(streamToRead, CHUNK_SIZE, tempBuffer);

        // if a stream is finished, we start playing the loop again, if possible
        if (lengthRead == 0) {
            S_CodecCloseStream(streamToRead);
            playingLeadingSound = false;
            // either the stream was the leadin stream and we null it
            leadingStream = nullptr;
            // either it is the loop stream and we overwrite it
            loopStream = S_CodecOpenStream(loopStreamName.c_str());
            AppendBuffer(source, std::move(buffer));
            return;
        }

        snd_info_t streamInfo = streamToRead->info;
        streamInfo.size = lengthRead; // this isn't set by Codec
        buffer.Feed(streamInfo, tempBuffer);

        source.QueueBuffer(std::move(buffer));
    }

    // Implementation of StreamingSound

    StreamingSound::StreamingSound() {
    }

    StreamingSound::~StreamingSound() {
    }

    void StreamingSound::SetupSource(AL::Source&) {
    }

    void StreamingSound::InternalUpdate() {
        AL::Source& source = GetSource();

        while (source.GetNumProcessedBuffers() > 0) {
            source.PopBuffer();
        }

        if (source.GetNumQueuedBuffers() == 0) {
            Stop();
        }
    }

	//TODO somehow try to catch back when data is coming faster than we consume (e.g. capture data)
    void StreamingSound::AppendBuffer(AL::Buffer buffer) {
        if (IsStopped()) {
            return;
        }

        AL::Source& source = GetSource();
        source.QueueBuffer(std::move(buffer));

        if (source.IsStopped()) {
            source.Play();
        }
    }

    void StreamingSound::SetGain(float gain) {
        SetSoundGain(gain);
    }
}
<commit_msg>Fully initialise instances of class Sound.<commit_after>/*
===========================================================================

daemon gpl source code
copyright (c) 2013 unvanquished developers

this file is part of the daemon gpl source code (daemon source code).

daemon source code is free software: you can redistribute it and/or modify
it under the terms of the gnu general public license as published by
the free software foundation, either version 3 of the license, or
(at your option) any later version.

daemon source code is distributed in the hope that it will be useful,
but without any warranty; without even the implied warranty of
merchantability or fitness for a particular purpose.  see the
gnu general public license for more details.

you should have received a copy of the gnu general public license
along with daemon source code.  if not, see <http://www.gnu.org/licenses/>.

===========================================================================
*/

#include "AudioPrivate.h"

namespace Audio {

    //TODO nice usecase for Cvar::Range
    //TODO lazily check for the values
    static Cvar::Cvar<float> effectsVolume("audio.volume.effects", "the volume of the effects", Cvar::ARCHIVE, 0.8f);
    static Cvar::Cvar<float> musicVolume("audio.volume.music", "the volume of the music", Cvar::ARCHIVE, 0.8f);

    // We have a big, fixed number of source to avoid rendering too many sounds and slowing down the rest of the engine.
    struct sourceRecord_t {
        AL::Source source;
        std::shared_ptr<Sound> usingSound;
        bool active;
        int priority;
    };

    static sourceRecord_t* sources = nullptr;
    static constexpr int nSources = 128; //TODO see what's the limit for OpenAL soft

    sourceRecord_t* GetSource(int priority);

    static bool initialized = false;

    void InitSounds() {
        if (initialized) {
            return;
        }

        sources = new sourceRecord_t[nSources];

        for (int i = 0; i < nSources; i++) {
            sources[i].active = false;
        }

        initialized = true;
    }

    void ShutdownSounds() {
        if (not initialized) {
            return;
        }

        delete[] sources;
        sources = nullptr;

        initialized = false;
    }

    void UpdateSounds() {
        for (int i = 0; i < nSources; i++) {
            if (sources[i].active) {
                auto sound = sources[i].usingSound;

                // Update and Emitter::UpdateSound can call Sound::Stop
                if (not sound->IsStopped()) {
                    sound->Update();
                }

                if (not sound->IsStopped()) {
                    sound->GetEmitter()->UpdateSound(*sound);
                }

                if (sound->IsStopped()) {
                    sources[i].active = false;
                    sources[i].usingSound = nullptr;
                }
            }
        }
    }

    void AddSound(std::shared_ptr<Emitter> emitter, std::shared_ptr<Sound> sound, int priority) {
        sourceRecord_t* source = GetSource(priority);

        if (source) {
            // Make the source forget if it was a "static" or a "streaming" source.
            source->source.ResetBuffer();
            sound->SetEmitter(emitter);
            sound->AcquireSource(source->source);
            source->usingSound = sound;
            source->priority = priority;
            source->active = true;

            sound->FinishSetup();
            sound->Play();
        }
    }

    // Finds a inactive or low-priority source to play a new sound.
    sourceRecord_t* GetSource(int priority) {
        //TODO make a better heuristic? (take into account the distance / the volume /... ?)
        int best = -1;
        int bestPriority = priority;

        // Gets the minimum sound by comparing activity first then priority
        for (int i = 0; i < nSources; i++) {
            sourceRecord_t& source = sources[i];

            if (not source.active) {
                return &source;
            }

            if (best < 0 && source.priority <= priority) {
                best = i;
                bestPriority = source.priority;
                continue;
            }

            if (source.priority < bestPriority) {
                best = i;
                bestPriority = source.priority;
                continue;
            }
        }

        if (best >= 0) {
            sourceRecord_t& source = sources[best];

            source.source.Stop();
            source.source.RemoveAllQueuedBuffers();

            source.usingSound = nullptr;
            return &source;
        } else {
            return nullptr;
        }
    }

    // Implementation of Sound

    Sound::Sound(): positionalGain(1.0f), soundGain(1.0f), currentGain(1.0f), playing(false), source(nullptr) {
    }

    Sound::~Sound() {
    }

    void Sound::Play() {
        source->Play();
        playing = true;
    }

    void Sound::Stop() {
        source->Stop();
        playing = false;
    }

    bool Sound::IsStopped() {
        return not playing;
    }

    void Sound::SetPositionalGain(float gain) {
        positionalGain = gain;
    }

    void Sound::SetSoundGain(float gain) {
        soundGain = gain;
    }

    float Sound::GetCurrentGain() {
        return currentGain;
    }

    void Sound::SetEmitter(std::shared_ptr<Emitter> emitter) {
        this->emitter = emitter;
    }

    std::shared_ptr<Emitter> Sound::GetEmitter() {
        return emitter;
    }

    void Sound::AcquireSource(AL::Source& source) {
        this->source = &source;

        source.SetLooping(false);

        SetupSource(source);
        emitter->SetupSound(*this);
    }

    AL::Source& Sound::GetSource() {
        return *source;
    }

    // Set the gain before the source is started to avoid having a few milliseconds of very lound sound
    void Sound::FinishSetup() {
        currentGain = positionalGain * soundGain * effectsVolume.Get();
        source->SetGain(currentGain);
    }

    void Sound::Update() {
        // Fade the Gain update to avoid "ticking" sounds when there is a gain discontinuity
        float targetGain = positionalGain * soundGain * effectsVolume.Get();

        //TODO make it framerate independant and fade out in about 1/8 seconds ?
        if (currentGain > targetGain) {
            currentGain = std::max(currentGain - 0.02f, targetGain);
            //currentGain = std::max(currentGain * 1.05f, targetGain);
        } else if (currentGain < targetGain) {
            currentGain = std::min(currentGain + 0.02f, targetGain);
            //currentGain = std::min(currentGain / 1.05f - 0.01f, targetGain);
        }

        source->SetGain(currentGain);

        InternalUpdate();
    }
    // Implementation of OneShotSound

    OneShotSound::OneShotSound(Sample* sample): sample(sample) {
    }

    OneShotSound::~OneShotSound() {
    }

    void OneShotSound::SetupSource(AL::Source& source) {
        source.SetBuffer(sample->GetBuffer());
        SetSoundGain(effectsVolume.Get());
    }

    void OneShotSound::InternalUpdate() {
        if (GetSource().IsStopped()) {
            Stop();
            return;
        }
        SetSoundGain(effectsVolume.Get());
    }

    // Implementation of LoopingSound

    LoopingSound::LoopingSound(Sample* sample): sample(sample), fadingOut(false) {
    }

    LoopingSound::~LoopingSound() {
    }

    void LoopingSound::FadeOutAndDie() {
        fadingOut = true;
        SetSoundGain(0.0f);
    }

    void LoopingSound::SetupSource(AL::Source& source) {
        source.SetLooping(true);
        source.SetBuffer(sample->GetBuffer());
        SetSoundGain(effectsVolume.Get());
    }

    void LoopingSound::InternalUpdate() {
        if (fadingOut and GetCurrentGain() == 0.0f) {
            Stop();
        }

        if (not fadingOut) {
            SetSoundGain(effectsVolume.Get());
        }
    }

    // Implementation of MusicSound

    MusicSound::MusicSound(Str::StringRef leadingStreamName, Str::StringRef loopStreamName)
        : leadingStream(S_CodecOpenStream(leadingStreamName.c_str())),
          loopStreamName(loopStreamName), loopStream(nullptr), playingLeadingSound(true){
    }

    MusicSound::~MusicSound() {
        if (leadingStream) {
            S_CodecCloseStream(leadingStream);
        }
        if (loopStream) {
            S_CodecCloseStream(loopStream);
        }
    }

    void MusicSound::SetupSource(AL::Source& source) {
        for (int i = 0; i < NUM_BUFFERS; i++) {
            AppendBuffer(source, std::move(AL::Buffer()));
        }
        SetSoundGain(musicVolume.Get());
    }

    void MusicSound::InternalUpdate() {
        AL::Source& source = GetSource();

        // Fill processed buffers and queue them back in the source
        while (source.GetNumProcessedBuffers() > 0) {
            AppendBuffer(source, std::move(source.PopBuffer()));
        }

        // If we don't have any more buffers queued it means we have to stop the music
        if (source.GetNumQueuedBuffers() == 0) {
            Stop();

        // If the source stopped because of a lack of buffer but we still have data to play we start the source again
        } else if (source.IsStopped()) {
            Play();
        }

        SetSoundGain(musicVolume.Get());
    }

    void MusicSound::AppendBuffer(AL::Source& source, AL::Buffer buffer) {
        snd_stream_t* streamToRead;
        if (playingLeadingSound and leadingStream) {
            streamToRead = leadingStream;
        } else if (loopStream) {
            streamToRead = loopStream;
        } else {
            return;
        }

        static char tempBuffer[CHUNK_SIZE];
        int lengthRead = S_CodecReadStream(streamToRead, CHUNK_SIZE, tempBuffer);

        // if a stream is finished, we start playing the loop again, if possible
        if (lengthRead == 0) {
            S_CodecCloseStream(streamToRead);
            playingLeadingSound = false;
            // either the stream was the leadin stream and we null it
            leadingStream = nullptr;
            // either it is the loop stream and we overwrite it
            loopStream = S_CodecOpenStream(loopStreamName.c_str());
            AppendBuffer(source, std::move(buffer));
            return;
        }

        snd_info_t streamInfo = streamToRead->info;
        streamInfo.size = lengthRead; // this isn't set by Codec
        buffer.Feed(streamInfo, tempBuffer);

        source.QueueBuffer(std::move(buffer));
    }

    // Implementation of StreamingSound

    StreamingSound::StreamingSound() {
    }

    StreamingSound::~StreamingSound() {
    }

    void StreamingSound::SetupSource(AL::Source&) {
    }

    void StreamingSound::InternalUpdate() {
        AL::Source& source = GetSource();

        while (source.GetNumProcessedBuffers() > 0) {
            source.PopBuffer();
        }

        if (source.GetNumQueuedBuffers() == 0) {
            Stop();
        }
    }

	//TODO somehow try to catch back when data is coming faster than we consume (e.g. capture data)
    void StreamingSound::AppendBuffer(AL::Buffer buffer) {
        if (IsStopped()) {
            return;
        }

        AL::Source& source = GetSource();
        source.QueueBuffer(std::move(buffer));

        if (source.IsStopped()) {
            source.Play();
        }
    }

    void StreamingSound::SetGain(float gain) {
        SetSoundGain(gain);
    }
}
<|endoftext|>


<commit_before>#include "scene/Scene.hpp"
#include "scene/Sky.hpp"
#include "system/TextUtilities.hpp"

#include <map>
#include <sstream>

Scene::Scene(const std::string & name) {
	// Append the extension if needed.
	std::string fullName = name;
	if(!TextUtilities::hasSuffix(name, ".scene")) {
		fullName += ".scene";
	}
	_name = fullName;
}

void printToken(const KeyValues & tk, const std::string & shift) {
	Log::Info() << shift << tk.key << ": " << std::endl;
	if(!tk.values.empty()) {
		Log::Info() << shift << "\t";
		for(const auto & val : tk.values) {
			Log::Info() << val << " | ";
		}
		Log::Info() << std::endl;
	}
	for(const auto & subtk : tk.elements) {
		printToken(subtk, shift + "\t");
	}
}

void Scene::init(Storage mode) {
	if(_loaded) {
		return;
	}
	const auto start = std::chrono::steady_clock::now();

	// Define loaders for each keyword.
	std::map<std::string, void (Scene::*)(const KeyValues &, Storage)> loaders = {
		{"scene", &Scene::loadScene}, {"object", &Scene::loadObject}, {"point", &Scene::loadLight}, {"directional", &Scene::loadLight}, {"spot", &Scene::loadLight}, {"camera", &Scene::loadCamera}, {"background", &Scene::loadBackground}};

	// Parse the file.
	const std::string sceneFile			   = Resources::manager().getString(_name);
	const std::vector<KeyValues> allParams = Codable::parse(sceneFile);

	// Process each group of keyvalues.
	for(const auto & element : allParams) {
		const std::string key = element.key;
		// By construction (see above), all keys should have a loader.
		(this->*loaders[key])(element, mode);
	}

	// Update all objects poses.
	for(auto & object : objects) {
		const glm::mat4 newModel = _sceneModel * object.model();
		object.set(newModel);
	}
	// The scene model matrix has been applied to all objects, we can reset it.
	_sceneModel = glm::mat4(1.0f);
	// Update all lights bounding box infos.
	_bbox = computeBoundingBox(true);
	for(auto & light : lights) {
		light->setScene(_bbox);
	}
	_loaded = true;
	const auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::steady_clock::now() - start);
	Log::Info() << Log::Resources << "Loading took " << duration.count() << "ms." << std::endl;
}

void Scene::loadObject(const KeyValues & params, Storage mode) {
	objects.emplace_back();
	objects.back().decode(params, mode);
}

void Scene::loadLight(const KeyValues & params, Storage) {
	const auto light = Light::decode(params);
	if(light) {
		lights.push_back(light);
	}
}

void Scene::loadCamera(const KeyValues & params, Storage) {
	_camera.decode(params);
}

void Scene::loadBackground(const KeyValues & params, Storage mode) {
	background = std::unique_ptr<Object>(new Object(Object::Type::Common, Resources::manager().getMesh("plane", mode), false));

	for(const auto & param : params.elements) {
		if(param.key == "color") {
			backgroundMode = Background::COLOR;
			// Background is a plane, store the color.
			backgroundColor = Codable::decodeVec3(param);

		} else if(param.key == "image" && !param.elements.empty()) {
			backgroundMode = Background::IMAGE;
			// Load image described as sub-element.
			const auto texInfos = Codable::decodeTexture(param.elements[0]);
			const Texture * tex = Resources::manager().getTexture(texInfos.first, texInfos.second, mode);
			background->addTexture(tex);

		} else if(param.key == "cube" && !param.elements.empty()) {
			backgroundMode = Background::SKYBOX;
			// Object is a textured skybox.
			background = std::unique_ptr<Object>(new Object(Object::Type::Common, Resources::manager().getMesh("skybox", mode), false));
			background->decode(params, mode);
			// Load cubemap described as subelement.
			const auto texInfos = Codable::decodeTexture(param.elements[0]);
			const Texture * tex = Resources::manager().getTexture(texInfos.first, texInfos.second, mode);
			background->addTexture(tex);

		} else if(param.key == "sun") {
			// In that case the background is a sky object.
			backgroundMode = Background::ATMOSPHERE;
			background	 = std::unique_ptr<Sky>(new Sky(mode));
			background->decode(params, mode);
			// Load the scattering table.
			const Texture * tex = Resources::manager().getTexture("scattering-precomputed", {Layout::RGB32F, Filter::LINEAR_LINEAR, Wrap::CLAMP}, mode);
			background->addTexture(tex);
		}
	}
}

void Scene::loadScene(const KeyValues & params, Storage mode) {
	backgroundIrradiance = std::vector<glm::vec3>(9, glm::vec3(0.0f));

	for(const auto & param : params.elements) {
		if(param.key == "irradiance" && !param.values.empty()) {
			// Load the SH coefficients from the corresponding text file.
			const std::string coeffsRaw = Resources::manager().getString(param.values[0]);
			std::stringstream coeffsStream(coeffsRaw);
			float x = 0.0f;
			float y = 0.0f;
			float z = 0.0f;
			for(int i = 0; i < 9; ++i) {
				coeffsStream >> x >> y >> z;
				backgroundIrradiance[i] = glm::vec3(x, y, z);
			}

		} else if(param.key == "probe" && !param.elements.empty()) {
			// Load cubemap described as sub-element.
			const auto texInfos = Codable::decodeTexture(param.elements[0]);
			backgroundReflection = Resources::manager().getTexture(texInfos.first, texInfos.second, mode);
		}
	}
	// Update matrix, there is at most one transformation in the scene object.
	_sceneModel = Codable::decodeTransformation(params.elements);
}

BoundingBox Scene::computeBoundingBox(bool onlyShadowCasters) {
	BoundingBox bbox;
	if(objects.empty()) {
		return bbox;
	}

	for(const auto & obj : objects) {
		if(onlyShadowCasters && !obj.castsShadow()) {
			continue;
		}
		bbox.merge(obj.boundingBox());
	}
	Log::Info() << Log::Resources << "Scene bounding box:" << std::endl
				<< "mini: " << bbox.minis << std::endl
				<< "maxi: " << bbox.maxis << "." << std::endl;
	return bbox;
}

void Scene::update(double fullTime, double frameTime) {
	for(auto & light : lights) {
		light->update(fullTime, frameTime);
	}
	for(auto & object : objects) {
		object.update(fullTime, frameTime);
	}
	background->update(fullTime, frameTime);
}

void Scene::clean() {
	for(auto & light : lights) {
		light->clean();
	}
}
<commit_msg>Scene: fix missing include.<commit_after>#include "scene/Scene.hpp"
#include "scene/Sky.hpp"
#include "system/TextUtilities.hpp"

#include <map>
#include <sstream>
#include <chrono>

Scene::Scene(const std::string & name) {
	// Append the extension if needed.
	std::string fullName = name;
	if(!TextUtilities::hasSuffix(name, ".scene")) {
		fullName += ".scene";
	}
	_name = fullName;
}

void printToken(const KeyValues & tk, const std::string & shift) {
	Log::Info() << shift << tk.key << ": " << std::endl;
	if(!tk.values.empty()) {
		Log::Info() << shift << "\t";
		for(const auto & val : tk.values) {
			Log::Info() << val << " | ";
		}
		Log::Info() << std::endl;
	}
	for(const auto & subtk : tk.elements) {
		printToken(subtk, shift + "\t");
	}
}

void Scene::init(Storage mode) {
	if(_loaded) {
		return;
	}
	const auto start = std::chrono::steady_clock::now();

	// Define loaders for each keyword.
	std::map<std::string, void (Scene::*)(const KeyValues &, Storage)> loaders = {
		{"scene", &Scene::loadScene}, {"object", &Scene::loadObject}, {"point", &Scene::loadLight}, {"directional", &Scene::loadLight}, {"spot", &Scene::loadLight}, {"camera", &Scene::loadCamera}, {"background", &Scene::loadBackground}};

	// Parse the file.
	const std::string sceneFile			   = Resources::manager().getString(_name);
	const std::vector<KeyValues> allParams = Codable::parse(sceneFile);

	// Process each group of keyvalues.
	for(const auto & element : allParams) {
		const std::string key = element.key;
		// By construction (see above), all keys should have a loader.
		(this->*loaders[key])(element, mode);
	}

	// Update all objects poses.
	for(auto & object : objects) {
		const glm::mat4 newModel = _sceneModel * object.model();
		object.set(newModel);
	}
	// The scene model matrix has been applied to all objects, we can reset it.
	_sceneModel = glm::mat4(1.0f);
	// Update all lights bounding box infos.
	_bbox = computeBoundingBox(true);
	for(auto & light : lights) {
		light->setScene(_bbox);
	}
	_loaded = true;
	const auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::steady_clock::now() - start);
	Log::Info() << Log::Resources << "Loading took " << duration.count() << "ms." << std::endl;
}

void Scene::loadObject(const KeyValues & params, Storage mode) {
	objects.emplace_back();
	objects.back().decode(params, mode);
}

void Scene::loadLight(const KeyValues & params, Storage) {
	const auto light = Light::decode(params);
	if(light) {
		lights.push_back(light);
	}
}

void Scene::loadCamera(const KeyValues & params, Storage) {
	_camera.decode(params);
}

void Scene::loadBackground(const KeyValues & params, Storage mode) {
	background = std::unique_ptr<Object>(new Object(Object::Type::Common, Resources::manager().getMesh("plane", mode), false));

	for(const auto & param : params.elements) {
		if(param.key == "color") {
			backgroundMode = Background::COLOR;
			// Background is a plane, store the color.
			backgroundColor = Codable::decodeVec3(param);

		} else if(param.key == "image" && !param.elements.empty()) {
			backgroundMode = Background::IMAGE;
			// Load image described as sub-element.
			const auto texInfos = Codable::decodeTexture(param.elements[0]);
			const Texture * tex = Resources::manager().getTexture(texInfos.first, texInfos.second, mode);
			background->addTexture(tex);

		} else if(param.key == "cube" && !param.elements.empty()) {
			backgroundMode = Background::SKYBOX;
			// Object is a textured skybox.
			background = std::unique_ptr<Object>(new Object(Object::Type::Common, Resources::manager().getMesh("skybox", mode), false));
			background->decode(params, mode);
			// Load cubemap described as subelement.
			const auto texInfos = Codable::decodeTexture(param.elements[0]);
			const Texture * tex = Resources::manager().getTexture(texInfos.first, texInfos.second, mode);
			background->addTexture(tex);

		} else if(param.key == "sun") {
			// In that case the background is a sky object.
			backgroundMode = Background::ATMOSPHERE;
			background	 = std::unique_ptr<Sky>(new Sky(mode));
			background->decode(params, mode);
			// Load the scattering table.
			const Texture * tex = Resources::manager().getTexture("scattering-precomputed", {Layout::RGB32F, Filter::LINEAR_LINEAR, Wrap::CLAMP}, mode);
			background->addTexture(tex);
		}
	}
}

void Scene::loadScene(const KeyValues & params, Storage mode) {
	backgroundIrradiance = std::vector<glm::vec3>(9, glm::vec3(0.0f));

	for(const auto & param : params.elements) {
		if(param.key == "irradiance" && !param.values.empty()) {
			// Load the SH coefficients from the corresponding text file.
			const std::string coeffsRaw = Resources::manager().getString(param.values[0]);
			std::stringstream coeffsStream(coeffsRaw);
			float x = 0.0f;
			float y = 0.0f;
			float z = 0.0f;
			for(int i = 0; i < 9; ++i) {
				coeffsStream >> x >> y >> z;
				backgroundIrradiance[i] = glm::vec3(x, y, z);
			}

		} else if(param.key == "probe" && !param.elements.empty()) {
			// Load cubemap described as sub-element.
			const auto texInfos = Codable::decodeTexture(param.elements[0]);
			backgroundReflection = Resources::manager().getTexture(texInfos.first, texInfos.second, mode);
		}
	}
	// Update matrix, there is at most one transformation in the scene object.
	_sceneModel = Codable::decodeTransformation(params.elements);
}

BoundingBox Scene::computeBoundingBox(bool onlyShadowCasters) {
	BoundingBox bbox;
	if(objects.empty()) {
		return bbox;
	}

	for(const auto & obj : objects) {
		if(onlyShadowCasters && !obj.castsShadow()) {
			continue;
		}
		bbox.merge(obj.boundingBox());
	}
	Log::Info() << Log::Resources << "Scene bounding box:" << std::endl
				<< "mini: " << bbox.minis << std::endl
				<< "maxi: " << bbox.maxis << "." << std::endl;
	return bbox;
}

void Scene::update(double fullTime, double frameTime) {
	for(auto & light : lights) {
		light->update(fullTime, frameTime);
	}
	for(auto & object : objects) {
		object.update(fullTime, frameTime);
	}
	background->update(fullTime, frameTime);
}

void Scene::clean() {
	for(auto & light : lights) {
		light->clean();
	}
}
<|endoftext|>


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

#include "autopilot_tester.h"
#include <chrono>

TEST_CASE("Takeoff and Land", "[multicopter][vtol]")
{
	AutopilotTester tester;
	tester.connect(connection_url);
	tester.wait_until_ready();
	tester.arm();
	tester.takeoff();
	tester.wait_until_hovering();
	tester.land();
	std::chrono::seconds until_disarmed_timeout = std::chrono::seconds(180);
	tester.wait_until_disarmed(until_disarmed_timeout);
}

TEST_CASE("Fly square Multicopter Missions including RTL", "[multicopter][vtol]")
{
	AutopilotTester tester;
	tester.connect(connection_url);
	tester.wait_until_ready();

	AutopilotTester::MissionOptions mission_options;
	mission_options.rtl_at_end = true;
	tester.prepare_square_mission(mission_options);
	tester.arm();
	tester.execute_mission();
	std::chrono::seconds until_disarmed_timeout = std::chrono::seconds(180);
	tester.wait_until_disarmed(until_disarmed_timeout);
}

TEST_CASE("Fly square Multicopter Missions with manual RTL", "[multicopter][vtol]")
{
	AutopilotTester tester;
	tester.connect(connection_url);
	tester.wait_until_ready();

	AutopilotTester::MissionOptions mission_options;
	mission_options.rtl_at_end = false;
	tester.prepare_square_mission(mission_options);
	tester.check_tracks_mission();
	tester.arm();
	tester.execute_mission();
	tester.wait_until_hovering();
	tester.execute_rtl();
	std::chrono::seconds until_disarmed_timeout = std::chrono::seconds(180);
	tester.wait_until_disarmed(until_disarmed_timeout);
}

TEST_CASE("Fly straight Multicopter Mission", "[multicopter]")
{
	AutopilotTester tester;
	tester.connect(connection_url);
	tester.wait_until_ready();

	AutopilotTester::MissionOptions mission_options;
	mission_options.rtl_at_end = false;
	mission_options.fly_through = true;
	tester.prepare_straight_mission(mission_options);
	tester.check_mission_item_speed_above(2, 4.5);
	tester.check_tracks_mission();
	tester.arm();
	tester.execute_mission();
	tester.wait_until_hovering();
	tester.execute_rtl();
	std::chrono::seconds until_disarmed_timeout = std::chrono::seconds(180);
	tester.wait_until_disarmed(until_disarmed_timeout);
}
<commit_msg>Increase corridor check thresholds for mission tests<commit_after>/****************************************************************************
 *
 *   Copyright (c) 2020 PX4 Development Team. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 * 3. Neither the name PX4 nor the names of its contributors may be
 *    used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 ****************************************************************************/

#include "autopilot_tester.h"
#include <chrono>

TEST_CASE("Takeoff and Land", "[multicopter][vtol]")
{
	AutopilotTester tester;
	tester.connect(connection_url);
	tester.wait_until_ready();
	tester.arm();
	tester.takeoff();
	tester.wait_until_hovering();
	tester.land();
	std::chrono::seconds until_disarmed_timeout = std::chrono::seconds(180);
	tester.wait_until_disarmed(until_disarmed_timeout);
}

TEST_CASE("Fly square Multicopter Missions including RTL", "[multicopter][vtol]")
{
	AutopilotTester tester;
	tester.connect(connection_url);
	tester.wait_until_ready();

	AutopilotTester::MissionOptions mission_options;
	mission_options.rtl_at_end = true;
	tester.prepare_square_mission(mission_options);
	tester.arm();
	tester.execute_mission();
	std::chrono::seconds until_disarmed_timeout = std::chrono::seconds(180);
	tester.wait_until_disarmed(until_disarmed_timeout);
}

TEST_CASE("Fly square Multicopter Missions with manual RTL", "[multicopter][vtol]")
{
	AutopilotTester tester;
	tester.connect(connection_url);
	tester.wait_until_ready();

	AutopilotTester::MissionOptions mission_options;
	mission_options.rtl_at_end = false;
	tester.prepare_square_mission(mission_options);
	tester.check_tracks_mission(5.f);
	tester.arm();
	tester.execute_mission();
	tester.wait_until_hovering();
	tester.execute_rtl();
	std::chrono::seconds until_disarmed_timeout = std::chrono::seconds(180);
	tester.wait_until_disarmed(until_disarmed_timeout);
}

TEST_CASE("Fly straight Multicopter Mission", "[multicopter]")
{
	AutopilotTester tester;
	tester.connect(connection_url);
	tester.wait_until_ready();

	AutopilotTester::MissionOptions mission_options;
	mission_options.rtl_at_end = false;
	mission_options.fly_through = true;
	tester.prepare_straight_mission(mission_options);
	tester.check_mission_item_speed_above(2, 4.5);
	tester.check_tracks_mission(5.f);
	tester.arm();
	tester.execute_mission();
	tester.wait_until_hovering();
	tester.execute_rtl();
	std::chrono::seconds until_disarmed_timeout = std::chrono::seconds(180);
	tester.wait_until_disarmed(until_disarmed_timeout);
}
<|endoftext|>


<commit_before>#pragma once
#define ENABLE_WAWL_WINDOWBASETYPE

#include "BaseType.hpp"
#include "MenuBaseType.hpp"

namespace wawl {
	namespace wnd {

		enum class ImageLoadOption : Uint {
			DefaultColor = LR_DEFAULTCOLOR,
			UseDIBSection = LR_CREATEDIBSECTION,
			SysDefaultSize = LR_DEFAULTSIZE,
			Monochrome = LR_MONOCHROME,
			ShareHandle = LR_SHARED,
			UseVGA = LR_VGACOLOR
		};

		// window show mode
		enum class ShowMode : Uint16 {
			ForceMinimize = SW_FORCEMINIMIZE,
			Hide = SW_HIDE,
			Maximize = SW_MAXIMIZE,
			Minimize = SW_MINIMIZE,
			Restore = SW_RESTORE,
			Show = SW_SHOW,
			DefaultShow = SW_SHOWDEFAULT,
			MaximizedShow = SW_SHOWMAXIMIZED,
			MinimizedShow = SW_SHOWMINIMIZED,
			InactivateMinimized = SW_SHOWMINNOACTIVE,
			NoactivateShow = SW_SHOWNA,
			NormalShow = SW_SHOWNORMAL,
			NoactivateNormalShow = SW_SHOWNOACTIVATE
		};

		// window property option
		enum class PropOption : unsigned int {
			AlignClientByByte = CS_BYTEALIGNCLIENT,
			AlignWndByByte = CS_BYTEALIGNWINDOW,
			VRedraw = CS_HREDRAW,
			HRedraw = CS_VREDRAW,
			CallOnDoubleClick = CS_DBLCLKS,
			NoClose = CS_NOCLOSE,
			ShareDC = CS_CLASSDC,
			OriginalDC = CS_OWNDC,
			ParentDC = CS_PARENTDC,
			Global = CS_GLOBALCLASS,
			SaveBitmap = CS_SAVEBITS,
			DropShadow = CS_DROPSHADOW
		};

		// gdi color brushes
		enum class ColorBrush : int {
			White = WHITE_BRUSH,
			Black = BLACK_BRUSH,
			DarkGray = DKGRAY_BRUSH,
			LightGray = LTGRAY_BRUSH,
			Hollow = HOLLOW_BRUSH
		};

		// window procedure message
		// ToDo: need more
		enum class Msg : unsigned int {
			Activate = WM_ACTIVATE,
			ActivateApp = WM_ACTIVATEAPP,
			Create = WM_CREATE,
			Timer = WM_TIMER,
			Destroy = WM_DESTROY,
			LClick = WM_LBUTTONDOWN,
			MClick = WM_MBUTTONDOWN,
			RClick = WM_RBUTTONDOWN,
			MouseLDoubleClick = WM_LBUTTONDBLCLK,
			MouseMDoubleClick = WM_MBUTTONDBLCLK,
			MouseRDoubleClick = WM_RBUTTONDBLCLK,
			MouseLUp = WM_LBUTTONUP,
			MouseMUp = WM_MBUTTONUP,
			MouseRUp = WM_RBUTTONUP,
			Close = WM_CLOSE,
			Enable = WM_ENABLE,
			Resize = WM_SIZE,
			Resizing = WM_SIZING,
			Move = WM_MOVE,
			Quit = WM_QUIT,
			Null = WM_NULL,
			Paint = WM_PAINT,

			// and more...
		};

		using Message = ::MSG;

		// window option
		enum class Option : Uint32 {
			Bordered = WS_BORDER,
			Caption = WS_CAPTION,
			Child = WS_CHILD,
			NotDrawChildrenRegion = WS_CLIPCHILDREN,
			NotDrawBroserRegion = WS_CLIPSIBLINGS,
			Disabled = WS_DISABLED,
			ControlGroup = WS_GROUP,
			UseHorizontalScroll = WS_HSCROLL,
			UseVerticalScroll = WS_VSCROLL,
			Maxmize = WS_MAXIMIZE,
			EnableMaximize = WS_MAXIMIZEBOX,
			Minimize = WS_MINIMIZE,
			EnableMinimize = WS_MINIMIZEBOX,
			Tiled = WS_TILED,
			Overlapped = WS_OVERLAPPEDWINDOW,
			Popup = WS_POPUP,
			PopupSet = WS_POPUPWINDOW,
			EnableSizeChange = WS_SIZEBOX,
			SysMenu = WS_SYSMENU,
			AcceptTab = WS_TABSTOP,
			Visible = WS_VISIBLE
		};

		// extended window option
		enum class ExtOption : Uint32 {
			EnableFileDD = WS_EX_ACCEPTFILES,
			ShowToTaskbar = WS_EX_APPWINDOW,
			UseEdgeFrame = WS_EX_CLIENTEDGE,
			EnableHelp = WS_EX_CONTEXTHELP,
			DistinguishChild = WS_EX_CONTROLPARENT,
			EmphasisDialog = WS_EX_DLGMODALFRAME,
			Layered = WS_EX_LAYERED,
			LeftOrder = WS_EX_LEFT,
			LeftScrollBar = WS_EX_LEFTSCROLLBAR,
			ReadFromLeft = WS_EX_LTRREADING,
			MdiChiled = WS_EX_MDICHILD,
			NoParentNotify = WS_EX_NOPARENTNOTIFY,
			Overlapped = WS_EX_OVERLAPPEDWINDOW,
			Palette = WS_EX_PALETTEWINDOW,
			RightOrder = WS_EX_RIGHT,
			RightScrollBar = WS_EX_RIGHTSCROLLBAR,
			ReadFromRight = WS_EX_RTLREADING,
			UseFloatFrame = WS_EX_STATICEDGE,
			ToolWindow = WS_EX_TOOLWINDOW,
			TopMost = WS_EX_TOPMOST,
			Transparent = WS_EX_TRANSPARENT
		};

		// window procedure function
		using ProcFunc = std::remove_pointer_t<::WNDPROC>;

		using WindowHandle = ::HWND;
		using ChildID = MenuHandle;

		using CreateStruct = ::CREATESTRUCT;

	} // ::wawl::wnd
} // ::wawl<commit_msg>Add some window messages<commit_after>#pragma once
#define ENABLE_WAWL_WINDOWBASETYPE

#include "BaseType.hpp"
#include "MenuBaseType.hpp"

namespace wawl {
	namespace wnd {

		enum class ImageLoadOption : Uint {
			DefaultColor = LR_DEFAULTCOLOR,
			UseDIBSection = LR_CREATEDIBSECTION,
			SysDefaultSize = LR_DEFAULTSIZE,
			Monochrome = LR_MONOCHROME,
			ShareHandle = LR_SHARED,
			UseVGA = LR_VGACOLOR
		};

		// window show mode
		enum class ShowMode : Uint16 {
			ForceMinimize = SW_FORCEMINIMIZE,
			Hide = SW_HIDE,
			Maximize = SW_MAXIMIZE,
			Minimize = SW_MINIMIZE,
			Restore = SW_RESTORE,
			Show = SW_SHOW,
			DefaultShow = SW_SHOWDEFAULT,
			MaximizedShow = SW_SHOWMAXIMIZED,
			MinimizedShow = SW_SHOWMINIMIZED,
			InactivateMinimized = SW_SHOWMINNOACTIVE,
			NoactivateShow = SW_SHOWNA,
			NormalShow = SW_SHOWNORMAL,
			NoactivateNormalShow = SW_SHOWNOACTIVATE
		};

		// window property option
		enum class PropOption : unsigned int {
			AlignClientByByte = CS_BYTEALIGNCLIENT,
			AlignWndByByte = CS_BYTEALIGNWINDOW,
			VRedraw = CS_HREDRAW,
			HRedraw = CS_VREDRAW,
			CallOnDoubleClick = CS_DBLCLKS,
			NoClose = CS_NOCLOSE,
			ShareDC = CS_CLASSDC,
			OriginalDC = CS_OWNDC,
			ParentDC = CS_PARENTDC,
			Global = CS_GLOBALCLASS,
			SaveBitmap = CS_SAVEBITS,
			DropShadow = CS_DROPSHADOW
		};

		// gdi color brushes
		enum class ColorBrush : int {
			White = WHITE_BRUSH,
			Black = BLACK_BRUSH,
			DarkGray = DKGRAY_BRUSH,
			LightGray = LTGRAY_BRUSH,
			Hollow = HOLLOW_BRUSH
		};

		// window procedure message
		// ToDo: need more
		enum class Msg : unsigned int {
			Activate = WM_ACTIVATE,
			ActivateApp = WM_ACTIVATEAPP,
			ChildActivate = WM_CHILDACTIVATE,
			Close = WM_CLOSE,
			Command = WM_COMMAND,
			Create = WM_CREATE,
			Destroy = WM_DESTROY,
			ToggleState = WM_ENABLE,
			Timer = WM_TIMER,
			LClick = WM_LBUTTONDOWN,
			MClick = WM_MBUTTONDOWN,
			RClick = WM_RBUTTONDOWN,
			MouseLDoubleClick = WM_LBUTTONDBLCLK,
			MouseMDoubleClick = WM_MBUTTONDBLCLK,
			MouseRDoubleClick = WM_RBUTTONDBLCLK,
			MouseLUp = WM_LBUTTONUP,
			MouseMUp = WM_MBUTTONUP,
			MouseRUp = WM_RBUTTONUP,
			Resize = WM_SIZE,
			Resizing = WM_SIZING,
			Move = WM_MOVE,
			Quit = WM_QUIT,
			Null = WM_NULL,
			Paint = WM_PAINT,
			CharInput = WM_CHAR,
			CharInputDetail = WM_CHARTOITEM,
			GetFocus = WM_SETFOCUS,
			LostFocus = WM_KILLFOCUS,
			GetClipboardFormats = WM_ASKCBFORMATNAME,
			CancelJaurnal = WM_CANCELJOURNAL,
			MouseCaptureChanged = WM_CAPTURECHANGED,
			ClipboardChainChanged = WM_CHANGECBCHAIN,
			DestroyClipboard = WM_DESTROYCLIPBOARD,
			Disable = WM_CANCELMODE,
			FontChoose = WM_CHOOSEFONT_GETLOGFONT,
			ClearText = WM_CLEAR,
			CopyText = WM_COPY,
			CutText = WM_CUT,
			DeviceChanged = WM_DEVICECHANGE,
			DisplayChanged = WM_DISPLAYCHANGE,
			ClipboardUpdated = WM_DRAWCLIPBOARD,
			SystemShutdown = WM_ENDSESSION,
			SystemFontChanged = WM_FONTCHANGE,
			Help = WM_HELP,
			HotkeyPushed = WM_HOTKEY,

			// and more...
		};

		using Message = ::MSG;

		// window option
		enum class Option : Uint32 {
			Bordered = WS_BORDER,
			Caption = WS_CAPTION,
			Child = WS_CHILD,
			NotDrawChildrenRegion = WS_CLIPCHILDREN,
			NotDrawBroserRegion = WS_CLIPSIBLINGS,
			Disabled = WS_DISABLED,
			ControlGroup = WS_GROUP,
			UseHorizontalScroll = WS_HSCROLL,
			UseVerticalScroll = WS_VSCROLL,
			Maxmize = WS_MAXIMIZE,
			EnableMaximize = WS_MAXIMIZEBOX,
			Minimize = WS_MINIMIZE,
			EnableMinimize = WS_MINIMIZEBOX,
			Tiled = WS_TILED,
			Overlapped = WS_OVERLAPPEDWINDOW,
			Popup = WS_POPUP,
			PopupSet = WS_POPUPWINDOW,
			EnableSizeChange = WS_SIZEBOX,
			SysMenu = WS_SYSMENU,
			AcceptTab = WS_TABSTOP,
			Visible = WS_VISIBLE
		};

		// extended window option
		enum class ExtOption : Uint32 {
			EnableFileDD = WS_EX_ACCEPTFILES,
			ShowToTaskbar = WS_EX_APPWINDOW,
			UseEdgeFrame = WS_EX_CLIENTEDGE,
			EnableHelp = WS_EX_CONTEXTHELP,
			DistinguishChild = WS_EX_CONTROLPARENT,
			EmphasisDialog = WS_EX_DLGMODALFRAME,
			Layered = WS_EX_LAYERED,
			LeftOrder = WS_EX_LEFT,
			LeftScrollBar = WS_EX_LEFTSCROLLBAR,
			ReadFromLeft = WS_EX_LTRREADING,
			MdiChiled = WS_EX_MDICHILD,
			NoParentNotify = WS_EX_NOPARENTNOTIFY,
			Overlapped = WS_EX_OVERLAPPEDWINDOW,
			Palette = WS_EX_PALETTEWINDOW,
			RightOrder = WS_EX_RIGHT,
			RightScrollBar = WS_EX_RIGHTSCROLLBAR,
			ReadFromRight = WS_EX_RTLREADING,
			UseFloatFrame = WS_EX_STATICEDGE,
			ToolWindow = WS_EX_TOOLWINDOW,
			TopMost = WS_EX_TOPMOST,
			Transparent = WS_EX_TRANSPARENT
		};

		// window procedure function
		using ProcFunc = std::remove_pointer_t<::WNDPROC>;

		using WindowHandle = ::HWND;
		using ChildID = MenuHandle;

		using CreateStruct = ::CREATESTRUCT;

	} // ::wawl::wnd
} // ::wawl<|endoftext|>