<commit_before>#pragma once

#include <functional>
#include <stdexcept>
#include <boost/algorithm/string.hpp>
#include <boost/lexical_cast.hpp>
#include <boost/regex.hpp>
#include <boost/optional.hpp>

#include <supermarx/scraper/html_parser.hpp>
#include <supermarx/scraper/html_watcher.hpp>
#include <supermarx/scraper/html_recorder.hpp>
#include <supermarx/scraper/util.hpp>

namespace supermarx
{
	class product_parser : public html_parser::default_handler
	{
	public:
		typedef std::function<void(const message::product_base&, boost::optional<std::string>, datetime, confidence, std::vector<std::string>)> product_callback_t;

	private:
		enum state_e {
			S_INIT,
			S_ENABLED,
			S_PRODUCT_LIST,
			S_PRODUCT,
			S_PRODUCT_IMAGE
		};

		product_callback_t product_callback;

		boost::optional<html_recorder> rec;
		html_watcher_collection wc;

		state_e state;

		struct product_proto
		{
			std::string identifier, name;
			boost::optional<std::string> image_uri;
			boost::optional<size_t> price;
			boost::optional<std::string> caliber;
			boost::optional<std::string> discount;

			confidence conf = confidence::NEUTRAL;
			std::vector<std::string> problems;
		};

		product_proto current_p;

		static date first_monday(date d)
		{
			while(d.day_of_week() != weekday::Monday)
				d += boost::gregorian::date_duration(1);

			return d;
		}

		void report_problem_understanding(std::string const& field, std::string const& value)
		{
			std::stringstream sstr;
			sstr << "Unclear '" << field << "' with value '" << value << "'";

			std::cerr << "problem: " << sstr.str() << std::endl;
			current_p.problems.emplace_back(sstr.str());
		}

		void interpret_caliber(std::string unit, uint64_t& volume, measure& volume_measure)
		{
			boost::smatch what;
			static const boost::regex match_prefix("Per (?:[a-z]+ )?(.+)");
			static const boost::regex match_measure("([0-9]+(?:\\.[0-9]+)?)[\\s]+(.+)");

			if(boost::regex_match(unit, what, match_prefix))
				unit = what[1];

			boost::erase_all(unit, ".");

			if(boost::regex_match(unit, what, match_measure))
			{
				std::string measure_type = what[2];

				const static std::set<std::string> generic_types({{
					"stuk", "stuks",
					"pak", "bus", "rol", "vel", "doos", "blik", "paar", "fles",
					"zak", "bord"
				}});

				if(generic_types.find(measure_type) != generic_types.end())
				{
					volume = boost::lexical_cast<float>(what[1]);
					volume_measure = measure::UNITS;
				}
				else if(measure_type == "mg")
				{
					volume = boost::lexical_cast<float>(what[1]);
					volume_measure = measure::MILLIGRAMS;
				}
				else if(measure_type == "g" || measure_type == "gr" || measure_type == "gram" || measure_type == "milligram")
				{
					volume = boost::lexical_cast<float>(what[1])*1000.0;
					volume_measure = measure::MILLIGRAMS;
				}
				else if(measure_type == "kg" || measure_type == "kilo" || measure_type == "kilogram")
				{
					volume = boost::lexical_cast<float>(what[1])*1000000.0;
					volume_measure = measure::MILLIGRAMS;
				}
				else if(measure_type == "ml" || measure_type == "milliliter")
				{
					volume = boost::lexical_cast<float>(what[1]);
					volume_measure = measure::MILLILITRES;
				}
				else if(measure_type == "cl" || measure_type == "centilliter")
				{
					volume = boost::lexical_cast<float>(what[1])*10.0;
					volume_measure = measure::MILLILITRES;
				}
				else if(measure_type == "l" || measure_type == "lt" || measure_type == "liter" || measure_type == "litre")
				{
					volume = boost::lexical_cast<float>(what[1])*1000.0;
					volume_measure = measure::MILLILITRES;
				}
				else if(measure_type == "meter")
				{
					volume = boost::lexical_cast<float>(what[1])*1000.0;
					volume_measure = measure::MILLIMETRES;
				}
				else
				{
					report_problem_understanding("measure_type", measure_type);
					current_p.conf = confidence::LOW;
					return;
				}
			}
			else
			{
				report_problem_understanding("unit", unit);
				current_p.conf = confidence::LOW;
			}
		}

		void interpret_discount(std::string discount_str, uint64_t& price, uint64_t& discount_amount)
		{
			static const boost::regex match_percent_discount("([0-9]+)%KORTING");
			static const boost::regex match_new_price("([0-9]+)");
			boost::smatch what;

			if(boost::regex_match(discount_str, what, match_percent_discount))
			{
				price *= 1.0 - boost::lexical_cast<float>(what[1])/100.0;
			}
			else if(boost::regex_match(discount_str, what, match_new_price))
			{
				price = boost::lexical_cast<uint64_t>(what[1]);
			}
			else if(discount_str == "2eHALVEPRIJS")
			{
				discount_amount = 2;
				price = price * 0.75;
			}
			else if(discount_str == "1+1GRATIS" || discount_str == "1+1")
			{
				discount_amount = 2;
				price = price * 0.5;
			}
			else if(discount_str == "1+2GRATIS")
			{
				discount_amount = 3;
				price = price / 3;
			}
			else if(discount_str == "2+1GRATIS")
			{
				discount_amount = 3;
				price = (price * 2) / 3;
			}
			else if(discount_str == "3+1GRATIS")
			{
				discount_amount = 4;
				price = price * 0.75;
			}
			else
			{
				report_problem_understanding("discount_str", discount_str);
				current_p.conf = confidence::LOW;
			}
		}

		void deliver_product()
		{
			uint64_t volume = 1;
			measure volume_measure = measure::UNITS;

			if(current_p.caliber)
				interpret_caliber(*current_p.caliber, volume, volume_measure);

			if(!current_p.price)
			{
				std::cerr << "Price not set for " << current_p.name << std::endl;
				return;
			}

			uint64_t orig_price = *current_p.price;
			uint64_t price = orig_price;

			uint64_t discount_amount = 1;

			if(current_p.discount)
				interpret_discount(*current_p.discount, price, discount_amount);

			product_callback(
				message::product_base{
					current_p.identifier,
					current_p.name,
					volume,
					volume_measure,
					orig_price,
					price,
					discount_amount,
					datetime_now(),
					{} // TODO (tags)
				},
				current_p.image_uri,
				datetime_now(),
				current_p.conf,
				current_p.problems
			);
		}

	public:
		product_parser(product_callback_t product_callback_)
		: product_callback(product_callback_)
		, rec()
		, wc()
		, state(S_INIT)
		, current_p()
		{}

		template<typename T>
		void parse(T source)
		{
			html_parser::parse(source, *this);
		}

		virtual void startElement(const std::string& /* namespaceURI */, const std::string& /* localName */, const std::string& qName, const AttributesT& atts)
		{
			if(rec)
				rec.get().startElement();

			wc.startElement();

			const std::string att_class = atts.getValue("class");

			switch(state)
			{
			case S_INIT:
				if(util::contains_attr("list-filters-and-pagination", att_class)) // Core product listing with pagination
					state = S_ENABLED;
			break;
			case S_ENABLED:
				if(qName == "ul" && util::contains_attr("ish-productList", att_class))
				{
					state = S_PRODUCT_LIST;
					wc.add([&]() {
						state = S_ENABLED;
					});
				}
			break;
			case S_PRODUCT_LIST:
				if(qName == "div" && util::contains_attr("ish-productTileKlik", att_class))
				{
					//Reset product
					current_p = product_proto();

					state = S_PRODUCT;
					wc.add([&]() {
						state = S_PRODUCT_LIST;

						deliver_product();
					});
				}
			break;
			case S_PRODUCT:
				if(atts.getValue("data-attr-sku") != "")
					current_p.identifier = atts.getValue("data-attr-sku");

				if(qName == "div" && atts.getValue("data-dynamic-block-id") == "PRODUCTTILE-PRODUCTTITLE")
				{
					rec = html_recorder(
						[&](std::string ch) {
							current_p.name = util::sanitize(ch);
						});
				}
				else if(util::contains_attr("ish-productTile-withCartButton-photo", att_class))
				{
					state = S_PRODUCT_IMAGE;
					wc.add([&]() {
						state = S_PRODUCT;
					});
				}
				if(util::contains_attr("shape-tekst", att_class))
				{
					rec = html_recorder(
						[&](std::string ch) {
							current_p.discount = util::sanitize(ch);
						});
				}
				else if(util::contains_attr("product-tile-priceContainer", att_class))
				{
					rec = html_recorder(
						[&](std::string ch) {
							static const boost::regex match_price("([0-9]+) ([0-9]+)");
							boost::smatch what;

							std::string ch_san(util::sanitize(ch));
							if(!boost::regex_match(ch_san, what, match_price))
								throw std::runtime_error("Malformed price '" + ch_san + "'");

							current_p.price = boost::lexical_cast<size_t>(what[1]) * 100 + boost::lexical_cast<size_t>(what[2]);
						});
				}
				else if(util::contains_attr("content-weight-or-per-piece", att_class))
				{
					rec = html_recorder(
						[&](std::string ch) {
							current_p.caliber = util::sanitize(ch);
						});
				}
			break;
			case S_PRODUCT_IMAGE:
				if(qName == "img")
				{
					static const boost::regex match_img("(.*)/M/(.*)");
					boost::smatch what;

					std::string src(atts.getValue("data-src"));
					if(src == "") // No image available
						break;

					if(!boost::regex_match(src, what, match_img))
						throw std::runtime_error("Malformed image uri '" + src + "'");

					current_p.image_uri = what[1] + "/L/" + what[2];
				}
			break;
			}
		}

		virtual void characters(const std::string& ch)
		{
			if(rec)
				rec.get().characters(ch);
		}

		virtual void endElement(const std::string& /* namespaceURI */, const std::string& /* localName */, const std::string& /* qName */)
		{
			if(rec && rec.get().endElement())
				rec = boost::none;

			wc.endElement();
		}
	};
}
<commit_msg>Added missing discount strings<commit_after>#pragma once

#include <functional>
#include <stdexcept>
#include <boost/algorithm/string.hpp>
#include <boost/lexical_cast.hpp>
#include <boost/regex.hpp>
#include <boost/optional.hpp>

#include <supermarx/scraper/html_parser.hpp>
#include <supermarx/scraper/html_watcher.hpp>
#include <supermarx/scraper/html_recorder.hpp>
#include <supermarx/scraper/util.hpp>

namespace supermarx
{
	class product_parser : public html_parser::default_handler
	{
	public:
		typedef std::function<void(const message::product_base&, boost::optional<std::string>, datetime, confidence, std::vector<std::string>)> product_callback_t;

	private:
		enum state_e {
			S_INIT,
			S_ENABLED,
			S_PRODUCT_LIST,
			S_PRODUCT,
			S_PRODUCT_IMAGE
		};

		product_callback_t product_callback;

		boost::optional<html_recorder> rec;
		html_watcher_collection wc;

		state_e state;

		struct product_proto
		{
			std::string identifier, name;
			boost::optional<std::string> image_uri;
			boost::optional<size_t> price;
			boost::optional<std::string> caliber;
			boost::optional<std::string> discount;

			confidence conf = confidence::NEUTRAL;
			std::vector<std::string> problems;
		};

		product_proto current_p;

		static date first_monday(date d)
		{
			while(d.day_of_week() != weekday::Monday)
				d += boost::gregorian::date_duration(1);

			return d;
		}

		void report_problem_understanding(std::string const& field, std::string const& value)
		{
			std::stringstream sstr;
			sstr << "Unclear '" << field << "' with value '" << value << "'";

			std::cerr << "problem: " << sstr.str() << std::endl;
			current_p.problems.emplace_back(sstr.str());
		}

		void interpret_caliber(std::string unit, uint64_t& volume, measure& volume_measure)
		{
			boost::smatch what;
			static const boost::regex match_prefix("Per (?:[a-z]+ )?(.+)");
			static const boost::regex match_measure("([0-9]+(?:\\.[0-9]+)?)[\\s]+(.+)");

			if(boost::regex_match(unit, what, match_prefix))
				unit = what[1];

			boost::erase_all(unit, ".");

			if(boost::regex_match(unit, what, match_measure))
			{
				std::string measure_type = what[2];

				const static std::set<std::string> generic_types({{
					"stuk", "stuks",
					"pak", "bus", "rol", "vel", "doos", "blik", "paar", "fles",
					"zak", "bord"
				}});

				if(generic_types.find(measure_type) != generic_types.end())
				{
					volume = boost::lexical_cast<float>(what[1]);
					volume_measure = measure::UNITS;
				}
				else if(measure_type == "mg")
				{
					volume = boost::lexical_cast<float>(what[1]);
					volume_measure = measure::MILLIGRAMS;
				}
				else if(measure_type == "g" || measure_type == "gr" || measure_type == "gram" || measure_type == "milligram")
				{
					volume = boost::lexical_cast<float>(what[1])*1000.0;
					volume_measure = measure::MILLIGRAMS;
				}
				else if(measure_type == "kg" || measure_type == "kilo" || measure_type == "kilogram")
				{
					volume = boost::lexical_cast<float>(what[1])*1000000.0;
					volume_measure = measure::MILLIGRAMS;
				}
				else if(measure_type == "ml" || measure_type == "milliliter")
				{
					volume = boost::lexical_cast<float>(what[1]);
					volume_measure = measure::MILLILITRES;
				}
				else if(measure_type == "cl" || measure_type == "centilliter")
				{
					volume = boost::lexical_cast<float>(what[1])*10.0;
					volume_measure = measure::MILLILITRES;
				}
				else if(measure_type == "l" || measure_type == "lt" || measure_type == "liter" || measure_type == "litre")
				{
					volume = boost::lexical_cast<float>(what[1])*1000.0;
					volume_measure = measure::MILLILITRES;
				}
				else if(measure_type == "meter")
				{
					volume = boost::lexical_cast<float>(what[1])*1000.0;
					volume_measure = measure::MILLIMETRES;
				}
				else
				{
					report_problem_understanding("measure_type", measure_type);
					current_p.conf = confidence::LOW;
					return;
				}
			}
			else
			{
				report_problem_understanding("unit", unit);
				current_p.conf = confidence::LOW;
			}
		}

		void interpret_discount(std::string discount_str, uint64_t& price, uint64_t& discount_amount)
		{
			static const boost::regex match_percent_discount("([0-9]+)%KORTING");
			static const boost::regex match_new_price("([0-9]+)");
			boost::smatch what;

			if(boost::regex_match(discount_str, what, match_percent_discount))
			{
				price *= 1.0 - boost::lexical_cast<float>(what[1])/100.0;
			}
			else if(boost::regex_match(discount_str, what, match_new_price))
			{
				price = boost::lexical_cast<uint64_t>(what[1]);
			}
			else if(discount_str == "2eHALVEPRIJS")
			{
				discount_amount = 2;
				price = price * 0.75;
			}
			else if(discount_str == "1+1GRATIS" || discount_str == "1+1")
			{
				discount_amount = 2;
				price = price * 0.5;
			}
			else if(discount_str == "1+2GRATIS" || discount_str == "1+2")
			{
				discount_amount = 3;
				price = price / 3;
			}
			else if(discount_str == "2+1GRATIS" || discount_str == "2+1")
			{
				discount_amount = 3;
				price = (price * 2) / 3;
			}
			else if(discount_str == "3+1GRATIS" || discount_str == "3+1")
			{
				discount_amount = 4;
				price = price * 0.75;
			}
			else
			{
				report_problem_understanding("discount_str", discount_str);
				current_p.conf = confidence::LOW;
			}
		}

		void deliver_product()
		{
			uint64_t volume = 1;
			measure volume_measure = measure::UNITS;

			if(current_p.caliber)
				interpret_caliber(*current_p.caliber, volume, volume_measure);

			if(!current_p.price)
			{
				std::cerr << "Price not set for " << current_p.name << std::endl;
				return;
			}

			uint64_t orig_price = *current_p.price;
			uint64_t price = orig_price;

			uint64_t discount_amount = 1;

			if(current_p.discount)
				interpret_discount(*current_p.discount, price, discount_amount);

			product_callback(
				message::product_base{
					current_p.identifier,
					current_p.name,
					volume,
					volume_measure,
					orig_price,
					price,
					discount_amount,
					datetime_now(),
					{} // TODO (tags)
				},
				current_p.image_uri,
				datetime_now(),
				current_p.conf,
				current_p.problems
			);
		}

	public:
		product_parser(product_callback_t product_callback_)
		: product_callback(product_callback_)
		, rec()
		, wc()
		, state(S_INIT)
		, current_p()
		{}

		template<typename T>
		void parse(T source)
		{
			html_parser::parse(source, *this);
		}

		virtual void startElement(const std::string& /* namespaceURI */, const std::string& /* localName */, const std::string& qName, const AttributesT& atts)
		{
			if(rec)
				rec.get().startElement();

			wc.startElement();

			const std::string att_class = atts.getValue("class");

			switch(state)
			{
			case S_INIT:
				if(util::contains_attr("list-filters-and-pagination", att_class)) // Core product listing with pagination
					state = S_ENABLED;
			break;
			case S_ENABLED:
				if(qName == "ul" && util::contains_attr("ish-productList", att_class))
				{
					state = S_PRODUCT_LIST;
					wc.add([&]() {
						state = S_ENABLED;
					});
				}
			break;
			case S_PRODUCT_LIST:
				if(qName == "div" && util::contains_attr("ish-productTileKlik", att_class))
				{
					//Reset product
					current_p = product_proto();

					state = S_PRODUCT;
					wc.add([&]() {
						state = S_PRODUCT_LIST;

						deliver_product();
					});
				}
			break;
			case S_PRODUCT:
				if(atts.getValue("data-attr-sku") != "")
					current_p.identifier = atts.getValue("data-attr-sku");

				if(qName == "div" && atts.getValue("data-dynamic-block-id") == "PRODUCTTILE-PRODUCTTITLE")
				{
					rec = html_recorder(
						[&](std::string ch) {
							current_p.name = util::sanitize(ch);
						});
				}
				else if(util::contains_attr("ish-productTile-withCartButton-photo", att_class))
				{
					state = S_PRODUCT_IMAGE;
					wc.add([&]() {
						state = S_PRODUCT;
					});
				}
				if(util::contains_attr("shape-tekst", att_class))
				{
					rec = html_recorder(
						[&](std::string ch) {
							current_p.discount = util::sanitize(ch);
						});
				}
				else if(util::contains_attr("product-tile-priceContainer", att_class))
				{
					rec = html_recorder(
						[&](std::string ch) {
							static const boost::regex match_price("([0-9]+) ([0-9]+)");
							boost::smatch what;

							std::string ch_san(util::sanitize(ch));
							if(!boost::regex_match(ch_san, what, match_price))
								throw std::runtime_error("Malformed price '" + ch_san + "'");

							current_p.price = boost::lexical_cast<size_t>(what[1]) * 100 + boost::lexical_cast<size_t>(what[2]);
						});
				}
				else if(util::contains_attr("content-weight-or-per-piece", att_class))
				{
					rec = html_recorder(
						[&](std::string ch) {
							current_p.caliber = util::sanitize(ch);
						});
				}
			break;
			case S_PRODUCT_IMAGE:
				if(qName == "img")
				{
					static const boost::regex match_img("(.*)/M/(.*)");
					boost::smatch what;

					std::string src(atts.getValue("data-src"));
					if(src == "") // No image available
						break;

					if(!boost::regex_match(src, what, match_img))
						throw std::runtime_error("Malformed image uri '" + src + "'");

					current_p.image_uri = what[1] + "/L/" + what[2];
				}
			break;
			}
		}

		virtual void characters(const std::string& ch)
		{
			if(rec)
				rec.get().characters(ch);
		}

		virtual void endElement(const std::string& /* namespaceURI */, const std::string& /* localName */, const std::string& /* qName */)
		{
			if(rec && rec.get().endElement())
				rec = boost::none;

			wc.endElement();
		}
	};
}
<|endoftext|>


<commit_before>/*
 * Software License Agreement (BSD License)
 *
 *  Copyright (c) 2010, Willow Garage, Inc.
 *  All rights reserved.
 *
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions
 *  are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *   * Redistributions in binary form must reproduce the above
 *     copyright notice, this list of conditions and the following
 *     disclaimer in the documentation and/or other materials provided
 *     with the distribution.
 *   * Neither the name of Willow Garage, Inc. 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.
 *
 * $Id: pcd_viewer.cpp 35932 2011-02-10 03:55:03Z rusu $
 *
 */
// PCL
#include <Eigen/Geometry>
#include <pcl/common/common.h>
#include <pcl/io/pcd_io.h>
#include <pcl/io/kinect_grabber.h>
#include <cfloat>
#include <pcl/visualization/point_cloud_handlers.h>
#include <pcl/visualization/pcl_visualizer.h>
#include <pcl/visualization/histogram_visualizer.h>
#include <pcl/terminal_tools/print.h>
#include <pcl/terminal_tools/parse.h>
#include <pcl/terminal_tools/time.h>

using terminal_tools::print_color;
using terminal_tools::print_error;
using terminal_tools::print_error;
using terminal_tools::print_warn;
using terminal_tools::print_info;
using terminal_tools::print_debug;
using terminal_tools::print_value;
using terminal_tools::print_highlight;
using terminal_tools::TT_BRIGHT;
using terminal_tools::TT_RED;
using terminal_tools::TT_GREEN;
using terminal_tools::TT_BLUE;

typedef pcl_visualization::PointCloudColorHandler<pcl::PointCloud<pcl::PointXYZ> > ColorHandler;
typedef ColorHandler::Ptr ColorHandlerPtr;
typedef ColorHandler::ConstPtr ColorHandlerConstPtr;

typedef pcl_visualization::PointCloudGeometryHandler<pcl::PointCloud<pcl::PointXYZ> > GeometryHandler;
typedef GeometryHandler::Ptr GeometryHandlerPtr;
typedef GeometryHandler::ConstPtr GeometryHandlerConstPtr;
boost::mutex mutex_;

#define NORMALS_SCALE 0.01
#define PC_SCALE 0.001

void
  printHelp (int argc, char **argv)
{
  print_error ("Syntax is: %s <file_name 1..N>.pcd <options>\n", argv[0]);
  print_info ("  where options are:\n");
  print_info ("                     -bc r,g,b                = background color\n");
  print_info ("                     -fc r,g,b                = foreground color\n");
  print_info ("                     -ps X                    = point size ("); print_value ("1..64"); print_info (") \n");
  print_info ("                     -opaque X                = rendered point cloud opacity ("); print_value ("0..1"); print_info (")\n");

  print_info ("                     -ax "); print_value ("n"); print_info ("                    = enable on-screen display of ");
  print_color (stdout, TT_BRIGHT, TT_RED, "X"); print_color (stdout, TT_BRIGHT, TT_GREEN, "Y"); print_color (stdout, TT_BRIGHT, TT_BLUE, "Z");
  print_info (" axes and scale them to "); print_value ("n\n");
  print_info ("                     -ax_pos X,Y,Z            = if axes are enabled, set their X,Y,Z position in space (default "); print_value ("0,0,0"); print_info (")\n");

  print_info ("\n");
  print_info ("                     -cam (*)                 = use given camera settings as initial view\n");
  print_info (stderr, " (*) [Clipping Range / Focal Point / Position / ViewUp / Distance / Window Size / Window Pos] or use a <filename.cam> that contains the same information.\n");

  print_info ("\n");
  print_info ("                     -multiview 0/1           = enable/disable auto-multi viewport rendering (default "); print_value ("disabled"); print_info (")\n");
  print_info ("\n");

  print_info ("\n");
  print_info ("                     -normals 0/X             = disable/enable the display of every Xth point's surface normal as lines (default "); print_value ("disabled"); print_info (")\n");
  print_info ("                     -normals_scale X         = resize the normal unit vector size to X (default "); print_value ("0.02"); print_info (")\n");
  print_info ("\n");
  print_info ("                     -pc 0/X                  = disable/enable the display of every Xth point's principal curvatures as lines (default "); print_value ("disabled"); print_info (")\n");
  print_info ("                     -pc_scale X              = resize the principal curvatures vectors size to X (default "); print_value ("0.02"); print_info (")\n");
  print_info ("\n");

  print_info ("\n(Note: for multiple .pcd files, provide multiple -{fc,ps,opaque} parameters; they will be automatically assigned to the right file)\n");
}

// Create the PCLVisualizer object
boost::shared_ptr<pcl_visualization::PCLVisualizer> p;
ColorHandlerPtr color_handler;
GeometryHandlerPtr geometry_handler;
std::vector<double> fcolor_r, fcolor_b, fcolor_g;
bool fcolorparam = false;

struct EventHelper
{
  void cloud_cb (const pcl::PointCloud<pcl::PointXYZRGB>::ConstPtr &cloud)
  {
      std::cout << __PRETTY_FUNCTION__ << " " << cloud->width << std::endl;
    // Add the dataset with a XYZ and a random handler
  //  geometry_handler.reset (new pcl_visualization::PointCloudGeometryHandlerXYZ<pcl::PointCloud<pcl::PointXYZRGB> > (*cloud));

    //// If color was given, ues that
    //if (fcolorparam)
    //  color_handler.reset (new pcl_visualization::PointCloudColorHandlerCustom<pcl::PointCloud<pcl::PointXYZRGB> > (cloud, fcolor_r, fcolor_g, fcolor_b));
    //else
    //  color_handler.reset (new pcl_visualization::PointCloudColorHandlerRandom<pcl::PointCloud<pcl::PointXYZRGB> > (cloud));

    // Add the cloud to the renderer

    boost::mutex::scoped_lock (mutex_);
    if (!cloud)
      return;
    p->removePointCloud ("KinectCloud");
    p->addPointCloud (*cloud, "KinectCloud");
  }
};

/* ---[ */
int
  main (int argc, char** argv)
{
  srand (time (0));

  if (argc > 2)
    for (unsigned int i = 1; i < argc; i++)
      if (std::string(argv[i]) == "-h")
      {
        printHelp (argc, argv);
        return (-1);
      }

  // Command line parsing
  double bcolor[3] = {0, 0, 0};
  terminal_tools::parse_3x_arguments (argc, argv, "-bc", bcolor[0], bcolor[1], bcolor[2]);

  fcolorparam = terminal_tools::parse_multiple_3x_arguments (argc, argv, "-fc", fcolor_r, fcolor_g, fcolor_b);

  int psize = 0;
  terminal_tools::parse_argument (argc, argv, "-ps", psize);

  double opaque;
  terminal_tools::parse_argument (argc, argv, "-opaque", opaque);

  p.reset (new pcl_visualization::PCLVisualizer (argc, argv, "PCD viewer"));

//  // Change the cloud rendered point size
//  if (psize > 0)
//    p->setPointCloudRenderingProperties (pcl_visualization::PCL_VISUALIZER_POINT_SIZE, psize, "KinectCloud");
//
//  // Change the cloud rendered opacity
//  if (opaque >= 0)
//    p->setPointCloudRenderingProperties (pcl_visualization::PCL_VISUALIZER_OPACITY, opaque, "KinectCloud");

  p->setBackgroundColor (bcolor[0], bcolor[1], bcolor[2]);

  pcl::Grabber* interface = new pcl::OpenNIGrabber();

  //boost::signals2::connection c = interface->registerCallback (boost::bind (&bla::blatestpointcloudrgb, *this, _1));
  //boost::function<void (boost::shared_ptr<pcl::PointCloud<pcl::PointXYZRGB> >)> f = boost::bind (&bla::blatestpointcloudrgb, this, _1);
  //boost::signals2::connection c =
  //  interface->registerCallback <void(boost::shared_ptr<pcl::PointCloud<pcl::PointXYZRGB> >)> (boost::bind (&bla::blatestpointcloudrgb, *this, _1).);

  // Read axes settings
  double axes  = 0.0;
  terminal_tools::parse_argument (argc, argv, "-ax", axes);
  if (axes != 0.0 && p)
  {
    double ax_x = 0.0, ax_y = 0.0, ax_z = 0.0;
    terminal_tools::parse_3x_arguments (argc, argv, "-ax_pos", ax_x, ax_y, ax_z, false);
    // Draw XYZ axes if command-line enabled
    p->addCoordinateSystem (axes, ax_x, ax_y, ax_z);
  }

  EventHelper h;
  boost::function<void(const pcl::PointCloud<pcl::PointXYZRGB>::ConstPtr&)> f = boost::bind(&EventHelper::cloud_cb, &h, _1);
  boost::signals2::connection c1 = interface->registerCallback (f);

  interface->start ();
  while (true)
  {
    usleep (10000);
    {
      boost::mutex::scoped_lock (mutex_);
      p->spinOnce ();
      if (p->wasStopped ())
        break;
    }

  }

  interface->stop ();
}
/* ]--- */
<commit_msg>scoped_lock must be instantiated. Credit goes to Vincent for finding this error<commit_after>/*
 * Software License Agreement (BSD License)
 *
 *  Copyright (c) 2010, Willow Garage, Inc.
 *  All rights reserved.
 *
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions
 *  are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *   * Redistributions in binary form must reproduce the above
 *     copyright notice, this list of conditions and the following
 *     disclaimer in the documentation and/or other materials provided
 *     with the distribution.
 *   * Neither the name of Willow Garage, Inc. 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.
 *
 * $Id: pcd_viewer.cpp 35932 2011-02-10 03:55:03Z rusu $
 *
 */
// PCL
#include <Eigen/Geometry>
#include <pcl/common/common.h>
#include <pcl/io/pcd_io.h>
#include <pcl/io/kinect_grabber.h>
#include <cfloat>
#include <pcl/visualization/point_cloud_handlers.h>
#include <pcl/visualization/pcl_visualizer.h>
#include <pcl/visualization/histogram_visualizer.h>
#include <pcl/terminal_tools/print.h>
#include <pcl/terminal_tools/parse.h>
#include <pcl/terminal_tools/time.h>

using terminal_tools::print_color;
using terminal_tools::print_error;
using terminal_tools::print_error;
using terminal_tools::print_warn;
using terminal_tools::print_info;
using terminal_tools::print_debug;
using terminal_tools::print_value;
using terminal_tools::print_highlight;
using terminal_tools::TT_BRIGHT;
using terminal_tools::TT_RED;
using terminal_tools::TT_GREEN;
using terminal_tools::TT_BLUE;

typedef pcl_visualization::PointCloudColorHandler<pcl::PointCloud<pcl::PointXYZ> > ColorHandler;
typedef ColorHandler::Ptr ColorHandlerPtr;
typedef ColorHandler::ConstPtr ColorHandlerConstPtr;

typedef pcl_visualization::PointCloudGeometryHandler<pcl::PointCloud<pcl::PointXYZ> > GeometryHandler;
typedef GeometryHandler::Ptr GeometryHandlerPtr;
typedef GeometryHandler::ConstPtr GeometryHandlerConstPtr;
boost::mutex mutex_;

#define NORMALS_SCALE 0.01
#define PC_SCALE 0.001

void
  printHelp (int argc, char **argv)
{
  print_error ("Syntax is: %s <file_name 1..N>.pcd <options>\n", argv[0]);
  print_info ("  where options are:\n");
  print_info ("                     -bc r,g,b                = background color\n");
  print_info ("                     -fc r,g,b                = foreground color\n");
  print_info ("                     -ps X                    = point size ("); print_value ("1..64"); print_info (") \n");
  print_info ("                     -opaque X                = rendered point cloud opacity ("); print_value ("0..1"); print_info (")\n");

  print_info ("                     -ax "); print_value ("n"); print_info ("                    = enable on-screen display of ");
  print_color (stdout, TT_BRIGHT, TT_RED, "X"); print_color (stdout, TT_BRIGHT, TT_GREEN, "Y"); print_color (stdout, TT_BRIGHT, TT_BLUE, "Z");
  print_info (" axes and scale them to "); print_value ("n\n");
  print_info ("                     -ax_pos X,Y,Z            = if axes are enabled, set their X,Y,Z position in space (default "); print_value ("0,0,0"); print_info (")\n");

  print_info ("\n");
  print_info ("                     -cam (*)                 = use given camera settings as initial view\n");
  print_info (stderr, " (*) [Clipping Range / Focal Point / Position / ViewUp / Distance / Window Size / Window Pos] or use a <filename.cam> that contains the same information.\n");

  print_info ("\n");
  print_info ("                     -multiview 0/1           = enable/disable auto-multi viewport rendering (default "); print_value ("disabled"); print_info (")\n");
  print_info ("\n");

  print_info ("\n");
  print_info ("                     -normals 0/X             = disable/enable the display of every Xth point's surface normal as lines (default "); print_value ("disabled"); print_info (")\n");
  print_info ("                     -normals_scale X         = resize the normal unit vector size to X (default "); print_value ("0.02"); print_info (")\n");
  print_info ("\n");
  print_info ("                     -pc 0/X                  = disable/enable the display of every Xth point's principal curvatures as lines (default "); print_value ("disabled"); print_info (")\n");
  print_info ("                     -pc_scale X              = resize the principal curvatures vectors size to X (default "); print_value ("0.02"); print_info (")\n");
  print_info ("\n");

  print_info ("\n(Note: for multiple .pcd files, provide multiple -{fc,ps,opaque} parameters; they will be automatically assigned to the right file)\n");
}

// Create the PCLVisualizer object
boost::shared_ptr<pcl_visualization::PCLVisualizer> p;
ColorHandlerPtr color_handler;
GeometryHandlerPtr geometry_handler;
std::vector<double> fcolor_r, fcolor_b, fcolor_g;
bool fcolorparam = false;

struct EventHelper
{
  void cloud_cb (const pcl::PointCloud<pcl::PointXYZRGB>::ConstPtr &cloud)
  {
      std::cout << __PRETTY_FUNCTION__ << " " << cloud->width << std::endl;
    // Add the dataset with a XYZ and a random handler
  //  geometry_handler.reset (new pcl_visualization::PointCloudGeometryHandlerXYZ<pcl::PointCloud<pcl::PointXYZRGB> > (*cloud));

    //// If color was given, ues that
    //if (fcolorparam)
    //  color_handler.reset (new pcl_visualization::PointCloudColorHandlerCustom<pcl::PointCloud<pcl::PointXYZRGB> > (cloud, fcolor_r, fcolor_g, fcolor_b));
    //else
    //  color_handler.reset (new pcl_visualization::PointCloudColorHandlerRandom<pcl::PointCloud<pcl::PointXYZRGB> > (cloud));

    // Add the cloud to the renderer

    boost::mutex::scoped_lock lock(mutex_);
    if (!cloud)
      return;
    p->removePointCloud ("KinectCloud");
    p->addPointCloud (*cloud, "KinectCloud");
  }
};

/* ---[ */
int
  main (int argc, char** argv)
{
  srand (time (0));

  if (argc > 2)
    for (unsigned int i = 1; i < argc; i++)
      if (std::string(argv[i]) == "-h")
      {
        printHelp (argc, argv);
        return (-1);
      }

  // Command line parsing
  double bcolor[3] = {0, 0, 0};
  terminal_tools::parse_3x_arguments (argc, argv, "-bc", bcolor[0], bcolor[1], bcolor[2]);

  fcolorparam = terminal_tools::parse_multiple_3x_arguments (argc, argv, "-fc", fcolor_r, fcolor_g, fcolor_b);

  int psize = 0;
  terminal_tools::parse_argument (argc, argv, "-ps", psize);

  double opaque;
  terminal_tools::parse_argument (argc, argv, "-opaque", opaque);

  p.reset (new pcl_visualization::PCLVisualizer (argc, argv, "PCD viewer"));

//  // Change the cloud rendered point size
//  if (psize > 0)
//    p->setPointCloudRenderingProperties (pcl_visualization::PCL_VISUALIZER_POINT_SIZE, psize, "KinectCloud");
//
//  // Change the cloud rendered opacity
//  if (opaque >= 0)
//    p->setPointCloudRenderingProperties (pcl_visualization::PCL_VISUALIZER_OPACITY, opaque, "KinectCloud");

  p->setBackgroundColor (bcolor[0], bcolor[1], bcolor[2]);

  pcl::Grabber* interface = new pcl::OpenNIGrabber();

  //boost::signals2::connection c = interface->registerCallback (boost::bind (&bla::blatestpointcloudrgb, *this, _1));
  //boost::function<void (boost::shared_ptr<pcl::PointCloud<pcl::PointXYZRGB> >)> f = boost::bind (&bla::blatestpointcloudrgb, this, _1);
  //boost::signals2::connection c =
  //  interface->registerCallback <void(boost::shared_ptr<pcl::PointCloud<pcl::PointXYZRGB> >)> (boost::bind (&bla::blatestpointcloudrgb, *this, _1).);

  // Read axes settings
  double axes  = 0.0;
  terminal_tools::parse_argument (argc, argv, "-ax", axes);
  if (axes != 0.0 && p)
  {
    double ax_x = 0.0, ax_y = 0.0, ax_z = 0.0;
    terminal_tools::parse_3x_arguments (argc, argv, "-ax_pos", ax_x, ax_y, ax_z, false);
    // Draw XYZ axes if command-line enabled
    p->addCoordinateSystem (axes, ax_x, ax_y, ax_z);
  }

  EventHelper h;
  boost::function<void(const pcl::PointCloud<pcl::PointXYZRGB>::ConstPtr&)> f = boost::bind(&EventHelper::cloud_cb, &h, _1);
  boost::signals2::connection c1 = interface->registerCallback (f);

  interface->start ();
  while (true)
  {
    usleep (10000);
    {
      boost::mutex::scoped_lock lock(mutex_);
      p->spinOnce ();
      if (p->wasStopped ())
        break;
    }

  }

  interface->stop ();
}
/* ]--- */
<|endoftext|>


<commit_before>/*****************************************************************************
 * actions_manager.cpp : Controller for the main interface
 ****************************************************************************
 * Copyright (C) 2006-2008 the VideoLAN team
 * $Id$
 *
 * Authors: Jean-Baptiste Kempf <jb@videolan.org>
 *          Ilkka Ollakka <ileoo@videolan.org>
 *
 * This program 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 2 of the License, or
 * ( at your option ) any later version.
 *
 * This program 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 this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
 *****************************************************************************/

#ifdef HAVE_CONFIG_H
# include "config.h"
#endif

#include <vlc_vout.h>
#include <vlc_aout_intf.h>
#include <vlc_keys.h>

#include "actions_manager.hpp"
#include "dialogs_provider.hpp" /* Opening Dialogs */
#include "input_manager.hpp"
#include "main_interface.hpp" /* Show playlist */
#include "components/controller.hpp" /* Toggle FSC controller width */

ActionsManager * ActionsManager::instance = NULL;

ActionsManager::ActionsManager( intf_thread_t * _p_i, QObject *_parent )
               : QObject( _parent )
{
    p_intf = _p_i;
}

ActionsManager::~ActionsManager(){}

void ActionsManager::doAction( int id_action )
{
    switch( id_action )
    {
        case PLAY_ACTION:
            play(); break;
        case STOP_ACTION:
            THEMIM->stop(); break;
        case OPEN_ACTION:
            THEDP->openDialog(); break;
        case PREVIOUS_ACTION:
            THEMIM->prev(); break;
        case NEXT_ACTION:
            THEMIM->next(); break;
        case SLOWER_ACTION:
            THEMIM->getIM()->slower(); break;
        case FASTER_ACTION:
            THEMIM->getIM()->faster(); break;
        case FULLSCREEN_ACTION:
            fullscreen(); break;
        case EXTENDED_ACTION:
            THEDP->extendedDialog(); break;
        case PLAYLIST_ACTION:
            playlist(); break;
        case SNAPSHOT_ACTION:
            snapshot(); break;
        case RECORD_ACTION:
            record(); break;
        case FRAME_ACTION:
            frame(); break;
        case ATOB_ACTION:
            THEMIM->getIM()->setAtoB(); break;
        case REVERSE_ACTION:
            THEMIM->getIM()->reverse(); break;
        case SKIP_BACK_ACTION:
            skipBackward();
            break;
        case SKIP_FW_ACTION:
            skipForward();
            break;
        case QUIT_ACTION:
            THEDP->quit();  break;
        case RANDOM_ACTION:
            THEMIM->toggleRandom(); break;
        case INFO_ACTION:
            THEDP->mediaInfoDialog(); break;
        case OPEN_SUB_ACTION:
            THEDP->loadSubtitlesFile(); break;
        case FULLWIDTH_ACTION:
            if( p_intf->p_sys->p_mi )
                p_intf->p_sys->p_mi->getFullscreenControllerWidget()->toggleFullwidth();
            break;
        default:
            msg_Dbg( p_intf, "Action: %i", id_action );
            break;
    }
}

void ActionsManager::play()
{
    if( THEPL->current.i_size == 0 )
    {
        /* The playlist is empty, open a file requester */
        THEDP->openFileDialog();
        return;
    }
    THEMIM->togglePlayPause();
}

/**
  * TODO
 * This functions toggle the fullscreen mode
 * If there is no video, it should first activate Visualisations...
 *  This has also to be fixed in enableVideo()
 */
void ActionsManager::fullscreen()
{
    bool fs = var_ToggleBool( THEPL, "fullscreen" );
    vout_thread_t *p_vout = THEMIM->getVout();
    if( p_vout)
    {
        var_SetBool( p_vout, "fullscreen", fs );
        vlc_object_release( p_vout );
    }
}

void ActionsManager::snapshot()
{
    vout_thread_t *p_vout = THEMIM->getVout();
    if( p_vout )
    {
        var_TriggerCallback( p_vout, "video-snapshot" );
        vlc_object_release( p_vout );
    }
}

void ActionsManager::playlist()
{
    if( p_intf->p_sys->p_mi ) p_intf->p_sys->p_mi->togglePlaylist();
}

void ActionsManager::record()
{
    input_thread_t *p_input = THEMIM->getInput();
    if( p_input )
    {
        /* This method won't work fine if the stream can't be cut anywhere */
        var_ToggleBool( p_input, "record" );
#if 0
        else
        {
            /* 'record' access-filter is not loaded, we open Save dialog */
            input_item_t *p_item = input_GetItem( p_input );
            if( !p_item )
                return;

            char *psz = input_item_GetURI( p_item );
            if( psz )
                THEDP->streamingDialog( NULL, qfu(psz), true );
        }
#endif
    }
}

void ActionsManager::frame()
{
    input_thread_t *p_input = THEMIM->getInput();
    if( p_input )
        var_TriggerCallback( p_input, "frame-next" );
}

void ActionsManager::toggleMuteAudio()
{
     aout_MuteToggle( THEPL );
}

void ActionsManager::AudioUp()
{
    aout_VolumeUp( THEPL, 1, NULL );
}

void ActionsManager::AudioDown()
{
    aout_VolumeDown( THEPL, 1, NULL );
}

void ActionsManager::skipForward()
{
    THEMIM->getIM()->jumpFwd();
}

void ActionsManager::skipBackward()
{
    THEMIM->getIM()->jumpBwd();
}

<commit_msg>Qt: avoid a crash<commit_after>/*****************************************************************************
 * actions_manager.cpp : Controller for the main interface
 ****************************************************************************
 * Copyright (C) 2006-2008 the VideoLAN team
 * $Id$
 *
 * Authors: Jean-Baptiste Kempf <jb@videolan.org>
 *          Ilkka Ollakka <ileoo@videolan.org>
 *
 * This program 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 2 of the License, or
 * ( at your option ) any later version.
 *
 * This program 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 this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
 *****************************************************************************/

#ifdef HAVE_CONFIG_H
# include "config.h"
#endif

#include <vlc_vout.h>
#include <vlc_aout_intf.h>
#include <vlc_keys.h>

#include "actions_manager.hpp"
#include "dialogs_provider.hpp" /* Opening Dialogs */
#include "input_manager.hpp"
#include "main_interface.hpp" /* Show playlist */
#include "components/controller.hpp" /* Toggle FSC controller width */

ActionsManager * ActionsManager::instance = NULL;

ActionsManager::ActionsManager( intf_thread_t * _p_i, QObject *_parent )
               : QObject( _parent )
{
    p_intf = _p_i;
}

ActionsManager::~ActionsManager(){}

void ActionsManager::doAction( int id_action )
{
    switch( id_action )
    {
        case PLAY_ACTION:
            play(); break;
        case STOP_ACTION:
            THEMIM->stop(); break;
        case OPEN_ACTION:
            THEDP->openDialog(); break;
        case PREVIOUS_ACTION:
            THEMIM->prev(); break;
        case NEXT_ACTION:
            THEMIM->next(); break;
        case SLOWER_ACTION:
            THEMIM->getIM()->slower(); break;
        case FASTER_ACTION:
            THEMIM->getIM()->faster(); break;
        case FULLSCREEN_ACTION:
            fullscreen(); break;
        case EXTENDED_ACTION:
            THEDP->extendedDialog(); break;
        case PLAYLIST_ACTION:
            playlist(); break;
        case SNAPSHOT_ACTION:
            snapshot(); break;
        case RECORD_ACTION:
            record(); break;
        case FRAME_ACTION:
            frame(); break;
        case ATOB_ACTION:
            THEMIM->getIM()->setAtoB(); break;
        case REVERSE_ACTION:
            THEMIM->getIM()->reverse(); break;
        case SKIP_BACK_ACTION:
            skipBackward();
            break;
        case SKIP_FW_ACTION:
            skipForward();
            break;
        case QUIT_ACTION:
            THEDP->quit();  break;
        case RANDOM_ACTION:
            THEMIM->toggleRandom(); break;
        case INFO_ACTION:
            THEDP->mediaInfoDialog(); break;
        case OPEN_SUB_ACTION:
            THEDP->loadSubtitlesFile(); break;
        case FULLWIDTH_ACTION:
            if( p_intf->p_sys->p_mi )
                p_intf->p_sys->p_mi->getFullscreenControllerWidget()->toggleFullwidth();
            break;
        default:
            msg_Dbg( p_intf, "Action: %i", id_action );
            break;
    }
}

void ActionsManager::play()
{
    if( THEPL->current.i_size == 0 )
    {
        /* The playlist is empty, open a file requester */
        THEDP->openFileDialog();
        return;
    }
    THEMIM->togglePlayPause();
}

/**
  * TODO
 * This functions toggle the fullscreen mode
 * If there is no video, it should first activate Visualisations...
 *  This has also to be fixed in enableVideo()
 */
void ActionsManager::fullscreen()
{
    bool fs = var_ToggleBool( THEPL, "fullscreen" );
    vout_thread_t *p_vout = THEMIM->getVout();
    if( p_vout)
    {
        var_SetBool( p_vout, "fullscreen", fs );
        vlc_object_release( p_vout );
    }
}

void ActionsManager::snapshot()
{
    vout_thread_t *p_vout = THEMIM->getVout();
    if( p_vout )
    {
        var_TriggerCallback( p_vout, "video-snapshot" );
        vlc_object_release( p_vout );
    }
}

void ActionsManager::playlist()
{
    if( p_intf->p_sys->p_mi ) p_intf->p_sys->p_mi->togglePlaylist();
}

void ActionsManager::record()
{
    input_thread_t *p_input = THEMIM->getInput();
    if( p_input )
    {
        /* This method won't work fine if the stream can't be cut anywhere */
        var_ToggleBool( p_input, "record" );
#if 0
        else
        {
            /* 'record' access-filter is not loaded, we open Save dialog */
            input_item_t *p_item = input_GetItem( p_input );
            if( !p_item )
                return;

            char *psz = input_item_GetURI( p_item );
            if( psz )
                THEDP->streamingDialog( NULL, qfu(psz), true );
        }
#endif
    }
}

void ActionsManager::frame()
{
    input_thread_t *p_input = THEMIM->getInput();
    if( p_input )
        var_TriggerCallback( p_input, "frame-next" );
}

void ActionsManager::toggleMuteAudio()
{
     aout_MuteToggle( THEPL );
}

void ActionsManager::AudioUp()
{
    aout_VolumeUp( THEPL, 1, NULL );
}

void ActionsManager::AudioDown()
{
    aout_VolumeDown( THEPL, 1, NULL );
}

void ActionsManager::skipForward()
{
    input_thread_t *p_input = THEMIM->getInput();
    if( p_input )
        THEMIM->getIM()->jumpFwd();
}

void ActionsManager::skipBackward()
{
    input_thread_t *p_input = THEMIM->getInput();
    if( p_input )
        THEMIM->getIM()->jumpBwd();
}

<|endoftext|>


<commit_before>#include "BreakingDam.h"

peanoclaw::native::scenarios::BreakingDamSWEScenario::BreakingDamSWEScenario(
  const tarch::la::Vector<DIMENSIONS, double>& domainOffset,
  const tarch::la::Vector<DIMENSIONS, double>& domainSize,
  const tarch::la::Vector<DIMENSIONS, int>&    finestSubgridTopology,
  const tarch::la::Vector<DIMENSIONS, int>&    coarsestSubgridTopology,
  const tarch::la::Vector<DIMENSIONS, int>& subdivisionFactor,
  double                                    globalTimestepSize,
  double                                    endTime
) : _domainOffset(domainOffset),
    _domainSize(domainSize),
    _minimalMeshWidth(-1),
    _maximalMeshWidth(-1),
    _subdivisionFactor(subdivisionFactor),
    _globalTimestepSize(globalTimestepSize),
    _endTime(endTime)
{
  _minimalMeshWidth
    = tarch::la::multiplyComponents(domainSize, tarch::la::invertEntries(finestSubgridTopology.convertScalar<double>()));
  _maximalMeshWidth
    = tarch::la::multiplyComponents(domainSize, tarch::la::invertEntries(coarsestSubgridTopology.convertScalar<double>()));

//  assertion2(tarch::la::allGreaterEquals(_maximalMeshWidth, _minimalMeshWidth), _minimalMeshWidth, _maximalMeshWidth);
  assertion2(tarch::la::allSmallerEquals(_minimalMeshWidth, _maximalMeshWidth), _minimalMeshWidth, _maximalMeshWidth);
}

peanoclaw::native::scenarios::BreakingDamSWEScenario::BreakingDamSWEScenario(
  std::vector<std::string> arguments
) : _domainOffset(0),
    _domainSize(1){
  if(arguments.size() != 5) {
    std::cerr << "Expected arguments for Scenario 'BreakingDam': finestSubgridTopology coarsestSubgridTopology subdivisionFactor endTime globalTimestepSize" << std::endl
        << "\tGot " << arguments.size() << " arguments." << std::endl;
    throw "";
  }

  double finestSubgridTopologyPerDimension = atof(arguments[0].c_str());
  _minimalMeshWidth = _domainSize/ finestSubgridTopologyPerDimension;

  double coarsestSubgridTopologyPerDimension = atof(arguments[1].c_str());
  _maximalMeshWidth = _domainSize/ coarsestSubgridTopologyPerDimension;

  _subdivisionFactor = tarch::la::Vector<DIMENSIONS,int>(atoi(arguments[2].c_str()));

  _endTime = atof(arguments[3].c_str());

  _globalTimestepSize = atof(arguments[4].c_str());
}

peanoclaw::native::scenarios::BreakingDamSWEScenario::~BreakingDamSWEScenario() {}

void peanoclaw::native::scenarios::BreakingDamSWEScenario::initializePatch(peanoclaw::Patch& patch) {
    // compute from mesh data
    const tarch::la::Vector<DIMENSIONS, double> patchPosition = patch.getPosition();
    const tarch::la::Vector<DIMENSIONS, double> meshWidth = patch.getSubcellSize();
    peanoclaw::grid::SubgridAccessor& accessor = patch.getAccessor();

    tarch::la::Vector<DIMENSIONS, int> subcellIndex;
    for (int yi = 0; yi < patch.getSubdivisionFactor()(1); yi++) {
        for (int xi = 0; xi < patch.getSubdivisionFactor()(0); xi++) {
            subcellIndex(0) = xi;
            subcellIndex(1) = yi;

            double X = patchPosition(0) + xi*meshWidth(0);
            double Y = patchPosition(1) + yi*meshWidth(1);

            double q0 = getWaterHeight(X, Y);
            double q1 = 0.0; //hl*ul*(r<=radDam) + hr*ur*(r>radDam);
            double q2 = 0.0; //hl*vl*(r<=radDam) + hr*vr*(r>radDam);

            accessor.setValueUNew(subcellIndex, 0, q0);
            accessor.setValueUNew(subcellIndex, 1, q1);
            accessor.setValueUNew(subcellIndex, 2, q2);

            accessor.setParameterWithGhostlayer(subcellIndex, 0, 0.0);

            assertion2(tarch::la::equals(accessor.getValueUNew(subcellIndex, 0), q0, 1e-5), accessor.getValueUNew(subcellIndex, 0), q0);
            assertion2(tarch::la::equals(accessor.getValueUNew(subcellIndex, 1), q1, 1e-5), accessor.getValueUNew(subcellIndex, 1), q1);
            assertion2(tarch::la::equals(accessor.getValueUNew(subcellIndex, 2), q2, 1e-5), accessor.getValueUNew(subcellIndex, 2), q2);
        }
    }
}

tarch::la::Vector<DIMENSIONS,double> peanoclaw::native::scenarios::BreakingDamSWEScenario::computeDemandedMeshWidth(
  peanoclaw::Patch& patch,
  bool isInitializing
) {
  if(tarch::la::equals(_minimalMeshWidth, _maximalMeshWidth)) {
    return _minimalMeshWidth;
  }

    double max_gradient = 0.0;
    const tarch::la::Vector<DIMENSIONS, double> meshWidth = patch.getSubcellSize();
    peanoclaw::grid::SubgridAccessor& accessor = patch.getAccessor();

    tarch::la::Vector<DIMENSIONS, int> this_subcellIndex;
    tarch::la::Vector<DIMENSIONS, int> next_subcellIndex_x;
    tarch::la::Vector<DIMENSIONS, int> next_subcellIndex_y;
    for (int yi = 0; yi < patch.getSubdivisionFactor()(1)-1; yi++) {
        for (int xi = 0; xi < patch.getSubdivisionFactor()(0)-1; xi++) {
            this_subcellIndex(0) = xi;
            this_subcellIndex(1) = yi;

            next_subcellIndex_x(0) = xi+1;
            next_subcellIndex_x(1) = yi;

            next_subcellIndex_y(0) = xi;
            next_subcellIndex_y(1) = yi+1;

            double q0 =  accessor.getValueUNew(this_subcellIndex, 0);
            double q0_x =  (accessor.getValueUNew(next_subcellIndex_x, 0) - q0) / meshWidth(0);
            double q0_y =  (accessor.getValueUNew(next_subcellIndex_y, 0) - q0) / meshWidth(1);

            max_gradient = fmax(max_gradient, sqrt(fabs(q0_x)*fabs(q0_x) + fabs(q0_y)*fabs(q0_y)));
        }
    }

    tarch::la::Vector<DIMENSIONS,double> demandedMeshWidth;
    if (max_gradient > 0.1) {
        //demandedMeshWidth = 1.0/243;
        //demandedMeshWidth = tarch::la::Vector<DIMENSIONS,double>(10.0/6/27);
      demandedMeshWidth = _minimalMeshWidth;
    } else if (max_gradient < 0.1) {
        //demandedMeshWidth = 10.0/130/27;
        //demandedMeshWidth = tarch::la::Vector<DIMENSIONS,double>(10.0/6/9);
      demandedMeshWidth = _maximalMeshWidth;
    } else {
      demandedMeshWidth = patch.getSubcellSize();
    }

//    if(isInitializing) {
//      return 10.0/6/9;
//    } else {
//      return demandedMeshWidth;
//    }
    return demandedMeshWidth;
}

tarch::la::Vector<DIMENSIONS,double> peanoclaw::native::scenarios::BreakingDamSWEScenario::getDomainOffset() const {
  return _domainOffset;
}

tarch::la::Vector<DIMENSIONS,double> peanoclaw::native::scenarios::BreakingDamSWEScenario::getDomainSize() const {
  return _domainSize;
}

tarch::la::Vector<DIMENSIONS,double> peanoclaw::native::scenarios::BreakingDamSWEScenario::getInitialMinimalMeshWidth() const {
  return _maximalMeshWidth;
}

tarch::la::Vector<DIMENSIONS,int> peanoclaw::native::scenarios::BreakingDamSWEScenario::getSubdivisionFactor() const {
  return _subdivisionFactor;
}

double peanoclaw::native::scenarios::BreakingDamSWEScenario::getGlobalTimestepSize() const {
  return _globalTimestepSize;
}

double peanoclaw::native::scenarios::BreakingDamSWEScenario::getEndTime() const {
  return _endTime;
}

float peanoclaw::native::scenarios::BreakingDamSWEScenario::getWaterHeight(float x, float y) {
  // dam coordinates
  const double x0=1/2.0;
  const double y0=1/2.0;
  // Riemann states of the dam break problem
  const double radDam = 0.25;
  const double hl = 3.;
  const double hr = 2.;

  double r = sqrt((x-x0)*(x-x0) + (y-y0)*(y-y0));
  return hl*(r<=radDam) + hr*(r>radDam);
}
<commit_msg>fixed<commit_after>#include "BreakingDam.h"

peanoclaw::native::scenarios::BreakingDamSWEScenario::BreakingDamSWEScenario(
  const tarch::la::Vector<DIMENSIONS, double>& domainOffset,
  const tarch::la::Vector<DIMENSIONS, double>& domainSize,
  const tarch::la::Vector<DIMENSIONS, int>&    finestSubgridTopology,
  const tarch::la::Vector<DIMENSIONS, int>&    coarsestSubgridTopology,
  const tarch::la::Vector<DIMENSIONS, int>& subdivisionFactor,
  double                                    globalTimestepSize,
  double                                    endTime
) : _domainOffset(domainOffset),
    _domainSize(domainSize),
    _minimalMeshWidth(-1),
    _maximalMeshWidth(-1),
    _subdivisionFactor(subdivisionFactor),
    _globalTimestepSize(globalTimestepSize),
    _endTime(endTime)
{
  _minimalMeshWidth
    = tarch::la::multiplyComponents(domainSize, tarch::la::invertEntries(finestSubgridTopology.convertScalar<double>()));
  _maximalMeshWidth
    = tarch::la::multiplyComponents(domainSize, tarch::la::invertEntries(coarsestSubgridTopology.convertScalar<double>()));

//  assertion2(tarch::la::allGreaterEquals(_maximalMeshWidth, _minimalMeshWidth), _minimalMeshWidth, _maximalMeshWidth);
  assertion2(tarch::la::allSmallerEquals(_minimalMeshWidth, _maximalMeshWidth), _minimalMeshWidth, _maximalMeshWidth);
}

peanoclaw::native::scenarios::BreakingDamSWEScenario::BreakingDamSWEScenario(
  std::vector<std::string> arguments
) : _domainOffset(0),
    _domainSize(1){
  if(arguments.size() != 5) {
    std::cerr << "Expected arguments for Scenario 'BreakingDam': finestSubgridTopology coarsestSubgridTopology subdivisionFactor endTime globalTimestepSize" << std::endl
        << "\tGot " << arguments.size() << " arguments." << std::endl;
    throw "";
  }

  double finestSubgridTopologyPerDimension = atof(arguments[0].c_str());
  _minimalMeshWidth = _domainSize/ finestSubgridTopologyPerDimension;

  double coarsestSubgridTopologyPerDimension = atof(arguments[1].c_str());
  _maximalMeshWidth = _domainSize/ coarsestSubgridTopologyPerDimension;

  _subdivisionFactor = tarch::la::Vector<DIMENSIONS,int>(atoi(arguments[2].c_str()));

  _endTime = atof(arguments[3].c_str());

  _globalTimestepSize = atof(arguments[4].c_str());
}

peanoclaw::native::scenarios::BreakingDamSWEScenario::~BreakingDamSWEScenario() {}

void peanoclaw::native::scenarios::BreakingDamSWEScenario::initializePatch(peanoclaw::Patch& patch) {
    // compute from mesh data
    const tarch::la::Vector<DIMENSIONS, double> patchPosition = patch.getPosition();
    const tarch::la::Vector<DIMENSIONS, double> meshWidth = patch.getSubcellSize();
    peanoclaw::grid::SubgridAccessor& accessor = patch.getAccessor();

    tarch::la::Vector<DIMENSIONS, int> subcellIndex;
    for (int yi = 0; yi < patch.getSubdivisionFactor()(1); yi++) {
        for (int xi = 0; xi < patch.getSubdivisionFactor()(0); xi++) {
            subcellIndex(0) = xi;
            subcellIndex(1) = yi;

            double X = patchPosition(0) + (xi+0.5)*meshWidth(0);
            double Y = patchPosition(1) + (yi+0.5)*meshWidth(1);

            double q0 = getWaterHeight(X, Y);
            double q1 = 0.0; //hl*ul*(r<=radDam) + hr*ur*(r>radDam);
            double q2 = 0.0; //hl*vl*(r<=radDam) + hr*vr*(r>radDam);

            accessor.setValueUNew(subcellIndex, 0, q0);
            accessor.setValueUNew(subcellIndex, 1, q1);
            accessor.setValueUNew(subcellIndex, 2, q2);

            accessor.setParameterWithGhostlayer(subcellIndex, 0, 0.0);

            assertion2(tarch::la::equals(accessor.getValueUNew(subcellIndex, 0), q0, 1e-5), accessor.getValueUNew(subcellIndex, 0), q0);
            assertion2(tarch::la::equals(accessor.getValueUNew(subcellIndex, 1), q1, 1e-5), accessor.getValueUNew(subcellIndex, 1), q1);
            assertion2(tarch::la::equals(accessor.getValueUNew(subcellIndex, 2), q2, 1e-5), accessor.getValueUNew(subcellIndex, 2), q2);
        }
    }
}

tarch::la::Vector<DIMENSIONS,double> peanoclaw::native::scenarios::BreakingDamSWEScenario::computeDemandedMeshWidth(
  peanoclaw::Patch& patch,
  bool isInitializing
) {
  if(tarch::la::equals(_minimalMeshWidth, _maximalMeshWidth)) {
    return _minimalMeshWidth;
  }

    double max_gradient = 0.0;
    const tarch::la::Vector<DIMENSIONS, double> meshWidth = patch.getSubcellSize();
    peanoclaw::grid::SubgridAccessor& accessor = patch.getAccessor();

    tarch::la::Vector<DIMENSIONS, int> this_subcellIndex;
    tarch::la::Vector<DIMENSIONS, int> next_subcellIndex_x;
    tarch::la::Vector<DIMENSIONS, int> next_subcellIndex_y;
    for (int yi = 0; yi < patch.getSubdivisionFactor()(1)-1; yi++) {
        for (int xi = 0; xi < patch.getSubdivisionFactor()(0)-1; xi++) {
            this_subcellIndex(0) = xi;
            this_subcellIndex(1) = yi;

            next_subcellIndex_x(0) = xi+1;
            next_subcellIndex_x(1) = yi;

            next_subcellIndex_y(0) = xi;
            next_subcellIndex_y(1) = yi+1;

            double q0 =  accessor.getValueUNew(this_subcellIndex, 0);
            double q0_x =  (accessor.getValueUNew(next_subcellIndex_x, 0) - q0) / meshWidth(0);
            double q0_y =  (accessor.getValueUNew(next_subcellIndex_y, 0) - q0) / meshWidth(1);

            max_gradient = fmax(max_gradient, sqrt(fabs(q0_x)*fabs(q0_x) + fabs(q0_y)*fabs(q0_y)));
        }
    }

    tarch::la::Vector<DIMENSIONS,double> demandedMeshWidth;
    if (max_gradient > 0.1) {
        //demandedMeshWidth = 1.0/243;
        //demandedMeshWidth = tarch::la::Vector<DIMENSIONS,double>(10.0/6/27);
      demandedMeshWidth = _minimalMeshWidth;
    } else if (max_gradient < 0.1) {
        //demandedMeshWidth = 10.0/130/27;
        //demandedMeshWidth = tarch::la::Vector<DIMENSIONS,double>(10.0/6/9);
      demandedMeshWidth = _maximalMeshWidth;
    } else {
      demandedMeshWidth = patch.getSubcellSize();
    }

//    if(isInitializing) {
//      return 10.0/6/9;
//    } else {
//      return demandedMeshWidth;
//    }
    return demandedMeshWidth;
}

tarch::la::Vector<DIMENSIONS,double> peanoclaw::native::scenarios::BreakingDamSWEScenario::getDomainOffset() const {
  return _domainOffset;
}

tarch::la::Vector<DIMENSIONS,double> peanoclaw::native::scenarios::BreakingDamSWEScenario::getDomainSize() const {
  return _domainSize;
}

tarch::la::Vector<DIMENSIONS,double> peanoclaw::native::scenarios::BreakingDamSWEScenario::getInitialMinimalMeshWidth() const {
  return _maximalMeshWidth;
}

tarch::la::Vector<DIMENSIONS,int> peanoclaw::native::scenarios::BreakingDamSWEScenario::getSubdivisionFactor() const {
  return _subdivisionFactor;
}

double peanoclaw::native::scenarios::BreakingDamSWEScenario::getGlobalTimestepSize() const {
  return _globalTimestepSize;
}

double peanoclaw::native::scenarios::BreakingDamSWEScenario::getEndTime() const {
  return _endTime;
}

float peanoclaw::native::scenarios::BreakingDamSWEScenario::getWaterHeight(float x, float y) {
  // dam coordinates
  const double x0=1/2.0;
  const double y0=1/2.0;
  // Riemann states of the dam break problem
  const double radDam = 0.25;
  const double hl = 3.;
  const double hr = 2.;

  double r = sqrt((x-x0)*(x-x0) + (y-y0)*(y-y0));
  return hl*(r<=radDam) + hr*(r>radDam);
}
<|endoftext|>


<commit_before>#include "depthai/pipeline/datatype/FeatureTrackerConfig.hpp"

namespace dai {

std::shared_ptr<RawBuffer> FeatureTrackerConfig::serialize() const {
    return raw;
}

FeatureTrackerConfig::FeatureTrackerConfig() : Buffer(std::make_shared<RawFeatureTrackerConfig>()), cfg(*dynamic_cast<RawFeatureTrackerConfig*>(raw.get())) {}
FeatureTrackerConfig::FeatureTrackerConfig(std::shared_ptr<RawFeatureTrackerConfig> ptr)
    : Buffer(std::move(ptr)), cfg(*dynamic_cast<RawFeatureTrackerConfig*>(raw.get())) {}

dai::RawFeatureTrackerConfig FeatureTrackerConfig::get() const {
    return cfg;
}

void FeatureTrackerConfig::setCornerDetector(dai::FeatureTrackerConfig::CornerDetector::Type cornerDetector) {
    cfg.cornerDetector.type = cornerDetector;
}

void FeatureTrackerConfig::setCornerDetector(dai::FeatureTrackerConfig::CornerDetector config) {
    cfg.cornerDetector = config;
}

void FeatureTrackerConfig::setMotionEstimator(bool enable) {
    cfg.motionEstimator.enable = enable;
}

void FeatureTrackerConfig::setMotionEstimator(dai::FeatureTrackerConfig::MotionEstimator config) {
    cfg.motionEstimator = config;
}

void FeatureTrackerConfig::setOpticalFlow(dai::FeatureTrackerConfig::MotionEstimator::OpticalFlow config) {
    cfg.motionEstimator.type = dai::FeatureTrackerConfig::MotionEstimator::Type::LUCAS_KANADE_OPTICAL_FLOW;
    cfg.motionEstimator.opticalFlow = config;
    setMotionEstimator(true);
}

void FeatureTrackerConfig::setHwMotionEstimation() {
    cfg.motionEstimator.type = dai::FeatureTrackerConfig::MotionEstimator::Type::HW_MOTION_ESTIMATION;
    setMotionEstimator(true);
}

void FeatureTrackerConfig::setFeatureMaintainer(bool enable) {
    cfg.featureMaintainer.enable = enable;
}

void FeatureTrackerConfig::setFeatureMaintainer(dai::FeatureTrackerConfig::FeatureMaintainer config) {
    cfg.featureMaintainer = config;
}

void FeatureTrackerConfig::set(dai::RawFeatureTrackerConfig config) {
    cfg = config;
}

void FeatureTrackerConfig::setNumTargetFeatures(std::int32_t numTargetFeatures) {
    cfg.cornerDetector.numTargetFeatures = numTargetFeatures;
}

}  // namespace dai
<commit_msg>Fix build issue<commit_after>#include "depthai/pipeline/datatype/FeatureTrackerConfig.hpp"

namespace dai {

std::shared_ptr<RawBuffer> FeatureTrackerConfig::serialize() const {
    return raw;
}

FeatureTrackerConfig::FeatureTrackerConfig() : Buffer(std::make_shared<RawFeatureTrackerConfig>()), cfg(*dynamic_cast<RawFeatureTrackerConfig*>(raw.get())) {}
FeatureTrackerConfig::FeatureTrackerConfig(std::shared_ptr<RawFeatureTrackerConfig> ptr)
    : Buffer(std::move(ptr)), cfg(*dynamic_cast<RawFeatureTrackerConfig*>(raw.get())) {}

dai::RawFeatureTrackerConfig FeatureTrackerConfig::get() const {
    return cfg;
}

void FeatureTrackerConfig::setCornerDetector(dai::FeatureTrackerConfig::CornerDetector::Type cornerDetector) {
    cfg.cornerDetector.type = cornerDetector;
}

void FeatureTrackerConfig::setCornerDetector(dai::FeatureTrackerConfig::CornerDetector config) {
    cfg.cornerDetector = config;
}

void FeatureTrackerConfig::setMotionEstimator(bool enable) {
    cfg.motionEstimator.enable = enable;
}

void FeatureTrackerConfig::setMotionEstimator(dai::FeatureTrackerConfig::MotionEstimator config) {
    cfg.motionEstimator = config;
}

void FeatureTrackerConfig::setOpticalFlow() {
    cfg.motionEstimator.type = dai::FeatureTrackerConfig::MotionEstimator::Type::LUCAS_KANADE_OPTICAL_FLOW;
    setMotionEstimator(true);
}

void FeatureTrackerConfig::setOpticalFlow(dai::FeatureTrackerConfig::MotionEstimator::OpticalFlow config) {
    cfg.motionEstimator.type = dai::FeatureTrackerConfig::MotionEstimator::Type::LUCAS_KANADE_OPTICAL_FLOW;
    cfg.motionEstimator.opticalFlow = config;
    setMotionEstimator(true);
}

void FeatureTrackerConfig::setHwMotionEstimation() {
    cfg.motionEstimator.type = dai::FeatureTrackerConfig::MotionEstimator::Type::HW_MOTION_ESTIMATION;
    setMotionEstimator(true);
}

void FeatureTrackerConfig::setFeatureMaintainer(bool enable) {
    cfg.featureMaintainer.enable = enable;
}

void FeatureTrackerConfig::setFeatureMaintainer(dai::FeatureTrackerConfig::FeatureMaintainer config) {
    cfg.featureMaintainer = config;
}

void FeatureTrackerConfig::set(dai::RawFeatureTrackerConfig config) {
    cfg = config;
}

void FeatureTrackerConfig::setNumTargetFeatures(std::int32_t numTargetFeatures) {
    cfg.cornerDetector.numTargetFeatures = numTargetFeatures;
}

}  // namespace dai
<|endoftext|>


<commit_before>#include <msgpack.hpp>
#include <sstream>
#include <iterator>
#include <gtest/gtest.h>

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#if defined(MSGPACK_USE_BOOST)

#include <boost/fusion/adapted/struct/define_struct.hpp>

BOOST_FUSION_DEFINE_STRUCT(
    BOOST_PP_EMPTY(),
    mystruct,
    (int, f1)
    (double, f2)
    )

TEST(MSGPACK_BOOST, fusion_pack_unpack_convert)
{
    std::stringstream ss;
    mystruct val1;
    val1.f1 = 42;
    val1.f2 = 123.45;
    msgpack::pack(ss, val1);
    msgpack::unpacked ret;
    msgpack::unpack(ret, ss.str().data(), ss.str().size());
    mystruct val2 = ret.get().as<mystruct>();
    EXPECT_TRUE(val1.f1 == val2.f1);
    EXPECT_TRUE(val1.f2 == val2.f2);
}

TEST(MSGPACK_BOOST, object_with_zone_convert)
{
    mystruct val1;
    val1.f1 = 42;
    val1.f2 = 123.45;
    msgpack::zone z;
    msgpack::object obj(val1, z);
    mystruct val2 = obj.as<mystruct>();
    EXPECT_TRUE(val1.f1 == val2.f1);
    EXPECT_TRUE(val1.f2 == val2.f2);
}

#endif // defined(MSGPACK_USE_BOOST)
<commit_msg>Fixed double comparison in tests.<commit_after>#include <msgpack.hpp>
#include <sstream>
#include <iterator>
#include <cmath>

#include <gtest/gtest.h>

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#if defined(MSGPACK_USE_BOOST)

#include <boost/fusion/adapted/struct/define_struct.hpp>

const double kEPS = 1e-10;

BOOST_FUSION_DEFINE_STRUCT(
    BOOST_PP_EMPTY(),
    mystruct,
    (int, f1)
    (double, f2)
    )

TEST(MSGPACK_BOOST, fusion_pack_unpack_convert)
{
    std::stringstream ss;
    mystruct val1;
    val1.f1 = 42;
    val1.f2 = 123.45;
    msgpack::pack(ss, val1);
    msgpack::unpacked ret;
    msgpack::unpack(ret, ss.str().data(), ss.str().size());
    mystruct val2 = ret.get().as<mystruct>();
    EXPECT_TRUE(val1.f1 == val2.f1);
    EXPECT_TRUE(fabs(val2.f2 - val1.f2) <= kEPS);
}

TEST(MSGPACK_BOOST, object_with_zone_convert)
{
    mystruct val1;
    val1.f1 = 42;
    val1.f2 = 123.45;
    msgpack::zone z;
    msgpack::object obj(val1, z);
    mystruct val2 = obj.as<mystruct>();
    EXPECT_TRUE(val1.f1 == val2.f1);
    EXPECT_TRUE(fabs(val2.f2 - val1.f2) <= kEPS);
}

#endif // defined(MSGPACK_USE_BOOST)
<|endoftext|>


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

#include <query_repository.h>

#include <dns/name.h>
#include <dns/message.h>
#include <dns/opcode.h>
#include <dns/rcode.h>
#include <dns/rrclass.h>
#include <dns/rrtype.h>
#include <dns/question.h>

#include <boost/scoped_ptr.hpp>

#include <istream>
#include <fstream>
#include <string>
#include <map>
#include <vector>

using namespace std;
using boost::scoped_ptr;
using namespace isc::dns;

namespace {
// an ad hoc threadshold to prevent a busy loop due to an empty input file.
const size_t MAX_EMPTY_LOOP = 1000;
}

namespace Queryperf {

struct QueryRepository::QueryRepositoryImpl {
    QueryRepositoryImpl(istream& input) :
        qclass_(RRClass::IN()), input_(input)
    {
        initialize();
    }

    QueryRepositoryImpl(const string& input_file) :
        qclass_(RRClass::IN()),
        input_ifs_(new ifstream(input_file.c_str())),
        input_(*input_ifs_)
    {
        initialize();
    }

    void initialize() {
        // BIND 10 libdns++ doesn't yet recognize all standardized RR type
        // menmonics.  To suppress noisy log and avoid ignoring query data
        // containing such RR types, we use a homebrew mapping table.
        // We keep the same map for each repository object to avoid inter
        // thread contention.
        aux_typemap_["A6"] = "TYPE38";
        aux_typemap_["ANY"] = "TYPE255";
    }

    // Extract the next question from the input stream
    QuestionPtr readNextQuestion(bool rewind);

    // Return the next question, either from the preloaded vector (if done)
    // or from the input stream.
    QuestionPtr getNextQuestion();

    RRClass qclass_;            // Query class
    scoped_ptr<ifstream> input_ifs_;
    istream& input_;
    map<string, string> aux_typemap_;
    vector<QuestionPtr> questions_; // used in the "preload" mode
    vector<QuestionPtr>::const_iterator current_question_;
    vector<QuestionPtr>::const_iterator end_question_;
};

QuestionPtr
QueryRepository::QueryRepositoryImpl::readNextQuestion(bool rewind) {
    QuestionPtr question;

    if (!rewind && input_.eof()) {
        return (QuestionPtr());
    }

    while (!question) {
        string line;
        size_t loop_count = 0;
        while (line.empty()) {
            if (loop_count++ == MAX_EMPTY_LOOP) {
                throw QueryRepositoryError("failed to get input line too long,"
                                           " possibly an empty input?");
            }
            getline(input_, line);
            if (input_.eof()) {
                if (rewind) {
                    input_.clear();
                    input_.seekg(0);
                } else if (line.empty()) {
                    return (QuestionPtr());
                }
            } else if (input_.bad() || input_.fail()) {
                throw QueryRepositoryError("unexpected failure in reading "
                                           "input data");
            }
            if (line[0] == ';') { // comment check (note it's safe to see [0])
                line.clear();     // force ingoring this line.
            }
        }

        stringstream ss(line);
        string qname_text, qtype_text;
        ss >> qname_text >> qtype_text;
        if (ss.bad() || ss.fail() || !ss.eof()) {
            // Ignore the line is organized in an unexpected way.
            continue;
        }
        // Workaround for some RR types that are not recognized by BIND 10
        map<string, string>::const_iterator it =
            aux_typemap_.find(qtype_text);
        if (it != aux_typemap_.end()) {
            qtype_text = it->second;
        }
        try {
            question.reset(new Question(Name(qname_text), qclass_,
                                        RRType(qtype_text)));
        } catch (const isc::Exception& ex) {
            // The input data may contain bad string, which would trigger an
            // exception.  We ignore them and continue reading until we find
            // a valid one.
            cerr << "Error parsing query (" << ex.what() << "): "
                 << line << endl;
        }
    }

    return (question);
}

QuestionPtr
QueryRepository::QueryRepositoryImpl::getNextQuestion() {
    if (!questions_.empty()) {
        // queries have been preloaded.  get the next one from the vector.
        QuestionPtr question = *current_question_;
        if (++current_question_ == end_question_) {
            current_question_ = questions_.begin();
        }
        return (question);
    }
    return (readNextQuestion(true));
}

QueryRepository::QueryRepository(istream& input) :
    impl_(new QueryRepositoryImpl(input))
{
}

QueryRepository::QueryRepository(const string& input_file) :
    impl_(new QueryRepositoryImpl(input_file))
{
    if (impl_->input_.fail()) {
        delete impl_;
        throw QueryRepositoryError("failed to input data file: " + input_file);
    }
}

QueryRepository::~QueryRepository() {
    delete impl_;
}

void
QueryRepository::load() {
    QuestionPtr question;
    while ((question = impl_->readNextQuestion(false)) != NULL) {
        impl_->questions_.push_back(question);
    }
    if (impl_->questions_.empty()) {
        throw QueryRepositoryError("failed to preload queries: empty input");
    }
    impl_->current_question_ = impl_->questions_.begin();
    impl_->end_question_ = impl_->questions_.end();
}

size_t
QueryRepository::getQueryCount() const {
    return (impl_->questions_.size());
}

void
QueryRepository::getNextQuery(Message& query_msg) {
    QuestionPtr question = impl_->getNextQuestion();

    query_msg.clear(Message::RENDER);
    query_msg.setOpcode(Opcode::QUERY());
    query_msg.setRcode(Rcode::NOERROR());
    query_msg.setHeaderFlag(Message::HEADERFLAG_RD);
    query_msg.addQuestion(question);
}

void
QueryRepository::setQueryClass(RRClass qclass) {
    impl_->qclass_ = qclass;
}

} // end of QueryPerf
<commit_msg>prohibit duplicate preload<commit_after>// Copyright (C) 2012  JINMEI Tatuya
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
// AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
// PERFORMANCE OF THIS SOFTWARE.

#include <query_repository.h>

#include <dns/name.h>
#include <dns/message.h>
#include <dns/opcode.h>
#include <dns/rcode.h>
#include <dns/rrclass.h>
#include <dns/rrtype.h>
#include <dns/question.h>

#include <boost/scoped_ptr.hpp>

#include <istream>
#include <fstream>
#include <string>
#include <map>
#include <vector>

using namespace std;
using boost::scoped_ptr;
using namespace isc::dns;

namespace {
// an ad hoc threadshold to prevent a busy loop due to an empty input file.
const size_t MAX_EMPTY_LOOP = 1000;
}

namespace Queryperf {

struct QueryRepository::QueryRepositoryImpl {
    QueryRepositoryImpl(istream& input) :
        qclass_(RRClass::IN()), input_(input)
    {
        initialize();
    }

    QueryRepositoryImpl(const string& input_file) :
        qclass_(RRClass::IN()),
        input_ifs_(new ifstream(input_file.c_str())),
        input_(*input_ifs_)
    {
        initialize();
    }

    void initialize() {
        // BIND 10 libdns++ doesn't yet recognize all standardized RR type
        // menmonics.  To suppress noisy log and avoid ignoring query data
        // containing such RR types, we use a homebrew mapping table.
        // We keep the same map for each repository object to avoid inter
        // thread contention.
        aux_typemap_["A6"] = "TYPE38";
        aux_typemap_["ANY"] = "TYPE255";
    }

    // Extract the next question from the input stream
    QuestionPtr readNextQuestion(bool rewind);

    // Return the next question, either from the preloaded vector (if done)
    // or from the input stream.
    QuestionPtr getNextQuestion();

    RRClass qclass_;            // Query class
    scoped_ptr<ifstream> input_ifs_;
    istream& input_;
    map<string, string> aux_typemap_;
    vector<QuestionPtr> questions_; // used in the "preload" mode
    vector<QuestionPtr>::const_iterator current_question_;
    vector<QuestionPtr>::const_iterator end_question_;
};

QuestionPtr
QueryRepository::QueryRepositoryImpl::readNextQuestion(bool rewind) {
    QuestionPtr question;

    if (!rewind && input_.eof()) {
        return (QuestionPtr());
    }

    while (!question) {
        string line;
        size_t loop_count = 0;
        while (line.empty()) {
            if (loop_count++ == MAX_EMPTY_LOOP) {
                throw QueryRepositoryError("failed to get input line too long,"
                                           " possibly an empty input?");
            }
            getline(input_, line);
            if (input_.eof()) {
                if (rewind) {
                    input_.clear();
                    input_.seekg(0);
                } else if (line.empty()) {
                    return (QuestionPtr());
                }
            } else if (input_.bad() || input_.fail()) {
                throw QueryRepositoryError("unexpected failure in reading "
                                           "input data");
            }
            if (line[0] == ';') { // comment check (note it's safe to see [0])
                line.clear();     // force ingoring this line.
            }
        }

        stringstream ss(line);
        string qname_text, qtype_text;
        ss >> qname_text >> qtype_text;
        if (ss.bad() || ss.fail() || !ss.eof()) {
            // Ignore the line is organized in an unexpected way.
            continue;
        }
        // Workaround for some RR types that are not recognized by BIND 10
        map<string, string>::const_iterator it =
            aux_typemap_.find(qtype_text);
        if (it != aux_typemap_.end()) {
            qtype_text = it->second;
        }
        try {
            question.reset(new Question(Name(qname_text), qclass_,
                                        RRType(qtype_text)));
        } catch (const isc::Exception& ex) {
            // The input data may contain bad string, which would trigger an
            // exception.  We ignore them and continue reading until we find
            // a valid one.
            cerr << "Error parsing query (" << ex.what() << "): "
                 << line << endl;
        }
    }

    return (question);
}

QuestionPtr
QueryRepository::QueryRepositoryImpl::getNextQuestion() {
    if (!questions_.empty()) {
        // queries have been preloaded.  get the next one from the vector.
        QuestionPtr question = *current_question_;
        if (++current_question_ == end_question_) {
            current_question_ = questions_.begin();
        }
        return (question);
    }
    return (readNextQuestion(true));
}

QueryRepository::QueryRepository(istream& input) :
    impl_(new QueryRepositoryImpl(input))
{
}

QueryRepository::QueryRepository(const string& input_file) :
    impl_(new QueryRepositoryImpl(input_file))
{
    if (impl_->input_.fail()) {
        delete impl_;
        throw QueryRepositoryError("failed to input data file: " + input_file);
    }
}

QueryRepository::~QueryRepository() {
    delete impl_;
}

void
QueryRepository::load() {
    // duplicate load check
    if (!impl_->questions_.empty()) {
        throw QueryRepositoryError("duplicate preload attempt");
    }

    QuestionPtr question;
    while ((question = impl_->readNextQuestion(false)) != NULL) {
        impl_->questions_.push_back(question);
    }
    if (impl_->questions_.empty()) {
        throw QueryRepositoryError("failed to preload queries: empty input");
    }
    impl_->current_question_ = impl_->questions_.begin();
    impl_->end_question_ = impl_->questions_.end();
}

size_t
QueryRepository::getQueryCount() const {
    return (impl_->questions_.size());
}

void
QueryRepository::getNextQuery(Message& query_msg) {
    QuestionPtr question = impl_->getNextQuestion();

    query_msg.clear(Message::RENDER);
    query_msg.setOpcode(Opcode::QUERY());
    query_msg.setRcode(Rcode::NOERROR());
    query_msg.setHeaderFlag(Message::HEADERFLAG_RD);
    query_msg.addQuestion(question);
}

void
QueryRepository::setQueryClass(RRClass qclass) {
    impl_->qclass_ = qclass;
}

} // end of QueryPerf
<|endoftext|>


<commit_before>/* -*- Mode: C++; indent-tabs-mode: nil -*- */
#include <schwa/io/logging.h>

#include <cassert>
#include <cstring>
#include <ctime>
#include <iostream>

#include <sys/time.h>

namespace schwa {
namespace io {

const char *
loglevel_name(const LogLevel level) {
  switch (level) {
  case LogLevel::CRITICAL: return LogLevelTraits<LogLevel::CRITICAL>::name; break;
  case LogLevel::ERROR: return LogLevelTraits<LogLevel::ERROR>::name; break;
  case LogLevel::WARNING: return LogLevelTraits<LogLevel::WARNING>::name; break;
  case LogLevel::INFO: return LogLevelTraits<LogLevel::INFO>::name; break;
  case LogLevel::DEBUG: return LogLevelTraits<LogLevel::DEBUG>::name; break;
  default: return nullptr; break;
  }
}

unsigned int
loglevel_value(const LogLevel level) {
  switch (level) {
  case LogLevel::CRITICAL: return LogLevelTraits<LogLevel::CRITICAL>::value; break;
  case LogLevel::ERROR: return LogLevelTraits<LogLevel::ERROR>::value; break;
  case LogLevel::WARNING: return LogLevelTraits<LogLevel::WARNING>::value; break;
  case LogLevel::INFO: return LogLevelTraits<LogLevel::INFO>::value; break;
  case LogLevel::DEBUG: return LogLevelTraits<LogLevel::DEBUG>::value; break;
  default: return 0; break;
  }
}

std::ostream &
operator <<(std::ostream &out, const LogLevel level) {
  return out << loglevel_name(level);
}

size_t
pretty_log_header(const LogLevel level, const char *file, const unsigned int linenum, char *const buf, const size_t buf_len) {
  char now_buf[20];
  time_t now;
  timeval now_tv;
  gettimeofday(&now_tv, nullptr);
  now = now_tv.tv_sec;

  std::strftime(now_buf, sizeof(now_buf), "%FT%T", std::localtime(&now));  // YYYY-MM-DDTHH:mm:ss (19)
  const size_t len = std::strlen(file);
  if (len > 34) {
    file += len - 34;
  }
  return std::snprintf(buf, buf_len, "[%19s.%06zd %-8s %34s:%-5u] ", now_buf, now_tv.tv_usec, loglevel_name(level), file, linenum);
}

BasicLogger::Streambuf::Streambuf(std::ostream &ostream, LogLevel threshold) : _ostream(ostream), _threshold(threshold), _level(LogLevel::INFO) { }

BasicLogger::Streambuf::~Streambuf(void) { }

int
BasicLogger::Streambuf::sync(void) {
  if (_level >= _threshold) {
    _ostream << str();
  }
  str("");
  return 0;
}

BasicLogger::BasicLogger(std::ostream &out, LogLevel threshold) : Logger(&_streambuf), _streambuf(out, threshold) { }

BasicLogger::~BasicLogger(void) { }

Logger &
BasicLogger::operator ()(const LogLevel level, const char *const file, const unsigned int linenum) {
  (void)file;
  (void)linenum;
  _streambuf.level(level);
  *this << "[" << level << "]";
  return *this;
}

PrettyLogger::PrettyLogger(std::ostream &out, LogLevel threshold) : BasicLogger(out, threshold) { }

PrettyLogger::~PrettyLogger(void) { }

Logger &
PrettyLogger::operator ()(const LogLevel level, const char *const file, const unsigned int linenum) {
  _streambuf.level(level);
  const size_t used = pretty_log_header(level, file, linenum, _buf, sizeof(_buf));
  assert(used == sizeof(_buf) - 1);
  *this << _buf;
  return *this;
}

ThreadsafeBasicLogger::Streambuf::Streambuf(std::ostream &ostream, LogLevel threshold) : BasicLogger::Streambuf(ostream, threshold) { }

ThreadsafeBasicLogger::Streambuf::~Streambuf(void) { }

int
ThreadsafeBasicLogger::Streambuf::sync(void) {
  const int ret = BasicLogger::Streambuf::sync();
  _lock.unlock();
  return ret;
}

ThreadsafeBasicLogger::ThreadsafeBasicLogger(std::ostream &out, LogLevel threshold) : Logger(&_streambuf), _streambuf(out, threshold) { }

ThreadsafeBasicLogger::~ThreadsafeBasicLogger(void) { }

Logger &
ThreadsafeBasicLogger::operator ()(const LogLevel level, const char *const file, const unsigned int linenum) {
  (void)file;
  (void)linenum;
  _streambuf.lock();
  _streambuf.level(level);
  *this << "[" << level << "]";
  return *this;
}

ThreadsafePrettyLogger::ThreadsafePrettyLogger(std::ostream &out, LogLevel threshold) : ThreadsafeBasicLogger(out, threshold) { }

ThreadsafePrettyLogger::~ThreadsafePrettyLogger(void) { }

Logger &
ThreadsafePrettyLogger::operator ()(const LogLevel level, const char *const file, const unsigned int linenum) {
  _streambuf.lock();
  _streambuf.level(level);
  const size_t used = pretty_log_header(level, file, linenum, _buf, sizeof(_buf));
  assert(used == sizeof(_buf) - 1);
  *this << _buf;
  return *this;
}

static BasicLogger _default_default_logger(std::clog);
Logger *default_logger = &_default_default_logger;

}  // namespace io
}  // namespace schwa
<commit_msg>Added thread ID representation to pretty thread-safe logger output.<commit_after>/* -*- Mode: C++; indent-tabs-mode: nil -*- */
#include <schwa/io/logging.h>

#include <cassert>
#include <cstring>
#include <ctime>
#include <iostream>
#include <sstream>
#include <thread>

#include <sys/time.h>

namespace schwa {
namespace io {

const char *
loglevel_name(const LogLevel level) {
  switch (level) {
  case LogLevel::CRITICAL: return LogLevelTraits<LogLevel::CRITICAL>::name; break;
  case LogLevel::ERROR: return LogLevelTraits<LogLevel::ERROR>::name; break;
  case LogLevel::WARNING: return LogLevelTraits<LogLevel::WARNING>::name; break;
  case LogLevel::INFO: return LogLevelTraits<LogLevel::INFO>::name; break;
  case LogLevel::DEBUG: return LogLevelTraits<LogLevel::DEBUG>::name; break;
  default: return nullptr; break;
  }
}

unsigned int
loglevel_value(const LogLevel level) {
  switch (level) {
  case LogLevel::CRITICAL: return LogLevelTraits<LogLevel::CRITICAL>::value; break;
  case LogLevel::ERROR: return LogLevelTraits<LogLevel::ERROR>::value; break;
  case LogLevel::WARNING: return LogLevelTraits<LogLevel::WARNING>::value; break;
  case LogLevel::INFO: return LogLevelTraits<LogLevel::INFO>::value; break;
  case LogLevel::DEBUG: return LogLevelTraits<LogLevel::DEBUG>::value; break;
  default: return 0; break;
  }
}

std::ostream &
operator <<(std::ostream &out, const LogLevel level) {
  return out << loglevel_name(level);
}

size_t
pretty_log_header(const LogLevel level, const char *file, const unsigned int linenum, char *const buf, const size_t buf_len) {
  char now_buf[20];
  time_t now;
  timeval now_tv;
  gettimeofday(&now_tv, nullptr);
  now = now_tv.tv_sec;

  std::strftime(now_buf, sizeof(now_buf), "%FT%T", std::localtime(&now));  // YYYY-MM-DDTHH:mm:ss (19)
  const size_t len = std::strlen(file);
  if (len > 34) {
    file += len - 34;
  }
  return std::snprintf(buf, buf_len, "[%19s.%06zd %-8s %34s:%-5u] ", now_buf, now_tv.tv_usec, loglevel_name(level), file, linenum);
}

size_t
pretty_log_header_threaded(const LogLevel level, const char *file, const unsigned int linenum, char *const buf, const size_t buf_len) {
  char now_buf[20];
  time_t now;
  timeval now_tv;
  gettimeofday(&now_tv, nullptr);
  now = now_tv.tv_sec;

  std::strftime(now_buf, sizeof(now_buf), "%FT%T", std::localtime(&now));  // YYYY-MM-DDTHH:mm:ss (19)

  std::ostringstream thread_id_ss;
  thread_id_ss << std::this_thread::get_id();
  std::string thread_id = thread_id_ss.str();
  if (thread_id.size() > 9) {
    thread_id.resize(9);
  }

  const size_t len = std::strlen(file);
  if (len > 24) {
    file += len - 24;
  }
  return std::snprintf(buf, buf_len, "[%19s.%06zd %-8s %-9s %24s:%-5u] ", now_buf, now_tv.tv_usec, loglevel_name(level), thread_id.c_str(), file, linenum);
}

BasicLogger::Streambuf::Streambuf(std::ostream &ostream, LogLevel threshold) : _ostream(ostream), _threshold(threshold), _level(LogLevel::INFO) { }

BasicLogger::Streambuf::~Streambuf(void) { }

int
BasicLogger::Streambuf::sync(void) {
  if (_level >= _threshold) {
    _ostream << str();
  }
  str("");
  return 0;
}

BasicLogger::BasicLogger(std::ostream &out, LogLevel threshold) : Logger(&_streambuf), _streambuf(out, threshold) { }

BasicLogger::~BasicLogger(void) { }

Logger &
BasicLogger::operator ()(const LogLevel level, const char *const file, const unsigned int linenum) {
  (void)file;
  (void)linenum;
  _streambuf.level(level);
  *this << "[" << level << "]";
  return *this;
}

PrettyLogger::PrettyLogger(std::ostream &out, LogLevel threshold) : BasicLogger(out, threshold) { }

PrettyLogger::~PrettyLogger(void) { }

Logger &
PrettyLogger::operator ()(const LogLevel level, const char *const file, const unsigned int linenum) {
  _streambuf.level(level);
  const size_t used = pretty_log_header(level, file, linenum, _buf, sizeof(_buf));
  assert(used == sizeof(_buf) - 1);
  *this << _buf;
  return *this;
}

ThreadsafeBasicLogger::Streambuf::Streambuf(std::ostream &ostream, LogLevel threshold) : BasicLogger::Streambuf(ostream, threshold) { }

ThreadsafeBasicLogger::Streambuf::~Streambuf(void) { }

int
ThreadsafeBasicLogger::Streambuf::sync(void) {
  const int ret = BasicLogger::Streambuf::sync();
  _lock.unlock();
  return ret;
}

ThreadsafeBasicLogger::ThreadsafeBasicLogger(std::ostream &out, LogLevel threshold) : Logger(&_streambuf), _streambuf(out, threshold) { }

ThreadsafeBasicLogger::~ThreadsafeBasicLogger(void) { }

Logger &
ThreadsafeBasicLogger::operator ()(const LogLevel level, const char *const file, const unsigned int linenum) {
  (void)file;
  (void)linenum;
  _streambuf.lock();
  _streambuf.level(level);
  *this << "[" << level << "]";
  return *this;
}

ThreadsafePrettyLogger::ThreadsafePrettyLogger(std::ostream &out, LogLevel threshold) : ThreadsafeBasicLogger(out, threshold) { }

ThreadsafePrettyLogger::~ThreadsafePrettyLogger(void) { }

Logger &
ThreadsafePrettyLogger::operator ()(const LogLevel level, const char *const file, const unsigned int linenum) {
  _streambuf.lock();
  _streambuf.level(level);
  const size_t used = pretty_log_header_threaded(level, file, linenum, _buf, sizeof(_buf));
  assert(used == sizeof(_buf) - 1);
  *this << _buf;
  return *this;
}

static BasicLogger _default_default_logger(std::clog);
Logger *default_logger = &_default_default_logger;

}  // namespace io
}  // namespace schwa
<|endoftext|>