<commit_before>#include <libdariadb/storage/memstorage.h>
#include <libdariadb/flags.h>
#include <memory>
#include <tuple>
#include <unordered_map>
#include <cstring>
#include <cassert>

using namespace dariadb;
using namespace dariadb::storage;

MemChunkAllocator::MemChunkAllocator(size_t maxSize, size_t bufferSize) {
  _maxSize = maxSize;
  _bufferSize = bufferSize;
  _allocated = size_t(0);
  size_t one_sz = sizeof(ChunkHeader) + bufferSize;
  _capacity = (int)(float(_maxSize) / one_sz);

  _headers.resize(_capacity);
  _buffers = new uint8_t[_capacity * _bufferSize];
  for(size_t i=0;i<_capacity;++i){
      _free_list.push_back(i);
  }
}

MemChunkAllocator::~MemChunkAllocator() {
  delete[] _buffers;
}

MemChunkAllocator::allocated_data MemChunkAllocator::allocate() {
  _locker.lock();
  if(_free_list.empty()){
      _locker.unlock();
      return EMPTY;
  }
  auto pos=_free_list.front();
  _free_list.pop_front();
  _allocated++;
  _locker.unlock();
  memset(&_headers[pos], 0, sizeof(ChunkHeader));
  memset(&_buffers[pos * _bufferSize], 0, sizeof(_bufferSize));
  return allocated_data(&_headers[pos], &_buffers[pos * _bufferSize], pos);
}

void MemChunkAllocator::free(const MemChunkAllocator::allocated_data &d) {
  auto header = std::get<0>(d);
  auto buffer = std::get<1>(d);
  auto position = std::get<2>(d);
  memset(header, 0, sizeof(ChunkHeader));
  memset(buffer, 0, _bufferSize);
  _locker.lock();
  _allocated--;
  _free_list.push_back(position);
  _locker.unlock();
}

/**
Map:
  Meas.id -> TimeTrack{ MemChunkList[MemChunk{data}]}
*/

struct MemChunk : public ZippedChunk {
  ChunkHeader *index_ptr;
  uint8_t *buffer_ptr;
  MemChunkAllocator::allocated_data _a_data;
  MemChunk(ChunkHeader *index, uint8_t *buffer, size_t size, Meas first_m)
      : ZippedChunk(index, buffer, size, first_m) {
    index_ptr = index;
    buffer_ptr = buffer;
  }
  MemChunk(ChunkHeader *index, uint8_t *buffer) : ZippedChunk(index, buffer) {
    index_ptr = index;
    buffer_ptr = buffer;
  }
  ~MemChunk() {}
};

using MemChunk_Ptr = std::shared_ptr<MemChunk>;
using MemChunkList = std::list<MemChunk_Ptr>;

class TimeTrack : public IMeasStorage {
public:
  TimeTrack(const Time step, Id meas_id, MemChunkAllocator*allocator) {
	  _allocator = allocator;
    _meas_id = meas_id;
    _step = step;
	_minTime = MAX_TIME;
	_maxTime = MIN_TIME;
  }
  ~TimeTrack() {}

  MemChunkAllocator*_allocator;
  Id _meas_id;
  Time _minTime;
  Time _maxTime;
  Time _step;
  MemChunkList _chunks;
  MemChunk_Ptr _cur_chunk;
  utils::Locker _locker;

  void updateMinMax(const Meas&value) {
	  _minTime = std::min(_minTime, value.time);
	  _maxTime = std::max(_maxTime, value.time);
  }
  virtual append_result append(const Meas &value) override {
    std::lock_guard<utils::Locker> lg(_locker);
    if (_chunks.empty() || _chunks.back()->is_full()) {
		if (!create_new_chunk(value)) {
			return append_result(0,1);
		}
		else {
			updateMinMax(value);
			return append_result(1, 0);
		}
    }
	if (!_cur_chunk->append(value)) {
		if (!create_new_chunk(value)) {
			return append_result(0, 1);
		}
		else {
			updateMinMax(value);
			return append_result(1, 0);
		}
	}
	updateMinMax(value);
    return append_result(1, 0);
  }

  virtual void flush() {}

  virtual Time minTime() override {
	  return _minTime;
  }

  virtual Time maxTime() override {
	  return _maxTime;
  }

  virtual bool minMaxTime(dariadb::Id id, dariadb::Time *minResult,
                          dariadb::Time *maxResult) override {
	  if (id != this->_meas_id) {
		  return false;
	  }
	  std::lock_guard<utils::Locker> lg(_locker);
	  *minResult = MAX_TIME;
	  *maxResult = MIN_TIME;
	  for (auto c : _chunks) {
		  *minResult = std::min(c->header->minTime, *minResult);
		  *maxResult = std::max(c->header->maxTime, *maxResult);
	  }
	  return true;
  }

  //TODO use b+tree for fast search;
  virtual void foreach (const QueryInterval &q, IReaderClb * clbk) override {
    std::lock_guard<utils::Locker> lg(_locker);
    for (auto c : _chunks) {
      if (utils::inInterval(c->header->minTime, c->header->maxTime, q.from)
		  ||utils::inInterval(c->header->minTime, c->header->maxTime, q.to)
		  || utils::inInterval(q.from, q.to, c->header->minTime)
		  || utils::inInterval(q.from, q.to, c->header->maxTime)) {
        auto rdr = c->get_reader();

        while (!rdr->is_end()) {
          auto v = rdr->readNext();
		  if (utils::inInterval(q.from, q.to, v.time)) {
			  clbk->call(v);
		  }
        }
      }
    }
  }

  //TODO use b+tree for fast search;
  virtual Id2Meas readTimePoint(const QueryTimePoint &q) override {
	  std::lock_guard<utils::Locker> lg(_locker);
	  Id2Meas result;
	  result[this->_meas_id].flag = Flags::_NO_DATA;
	  for (auto c : _chunks) {
		  if (c->header->minTime >= q.time_point && c->header->maxTime <= q.time_point) {
			  auto rdr = c->get_reader();

			  while (!rdr->is_end()) {
				  auto v = rdr->readNext();
				  if (v.time > result[this->_meas_id].time && v.time<=q.time_point) {
					  result[this->_meas_id] = v;
				  }
			  }
		  }
	  }
	  if (result[this->_meas_id].flag == Flags::_NO_DATA) {
		  result[this->_meas_id].time = q.time_point;
	  }
	  return result;
  }

  virtual Id2Meas currentValue(const IdArray &ids, const Flag &flag) override {
      assert(ids.size() == size_t(1));
      assert(ids[0]==this->_meas_id);
	  std::lock_guard<utils::Locker> lg(_locker);
	  Id2Meas result;
	  result[_meas_id] = _chunks.back()->header->last;
	  return result;
  }

  bool create_new_chunk(const Meas&value) {
	  auto new_chunk_data = _allocator->allocate();
	  if (std::get<0>(new_chunk_data) == nullptr) {
		  return false;
	  }
	  auto mc = MemChunk_Ptr{ new MemChunk{ std::get<0>(new_chunk_data),
		  std::get<1>(new_chunk_data),
		  _allocator->_bufferSize, value } };
	  this->_chunks.push_back(mc);
	  _cur_chunk = mc;
	  return true;
  }
};

using TimeTrack_ptr = std::shared_ptr<TimeTrack>;
using Id2Track = std::unordered_map<Id, TimeTrack_ptr>;

struct MemStorage::Private : public IMeasStorage {
	Private(const MemStorage::Params &p) : _chunk_allocator(p.max_size, p.chunk_size) {}

	MemStorage::Description description()const {
		MemStorage::Description result;
        result.allocated = _chunk_allocator._allocated;
        result.allocator_capacity = _chunk_allocator._capacity;
		return result;
	}
  append_result append(const Meas &value) override {
	  auto track = _id2track.find(value.id);
	  if (track == _id2track.end()) {
		  std::lock_guard<utils::Locker> lg(_all_tracks_locker);
		  track = _id2track.find(value.id);
		  if (track == _id2track.end()) {
			  auto new_track = std::make_shared<TimeTrack>(Time(0), value.id, &_chunk_allocator);
			  _id2track.insert(std::make_pair(value.id, new_track));
			  new_track->append(value);
			  return append_result(1,0);
		  }
	  }
	  return track->second->append(value);
  }
  Time minTime() override {
	  Time result = MAX_TIME;
	  for (auto t : _id2track) {
		  result=std::min(result, t.second->minTime());
	  }
	  return result;
  }
  virtual Time maxTime() override {
	  Time result = MIN_TIME;
	  for (auto t : _id2track) {
		  result = std::max(result, t.second->maxTime());
	  }
	  return result;
  }
  virtual bool minMaxTime(dariadb::Id id, dariadb::Time *minResult,
                          dariadb::Time *maxResult) override {
	  auto tracker = _id2track.find(id);
	  if (tracker != _id2track.end()) {
		  return tracker->second->minMaxTime(id, minResult, maxResult);
	  }
	  return false;
  }

  void foreach (const QueryInterval &q, IReaderClb * clbk) override {
	  QueryInterval local_q({}, q.flag, q.from,q.to);
	  local_q.ids.resize(1);
	  for (auto id : q.ids) {
		  auto tracker = _id2track.find(id);
		  if (tracker != _id2track.end()) {
			  local_q.ids[0] = id;
			  tracker->second->foreach(local_q,clbk);
		  }
	  }
	  clbk->is_end();
  }

  virtual Id2Meas readTimePoint(const QueryTimePoint &q) override {
	  QueryTimePoint local_q({}, q.flag, q.time_point);
	  local_q.ids.resize(1);
	  Id2Meas result;
	  for (auto id : q.ids) {
		  auto tracker = _id2track.find(id);
		  if (tracker != _id2track.end()) {
			  local_q.ids[0] = id;
			  auto sub_res = tracker->second->readTimePoint(local_q);
			  result[id] = sub_res[id];
		  }
		  else {
			  result[id].flag = Flags::_NO_DATA;
		  }
	  }
	  return result;
  }
  virtual Id2Meas currentValue(const IdArray &ids, const Flag &flag) override {
	  IdArray local_ids;
      local_ids.resize(1);
	  Id2Meas result;
	  for (auto id : ids) {
		  auto tracker = _id2track.find(id);
		  if (tracker != _id2track.end()) {
			  local_ids[0] = id;
			  auto sub_res = tracker->second->currentValue(local_ids, flag);
			  result[id] = sub_res[id];
		  }
		  else {
			  result[id].flag = Flags::_NO_DATA;
		  }
	  }
	  return result;
  }

  void flush() override {}

  Id2Track _id2track;
  MemChunkAllocator _chunk_allocator;
  utils::Locker _all_tracks_locker;
};

MemStorage::MemStorage(const MemStorage::Params &p) : _impl(new MemStorage::Private(p)) {}

MemStorage::~MemStorage() {
  _impl = nullptr;
}

MemStorage::Description MemStorage::description() const{
	return _impl->description();
}

Time dariadb::storage::MemStorage::minTime() {
  return _impl->minTime();
}

Time dariadb::storage::MemStorage::maxTime() {
  return _impl->maxTime();
}

bool dariadb::storage::MemStorage::minMaxTime(dariadb::Id id, dariadb::Time *minResult,
                                              dariadb::Time *maxResult) {
  return _impl->minMaxTime(id, minResult, maxResult);
}

void dariadb::storage::MemStorage::foreach (const QueryInterval &q, IReaderClb * clbk) {
  _impl->foreach (q, clbk);
}

Id2Meas dariadb::storage::MemStorage::readTimePoint(const QueryTimePoint &q) {
  return _impl->readTimePoint(q);
}

Id2Meas dariadb::storage::MemStorage::currentValue(const IdArray &ids, const Flag &flag) {
  return _impl->currentValue(ids, flag);
}

append_result dariadb::storage::MemStorage::append(const Meas &value) {
  return _impl->append(value);
}

void dariadb::storage::MemStorage::flush() {
  _impl->flush();
}
<commit_msg>MemChunkAllocator: memset for buffer.<commit_after>#include <libdariadb/storage/memstorage.h>
#include <libdariadb/flags.h>
#include <memory>
#include <tuple>
#include <unordered_map>
#include <cstring>
#include <cassert>

using namespace dariadb;
using namespace dariadb::storage;

MemChunkAllocator::MemChunkAllocator(size_t maxSize, size_t bufferSize) {
  _maxSize = maxSize;
  _bufferSize = bufferSize;
  _allocated = size_t(0);
  size_t one_chunk_size = sizeof(ChunkHeader) + bufferSize;
  _capacity = (int)(float(_maxSize) / one_chunk_size);
  size_t buffers_size=_capacity * _bufferSize;

  _headers.resize(_capacity);
  _buffers = new uint8_t[buffers_size];

  memset(_buffers,0,buffers_size);
  for(size_t i=0;i<_capacity;++i){
      memset(&_headers[i],0,sizeof(ChunkHeader));
      _free_list.push_back(i);
  }
}

MemChunkAllocator::~MemChunkAllocator() {
  delete[] _buffers;
}

MemChunkAllocator::allocated_data MemChunkAllocator::allocate() {
  _locker.lock();
  if(_free_list.empty()){
      _locker.unlock();
      return EMPTY;
  }
  auto pos=_free_list.front();
  _free_list.pop_front();
  _allocated++;
  _locker.unlock();
  return allocated_data(&_headers[pos], &_buffers[pos * _bufferSize], pos);
}

void MemChunkAllocator::free(const MemChunkAllocator::allocated_data &d) {
  auto header = std::get<0>(d);
  auto buffer = std::get<1>(d);
  auto position = std::get<2>(d);
  memset(header, 0, sizeof(ChunkHeader));
  memset(buffer, 0, _bufferSize);
  _locker.lock();
  _allocated--;
  _free_list.push_back(position);
  _locker.unlock();
}

/**
Map:
  Meas.id -> TimeTrack{ MemChunkList[MemChunk{data}]}
*/

struct MemChunk : public ZippedChunk {
  ChunkHeader *index_ptr;
  uint8_t *buffer_ptr;
  MemChunkAllocator::allocated_data _a_data;
  MemChunk(ChunkHeader *index, uint8_t *buffer, size_t size, Meas first_m)
      : ZippedChunk(index, buffer, size, first_m) {
    index_ptr = index;
    buffer_ptr = buffer;
  }
  MemChunk(ChunkHeader *index, uint8_t *buffer) : ZippedChunk(index, buffer) {
    index_ptr = index;
    buffer_ptr = buffer;
  }
  ~MemChunk() {}
};

using MemChunk_Ptr = std::shared_ptr<MemChunk>;
using MemChunkList = std::list<MemChunk_Ptr>;

class TimeTrack : public IMeasStorage {
public:
  TimeTrack(const Time step, Id meas_id, MemChunkAllocator*allocator) {
	  _allocator = allocator;
    _meas_id = meas_id;
    _step = step;
	_minTime = MAX_TIME;
	_maxTime = MIN_TIME;
  }
  ~TimeTrack() {}

  MemChunkAllocator*_allocator;
  Id _meas_id;
  Time _minTime;
  Time _maxTime;
  Time _step;
  MemChunkList _chunks;
  MemChunk_Ptr _cur_chunk;
  utils::Locker _locker;

  void updateMinMax(const Meas&value) {
	  _minTime = std::min(_minTime, value.time);
	  _maxTime = std::max(_maxTime, value.time);
  }
  virtual append_result append(const Meas &value) override {
    std::lock_guard<utils::Locker> lg(_locker);
    if (_chunks.empty() || _chunks.back()->is_full()) {
		if (!create_new_chunk(value)) {
			return append_result(0,1);
		}
		else {
			updateMinMax(value);
			return append_result(1, 0);
		}
    }
	if (!_cur_chunk->append(value)) {
		if (!create_new_chunk(value)) {
			return append_result(0, 1);
		}
		else {
			updateMinMax(value);
			return append_result(1, 0);
		}
	}
	updateMinMax(value);
    return append_result(1, 0);
  }

  virtual void flush() {}

  virtual Time minTime() override {
	  return _minTime;
  }

  virtual Time maxTime() override {
	  return _maxTime;
  }

  virtual bool minMaxTime(dariadb::Id id, dariadb::Time *minResult,
                          dariadb::Time *maxResult) override {
	  if (id != this->_meas_id) {
		  return false;
	  }
	  std::lock_guard<utils::Locker> lg(_locker);
	  *minResult = MAX_TIME;
	  *maxResult = MIN_TIME;
	  for (auto c : _chunks) {
		  *minResult = std::min(c->header->minTime, *minResult);
		  *maxResult = std::max(c->header->maxTime, *maxResult);
	  }
	  return true;
  }

  //TODO use b+tree for fast search;
  virtual void foreach (const QueryInterval &q, IReaderClb * clbk) override {
    std::lock_guard<utils::Locker> lg(_locker);
    for (auto c : _chunks) {
      if (utils::inInterval(c->header->minTime, c->header->maxTime, q.from)
		  ||utils::inInterval(c->header->minTime, c->header->maxTime, q.to)
		  || utils::inInterval(q.from, q.to, c->header->minTime)
		  || utils::inInterval(q.from, q.to, c->header->maxTime)) {
        auto rdr = c->get_reader();

        while (!rdr->is_end()) {
          auto v = rdr->readNext();
		  if (utils::inInterval(q.from, q.to, v.time)) {
			  clbk->call(v);
		  }
        }
      }
    }
  }

  //TODO use b+tree for fast search;
  virtual Id2Meas readTimePoint(const QueryTimePoint &q) override {
	  std::lock_guard<utils::Locker> lg(_locker);
	  Id2Meas result;
	  result[this->_meas_id].flag = Flags::_NO_DATA;
	  for (auto c : _chunks) {
		  if (c->header->minTime >= q.time_point && c->header->maxTime <= q.time_point) {
			  auto rdr = c->get_reader();

			  while (!rdr->is_end()) {
				  auto v = rdr->readNext();
				  if (v.time > result[this->_meas_id].time && v.time<=q.time_point) {
					  result[this->_meas_id] = v;
				  }
			  }
		  }
	  }
	  if (result[this->_meas_id].flag == Flags::_NO_DATA) {
		  result[this->_meas_id].time = q.time_point;
	  }
	  return result;
  }

  virtual Id2Meas currentValue(const IdArray &ids, const Flag &flag) override {
      assert(ids.size() == size_t(1));
      assert(ids[0]==this->_meas_id);
	  std::lock_guard<utils::Locker> lg(_locker);
	  Id2Meas result;
	  result[_meas_id] = _chunks.back()->header->last;
	  return result;
  }

  bool create_new_chunk(const Meas&value) {
	  auto new_chunk_data = _allocator->allocate();
	  if (std::get<0>(new_chunk_data) == nullptr) {
		  return false;
	  }
	  auto mc = MemChunk_Ptr{ new MemChunk{ std::get<0>(new_chunk_data),
		  std::get<1>(new_chunk_data),
		  _allocator->_bufferSize, value } };
	  this->_chunks.push_back(mc);
	  _cur_chunk = mc;
	  return true;
  }
};

using TimeTrack_ptr = std::shared_ptr<TimeTrack>;
using Id2Track = std::unordered_map<Id, TimeTrack_ptr>;

struct MemStorage::Private : public IMeasStorage {
	Private(const MemStorage::Params &p) : _chunk_allocator(p.max_size, p.chunk_size) {}

	MemStorage::Description description()const {
		MemStorage::Description result;
        result.allocated = _chunk_allocator._allocated;
        result.allocator_capacity = _chunk_allocator._capacity;
		return result;
	}
  append_result append(const Meas &value) override {
	  auto track = _id2track.find(value.id);
	  if (track == _id2track.end()) {
		  std::lock_guard<utils::Locker> lg(_all_tracks_locker);
		  track = _id2track.find(value.id);
		  if (track == _id2track.end()) {
			  auto new_track = std::make_shared<TimeTrack>(Time(0), value.id, &_chunk_allocator);
			  _id2track.insert(std::make_pair(value.id, new_track));
			  new_track->append(value);
			  return append_result(1,0);
		  }
	  }
	  return track->second->append(value);
  }
  Time minTime() override {
	  Time result = MAX_TIME;
	  for (auto t : _id2track) {
		  result=std::min(result, t.second->minTime());
	  }
	  return result;
  }
  virtual Time maxTime() override {
	  Time result = MIN_TIME;
	  for (auto t : _id2track) {
		  result = std::max(result, t.second->maxTime());
	  }
	  return result;
  }
  virtual bool minMaxTime(dariadb::Id id, dariadb::Time *minResult,
                          dariadb::Time *maxResult) override {
	  auto tracker = _id2track.find(id);
	  if (tracker != _id2track.end()) {
		  return tracker->second->minMaxTime(id, minResult, maxResult);
	  }
	  return false;
  }

  void foreach (const QueryInterval &q, IReaderClb * clbk) override {
	  QueryInterval local_q({}, q.flag, q.from,q.to);
	  local_q.ids.resize(1);
	  for (auto id : q.ids) {
		  auto tracker = _id2track.find(id);
		  if (tracker != _id2track.end()) {
			  local_q.ids[0] = id;
			  tracker->second->foreach(local_q,clbk);
		  }
	  }
	  clbk->is_end();
  }

  virtual Id2Meas readTimePoint(const QueryTimePoint &q) override {
	  QueryTimePoint local_q({}, q.flag, q.time_point);
	  local_q.ids.resize(1);
	  Id2Meas result;
	  for (auto id : q.ids) {
		  auto tracker = _id2track.find(id);
		  if (tracker != _id2track.end()) {
			  local_q.ids[0] = id;
			  auto sub_res = tracker->second->readTimePoint(local_q);
			  result[id] = sub_res[id];
		  }
		  else {
			  result[id].flag = Flags::_NO_DATA;
		  }
	  }
	  return result;
  }
  virtual Id2Meas currentValue(const IdArray &ids, const Flag &flag) override {
	  IdArray local_ids;
      local_ids.resize(1);
	  Id2Meas result;
	  for (auto id : ids) {
		  auto tracker = _id2track.find(id);
		  if (tracker != _id2track.end()) {
			  local_ids[0] = id;
			  auto sub_res = tracker->second->currentValue(local_ids, flag);
			  result[id] = sub_res[id];
		  }
		  else {
			  result[id].flag = Flags::_NO_DATA;
		  }
	  }
	  return result;
  }

  void flush() override {}

  Id2Track _id2track;
  MemChunkAllocator _chunk_allocator;
  utils::Locker _all_tracks_locker;
};

MemStorage::MemStorage(const MemStorage::Params &p) : _impl(new MemStorage::Private(p)) {}

MemStorage::~MemStorage() {
  _impl = nullptr;
}

MemStorage::Description MemStorage::description() const{
	return _impl->description();
}

Time dariadb::storage::MemStorage::minTime() {
  return _impl->minTime();
}

Time dariadb::storage::MemStorage::maxTime() {
  return _impl->maxTime();
}

bool dariadb::storage::MemStorage::minMaxTime(dariadb::Id id, dariadb::Time *minResult,
                                              dariadb::Time *maxResult) {
  return _impl->minMaxTime(id, minResult, maxResult);
}

void dariadb::storage::MemStorage::foreach (const QueryInterval &q, IReaderClb * clbk) {
  _impl->foreach (q, clbk);
}

Id2Meas dariadb::storage::MemStorage::readTimePoint(const QueryTimePoint &q) {
  return _impl->readTimePoint(q);
}

Id2Meas dariadb::storage::MemStorage::currentValue(const IdArray &ids, const Flag &flag) {
  return _impl->currentValue(ids, flag);
}

append_result dariadb::storage::MemStorage::append(const Meas &value) {
  return _impl->append(value);
}

void dariadb::storage::MemStorage::flush() {
  _impl->flush();
}
<|endoftext|>


<commit_before>// ------------------------------------------------------------------------
// audioio-db-client.cpp: Client class for double-buffering providing
//                        additional layer of buffering for objects
//                        derived from AUDIO_IO.
// Copyright (C) 2000-2005,2009 Kai Vehmanen
//
// Attributes:
//     eca-style-version: 3
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA
// ------------------------------------------------------------------------

#include <unistd.h> /* open(), close() */

#include <kvu_dbc.h>
#include <kvu_numtostr.h>

#include "samplebuffer.h"
#include "eca-logger.h"
#include "audioio-db-client.h"

/**
 * Constructor. The given client object is registered to
 * the given db server as a client object.
 *
 * Ownership of 'aobject' is transfered to this db client
 * object if 'transfer_ownership' is true.
 */
AUDIO_IO_DB_CLIENT::AUDIO_IO_DB_CLIENT (AUDIO_IO_DB_SERVER *pserver,
					AUDIO_IO* aobject,
					bool transfer_ownership)
  : pserver_repp(pserver),
    free_child_rep(transfer_ownership)
{
  set_child(aobject);
  pbuffer_repp = 0;
  xruns_rep = 0;
  finished_rep = false;
  recursing_rep = false;

  ECA_LOG_MSG(ECA_LOGGER::user_objects,
		std::string("DB-client created for ") +
		child()->label() +
		".");

  // just in case the child object has already been configured
  fetch_initial_child_data();
}

/**
 * Copy attributes from the proxied (child) object.
 */
void AUDIO_IO_DB_CLIENT::fetch_initial_child_data(void)
{
  // note! the child object is one that is configured
  //       at this point
  set_audio_format(child()->audio_format());
  set_position_in_samples(child()->position_in_samples());
  set_length_in_samples(child()->length_in_samples());
  set_buffersize(child()->buffersize());
  set_io_mode(child()->io_mode());
  set_label(child()->label());
  toggle_nonblocking_mode(child()->nonblocking_mode());
}

/**
 * Desctructor. Unregisters the client from the db
 * server.
 */
AUDIO_IO_DB_CLIENT::~AUDIO_IO_DB_CLIENT(void)
{
  ECA_LOG_MSG(ECA_LOGGER::user_objects, "destructor " + label() + ".");

  if (is_open() == true) {
    close();
  }

  if (pserver_repp != 0) {
    bool was_running = false;
    if (pserver_repp->is_running() == true) {
      was_running = true;
      pserver_repp->stop();
      pserver_repp->wait_for_stop();
      DBC_CHECK(pserver_repp->is_running() != true);
    }

    pserver_repp->unregister_client(child());
    pbuffer_repp = 0;

    if (was_running == true) {
      pserver_repp->start();
    }
  }

  if (free_child_rep != true) {
    /* to avoid deleting the original registered child */
    release_child_no_delete();
  }

  if (xruns_rep > 0)
    std::cerr << "(audioio-db-client) There were total " << xruns_rep << " xruns." << std::endl;
}

/**
 * Whether all data has been processed? If opened in mode 'io_read',
 * this means that end of stream has been reached. If opened in
 * 'io_write' or 'io_readwrite' modes, finished status usually
 * means that an error has occured (no space left, etc). After
 * finished() has returned 'true', further calls to read_buffer()
 * and/or write_buffer() won't process any data.
 */
bool AUDIO_IO_DB_CLIENT::finished(void) const { return finished_rep; }

/**
 * Reads samples to buffer pointed by 'sbuf'. If necessary, the target
 * buffer will be resized.
 */
void AUDIO_IO_DB_CLIENT::read_buffer(SAMPLE_BUFFER* sbuf)
{
  DBC_CHECK(pbuffer_repp != 0);

  if (pbuffer_repp->read_space() > 0) {
    SAMPLE_BUFFER* source = pbuffer_repp->sbufs_rep[pbuffer_repp->readptr_rep.get()];
    sbuf->copy_all_content(*source);
    pbuffer_repp->advance_read_pointer();
    pserver_repp->signal_client_activity();
    change_position_in_samples(sbuf->length_in_samples());
  }
  else {
    sbuf->number_of_channels(channels());
    if (pbuffer_repp->finished_rep.get() == 1) {
      finished_rep = true;
      sbuf->length_in_samples(0);
    }
    else {
      xruns_rep++;
      sbuf->length_in_samples(0);

      std::cerr << "(audioio-db-client) WARNING: Underrun in reading from \""
		<< child()->label()
		<< "\". Trying to recover." << std::endl;
    }
  }
}

/**
 * Writes all data from sample buffer pointed by 'sbuf'. Notes
 * concerning read_buffer() also apply to this routine.
 */
void AUDIO_IO_DB_CLIENT::write_buffer(SAMPLE_BUFFER* sbuf)
{
  DBC_CHECK(pbuffer_repp != 0);

  if (pbuffer_repp->write_space() > 0) {
    SAMPLE_BUFFER* target = pbuffer_repp->sbufs_rep[pbuffer_repp->writeptr_rep.get()];
    target->copy_all_content(*sbuf);
    target->number_of_channels(channels());
    pbuffer_repp->advance_write_pointer();
    pserver_repp->signal_client_activity();
    change_position_in_samples(sbuf->length_in_samples());
    extend_position();
  }
  else {
    if (pbuffer_repp->finished_rep.get() == 1) finished_rep = true;
    else {
      /* NOTE: not always rt-safe, but it's better to break rt-safety than
       *       to lose recorded data */

      std::cerr << "(audioio-db-client) WARNING: Overrun in writing to \""
		<< child()->label()
		<< "\". Trying to recover." << std::endl;

      xruns_rep++;

      pserver_repp->wait_for_full();
      if (recursing_rep != true && pbuffer_repp->write_space() > 0) {
	recursing_rep = true;
	this->write_buffer(sbuf);
	recursing_rep = false;
      }
      else {
	seek_position(position_in_samples()); // hack to force a restart of the db server
	std::cerr << "(audioio-db-client) Serious trouble with the disk-io subsystem! (output)" << std::endl;
      }
    }
  }
}

/**
 * Stops the DB server in case it's running.
 * Returns true if server was running. The return
 * value should be passed to restore_db_server_state()
 * function.
 */
bool AUDIO_IO_DB_CLIENT::pause_db_server_if_running(void)
{
  bool was_running = false;
  if (pserver_repp->is_running() == true) {
    was_running = true;
    pserver_repp->stop();
    pserver_repp->wait_for_stop();
    DBC_CHECK(pserver_repp->is_running() != true);
  }

  return was_running;
}

void AUDIO_IO_DB_CLIENT::restore_db_server_state(bool was_running)
{
  if (was_running == true) {
    pserver_repp->start();
    pserver_repp->wait_for_full();
    DBC_CHECK(pserver_repp->is_running() == true);
  }
}

/**
 * Seeks to the current position.
 *
 * Note! Seeking involves stopping the whole db
 *       server, so it's a costly operation.
 */
SAMPLE_SPECS::sample_pos_t AUDIO_IO_DB_CLIENT::seek_position(SAMPLE_SPECS::sample_pos_t pos)
{
  ECA_LOG_MSG(ECA_LOGGER::user_objects,
	      "seek " + label() +
	      " to pos " + kvu_numtostr(pos) + ".");
  SAMPLE_SPECS::sample_pos_t res =
    child()->position_in_samples();

  if (child()->supports_seeking() == true) {
    bool was_running = pause_db_server_if_running();

    child()->seek_position_in_samples(pos);
    res = child()->position_in_samples();
    if (pbuffer_repp != 0) {
      pbuffer_repp->reset();
    }

    finished_rep = false;

    restore_db_server_state(was_running);
  }

  return AUDIO_IO_PROXY::seek_position(res);
}

/**
 * Opens the child audio object (possibly in exclusive mode).
 * This routine is meant for opening files and devices,
 * loading libraries, etc.
 */
void AUDIO_IO_DB_CLIENT::open(void) throw(AUDIO_IO::SETUP_ERROR&)
{
  ECA_LOG_MSG(ECA_LOGGER::user_objects, "open " + label() + ".");

  if (child()->is_open() != true) {
    child()->open();
  }

  set_audio_format(child()->audio_format());
  set_length_in_samples(child()->length_in_samples());

  if (pbuffer_repp == 0) {
    pserver_repp->register_client(child());
    pbuffer_repp = pserver_repp->get_client_buffer(child());

    for(unsigned int n = 0; n < pbuffer_repp->sbufs_rep.size(); n++) {
      pbuffer_repp->sbufs_rep[n]->number_of_channels(channels());
      pbuffer_repp->sbufs_rep[n]->length_in_samples(buffersize());
    }

    if (io_mode() == AUDIO_IO::io_read)
      pbuffer_repp->io_mode_rep = AUDIO_IO::io_read;
    else
      pbuffer_repp->io_mode_rep = AUDIO_IO::io_write;
  }

  AUDIO_IO::open();
}

/**
 * Closes the child audio object. After calling this routine,
 * all resources (ie. soundcard) must be freed
 * (they can be used by other processes).
 */
void AUDIO_IO_DB_CLIENT::close(void)
{
  ECA_LOG_MSG(ECA_LOGGER::user_objects, "close " + label() + ".");

  if (child()->is_open() == true) child()->close();

  AUDIO_IO::close();
}

void AUDIO_IO_DB_CLIENT::start_io(void)
{
  AUDIO_IO_PROXY::start_io();

  /* note: child may have changed its position after
   *       start_io() is issued (via AUDIO_IO_PROXY::start_io() */

  if (child()->supports_seeking() != true) {
    bool was_running = pause_db_server_if_running();

    set_position_in_samples(child()->position_in_samples());

    /* as position might have changed, flush the buffers */
    if (pbuffer_repp != 0) {
      pbuffer_repp->reset();
    }

    restore_db_server_state(was_running);
  }
}

void AUDIO_IO_DB_CLIENT::stop_io(void)
{
  AUDIO_IO_PROXY::stop_io();
}
<commit_msg>Added a dbc check to AUDIO_IO_DB_CLIENT<commit_after>// ------------------------------------------------------------------------
// audioio-db-client.cpp: Client class for double-buffering providing
//                        additional layer of buffering for objects
//                        derived from AUDIO_IO.
// Copyright (C) 2000-2005,2009 Kai Vehmanen
//
// Attributes:
//     eca-style-version: 3
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA
// ------------------------------------------------------------------------

#include <unistd.h> /* open(), close() */

#include <kvu_dbc.h>
#include <kvu_numtostr.h>

#include "samplebuffer.h"
#include "eca-logger.h"
#include "audioio-db-client.h"

/**
 * Constructor. The given client object is registered to
 * the given db server as a client object.
 *
 * Ownership of 'aobject' is transfered to this db client
 * object if 'transfer_ownership' is true.
 */
AUDIO_IO_DB_CLIENT::AUDIO_IO_DB_CLIENT (AUDIO_IO_DB_SERVER *pserver,
					AUDIO_IO* aobject,
					bool transfer_ownership)
  : pserver_repp(pserver),
    free_child_rep(transfer_ownership)
{
  set_child(aobject);
  pbuffer_repp = 0;
  xruns_rep = 0;
  finished_rep = false;
  recursing_rep = false;

  ECA_LOG_MSG(ECA_LOGGER::user_objects,
		std::string("DB-client created for ") +
		child()->label() +
		".");

  // just in case the child object has already been configured
  fetch_initial_child_data();
}

/**
 * Copy attributes from the proxied (child) object.
 */
void AUDIO_IO_DB_CLIENT::fetch_initial_child_data(void)
{
  // note! the child object is one that is configured
  //       at this point
  set_audio_format(child()->audio_format());
  set_position_in_samples(child()->position_in_samples());
  set_length_in_samples(child()->length_in_samples());
  set_buffersize(child()->buffersize());
  set_io_mode(child()->io_mode());
  set_label(child()->label());
  toggle_nonblocking_mode(child()->nonblocking_mode());
}

/**
 * Desctructor. Unregisters the client from the db
 * server.
 */
AUDIO_IO_DB_CLIENT::~AUDIO_IO_DB_CLIENT(void)
{
  ECA_LOG_MSG(ECA_LOGGER::user_objects, "destructor " + label() + ".");

  if (is_open() == true) {
    close();
  }

  if (pserver_repp != 0) {
    bool was_running = false;
    if (pserver_repp->is_running() == true) {
      was_running = true;
      pserver_repp->stop();
      pserver_repp->wait_for_stop();
      DBC_CHECK(pserver_repp->is_running() != true);
    }

    pserver_repp->unregister_client(child());
    pbuffer_repp = 0;

    if (was_running == true) {
      pserver_repp->start();
    }
  }

  if (free_child_rep != true) {
    /* to avoid deleting the original registered child */
    release_child_no_delete();
  }

  if (xruns_rep > 0)
    std::cerr << "(audioio-db-client) There were total " << xruns_rep << " xruns." << std::endl;
}

/**
 * Whether all data has been processed? If opened in mode 'io_read',
 * this means that end of stream has been reached. If opened in
 * 'io_write' or 'io_readwrite' modes, finished status usually
 * means that an error has occured (no space left, etc). After
 * finished() has returned 'true', further calls to read_buffer()
 * and/or write_buffer() won't process any data.
 */
bool AUDIO_IO_DB_CLIENT::finished(void) const { return finished_rep; }

/**
 * Reads samples to buffer pointed by 'sbuf'. If necessary, the target
 * buffer will be resized.
 */
void AUDIO_IO_DB_CLIENT::read_buffer(SAMPLE_BUFFER* sbuf)
{
  DBC_CHECK(pbuffer_repp != 0);

  if (pbuffer_repp->read_space() > 0) {
    SAMPLE_BUFFER* source = pbuffer_repp->sbufs_rep[pbuffer_repp->readptr_rep.get()];
    sbuf->copy_all_content(*source);
    pbuffer_repp->advance_read_pointer();
    pserver_repp->signal_client_activity();
    change_position_in_samples(sbuf->length_in_samples());
  }
  else {
    sbuf->number_of_channels(channels());
    if (pbuffer_repp->finished_rep.get() == 1) {
      finished_rep = true;
      sbuf->length_in_samples(0);
    }
    else {
      xruns_rep++;
      sbuf->length_in_samples(0);

      std::cerr << "(audioio-db-client) WARNING: Underrun in reading from \""
		<< child()->label()
		<< "\". Trying to recover." << std::endl;
    }
  }

  // --------
  DBC_ENSURE(sbuf->number_of_channels() == channels());
  // --------
}

/**
 * Writes all data from sample buffer pointed by 'sbuf'. Notes
 * concerning read_buffer() also apply to this routine.
 */
void AUDIO_IO_DB_CLIENT::write_buffer(SAMPLE_BUFFER* sbuf)
{
  DBC_CHECK(pbuffer_repp != 0);

  if (pbuffer_repp->write_space() > 0) {
    SAMPLE_BUFFER* target = pbuffer_repp->sbufs_rep[pbuffer_repp->writeptr_rep.get()];
    target->copy_all_content(*sbuf);
    target->number_of_channels(channels());
    pbuffer_repp->advance_write_pointer();
    pserver_repp->signal_client_activity();
    change_position_in_samples(sbuf->length_in_samples());
    extend_position();
  }
  else {
    if (pbuffer_repp->finished_rep.get() == 1) finished_rep = true;
    else {
      /* NOTE: not always rt-safe, but it's better to break rt-safety than
       *       to lose recorded data */

      std::cerr << "(audioio-db-client) WARNING: Overrun in writing to \""
		<< child()->label()
		<< "\". Trying to recover." << std::endl;

      xruns_rep++;

      pserver_repp->wait_for_full();
      if (recursing_rep != true && pbuffer_repp->write_space() > 0) {
	recursing_rep = true;
	this->write_buffer(sbuf);
	recursing_rep = false;
      }
      else {
	seek_position(position_in_samples()); // hack to force a restart of the db server
	std::cerr << "(audioio-db-client) Serious trouble with the disk-io subsystem! (output)" << std::endl;
      }
    }
  }
}

/**
 * Stops the DB server in case it's running.
 * Returns true if server was running. The return
 * value should be passed to restore_db_server_state()
 * function.
 */
bool AUDIO_IO_DB_CLIENT::pause_db_server_if_running(void)
{
  bool was_running = false;
  if (pserver_repp->is_running() == true) {
    was_running = true;
    pserver_repp->stop();
    pserver_repp->wait_for_stop();
    DBC_CHECK(pserver_repp->is_running() != true);
  }

  return was_running;
}

void AUDIO_IO_DB_CLIENT::restore_db_server_state(bool was_running)
{
  if (was_running == true) {
    pserver_repp->start();
    pserver_repp->wait_for_full();
    DBC_CHECK(pserver_repp->is_running() == true);
  }
}

/**
 * Seeks to the current position.
 *
 * Note! Seeking involves stopping the whole db
 *       server, so it's a costly operation.
 */
SAMPLE_SPECS::sample_pos_t AUDIO_IO_DB_CLIENT::seek_position(SAMPLE_SPECS::sample_pos_t pos)
{
  ECA_LOG_MSG(ECA_LOGGER::user_objects,
	      "seek " + label() +
	      " to pos " + kvu_numtostr(pos) + ".");
  SAMPLE_SPECS::sample_pos_t res =
    child()->position_in_samples();

  if (child()->supports_seeking() == true) {
    bool was_running = pause_db_server_if_running();

    child()->seek_position_in_samples(pos);
    res = child()->position_in_samples();
    if (pbuffer_repp != 0) {
      pbuffer_repp->reset();
    }

    finished_rep = false;

    restore_db_server_state(was_running);
  }

  return AUDIO_IO_PROXY::seek_position(res);
}

/**
 * Opens the child audio object (possibly in exclusive mode).
 * This routine is meant for opening files and devices,
 * loading libraries, etc.
 */
void AUDIO_IO_DB_CLIENT::open(void) throw(AUDIO_IO::SETUP_ERROR&)
{
  ECA_LOG_MSG(ECA_LOGGER::user_objects, "open " + label() + ".");

  if (child()->is_open() != true) {
    child()->open();
  }

  set_audio_format(child()->audio_format());
  set_length_in_samples(child()->length_in_samples());

  if (pbuffer_repp == 0) {
    pserver_repp->register_client(child());
    pbuffer_repp = pserver_repp->get_client_buffer(child());

    for(unsigned int n = 0; n < pbuffer_repp->sbufs_rep.size(); n++) {
      pbuffer_repp->sbufs_rep[n]->number_of_channels(channels());
      pbuffer_repp->sbufs_rep[n]->length_in_samples(buffersize());
    }

    if (io_mode() == AUDIO_IO::io_read)
      pbuffer_repp->io_mode_rep = AUDIO_IO::io_read;
    else
      pbuffer_repp->io_mode_rep = AUDIO_IO::io_write;
  }

  AUDIO_IO::open();
}

/**
 * Closes the child audio object. After calling this routine,
 * all resources (ie. soundcard) must be freed
 * (they can be used by other processes).
 */
void AUDIO_IO_DB_CLIENT::close(void)
{
  ECA_LOG_MSG(ECA_LOGGER::user_objects, "close " + label() + ".");

  if (child()->is_open() == true) child()->close();

  AUDIO_IO::close();
}

void AUDIO_IO_DB_CLIENT::start_io(void)
{
  AUDIO_IO_PROXY::start_io();

  /* note: child may have changed its position after
   *       start_io() is issued (via AUDIO_IO_PROXY::start_io() */

  if (child()->supports_seeking() != true) {
    bool was_running = pause_db_server_if_running();

    set_position_in_samples(child()->position_in_samples());

    /* as position might have changed, flush the buffers */
    if (pbuffer_repp != 0) {
      pbuffer_repp->reset();
    }

    restore_db_server_state(was_running);
  }
}

void AUDIO_IO_DB_CLIENT::stop_io(void)
{
  AUDIO_IO_PROXY::stop_io();
}
<|endoftext|>


<commit_before>/******************************************************************************
* Zowi LED Matrix Library
*
* @version 20150710
* @author Raul de Pablos Martin
*         José Alberca Pita-Romero (Mouth's definitions)
******************************************************************************/

#include "LedMatrix.h"

#if defined(ARDUINO) && ARDUINO >= 100
  #include "Arduino.h"
#else
  #include "WProgram.h"
#endif

LedMatrix::LedMatrix(char ser_pin, char clk_pin, char rck_pin) {
	memory = 0x00000000;
	SER = ser_pin;
	CLK = clk_pin;
	RCK = rck_pin;
	pinMode(SER, OUTPUT);
	pinMode(CLK, OUTPUT);
	pinMode(RCK, OUTPUT);
	digitalWrite(SER, LOW);
	digitalWrite(CLK, LOW);
	digitalWrite(RCK, LOW);
	sendMemory();
}

void LedMatrix::writeFull(unsigned long value) {
	memory = value;
	sendMemory();
}

unsigned long LedMatrix::readFull(void) {
	return memory;
}

void LedMatrix::setLed(char row, char column) {
	if(row >= 1 && row <= ROWS && column >= 1 && column <= COLUMNS) {
		memory |= (1L << (MATRIX_LENGTH - (row-1)*COLUMNS - (column)));
		sendMemory();
	}
}

void LedMatrix::unsetLed(char row, char column) {
	if(row >= 1 && row <= ROWS && column >= 1 && column <= COLUMNS) {
		memory &= ~(1L << (MATRIX_LENGTH - (row-1)*COLUMNS - (column)));
		sendMemory();
	}
}

void LedMatrix::clearMatrix(void) {
	memory = 0x00000000;
	sendMemory();
}

void LedMatrix::setEntireMatrix(void) {
	memory = 0x3FFFFFFF;
	sendMemory();
}

void LedMatrix::sendMemory(void) {
	int i;

	for(i = 0; i < MATRIX_LENGTH; i++) {
		digitalWrite(SER, 1L & (memory >> i));
		// ## adjust this delay to match with 74HC595 timing
		asm volatile ("nop");
		asm volatile ("nop");
		asm volatile ("nop");
		digitalWrite(CLK, 1);
		// ## adjust this delay to match with 74HC595 timing
		asm volatile ("nop");
		asm volatile ("nop");
		asm volatile ("nop");
		digitalWrite(CLK, 0);
	}

	digitalWrite(RCK, 1);
	// ## adjust this delay to match with 74HC595 timing
	asm volatile ("nop");
	asm volatile ("nop");
	asm volatile ("nop");
	digitalWrite(RCK, 0);
}

<commit_msg>Delete LedMatrix.cpp<commit_after><|endoftext|>


<commit_before>/*
 * Stepper.cpp - Stepper library for Wiring/Arduino - Version 1.1.0
 *
 * Original library        (0.1)   by Tom Igoe.
 * Two-wire modifications  (0.2)   by Sebastian Gassner
 * Combination version     (0.3)   by Tom Igoe and David Mellis
 * Bug fix for four-wire   (0.4)   by Tom Igoe, bug fix from Noah Shibley
 * High-speed stepping mod         by Eugene Kozlenko
 * Timer rollover fix              by Eugene Kozlenko
 * Five phase five wire    (1.1.0) by Ryan Orendorff
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 *
 * Drives a unipolar, bipolar, or five phase stepper motor.
 *
 * When wiring multiple stepper motors to a microcontroller, you quickly run
 * out of output pins, with each motor requiring 4 connections.
 *
 * By making use of the fact that at any time two of the four motor coils are
 * the inverse of the other two, the number of control connections can be
 * reduced from 4 to 2 for the unipolar and bipolar motors.
 *
 * A slightly modified circuit around a Darlington transistor array or an
 * L293 H-bridge connects to only 2 microcontroler pins, inverts the signals
 * received, and delivers the 4 (2 plus 2 inverted ones) output signals
 * required for driving a stepper motor. Similarly the Arduino motor shields
 * 2 direction pins may be used.
 *
 * The sequence of control signals for 5 phase, 5 control wires is as follows:
 *
 * Step C0 C1 C2 C3 C4
 *    1  0  1  1  0  1
 *    2  0  1  0  0  1
 *    3  0  1  0  1  1
 *    4  0  1  0  1  0
 *    5  1  1  0  1  0
 *    6  1  0  0  1  0
 *    7  1  0  1  1  0
 *    8  1  0  1  0  0
 *    9  1  0  1  0  1
 *   10  0  0  1  0  1
 *
 * The sequence of control signals for 4 control wires is as follows:
 *
 * Step C0 C1 C2 C3
 *    1  1  0  1  0
 *    2  0  1  1  0
 *    3  0  1  0  1
 *    4  1  0  0  1
 *
 * The sequence of controls signals for 2 control wires is as follows
 * (columns C1 and C2 from above):
 *
 * Step C0 C1
 *    1  0  1
 *    2  1  1
 *    3  1  0
 *    4  0  0
 *
 * The circuits can be found at
 *
 * http://www.arduino.cc/en/Tutorial/Stepper
 */

#include "Arduino.h"
#include "Stepper.h"

/*
 * two-wire constructor.
 * Sets which wires should control the motor.
 */
Stepper::Stepper(int number_of_steps, int motor_pin_1, int motor_pin_2)
{
  this->step_number = 0;    // which step the motor is on
  this->speed = 0;          // the motor speed, in revolutions per minute
  this->direction = 0;      // motor direction
  this->last_step_time = 0; // time stamp in us of the last step taken
  this->number_of_steps = number_of_steps; // total number of steps for this motor

  // Arduino pins for the motor control connection:
  this->motor_pin_1 = motor_pin_1;
  this->motor_pin_2 = motor_pin_2;

  // setup the pins on the microcontroller:
  pinMode(this->motor_pin_1, OUTPUT);
  pinMode(this->motor_pin_2, OUTPUT);

  // When there are only 2 pins, set the others to 0:
  this->motor_pin_3 = 0;
  this->motor_pin_4 = 0;
  this->motor_pin_5 = 0;

  // pin_count is used by the stepMotor() method:
  this->pin_count = 2;
}

/*
 *   constructor for four-pin version
 *   Sets which wires should control the motor.
 */
Stepper::Stepper(int number_of_steps, int motor_pin_1, int motor_pin_2,
                                      int motor_pin_3, int motor_pin_4)
{
  this->step_number = 0;    // which step the motor is on
  this->speed = 0;          // the motor speed, in revolutions per minute
  this->direction = 0;      // motor direction
  this->last_step_time = 0; // time stamp in us of the last step taken
  this->number_of_steps = number_of_steps; // total number of steps for this motor

  // Arduino pins for the motor control connection:
  this->motor_pin_1 = motor_pin_1;
  this->motor_pin_2 = motor_pin_2;
  this->motor_pin_3 = motor_pin_3;
  this->motor_pin_4 = motor_pin_4;

  // setup the pins on the microcontroller:
  pinMode(this->motor_pin_1, OUTPUT);
  pinMode(this->motor_pin_2, OUTPUT);
  pinMode(this->motor_pin_3, OUTPUT);
  pinMode(this->motor_pin_4, OUTPUT);

  // When there are 4 pins, set the others to 0:
  this->motor_pin_5 = 0;

  // pin_count is used by the stepMotor() method:
  this->pin_count = 4;
}

/*
 *   constructor for five phase motor with five wires
 *   Sets which wires should control the motor.
 */
Stepper::Stepper(int number_of_steps, int motor_pin_1, int motor_pin_2,
                                      int motor_pin_3, int motor_pin_4,
                                      int motor_pin_5)
{
  this->step_number = 0;    // which step the motor is on
  this->speed = 0;          // the motor speed, in revolutions per minute
  this->direction = 0;      // motor direction
  this->last_step_time = 0; // time stamp in us of the last step taken
  this->number_of_steps = number_of_steps; // total number of steps for this motor

  // Arduino pins for the motor control connection:
  this->motor_pin_1 = motor_pin_1;
  this->motor_pin_2 = motor_pin_2;
  this->motor_pin_3 = motor_pin_3;
  this->motor_pin_4 = motor_pin_4;
  this->motor_pin_5 = motor_pin_5;

  // setup the pins on the microcontroller:
  pinMode(this->motor_pin_1, OUTPUT);
  pinMode(this->motor_pin_2, OUTPUT);
  pinMode(this->motor_pin_3, OUTPUT);
  pinMode(this->motor_pin_4, OUTPUT);
  pinMode(this->motor_pin_5, OUTPUT);

  // pin_count is used by the stepMotor() method:
  this->pin_count = 5;
}

/*
 * Sets the speed in revs per minute
 */
void Stepper::setSpeed(long whatSpeed)
{
  this->step_delay = 60L * 1000L * 1000L / this->number_of_steps / whatSpeed;
}

/*
 * Moves the motor steps_to_move steps.  If the number is negative,
 * the motor moves in the reverse direction.
 */
void Stepper::step(int steps_to_move)
{
  int steps_left = abs(steps_to_move);  // how many steps to take

  // determine direction based on whether steps_to_mode is + or -:
  if (steps_to_move > 0) {this->direction = 1;}
  if (steps_to_move < 0) {this->direction = 0;}

  // decrement the number of steps, moving one step each time:
  while(steps_left > 0) {
  // move only if the appropriate delay has passed:
  if (micros() - this->last_step_time >= this->step_delay || micros() < this->last_step_time) {
      // get the timeStamp of when you stepped:
      this->last_step_time = micros();
      // increment or decrement the step number,
      // depending on direction:
      if (this->direction == 1) {
        this->step_number++;
        if (this->step_number == this->number_of_steps) {
          this->step_number = 0;
        }
      }
      else {
        if (this->step_number == 0) {
          this->step_number = this->number_of_steps;
        }
        this->step_number--;
      }
      // decrement the steps left:
      steps_left--;
      // step the motor to step number 0, 1, ..., {3 or 10}
      if (this->pin_count == 5)
        stepMotor(this->step_number % 10);
      else
        stepMotor(this->step_number % 4);
    }
  }
}

/*
 * Moves the motor forward or backwards.
 */
void Stepper::stepMotor(int thisStep)
{
  if (this->pin_count == 2) {
    switch (thisStep) {
      case 0:  // 01
        digitalWrite(motor_pin_1, LOW);
        digitalWrite(motor_pin_2, HIGH);
      break;
      case 1:  // 11
        digitalWrite(motor_pin_1, HIGH);
        digitalWrite(motor_pin_2, HIGH);
      break;
      case 2:  // 10
        digitalWrite(motor_pin_1, HIGH);
        digitalWrite(motor_pin_2, LOW);
      break;
      case 3:  // 00
        digitalWrite(motor_pin_1, LOW);
        digitalWrite(motor_pin_2, LOW);
      break;
    }
  }
  if (this->pin_count == 4) {
    switch (thisStep) {
      case 0:  // 1010
        digitalWrite(motor_pin_1, HIGH);
        digitalWrite(motor_pin_2, LOW);
        digitalWrite(motor_pin_3, HIGH);
        digitalWrite(motor_pin_4, LOW);
      break;
      case 1:  // 0110
        digitalWrite(motor_pin_1, LOW);
        digitalWrite(motor_pin_2, HIGH);
        digitalWrite(motor_pin_3, HIGH);
        digitalWrite(motor_pin_4, LOW);
      break;
      case 2:  //0101
        digitalWrite(motor_pin_1, LOW);
        digitalWrite(motor_pin_2, HIGH);
        digitalWrite(motor_pin_3, LOW);
        digitalWrite(motor_pin_4, HIGH);
      break;
      case 3:  //1001
        digitalWrite(motor_pin_1, HIGH);
        digitalWrite(motor_pin_2, LOW);
        digitalWrite(motor_pin_3, LOW);
        digitalWrite(motor_pin_4, HIGH);
      break;
    }
  }

  if (this->pin_count == 5) {
    switch (thisStep) {
      case 0:  // 01101
        digitalWrite(motor_pin_1, LOW);
        digitalWrite(motor_pin_2, HIGH);
        digitalWrite(motor_pin_3, HIGH);
        digitalWrite(motor_pin_4, LOW);
        digitalWrite(motor_pin_5, HIGH);
        break;
      case 1:  // 01001
        digitalWrite(motor_pin_1, LOW);
        digitalWrite(motor_pin_2, HIGH);
        digitalWrite(motor_pin_3, LOW);
        digitalWrite(motor_pin_4, LOW);
        digitalWrite(motor_pin_5, HIGH);
        break;
      case 2:  // 01011
        digitalWrite(motor_pin_1, LOW);
        digitalWrite(motor_pin_2, HIGH);
        digitalWrite(motor_pin_3, LOW);
        digitalWrite(motor_pin_4, HIGH);
        digitalWrite(motor_pin_5, HIGH);
        break;
      case 3:  // 01010
        digitalWrite(motor_pin_1, LOW);
        digitalWrite(motor_pin_2, HIGH);
        digitalWrite(motor_pin_3, LOW);
        digitalWrite(motor_pin_4, HIGH);
        digitalWrite(motor_pin_5, LOW);
        break;
      case 4:  // 11010
        digitalWrite(motor_pin_1, HIGH);
        digitalWrite(motor_pin_2, HIGH);
        digitalWrite(motor_pin_3, LOW);
        digitalWrite(motor_pin_4, HIGH);
        digitalWrite(motor_pin_5, LOW);
        break;
      case 5:  // 10010
        digitalWrite(motor_pin_1, HIGH);
        digitalWrite(motor_pin_2, LOW);
        digitalWrite(motor_pin_3, LOW);
        digitalWrite(motor_pin_4, HIGH);
        digitalWrite(motor_pin_5, LOW);
        break;
      case 6:  // 10110
        digitalWrite(motor_pin_1, HIGH);
        digitalWrite(motor_pin_2, LOW);
        digitalWrite(motor_pin_3, HIGH);
        digitalWrite(motor_pin_4, HIGH);
        digitalWrite(motor_pin_5, LOW);
        break;
      case 7:  // 10100
        digitalWrite(motor_pin_1, HIGH);
        digitalWrite(motor_pin_2, LOW);
        digitalWrite(motor_pin_3, HIGH);
        digitalWrite(motor_pin_4, LOW);
        digitalWrite(motor_pin_5, LOW);
        break;
      case 8:  // 10101
        digitalWrite(motor_pin_1, HIGH);
        digitalWrite(motor_pin_2, LOW);
        digitalWrite(motor_pin_3, HIGH);
        digitalWrite(motor_pin_4, LOW);
        digitalWrite(motor_pin_5, HIGH);
        break;
      case 9:  // 00101
        digitalWrite(motor_pin_1, LOW);
        digitalWrite(motor_pin_2, LOW);
        digitalWrite(motor_pin_3, HIGH);
        digitalWrite(motor_pin_4, LOW);
        digitalWrite(motor_pin_5, HIGH);
        break;
    }
  }
}

/*
  version() returns the version of the library:
*/
int Stepper::version(void)
{
  return 5;
}
<commit_msg>Stepper: optimization on timing calculations<commit_after>/*
 * Stepper.cpp - Stepper library for Wiring/Arduino - Version 1.1.0
 *
 * Original library        (0.1)   by Tom Igoe.
 * Two-wire modifications  (0.2)   by Sebastian Gassner
 * Combination version     (0.3)   by Tom Igoe and David Mellis
 * Bug fix for four-wire   (0.4)   by Tom Igoe, bug fix from Noah Shibley
 * High-speed stepping mod         by Eugene Kozlenko
 * Timer rollover fix              by Eugene Kozlenko
 * Five phase five wire    (1.1.0) by Ryan Orendorff
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 *
 * Drives a unipolar, bipolar, or five phase stepper motor.
 *
 * When wiring multiple stepper motors to a microcontroller, you quickly run
 * out of output pins, with each motor requiring 4 connections.
 *
 * By making use of the fact that at any time two of the four motor coils are
 * the inverse of the other two, the number of control connections can be
 * reduced from 4 to 2 for the unipolar and bipolar motors.
 *
 * A slightly modified circuit around a Darlington transistor array or an
 * L293 H-bridge connects to only 2 microcontroler pins, inverts the signals
 * received, and delivers the 4 (2 plus 2 inverted ones) output signals
 * required for driving a stepper motor. Similarly the Arduino motor shields
 * 2 direction pins may be used.
 *
 * The sequence of control signals for 5 phase, 5 control wires is as follows:
 *
 * Step C0 C1 C2 C3 C4
 *    1  0  1  1  0  1
 *    2  0  1  0  0  1
 *    3  0  1  0  1  1
 *    4  0  1  0  1  0
 *    5  1  1  0  1  0
 *    6  1  0  0  1  0
 *    7  1  0  1  1  0
 *    8  1  0  1  0  0
 *    9  1  0  1  0  1
 *   10  0  0  1  0  1
 *
 * The sequence of control signals for 4 control wires is as follows:
 *
 * Step C0 C1 C2 C3
 *    1  1  0  1  0
 *    2  0  1  1  0
 *    3  0  1  0  1
 *    4  1  0  0  1
 *
 * The sequence of controls signals for 2 control wires is as follows
 * (columns C1 and C2 from above):
 *
 * Step C0 C1
 *    1  0  1
 *    2  1  1
 *    3  1  0
 *    4  0  0
 *
 * The circuits can be found at
 *
 * http://www.arduino.cc/en/Tutorial/Stepper
 */

#include "Arduino.h"
#include "Stepper.h"

/*
 * two-wire constructor.
 * Sets which wires should control the motor.
 */
Stepper::Stepper(int number_of_steps, int motor_pin_1, int motor_pin_2)
{
  this->step_number = 0;    // which step the motor is on
  this->speed = 0;          // the motor speed, in revolutions per minute
  this->direction = 0;      // motor direction
  this->last_step_time = 0; // time stamp in us of the last step taken
  this->number_of_steps = number_of_steps; // total number of steps for this motor

  // Arduino pins for the motor control connection:
  this->motor_pin_1 = motor_pin_1;
  this->motor_pin_2 = motor_pin_2;

  // setup the pins on the microcontroller:
  pinMode(this->motor_pin_1, OUTPUT);
  pinMode(this->motor_pin_2, OUTPUT);

  // When there are only 2 pins, set the others to 0:
  this->motor_pin_3 = 0;
  this->motor_pin_4 = 0;
  this->motor_pin_5 = 0;

  // pin_count is used by the stepMotor() method:
  this->pin_count = 2;
}

/*
 *   constructor for four-pin version
 *   Sets which wires should control the motor.
 */
Stepper::Stepper(int number_of_steps, int motor_pin_1, int motor_pin_2,
                                      int motor_pin_3, int motor_pin_4)
{
  this->step_number = 0;    // which step the motor is on
  this->speed = 0;          // the motor speed, in revolutions per minute
  this->direction = 0;      // motor direction
  this->last_step_time = 0; // time stamp in us of the last step taken
  this->number_of_steps = number_of_steps; // total number of steps for this motor

  // Arduino pins for the motor control connection:
  this->motor_pin_1 = motor_pin_1;
  this->motor_pin_2 = motor_pin_2;
  this->motor_pin_3 = motor_pin_3;
  this->motor_pin_4 = motor_pin_4;

  // setup the pins on the microcontroller:
  pinMode(this->motor_pin_1, OUTPUT);
  pinMode(this->motor_pin_2, OUTPUT);
  pinMode(this->motor_pin_3, OUTPUT);
  pinMode(this->motor_pin_4, OUTPUT);

  // When there are 4 pins, set the others to 0:
  this->motor_pin_5 = 0;

  // pin_count is used by the stepMotor() method:
  this->pin_count = 4;
}

/*
 *   constructor for five phase motor with five wires
 *   Sets which wires should control the motor.
 */
Stepper::Stepper(int number_of_steps, int motor_pin_1, int motor_pin_2,
                                      int motor_pin_3, int motor_pin_4,
                                      int motor_pin_5)
{
  this->step_number = 0;    // which step the motor is on
  this->speed = 0;          // the motor speed, in revolutions per minute
  this->direction = 0;      // motor direction
  this->last_step_time = 0; // time stamp in us of the last step taken
  this->number_of_steps = number_of_steps; // total number of steps for this motor

  // Arduino pins for the motor control connection:
  this->motor_pin_1 = motor_pin_1;
  this->motor_pin_2 = motor_pin_2;
  this->motor_pin_3 = motor_pin_3;
  this->motor_pin_4 = motor_pin_4;
  this->motor_pin_5 = motor_pin_5;

  // setup the pins on the microcontroller:
  pinMode(this->motor_pin_1, OUTPUT);
  pinMode(this->motor_pin_2, OUTPUT);
  pinMode(this->motor_pin_3, OUTPUT);
  pinMode(this->motor_pin_4, OUTPUT);
  pinMode(this->motor_pin_5, OUTPUT);

  // pin_count is used by the stepMotor() method:
  this->pin_count = 5;
}

/*
 * Sets the speed in revs per minute
 */
void Stepper::setSpeed(long whatSpeed)
{
  this->step_delay = 60L * 1000L * 1000L / this->number_of_steps / whatSpeed;
}

/*
 * Moves the motor steps_to_move steps.  If the number is negative,
 * the motor moves in the reverse direction.
 */
void Stepper::step(int steps_to_move)
{
  int steps_left = abs(steps_to_move);  // how many steps to take

  // determine direction based on whether steps_to_mode is + or -:
  if (steps_to_move > 0) {this->direction = 1;}
  if (steps_to_move < 0) {this->direction = 0;}

  // decrement the number of steps, moving one step each time:
  while(steps_left > 0) {
  unsigned long now = micros();
  // move only if the appropriate delay has passed:
  if (now - this->last_step_time >= this->step_delay) {
      // get the timeStamp of when you stepped:
      this->last_step_time = now;
      // increment or decrement the step number,
      // depending on direction:
      if (this->direction == 1) {
        this->step_number++;
        if (this->step_number == this->number_of_steps) {
          this->step_number = 0;
        }
      }
      else {
        if (this->step_number == 0) {
          this->step_number = this->number_of_steps;
        }
        this->step_number--;
      }
      // decrement the steps left:
      steps_left--;
      // step the motor to step number 0, 1, ..., {3 or 10}
      if (this->pin_count == 5)
        stepMotor(this->step_number % 10);
      else
        stepMotor(this->step_number % 4);
    }
  }
}

/*
 * Moves the motor forward or backwards.
 */
void Stepper::stepMotor(int thisStep)
{
  if (this->pin_count == 2) {
    switch (thisStep) {
      case 0:  // 01
        digitalWrite(motor_pin_1, LOW);
        digitalWrite(motor_pin_2, HIGH);
      break;
      case 1:  // 11
        digitalWrite(motor_pin_1, HIGH);
        digitalWrite(motor_pin_2, HIGH);
      break;
      case 2:  // 10
        digitalWrite(motor_pin_1, HIGH);
        digitalWrite(motor_pin_2, LOW);
      break;
      case 3:  // 00
        digitalWrite(motor_pin_1, LOW);
        digitalWrite(motor_pin_2, LOW);
      break;
    }
  }
  if (this->pin_count == 4) {
    switch (thisStep) {
      case 0:  // 1010
        digitalWrite(motor_pin_1, HIGH);
        digitalWrite(motor_pin_2, LOW);
        digitalWrite(motor_pin_3, HIGH);
        digitalWrite(motor_pin_4, LOW);
      break;
      case 1:  // 0110
        digitalWrite(motor_pin_1, LOW);
        digitalWrite(motor_pin_2, HIGH);
        digitalWrite(motor_pin_3, HIGH);
        digitalWrite(motor_pin_4, LOW);
      break;
      case 2:  //0101
        digitalWrite(motor_pin_1, LOW);
        digitalWrite(motor_pin_2, HIGH);
        digitalWrite(motor_pin_3, LOW);
        digitalWrite(motor_pin_4, HIGH);
      break;
      case 3:  //1001
        digitalWrite(motor_pin_1, HIGH);
        digitalWrite(motor_pin_2, LOW);
        digitalWrite(motor_pin_3, LOW);
        digitalWrite(motor_pin_4, HIGH);
      break;
    }
  }

  if (this->pin_count == 5) {
    switch (thisStep) {
      case 0:  // 01101
        digitalWrite(motor_pin_1, LOW);
        digitalWrite(motor_pin_2, HIGH);
        digitalWrite(motor_pin_3, HIGH);
        digitalWrite(motor_pin_4, LOW);
        digitalWrite(motor_pin_5, HIGH);
        break;
      case 1:  // 01001
        digitalWrite(motor_pin_1, LOW);
        digitalWrite(motor_pin_2, HIGH);
        digitalWrite(motor_pin_3, LOW);
        digitalWrite(motor_pin_4, LOW);
        digitalWrite(motor_pin_5, HIGH);
        break;
      case 2:  // 01011
        digitalWrite(motor_pin_1, LOW);
        digitalWrite(motor_pin_2, HIGH);
        digitalWrite(motor_pin_3, LOW);
        digitalWrite(motor_pin_4, HIGH);
        digitalWrite(motor_pin_5, HIGH);
        break;
      case 3:  // 01010
        digitalWrite(motor_pin_1, LOW);
        digitalWrite(motor_pin_2, HIGH);
        digitalWrite(motor_pin_3, LOW);
        digitalWrite(motor_pin_4, HIGH);
        digitalWrite(motor_pin_5, LOW);
        break;
      case 4:  // 11010
        digitalWrite(motor_pin_1, HIGH);
        digitalWrite(motor_pin_2, HIGH);
        digitalWrite(motor_pin_3, LOW);
        digitalWrite(motor_pin_4, HIGH);
        digitalWrite(motor_pin_5, LOW);
        break;
      case 5:  // 10010
        digitalWrite(motor_pin_1, HIGH);
        digitalWrite(motor_pin_2, LOW);
        digitalWrite(motor_pin_3, LOW);
        digitalWrite(motor_pin_4, HIGH);
        digitalWrite(motor_pin_5, LOW);
        break;
      case 6:  // 10110
        digitalWrite(motor_pin_1, HIGH);
        digitalWrite(motor_pin_2, LOW);
        digitalWrite(motor_pin_3, HIGH);
        digitalWrite(motor_pin_4, HIGH);
        digitalWrite(motor_pin_5, LOW);
        break;
      case 7:  // 10100
        digitalWrite(motor_pin_1, HIGH);
        digitalWrite(motor_pin_2, LOW);
        digitalWrite(motor_pin_3, HIGH);
        digitalWrite(motor_pin_4, LOW);
        digitalWrite(motor_pin_5, LOW);
        break;
      case 8:  // 10101
        digitalWrite(motor_pin_1, HIGH);
        digitalWrite(motor_pin_2, LOW);
        digitalWrite(motor_pin_3, HIGH);
        digitalWrite(motor_pin_4, LOW);
        digitalWrite(motor_pin_5, HIGH);
        break;
      case 9:  // 00101
        digitalWrite(motor_pin_1, LOW);
        digitalWrite(motor_pin_2, LOW);
        digitalWrite(motor_pin_3, HIGH);
        digitalWrite(motor_pin_4, LOW);
        digitalWrite(motor_pin_5, HIGH);
        break;
    }
  }
}

/*
  version() returns the version of the library:
*/
int Stepper::version(void)
{
  return 5;
}
<|endoftext|>


<commit_before>#include <string.h>
#include <windows.h>
#include <shellapi.h>
#include "../Config.h"
#include "resource.h"
#include "Win32App.h"
#include <stdio.h>

#if defined(_MSC_VER) && _MSC_VER < 1900
#define snprintf _snprintf
#endif

#define ID_ABOUT 2000
#define ID_EXIT 2001
#define ID_CONSOLE 2002
#define ID_APP 2003

#define ID_TRAY_ICON 2050
#define WM_TRAYICON (WM_USER + 1)

namespace i2p
{
namespace win32
{
    static void ShowPopupMenu (HWND hWnd, POINT *curpos, int wDefaultItem)
    {
        HMENU hPopup = CreatePopupMenu();
        InsertMenu (hPopup, -1, MF_BYPOSITION | MF_STRING, ID_CONSOLE, "Open &console");
        InsertMenu (hPopup, -1, MF_BYPOSITION | MF_STRING, ID_APP, "Show app");
        InsertMenu (hPopup, -1, MF_BYPOSITION | MF_STRING, ID_ABOUT, "&About...");
        InsertMenu (hPopup, -1, MF_BYPOSITION | MF_SEPARATOR, NULL, NULL);
        InsertMenu (hPopup, -1, MF_BYPOSITION | MF_STRING, ID_EXIT, "E&xit");
        SetMenuDefaultItem (hPopup, ID_CONSOLE, FALSE);
        SendMessage (hWnd, WM_INITMENUPOPUP, (WPARAM)hPopup, 0);

        POINT p;
        if (!curpos)
        {
            GetCursorPos (&p);
            curpos = &p;
        }

        WORD cmd = TrackPopupMenu (hPopup, TPM_LEFTALIGN | TPM_RIGHTBUTTON | TPM_RETURNCMD | TPM_NONOTIFY, curpos->x, curpos->y, 0, hWnd, NULL);
        SendMessage (hWnd, WM_COMMAND, cmd, 0);

        DestroyMenu(hPopup);
    }

    static void AddTrayIcon (HWND hWnd)
    {
        NOTIFYICONDATA nid;
        memset(&nid, 0, sizeof(nid));
        nid.cbSize = sizeof(nid);
        nid.hWnd = hWnd;
        nid.uID = ID_TRAY_ICON;
        nid.uFlags = NIF_ICON | NIF_MESSAGE | NIF_TIP | NIF_INFO;
        nid.uCallbackMessage = WM_TRAYICON;
        nid.hIcon = LoadIcon (GetModuleHandle(NULL), MAKEINTRESOURCE (MAINICON));
        strcpy (nid.szTip, "i2pd");
        strcpy (nid.szInfo, "i2pd is running");
        Shell_NotifyIcon(NIM_ADD, &nid );
    }

    static void RemoveTrayIcon (HWND hWnd)
    {
        NOTIFYICONDATA nid;
        nid.hWnd = hWnd;
        nid.uID = ID_TRAY_ICON;
        Shell_NotifyIcon (NIM_DELETE, &nid);
    }

    static LRESULT CALLBACK WndProc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
    {
        switch (uMsg)
        {
            case WM_CREATE:
            {
                AddTrayIcon (hWnd);
                break;
            }
            case WM_CLOSE:
            {
                RemoveTrayIcon (hWnd);
                PostQuitMessage (0);
                break;
            }
            case WM_COMMAND:
            {
                switch (LOWORD(wParam))
                {
                    case ID_ABOUT:
                    {
                        MessageBox( hWnd, TEXT("i2pd"), TEXT("About"), MB_ICONINFORMATION | MB_OK );
                        return 0;
                    }
                    case ID_EXIT:
                    {
                        PostMessage (hWnd, WM_CLOSE, 0, 0);
                        return 0;
                    }
                    case ID_CONSOLE:
                    {
                        char buf[30];
                        std::string httpAddr; i2p::config::GetOption("http.address", httpAddr);
                        uint16_t    httpPort; i2p::config::GetOption("http.port", httpPort);
                        snprintf(buf, 30, "http://%s:%d", httpAddr.c_str(), httpPort);
                        ShellExecute(NULL, "open", buf, NULL, NULL, SW_SHOWNORMAL);
                        return 0;
                    }
                    case ID_APP:
                    {
                        ShowWindow(hWnd, SW_SHOW);
                        return 0;
                    }
                }
                break;
            }
            case WM_SYSCOMMAND:
            {
                switch (wParam)
                {
                    case SC_MINIMIZE:
                    {
                        ShowWindow(hWnd, SW_HIDE);
                        return 0;
                    }
                    case SC_CLOSE:
                    {
                        std::string close; i2p::config::GetOption("close", close);
                        if (0 == close.compare("ask"))
                            switch(::MessageBox(hWnd, "Would you like to minimize instead of exiting?"
                                " You can add 'close' configuration option. Valid values are: ask, minimize, exit.",
                                "Minimize instead of exiting?", MB_ICONQUESTION | MB_YESNOCANCEL | MB_DEFBUTTON1))
                            {
                                case IDYES: close = "minimize"; break;
                                case IDNO: close = "exit"; break;
                                default: return 0;
                            }
                        if (0 == close.compare("minimize"))
                        {
                            ShowWindow(hWnd, SW_HIDE);
                            return 0;
                        }
                        if (0 != close.compare("exit"))
                        {
                            ::MessageBox(hWnd, close.c_str(), "Unknown close action in config", MB_OK | MB_ICONWARNING);
                            return 0;
                        }
                    }
                }
            }
            case WM_TRAYICON:
            {
                switch (lParam)
                {
                    case WM_LBUTTONUP:
                    case WM_RBUTTONUP:
                    {
                        SetForegroundWindow (hWnd);
                        ShowPopupMenu(hWnd, NULL, -1);
                        PostMessage (hWnd, WM_APP + 1, 0, 0);
                        break;
                    }
                }
                break;
            }
		 case WM_PAINT:
		 {
			PAINTSTRUCT ps;
			auto hDC = BeginPaint (hWnd, &ps);
			auto mascot = LoadBitmap (GetModuleHandle(NULL), MAKEINTRESOURCE (MASCOT));
			auto mascotDC = CreateCompatibleDC (hDC);
			SelectObject (mascotDC, mascot);
			BitBlt (hDC, 0,0, 533, 700, mascotDC, 0, 0, SRCCOPY);
			DeleteDC (mascotDC);
			DeleteObject (mascot);
			EndPaint (hWnd, &ps);
			break;
		 }
        }
        return DefWindowProc( hWnd, uMsg, wParam, lParam);
    }

    bool StartWin32App ()
    {
        if (FindWindow (I2PD_WIN32_CLASSNAME, TEXT("i2pd")))
        {
            MessageBox(NULL, TEXT("I2Pd is running already"), TEXT("Warning"), MB_OK);
            return false;
        }
        // register main window
        auto hInst = GetModuleHandle(NULL);
        WNDCLASSEX wclx;
        memset (&wclx, 0, sizeof(wclx));
        wclx.cbSize = sizeof(wclx);
        wclx.style = 0;
        wclx.lpfnWndProc = WndProc;
        wclx.cbClsExtra = 0;
        wclx.cbWndExtra = 0;
        wclx.hInstance = hInst;
        wclx.hIcon = LoadIcon (hInst, MAKEINTRESOURCE(MAINICON));
        wclx.hCursor = LoadCursor (NULL, IDC_ARROW);
        wclx.hbrBackground = (HBRUSH)(COLOR_BTNFACE + 1);
        wclx.lpszMenuName = NULL;
        wclx.lpszClassName = I2PD_WIN32_CLASSNAME;
        RegisterClassEx (&wclx);
        // create new window
        if (!CreateWindow(I2PD_WIN32_CLASSNAME, TEXT("i2pd"), WS_OVERLAPPEDWINDOW, 100, 100, 549, 738, NULL, NULL, hInst, NULL))
        {
            MessageBox(NULL, "Failed to create main window", TEXT("Warning!"), MB_ICONERROR | MB_OK | MB_TOPMOST);
            return false;
        }
        return true;
    }

    int RunWin32App ()
    {
        MSG msg;
        while (GetMessage (&msg, NULL, 0, 0 ))
        {
            TranslateMessage (&msg);
            DispatchMessage (&msg);
        }
        return msg.wParam;
    }

    void StopWin32App ()
    {
         UnregisterClass (I2PD_WIN32_CLASSNAME, GetModuleHandle(NULL));
    }
}
}
<commit_msg>show version in the 'About' window<commit_after>#include <string.h>
#include <windows.h>
#include <shellapi.h>
#include "../Config.h"
#include "../version.h"
#include "resource.h"
#include "Win32App.h"
#include <stdio.h>

#if defined(_MSC_VER) && _MSC_VER < 1900
#define snprintf _snprintf
#endif

#define ID_ABOUT 2000
#define ID_EXIT 2001
#define ID_CONSOLE 2002
#define ID_APP 2003

#define ID_TRAY_ICON 2050
#define WM_TRAYICON (WM_USER + 1)

namespace i2p
{
namespace win32
{
    static void ShowPopupMenu (HWND hWnd, POINT *curpos, int wDefaultItem)
    {
        HMENU hPopup = CreatePopupMenu();
        InsertMenu (hPopup, -1, MF_BYPOSITION | MF_STRING, ID_CONSOLE, "Open &console");
        InsertMenu (hPopup, -1, MF_BYPOSITION | MF_STRING, ID_APP, "Show app");
        InsertMenu (hPopup, -1, MF_BYPOSITION | MF_STRING, ID_ABOUT, "&About...");
        InsertMenu (hPopup, -1, MF_BYPOSITION | MF_SEPARATOR, NULL, NULL);
        InsertMenu (hPopup, -1, MF_BYPOSITION | MF_STRING, ID_EXIT, "E&xit");
        SetMenuDefaultItem (hPopup, ID_CONSOLE, FALSE);
        SendMessage (hWnd, WM_INITMENUPOPUP, (WPARAM)hPopup, 0);

        POINT p;
        if (!curpos)
        {
            GetCursorPos (&p);
            curpos = &p;
        }

        WORD cmd = TrackPopupMenu (hPopup, TPM_LEFTALIGN | TPM_RIGHTBUTTON | TPM_RETURNCMD | TPM_NONOTIFY, curpos->x, curpos->y, 0, hWnd, NULL);
        SendMessage (hWnd, WM_COMMAND, cmd, 0);

        DestroyMenu(hPopup);
    }

    static void AddTrayIcon (HWND hWnd)
    {
        NOTIFYICONDATA nid;
        memset(&nid, 0, sizeof(nid));
        nid.cbSize = sizeof(nid);
        nid.hWnd = hWnd;
        nid.uID = ID_TRAY_ICON;
        nid.uFlags = NIF_ICON | NIF_MESSAGE | NIF_TIP | NIF_INFO;
        nid.uCallbackMessage = WM_TRAYICON;
        nid.hIcon = LoadIcon (GetModuleHandle(NULL), MAKEINTRESOURCE (MAINICON));
        strcpy (nid.szTip, "i2pd");
        strcpy (nid.szInfo, "i2pd is running");
        Shell_NotifyIcon(NIM_ADD, &nid );
    }

    static void RemoveTrayIcon (HWND hWnd)
    {
        NOTIFYICONDATA nid;
        nid.hWnd = hWnd;
        nid.uID = ID_TRAY_ICON;
        Shell_NotifyIcon (NIM_DELETE, &nid);
    }

    static LRESULT CALLBACK WndProc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
    {
        switch (uMsg)
        {
            case WM_CREATE:
            {
                AddTrayIcon (hWnd);
                break;
            }
            case WM_CLOSE:
            {
                RemoveTrayIcon (hWnd);
                PostQuitMessage (0);
                break;
            }
            case WM_COMMAND:
            {
                switch (LOWORD(wParam))
                {
                    case ID_ABOUT:
                    {
                        std::stringstream text;
                        text << "Version: " << I2PD_VERSION << " " << CODENAME;
                        MessageBox( hWnd, TEXT(text.str ().c_str ()), TEXT("i2pd"), MB_ICONINFORMATION | MB_OK );
                        return 0;
                    }
                    case ID_EXIT:
                    {
                        PostMessage (hWnd, WM_CLOSE, 0, 0);
                        return 0;
                    }
                    case ID_CONSOLE:
                    {
                        char buf[30];
                        std::string httpAddr; i2p::config::GetOption("http.address", httpAddr);
                        uint16_t    httpPort; i2p::config::GetOption("http.port", httpPort);
                        snprintf(buf, 30, "http://%s:%d", httpAddr.c_str(), httpPort);
                        ShellExecute(NULL, "open", buf, NULL, NULL, SW_SHOWNORMAL);
                        return 0;
                    }
                    case ID_APP:
                    {
                        ShowWindow(hWnd, SW_SHOW);
                        return 0;
                    }
                }
                break;
            }
            case WM_SYSCOMMAND:
            {
                switch (wParam)
                {
                    case SC_MINIMIZE:
                    {
                        ShowWindow(hWnd, SW_HIDE);
                        return 0;
                    }
                    case SC_CLOSE:
                    {
                        std::string close; i2p::config::GetOption("close", close);
                        if (0 == close.compare("ask"))
                            switch(::MessageBox(hWnd, "Would you like to minimize instead of exiting?"
                                " You can add 'close' configuration option. Valid values are: ask, minimize, exit.",
                                "Minimize instead of exiting?", MB_ICONQUESTION | MB_YESNOCANCEL | MB_DEFBUTTON1))
                            {
                                case IDYES: close = "minimize"; break;
                                case IDNO: close = "exit"; break;
                                default: return 0;
                            }
                        if (0 == close.compare("minimize"))
                        {
                            ShowWindow(hWnd, SW_HIDE);
                            return 0;
                        }
                        if (0 != close.compare("exit"))
                        {
                            ::MessageBox(hWnd, close.c_str(), "Unknown close action in config", MB_OK | MB_ICONWARNING);
                            return 0;
                        }
                    }
                }
            }
            case WM_TRAYICON:
            {
                switch (lParam)
                {
                    case WM_LBUTTONUP:
                    case WM_RBUTTONUP:
                    {
                        SetForegroundWindow (hWnd);
                        ShowPopupMenu(hWnd, NULL, -1);
                        PostMessage (hWnd, WM_APP + 1, 0, 0);
                        break;
                    }
                }
                break;
            }
		 case WM_PAINT:
		 {
			PAINTSTRUCT ps;
			auto hDC = BeginPaint (hWnd, &ps);
			auto mascot = LoadBitmap (GetModuleHandle(NULL), MAKEINTRESOURCE (MASCOT));
			auto mascotDC = CreateCompatibleDC (hDC);
			SelectObject (mascotDC, mascot);
			BitBlt (hDC, 0,0, 533, 700, mascotDC, 0, 0, SRCCOPY);
			DeleteDC (mascotDC);
			DeleteObject (mascot);
			EndPaint (hWnd, &ps);
			break;
		 }
        }
        return DefWindowProc( hWnd, uMsg, wParam, lParam);
    }

    bool StartWin32App ()
    {
        if (FindWindow (I2PD_WIN32_CLASSNAME, TEXT("i2pd")))
        {
            MessageBox(NULL, TEXT("I2Pd is running already"), TEXT("Warning"), MB_OK);
            return false;
        }
        // register main window
        auto hInst = GetModuleHandle(NULL);
        WNDCLASSEX wclx;
        memset (&wclx, 0, sizeof(wclx));
        wclx.cbSize = sizeof(wclx);
        wclx.style = 0;
        wclx.lpfnWndProc = WndProc;
        wclx.cbClsExtra = 0;
        wclx.cbWndExtra = 0;
        wclx.hInstance = hInst;
        wclx.hIcon = LoadIcon (hInst, MAKEINTRESOURCE(MAINICON));
        wclx.hCursor = LoadCursor (NULL, IDC_ARROW);
        wclx.hbrBackground = (HBRUSH)(COLOR_BTNFACE + 1);
        wclx.lpszMenuName = NULL;
        wclx.lpszClassName = I2PD_WIN32_CLASSNAME;
        RegisterClassEx (&wclx);
        // create new window
        if (!CreateWindow(I2PD_WIN32_CLASSNAME, TEXT("i2pd"), WS_OVERLAPPEDWINDOW, 100, 100, 549, 738, NULL, NULL, hInst, NULL))
        {
            MessageBox(NULL, "Failed to create main window", TEXT("Warning!"), MB_ICONERROR | MB_OK | MB_TOPMOST);
            return false;
        }
        return true;
    }

    int RunWin32App ()
    {
        MSG msg;
        while (GetMessage (&msg, NULL, 0, 0 ))
        {
            TranslateMessage (&msg);
            DispatchMessage (&msg);
        }
        return msg.wParam;
    }

    void StopWin32App ()
    {
         UnregisterClass (I2PD_WIN32_CLASSNAME, GetModuleHandle(NULL));
    }
}
}
<|endoftext|>


<commit_before>#include <iostream>
#include <cstdio>
#include <cmath>
#include <string>
#include <unordered_map>

using namespace std;

long long get_factor(long long x) {
  for (long long j = 2; j < sqrt(x); j++) {
    if (x % j == 0) {
      return j;
    }
  }

  return -1;
}

int main() {
  unordered_map<long long, long long> factors;

  int n_cases;
  cin >> n_cases;

  for (int i_case = 0; i_case < n_cases; i_case++) {
    printf("Case #%d:\n", i_case + 1);

    int n, count;
    cin >> n >> count;

    long long pows[10 - 2 + 1][n];
    for (int j = 2; j <= 10; j++) {
      long long temp_pow = 1;

      for (int k = 0; k < n; k++) {
        pows[j - 2][k] = temp_pow;
        temp_pow *= j;
      }
    }

    for (long long i = 0; i < (int)pow(2, n - 2); i++){
      // Get binary representation
      bool digits[n];
      digits[0] = true;
      digits[n - 1] = true;
      for (int j = 0; j < n - 2; j++) { digits[j + 1] = false; }

      long long temp = i;
      int temp_index = 1;
      while (temp > 0) {
        digits[temp_index] = (temp % 2 == 1);
        temp /= 2;
        temp_index++;
      }

      // Check 2->10
      long long ans[10 - 2 + 1];
      bool works = true;
      for (int j = 2; j <= 10; j++) {
        long long total = 0;
        for (int k = 0; k < n; k++) {
          if (digits[k]) { total += pows[j - 2][k]; }
        }

        if (factors.find(total) == factors.end()) {
          factors[total] = get_factor(total);
        }

        if (factors.at(total) == -1) {
          works = false;
          break;
        }

        ans[j - 2] = factors.at(total);
      }

      if (works) {
        count--;

        for (int j = n - 1; j >= 0; j--) {
          cout << (digits[j] ? '1' : '0');
        }

        for (int j = 2; j <= 10; j++) {
          cout << " " << ans[j - 2];
        }
        cout << endl;
      }

      if (count == 0) { break; }
    }
  }

  return 0;
}
<commit_msg>Update 2016-C<commit_after>#include <iostream>
#include <cstdio>
#include <cmath>
#include <string>
#include <unordered_map>

using namespace std;

#define MAX_TRY 10000000

unsigned long long get_factor(unsigned long long x) {
  for (unsigned long long j = 2; j < sqrt(x); j++) {
    if (x % j == 0) { return j; }
    if (j > MAX_TRY) { return -1; }
  }

  return -1;
}

int main() {
  unordered_map<unsigned long long, unsigned long long> factors;

  int n_cases;
  cin >> n_cases;

  for (int i_case = 0; i_case < n_cases; i_case++) {
    printf("Case #%d:\n", i_case + 1);

    int n, count;
    cin >> n >> count;

    unsigned long long pows[10 - 2 + 1][n];
    for (int j = 2; j <= 10; j++) {
      unsigned long long temp_pow = 1;

      for (int k = 0; k < n; k++) {
        pows[j - 2][k] = temp_pow;
        temp_pow *= j;
      }
    }

    for (unsigned long long i = 0; i < (int)pow(2, n - 2); i++){
      // cout << "********** NEW NUM **************" << endl;
      // Get binary representation
      bool digits[n];
      digits[0] = true;
      digits[n - 1] = true;
      for (int j = 0; j < n - 2; j++) { digits[j + 1] = false; }

      unsigned long long temp = i;
      int temp_index = 1;
      while (temp > 0) {
        digits[temp_index] = (temp % 2 == 1);
        temp /= 2;
        temp_index++;
      }

      // Check 2->10
      unsigned long long ans[10 - 2 + 1];
      bool works = true;
      for (int j = 2; j <= 10; j++) {
        unsigned long long total = 0;
        for (int k = 0; k < n; k++) {
          if (digits[k]) { total += pows[j - 2][k]; }
        }
        // cout << "  trying base " << j << " and TOTAL " << total << endl;

        if (factors.find(total) == factors.end()) {
          factors[total] = get_factor(total);
        }

        if (factors.at(total) == -1) {
          works = false;
          break;
        }

        ans[j - 2] = factors.at(total);
      }

      if (works) {
        count--;

        for (int j = n - 1; j >= 0; j--) {
          cout << (digits[j] ? '1' : '0');
        }

        for (int j = 2; j <= 10; j++) {
          cout << " " << ans[j - 2];
        }
        cout << endl;
      }

      if (count == 0) { break; }
    }
  }

  return 0;
}
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: ConfigurationAccess.cxx,v $
 *
 *  $Revision: 1.2 $
 *
 *  last change: $Author: rt $ $Date: 2005-09-08 00:34:21 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

#include "ConfigurationAccess.hxx"
#include "macros.hxx"

// header for class SvtSysLocale
#ifndef INCLUDED_SVTOOLS_SYSLOCALE_HXX
#include <svtools/syslocale.hxx>
#endif
// header for class ConfigItem
#ifndef _UTL_CONFIGITEM_HXX_
#include <unotools/configitem.hxx>
#endif

//.............................................................................
namespace chart
{
//.............................................................................
using namespace ::com::sun::star;

namespace
{
bool lcl_IsMetric()
{
    SvtSysLocale aSysLocale;
    const LocaleDataWrapper* pLocWrapper = aSysLocale.GetLocaleDataPtr();
    MeasurementSystem eSys = pLocWrapper->getMeasurementSystemEnum();

    return ( eSys == MEASURE_METRIC );
}
}//end anonymous namespace

class CalcConfigItem : public ::utl::ConfigItem
{
public:
    CalcConfigItem();
    virtual ~CalcConfigItem();

    FieldUnit getFieldUnit();
};

CalcConfigItem::CalcConfigItem()
    : ConfigItem( ::rtl::OUString( C2U( "Office.Calc/Layout" )))
{
}
CalcConfigItem::~CalcConfigItem()
{
}

FieldUnit CalcConfigItem::getFieldUnit()
{
    FieldUnit eResult( FUNIT_CM );

    uno::Sequence< ::rtl::OUString > aNames( 1 );
    if( lcl_IsMetric() )
        aNames[ 0 ] = ::rtl::OUString( C2U( "Other/MeasureUnit/Metric" ));
    else
        aNames[ 0 ] = ::rtl::OUString( C2U( "Other/MeasureUnit/NonMetric" ));

    uno::Sequence< uno::Any > aResult( GetProperties( aNames ));
    sal_Int32 nValue;
    if( aResult[ 0 ] >>= nValue )
        eResult = static_cast< FieldUnit >( nValue );

    return eResult;
}

ConfigurationAccess::ConfigurationAccess()
    : m_pCalcConfigItem(0)
{
    m_pCalcConfigItem = new CalcConfigItem();
}
ConfigurationAccess::~ConfigurationAccess()
{
    delete m_pCalcConfigItem;
}
FieldUnit ConfigurationAccess::getFieldUnit()
{
    FieldUnit aUnit( m_pCalcConfigItem->getFieldUnit() );
    return aUnit;
}

//.............................................................................
} //namespace chart
//.............................................................................
<commit_msg>INTEGRATION: CWS pchfix02 (1.2.82); FILE MERGED 2006/09/01 17:18:40 kaib 1.2.82.1: #i68856# Added header markers and pch files<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: ConfigurationAccess.cxx,v $
 *
 *  $Revision: 1.3 $
 *
 *  last change: $Author: obo $ $Date: 2006-09-17 13:06:36 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_chart2.hxx"

#include "ConfigurationAccess.hxx"
#include "macros.hxx"

// header for class SvtSysLocale
#ifndef INCLUDED_SVTOOLS_SYSLOCALE_HXX
#include <svtools/syslocale.hxx>
#endif
// header for class ConfigItem
#ifndef _UTL_CONFIGITEM_HXX_
#include <unotools/configitem.hxx>
#endif

//.............................................................................
namespace chart
{
//.............................................................................
using namespace ::com::sun::star;

namespace
{
bool lcl_IsMetric()
{
    SvtSysLocale aSysLocale;
    const LocaleDataWrapper* pLocWrapper = aSysLocale.GetLocaleDataPtr();
    MeasurementSystem eSys = pLocWrapper->getMeasurementSystemEnum();

    return ( eSys == MEASURE_METRIC );
}
}//end anonymous namespace

class CalcConfigItem : public ::utl::ConfigItem
{
public:
    CalcConfigItem();
    virtual ~CalcConfigItem();

    FieldUnit getFieldUnit();
};

CalcConfigItem::CalcConfigItem()
    : ConfigItem( ::rtl::OUString( C2U( "Office.Calc/Layout" )))
{
}
CalcConfigItem::~CalcConfigItem()
{
}

FieldUnit CalcConfigItem::getFieldUnit()
{
    FieldUnit eResult( FUNIT_CM );

    uno::Sequence< ::rtl::OUString > aNames( 1 );
    if( lcl_IsMetric() )
        aNames[ 0 ] = ::rtl::OUString( C2U( "Other/MeasureUnit/Metric" ));
    else
        aNames[ 0 ] = ::rtl::OUString( C2U( "Other/MeasureUnit/NonMetric" ));

    uno::Sequence< uno::Any > aResult( GetProperties( aNames ));
    sal_Int32 nValue;
    if( aResult[ 0 ] >>= nValue )
        eResult = static_cast< FieldUnit >( nValue );

    return eResult;
}

ConfigurationAccess::ConfigurationAccess()
    : m_pCalcConfigItem(0)
{
    m_pCalcConfigItem = new CalcConfigItem();
}
ConfigurationAccess::~ConfigurationAccess()
{
    delete m_pCalcConfigItem;
}
FieldUnit ConfigurationAccess::getFieldUnit()
{
    FieldUnit aUnit( m_pCalcConfigItem->getFieldUnit() );
    return aUnit;
}

//.............................................................................
} //namespace chart
//.............................................................................
<|endoftext|>