<commit_before>//----------------------------  point_value_history_01.cc  ---------------------------
//    $Id$
//    Version: $Name$
//
//    Copyright (C) 2009, 2010 by the deal.II authors and Michael Rapson
//
//    This file is subject to QPL and may not be  distributed
//    without copyright and license information. Please refer
//    to the file deal.II/doc/license.html for the  text  and
//    further information on this license.
//
//----------------------------  point_value_history_01.cc  ---------------------------

// ************************************************
// A test program for the PointValueHistory class
// Currently this only tests a finite element system
// with 3 components, on a hyper cube and with Vectors.
// The testing is done in two dimensions.
// ************************************************

#include <base/quadrature_lib.h>

#include <dofs/dof_handler.h>
#include <dofs/dof_accessor.h>
#include <dofs/dof_renumbering.h>

#include <fe/fe_q.h>
#include <fe/fe_system.h>
#include <fe/fe_values.h>

#include <grid/tria.h>
#include <grid/tria_accessor.h>
#include <grid/tria_iterator.h>
#include <grid/grid_generator.h>

#include <lac/vector.h>

#include <numerics/point_value_history.h>

#include <fstream>

using namespace dealii;

template <int dim>
class TestPointValueHistory
{
public:
    TestPointValueHistory();
    void run();

private:
    Triangulation <dim> triangulation;
    FESystem<dim> finite_element;
    DoFHandler <dim > dof_handler;
    PointValueHistory <dim> test_copy;
};

template <int dim>
TestPointValueHistory<dim>::TestPointValueHistory() :
finite_element(FE_Q<dim > (1 + 1), dim, FE_Q<dim > (1), 1),

dof_handler(triangulation)
{ }

template <int dim>
void TestPointValueHistory<dim>::run()
{
    // Make a triangulation
    GridGenerator::hyper_cube(triangulation, 0, 1);
    triangulation.refine_global(2); // refine 2 times to make 5 nodes per side

    // make a DOF handler, a model solution filled with ones and a flow vector
    FESystem<dim> finite_element(FE_Q<dim > (1 + 1), dim, FE_Q<dim > (1), 1);
    DoFHandler <dim > dof_handler(triangulation);
    dof_handler.distribute_dofs(finite_element);
    DoFRenumbering::Cuthill_McKee(dof_handler);

    // renumber for components so that same dof indices are used for BlockVectors and normal Vectors
    std::vector<unsigned int> block_component(dim + 1, 0);
    block_component[dim] = 1; // component dim = pressure component!
    DoFRenumbering::component_wise(dof_handler, block_component);

    // Vector
    Vector <double> solution, post_processed, poles;
    solution.reinit(dof_handler.n_dofs());
    post_processed.reinit(dof_handler.n_dofs());
    poles.reinit(dof_handler.n_dofs());

    // set up a simple linear discrete time system so that time plots vary
    // over the mesh but can be easily checked. The basic idea is to have each
    // component of the fe_system to depend on a specific dimension (i.e component 0
    // depends on dim 0, etc. % dim handles the case where there are more components
    // than dimensions. The code breaks down at the edges of the mesh and this is
    // not corrected for.
    {
        QGauss<dim> quadrature_formula(2);
        FEValues<dim> fe_values(finite_element, quadrature_formula, update_values | update_quadrature_points); // just need local_dof_indices and quadrature_points

        std::vector<unsigned int> local_dof_indices(finite_element.dofs_per_cell);
        std::vector<Point<dim> > dof_locations(finite_element.dofs_per_cell);
        Vector<double> cell_pole(finite_element.dofs_per_cell);

        typename DoFHandler<dim>::active_cell_iterator cell, endc;
        cell = dof_handler.begin_active();
        endc = dof_handler.end();
        for (; cell != endc; ++cell)
        {
            fe_values.reinit(cell); // need to get local_dof_indices
            cell->get_dof_indices(local_dof_indices);
            dof_locations = fe_values.get_quadrature_points();
            cell_pole = 0;
            for (unsigned int dof = 0; dof != finite_element.dofs_per_cell; dof++)
            {
                unsigned int dof_component = finite_element.system_to_component_index(dof).first;

                for (unsigned int q_point = 0; q_point < quadrature_formula.size(); ++q_point)
                {
                    cell_pole(dof) += (fe_values.shape_value(dof, q_point) * dof_locations [q_point] (dof_component % dim));
                }
                solution(local_dof_indices [dof]) = 1; // start all solutions at 1
                poles(local_dof_indices[dof]) -= cell_pole(dof);

                if (dof_component == dim) // components start numbering at 0
                    poles(local_dof_indices[dof]) = -0.1; // dim+1th component is not handled well by the code above
            }

        } // loop over all cells
        poles.add(1.0); // slow down the pole settling time
        post_processed.add(3.0); // set to starting value.
    }

    // Setup monitor node to print variation over time
    unsigned int n_inputs = 1;
    PointValueHistory<dim> node_monitor (dof_handler, n_inputs);
    PointValueHistory<dim> no_dof_handler (n_inputs);

    // check that the assignment operator is valid
    test_copy = node_monitor;
    test_copy.add_point(Point<2>(1, 0.2));
    test_copy.add_field_name("Solution");
    std::vector < std::vector <Point <dim> > > selected_locations;
    test_copy.get_points(selected_locations);
    test_copy.mark_locations();
    test_copy.close();
    test_copy.start_new_dataset(0.1);
    test_copy.evaluate_field("Solution", solution);
    std::vector <double> input_value(n_inputs, 1);
    test_copy.push_back_independent(input_value);
    test_copy.write_gnuplot("point_value_history_01/Test_Copy");
    test_copy.status(deallog.get_file_stream());
    test_copy.clear ();
    // end of assignment operator check

    {
        node_monitor.add_field_name("Solution");
        node_monitor.add_field_name("Post Processed Vector"); // not sensitive to spaces

        // two alternatives here, adding a point at a time or a vector of points
        // 2d points
        std::vector <Point < 2 > > point_vector(5, Point < 2 > ());
        point_vector[0] = Point < 2 > (0, 0); // some of these points will hit a node, others won't
        point_vector[1] = Point < 2 > (0.25, 0);
        point_vector[2] = Point < 2 > (0.25, 0.45);
        point_vector[3] = Point < 2 > (0.45, 0.45);
        point_vector[4] = Point < 2 > (0.8, 0.8);

        node_monitor.add_points(point_vector);
        node_monitor.add_point(Point<2>(1, 0.2)); // add a single point

        // MonitorNode requires that the instance is 'closed' before any data is added
        // this ensures that points are not added once time starts.
        node_monitor.close();
        no_dof_handler.close(); // closing still required!

        std::vector < std::vector <Point <dim> > > selected_locations;
        node_monitor.get_points(selected_locations);
	// write output to a file
        Vector<double> node_locations = node_monitor.mark_locations();
	// write output to a file
    }

    double delta_t = 0.000001;
    double t_max = 0.00001;

    for (double time = 0; time < t_max; time = time + delta_t)
    {
        node_monitor.start_new_dataset(time);
        no_dof_handler.start_new_dataset(time);
        // time and input are special, they don't vary over the mesh.

        std::vector <double> input_value(n_inputs, 1); // manufacture an input value
        node_monitor.push_back_independent(input_value);
        no_dof_handler.push_back_independent(input_value);
        node_monitor.evaluate_field("Solution", solution);
        node_monitor.evaluate_field("Post Processed Vector", post_processed);

        solution.scale(poles); // decaying exponentials of varying time constants
        post_processed = solution;
        post_processed.add(2.0); // simple post processing, giving it a dc offset
    }
    node_monitor.write_gnuplot("point_value_history_01/node");
    no_dof_handler.write_gnuplot("point_value_history_01/no_dof");

    node_monitor.status (deallog.get_file_stream());
    no_dof_handler.status (deallog.get_file_stream());

    deallog << "Starting data files" << std::endl;

				     // copy all the data into deallog and
				     // delete those files
    const std::string filenames[]
      = { "point_value_history_01/node_00.gpl",
	  "point_value_history_01/node_01.gpl",
	  "point_value_history_01/node_02.gpl",
	  "point_value_history_01/node_03.gpl",
	  "point_value_history_01/node_04.gpl",
	  "point_value_history_01/node_05.gpl",
	  "point_value_history_01/node_indep.gpl",
	  "point_value_history_01/Test_Copy_00.gpl",
	  "point_value_history_01/Test_Copy_indep.gpl",
	  "point_value_history_01/no_dof_indep.gpl" };

    for (unsigned int i=0; i<sizeof(filenames)/sizeof(filenames[0]); ++i)
      {
	deallog << "Copying output file " << filenames[i]
		<< std::endl;

	std::ifstream in(filenames[i].c_str());
	AssertThrow (in, ExcIO());

	std::string s;
	while (in)
	  {
	    std::getline (in, s);
	    deallog << s << std::endl;
	  }

	std::remove (filenames[i].c_str());

	deallog << std::endl;
      }
}

int main()
{
    std::ofstream logfile("point_value_history_01/output");
    logfile << std::setprecision(2);
    deallog << std::setprecision(2);
    deallog.attach(logfile);
    deallog.depth_console(0);
    deallog.threshold_double(1.e-10);

    TestPointValueHistory<2> test;
    test.run();
}
<commit_msg>Make sure we include "../tests.h"<commit_after>//----------------------------  point_value_history_01.cc  ---------------------------
//    $Id$
//    Version: $Name$
//
//    Copyright (C) 2009, 2010 by the deal.II authors and Michael Rapson
//
//    This file is subject to QPL and may not be  distributed
//    without copyright and license information. Please refer
//    to the file deal.II/doc/license.html for the  text  and
//    further information on this license.
//
//----------------------------  point_value_history_01.cc  ---------------------------

// ************************************************
// A test program for the PointValueHistory class
// Currently this only tests a finite element system
// with 3 components, on a hyper cube and with Vectors.
// The testing is done in two dimensions.
// ************************************************

#include "../tests.h"
#include <base/quadrature_lib.h>

#include <dofs/dof_handler.h>
#include <dofs/dof_accessor.h>
#include <dofs/dof_renumbering.h>

#include <fe/fe_q.h>
#include <fe/fe_system.h>
#include <fe/fe_values.h>

#include <grid/tria.h>
#include <grid/tria_accessor.h>
#include <grid/tria_iterator.h>
#include <grid/grid_generator.h>

#include <lac/vector.h>

#include <numerics/point_value_history.h>

#include <fstream>

using namespace dealii;

template <int dim>
class TestPointValueHistory
{
public:
    TestPointValueHistory();
    void run();

private:
    Triangulation <dim> triangulation;
    FESystem<dim> finite_element;
    DoFHandler <dim > dof_handler;
    PointValueHistory <dim> test_copy;
};

template <int dim>
TestPointValueHistory<dim>::TestPointValueHistory() :
finite_element(FE_Q<dim > (1 + 1), dim, FE_Q<dim > (1), 1),

dof_handler(triangulation)
{ }

template <int dim>
void TestPointValueHistory<dim>::run()
{
    // Make a triangulation
    GridGenerator::hyper_cube(triangulation, 0, 1);
    triangulation.refine_global(2); // refine 2 times to make 5 nodes per side

    // make a DOF handler, a model solution filled with ones and a flow vector
    FESystem<dim> finite_element(FE_Q<dim > (1 + 1), dim, FE_Q<dim > (1), 1);
    DoFHandler <dim > dof_handler(triangulation);
    dof_handler.distribute_dofs(finite_element);
    DoFRenumbering::Cuthill_McKee(dof_handler);

    // renumber for components so that same dof indices are used for BlockVectors and normal Vectors
    std::vector<unsigned int> block_component(dim + 1, 0);
    block_component[dim] = 1; // component dim = pressure component!
    DoFRenumbering::component_wise(dof_handler, block_component);

    // Vector
    Vector <double> solution, post_processed, poles;
    solution.reinit(dof_handler.n_dofs());
    post_processed.reinit(dof_handler.n_dofs());
    poles.reinit(dof_handler.n_dofs());

    // set up a simple linear discrete time system so that time plots vary
    // over the mesh but can be easily checked. The basic idea is to have each
    // component of the fe_system to depend on a specific dimension (i.e component 0
    // depends on dim 0, etc. % dim handles the case where there are more components
    // than dimensions. The code breaks down at the edges of the mesh and this is
    // not corrected for.
    {
        QGauss<dim> quadrature_formula(2);
        FEValues<dim> fe_values(finite_element, quadrature_formula, update_values | update_quadrature_points); // just need local_dof_indices and quadrature_points

        std::vector<unsigned int> local_dof_indices(finite_element.dofs_per_cell);
        std::vector<Point<dim> > dof_locations(finite_element.dofs_per_cell);
        Vector<double> cell_pole(finite_element.dofs_per_cell);

        typename DoFHandler<dim>::active_cell_iterator cell, endc;
        cell = dof_handler.begin_active();
        endc = dof_handler.end();
        for (; cell != endc; ++cell)
        {
            fe_values.reinit(cell); // need to get local_dof_indices
            cell->get_dof_indices(local_dof_indices);
            dof_locations = fe_values.get_quadrature_points();
            cell_pole = 0;
            for (unsigned int dof = 0; dof != finite_element.dofs_per_cell; dof++)
            {
                unsigned int dof_component = finite_element.system_to_component_index(dof).first;

                for (unsigned int q_point = 0; q_point < quadrature_formula.size(); ++q_point)
                {
                    cell_pole(dof) += (fe_values.shape_value(dof, q_point) * dof_locations [q_point] (dof_component % dim));
                }
                solution(local_dof_indices [dof]) = 1; // start all solutions at 1
                poles(local_dof_indices[dof]) -= cell_pole(dof);

                if (dof_component == dim) // components start numbering at 0
                    poles(local_dof_indices[dof]) = -0.1; // dim+1th component is not handled well by the code above
            }

        } // loop over all cells
        poles.add(1.0); // slow down the pole settling time
        post_processed.add(3.0); // set to starting value.
    }

    // Setup monitor node to print variation over time
    unsigned int n_inputs = 1;
    PointValueHistory<dim> node_monitor (dof_handler, n_inputs);
    PointValueHistory<dim> no_dof_handler (n_inputs);

    // check that the assignment operator is valid
    test_copy = node_monitor;
    test_copy.add_point(Point<2>(1, 0.2));
    test_copy.add_field_name("Solution");
    std::vector < std::vector <Point <dim> > > selected_locations;
    test_copy.get_points(selected_locations);
    test_copy.mark_locations();
    test_copy.close();
    test_copy.start_new_dataset(0.1);
    test_copy.evaluate_field("Solution", solution);
    std::vector <double> input_value(n_inputs, 1);
    test_copy.push_back_independent(input_value);
    test_copy.write_gnuplot("point_value_history_01/Test_Copy");
    test_copy.status(deallog.get_file_stream());
    test_copy.clear ();
    // end of assignment operator check

    {
        node_monitor.add_field_name("Solution");
        node_monitor.add_field_name("Post Processed Vector"); // not sensitive to spaces

        // two alternatives here, adding a point at a time or a vector of points
        // 2d points
        std::vector <Point < 2 > > point_vector(5, Point < 2 > ());
        point_vector[0] = Point < 2 > (0, 0); // some of these points will hit a node, others won't
        point_vector[1] = Point < 2 > (0.25, 0);
        point_vector[2] = Point < 2 > (0.25, 0.45);
        point_vector[3] = Point < 2 > (0.45, 0.45);
        point_vector[4] = Point < 2 > (0.8, 0.8);

        node_monitor.add_points(point_vector);
        node_monitor.add_point(Point<2>(1, 0.2)); // add a single point

        // MonitorNode requires that the instance is 'closed' before any data is added
        // this ensures that points are not added once time starts.
        node_monitor.close();
        no_dof_handler.close(); // closing still required!

        std::vector < std::vector <Point <dim> > > selected_locations;
        node_monitor.get_points(selected_locations);
	// write output to a file
        Vector<double> node_locations = node_monitor.mark_locations();
	// write output to a file
    }

    double delta_t = 0.000001;
    double t_max = 0.00001;

    for (double time = 0; time < t_max; time = time + delta_t)
    {
        node_monitor.start_new_dataset(time);
        no_dof_handler.start_new_dataset(time);
        // time and input are special, they don't vary over the mesh.

        std::vector <double> input_value(n_inputs, 1); // manufacture an input value
        node_monitor.push_back_independent(input_value);
        no_dof_handler.push_back_independent(input_value);
        node_monitor.evaluate_field("Solution", solution);
        node_monitor.evaluate_field("Post Processed Vector", post_processed);

        solution.scale(poles); // decaying exponentials of varying time constants
        post_processed = solution;
        post_processed.add(2.0); // simple post processing, giving it a dc offset
    }
    node_monitor.write_gnuplot("point_value_history_01/node");
    no_dof_handler.write_gnuplot("point_value_history_01/no_dof");

    node_monitor.status (deallog.get_file_stream());
    no_dof_handler.status (deallog.get_file_stream());

    deallog << "Starting data files" << std::endl;

				     // copy all the data into deallog and
				     // delete those files
    const std::string filenames[]
      = { "point_value_history_01/node_00.gpl",
	  "point_value_history_01/node_01.gpl",
	  "point_value_history_01/node_02.gpl",
	  "point_value_history_01/node_03.gpl",
	  "point_value_history_01/node_04.gpl",
	  "point_value_history_01/node_05.gpl",
	  "point_value_history_01/node_indep.gpl",
	  "point_value_history_01/Test_Copy_00.gpl",
	  "point_value_history_01/Test_Copy_indep.gpl",
	  "point_value_history_01/no_dof_indep.gpl" };

    for (unsigned int i=0; i<sizeof(filenames)/sizeof(filenames[0]); ++i)
      {
	deallog << "Copying output file " << filenames[i]
		<< std::endl;

	std::ifstream in(filenames[i].c_str());
	AssertThrow (in, ExcIO());

	std::string s;
	while (in)
	  {
	    std::getline (in, s);
	    deallog << s << std::endl;
	  }

	std::remove (filenames[i].c_str());

	deallog << std::endl;
      }
}

int main()
{
    std::ofstream logfile("point_value_history_01/output");
    logfile << std::setprecision(2);
    deallog << std::setprecision(2);
    deallog.attach(logfile);
    deallog.depth_console(0);
    deallog.threshold_double(1.e-10);

    TestPointValueHistory<2> test;
    test.run();
}
<|endoftext|>


<commit_before>//===-- SectionLoadList.cpp -------------------------------------*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include "lldb/Target/SectionLoadList.h"

// C Includes
// C++ Includes
// Other libraries and framework includes
// Project includes
#include "lldb/Core/Log.h"
#include "lldb/Core/Module.h"
#include "lldb/Core/Section.h"
#include "lldb/Core/Stream.h"
#include "lldb/Symbol/Block.h"
#include "lldb/Symbol/Symbol.h"
#include "lldb/Symbol/SymbolContext.h"

using namespace lldb;
using namespace lldb_private;

bool
SectionLoadList::IsEmpty() const
{
    Mutex::Locker locker(m_mutex);
    return m_addr_to_sect.empty();
}

void
SectionLoadList::Clear ()
{
    Mutex::Locker locker(m_mutex);
    m_addr_to_sect.clear();
    m_sect_to_addr.clear();
}

addr_t
SectionLoadList::GetSectionLoadAddress (const lldb::SectionSP &section) const
{
    // TODO: add support for the same section having multiple load addresses
    addr_t section_load_addr = LLDB_INVALID_ADDRESS;
    if (section)
    {
        Mutex::Locker locker(m_mutex);
        sect_to_addr_collection::const_iterator pos = m_sect_to_addr.find (section.get());

        if (pos != m_sect_to_addr.end())
            section_load_addr = pos->second;
    }
    return section_load_addr;
}

bool
SectionLoadList::SetSectionLoadAddress (const lldb::SectionSP &section, addr_t load_addr, bool warn_multiple)
{
    LogSP log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_DYNAMIC_LOADER | LIBLLDB_LOG_VERBOSE));

    if (log)
    {
        const FileSpec &module_file_spec (section->GetModule()->GetFileSpec());
        log->Printf ("SectionLoadList::%s (section = %p (%s%s%s.%s), load_addr = 0x%16.16llx)",
                     __FUNCTION__,
                     section.get(),
                     module_file_spec.GetDirectory().AsCString(),
                     module_file_spec.GetDirectory() ? "/" : "",
                     module_file_spec.GetFilename().AsCString(),
                     section->GetName().AsCString(),
                     load_addr);
    }

    if (section->GetByteSize() == 0)
        return false; // No change

    // Fill in the section -> load_addr map
    Mutex::Locker locker(m_mutex);
    sect_to_addr_collection::iterator sta_pos = m_sect_to_addr.find(section.get());
    if (sta_pos != m_sect_to_addr.end())
    {
        if (load_addr == sta_pos->second)
            return false; // No change...
        else
            sta_pos->second = load_addr;
    }
    else
        m_sect_to_addr[section.get()] = load_addr;

    // Fill in the load_addr -> section map
    addr_to_sect_collection::iterator ats_pos = m_addr_to_sect.find(load_addr);
    if (ats_pos != m_addr_to_sect.end())
    {
        // Some sections are ok to overlap, and for others we should warn. When
        // we have multiple load addresses that correspond to a section, we will
        // allways attribute the section to the be last section that claims it
        // exists at that address. Sometimes it is ok for more that one section
        // to be loaded at a specific load address, and other times it isn't.
        // The "warn_multiple" parameter tells us if we should warn in this case
        // or not. The DynamicLoader plug-in subclasses should know which
        // sections should warn and which shouldn't (darwin shared cache modules
        // all shared the same "__LINKEDIT" sections, so the dynamic loader can
        // pass false for "warn_multiple").
        if (warn_multiple && section != ats_pos->second)
        {
            ModuleSP module_sp (section->GetModule());
            if (module_sp)
            {
                module_sp->ReportWarning ("address 0x%16.16llx maps to more than one section: %s.%s and %s.%s",
                                          load_addr,
                                          module_sp->GetFileSpec().GetFilename().GetCString(),
                                          section->GetName().GetCString(),
                                          ats_pos->second->GetModule()->GetFileSpec().GetFilename().GetCString(),
                                          ats_pos->second->GetName().GetCString());
            }
        }
        ats_pos->second = section;
    }
    else
        m_addr_to_sect[load_addr] = section;

    return true;    // Changed
}

size_t
SectionLoadList::SetSectionUnloaded (const lldb::SectionSP &section_sp)
{
    size_t unload_count = 0;

    if (section_sp)
    {
        LogSP log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_DYNAMIC_LOADER | LIBLLDB_LOG_VERBOSE));

        if (log)
        {
            const FileSpec &module_file_spec (section_sp->GetModule()->GetFileSpec());
            log->Printf ("SectionLoadList::%s (section = %p (%s%s%s.%s))",
                         __FUNCTION__,
                         section_sp.get(),
                         module_file_spec.GetDirectory().AsCString(),
                         module_file_spec.GetDirectory() ? "/" : "",
                         module_file_spec.GetFilename().AsCString(),
                         section_sp->GetName().AsCString());
        }

        Mutex::Locker locker(m_mutex);

        sect_to_addr_collection::iterator sta_pos = m_sect_to_addr.find(section_sp.get());
        if (sta_pos != m_sect_to_addr.end())
        {
            addr_t load_addr = sta_pos->second;
            m_sect_to_addr.erase (sta_pos);

            addr_to_sect_collection::iterator ats_pos = m_addr_to_sect.find(load_addr);
            if (ats_pos != m_addr_to_sect.end())
                m_addr_to_sect.erase (ats_pos);
        }
    }
    return unload_count;
}

bool
SectionLoadList::SetSectionUnloaded (const lldb::SectionSP &section_sp, addr_t load_addr)
{
    LogSP log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_DYNAMIC_LOADER | LIBLLDB_LOG_VERBOSE));

    if (log)
    {
        const FileSpec &module_file_spec (section_sp->GetModule()->GetFileSpec());
        log->Printf ("SectionLoadList::%s (section = %p (%s%s%s.%s), load_addr = 0x%16.16llx)",
                     __FUNCTION__,
                     section_sp.get(),
                     module_file_spec.GetDirectory().AsCString(),
                     module_file_spec.GetDirectory() ? "/" : "",
                     module_file_spec.GetFilename().AsCString(),
                     section_sp->GetName().AsCString(),
                     load_addr);
    }
    bool erased = false;
    Mutex::Locker locker(m_mutex);
    sect_to_addr_collection::iterator sta_pos = m_sect_to_addr.find(section_sp.get());
    if (sta_pos != m_sect_to_addr.end())
    {
        erased = true;
        m_sect_to_addr.erase (sta_pos);
    }

    addr_to_sect_collection::iterator ats_pos = m_addr_to_sect.find(load_addr);
    if (ats_pos != m_addr_to_sect.end())
    {
        erased = true;
        m_addr_to_sect.erase (ats_pos);
    }

    return erased;
}

bool
SectionLoadList::ResolveLoadAddress (addr_t load_addr, Address &so_addr) const
{
    // First find the top level section that this load address exists in
    Mutex::Locker locker(m_mutex);
    if (!m_addr_to_sect.empty())
    {
        addr_to_sect_collection::const_iterator pos = m_addr_to_sect.lower_bound (load_addr);
        if (pos != m_addr_to_sect.end())
        {
            if (load_addr != pos->first && pos != m_addr_to_sect.begin())
                --pos;
            if (load_addr >= pos->first)
            {
                addr_t offset = load_addr - pos->first;
                if (offset < pos->second->GetByteSize())
                {
                    // We have found the top level section, now we need to find the
                    // deepest child section.
                    return pos->second->ResolveContainedAddress (offset, so_addr);
                }
            }
        }
        else
        {
            // There are no entries that have an address that is >= load_addr,
            // so we need to check the last entry on our collection.
            addr_to_sect_collection::const_reverse_iterator rpos = m_addr_to_sect.rbegin();
            if (load_addr >= rpos->first)
            {
                addr_t offset = load_addr - rpos->first;
                if (offset < rpos->second->GetByteSize())
                {
                    // We have found the top level section, now we need to find the
                    // deepest child section.
                    return rpos->second->ResolveContainedAddress (offset, so_addr);
                }
            }
        }
    }
    so_addr.Clear();
    return false;
}

void
SectionLoadList::Dump (Stream &s, Target *target)
{
    Mutex::Locker locker(m_mutex);
    addr_to_sect_collection::const_iterator pos, end;
    for (pos = m_addr_to_sect.begin(), end = m_addr_to_sect.end(); pos != end; ++pos)
    {
        s.Printf("addr = 0x%16.16llx, section = %p: ", pos->first, pos->second.get());
        pos->second->Dump (&s, target, 0);
    }
}

<commit_msg><rdar://problem/11620586><commit_after>//===-- SectionLoadList.cpp -------------------------------------*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include "lldb/Target/SectionLoadList.h"

// C Includes
// C++ Includes
// Other libraries and framework includes
// Project includes
#include "lldb/Core/Log.h"
#include "lldb/Core/Module.h"
#include "lldb/Core/Section.h"
#include "lldb/Core/Stream.h"
#include "lldb/Symbol/Block.h"
#include "lldb/Symbol/Symbol.h"
#include "lldb/Symbol/SymbolContext.h"

using namespace lldb;
using namespace lldb_private;

bool
SectionLoadList::IsEmpty() const
{
    Mutex::Locker locker(m_mutex);
    return m_addr_to_sect.empty();
}

void
SectionLoadList::Clear ()
{
    Mutex::Locker locker(m_mutex);
    m_addr_to_sect.clear();
    m_sect_to_addr.clear();
}

addr_t
SectionLoadList::GetSectionLoadAddress (const lldb::SectionSP &section) const
{
    // TODO: add support for the same section having multiple load addresses
    addr_t section_load_addr = LLDB_INVALID_ADDRESS;
    if (section)
    {
        Mutex::Locker locker(m_mutex);
        sect_to_addr_collection::const_iterator pos = m_sect_to_addr.find (section.get());

        if (pos != m_sect_to_addr.end())
            section_load_addr = pos->second;
    }
    return section_load_addr;
}

bool
SectionLoadList::SetSectionLoadAddress (const lldb::SectionSP &section, addr_t load_addr, bool warn_multiple)
{
    LogSP log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_DYNAMIC_LOADER | LIBLLDB_LOG_VERBOSE));

    if (log)
    {
        const FileSpec &module_file_spec (section->GetModule()->GetFileSpec());
        log->Printf ("SectionLoadList::%s (section = %p (%s%s%s.%s), load_addr = 0x%16.16llx)",
                     __FUNCTION__,
                     section.get(),
                     module_file_spec.GetDirectory().AsCString(),
                     module_file_spec.GetDirectory() ? "/" : "",
                     module_file_spec.GetFilename().AsCString(),
                     section->GetName().AsCString(),
                     load_addr);
    }

    if (section->GetByteSize() == 0)
        return false; // No change

    // Fill in the section -> load_addr map
    Mutex::Locker locker(m_mutex);
    sect_to_addr_collection::iterator sta_pos = m_sect_to_addr.find(section.get());
    if (sta_pos != m_sect_to_addr.end())
    {
        if (load_addr == sta_pos->second)
            return false; // No change...
        else
            sta_pos->second = load_addr;
    }
    else
        m_sect_to_addr[section.get()] = load_addr;

    // Fill in the load_addr -> section map
    addr_to_sect_collection::iterator ats_pos = m_addr_to_sect.find(load_addr);
    if (ats_pos != m_addr_to_sect.end())
    {
        // Some sections are ok to overlap, and for others we should warn. When
        // we have multiple load addresses that correspond to a section, we will
        // allways attribute the section to the be last section that claims it
        // exists at that address. Sometimes it is ok for more that one section
        // to be loaded at a specific load address, and other times it isn't.
        // The "warn_multiple" parameter tells us if we should warn in this case
        // or not. The DynamicLoader plug-in subclasses should know which
        // sections should warn and which shouldn't (darwin shared cache modules
        // all shared the same "__LINKEDIT" sections, so the dynamic loader can
        // pass false for "warn_multiple").
        if (warn_multiple && section != ats_pos->second)
        {
            ModuleSP module_sp (section->GetModule());
            if (module_sp)
            {
                ModuleSP curr_module_sp (ats_pos->second->GetModule());
                if (curr_module_sp)
                {
                    module_sp->ReportWarning ("address 0x%16.16llx maps to more than one section: %s.%s and %s.%s",
                                              load_addr,
                                              module_sp->GetFileSpec().GetFilename().GetCString(),
                                              section->GetName().GetCString(),
                                              curr_module_sp->GetFileSpec().GetFilename().GetCString(),
                                              ats_pos->second->GetName().GetCString());
                }
            }
        }
        ats_pos->second = section;
    }
    else
        m_addr_to_sect[load_addr] = section;

    return true;    // Changed
}

size_t
SectionLoadList::SetSectionUnloaded (const lldb::SectionSP &section_sp)
{
    size_t unload_count = 0;

    if (section_sp)
    {
        LogSP log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_DYNAMIC_LOADER | LIBLLDB_LOG_VERBOSE));

        if (log)
        {
            const FileSpec &module_file_spec (section_sp->GetModule()->GetFileSpec());
            log->Printf ("SectionLoadList::%s (section = %p (%s%s%s.%s))",
                         __FUNCTION__,
                         section_sp.get(),
                         module_file_spec.GetDirectory().AsCString(),
                         module_file_spec.GetDirectory() ? "/" : "",
                         module_file_spec.GetFilename().AsCString(),
                         section_sp->GetName().AsCString());
        }

        Mutex::Locker locker(m_mutex);

        sect_to_addr_collection::iterator sta_pos = m_sect_to_addr.find(section_sp.get());
        if (sta_pos != m_sect_to_addr.end())
        {
            addr_t load_addr = sta_pos->second;
            m_sect_to_addr.erase (sta_pos);

            addr_to_sect_collection::iterator ats_pos = m_addr_to_sect.find(load_addr);
            if (ats_pos != m_addr_to_sect.end())
                m_addr_to_sect.erase (ats_pos);
        }
    }
    return unload_count;
}

bool
SectionLoadList::SetSectionUnloaded (const lldb::SectionSP &section_sp, addr_t load_addr)
{
    LogSP log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_DYNAMIC_LOADER | LIBLLDB_LOG_VERBOSE));

    if (log)
    {
        const FileSpec &module_file_spec (section_sp->GetModule()->GetFileSpec());
        log->Printf ("SectionLoadList::%s (section = %p (%s%s%s.%s), load_addr = 0x%16.16llx)",
                     __FUNCTION__,
                     section_sp.get(),
                     module_file_spec.GetDirectory().AsCString(),
                     module_file_spec.GetDirectory() ? "/" : "",
                     module_file_spec.GetFilename().AsCString(),
                     section_sp->GetName().AsCString(),
                     load_addr);
    }
    bool erased = false;
    Mutex::Locker locker(m_mutex);
    sect_to_addr_collection::iterator sta_pos = m_sect_to_addr.find(section_sp.get());
    if (sta_pos != m_sect_to_addr.end())
    {
        erased = true;
        m_sect_to_addr.erase (sta_pos);
    }

    addr_to_sect_collection::iterator ats_pos = m_addr_to_sect.find(load_addr);
    if (ats_pos != m_addr_to_sect.end())
    {
        erased = true;
        m_addr_to_sect.erase (ats_pos);
    }

    return erased;
}

bool
SectionLoadList::ResolveLoadAddress (addr_t load_addr, Address &so_addr) const
{
    // First find the top level section that this load address exists in
    Mutex::Locker locker(m_mutex);
    if (!m_addr_to_sect.empty())
    {
        addr_to_sect_collection::const_iterator pos = m_addr_to_sect.lower_bound (load_addr);
        if (pos != m_addr_to_sect.end())
        {
            if (load_addr != pos->first && pos != m_addr_to_sect.begin())
                --pos;
            if (load_addr >= pos->first)
            {
                addr_t offset = load_addr - pos->first;
                if (offset < pos->second->GetByteSize())
                {
                    // We have found the top level section, now we need to find the
                    // deepest child section.
                    return pos->second->ResolveContainedAddress (offset, so_addr);
                }
            }
        }
        else
        {
            // There are no entries that have an address that is >= load_addr,
            // so we need to check the last entry on our collection.
            addr_to_sect_collection::const_reverse_iterator rpos = m_addr_to_sect.rbegin();
            if (load_addr >= rpos->first)
            {
                addr_t offset = load_addr - rpos->first;
                if (offset < rpos->second->GetByteSize())
                {
                    // We have found the top level section, now we need to find the
                    // deepest child section.
                    return rpos->second->ResolveContainedAddress (offset, so_addr);
                }
            }
        }
    }
    so_addr.Clear();
    return false;
}

void
SectionLoadList::Dump (Stream &s, Target *target)
{
    Mutex::Locker locker(m_mutex);
    addr_to_sect_collection::const_iterator pos, end;
    for (pos = m_addr_to_sect.begin(), end = m_addr_to_sect.end(); pos != end; ++pos)
    {
        s.Printf("addr = 0x%16.16llx, section = %p: ", pos->first, pos->second.get());
        pos->second->Dump (&s, target, 0);
    }
}

<|endoftext|>


<commit_before><commit_msg>PWGPP-570 - bug fix in AliESDUtils::GetITSPileupVertexInfo<commit_after><|endoftext|>


<commit_before>/*****************************************************************/
/* Cross probing function: handle communication to/from eeschema */
/*****************************************************************/

/* cross-probing.cpp */

#include "fctsys.h"

#include "common.h"
#include "pcbnew.h"
#include "eda_dde.h"

#include "id.h"
#include "collectors.h"

#include "protos.h"

/*******************************************/
void RemoteCommand(  const char* cmdline )
/*******************************************/

/** Read a remote command send by eeschema via a socket,
 *  port KICAD_PCB_PORT_SERVICE_NUMBER (currently 4242)
 * @param cmdline = received command from eeschema
 * Commands are
 * $PART: "reference"   put cursor on component
 * $PIN: "pin name"  $PART: "reference" put cursor on the footprint pin
 */
{
    char             line[1024];
    wxString         msg;
    wxString         modName;
    char*            idcmd;
    char*            text;
    MODULE*          module = 0;
    WinEDA_PcbFrame* frame  = g_EDA_Appl->m_PcbFrame;

    strncpy( line, cmdline, sizeof(line) - 1 );

    idcmd = strtok( line, " \n\r" );
    text  = strtok( NULL, " \n\r" );

    if( !idcmd || !text )
        return;

    if( strcmp( idcmd, "$PART:" ) == 0 )
    {
        modName = CONV_FROM_UTF8( text );

        module = ReturnModule( frame->m_Pcb, modName );

        if( module )
            msg.Printf( _( "Module %s found" ), modName.GetData() );
        else
            msg.Printf( _( "Module %s not found"), modName.GetData() );

        frame->Affiche_Message( msg );
        if( module )
        {
            wxClientDC dc( frame->DrawPanel );

            frame->DrawPanel->PrepareGraphicContext( &dc );
            frame->DrawPanel->CursorOff( &dc );
            frame->GetScreen()->m_Curseur = module->GetPosition();
            frame->DrawPanel->CursorOn( &dc );
        }
    }

    else if( strcmp( idcmd, "$PIN:" ) == 0 )
    {
        wxString pinName;
        D_PAD*   pad     = NULL;
        int      netcode = -1;

        pinName = CONV_FROM_UTF8( text );

        text = strtok( NULL, " \n\r" );
        if( text && strcmp( text, "$PART:" ) == 0 )
            text = strtok( NULL, "\n\r" );

        wxClientDC dc( frame->DrawPanel );

        frame->DrawPanel->PrepareGraphicContext( &dc );

        modName = CONV_FROM_UTF8( text );

        module  = ReturnModule( frame->m_Pcb, modName );
        if( module )
            pad = ReturnPad( module, pinName );

        if( pad )
            netcode = pad->GetNet();

        if( netcode > 0 )               /* hightlighted the net selected net*/
        {
            if( g_HightLigt_Status )    /* erase the old hightlighted net */
                frame->Hight_Light( &dc );

            g_HightLigth_NetCode = netcode;
            frame->Hight_Light( &dc );      /* hightlighted the new one */

            frame->DrawPanel->CursorOff( &dc );
            frame->GetScreen()->m_Curseur = pad->GetPosition();
            frame->DrawPanel->CursorOn( &dc );
        }

        if( module == NULL )
            msg.Printf( _( "Module %s not found" ), modName.GetData() );
        else if( pad == NULL )
            msg.Printf( _( "Pin %s (module %s) not found" ), pinName.GetData(), modName.GetData() );
        else
            msg.Printf( _( "%s pin %s found" ), modName.GetData(), pinName.GetData() );

        frame->Affiche_Message( msg );
    }

    if( module )  // if found, center the module on screen.
        frame->Recadre_Trace( false );
}

// see wxstruct.h
/**************************************************************************/
void WinEDA_PcbFrame::SendMessageToEESCHEMA( BOARD_ITEM* objectToSync )
/**************************************************************************/

/** Send a remote command to eeschema via a socket,
 * @param objectToSync = item to be located on schematic (module, pin or text)
 * Commands are
 * $PART: "reference"   put cursor on component anchor
 * $PART: "reference" $PAD: "pad number" put cursor on the component pin
 * $PART: "reference" $REF: "reference" put cursor on the component ref
 * $PART: "reference" $VAL: "value" put cursor on the component value
 */
{
    char          cmd[1024];
    const char*   text_key;
    MODULE*       module = NULL;
    D_PAD*        pad;
    TEXTE_MODULE* text_mod;
    wxString      msg;

    if( objectToSync == NULL )
        return;

    switch( objectToSync->Type() )
    {
    case TYPEMODULE:
        module = (MODULE*) objectToSync;
        sprintf( cmd, "$PART: \"%s\"",
                CONV_TO_UTF8( module->m_Reference->m_Text ) );
        break;

    case TYPEPAD:
        module = (MODULE*) objectToSync->m_Parent;
        pad    = (D_PAD*) objectToSync;
        msg    = pad->ReturnStringPadName();
        sprintf( cmd, "$PART: \"%s\" $PAD: \"%s\"",
                CONV_TO_UTF8( module->m_Reference->m_Text ),
                CONV_TO_UTF8( msg ) );
        break;

    case TYPETEXTEMODULE:
            #define REFERENCE 0
            #define VALUE     1
        module   = (MODULE*) objectToSync->m_Parent;
        text_mod = (TEXTE_MODULE*) objectToSync;
        if( text_mod->m_Type == REFERENCE )
            text_key = "$REF:";
        else if( text_mod->m_Type == VALUE )
            text_key = "$VAL:";
        else
            break;

        sprintf( cmd, "$PART: \"%s\" %s \"%s\"",
                CONV_TO_UTF8( module->m_Reference->m_Text ),
                text_key,
                CONV_TO_UTF8( text_mod->m_Text ) );
        break;

    default:
        break;
    }

    if( module )
    {
        SendCommand( MSG_TO_SCH, cmd );
    }
}
<commit_msg>message consistency<commit_after>/*****************************************************************/
/* Cross probing function: handle communication to/from eeschema */
/*****************************************************************/

/* cross-probing.cpp */

#include "fctsys.h"

#include "common.h"
#include "pcbnew.h"
#include "eda_dde.h"

#include "id.h"
#include "collectors.h"

#include "protos.h"

/*******************************************/
void RemoteCommand(  const char* cmdline )
/*******************************************/

/** Read a remote command send by eeschema via a socket,
 *  port KICAD_PCB_PORT_SERVICE_NUMBER (currently 4242)
 * @param cmdline = received command from eeschema
 * Commands are
 * $PART: "reference"   put cursor on component
 * $PIN: "pin name"  $PART: "reference" put cursor on the footprint pin
 */
{
    char             line[1024];
    wxString         msg;
    wxString         modName;
    char*            idcmd;
    char*            text;
    MODULE*          module = 0;
    WinEDA_PcbFrame* frame  = g_EDA_Appl->m_PcbFrame;

    strncpy( line, cmdline, sizeof(line) - 1 );

    idcmd = strtok( line, " \n\r" );
    text  = strtok( NULL, " \n\r" );

    if( !idcmd || !text )
        return;

    if( strcmp( idcmd, "$PART:" ) == 0 )
    {
        modName = CONV_FROM_UTF8( text );

        module = ReturnModule( frame->m_Pcb, modName );

        if( module )
            msg.Printf( _( "%s found" ), modName.GetData() );
        else
            msg.Printf( _( "%s not found"), modName.GetData() );

        frame->Affiche_Message( msg );
        if( module )
        {
            wxClientDC dc( frame->DrawPanel );

            frame->DrawPanel->PrepareGraphicContext( &dc );
            frame->DrawPanel->CursorOff( &dc );
            frame->GetScreen()->m_Curseur = module->GetPosition();
            frame->DrawPanel->CursorOn( &dc );
        }
    }

    else if( strcmp( idcmd, "$PIN:" ) == 0 )
    {
        wxString pinName;
        D_PAD*   pad     = NULL;
        int      netcode = -1;

        pinName = CONV_FROM_UTF8( text );

        text = strtok( NULL, " \n\r" );
        if( text && strcmp( text, "$PART:" ) == 0 )
            text = strtok( NULL, "\n\r" );

        wxClientDC dc( frame->DrawPanel );

        frame->DrawPanel->PrepareGraphicContext( &dc );

        modName = CONV_FROM_UTF8( text );

        module  = ReturnModule( frame->m_Pcb, modName );
        if( module )
            pad = ReturnPad( module, pinName );

        if( pad )
            netcode = pad->GetNet();

        if( netcode > 0 )               /* hightlighted the net selected net*/
        {
            if( g_HightLigt_Status )    /* erase the old hightlighted net */
                frame->Hight_Light( &dc );

            g_HightLigth_NetCode = netcode;
            frame->Hight_Light( &dc );      /* hightlighted the new one */

            frame->DrawPanel->CursorOff( &dc );
            frame->GetScreen()->m_Curseur = pad->GetPosition();
            frame->DrawPanel->CursorOn( &dc );
        }

        if( module == NULL )
            msg.Printf( _( "%s not found" ), modName.GetData() );
        else if( pad == NULL )
            msg.Printf( _( "%s pin %s not found" ), modName.GetData(), pinName.GetData() );
        else
            msg.Printf( _( "%s pin %s found" ), modName.GetData(), pinName.GetData() );

        frame->Affiche_Message( msg );
    }

    if( module )  // if found, center the module on screen.
        frame->Recadre_Trace( false );
}

// see wxstruct.h
/**************************************************************************/
void WinEDA_PcbFrame::SendMessageToEESCHEMA( BOARD_ITEM* objectToSync )
/**************************************************************************/

/** Send a remote command to eeschema via a socket,
 * @param objectToSync = item to be located on schematic (module, pin or text)
 * Commands are
 * $PART: "reference"   put cursor on component anchor
 * $PART: "reference" $PAD: "pad number" put cursor on the component pin
 * $PART: "reference" $REF: "reference" put cursor on the component ref
 * $PART: "reference" $VAL: "value" put cursor on the component value
 */
{
    char          cmd[1024];
    const char*   text_key;
    MODULE*       module = NULL;
    D_PAD*        pad;
    TEXTE_MODULE* text_mod;
    wxString      msg;

    if( objectToSync == NULL )
        return;

    switch( objectToSync->Type() )
    {
    case TYPEMODULE:
        module = (MODULE*) objectToSync;
        sprintf( cmd, "$PART: \"%s\"",
                CONV_TO_UTF8( module->m_Reference->m_Text ) );
        break;

    case TYPEPAD:
        module = (MODULE*) objectToSync->m_Parent;
        pad    = (D_PAD*) objectToSync;
        msg    = pad->ReturnStringPadName();
        sprintf( cmd, "$PART: \"%s\" $PAD: \"%s\"",
                CONV_TO_UTF8( module->m_Reference->m_Text ),
                CONV_TO_UTF8( msg ) );
        break;

    case TYPETEXTEMODULE:
            #define REFERENCE 0
            #define VALUE     1
        module   = (MODULE*) objectToSync->m_Parent;
        text_mod = (TEXTE_MODULE*) objectToSync;
        if( text_mod->m_Type == REFERENCE )
            text_key = "$REF:";
        else if( text_mod->m_Type == VALUE )
            text_key = "$VAL:";
        else
            break;

        sprintf( cmd, "$PART: \"%s\" %s \"%s\"",
                CONV_TO_UTF8( module->m_Reference->m_Text ),
                text_key,
                CONV_TO_UTF8( text_mod->m_Text ) );
        break;

    default:
        break;
    }

    if( module )
    {
        SendCommand( MSG_TO_SCH, cmd );
    }
}
<|endoftext|>


<commit_before>/*  This file is part of the KDE project
    Copyright (C) 2005-2006 Matthias Kretz <kretz@kde.org>

    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Library General Public
    License version 2 as published by the Free Software Foundation.

    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
    Library General Public License for more details.

    You should have received a copy of the GNU Library General Public License
    along with this library; see the file COPYING.LIB.  If not, write to
    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
    Boston, MA 02110-1301, USA.

*/
#include "audiooutput.h"
#include "audiooutput_p.h"
#include "factory.h"
#include "objectdescription.h"
#include "audiooutputadaptor.h"
#include "globalconfig.h"
#include "audiooutputinterface.h"
#include "phononnamespace_p.h"

#include <cmath>

#define PHONON_CLASSNAME AudioOutput
#define PHONON_INTERFACENAME AudioOutputInterface

namespace Phonon
{
AudioOutput::AudioOutput(Phonon::Category category, QObject *parent)
    : AbstractAudioOutput(*new AudioOutputPrivate, parent)
{
    K_D(AudioOutput);
    d->category = category;

    // select hardware device according to the category
    d->outputDeviceIndex = GlobalConfig().audioOutputDeviceFor(d->category);

    d->createBackendObject();
    new AudioOutputAdaptor(this);
    for (int i = 0; !QDBusConnection::sessionBus().registerObject("/AudioOutputs/" + QString::number(i), this); ++i);

    connect(Factory::sender(), SIGNAL(availableAudioOutputDevicesChanged()), SLOT(_k_deviceListChanged()));
}

void AudioOutputPrivate::createBackendObject()
{
    if (m_backendObject)
        return;
    Q_Q(AudioOutput);
    m_backendObject = Factory::createAudioOutput(q);
    if (m_backendObject) {
        setupBackendObject();
    }
}

QString AudioOutput::name() const
{
    K_D(const AudioOutput);
    return d->name;
}

void AudioOutput::setName(const QString &newName)
{
    K_D(AudioOutput);
    d->name = newName;
}

void AudioOutput::setVolume(qreal volume)
{
    K_D(AudioOutput);
    d->volume = volume;
    if (k_ptr->backendObject() && !d->muted) {
        // using Stevens' power law loudness is proportional to (sound pressure)^0.67
        // sound pressure is proportional to voltage:
        // p² \prop P \prop V²
        // => if a factor for loudness of x is requested
        INTERFACE_CALL(setVolume(pow(volume, 1.4925373)));
    } else {
        emit volumeChanged(volume);
    }
}

qreal AudioOutput::volume() const
{
    K_D(const AudioOutput);
    if (d->muted || !d->m_backendObject) {
        return d->volume;
    }
    return pow(INTERFACE_CALL(volume()), 0.67);
}

#ifndef PHONON_LOG10OVER20
#define PHONON_LOG10OVER20
static const qreal log10over20 = 0.1151292546497022842; // ln(10) / 20
#endif // PHONON_LOG10OVER20

qreal AudioOutput::volumeDecibel() const
{
    K_D(const AudioOutput);
    if (d->muted || !d->m_backendObject) {
        return -log(d->volume) / log10over20;
    }
    return -0.67 * log(INTERFACE_CALL(volume())) / log10over20;
}

void AudioOutput::setVolumeDecibel(qreal newVolumeDecibel)
{
    setVolume(exp(-newVolumeDecibel * log10over20));
}

bool AudioOutput::isMuted() const
{
    K_D(const AudioOutput);
    return d->muted;
}

void AudioOutput::setMuted(bool mute)
{
    K_D(AudioOutput);
    if (d->muted != mute) {
        if (mute) {
            d->muted = mute;
            if (k_ptr->backendObject()) {
                INTERFACE_CALL(setVolume(0.0));
            }
        } else {
            if (k_ptr->backendObject()) {
                INTERFACE_CALL(setVolume(pow(d->volume, 1.4925373)));
            }
            d->muted = mute;
        }
        emit mutedChanged(mute);
    }
}

Category AudioOutput::category() const
{
    K_D(const AudioOutput);
    return d->category;
}

AudioOutputDevice AudioOutput::outputDevice() const
{
    K_D(const AudioOutput);
    int index;
    if (d->m_backendObject)
        index = INTERFACE_CALL(outputDevice());
    else
        index = d->outputDeviceIndex;
    return AudioOutputDevice::fromIndex(index);
}

bool AudioOutput::setOutputDevice(const AudioOutputDevice &newAudioOutputDevice)
{
    K_D(AudioOutput);
    if (!newAudioOutputDevice.isValid()) {
        d->outputDeviceOverridden = false;
        d->outputDeviceIndex = GlobalConfig().audioOutputDeviceFor(d->category);
    } else {
        d->outputDeviceOverridden = true;
        d->outputDeviceIndex = newAudioOutputDevice.index();
    }
    if (k_ptr->backendObject()) {
        return INTERFACE_CALL(setOutputDevice(d->outputDeviceIndex));
    }
    return true;
}

bool AudioOutputPrivate::aboutToDeleteBackendObject()
{
    if (m_backendObject) {
        volume = pINTERFACE_CALL(volume());
    }
    return AbstractAudioOutputPrivate::aboutToDeleteBackendObject();
}

void AudioOutputPrivate::setupBackendObject()
{
    Q_Q(AudioOutput);
    Q_ASSERT(m_backendObject);
    AbstractAudioOutputPrivate::setupBackendObject();

    QObject::connect(m_backendObject, SIGNAL(volumeChanged(qreal)), q, SLOT(_k_volumeChanged(qreal)));
    QObject::connect(m_backendObject, SIGNAL(audioDeviceFailed()), q, SLOT(_k_audioDeviceFailed()));

    // set up attributes
    pINTERFACE_CALL(setVolume(volume));

    // if the output device is not available and the device was not explicitly set
    if (!pINTERFACE_CALL(setOutputDevice(outputDeviceIndex)) && !outputDeviceOverridden) {
        // fall back in the preference list of output devices
        QList<int> deviceList = GlobalConfig().audioOutputDeviceListFor(category);
        if (deviceList.isEmpty()) {
            return;
        }
        if (outputDeviceIndex == deviceList.takeFirst()) { // removing the first device so that
            // if it's the same device as the one we tried we only try all the following
            foreach (int devIndex, deviceList) {
                if (pINTERFACE_CALL(setOutputDevice(devIndex))) {
                    handleAutomaticDeviceChange(devIndex, AudioOutputPrivate::FallbackChange);
                    break; // found one that works
                }
            }
        }
    }
}

void AudioOutputPrivate::_k_volumeChanged(qreal newVolume)
{
    if (!muted) {
        Q_Q(AudioOutput);
        emit q->volumeChanged(pow(newVolume, 0.67));
    }
}

void AudioOutputPrivate::_k_revertFallback()
{
    if (deviceBeforeFallback == -1) {
        return;
    }
    outputDeviceIndex = deviceBeforeFallback;
    pINTERFACE_CALL(setOutputDevice(outputDeviceIndex));
    Q_Q(AudioOutput);
    emit q->outputDeviceChanged(AudioOutputDevice::fromIndex(outputDeviceIndex));
}

void AudioOutputPrivate::_k_audioDeviceFailed()
{
    pDebug() << Q_FUNC_INFO;
    // outputDeviceIndex identifies a failing device
    // fall back in the preference list of output devices
    QList<int> deviceList = GlobalConfig().audioOutputDeviceListFor(category);
    foreach (int devIndex, deviceList) {
        // if it's the same device as the one that failed, ignore it
        if (outputDeviceIndex != devIndex) {
            if (pINTERFACE_CALL(setOutputDevice(devIndex))) {
                handleAutomaticDeviceChange(devIndex, FallbackChange);
                break; // found one that works
            }
        }
    }
}

void AudioOutputPrivate::_k_deviceListChanged()
{
    pDebug() << Q_FUNC_INFO;
    // let's see if there's a usable device higher in the preference list
    QList<int> deviceList = GlobalConfig().audioOutputDeviceListFor(category);
    foreach (int devIndex, deviceList) {
        pDebug() << devIndex;
        if (outputDeviceIndex == devIndex) {
            break; // we've reached the currently used device, nothing to change
        }
        if (pINTERFACE_CALL(setOutputDevice(devIndex))) {
            handleAutomaticDeviceChange(devIndex, HigherPreferenceChange);
            break; // found one with higher preference that works
        }
    }
}

void AudioOutputPrivate::handleAutomaticDeviceChange(int newIndex, DeviceChangeType type)
{
    Q_Q(AudioOutput);
    deviceBeforeFallback = outputDeviceIndex;
    outputDeviceIndex = newIndex;
    emit q->outputDeviceChanged(AudioOutputDevice::fromIndex(outputDeviceIndex));
    QString text;
    AudioOutputDevice device1 = AudioOutputDevice::fromIndex(deviceBeforeFallback);
    AudioOutputDevice device2 = AudioOutputDevice::fromIndex(outputDeviceIndex);
    switch (type) {
    case FallbackChange:
        text = AudioOutput::tr("The audio playback device '%1' does not work. "
            "Falling back to '%2'.").arg(device1.name()).arg(device2.name());
        break;
    case HigherPreferenceChange:
        text = AudioOutput::tr("Switching to the audio playback device '%1' "
                "which just became available and has higher preference.").arg(device2.name());
        break;
    }
    Factory::notification("AudioDeviceFallback", text,
            QStringList(AudioOutput::tr("Revert back to device '%1'").arg(device1.name())),
            q, SLOT(_k_revertFallback()));
}

} //namespace Phonon

#include "audiooutput.moc"

#undef PHONON_CLASSNAME
#undef PHONON_INTERFACENAME
// vim: sw=4 ts=4 tw=100 et
<commit_msg>nicer (more compact) formatting of knotify messages<commit_after>/*  This file is part of the KDE project
    Copyright (C) 2005-2006 Matthias Kretz <kretz@kde.org>

    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Library General Public
    License version 2 as published by the Free Software Foundation.

    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
    Library General Public License for more details.

    You should have received a copy of the GNU Library General Public License
    along with this library; see the file COPYING.LIB.  If not, write to
    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
    Boston, MA 02110-1301, USA.

*/
#include "audiooutput.h"
#include "audiooutput_p.h"
#include "factory.h"
#include "objectdescription.h"
#include "audiooutputadaptor.h"
#include "globalconfig.h"
#include "audiooutputinterface.h"
#include "phononnamespace_p.h"

#include <cmath>

#define PHONON_CLASSNAME AudioOutput
#define PHONON_INTERFACENAME AudioOutputInterface

namespace Phonon
{
AudioOutput::AudioOutput(Phonon::Category category, QObject *parent)
    : AbstractAudioOutput(*new AudioOutputPrivate, parent)
{
    K_D(AudioOutput);
    d->category = category;

    // select hardware device according to the category
    d->outputDeviceIndex = GlobalConfig().audioOutputDeviceFor(d->category);

    d->createBackendObject();
    new AudioOutputAdaptor(this);
    for (int i = 0; !QDBusConnection::sessionBus().registerObject("/AudioOutputs/" + QString::number(i), this); ++i);

    connect(Factory::sender(), SIGNAL(availableAudioOutputDevicesChanged()), SLOT(_k_deviceListChanged()));
}

void AudioOutputPrivate::createBackendObject()
{
    if (m_backendObject)
        return;
    Q_Q(AudioOutput);
    m_backendObject = Factory::createAudioOutput(q);
    if (m_backendObject) {
        setupBackendObject();
    }
}

QString AudioOutput::name() const
{
    K_D(const AudioOutput);
    return d->name;
}

void AudioOutput::setName(const QString &newName)
{
    K_D(AudioOutput);
    d->name = newName;
}

void AudioOutput::setVolume(qreal volume)
{
    K_D(AudioOutput);
    d->volume = volume;
    if (k_ptr->backendObject() && !d->muted) {
        // using Stevens' power law loudness is proportional to (sound pressure)^0.67
        // sound pressure is proportional to voltage:
        // p² \prop P \prop V²
        // => if a factor for loudness of x is requested
        INTERFACE_CALL(setVolume(pow(volume, 1.4925373)));
    } else {
        emit volumeChanged(volume);
    }
}

qreal AudioOutput::volume() const
{
    K_D(const AudioOutput);
    if (d->muted || !d->m_backendObject) {
        return d->volume;
    }
    return pow(INTERFACE_CALL(volume()), 0.67);
}

#ifndef PHONON_LOG10OVER20
#define PHONON_LOG10OVER20
static const qreal log10over20 = 0.1151292546497022842; // ln(10) / 20
#endif // PHONON_LOG10OVER20

qreal AudioOutput::volumeDecibel() const
{
    K_D(const AudioOutput);
    if (d->muted || !d->m_backendObject) {
        return -log(d->volume) / log10over20;
    }
    return -0.67 * log(INTERFACE_CALL(volume())) / log10over20;
}

void AudioOutput::setVolumeDecibel(qreal newVolumeDecibel)
{
    setVolume(exp(-newVolumeDecibel * log10over20));
}

bool AudioOutput::isMuted() const
{
    K_D(const AudioOutput);
    return d->muted;
}

void AudioOutput::setMuted(bool mute)
{
    K_D(AudioOutput);
    if (d->muted != mute) {
        if (mute) {
            d->muted = mute;
            if (k_ptr->backendObject()) {
                INTERFACE_CALL(setVolume(0.0));
            }
        } else {
            if (k_ptr->backendObject()) {
                INTERFACE_CALL(setVolume(pow(d->volume, 1.4925373)));
            }
            d->muted = mute;
        }
        emit mutedChanged(mute);
    }
}

Category AudioOutput::category() const
{
    K_D(const AudioOutput);
    return d->category;
}

AudioOutputDevice AudioOutput::outputDevice() const
{
    K_D(const AudioOutput);
    int index;
    if (d->m_backendObject)
        index = INTERFACE_CALL(outputDevice());
    else
        index = d->outputDeviceIndex;
    return AudioOutputDevice::fromIndex(index);
}

bool AudioOutput::setOutputDevice(const AudioOutputDevice &newAudioOutputDevice)
{
    K_D(AudioOutput);
    if (!newAudioOutputDevice.isValid()) {
        d->outputDeviceOverridden = false;
        d->outputDeviceIndex = GlobalConfig().audioOutputDeviceFor(d->category);
    } else {
        d->outputDeviceOverridden = true;
        d->outputDeviceIndex = newAudioOutputDevice.index();
    }
    if (k_ptr->backendObject()) {
        return INTERFACE_CALL(setOutputDevice(d->outputDeviceIndex));
    }
    return true;
}

bool AudioOutputPrivate::aboutToDeleteBackendObject()
{
    if (m_backendObject) {
        volume = pINTERFACE_CALL(volume());
    }
    return AbstractAudioOutputPrivate::aboutToDeleteBackendObject();
}

void AudioOutputPrivate::setupBackendObject()
{
    Q_Q(AudioOutput);
    Q_ASSERT(m_backendObject);
    AbstractAudioOutputPrivate::setupBackendObject();

    QObject::connect(m_backendObject, SIGNAL(volumeChanged(qreal)), q, SLOT(_k_volumeChanged(qreal)));
    QObject::connect(m_backendObject, SIGNAL(audioDeviceFailed()), q, SLOT(_k_audioDeviceFailed()));

    // set up attributes
    pINTERFACE_CALL(setVolume(volume));

    // if the output device is not available and the device was not explicitly set
    if (!pINTERFACE_CALL(setOutputDevice(outputDeviceIndex)) && !outputDeviceOverridden) {
        // fall back in the preference list of output devices
        QList<int> deviceList = GlobalConfig().audioOutputDeviceListFor(category);
        if (deviceList.isEmpty()) {
            return;
        }
        if (outputDeviceIndex == deviceList.takeFirst()) { // removing the first device so that
            // if it's the same device as the one we tried we only try all the following
            foreach (int devIndex, deviceList) {
                if (pINTERFACE_CALL(setOutputDevice(devIndex))) {
                    handleAutomaticDeviceChange(devIndex, AudioOutputPrivate::FallbackChange);
                    break; // found one that works
                }
            }
        }
    }
}

void AudioOutputPrivate::_k_volumeChanged(qreal newVolume)
{
    if (!muted) {
        Q_Q(AudioOutput);
        emit q->volumeChanged(pow(newVolume, 0.67));
    }
}

void AudioOutputPrivate::_k_revertFallback()
{
    if (deviceBeforeFallback == -1) {
        return;
    }
    outputDeviceIndex = deviceBeforeFallback;
    pINTERFACE_CALL(setOutputDevice(outputDeviceIndex));
    Q_Q(AudioOutput);
    emit q->outputDeviceChanged(AudioOutputDevice::fromIndex(outputDeviceIndex));
}

void AudioOutputPrivate::_k_audioDeviceFailed()
{
    pDebug() << Q_FUNC_INFO;
    // outputDeviceIndex identifies a failing device
    // fall back in the preference list of output devices
    QList<int> deviceList = GlobalConfig().audioOutputDeviceListFor(category);
    foreach (int devIndex, deviceList) {
        // if it's the same device as the one that failed, ignore it
        if (outputDeviceIndex != devIndex) {
            if (pINTERFACE_CALL(setOutputDevice(devIndex))) {
                handleAutomaticDeviceChange(devIndex, FallbackChange);
                break; // found one that works
            }
        }
    }
}

void AudioOutputPrivate::_k_deviceListChanged()
{
    pDebug() << Q_FUNC_INFO;
    // let's see if there's a usable device higher in the preference list
    QList<int> deviceList = GlobalConfig().audioOutputDeviceListFor(category);
    foreach (int devIndex, deviceList) {
        pDebug() << devIndex;
        if (outputDeviceIndex == devIndex) {
            break; // we've reached the currently used device, nothing to change
        }
        if (pINTERFACE_CALL(setOutputDevice(devIndex))) {
            handleAutomaticDeviceChange(devIndex, HigherPreferenceChange);
            break; // found one with higher preference that works
        }
    }
}

void AudioOutputPrivate::handleAutomaticDeviceChange(int newIndex, DeviceChangeType type)
{
    Q_Q(AudioOutput);
    deviceBeforeFallback = outputDeviceIndex;
    outputDeviceIndex = newIndex;
    emit q->outputDeviceChanged(AudioOutputDevice::fromIndex(outputDeviceIndex));
    QString text;
    AudioOutputDevice device1 = AudioOutputDevice::fromIndex(deviceBeforeFallback);
    AudioOutputDevice device2 = AudioOutputDevice::fromIndex(outputDeviceIndex);
    switch (type) {
    case FallbackChange:
        text = AudioOutput::tr("The audio playback device %1 does not work.
"
            "Falling back to %2.").arg(device1.name()).arg(device2.name());
        break;
    case HigherPreferenceChange:
        text = AudioOutput::tr("Switching to the audio playback device %1
"
                "which just became available and has higher preference.").arg(device2.name());
        break;
    }
    Factory::notification("AudioDeviceFallback", text,
            QStringList(AudioOutput::tr("Revert back to device '%1'").arg(device1.name())),
            q, SLOT(_k_revertFallback()));
}

} //namespace Phonon

#include "audiooutput.moc"

#undef PHONON_CLASSNAME
#undef PHONON_INTERFACENAME
// vim: sw=4 ts=4 tw=100 et
<|endoftext|>


<commit_before>/*
    Copyright 2011 Google Inc.

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

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

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

#include "GrPathUtils.h"
#include "GrPoint.h"

static const int MAX_POINTS_PER_CURVE = 1 << 10;
const GrScalar GrPathUtils::gMinCurveTol (GrFloatToScalar(0.0001f));

uint32_t GrPathUtils::quadraticPointCount(const GrPoint points[],
                                          GrScalar tol) {
    if (tol < gMinCurveTol) {
        tol == gMinCurveTol;
    }
    GrAssert(tol > 0);

    GrScalar d = points[1].distanceToLineSegmentBetween(points[0], points[2]);
    if (d <= tol) {
        return 1;
    } else {
        // Each time we subdivide, d should be cut in 4. So we need to
        // subdivide x = log4(d/tol) times. x subdivisions creates 2^(x)
        // points.
        // 2^(log4(x)) = sqrt(x);
        int temp = SkScalarCeil(SkScalarSqrt(SkScalarDiv(d, tol)));
        int pow2 = GrNextPow2(temp);
        // Because of NaNs & INFs we can wind up with a degenerate temp
        // such that pow2 comes out negative. Also, our point generator
        // will always output at least one pt.
        if (pow2 < 1) {
            pow2 = 1;
        }
        return GrMin(pow2, MAX_POINTS_PER_CURVE);
    }
}

uint32_t GrPathUtils::generateQuadraticPoints(const GrPoint& p0,
                                              const GrPoint& p1,
                                              const GrPoint& p2,
                                              GrScalar tolSqd,
                                              GrPoint** points,
                                              uint32_t pointsLeft) {
    if (pointsLeft < 2 ||
        (p1.distanceToLineSegmentBetweenSqd(p0, p2)) < tolSqd) {
        (*points)[0] = p2;
        *points += 1;
        return 1;
    }

    GrPoint q[] = {
        { GrScalarAve(p0.fX, p1.fX), GrScalarAve(p0.fY, p1.fY) },
        { GrScalarAve(p1.fX, p2.fX), GrScalarAve(p1.fY, p2.fY) },
    };
    GrPoint r = { GrScalarAve(q[0].fX, q[1].fX), GrScalarAve(q[0].fY, q[1].fY) };

    pointsLeft >>= 1;
    uint32_t a = generateQuadraticPoints(p0, q[0], r, tolSqd, points, pointsLeft);
    uint32_t b = generateQuadraticPoints(r, q[1], p2, tolSqd, points, pointsLeft);
    return a + b;
}

uint32_t GrPathUtils::cubicPointCount(const GrPoint points[],
                                           GrScalar tol) {
    if (tol < gMinCurveTol) {
        tol == gMinCurveTol;
    }
    GrAssert(tol > 0);

    GrScalar d = GrMax(
        points[1].distanceToLineSegmentBetweenSqd(points[0], points[3]),
        points[2].distanceToLineSegmentBetweenSqd(points[0], points[3]));
    d = SkScalarSqrt(d);
    if (d <= tol) {
        return 1;
    } else {
        int temp = SkScalarCeil(SkScalarSqrt(SkScalarDiv(d, tol)));
        int pow2 = GrNextPow2(temp);
        // Because of NaNs & INFs we can wind up with a degenerate temp
        // such that pow2 comes out negative. Also, our point generator
        // will always output at least one pt.
        if (pow2 < 1) {
            pow2 = 1;
        }
        return GrMin(pow2, MAX_POINTS_PER_CURVE);
    }
}

uint32_t GrPathUtils::generateCubicPoints(const GrPoint& p0,
                                          const GrPoint& p1,
                                          const GrPoint& p2,
                                          const GrPoint& p3,
                                          GrScalar tolSqd,
                                          GrPoint** points,
                                          uint32_t pointsLeft) {
    if (pointsLeft < 2 ||
        (p1.distanceToLineSegmentBetweenSqd(p0, p3) < tolSqd &&
         p2.distanceToLineSegmentBetweenSqd(p0, p3) < tolSqd)) {
            (*points)[0] = p3;
            *points += 1;
            return 1;
        }
    GrPoint q[] = {
        { GrScalarAve(p0.fX, p1.fX), GrScalarAve(p0.fY, p1.fY) },
        { GrScalarAve(p1.fX, p2.fX), GrScalarAve(p1.fY, p2.fY) },
        { GrScalarAve(p2.fX, p3.fX), GrScalarAve(p2.fY, p3.fY) }
    };
    GrPoint r[] = {
        { GrScalarAve(q[0].fX, q[1].fX), GrScalarAve(q[0].fY, q[1].fY) },
        { GrScalarAve(q[1].fX, q[2].fX), GrScalarAve(q[1].fY, q[2].fY) }
    };
    GrPoint s = { GrScalarAve(r[0].fX, r[1].fX), GrScalarAve(r[0].fY, r[1].fY) };
    pointsLeft >>= 1;
    uint32_t a = generateCubicPoints(p0, q[0], r[0], s, tolSqd, points, pointsLeft);
    uint32_t b = generateCubicPoints(s, r[1], q[2], p3, tolSqd, points, pointsLeft);
    return a + b;
}

int GrPathUtils::worstCasePointCount(const GrPath& path, int* subpaths,
                                     GrScalar tol) {
    if (tol < gMinCurveTol) {
        tol == gMinCurveTol;
    }
    GrAssert(tol > 0);

    int pointCount = 0;
    *subpaths = 1;

    bool first = true;

    SkPath::Iter iter(path, false);
    GrPathCmd cmd;

    GrPoint pts[4];
    while ((cmd = (GrPathCmd)iter.next(pts)) != kEnd_PathCmd) {

        switch (cmd) {
            case kLine_PathCmd:
                pointCount += 1;
                break;
            case kQuadratic_PathCmd:
                pointCount += quadraticPointCount(pts, tol);
                break;
            case kCubic_PathCmd:
                pointCount += cubicPointCount(pts, tol);
                break;
            case kMove_PathCmd:
                pointCount += 1;
                if (!first) {
                    ++(*subpaths);
                }
                break;
            default:
                break;
        }
        first = false;
    }
    return pointCount;
}
<commit_msg>Fix bug where equality was used instead of assignment.<commit_after>/*
    Copyright 2011 Google Inc.

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

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

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

#include "GrPathUtils.h"
#include "GrPoint.h"

static const int MAX_POINTS_PER_CURVE = 1 << 10;
const GrScalar GrPathUtils::gMinCurveTol (GrFloatToScalar(0.0001f));

uint32_t GrPathUtils::quadraticPointCount(const GrPoint points[],
                                          GrScalar tol) {
    if (tol < gMinCurveTol) {
        tol = gMinCurveTol;
    }
    GrAssert(tol > 0);

    GrScalar d = points[1].distanceToLineSegmentBetween(points[0], points[2]);
    if (d <= tol) {
        return 1;
    } else {
        // Each time we subdivide, d should be cut in 4. So we need to
        // subdivide x = log4(d/tol) times. x subdivisions creates 2^(x)
        // points.
        // 2^(log4(x)) = sqrt(x);
        int temp = SkScalarCeil(SkScalarSqrt(SkScalarDiv(d, tol)));
        int pow2 = GrNextPow2(temp);
        // Because of NaNs & INFs we can wind up with a degenerate temp
        // such that pow2 comes out negative. Also, our point generator
        // will always output at least one pt.
        if (pow2 < 1) {
            pow2 = 1;
        }
        return GrMin(pow2, MAX_POINTS_PER_CURVE);
    }
}

uint32_t GrPathUtils::generateQuadraticPoints(const GrPoint& p0,
                                              const GrPoint& p1,
                                              const GrPoint& p2,
                                              GrScalar tolSqd,
                                              GrPoint** points,
                                              uint32_t pointsLeft) {
    if (pointsLeft < 2 ||
        (p1.distanceToLineSegmentBetweenSqd(p0, p2)) < tolSqd) {
        (*points)[0] = p2;
        *points += 1;
        return 1;
    }

    GrPoint q[] = {
        { GrScalarAve(p0.fX, p1.fX), GrScalarAve(p0.fY, p1.fY) },
        { GrScalarAve(p1.fX, p2.fX), GrScalarAve(p1.fY, p2.fY) },
    };
    GrPoint r = { GrScalarAve(q[0].fX, q[1].fX), GrScalarAve(q[0].fY, q[1].fY) };

    pointsLeft >>= 1;
    uint32_t a = generateQuadraticPoints(p0, q[0], r, tolSqd, points, pointsLeft);
    uint32_t b = generateQuadraticPoints(r, q[1], p2, tolSqd, points, pointsLeft);
    return a + b;
}

uint32_t GrPathUtils::cubicPointCount(const GrPoint points[],
                                           GrScalar tol) {
    if (tol < gMinCurveTol) {
        tol = gMinCurveTol;
    }
    GrAssert(tol > 0);

    GrScalar d = GrMax(
        points[1].distanceToLineSegmentBetweenSqd(points[0], points[3]),
        points[2].distanceToLineSegmentBetweenSqd(points[0], points[3]));
    d = SkScalarSqrt(d);
    if (d <= tol) {
        return 1;
    } else {
        int temp = SkScalarCeil(SkScalarSqrt(SkScalarDiv(d, tol)));
        int pow2 = GrNextPow2(temp);
        // Because of NaNs & INFs we can wind up with a degenerate temp
        // such that pow2 comes out negative. Also, our point generator
        // will always output at least one pt.
        if (pow2 < 1) {
            pow2 = 1;
        }
        return GrMin(pow2, MAX_POINTS_PER_CURVE);
    }
}

uint32_t GrPathUtils::generateCubicPoints(const GrPoint& p0,
                                          const GrPoint& p1,
                                          const GrPoint& p2,
                                          const GrPoint& p3,
                                          GrScalar tolSqd,
                                          GrPoint** points,
                                          uint32_t pointsLeft) {
    if (pointsLeft < 2 ||
        (p1.distanceToLineSegmentBetweenSqd(p0, p3) < tolSqd &&
         p2.distanceToLineSegmentBetweenSqd(p0, p3) < tolSqd)) {
            (*points)[0] = p3;
            *points += 1;
            return 1;
        }
    GrPoint q[] = {
        { GrScalarAve(p0.fX, p1.fX), GrScalarAve(p0.fY, p1.fY) },
        { GrScalarAve(p1.fX, p2.fX), GrScalarAve(p1.fY, p2.fY) },
        { GrScalarAve(p2.fX, p3.fX), GrScalarAve(p2.fY, p3.fY) }
    };
    GrPoint r[] = {
        { GrScalarAve(q[0].fX, q[1].fX), GrScalarAve(q[0].fY, q[1].fY) },
        { GrScalarAve(q[1].fX, q[2].fX), GrScalarAve(q[1].fY, q[2].fY) }
    };
    GrPoint s = { GrScalarAve(r[0].fX, r[1].fX), GrScalarAve(r[0].fY, r[1].fY) };
    pointsLeft >>= 1;
    uint32_t a = generateCubicPoints(p0, q[0], r[0], s, tolSqd, points, pointsLeft);
    uint32_t b = generateCubicPoints(s, r[1], q[2], p3, tolSqd, points, pointsLeft);
    return a + b;
}

int GrPathUtils::worstCasePointCount(const GrPath& path, int* subpaths,
                                     GrScalar tol) {
    if (tol < gMinCurveTol) {
        tol = gMinCurveTol;
    }
    GrAssert(tol > 0);

    int pointCount = 0;
    *subpaths = 1;

    bool first = true;

    SkPath::Iter iter(path, false);
    GrPathCmd cmd;

    GrPoint pts[4];
    while ((cmd = (GrPathCmd)iter.next(pts)) != kEnd_PathCmd) {

        switch (cmd) {
            case kLine_PathCmd:
                pointCount += 1;
                break;
            case kQuadratic_PathCmd:
                pointCount += quadraticPointCount(pts, tol);
                break;
            case kCubic_PathCmd:
                pointCount += cubicPointCount(pts, tol);
                break;
            case kMove_PathCmd:
                pointCount += 1;
                if (!first) {
                    ++(*subpaths);
                }
                break;
            default:
                break;
        }
        first = false;
    }
    return pointCount;
}
<|endoftext|>


<commit_before>/*
    Copyright (C) 2002 by Norman Krmer

    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Library General Public
    License as published by the Free Software Foundation; either
    version 2 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
    Library General Public License for more details.

    You should have received a copy of the GNU Library General Public
    License along with this library; if not, write to the Free
    Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/

#include "cssysdef.h"
#include "csver.h"
#include "csjoylin.h"
#include "ivaria/reporter.h"
#include "csutil/csstring.h"
#include "csutil/csvector.h"

#include <fcntl.h>
#include <unistd.h>
#include <linux/joystick.h>

#define CS_LINUX_JOYSTICK_CFG "/config/joystick.cfg"
#define CS_LINUX_JOYSTICK_KEY "Device.Joystick."

#define CS_LINUX_JOYSTICK_OLD_EVENTS // the values of the first two axis are sent only

CS_IMPLEMENT_PLUGIN;

SCF_IMPLEMENT_IBASE (csLinuxJoystick)
  SCF_IMPLEMENTS_INTERFACE (iComponent)
  SCF_IMPLEMENTS_EMBEDDED_INTERFACE (iEventPlug)
  SCF_IMPLEMENTS_EMBEDDED_INTERFACE (iEventHandler)
SCF_IMPLEMENT_IBASE_END

SCF_IMPLEMENT_EMBEDDED_IBASE (csLinuxJoystick::eiEventPlug)
  SCF_IMPLEMENTS_INTERFACE (iEventPlug)
SCF_IMPLEMENT_EMBEDDED_IBASE_END

SCF_IMPLEMENT_EMBEDDED_IBASE (csLinuxJoystick::eiEventHandler)
  SCF_IMPLEMENTS_INTERFACE (iEventHandler)
SCF_IMPLEMENT_EMBEDDED_IBASE_END

csLinuxJoystick::csLinuxJoystick (iBase *parent):
  object_reg(0),
  joystick(0),
  nJoy(0),
  bHooked(false),
  EventOutlet(0)
{
  SCF_CONSTRUCT_IBASE(parent);
  SCF_CONSTRUCT_EMBEDDED_IBASE(scfiEventPlug);
  SCF_CONSTRUCT_EMBEDDED_IBASE(scfiEventHandler);
}

csLinuxJoystick::~csLinuxJoystick ()
{
  Close ();
}

bool csLinuxJoystick::Initialize (iObjectRegistry *oreg)
{
  object_reg = oreg;
  return Init ();
}

bool csLinuxJoystick::HandleEvent (iEvent &)
{
  struct js_event js;

  for (int i=0; i < nJoy; i++)
  {
    while (read (joystick [i].fd, &js, sizeof(struct js_event)) == sizeof(struct js_event))
    {
      switch (js.type & ~JS_EVENT_INIT)
      {
      case JS_EVENT_BUTTON:
        //        DEBUG_BREAK;
        joystick[i].button[js.number] = js.value;
        EventOutlet->Joystick (i, js.number+1, js.value, -1, 0);
        break;
      case JS_EVENT_AXIS:
        joystick[i].axis[js.number] = js.value;
#ifdef CS_LINUX_JOYSTICK_OLD_EVENTS
        if (js.number < 2)
          EventOutlet->Joystick (i, 0, 0, joystick[i].axis[0], (joystick[i].nAxes > 1 ? joystick[i].axis[1] : 0));
#else
        EventOutlet->Joystick (i, 0, 0, js.number, js.value);
#endif
        break;
      }
    }
  }
  return false;
}

bool csLinuxJoystick::Init ()
{
  // read list of devices
  config.AddConfig (object_reg, CS_LINUX_JOYSTICK_CFG);

  // create the key
  csString key(CS_LINUX_JOYSTICK_KEY);
  key += CS_PLATFORM_NAME;
  key += ".";
  key += CS_COMPILER_NAME;
  key += ".";

  csRef<iConfigIterator> it (config->Enumerate (CS_LINUX_JOYSTICK_KEY));

  csVector h;
  int fd;

  nJoy=0;
  bHooked = false;
  EventOutlet = 0;

  while (it->Next ())
  {
    if ((fd = open (it->GetStr (), O_RDONLY)) < 0)
    {
      Report (CS_REPORTER_SEVERITY_NOTIFY,
              "Failed to open joystick device %s - error: %s\n",
              it->GetStr (),
              strerror (errno));
    }
    else
      nJoy++;
    h.Push ((void*) fd);
  }

  if (nJoy)
  {
    delete [] joystick;
    joystick = new joydata[nJoy];

    for (int i=0, n=0; i < h.Length (); i++)
    {
      fd = (int)h.Get (i);
      if (fd > -1)
      {
	unsigned char axes = 2;
	unsigned char buttons = 2;
	int version = 0x000800;
	char name[128] = "Unknown";

	ioctl (fd, JSIOCGVERSION, &version);
	ioctl (fd, JSIOCGAXES, &axes);
	ioctl (fd, JSIOCGBUTTONS, &buttons);
	ioctl (fd, JSIOCGNAME(128), name);

	Report (CS_REPORTER_SEVERITY_NOTIFY,
                "Joystick number %d (%s) has %d axes and %d buttons. Driver version is %d.%d.%d.\n",
		i, name, axes, buttons, version >> 16, (version >> 8) & 0xff, version & 0xff);
        joystick[n].number = i;
        joystick[n].fd = fd;
        joystick[n].nButtons = buttons;
        joystick[n].nAxes = axes;
        joystick[n].axis = new int16[axes];
        joystick[n].button = new int16[buttons];

        // make device non blocking
        fcntl(fd, F_SETFL, O_NONBLOCK);
        n++;
      }
    }

    // hook into eventqueue
    csRef<iEventQueue> eq (CS_QUERY_REGISTRY(object_reg, iEventQueue));
    if (eq != 0)
    {
      eq->RegisterListener (&scfiEventHandler, CSMASK_Nothing);
      EventOutlet = eq->CreateEventOutlet (&scfiEventPlug);
      bHooked = true;
    }
  }
  else
  {
    Report (CS_REPORTER_SEVERITY_NOTIFY,
            "No operable joystick found\n");
  }

  return EventOutlet.IsValid();
}

bool csLinuxJoystick::Close ()
{
  if (bHooked)
  {
    csRef<iEventQueue> eq (CS_QUERY_REGISTRY(object_reg, iEventQueue));
    if (eq != 0)
      eq->RemoveListener (&scfiEventHandler);
    bHooked = false;
  }

  EventOutlet = 0;

  for (int i=0; i<nJoy; i++)
    close (joystick[i].fd);

  delete [] joystick;
  joystick = 0;
  nJoy = 0;

  return true;
}

void csLinuxJoystick::Report (int severity, const char* msg, ...)
{
  va_list arg;
  va_start (arg, msg);
  csRef<iReporter> rep (CS_QUERY_REGISTRY (object_reg, iReporter));
  if (rep)
    rep->ReportV (severity, "crystalspace.device.joystick.linux", msg, arg);
  else
  {
    csPrintfV (msg, arg);
    csPrintf ("\n");
  }
  va_end (arg);
}

SCF_IMPLEMENT_FACTORY (csLinuxJoystick);

<commit_msg>move from csVetor to csArray for linux joystick plugin<commit_after>/*
    Copyright (C) 2002 by Norman Krmer

    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Library General Public
    License as published by the Free Software Foundation; either
    version 2 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
    Library General Public License for more details.

    You should have received a copy of the GNU Library General Public
    License along with this library; if not, write to the Free
    Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/

#include "cssysdef.h"
#include "csver.h"
#include "csjoylin.h"
#include "ivaria/reporter.h"
#include "csutil/csstring.h"
#include "csutil/csvector.h"

#include <fcntl.h>
#include <unistd.h>
#include <linux/joystick.h>

#define CS_LINUX_JOYSTICK_CFG "/config/joystick.cfg"
#define CS_LINUX_JOYSTICK_KEY "Device.Joystick."

#define CS_LINUX_JOYSTICK_OLD_EVENTS // the values of the first two axis are sent only

CS_IMPLEMENT_PLUGIN;

SCF_IMPLEMENT_IBASE (csLinuxJoystick)
  SCF_IMPLEMENTS_INTERFACE (iComponent)
  SCF_IMPLEMENTS_EMBEDDED_INTERFACE (iEventPlug)
  SCF_IMPLEMENTS_EMBEDDED_INTERFACE (iEventHandler)
SCF_IMPLEMENT_IBASE_END

SCF_IMPLEMENT_EMBEDDED_IBASE (csLinuxJoystick::eiEventPlug)
  SCF_IMPLEMENTS_INTERFACE (iEventPlug)
SCF_IMPLEMENT_EMBEDDED_IBASE_END

SCF_IMPLEMENT_EMBEDDED_IBASE (csLinuxJoystick::eiEventHandler)
  SCF_IMPLEMENTS_INTERFACE (iEventHandler)
SCF_IMPLEMENT_EMBEDDED_IBASE_END

csLinuxJoystick::csLinuxJoystick (iBase *parent):
  object_reg(0),
  joystick(0),
  nJoy(0),
  bHooked(false),
  EventOutlet(0)
{
  SCF_CONSTRUCT_IBASE(parent);
  SCF_CONSTRUCT_EMBEDDED_IBASE(scfiEventPlug);
  SCF_CONSTRUCT_EMBEDDED_IBASE(scfiEventHandler);
}

csLinuxJoystick::~csLinuxJoystick ()
{
  Close ();
}

bool csLinuxJoystick::Initialize (iObjectRegistry *oreg)
{
  object_reg = oreg;
  return Init ();
}

bool csLinuxJoystick::HandleEvent (iEvent &)
{
  struct js_event js;

  for (int i=0; i < nJoy; i++)
  {
    while (read (joystick [i].fd, &js, sizeof(struct js_event)) == sizeof(struct js_event))
    {
      switch (js.type & ~JS_EVENT_INIT)
      {
      case JS_EVENT_BUTTON:
        //        DEBUG_BREAK;
        joystick[i].button[js.number] = js.value;
        EventOutlet->Joystick (i, js.number+1, js.value, -1, 0);
        break;
      case JS_EVENT_AXIS:
        joystick[i].axis[js.number] = js.value;
#ifdef CS_LINUX_JOYSTICK_OLD_EVENTS
        if (js.number < 2)
          EventOutlet->Joystick (i, 0, 0, joystick[i].axis[0], (joystick[i].nAxes > 1 ? joystick[i].axis[1] : 0));
#else
        EventOutlet->Joystick (i, 0, 0, js.number, js.value);
#endif
        break;
      }
    }
  }
  return false;
}

bool csLinuxJoystick::Init ()
{
  // read list of devices
  config.AddConfig (object_reg, CS_LINUX_JOYSTICK_CFG);

  // create the key
  csString key(CS_LINUX_JOYSTICK_KEY);
  key += CS_PLATFORM_NAME;
  key += ".";
  key += CS_COMPILER_NAME;
  key += ".";

  csRef<iConfigIterator> it (config->Enumerate (CS_LINUX_JOYSTICK_KEY));

  csArray<void*> h;
  int fd;

  nJoy=0;
  bHooked = false;
  EventOutlet = 0;

  while (it->Next ())
  {
    if ((fd = open (it->GetStr (), O_RDONLY)) < 0)
    {
      Report (CS_REPORTER_SEVERITY_NOTIFY,
              "Failed to open joystick device %s - error: %s\n",
              it->GetStr (),
              strerror (errno));
    }
    else
      nJoy++;
    h.Push ((void*) fd);
  }

  if (nJoy)
  {
    delete [] joystick;
    joystick = new joydata[nJoy];

    for (int i=0, n=0; i < h.Length (); i++)
    {
      fd = (int)h.Get (i);
      if (fd > -1)
      {
	unsigned char axes = 2;
	unsigned char buttons = 2;
	int version = 0x000800;
	char name[128] = "Unknown";

	ioctl (fd, JSIOCGVERSION, &version);
	ioctl (fd, JSIOCGAXES, &axes);
	ioctl (fd, JSIOCGBUTTONS, &buttons);
	ioctl (fd, JSIOCGNAME(128), name);

	Report (CS_REPORTER_SEVERITY_NOTIFY,
                "Joystick number %d (%s) has %d axes and %d buttons. Driver version is %d.%d.%d.\n",
		i, name, axes, buttons, version >> 16, (version >> 8) & 0xff, version & 0xff);
        joystick[n].number = i;
        joystick[n].fd = fd;
        joystick[n].nButtons = buttons;
        joystick[n].nAxes = axes;
        joystick[n].axis = new int16[axes];
        joystick[n].button = new int16[buttons];

        // make device non blocking
        fcntl(fd, F_SETFL, O_NONBLOCK);
        n++;
      }
    }

    // hook into eventqueue
    csRef<iEventQueue> eq (CS_QUERY_REGISTRY(object_reg, iEventQueue));
    if (eq != 0)
    {
      eq->RegisterListener (&scfiEventHandler, CSMASK_Nothing);
      EventOutlet = eq->CreateEventOutlet (&scfiEventPlug);
      bHooked = true;
    }
  }
  else
  {
    Report (CS_REPORTER_SEVERITY_NOTIFY,
            "No operable joystick found\n");
  }

  return EventOutlet.IsValid();
}

bool csLinuxJoystick::Close ()
{
  if (bHooked)
  {
    csRef<iEventQueue> eq (CS_QUERY_REGISTRY(object_reg, iEventQueue));
    if (eq != 0)
      eq->RemoveListener (&scfiEventHandler);
    bHooked = false;
  }

  EventOutlet = 0;

  for (int i=0; i<nJoy; i++)
    close (joystick[i].fd);

  delete [] joystick;
  joystick = 0;
  nJoy = 0;

  return true;
}

void csLinuxJoystick::Report (int severity, const char* msg, ...)
{
  va_list arg;
  va_start (arg, msg);
  csRef<iReporter> rep (CS_QUERY_REGISTRY (object_reg, iReporter));
  if (rep)
    rep->ReportV (severity, "crystalspace.device.joystick.linux", msg, arg);
  else
  {
    csPrintfV (msg, arg);
    csPrintf ("\n");
  }
  va_end (arg);
}

SCF_IMPLEMENT_FACTORY (csLinuxJoystick);

<|endoftext|>