<commit_before>/******************************************************************************
*       SOFA, Simulation Open-Framework Architecture, version 1.0 RC 1        *
*                (c) 2006-2011 MGH, INRIA, USTL, UJF, CNRS                    *
*                                                                             *
* This library is free software; you can redistribute it and/or modify it     *
* under the terms of the GNU Lesser General Public License as published by    *
* the Free Software Foundation; either version 2.1 of the License, or (at     *
* your option) any later version.                                             *
*                                                                             *
* This library is distributed in the hope that it will be useful, but WITHOUT *
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or       *
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License *
* for more details.                                                           *
*                                                                             *
* You should have received a copy of the GNU Lesser General Public License    *
* along with this library; if not, write to the Free Software Foundation,     *
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA.          *
*******************************************************************************
*                               SOFA :: Modules                               *
*                                                                             *
* Authors: The SOFA Team and external contributors (see Authors.txt)          *
*                                                                             *
* Contact information: contact@sofa-framework.org                             *
******************************************************************************/
// Author: Hadrien Courtecuisse
//
// Copyright: See COPYING file that comes with this distribution
#ifndef SOFA_COMPONENT_COLLISION_PRECOMPUTEDLINEARSOLVER_INL
#define SOFA_COMPONENT_COLLISION_PRECOMPUTEDLINEARSOLVER_INL

#include "PrecomputedLinearSolver.h"
#include <SofaBaseLinearSolver/FullMatrix.h>
#include <SofaBaseLinearSolver/SparseMatrix.h>
#include <sofa/core/ObjectFactory.h>
#include <iostream>
#include "sofa/helper/system/thread/CTime.h"
#include <sofa/core/objectmodel/BaseContext.h>
#include <sofa/core/behavior/LinearSolver.h>
#include <math.h>
#include <sofa/helper/system/thread/CTime.h>
#include <SofaSimpleFem/TetrahedronFEMForceField.h>
#include <sofa/defaulttype/Vec3Types.h>
#include <SofaBaseLinearSolver/MatrixLinearSolver.h>
#include <sofa/helper/system/thread/CTime.h>
#include <sofa/core/behavior/LinearSolver.h>

#include <SofaImplicitOdeSolver/EulerImplicitSolver.h>
#include <SofaBaseLinearSolver/CGLinearSolver.h>

#include <SofaSparseSolver/SparseCholeskySolver.h>
#include <SofaBaseLinearSolver/CompressedRowSparseMatrix.h>
#include <SofaBaseLinearSolver/CholeskySolver.h>

namespace sofa
{

namespace component
{

namespace linearsolver
{

template<class TMatrix,class TVector>
PrecomputedLinearSolver<TMatrix,TVector>::PrecomputedLinearSolver()
    : jmjt_twostep( initData(&jmjt_twostep,true,"jmjt_twostep","Use two step algorithm to compute JMinvJt") )
    , f_verbose( initData(&f_verbose,false,"verbose","Dump system state at each iteration") )
    , use_file( initData(&use_file,true,"use_file","Dump system matrix in a file") )
{
    first = true;
}

template<class TMatrix,class TVector>
void PrecomputedLinearSolver<TMatrix,TVector>::setSystemMBKMatrix(const core::MechanicalParams* mparams)
{
    // Update the matrix only the first time
    if (first)
    {
        first = false;
        Inherit::setSystemMBKMatrix(mparams);
        loadMatrix(*this->currentGroup->systemMatrix);
    }
}

//Solve x = R * M^-1 * R^t * b
template<class TMatrix,class TVector>
void PrecomputedLinearSolver<TMatrix,TVector>::solve (TMatrix& , TVector& z, TVector& r)
{
    z = internalData.Minv * r;
}

template<class TMatrix,class TVector>
void PrecomputedLinearSolver<TMatrix,TVector >::loadMatrix(TMatrix& /*M*/)
{
    systemSize = this->currentGroup->systemMatrix->rowSize();
    internalData.Minv.resize(systemSize,systemSize);
    dt = this->getContext()->getDt();

    odesolver::EulerImplicitSolver* EulerSolver;
    this->getContext()->get(EulerSolver);
    factInt = 1.0; // christian : it is not a compliance... but an admittance that is computed !
    if (EulerSolver) factInt = EulerSolver->getPositionIntegrationFactor(); // here, we compute a compliance

    std::stringstream ss;
    ss << this->getContext()->getName() << "-" << systemSize << "-" << dt << ".comp";
    if(! use_file.getValue() || ! internalData.readFile(ss.str().c_str(),systemSize) )
    {
        loadMatrixWithCSparse(M);
        if (use_file.getValue()) internalData.writeFile(ss.str().c_str(),systemSize);
    }

    for (unsigned int j=0; j<systemSize; j++)
    {
        for (unsigned i=0; i<systemSize; i++)
        {
            internalData.Minv.set(j,i,internalData.Minv.element(j,i)/factInt);
        }
    }
}

template<class TMatrix,class TVector>
void PrecomputedLinearSolver<TMatrix,TVector>::loadMatrixWithCSparse(TMatrix& M)
{
    std::cout << "Compute the initial invert matrix with CS_PARSE" << std::endl;

    CompressedRowSparseMatrix<double> matSolv;
    FullVector<double> r;
    FullVector<double> b;

// 	unsigned systemSize = internalData.Minv.colSize();

    matSolv.resize(systemSize,systemSize);
    r.resize(systemSize);
    b.resize(systemSize);
    SparseCholeskySolver<CompressedRowSparseMatrix<double>, FullVector<double> > solver;

    for (unsigned int j=0; j<systemSize; j++)
    {
        for (unsigned int i=0; i<systemSize; i++)
        {
            if (M.element(j,i)!=0) matSolv.set(j,i,M.element(j,i));
        }
        b.set(j,0.0);
    }

    std::cout << "Precomputing constraint correction LU decomposition " << std::endl;
    solver.invert(matSolv);

    for (unsigned int j=0; j<systemSize; j++)
    {
        std::cout.precision(2);
        std::cout << "Precomputing constraint correction : " << std::fixed << (float)j/(float)systemSize*100.0f << " %   " << '\xd';
        std::cout.flush();

        if (j>0) b.set(j-1,0.0);
        b.set(j,1.0);

        solver.solve(matSolv,r,b);
        for (unsigned int i=0; i<systemSize; i++)
        {
            internalData.Minv.set(j,i,r.element(i) * factInt);
        }
    }
    std::cout << "Precomputing constraint correction : " << std::fixed << 100.0f << " %   " << '\xd';
    std::cout.flush();
}

template<class TMatrix,class TVector>
void PrecomputedLinearSolver<TMatrix,TVector>::invert(TMatrix& /*M*/) {}

template<class TMatrix,class TVector> template<class JMatrix>
void PrecomputedLinearSolver<TMatrix,TVector>::computeActiveDofs(JMatrix& J)
{
    isActiveDofs.clear();
    isActiveDofs.resize(systemSize);

    //compute JR = J * R
    for (typename JMatrix::LineConstIterator jit1 = J.begin(); jit1 != J.end(); jit1++)
    {
        for (typename JMatrix::LElementConstIterator i1 = jit1->second.begin(); i1 != jit1->second.end(); i1++)
        {
            isActiveDofs[i1->first] = true;
        }
    }

    internalData.invActiveDofs.clear();
    internalData.invActiveDofs.resize(systemSize);
    internalData.idActiveDofs.clear();

    for (unsigned c=0; c<systemSize; c++)
    {
        if (isActiveDofs[c])
        {
            internalData.invActiveDofs[c] = internalData.idActiveDofs.size();
            internalData.idActiveDofs.push_back(c);
        }
    }
}

template<class TMatrix,class TVector>
bool PrecomputedLinearSolver<TMatrix,TVector>::addJMInvJt(defaulttype::BaseMatrix* result, defaulttype::BaseMatrix* J, double fact)
{
    if (first)
    {
        core::MechanicalParams mparams = *core::MechanicalParams::defaultInstance();
        //TODO get the m b k factor from euler

        std::cerr << "ERROR : the construction of the matrix when the solver is used only as cvonstraint correction is not implemented. You first need to save the matrix into a file" << std::endl;
        setSystemMBKMatrix(&mparams);
    }

    if (SparseMatrix<double>* j = dynamic_cast<SparseMatrix<double>*>(J))
    {
        computeActiveDofs(*j);
        ComputeResult(result, *j, (float) fact);
    }
    else if (SparseMatrix<float>* j = dynamic_cast<SparseMatrix<float>*>(J))
    {
        computeActiveDofs(*j);
        ComputeResult(result, *j, (float) fact);
    } return false;

    return true;
}

template<class TMatrix,class TVector> template<class JMatrix>
void PrecomputedLinearSolver<TMatrix,TVector>::ComputeResult(defaulttype::BaseMatrix * result,JMatrix& J, float fact)
{
    unsigned nl = 0;
    internalData.JMinv.clear();
    internalData.JMinv.resize(J.rowSize(),internalData.idActiveDofs.size());

    nl=0;
    for (typename JMatrix::LineConstIterator jit1 = J.begin(); jit1 != J.end(); jit1++)
    {
        for (unsigned c = 0; c<internalData.idActiveDofs.size(); c++)
        {
            int col = internalData.idActiveDofs[c];
            Real v = 0.0;
            for (typename JMatrix::LElementConstIterator i1 = jit1->second.begin(); i1 != jit1->second.end(); i1++)
            {
                v += internalData.Minv.element(i1->first,col) * i1->second;
            }
            internalData.JMinv.set(nl,c,v);
        }
        nl++;
    }
    //compute Result = JRMinv * (JR)t
    nl = 0;
    for (typename JMatrix::LineConstIterator jit1 = J.begin(); jit1 != J.end(); jit1++)
    {
        int row = jit1->first;
        for (typename JMatrix::LineConstIterator jit2 = J.begin(); jit2 != J.end(); jit2++)
        {
            int col = jit2->first;
            Real res = 0.0;
            for (typename JMatrix::LElementConstIterator i1 = jit2->second.begin(); i1 != jit2->second.end(); i1++)
            {
                res += internalData.JMinv.element(nl,internalData.invActiveDofs[i1->first]) * i1->second;
            }
            result->add(row,col,res*fact);
        }
        nl++;
    }
}

} // namespace linearsolver

} // namespace component

} // namespace sofa

#endif
<commit_msg>Fix compilation<commit_after>/******************************************************************************
*       SOFA, Simulation Open-Framework Architecture, version 1.0 RC 1        *
*                (c) 2006-2011 MGH, INRIA, USTL, UJF, CNRS                    *
*                                                                             *
* This library is free software; you can redistribute it and/or modify it     *
* under the terms of the GNU Lesser General Public License as published by    *
* the Free Software Foundation; either version 2.1 of the License, or (at     *
* your option) any later version.                                             *
*                                                                             *
* This library is distributed in the hope that it will be useful, but WITHOUT *
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or       *
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License *
* for more details.                                                           *
*                                                                             *
* You should have received a copy of the GNU Lesser General Public License    *
* along with this library; if not, write to the Free Software Foundation,     *
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA.          *
*******************************************************************************
*                               SOFA :: Modules                               *
*                                                                             *
* Authors: The SOFA Team and external contributors (see Authors.txt)          *
*                                                                             *
* Contact information: contact@sofa-framework.org                             *
******************************************************************************/
// Author: Hadrien Courtecuisse
//
// Copyright: See COPYING file that comes with this distribution
#ifndef SOFA_COMPONENT_COLLISION_PRECOMPUTEDLINEARSOLVER_INL
#define SOFA_COMPONENT_COLLISION_PRECOMPUTEDLINEARSOLVER_INL

#include "PrecomputedLinearSolver.h"
#include <SofaBaseLinearSolver/FullMatrix.h>
#include <SofaBaseLinearSolver/SparseMatrix.h>
#include <sofa/core/ObjectFactory.h>
#include <iostream>
#include "sofa/helper/system/thread/CTime.h"
#include <sofa/core/objectmodel/BaseContext.h>
#include <sofa/core/behavior/LinearSolver.h>
#include <math.h>
#include <sofa/helper/system/thread/CTime.h>
#include <SofaSimpleFem/TetrahedronFEMForceField.h>
#include <sofa/defaulttype/Vec3Types.h>
#include <SofaBaseLinearSolver/MatrixLinearSolver.h>
#include <sofa/helper/system/thread/CTime.h>
#include <sofa/core/behavior/LinearSolver.h>

#include <SofaImplicitOdeSolver/EulerImplicitSolver.h>
#include <SofaBaseLinearSolver/CGLinearSolver.h>

#include <SofaSparseSolver/SparseCholeskySolver.h>
#include <SofaBaseLinearSolver/CompressedRowSparseMatrix.h>
#include <SofaBaseLinearSolver/CholeskySolver.h>

namespace sofa
{

namespace component
{

namespace linearsolver
{

template<class TMatrix,class TVector>
PrecomputedLinearSolver<TMatrix,TVector>::PrecomputedLinearSolver()
    : jmjt_twostep( initData(&jmjt_twostep,true,"jmjt_twostep","Use two step algorithm to compute JMinvJt") )
    , f_verbose( initData(&f_verbose,false,"verbose","Dump system state at each iteration") )
    , use_file( initData(&use_file,true,"use_file","Dump system matrix in a file") )
{
    first = true;
}

template<class TMatrix,class TVector>
void PrecomputedLinearSolver<TMatrix,TVector>::setSystemMBKMatrix(const core::MechanicalParams* mparams)
{
    // Update the matrix only the first time
    if (first)
    {
        first = false;
        Inherit::setSystemMBKMatrix(mparams);
        loadMatrix(*this->currentGroup->systemMatrix);
    }
}

//Solve x = R * M^-1 * R^t * b
template<class TMatrix,class TVector>
void PrecomputedLinearSolver<TMatrix,TVector>::solve (TMatrix& , TVector& z, TVector& r)
{
    z = internalData.Minv * r;
}

template<class TMatrix,class TVector>
void PrecomputedLinearSolver<TMatrix,TVector >::loadMatrix(TMatrix& M)
{
    systemSize = this->currentGroup->systemMatrix->rowSize();
    internalData.Minv.resize(systemSize,systemSize);
    dt = this->getContext()->getDt();

    odesolver::EulerImplicitSolver* EulerSolver;
    this->getContext()->get(EulerSolver);
    factInt = 1.0; // christian : it is not a compliance... but an admittance that is computed !
    if (EulerSolver) factInt = EulerSolver->getPositionIntegrationFactor(); // here, we compute a compliance

    std::stringstream ss;
    ss << this->getContext()->getName() << "-" << systemSize << "-" << dt << ".comp";
    if(! use_file.getValue() || ! internalData.readFile(ss.str().c_str(),systemSize) )
    {
        loadMatrixWithCSparse(M);
        if (use_file.getValue()) internalData.writeFile(ss.str().c_str(),systemSize);
    }

    for (unsigned int j=0; j<systemSize; j++)
    {
        for (unsigned i=0; i<systemSize; i++)
        {
            internalData.Minv.set(j,i,internalData.Minv.element(j,i)/factInt);
        }
    }
}

template<class TMatrix,class TVector>
void PrecomputedLinearSolver<TMatrix,TVector>::loadMatrixWithCSparse(TMatrix& M)
{
    std::cout << "Compute the initial invert matrix with CS_PARSE" << std::endl;

    CompressedRowSparseMatrix<double> matSolv;
    FullVector<double> r;
    FullVector<double> b;

// 	unsigned systemSize = internalData.Minv.colSize();

    matSolv.resize(systemSize,systemSize);
    r.resize(systemSize);
    b.resize(systemSize);
    SparseCholeskySolver<CompressedRowSparseMatrix<double>, FullVector<double> > solver;

    for (unsigned int j=0; j<systemSize; j++)
    {
        for (unsigned int i=0; i<systemSize; i++)
        {
            if (M.element(j,i)!=0) matSolv.set(j,i,M.element(j,i));
        }
        b.set(j,0.0);
    }

    std::cout << "Precomputing constraint correction LU decomposition " << std::endl;
    solver.invert(matSolv);

    for (unsigned int j=0; j<systemSize; j++)
    {
        std::cout.precision(2);
        std::cout << "Precomputing constraint correction : " << std::fixed << (float)j/(float)systemSize*100.0f << " %   " << '\xd';
        std::cout.flush();

        if (j>0) b.set(j-1,0.0);
        b.set(j,1.0);

        solver.solve(matSolv,r,b);
        for (unsigned int i=0; i<systemSize; i++)
        {
            internalData.Minv.set(j,i,r.element(i) * factInt);
        }
    }
    std::cout << "Precomputing constraint correction : " << std::fixed << 100.0f << " %   " << '\xd';
    std::cout.flush();
}

template<class TMatrix,class TVector>
void PrecomputedLinearSolver<TMatrix,TVector>::invert(TMatrix& /*M*/) {}

template<class TMatrix,class TVector> template<class JMatrix>
void PrecomputedLinearSolver<TMatrix,TVector>::computeActiveDofs(JMatrix& J)
{
    isActiveDofs.clear();
    isActiveDofs.resize(systemSize);

    //compute JR = J * R
    for (typename JMatrix::LineConstIterator jit1 = J.begin(); jit1 != J.end(); jit1++)
    {
        for (typename JMatrix::LElementConstIterator i1 = jit1->second.begin(); i1 != jit1->second.end(); i1++)
        {
            isActiveDofs[i1->first] = true;
        }
    }

    internalData.invActiveDofs.clear();
    internalData.invActiveDofs.resize(systemSize);
    internalData.idActiveDofs.clear();

    for (unsigned c=0; c<systemSize; c++)
    {
        if (isActiveDofs[c])
        {
            internalData.invActiveDofs[c] = internalData.idActiveDofs.size();
            internalData.idActiveDofs.push_back(c);
        }
    }
}

template<class TMatrix,class TVector>
bool PrecomputedLinearSolver<TMatrix,TVector>::addJMInvJt(defaulttype::BaseMatrix* result, defaulttype::BaseMatrix* J, double fact)
{
    if (first)
    {
        core::MechanicalParams mparams = *core::MechanicalParams::defaultInstance();
        //TODO get the m b k factor from euler

        std::cerr << "ERROR : the construction of the matrix when the solver is used only as cvonstraint correction is not implemented. You first need to save the matrix into a file" << std::endl;
        setSystemMBKMatrix(&mparams);
    }

    if (SparseMatrix<double>* j = dynamic_cast<SparseMatrix<double>*>(J))
    {
        computeActiveDofs(*j);
        ComputeResult(result, *j, (float) fact);
    }
    else if (SparseMatrix<float>* j = dynamic_cast<SparseMatrix<float>*>(J))
    {
        computeActiveDofs(*j);
        ComputeResult(result, *j, (float) fact);
    } return false;

    return true;
}

template<class TMatrix,class TVector> template<class JMatrix>
void PrecomputedLinearSolver<TMatrix,TVector>::ComputeResult(defaulttype::BaseMatrix * result,JMatrix& J, float fact)
{
    unsigned nl = 0;
    internalData.JMinv.clear();
    internalData.JMinv.resize(J.rowSize(),internalData.idActiveDofs.size());

    nl=0;
    for (typename JMatrix::LineConstIterator jit1 = J.begin(); jit1 != J.end(); jit1++)
    {
        for (unsigned c = 0; c<internalData.idActiveDofs.size(); c++)
        {
            int col = internalData.idActiveDofs[c];
            Real v = 0.0;
            for (typename JMatrix::LElementConstIterator i1 = jit1->second.begin(); i1 != jit1->second.end(); i1++)
            {
                v += internalData.Minv.element(i1->first,col) * i1->second;
            }
            internalData.JMinv.set(nl,c,v);
        }
        nl++;
    }
    //compute Result = JRMinv * (JR)t
    nl = 0;
    for (typename JMatrix::LineConstIterator jit1 = J.begin(); jit1 != J.end(); jit1++)
    {
        int row = jit1->first;
        for (typename JMatrix::LineConstIterator jit2 = J.begin(); jit2 != J.end(); jit2++)
        {
            int col = jit2->first;
            Real res = 0.0;
            for (typename JMatrix::LElementConstIterator i1 = jit2->second.begin(); i1 != jit2->second.end(); i1++)
            {
                res += internalData.JMinv.element(nl,internalData.invActiveDofs[i1->first]) * i1->second;
            }
            result->add(row,col,res*fact);
        }
        nl++;
    }
}

} // namespace linearsolver

} // namespace component

} // namespace sofa

#endif
<|endoftext|>


<commit_before>/*
 *  Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */

#include "webrtc/modules/audio_device/audio_device_config.h"
#include "webrtc/modules/audio_device/ios/audio_device_utility_ios.h"

#include "webrtc/system_wrappers/interface/critical_section_wrapper.h"
#include "webrtc/system_wrappers/interface/trace.h"

namespace webrtc {
AudioDeviceUtilityIOS::AudioDeviceUtilityIOS(const int32_t id)
:
    _critSect(*CriticalSectionWrapper::CreateCriticalSection()),
    _id(id),
    _lastError(AudioDeviceModule::kAdmErrNone) {
    WEBRTC_TRACE(kTraceMemory, kTraceAudioDevice, id,
                 "%s created", __FUNCTION__);
}

AudioDeviceUtilityIOS::~AudioDeviceUtilityIOS() {
    WEBRTC_TRACE(kTraceMemory, kTraceAudioDevice, _id,
                 "%s destroyed", __FUNCTION__);
    CriticalSectionScoped lock(&_critSect);

    delete &_critSect;
}

int32_t AudioDeviceUtilityIOS::Init() {
    WEBRTC_TRACE(kTraceModuleCall, kTraceAudioDevice, _id,
                 "%s", __FUNCTION__);

    WEBRTC_TRACE(kTraceStateInfo, kTraceAudioDevice, _id,
                 "  OS info: %s", "iOS");

    return 0;
}

}  // namespace webrtc
<commit_msg>Fix crash in AudioDeviceUtilityIOS::~AudioDeviceUtilityIOS.<commit_after>/*
 *  Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */

#include "webrtc/modules/audio_device/audio_device_config.h"
#include "webrtc/modules/audio_device/ios/audio_device_utility_ios.h"

#include "webrtc/system_wrappers/interface/critical_section_wrapper.h"
#include "webrtc/system_wrappers/interface/trace.h"

namespace webrtc {
AudioDeviceUtilityIOS::AudioDeviceUtilityIOS(const int32_t id)
:
    _critSect(*CriticalSectionWrapper::CreateCriticalSection()),
    _id(id),
    _lastError(AudioDeviceModule::kAdmErrNone) {
    WEBRTC_TRACE(kTraceMemory, kTraceAudioDevice, id,
                 "%s created", __FUNCTION__);
}

AudioDeviceUtilityIOS::~AudioDeviceUtilityIOS() {
    WEBRTC_TRACE(kTraceMemory, kTraceAudioDevice, _id,
                 "%s destroyed", __FUNCTION__);
    {
        CriticalSectionScoped lock(&_critSect);
    }
    delete &_critSect;
}

int32_t AudioDeviceUtilityIOS::Init() {
    WEBRTC_TRACE(kTraceModuleCall, kTraceAudioDevice, _id,
                 "%s", __FUNCTION__);

    WEBRTC_TRACE(kTraceStateInfo, kTraceAudioDevice, _id,
                 "  OS info: %s", "iOS");

    return 0;
}

}  // namespace webrtc
<|endoftext|>


<commit_before><commit_msg>canbus:fix wrong using static_cast<commit_after><|endoftext|>


<commit_before>/*****************************************************************************
 * profile_selector.cpp : A small profile selector and editor
 ****************************************************************************
 * Copyright (C) 2009 the VideoLAN team
 * $Id$
 *
 * Authors: Jean-Baptiste Kempf <jb@videolan.org>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
 *****************************************************************************/

#include "components/sout/profile_selector.hpp"
#include "components/sout/profiles.hpp"
#include "dialogs/sout.hpp"

#include <QHBoxLayout>
#include <QToolButton>
#include <QComboBox>
#include <QLabel>
#include <QMessageBox>

VLCProfileSelector::VLCProfileSelector( QWidget *_parent ): QWidget( _parent )
{
    QHBoxLayout *layout = new QHBoxLayout( this );

    QLabel *prLabel = new QLabel( qtr( "Profile"), this );
    layout->addWidget( prLabel );

    profileBox = new QComboBox( this );
    layout->addWidget( profileBox );

    QToolButton *editButton = new QToolButton( this );
    editButton->setIcon( QIcon( ":/preferences" ) );
    editButton->setToolTip( qtr( "Edit selected profile" ) );
    layout->addWidget( editButton );

    QToolButton *deleteButton = new QToolButton( this );
    deleteButton->setIcon( QIcon( ":/clear" ) );
    deleteButton->setToolTip( qtr( "Delete selected profile" ) );
    layout->addWidget( deleteButton );

    QToolButton *newButton = new QToolButton( this );
    newButton->setIcon( QIcon( ":/new" ) );
    newButton->setToolTip( qtr( "Create a new profile" ) );
    layout->addWidget(newButton);

    BUTTONACT( newButton, newProfile() );
    BUTTONACT( editButton, editProfile() );
    BUTTONACT( deleteButton, deleteProfile() );
    fillProfilesCombo();

    CONNECT( profileBox, activated( int ),
             this, updateOptions( int ) );

}

inline void VLCProfileSelector::fillProfilesCombo()
{
    QSettings settings(
#ifdef WIN32
            QSettings::IniFormat,
#else
            QSettings::NativeFormat,
#endif
            QSettings::UserScope, "vlc", "vlc-qt-interface" );

    int i_size = settings.beginReadArray( "codecs-profiles" );

    for( int i = 0; i < i_size; i++ )
    {
        settings.setArrayIndex( i );
        if( settings.value( "Profile-Name" ).toString().isEmpty() ) continue;
        profileBox->addItem( settings.value( "Profile-Name" ).toString(),
                settings.value( "Profile-Value" ) );
    }
    if( i_size == 0 )
    {
        for( int i = 0; i < NB_PROFILE; i++ )
        {
            profileBox->addItem( video_profile_name_list[i],
                                 video_profile_value_list[i] );
        }
    }
    settings.endArray();
}

void VLCProfileSelector::newProfile()
{
    editProfile( "", "" );
}

void VLCProfileSelector::editProfile()
{
    editProfile( profileBox->currentText(),
                 profileBox->itemData( profileBox->currentIndex() ).toString() );
}

void VLCProfileSelector::editProfile( QString qs, QString value )
{
    VLCProfileEditor *editor = new VLCProfileEditor( qs, value, this );

    if( QDialog::Accepted == editor->exec() )
    {
        if( qs.isEmpty() )
            profileBox->addItem( editor->name, QVariant( editor->transcodeValue() ) );
        else
        {
            int i_profile = profileBox->findText( qs );
            profileBox->setItemText( i_profile, editor->name );
            profileBox->setItemData( i_profile, QVariant( editor->transcodeValue() ) );
        }
    }
    delete editor;

    saveProfiles();
    emit optionsChanged();
}

void VLCProfileSelector::deleteProfile()
{
    profileBox->removeItem( profileBox->currentIndex() );
}

void VLCProfileSelector::saveProfiles()
{
    QSettings settings(
#ifdef WIN32
            QSettings::IniFormat,
#else
            QSettings::NativeFormat,
#endif
            QSettings::UserScope, "vlc", "vlc-qt-interface" );

    settings.beginWriteArray( "codecs-profiles" );
    for( int i = 0; i < profileBox->count(); i++ )
    {
        settings.setArrayIndex( i );
        settings.setValue( "Profile-Name", profileBox->itemText( i ) );
        settings.setValue( "Profile-Value", profileBox->itemData( i ).toString() );
    }
    settings.endArray();
}

void VLCProfileSelector::updateOptions( int i )
{
    QStringList options = profileBox->itemData( i ).toString().split( ";" );
    if( options.size() < 16 )
        return;

    mux = options[0];

    SoutMrl smrl;
    if( options[1].toInt() || options[2].toInt() )
    {
        smrl.begin( "transcode" );

        if( options[1].toInt() )
        {
            smrl.option( "vcodec", options[4] );
            smrl.option( "vb", options[5].toInt() );
            smrl.option( "scale", options[6] );
            smrl.option( "fps", options[7] );
            smrl.option( "width", options[8].toInt() );
            smrl.option( "height", options[9].toInt() );
        }

        if( options[2].toInt() )
        {
            smrl.option( "acodec", options[10] );
            smrl.option( "ab", options[11].toInt() );
            smrl.option( "channels", options[12].toInt() );
            smrl.option( "samplerate", options[13].toInt() );
        }

        if( options[3].toInt() )
        {
            smrl.option( "scodec", options[14] );
            if( options[15].toInt() )
                smrl.option( "soverlay" );
        }

        smrl.end();

        transcode = smrl.getMrl();
    }
    else
        transcode = "";
    emit optionsChanged();
}

/**
 * VLCProfileEditor
 **/
VLCProfileEditor::VLCProfileEditor( QString qs_name, QString value,
        QWidget *_parent )
                 : QVLCDialog( _parent, NULL )
{
    ui.setupUi( this );
    if( !qs_name.isEmpty() )
    {
        ui.profileLine->setText( qs_name );
        ui.profileLine->setReadOnly( true );
    }
    registerCodecs();
    CONNECT( ui.transcodeVideo, toggled( bool ),
            this, setVTranscodeOptions( bool ) );
    CONNECT( ui.transcodeAudio, toggled( bool ),
            this, setATranscodeOptions( bool ) );
    CONNECT( ui.transcodeSubs, toggled( bool ),
            this, setSTranscodeOptions( bool ) );
    setVTranscodeOptions( false );
    setATranscodeOptions( false );
    setSTranscodeOptions( false );

    QPushButton *saveButton = new QPushButton( qtr( "Save" ) );
    ui.buttonBox->addButton( saveButton, QDialogButtonBox::AcceptRole );
    BUTTONACT( saveButton, close() );
    QPushButton *cancelButton = new QPushButton( qtr( "Cancel" ) );
    ui.buttonBox->addButton( cancelButton, QDialogButtonBox::RejectRole );
    BUTTONACT( cancelButton, reject() );

    fillProfile( value );
}

inline void VLCProfileEditor::registerCodecs()
{

#define ADD_VCODEC( name, fourcc ) ui.vCodecBox->addItem( name, QVariant( fourcc ) );
    ADD_VCODEC( "MPEG-1", "mp1v" )
    ADD_VCODEC( "MPEG-2", "mp2v" )
    ADD_VCODEC( "MPEG-4", "mp4v" )
    ADD_VCODEC( "DIVX 1" , "DIV1" )
    ADD_VCODEC( "DIVX 2" , "DIV2" )
    ADD_VCODEC( "DIVX 3" , "DIV3" )
    ADD_VCODEC( "H-263", "H263" )
    ADD_VCODEC( "H-264", "h264" )
    ADD_VCODEC( "WMV1", "WMV1" )
    ADD_VCODEC( "WMV2" , "WMV2" )
    ADD_VCODEC( "M-JPEG", "MJPG" )
    ADD_VCODEC( "Theora", "theo" )
    ADD_VCODEC( "Dirac", "drac" )

#define ADD_ACODEC( name, fourcc ) ui.aCodecBox->addItem( name, QVariant( fourcc ) );
    ADD_ACODEC( "MPEG Audio", "mpga" )
    ADD_ACODEC( "MP3", "mp3" )
    ADD_ACODEC( "MPEG 4 Audio ( AAC )", "mp4a" )
    ADD_ACODEC( "A52/AC-3", "a52" )
    ADD_ACODEC( "Vorbis", "vorb" )
    ADD_ACODEC( "Flac", "flac" )
    ADD_ACODEC( "Speex", "spx" )
    ADD_ACODEC( "WAV", "s16l" )
    ADD_ACODEC( "WMA", "wma" )

#define ADD_SCALING( factor ) ui.vScaleBox->addItem( factor );
    ADD_SCALING( "1" )
    ADD_SCALING( "0.25" )
    ADD_SCALING( "0.5" )
    ADD_SCALING( "0.75" )
    ADD_SCALING( "1.25" )
    ADD_SCALING( "1.5" )
    ADD_SCALING( "1.75" )
    ADD_SCALING( "2" )

#define ADD_SAMPLERATE( sample ) ui.aSampleBox->addItem( sample );
    ADD_SAMPLERATE( "11250" )
    ADD_SAMPLERATE( "22500" )
    ADD_SAMPLERATE( "44100" )
    ADD_SAMPLERATE( "48000" )

#define ADD_SCODEC( name, fourcc ) ui.subsCodecBox->addItem( name, QVariant( fourcc ) );
    ADD_SCODEC( "DVB subtitle", "dvbs" )
    ADD_SCODEC( "T.140", "t140" )
}

void VLCProfileEditor::fillProfile( QString qs )
{
    QStringList options = qs.split( ";" );
    if( options.size() < 16 )
        return;

    ui.transcodeVideo->setChecked( options[1].toInt() );
    ui.transcodeAudio->setChecked( options[2].toInt() );
    ui.transcodeSubs->setChecked( options[3].toInt() );

    ui.vCodecBox->setCurrentIndex( ui.vCodecBox->findData( options[4] ) );
    ui.vBitrateSpin->setValue( options[5].toInt() );
    ui.vScaleBox->setEditText( options[6] );
    ui.vFrameBox->setValue( options[7].toDouble() );
    ui.widthBox->setValue( options[8].toInt() );
    ui.heightBox->setValue( options[9].toInt() );

    ui.aCodecBox->setCurrentIndex( ui.aCodecBox->findData( options[10] ) );
    ui.aBitrateSpin->setValue( options[11].toInt() );
    ui.aChannelsSpin->setValue( options[12].toInt() );
    ui.aSampleBox->setCurrentIndex( ui.aSampleBox->findText( options[13] ) );

    ui.subsCodecBox->setCurrentIndex( ui.subsCodecBox->findData( options[14] ) );
    ui.subsOverlay->setChecked( options[15].toInt() );
}

void VLCProfileEditor::setVTranscodeOptions( bool b_trans )
{
    ui.vCodecLabel->setEnabled( b_trans );
    ui.vCodecBox->setEnabled( b_trans );
    ui.vBitrateLabel->setEnabled( b_trans );
    ui.vBitrateSpin->setEnabled( b_trans );
    ui.vScaleLabel->setEnabled( b_trans );
    ui.vScaleBox->setEnabled( b_trans );
    ui.heightBox->setEnabled( b_trans );
    ui.heightLabel->setEnabled( b_trans );
    ui.widthBox->setEnabled( b_trans );
    ui.widthLabel->setEnabled( b_trans );
    ui.vFrameBox->setEnabled( b_trans );
    ui.vFrameLabel->setEnabled( b_trans );
}

void VLCProfileEditor::setATranscodeOptions( bool b_trans )
{
    ui.aCodecLabel->setEnabled( b_trans );
    ui.aCodecBox->setEnabled( b_trans );
    ui.aBitrateLabel->setEnabled( b_trans );
    ui.aBitrateSpin->setEnabled( b_trans );
    ui.aChannelsLabel->setEnabled( b_trans );
    ui.aChannelsSpin->setEnabled( b_trans );
    ui.aSampleLabel->setEnabled( b_trans );
    ui.aSampleBox->setEnabled( b_trans );
}

void VLCProfileEditor::setSTranscodeOptions( bool b_trans )
{
    ui.subsCodecBox->setEnabled( b_trans );
    ui.subsOverlay->setEnabled( b_trans );
}

void VLCProfileEditor::close()
{
    if( ui.profileLine->text().isEmpty() )
    {
        QMessageBox::warning( this, qtr(" Profile Name Missing" ),
                qtr( "You must set a name for the profile." ) );
        ui.profileLine->setFocus();
        return;
    }
    name = ui.profileLine->text();

    accept();
}

QString VLCProfileEditor::transcodeValue()
{
#define SMUX( x, txt ) if( ui.x->isChecked() ) muxValue =  txt; else
    SMUX( PSMux, "ps" )
    SMUX( TSMux, "ts" )
    SMUX( MPEG1Mux, "mpeg1" )
    SMUX( OggMux, "ogg" )
    SMUX( ASFMux, "asf" )
    SMUX( MOVMux, "mp4" )
    SMUX( WAVMux, "wav" )
    SMUX( RAWMux, "raw" )
    SMUX( FLVMux, "flv" )
    SMUX( MKVMux, "mkv" )
    SMUX( AVIMux, "avi" )
    SMUX( MJPEGMux, "mjpg" );

#define currentData( box ) box->itemData( box->currentIndex() )
    QStringList transcodeMRL;
    transcodeMRL
            << muxValue

            << QString::number( ui.transcodeVideo->isChecked() )
            << QString::number( ui.transcodeAudio->isChecked() )
            << QString::number( ui.transcodeSubs->isChecked() )

            << currentData( ui.vCodecBox ).toString()
            << QString::number( ui.vBitrateSpin->value() )
            << ui.vScaleBox->currentText()
            << QString::number( ui.vFrameBox->value() )
            << QString::number( ui.widthBox->value() )
            << QString::number( ui.heightBox->value() )

            << currentData( ui.aCodecBox ).toString()
            << QString::number( ui.aBitrateSpin->value() )
            << QString::number( ui.aChannelsSpin->value() )
            << ui.aSampleBox->currentText()

            << currentData( ui.subsCodecBox ).toString()
            << QString::number( ui.subsOverlay->isChecked() );

    return transcodeMRL.join( ";" );
}

<commit_msg>Qt: Sout Profiles: be sure to set a mux.<commit_after>/*****************************************************************************
 * profile_selector.cpp : A small profile selector and editor
 ****************************************************************************
 * Copyright (C) 2009 the VideoLAN team
 * $Id$
 *
 * Authors: Jean-Baptiste Kempf <jb@videolan.org>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
 *****************************************************************************/

#include "components/sout/profile_selector.hpp"
#include "components/sout/profiles.hpp"
#include "dialogs/sout.hpp"

#include <QHBoxLayout>
#include <QToolButton>
#include <QComboBox>
#include <QLabel>
#include <QMessageBox>

VLCProfileSelector::VLCProfileSelector( QWidget *_parent ): QWidget( _parent )
{
    QHBoxLayout *layout = new QHBoxLayout( this );

    QLabel *prLabel = new QLabel( qtr( "Profile"), this );
    layout->addWidget( prLabel );

    profileBox = new QComboBox( this );
    layout->addWidget( profileBox );

    QToolButton *editButton = new QToolButton( this );
    editButton->setIcon( QIcon( ":/preferences" ) );
    editButton->setToolTip( qtr( "Edit selected profile" ) );
    layout->addWidget( editButton );

    QToolButton *deleteButton = new QToolButton( this );
    deleteButton->setIcon( QIcon( ":/clear" ) );
    deleteButton->setToolTip( qtr( "Delete selected profile" ) );
    layout->addWidget( deleteButton );

    QToolButton *newButton = new QToolButton( this );
    newButton->setIcon( QIcon( ":/new" ) );
    newButton->setToolTip( qtr( "Create a new profile" ) );
    layout->addWidget(newButton);

    BUTTONACT( newButton, newProfile() );
    BUTTONACT( editButton, editProfile() );
    BUTTONACT( deleteButton, deleteProfile() );
    fillProfilesCombo();

    CONNECT( profileBox, activated( int ),
             this, updateOptions( int ) );

    updateOptions( 0 );
}

inline void VLCProfileSelector::fillProfilesCombo()
{
    QSettings settings(
#ifdef WIN32
            QSettings::IniFormat,
#else
            QSettings::NativeFormat,
#endif
            QSettings::UserScope, "vlc", "vlc-qt-interface" );

    int i_size = settings.beginReadArray( "codecs-profiles" );

    for( int i = 0; i < i_size; i++ )
    {
        settings.setArrayIndex( i );
        if( settings.value( "Profile-Name" ).toString().isEmpty() ) continue;
        profileBox->addItem( settings.value( "Profile-Name" ).toString(),
                settings.value( "Profile-Value" ) );
    }
    if( i_size == 0 )
    {
        for( int i = 0; i < NB_PROFILE; i++ )
        {
            profileBox->addItem( video_profile_name_list[i],
                                 video_profile_value_list[i] );
        }
    }
    settings.endArray();
}

void VLCProfileSelector::newProfile()
{
    editProfile( "", "" );
}

void VLCProfileSelector::editProfile()
{
    editProfile( profileBox->currentText(),
                 profileBox->itemData( profileBox->currentIndex() ).toString() );
}

void VLCProfileSelector::editProfile( QString qs, QString value )
{
    VLCProfileEditor *editor = new VLCProfileEditor( qs, value, this );

    if( QDialog::Accepted == editor->exec() )
    {
        if( qs.isEmpty() )
            profileBox->addItem( editor->name, QVariant( editor->transcodeValue() ) );
        else
        {
            int i_profile = profileBox->findText( qs );
            profileBox->setItemText( i_profile, editor->name );
            profileBox->setItemData( i_profile, QVariant( editor->transcodeValue() ) );
        }
    }
    delete editor;

    saveProfiles();
    emit optionsChanged();
}

void VLCProfileSelector::deleteProfile()
{
    profileBox->removeItem( profileBox->currentIndex() );
}

void VLCProfileSelector::saveProfiles()
{
    QSettings settings(
#ifdef WIN32
            QSettings::IniFormat,
#else
            QSettings::NativeFormat,
#endif
            QSettings::UserScope, "vlc", "vlc-qt-interface" );

    settings.beginWriteArray( "codecs-profiles" );
    for( int i = 0; i < profileBox->count(); i++ )
    {
        settings.setArrayIndex( i );
        settings.setValue( "Profile-Name", profileBox->itemText( i ) );
        settings.setValue( "Profile-Value", profileBox->itemData( i ).toString() );
    }
    settings.endArray();
}

void VLCProfileSelector::updateOptions( int i )
{
    QStringList options = profileBox->itemData( i ).toString().split( ";" );
    if( options.size() < 16 )
        return;

    mux = options[0];

    SoutMrl smrl;
    if( options[1].toInt() || options[2].toInt() )
    {
        smrl.begin( "transcode" );

        if( options[1].toInt() )
        {
            smrl.option( "vcodec", options[4] );
            smrl.option( "vb", options[5].toInt() );
            smrl.option( "scale", options[6] );
            smrl.option( "fps", options[7] );
            smrl.option( "width", options[8].toInt() );
            smrl.option( "height", options[9].toInt() );
        }

        if( options[2].toInt() )
        {
            smrl.option( "acodec", options[10] );
            smrl.option( "ab", options[11].toInt() );
            smrl.option( "channels", options[12].toInt() );
            smrl.option( "samplerate", options[13].toInt() );
        }

        if( options[3].toInt() )
        {
            smrl.option( "scodec", options[14] );
            if( options[15].toInt() )
                smrl.option( "soverlay" );
        }

        smrl.end();

        transcode = smrl.getMrl();
    }
    else
        transcode = "";
    emit optionsChanged();
}

/**
 * VLCProfileEditor
 **/
VLCProfileEditor::VLCProfileEditor( QString qs_name, QString value,
        QWidget *_parent )
                 : QVLCDialog( _parent, NULL )
{
    ui.setupUi( this );
    if( !qs_name.isEmpty() )
    {
        ui.profileLine->setText( qs_name );
        ui.profileLine->setReadOnly( true );
    }
    registerCodecs();
    CONNECT( ui.transcodeVideo, toggled( bool ),
            this, setVTranscodeOptions( bool ) );
    CONNECT( ui.transcodeAudio, toggled( bool ),
            this, setATranscodeOptions( bool ) );
    CONNECT( ui.transcodeSubs, toggled( bool ),
            this, setSTranscodeOptions( bool ) );
    setVTranscodeOptions( false );
    setATranscodeOptions( false );
    setSTranscodeOptions( false );

    QPushButton *saveButton = new QPushButton( qtr( "Save" ) );
    ui.buttonBox->addButton( saveButton, QDialogButtonBox::AcceptRole );
    BUTTONACT( saveButton, close() );
    QPushButton *cancelButton = new QPushButton( qtr( "Cancel" ) );
    ui.buttonBox->addButton( cancelButton, QDialogButtonBox::RejectRole );
    BUTTONACT( cancelButton, reject() );

    fillProfile( value );
}

inline void VLCProfileEditor::registerCodecs()
{

#define ADD_VCODEC( name, fourcc ) ui.vCodecBox->addItem( name, QVariant( fourcc ) );
    ADD_VCODEC( "MPEG-1", "mp1v" )
    ADD_VCODEC( "MPEG-2", "mp2v" )
    ADD_VCODEC( "MPEG-4", "mp4v" )
    ADD_VCODEC( "DIVX 1" , "DIV1" )
    ADD_VCODEC( "DIVX 2" , "DIV2" )
    ADD_VCODEC( "DIVX 3" , "DIV3" )
    ADD_VCODEC( "H-263", "H263" )
    ADD_VCODEC( "H-264", "h264" )
    ADD_VCODEC( "WMV1", "WMV1" )
    ADD_VCODEC( "WMV2" , "WMV2" )
    ADD_VCODEC( "M-JPEG", "MJPG" )
    ADD_VCODEC( "Theora", "theo" )
    ADD_VCODEC( "Dirac", "drac" )

#define ADD_ACODEC( name, fourcc ) ui.aCodecBox->addItem( name, QVariant( fourcc ) );
    ADD_ACODEC( "MPEG Audio", "mpga" )
    ADD_ACODEC( "MP3", "mp3" )
    ADD_ACODEC( "MPEG 4 Audio ( AAC )", "mp4a" )
    ADD_ACODEC( "A52/AC-3", "a52" )
    ADD_ACODEC( "Vorbis", "vorb" )
    ADD_ACODEC( "Flac", "flac" )
    ADD_ACODEC( "Speex", "spx" )
    ADD_ACODEC( "WAV", "s16l" )
    ADD_ACODEC( "WMA", "wma" )

#define ADD_SCALING( factor ) ui.vScaleBox->addItem( factor );
    ADD_SCALING( "1" )
    ADD_SCALING( "0.25" )
    ADD_SCALING( "0.5" )
    ADD_SCALING( "0.75" )
    ADD_SCALING( "1.25" )
    ADD_SCALING( "1.5" )
    ADD_SCALING( "1.75" )
    ADD_SCALING( "2" )

#define ADD_SAMPLERATE( sample ) ui.aSampleBox->addItem( sample );
    ADD_SAMPLERATE( "11250" )
    ADD_SAMPLERATE( "22500" )
    ADD_SAMPLERATE( "44100" )
    ADD_SAMPLERATE( "48000" )

#define ADD_SCODEC( name, fourcc ) ui.subsCodecBox->addItem( name, QVariant( fourcc ) );
    ADD_SCODEC( "DVB subtitle", "dvbs" )
    ADD_SCODEC( "T.140", "t140" )
}

void VLCProfileEditor::fillProfile( QString qs )
{
    QStringList options = qs.split( ";" );
    if( options.size() < 16 )
        return;

    ui.transcodeVideo->setChecked( options[1].toInt() );
    ui.transcodeAudio->setChecked( options[2].toInt() );
    ui.transcodeSubs->setChecked( options[3].toInt() );

    ui.vCodecBox->setCurrentIndex( ui.vCodecBox->findData( options[4] ) );
    ui.vBitrateSpin->setValue( options[5].toInt() );
    ui.vScaleBox->setEditText( options[6] );
    ui.vFrameBox->setValue( options[7].toDouble() );
    ui.widthBox->setValue( options[8].toInt() );
    ui.heightBox->setValue( options[9].toInt() );

    ui.aCodecBox->setCurrentIndex( ui.aCodecBox->findData( options[10] ) );
    ui.aBitrateSpin->setValue( options[11].toInt() );
    ui.aChannelsSpin->setValue( options[12].toInt() );
    ui.aSampleBox->setCurrentIndex( ui.aSampleBox->findText( options[13] ) );

    ui.subsCodecBox->setCurrentIndex( ui.subsCodecBox->findData( options[14] ) );
    ui.subsOverlay->setChecked( options[15].toInt() );
}

void VLCProfileEditor::setVTranscodeOptions( bool b_trans )
{
    ui.vCodecLabel->setEnabled( b_trans );
    ui.vCodecBox->setEnabled( b_trans );
    ui.vBitrateLabel->setEnabled( b_trans );
    ui.vBitrateSpin->setEnabled( b_trans );
    ui.vScaleLabel->setEnabled( b_trans );
    ui.vScaleBox->setEnabled( b_trans );
    ui.heightBox->setEnabled( b_trans );
    ui.heightLabel->setEnabled( b_trans );
    ui.widthBox->setEnabled( b_trans );
    ui.widthLabel->setEnabled( b_trans );
    ui.vFrameBox->setEnabled( b_trans );
    ui.vFrameLabel->setEnabled( b_trans );
}

void VLCProfileEditor::setATranscodeOptions( bool b_trans )
{
    ui.aCodecLabel->setEnabled( b_trans );
    ui.aCodecBox->setEnabled( b_trans );
    ui.aBitrateLabel->setEnabled( b_trans );
    ui.aBitrateSpin->setEnabled( b_trans );
    ui.aChannelsLabel->setEnabled( b_trans );
    ui.aChannelsSpin->setEnabled( b_trans );
    ui.aSampleLabel->setEnabled( b_trans );
    ui.aSampleBox->setEnabled( b_trans );
}

void VLCProfileEditor::setSTranscodeOptions( bool b_trans )
{
    ui.subsCodecBox->setEnabled( b_trans );
    ui.subsOverlay->setEnabled( b_trans );
}

void VLCProfileEditor::close()
{
    if( ui.profileLine->text().isEmpty() )
    {
        QMessageBox::warning( this, qtr(" Profile Name Missing" ),
                qtr( "You must set a name for the profile." ) );
        ui.profileLine->setFocus();
        return;
    }
    name = ui.profileLine->text();

    accept();
}

QString VLCProfileEditor::transcodeValue()
{
#define SMUX( x, txt ) if( ui.x->isChecked() ) muxValue =  txt; else
    SMUX( PSMux, "ps" )
    SMUX( TSMux, "ts" )
    SMUX( MPEG1Mux, "mpeg1" )
    SMUX( OggMux, "ogg" )
    SMUX( ASFMux, "asf" )
    SMUX( MOVMux, "mp4" )
    SMUX( WAVMux, "wav" )
    SMUX( RAWMux, "raw" )
    SMUX( FLVMux, "flv" )
    SMUX( MKVMux, "mkv" )
    SMUX( AVIMux, "avi" )
    SMUX( MJPEGMux, "mjpg" );

#define currentData( box ) box->itemData( box->currentIndex() )
    QStringList transcodeMRL;
    transcodeMRL
            << muxValue

            << QString::number( ui.transcodeVideo->isChecked() )
            << QString::number( ui.transcodeAudio->isChecked() )
            << QString::number( ui.transcodeSubs->isChecked() )

            << currentData( ui.vCodecBox ).toString()
            << QString::number( ui.vBitrateSpin->value() )
            << ui.vScaleBox->currentText()
            << QString::number( ui.vFrameBox->value() )
            << QString::number( ui.widthBox->value() )
            << QString::number( ui.heightBox->value() )

            << currentData( ui.aCodecBox ).toString()
            << QString::number( ui.aBitrateSpin->value() )
            << QString::number( ui.aChannelsSpin->value() )
            << ui.aSampleBox->currentText()

            << currentData( ui.subsCodecBox ).toString()
            << QString::number( ui.subsOverlay->isChecked() );

    return transcodeMRL.join( ";" );
}

<|endoftext|>


<commit_before>/*************** <auto-copyright.pl BEGIN do not edit this line> **************
 *
 * VR Juggler is (C) Copyright 1998-2003 by Iowa State University
 *
 * Original Authors:
 *   Allen Bierbaum, Christopher Just,
 *   Patrick Hartling, Kevin Meinert,
 *   Carolina Cruz-Neira, Albert Baker
 *
 * 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., 59 Temple Place - Suite 330,
 * Boston, MA 02111-1307, USA.
 *
 * -----------------------------------------------------------------
 * File:          $RCSfile$
 * Date modified: $Date$
 * Version:       $Revision$
 * -----------------------------------------------------------------
 *
 *************** <auto-copyright.pl END do not edit this line> ***************/

#include <jccl/jcclConfig.h>
#include <jccl/Util/Debug.h>
#include <jccl/Config/ElementFactory.h>
#include <jccl/Config/ConfigDefinitionReader.h>
#include <jccl/Config/ParseUtil.h>

#include <boost/filesystem/path.hpp>
#include <boost/filesystem/operations.hpp>
#include <boost/filesystem/exception.hpp>

namespace fs = boost::filesystem;

namespace jccl
{

   ElementFactory::ElementFactory()
   {
      // Create global context
      mGlobalContext = cppdom::ContextPtr(new cppdom::Context);
   }

   void ElementFactory::loadDefs(const std::string& path)
   {
      // Split the path on the native separator character
      std::vector<std::string> search_path;
      std::string::size_type sep_index = 0;
      while (sep_index != std::string::npos)
      {
         std::string::size_type next_sep_index = path.find_first_of(":;", sep_index);
         const std::string dir_str = path.substr(sep_index, next_sep_index - sep_index);
         vprDEBUG(jcclDBG_CONFIG, vprDBG_CONFIG_LVL)
            << "Adding directory to search path: " << dir_str << "\n"
            << vprDEBUG_FLUSH;
         search_path.push_back(dir_str);

         if (next_sep_index == std::string::npos)
         {
            break;
         }
         sep_index = next_sep_index + 1;
      }

      // Search each directory in the path for definition files
      for (std::vector<std::string>::const_iterator itr = search_path.begin();
           itr != search_path.end();
           ++itr)
      {
         const std::string dir_str = demangleFileName(*itr, "");
         try
         {
            fs::path dir(dir_str, boost::filesystem::native);

            if (fs::exists(dir) && fs::is_directory(dir))
            {
               fs::directory_iterator end_itr;
               for (fs::directory_iterator file(dir); file != end_itr; ++file)
               {
                  try
                  {
                     // Ignore directories
                     if (!fs::is_directory(*file))
                     {
                        // Only accept files with a .jdef extension
                        const std::string def_ext = ".jdef";
                        const std::string::size_type pos = file->leaf().size() - def_ext.size();
                        const std::string file_ext = file->leaf().substr(pos);
                        if (file_ext == def_ext)
                        {
                           vprDEBUG(jcclDBG_CONFIG, vprDBG_VERB_LVL)
                              << "Loading '" << file->native_file_string()
                              << "'\n" << vprDEBUG_FLUSH;
                           loadDef(file->native_file_string());
                        }
                     }
                  }
                  catch (fs::filesystem_error& err)
                  {
                     vprDEBUG(jcclDBG_CONFIG, vprDBG_WARNING_LVL)
                        << "Failed to read '" << file->native_file_string()
                        << "': " << err.what() << std::endl << vprDEBUG_FLUSH;
                  }
               }
            }
         }
         catch (fs::filesystem_error& err)
         {
            vprDEBUG(jcclDBG_CONFIG, vprDBG_WARNING_LVL)
               << "Failed to load definitions in directory '"
               << (*itr) << "': " << err.what() << "\n"
               << vprDEBUG_FLUSH;
         }
      }
   }

   // Adds definitions in file 'file_name' to the factory.
   bool ElementFactory::loadDef(const std::string& file_name,
                                const std::string& parentFile)
   {

      // Attempt to read all the definitions from the file
      try
      {
         const std::string abs_filename = demangleFileName(file_name, parentFile);
         ConfigDefinitionReader reader;
         std::vector<ConfigDefinitionPtr> defs = reader.read(abs_filename);

         // Add the definitions to the repository
         for (std::vector<ConfigDefinitionPtr>::const_iterator itr = defs.begin();
              itr != defs.end();
              ++itr)
         {
            mRepository.add(*itr);
         }
      }
      catch (std::runtime_error& e)
      {
         vprDEBUG(vprDBG_ERROR, vprDBG_CRITICAL_LVL)
            << "Failed to load definition file: '" << file_name.c_str()
            << ": " << e.what() << "'.\n" << vprDEBUG_FLUSH;
         return false;
      }

      vprDEBUG(jcclDBG_CONFIG,vprDBG_CONFIG_LVL)
         << "Loaded definition file: '" << file_name.c_str() << "'.\n"
         << vprDEBUG_FLUSH;

      return true;
   }

   ConfigDefinitionPtr ElementFactory::getConfigDefinition(const std::string& token,
                                                           unsigned int version)
   {
      return mRepository.get(token, version);
   }

   // Creates an Element using the named definition.
   ConfigElementPtr ElementFactory::createElement(const std::string& defToken,
                                                  unsigned int version)
   {
      return createElement(mRepository.get(defToken, version));
   }

   // Creates an element using the given config definition.
   ConfigElementPtr ElementFactory::createElement(ConfigDefinitionPtr d)
   {
      if ( d.get() != NULL )
      {
         d->assertValid();
         return ConfigElementPtr(new ConfigElement(d));
      }
      else
      {
         return ConfigElementPtr();
      }
   }

   // Get the global XML context that we are using system-wide.
   cppdom::ContextPtr ElementFactory::getXMLContext()
   {
      vprASSERT(mGlobalContext.get() != NULL);
      return mGlobalContext;
   }

   // Creates a new (empty) XML node using global context.
   cppdom::NodePtr ElementFactory::createXMLNode()
   {
      return cppdom::NodePtr(new cppdom::Node(getXMLContext()));
   }

   // Creates a new (empty) XML document using global context.
   cppdom::DocumentPtr ElementFactory::createXMLDocument()
   {
      return cppdom::DocumentPtr(new cppdom::Document(getXMLContext()));
   }

   vprSingletonImp(ElementFactory);

} // namespace jccl
<commit_msg>Help with debugging of bad definition pointer<commit_after>/*************** <auto-copyright.pl BEGIN do not edit this line> **************
 *
 * VR Juggler is (C) Copyright 1998-2003 by Iowa State University
 *
 * Original Authors:
 *   Allen Bierbaum, Christopher Just,
 *   Patrick Hartling, Kevin Meinert,
 *   Carolina Cruz-Neira, Albert Baker
 *
 * 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., 59 Temple Place - Suite 330,
 * Boston, MA 02111-1307, USA.
 *
 * -----------------------------------------------------------------
 * File:          $RCSfile$
 * Date modified: $Date$
 * Version:       $Revision$
 * -----------------------------------------------------------------
 *
 *************** <auto-copyright.pl END do not edit this line> ***************/

#include <jccl/jcclConfig.h>
#include <jccl/Util/Debug.h>
#include <jccl/Config/ElementFactory.h>
#include <jccl/Config/ConfigDefinitionReader.h>
#include <jccl/Config/ParseUtil.h>

#include <boost/filesystem/path.hpp>
#include <boost/filesystem/operations.hpp>
#include <boost/filesystem/exception.hpp>

namespace fs = boost::filesystem;

namespace jccl
{

   ElementFactory::ElementFactory()
   {
      // Create global context
      mGlobalContext = cppdom::ContextPtr(new cppdom::Context);
   }

   void ElementFactory::loadDefs(const std::string& path)
   {
      // Split the path on the native separator character
      std::vector<std::string> search_path;
      std::string::size_type sep_index = 0;
      while (sep_index != std::string::npos)
      {
         std::string::size_type next_sep_index = path.find_first_of(":;", sep_index);
         const std::string dir_str = path.substr(sep_index, next_sep_index - sep_index);
         vprDEBUG(jcclDBG_CONFIG, vprDBG_CONFIG_LVL)
            << "Adding directory to search path: " << dir_str << "\n"
            << vprDEBUG_FLUSH;
         search_path.push_back(dir_str);

         if (next_sep_index == std::string::npos)
         {
            break;
         }
         sep_index = next_sep_index + 1;
      }

      // Search each directory in the path for definition files
      for (std::vector<std::string>::const_iterator itr = search_path.begin();
           itr != search_path.end();
           ++itr)
      {
         const std::string dir_str = demangleFileName(*itr, "");
         try
         {
            fs::path dir(dir_str, boost::filesystem::native);

            if (fs::exists(dir) && fs::is_directory(dir))
            {
               fs::directory_iterator end_itr;
               for (fs::directory_iterator file(dir); file != end_itr; ++file)
               {
                  try
                  {
                     // Ignore directories
                     if (!fs::is_directory(*file))
                     {
                        // Only accept files with a .jdef extension
                        const std::string def_ext = ".jdef";
                        const std::string::size_type pos = file->leaf().size() - def_ext.size();
                        const std::string file_ext = file->leaf().substr(pos);
                        if (file_ext == def_ext)
                        {
                           vprDEBUG(jcclDBG_CONFIG, vprDBG_VERB_LVL)
                              << "Loading '" << file->native_file_string()
                              << "'\n" << vprDEBUG_FLUSH;
                           loadDef(file->native_file_string());
                        }
                     }
                  }
                  catch (fs::filesystem_error& err)
                  {
                     vprDEBUG(jcclDBG_CONFIG, vprDBG_WARNING_LVL)
                        << "Failed to read '" << file->native_file_string()
                        << "': " << err.what() << std::endl << vprDEBUG_FLUSH;
                  }
               }
            }
         }
         catch (fs::filesystem_error& err)
         {
            vprDEBUG(jcclDBG_CONFIG, vprDBG_WARNING_LVL)
               << "Failed to load definitions in directory '"
               << (*itr) << "': " << err.what() << "\n"
               << vprDEBUG_FLUSH;
         }
      }
   }

   // Adds definitions in file 'file_name' to the factory.
   bool ElementFactory::loadDef(const std::string& file_name,
                                const std::string& parentFile)
   {

      // Attempt to read all the definitions from the file
      try
      {
         const std::string abs_filename = demangleFileName(file_name, parentFile);
         ConfigDefinitionReader reader;
         std::vector<ConfigDefinitionPtr> defs = reader.read(abs_filename);

         // Add the definitions to the repository
         for (std::vector<ConfigDefinitionPtr>::const_iterator itr = defs.begin();
              itr != defs.end();
              ++itr)
         {
            ConfigDefinitionPtr cfg_def = (*itr);
            mRepository.add(cfg_def);
         }
      }
      catch (std::runtime_error& e)
      {
         vprDEBUG(vprDBG_ERROR, vprDBG_CRITICAL_LVL)
            << "Failed to load definition file: '" << file_name.c_str()
            << ": " << e.what() << "'.\n" << vprDEBUG_FLUSH;
         return false;
      }

      vprDEBUG(jcclDBG_CONFIG,vprDBG_CONFIG_LVL)
         << "Loaded definition file: '" << file_name.c_str() << "'.\n"
         << vprDEBUG_FLUSH;

      return true;
   }

   ConfigDefinitionPtr ElementFactory::getConfigDefinition(const std::string& token,
                                                           unsigned int version)
   {
      return mRepository.get(token, version);
   }

   // Creates an Element using the named definition.
   ConfigElementPtr ElementFactory::createElement(const std::string& defToken,
                                                  unsigned int version)
   {
      return createElement(mRepository.get(defToken, version));
   }

   // Creates an element using the given config definition.
   ConfigElementPtr ElementFactory::createElement(ConfigDefinitionPtr d)
   {
      if ( d.get() != NULL )
      {
         d->assertValid();
         return ConfigElementPtr(new ConfigElement(d));
      }
      else
      {
         return ConfigElementPtr();
      }
   }

   // Get the global XML context that we are using system-wide.
   cppdom::ContextPtr ElementFactory::getXMLContext()
   {
      vprASSERT(mGlobalContext.get() != NULL);
      return mGlobalContext;
   }

   // Creates a new (empty) XML node using global context.
   cppdom::NodePtr ElementFactory::createXMLNode()
   {
      return cppdom::NodePtr(new cppdom::Node(getXMLContext()));
   }

   // Creates a new (empty) XML document using global context.
   cppdom::DocumentPtr ElementFactory::createXMLDocument()
   {
      return cppdom::DocumentPtr(new cppdom::Document(getXMLContext()));
   }

   vprSingletonImp(ElementFactory);

} // namespace jccl
<|endoftext|>


<commit_before>/******************************************************************************
*       SOFA, Simulation Open-Framework Architecture, version 1.0 beta 4      *
*                (c) 2006-2009 MGH, INRIA, USTL, UJF, CNRS                    *
*                                                                             *
* This library is free software; you can redistribute it and/or modify it     *
* under the terms of the GNU Lesser General Public License as published by    *
* the Free Software Foundation; either version 2.1 of the License, or (at     *
* your option) any later version.                                             *
*                                                                             *
* This library is distributed in the hope that it will be useful, but WITHOUT *
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or       *
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License *
* for more details.                                                           *
*                                                                             *
* You should have received a copy of the GNU Lesser General Public License    *
* along with this library; if not, write to the Free Software Foundation,     *
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA.          *
*******************************************************************************
*                               SOFA :: Modules                               *
*                                                                             *
* Authors: The SOFA Team and external contributors (see Authors.txt)          *
*                                                                             *
* Contact information: contact@sofa-framework.org                             *
******************************************************************************/
#ifndef SOFA_COMPONENT_COLLISION_FRICTIONCONTACT_INL
#define SOFA_COMPONENT_COLLISION_FRICTIONCONTACT_INL

#include <sofa/component/collision/FrictionContact.h>
#include <sofa/component/collision/DefaultContactManager.h>
#include <iostream>

namespace sofa
{

namespace component
{

namespace collision
{

using namespace sofa::defaulttype;
using namespace core::componentmodel::collision;
using simulation::Node;

template < class TCollisionModel1, class TCollisionModel2 >
FrictionContact<TCollisionModel1,TCollisionModel2>::FrictionContact(CollisionModel1* model1, CollisionModel2* model2, Intersection* intersectionMethod)
    : model1(model1), model2(model2), intersectionMethod(intersectionMethod), c(NULL), parent(NULL)
    , mu (initData(&mu, 0.8, "mu", "friction coefficient (0 for frictionless contacts)"))
{
    selfCollision = ((core::CollisionModel*)model1 == (core::CollisionModel*)model2);
    mapper1.setCollisionModel(model1);
    if (!selfCollision) mapper2.setCollisionModel(model2);
}

template < class TCollisionModel1, class TCollisionModel2 >
FrictionContact<TCollisionModel1,TCollisionModel2>::~FrictionContact()
{
}
template < class TCollisionModel1, class TCollisionModel2 >
void FrictionContact<TCollisionModel1,TCollisionModel2>::cleanup()
{
    if (c!=NULL)
    {
        c->cleanup();
        if (parent!=NULL)
            parent->removeObject(c);
        delete c;
        parent = NULL;
        c = NULL;
        mapper1.cleanup();
        if (!selfCollision) mapper2.cleanup();
    }
}

template < class TCollisionModel1, class TCollisionModel2 >
void FrictionContact<TCollisionModel1,TCollisionModel2>::setDetectionOutputs(OutputVector* o)
{
    TOutputVector& outputs = *static_cast<TOutputVector*>(o);
    // We need to remove duplicate contacts
    const double minDist2 = 0.00000001f;
    std::vector<DetectionOutput*> contacts;
    contacts.reserve(outputs.size());

    const double mu = this->mu.getValue();
    // Checks if friction is considered
    if (mu < 0.0 || mu > 1.0)
        serr << sendl << "Error: mu has to take values between 0.0 and 1.0" << sendl;

    int SIZE = outputs.size();

    for (int cpt=0; cpt<SIZE; cpt++)
    {
        DetectionOutput* o = &outputs[cpt];

        bool found = false;
        for (unsigned int i=0; i<contacts.size() && !found; i++)
        {
            DetectionOutput* p = contacts[i];
            if ((o->point[0]-p->point[0]).norm2()+(o->point[1]-p->point[1]).norm2() < minDist2)
                found = true;
        }

        if (!found)
            contacts.push_back(o);
    }

    if (contacts.size()<outputs.size())
    {
        //sout << "Removed " << (outputs.size()-contacts.size()) <<" / " << outputs.size() << " collision points." << sendl;
    }

    if (c==NULL)
    {
        // Get the mechanical model from mapper1 to fill the constraint vector
        MechanicalState1* mmodel1 = mapper1.createMapping();
        // Get the mechanical model from mapper2 to fill the constraints vector
        MechanicalState2* mmodel2 = selfCollision ? mmodel1 : mapper2.createMapping();
        c = new constraint::UnilateralInteractionConstraint<Vec3Types>(mmodel1, mmodel2);
        c->setName( getName() );
    }

    int size = contacts.size();
    c->clear(size);
    if (selfCollision) mapper1.resize(2*size);
    else
    {
        mapper1.resize(size);
        mapper2.resize(size);
    }
    int i = 0;
    const double d0 = intersectionMethod->getContactDistance() + model1->getProximity() + model2->getProximity(); // - 0.001;
    std::vector< std::pair< std::pair<int, int>, double > > mappedContacts;
    mappedContacts.resize(contacts.size());
    for (std::vector<DetectionOutput*>::const_iterator it = contacts.begin(); it!=contacts.end(); it++, i++)
    {
        DetectionOutput* o = *it;
        CollisionElement1 elem1(o->elem.first);
        CollisionElement2 elem2(o->elem.second);
        int index1 = elem1.getIndex();
        int index2 = elem2.getIndex();
        typename DataTypes1::Real r1 = 0.0;
        typename DataTypes2::Real r2 = 0.0;
        //double constraintValue = ((o->point[1] - o->point[0]) * o->normal) - intersectionMethod->getContactDistance();

        // Create mapping for first point
        index1 = mapper1.addPoint(o->point[0], index1, r1);
        // Create mapping for second point
        index2 = selfCollision ? mapper1.addPoint(o->point[1], index2, r2) : mapper2.addPoint(o->point[1], index2, r2);
        double distance = d0 + r1 + r2;

        mappedContacts[i].first.first = index1;
        mappedContacts[i].first.second = index2;
        mappedContacts[i].second = distance;
    }

    // Update mappings
    mapper1.update();
    mapper1.updateXfree();
    if (!selfCollision) mapper2.update();
    if (!selfCollision) mapper2.updateXfree();
    i=0;
    for (std::vector<DetectionOutput*>::const_iterator it = contacts.begin(); it!=contacts.end(); it++, i++)
    {
        DetectionOutput* o = *it;
        int index1 = mappedContacts[i].first.first;
        int index2 = mappedContacts[i].first.second;
        double distance = mappedContacts[i].second;
#if 0
        std::cout << "P0     = " << (*c->getObject1()->getX())[index1];
        if (((*c->getObject1()->getX())[index1] - o->point[0]).norm() > 1.0e-10) std::cout << " ( " << (*c->getObject1()->getX())[index1] - o->point[0] << " )";
        std::cout << std::endl;
        std::cout << "P0free = " << (*c->getObject1()->getXfree())[index1];
#ifdef DETECTIONOUTPUT_FREEMOTION
        if (((*c->getObject1()->getXfree())[index1] - o->freePoint[0]).norm() > 1.0e-10) std::cout << " ( " << (*c->getObject1()->getXfree())[index1] - o->freePoint[0] << " )";
        std::cout << std::endl;
#else
        if (((*c->getObject1()->getXfree())[index1] - o->point[0]).norm() > 1.0e-10) std::cout << " ( " << (*c->getObject1()->getXfree())[index1] - o->point[0] << " )";
        std::cout << std::endl;
#endif

        std::cout << "P1     = " << (*c->getObject2()->getX())[index2];
        if (((*c->getObject2()->getX())[index2] - o->point[1]).norm() > 1.0e-10) std::cout << " ( " << (*c->getObject2()->getX())[index2] - o->point[2] << " )";
        std::cout << std::endl;
        std::cout << "P1free = " << (*c->getObject2()->getXfree())[index2];
#ifdef DETECTIONOUTPUT_FREEMOTION
        if (((*c->getObject2()->getXfree())[index2] - o->freePoint[1]).norm() > 1.0e-10) std::cout << " ( " << (*c->getObject2()->getXfree())[index2] - o->freePoint[1] << " )";
        std::cout << std::endl;
#else
        if (((*c->getObject2()->getXfree())[index2] - o->point[1]).norm() > 1.0e-10) std::cout << " ( " << (*c->getObject2()->getXfree())[index2] - o->point[1] << " )";
        std::cout << std::endl;
#endif
#endif

        // Polynome de Cantor de N� sur N bijectif f(x,y)=((x+y)^2+3x+y)/2
        long index = cantorPolynomia(o->id /*cantorPolynomia(index1, index2)*/,id);
//#ifdef DETECTIONOUTPUT_FREEMOTION
//		c->addContact(mu, o->normal, o->point[1], o->point[0], distance, index1, index2, o->freePoint[1], o->freePoint[0], index);
//#else
        // as we called updateXfree on the mappings, the contact class can now use the Xfree value of the contact points instead of relying on the collision detection method to fill freePoint[0] and freePoint[1]
        //c->addContact(mu, o->normal, o->point[1], o->point[0], distance, index1, index2, index);
        c->addContact(mu, o->normal, distance, index1, index2, index, o->id);
//#endif
    }
}

template < class TCollisionModel1, class TCollisionModel2 >
void FrictionContact<TCollisionModel1,TCollisionModel2>::createResponse(core::objectmodel::BaseContext* group)
{
    if (c!=NULL)
    {
        if (parent!=NULL)
        {
            parent->removeObject(this);
            parent->removeObject(c);
        }
        parent = group;
        if (parent!=NULL)
        {
            //sout << "Attaching contact response to "<<parent->getName()<<sendl;
            parent->addObject(this);
            parent->addObject(c);
        }
    }
}

template < class TCollisionModel1, class TCollisionModel2 >
void FrictionContact<TCollisionModel1,TCollisionModel2>::removeResponse()
{
    if (c!=NULL)
    {
        if (parent!=NULL)
        {
            //sout << "Removing contact response from "<<parent->getName()<<sendl;
            parent->removeObject(this);
            parent->removeObject(c);
        }
        parent = NULL;
    }
}

} // namespace collision

} // namespace component

} // namespace sofa

#endif
<commit_msg>r6469/sofa-dev : BUGFIX: crash in contact points mapping when using MasterContactSolver + CarvingManager, fixed by adding a CollisionResetVisitor before the free motion and resetting the mappers in FrictionContact::removeResponse()<commit_after>/******************************************************************************
*       SOFA, Simulation Open-Framework Architecture, version 1.0 beta 4      *
*                (c) 2006-2009 MGH, INRIA, USTL, UJF, CNRS                    *
*                                                                             *
* This library is free software; you can redistribute it and/or modify it     *
* under the terms of the GNU Lesser General Public License as published by    *
* the Free Software Foundation; either version 2.1 of the License, or (at     *
* your option) any later version.                                             *
*                                                                             *
* This library is distributed in the hope that it will be useful, but WITHOUT *
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or       *
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License *
* for more details.                                                           *
*                                                                             *
* You should have received a copy of the GNU Lesser General Public License    *
* along with this library; if not, write to the Free Software Foundation,     *
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA.          *
*******************************************************************************
*                               SOFA :: Modules                               *
*                                                                             *
* Authors: The SOFA Team and external contributors (see Authors.txt)          *
*                                                                             *
* Contact information: contact@sofa-framework.org                             *
******************************************************************************/
#ifndef SOFA_COMPONENT_COLLISION_FRICTIONCONTACT_INL
#define SOFA_COMPONENT_COLLISION_FRICTIONCONTACT_INL

#include <sofa/component/collision/FrictionContact.h>
#include <sofa/component/collision/DefaultContactManager.h>
#include <iostream>

namespace sofa
{

namespace component
{

namespace collision
{

using namespace sofa::defaulttype;
using namespace core::componentmodel::collision;
using simulation::Node;

template < class TCollisionModel1, class TCollisionModel2 >
FrictionContact<TCollisionModel1,TCollisionModel2>::FrictionContact(CollisionModel1* model1, CollisionModel2* model2, Intersection* intersectionMethod)
    : model1(model1), model2(model2), intersectionMethod(intersectionMethod), c(NULL), parent(NULL)
    , mu (initData(&mu, 0.8, "mu", "friction coefficient (0 for frictionless contacts)"))
{
    selfCollision = ((core::CollisionModel*)model1 == (core::CollisionModel*)model2);
    mapper1.setCollisionModel(model1);
    if (!selfCollision) mapper2.setCollisionModel(model2);
}

template < class TCollisionModel1, class TCollisionModel2 >
FrictionContact<TCollisionModel1,TCollisionModel2>::~FrictionContact()
{
}
template < class TCollisionModel1, class TCollisionModel2 >
void FrictionContact<TCollisionModel1,TCollisionModel2>::cleanup()
{
    if (c!=NULL)
    {
        c->cleanup();
        if (parent!=NULL)
            parent->removeObject(c);
        delete c;
        parent = NULL;
        c = NULL;
        mapper1.cleanup();
        if (!selfCollision) mapper2.cleanup();
    }
}

template < class TCollisionModel1, class TCollisionModel2 >
void FrictionContact<TCollisionModel1,TCollisionModel2>::setDetectionOutputs(OutputVector* o)
{
    TOutputVector& outputs = *static_cast<TOutputVector*>(o);
    // We need to remove duplicate contacts
    const double minDist2 = 0.00000001f;
    std::vector<DetectionOutput*> contacts;
    contacts.reserve(outputs.size());

    const double mu = this->mu.getValue();
    // Checks if friction is considered
    if (mu < 0.0 || mu > 1.0)
        serr << sendl << "Error: mu has to take values between 0.0 and 1.0" << sendl;

    int SIZE = outputs.size();

    for (int cpt=0; cpt<SIZE; cpt++)
    {
        DetectionOutput* o = &outputs[cpt];

        bool found = false;
        for (unsigned int i=0; i<contacts.size() && !found; i++)
        {
            DetectionOutput* p = contacts[i];
            if ((o->point[0]-p->point[0]).norm2()+(o->point[1]-p->point[1]).norm2() < minDist2)
                found = true;
        }

        if (!found)
            contacts.push_back(o);
    }

    if (contacts.size()<outputs.size())
    {
        //sout << "Removed " << (outputs.size()-contacts.size()) <<" / " << outputs.size() << " collision points." << sendl;
    }

    if (c==NULL)
    {
        // Get the mechanical model from mapper1 to fill the constraint vector
        MechanicalState1* mmodel1 = mapper1.createMapping();
        // Get the mechanical model from mapper2 to fill the constraints vector
        MechanicalState2* mmodel2 = selfCollision ? mmodel1 : mapper2.createMapping();
        c = new constraint::UnilateralInteractionConstraint<Vec3Types>(mmodel1, mmodel2);
        c->setName( getName() );
    }

    int size = contacts.size();
    c->clear(size);
    if (selfCollision) mapper1.resize(2*size);
    else
    {
        mapper1.resize(size);
        mapper2.resize(size);
    }
    int i = 0;
    const double d0 = intersectionMethod->getContactDistance() + model1->getProximity() + model2->getProximity(); // - 0.001;
    std::vector< std::pair< std::pair<int, int>, double > > mappedContacts;
    mappedContacts.resize(contacts.size());
    for (std::vector<DetectionOutput*>::const_iterator it = contacts.begin(); it!=contacts.end(); it++, i++)
    {
        DetectionOutput* o = *it;
        CollisionElement1 elem1(o->elem.first);
        CollisionElement2 elem2(o->elem.second);
        int index1 = elem1.getIndex();
        int index2 = elem2.getIndex();
        typename DataTypes1::Real r1 = 0.0;
        typename DataTypes2::Real r2 = 0.0;
        //double constraintValue = ((o->point[1] - o->point[0]) * o->normal) - intersectionMethod->getContactDistance();

        // Create mapping for first point
        index1 = mapper1.addPoint(o->point[0], index1, r1);
        // Create mapping for second point
        index2 = selfCollision ? mapper1.addPoint(o->point[1], index2, r2) : mapper2.addPoint(o->point[1], index2, r2);
        double distance = d0 + r1 + r2;

        mappedContacts[i].first.first = index1;
        mappedContacts[i].first.second = index2;
        mappedContacts[i].second = distance;
    }

    // Update mappings
    mapper1.update();
    mapper1.updateXfree();
    if (!selfCollision) mapper2.update();
    if (!selfCollision) mapper2.updateXfree();
    i=0;
    for (std::vector<DetectionOutput*>::const_iterator it = contacts.begin(); it!=contacts.end(); it++, i++)
    {
        DetectionOutput* o = *it;
        int index1 = mappedContacts[i].first.first;
        int index2 = mappedContacts[i].first.second;
        double distance = mappedContacts[i].second;
#if 0
        std::cout << "P0     = " << (*c->getObject1()->getX())[index1];
        if (((*c->getObject1()->getX())[index1] - o->point[0]).norm() > 1.0e-10) std::cout << " ( " << (*c->getObject1()->getX())[index1] - o->point[0] << " )";
        std::cout << std::endl;
        std::cout << "P0free = " << (*c->getObject1()->getXfree())[index1];
#ifdef DETECTIONOUTPUT_FREEMOTION
        if (((*c->getObject1()->getXfree())[index1] - o->freePoint[0]).norm() > 1.0e-10) std::cout << " ( " << (*c->getObject1()->getXfree())[index1] - o->freePoint[0] << " )";
        std::cout << std::endl;
#else
        if (((*c->getObject1()->getXfree())[index1] - o->point[0]).norm() > 1.0e-10) std::cout << " ( " << (*c->getObject1()->getXfree())[index1] - o->point[0] << " )";
        std::cout << std::endl;
#endif

        std::cout << "P1     = " << (*c->getObject2()->getX())[index2];
        if (((*c->getObject2()->getX())[index2] - o->point[1]).norm() > 1.0e-10) std::cout << " ( " << (*c->getObject2()->getX())[index2] - o->point[2] << " )";
        std::cout << std::endl;
        std::cout << "P1free = " << (*c->getObject2()->getXfree())[index2];
#ifdef DETECTIONOUTPUT_FREEMOTION
        if (((*c->getObject2()->getXfree())[index2] - o->freePoint[1]).norm() > 1.0e-10) std::cout << " ( " << (*c->getObject2()->getXfree())[index2] - o->freePoint[1] << " )";
        std::cout << std::endl;
#else
        if (((*c->getObject2()->getXfree())[index2] - o->point[1]).norm() > 1.0e-10) std::cout << " ( " << (*c->getObject2()->getXfree())[index2] - o->point[1] << " )";
        std::cout << std::endl;
#endif
#endif

        // Polynome de Cantor de N� sur N bijectif f(x,y)=((x+y)^2+3x+y)/2
        long index = cantorPolynomia(o->id /*cantorPolynomia(index1, index2)*/,id);
//#ifdef DETECTIONOUTPUT_FREEMOTION
//		c->addContact(mu, o->normal, o->point[1], o->point[0], distance, index1, index2, o->freePoint[1], o->freePoint[0], index);
//#else
        // as we called updateXfree on the mappings, the contact class can now use the Xfree value of the contact points instead of relying on the collision detection method to fill freePoint[0] and freePoint[1]
        //c->addContact(mu, o->normal, o->point[1], o->point[0], distance, index1, index2, index);
        c->addContact(mu, o->normal, distance, index1, index2, index, o->id);
//#endif
    }
}

template < class TCollisionModel1, class TCollisionModel2 >
void FrictionContact<TCollisionModel1,TCollisionModel2>::createResponse(core::objectmodel::BaseContext* group)
{
    if (c!=NULL)
    {
        if (parent!=NULL)
        {
            parent->removeObject(this);
            parent->removeObject(c);
        }
        parent = group;
        if (parent!=NULL)
        {
            //sout << "Attaching contact response to "<<parent->getName()<<sendl;
            parent->addObject(this);
            parent->addObject(c);
        }
    }
}

template < class TCollisionModel1, class TCollisionModel2 >
void FrictionContact<TCollisionModel1,TCollisionModel2>::removeResponse()
{
    if (c!=NULL)
    {
        mapper1.resize(0);
        mapper2.resize(0);
        if (parent!=NULL)
        {
            //sout << "Removing contact response from "<<parent->getName()<<sendl;
            parent->removeObject(this);
            parent->removeObject(c);
        }
        parent = NULL;
    }
}

} // namespace collision

} // namespace component

} // namespace sofa

#endif
<|endoftext|>