<commit_before>/**************************************************************************
* Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
*                                                                        *
* Author: The ALICE Off-line Project.                                    *
* Contributors are mentioned in the code where appropriate.              *
*                                                                        *
* Permission to use, copy, modify and distribute this software and its   *
* documentation strictly for non-commercial purposes is hereby granted   *
* without fee, provided that the above copyright notice appears in all   *
* copies and that both the copyright notice and this permission notice   *
* appear in the supporting documentation. The authors make no claims     *
* about the suitability of this software for any purpose. It is          *
* provided "as is" without express or implied warranty.                  *
**************************************************************************/

// $Id$
// $MpId: AliMpSlatSegmentation.cxx,v 1.4 2005/09/19 19:01:31 ivana Exp $

#include "AliMpSlatSegmentation.h"

#include "AliLog.h"
#include "AliMpConnection.h"
#include "AliMpMotif.h"
#include "AliMpMotifPosition.h"
#include "AliMpMotifType.h"
#include "AliMpPCB.h"
#include "AliMpSlat.h"
#include "AliMpSlatPadIterator.h"

ClassImp(AliMpSlatSegmentation)

//_____________________________________________________________________________
AliMpSlatSegmentation::AliMpSlatSegmentation()
: AliMpVSegmentation(),
fkSlat(0)
{
  //
  // Default ctor. Not to be used really.
  //
  AliDebug(1,Form("this=%p Empty ctor",this));
}

//_____________________________________________________________________________
AliMpSlatSegmentation::AliMpSlatSegmentation(const AliMpSlat* slat)
: AliMpVSegmentation(),
fkSlat(slat)
{
  //
  // Normal ctor.
  //
  AliDebug(1,Form("this=%p Normal ctor slat=%p",this,slat));
}

//_____________________________________________________________________________
AliMpSlatSegmentation::~AliMpSlatSegmentation()
{
  //
  // Dtor (empty).
  //
  Int_t i(0);//just to be able to put a breakpoint in gdb
  AliDebug(1,Form("this=%p",this));
}

//_____________________________________________________________________________
AliMpVPadIterator*
AliMpSlatSegmentation::CreateIterator(const AliMpArea& area) const
{
  //
  // Returns an iterator to loop over the pad contained within given area.
  //

  return new AliMpSlatPadIterator(fkSlat,area);
}

//_____________________________________________________________________________
const char*
AliMpSlatSegmentation::GetName() const
{
  TString name("SlatSegmentation");
  if ( fkSlat)
  {
    name += ".";
    name += fkSlat->GetName();
  }
  return name.Data();
}

//_____________________________________________________________________________
Bool_t
AliMpSlatSegmentation::HasPad(const AliMpIntPair& indices) const
{
  //
  // Test if this slat has a pad located at the position referenced
  // by the integer indices.
  //

  return PadByIndices(indices,kFALSE) != AliMpPad::Invalid();
}

//_____________________________________________________________________________
Int_t
AliMpSlatSegmentation::MaxPadIndexX()
{
  //
  // Returns the value of the largest pad index in x-direction.
  //

  return fkSlat->GetMaxPadIndexX();
}

//_____________________________________________________________________________
Int_t
AliMpSlatSegmentation::MaxPadIndexY()
{
  //
  // Returns the value of the largest pad index in y-direction.
  //

  return fkSlat->GetMaxNofPadsY()-1;
}

//_____________________________________________________________________________
AliMpPad
AliMpSlatSegmentation::PadByLocation(const AliMpIntPair& location,
                                     Bool_t warning) const
{
  //
  // Returns the pad specified by its location, where location is the
  // pair (ManuID,ManuChannel).
  // If warning=kTRUE and the pad does not exist, a warning message is
  // printed.
  //
  // AliMpPad::Invalid() is returned if there's no pad at the given location.
  //
  Int_t manuID = location.GetFirst();

  AliMpMotifPosition* motifPos = fkSlat->FindMotifPosition(manuID);

  if (!motifPos)
	{
		if (warning)
		{
			AliWarning(Form("Manu ID %d not found in slat %s",
			                 manuID, fkSlat->GetID()));
    }
    return AliMpPad::Invalid();
	}
  AliMpVMotif* motif = motifPos->GetMotif();
  AliMpIntPair localIndices =
    motif->GetMotifType()->FindLocalIndicesByGassiNum(location.GetSecond());

  if (!localIndices.IsValid())
	{
		if (warning)
		{
			AliWarning(Form("The pad number %d doesn't exists",
			                location.GetSecond()));
		}
		return AliMpPad::Invalid();
	}

  return AliMpPad(location,
                  motifPos->GlobalIndices(localIndices),
                  motifPos->Position()
                  + motif->PadPositionLocal(localIndices)
                  - fkSlat->Position(),
                  motif->GetPadDimensions(localIndices));
}

//_____________________________________________________________________________
AliMpPad
AliMpSlatSegmentation::PadByIndices(const AliMpIntPair& indices,
                                    Bool_t warning) const
{
  //
  // Returns the pad specified by its integer indices.
  // If warning=kTRUE and the pad does not exist, a warning message is
  // printed.
  //
  // AliMpPad::Invalid() is returned if there's no pad at the given location.
  //
  //
  // FIXME: except for the FindMotifPosition below, this method
  // is exactly as the one in AliMpSectorSegmentation.
  // See if we can merge them somehow.

  AliMpMotifPosition* motifPos = fkSlat->FindMotifPosition(indices.GetFirst(),
																									 indices.GetSecond());
  if (!motifPos)
	{
		if ( warning )
		{
			AliWarning(Form("No motif found containing pad location (%d,%d)",
			                 indices.GetFirst(),indices.GetSecond()));
		}
		return AliMpPad::Invalid();
	}

  AliMpVMotif* motif = motifPos->GetMotif();
  AliMpMotifType* motifType = motif->GetMotifType();
  AliMpIntPair localIndices(indices-motifPos->GetLowIndicesLimit());
  AliMpConnection* connection = motifType->FindConnectionByLocalIndices(localIndices);

  if (!connection)
	{
		if ( warning )
		{
			AliWarning(Form("No connection for pad location (%d,%d)",
			                indices.GetFirst(),indices.GetSecond()));
    }
    return AliMpPad::Invalid();
	}

  return AliMpPad(AliMpIntPair(motifPos->GetID(),connection->GetGassiNum()),
                  indices,
                  motifPos->Position()
                  + motif->PadPositionLocal(localIndices)
                  - fkSlat->Position(),
                  motif->GetPadDimensions(localIndices));
}

//_____________________________________________________________________________
AliMpPad
AliMpSlatSegmentation::PadByPosition(const TVector2& position,
                                     Bool_t warning) const
{
  //
  // Returns the pad specified by its (floating point) position.
  // If warning=kTRUE and the pad does not exist, a warning message is
  // printed.
  //
  // AliMpPad::Invalid() is returned if there's no pad at the given location.
  //

  AliMpMotifPosition* motifPos = fkSlat->FindMotifPosition(position.X(),position.Y());

  if (!motifPos)
	{
		if (warning)
		{
			AliWarning(Form("Slat %s Position (%e,%e) mm outside limits",
                      fkSlat->GetID(),position.X(),position.Y()));
		}
		return AliMpPad::Invalid();
	}

  AliMpVMotif* motif =  motifPos->GetMotif();
  AliMpIntPair localIndices
    = motif->PadIndicesLocal(position-motifPos->Position());

  AliMpConnection* connect =
    motif->GetMotifType()->FindConnectionByLocalIndices(localIndices);

  if (!connect)
	{
		if (warning)
		{
			AliWarning(Form("Slat %s localIndices (%d,%d) outside motif %s limits",
                      fkSlat->GetID(),localIndices.GetFirst(),
                      localIndices.GetSecond(),motif->GetID().Data()));
		}
		return AliMpPad::Invalid();
	}

  return AliMpPad(AliMpIntPair(motifPos->GetID(),connect->GetGassiNum()),
                  motifPos->GlobalIndices(localIndices),
                  motifPos->Position()
                  + motif->PadPositionLocal(localIndices)
                  - fkSlat->Position(),
                  motif->GetPadDimensions(localIndices));
}

//_____________________________________________________________________________
const AliMpSlat*
AliMpSlatSegmentation::Slat() const
{
  //
  // Returns the pointer to the referenced slat.
  //

  return fkSlat;
}
<commit_msg>Commented out declaration of unused variable (causing compiler warning)<commit_after>/**************************************************************************
* Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
*                                                                        *
* Author: The ALICE Off-line Project.                                    *
* Contributors are mentioned in the code where appropriate.              *
*                                                                        *
* Permission to use, copy, modify and distribute this software and its   *
* documentation strictly for non-commercial purposes is hereby granted   *
* without fee, provided that the above copyright notice appears in all   *
* copies and that both the copyright notice and this permission notice   *
* appear in the supporting documentation. The authors make no claims     *
* about the suitability of this software for any purpose. It is          *
* provided "as is" without express or implied warranty.                  *
**************************************************************************/

// $Id$
// $MpId: AliMpSlatSegmentation.cxx,v 1.5 2005/10/28 15:26:01 ivana Exp $

#include "AliMpSlatSegmentation.h"

#include "AliLog.h"
#include "AliMpConnection.h"
#include "AliMpMotif.h"
#include "AliMpMotifPosition.h"
#include "AliMpMotifType.h"
#include "AliMpPCB.h"
#include "AliMpSlat.h"
#include "AliMpSlatPadIterator.h"

ClassImp(AliMpSlatSegmentation)

//_____________________________________________________________________________
AliMpSlatSegmentation::AliMpSlatSegmentation()
: AliMpVSegmentation(),
fkSlat(0)
{
  //
  // Default ctor. Not to be used really.
  //
  AliDebug(1,Form("this=%p Empty ctor",this));
}

//_____________________________________________________________________________
AliMpSlatSegmentation::AliMpSlatSegmentation(const AliMpSlat* slat)
: AliMpVSegmentation(),
fkSlat(slat)
{
  //
  // Normal ctor.
  //
  AliDebug(1,Form("this=%p Normal ctor slat=%p",this,slat));
}

//_____________________________________________________________________________
AliMpSlatSegmentation::~AliMpSlatSegmentation()
{
  //
  // Dtor (empty).
  //
  // Int_t i(0);//just to be able to put a breakpoint in gdb
  AliDebug(1,Form("this=%p",this));
}

//_____________________________________________________________________________
AliMpVPadIterator*
AliMpSlatSegmentation::CreateIterator(const AliMpArea& area) const
{
  //
  // Returns an iterator to loop over the pad contained within given area.
  //

  return new AliMpSlatPadIterator(fkSlat,area);
}

//_____________________________________________________________________________
const char*
AliMpSlatSegmentation::GetName() const
{
  TString name("SlatSegmentation");
  if ( fkSlat)
  {
    name += ".";
    name += fkSlat->GetName();
  }
  return name.Data();
}

//_____________________________________________________________________________
Bool_t
AliMpSlatSegmentation::HasPad(const AliMpIntPair& indices) const
{
  //
  // Test if this slat has a pad located at the position referenced
  // by the integer indices.
  //

  return PadByIndices(indices,kFALSE) != AliMpPad::Invalid();
}

//_____________________________________________________________________________
Int_t
AliMpSlatSegmentation::MaxPadIndexX()
{
  //
  // Returns the value of the largest pad index in x-direction.
  //

  return fkSlat->GetMaxPadIndexX();
}

//_____________________________________________________________________________
Int_t
AliMpSlatSegmentation::MaxPadIndexY()
{
  //
  // Returns the value of the largest pad index in y-direction.
  //

  return fkSlat->GetMaxNofPadsY()-1;
}

//_____________________________________________________________________________
AliMpPad
AliMpSlatSegmentation::PadByLocation(const AliMpIntPair& location,
                                     Bool_t warning) const
{
  //
  // Returns the pad specified by its location, where location is the
  // pair (ManuID,ManuChannel).
  // If warning=kTRUE and the pad does not exist, a warning message is
  // printed.
  //
  // AliMpPad::Invalid() is returned if there's no pad at the given location.
  //
  Int_t manuID = location.GetFirst();

  AliMpMotifPosition* motifPos = fkSlat->FindMotifPosition(manuID);

  if (!motifPos)
	{
		if (warning)
		{
			AliWarning(Form("Manu ID %d not found in slat %s",
			                 manuID, fkSlat->GetID()));
    }
    return AliMpPad::Invalid();
	}
  AliMpVMotif* motif = motifPos->GetMotif();
  AliMpIntPair localIndices =
    motif->GetMotifType()->FindLocalIndicesByGassiNum(location.GetSecond());

  if (!localIndices.IsValid())
	{
		if (warning)
		{
			AliWarning(Form("The pad number %d doesn't exists",
			                location.GetSecond()));
		}
		return AliMpPad::Invalid();
	}

  return AliMpPad(location,
                  motifPos->GlobalIndices(localIndices),
                  motifPos->Position()
                  + motif->PadPositionLocal(localIndices)
                  - fkSlat->Position(),
                  motif->GetPadDimensions(localIndices));
}

//_____________________________________________________________________________
AliMpPad
AliMpSlatSegmentation::PadByIndices(const AliMpIntPair& indices,
                                    Bool_t warning) const
{
  //
  // Returns the pad specified by its integer indices.
  // If warning=kTRUE and the pad does not exist, a warning message is
  // printed.
  //
  // AliMpPad::Invalid() is returned if there's no pad at the given location.
  //
  //
  // FIXME: except for the FindMotifPosition below, this method
  // is exactly as the one in AliMpSectorSegmentation.
  // See if we can merge them somehow.

  AliMpMotifPosition* motifPos = fkSlat->FindMotifPosition(indices.GetFirst(),
																									 indices.GetSecond());
  if (!motifPos)
	{
		if ( warning )
		{
			AliWarning(Form("No motif found containing pad location (%d,%d)",
			                 indices.GetFirst(),indices.GetSecond()));
		}
		return AliMpPad::Invalid();
	}

  AliMpVMotif* motif = motifPos->GetMotif();
  AliMpMotifType* motifType = motif->GetMotifType();
  AliMpIntPair localIndices(indices-motifPos->GetLowIndicesLimit());
  AliMpConnection* connection = motifType->FindConnectionByLocalIndices(localIndices);

  if (!connection)
	{
		if ( warning )
		{
			AliWarning(Form("No connection for pad location (%d,%d)",
			                indices.GetFirst(),indices.GetSecond()));
    }
    return AliMpPad::Invalid();
	}

  return AliMpPad(AliMpIntPair(motifPos->GetID(),connection->GetGassiNum()),
                  indices,
                  motifPos->Position()
                  + motif->PadPositionLocal(localIndices)
                  - fkSlat->Position(),
                  motif->GetPadDimensions(localIndices));
}

//_____________________________________________________________________________
AliMpPad
AliMpSlatSegmentation::PadByPosition(const TVector2& position,
                                     Bool_t warning) const
{
  //
  // Returns the pad specified by its (floating point) position.
  // If warning=kTRUE and the pad does not exist, a warning message is
  // printed.
  //
  // AliMpPad::Invalid() is returned if there's no pad at the given location.
  //

  AliMpMotifPosition* motifPos = fkSlat->FindMotifPosition(position.X(),position.Y());

  if (!motifPos)
	{
		if (warning)
		{
			AliWarning(Form("Slat %s Position (%e,%e) mm outside limits",
                      fkSlat->GetID(),position.X(),position.Y()));
		}
		return AliMpPad::Invalid();
	}

  AliMpVMotif* motif =  motifPos->GetMotif();
  AliMpIntPair localIndices
    = motif->PadIndicesLocal(position-motifPos->Position());

  AliMpConnection* connect =
    motif->GetMotifType()->FindConnectionByLocalIndices(localIndices);

  if (!connect)
	{
		if (warning)
		{
			AliWarning(Form("Slat %s localIndices (%d,%d) outside motif %s limits",
                      fkSlat->GetID(),localIndices.GetFirst(),
                      localIndices.GetSecond(),motif->GetID().Data()));
		}
		return AliMpPad::Invalid();
	}

  return AliMpPad(AliMpIntPair(motifPos->GetID(),connect->GetGassiNum()),
                  motifPos->GlobalIndices(localIndices),
                  motifPos->Position()
                  + motif->PadPositionLocal(localIndices)
                  - fkSlat->Position(),
                  motif->GetPadDimensions(localIndices));
}

//_____________________________________________________________________________
const AliMpSlat*
AliMpSlatSegmentation::Slat() const
{
  //
  // Returns the pointer to the referenced slat.
  //

  return fkSlat;
}
<|endoftext|>


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

  Program:   Visualization Library
  Module:    Object.hh
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

This file is part of the Visualization Library. No part of this file or its
contents may be copied, reproduced or altered in any way without the express
written consent of the authors.

Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen 1993, 1994

=========================================================================*/
// .NAME vlObject - abstract base class for visualization library
// .SECTION Description
// vlObject is the base class for many objects in the visualization
// library. vlObject provides methods for tracking modification time,
// debugging, and printing.

#ifndef __vlObject_hh
#define __vlObject_hh

#include <iostream.h>
#include "TimeSt.hh"
#include "SetGet.hh"
#include "Indent.hh"

class vlObject
{
public:
  vlObject();
  virtual ~vlObject();
  virtual char *GetClassName() {return "vlObject";};

  // debugging
  void DebugOn();
  void DebugOff();
  int GetDebug();

  // modified time
  virtual unsigned long int GetMTime();
  virtual void Modified();

  // printing
  virtual void PrintSelf(ostream& os, vlIndent indent);
  void Print(ostream& os);
  virtual void PrintHeader(ostream& os, vlIndent indent);
  virtual void PrintTrailer(ostream& os, vlIndent indent);

protected:
  int Debug;         // Enable debug messages
  vlTimeStamp MTime; // Keep track of modification time

private:
  friend ostream& operator<<(ostream& os, vlObject& o);
};

// Description:
// Update the modification time for this object.
inline void vlObject::Modified()
{
  this->MTime.Modified();
}

#endif

<commit_msg>ENH: Multiple inheritance tweaks (with debug)<commit_after>/*=========================================================================

  Program:   Visualization Library
  Module:    Object.hh
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

This file is part of the Visualization Library. No part of this file or its
contents may be copied, reproduced or altered in any way without the express
written consent of the authors.

Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen 1993, 1994

=========================================================================*/
// .NAME vlObject - abstract base class for visualization library
// .SECTION Description
// vlObject is the base class for many objects in the visualization
// library. vlObject provides methods for tracking modification time,
// debugging, and printing.

#ifndef __vlObject_hh
#define __vlObject_hh

#include <iostream.h>
#include "TimeSt.hh"
#include "SetGet.hh"
#include "Indent.hh"

class vlObject
{
public:
  vlObject();
  virtual ~vlObject();
  virtual char *GetClassName() {return "vlObject";};

  // debugging
  virtual void DebugOn();
  virtual void DebugOff();
  int GetDebug();

  // modified time
  virtual unsigned long int GetMTime();
  virtual void Modified();

  // printing
  virtual void PrintSelf(ostream& os, vlIndent indent);
  void Print(ostream& os);
  virtual void PrintHeader(ostream& os, vlIndent indent);
  virtual void PrintTrailer(ostream& os, vlIndent indent);

protected:
  int Debug;         // Enable debug messages
  vlTimeStamp MTime; // Keep track of modification time

private:
  friend ostream& operator<<(ostream& os, vlObject& o);
};

// Description:
// Update the modification time for this object.
inline void vlObject::Modified()
{
  this->MTime.Modified();
}

#endif

<|endoftext|>


<commit_before>//
//  Video.hpp
//  Clock Signal
//
//  Created by Thomas Harte on 18/03/2021.
//  Copyright © 2021 Thomas Harte. All rights reserved.
//

#ifndef Video_hpp
#define Video_hpp

#include "../../../Outputs/CRT/CRT.hpp"
#include "../../../ClockReceiver/ClockReceiver.hpp"

#include <algorithm>

namespace Sinclair {
namespace ZXSpectrum {

enum class VideoTiming {
	Plus3
};

/*
	Timing notes:

	As of the +2a/+3:

		311 lines, 228 cycles/line
		Delays begin at 14361, follow the pattern 1, 0, 7, 6, 5, 4, 3, 2; run for 129 cycles/line.
		Possibly delays only affect actual reads and writes; documentation is unclear.

	Unknowns, to me, presently:

		How long the interrupt line held for.

	So...

		Probably two bytes of video and attribute are fetched in each 8-cycle block,
		with 16 such blocks therefore providing the whole visible display, an island
		within 28.5 blocks horizontally.

		14364 is 228*63, so I I guess almost 63 lines run from the start of vertical
		blank through to the top of the display, implying 56 lines on to vertical blank.

*/

template <VideoTiming timing> class Video {
	private:
		struct Timings {
			int cycles_per_line;
			int lines_per_frame;
			int first_delay;
			int contended_period;
			int first_fetch;
			int delays[16];
		};

		static constexpr Timings get_timings() {
			constexpr Timings result = {
				.cycles_per_line = 228 * 2,
				.lines_per_frame = 311,
				.first_delay = 14361 * 2,
				.contended_period = (14490 - 14361) * 2,
				.first_fetch = 14364 * 2,	// TODO: find a source for this, a guess.
				.delays = {
					2, 1,
					0, 0,
					14, 13,
					12, 11,
					10, 9,
					8, 7,
					6, 5,
					4, 3,
				}
			};
			return result;
		}

	public:
		void run_for(HalfCycles duration) {
			constexpr auto timings = get_timings();
			constexpr int first_line = timings.first_fetch / timings.cycles_per_line;
			constexpr int sync_position = 166 * 2;
			constexpr int sync_length = 17 * 2;
			constexpr int burst_position = sync_position + 40;
			constexpr int burst_length = 17;

			int cycles_remaining = duration.as<int>();
			while(cycles_remaining) {
				int line = time_since_interrupt_ / timings.cycles_per_line;
				int offset = time_since_interrupt_ % timings.cycles_per_line;
				const int cycles_this_line = std::min(cycles_remaining, timings.cycles_per_line - offset);
				const int end_offset = offset + cycles_this_line;

				if(!offset) {
					is_alternate_line_ ^= true;

					if(!line) {
						flash_counter_ = (flash_counter_ + 1) & 31;
						flash_mask_ = uint8_t(flash_counter_ >> 4);
					}
				}

				if(line < 3) {
					// Output sync line.
					crt_.output_sync(cycles_this_line);
				} else {
					if((line < first_line) || (line >= first_line+192)) {
						// Output plain border line.
						if(offset < sync_position) {
							const int border_duration = std::min(sync_position, end_offset) - offset;
							output_border(border_duration);
							offset += border_duration;
						}
					} else {
						// Output pixel line.
						if(offset < 256) {
							const int pixel_duration = std::min(256, end_offset) - offset;

							if(!offset) {
								const int pixel_line = line - first_line;

								pixel_target_ = crt_.begin_data(256);
								attribute_address_ = ((pixel_line / 8) * 32) + 6144;
								pixel_address_ = ((pixel_line & 0x07) << 8) | ((pixel_line&0x38) << 2) | ((pixel_line&0xc0) << 5);
							}

							if(pixel_target_) {
								const int start_column = offset >> 4;
								const int end_column = (offset + pixel_duration) >> 4;
								for(int column = start_column; column < end_column; column++) {
									const uint8_t attributes[2] = {
										memory_[attribute_address_],
										memory_[attribute_address_+1],
									};

									constexpr uint8_t masks[] = {0, 0xff};
									const uint8_t pixels[2] = {
										uint8_t(memory_[pixel_address_] ^ masks[flash_mask_ & (attributes[0] >> 7)]),
										uint8_t(memory_[pixel_address_+1] ^ masks[flash_mask_ & (attributes[1] >> 7)]),
									};

									{
										const uint8_t colours[2] = {
											palette[(attributes[0] & 0x78) >> 3],
											palette[((attributes[0] & 0x40) >> 3) | (attributes[0] & 0x07)],
										};

										pixel_target_[0] = colours[(pixels[0] >> 7) & 1];
										pixel_target_[1] = colours[(pixels[0] >> 6) & 1];
										pixel_target_[2] = colours[(pixels[0] >> 5) & 1];
										pixel_target_[3] = colours[(pixels[0] >> 4) & 1];
										pixel_target_[4] = colours[(pixels[0] >> 3) & 1];
										pixel_target_[5] = colours[(pixels[0] >> 2) & 1];
										pixel_target_[6] = colours[(pixels[0] >> 1) & 1];
										pixel_target_[7] = colours[(pixels[0] >> 0) & 1];
										pixel_target_ += 8;
									}

									{
										const uint8_t colours[2] = {
											palette[(attributes[1] & 0x78) >> 3],
											palette[((attributes[1] & 0x40) >> 3) | (attributes[1] & 0x07)],
										};

										pixel_target_[0] = colours[(pixels[1] >> 7) & 1];
										pixel_target_[1] = colours[(pixels[1] >> 6) & 1];
										pixel_target_[2] = colours[(pixels[1] >> 5) & 1];
										pixel_target_[3] = colours[(pixels[1] >> 4) & 1];
										pixel_target_[4] = colours[(pixels[1] >> 3) & 1];
										pixel_target_[5] = colours[(pixels[1] >> 2) & 1];
										pixel_target_[6] = colours[(pixels[1] >> 1) & 1];
										pixel_target_[7] = colours[(pixels[1] >> 0) & 1];
										pixel_target_ += 8;
									}

									pixel_address_ += 2;
									attribute_address_ += 2;
								}
							}

							offset += pixel_duration;
							if(offset == 256) {
								crt_.output_data(256);
								pixel_target_ = nullptr;
							}
						}

						if(offset >= 256 && offset < sync_position && end_offset > offset) {
							const int border_duration = std::min(sync_position, end_offset) - offset;
							output_border(border_duration);
							offset += border_duration;
						}
					}

					// Output the common tail to border and pixel lines: sync, blank, colour burst, border.

					if(offset >= sync_position && offset < sync_position + sync_length && end_offset > offset) {
						const int sync_duration = std::min(sync_position + sync_length, end_offset) - offset;
						crt_.output_sync(sync_duration);
						offset += sync_duration;
					}

					if(offset >= sync_position + sync_length && offset < burst_position && end_offset > offset) {
						const int blank_duration = std::min(burst_position, end_offset) - offset;
						crt_.output_blank(blank_duration);
						offset += blank_duration;
					}

					if(offset >= burst_position && offset < burst_position+burst_length && end_offset > offset) {
						const int burst_duration = std::min(burst_position + burst_length, end_offset) - offset;
						crt_.output_colour_burst(burst_duration, 0, is_alternate_line_);
						offset += burst_duration;
					}

					if(offset >= burst_position+burst_length && end_offset > offset) {
						const int border_duration = end_offset - offset;
						output_border(border_duration);
					}
				}

				cycles_remaining -= cycles_this_line;
				time_since_interrupt_ = (time_since_interrupt_ + cycles_this_line) % (timings.cycles_per_line * timings.lines_per_frame);
			}
		}

	private:
		// TODO: how long is the interrupt line held for?
		static constexpr int interrupt_duration = 48;

		void output_border(int duration) {
			uint8_t *const colour_pointer = crt_.begin_data(1);
			if(colour_pointer) *colour_pointer = border_colour_;
			crt_.output_level(duration);
		}

	public:
		Video() :
			crt_(227 * 2, 2, Outputs::Display::Type::PAL50, Outputs::Display::InputDataType::Red2Green2Blue2)
		{
			// Show only the centre 80% of the TV frame.
			crt_.set_display_type(Outputs::Display::DisplayType::RGB);
			crt_.set_visible_area(Outputs::Display::Rect(0.1f, 0.1f, 0.8f, 0.8f));

		}

		void set_video_source(const uint8_t *source) {
			memory_ = source;
		}

		HalfCycles get_next_sequence_point() {
			if(time_since_interrupt_ < interrupt_duration) {
				return HalfCycles(interrupt_duration - time_since_interrupt_);
			}

			constexpr auto timings = get_timings();
			return timings.cycles_per_line * timings.lines_per_frame - time_since_interrupt_;
		}

		bool get_interrupt_line() const {
			return time_since_interrupt_ < interrupt_duration;
		}

		int access_delay(HalfCycles offset) const {
			constexpr auto timings = get_timings();
			const int delay_time = (time_since_interrupt_ + offset.as<int>()) % (timings.cycles_per_line * timings.lines_per_frame);

			if(delay_time < timings.first_delay) return 0;

			const int time_since = delay_time - timings.first_delay;
			const int lines = time_since / timings.cycles_per_line;
			if(lines >= 192) return 0;

			const int line_position = time_since % timings.cycles_per_line;
			if(line_position >= timings.contended_period) return 0;

			return timings.delays[line_position & 15];
		}

		void set_border_colour(uint8_t colour) {
			border_colour_ = palette[colour];
		}

		/// Sets the scan target.
		void set_scan_target(Outputs::Display::ScanTarget *scan_target) {
			crt_.set_scan_target(scan_target);
		}

		/// Gets the current scan status.
		Outputs::Display::ScanStatus get_scaled_scan_status() const {
			return crt_.get_scaled_scan_status();
		}

		/*! Sets the type of display the CRT will request. */
		void set_display_type(Outputs::Display::DisplayType type) {
			crt_.set_display_type(type);
		}

	private:
		int time_since_interrupt_ = 0;
		Outputs::CRT::CRT crt_;
		const uint8_t *memory_ = nullptr;
		uint8_t border_colour_ = 0;

		uint8_t *pixel_target_ = nullptr;
		int attribute_address_ = 0;
		int pixel_address_ = 0;

		uint8_t flash_mask_ = 0;
		int flash_counter_ = 0;
		bool is_alternate_line_ = false;

#define RGB(r, g, b)	(r << 4) | (g << 2) | b
		static constexpr uint8_t palette[] = {
			RGB(0, 0, 0),	RGB(0, 0, 2),	RGB(2, 0, 0),	RGB(2, 0, 2),
			RGB(0, 2, 0),	RGB(0, 2, 2),	RGB(2, 2, 0),	RGB(2, 2, 2),
			RGB(0, 0, 0),	RGB(0, 0, 3),	RGB(3, 0, 0),	RGB(3, 0, 3),
			RGB(0, 3, 0),	RGB(0, 3, 3),	RGB(3, 3, 0),	RGB(3, 3, 3),
		};
#undef RGB
};

}
}

#endif /* Video_hpp */
<commit_msg>Makes another guess at total colour phase.<commit_after>//
//  Video.hpp
//  Clock Signal
//
//  Created by Thomas Harte on 18/03/2021.
//  Copyright © 2021 Thomas Harte. All rights reserved.
//

#ifndef Video_hpp
#define Video_hpp

#include "../../../Outputs/CRT/CRT.hpp"
#include "../../../ClockReceiver/ClockReceiver.hpp"

#include <algorithm>

namespace Sinclair {
namespace ZXSpectrum {

enum class VideoTiming {
	Plus3
};

/*
	Timing notes:

	As of the +2a/+3:

		311 lines, 228 cycles/line
		Delays begin at 14361, follow the pattern 1, 0, 7, 6, 5, 4, 3, 2; run for 129 cycles/line.
		Possibly delays only affect actual reads and writes; documentation is unclear.

	Unknowns, to me, presently:

		How long the interrupt line held for.

	So...

		Probably two bytes of video and attribute are fetched in each 8-cycle block,
		with 16 such blocks therefore providing the whole visible display, an island
		within 28.5 blocks horizontally.

		14364 is 228*63, so I I guess almost 63 lines run from the start of vertical
		blank through to the top of the display, implying 56 lines on to vertical blank.

*/

template <VideoTiming timing> class Video {
	private:
		struct Timings {
			int cycles_per_line;
			int lines_per_frame;
			int first_delay;
			int contended_period;
			int first_fetch;
			int delays[16];
		};

		static constexpr Timings get_timings() {
			constexpr Timings result = {
				.cycles_per_line = 228 * 2,
				.lines_per_frame = 311,
				.first_delay = 14361 * 2,
				.contended_period = (14490 - 14361) * 2,
				.first_fetch = 14364 * 2,	// TODO: find a source for this, a guess.
				.delays = {
					2, 1,
					0, 0,
					14, 13,
					12, 11,
					10, 9,
					8, 7,
					6, 5,
					4, 3,
				}
			};
			return result;
		}

	public:
		void run_for(HalfCycles duration) {
			constexpr auto timings = get_timings();
			constexpr int first_line = timings.first_fetch / timings.cycles_per_line;
			constexpr int sync_position = 166 * 2;
			constexpr int sync_length = 17 * 2;
			constexpr int burst_position = sync_position + 40;
			constexpr int burst_length = 17;

			int cycles_remaining = duration.as<int>();
			while(cycles_remaining) {
				int line = time_since_interrupt_ / timings.cycles_per_line;
				int offset = time_since_interrupt_ % timings.cycles_per_line;
				const int cycles_this_line = std::min(cycles_remaining, timings.cycles_per_line - offset);
				const int end_offset = offset + cycles_this_line;

				if(!offset) {
					is_alternate_line_ ^= true;

					if(!line) {
						flash_counter_ = (flash_counter_ + 1) & 31;
						flash_mask_ = uint8_t(flash_counter_ >> 4);
					}
				}

				if(line < 3) {
					// Output sync line.
					crt_.output_sync(cycles_this_line);
				} else {
					if((line < first_line) || (line >= first_line+192)) {
						// Output plain border line.
						if(offset < sync_position) {
							const int border_duration = std::min(sync_position, end_offset) - offset;
							output_border(border_duration);
							offset += border_duration;
						}
					} else {
						// Output pixel line.
						if(offset < 256) {
							const int pixel_duration = std::min(256, end_offset) - offset;

							if(!offset) {
								const int pixel_line = line - first_line;

								pixel_target_ = crt_.begin_data(256);
								attribute_address_ = ((pixel_line / 8) * 32) + 6144;
								pixel_address_ = ((pixel_line & 0x07) << 8) | ((pixel_line&0x38) << 2) | ((pixel_line&0xc0) << 5);
							}

							if(pixel_target_) {
								const int start_column = offset >> 4;
								const int end_column = (offset + pixel_duration) >> 4;
								for(int column = start_column; column < end_column; column++) {
									const uint8_t attributes[2] = {
										memory_[attribute_address_],
										memory_[attribute_address_+1],
									};

									constexpr uint8_t masks[] = {0, 0xff};
									const uint8_t pixels[2] = {
										uint8_t(memory_[pixel_address_] ^ masks[flash_mask_ & (attributes[0] >> 7)]),
										uint8_t(memory_[pixel_address_+1] ^ masks[flash_mask_ & (attributes[1] >> 7)]),
									};

									{
										const uint8_t colours[2] = {
											palette[(attributes[0] & 0x78) >> 3],
											palette[((attributes[0] & 0x40) >> 3) | (attributes[0] & 0x07)],
										};

										pixel_target_[0] = colours[(pixels[0] >> 7) & 1];
										pixel_target_[1] = colours[(pixels[0] >> 6) & 1];
										pixel_target_[2] = colours[(pixels[0] >> 5) & 1];
										pixel_target_[3] = colours[(pixels[0] >> 4) & 1];
										pixel_target_[4] = colours[(pixels[0] >> 3) & 1];
										pixel_target_[5] = colours[(pixels[0] >> 2) & 1];
										pixel_target_[6] = colours[(pixels[0] >> 1) & 1];
										pixel_target_[7] = colours[(pixels[0] >> 0) & 1];
										pixel_target_ += 8;
									}

									{
										const uint8_t colours[2] = {
											palette[(attributes[1] & 0x78) >> 3],
											palette[((attributes[1] & 0x40) >> 3) | (attributes[1] & 0x07)],
										};

										pixel_target_[0] = colours[(pixels[1] >> 7) & 1];
										pixel_target_[1] = colours[(pixels[1] >> 6) & 1];
										pixel_target_[2] = colours[(pixels[1] >> 5) & 1];
										pixel_target_[3] = colours[(pixels[1] >> 4) & 1];
										pixel_target_[4] = colours[(pixels[1] >> 3) & 1];
										pixel_target_[5] = colours[(pixels[1] >> 2) & 1];
										pixel_target_[6] = colours[(pixels[1] >> 1) & 1];
										pixel_target_[7] = colours[(pixels[1] >> 0) & 1];
										pixel_target_ += 8;
									}

									pixel_address_ += 2;
									attribute_address_ += 2;
								}
							}

							offset += pixel_duration;
							if(offset == 256) {
								crt_.output_data(256);
								pixel_target_ = nullptr;
							}
						}

						if(offset >= 256 && offset < sync_position && end_offset > offset) {
							const int border_duration = std::min(sync_position, end_offset) - offset;
							output_border(border_duration);
							offset += border_duration;
						}
					}

					// Output the common tail to border and pixel lines: sync, blank, colour burst, border.

					if(offset >= sync_position && offset < sync_position + sync_length && end_offset > offset) {
						const int sync_duration = std::min(sync_position + sync_length, end_offset) - offset;
						crt_.output_sync(sync_duration);
						offset += sync_duration;
					}

					if(offset >= sync_position + sync_length && offset < burst_position && end_offset > offset) {
						const int blank_duration = std::min(burst_position, end_offset) - offset;
						crt_.output_blank(blank_duration);
						offset += blank_duration;
					}

					if(offset >= burst_position && offset < burst_position+burst_length && end_offset > offset) {
						const int burst_duration = std::min(burst_position + burst_length, end_offset) - offset;
						crt_.output_colour_burst(burst_duration, 116, is_alternate_line_);
						offset += burst_duration;
						// The colour burst phase above is an empirical guess. I need to research further.
					}

					if(offset >= burst_position+burst_length && end_offset > offset) {
						const int border_duration = end_offset - offset;
						output_border(border_duration);
					}
				}

				cycles_remaining -= cycles_this_line;
				time_since_interrupt_ = (time_since_interrupt_ + cycles_this_line) % (timings.cycles_per_line * timings.lines_per_frame);
			}
		}

	private:
		// TODO: how long is the interrupt line held for?
		static constexpr int interrupt_duration = 48;

		void output_border(int duration) {
			uint8_t *const colour_pointer = crt_.begin_data(1);
			if(colour_pointer) *colour_pointer = border_colour_;
			crt_.output_level(duration);
		}

	public:
		Video() :
			crt_(227 * 2, 2, Outputs::Display::Type::PAL50, Outputs::Display::InputDataType::Red2Green2Blue2)
		{
			// Show only the centre 80% of the TV frame.
			crt_.set_display_type(Outputs::Display::DisplayType::RGB);
			crt_.set_visible_area(Outputs::Display::Rect(0.1f, 0.1f, 0.8f, 0.8f));

		}

		void set_video_source(const uint8_t *source) {
			memory_ = source;
		}

		HalfCycles get_next_sequence_point() {
			if(time_since_interrupt_ < interrupt_duration) {
				return HalfCycles(interrupt_duration - time_since_interrupt_);
			}

			constexpr auto timings = get_timings();
			return timings.cycles_per_line * timings.lines_per_frame - time_since_interrupt_;
		}

		bool get_interrupt_line() const {
			return time_since_interrupt_ < interrupt_duration;
		}

		int access_delay(HalfCycles offset) const {
			constexpr auto timings = get_timings();
			const int delay_time = (time_since_interrupt_ + offset.as<int>()) % (timings.cycles_per_line * timings.lines_per_frame);

			if(delay_time < timings.first_delay) return 0;

			const int time_since = delay_time - timings.first_delay;
			const int lines = time_since / timings.cycles_per_line;
			if(lines >= 192) return 0;

			const int line_position = time_since % timings.cycles_per_line;
			if(line_position >= timings.contended_period) return 0;

			return timings.delays[line_position & 15];
		}

		void set_border_colour(uint8_t colour) {
			border_colour_ = palette[colour];
		}

		/// Sets the scan target.
		void set_scan_target(Outputs::Display::ScanTarget *scan_target) {
			crt_.set_scan_target(scan_target);
		}

		/// Gets the current scan status.
		Outputs::Display::ScanStatus get_scaled_scan_status() const {
			return crt_.get_scaled_scan_status();
		}

		/*! Sets the type of display the CRT will request. */
		void set_display_type(Outputs::Display::DisplayType type) {
			crt_.set_display_type(type);
		}

	private:
		int time_since_interrupt_ = 0;
		Outputs::CRT::CRT crt_;
		const uint8_t *memory_ = nullptr;
		uint8_t border_colour_ = 0;

		uint8_t *pixel_target_ = nullptr;
		int attribute_address_ = 0;
		int pixel_address_ = 0;

		uint8_t flash_mask_ = 0;
		int flash_counter_ = 0;
		bool is_alternate_line_ = false;

#define RGB(r, g, b)	(r << 4) | (g << 2) | b
		static constexpr uint8_t palette[] = {
			RGB(0, 0, 0),	RGB(0, 0, 2),	RGB(2, 0, 0),	RGB(2, 0, 2),
			RGB(0, 2, 0),	RGB(0, 2, 2),	RGB(2, 2, 0),	RGB(2, 2, 2),
			RGB(0, 0, 0),	RGB(0, 0, 3),	RGB(3, 0, 0),	RGB(3, 0, 3),
			RGB(0, 3, 0),	RGB(0, 3, 3),	RGB(3, 3, 0),	RGB(3, 3, 3),
		};
#undef RGB
};

}
}

#endif /* Video_hpp */
<|endoftext|>


<commit_before>/*
 * service.cpp
 *
 *  Created on: Aug 21, 2015
 *      Author: zmij
 */

#include <tip/http/client/service.hpp>
#include <tip/log.hpp>

#include <set>
#include <map>

#include <tip/http/client/session.hpp>
#include <tip/http/client/errors.hpp>
#include <tip/http/common/response.hpp>

namespace tip {
namespace http {
namespace client {

LOCAL_LOGGING_FACILITY(HTTPCLIENT, TRACE);

service::io_service::id service::id;

namespace {

const iri::scheme HTTP_SCHEME = iri::scheme{"http"};
const iri::scheme HTTPS_SCHEME = iri::scheme{"https"};

const std::set< iri::scheme > SUPPORTED_SCHEMES { HTTP_SCHEME, HTTPS_SCHEME };

}  // namespace

struct service::impl : std::enable_shared_from_this<impl> {
	typedef std::pair< iri::host, std::string > connection_id;
	// TODO multiple sessions per host
	typedef std::map< connection_id, session_ptr > session_container;

	io_service&			owner_;
	headers				default_headers_;
	session_container	sessions_;

	impl(io_service& owner, headers const& default_headers) :
		owner_(owner), default_headers_(default_headers)
	{
	}

	~impl()
	{
		local_log() << "service::impl::~impl";
	}

	void
	get(std::string const& url, response_callback cb, error_callback ecb)
	{
		request::iri_type iri;
		if (!request::parse_iri(url, iri)) {
			try {
				throw errors::http_client_error("Invalid IRI");
			} catch (std::exception const& e) {
				if (ecb) {
					ecb(std::current_exception());
				} else throw;
			}
		}
		send_request(GET, iri, session::body_type(), cb, ecb);
	}
	void
	post(std::string const& url, body_type const& body,
			response_callback cb, error_callback ecb)
	{
		request::iri_type iri;
		if (!request::parse_iri(url, iri)) {
			return;
		}
		send_request(POST, iri, body, cb, ecb);
	}
	void
	post(std::string const& url, body_type&& body,
			response_callback cb, error_callback ecb)
	{
		request::iri_type iri;
		if (!request::parse_iri(url, iri)) {
			return;
		}
		send_request(POST, iri, std::move(body), cb, ecb);
	}

	void
	send_request(request_method method, request::iri_type const& iri,
			session::body_type const& body,
			response_callback cb, error_callback ecb)
	{
		using std::placeholders::_1;
		using std::placeholders::_2;
		session_ptr s = get_session(iri);
		s->send_request(GET, iri, body,
				std::bind(&impl::handle_response,
						shared_from_this(), _1, _2, cb, ecb), ecb);
	}
	void
	send_request(request_method method, request::iri_type const& iri,
			session::body_type&& body,
			response_callback cb, error_callback ecb)
	{
		using std::placeholders::_1;
		using std::placeholders::_2;
		session_ptr s = get_session(iri);
		s->send_request(GET, iri, std::move(body),
				std::bind(&impl::handle_response,
						shared_from_this(), _1, _2, cb, ecb), ecb);
	}

	session_ptr
	get_session(request::iri_type const& iri)
	{
		if (SUPPORTED_SCHEMES.count(iri.scheme) == 0) {
			// TODO Throw an error - unsupported scheme
			local_log(logger::ERROR) << "IRI scheme "
					<< iri.scheme << " is not supported";
			throw std::runtime_error("Scheme not supported");
		}
		if (iri.authority.host.empty()) {
			// TODO Throw an error - empty host
			local_log(logger::ERROR) << "Host is empty";
			throw std::runtime_error("Host is empty");
		}
		connection_id cid{ iri.authority.host,
			iri.authority.port.empty() ?
					static_cast<std::string const&>(iri.scheme) :
					static_cast<std::string const&>(iri.authority.port) };
		// FIXME Add mutex
		auto f = sessions_.find(cid);
		if (f == sessions_.end()) {
			session_ptr s = create_session(iri);
			f = sessions_.insert(std::make_pair(cid, s)).first;
		}
		return f->second;
	}

	session_ptr
	create_session(request::iri_type const& iri)
	{
		return session::create(owner_, iri,
				std::bind(&impl::session_closed,
						shared_from_this(), std::placeholders::_1),
				default_headers_);
	}

	void
	handle_response(request_ptr req, response_ptr resp, response_callback cb,
			error_callback ecb)
	{
		using std::placeholders::_1;
		using std::placeholders::_2;
		int status = resp->status / 100;
		if (status == 3) {
			// Handle redirect
			headers::const_iterator f = resp->headers_.find(Location);
			if (f != resp->headers_.end()) {
				local_log(logger::DEBUG) << "Request redirected to " << f->second;
				request::iri_type iri;
				if (!request::parse_iri(f->second, iri)) {
					local_log(logger::WARNING) << "Invalid redirect location";
					cb(resp);
				} else {
					req->path = iri.path;
					req->query = iri.query;
					req->fragment = iri.fragment;
					req->host( iri.authority.host );

					session_ptr s = get_session(iri);
					s->send_request(req, std::bind(
							&impl::handle_response, this, _1, _2, cb, ecb), ecb);
				}
			} else {
				local_log(logger::WARNING) << "Request redirected, but no Location header set";
				cb(resp);
			}
		} else if (status == 4) {

			local_log(logger::WARNING) << "Received error response " << resp->status
					<< " " << resp->status_line << "\n" << *req;

			cb(resp);
		} else {
			cb(resp);
		}
	}

	void
	session_closed(session_ptr s)
	{
		local_log() << "Session closed";
		session_container::const_iterator p = sessions_.begin();
		for (; p != sessions_.end(); ++p) {
			if (p->second == s) break;
		}
		if (p != sessions_.end()) {
			sessions_.erase(p);
		}
	}

	void
	shutdown()
	{
		session_container save = sessions_;
		for (session_container::const_iterator p = save.begin();
				p != save.end(); ++p) {
			p->second->close();
		}
	}
};

service::service(io_service& owner) :
		base_type(owner),
		pimpl_(new impl {
			owner,
			{
				{ Connection, "keep-alive" },
				{ UserAgent, "tip-http-client" }
			}
		})
{
}

service::~service()
{
}

void
service::shutdown_service()
{
	local_log(logger::DEBUG) << "Shutdown HTTP client service";
	pimpl_->shutdown();
}

void
service::get(std::string const& url, response_callback cb, error_callback eb)
{
	pimpl_->get(url, cb, eb);
}
void
service::post(std::string const& url, body_type const& body,
		response_callback cb, error_callback eb)
{
	pimpl_->post(url, body, cb, eb);
}
void
service::post(std::string const& url, body_type&& body,
		response_callback cb, error_callback eb)
{
	pimpl_->post(url, std::move(body), cb, eb);
}

} /* namespace client */
} /* namespace http */
} /* namespace tip */
<commit_msg>Call error callback if an exception is throwed in get_session<commit_after>/*
 * service.cpp
 *
 *  Created on: Aug 21, 2015
 *      Author: zmij
 */

#include <tip/http/client/service.hpp>
#include <tip/log.hpp>

#include <set>
#include <map>

#include <tip/http/client/session.hpp>
#include <tip/http/client/errors.hpp>
#include <tip/http/common/response.hpp>

namespace tip {
namespace http {
namespace client {

LOCAL_LOGGING_FACILITY(HTTPCLIENT, TRACE);

service::io_service::id service::id;

namespace {

const iri::scheme HTTP_SCHEME = iri::scheme{"http"};
const iri::scheme HTTPS_SCHEME = iri::scheme{"https"};

const std::set< iri::scheme > SUPPORTED_SCHEMES { HTTP_SCHEME, HTTPS_SCHEME };

}  // namespace

struct service::impl : std::enable_shared_from_this<impl> {
	typedef std::pair< iri::host, std::string > connection_id;
	// TODO multiple sessions per host
	typedef std::map< connection_id, session_ptr > session_container;

	io_service&			owner_;
	headers				default_headers_;
	session_container	sessions_;

	impl(io_service& owner, headers const& default_headers) :
		owner_(owner), default_headers_(default_headers)
	{
	}

	~impl()
	{
		local_log() << "service::impl::~impl";
	}

	void
	get(std::string const& url, response_callback cb, error_callback ecb)
	{
		request::iri_type iri;
		if (!request::parse_iri(url, iri)) {
			try {
				throw errors::http_client_error("Invalid IRI");
			} catch (std::exception const& e) {
				if (ecb) {
					ecb(std::current_exception());
				} else throw;
			}
		}
		send_request(GET, iri, session::body_type(), cb, ecb);
	}
	void
	post(std::string const& url, body_type const& body,
			response_callback cb, error_callback ecb)
	{
		request::iri_type iri;
		if (!request::parse_iri(url, iri)) {
			return;
		}
		send_request(POST, iri, body, cb, ecb);
	}
	void
	post(std::string const& url, body_type&& body,
			response_callback cb, error_callback ecb)
	{
		request::iri_type iri;
		if (!request::parse_iri(url, iri)) {
			return;
		}
		send_request(POST, iri, std::move(body), cb, ecb);
	}

	void
	send_request(request_method method, request::iri_type const& iri,
			session::body_type const& body,
			response_callback cb, error_callback ecb)
	{
		using std::placeholders::_1;
		using std::placeholders::_2;
		try {
			session_ptr s = get_session(iri);
			s->send_request(GET, iri, body,
					std::bind(&impl::handle_response,
							shared_from_this(), _1, _2, cb, ecb), ecb);
		} catch (...) {
			if (ecb) {
				ecb(std::current_exception());
			} else throw;
		}
	}
	void
	send_request(request_method method, request::iri_type const& iri,
			session::body_type&& body,
			response_callback cb, error_callback ecb)
	{
		using std::placeholders::_1;
		using std::placeholders::_2;
		try {
			session_ptr s = get_session(iri);
			s->send_request(GET, iri, std::move(body),
					std::bind(&impl::handle_response,
							shared_from_this(), _1, _2, cb, ecb), ecb);
		} catch (...) {
			if (ecb) {
				ecb(std::current_exception());
			} else throw;
		}
	}

	session_ptr
	get_session(request::iri_type const& iri)
	{
		if (SUPPORTED_SCHEMES.count(iri.scheme) == 0) {
			// TODO Throw an error - unsupported scheme
			local_log(logger::ERROR) << "IRI scheme "
					<< iri.scheme << " is not supported";
			throw std::runtime_error("Scheme not supported");
		}
		if (iri.authority.host.empty()) {
			// TODO Throw an error - empty host
			local_log(logger::ERROR) << "Host is empty";
			throw std::runtime_error("Host is empty");
		}
		connection_id cid{ iri.authority.host,
			iri.authority.port.empty() ?
					static_cast<std::string const&>(iri.scheme) :
					static_cast<std::string const&>(iri.authority.port) };
		// FIXME Add mutex
		auto f = sessions_.find(cid);
		if (f == sessions_.end()) {
			session_ptr s = create_session(iri);
			f = sessions_.insert(std::make_pair(cid, s)).first;
		}
		return f->second;
	}

	session_ptr
	create_session(request::iri_type const& iri)
	{
		return session::create(owner_, iri,
				std::bind(&impl::session_closed,
						shared_from_this(), std::placeholders::_1),
				default_headers_);
	}

	void
	handle_response(request_ptr req, response_ptr resp, response_callback cb,
			error_callback ecb)
	{
		using std::placeholders::_1;
		using std::placeholders::_2;
		int status = resp->status / 100;
		if (status == 3) {
			// Handle redirect
			headers::const_iterator f = resp->headers_.find(Location);
			if (f != resp->headers_.end()) {
				local_log(logger::DEBUG) << "Request redirected to " << f->second;
				request::iri_type iri;
				if (!request::parse_iri(f->second, iri)) {
					local_log(logger::WARNING) << "Invalid redirect location";
					cb(resp);
				} else {
					req->path = iri.path;
					req->query = iri.query;
					req->fragment = iri.fragment;
					req->host( iri.authority.host );

					session_ptr s = get_session(iri);
					s->send_request(req, std::bind(
							&impl::handle_response, this, _1, _2, cb, ecb), ecb);
				}
			} else {
				local_log(logger::WARNING) << "Request redirected, but no Location header set";
				cb(resp);
			}
		} else if (status == 4) {

			local_log(logger::WARNING) << "Received error response " << resp->status
					<< " " << resp->status_line << "\n" << *req;

			cb(resp);
		} else {
			cb(resp);
		}
	}

	void
	session_closed(session_ptr s)
	{
		local_log() << "Session closed";
		session_container::const_iterator p = sessions_.begin();
		for (; p != sessions_.end(); ++p) {
			if (p->second == s) break;
		}
		if (p != sessions_.end()) {
			sessions_.erase(p);
		}
	}

	void
	shutdown()
	{
		session_container save = sessions_;
		for (session_container::const_iterator p = save.begin();
				p != save.end(); ++p) {
			p->second->close();
		}
	}
};

service::service(io_service& owner) :
		base_type(owner),
		pimpl_(new impl {
			owner,
			{
				{ Connection, "keep-alive" },
				{ UserAgent, "tip-http-client" }
			}
		})
{
}

service::~service()
{
}

void
service::shutdown_service()
{
	local_log(logger::DEBUG) << "Shutdown HTTP client service";
	pimpl_->shutdown();
}

void
service::get(std::string const& url, response_callback cb, error_callback eb)
{
	pimpl_->get(url, cb, eb);
}
void
service::post(std::string const& url, body_type const& body,
		response_callback cb, error_callback eb)
{
	pimpl_->post(url, body, cb, eb);
}
void
service::post(std::string const& url, body_type&& body,
		response_callback cb, error_callback eb)
{
	pimpl_->post(url, std::move(body), cb, eb);
}

} /* namespace client */
} /* namespace http */
} /* namespace tip */
<|endoftext|>


<commit_before>#include <aleph/containers/PointCloud.hh>

#include <aleph/config/FLANN.hh>

#include <aleph/geometry/BruteForce.hh>
#include <aleph/geometry/FLANN.hh>

#include <aleph/geometry/distances/Euclidean.hh>
#include <aleph/geometry/distances/Manhattan.hh>
#include <aleph/geometry/distances/Traits.hh>

#include <iostream>
#include <string>
#include <vector>

#include <getopt.h>

using DataType          = double;
using PointCloud        = aleph::containers::PointCloud<DataType>;
using EuclideanDistance = aleph::distances::Euclidean<DataType>;
using ManhattanDistance = aleph::distances::Manhattan<DataType>;

template <class Distance> std::vector<DataType> pairwiseDistances( const PointCloud& pointCloud, Distance distance = Distance() )
{
  if( pointCloud.empty() )
    return {};

  std::vector<DataType> distances;
  distances.reserve( pointCloud.size() * ( pointCloud.size() - 1 ) / 2 );

  auto d       = pointCloud.dimension();
  auto n       = pointCloud.size();
  using Traits = aleph::distances::Traits<Distance>;

  Traits traits;
  for( decltype(n) i = 0; i < n; i++ )
  {
    for( decltype(n) j = i+1; j < n; j++ )
    {
      auto dist = distance( pointCloud[i].begin(),
                            pointCloud[j].begin(),
                            d );

      dist      = traits.from( dist );

      distances.emplace_back( dist );
    }
  }

  return distances;
}

int main( int argc, char** argv )
{
  static option commandLineOptions[] =
  {
    { "distance"      , required_argument, nullptr, 'd' },
    { nullptr         , 0                , nullptr,  0  }
  };

  std::string selectedDistanceFunctor = "euclidean";

  {
    int option = 0;
    while( ( option = getopt_long( argc, argv, "d:", commandLineOptions, nullptr ) ) != -1 )
    {
      switch( option )
      {
      case 'd':
        selectedDistanceFunctor = optarg;
        break;
      }
    }
  }

  if( (argc - optind) < 1 )
    return -1;

  auto filename   = std::string( argv[optind++] );
  auto pointCloud = aleph::containers::load<DataType>( filename );

  std::cerr << "* Loaded point cloud with " << pointCloud.size() << " points\n";

  std::vector<DataType> distances;

  if( selectedDistanceFunctor == "euclidean" )
    distances = pairwiseDistances( pointCloud, EuclideanDistance() );
  else if( selectedDistanceFunctor == "manhattan" )
    distances = pairwiseDistances( pointCloud, ManhattanDistance() );

  for( auto&& distance : distances )
    std::cout << distance << "\n";
}
<commit_msg>Simple JSON output for distances<commit_after>#include <aleph/containers/PointCloud.hh>

#include <aleph/config/FLANN.hh>

#include <aleph/geometry/BruteForce.hh>
#include <aleph/geometry/FLANN.hh>

#include <aleph/geometry/distances/Euclidean.hh>
#include <aleph/geometry/distances/Manhattan.hh>
#include <aleph/geometry/distances/Traits.hh>

#include <iostream>
#include <string>
#include <vector>

#include <getopt.h>

using DataType          = double;
using PointCloud        = aleph::containers::PointCloud<DataType>;
using EuclideanDistance = aleph::distances::Euclidean<DataType>;
using ManhattanDistance = aleph::distances::Manhattan<DataType>;

template <class Distance> std::vector<DataType> pairwiseDistances( const PointCloud& pointCloud, Distance distance = Distance() )
{
  if( pointCloud.empty() )
    return {};

  std::vector<DataType> distances;
  distances.reserve( pointCloud.size() * ( pointCloud.size() - 1 ) / 2 );

  auto d       = pointCloud.dimension();
  auto n       = pointCloud.size();
  using Traits = aleph::distances::Traits<Distance>;

  Traits traits;
  for( decltype(n) i = 0; i < n; i++ )
  {
    for( decltype(n) j = i+1; j < n; j++ )
    {
      auto dist = distance( pointCloud[i].begin(),
                            pointCloud[j].begin(),
                            d );

      // I want to be sure that I get the *square* of the distance, but
      // I cannot take this transformation within the distance functor,
      // such as the Manhattan distance, for granted.
      dist      = traits.from( dist );
      dist     *= dist;

      distances.emplace_back( dist );
    }
  }

  return distances;
}

template <class Container> void containerAsJSON( std::ostream& out, const Container& container, const std::string& name, unsigned indent = 2 )
{
  out << std::string( indent, ' ' ) << "\"" << name << "\": "
      << "[";

  for( auto it = container.begin(); it != container.end(); ++it )
  {
    if( it != container.begin() )
      out << ",";

    out << *it;
  }

  out << "]\n";
}

int main( int argc, char** argv )
{
  static option commandLineOptions[] =
  {
    { "distance"      , required_argument, nullptr, 'd' },
    { nullptr         , 0                , nullptr,  0  }
  };

  std::string selectedDistanceFunctor = "euclidean";

  {
    int option = 0;
    while( ( option = getopt_long( argc, argv, "d:", commandLineOptions, nullptr ) ) != -1 )
    {
      switch( option )
      {
      case 'd':
        selectedDistanceFunctor = optarg;
        break;
      }
    }
  }

  if( (argc - optind) < 1 )
    return -1;

  auto filename   = std::string( argv[optind++] );
  auto pointCloud = aleph::containers::load<DataType>( filename );

  std::cerr << "* Loaded point cloud with " << pointCloud.size() << " points\n";

  std::vector<DataType> distances;

  if( selectedDistanceFunctor == "euclidean" )
    distances = pairwiseDistances( pointCloud, EuclideanDistance() );
  else if( selectedDistanceFunctor == "manhattan" )
    distances = pairwiseDistances( pointCloud, ManhattanDistance() );

  std::cout << "{\n";

  containerAsJSON( std::cout, distances, "distances" );

  std::cout << "}\n";
}
<|endoftext|>


<commit_before>/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
** Contact: Qt Software Information (qt-info@nokia.com)
**
** This file is part of the QtDeclarative module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the either Technology Preview License Agreement or the
** Beta Release License Agreement.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain
** additional rights. These rights are described in the Nokia Qt LGPL
** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
** package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3.0 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU General Public License version 3.0 requirements will be
** met: http://www.gnu.org/copyleft/gpl.html.
**
** If you are unsure which license is appropriate for your use, please
** contact the sales department at qt-sales@nokia.com.
** $QT_END_LICENSE$
**
****************************************************************************/

#include <qml.h>
#include "qmlbindablevalue.h"
#include "qmlbindablevalue_p.h"
#include <qmlcontext.h>
#include <qmlinfo.h>
#include <QVariant>
#include <qfxperf.h>
#include <QtCore/qdebug.h>

Q_DECLARE_METATYPE(QList<QObject *>);

QT_BEGIN_NAMESPACE

DEFINE_BOOL_CONFIG_OPTION(scriptWarnings, QML_SCRIPT_WARNINGS);

QmlBindableValuePrivate::QmlBindableValuePrivate()
: inited(false), updating(false), enabled(true), mePtr(0)
{
}

QML_DEFINE_NOCREATE_TYPE(QmlBindableValue);
QmlBindableValue::QmlBindableValue(void *data, QmlRefCount *rc, QObject *obj, QmlContext *ctxt, QObject *parent)
: QmlPropertyValueSource(*new QmlBindableValuePrivate, parent), QmlExpression(ctxt, data, rc, obj)
{
}

QmlBindableValue::QmlBindableValue(const QString &str, QObject *obj, QmlContext *ctxt, QObject *parent)
: QmlPropertyValueSource(*new QmlBindableValuePrivate, parent), QmlExpression(ctxt, str, obj)
{
}

QmlBindableValue::~QmlBindableValue()
{
    Q_D(QmlBindableValue);
    if(d->mePtr)
        *(d->mePtr) = 0;
}

void QmlBindableValue::setTarget(const QmlMetaProperty &prop)
{
    Q_D(QmlBindableValue);
    d->property = prop;

    update();
}

QmlMetaProperty QmlBindableValue::property() const
{
   Q_D(const QmlBindableValue);
   return d->property;
}

void QmlBindableValue::init()
{
    Q_D(QmlBindableValue);

    if (d->inited)
        return;
    d->inited = true;
    update();
}

void QmlBindableValue::setExpression(const QString &expr)
{
    QmlExpression::setExpression(expr);
    update();
}

void QmlBindableValue::forceUpdate()
{
    Q_D(QmlBindableValue);
    if (!d->inited)
        init();
    else
        update();
}

void QmlBindableValue::update()
{
    Q_D(QmlBindableValue);

#ifdef Q_ENABLE_PERFORMANCE_LOG
    QFxPerfTimer<QFxPerf::BindableValueUpdate> bu;
#endif
    if (!d->inited || !d->enabled)
        return;

    if (!d->updating) {
        d->updating = true;

        if (d->property.propertyCategory() == QmlMetaProperty::Bindable) {

            int idx = d->property.coreIndex();
            Q_ASSERT(idx != -1);

            void *a[1];
            QmlBindableValue *t = this;
            a[0] = (void *)&t;
            QMetaObject::metacall(d->property.object(),
                                  QMetaObject::WriteProperty,
                                  idx, a);

        } else {

            QVariant value = this->value();
            if ((uint)d->property.propertyType() >= QVariant::UserType &&
                value.type() == QVariant::String) {
                QmlMetaType::StringConverter con = QmlMetaType::customStringConverter(d->property.propertyType());
                if (con)
                    value = con(value.toString());
            }

            if (d->property.propertyType() == QVariant::Url &&
                value.canConvert(QVariant::String) && !value.isNull())
                value.setValue(context()->resolvedUrl(QUrl(value.toString())));

            d->property.write(value);
        }

        d->updating = false;
    } else {
        qmlInfo(d->property.object()) << "Binding loop detected for property" << d->property.name();
    }
}

void QmlBindableValue::valueChanged()
{
    update();
}

void QmlBindableValue::setEnabled(bool e)
{
    Q_D(QmlBindableValue);
    d->enabled = e;
    setTrackChange(e);
}

bool QmlBindableValue::enabled() const
{
    Q_D(const QmlBindableValue);

    return d->enabled;
}

QT_END_NAMESPACE
<commit_msg>URL can convert from string or bytearray.<commit_after>/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
** Contact: Qt Software Information (qt-info@nokia.com)
**
** This file is part of the QtDeclarative module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the either Technology Preview License Agreement or the
** Beta Release License Agreement.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain
** additional rights. These rights are described in the Nokia Qt LGPL
** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
** package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3.0 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU General Public License version 3.0 requirements will be
** met: http://www.gnu.org/copyleft/gpl.html.
**
** If you are unsure which license is appropriate for your use, please
** contact the sales department at qt-sales@nokia.com.
** $QT_END_LICENSE$
**
****************************************************************************/

#include <qml.h>
#include "qmlbindablevalue.h"
#include "qmlbindablevalue_p.h"
#include <qmlcontext.h>
#include <qmlinfo.h>
#include <QVariant>
#include <qfxperf.h>
#include <QtCore/qdebug.h>

Q_DECLARE_METATYPE(QList<QObject *>);

QT_BEGIN_NAMESPACE

DEFINE_BOOL_CONFIG_OPTION(scriptWarnings, QML_SCRIPT_WARNINGS);

QmlBindableValuePrivate::QmlBindableValuePrivate()
: inited(false), updating(false), enabled(true), mePtr(0)
{
}

QML_DEFINE_NOCREATE_TYPE(QmlBindableValue);
QmlBindableValue::QmlBindableValue(void *data, QmlRefCount *rc, QObject *obj, QmlContext *ctxt, QObject *parent)
: QmlPropertyValueSource(*new QmlBindableValuePrivate, parent), QmlExpression(ctxt, data, rc, obj)
{
}

QmlBindableValue::QmlBindableValue(const QString &str, QObject *obj, QmlContext *ctxt, QObject *parent)
: QmlPropertyValueSource(*new QmlBindableValuePrivate, parent), QmlExpression(ctxt, str, obj)
{
}

QmlBindableValue::~QmlBindableValue()
{
    Q_D(QmlBindableValue);
    if(d->mePtr)
        *(d->mePtr) = 0;
}

void QmlBindableValue::setTarget(const QmlMetaProperty &prop)
{
    Q_D(QmlBindableValue);
    d->property = prop;

    update();
}

QmlMetaProperty QmlBindableValue::property() const
{
   Q_D(const QmlBindableValue);
   return d->property;
}

void QmlBindableValue::init()
{
    Q_D(QmlBindableValue);

    if (d->inited)
        return;
    d->inited = true;
    update();
}

void QmlBindableValue::setExpression(const QString &expr)
{
    QmlExpression::setExpression(expr);
    update();
}

void QmlBindableValue::forceUpdate()
{
    Q_D(QmlBindableValue);
    if (!d->inited)
        init();
    else
        update();
}

void QmlBindableValue::update()
{
    Q_D(QmlBindableValue);

#ifdef Q_ENABLE_PERFORMANCE_LOG
    QFxPerfTimer<QFxPerf::BindableValueUpdate> bu;
#endif
    if (!d->inited || !d->enabled)
        return;

    if (!d->updating) {
        d->updating = true;

        if (d->property.propertyCategory() == QmlMetaProperty::Bindable) {

            int idx = d->property.coreIndex();
            Q_ASSERT(idx != -1);

            void *a[1];
            QmlBindableValue *t = this;
            a[0] = (void *)&t;
            QMetaObject::metacall(d->property.object(),
                                  QMetaObject::WriteProperty,
                                  idx, a);

        } else {

            QVariant value = this->value();
            if ((uint)d->property.propertyType() >= QVariant::UserType &&
                value.type() == QVariant::String) {
                QmlMetaType::StringConverter con = QmlMetaType::customStringConverter(d->property.propertyType());
                if (con)
                    value = con(value.toString());
            }

            if (d->property.propertyType() == QVariant::Url &&
                (value.type() == QVariant::String || value.type() == QVariant::ByteArray) && !value.isNull())
                value.setValue(context()->resolvedUrl(QUrl(value.toString())));

            d->property.write(value);
        }

        d->updating = false;
    } else {
        qmlInfo(d->property.object()) << "Binding loop detected for property" << d->property.name();
    }
}

void QmlBindableValue::valueChanged()
{
    update();
}

void QmlBindableValue::setEnabled(bool e)
{
    Q_D(QmlBindableValue);
    d->enabled = e;
    setTrackChange(e);
}

bool QmlBindableValue::enabled() const
{
    Q_D(const QmlBindableValue);

    return d->enabled;
}

QT_END_NAMESPACE
<|endoftext|>


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

  Program:   Visualization Toolkit
  Module:    vtkAVIWriter.cxx

  Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
  All rights reserved.
  See Copyright.txt or http://www.kitware.com/Copyright.htm for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notice for more information.

=========================================================================*/
#include "vtkWindows.h"
#include "vtkAVIWriter.h"

#include "vtkImageData.h"
#include "vtkInformation.h"
#include "vtkObjectFactory.h"
#include "vtkStreamingDemandDrivenPipeline.h"

#include "vtkErrorCode.h"

#ifdef _MSC_VER
#pragma warning (push, 3)
#endif

#include <vfw.h>

#ifdef _MSC_VER
#pragma warning (pop)
#endif

class vtkAVIWriterInternal
{
public:
  PAVISTREAM Stream;
  PAVISTREAM StreamCompressed;
  PAVIFILE AVIFile;
  LPBITMAPINFOHEADER  lpbi;       // pointer to BITMAPINFOHEADER
  HANDLE              hDIB;  // handle to DIB, temp handle
};

//---------------------------------------------------------------------------
vtkStandardNewMacro(vtkAVIWriter);

//---------------------------------------------------------------------------
vtkAVIWriter::vtkAVIWriter()
{
  this->Internals = new vtkAVIWriterInternal;
  this->Internals->Stream = NULL;
  this->Internals->StreamCompressed = NULL;
  this->Internals->AVIFile = NULL;
  this->Time = 0;
  this->Quality = 10000;
  this->Rate = 1000;
  this->Internals->hDIB = NULL;  // handle to DIB, temp handle
  this->PromptCompressionOptions = 0;
  this->CompressorFourCC = NULL;
  this->SetCompressorFourCC("MSVC");
}

//---------------------------------------------------------------------------
vtkAVIWriter::~vtkAVIWriter()
{
  if (this->Internals->AVIFile)
    {
    this->End();
    }
  delete this->Internals;
  this->SetCompressorFourCC(NULL);
}

//---------------------------------------------------------------------------
void vtkAVIWriter::Start()
{
  // Error checking
  this->Error = 1;
  if ( this->GetInput() == NULL )
    {
    vtkErrorMacro(<<"Write:Please specify an input!");
    this->SetErrorCode(vtkGenericMovieWriter::NoInputError);
    return;
    }
  if (!this->FileName)
    {
    vtkErrorMacro(<<"Write:Please specify a FileName");
    this->SetErrorCode(vtkErrorCode::NoFileNameError);
    return;
    }

  // Fill in image information.
  this->GetInputAlgorithm(0, 0)->UpdateInformation();
  int wExtent[6];
  this->GetInputInformation(0,0)->Get(
    vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(), wExtent);
  int inputAlgPort;
  vtkAlgorithm* inputAlg = this->GetInputAlgorithm(0, 0, inputAlgPort);
  inputAlg->SetUpdateExtentToWholeExtent(inputAlgPort);

  LONG hr;
  AVISTREAMINFO strhdr;

  AVIFileInit();
  // opens AVIFile library
  hr = AVIFileOpen(&this->Internals->AVIFile, this->FileName,
                   OF_WRITE | OF_CREATE, 0L);
  if (hr != 0)
    {
    vtkErrorMacro("Unable to open " << this->FileName);
    this->SetErrorCode(vtkErrorCode::CannotOpenFileError);
    return;
    }

  // Fill in the header for the video stream....
  // The video stream will run in 15ths of a second....
  memset(&strhdr, 0, sizeof(strhdr));
  strhdr.fccType                = streamtypeVIDEO;// stream type
  strhdr.fccHandler             = 0;
  strhdr.dwScale                = 1;
  strhdr.dwRate                 = this->Rate;
  strhdr.dwQuality              = (DWORD) -1;
  strhdr.dwSuggestedBufferSize  = (wExtent[1] - wExtent[0] + 1)*
    (wExtent[3] - wExtent[2] + 1)*3;
  SetRect(&strhdr.rcFrame, 0, 0, wExtent[1] - wExtent[0] + 1,
          wExtent[3] - wExtent[2] + 1);

  // And create the stream;
  AVIFileCreateStream(this->Internals->AVIFile,  // file pointer
                      &this->Internals->Stream,  // returned stream pointer
                      &strhdr);      // stream header

  // do not want to display this dialog
  AVICOMPRESSOPTIONS opts;
  AVICOMPRESSOPTIONS FAR * aopts[1] = {&opts};
  memset(&opts, 0, sizeof(opts));

  // need to setup opts
  opts.fccType = 0;
  char fourcc[4] = {' ', ' ', ' ', ' '};
  if (this->CompressorFourCC)
    {
    size_t len = strlen(this->CompressorFourCC);
    memcpy(fourcc, this->CompressorFourCC, len > 4 ? 4 : len);
    }
  opts.fccHandler=mmioFOURCC(fourcc[0], fourcc[1], fourcc[2], fourcc[3]);
  switch (this->GetQuality())
    {
    case 0:
      opts.dwQuality = 2500;
      break;
    case 1:
      opts.dwQuality = 5000;
      break;
    default:
      opts.dwQuality = 10000;
      break;
    }

  opts.dwBytesPerSecond = 0;
  opts.dwFlags = AVICOMPRESSF_VALID;

  if (this->PromptCompressionOptions)
    {
    if (!AVISaveOptions(NULL, 0,
                        1, &this->Internals->Stream,
                        (LPAVICOMPRESSOPTIONS FAR *) &aopts))
      {
      vtkErrorMacro("Unable to save " << this->FileName);
      return;
      }
    }

  if (AVIMakeCompressedStream(&this->Internals->StreamCompressed,
                              this->Internals->Stream,
                              &opts, NULL) != AVIERR_OK)
    {
    vtkErrorMacro("Unable to compress " << this->FileName);
    this->SetErrorCode(vtkGenericMovieWriter::CanNotCompress);
    return;
    }

  DWORD               dwLen;      // size of memory block
  int dataWidth = (((wExtent[1] - wExtent[0] + 1)*3+3)/4)*4;

  dwLen = sizeof(BITMAPINFOHEADER) + dataWidth*(wExtent[3] - wExtent[2] + 1);
  this->Internals->hDIB = ::GlobalAlloc(GHND, dwLen);
  this->Internals->lpbi = (LPBITMAPINFOHEADER) ::GlobalLock(this->Internals->hDIB);

  this->Internals->lpbi->biSize = sizeof(BITMAPINFOHEADER);
  this->Internals->lpbi->biWidth = wExtent[1] - wExtent[0] + 1;
  this->Internals->lpbi->biHeight = wExtent[3] - wExtent[2] + 1;
  this->Internals->lpbi->biPlanes = 1;
  this->Internals->lpbi->biBitCount = 24;
  this->Internals->lpbi->biCompression = BI_RGB;
  this->Internals->lpbi->biClrUsed = 0;
  this->Internals->lpbi->biClrImportant = 0;
  this->Internals->lpbi->biSizeImage = dataWidth*(wExtent[3] - wExtent[2] + 1);

  if (AVIStreamSetFormat(this->Internals->StreamCompressed, 0,
                         this->Internals->lpbi, this->Internals->lpbi->biSize))
    {
    vtkErrorMacro("Unable to format " << this->FileName << " Most likely this means that the video compression scheme you seleted could not handle the data. Try selecting a different compression scheme." );
    this->SetErrorCode(vtkGenericMovieWriter::CanNotFormat);
    return;
    }

  this->Error = 0;
  this->Time = 0;
}

//---------------------------------------------------------------------------
void vtkAVIWriter::Write()
{
  if (this->Error)
    {
    return;
    }

  // get the data
  vtkImageData* input = this->GetImageDataInput(0);
  this->GetInputAlgorithm(0, 0)->UpdateWholeExtent();
  int *wExtent = input->GetExtent();

  // get the pointer to the data
  unsigned char *ptr =
    (unsigned char *)(input->GetScalarPointer());

  int dataWidth = (((wExtent[1] - wExtent[0] + 1)*3+3)/4)*4;
  int srcWidth = (wExtent[1] - wExtent[0] + 1)*3;

  // copy the data to the clipboard
  unsigned char *dest
    = (unsigned char *)this->Internals->lpbi + this->Internals->lpbi->biSize;
  int i,j;
  for (i = 0; i < this->Internals->lpbi->biHeight; i++)
    {
    for (j = 0; j < this->Internals->lpbi->biWidth; j++)
      {
      *dest++ = ptr[2];
      *dest++ = ptr[1];
      *dest++ = *ptr;
      ptr += 3;
      }
    dest = dest + (dataWidth - srcWidth);
    }

  AVIStreamWrite(this->Internals->StreamCompressed,  // stream pointer
                 this->Time, // time of this frame
                 1,        // number to write
                 (LPBYTE) this->Internals->lpbi +    // pointer to data
                 this->Internals->lpbi->biSize,
                 this->Internals->lpbi->biSizeImage,  // size of this frame
                 AVIIF_KEYFRAME,       // flags....
                 NULL, NULL);
  this->Time++;
}

//---------------------------------------------------------------------------
void vtkAVIWriter::End()
{
  ::GlobalUnlock(this->Internals->hDIB);
  if (this->Internals->Stream)
    {
    AVIStreamClose(this->Internals->Stream);
    this->Internals->Stream = NULL;
    }

  if (this->Internals->StreamCompressed)
    {
    AVIStreamClose(this->Internals->StreamCompressed);
    this->Internals->StreamCompressed = NULL;
    }

  if (this->Internals->AVIFile)
    {
    AVIFileClose(this->Internals->AVIFile);
    this->Internals->AVIFile = NULL;
    }

  AVIFileExit();          // releases AVIFile library
}

//---------------------------------------------------------------------------
void vtkAVIWriter::PrintSelf(ostream& os, vtkIndent indent)
{
  this->Superclass::PrintSelf(os, indent);
  os << indent << "Rate: " << this->Rate << endl;
  os << indent << "Quality: " << this->Quality << endl;
  os << indent << "PromptCompressionOptions: " << (this->GetPromptCompressionOptions() ? "on":"off") << endl;
  os << indent << "CompressorFourCC: "
     << (this->CompressorFourCC ? this->CompressorFourCC : "(None)") << endl;
}

<commit_msg>vtkAVIWriter: make a more informative error message<commit_after>/*=========================================================================

  Program:   Visualization Toolkit
  Module:    vtkAVIWriter.cxx

  Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
  All rights reserved.
  See Copyright.txt or http://www.kitware.com/Copyright.htm for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notice for more information.

=========================================================================*/
#include "vtkWindows.h"
#include "vtkAVIWriter.h"

#include "vtkImageData.h"
#include "vtkInformation.h"
#include "vtkObjectFactory.h"
#include "vtkStreamingDemandDrivenPipeline.h"

#include "vtkErrorCode.h"

#ifdef _MSC_VER
#pragma warning (push, 3)
#endif

#include <vfw.h>

#ifdef _MSC_VER
#pragma warning (pop)
#endif

class vtkAVIWriterInternal
{
public:
  PAVISTREAM Stream;
  PAVISTREAM StreamCompressed;
  PAVIFILE AVIFile;
  LPBITMAPINFOHEADER  lpbi;       // pointer to BITMAPINFOHEADER
  HANDLE              hDIB;  // handle to DIB, temp handle
};

//---------------------------------------------------------------------------
vtkStandardNewMacro(vtkAVIWriter);

//---------------------------------------------------------------------------
vtkAVIWriter::vtkAVIWriter()
{
  this->Internals = new vtkAVIWriterInternal;
  this->Internals->Stream = NULL;
  this->Internals->StreamCompressed = NULL;
  this->Internals->AVIFile = NULL;
  this->Time = 0;
  this->Quality = 10000;
  this->Rate = 1000;
  this->Internals->hDIB = NULL;  // handle to DIB, temp handle
  this->PromptCompressionOptions = 0;
  this->CompressorFourCC = NULL;
  this->SetCompressorFourCC("MSVC");
}

//---------------------------------------------------------------------------
vtkAVIWriter::~vtkAVIWriter()
{
  if (this->Internals->AVIFile)
    {
    this->End();
    }
  delete this->Internals;
  this->SetCompressorFourCC(NULL);
}

//---------------------------------------------------------------------------
void vtkAVIWriter::Start()
{
  // Error checking
  this->Error = 1;
  if ( this->GetInput() == NULL )
    {
    vtkErrorMacro(<<"Write:Please specify an input!");
    this->SetErrorCode(vtkGenericMovieWriter::NoInputError);
    return;
    }
  if (!this->FileName)
    {
    vtkErrorMacro(<<"Write:Please specify a FileName");
    this->SetErrorCode(vtkErrorCode::NoFileNameError);
    return;
    }

  // Fill in image information.
  this->GetInputAlgorithm(0, 0)->UpdateInformation();
  int wExtent[6];
  this->GetInputInformation(0,0)->Get(
    vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(), wExtent);
  int inputAlgPort;
  vtkAlgorithm* inputAlg = this->GetInputAlgorithm(0, 0, inputAlgPort);
  inputAlg->SetUpdateExtentToWholeExtent(inputAlgPort);

  LONG hr;
  AVISTREAMINFO strhdr;

  AVIFileInit();
  // opens AVIFile library
  hr = AVIFileOpen(&this->Internals->AVIFile, this->FileName,
                   OF_WRITE | OF_CREATE, 0L);
  if (hr != 0)
    {
    vtkErrorMacro("Unable to open " << this->FileName);
    this->SetErrorCode(vtkErrorCode::CannotOpenFileError);
    return;
    }

  // Fill in the header for the video stream....
  // The video stream will run in 15ths of a second....
  memset(&strhdr, 0, sizeof(strhdr));
  strhdr.fccType                = streamtypeVIDEO;// stream type
  strhdr.fccHandler             = 0;
  strhdr.dwScale                = 1;
  strhdr.dwRate                 = this->Rate;
  strhdr.dwQuality              = (DWORD) -1;
  strhdr.dwSuggestedBufferSize  = (wExtent[1] - wExtent[0] + 1)*
    (wExtent[3] - wExtent[2] + 1)*3;
  SetRect(&strhdr.rcFrame, 0, 0, wExtent[1] - wExtent[0] + 1,
          wExtent[3] - wExtent[2] + 1);

  // And create the stream;
  AVIFileCreateStream(this->Internals->AVIFile,  // file pointer
                      &this->Internals->Stream,  // returned stream pointer
                      &strhdr);      // stream header

  // do not want to display this dialog
  AVICOMPRESSOPTIONS opts;
  AVICOMPRESSOPTIONS FAR * aopts[1] = {&opts};
  memset(&opts, 0, sizeof(opts));

  // need to setup opts
  opts.fccType = 0;
  char fourcc[4] = {' ', ' ', ' ', ' '};
  if (this->CompressorFourCC)
    {
    size_t len = strlen(this->CompressorFourCC);
    memcpy(fourcc, this->CompressorFourCC, len > 4 ? 4 : len);
    }
  opts.fccHandler=mmioFOURCC(fourcc[0], fourcc[1], fourcc[2], fourcc[3]);
  switch (this->GetQuality())
    {
    case 0:
      opts.dwQuality = 2500;
      break;
    case 1:
      opts.dwQuality = 5000;
      break;
    default:
      opts.dwQuality = 10000;
      break;
    }

  opts.dwBytesPerSecond = 0;
  opts.dwFlags = AVICOMPRESSF_VALID;

  if (this->PromptCompressionOptions)
    {
    if (!AVISaveOptions(NULL, 0,
                        1, &this->Internals->Stream,
                        (LPAVICOMPRESSOPTIONS FAR *) &aopts))
      {
      vtkErrorMacro("Unable to save " << this->FileName);
      return;
      }
    }

  int avierr = AVIMakeCompressedStream(&this->Internals->StreamCompressed,
                              this->Internals->Stream,
                              &opts, NULL);
  if (avierr != AVIERR_OK)
    {
    vtkErrorMacro("Unable to compress " << this->FileName << ": " <<
        (avierr == AVIERR_NOCOMPRESSOR ? "unknown compressor" :
        (avierr == AVIERR_MEMORY ? "not enough memory" :
        (avierr == AVIERR_UNSUPPORTED ? "unsupported data type" :
         "unknown error"))));
    this->SetErrorCode(vtkGenericMovieWriter::CanNotCompress);
    return;
    }

  DWORD               dwLen;      // size of memory block
  int dataWidth = (((wExtent[1] - wExtent[0] + 1)*3+3)/4)*4;

  dwLen = sizeof(BITMAPINFOHEADER) + dataWidth*(wExtent[3] - wExtent[2] + 1);
  this->Internals->hDIB = ::GlobalAlloc(GHND, dwLen);
  this->Internals->lpbi = (LPBITMAPINFOHEADER) ::GlobalLock(this->Internals->hDIB);

  this->Internals->lpbi->biSize = sizeof(BITMAPINFOHEADER);
  this->Internals->lpbi->biWidth = wExtent[1] - wExtent[0] + 1;
  this->Internals->lpbi->biHeight = wExtent[3] - wExtent[2] + 1;
  this->Internals->lpbi->biPlanes = 1;
  this->Internals->lpbi->biBitCount = 24;
  this->Internals->lpbi->biCompression = BI_RGB;
  this->Internals->lpbi->biClrUsed = 0;
  this->Internals->lpbi->biClrImportant = 0;
  this->Internals->lpbi->biSizeImage = dataWidth*(wExtent[3] - wExtent[2] + 1);

  if (AVIStreamSetFormat(this->Internals->StreamCompressed, 0,
                         this->Internals->lpbi, this->Internals->lpbi->biSize))
    {
    vtkErrorMacro("Unable to format " << this->FileName << " Most likely this means that the video compression scheme you seleted could not handle the data. Try selecting a different compression scheme." );
    this->SetErrorCode(vtkGenericMovieWriter::CanNotFormat);
    return;
    }

  this->Error = 0;
  this->Time = 0;
}

//---------------------------------------------------------------------------
void vtkAVIWriter::Write()
{
  if (this->Error)
    {
    return;
    }

  // get the data
  vtkImageData* input = this->GetImageDataInput(0);
  this->GetInputAlgorithm(0, 0)->UpdateWholeExtent();
  int *wExtent = input->GetExtent();

  // get the pointer to the data
  unsigned char *ptr =
    (unsigned char *)(input->GetScalarPointer());

  int dataWidth = (((wExtent[1] - wExtent[0] + 1)*3+3)/4)*4;
  int srcWidth = (wExtent[1] - wExtent[0] + 1)*3;

  // copy the data to the clipboard
  unsigned char *dest
    = (unsigned char *)this->Internals->lpbi + this->Internals->lpbi->biSize;
  int i,j;
  for (i = 0; i < this->Internals->lpbi->biHeight; i++)
    {
    for (j = 0; j < this->Internals->lpbi->biWidth; j++)
      {
      *dest++ = ptr[2];
      *dest++ = ptr[1];
      *dest++ = *ptr;
      ptr += 3;
      }
    dest = dest + (dataWidth - srcWidth);
    }

  AVIStreamWrite(this->Internals->StreamCompressed,  // stream pointer
                 this->Time, // time of this frame
                 1,        // number to write
                 (LPBYTE) this->Internals->lpbi +    // pointer to data
                 this->Internals->lpbi->biSize,
                 this->Internals->lpbi->biSizeImage,  // size of this frame
                 AVIIF_KEYFRAME,       // flags....
                 NULL, NULL);
  this->Time++;
}

//---------------------------------------------------------------------------
void vtkAVIWriter::End()
{
  ::GlobalUnlock(this->Internals->hDIB);
  if (this->Internals->Stream)
    {
    AVIStreamClose(this->Internals->Stream);
    this->Internals->Stream = NULL;
    }

  if (this->Internals->StreamCompressed)
    {
    AVIStreamClose(this->Internals->StreamCompressed);
    this->Internals->StreamCompressed = NULL;
    }

  if (this->Internals->AVIFile)
    {
    AVIFileClose(this->Internals->AVIFile);
    this->Internals->AVIFile = NULL;
    }

  AVIFileExit();          // releases AVIFile library
}

//---------------------------------------------------------------------------
void vtkAVIWriter::PrintSelf(ostream& os, vtkIndent indent)
{
  this->Superclass::PrintSelf(os, indent);
  os << indent << "Rate: " << this->Rate << endl;
  os << indent << "Quality: " << this->Quality << endl;
  os << indent << "PromptCompressionOptions: " << (this->GetPromptCompressionOptions() ? "on":"off") << endl;
  os << indent << "CompressorFourCC: "
     << (this->CompressorFourCC ? this->CompressorFourCC : "(None)") << endl;
}

<|endoftext|>


<commit_before>/**
* @file BodyStateProvider.h
*
* @author Heinrich Mellmann
* Implementation of class BodyStateProvider
*/

#include "BodyStateProvider.h"

// Debug
#include "Tools/Debug/DebugModify.h"

BodyStateProvider::BodyStateProvider()
{

}

void BodyStateProvider::execute()
{
  // update the fall down state (written by Heinrich Mellmann at 1 am in Magdeburg)
  updateTheFallDownState();

  // ... :)
  updateTheFootState();
  PLOT("BodyStateProvider:standByLeftFoot", getBodyState().standByLeftFoot);
  PLOT("BodyStateProvider:standByRightFoot", getBodyState().standByRightFoot);
  PLOT("BodyStateProvider:foot_state_time", getFrameInfo().getTimeSince(getBodyState().foot_state_time));

  //
  updateTheLegTemperature();

}//end execute

void BodyStateProvider::updateTheFootState()
{
  bool old_standByLeftFoot = getBodyState().standByLeftFoot;
  bool old_standByRightFoot = getBodyState().standByRightFoot;

  getBodyState().standByLeftFoot = getFSRData().forceLeft() > theParams.foot_threshold;
  getBodyState().standByRightFoot = getFSRData().forceRight() > theParams.foot_threshold;

  if(old_standByLeftFoot != getBodyState().standByLeftFoot ||
     old_standByRightFoot != getBodyState().standByRightFoot)
  {
    getBodyState().foot_state_time = getFrameInfo().getTime();
  }
}//end updateTheFootState

void BodyStateProvider::updateTheFallDownState()
{
  BodyState::State old_fall_down_state = getBodyState().fall_down_state;

  // buffer the inertial data
  inertialBuffer.add(getInertialSensorData().data);

  Vector2d avg = inertialBuffer.getAverage();
  double inertialXaverage = avg.x;
  double inertialYaverage = avg.y;

  getBodyState().fall_down_state = BodyState::upright;

  if(inertialXaverage < -theParams.getup_threshold) {
    getBodyState().fall_down_state = BodyState::lying_on_left_side;
  } else if(inertialXaverage > theParams.getup_threshold) {
    getBodyState().fall_down_state = BodyState::lying_on_right_side;
  }

  if(inertialYaverage < -theParams.getup_threshold) {
    getBodyState().fall_down_state = BodyState::lying_on_back;
  } else if(inertialYaverage > theParams.getup_threshold) {
    getBodyState().fall_down_state = BodyState::lying_on_front;
  }

  if(old_fall_down_state != getBodyState().fall_down_state) {
    getBodyState().fall_down_state_time = getFrameInfo().getTime();
  }
}//end updateTheFallDownState

void BodyStateProvider::updateTheLegTemperature()
{
  static naoth::JointData::JointID leftLegId[] =
  {
    naoth::JointData::LHipPitch,
    naoth::JointData::LHipRoll,
    naoth::JointData::LKneePitch,
    naoth::JointData::LAnklePitch,
    naoth::JointData::LAnkleRoll
  };

  static naoth::JointData::JointID rightLegId[] =
  {
    naoth::JointData::RHipPitch,
    naoth::JointData::RHipRoll,
    naoth::JointData::RKneePitch,
    naoth::JointData::RAnklePitch,
    naoth::JointData::RAnkleRoll
  };

  double tempL(0);
  double tempR(0);

  for(int i = 0; i < 5; i++)
  {
    tempL = std::max(tempL, getSensorJointData().temperature[leftLegId[i]]);
    tempR = std::max(tempR, getSensorJointData().temperature[rightLegId[i]]);
  }

  getBodyState().temperatureLeftLeg = tempL;
  getBodyState().temperatureRightLeg = tempR;
}//end updateTheLegTemperature

void BodyStateProvider::updateIsLiftedUp(){
   getBodyState().isLiftedUp =  getBodyState().fall_down_state == BodyState::upright &&
                      !getBodyState().standByLeftFoot &&
                      !getBodyState().standByRightFoot && // no foot is on the ground
                       getFrameInfo().getTimeSince(getBodyState().foot_state_time) > theParams.maxTimeForLiftUp;

}<commit_msg>oops call updateIsLiftedUp<commit_after>/**
* @file BodyStateProvider.h
*
* @author Heinrich Mellmann
* Implementation of class BodyStateProvider
*/

#include "BodyStateProvider.h"

// Debug
#include "Tools/Debug/DebugModify.h"

BodyStateProvider::BodyStateProvider()
{

}

void BodyStateProvider::execute()
{
  // update the fall down state (written by Heinrich Mellmann at 1 am in Magdeburg)
  updateTheFallDownState();

  // ... :)
  updateTheFootState();
  PLOT("BodyStateProvider:standByLeftFoot", getBodyState().standByLeftFoot);
  PLOT("BodyStateProvider:standByRightFoot", getBodyState().standByRightFoot);
  PLOT("BodyStateProvider:foot_state_time", getFrameInfo().getTimeSince(getBodyState().foot_state_time));

  //
  updateTheLegTemperature();
  updateIsLiftedUp();

}//end execute

void BodyStateProvider::updateTheFootState()
{
  bool old_standByLeftFoot = getBodyState().standByLeftFoot;
  bool old_standByRightFoot = getBodyState().standByRightFoot;

  getBodyState().standByLeftFoot = getFSRData().forceLeft() > theParams.foot_threshold;
  getBodyState().standByRightFoot = getFSRData().forceRight() > theParams.foot_threshold;

  if(old_standByLeftFoot != getBodyState().standByLeftFoot ||
     old_standByRightFoot != getBodyState().standByRightFoot)
  {
    getBodyState().foot_state_time = getFrameInfo().getTime();
  }
}//end updateTheFootState

void BodyStateProvider::updateTheFallDownState()
{
  BodyState::State old_fall_down_state = getBodyState().fall_down_state;

  // buffer the inertial data
  inertialBuffer.add(getInertialSensorData().data);

  Vector2d avg = inertialBuffer.getAverage();
  double inertialXaverage = avg.x;
  double inertialYaverage = avg.y;

  getBodyState().fall_down_state = BodyState::upright;

  if(inertialXaverage < -theParams.getup_threshold) {
    getBodyState().fall_down_state = BodyState::lying_on_left_side;
  } else if(inertialXaverage > theParams.getup_threshold) {
    getBodyState().fall_down_state = BodyState::lying_on_right_side;
  }

  if(inertialYaverage < -theParams.getup_threshold) {
    getBodyState().fall_down_state = BodyState::lying_on_back;
  } else if(inertialYaverage > theParams.getup_threshold) {
    getBodyState().fall_down_state = BodyState::lying_on_front;
  }

  if(old_fall_down_state != getBodyState().fall_down_state) {
    getBodyState().fall_down_state_time = getFrameInfo().getTime();
  }
}//end updateTheFallDownState

void BodyStateProvider::updateTheLegTemperature()
{
  static naoth::JointData::JointID leftLegId[] =
  {
    naoth::JointData::LHipPitch,
    naoth::JointData::LHipRoll,
    naoth::JointData::LKneePitch,
    naoth::JointData::LAnklePitch,
    naoth::JointData::LAnkleRoll
  };

  static naoth::JointData::JointID rightLegId[] =
  {
    naoth::JointData::RHipPitch,
    naoth::JointData::RHipRoll,
    naoth::JointData::RKneePitch,
    naoth::JointData::RAnklePitch,
    naoth::JointData::RAnkleRoll
  };

  double tempL(0);
  double tempR(0);

  for(int i = 0; i < 5; i++)
  {
    tempL = std::max(tempL, getSensorJointData().temperature[leftLegId[i]]);
    tempR = std::max(tempR, getSensorJointData().temperature[rightLegId[i]]);
  }

  getBodyState().temperatureLeftLeg = tempL;
  getBodyState().temperatureRightLeg = tempR;
}//end updateTheLegTemperature

void BodyStateProvider::updateIsLiftedUp(){
   getBodyState().isLiftedUp =  getBodyState().fall_down_state == BodyState::upright &&
                      !getBodyState().standByLeftFoot &&
                      !getBodyState().standByRightFoot && // no foot is on the ground
                       getFrameInfo().getTimeSince(getBodyState().foot_state_time) > theParams.maxTimeForLiftUp;

}<|endoftext|>