<commit_before>#include "fid/base_fid.h"

namespace fid {

void BaseFid::Init()
{
  // Prevent memory issues with the TF1s.
  TF1::DefaultAddToGlobalList(false);

  // Initialize the health properly.
  health_ = 100.0;

  // Resize the temp array (maybe others?)
  temp_.reserve(wf_.size());

  // Initialize the BaseFid for analysis
  LoadParams();
  CenterFid();
  CalcNoise();
  CalcMaxAmp();
  FindFidRange();
  InitHook();

  CalcFreq();

  // Flag the FID as bad if it's negative.
  if (freq_ < 0.0) {
    health_ = 0.0;
  }

  // Else calculate a health based on signal to noise.
  if (max_amp_ < noise_ * snr_thresh_) {
    health_ *= max_amp_ / (noise_ * snr_thresh_);
  }

  // And factor fid duration into health.
  if (f_wf_ - i_wf_ < wf_.size() * len_thresh_) {
    health_ *= (f_wf_ - i_wf_) / (wf_.size() * len_thresh_);
  }
}

// Load FID data from a formatted text file.
void BaseFid::LoadTextData(std::string filename)
{
  // open the file first
  std::ifstream in(filename);

  // shrink vectors
  wf_.resize(0);
  tm_.resize(0);

  double wf_temp;
  double tm_temp;

  while (in.good()) {
    in >> tm_temp >> wf_temp;
    tm_.push_back(tm_temp);
    wf_.push_back(wf_temp);
  }
}

// Load all the current parameters in the fid::params namespace.
void BaseFid::LoadParams()
{
  edge_width_ = params::edge_width;
  edge_ignore_ = params::edge_ignore;
  start_amplitude_ = params::start_amplitude;
  max_phase_jump_ = params::max_phase_jump;
  low_pass_freq_ = params::low_pass_freq;
  fft_peak_width_ = params::fft_peak_width;
  centroid_thresh_ = params::centroid_thresh;
  hyst_thresh_ = params::hyst_thresh;
  snr_thresh_ = params::snr_thresh;
  len_thresh_ = params::len_thresh;
  freq_method_ = params::freq_method;
}

void BaseFid::CenterFid()
{
  int w = edge_width_;
  double sum  = std::accumulate(wf_.begin(), wf_.begin() + w, 0.0);
  double avg = sum / w; // to pass into lambda
  mean_ = avg; // save to class

  std::for_each(wf_.begin(), wf_.end(), [avg](double& x){ x -= avg; });
}

void BaseFid::CalcNoise()
{
  // Grab a new handle to the noise window width for aesthetics.
  int i = edge_ignore_;
  int f = edge_width_ + i;

  // Find the noise level in the head and tail.
  double head = stdev(wf_.begin() + i, wf_.begin() + f);
  double tail = stdev(wf_.rbegin() + i, wf_.rbegin() + f);

  // Take the smaller of the two.
  noise_ = (tail < head) ? (tail) : (head);
}

void BaseFid::CalcMaxAmp()
{
  auto mm = std::minmax_element(wf_.begin(), wf_.end());

  if (std::abs(*mm.first) > std::abs(*mm.second)) {

    max_amp_ = std::abs(*mm.first);

  } else {

    max_amp_ = std::abs(*mm.second);
  }
}

void BaseFid::FindFidRange()
{
  // Find the starting and ending points
  double thresh = start_amplitude_ * max_amp_;
  bool checks_out = false;

  // Find the first element with magnitude larger than thresh
  auto it_1 = wf_.begin() + edge_ignore_;

  while (!checks_out) {

    // Check if the point is above threshold.
    auto it_i = std::find_if(it_1, wf_.end(),
      [thresh](double x) {
        return std::abs(x) > thresh;
    });

    // Make sure the point is not with one of the vector's end.
    if ((it_i != wf_.end()) && (it_i + 1 != wf_.end())) {

      // Check if the next point is also over threshold.
      checks_out = std::abs(*(it_i + 1)) > thresh;

      // Increase the comparison starting point.
      it_1 = it_i + 1;

      // Turn the iterator into an index
      if (checks_out) {
        i_wf_ = std::distance(wf_.begin(), it_i);
      }

    } else {

      // If we have reached the end, mark it as the last.
      i_wf_ = std::distance(wf_.begin(), wf_.end());
      break;
    }
  }

  // Find the next element with magnitude lower than thresh
  auto it_2 = std::find_if(wf_.begin() + i_wf_, wf_.end(),
      [thresh](double x) {
        return std::abs(x) < 0.8 * thresh;
  });

  checks_out = false;

  while (!checks_out) {

    // Find the range around a peak.
    auto it_i = std::find_if(it_2, wf_.end(),
      [thresh](double x) {
        return std::abs(x) > 0.8 * thresh;
    });

    auto it_f = std::find_if(it_i + 1, wf_.end(),
      [thresh](double x) {
        return std::abs(x) < 0.8 * thresh;
    });

    // Now check if the peak actually made it over threshold.
    if ((it_i != wf_.end()) && (it_f != wf_.end())) {

      auto mm = std::minmax_element(it_i, it_f);

      if ((*mm.first < -thresh) || (*mm.second > thresh)) {

        it_2 = it_f;

      } else {

        checks_out = true;
      }

      // Turn the iterator into an index
      if (checks_out) {
        f_wf_ = std::distance(wf_.begin(), it_f);
      }

    } else {

      f_wf_ = std::distance(wf_.begin(), wf_.end());
      break;
    }
  }

  // Gradients can cause a waist in the amplitude.
  // Mark the signal as bad if it didn't find signal above threshold.
  if (i_wf_ > wf_.size() * 0.95 || i_wf_ >= f_wf_) {

    health_ = 0.0;

    i_wf_ = 0;
    f_wf_ = wf_.size() * 0.01;
  }
}

// Save the interanl TGraph.
void BaseFid::SaveGraph(std::string filename, std::string title)
{
  gr_.SetTitle(title.c_str());
  gr_.Draw();
  c1_.Print(filename.c_str());
}

// Save a plot of FID waveform.
void BaseFid::SavePlot(std::string filename, std::string title)
{
  // If no title supplied give a reasonable default.
  if (title == "") {

    title = std::string("FID; time [ms]; amplitude [a.u.]");

  } else {

    // In case they didn't append x/y labels.
    title.append("; time [ms]; amplitude [a.u.]");
  }

  gr_ = TGraph(wf_.size(), &tm_[0], &wf_[0]);

  SaveGraph(filename, title);
}

// Print the time series fit from an FID.
void BaseFid::SaveTimeFit(std::string filename, std::string title)
{
  if (title == "") {

    title = std::string("Time Series Fit; time [ms]; amplitude [a.u.]");

  } else {

    // In case they didn't append x/y labels.
    title.append("; time [ms]; amplitude [a.u.]");
  }

  // Copy the current time fit graph.
  gr_ = gr_time_series_;
  SaveGraph(filename, title);
}

// Print the time series fit from an FID.
void BaseFid::SaveFreqFit(std::string filename, std::string title)
{
  if (title == "") {

    title = std::string("Frequency Series Fit; time [ms]; amplitude [a.u.]");

  } else {

    // In case they didn't append x/y labels.
    title.append("; freq [kHz]; amplitude [a.u.]");
  }

  // Copy the current time fit graph.
  gr_ = gr_freq_series_;
  SaveGraph(filename, title);
}

void BaseFid::SaveTimeRes(std::string filename, std::string title)
{
  if (title == "") {

    title = std::string("Time Series Fit Residuals; time [ms]; amplitude [a.u.]");

  } else {

    // In case they didn't append x/y labels.
    title.append("; time [ms]; amplitude [a.u.]");
  }

  // Copy the current time fit.
  gr_ = gr_time_series_;

  // Set the points
  for (uint i = 0; i < res_.size(); ++i){
    static double x, y;

    gr_.GetPoint(i, x, y);
    gr_.SetPoint(i, x, res_[i]);
  }

  SaveGraph(filename, title);
}

void BaseFid::SaveFreqRes(std::string filename, std::string title)
{
  if (title == "") {

    title = std::string("Freq Series Fit Residuals; time [ms]; amplitude [a.u.]");

  } else {

    // In case they didn't append x/y labels.
    title.append("; freq [kHz]; amplitude [a.u.]");
  }

  // Copy the current time fit.
  gr_ = gr_freq_series_;

  // Set the points
  for (uint i = 0; i < res_.size(); ++i){
    static double x, y;

    gr_.GetPoint(i, x, y);
    gr_.SetPoint(i, x, res_[i]);
  }

  SaveGraph(filename, title);
}

// Save the FID data to a text file as "<time> <amp>".
void BaseFid::SaveData(std::string filename)
{
  // open the file first
  std::ofstream out(filename);

  for (int i = 0; i < tm_.size(); ++i) {
    out << tm_[i] << " " << wf_[i] << std::endl;
  }
}

void BaseFid::DiagnosticInfo(std::ostream& out)
{
  using std::endl;

  // Save the flags, set them to defaults.
  auto flags = out.flags();
  std::ofstream testout;
  out.flags(testout.flags());

  out << std::string(80, '<') << endl << std::string(4, ' ');
  out << "Diagostic Information for Fid @ " << this << endl;
  out << std::string(80, '<') << endl;

  out << "    Fid Waveform Characteristics" << endl;
  out << "        mean:       " << mean_ << endl;
  out << "        amplitude:  " << max_amp_ << endl;
  out << "        noise:      " << noise_ << endl;
  out << "        start time: " << i_wf_;
  out << " (" << tm_[i_wf_] << " ms)" << endl;
  out << "        stop time:  " << f_wf_ - 1;
  out << " (" << tm_[f_wf_ - 1] << " ms)" << endl;
  out << "        health:     " << health_ << endl;
  out << std::string(80, '>') << endl << endl;

  // Restore set flags.
  out.flags(flags);
}

void BaseFid::DiagnosticPlot(std::string dirname, std::string filestub)
{
  boost::filesystem::path dir(dirname);
  boost::filesystem::create_directories(dir);

  SaveFreqFit(dir.string() + filestub + std::string("_freq_fit.png"));
  SaveTimeFit(dir.string() + filestub + std::string("_time_fit.png"));
  SaveFreqRes(dir.string() + filestub + std::string("_freq_res.png"));
  SaveTimeRes(dir.string() + filestub + std::string("_time_res.png"));
}

void BaseFid::DiagnosticDump(std::string dirname, std::string filestub)
{
  // Make the plots first, that will create the directory if needed.
  DiagnosticPlot(dirname, filestub);

  std::ofstream out;
  boost::filesystem::path dir(dirname);

  std::string str = dir.string() + std::string("libfid.log");
  out.open(str , std::ofstream::out | std::ofstream::app);

  DiagnosticInfo(out);
  out.close();
}

} // fid
<commit_msg>Adds compatibility with root5 back.<commit_after>#include "fid/base_fid.h"

namespace fid {

void BaseFid::Init()
{
  // Prevent memory issues with the TF1s in root6.
#ifdef __ROOTCLING__
  TF1::DefaultAddToGlobalList(false);
#endif

  // Initialize the health properly.
  health_ = 100.0;

  // Resize the temp array (maybe others?)
  temp_.reserve(wf_.size());

  // Initialize the BaseFid for analysis
  LoadParams();
  CenterFid();
  CalcNoise();
  CalcMaxAmp();
  FindFidRange();
  InitHook();

  CalcFreq();

  // Flag the FID as bad if it's negative.
  if (freq_ < 0.0) {
    health_ = 0.0;
  }

  // Else calculate a health based on signal to noise.
  if (max_amp_ < noise_ * snr_thresh_) {
    health_ *= max_amp_ / (noise_ * snr_thresh_);
  }

  // And factor fid duration into health.
  if (f_wf_ - i_wf_ < wf_.size() * len_thresh_) {
    health_ *= (f_wf_ - i_wf_) / (wf_.size() * len_thresh_);
  }
}

// Load FID data from a formatted text file.
void BaseFid::LoadTextData(std::string filename)
{
  // open the file first
  std::ifstream in(filename);

  // shrink vectors
  wf_.resize(0);
  tm_.resize(0);

  double wf_temp;
  double tm_temp;

  while (in.good()) {
    in >> tm_temp >> wf_temp;
    tm_.push_back(tm_temp);
    wf_.push_back(wf_temp);
  }
}

// Load all the current parameters in the fid::params namespace.
void BaseFid::LoadParams()
{
  edge_width_ = params::edge_width;
  edge_ignore_ = params::edge_ignore;
  start_amplitude_ = params::start_amplitude;
  max_phase_jump_ = params::max_phase_jump;
  low_pass_freq_ = params::low_pass_freq;
  fft_peak_width_ = params::fft_peak_width;
  centroid_thresh_ = params::centroid_thresh;
  hyst_thresh_ = params::hyst_thresh;
  snr_thresh_ = params::snr_thresh;
  len_thresh_ = params::len_thresh;
  freq_method_ = params::freq_method;
}

void BaseFid::CenterFid()
{
  int w = edge_width_;
  double sum  = std::accumulate(wf_.begin(), wf_.begin() + w, 0.0);
  double avg = sum / w; // to pass into lambda
  mean_ = avg; // save to class

  std::for_each(wf_.begin(), wf_.end(), [avg](double& x){ x -= avg; });
}

void BaseFid::CalcNoise()
{
  // Grab a new handle to the noise window width for aesthetics.
  int i = edge_ignore_;
  int f = edge_width_ + i;

  // Find the noise level in the head and tail.
  double head = stdev(wf_.begin() + i, wf_.begin() + f);
  double tail = stdev(wf_.rbegin() + i, wf_.rbegin() + f);

  // Take the smaller of the two.
  noise_ = (tail < head) ? (tail) : (head);
}

void BaseFid::CalcMaxAmp()
{
  auto mm = std::minmax_element(wf_.begin(), wf_.end());

  if (std::abs(*mm.first) > std::abs(*mm.second)) {

    max_amp_ = std::abs(*mm.first);

  } else {

    max_amp_ = std::abs(*mm.second);
  }
}

void BaseFid::FindFidRange()
{
  // Find the starting and ending points
  double thresh = start_amplitude_ * max_amp_;
  bool checks_out = false;

  // Find the first element with magnitude larger than thresh
  auto it_1 = wf_.begin() + edge_ignore_;

  while (!checks_out) {

    // Check if the point is above threshold.
    auto it_i = std::find_if(it_1, wf_.end(),
      [thresh](double x) {
        return std::abs(x) > thresh;
    });

    // Make sure the point is not with one of the vector's end.
    if ((it_i != wf_.end()) && (it_i + 1 != wf_.end())) {

      // Check if the next point is also over threshold.
      checks_out = std::abs(*(it_i + 1)) > thresh;

      // Increase the comparison starting point.
      it_1 = it_i + 1;

      // Turn the iterator into an index
      if (checks_out) {
        i_wf_ = std::distance(wf_.begin(), it_i);
      }

    } else {

      // If we have reached the end, mark it as the last.
      i_wf_ = std::distance(wf_.begin(), wf_.end());
      break;
    }
  }

  // Find the next element with magnitude lower than thresh
  auto it_2 = std::find_if(wf_.begin() + i_wf_, wf_.end(),
      [thresh](double x) {
        return std::abs(x) < 0.8 * thresh;
  });

  checks_out = false;

  while (!checks_out) {

    // Find the range around a peak.
    auto it_i = std::find_if(it_2, wf_.end(),
      [thresh](double x) {
        return std::abs(x) > 0.8 * thresh;
    });

    auto it_f = std::find_if(it_i + 1, wf_.end(),
      [thresh](double x) {
        return std::abs(x) < 0.8 * thresh;
    });

    // Now check if the peak actually made it over threshold.
    if ((it_i != wf_.end()) && (it_f != wf_.end())) {

      auto mm = std::minmax_element(it_i, it_f);

      if ((*mm.first < -thresh) || (*mm.second > thresh)) {

        it_2 = it_f;

      } else {

        checks_out = true;
      }

      // Turn the iterator into an index
      if (checks_out) {
        f_wf_ = std::distance(wf_.begin(), it_f);
      }

    } else {

      f_wf_ = std::distance(wf_.begin(), wf_.end());
      break;
    }
  }

  // Gradients can cause a waist in the amplitude.
  // Mark the signal as bad if it didn't find signal above threshold.
  if (i_wf_ > wf_.size() * 0.95 || i_wf_ >= f_wf_) {

    health_ = 0.0;

    i_wf_ = 0;
    f_wf_ = wf_.size() * 0.01;
  }
}

// Save the interanl TGraph.
void BaseFid::SaveGraph(std::string filename, std::string title)
{
  gr_.SetTitle(title.c_str());
  gr_.Draw();
  c1_.Print(filename.c_str());
}

// Save a plot of FID waveform.
void BaseFid::SavePlot(std::string filename, std::string title)
{
  // If no title supplied give a reasonable default.
  if (title == "") {

    title = std::string("FID; time [ms]; amplitude [a.u.]");

  } else {

    // In case they didn't append x/y labels.
    title.append("; time [ms]; amplitude [a.u.]");
  }

  gr_ = TGraph(wf_.size(), &tm_[0], &wf_[0]);

  SaveGraph(filename, title);
}

// Print the time series fit from an FID.
void BaseFid::SaveTimeFit(std::string filename, std::string title)
{
  if (title == "") {

    title = std::string("Time Series Fit; time [ms]; amplitude [a.u.]");

  } else {

    // In case they didn't append x/y labels.
    title.append("; time [ms]; amplitude [a.u.]");
  }

  // Copy the current time fit graph.
  gr_ = gr_time_series_;
  SaveGraph(filename, title);
}

// Print the time series fit from an FID.
void BaseFid::SaveFreqFit(std::string filename, std::string title)
{
  if (title == "") {

    title = std::string("Frequency Series Fit; time [ms]; amplitude [a.u.]");

  } else {

    // In case they didn't append x/y labels.
    title.append("; freq [kHz]; amplitude [a.u.]");
  }

  // Copy the current time fit graph.
  gr_ = gr_freq_series_;
  SaveGraph(filename, title);
}

void BaseFid::SaveTimeRes(std::string filename, std::string title)
{
  if (title == "") {

    title = std::string("Time Series Fit Residuals; time [ms]; amplitude [a.u.]");

  } else {

    // In case they didn't append x/y labels.
    title.append("; time [ms]; amplitude [a.u.]");
  }

  // Copy the current time fit.
  gr_ = gr_time_series_;

  // Set the points
  for (uint i = 0; i < res_.size(); ++i){
    static double x, y;

    gr_.GetPoint(i, x, y);
    gr_.SetPoint(i, x, res_[i]);
  }

  SaveGraph(filename, title);
}

void BaseFid::SaveFreqRes(std::string filename, std::string title)
{
  if (title == "") {

    title = std::string("Freq Series Fit Residuals; time [ms]; amplitude [a.u.]");

  } else {

    // In case they didn't append x/y labels.
    title.append("; freq [kHz]; amplitude [a.u.]");
  }

  // Copy the current time fit.
  gr_ = gr_freq_series_;

  // Set the points
  for (uint i = 0; i < res_.size(); ++i){
    static double x, y;

    gr_.GetPoint(i, x, y);
    gr_.SetPoint(i, x, res_[i]);
  }

  SaveGraph(filename, title);
}

// Save the FID data to a text file as "<time> <amp>".
void BaseFid::SaveData(std::string filename)
{
  // open the file first
  std::ofstream out(filename);

  for (int i = 0; i < tm_.size(); ++i) {
    out << tm_[i] << " " << wf_[i] << std::endl;
  }
}

void BaseFid::DiagnosticInfo(std::ostream& out)
{
  using std::endl;

  // Save the flags, set them to defaults.
  auto flags = out.flags();
  std::ofstream testout;
  out.flags(testout.flags());

  out << std::string(80, '<') << endl << std::string(4, ' ');
  out << "Diagostic Information for Fid @ " << this << endl;
  out << std::string(80, '<') << endl;

  out << "    Fid Waveform Characteristics" << endl;
  out << "        mean:       " << mean_ << endl;
  out << "        amplitude:  " << max_amp_ << endl;
  out << "        noise:      " << noise_ << endl;
  out << "        start time: " << i_wf_;
  out << " (" << tm_[i_wf_] << " ms)" << endl;
  out << "        stop time:  " << f_wf_ - 1;
  out << " (" << tm_[f_wf_ - 1] << " ms)" << endl;
  out << "        health:     " << health_ << endl;
  out << std::string(80, '>') << endl << endl;

  // Restore set flags.
  out.flags(flags);
}

void BaseFid::DiagnosticPlot(std::string dirname, std::string filestub)
{
  boost::filesystem::path dir(dirname);
  boost::filesystem::create_directories(dir);

  SaveFreqFit(dir.string() + filestub + std::string("_freq_fit.png"));
  SaveTimeFit(dir.string() + filestub + std::string("_time_fit.png"));
  SaveFreqRes(dir.string() + filestub + std::string("_freq_res.png"));
  SaveTimeRes(dir.string() + filestub + std::string("_time_res.png"));
}

void BaseFid::DiagnosticDump(std::string dirname, std::string filestub)
{
  // Make the plots first, that will create the directory if needed.
  DiagnosticPlot(dirname, filestub);

  std::ofstream out;
  boost::filesystem::path dir(dirname);

  std::string str = dir.string() + std::string("libfid.log");
  out.open(str , std::ofstream::out | std::ofstream::app);

  DiagnosticInfo(out);
  out.close();
}

} // fid
<|endoftext|>


<commit_before>/*
 * ScopeLink.cc
 *
 * Copyright (C) 2009, 2014, 2015 Linas Vepstas
 *
 * Author: Linas Vepstas <linasvepstas@gmail.com>  January 2009
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License v3 as
 * published by the Free Software Foundation and including the
 * exceptions at http://opencog.org/wiki/Licenses
 *
 * 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 Affero General Public
 * License along with this program; if not, write to:
 * Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 */

#include <opencog/atoms/base/ClassServer.h>
#include <opencog/atoms/TypeNode.h>
#include <opencog/atoms/core/FreeLink.h>
#include <opencog/atoms/core/LambdaLink.h>

#include "ScopeLink.h"

using namespace opencog;

void ScopeLink::init(void)
{
	extract_variables(_outgoing);
}

void ScopeLink::set_body(const Handle& body)
{
	_body = body;
	if (_bodies.empty())
		_bodies.push_back(body);
	else
		_bodies[0] = body;
}

ScopeLink::ScopeLink(const HandleSeq& oset,
                     TruthValuePtr tv, AttentionValuePtr av)
	: Link(SCOPE_LINK, oset, tv, av)
{
	init();
}

ScopeLink::ScopeLink(const Handle& vars, const Handle& body,
                     TruthValuePtr tv, AttentionValuePtr av)
	: Link(SCOPE_LINK, HandleSeq({vars, body}), tv, av)
{
	init();
}

ScopeLink::ScopeLink(Type t, const Handle& body,
                     TruthValuePtr tv, AttentionValuePtr av)
	: Link(t, HandleSeq({body}), tv, av)
{
	// Derived classes have a different initialization sequence
	if (SCOPE_LINK != t) return;
	init();
}

ScopeLink::ScopeLink(Type t, const HandleSeq& oset,
                     TruthValuePtr tv, AttentionValuePtr av)
	: Link(t, oset, tv, av)
{
	// Derived classes have a different initialization sequence
	if (SCOPE_LINK != t) return;
	init();
}

ScopeLink::ScopeLink(Link &l)
	: Link(l)
{
	// Type must be as expected.
	Type tscope = l.getType();
	if (not classserver().isA(tscope, SCOPE_LINK))
	{
		const std::string& tname = classserver().getTypeName(tscope);
		throw InvalidParamException(TRACE_INFO,
			"Expecting a ScopeLink, got %s", tname.c_str());
	}

	// Derived types have a different initialization sequence.
	if (SCOPE_LINK != tscope) return;
	init();
}

/* ================================================================= */
///
/// Find and unpack variable declarations, if any; otherwise, just
/// find all free variables.
///
void ScopeLink::extract_variables(const HandleSeq& oset)
{
	if (oset.size() == 0)
		throw SyntaxException(TRACE_INFO,
			"Expecting a non-empty outgoing set.");

	Type decls = oset.at(0)->getType();

	// If the first atom is not explicitly a variable declaration, then
	// there are no variable declarations. There are two cases that; can
	// apply here: either the body is a lambda, in which case, we copy
	// the variables from the lambda; else we extract all free variables.
	if (VARIABLE_LIST != decls and
	    VARIABLE_NODE != decls and
	    TYPED_VARIABLE_LINK != decls and
	    GLOB_NODE != decls)
	{
		set_body(oset[0]);

		if (classserver().isA(_body->getType(), LAMBDA_LINK))
		{
			LambdaLinkPtr lam(LambdaLinkCast(_body));
			if (nullptr == lam)
				lam = createLambdaLink(*LinkCast(_body));
			_varlist = lam->get_variables();
			set_body(lam->get_body());
		}
		else
		{
			_varlist.find_variables(oset[0]);
		}
		return;
	}

	if (oset.size() < 2)
		throw SyntaxException(TRACE_INFO,
			"Expecting an outgoing set size of at least two; got %s",
			oset[0]->toString().c_str());

	// If we are here, then the first outgoing set member should be
	// a variable declaration.
	_vardecl = oset[0];
	set_body(oset[1]);

	// Initialize _varlist with the scoped variables
	init_scoped_variables(_vardecl);
}

/* ================================================================= */
///
/// Initialize _varlist given a handle of either VariableList or a
/// variable.
///
void ScopeLink::init_scoped_variables(const Handle& hvar)
{
	// Use the VariableList class as a tool to extract the variables
	// for us.
	VariableList vl(hvar);
	_varlist = vl.get_variables();
}

/* ================================================================= */
///
/// Compare other ScopeLink, return true if it is equal to this one,
/// up to an alpha-conversion of variables.
///
bool ScopeLink::is_equal(const Handle& other) const
{
	if (other == this) return true;
	if (other->getType() != _type) return false;

	ScopeLinkPtr scother(ScopeLinkCast(other));

	// Variable declarations must match.
	if (not _varlist.is_equal(scother->_varlist)) return false;

	// Other body, with our variables in place of its variables,
	// should be same as our body.
	Handle altbod = scother->_varlist.substitute_nocheck(scother->_body,
	                                                  _varlist.varseq);

	// Compare bodies, they should match.
	if (*((AtomPtr)altbod) != *((AtomPtr) _body)) return false;

	return true;
}

bool ScopeLink::operator==(const Atom& ac) const
{
	Atom& a = (Atom&) ac; // cast away constness, for smart ptr.
	return is_equal(a.getHandle());
}

bool ScopeLink::operator!=(const Atom& a) const
{
	return not operator==(a);
}

/* ===================== END OF FILE ===================== */
<commit_msg>Support links with multiple bodies in ScopeLink::is_equal<commit_after>/*
 * ScopeLink.cc
 *
 * Copyright (C) 2009, 2014, 2015 Linas Vepstas
 *
 * Author: Linas Vepstas <linasvepstas@gmail.com>  January 2009
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License v3 as
 * published by the Free Software Foundation and including the
 * exceptions at http://opencog.org/wiki/Licenses
 *
 * 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 Affero General Public
 * License along with this program; if not, write to:
 * Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 */

#include <opencog/atoms/base/ClassServer.h>
#include <opencog/atoms/TypeNode.h>
#include <opencog/atoms/core/FreeLink.h>
#include <opencog/atoms/core/LambdaLink.h>

#include "ScopeLink.h"

using namespace opencog;

void ScopeLink::init(void)
{
	extract_variables(_outgoing);
}

void ScopeLink::set_body(const Handle& body)
{
	_body = body;
	if (_bodies.empty())
		_bodies.push_back(body);
	else
		_bodies[0] = body;
}

ScopeLink::ScopeLink(const HandleSeq& oset,
                     TruthValuePtr tv, AttentionValuePtr av)
	: Link(SCOPE_LINK, oset, tv, av)
{
	init();
}

ScopeLink::ScopeLink(const Handle& vars, const Handle& body,
                     TruthValuePtr tv, AttentionValuePtr av)
	: Link(SCOPE_LINK, HandleSeq({vars, body}), tv, av)
{
	init();
}

ScopeLink::ScopeLink(Type t, const Handle& body,
                     TruthValuePtr tv, AttentionValuePtr av)
	: Link(t, HandleSeq({body}), tv, av)
{
	// Derived classes have a different initialization sequence
	if (SCOPE_LINK != t) return;
	init();
}

ScopeLink::ScopeLink(Type t, const HandleSeq& oset,
                     TruthValuePtr tv, AttentionValuePtr av)
	: Link(t, oset, tv, av)
{
	// Derived classes have a different initialization sequence
	if (SCOPE_LINK != t) return;
	init();
}

ScopeLink::ScopeLink(Link &l)
	: Link(l)
{
	// Type must be as expected.
	Type tscope = l.getType();
	if (not classserver().isA(tscope, SCOPE_LINK))
	{
		const std::string& tname = classserver().getTypeName(tscope);
		throw InvalidParamException(TRACE_INFO,
			"Expecting a ScopeLink, got %s", tname.c_str());
	}

	// Derived types have a different initialization sequence.
	if (SCOPE_LINK != tscope) return;
	init();
}

/* ================================================================= */
///
/// Find and unpack variable declarations, if any; otherwise, just
/// find all free variables.
///
void ScopeLink::extract_variables(const HandleSeq& oset)
{
	if (oset.size() == 0)
		throw SyntaxException(TRACE_INFO,
			"Expecting a non-empty outgoing set.");

	Type decls = oset.at(0)->getType();

	// If the first atom is not explicitly a variable declaration, then
	// there are no variable declarations. There are two cases that; can
	// apply here: either the body is a lambda, in which case, we copy
	// the variables from the lambda; else we extract all free variables.
	if (VARIABLE_LIST != decls and
	    VARIABLE_NODE != decls and
	    TYPED_VARIABLE_LINK != decls and
	    GLOB_NODE != decls)
	{
		set_body(oset[0]);

		if (classserver().isA(_body->getType(), LAMBDA_LINK))
		{
			LambdaLinkPtr lam(LambdaLinkCast(_body));
			if (nullptr == lam)
				lam = createLambdaLink(*LinkCast(_body));
			_varlist = lam->get_variables();
			set_body(lam->get_body());
		}
		else
		{
			_varlist.find_variables(oset[0]);
		}
		return;
	}

	if (oset.size() < 2)
		throw SyntaxException(TRACE_INFO,
			"Expecting an outgoing set size of at least two; got %s",
			oset[0]->toString().c_str());

	// If we are here, then the first outgoing set member should be
	// a variable declaration.
	_vardecl = oset[0];
	set_body(oset[1]);

	// Initialize _varlist with the scoped variables
	init_scoped_variables(_vardecl);
}

/* ================================================================= */
///
/// Initialize _varlist given a handle of either VariableList or a
/// variable.
///
void ScopeLink::init_scoped_variables(const Handle& hvar)
{
	// Use the VariableList class as a tool to extract the variables
	// for us.
	VariableList vl(hvar);
	_varlist = vl.get_variables();
}

/* ================================================================= */
///
/// Compare other ScopeLink, return true if it is equal to this one,
/// up to an alpha-conversion of variables.
///
bool ScopeLink::is_equal(const Handle& other) const
{
	if (other == this) return true;
	if (other->getType() != _type) return false;

	ScopeLinkPtr scother(ScopeLinkCast(other));

	// Variable declarations must match.
	if (not _varlist.is_equal(scother->_varlist)) return false;

	// Other body(ies), with our variables in place of its variables,
	// should be same as our body(ies).
	for (size_t i = 0; i < _bodies.size(); ++i) {
		Handle altbod = scother->_varlist.substitute_nocheck(scother->_bodies[i],
		                                                     _varlist.varseq);
		// Compare bodies, they should match.
		if (*((AtomPtr)altbod) != *((AtomPtr) _bodies[i])) return false;
	}

	return true;
}

bool ScopeLink::operator==(const Atom& ac) const
{
	Atom& a = (Atom&) ac; // cast away constness, for smart ptr.
	return is_equal(a.getHandle());
}

bool ScopeLink::operator!=(const Atom& a) const
{
	return not operator==(a);
}

/* ===================== END OF FILE ===================== */
<|endoftext|>


<commit_before>#include "ofxGpuLut.h"

ofxGpuLut::ofxGpuLut(){}
ofxGpuLut::~ofxGpuLut(){}

void ofxGpuLut::load(ofTexture lutTexture){
    fragmentShader = "#version 120\n#extension GL_ARB_texture_rectangle : enable\n";
    fragmentShader += STRINGIFY(
                                uniform sampler2DRect tex;
                                uniform sampler2DRect lut;

                                float size = 64.0;

                                void main( void )
                                {
                                    vec3 originalColor = floor(texture2DRect(tex, gl_TexCoord[0].st).rgb * vec3(size - 1.0));
                                    vec2 blueIndex = vec2(mod(originalColor.b, sqrt(size)), floor(originalColor.b / sqrt(size)));
                                    vec2 index = vec2((size * blueIndex.x + originalColor.r) + 0.5, (size * blueIndex.y + originalColor.g) + 0.5);
                                    gl_FragColor = vec4(texture2DRect(lut, index).rgb, 1.0);
                                }
                                );
    lutShader.unload();
    lutShader.setupShaderFromSource(GL_FRAGMENT_SHADER, fragmentShader);
    lutShader.linkProgram();
    lut.setTextureWrap(GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE);
    lut.setTextureMinMagFilter(GL_NEAREST, GL_NEAREST);
    if(!ofGetUsingArbTex()){
        ofEnableArbTex();
        lut = lutTexture;
        ofDisableArbTex();
    }else{
        lut = lutTexture;
    }
}

void ofxGpuLut::load(ofImage lutImage){
    load(lutImage.getTexture());
}

void ofxGpuLut::load(string path){
    lutImage.load(path);
    load(lutImage.getTexture());
}

void ofxGpuLut::begin(){
    lutShader.begin();
    lutShader.setUniformTexture("lut", lut, 1);
}

void ofxGpuLut::end(){
    lutShader.end();
}<commit_msg>Taking in account the alpha channel of the source texture.<commit_after>#include "ofxGpuLut.h"

ofxGpuLut::ofxGpuLut(){}
ofxGpuLut::~ofxGpuLut(){}

void ofxGpuLut::load(ofTexture lutTexture){
    fragmentShader = "#version 120\n#extension GL_ARB_texture_rectangle : enable\n";
    fragmentShader += STRINGIFY(
                                uniform sampler2DRect tex;
                                uniform sampler2DRect lut;

                                float size = 64.0;

                                void main( void )
                                {
                                    vec3 rawColor = texture2DRect(tex, gl_TexCoord[0].st).rgb;
                                    float rawAlpha = texture2DRect(tex, gl_TexCoord[0].st).a;

                                    if (rawAlpha <= 0.0) {
                                        gl_FragColor = vec4(rawColor, 0.0);
                                    }
                                    else {
                                        vec3 originalColor = floor(texture2DRect(tex, gl_TexCoord[0].st).rgb * vec3(size - 1.0));
                                        vec2 blueIndex = vec2(mod(originalColor.b, sqrt(size)), floor(originalColor.b / sqrt(size)));
                                        vec2 index = vec2((size * blueIndex.x + originalColor.r) + 0.5, (size * blueIndex.y + originalColor.g) + 0.5);
                                        gl_FragColor = vec4(texture2DRect(lut, index).rgb, rawAlpha);
                                    }
                                }
                                );

    lutShader.unload();
    lutShader.setupShaderFromSource(GL_FRAGMENT_SHADER, fragmentShader);
    lutShader.linkProgram();
    lut.setTextureWrap(GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE);
    lut.setTextureMinMagFilter(GL_NEAREST, GL_NEAREST);
    if(!ofGetUsingArbTex()){
        ofEnableArbTex();
        lut = lutTexture;
        ofDisableArbTex();
    }else{
        lut = lutTexture;
    }
}

void ofxGpuLut::load(ofImage lutImage){
    load(lutImage.getTexture());
}

void ofxGpuLut::load(string path){
    lutImage.load(path);
    load(lutImage.getTexture());
}

void ofxGpuLut::begin(){
    lutShader.begin();
    lutShader.setUniformTexture("lut", lut, 1);
}

void ofxGpuLut::end(){
    lutShader.end();
}<|endoftext|>


<commit_before>/*
 * film.cpp
 *
 *  Created on: 2016年12月2日
 *      Author: zhuqian
 */
#include "film.h"
#include "paramset.h"
#include "imageio.h"

Film::Film(const Point2i& res/*分辨率*/, const Bound2f& cropped/*实际渲染窗口比例*/,
		std::unique_ptr<Filter> filt, const std::string& fileName/*输出文件名*/,
		Float maxSampleLuminance) :
		fullResolution(res), fileName(fileName), filter(std::move(filt)), _maxSampleLuminance(
				maxSampleLuminance) {
	Point2i minCropped = Point2i(
			std::ceil(fullResolution.x * cropped.minPoint.x),
			std::ceil(fullResolution.y * cropped.minPoint.y));
	Point2i maxCropped = Point2i(
			std::floor(fullResolution.x * cropped.maxPoint.x),
			std::floor(fullResolution.y * cropped.maxPoint.y));
	croppedPixelBound = Bound2i(minCropped, maxCropped);
	//分配储存像素所需要的空间
	_pixels = std::unique_ptr<Pixel[]>(new Pixel[croppedPixelBound.Area()]);
	//预计算filterTable 只计算1/4
	int offset = 0;
	for (int y = 0; y < filterTableWidth; ++y) {
		for (int x = 0; x < filterTableWidth; ++x, ++offset) {
			Point2f point;
			point.x = (x + 0.5f) * (filter->radius.x / filterTableWidth);
			point.y = (y + 0.5f) * (filter->radius.y / filterTableWidth);
			_filterTable[offset] = filter->Evaluate(point);
		}
	}

}

void Film::SetImage(const Spectrum* img) {
	int numPixel = croppedPixelBound.Area();
	for (int i = 0; i < numPixel; ++i) {
		Pixel& p = _pixels[i];
		img[i].ToXYZ(p.xyz);
		p.filterWeightSum = 1;
		p.splatXYZ[0] = p.splatXYZ[1] = p.splatXYZ[2] = 0;
	}
}

void Film::WriteImage(Float splatScale) {
	std::vector<Float> image;
	for (int j = croppedPixelBound[0].y; j < croppedPixelBound[1].y; ++j) {
			for (int i = croppedPixelBound[0].x; i < croppedPixelBound[1].x; ++i) {
				Pixel &p = GetPixel(Point2i(i, j));
				Float rgb[3];
				XYZToRGB(p.xyz, rgb);
				if(p.filterWeightSum!=0){
					Float invWeight = 1.0 / p.filterWeightSum;
					rgb[0] *= invWeight;
					rgb[1] *= invWeight;
					rgb[2] *= invWeight;
				}

				//添加splatXYZ内的能量
				Float splatRGB[3];
				Float splatXYZ[3]={p.splatXYZ[0],p.splatXYZ[1] ,p.splatXYZ[2] };
				XYZToRGB(splatXYZ, splatRGB);

				rgb[0] += splatRGB[0] * splatScale;
				rgb[1] += splatRGB[1] * splatScale;
				rgb[2] += splatRGB[2] * splatScale;

				image.push_back(rgb[0]);
				image.push_back(rgb[1]);
				image.push_back(rgb[2]);
			}
		}
	Vector2i resolution=croppedPixelBound.Diagonal();
	WriteImageToFile(fileName.c_str(), &image[0], resolution.x, resolution.y);
}

void Film::AddSplat(const Point2f& p, Spectrum L) {
	if (L.HasNaNs()) {
		LWarning << "Ignoring splatted spectrum with NaN values at (" << p.x << "," << p.y << ")";
		return;
	}
	else if (L.y() < 0) {
		LWarning<<"Ignoring splatted spectrum with negative luminance"<<L.y()<<"at (" << p.x << "," << p.y << ")";
		return;
	}
	else if (std::isinf(L.y())) {
		LWarning << "Ignoring splatted spectrum with infinite luminance at (" << p.x << "," << p.y << ")";
		return;
	}

	if(!InsideExclusive((Point2i)p, croppedPixelBound)) {
		return;
	}

	if (L.y() > _maxSampleLuminance){
		L = (_maxSampleLuminance / L.y())*L;
	}

	auto& pixel=GetPixel((Point2i)p);
	Float xyz[3];
	L.ToXYZ(xyz);
	for (int i = 0; i < 3; ++i) {
		pixel.splatXYZ[i].Add(xyz[i]);
	}
}

void FilmTile::AddSample(const Point2f& pFilm, Spectrum L, Float weight) {
	Assert(weight>0.0f);
	//Assert(InsideExclusive(pFilm,_pixelBound));
	//贡献值大于最大值，需要scale
	if (L.y() > _maxSampleLuminance) {
		L *= (_maxSampleLuminance / L.y());
	}

	//计算过滤范围
	Point2f pFilmDiscrete = pFilm - Vector2f(0.5f, 0.5f);
	Point2i pMin = Point2i(Ceil(pFilmDiscrete - _filterRadius));
	Point2i pMax = Point2i(Floor(pFilmDiscrete + _filterRadius))+Point2i(1,1);
	pMin = Max(_pixelBound.minPoint, pMin);
	pMax = Min(_pixelBound.maxPoint, pMax);
	//预计算row和col上的偏移
	int *ifx = ALLOCA(int, pMax.x - pMin.x);
	for (int x = pMin.x; x < pMax.x; ++x) {
		Float offsetX = std::abs(x - pFilmDiscrete.x) * _invFilterRadius.x
				* _filterTableWidth;
		ifx[x - pMin.x] = std::min((int) std::floor(offsetX),
				_filterTableWidth - 1);
	}
	int *ify = ALLOCA(int, pMax.y - pMin.y);
	for (int y = pMin.y; y < pMax.y; ++y) {
		Float offsetY = std::abs(y - pFilmDiscrete.y) * _invFilterRadius.y
				* _filterTableWidth;
		ify[y - pMin.y] = std::min((int) std::floor(offsetY),
				_filterTableWidth - 1);
	}

	for (int y = pMin.y; y < pMax.y; ++y) {
		for (int x = pMin.x; x < pMax.x; ++x) {
			int filterTableIndex = ify[y - pMin.y] * _filterTableWidth
					+ ifx[x - pMin.x];	//filter表索引
			Float fiterWeight = _filterTable[filterTableIndex];	//过滤器权重
			FilmTilePixel& pixel = GetPixel(Point2i(x, y));
			pixel.contribSum += L * weight * fiterWeight;
			pixel.filterWeightSum += fiterWeight;
		}
	}
}

std::unique_ptr<FilmTile> Film::GetFilmTile(const Bound2i &sampleBounds) {
	Vector2f half(0.5f, 0.5f);
	Bound2f floatBounds = (Bound2f) sampleBounds;
	Point2i p0 = (Point2i) Ceil(floatBounds.minPoint - half - filter->radius);
	Point2i p1 = (Point2i) Floor(floatBounds.maxPoint - half + filter->radius)
			+ Point2i(1, 1);
	Bound2i pixelBound=Intersect(Bound2i(p0,p1),croppedPixelBound);
	return std::unique_ptr<FilmTile>(new FilmTile(pixelBound,filter->radius,_filterTable,filterTableWidth,_maxSampleLuminance));
}

void Film::MergeFilmTile(std::unique_ptr<FilmTile> tile){
	//获取互斥锁
	std::lock_guard<std::mutex> lock(_mutex);
	for(Point2i pixelPos:tile->GetPixelBound()){
		const FilmTilePixel& tilePixel=tile->GetPixel(pixelPos);
		Pixel& pixel=GetPixel(pixelPos);
		Float xyz[3];
		tilePixel.contribSum.ToXYZ(xyz);
		for(int i=0;i<3;++i){
			pixel.xyz[i]+=xyz[i];
		}
		pixel.filterWeightSum+=tilePixel.filterWeightSum;
	}
}

//{filename:string,xresolution:int,yresolution:int,cropwindow:Float[4],maxsampleluminance:Float}
Film *CreateFilm(const ParamSet &params, std::unique_ptr<Filter> filter) {
    std::string filename = params.FindOneString("filename", "");
    if (RaidenOptions.imageFile != "") {
        if (filename != "") {
        	LWarning<<"ingore commandline filename:"<<RaidenOptions.imageFile.c_str()<<",use descriptionfile filename:"<<filename.c_str();
        } else{
            filename = RaidenOptions.imageFile;
        }
    }
    if (filename == "") {filename = "raiden.png";}

    int xres = params.FindOneInt("xresolution", 1280);
    int yres = params.FindOneInt("yresolution", 720);
    Bound2f crop(Point2f(0, 0), Point2f(1, 1));
    int cwi;
    const Float *cr = params.FindFloat("cropwindow", &cwi);
    if (cr && cwi == 4) {
        crop.minPoint.x = Clamp(std::min(cr[0], cr[1]), 0.0f, 1.0f);
        crop.maxPoint.x = Clamp(std::max(cr[0], cr[1]), 0.0f, 1.0f);
        crop.minPoint.y = Clamp(std::min(cr[2], cr[3]), 0.0f, 1.0f);
        crop.maxPoint.y = Clamp(std::max(cr[2], cr[3]), 0.0f, 1.0f);
    } else if (cr){
    	LError<<"cropwindow need four values, and "<<cwi<<" for now.";
    }
    Float maxSampleLuminance = params.FindOneFloat("maxsampleluminance",
                                                   Infinity);
	Debug("[CreateFilm][ res:" << Point2i(xres, yres) << ",croppedPixelBound:" << crop << ".]");

    return new Film(Point2i(xres, yres), crop, std::move(filter),
                    filename,maxSampleLuminance);
}
<commit_msg>为film添加是否支持相应格式的代码<commit_after>/*
 * film.cpp
 *
 *  Created on: 2016年12月2日
 *      Author: zhuqian
 */
#include "film.h"
#include "paramset.h"
#include "imageio.h"

Film::Film(const Point2i &res /*分辨率*/, const Bound2f &cropped /*实际渲染窗口比例*/,
		   std::unique_ptr<Filter> filt, const std::string &fileName /*输出文件名*/,
		   Float maxSampleLuminance) : fullResolution(res), fileName(fileName), filter(std::move(filt)), _maxSampleLuminance(maxSampleLuminance)
{
	Point2i minCropped = Point2i(
		std::ceil(fullResolution.x * cropped.minPoint.x),
		std::ceil(fullResolution.y * cropped.minPoint.y));
	Point2i maxCropped = Point2i(
		std::floor(fullResolution.x * cropped.maxPoint.x),
		std::floor(fullResolution.y * cropped.maxPoint.y));
	croppedPixelBound = Bound2i(minCropped, maxCropped);
	//分配储存像素所需要的空间
	_pixels = std::unique_ptr<Pixel[]>(new Pixel[croppedPixelBound.Area()]);
	//预计算filterTable 只计算1/4
	int offset = 0;
	for (int y = 0; y < filterTableWidth; ++y)
	{
		for (int x = 0; x < filterTableWidth; ++x, ++offset)
		{
			Point2f point;
			point.x = (x + 0.5f) * (filter->radius.x / filterTableWidth);
			point.y = (y + 0.5f) * (filter->radius.y / filterTableWidth);
			_filterTable[offset] = filter->Evaluate(point);
		}
	}
}

void Film::SetImage(const Spectrum *img)
{
	int numPixel = croppedPixelBound.Area();
	for (int i = 0; i < numPixel; ++i)
	{
		Pixel &p = _pixels[i];
		img[i].ToXYZ(p.xyz);
		p.filterWeightSum = 1;
		p.splatXYZ[0] = p.splatXYZ[1] = p.splatXYZ[2] = 0;
	}
}

void Film::WriteImage(Float splatScale)
{
	std::vector<Float> image;
	for (int j = croppedPixelBound[0].y; j < croppedPixelBound[1].y; ++j)
	{
		for (int i = croppedPixelBound[0].x; i < croppedPixelBound[1].x; ++i)
		{
			Pixel &p = GetPixel(Point2i(i, j));
			Float rgb[3];
			XYZToRGB(p.xyz, rgb);
			if (p.filterWeightSum != 0)
			{
				Float invWeight = 1.0 / p.filterWeightSum;
				rgb[0] *= invWeight;
				rgb[1] *= invWeight;
				rgb[2] *= invWeight;
			}

			//添加splatXYZ内的能量
			Float splatRGB[3];
			Float splatXYZ[3] = {p.splatXYZ[0], p.splatXYZ[1], p.splatXYZ[2]};
			XYZToRGB(splatXYZ, splatRGB);

			rgb[0] += splatRGB[0] * splatScale;
			rgb[1] += splatRGB[1] * splatScale;
			rgb[2] += splatRGB[2] * splatScale;

			image.push_back(rgb[0]);
			image.push_back(rgb[1]);
			image.push_back(rgb[2]);
		}
	}
	Vector2i resolution = croppedPixelBound.Diagonal();
	WriteImageToFile(fileName.c_str(), &image[0], resolution.x, resolution.y);
}

void Film::AddSplat(const Point2f &p, Spectrum L)
{
	if (L.HasNaNs())
	{
		LWarning << "Ignoring splatted spectrum with NaN values at (" << p.x << "," << p.y << ")";
		return;
	}
	else if (L.y() < 0)
	{
		LWarning << "Ignoring splatted spectrum with negative luminance" << L.y() << "at (" << p.x << "," << p.y << ")";
		return;
	}
	else if (std::isinf(L.y()))
	{
		LWarning << "Ignoring splatted spectrum with infinite luminance at (" << p.x << "," << p.y << ")";
		return;
	}

	if (!InsideExclusive((Point2i)p, croppedPixelBound))
	{
		return;
	}

	if (L.y() > _maxSampleLuminance)
	{
		L = (_maxSampleLuminance / L.y()) * L;
	}

	auto &pixel = GetPixel((Point2i)p);
	Float xyz[3];
	L.ToXYZ(xyz);
	for (int i = 0; i < 3; ++i)
	{
		pixel.splatXYZ[i].Add(xyz[i]);
	}
}

void FilmTile::AddSample(const Point2f &pFilm, Spectrum L, Float weight)
{
	Assert(weight > 0.0f);
	//Assert(InsideExclusive(pFilm,_pixelBound));
	//贡献值大于最大值，需要scale
	if (L.y() > _maxSampleLuminance)
	{
		L *= (_maxSampleLuminance / L.y());
	}

	//计算过滤范围
	Point2f pFilmDiscrete = pFilm - Vector2f(0.5f, 0.5f);
	Point2i pMin = Point2i(Ceil(pFilmDiscrete - _filterRadius));
	Point2i pMax = Point2i(Floor(pFilmDiscrete + _filterRadius)) + Point2i(1, 1);
	pMin = Max(_pixelBound.minPoint, pMin);
	pMax = Min(_pixelBound.maxPoint, pMax);
	//预计算row和col上的偏移
	int *ifx = ALLOCA(int, pMax.x - pMin.x);
	for (int x = pMin.x; x < pMax.x; ++x)
	{
		Float offsetX = std::abs(x - pFilmDiscrete.x) * _invFilterRadius.x * _filterTableWidth;
		ifx[x - pMin.x] = std::min((int)std::floor(offsetX),
								   _filterTableWidth - 1);
	}
	int *ify = ALLOCA(int, pMax.y - pMin.y);
	for (int y = pMin.y; y < pMax.y; ++y)
	{
		Float offsetY = std::abs(y - pFilmDiscrete.y) * _invFilterRadius.y * _filterTableWidth;
		ify[y - pMin.y] = std::min((int)std::floor(offsetY),
								   _filterTableWidth - 1);
	}

	for (int y = pMin.y; y < pMax.y; ++y)
	{
		for (int x = pMin.x; x < pMax.x; ++x)
		{
			int filterTableIndex = ify[y - pMin.y] * _filterTableWidth + ifx[x - pMin.x]; //filter表索引
			Float fiterWeight = _filterTable[filterTableIndex];							  //过滤器权重
			FilmTilePixel &pixel = GetPixel(Point2i(x, y));
			pixel.contribSum += L * weight * fiterWeight;
			pixel.filterWeightSum += fiterWeight;
		}
	}
}

std::unique_ptr<FilmTile> Film::GetFilmTile(const Bound2i &sampleBounds)
{
	Vector2f half(0.5f, 0.5f);
	Bound2f floatBounds = (Bound2f)sampleBounds;
	Point2i p0 = (Point2i)Ceil(floatBounds.minPoint - half - filter->radius);
	Point2i p1 = (Point2i)Floor(floatBounds.maxPoint - half + filter->radius) + Point2i(1, 1);
	Bound2i pixelBound = Intersect(Bound2i(p0, p1), croppedPixelBound);
	return std::unique_ptr<FilmTile>(new FilmTile(pixelBound, filter->radius, _filterTable, filterTableWidth, _maxSampleLuminance));
}

void Film::MergeFilmTile(std::unique_ptr<FilmTile> tile)
{
	//获取互斥锁
	std::lock_guard<std::mutex> lock(_mutex);
	for (Point2i pixelPos : tile->GetPixelBound())
	{
		const FilmTilePixel &tilePixel = tile->GetPixel(pixelPos);
		Pixel &pixel = GetPixel(pixelPos);
		Float xyz[3];
		tilePixel.contribSum.ToXYZ(xyz);
		for (int i = 0; i < 3; ++i)
		{
			pixel.xyz[i] += xyz[i];
		}
		pixel.filterWeightSum += tilePixel.filterWeightSum;
	}
}

//{filename:string,xresolution:int,yresolution:int,cropwindow:Float[4],maxsampleluminance:Float}
Film *CreateFilm(const ParamSet &params, std::unique_ptr<Filter> filter)
{
	std::string filename = params.FindOneString("filename", "");
	if (RaidenOptions.imageFile != "")
	{
		if (filename != "")
		{
			LWarning << "ingore commandline filename:" << RaidenOptions.imageFile.c_str() << ",use descriptionfile filename:" << filename.c_str();
		}
		else
		{
			filename = RaidenOptions.imageFile;
		}
	}

	if (filename == "")
	{
		filename = "default.png";
	}
	else
	{
		bool isSupported=IsImageFormatSupported(filename.c_str());
		if(!isSupported){
			LError<<"file format '"<<filename<<"' is not supported!";
			exit(-1);
		}
	}

	int xres = params.FindOneInt("xresolution", 1280);
	int yres = params.FindOneInt("yresolution", 720);
	Bound2f crop(Point2f(0, 0), Point2f(1, 1));
	int cwi;
	const Float *cr = params.FindFloat("cropwindow", &cwi);
	if (cr && cwi == 4)
	{
		crop.minPoint.x = Clamp(std::min(cr[0], cr[1]), 0.0f, 1.0f);
		crop.maxPoint.x = Clamp(std::max(cr[0], cr[1]), 0.0f, 1.0f);
		crop.minPoint.y = Clamp(std::min(cr[2], cr[3]), 0.0f, 1.0f);
		crop.maxPoint.y = Clamp(std::max(cr[2], cr[3]), 0.0f, 1.0f);
	}
	else if (cr)
	{
		LError << "cropwindow need four values, and " << cwi << " for now.";
	}
	Float maxSampleLuminance = params.FindOneFloat("maxsampleluminance",
												   Infinity);
	Debug("[CreateFilm][ res:" << Point2i(xres, yres) << ",croppedPixelBound:" << crop << ".]");

	return new Film(Point2i(xres, yres), crop, std::move(filter),
					filename, maxSampleLuminance);
}
<|endoftext|>


<commit_before>#include "ofxJamoma.h"
#include "gorgone.h"

void ofxJamoma::setup(void* parent, string name, string masterIp)
{
  mParent = TTPtr(parent);
  mAppLocalName = name;
  mAppRemoteName = "master";
  mAppRemoteName2 = "laser-1";
  mAppRemoteIp = masterIp;
  setupJamomaApp();
  registerJamomaParam();
}

void ofxJamoma::exit()
{
}

void ofxJamoma::setupJamomaApp(){
    TTValue     args, v, out, none;
    TTAddress   address;
    TTErr       err;

    TTLogMessage("\n*** Initialisation of Modular environnement ***\n");
    /////////////////////////////////////////////////////////////////////

    // Init the Modular library (passing the folder path where all the dylibs are)
    TTModularInit("/usr/local/jamoma/lib/jamoma/");

    // Create an application manager
    mApplicationManager = TTObject("ApplicationManager");

    TTLogMessage("\n*** Creation of %s and %s applications ***\n", mAppLocalName.c_str(), mAppRemoteName.c_str());
    ////////////////////////////////////////////////////////////////////////////////

    // Create a local application called "gorgone-1" and get it back
    mApplicationLocal = mApplicationManager.send("ApplicationInstantiateLocal", mAppLocalName.c_str());
    mApplicationRemote = mApplicationManager.send("ApplicationInstantiateDistant", mAppRemoteName.c_str());
    mApplicationRemote2 = mApplicationManager.send("ApplicationInstantiateDistant", mAppRemoteName2.c_str());

    // Get registered application names
    mApplicationManager.get("applicationNames", out);
    for (TTElementIter it = out.begin() ; it != out.end() ; it++) {
        TTSymbol name = TTElement(*it);
        TTLogMessage("%s application is well registered into the application manager \n", name.c_str());
    }

    TTLogMessage("\n*** Enable Minuit communication ***\n");
    ////////////////////////////////////////////////////////////////////////

    // Create a Minuit protocol unit
    err = mApplicationManager.send("ProtocolInstantiate", "Minuit", out);

    if (err) {
        TTLogError("Error : can't create Minuit protocol unit \n");
        return;
    }
    else
        mProtocolMinuit = out[0];

    // Get Minuit Protocol attribute names and types
    mProtocolMinuit.get("parameterNames", out);
    for (TTElementIter it = out.begin() ; it != out.end() ; it++) {
        TTSymbol name = TTElement(*it);
        TTSymbol type = mProtocolMinuit.attributeType(name);
        TTLogMessage("Minuit %s parameter is a %s \n", name.c_str(), type.c_str());
    }

    // Register mymyRemoteAppApp and myRemoteApp to the Minuit protocol
    mProtocolMinuit.send("ApplicationRegister", mAppLocalName.c_str(), out);
    mProtocolMinuit.send("ApplicationRegister", mAppRemoteName.c_str(), out);
    mProtocolMinuit.send("ApplicationRegister", mAppRemoteName2.c_str(), out);

    // Select gorgone-1 to set its protocol parameters
    mProtocolMinuit.send("ApplicationSelect", mAppLocalName.c_str(), out);
    mProtocolMinuit.set("port", 9998);
    mProtocolMinuit.set("ip", "127.0.0.1");

    // Select gorgone-1 to set its protocol parameters
    mProtocolMinuit.send("ApplicationSelect", mAppRemoteName2.c_str(), out);
    mProtocolMinuit.set("port", 9999);
    mProtocolMinuit.set("ip", "127.0.0.1");

    // Select myRemoteApp to set its protocol parameters
    mProtocolMinuit.send("ApplicationSelect", mAppRemoteName.c_str(), out);
    mProtocolMinuit.set("port", 13579);
    mProtocolMinuit.set("ip", mAppRemoteIp.c_str());

    // Get Minuit parameters for each registered application
    mProtocolMinuit.get("applicationNames", out);
    for (TTElementIter it = out.begin() ; it != out.end() ; it++) {
        TTSymbol name = TTElement(*it);

        mProtocolMinuit.send("ApplicationSelect", name, out);
        TTLogMessage("Minuit setup for %s application : \n", name.c_str());

        mProtocolMinuit.get("ip", v);
        TTSymbol ip = v[0];
        TTLogMessage("- ip = %s \n", ip.c_str());

        mProtocolMinuit.get("port", v);
        TTUInt16 port = v[0];
        TTLogMessage("- port = %d \n", port);
    }

    // Enable Minuit communication
    mProtocolMinuit.send("Run");

    TTLogMessage("\n*** Current Protocol Setup ***\n");
    // Get protocol names
    mApplicationManager.get("protocolNames", out);
    for (TTElementIter it = out.begin() ; it != out.end() ; it++) {
        TTSymbol name = TTElement(*it);
        TTLogMessage("%s protocol is well registered into the application manager \n", name.c_str());
    }
}

void ofxJamoma::registerJamomaParam(){
    TTValue     args, v, out, none;
    TTAddress   address;
    TTErr       err;
      TTLogMessage("\n*** Creation and registration of a decimal parameter ***\n");
    /////////////////////////////////////////////////////////

    // Create a decimal parameter data and set its callback function and baton and some attributes
    mTrackEnableParameter = TTObject("Data", "parameter");

    // Setup the callback mechanism to get the value back
    args = TTValue(mParent, mTrackEnableParameter);
    mTrackEnableParameter.set("baton", args);
    mTrackEnableParameter.set("function", TTPtr(&DemoAppDataReturnValueCallback));

    // Setup the data attributes depending of its use inside the application
    mTrackEnableParameter.set("type", "boolean");
    mTrackEnableParameter.set("description", "start/stop tracking");

    // Register the parameter data into gorgone-1 at an address
    args = TTValue("/tracking/enable", mTrackEnableParameter);
    err = mApplicationLocal.send("ObjectRegister", args, out);

    if (err)
        TTLogError("Error : can't register data at /tracking/enable address \n");

    else {
        address = out[0];
        TTLogMessage("\n /tracking/enable : effective registration address is %s \n", address.c_str());
    }

        // Create a decimal parameter data and set its callback function and baton and some attributes
    mDrawingEnableParameter = TTObject("Data", "parameter");

    // Setup the callback mechanism to get the value back
    args = TTValue(mParent, mDrawingEnableParameter);
    mDrawingEnableParameter.set("baton", args);
    mDrawingEnableParameter.set("function", TTPtr(&DemoAppDataReturnValueCallback));

    // Setup the data attributes depending of its use inside the application
    mDrawingEnableParameter.set("type", "boolean");
    mDrawingEnableParameter.set("description", "start/stop drawing");

    // Register the parameter data into gorgone-1 at an address
    args = TTValue("/drawing/enable", mDrawingEnableParameter);
    err = mApplicationLocal.send("ObjectRegister", args, out);

    if (err)
        TTLogError("Error : can't register data at /drawing/enable address \n");

    else {
        address = out[0];
        TTLogMessage("\n /drawing/enable : effective registration address is %s \n", address.c_str());
    }

    // Create a new boolean parameter
    mComputeIrisCodeParameter = TTObject("Data", "parameter");

    // Setup the callback mechanism to get the value back
    args = TTValue(mParent, mComputeIrisCodeParameter);
    mComputeIrisCodeParameter.set("baton", args);
    mComputeIrisCodeParameter.set("function", TTPtr(&DemoAppDataReturnValueCallback));

    // Setup the data attributes depending of its use inside the application
    mComputeIrisCodeParameter.set("type", "boolean");
    mComputeIrisCodeParameter.set("description", "start/stop drawing");

    // Register the parameter data into gorgone-1 at an address
    args = TTValue("/tracking/computecode", mComputeIrisCodeParameter);
    err = mApplicationLocal.send("ObjectRegister", args, out);

    if (err)
        TTLogError("Error : can't register data at /tracking/computecode address \n");

    else {
        address = out[0];
        TTLogMessage("\n /tracking/computecode : effective registration address is %s \n", address.c_str());
    }

    // Create a new array parameter
    mDrawingCoeffParameter = TTObject("Data", "parameter");

    // Setup the callback mechanism to get the value back
    args = TTValue(mParent, mDrawingCoeffParameter);
    mDrawingCoeffParameter.set("baton", args);
    mDrawingCoeffParameter.set("function", TTPtr(&DemoAppDataReturnValueCallback));

    // Setup the data attributes depending of its use inside the application
    mDrawingCoeffParameter.set("type", "array");
    mDrawingCoeffParameter.set("description", "shape coefficient");

    // Register the parameter data into gorgone-1 at an address
    args = TTValue("/drawing/coeff", mDrawingCoeffParameter);
    err = mApplicationLocal.send("ObjectRegister", args, out);

    if (err)
        TTLogError("Error : can't register data at /drawing/coeff address \n");

    else {
        address = out[0];
        TTLogMessage("\n /drawing/coeff : effective registration address is %s \n", address.c_str());
    }

    // Create a new array return for iris code
    mTrackingIrisCodeReturn = TTObject("Data", "return");

    // Setup the callback mechanism to get the value back
    args = TTValue(mParent, mTrackingIrisCodeReturn);
    mTrackingIrisCodeReturn.set("baton", args);
    mTrackingIrisCodeReturn.set("function", TTPtr(&DemoAppDataReturnValueCallback));

    // Setup the data attributes depending of its use inside the application
    mTrackingIrisCodeReturn.set("type", "array");
    mTrackingIrisCodeReturn.set("description", "iris code");

    // Register the parameter data into gorgone-1 at an address
    args = TTValue("/tracking/iriscode", mTrackingIrisCodeReturn);
    err = mApplicationLocal.send("ObjectRegister", args, out);

    if (err)
        TTLogError("Error : can't register data at /tracking/iriscode address \n");

    else {
        address = out[0];
        TTLogMessage("\n /tracking/iriscode : effective registration address is %s \n", address.c_str());
    }

        // Create a new array return for drawing shape
    mDrawingShapeXReturn = TTObject("Data", "return");

    // Setup the callback mechanism to get the value back
    args = TTValue(mParent, mDrawingShapeXReturn);
    mDrawingShapeXReturn.set("baton", args);
    mDrawingShapeXReturn.set("function", TTPtr(&DemoAppDataReturnValueCallback));

    // Setup the data attributes depending of its use inside the application
    mDrawingShapeXReturn.set("type", "array");
    mDrawingShapeXReturn.set("description", "drawing shape X");

    // Register the parameter data into gorgone-1 at an address
    args = TTValue("/drawing/shape/x", mDrawingShapeXReturn);
    err = mApplicationLocal.send("ObjectRegister", args, out);

    if (err)
        TTLogError("Error : can't register data at /drawing/shape/x address \n");

    else {
        address = out[0];
        TTLogMessage("\n /drawing/shape/x : effective registration address is %s \n", address.c_str());
    }

            // Create a new array return for drawing shape
    mDrawingShapeYReturn = TTObject("Data", "return");

    // Setup the callback mechanism to get the value back
    args = TTValue(mParent, mDrawingShapeYReturn);
    mDrawingShapeYReturn.set("baton", args);
    mDrawingShapeYReturn.set("function", TTPtr(&DemoAppDataReturnValueCallback));

    // Setup the data attributes depending of its use inside the application
    mDrawingShapeYReturn.set("type", "array");
    mDrawingShapeYReturn.set("description", "Drawing shape Y");

    // Register the parameter data into gorgone-1 at an address
    args = TTValue("/drawing/shape/y", mDrawingShapeYReturn);
    err = mApplicationLocal.send("ObjectRegister", args, out);

    if (err)
        TTLogError("Error : can't register data at /drawing/shape/y address \n");

    else {
        address = out[0];
        TTLogMessage("\n /drawing/shape/y : effective registration address is %s \n", address.c_str());
    }

    // Create a new brightness parameter
    mTrackingLedBrightness = TTObject("Data", "parameter");

    // Setup the callback mechanism to get the value back
    args = TTValue(mParent, mTrackingLedBrightness);
    mTrackingLedBrightness.set("baton", args);
    mTrackingLedBrightness.set("function", TTPtr(&DemoAppDataReturnValueCallback));

    // Setup the data attributes depending of its use inside the application
    mTrackingLedBrightness.set("type", "integer");
    mTrackingLedBrightness.set("description", "LED brightness");
    mTrackingLedBrightness.set("rangeBounds", TTValue(0, 1023));
    mTrackingLedBrightness.set("rangeClipmode", "both");

    // Register the parameter data into gorgone-1 at an address
    args = TTValue("/tracking/ledbrightness", mTrackingLedBrightness);
    err = mApplicationLocal.send("ObjectRegister", args, out);

    if (err)
        TTLogError("Error : can't register data at /tracking/ledbrightness address \n");

    else {
        address = out[0];
        TTLogMessage("\n /tracking/ledbrightness : effective registration address is %s \n", address.c_str());
    }

    // Create a new brightness parameter
    mTrackingLaserBrightness = TTObject("Data", "parameter");

    // Setup the callback mechanism to get the value back
    args = TTValue(mParent, mTrackingLaserBrightness);
    mTrackingLaserBrightness.set("baton", args);
    mTrackingLaserBrightness.set("function", TTPtr(&DemoAppDataReturnValueCallback));

    // Setup the data attributes depending of its use inside the application
    mTrackingLaserBrightness.set("type", "decimal");
    mTrackingLaserBrightness.set("description", "laser brightness");
    mTrackingLaserBrightness.set("rangeBounds", TTValue(0., 100.));
    mTrackingLaserBrightness.set("rangeClipmode", "both");

    // Register the parameter data into gorgone-1 at an address
    args = TTValue("/tracking/laserbrightness", mTrackingLaserBrightness);
    err = mApplicationLocal.send("ObjectRegister", args, out);

    if (err)
        TTLogError("Error : can't register data at /tracking/laserbrightness address \n");

    else {
        address = out[0];
        TTLogMessage("\n /tracking/laserbrightness : effective registration address is %s \n", address.c_str());
    }
}

TTErr
DemoAppDataReturnValueCallback(const TTValue& baton, const TTValue& value)
{
    gorgone*  gorgoneApp = (gorgone*)TTPtr(baton[0]);
    TTObject    anObject = baton[1];

  // Reteive which data has been updated
    if (anObject.instance() == gorgoneApp->jamoma.mTrackEnableParameter.instance()) {

        gorgoneApp->bTracking = value[0];
        return kTTErrNone;
    }

    if (anObject.instance() == gorgoneApp->jamoma.mDrawingEnableParameter.instance()) {
        gorgoneApp->bDisplaying = value[0];
        return kTTErrNone;
    }

    if (anObject.instance() == gorgoneApp->jamoma.mComputeIrisCodeParameter.instance()) {
        gorgoneApp->bComputeCode = value[0];
        return kTTErrNone;
    }

    if (anObject.instance() == gorgoneApp->jamoma.mDrawingCoeffParameter.instance()) {
        gorgoneApp->svgInterp.coeff.clear();
        for (int i = 0; i < value.size(); i++)
            gorgoneApp->svgInterp.coeff.push_back(value[i]);
        gorgoneApp->svgInterp.multiInterpolation();
        return kTTErrNone;
    }

#ifdef TARGET_RASPBERRY_PI
    if (anObject.instance() == gorgoneApp->jamoma.mTrackingLedBrightness.instance()) {
        gorgoneApp->vidGrabber.led.setBrightness(value[0]);
        return kTTErrNone;
    }

    if (anObject.instance() == gorgoneApp->jamoma.mTrackingLaserBrightness.instance()) {
        gorgoneApp->setPwm(value[0]);
        return kTTErrNone;
    }

#endif

    return kTTErrGeneric;
}
<commit_msg>fix laser brightness address<commit_after>#include "ofxJamoma.h"
#include "gorgone.h"

void ofxJamoma::setup(void* parent, string name, string masterIp)
{
  mParent = TTPtr(parent);
  mAppLocalName = name;
  mAppRemoteName = "master";
  mAppRemoteName2 = "laser-1";
  mAppRemoteIp = masterIp;
  setupJamomaApp();
  registerJamomaParam();
}

void ofxJamoma::exit()
{
}

void ofxJamoma::setupJamomaApp(){
    TTValue     args, v, out, none;
    TTAddress   address;
    TTErr       err;

    TTLogMessage("\n*** Initialisation of Modular environnement ***\n");
    /////////////////////////////////////////////////////////////////////

    // Init the Modular library (passing the folder path where all the dylibs are)
    TTModularInit("/usr/local/jamoma/lib/jamoma/");

    // Create an application manager
    mApplicationManager = TTObject("ApplicationManager");

    TTLogMessage("\n*** Creation of %s and %s applications ***\n", mAppLocalName.c_str(), mAppRemoteName.c_str());
    ////////////////////////////////////////////////////////////////////////////////

    // Create a local application called "gorgone-1" and get it back
    mApplicationLocal = mApplicationManager.send("ApplicationInstantiateLocal", mAppLocalName.c_str());
    mApplicationRemote = mApplicationManager.send("ApplicationInstantiateDistant", mAppRemoteName.c_str());
    mApplicationRemote2 = mApplicationManager.send("ApplicationInstantiateDistant", mAppRemoteName2.c_str());

    // Get registered application names
    mApplicationManager.get("applicationNames", out);
    for (TTElementIter it = out.begin() ; it != out.end() ; it++) {
        TTSymbol name = TTElement(*it);
        TTLogMessage("%s application is well registered into the application manager \n", name.c_str());
    }

    TTLogMessage("\n*** Enable Minuit communication ***\n");
    ////////////////////////////////////////////////////////////////////////

    // Create a Minuit protocol unit
    err = mApplicationManager.send("ProtocolInstantiate", "Minuit", out);

    if (err) {
        TTLogError("Error : can't create Minuit protocol unit \n");
        return;
    }
    else
        mProtocolMinuit = out[0];

    // Get Minuit Protocol attribute names and types
    mProtocolMinuit.get("parameterNames", out);
    for (TTElementIter it = out.begin() ; it != out.end() ; it++) {
        TTSymbol name = TTElement(*it);
        TTSymbol type = mProtocolMinuit.attributeType(name);
        TTLogMessage("Minuit %s parameter is a %s \n", name.c_str(), type.c_str());
    }

    // Register mymyRemoteAppApp and myRemoteApp to the Minuit protocol
    mProtocolMinuit.send("ApplicationRegister", mAppLocalName.c_str(), out);
    mProtocolMinuit.send("ApplicationRegister", mAppRemoteName.c_str(), out);
    mProtocolMinuit.send("ApplicationRegister", mAppRemoteName2.c_str(), out);

    // Select gorgone-1 to set its protocol parameters
    mProtocolMinuit.send("ApplicationSelect", mAppLocalName.c_str(), out);
    mProtocolMinuit.set("port", 9998);
    mProtocolMinuit.set("ip", "127.0.0.1");

    // Select gorgone-1 to set its protocol parameters
    mProtocolMinuit.send("ApplicationSelect", mAppRemoteName2.c_str(), out);
    mProtocolMinuit.set("port", 9999);
    mProtocolMinuit.set("ip", "127.0.0.1");

    // Select myRemoteApp to set its protocol parameters
    mProtocolMinuit.send("ApplicationSelect", mAppRemoteName.c_str(), out);
    mProtocolMinuit.set("port", 13579);
    mProtocolMinuit.set("ip", mAppRemoteIp.c_str());

    // Get Minuit parameters for each registered application
    mProtocolMinuit.get("applicationNames", out);
    for (TTElementIter it = out.begin() ; it != out.end() ; it++) {
        TTSymbol name = TTElement(*it);

        mProtocolMinuit.send("ApplicationSelect", name, out);
        TTLogMessage("Minuit setup for %s application : \n", name.c_str());

        mProtocolMinuit.get("ip", v);
        TTSymbol ip = v[0];
        TTLogMessage("- ip = %s \n", ip.c_str());

        mProtocolMinuit.get("port", v);
        TTUInt16 port = v[0];
        TTLogMessage("- port = %d \n", port);
    }

    // Enable Minuit communication
    mProtocolMinuit.send("Run");

    TTLogMessage("\n*** Current Protocol Setup ***\n");
    // Get protocol names
    mApplicationManager.get("protocolNames", out);
    for (TTElementIter it = out.begin() ; it != out.end() ; it++) {
        TTSymbol name = TTElement(*it);
        TTLogMessage("%s protocol is well registered into the application manager \n", name.c_str());
    }
}

void ofxJamoma::registerJamomaParam(){
    TTValue     args, v, out, none;
    TTAddress   address;
    TTErr       err;
      TTLogMessage("\n*** Creation and registration of a decimal parameter ***\n");
    /////////////////////////////////////////////////////////

    // Create a decimal parameter data and set its callback function and baton and some attributes
    mTrackEnableParameter = TTObject("Data", "parameter");

    // Setup the callback mechanism to get the value back
    args = TTValue(mParent, mTrackEnableParameter);
    mTrackEnableParameter.set("baton", args);
    mTrackEnableParameter.set("function", TTPtr(&DemoAppDataReturnValueCallback));

    // Setup the data attributes depending of its use inside the application
    mTrackEnableParameter.set("type", "boolean");
    mTrackEnableParameter.set("description", "start/stop tracking");

    // Register the parameter data into gorgone-1 at an address
    args = TTValue("/tracking/enable", mTrackEnableParameter);
    err = mApplicationLocal.send("ObjectRegister", args, out);

    if (err)
        TTLogError("Error : can't register data at /tracking/enable address \n");

    else {
        address = out[0];
        TTLogMessage("\n /tracking/enable : effective registration address is %s \n", address.c_str());
    }

        // Create a decimal parameter data and set its callback function and baton and some attributes
    mDrawingEnableParameter = TTObject("Data", "parameter");

    // Setup the callback mechanism to get the value back
    args = TTValue(mParent, mDrawingEnableParameter);
    mDrawingEnableParameter.set("baton", args);
    mDrawingEnableParameter.set("function", TTPtr(&DemoAppDataReturnValueCallback));

    // Setup the data attributes depending of its use inside the application
    mDrawingEnableParameter.set("type", "boolean");
    mDrawingEnableParameter.set("description", "start/stop drawing");

    // Register the parameter data into gorgone-1 at an address
    args = TTValue("/drawing/enable", mDrawingEnableParameter);
    err = mApplicationLocal.send("ObjectRegister", args, out);

    if (err)
        TTLogError("Error : can't register data at /drawing/enable address \n");

    else {
        address = out[0];
        TTLogMessage("\n /drawing/enable : effective registration address is %s \n", address.c_str());
    }

    // Create a new boolean parameter
    mComputeIrisCodeParameter = TTObject("Data", "parameter");

    // Setup the callback mechanism to get the value back
    args = TTValue(mParent, mComputeIrisCodeParameter);
    mComputeIrisCodeParameter.set("baton", args);
    mComputeIrisCodeParameter.set("function", TTPtr(&DemoAppDataReturnValueCallback));

    // Setup the data attributes depending of its use inside the application
    mComputeIrisCodeParameter.set("type", "boolean");
    mComputeIrisCodeParameter.set("description", "start/stop drawing");

    // Register the parameter data into gorgone-1 at an address
    args = TTValue("/tracking/computecode", mComputeIrisCodeParameter);
    err = mApplicationLocal.send("ObjectRegister", args, out);

    if (err)
        TTLogError("Error : can't register data at /tracking/computecode address \n");

    else {
        address = out[0];
        TTLogMessage("\n /tracking/computecode : effective registration address is %s \n", address.c_str());
    }

    // Create a new array parameter
    mDrawingCoeffParameter = TTObject("Data", "parameter");

    // Setup the callback mechanism to get the value back
    args = TTValue(mParent, mDrawingCoeffParameter);
    mDrawingCoeffParameter.set("baton", args);
    mDrawingCoeffParameter.set("function", TTPtr(&DemoAppDataReturnValueCallback));

    // Setup the data attributes depending of its use inside the application
    mDrawingCoeffParameter.set("type", "array");
    mDrawingCoeffParameter.set("description", "shape coefficient");

    // Register the parameter data into gorgone-1 at an address
    args = TTValue("/drawing/coeff", mDrawingCoeffParameter);
    err = mApplicationLocal.send("ObjectRegister", args, out);

    if (err)
        TTLogError("Error : can't register data at /drawing/coeff address \n");

    else {
        address = out[0];
        TTLogMessage("\n /drawing/coeff : effective registration address is %s \n", address.c_str());
    }

    // Create a new array return for iris code
    mTrackingIrisCodeReturn = TTObject("Data", "return");

    // Setup the callback mechanism to get the value back
    args = TTValue(mParent, mTrackingIrisCodeReturn);
    mTrackingIrisCodeReturn.set("baton", args);
    mTrackingIrisCodeReturn.set("function", TTPtr(&DemoAppDataReturnValueCallback));

    // Setup the data attributes depending of its use inside the application
    mTrackingIrisCodeReturn.set("type", "array");
    mTrackingIrisCodeReturn.set("description", "iris code");

    // Register the parameter data into gorgone-1 at an address
    args = TTValue("/tracking/iriscode", mTrackingIrisCodeReturn);
    err = mApplicationLocal.send("ObjectRegister", args, out);

    if (err)
        TTLogError("Error : can't register data at /tracking/iriscode address \n");

    else {
        address = out[0];
        TTLogMessage("\n /tracking/iriscode : effective registration address is %s \n", address.c_str());
    }

        // Create a new array return for drawing shape
    mDrawingShapeXReturn = TTObject("Data", "return");

    // Setup the callback mechanism to get the value back
    args = TTValue(mParent, mDrawingShapeXReturn);
    mDrawingShapeXReturn.set("baton", args);
    mDrawingShapeXReturn.set("function", TTPtr(&DemoAppDataReturnValueCallback));

    // Setup the data attributes depending of its use inside the application
    mDrawingShapeXReturn.set("type", "array");
    mDrawingShapeXReturn.set("description", "drawing shape X");

    // Register the parameter data into gorgone-1 at an address
    args = TTValue("/drawing/shape/x", mDrawingShapeXReturn);
    err = mApplicationLocal.send("ObjectRegister", args, out);

    if (err)
        TTLogError("Error : can't register data at /drawing/shape/x address \n");

    else {
        address = out[0];
        TTLogMessage("\n /drawing/shape/x : effective registration address is %s \n", address.c_str());
    }

            // Create a new array return for drawing shape
    mDrawingShapeYReturn = TTObject("Data", "return");

    // Setup the callback mechanism to get the value back
    args = TTValue(mParent, mDrawingShapeYReturn);
    mDrawingShapeYReturn.set("baton", args);
    mDrawingShapeYReturn.set("function", TTPtr(&DemoAppDataReturnValueCallback));

    // Setup the data attributes depending of its use inside the application
    mDrawingShapeYReturn.set("type", "array");
    mDrawingShapeYReturn.set("description", "Drawing shape Y");

    // Register the parameter data into gorgone-1 at an address
    args = TTValue("/drawing/shape/y", mDrawingShapeYReturn);
    err = mApplicationLocal.send("ObjectRegister", args, out);

    if (err)
        TTLogError("Error : can't register data at /drawing/shape/y address \n");

    else {
        address = out[0];
        TTLogMessage("\n /drawing/shape/y : effective registration address is %s \n", address.c_str());
    }

    // Create a new brightness parameter
    mTrackingLedBrightness = TTObject("Data", "parameter");

    // Setup the callback mechanism to get the value back
    args = TTValue(mParent, mTrackingLedBrightness);
    mTrackingLedBrightness.set("baton", args);
    mTrackingLedBrightness.set("function", TTPtr(&DemoAppDataReturnValueCallback));

    // Setup the data attributes depending of its use inside the application
    mTrackingLedBrightness.set("type", "integer");
    mTrackingLedBrightness.set("description", "LED brightness");
    mTrackingLedBrightness.set("rangeBounds", TTValue(0, 1023));
    mTrackingLedBrightness.set("rangeClipmode", "both");

    // Register the parameter data into gorgone-1 at an address
    args = TTValue("/tracking/ledbrightness", mTrackingLedBrightness);
    err = mApplicationLocal.send("ObjectRegister", args, out);

    if (err)
        TTLogError("Error : can't register data at /tracking/ledbrightness address \n");

    else {
        address = out[0];
        TTLogMessage("\n /tracking/ledbrightness : effective registration address is %s \n", address.c_str());
    }

    // Create a new brightness parameter
    mTrackingLaserBrightness = TTObject("Data", "parameter");

    // Setup the callback mechanism to get the value back
    args = TTValue(mParent, mTrackingLaserBrightness);
    mTrackingLaserBrightness.set("baton", args);
    mTrackingLaserBrightness.set("function", TTPtr(&DemoAppDataReturnValueCallback));

    // Setup the data attributes depending of its use inside the application
    mTrackingLaserBrightness.set("type", "decimal");
    mTrackingLaserBrightness.set("description", "laser brightness");
    mTrackingLaserBrightness.set("rangeBounds", TTValue(0., 100.));
    mTrackingLaserBrightness.set("rangeClipmode", "both");

    // Register the parameter data into gorgone-1 at an address
    args = TTValue("/drawing/laserbrightness", mTrackingLaserBrightness);
    err = mApplicationLocal.send("ObjectRegister", args, out);

    if (err)
        TTLogError("Error : can't register data at /drawing/laserbrightness address \n");

    else {
        address = out[0];
        TTLogMessage("\n /drawing/laserbrightness : effective registration address is %s \n", address.c_str());
    }
}

TTErr
DemoAppDataReturnValueCallback(const TTValue& baton, const TTValue& value)
{
    gorgone*  gorgoneApp = (gorgone*)TTPtr(baton[0]);
    TTObject    anObject = baton[1];

  // Reteive which data has been updated
    if (anObject.instance() == gorgoneApp->jamoma.mTrackEnableParameter.instance()) {

        gorgoneApp->bTracking = value[0];
        return kTTErrNone;
    }

    if (anObject.instance() == gorgoneApp->jamoma.mDrawingEnableParameter.instance()) {
        gorgoneApp->bDisplaying = value[0];
        return kTTErrNone;
    }

    if (anObject.instance() == gorgoneApp->jamoma.mComputeIrisCodeParameter.instance()) {
        gorgoneApp->bComputeCode = value[0];
        return kTTErrNone;
    }

    if (anObject.instance() == gorgoneApp->jamoma.mDrawingCoeffParameter.instance()) {
        gorgoneApp->svgInterp.coeff.clear();
        for (int i = 0; i < value.size(); i++)
            gorgoneApp->svgInterp.coeff.push_back(value[i]);
        gorgoneApp->svgInterp.multiInterpolation();
        return kTTErrNone;
    }

#ifdef TARGET_RASPBERRY_PI
    if (anObject.instance() == gorgoneApp->jamoma.mTrackingLedBrightness.instance()) {
        gorgoneApp->vidGrabber.led.setBrightness(value[0]);
        return kTTErrNone;
    }

    if (anObject.instance() == gorgoneApp->jamoma.mTrackingLaserBrightness.instance()) {
        gorgoneApp->setPwm(value[0]);
        return kTTErrNone;
    }

#endif

    return kTTErrGeneric;
}
<|endoftext|>


<commit_before>/*
** Copyright 2011-2014 Merethis
**
** This file is part of Centreon Broker.
**
** Centreon Broker is free software: you can redistribute it and/or
** modify it under the terms of the GNU General Public License version 2
** as published by the Free Software Foundation.
**
** Centreon Broker 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 Centreon Broker. If not, see
** <http://www.gnu.org/licenses/>.
*/

#include <sstream>
#include "com/centreon/broker/influxdb/json_printer.hh"

using namespace com::centreon::broker::influxdb;

/**
 *  Default constructor.
 */
json_printer::json_printer() {
  _data.reserve(128);
}

/**
 *  Destructor.
 */
json_printer::~json_printer() {

}

/**
 *  Copy constructor.
 *
 *  @param[in] other  The object to copy.
 */
json_printer::json_printer(json_printer const& other) {
  _data = other._data;
}

/**
 *  Assignment operator.
 *
 *  @param[in] other  The object to copy.
 *
 *  @return           A reference to this object.
 */
json_printer& json_printer::operator=(json_printer const& other) {
  if (this != &other) {
    _data = other._data;
  }
  return (*this);
}

/**
 *  Get the resulting string.
 *
 *  @return  The resulting string.
 */
std::string const& json_printer::get_data() const {
  return (_data);
}

/**
 *  Get the size of the resulting string.
 *
 *  @return The size of the resulting string.
 */
size_t json_printer::get_size() const {
  return (_data.size());
}

static void add_tag(std::string& data, std::string const& name) {
  if (!name.empty())
    data.append("\"").append(name).append("\":");
}

/**
 *  Open an object.
 *
 *  @param[in] name  The name of the object.
 *
 *  @return          A reference to this object.
 */
json_printer& json_printer::open_object(std::string const& name) {
  add_tag(_data, name);
  _data.append("{");
  return (*this);
}

/**
 *  Close an object.
 *
 *  @return          A reference to this object.
 */
json_printer& json_printer::close_object() {
  _data.append("},");
  return (*this);
}

/**
 *  Open an array.
 *
 *  @param[in] name  The name of the array.
 *
 *  @return          A reference to this object.
 */
json_printer& json_printer::open_array(std::string const& name) {
  add_tag(_data, name);
  _data.append("[");
  return (*this);
}

/**
 *  Close an object.
 *
 *  @return          A reference to this object.
 */
json_printer& json_printer::close_array() {
  _data.append("]");
  return (*this);
}

/**
 *  Add a string value.
 *
 *  @param[in] name   The name of the value.
 *  @param[in] value  The value.
 *
 *  @return           A reference to this object.
 */
json_printer& json_printer::add_string(
                std::string const& name,
                std::string const& value) {
  add_tag(_data, name);
  _data.append("\"").append(value).append("\",");
  return (*this);
}
<commit_msg>Influxdb: Manage trailing comas.<commit_after>/*
** Copyright 2011-2014 Merethis
**
** This file is part of Centreon Broker.
**
** Centreon Broker is free software: you can redistribute it and/or
** modify it under the terms of the GNU General Public License version 2
** as published by the Free Software Foundation.
**
** Centreon Broker 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 Centreon Broker. If not, see
** <http://www.gnu.org/licenses/>.
*/

#include <sstream>
#include "com/centreon/broker/influxdb/json_printer.hh"

using namespace com::centreon::broker::influxdb;

/**
 *  Default constructor.
 */
json_printer::json_printer() {
  _data.reserve(128);
}

/**
 *  Destructor.
 */
json_printer::~json_printer() {

}

/**
 *  Copy constructor.
 *
 *  @param[in] other  The object to copy.
 */
json_printer::json_printer(json_printer const& other) {
  _data = other._data;
}

/**
 *  Assignment operator.
 *
 *  @param[in] other  The object to copy.
 *
 *  @return           A reference to this object.
 */
json_printer& json_printer::operator=(json_printer const& other) {
  if (this != &other) {
    _data = other._data;
  }
  return (*this);
}

/**
 *  Get the resulting string.
 *
 *  @return  The resulting string.
 */
std::string const& json_printer::get_data() const {
  std::string& data = (const_cast<json_printer*>(this))->_data;
  if (!data.empty() && data[data.size() - 1] == ',')
    data[data.size() - 1] = ' ';
  return (_data);
}

/**
 *  Get the size of the resulting string.
 *
 *  @return The size of the resulting string.
 */
size_t json_printer::get_size() const {
  return (_data.size());
}

static void add_tag(std::string& data, std::string const& name) {
  if (!name.empty())
    data.append("\"").append(name).append("\":");
}

/**
 *  Open an object.
 *
 *  @param[in] name  The name of the object.
 *
 *  @return          A reference to this object.
 */
json_printer& json_printer::open_object(std::string const& name) {
  add_tag(_data, name);
  _data.append("{");
  return (*this);
}

/**
 *  Close an object.
 *
 *  @return          A reference to this object.
 */
json_printer& json_printer::close_object() {
  if (!_data.empty() && _data[_data.size() - 1] == ',')
    _data[_data.size() - 1] = ' ';
  _data.append("},");
  return (*this);
}

/**
 *  Open an array.
 *
 *  @param[in] name  The name of the array.
 *
 *  @return          A reference to this object.
 */
json_printer& json_printer::open_array(std::string const& name) {
  add_tag(_data, name);
  _data.append("[");
  return (*this);
}

/**
 *  Close an object.
 *
 *  @return          A reference to this object.
 */
json_printer& json_printer::close_array() {
  if (!_data.empty() && _data[_data.size() - 1] == ',')
    _data[_data.size() - 1] = ']';
  else
    _data.append("]");
  return (*this);
}

/**
 *  Add a string value.
 *
 *  @param[in] name   The name of the value.
 *  @param[in] value  The value.
 *
 *  @return           A reference to this object.
 */
json_printer& json_printer::add_string(
                std::string const& name,
                std::string const& value) {
  add_tag(_data, name);
  _data.append("\"").append(value).append("\",");
  return (*this);
}
<|endoftext|>


<commit_before>// Copyright (c) 2009-2010 Satoshi Nakamoto
// Copyright (c) 2009-2016 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#if defined(HAVE_CONFIG_H)
#include "config/bitcoin-config.h"
#endif

#include "chainparams.h"
#include "clientversion.h"
#include "compat.h"
#include "fs.h"
#include "rpc/server.h"
#include "init.h"
#include "noui.h"
#include "scheduler.h"
#include "util.h"
#include "httpserver.h"
#include "httprpc.h"
#include "utilstrencodings.h"

#include <boost/algorithm/string/predicate.hpp>
#include <boost/thread.hpp>

#include <stdio.h>

/* Introduction text for doxygen: */

/*! \mainpage Developer documentation
 *
 * \section intro_sec Introduction
 *
 * This is the developer documentation of the reference client for an experimental new digital currency called Bitcoin (https://www.bitcoin.org/),
 * which enables instant payments to anyone, anywhere in the world. Bitcoin uses peer-to-peer technology to operate
 * with no central authority: managing transactions and issuing money are carried out collectively by the network.
 *
 * The software is a community-driven open source project, released under the MIT license.
 *
 * \section Navigation
 * Use the buttons Namespaces, Classes or Files at the top of the page to start navigating the code.
 */

void WaitForShutdown(boost::thread_group* threadGroup)
{
    bool fShutdown = ShutdownRequested();
    // Tell the main threads to shutdown.
    while (!fShutdown)
    {
        MilliSleep(200);
        fShutdown = ShutdownRequested();
    }
    if (threadGroup)
    {
        Interrupt(*threadGroup);
        threadGroup->join_all();
    }
}

//////////////////////////////////////////////////////////////////////////////
//
// Start
//
bool AppInit(int argc, char* argv[])
{
    boost::thread_group threadGroup;
    CScheduler scheduler;

    bool fRet = false;

    //
    // Parameters
    //
    // If Qt is used, parameters/bitcoin.conf are parsed in qt/bitcoin.cpp's main()
    ParseParameters(argc, argv);

    // Process help and version before taking care about datadir
    if (IsArgSet("-?") || IsArgSet("-h") ||  IsArgSet("-help") || IsArgSet("-version"))
    {
        std::string strUsage = strprintf(_("%s Daemon"), _(PACKAGE_NAME)) + " " + _("version") + " " + FormatFullVersion() + "\n";

        if (IsArgSet("-version"))
        {
            strUsage += FormatParagraph(LicenseInfo());
        }
        else
        {
            strUsage += "\n" + _("Usage:") + "\n" +
                  "  bitcoind [options]                     " + strprintf(_("Start %s Daemon"), _(PACKAGE_NAME)) + "\n";

            strUsage += "\n" + HelpMessage(HMM_BITCOIND);
        }

        fprintf(stdout, "%s", strUsage.c_str());
        return true;
    }

    try
    {
        if (!fs::is_directory(GetDataDir(false)))
        {
            fprintf(stderr, "Error: Specified data directory \"%s\" does not exist.\n", GetArg("-datadir", "").c_str());
            return false;
        }
        try
        {
            ReadConfigFile(GetArg("-conf", BITCOIN_CONF_FILENAME));
        } catch (const std::exception& e) {
            fprintf(stderr,"Error reading configuration file: %s\n", e.what());
            return false;
        }
        // Check for -testnet or -regtest parameter (Params() calls are only valid after this clause)
        try {
            SelectParams(ChainNameFromCommandLine());
        } catch (const std::exception& e) {
            fprintf(stderr, "Error: %s\n", e.what());
            return false;
        }

        // Command-line RPC
        bool fCommandLine = false;
        for (int i = 1; i < argc; i++)
            if (!IsSwitchChar(argv[i][0]) && !boost::algorithm::istarts_with(argv[i], "bitcoin:"))
                fCommandLine = true;

        if (fCommandLine)
        {
            fprintf(stderr, "Error: There is no RPC client functionality in bitcoind anymore. Use the bitcoin-cli utility instead.\n");
            exit(EXIT_FAILURE);
        }
        // -server defaults to true for bitcoind but not for the GUI so do this here
        SoftSetBoolArg("-server", true);
        // Set this early so that parameter interactions go to console
        InitLogging();
        InitParameterInteraction();
        if (!AppInitBasicSetup())
        {
            // InitError will have been called with detailed error, which ends up on console
            exit(EXIT_FAILURE);
        }
        if (!AppInitParameterInteraction())
        {
            // InitError will have been called with detailed error, which ends up on console
            exit(EXIT_FAILURE);
        }
        if (!AppInitSanityChecks())
        {
            // InitError will have been called with detailed error, which ends up on console
            exit(EXIT_FAILURE);
        }
        if (GetBoolArg("-daemon", false))
        {
#if HAVE_DECL_DAEMON
            fprintf(stdout, "Bitcoin server starting\n");

            // Daemonize
            if (daemon(1, 0)) { // don't chdir (1), do close FDs (0)
                fprintf(stderr, "Error: daemon() failed: %s\n", strerror(errno));
                return false;
            }
#else
            fprintf(stderr, "Error: -daemon is not supported on this operating system\n");
            return false;
#endif // HAVE_DECL_DAEMON
        }

        fRet = AppInitMain(threadGroup, scheduler);
    }
    catch (const std::exception& e) {
        PrintExceptionContinue(&e, "AppInit()");
    } catch (...) {
        PrintExceptionContinue(NULL, "AppInit()");
    }

    if (!fRet)
    {
        Interrupt(threadGroup);
        // threadGroup.join_all(); was left out intentionally here, because we didn't re-test all of
        // the startup-failure cases to make sure they don't result in a hang due to some
        // thread-blocking-waiting-for-another-thread-during-startup case
    } else {
        WaitForShutdown(&threadGroup);
    }
    Shutdown();

    return fRet;
}

int main(int argc, char* argv[])
{
    SetupEnvironment();

    // Connect bitcoind signal handlers
    noui_connect();

    return (AppInit(argc, argv) ? EXIT_SUCCESS : EXIT_FAILURE);
}
<commit_msg>Make bitcoind invalid argument error message specific<commit_after>// Copyright (c) 2009-2010 Satoshi Nakamoto
// Copyright (c) 2009-2016 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#if defined(HAVE_CONFIG_H)
#include "config/bitcoin-config.h"
#endif

#include "chainparams.h"
#include "clientversion.h"
#include "compat.h"
#include "fs.h"
#include "rpc/server.h"
#include "init.h"
#include "noui.h"
#include "scheduler.h"
#include "util.h"
#include "httpserver.h"
#include "httprpc.h"
#include "utilstrencodings.h"

#include <boost/algorithm/string/predicate.hpp>
#include <boost/thread.hpp>

#include <stdio.h>

/* Introduction text for doxygen: */

/*! \mainpage Developer documentation
 *
 * \section intro_sec Introduction
 *
 * This is the developer documentation of the reference client for an experimental new digital currency called Bitcoin (https://www.bitcoin.org/),
 * which enables instant payments to anyone, anywhere in the world. Bitcoin uses peer-to-peer technology to operate
 * with no central authority: managing transactions and issuing money are carried out collectively by the network.
 *
 * The software is a community-driven open source project, released under the MIT license.
 *
 * \section Navigation
 * Use the buttons Namespaces, Classes or Files at the top of the page to start navigating the code.
 */

void WaitForShutdown(boost::thread_group* threadGroup)
{
    bool fShutdown = ShutdownRequested();
    // Tell the main threads to shutdown.
    while (!fShutdown)
    {
        MilliSleep(200);
        fShutdown = ShutdownRequested();
    }
    if (threadGroup)
    {
        Interrupt(*threadGroup);
        threadGroup->join_all();
    }
}

//////////////////////////////////////////////////////////////////////////////
//
// Start
//
bool AppInit(int argc, char* argv[])
{
    boost::thread_group threadGroup;
    CScheduler scheduler;

    bool fRet = false;

    //
    // Parameters
    //
    // If Qt is used, parameters/bitcoin.conf are parsed in qt/bitcoin.cpp's main()
    ParseParameters(argc, argv);

    // Process help and version before taking care about datadir
    if (IsArgSet("-?") || IsArgSet("-h") ||  IsArgSet("-help") || IsArgSet("-version"))
    {
        std::string strUsage = strprintf(_("%s Daemon"), _(PACKAGE_NAME)) + " " + _("version") + " " + FormatFullVersion() + "\n";

        if (IsArgSet("-version"))
        {
            strUsage += FormatParagraph(LicenseInfo());
        }
        else
        {
            strUsage += "\n" + _("Usage:") + "\n" +
                  "  bitcoind [options]                     " + strprintf(_("Start %s Daemon"), _(PACKAGE_NAME)) + "\n";

            strUsage += "\n" + HelpMessage(HMM_BITCOIND);
        }

        fprintf(stdout, "%s", strUsage.c_str());
        return true;
    }

    try
    {
        if (!fs::is_directory(GetDataDir(false)))
        {
            fprintf(stderr, "Error: Specified data directory \"%s\" does not exist.\n", GetArg("-datadir", "").c_str());
            return false;
        }
        try
        {
            ReadConfigFile(GetArg("-conf", BITCOIN_CONF_FILENAME));
        } catch (const std::exception& e) {
            fprintf(stderr,"Error reading configuration file: %s\n", e.what());
            return false;
        }
        // Check for -testnet or -regtest parameter (Params() calls are only valid after this clause)
        try {
            SelectParams(ChainNameFromCommandLine());
        } catch (const std::exception& e) {
            fprintf(stderr, "Error: %s\n", e.what());
            return false;
        }

        // Error out when loose non-argument tokens are encountered on command line
        for (int i = 1; i < argc; i++) {
            if (!IsSwitchChar(argv[i][0])) {
                fprintf(stderr, "Error: Command line contains unexpected token '%s', see bitcoind -h for a list of options.\n", argv[i]);
                exit(EXIT_FAILURE);
            }
        }

        // -server defaults to true for bitcoind but not for the GUI so do this here
        SoftSetBoolArg("-server", true);
        // Set this early so that parameter interactions go to console
        InitLogging();
        InitParameterInteraction();
        if (!AppInitBasicSetup())
        {
            // InitError will have been called with detailed error, which ends up on console
            exit(EXIT_FAILURE);
        }
        if (!AppInitParameterInteraction())
        {
            // InitError will have been called with detailed error, which ends up on console
            exit(EXIT_FAILURE);
        }
        if (!AppInitSanityChecks())
        {
            // InitError will have been called with detailed error, which ends up on console
            exit(EXIT_FAILURE);
        }
        if (GetBoolArg("-daemon", false))
        {
#if HAVE_DECL_DAEMON
            fprintf(stdout, "Bitcoin server starting\n");

            // Daemonize
            if (daemon(1, 0)) { // don't chdir (1), do close FDs (0)
                fprintf(stderr, "Error: daemon() failed: %s\n", strerror(errno));
                return false;
            }
#else
            fprintf(stderr, "Error: -daemon is not supported on this operating system\n");
            return false;
#endif // HAVE_DECL_DAEMON
        }

        fRet = AppInitMain(threadGroup, scheduler);
    }
    catch (const std::exception& e) {
        PrintExceptionContinue(&e, "AppInit()");
    } catch (...) {
        PrintExceptionContinue(NULL, "AppInit()");
    }

    if (!fRet)
    {
        Interrupt(threadGroup);
        // threadGroup.join_all(); was left out intentionally here, because we didn't re-test all of
        // the startup-failure cases to make sure they don't result in a hang due to some
        // thread-blocking-waiting-for-another-thread-during-startup case
    } else {
        WaitForShutdown(&threadGroup);
    }
    Shutdown();

    return fRet;
}

int main(int argc, char* argv[])
{
    SetupEnvironment();

    // Connect bitcoind signal handlers
    noui_connect();

    return (AppInit(argc, argv) ? EXIT_SUCCESS : EXIT_FAILURE);
}
<|endoftext|>