<commit_before>/*
 * CvFindChessboardCorners_Processor.cpp
 *
 *  Created on: 16-10-2010
 *      Author: mateusz
 */

#include "CvFindChessboardCorners_Processor.hpp"

namespace Processors {

namespace CvFindChessboardCorners {

using namespace std;
using namespace boost;
using namespace cv;
using namespace Types::Objects3D;

CvFindChessboardCorners_Processor::CvFindChessboardCorners_Processor(const std::string & name) :
	Component(name),
	prop_subpix("subpix", true),
	prop_subpix_window("subpix_window", 9, "range"),
	prop_scale("scale", true),
	prop_scale_factor("scale_factor", 2, "range"),

	prop_width("chessboard.width", 9),
	prop_height("chessboard.height", 6),
	prop_square_width("chessboard.square_width", 1),
	prop_square_height("chessboard.square_height", 1),

	prop_fastCheck("flags.fast_check", true),
	prop_filterQuads("flags.filter_quads", true),
	prop_adaptiveThreshold("flags.adaptive_treshold", true),
	prop_normalizeImage("flags.normalize_image", true)
{

	findChessboardCornersFlags = 0;

	registerProperty(prop_subpix);

	prop_subpix_window.addConstraint("3");
	prop_subpix_window.addConstraint("11");
	registerProperty(prop_subpix_window);

	registerProperty(prop_scale);

	prop_scale_factor.addConstraint("1");
	prop_scale_factor.addConstraint("8");
	registerProperty(prop_scale_factor);

	registerProperty(prop_width);
	registerProperty(prop_height);
	registerProperty(prop_square_width);
	registerProperty(prop_square_height);

	prop_fastCheck.setCallback(boost::bind(&CvFindChessboardCorners_Processor::flagsCallback, this, _1, _2));
	registerProperty(prop_fastCheck);

	prop_filterQuads.setCallback(boost::bind(&CvFindChessboardCorners_Processor::flagsCallback, this, _1, _2));
	registerProperty(prop_filterQuads);

	prop_adaptiveThreshold.setCallback(boost::bind(&CvFindChessboardCorners_Processor::flagsCallback, this, _1, _2));
	registerProperty(prop_adaptiveThreshold);

	prop_normalizeImage.setCallback(boost::bind(&CvFindChessboardCorners_Processor::flagsCallback, this, _1, _2));
	registerProperty(prop_normalizeImage);

	prop_width.setCallback(boost::bind(&CvFindChessboardCorners_Processor::sizeCallback, this, _1, _2));
	prop_height.setCallback(boost::bind(&CvFindChessboardCorners_Processor::sizeCallback, this, _1, _2));

}

CvFindChessboardCorners_Processor::~CvFindChessboardCorners_Processor()
{
}

bool CvFindChessboardCorners_Processor::onFinish()
{
	return true;
}

bool CvFindChessboardCorners_Processor::onStop()
{
	return true;
}

bool CvFindChessboardCorners_Processor::onInit()
{
	h_onNewImage.setup(this, &CvFindChessboardCorners_Processor::onNewImage);
	registerHandler("onNewImage", &h_onNewImage);

	registerStream("in_img", &in_img);
	registerStream("out_chessboard", &out_chessboard);
	registerStream("out_imagePosition", &out_imagePosition);

	chessboardFound = registerEvent("chessboardFound");
	chessboardNotFound = registerEvent("chessboardNotFound");

	initChessboard();

	LOG(LTRACE) << "component initialized\n";
	return true;
}

void CvFindChessboardCorners_Processor::initChessboard() {
	LOG(LINFO) << "CvFindChessboardCorners_Processor: width: " << prop_width << "\n";
	LOG(LINFO) << "CvFindChessboardCorners_Processor: height: " << prop_height << "\n";
	LOG(LINFO) << "CvFindChessboardCorners_Processor: squareSize: " << prop_square_width << "x" << prop_square_height << "m\n";

	chessboard = boost::shared_ptr <Chessboard>(new Chessboard(cv::Size(prop_width, prop_height)));

	vector <Point3f> modelPoints;
	for (int i = 0; i < prop_height; ++i) {
		for (int j = 0; j < prop_width; ++j) {
			modelPoints.push_back(Point3f(-j * prop_square_height, -i * prop_square_width, 0));
		}
	}

	chessboard->setModelPoints(modelPoints);
}

void CvFindChessboardCorners_Processor::sizeCallback(int old_value, int new_value) {
	initChessboard();
}

void CvFindChessboardCorners_Processor::flagsCallback(bool old_value, bool new_value) {
	if(prop_fastCheck){
		findChessboardCornersFlags |= CV_CALIB_CB_FAST_CHECK;
	} else {
		findChessboardCornersFlags &= ~CV_CALIB_CB_FAST_CHECK;
	}

	if(prop_filterQuads){
		findChessboardCornersFlags |= CV_CALIB_CB_FILTER_QUADS;
	} else {
		findChessboardCornersFlags &= ~CV_CALIB_CB_FILTER_QUADS;
	}

	if(prop_adaptiveThreshold){
		findChessboardCornersFlags |= CV_CALIB_CB_ADAPTIVE_THRESH;
	} else {
		findChessboardCornersFlags &= ~CV_CALIB_CB_ADAPTIVE_THRESH;
	}

	if(prop_normalizeImage){
		findChessboardCornersFlags |= CV_CALIB_CB_NORMALIZE_IMAGE;
	} else {
		findChessboardCornersFlags &= ~CV_CALIB_CB_NORMALIZE_IMAGE;
	}
}

bool CvFindChessboardCorners_Processor::onStart()
{
	return true;
}

bool CvFindChessboardCorners_Processor::onStep()
{
	return true;
}

void CvFindChessboardCorners_Processor::onNewImage()
{
	LOG(LTRACE) << "void CvFindChessboardCorners_Processor::onNewImage() begin\n";
	try {
		if(in_img.empty()){
			return;
		}
		Mat image = in_img.read();

		timer.restart();

		cv::resize(image, sub_img, Size(), 1.0 / prop_scale_factor, 1.0 / prop_scale_factor, INTER_NEAREST);

		bool found;

		cv::Size chessboardSize(prop_width, prop_height);

		if (prop_scale) {
			found = findChessboardCorners(sub_img, chessboardSize, corners, findChessboardCornersFlags);
			for (size_t i = 0; i < corners.size(); ++i) {
				corners[i].x *= prop_scale_factor;
				corners[i].y *= prop_scale_factor;
			}
		} else {
			found = findChessboardCorners(image, chessboardSize, corners, findChessboardCornersFlags);
		}

		LOG(LTRACE) << "findChessboardCorners() execution time: " << timer.elapsed() << " s\n";

		if (found) {
			LOG(LTRACE) << "chessboard found\n";

			if (prop_subpix) {
				cornerSubPix(image, corners, Size(prop_subpix_window, prop_subpix_window), Size(1, 1), TermCriteria(CV_TERMCRIT_EPS | CV_TERMCRIT_ITER, 50, 1e-3));
			}

			chessboard->setImagePoints(corners);
			out_chessboard.write(*chessboard);

			Types::ImagePosition imagePosition;
			double maxPixels = std::max(image.size().width, image.size().height);
			imagePosition.elements[0] = (corners[0].x - image.size().width / 2) / maxPixels;
			imagePosition.elements[1] = (corners[1].y - image.size().height / 2) / maxPixels;
			imagePosition.elements[2] = 0;
			imagePosition.elements[3] = 0;
			out_imagePosition.write(imagePosition);

			chessboardFound->raise();
		} else {
			LOG(LTRACE) << "chessboard not found\n";

			chessboardNotFound->raise();
		}
	} catch (const Exception& e) {
		LOG(LERROR) << e.what() << "\n";
	}
	LOG(LTRACE) << "void CvFindChessboardCorners_Processor::onNewImage() end\n";
}

} // namespace CvFindChessboardCorners {
} // namespace Processors {
<commit_msg>IB-EIH visual servo in progress<commit_after>/*
 * CvFindChessboardCorners_Processor.cpp
 *
 *  Created on: 16-10-2010
 *      Author: mateusz
 */

#include "CvFindChessboardCorners_Processor.hpp"

namespace Processors {

namespace CvFindChessboardCorners {

using namespace std;
using namespace boost;
using namespace cv;
using namespace Types::Objects3D;

CvFindChessboardCorners_Processor::CvFindChessboardCorners_Processor(const std::string & name) :
	Component(name),
	prop_subpix("subpix", true),
	prop_subpix_window("subpix_window", 9, "range"),
	prop_scale("scale", true),
	prop_scale_factor("scale_factor", 2, "range"),

	prop_width("chessboard.width", 9),
	prop_height("chessboard.height", 6),
	prop_square_width("chessboard.square_width", 1),
	prop_square_height("chessboard.square_height", 1),

	prop_fastCheck("flags.fast_check", true),
	prop_filterQuads("flags.filter_quads", true),
	prop_adaptiveThreshold("flags.adaptive_treshold", true),
	prop_normalizeImage("flags.normalize_image", true)
{

	findChessboardCornersFlags = 0;

	registerProperty(prop_subpix);

	prop_subpix_window.addConstraint("3");
	prop_subpix_window.addConstraint("11");
	registerProperty(prop_subpix_window);

	registerProperty(prop_scale);

	prop_scale_factor.addConstraint("1");
	prop_scale_factor.addConstraint("8");
	registerProperty(prop_scale_factor);

	registerProperty(prop_width);
	registerProperty(prop_height);
	registerProperty(prop_square_width);
	registerProperty(prop_square_height);

	prop_fastCheck.setCallback(boost::bind(&CvFindChessboardCorners_Processor::flagsCallback, this, _1, _2));
	registerProperty(prop_fastCheck);

	prop_filterQuads.setCallback(boost::bind(&CvFindChessboardCorners_Processor::flagsCallback, this, _1, _2));
	registerProperty(prop_filterQuads);

	prop_adaptiveThreshold.setCallback(boost::bind(&CvFindChessboardCorners_Processor::flagsCallback, this, _1, _2));
	registerProperty(prop_adaptiveThreshold);

	prop_normalizeImage.setCallback(boost::bind(&CvFindChessboardCorners_Processor::flagsCallback, this, _1, _2));
	registerProperty(prop_normalizeImage);

	prop_width.setCallback(boost::bind(&CvFindChessboardCorners_Processor::sizeCallback, this, _1, _2));
	prop_height.setCallback(boost::bind(&CvFindChessboardCorners_Processor::sizeCallback, this, _1, _2));

}

CvFindChessboardCorners_Processor::~CvFindChessboardCorners_Processor()
{
}

bool CvFindChessboardCorners_Processor::onFinish()
{
	return true;
}

bool CvFindChessboardCorners_Processor::onStop()
{
	return true;
}

bool CvFindChessboardCorners_Processor::onInit()
{
	h_onNewImage.setup(this, &CvFindChessboardCorners_Processor::onNewImage);
	registerHandler("onNewImage", &h_onNewImage);

	registerStream("in_img", &in_img);
	registerStream("out_chessboard", &out_chessboard);
	registerStream("out_imagePosition", &out_imagePosition);

	chessboardFound = registerEvent("chessboardFound");
	chessboardNotFound = registerEvent("chessboardNotFound");

	initChessboard();

	LOG(LTRACE) << "component initialized\n";
	return true;
}

void CvFindChessboardCorners_Processor::initChessboard() {
	LOG(LINFO) << "CvFindChessboardCorners_Processor: width: " << prop_width << "\n";
	LOG(LINFO) << "CvFindChessboardCorners_Processor: height: " << prop_height << "\n";
	LOG(LINFO) << "CvFindChessboardCorners_Processor: squareSize: " << prop_square_width << "x" << prop_square_height << "m\n";

	chessboard = boost::shared_ptr <Chessboard>(new Chessboard(cv::Size(prop_width, prop_height)));

	vector <Point3f> modelPoints;
	for (int i = 0; i < prop_height; ++i) {
		for (int j = 0; j < prop_width; ++j) {
			modelPoints.push_back(Point3f(-j * prop_square_height, -i * prop_square_width, 0));
		}
	}

	chessboard->setModelPoints(modelPoints);
}

void CvFindChessboardCorners_Processor::sizeCallback(int old_value, int new_value) {
	initChessboard();
}

void CvFindChessboardCorners_Processor::flagsCallback(bool old_value, bool new_value) {
	if(prop_fastCheck){
		findChessboardCornersFlags |= CV_CALIB_CB_FAST_CHECK;
	} else {
		findChessboardCornersFlags &= ~CV_CALIB_CB_FAST_CHECK;
	}

	if(prop_filterQuads){
		findChessboardCornersFlags |= CV_CALIB_CB_FILTER_QUADS;
	} else {
		findChessboardCornersFlags &= ~CV_CALIB_CB_FILTER_QUADS;
	}

	if(prop_adaptiveThreshold){
		findChessboardCornersFlags |= CV_CALIB_CB_ADAPTIVE_THRESH;
	} else {
		findChessboardCornersFlags &= ~CV_CALIB_CB_ADAPTIVE_THRESH;
	}

	if(prop_normalizeImage){
		findChessboardCornersFlags |= CV_CALIB_CB_NORMALIZE_IMAGE;
	} else {
		findChessboardCornersFlags &= ~CV_CALIB_CB_NORMALIZE_IMAGE;
	}
}

bool CvFindChessboardCorners_Processor::onStart()
{
	return true;
}

bool CvFindChessboardCorners_Processor::onStep()
{
	return true;
}

void CvFindChessboardCorners_Processor::onNewImage()
{
	LOG(LTRACE) << "void CvFindChessboardCorners_Processor::onNewImage() begin\n";
	try {
		if(in_img.empty()){
			return;
		}
		Mat image = in_img.read();

		timer.restart();

		cv::resize(image, sub_img, Size(), 1.0 / prop_scale_factor, 1.0 / prop_scale_factor, INTER_NEAREST);

		bool found;

		cv::Size chessboardSize(prop_width, prop_height);

		if (prop_scale) {
			found = findChessboardCorners(sub_img, chessboardSize, corners, findChessboardCornersFlags);
			for (size_t i = 0; i < corners.size(); ++i) {
				corners[i].x *= prop_scale_factor;
				corners[i].y *= prop_scale_factor;
			}
		} else {
			found = findChessboardCorners(image, chessboardSize, corners, findChessboardCornersFlags);
		}

		LOG(LTRACE) << "findChessboardCorners() execution time: " << timer.elapsed() << " s\n";

		if (found) {
			LOG(LTRACE) << "chessboard found\n";

			if (prop_subpix) {
				cornerSubPix(image, corners, Size(prop_subpix_window, prop_subpix_window), Size(1, 1), TermCriteria(CV_TERMCRIT_EPS | CV_TERMCRIT_ITER, 50, 1e-3));
			}

			chessboard->setImagePoints(corners);
			out_chessboard.write(*chessboard);

			Types::ImagePosition imagePosition;
			double maxPixels = std::max(image.size().width, image.size().height);
			imagePosition.elements[0] = (corners[0].x - image.size().width / 2) / maxPixels;
			imagePosition.elements[1] = (corners[0].y - image.size().height / 2) / maxPixels;
			imagePosition.elements[2] = 0;
			imagePosition.elements[3] = - atan2(corners[1].y - corners[0].y, corners[1].x - corners[0].x);
			out_imagePosition.write(imagePosition);

			chessboardFound->raise();
		} else {
			LOG(LTRACE) << "chessboard not found\n";

			chessboardNotFound->raise();
		}
	} catch (const Exception& e) {
		LOG(LERROR) << e.what() << "\n";
	}
	LOG(LTRACE) << "void CvFindChessboardCorners_Processor::onNewImage() end\n";
}

} // namespace CvFindChessboardCorners {
} // namespace Processors {
<|endoftext|>


<commit_before>/*
  WiFiClient.cpp - TCP/IP client for esp8266, mostly compatible
                   with Arduino WiFi shield library

  Copyright (c) 2014 Ivan Grokhotkov. All rights reserved.
  This file is part of the esp8266 core for Arduino environment.

  This library is free software; you can redistribute it and/or
  modify it under the terms of the GNU Lesser General Public
  License as published by the Free Software Foundation; either
  version 2.1 of the License, or (at your option) any later version.

  This library is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  Lesser General Public License for more details.

  You should have received a copy of the GNU Lesser General Public
  License along with this library; if not, write to the Free Software
  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
*/

#define LWIP_INTERNAL

extern "C"
{
    #include "include/wl_definitions.h"
    #include "osapi.h"
    #include "ets_sys.h"
}

#include "debug.h"
#include "ESP8266WiFi.h"
#include "WiFiClient.h"
#include "WiFiServer.h"
#include "lwip/opt.h"
#include "lwip/tcp.h"
#include "lwip/inet.h"
#include "cbuf.h"
#include "include/ClientContext.h"
#include "c_types.h"

ICACHE_FLASH_ATTR WiFiClient::WiFiClient()
: _client(0)
{
}

ICACHE_FLASH_ATTR WiFiClient::WiFiClient(ClientContext* client) : _client(client)
{
    _client->ref();
}

ICACHE_FLASH_ATTR WiFiClient::~WiFiClient()
{
    if (_client)
        _client->unref();
}

ICACHE_FLASH_ATTR WiFiClient::WiFiClient(const WiFiClient& other)
{
    _client = other._client;
    if (_client)
        _client->ref();
}

WiFiClient& ICACHE_FLASH_ATTR  WiFiClient::operator=(const WiFiClient& other)
{
   if (_client)
        _client->unref();
    _client = other._client;
    if (_client)
        _client->ref();
    return *this;
}

int ICACHE_FLASH_ATTR  WiFiClient::connect(const char* host, uint16_t port)
{
    IPAddress remote_addr;
    if (WiFi.hostByName(host, remote_addr))
    {
        return connect(remote_addr, port);
    }
    return 0;
}

int ICACHE_FLASH_ATTR  WiFiClient::connect(IPAddress ip, uint16_t port)
{
    if (_client)
        stop();

    tcp_pcb* pcb = tcp_new();
    if (!pcb)
        return 0;

    ip_addr_t addr;
    addr.addr = ip;
    tcp_arg(pcb, this);
    tcp_err(pcb, &WiFiClient::_s_err);
    tcp_connect(pcb, &addr, port, reinterpret_cast<tcp_connected_fn>(&WiFiClient::_s_connected));

    esp_yield();
    if (_client)
        return 1;

    //  if tcp_error was called, pcb has already been destroyed.
    // tcp_abort(pcb);
    return 0;
}

int8_t ICACHE_FLASH_ATTR WiFiClient::_connected(void* pcb, int8_t err)
{
    tcp_pcb* tpcb = reinterpret_cast<tcp_pcb*>(pcb);
    _client = new ClientContext(tpcb, 0, 0);
    _client->ref();
    esp_schedule();
    return ERR_OK;
}

void ICACHE_FLASH_ATTR WiFiClient::_err(int8_t err)
{
    DEBUGV(":err %d\r\n", err);
    esp_schedule();
}

size_t ICACHE_FLASH_ATTR WiFiClient::write(uint8_t b)
{
    return write(&b, 1);
}

size_t ICACHE_FLASH_ATTR WiFiClient::write(const uint8_t *buf, size_t size)
{
    if (!_client || !size)
    {
        return 0;
    }

    return _client->write(reinterpret_cast<const char*>(buf), size);
}

extern "C" uint32_t esp_micros_at_task_start();

int ICACHE_FLASH_ATTR WiFiClient::available()
{
    static uint32_t lastPollTime = 0;
    if (!_client)
        return 0;

    if (lastPollTime > esp_micros_at_task_start())
        yield();

    lastPollTime = micros();

    int result = _client->getSize();
    return result;
}

int ICACHE_FLASH_ATTR WiFiClient::read()
{
    if (!available())
        return -1;

    return _client->read();
}

int ICACHE_FLASH_ATTR WiFiClient::read(uint8_t* buf, size_t size)
{
    return (int) _client->read(reinterpret_cast<char*>(buf), size);
}

int ICACHE_FLASH_ATTR WiFiClient::peek()
{
    if (!available())
        return -1;

    return _client->peek();
}

void ICACHE_FLASH_ATTR WiFiClient::flush()
{
    if (_client)
        _client->flush();
}

void ICACHE_FLASH_ATTR WiFiClient::stop()
{
    if (!_client)
        return;

    _client->unref();
    _client = 0;
}

uint8_t ICACHE_FLASH_ATTR WiFiClient::connected()
{
    if (!_client)
        return 0;

    return _client->state() == ESTABLISHED;
}

uint8_t ICACHE_FLASH_ATTR WiFiClient::status()
{
    if (!_client)
        return CLOSED;
    return _client->state();
}

ICACHE_FLASH_ATTR  WiFiClient::operator bool()
{
    return _client != 0;
}

IPAddress WiFiClient::remoteIP()
{
    if (!_client)
        return IPAddress(0U);

    return IPAddress(_client->getRemoteAddress());
}

uint16_t WiFiClient::remotePort()
{
    if (!_client)
        return 0;

    return _client->getRemotePort();
}

int8_t ICACHE_FLASH_ATTR WiFiClient::_s_connected(void* arg, void* tpcb, int8_t err)
{
    return reinterpret_cast<WiFiClient*>(arg)->_connected(tpcb, err);
}

void ICACHE_FLASH_ATTR WiFiClient::_s_err(void* arg, int8_t err)
{
    reinterpret_cast<WiFiClient*>(arg)->_err(err);
}

<commit_msg>ESP8266WiFi: made connected() return true if data is available<commit_after>/*
  WiFiClient.cpp - TCP/IP client for esp8266, mostly compatible
                   with Arduino WiFi shield library

  Copyright (c) 2014 Ivan Grokhotkov. All rights reserved.
  This file is part of the esp8266 core for Arduino environment.

  This library is free software; you can redistribute it and/or
  modify it under the terms of the GNU Lesser General Public
  License as published by the Free Software Foundation; either
  version 2.1 of the License, or (at your option) any later version.

  This library is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  Lesser General Public License for more details.

  You should have received a copy of the GNU Lesser General Public
  License along with this library; if not, write to the Free Software
  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
*/

#define LWIP_INTERNAL

extern "C"
{
    #include "include/wl_definitions.h"
    #include "osapi.h"
    #include "ets_sys.h"
}

#include "debug.h"
#include "ESP8266WiFi.h"
#include "WiFiClient.h"
#include "WiFiServer.h"
#include "lwip/opt.h"
#include "lwip/tcp.h"
#include "lwip/inet.h"
#include "cbuf.h"
#include "include/ClientContext.h"
#include "c_types.h"

ICACHE_FLASH_ATTR WiFiClient::WiFiClient()
: _client(0)
{
}

ICACHE_FLASH_ATTR WiFiClient::WiFiClient(ClientContext* client) : _client(client)
{
    _client->ref();
}

ICACHE_FLASH_ATTR WiFiClient::~WiFiClient()
{
    if (_client)
        _client->unref();
}

ICACHE_FLASH_ATTR WiFiClient::WiFiClient(const WiFiClient& other)
{
    _client = other._client;
    if (_client)
        _client->ref();
}

WiFiClient& ICACHE_FLASH_ATTR  WiFiClient::operator=(const WiFiClient& other)
{
   if (_client)
        _client->unref();
    _client = other._client;
    if (_client)
        _client->ref();
    return *this;
}

int ICACHE_FLASH_ATTR  WiFiClient::connect(const char* host, uint16_t port)
{
    IPAddress remote_addr;
    if (WiFi.hostByName(host, remote_addr))
    {
        return connect(remote_addr, port);
    }
    return 0;
}

int ICACHE_FLASH_ATTR  WiFiClient::connect(IPAddress ip, uint16_t port)
{
    if (_client)
        stop();

    tcp_pcb* pcb = tcp_new();
    if (!pcb)
        return 0;

    ip_addr_t addr;
    addr.addr = ip;
    tcp_arg(pcb, this);
    tcp_err(pcb, &WiFiClient::_s_err);
    tcp_connect(pcb, &addr, port, reinterpret_cast<tcp_connected_fn>(&WiFiClient::_s_connected));

    esp_yield();
    if (_client)
        return 1;

    //  if tcp_error was called, pcb has already been destroyed.
    // tcp_abort(pcb);
    return 0;
}

int8_t ICACHE_FLASH_ATTR WiFiClient::_connected(void* pcb, int8_t err)
{
    tcp_pcb* tpcb = reinterpret_cast<tcp_pcb*>(pcb);
    _client = new ClientContext(tpcb, 0, 0);
    _client->ref();
    esp_schedule();
    return ERR_OK;
}

void ICACHE_FLASH_ATTR WiFiClient::_err(int8_t err)
{
    DEBUGV(":err %d\r\n", err);
    esp_schedule();
}

size_t ICACHE_FLASH_ATTR WiFiClient::write(uint8_t b)
{
    return write(&b, 1);
}

size_t ICACHE_FLASH_ATTR WiFiClient::write(const uint8_t *buf, size_t size)
{
    if (!_client || !size)
    {
        return 0;
    }

    return _client->write(reinterpret_cast<const char*>(buf), size);
}

extern "C" uint32_t esp_micros_at_task_start();

int ICACHE_FLASH_ATTR WiFiClient::available()
{
    static uint32_t lastPollTime = 0;
    if (!_client)
        return 0;

    if (lastPollTime > esp_micros_at_task_start())
        yield();

    lastPollTime = micros();

    int result = _client->getSize();
    return result;
}

int ICACHE_FLASH_ATTR WiFiClient::read()
{
    if (!available())
        return -1;

    return _client->read();
}

int ICACHE_FLASH_ATTR WiFiClient::read(uint8_t* buf, size_t size)
{
    return (int) _client->read(reinterpret_cast<char*>(buf), size);
}

int ICACHE_FLASH_ATTR WiFiClient::peek()
{
    if (!available())
        return -1;

    return _client->peek();
}

void ICACHE_FLASH_ATTR WiFiClient::flush()
{
    if (_client)
        _client->flush();
}

void ICACHE_FLASH_ATTR WiFiClient::stop()
{
    if (!_client)
        return;

    _client->unref();
    _client = 0;
}

uint8_t ICACHE_FLASH_ATTR WiFiClient::connected()
{
    if (!_client)
        return 0;

    return _client->state() == ESTABLISHED || available();
}

uint8_t ICACHE_FLASH_ATTR WiFiClient::status()
{
    if (!_client)
        return CLOSED;
    return _client->state();
}

ICACHE_FLASH_ATTR  WiFiClient::operator bool()
{
    return _client != 0;
}

IPAddress WiFiClient::remoteIP()
{
    if (!_client)
        return IPAddress(0U);

    return IPAddress(_client->getRemoteAddress());
}

uint16_t WiFiClient::remotePort()
{
    if (!_client)
        return 0;

    return _client->getRemotePort();
}

int8_t ICACHE_FLASH_ATTR WiFiClient::_s_connected(void* arg, void* tpcb, int8_t err)
{
    return reinterpret_cast<WiFiClient*>(arg)->_connected(tpcb, err);
}

void ICACHE_FLASH_ATTR WiFiClient::_s_err(void* arg, int8_t err)
{
    reinterpret_cast<WiFiClient*>(arg)->_err(err);
}

<|endoftext|>


<commit_before>// Copyright (c) 2009 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "gfx/blit.h"

#include "base/logging.h"
#include "build/build_config.h"
#include "gfx/point.h"
#include "gfx/rect.h"
#include "skia/ext/platform_canvas.h"
#include "skia/ext/platform_device.h"

#if defined(TOOLKIT_GTK)
#include <cairo/cairo.h>
#endif

#if defined(OS_MACOSX)
#include "base/mac_util.h"
#include "base/scoped_cftyperef.h"
#endif

namespace gfx {

namespace {

// Returns true if the given canvas has any part of itself clipped out or
// any non-identity tranform.
bool HasClipOrTransform(const skia::PlatformCanvas& canvas) {
  if (!canvas.getTotalMatrix().isIdentity())
    return true;

  const SkRegion& clip_region = canvas.getTotalClip();
  if (clip_region.isEmpty() || clip_region.isComplex())
    return true;

  // Now we know the clip is a regular rectangle, make sure it covers the
  // entire canvas.
  const SkBitmap& bitmap = canvas.getTopPlatformDevice().accessBitmap(false);
  const SkIRect& clip_bounds = clip_region.getBounds();
  if (clip_bounds.fLeft != 0 || clip_bounds.fTop != 0 ||
      clip_bounds.fRight != bitmap.width() ||
      clip_bounds.fBottom != bitmap.height())
    return true;

  return false;
}

}  // namespace

void BlitContextToContext(NativeDrawingContext dst_context,
                          const Rect& dst_rect,
                          NativeDrawingContext src_context,
                          const Point& src_origin) {
#if defined(OS_WIN)
  BitBlt(dst_context, dst_rect.x(), dst_rect.y(),
         dst_rect.width(), dst_rect.height(),
         src_context, src_origin.x(), src_origin.y(), SRCCOPY);
#elif defined(OS_MACOSX)
  // Only translations and/or vertical flips in the source context are
  // supported; more complex source context transforms will be ignored.

  // If there is a translation on the source context, we need to account for
  // it ourselves since CGBitmapContextCreateImage will bypass it.
  Rect src_rect(src_origin, dst_rect.size());
  CGAffineTransform transform = CGContextGetCTM(src_context);
  bool flipped = fabs(transform.d + 1) < 0.0001;
  CGFloat delta_y = flipped ? CGBitmapContextGetHeight(src_context) -
                              transform.ty
                            : transform.ty;
  src_rect.Offset(transform.tx, delta_y);

  scoped_cftyperef<CGImageRef>
      src_image(CGBitmapContextCreateImage(src_context));
  scoped_cftyperef<CGImageRef> src_sub_image(
      CGImageCreateWithImageInRect(src_image, src_rect.ToCGRect()));
  CGContextDrawImage(dst_context, dst_rect.ToCGRect(), src_sub_image);
#else  // Linux, BSD, others
  // Only translations in the source context are supported; more complex
  // source context transforms will be ignored.
  cairo_save(dst_context);
  double surface_x = src_origin.x();
  double surface_y = src_origin.y();
  cairo_user_to_device(src_context, &surface_x, &surface_y);
  cairo_set_source_surface(dst_context, cairo_get_target(src_context),
                           dst_rect.x()-surface_x, dst_rect.y()-surface_y);
  cairo_rectangle(dst_context, dst_rect.x(), dst_rect.y(),
                  dst_rect.width(), dst_rect.height());
  cairo_clip(dst_context);
  cairo_paint(dst_context);
  cairo_restore(dst_context);
#endif
}

static NativeDrawingContext GetContextFromCanvas(
    skia::PlatformCanvas *canvas) {
  skia::PlatformDevice& device = canvas->getTopPlatformDevice();
#if defined(OS_WIN)
  return device.getBitmapDC();
#elif defined(OS_MACOSX)
  return device.GetBitmapContext();
#else  // Linux, BSD, others
  return device.beginPlatformPaint();
#endif
}

void BlitContextToCanvas(skia::PlatformCanvas *dst_canvas,
                         const Rect& dst_rect,
                         NativeDrawingContext src_context,
                         const Point& src_origin) {
  BlitContextToContext(GetContextFromCanvas(dst_canvas), dst_rect,
                       src_context, src_origin);
}

void BlitCanvasToContext(NativeDrawingContext dst_context,
                         const Rect& dst_rect,
                         skia::PlatformCanvas *src_canvas,
                         const Point& src_origin) {
  BlitContextToContext(dst_context, dst_rect,
                       GetContextFromCanvas(src_canvas), src_origin);
}

void BlitCanvasToCanvas(skia::PlatformCanvas *dst_canvas,
                        const Rect& dst_rect,
                        skia::PlatformCanvas *src_canvas,
                        const Point& src_origin) {
  BlitContextToContext(GetContextFromCanvas(dst_canvas), dst_rect,
                       GetContextFromCanvas(src_canvas), src_origin);
}

#if defined(OS_WIN)

void ScrollCanvas(skia::PlatformCanvas* canvas,
                  const gfx::Rect& clip,
                  const gfx::Point& amount) {
  DCHECK(!HasClipOrTransform(*canvas));  // Don't support special stuff.
  HDC hdc = canvas->beginPlatformPaint();

  RECT damaged_rect;
  RECT r = clip.ToRECT();
  ScrollDC(hdc, amount.x(), amount.y(), NULL, &r, NULL, &damaged_rect);

  canvas->endPlatformPaint();
}

#elif defined(OS_POSIX)
// Cairo has no nice scroll function so we do our own. On Mac it's possible to
// use platform scroll code, but it's complex so we just use the same path
// here. Either way it will be software-only, so it shouldn't matter much.

void ScrollCanvas(skia::PlatformCanvas* canvas,
                  const gfx::Rect& in_clip,
                  const gfx::Point& amount) {
  DCHECK(!HasClipOrTransform(*canvas));  // Don't support special stuff.
  SkBitmap& bitmap = const_cast<SkBitmap&>(
      canvas->getTopPlatformDevice().accessBitmap(true));
  SkAutoLockPixels lock(bitmap);

  // We expect all coords to be inside the canvas, so clip here.
  gfx::Rect clip = in_clip.Intersect(
      gfx::Rect(0, 0, bitmap.width(), bitmap.height()));

  // Compute the set of pixels we'll actually end up painting.
  gfx::Rect dest_rect = clip;
  dest_rect.Offset(amount);
  dest_rect = dest_rect.Intersect(clip);
  if (dest_rect.size() == gfx::Size())
    return;  // Nothing to do.

  // Compute the source pixels that will map to the dest_rect
  gfx::Rect src_rect = dest_rect;
  src_rect.Offset(-amount.x(), -amount.y());

  size_t row_bytes = dest_rect.width() * 4;
  if (amount.y() > 0) {
    // Data is moving down, copy from the bottom up.
    for (int y = dest_rect.height() - 1; y >= 0; y--) {
      memcpy(bitmap.getAddr32(dest_rect.x(), dest_rect.y() + y),
             bitmap.getAddr32(src_rect.x(), src_rect.y() + y),
             row_bytes);
    }
  } else if (amount.y() < 0) {
    // Data is moving up, copy from the top down.
    for (int y = 0; y < dest_rect.height(); y++) {
      memcpy(bitmap.getAddr32(dest_rect.x(), dest_rect.y() + y),
             bitmap.getAddr32(src_rect.x(), src_rect.y() + y),
             row_bytes);
    }
  } else if (amount.x() != 0) {
    // Horizontal-only scroll. We can do it in either top-to-bottom or bottom-
    // to-top, but have to be careful about the order for copying each row.
    // Fortunately, memmove already handles this for us.
    for (int y = 0; y < dest_rect.height(); y++) {
      memmove(bitmap.getAddr32(dest_rect.x(), dest_rect.y() + y),
              bitmap.getAddr32(src_rect.x(), src_rect.y() + y),
              row_bytes);
    }
  }
}

#endif

}  // namespace gfx
<commit_msg>Fix ChromeOS build by putting back define from previous patch (tried incorrectly to clean this up).<commit_after>// Copyright (c) 2009 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "gfx/blit.h"

#include "base/logging.h"
#include "build/build_config.h"
#include "gfx/point.h"
#include "gfx/rect.h"
#include "skia/ext/platform_canvas.h"
#include "skia/ext/platform_device.h"

#if defined(OS_POSIX) && !defined(OS_MACOSX)
#include <cairo/cairo.h>
#endif

#if defined(OS_MACOSX)
#include "base/mac_util.h"
#include "base/scoped_cftyperef.h"
#endif

namespace gfx {

namespace {

// Returns true if the given canvas has any part of itself clipped out or
// any non-identity tranform.
bool HasClipOrTransform(const skia::PlatformCanvas& canvas) {
  if (!canvas.getTotalMatrix().isIdentity())
    return true;

  const SkRegion& clip_region = canvas.getTotalClip();
  if (clip_region.isEmpty() || clip_region.isComplex())
    return true;

  // Now we know the clip is a regular rectangle, make sure it covers the
  // entire canvas.
  const SkBitmap& bitmap = canvas.getTopPlatformDevice().accessBitmap(false);
  const SkIRect& clip_bounds = clip_region.getBounds();
  if (clip_bounds.fLeft != 0 || clip_bounds.fTop != 0 ||
      clip_bounds.fRight != bitmap.width() ||
      clip_bounds.fBottom != bitmap.height())
    return true;

  return false;
}

}  // namespace

void BlitContextToContext(NativeDrawingContext dst_context,
                          const Rect& dst_rect,
                          NativeDrawingContext src_context,
                          const Point& src_origin) {
#if defined(OS_WIN)
  BitBlt(dst_context, dst_rect.x(), dst_rect.y(),
         dst_rect.width(), dst_rect.height(),
         src_context, src_origin.x(), src_origin.y(), SRCCOPY);
#elif defined(OS_MACOSX)
  // Only translations and/or vertical flips in the source context are
  // supported; more complex source context transforms will be ignored.

  // If there is a translation on the source context, we need to account for
  // it ourselves since CGBitmapContextCreateImage will bypass it.
  Rect src_rect(src_origin, dst_rect.size());
  CGAffineTransform transform = CGContextGetCTM(src_context);
  bool flipped = fabs(transform.d + 1) < 0.0001;
  CGFloat delta_y = flipped ? CGBitmapContextGetHeight(src_context) -
                              transform.ty
                            : transform.ty;
  src_rect.Offset(transform.tx, delta_y);

  scoped_cftyperef<CGImageRef>
      src_image(CGBitmapContextCreateImage(src_context));
  scoped_cftyperef<CGImageRef> src_sub_image(
      CGImageCreateWithImageInRect(src_image, src_rect.ToCGRect()));
  CGContextDrawImage(dst_context, dst_rect.ToCGRect(), src_sub_image);
#else  // Linux, BSD, others
  // Only translations in the source context are supported; more complex
  // source context transforms will be ignored.
  cairo_save(dst_context);
  double surface_x = src_origin.x();
  double surface_y = src_origin.y();
  cairo_user_to_device(src_context, &surface_x, &surface_y);
  cairo_set_source_surface(dst_context, cairo_get_target(src_context),
                           dst_rect.x()-surface_x, dst_rect.y()-surface_y);
  cairo_rectangle(dst_context, dst_rect.x(), dst_rect.y(),
                  dst_rect.width(), dst_rect.height());
  cairo_clip(dst_context);
  cairo_paint(dst_context);
  cairo_restore(dst_context);
#endif
}

static NativeDrawingContext GetContextFromCanvas(
    skia::PlatformCanvas *canvas) {
  skia::PlatformDevice& device = canvas->getTopPlatformDevice();
#if defined(OS_WIN)
  return device.getBitmapDC();
#elif defined(OS_MACOSX)
  return device.GetBitmapContext();
#else  // Linux, BSD, others
  return device.beginPlatformPaint();
#endif
}

void BlitContextToCanvas(skia::PlatformCanvas *dst_canvas,
                         const Rect& dst_rect,
                         NativeDrawingContext src_context,
                         const Point& src_origin) {
  BlitContextToContext(GetContextFromCanvas(dst_canvas), dst_rect,
                       src_context, src_origin);
}

void BlitCanvasToContext(NativeDrawingContext dst_context,
                         const Rect& dst_rect,
                         skia::PlatformCanvas *src_canvas,
                         const Point& src_origin) {
  BlitContextToContext(dst_context, dst_rect,
                       GetContextFromCanvas(src_canvas), src_origin);
}

void BlitCanvasToCanvas(skia::PlatformCanvas *dst_canvas,
                        const Rect& dst_rect,
                        skia::PlatformCanvas *src_canvas,
                        const Point& src_origin) {
  BlitContextToContext(GetContextFromCanvas(dst_canvas), dst_rect,
                       GetContextFromCanvas(src_canvas), src_origin);
}

#if defined(OS_WIN)

void ScrollCanvas(skia::PlatformCanvas* canvas,
                  const gfx::Rect& clip,
                  const gfx::Point& amount) {
  DCHECK(!HasClipOrTransform(*canvas));  // Don't support special stuff.
  HDC hdc = canvas->beginPlatformPaint();

  RECT damaged_rect;
  RECT r = clip.ToRECT();
  ScrollDC(hdc, amount.x(), amount.y(), NULL, &r, NULL, &damaged_rect);

  canvas->endPlatformPaint();
}

#elif defined(OS_POSIX)
// Cairo has no nice scroll function so we do our own. On Mac it's possible to
// use platform scroll code, but it's complex so we just use the same path
// here. Either way it will be software-only, so it shouldn't matter much.

void ScrollCanvas(skia::PlatformCanvas* canvas,
                  const gfx::Rect& in_clip,
                  const gfx::Point& amount) {
  DCHECK(!HasClipOrTransform(*canvas));  // Don't support special stuff.
  SkBitmap& bitmap = const_cast<SkBitmap&>(
      canvas->getTopPlatformDevice().accessBitmap(true));
  SkAutoLockPixels lock(bitmap);

  // We expect all coords to be inside the canvas, so clip here.
  gfx::Rect clip = in_clip.Intersect(
      gfx::Rect(0, 0, bitmap.width(), bitmap.height()));

  // Compute the set of pixels we'll actually end up painting.
  gfx::Rect dest_rect = clip;
  dest_rect.Offset(amount);
  dest_rect = dest_rect.Intersect(clip);
  if (dest_rect.size() == gfx::Size())
    return;  // Nothing to do.

  // Compute the source pixels that will map to the dest_rect
  gfx::Rect src_rect = dest_rect;
  src_rect.Offset(-amount.x(), -amount.y());

  size_t row_bytes = dest_rect.width() * 4;
  if (amount.y() > 0) {
    // Data is moving down, copy from the bottom up.
    for (int y = dest_rect.height() - 1; y >= 0; y--) {
      memcpy(bitmap.getAddr32(dest_rect.x(), dest_rect.y() + y),
             bitmap.getAddr32(src_rect.x(), src_rect.y() + y),
             row_bytes);
    }
  } else if (amount.y() < 0) {
    // Data is moving up, copy from the top down.
    for (int y = 0; y < dest_rect.height(); y++) {
      memcpy(bitmap.getAddr32(dest_rect.x(), dest_rect.y() + y),
             bitmap.getAddr32(src_rect.x(), src_rect.y() + y),
             row_bytes);
    }
  } else if (amount.x() != 0) {
    // Horizontal-only scroll. We can do it in either top-to-bottom or bottom-
    // to-top, but have to be careful about the order for copying each row.
    // Fortunately, memmove already handles this for us.
    for (int y = 0; y < dest_rect.height(); y++) {
      memmove(bitmap.getAddr32(dest_rect.x(), dest_rect.y() + y),
              bitmap.getAddr32(src_rect.x(), src_rect.y() + y),
              row_bytes);
    }
  }
}

#endif

}  // namespace gfx
<|endoftext|>


<commit_before>/****************************************************************************
**
** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/
**
** This file is part of the Qt Compositor.
**
** $QT_BEGIN_LICENSE:BSD$
** You may use this file under the terms of the BSD license as follows:
**
** "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 Nokia Corporation and its Subsidiary(-ies) 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."
**
** $QT_END_LICENSE$
**
****************************************************************************/

#include "xcompositeglxintegration.h"

#include "waylandobject.h"
#include "wayland_wrapper/wlcompositor.h"
#include "wayland-xcomposite-server-protocol.h"

#include <QtGui/QPlatformNativeInterface>
#include <QtGui/QOpenGLContext>

#include "xcompositebuffer.h"
#include "xcompositehandler.h"
#include <X11/extensions/Xcomposite.h>

#include <QtCore/QDebug>

QVector<int> qglx_buildSpec()
{
    QVector<int> spec(48);
    int i = 0;

    spec[i++] = GLX_LEVEL;
    spec[i++] = 0;
    spec[i++] = GLX_DRAWABLE_TYPE; spec[i++] = GLX_PIXMAP_BIT | GLX_WINDOW_BIT;
    spec[i++] = GLX_BIND_TO_TEXTURE_TARGETS_EXT; spec[i++] = GLX_TEXTURE_2D_BIT_EXT;
    spec[i++] = GLX_BIND_TO_TEXTURE_RGB_EXT; spec[i++] = TRUE;

    spec[i++] = 0;
    return spec;
}

struct wl_xcomposite_interface XCompositeHandler::xcomposite_interface = {
    XCompositeHandler::create_buffer
};

GraphicsHardwareIntegration *GraphicsHardwareIntegration::createGraphicsHardwareIntegration(WaylandCompositor *compositor)
{
    return new XCompositeGLXIntegration(compositor);
}

XCompositeGLXIntegration::XCompositeGLXIntegration(WaylandCompositor *compositor)
    : GraphicsHardwareIntegration(compositor)
    , mDisplay(0)
    , mHandler(0)
{
    QPlatformNativeInterface *nativeInterface = QGuiApplicationPrivate::platformIntegration()->nativeInterface();
    if (nativeInterface) {
        mDisplay = static_cast<Display *>(nativeInterface->nativeResourceForWindow("Display",m_compositor->window()));
        if (!mDisplay)
            qFatal("could not retireve Display from platform integration");
    } else {
        qFatal("Platform integration doesn't have native interface");
    }
    mScreen = XDefaultScreen(mDisplay);
}

XCompositeGLXIntegration::~XCompositeGLXIntegration()
{
    delete mHandler;
}

void XCompositeGLXIntegration::initializeHardware(Wayland::Display *waylandDisplay)
{
    mHandler = new XCompositeHandler(m_compositor->handle(),mDisplay,m_compositor->window());
    wl_display_add_global(waylandDisplay->handle(),&wl_xcomposite_interface,mHandler,XCompositeHandler::xcomposite_bind_func);

    QOpenGLContext *glContext = new QOpenGLContext();
    glContext->create();

    m_glxBindTexImageEXT = reinterpret_cast<PFNGLXBINDTEXIMAGEEXTPROC>(glContext->getProcAddress("glXBindTexImageEXT"));
    if (!m_glxBindTexImageEXT) {
        qDebug() << "Did not find glxBindTexImageExt, everything will FAIL!";
    }
    m_glxReleaseTexImageEXT = reinterpret_cast<PFNGLXRELEASETEXIMAGEEXTPROC>(glContext->getProcAddress("glXReleaseTexImageEXT"));
    if (!m_glxReleaseTexImageEXT) {
        qDebug() << "Did not find glxReleaseTexImageExt";
    }

    delete glContext;
}

GLuint XCompositeGLXIntegration::createTextureFromBuffer(wl_buffer *buffer, QOpenGLContext *)
{
    XCompositeBuffer *compositorBuffer = Wayland::wayland_cast<XCompositeBuffer *>(buffer);
    Pixmap pixmap = XCompositeNameWindowPixmap(mDisplay, compositorBuffer->window());

    QVector<int> glxConfigSpec = qglx_buildSpec();
    int numberOfConfigs;
    GLXFBConfig *configs = glXChooseFBConfig(mDisplay,mScreen,glxConfigSpec.constData(),&numberOfConfigs);

    QVector<int> attribList;
    attribList.append(GLX_TEXTURE_FORMAT_EXT);
    attribList.append(GLX_TEXTURE_FORMAT_RGB_EXT);
    attribList.append(GLX_TEXTURE_TARGET_EXT);
    attribList.append(GLX_TEXTURE_2D_EXT);
    attribList.append(0);
    GLXPixmap glxPixmap = glXCreatePixmap(mDisplay,*configs,pixmap,attribList.constData());

    uint inverted = 0;
    glXQueryDrawable(mDisplay, glxPixmap, GLX_Y_INVERTED_EXT,&inverted);
    compositorBuffer->setInvertedY(!inverted);

    XFree(configs);

    GLuint textureId;
    glGenTextures(1,&textureId);
    glBindTexture(GL_TEXTURE_2D, textureId);
    m_glxBindTexImageEXT(mDisplay,glxPixmap,GLX_FRONT_EXT, 0);
    //Do we need to change the api so that we do bind and release in the painevent?
    //The specification states that when deleting the texture the color buffer is deleted
//    m_glxReleaseTexImageEXT(mDisplay,glxPixmap,GLX_FRONT_EXT);
    return textureId;
}

bool XCompositeGLXIntegration::isYInverted(wl_buffer *buffer) const
{
    XCompositeBuffer *compositorBuffer = Wayland::wayland_cast<XCompositeBuffer *>(buffer);
    return compositorBuffer->isYInverted();
}
<commit_msg>Make glx backend compiling again after qtbase broke the includes<commit_after>/****************************************************************************
**
** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/
**
** This file is part of the Qt Compositor.
**
** $QT_BEGIN_LICENSE:BSD$
** You may use this file under the terms of the BSD license as follows:
**
** "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 Nokia Corporation and its Subsidiary(-ies) 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."
**
** $QT_END_LICENSE$
**
****************************************************************************/

#include "xcompositeglxintegration.h"

#include "waylandobject.h"
#include "wayland_wrapper/wlcompositor.h"
#include "wayland-xcomposite-server-protocol.h"

#include <QtGui/QPlatformNativeInterface>
#include <QtGui/QPlatformIntegration>
#include <QtGui/QOpenGLContext>

#include "xcompositebuffer.h"
#include "xcompositehandler.h"
#include <X11/extensions/Xcomposite.h>

#include <QtCore/QDebug>

QVector<int> qglx_buildSpec()
{
    QVector<int> spec(48);
    int i = 0;

    spec[i++] = GLX_LEVEL;
    spec[i++] = 0;
    spec[i++] = GLX_DRAWABLE_TYPE; spec[i++] = GLX_PIXMAP_BIT | GLX_WINDOW_BIT;
    spec[i++] = GLX_BIND_TO_TEXTURE_TARGETS_EXT; spec[i++] = GLX_TEXTURE_2D_BIT_EXT;
    spec[i++] = GLX_BIND_TO_TEXTURE_RGB_EXT; spec[i++] = TRUE;

    spec[i++] = 0;
    return spec;
}

struct wl_xcomposite_interface XCompositeHandler::xcomposite_interface = {
    XCompositeHandler::create_buffer
};

GraphicsHardwareIntegration *GraphicsHardwareIntegration::createGraphicsHardwareIntegration(WaylandCompositor *compositor)
{
    return new XCompositeGLXIntegration(compositor);
}

XCompositeGLXIntegration::XCompositeGLXIntegration(WaylandCompositor *compositor)
    : GraphicsHardwareIntegration(compositor)
    , mDisplay(0)
    , mHandler(0)
{
    QPlatformNativeInterface *nativeInterface = QGuiApplicationPrivate::platformIntegration()->nativeInterface();
    if (nativeInterface) {
        mDisplay = static_cast<Display *>(nativeInterface->nativeResourceForWindow("Display",m_compositor->window()));
        if (!mDisplay)
            qFatal("could not retireve Display from platform integration");
    } else {
        qFatal("Platform integration doesn't have native interface");
    }
    mScreen = XDefaultScreen(mDisplay);
}

XCompositeGLXIntegration::~XCompositeGLXIntegration()
{
    delete mHandler;
}

void XCompositeGLXIntegration::initializeHardware(Wayland::Display *waylandDisplay)
{
    mHandler = new XCompositeHandler(m_compositor->handle(),mDisplay,m_compositor->window());
    wl_display_add_global(waylandDisplay->handle(),&wl_xcomposite_interface,mHandler,XCompositeHandler::xcomposite_bind_func);

    QOpenGLContext *glContext = new QOpenGLContext();
    glContext->create();

    m_glxBindTexImageEXT = reinterpret_cast<PFNGLXBINDTEXIMAGEEXTPROC>(glContext->getProcAddress("glXBindTexImageEXT"));
    if (!m_glxBindTexImageEXT) {
        qDebug() << "Did not find glxBindTexImageExt, everything will FAIL!";
    }
    m_glxReleaseTexImageEXT = reinterpret_cast<PFNGLXRELEASETEXIMAGEEXTPROC>(glContext->getProcAddress("glXReleaseTexImageEXT"));
    if (!m_glxReleaseTexImageEXT) {
        qDebug() << "Did not find glxReleaseTexImageExt";
    }

    delete glContext;
}

GLuint XCompositeGLXIntegration::createTextureFromBuffer(wl_buffer *buffer, QOpenGLContext *)
{
    XCompositeBuffer *compositorBuffer = Wayland::wayland_cast<XCompositeBuffer *>(buffer);
    Pixmap pixmap = XCompositeNameWindowPixmap(mDisplay, compositorBuffer->window());

    QVector<int> glxConfigSpec = qglx_buildSpec();
    int numberOfConfigs;
    GLXFBConfig *configs = glXChooseFBConfig(mDisplay,mScreen,glxConfigSpec.constData(),&numberOfConfigs);

    QVector<int> attribList;
    attribList.append(GLX_TEXTURE_FORMAT_EXT);
    attribList.append(GLX_TEXTURE_FORMAT_RGB_EXT);
    attribList.append(GLX_TEXTURE_TARGET_EXT);
    attribList.append(GLX_TEXTURE_2D_EXT);
    attribList.append(0);
    GLXPixmap glxPixmap = glXCreatePixmap(mDisplay,*configs,pixmap,attribList.constData());

    uint inverted = 0;
    glXQueryDrawable(mDisplay, glxPixmap, GLX_Y_INVERTED_EXT,&inverted);
    compositorBuffer->setInvertedY(!inverted);

    XFree(configs);

    GLuint textureId;
    glGenTextures(1,&textureId);
    glBindTexture(GL_TEXTURE_2D, textureId);
    m_glxBindTexImageEXT(mDisplay,glxPixmap,GLX_FRONT_EXT, 0);
    //Do we need to change the api so that we do bind and release in the painevent?
    //The specification states that when deleting the texture the color buffer is deleted
//    m_glxReleaseTexImageEXT(mDisplay,glxPixmap,GLX_FRONT_EXT);
    return textureId;
}

bool XCompositeGLXIntegration::isYInverted(wl_buffer *buffer) const
{
    XCompositeBuffer *compositorBuffer = Wayland::wayland_cast<XCompositeBuffer *>(buffer);
    return compositorBuffer->isYInverted();
}
<|endoftext|>


<commit_before>/* -*- Mode: C++; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */
#ifndef STORED_VALUE_H
#define STORED_VALUE_H 1

#include "locks.hh"

extern "C" {
    extern rel_time_t (*ep_current_time)();
}

// Forward declaration for StoredValue
class HashTable;

class StoredValue {
public:
    StoredValue(const Item &itm, StoredValue *n) :
        key(itm.getKey()), value(const_cast<Item&>(itm).getData(), itm.getNBytes()),
        flags(itm.getFlags()), exptime(itm.getExptime()), dirtied(0), next(n),
        cas(itm.getCas())
    {
        markDirty();
    }

    StoredValue(const Item &itm, StoredValue *n, bool setDirty) :
        key(itm.getKey()), value(const_cast<Item&>(itm).getData(), itm.getNBytes()),
        flags(itm.getFlags()), exptime(itm.getExptime()), dirtied(0), next(n),
        cas(itm.getCas())
    {
        if (setDirty) {
            markDirty();
        } else {
            markClean(NULL, NULL);
        }
    }

    ~StoredValue() {
    }
    void markDirty() {
        data_age = ep_current_time();
        if (!isDirty()) {
            dirtied = data_age;
        }
    }

    void reDirty(rel_time_t dirtyAge, rel_time_t dataAge) {
        data_age = dataAge;
        dirtied = dirtyAge;
    }

    // returns time this object was dirtied.
    void markClean(rel_time_t *dirtyAge, rel_time_t *dataAge) {
        if (dirtyAge) {
            *dirtyAge = dirtied;
        }
        if (dataAge) {
            *dataAge = data_age;
        }
        dirtied = 0;
        data_age = 0;
    }

    bool isDirty() const {
        return dirtied != 0;
    }

    bool isClean() const {
        return dirtied == 0;
    }

    const std::string &getKey() const {
        return key;
    }

    const std::string &getValue() const {
        return value;
    }

    rel_time_t getExptime() const {
        return exptime;
    }

    uint32_t getFlags() const {
        return flags;
    }

    void setValue(const char *v, const size_t nv,
                  uint32_t newFlags, rel_time_t newExp, uint64_t theCas) {
        cas = theCas;
        flags = newFlags;
        exptime = newExp;
        value.assign(v, nv);
        markDirty();
    }

    uint64_t getCas() const {
        return cas;
    }

private:

    friend class HashTable;

    std::string key;
    std::string value;
    uint32_t flags;
    rel_time_t exptime;
    rel_time_t dirtied;
    rel_time_t data_age;
    StoredValue *next;
    uint64_t cas;
    DISALLOW_COPY_AND_ASSIGN(StoredValue);
};

typedef enum {
    NOT_FOUND, INVALID_CAS, WAS_CLEAN, WAS_DIRTY
} mutation_type_t;

class HashTableVisitor {
public:
    virtual ~HashTableVisitor() {}
    virtual void visit(StoredValue *v) = 0;
};

class HashTable {
public:

    // Construct with number of buckets and locks.
    HashTable(size_t s = 196613, size_t l = 193) {
        size = s;
        n_locks = l;
        active = true;
        values = (StoredValue**)calloc(s, sizeof(StoredValue**));
        mutexes = new Mutex[l];
    }

    ~HashTable() {
        clear();
        delete []mutexes;
        free(values);
    }

    void clear() {
        assert(active);
        for (int i = 0; i < (int)size; i++) {
            LockHolder lh(getMutex(i));
            while (values[i]) {
                StoredValue *v = values[i];
                values[i] = v->next;
                delete v;
            }
        }
    }

    StoredValue *find(std::string &key) {
        assert(active);
        int bucket_num = bucket(key);
        LockHolder lh(getMutex(bucket_num));
        return unlocked_find(key, bucket_num);
    }

    mutation_type_t set(const Item &val, bool preserveCas = false) {
        assert(active);
        mutation_type_t rv = NOT_FOUND;
        int bucket_num = bucket(val.getKey());
        LockHolder lh(getMutex(bucket_num));
        StoredValue *v = unlocked_find(val.getKey(), bucket_num);
        Item &itm = const_cast<Item&>(val);
        if (v) {
            if (val.getCas() != 0 && val.getCas() != v->getCas()) {
                return INVALID_CAS;
            }
            if (!preserveCas) {
                itm.setCas();
            }
            rv = v->isClean() ? WAS_CLEAN : WAS_DIRTY;
            v->setValue(itm.getData(), itm.getNBytes(),
                        itm.getFlags(), itm.getExptime(),
                        itm.getCas());
        } else {
            if (!preserveCas) {
                if (itm.getCas() != 0) {
                    return INVALID_CAS;
                }
                itm.setCas();
            }

            v = new StoredValue(itm, values[bucket_num]);
            values[bucket_num] = v;
        }
        return rv;
    }

    bool add(const Item &val, bool isDirty, bool preserveCas = false) {
        assert(active);
        int bucket_num = bucket(val.getKey());
        LockHolder lh(getMutex(bucket_num));
        StoredValue *v = unlocked_find(val.getKey(), bucket_num);
        if (v) {
            return false;
        } else {
            Item &itm = const_cast<Item&>(val);
            if (!preserveCas) {
                itm.setCas();
            }
            v = new StoredValue(itm, values[bucket_num], isDirty);
            values[bucket_num] = v;
        }

        return true;
    }

    bool add(const Item &val) {
        return add(val, true);
    }

    StoredValue *unlocked_find(const std::string &key, int bucket_num) {
        StoredValue *v = values[bucket_num];
        while (v) {
            if (key.compare(v->key) == 0) {
                return v;
            }
            v = v->next;
        }
        return NULL;
    }

    inline int bucket(const std::string &key) {
        assert(active);
        int h=5381;
        int i=0;
        const char *str = key.c_str();

        for(i=0; str[i] != 0x00; i++) {
            h = ((h << 5) + h) ^ str[i];
        }

        return abs(h) % (int)size;
    }

    // Get the mutex for a bucket (for doing your own lock management)
    inline Mutex &getMutex(int bucket_num) {
        assert(active);
        assert(bucket_num < (int)size);
        assert(bucket_num >= 0);
        int lock_num = bucket_num % (int)n_locks;
        assert(lock_num < (int)n_locks);
        assert(lock_num >= 0);
        return mutexes[lock_num];
    }

    // True if it existed
    bool del(const std::string &key) {
        assert(active);
        int bucket_num = bucket(key);
        LockHolder lh(getMutex(bucket_num));

        StoredValue *v = values[bucket_num];

        // Special case empty bucket.
        if (!v) {
            return false;
        }

        // Special case the first one
        if (key.compare(v->key) == 0) {
            values[bucket_num] = v->next;
            delete v;
            return true;
        }

        while (v->next) {
            if (key.compare(v->next->key) == 0) {
                StoredValue *tmp = v->next;
                v->next = v->next->next;
                delete tmp;
                return true;
            } else {
                v = v->next;
            }
        }

        return false;
    }

    void visit(HashTableVisitor &visitor) {
        for (int i = 0; i < (int)size; i++) {
            LockHolder lh(getMutex(i));
            StoredValue *v = values[i];
            while (v) {
                visitor.visit(v);
                v = v->next;
            }
        }
    }

private:
    size_t            size;
    size_t            n_locks;
    bool              active;
    StoredValue     **values;
    Mutex            *mutexes;

    DISALLOW_COPY_AND_ASSIGN(HashTable);
};

#endif /* STORED_VALUE_H */
<commit_msg>Remove preserveCas argument to set and add.<commit_after>/* -*- Mode: C++; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */
#ifndef STORED_VALUE_H
#define STORED_VALUE_H 1

#include "locks.hh"

extern "C" {
    extern rel_time_t (*ep_current_time)();
}

// Forward declaration for StoredValue
class HashTable;

class StoredValue {
public:
    StoredValue(const Item &itm, StoredValue *n) :
        key(itm.getKey()), value(const_cast<Item&>(itm).getData(), itm.getNBytes()),
        flags(itm.getFlags()), exptime(itm.getExptime()), dirtied(0), next(n),
        cas(itm.getCas())
    {
        markDirty();
    }

    StoredValue(const Item &itm, StoredValue *n, bool setDirty) :
        key(itm.getKey()), value(const_cast<Item&>(itm).getData(), itm.getNBytes()),
        flags(itm.getFlags()), exptime(itm.getExptime()), dirtied(0), next(n),
        cas(itm.getCas())
    {
        if (setDirty) {
            markDirty();
        } else {
            markClean(NULL, NULL);
        }
    }

    ~StoredValue() {
    }
    void markDirty() {
        data_age = ep_current_time();
        if (!isDirty()) {
            dirtied = data_age;
        }
    }

    void reDirty(rel_time_t dirtyAge, rel_time_t dataAge) {
        data_age = dataAge;
        dirtied = dirtyAge;
    }

    // returns time this object was dirtied.
    void markClean(rel_time_t *dirtyAge, rel_time_t *dataAge) {
        if (dirtyAge) {
            *dirtyAge = dirtied;
        }
        if (dataAge) {
            *dataAge = data_age;
        }
        dirtied = 0;
        data_age = 0;
    }

    bool isDirty() const {
        return dirtied != 0;
    }

    bool isClean() const {
        return dirtied == 0;
    }

    const std::string &getKey() const {
        return key;
    }

    const std::string &getValue() const {
        return value;
    }

    rel_time_t getExptime() const {
        return exptime;
    }

    uint32_t getFlags() const {
        return flags;
    }

    void setValue(const char *v, const size_t nv,
                  uint32_t newFlags, rel_time_t newExp, uint64_t theCas) {
        cas = theCas;
        flags = newFlags;
        exptime = newExp;
        value.assign(v, nv);
        markDirty();
    }

    uint64_t getCas() const {
        return cas;
    }

private:

    friend class HashTable;

    std::string key;
    std::string value;
    uint32_t flags;
    rel_time_t exptime;
    rel_time_t dirtied;
    rel_time_t data_age;
    StoredValue *next;
    uint64_t cas;
    DISALLOW_COPY_AND_ASSIGN(StoredValue);
};

typedef enum {
    NOT_FOUND, INVALID_CAS, WAS_CLEAN, WAS_DIRTY
} mutation_type_t;

class HashTableVisitor {
public:
    virtual ~HashTableVisitor() {}
    virtual void visit(StoredValue *v) = 0;
};

class HashTable {
public:

    // Construct with number of buckets and locks.
    HashTable(size_t s = 196613, size_t l = 193) {
        size = s;
        n_locks = l;
        active = true;
        values = (StoredValue**)calloc(s, sizeof(StoredValue**));
        mutexes = new Mutex[l];
    }

    ~HashTable() {
        clear();
        delete []mutexes;
        free(values);
    }

    void clear() {
        assert(active);
        for (int i = 0; i < (int)size; i++) {
            LockHolder lh(getMutex(i));
            while (values[i]) {
                StoredValue *v = values[i];
                values[i] = v->next;
                delete v;
            }
        }
    }

    StoredValue *find(std::string &key) {
        assert(active);
        int bucket_num = bucket(key);
        LockHolder lh(getMutex(bucket_num));
        return unlocked_find(key, bucket_num);
    }

    mutation_type_t set(const Item &val) {
        assert(active);
        mutation_type_t rv = NOT_FOUND;
        int bucket_num = bucket(val.getKey());
        LockHolder lh(getMutex(bucket_num));
        StoredValue *v = unlocked_find(val.getKey(), bucket_num);
        Item &itm = const_cast<Item&>(val);
        if (v) {
            if (val.getCas() != 0 && val.getCas() != v->getCas()) {
                return INVALID_CAS;
            }
            itm.setCas();
            rv = v->isClean() ? WAS_CLEAN : WAS_DIRTY;
            v->setValue(itm.getData(), itm.getNBytes(),
                        itm.getFlags(), itm.getExptime(),
                        itm.getCas());
        } else {
            if (itm.getCas() != 0) {
                return INVALID_CAS;
            }

            v = new StoredValue(itm, values[bucket_num]);
            values[bucket_num] = v;
        }
        return rv;
    }

    bool add(const Item &val, bool isDirty = true) {
        assert(active);
        int bucket_num = bucket(val.getKey());
        LockHolder lh(getMutex(bucket_num));
        StoredValue *v = unlocked_find(val.getKey(), bucket_num);
        if (v) {
            return false;
        } else {
            Item &itm = const_cast<Item&>(val);
            itm.setCas();
            v = new StoredValue(itm, values[bucket_num], isDirty);
            values[bucket_num] = v;
        }

        return true;
    }

    StoredValue *unlocked_find(const std::string &key, int bucket_num) {
        StoredValue *v = values[bucket_num];
        while (v) {
            if (key.compare(v->key) == 0) {
                return v;
            }
            v = v->next;
        }
        return NULL;
    }

    inline int bucket(const std::string &key) {
        assert(active);
        int h=5381;
        int i=0;
        const char *str = key.c_str();

        for(i=0; str[i] != 0x00; i++) {
            h = ((h << 5) + h) ^ str[i];
        }

        return abs(h) % (int)size;
    }

    // Get the mutex for a bucket (for doing your own lock management)
    inline Mutex &getMutex(int bucket_num) {
        assert(active);
        assert(bucket_num < (int)size);
        assert(bucket_num >= 0);
        int lock_num = bucket_num % (int)n_locks;
        assert(lock_num < (int)n_locks);
        assert(lock_num >= 0);
        return mutexes[lock_num];
    }

    // True if it existed
    bool del(const std::string &key) {
        assert(active);
        int bucket_num = bucket(key);
        LockHolder lh(getMutex(bucket_num));

        StoredValue *v = values[bucket_num];

        // Special case empty bucket.
        if (!v) {
            return false;
        }

        // Special case the first one
        if (key.compare(v->key) == 0) {
            values[bucket_num] = v->next;
            delete v;
            return true;
        }

        while (v->next) {
            if (key.compare(v->next->key) == 0) {
                StoredValue *tmp = v->next;
                v->next = v->next->next;
                delete tmp;
                return true;
            } else {
                v = v->next;
            }
        }

        return false;
    }

    void visit(HashTableVisitor &visitor) {
        for (int i = 0; i < (int)size; i++) {
            LockHolder lh(getMutex(i));
            StoredValue *v = values[i];
            while (v) {
                visitor.visit(v);
                v = v->next;
            }
        }
    }

private:
    size_t            size;
    size_t            n_locks;
    bool              active;
    StoredValue     **values;
    Mutex            *mutexes;

    DISALLOW_COPY_AND_ASSIGN(HashTable);
};

#endif /* STORED_VALUE_H */
<|endoftext|>


<commit_before>//
// This file is part of the Marble Virtual Globe.
//
// This program is free software licensed under the GNU LGPL. You can
// find a copy of this license in LICENSE.txt in the top directory of
// the source code.
//
// Copyright 2011      Konrad Enzensberger <e.konrad@mpegcode.com>
// Copyright 2011      Dennis Nienhüser <earthwings@gentoo.org>
//

#include "FileReaderPositionProviderPlugin.h"

#include <QtCore/QTimer>
#include <QtCore/QFile>

#include "GeoDataCoordinates.h"
#include "GeoDataParser.h"
#include "GeoDataDocument.h"
#include "GeoDataTypes.h"
#include "GeoDataData.h"
#include "GeoDataFolder.h"
#include "GeoDataPlacemark.h"
#include "GeoDataLineString.h"
#include "GeoDataLinearRing.h"
#include "GeoDataIconStyle.h"
#include "MarbleDirs.h"
#include "MarbleDebug.h"

namespace Marble
{

class FileReaderPositionProviderPluginPrivate
{
public:
    FileReaderPositionProviderPluginPrivate();
    ~FileReaderPositionProviderPluginPrivate();

    void importKmlFromData();
    void createSimulationPlacemarks( GeoDataContainer *container );

    int   m_currentIndex;
    PositionProviderStatus m_status;
    GeoDataLineString m_lineString;
};

FileReaderPositionProviderPluginPrivate::FileReaderPositionProviderPluginPrivate() :
    m_currentIndex( 0 ), m_status( PositionProviderStatusAcquiring )
{
    // nothing to do
}

FileReaderPositionProviderPluginPrivate::~FileReaderPositionProviderPluginPrivate()
{
    m_lineString.clear();
}

void FileReaderPositionProviderPluginPrivate::importKmlFromData()
{
    GeoDataParser parser( GeoData_KML );

    QString filename = MarbleDirs::path( "routing" );
    filename += "/route.kml";
    QFile file( filename );
    if ( !file.exists() ) {
        mDebug() << "The GPS file reader plugin expects routing/route.kml to exist in the local marble dir.";
        mDebug() << "Create a route and exit Marble to have it created automatically.";
        return;
    }

    // Open file in right mode
    file.open( QIODevice::ReadOnly );

    if ( !parser.read( &file ) ) {
        mDebug() << "Could not import kml file. No position updates will happen.";
        return;
    }

    GeoDocument* doc = parser.releaseDocument();
    if ( doc ) {
        GeoDataDocument* document = dynamic_cast<GeoDataDocument*>( doc );
        if ( document && document->size() > 0 ) {
            document->setDocumentRole( UserDocument );
            document->setFileName( filename );
            createSimulationPlacemarks( dynamic_cast<GeoDataDocument*>( &document->last() ) );
        }
    }

    file.close();
}

void FileReaderPositionProviderPluginPrivate::createSimulationPlacemarks( GeoDataContainer *container )
{
    if ( !container ) {
        return;
    }

    m_lineString.clear();

    QVector<GeoDataFolder*> folders = container->folderList();
    foreach( const GeoDataFolder *folder, folders ) {
        foreach( const GeoDataPlacemark *placemark, folder->placemarkList() ) {
            GeoDataGeometry* geometry = placemark->geometry();
            GeoDataLineString* lineString = dynamic_cast<GeoDataLineString*>( geometry );
            if ( lineString ) {
                m_lineString = *lineString;
                return;
            }
        }
    }

    foreach( const GeoDataPlacemark *placemark, container->placemarkList() ) {
        GeoDataGeometry* geometry = placemark->geometry();
        GeoDataLineString* lineString = dynamic_cast<GeoDataLineString*>( geometry );
        if ( lineString ) {
            m_lineString = *lineString;
            return;
        }
    }
}

QString FileReaderPositionProviderPlugin::name() const
{
    return tr( "File Reader Position ProviderPlugin" );
}

QString FileReaderPositionProviderPlugin::nameId() const
{
    return "FileReaderPositionProviderPlugin";
}

QString FileReaderPositionProviderPlugin::guiString() const
{
    return tr( "GPS Position Simulation (File Reader)" );
}

QString FileReaderPositionProviderPlugin::version() const
{
    return "1.0";
}

QString FileReaderPositionProviderPlugin::description() const
{
    return tr( "Reports the GPS position from a previously calculated route." );
}

QString FileReaderPositionProviderPlugin::copyrightYears() const
{
    return "2011";
}

QList<PluginAuthor> FileReaderPositionProviderPlugin::pluginAuthors() const
{
    return QList<PluginAuthor>()
            << PluginAuthor( "Konrad Enzensberger", "e.konrad@mpegcode.com" )
            << PluginAuthor( QString::fromUtf8( "Dennis Nienhüser" ), "earthwings@gentoo.org" );
}

QIcon FileReaderPositionProviderPlugin::icon() const
{
    return QIcon();
}

PositionProviderPlugin* FileReaderPositionProviderPlugin::newInstance() const
{
    return new FileReaderPositionProviderPlugin;
}

PositionProviderStatus FileReaderPositionProviderPlugin::status() const
{
    return d->m_status;
}

GeoDataCoordinates FileReaderPositionProviderPlugin::position() const
{
    return d->m_lineString.at( d->m_currentIndex );
}

GeoDataAccuracy FileReaderPositionProviderPlugin::accuracy() const
{
    GeoDataAccuracy result;

    // faked values
    result.level = GeoDataAccuracy::Detailed;
    result.horizontal = 10.0;
    result.vertical = 10.0;

    return result;
}

FileReaderPositionProviderPlugin::FileReaderPositionProviderPlugin() :
    d( new FileReaderPositionProviderPluginPrivate )
{
    // nothing to do
}

FileReaderPositionProviderPlugin::~FileReaderPositionProviderPlugin()
{
    delete d;
}

void FileReaderPositionProviderPlugin::initialize()
{
    d->m_status = PositionProviderStatusAcquiring;

    d->m_currentIndex = 0;
    d->importKmlFromData();

    QTimer::singleShot( 1000, this, SLOT( update() ) );
}

bool FileReaderPositionProviderPlugin::isInitialized() const
{
    return ( d->m_lineString.size() > 0 );
}

qreal FileReaderPositionProviderPlugin::speed() const
{
    /** @todo: calculate speed */
    return 0.0;
}

qreal FileReaderPositionProviderPlugin::direction() const
{
    /** @todo: calculate direction */
    return 0.0;
}

QDateTime FileReaderPositionProviderPlugin::timestamp() const
{
    return QDateTime::currentDateTime();
}

void FileReaderPositionProviderPlugin::update()
{
    PositionProviderStatus newStatus = PositionProviderStatusAvailable;

    if ( d->m_currentIndex >= 0 && d->m_currentIndex < d->m_lineString.size() ) {
        if ( newStatus != d->m_status ) {
            d->m_status = newStatus;
            emit statusChanged( newStatus );
        }

        if ( newStatus == PositionProviderStatusAvailable ) {
            emit positionChanged( position(), accuracy() );
        }

        ++d->m_currentIndex;

        if( d->m_currentIndex < d->m_lineString.size() ) {
            QTimer::singleShot( 1000, this, SLOT( update() ) );
        }
    }

    if ( !d->m_lineString.isEmpty() && d->m_currentIndex >= d->m_lineString.size() ) {
        // Repeat from start
        d->m_currentIndex = 0;
        update();
    }
}

} // namespace Marble

Q_EXPORT_PLUGIN2( FileReaderPositionProviderPlugin, Marble::FileReaderPositionProviderPlugin )

#include "FileReaderPositionProviderPlugin.moc"
<commit_msg>have FileReaderPositionProviderPlugin make use of AlternativeRoutingModel's current route<commit_after>//
// This file is part of the Marble Virtual Globe.
//
// This program is free software licensed under the GNU LGPL. You can
// find a copy of this license in LICENSE.txt in the top directory of
// the source code.
//
// Copyright 2011      Konrad Enzensberger <e.konrad@mpegcode.com>
// Copyright 2011      Dennis Nienhüser <earthwings@gentoo.org>
// Copyright 2012      Bernhard Beschow <bbeschow@cs.tu-berlin.de>
//

#include "FileReaderPositionProviderPlugin.h"

#include <QtCore/QTimer>

#include "GeoDataCoordinates.h"
#include "GeoDataDocument.h"
#include "GeoDataTypes.h"
#include "GeoDataData.h"
#include "GeoDataFolder.h"
#include "GeoDataPlacemark.h"
#include "GeoDataLineString.h"
#include "GeoDataLinearRing.h"
#include "GeoDataIconStyle.h"
#include "MarbleDirs.h"
#include "MarbleDebug.h"
#include "MarbleModel.h"
#include "routing/AlternativeRoutesModel.h"
#include "routing/RoutingManager.h"

namespace Marble
{

class FileReaderPositionProviderPluginPrivate
{
public:
    FileReaderPositionProviderPluginPrivate();
    ~FileReaderPositionProviderPluginPrivate();

    int   m_currentIndex;
    PositionProviderStatus m_status;
    GeoDataLineString m_lineString;
};

FileReaderPositionProviderPluginPrivate::FileReaderPositionProviderPluginPrivate() :
    m_currentIndex( -1 ),
    m_status( PositionProviderStatusUnavailable )
{
    // nothing to do
}

FileReaderPositionProviderPluginPrivate::~FileReaderPositionProviderPluginPrivate()
{
    m_lineString.clear();
}

QString FileReaderPositionProviderPlugin::name() const
{
    return tr( "File Reader Position ProviderPlugin" );
}

QString FileReaderPositionProviderPlugin::nameId() const
{
    return "FileReaderPositionProviderPlugin";
}

QString FileReaderPositionProviderPlugin::guiString() const
{
    return tr( "GPS Position Simulation (File Reader)" );
}

QString FileReaderPositionProviderPlugin::version() const
{
    return "1.0";
}

QString FileReaderPositionProviderPlugin::description() const
{
    return tr( "Reports the GPS position from a previously calculated route." );
}

QString FileReaderPositionProviderPlugin::copyrightYears() const
{
    return "2011";
}

QList<PluginAuthor> FileReaderPositionProviderPlugin::pluginAuthors() const
{
    return QList<PluginAuthor>()
            << PluginAuthor( "Konrad Enzensberger", "e.konrad@mpegcode.com" )
            << PluginAuthor( QString::fromUtf8( "Dennis Nienhüser" ), "earthwings@gentoo.org" );
}

QIcon FileReaderPositionProviderPlugin::icon() const
{
    return QIcon();
}

PositionProviderPlugin* FileReaderPositionProviderPlugin::newInstance() const
{
    return new FileReaderPositionProviderPlugin;
}

PositionProviderStatus FileReaderPositionProviderPlugin::status() const
{
    return d->m_status;
}

GeoDataCoordinates FileReaderPositionProviderPlugin::position() const
{
    return d->m_lineString.at( d->m_currentIndex );
}

GeoDataAccuracy FileReaderPositionProviderPlugin::accuracy() const
{
    GeoDataAccuracy result;

    // faked values
    result.level = GeoDataAccuracy::Detailed;
    result.horizontal = 10.0;
    result.vertical = 10.0;

    return result;
}

FileReaderPositionProviderPlugin::FileReaderPositionProviderPlugin() :
    d( new FileReaderPositionProviderPluginPrivate )
{
    // nothing to do
}

FileReaderPositionProviderPlugin::~FileReaderPositionProviderPlugin()
{
    delete d;
}

void FileReaderPositionProviderPlugin::initialize()
{
    d->m_currentIndex = 0;

    d->m_lineString.clear();

    GeoDataDocument* document = const_cast<MarbleModel *>( marbleModel() )->routingManager()->alternativeRoutesModel()->currentRoute();
    if ( document && document->size() > 0 ) {
        foreach( const GeoDataPlacemark *placemark, document->placemarkList() ) {
            GeoDataGeometry* geometry = placemark->geometry();
            GeoDataLineString* lineString = dynamic_cast<GeoDataLineString*>( geometry );
            if ( lineString ) {
                d->m_lineString << *lineString;
            }
        }
    }

    d->m_status = d->m_lineString.isEmpty() ? PositionProviderStatusUnavailable : PositionProviderStatusAcquiring;

    QTimer::singleShot( 1000, this, SLOT( update() ) );
}

bool FileReaderPositionProviderPlugin::isInitialized() const
{
    return ( d->m_currentIndex >= 0 );
}

qreal FileReaderPositionProviderPlugin::speed() const
{
    /** @todo: calculate speed */
    return 0.0;
}

qreal FileReaderPositionProviderPlugin::direction() const
{
    /** @todo: calculate direction */
    return 0.0;
}

QDateTime FileReaderPositionProviderPlugin::timestamp() const
{
    return QDateTime::currentDateTime();
}

void FileReaderPositionProviderPlugin::update()
{
    PositionProviderStatus newStatus = PositionProviderStatusAvailable;

    if ( d->m_currentIndex >= 0 && d->m_currentIndex < d->m_lineString.size() ) {
        if ( newStatus != d->m_status ) {
            d->m_status = newStatus;
            emit statusChanged( newStatus );
        }

        if ( newStatus == PositionProviderStatusAvailable ) {
            emit positionChanged( position(), accuracy() );
        }

        ++d->m_currentIndex;

        if( d->m_currentIndex < d->m_lineString.size() ) {
            QTimer::singleShot( 1000, this, SLOT( update() ) );
        }
    }

    if ( !d->m_lineString.isEmpty() && d->m_currentIndex >= d->m_lineString.size() ) {
        // Repeat from start
        d->m_currentIndex = 0;
        update();
    }
}

} // namespace Marble

Q_EXPORT_PLUGIN2( FileReaderPositionProviderPlugin, Marble::FileReaderPositionProviderPlugin )

#include "FileReaderPositionProviderPlugin.moc"
<|endoftext|>