<commit_before>/*
 * Copyright 2014, Nicolas Mansard, LAAS-CNRS
 *
 * This file is part of eigenpy.
 * eigenpy 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 3 of
 * the License, or (at your option) any later version.
 * eigenpy 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 eigenpy.  If not, see <http://www.gnu.org/licenses/>.
 */

#ifndef __eigenpy_details_hpp__
#define __eigenpy_details_hpp__

#include <boost/python.hpp>
#include <Eigen/Core>

#include <numpy/arrayobject.h>
#include <iostream>

#include "eigenpy/eigenpy.hpp"
#include "eigenpy/exception.hpp"
#include "eigenpy/map.hpp"

namespace eigenpy
{
  template <typename SCALAR>  struct NumpyEquivalentType {};
  template <> struct NumpyEquivalentType<double>  { enum { type_code = NPY_DOUBLE };};
  template <> struct NumpyEquivalentType<int>     { enum { type_code = NPY_INT    };};
  template <> struct NumpyEquivalentType<float>   { enum { type_code = NPY_FLOAT  };};

  namespace bp = boost::python;

  struct PyMatrixType
  {

    static PyMatrixType & getInstance()
    {
      static PyMatrixType instance;
      return instance;
    }

    operator bp::object () { return pyMatrixType; }

    bp::object make(PyArrayObject* pyArray, bool copy = false)
    { return make((PyObject*)pyArray,copy); }
    bp::object make(PyObject* pyObj, bool copy = false)
    {
      boost::python::object m
      = pyMatrixType(bp::object(bp::handle<>(pyObj)), bp::object(), copy);
      Py_INCREF(m.ptr());
      return m;
    }

  protected:
    PyMatrixType()
    {
      pyModule = boost::python::import("numpy");
      pyMatrixType = pyModule.attr("matrix");
    }

    bp::object pyMatrixType;
    bp::object pyModule;
  };

  /* --- TO PYTHON -------------------------------------------------------------- */
  template< typename MatType,typename EquivalentEigenType >
  struct EigenToPy
  {
    static PyObject* convert(MatType const& mat)
    {
      typedef typename MatType::Scalar T;
      assert( (mat.rows()<INT_MAX) && (mat.cols()<INT_MAX)
	      && "Matrix range larger than int ... should never happen." );
      const int R  = (int)mat.rows(), C = (int)mat.cols();

      npy_intp shape[2] = { R,C };
      PyArrayObject* pyArray = (PyArrayObject*)
	PyArray_SimpleNew(2, shape, NumpyEquivalentType<T>::type_code);

      MapNumpy<EquivalentEigenType>::map(pyArray) = mat;

      return PyMatrixType::getInstance().make(pyArray).ptr();
    }
  };

  /* --- FROM PYTHON ------------------------------------------------------------ */
  namespace bp = boost::python;

  template<typename MatType, int ROWS,int COLS>
  struct TraitsMatrixConstructor
  {
    static MatType & construct(void*storage,int /*r*/,int /*c*/)
    {
      return * new(storage) MatType();
    }
  };

  template<typename MatType>
  struct TraitsMatrixConstructor<MatType,Eigen::Dynamic,Eigen::Dynamic>
  {
    static MatType & construct(void*storage,int r,int c)
    {
      return * new(storage) MatType(r,c);
    }
  };

  template<typename MatType,int R>
  struct TraitsMatrixConstructor<MatType,R,Eigen::Dynamic>
  {
    static MatType & construct(void*storage,int /*r*/,int c)
    {
      return * new(storage) MatType(R,c);
    }
  };

  template<typename MatType,int C>
  struct TraitsMatrixConstructor<MatType,Eigen::Dynamic,C>
  {
    static MatType & construct(void*storage,int r,int /*c*/)
    {
      return * new(storage) MatType(r,C);
    }
  };

  template<typename MatType,typename EquivalentEigenType>
  struct EigenFromPy
  {
    EigenFromPy()
    {
      bp::converter::registry::push_back
	(&convertible,&construct,bp::type_id<MatType>());
    }

    // Determine if obj_ptr can be converted in a Eigenvec
    static void* convertible(PyObject* obj_ptr)
    {
      typedef typename MatType::Scalar T;

      if (!PyArray_Check(obj_ptr))
	{
#ifndef NDEBUG
	  std::cerr << "The python object is not a numpy array." << std::endl;
#endif
	  return 0;
	}

      if (PyArray_NDIM(obj_ptr) != 2)
	if ( (PyArray_NDIM(obj_ptr) !=1) || (! MatType::IsVectorAtCompileTime) )
	  {
#ifndef NDEBUG
	    std::cerr << "The number of dimension of the object is not correct." << std::endl;
#endif
	    return 0;
	  }

      if ((PyArray_ObjectType(obj_ptr, 0)) != NumpyEquivalentType<T>::type_code)
	{
#ifndef NDEBUG
	  std::cerr << "The internal type as no Eigen equivalent." << std::endl;
#endif
	  return 0;
	}

      if (!(PyArray_FLAGS(obj_ptr) & NPY_ALIGNED))
	{
#ifndef NDEBUG
	  std::cerr << "NPY non-aligned matrices are not implemented." << std::endl;
#endif
	  return 0;
	}

      return obj_ptr;
    }

    // Convert obj_ptr into a Eigenvec
    static void construct(PyObject* pyObj,
			  bp::converter::rvalue_from_python_stage1_data* memory)
    {
      using namespace Eigen;

      PyArrayObject * pyArray = reinterpret_cast<PyArrayObject*>(pyObj);
      typename MapNumpy<EquivalentEigenType>::EigenMap numpyMap = MapNumpy<EquivalentEigenType>::map(pyArray);

      void* storage = ((bp::converter::rvalue_from_python_storage<MatType>*)
		       (memory))->storage.bytes;
      assert( (numpyMap.rows()<INT_MAX) && (numpyMap.cols()<INT_MAX)
	      && "Map range larger than int ... can never happen." );
      int r=(int)numpyMap.rows(),c=(int)numpyMap.cols();
      EquivalentEigenType & eigenMatrix = //* new(storage) MatType(numpyMap.rows(),numpyMap.cols());
	TraitsMatrixConstructor<MatType,MatType::RowsAtCompileTime,MatType::ColsAtCompileTime>::construct (storage,r,c);
      memory->convertible = storage;

      eigenMatrix = numpyMap;
    }
  };

  template<typename MatType,typename EigenEquivalentType>
  void enableEigenPySpecific()
  {
    import_array();

#ifdef EIGEN_DONT_VECTORIZE

    boost::python::to_python_converter<MatType,
                                      eigenpy::EigenToPy<MatType,MatType> >();
    eigenpy::EigenFromPy<MatType,MatType>();
#else

    boost::python::to_python_converter<MatType,
				       eigenpy::EigenToPy<MatType,MatType> >();
    eigenpy::EigenFromPy<MatType,MatType>();

    typedef typename eigenpy::UnalignedEquivalent<MatType>::type MatTypeDontAlign;
#ifndef EIGENPY_ALIGNED
    boost::python::to_python_converter<MatTypeDontAlign,
				       eigenpy::EigenToPy<MatTypeDontAlign,MatTypeDontAlign> >();
    eigenpy::EigenFromPy<MatTypeDontAlign,MatTypeDontAlign>();
#endif
#endif

  }

} // namespace eigenpy

#endif // ifndef __eigenpy_details_hpp__
<commit_msg>[C++] Remove useless warning in the cast of memory ptr<commit_after>/*
 * Copyright 2014, Nicolas Mansard, LAAS-CNRS
 *
 * This file is part of eigenpy.
 * eigenpy 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 3 of
 * the License, or (at your option) any later version.
 * eigenpy 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 eigenpy.  If not, see <http://www.gnu.org/licenses/>.
 */

#ifndef __eigenpy_details_hpp__
#define __eigenpy_details_hpp__

#include <boost/python.hpp>
#include <Eigen/Core>

#include <numpy/arrayobject.h>
#include <iostream>

#include "eigenpy/eigenpy.hpp"
#include "eigenpy/exception.hpp"
#include "eigenpy/map.hpp"

namespace eigenpy
{
  template <typename SCALAR>  struct NumpyEquivalentType {};
  template <> struct NumpyEquivalentType<double>  { enum { type_code = NPY_DOUBLE };};
  template <> struct NumpyEquivalentType<int>     { enum { type_code = NPY_INT    };};
  template <> struct NumpyEquivalentType<float>   { enum { type_code = NPY_FLOAT  };};

  namespace bp = boost::python;

  struct PyMatrixType
  {

    static PyMatrixType & getInstance()
    {
      static PyMatrixType instance;
      return instance;
    }

    operator bp::object () { return pyMatrixType; }

    bp::object make(PyArrayObject* pyArray, bool copy = false)
    { return make((PyObject*)pyArray,copy); }
    bp::object make(PyObject* pyObj, bool copy = false)
    {
      boost::python::object m
      = pyMatrixType(bp::object(bp::handle<>(pyObj)), bp::object(), copy);
      Py_INCREF(m.ptr());
      return m;
    }

  protected:
    PyMatrixType()
    {
      pyModule = boost::python::import("numpy");
      pyMatrixType = pyModule.attr("matrix");
    }

    bp::object pyMatrixType;
    bp::object pyModule;
  };

  /* --- TO PYTHON -------------------------------------------------------------- */
  template< typename MatType,typename EquivalentEigenType >
  struct EigenToPy
  {
    static PyObject* convert(MatType const& mat)
    {
      typedef typename MatType::Scalar T;
      assert( (mat.rows()<INT_MAX) && (mat.cols()<INT_MAX)
	      && "Matrix range larger than int ... should never happen." );
      const int R  = (int)mat.rows(), C = (int)mat.cols();

      npy_intp shape[2] = { R,C };
      PyArrayObject* pyArray = (PyArrayObject*)
	PyArray_SimpleNew(2, shape, NumpyEquivalentType<T>::type_code);

      MapNumpy<EquivalentEigenType>::map(pyArray) = mat;

      return PyMatrixType::getInstance().make(pyArray).ptr();
    }
  };

  /* --- FROM PYTHON ------------------------------------------------------------ */
  namespace bp = boost::python;

  template<typename MatType, int ROWS,int COLS>
  struct TraitsMatrixConstructor
  {
    static MatType & construct(void*storage,int /*r*/,int /*c*/)
    {
      return * new(storage) MatType();
    }
  };

  template<typename MatType>
  struct TraitsMatrixConstructor<MatType,Eigen::Dynamic,Eigen::Dynamic>
  {
    static MatType & construct(void*storage,int r,int c)
    {
      return * new(storage) MatType(r,c);
    }
  };

  template<typename MatType,int R>
  struct TraitsMatrixConstructor<MatType,R,Eigen::Dynamic>
  {
    static MatType & construct(void*storage,int /*r*/,int c)
    {
      return * new(storage) MatType(R,c);
    }
  };

  template<typename MatType,int C>
  struct TraitsMatrixConstructor<MatType,Eigen::Dynamic,C>
  {
    static MatType & construct(void*storage,int r,int /*c*/)
    {
      return * new(storage) MatType(r,C);
    }
  };

  template<typename MatType,typename EquivalentEigenType>
  struct EigenFromPy
  {
    EigenFromPy()
    {
      bp::converter::registry::push_back
	(&convertible,&construct,bp::type_id<MatType>());
    }

    // Determine if obj_ptr can be converted in a Eigenvec
    static void* convertible(PyObject* obj_ptr)
    {
      typedef typename MatType::Scalar T;

      if (!PyArray_Check(obj_ptr))
	{
#ifndef NDEBUG
	  std::cerr << "The python object is not a numpy array." << std::endl;
#endif
	  return 0;
	}

      if (PyArray_NDIM(obj_ptr) != 2)
	if ( (PyArray_NDIM(obj_ptr) !=1) || (! MatType::IsVectorAtCompileTime) )
	  {
#ifndef NDEBUG
	    std::cerr << "The number of dimension of the object is not correct." << std::endl;
#endif
	    return 0;
	  }

      if ((PyArray_ObjectType(obj_ptr, 0)) != NumpyEquivalentType<T>::type_code)
	{
#ifndef NDEBUG
	  std::cerr << "The internal type as no Eigen equivalent." << std::endl;
#endif
	  return 0;
	}

      if (!(PyArray_FLAGS(obj_ptr) & NPY_ALIGNED))
	{
#ifndef NDEBUG
	  std::cerr << "NPY non-aligned matrices are not implemented." << std::endl;
#endif
	  return 0;
	}

      return obj_ptr;
    }

    // Convert obj_ptr into a Eigenvec
    static void construct(PyObject* pyObj,
			  bp::converter::rvalue_from_python_stage1_data* memory)
    {
      using namespace Eigen;

      PyArrayObject * pyArray = reinterpret_cast<PyArrayObject*>(pyObj);
      typename MapNumpy<EquivalentEigenType>::EigenMap numpyMap = MapNumpy<EquivalentEigenType>::map(pyArray);

      void* storage = ((bp::converter::rvalue_from_python_storage<MatType>*)
		       ((void*)memory))->storage.bytes;
      assert( (numpyMap.rows()<INT_MAX) && (numpyMap.cols()<INT_MAX)
	      && "Map range larger than int ... can never happen." );
      int r=(int)numpyMap.rows(),c=(int)numpyMap.cols();
      EquivalentEigenType & eigenMatrix = //* new(storage) MatType(numpyMap.rows(),numpyMap.cols());
	TraitsMatrixConstructor<MatType,MatType::RowsAtCompileTime,MatType::ColsAtCompileTime>::construct (storage,r,c);
      memory->convertible = storage;

      eigenMatrix = numpyMap;
    }
  };

  template<typename MatType,typename EigenEquivalentType>
  void enableEigenPySpecific()
  {
    import_array();

#ifdef EIGEN_DONT_VECTORIZE

    boost::python::to_python_converter<MatType,
                                      eigenpy::EigenToPy<MatType,MatType> >();
    eigenpy::EigenFromPy<MatType,MatType>();
#else

    boost::python::to_python_converter<MatType,
				       eigenpy::EigenToPy<MatType,MatType> >();
    eigenpy::EigenFromPy<MatType,MatType>();

    typedef typename eigenpy::UnalignedEquivalent<MatType>::type MatTypeDontAlign;
#ifndef EIGENPY_ALIGNED
    boost::python::to_python_converter<MatTypeDontAlign,
				       eigenpy::EigenToPy<MatTypeDontAlign,MatTypeDontAlign> >();
    eigenpy::EigenFromPy<MatTypeDontAlign,MatTypeDontAlign>();
#endif
#endif

  }

} // namespace eigenpy

#endif // ifndef __eigenpy_details_hpp__
<|endoftext|>


<commit_before>#include "TMVA/training_history.h"

#include "TH2F.h"
#include "TFile.h"
#include "TIterator.h"
#include "TKey.h"

void TMVA::plot_training_history(TString dataset, TFile* /*file*/, TDirectory* BinDir)
{

   Bool_t __PLOT_LOGO__  = kTRUE;
   Bool_t __SAVE_IMAGE__ = kTRUE;

   // the coordinates
   Float_t x1 = 999;
   Float_t x2 = -999;
   Float_t y1 = 999.;
   Float_t y2 = -999;

   // create canvas
   TCanvas* c = new TCanvas( "c", "the canvas", 200, 0, 650, 500 );

   // global style settings
   c->SetGrid();
   c->SetTicks();

   // legend
   Float_t x0L = 0.107,     y0H = 0.899;
   Float_t dxL = 0.457-x0L, dyH = 0.22;

   TLegend *legend = new TLegend( x0L, y0H-dyH, x0L+dxL, y0H );
   //legend->SetTextSize( 0.05 );
   legend->SetHeader( "MVA Method:" );
   legend->SetMargin( 0.4 );

   TString xtit = "Training Step";
   TString ytit = "";

   TString ftit = "Training History";

   TString hNameRef = "";//training_history";

   TList xhists;
   TList xmethods;
   UInt_t xnm = TMVAGlob::GetListOfMethods( xmethods ,BinDir);
   if (xnm==0){
      cout << "ups .. no methods found in to plot training history for ... give up"  << endl;
      return;
   }
   TIter xnext(&xmethods);
   // loop over all methods
   TKey *xkey;
   while ((xkey = (TKey*)xnext())) {
      TDirectory * mDir = (TDirectory*)xkey->ReadObj();
      TList titles;
      UInt_t ninst = TMVAGlob::GetListOfTitles(mDir,titles);
      if (ninst==0) cout << "hmm... sorry, but this printout was supposed to be only to keep the compiler quite.. never supposed to happen :(" << endl;
      TIter nextTitle(&titles);
      TKey *titkey;
      TDirectory *titDir;
      while ((titkey = TMVAGlob::NextKey(nextTitle,"TDirectory"))) {
         titDir = (TDirectory *)titkey->ReadObj();
         TString methodTitle;
         TMVAGlob::GetMethodTitle(methodTitle,titDir);
         TIter nextKey( titDir->GetListOfKeys() );
         TKey *hkey2;
         while ((hkey2 = TMVAGlob::NextKey(nextKey,"TH1"))) {
            TH1 *h = (TH1*)hkey2->ReadObj();
            TString hname = h->GetName();
            if (hname.Contains( hNameRef ) && hname.BeginsWith( "TrainingHistory_" )) {

               if (h->GetMaximum() > y2) y2 = h->GetMaximum()*1.1;
               if (h->GetMinimum() < y1) y1 = h->GetMinimum();
               if (h->GetBinLowEdge(0) < x1 ) x1 = h->GetBinLowEdge(0);
               if (h->GetBinLowEdge(h->GetNbinsX()+1 ) > x2 ) x2 = h->GetBinLowEdge(h->GetNbinsX()+1 );

            }
         }
      }
   }

   // draw empty frame
   if(gROOT->FindObject("frame")!=0) gROOT->FindObject("frame")->Delete();
   TH2F* frame = new TH2F( "frame", ftit, 500, x1, x2, 500, y1, y2 );
   frame->GetXaxis()->SetTitle( xtit );
   frame->GetYaxis()->SetTitle( ytit );
   TMVAGlob::SetFrameStyle( frame, 1.0 );

   frame->Draw();

   Int_t color = 1;
   Int_t nmva  = 0;
   TKey *key;

   TList hists;
   TList methods;
   UInt_t nm = TMVAGlob::GetListOfMethods( methods,BinDir );
   if (nm==0){
      cout << "ups .. no methods found in to plot ROC curve for ... give up"  << endl;
      return;
   }
   //   TIter next(file->GetListOfKeys());
   TIter next(&methods);

   // loop over all methods
   while ((key = (TKey*)next())) {
      TDirectory * mDir = (TDirectory*)key->ReadObj();
      TList titles;
      UInt_t ninst = TMVAGlob::GetListOfTitles(mDir,titles);
      if (ninst==0) cout << "hmm...  sorry, but this printout was supposed to be only to keep the compiler quite.. never supposed to happen :(" << endl;
      TIter nextTitle(&titles);
      TKey *titkey;
      TDirectory *titDir;
      while ((titkey = TMVAGlob::NextKey(nextTitle,"TDirectory"))) {
         titDir = (TDirectory *)titkey->ReadObj();
         TString methodTitle;
         TMVAGlob::GetMethodTitle(methodTitle,titDir);
         TIter nextKey( titDir->GetListOfKeys() );
         TKey *hkey2;
         while ((hkey2 = TMVAGlob::NextKey(nextKey,"TH1"))) {
            TH1 *h = (TH1*)hkey2->ReadObj();
            TString hname = h->GetName();
            if (hname.Contains( hNameRef ) && hname.BeginsWith( "TrainingHistory_" )) {
               h->SetLineWidth(3);
               h->SetLineColor(color);
               color++; if (color == 5 || color == 10 || color == 11) color++;
               h->Draw("csame");
               hists.Add(h);
               nmva++;
            }
         }
      }
   }

   while (hists.GetSize()) {
      TListIter hIt(&hists);
      TH1* hist(0);
      Double_t largestInt=-1;
      TH1* histWithLargestInt(0);
      while ((hist = (TH1*)hIt())!=0) {
         Double_t integral = hist->Integral(1,hist->FindBin(0.9999));
         if (integral>largestInt) {
            largestInt = integral;
            histWithLargestInt = hist;
         }
      }
      if (histWithLargestInt == 0) {
         cout << "ERROR - unknown hist \"histWithLargestInt\" --> serious problem in ROOT file" << endl;
         break;
      }
      legend->AddEntry(histWithLargestInt,TString(histWithLargestInt->GetTitle()).ReplaceAll("MVA_",""),"l");
      hists.Remove(histWithLargestInt);
   }

   // rescale legend box size
   // current box size has been tuned for 3 MVAs + 1 title
   dyH *= (Float_t(TMath::Min(10,nmva) - 3.0)/4.0);
   legend->SetY2( y0H + dyH);

   // redraw axes
   frame->Draw("sameaxis");
   legend->Draw("same");

   // ============================================================

   if (__PLOT_LOGO__) TMVAGlob::plot_logo();

   // ============================================================

   c->Update();

   TString fname = dataset+"/plots/" + hNameRef;
   if (TString(BinDir->GetName()).Contains("multicut")){
      TString fprepend(BinDir->GetName());
      fprepend.ReplaceAll("multicutMVA_","");
      fname = dataset+"plots/" + fprepend + "_" + hNameRef;
   }
   if (__SAVE_IMAGE__) TMVAGlob::imgconv( c, fname );

   return;
}

void TMVA::training_history(TString dataset, TString fin , Bool_t useTMVAStyle )
{

   // set style and remove existing canvas'
   TMVAGlob::Initialize( useTMVAStyle );

   // checks if file with name "fin" is already open, and if not opens one
   TFile* file = TMVAGlob::OpenFile( fin );

   plot_training_history(dataset, file, file->GetDirectory(dataset.Data()));

   return;
}

<commit_msg>Fix missing filename when the 'Training History' button was clicked in TMVA-Gui (functionality added in pull request #4337)<commit_after>#include "TMVA/training_history.h"

#include "TH2F.h"
#include "TFile.h"
#include "TIterator.h"
#include "TKey.h"

void TMVA::plot_training_history(TString dataset, TFile* /*file*/, TDirectory* BinDir)
{

   Bool_t __PLOT_LOGO__  = kTRUE;
   Bool_t __SAVE_IMAGE__ = kTRUE;

   // the coordinates
   Float_t x1 = 999;
   Float_t x2 = -999;
   Float_t y1 = 999.;
   Float_t y2 = -999;

   // create canvas
   TCanvas* c = new TCanvas( "c", "the canvas", 200, 0, 650, 500 );

   // global style settings
   c->SetGrid();
   c->SetTicks();

   // legend
   Float_t x0L = 0.107,     y0H = 0.899;
   Float_t dxL = 0.457-x0L, dyH = 0.22;

   TLegend *legend = new TLegend( x0L, y0H-dyH, x0L+dxL, y0H );
   //legend->SetTextSize( 0.05 );
   legend->SetHeader( "MVA Method:" );
   legend->SetMargin( 0.4 );

   TString xtit = "Training Step";
   TString ytit = "";

   TString ftit = "Training History";

   TString hNameRef = "TrainingHistory";

   TList xhists;
   TList xmethods;
   UInt_t xnm = TMVAGlob::GetListOfMethods( xmethods ,BinDir);
   if (xnm==0){
      cout << "ups .. no methods found in to plot training history for ... give up"  << endl;
      return;
   }
   TIter xnext(&xmethods);
   // loop over all methods
   TKey *xkey;
   while ((xkey = (TKey*)xnext())) {
      TDirectory * mDir = (TDirectory*)xkey->ReadObj();
      TList titles;
      UInt_t ninst = TMVAGlob::GetListOfTitles(mDir,titles);
      if (ninst==0) cout << "hmm... sorry, but this printout was supposed to be only to keep the compiler quite.. never supposed to happen :(" << endl;
      TIter nextTitle(&titles);
      TKey *titkey;
      TDirectory *titDir;
      while ((titkey = TMVAGlob::NextKey(nextTitle,"TDirectory"))) {
         titDir = (TDirectory *)titkey->ReadObj();
         TString methodTitle;
         TMVAGlob::GetMethodTitle(methodTitle,titDir);
         TIter nextKey( titDir->GetListOfKeys() );
         TKey *hkey2;
         while ((hkey2 = TMVAGlob::NextKey(nextKey,"TH1"))) {
            TH1 *h = (TH1*)hkey2->ReadObj();
            TString hname = h->GetName();
            if (hname.Contains( hNameRef ) && hname.BeginsWith( "TrainingHistory_" )) {

               if (h->GetMaximum() > y2) y2 = h->GetMaximum()*1.1;
               if (h->GetMinimum() < y1) y1 = h->GetMinimum();
               if (h->GetBinLowEdge(0) < x1 ) x1 = h->GetBinLowEdge(0);
               if (h->GetBinLowEdge(h->GetNbinsX()+1 ) > x2 ) x2 = h->GetBinLowEdge(h->GetNbinsX()+1 );

            }
         }
      }
   }

   // draw empty frame
   if(gROOT->FindObject("frame")!=0) gROOT->FindObject("frame")->Delete();
   TH2F* frame = new TH2F( "frame", ftit, 500, x1, x2, 500, y1, y2 );
   frame->GetXaxis()->SetTitle( xtit );
   frame->GetYaxis()->SetTitle( ytit );
   TMVAGlob::SetFrameStyle( frame, 1.0 );

   frame->Draw();

   Int_t color = 1;
   Int_t nmva  = 0;
   TKey *key;

   TList hists;
   TList methods;
   UInt_t nm = TMVAGlob::GetListOfMethods( methods,BinDir );
   if (nm==0){
      cout << "ups .. no methods found in to plot ROC curve for ... give up"  << endl;
      return;
   }
   //   TIter next(file->GetListOfKeys());
   TIter next(&methods);

   // loop over all methods
   while ((key = (TKey*)next())) {
      TDirectory * mDir = (TDirectory*)key->ReadObj();
      TList titles;
      UInt_t ninst = TMVAGlob::GetListOfTitles(mDir,titles);
      if (ninst==0) cout << "hmm...  sorry, but this printout was supposed to be only to keep the compiler quite.. never supposed to happen :(" << endl;
      TIter nextTitle(&titles);
      TKey *titkey;
      TDirectory *titDir;
      while ((titkey = TMVAGlob::NextKey(nextTitle,"TDirectory"))) {
         titDir = (TDirectory *)titkey->ReadObj();
         TString methodTitle;
         TMVAGlob::GetMethodTitle(methodTitle,titDir);
         TIter nextKey( titDir->GetListOfKeys() );
         TKey *hkey2;
         while ((hkey2 = TMVAGlob::NextKey(nextKey,"TH1"))) {
            TH1 *h = (TH1*)hkey2->ReadObj();
            TString hname = h->GetName();
            if (hname.Contains( hNameRef ) && hname.BeginsWith( "TrainingHistory_" )) {
               h->SetLineWidth(3);
               h->SetLineColor(color);
               color++; if (color == 5 || color == 10 || color == 11) color++;
               h->Draw("csame");
               hists.Add(h);
               nmva++;
            }
         }
      }
   }

   while (hists.GetSize()) {
      TListIter hIt(&hists);
      TH1* hist(0);
      Double_t largestInt=-1;
      TH1* histWithLargestInt(0);
      while ((hist = (TH1*)hIt())!=0) {
         Double_t integral = hist->Integral(1,hist->FindBin(0.9999));
         if (integral>largestInt) {
            largestInt = integral;
            histWithLargestInt = hist;
         }
      }
      if (histWithLargestInt == 0) {
         cout << "ERROR - unknown hist \"histWithLargestInt\" --> serious problem in ROOT file" << endl;
         break;
      }
      legend->AddEntry(histWithLargestInt,TString(histWithLargestInt->GetTitle()).ReplaceAll("MVA_",""),"l");
      hists.Remove(histWithLargestInt);
   }

   // rescale legend box size
   // current box size has been tuned for 3 MVAs + 1 title
   dyH *= (Float_t(TMath::Min(10,nmva) - 3.0)/4.0);
   legend->SetY2( y0H + dyH);

   // redraw axes
   frame->Draw("sameaxis");
   legend->Draw("same");

   // ============================================================

   if (__PLOT_LOGO__) TMVAGlob::plot_logo();

   // ============================================================

   c->Update();

   TString fname = dataset+"/plots/" + hNameRef;
   if (TString(BinDir->GetName()).Contains("multicut")){
      TString fprepend(BinDir->GetName());
      fprepend.ReplaceAll("multicutMVA_","");
      fname = dataset+"plots/" + fprepend + "_" + hNameRef;
   }
   if (__SAVE_IMAGE__) TMVAGlob::imgconv( c, fname );

   return;
}

void TMVA::training_history(TString dataset, TString fin , Bool_t useTMVAStyle )
{

   // set style and remove existing canvas'
   TMVAGlob::Initialize( useTMVAStyle );

   // checks if file with name "fin" is already open, and if not opens one
   TFile* file = TMVAGlob::OpenFile( fin );

   plot_training_history(dataset, file, file->GetDirectory(dataset.Data()));

   return;
}

<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  $RCSfile: dataview.cxx,v $
 *
 *  $Revision: 1.3 $
 *
 *  last change: $Author: oj $ $Date: 2001-02-14 14:29:32 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 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
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (the License); You may not use this file
 *  except in compliance with the License. You may obtain a copy of the
 *  License at http://www.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an AS IS basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/

#ifndef DBAUI_DATAVIEW_HXX
#include "dataview.hxx"
#endif
#ifndef _TOOLBOX_HXX //autogen
#include <vcl/toolbox.hxx>
#endif
#ifndef _TOOLKIT_HELPER_VCLUNOHELPER_HXX_
#include <toolkit/unohlp.hxx>
#endif
#ifndef _COMPHELPER_TYPES_HXX_
#include <comphelper/types.hxx>
#endif
#ifndef _SFXAPP_HXX //autogen wg. SFX_APP
#include <sfx2/app.hxx>
#endif
#ifndef _SFXIMGMGR_HXX
#include <sfx2/imgmgr.hxx>
#endif

using namespace dbaui;
using namespace ::com::sun::star::uno;
//  using namespace ::com::sun::star::beans;
using namespace ::com::sun::star::lang;
//  using namespace ::com::sun::star::container;

// -------------------------------------------------------------------------
ODataView::ODataView(Window* pParent, const Reference< XMultiServiceFactory >& _rFactory, WinBits nStyle)
    :Window(pParent,nStyle)
    ,m_pToolBox(NULL)
    ,m_xServiceFactory(_rFactory)
{
}
// -------------------------------------------------------------------------
void ODataView::Construct(const Reference< ::com::sun::star::awt::XControlModel >& xModel)
{
    try
    {
        // our UNO representation
        m_xMe = VCLUnoHelper::CreateControlContainer(this);
        DBG_ASSERT(m_xMe.is(), "ODataView::Construct : no UNO representation");
    }
    catch(Exception&)
    {
        ::comphelper::disposeComponent(m_xMe);
        throw;
    }
}
// -------------------------------------------------------------------------
ODataView::~ODataView()
{
    setToolBox(NULL);

    ::comphelper::disposeComponent(m_xMe);
}
// -------------------------------------------------------------------------
void ODataView::setToolBox(ToolBox* pTB)
{
    if (pTB == m_pToolBox)
        return;

    if (m_pToolBox)
    {
        SFX_IMAGEMANAGER()->ReleaseToolBox(m_pToolBox);
        delete m_pToolBox;
    }

    m_pToolBox = pTB;
    if (m_pToolBox)
    {
        SFX_IMAGEMANAGER()->RegisterToolBox(m_pToolBox, SFX_TOOLBOX_CHANGEOUTSTYLE);

        m_pToolBox->SetParent(this);
        m_pToolBox->Show();
    }

    // rearrange the grid and the TB
    Resize();
}
// -------------------------------------------------------------------------
void ODataView::Resize()
{
    Window::Resize();
    Rectangle aRect(Point(0,0),GetOutputSizePixel());
    resizeControl(aRect);

    // set the size of the toolbox
    if (m_pToolBox)
        m_pToolBox->SetPosSizePixel(aRect.TopLeft(),aRect.GetSize());
}
//------------------------------------------------------------------

<commit_msg>#65293# change in SFX not made (no changes mail for this ...)<commit_after>/*************************************************************************
 *
 *  $RCSfile: dataview.cxx,v $
 *
 *  $Revision: 1.4 $
 *
 *  last change: $Author: fs $ $Date: 2001-06-12 16:31:14 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 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
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (the License); You may not use this file
 *  except in compliance with the License. You may obtain a copy of the
 *  License at http://www.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an AS IS basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/

#ifndef DBAUI_DATAVIEW_HXX
#include "dataview.hxx"
#endif
#ifndef _TOOLBOX_HXX //autogen
#include <vcl/toolbox.hxx>
#endif
#ifndef _TOOLKIT_HELPER_VCLUNOHELPER_HXX_
#include <toolkit/unohlp.hxx>
#endif
#ifndef _COMPHELPER_TYPES_HXX_
#include <comphelper/types.hxx>
#endif
#ifndef _SFXAPP_HXX //autogen wg. SFX_APP
#include <sfx2/app.hxx>
#endif
#ifndef _SFXIMGMGR_HXX
#include <sfx2/imgmgr.hxx>
#endif

using namespace dbaui;
using namespace ::com::sun::star::uno;
//  using namespace ::com::sun::star::beans;
using namespace ::com::sun::star::lang;
//  using namespace ::com::sun::star::container;

// -------------------------------------------------------------------------
ODataView::ODataView(Window* pParent, const Reference< XMultiServiceFactory >& _rFactory, WinBits nStyle)
    :Window(pParent,nStyle)
    ,m_pToolBox(NULL)
    ,m_xServiceFactory(_rFactory)
{
}
// -------------------------------------------------------------------------
void ODataView::Construct(const Reference< ::com::sun::star::awt::XControlModel >& xModel)
{
    try
    {
        // our UNO representation
        m_xMe = VCLUnoHelper::CreateControlContainer(this);
        DBG_ASSERT(m_xMe.is(), "ODataView::Construct : no UNO representation");
    }
    catch(Exception&)
    {
        ::comphelper::disposeComponent(m_xMe);
        throw;
    }
}
// -------------------------------------------------------------------------
ODataView::~ODataView()
{
    setToolBox(NULL);

    ::comphelper::disposeComponent(m_xMe);
}
// -------------------------------------------------------------------------
void ODataView::setToolBox(ToolBox* pTB)
{
    if (pTB == m_pToolBox)
        return;

    if (m_pToolBox)
        delete m_pToolBox;

    m_pToolBox = pTB;
    if (m_pToolBox)
    {
        m_pToolBox->SetParent(this);
        m_pToolBox->Show();
    }

    // rearrange the grid and the TB
    Resize();
}
// -------------------------------------------------------------------------
void ODataView::Resize()
{
    Window::Resize();
    Rectangle aRect(Point(0,0),GetOutputSizePixel());
    resizeControl(aRect);

    // set the size of the toolbox
    if (m_pToolBox)
        m_pToolBox->SetPosSizePixel(aRect.TopLeft(),aRect.GetSize());
}
//------------------------------------------------------------------

<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  $RCSfile: marktree.cxx,v $
 *
 *  $Revision: 1.11 $
 *
 *  last change: $Author: vg $ $Date: 2003-06-06 10:48:15 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 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
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (the "License"); You may not use this file
 *  except in compliance with the License. You may obtain a copy of the
 *  License at http://www.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc..
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/

#ifndef _DBAUI_MARKTREE_HXX_
#include "marktree.hxx"
#endif
#ifndef _DBAUI_MODULE_DBU_HXX_
#include "moduledbu.hxx"
#endif
#ifndef _DBU_CONTROL_HRC_
#include "dbu_control.hrc"
#endif
#ifndef _SV_SVAPP_HXX
#include <vcl/svapp.hxx>
#endif

//.........................................................................
namespace dbaui
{
//.........................................................................
#define SPACEBETWEENENTRIES     4
//========================================================================
//= OMarkableTreeListBox
//========================================================================
//------------------------------------------------------------------------
OMarkableTreeListBox::OMarkableTreeListBox( Window* pParent, WinBits nWinStyle ) : SvTreeListBox(pParent,nWinStyle)
{
    InitButtonData();
}
//------------------------------------------------------------------------
OMarkableTreeListBox::OMarkableTreeListBox( Window* pParent, const ResId& rResId) : SvTreeListBox(pParent,rResId)
{
    InitButtonData();
}
//------------------------------------------------------------------------
OMarkableTreeListBox::~OMarkableTreeListBox()
{
    delete m_pCheckButton;
}
// -----------------------------------------------------------------------------
void OMarkableTreeListBox::notifyHiContrastChanged()
{
    // old actions now done in SvTreeListBox::DataChanged() / InitSettings()
}
//------------------------------------------------------------------------
void OMarkableTreeListBox::Paint(const Rectangle& _rRect)
{
    if (!IsEnabled())
    {
        Font aOldFont = GetFont();
        Font aNewFont(aOldFont);

        StyleSettings aSystemStyle = Application::GetSettings().GetStyleSettings();
        aNewFont.SetColor(aSystemStyle.GetDisableColor());

        SetFont(aNewFont);
        SvTreeListBox::Paint(_rRect);
        SetFont(aOldFont);
    }
    else
        SvTreeListBox::Paint(_rRect);
}
//------------------------------------------------------------------------
void OMarkableTreeListBox::InitButtonData()
{
    USHORT nSize = SPACEBETWEENENTRIES;
    SetSpaceBetweenEntries(nSize);
    SetNodeDefaultImages( );

    m_pCheckButton = new SvLBoxButtonData( this );
    OMarkableTreeListBox::notifyHiContrastChanged();
    EnableCheckButton( m_pCheckButton );
}
//------------------------------------------------------------------------
void OMarkableTreeListBox::KeyInput( const KeyEvent& rKEvt )
{
    // nur wenn space
    if (rKEvt.GetKeyCode().GetCode() == KEY_SPACE && !rKEvt.GetKeyCode().IsShift() && !rKEvt.GetKeyCode().IsMod1())
    {
        SvLBoxEntry* pHdlEntry = GetHdlEntry();
        if(pHdlEntry)
        {
            SvButtonState eState = GetCheckButtonState( pHdlEntry);
            if(eState == SV_BUTTON_CHECKED)
                SetCheckButtonState( pHdlEntry,SV_BUTTON_UNCHECKED);
            else
                SetCheckButtonState( pHdlEntry,SV_BUTTON_CHECKED);

            CheckButtonHdl();
        }
        else
            SvTreeListBox::KeyInput(rKEvt);
    }
    else
        SvTreeListBox::KeyInput(rKEvt);

}
//------------------------------------------------------------------------
SvButtonState OMarkableTreeListBox::implDetermineState(SvLBoxEntry* _pEntry)
{
    SvButtonState eState = GetCheckButtonState(_pEntry);
    if (!GetModel()->HasChilds(_pEntry))
        // nothing to do in this bottom-up routine if there are no children ...
        return eState;
#ifdef DBG_UTIL
    String sEntryText = GetEntryText(_pEntry);
#endif

    // loop through the children and check their states
    sal_uInt16 nCheckedChildren = 0;
    sal_uInt16 nChildrenOverall = 0;

    SvLBoxEntry* pChildLoop = GetModel()->FirstChild(_pEntry);
    while (pChildLoop)
    {
#ifdef DBG_UTIL
        String sChildText = GetEntryText(pChildLoop);
#endif
        SvButtonState eChildState = implDetermineState(pChildLoop);
        if (SV_BUTTON_TRISTATE == eChildState)
            break;

        if (SV_BUTTON_CHECKED == eChildState)
            ++nCheckedChildren;
        ++nChildrenOverall;

        pChildLoop = GetModel()->NextSibling(pChildLoop);
    }

    if (pChildLoop)
    {
        // we did not finish the loop because at least one of the children is in tristate
        eState = SV_BUTTON_TRISTATE;

        // but this means that we did not finish all the siblings of pChildLoop, so their checking may be
        // incorrect at the moment
        // -> correct this
        // 88485 - 20.06.2001 - frank.schoenheit@sun.com
        while (pChildLoop)
        {
            implDetermineState(pChildLoop);
            pChildLoop = GetModel()->NextSibling(pChildLoop);
        }
    }
    else
        // none if the children is in tristate
        if (nCheckedChildren)
            // we have at least one chil checked
            if (nCheckedChildren != nChildrenOverall)
                // not all children are checked
                eState = SV_BUTTON_TRISTATE;
            else
                // all children are checked
                eState = SV_BUTTON_CHECKED;
        else
            // no children are checked
            eState = SV_BUTTON_UNCHECKED;

    // finally set the entry to the state we just determined
    SetCheckButtonState(_pEntry, eState);

    // outta here
    return eState;
}

//------------------------------------------------------------------------
void OMarkableTreeListBox::CheckButtons()
{
    SvLBoxEntry* pEntry = GetModel()->First();
    while (pEntry)
    {
        implDetermineState(pEntry);
        pEntry = GetModel()->NextSibling(pEntry);
    }

#if 0
    // Plausibilit"atspr"ufung
    SvButtonState eState;
    SvLBoxEntry* pEntry = GetModel()->First();
    while(pEntry)
    {
        if(!GetModel()->HasChilds(pEntry))
        {
            sal_uInt16 nCheck=0;
            sal_uInt16 nCount=0;
            SvLBoxEntry* pChildEntry = pEntry;
            while(pChildEntry)
            {
                if(GetCheckButtonState(pChildEntry) == SV_BUTTON_CHECKED)
                    nCheck++;
                nCount++;
                pChildEntry = GetModel()->NextSibling(pChildEntry);
            }

            if(nCheck && nCount != nCheck)
                eState = SV_BUTTON_TRISTATE;
            else if(nCheck)
                eState = SV_BUTTON_CHECKED;
            else
                eState = SV_BUTTON_UNCHECKED;

            SvLBoxEntry* pSchema = GetModel()->GetParent(pEntry);
            if(pSchema)
            {
                pEntry = GetModel()->NextSibling(pSchema);
                SetCheckButtonState(pSchema, eState);
            }
            else
                pEntry = NULL; // wenn kein Schema dann sind bereits alle pEntry's durchlaufen worden
        }
        else
            pEntry = GetModel()->Next(pEntry);
    }

    SvLBoxEntry* pCatalog = GetModel()->First();
    SvLBoxEntry* pSchema = NULL;
    if(GetModel()->HasChilds(pCatalog) && GetModel()->HasChilds(pSchema = GetModel()->Next(pCatalog)))
    {
        sal_uInt16 nCheck   =0;
        sal_uInt16 nTri     =0;
        sal_uInt16 nCount   =0;
        while(pSchema)
        {
            if((eState = GetCheckButtonState(pSchema)) == SV_BUTTON_TRISTATE)
                break;

            if(eState == SV_BUTTON_CHECKED)
                nCheck++;
            nCount++;
            pSchema = GetModel()->NextSibling(pSchema);
        }

        if(eState != SV_BUTTON_TRISTATE)
        {
            if(nCheck && nCount == nCheck)
                eState = SV_BUTTON_CHECKED;
            else if(nCheck)
                eState = SV_BUTTON_TRISTATE;
            else
                eState = SV_BUTTON_UNCHECKED;
        }
        SetCheckButtonState( pCatalog,eState);
    }
#endif
}
//------------------------------------------------------------------------
void OMarkableTreeListBox::CheckButtonHdl()
{
    checkedButton_noBroadcast(GetHdlEntry());
    if (m_aCheckButtonHandler.IsSet())
        m_aCheckButtonHandler.Call(this);
}

//------------------------------------------------------------------------
void OMarkableTreeListBox::checkedButton_noBroadcast(SvLBoxEntry* _pEntry)
{
    SvButtonState eState = GetCheckButtonState( _pEntry);
    if (GetModel()->HasChilds(_pEntry)) // Falls Kinder, dann diese auch checken
    {
        SvLBoxEntry* pChildEntry = GetModel()->Next(_pEntry);
        SvLBoxEntry* pSiblingEntry = GetModel()->NextSibling(_pEntry);
        while(pChildEntry && pChildEntry != pSiblingEntry)
        {
            SetCheckButtonState(pChildEntry, eState);
            pChildEntry = GetModel()->Next(pChildEntry);
        }
    }

    SvLBoxEntry* pEntry = IsSelected(_pEntry) ? FirstSelected() : NULL;
    while(pEntry)
    {
        SetCheckButtonState(pEntry,eState);
        if(GetModel()->HasChilds(pEntry))   // Falls Kinder, dann diese auch checken
        {
            SvLBoxEntry* pChildEntry = GetModel()->Next(pEntry);
            SvLBoxEntry* pSiblingEntry = GetModel()->NextSibling(pEntry);
            while(pChildEntry && pChildEntry != pSiblingEntry)
            {
                SetCheckButtonState(pChildEntry,eState);
                pChildEntry = GetModel()->Next(pChildEntry);
            }
        }
        pEntry = NextSelected(pEntry);
    }
    CheckButtons();
}

//------------------------------------------------------------------------
SvLBoxEntry* OMarkableTreeListBox::GetEntryPosByName(const String& aName,SvLBoxEntry* pStart) const
{
    SvLBoxEntry* pEntry = pStart ? GetModel()->FirstChild(pStart) : GetModel()->First();
    while(pEntry && !GetEntryText(pEntry).Equals(aName))
        pEntry = GetModel()->Next(pEntry);

    return pEntry;
}

//.........................................................................
}   // namespace dbaui
//.........................................................................

<commit_msg>INTEGRATION: CWS insight01 (1.11.16); FILE MERGED 2004/07/09 14:05:15 oj 1.11.16.3: resource changes 2003/08/20 08:19:40 oj 1.11.16.2: #98349# don't display dialog if conenction could not be established 2003/08/15 08:51:04 oj 1.11.16.1: #111075# ongoing new dbaapp work<commit_after>/*************************************************************************
 *
 *  $RCSfile: marktree.cxx,v $
 *
 *  $Revision: 1.12 $
 *
 *  last change: $Author: hr $ $Date: 2004-08-02 15:36:43 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 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
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (the "License"); You may not use this file
 *  except in compliance with the License. You may obtain a copy of the
 *  License at http://www.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc..
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/

#ifndef _DBAUI_MARKTREE_HXX_
#include "marktree.hxx"
#endif
#ifndef _DBAUI_MODULE_DBU_HXX_
#include "moduledbu.hxx"
#endif
#ifndef _DBU_CONTROL_HRC_
#include "dbu_control.hrc"
#endif
#ifndef _SV_SVAPP_HXX
#include <vcl/svapp.hxx>
#endif

//.........................................................................
namespace dbaui
{
    using namespace ::com::sun::star::uno;
using namespace ::com::sun::star::lang;
//.........................................................................
#define SPACEBETWEENENTRIES     4
//========================================================================
//= OMarkableTreeListBox
//========================================================================
//------------------------------------------------------------------------
OMarkableTreeListBox::OMarkableTreeListBox( Window* pParent, const Reference< XMultiServiceFactory >& _rxORB, WinBits nWinStyle )
    : DBTreeListBox(pParent,_rxORB,nWinStyle)
{
    InitButtonData();
}
//------------------------------------------------------------------------
OMarkableTreeListBox::OMarkableTreeListBox( Window* pParent, const Reference< XMultiServiceFactory >& _rxORB, const ResId& rResId)
    : DBTreeListBox(pParent,_rxORB,rResId)
{
    InitButtonData();
}
//------------------------------------------------------------------------
OMarkableTreeListBox::~OMarkableTreeListBox()
{
    delete m_pCheckButton;
}
//------------------------------------------------------------------------
void OMarkableTreeListBox::Paint(const Rectangle& _rRect)
{
    if (!IsEnabled())
    {
        Font aOldFont = GetFont();
        Font aNewFont(aOldFont);

        StyleSettings aSystemStyle = Application::GetSettings().GetStyleSettings();
        aNewFont.SetColor(aSystemStyle.GetDisableColor());

        SetFont(aNewFont);
        DBTreeListBox::Paint(_rRect);
        SetFont(aOldFont);
    }
    else
        DBTreeListBox::Paint(_rRect);
}
//------------------------------------------------------------------------
void OMarkableTreeListBox::InitButtonData()
{
    m_pCheckButton = new SvLBoxButtonData( this );
    EnableCheckButton( m_pCheckButton );
}
//------------------------------------------------------------------------
void OMarkableTreeListBox::KeyInput( const KeyEvent& rKEvt )
{
    // nur wenn space
    if (rKEvt.GetKeyCode().GetCode() == KEY_SPACE && !rKEvt.GetKeyCode().IsShift() && !rKEvt.GetKeyCode().IsMod1())
    {
        SvLBoxEntry* pHdlEntry = GetHdlEntry();
        if(pHdlEntry)
        {
            SvButtonState eState = GetCheckButtonState( pHdlEntry);
            if(eState == SV_BUTTON_CHECKED)
                SetCheckButtonState( pHdlEntry,SV_BUTTON_UNCHECKED);
            else
                SetCheckButtonState( pHdlEntry,SV_BUTTON_CHECKED);

            CheckButtonHdl();
        }
        else
            DBTreeListBox::KeyInput(rKEvt);
    }
    else
        DBTreeListBox::KeyInput(rKEvt);

}
//------------------------------------------------------------------------
SvButtonState OMarkableTreeListBox::implDetermineState(SvLBoxEntry* _pEntry)
{
    SvButtonState eState = GetCheckButtonState(_pEntry);
    if (!GetModel()->HasChilds(_pEntry))
        // nothing to do in this bottom-up routine if there are no children ...
        return eState;
#ifdef DBG_UTIL
    String sEntryText  =GetEntryText(_pEntry);
#endif

    // loop through the children and check their states
    sal_uInt16 nCheckedChildren = 0;
    sal_uInt16 nChildrenOverall = 0;

    SvLBoxEntry* pChildLoop = GetModel()->FirstChild(_pEntry);
    while (pChildLoop)
    {
#ifdef DBG_UTIL
        String sChildText  =GetEntryText(pChildLoop);
#endif
        SvButtonState eChildState = implDetermineState(pChildLoop);
        if (SV_BUTTON_TRISTATE == eChildState)
            break;

        if (SV_BUTTON_CHECKED == eChildState)
            ++nCheckedChildren;
        ++nChildrenOverall;

        pChildLoop = GetModel()->NextSibling(pChildLoop);
    }

    if (pChildLoop)
    {
        // we did not finish the loop because at least one of the children is in tristate
        eState = SV_BUTTON_TRISTATE;

        // but this means that we did not finish all the siblings of pChildLoop, so their checking may be
        // incorrect at the moment
        // -> correct this
        // 88485 - 20.06.2001 - frank.schoenheit@sun.com
        while (pChildLoop)
        {
            implDetermineState(pChildLoop);
            pChildLoop = GetModel()->NextSibling(pChildLoop);
        }
    }
    else
        // none if the children is in tristate
        if (nCheckedChildren)
            // we have at least one chil checked
            if (nCheckedChildren != nChildrenOverall)
                // not all children are checked
                eState = SV_BUTTON_TRISTATE;
            else
                // all children are checked
                eState = SV_BUTTON_CHECKED;
        else
            // no children are checked
            eState = SV_BUTTON_UNCHECKED;

    // finally set the entry to the state we just determined
    SetCheckButtonState(_pEntry, eState);

    // outta here
    return eState;
}

//------------------------------------------------------------------------
void OMarkableTreeListBox::CheckButtons()
{
    SvLBoxEntry* pEntry = GetModel()->First();
    while (pEntry)
    {
        implDetermineState(pEntry);
        pEntry = GetModel()->NextSibling(pEntry);
    }

#if 0
    // Plausibilit"atspr"ufung
    SvButtonState eState;
    SvLBoxEntry* pEntry = GetModel()->First();
    while(pEntry)
    {
        if(!GetModel()->HasChilds(pEntry))
        {
            sal_uInt16 nCheck=0;
            sal_uInt16 nCount=0;
            SvLBoxEntry* pChildEntry = pEntry;
            while(pChildEntry)
            {
                if(GetCheckButtonState(pChildEntry) == SV_BUTTON_CHECKED)
                    nCheck++;
                nCount++;
                pChildEntry = GetModel()->NextSibling(pChildEntry);
            }

            if(nCheck && nCount != nCheck)
                eState = SV_BUTTON_TRISTATE;
            else if(nCheck)
                eState = SV_BUTTON_CHECKED;
            else
                eState = SV_BUTTON_UNCHECKED;

            SvLBoxEntry* pSchema = GetModel()->GetParent(pEntry);
            if(pSchema)
            {
                pEntry = GetModel()->NextSibling(pSchema);
                SetCheckButtonState(pSchema, eState);
            }
            else
                pEntry = NULL; // wenn kein Schema dann sind bereits alle pEntry's durchlaufen worden
        }
        else
            pEntry = GetModel()->Next(pEntry);
    }

    SvLBoxEntry* pCatalog = GetModel()->First();
    SvLBoxEntry* pSchema = NULL;
    if(GetModel()->HasChilds(pCatalog) && GetModel()->HasChilds(pSchema = GetModel()->Next(pCatalog)))
    {
        sal_uInt16 nCheck   =0;
        sal_uInt16 nTri     =0;
        sal_uInt16 nCount   =0;
        while(pSchema)
        {
            if((eState = GetCheckButtonState(pSchema)) == SV_BUTTON_TRISTATE)
                break;

            if(eState == SV_BUTTON_CHECKED)
                nCheck++;
            nCount++;
            pSchema = GetModel()->NextSibling(pSchema);
        }

        if(eState != SV_BUTTON_TRISTATE)
        {
            if(nCheck && nCount == nCheck)
                eState = SV_BUTTON_CHECKED;
            else if(nCheck)
                eState = SV_BUTTON_TRISTATE;
            else
                eState = SV_BUTTON_UNCHECKED;
        }
        SetCheckButtonState( pCatalog,eState);
    }
#endif
}
//------------------------------------------------------------------------
void OMarkableTreeListBox::CheckButtonHdl()
{
    checkedButton_noBroadcast(GetHdlEntry());
    if (m_aCheckButtonHandler.IsSet())
        m_aCheckButtonHandler.Call(this);
}

//------------------------------------------------------------------------
void OMarkableTreeListBox::checkedButton_noBroadcast(SvLBoxEntry* _pEntry)
{
    SvButtonState eState = GetCheckButtonState( _pEntry);
    if (GetModel()->HasChilds(_pEntry)) // Falls Kinder, dann diese auch checken
    {
        SvLBoxEntry* pChildEntry = GetModel()->Next(_pEntry);
        SvLBoxEntry* pSiblingEntry = GetModel()->NextSibling(_pEntry);
        while(pChildEntry && pChildEntry != pSiblingEntry)
        {
            SetCheckButtonState(pChildEntry, eState);
            pChildEntry = GetModel()->Next(pChildEntry);
        }
    }

    SvLBoxEntry* pEntry = IsSelected(_pEntry) ? FirstSelected() : NULL;
    while(pEntry)
    {
        SetCheckButtonState(pEntry,eState);
        if(GetModel()->HasChilds(pEntry))   // Falls Kinder, dann diese auch checken
        {
            SvLBoxEntry* pChildEntry = GetModel()->Next(pEntry);
            SvLBoxEntry* pSiblingEntry = GetModel()->NextSibling(pEntry);
            while(pChildEntry && pChildEntry != pSiblingEntry)
            {
                SetCheckButtonState(pChildEntry,eState);
                pChildEntry = GetModel()->Next(pChildEntry);
            }
        }
        pEntry = NextSelected(pEntry);
    }
    CheckButtons();
}

//------------------------------------------------------------------------
//.........................................................................
}   // namespace dbaui
//.........................................................................

<|endoftext|>


<commit_before>// The libMesh Finite Element Library.
// Copyright (C) 2002-2012 Benjamin S. Kirk, John W. Peterson, Roy H. Stogner

// 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

// Local includes
#include "libmesh/edge.h"
#include "libmesh/node_elem.h"

namespace libMesh
{

AutoPtr<Elem> Edge::side (const unsigned int i) const
{
  libmesh_assert_less (i, 2);
  const Elem* parent = this;
  Elem *nodeelem = new NodeElem(const_cast<Elem*>(parent));
  nodeelem->set_node(0) = this->get_node(i);
  return AutoPtr<Elem>(nodeelem);
}

AutoPtr<Elem> Edge::build_side (const unsigned int i, bool) const
{
  libmesh_assert_less (i, 2);
  const Elem* parent = this;
  Elem *nodeelem = new NodeElem(const_cast<Elem*>(parent));
  nodeelem->set_node(0) = this->get_node(i);
  return AutoPtr<Elem>(nodeelem);
}

bool Edge::is_child_on_side(const unsigned int c,
                            const unsigned int s) const
{
  libmesh_assert_less (c, this->n_children());
  libmesh_assert_less (s, this->n_sides());

  return (c == s);
}

unsigned int Edge::opposite_side(const unsigned int side) const
{
  libmesh_assert_less (side, 2);
  return 1 - side;
}

unsigned int Edge::opposite_node(const unsigned int node,
                                 const unsigned int libmesh_dbg_var(side)) const
{
  libmesh_assert_less (node, 2);
  libmesh_assert_less (side, this->n_sides());
  libmesh_assert(this->is_node_on_side(node, side));

  return 1 - node;
}

} // namespace libMesh
<commit_msg>Changes in edge.C for -Wshadow.<commit_after>// The libMesh Finite Element Library.
// Copyright (C) 2002-2012 Benjamin S. Kirk, John W. Peterson, Roy H. Stogner

// 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

// Local includes
#include "libmesh/edge.h"
#include "libmesh/node_elem.h"

namespace libMesh
{

AutoPtr<Elem> Edge::side (const unsigned int i) const
{
  libmesh_assert_less (i, 2);
  const Elem* the_parent = this;
  Elem *nodeelem = new NodeElem(const_cast<Elem*>(the_parent));
  nodeelem->set_node(0) = this->get_node(i);
  return AutoPtr<Elem>(nodeelem);
}

AutoPtr<Elem> Edge::build_side (const unsigned int i, bool) const
{
  libmesh_assert_less (i, 2);
  const Elem* the_parent = this;
  Elem *nodeelem = new NodeElem(const_cast<Elem*>(the_parent));
  nodeelem->set_node(0) = this->get_node(i);
  return AutoPtr<Elem>(nodeelem);
}

bool Edge::is_child_on_side(const unsigned int c,
                            const unsigned int s) const
{
  libmesh_assert_less (c, this->n_children());
  libmesh_assert_less (s, this->n_sides());

  return (c == s);
}

unsigned int Edge::opposite_side(const unsigned int side_in) const
{
  libmesh_assert_less (side_in, 2);
  return 1 - side_in;
}

unsigned int Edge::opposite_node(const unsigned int node_in,
                                 const unsigned int libmesh_dbg_var(side_in)) const
{
  libmesh_assert_less (node_in, 2);
  libmesh_assert_less (side_in, this->n_sides());
  libmesh_assert(this->is_node_on_side(node_in, side_in));

  return 1 - node_in;
}

} // namespace libMesh
<|endoftext|>


<commit_before>/*

    OpenPnp-Capture: a video capture subsystem.

    Windows platform/implementation specific structures and typedefs.

    The platform classes are also responsible for converting
    the frames into 24-bit per pixel RGB frames.

    Created by Niels Moseley on 7/6/17.
    Copyright (c) 2017 Niels Moseley.

    Permission is hereby granted, free of charge, to any person obtaining a copy
    of this software and associated documentation files (the "Software"), to deal
    in the Software without restriction, including without limitation the rights
    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
    copies of the Software, and to permit persons to whom the Software is
    furnished to do so, subject to the following conditions:

    The above copyright notice and this permission notice shall be included in all
    copies or substantial portions of the Software.

    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
    SOFTWARE.
*/

#include <vector>
#include <stdio.h>

#include <windows.h>
#include <mmsystem.h> // for MAKEFOURCC macro

#include "../common/logging.h"
#include "scopedcomptr.h"
#include "platformstream.h"
#include "platformcontext.h"

// a platform factory function needed by
// libmain.cpp
Context* createPlatformContext()
{
    return new PlatformContext();
}

PlatformContext::PlatformContext() : Context()
{
    HRESULT hr;
    hr = CoInitializeEx(NULL, COINIT_MULTITHREADED);
    if (hr != S_OK)
    {
        // This might happen when another part of the program
        // as already called CoInitializeEx.
        // and we can carry on without problems...
        LOG(LOG_WARNING, "PlatformContext::CoInitializeEx failed (HRESULT = %08X)!\n", hr);
    }
    else
    {
        LOG(LOG_DEBUG, "PlatformContext created\n");
    }

    enumerateDevices();
}

PlatformContext::~PlatformContext()
{
    CoUninitialize();
}

bool PlatformContext::enumerateDevices()
{
    ICreateDevEnum*		dev_enum = nullptr;
	IEnumMoniker*		enum_moniker = nullptr;
	IMoniker*			moniker = nullptr;
	IPropertyBag*		pbag = nullptr;

    LOG(LOG_DEBUG, "Enumerating devices\n");

    m_devices.clear();

	//create an enumerator for video input devices
	HRESULT hr = CoCreateInstance(CLSID_SystemDeviceEnum, NULL,CLSCTX_INPROC_SERVER,IID_ICreateDevEnum,(void**) &dev_enum);
	if ((hr != S_OK) || (dev_enum == nullptr))
    {
        LOG(LOG_CRIT, "Could not create ICreateDevEnum object\n");
        return false;
    }
    else
    {
        LOG(LOG_DEBUG, "ICreateDevEnum created\n");
    }

    ScopedComPtr<ICreateDevEnum> devEnum(dev_enum);

	hr = devEnum->CreateClassEnumerator(CLSID_VideoInputDeviceCategory,&enum_moniker, 0);
	if (hr == S_FALSE)
    {
        // no devices found!
        LOG(LOG_INFO, "No devices found\n");
        return true;
    }
    if (hr != S_OK)
    {
        LOG(LOG_CRIT, "Could not create class enumerator object\n");
        return false;
    }

    ScopedComPtr<IEnumMoniker> enumMoniker(enum_moniker);

	//get devices
	uint32_t num_devices = 0;
    VARIANT name;
	while (enumMoniker->Next(1, &moniker,0) == S_OK)
	{
		//get properties
		hr = moniker->BindToStorage(0, 0, IID_IPropertyBag, (void**) &pbag);

		if (hr >= 0)
		{
            platformDeviceInfo *info = new platformDeviceInfo();
			VariantInit(&name);

			//get the description
			hr = pbag->Read(L"Description", &name, 0);
			if (hr < 0) hr = pbag->Read(L"FriendlyName", &name, 0);
			if (hr >= 0)
			{
				BSTR BStringPtr = name.bstrVal;

                if (BStringPtr)
                {
                    // copy wchar device name into info structure so we can reference the
                    // device later
                    info->m_filterName = std::wstring(BStringPtr);

                    // convert wchar string to UTF-8 to pass to JAVA
                    info->m_name = wcharPtrToString(BStringPtr);
                    info->m_uniqueID = info->m_name;
                }
            }
            else
            {
                LOG(LOG_ERR, "Could not generate device name for device!\n");
            }

            hr = pbag->Read(L"DevicePath", &name, 0);
            if (hr >= 0 && name.bstrVal)
            {
                info->m_devicePath = std::wstring(name.bstrVal);
            }
            else {
                LOG(LOG_WARNING, "     device path not found! fallback to using device index...\n");
                info->m_devicePath = std::to_wstring(num_devices);
            }

            info->m_uniqueID.append(" ");
            info->m_uniqueID.append(wstringToString(info->m_devicePath));
            LOG(LOG_INFO, "     -> PATH %s\n", wstringToString(info->m_devicePath).c_str());

            enumerateFrameInfo(moniker, info);
            m_devices.push_back(info);

            LOG(LOG_INFO, "ID %d -> %s\n", num_devices, info->m_name.c_str());

            VariantClear(&name);

            pbag->Release();
            pbag = nullptr;

            moniker->Release();
            moniker = nullptr;

            num_devices++;
        }
        else{
            moniker->Release();
        }
    }
    return true;
}

std::string PlatformContext::wstringToString(const std::wstring &wstr)
{
    return wcharPtrToString(wstr.c_str());
}

std::string PlatformContext::wcharPtrToString(const wchar_t *sstr)
{
    std::vector<char> buffer;
    int32_t chars = WideCharToMultiByte(CP_UTF8, 0, sstr, -1, nullptr, 0, nullptr, nullptr);
    if (chars == 0) return std::string("");

    buffer.resize(chars);
    WideCharToMultiByte(CP_UTF8, 0, sstr, -1, &buffer[0], chars, nullptr, nullptr);
    return std::string(&buffer[0]);
}

// Release the format block for a media type.
void _FreeMediaType(AM_MEDIA_TYPE& mt)
{
    if (mt.cbFormat != 0)
    {
        CoTaskMemFree((PVOID)mt.pbFormat);
        mt.cbFormat = 0;
        mt.pbFormat = NULL;
    }
    if (mt.pUnk != NULL)
    {
        // pUnk should not be used.
        mt.pUnk->Release();
        mt.pUnk = NULL;
    }
}

// Delete a media type structure that was allocated on the heap.
void _DeleteMediaType(AM_MEDIA_TYPE *pmt)
{
    if (pmt != NULL)
    {
        _FreeMediaType(*pmt);
        CoTaskMemFree(pmt);
    }
}

bool PinMatchesCategory(IPin *pPin, REFGUID Category)
{
    bool bFound = FALSE;

    IKsPropertySet *pKs = NULL;
    HRESULT hr = pPin->QueryInterface(IID_PPV_ARGS(&pKs));
    if (SUCCEEDED(hr))
    {
        GUID PinCategory;
        DWORD cbReturned;
        hr = pKs->Get(AMPROPSETID_Pin, AMPROPERTY_PIN_CATEGORY, NULL, 0,
            &PinCategory, sizeof(GUID), &cbReturned);
        if (SUCCEEDED(hr) && (cbReturned == sizeof(GUID)))
        {
            bFound = (PinCategory == Category);
        }
        pKs->Release();
    }
    return bFound;
}

HRESULT FindPinByCategory(
    IBaseFilter *pFilter, // Pointer to the filter to search.
    PIN_DIRECTION PinDir, // Direction of the pin.
    REFGUID Category,     // Pin category.
    IPin **ppPin)         // Receives a pointer to the pin.
{
    *ppPin = 0;

    HRESULT hr = S_OK;
    BOOL bFound = FALSE;

    IEnumPins *pEnum = 0;
    IPin *pPin = 0;

    hr = pFilter->EnumPins(&pEnum);
    if (FAILED(hr))
    {
        return hr;
    }

    ScopedComPtr<IEnumPins> pinEnum(pEnum);

    while (hr = pinEnum->Next(1, &pPin, 0), hr == S_OK)
    {
        PIN_DIRECTION ThisPinDir;
        hr = pPin->QueryDirection(&ThisPinDir);
        if (FAILED(hr))
        {
            return hr;
        }

        ScopedComPtr<IPin> myPin(pPin);

        if ((ThisPinDir == PinDir) &&
            PinMatchesCategory(pPin, Category))
        {
            *ppPin = pPin;
            (*ppPin)->AddRef();   // The caller must release the interface.
            return S_OK;
        }
    }

    return E_FAIL;
}

bool PlatformContext::enumerateFrameInfo(IMoniker *moniker, platformDeviceInfo *info)
{
    IBaseFilter *pCap  = NULL;
    IEnumPins   *pEnum = NULL;
    IPin        *pPin  = NULL;

    LOG(LOG_DEBUG, "enumerateFrameInfo() called\n");

    HRESULT hr = moniker->BindToObject(0, 0, IID_IBaseFilter, (void**)&pCap);
    if (!SUCCEEDED(hr))
    {
        LOG(LOG_ERR, "No frame information: BindToObject failed.\n");
        return false;
    }

    ScopedComPtr<IBaseFilter> baseFilter(pCap);

    hr = baseFilter->EnumPins(&pEnum);
    if (FAILED(hr))
    {
        LOG(LOG_ERR, "No frame information: EnumPins failed.\n");
        return false;
    }
    ScopedComPtr<IEnumPins> pinEnum(pEnum);
    if (FindPinByCategory(pCap, PINDIR_OUTPUT, PIN_CATEGORY_CAPTURE, &pPin) == S_OK)
    {
        LOG(LOG_INFO, "Capture pin found!\n");
    }
    else
    {
        LOG(LOG_ERR, "Could not find capture pin!\n");
        return false;
    }

    ScopedComPtr<IPin> capturePin(pPin);

    // retrieve an IAMStreamConfig interface
    IAMStreamConfig *pConfig = NULL;
    if (capturePin->QueryInterface(IID_IAMStreamConfig, (void**)&pConfig) != S_OK)
    {
        LOG(LOG_ERR, "Could not create IAMStreamConfig interface!\n");
        return false;
    }

    ScopedComPtr<IAMStreamConfig> streamConfig(pConfig);

    int iCount = 0, iSize = 0;
    hr = pConfig->GetNumberOfCapabilities(&iCount, &iSize);

    LOG(LOG_INFO,"Stream has %d capabilities.\n", iCount);

    // Check the size to make sure we pass in the correct structure.
    if (iSize == sizeof(VIDEO_STREAM_CONFIG_CAPS))
    {
        // Use the video capabilities structure.

        for (int32_t iFormat = 0; iFormat < iCount; iFormat++)
        {
            VIDEO_STREAM_CONFIG_CAPS scc;
            AM_MEDIA_TYPE *pmtConfig;
            hr = pConfig->GetStreamCaps(iFormat, &pmtConfig, (BYTE*)&scc);
            if (SUCCEEDED(hr))
            {
                /* Examine the format, and possibly use it. */
                if (pmtConfig->formattype == FORMAT_VideoInfo)
                {
                    // Check the buffer size.
                    if (pmtConfig->cbFormat >= sizeof(VIDEOINFOHEADER))
                    {
                        VIDEOINFOHEADER *pVih = reinterpret_cast<VIDEOINFOHEADER*>(pmtConfig->pbFormat);
                        CapFormatInfo newFrameInfo;
                        if (pVih != nullptr)
                        {
                            newFrameInfo.bpp = pVih->bmiHeader.biBitCount;
                            if (pVih->bmiHeader.biCompression == BI_RGB)
                            {
                                newFrameInfo.fourcc = MAKEFOURCC('R', 'G', 'B', ' ');
                            }
                            else if (pVih->bmiHeader.biCompression == BI_BITFIELDS)
                            {
                                newFrameInfo.fourcc = MAKEFOURCC(' ', ' ', ' ', ' ');
                            }
                            else
                            {
                                newFrameInfo.fourcc = pVih->bmiHeader.biCompression;
                            }

                            newFrameInfo.width  = pVih->bmiHeader.biWidth;
                            newFrameInfo.height = pVih->bmiHeader.biHeight;

                            if (pVih->AvgTimePerFrame != 0)
                            {
                                // pVih->AvgTimePerFrame is in units of 100ns
                                newFrameInfo.fps = static_cast<uint32_t>(10.0e6f/static_cast<float>(pVih->AvgTimePerFrame));
                            }
                            else
                            {
                                newFrameInfo.fps = 0;
                            }

                            std::string fourCCString = fourCCToString(newFrameInfo.fourcc);

                            LOG(LOG_INFO, "%d x %d  %d fps  %d bpp FOURCC=%s\n", newFrameInfo.width, newFrameInfo.height,
                                newFrameInfo.fps, newFrameInfo.bpp, fourCCString.c_str());

                            info->m_formats.push_back(newFrameInfo);
                        }
                    }
                }
                // Delete the media type when you are done.
                _DeleteMediaType(pmtConfig);
            }
        }
    }

    return true;
}

HRESULT FindCaptureDevice(IBaseFilter** ppSrcFilter, const wchar_t* devicePath)
{
    HRESULT hr = S_OK;

    std::wstring strDevicePath = devicePath;

    ICreateDevEnum* pDevEnum = nullptr;
    hr = CoCreateInstance(CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&pDevEnum));
    if (FAILED(hr)) {
        return hr;
    }
    ScopedComPtr<ICreateDevEnum> devEnum(pDevEnum);

    IEnumMoniker* pEnumMoniker = nullptr;
    hr = devEnum->CreateClassEnumerator(CLSID_VideoInputDeviceCategory, &pEnumMoniker, 0);
    if(FAILED(hr)) {
        return hr;
    }
    ScopedComPtr<IEnumMoniker> enumMoniker(pEnumMoniker);

    IMoniker* pMoniker = nullptr;
    for(int num_devices = 0; enumMoniker->Next(1, &pMoniker, 0) == S_OK; ++num_devices)
    {
        ScopedComPtr<IMoniker> moniker(pMoniker);

        IPropertyBag* pbag = nullptr;
        hr = moniker->BindToStorage(0, 0, IID_PPV_ARGS(&pbag));
        if(FAILED(hr)) {
            continue;  // Skip this one, maybe the next one will work.
        }
        ScopedComPtr<IPropertyBag> propertyBag(pbag);

        VARIANT varName;
        VariantInit(&varName);
        hr = pbag->Read(L"DevicePath", &varName, 0);
        if ((SUCCEEDED(hr) && strDevicePath == varName.bstrVal) ||
            (FAILED(hr) && strDevicePath == std::to_wstring(num_devices))) {
            VariantClear(&varName);
            if (bMatch)
            {
                hr = pMoniker->BindToObject(0, 0, IID_PPV_ARGS(ppSrcFilter));
                pMoniker->Release();
                return hr;
            }
        }
        VariantClear(&varName);
    }

    return E_FAIL;
}

<commit_msg>(Hopefully) fix my bad merge.<commit_after>/*

    OpenPnp-Capture: a video capture subsystem.

    Windows platform/implementation specific structures and typedefs.

    The platform classes are also responsible for converting
    the frames into 24-bit per pixel RGB frames.

    Created by Niels Moseley on 7/6/17.
    Copyright (c) 2017 Niels Moseley.

    Permission is hereby granted, free of charge, to any person obtaining a copy
    of this software and associated documentation files (the "Software"), to deal
    in the Software without restriction, including without limitation the rights
    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
    copies of the Software, and to permit persons to whom the Software is
    furnished to do so, subject to the following conditions:

    The above copyright notice and this permission notice shall be included in all
    copies or substantial portions of the Software.

    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
    SOFTWARE.
*/

#include <vector>
#include <stdio.h>

#include <windows.h>
#include <mmsystem.h> // for MAKEFOURCC macro

#include "../common/logging.h"
#include "scopedcomptr.h"
#include "platformstream.h"
#include "platformcontext.h"

// a platform factory function needed by
// libmain.cpp
Context* createPlatformContext()
{
    return new PlatformContext();
}

PlatformContext::PlatformContext() : Context()
{
    HRESULT hr;
    hr = CoInitializeEx(NULL, COINIT_MULTITHREADED);
    if (hr != S_OK)
    {
        // This might happen when another part of the program
        // as already called CoInitializeEx.
        // and we can carry on without problems...
        LOG(LOG_WARNING, "PlatformContext::CoInitializeEx failed (HRESULT = %08X)!\n", hr);
    }
    else
    {
        LOG(LOG_DEBUG, "PlatformContext created\n");
    }

    enumerateDevices();
}

PlatformContext::~PlatformContext()
{
    CoUninitialize();
}

bool PlatformContext::enumerateDevices()
{
    ICreateDevEnum*		dev_enum = nullptr;
	IEnumMoniker*		enum_moniker = nullptr;
	IMoniker*			moniker = nullptr;
	IPropertyBag*		pbag = nullptr;

    LOG(LOG_DEBUG, "Enumerating devices\n");

    m_devices.clear();

	//create an enumerator for video input devices
	HRESULT hr = CoCreateInstance(CLSID_SystemDeviceEnum, NULL,CLSCTX_INPROC_SERVER,IID_ICreateDevEnum,(void**) &dev_enum);
	if ((hr != S_OK) || (dev_enum == nullptr))
    {
        LOG(LOG_CRIT, "Could not create ICreateDevEnum object\n");
        return false;
    }
    else
    {
        LOG(LOG_DEBUG, "ICreateDevEnum created\n");
    }

    ScopedComPtr<ICreateDevEnum> devEnum(dev_enum);

	hr = devEnum->CreateClassEnumerator(CLSID_VideoInputDeviceCategory,&enum_moniker, 0);
	if (hr == S_FALSE)
    {
        // no devices found!
        LOG(LOG_INFO, "No devices found\n");
        return true;
    }
    if (hr != S_OK)
    {
        LOG(LOG_CRIT, "Could not create class enumerator object\n");
        return false;
    }

    ScopedComPtr<IEnumMoniker> enumMoniker(enum_moniker);

	//get devices
	uint32_t num_devices = 0;
    VARIANT name;
	while (enumMoniker->Next(1, &moniker,0) == S_OK)
	{
		//get properties
		hr = moniker->BindToStorage(0, 0, IID_IPropertyBag, (void**) &pbag);

		if (hr >= 0)
		{
            platformDeviceInfo *info = new platformDeviceInfo();
			VariantInit(&name);

			//get the description
			hr = pbag->Read(L"Description", &name, 0);
			if (hr < 0) hr = pbag->Read(L"FriendlyName", &name, 0);
			if (hr >= 0)
			{
				BSTR BStringPtr = name.bstrVal;

                if (BStringPtr)
                {
                    // copy wchar device name into info structure so we can reference the
                    // device later
                    info->m_filterName = std::wstring(BStringPtr);

                    // convert wchar string to UTF-8 to pass to JAVA
                    info->m_name = wcharPtrToString(BStringPtr);
                    info->m_uniqueID = info->m_name;
                }
            }
            else
            {
                LOG(LOG_ERR, "Could not generate device name for device!\n");
            }

            hr = pbag->Read(L"DevicePath", &name, 0);
            if (hr >= 0 && name.bstrVal)
            {
                info->m_devicePath = std::wstring(name.bstrVal);
            }
            else {
                LOG(LOG_WARNING, "     device path not found! fallback to using device index...\n");
                info->m_devicePath = std::to_wstring(num_devices);
            }

            info->m_uniqueID.append(" ");
            info->m_uniqueID.append(wstringToString(info->m_devicePath));
            LOG(LOG_INFO, "     -> PATH %s\n", wstringToString(info->m_devicePath).c_str());

            enumerateFrameInfo(moniker, info);
            m_devices.push_back(info);

            LOG(LOG_INFO, "ID %d -> %s\n", num_devices, info->m_name.c_str());

            VariantClear(&name);

            pbag->Release();
            pbag = nullptr;

            moniker->Release();
            moniker = nullptr;

            num_devices++;
        }
        else{
            moniker->Release();
        }
    }
    return true;
}

std::string PlatformContext::wstringToString(const std::wstring &wstr)
{
    return wcharPtrToString(wstr.c_str());
}

std::string PlatformContext::wcharPtrToString(const wchar_t *sstr)
{
    std::vector<char> buffer;
    int32_t chars = WideCharToMultiByte(CP_UTF8, 0, sstr, -1, nullptr, 0, nullptr, nullptr);
    if (chars == 0) return std::string("");

    buffer.resize(chars);
    WideCharToMultiByte(CP_UTF8, 0, sstr, -1, &buffer[0], chars, nullptr, nullptr);
    return std::string(&buffer[0]);
}

// Release the format block for a media type.
void _FreeMediaType(AM_MEDIA_TYPE& mt)
{
    if (mt.cbFormat != 0)
    {
        CoTaskMemFree((PVOID)mt.pbFormat);
        mt.cbFormat = 0;
        mt.pbFormat = NULL;
    }
    if (mt.pUnk != NULL)
    {
        // pUnk should not be used.
        mt.pUnk->Release();
        mt.pUnk = NULL;
    }
}

// Delete a media type structure that was allocated on the heap.
void _DeleteMediaType(AM_MEDIA_TYPE *pmt)
{
    if (pmt != NULL)
    {
        _FreeMediaType(*pmt);
        CoTaskMemFree(pmt);
    }
}

bool PinMatchesCategory(IPin *pPin, REFGUID Category)
{
    bool bFound = FALSE;

    IKsPropertySet *pKs = NULL;
    HRESULT hr = pPin->QueryInterface(IID_PPV_ARGS(&pKs));
    if (SUCCEEDED(hr))
    {
        GUID PinCategory;
        DWORD cbReturned;
        hr = pKs->Get(AMPROPSETID_Pin, AMPROPERTY_PIN_CATEGORY, NULL, 0,
            &PinCategory, sizeof(GUID), &cbReturned);
        if (SUCCEEDED(hr) && (cbReturned == sizeof(GUID)))
        {
            bFound = (PinCategory == Category);
        }
        pKs->Release();
    }
    return bFound;
}

HRESULT FindPinByCategory(
    IBaseFilter *pFilter, // Pointer to the filter to search.
    PIN_DIRECTION PinDir, // Direction of the pin.
    REFGUID Category,     // Pin category.
    IPin **ppPin)         // Receives a pointer to the pin.
{
    *ppPin = 0;

    HRESULT hr = S_OK;
    BOOL bFound = FALSE;

    IEnumPins *pEnum = 0;
    IPin *pPin = 0;

    hr = pFilter->EnumPins(&pEnum);
    if (FAILED(hr))
    {
        return hr;
    }

    ScopedComPtr<IEnumPins> pinEnum(pEnum);

    while (hr = pinEnum->Next(1, &pPin, 0), hr == S_OK)
    {
        PIN_DIRECTION ThisPinDir;
        hr = pPin->QueryDirection(&ThisPinDir);
        if (FAILED(hr))
        {
            return hr;
        }

        ScopedComPtr<IPin> myPin(pPin);

        if ((ThisPinDir == PinDir) &&
            PinMatchesCategory(pPin, Category))
        {
            *ppPin = pPin;
            (*ppPin)->AddRef();   // The caller must release the interface.
            return S_OK;
        }
    }

    return E_FAIL;
}

bool PlatformContext::enumerateFrameInfo(IMoniker *moniker, platformDeviceInfo *info)
{
    IBaseFilter *pCap  = NULL;
    IEnumPins   *pEnum = NULL;
    IPin        *pPin  = NULL;

    LOG(LOG_DEBUG, "enumerateFrameInfo() called\n");

    HRESULT hr = moniker->BindToObject(0, 0, IID_IBaseFilter, (void**)&pCap);
    if (!SUCCEEDED(hr))
    {
        LOG(LOG_ERR, "No frame information: BindToObject failed.\n");
        return false;
    }

    ScopedComPtr<IBaseFilter> baseFilter(pCap);

    hr = baseFilter->EnumPins(&pEnum);
    if (FAILED(hr))
    {
        LOG(LOG_ERR, "No frame information: EnumPins failed.\n");
        return false;
    }
    ScopedComPtr<IEnumPins> pinEnum(pEnum);
    if (FindPinByCategory(pCap, PINDIR_OUTPUT, PIN_CATEGORY_CAPTURE, &pPin) == S_OK)
    {
        LOG(LOG_INFO, "Capture pin found!\n");
    }
    else
    {
        LOG(LOG_ERR, "Could not find capture pin!\n");
        return false;
    }

    ScopedComPtr<IPin> capturePin(pPin);

    // retrieve an IAMStreamConfig interface
    IAMStreamConfig *pConfig = NULL;
    if (capturePin->QueryInterface(IID_IAMStreamConfig, (void**)&pConfig) != S_OK)
    {
        LOG(LOG_ERR, "Could not create IAMStreamConfig interface!\n");
        return false;
    }

    ScopedComPtr<IAMStreamConfig> streamConfig(pConfig);

    int iCount = 0, iSize = 0;
    hr = pConfig->GetNumberOfCapabilities(&iCount, &iSize);

    LOG(LOG_INFO,"Stream has %d capabilities.\n", iCount);

    // Check the size to make sure we pass in the correct structure.
    if (iSize == sizeof(VIDEO_STREAM_CONFIG_CAPS))
    {
        // Use the video capabilities structure.

        for (int32_t iFormat = 0; iFormat < iCount; iFormat++)
        {
            VIDEO_STREAM_CONFIG_CAPS scc;
            AM_MEDIA_TYPE *pmtConfig;
            hr = pConfig->GetStreamCaps(iFormat, &pmtConfig, (BYTE*)&scc);
            if (SUCCEEDED(hr))
            {
                /* Examine the format, and possibly use it. */
                if (pmtConfig->formattype == FORMAT_VideoInfo)
                {
                    // Check the buffer size.
                    if (pmtConfig->cbFormat >= sizeof(VIDEOINFOHEADER))
                    {
                        VIDEOINFOHEADER *pVih = reinterpret_cast<VIDEOINFOHEADER*>(pmtConfig->pbFormat);
                        CapFormatInfo newFrameInfo;
                        if (pVih != nullptr)
                        {
                            newFrameInfo.bpp = pVih->bmiHeader.biBitCount;
                            if (pVih->bmiHeader.biCompression == BI_RGB)
                            {
                                newFrameInfo.fourcc = MAKEFOURCC('R', 'G', 'B', ' ');
                            }
                            else if (pVih->bmiHeader.biCompression == BI_BITFIELDS)
                            {
                                newFrameInfo.fourcc = MAKEFOURCC(' ', ' ', ' ', ' ');
                            }
                            else
                            {
                                newFrameInfo.fourcc = pVih->bmiHeader.biCompression;
                            }

                            newFrameInfo.width  = pVih->bmiHeader.biWidth;
                            newFrameInfo.height = pVih->bmiHeader.biHeight;

                            if (pVih->AvgTimePerFrame != 0)
                            {
                                // pVih->AvgTimePerFrame is in units of 100ns
                                newFrameInfo.fps = static_cast<uint32_t>(10.0e6f/static_cast<float>(pVih->AvgTimePerFrame));
                            }
                            else
                            {
                                newFrameInfo.fps = 0;
                            }

                            std::string fourCCString = fourCCToString(newFrameInfo.fourcc);

                            LOG(LOG_INFO, "%d x %d  %d fps  %d bpp FOURCC=%s\n", newFrameInfo.width, newFrameInfo.height,
                                newFrameInfo.fps, newFrameInfo.bpp, fourCCString.c_str());

                            info->m_formats.push_back(newFrameInfo);
                        }
                    }
                }
                // Delete the media type when you are done.
                _DeleteMediaType(pmtConfig);
            }
        }
    }

    return true;
}

HRESULT FindCaptureDevice(IBaseFilter** ppSrcFilter, const wchar_t* devicePath)
{
    HRESULT hr = S_OK;

    std::wstring strDevicePath = devicePath;

    ICreateDevEnum* pDevEnum = nullptr;
    hr = CoCreateInstance(CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&pDevEnum));
    if (FAILED(hr)) {
        return hr;
    }
    ScopedComPtr<ICreateDevEnum> devEnum(pDevEnum);

    IEnumMoniker* pEnumMoniker = nullptr;
    hr = devEnum->CreateClassEnumerator(CLSID_VideoInputDeviceCategory, &pEnumMoniker, 0);
    if(FAILED(hr)) {
        return hr;
    }
    ScopedComPtr<IEnumMoniker> enumMoniker(pEnumMoniker);

    IMoniker* pMoniker = nullptr;
    for(int num_devices = 0; enumMoniker->Next(1, &pMoniker, 0) == S_OK; ++num_devices)
    {
        ScopedComPtr<IMoniker> moniker(pMoniker);

        IPropertyBag* pbag = nullptr;
        hr = moniker->BindToStorage(0, 0, IID_PPV_ARGS(&pbag));
        if(FAILED(hr)) {
            continue;  // Skip this one, maybe the next one will work.
        }
        ScopedComPtr<IPropertyBag> propertyBag(pbag);

        VARIANT varName;
        VariantInit(&varName);
        hr = pbag->Read(L"DevicePath", &varName, 0);
        if ((SUCCEEDED(hr) && strDevicePath == varName.bstrVal) ||
            (FAILED(hr) && strDevicePath == std::to_wstring(num_devices))) {
            VariantClear(&varName);
            hr = pMoniker->BindToObject(0, 0, IID_PPV_ARGS(ppSrcFilter));
            pMoniker->Release();
            return hr;
        }
        VariantClear(&varName);
    }

    return E_FAIL;
}

<|endoftext|>