<commit_before>/* $Id: ex18.C,v 1.14 2007-02-27 16:02:58 jwpeterson Exp $ */

/* The Next Great Finite Element Library. */
/* Copyright (C) 2003  Benjamin S. Kirk */

/* 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */

 //
Example 18 - Unsteady Navier-Stokes Equations with DiffSystem

 //
 // This example shows how the transient nonlinear problem from
 // example 13 can be solved using the new (and experimental)
 // DiffSystem class framework

// Basic include files
#include "equation_systems.h"
#include "error_vector.h"
#include "getpot.h"
#include "gmv_io.h"
#include "kelly_error_estimator.h"
#include "mesh.h"
#include "mesh_generation.h"
#include "mesh_refinement.h"
#include "uniform_refinement_estimator.h"

// Some (older) compilers do not offer full stream
// functionality, OStringStream works around this.
#include "o_string_stream.h"

// The systems and solvers we may use
#include "naviersystem.h"
#include "diff_solver.h"
#include "euler_solver.h"
#include "steady_solver.h"

// The main program.
int main (int argc, char** argv)
{
  // Initialize libMesh.
  libMesh::init (argc, argv);
  {
    // Parse the input file
    GetPot infile("ex18.in");

    // Read in parameters from the input file
    const Real global_tolerance          = infile("global_tolerance", 0.);
    const unsigned int nelem_target      = infile("n_elements", 400);
    const bool transient                 = infile("transient", true);
    const Real deltat                    = infile("deltat", 0.005);
    unsigned int n_timesteps             = infile("n_timesteps", 20);
    const unsigned int write_interval    = infile("write_interval", 5);
    const unsigned int coarsegridsize    = infile("coarsegridsize", 1);
    const unsigned int coarserefinements = infile("coarserefinements", 0);
    const unsigned int max_adaptivesteps = infile("max_adaptivesteps", 10);
    const unsigned int dim               = infile("dimension", 2);

    assert (dim == 2 || dim == 3);
    // Create a n-dimensional mesh.
    Mesh mesh (dim);

    // And an object to refine it
    MeshRefinement mesh_refinement(mesh);
    mesh_refinement.coarsen_by_parents() = true;
    mesh_refinement.absolute_global_tolerance() = global_tolerance;
    mesh_refinement.nelem_target() = nelem_target;
    mesh_refinement.refine_fraction() = 0.3;
    mesh_refinement.coarsen_fraction() = 0.3;
    mesh_refinement.coarsen_threshold() = 0.1;

    // Use the MeshTools::Generation mesh generator to create a uniform
    // grid on the square [-1,1]^D.  We instruct the mesh generator
    // to build a mesh of 8x8 \p Quad9 elements in 2D, or \p Hex27
    // elements in 3D.  Building these higher-order elements allows
    // us to use higher-order approximation, as in example 3.
    if (dim == 2)
      MeshTools::Generation::build_square (mesh,
                                           coarsegridsize,
                                           coarsegridsize,
                                           0., 1.,
                                           0., 1.,
                                           QUAD9);
    else if (dim == 3)
      MeshTools::Generation::build_cube (mesh,
                                         coarsegridsize,
                                         coarsegridsize,
                                         coarsegridsize,
                                         0., 1.,
                                         0., 1.,
                                         0., 1.,
                                         HEX27);

    mesh_refinement.uniformly_refine(coarserefinements);

    // Print information about the mesh to the screen.
    mesh.print_info();

    // Create an equation systems object.
    EquationSystems equation_systems (mesh);

    // Declare the system "Navier-Stokes" and its variables.
    NavierSystem & system =
      equation_systems.add_system<NavierSystem> ("Navier-Stokes");

    // Solve this as a time-dependent or steady system
    if (transient)
      system.time_solver =
        AutoPtr<TimeSolver>(new EulerSolver(system));
    else
      {
        system.time_solver =
          AutoPtr<TimeSolver>(new SteadySolver(system));
        assert(n_timesteps == 1);
      }

    // Initialize the system
    equation_systems.init ();

    // Set the time stepping options
    system.deltat = deltat;

    // And the nonlinear solver options
    DiffSolver &solver = *(system.time_solver->diff_solver().get());
    solver.quiet = infile("solver_quiet", true);
    solver.max_nonlinear_iterations =
      infile("max_nonlinear_iterations", 15);
    solver.relative_step_tolerance =
      infile("relative_step_tolerance", 1.e-3);
    solver.relative_residual_tolerance =
      infile("relative_residual_tolerance", 0);

    // And the linear solver options
    solver.max_linear_iterations =
      infile("max_linear_iterations", 50000);
    solver.initial_linear_tolerance =
      infile("initial_linear_tolerance", 1.e-3);

    // Print information about the system to the screen.
    equation_systems.print_info();

    // Now we begin the timestep loop to compute the time-accurate
    // solution of the equations.
    for (unsigned int t_step=0; t_step != n_timesteps; ++t_step)
      {
        // A pretty update message
        std::cout << " Solving time step " << t_step << ", time = "
                  << system.time << std::endl;

        // Adaptively solve the timestep
        unsigned int a_step = 0;
        for (; a_step != max_adaptivesteps; ++a_step)
          {
            system.solve();

            ErrorVector error;

            AutoPtr<ErrorEstimator> error_estimator;

            // To solve to a tolerance in this problem we
            // need a better estimator than Kelly
            if (global_tolerance != 0.)
              {
                // We can't adapt to both a tolerance and a mesh
                // size at once
                assert (nelem_target == 0);

                UniformRefinementEstimator *u =
                  new UniformRefinementEstimator;

                // The lid-driven cavity problem isn't in H1, so
                // lets estimate H0 (i.e. L2) error
                u->sobolev_order() = 0;

                error_estimator.reset(u);
              }
            else
              {
                // If we aren't adapting to a tolerance we need a
                // target mesh size
                assert (nelem_target > 0);

                // Kelly is a lousy estimator to use for a problem
                // not in H1 - if we were doing more than a few
                // timesteps we'd need to turn off or limit the
                // maximum level of our adaptivity eventually
                error_estimator.reset(new KellyErrorEstimator);
              }

            // Calculate error based on u and v but not p
            error_estimator->component_scale.push_back(1.0); // u
            error_estimator->component_scale.push_back(1.0); // v
            if (dim == 3)
              error_estimator->component_scale.push_back(1.0); // w
            error_estimator->component_scale.push_back(0.0); // p

            error_estimator->estimate_error(system, error);

            // Print out status at each adaptive step.
            Real global_error = error.l2_norm();
            std::cout << "adaptive step " << a_step << ": ";
            if (global_tolerance != 0.)
              std::cout << "global_error = " << global_error
                        << " with ";
            std::cout << mesh.n_active_elem()
                      << " active elements and "
                      << equation_systems.n_active_dofs()
                      << " active dofs." << std::endl;
            if (global_tolerance != 0.)
              std::cout << "worst element error = " << error.maximum()
                        << ", mean = " << error.mean() << std::endl;

            if (global_tolerance != 0.)
              {
                // If we've reached our desired tolerance, we
                // don't need any more adaptive steps
                if (global_error < global_tolerance)
                  break;
                mesh_refinement.flag_elements_by_error_tolerance(error);
              }
            else
              {
                // If flag_elements_by_nelem_target returns true, this
                // should be our last adaptive step.
                if (mesh_refinement.flag_elements_by_nelem_target(error))
                  {
                    mesh_refinement.refine_and_coarsen_elements();
                    equation_systems.reinit();
                    break;
                  }
              }

            // Carry out the adaptive mesh refinement/coarsening
            mesh_refinement.refine_and_coarsen_elements();
            equation_systems.reinit();
          }
        // Do one last solve if necessary
        if (a_step == max_adaptivesteps)
          {
            system.solve();
          }

        // Advance to the next timestep in a transient problem
        system.time_solver->advance_timestep();

        // Write out this timestep if we're requested to
        if ((t_step+1)%write_interval == 0)
          {
            OStringStream file_name;

            // We write the file name in the gmv auto-read format.
            file_name << "out.gmv.";
            OSSRealzeroright(file_name,3,0, t_step + 1);

            GMVIO(mesh).write_equation_systems (file_name.str(),
                                                equation_systems);
          }
      }
  }

  // All done.
  return libMesh::close ();
}
<commit_msg>Fix relative_residual_tolerance read bug, undersolved adaptivity bug<commit_after>/* $Id: ex18.C,v 1.15 2007-02-27 19:51:43 roystgnr Exp $ */

/* The Next Great Finite Element Library. */
/* Copyright (C) 2003  Benjamin S. Kirk */

/* 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */

 //
Example 18 - Unsteady Navier-Stokes Equations with DiffSystem

 //
 // This example shows how the transient nonlinear problem from
 // example 13 can be solved using the new (and experimental)
 // DiffSystem class framework

// Basic include files
#include "equation_systems.h"
#include "error_vector.h"
#include "getpot.h"
#include "gmv_io.h"
#include "kelly_error_estimator.h"
#include "mesh.h"
#include "mesh_generation.h"
#include "mesh_refinement.h"
#include "uniform_refinement_estimator.h"

// Some (older) compilers do not offer full stream
// functionality, OStringStream works around this.
#include "o_string_stream.h"

// The systems and solvers we may use
#include "naviersystem.h"
#include "diff_solver.h"
#include "euler_solver.h"
#include "steady_solver.h"

// The main program.
int main (int argc, char** argv)
{
  // Initialize libMesh.
  libMesh::init (argc, argv);
  {
    // Parse the input file
    GetPot infile("ex18.in");

    // Read in parameters from the input file
    const Real global_tolerance          = infile("global_tolerance", 0.);
    const unsigned int nelem_target      = infile("n_elements", 400);
    const bool transient                 = infile("transient", true);
    const Real deltat                    = infile("deltat", 0.005);
    unsigned int n_timesteps             = infile("n_timesteps", 20);
    const unsigned int write_interval    = infile("write_interval", 5);
    const unsigned int coarsegridsize    = infile("coarsegridsize", 1);
    const unsigned int coarserefinements = infile("coarserefinements", 0);
    const unsigned int max_adaptivesteps = infile("max_adaptivesteps", 10);
    const unsigned int dim               = infile("dimension", 2);

    assert (dim == 2 || dim == 3);
    // Create a n-dimensional mesh.
    Mesh mesh (dim);

    // And an object to refine it
    MeshRefinement mesh_refinement(mesh);
    mesh_refinement.coarsen_by_parents() = true;
    mesh_refinement.absolute_global_tolerance() = global_tolerance;
    mesh_refinement.nelem_target() = nelem_target;
    mesh_refinement.refine_fraction() = 0.3;
    mesh_refinement.coarsen_fraction() = 0.3;
    mesh_refinement.coarsen_threshold() = 0.1;

    // Use the MeshTools::Generation mesh generator to create a uniform
    // grid on the square [-1,1]^D.  We instruct the mesh generator
    // to build a mesh of 8x8 \p Quad9 elements in 2D, or \p Hex27
    // elements in 3D.  Building these higher-order elements allows
    // us to use higher-order approximation, as in example 3.
    if (dim == 2)
      MeshTools::Generation::build_square (mesh,
                                           coarsegridsize,
                                           coarsegridsize,
                                           0., 1.,
                                           0., 1.,
                                           QUAD9);
    else if (dim == 3)
      MeshTools::Generation::build_cube (mesh,
                                         coarsegridsize,
                                         coarsegridsize,
                                         coarsegridsize,
                                         0., 1.,
                                         0., 1.,
                                         0., 1.,
                                         HEX27);

    mesh_refinement.uniformly_refine(coarserefinements);

    // Print information about the mesh to the screen.
    mesh.print_info();

    // Create an equation systems object.
    EquationSystems equation_systems (mesh);

    // Declare the system "Navier-Stokes" and its variables.
    NavierSystem & system =
      equation_systems.add_system<NavierSystem> ("Navier-Stokes");

    // Solve this as a time-dependent or steady system
    if (transient)
      system.time_solver =
        AutoPtr<TimeSolver>(new EulerSolver(system));
    else
      {
        system.time_solver =
          AutoPtr<TimeSolver>(new SteadySolver(system));
        assert(n_timesteps == 1);
      }

    // Initialize the system
    equation_systems.init ();

    // Set the time stepping options
    system.deltat = deltat;

    // And the nonlinear solver options
    DiffSolver &solver = *(system.time_solver->diff_solver().get());
    solver.quiet = infile("solver_quiet", true);
    solver.max_nonlinear_iterations =
      infile("max_nonlinear_iterations", 15);
    solver.relative_step_tolerance =
      infile("relative_step_tolerance", 1.e-3);
    solver.relative_residual_tolerance =
      infile("relative_residual_tolerance", 0.0);

    // And the linear solver options
    solver.max_linear_iterations =
      infile("max_linear_iterations", 50000);
    solver.initial_linear_tolerance =
      infile("initial_linear_tolerance", 1.e-3);

    // Print information about the system to the screen.
    equation_systems.print_info();

    // Now we begin the timestep loop to compute the time-accurate
    // solution of the equations.
    for (unsigned int t_step=0; t_step != n_timesteps; ++t_step)
      {
        // A pretty update message
        std::cout << " Solving time step " << t_step << ", time = "
                  << system.time << std::endl;

        // Adaptively solve the timestep
        unsigned int a_step = 0;
        for (; a_step != max_adaptivesteps; ++a_step)
          {
            system.solve();

            ErrorVector error;

            AutoPtr<ErrorEstimator> error_estimator;

            // To solve to a tolerance in this problem we
            // need a better estimator than Kelly
            if (global_tolerance != 0.)
              {
                // We can't adapt to both a tolerance and a mesh
                // size at once
                assert (nelem_target == 0);

                UniformRefinementEstimator *u =
                  new UniformRefinementEstimator;

                // The lid-driven cavity problem isn't in H1, so
                // lets estimate H0 (i.e. L2) error
                u->sobolev_order() = 0;

                error_estimator.reset(u);
              }
            else
              {
                // If we aren't adapting to a tolerance we need a
                // target mesh size
                assert (nelem_target > 0);

                // Kelly is a lousy estimator to use for a problem
                // not in H1 - if we were doing more than a few
                // timesteps we'd need to turn off or limit the
                // maximum level of our adaptivity eventually
                error_estimator.reset(new KellyErrorEstimator);
              }

            // Calculate error based on u and v but not p
            error_estimator->component_scale.push_back(1.0); // u
            error_estimator->component_scale.push_back(1.0); // v
            if (dim == 3)
              error_estimator->component_scale.push_back(1.0); // w
            error_estimator->component_scale.push_back(0.0); // p

            error_estimator->estimate_error(system, error);

            // Print out status at each adaptive step.
            Real global_error = error.l2_norm();
            std::cout << "adaptive step " << a_step << ": ";
            if (global_tolerance != 0.)
              std::cout << "global_error = " << global_error
                        << " with ";
            std::cout << mesh.n_active_elem()
                      << " active elements and "
                      << equation_systems.n_active_dofs()
                      << " active dofs." << std::endl;
            if (global_tolerance != 0.)
              std::cout << "worst element error = " << error.maximum()
                        << ", mean = " << error.mean() << std::endl;

            if (global_tolerance != 0.)
              {
                // If we've reached our desired tolerance, we
                // don't need any more adaptive steps
                if (global_error < global_tolerance)
                  break;
                mesh_refinement.flag_elements_by_error_tolerance(error);
              }
            else
              {
                // If flag_elements_by_nelem_target returns true, this
                // should be our last adaptive step.
                if (mesh_refinement.flag_elements_by_nelem_target(error))
                  {
                    mesh_refinement.refine_and_coarsen_elements();
                    equation_systems.reinit();
                    a_step = max_adaptivesteps;
                    break;
                  }
              }

            // Carry out the adaptive mesh refinement/coarsening
            mesh_refinement.refine_and_coarsen_elements();
            equation_systems.reinit();
          }
        // Do one last solve if necessary
        if (a_step == max_adaptivesteps)
          {
            system.solve();
          }

        // Advance to the next timestep in a transient problem
        system.time_solver->advance_timestep();

        // Write out this timestep if we're requested to
        if ((t_step+1)%write_interval == 0)
          {
            OStringStream file_name;

            // We write the file name in the gmv auto-read format.
            file_name << "out.gmv.";
            OSSRealzeroright(file_name,3,0, t_step + 1);

            GMVIO(mesh).write_equation_systems (file_name.str(),
                                                equation_systems);
          }
      }
  }

  // All done.
  return libMesh::close ();
}
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: hatchwindow.cxx,v $
 *
 *  $Revision: 1.4 $
 *
 *  last change: $Author: obo $ $Date: 2006-09-17 14:57:27 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, 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
 *    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., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_svtools.hxx"

#ifndef _COM_SUN_STAR_EMBED_XHATCHWINDOWCONTROLLER_HPP_
#include <com/sun/star/embed/XHatchWindowController.hpp>
#endif

#include "hatchwindow.hxx"
#include "ipwin.hxx"

#include <toolkit/helper/convert.hxx>

using namespace ::com::sun::star;

VCLXHatchWindow::VCLXHatchWindow()
: VCLXWindow()
{
}

VCLXHatchWindow::~VCLXHatchWindow()
{
}

void VCLXHatchWindow::initializeWindow( const uno::Reference< awt::XWindowPeer >& xParent,
                const awt::Rectangle& aBounds,
                const awt::Size& aSize )
{
    Window* pParent = NULL;
    VCLXWindow* pParentComponent = VCLXWindow::GetImplementation( xParent );

    if ( pParentComponent )
        pParent = pParentComponent->GetWindow();

    OSL_ENSURE( pParent, "No parent window is provided!\n" );
    if ( !pParent )
        throw lang::IllegalArgumentException(); // TODO

    SvResizeWindow* pHatchWindow = new SvResizeWindow( pParent, this );
    pHatchWindow->SetPosSizePixel( aBounds.X, aBounds.Y, aBounds.Width, aBounds.Height );
    pHatchWindow->SetHatchBorderPixel( Size( aSize.Width, aSize.Height ) );

    SetWindow( pHatchWindow );
    pHatchWindow->SetComponentInterface( this );

    //pHatchWindow->Show();
}

void VCLXHatchWindow::QueryObjAreaPixel( Rectangle & aRect )
{
    if ( m_xController.is() )
    {
        awt::Rectangle aUnoRequestRect = AWTRectangle( aRect );

        try {
            awt::Rectangle aUnoResultRect = m_xController->calcAdjustedRectangle( aUnoRequestRect );
            aRect = VCLRectangle( aUnoResultRect );
        }
        catch( uno::Exception& )
        {
            OSL_ENSURE( sal_False, "Can't adjust rectangle size!\n" );
        }
    }
}

void VCLXHatchWindow::RequestObjAreaPixel( const Rectangle & aRect )
{
    if ( m_xController.is() )
    {
        awt::Rectangle aUnoRequestRect = AWTRectangle( aRect );

        try {
            m_xController->requestPositioning( aUnoRequestRect );
        }
        catch( uno::Exception& )
        {
            OSL_ENSURE( sal_False, "Can't request resizing!\n" );
        }
    }
}

void VCLXHatchWindow::InplaceDeactivate()
{
    if ( m_xController.is() )
    {
        // TODO: communicate with controller
    }
}

uno::Any SAL_CALL VCLXHatchWindow::queryInterface( const uno::Type & rType )
    throw( uno::RuntimeException )
{
    // Attention:
    //  Don't use mutex or guard in this method!!! Is a method of XInterface.

    uno::Any aReturn( ::cppu::queryInterface( rType,
                                           static_cast< embed::XHatchWindow* >( this ) ) );

    if ( aReturn.hasValue() == sal_True )
    {
        return aReturn ;
    }

    return VCLXWindow::queryInterface( rType ) ;
}

void SAL_CALL VCLXHatchWindow::acquire()
    throw()
{
    VCLXWindow::acquire();
}

void SAL_CALL VCLXHatchWindow::release()
    throw()
{
    VCLXWindow::release();
}

uno::Sequence< uno::Type > SAL_CALL VCLXHatchWindow::getTypes()
    throw( uno::RuntimeException )
{
    static ::cppu::OTypeCollection* pTypeCollection = NULL ;

    if ( pTypeCollection == NULL )
    {
        ::osl::MutexGuard aGuard( ::osl::Mutex::getGlobalMutex() ) ;

        if ( pTypeCollection == NULL )
        {
            static ::cppu::OTypeCollection aTypeCollection(
                    ::getCppuType(( const uno::Reference< embed::XHatchWindow >* )NULL ),
                    VCLXHatchWindow::getTypes() );

            pTypeCollection = &aTypeCollection ;
        }
    }

    return pTypeCollection->getTypes() ;
}

uno::Sequence< sal_Int8 > SAL_CALL VCLXHatchWindow::getImplementationId()
    throw( uno::RuntimeException )
{
    static ::cppu::OImplementationId* pID = NULL ;

    if ( pID == NULL )
    {
        ::osl::MutexGuard aGuard( ::osl::Mutex::getGlobalMutex() ) ;

        if ( pID == NULL )
        {
            static ::cppu::OImplementationId aID( sal_False ) ;
            pID = &aID ;
        }
    }

    return pID->getImplementationId() ;
}

void SAL_CALL VCLXHatchWindow::setController( const uno::Reference< embed::XHatchWindowController >& xController )
    throw (uno::RuntimeException)
{
    m_xController = xController;
}

void SAL_CALL VCLXHatchWindow::dispose()
    throw (uno::RuntimeException)
{
    VCLXWindow::dispose();
}

void SAL_CALL VCLXHatchWindow::addEventListener( const uno::Reference< lang::XEventListener >& xListener )
    throw (uno::RuntimeException)
{
    VCLXWindow::addEventListener( xListener );
}

void SAL_CALL VCLXHatchWindow::removeEventListener( const uno::Reference< lang::XEventListener >& xListener )
    throw (uno::RuntimeException)
{
    VCLXWindow::removeEventListener( xListener );
}

<commit_msg>INTEGRATION: CWS inplaceobjects (1.3.250); FILE MERGED 2006/09/28 19:30:48 mba 1.3.250.3: RESYNC: (1.3-1.4); FILE MERGED 2006/07/03 15:12:24 mba 1.3.250.2: #i66239#: need means to change border size 2006/06/14 10:57:13 mba 1.3.250.1: #i66239#: new API for inplace active objects<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: hatchwindow.cxx,v $
 *
 *  $Revision: 1.5 $
 *
 *  last change: $Author: vg $ $Date: 2006-11-01 18:18:23 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, 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
 *    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., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_svtools.hxx"

#ifndef _COM_SUN_STAR_EMBED_XHATCHWINDOWCONTROLLER_HPP_
#include <com/sun/star/embed/XHatchWindowController.hpp>
#endif

#include "hatchwindow.hxx"
#include "ipwin.hxx"

#include <toolkit/helper/convert.hxx>

using namespace ::com::sun::star;

VCLXHatchWindow::VCLXHatchWindow()
: VCLXWindow()
, pHatchWindow(0)
{
}

VCLXHatchWindow::~VCLXHatchWindow()
{
}

void VCLXHatchWindow::initializeWindow( const uno::Reference< awt::XWindowPeer >& xParent,
                const awt::Rectangle& aBounds,
                const awt::Size& aSize )
{
    Window* pParent = NULL;
    VCLXWindow* pParentComponent = VCLXWindow::GetImplementation( xParent );

    if ( pParentComponent )
        pParent = pParentComponent->GetWindow();

    OSL_ENSURE( pParent, "No parent window is provided!\n" );
    if ( !pParent )
        throw lang::IllegalArgumentException(); // TODO

    pHatchWindow = new SvResizeWindow( pParent, this );
    pHatchWindow->SetPosSizePixel( aBounds.X, aBounds.Y, aBounds.Width, aBounds.Height );
    aHatchBorderSize = aSize;
    pHatchWindow->SetHatchBorderPixel( Size( aSize.Width, aSize.Height ) );

    SetWindow( pHatchWindow );
    pHatchWindow->SetComponentInterface( this );

    //pHatchWindow->Show();
}

void VCLXHatchWindow::QueryObjAreaPixel( Rectangle & aRect )
{
    if ( m_xController.is() )
    {
        awt::Rectangle aUnoRequestRect = AWTRectangle( aRect );

        try {
            awt::Rectangle aUnoResultRect = m_xController->calcAdjustedRectangle( aUnoRequestRect );
            aRect = VCLRectangle( aUnoResultRect );
        }
        catch( uno::Exception& )
        {
            OSL_ENSURE( sal_False, "Can't adjust rectangle size!\n" );
        }
    }
}

void VCLXHatchWindow::RequestObjAreaPixel( const Rectangle & aRect )
{
    if ( m_xController.is() )
    {
        awt::Rectangle aUnoRequestRect = AWTRectangle( aRect );

        try {
            m_xController->requestPositioning( aUnoRequestRect );
        }
        catch( uno::Exception& )
        {
            OSL_ENSURE( sal_False, "Can't request resizing!\n" );
        }
    }
}

void VCLXHatchWindow::InplaceDeactivate()
{
    if ( m_xController.is() )
    {
        // TODO: communicate with controller
    }
}

uno::Any SAL_CALL VCLXHatchWindow::queryInterface( const uno::Type & rType )
    throw( uno::RuntimeException )
{
    // Attention:
    //  Don't use mutex or guard in this method!!! Is a method of XInterface.

    uno::Any aReturn( ::cppu::queryInterface( rType,
                                           static_cast< embed::XHatchWindow* >( this ) ) );

    if ( aReturn.hasValue() == sal_True )
    {
        return aReturn ;
    }

    return VCLXWindow::queryInterface( rType ) ;
}

void SAL_CALL VCLXHatchWindow::acquire()
    throw()
{
    VCLXWindow::acquire();
}

void SAL_CALL VCLXHatchWindow::release()
    throw()
{
    VCLXWindow::release();
}

uno::Sequence< uno::Type > SAL_CALL VCLXHatchWindow::getTypes()
    throw( uno::RuntimeException )
{
    static ::cppu::OTypeCollection* pTypeCollection = NULL ;

    if ( pTypeCollection == NULL )
    {
        ::osl::MutexGuard aGuard( ::osl::Mutex::getGlobalMutex() ) ;

        if ( pTypeCollection == NULL )
        {
            static ::cppu::OTypeCollection aTypeCollection(
                    ::getCppuType(( const uno::Reference< embed::XHatchWindow >* )NULL ),
                    VCLXHatchWindow::getTypes() );

            pTypeCollection = &aTypeCollection ;
        }
    }

    return pTypeCollection->getTypes() ;
}

uno::Sequence< sal_Int8 > SAL_CALL VCLXHatchWindow::getImplementationId()
    throw( uno::RuntimeException )
{
    static ::cppu::OImplementationId* pID = NULL ;

    if ( pID == NULL )
    {
        ::osl::MutexGuard aGuard( ::osl::Mutex::getGlobalMutex() ) ;

        if ( pID == NULL )
        {
            static ::cppu::OImplementationId aID( sal_False ) ;
            pID = &aID ;
        }
    }

    return pID->getImplementationId() ;
}

::com::sun::star::awt::Size SAL_CALL VCLXHatchWindow::getHatchBorderSize() throw (::com::sun::star::uno::RuntimeException)
{
    return aHatchBorderSize;
}

void SAL_CALL VCLXHatchWindow::setHatchBorderSize( const ::com::sun::star::awt::Size& _hatchbordersize ) throw (::com::sun::star::uno::RuntimeException)
{
    if ( pHatchWindow )
    {
        aHatchBorderSize = _hatchbordersize;
        pHatchWindow->SetHatchBorderPixel( Size( aHatchBorderSize.Width, aHatchBorderSize.Height ) );
    }
}

void SAL_CALL VCLXHatchWindow::setController( const uno::Reference< embed::XHatchWindowController >& xController )
    throw (uno::RuntimeException)
{
    m_xController = xController;
}

void SAL_CALL VCLXHatchWindow::dispose()
    throw (uno::RuntimeException)
{
    pHatchWindow = 0;
    VCLXWindow::dispose();
}

void SAL_CALL VCLXHatchWindow::addEventListener( const uno::Reference< lang::XEventListener >& xListener )
    throw (uno::RuntimeException)
{
    VCLXWindow::addEventListener( xListener );
}

void SAL_CALL VCLXHatchWindow::removeEventListener( const uno::Reference< lang::XEventListener >& xListener )
    throw (uno::RuntimeException)
{
    VCLXWindow::removeEventListener( xListener );
}

void VCLXHatchWindow::Activated()
{
    if ( m_xController.is() )
        m_xController->activated();
}

void VCLXHatchWindow::Deactivated()
{
    if ( m_xController.is() )
        m_xController->deactivated();
}
<|endoftext|>


<commit_before><commit_msg>Revert "skip SkipImages unit test on MacOs"<commit_after><|endoftext|>


<commit_before><commit_msg>[AMDGPU] Initialize accumulator register in waterfall code<commit_after><|endoftext|>


<commit_before>/****************************************************************************
**
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the QtQml module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia.  For licensing terms and
** conditions see http://qt.digia.com/licensing.  For further information
** use the contact form at http://qt.digia.com/contact-us.
**
** 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, Digia gives you certain additional
** rights.  These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3.0 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU General Public License version 3.0 requirements will be
** met: http://www.gnu.org/copyleft/gpl.html.
**
**
** $QT_END_LICENSE$
**
****************************************************************************/

#include "qquickqfiledialog_p.h"
#include "qquickitem.h"

#include <private/qguiapplication_p.h>
#include <private/qqmlcontext_p.h>
#include <QWindow>
#include <QQuickWindow>
#include <QFileDialog>

QT_BEGIN_NAMESPACE

/*!
    \qmltype QtFileDialog
    \instantiates QQuickQFileDialog
    \inqmlmodule QtQuick.PrivateWidgets 1
    \ingroup qtquick-visual
    \brief Dialog component for choosing files from a local filesystem.
    \since 5.1
    \internal

    QtFileDialog provides a means to instantiate and manage a QFileDialog.
    It is not recommended to be used directly; it is an implementation
    detail of \l FileDialog in the \l QtQuick.Dialogs module.

    To use this type, you will need to import the module with the following line:
    \code
    import QtQuick.PrivateWidgets 1.0
    \endcode
*/

/*!
    \qmlsignal QtQuick::Dialogs::FileDialog::accepted

    The \a accepted signal is emitted when the user has finished using the
    dialog. You can then inspect the \a fileUrl or \a fileUrls properties to
    get the selection.

    Example:

    \qml
    FileDialog {
        onAccepted: { console.log("Selected file: " + fileUrl) }
    }
    \endqml
*/

/*!
    \qmlsignal QtQuick::Dialogs::FileDialog::rejected

    The \a rejected signal is emitted when the user has dismissed the dialog,
    either by closing the dialog window or by pressing the Cancel button.
*/

/*!
    \class QQuickQFileDialog
    \inmodule QtQuick.PrivateWidgets
    \internal

    \brief The QQuickQFileDialog class is a wrapper for a QFileDialog.

    \since 5.1
*/

/*!
    Constructs a file dialog with parent window \a parent.
*/
QQuickQFileDialog::QQuickQFileDialog(QObject *parent)
    : QQuickAbstractFileDialog(parent)
{
}

/*!
    Destroys the file dialog.
*/
QQuickQFileDialog::~QQuickQFileDialog()
{
    if (m_dlgHelper)
        m_dlgHelper->hide();
    delete m_dlgHelper;
}

QPlatformFileDialogHelper *QQuickQFileDialog::helper()
{
    QQuickItem *parentItem = qobject_cast<QQuickItem *>(parent());
    if (parentItem)
        m_parentWindow = parentItem->window();

    if (!m_dlgHelper) {
        m_dlgHelper = new QFileDialogHelper();
        connect(m_dlgHelper, SIGNAL(directoryEntered(const QUrl &)), this, SIGNAL(folderChanged()));
        connect(m_dlgHelper, SIGNAL(filterSelected(const QString &)), this, SIGNAL(filterSelected()));
        connect(m_dlgHelper, SIGNAL(accept()), this, SLOT(accept()));
        connect(m_dlgHelper, SIGNAL(reject()), this, SLOT(reject()));
    }

    return m_dlgHelper;
}

QFileDialogHelper::QFileDialogHelper() :
    QPlatformFileDialogHelper()
{
    connect(&m_dialog, SIGNAL(currentChanged(const QString&)), this, SLOT(currentChanged(const QString&)));
    connect(&m_dialog, SIGNAL(directoryEntered(const QString&)), this, SLOT(directoryEntered(const QString&)));
    connect(&m_dialog, SIGNAL(fileSelected(const QString&)), this, SLOT(fileSelected(const QString&)));
    connect(&m_dialog, SIGNAL(filesSelected(const QStringList&)), this, SLOT(filesSelected(const QStringList&)));
    connect(&m_dialog, SIGNAL(filterSelected(const QString&)), this, SIGNAL(filterSelected(const QString&)));
    connect(&m_dialog, SIGNAL(accepted()), this, SIGNAL(accept()));
    connect(&m_dialog, SIGNAL(rejected()), this, SIGNAL(reject()));
}

QList<QUrl> QFileDialogHelper::selectedFiles() const
{
    return m_dialog.selectedUrls();
}

void QFileDialogHelper::setFilter() {
    m_dialog.setWindowTitle(QPlatformFileDialogHelper::options()->windowTitle());
    if (QPlatformFileDialogHelper::options()->isLabelExplicitlySet(QFileDialogOptions::LookIn))
        m_dialog.setLabelText(m_dialog.LookIn, QPlatformFileDialogHelper::options()->labelText(QFileDialogOptions::LookIn));
    if (QPlatformFileDialogHelper::options()->isLabelExplicitlySet(QFileDialogOptions::FileName))
        m_dialog.setLabelText(m_dialog.FileName, QPlatformFileDialogHelper::options()->labelText(QFileDialogOptions::FileName));
    if (QPlatformFileDialogHelper::options()->isLabelExplicitlySet(QFileDialogOptions::FileType))
        m_dialog.setLabelText(m_dialog.FileType, QPlatformFileDialogHelper::options()->labelText(QFileDialogOptions::FileType));
    if (QPlatformFileDialogHelper::options()->isLabelExplicitlySet(QFileDialogOptions::Accept))
        m_dialog.setLabelText(m_dialog.Accept, QPlatformFileDialogHelper::options()->labelText(QFileDialogOptions::Accept));
    if (QPlatformFileDialogHelper::options()->isLabelExplicitlySet(QFileDialogOptions::Reject))
        m_dialog.setLabelText(m_dialog.Reject, QPlatformFileDialogHelper::options()->labelText(QFileDialogOptions::Reject));
    m_dialog.setFilter(QPlatformFileDialogHelper::options()->filter());
    m_dialog.setNameFilters(QPlatformFileDialogHelper::options()->nameFilters());
    m_dialog.selectNameFilter(QPlatformFileDialogHelper::options()->initiallySelectedNameFilter());
    m_dialog.setFileMode(QFileDialog::FileMode(QPlatformFileDialogHelper::options()->fileMode()));
    m_dialog.setOptions((QFileDialog::Options)((int)(QPlatformFileDialogHelper::options()->options())));
    m_dialog.setAcceptMode(QFileDialog::AcceptMode(QPlatformFileDialogHelper::options()->acceptMode()));
}

bool QFileDialogHelper::show(Qt::WindowFlags f, Qt::WindowModality m, QWindow *parent) {
    m_dialog.winId();
    QWindow *window = m_dialog.windowHandle();
    Q_ASSERT(window);
    window->setTransientParent(parent);
    window->setFlags(f);
    m_dialog.setWindowModality(m);
    m_dialog.show();
    return m_dialog.isVisible();
}

void QFileDialogHelper::currentChanged(const QString& path)
{
    emit QPlatformFileDialogHelper::currentChanged(QUrl::fromLocalFile(path));
}

void QFileDialogHelper::directoryEntered(const QString& path)
{
    emit QPlatformFileDialogHelper::directoryEntered(QUrl::fromLocalFile(path));
}

void QFileDialogHelper::fileSelected(const QString& path)
{
    emit QPlatformFileDialogHelper::fileSelected(QUrl::fromLocalFile(path));
}

void QFileDialogHelper::filesSelected(const QStringList& paths)
{
    QList<QUrl> pathUrls;
    foreach (const QString &path, paths)
        pathUrls << QUrl::fromLocalFile(path);
    emit QPlatformFileDialogHelper::filesSelected(pathUrls);
}

QT_END_NAMESPACE
<commit_msg>Fix usage of FileDialog.folder property in QtQuick<commit_after>/****************************************************************************
**
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the QtQml module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia.  For licensing terms and
** conditions see http://qt.digia.com/licensing.  For further information
** use the contact form at http://qt.digia.com/contact-us.
**
** 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, Digia gives you certain additional
** rights.  These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3.0 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU General Public License version 3.0 requirements will be
** met: http://www.gnu.org/copyleft/gpl.html.
**
**
** $QT_END_LICENSE$
**
****************************************************************************/

#include "qquickqfiledialog_p.h"
#include "qquickitem.h"

#include <private/qguiapplication_p.h>
#include <private/qqmlcontext_p.h>
#include <QWindow>
#include <QQuickWindow>
#include <QFileDialog>

QT_BEGIN_NAMESPACE

/*!
    \qmltype QtFileDialog
    \instantiates QQuickQFileDialog
    \inqmlmodule QtQuick.PrivateWidgets 1
    \ingroup qtquick-visual
    \brief Dialog component for choosing files from a local filesystem.
    \since 5.1
    \internal

    QtFileDialog provides a means to instantiate and manage a QFileDialog.
    It is not recommended to be used directly; it is an implementation
    detail of \l FileDialog in the \l QtQuick.Dialogs module.

    To use this type, you will need to import the module with the following line:
    \code
    import QtQuick.PrivateWidgets 1.0
    \endcode
*/

/*!
    \qmlsignal QtQuick::Dialogs::FileDialog::accepted

    The \a accepted signal is emitted when the user has finished using the
    dialog. You can then inspect the \a fileUrl or \a fileUrls properties to
    get the selection.

    Example:

    \qml
    FileDialog {
        onAccepted: { console.log("Selected file: " + fileUrl) }
    }
    \endqml
*/

/*!
    \qmlsignal QtQuick::Dialogs::FileDialog::rejected

    The \a rejected signal is emitted when the user has dismissed the dialog,
    either by closing the dialog window or by pressing the Cancel button.
*/

/*!
    \class QQuickQFileDialog
    \inmodule QtQuick.PrivateWidgets
    \internal

    \brief The QQuickQFileDialog class is a wrapper for a QFileDialog.

    \since 5.1
*/

/*!
    Constructs a file dialog with parent window \a parent.
*/
QQuickQFileDialog::QQuickQFileDialog(QObject *parent)
    : QQuickAbstractFileDialog(parent)
{
}

/*!
    Destroys the file dialog.
*/
QQuickQFileDialog::~QQuickQFileDialog()
{
    if (m_dlgHelper)
        m_dlgHelper->hide();
    delete m_dlgHelper;
}

QPlatformFileDialogHelper *QQuickQFileDialog::helper()
{
    QQuickItem *parentItem = qobject_cast<QQuickItem *>(parent());
    if (parentItem)
        m_parentWindow = parentItem->window();

    if (!m_dlgHelper) {
        m_dlgHelper = new QFileDialogHelper();
        connect(m_dlgHelper, SIGNAL(directoryEntered(const QUrl &)), this, SIGNAL(folderChanged()));
        connect(m_dlgHelper, SIGNAL(filterSelected(const QString &)), this, SIGNAL(filterSelected()));
        connect(m_dlgHelper, SIGNAL(accept()), this, SLOT(accept()));
        connect(m_dlgHelper, SIGNAL(reject()), this, SLOT(reject()));
    }

    return m_dlgHelper;
}

QFileDialogHelper::QFileDialogHelper() :
    QPlatformFileDialogHelper()
{
    connect(&m_dialog, SIGNAL(currentChanged(const QString&)), this, SLOT(currentChanged(const QString&)));
    connect(&m_dialog, SIGNAL(directoryEntered(const QString&)), this, SLOT(directoryEntered(const QString&)));
    connect(&m_dialog, SIGNAL(fileSelected(const QString&)), this, SLOT(fileSelected(const QString&)));
    connect(&m_dialog, SIGNAL(filesSelected(const QStringList&)), this, SLOT(filesSelected(const QStringList&)));
    connect(&m_dialog, SIGNAL(filterSelected(const QString&)), this, SIGNAL(filterSelected(const QString&)));
    connect(&m_dialog, SIGNAL(accepted()), this, SIGNAL(accept()));
    connect(&m_dialog, SIGNAL(rejected()), this, SIGNAL(reject()));
}

QList<QUrl> QFileDialogHelper::selectedFiles() const
{
    return m_dialog.selectedUrls();
}

void QFileDialogHelper::setFilter() {
    m_dialog.setWindowTitle(QPlatformFileDialogHelper::options()->windowTitle());
    if (QPlatformFileDialogHelper::options()->isLabelExplicitlySet(QFileDialogOptions::LookIn))
        m_dialog.setLabelText(m_dialog.LookIn, QPlatformFileDialogHelper::options()->labelText(QFileDialogOptions::LookIn));
    if (QPlatformFileDialogHelper::options()->isLabelExplicitlySet(QFileDialogOptions::FileName))
        m_dialog.setLabelText(m_dialog.FileName, QPlatformFileDialogHelper::options()->labelText(QFileDialogOptions::FileName));
    if (QPlatformFileDialogHelper::options()->isLabelExplicitlySet(QFileDialogOptions::FileType))
        m_dialog.setLabelText(m_dialog.FileType, QPlatformFileDialogHelper::options()->labelText(QFileDialogOptions::FileType));
    if (QPlatformFileDialogHelper::options()->isLabelExplicitlySet(QFileDialogOptions::Accept))
        m_dialog.setLabelText(m_dialog.Accept, QPlatformFileDialogHelper::options()->labelText(QFileDialogOptions::Accept));
    if (QPlatformFileDialogHelper::options()->isLabelExplicitlySet(QFileDialogOptions::Reject))
        m_dialog.setLabelText(m_dialog.Reject, QPlatformFileDialogHelper::options()->labelText(QFileDialogOptions::Reject));
    m_dialog.setFilter(QPlatformFileDialogHelper::options()->filter());
    m_dialog.setNameFilters(QPlatformFileDialogHelper::options()->nameFilters());
    m_dialog.selectNameFilter(QPlatformFileDialogHelper::options()->initiallySelectedNameFilter());
    m_dialog.setFileMode(QFileDialog::FileMode(QPlatformFileDialogHelper::options()->fileMode()));
    m_dialog.setOptions((QFileDialog::Options)((int)(QPlatformFileDialogHelper::options()->options())));
    m_dialog.setAcceptMode(QFileDialog::AcceptMode(QPlatformFileDialogHelper::options()->acceptMode()));

    const QUrl initialDirectory = QPlatformFileDialogHelper::options()->initialDirectory();
    if (initialDirectory.isValid() && initialDirectory.isLocalFile())
        m_dialog.setDirectory(initialDirectory.toLocalFile());
}

bool QFileDialogHelper::show(Qt::WindowFlags f, Qt::WindowModality m, QWindow *parent) {
    m_dialog.winId();
    QWindow *window = m_dialog.windowHandle();
    Q_ASSERT(window);
    window->setTransientParent(parent);
    window->setFlags(f);
    m_dialog.setWindowModality(m);
    m_dialog.show();
    return m_dialog.isVisible();
}

void QFileDialogHelper::currentChanged(const QString& path)
{
    emit QPlatformFileDialogHelper::currentChanged(QUrl::fromLocalFile(path));
}

void QFileDialogHelper::directoryEntered(const QString& path)
{
    emit QPlatformFileDialogHelper::directoryEntered(QUrl::fromLocalFile(path));
}

void QFileDialogHelper::fileSelected(const QString& path)
{
    emit QPlatformFileDialogHelper::fileSelected(QUrl::fromLocalFile(path));
}

void QFileDialogHelper::filesSelected(const QStringList& paths)
{
    QList<QUrl> pathUrls;
    foreach (const QString &path, paths)
        pathUrls << QUrl::fromLocalFile(path);
    emit QPlatformFileDialogHelper::filesSelected(pathUrls);
}

QT_END_NAMESPACE
<|endoftext|>


<commit_before>#include <cstring>
#include <iostream>
#include <iomanip>
#include <vector>
#include <utility>
#include <sstream>
#include <stdexcept>
#include <cmath>

#include "smf.hpp"
#include "parseutils.hpp"

namespace MgCore
{
    uint32_t SmfReader::readVarLen()
    {
        uint8_t c = MgCore::read_type<uint8_t>(m_smfFile);
        uint32_t value = c & 0x7F;

        if (c & 0x80) {

            do {
                c = MgCore::read_type<uint8_t>(m_smfFile);
                value = (value << 7) + (c & 0x7F);

            } while (c & 0x80);

        }
        return value;
    }

    void SmfReader::readMidiEvent(SmfEventInfo &event)
    {

        MidiEvent midiEvent;
        midiEvent.info = event;
        midiEvent.message = event.status & 0xF0;
        midiEvent.channel = event.status & 0xF;
        midiEvent.data1 = MgCore::read_type<uint8_t>(m_smfFile);
        midiEvent.data2 = MgCore::read_type<uint8_t>(m_smfFile);

        m_currentTrack->midiEvents.push_back(midiEvent);
    }

    void SmfReader::readMetaEvent(SmfEventInfo &event)
    {
        event.type = static_cast<MidiMetaEvent>(MgCore::read_type<uint8_t>(m_smfFile));
        uint32_t length = readVarLen();

        // In the cases where we dont implement an event type log it, and its data.
        switch(event.type)
        {
            case meta_SequenceNumber:
            {
                auto sequenceNumber = MgCore::read_type<uint16_t>(m_smfFile);
                m_logger->trace("Sequence Number {}", sequenceNumber);
                break;
            }
            case meta_Text:
            case meta_Copyright:
            case meta_InstrumentName:
            case meta_Lyrics:
            case meta_Marker:
            case meta_CuePoint:
            // RP-019 - SMF Device Name and Program Name Meta Events
            case meta_ProgramName:
            case meta_DeviceName:
            // The midi spec says the following text events exist and act the same as meta_Text.
            case meta_TextReserved3:
            case meta_TextReserved4:
            case meta_TextReserved5:
            case meta_TextReserved6:
            case meta_TextReserved7:
            case meta_TextReserved8:
            {
                auto textData = std::make_unique<char[]>(length+1);
                textData[length] = '\0';
                MgCore::read_type<char>(m_smfFile, textData.get(), length);
                TextEvent text {event, textData.get()};
                break;
            }
            case meta_TrackName:
            {
                auto textData = std::make_unique<char[]>(length+1);
                textData[length] = '\0';

                MgCore::read_type<char>(m_smfFile, textData.get(), length);
                m_currentTrack->name = std::string(textData.get());
                break;
            }
            case meta_MIDIChannelPrefix: {
                auto midiChannel = MgCore::read_type<uint8_t>(m_smfFile);
                m_logger->trace("Midi Channel {}", midiChannel);
                break;
            }
            case meta_EndOfTrack:
            {
                // TODO - We might be able to use this for some purpose.
                m_logger->trace("End of Track {}", m_currentTrack->name);
                break;
            }
            case meta_Tempo:
            {
                uint32_t qnLength = read_type<uint32_t>(m_smfFile, 3);
                double ppqn = qnLength/static_cast<double>(m_header.division);
                m_currentTrack->tempo.push_back({event, qnLength, ppqn});
                break;
            }
            case meta_TimeSignature:  // TODO - Implement this...
            {
                TimeSignatureEvent tsEvent;
                tsEvent.numerator = MgCore::read_type<uint8_t>(m_smfFile); // 4 default
                tsEvent.denominator = std::pow(2, MgCore::read_type<uint8_t>(m_smfFile)); // 4 default

                tsEvent.ticksPerBeat = MgCore::read_type<uint8_t>(m_smfFile); // Standard is 24

                // The number of 1/32nd notes per quarter note
                tsEvent.thirtySecondPQN = MgCore::read_type<uint8_t>(m_smfFile); // 8 default

                m_logger->trace("Time signature  {}/{} CPC: {} TSPQN: {}",
                                    tsEvent.numerator,
                                    tsEvent.denominator,
                                    tsEvent.ticksPerBeat,
                                    tsEvent.thirtySecondPQN);

                m_currentTrack->timeSigEvents.push_back(tsEvent);

                break;
            }
            // These are mainly here to just represent them existing :P
            case meta_MIDIPort:  // obsolete no longer used.
            case meta_SMPTEOffset: // Not currently implemented, maybe someday.
            case meta_KeySignature: // Not very useful for us
            case meta_XMFPatchType: // probably not used
            case meta_SequencerSpecific:
            default:
            {
                m_smfFile.seekg(length, std::ios::cur);
                break;
            }
        }
    }

    void SmfReader::readSysExEvent(SmfEventInfo &event)
    {
        auto length = readVarLen();
        m_logger->info("sysex even at position {}", m_smfFile.tellg());
        m_smfFile.seekg(length, std::ios::cur);
    }

    double SmfReader::conv_abstime(uint32_t deltaPulses)
    {
        return deltaPulses * (m_currentTempoEvent->ppqn / 1000000.0);
    }

    void SmfReader::readEvents(int chunkEnd)
    {
        uint32_t pulseTime = 0;
        uint8_t prevStatus = 0;
        double currentRunningTimeSec = 0;

        while (m_smfFile.tellg() < chunkEnd)
        {
            SmfEventInfo event;

            event.deltaPulses = readVarLen();

            pulseTime += event.deltaPulses;

            event.pulseTime = pulseTime;

            if (pulseTime == 0) {
                event.absTime = 0.0;
            } else {
                event.absTime = conv_abstime(pulseTime);
            }

            auto status = MgCore::peek_type<uint8_t>(m_smfFile);

            if (status == status_MetaEvent) {
                prevStatus = 0; // reset running status
                event.status = MgCore::read_type<uint8_t>(m_smfFile);
                readMetaEvent(event);
            } else if (status == status_SysexEvent || status == status_SysexEvent2) {
                prevStatus = 0;  // reset running status
                event.status = MgCore::read_type<uint8_t>(m_smfFile);
                readSysExEvent(event);
            } else {
                if ((status & 0xF0) >= 0x80) {
                    event.status = MgCore::read_type<uint8_t>(m_smfFile);
                } else {
                    event.status = prevStatus;
                }
                readMidiEvent(event);
                prevStatus = event.status;
            }

            if (pulseTime != 0 && m_tempoTrack->tempo.size() == 0) {

                m_logger->info("No tempo change at deltatime 0 setting default of 120 BPM.");

                // We construct a new tempo event that will have a default
                // equivelent to 120 BPM the same thing will need to be done
                // for the time signature meta event.
                SmfEventInfo tempoEvent;
                tempoEvent.deltaPulses = 0;
                tempoEvent.type = meta_Tempo;
                tempoEvent.pulseTime = 0;
                tempoEvent.absTime = 0.0;

                m_tempoTrack->tempo.push_back({tempoEvent, 500000}); // last value is ppqn
            }

            if (pulseTime != 0 && m_tempoTrack->timeSigEvents.size() == 0) {

                m_logger->info("No time signature change at deltatime 0 setting default of 4/4.");

                TimeSignatureEvent tsEvent;
                tsEvent.numerator = 4;
                tsEvent.denominator = 4;
                tsEvent.ticksPerBeat = 24;
                tsEvent.thirtySecondPQN = 8;

                m_tempoTrack->timeSigEvents.push_back(tsEvent);
            }
            if (pulseTime != 0 || m_tempoTrack->tempo.size() != 0) {
                m_currentTempoEvent = getLastTempoIdViaPulses(pulseTime);
                currentRunningTimeSec += event.absTime;
            }
        }
        m_currentTrack->seconds = static_cast<float>(currentRunningTimeSec);
    }

    void SmfReader::readFile()
    {
        // seek to the end in order to get the fileSize.
        m_smfFile.seekg(0, std::ios::end);
        int fileEnd = static_cast<int>(m_smfFile.tellg());

        // Now we go back to the beginning and begin reading the file
        m_smfFile.seekg(0, std::ios::beg);

        int fileStart = static_cast<int>(m_smfFile.tellg());
        int filePos = fileStart;
        int fileRemaining = fileEnd;

        SmfChunkInfo chunk;

        // set the intial chunk starting position at the beginning of the file.
        int chunkStart = fileStart;

        // The chunk end will be calculated after a chunk is loaded.
        int chunkEnd = 0;

        int trackChunkCount = 0;

        // We could loop through the number of track chunks given in the header.
        // However if there are any unknown chunk types inside the midi file
        // this will likely break. So we just loop until we hit the end of the
        // file instead...
        while (filePos < fileEnd)
        {

            MgCore::read_type<char>(m_smfFile, chunk.chunkType, 4);
            chunk.length = MgCore::read_type<uint32_t>(m_smfFile);
            chunkEnd = chunkStart + (8 + chunk.length); // 8 is the length of the type + length fields

            // MThd chunk is only in the beginning of the file.
            if (chunkStart == fileStart && strcmp(chunk.chunkType, "MThd") == 0) {
                // Load header chunk
                m_header.info = chunk;
                m_header.format = MgCore::read_type<uint16_t>(m_smfFile);
                m_header.trackNum = MgCore::read_type<uint16_t>(m_smfFile);
                m_header.division = MgCore::read_type<int16_t>(m_smfFile);

                // Make sure we reserve enough space for m_tracks just in-case.
                m_tracks.reserve(sizeof(SmfTrack) * m_header.trackNum);

                if (m_header.format == smfType0 && m_header.trackNum != 1) {
                    throw std::runtime_error("Not a valid type 0 midi.");
                }

                // TODO - For completionist reasons eventually add support for this.
                if ((m_header.division & 0x8000) != 0) {
                    throw std::runtime_error("SMPTE time division not supported");
                }

            } else if (strcmp(chunk.chunkType, "MTrk") == 0) {
                trackChunkCount += 1;
                m_tracks.emplace_back();
                m_currentTrack = &m_tracks.back();

                // Make sure that for midi type 0 and type 2 the tempoTrack is
                // changing with m_currentTrack.
                if (m_header.format != smfType1 || trackChunkCount == 1) {
                    m_tempoTrack = m_currentTrack;
                }

                readEvents(chunkEnd);

            } else {
                m_logger->warn("Non-standard chunk of type {} detected, skipping.", chunk.chunkType);
            }

            filePos = chunkEnd;
            chunkStart = filePos;

            // Make sure that we are in the correct location in the chunk
            // If not seek to the correct location and output an error in the log.
            if (static_cast<int>(m_smfFile.tellg()) != filePos) {
                m_logger->warn("Offset for chunk '{}' incorrect, seeking to correct location.", chunk.chunkType);
                m_smfFile.seekg(filePos);
            }
            fileRemaining = (fileEnd-filePos);
            if (fileRemaining != 0 && fileRemaining <= 8) {
                m_logger->warn("To few bytes remaining in midi for another track, this is likely a bug.");
            }
        }
        if (trackChunkCount != m_header.trackNum) {
            m_logger->warn("Track chunk count does not match header.");
        }
        m_logger->info("End of MIDI reached.");

    }

    SmfReader::SmfReader(std::string filename)
    {
        m_logger = spdlog::get("default");
        m_logger->info("Loading MIDI");

        std::ifstream smfFile(filename, std::ios_base::binary);

        if (smfFile) {
            m_smfFile << smfFile.rdbuf();
            smfFile.close();
        } else {
            throw std::runtime_error("Failed to load MIDI file.");
        }

        readFile();
        // Release midifile data after we are finished reading.
        m_smfFile.str( std::string() );
        m_smfFile.clear();
    }

    TempoEvent* SmfReader::getLastTempoIdViaPulses(uint32_t pulseTime)
    {
        static unsigned int value = 0;
        SmfTrack &tempoTrack = m_tracks.front();
        std::vector<TempoEvent> &tempos = tempoTrack.tempo;

        static uint32_t lastPulseTime = 0;

        // Ignore the cached last tempo value if the new pulse time is older.
        if (lastPulseTime > pulseTime) {
            //m_logger->trace("Reset tempo id from: {}", value);
            value = 0;
        }

        for (unsigned int i = 0; i < tempos.size(); i++) {
            // Restore tempo to previous value
            if (i < value) {
                //m_logger->trace("Restored tempo id to: {}", value);
                i = value;
            }
            if (tempos[i].info.pulseTime >=pulseTime) {
                value = i;
                lastPulseTime = pulseTime;
                return &tempos[i];
            }
        }
        // return last value if nothing else is found
        return &tempos.back();

    }

    std::vector<SmfTrack*> SmfReader::getTracks()
    {
        std::vector<SmfTrack*> tracks;

        for (auto &track : m_tracks) {
            tracks.push_back(&track);
        }
        return tracks;
    }
}
<commit_msg>Change teh way the file is loaded into the stringstream.<commit_after>#include <cstring>
#include <iostream>
#include <iomanip>
#include <vector>
#include <utility>
#include <sstream>
#include <stdexcept>
#include <cmath>

#include "smf.hpp"
#include "parseutils.hpp"

namespace MgCore
{
    uint32_t SmfReader::readVarLen()
    {
        uint8_t c = MgCore::read_type<uint8_t>(m_smfFile);
        uint32_t value = c & 0x7F;

        if (c & 0x80) {

            do {
                c = MgCore::read_type<uint8_t>(m_smfFile);
                value = (value << 7) + (c & 0x7F);

            } while (c & 0x80);

        }
        return value;
    }

    void SmfReader::readMidiEvent(SmfEventInfo &event)
    {

        MidiEvent midiEvent;
        midiEvent.info = event;
        midiEvent.message = event.status & 0xF0;
        midiEvent.channel = event.status & 0xF;
        midiEvent.data1 = MgCore::read_type<uint8_t>(m_smfFile);
        midiEvent.data2 = MgCore::read_type<uint8_t>(m_smfFile);

        m_currentTrack->midiEvents.push_back(midiEvent);
    }

    void SmfReader::readMetaEvent(SmfEventInfo &event)
    {
        event.type = static_cast<MidiMetaEvent>(MgCore::read_type<uint8_t>(m_smfFile));
        uint32_t length = readVarLen();

        // In the cases where we dont implement an event type log it, and its data.
        switch(event.type)
        {
            case meta_SequenceNumber:
            {
                auto sequenceNumber = MgCore::read_type<uint16_t>(m_smfFile);
                m_logger->trace("Sequence Number {}", sequenceNumber);
                break;
            }
            case meta_Text:
            case meta_Copyright:
            case meta_InstrumentName:
            case meta_Lyrics:
            case meta_Marker:
            case meta_CuePoint:
            // RP-019 - SMF Device Name and Program Name Meta Events
            case meta_ProgramName:
            case meta_DeviceName:
            // The midi spec says the following text events exist and act the same as meta_Text.
            case meta_TextReserved3:
            case meta_TextReserved4:
            case meta_TextReserved5:
            case meta_TextReserved6:
            case meta_TextReserved7:
            case meta_TextReserved8:
            {
                auto textData = std::make_unique<char[]>(length+1);
                textData[length] = '\0';
                MgCore::read_type<char>(m_smfFile, textData.get(), length);
                TextEvent text {event, textData.get()};
                break;
            }
            case meta_TrackName:
            {
                auto textData = std::make_unique<char[]>(length+1);
                textData[length] = '\0';

                MgCore::read_type<char>(m_smfFile, textData.get(), length);
                m_currentTrack->name = std::string(textData.get());
                break;
            }
            case meta_MIDIChannelPrefix: {
                auto midiChannel = MgCore::read_type<uint8_t>(m_smfFile);
                m_logger->trace("Midi Channel {}", midiChannel);
                break;
            }
            case meta_EndOfTrack:
            {
                // TODO - We might be able to use this for some purpose.
                m_logger->trace("End of Track {}", m_currentTrack->name);
                break;
            }
            case meta_Tempo:
            {
                uint32_t qnLength = read_type<uint32_t>(m_smfFile, 3);
                double ppqn = qnLength/static_cast<double>(m_header.division);
                m_currentTrack->tempo.push_back({event, qnLength, ppqn});
                break;
            }
            case meta_TimeSignature:  // TODO - Implement this...
            {
                TimeSignatureEvent tsEvent;
                tsEvent.numerator = MgCore::read_type<uint8_t>(m_smfFile); // 4 default
                tsEvent.denominator = std::pow(2, MgCore::read_type<uint8_t>(m_smfFile)); // 4 default

                tsEvent.ticksPerBeat = MgCore::read_type<uint8_t>(m_smfFile); // Standard is 24

                // The number of 1/32nd notes per quarter note
                tsEvent.thirtySecondPQN = MgCore::read_type<uint8_t>(m_smfFile); // 8 default

                m_logger->trace("Time signature  {}/{} CPC: {} TSPQN: {}",
                                    tsEvent.numerator,
                                    tsEvent.denominator,
                                    tsEvent.ticksPerBeat,
                                    tsEvent.thirtySecondPQN);

                m_currentTrack->timeSigEvents.push_back(tsEvent);

                break;
            }
            // These are mainly here to just represent them existing :P
            case meta_MIDIPort:  // obsolete no longer used.
            case meta_SMPTEOffset: // Not currently implemented, maybe someday.
            case meta_KeySignature: // Not very useful for us
            case meta_XMFPatchType: // probably not used
            case meta_SequencerSpecific:
            default:
            {
                m_smfFile.seekg(length, std::ios::cur);
                break;
            }
        }
    }

    void SmfReader::readSysExEvent(SmfEventInfo &event)
    {
        auto length = readVarLen();
        m_logger->info("sysex even at position {}", m_smfFile.tellg());
        m_smfFile.seekg(length, std::ios::cur);
    }

    double SmfReader::conv_abstime(uint32_t deltaPulses)
    {
        return deltaPulses * (m_currentTempoEvent->ppqn / 1000000.0);
    }

    void SmfReader::readEvents(int chunkEnd)
    {
        uint32_t pulseTime = 0;
        uint8_t prevStatus = 0;
        double currentRunningTimeSec = 0;

        while (m_smfFile.tellg() < chunkEnd)
        {
            SmfEventInfo event;

            event.deltaPulses = readVarLen();

            pulseTime += event.deltaPulses;

            event.pulseTime = pulseTime;

            if (pulseTime == 0) {
                event.absTime = 0.0;
            } else {
                event.absTime = conv_abstime(pulseTime);
            }

            auto status = MgCore::peek_type<uint8_t>(m_smfFile);

            if (status == status_MetaEvent) {
                prevStatus = 0; // reset running status
                event.status = MgCore::read_type<uint8_t>(m_smfFile);
                readMetaEvent(event);
            } else if (status == status_SysexEvent || status == status_SysexEvent2) {
                prevStatus = 0;  // reset running status
                event.status = MgCore::read_type<uint8_t>(m_smfFile);
                readSysExEvent(event);
            } else {
                if ((status & 0xF0) >= 0x80) {
                    event.status = MgCore::read_type<uint8_t>(m_smfFile);
                } else {
                    event.status = prevStatus;
                }
                readMidiEvent(event);
                prevStatus = event.status;
            }

            if (pulseTime != 0 && m_tempoTrack->tempo.size() == 0) {

                m_logger->info("No tempo change at deltatime 0 setting default of 120 BPM.");

                // We construct a new tempo event that will have a default
                // equivelent to 120 BPM the same thing will need to be done
                // for the time signature meta event.
                SmfEventInfo tempoEvent;
                tempoEvent.deltaPulses = 0;
                tempoEvent.type = meta_Tempo;
                tempoEvent.pulseTime = 0;
                tempoEvent.absTime = 0.0;

                m_tempoTrack->tempo.push_back({tempoEvent, 500000}); // last value is ppqn
            }

            if (pulseTime != 0 && m_tempoTrack->timeSigEvents.size() == 0) {

                m_logger->info("No time signature change at deltatime 0 setting default of 4/4.");

                TimeSignatureEvent tsEvent;
                tsEvent.numerator = 4;
                tsEvent.denominator = 4;
                tsEvent.ticksPerBeat = 24;
                tsEvent.thirtySecondPQN = 8;

                m_tempoTrack->timeSigEvents.push_back(tsEvent);
            }
            if (pulseTime != 0 || m_tempoTrack->tempo.size() != 0) {
                m_currentTempoEvent = getLastTempoIdViaPulses(pulseTime);
                currentRunningTimeSec += event.absTime;
            }
        }
        m_currentTrack->seconds = static_cast<float>(currentRunningTimeSec);
    }

    void SmfReader::readFile()
    {
        // seek to the end in order to get the fileSize.
        m_smfFile.seekg(0, std::ios::end);
        int fileEnd = static_cast<int>(m_smfFile.tellg());

        // Now we go back to the beginning and begin reading the file
        m_smfFile.seekg(0, std::ios::beg);

        int fileStart = static_cast<int>(m_smfFile.tellg());
        int filePos = fileStart;
        int fileRemaining = fileEnd;

        SmfChunkInfo chunk;

        // set the intial chunk starting position at the beginning of the file.
        int chunkStart = fileStart;

        // The chunk end will be calculated after a chunk is loaded.
        int chunkEnd = 0;

        int trackChunkCount = 0;

        // We could loop through the number of track chunks given in the header.
        // However if there are any unknown chunk types inside the midi file
        // this will likely break. So we just loop until we hit the end of the
        // file instead...
        while (filePos < fileEnd)
        {

            MgCore::read_type<char>(m_smfFile, chunk.chunkType, 4);
            chunk.length = MgCore::read_type<uint32_t>(m_smfFile);
            chunkEnd = chunkStart + (8 + chunk.length); // 8 is the length of the type + length fields

            // MThd chunk is only in the beginning of the file.
            if (chunkStart == fileStart && strcmp(chunk.chunkType, "MThd") == 0) {
                // Load header chunk
                m_header.info = chunk;
                m_header.format = MgCore::read_type<uint16_t>(m_smfFile);
                m_header.trackNum = MgCore::read_type<uint16_t>(m_smfFile);
                m_header.division = MgCore::read_type<int16_t>(m_smfFile);

                // Make sure we reserve enough space for m_tracks just in-case.
                m_tracks.reserve(sizeof(SmfTrack) * m_header.trackNum);

                if (m_header.format == smfType0 && m_header.trackNum != 1) {
                    throw std::runtime_error("Not a valid type 0 midi.");
                }

                // TODO - For completionist reasons eventually add support for this.
                if ((m_header.division & 0x8000) != 0) {
                    throw std::runtime_error("SMPTE time division not supported");
                }

            } else if (strcmp(chunk.chunkType, "MTrk") == 0) {
                trackChunkCount += 1;
                m_tracks.emplace_back();
                m_currentTrack = &m_tracks.back();

                // Make sure that for midi type 0 and type 2 the tempoTrack is
                // changing with m_currentTrack.
                if (m_header.format != smfType1 || trackChunkCount == 1) {
                    m_tempoTrack = m_currentTrack;
                }

                readEvents(chunkEnd);

            } else {
                m_logger->warn("Non-standard chunk of type {} detected, skipping.", chunk.chunkType);
            }

            filePos = chunkEnd;
            chunkStart = filePos;

            // Make sure that we are in the correct location in the chunk
            // If not seek to the correct location and output an error in the log.
            if (static_cast<int>(m_smfFile.tellg()) != filePos) {
                m_logger->warn("Offset for chunk '{}' incorrect, seeking to correct location.", chunk.chunkType);
                m_smfFile.seekg(filePos);
            }
            fileRemaining = (fileEnd-filePos);
            if (fileRemaining != 0 && fileRemaining <= 8) {
                m_logger->warn("To few bytes remaining in midi for another track, this is likely a bug.");
            }
        }
        if (trackChunkCount != m_header.trackNum) {
            m_logger->warn("Track chunk count does not match header.");
        }
        m_logger->info("End of MIDI reached.");

    }

    SmfReader::SmfReader(std::string filename)
    {
        m_logger = spdlog::get("default");
        m_logger->info("Loading MIDI");

        std::ifstream smfFile(filename, std::ios_base::ate | std::ios_base::binary);

        if (smfFile) {
            std::string contents;
            auto size = smfFile.tellg();
            smfFile.seekg(0, std::ios::beg);
            contents.resize(size);
            smfFile.read(&contents[0], size);
            smfFile.close();
            m_smfFile.str(contents);
        } else {
            throw std::runtime_error("Failed to load MIDI file.");
        }

        readFile();
        // Release midifile data after we are finished reading.
        m_smfFile.str( std::string() );
        m_smfFile.clear();
    }

    TempoEvent* SmfReader::getLastTempoIdViaPulses(uint32_t pulseTime)
    {
        static unsigned int value = 0;
        SmfTrack &tempoTrack = m_tracks.front();
        std::vector<TempoEvent> &tempos = tempoTrack.tempo;

        static uint32_t lastPulseTime = 0;

        // Ignore the cached last tempo value if the new pulse time is older.
        if (lastPulseTime > pulseTime) {
            //m_logger->trace("Reset tempo id from: {}", value);
            value = 0;
        }

        for (unsigned int i = 0; i < tempos.size(); i++) {
            // Restore tempo to previous value
            if (i < value) {
                //m_logger->trace("Restored tempo id to: {}", value);
                i = value;
            }
            if (tempos[i].info.pulseTime >=pulseTime) {
                value = i;
                lastPulseTime = pulseTime;
                return &tempos[i];
            }
        }
        // return last value if nothing else is found
        return &tempos.back();

    }

    std::vector<SmfTrack*> SmfReader::getTracks()
    {
        std::vector<SmfTrack*> tracks;

        for (auto &track : m_tracks) {
            tracks.push_back(&track);
        }
        return tracks;
    }
}
<|endoftext|>


<commit_before>// 8.exercise.11.cpp
//
//  Write a function that finds the smallest and the largest element of a
//  vector argument and also computes the mean and the median. Do not use
//  global variables. Either return a struct containing the results or pass
//  them back through reference arguments. Which of the two ways of returning
//  several result values do you prefer and why?
//
// COMMENTS
//
//  Since to calculate the median we must sort the numbers, we can take
//  advantage of that to get the smallest and largest element.
//
//  Median calculation differs on odd or even number of elements. Must test
//  that.
//
//  I prefer:
//      stats get_stats(const vector<double>& v);
//      my_stats = get_stats(data);
//  than:
//      void get_stats(const vector<double>& v, double& max, double& min,
//          double& mean, double& median);
//      get_stats(data, max, min, mean, median);
//
//  More concise and smaller number of parameters and arguments. Less prone to
//  errors, I think.
//

#include "std_lib_facilities.h"

struct Stats {
    double max{0};
    double min{0};
    double mean{0};
    double median{0};
};

void print(const string& label, const vector<double>& data)
// Only read arguments, so it safe to pass them by const-reference
{
    cout << label << ": { ";
    for (double d : data)
        cout << d << ' ';
    cout << "}\n";
}

void print_stats(const Stats& stats)
{
    cout << "Statistics:\n\tMax: " << stats.max << '\n'
         << "\tMin: " << stats.min << '\n'
         << "\tMean: " << stats.mean << '\n'
         << "\tMedian: " << stats.median << '\n';
}

double mean(const vector<double>& v)
{
    double sum{0};
    for (double d : v)
        sum += d;
    return sum/v.size();
}

double median(const vector<double>& v)
// The vector must be sorted
{
    if ((v.size()%2) == 1)          // odd number of elements
        return v[v.size()/2];   // the central element
    size_t idx{v.size()/2};
    return (v[idx-1]+v[idx])/2;
}

Stats get_stats(const vector<double>& v)
// Do not modify the passed vector
{
    vector<double> tmp{v};  // temporal vector to work

    sort(tmp.begin(), tmp.end());   // sort the work vector
    Stats stats;
    stats.min = tmp[0];
    stats.max = tmp[tmp.size()-1];
    stats.mean = mean(tmp);
    stats.median = median(tmp);

    return stats;
}

int main()
try {
    // Mean: 5.28571, Median: 6;
    vector<double> odd_data{3, 9, 1, 8, 7, 6, 3};
    // Mean: 4.75, Median: 4.5
    vector<double> even_data{4, 1, 9, 8, 5, 3, 2, 6};

    print("Odd (number of elements) data", odd_data);
    print_stats(get_stats(odd_data));
    cout << '\n';

    print("Even (number of elements) data", even_data);
    print_stats(get_stats(even_data));
    cout << '\n';

    return 0;
}
catch(exception& e)
{
    cerr << e.what() << '\n';
    return 1;
}
catch(...)
{
    cerr << "Unknown exception!!\n";
    return 2;
}
<commit_msg>Finished exercise 11 from chapter 8.<commit_after>// 8.exercise.11.cpp
//
//  Write a function that finds the smallest and the largest element of a
//  vector argument and also computes the mean and the median. Do not use
//  global variables. Either return a struct containing the results or pass
//  them back through reference arguments. Which of the two ways of returning
//  several result values do you prefer and why?
//
// COMMENTS
//
//  Since to calculate the median we must sort the numbers, we can take
//  advantage of that to get the smallest and largest element.
//
//  Median calculation differs on odd or even number of elements. Must test
//  that.
//
//  I prefer:
//      stats get_stats(const vector<double>& v);
//      my_stats = get_stats(data);
//  than:
//      void get_stats(const vector<double>& v, double& max, double& min,
//          double& mean, double& median);
//      get_stats(data, max, min, mean, median);
//
//  More concise and smaller number of parameters and arguments. Less prone to
//  errors, I think.

#include "std_lib_facilities.h"

struct Stats {
    double max{0};
    double min{0};
    double mean{0};
    double median{0};
};

void print(const string& label, const vector<double>& data)
// Only read arguments, so it safe to pass them by const-reference
{
    cout << label << ": { ";
    for (double d : data)
        cout << d << ' ';
    cout << "}\n";
}

void print_stats(const Stats& stats)
{
    cout << "Statistics:\n\tMax: " << stats.max << '\n'
         << "\tMin: " << stats.min << '\n'
         << "\tMean: " << stats.mean << '\n'
         << "\tMedian: " << stats.median << '\n';
}

double mean(const vector<double>& v)
// Calculates the the mean of the set of values in v
{
    double sum{0};
    for (double d : v)
        sum += d;
    return sum/v.size();
}

double median(const vector<double>& v)
// Calculates the the median of the set of values in v
// The vector iss supposed to be sorted!
// When the number of elements is even, the median is defined
// as the mean between the two most central values in the series.
{
    if ((v.size()%2) == 1)          // odd number of elements
        return v[v.size()/2];       // the central element
    size_t idx{v.size()/2};
    return (v[idx-1]+v[idx])/2;
}

Stats get_stats(const vector<double>& v)
// Doesn't modify the passed vector
{
    vector<double> tmp{v};  // temporal vector to work

    sort(tmp.begin(), tmp.end());   // sort the work vector
    Stats stats;
    stats.min = tmp[0];
    stats.max = tmp[tmp.size()-1];
    stats.mean = mean(tmp);
    stats.median = median(tmp);

    return stats;
}

int main()
try {
    // Mean: 5.28571, Median: 6;
    vector<double> odd_data{3, 9, 1, 8, 7, 6, 3};
    // Mean: 4.75, Median: 4.5
    vector<double> even_data{4, 1, 9, 8, 5, 3, 2, 6};

    print("Odd (number of elements) data", odd_data);
    print_stats(get_stats(odd_data));
    cout << '\n';

    print("Even (number of elements) data", even_data);
    print_stats(get_stats(even_data));
    cout << '\n';

    return 0;
}
catch(exception& e)
{
    cerr << e.what() << '\n';
    return 1;
}
catch(...)
{
    cerr << "Unknown exception!!\n";
    return 2;
}
<|endoftext|>


<commit_before>#include "CShader.h"

Shader::Shader()
{
    // Initialize variables
    shaderID = 0;
    type     = 0;
    loaded   = false;
}

Shader::~Shader()
{
    // Delete the shader
    DeleteShader();
}

void Shader::DeleteShader()
{
    if (!IsLoaded())
    {
        // Delete the shader
        glDeleteShader(shaderID);

        // Set shaderID to 0
        shaderID = 0;

        // Set loaded to false
        loaded = false;
    }
}

bool Shader::Load(string path, GLuint shaderType)
{
    //  Success flag
    GLint compiled = GL_FALSE;

    // Create a shader of the correct type
    shaderID = glCreateShader(shaderType);

    // Input stream
    ifstream file(path.c_str());

    // Source string
    string shaderSource;

    // Clear file flags
    file.clear();

    // If the file opened successfully
    if (file.good())
    {
        // Get total length of file
        file.seekg(0, ios::end);

        // Set string size to length of file
        shaderSource.reserve((unsigned int)file.tellg());

        // Reset cursor to beginning of file
        file.seekg(0, ios::beg);

        // Read in file as one string
        shaderSource.assign((istreambuf_iterator<char>(file)), (istreambuf_iterator<char>()));

    }
    else
    {
        // Print error message
        printf("Couldn't open file %s\n", path.c_str());

        // Set string to empty
        shaderSource = "";

        // Return false
        return false;
    }

    // Close file
    file.close();

    // Set shader source
    glShaderSource(shaderID, 1, (const GLchar**)&shaderSource, NULL);

    // Compile shader
    glCompileShader(shaderID);

    // Check if shader compiled successfully
    glGetShaderiv(shaderID, GL_COMPILE_STATUS, &compiled);

    // If compilation failed
    if (compiled != GL_TRUE)
    {
        // Print an error message
        printf("Couldn't compile shader %d\n\n Source code\n%s\n", shaderID, shaderSource.c_str());

        // Print shader log
        PrintLog();

        // Delete the shader
        glDeleteShader(shaderID);

        // Set shaderID to 0
        shaderID = 0;

        // Return false
        return false;
    }

    // Set type
    type = shaderType;

    // loaded succesfully
    loaded = true;

    // Return success
    return true;
}

void Shader::PrintLog()
{
    //Make sure name is shader
    if (glIsShader(shaderID))
    {
        //Shader log length
        int infoLogLength = 0;
        int maxLength = infoLogLength;

        //Get info string length
        glGetShaderiv(shaderID, GL_INFO_LOG_LENGTH, &maxLength);

        //Allocate string
        char* infoLog = new char[maxLength];

        //Get info log
        glGetShaderInfoLog(shaderID, maxLength, &infoLogLength, infoLog);

        if (infoLogLength > 0)
        {
            //Print Log
            printf("%s\n", infoLog);
        }

        //Deallocate string
        delete[] infoLog;
    }
    else
    {
        printf("Name %d is not a shader\n", shaderID);
    }
}
<commit_msg>Correct typo in Shader class.<commit_after>#include "CShader.h"

Shader::Shader()
{
    // Initialize variables
    shaderID = 0;
    type     = 0;
    loaded   = false;
}

Shader::~Shader()
{
    // Delete the shader
    DeleteShader();
}

void Shader::DeleteShader()
{
    if (IsLoaded())
    {
        // Delete the shader
        glDeleteShader(shaderID);

        // Set shaderID to 0
        shaderID = 0;

        // Set loaded to false
        loaded = false;
    }
}

bool Shader::Load(string path, GLuint shaderType)
{
    //  Success flag
    GLint compiled = GL_FALSE;

    // Create a shader of the correct type
    shaderID = glCreateShader(shaderType);

    // Input stream
    ifstream file(path.c_str());

    // Source string
    string shaderSource;

    // Clear file flags
    file.clear();

    // If the file opened successfully
    if (file.good())
    {
        // Get total length of file
        file.seekg(0, ios::end);

        // Set string size to length of file
        shaderSource.reserve((unsigned int)file.tellg());

        // Reset cursor to beginning of file
        file.seekg(0, ios::beg);

        // Read in file as one string
        shaderSource.assign((istreambuf_iterator<char>(file)), (istreambuf_iterator<char>()));

    }
    else
    {
        // Print error message
        printf("Couldn't open file %s\n", path.c_str());

        // Set string to empty
        shaderSource = "";

        // Return false
        return false;
    }

    // Close file
    file.close();

    // Set shader source
    glShaderSource(shaderID, 1, (const GLchar**)&shaderSource, NULL);

    // Compile shader
    glCompileShader(shaderID);

    // Check if shader compiled successfully
    glGetShaderiv(shaderID, GL_COMPILE_STATUS, &compiled);

    // If compilation failed
    if (compiled != GL_TRUE)
    {
        // Print an error message
        printf("Couldn't compile shader %d\n\n Source code\n%s\n", shaderID, shaderSource.c_str());

        // Print shader log
        PrintLog();

        // Delete the shader
        glDeleteShader(shaderID);

        // Set shaderID to 0
        shaderID = 0;

        // Return false
        return false;
    }

    // Set type
    type = shaderType;

    // loaded succesfully
    loaded = true;

    // Return success
    return true;
}

void Shader::PrintLog()
{
    //Make sure name is shader
    if (glIsShader(shaderID))
    {
        //Shader log length
        int infoLogLength = 0;
        int maxLength = infoLogLength;

        //Get info string length
        glGetShaderiv(shaderID, GL_INFO_LOG_LENGTH, &maxLength);

        //Allocate string
        char* infoLog = new char[maxLength];

        //Get info log
        glGetShaderInfoLog(shaderID, maxLength, &infoLogLength, infoLog);

        if (infoLogLength > 0)
        {
            //Print Log
            printf("%s\n", infoLog);
        }

        //Deallocate string
        delete[] infoLog;
    }
    else
    {
        printf("Name %d is not a shader\n", shaderID);
    }
}
<|endoftext|>