<commit_before>class AliAnalysisGrid;

void RunAnalysisITS() {
  //
  // Macro to analyze ESDs from raw data reconstruction
  // A.Dainese, andrea.dainese@pd.infn.it
  //
  //gSystem->Setenv("alien_CLOSE_SE","ALICE::CNAF::SE");

  gSystem->SetIncludePath("-I. -I$ROOTSYS/include -I$ALICE_ROOT -I$ALICE_ROOT/include -I$ALICE_ROOT/ITS -I$ALICE_ROOT/TPC -I$ALICE_ROOT/CONTAINERS -I$ALICE_ROOT/STEER -I$ALICE_ROOT/TRD -I$ALICE_ROOT/macros -I$ALICE_ROOT/ANALYSIS -g");

  //
  TString analysisMode = "grid"; // "local", "grid", or "proof" (not yet)

  Long64_t nentries=1000000000000000,firstentry=0;
  Bool_t useAlienPlugin=kTRUE;
  Bool_t uselibPWG1=kTRUE;
  TString pluginmode="full";
  TString loadMacroPath="./";
  Bool_t readHLT=kFALSE;
  //

  if(analysisMode=="grid") {
    // Connect to AliEn
    TGrid::Connect("alien://");
  } else if(analysisMode=="proof") {
    // Connect to the PROOF cluster
    printf("PROOF mode not yet functional..\n");
    return;
    TProof::Open("alicecaf");
    //TProof::Reset("alicecaf");
  }

  // Load analysis libraries
  gSystem->Load("libANALYSIS.so");
  gSystem->Load("libANALYSISalice.so");
  if(uselibPWG1) gSystem->Load("libPWG1.so");

  // Create Alien plugin, if requested
  if(useAlienPlugin) {
    AliAnalysisGrid *alienHandler = CreateAlienHandler(pluginmode,uselibPWG1);
    if(!alienHandler) return;
  }

  TChain *chainESD = 0;
  if(!useAlienPlugin) {
    // Prepare input chain
    //    chainESD = CreateESDChain("/home/dainesea/alignData/RAWdata_CosmicsSum09/RecoSPD/chunk.",13,13);
    chainESD=new TChain("esdTree");
    //chainESD->Add("alien:///alice/cern.ch/user/s/sitta/output/000088361/ESDs/pass1/09000088361017.10/AliESDs.root");
    chainESD->Add("AliESDs.root");
  }

  // Create the analysis manager
  AliAnalysisManager *mgr  = new AliAnalysisManager("My Manager","My Manager");
  // Enable debug printouts
  mgr->SetDebugLevel(10);
  // Connect plug-in to the analysis manager
  if(useAlienPlugin) mgr->SetGridHandler(alienHandler);

  // Add ESD handler
  AliESDInputHandler *esdH = new AliESDInputHandler();
  if(readHLT) esdH->SetReadHLT();
  mgr->SetInputEventHandler(esdH);
  //-------------------------------------------------------------------

  //-------------------------------------------------------------------
  // Analysis tasks (wagons of the train)
  //
  TString taskName;

  if(!uselibPWG1) gROOT->LoadMacro("AliAlignmentDataFilterITS.cxx++g");
  taskName="AddTaskAlignmentDataFilterITS.C";
  taskName.Prepend(loadMacroPath.Data());
  gROOT->LoadMacro(taskName.Data());
  AliAlignmentDataFilterITS *itsTask = AddTaskAlignmentDataFilterITS();

  if(!uselibPWG1) gROOT->LoadMacro("AliTrackMatchingTPCITSCosmics.cxx++g");
  taskName="AddTaskTrackMatchingTPCITS.C";
  taskName.Prepend(loadMacroPath.Data());
  gROOT->LoadMacro(taskName.Data());
  AliTrackMatchingTPCITSCosmics *tpcitsTask = AddTaskTrackMatchingTPCITS();
  if(readHLT) tpcitsTask->SetReadHLTESD(kTRUE);

  //
  // Run the analysis
  //
  if(chainESD) printf("CHAIN HAS %d ENTRIES\n",(Int_t)chainESD->GetEntries());

  if(!mgr->InitAnalysis()) return;
  mgr->PrintStatus();
  if(analysisMode=="grid" && !useAlienPlugin) analysisMode="local";
  mgr->StartAnalysis(analysisMode.Data(),chainESD,nentries,firstentry);

  return;
}
//_____________________________________________________________________________
//
AliAnalysisGrid* CreateAlienHandler(TString pluginmode="test",
				    Bool_t uselibPWG1=kFALSE)
{
  // Check if user has a valid token, otherwise make one. This has limitations.
  // One can always follow the standard procedure of calling alien-token-init then
  //   source /tmp/gclient_env_$UID in the current shell.
   if (!AliAnalysisGrid::CreateToken()) return NULL;
   AliAnalysisAlien *plugin = new AliAnalysisAlien();
   // Set the run mode (can be "full", "test", "offline", "submit" or "terminate")
   plugin->SetRunMode(pluginmode.Data());
   plugin->SetUser("dainesea");
   plugin->SetNtestFiles(1);
   // Set versions of used packages
   plugin->SetAPIVersion("V2.4");
   plugin->SetROOTVersion("v5-24-00");
   plugin->SetAliROOTVersion("v4-18-07-AN");
   // Declare input data to be processed.
   // Method 1: Create automatically XML collections using alien 'find' command.
   // Define production directory LFN
   plugin->SetGridDataDir("/alice/data/2009/LHC09c");
   //plugin->SetGridDataDir("/alice/cern.ch/user/s/sitta/output/000088361/");
   // Set data search pattern
   //plugin->SetDataPattern("AliESDs.root");
   plugin->SetDataPattern("ESD.tag.root");
   Int_t n=0;
   n++; plugin->AddRunNumber("000080015");
   n++; plugin->AddRunNumber("000080261");
   plugin->SetNrunsPerMaster(n);
   // Method 2: Declare existing data files (raw collections, xml collections, root file)
   // If no path mentioned data is supposed to be in the work directory (see SetGridWorkingDir())
   // XML collections added via this method can be combined with the first method if
   // the content is compatible (using or not tags)
   // e.g.: find -z -x 80015 /alice/data/2009/LHC09c/000080015/ESDs/ ESD.tag.root > 80015.xml
   //plugin->AddDataFile("79876.xml");
   //plugin->AddDataFile("80015.xml");
   //plugin->AddDataFile("80261.xml");
   //   plugin->AddDataFile("/alice/data/2008/LHC08c/000057657/raw/Run57657.Merged.RAW.tag.root");
   // Define alien work directory where all files will be copied. Relative to alien $HOME.
   plugin->SetGridWorkingDir("analysisITS");
   // Declare alien output directory. Relative to working directory.
   plugin->SetGridOutputDir("output151009"); // In this case will be $HOME/work/output
   // Declare the analysis source files names separated by blancs. To be compiled runtime
   // using ACLiC on the worker nodes.
   if(!uselibPWG1) {
     plugin->SetAnalysisSource("AliAlignmentDataFilterITS.cxx");
     plugin->SetAnalysisSource("AliTrackMatchingTPCITSCosmics.cxx");
   }
   // Declare all libraries (other than the default ones for the framework. These will be
   // loaded by the generated analysis macro. Add all extra files (task .cxx/.h) here.
   //plugin->SetAdditionalLibs("AliAlignmentDataFilterITS.h AliAlignmentDataFilterITS.cxx libProof.so libRAWDatabase.so libRAWDatarec.so libCDB.so libSTEER.so libITSbase.so libITSrec.so");
   plugin->AddIncludePath("-I. -I$ROOTSYS/include -I$ALICE_ROOT -I$ALICE_ROOT/include -I$ALICE_ROOT/ITS -I$ALICE_ROOT/TPC -I$ALICE_ROOT/CONTAINERS -I$ALICE_ROOT/STEER -I$ALICE_ROOT/TRD -I$ALICE_ROOT/macros -I$ALICE_ROOT/ANALYSIS -g");
   if(!uselibPWG1) {
     plugin->SetAdditionalLibs("AliAlignmentDataFilterITS.h AliAlignmentDataFilterITS.cxx AliTrackMatchingTPCITSCosmics.h AliTrackMatchingTPCITSCosmics.cxx libProof.so libRAWDatabase.so libRAWDatarec.so libCDB.so libSTEER.so libITSbase.so libITSrec.so");
   } else {
     plugin->SetAdditionalLibs("libGui.so libProof.so libMinuit.so libRAWDatabase.so libRAWDatarec.so libCDB.so libSTEER.so libITSbase.so libITSrec.so libTPCbase.so libTPCrec.so libTRDbase.so libTRDrec.so libPWG1.so");
   }
   // Declare the output file names separated by blancs.
   // (can be like: file.root or file.root@ALICE::Niham::File)
   plugin->SetDefaultOutputs(kTRUE);
   // Optionally define the files to be archived.
   //   plugin->SetOutputArchive("log_archive.zip:stdout,stderr@ALICE::NIHAM::File root_archive.zip:*.root@ALICE::NIHAM::File");
   plugin->SetOutputArchive("log_archive.zip:stdout,stderr");
   // Optionally set a name for the generated analysis macro (default MyAnalysis.C)
   plugin->SetAnalysisMacro("AnalysisITS.C");
   // Optionally set maximum number of input files/subjob (default 100, put 0 to ignore)
   plugin->SetSplitMaxInputFileNumber(1);
   // Optionally set number of failed jobs that will trigger killing waiting sub-jobs.
   //plugin->SetMaxInitFailed(5);
   // Optionally resubmit threshold.
   //plugin->SetMasterResubmitThreshold(90);
   // Optionally set time to live (default 30000 sec)
   //plugin->SetTTL(20000);
   // Optionally set input format (default xml-single)
   plugin->SetInputFormat("xml-single");
   // Optionally modify the name of the generated JDL (default analysis.jdl)
   plugin->SetJDLName("TaskAnalysisITS.jdl");
   // Optionally modify job price (default 1)
   //plugin->SetPrice(1);
   // Optionally modify split mode (default 'se')
   plugin->SetSplitMode("se");
   // Optionally set the preferred SE
   plugin->SetPreferedSE("ALICE::CNAF::SE");

   return plugin;
}
//-----------------------------------------------------------------------------
TChain *CreateESDChain(TString esdpath=".",Int_t ifirst=-1,Int_t ilast=-1) {

  TChain *chainESD = new TChain("esdTree");

  if(ifirst<0) {
    chainESD->Add("AliESDs.root");
  } else {
    for(Int_t i=ifirst; i<=ilast; i++) {
      TString esdfile=esdpath; esdfile+=i; esdfile.Append("/AliESDs.root");
      chainESD->Add(esdfile.Data());
    }
  }

  return chainESD;
}
<commit_msg>New task for ITS tracking check<commit_after>class AliAnalysisGrid;

void RunAnalysisITS() {
  //
  // Macro to analyze ESDs from raw data reconstruction
  // A.Dainese, andrea.dainese@pd.infn.it
  //
  //gSystem->Setenv("alien_CLOSE_SE","ALICE::CNAF::SE");

  gSystem->SetIncludePath("-I. -I$ROOTSYS/include -I$ALICE_ROOT -I$ALICE_ROOT/include -I$ALICE_ROOT/ITS -I$ALICE_ROOT/TPC -I$ALICE_ROOT/CONTAINERS -I$ALICE_ROOT/STEER -I$ALICE_ROOT/TRD -I$ALICE_ROOT/macros -I$ALICE_ROOT/ANALYSIS -g");

  //
  TString analysisMode = "local"; // "local", "grid", or "proof" (not yet)

  Long64_t nentries=1000000000000000,firstentry=0;
  Bool_t useAlienPlugin=kFALSE;
  Bool_t uselibPWG1=kTRUE;
  TString pluginmode="full";
  TString loadMacroPath="./";
  Bool_t readHLT=kFALSE;
  //

  if(analysisMode=="grid") {
    // Connect to AliEn
    TGrid::Connect("alien://");
  } else if(analysisMode=="proof") {
    // Connect to the PROOF cluster
    printf("PROOF mode not yet functional..\n");
    return;
    TProof::Open("alicecaf");
    //TProof::Reset("alicecaf");
  }

  // Load analysis libraries
  gSystem->Load("libANALYSIS.so");
  gSystem->Load("libANALYSISalice.so");
  if(uselibPWG1) gSystem->Load("libPWG1.so");

  // Create Alien plugin, if requested
  if(useAlienPlugin) {
    AliAnalysisGrid *alienHandler = CreateAlienHandler(pluginmode,uselibPWG1);
    if(!alienHandler) return;
  }

  TChain *chainESD = 0;
  if(!useAlienPlugin) {
    // Prepare input chain
    //    chainESD = CreateESDChain("/home/dainesea/alignData/RAWdata_CosmicsSum09/RecoSPD/chunk.",13,13);
    chainESD=new TChain("esdTree");
    //chainESD->Add("alien:///alice/cern.ch/user/s/sitta/output/000088361/ESDs/pass1/09000088361017.10/AliESDs.root");
    chainESD->Add("AliESDs.root");
  }

  // Create the analysis manager
  AliAnalysisManager *mgr  = new AliAnalysisManager("My Manager","My Manager");
  // Enable debug printouts
  mgr->SetDebugLevel(10);
  // Connect plug-in to the analysis manager
  if(useAlienPlugin) mgr->SetGridHandler(alienHandler);

  // Add ESD handler
  AliESDInputHandler *esdH = new AliESDInputHandler();
  if(readHLT) esdH->SetReadHLT();
  mgr->SetInputEventHandler(esdH);

  //-------------------------------------------------------------------

  //-------------------------------------------------------------------
  // Analysis tasks (wagons of the train)
  //
  TString taskName;

  if(!uselibPWG1) gROOT->LoadMacro("AliAlignmentDataFilterITS.cxx++g");
  taskName="AddTaskAlignmentDataFilterITS.C";
  taskName.Prepend(loadMacroPath.Data());
  gROOT->LoadMacro(taskName.Data());
  AliAlignmentDataFilterITS *itsTask = AddTaskAlignmentDataFilterITS();

  if(!uselibPWG1) gROOT->LoadMacro("AliTrackMatchingTPCITSCosmics.cxx++g");
  taskName="AddTaskTrackMatchingTPCITS.C";
  taskName.Prepend(loadMacroPath.Data());
  gROOT->LoadMacro(taskName.Data());
  AliTrackMatchingTPCITSCosmics *tpcitsTask = AddTaskTrackMatchingTPCITS();
  if(readHLT) tpcitsTask->SetReadHLTESD(kTRUE);
  /*
  Bool_t readMC=kTRUE;

  if(!uselibPWG1) gROOT->LoadMacro("AliAnalysisTaskVertexESD.cxx++g");
  taskName="AddTaskVertexESD.C";
  taskName.Prepend(loadMacroPath.Data());
  gROOT->LoadMacro(taskName.Data());
  AliAnalysisTaskVertexESD *vtxTask = AddTaskVertexESD(readMC);

  if(!uselibPWG1) gROOT->LoadMacro("AliAnalysisTaskITSTrackingCheck.cxx++g");
  taskName="AddTaskPerformanceITS.C";
  taskName.Prepend(loadMacroPath.Data());
  gROOT->LoadMacro(taskName.Data());
  AliAnalysisTaskITSTrackingCheck *itsTask = AddTaskPerformanceITS(readMC);

  if(readMC) {
    AliMCEventHandler  *mcH = new AliMCEventHandler();
    mgr->SetMCtruthEventHandler(mcH);
  }
  */
  //
  // Run the analysis
  //
  if(chainESD) printf("CHAIN HAS %d ENTRIES\n",(Int_t)chainESD->GetEntries());

  if(!mgr->InitAnalysis()) return;
  mgr->PrintStatus();
  if(analysisMode=="grid" && !useAlienPlugin) analysisMode="local";
  mgr->StartAnalysis(analysisMode.Data(),chainESD,nentries,firstentry);

  return;
}
//_____________________________________________________________________________
//
AliAnalysisGrid* CreateAlienHandler(TString pluginmode="test",
				    Bool_t uselibPWG1=kFALSE)
{
  // Check if user has a valid token, otherwise make one. This has limitations.
  // One can always follow the standard procedure of calling alien-token-init then
  //   source /tmp/gclient_env_$UID in the current shell.
   if (!AliAnalysisGrid::CreateToken()) return NULL;
   AliAnalysisAlien *plugin = new AliAnalysisAlien();
   // Set the run mode (can be "full", "test", "offline", "submit" or "terminate")
   plugin->SetRunMode(pluginmode.Data());
   plugin->SetUser("dainesea");
   plugin->SetNtestFiles(1);
   // Set versions of used packages
   plugin->SetAPIVersion("V2.4");
   plugin->SetROOTVersion("v5-24-00");
   plugin->SetAliROOTVersion("v4-18-07-AN");
   // Declare input data to be processed.
   // Method 1: Create automatically XML collections using alien 'find' command.
   // Define production directory LFN
   plugin->SetGridDataDir("/alice/data/2009/LHC09c");
   //plugin->SetGridDataDir("/alice/cern.ch/user/s/sitta/output/000088361/");
   // Set data search pattern
   //plugin->SetDataPattern("AliESDs.root");
   plugin->SetDataPattern("ESD.tag.root");
   Int_t n=0;
   n++; plugin->AddRunNumber("000080015");
   n++; plugin->AddRunNumber("000080261");
   plugin->SetNrunsPerMaster(n);
   // Method 2: Declare existing data files (raw collections, xml collections, root file)
   // If no path mentioned data is supposed to be in the work directory (see SetGridWorkingDir())
   // XML collections added via this method can be combined with the first method if
   // the content is compatible (using or not tags)
   // e.g.: find -z -x 80015 /alice/data/2009/LHC09c/000080015/ESDs/ ESD.tag.root > 80015.xml
   //plugin->AddDataFile("79876.xml");
   //plugin->AddDataFile("80015.xml");
   //plugin->AddDataFile("80261.xml");
   //   plugin->AddDataFile("/alice/data/2008/LHC08c/000057657/raw/Run57657.Merged.RAW.tag.root");
   // Define alien work directory where all files will be copied. Relative to alien $HOME.
   plugin->SetGridWorkingDir("analysisITS");
   // Declare alien output directory. Relative to working directory.
   plugin->SetGridOutputDir("output151009"); // In this case will be $HOME/work/output
   // Declare the analysis source files names separated by blancs. To be compiled runtime
   // using ACLiC on the worker nodes.
   if(!uselibPWG1) {
     plugin->SetAnalysisSource("AliAlignmentDataFilterITS.cxx");
     plugin->SetAnalysisSource("AliTrackMatchingTPCITSCosmics.cxx");
   }
   // Declare all libraries (other than the default ones for the framework. These will be
   // loaded by the generated analysis macro. Add all extra files (task .cxx/.h) here.
   //plugin->SetAdditionalLibs("AliAlignmentDataFilterITS.h AliAlignmentDataFilterITS.cxx libProof.so libRAWDatabase.so libRAWDatarec.so libCDB.so libSTEER.so libITSbase.so libITSrec.so");
   plugin->AddIncludePath("-I. -I$ROOTSYS/include -I$ALICE_ROOT -I$ALICE_ROOT/include -I$ALICE_ROOT/ITS -I$ALICE_ROOT/TPC -I$ALICE_ROOT/CONTAINERS -I$ALICE_ROOT/STEER -I$ALICE_ROOT/TRD -I$ALICE_ROOT/macros -I$ALICE_ROOT/ANALYSIS -g");
   if(!uselibPWG1) {
     plugin->SetAdditionalLibs("AliAlignmentDataFilterITS.h AliAlignmentDataFilterITS.cxx AliTrackMatchingTPCITSCosmics.h AliTrackMatchingTPCITSCosmics.cxx libProof.so libRAWDatabase.so libRAWDatarec.so libCDB.so libSTEER.so libITSbase.so libITSrec.so");
   } else {
     plugin->SetAdditionalLibs("libGui.so libProof.so libMinuit.so libRAWDatabase.so libRAWDatarec.so libCDB.so libSTEER.so libITSbase.so libITSrec.so libTPCbase.so libTPCrec.so libTRDbase.so libTRDrec.so libPWG1.so");
   }
   // Declare the output file names separated by blancs.
   // (can be like: file.root or file.root@ALICE::Niham::File)
   plugin->SetDefaultOutputs(kTRUE);
   // Optionally define the files to be archived.
   //   plugin->SetOutputArchive("log_archive.zip:stdout,stderr@ALICE::NIHAM::File root_archive.zip:*.root@ALICE::NIHAM::File");
   plugin->SetOutputArchive("log_archive.zip:stdout,stderr");
   // Optionally set a name for the generated analysis macro (default MyAnalysis.C)
   plugin->SetAnalysisMacro("AnalysisITS.C");
   // Optionally set maximum number of input files/subjob (default 100, put 0 to ignore)
   plugin->SetSplitMaxInputFileNumber(1);
   // Optionally set number of failed jobs that will trigger killing waiting sub-jobs.
   //plugin->SetMaxInitFailed(5);
   // Optionally resubmit threshold.
   //plugin->SetMasterResubmitThreshold(90);
   // Optionally set time to live (default 30000 sec)
   //plugin->SetTTL(20000);
   // Optionally set input format (default xml-single)
   plugin->SetInputFormat("xml-single");
   // Optionally modify the name of the generated JDL (default analysis.jdl)
   plugin->SetJDLName("TaskAnalysisITS.jdl");
   // Optionally modify job price (default 1)
   //plugin->SetPrice(1);
   // Optionally modify split mode (default 'se')
   plugin->SetSplitMode("se");
   // Optionally set the preferred SE
   plugin->SetPreferedSE("ALICE::CNAF::SE");

   return plugin;
}
//-----------------------------------------------------------------------------
TChain *CreateESDChain(TString esdpath=".",Int_t ifirst=-1,Int_t ilast=-1) {

  TChain *chainESD = new TChain("esdTree");

  if(ifirst<0) {
    chainESD->Add("AliESDs.root");
  } else {
    for(Int_t i=ifirst; i<=ilast; i++) {
      TString esdfile=esdpath; esdfile+=i; esdfile.Append("/AliESDs.root");
      chainESD->Add(esdfile.Data());
    }
  }

  return chainESD;
}
<|endoftext|>


<commit_before>/*
  ------------------
   Quadcopter Pilot
  ------------------
  author : vincent jaunet
  mail : vincent.jaunet(AT)hotmail(DOT)fr

  - Initialization of PID
  - Initialization of ESC
  - Initialization of MPU6050

  Copyright (c) <2014> <Vincent Jaunet>

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

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

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

#include <signal.h>
#include "main.h"

void stop_motors(int s){
  printf("Caught signal %d\n",s);

  uint8_t checksum=0;
  ArduSPI.writeByte('S');
  for (int iesc=0;iesc < 8; iesc++) {
    ArduSPI.writeByte((uint8_t) 0);
  }
  ArduSPI.writeByte(checksum);
  //sending end of transaction
  ArduSPI.writeByte('P');

  exit(0);
}

void Set_default_PID_config(){
  //manual initialization of PID constants
  yprRATE[YAW].set_Kpid(2.5, 0.0, 0.0);
  for (int i=1;i<3;i++){
    yprSTAB[i].set_Kpid(3.0, 0.01, 0.5);
    yprRATE[i].set_Kpid(1.8, 0.01, 0.01);
  }
}

void Blink_led(int N){
  // use gpio to blink an led on pin 0
  for(int i=0;i<N;i++){
  system("/usr/local/bin/gpio write 0 0");
  usleep(50000);
  system("/usr/local/bin/gpio write 0 1");
  usleep(50000);
  }
}

void Beep(int N){
  // use gpio to blink an led on pin 0
  for(int i=0;i<N;i++){
  system("sudo /home/pi/QUADCOPTER_V2/RPI/BEEP/beep");
  usleep(160000);
  }
}

//-------------------------------------
//--------- Main-----------------------

int main(int argc, char *argv[])
{
  printf("QuadCopter Pilot v2.0\n");
  printf("----------------------\n");
  printf("\n");

  system("rm quadpilot.log");

  //handling of CTRL+C input
  struct sigaction sigIntHandler;
  sigIntHandler.sa_handler = stop_motors;
  sigemptyset(&sigIntHandler.sa_mask);
  sigIntHandler.sa_flags = 0;
  sigaction(SIGINT, &sigIntHandler, NULL);

  //setting up IMU
  imu.set_com();
  imu.initialize();

  //setting up SPI
  ArduSPI.initialize();

  //Set PID config
  if (argc == 8) {
    printf("Setting PID constants\n");
    printf("Rate PID :\n");
    printf("    Kp = %f, Ki = %f, Kd = %f\n",
	   atof(argv[1]),atof(argv[2]),atof(argv[3]));
    printf("Rate PID :\n");
    printf("    Kp = %f, Ki = %f, Kd = %f\n",
	   atof(argv[4]),atof(argv[5]),atof(argv[6]));
      for (int i=1;i<3;i++){
	yprRATE[i].set_Kpid(atof(argv[1]),atof(argv[2]),atof(argv[3]));
	yprSTAB[i].set_Kpid(atof(argv[4]),atof(argv[5]),atof(argv[6]));
      }
    printf("Yaw Rate PID :\n");
    printf("    Kp = %f\n",atof(argv[7]));
    yprRATE[YAW].set_Kpid(atof(argv[7]), 0.0, 0.0);

  }else {
    printf("Setting default PID constants\n");
    Set_default_PID_config();
  }

  //Say I am ready
  Beep(3);
  Blink_led(10);

  //Starting Timer
  Timer.start();

  /* Sleeping everything is done via
     software interrupts  */
  while (true){

    usleep(20000);

  }//end

  return 0;
}

//
<commit_msg>New Default PID values<commit_after>/*
  ------------------
   Quadcopter Pilot
  ------------------
  author : vincent jaunet
  mail : vincent.jaunet(AT)hotmail(DOT)fr

  - Initialization of PID
  - Initialization of ESC
  - Initialization of MPU6050

  Copyright (c) <2014> <Vincent Jaunet>

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

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

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

#include <signal.h>
#include "main.h"

void stop_motors(int s){
  printf("Caught signal %d\n",s);

  uint8_t checksum=0;
  ArduSPI.writeByte('S');
  for (int iesc=0;iesc < 8; iesc++) {
    ArduSPI.writeByte((uint8_t) 0);
  }
  ArduSPI.writeByte(checksum);
  //sending end of transaction
  ArduSPI.writeByte('P');

  exit(0);
}

void Set_default_PID_config(){
  //manual initialization of PID constants
  yprRATE[YAW].set_Kpid(6.0, 0.0, 0.0);
  for (int i=1;i<3;i++){
    yprSTAB[i].set_Kpid(2.0, 0.001, 0.1);
    yprRATE[i].set_Kpid(2.0, 0.0, 0.0);
  }
}

void Blink_led(int N){
  // use gpio to blink an led on pin 0
  for(int i=0;i<N;i++){
  system("/usr/local/bin/gpio write 0 0");
  usleep(50000);
  system("/usr/local/bin/gpio write 0 1");
  usleep(50000);
  }
}

void Beep(int N){
  // use gpio to blink an led on pin 0
  for(int i=0;i<N;i++){
  system("sudo /home/pi/QUADCOPTER_V2/RPI/BEEP/beep");
  usleep(160000);
  }
}

//-------------------------------------
//--------- Main-----------------------

int main(int argc, char *argv[])
{
  printf("QuadCopter Pilot v2.0\n");
  printf("----------------------\n");
  printf("\n");

  system("rm quadpilot.log");

  //handling of CTRL+C input
  struct sigaction sigIntHandler;
  sigIntHandler.sa_handler = stop_motors;
  sigemptyset(&sigIntHandler.sa_mask);
  sigIntHandler.sa_flags = 0;
  sigaction(SIGINT, &sigIntHandler, NULL);

  //setting up IMU
  imu.set_com();
  imu.initialize();

  //setting up SPI
  ArduSPI.initialize();

  //Set PID config
  if (argc == 8) {
    printf("Setting PID constants\n");
    printf("Rate PID :\n");
    printf("    Kp = %f, Ki = %f, Kd = %f\n",
	   atof(argv[1]),atof(argv[2]),atof(argv[3]));
    printf("Rate PID :\n");
    printf("    Kp = %f, Ki = %f, Kd = %f\n",
	   atof(argv[4]),atof(argv[5]),atof(argv[6]));
      for (int i=1;i<3;i++){
	yprRATE[i].set_Kpid(atof(argv[1]),atof(argv[2]),atof(argv[3]));
	yprSTAB[i].set_Kpid(atof(argv[4]),atof(argv[5]),atof(argv[6]));
      }
    printf("Yaw Rate PID :\n");
    printf("    Kp = %f\n",atof(argv[7]));
    yprRATE[YAW].set_Kpid(atof(argv[7]), 0.0, 0.0);

  }else {
    printf("Setting default PID constants\n");
    Set_default_PID_config();
  }

  //Say I am ready
  Beep(3);
  Blink_led(10);

  //Starting Timer
  Timer.start();

  /* Sleeping everything is done via
     software interrupts  */
  while (true){

    usleep(20000);

  }//end

  return 0;
}

//
<|endoftext|>


<commit_before>// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

#include "platform/globals.h"
#if defined(HOST_OS_FUCHSIA)

#include "vm/thread_interrupter.h"

#include <zircon/process.h>
#include <zircon/status.h>
#include <zircon/syscalls.h>
#include <zircon/syscalls/debug.h>
#include <zircon/syscalls/object.h>
#include <zircon/types.h>

#include "vm/flags.h"
#include "vm/instructions.h"
#include "vm/os.h"
#include "vm/profiler.h"

namespace dart {

#ifndef PRODUCT

DECLARE_FLAG(bool, thread_interrupter);
DECLARE_FLAG(bool, trace_thread_interrupter);

// TODO(ZX-430): Currently, CPU profiling for Fuchsia is arranged very similarly
// to our Windows profiling. That is, the interrupter thread iterates over
// all threads, suspends them, samples various things, and then resumes them.
// When ZX-430 is resolved, the code below should be rewritten to use whatever
// feature is added for it.

// A scope within which a target thread is suspended. When the scope is exited,
// the thread is resumed and its handle is closed.
class ThreadSuspendScope {
 public:
  explicit ThreadSuspendScope(zx_handle_t thread_handle)
      : thread_handle_(thread_handle), suspended_(true) {
    zx_status_t status = zx_task_suspend(thread_handle);
    // If a thread is somewhere where suspend is impossible, zx_task_suspend()
    // can return ZX_ERR_NOT_SUPPORTED.
    if (status != ZX_OK) {
      if (FLAG_trace_thread_interrupter) {
        OS::PrintErr("ThreadInterrupter: zx_task_suspend failed: %s\n",
                     zx_status_get_string(status));
      }
      suspended_ = false;
    }
  }

  ~ThreadSuspendScope() {
    if (suspended_) {
      zx_status_t status = zx_task_resume(thread_handle_, 0);
      if (status != ZX_OK) {
        // If we fail to resume a thread, then it's likely the program will
        // hang. Crash instead.
        FATAL1("zx_task_resume failed: %s", zx_status_get_string(status));
      }
    }
    zx_handle_close(thread_handle_);
  }

  bool suspended() const { return suspended_; }

 private:
  zx_handle_t thread_handle_;
  bool suspended_;

  DISALLOW_ALLOCATION();
  DISALLOW_COPY_AND_ASSIGN(ThreadSuspendScope);
};

class ThreadInterrupterFuchsia : public AllStatic {
 public:
#if defined(TARGET_ARCH_X64)
  static bool GrabRegisters(zx_handle_t thread, InterruptedThreadState* state) {
    zx_x86_64_general_regs_t regs;
    size_t regset_size;
    zx_status_t status = zx_thread_read_state(
        thread, ZX_THREAD_STATE_REGSET0, &regs, sizeof(regs), &regset_size);
    if (status != ZX_OK) {
      if (FLAG_trace_thread_interrupter) {
        OS::PrintErr("ThreadInterrupter failed to get registers: %s\n",
                     zx_status_get_string(status));
      }
      return false;
    }
    state->pc = static_cast<uintptr_t>(regs.rip);
    state->fp = static_cast<uintptr_t>(regs.rbp);
    state->csp = static_cast<uintptr_t>(regs.rsp);
    state->dsp = static_cast<uintptr_t>(regs.rsp);
    return true;
  }
#elif defined(TARGET_ARCH_ARM64)
  static bool GrabRegisters(zx_handle_t thread, InterruptedThreadState* state) {
    zx_arm64_general_regs_t regs;
    uint32_t regset_size;
    zx_status_t status = zx_thread_read_state(
        thread, ZX_THREAD_STATE_REGSET0, &regs, sizeof(regs), &regset_size);
    if (status != ZX_OK) {
      if (FLAG_trace_thread_interrupter) {
        OS::PrintErr("ThreadInterrupter failed to get registers: %s\n",
                     zx_status_get_string(status));
      }
      return false;
    }
    state->pc = static_cast<uintptr_t>(regs.pc);
    state->fp = static_cast<uintptr_t>(regs.r[FPREG]);
    state->csp = static_cast<uintptr_t>(regs.sp);
    state->dsp = static_cast<uintptr_t>(regs.r[SPREG]);
    state->lr = static_cast<uintptr_t>(regs.lr);
    return true;
  }
#else
#error "Unsupported architecture"
#endif

  static void Interrupt(OSThread* os_thread) {
    ASSERT(os_thread->id() != ZX_KOID_INVALID);
    ASSERT(!OSThread::Compare(OSThread::GetCurrentThreadId(), os_thread->id()));
    zx_status_t status;

    // Get a handle on the target thread.
    const zx_koid_t target_thread_koid = os_thread->id();
    if (FLAG_trace_thread_interrupter) {
      OS::PrintErr("ThreadInterrupter: interrupting thread with koid=%ld\n",
                   target_thread_koid);
    }
    zx_handle_t target_thread_handle;
    status = zx_object_get_child(zx_process_self(), target_thread_koid,
                                 ZX_RIGHT_SAME_RIGHTS, &target_thread_handle);
    if (status != ZX_OK) {
      if (FLAG_trace_thread_interrupter) {
        OS::PrintErr("ThreadInterrupter: zx_object_get_child failed: %s\n",
                     zx_status_get_string(status));
      }
      return;
    }
    if (target_thread_handle == ZX_HANDLE_INVALID) {
      if (FLAG_trace_thread_interrupter) {
        OS::PrintErr(
            "ThreadInterrupter: zx_object_get_child gave an invalid "
            "thread handle!");
      }
      return;
    }

    // This scope suspends the thread. When we exit the scope, the thread is
    // resumed, and the thread handle is closed.
    ThreadSuspendScope tss(target_thread_handle);
    if (!tss.suspended()) {
      return;
    }

    // Check that the thread is suspended.
    status = PollThreadUntilSuspended(target_thread_handle);
    if (status != ZX_OK) {
      return;
    }

    // Grab the target thread's registers.
    InterruptedThreadState its;
    if (!GrabRegisters(target_thread_handle, &its)) {
      return;
    }
    // Currently we sample only threads that are associated
    // with an isolate. It is safe to call 'os_thread->thread()'
    // here as the thread which is being queried is suspended.
    Thread* thread = os_thread->thread();
    if (thread != NULL) {
      Profiler::SampleThread(thread, its);
    }
  }

 private:
  static const char* ThreadStateGetString(uint32_t state) {
    switch (state) {
      case ZX_THREAD_STATE_NEW:
        return "ZX_THREAD_STATE_NEW";
      case ZX_THREAD_STATE_RUNNING:
        return "ZX_THREAD_STATE_RUNNING";
      case ZX_THREAD_STATE_SUSPENDED:
        return "ZX_THREAD_STATE_SUSPENDED";
      case ZX_THREAD_STATE_BLOCKED:
        return "ZX_THREAD_STATE_BLOCKED";
      case ZX_THREAD_STATE_DYING:
        return "ZX_THREAD_STATE_DYING";
      case ZX_THREAD_STATE_DEAD:
        return "ZX_THREAD_STATE_DEAD";
      default:
        return "<Unknown>";
    }
  }

  static zx_status_t PollThreadUntilSuspended(zx_handle_t thread_handle) {
    const intptr_t kMaxPollAttempts = 10;
    intptr_t poll_tries = 0;
    while (poll_tries < kMaxPollAttempts) {
      zx_info_thread_t thread_info;
      zx_status_t status =
          zx_object_get_info(thread_handle, ZX_INFO_THREAD, &thread_info,
                             sizeof(thread_info), NULL, NULL);
      poll_tries++;
      if (status != ZX_OK) {
        if (FLAG_trace_thread_interrupter) {
          OS::PrintErr("ThreadInterrupter: zx_object_get_info failed: %s\n",
                       zx_status_get_string(status));
        }
        return status;
      }
      if (thread_info.state == ZX_THREAD_STATE_SUSPENDED) {
        // Success.
        return ZX_OK;
      }
      if (thread_info.state == ZX_THREAD_STATE_RUNNING) {
        // Poll.
        continue;
      }
      if (FLAG_trace_thread_interrupter) {
        OS::PrintErr("ThreadInterrupter: Thread is not suspended: %s\n",
                     ThreadStateGetString(thread_info.state));
      }
      return ZX_ERR_BAD_STATE;
    }
    if (FLAG_trace_thread_interrupter) {
      OS::PrintErr("ThreadInterrupter: Exceeded max suspend poll tries\n");
    }
    return ZX_ERR_BAD_STATE;
  }
};

bool ThreadInterrupter::IsDebuggerAttached() {
  return false;
}

void ThreadInterrupter::InterruptThread(OSThread* thread) {
  if (FLAG_trace_thread_interrupter) {
    OS::PrintErr("ThreadInterrupter suspending %p\n",
                 reinterpret_cast<void*>(thread->id()));
  }
  ThreadInterrupterFuchsia::Interrupt(thread);
  if (FLAG_trace_thread_interrupter) {
    OS::PrintErr("ThreadInterrupter resuming %p\n",
                 reinterpret_cast<void*>(thread->id()));
  }
}

void ThreadInterrupter::InstallSignalHandler() {
  // Nothing to do on Fuchsia.
}

void ThreadInterrupter::RemoveSignalHandler() {
  // Nothing to do on Fuchsia.
}

#endif  // !PRODUCT

}  // namespace dart

#endif  // defined(HOST_OS_FUCHSIA)
<commit_msg>Fix one more Fuchsia syscall.<commit_after>// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

#include "platform/globals.h"
#if defined(HOST_OS_FUCHSIA)

#include "vm/thread_interrupter.h"

#include <zircon/process.h>
#include <zircon/status.h>
#include <zircon/syscalls.h>
#include <zircon/syscalls/debug.h>
#include <zircon/syscalls/object.h>
#include <zircon/types.h>

#include "vm/flags.h"
#include "vm/instructions.h"
#include "vm/os.h"
#include "vm/profiler.h"

namespace dart {

#ifndef PRODUCT

DECLARE_FLAG(bool, thread_interrupter);
DECLARE_FLAG(bool, trace_thread_interrupter);

// TODO(ZX-430): Currently, CPU profiling for Fuchsia is arranged very similarly
// to our Windows profiling. That is, the interrupter thread iterates over
// all threads, suspends them, samples various things, and then resumes them.
// When ZX-430 is resolved, the code below should be rewritten to use whatever
// feature is added for it.

// A scope within which a target thread is suspended. When the scope is exited,
// the thread is resumed and its handle is closed.
class ThreadSuspendScope {
 public:
  explicit ThreadSuspendScope(zx_handle_t thread_handle)
      : thread_handle_(thread_handle), suspended_(true) {
    zx_status_t status = zx_task_suspend(thread_handle);
    // If a thread is somewhere where suspend is impossible, zx_task_suspend()
    // can return ZX_ERR_NOT_SUPPORTED.
    if (status != ZX_OK) {
      if (FLAG_trace_thread_interrupter) {
        OS::PrintErr("ThreadInterrupter: zx_task_suspend failed: %s\n",
                     zx_status_get_string(status));
      }
      suspended_ = false;
    }
  }

  ~ThreadSuspendScope() {
    if (suspended_) {
      zx_status_t status = zx_task_resume(thread_handle_, 0);
      if (status != ZX_OK) {
        // If we fail to resume a thread, then it's likely the program will
        // hang. Crash instead.
        FATAL1("zx_task_resume failed: %s", zx_status_get_string(status));
      }
    }
    zx_handle_close(thread_handle_);
  }

  bool suspended() const { return suspended_; }

 private:
  zx_handle_t thread_handle_;
  bool suspended_;

  DISALLOW_ALLOCATION();
  DISALLOW_COPY_AND_ASSIGN(ThreadSuspendScope);
};

class ThreadInterrupterFuchsia : public AllStatic {
 public:
#if defined(TARGET_ARCH_X64)
  static bool GrabRegisters(zx_handle_t thread, InterruptedThreadState* state) {
    zx_x86_64_general_regs_t regs;
    size_t regset_size;
    zx_status_t status = zx_thread_read_state(
        thread, ZX_THREAD_STATE_REGSET0, &regs, sizeof(regs), &regset_size);
    if (status != ZX_OK) {
      if (FLAG_trace_thread_interrupter) {
        OS::PrintErr("ThreadInterrupter failed to get registers: %s\n",
                     zx_status_get_string(status));
      }
      return false;
    }
    state->pc = static_cast<uintptr_t>(regs.rip);
    state->fp = static_cast<uintptr_t>(regs.rbp);
    state->csp = static_cast<uintptr_t>(regs.rsp);
    state->dsp = static_cast<uintptr_t>(regs.rsp);
    return true;
  }
#elif defined(TARGET_ARCH_ARM64)
  static bool GrabRegisters(zx_handle_t thread, InterruptedThreadState* state) {
    zx_arm64_general_regs_t regs;
    size_t regset_size;
    zx_status_t status = zx_thread_read_state(
        thread, ZX_THREAD_STATE_REGSET0, &regs, sizeof(regs), &regset_size);
    if (status != ZX_OK) {
      if (FLAG_trace_thread_interrupter) {
        OS::PrintErr("ThreadInterrupter failed to get registers: %s\n",
                     zx_status_get_string(status));
      }
      return false;
    }
    state->pc = static_cast<uintptr_t>(regs.pc);
    state->fp = static_cast<uintptr_t>(regs.r[FPREG]);
    state->csp = static_cast<uintptr_t>(regs.sp);
    state->dsp = static_cast<uintptr_t>(regs.r[SPREG]);
    state->lr = static_cast<uintptr_t>(regs.lr);
    return true;
  }
#else
#error "Unsupported architecture"
#endif

  static void Interrupt(OSThread* os_thread) {
    ASSERT(os_thread->id() != ZX_KOID_INVALID);
    ASSERT(!OSThread::Compare(OSThread::GetCurrentThreadId(), os_thread->id()));
    zx_status_t status;

    // Get a handle on the target thread.
    const zx_koid_t target_thread_koid = os_thread->id();
    if (FLAG_trace_thread_interrupter) {
      OS::PrintErr("ThreadInterrupter: interrupting thread with koid=%ld\n",
                   target_thread_koid);
    }
    zx_handle_t target_thread_handle;
    status = zx_object_get_child(zx_process_self(), target_thread_koid,
                                 ZX_RIGHT_SAME_RIGHTS, &target_thread_handle);
    if (status != ZX_OK) {
      if (FLAG_trace_thread_interrupter) {
        OS::PrintErr("ThreadInterrupter: zx_object_get_child failed: %s\n",
                     zx_status_get_string(status));
      }
      return;
    }
    if (target_thread_handle == ZX_HANDLE_INVALID) {
      if (FLAG_trace_thread_interrupter) {
        OS::PrintErr(
            "ThreadInterrupter: zx_object_get_child gave an invalid "
            "thread handle!");
      }
      return;
    }

    // This scope suspends the thread. When we exit the scope, the thread is
    // resumed, and the thread handle is closed.
    ThreadSuspendScope tss(target_thread_handle);
    if (!tss.suspended()) {
      return;
    }

    // Check that the thread is suspended.
    status = PollThreadUntilSuspended(target_thread_handle);
    if (status != ZX_OK) {
      return;
    }

    // Grab the target thread's registers.
    InterruptedThreadState its;
    if (!GrabRegisters(target_thread_handle, &its)) {
      return;
    }
    // Currently we sample only threads that are associated
    // with an isolate. It is safe to call 'os_thread->thread()'
    // here as the thread which is being queried is suspended.
    Thread* thread = os_thread->thread();
    if (thread != NULL) {
      Profiler::SampleThread(thread, its);
    }
  }

 private:
  static const char* ThreadStateGetString(uint32_t state) {
    switch (state) {
      case ZX_THREAD_STATE_NEW:
        return "ZX_THREAD_STATE_NEW";
      case ZX_THREAD_STATE_RUNNING:
        return "ZX_THREAD_STATE_RUNNING";
      case ZX_THREAD_STATE_SUSPENDED:
        return "ZX_THREAD_STATE_SUSPENDED";
      case ZX_THREAD_STATE_BLOCKED:
        return "ZX_THREAD_STATE_BLOCKED";
      case ZX_THREAD_STATE_DYING:
        return "ZX_THREAD_STATE_DYING";
      case ZX_THREAD_STATE_DEAD:
        return "ZX_THREAD_STATE_DEAD";
      default:
        return "<Unknown>";
    }
  }

  static zx_status_t PollThreadUntilSuspended(zx_handle_t thread_handle) {
    const intptr_t kMaxPollAttempts = 10;
    intptr_t poll_tries = 0;
    while (poll_tries < kMaxPollAttempts) {
      zx_info_thread_t thread_info;
      zx_status_t status =
          zx_object_get_info(thread_handle, ZX_INFO_THREAD, &thread_info,
                             sizeof(thread_info), NULL, NULL);
      poll_tries++;
      if (status != ZX_OK) {
        if (FLAG_trace_thread_interrupter) {
          OS::PrintErr("ThreadInterrupter: zx_object_get_info failed: %s\n",
                       zx_status_get_string(status));
        }
        return status;
      }
      if (thread_info.state == ZX_THREAD_STATE_SUSPENDED) {
        // Success.
        return ZX_OK;
      }
      if (thread_info.state == ZX_THREAD_STATE_RUNNING) {
        // Poll.
        continue;
      }
      if (FLAG_trace_thread_interrupter) {
        OS::PrintErr("ThreadInterrupter: Thread is not suspended: %s\n",
                     ThreadStateGetString(thread_info.state));
      }
      return ZX_ERR_BAD_STATE;
    }
    if (FLAG_trace_thread_interrupter) {
      OS::PrintErr("ThreadInterrupter: Exceeded max suspend poll tries\n");
    }
    return ZX_ERR_BAD_STATE;
  }
};

bool ThreadInterrupter::IsDebuggerAttached() {
  return false;
}

void ThreadInterrupter::InterruptThread(OSThread* thread) {
  if (FLAG_trace_thread_interrupter) {
    OS::PrintErr("ThreadInterrupter suspending %p\n",
                 reinterpret_cast<void*>(thread->id()));
  }
  ThreadInterrupterFuchsia::Interrupt(thread);
  if (FLAG_trace_thread_interrupter) {
    OS::PrintErr("ThreadInterrupter resuming %p\n",
                 reinterpret_cast<void*>(thread->id()));
  }
}

void ThreadInterrupter::InstallSignalHandler() {
  // Nothing to do on Fuchsia.
}

void ThreadInterrupter::RemoveSignalHandler() {
  // Nothing to do on Fuchsia.
}

#endif  // !PRODUCT

}  // namespace dart

#endif  // defined(HOST_OS_FUCHSIA)
<|endoftext|>


<commit_before>/****************************************************************************

 This file is part of the GLC-lib library.
 Copyright (C) 2005-2008 Laurent Ribon (laumaya@users.sourceforge.net)
 Version 1.1.0, packaged on March, 2009.

 http://glc-lib.sourceforge.net

 GLC-lib is free software; you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
 the Free Software Foundation; either version 2 of the License, or
 (at your option) any later version.

 GLC-lib is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU General Public License for more details.

 You should have received a copy of the GNU General Public License
 along with GLC-lib; if not, write to the Free Software
 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA

*****************************************************************************/

//! \file glc_instance.cpp implementation of the GLC_Instance class.

#include "glc_instance.h"
#include "glc_selectionmaterial.h"
#include "glc_state.h"

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

// Default constructor
GLC_Instance::GLC_Instance()
: GLC_Object()
, m_pGeom(NULL)
, m_pBoundingBox(NULL)
, m_pNumberOfInstance(new int(1))
, m_MatPos()
, m_IsBoundingBoxValid(false)
, m_IsSelected(false)
, m_PolyFace(GL_FRONT_AND_BACK)
, m_PolyMode(GL_FILL)
, m_IsVisible(true)
{
	// Encode Color Id
	encodeIdInRGBA();

	//qDebug() << "GLC_Instance::GLC_Instance null instance ID = " << m_Uid;
	//qDebug() << "Number of instance" << (*m_pNumberOfInstance);
}

// Contruct instance with a geometry
GLC_Instance::GLC_Instance(GLC_VboGeom* pGeom)
: GLC_Object()
, m_pGeom(pGeom)
, m_pBoundingBox(NULL)
, m_pNumberOfInstance(new int(1))
, m_MatPos()
, m_IsBoundingBoxValid(false)
, m_IsSelected(false)
, m_PolyFace(GL_FRONT_AND_BACK)
, m_PolyMode(GL_FILL)
, m_IsVisible(true)
{
	// Encode Color Id
	encodeIdInRGBA();

	setName(pGeom->name());

	//qDebug() << "GLC_Instance::GLC_Instance ID = " << m_Uid;
	//qDebug() << "Number of instance" << (*m_pNumberOfInstance);
}

// Copy constructor
GLC_Instance::GLC_Instance(const GLC_Instance& inputNode)
: GLC_Object(inputNode)
, m_pGeom(inputNode.m_pGeom)
, m_pBoundingBox(NULL)
, m_pNumberOfInstance(inputNode.m_pNumberOfInstance)
, m_MatPos(inputNode.m_MatPos)
, m_IsBoundingBoxValid(inputNode.m_IsBoundingBoxValid)
, m_IsSelected(inputNode.m_IsSelected)
, m_PolyFace(inputNode.m_PolyFace)
, m_PolyMode(inputNode.m_PolyMode)
, m_IsVisible(inputNode.m_IsVisible)

{
	// Encode Color Id
	encodeIdInRGBA();

	if (NULL != inputNode.m_pBoundingBox)
	{
		m_pBoundingBox= new GLC_BoundingBox(*inputNode.m_pBoundingBox);
	}
	// Increment the number of instance
	++(*m_pNumberOfInstance);
	//qDebug() << "GLC_Instance::GLC_Instance CopyConstructor ID = " << m_Uid;
	//qDebug() << "Number of instance" << (*m_pNumberOfInstance);
}

// Assignement operator
GLC_Instance& GLC_Instance::operator=(const GLC_Instance& inputNode)
{
	if (this != &inputNode)
	{
		clear();
		m_Uid= inputNode.m_Uid;
		// Encode Color Id
		encodeIdInRGBA();

		m_Name= inputNode.m_Name;

		m_pGeom= inputNode.m_pGeom;
		if (NULL != inputNode.m_pBoundingBox)
		{
			m_pBoundingBox= new GLC_BoundingBox(*inputNode.m_pBoundingBox);
		}
		m_pNumberOfInstance= inputNode.m_pNumberOfInstance;
		++(*m_pNumberOfInstance);
		m_MatPos= inputNode.m_MatPos;
		m_IsBoundingBoxValid= inputNode.m_IsBoundingBoxValid;
		m_IsSelected= inputNode.m_IsSelected;
		m_PolyFace= inputNode.m_PolyFace;
		m_PolyMode= inputNode.m_PolyMode;
		m_IsVisible= inputNode.m_IsVisible;

		//qDebug() << "GLC_Instance::operator= :ID = " << m_Uid;
		//qDebug() << "Number of instance" << (*m_pNumberOfInstance);
	}

	return *this;
}

// Destructor
GLC_Instance::~GLC_Instance()
{
	clear();
}

//////////////////////////////////////////////////////////////////////
// Get Functions
//////////////////////////////////////////////////////////////////////

// Get the bounding box
GLC_BoundingBox GLC_Instance::getBoundingBox(void)
{
	if (getBoundingBoxValidity())
	{
		return *m_pBoundingBox;
	}
	else if (m_pGeom != NULL)
	{
		computeBoundingBox();
		if (m_pBoundingBox != NULL)
		{
			m_IsBoundingBoxValid= true;
			return *m_pBoundingBox;
		}
	}

	GLC_BoundingBox nullBoundingBox;
	return nullBoundingBox;
}

// Get the validity of the Bounding Box
const bool GLC_Instance::getBoundingBoxValidity(void) const
{
	if ((m_pGeom != NULL) && (m_pBoundingBox != NULL))
	{
		return m_pGeom->boundingBoxIsValid() and m_IsBoundingBoxValid;
	}
	else return false;
}

// Clone the instance
GLC_Instance GLC_Instance::clone() const
{
	GLC_Instance cloneInstance;
	cloneInstance.m_pGeom= m_pGeom->clone();
	if (NULL != m_pBoundingBox)
	{
		cloneInstance.m_pBoundingBox= new GLC_BoundingBox(*m_pBoundingBox);
	}

	cloneInstance.m_MatPos= m_MatPos;
	cloneInstance.m_IsBoundingBoxValid= m_IsBoundingBoxValid;
	cloneInstance.m_IsSelected= m_IsSelected;
	cloneInstance.m_PolyFace= m_PolyFace;
	cloneInstance.m_PolyMode= m_PolyMode;
	cloneInstance.m_IsVisible= m_IsVisible;
	return cloneInstance;
}

// Instanciate the instance
GLC_Instance GLC_Instance::instanciate()
{
	GLC_Instance instance(*this);
	instance.m_Uid= glc::GLC_GenID();
	// Encode Color Id
	encodeIdInRGBA();

	return instance;
}

// Return the GLC_uint decoded ID from RGBA encoded ID
GLC_uint GLC_Instance::decodeRgbId(const GLubyte* pcolorId)
{
	GLC_uint returnId= 0;
	returnId|= (GLC_uint)pcolorId[0] << (0 * 8);
	returnId|= (GLC_uint)pcolorId[1] << (1 * 8);
	returnId|= (GLC_uint)pcolorId[2] << (2 * 8);
	// Only get first 24 bits
	//returnId|= (GLC_uint)pcolorId[3] << (3 * 8);

	return returnId;
}

//////////////////////////////////////////////////////////////////////
// Set Functions
//////////////////////////////////////////////////////////////////////

// Set the instance Geometry
bool GLC_Instance::setGeometry(GLC_VboGeom* pGeom)
{
		if (NULL == m_pGeom) return false;
		else
		{
			m_pGeom= pGeom;
			return true;
		}
}

// Instance translation
GLC_Instance& GLC_Instance::translate(double Tx, double Ty, double Tz)
{
	multMatrix(GLC_Matrix4x4(Tx, Ty, Tz));

	return *this;
}

// Move instance with a 4x4Matrix
GLC_Instance& GLC_Instance::multMatrix(const GLC_Matrix4x4 &MultMat)
{
	m_MatPos= MultMat * m_MatPos;
	m_IsBoundingBoxValid= false;

	return *this;
}

// Replace the instance Matrix
GLC_Instance& GLC_Instance::setMatrix(const GLC_Matrix4x4 &SetMat)
{
	m_MatPos= SetMat;
	m_IsBoundingBoxValid= false;

	return *this;
}

// Reset the instance Matrix
GLC_Instance& GLC_Instance::resetMatrix(void)
{
	m_MatPos.setToIdentity();
	m_IsBoundingBoxValid= false;

	return *this;
}

// Polygon's display style
void GLC_Instance::setPolygonMode(GLenum Face, GLenum Mode)
{
	// Change the polygon mode only if there is a change
	if ((m_PolyFace != Face) || (m_PolyMode != Mode))
	{
		m_PolyFace= Face;
		m_PolyMode= Mode;
	}
}

//////////////////////////////////////////////////////////////////////
// OpenGL Functions
//////////////////////////////////////////////////////////////////////

// Display the instance
void GLC_Instance::glExecute(bool transparent)
{
	if (NULL == m_pGeom) return;

	// Object ID for selection purpose
	//glLoadName(id());

	// Save current OpenGL Matrix
	glPushMatrix();
	glVisProperties();
	if(GLC_State::isInSelectionMode())
	{
		// D'ont use Alpha component
		glColor3ubv(m_colorId);
	}
	m_pGeom->glExecute(m_IsSelected, transparent);
	// Restore OpenGL Matrix
	glPopMatrix();
}

// Set instance visualisation properties
void GLC_Instance::glVisProperties()
{
	// Polygons display mode
	glPolygonMode(m_PolyFace, m_PolyMode);
	// Change the current matrix
	glMultMatrixd(m_MatPos.data());

}

//////////////////////////////////////////////////////////////////////
// private services functions
//////////////////////////////////////////////////////////////////////

// compute the instance bounding box
// m_pGeom should be not null
void GLC_Instance::computeBoundingBox(void)
{
	if (m_pBoundingBox != NULL)
	{
		delete m_pBoundingBox;
		m_pBoundingBox= NULL;
	}

	m_pBoundingBox= new GLC_BoundingBox(m_pGeom->boundingBox());
	m_pBoundingBox->transform(m_MatPos);
}

// Clear current instance
void GLC_Instance::clear()
{
	Q_ASSERT(m_pNumberOfInstance != NULL);

	if ((--(*m_pNumberOfInstance)) == 0)
	{
		// this is the last instance, delete the geometry
		if (m_pGeom != NULL)
		{
			delete m_pGeom;
			m_pGeom= NULL;
		}
		// delete instance counter
		//qDebug() << "GLC_Instance::clear ID = " << m_Uid;
		//qDebug() << "- Number of instance" << (*m_pNumberOfInstance);
		delete m_pNumberOfInstance;
		m_pNumberOfInstance= NULL;

	}
	else
	{
		//qDebug() << "GLC_Instance::clear ID = " << m_Uid;
		//qDebug() << " - Number of instance" << (*m_pNumberOfInstance);
	}

	if (m_pBoundingBox != NULL)
	{
		delete m_pBoundingBox;
		m_pBoundingBox= NULL;
	}

	// invalidate the bounding box
	m_IsBoundingBoxValid= false;

}

//! Encode Id to RGBA color
void GLC_Instance::encodeIdInRGBA()
{
	m_colorId[0]= static_cast<GLubyte>((m_Uid >> (0 * 8)) & 0xFF);
	m_colorId[1]= static_cast<GLubyte>((m_Uid >> (1 * 8)) & 0xFF);
	m_colorId[2]= static_cast<GLubyte>((m_Uid >> (2 * 8)) & 0xFF);
	m_colorId[3]= static_cast<GLubyte>((m_Uid >> (3 * 8)) & 0xFF);
}

<commit_msg>Minor changes to avoid compilation warning.<commit_after>/****************************************************************************

 This file is part of the GLC-lib library.
 Copyright (C) 2005-2008 Laurent Ribon (laumaya@users.sourceforge.net)
 Version 1.1.0, packaged on March, 2009.

 http://glc-lib.sourceforge.net

 GLC-lib is free software; you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
 the Free Software Foundation; either version 2 of the License, or
 (at your option) any later version.

 GLC-lib is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU General Public License for more details.

 You should have received a copy of the GNU General Public License
 along with GLC-lib; if not, write to the Free Software
 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA

*****************************************************************************/

//! \file glc_instance.cpp implementation of the GLC_Instance class.

#include "glc_instance.h"
#include "glc_selectionmaterial.h"
#include "glc_state.h"

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

// Default constructor
GLC_Instance::GLC_Instance()
: GLC_Object()
, m_pGeom(NULL)
, m_pBoundingBox(NULL)
, m_pNumberOfInstance(new int(1))
, m_MatPos()
, m_IsBoundingBoxValid(false)
, m_IsSelected(false)
, m_PolyFace(GL_FRONT_AND_BACK)
, m_PolyMode(GL_FILL)
, m_IsVisible(true)
{
	// Encode Color Id
	encodeIdInRGBA();

	//qDebug() << "GLC_Instance::GLC_Instance null instance ID = " << m_Uid;
	//qDebug() << "Number of instance" << (*m_pNumberOfInstance);
}

// Contruct instance with a geometry
GLC_Instance::GLC_Instance(GLC_VboGeom* pGeom)
: GLC_Object()
, m_pGeom(pGeom)
, m_pBoundingBox(NULL)
, m_pNumberOfInstance(new int(1))
, m_MatPos()
, m_IsBoundingBoxValid(false)
, m_IsSelected(false)
, m_PolyFace(GL_FRONT_AND_BACK)
, m_PolyMode(GL_FILL)
, m_IsVisible(true)
{
	// Encode Color Id
	encodeIdInRGBA();

	setName(pGeom->name());

	//qDebug() << "GLC_Instance::GLC_Instance ID = " << m_Uid;
	//qDebug() << "Number of instance" << (*m_pNumberOfInstance);
}

// Copy constructor
GLC_Instance::GLC_Instance(const GLC_Instance& inputNode)
: GLC_Object(inputNode)
, m_pGeom(inputNode.m_pGeom)
, m_pBoundingBox(NULL)
, m_pNumberOfInstance(inputNode.m_pNumberOfInstance)
, m_MatPos(inputNode.m_MatPos)
, m_IsBoundingBoxValid(inputNode.m_IsBoundingBoxValid)
, m_IsSelected(inputNode.m_IsSelected)
, m_PolyFace(inputNode.m_PolyFace)
, m_PolyMode(inputNode.m_PolyMode)
, m_IsVisible(inputNode.m_IsVisible)

{
	// Encode Color Id
	encodeIdInRGBA();

	if (NULL != inputNode.m_pBoundingBox)
	{
		m_pBoundingBox= new GLC_BoundingBox(*inputNode.m_pBoundingBox);
	}
	// Increment the number of instance
	++(*m_pNumberOfInstance);
	//qDebug() << "GLC_Instance::GLC_Instance CopyConstructor ID = " << m_Uid;
	//qDebug() << "Number of instance" << (*m_pNumberOfInstance);
}

// Assignement operator
GLC_Instance& GLC_Instance::operator=(const GLC_Instance& inputNode)
{
	if (this != &inputNode)
	{
		clear();
		m_Uid= inputNode.m_Uid;
		// Encode Color Id
		encodeIdInRGBA();

		m_Name= inputNode.m_Name;

		m_pGeom= inputNode.m_pGeom;
		if (NULL != inputNode.m_pBoundingBox)
		{
			m_pBoundingBox= new GLC_BoundingBox(*inputNode.m_pBoundingBox);
		}
		m_pNumberOfInstance= inputNode.m_pNumberOfInstance;
		++(*m_pNumberOfInstance);
		m_MatPos= inputNode.m_MatPos;
		m_IsBoundingBoxValid= inputNode.m_IsBoundingBoxValid;
		m_IsSelected= inputNode.m_IsSelected;
		m_PolyFace= inputNode.m_PolyFace;
		m_PolyMode= inputNode.m_PolyMode;
		m_IsVisible= inputNode.m_IsVisible;

		//qDebug() << "GLC_Instance::operator= :ID = " << m_Uid;
		//qDebug() << "Number of instance" << (*m_pNumberOfInstance);
	}

	return *this;
}

// Destructor
GLC_Instance::~GLC_Instance()
{
	clear();
}

//////////////////////////////////////////////////////////////////////
// Get Functions
//////////////////////////////////////////////////////////////////////

// Get the bounding box
GLC_BoundingBox GLC_Instance::getBoundingBox(void)
{
	GLC_BoundingBox resultBox;
	if (getBoundingBoxValidity())
	{
		resultBox= *m_pBoundingBox;
	}
	else if (m_pGeom != NULL)
	{
		computeBoundingBox();
		m_IsBoundingBoxValid= true;
		resultBox= *m_pBoundingBox;
	}

	return resultBox;
}

// Get the validity of the Bounding Box
const bool GLC_Instance::getBoundingBoxValidity(void) const
{
	bool result;
	if ((m_pGeom != NULL) && (m_pBoundingBox != NULL))
	{
		result= m_pGeom->boundingBoxIsValid() and m_IsBoundingBoxValid;
	}
	else result= false;

	return result;
}

// Clone the instance
GLC_Instance GLC_Instance::clone() const
{
	GLC_Instance cloneInstance;
	cloneInstance.m_pGeom= m_pGeom->clone();
	if (NULL != m_pBoundingBox)
	{
		cloneInstance.m_pBoundingBox= new GLC_BoundingBox(*m_pBoundingBox);
	}

	cloneInstance.m_MatPos= m_MatPos;
	cloneInstance.m_IsBoundingBoxValid= m_IsBoundingBoxValid;
	cloneInstance.m_IsSelected= m_IsSelected;
	cloneInstance.m_PolyFace= m_PolyFace;
	cloneInstance.m_PolyMode= m_PolyMode;
	cloneInstance.m_IsVisible= m_IsVisible;
	return cloneInstance;
}

// Instanciate the instance
GLC_Instance GLC_Instance::instanciate()
{
	GLC_Instance instance(*this);
	instance.m_Uid= glc::GLC_GenID();
	// Encode Color Id
	encodeIdInRGBA();

	return instance;
}

// Return the GLC_uint decoded ID from RGBA encoded ID
GLC_uint GLC_Instance::decodeRgbId(const GLubyte* pcolorId)
{
	GLC_uint returnId= 0;
	returnId|= (GLC_uint)pcolorId[0] << (0 * 8);
	returnId|= (GLC_uint)pcolorId[1] << (1 * 8);
	returnId|= (GLC_uint)pcolorId[2] << (2 * 8);
	// Only get first 24 bits
	//returnId|= (GLC_uint)pcolorId[3] << (3 * 8);

	return returnId;
}

//////////////////////////////////////////////////////////////////////
// Set Functions
//////////////////////////////////////////////////////////////////////

// Set the instance Geometry
bool GLC_Instance::setGeometry(GLC_VboGeom* pGeom)
{
		if (NULL == m_pGeom) return false;
		else
		{
			m_pGeom= pGeom;
			return true;
		}
}

// Instance translation
GLC_Instance& GLC_Instance::translate(double Tx, double Ty, double Tz)
{
	multMatrix(GLC_Matrix4x4(Tx, Ty, Tz));

	return *this;
}

// Move instance with a 4x4Matrix
GLC_Instance& GLC_Instance::multMatrix(const GLC_Matrix4x4 &MultMat)
{
	m_MatPos= MultMat * m_MatPos;
	m_IsBoundingBoxValid= false;

	return *this;
}

// Replace the instance Matrix
GLC_Instance& GLC_Instance::setMatrix(const GLC_Matrix4x4 &SetMat)
{
	m_MatPos= SetMat;
	m_IsBoundingBoxValid= false;

	return *this;
}

// Reset the instance Matrix
GLC_Instance& GLC_Instance::resetMatrix(void)
{
	m_MatPos.setToIdentity();
	m_IsBoundingBoxValid= false;

	return *this;
}

// Polygon's display style
void GLC_Instance::setPolygonMode(GLenum Face, GLenum Mode)
{
	// Change the polygon mode only if there is a change
	if ((m_PolyFace != Face) || (m_PolyMode != Mode))
	{
		m_PolyFace= Face;
		m_PolyMode= Mode;
	}
}

//////////////////////////////////////////////////////////////////////
// OpenGL Functions
//////////////////////////////////////////////////////////////////////

// Display the instance
void GLC_Instance::glExecute(bool transparent)
{
	if (NULL == m_pGeom) return;

	// Object ID for selection purpose
	//glLoadName(id());

	// Save current OpenGL Matrix
	glPushMatrix();
	glVisProperties();
	if(GLC_State::isInSelectionMode())
	{
		// D'ont use Alpha component
		glColor3ubv(m_colorId);
	}
	m_pGeom->glExecute(m_IsSelected, transparent);
	// Restore OpenGL Matrix
	glPopMatrix();
}

// Set instance visualisation properties
void GLC_Instance::glVisProperties()
{
	// Polygons display mode
	glPolygonMode(m_PolyFace, m_PolyMode);
	// Change the current matrix
	glMultMatrixd(m_MatPos.data());

}

//////////////////////////////////////////////////////////////////////
// private services functions
//////////////////////////////////////////////////////////////////////

// compute the instance bounding box
// m_pGeom should be not null
void GLC_Instance::computeBoundingBox(void)
{
	if (m_pBoundingBox != NULL)
	{
		delete m_pBoundingBox;
		m_pBoundingBox= NULL;
	}

	m_pBoundingBox= new GLC_BoundingBox(m_pGeom->boundingBox());
	m_pBoundingBox->transform(m_MatPos);
}

// Clear current instance
void GLC_Instance::clear()
{
	Q_ASSERT(m_pNumberOfInstance != NULL);

	if ((--(*m_pNumberOfInstance)) == 0)
	{
		// this is the last instance, delete the geometry
		if (m_pGeom != NULL)
		{
			delete m_pGeom;
			m_pGeom= NULL;
		}
		// delete instance counter
		//qDebug() << "GLC_Instance::clear ID = " << m_Uid;
		//qDebug() << "- Number of instance" << (*m_pNumberOfInstance);
		delete m_pNumberOfInstance;
		m_pNumberOfInstance= NULL;

	}
	else
	{
		//qDebug() << "GLC_Instance::clear ID = " << m_Uid;
		//qDebug() << " - Number of instance" << (*m_pNumberOfInstance);
	}

	if (m_pBoundingBox != NULL)
	{
		delete m_pBoundingBox;
		m_pBoundingBox= NULL;
	}

	// invalidate the bounding box
	m_IsBoundingBoxValid= false;

}

//! Encode Id to RGBA color
void GLC_Instance::encodeIdInRGBA()
{
	m_colorId[0]= static_cast<GLubyte>((m_Uid >> (0 * 8)) & 0xFF);
	m_colorId[1]= static_cast<GLubyte>((m_Uid >> (1 * 8)) & 0xFF);
	m_colorId[2]= static_cast<GLubyte>((m_Uid >> (2 * 8)) & 0xFF);
	m_colorId[3]= static_cast<GLubyte>((m_Uid >> (3 * 8)) & 0xFF);
}

<|endoftext|>


<commit_before>/*
    This file is part of Akregator.

    Copyright (C) 2007 Frank Osterfeld <frank.osterfeld at kdemail.net>

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    GNU General Public License for more details.

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

    As a special exception, permission is given to link this program
    with any edition of Qt, and distribute the resulting executable,
    without including the source code for Qt in the source distribution.
*/

#include "selectioncontroller.h"

#include "actionmanager.h"
#include "article.h"
#include "articlemodel.h"
#include "feedlist.h"
#include "subscriptionlistmodel.h"
#include "treenode.h"

#include <KRandom>

#include <QAbstractItemView>
#include <QItemSelectionModel>
#include <QMenu>
#include <QTimer>

namespace {
    static Akregator::Article articleForIndex( const QModelIndex& index, Akregator::FeedList* feedList )
    {
        if ( !index.isValid() )
            return Akregator::Article();

        const QString guid = index.data( Akregator::ArticleModel::GuidRole ).toString();
        const QString feedId = index.data( Akregator::ArticleModel::FeedIdRole ).toString();
        return feedList->findArticle( feedId, guid );
    }

    static QList<Akregator::Article> articlesForIndexes( const QModelIndexList& indexes, Akregator::FeedList* feedList )
    {
        QList<Akregator::Article> articles;
        Q_FOREACH ( const QModelIndex i, indexes )
        {
            articles.append( articleForIndex( i, feedList ) );
        }

        return articles;
    }

    static Akregator::TreeNode* subscriptionForIndex( const QModelIndex& index, Akregator::FeedList* feedList )
    {
        if ( !index.isValid() )
            return 0L;

         return feedList->findByID( index.data( Akregator::SubscriptionListModel::SubscriptionIdRole ).toInt() );
    }
} // anon namespace

Akregator::SelectionController::SelectionController( QObject* parent ) : AbstractSelectionController( parent ), m_feedList( 0 ), m_feedSelector( 0 ), m_articleLister( 0 ), m_singleDisplay( 0 ), m_subscriptionModel ( 0 ), m_folderExpansionHandler( 0 ), m_selectedSubscription( 0 )
{
    m_articleFetchTimer = new QTimer( this );
}

void Akregator::SelectionController::setFeedSelector( QAbstractItemView* feedSelector )
{
    if ( m_feedSelector )
    {
        disconnect( m_feedSelector, SIGNAL( customContextMenuRequested( QPoint ) ),
                    this, SLOT( subscriptionContextMenuRequested( QPoint ) ) );

        if ( m_feedSelector->selectionModel() )
        {
            disconnect( m_feedSelector->selectionModel(), SIGNAL( currentChanged( QModelIndex, QModelIndex ) ),
                        this, SLOT( selectedSubscriptionChanged( QModelIndex ) ) );
        }
    }
    m_feedSelector = feedSelector;

    connect( m_feedSelector, SIGNAL( customContextMenuRequested( QPoint ) ),
             this, SLOT( subscriptionContextMenuRequested( QPoint ) ) );
    setUp();
}

void Akregator::SelectionController::setArticleLister( Akregator::ArticleLister* lister )
{
    if ( m_articleLister )
    {
        disconnect( m_articleLister->articleSelectionModel(), SIGNAL( currentChanged( QModelIndex, QModelIndex ) ),
                 this, SLOT( currentArticleIndexChanged( QModelIndex ) ) );
    }

    m_articleLister = lister;

    if ( m_articleLister->itemView() )
    {
        connect( m_articleLister->itemView(), SIGNAL( doubleClicked( QModelIndex ) ), this, SLOT( articleIndexDoubleClicked( QModelIndex ) )  );
    }
}

void Akregator::SelectionController::setSingleArticleDisplay( Akregator::SingleArticleDisplay* display )
{
    m_singleDisplay = display;
}

Akregator::Article Akregator::SelectionController::currentArticle() const
{
    return ::articleForIndex( m_articleLister->articleSelectionModel()->currentIndex(), m_feedList );
}

QList<Akregator::Article> Akregator::SelectionController::selectedArticles() const
{
    return ::articlesForIndexes( m_articleLister->articleSelectionModel()->selectedIndexes(), m_feedList );
}

Akregator::TreeNode* Akregator::SelectionController::selectedSubscription() const
{
    return ::subscriptionForIndex( m_feedSelector->selectionModel()->currentIndex(), m_feedList );
}

void Akregator::SelectionController::setFeedList( Akregator::FeedList* list )
{
    m_feedList = list;
    setUp();
}

void Akregator::SelectionController::setFolderExpansionHandler( Akregator::FolderExpansionHandler* handler )
{
    m_folderExpansionHandler = handler;
    if ( !handler )
        return;
    handler->setFeedList( m_feedList );
    handler->setModel( m_subscriptionModel );
}

void Akregator::SelectionController::setUp()
{
    if ( !m_feedList || !m_feedSelector )
        return;

    //FIXME: Make sure that setUp is only run once (or that we're not connecting more than once)

    m_subscriptionModel = new SubscriptionListModel( m_feedList, this );
    if ( m_folderExpansionHandler )
    {
        m_folderExpansionHandler->setFeedList( m_feedList );
        m_folderExpansionHandler->setModel( m_subscriptionModel );
    }
    m_feedSelector->setModel( m_subscriptionModel );

    connect( m_feedSelector->selectionModel(), SIGNAL( currentChanged( QModelIndex, QModelIndex ) ),
             this, SLOT( selectedSubscriptionChanged( QModelIndex ) ) );
}

void Akregator::SelectionController::articleHeadersAvailable()
{
    m_articleLister->setArticleModel( new Akregator::ArticleModel( m_selectedSubscription ) );

    m_articleLister->setIsAggregation( m_selectedSubscription->isAggregation() );

    connect( m_articleLister->articleSelectionModel(), SIGNAL( currentChanged( QModelIndex, QModelIndex) ),
             this, SLOT( currentArticleIndexChanged( QModelIndex ) ) );
}

void Akregator::SelectionController::selectedSubscriptionChanged( const QModelIndex& index )
{
    if ( !index.isValid() )
        return;

    m_selectedSubscription = selectedSubscription();
    emit currentSubscriptionChanged( m_selectedSubscription );

    // using a timer here internally to simulate async data fetching (which is still synchronous),
    // to ensure the UI copes with async behavior later on

    if ( m_articleFetchTimer->isActive() )
        m_articleFetchTimer->stop(); // to come: kill running list job

    m_articleFetchTimer->setInterval( KRandom::random() % 400 );
    m_articleFetchTimer->setSingleShot( true );
    connect( m_articleFetchTimer, SIGNAL( timeout() ),
             this, SLOT( articleHeadersAvailable() ) );
    m_articleFetchTimer->start();

}

void Akregator::SelectionController::subscriptionContextMenuRequested( const QPoint& point )
{
    Q_ASSERT( m_feedSelector );
    const TreeNode* const node = ::subscriptionForIndex( m_feedSelector->indexAt( point ), m_feedList );
    if ( !node )
        return;

    QWidget* w = ActionManager::getInstance()->container( node->isGroup() ? "feedgroup_popup" : "feeds_popup" );
    QMenu* popup = qobject_cast<QMenu*>( w );
    if ( popup )
    {
        const QPoint globalPos = m_feedSelector->viewport()->mapToGlobal( point );
        popup->exec( globalPos );
    }
}

void Akregator::SelectionController::currentArticleIndexChanged( const QModelIndex& )
{
    const Akregator::Article article = currentArticle();
    if ( m_singleDisplay )
        m_singleDisplay->showArticle( article );
    emit currentArticleChanged( article );
}

void Akregator::SelectionController::articleIndexDoubleClicked( const QModelIndex& index )
{
    const Akregator::Article article = ::articleForIndex( index, m_feedList );
    emit articleDoubleClicked( article );
}

#include "selectioncontroller.moc"
<commit_msg>Prevent connecting more than once, second try<commit_after>/*
    This file is part of Akregator.

    Copyright (C) 2007 Frank Osterfeld <frank.osterfeld at kdemail.net>

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    GNU General Public License for more details.

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

    As a special exception, permission is given to link this program
    with any edition of Qt, and distribute the resulting executable,
    without including the source code for Qt in the source distribution.
*/

#include "selectioncontroller.h"

#include "actionmanager.h"
#include "article.h"
#include "articlemodel.h"
#include "feedlist.h"
#include "subscriptionlistmodel.h"
#include "treenode.h"

#include <KRandom>

#include <QAbstractItemView>
#include <QItemSelectionModel>
#include <QMenu>
#include <QTimer>

namespace {
    static Akregator::Article articleForIndex( const QModelIndex& index, Akregator::FeedList* feedList )
    {
        if ( !index.isValid() )
            return Akregator::Article();

        const QString guid = index.data( Akregator::ArticleModel::GuidRole ).toString();
        const QString feedId = index.data( Akregator::ArticleModel::FeedIdRole ).toString();
        return feedList->findArticle( feedId, guid );
    }

    static QList<Akregator::Article> articlesForIndexes( const QModelIndexList& indexes, Akregator::FeedList* feedList )
    {
        QList<Akregator::Article> articles;
        Q_FOREACH ( const QModelIndex i, indexes )
        {
            articles.append( articleForIndex( i, feedList ) );
        }

        return articles;
    }

    static Akregator::TreeNode* subscriptionForIndex( const QModelIndex& index, Akregator::FeedList* feedList )
    {
        if ( !index.isValid() )
            return 0L;

         return feedList->findByID( index.data( Akregator::SubscriptionListModel::SubscriptionIdRole ).toInt() );
    }
} // anon namespace

Akregator::SelectionController::SelectionController( QObject* parent ) : AbstractSelectionController( parent ), m_feedList( 0 ), m_feedSelector( 0 ), m_articleLister( 0 ), m_singleDisplay( 0 ), m_subscriptionModel ( 0 ), m_folderExpansionHandler( 0 ), m_selectedSubscription( 0 )
{
    m_articleFetchTimer = new QTimer( this );
}

void Akregator::SelectionController::setFeedSelector( QAbstractItemView* feedSelector )
{
    if ( m_feedSelector )
    {
        disconnect( m_feedSelector, SIGNAL( customContextMenuRequested( QPoint ) ),
                    this, SLOT( subscriptionContextMenuRequested( QPoint ) ) );

        if ( m_feedSelector->selectionModel() )
        {
            disconnect( m_feedSelector->selectionModel(), SIGNAL( currentChanged( QModelIndex, QModelIndex ) ),
                        this, SLOT( selectedSubscriptionChanged( QModelIndex ) ) );
        }
    }
    m_feedSelector = feedSelector;
    setUp();
}

void Akregator::SelectionController::setArticleLister( Akregator::ArticleLister* lister )
{
    if ( m_articleLister )
    {
        disconnect( m_articleLister->articleSelectionModel(), SIGNAL( currentChanged( QModelIndex, QModelIndex ) ),
                 this, SLOT( currentArticleIndexChanged( QModelIndex ) ) );
    }

    m_articleLister = lister;
    setUp();
}

void Akregator::SelectionController::setSingleArticleDisplay( Akregator::SingleArticleDisplay* display )
{
    m_singleDisplay = display;
}

Akregator::Article Akregator::SelectionController::currentArticle() const
{
    return ::articleForIndex( m_articleLister->articleSelectionModel()->currentIndex(), m_feedList );
}

QList<Akregator::Article> Akregator::SelectionController::selectedArticles() const
{
    return ::articlesForIndexes( m_articleLister->articleSelectionModel()->selectedIndexes(), m_feedList );
}

Akregator::TreeNode* Akregator::SelectionController::selectedSubscription() const
{
    return ::subscriptionForIndex( m_feedSelector->selectionModel()->currentIndex(), m_feedList );
}

void Akregator::SelectionController::setFeedList( Akregator::FeedList* list )
{
    m_feedList = list;
    setUp();
}

void Akregator::SelectionController::setFolderExpansionHandler( Akregator::FolderExpansionHandler* handler )
{
    m_folderExpansionHandler = handler;
    if ( !handler )
        return;
    handler->setFeedList( m_feedList );
    handler->setModel( m_subscriptionModel );
}

void Akregator::SelectionController::setUp()
{
    if ( !m_feedList || !m_feedSelector || !m_articleLister )
        return;

    m_subscriptionModel = new SubscriptionListModel( m_feedList, this );
    if ( m_folderExpansionHandler )
    {
        m_folderExpansionHandler->setFeedList( m_feedList );
        m_folderExpansionHandler->setModel( m_subscriptionModel );
    }
    m_feedSelector->setModel( m_subscriptionModel );

    // setUp might be called more than once, so disconnect first

    disconnect( m_feedSelector->selectionModel(), SIGNAL( currentChanged( QModelIndex, QModelIndex ) ),
             this, SLOT( selectedSubscriptionChanged( QModelIndex ) ) );
    connect( m_feedSelector->selectionModel(), SIGNAL( currentChanged( QModelIndex, QModelIndex ) ),
             this, SLOT( selectedSubscriptionChanged( QModelIndex ) ) );

    disconnect( m_feedSelector, SIGNAL( customContextMenuRequested( QPoint ) ),
             this, SLOT( subscriptionContextMenuRequested( QPoint ) ) );
    connect( m_feedSelector, SIGNAL( customContextMenuRequested( QPoint ) ),
             this, SLOT( subscriptionContextMenuRequested( QPoint ) ) );

    if ( m_articleLister->itemView() )
    {
        disconnect( m_articleLister->itemView(), SIGNAL( doubleClicked( QModelIndex ) ), this, SLOT( articleIndexDoubleClicked( QModelIndex ) )  );
        connect( m_articleLister->itemView(), SIGNAL( doubleClicked( QModelIndex ) ), this, SLOT( articleIndexDoubleClicked( QModelIndex ) )  );
    }
}

void Akregator::SelectionController::articleHeadersAvailable()
{
    m_articleLister->setArticleModel( new Akregator::ArticleModel( m_selectedSubscription ) );

    m_articleLister->setIsAggregation( m_selectedSubscription->isAggregation() );

    connect( m_articleLister->articleSelectionModel(), SIGNAL( currentChanged( QModelIndex, QModelIndex) ),
             this, SLOT( currentArticleIndexChanged( QModelIndex ) ) );
}

void Akregator::SelectionController::selectedSubscriptionChanged( const QModelIndex& index )
{
    if ( !index.isValid() )
        return;

    m_selectedSubscription = selectedSubscription();
    emit currentSubscriptionChanged( m_selectedSubscription );

    // using a timer here internally to simulate async data fetching (which is still synchronous),
    // to ensure the UI copes with async behavior later on

    if ( m_articleFetchTimer->isActive() )
        m_articleFetchTimer->stop(); // to come: kill running list job

    m_articleFetchTimer->setInterval( KRandom::random() % 400 );
    m_articleFetchTimer->setSingleShot( true );
    connect( m_articleFetchTimer, SIGNAL( timeout() ),
             this, SLOT( articleHeadersAvailable() ) );
    m_articleFetchTimer->start();

}

void Akregator::SelectionController::subscriptionContextMenuRequested( const QPoint& point )
{
    Q_ASSERT( m_feedSelector );
    const TreeNode* const node = ::subscriptionForIndex( m_feedSelector->indexAt( point ), m_feedList );
    if ( !node )
        return;

    QWidget* w = ActionManager::getInstance()->container( node->isGroup() ? "feedgroup_popup" : "feeds_popup" );
    QMenu* popup = qobject_cast<QMenu*>( w );
    if ( popup )
    {
        const QPoint globalPos = m_feedSelector->viewport()->mapToGlobal( point );
        popup->exec( globalPos );
    }
}

void Akregator::SelectionController::currentArticleIndexChanged( const QModelIndex& )
{
    const Akregator::Article article = currentArticle();
    if ( m_singleDisplay )
        m_singleDisplay->showArticle( article );
    emit currentArticleChanged( article );
}

void Akregator::SelectionController::articleIndexDoubleClicked( const QModelIndex& index )
{
    const Akregator::Article article = ::articleForIndex( index, m_feedList );
    emit articleDoubleClicked( article );
}

#include "selectioncontroller.moc"
<|endoftext|>