<commit_before>#include "TChain.h"
#include "TTree.h"
#include "TList.h"
#include "TH2F.h"
#include "TF1.h"
#include "TCanvas.h"
#include "TLorentzVector.h"

#include "AliAnalysisTask.h"
#include "AliAnalysisManager.h"

#include "AliESDEvent.h"
#include "AliESDInputHandler.h"
#include "AliAODEvent.h"
#include "AliAODInputHandler.h"

#include "AliProtonAnalysis.h"
#include "AliAnalysisTaskProtons.h"

// Analysis task creating a the 2d y-p_t spectrum of p and antip
// Author: Panos Cristakoglou

ClassImp(AliAnalysisTaskProtons)

//________________________________________________________________________
AliAnalysisTaskProtons::AliAnalysisTaskProtons()
: AliAnalysisTask(name, ""), fESD(0), fAOD(0), fAnalysisType("ESD"),
  fList(0), fAnalysis(0),
  fElectronFunction(0), fMuonFunction(0),
  fPionFunction(0), fKaonFunction(0), fProtonFunction(0),
  fFunctionUsed(kFALSE) {
  //Dummy constructor
}

//________________________________________________________________________
AliAnalysisTaskProtons::AliAnalysisTaskProtons(const char *name)
: AliAnalysisTask(name, ""), fESD(0), fAOD(0), fAnalysisType("ESD"),
  fList(0), fAnalysis(0),
  fElectronFunction(0), fMuonFunction(0),
  fPionFunction(0), fKaonFunction(0), fProtonFunction(0),
  fFunctionUsed(kFALSE) {
  // Constructor

  // Define input and output slots here
  // Input slot #0 works with a TChain
  DefineInput(0, TChain::Class());
  // Output slot #0 writes into a TList container
  DefineOutput(0, TList::Class());
}

//________________________________________________________________________
void AliAnalysisTaskProtons::ConnectInputData(Option_t *) {
  // Connect ESD or AOD here
  // Called once

  TTree* tree = dynamic_cast<TTree*> (GetInputData(0));
  if (!tree) {
    Printf("ERROR: Could not read chain from input slot 0");
  } else {
    // Disable all branches and enable only the needed ones
    // The next two lines are different when data produced as AliESDEvent is read
    if(fAnalysisType == "ESD") {
// In train mode branches can be disabled at the level of ESD handler (M.G.)
//      tree->SetBranchStatus("*", kFALSE);
      tree->SetBranchStatus("*Tracks.*", kTRUE);

      AliESDInputHandler *esdH = dynamic_cast<AliESDInputHandler*> (AliAnalysisManager::GetAnalysisManager()->GetInputEventHandler());

      if (!esdH) {
	Printf("ERROR: Could not get ESDInputHandler");
      } else
	fESD = esdH->GetEvent();
    }
    else if(fAnalysisType == "AOD") {
      AliAODInputHandler *aodH = dynamic_cast<AliAODInputHandler*> (AliAnalysisManager::GetAnalysisManager()->GetInputEventHandler());

      if (!aodH) {
	Printf("ERROR: Could not get AODInputHandler");
      } else
	fAOD = aodH->GetEvent();
    }
    else
      Printf("Wrong analysis type: Only ESD and AOD types are allowed!");
  }
}

//________________________________________________________________________
void AliAnalysisTaskProtons::CreateOutputObjects() {
  // Create histograms
  // Called once
  Double_t partFrac[5] = {0.01, 0.01, 0.85, 0.10, 0.05};

  fAnalysis = new AliProtonAnalysis();
  fAnalysis->InitHistograms(10,-1.0,1.0,30,0.1,3.1);
  if(fAnalysisType == "ESD") {
    fAnalysis->SetMinTPCClusters(50);
    fAnalysis->SetMinITSClusters(1);
    fAnalysis->SetMaxChi2PerTPCCluster(3.5);
    fAnalysis->SetMaxCov11(2.0);
    fAnalysis->SetMaxCov22(2.0);
    fAnalysis->SetMaxCov33(0.5);
    fAnalysis->SetMaxCov44(0.5);
    fAnalysis->SetMaxCov55(2.0);
    fAnalysis->SetMaxSigmaToVertex(3.);
    fAnalysis->SetITSRefit();
    fAnalysis->SetTPCRefit();
  }
  if(fFunctionUsed)
    fAnalysis->SetPriorProbabilityFunctions(fElectronFunction,
					    fMuonFunction,
					    fPionFunction,
					    fKaonFunction,
					    fProtonFunction);
  else
    fAnalysis->SetPriorProbabilities(partFrac);

  fList = new TList();
  fList->Add(fAnalysis->GetProtonYPtHistogram());
  fList->Add(fAnalysis->GetAntiProtonYPtHistogram());
}

//________________________________________________________________________
void AliAnalysisTaskProtons::Exec(Option_t *) {
  // Main loop
  // Called for each event

  if(fAnalysisType == "ESD") {
    if (!fESD) {
      Printf("ERROR: fESD not available");
      return;
    }

    Printf("Proton analysis task: There are %d tracks in this event", fESD->GetNumberOfTracks());
    fAnalysis->Analyze(fESD);
  }
  else if(fAnalysisType == "AOD") {
    if (!fAOD) {
      Printf("ERROR: fAOD not available");
      return;
    }

    Printf("Proton analysis task: There are %d tracks in this event", fAOD->GetNumberOfTracks());
    fAnalysis->Analyze(fAOD);
  }

  // Post output data.
  PostData(0, fList);
}

//________________________________________________________________________
void AliAnalysisTaskProtons::Terminate(Option_t *) {
  // Draw result to the screen
  // Called once at the end of the query

  fList = dynamic_cast<TList*> (GetOutputData(0));
  if (!fList) {
    Printf("ERROR: fList not available");
    return;
  }

  TH2F *fHistYPtProtons = (TH2F *)fList->At(0);
  TH2F *fHistYPtAntiProtons = (TH2F *)fList->At(1);

  TCanvas *c2 = new TCanvas("c2","p-\bar{p}",200,0,800,400);
  c2->SetFillColor(10); c2->SetHighLightColor(10); c2->Divide(2,1);

  c2->cd(1)->SetLeftMargin(0.15); c2->cd(1)->SetBottomMargin(0.15);
  if (fHistYPtProtons) fHistYPtProtons->DrawCopy("colz");
  c2->cd(2)->SetLeftMargin(0.15); c2->cd(2)->SetBottomMargin(0.15);
  if (fHistYPtAntiProtons) fHistYPtAntiProtons->DrawCopy("colz");
}

<commit_msg>Small modifications in the dummy constructor<commit_after>#include "TChain.h"
#include "TTree.h"
#include "TList.h"
#include "TH2F.h"
#include "TF1.h"
#include "TCanvas.h"
#include "TLorentzVector.h"

#include "AliAnalysisTask.h"
#include "AliAnalysisManager.h"

#include "AliESDEvent.h"
#include "AliESDInputHandler.h"
#include "AliAODEvent.h"
#include "AliAODInputHandler.h"

#include "AliProtonAnalysis.h"
#include "AliAnalysisTaskProtons.h"

// Analysis task creating a the 2d y-p_t spectrum of p and antip
// Author: Panos Cristakoglou

ClassImp(AliAnalysisTaskProtons)

//________________________________________________________________________
AliAnalysisTaskProtons::AliAnalysisTaskProtons()
: AliAnalysisTask(), fESD(0), fAOD(0), fAnalysisType("ESD"),
  fList(0), fAnalysis(0),
  fElectronFunction(0), fMuonFunction(0),
  fPionFunction(0), fKaonFunction(0), fProtonFunction(0),
  fFunctionUsed(kFALSE) {
  //Dummy constructor
}

//________________________________________________________________________
AliAnalysisTaskProtons::AliAnalysisTaskProtons(const char *name)
: AliAnalysisTask(name, ""), fESD(0), fAOD(0), fAnalysisType("ESD"),
  fList(0), fAnalysis(0),
  fElectronFunction(0), fMuonFunction(0),
  fPionFunction(0), fKaonFunction(0), fProtonFunction(0),
  fFunctionUsed(kFALSE) {
  // Constructor

  // Define input and output slots here
  // Input slot #0 works with a TChain
  DefineInput(0, TChain::Class());
  // Output slot #0 writes into a TList container
  DefineOutput(0, TList::Class());
}

//________________________________________________________________________
void AliAnalysisTaskProtons::ConnectInputData(Option_t *) {
  // Connect ESD or AOD here
  // Called once

  TTree* tree = dynamic_cast<TTree*> (GetInputData(0));
  if (!tree) {
    Printf("ERROR: Could not read chain from input slot 0");
  } else {
    // Disable all branches and enable only the needed ones
    // The next two lines are different when data produced as AliESDEvent is read
    if(fAnalysisType == "ESD") {
// In train mode branches can be disabled at the level of ESD handler (M.G.)
//      tree->SetBranchStatus("*", kFALSE);
      tree->SetBranchStatus("*Tracks.*", kTRUE);

      AliESDInputHandler *esdH = dynamic_cast<AliESDInputHandler*> (AliAnalysisManager::GetAnalysisManager()->GetInputEventHandler());

      if (!esdH) {
	Printf("ERROR: Could not get ESDInputHandler");
      } else
	fESD = esdH->GetEvent();
    }
    else if(fAnalysisType == "AOD") {
      AliAODInputHandler *aodH = dynamic_cast<AliAODInputHandler*> (AliAnalysisManager::GetAnalysisManager()->GetInputEventHandler());

      if (!aodH) {
	Printf("ERROR: Could not get AODInputHandler");
      } else
	fAOD = aodH->GetEvent();
    }
    else
      Printf("Wrong analysis type: Only ESD and AOD types are allowed!");
  }
}

//________________________________________________________________________
void AliAnalysisTaskProtons::CreateOutputObjects() {
  // Create histograms
  // Called once
  Double_t partFrac[5] = {0.01, 0.01, 0.85, 0.10, 0.05};

  fAnalysis = new AliProtonAnalysis();
  fAnalysis->InitHistograms(10,-1.0,1.0,30,0.1,3.1);
  if(fAnalysisType == "ESD") {
    fAnalysis->SetMinTPCClusters(50);
    fAnalysis->SetMinITSClusters(1);
    fAnalysis->SetMaxChi2PerTPCCluster(3.5);
    fAnalysis->SetMaxCov11(2.0);
    fAnalysis->SetMaxCov22(2.0);
    fAnalysis->SetMaxCov33(0.5);
    fAnalysis->SetMaxCov44(0.5);
    fAnalysis->SetMaxCov55(2.0);
    fAnalysis->SetMaxSigmaToVertex(3.);
    fAnalysis->SetITSRefit();
    fAnalysis->SetTPCRefit();
  }
  if(fFunctionUsed)
    fAnalysis->SetPriorProbabilityFunctions(fElectronFunction,
					    fMuonFunction,
					    fPionFunction,
					    fKaonFunction,
					    fProtonFunction);
  else
    fAnalysis->SetPriorProbabilities(partFrac);

  fList = new TList();
  fList->Add(fAnalysis->GetProtonYPtHistogram());
  fList->Add(fAnalysis->GetAntiProtonYPtHistogram());
}

//________________________________________________________________________
void AliAnalysisTaskProtons::Exec(Option_t *) {
  // Main loop
  // Called for each event

  if(fAnalysisType == "ESD") {
    if (!fESD) {
      Printf("ERROR: fESD not available");
      return;
    }

    Printf("Proton analysis task: There are %d tracks in this event", fESD->GetNumberOfTracks());
    fAnalysis->Analyze(fESD);
  }
  else if(fAnalysisType == "AOD") {
    if (!fAOD) {
      Printf("ERROR: fAOD not available");
      return;
    }

    Printf("Proton analysis task: There are %d tracks in this event", fAOD->GetNumberOfTracks());
    fAnalysis->Analyze(fAOD);
  }

  // Post output data.
  PostData(0, fList);
}

//________________________________________________________________________
void AliAnalysisTaskProtons::Terminate(Option_t *) {
  // Draw result to the screen
  // Called once at the end of the query

  fList = dynamic_cast<TList*> (GetOutputData(0));
  if (!fList) {
    Printf("ERROR: fList not available");
    return;
  }

  TH2F *fHistYPtProtons = (TH2F *)fList->At(0);
  TH2F *fHistYPtAntiProtons = (TH2F *)fList->At(1);

  TCanvas *c2 = new TCanvas("c2","p-\bar{p}",200,0,800,400);
  c2->SetFillColor(10); c2->SetHighLightColor(10); c2->Divide(2,1);

  c2->cd(1)->SetLeftMargin(0.15); c2->cd(1)->SetBottomMargin(0.15);
  if (fHistYPtProtons) fHistYPtProtons->DrawCopy("colz");
  c2->cd(2)->SetLeftMargin(0.15); c2->cd(2)->SetBottomMargin(0.15);
  if (fHistYPtAntiProtons) fHistYPtAntiProtons->DrawCopy("colz");
}

<|endoftext|>


<commit_before>AliAnalysisTaskJetCluster *AddTaskJetCluster(char* bRec = "AOD",char* bGen = "",UInt_t filterMask = 16, Int_t iPhysicsSelection = 1,Char_t *jf = "KT", Float_t radius = 0.4);

AliAnalysisTaskJetCluster *AddTaskJetClusterDelta(UInt_t filterMask = 16,Bool_t kUseAODMC = kFALSE,Int_t iPhysicsSelection = 1,Char_t *jf = "KT", UInt_t iFlag){
  AliAnalysisTaskJetCluster *js = 0;
  if(kUseAODMC&&false){// do not use the MC info yet
    if(iFlag&(1<<0))js = AddTaskJetCluster("AOD","AODMC",filterMask,iPhysicsSelection,jf,0.00001);
    if(iFlag&(2<<0))js = AddTaskJetCluster("AOD","AODMC",filterMask,iPhysicsSelection,jf,0.1);
    if(iFlag&(3<<0))js = AddTaskJetCluster("AOD","AODMC",filterMask,iPhysicsSelection,jf,0.2);
    if(iFlag&(4<<0))js = AddTaskJetCluster("AOD","AODMC",filterMask,iPhysicsSelection,jf,0.4);
    if(iFlag&(5<<0))js = AddTaskJetCluster("AOD","AODMC",filterMask,iPhysicsSelection,jf,0.6);
    if(iFlag&(6<<0))js = AddTaskJetCluster("AOD","AODMC",filterMask,iPhysicsSelection,jf,0.8);
    if(iFlag&(7<<0))js = AddTaskJetCluster("AOD","AODMC",filterMask,iPhysicsSelection,jf,1.0);
  }
  else{
    if(iFlag&(1<<0))js = AddTaskJetCluster("AOD","",filterMask,iPhysicsSelection,jf,0.00001);
    if(iFlag&(2<<0))js = AddTaskJetCluster("AOD","",filterMask,iPhysicsSelection,jf,0.1);
    if(iFlag&(3<<0))js = AddTaskJetCluster("AOD","",filterMask,iPhysicsSelection,jf,0.2);
    //    if(iFlag&(4<<0))js = AddTaskJetCluster("AOD","",filterMask,iPhysicsSelection,jf,0.4);
    if(iFlag&(5<<0))js = AddTaskJetCluster("AOD","",filterMask,iPhysicsSelection,jf,0.6);
    if(iFlag&(6<<0))js = AddTaskJetCluster("AOD","",filterMask,iPhysicsSelection,jf,0.8);
    if(iFlag&(7<<0))js = AddTaskJetCluster("AOD","",filterMask,iPhysicsSelection,jf,1.0);
  }

  return js;
}

AliAnalysisTaskJetCluster *AddTaskJetCluster(char* bRec,char* bGen ,UInt_t filterMask,Int_t iPhysicsSelection,Char_t *jf,Float_t radius)
{
// Creates a jet fider task, configures it and adds it to the analysis manager.

   // Get the pointer to the existing analysis manager via the static access method.
   //==============================================================================
   AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
   if (!mgr) {
      ::Error("AddTaskJetCluster", "No analysis manager to connect to.");
      return NULL;
   }

   // Check the analysis type using the event handlers connected to the analysis manager.
   //==============================================================================
   if (!mgr->GetInputEventHandler()) {
     ::Error("AddTaskJetCluster", "This task requires an input event handler");
      return NULL;
   }

   TString type = mgr->GetInputEventHandler()->GetDataType();
   TString typeRec(bRec);
   TString typeGen(bGen);
   typeGen.ToUpper();
   typeRec.ToUpper();
   // Create the task and configure it.
   //===========================================================================

   char *cRadius = "";
   if(radius>0)cRadius = Form("%02d",(int)((radius+0.01)*10.));

   AliAnalysisTaskJetCluster* pwg4spec = new  AliAnalysisTaskJetCluster(Form("JetCluster_%s_%s",jf,cRadius));

   // or a config file
   // pwg4spec->SetAnalysisType(AliAnalysisTaskJetCluster::kAnaMC);
   // if(iAODanalysis)pwg4spec->SetAODInput(kTRUE);
   // pwg4spec->SetDebugLevel(11);
   pwg4spec->SetFilterMask(filterMask);
   //   pwg4spec->SetUseGlobalSelection(kTRUE);

   if(type == "AOD"){
     // Assume all jet are produced already
     pwg4spec->SetAODTrackInput(kTRUE);
     pwg4spec->SetAODMCInput(kTRUE);
   }

   if(typeRec.Contains("AODMC2b")){// work down from the top AODMC2b -> AODMC2 -> AODMC -> AOD
     pwg4spec->SetTrackTypeRec(AliAnalysisTaskJetCluster::kTrackAODMCChargedAcceptance);
   }
   else if (typeRec.Contains("AODMC2")){
     pwg4spec->SetTrackTypeRec(AliAnalysisTaskJetCluster::kTrackAODMCCharged);
   }
   else if (typeRec.Contains("AODMC")){
     pwg4spec->SetTrackTypeRec(AliAnalysisTaskJetCluster::kTrackAODMCAll);
   }
   else if (typeRec.Contains("AOD")) {
     pwg4spec->SetTrackTypeRec(AliAnalysisTaskJetCluster::kTrackAOD);
   }

   if(typeGen.Contains("AODMC2b")){// work down from the top AODMC2b -> AODMC2 -> AODMC -> AOD
     pwg4spec->SetTrackTypeGen(AliAnalysisTaskJetCluster::kTrackAODMCChargedAcceptance);
   }
   else if (typeGen.Contains("AODMC2")){
     pwg4spec->SetTrackTypeGen(AliAnalysisTaskJetCluster::kTrackAODMCCharged);
   }
   else if (typeGen.Contains("AODMC")){
     pwg4spec->SetTrackTypeGen(AliAnalysisTaskJetCluster::kTrackAODMCAll);
   }
   else if (typeGen.Contains("AOD")) {
     pwg4spec->SetTrackTypeGen(AliAnalysisTaskJetCluster::kTrackAOD);
   }

   pwg4spec->SetRparam(radius);

   switch (jf) {
   case "ANTIKT":
     pwg4spec->SetAlgorithm(2); // antikt from fastjet/JetDefinition.hh
     break;
   case "CA":
     pwg4spec->SetAlgorithm(1); // CA from fastjet/JetDefinition.hh
     break;
   case "KT":
     pwg4spec->SetAlgorithm(0); // kt from fastjet/JetDefinition.hh
     break;
   default:
     ::Error("AddTaskJetCluster", "Wrong jet finder selected\n");
     return 0;
   }

   if(iPhysicsSelection)pwg4spec->SelectCollisionCandidates();

   mgr->AddTask(pwg4spec);

   // Create ONLY the output containers for the data produced by the task.
   // Get and connect other common input/output containers via the manager as below
   //==============================================================================
   AliAnalysisDataContainer *coutput1_Spec = mgr->CreateContainer(Form("pwg4cluster_%s_%s_%s_%s",bRec,bGen,jf,cRadius), TList::Class(),AliAnalysisManager::kOutputContainer,Form("%s:PWG4_cluster_%s_%s_%s_%s",AliAnalysisManager::GetCommonFileName(),bRec,bGen,jf,cRadius));

   mgr->ConnectInput  (pwg4spec, 0, mgr->GetCommonInputContainer());
   mgr->ConnectOutput (pwg4spec, 0, mgr->GetCommonOutputContainer());
   mgr->ConnectOutput (pwg4spec,  1, coutput1_Spec );

   return pwg4spec;
}
<commit_msg>fixed typos in task configuration, reduced number of tasks<commit_after>AliAnalysisTaskJetCluster *AddTaskJetCluster(char* bRec = "AOD",char* bGen = "",UInt_t filterMask = 16, Int_t iPhysicsSelection = 1,Char_t *jf = "KT", Float_t radius = 0.4);

AliAnalysisTaskJetCluster *AddTaskJetClusterDelta(UInt_t filterMask = 16,Bool_t kUseAODMC = kFALSE,Int_t iPhysicsSelection = 1,Char_t *jf = "KT", UInt_t iFlag){
  AliAnalysisTaskJetCluster *js = 0;
  if(kUseAODMC&&false){// do not use the MC info yet
    if(iFlag&(1<<0))js = AddTaskJetCluster("AOD","AODMC",filterMask,iPhysicsSelection,jf,0.00001);
    if(iFlag&(1<<1))js = AddTaskJetCluster("AOD","AODMC",filterMask,iPhysicsSelection,jf,0.1);
    if(iFlag&(1<<2))js = AddTaskJetCluster("AOD","AODMC",filterMask,iPhysicsSelection,jf,0.2);
    if(iFlag&(1<<4))js = AddTaskJetCluster("AOD","AODMC",filterMask,iPhysicsSelection,jf,0.4);
    if(iFlag&(1<<6))js = AddTaskJetCluster("AOD","AODMC",filterMask,iPhysicsSelection,jf,0.6);
    if(iFlag&(1<<8))js = AddTaskJetCluster("AOD","AODMC",filterMask,iPhysicsSelection,jf,0.8);
    if(iFlag&(1<<10))js = AddTaskJetCluster("AOD","AODMC",filterMask,iPhysicsSelection,jf,1.0);
  }
  else{
    if(iFlag&(1<<0))js = AddTaskJetCluster("AOD","",filterMask,iPhysicsSelection,jf,0.00001);
    if(iFlag&(1<<1))js = AddTaskJetCluster("AOD","",filterMask,iPhysicsSelection,jf,0.1);
    if(iFlag&(1<<2))js = AddTaskJetCluster("AOD","",filterMask,iPhysicsSelection,jf,0.2);
    if(iFlag&(1<<4))js = AddTaskJetCluster("AOD","",filterMask,iPhysicsSelection,jf,0.4);
    if(iFlag&(1<<6))js = AddTaskJetCluster("AOD","",filterMask,iPhysicsSelection,jf,0.6);
    if(iFlag&(1<<8))js = AddTaskJetCluster("AOD","",filterMask,iPhysicsSelection,jf,0.8);
    if(iFlag&(1<<10))js = AddTaskJetCluster("AOD","",filterMask,iPhysicsSelection,jf,1.0);
  }

  return js;
}

AliAnalysisTaskJetCluster *AddTaskJetCluster(char* bRec,char* bGen ,UInt_t filterMask,Int_t iPhysicsSelection,Char_t *jf,Float_t radius)
{
// Creates a jet fider task, configures it and adds it to the analysis manager.

   // Get the pointer to the existing analysis manager via the static access method.
   //==============================================================================
   AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
   if (!mgr) {
      ::Error("AddTaskJetCluster", "No analysis manager to connect to.");
      return NULL;
   }

   // Check the analysis type using the event handlers connected to the analysis manager.
   //==============================================================================
   if (!mgr->GetInputEventHandler()) {
     ::Error("AddTaskJetCluster", "This task requires an input event handler");
      return NULL;
   }

   TString type = mgr->GetInputEventHandler()->GetDataType();
   TString typeRec(bRec);
   TString typeGen(bGen);
   typeGen.ToUpper();
   typeRec.ToUpper();
   // Create the task and configure it.
   //===========================================================================

   char *cRadius = "";
   if(radius>0)cRadius = Form("%02d",(int)((radius+0.01)*10.));

   AliAnalysisTaskJetCluster* pwg4spec = new  AliAnalysisTaskJetCluster(Form("JetCluster_%s_%s",jf,cRadius));

   // or a config file
   // pwg4spec->SetAnalysisType(AliAnalysisTaskJetCluster::kAnaMC);
   // if(iAODanalysis)pwg4spec->SetAODInput(kTRUE);
   // pwg4spec->SetDebugLevel(11);
   pwg4spec->SetFilterMask(filterMask);
   //   pwg4spec->SetUseGlobalSelection(kTRUE);

   if(type == "AOD"){
     // Assume all jet are produced already
     pwg4spec->SetAODTrackInput(kTRUE);
     pwg4spec->SetAODMCInput(kTRUE);
   }

   if(typeRec.Contains("AODMC2b")){// work down from the top AODMC2b -> AODMC2 -> AODMC -> AOD
     pwg4spec->SetTrackTypeRec(AliAnalysisTaskJetCluster::kTrackAODMCChargedAcceptance);
   }
   else if (typeRec.Contains("AODMC2")){
     pwg4spec->SetTrackTypeRec(AliAnalysisTaskJetCluster::kTrackAODMCCharged);
   }
   else if (typeRec.Contains("AODMC")){
     pwg4spec->SetTrackTypeRec(AliAnalysisTaskJetCluster::kTrackAODMCAll);
   }
   else if (typeRec.Contains("AOD")) {
     pwg4spec->SetTrackTypeRec(AliAnalysisTaskJetCluster::kTrackAOD);
   }

   if(typeGen.Contains("AODMC2b")){// work down from the top AODMC2b -> AODMC2 -> AODMC -> AOD
     pwg4spec->SetTrackTypeGen(AliAnalysisTaskJetCluster::kTrackAODMCChargedAcceptance);
   }
   else if (typeGen.Contains("AODMC2")){
     pwg4spec->SetTrackTypeGen(AliAnalysisTaskJetCluster::kTrackAODMCCharged);
   }
   else if (typeGen.Contains("AODMC")){
     pwg4spec->SetTrackTypeGen(AliAnalysisTaskJetCluster::kTrackAODMCAll);
   }
   else if (typeGen.Contains("AOD")) {
     pwg4spec->SetTrackTypeGen(AliAnalysisTaskJetCluster::kTrackAOD);
   }

   pwg4spec->SetRparam(radius);

   switch (jf) {
   case "ANTIKT":
     pwg4spec->SetAlgorithm(2); // antikt from fastjet/JetDefinition.hh
     break;
   case "CA":
     pwg4spec->SetAlgorithm(1); // CA from fastjet/JetDefinition.hh
     break;
   case "KT":
     pwg4spec->SetAlgorithm(0); // kt from fastjet/JetDefinition.hh
     break;
   default:
     ::Error("AddTaskJetCluster", "Wrong jet finder selected\n");
     return 0;
   }

   if(iPhysicsSelection)pwg4spec->SelectCollisionCandidates();

   mgr->AddTask(pwg4spec);

   // Create ONLY the output containers for the data produced by the task.
   // Get and connect other common input/output containers via the manager as below
   //==============================================================================
   AliAnalysisDataContainer *coutput1_Spec = mgr->CreateContainer(Form("pwg4cluster_%s_%s_%s_%s",bRec,bGen,jf,cRadius), TList::Class(),AliAnalysisManager::kOutputContainer,Form("%s:PWG4_cluster_%s_%s_%s_%s",AliAnalysisManager::GetCommonFileName(),bRec,bGen,jf,cRadius));

   mgr->ConnectInput  (pwg4spec, 0, mgr->GetCommonInputContainer());
   mgr->ConnectOutput (pwg4spec, 0, mgr->GetCommonOutputContainer());
   mgr->ConnectOutput (pwg4spec,  1, coutput1_Spec );

   return pwg4spec;
}
<|endoftext|>


<commit_before><commit_msg>Converting an ERROR message into a slightly more descriptive WARNING with a default option<commit_after><|endoftext|>


<commit_before>/*
 * Copyright (C) 2018 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "PlatformWGL.h"

#include <Wingdi.h>

#include "OpenGLDriverFactory.h"

#ifdef _MSC_VER
    // this variable is checked in BlueGL.h (included from "gl_headers.h" right after this),
    // and prevents duplicate definition of OpenGL apis when building this file.
    // However, GL_GLEXT_PROTOTYPES need to be defined in BlueGL.h when included from other files.
    #define FILAMENT_PLATFORM_WGL
#endif

#include "gl_headers.h"

#include "Windows.h"
#include <GL/gl.h>
#include "GL/glext.h"
#include "GL/wglext.h"

#include <utils/Log.h>
#include <utils/Panic.h>

namespace {

void reportLastWindowsError() {
    LPSTR lpMessageBuffer = nullptr;
    DWORD dwError = GetLastError();

    if (dwError == 0) {
        return;
    }

    FormatMessage(
        FORMAT_MESSAGE_ALLOCATE_BUFFER |
        FORMAT_MESSAGE_FROM_SYSTEM |
        FORMAT_MESSAGE_IGNORE_INSERTS,
        nullptr,
        dwError,
        MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
        lpMessageBuffer,
        0, nullptr
	);

    utils::slog.e << "Windows error code: " << dwError << ". " << lpMessageBuffer
            << utils::io::endl;

    LocalFree(lpMessageBuffer);
}

} // namespace

namespace filament {

using namespace backend;

Driver* PlatformWGL::createDriver(void* const sharedGLContext) noexcept {
    mPfd = {
        sizeof(PIXELFORMATDESCRIPTOR),
        1,
        PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER,    // Flags
        PFD_TYPE_RGBA,        // The kind of framebuffer. RGBA or palette.
        32,                   // Colordepth of the framebuffer.
        0, 0, 0, 0, 0, 0,
        0,
        0,
        0,
        0, 0, 0, 0,
        24,                   // Number of bits for the depthbuffer
        0,                    // Number of bits for the stencilbuffer
        0,                    // Number of Aux buffers in the framebuffer.
        PFD_MAIN_PLANE,
        0,
        0, 0, 0
    };

    int attribs[] = {
        WGL_CONTEXT_MAJOR_VERSION_ARB, 4,
        WGL_CONTEXT_MINOR_VERSION_ARB, 1,
        WGL_CONTEXT_FLAGS_ARB, WGL_CONTEXT_PROFILE_MASK_ARB,
        0
    };

    HGLRC tempContext = NULL;

    mHWnd = CreateWindowA("STATIC", "dummy", 0, 0, 0, 1, 1, NULL, NULL, NULL, NULL);
    HDC whdc = mWhdc = GetDC(mHWnd);
    if (whdc == NULL) {
        utils::slog.e << "CreateWindowA() failed" << utils::io::endl;
        goto error;
    }

    int pixelFormat = ChoosePixelFormat(whdc, &mPfd);
    SetPixelFormat(whdc, pixelFormat, &mPfd);

    // We need a tmp context to retrieve and call wglCreateContextAttribsARB.
    tempContext = wglCreateContext(whdc);
    if (!wglMakeCurrent(whdc, tempContext)) {
        utils::slog.e << "wglMakeCurrent() failed, whdc=" << whdc << ", tempContext=" <<
                tempContext << utils::io::endl;
        goto error;
    }

    PFNWGLCREATECONTEXTATTRIBSARBPROC wglCreateContextAttribs =
            (PFNWGLCREATECONTEXTATTRIBSARBPROC) wglGetProcAddress("wglCreateContextAttribsARB");
    mContext = wglCreateContextAttribs(whdc, nullptr, attribs);
    if (!mContext) {
        utils::slog.e << "wglCreateContextAttribs() failed, whdc=" << whdc << utils::io::endl;
        goto error;
    }

    wglMakeCurrent(NULL, NULL);
    wglDeleteContext(tempContext);
    tempContext = NULL;

    if (!wglMakeCurrent(whdc, mContext)) {
        utils::slog.e << "wglMakeCurrent() failed, whdc=" << whdc << ", mContext=" <<
                mContext << utils::io::endl;
        goto error;
    }

    int result = bluegl::bind();
    ASSERT_POSTCONDITION(!result, "Unable to load OpenGL entry points.");
    return OpenGLDriverFactory::create(this, sharedGLContext);

error:
    if (tempContext) {
        wglDeleteContext(tempContext);
    }
    reportLastWindowsError();
    terminate();
    return NULL;
}

void PlatformWGL::terminate() noexcept {
    wglMakeCurrent(NULL, NULL);
    if (mContext) {
        wglDeleteContext(mContext);
        mContext = NULL;
    }
    if (mHWnd && mWhdc) {
        ReleaseDC(mHWnd, mWhdc);
        DestroyWindow(mHWnd);
        mHWnd = NULL;
        mWhdc = NULL;
    } else if (mHWnd) {
        DestroyWindow(mHWnd);
        mHWnd = NULL;
    }
    bluegl::unbind();
}

Platform::SwapChain* PlatformWGL::createSwapChain(void* nativeWindow, uint64_t& flags) noexcept {
    // on Windows, the nativeWindow maps to a HWND
    HDC hdc = GetDC((HWND) nativeWindow);
    if (!ASSERT_POSTCONDITION_NON_FATAL(hdc,
            "Unable to create the SwapChain (nativeWindow = %p)", nativeWindow)) {
        reportLastWindowsError();
    }

	// We have to match pixel formats across the HDC and HGLRC (mContext)
    int pixelFormat = ChoosePixelFormat(hdc, &mPfd);
    SetPixelFormat(hdc, pixelFormat, &mPfd);

    SwapChain* swapChain = (SwapChain*) hdc;
    return swapChain;
}

Platform::SwapChain* PlatformWGL::createSwapChain(uint32_t width, uint32_t height, uint64_t& flags) noexcept {
    // TODO: implement headless SwapChain
    return nullptr;
}

void PlatformWGL::destroySwapChain(Platform::SwapChain* swapChain) noexcept {
    HDC dc = (HDC) swapChain;
    HWND window = WindowFromDC(dc);
    ReleaseDC(window, dc);
    // make this swapChain not current (by making a dummy one current)
    wglMakeCurrent(mWhdc, mContext);
}

void PlatformWGL::makeCurrent(Platform::SwapChain* drawSwapChain,
                              Platform::SwapChain* readSwapChain) noexcept {
    ASSERT_PRECONDITION_NON_FATAL(drawSwapChain == readSwapChain,
                                  "PlatformWGL does not support distinct draw/read swap chains.");
    HDC hdc = (HDC)(drawSwapChain);
    if (hdc != NULL) {
        BOOL success = wglMakeCurrent(hdc, mContext);
        if (!ASSERT_POSTCONDITION_NON_FATAL(success, "wglMakeCurrent() failed. hdc = %p", hdc)) {
            reportLastWindowsError();
            wglMakeCurrent(0, NULL);
        }
    }
}

void PlatformWGL::commit(Platform::SwapChain* swapChain) noexcept {
    HDC hdc = (HDC)(swapChain);
    if (hdc != NULL) {
        SwapBuffers(hdc);
    }
}

//TODO Implement WGL fences
Platform::Fence* PlatformWGL::createFence() noexcept {
    return nullptr;
}

void PlatformWGL::destroyFence(Fence* fence) noexcept {
}

backend::FenceStatus PlatformWGL::waitFence(Fence* fence, uint64_t timeout) noexcept {
    return backend::FenceStatus::ERROR;
}

} // namespace filament
<commit_msg>Pass shared context on Windows to wglCreateContextAttribs (#1913)<commit_after>/*
 * Copyright (C) 2018 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "PlatformWGL.h"

#include <Wingdi.h>

#include "OpenGLDriverFactory.h"

#ifdef _MSC_VER
    // this variable is checked in BlueGL.h (included from "gl_headers.h" right after this),
    // and prevents duplicate definition of OpenGL apis when building this file.
    // However, GL_GLEXT_PROTOTYPES need to be defined in BlueGL.h when included from other files.
    #define FILAMENT_PLATFORM_WGL
#endif

#include "gl_headers.h"

#include "Windows.h"
#include <GL/gl.h>
#include "GL/glext.h"
#include "GL/wglext.h"

#include <utils/Log.h>
#include <utils/Panic.h>

namespace {

void reportLastWindowsError() {
    LPSTR lpMessageBuffer = nullptr;
    DWORD dwError = GetLastError();

    if (dwError == 0) {
        return;
    }

    FormatMessage(
        FORMAT_MESSAGE_ALLOCATE_BUFFER |
        FORMAT_MESSAGE_FROM_SYSTEM |
        FORMAT_MESSAGE_IGNORE_INSERTS,
        nullptr,
        dwError,
        MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
        lpMessageBuffer,
        0, nullptr
	);

    utils::slog.e << "Windows error code: " << dwError << ". " << lpMessageBuffer
            << utils::io::endl;

    LocalFree(lpMessageBuffer);
}

} // namespace

namespace filament {

using namespace backend;

Driver* PlatformWGL::createDriver(void* const sharedGLContext) noexcept {
    mPfd = {
        sizeof(PIXELFORMATDESCRIPTOR),
        1,
        PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER,    // Flags
        PFD_TYPE_RGBA,        // The kind of framebuffer. RGBA or palette.
        32,                   // Colordepth of the framebuffer.
        0, 0, 0, 0, 0, 0,
        0,
        0,
        0,
        0, 0, 0, 0,
        24,                   // Number of bits for the depthbuffer
        0,                    // Number of bits for the stencilbuffer
        0,                    // Number of Aux buffers in the framebuffer.
        PFD_MAIN_PLANE,
        0,
        0, 0, 0
    };

    int attribs[] = {
        WGL_CONTEXT_MAJOR_VERSION_ARB, 4,
        WGL_CONTEXT_MINOR_VERSION_ARB, 1,
        WGL_CONTEXT_FLAGS_ARB, WGL_CONTEXT_PROFILE_MASK_ARB,
        0
    };

    HGLRC tempContext = NULL;

    mHWnd = CreateWindowA("STATIC", "dummy", 0, 0, 0, 1, 1, NULL, NULL, NULL, NULL);
    HDC whdc = mWhdc = GetDC(mHWnd);
    if (whdc == NULL) {
        utils::slog.e << "CreateWindowA() failed" << utils::io::endl;
        goto error;
    }

    int pixelFormat = ChoosePixelFormat(whdc, &mPfd);
    SetPixelFormat(whdc, pixelFormat, &mPfd);

    // We need a tmp context to retrieve and call wglCreateContextAttribsARB.
    tempContext = wglCreateContext(whdc);
    if (!wglMakeCurrent(whdc, tempContext)) {
        utils::slog.e << "wglMakeCurrent() failed, whdc=" << whdc << ", tempContext=" <<
                tempContext << utils::io::endl;
        goto error;
    }

    PFNWGLCREATECONTEXTATTRIBSARBPROC wglCreateContextAttribs =
            (PFNWGLCREATECONTEXTATTRIBSARBPROC) wglGetProcAddress("wglCreateContextAttribsARB");
    mContext = wglCreateContextAttribs(whdc, (HGLRC) sharedGLContext, attribs);
    if (!mContext) {
        utils::slog.e << "wglCreateContextAttribs() failed, whdc=" << whdc << utils::io::endl;
        goto error;
    }

    wglMakeCurrent(NULL, NULL);
    wglDeleteContext(tempContext);
    tempContext = NULL;

    if (!wglMakeCurrent(whdc, mContext)) {
        utils::slog.e << "wglMakeCurrent() failed, whdc=" << whdc << ", mContext=" <<
                mContext << utils::io::endl;
        goto error;
    }

    int result = bluegl::bind();
    ASSERT_POSTCONDITION(!result, "Unable to load OpenGL entry points.");
    return OpenGLDriverFactory::create(this, sharedGLContext);

error:
    if (tempContext) {
        wglDeleteContext(tempContext);
    }
    reportLastWindowsError();
    terminate();
    return NULL;
}

void PlatformWGL::terminate() noexcept {
    wglMakeCurrent(NULL, NULL);
    if (mContext) {
        wglDeleteContext(mContext);
        mContext = NULL;
    }
    if (mHWnd && mWhdc) {
        ReleaseDC(mHWnd, mWhdc);
        DestroyWindow(mHWnd);
        mHWnd = NULL;
        mWhdc = NULL;
    } else if (mHWnd) {
        DestroyWindow(mHWnd);
        mHWnd = NULL;
    }
    bluegl::unbind();
}

Platform::SwapChain* PlatformWGL::createSwapChain(void* nativeWindow, uint64_t& flags) noexcept {
    // on Windows, the nativeWindow maps to a HWND
    HDC hdc = GetDC((HWND) nativeWindow);
    if (!ASSERT_POSTCONDITION_NON_FATAL(hdc,
            "Unable to create the SwapChain (nativeWindow = %p)", nativeWindow)) {
        reportLastWindowsError();
    }

	// We have to match pixel formats across the HDC and HGLRC (mContext)
    int pixelFormat = ChoosePixelFormat(hdc, &mPfd);
    SetPixelFormat(hdc, pixelFormat, &mPfd);

    SwapChain* swapChain = (SwapChain*) hdc;
    return swapChain;
}

Platform::SwapChain* PlatformWGL::createSwapChain(uint32_t width, uint32_t height, uint64_t& flags) noexcept {
    // TODO: implement headless SwapChain
    return nullptr;
}

void PlatformWGL::destroySwapChain(Platform::SwapChain* swapChain) noexcept {
    HDC dc = (HDC) swapChain;
    HWND window = WindowFromDC(dc);
    ReleaseDC(window, dc);
    // make this swapChain not current (by making a dummy one current)
    wglMakeCurrent(mWhdc, mContext);
}

void PlatformWGL::makeCurrent(Platform::SwapChain* drawSwapChain,
                              Platform::SwapChain* readSwapChain) noexcept {
    ASSERT_PRECONDITION_NON_FATAL(drawSwapChain == readSwapChain,
                                  "PlatformWGL does not support distinct draw/read swap chains.");
    HDC hdc = (HDC)(drawSwapChain);
    if (hdc != NULL) {
        BOOL success = wglMakeCurrent(hdc, mContext);
        if (!ASSERT_POSTCONDITION_NON_FATAL(success, "wglMakeCurrent() failed. hdc = %p", hdc)) {
            reportLastWindowsError();
            wglMakeCurrent(0, NULL);
        }
    }
}

void PlatformWGL::commit(Platform::SwapChain* swapChain) noexcept {
    HDC hdc = (HDC)(swapChain);
    if (hdc != NULL) {
        SwapBuffers(hdc);
    }
}

//TODO Implement WGL fences
Platform::Fence* PlatformWGL::createFence() noexcept {
    return nullptr;
}

void PlatformWGL::destroyFence(Fence* fence) noexcept {
}

backend::FenceStatus PlatformWGL::waitFence(Fence* fence, uint64_t timeout) noexcept {
    return backend::FenceStatus::ERROR;
}

} // namespace filament
<|endoftext|>


<commit_before>#include "pch.h"
#include "DeviceManager.h"

#include "DspMatrix.h"

namespace SaneAudioRenderer
{
    namespace
    {
        const auto WindowClass = L"SaneAudioRenderer::DeviceManager";
        const auto WindowTitle = L"";

        enum
        {
            WM_CHECK_BITSTREAM_FORMAT = WM_USER + 100,
            WM_CREATE_DEVICE,
        };

        template <class T>
        bool IsLastInstance(T& smartPointer)
        {
            bool ret = (smartPointer.GetInterfacePtr()->AddRef() == 2);
            smartPointer.GetInterfacePtr()->Release();
            return ret;
        }

        WAVEFORMATEX BuildWaveFormat(WORD formatTag, uint32_t formatBits, uint32_t rate, uint32_t channelCount)
        {
            WAVEFORMATEX ret;

            ret.wFormatTag      = formatTag;
            ret.nChannels       = channelCount;
            ret.nSamplesPerSec  = rate;
            ret.nAvgBytesPerSec = formatBits / 8 * channelCount * rate;
            ret.nBlockAlign     = formatBits / 8 * channelCount;
            ret.wBitsPerSample  = formatBits;
            ret.cbSize          = (formatTag == WAVE_FORMAT_EXTENSIBLE) ? 22 : 0;

            return ret;
        }

        WAVEFORMATEXTENSIBLE BuildWaveFormatExt(GUID formatGuid, uint32_t formatBits, WORD formatExtProps,
                                                uint32_t rate, uint32_t channelCount, DWORD channelMask)
        {
            WAVEFORMATEXTENSIBLE ret;

            ret.Format                      = BuildWaveFormat(WAVE_FORMAT_EXTENSIBLE, formatBits, rate, channelCount);
            ret.Samples.wValidBitsPerSample = formatExtProps;
            ret.dwChannelMask               = channelMask;
            ret.SubFormat                   = formatGuid;

            return ret;
        }

        std::shared_ptr<std::wstring> GetDevicePropertyString(IPropertyStore* pStore, REFPROPERTYKEY key)
        {
            assert(pStore);

            PROPVARIANT prop;
            PropVariantInit(&prop);
            ThrowIfFailed(pStore->GetValue(key, &prop));
            auto ret = std::make_shared<std::wstring>(prop.pwszVal);
            PropVariantClear(&prop);

            return ret;
        }

        void CreateAudioClient(AudioDevice& audioDevice)
        {
            IMMDeviceEnumeratorPtr enumerator;
            ThrowIfFailed(CoCreateInstance(__uuidof(MMDeviceEnumerator), nullptr,
                                           CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&enumerator)));

            IMMDevicePtr device;
            IPropertyStorePtr devicePropertyStore;

            if (!audioDevice.friendlyName || audioDevice.friendlyName->empty())
            {
                audioDevice.default = true;
                ThrowIfFailed(enumerator->GetDefaultAudioEndpoint(eRender, eConsole, &device));
                ThrowIfFailed(device->OpenPropertyStore(STGM_READ, &devicePropertyStore));
                audioDevice.friendlyName = GetDevicePropertyString(devicePropertyStore, PKEY_Device_FriendlyName);
            }
            else
            {
                auto targetName = audioDevice.friendlyName;
                audioDevice.default = false;

                IMMDeviceCollectionPtr collection;
                ThrowIfFailed(enumerator->EnumAudioEndpoints(eRender, DEVICE_STATE_ACTIVE, &collection));

                UINT count = 0;
                ThrowIfFailed(collection->GetCount(&count));

                for (UINT i = 0; i < count; i++)
                {
                    ThrowIfFailed(collection->Item(i, &device));
                    ThrowIfFailed(device->OpenPropertyStore(STGM_READ, &devicePropertyStore));
                    audioDevice.friendlyName = GetDevicePropertyString(devicePropertyStore, PKEY_Device_FriendlyName);

                    if (*targetName != *audioDevice.friendlyName)
                    {
                        device = nullptr;
                        devicePropertyStore = nullptr;
                        audioDevice.friendlyName = nullptr;
                    }
                }
            }

            if (!device)
                return;

            audioDevice.adapterName = GetDevicePropertyString(devicePropertyStore, PKEY_DeviceInterface_FriendlyName);
            audioDevice.endpointName = GetDevicePropertyString(devicePropertyStore, PKEY_Device_DeviceDesc);

            ThrowIfFailed(device->Activate(__uuidof(IAudioClient),
                                           CLSCTX_INPROC_SERVER, nullptr, (void**)&audioDevice.audioClient));
        }
    }

    DeviceManager::DeviceManager(HRESULT& result)
    {
        if (FAILED(result))
            return;

        m_hThread = (HANDLE)_beginthreadex(nullptr, 0, StaticThreadProc<DeviceManager>, this, 0, nullptr);

        if (m_hThread == NULL || !m_windowInitialized.get_future().get())
            result = E_FAIL;
    }

    DeviceManager::~DeviceManager()
    {
        m_queuedDestroy = true;
        PostMessage(m_hWindow, WM_DESTROY, 0, 0);
        WaitForSingleObject(m_hThread, INFINITE);
        CloseHandle(m_hThread);
        UnregisterClass(WindowClass, GetModuleHandle(nullptr));
    }

    bool DeviceManager::BitstreamFormatSupported(SharedWaveFormat format, ISettings* pSettings)
    {
        assert(format);
        assert(pSettings);

        m_checkBitstreamFormat = format;
        m_checkBitstreamSettings = pSettings;
        m_queuedCheckBitstream = true;

        bool ret = (SendMessage(m_hWindow, WM_CHECK_BITSTREAM_FORMAT, 0, 0) == 0);

        m_checkBitstreamFormat = nullptr;
        m_checkBitstreamSettings = nullptr;
        assert(m_queuedCheckBitstream == false);

        return ret;
    }

    SharedAudioDevice DeviceManager::CreateDevice(SharedWaveFormat format, ISettings* pSettings)
    {
        assert(format);
        assert(pSettings);

        m_createDeviceFormat = format;
        m_createDeviceSettings = pSettings;
        m_queuedCreateDevice = true;

        SharedAudioDevice ret = (SendMessage(m_hWindow, WM_CREATE_DEVICE, 0, 0) == 0) ? m_device : nullptr;

        m_createDeviceFormat = nullptr;
        m_createDeviceSettings = nullptr;
        assert(m_queuedCreateDevice == false);

        return ret;
    }

    void DeviceManager::ReleaseDevice()
    {
        if (!m_device)
            return;

        auto areLastInstances = [this]
        {
            if (!m_device.unique())
                return false;

            if (m_device->audioClock && !IsLastInstance(m_device->audioClock))
                return false;

            m_device->audioClock = nullptr;

            if (m_device->audioRenderClient && !IsLastInstance(m_device->audioRenderClient))
                return false;

            m_device->audioRenderClient = nullptr;

            if (m_device->audioClient && !IsLastInstance(m_device->audioClient))
                return false;

            return true;
        };
        assert(areLastInstances());

        m_device = nullptr;
    }

    LRESULT DeviceManager::OnCheckBitstreamFormat()
    {
        if (!m_queuedCheckBitstream)
            return 1;

        assert(m_checkBitstreamFormat);
        assert(m_checkBitstreamSettings);
        m_queuedCheckBitstream = false;

        try
        {
            AudioDevice device = {};

            {
                LPWSTR pDeviceName = nullptr;
                ThrowIfFailed(m_createDeviceSettings->GetOuputDevice(&pDeviceName, nullptr, nullptr));

                std::unique_ptr<wchar_t, CoTaskMemFreeDeleter> deviceName;
                deviceName.reset(pDeviceName);

                m_device->friendlyName = std::make_shared<std::wstring>(deviceName.get());
            }

            CreateAudioClient(device);

            if (!device.audioClient)
                return 1;

            return SUCCEEDED(device.audioClient->IsFormatSupported(AUDCLNT_SHAREMODE_EXCLUSIVE,
                                                                   &(*m_checkBitstreamFormat), nullptr)) ? 0 : 1;
        }
        catch (HRESULT)
        {
            return 1;
        }
    }

    LRESULT DeviceManager::OnCreateDevice()
    {
        if (!m_queuedCreateDevice)
            return 1;

        assert(m_createDeviceFormat);
        assert(m_createDeviceSettings);
        m_queuedCreateDevice = false;

        ReleaseDevice();
        try
        {
            assert(!m_device);
            m_device = std::make_shared<AudioDevice>();

            {
                LPWSTR pDeviceName = nullptr;
                BOOL exclusive;
                UINT32 buffer;
                ThrowIfFailed(m_createDeviceSettings->GetOuputDevice(&pDeviceName, &exclusive, &buffer));

                std::unique_ptr<wchar_t, CoTaskMemFreeDeleter> deviceName;
                deviceName.reset(pDeviceName);

                m_device->friendlyName = std::make_shared<std::wstring>(deviceName.get());
                m_device->exclusive = !!exclusive;
                m_device->bufferDuration = buffer;
            }

            CreateAudioClient(*m_device);

            if (!m_device->audioClient)
                return 1;

            WAVEFORMATEX* pFormat;
            ThrowIfFailed(m_device->audioClient->GetMixFormat(&pFormat));
            SharedWaveFormat mixFormat(pFormat, CoTaskMemFreeDeleter());

            m_device->bitstream = (DspFormatFromWaveFormat(*m_createDeviceFormat) == DspFormat::Unknown);

            if (m_device->bitstream)
            {
                // Exclusive bitstreaming.
                if (!m_device->exclusive)
                    return 1;

                m_device->dspFormat = DspFormat::Unknown;
                m_device->waveFormat = m_createDeviceFormat;
            }
            else if (m_device->exclusive)
            {
                // Exclusive.
                auto inputRate = m_createDeviceFormat->nSamplesPerSec;
                auto mixRate = mixFormat->nSamplesPerSec;
                auto mixChannels = mixFormat->nChannels;
                auto mixMask = DspMatrix::GetChannelMask(*mixFormat);

                auto priorities = make_array(
                    BuildWaveFormatExt(KSDATAFORMAT_SUBTYPE_IEEE_FLOAT, 32, 32, inputRate, mixChannels, mixMask),
                    BuildWaveFormatExt(KSDATAFORMAT_SUBTYPE_PCM,        32, 32, inputRate, mixChannels, mixMask),
                    BuildWaveFormatExt(KSDATAFORMAT_SUBTYPE_PCM,        24, 24, inputRate, mixChannels, mixMask),
                    BuildWaveFormatExt(KSDATAFORMAT_SUBTYPE_PCM,        32, 24, inputRate, mixChannels, mixMask),
                    BuildWaveFormatExt(KSDATAFORMAT_SUBTYPE_PCM,        16, 16, inputRate, mixChannels, mixMask),

                    BuildWaveFormatExt(KSDATAFORMAT_SUBTYPE_IEEE_FLOAT, 32, 32, mixRate, mixChannels, mixMask),
                    BuildWaveFormatExt(KSDATAFORMAT_SUBTYPE_PCM,        32, 32, mixRate, mixChannels, mixMask),
                    BuildWaveFormatExt(KSDATAFORMAT_SUBTYPE_PCM,        24, 24, mixRate, mixChannels, mixMask),
                    BuildWaveFormatExt(KSDATAFORMAT_SUBTYPE_PCM,        32, 24, mixRate, mixChannels, mixMask),
                    BuildWaveFormatExt(KSDATAFORMAT_SUBTYPE_PCM,        16, 16, mixRate, mixChannels, mixMask),

                    WAVEFORMATEXTENSIBLE{BuildWaveFormat(WAVE_FORMAT_PCM, 16, inputRate, mixChannels)},
                    WAVEFORMATEXTENSIBLE{BuildWaveFormat(WAVE_FORMAT_PCM, 16, mixRate,   mixChannels)}
                );

                for (const auto& f : priorities)
                {
                    assert(DspFormatFromWaveFormat(f.Format) != DspFormat::Unknown);

                    if (SUCCEEDED(m_device->audioClient->IsFormatSupported(AUDCLNT_SHAREMODE_EXCLUSIVE, &f.Format, nullptr)))
                    {
                        m_device->dspFormat = DspFormatFromWaveFormat(f.Format);
                        m_device->waveFormat = CopyWaveFormat(f.Format);
                        break;
                    }
                }
            }
            else
            {
                // Shared.
                m_device->dspFormat = DspFormat::Float;
                m_device->waveFormat = mixFormat;
            }

            ThrowIfFailed(m_device->audioClient->Initialize(m_device->exclusive ? AUDCLNT_SHAREMODE_EXCLUSIVE : AUDCLNT_SHAREMODE_SHARED,
                                                            0, MILLISECONDS_TO_100NS_UNITS(m_device->bufferDuration),
                                                            0, &(*m_device->waveFormat), nullptr));

            ThrowIfFailed(m_device->audioClient->GetService(IID_PPV_ARGS(&m_device->audioRenderClient)));

            ThrowIfFailed(m_device->audioClient->GetService(IID_PPV_ARGS(&m_device->audioClock)));

            return 0;
        }
        catch (std::bad_alloc&)
        {
            ReleaseDevice();
            return 1;
        }
        catch (HRESULT)
        {
            ReleaseDevice();
            return 1;
        }
    }

    DWORD DeviceManager::ThreadProc()
    {
        CoInitializeHelper coInitializeHelper(COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE);

        HINSTANCE hInstance = GetModuleHandle(nullptr);

        WNDCLASSEX windowClass{sizeof(windowClass), 0, StaticWindowProc<DeviceManager>, 0, 0, hInstance,
                               NULL, NULL, NULL, nullptr, WindowClass, NULL};

        m_hWindow = NULL;
        if (coInitializeHelper.Initialized())
        {
            RegisterClassEx(&windowClass);
            m_hWindow = CreateWindowEx(0, WindowClass, WindowTitle, 0, 0, 0, 0, 0, 0, NULL, hInstance, this);
        }

        if (m_hWindow != NULL)
        {
            m_windowInitialized.set_value(true);
            RunMessageLoop();
            ReleaseDevice();
        }
        else
        {
            m_windowInitialized.set_value(false);
        }

        return 0;
    }

    LRESULT DeviceManager::WindowProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
    {
        switch (msg)
        {
            case WM_DESTROY:
                if (m_queuedDestroy)
                    PostQuitMessage(0);
                return 0;

            case WM_CHECK_BITSTREAM_FORMAT:
                return OnCheckBitstreamFormat();

            case WM_CREATE_DEVICE:
                return OnCreateDevice();

            default:
                return DefWindowProc(hWnd, msg, wParam, lParam);
        }
    }
}
<commit_msg>Fix wrong copypasta<commit_after>#include "pch.h"
#include "DeviceManager.h"

#include "DspMatrix.h"

namespace SaneAudioRenderer
{
    namespace
    {
        const auto WindowClass = L"SaneAudioRenderer::DeviceManager";
        const auto WindowTitle = L"";

        enum
        {
            WM_CHECK_BITSTREAM_FORMAT = WM_USER + 100,
            WM_CREATE_DEVICE,
        };

        template <class T>
        bool IsLastInstance(T& smartPointer)
        {
            bool ret = (smartPointer.GetInterfacePtr()->AddRef() == 2);
            smartPointer.GetInterfacePtr()->Release();
            return ret;
        }

        WAVEFORMATEX BuildWaveFormat(WORD formatTag, uint32_t formatBits, uint32_t rate, uint32_t channelCount)
        {
            WAVEFORMATEX ret;

            ret.wFormatTag      = formatTag;
            ret.nChannels       = channelCount;
            ret.nSamplesPerSec  = rate;
            ret.nAvgBytesPerSec = formatBits / 8 * channelCount * rate;
            ret.nBlockAlign     = formatBits / 8 * channelCount;
            ret.wBitsPerSample  = formatBits;
            ret.cbSize          = (formatTag == WAVE_FORMAT_EXTENSIBLE) ? 22 : 0;

            return ret;
        }

        WAVEFORMATEXTENSIBLE BuildWaveFormatExt(GUID formatGuid, uint32_t formatBits, WORD formatExtProps,
                                                uint32_t rate, uint32_t channelCount, DWORD channelMask)
        {
            WAVEFORMATEXTENSIBLE ret;

            ret.Format                      = BuildWaveFormat(WAVE_FORMAT_EXTENSIBLE, formatBits, rate, channelCount);
            ret.Samples.wValidBitsPerSample = formatExtProps;
            ret.dwChannelMask               = channelMask;
            ret.SubFormat                   = formatGuid;

            return ret;
        }

        std::shared_ptr<std::wstring> GetDevicePropertyString(IPropertyStore* pStore, REFPROPERTYKEY key)
        {
            assert(pStore);

            PROPVARIANT prop;
            PropVariantInit(&prop);
            ThrowIfFailed(pStore->GetValue(key, &prop));
            auto ret = std::make_shared<std::wstring>(prop.pwszVal);
            PropVariantClear(&prop);

            return ret;
        }

        void CreateAudioClient(AudioDevice& audioDevice)
        {
            IMMDeviceEnumeratorPtr enumerator;
            ThrowIfFailed(CoCreateInstance(__uuidof(MMDeviceEnumerator), nullptr,
                                           CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&enumerator)));

            IMMDevicePtr device;
            IPropertyStorePtr devicePropertyStore;

            if (!audioDevice.friendlyName || audioDevice.friendlyName->empty())
            {
                audioDevice.default = true;
                ThrowIfFailed(enumerator->GetDefaultAudioEndpoint(eRender, eConsole, &device));
                ThrowIfFailed(device->OpenPropertyStore(STGM_READ, &devicePropertyStore));
                audioDevice.friendlyName = GetDevicePropertyString(devicePropertyStore, PKEY_Device_FriendlyName);
            }
            else
            {
                auto targetName = audioDevice.friendlyName;
                audioDevice.default = false;

                IMMDeviceCollectionPtr collection;
                ThrowIfFailed(enumerator->EnumAudioEndpoints(eRender, DEVICE_STATE_ACTIVE, &collection));

                UINT count = 0;
                ThrowIfFailed(collection->GetCount(&count));

                for (UINT i = 0; i < count; i++)
                {
                    ThrowIfFailed(collection->Item(i, &device));
                    ThrowIfFailed(device->OpenPropertyStore(STGM_READ, &devicePropertyStore));
                    audioDevice.friendlyName = GetDevicePropertyString(devicePropertyStore, PKEY_Device_FriendlyName);

                    if (*targetName != *audioDevice.friendlyName)
                    {
                        device = nullptr;
                        devicePropertyStore = nullptr;
                        audioDevice.friendlyName = nullptr;
                    }
                }
            }

            if (!device)
                return;

            audioDevice.adapterName = GetDevicePropertyString(devicePropertyStore, PKEY_DeviceInterface_FriendlyName);
            audioDevice.endpointName = GetDevicePropertyString(devicePropertyStore, PKEY_Device_DeviceDesc);

            ThrowIfFailed(device->Activate(__uuidof(IAudioClient),
                                           CLSCTX_INPROC_SERVER, nullptr, (void**)&audioDevice.audioClient));
        }
    }

    DeviceManager::DeviceManager(HRESULT& result)
    {
        if (FAILED(result))
            return;

        m_hThread = (HANDLE)_beginthreadex(nullptr, 0, StaticThreadProc<DeviceManager>, this, 0, nullptr);

        if (m_hThread == NULL || !m_windowInitialized.get_future().get())
            result = E_FAIL;
    }

    DeviceManager::~DeviceManager()
    {
        m_queuedDestroy = true;
        PostMessage(m_hWindow, WM_DESTROY, 0, 0);
        WaitForSingleObject(m_hThread, INFINITE);
        CloseHandle(m_hThread);
        UnregisterClass(WindowClass, GetModuleHandle(nullptr));
    }

    bool DeviceManager::BitstreamFormatSupported(SharedWaveFormat format, ISettings* pSettings)
    {
        assert(format);
        assert(pSettings);

        m_checkBitstreamFormat = format;
        m_checkBitstreamSettings = pSettings;
        m_queuedCheckBitstream = true;

        bool ret = (SendMessage(m_hWindow, WM_CHECK_BITSTREAM_FORMAT, 0, 0) == 0);

        m_checkBitstreamFormat = nullptr;
        m_checkBitstreamSettings = nullptr;
        assert(m_queuedCheckBitstream == false);

        return ret;
    }

    SharedAudioDevice DeviceManager::CreateDevice(SharedWaveFormat format, ISettings* pSettings)
    {
        assert(format);
        assert(pSettings);

        m_createDeviceFormat = format;
        m_createDeviceSettings = pSettings;
        m_queuedCreateDevice = true;

        SharedAudioDevice ret = (SendMessage(m_hWindow, WM_CREATE_DEVICE, 0, 0) == 0) ? m_device : nullptr;

        m_createDeviceFormat = nullptr;
        m_createDeviceSettings = nullptr;
        assert(m_queuedCreateDevice == false);

        return ret;
    }

    void DeviceManager::ReleaseDevice()
    {
        if (!m_device)
            return;

        auto areLastInstances = [this]
        {
            if (!m_device.unique())
                return false;

            if (m_device->audioClock && !IsLastInstance(m_device->audioClock))
                return false;

            m_device->audioClock = nullptr;

            if (m_device->audioRenderClient && !IsLastInstance(m_device->audioRenderClient))
                return false;

            m_device->audioRenderClient = nullptr;

            if (m_device->audioClient && !IsLastInstance(m_device->audioClient))
                return false;

            return true;
        };
        assert(areLastInstances());

        m_device = nullptr;
    }

    LRESULT DeviceManager::OnCheckBitstreamFormat()
    {
        if (!m_queuedCheckBitstream)
            return 1;

        assert(m_checkBitstreamFormat);
        assert(m_checkBitstreamSettings);
        m_queuedCheckBitstream = false;

        try
        {
            AudioDevice device = {};

            {
                LPWSTR pDeviceName = nullptr;
                ThrowIfFailed(m_checkBitstreamSettings->GetOuputDevice(&pDeviceName, nullptr, nullptr));

                std::unique_ptr<wchar_t, CoTaskMemFreeDeleter> deviceName;
                deviceName.reset(pDeviceName);

                device.friendlyName = std::make_shared<std::wstring>(deviceName.get());
            }

            CreateAudioClient(device);

            if (!device.audioClient)
                return 1;

            return SUCCEEDED(device.audioClient->IsFormatSupported(AUDCLNT_SHAREMODE_EXCLUSIVE,
                                                                   &(*m_checkBitstreamFormat), nullptr)) ? 0 : 1;
        }
        catch (HRESULT)
        {
            return 1;
        }
    }

    LRESULT DeviceManager::OnCreateDevice()
    {
        if (!m_queuedCreateDevice)
            return 1;

        assert(m_createDeviceFormat);
        assert(m_createDeviceSettings);
        m_queuedCreateDevice = false;

        ReleaseDevice();
        try
        {
            assert(!m_device);
            m_device = std::make_shared<AudioDevice>();

            {
                LPWSTR pDeviceName = nullptr;
                BOOL exclusive;
                UINT32 buffer;
                ThrowIfFailed(m_createDeviceSettings->GetOuputDevice(&pDeviceName, &exclusive, &buffer));

                std::unique_ptr<wchar_t, CoTaskMemFreeDeleter> deviceName;
                deviceName.reset(pDeviceName);

                m_device->friendlyName = std::make_shared<std::wstring>(deviceName.get());
                m_device->exclusive = !!exclusive;
                m_device->bufferDuration = buffer;
            }

            CreateAudioClient(*m_device);

            if (!m_device->audioClient)
                return 1;

            WAVEFORMATEX* pFormat;
            ThrowIfFailed(m_device->audioClient->GetMixFormat(&pFormat));
            SharedWaveFormat mixFormat(pFormat, CoTaskMemFreeDeleter());

            m_device->bitstream = (DspFormatFromWaveFormat(*m_createDeviceFormat) == DspFormat::Unknown);

            if (m_device->bitstream)
            {
                // Exclusive bitstreaming.
                if (!m_device->exclusive)
                    return 1;

                m_device->dspFormat = DspFormat::Unknown;
                m_device->waveFormat = m_createDeviceFormat;
            }
            else if (m_device->exclusive)
            {
                // Exclusive.
                auto inputRate = m_createDeviceFormat->nSamplesPerSec;
                auto mixRate = mixFormat->nSamplesPerSec;
                auto mixChannels = mixFormat->nChannels;
                auto mixMask = DspMatrix::GetChannelMask(*mixFormat);

                auto priorities = make_array(
                    BuildWaveFormatExt(KSDATAFORMAT_SUBTYPE_IEEE_FLOAT, 32, 32, inputRate, mixChannels, mixMask),
                    BuildWaveFormatExt(KSDATAFORMAT_SUBTYPE_PCM,        32, 32, inputRate, mixChannels, mixMask),
                    BuildWaveFormatExt(KSDATAFORMAT_SUBTYPE_PCM,        24, 24, inputRate, mixChannels, mixMask),
                    BuildWaveFormatExt(KSDATAFORMAT_SUBTYPE_PCM,        32, 24, inputRate, mixChannels, mixMask),
                    BuildWaveFormatExt(KSDATAFORMAT_SUBTYPE_PCM,        16, 16, inputRate, mixChannels, mixMask),

                    BuildWaveFormatExt(KSDATAFORMAT_SUBTYPE_IEEE_FLOAT, 32, 32, mixRate, mixChannels, mixMask),
                    BuildWaveFormatExt(KSDATAFORMAT_SUBTYPE_PCM,        32, 32, mixRate, mixChannels, mixMask),
                    BuildWaveFormatExt(KSDATAFORMAT_SUBTYPE_PCM,        24, 24, mixRate, mixChannels, mixMask),
                    BuildWaveFormatExt(KSDATAFORMAT_SUBTYPE_PCM,        32, 24, mixRate, mixChannels, mixMask),
                    BuildWaveFormatExt(KSDATAFORMAT_SUBTYPE_PCM,        16, 16, mixRate, mixChannels, mixMask),

                    WAVEFORMATEXTENSIBLE{BuildWaveFormat(WAVE_FORMAT_PCM, 16, inputRate, mixChannels)},
                    WAVEFORMATEXTENSIBLE{BuildWaveFormat(WAVE_FORMAT_PCM, 16, mixRate,   mixChannels)}
                );

                for (const auto& f : priorities)
                {
                    assert(DspFormatFromWaveFormat(f.Format) != DspFormat::Unknown);

                    if (SUCCEEDED(m_device->audioClient->IsFormatSupported(AUDCLNT_SHAREMODE_EXCLUSIVE, &f.Format, nullptr)))
                    {
                        m_device->dspFormat = DspFormatFromWaveFormat(f.Format);
                        m_device->waveFormat = CopyWaveFormat(f.Format);
                        break;
                    }
                }
            }
            else
            {
                // Shared.
                m_device->dspFormat = DspFormat::Float;
                m_device->waveFormat = mixFormat;
            }

            ThrowIfFailed(m_device->audioClient->Initialize(m_device->exclusive ? AUDCLNT_SHAREMODE_EXCLUSIVE : AUDCLNT_SHAREMODE_SHARED,
                                                            0, MILLISECONDS_TO_100NS_UNITS(m_device->bufferDuration),
                                                            0, &(*m_device->waveFormat), nullptr));

            ThrowIfFailed(m_device->audioClient->GetService(IID_PPV_ARGS(&m_device->audioRenderClient)));

            ThrowIfFailed(m_device->audioClient->GetService(IID_PPV_ARGS(&m_device->audioClock)));

            return 0;
        }
        catch (std::bad_alloc&)
        {
            ReleaseDevice();
            return 1;
        }
        catch (HRESULT)
        {
            ReleaseDevice();
            return 1;
        }
    }

    DWORD DeviceManager::ThreadProc()
    {
        CoInitializeHelper coInitializeHelper(COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE);

        HINSTANCE hInstance = GetModuleHandle(nullptr);

        WNDCLASSEX windowClass{sizeof(windowClass), 0, StaticWindowProc<DeviceManager>, 0, 0, hInstance,
                               NULL, NULL, NULL, nullptr, WindowClass, NULL};

        m_hWindow = NULL;
        if (coInitializeHelper.Initialized())
        {
            RegisterClassEx(&windowClass);
            m_hWindow = CreateWindowEx(0, WindowClass, WindowTitle, 0, 0, 0, 0, 0, 0, NULL, hInstance, this);
        }

        if (m_hWindow != NULL)
        {
            m_windowInitialized.set_value(true);
            RunMessageLoop();
            ReleaseDevice();
        }
        else
        {
            m_windowInitialized.set_value(false);
        }

        return 0;
    }

    LRESULT DeviceManager::WindowProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
    {
        switch (msg)
        {
            case WM_DESTROY:
                if (m_queuedDestroy)
                    PostQuitMessage(0);
                return 0;

            case WM_CHECK_BITSTREAM_FORMAT:
                return OnCheckBitstreamFormat();

            case WM_CREATE_DEVICE:
                return OnCreateDevice();

            default:
                return DefWindowProc(hWnd, msg, wParam, lParam);
        }
    }
}
<|endoftext|>


<commit_before>#include <UtH/Engine/Sprite.hpp>
#include <UtH/Engine/GameObject.hpp>
#include <UtH/Renderer/RenderTarget.hpp>
#include <UtH/Platform/Graphics.hpp>
#include <pmath/Vector3.hpp>

using namespace uth;

Sprite::Sprite(Texture* texture, const std::string& name)
	: Component(name),
	  m_texture(texture)
{
	defaults();
}

// Public

Sprite::Sprite(const std::string& filePath, const std::string& name)
	: Component(name)
{
	SetTexture(uthRS.LoadTexture(filePath));

	defaults();
}

Sprite::Sprite(const pmath::Vec4& fillColor, const pmath::Vec2& size, const std::string& name)
	: Component(name),
	  m_texture(nullptr)
{
	m_size = size;
    m_color = fillColor;
}

Sprite::~Sprite()
{
	m_texture = nullptr;
}

void Sprite::Init()
{
	generateBuffer(true);
	if (parent)
		parent->transform.SetSize(m_size);
}

void Sprite::Draw(RenderTarget& target)
{
	Shader& shader = target.GetShader();

	if (m_texture)
	{
		m_texture->Bind();
		shader.SetUniform("useTexture", 1.f);
		shader.SetUniform("unifSampler", 0);
	}
	else
	{
		shader.SetUniform("useTexture", 0.f);
	}

	m_vertexBuffer.bindArrayBuffer();
	// (position + uv + color) * sizeof(float)
	const int posOffset = (3 + 2 + 4)*sizeof(float);
	// position * sizeof(float)
	const int uvStart = 3*sizeof(float);
	// (position + uv) * sizeof(float)
	const int colorStart = (3 + 2)*sizeof(float);

	// Attribute name, number of components, datatype, bytes between first elements,
	// offset of first element in buffer
	shader.setAttributeData("attrPosition", 3, FLOAT_TYPE, posOffset, (void*)0);
	shader.setAttributeData("attrUV", 2, FLOAT_TYPE, posOffset, (void*)uvStart);
	shader.setAttributeData("attrColor", 4, FLOAT_TYPE, posOffset, (void*)colorStart);

	m_vertexBuffer.bindElementBuffer();
	uth::Graphics::DrawElements(TRIANGLES, m_vertexBuffer.getIndices().size(), UNSIGNED_SHORT_TYPE, (void*)0);

	uth::Graphics::BindBuffer(ARRAY_BUFFER, 0);
}

void Sprite::SetTexture(Texture* texture)
{
	m_texture = texture;
	m_size = texture->GetSize();
	Init();
}

Texture* Sprite::GetTexture() const
{
	return m_texture;
}

const pmath::Vec2& Sprite::GetSize() const
{
	return m_size;
}

void Sprite::SetColor(const pmath::Vec4& color)
{
	m_color = color;
	generateBuffer();
}

void Sprite::SetColor(float r, float g, float b, float a)
{
	SetColor(pmath::Vec4(r,g,b,a));
}

const pmath::Vec4& Sprite::GetColor() const
{
	return m_color;
}

// Private
void Sprite::defaults()
{
    if (m_texture)
	    m_size = m_texture->GetSize();
    else
        m_size = pmath::Vec2();

	m_color = pmath::Vec4(1.f, 1.f, 1.f, 1.f);
}

void Sprite::generateBuffer(bool init)
{
    if (init) // Create the buffer for the first time
    {
        m_vertexBuffer.clear();

        m_vertexBuffer.addVertex(Vertex(pmath::Vec3(-0.5f * m_size.x, -0.5f * m_size.y, 0),
            pmath::Vec2(0.0f, 1.0f), m_color));
        m_vertexBuffer.addVertex(Vertex(pmath::Vec3(0.5f * m_size.x, -0.5f * m_size.y, 0),
            pmath::Vec2(1.0f, 1.0f), m_color));
        m_vertexBuffer.addVertex(Vertex(pmath::Vec3(-0.5f * m_size.x, 0.5f * m_size.y, 0),
            pmath::Vec2(0.0f, 0.0f), m_color));
        m_vertexBuffer.addVertex(Vertex(pmath::Vec3(0.5f * m_size.x, 0.5f * m_size.y, 0),
            pmath::Vec2(1.0f, 0.0f), m_color));

        m_vertexBuffer.addIndex(0);
        m_vertexBuffer.addIndex(1);
        m_vertexBuffer.addIndex(2);
        m_vertexBuffer.addIndex(1);
        m_vertexBuffer.addIndex(3);
        m_vertexBuffer.addIndex(2);

        m_vertexBuffer.setData();
    }
    else // We are updating the buffer
    {
        std::vector<Vertex> vertices;
        vertices.reserve(4);
        vertices.push_back(Vertex(pmath::Vec3(-0.5f * m_size.x, -0.5f * m_size.y, 0),
        pmath::Vec2(0.0f, 1.0f), m_color));
        vertices.push_back(Vertex(pmath::Vec3(0.5f * m_size.x, -0.5f * m_size.y, 0),
        pmath::Vec2(1.0f, 1.0f), m_color));
        vertices.push_back(Vertex(pmath::Vec3(-0.5f * m_size.x, 0.5f * m_size.y, 0),
        pmath::Vec2(0.0f, 0.0f), m_color));
        vertices.push_back(Vertex(pmath::Vec3(0.5f * m_size.x, 0.5f * m_size.y, 0),
        pmath::Vec2(1.0f, 0.0f), m_color));

        m_vertexBuffer.changeBufferData(0, vertices);
    }
}
<commit_msg>Fixed transform size with textureless sprites<commit_after>#include <UtH/Engine/Sprite.hpp>
#include <UtH/Engine/GameObject.hpp>
#include <UtH/Renderer/RenderTarget.hpp>
#include <UtH/Platform/Graphics.hpp>
#include <pmath/Vector3.hpp>

using namespace uth;

Sprite::Sprite(Texture* texture, const std::string& name)
	: Component(name),
	  m_texture(texture)
{
	defaults();
}

// Public

Sprite::Sprite(const std::string& filePath, const std::string& name)
	: Component(name)
{
	SetTexture(uthRS.LoadTexture(filePath));

	defaults();
}

Sprite::Sprite(const pmath::Vec4& fillColor, const pmath::Vec2& size, const std::string& name)
	: Component(name),
	  m_texture(nullptr)
{
	m_size = size;
    m_color = fillColor;
	Init();
}

Sprite::~Sprite()
{
	m_texture = nullptr;
}

void Sprite::Init()
{
	generateBuffer(true);
	if (parent)
		parent->transform.SetSize(m_size);
}

void Sprite::Draw(RenderTarget& target)
{
	Shader& shader = target.GetShader();

	if (m_texture)
	{
		m_texture->Bind();
		shader.SetUniform("useTexture", 1.f);
		shader.SetUniform("unifSampler", 0);
	}
	else
	{
		shader.SetUniform("useTexture", 0.f);
	}

	m_vertexBuffer.bindArrayBuffer();
	// (position + uv + color) * sizeof(float)
	const int posOffset = (3 + 2 + 4)*sizeof(float);
	// position * sizeof(float)
	const int uvStart = 3*sizeof(float);
	// (position + uv) * sizeof(float)
	const int colorStart = (3 + 2)*sizeof(float);

	// Attribute name, number of components, datatype, bytes between first elements,
	// offset of first element in buffer
	shader.setAttributeData("attrPosition", 3, FLOAT_TYPE, posOffset, (void*)0);
	shader.setAttributeData("attrUV", 2, FLOAT_TYPE, posOffset, (void*)uvStart);
	shader.setAttributeData("attrColor", 4, FLOAT_TYPE, posOffset, (void*)colorStart);

	m_vertexBuffer.bindElementBuffer();
	uth::Graphics::DrawElements(TRIANGLES, m_vertexBuffer.getIndices().size(), UNSIGNED_SHORT_TYPE, (void*)0);

	uth::Graphics::BindBuffer(ARRAY_BUFFER, 0);
}

void Sprite::SetTexture(Texture* texture)
{
	m_texture = texture;
	m_size = texture->GetSize();
	Init();
}

Texture* Sprite::GetTexture() const
{
	return m_texture;
}

const pmath::Vec2& Sprite::GetSize() const
{
	return m_size;
}

void Sprite::SetColor(const pmath::Vec4& color)
{
	m_color = color;
	generateBuffer();
}

void Sprite::SetColor(float r, float g, float b, float a)
{
	SetColor(pmath::Vec4(r,g,b,a));
}

const pmath::Vec4& Sprite::GetColor() const
{
	return m_color;
}

// Private
void Sprite::defaults()
{
    if (m_texture)
	    m_size = m_texture->GetSize();
    else
        m_size = pmath::Vec2();

	m_color = pmath::Vec4(1.f, 1.f, 1.f, 1.f);
}

void Sprite::generateBuffer(bool init)
{
    if (init) // Create the buffer for the first time
    {
        m_vertexBuffer.clear();

        m_vertexBuffer.addVertex(Vertex(pmath::Vec3(-0.5f * m_size.x, -0.5f * m_size.y, 0),
            pmath::Vec2(0.0f, 1.0f), m_color));
        m_vertexBuffer.addVertex(Vertex(pmath::Vec3(0.5f * m_size.x, -0.5f * m_size.y, 0),
            pmath::Vec2(1.0f, 1.0f), m_color));
        m_vertexBuffer.addVertex(Vertex(pmath::Vec3(-0.5f * m_size.x, 0.5f * m_size.y, 0),
            pmath::Vec2(0.0f, 0.0f), m_color));
        m_vertexBuffer.addVertex(Vertex(pmath::Vec3(0.5f * m_size.x, 0.5f * m_size.y, 0),
            pmath::Vec2(1.0f, 0.0f), m_color));

        m_vertexBuffer.addIndex(0);
        m_vertexBuffer.addIndex(1);
        m_vertexBuffer.addIndex(2);
        m_vertexBuffer.addIndex(1);
        m_vertexBuffer.addIndex(3);
        m_vertexBuffer.addIndex(2);

        m_vertexBuffer.setData();
    }
    else // We are updating the buffer
    {
        std::vector<Vertex> vertices;
        vertices.reserve(4);
        vertices.push_back(Vertex(pmath::Vec3(-0.5f * m_size.x, -0.5f * m_size.y, 0),
        pmath::Vec2(0.0f, 1.0f), m_color));
        vertices.push_back(Vertex(pmath::Vec3(0.5f * m_size.x, -0.5f * m_size.y, 0),
        pmath::Vec2(1.0f, 1.0f), m_color));
        vertices.push_back(Vertex(pmath::Vec3(-0.5f * m_size.x, 0.5f * m_size.y, 0),
        pmath::Vec2(0.0f, 0.0f), m_color));
        vertices.push_back(Vertex(pmath::Vec3(0.5f * m_size.x, 0.5f * m_size.y, 0),
        pmath::Vec2(1.0f, 0.0f), m_color));

        m_vertexBuffer.changeBufferData(0, vertices);
    }
}
<|endoftext|>


<commit_before>#include <gtest/gtest.h>
#include <Process.h>
#include <signal.h>

using namespace testing;
using namespace Interprocess;

class InterprocessChildDestructionTest : public Test
{
public:
  static void dummyFunction(){}
  std::unique_ptr<Process> process;
  int processID;
  void SetUp() override
  {
    process = std::make_unique<Process>(dummyFunction);
    processID = process->GetProcessId();
  }
};

TEST_F(InterprocessChildDestructionTest, ExpectToKillChildOnProcessDestructor)
{
  process.reset(nullptr);
  int result = kill(processID, SIGINT);
  ASSERT_TRUE(result == -1);
}

TEST_F(InterprocessChildDestructionTest, ExpectNotToKillChildWhenProcessIsReleased)
{
  process->detach();
  process.reset(nullptr);
  int result = kill(processID, SIGINT);
  ASSERT_TRUE(result == 0);
}
<commit_msg>Changed ChildDestructionTest fixture name.<commit_after>#include <gtest/gtest.h>
#include <Process.h>
#include <signal.h>

using namespace testing;
using namespace Interprocess;

class ChildDestructionTest : public Test
{
public:
  static void dummyFunction(){}
  std::unique_ptr<Process> process;
  int processID;
  void SetUp() override
  {
    process = std::make_unique<Process>(dummyFunction);
    processID = process->GetProcessId();
  }
};

TEST_F(ChildDestructionTest, ExpectToKillChildOnProcessDestructor)
{
  process.reset(nullptr);
  int result = kill(processID, SIGINT);
  ASSERT_TRUE(result == -1);
}

TEST_F(ChildDestructionTest, ExpectNotToKillChildWhenProcessIsReleased)
{
  process->detach();
  process.reset(nullptr);
  int result = kill(processID, SIGINT);
  ASSERT_TRUE(result == 0);
}
<|endoftext|>


<commit_before>#pragma once

#include <limits>
#include <type_traits>

namespace fly::detail {

/**
 * Structures to recursively aggregate the value of an integer literal as it is being parsed.
 *
 * @tparam T The desired integer literal type.
 * @tparam Base The base of the integer literal being parsed.
 * @tparam Literals Variadic list of characters to parse.
 */
template <typename T, T Base, char... Literals>
struct Aggregator;

// Specialization to convert the current character being parsed to an integer and recurse on the
// remainder of the characters.
template <typename T, T Base, char Digit, char... Literals>
struct Aggregator<T, Base, Digit, Literals...>
{
    constexpr static T aggregate(T aggregated)
    {
        return Aggregator<T, Base, Literals...>::aggregate(
            aggregated * Base + parse_and_validate_literal());
    }

private:
    /**
     * Convert the current character being parsed to an integer literal. Validate that the character
     * fits within its base.
     *
     * @return The result of conversion.
     */
    constexpr static T parse_and_validate_literal()
    {
        constexpr bool literal_is_valid_for_base =
            ((Base == 2) && ((Digit >= '0') && (Digit <= '1'))) ||
            ((Base == 8) && ((Digit >= '0') && (Digit <= '7'))) ||
            ((Base == 10) && ((Digit >= '0') && (Digit <= '9'))) ||
            ((Base == 16) && ((Digit >= '0') && (Digit <= '9'))) ||
            ((Base == 16) && ((Digit >= 'A') && (Digit <= 'F'))) ||
            ((Base == 16) && ((Digit >= 'a') && (Digit <= 'f')));
        static_assert(literal_is_valid_for_base, "Invalid literal for base");

        if constexpr ((Digit >= 'A') && (Digit <= 'F'))
        {
            return static_cast<T>(Digit) - static_cast<T>('A') + 0xA;
        }
        else if constexpr ((Digit >= 'a') && (Digit <= 'f'))
        {
            return static_cast<T>(Digit) - static_cast<T>('a') + 0xa;
        }
        else
        {
            return static_cast<T>(Digit) - static_cast<T>('0');
        }
    }
};

// Specialization to simply ignore a separator character and recurse on the remainder of the
// characters.
template <typename T, T Base, char... Literals>
struct Aggregator<T, Base, '\'', Literals...>
{
    constexpr static T aggregate(T aggregated)
    {
        return Aggregator<T, Base, Literals...>::aggregate(aggregated);
    }
};

// Specialization to terminate agregation when there are no more characters to be parsed.
template <typename T, T Base>
struct Aggregator<T, Base>
{
    constexpr static T aggregate(T aggregated)
    {
        return aggregated;
    }
};

/**
 * Structures to parse a sequence of characters and convert the result to an integer literal of a
 * desired type.
 *
 * Parsing occurs in two phases. First, any base-specifying prefix is parsed. By default, base-10 is
 * assumed, and specializations are used for other bases. Next, the remaining characters are parsed
 * base on the determined base and converted to the desired type.
 *
 * @tparam T The desired integer literal type.
 * @tparam Base The base of the integer literal being parsed.
 * @tparam Literals Variadic list of characters to parse.
 */
template <typename T, T Base, char... Literals>
struct ParserBase
{
    static constexpr T parse()
    {
        return Aggregator<T, Base, Literals...>::aggregate(static_cast<T>(0));
    }
};

// Decimal default.
template <typename T, char... Literals>
struct Parser : ParserBase<T, 10, Literals...>
{
};

// Binary specializations.
template <typename T, char... Literals>
struct Parser<T, '0', 'b', Literals...> : ParserBase<T, 2, Literals...>
{
};

template <typename T, char... Literals>
struct Parser<T, '0', 'B', Literals...> : ParserBase<T, 2, Literals...>
{
};

// Octal specializations.
template <typename T, char... Literals>
struct Parser<T, '0', Literals...> : ParserBase<T, 8, Literals...>
{
};

// Hexadecimal specializations.
template <typename T, char... Literals>
struct Parser<T, '0', 'x', Literals...> : ParserBase<T, 16, Literals...>
{
};

template <typename T, char... Literals>
struct Parser<T, '0', 'X', Literals...> : ParserBase<T, 16, Literals...>
{
};

/**
 * Validate that a value can be converted to a desired type and perform that conversion
 *
 * @tparam From The current integer literal type.
 * @tparam To The desired integer literal type.
 * @tparam Value The value to convert.
 *
 * @return The converted integer literal.
 */
template <typename From, typename To, From Value>
constexpr To validate_and_convert()
{
    static_assert(Value >= std::numeric_limits<To>::min(), "Literal overflow");
    static_assert(Value <= std::numeric_limits<To>::max(), "Literal overflow");

    return static_cast<To>(Value);
}

/**
 * Parse a sequence of characters and convert the result to an integer literal of a desired type.
 *
 * @tparam T The desired integer literal type.
 * @tparam Literals Variadic list of characters to parse.
 *
 * @return The parsed integer literal.
 */
template <typename T, char... Literals>
constexpr T literal()
{
    if constexpr (std::is_signed_v<T>)
    {
        constexpr auto value = Parser<long long, Literals...>::parse();
        return validate_and_convert<decltype(value), T, value>();
    }
    else
    {
        constexpr auto value = Parser<unsigned long long, Literals...>::parse();
        return validate_and_convert<decltype(value), T, value>();
    }
}

} // namespace fly::detail
<commit_msg>Briefer fly::detail::literal() implementation<commit_after>#pragma once

#include <cstdint>
#include <limits>
#include <type_traits>

namespace fly::detail {

/**
 * Structures to recursively aggregate the value of an integer literal as it is being parsed.
 *
 * @tparam T The desired integer literal type.
 * @tparam Base The base of the integer literal being parsed.
 * @tparam Literals Variadic list of characters to parse.
 */
template <typename T, T Base, char... Literals>
struct Aggregator;

// Specialization to convert the current character being parsed to an integer and recurse on the
// remainder of the characters.
template <typename T, T Base, char Digit, char... Literals>
struct Aggregator<T, Base, Digit, Literals...>
{
    static constexpr T aggregate(T aggregated)
    {
        return Aggregator<T, Base, Literals...>::aggregate(
            aggregated * Base + parse_and_validate_literal());
    }

private:
    /**
     * Convert the current character being parsed to an integer literal. Validate that the character
     * fits within its base.
     *
     * @return The result of conversion.
     */
    static constexpr T parse_and_validate_literal()
    {
        constexpr bool literal_is_valid_for_base =
            ((Base == 2) && ((Digit >= '0') && (Digit <= '1'))) ||
            ((Base == 8) && ((Digit >= '0') && (Digit <= '7'))) ||
            ((Base == 10) && ((Digit >= '0') && (Digit <= '9'))) ||
            ((Base == 16) && ((Digit >= '0') && (Digit <= '9'))) ||
            ((Base == 16) && ((Digit >= 'A') && (Digit <= 'F'))) ||
            ((Base == 16) && ((Digit >= 'a') && (Digit <= 'f')));
        static_assert(literal_is_valid_for_base, "Invalid literal for base");

        if constexpr ((Digit >= 'A') && (Digit <= 'F'))
        {
            return static_cast<T>(Digit) - static_cast<T>('A') + 0xA;
        }
        else if constexpr ((Digit >= 'a') && (Digit <= 'f'))
        {
            return static_cast<T>(Digit) - static_cast<T>('a') + 0xa;
        }
        else
        {
            return static_cast<T>(Digit) - static_cast<T>('0');
        }
    }
};

// Specialization to simply ignore a separator character and recurse on the remainder of the
// characters.
template <typename T, T Base, char... Literals>
struct Aggregator<T, Base, '\'', Literals...>
{
    static constexpr T aggregate(T aggregated)
    {
        return Aggregator<T, Base, Literals...>::aggregate(aggregated);
    }
};

// Specialization to terminate agregation when there are no more characters to be parsed.
template <typename T, T Base>
struct Aggregator<T, Base>
{
    static constexpr T aggregate(T aggregated)
    {
        return aggregated;
    }
};

/**
 * Structures to parse a sequence of characters and convert the result to an integer literal of a
 * desired type.
 *
 * Parsing occurs in two phases. First, any base-specifying prefix is parsed. By default, base-10 is
 * assumed, and specializations are used for other bases. Next, the remaining characters are parsed
 * base on the determined base and converted to the desired type.
 *
 * @tparam T The desired integer literal type.
 * @tparam Base The base of the integer literal being parsed.
 * @tparam Literals Variadic list of characters to parse.
 */
template <typename T, T Base, char... Literals>
struct ParserBase
{
    static constexpr T parse()
    {
        return Aggregator<T, Base, Literals...>::aggregate(static_cast<T>(0));
    }
};

// Decimal default.
template <typename T, char... Literals>
struct Parser : ParserBase<T, 10, Literals...>
{
};

// Binary specializations.
template <typename T, char... Literals>
struct Parser<T, '0', 'b', Literals...> : ParserBase<T, 2, Literals...>
{
};

template <typename T, char... Literals>
struct Parser<T, '0', 'B', Literals...> : ParserBase<T, 2, Literals...>
{
};

// Octal specializations.
template <typename T, char... Literals>
struct Parser<T, '0', Literals...> : ParserBase<T, 8, Literals...>
{
};

// Hexadecimal specializations.
template <typename T, char... Literals>
struct Parser<T, '0', 'x', Literals...> : ParserBase<T, 16, Literals...>
{
};

template <typename T, char... Literals>
struct Parser<T, '0', 'X', Literals...> : ParserBase<T, 16, Literals...>
{
};

/**
 * Validate that a value can be converted to a desired type and perform that conversion
 *
 * @tparam From The current integer literal type.
 * @tparam To The desired integer literal type.
 * @tparam Value The value to convert.
 *
 * @return The converted integer literal.
 */
template <typename From, typename To, From Value>
constexpr To validate_and_convert()
{
    static_assert(Value >= std::numeric_limits<To>::min(), "Literal overflow");
    static_assert(Value <= std::numeric_limits<To>::max(), "Literal overflow");

    return static_cast<To>(Value);
}

/**
 * Parse a sequence of characters and convert the result to an integer literal of a desired type.
 *
 * @tparam T The desired integer literal type.
 * @tparam Literals Variadic list of characters to parse.
 *
 * @return The parsed integer literal.
 */
template <typename T, char... Literals>
constexpr T literal()
{
    using ValueType = std::conditional_t<std::is_signed_v<T>, std::intmax_t, std::uintmax_t>;
    return validate_and_convert<ValueType, T, Parser<ValueType, Literals...>::parse()>();
}

} // namespace fly::detail
<|endoftext|>


<commit_before>// Scintilla source code edit control
/** @file ExternalLexer.cxx
 ** Support external lexers in DLLs.
 **/
// Copyright 2001 Simon Steele <ss@pnotepad.org>, portions copyright Neil Hodgson.
// The License.txt file describes the conditions under which this software may be distributed.

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>

#include <string>

#include "Platform.h"

#include "Scintilla.h"

#include "SciLexer.h"
#include "PropSet.h"
#include "Accessor.h"
#include "DocumentAccessor.h"
#include "KeyWords.h"
#include "ExternalLexer.h"

#ifdef SCI_NAMESPACE
using namespace Scintilla;
#endif

LexerManager *LexerManager::theInstance = NULL;

//------------------------------------------
//
// ExternalLexerModule
//
//------------------------------------------

char **WordListsToStrings(WordList *val[]) {
	int dim = 0;
	while (val[dim])
		dim++;
	char **wls = new char * [dim + 1];
	for (int i = 0; i < dim; i++) {
		std::string words;
		words = "";
		for (int n = 0; n < val[i]->len; n++) {
			words += val[i]->words[n];
			if (n != val[i]->len - 1)
				words += " ";
		}
		wls[i] = new char[words.length() + 1];
		strcpy(wls[i], words.c_str());
	}
	wls[dim] = 0;
	return wls;
}

void DeleteWLStrings(char *strs[]) {
	int dim = 0;
	while (strs[dim]) {
		delete strs[dim];
		dim++;
	}
	delete [] strs;
}

void ExternalLexerModule::Lex(unsigned int startPos, int lengthDoc, int initStyle,
                              WordList *keywordlists[], Accessor &styler) const {
	if (!fneLexer)
		return ;

	char **kwds = WordListsToStrings(keywordlists);
	char *ps = styler.GetProperties();

	// The accessor passed in is always a DocumentAccessor so this cast and the subsequent
	// access will work. Can not use the stricter dynamic_cast as that requires RTTI.
	DocumentAccessor &da = static_cast<DocumentAccessor &>(styler);
	WindowID wID = da.GetWindow();

	fneLexer(externalLanguage, startPos, lengthDoc, initStyle, kwds, wID, ps);

	delete ps;
	DeleteWLStrings(kwds);
}

void ExternalLexerModule::Fold(unsigned int startPos, int lengthDoc, int initStyle,
                               WordList *keywordlists[], Accessor &styler) const {
	if (!fneFolder)
		return ;

	char **kwds = WordListsToStrings(keywordlists);
	char *ps = styler.GetProperties();

	// The accessor passed in is always a DocumentAccessor so this cast and the subsequent
	// access will work. Can not use the stricter dynamic_cast as that requires RTTI.
	DocumentAccessor &da = static_cast<DocumentAccessor &>(styler);
	WindowID wID = da.GetWindow();

	fneFolder(externalLanguage, startPos, lengthDoc, initStyle, kwds, wID, ps);

	delete ps;
	DeleteWLStrings(kwds);
}

void ExternalLexerModule::SetExternal(ExtLexerFunction fLexer, ExtFoldFunction fFolder, int index) {
	fneLexer = fLexer;
	fneFolder = fFolder;
	externalLanguage = index;
}

//------------------------------------------
//
// LexerLibrary
//
//------------------------------------------

LexerLibrary::LexerLibrary(const char *ModuleName) {
	// Initialise some members...
	first = NULL;
	last = NULL;

	// Load the DLL
	lib = DynamicLibrary::Load(ModuleName);
	if (lib->IsValid()) {
		m_sModuleName = ModuleName;
		//Cannot use reinterpret_cast because: ANSI C++ forbids casting between pointers to functions and objects
		GetLexerCountFn GetLexerCount = (GetLexerCountFn)(sptr_t)lib->FindFunction("GetLexerCount");

		if (GetLexerCount) {
			ExternalLexerModule *lex;
			LexerMinder *lm;

			// Find functions in the DLL
			GetLexerNameFn GetLexerName = (GetLexerNameFn)(sptr_t)lib->FindFunction("GetLexerName");
			ExtLexerFunction Lexer = (ExtLexerFunction)(sptr_t)lib->FindFunction("Lex");
			ExtFoldFunction Folder = (ExtFoldFunction)(sptr_t)lib->FindFunction("Fold");

			// Assign a buffer for the lexer name.
			char lexname[100];
			strcpy(lexname, "");

			int nl = GetLexerCount();

			for (int i = 0; i < nl; i++) {
				GetLexerName(i, lexname, 100);
				lex = new ExternalLexerModule(SCLEX_AUTOMATIC, NULL, lexname, NULL);

				// Create a LexerMinder so we don't leak the ExternalLexerModule...
				lm = new LexerMinder;
				lm->self = lex;
				lm->next = NULL;
				if (first != NULL) {
					last->next = lm;
					last = lm;
				} else {
					first = lm;
					last = lm;
				}

				// The external lexer needs to know how to call into its DLL to
				// do its lexing and folding, we tell it here. Folder may be null.
				lex->SetExternal(Lexer, Folder, i);
			}
		}
	}
	next = NULL;
}

LexerLibrary::~LexerLibrary() {
	Release();
	delete lib;
}

void LexerLibrary::Release() {
	//TODO maintain a list of lexers created, and delete them!
	LexerMinder *lm;
	LexerMinder *lmNext;
	lm = first;
	while (NULL != lm) {
		lmNext = lm->next;
		delete lm->self;
		delete lm;
		lm = lmNext;
	}

	first = NULL;
	last = NULL;
}

//------------------------------------------
//
// LexerManager
//
//------------------------------------------

/// Return the single LexerManager instance...
LexerManager *LexerManager::GetInstance() {
	if (!theInstance)
		theInstance = new LexerManager;
	return theInstance;
}

/// Delete any LexerManager instance...
void LexerManager::DeleteInstance() {
	delete theInstance;
	theInstance = NULL;
}

/// protected constructor - this is a singleton...
LexerManager::LexerManager() {
	first = NULL;
	last = NULL;
}

LexerManager::~LexerManager() {
	Clear();
}

void LexerManager::Load(const char *path) {
	LoadLexerLibrary(path);
}

void LexerManager::LoadLexerLibrary(const char *module) {
	LexerLibrary *lib = new LexerLibrary(module);
	if (NULL != first) {
		last->next = lib;
		last = lib;
	} else {
		first = lib;
		last = lib;
	}
}

void LexerManager::Clear() {
	if (NULL != first) {
		LexerLibrary *cur = first;
		LexerLibrary *next;
		while (cur) {
			next = cur->next;
			delete cur;
			cur = next;
		}
		first = NULL;
		last = NULL;
	}
}

//------------------------------------------
//
// LexerManager
//
//------------------------------------------

LMMinder::~LMMinder() {
	LexerManager::DeleteInstance();
}

LMMinder minder;
<commit_msg>Ensure each external lexer library is only loaded once.<commit_after>// Scintilla source code edit control
/** @file ExternalLexer.cxx
 ** Support external lexers in DLLs.
 **/
// Copyright 2001 Simon Steele <ss@pnotepad.org>, portions copyright Neil Hodgson.
// The License.txt file describes the conditions under which this software may be distributed.

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>

#include <string>

#include "Platform.h"

#include "Scintilla.h"

#include "SciLexer.h"
#include "PropSet.h"
#include "Accessor.h"
#include "DocumentAccessor.h"
#include "KeyWords.h"
#include "ExternalLexer.h"

#ifdef SCI_NAMESPACE
using namespace Scintilla;
#endif

LexerManager *LexerManager::theInstance = NULL;

//------------------------------------------
//
// ExternalLexerModule
//
//------------------------------------------

char **WordListsToStrings(WordList *val[]) {
	int dim = 0;
	while (val[dim])
		dim++;
	char **wls = new char * [dim + 1];
	for (int i = 0; i < dim; i++) {
		std::string words;
		words = "";
		for (int n = 0; n < val[i]->len; n++) {
			words += val[i]->words[n];
			if (n != val[i]->len - 1)
				words += " ";
		}
		wls[i] = new char[words.length() + 1];
		strcpy(wls[i], words.c_str());
	}
	wls[dim] = 0;
	return wls;
}

void DeleteWLStrings(char *strs[]) {
	int dim = 0;
	while (strs[dim]) {
		delete strs[dim];
		dim++;
	}
	delete [] strs;
}

void ExternalLexerModule::Lex(unsigned int startPos, int lengthDoc, int initStyle,
                              WordList *keywordlists[], Accessor &styler) const {
	if (!fneLexer)
		return ;

	char **kwds = WordListsToStrings(keywordlists);
	char *ps = styler.GetProperties();

	// The accessor passed in is always a DocumentAccessor so this cast and the subsequent
	// access will work. Can not use the stricter dynamic_cast as that requires RTTI.
	DocumentAccessor &da = static_cast<DocumentAccessor &>(styler);
	WindowID wID = da.GetWindow();

	fneLexer(externalLanguage, startPos, lengthDoc, initStyle, kwds, wID, ps);

	delete ps;
	DeleteWLStrings(kwds);
}

void ExternalLexerModule::Fold(unsigned int startPos, int lengthDoc, int initStyle,
                               WordList *keywordlists[], Accessor &styler) const {
	if (!fneFolder)
		return ;

	char **kwds = WordListsToStrings(keywordlists);
	char *ps = styler.GetProperties();

	// The accessor passed in is always a DocumentAccessor so this cast and the subsequent
	// access will work. Can not use the stricter dynamic_cast as that requires RTTI.
	DocumentAccessor &da = static_cast<DocumentAccessor &>(styler);
	WindowID wID = da.GetWindow();

	fneFolder(externalLanguage, startPos, lengthDoc, initStyle, kwds, wID, ps);

	delete ps;
	DeleteWLStrings(kwds);
}

void ExternalLexerModule::SetExternal(ExtLexerFunction fLexer, ExtFoldFunction fFolder, int index) {
	fneLexer = fLexer;
	fneFolder = fFolder;
	externalLanguage = index;
}

//------------------------------------------
//
// LexerLibrary
//
//------------------------------------------

LexerLibrary::LexerLibrary(const char *ModuleName) {
	// Initialise some members...
	first = NULL;
	last = NULL;

	// Load the DLL
	lib = DynamicLibrary::Load(ModuleName);
	if (lib->IsValid()) {
		m_sModuleName = ModuleName;
		//Cannot use reinterpret_cast because: ANSI C++ forbids casting between pointers to functions and objects
		GetLexerCountFn GetLexerCount = (GetLexerCountFn)(sptr_t)lib->FindFunction("GetLexerCount");

		if (GetLexerCount) {
			ExternalLexerModule *lex;
			LexerMinder *lm;

			// Find functions in the DLL
			GetLexerNameFn GetLexerName = (GetLexerNameFn)(sptr_t)lib->FindFunction("GetLexerName");
			ExtLexerFunction Lexer = (ExtLexerFunction)(sptr_t)lib->FindFunction("Lex");
			ExtFoldFunction Folder = (ExtFoldFunction)(sptr_t)lib->FindFunction("Fold");

			// Assign a buffer for the lexer name.
			char lexname[100];
			strcpy(lexname, "");

			int nl = GetLexerCount();

			for (int i = 0; i < nl; i++) {
				GetLexerName(i, lexname, 100);
				lex = new ExternalLexerModule(SCLEX_AUTOMATIC, NULL, lexname, NULL);

				// Create a LexerMinder so we don't leak the ExternalLexerModule...
				lm = new LexerMinder;
				lm->self = lex;
				lm->next = NULL;
				if (first != NULL) {
					last->next = lm;
					last = lm;
				} else {
					first = lm;
					last = lm;
				}

				// The external lexer needs to know how to call into its DLL to
				// do its lexing and folding, we tell it here. Folder may be null.
				lex->SetExternal(Lexer, Folder, i);
			}
		}
	}
	next = NULL;
}

LexerLibrary::~LexerLibrary() {
	Release();
	delete lib;
}

void LexerLibrary::Release() {
	//TODO maintain a list of lexers created, and delete them!
	LexerMinder *lm;
	LexerMinder *lmNext;
	lm = first;
	while (NULL != lm) {
		lmNext = lm->next;
		delete lm->self;
		delete lm;
		lm = lmNext;
	}

	first = NULL;
	last = NULL;
}

//------------------------------------------
//
// LexerManager
//
//------------------------------------------

/// Return the single LexerManager instance...
LexerManager *LexerManager::GetInstance() {
	if (!theInstance)
		theInstance = new LexerManager;
	return theInstance;
}

/// Delete any LexerManager instance...
void LexerManager::DeleteInstance() {
	delete theInstance;
	theInstance = NULL;
}

/// protected constructor - this is a singleton...
LexerManager::LexerManager() {
	first = NULL;
	last = NULL;
}

LexerManager::~LexerManager() {
	Clear();
}

void LexerManager::Load(const char *path) {
	LoadLexerLibrary(path);
}

void LexerManager::LoadLexerLibrary(const char *module) {
	for (LexerLibrary *ll = first; ll; ll= ll->next) {
		if (strcmp(ll->m_sModuleName.c_str(), module) == 0)
			return;
	}
	LexerLibrary *lib = new LexerLibrary(module);
	if (NULL != first) {
		last->next = lib;
		last = lib;
	} else {
		first = lib;
		last = lib;
	}
}

void LexerManager::Clear() {
	if (NULL != first) {
		LexerLibrary *cur = first;
		LexerLibrary *next;
		while (cur) {
			next = cur->next;
			delete cur;
			cur = next;
		}
		first = NULL;
		last = NULL;
	}
}

//------------------------------------------
//
// LexerManager
//
//------------------------------------------

LMMinder::~LMMinder() {
	LexerManager::DeleteInstance();
}

LMMinder minder;
<|endoftext|>