<commit_before>/*
 * JSDX Framework
 *
 * Copyright(c) 2012 Fred Chien <fred@mandice.com>
 *
 */

#include <v8.h>
#include <node.h>
#include <string.h>
#include <clutter/clutter.h>

#include "jsdx_toolkit.hpp"
#include "actor.hpp"
#include "texture.hpp"
#include "media.hpp"

namespace JSDXToolkit {

	using namespace node;
	using namespace v8;

	Media::Media() : Texture() {

		notify_state_cb = NULL;
		notify_buffering_cb = NULL;
		signal_eos_cb = NULL;
		signal_error_cb = NULL;
	}

	void Media::PrototypeMethodsInit(Handle<FunctionTemplate> constructor_template)
	{
		HandleScope scope;

		constructor_template->InstanceTemplate()->SetAccessor(String::NewSymbol("playing"), Media::PlayingGetter, Media::PlayingSetter);

		NODE_SET_PROTOTYPE_METHOD(constructor_template, "loadFile", Media::LoadFile);
		NODE_SET_PROTOTYPE_METHOD(constructor_template, "loadFileURI", Media::LoadFileURI);
		NODE_SET_PROTOTYPE_METHOD(constructor_template, "play", Media::Play);
		NODE_SET_PROTOTYPE_METHOD(constructor_template, "pause", Media::Pause);
		NODE_SET_PROTOTYPE_METHOD(constructor_template, "setVolume", Media::SetVolume);
		NODE_SET_PROTOTYPE_METHOD(constructor_template, "getVolume", Media::GetVolume);
		NODE_SET_PROTOTYPE_METHOD(constructor_template, "setProgress", Media::SetProgress);
		NODE_SET_PROTOTYPE_METHOD(constructor_template, "getProgress", Media::GetProgress);
		NODE_SET_PROTOTYPE_METHOD(constructor_template, "getBufferFill", Media::GetBufferFill);

		NODE_SET_PROTOTYPE_METHOD(constructor_template, "on", Media::On);
	}

	/* Accessors */
	Handle<Value> Media::PlayingGetter(Local<String> name, const AccessorInfo& info)
	{
		HandleScope scope;

		ClutterActor *instance = ObjectWrap::Unwrap<Actor>(info.This())->_actor;

		return scope.Close(
			Boolean::New(clutter_media_get_playing(CLUTTER_MEDIA(instance)))
		);
	}

	void Media::PlayingSetter(Local<String> name, Local<Value> value, const AccessorInfo& info)
	{
		HandleScope scope;

		if (value->IsBoolean()) {
			ClutterActor *instance = ObjectWrap::Unwrap<Actor>(info.This())->_actor;

			clutter_media_set_playing(CLUTTER_MEDIA(instance), value->ToBoolean()->Value());
		}
	}

	/* Methods */
	Handle<Value> Media::LoadFile(const Arguments &args)
	{
		HandleScope scope;

		if (args[0]->IsString()) {
			ClutterActor *instance = ObjectWrap::Unwrap<Actor>(args.This())->_actor;

			clutter_media_set_filename(CLUTTER_MEDIA(instance), *String::Utf8Value(args[0]->ToString()));
		}

		return args.This();
	}

	Handle<Value> Media::LoadFileURI(const Arguments &args)
	{
		HandleScope scope;

		if (args[0]->IsString()) {
			ClutterActor *instance = ObjectWrap::Unwrap<Actor>(args.This())->_actor;

			clutter_media_set_uri(CLUTTER_MEDIA(instance), *String::Utf8Value(args[0]->ToString()));
		}

		return args.This();
	}

	Handle<Value> Media::Play(const Arguments &args)
	{
		HandleScope scope;

		ClutterActor *instance = ObjectWrap::Unwrap<Actor>(args.This())->_actor;

		clutter_media_set_playing(CLUTTER_MEDIA(instance), TRUE);

		return args.This();
	}

	Handle<Value> Media::Pause(const Arguments &args)
	{
		HandleScope scope;

		ClutterActor *instance = ObjectWrap::Unwrap<Actor>(args.This())->_actor;

		clutter_media_set_playing(CLUTTER_MEDIA(instance), FALSE);

		return args.This();
	}

	Handle<Value> Media::SetVolume(const Arguments &args)
	{
		HandleScope scope;

		if (args[0]->IsNumber()) {
			ClutterActor *instance = ObjectWrap::Unwrap<Actor>(args.This())->_actor;

			clutter_media_set_audio_volume(CLUTTER_MEDIA(instance), args[0]->NumberValue());
		}

		return args.This();
	}

	Handle<Value> Media::GetVolume(const Arguments &args)
	{
		HandleScope scope;

		ClutterActor *instance = ObjectWrap::Unwrap<Actor>(args.This())->_actor;

		return scope.Close(
			Number::New(clutter_media_get_audio_volume(CLUTTER_MEDIA(instance)))
		);
	}

	Handle<Value> Media::SetProgress(const Arguments &args)
	{
		HandleScope scope;

		if (args[0]->IsNumber()) {
			ClutterActor *instance = ObjectWrap::Unwrap<Actor>(args.This())->_actor;

			clutter_media_set_progress(CLUTTER_MEDIA(instance), args[0]->NumberValue());
		}

		return args.This();
	}

	Handle<Value> Media::GetProgress(const Arguments &args)
	{
		HandleScope scope;

		ClutterActor *instance = ObjectWrap::Unwrap<Actor>(args.This())->_actor;

		return scope.Close(
			Number::New(clutter_media_get_progress(CLUTTER_MEDIA(instance)))
		);
	}

	Handle<Value> Media::GetBufferFill(const Arguments &args)
	{
		HandleScope scope;

		ClutterActor *instance = ObjectWrap::Unwrap<Actor>(args.This())->_actor;

		return scope.Close(
			Number::New(clutter_media_get_buffer_fill(CLUTTER_MEDIA(instance)))
		);
	}

	Handle<Value> Media::On(const Arguments &args)
	{
		HandleScope scope;
		Local<Value> Event;
		Local<Value> Options;
		Local<Value> Callback;

		Media *media = ObjectWrap::Unwrap<Media>(args.This());
		ClutterActor *instance = ObjectWrap::Unwrap<Actor>(args.This())->_actor;

		/* Check arguments */
		if (args.Length() > 3) {
			return ThrowException(Exception::TypeError(
				String::New("too much arguments")));
		} else if (args.Length() < 2) {
			return ThrowException(Exception::TypeError(
				String::New("too few arguments")));
		}

		if (args.Length() == 2) {
			Event = args[0];
			Callback = args[1];
		} else if (args.Length() == 3) {
			Event = args[0];
			Options = args[1];
			Callback = args[2];

			if (!Options->IsObject())
				return ThrowException(Exception::TypeError(
					String::New("options parameter must be object")));
		}

		if (!Event->IsString())
			return ThrowException(Exception::TypeError(
				String::New("first arguments must be string")));

		if (!Callback->IsFunction())
			return ThrowException(Exception::TypeError(
				String::New("require callback function")));

		if (strcmp(*String::Utf8Value(Event->ToString()), "state") == 0) {

			if (!media->notify_state_cb) {
				media->notify_state_cb = new NodeCallback;
			} else {
				media->notify_state_cb->Holder.Dispose();
				media->notify_state_cb->cb.Dispose();
			}

			media->notify_state_cb->Holder = Persistent<Object>::New(args.Holder());
			media->notify_state_cb->cb = Persistent<Function>::New(Handle<Function>::Cast(Callback));

			g_signal_connect(G_OBJECT(instance), "notify::playing", G_CALLBACK(Media::_NotifyStateCallback), (gpointer)media->notify_state_cb);

		} else if (strcmp(*String::Utf8Value(Event->ToString()), "buffering") == 0) {

			if (!media->notify_buffering_cb) {
				media->notify_buffering_cb = new NodeCallback;
			} else {
				media->notify_buffering_cb->Holder.Dispose();
				media->notify_buffering_cb->cb.Dispose();
			}

			media->notify_buffering_cb->Holder = Persistent<Object>::New(args.Holder());
			media->notify_buffering_cb->cb = Persistent<Function>::New(Handle<Function>::Cast(Callback));

			g_signal_connect(G_OBJECT(instance), "notify::buffer-fill", G_CALLBACK(Media::_NotifyBufferingCallback), (gpointer)media->notify_buffering_cb);

		} else if (strcmp(*String::Utf8Value(Event->ToString()), "eos") == 0) {

			if (!media->signal_eos_cb) {
				media->signal_eos_cb = new NodeCallback;
			} else {
				media->signal_eos_cb->Holder.Dispose();
				media->signal_eos_cb->cb.Dispose();
			}

			media->signal_eos_cb->Holder = Persistent<Object>::New(args.Holder());
			media->signal_eos_cb->cb = Persistent<Function>::New(Handle<Function>::Cast(Callback));

			g_signal_connect(G_OBJECT(instance), "eos", G_CALLBACK(Media::_SignalEOSCallback), (gpointer)media->signal_eos_cb);

		} else if (strcmp(*String::Utf8Value(Event->ToString()), "error") == 0) {

			if (!media->signal_error_cb) {
				media->signal_error_cb = new NodeCallback;
			} else {
				media->signal_error_cb->Holder.Dispose();
				media->signal_error_cb->cb.Dispose();
			}

			media->signal_error_cb->Holder = Persistent<Object>::New(args.Holder());
			media->signal_error_cb->cb = Persistent<Function>::New(Handle<Function>::Cast(Callback));

			g_signal_connect(G_OBJECT(instance), "error", G_CALLBACK(Media::_SignalErrorCallback), (gpointer)media->signal_error_cb);
		} else {
			Texture::On(args);
		}

		return args.This();
	}

	/* Signal callback */
	void Media::_NotifyStateCallback(GObject *object, GParamSpec *pspec, gpointer user_data)
	{
		NodeCallback *cb = (NodeCallback *)user_data;

		cb->cb->Call(cb->Holder, 0, 0);
	}

	void Media::_NotifyBufferingCallback(GObject *object, GParamSpec *pspec, gpointer user_data)
	{
		NodeCallback *cb = (NodeCallback *)user_data;

		cb->cb->Call(cb->Holder, 0, 0);
	}

	void Media::_SignalEOSCallback(ClutterMedia *media, gpointer user_data)
	{
		NodeCallback *cb = (NodeCallback *)user_data;

		cb->cb->Call(cb->Holder, 0, 0);
	}

	void Media::_SignalErrorCallback(ClutterMedia *media, GError *error, gpointer user_data)
	{
		NodeCallback *cb = (NodeCallback *)user_data;

		cb->cb->Call(cb->Holder, 0, 0);
	}
}
<commit_msg>allow event handler of media actor to be registered once only<commit_after>/*
 * JSDX Framework
 *
 * Copyright(c) 2012 Fred Chien <fred@mandice.com>
 *
 */

#include <v8.h>
#include <node.h>
#include <string.h>
#include <clutter/clutter.h>

#include "jsdx_toolkit.hpp"
#include "actor.hpp"
#include "texture.hpp"
#include "media.hpp"

namespace JSDXToolkit {

	using namespace node;
	using namespace v8;

	Media::Media() : Texture() {

		notify_state_cb = NULL;
		notify_buffering_cb = NULL;
		signal_eos_cb = NULL;
		signal_error_cb = NULL;
	}

	void Media::PrototypeMethodsInit(Handle<FunctionTemplate> constructor_template)
	{
		HandleScope scope;

		constructor_template->InstanceTemplate()->SetAccessor(String::NewSymbol("playing"), Media::PlayingGetter, Media::PlayingSetter);

		NODE_SET_PROTOTYPE_METHOD(constructor_template, "loadFile", Media::LoadFile);
		NODE_SET_PROTOTYPE_METHOD(constructor_template, "loadFileURI", Media::LoadFileURI);
		NODE_SET_PROTOTYPE_METHOD(constructor_template, "play", Media::Play);
		NODE_SET_PROTOTYPE_METHOD(constructor_template, "pause", Media::Pause);
		NODE_SET_PROTOTYPE_METHOD(constructor_template, "setVolume", Media::SetVolume);
		NODE_SET_PROTOTYPE_METHOD(constructor_template, "getVolume", Media::GetVolume);
		NODE_SET_PROTOTYPE_METHOD(constructor_template, "setProgress", Media::SetProgress);
		NODE_SET_PROTOTYPE_METHOD(constructor_template, "getProgress", Media::GetProgress);
		NODE_SET_PROTOTYPE_METHOD(constructor_template, "getBufferFill", Media::GetBufferFill);

		NODE_SET_PROTOTYPE_METHOD(constructor_template, "on", Media::On);
	}

	/* Accessors */
	Handle<Value> Media::PlayingGetter(Local<String> name, const AccessorInfo& info)
	{
		HandleScope scope;

		ClutterActor *instance = ObjectWrap::Unwrap<Actor>(info.This())->_actor;

		return scope.Close(
			Boolean::New(clutter_media_get_playing(CLUTTER_MEDIA(instance)))
		);
	}

	void Media::PlayingSetter(Local<String> name, Local<Value> value, const AccessorInfo& info)
	{
		HandleScope scope;

		if (value->IsBoolean()) {
			ClutterActor *instance = ObjectWrap::Unwrap<Actor>(info.This())->_actor;

			clutter_media_set_playing(CLUTTER_MEDIA(instance), value->ToBoolean()->Value());
		}
	}

	/* Methods */
	Handle<Value> Media::LoadFile(const Arguments &args)
	{
		HandleScope scope;

		if (args[0]->IsString()) {
			ClutterActor *instance = ObjectWrap::Unwrap<Actor>(args.This())->_actor;

			clutter_media_set_filename(CLUTTER_MEDIA(instance), *String::Utf8Value(args[0]->ToString()));
		}

		return args.This();
	}

	Handle<Value> Media::LoadFileURI(const Arguments &args)
	{
		HandleScope scope;

		if (args[0]->IsString()) {
			ClutterActor *instance = ObjectWrap::Unwrap<Actor>(args.This())->_actor;

			clutter_media_set_uri(CLUTTER_MEDIA(instance), *String::Utf8Value(args[0]->ToString()));
		}

		return args.This();
	}

	Handle<Value> Media::Play(const Arguments &args)
	{
		HandleScope scope;

		ClutterActor *instance = ObjectWrap::Unwrap<Actor>(args.This())->_actor;

		clutter_media_set_playing(CLUTTER_MEDIA(instance), TRUE);

		return args.This();
	}

	Handle<Value> Media::Pause(const Arguments &args)
	{
		HandleScope scope;

		ClutterActor *instance = ObjectWrap::Unwrap<Actor>(args.This())->_actor;

		clutter_media_set_playing(CLUTTER_MEDIA(instance), FALSE);

		return args.This();
	}

	Handle<Value> Media::SetVolume(const Arguments &args)
	{
		HandleScope scope;

		if (args[0]->IsNumber()) {
			ClutterActor *instance = ObjectWrap::Unwrap<Actor>(args.This())->_actor;

			clutter_media_set_audio_volume(CLUTTER_MEDIA(instance), args[0]->NumberValue());
		}

		return args.This();
	}

	Handle<Value> Media::GetVolume(const Arguments &args)
	{
		HandleScope scope;

		ClutterActor *instance = ObjectWrap::Unwrap<Actor>(args.This())->_actor;

		return scope.Close(
			Number::New(clutter_media_get_audio_volume(CLUTTER_MEDIA(instance)))
		);
	}

	Handle<Value> Media::SetProgress(const Arguments &args)
	{
		HandleScope scope;

		if (args[0]->IsNumber()) {
			ClutterActor *instance = ObjectWrap::Unwrap<Actor>(args.This())->_actor;

			clutter_media_set_progress(CLUTTER_MEDIA(instance), args[0]->NumberValue());
		}

		return args.This();
	}

	Handle<Value> Media::GetProgress(const Arguments &args)
	{
		HandleScope scope;

		ClutterActor *instance = ObjectWrap::Unwrap<Actor>(args.This())->_actor;

		return scope.Close(
			Number::New(clutter_media_get_progress(CLUTTER_MEDIA(instance)))
		);
	}

	Handle<Value> Media::GetBufferFill(const Arguments &args)
	{
		HandleScope scope;

		ClutterActor *instance = ObjectWrap::Unwrap<Actor>(args.This())->_actor;

		return scope.Close(
			Number::New(clutter_media_get_buffer_fill(CLUTTER_MEDIA(instance)))
		);
	}

	Handle<Value> Media::On(const Arguments &args)
	{
		HandleScope scope;
		Local<Value> Event;
		Local<Value> Options;
		Local<Value> Callback;

		Media *media = ObjectWrap::Unwrap<Media>(args.This());
		ClutterActor *instance = ObjectWrap::Unwrap<Actor>(args.This())->_actor;

		/* Check arguments */
		if (args.Length() > 3) {
			return ThrowException(Exception::TypeError(
				String::New("too much arguments")));
		} else if (args.Length() < 2) {
			return ThrowException(Exception::TypeError(
				String::New("too few arguments")));
		}

		if (args.Length() == 2) {
			Event = args[0];
			Callback = args[1];
		} else if (args.Length() == 3) {
			Event = args[0];
			Options = args[1];
			Callback = args[2];

			if (!Options->IsObject())
				return ThrowException(Exception::TypeError(
					String::New("options parameter must be object")));
		}

		if (!Event->IsString())
			return ThrowException(Exception::TypeError(
				String::New("first arguments must be string")));

		if (!Callback->IsFunction())
			return ThrowException(Exception::TypeError(
				String::New("require callback function")));

		bool reg = FALSE;
		if (strcmp(*String::Utf8Value(Event->ToString()), "state") == 0) {

			if (!media->notify_state_cb) {
				reg = TRUE;
				media->notify_state_cb = new NodeCallback;
			} else {
				media->notify_state_cb->Holder.Dispose();
				media->notify_state_cb->cb.Dispose();
			}

			media->notify_state_cb->Holder = Persistent<Object>::New(args.Holder());
			media->notify_state_cb->cb = Persistent<Function>::New(Handle<Function>::Cast(Callback));

			if (reg)
				g_signal_connect(G_OBJECT(instance), "notify::playing", G_CALLBACK(Media::_NotifyStateCallback), (gpointer)media->notify_state_cb);

		} else if (strcmp(*String::Utf8Value(Event->ToString()), "buffering") == 0) {

			if (!media->notify_buffering_cb) {
				reg = TRUE;
				media->notify_buffering_cb = new NodeCallback;
			} else {
				media->notify_buffering_cb->Holder.Dispose();
				media->notify_buffering_cb->cb.Dispose();
			}

			media->notify_buffering_cb->Holder = Persistent<Object>::New(args.Holder());
			media->notify_buffering_cb->cb = Persistent<Function>::New(Handle<Function>::Cast(Callback));

			if (reg)
				g_signal_connect(G_OBJECT(instance), "notify::buffer-fill", G_CALLBACK(Media::_NotifyBufferingCallback), (gpointer)media->notify_buffering_cb);

		} else if (strcmp(*String::Utf8Value(Event->ToString()), "eos") == 0) {

			if (!media->signal_eos_cb) {
				reg = TRUE;
				media->signal_eos_cb = new NodeCallback;
			} else {
				media->signal_eos_cb->Holder.Dispose();
				media->signal_eos_cb->cb.Dispose();
			}

			media->signal_eos_cb->Holder = Persistent<Object>::New(args.Holder());
			media->signal_eos_cb->cb = Persistent<Function>::New(Handle<Function>::Cast(Callback));

			if (reg)
				g_signal_connect(G_OBJECT(instance), "eos", G_CALLBACK(Media::_SignalEOSCallback), (gpointer)media->signal_eos_cb);

		} else if (strcmp(*String::Utf8Value(Event->ToString()), "error") == 0) {

			if (!media->signal_error_cb) {
				reg = TRUE;
				media->signal_error_cb = new NodeCallback;
			} else {
				media->signal_error_cb->Holder.Dispose();
				media->signal_error_cb->cb.Dispose();
			}

			media->signal_error_cb->Holder = Persistent<Object>::New(args.Holder());
			media->signal_error_cb->cb = Persistent<Function>::New(Handle<Function>::Cast(Callback));

			if (reg)
				g_signal_connect(G_OBJECT(instance), "error", G_CALLBACK(Media::_SignalErrorCallback), (gpointer)media->signal_error_cb);

		} else {
			Texture::On(args);
		}

		return args.This();
	}

	/* Signal callback */
	void Media::_NotifyStateCallback(GObject *object, GParamSpec *pspec, gpointer user_data)
	{
		NodeCallback *cb = (NodeCallback *)user_data;

		cb->cb->Call(cb->Holder, 0, 0);
	}

	void Media::_NotifyBufferingCallback(GObject *object, GParamSpec *pspec, gpointer user_data)
	{
		NodeCallback *cb = (NodeCallback *)user_data;

		cb->cb->Call(cb->Holder, 0, 0);
	}

	void Media::_SignalEOSCallback(ClutterMedia *media, gpointer user_data)
	{
		NodeCallback *cb = (NodeCallback *)user_data;

		cb->cb->Call(cb->Holder, 0, 0);
	}

	void Media::_SignalErrorCallback(ClutterMedia *media, GError *error, gpointer user_data)
	{
		NodeCallback *cb = (NodeCallback *)user_data;

		cb->cb->Call(cb->Holder, 0, 0);
	}
}
<|endoftext|>


<commit_before>/*
 * Copyright 2020 INRIA
 */

#include "eigenpy/numpy.hpp"

namespace eigenpy
{
  void import_numpy()
  {
    if(_import_array() < 0)
    {
      PyErr_Print();
      PyErr_SetString(PyExc_ImportError, "numpy.core.multiarray failed to import");
    }
  }

  int PyArray_TypeNum(PyTypeObject * type)
  {
    return PyArray_TypeNumFromName(const_cast<char*>(type->tp_name));
  }

#if defined _WIN32 || defined __CYGWIN__

  PyObject* call_PyArray_SimpleNew(int nd, npy_intp * shape, int np_type)
  {
    return PyArray_SimpleNew(nd,shape,np_type);
  }

  PyObject* call_PyArray_New(PyTypeObject * py_type_ptr, int nd, npy_intp * shape, int np_type, void * data_ptr, int options)
  {
    return PyArray_New(py_type_ptr,nd,shape,np_type,NULL,data_ptr,0,options,NULL);
  }

  int call_PyArray_ObjectType(PyObject * obj, int val)
  {
    return PyArray_ObjectType(obj,val);
  }

  PyTypeObject * getPyArrayType() { return &PyArray_Type; }

  int call_PyArray_TypeNumFromName(const std::string & name)
  {
    return getPyArrayType(name.c_str());
  }

#endif
}
<commit_msg>core: fix Win32 issue<commit_after>/*
 * Copyright 2020 INRIA
 */

#include "eigenpy/numpy.hpp"

namespace eigenpy
{
  void import_numpy()
  {
    if(_import_array() < 0)
    {
      PyErr_Print();
      PyErr_SetString(PyExc_ImportError, "numpy.core.multiarray failed to import");
    }
  }

  int PyArray_TypeNum(PyTypeObject * type)
  {
    return PyArray_TypeNumFromName(const_cast<char*>(type->tp_name));
  }

#if defined _WIN32 || defined __CYGWIN__

  PyObject* call_PyArray_SimpleNew(int nd, npy_intp * shape, int np_type)
  {
    return PyArray_SimpleNew(nd,shape,np_type);
  }

  PyObject* call_PyArray_New(PyTypeObject * py_type_ptr, int nd, npy_intp * shape, int np_type, void * data_ptr, int options)
  {
    return PyArray_New(py_type_ptr,nd,shape,np_type,NULL,data_ptr,0,options,NULL);
  }

  int call_PyArray_ObjectType(PyObject * obj, int val)
  {
    return PyArray_ObjectType(obj,val);
  }

  PyTypeObject * getPyArrayType() { return &PyArray_Type; }

  int call_PyArray_TypeNumFromName(const std::string & name)
  {
    return PyArray_TypeNumFromName(name.c_str());
  }

#endif
}
<|endoftext|>


<commit_before>#include "ofApp.h"

#include "Widget.hpp"
#include "Label.hpp"
#include "Button.hpp"
#include "HorizontalPanel.hpp"
#include "VerticalPanel.hpp"

//--------------------------------------------------------------
void ofApp::setup(){
    fonts.push_back(new ofTrueTypeFont());
    fonts.back()->load("HelveticaNeue", 32);
    Panel *basePanel = new VerticalPanel(10, 10);

    basePanel->addWidget(new Label("hello",
                                fonts.back()));

    Panel *innerPanel = new HorizontalPanel();

    innerPanel->addWidget(
        new Button("Button1",
                   fonts.back(),
                   [](){std::cout << "B1" << std::endl;}));
    innerPanel->addWidget(
        new Button("Button2",
                   fonts.back(),
                   [](){std::cout << "B2" << std::endl;}));

    basePanel->addWidget(innerPanel);

    baseWidget = basePanel;
}

//--------------------------------------------------------------
void ofApp::update(){

}

//--------------------------------------------------------------
void ofApp::draw(){
    baseWidget->draw();
}

//--------------------------------------------------------------
void ofApp::keyPressed(int key){

}

//--------------------------------------------------------------
void ofApp::keyReleased(int key){

}

//--------------------------------------------------------------
void ofApp::mouseMoved(int x, int y ){

}

//--------------------------------------------------------------
void ofApp::mouseDragged(int x, int y, int button){

}

//--------------------------------------------------------------
void ofApp::mousePressed(int x, int y, int button){

}

//--------------------------------------------------------------
void ofApp::mouseReleased(int x, int y, int button){
    baseWidget->mouseClicked(x,y);
}

//--------------------------------------------------------------
void ofApp::mouseEntered(int x, int y){

}

//--------------------------------------------------------------
void ofApp::mouseExited(int x, int y){

}

//--------------------------------------------------------------
void ofApp::windowResized(int w, int h){

}

//--------------------------------------------------------------
void ofApp::gotMessage(ofMessage msg){

}

//--------------------------------------------------------------
void ofApp::dragEvent(ofDragInfo dragInfo){

}
<commit_msg>changed the font so it works on windows<commit_after>#include "ofApp.h"

#include "Widget.hpp"
#include "Label.hpp"
#include "Button.hpp"
#include "HorizontalPanel.hpp"
#include "VerticalPanel.hpp"

//--------------------------------------------------------------
void ofApp::setup(){
    fonts.push_back(new ofTrueTypeFont());
    fonts.back()->load("Arial", 32);
    Panel *basePanel = new VerticalPanel(10, 10);

    basePanel->addWidget(new Label("hello",
                                fonts.back()));

    Panel *innerPanel = new HorizontalPanel();

    innerPanel->addWidget(
        new Button("Button1",
                   fonts.back(),
                   [](){std::cout << "B1" << std::endl;}));
    innerPanel->addWidget(
        new Button("Button2",
                   fonts.back(),
                   [](){std::cout << "B2" << std::endl;}));

    basePanel->addWidget(innerPanel);

    baseWidget = basePanel;
}

//--------------------------------------------------------------
void ofApp::update(){

}

//--------------------------------------------------------------
void ofApp::draw(){
    baseWidget->draw();
}

//--------------------------------------------------------------
void ofApp::keyPressed(int key){

}

//--------------------------------------------------------------
void ofApp::keyReleased(int key){

}

//--------------------------------------------------------------
void ofApp::mouseMoved(int x, int y ){

}

//--------------------------------------------------------------
void ofApp::mouseDragged(int x, int y, int button){

}

//--------------------------------------------------------------
void ofApp::mousePressed(int x, int y, int button){

}

//--------------------------------------------------------------
void ofApp::mouseReleased(int x, int y, int button){
    baseWidget->mouseClicked(x,y);
}

//--------------------------------------------------------------
void ofApp::mouseEntered(int x, int y){

}

//--------------------------------------------------------------
void ofApp::mouseExited(int x, int y){

}

//--------------------------------------------------------------
void ofApp::windowResized(int w, int h){

}

//--------------------------------------------------------------
void ofApp::gotMessage(ofMessage msg){

}

//--------------------------------------------------------------
void ofApp::dragEvent(ofDragInfo dragInfo){

}
<|endoftext|>


<commit_before>#include "posit.h"

#include <cstdio>
#include <cmath>

#define POW2(n) \
    (1 << n)

POSIT_UTYPE Posit::buildMask(unsigned size)
{
    return POSIT_MASK << (POSIT_SIZE - size);
}

Posit::Posit(POSIT_UTYPE bits, unsigned nbits, unsigned es, bool nan) :
    mBits(bits),
    mNbits(nbits),
    mEs(es),
    mNan(nan)
{
}

Posit::Posit(unsigned nbits, unsigned es, bool nan) :
    Posit(0, nbits, es, nan)
{
}

Posit::Posit(unsigned nbits, unsigned es) :
    Posit(nbits, es, false)
{
}

bool Posit::isZero()
{
    return mBits == POSIT_ZERO;
}

bool Posit::isOne()
{
    return mBits == POSIT_ONE || mBits == POSIT_MONE;
}

bool Posit::isInf()
{
    return mBits == POSIT_INF;
}

bool Posit::isNeg()
{
    return (POSIT_STYPE)mBits < 0 && mBits != POSIT_INF;
}

bool Posit::isNan()
{
    return mNan;
}

unsigned Posit::nbits()
{
    return mNbits;
}

unsigned Posit::rs()
{
    signed lastBit = -1;
    unsigned rs = 0;

    // find a bit that changes, ignoring sign bit
    for (signed i = POSIT_SIZE - 2; i >= POSIT_SIZE - mNbits; i--) {
        bool bit = (mBits >> i) & 1;
        rs++;

        if (bit != lastBit && lastBit >= 0) {
            break;
        }

        lastBit = bit;
    }

    return rs;
}

unsigned Posit::es()
{
    unsigned efs = mNbits - 1 - rs();
    unsigned es = mEs < efs ? mEs : efs;

    return (es >= 0 ? es : 0);
}

unsigned Posit::fs()
{
    return mNbits - 1 - rs() - es();
}

unsigned Posit::useed()
{
    return POW2(POW2(mEs));
}

signed Posit::regime()
{
    POSIT_UTYPE bits = (isNeg() ? neg().mBits : mBits) << 1;
    POSIT_UTYPE himask = 1 << (POSIT_SIZE - 1);
    signed r = 0;

    // out of bounds regime for error handling
    if (isZero()) {
        return -mNbits + 1;
    } else if (isInf()) {
        return mNbits - 1;
    }

    if (bits & himask) {    // >0
        while (1) {
            bits <<= 1;
            if (!(bits & himask))
                break;
            r++;
        }
    } else {                // <=0
        while (1) {
            bits <<= 1;
            r--;
            if (bits & himask)
                break;
        }
    }

    return r;
}

POSIT_UTYPE Posit::exponent()
{
    POSIT_UTYPE expBits = (mBits & (buildMask(mEs) >> (1 + rs())));

    return expBits >> (POSIT_SIZE - mNbits + fs());
}

POSIT_UTYPE Posit::fraction()
{
    POSIT_UTYPE fracBits = (mBits & (buildMask(fs()) >> (1 + rs() + es())));

    return fracBits >> (POSIT_SIZE - mNbits);
}

Posit Posit::zero()
{
    return Posit(POSIT_ZERO, mNbits, mEs, false);
}

Posit Posit::one()
{
    return Posit(POSIT_ONE, mNbits, mEs, false);
}

Posit Posit::inf()
{
    return Posit(POSIT_INF, mNbits, mEs, false);
}

Posit Posit::nan()
{
    return Posit(mNbits, mEs, true);
}

Posit Posit::neg()
{
    Posit p = Posit(mNbits, mEs);
    POSIT_UTYPE mask = buildMask(mNbits);

    // reverse all bits and add one
    p.mBits = ((mBits ^ POSIT_MASK) + 1) & mask;

    return p;
}

Posit Posit::rec()
{
    Posit p = Posit(mNbits, mEs);
    POSIT_UTYPE mask = buildMask(mNbits);

    // reverse all bits but the first one and add one
    p.mBits = ((mBits ^ (POSIT_MASK >> 1)) + 1) & mask;

    return p;
}

Posit Posit::add(Posit& p)
{
    // fast exit
    if (isZero()) {
        return p;
    } else if (p.isZero()) {
        return *this;
    } else if (isInf() && p.isInf()) {
        return nan();
    } else if (isInf() || p.isInf()) {
        return inf();
    } else if (neg().eq(p)) {
        return zero();
    }

    // TODO implement
    return *this;
}

Posit Posit::sub(Posit& p)
{
    // no loss on negation
    Posit np = p.neg();

    return add(np);
}

Posit Posit::mul(Posit& p)
{
    // fast exit
    if (isZero()) {
        return (p.isInf() ? nan() : zero());
    } else if (p.isZero()) {
        return (isInf() ? nan() : zero());
    } else if (isOne()) {
        return (isNeg() ? p.neg() : p);
    } else if (p.isOne()) {
        return (p.isNeg() ? neg() : *this);
    } else if (isInf() || p.isInf()) {
        return inf();
    } else if (rec().eq(p)) {
        return one();
    } else if (rec().neg().eq(p)) {
        return one().neg();
    }

    // TODO implement
    return *this;
}

Posit Posit::div(Posit& p)
{
    // no loss on reciprocation!
    Posit rp = p.rec();

    return mul(rp);
}

bool Posit::eq(Posit& p)
{
    return mBits == p.mBits;
}

bool Posit::gt(Posit& p)
{
    if (isInf() || p.isInf()) {
        return false;
    }

    return mBits > p.mBits;
}

bool Posit::ge(Posit& p)
{
    return gt(p) || eq(p);
}

bool Posit::lt(Posit& p)
{
    return !gt(p) && !eq(p);
}

bool Posit::le(Posit& p)
{
    return !gt(p);
}

void Posit::set(int n)
{
    // TODO implement
}

void Posit::set(float n)
{
    // TODO implement
}

void Posit::set(double n)
{
    // TODO implement
}

int Posit::getInt()
{
    return (int)roundf(getFloat());
}

float Posit::getFloat()
{
    if (isZero()) {
        return 0.f;
    } else if (isInf()) {
        return 1.f / 0.f;
    }

    Posit p = (isNeg() ? neg() : *this);

    return (isNeg() ? -1 : 1) *
           powf(p.useed(), p.regime()) *
           POW2(p.exponent()) *
           (1 + (float)p.fraction() / POW2(p.fs()));
}

double Posit::getDouble()
{
    if (isZero()) {
        return 0.0;
    } else if (isInf()) {
        return 1.0 / 0.0;
    }

    Posit p = (isNeg() ? neg() : *this);

    return (isNeg() ? -1 : 1) *
           pow(p.useed(), p.regime()) *
           POW2(p.exponent()) *
           (1 + (double)p.fraction() / POW2(p.fs()));
}

void Posit::setBits(POSIT_UTYPE bits)
{
    mBits = bits << (POSIT_SIZE - mNbits);
}

POSIT_UTYPE Posit::getBits()
{
    return mBits >> (POSIT_SIZE - mNbits);
}

void Posit::print()
{
    Posit p = isNeg() || isInf() ? neg() : *this;

    printf("{%d, %d} ", mNbits, mEs);

    for (signed i = POSIT_SIZE - 1; i >= POSIT_SIZE - mNbits; i--) {
        printf("%d", (mBits >> i) & 1);
    }

    printf(" (%d) -> ", regime());
    printf(isNeg() || isInf() ? "-" : "+");

    for (signed i = POSIT_SIZE - 2; i >= POSIT_SIZE - mNbits; i--) {
        printf("%d", (p.mBits >> i) & 1);

        if (i != POSIT_SIZE - mNbits &&
            (((unsigned)i == (POSIT_SIZE - 1 - p.rs())) ||
             ((unsigned)i == (POSIT_SIZE - 1 - p.rs() - mEs)))) {
            printf(" ");
        }
    }

    printf(" = %lg\n", getDouble());
}
<commit_msg>lib: silence warnings<commit_after>#include "posit.h"

#include <cstdio>
#include <cmath>

#define POW2(n) \
    (1 << n)

POSIT_UTYPE Posit::buildMask(unsigned size)
{
    return POSIT_MASK << (POSIT_SIZE - size);
}

Posit::Posit(POSIT_UTYPE bits, unsigned nbits, unsigned es, bool nan) :
    mBits(bits),
    mNbits(nbits),
    mEs(es),
    mNan(nan)
{
}

Posit::Posit(unsigned nbits, unsigned es, bool nan) :
    Posit(0, nbits, es, nan)
{
}

Posit::Posit(unsigned nbits, unsigned es) :
    Posit(nbits, es, false)
{
}

bool Posit::isZero()
{
    return mBits == POSIT_ZERO;
}

bool Posit::isOne()
{
    return mBits == POSIT_ONE || mBits == POSIT_MONE;
}

bool Posit::isInf()
{
    return mBits == POSIT_INF;
}

bool Posit::isNeg()
{
    return (POSIT_STYPE)mBits < 0 && mBits != POSIT_INF;
}

bool Posit::isNan()
{
    return mNan;
}

unsigned Posit::nbits()
{
    return mNbits;
}

unsigned Posit::rs()
{
    signed lastBit = -1;
    unsigned rs = 0;

    // find a bit that changes, ignoring sign bit
    for (signed i = POSIT_SIZE - 2; i >= (signed)(POSIT_SIZE - mNbits); i--) {
        bool bit = (mBits >> i) & 1;
        rs++;

        if (bit != lastBit && lastBit >= 0) {
            break;
        }

        lastBit = bit;
    }

    return rs;
}

unsigned Posit::es()
{
    unsigned efs = mNbits - 1 - rs();
    unsigned es = mEs < efs ? mEs : efs;

    return (es >= 0 ? es : 0);
}

unsigned Posit::fs()
{
    return mNbits - 1 - rs() - es();
}

unsigned Posit::useed()
{
    return POW2(POW2(mEs));
}

signed Posit::regime()
{
    POSIT_UTYPE bits = (isNeg() ? neg().mBits : mBits) << 1;
    POSIT_UTYPE himask = 1 << (POSIT_SIZE - 1);
    signed r = 0;

    // out of bounds regime for error handling
    if (isZero()) {
        return -mNbits + 1;
    } else if (isInf()) {
        return mNbits - 1;
    }

    if (bits & himask) {    // >0
        while (1) {
            bits <<= 1;
            if (!(bits & himask))
                break;
            r++;
        }
    } else {                // <=0
        while (1) {
            bits <<= 1;
            r--;
            if (bits & himask)
                break;
        }
    }

    return r;
}

POSIT_UTYPE Posit::exponent()
{
    POSIT_UTYPE expBits = (mBits & (buildMask(mEs) >> (1 + rs())));

    return expBits >> (POSIT_SIZE - mNbits + fs());
}

POSIT_UTYPE Posit::fraction()
{
    POSIT_UTYPE fracBits = (mBits & (buildMask(fs()) >> (1 + rs() + es())));

    return fracBits >> (POSIT_SIZE - mNbits);
}

Posit Posit::zero()
{
    return Posit(POSIT_ZERO, mNbits, mEs, false);
}

Posit Posit::one()
{
    return Posit(POSIT_ONE, mNbits, mEs, false);
}

Posit Posit::inf()
{
    return Posit(POSIT_INF, mNbits, mEs, false);
}

Posit Posit::nan()
{
    return Posit(mNbits, mEs, true);
}

Posit Posit::neg()
{
    Posit p = Posit(mNbits, mEs);
    POSIT_UTYPE mask = buildMask(mNbits);

    // reverse all bits and add one
    p.mBits = ((mBits ^ POSIT_MASK) + 1) & mask;

    return p;
}

Posit Posit::rec()
{
    Posit p = Posit(mNbits, mEs);
    POSIT_UTYPE mask = buildMask(mNbits);

    // reverse all bits but the first one and add one
    p.mBits = ((mBits ^ (POSIT_MASK >> 1)) + 1) & mask;

    return p;
}

Posit Posit::add(Posit& p)
{
    // fast exit
    if (isZero()) {
        return p;
    } else if (p.isZero()) {
        return *this;
    } else if (isInf() && p.isInf()) {
        return nan();
    } else if (isInf() || p.isInf()) {
        return inf();
    } else if (neg().eq(p)) {
        return zero();
    }

    // TODO implement
    return *this;
}

Posit Posit::sub(Posit& p)
{
    // no loss on negation
    Posit np = p.neg();

    return add(np);
}

Posit Posit::mul(Posit& p)
{
    // fast exit
    if (isZero()) {
        return (p.isInf() ? nan() : zero());
    } else if (p.isZero()) {
        return (isInf() ? nan() : zero());
    } else if (isOne()) {
        return (isNeg() ? p.neg() : p);
    } else if (p.isOne()) {
        return (p.isNeg() ? neg() : *this);
    } else if (isInf() || p.isInf()) {
        return inf();
    } else if (rec().eq(p)) {
        return one();
    } else if (rec().neg().eq(p)) {
        return one().neg();
    }

    // TODO implement
    return *this;
}

Posit Posit::div(Posit& p)
{
    // no loss on reciprocation!
    Posit rp = p.rec();

    return mul(rp);
}

bool Posit::eq(Posit& p)
{
    return mBits == p.mBits;
}

bool Posit::gt(Posit& p)
{
    if (isInf() || p.isInf()) {
        return false;
    }

    return mBits > p.mBits;
}

bool Posit::ge(Posit& p)
{
    return gt(p) || eq(p);
}

bool Posit::lt(Posit& p)
{
    return !gt(p) && !eq(p);
}

bool Posit::le(Posit& p)
{
    return !gt(p);
}

void Posit::set(int n)
{
    // TODO implement
}

void Posit::set(float n)
{
    // TODO implement
}

void Posit::set(double n)
{
    // TODO implement
}

int Posit::getInt()
{
    return (int)roundf(getFloat());
}

float Posit::getFloat()
{
    if (isZero()) {
        return 0.f;
    } else if (isInf()) {
        return 1.f / 0.f;
    }

    Posit p = (isNeg() ? neg() : *this);

    return (isNeg() ? -1 : 1) *
           powf(p.useed(), p.regime()) *
           POW2(p.exponent()) *
           (1 + (float)p.fraction() / POW2(p.fs()));
}

double Posit::getDouble()
{
    if (isZero()) {
        return 0.0;
    } else if (isInf()) {
        return 1.0 / 0.0;
    }

    Posit p = (isNeg() ? neg() : *this);

    return (isNeg() ? -1 : 1) *
           pow(p.useed(), p.regime()) *
           POW2(p.exponent()) *
           (1 + (double)p.fraction() / POW2(p.fs()));
}

void Posit::setBits(POSIT_UTYPE bits)
{
    mBits = bits << (POSIT_SIZE - mNbits);
}

POSIT_UTYPE Posit::getBits()
{
    return mBits >> (POSIT_SIZE - mNbits);
}

void Posit::print()
{
    Posit p = isNeg() || isInf() ? neg() : *this;

    printf("{%d, %d} ", mNbits, mEs);

    for (signed i = POSIT_SIZE - 1; i >= (signed)(POSIT_SIZE - mNbits); i--) {
        printf("%d", (mBits >> i) & 1);
    }

    printf(" (%d) -> ", regime());
    printf(isNeg() || isInf() ? "-" : "+");

    for (signed i = POSIT_SIZE - 2; i >= (signed)(POSIT_SIZE - mNbits); i--) {
        printf("%d", (p.mBits >> i) & 1);

        if (i != (signed)(POSIT_SIZE - mNbits) &&
            (((unsigned)i == (POSIT_SIZE - 1 - p.rs())) ||
             ((unsigned)i == (POSIT_SIZE - 1 - p.rs() - mEs)))) {
            printf(" ");
        }
    }

    printf(" = %lg\n", getDouble());
}
<|endoftext|>


<commit_before>#include "order.h"

Order::Order(vector<Task> tasks, vector<Maitenance> maitenance_v){

}

int Order::get_exectime(){
	return exec_t;
}

vector<Task_t> Order::get_tasks(){
	return machine1.get_tasks();
}

/*
Order::Order(){

}
Order::Order(vector<Task_t> task_m1_v, vector<Task_t> task_m2_v, vector<Maitenance> maitenance_v){
	machine1.set_id(1);
	machine1.set_start(0);
	machine1.set_stop(0);
	machine2.set_id(2);
	int n = 0;
	unsigned int size = (task_m1_v.size() >= task_m2_v.size())?(task_m1_v.size()):(task_m2_v.size());

	for(unsigned int i = 0; i < size; i++){
		if (task_m1_v.size() < i){
			while(!machine1.add(task_m1_v[i+n], maitenance_v)){
				task_m1_v.push_back(task_m1_v[i+n]);
				n++;
			}
			n = 0;
		}

		if (task_m2_v.size() < i){
			if( i == 0 ){
				machine2.set_start(machine1.get_sop());
				machine2.set_stop(machine1.get_sop());
			}

			if(machine1.get_sop() <= machine2.get_sop()) machine2.add(task_m2_v[i], maitenance_v);
			else machine2.addt(machine1.get_sop(), task_m2_v[i]);
		}
	}

	this->exec_t = machine2.get_sop();
}

void Order::initialization(vector<int> O, vector<Task> task_v, vector<Maitenance> maitenance_v){
	machine1.set_id(1);
	machine1.set_start(0);
	machine1.set_stop(0);
	machine2.set_id(2);
	int n, tmp;
	for (vector<int>::size_type i = 0; i < O.size(); i++){
		//Machine 1
		n = 1;
		while(!machine1.add(O[i], task_v, maitenance_v)){
			tmp = O[i];
			O[i] = O[i + n];
			O[i + n] = tmp;
			n++;
		}
		// Machine 2
		if( i == 0 ){
			machine2.set_start(machine1.get_sop());
			machine2.set_stop(machine1.get_sop());
		}
		if(machine1.get_sop() <= machine2.get_sop()){
			machine2.add(O[i], task_v, maitenance_v);
		}else{
			machine2.addt(machine1.get_sop(), O[i], task_v);
		}
	}

	this->exec_t = machine2.get_sop();
}
*/
<commit_msg>Further order fixes<commit_after>#include "order.h"

Order::Order(vector<Task> tasks, vector<Maitenance> maitenance_v){

}

int Order::get_exectime(){
	return exec_t;
}

vector<Task> Order::get_tasks(){
	return machine1.get_tasks();
}

/*
Order::Order(){

}
Order::Order(vector<Task_t> task_m1_v, vector<Task_t> task_m2_v, vector<Maitenance> maitenance_v){
	machine1.set_id(1);
	machine1.set_start(0);
	machine1.set_stop(0);
	machine2.set_id(2);
	int n = 0;
	unsigned int size = (task_m1_v.size() >= task_m2_v.size())?(task_m1_v.size()):(task_m2_v.size());

	for(unsigned int i = 0; i < size; i++){
		if (task_m1_v.size() < i){
			while(!machine1.add(task_m1_v[i+n], maitenance_v)){
				task_m1_v.push_back(task_m1_v[i+n]);
				n++;
			}
			n = 0;
		}

		if (task_m2_v.size() < i){
			if( i == 0 ){
				machine2.set_start(machine1.get_sop());
				machine2.set_stop(machine1.get_sop());
			}

			if(machine1.get_sop() <= machine2.get_sop()) machine2.add(task_m2_v[i], maitenance_v);
			else machine2.addt(machine1.get_sop(), task_m2_v[i]);
		}
	}

	this->exec_t = machine2.get_sop();
}

void Order::initialization(vector<int> O, vector<Task> task_v, vector<Maitenance> maitenance_v){
	machine1.set_id(1);
	machine1.set_start(0);
	machine1.set_stop(0);
	machine2.set_id(2);
	int n, tmp;
	for (vector<int>::size_type i = 0; i < O.size(); i++){
		//Machine 1
		n = 1;
		while(!machine1.add(O[i], task_v, maitenance_v)){
			tmp = O[i];
			O[i] = O[i + n];
			O[i + n] = tmp;
			n++;
		}
		// Machine 2
		if( i == 0 ){
			machine2.set_start(machine1.get_sop());
			machine2.set_stop(machine1.get_sop());
		}
		if(machine1.get_sop() <= machine2.get_sop()){
			machine2.add(O[i], task_v, maitenance_v);
		}else{
			machine2.addt(machine1.get_sop(), O[i], task_v);
		}
	}

	this->exec_t = machine2.get_sop();
}
*/
<|endoftext|>


<commit_before>#include <cilantro/voxel_grid.hpp>
//#include <cilantro/pca.hpp>

VoxelGrid::VoxelGrid(const std::vector<Eigen::Vector3f> &points, float bin_size)
        : input_points_(&points),
          input_normals_(NULL),
          input_colors_(NULL),
          bin_size_(bin_size),
          empty_indices_(0)
{
    build_lookup_table_();
}

VoxelGrid::VoxelGrid(const PointCloud &cloud, float bin_size)
        : input_points_(&cloud.points),
          input_normals_(cloud.hasNormals()?&cloud.normals:NULL),
          input_colors_(cloud.hasColors()?&cloud.colors:NULL),
          bin_size_(bin_size),
          empty_indices_(0)
{
    build_lookup_table_();
}

std::vector<Eigen::Vector3f> VoxelGrid::getDownsampledPoints(size_t min_points_in_bin) const {
    std::vector<Eigen::Vector3f> points;
    points.reserve(grid_lookup_table_.size());
    for (auto it = grid_lookup_table_.begin(); it != grid_lookup_table_.end(); ++it) {
        if (it->second.size() < min_points_in_bin) continue;

        Eigen::MatrixXf bin_points(3, it->second.size());
        for (size_t i = 0; i < it->second.size(); i++) {
            bin_points.col(i) = (*input_points_)[it->second[i]];
        }
        points.emplace_back(bin_points.rowwise().mean());
    }

    return points;
}

std::vector<Eigen::Vector3f> VoxelGrid::getDownsampledNormals(size_t min_points_in_bin) const {
    std::vector<Eigen::Vector3f> normals;
    if (input_normals_ == NULL) {
        return normals;
    }

//    normals.reserve(grid_lookup_table_.size());
//    for (auto it = grid_lookup_table_.begin(); it != grid_lookup_table_.end(); ++it) {
//        if (it->second.size() < min_points_in_bin) continue;
//
//        Eigen::MatrixXf bin_normals(3, it->second.size()*2);
//        Eigen::Vector3f ref_dir = (*input_normals_)[it->second[0]];
//        size_t pos = 0, neg = 0;
//        for (size_t i = 0; i < it->second.size(); i++) {
//            const Eigen::Vector3f& curr_normal = (*input_normals_)[it->second[i]];
//            if (ref_dir.dot(curr_normal) < 0.0f) neg++; else pos++;
//            bin_normals.col(2*i) = -curr_normal;
//            bin_normals.col(2*i+1) = curr_normal;
//        }
//        if (neg > pos) ref_dir = -ref_dir;
//
//        PCA3D pca(bin_normals.data(), 3, it->second.size()*2);
//        Eigen::Vector3f avg = pca.getEigenVectorsMatrix().col(0);
//        if (ref_dir.dot(avg) < 0.0f) {
//            normals.emplace_back(-avg);
//        } else {
//            normals.emplace_back(avg);
//        }
//    }

    normals.reserve(grid_lookup_table_.size());
    for (auto it = grid_lookup_table_.begin(); it != grid_lookup_table_.end(); ++it) {
        if (it->second.size() < min_points_in_bin) continue;

        Eigen::MatrixXf bin_normals(3, it->second.size());
        Eigen::Vector3f ref_dir = (*input_normals_)[it->second[0]];
        size_t pos = 0, neg = 0;
        for (size_t i = 0; i < it->second.size(); i++) {
            const Eigen::Vector3f& curr_normal = (*input_normals_)[it->second[i]];
            if (ref_dir.dot(curr_normal) < 0.0f) {
                bin_normals.col(i) = -curr_normal;
                neg++;
            } else {
                bin_normals.col(i) = curr_normal;
                pos++;
            }
        }

        Eigen::Vector3f avg = bin_normals.rowwise().mean().normalized();
        if (neg > pos) {
            normals.emplace_back(-avg);
        } else {
            normals.emplace_back(avg);
        }
    }

    return normals;
}

std::vector<Eigen::Vector3f> VoxelGrid::getDownsampledColors(size_t min_points_in_bin) const {
    std::vector<Eigen::Vector3f> colors;
    if (input_colors_ == NULL) return colors;

    colors.reserve(grid_lookup_table_.size());
    for (auto it = grid_lookup_table_.begin(); it != grid_lookup_table_.end(); ++it) {
        if (it->second.size() < min_points_in_bin) continue;

        Eigen::MatrixXf bin_colors(3, it->second.size());
        for (size_t i = 0; i < it->second.size(); i++) {
            bin_colors.col(i) = (*input_colors_)[it->second[i]];
        }
        colors.emplace_back(bin_colors.rowwise().mean());
    }

    return colors;
}

PointCloud VoxelGrid::getDownsampledCloud(size_t min_points_in_bin) const {
    return PointCloud(getDownsampledPoints(min_points_in_bin), getDownsampledNormals(min_points_in_bin), getDownsampledColors(min_points_in_bin));
}

const std::vector<size_t>& VoxelGrid::getGridBinNeighbors(const Eigen::Vector3f &point) const {
    Eigen::Vector3i grid_coords = ((point-min_pt_)/bin_size_).array().floor().cast<int>();
    if ((grid_coords.array() < Eigen::Vector3i::Zero().array()).any()) return empty_indices_;

    auto it = grid_lookup_table_.find(grid_coords);
    if (it == grid_lookup_table_.end()) return empty_indices_;

    return it->second;
}

const std::vector<size_t>& VoxelGrid::getGridBinNeighbors(size_t point_ind) const {
    return VoxelGrid::getGridBinNeighbors((*input_points_)[point_ind]);
}

void VoxelGrid::build_lookup_table_() {
    if (input_points_->empty()) return;

    min_pt_ = Eigen::Map<Eigen::MatrixXf>((float *)input_points_->data(), 3, input_points_->size()).rowwise().minCoeff();
    Eigen::MatrixXi grid_coords = ((Eigen::Map<Eigen::MatrixXf>((float *)input_points_->data(), 3, input_points_->size()).colwise()-min_pt_)/bin_size_).array().floor().cast<int>();

    // Build lookup table
    for (size_t i = 0; i < input_points_->size(); i++) {
        auto it = grid_lookup_table_.find(grid_coords.col(i));
        if (it == grid_lookup_table_.end()) {
            grid_lookup_table_.insert(std::pair<Eigen::Vector3i,std::vector<size_t> >(grid_coords.col(i), std::vector<size_t>(1, i)));
        } else {
            it->second.emplace_back(i);
        }
    }
}
<commit_msg>Minor change<commit_after>#include <cilantro/voxel_grid.hpp>
//#include <cilantro/pca.hpp>

VoxelGrid::VoxelGrid(const std::vector<Eigen::Vector3f> &points, float bin_size)
        : input_points_(&points),
          input_normals_(NULL),
          input_colors_(NULL),
          bin_size_(bin_size),
          empty_indices_(0)
{
    build_lookup_table_();
}

VoxelGrid::VoxelGrid(const PointCloud &cloud, float bin_size)
        : input_points_(&cloud.points),
          input_normals_(cloud.hasNormals()?&cloud.normals:NULL),
          input_colors_(cloud.hasColors()?&cloud.colors:NULL),
          bin_size_(bin_size),
          empty_indices_(0)
{
    build_lookup_table_();
}

std::vector<Eigen::Vector3f> VoxelGrid::getDownsampledPoints(size_t min_points_in_bin) const {
    std::vector<Eigen::Vector3f> points;
    points.reserve(grid_lookup_table_.size());
    for (auto it = grid_lookup_table_.begin(); it != grid_lookup_table_.end(); ++it) {
        if (it->second.size() < min_points_in_bin) continue;

        Eigen::MatrixXf bin_points(3, it->second.size());
        for (size_t i = 0; i < it->second.size(); i++) {
            bin_points.col(i) = (*input_points_)[it->second[i]];
        }
        points.emplace_back(bin_points.rowwise().mean());
    }

    return points;
}

std::vector<Eigen::Vector3f> VoxelGrid::getDownsampledNormals(size_t min_points_in_bin) const {
    std::vector<Eigen::Vector3f> normals;
    if (input_normals_ == NULL) {
        return normals;
    }

//    normals.reserve(grid_lookup_table_.size());
//    for (auto it = grid_lookup_table_.begin(); it != grid_lookup_table_.end(); ++it) {
//        if (it->second.size() < min_points_in_bin) continue;
//
//        Eigen::MatrixXf bin_normals(3, it->second.size()*2);
//        Eigen::Vector3f ref_dir = (*input_normals_)[it->second[0]];
//        size_t pos = 0, neg = 0;
//        for (size_t i = 0; i < it->second.size(); i++) {
//            const Eigen::Vector3f& curr_normal = (*input_normals_)[it->second[i]];
//            if (ref_dir.dot(curr_normal) < 0.0f) neg++; else pos++;
//            bin_normals.col(2*i) = -curr_normal;
//            bin_normals.col(2*i+1) = curr_normal;
//        }
//        if (neg > pos) ref_dir = -ref_dir;
//
//        PCA3D pca(bin_normals.data(), 3, it->second.size()*2);
//        Eigen::Vector3f avg = pca.getEigenVectorsMatrix().col(0);
//        if (ref_dir.dot(avg) < 0.0f) {
//            normals.emplace_back(-avg);
//        } else {
//            normals.emplace_back(avg);
//        }
//    }

    normals.reserve(grid_lookup_table_.size());
    for (auto it = grid_lookup_table_.begin(); it != grid_lookup_table_.end(); ++it) {
        if (it->second.size() < min_points_in_bin) continue;

        Eigen::MatrixXf bin_normals(3, it->second.size());
        Eigen::Vector3f ref_dir = (*input_normals_)[it->second[0]];
        size_t pos = 0, neg = 0;
        for (size_t i = 0; i < it->second.size(); i++) {
            const Eigen::Vector3f& curr_normal = (*input_normals_)[it->second[i]];
            if (ref_dir.dot(curr_normal) < 0.0f) {
                bin_normals.col(i) = -curr_normal;
                neg++;
            } else {
                bin_normals.col(i) = curr_normal;
                pos++;
            }
        }

        Eigen::Vector3f avg = bin_normals.rowwise().mean().normalized();
        if (neg > pos) {
            normals.emplace_back(-avg);
        } else {
            normals.emplace_back(avg);
        }
    }

    return normals;
}

std::vector<Eigen::Vector3f> VoxelGrid::getDownsampledColors(size_t min_points_in_bin) const {
    std::vector<Eigen::Vector3f> colors;
    if (input_colors_ == NULL) return colors;

    colors.reserve(grid_lookup_table_.size());
    for (auto it = grid_lookup_table_.begin(); it != grid_lookup_table_.end(); ++it) {
        if (it->second.size() < min_points_in_bin) continue;

        Eigen::MatrixXf bin_colors(3, it->second.size());
        for (size_t i = 0; i < it->second.size(); i++) {
            bin_colors.col(i) = (*input_colors_)[it->second[i]];
        }
        colors.emplace_back(bin_colors.rowwise().mean());
    }

    return colors;
}

PointCloud VoxelGrid::getDownsampledCloud(size_t min_points_in_bin) const {
    return PointCloud(getDownsampledPoints(min_points_in_bin), getDownsampledNormals(min_points_in_bin), getDownsampledColors(min_points_in_bin));
}

const std::vector<size_t>& VoxelGrid::getGridBinNeighbors(const Eigen::Vector3f &point) const {
    Eigen::Vector3i grid_coords = ((point-min_pt_)/bin_size_).array().floor().cast<int>();
    if ((grid_coords.array() < 0).any()) return empty_indices_;

    auto it = grid_lookup_table_.find(grid_coords);
    if (it == grid_lookup_table_.end()) return empty_indices_;

    return it->second;
}

const std::vector<size_t>& VoxelGrid::getGridBinNeighbors(size_t point_ind) const {
    return VoxelGrid::getGridBinNeighbors((*input_points_)[point_ind]);
}

void VoxelGrid::build_lookup_table_() {
    if (input_points_->empty()) return;

    min_pt_ = Eigen::Map<Eigen::MatrixXf>((float *)input_points_->data(), 3, input_points_->size()).rowwise().minCoeff();
    Eigen::MatrixXi grid_coords = ((Eigen::Map<Eigen::MatrixXf>((float *)input_points_->data(), 3, input_points_->size()).colwise()-min_pt_)/bin_size_).array().floor().cast<int>();

    // Build lookup table
    for (size_t i = 0; i < input_points_->size(); i++) {
        auto it = grid_lookup_table_.find(grid_coords.col(i));
        if (it == grid_lookup_table_.end()) {
            grid_lookup_table_.insert(std::pair<Eigen::Vector3i,std::vector<size_t> >(grid_coords.col(i), std::vector<size_t>(1, i)));
        } else {
            it->second.emplace_back(i);
        }
    }
}
<|endoftext|>


<commit_before>// Copyright 2012-2013 Samplecount S.L.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#ifndef METHCLA_AUDIO_SYNTH_HPP_INCLUDED
#define METHCLA_AUDIO_SYNTH_HPP_INCLUDED

#include "Methcla/Audio/AudioBus.hpp"
#include "Methcla/Audio/Engine.hpp"

#include <boost/intrusive/list.hpp>
#include <boost/utility.hpp>
#include <oscpp/server.hpp>
#include <thread>

namespace Methcla { namespace Audio {

enum InputConnectionType
{
    kIn
  , kInFeedback
};

enum OutputConnectionType
{
    kOut
  , kReplaceOut
};

class Synth;

template <typename BusId, typename ConnectionType>
class Connection : public boost::noncopyable
                 , public boost::intrusive::list_base_hook<>
{
public:
    Connection(size_t index, ConnectionType type)
        : m_index(index)
        , m_connected(false)
        , m_busId(0)
        , m_type(type)
    { }

    size_t index() const { return m_index; }
    bool isConnected() const { return m_connected; }
    BusId busId() const { return m_busId; }
    const ConnectionType& type() const { return m_type; }

    bool connect(const BusId& busId, const ConnectionType& type)
    {
        bool changed = false;
        if (!m_connected || (busId != m_busId)) {
            m_connected = true;
            m_busId = busId;
            changed = true;
        }
        m_type = type;
        return changed;
    }

private:
    size_t          m_index;
    bool            m_connected;
    BusId           m_busId;
    ConnectionType  m_type;
};

class AudioInputConnection : public Connection<AudioBusId,InputConnectionType>
{
public:
    AudioInputConnection(size_t index)
        : Connection<AudioBusId,InputConnectionType>(index, kIn)
    { }

    void read(Environment& env, size_t numFrames, sample_t* dst)
    {
        if (isConnected()) {
            AudioBus* bus = env.audioBus(busId());

            if (bus != nullptr) {
                std::lock_guard<AudioBus::Lock> lock(bus->lock());
                if ((type() == kInFeedback) || (bus->epoch() == env.epoch())) {
                    memcpy(dst, bus->data(), numFrames * sizeof(sample_t));
                } else {
                    memset(dst, 0, numFrames * sizeof(sample_t));
                }
            } else {
                memset(dst, 0, numFrames * sizeof(sample_t));
            }
        }
    }
};

class AudioOutputConnection : public Connection<AudioBusId,OutputConnectionType>
{
public:
    AudioOutputConnection(size_t index)
        : Connection<AudioBusId,OutputConnectionType>(index, kOut)
        , m_offset(0)
        , m_buffer(0)
    { }

    bool connect(const AudioBusId& busId, const OutputConnectionType& type, size_t offset, sample_t* buffer)
    {
        BOOST_ASSERT((m_offset == 0) && (m_buffer == 0));
        m_offset = offset;
        m_buffer = buffer;
        return Connection<AudioBusId,OutputConnectionType>::connect(busId, type);
    }

    void release(Environment& env)
    {
        if (m_buffer != 0) {
            env.rtMem().free(m_buffer);
            m_offset = 0;
            m_buffer = 0;
        }
    }

    void write(Environment& env, size_t numFrames, const sample_t* src)
    {
        if (isConnected()) {
            AudioBus* bus = env.audioBus(busId());

            if (bus != nullptr) {
                const Epoch epoch = env.epoch();
                std::lock_guard<AudioBus::Lock> lock(bus->lock());
                if ((type() != kReplaceOut) && (bus->epoch() == epoch)) {
                    // Accumulate
                    sample_t* dst = bus->data();
                    for (size_t i=0; i < numFrames; i++) {
                        dst[i] += src[i];
                    }
                } else {
                    // Copy
                    memcpy(bus->data(), src, numFrames * sizeof(sample_t));
                    bus->setEpoch(epoch);
                }
            }
        }
    }

private:
    size_t      m_offset;
    sample_t*   m_buffer;
};

class Synth : public Node
{
protected:
    enum Flags
    {
        kAudioInputConnectionsChanged
      , kAudioOutputConnectionsChanged
      , kControlInputConnectionsChanged
      , kControlOutputConnectionsChanged
      , kHasTriggerInput
    };

    Synth( Environment& env
         , Group* target
         , AddAction addAction
         , const SynthDef& synthDef
         , OSC::Server::ArgStream controls
         , OSC::Server::ArgStream args
         , size_t synthOffset
         , size_t audioInputConnectionsOffset
         , size_t audioOutputConnectionsOffset
         , size_t controlBufferOffset
         , size_t audioBufferOffset
         , size_t audioBufferSize
         );
    ~Synth();

public:
    static Synth* construct(Environment& env, Group* target, Node::AddAction addAction, const SynthDef& synthDef, OSC::Server::ArgStream controls, OSC::Server::ArgStream args);

    virtual bool isSynth() const override { return true; }

    //* Return this synth's SynthDef.
    const SynthDef& synthDef() const { return m_synthDef; }

    //* Return number of audio inputs.
    size_t numAudioInputs() const { return synthDef().numAudioInputs(); }

    //* Map input to bus.
    void mapInput(size_t input, const AudioBusId& busId, InputConnectionType type);

    //* Return number of audio outputs.
    size_t numAudioOutputs() const { return synthDef().numAudioOutputs(); }

    //* Map output to bus.
    void mapOutput(size_t output, const AudioBusId& busId, OutputConnectionType type);

    typedef boost::intrusive::list<AudioInputConnection>  AudioInputConnections;
    typedef boost::intrusive::list<AudioOutputConnection> AudioOutputConnections;
    // typedef boost::container::vector<Connection<ControlBus, InputConnectionType> > ControlInputConnections;
    // typedef boost::container::vector<Connection<ControlBus, OutputConnectionType> > ControlOutputConnections;

    size_t numControlInputs() const { return synthDef().numControlInputs(); }
    size_t numControlOutputs() const { return synthDef().numControlOutputs(); }

    float controlInput(size_t index) const
    {
        BOOST_ASSERT_MSG( index < numControlInputs(), "control input index out of range" );
        return m_controlBuffers[index];
    }

    float& controlInput(size_t index)
    {
        BOOST_ASSERT_MSG( index < numControlInputs(), "control input index out of range" );
        return m_controlBuffers[index];
    }

    float controlOutput(size_t index) const
    {
        BOOST_ASSERT_MSG( index < numControlOutputs(), "control output index out of range" );
        return m_controlBuffers[numControlInputs() + index];
    }

    /// Sample offset for sample accurate synth scheduling.
    size_t sampleOffset() const { return 0; }

    /// Sets up inputs and outputs and calls compute.
    virtual void process(size_t numFrames);

    template <class T> T* synth() { return static_cast<T*>(m_synth); }

private:
    const SynthDef&         m_synthDef;
    std::bitset<32>         m_flags;
    Methcla_Synth*          m_synth;
    AudioInputConnections   m_audioInputConnections;
    AudioOutputConnections  m_audioOutputConnections;
    sample_t*               m_controlBuffers;
    sample_t*               m_audioBuffers;
};

}; };

#endif // METHCLA_AUDIO_SYNTH_HPP_INCLUDED
<commit_msg>Remove unused method<commit_after>// Copyright 2012-2013 Samplecount S.L.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#ifndef METHCLA_AUDIO_SYNTH_HPP_INCLUDED
#define METHCLA_AUDIO_SYNTH_HPP_INCLUDED

#include "Methcla/Audio/AudioBus.hpp"
#include "Methcla/Audio/Engine.hpp"

#include <boost/intrusive/list.hpp>
#include <boost/utility.hpp>
#include <oscpp/server.hpp>
#include <thread>

namespace Methcla { namespace Audio {

enum InputConnectionType
{
    kIn
  , kInFeedback
};

enum OutputConnectionType
{
    kOut
  , kReplaceOut
};

class Synth;

template <typename BusId, typename ConnectionType>
class Connection : public boost::noncopyable
                 , public boost::intrusive::list_base_hook<>
{
public:
    Connection(size_t index, ConnectionType type)
        : m_index(index)
        , m_connected(false)
        , m_busId(0)
        , m_type(type)
    { }

    size_t index() const { return m_index; }
    bool isConnected() const { return m_connected; }
    BusId busId() const { return m_busId; }
    const ConnectionType& type() const { return m_type; }

    bool connect(const BusId& busId, const ConnectionType& type)
    {
        bool changed = false;
        if (!m_connected || (busId != m_busId)) {
            m_connected = true;
            m_busId = busId;
            changed = true;
        }
        m_type = type;
        return changed;
    }

private:
    size_t          m_index;
    bool            m_connected;
    BusId           m_busId;
    ConnectionType  m_type;
};

class AudioInputConnection : public Connection<AudioBusId,InputConnectionType>
{
public:
    AudioInputConnection(size_t index)
        : Connection<AudioBusId,InputConnectionType>(index, kIn)
    { }

    void read(Environment& env, size_t numFrames, sample_t* dst)
    {
        if (isConnected()) {
            AudioBus* bus = env.audioBus(busId());

            if (bus != nullptr) {
                std::lock_guard<AudioBus::Lock> lock(bus->lock());
                if ((type() == kInFeedback) || (bus->epoch() == env.epoch())) {
                    memcpy(dst, bus->data(), numFrames * sizeof(sample_t));
                } else {
                    memset(dst, 0, numFrames * sizeof(sample_t));
                }
            } else {
                memset(dst, 0, numFrames * sizeof(sample_t));
            }
        }
    }
};

class AudioOutputConnection : public Connection<AudioBusId,OutputConnectionType>
{
public:
    AudioOutputConnection(size_t index)
        : Connection<AudioBusId,OutputConnectionType>(index, kOut)
        , m_offset(0)
        , m_buffer(0)
    { }

    bool connect(const AudioBusId& busId, const OutputConnectionType& type, size_t offset, sample_t* buffer)
    {
        BOOST_ASSERT((m_offset == 0) && (m_buffer == 0));
        m_offset = offset;
        m_buffer = buffer;
        return Connection<AudioBusId,OutputConnectionType>::connect(busId, type);
    }

    void release(Environment& env)
    {
        if (m_buffer != 0) {
            env.rtMem().free(m_buffer);
            m_offset = 0;
            m_buffer = 0;
        }
    }

    void write(Environment& env, size_t numFrames, const sample_t* src)
    {
        if (isConnected()) {
            AudioBus* bus = env.audioBus(busId());

            if (bus != nullptr) {
                const Epoch epoch = env.epoch();
                std::lock_guard<AudioBus::Lock> lock(bus->lock());
                if ((type() != kReplaceOut) && (bus->epoch() == epoch)) {
                    // Accumulate
                    sample_t* dst = bus->data();
                    for (size_t i=0; i < numFrames; i++) {
                        dst[i] += src[i];
                    }
                } else {
                    // Copy
                    memcpy(bus->data(), src, numFrames * sizeof(sample_t));
                    bus->setEpoch(epoch);
                }
            }
        }
    }

private:
    size_t      m_offset;
    sample_t*   m_buffer;
};

class Synth : public Node
{
protected:
    enum Flags
    {
        kAudioInputConnectionsChanged
      , kAudioOutputConnectionsChanged
      , kControlInputConnectionsChanged
      , kControlOutputConnectionsChanged
      , kHasTriggerInput
    };

    Synth( Environment& env
         , Group* target
         , AddAction addAction
         , const SynthDef& synthDef
         , OSC::Server::ArgStream controls
         , OSC::Server::ArgStream args
         , size_t synthOffset
         , size_t audioInputConnectionsOffset
         , size_t audioOutputConnectionsOffset
         , size_t controlBufferOffset
         , size_t audioBufferOffset
         , size_t audioBufferSize
         );
    ~Synth();

public:
    static Synth* construct(Environment& env, Group* target, Node::AddAction addAction, const SynthDef& synthDef, OSC::Server::ArgStream controls, OSC::Server::ArgStream args);

    virtual bool isSynth() const override { return true; }

    //* Return this synth's SynthDef.
    const SynthDef& synthDef() const { return m_synthDef; }

    //* Return number of audio inputs.
    size_t numAudioInputs() const { return synthDef().numAudioInputs(); }

    //* Map input to bus.
    void mapInput(size_t input, const AudioBusId& busId, InputConnectionType type);

    //* Return number of audio outputs.
    size_t numAudioOutputs() const { return synthDef().numAudioOutputs(); }

    //* Map output to bus.
    void mapOutput(size_t output, const AudioBusId& busId, OutputConnectionType type);

    typedef boost::intrusive::list<AudioInputConnection>  AudioInputConnections;
    typedef boost::intrusive::list<AudioOutputConnection> AudioOutputConnections;
    // typedef boost::container::vector<Connection<ControlBus, InputConnectionType> > ControlInputConnections;
    // typedef boost::container::vector<Connection<ControlBus, OutputConnectionType> > ControlOutputConnections;

    size_t numControlInputs() const { return synthDef().numControlInputs(); }
    size_t numControlOutputs() const { return synthDef().numControlOutputs(); }

    float controlInput(size_t index) const
    {
        BOOST_ASSERT_MSG( index < numControlInputs(), "control input index out of range" );
        return m_controlBuffers[index];
    }

    float& controlInput(size_t index)
    {
        BOOST_ASSERT_MSG( index < numControlInputs(), "control input index out of range" );
        return m_controlBuffers[index];
    }

    float controlOutput(size_t index) const
    {
        BOOST_ASSERT_MSG( index < numControlOutputs(), "control output index out of range" );
        return m_controlBuffers[numControlInputs() + index];
    }

    /// Sample offset for sample accurate synth scheduling.
    size_t sampleOffset() const { return 0; }

    /// Sets up inputs and outputs and calls compute.
    virtual void process(size_t numFrames);

private:
    const SynthDef&         m_synthDef;
    std::bitset<32>         m_flags;
    Methcla_Synth*          m_synth;
    AudioInputConnections   m_audioInputConnections;
    AudioOutputConnections  m_audioOutputConnections;
    sample_t*               m_controlBuffers;
    sample_t*               m_audioBuffers;
};

}; };

#endif // METHCLA_AUDIO_SYNTH_HPP_INCLUDED
<|endoftext|>


<commit_before>#include "wave/header.h"

#include "wave/header/riff_header.h"

namespace wave {
  Error Header::Init(std::ifstream* stream, uint64_t position) {
    position_ = position;
    if (!stream->is_open()) {
      return Error::kNotOpen;
    }

    // read chunk ID
    auto chunk_id_size = 4;
    stream->seekg(position_, std::ios::beg);
    char result[chunk_id_size];
    stream->read(result, chunk_id_size * sizeof(char));
    id_ = std::string(result, chunk_id_size);

    // and size
    stream->read(reinterpret_cast<char*>(&size_), sizeof(uint32_t));
    size_ += chunk_id_size * sizeof(char) + sizeof(uint32_t);

    return Error::kNoError;
  }

std::string Header::chunk_id() const {
  return id_;
}

uint32_t Header::chunk_size() const {
  if (chunk_id() == "RIFF") {
    return sizeof(wave::RIFFHeader);
  }
  return size_;
}

uint64_t Header::position() const {
  return position_;
}
};  // namespace wave
<commit_msg>Fix error on windows<commit_after>#include "wave/header.h"

#include "wave/header/riff_header.h"

namespace wave {
  Error Header::Init(std::ifstream* stream, uint64_t position) {
    position_ = position;
    if (!stream->is_open()) {
      return Error::kNotOpen;
    }

    // read chunk ID
    const auto chunk_id_size = 4;
    stream->seekg(position_, std::ios::beg);
    char result[chunk_id_size];
    stream->read(result, chunk_id_size * sizeof(char));
    id_ = std::string(result, chunk_id_size);

    // and size
    stream->read(reinterpret_cast<char*>(&size_), sizeof(uint32_t));
    size_ += chunk_id_size * sizeof(char) + sizeof(uint32_t);

    return Error::kNoError;
  }

std::string Header::chunk_id() const {
  return id_;
}

uint32_t Header::chunk_size() const {
  if (chunk_id() == "RIFF") {
    return sizeof(wave::RIFFHeader);
  }
  return size_;
}

uint64_t Header::position() const {
  return position_;
}
};  // namespace wave
<|endoftext|>


<commit_before>/*
 * bacteria-core, core for cellular automaton
 * Copyright (C) 2016 Pavel Dolgov
 *
 * See the LICENSE file for terms of use.
 */

#include <boost/test/unit_test.hpp>

#include "CoreConstants.hpp"
#include "CoreGlobals.hpp"
#include "Creator.hpp"

static void baseModelChecks(
    ModelPtr model,
    int width,
    int height,
    int bacteria_number
) {
    BOOST_REQUIRE(model->getWidth() == width);
    BOOST_REQUIRE(model->getHeight() == height);
    BOOST_REQUIRE(model->getBacteriaNumber(0) == bacteria_number);
}

BOOST_AUTO_TEST_CASE (create_special_model_test) {
    Implementation::Unit unit(
        Abstract::Point(0, 0),
        DEFAULT_MASS,
        0,
        0,
        0
    );
    Units units(1, unit);
    ModelPtr model = Creator::createSpecialModel(
        MIN_WIDTH,
        MIN_HEIGHT,
        1,
        units
    );
    baseModelChecks(model, MIN_WIDTH, MIN_HEIGHT, 1);
    BOOST_REQUIRE(model->getCoordinates(0, 0) == unit.coordinates);
    BOOST_REQUIRE(model->getMass(0, 0) == unit.mass);
    BOOST_REQUIRE(model->getDirection(0, 0) == unit.direction);
    BOOST_REQUIRE(model->getInstruction(0, 0) == unit.instruction);
}

BOOST_AUTO_TEST_CASE (create_model_test) {
    ModelPtr model = Creator::createModel(
        MIN_WIDTH,
        MIN_HEIGHT,
        1,
        1
    );
    baseModelChecks(model, MIN_WIDTH, MIN_HEIGHT, 1);
}
<commit_msg>Unit tests (creator): add create_core_objects_test<commit_after>/*
 * bacteria-core, core for cellular automaton
 * Copyright (C) 2016 Pavel Dolgov
 *
 * See the LICENSE file for terms of use.
 */

#include <fstream>

#include <QStringList>

#include <boost/test/unit_test.hpp>

#include "CoreConstants.hpp"
#include "CoreGlobals.hpp"
#include "Creator.hpp"

static void baseModelChecks(
    ModelPtr model,
    int width,
    int height,
    int bacteria_number
) {
    BOOST_REQUIRE(model->getWidth() == width);
    BOOST_REQUIRE(model->getHeight() == height);
    BOOST_REQUIRE(model->getBacteriaNumber(0) == bacteria_number);
}

BOOST_AUTO_TEST_CASE (create_special_model_test) {
    Implementation::Unit unit(
        Abstract::Point(0, 0),
        DEFAULT_MASS,
        0,
        0,
        0
    );
    Units units(1, unit);
    ModelPtr model = Creator::createSpecialModel(
        MIN_WIDTH,
        MIN_HEIGHT,
        1,
        units
    );
    baseModelChecks(model, MIN_WIDTH, MIN_HEIGHT, 1);
    BOOST_REQUIRE(model->getCoordinates(0, 0) == unit.coordinates);
    BOOST_REQUIRE(model->getMass(0, 0) == unit.mass);
    BOOST_REQUIRE(model->getDirection(0, 0) == unit.direction);
    BOOST_REQUIRE(model->getInstruction(0, 0) == unit.instruction);
}

BOOST_AUTO_TEST_CASE (create_model_test) {
    ModelPtr model = Creator::createModel(
        MIN_WIDTH,
        MIN_HEIGHT,
        1,
        1
    );
    baseModelChecks(model, MIN_WIDTH, MIN_HEIGHT, 1);
}

BOOST_AUTO_TEST_CASE (create_core_objects_test) {
    ModelPtr model = Creator::createModel(
        MIN_WIDTH,
        MIN_HEIGHT,
        1,
        1
    );
    ChangerPtrs changers;
    std::ofstream bact_file("eat.bact");
    if (bact_file.is_open()) {
        bact_file << "eat\n";
        bact_file.close();
    } else {
        std::cerr << "Error: Unable to open script file." << std::endl;
    }
    QStringList scripts(QString("eat.bact"));
    InterpreterPtr interpreter = Creator::createCoreObjects(
        model,
        scripts,
        changers
    );
    BOOST_REQUIRE(changers[0]->getBacteriaNumber() == 1);
    interpreter->makeMove(*(changers[0].data()), 0);
    BOOST_REQUIRE(model->getMass(0, 0) == DEFAULT_MASS + EAT_MASS);
}
<|endoftext|>


<commit_before><commit_msg>Remove unused local from CreateAttachment<commit_after><|endoftext|>


<commit_before>/**
 * @file steepest_descent.hpp
 * @author Marcus Edel
 *
 * Implementation of the steepest descent optimizer. The method of steepest
 * descent, also called the gradient descent method, is used to find the
 * nearest local minimum of a function which the assumtion that the gradient of
 * the function can be computed.
 */
#ifndef __MLPACK_METHODS_ANN_OPTIMIZER_STEEPEST_DESCENT_HPP
#define __MLPACK_METHODS_ANN_OPTIMIZER_STEEPEST_DESCENT_HPP

#include <mlpack/core.hpp>

namespace mlpack {
namespace ann /** Artificial Neural Network. */ {

/**
 * This class is used to update the weights using steepest descent.
 *
 * @tparam DataType Type of input data (should be arma::mat,
 * arma::spmat or arma::cube).
 */
template<typename DecomposableFunctionType, typename DataType>
class SteepestDescent
{
 public:
  /**
   * Construct the SteepestDescent optimizer with the given function and
   * parameters.
   *
   * @param function Function to be optimized (minimized).
   * @param lr The learning rate coefficient.
   * @param mom The momentum coefficient.
   */
  SteepestDescent(DecomposableFunctionType& function,
                  const double lr = 1,
                  const double mom = 0) :
      function(function),
      lr(lr),
      mom(mom),
      momWeights(function.Weights())

  {
    // Nothing to do here.
  }

  /**
   * Optimize the given function using steepest descent.
   */
  void Optimize()
  {
    if (momWeights.n_elem == 0)
    {
      momWeights = function.Weights();
      momWeights.zeros();
    }

    Optimize(function.Weights(), gradient, momWeights);
  }

  /*
   * Sum up all gradients and store the results in the gradients storage.
   */
  void Update()
  {
    if (gradient.n_elem != 0)
    {
      DataType outputGradient;
      function.Gradient(outputGradient);
      gradient += outputGradient;
    }
    else
    {
      function.Gradient(gradient);
    }
  }

  /*
   * Reset the gradient storage.
   */
  void Reset()
  {
    gradient.zeros();
  }

 private:
  /** Optimize the given function using steepest descent.
   *
   * @param weights The weights that should be updated.
   * @param gradient The gradient used to update the weights.
   * @param gradient The moving average over the root mean squared gradient used
   *    to update the weights.
   */
  template<typename eT>
  void Optimize(arma::Cube<eT>& weights,
                arma::Cube<eT>& gradient,
                arma::Cube<eT>& momWeights)
  {
    for (size_t s = 0; s < weights.n_slices; s++)
      Optimize(weights.slice(s), gradient.slice(s), momWeights.slice(s));
  }

  /**
   * Optimize the given function using steepest descent.
   *
   * @param weights The weights that should be updated.
   * @param gradient The gradient used to update the weights.
   * @param gradient The moving average over the root mean squared gradient used
   *    to update the weights.
   */
  template<typename eT>
  void Optimize(arma::Mat<eT>& weights,
                arma::Mat<eT>& gradient,
                arma::Mat<eT>& momWeights)
  {
    if (mom > 0)
    {
      momWeights *= mom;
      momWeights += (lr * gradient);
      weights -= momWeights;
    }
    else
    {
      weights -= lr * gradient;
    }
  }

  //! The instantiated function.
  DecomposableFunctionType& function;

  //! The value used as learning rate.
  const double lr;

  //! The value used as momentum.
  const double mom;

  //! Momentum matrix.
  DataType momWeights;

  //! The current gradient.
  DataType gradient;
}; // class SteepestDescent

}; // namespace ann
}; // namespace mlpack

#endif
<commit_msg>Use the new optimizer interface.<commit_after>/**
 * @file steepest_descent.hpp
 * @author Marcus Edel
 *
 * Implementation of the steepest descent optimizer. The method of steepest
 * descent, also called the gradient descent method, is used to find the
 * nearest local minimum of a function which the assumtion that the gradient of
 * the function can be computed.
 */
#ifndef __MLPACK_METHODS_ANN_OPTIMIZER_STEEPEST_DESCENT_HPP
#define __MLPACK_METHODS_ANN_OPTIMIZER_STEEPEST_DESCENT_HPP

#include <mlpack/core.hpp>

namespace mlpack {
namespace ann /** Artificial Neural Network. */ {

/**
 * This class is used to update the weights using steepest descent.
 *
 * @tparam DataType Type of input data (should be arma::mat,
 * arma::spmat or arma::cube).
 */
template<typename DecomposableFunctionType, typename DataType>
class SteepestDescent
{
 public:
  /**
   * Construct the SteepestDescent optimizer with the given function and
   * parameters.
   *
   * @param function Function to be optimized (minimized).
   * @param lr The learning rate coefficient.
   * @param mom The momentum coefficient.
   */
  SteepestDescent(DecomposableFunctionType& function,
                  const double lr = 0.5,
                  const double mom = 0) :
      function(function),
      lr(lr),
      mom(mom),
      momWeights(function.Weights())

  {
    // Nothing to do here.
  }

  /**
   * Optimize the given function using steepest descent.
   */
  void Optimize()
  {
    if (momWeights.n_elem == 0)
    {
      momWeights = function.Weights();
      momWeights.zeros();
    }

    Optimize(function.Weights(), gradient, momWeights);
  }

  /*
   * Sum up all gradients and store the results in the gradients storage.
   */
  void Update()
  {
    if (gradient.n_elem != 0)
    {
      DataType outputGradient = function.Gradient();
      gradient += outputGradient;
    }
    else
    {
      gradient = function.Gradient();
    }
  }

  /*
   * Reset the gradient storage.
   */
  void Reset()
  {
    gradient.zeros();
  }

 private:
  /** Optimize the given function using steepest descent.
   *
   * @param weights The weights that should be updated.
   * @param gradient The gradient used to update the weights.
   * @param gradient The moving average over the root mean squared gradient used
   *    to update the weights.
   */
  template<typename eT>
  void Optimize(arma::Cube<eT>& weights,
                arma::Cube<eT>& gradient,
                arma::Cube<eT>& momWeights)
  {
    for (size_t s = 0; s < weights.n_slices; s++)
      Optimize(weights.slice(s), gradient.slice(s), momWeights.slice(s));
  }

  /**
   * Optimize the given function using steepest descent.
   *
   * @param weights The weights that should be updated.
   * @param gradient The gradient used to update the weights.
   * @param gradient The moving average over the root mean squared gradient used
   *    to update the weights.
   */
  template<typename eT>
  void Optimize(arma::Mat<eT>& weights,
                arma::Mat<eT>& gradient,
                arma::Mat<eT>& momWeights)
  {
    if (mom > 0)
    {
      momWeights *= mom;
      momWeights += (lr * gradient);
      weights -= momWeights;
    }
    else
    {
      weights -= lr * gradient;
    }
  }

  //! The instantiated function.
  DecomposableFunctionType& function;

  //! The value used as learning rate.
  const double lr;

  //! The value used as momentum.
  const double mom;

  //! Momentum matrix.
  DataType momWeights;

  //! The current gradient.
  DataType gradient;
}; // class SteepestDescent

}; // namespace ann
}; // namespace mlpack

#endif
<|endoftext|>


<commit_before>#include "RTClib.h"
#include "accel.h"
#include "daytimes.h"
#include "ledctrl.h"
#include "m0_hf_pwm.h"
#include "mqtt_client.h"
#include "netcfg.h"
#include "proxim.h"
#include "solenoids.h"
#include "utils.h"
#include "watchdog_timer.h"

// For float to string formatting
#include <avr/dtostrf.h>

// Where to get the battery voltage
#define VBATPIN A7

// Customization for acceptable daylight times
static const TimeSpan margin_after_sunrise(0, 0, 45, 0);
static const TimeSpan margin_before_sunset(0, 2, 0, 0);

static const unsigned long LOOP_PERIOD_MS = 25;

// global objects...
RTC_DS3231 rtc;
Accel accel_sensor;
Proxim proxim_sensor;
Solenoids& sol_actuators = Solenoids::Instance();
LedCtrl& status_led = LedCtrl::Instance();
WiFiClient wifi_client;
MQTT_Client mqtt_client(wifi_client, status_led);

// interupts function prototypes
void proximThreshold() { proxim_sensor.new_state = true; }

void accelReady() { accel_sensor.data_ready = true; }

void setup() {
  wdt_configure(11);

  // HF PWM
  pwm_configure();

  // let things stabilize before pulling too much current
  // not necessary, but surprise the developer less also
  delay(1000);

  // Force unjam, no matter what, just in case we rebooted
  // Also this says Hi to the world
  sol_actuators.unjam();

  // start in unkown state
  status_led.warning();

#ifdef USE_SERIAL
  Serial.begin(115200);
  while (!Serial) {
    ;  // wait for serial port to connect to start the app
  }
// Serial.print("sizeof(int)=");
// Serial.println(sizeof(int));
#endif

  //
  // Accelerometer setup
  //
  if (!accel_sensor.begin(0x18)) {
    PRINTLN("Couldnt start accelerometer!");
    while (1)
      ;
  }
  PRINTLN("LIS3DH found.");

  // configure sensor
  accel_sensor.setDataRate(LIS3DH_DATARATE_10_HZ);
  accel_sensor.setRange(LIS3DH_RANGE_2_G);

  // attach hardware interrupt
  pinMode(A2, INPUT_PULLUP);
  attachInterrupt(A2, accelReady, RISING);
  delay(1);             // for some reason, this delay is CRITICAL!
  accel_sensor.read();  // read reset the signal --> start interrupts

  //
  // Proximity sensor setup
  //
  if (!proxim_sensor.begin()) {
    PRINTLN("Proximity sensor not found!");
    while (1)
      ;
  }
  PRINTLN("VCNL4010 found.");

  // configure sensor
  proxim_sensor.setModulatorFrequency(VCNL4010_390K625);
  proxim_sensor.setLEDcurrent(16);
  proxim_sensor.setProximityRate(VCNL4010_62_5Hz);

  // prepare hardware interrupt
  pinMode(A1, INPUT_PULLUP);
  attachInterrupt(A1, proximThreshold, FALLING);
  delay(1);
  proxim_sensor.setProximThresholdInterrupt(3);
  proxim_sensor.setLowThreshold(0);
  proxim_sensor.setHighThreshold(Proxim::THRESHOLD);
  proxim_sensor.activateProximityThresholdInterrupt();

  // RTC
  if (!rtc.begin()) {
    PRINTLN("Couldn't find RTC!");
    while (1)
      ;
  }

  // Configure pins for Adafruit ATWINC1500 Feather
  WiFi.setPins(8, 7, 4, 2);
  // Check for the presence of the shield
  PRINTLN("Connecting to the Wifi module...");
  if (WiFi.status() == WL_NO_SHIELD) {
    PRINTLN("WiFi shield not present");
    return;  // don't continue
  }

  mqtt_client.connect_wifi(MY_WIFI_SSID, MY_WIFI_PASS);
  status_led.warning();  // not done yet with setup!
  mqtt_client.setServer(MQTT_SERVER, MQTT_PORT);
  mqtt_client.connect_client();
  status_led.warning();  // not done yet with setup!

  PRINTLN("MQTT client connected.");
  const char* msg = "Catdoor v2 started";
  DateTime utc_time = rtc.now();
  unsigned int now = millis();
  DateTime local_time = utc_time.getLocalTime(TIME_ZONE_OFFSET);
  mqtt_client.sync_time(local_time, now);
  mqtt_client.publish_timed_msg(now, TOPIC_MESSAGE, msg);
  // start by flashing like in the darkness..
  status_led.alive();

  wdt_configure(4);
}

void loop() {
  static bool cat_exiting = false;
  static bool daylight = false;
  static bool rtc_read = true;
  static unsigned long last_time = millis();
  static unsigned long last_unjam = millis();
  unsigned long now = millis();
  unsigned long elapsed;
  unsigned long sleep_ms;
  static Solenoids::state_t prev_actuators_state = Solenoids::OFF;

  if ((now - last_time) > 10 * 1000) {
    if (rtc_read) {
      // Check RC every 20s
      DateTime ltime = rtc.now().getLocalTime(TIME_ZONE_OFFSET);
      mqtt_client.sync_time(ltime, now);
      uint16_t day = ltime.yDay();
      if (day == 366)
        day = 1;  // We will be one day offset for all leap years...
      DateTime sunrise(ltime.year(), ltime.month(), ltime.day(),
                       sunset_sunrise_times[day - 1][0],
                       sunset_sunrise_times[day - 1][1], 0, TIME_ZONE_OFFSET);
      DateTime sunset(ltime.year(), ltime.month(), ltime.day(),
                      sunset_sunrise_times[day - 1][2],
                      sunset_sunrise_times[day - 1][3], 0, TIME_ZONE_OFFSET);
      DateTime morning = sunrise + margin_after_sunrise;
      DateTime afternoon = sunset - margin_before_sunset;
      if (false || (morning < ltime && ltime < afternoon)) {
        status_led.ok();  // safe to repeat without breaking the pattern
        if (!daylight) {
          daylight = true;
          mqtt_client.publish_timed_msg(now, TOPIC_MESSAGE, "UNLOCKED");
        }
      }  // if daylight
      else {
        status_led.alive();  // safe to repeat without breaking the pattern
        if (daylight) {
          daylight = false;
          mqtt_client.publish_timed_msg(now, TOPIC_MESSAGE, "LOCKED");
        }
      }  // else daylight
      rtc_read = false;
      mqtt_client.publish_timed_msg(now, TOPIC_HEARTBEAT,
                                    daylight ? "DAYLIGHT" : "DARK");
    } else {
      // alternate with reading the battery voltage
      float measuredvbat = analogRead(VBATPIN);
      measuredvbat *= 2;     // we divided by 2, so multiply back
      measuredvbat *= 3.3;   // Multiply by 3.3V, our reference voltage
      measuredvbat /= 1024;  // convert to voltage
      char num[6];
      dtostrf(measuredvbat, 5, 2, num);
      char str[12];
      sprintf(str, "VBAT=%s", num);
      mqtt_client.publish_timed_msg(now, TOPIC_BATTERY_V, str);
      rtc_read = true;
    }

    last_time = now;
  }  // if 10s

  // Process accelerometer
  if (accel_sensor.data_ready) {
    accel_sensor.process();
    if (accel_sensor.new_state) {
      PRINTLN(ACCEL_STATES_NAMES[(uint8_t)accel_sensor.state]);
      accel_sensor.new_state = false;
      mqtt_client.publish_timed_msg(
          now, TOPIC_DOORSTATE,
          ACCEL_STATES_NAMES[(uint8_t)accel_sensor.state]);
    }
  }

  // Check if cat is in front of door
  if (proxim_sensor.new_state) {
    proxim_sensor.process();
    if (proxim_sensor.state == Proxim::CAT) {
      PRINTLN("CAT");
      mqtt_client.publish_timed_msg(now, TOPIC_PROXIMITY, "CAT");
      if (daylight && accel_sensor.state == Accel::CLOSED) {
        // Retract the door locks!
        if (sol_actuators.state() == Solenoids::OFF) {
          sol_actuators.open();
          mqtt_client.publish_timed_msg(now, TOPIC_SOLENOIDS, "RETRACTED");
        }
      }
    } else {
      PRINTLN("CLEAR");
      mqtt_client.publish_timed_msg(now, TOPIC_PROXIMITY, "CLEAR");
    }
  }

  // Mark that cat is going out (to release the solenoids later)
  if (sol_actuators.state() == Solenoids::ON &&
      accel_sensor.state == Accel::OPEN_OUT) {
    cat_exiting = true;
  }

  // Release solenoids if cat finished exiting
  if (cat_exiting && accel_sensor.state == Accel::CLOSED &&
      sol_actuators.state() == Solenoids::ON &&
      proxim_sensor.state == Proxim::CLEAR) {
    sol_actuators.release();
    mqtt_client.publish_timed_msg(now, TOPIC_SOLENOIDS, "RELEASE");
    cat_exiting = false;
  }

  // Detect jammed condition and try to resolve it
  if (accel_sensor.state == Accel::JAMMED &&
      sol_actuators.state() == Solenoids::OFF) {
    if ((now - last_unjam) > Solenoids::COOLDOWN_DURATION_MS) {
      last_unjam = now;
      sol_actuators.unjam();
      mqtt_client.publish_timed_msg(now, TOPIC_SOLENOIDS, "UNJAM");
    }
  }

  // Check a hot release
  if (sol_actuators.state() != prev_actuators_state) {
    if (prev_actuators_state == Solenoids::ON &&
        sol_actuators.state() == Solenoids::HOT) {
      mqtt_client.publish_timed_msg(now, TOPIC_SOLENOIDS, "HOT_RELEASE");
    }
    prev_actuators_state = sol_actuators.state();
  }

  // Let the MQTT client do some work
  mqtt_client.loop();

  elapsed = millis() - now;
  if (elapsed > LOOP_PERIOD_MS) {
    PRINT("==== warning, loop overrun: ");
    PRINTLN(elapsed);
    mqtt_client.publish_timed_msg(now, TOPIC_MESSAGE, "LOOP OVERRUN");
    sleep_ms = 0;
  } else {
    sleep_ms = LOOP_PERIOD_MS - elapsed;
  }

  // Say we are still alive!
  wdt_reset();

  // Loop is variable period, but we do not really care...
  delay(sleep_ms);
}
<commit_msg>Added a solenoid release condition if the cat is not well decided + some tuning<commit_after>#include "RTClib.h"
#include "accel.h"
#include "daytimes.h"
#include "ledctrl.h"
#include "m0_hf_pwm.h"
#include "mqtt_client.h"
#include "netcfg.h"
#include "proxim.h"
#include "solenoids.h"
#include "utils.h"
#include "watchdog_timer.h"

// For float to string formatting
#include <avr/dtostrf.h>

// Where to get the battery voltage
#define VBATPIN A7

// Customization for acceptable daylight times
static const TimeSpan margin_after_sunrise(0, 0, 45, 0);
static const TimeSpan margin_before_sunset(0, 2, 0, 0);

static const unsigned long LOOP_PERIOD_MS = 25;

// global objects...
RTC_DS3231 rtc;
Accel accel_sensor;
Proxim proxim_sensor;
Solenoids& sol_actuators = Solenoids::Instance();
LedCtrl& status_led = LedCtrl::Instance();
WiFiClient wifi_client;
MQTT_Client mqtt_client(wifi_client, status_led);

// interupts function prototypes
void proximThreshold() { proxim_sensor.new_state = true; }

void accelReady() { accel_sensor.data_ready = true; }

void setup() {
  wdt_configure(11);

  // HF PWM
  pwm_configure();

  // let things stabilize before pulling too much current
  // not necessary, but surprise the developer less also
  delay(1000);

  // Force unjam, no matter what, just in case we rebooted
  // Also this says Hi to the world
  sol_actuators.unjam();

  // start in unkown state
  status_led.warning();

#ifdef USE_SERIAL
  Serial.begin(115200);
  while (!Serial) {
    ;  // wait for serial port to connect to start the app
  }
// Serial.print("sizeof(int)=");
// Serial.println(sizeof(int));
#endif

  //
  // Accelerometer setup
  //
  if (!accel_sensor.begin(0x18)) {
    PRINTLN("Couldnt start accelerometer!");
    while (1)
      ;
  }
  PRINTLN("LIS3DH found.");

  // configure sensor
  accel_sensor.setDataRate(LIS3DH_DATARATE_10_HZ);
  accel_sensor.setRange(LIS3DH_RANGE_2_G);

  // attach hardware interrupt
  pinMode(A2, INPUT_PULLUP);
  attachInterrupt(A2, accelReady, RISING);
  delay(1);             // for some reason, this delay is CRITICAL!
  accel_sensor.read();  // read reset the signal --> start interrupts

  //
  // Proximity sensor setup
  //
  if (!proxim_sensor.begin()) {
    PRINTLN("Proximity sensor not found!");
    while (1)
      ;
  }
  PRINTLN("VCNL4010 found.");

  // configure sensor
  proxim_sensor.setModulatorFrequency(VCNL4010_390K625);
  proxim_sensor.setLEDcurrent(16);
  proxim_sensor.setProximityRate(VCNL4010_62_5Hz);

  // prepare hardware interrupt
  pinMode(A1, INPUT_PULLUP);
  attachInterrupt(A1, proximThreshold, FALLING);
  delay(1);
  proxim_sensor.setProximThresholdInterrupt(3);
  proxim_sensor.setLowThreshold(0);
  proxim_sensor.setHighThreshold(Proxim::THRESHOLD);
  proxim_sensor.activateProximityThresholdInterrupt();

  // RTC
  if (!rtc.begin()) {
    PRINTLN("Couldn't find RTC!");
    while (1)
      ;
  }

  // Configure pins for Adafruit ATWINC1500 Feather
  WiFi.setPins(8, 7, 4, 2);
  // Check for the presence of the shield
  PRINTLN("Connecting to the Wifi module...");
  if (WiFi.status() == WL_NO_SHIELD) {
    PRINTLN("WiFi shield not present");
    return;  // don't continue
  }

  mqtt_client.connect_wifi(MY_WIFI_SSID, MY_WIFI_PASS);
  status_led.warning();  // not done yet with setup!
  mqtt_client.setServer(MQTT_SERVER, MQTT_PORT);
  mqtt_client.connect_client();
  status_led.warning();  // not done yet with setup!

  PRINTLN("MQTT client connected.");
  const char* msg = "Catdoor v2 started";
  DateTime utc_time = rtc.now();
  unsigned int now = millis();
  DateTime local_time = utc_time.getLocalTime(TIME_ZONE_OFFSET);
  mqtt_client.sync_time(local_time, now);
  mqtt_client.publish_timed_msg(now, TOPIC_MESSAGE, msg);
  // start by flashing like in the darkness..
  status_led.alive();

  wdt_configure(4);
}

void loop() {
  static bool cat_exiting = false;
  static bool daylight = false;
  static bool rtc_read = true;
  static unsigned long last_time = millis();
  static unsigned long last_unjam = last_time;
  static unsigned long door_clear_time = last_time;
  unsigned long now = millis();
  unsigned long elapsed;
  unsigned long sleep_ms;
  static Solenoids::state_t prev_actuators_state = Solenoids::OFF;
  static char buffer[24];

  if ((now - last_time) > 10 * 1000) {
    if (rtc_read) {
      // Check RC every 20s
      DateTime ltime = rtc.now().getLocalTime(TIME_ZONE_OFFSET);
      mqtt_client.sync_time(ltime, now);
      uint16_t day = ltime.yDay();
      if (day == 366)
        day = 1;  // We will be one day offset for all leap years...
      DateTime sunrise(ltime.year(), ltime.month(), ltime.day(),
                       sunset_sunrise_times[day - 1][0],
                       sunset_sunrise_times[day - 1][1], 0, TIME_ZONE_OFFSET);
      DateTime sunset(ltime.year(), ltime.month(), ltime.day(),
                      sunset_sunrise_times[day - 1][2],
                      sunset_sunrise_times[day - 1][3], 0, TIME_ZONE_OFFSET);
      DateTime morning = sunrise + margin_after_sunrise;
      DateTime afternoon = sunset - margin_before_sunset;
      if (false || (morning < ltime && ltime < afternoon)) {
        status_led.ok();  // safe to repeat without breaking the pattern
        if (!daylight) {
          daylight = true;
          sprintf(buffer, "%s %d:%d", "UNLOCKED", afternoon.hour(),
                  afternoon.minute());
          mqtt_client.publish_timed_msg(now, TOPIC_MESSAGE, buffer);
        }
      }  // if daylight
      else {
        status_led.alive();  // safe to repeat without breaking the pattern
        if (daylight) {
          daylight = false;
          sprintf(buffer, "%s %d:%d", "LOCKED", morning.hour(),
                  morning.minute());
          mqtt_client.publish_timed_msg(now, TOPIC_MESSAGE, buffer);
        }
      }  // else daylight
      rtc_read = false;
      mqtt_client.publish_timed_msg(now, TOPIC_HEARTBEAT,
                                    daylight ? "DAYLIGHT" : "DARK");
    } else {
      // alternate with reading the battery voltage
      float measuredvbat = analogRead(VBATPIN);
      measuredvbat *= 2;     // we divided by 2, so multiply back
      measuredvbat *= 3.3;   // Multiply by 3.3V, our reference voltage
      measuredvbat /= 1024;  // convert to voltage
      char num[6];
      dtostrf(measuredvbat, 5, 2, num);
      // char str[12];
      // sprintf(str, "VBAT %s", num);
      mqtt_client.publish_timed_msg(now, TOPIC_BATTERY_V, num);
      rtc_read = true;
    }

    last_time = now;
  }  // if 10s

  // Process accelerometer
  if (accel_sensor.data_ready) {
    accel_sensor.process();
    if (accel_sensor.new_state) {
      PRINTLN(ACCEL_STATES_NAMES[(uint8_t)accel_sensor.state]);
      accel_sensor.new_state = false;
      mqtt_client.publish_timed_msg(
          now, TOPIC_DOORSTATE,
          ACCEL_STATES_NAMES[(uint8_t)accel_sensor.state]);
    }
  }

  // Check if cat is in front of door
  if (proxim_sensor.new_state) {
    proxim_sensor.process();
    if (proxim_sensor.state == Proxim::CAT) {
      PRINTLN("CAT");
      mqtt_client.publish_timed_msg(now, TOPIC_PROXIMITY, "CAT");
      if (daylight && accel_sensor.state == Accel::CLOSED) {
        // Retract the door locks!
        if (sol_actuators.state() == Solenoids::OFF) {
          sol_actuators.open();
          mqtt_client.publish_timed_msg(now, TOPIC_SOLENOIDS, "RETRACTED");
        }
      }
    } else {
      PRINTLN("CLEAR");
      door_clear_time = now;
      mqtt_client.publish_timed_msg(now, TOPIC_PROXIMITY, "CLEAR");
    }
  }

  // Relase if the cat give up after 12s (to avoid a HOT_RELEASE much later)
  if (proxim_sensor.state == Proxim::CLEAR &&
      sol_actuators.state() == Solenoids::ON &&
      accel_sensor.state == Accel::CLOSED && (now - door_clear_time) > 12000) {
    sol_actuators.release();
    mqtt_client.publish_timed_msg(now, TOPIC_SOLENOIDS, "RELEASE");
  }

  // Mark that cat is going out (to release the solenoids later)
  if (sol_actuators.state() == Solenoids::ON &&
      accel_sensor.state == Accel::OPEN_OUT) {
    cat_exiting = true;
  }

  // Release solenoids if cat finished exiting
  if (cat_exiting && accel_sensor.state == Accel::CLOSED &&
      sol_actuators.state() == Solenoids::ON &&
      proxim_sensor.state == Proxim::CLEAR) {
    sol_actuators.release();
    mqtt_client.publish_timed_msg(now, TOPIC_SOLENOIDS, "RELEASE");
    cat_exiting = false;
  }

  // Detect jammed condition and try to resolve it
  if (accel_sensor.state == Accel::JAMMED &&
      sol_actuators.state() == Solenoids::OFF) {
    if ((now - last_unjam) > Solenoids::COOLDOWN_DURATION_MS) {
      last_unjam = now;
      sol_actuators.unjam();
      mqtt_client.publish_timed_msg(now, TOPIC_SOLENOIDS, "UNJAM");
    }
  }

  // Check a hot release
  if (sol_actuators.state() != prev_actuators_state) {
    if (prev_actuators_state == Solenoids::ON &&
        sol_actuators.state() == Solenoids::HOT) {
      mqtt_client.publish_timed_msg(now, TOPIC_SOLENOIDS, "HOT_RELEASE");
    }
    prev_actuators_state = sol_actuators.state();
  }

  // Let the MQTT client do some work
  mqtt_client.loop();

  elapsed = millis() - now;
  if (elapsed > LOOP_PERIOD_MS) {
    PRINT("==== warning, loop overrun: ");
    PRINTLN(elapsed);
    mqtt_client.publish_timed_msg(now, TOPIC_MESSAGE, "LOOP OVERRUN");
    sleep_ms = 0;
  } else {
    sleep_ms = LOOP_PERIOD_MS - elapsed;
  }

  // Say we are still alive!
  wdt_reset();

  // Loop is variable period, but we do not really care...
  delay(sleep_ms);
}
<|endoftext|>