<commit_before>/*****************************************************************************
 *
 * This file is part of Mapnik (c++ mapping toolkit)
 *
 * Copyright (C) 2006 Artem Pavlenko
 *
 * 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
 *
 *****************************************************************************/

//$Id: postgis.cc 44 2005-04-22 18:53:54Z pavlenko $

#include <string>
#include <algorithm>
#include <set>
#include <sstream>
#include <iomanip>
#include <boost/lexical_cast.hpp>
#include "connection_manager.hpp"
#include "postgis.hpp"

DATASOURCE_PLUGIN(postgis_datasource)

const std::string postgis_datasource::GEOMETRY_COLUMNS="geometry_columns";
const std::string postgis_datasource::SPATIAL_REF_SYS="spatial_ref_system";

using std::clog;
using std::endl;

using boost::lexical_cast;
using boost::bad_lexical_cast;
using boost::shared_ptr;

postgis_datasource::postgis_datasource(parameters const& params)
    : datasource (params),
      table_(params.get("table")),
      type_(datasource::Vector),
      extent_initialized_(false),
      desc_(params.get("type")),
      creator_(params.get("host"),
               params.get("port"),
               params.get("dbname"),
               params.get("user"),
               params.get("password"))
{

    unsigned initial_size;
    unsigned max_size;

    try
    {
        initial_size = boost::lexical_cast<unsigned>(params_.get("initial_size"));
    }
    catch (bad_lexical_cast& )
    {
        initial_size = 1;
    }

    try
    {
        max_size = boost::lexical_cast<unsigned>(params_.get("max_size"));
    }
    catch (bad_lexical_cast&)
    {
        max_size = 10;
    }

    ConnectionManager *mgr=ConnectionManager::instance();
    mgr->registerPool(creator_, initial_size, max_size);

    shared_ptr<Pool<Connection,ConnectionCreator> > pool=mgr->getPool(creator_.id());
    if (pool)
    {
        shared_ptr<Connection> conn = pool->borrowObject();
        if (conn && conn->isOK())
        {
            PoolGuard<shared_ptr<Connection>,shared_ptr<Pool<Connection,ConnectionCreator> > > guard(conn,pool);
            std::string table_name=table_from_sql(table_);
            std::ostringstream s;
            s << "select f_geometry_column,srid,type from ";
            s << GEOMETRY_COLUMNS <<" where f_table_name='" << table_name<<"'";

            shared_ptr<ResultSet> rs=conn->executeQuery(s.str());

            if (rs->next())
            {
                try
                {
                    srid_ = lexical_cast<int>(rs->getValue("srid"));
                    desc_.set_srid(srid_);
                }
                catch (bad_lexical_cast &ex)
                {
                    clog << ex.what() << endl;
                }
                geometryColumn_=rs->getValue("f_geometry_column");
                std::string postgisType=rs->getValue("type");
            }
            rs->close();

            // collect attribute desc
            s.str("");
            s << "select * from "<<table_<<" limit 1";
            rs=conn->executeQuery(s.str());
            if (rs->next())
            {
                int count = rs->getNumFields();
                for (int i=0;i<count;++i)
                {
                    std::string fld_name=rs->getFieldName(i);
                    int length = rs->getFieldLength(i);

                    int type_oid = rs->getTypeOID(i);
                    switch (type_oid)
                    {
                    case 21:    // int2
                    case 23:    // int4
                        desc_.add_descriptor(attribute_descriptor(fld_name,mapnik::Integer,false,length));
                        break;
                    case 700:   // float4
                    case 701:   // float8
                        desc_.add_descriptor(attribute_descriptor(fld_name,mapnik::Double,false,length));
                    case 1042:  // bpchar
                    case 1043:  // varchar
                    case 25:    // text
                        desc_.add_descriptor(attribute_descriptor(fld_name,mapnik::String));
                        break;
                    default: // shouldn't get here
#ifdef MAPNIK_DEBUG
                        clog << "unknown type_oid="<<type_oid<<endl;
#endif
                        break;
                    }
                }
            }
        }
    }
}

std::string const postgis_datasource::name_="postgis";

std::string postgis_datasource::name()
{
    return name_;
}

int postgis_datasource::type() const
{
    return type_;
}

layer_descriptor postgis_datasource::get_descriptor() const
{
    return desc_;
}

std::string postgis_datasource::table_from_sql(const std::string& sql)
{
    std::string table_name(sql);
    transform(table_name.begin(),table_name.end(),table_name.begin(),tolower);
    std::string::size_type idx=table_name.rfind("from");
    if (idx!=std::string::npos)
    {
        idx=table_name.find_first_not_of(" ",idx+4);
        table_name=table_name.substr(idx);
        idx=table_name.find_first_of(" )");
        return table_name.substr(0,idx);
    }
    return table_name;
}

featureset_ptr postgis_datasource::features(const query& q) const
{
    Envelope<double> const& box=q.get_bbox();
    ConnectionManager *mgr=ConnectionManager::instance();
    shared_ptr<Pool<Connection,ConnectionCreator> > pool=mgr->getPool(creator_.id());
    if (pool)
    {
        shared_ptr<Connection> conn = pool->borrowObject();
        if (conn && conn->isOK())
        {
            PoolGuard<shared_ptr<Connection>,shared_ptr<Pool<Connection,ConnectionCreator> > > guard(conn,pool);
            std::ostringstream s;

            s << "select asbinary("<<geometryColumn_<<") as geom";
            std::set<std::string> const& props=q.property_names();
            std::set<std::string>::const_iterator pos=props.begin();
            std::set<std::string>::const_iterator end=props.end();
            while (pos != end)
            {
                s <<",\""<<*pos<<"\"";
                ++pos;
            }
            s << " from " << table_<<" where "<<geometryColumn_<<" && setSRID('BOX3D(";
            s << std::setprecision(16);
            s << box.minx() << " " << box.miny() << ",";
            s << box.maxx() << " " << box.maxy() << ")'::box3d,"<<srid_<<")";

#ifdef MAPNIK_DEBUG
            std::clog << s.str() << "\n";
#endif
            shared_ptr<ResultSet> rs=conn->executeQuery(s.str(),1);
            return featureset_ptr(new postgis_featureset(rs,props.size()));
        }
    }
    return featureset_ptr();
}

featureset_ptr postgis_datasource::features_at_point(coord2d const& pt) const
{
    ConnectionManager *mgr=ConnectionManager::instance();
    shared_ptr<Pool<Connection,ConnectionCreator> > pool=mgr->getPool(creator_.id());
    if (pool)
    {
        shared_ptr<Connection> conn = pool->borrowObject();
        if (conn && conn->isOK())
        {
            PoolGuard<shared_ptr<Connection>,shared_ptr<Pool<Connection,ConnectionCreator> > > guard(conn,pool);
            std::ostringstream s;

            s << "select asbinary(" << geometryColumn_ << ") as geom";

            std::vector<attribute_descriptor>::const_iterator itr = desc_.get_descriptors().begin();
            std::vector<attribute_descriptor>::const_iterator end = desc_.get_descriptors().end();
            unsigned size=0;
            while (itr != end)
            {
                s <<",\""<< itr->get_name() << "\"";
                ++itr;
                ++size;
            }

            s << " from " << table_<<" where "<<geometryColumn_<<" && setSRID('BOX3D(";
            s << std::setprecision(16);
            s << pt.x << " " << pt.y << ",";
            s << pt.x << " " << pt.y << ")'::box3d,"<<srid_<<")";

#ifdef MAPNIK_DEBUG
            std::clog << s.str() << "\n";
#endif
            shared_ptr<ResultSet> rs=conn->executeQuery(s.str(),1);
            return featureset_ptr(new postgis_featureset(rs, size));
        }
    }
    return featureset_ptr();
}

Envelope<double> postgis_datasource::envelope() const
{
    if (extent_initialized_) return extent_;

    ConnectionManager *mgr=ConnectionManager::instance();
    shared_ptr<Pool<Connection,ConnectionCreator> > pool=mgr->getPool(creator_.id());
    if (pool)
    {
        shared_ptr<Connection> conn = pool->borrowObject();
        if (conn && conn->isOK())
        {
            std::ostringstream s;
            std::string table_name = table_from_sql(table_);
            if (params_.get("estimate_extent") == "true")
            {
                s << "select xmin(ext),ymin(ext),xmax(ext),ymax(ext)"
                  << " from (select estimated_extent('"
                  << table_name <<"','"
                  << geometryColumn_ << "') as ext) as tmp";
            }
            else
            {
                s << "select xmin(ext),ymin(ext),xmax(ext),ymax(ext)"
                  << " from (select extent(" <<geometryColumn_<< ") as ext from "
                  << table_name << ") as tmp";
            }

            shared_ptr<ResultSet> rs=conn->executeQuery(s.str());
            if (rs->next())
            {
                try
                {
                    double lox=lexical_cast<double>(rs->getValue(0));
                    double loy=lexical_cast<double>(rs->getValue(1));
                    double hix=lexical_cast<double>(rs->getValue(2));
                    double hiy=lexical_cast<double>(rs->getValue(3));
                    extent_.init(lox,loy,hix,hiy);
                    extent_initialized_ = true;
                }
                catch (bad_lexical_cast &ex)
                {
                    clog << ex.what() << endl;
                }
            }
            rs->close();
        }
    }
    return extent_;
}

postgis_datasource::~postgis_datasource() {}
<commit_msg>append namespace to 'transform' to support buiding with STLport.<commit_after>/*****************************************************************************
 *
 * This file is part of Mapnik (c++ mapping toolkit)
 *
 * Copyright (C) 2006 Artem Pavlenko
 *
 * 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
 *
 *****************************************************************************/

//$Id: postgis.cc 44 2005-04-22 18:53:54Z pavlenko $

#include <string>
#include <algorithm>
#include <set>
#include <sstream>
#include <iomanip>
#include <boost/lexical_cast.hpp>
#include "connection_manager.hpp"
#include "postgis.hpp"

DATASOURCE_PLUGIN(postgis_datasource)

const std::string postgis_datasource::GEOMETRY_COLUMNS="geometry_columns";
const std::string postgis_datasource::SPATIAL_REF_SYS="spatial_ref_system";

using std::clog;
using std::endl;

using boost::lexical_cast;
using boost::bad_lexical_cast;
using boost::shared_ptr;

postgis_datasource::postgis_datasource(parameters const& params)
    : datasource (params),
      table_(params.get("table")),
      type_(datasource::Vector),
      extent_initialized_(false),
      desc_(params.get("type")),
      creator_(params.get("host"),
               params.get("port"),
               params.get("dbname"),
               params.get("user"),
               params.get("password"))
{

    unsigned initial_size;
    unsigned max_size;

    try
    {
        initial_size = boost::lexical_cast<unsigned>(params_.get("initial_size"));
    }
    catch (bad_lexical_cast& )
    {
        initial_size = 1;
    }

    try
    {
        max_size = boost::lexical_cast<unsigned>(params_.get("max_size"));
    }
    catch (bad_lexical_cast&)
    {
        max_size = 10;
    }

    ConnectionManager *mgr=ConnectionManager::instance();
    mgr->registerPool(creator_, initial_size, max_size);

    shared_ptr<Pool<Connection,ConnectionCreator> > pool=mgr->getPool(creator_.id());
    if (pool)
    {
        shared_ptr<Connection> conn = pool->borrowObject();
        if (conn && conn->isOK())
        {
            PoolGuard<shared_ptr<Connection>,shared_ptr<Pool<Connection,ConnectionCreator> > > guard(conn,pool);
            std::string table_name=table_from_sql(table_);
            std::ostringstream s;
            s << "select f_geometry_column,srid,type from ";
            s << GEOMETRY_COLUMNS <<" where f_table_name='" << table_name<<"'";

            shared_ptr<ResultSet> rs=conn->executeQuery(s.str());

            if (rs->next())
            {
                try
                {
                    srid_ = lexical_cast<int>(rs->getValue("srid"));
                    desc_.set_srid(srid_);
                }
                catch (bad_lexical_cast &ex)
                {
                    clog << ex.what() << endl;
                }
                geometryColumn_=rs->getValue("f_geometry_column");
                std::string postgisType=rs->getValue("type");
            }
            rs->close();

            // collect attribute desc
            s.str("");
            s << "select * from "<<table_<<" limit 1";
            rs=conn->executeQuery(s.str());
            if (rs->next())
            {
                int count = rs->getNumFields();
                for (int i=0;i<count;++i)
                {
                    std::string fld_name=rs->getFieldName(i);
                    int length = rs->getFieldLength(i);

                    int type_oid = rs->getTypeOID(i);
                    switch (type_oid)
                    {
                    case 21:    // int2
                    case 23:    // int4
                        desc_.add_descriptor(attribute_descriptor(fld_name,mapnik::Integer,false,length));
                        break;
                    case 700:   // float4
                    case 701:   // float8
                        desc_.add_descriptor(attribute_descriptor(fld_name,mapnik::Double,false,length));
                    case 1042:  // bpchar
                    case 1043:  // varchar
                    case 25:    // text
                        desc_.add_descriptor(attribute_descriptor(fld_name,mapnik::String));
                        break;
                    default: // shouldn't get here
#ifdef MAPNIK_DEBUG
                        clog << "unknown type_oid="<<type_oid<<endl;
#endif
                        break;
                    }
                }
            }
        }
    }
}

std::string const postgis_datasource::name_="postgis";

std::string postgis_datasource::name()
{
    return name_;
}

int postgis_datasource::type() const
{
    return type_;
}

layer_descriptor postgis_datasource::get_descriptor() const
{
    return desc_;
}

std::string postgis_datasource::table_from_sql(const std::string& sql)
{
    std::string table_name(sql);
    std::transform(table_name.begin(),table_name.end(),table_name.begin(),tolower);
    std::string::size_type idx=table_name.rfind("from");
    if (idx!=std::string::npos)
    {
        idx=table_name.find_first_not_of(" ",idx+4);
        table_name=table_name.substr(idx);
        idx=table_name.find_first_of(" )");
        return table_name.substr(0,idx);
    }
    return table_name;
}

featureset_ptr postgis_datasource::features(const query& q) const
{
    Envelope<double> const& box=q.get_bbox();
    ConnectionManager *mgr=ConnectionManager::instance();
    shared_ptr<Pool<Connection,ConnectionCreator> > pool=mgr->getPool(creator_.id());
    if (pool)
    {
        shared_ptr<Connection> conn = pool->borrowObject();
        if (conn && conn->isOK())
        {
            PoolGuard<shared_ptr<Connection>,shared_ptr<Pool<Connection,ConnectionCreator> > > guard(conn,pool);
            std::ostringstream s;

            s << "select asbinary("<<geometryColumn_<<") as geom";
            std::set<std::string> const& props=q.property_names();
            std::set<std::string>::const_iterator pos=props.begin();
            std::set<std::string>::const_iterator end=props.end();
            while (pos != end)
            {
                s <<",\""<<*pos<<"\"";
                ++pos;
            }
            s << " from " << table_<<" where "<<geometryColumn_<<" && setSRID('BOX3D(";
            s << std::setprecision(16);
            s << box.minx() << " " << box.miny() << ",";
            s << box.maxx() << " " << box.maxy() << ")'::box3d,"<<srid_<<")";

#ifdef MAPNIK_DEBUG
            std::clog << s.str() << "\n";
#endif
            shared_ptr<ResultSet> rs=conn->executeQuery(s.str(),1);
            return featureset_ptr(new postgis_featureset(rs,props.size()));
        }
    }
    return featureset_ptr();
}

featureset_ptr postgis_datasource::features_at_point(coord2d const& pt) const
{
    ConnectionManager *mgr=ConnectionManager::instance();
    shared_ptr<Pool<Connection,ConnectionCreator> > pool=mgr->getPool(creator_.id());
    if (pool)
    {
        shared_ptr<Connection> conn = pool->borrowObject();
        if (conn && conn->isOK())
        {
            PoolGuard<shared_ptr<Connection>,shared_ptr<Pool<Connection,ConnectionCreator> > > guard(conn,pool);
            std::ostringstream s;

            s << "select asbinary(" << geometryColumn_ << ") as geom";

            std::vector<attribute_descriptor>::const_iterator itr = desc_.get_descriptors().begin();
            std::vector<attribute_descriptor>::const_iterator end = desc_.get_descriptors().end();
            unsigned size=0;
            while (itr != end)
            {
                s <<",\""<< itr->get_name() << "\"";
                ++itr;
                ++size;
            }

            s << " from " << table_<<" where "<<geometryColumn_<<" && setSRID('BOX3D(";
            s << std::setprecision(16);
            s << pt.x << " " << pt.y << ",";
            s << pt.x << " " << pt.y << ")'::box3d,"<<srid_<<")";

#ifdef MAPNIK_DEBUG
            std::clog << s.str() << "\n";
#endif
            shared_ptr<ResultSet> rs=conn->executeQuery(s.str(),1);
            return featureset_ptr(new postgis_featureset(rs, size));
        }
    }
    return featureset_ptr();
}

Envelope<double> postgis_datasource::envelope() const
{
    if (extent_initialized_) return extent_;

    ConnectionManager *mgr=ConnectionManager::instance();
    shared_ptr<Pool<Connection,ConnectionCreator> > pool=mgr->getPool(creator_.id());
    if (pool)
    {
        shared_ptr<Connection> conn = pool->borrowObject();
        if (conn && conn->isOK())
        {
            std::ostringstream s;
            std::string table_name = table_from_sql(table_);
            if (params_.get("estimate_extent") == "true")
            {
                s << "select xmin(ext),ymin(ext),xmax(ext),ymax(ext)"
                  << " from (select estimated_extent('"
                  << table_name <<"','"
                  << geometryColumn_ << "') as ext) as tmp";
            }
            else
            {
                s << "select xmin(ext),ymin(ext),xmax(ext),ymax(ext)"
                  << " from (select extent(" <<geometryColumn_<< ") as ext from "
                  << table_name << ") as tmp";
            }

            shared_ptr<ResultSet> rs=conn->executeQuery(s.str());
            if (rs->next())
            {
                try
                {
                    double lox=lexical_cast<double>(rs->getValue(0));
                    double loy=lexical_cast<double>(rs->getValue(1));
                    double hix=lexical_cast<double>(rs->getValue(2));
                    double hiy=lexical_cast<double>(rs->getValue(3));
                    extent_.init(lox,loy,hix,hiy);
                    extent_initialized_ = true;
                }
                catch (bad_lexical_cast &ex)
                {
                    clog << ex.what() << endl;
                }
            }
            rs->close();
        }
    }
    return extent_;
}

postgis_datasource::~postgis_datasource() {}
<|endoftext|>


<commit_before>// Copyright (c) 2013-2017, Matt Godbolt
// 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.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.

#include "internal/PageRequest.h"

#include <cstdlib>
#include <cstring>

namespace seasocks {

PageRequest::PageRequest(
    const sockaddr_in& remoteAddress,
    const std::string& requestUri,
    Server& server,
    Verb verb,
    HeaderMap&& headers)
        : _credentials(std::make_shared<Credentials>()),
          _remoteAddress(remoteAddress),
          _requestUri(requestUri),
          _server(server),
          _verb(verb),
          _headers(std::move(headers)),
          _contentLength(getUintHeader("Content-Length")) {
}

bool PageRequest::consumeContent(std::vector<uint8_t>& buffer) {
    if (buffer.size() < _contentLength) {
        return false;
    }
    if (buffer.size() == _contentLength) {
        _content.swap(buffer);
    } else {
        _content.assign(buffer.begin(), buffer.begin() + _contentLength);
        buffer.erase(buffer.begin(), buffer.begin() + _contentLength);
    }
    return true;
}

size_t PageRequest::getUintHeader(const std::string& name) const {
    const auto iter = _headers.find(name);
    if (iter == _headers.end()) {
        return 0u;
    }
    try {
        const auto val = std::stoi(iter->second);
    } catch (const std::logic_error&) {
        return 0u;
    }
    if (val < 0) {
        return 0u;
    }
    return static_cast<size_t>(val);
}

} // namespace seasocks
<commit_msg>Fix variable scope<commit_after>// Copyright (c) 2013-2017, Matt Godbolt
// 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.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.

#include "internal/PageRequest.h"

#include <cstdlib>
#include <cstring>
#include <algorithm>

namespace seasocks {

PageRequest::PageRequest(
    const sockaddr_in& remoteAddress,
    const std::string& requestUri,
    Server& server,
    Verb verb,
    HeaderMap&& headers)
        : _credentials(std::make_shared<Credentials>()),
          _remoteAddress(remoteAddress),
          _requestUri(requestUri),
          _server(server),
          _verb(verb),
          _headers(std::move(headers)),
          _contentLength(getUintHeader("Content-Length")) {
}

bool PageRequest::consumeContent(std::vector<uint8_t>& buffer) {
    if (buffer.size() < _contentLength) {
        return false;
    }
    if (buffer.size() == _contentLength) {
        _content.swap(buffer);
    } else {
        _content.assign(buffer.begin(), buffer.begin() + _contentLength);
        buffer.erase(buffer.begin(), buffer.begin() + _contentLength);
    }
    return true;
}

size_t PageRequest::getUintHeader(const std::string& name) const {
    const auto iter = _headers.find(name);
    if (iter == _headers.end()) {
        return 0u;
    }
    try {
        return std::max(std::stoi(iter->second), 0);
    } catch (const std::logic_error&) {
        return 0u;
    }
}

} // namespace seasocks
<|endoftext|>


<commit_before>#include "oemhandler.h"
#include <host-ipmid/ipmid-api.h>
#include <stdio.h>
#include <string.h>

void register_netfn_oem_partial_esel() __attribute__((constructor));

const char *g_esel_path = "/tmp/";
uint16_t g_record_id = 0x0100;

#define LSMSSWAP(x,y) ((y)<<8|(x))

///////////////////////////////////////////////////////////////////////////////
// For the First partial add eSEL the SEL Record ID and offset
// value should be 0x0000. The extended data needs to be in
// the form of an IPMI SEL Event Record, with Event sensor type
// of 0xDF and Event Message format of 0x04. The returned
// Record ID should be used for all partial eSEL adds.
//
// This function creates a /tmp/esel# file to store the
// incoming partial esel.  It is the role of some other
// function to commit the error log in to long term
// storage.  Likely via the ipmi add_sel command.
///////////////////////////////////////////////////////////////////////////////
ipmi_ret_t ipmi_ibm_oem_partial_esel(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
                              ipmi_request_t request, ipmi_response_t response,
                              ipmi_data_len_t data_len, ipmi_context_t context)
{
    esel_request_t *reqptr = (esel_request_t*) request;
    FILE *fp;
    short offset = 0;
    uint8_t rlen;
    ipmi_ret_t rc = IPMI_CC_OK;
    char string[64];
    const char *pio;

    offset = LSMSSWAP(reqptr->offsetls, reqptr->offsetms);

    snprintf(string, sizeof(string), "%s%s%02x%02x", g_esel_path, "esel", reqptr->selrecordms, reqptr->selrecordls);

    // Length is the number of request bytes minus the header itself.
    // The header contains an extra byte to indicate the start of
    // the data (so didn't need to worry about word/byte boundaries)
    // hence the -1...
    rlen = (*data_len) - (uint8_t) (sizeof(esel_request_t));

    printf("IPMI PARTIAL ESEL for %s  Offset = %d Length = %d\n",
        string, offset, rlen);

    // Rules state for a Partial eSel that the first write of a
    // new esel will be the sensor data record.  We will use that
    // to indicate this is a new record rather then an ofset in
    // my next commit TODO
    if (offset == 0) {
        pio = "wb";
    } else {
        pio = "rb+";
    }

    if ((fp = fopen(string, pio)) != NULL) {
        fseek(fp, offset, SEEK_SET);
        fwrite(reqptr+1,rlen,1,fp);
        fclose(fp);

        *data_len = sizeof(g_record_id);
        memcpy(response, &g_record_id, *data_len);

    } else {
        fprintf(stderr, "Error trying to perform %s for esel%s\n",pio, string);
        rc = IPMI_CC_INVALID;
        *data_len     = 0;
    }

    return rc;
}

void register_netfn_oem_partial_esel()
{
    printf("Registering NetFn:[0x%X], Cmd:[0x%X]\n",NETFUN_OEM, IPMI_CMD_PESEL);
    ipmi_register_callback(NETFUN_OEM, IPMI_CMD_PESEL, NULL, ipmi_ibm_oem_partial_esel);
    return;
}
<commit_msg>Fixed byte swapped esel log name so logs are saved<commit_after>#include "oemhandler.h"
#include <host-ipmid/ipmid-api.h>
#include <stdio.h>
#include <string.h>

void register_netfn_oem_partial_esel() __attribute__((constructor));

const char *g_esel_path = "/tmp/";
uint16_t g_record_id = 0x0100;

#define LSMSSWAP(x,y) ((y)<<8|(x))

///////////////////////////////////////////////////////////////////////////////
// For the First partial add eSEL the SEL Record ID and offset
// value should be 0x0000. The extended data needs to be in
// the form of an IPMI SEL Event Record, with Event sensor type
// of 0xDF and Event Message format of 0x04. The returned
// Record ID should be used for all partial eSEL adds.
//
// This function creates a /tmp/esel# file to store the
// incoming partial esel.  It is the role of some other
// function to commit the error log in to long term
// storage.  Likely via the ipmi add_sel command.
///////////////////////////////////////////////////////////////////////////////
ipmi_ret_t ipmi_ibm_oem_partial_esel(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
                                     ipmi_request_t request, ipmi_response_t response,
                                     ipmi_data_len_t data_len, ipmi_context_t context)
{
    esel_request_t *reqptr = (esel_request_t*) request;
    FILE *fp;
    short recid, offset = 0;
    uint8_t rlen;
    ipmi_ret_t rc = IPMI_CC_OK;
    char string[64];
    const char *pio;

    recid  = LSMSSWAP(reqptr->selrecordls, reqptr->selrecordms);
    offset = LSMSSWAP(reqptr->offsetls, reqptr->offsetms);

    if (!recid && !offset) {
        // OpenPOWER Host Interface spec says if RecordID and Offset are
        // 0 then then this is a new request
        pio = "wb";
        snprintf(string, sizeof(string), "%s%s%02x%02x", g_esel_path, "esel", (g_record_id&0xFF00>>8), (g_record_id&0xFF));
    } else {
        pio = "rb+";
        snprintf(string, sizeof(string), "%s%s%02x%02x", g_esel_path, "esel", reqptr->selrecordms, reqptr->selrecordls);
    }

    // Length is the number of request bytes minus the header itself.
    // The header contains an extra byte to indicate the start of
    // the data (so didn't need to worry about word/byte boundaries)
    // hence the -1...
    rlen = (*data_len) - (uint8_t) (sizeof(esel_request_t));

    printf("IPMI PARTIAL ESEL for %s  Offset = %d Length = %d\n",
        string, offset, rlen);

    if ((fp = fopen(string, pio)) != NULL) {
        fseek(fp, offset, SEEK_SET);
        fwrite(reqptr+1,rlen,1,fp);
        fclose(fp);

        *data_len = sizeof(g_record_id);
        memcpy(response, &g_record_id, *data_len);
    } else {
        fprintf(stderr, "Error trying to perform %s for esel%s\n",pio, string);
        rc = IPMI_CC_INVALID;
        *data_len     = 0;
    }

    return rc;
}

void register_netfn_oem_partial_esel()
{
    printf("Registering NetFn:[0x%X], Cmd:[0x%X]\n",NETFUN_OEM, IPMI_CMD_PESEL);
    ipmi_register_callback(NETFUN_OEM, IPMI_CMD_PESEL, NULL, ipmi_ibm_oem_partial_esel);
    return;
}
<|endoftext|>


<commit_before>#include <sstream>
#include "../system/engine.h"
#include "../renderer/renderer.h"
#include "../renderer/forms.h"
#include "../math/vector.h"
#include "messagebox.h"

using std::istringstream;
using namespace Gui;
using Graphics::Color;
using Math::Vector3D;
using Math::Vector2D;

//The MessageBox constructor
MessageBox::MessageBox(){
  handleClicks_ = NULL;
  input_.setColors(Vector3D(1,1,0.1f),Color(51,2,2,255));
  input_.setSpan(Vector2D(75,18));
  bgColor_ = Color(0,0,0,200);//178);
  fgColor_ = Color(255,0,0,255);
  setText("  OK");
  span_ = Vector2D(800, 600);
  setPosition(Vector2D(100,100));
}

MessageBox::MessageBox(const MessageBox& m){
  std::cerr << "MessageBox copy constructor not yet implemented\n";
}

//and destructor
MessageBox::~MessageBox(){
}

void MessageBox::process(){
  //close messageBox
  //find yourself
  list< ::Gui::Button*>& buts = System::Engine::instance()->getButtons();
  list< ::Gui::Button* >::iterator iter;
  int idx = 0;
  for (iter = buts.begin(); iter != buts.end(); iter++){
    if (*iter == this){
      break;
    }
    idx++;
  }
  System::Engine::instance()->removeButtonListener(idx, false);
}

void MessageBox::setPosition(const ::Math::Vector2D& pos){
  pos_ = pos;
  Vector2D inpos = pos;
  inpos.x += (short)(0.5*span_.x-75.0/2.0);
  inpos.y += (short)(0.05*span_.y);
  input_.setPosition(inpos);
}

void MessageBox::setMessage(const string& text){
  istringstream str(text);
  unsigned maxchars = span_.x/10-1;
  unsigned chars = 0;
  string word;
  string line = "";
  while (str >> word){
    //the word does not fit into the current line
    if (chars + word.size() > maxchars){
      msg_.push_back(line);
      line = "";
      chars = 0;
    }
    //concatenate word to current line
    line += word + " ";
    chars += word.size()+1;
  }
  msg_.push_back(line);
}

void MessageBox::render(){
  Graphics::Renderer* rend = System::Engine::instance()->getRenderer();

  rend->blendFunc(Graphics::BLEND_SRC_ALPHA, Graphics::BLEND_ONE_MINUS_SRC_ALPHA);
  rend->enableTexturing(false);

  //draw background
  rend->setColor(&bgColor_);//_.r, bgColor_.g, bgColor_.b, opacity_);
  System::Engine::instance()->getForms()->activateQuad();
  System::Engine::instance()->getForms()->drawQuad(pos_, span_);

  //draw console text
  rend->enableTexturing(true);
  rend->blendFunc(Graphics::BLEND_SRC_ALPHA, Graphics::BLEND_ONE);
  System::Engine::instance()->getFont(1)->setColor(fgColor_);
  int y = pos_.y + span_.y - 20;
  for (list<string>::iterator iter = msg_.begin(); iter != msg_.end(); iter++){
    System::Engine::instance()->getFont(1)->glPrint(pos_.x, y, (*iter).c_str(), 0, 0.0);
    y -= 20;
  }
  input_.render();
}
<commit_msg>messagebox has now callback capability<commit_after>#include <sstream>
#include "../system/engine.h"
#include "../renderer/renderer.h"
#include "../renderer/forms.h"
#include "../math/vector.h"
#include "messagebox.h"

using std::istringstream;
using namespace Gui;
using Graphics::Color;
using Math::Vector3D;
using Math::Vector2D;

//The MessageBox constructor
MessageBox::MessageBox(){
  handleClicks_ = NULL;
  input_.setColors(Vector3D(1,1,0.1f),Color(51,2,2,255));
  input_.setSpan(Vector2D(75,18));
  bgColor_ = Color(0,0,0,200);//178);
  fgColor_ = Color(255,0,0,255);
  setText("  OK");
  span_ = Vector2D(800, 600);
  setPosition(Vector2D(100,100));
}

MessageBox::MessageBox(const MessageBox& m){
  std::cerr << "MessageBox copy constructor not yet implemented\n";
}

//and destructor
MessageBox::~MessageBox(){
}

void MessageBox::process(){
  //close messageBox
  //find yourself
  list< ::Gui::Button*>& buts = System::Engine::instance()->getButtons();
  list< ::Gui::Button* >::iterator iter;
  int idx = 0;
  for (iter = buts.begin(); iter != buts.end(); iter++){
    if (*iter == this){
      break;
    }
    idx++;
  }
  System::Engine::instance()->removeButtonListener(idx, false);
  if (handleClicks_)
    (*handleClicks_)();
}

void MessageBox::setPosition(const ::Math::Vector2D& pos){
  pos_ = pos;
  Vector2D inpos = pos;
  inpos.x += (short)(0.5*span_.x-75.0/2.0);
  inpos.y += (short)(0.05*span_.y);
  input_.setPosition(inpos);
}

void MessageBox::setMessage(const string& text){
  istringstream str(text);
  unsigned maxchars = span_.x/10-1;
  unsigned chars = 0;
  string word;
  string line = "";
  while (str >> word){
    //the word does not fit into the current line
    if (chars + word.size() > maxchars){
      msg_.push_back(line);
      line = "";
      chars = 0;
    }
    //concatenate word to current line
    line += word + " ";
    chars += word.size()+1;
  }
  msg_.push_back(line);
}

void MessageBox::render(){
  Graphics::Renderer* rend = System::Engine::instance()->getRenderer();

  rend->blendFunc(Graphics::BLEND_SRC_ALPHA, Graphics::BLEND_ONE_MINUS_SRC_ALPHA);
  rend->enableTexturing(false);

  //draw background
  rend->setColor(&bgColor_);//_.r, bgColor_.g, bgColor_.b, opacity_);
  System::Engine::instance()->getForms()->activateQuad();
  System::Engine::instance()->getForms()->drawQuad(pos_, span_);

  //draw console text
  rend->enableTexturing(true);
  rend->blendFunc(Graphics::BLEND_SRC_ALPHA, Graphics::BLEND_ONE);
  System::Engine::instance()->getFont(1)->setColor(fgColor_);
  int y = pos_.y + span_.y - 20;
  for (list<string>::iterator iter = msg_.begin(); iter != msg_.end(); iter++){
    System::Engine::instance()->getFont(1)->glPrint(pos_.x, y, (*iter).c_str(), 0, 0.0);
    y -= 20;
  }
  input_.render();
}
<|endoftext|>


<commit_before>#include "openhevcfilter.h"

#include "statisticsinterface.h"

#include "common.h"
#include "settingskeys.h"
#include "logger.h"

#include <QSettings>

enum OHThreadType {OH_THREAD_FRAME  = 1, OH_THREAD_SLICE  = 2, OH_THREAD_FRAMESLICE  = 3};

OpenHEVCFilter::OpenHEVCFilter(uint32_t sessionID, StatisticsInterface *stats,
                               std::shared_ptr<ResourceAllocator> hwResources):
  Filter(QString::number(sessionID), "OpenHEVC", stats, hwResources, DT_HEVCVIDEO, DT_YUV420VIDEO),
  handle_(),
  vpsReceived_(false),
  spsReceived_(false),
  ppsReceived_(false),
  slices_(true),
  sessionID_(sessionID),
  threads_(-1)
{}

bool OpenHEVCFilter::init()
{
  Logger::getLogger()->printNormal(this, "Starting to initiate OpenHEVC");
  QSettings settings(settingsFile, settingsFileFormat);

  threads_ = settings.value(SettingsKey::videoOpenHEVCThreads).toInt();
  handle_ = libOpenHevcInit(threads_, OH_THREAD_FRAME);

  //libOpenHevcSetDebugMode(handle_, 0);
  if(libOpenHevcStartDecoder(handle_) == -1)
  {
    Logger::getLogger()->printDebug(DEBUG_PROGRAM_ERROR, this, "Failed to start decoder.");
    return false;
  }
  libOpenHevcSetTemporalLayer_id(handle_, 0);
  libOpenHevcSetActiveDecoders(handle_, 0);
  libOpenHevcSetViewLayers(handle_, 0);
  Logger::getLogger()->printNormal(this, "OpenHEVC initiation successful.",
                                   {"Version"}, {libOpenHevcVersion(handle_)});

  // This is because we don't know anything about the incoming stream
  maxBufferSize_ = -1; // no buffer limit

  setPriority(QThread::HighPriority);

  return true;
}

void OpenHEVCFilter::uninit()
{
  Logger::getLogger()->printNormal(this, "Uniniating.");
  libOpenHevcFlush(handle_);
  libOpenHevcClose(handle_);
}

void OpenHEVCFilter::updateSettings()
{
  QSettings settings(settingsFile, settingsFileFormat);
  if (settings.value(SettingsKey::videoOpenHEVCThreads).toInt() != threads_)
  {
    uninit();
    init();
  }
  Filter::updateSettings();
}

void OpenHEVCFilter::combineFrame(std::unique_ptr<Data>& combinedFrame)
{
  if(sliceBuffer_.size() == 0)
  {
    Logger::getLogger()->printWarning(this, "No previous slices");
    return;
  }

  combinedFrame = std::unique_ptr<Data>(shallowDataCopy(sliceBuffer_.at(0).get()));
  combinedFrame->data_size = 0;

  for(unsigned int i = 0; i < sliceBuffer_.size(); ++i)
  {
    combinedFrame->data_size += sliceBuffer_.at(i)->data_size;
  }

  combinedFrame->data = std::unique_ptr<uchar[]>(new uchar[combinedFrame->data_size]);

  uint32_t dataWritten = 0;
  for(unsigned int i = 0; i < sliceBuffer_.size(); ++i)
  {
    memcpy(combinedFrame->data.get() + dataWritten,
           sliceBuffer_.at(i)->data.get(), sliceBuffer_.at(i)->data_size );
    dataWritten += sliceBuffer_.at(i)->data_size;
  }

  if(slices_ && sliceBuffer_.size() == 1)
  {
    slices_ = false;
    Logger::getLogger()->printPeerError(this, "Detected no slices in incoming stream.");
    uninit();
    init();
  }

  sliceBuffer_.clear();

  return;
}

void OpenHEVCFilter::process()
{
  std::unique_ptr<Data> input = getInput();
  while(input)
  {
    getStats()->addReceivePacket(sessionID_, "Video", input->data_size);

    const unsigned char *buff = input->data.get();

    bool nextSlice = buff[0] == 0
        && buff[1] == 0
        && buff[2] == 0;

    if(!slices_ && buff[0] == 0
       && buff[1] == 0
       && buff[2] == 1)
    {
      slices_ = true;
      Logger::getLogger()->printNormal(this, "Detected slices in incoming stream");
      uninit();
      init();
    }

    bool vps = (buff[4] >> 1) == 32;
    if (!vpsReceived_ && vps)
    {
      Logger::getLogger()->printDebug(DEBUG_NORMAL, this,  "VPS found");
      vpsReceived_ = true;
    }

    bool sps = (buff[4] >> 1) == 33;
    if (!spsReceived_ && sps)
    {
      Logger::getLogger()->printDebug(DEBUG_NORMAL, this,  "SPS found");
      spsReceived_ = true;
    }

    bool pps = (buff[4] >> 1) == 34;
    if (!ppsReceived_ && pps)
    {
      Logger::getLogger()->printDebug(DEBUG_NORMAL, this,  "PPS found");
      ppsReceived_ = true;
    }

    if((vpsReceived_ && spsReceived_ && ppsReceived_) || vps || sps || pps)
    {
      if(nextSlice && sliceBuffer_.size() != 0)
      {
        std::unique_ptr<Data> frame;
        combineFrame(frame);

        if (frame == nullptr)
        {
          break;
        }

        int gotPicture = libOpenHevcDecode(handle_, frame->data.get(), frame->data_size, frame->presentationTime);

        OpenHevc_Frame openHevcFrame;
        if( gotPicture == -1)
        {
          Logger::getLogger()->printDebug(DEBUG_ERROR, this,  "Error while decoding.");
        }
        else if( libOpenHevcGetOutput(handle_, gotPicture, &openHevcFrame) == -1 )
        {
          Logger::getLogger()->printDebug(DEBUG_ERROR, this,  "Failed to get output.");
        }
        else if(gotPicture)
        {
          libOpenHevcGetPictureInfo(handle_, &openHevcFrame.frameInfo);

          frame->vInfo->width = openHevcFrame.frameInfo.nWidth;
          frame->vInfo->height = openHevcFrame.frameInfo.nHeight;
          uint32_t finalDataSize = frame->vInfo->width*frame->vInfo->height +
              frame->vInfo->width*frame->vInfo->height/2;
          std::unique_ptr<uchar[]> yuv_frame(new uchar[finalDataSize]);

          uint8_t* pY = (uint8_t*)yuv_frame.get();
          uint8_t* pU = (uint8_t*)&(yuv_frame.get()[frame->vInfo->width*frame->vInfo->height]);
          uint8_t* pV = (uint8_t*)&(yuv_frame.get()[frame->vInfo->width*frame->vInfo->height +
              frame->vInfo->width*frame->vInfo->height/4]);

          uint32_t s_stride = openHevcFrame.frameInfo.nYPitch;
          uint32_t qs_stride = openHevcFrame.frameInfo.nUPitch/2;

          uint32_t d_stride = frame->vInfo->width/2;
          uint32_t dd_stride = frame->vInfo->width;

          for (int i=0; i<frame->vInfo->height; i++) {
            memcpy(pY,  (uint8_t *) openHevcFrame.pvY + i*s_stride, dd_stride);
            pY += dd_stride;

            if (! (i%2) ) {
              memcpy(pU,  (uint8_t *) openHevcFrame.pvU + i*qs_stride, d_stride);
              pU += d_stride;

              memcpy(pV,  (uint8_t *) openHevcFrame.pvV + i*qs_stride, d_stride);
              pV += d_stride;
            }
          }

          // TODO: put delay into deque, and set timestamp accordingly to get more accurate latency.

          frame->type = DT_YUV420VIDEO;
          if (openHevcFrame.frameInfo.frameRate.den != 0)
          {
            frame->vInfo->framerate = openHevcFrame.frameInfo.frameRate.num/openHevcFrame.frameInfo.frameRate.den;
          }
          else
          {
            frame->vInfo->framerate = openHevcFrame.frameInfo.frameRate.num;
          }
          frame->data_size = finalDataSize;
          frame->data = std::move(yuv_frame);

          sendOutput(std::move(frame));
        }
      }
      sliceBuffer_.push_back(std::move(input));
    }

    input = getInput();
  }
}
<commit_msg>refactor(Processing): Print warning when waiting for first intra<commit_after>#include "openhevcfilter.h"

#include "statisticsinterface.h"

#include "common.h"
#include "settingskeys.h"
#include "logger.h"

#include <QSettings>

enum OHThreadType {OH_THREAD_FRAME  = 1, OH_THREAD_SLICE  = 2, OH_THREAD_FRAMESLICE  = 3};

OpenHEVCFilter::OpenHEVCFilter(uint32_t sessionID, StatisticsInterface *stats,
                               std::shared_ptr<ResourceAllocator> hwResources):
  Filter(QString::number(sessionID), "OpenHEVC", stats, hwResources, DT_HEVCVIDEO, DT_YUV420VIDEO),
  handle_(),
  vpsReceived_(false),
  spsReceived_(false),
  ppsReceived_(false),
  slices_(true),
  sessionID_(sessionID),
  threads_(-1)
{}

bool OpenHEVCFilter::init()
{
  Logger::getLogger()->printNormal(this, "Starting to initiate OpenHEVC");
  QSettings settings(settingsFile, settingsFileFormat);

  threads_ = settings.value(SettingsKey::videoOpenHEVCThreads).toInt();
  handle_ = libOpenHevcInit(threads_, OH_THREAD_FRAME);

  //libOpenHevcSetDebugMode(handle_, 0);
  if(libOpenHevcStartDecoder(handle_) == -1)
  {
    Logger::getLogger()->printDebug(DEBUG_PROGRAM_ERROR, this, "Failed to start decoder.");
    return false;
  }
  libOpenHevcSetTemporalLayer_id(handle_, 0);
  libOpenHevcSetActiveDecoders(handle_, 0);
  libOpenHevcSetViewLayers(handle_, 0);
  Logger::getLogger()->printNormal(this, "OpenHEVC initiation successful.",
                                   {"Version"}, {libOpenHevcVersion(handle_)});

  // This is because we don't know anything about the incoming stream
  maxBufferSize_ = -1; // no buffer limit

  setPriority(QThread::HighPriority);

  return true;
}

void OpenHEVCFilter::uninit()
{
  Logger::getLogger()->printNormal(this, "Uniniating.");
  libOpenHevcFlush(handle_);
  libOpenHevcClose(handle_);
}

void OpenHEVCFilter::updateSettings()
{
  QSettings settings(settingsFile, settingsFileFormat);
  if (settings.value(SettingsKey::videoOpenHEVCThreads).toInt() != threads_)
  {
    uninit();
    init();
  }
  Filter::updateSettings();
}

void OpenHEVCFilter::combineFrame(std::unique_ptr<Data>& combinedFrame)
{
  if(sliceBuffer_.size() == 0)
  {
    Logger::getLogger()->printWarning(this, "No previous slices");
    return;
  }

  combinedFrame = std::unique_ptr<Data>(shallowDataCopy(sliceBuffer_.at(0).get()));
  combinedFrame->data_size = 0;

  for(unsigned int i = 0; i < sliceBuffer_.size(); ++i)
  {
    combinedFrame->data_size += sliceBuffer_.at(i)->data_size;
  }

  combinedFrame->data = std::unique_ptr<uchar[]>(new uchar[combinedFrame->data_size]);

  uint32_t dataWritten = 0;
  for(unsigned int i = 0; i < sliceBuffer_.size(); ++i)
  {
    memcpy(combinedFrame->data.get() + dataWritten,
           sliceBuffer_.at(i)->data.get(), sliceBuffer_.at(i)->data_size );
    dataWritten += sliceBuffer_.at(i)->data_size;
  }

  if(slices_ && sliceBuffer_.size() == 1)
  {
    slices_ = false;
    Logger::getLogger()->printPeerError(this, "Detected no slices in incoming stream.");
    uninit();
    init();
  }

  sliceBuffer_.clear();

  return;
}

void OpenHEVCFilter::process()
{
  std::unique_ptr<Data> input = getInput();
  while(input)
  {
    getStats()->addReceivePacket(sessionID_, "Video", input->data_size);

    const unsigned char *buff = input->data.get();

    bool nextSlice = buff[0] == 0
        && buff[1] == 0
        && buff[2] == 0;

    if(!slices_ && buff[0] == 0
       && buff[1] == 0
       && buff[2] == 1)
    {
      slices_ = true;
      Logger::getLogger()->printNormal(this, "Detected slices in incoming stream");
      uninit();
      init();
    }

    bool vps = (buff[4] >> 1) == 32;
    if (!vpsReceived_ && vps)
    {
      Logger::getLogger()->printDebug(DEBUG_NORMAL, this,  "VPS found");
      vpsReceived_ = true;
    }

    bool sps = (buff[4] >> 1) == 33;
    if (!spsReceived_ && sps)
    {
      Logger::getLogger()->printDebug(DEBUG_NORMAL, this,  "SPS found");
      spsReceived_ = true;
    }

    bool pps = (buff[4] >> 1) == 34;
    if (!ppsReceived_ && pps)
    {
      Logger::getLogger()->printDebug(DEBUG_NORMAL, this,  "PPS found");
      ppsReceived_ = true;
    }

    if(slices_ || (vpsReceived_ && spsReceived_ && ppsReceived_) || vps || sps || pps)
    {
      if(nextSlice && sliceBuffer_.size() != 0)
      {
        std::unique_ptr<Data> frame;
        combineFrame(frame);

        if (frame == nullptr)
        {
          break;
        }

        int gotPicture = libOpenHevcDecode(handle_, frame->data.get(), frame->data_size, frame->presentationTime);

        OpenHevc_Frame openHevcFrame;
        if( gotPicture == -1)
        {
          Logger::getLogger()->printDebug(DEBUG_ERROR, this,  "Error while decoding.");
        }
        else if( libOpenHevcGetOutput(handle_, gotPicture, &openHevcFrame) == -1 )
        {
          Logger::getLogger()->printDebug(DEBUG_ERROR, this,  "Failed to get output.");
        }
        else if(gotPicture)
        {
          libOpenHevcGetPictureInfo(handle_, &openHevcFrame.frameInfo);

          frame->vInfo->width = openHevcFrame.frameInfo.nWidth;
          frame->vInfo->height = openHevcFrame.frameInfo.nHeight;
          uint32_t finalDataSize = frame->vInfo->width*frame->vInfo->height +
              frame->vInfo->width*frame->vInfo->height/2;
          std::unique_ptr<uchar[]> yuv_frame(new uchar[finalDataSize]);

          uint8_t* pY = (uint8_t*)yuv_frame.get();
          uint8_t* pU = (uint8_t*)&(yuv_frame.get()[frame->vInfo->width*frame->vInfo->height]);
          uint8_t* pV = (uint8_t*)&(yuv_frame.get()[frame->vInfo->width*frame->vInfo->height +
              frame->vInfo->width*frame->vInfo->height/4]);

          uint32_t s_stride = openHevcFrame.frameInfo.nYPitch;
          uint32_t qs_stride = openHevcFrame.frameInfo.nUPitch/2;

          uint32_t d_stride = frame->vInfo->width/2;
          uint32_t dd_stride = frame->vInfo->width;

          for (int i=0; i<frame->vInfo->height; i++) {
            memcpy(pY,  (uint8_t *) openHevcFrame.pvY + i*s_stride, dd_stride);
            pY += dd_stride;

            if (! (i%2) ) {
              memcpy(pU,  (uint8_t *) openHevcFrame.pvU + i*qs_stride, d_stride);
              pU += d_stride;

              memcpy(pV,  (uint8_t *) openHevcFrame.pvV + i*qs_stride, d_stride);
              pV += d_stride;
            }
          }

          // TODO: put delay into deque, and set timestamp accordingly to get more accurate latency.

          frame->type = DT_YUV420VIDEO;
          if (openHevcFrame.frameInfo.frameRate.den != 0)
          {
            frame->vInfo->framerate = openHevcFrame.frameInfo.frameRate.num/openHevcFrame.frameInfo.frameRate.den;
          }
          else
          {
            frame->vInfo->framerate = openHevcFrame.frameInfo.frameRate.num;
          }
          frame->data_size = finalDataSize;
          frame->data = std::move(yuv_frame);

          sendOutput(std::move(frame));
        }
      }
      sliceBuffer_.push_back(std::move(input));
    }
    else
    {
      Logger::getLogger()->printWarning(this, "Discarding frame until necessary structures have arrived");
    }

    input = getInput();
  }
}
<|endoftext|>


<commit_before>// Copyright 2014 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 "config.h"
#include "core/animation/css/CSSTransitionData.h"

#include "core/animation/Timing.h"

namespace blink {

CSSTransitionData::CSSTransitionData()
{
    m_propertyList.append(initialProperty());
}

CSSTransitionData::CSSTransitionData(const CSSTransitionData& other)
    : CSSTimingData(other)
    , m_propertyList(other.m_propertyList)
{
}

bool CSSTransitionData::transitionsMatchForStyleRecalc(const CSSTransitionData& other) const
{
    return m_propertyList == other.m_propertyList;
}

Timing CSSTransitionData::convertToTiming(size_t index) const
{
    ASSERT(index < m_propertyList.size());
    // Note that the backwards fill part is required for delay to work.
    Timing timing = CSSTimingData::convertToTiming(index);
    timing.fillMode = Timing::FillModeBoth;
    return timing;
}

} // namespace blink
<commit_msg>Animations: Change fill mode of transitions to backwards not both<commit_after>// Copyright 2014 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 "config.h"
#include "core/animation/css/CSSTransitionData.h"

#include "core/animation/Timing.h"

namespace blink {

CSSTransitionData::CSSTransitionData()
{
    m_propertyList.append(initialProperty());
}

CSSTransitionData::CSSTransitionData(const CSSTransitionData& other)
    : CSSTimingData(other)
    , m_propertyList(other.m_propertyList)
{
}

bool CSSTransitionData::transitionsMatchForStyleRecalc(const CSSTransitionData& other) const
{
    return m_propertyList == other.m_propertyList;
}

Timing CSSTransitionData::convertToTiming(size_t index) const
{
    ASSERT(index < m_propertyList.size());
    // Note that the backwards fill part is required for delay to work.
    Timing timing = CSSTimingData::convertToTiming(index);
    timing.fillMode = Timing::FillModeBackwards;
    return timing;
}

} // namespace blink
<|endoftext|>


<commit_before>#include "ConnectionList.hpp"

void AbstractConnection::disconnect()
{
	ThreadDataLocker lock1(outerLock_);
	ThreadDataLocker lock2(innerLock_);
	doDisconnect();
}

bool AbstractConnection::tryDisconnectWithLock(ThreadDataRef const & lock)
{
	if(lock != outerLock_) return false;
	ThreadDataLocker lock2(innerLock_);
	doDisconnect();
	return true;
}

void AbstractConnection::doDisconnect()
{
	if(!sourceList_ && !targetList_) return;
	assert(sourceList_ && targetList_);

	{
		ConnectionsVector & connections = sourceList_->data_.mutableRef();
		AbstractConnection * & xs = connections[sourceIndex_];
		assert(xs == this);
		xs = connections.back();
		xs->sourceIndex_ = sourceIndex_;
		connections.pop_back();
		sourceIndex_ = npos; sourceList_ = 0;
		release();
	}
	{
		ConnectionsVector & connections = targetList_->data_.mutableRef();
		AbstractConnection * & xt = connections[targetIndex_];
		assert(xt == this);
		xt = connections.back();
		xt->targetIndex_ = targetIndex_;
		connections.pop_back();
		targetIndex_ = npos; targetList_ = 0;
		release();
	}
}

ConnectionList::ConnectionList()
	: lock_(ThreadDataRef::current())
	, data_()
{
}

ConnectionList::~ConnectionList()
{
	assert(!data_.isBorrowed());
	disconnectAll();
}

void ConnectionList::connect(ConnectionList * peer, AbstractConnection * conn)
{
	conn->outerLock_ = this->lock_;
	conn->innerLock_ = peer->lock_;
	conn->outerLock_.makeBefore(conn->innerLock_);

	ThreadDataLocker lock1(conn->outerLock_);
	ThreadDataLocker lock2(conn->innerLock_);

	{
		assert(!conn->sourceList_ && conn->sourceIndex_ == AbstractConnection::npos);
		ConnectionsVector & connections = data_.mutableRef();
		conn->sourceList_ = this;
		conn->sourceIndex_ = connections.size();
		connections.push_back(conn);
		conn->retain();
	}
	{
		assert(!conn->targetList_ && conn->targetIndex_ == AbstractConnection::npos);
		ConnectionsVector & connections = data_.mutableRef();
		conn->targetList_ = peer;
		conn->targetIndex_ = connections.size();
		connections.push_back(conn);
		conn->retain();
	}
}

#define mutable_iterate(it, container) \
	ConnectionsVector::iterator it = (container).begin(); it != (container).end(); ++it

#define const_iterate(it, container) \
	ConnectionsVector::const_iterator it = (container).begin(); it != (container).end(); ++it

class ConnectionList::NullComparer
{
public:
	bool operator()(AbstractConnection const * conn) const { (void)conn; return true; }
};

class ConnectionList::DelegateComparer
{
public:
	DelegateComparer(AbstractDelegate const & deleg) : deleg_(deleg) {}
	bool operator()(AbstractConnection const * conn) const { return conn->recieverDelegate() == deleg_; }
private:
	AbstractDelegate const & deleg_;
};

class ConnectionList::PeerComparer
{
public:
	PeerComparer(ConnectionList * peer) : peer_(peer) {}
	bool operator()(AbstractConnection const * conn) const { return conn->hasPeer(peer_); }
private:
	ConnectionList * const peer_;
};

class ConnectionList::FullComparer
{
public:
	FullComparer(ConnectionList * peer, AbstractDelegate const & deleg) : e_(peer), d_(deleg) {}
	bool operator()(AbstractConnection const * conn) const { return e_(conn) && d_(conn); }
private:
	PeerComparer e_;
	DelegateComparer d_;
};

size_t ConnectionList::connectionCount() const
{
	ThreadDataLocker lock(lock_);
	return data_.constRef().size();
}

template<class Comparer> inline size_t ConnectionList::getConnectionCount(Comparer const & comp) const
{
	ThreadDataLocker lock(lock_);
	ConnectionsVector const & connections = data_.constRef();
	size_t retVal = 0;
	for(const_iterate(it, connections))
	{
		AbstractConnection const * conn = *it;
		if(comp(conn)) ++retVal;
	}
	return retVal;
}

size_t ConnectionList::connectionCount(AbstractDelegate const & deleg) const
{
	DelegateComparer comp(deleg);
	return getConnectionCount(comp);
}

size_t ConnectionList::connectionCount(ConnectionList * peer) const
{
	PeerComparer comp(peer);
	return getConnectionCount(comp);
}

size_t ConnectionList::connectionCount(ConnectionList * peer, AbstractDelegate const & deleg) const
{
	FullComparer comp(peer, deleg);
	return getConnectionCount(comp);
}

bool ConnectionList::hasConnections() const
{
	ThreadDataLocker lock(lock_);
	return !data_.constRef().empty();
}

template<class Comparer> inline bool ConnectionList::getHasConnections(Comparer const & comp) const
{
	ThreadDataLocker lock(lock_);
	ConnectionsVector const & connections = data_.constRef();
	for(const_iterate(it, connections))
	{
		AbstractConnection const * conn = *it;
		if(comp(conn)) return true;
	}
	return false;
}

bool ConnectionList::hasConnections(AbstractDelegate const & deleg) const
{
	DelegateComparer comp(deleg);
	return getHasConnections(comp);
}

bool ConnectionList::hasConnections(ConnectionList * peer) const
{
	PeerComparer comp(peer);
	return getHasConnections(comp);
}

bool ConnectionList::hasConnections(ConnectionList * peer, AbstractDelegate const & deleg) const
{
	FullComparer comp(peer, deleg);
	return getHasConnections(comp);
}

template<class Comparer> inline size_t ConnectionList::doDisconnectAll(Comparer const & comp)
{
	ConnectionsVector needRelock;
	size_t retVal = 0;
	{
		ThreadDataLocker lock(lock_);
		ConnectionsVector & connections = data_.mutableRef();
		for(size_t i = 0; i < connections.size(); )
		{
			AbstractConnection * conn = connections.at(i);
			if(!comp(conn))
			{
				++i;
				continue;
			}
			++retVal;
			bool done = conn->tryDisconnectWithLock(lock_);
			if(!done)
			{
				conn->retain();
				needRelock.push_back(conn);
				++i;
			}
		}
	}
	for(const_iterate(it, needRelock))
	{
		AbstractConnection * conn = *it;
		conn->disconnect();
		conn->release();
	}
	return retVal;
}

size_t ConnectionList::disconnectAll()
{
	NullComparer comp;
	return doDisconnectAll(comp);
}

size_t ConnectionList::disconnectAll(AbstractDelegate const & deleg)
{
	DelegateComparer comp(deleg);
	return doDisconnectAll(comp);
}

size_t ConnectionList::disconnectAll(ConnectionList * peer, AbstractDelegate const & deleg)
{
	FullComparer comp(peer, deleg);
	return doDisconnectAll(comp);
}

size_t ConnectionList::disconnectAll(ConnectionList * peer)
{
	PeerComparer comp(peer);
	return doDisconnectAll(comp);
}

template<class Comparer> inline bool ConnectionList::doDisconnectOne(Comparer const & comp)
{
	AbstractConnection * needRelock = 0;
	{
		ThreadDataLocker lock(lock_);
		ConnectionsVector & connections = data_.mutableRef();
		for(size_t i = 0; i < connections.size(); )
		{
			AbstractConnection * conn = connections.at(i);
			if(!comp(conn))
			{
				++i;
				continue;
			}
			bool done = conn->tryDisconnectWithLock(lock_);
			if(done) return true;
			needRelock = conn;
			conn->retain();
			break;
		}
	}

	if(!needRelock) return false;

	needRelock->disconnect();
	needRelock->release();
	return true;
}

bool ConnectionList::disconnectOne(AbstractDelegate const & deleg)
{
	DelegateComparer comp(deleg);
	return doDisconnectOne(comp);
}

bool ConnectionList::disconnectOne(ConnectionList * peer)
{
	PeerComparer comp(peer);
	return doDisconnectOne(comp);
}

bool ConnectionList::disconnectOne(ConnectionList * peer, AbstractDelegate const & deleg)
{
	FullComparer comp(peer, deleg);
	return doDisconnectOne(comp);
}
<commit_msg>-: Fixed: bug in ConnectionList::connect()<commit_after>#include "ConnectionList.hpp"

void AbstractConnection::disconnect()
{
	ThreadDataLocker lock1(outerLock_);
	ThreadDataLocker lock2(innerLock_);
	doDisconnect();
}

bool AbstractConnection::tryDisconnectWithLock(ThreadDataRef const & lock)
{
	if(lock != outerLock_) return false;
	ThreadDataLocker lock2(innerLock_);
	doDisconnect();
	return true;
}

void AbstractConnection::doDisconnect()
{
	if(!sourceList_ && !targetList_) return;
	assert(sourceList_ && targetList_);

	{
		ConnectionsVector & connections = sourceList_->data_.mutableRef();
		AbstractConnection * & xs = connections[sourceIndex_];
		assert(xs == this);
		xs = connections.back();
		xs->sourceIndex_ = sourceIndex_;
		connections.pop_back();
		sourceIndex_ = npos; sourceList_ = 0;
		release();
	}
	{
		ConnectionsVector & connections = targetList_->data_.mutableRef();
		AbstractConnection * & xt = connections[targetIndex_];
		assert(xt == this);
		xt = connections.back();
		xt->targetIndex_ = targetIndex_;
		connections.pop_back();
		targetIndex_ = npos; targetList_ = 0;
		release();
	}
}

ConnectionList::ConnectionList()
	: lock_(ThreadDataRef::current())
	, data_()
{
}

ConnectionList::~ConnectionList()
{
	assert(!data_.isBorrowed());
	disconnectAll();
}

void ConnectionList::connect(ConnectionList * peer, AbstractConnection * conn)
{
	conn->outerLock_ = this->lock_;
	conn->innerLock_ = peer->lock_;
	conn->outerLock_.makeBefore(conn->innerLock_);

	ThreadDataLocker lock1(conn->outerLock_);
	ThreadDataLocker lock2(conn->innerLock_);

	{
		assert(!conn->sourceList_ && conn->sourceIndex_ == AbstractConnection::npos);
		ConnectionsVector & connections = data_.mutableRef();
		conn->sourceList_ = this;
		conn->sourceIndex_ = connections.size();
		connections.push_back(conn);
		conn->retain();
	}
	{
		assert(!conn->targetList_ && conn->targetIndex_ == AbstractConnection::npos);
		ConnectionsVector & connections = peer->data_.mutableRef();
		conn->targetList_ = peer;
		conn->targetIndex_ = connections.size();
		connections.push_back(conn);
		conn->retain();
	}
}

#define mutable_iterate(it, container) \
	ConnectionsVector::iterator it = (container).begin(); it != (container).end(); ++it

#define const_iterate(it, container) \
	ConnectionsVector::const_iterator it = (container).begin(); it != (container).end(); ++it

class ConnectionList::NullComparer
{
public:
	bool operator()(AbstractConnection const * conn) const { (void)conn; return true; }
};

class ConnectionList::DelegateComparer
{
public:
	DelegateComparer(AbstractDelegate const & deleg) : deleg_(deleg) {}
	bool operator()(AbstractConnection const * conn) const { return conn->recieverDelegate() == deleg_; }
private:
	AbstractDelegate const & deleg_;
};

class ConnectionList::PeerComparer
{
public:
	PeerComparer(ConnectionList * peer) : peer_(peer) {}
	bool operator()(AbstractConnection const * conn) const { return conn->hasPeer(peer_); }
private:
	ConnectionList * const peer_;
};

class ConnectionList::FullComparer
{
public:
	FullComparer(ConnectionList * peer, AbstractDelegate const & deleg) : e_(peer), d_(deleg) {}
	bool operator()(AbstractConnection const * conn) const { return e_(conn) && d_(conn); }
private:
	PeerComparer e_;
	DelegateComparer d_;
};

size_t ConnectionList::connectionCount() const
{
	ThreadDataLocker lock(lock_);
	return data_.constRef().size();
}

template<class Comparer> inline size_t ConnectionList::getConnectionCount(Comparer const & comp) const
{
	ThreadDataLocker lock(lock_);
	ConnectionsVector const & connections = data_.constRef();
	size_t retVal = 0;
	for(const_iterate(it, connections))
	{
		AbstractConnection const * conn = *it;
		if(comp(conn)) ++retVal;
	}
	return retVal;
}

size_t ConnectionList::connectionCount(AbstractDelegate const & deleg) const
{
	DelegateComparer comp(deleg);
	return getConnectionCount(comp);
}

size_t ConnectionList::connectionCount(ConnectionList * peer) const
{
	PeerComparer comp(peer);
	return getConnectionCount(comp);
}

size_t ConnectionList::connectionCount(ConnectionList * peer, AbstractDelegate const & deleg) const
{
	FullComparer comp(peer, deleg);
	return getConnectionCount(comp);
}

bool ConnectionList::hasConnections() const
{
	ThreadDataLocker lock(lock_);
	return !data_.constRef().empty();
}

template<class Comparer> inline bool ConnectionList::getHasConnections(Comparer const & comp) const
{
	ThreadDataLocker lock(lock_);
	ConnectionsVector const & connections = data_.constRef();
	for(const_iterate(it, connections))
	{
		AbstractConnection const * conn = *it;
		if(comp(conn)) return true;
	}
	return false;
}

bool ConnectionList::hasConnections(AbstractDelegate const & deleg) const
{
	DelegateComparer comp(deleg);
	return getHasConnections(comp);
}

bool ConnectionList::hasConnections(ConnectionList * peer) const
{
	PeerComparer comp(peer);
	return getHasConnections(comp);
}

bool ConnectionList::hasConnections(ConnectionList * peer, AbstractDelegate const & deleg) const
{
	FullComparer comp(peer, deleg);
	return getHasConnections(comp);
}

template<class Comparer> inline size_t ConnectionList::doDisconnectAll(Comparer const & comp)
{
	ConnectionsVector needRelock;
	size_t retVal = 0;
	{
		ThreadDataLocker lock(lock_);
		ConnectionsVector & connections = data_.mutableRef();
		for(size_t i = 0; i < connections.size(); )
		{
			AbstractConnection * conn = connections.at(i);
			if(!comp(conn))
			{
				++i;
				continue;
			}
			++retVal;
			bool done = conn->tryDisconnectWithLock(lock_);
			if(!done)
			{
				conn->retain();
				needRelock.push_back(conn);
				++i;
			}
		}
	}
	for(const_iterate(it, needRelock))
	{
		AbstractConnection * conn = *it;
		conn->disconnect();
		conn->release();
	}
	return retVal;
}

size_t ConnectionList::disconnectAll()
{
	NullComparer comp;
	return doDisconnectAll(comp);
}

size_t ConnectionList::disconnectAll(AbstractDelegate const & deleg)
{
	DelegateComparer comp(deleg);
	return doDisconnectAll(comp);
}

size_t ConnectionList::disconnectAll(ConnectionList * peer, AbstractDelegate const & deleg)
{
	FullComparer comp(peer, deleg);
	return doDisconnectAll(comp);
}

size_t ConnectionList::disconnectAll(ConnectionList * peer)
{
	PeerComparer comp(peer);
	return doDisconnectAll(comp);
}

template<class Comparer> inline bool ConnectionList::doDisconnectOne(Comparer const & comp)
{
	AbstractConnection * needRelock = 0;
	{
		ThreadDataLocker lock(lock_);
		ConnectionsVector & connections = data_.mutableRef();
		for(size_t i = 0; i < connections.size(); )
		{
			AbstractConnection * conn = connections.at(i);
			if(!comp(conn))
			{
				++i;
				continue;
			}
			bool done = conn->tryDisconnectWithLock(lock_);
			if(done) return true;
			needRelock = conn;
			conn->retain();
			break;
		}
	}

	if(!needRelock) return false;

	needRelock->disconnect();
	needRelock->release();
	return true;
}

bool ConnectionList::disconnectOne(AbstractDelegate const & deleg)
{
	DelegateComparer comp(deleg);
	return doDisconnectOne(comp);
}

bool ConnectionList::disconnectOne(ConnectionList * peer)
{
	PeerComparer comp(peer);
	return doDisconnectOne(comp);
}

bool ConnectionList::disconnectOne(ConnectionList * peer, AbstractDelegate const & deleg)
{
	FullComparer comp(peer, deleg);
	return doDisconnectOne(comp);
}
<|endoftext|>


<commit_before>/****************************************************************************
**
** Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the QtMultimedia module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain
** additional rights. These rights are described in the Nokia Qt LGPL
** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
** package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at http://www.qtsoftware.com/contact.
** $QT_END_LICENSE$
**
****************************************************************************/

#include "qmediaplayercontrol.h"
#include "qabstractmediacontrol_p.h"
#include "qmediasource.h"

/*!
    \class QMediaPlayerControl
    \ingroup multimedia

    \preliminary
    \brief The abstract class for controling media playback, this is proivided
    by a QAbstractMediaService object, and is used by QMediaPlayer for playback.

    \sa QAbstractMediaSerice, QMediaPlayer
*/

QMediaPlayerControl::~QMediaPlayerControl()
{
}

QMediaPlayerControl::QMediaPlayerControl(QObject *parent):
    QAbstractMediaControl(*new QAbstractMediaControlPrivate, parent)
{
//    addPropertyWatch("position");
}
<commit_msg>Fix typos.<commit_after>/****************************************************************************
**
** Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the QtMultimedia module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain
** additional rights. These rights are described in the Nokia Qt LGPL
** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
** package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at http://www.qtsoftware.com/contact.
** $QT_END_LICENSE$
**
****************************************************************************/

#include "qmediaplayercontrol.h"
#include "qabstractmediacontrol_p.h"
#include "qmediasource.h"

/*!
    \class QMediaPlayerControl
    \ingroup multimedia

    \preliminary
    \brief The abstract class for controling media playback, this is provided
    by a QAbstractMediaService object, and is used by QMediaPlayer for playback.

    \sa QAbstractMediaService, QMediaPlayer
*/

QMediaPlayerControl::~QMediaPlayerControl()
{
}

QMediaPlayerControl::QMediaPlayerControl(QObject *parent):
    QAbstractMediaControl(*new QAbstractMediaControlPrivate, parent)
{
//    addPropertyWatch("position");
}
<|endoftext|>


<commit_before>/* dtkComposerEvaluator.cpp ---
 *
 * Author: tkloczko
 * Copyright (C) 2011 - Thibaud Kloczko, Inria.
 * Created: Mon Jan 30 11:34:40 2012 (+0100)
 * Version: $Id$
 * Last-Updated: Fri Sep 28 23:01:51 2012 (+0200)
 *           By: tkloczko
 *     Update #: 782
 */

/* Commentary:
 *
 */

/* Change log:
 *
 */

#include "dtkComposerEvaluator.h"
#include "dtkComposerEvaluator_p.h"
#include "dtkComposerGraph.h"
#include "dtkComposerGraphEdge.h"
#include "dtkComposerGraphNode.h"
#include "dtkComposerGraphNodeBegin.h"
#include "dtkComposerGraphNodeEnd.h"

#include <dtkLog/dtkLog.h>
#include <dtkNotification/dtkNotification.h>

#include <QtCore>

// /////////////////////////////////////////////////////////////////
// Helper definitions
// /////////////////////////////////////////////////////////////////

#define DTK_DEBUG_COMPOSER_EVALUATION 0

// /////////////////////////////////////////////////////////////////
// dtkComposerEvaluatorPrivate
// /////////////////////////////////////////////////////////////////

// /////////////////////////////////////////////////////////////////
// dtkComposerEvaluator
// /////////////////////////////////////////////////////////////////

dtkComposerEvaluator::dtkComposerEvaluator(QObject *parent) : QObject(parent), d(new dtkComposerEvaluatorPrivate)
{
    d->should_stop = false;
    d->stack.setCapacity(1024);
    d->max_stack_size = 0;
}

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

    d = NULL;
}

void dtkComposerEvaluator::setGraph(dtkComposerGraph *graph)
{
    d->graph = graph;
}

void dtkComposerEvaluator::run(bool run_concurrent)
{
    QTime time; time.start();

    d->stack.clear();
    d->stack.append(d->graph->root());

    emit evaluationStarted();

    while (this->step(run_concurrent) && !d->should_stop);
    if (!d->should_stop) {
        QString msg = QString("Evaluation finished in %1 ms").arg(time.elapsed());
        dtkInfo() << msg;
        dtkNotify(msg,30000);
        d->max_stack_size = 0;
    } else {
        QString msg = QString("Evaluation stopped after %1 ms").arg(time.elapsed());
        dtkInfo() << msg;
        dtkNotify(msg,30000);
    }

    d->should_stop = false;

    emit evaluationStopped();
}

void dtkComposerEvaluator::stop(void)
{
    d->should_stop = true;
}

void dtkComposerEvaluator::reset(void)
{
    d->stack.clear();
    d->should_stop   = false;
}

void dtkComposerEvaluator::cont(bool run_concurrent)
{

    if (d->stack.isEmpty()) {
        this->run(run_concurrent);
        return;
    }

    while (this->step(run_concurrent) && !d->should_stop);
    if (!d->should_stop) {
        QString msg = QString("Evaluation resumed and finished");
        dtkInfo() << msg;
        dtkNotify(msg,30000);
    } else {
        QString msg = QString("Evaluation stopped ");
        dtkInfo() << msg;
        dtkNotify(msg,30000);
        dtkInfo() << "stack size: " << d->stack.size();
    }

    d->should_stop = false;

    emit evaluationStopped();
}

void dtkComposerEvaluator::logStack(void)
{
    // QListIterator<dtkComposerGraphNode *> i(d->stack);
    // dtkDebug() << "stack content:";
    // while (i.hasNext())
    //     dtkDebug() << i.next()->title();
    // dtkDebug() << "stack end";
}

void dtkComposerEvaluator::next(bool run_concurrent)
{
    if (d->stack.isEmpty())
        return;

    dtkComposerGraphNode *first = d->stack.first();
    if (dynamic_cast<dtkComposerGraphNodeBegin *>(first)) {
        // Begin node, look for the corresponding End node
        dtkComposerGraphNode *end = NULL;
        foreach(dtkComposerGraphNode *n,  d->graph->nodes())
            if ((dynamic_cast<dtkComposerGraphNodeEnd *>(n)) && n->wrapee() == first->wrapee()) {
                end = n;
                end->setBreakPoint();
                break;
            }
        while (d->current != end) // we must continue if a node inside the begin/end contains a breakpoint
            this->cont(run_concurrent);
        this->step(run_concurrent); // eval End
    } else {
        this->step(run_concurrent);
    }
}

bool dtkComposerEvaluator::step(bool run_concurrent)
{
    if (d->stack.isEmpty())
        return false;

    d->current = d->stack.takeFirst();
    // dtkTrace() << "handle " << d->current->title();
    bool runnable = true;

    dtkComposerGraphNodeList::const_iterator it;
    dtkComposerGraphNodeList::const_iterator ite;
    dtkComposerGraphNode *node ;

    dtkComposerGraphNodeList preds = d->current->predecessors();
    it = preds.constBegin();
    ite = preds.constEnd();
    while(it != ite) {
        node = *it++;
        if (node->status() != dtkComposerGraphNode::Done) {
            if (!node->endloop()) {
                runnable = false;
                break;
            } else {
                // predecessor is an end loop, we can continue, but we must unset the endloop flag.
                // dtkTrace() << "predecessor of "<< d->current->title() << " is an end loop, continue" << node->title();
                node->setEndLoop(false);
            }
        }
    }

    if (runnable) {
        if (d->current->breakpoint() && d->current->status() == dtkComposerGraphNode::Ready ) {
            dtkTrace() << "break point reached";
            d->current->setStatus(dtkComposerGraphNode::Break);
            d->stack.append( d->current);
            return false;
        }
        if (run_concurrent && (d->current->kind() == dtkComposerGraphNode::Process)){
            // dtkDebug() << "running process node in another thread"<< d->current->title();
            QtConcurrent::run(d->current, &dtkComposerGraphNode::eval);
        } else if ((d->current->kind() == dtkComposerGraphNode::View)) {
            connect(this, SIGNAL(runMainThread()), d->current, SLOT(eval()),Qt::BlockingQueuedConnection);
            // dtkTrace() << "emit signal and wait for GUI thread to run the node";
            emit runMainThread();
            disconnect(this, SIGNAL(runMainThread()), d->current, SLOT(eval()));
        } else {
            // dtkTrace() << "evaluating leaf node"<< d->current->title();
            d->current->eval();
        }

        dtkComposerGraphNodeList s = d->current->successors();
        it = s.constBegin();
        ite = s.constEnd();
        while(it != ite) {
            node = *it++;
            bool stacked = false;
            if (!d->stack.isEmpty()) {
                int j = d->stack.firstIndex();
                while(j <= d->stack.lastIndex() && !stacked)
                    stacked = (d->stack.at(j++) == node);
            }
            // dtkTrace() << "add successor to stack " << node->title();
            if (!stacked)
                d->stack.append(node);
        }
    } else if (run_concurrent) {
        dtkTrace() << "add back current node to stack: "<< d->current->title();
        d->stack.append(d->current);
    }
    // if (d->stack.size() > d->max_stack_size) {
    //     d->max_stack_size = d->stack.size();
    //     dtkDebug() << "Max stack size raised: "<< d->max_stack_size;
    // }

    return !d->stack.isEmpty();
}
<commit_msg>Lats one ;-) ....<commit_after>/* dtkComposerEvaluator.cpp ---
 *
 * Author: tkloczko
 * Copyright (C) 2011 - Thibaud Kloczko, Inria.
 * Created: Mon Jan 30 11:34:40 2012 (+0100)
 * Version: $Id$
 * Last-Updated: Fri Sep 28 23:59:12 2012 (+0200)
 *           By: tkloczko
 *     Update #: 787
 */

/* Commentary:
 *
 */

/* Change log:
 *
 */

#include "dtkComposerEvaluator.h"
#include "dtkComposerEvaluator_p.h"
#include "dtkComposerGraph.h"
#include "dtkComposerGraphEdge.h"
#include "dtkComposerGraphNode.h"
#include "dtkComposerGraphNodeBegin.h"
#include "dtkComposerGraphNodeEnd.h"

#include <dtkLog/dtkLog.h>
#include <dtkNotification/dtkNotification.h>

#include <QtCore>

// /////////////////////////////////////////////////////////////////
// Helper definitions
// /////////////////////////////////////////////////////////////////

#define DTK_DEBUG_COMPOSER_EVALUATION 0

// /////////////////////////////////////////////////////////////////
// dtkComposerEvaluatorPrivate
// /////////////////////////////////////////////////////////////////

// /////////////////////////////////////////////////////////////////
// dtkComposerEvaluator
// /////////////////////////////////////////////////////////////////

dtkComposerEvaluator::dtkComposerEvaluator(QObject *parent) : QObject(parent), d(new dtkComposerEvaluatorPrivate)
{
    d->should_stop = false;
    d->stack.setCapacity(1024);
    d->max_stack_size = 0;
}

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

    d = NULL;
}

void dtkComposerEvaluator::setGraph(dtkComposerGraph *graph)
{
    d->graph = graph;
}

void dtkComposerEvaluator::run(bool run_concurrent)
{
    QTime time; time.start();

    d->stack.clear();
    d->stack.append(d->graph->root());

    emit evaluationStarted();

    while (this->step(run_concurrent) && !d->should_stop);
    if (!d->should_stop) {
        QString msg = QString("Evaluation finished in %1 ms").arg(time.elapsed());
        dtkInfo() << msg;
        dtkNotify(msg,30000);
        d->max_stack_size = 0;
    } else {
        QString msg = QString("Evaluation stopped after %1 ms").arg(time.elapsed());
        dtkInfo() << msg;
        dtkNotify(msg,30000);
    }

    d->should_stop = false;

    emit evaluationStopped();
}

void dtkComposerEvaluator::stop(void)
{
    d->should_stop = true;
}

void dtkComposerEvaluator::reset(void)
{
    d->stack.clear();
    d->should_stop   = false;
}

void dtkComposerEvaluator::cont(bool run_concurrent)
{

    if (d->stack.isEmpty()) {
        this->run(run_concurrent);
        return;
    }

    while (this->step(run_concurrent) && !d->should_stop);
    if (!d->should_stop) {
        QString msg = QString("Evaluation resumed and finished");
        dtkInfo() << msg;
        dtkNotify(msg,30000);
    } else {
        QString msg = QString("Evaluation stopped ");
        dtkInfo() << msg;
        dtkNotify(msg,30000);
        dtkInfo() << "stack size: " << d->stack.size();
    }

    d->should_stop = false;

    emit evaluationStopped();
}

void dtkComposerEvaluator::logStack(void)
{
    // QListIterator<dtkComposerGraphNode *> i(d->stack);
    // dtkDebug() << "stack content:";
    // while (i.hasNext())
    //     dtkDebug() << i.next()->title();
    // dtkDebug() << "stack end";
}

void dtkComposerEvaluator::next(bool run_concurrent)
{
    if (d->stack.isEmpty())
        return;

    dtkComposerGraphNode *first = d->stack.first();
    if (dynamic_cast<dtkComposerGraphNodeBegin *>(first)) {
        // Begin node, look for the corresponding End node
        dtkComposerGraphNode *end = NULL;
        foreach(dtkComposerGraphNode *n,  d->graph->nodes())
            if ((dynamic_cast<dtkComposerGraphNodeEnd *>(n)) && n->wrapee() == first->wrapee()) {
                end = n;
                end->setBreakPoint();
                break;
            }
        while (d->current != end) // we must continue if a node inside the begin/end contains a breakpoint
            this->cont(run_concurrent);
        this->step(run_concurrent); // eval End
    } else {
        this->step(run_concurrent);
    }
}

bool dtkComposerEvaluator::step(bool run_concurrent)
{
    if (d->stack.isEmpty())
        return false;

    d->current = d->stack.takeFirst();
    // dtkTrace() << "handle " << d->current->title();
    bool runnable = true;

    dtkComposerGraphNodeList::const_iterator it;
    dtkComposerGraphNodeList::const_iterator ite;
    dtkComposerGraphNode *node ;

    dtkComposerGraphNodeList preds = d->current->predecessors();
    it = preds.constBegin();
    ite = preds.constEnd();
    while(it != ite) {
        node = *it++;
        if (node->status() != dtkComposerGraphNode::Done) {
            if (!node->endloop()) {
                runnable = false;
                break;
            } else {
                // predecessor is an end loop, we can continue, but we must unset the endloop flag.
                // dtkTrace() << "predecessor of "<< d->current->title() << " is an end loop, continue" << node->title();
                node->setEndLoop(false);
            }
        }
    }

    if (runnable) {
        if (d->current->breakpoint() && d->current->status() == dtkComposerGraphNode::Ready ) {
            dtkTrace() << "break point reached";
            d->current->setStatus(dtkComposerGraphNode::Break);
            d->stack.append( d->current);
            return false;
        }
        if (run_concurrent && (d->current->kind() == dtkComposerGraphNode::Process)){
            // dtkDebug() << "running process node in another thread"<< d->current->title();
            QtConcurrent::run(d->current, &dtkComposerGraphNode::eval);
        } else if ((d->current->kind() == dtkComposerGraphNode::View)) {
            connect(this, SIGNAL(runMainThread()), d->current, SLOT(eval()),Qt::BlockingQueuedConnection);
            // dtkTrace() << "emit signal and wait for GUI thread to run the node";
            emit runMainThread();
            disconnect(this, SIGNAL(runMainThread()), d->current, SLOT(eval()));
        } else {
            // dtkTrace() << "evaluating leaf node"<< d->current->title();
            d->current->eval();
        }

        dtkComposerGraphNodeList s = d->current->successors();
        it = s.constBegin();
        ite = s.constEnd();
        if (!d->stack.isEmpty()) {
            while(it != ite) {
                node = *it++;
                bool stacked = false;
                int j = d->stack.firstIndex();
                while(j <= d->stack.lastIndex() && !stacked)
                    stacked = (d->stack.at(j++) == node);
                // dtkTrace() << "add successor to stack " << node->title();
                if (!stacked)
                    d->stack.append(node);
            }
        } else {
            while(it != ite)
                d->stack.append(*it++);
        }

        // while(it != ite) {
        //     node = *it++;
        //     bool stacked = false;
        //     if (!d->stack.isEmpty()) {
        //         int j = d->stack.firstIndex();
        //         while(j <= d->stack.lastIndex() && !stacked)
        //             stacked = (d->stack.at(j++) == node);
        //     }
        //     // dtkTrace() << "add successor to stack " << node->title();
        //     if (!stacked)
        //         d->stack.append(node);
        // }
    } else if (run_concurrent) {
        dtkTrace() << "add back current node to stack: "<< d->current->title();
        d->stack.append(d->current);
    }
    // if (d->stack.size() > d->max_stack_size) {
    //     d->max_stack_size = d->stack.size();
    //     dtkDebug() << "Max stack size raised: "<< d->max_stack_size;
    // }

    return !d->stack.isEmpty();
}
<|endoftext|>


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

 /* @file enginefailure.cpp
 * Helper class for a fixedwing engine failure mode
 *
 * @author Thomas Gubler <thomasgubler@gmail.com>
 */
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include <fcntl.h>

#include <mavlink/mavlink_log.h>
#include <systemlib/err.h>
#include <geo/geo.h>

#include <uORB/uORB.h>
#include <uORB/topics/mission.h>

#include "navigator.h"
#include "enginefailure.h"

#define DELAY_SIGMA	0.01f

EngineFailure::EngineFailure(Navigator *navigator, const char *name) :
	MissionBlock(navigator, name),
	_ef_state(EF_STATE_NONE)
{
	/* load initial params */
	updateParams();
	/* initial reset */
	on_inactive();
}

EngineFailure::~EngineFailure()
{
}

void
EngineFailure::on_inactive()
{
	_ef_state = EF_STATE_NONE;
}

void
EngineFailure::on_activation()
{
	_ef_state = EF_STATE_LOITERDOWN;
	set_ef_item();
}

void
EngineFailure::on_active()
{
	if (is_mission_item_reached()) {
		advance_ef();
		set_ef_item();
	}
}

void
EngineFailure::set_ef_item()
{
	struct position_setpoint_triplet_s *pos_sp_triplet = _navigator->get_position_setpoint_triplet();

	/* make sure we have the latest params */
	updateParams();

	set_previous_pos_setpoint();
	_navigator->set_can_loiter_at_sp(false);

	switch (_ef_state) {
	case EF_STATE_LOITERDOWN: {
		//XXX create mission item at ground (below?) here

		_mission_item.lat = _navigator->get_global_position()->lat;
		_mission_item.lon = _navigator->get_global_position()->lon;
		_mission_item.altitude_is_relative = false;
		 //XXX setting altitude to a very low value, evaluate other options
		_mission_item.altitude = _navigator->get_home_position()->alt - 1000.0f;
		_mission_item.yaw = NAN;
		_mission_item.loiter_radius = _navigator->get_loiter_radius();
		_mission_item.loiter_direction = 1;
		_mission_item.nav_cmd = NAV_CMD_LOITER_UNLIMITED;
		_mission_item.acceptance_radius = _navigator->get_acceptance_radius();
		_mission_item.pitch_min = 0.0f;
		_mission_item.autocontinue = true;
		_mission_item.origin = ORIGIN_ONBOARD;

		_navigator->set_can_loiter_at_sp(true);
		break;
	}
	default:
		break;
	}

	reset_mission_item_reached();

	/* convert mission item to current position setpoint and make it valid */
	mission_item_to_position_setpoint(&_mission_item, &pos_sp_triplet->current);
	pos_sp_triplet->next.valid = false;

	_navigator->set_position_setpoint_triplet_updated();
}

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

 /* @file enginefailure.cpp
 * Helper class for a fixedwing engine failure mode
 *
 * @author Thomas Gubler <thomasgubler@gmail.com>
 */
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include <fcntl.h>

#include <mavlink/mavlink_log.h>
#include <systemlib/err.h>
#include <geo/geo.h>

#include <uORB/uORB.h>
#include <uORB/topics/mission.h>

#include "navigator.h"
#include "enginefailure.h"

#define DELAY_SIGMA	0.01f

EngineFailure::EngineFailure(Navigator *navigator, const char *name) :
	MissionBlock(navigator, name),
	_ef_state(EF_STATE_NONE)
{
	/* load initial params */
	updateParams();
	/* initial reset */
	on_inactive();
}

EngineFailure::~EngineFailure()
{
}

void
EngineFailure::on_inactive()
{
	_ef_state = EF_STATE_NONE;
}

void
EngineFailure::on_activation()
{
	_ef_state = EF_STATE_NONE;
	advance_ef();
	set_ef_item();
}

void
EngineFailure::on_active()
{
	if (is_mission_item_reached()) {
		advance_ef();
		set_ef_item();
	}
}

void
EngineFailure::set_ef_item()
{
	struct position_setpoint_triplet_s *pos_sp_triplet = _navigator->get_position_setpoint_triplet();

	/* make sure we have the latest params */
	updateParams();

	set_previous_pos_setpoint();
	_navigator->set_can_loiter_at_sp(false);

	switch (_ef_state) {
	case EF_STATE_LOITERDOWN: {
		//XXX create mission item at ground (below?) here

		_mission_item.lat = _navigator->get_global_position()->lat;
		_mission_item.lon = _navigator->get_global_position()->lon;
		_mission_item.altitude_is_relative = false;
		 //XXX setting altitude to a very low value, evaluate other options
		_mission_item.altitude = _navigator->get_home_position()->alt - 1000.0f;
		_mission_item.yaw = NAN;
		_mission_item.loiter_radius = _navigator->get_loiter_radius();
		_mission_item.loiter_direction = 1;
		_mission_item.nav_cmd = NAV_CMD_LOITER_UNLIMITED;
		_mission_item.acceptance_radius = _navigator->get_acceptance_radius();
		_mission_item.pitch_min = 0.0f;
		_mission_item.autocontinue = true;
		_mission_item.origin = ORIGIN_ONBOARD;

		_navigator->set_can_loiter_at_sp(true);
		break;
	}
	default:
		break;
	}

	reset_mission_item_reached();

	/* convert mission item to current position setpoint and make it valid */
	mission_item_to_position_setpoint(&_mission_item, &pos_sp_triplet->current);
	pos_sp_triplet->next.valid = false;

	_navigator->set_position_setpoint_triplet_updated();
}

void
EngineFailure::advance_ef()
{
	switch (_ef_state) {
	case EF_STATE_NONE:
		mavlink_log_info(_navigator->get_mavlink_fd(), "#audio: Engine failure. Loitering down");
		_ef_state = EF_STATE_LOITERDOWN;
		break;
	default:
		break;
	}
}
<|endoftext|>