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

  Program:   Visualization Toolkit
  Module:    vtkQtTreeView.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.

=========================================================================*/
/*-------------------------------------------------------------------------
  Copyright 2008 Sandia Corporation.
  Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
  the U.S. Government retains certain rights in this software.
-------------------------------------------------------------------------*/

#include "vtkQtTreeView.h"

#include <QHeaderView>
#include <QItemSelection>
#include <QTreeView>

#include "vtkAlgorithm.h"
#include "vtkAlgorithmOutput.h"
#include "vtkAnnotationLink.h"
#include "vtkConvertSelection.h"
#include "vtkDataRepresentation.h"
#include "vtkIdTypeArray.h"
#include "vtkInformation.h"
#include "vtkObjectFactory.h"
#include "vtkQtTreeModelAdapter.h"
#include "vtkSelection.h"
#include "vtkSelectionNode.h"
#include "vtkSmartPointer.h"
#include "vtkTree.h"

vtkCxxRevisionMacro(vtkQtTreeView, "1.19");
vtkStandardNewMacro(vtkQtTreeView);

//----------------------------------------------------------------------------
vtkQtTreeView::vtkQtTreeView()
{
  this->TreeView = new QTreeView();
  this->TreeAdapter = new vtkQtTreeModelAdapter();
  this->TreeView->setModel(this->TreeAdapter);

  // Set up some default properties
  this->TreeView->setSelectionMode(QAbstractItemView::ExtendedSelection);
  this->TreeView->setSelectionBehavior(QAbstractItemView::SelectRows);
  this->SetAlternatingRowColors(false);
  this->SetShowRootNode(false);
  this->Selecting = false;
  this->CurrentSelectionMTime = 0;

  // Drag/Drop parameters - defaults to off
  this->TreeView->setDragEnabled(false);
  this->TreeView->setDragDropMode(QAbstractItemView::DragOnly);
  this->TreeView->setDragDropOverwriteMode(false);
  this->TreeView->setAcceptDrops(false);
  this->TreeView->setDropIndicatorShown(false);

  QObject::connect(this->TreeView,
    SIGNAL(expanded(const QModelIndex&)),
    this, SIGNAL(expanded(const QModelIndex&)));
  QObject::connect(this->TreeView,
    SIGNAL(collapsed(const QModelIndex&)),
    this, SIGNAL(collapsed(const QModelIndex&)));

  QObject::connect(this->TreeView->selectionModel(),
      SIGNAL(selectionChanged(const QItemSelection&,const QItemSelection&)),
      this,
      SLOT(slotQtSelectionChanged(const QItemSelection&,const QItemSelection&)));
}

//----------------------------------------------------------------------------
vtkQtTreeView::~vtkQtTreeView()
{
  if(this->TreeView)
    {
    delete this->TreeView;
    }
  delete this->TreeAdapter;
}

//----------------------------------------------------------------------------
QWidget* vtkQtTreeView::GetWidget()
{
  return this->TreeView;
}

//----------------------------------------------------------------------------
void vtkQtTreeView::SetShowHeaders(bool state)
{
  if (state)
    {
    this->TreeView->header()->show();
    }
  else
    {
    this->TreeView->header()->hide();
    }
}

//----------------------------------------------------------------------------
void vtkQtTreeView::SetAlternatingRowColors(bool state)
{
  this->TreeView->setAlternatingRowColors(state);
}

//----------------------------------------------------------------------------
void vtkQtTreeView::SetEnableDragDrop(bool state)
{
  this->TreeView->setDragEnabled(state);
}

//----------------------------------------------------------------------------
void vtkQtTreeView::SetShowRootNode(bool state)
{
  if (!state)
    {
    this->TreeView->setRootIndex(this->TreeView->model()->index(0,0));
    }
  else
    {
    this->TreeView->setRootIndex(QModelIndex());
    }
}

//----------------------------------------------------------------------------
void vtkQtTreeView::HideColumn(int i)
{
  this->TreeView->hideColumn(i);
}

//----------------------------------------------------------------------------
void vtkQtTreeView::SetItemDelegate(QAbstractItemDelegate* delegate)
{
  this->TreeView->setItemDelegate(delegate);
}

//----------------------------------------------------------------------------
void vtkQtTreeView::AddInputConnection(
  vtkAlgorithmOutput* vtkNotUsed(conn), vtkAlgorithmOutput* vtkNotUsed(selectionConn))
{

}

//----------------------------------------------------------------------------
void vtkQtTreeView::RemoveInputConnection(
  vtkAlgorithmOutput* vtkNotUsed(conn), vtkAlgorithmOutput* vtkNotUsed(selectionConn))
{

}

//----------------------------------------------------------------------------
void vtkQtTreeView::slotQtSelectionChanged(const QItemSelection& vtkNotUsed(s1), const QItemSelection& vtkNotUsed(s2))
{
  this->Selecting = true;

  // Convert from a QModelIndexList to an index based vtkSelection
  const QModelIndexList qmil = this->TreeView->selectionModel()->selectedRows();
  vtkSelection *VTKIndexSelectList = this->TreeAdapter->QModelIndexListToVTKIndexSelection(qmil);

  // Convert to the correct type of selection
  vtkDataRepresentation* rep = this->GetRepresentation();
  vtkDataObject* data = this->TreeAdapter->GetVTKDataObject();
  vtkSmartPointer<vtkSelection> converted;
  converted.TakeReference(vtkConvertSelection::ToSelectionType(
    VTKIndexSelectList, data, rep->GetSelectionType(), rep->GetSelectionArrayNames()));

  // Call select on the representation (all 'linked' views will receive this selection)
  rep->Select(this, converted);

  this->Selecting = false;

  // Delete the selection list
  VTKIndexSelectList->Delete();

  // Store the selection mtime
  this->CurrentSelectionMTime = rep->GetAnnotationLink()->GetCurrentSelection()->GetMTime();
}

//----------------------------------------------------------------------------
void vtkQtTreeView::SetVTKSelection()
{
  // Make the selection current
  if (this->Selecting)
    {
    // If we initiated the selection, do nothing.
    return;
    }

  // Check to see we actually have data
  vtkDataObject *d = this->TreeAdapter->GetVTKDataObject();
  if (!d)
    {
    return;
    }

  // See if the selection has changed in any way
  vtkDataRepresentation* rep = this->GetRepresentation();
  vtkSelection* s = rep->GetAnnotationLink()->GetCurrentSelection();

  vtkSmartPointer<vtkSelection> selection;
  selection.TakeReference(vtkConvertSelection::ToSelectionType(
    s, d, vtkSelectionNode::INDICES, 0, vtkSelectionNode::VERTEX));

  QItemSelection qisList = this->TreeAdapter->
    VTKIndexSelectionToQItemSelection(selection);

  // Here we want the qt model to have it's selection changed
  // but we don't want to emit the selection.
  QObject::disconnect(this->TreeView->selectionModel(),
    SIGNAL(selectionChanged(const QItemSelection&,const QItemSelection&)),
    this, SLOT(slotQtSelectionChanged(const QItemSelection&,const QItemSelection&)));

  this->TreeView->selectionModel()->select(qisList,
    QItemSelectionModel::ClearAndSelect | QItemSelectionModel::Rows);

  QObject::connect(this->TreeView->selectionModel(),
   SIGNAL(selectionChanged(const QItemSelection&,const QItemSelection&)),
   this, SLOT(slotQtSelectionChanged(const QItemSelection&,const QItemSelection&)));

  // Make sure selected items are visible
  // FIXME: Should really recurse up all levels of the tree, this just does one.
  for(int i=0; i<qisList.size(); ++i)
    {
    this->TreeView->setExpanded(qisList[i].parent(), true);
    }
}

//----------------------------------------------------------------------------
void vtkQtTreeView::Update()
{
  vtkDataRepresentation* rep = this->GetRepresentation();
  if (!rep)
    {
    // Remove VTK data from the adapter
    this->TreeAdapter->SetVTKDataObject(0);
    this->TreeView->update();
    return;
    }
  rep->Update();

  // Make the data current
  vtkAlgorithm* alg = rep->GetInputConnection()->GetProducer();
  alg->Update();
  vtkDataObject *d = alg->GetOutputDataObject(0);
  vtkTree *tree = vtkTree::SafeDownCast(d);

  // Special-case: if our input is missing or not-a-tree, quietly exit.
  if(!tree)
    {
    //vtkErrorMacro("vtkQtTreeView requires a vtkTree as input");
    return;
    }

  // See if this is the same tree I already have
  if ((this->TreeAdapter->GetVTKDataObject() != tree) ||
      (this->TreeAdapter->GetVTKDataObjectMTime() != tree->GetMTime()))
    {
    this->TreeAdapter->SetVTKDataObject(tree);

    // Refresh the view
    this->TreeView->update();
    this->TreeView->expandAll();
    this->TreeView->resizeColumnToContents(0);
    this->TreeView->collapseAll();
    this->SetShowRootNode(false);
    }

  if(rep->GetAnnotationLink()->GetCurrentSelection()->GetMTime() !=
    this->CurrentSelectionMTime)
    {
    // Update the VTK selection
    this->SetVTKSelection();

    this->CurrentSelectionMTime =
      rep->GetAnnotationLink()->GetCurrentSelection()->GetMTime();
    }
}

//----------------------------------------------------------------------------
void vtkQtTreeView::PrintSelf(ostream& os, vtkIndent indent)
{
  this->Superclass::PrintSelf(os,indent);
}

<commit_msg>BUG: A valid, but empty, tree was making the adapter/view crash later. So also testing for an "empty" tree.<commit_after>/*=========================================================================

  Program:   Visualization Toolkit
  Module:    vtkQtTreeView.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.

=========================================================================*/
/*-------------------------------------------------------------------------
  Copyright 2008 Sandia Corporation.
  Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
  the U.S. Government retains certain rights in this software.
-------------------------------------------------------------------------*/

#include "vtkQtTreeView.h"

#include <QHeaderView>
#include <QItemSelection>
#include <QTreeView>

#include "vtkAlgorithm.h"
#include "vtkAlgorithmOutput.h"
#include "vtkAnnotationLink.h"
#include "vtkConvertSelection.h"
#include "vtkDataRepresentation.h"
#include "vtkIdTypeArray.h"
#include "vtkInformation.h"
#include "vtkObjectFactory.h"
#include "vtkQtTreeModelAdapter.h"
#include "vtkSelection.h"
#include "vtkSelectionNode.h"
#include "vtkSmartPointer.h"
#include "vtkTree.h"

vtkCxxRevisionMacro(vtkQtTreeView, "1.20");
vtkStandardNewMacro(vtkQtTreeView);

//----------------------------------------------------------------------------
vtkQtTreeView::vtkQtTreeView()
{
  this->TreeView = new QTreeView();
  this->TreeAdapter = new vtkQtTreeModelAdapter();
  this->TreeView->setModel(this->TreeAdapter);

  // Set up some default properties
  this->TreeView->setSelectionMode(QAbstractItemView::ExtendedSelection);
  this->TreeView->setSelectionBehavior(QAbstractItemView::SelectRows);
  this->SetAlternatingRowColors(false);
  this->SetShowRootNode(false);
  this->Selecting = false;
  this->CurrentSelectionMTime = 0;

  // Drag/Drop parameters - defaults to off
  this->TreeView->setDragEnabled(false);
  this->TreeView->setDragDropMode(QAbstractItemView::DragOnly);
  this->TreeView->setDragDropOverwriteMode(false);
  this->TreeView->setAcceptDrops(false);
  this->TreeView->setDropIndicatorShown(false);

  QObject::connect(this->TreeView,
    SIGNAL(expanded(const QModelIndex&)),
    this, SIGNAL(expanded(const QModelIndex&)));
  QObject::connect(this->TreeView,
    SIGNAL(collapsed(const QModelIndex&)),
    this, SIGNAL(collapsed(const QModelIndex&)));

  QObject::connect(this->TreeView->selectionModel(),
      SIGNAL(selectionChanged(const QItemSelection&,const QItemSelection&)),
      this,
      SLOT(slotQtSelectionChanged(const QItemSelection&,const QItemSelection&)));
}

//----------------------------------------------------------------------------
vtkQtTreeView::~vtkQtTreeView()
{
  if(this->TreeView)
    {
    delete this->TreeView;
    }
  delete this->TreeAdapter;
}

//----------------------------------------------------------------------------
QWidget* vtkQtTreeView::GetWidget()
{
  return this->TreeView;
}

//----------------------------------------------------------------------------
void vtkQtTreeView::SetShowHeaders(bool state)
{
  if (state)
    {
    this->TreeView->header()->show();
    }
  else
    {
    this->TreeView->header()->hide();
    }
}

//----------------------------------------------------------------------------
void vtkQtTreeView::SetAlternatingRowColors(bool state)
{
  this->TreeView->setAlternatingRowColors(state);
}

//----------------------------------------------------------------------------
void vtkQtTreeView::SetEnableDragDrop(bool state)
{
  this->TreeView->setDragEnabled(state);
}

//----------------------------------------------------------------------------
void vtkQtTreeView::SetShowRootNode(bool state)
{
  if (!state)
    {
    this->TreeView->setRootIndex(this->TreeView->model()->index(0,0));
    }
  else
    {
    this->TreeView->setRootIndex(QModelIndex());
    }
}

//----------------------------------------------------------------------------
void vtkQtTreeView::HideColumn(int i)
{
  this->TreeView->hideColumn(i);
}

//----------------------------------------------------------------------------
void vtkQtTreeView::SetItemDelegate(QAbstractItemDelegate* delegate)
{
  this->TreeView->setItemDelegate(delegate);
}

//----------------------------------------------------------------------------
void vtkQtTreeView::AddInputConnection(
  vtkAlgorithmOutput* vtkNotUsed(conn), vtkAlgorithmOutput* vtkNotUsed(selectionConn))
{

}

//----------------------------------------------------------------------------
void vtkQtTreeView::RemoveInputConnection(
  vtkAlgorithmOutput* vtkNotUsed(conn), vtkAlgorithmOutput* vtkNotUsed(selectionConn))
{

}

//----------------------------------------------------------------------------
void vtkQtTreeView::slotQtSelectionChanged(const QItemSelection& vtkNotUsed(s1), const QItemSelection& vtkNotUsed(s2))
{
  this->Selecting = true;

  // Convert from a QModelIndexList to an index based vtkSelection
  const QModelIndexList qmil = this->TreeView->selectionModel()->selectedRows();
  vtkSelection *VTKIndexSelectList = this->TreeAdapter->QModelIndexListToVTKIndexSelection(qmil);

  // Convert to the correct type of selection
  vtkDataRepresentation* rep = this->GetRepresentation();
  vtkDataObject* data = this->TreeAdapter->GetVTKDataObject();
  vtkSmartPointer<vtkSelection> converted;
  converted.TakeReference(vtkConvertSelection::ToSelectionType(
    VTKIndexSelectList, data, rep->GetSelectionType(), rep->GetSelectionArrayNames()));

  // Call select on the representation (all 'linked' views will receive this selection)
  rep->Select(this, converted);

  this->Selecting = false;

  // Delete the selection list
  VTKIndexSelectList->Delete();

  // Store the selection mtime
  this->CurrentSelectionMTime = rep->GetAnnotationLink()->GetCurrentSelection()->GetMTime();
}

//----------------------------------------------------------------------------
void vtkQtTreeView::SetVTKSelection()
{
  // Make the selection current
  if (this->Selecting)
    {
    // If we initiated the selection, do nothing.
    return;
    }

  // Check to see we actually have data
  vtkDataObject *d = this->TreeAdapter->GetVTKDataObject();
  if (!d)
    {
    return;
    }

  // See if the selection has changed in any way
  vtkDataRepresentation* rep = this->GetRepresentation();
  vtkSelection* s = rep->GetAnnotationLink()->GetCurrentSelection();

  vtkSmartPointer<vtkSelection> selection;
  selection.TakeReference(vtkConvertSelection::ToSelectionType(
    s, d, vtkSelectionNode::INDICES, 0, vtkSelectionNode::VERTEX));

  QItemSelection qisList = this->TreeAdapter->
    VTKIndexSelectionToQItemSelection(selection);

  // Here we want the qt model to have it's selection changed
  // but we don't want to emit the selection.
  QObject::disconnect(this->TreeView->selectionModel(),
    SIGNAL(selectionChanged(const QItemSelection&,const QItemSelection&)),
    this, SLOT(slotQtSelectionChanged(const QItemSelection&,const QItemSelection&)));

  this->TreeView->selectionModel()->select(qisList,
    QItemSelectionModel::ClearAndSelect | QItemSelectionModel::Rows);

  QObject::connect(this->TreeView->selectionModel(),
   SIGNAL(selectionChanged(const QItemSelection&,const QItemSelection&)),
   this, SLOT(slotQtSelectionChanged(const QItemSelection&,const QItemSelection&)));

  // Make sure selected items are visible
  // FIXME: Should really recurse up all levels of the tree, this just does one.
  for(int i=0; i<qisList.size(); ++i)
    {
    this->TreeView->setExpanded(qisList[i].parent(), true);
    }
}

//----------------------------------------------------------------------------
void vtkQtTreeView::Update()
{
  vtkDataRepresentation* rep = this->GetRepresentation();
  if (!rep)
    {
    // Remove VTK data from the adapter
    this->TreeAdapter->SetVTKDataObject(0);
    this->TreeView->update();
    return;
    }
  rep->Update();

  // Make the data current
  vtkAlgorithm* alg = rep->GetInputConnection()->GetProducer();
  alg->Update();
  vtkDataObject *d = alg->GetOutputDataObject(0);
  vtkTree *tree = vtkTree::SafeDownCast(d);

  // Special-case: if our input is missing or not-a-tree, or empty then quietly exit.
  if(!tree || !tree->GetNumberOfVertices())
    {
    return;
    }

  // See if this is the same tree I already have
  if ((this->TreeAdapter->GetVTKDataObject() != tree) ||
      (this->TreeAdapter->GetVTKDataObjectMTime() != tree->GetMTime()))
    {
    this->TreeAdapter->SetVTKDataObject(tree);

    // Refresh the view
    this->TreeView->update();
    this->TreeView->expandAll();
    this->TreeView->resizeColumnToContents(0);
    this->TreeView->collapseAll();
    this->SetShowRootNode(false);
    }

  if(rep->GetAnnotationLink()->GetCurrentSelection()->GetMTime() !=
    this->CurrentSelectionMTime)
    {
    // Update the VTK selection
    this->SetVTKSelection();

    this->CurrentSelectionMTime =
      rep->GetAnnotationLink()->GetCurrentSelection()->GetMTime();
    }
}

//----------------------------------------------------------------------------
void vtkQtTreeView::PrintSelf(ostream& os, vtkIndent indent)
{
  this->Superclass::PrintSelf(os,indent);
}

<|endoftext|>


<commit_before>/**
 * Appcelerator Titanium - licensed under the Apache Public License 2
 * see LICENSE in the root folder for details on the license.
 * Copyright (c) 2009 Appcelerator, Inc. All Rights Reserved.
 */
#include "file_stream.h"
#include <cstring>
#include <sstream>

#include <Poco/LineEndingConverter.h>

namespace ti
{
	FileStream::FileStream(std::string filenameIn) :
		StaticBoundObject("Filesystem.FileStream"),
		stream(0)
	{
#ifdef OS_OSX
		// in OSX, we need to expand ~ in paths to their absolute path value
		// we do that with a nifty helper method in NSString
		this->filename = [[[NSString stringWithUTF8String:filenameIn.c_str()]
			 stringByExpandingTildeInPath] fileSystemRepresentation];
#else
		this->filename = filenameIn;
#endif

		this->SetMethod("open", &FileStream::Open);
		this->SetMethod("close", &FileStream::Close);
		this->SetMethod("read", &FileStream::Read);
		this->SetMethod("readLine", &FileStream::ReadLine);
		this->SetMethod("write", &FileStream::Write);
		this->SetMethod("writeLine", &FileStream::WriteLine);
		this->SetMethod("ready", &FileStream::Ready);
		this->SetMethod("isOpen", &FileStream::IsOpen);

		this->Set("MODE_READ", Value::NewInt(MODE_READ));
		this->Set("MODE_APPEND", Value::NewInt(MODE_APPEND));
		this->Set("MODE_WRITE", Value::NewInt(MODE_WRITE));
	}

	FileStream::~FileStream()
	{
		this->Close();
	}

	void FileStream::Open(const ValueList& args, KValueRef result)
	{
		FileStreamMode mode = MODE_READ;
		bool binary = false;
		bool append = false;

		if (args.size() >= 1)
			mode = (FileStreamMode) args.at(0)->ToInt();

		if (args.size() >= 2)
				binary = args.at(1)->ToBool();

		if (args.size() >= 3)
			append = args.at(2)->ToBool();

		bool opened = this->Open(mode, binary, append);
		result->SetBool(opened);
	}

	bool FileStream::Open(FileStreamMode mode, bool binary, bool append)
	{
		// close the prev stream if needed
		this->Close();

		try
		{
			std::ios::openmode flags = (std::ios::openmode) 0;
			bool output = false;
			if (binary)
			{
				flags|=std::ios::binary;
			}
			if (mode == MODE_APPEND)
			{
				flags|=std::ios::out|std::ios::app;
				output = true;
			}
			else if (mode == MODE_WRITE)
			{
				flags |= std::ios::out|std::ios::trunc;
				output = true;
			}
			else if (mode == MODE_READ)
			{
				flags |= std::ios::in;
			}
			if (output)
			{
				this->stream = new Poco::FileOutputStream(this->filename,flags);
#ifndef OS_WIN32
				chmod(this->filename.c_str(),S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH);
#endif
			}
			else
			{
				this->stream = new Poco::FileInputStream(this->filename,flags);
			}
			return true;
		}
		catch (Poco::Exception& exc)
		{
			Logger* logger = Logger::Get("Filesystem.FileStream");
			logger->Error("Error in open. Exception: %s",exc.displayText().c_str());
			throw ValueException::FromString(exc.displayText());
		}
	}

	void FileStream::Close(const ValueList& args, KValueRef result)
	{
		bool closed = this->Close();
		result->SetBool(closed);
	}

	bool FileStream::Close()
	{
		try
		{
			if (this->stream)
			{
				Poco::FileOutputStream* fos = dynamic_cast<Poco::FileOutputStream*>(this->stream);
				if (fos)
				{
					fos->flush();
				}
				this->stream->close();
				delete this->stream;
				this->stream = NULL;
				return true;
			}
		}
		catch (Poco::Exception& exc)
		{
			Logger* logger = Logger::Get("Filesystem.FileStream");
			logger->Error("Error in close. Exception: %s",exc.displayText().c_str());
			throw ValueException::FromString(exc.displayText());
		}

		return false;
	}

	void FileStream::Write(const ValueList& args, KValueRef result)
	{
		char *text = NULL;
		int size = 0;
		if (args.at(0)->IsObject())
		{
			KObjectRef b = args.at(0)->ToObject();
			AutoPtr<Bytes> bytes = b.cast<Bytes>();
			if (!bytes.isNull())
			{
				text = (char*)bytes->Get();
				size = (int)bytes->Length();
			}
		}
		else if (args.at(0)->IsString())
		{
			text = (char*)args.at(0)->ToString();
		}
		else if (args.at(0)->IsInt())
		{
			std::stringstream ostr;
			ostr << args.at(0)->ToInt();
			text = (char*)ostr.str().c_str();
			size = ostr.str().length();
		}
		else if (args.at(0)->IsDouble())
		{
			std::stringstream ostr;
			ostr << args.at(0)->ToDouble();
			text = (char*)ostr.str().c_str();
			size = ostr.str().length();
		}
		else
		{
			throw ValueException::FromString("Could not write with type passed");
		}

		if (size==0)
		{
			size = strlen(text);
		}

		if (text == NULL)
		{
			result->SetBool(false);
			return;
		}
		if (size <= 0)
		{
			result->SetBool(false);
			return;
		}
		Write(text,size);
		result->SetBool(true);
	}

	void FileStream::Write(char *text, int size)
	{
		try
		{
			Poco::FileOutputStream* fos = dynamic_cast<Poco::FileOutputStream*>(this->stream);
			if(!fos)
			{
				throw ValueException::FromString("FileStream must be opened for writing before calling write");
			}

			fos->write(text, size);
		}
		catch (Poco::Exception& exc)
		{
			Logger* logger = Logger::Get("Filesystem.FileStream");
			logger->Error("Error in write. Exception: %s",exc.displayText().c_str());
			throw ValueException::FromString(exc.displayText());
		}
	}

	void FileStream::Read(const ValueList& args, KValueRef result)
	{
		if (!this->stream)
		{
			Logger* logger = Logger::Get("Filesystem.FileStream");
			logger->Error("Error in read. FileStream must be opened before calling read");
			throw ValueException::FromString("FileStream must be opened before calling read");
		}

		try
		{
			Poco::FileInputStream* fileStream = dynamic_cast<Poco::FileInputStream*>(this->stream);
			if (!fileStream)
			{
				Logger* logger = Logger::Get("Filesystem.FileStream");
				logger->Error("Error in read. FileInputStream is null");
				throw ValueException::FromString("FileStream must be opened for reading before calling read");
			}

			std::vector<char> buffer;
			char data[4096];

			while (!fileStream->eof())
			{
				fileStream->read((char*)&data, 4095);
				int length = fileStream->gcount();
				if (length > 0)
				{
					buffer.insert(buffer.end(), data, data+length);
				}
				else break;
			}

			result->SetObject(new Bytes(&(buffer[0]), buffer.size()));
		}
		catch (Poco::Exception& exc)
		{
			Logger* logger = Logger::Get("Filesystem.FileStream");
			logger->Error("Error in read. Exception: %s",exc.displayText().c_str());
			throw ValueException::FromString(exc.displayText());
		}
	}

	void FileStream::ReadLine(const ValueList& args, KValueRef result)
	{
		if (!this->stream)
		{
			Logger* logger = Logger::Get("Filesystem.FileStream");
			logger->Error("Error in readLine. FileStream must be opened before calling read");
			throw ValueException::FromString("FileStream must be opened before calling readLine");
		}

		try
		{
			Poco::FileInputStream* fis = dynamic_cast<Poco::FileInputStream*>(this->stream);
			if (!fis)
			{
				Logger* logger = Logger::Get("Filesystem.FileStream");
				logger->Error("Error in readLine. FileInputStream is null");
				throw ValueException::FromString("FileStream must be opened for reading before calling readLine");
			}

			if (fis->eof())
			{
				// close the file
				result->SetNull();
			}
			else
			{
				std::string line;
				std::getline(*fis, line);
#ifdef OS_WIN32
				// In some cases std::getline leaves a CR on the end of the line in win32 -- why God, why?
				if (!line.empty())
				{
					char lastChar = line.at(line.size()-1);
					if (lastChar == '\r') {
						line = line.substr(0, line.size()-1);
					}
				}
#endif
				if (line.empty() || line.size()==0)
				{
					if (fis->eof())
					{
						// if this is EOF, return null
						result->SetNull();
					}
					else
					{
						// this is an empty line, just empty Bytes object.
						result->SetObject(new Bytes());
					}
				}
				else
				{
					result->SetObject(new Bytes((std::string)line));
				}
			}
		}
		catch (Poco::Exception& exc)
		{
			Logger* logger = Logger::Get("Filesystem.FileStream");
			logger->Error("Error in readLine. Exception: %s",exc.displayText().c_str());
			throw ValueException::FromString(exc.displayText());
		}
	}

	void FileStream::WriteLine(const ValueList& args, KValueRef result)
	{
		if(! this->stream)
		{
			throw ValueException::FromString("FileStream must be opened before calling readLine");
		}
		char *text = NULL;
		int size = 0;
		if (args.at(0)->IsObject())
		{
			KObjectRef b = args.at(0)->ToObject();
			AutoPtr<Bytes> bytes = b.cast<Bytes>();
			if (!bytes.isNull())
			{
				text = (char*)bytes->Get();
				size = (int)bytes->Length();
			}
		}
		else if (args.at(0)->IsString())
		{
			text = (char*)args.at(0)->ToString();
		}
		else if (args.at(0)->IsInt())
		{
			std::stringstream ostr;
			ostr << args.at(0)->ToInt();
			text = (char*)ostr.str().c_str();
			size = ostr.str().length();
		}
		else if (args.at(0)->IsDouble())
		{
			std::stringstream ostr;
			ostr << args.at(0)->ToDouble();
			text = (char*)ostr.str().c_str();
			size = ostr.str().length();
		}
		else
		{
			throw ValueException::FromString("Could not write with type passed");
		}

		if (size==0)
		{
			size = strlen(text);
		}

		if (text == NULL)
		{
			result->SetBool(false);
			return;
		}
		if (size <= 0)
		{
			result->SetBool(false);
			return;
		}
		std::string astr = text;
#ifdef OS_WIN32
		astr += "\r\n";
#else
		astr += "\n";
#endif
		Write((char*)astr.c_str(),astr.length());
		result->SetBool(true);
	}

	void FileStream::Ready(const ValueList& args, KValueRef result)
	{
		Poco::FileIOS* fis = this->stream;
		if(!fis)
		{
			result->SetBool(false);
		}
		else
		{
			result->SetBool(fis->eof()==false);
		}
	}

	void FileStream::IsOpen(const ValueList& args, KValueRef result)
	{
		Poco::FileIOS* fis = this->stream;
		result->SetBool(fis!=NULL);
	}

}
<commit_msg>A bit of code cleanup.<commit_after>/**
 * Appcelerator Titanium - licensed under the Apache Public License 2
 * see LICENSE in the root folder for details on the license.
 * Copyright (c) 2009 Appcelerator, Inc. All Rights Reserved.
 */
#include "file_stream.h"
#include <cstring>
#include <sstream>

#include <Poco/LineEndingConverter.h>

namespace ti
{
	FileStream::FileStream(std::string filenameIn) :
		StaticBoundObject("Filesystem.FileStream"),
		stream(0)
	{
#ifdef OS_OSX
		// in OSX, we need to expand ~ in paths to their absolute path value
		// we do that with a nifty helper method in NSString
		this->filename = [[[NSString stringWithUTF8String:filenameIn.c_str()]
			 stringByExpandingTildeInPath] fileSystemRepresentation];
#else
		this->filename = filenameIn;
#endif

		this->SetMethod("open", &FileStream::Open);
		this->SetMethod("close", &FileStream::Close);
		this->SetMethod("read", &FileStream::Read);
		this->SetMethod("readLine", &FileStream::ReadLine);
		this->SetMethod("write", &FileStream::Write);
		this->SetMethod("writeLine", &FileStream::WriteLine);
		this->SetMethod("ready", &FileStream::Ready);
		this->SetMethod("isOpen", &FileStream::IsOpen);

		this->Set("MODE_READ", Value::NewInt(MODE_READ));
		this->Set("MODE_APPEND", Value::NewInt(MODE_APPEND));
		this->Set("MODE_WRITE", Value::NewInt(MODE_WRITE));
	}

	FileStream::~FileStream()
	{
		this->Close();
	}

	void FileStream::Open(const ValueList& args, KValueRef result)
	{
		args.VerifyException("open", "?ibb");

		FileStreamMode mode = (FileStreamMode) args.GetInt(0, MODE_READ);
		bool binary = args.GetBool(1, false);
		bool append = args.GetBool(2, false);

		bool opened = this->Open(mode, binary, append);
		result->SetBool(opened);
	}

	bool FileStream::Open(FileStreamMode mode, bool binary, bool append)
	{
		// close the prev stream if needed
		this->Close();

		try
		{
			std::ios::openmode flags = (std::ios::openmode) 0;
			bool output = false;
			if (binary)
			{
				flags|=std::ios::binary;
			}
			if (mode == MODE_APPEND)
			{
				flags|=std::ios::out|std::ios::app;
				output = true;
			}
			else if (mode == MODE_WRITE)
			{
				flags |= std::ios::out|std::ios::trunc;
				output = true;
			}
			else if (mode == MODE_READ)
			{
				flags |= std::ios::in;
			}
			if (output)
			{
				this->stream = new Poco::FileOutputStream(this->filename,flags);
#ifndef OS_WIN32
				chmod(this->filename.c_str(),S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH);
#endif
			}
			else
			{
				this->stream = new Poco::FileInputStream(this->filename,flags);
			}
			return true;
		}
		catch (Poco::Exception& exc)
		{
			Logger* logger = Logger::Get("Filesystem.FileStream");
			logger->Error("Error in open. Exception: %s",exc.displayText().c_str());
			throw ValueException::FromString(exc.displayText());
		}
	}

	void FileStream::Close(const ValueList& args, KValueRef result)
	{
		bool closed = this->Close();
		result->SetBool(closed);
	}

	bool FileStream::Close()
	{
		try
		{
			if (this->stream)
			{
				Poco::FileOutputStream* fos = dynamic_cast<Poco::FileOutputStream*>(this->stream);
				if (fos)
				{
					fos->flush();
				}
				this->stream->close();
				delete this->stream;
				this->stream = NULL;
				return true;
			}
		}
		catch (Poco::Exception& exc)
		{
			Logger* logger = Logger::Get("Filesystem.FileStream");
			logger->Error("Error in close. Exception: %s",exc.displayText().c_str());
			throw ValueException::FromString(exc.displayText());
		}

		return false;
	}

	void FileStream::Write(const ValueList& args, KValueRef result)
	{
		args.VerifyException("write", "s|o|n");

		char *text = NULL;
		int size = 0;
		if (args.at(0)->IsObject())
		{
			KObjectRef b = args.at(0)->ToObject();
			AutoPtr<Bytes> bytes = b.cast<Bytes>();
			if (!bytes.isNull())
			{
				text = (char*)bytes->Get();
				size = (int)bytes->Length();
			}
		}
		else if (args.at(0)->IsString())
		{
			text = (char*)args.at(0)->ToString();
		}
		else if (args.at(0)->IsInt())
		{
			std::stringstream ostr;
			ostr << args.at(0)->ToInt();
			text = (char*)ostr.str().c_str();
			size = ostr.str().length();
		}
		else if (args.at(0)->IsDouble())
		{
			std::stringstream ostr;
			ostr << args.at(0)->ToDouble();
			text = (char*)ostr.str().c_str();
			size = ostr.str().length();
		}
		else
		{
			throw ValueException::FromString("Could not write with type passed");
		}

		if (size==0)
		{
			size = strlen(text);
		}

		if (text == NULL || size <= 0)
		{
			result->SetBool(false);
			return;
		}

		Write(text,size);
		result->SetBool(true);
	}

	void FileStream::Write(char *text, int size)
	{
		try
		{
			Poco::FileOutputStream* fos = dynamic_cast<Poco::FileOutputStream*>(this->stream);
			if(!fos)
			{
				throw ValueException::FromString("FileStream must be opened for writing before calling write");
			}

			fos->write(text, size);
		}
		catch (Poco::Exception& exc)
		{
			Logger* logger = Logger::Get("Filesystem.FileStream");
			logger->Error("Error in write. Exception: %s",exc.displayText().c_str());
			throw ValueException::FromString(exc.displayText());
		}
	}

	void FileStream::Read(const ValueList& args, KValueRef result)
	{
		if (!this->stream)
		{
			Logger* logger = Logger::Get("Filesystem.FileStream");
			logger->Error("Error in read. FileStream must be opened before calling read");
			throw ValueException::FromString("FileStream must be opened before calling read");
		}

		try
		{
			Poco::FileInputStream* fileStream = dynamic_cast<Poco::FileInputStream*>(this->stream);
			if (!fileStream)
			{
				Logger* logger = Logger::Get("Filesystem.FileStream");
				logger->Error("Error in read. FileInputStream is null");
				throw ValueException::FromString("FileStream must be opened for reading before calling read");
			}

			std::vector<char> buffer;
			char data[4096];

			while (!fileStream->eof())
			{
				fileStream->read((char*)&data, 4095);
				int length = fileStream->gcount();
				if (length > 0)
				{
					buffer.insert(buffer.end(), data, data+length);
				}
				else break;
			}

			result->SetObject(new Bytes(&(buffer[0]), buffer.size()));
		}
		catch (Poco::Exception& exc)
		{
			Logger* logger = Logger::Get("Filesystem.FileStream");
			logger->Error("Error in read. Exception: %s",exc.displayText().c_str());
			throw ValueException::FromString(exc.displayText());
		}
	}

	void FileStream::ReadLine(const ValueList& args, KValueRef result)
	{
		if (!this->stream)
		{
			Logger* logger = Logger::Get("Filesystem.FileStream");
			logger->Error("Error in readLine. FileStream must be opened before calling read");
			throw ValueException::FromString("FileStream must be opened before calling readLine");
		}

		try
		{
			Poco::FileInputStream* fis = dynamic_cast<Poco::FileInputStream*>(this->stream);
			if (!fis)
			{
				Logger* logger = Logger::Get("Filesystem.FileStream");
				logger->Error("Error in readLine. FileInputStream is null");
				throw ValueException::FromString("FileStream must be opened for reading before calling readLine");
			}

			if (fis->eof())
			{
				// close the file
				result->SetNull();
			}
			else
			{
				std::string line;
				std::getline(*fis, line);
#ifdef OS_WIN32
				// In some cases std::getline leaves a CR on the end of the line in win32 -- why God, why?
				if (!line.empty())
				{
					char lastChar = line.at(line.size()-1);
					if (lastChar == '\r') {
						line = line.substr(0, line.size()-1);
					}
				}
#endif
				if (line.empty() || line.size()==0)
				{
					if (fis->eof())
					{
						// if this is EOF, return null
						result->SetNull();
					}
					else
					{
						// this is an empty line, just empty Bytes object.
						result->SetObject(new Bytes());
					}
				}
				else
				{
					result->SetObject(new Bytes((std::string)line));
				}
			}
		}
		catch (Poco::Exception& exc)
		{
			Logger* logger = Logger::Get("Filesystem.FileStream");
			logger->Error("Error in readLine. Exception: %s",exc.displayText().c_str());
			throw ValueException::FromString(exc.displayText());
		}
	}

	void FileStream::WriteLine(const ValueList& args, KValueRef result)
	{
		args.VerifyException("writeLine", "s|o|n");

		if(! this->stream)
		{
			throw ValueException::FromString("FileStream must be opened before calling readLine");
		}

		char *text = NULL;
		int size = 0;
		if (args.at(0)->IsObject())
		{
			KObjectRef b = args.at(0)->ToObject();
			AutoPtr<Bytes> bytes = b.cast<Bytes>();
			if (!bytes.isNull())
			{
				text = (char*)bytes->Get();
				size = (int)bytes->Length();
			}
		}
		else if (args.at(0)->IsString())
		{
			text = (char*)args.at(0)->ToString();
		}
		else if (args.at(0)->IsInt())
		{
			std::stringstream ostr;
			ostr << args.at(0)->ToInt();
			text = (char*)ostr.str().c_str();
			size = ostr.str().length();
		}
		else if (args.at(0)->IsDouble())
		{
			std::stringstream ostr;
			ostr << args.at(0)->ToDouble();
			text = (char*)ostr.str().c_str();
			size = ostr.str().length();
		}
		else
		{
			throw ValueException::FromString("Could not write with type passed");
		}

		if (size==0)
		{
			size = strlen(text);
		}

		if (text == NULL || size <= 0)
		{
			result->SetBool(false);
			return;
		}

		std::string astr = text;
#ifdef OS_WIN32
		astr += "\r\n";
#else
		astr += "\n";
#endif
		Write((char*)astr.c_str(),astr.length());
		result->SetBool(true);
	}

	void FileStream::Ready(const ValueList& args, KValueRef result)
	{
		Poco::FileIOS* fis = this->stream;
		if(!fis)
		{
			result->SetBool(false);
		}
		else
		{
			result->SetBool(fis->eof()==false);
		}
	}

	void FileStream::IsOpen(const ValueList& args, KValueRef result)
	{
		Poco::FileIOS* fis = this->stream;
		result->SetBool(fis!=NULL);
	}

}
<|endoftext|>


<commit_before>#include "zmq.h"
#include <iostream>
#include "AliHLTDataTypes.h"
#include "AliHLTComponent.h"
#include "AliHLTMessage.h"
#include "TClass.h"
#include "TCanvas.h"
#include "TMap.h"
#include "TPRegexp.h"
#include "TObjString.h"
#include "TDirectory.h"
#include "TList.h"
#include "AliZMQhelpers.h"
#include "TMessage.h"
#include "TSystem.h"
#include "TApplication.h"
#include "TH1.h"
#include "TH1F.h"
#include <time.h>
#include <string>
#include <map>
#include "TFile.h"
#include "TSystem.h"
#include "signal.h"
class MySignalHandler;

//this is meant to become a class, hence the structure with global vars etc.
//Also the code is rather flat - it is a bit of a playground to test ideas.
//TODO structure this at some point, e.g. introduce a SIMPLE unified way of handling
//zmq payloads, maybe a AliZMQmessage class which would by default be multipart and provide
//easy access to payloads based on topic or so (a la HLT GetFirstInputObject() etc...)

//methods
int ProcessOptionString(TString arguments);
int UpdatePad(TObject*);
int DumpToFile(TObject* object);
void* run(void* arg);

//configuration vars
Bool_t fVerbose = kFALSE;
TString fZMQconfigIN  = "PULL>tcp://localhost:60211";
int fZMQsocketModeIN=-1;
TString fZMQsubscriptionIN = "";
TString fFilter = "";

TString fFileName="";
TFile* fFile=NULL;

int fPollInterval = 0;
int fPollTimeout = 1000; //1s

//internal state
void* fZMQcontext = NULL;             //ze zmq context
void* fZMQin  = NULL;                 //the in socket - entry point for the data to be merged.

TApplication* gApp;
TCanvas* fCanvas;
TObjArray fDrawables;

TString fStatus = "";
Int_t fRunNumber = 0;
TPRegexp* fSelectionRegexp = NULL;
TPRegexp* fUnSelectionRegexp = NULL;
TString fDrawOptions;
Bool_t fScaleLogX = kFALSE;
Bool_t fScaleLogY = kFALSE;
Bool_t fScaleLogZ = kFALSE;
Bool_t fResetOnRequest = kFALSE;

ULong64_t iterations=0;

const char* fUSAGE =
    "ZMQhstViewer: Draw() all ROOT drawables in a message\n"
    "options: \n"
    " -in : data in\n"
    " -sleep : how long to sleep in between requests for data in s (if applicable)\n"
    " -timeout : how long to wait for the server to reply (s)\n"
    " -Verbose : be verbose\n"
    " -select : only show selected histograms (by regexp)\n"
    " -unselect : as select, only inverted\n"
    " -drawoptions : what draw option to use\n"
    " -file : dump input to file and exit\n"
    " -log[xyz] : use log scale on [xyz] dimension\n"
    ;
//_______________________________________________________________________________________
class MySignalHandler : public TSignalHandler
{
  public:
	MySignalHandler(ESignals sig) : TSignalHandler(sig) {}
	Bool_t Notify()
	{
    Printf("signal received, exiting");
		fgTerminationSignaled = true;
		return TSignalHandler::Notify();
	}
	static bool TerminationSignaled() { return fgTerminationSignaled; }
	static bool fgTerminationSignaled;
};
bool MySignalHandler::fgTerminationSignaled = false;

void sig_handler(int signo)
{
  if (signo == SIGINT)
    printf("received SIGINT\n");
  MySignalHandler::fgTerminationSignaled=true;
}

//_______________________________________________________________________________________
void* run(void* arg)
{
  //main loop
  while(!MySignalHandler::TerminationSignaled())
  {
    errno=0;
    //send a request if we are using REQ
    if (fZMQsocketModeIN==ZMQ_REQ)
    {
      TString request;
      TString requestTopic;

      if (fSelectionRegexp || fUnSelectionRegexp)
      {
        requestTopic = "CONFIG";
        if (fSelectionRegexp) request += " select="+fSelectionRegexp->GetPattern();
        if (fUnSelectionRegexp) request += " unselect="+fUnSelectionRegexp->GetPattern();
        if (fResetOnRequest) request += " ResetOnRequest";
        zmq_send(fZMQin, requestTopic.Data(), requestTopic.Length(), ZMQ_SNDMORE);
        zmq_send(fZMQin, request.Data(), request.Length(), ZMQ_SNDMORE);
      }

      if (fVerbose) Printf("sending request %s %s",requestTopic.Data(), request.Data());
      zmq_send(fZMQin, "", 0, ZMQ_SNDMORE);
      zmq_send(fZMQin, "", 0, 0);
    }

    //wait for the data
    zmq_pollitem_t sockets[] = {
                                 { fZMQin, 0, ZMQ_POLLIN, 0 },
                               };
    int rc = zmq_poll(sockets, 1, (fZMQsocketModeIN==ZMQ_REQ)?fPollTimeout:-1);

    if (rc==-1 && errno==ETERM)
    {
      Printf("jumping out of main loop");
      break;
    }

    if (!(sockets[0].revents & ZMQ_POLLIN))
    {
      //server died
      Printf("connection timed out, server %s died?", fZMQconfigIN.Data());
      fZMQsocketModeIN = alizmq_socket_init(fZMQin, fZMQcontext, fZMQconfigIN.Data());
      if (fZMQsocketModeIN < 0) return NULL;
      continue;
    }
    else
    {
      //get all data (topic+body), possibly many of them
      aliZMQmsg message;
      alizmq_msg_recv(&message, fZMQin, 0);
      for (aliZMQmsg::iterator i=message.begin(); i!=message.end(); ++i)
      {
        zmq_msg_t* topicMsg = i->first;
        zmq_msg_t* dataMsg = i->second;
        if (strncmp((char*)zmq_msg_data(topicMsg),"INFO",4)==0)
        {
            //check if we have a runnumber in the string
            string info;
            info.assign((char*)zmq_msg_data(dataMsg),zmq_msg_size(dataMsg));
            fCanvas->SetTitle(info.c_str());
            size_t runTagPos = info.find("run");
            if (runTagPos != std::string::npos)
            {
              size_t runStartPos = info.find("=",runTagPos);
              size_t runEndPos = info.find(" ");
              string runString = info.substr(runStartPos+1,runEndPos-runStartPos-1);
              if (fVerbose) printf("received run=%s\n",runString.c_str());

              int runnumber = atoi(runString.c_str());

              if (runnumber!=fRunNumber)
              {
                  if (fVerbose) printf("Run changed, resetting!\n");
                  fDrawables.Delete();
                  fCanvas->Clear();
              }
              fRunNumber = runnumber;
            }
        }

        TObject* object;
        alizmq_msg_iter_data(i, object);
        if (object) UpdatePad(object);

        if (!fFileName.IsNull())
        {
          DumpToFile(object);
        }
      }
      alizmq_msg_close(&message);

    }//socket 0
    gSystem->ProcessEvents();
    usleep(fPollInterval);
  }//main loop
  return NULL;
}

//_______________________________________________________________________________________
int main(int argc, char** argv)
{
  //process args
  int noptions = ProcessOptionString(AliOptionParser::GetFullArgString(argc,argv));
  if (noptions<=0)
  {
    printf("%s",fUSAGE);
    return 1;
  }

  TH1::AddDirectory(kFALSE);
  TDirectory::AddDirectory(kFALSE);
  gApp = new TApplication("viewer", &argc, argv);
  gApp->SetReturnFromRun(true);
  //gApp->Run();

  fCanvas = new TCanvas();
  gSystem->ProcessEvents();

  int mainReturnCode=0;

  //init stuff
  //globally enable schema evolution for serializing ROOT objects
  TMessage::EnableSchemaEvolutionForAll(kTRUE);
  //ZMQ init
  fZMQcontext = zmq_ctx_new();
  fZMQsocketModeIN = alizmq_socket_init(fZMQin, fZMQcontext, fZMQconfigIN.Data(), -1, 2);
  if (fZMQsocketModeIN < 0) return 1;

  gSystem->ResetSignal(kSigPipe);
  gSystem->ResetSignal(kSigQuit);
  gSystem->ResetSignal(kSigInterrupt);
  gSystem->ResetSignal(kSigTermination);
  //gSystem->AddSignalHandler(new MySignalHandler(kSigPipe));
  //gSystem->AddSignalHandler(new MySignalHandler(kSigQuit));
  //gSystem->AddSignalHandler(new MySignalHandler(kSigInterrupt));
  //gSystem->AddSignalHandler(new MySignalHandler(kSigTermination));

  if (signal(SIGINT, sig_handler) == SIG_ERR)
  printf("\ncan't catch SIGINT\n");

  run(NULL);

  Printf("exiting...");
  if (fFile) fFile->Close();
  delete fFile; fFile=0;

  //destroy ZMQ sockets

  int linger=0;
  zmq_setsockopt(fZMQin, ZMQ_LINGER, &linger, sizeof(linger));
  zmq_close(fZMQin);
  zmq_ctx_term(fZMQcontext);
  return mainReturnCode;
}

//______________________________________________________________________________
int DumpToFile(TObject* object)
{
  Option_t* fileMode="RECREATE";
  if (!fFile) fFile = new TFile(fFileName,fileMode);
  if (fVerbose) Printf("writing object %s to %s",object->GetName(), fFileName.Data());
  int rc = object->Write(object->GetName(),TObject::kOverwrite);
  MySignalHandler::fgTerminationSignaled=true;
  return rc;
}

//______________________________________________________________________________
int UpdatePad(TObject* object)
{
  if (!object) return -1;
  const char* name = object->GetName();

  TObject* drawable = fDrawables.FindObject(name);
  int padIndex = fDrawables.IndexOf(drawable);

  if (fVerbose) Printf("in: %s", name);
  Bool_t selected = kTRUE;
  Bool_t unselected = kFALSE;
  if (fSelectionRegexp) selected = fSelectionRegexp->Match(name);
  if (fUnSelectionRegexp) unselected = fUnSelectionRegexp->Match(name);
  if (!selected || unselected) return 0;

  if (drawable)
  {
    //only redraw the one thing
    if (fVerbose) Printf("  redrawing %s in pad %i", name, padIndex);
    fCanvas->cd(padIndex+1);
    gPad->GetListOfPrimitives()->Remove(drawable);
    gPad->Clear();
    fDrawables.RemoveAt(padIndex);
    delete drawable;
    fDrawables.AddAt(object, padIndex);
    object->Draw(fDrawOptions);
    gPad->Modified(kTRUE);
  }
  else
  {
    if (fVerbose) Printf("  new object %s", name);
    //add the new object to the collection, restructure the canvas
    //and redraw everything
    fDrawables.AddLast(object);

    //after we clear the canvas, the pads are gone, clear the pad cache as well
    fCanvas->Clear();
    fCanvas->DivideSquare(fDrawables.GetLast()+1);

    //redraw all objects at their old places and the new one as last
    for (int i=0; i<fDrawables.GetLast()+1; i++)
    {
      TObject* obj = fDrawables[i];
      fCanvas->cd(i+1);
      if (fScaleLogX) gPad->SetLogx();
      if (fScaleLogY) gPad->SetLogy();
      if (fScaleLogZ) gPad->SetLogz();
      if (fVerbose) Printf("  drawing %s in pad %i", obj->GetName(), i);
      if (obj) obj->Draw();
    }
  }
  gSystem->ProcessEvents();
  fCanvas->Update();
  return 0;
}

//______________________________________________________________________________
int ProcessOptionString(TString arguments)
{
  //process passed options
  stringMap* options = AliOptionParser::TokenizeOptionString(arguments);
  int nOptions = 0;
  for (stringMap::iterator i=options->begin(); i!=options->end(); ++i)
  {
    //Printf("  %s : %s", i->first.data(), i->second.data());
    const TString& option = i->first;
    const TString& value = i->second;
    if (option.EqualTo("PollInterval") || option.EqualTo("sleep"))
    {
      fPollInterval = round(value.Atof()*1e6);
    }
    else if (option.EqualTo("PollTimeout") || option.EqualTo("timeout"))
    {
      fPollTimeout = round(value.Atof()*1e3);
    }
    else if (option.EqualTo("ZMQconfigIN") || option.EqualTo("in") )
    {
      fZMQconfigIN = value;
    }
    else if (option.EqualTo("Verbose"))
    {
      fVerbose=kTRUE;
    }
    else if (option.EqualTo("select"))
    {
      delete fSelectionRegexp;
      fSelectionRegexp=new TPRegexp(value);
    }
    else if (option.EqualTo("unselect"))
    {
      delete fUnSelectionRegexp;
      fUnSelectionRegexp=new TPRegexp(value);
    }
    else if (option.EqualTo("ResetOnRequest"))
    {
      fResetOnRequest = kTRUE;
    }
    else if (option.EqualTo("drawoptions"))
    {
      fDrawOptions = value;
    }
    else if (option.EqualTo("logx"))
    {
      fScaleLogX=kTRUE;
    }
    else if (option.EqualTo("logy"))
    {
      fScaleLogY=kTRUE;
    }
    else if (option.EqualTo("logz"))
    {
      fScaleLogZ=kTRUE;
    }
    else if (option.EqualTo("file"))
    {
      fFileName = value;
    }
    else
    {
      nOptions=-1;
      break;
    }
    nOptions++;
  }
  delete options; //tidy up

  return nOptions;
}

<commit_msg>sort plots by title<commit_after>#include "zmq.h"
#include <iostream>
#include "AliHLTDataTypes.h"
#include "AliHLTComponent.h"
#include "AliHLTMessage.h"
#include "TClass.h"
#include "TCanvas.h"
#include "TMap.h"
#include "TPRegexp.h"
#include "TObjString.h"
#include "TDirectory.h"
#include "TList.h"
#include "AliZMQhelpers.h"
#include "TMessage.h"
#include "TSystem.h"
#include "TApplication.h"
#include "TH1.h"
#include "TH1F.h"
#include <time.h>
#include <string>
#include <map>
#include "TFile.h"
#include "TSystem.h"
#include "signal.h"
class MySignalHandler;

//this is meant to become a class, hence the structure with global vars etc.
//Also the code is rather flat - it is a bit of a playground to test ideas.
//TODO structure this at some point, e.g. introduce a SIMPLE unified way of handling
//zmq payloads, maybe a AliZMQmessage class which would by default be multipart and provide
//easy access to payloads based on topic or so (a la HLT GetFirstInputObject() etc...)

//methods
int ProcessOptionString(TString arguments);
int UpdatePad(TObject*);
int DumpToFile(TObject* object);
void* run(void* arg);

//configuration vars
Bool_t fVerbose = kFALSE;
TString fZMQconfigIN  = "PULL>tcp://localhost:60211";
int fZMQsocketModeIN=-1;
TString fZMQsubscriptionIN = "";
TString fFilter = "";

TString fFileName="";
TFile* fFile=NULL;

int fPollInterval = 0;
int fPollTimeout = 1000; //1s
Bool_t fSort = kTRUE;

//internal state
void* fZMQcontext = NULL;             //ze zmq context
void* fZMQin  = NULL;                 //the in socket - entry point for the data to be merged.

TApplication* gApp;
TCanvas* fCanvas;
TObjArray fDrawables;

TString fStatus = "";
Int_t fRunNumber = 0;
TPRegexp* fSelectionRegexp = NULL;
TPRegexp* fUnSelectionRegexp = NULL;
TString fDrawOptions;
Bool_t fScaleLogX = kFALSE;
Bool_t fScaleLogY = kFALSE;
Bool_t fScaleLogZ = kFALSE;
Bool_t fResetOnRequest = kFALSE;

ULong64_t iterations=0;

const char* fUSAGE =
    "ZMQhstViewer: Draw() all ROOT drawables in a message\n"
    "options: \n"
    " -in : data in\n"
    " -sleep : how long to sleep in between requests for data in s (if applicable)\n"
    " -timeout : how long to wait for the server to reply (s)\n"
    " -Verbose : be verbose\n"
    " -select : only show selected histograms (by regexp)\n"
    " -unselect : as select, only inverted\n"
    " -drawoptions : what draw option to use\n"
    " -file : dump input to file and exit\n"
    " -log[xyz] : use log scale on [xyz] dimension\n"
    ;
//_______________________________________________________________________________________
class MySignalHandler : public TSignalHandler
{
  public:
	MySignalHandler(ESignals sig) : TSignalHandler(sig) {}
	Bool_t Notify()
	{
    Printf("signal received, exiting");
		fgTerminationSignaled = true;
		return TSignalHandler::Notify();
	}
	static bool TerminationSignaled() { return fgTerminationSignaled; }
	static bool fgTerminationSignaled;
};
bool MySignalHandler::fgTerminationSignaled = false;

void sig_handler(int signo)
{
  if (signo == SIGINT)
    printf("received SIGINT\n");
  MySignalHandler::fgTerminationSignaled=true;
}

//_______________________________________________________________________________________
void* run(void* arg)
{
  //main loop
  while(!MySignalHandler::TerminationSignaled())
  {
    errno=0;
    //send a request if we are using REQ
    if (fZMQsocketModeIN==ZMQ_REQ)
    {
      TString request;
      TString requestTopic;

      if (fSelectionRegexp || fUnSelectionRegexp)
      {
        requestTopic = "CONFIG";
        if (fSelectionRegexp) request += " select="+fSelectionRegexp->GetPattern();
        if (fUnSelectionRegexp) request += " unselect="+fUnSelectionRegexp->GetPattern();
        if (fResetOnRequest) request += " ResetOnRequest";
        zmq_send(fZMQin, requestTopic.Data(), requestTopic.Length(), ZMQ_SNDMORE);
        zmq_send(fZMQin, request.Data(), request.Length(), ZMQ_SNDMORE);
      }

      if (fVerbose) Printf("sending request %s %s",requestTopic.Data(), request.Data());
      zmq_send(fZMQin, "", 0, ZMQ_SNDMORE);
      zmq_send(fZMQin, "", 0, 0);
    }

    //wait for the data
    zmq_pollitem_t sockets[] = {
                                 { fZMQin, 0, ZMQ_POLLIN, 0 },
                               };
    int rc = zmq_poll(sockets, 1, (fZMQsocketModeIN==ZMQ_REQ)?fPollTimeout:-1);

    if (rc==-1 && errno==ETERM)
    {
      Printf("jumping out of main loop");
      break;
    }

    if (!(sockets[0].revents & ZMQ_POLLIN))
    {
      //server died
      Printf("connection timed out, server %s died?", fZMQconfigIN.Data());
      fZMQsocketModeIN = alizmq_socket_init(fZMQin, fZMQcontext, fZMQconfigIN.Data());
      if (fZMQsocketModeIN < 0) return NULL;
      continue;
    }
    else
    {
      //get all data (topic+body), possibly many of them
      aliZMQmsg message;
      alizmq_msg_recv(&message, fZMQin, 0);
      for (aliZMQmsg::iterator i=message.begin(); i!=message.end(); ++i)
      {
        zmq_msg_t* topicMsg = i->first;
        zmq_msg_t* dataMsg = i->second;
        if (strncmp((char*)zmq_msg_data(topicMsg),"INFO",4)==0)
        {
            //check if we have a runnumber in the string
            string info;
            info.assign((char*)zmq_msg_data(dataMsg),zmq_msg_size(dataMsg));
            fCanvas->SetTitle(info.c_str());
            size_t runTagPos = info.find("run");
            if (runTagPos != std::string::npos)
            {
              size_t runStartPos = info.find("=",runTagPos);
              size_t runEndPos = info.find(" ");
              string runString = info.substr(runStartPos+1,runEndPos-runStartPos-1);
              if (fVerbose) printf("received run=%s\n",runString.c_str());

              int runnumber = atoi(runString.c_str());

              if (runnumber!=fRunNumber)
              {
                  if (fVerbose) printf("Run changed, resetting!\n");
                  fDrawables.Delete();
                  fCanvas->Clear();
              }
              fRunNumber = runnumber;
            }
        }

        TObject* object;
        alizmq_msg_iter_data(i, object);
        if (object) UpdatePad(object);

        if (!fFileName.IsNull())
        {
          DumpToFile(object);
        }
      }
      alizmq_msg_close(&message);

    }//socket 0
    gSystem->ProcessEvents();
    usleep(fPollInterval);
  }//main loop
  return NULL;
}

//_______________________________________________________________________________________
int main(int argc, char** argv)
{
  //process args
  int noptions = ProcessOptionString(AliOptionParser::GetFullArgString(argc,argv));
  if (noptions<=0)
  {
    printf("%s",fUSAGE);
    return 1;
  }

  TH1::AddDirectory(kFALSE);
  TDirectory::AddDirectory(kFALSE);
  gApp = new TApplication("viewer", &argc, argv);
  gApp->SetReturnFromRun(true);
  //gApp->Run();

  fCanvas = new TCanvas();
  gSystem->ProcessEvents();

  int mainReturnCode=0;

  //init stuff
  //globally enable schema evolution for serializing ROOT objects
  TMessage::EnableSchemaEvolutionForAll(kTRUE);
  //ZMQ init
  fZMQcontext = zmq_ctx_new();
  fZMQsocketModeIN = alizmq_socket_init(fZMQin, fZMQcontext, fZMQconfigIN.Data(), -1, 2);
  if (fZMQsocketModeIN < 0) return 1;

  gSystem->ResetSignal(kSigPipe);
  gSystem->ResetSignal(kSigQuit);
  gSystem->ResetSignal(kSigInterrupt);
  gSystem->ResetSignal(kSigTermination);
  //gSystem->AddSignalHandler(new MySignalHandler(kSigPipe));
  //gSystem->AddSignalHandler(new MySignalHandler(kSigQuit));
  //gSystem->AddSignalHandler(new MySignalHandler(kSigInterrupt));
  //gSystem->AddSignalHandler(new MySignalHandler(kSigTermination));

  if (signal(SIGINT, sig_handler) == SIG_ERR)
  printf("\ncan't catch SIGINT\n");

  run(NULL);

  Printf("exiting...");
  if (fFile) fFile->Close();
  delete fFile; fFile=0;

  //destroy ZMQ sockets

  int linger=0;
  zmq_setsockopt(fZMQin, ZMQ_LINGER, &linger, sizeof(linger));
  zmq_close(fZMQin);
  zmq_ctx_term(fZMQcontext);
  return mainReturnCode;
}

//______________________________________________________________________________
int DumpToFile(TObject* object)
{
  Option_t* fileMode="RECREATE";
  if (!fFile) fFile = new TFile(fFileName,fileMode);
  if (fVerbose) Printf("writing object %s to %s",object->GetName(), fFileName.Data());
  int rc = object->Write(object->GetName(),TObject::kOverwrite);
  MySignalHandler::fgTerminationSignaled=true;
  return rc;
}

//______________________________________________________________________________
int UpdatePad(TObject* object)
{
  if (!object) return -1;
  const char* name = object->GetName();

  TObject* drawable = fDrawables.FindObject(name);
  int padIndex = fDrawables.IndexOf(drawable);

  if (fVerbose) Printf("in: %s", name);
  Bool_t selected = kTRUE;
  Bool_t unselected = kFALSE;
  if (fSelectionRegexp) selected = fSelectionRegexp->Match(name);
  if (fUnSelectionRegexp) unselected = fUnSelectionRegexp->Match(name);
  if (!selected || unselected) return 0;

  if (drawable)
  {
    //only redraw the one thing
    if (fVerbose) Printf("  redrawing %s in pad %i", name, padIndex);
    fCanvas->cd(padIndex+1);
    gPad->GetListOfPrimitives()->Remove(drawable);
    gPad->Clear();
    fDrawables.RemoveAt(padIndex);
    delete drawable;
    fDrawables.AddAt(object, padIndex);
    object->Draw(fDrawOptions);
    gPad->Modified(kTRUE);
  }
  else
  {
    if (fVerbose) Printf("  new object %s", name);
    //add the new object to the collection, restructure the canvas
    //and redraw everything
    fDrawables.AddLast(object);

    if (fSort)
    {
      TObjArray sortedTitles(fDrawables.GetEntries());
      for (int i=0; i<fDrawables.GetEntries(); i++)
      { sortedTitles.AddAt(new TNamed(fDrawables[i]->GetTitle(),fDrawables[i]->GetName()),i); }
      sortedTitles.Sort();
      TObjArray sortedDrawables(fDrawables.GetEntries());
      for (int i=0; i<fDrawables.GetEntries(); i++)
      {
        const char* name = sortedTitles[i]->GetTitle();
        TObject* tmp = fDrawables.FindObject(name);
        int index = fDrawables.IndexOf(tmp);
        sortedDrawables.AddAt(fDrawables[index],i);
      }
      for (int i=0; i<sortedDrawables.GetEntries(); i++)
      { fDrawables.AddAt(sortedDrawables[i],i); }
      sortedTitles.Delete();
    }

    //after we clear the canvas, the pads are gone, clear the pad cache as well
    fCanvas->Clear();
    fCanvas->DivideSquare(fDrawables.GetLast()+1);

    //redraw all objects at their old places and the new one as last
    for (int i=0; i<fDrawables.GetLast()+1; i++)
    {
      TObject* obj = fDrawables[i];
      fCanvas->cd(i+1);
      if (fScaleLogX) gPad->SetLogx();
      if (fScaleLogY) gPad->SetLogy();
      if (fScaleLogZ) gPad->SetLogz();
      if (fVerbose) Printf("  drawing %s in pad %i", obj->GetName(), i);
      if (obj) obj->Draw();
    }
  }
  gSystem->ProcessEvents();
  fCanvas->Update();
  return 0;
}

//______________________________________________________________________________
int ProcessOptionString(TString arguments)
{
  //process passed options
  stringMap* options = AliOptionParser::TokenizeOptionString(arguments);
  int nOptions = 0;
  for (stringMap::iterator i=options->begin(); i!=options->end(); ++i)
  {
    //Printf("  %s : %s", i->first.data(), i->second.data());
    const TString& option = i->first;
    const TString& value = i->second;
    if (option.EqualTo("PollInterval") || option.EqualTo("sleep"))
    {
      fPollInterval = round(value.Atof()*1e6);
    }
    else if (option.EqualTo("PollTimeout") || option.EqualTo("timeout"))
    {
      fPollTimeout = round(value.Atof()*1e3);
    }
    else if (option.EqualTo("ZMQconfigIN") || option.EqualTo("in") )
    {
      fZMQconfigIN = value;
    }
    else if (option.EqualTo("Verbose"))
    {
      fVerbose=kTRUE;
    }
    else if (option.EqualTo("select"))
    {
      delete fSelectionRegexp;
      fSelectionRegexp=new TPRegexp(value);
    }
    else if (option.EqualTo("unselect"))
    {
      delete fUnSelectionRegexp;
      fUnSelectionRegexp=new TPRegexp(value);
    }
    else if (option.EqualTo("ResetOnRequest"))
    {
      fResetOnRequest = kTRUE;
    }
    else if (option.EqualTo("drawoptions"))
    {
      fDrawOptions = value;
    }
    else if (option.EqualTo("logx"))
    {
      fScaleLogX=kTRUE;
    }
    else if (option.EqualTo("logy"))
    {
      fScaleLogY=kTRUE;
    }
    else if (option.EqualTo("logz"))
    {
      fScaleLogZ=kTRUE;
    }
    else if (option.EqualTo("file"))
    {
      fFileName = value;
    }
    else if (option.EqualTo("sort"))
    {
      fSort=value.Contains(0)?kFALSE:kTRUE;
    }
    else
    {
      nOptions=-1;
      break;
    }
    nOptions++;
  }
  delete options; //tidy up

  return nOptions;
}

<|endoftext|>


<commit_before>
#include <QtCore>
#include "module_uid.h"
#include "form_uid.h"
#include <qextserialport.h>
#include <qextserialenumerator.h>

Module_UID::Module_UID(QString moduleId)
    :RobotModule(moduleId)
{

    portSettings = new PortSettings();
    portSettings->BaudRate = BAUD115200;
    portSettings->DataBits = DATA_8;
    portSettings->Parity = PAR_NONE;
    portSettings->StopBits = STOP_1;
    portSettings->FlowControl = FLOW_OFF;
    portSettings->Timeout_Millisec = 500;

    setDefaultValue("uidId", "UIDC0001");

    uid = NULL;
    reset();
}

Module_UID::~Module_UID()
{
    if (uid != NULL) {
        uid->close();
        delete uid;
        uid = NULL;
    }
}

void Module_UID::reset()
{
    RobotModule::reset();

    if (!getSettings().value("enabled").toBool())
        return;

    if (uid != NULL) {
        uid->close();
        delete uid;
        uid = NULL;

    }
    uid = findUIDPort();
    data["revision"] = this->UID_Revision();
    data["identity"] = this->UID_Identify();
}

QList<RobotModule*> Module_UID::getDependencies()
{
    return QList<RobotModule*>();
}

QWidget* Module_UID::createView(QWidget* parent)
{
    return new FormUID(this, parent);
}

void Module_UID::terminate()
{
    RobotModule::terminate();
}

QextSerialPort* Module_UID::findUIDPort()
{
    QString Id = settings.value("uidId").toString();

    QList<QextPortInfo> ports = QextSerialEnumerator::getPorts();

    logger->info("Trying out all available serial ports");

    QextSerialPort *p = NULL;

    foreach (QextPortInfo port, ports) {
            logger->debug("port name: "+port.portName);
            logger->debug("friendly name: "+ port.friendName);
            logger->debug("physical name: "+ port.physName);
            logger->debug("enumerator name: "+ port.enumName);
            logger->debug("===================================");

            p = tryOpenPort(Id, &port);

            if (p != NULL)
                break;
    }

    if (!p) {
        setHealthToSick("Didn't find any UID.");
    } else {
        setHealthToOk();
    }

    return p;
}

QextSerialPort* Module_UID::tryOpenPort(QString Id, QextPortInfo *port)
{
    //QextSerialPort* sport = new QextSerialPort( port->physName, *portSettings, QextSerialPort::Polling);
    QextSerialPort* sport = new QextSerialPort( port->portName, *portSettings, QextSerialPort::Polling);

    const char sequence[] = {Module_UID::UID_IDENTIFY};
    char id[9];

    //if ( !(port->open(QextSerialPort::ReadWrite) ) ) {
    if ( !(sport->open(QIODevice::ReadWrite | QIODevice::Unbuffered) ) ) {
        logger->debug("Could not open: "+sport->errorString());
        sport->close();
        delete sport;
        return NULL;
    }

    logger->debug("connected successfully");

    sport->flush();
    if (sport->bytesAvailable()>0) {
        logger->error("found some bytes in the uid serial buffer. discard them.");
        sport->flush();
        sport->readAll(); // don't care for the data
    }

    if ( (sport->write(sequence, 1)) == -1) {
        logger->debug("Writing Opcode failed");
        sport->close();
        delete sport;
        return NULL;
    }

    logger->debug("Could write to port");
    int bytesRead = sport->read(id, sizeof(id));
    if ( bytesRead < sizeof(id)) {
        logger->debug("No Id received, read only "+QString::number(bytesRead)+ " bytes.");
        sport->close();
        delete sport;
        return NULL;
    }

    if (QString::fromAscii(id,sizeof(id)-1) != Id) {
        logger->debug("Received id: " + QString::fromUtf8(id,8)+"; expected: "+Id);
        logger->debug("Wrong Id\r\nReceived: " + QString::fromUtf8(id,8));
        sport->close();
        delete sport;
        return NULL;
    }

    logger->debug("Found UID with id " + QString::fromAscii(id,8) + " on " + port->portName);
    sport->flush();
    return sport;

}

bool Module_UID::I2C_WriteRegister(unsigned char address, unsigned char reg, unsigned char* data, short byteCount) {
    if (!uid) {
        logger->error("Can't do. UID not open.");
        return false;
    }

    //unsigned char sequence[4+byteCount];// = {Module_UID::I2C_WRITEREGISTER, address, reg, (unsigned char)byteCount};
    unsigned char sequence[] = {Module_UID::I2C_WRITEREGISTER, address, reg, (unsigned char)byteCount};
    /*
    int pos = 0;
    sequence[pos++] = Module_UID::I2C_WRITEREGISTER;
    sequence[pos++] = address;
    sequence[pos++] = reg;
    sequence[pos++] = (unsigned char)byteCount;

    for (int i=0; i<byteCount; i++)
        sequence[pos++]=data[i];
        */
    if (!SendCommand(sequence, sizeof(sequence), 0)) return false;
    if (!SendCommand(data, byteCount, 0)) return false;
    return true;
}

bool Module_UID::I2C_ReadRegisters(unsigned char address, unsigned char reg, short byteCount, unsigned char* result) {
    if (!uid) {
        logger->error("Can't do. UID not open.");
        return false;
    }

    unsigned char sequence[] = {Module_UID::I2C_READREGISTER, address, reg, byteCount};
    if (!SendCommand(sequence, sizeof(sequence), 0)) return false;
    if ( (uid->read((char*)result, byteCount)) != byteCount) return false;
    return true;
}

bool Module_UID::SendCommand(unsigned char* sequence, unsigned char length, int msec) {
    if (!uid) {
        logger->error("Can't do. UID not open.");
        return false;
    }

    if ( (uid->write( (const char*)sequence, length )) == -1 ) {
        // this means almost certainly that the serial connection to the UID has died.
        setHealthToSick(uid->portName()+": "+uid->errorString());
        return false;
    }
    uid->flush();
    return true;
}

bool Module_UID::I2C_Write(unsigned char address, unsigned char* data, short byteCount) {
    if (!uid) {
        logger->error("Can't do. UID not open.");
        return false;
    }

    unsigned char sequence[] = {Module_UID::I2C_WRITE, address, byteCount};
    if (!SendCommand(sequence, sizeof(sequence), 0)) return false;
    if (!SendCommand(data, byteCount, 0)) return false;
    return true;
}

bool Module_UID::I2C_Read(unsigned char address, short byteCount, unsigned char* result) {
    if (!uid) {
        logger->error("Can't do. UID not open.");
        return false;
    }

    unsigned char sequence[] = {Module_UID::I2C_READ, address, byteCount};
    if (!SendCommand(sequence, sizeof(sequence) , 0)) return false;
    if ( (uid->read((char*)result, byteCount)) != byteCount) return false;
    return true;
}

QString Module_UID::UID_Identify() {
    if (!uid) {
        logger->error("Can't do. UID not open.");
        return "";
    }

    QString identify;
    unsigned char sequence[] = {Module_UID::UID_IDENTIFY};
    char result[9];
    if ( !(SendCommand(sequence, sizeof(sequence), 0)) ) {
        return "";
    }
    qint64 ret = uid->read(result,sizeof(result));
    if( ret == -1 ) {
        setHealthToSick("serial error: "+uid->errorString());
        return "";
    }
    if (ret < 9) {
        setHealthToSick("Short read.");
        return "";
    }
    return QString::fromAscii(result, ret-1);
}

QString Module_UID::UID_Revision() {
    if (!uid) {
        logger->error("Can't do. UID not open.");
        return "";
    }

    QString identify;
    unsigned char sequence[] = {Module_UID::UID_REVISION};
    char result[8];
    if ( !(SendCommand(sequence, sizeof(sequence), 0)) ) return NULL;
    //if (port->read(result,sizeof(result)) == -1) return NULL;
    qint64 ret = uid->read(result,sizeof(result));
    if (ret==-1) return NULL;
    //return QString(result);
    return QString::fromAscii(result, ret-1);
}

bool Module_UID::UID_Available()
{
    return uid != NULL;
}

void Module_UID::doHealthCheck()
{
    if (!getSettings().value("enabled").toBool())
        return;

    QString Id = settings.value("uidId").toString();

    if ( uid == NULL ) {
        setHealthToSick("No uid open.");
        return;
    }

    QString received = UID_Identify();
    if ( received.length()==0) {
        return;
    }
    if ( received.length()>0 && received != Id) {
        setHealthToSick("Wrong Id, received: " + received);
        return;
    }

    setHealthToOk();
}

QVector<unsigned char> Module_UID::I2C_Scan() {
    unsigned char sequence[] = {Module_UID::I2C_SCAN};
    QVector<unsigned char> slaves(0);
    if (!SendCommand(sequence, sizeof(sequence), 0)) return slaves;
    unsigned char result[127];
    qint64 read = uid->read((char*)result, 127);
    if (read != -1) {
        for (int i=0; i<read; i++) slaves.append(result[i]);
    }
    return slaves;
}

bool Module_UID::SPI_Speed(unsigned char speed) {
    unsigned char sequence[] = {Module_UID::SPI_SPEED, speed};
    return SendCommand(sequence, sizeof(sequence), 0);
}

bool Module_UID::SPI_SetPHA(bool phase) {
    unsigned char sequence[] = {Module_UID::SPI_SETPHA, phase};
    return SendCommand(sequence, sizeof(sequence), 0);
}

bool Module_UID::SPI_SetPOL(bool pol){
    unsigned char sequence[] = {Module_UID::SPI_SETPOL, pol};
    return SendCommand(sequence, sizeof(sequence), 0);
}

bool Module_UID::SPI_Read(unsigned char address, short byteCount, unsigned char* result) {
    unsigned char sequence[] = {Module_UID::SPI_READ, address, byteCount};
    if (!SendCommand(sequence, sizeof(sequence) , 0)) return false;
    if ( (uid->read((char*)result, byteCount)) == -1) return false;
    return true;
}

bool Module_UID::SPI_Write(unsigned char address, unsigned char* data, short byteCount) {
    unsigned char sequence[] = {Module_UID::SPI_WRITE, address, byteCount};
    if (!SendCommand(sequence, sizeof(sequence), 0)) return false;
    if (!SendCommand(data, byteCount, 0)) return false;
    return true;
}

bool Module_UID::SPI_WriteRead(unsigned char address, unsigned char* data, short byteCount, unsigned char* result) {
    unsigned char sequence[] = {Module_UID::SPI_WRITE, address, byteCount};
    if (!SendCommand(sequence, sizeof(sequence), 0)) return false;
    if (!SendCommand(data, byteCount, 0)) return false;
    if ( (uid->read((char*)result, byteCount)) == -1) return false;
    return true;
}

bool Module_UID::I2C_DA_ReceiveAck() {
    unsigned char sequence[] = {Module_UID::I2C_DA_RECEIVEACK};
    return SendCommand(sequence, sizeof(sequence), 0);
}

bool Module_UID::I2C_DA_ReceiveByteAck() {
    unsigned char sequence[] = {Module_UID::I2C_DA_RECEIVEBYTEACK};
    return SendCommand(sequence, sizeof(sequence), 0);
}

bool Module_UID::I2C_DA_ReceiveByteNoAck() {
    unsigned char sequence[] = {Module_UID::I2C_DA_RECEIVEBYTENOACK};
    return SendCommand(sequence, sizeof(sequence), 0);
}

bool Module_UID::I2C_DA_RepStart() {
    unsigned char sequence[] = {Module_UID::I2C_DA_REPSTART};
    return SendCommand(sequence, sizeof(sequence), 0);
}

bool Module_UID::I2C_DA_SendAck() {
    unsigned char sequence[] = {Module_UID::I2C_DA_SENDACK};
    return SendCommand(sequence, sizeof(sequence), 0);
}

bool Module_UID::I2C_DA_SendByteAck(unsigned char data) {
    unsigned char sequence[] = {Module_UID::I2C_DA_SENDBYTEACK};
    return SendCommand(sequence, sizeof(sequence), 0);
}

bool Module_UID::I2C_DA_SendByteNoAck(unsigned char data) {
    unsigned char sequence[] = {Module_UID::I2C_DA_RECEIVEBYTENOACK};
    return SendCommand(sequence, sizeof(sequence), 0);
}

bool Module_UID::I2C_DA_Start() {
    unsigned char sequence[] = {Module_UID::I2C_DA_START};
    return SendCommand(sequence, sizeof(sequence), 0);
}

bool Module_UID::I2C_DA_Stop() {
    unsigned char sequence[] = {Module_UID::I2C_DA_STOP};
    return SendCommand(sequence, sizeof(sequence), 0);
}

bool Module_UID::UID_ADC(unsigned char bitmask, unsigned char* result) {
    unsigned char sequence[] = {Module_UID::ADC_ADC, bitmask};
    unsigned char values = countBitsSet(bitmask);

    if ( !(SendCommand(sequence, sizeof(sequence), 0)) ) return false;

    qint64 res = uid->read((char*)result,values);
    if (res==-1 || res<values) return false;

    return true;
}

bool Module_UID::I2C_Speed(Module_UID::I2CSpeed speed) {
    unsigned char sequence[] = {Module_UID::I2C_SCAN, speed};
    return SendCommand(sequence, sizeof(sequence), 0);
}

bool Module_UID::I2C_EnterAckMode() {
    unsigned char sequence[] = {Module_UID::I2C_ENTERACKMODE};
    return SendCommand(sequence, sizeof(sequence), 0);
}

unsigned char Module_UID::countBitsSet( unsigned char bitmask ) {
    unsigned char bits = 0;
    while (bitmask>0) {
        bits += (bitmask&1);
        bitmask = bitmask >> 1;
    }
    return bits;
}
<commit_msg>flush read buffer before sendCommand<commit_after>
#include <QtCore>
#include "module_uid.h"
#include "form_uid.h"
#include <qextserialport.h>
#include <qextserialenumerator.h>

Module_UID::Module_UID(QString moduleId)
    :RobotModule(moduleId)
{

    portSettings = new PortSettings();
    portSettings->BaudRate = BAUD115200;
    portSettings->DataBits = DATA_8;
    portSettings->Parity = PAR_NONE;
    portSettings->StopBits = STOP_1;
    portSettings->FlowControl = FLOW_OFF;
    portSettings->Timeout_Millisec = 5;

    setDefaultValue("uidId", "UIDC0001");

    uid = NULL;
    reset();
}

Module_UID::~Module_UID()
{
    if (uid != NULL) {
        uid->close();
        delete uid;
        uid = NULL;
    }
}

void Module_UID::reset()
{
    RobotModule::reset();

    if (!getSettings().value("enabled").toBool())
        return;

    if (uid != NULL) {
        uid->close();
        delete uid;
        uid = NULL;

    }
    uid = findUIDPort();
    data["revision"] = this->UID_Revision();
    data["identity"] = this->UID_Identify();
}

QList<RobotModule*> Module_UID::getDependencies()
{
    return QList<RobotModule*>();
}

QWidget* Module_UID::createView(QWidget* parent)
{
    return new FormUID(this, parent);
}

void Module_UID::terminate()
{
    RobotModule::terminate();
}

QextSerialPort* Module_UID::findUIDPort()
{
    QString Id = settings.value("uidId").toString();

    QList<QextPortInfo> ports = QextSerialEnumerator::getPorts();

    logger->info("Trying out all available serial ports");

    QextSerialPort *p = NULL;

    foreach (QextPortInfo port, ports) {
            logger->debug("port name: "+port.portName);
            logger->debug("friendly name: "+ port.friendName);
            logger->debug("physical name: "+ port.physName);
            logger->debug("enumerator name: "+ port.enumName);
            logger->debug("===================================");

            p = tryOpenPort(Id, &port);

            if (p != NULL)
                break;
    }

    if (!p) {
        setHealthToSick("Didn't find any UID.");
    } else {
        setHealthToOk();
    }

    return p;
}

QextSerialPort* Module_UID::tryOpenPort(QString Id, QextPortInfo *port)
{
    //QextSerialPort* sport = new QextSerialPort( port->physName, *portSettings, QextSerialPort::Polling);
    QextSerialPort* sport = new QextSerialPort( port->portName, *portSettings, QextSerialPort::Polling);

    const char sequence[] = {Module_UID::UID_IDENTIFY};
    char id[9];

    //if ( !(port->open(QextSerialPort::ReadWrite) ) ) {
    if ( !(sport->open(QIODevice::ReadWrite | QIODevice::Unbuffered) ) ) {
        logger->debug("Could not open: "+sport->errorString());
        sport->close();
        delete sport;
        return NULL;
    }

    logger->debug("connected successfully");

    sport->flush();
    if (sport->bytesAvailable()>0) {
        logger->error("found some bytes in the uid serial buffer. discard them.");
        sport->flush();
        sport->readAll(); // don't care for the data
    }

    if ( (sport->write(sequence, 1)) == -1) {
        logger->debug("Writing Opcode failed");
        sport->close();
        delete sport;
        return NULL;
    }

    logger->debug("Could write to port");
    int bytesRead = sport->read(id, sizeof(id));
    if ( bytesRead < sizeof(id)) {
        logger->debug("No Id received, read only "+QString::number(bytesRead)+ " bytes.");
        sport->close();
        delete sport;
        return NULL;
    }

    if (QString::fromAscii(id,sizeof(id)-1) != Id) {
        logger->debug("Received id: " + QString::fromUtf8(id,8)+"; expected: "+Id);
        logger->debug("Wrong Id\r\nReceived: " + QString::fromUtf8(id,8));
        sport->close();
        delete sport;
        return NULL;
    }

    logger->debug("Found UID with id " + QString::fromAscii(id,8) + " on " + port->portName);
    sport->flush();
    return sport;

}

bool Module_UID::I2C_WriteRegister(unsigned char address, unsigned char reg, unsigned char* data, short byteCount) {
    if (!uid) {
        logger->error("Can't do. UID not open.");
        return false;
    }

    //unsigned char sequence[4+byteCount];// = {Module_UID::I2C_WRITEREGISTER, address, reg, (unsigned char)byteCount};
    unsigned char sequence[] = {Module_UID::I2C_WRITEREGISTER, address, reg, (unsigned char)byteCount};
    /*
    int pos = 0;
    sequence[pos++] = Module_UID::I2C_WRITEREGISTER;
    sequence[pos++] = address;
    sequence[pos++] = reg;
    sequence[pos++] = (unsigned char)byteCount;

    for (int i=0; i<byteCount; i++)
        sequence[pos++]=data[i];
        */
    if (!SendCommand(sequence, sizeof(sequence), 0)) return false;
    if (!SendCommand(data, byteCount, 0)) return false;
    return true;
}

bool Module_UID::I2C_ReadRegisters(unsigned char address, unsigned char reg, short byteCount, unsigned char* result) {
    if (!uid) {
        logger->error("Can't do. UID not open.");
        return false;
    }

    unsigned char sequence[] = {Module_UID::I2C_READREGISTER, address, reg, byteCount};
    if (!SendCommand(sequence, sizeof(sequence), 0)) return false;
    if ( (uid->read((char*)result, byteCount)) != byteCount) return false;
    return true;
}

bool Module_UID::SendCommand(unsigned char* sequence, unsigned char length, int msec) {
    if (!uid) {
        logger->error("Can't do. UID not open.");
        return false;
    }

    uid->flush();
    if (uid->bytesAvailable()>0) {
        logger->error("found some bytes in the uid serial buffer. discard them.");
        uid->flush();
        uid->readAll(); // don't care for the data
    }

    if ( (uid->write( (const char*)sequence, length )) == -1 ) {
        // this means almost certainly that the serial connection to the UID has died.
        setHealthToSick(uid->portName()+": "+uid->errorString());
        return false;
    }
    uid->flush();
    return true;
}

bool Module_UID::I2C_Write(unsigned char address, unsigned char* data, short byteCount) {
    if (!uid) {
        logger->error("Can't do. UID not open.");
        return false;
    }

    unsigned char sequence[] = {Module_UID::I2C_WRITE, address, byteCount};
    if (!SendCommand(sequence, sizeof(sequence), 0)) return false;
    if (!SendCommand(data, byteCount, 0)) return false;
    return true;
}

bool Module_UID::I2C_Read(unsigned char address, short byteCount, unsigned char* result) {
    if (!uid) {
        logger->error("Can't do. UID not open.");
        return false;
    }

    unsigned char sequence[] = {Module_UID::I2C_READ, address, byteCount};
    if (!SendCommand(sequence, sizeof(sequence) , 0)) return false;
    if ( (uid->read((char*)result, byteCount)) != byteCount) return false;
    return true;
}

QString Module_UID::UID_Identify() {
    if (!uid) {
        logger->error("Can't do. UID not open.");
        return "";
    }

    QString identify;
    unsigned char sequence[] = {Module_UID::UID_IDENTIFY};
    char result[9];
    if ( !(SendCommand(sequence, sizeof(sequence), 0)) ) {
        return "";
    }
    qint64 ret = uid->read(result,sizeof(result));
    if( ret == -1 ) {
        setHealthToSick("serial error: "+uid->errorString());
        return "";
    }
    if (ret < 9) {
        setHealthToSick("Short read.");
        return "";
    }
    return QString::fromAscii(result, ret-1);
}

QString Module_UID::UID_Revision() {
    if (!uid) {
        logger->error("Can't do. UID not open.");
        return "";
    }

    QString identify;
    unsigned char sequence[] = {Module_UID::UID_REVISION};
    char result[8];
    if ( !(SendCommand(sequence, sizeof(sequence), 0)) ) return NULL;
    //if (port->read(result,sizeof(result)) == -1) return NULL;
    qint64 ret = uid->read(result,sizeof(result));
    if (ret==-1) return NULL;
    //return QString(result);
    return QString::fromAscii(result, ret-1);
}

bool Module_UID::UID_Available()
{
    return uid != NULL;
}

void Module_UID::doHealthCheck()
{
    if (!getSettings().value("enabled").toBool())
        return;

    QString Id = settings.value("uidId").toString();

    if ( uid == NULL ) {
        setHealthToSick("No uid open.");
        return;
    }

    QString received = UID_Identify();
    if ( received.length()==0) {
        return;
    }
    if ( received.length()>0 && received != Id) {
        setHealthToSick("Wrong Id, received: " + received);
        return;
    }

    setHealthToOk();
}

QVector<unsigned char> Module_UID::I2C_Scan() {
    unsigned char sequence[] = {Module_UID::I2C_SCAN};
    QVector<unsigned char> slaves(0);
    if (!SendCommand(sequence, sizeof(sequence), 0)) return slaves;
    unsigned char result[127];
    qint64 read = uid->read((char*)result, 127);
    if (read != -1) {
        for (int i=0; i<read; i++) slaves.append(result[i]);
    }
    return slaves;
}

bool Module_UID::SPI_Speed(unsigned char speed) {
    unsigned char sequence[] = {Module_UID::SPI_SPEED, speed};
    return SendCommand(sequence, sizeof(sequence), 0);
}

bool Module_UID::SPI_SetPHA(bool phase) {
    unsigned char sequence[] = {Module_UID::SPI_SETPHA, phase};
    return SendCommand(sequence, sizeof(sequence), 0);
}

bool Module_UID::SPI_SetPOL(bool pol){
    unsigned char sequence[] = {Module_UID::SPI_SETPOL, pol};
    return SendCommand(sequence, sizeof(sequence), 0);
}

bool Module_UID::SPI_Read(unsigned char address, short byteCount, unsigned char* result) {
    unsigned char sequence[] = {Module_UID::SPI_READ, address, byteCount};
    if (!SendCommand(sequence, sizeof(sequence) , 0)) return false;
    if ( (uid->read((char*)result, byteCount)) == -1) return false;
    return true;
}

bool Module_UID::SPI_Write(unsigned char address, unsigned char* data, short byteCount) {
    unsigned char sequence[] = {Module_UID::SPI_WRITE, address, byteCount};
    if (!SendCommand(sequence, sizeof(sequence), 0)) return false;
    if (!SendCommand(data, byteCount, 0)) return false;
    return true;
}

bool Module_UID::SPI_WriteRead(unsigned char address, unsigned char* data, short byteCount, unsigned char* result) {
    unsigned char sequence[] = {Module_UID::SPI_WRITE, address, byteCount};
    if (!SendCommand(sequence, sizeof(sequence), 0)) return false;
    if (!SendCommand(data, byteCount, 0)) return false;
    if ( (uid->read((char*)result, byteCount)) == -1) return false;
    return true;
}

bool Module_UID::I2C_DA_ReceiveAck() {
    unsigned char sequence[] = {Module_UID::I2C_DA_RECEIVEACK};
    return SendCommand(sequence, sizeof(sequence), 0);
}

bool Module_UID::I2C_DA_ReceiveByteAck() {
    unsigned char sequence[] = {Module_UID::I2C_DA_RECEIVEBYTEACK};
    return SendCommand(sequence, sizeof(sequence), 0);
}

bool Module_UID::I2C_DA_ReceiveByteNoAck() {
    unsigned char sequence[] = {Module_UID::I2C_DA_RECEIVEBYTENOACK};
    return SendCommand(sequence, sizeof(sequence), 0);
}

bool Module_UID::I2C_DA_RepStart() {
    unsigned char sequence[] = {Module_UID::I2C_DA_REPSTART};
    return SendCommand(sequence, sizeof(sequence), 0);
}

bool Module_UID::I2C_DA_SendAck() {
    unsigned char sequence[] = {Module_UID::I2C_DA_SENDACK};
    return SendCommand(sequence, sizeof(sequence), 0);
}

bool Module_UID::I2C_DA_SendByteAck(unsigned char data) {
    unsigned char sequence[] = {Module_UID::I2C_DA_SENDBYTEACK};
    return SendCommand(sequence, sizeof(sequence), 0);
}

bool Module_UID::I2C_DA_SendByteNoAck(unsigned char data) {
    unsigned char sequence[] = {Module_UID::I2C_DA_RECEIVEBYTENOACK};
    return SendCommand(sequence, sizeof(sequence), 0);
}

bool Module_UID::I2C_DA_Start() {
    unsigned char sequence[] = {Module_UID::I2C_DA_START};
    return SendCommand(sequence, sizeof(sequence), 0);
}

bool Module_UID::I2C_DA_Stop() {
    unsigned char sequence[] = {Module_UID::I2C_DA_STOP};
    return SendCommand(sequence, sizeof(sequence), 0);
}

bool Module_UID::UID_ADC(unsigned char bitmask, unsigned char* result) {
    unsigned char sequence[] = {Module_UID::ADC_ADC, bitmask};
    unsigned char values = countBitsSet(bitmask);

    if ( !(SendCommand(sequence, sizeof(sequence), 0)) ) return false;

    qint64 res = uid->read((char*)result,values);
    if (res==-1 || res<values) return false;

    return true;
}

bool Module_UID::I2C_Speed(Module_UID::I2CSpeed speed) {
    unsigned char sequence[] = {Module_UID::I2C_SCAN, speed};
    return SendCommand(sequence, sizeof(sequence), 0);
}

bool Module_UID::I2C_EnterAckMode() {
    unsigned char sequence[] = {Module_UID::I2C_ENTERACKMODE};
    return SendCommand(sequence, sizeof(sequence), 0);
}

unsigned char Module_UID::countBitsSet( unsigned char bitmask ) {
    unsigned char bits = 0;
    while (bitmask>0) {
        bits += (bitmask&1);
        bitmask = bitmask >> 1;
    }
    return bits;
}
<|endoftext|>