[med-svn] [libsitplus] 01/02: Imported Upstream version 1.1.0

Andreas Tille tille at debian.org
Wed Aug 27 06:59:44 UTC 2014


This is an automated email from the git hooks/post-receive script.

tille pushed a commit to branch master
in repository libsitplus.

commit b052b07c757090c446eaeeff6c022e5281385a88
Author: Andreas Tille <tille at debian.org>
Date:   Wed Aug 27 08:39:46 2014 +0200

    Imported Upstream version 1.1.0
---
 .tx/config                                         |    9 +
 3rdparty/CMakeLists.txt                            |    5 +
 3rdparty/libconfig/AUTHORS                         |    5 +
 3rdparty/libconfig/CMakeLists.txt                  |   26 +
 3rdparty/libconfig/COPYING.LIB                     |  510 ++++
 3rdparty/libconfig/ChangeLog                       |  582 +++++
 3rdparty/libconfig/README                          |   58 +
 3rdparty/libconfig/README.sitplus                  |    3 +
 3rdparty/libconfig/TODO                            |   33 +
 3rdparty/libconfig/grammar.c                       | 2001 +++++++++++++++
 3rdparty/libconfig/grammar.h                       |  113 +
 3rdparty/libconfig/grammar.y                       |  389 +++
 3rdparty/libconfig/libconfig.c                     | 1595 ++++++++++++
 3rdparty/libconfig/libconfig.h                     |  321 +++
 3rdparty/libconfig/parsectx.h                      |   48 +
 3rdparty/libconfig/scanctx.c                       |  171 ++
 3rdparty/libconfig/scanctx.h                       |   62 +
 3rdparty/libconfig/scanner.c                       | 2362 ++++++++++++++++++
 3rdparty/libconfig/scanner.h                       |  326 +++
 3rdparty/libconfig/scanner.l                       |  190 ++
 3rdparty/libconfig/strbuf.c                        |   58 +
 3rdparty/libconfig/strbuf.h                        |   40 +
 3rdparty/libconfig/wincompat.h                     |   90 +
 3rdparty/wiiuse/CHANGELOG                          |  208 ++
 3rdparty/wiiuse/CMakeLists.txt                     |   58 +
 3rdparty/wiiuse/LICENSE                            |  620 +++++
 3rdparty/wiiuse/LICENSE_noncommercial              |  170 ++
 3rdparty/wiiuse/README                             |  155 ++
 3rdparty/wiiuse/README.sitplus                     |   72 +
 3rdparty/wiiuse/example-sdl/CMakeLists.txt         |   33 +
 3rdparty/wiiuse/example-sdl/sdl.c                  |  439 ++++
 3rdparty/wiiuse/example/CMakeLists.txt             |    5 +
 3rdparty/wiiuse/example/example.c                  |  546 +++++
 3rdparty/wiiuse/include/wiiuse.h                   |  805 ++++++
 3rdparty/wiiuse/src/CMakeLists.txt                 |  125 +
 3rdparty/wiiuse/src/balance_board.c                |  139 ++
 3rdparty/wiiuse/src/balance_board.h                |   53 +
 3rdparty/wiiuse/src/classic.c                      |  195 ++
 3rdparty/wiiuse/src/classic.h                      |   53 +
 3rdparty/wiiuse/src/definitions.h                  |   85 +
 3rdparty/wiiuse/src/dynamics.c                     |  231 ++
 3rdparty/wiiuse/src/dynamics.h                     |   56 +
 3rdparty/wiiuse/src/events.c                       |  837 +++++++
 3rdparty/wiiuse/src/events.h                       |   52 +
 3rdparty/wiiuse/src/guitar_hero_3.c                |  173 ++
 3rdparty/wiiuse/src/guitar_hero_3.h                |   62 +
 3rdparty/wiiuse/src/io.c                           |  276 +++
 3rdparty/wiiuse/src/io.h                           |   59 +
 3rdparty/wiiuse/src/io_nix.c                       |  272 +++
 3rdparty/wiiuse/src/io_win.c                       |  253 ++
 3rdparty/wiiuse/src/ir.c                           |  758 ++++++
 3rdparty/wiiuse/src/ir.h                           |   57 +
 3rdparty/wiiuse/src/motion_plus.c                  |  250 ++
 3rdparty/wiiuse/src/motion_plus.h                  |   23 +
 3rdparty/wiiuse/src/nunchuk.c                      |  235 ++
 3rdparty/wiiuse/src/nunchuk.h                      |   53 +
 3rdparty/wiiuse/src/os.h                           |   56 +
 3rdparty/wiiuse/src/wiiuse.c                       |  886 +++++++
 3rdparty/wiiuse/src/wiiuse_internal.h              |  261 ++
 AUTHORS                                            |    1 +
 CMakeLists.txt                                     |  568 +++++
 COPYING                                            |  674 ++++++
 Doxyfile.in                                        | 1419 +++++++++++
 LibSITPLUSConfig.cmake.in                          |  123 +
 NEWS                                               |   12 +
 README                                             |   38 +
 TODO                                               |    2 +
 cmake_modules/COPYING-CMAKE-SCRIPTS                |   22 +
 cmake_modules/FindGLIB2.cmake                      |  217 ++
 cmake_modules/FindLibConfig.cmake                  |   76 +
 cmake_modules/FindLibintl.cmake                    |   61 +
 cmake_modules/FindPOCO.cmake                       |  102 +
 cmake_modules/FindPkgMacros.cmake                  |  147 ++
 cmake_modules/FindPortMidi.cmake                   |   39 +
 cmake_modules/FindPotupdate.cmake                  |  178 ++
 cmake_modules/FindSDL_gfx.cmake                    |   75 +
 cmake_modules/FindTranslationTools.cmake           |  116 +
 cmake_modules/MacroLogFeature.cmake                |  134 +
 cmake_modules/README.txt                           |   10 +
 cmake_modules/update_pot_source_dependencies.cmake |   40 +
 doc/CMakeLists.txt                                 |   63 +
 doc/script_syntax.html                             |  776 ++++++
 doc/script_syntax.txt                              |  135 ++
 include/config.h.in                                |   44 +
 include/mod_camera/iplimagetype.h                  |   59 +
 include/mod_camera/roitype.h                       |  181 ++
 include/mod_midi/midi_types.h                      |  117 +
 include/mod_sdl/sdlsurfacetype.h                   |   85 +
 include/mod_wiimotes/wiimotes_types.h              |  438 ++++
 include/spcore/baseobj.h                           |  155 ++
 include/spcore/basetype.h                          |  267 ++
 include/spcore/basetypeimpl.h                      |  299 +++
 include/spcore/basictypes.h                        |  144 ++
 include/spcore/component.h                         |  630 +++++
 include/spcore/configuration.h                     |  158 ++
 include/spcore/conversion.h                        |   70 +
 include/spcore/coreruntime.h                       |  293 +++
 include/spcore/coreversion.h                       |   31 +
 include/spcore/iterator.h                          |   96 +
 include/spcore/language.h                          |  179 ++
 include/spcore/libimpexp.h                         |   46 +
 include/spcore/module.h                            |  146 ++
 include/spcore/pin.h                               |  189 ++
 include/spcore/pinimpl.h                           |  386 +++
 include/sphost/componenthelper.h                   |  141 ++
 include/sphost/configutils.h                       |   53 +
 include/sphost/langutils.h                         |   78 +
 include/sphost/libimpexp_sphost.h                  |   36 +
 include/sphost/paths.h                             |   83 +
 include/sphost/testcommon.h                        |   62 +
 include/widgets_base/containerbook.h               |  109 +
 include/widgets_base/containercollapsible.h        |  109 +
 include/widgets_base/containerpanel.h              |  111 +
 include/widgets_base/dialogcontainer.h             |  114 +
 include/widgets_base/libimpexp_widgetsbase.h       |   33 +
 include/widgets_base/mdichildcontainer.h           |  116 +
 po/CMakeLists.txt                                  |  250 ++
 po/LINGUAS                                         |    1 +
 po/README.txt                                      |    1 +
 po/libsitplus/POTFILES.sp.in                       |    0
 po/libsitplus/ca.po                                |  720 ++++++
 po/libsitplus/es.po                                |  721 ++++++
 po/libsitplus/gl.po                                |  714 ++++++
 po/libsitplus/libsitplus.pot                       |  711 ++++++
 sp/README.txt                                      |    1 +
 sp/examples/arguments/test_arguments.sps           |    5 +
 sp/examples/arguments/test_arguments_fail.sp       |    4 +
 sp/examples/arguments/test_arguments_fail2.sp      |    4 +
 sp/examples/arguments/test_arguments_fail3.sp      |    4 +
 .../arguments/test_arguments_fail_missing.sp       |   12 +
 .../arguments/test_arguments_fail_repeated.sp      |    5 +
 sp/examples/arguments/test_arguments_fail_twice.sp |   12 +
 .../arguments/test_arguments_fail_unexpected.sp    |    7 +
 sp/examples/arguments/test_arguments_i18n.sp       |   15 +
 sp/examples/arguments/test_arguments_main.sp       |   43 +
 sp/examples/basic_components/test_storage.sp       |   75 +
 sp/examples/camera_sdl/test_ipl2sdl.sp             |   30 +
 sp/examples/camera_sdl/test_ipl2sdl2.sp            |   27 +
 sp/examples/conditionals/test_conditionals1.sp     |   27 +
 sp/examples/conditionals/test_conditionals2.sp     |   10 +
 sp/examples/conditionals/test_conditionals3.sp     |   10 +
 sp/examples/conditionals/test_conditionals4.sp     |    6 +
 sp/examples/conditionals/test_conditionals5.sp     |    9 +
 sp/examples/conditionals/test_conditionals5.sps    |   17 +
 sp/examples/io/test_filebrowser.sp                 |   40 +
 sp/examples/io/test_textfiledump.sp                |   15 +
 sp/examples/layout/test_layouts.sp                 |   42 +
 sp/examples/print_dump/test_print_dump.sp          |    4 +
 sp/examples/widgets/test_choice.sp                 |   33 +
 sp/examples/widgets/test_collapsible.sp            |   22 +
 sp/examples/widgets/test_slider.sp                 |   60 +
 sp/examples/widgets/test_slider_log.sp             |   10 +
 src/CMakeLists.txt                                 |   19 +
 src/core/CMakeLists.txt                            |  109 +
 src/core/Doxyfile.in                               | 1419 +++++++++++
 src/core/TODO.txt                                  |    3 +
 src/core/basictypesimpl.cpp                        | 1012 ++++++++
 src/core/commoncomponents.h                        | 1064 ++++++++
 src/core/configurationimpl.h                       |  343 +++
 src/core/conversion.cpp                            |  145 ++
 src/core/coreruntimeimpl.cpp                       |  885 +++++++
 src/core/language.cpp                              |  306 +++
 src/core/tests/CMakeLists.txt                      |   63 +
 src/core/tests/test1.cpp                           |  149 ++
 src/core/tests/test_spcore_basic_types.cpp         |   94 +
 src/core/tests/test_spcore_component.cpp           |  147 ++
 src/core/tests/test_spcore_configuration.cpp       |  145 ++
 src/core/tests/test_spcore_runtime.cpp             |   27 +
 src/core/tests/test_spcore_smart_ptr.cpp           |   80 +
 src/core/tests/test_spcore_wx_main_thread.cpp      |  208 ++
 src/core/timecomponents.h                          |  153 ++
 src/core/win32env.cpp                              |  175 ++
 src/creavision/CMakeLists.txt                      |   90 +
 src/creavision/CreaVision_eviacam.vcproj           |  202 ++
 src/creavision/Makefile.am                         |   18 +
 src/creavision/colorspaces.cpp                     | 1398 +++++++++++
 src/creavision/colorspaces.h                       |  257 ++
 src/creavision/crvcamera.cpp                       |  119 +
 src/creavision/crvcamera.h                         |  187 ++
 src/creavision/crvcamera_cv.cpp                    |  198 ++
 src/creavision/crvcamera_cv.h                      |   64 +
 src/creavision/crvcamera_enum.cpp                  |   73 +
 src/creavision/crvcamera_enum.h                    |   52 +
 src/creavision/crvcamera_v4l2.cpp                  | 1752 ++++++++++++++
 src/creavision/crvcamera_v4l2.h                    |  157 ++
 src/creavision/crvcamera_wdm.cpp                   |  143 ++
 src/creavision/crvcamera_wdm.h                     |   59 +
 src/creavision/crvcolor.cpp                        |  220 ++
 src/creavision/crvcolor.h                          |   57 +
 src/creavision/crvgeomtry.cpp                      |  345 +++
 src/creavision/crvgeomtry.h                        |  131 +
 src/creavision/crvhistogram.cpp                    |  143 ++
 src/creavision/crvhistogram.h                      |   49 +
 src/creavision/crvimage.cpp                        |  327 +++
 src/creavision/crvimage.h                          |  101 +
 src/creavision/crvmisc.cpp                         |  488 ++++
 src/creavision/crvmisc.h                           |  124 +
 src/creavision/crvnormroi.cpp                      |  556 +++++
 src/creavision/crvnormroi.h                        |  110 +
 src/creavision/crvskindetection.cpp                |  174 ++
 src/creavision/crvskindetection.h                  |   41 +
 src/creavision/defs.h                              |  139 ++
 src/creavision/pwc-ioctl.h                         |  324 +++
 src/creavision/videoInput.cpp                      | 2360 ++++++++++++++++++
 src/creavision/videoInput.h                        |  385 +++
 src/host/CMakeLists.txt                            |   64 +
 src/host/componenthelper.cpp                       | 1322 ++++++++++
 src/host/configutils.cpp                           |  115 +
 src/host/langutils.cpp                             |   97 +
 src/host/paths.cpp                                 |   98 +
 src/host/testcommon.cpp                            |  235 ++
 src/libwebcam/CMakeLists.txt                       |   36 +
 src/libwebcam/COPYING                              |  674 ++++++
 src/libwebcam/COPYING.LESSER                       |  165 ++
 src/libwebcam/Makefile.am                          |    9 +
 src/libwebcam/README                               |  128 +
 src/libwebcam/README.eviacam                       |    1 +
 src/libwebcam/compat.h                             |  149 ++
 src/libwebcam/dynctrl-logitech.h                   |  108 +
 src/libwebcam/incvideodev.h.in                     |    1 +
 src/libwebcam/libwebcam.c                          | 2550 ++++++++++++++++++++
 src/libwebcam/libwebcam.h                          |  312 +++
 src/libwebcam/uvcvideo.h                           |  664 +++++
 src/libwebcam/webcam.h                             |  721 ++++++
 src/mod_audio/CMakeLists.txt                       |   12 +
 src/mod_audio/mod_audio.cpp                        |  162 ++
 src/mod_camera/CMakeLists.txt                      |   39 +
 src/mod_camera/mod_camera.cpp                      |  425 ++++
 src/mod_camera/mod_camera.h                        |  562 +++++
 src/mod_camera/mod_camera.pjd                      | 1238 ++++++++++
 src/mod_camera/roitype.cpp                         |  653 +++++
 src/mod_camera/tests/CMakeLists.txt                |   25 +
 src/mod_camera/tests/test_mod_camera_gui.cpp       |  235 ++
 src/mod_camera/tests/test_mod_camera_rois.cpp      |  188 ++
 src/mod_camera/tests/test_mod_camera_viewer.cpp    |  300 +++
 src/mod_camera/wcameraconfiguration.cpp            |  671 +++++
 src/mod_camera/wcameraconfiguration.h              |  152 ++
 src/mod_camera/wcamerapanel.cpp                    |  353 +++
 src/mod_camera/wcamerapanel.h                      |   91 +
 src/mod_camera/wxroicontrol.cpp                    |  427 ++++
 src/mod_camera/wxroicontrol.h                      |   97 +
 src/mod_hid/CMakeLists.txt                         |   44 +
 src/mod_hid/keyboardcode.cpp                       | 1029 ++++++++
 src/mod_hid/keyboardcode.h                         |  241 ++
 src/mod_hid/mod_hid.cpp                            |  214 ++
 src/mod_hid/mousecontrol.cpp                       |  552 +++++
 src/mod_hid/mousecontrol.h                         |  167 ++
 src/mod_hid/tests/CMakeLists.txt                   |   30 +
 src/mod_hid/tests/test_keycodes.cpp                |  294 +++
 src/mod_hid/ucs2keysym.c                           |  870 +++++++
 src/mod_hid/ucs2keysym.h                           |    6 +
 src/mod_io/CMakeLists.txt                          |   24 +
 src/mod_io/filebrowser.cpp                         |  185 ++
 src/mod_io/filebrowser.h                           |  119 +
 src/mod_io/mod_io.cpp                              |   49 +
 src/mod_io/textfiledump.cpp                        |  139 ++
 src/mod_io/textfiledump.h                          |  109 +
 src/mod_ipl_sdl/CMakeLists.txt                     |   31 +
 src/mod_ipl_sdl/mod_ipl_sdl.cpp                    |  360 +++
 src/mod_midi/CMakeLists.txt                        |   39 +
 src/mod_midi/midi_config_gui.pjd                   |  685 ++++++
 src/mod_midi/midiconfiggui.cpp                     |  361 +++
 src/mod_midi/midiconfiggui.h                       |  127 +
 src/mod_midi/mod_midi.cpp                          |  382 +++
 src/mod_midi/tests/CMakeLists.txt                  |   11 +
 src/mod_midi/tests/test_mod_midi_config_gui.cpp    |  214 ++
 src/mod_score_player/CMakeLists.txt                |   16 +
 src/mod_score_player/instrselect.cpp               |  311 +++
 src/mod_score_player/instrselect.h                 |  108 +
 src/mod_score_player/mod_score_player.cpp          |   49 +
 src/mod_score_player/mod_score_player.pjd          |  960 ++++++++
 src/mod_score_player/scoreplayer.cpp               |  478 ++++
 src/mod_score_player/scoreplayer.h                 |  265 ++
 src/mod_sdl/CMakeLists.txt                         |   54 +
 src/mod_sdl/config_gui.cpp                         |  312 +++
 src/mod_sdl/config_gui.h                           |  115 +
 src/mod_sdl/mod_sdl.cpp                            |  383 +++
 src/mod_sdl/sdl_config_gui.pjd                     |  967 ++++++++
 src/mod_sdl/tests/CMakeLists.txt                   |   22 +
 src/mod_sdl/tests/test_mod_sdl_drawer.cpp          |   85 +
 src/mod_sdl/tests/test_mod_sdl_gui.cpp             |  227 ++
 src/mod_sdl/tests/test_mod_sdl_loadlib.cpp         |   40 +
 src/mod_vision/CMakeLists.txt                      |   18 +
 src/mod_vision/mod_vision.cpp                      |  159 ++
 src/mod_vision/oftracker.cpp                       |  186 ++
 src/mod_vision/oftracker.h                         |   57 +
 src/mod_widgets/CMakeLists.txt                     |   27 +
 src/mod_widgets/TODO.txt                           |    1 +
 src/mod_widgets/base_widget.h                      |  260 ++
 src/mod_widgets/button.cpp                         |  187 ++
 src/mod_widgets/button.h                           |  155 ++
 src/mod_widgets/checkbox.cpp                       |  336 +++
 src/mod_widgets/checkbox.h                         |  199 ++
 src/mod_widgets/choice.cpp                         |  447 ++++
 src/mod_widgets/choice.h                           |  217 ++
 src/mod_widgets/collapsible.cpp                    |  281 +++
 src/mod_widgets/collapsible.h                      |  172 ++
 src/mod_widgets/filepicker.cpp                     |  416 ++++
 src/mod_widgets/filepicker.h                       |  218 ++
 src/mod_widgets/linear2exp.h                       |  107 +
 src/mod_widgets/mod_widgets.cpp                    |   57 +
 src/mod_widgets/mod_widgets.pjd                    | 1570 ++++++++++++
 src/mod_widgets/slider.cpp                         |  559 +++++
 src/mod_widgets/slider.h                           |  234 ++
 src/mod_wiimotes/CMakeLists.txt                    |   26 +
 src/mod_wiimotes/icons/balance-board.xpm           |  231 ++
 src/mod_wiimotes/icons/none.xpm                    |  151 ++
 src/mod_wiimotes/icons/wiimote-small.xpm           |  284 +++
 src/mod_wiimotes/mod_wiimotes.cpp                  | 1192 +++++++++
 src/mod_wiimotes/mod_wiimotes.h                    |   76 +
 src/mod_wiimotes/mod_wiimotes.pjd                  | 1329 ++++++++++
 src/mod_wiimotes/tests/CMakeLists.txt              |   16 +
 .../tests/test_mod_wiimites_config_gui.cpp         |  257 ++
 src/mod_wiimotes/tests/test_mod_wiimotes_basic.cpp |  345 +++
 src/mod_wiimotes/wiimotes_types.cpp                |  194 ++
 src/mod_wiimotes/wwiimotesconfiguration.cpp        |  259 ++
 src/mod_wiimotes/wwiimotesconfiguration.h          |  134 +
 src/mod_wiimotes/wwiimotesproperties.cpp           |  240 ++
 src/mod_wiimotes/wwiimotesproperties.h             |  122 +
 src/widgets_base/CMakeLists.txt                    |   42 +
 src/widgets_base/bitmaps/sitplus.ico               |  Bin 0 -> 295606 bytes
 src/widgets_base/bitmaps/sitplus_logo_16x16.xpm    |  156 ++
 src/widgets_base/bitmaps/sitplus_logo_32x32.xpm    |  148 ++
 src/widgets_base/containerbook.cpp                 |  192 ++
 src/widgets_base/containercollapsible.cpp          |  177 ++
 src/widgets_base/containerpanel.cpp                |  202 ++
 src/widgets_base/dialogcontainer.cpp               |  206 ++
 src/widgets_base/mdichildcontainer.cpp             |  198 ++
 src/widgets_base/widgets_base.pjd                  |  640 +++++
 329 files changed, 85183 insertions(+)

diff --git a/.tx/config b/.tx/config
new file mode 100644
index 0000000..a0d6b59
--- /dev/null
+++ b/.tx/config
@@ -0,0 +1,9 @@
+[main]
+host = https://www.transifex.com
+
+[libsitplus.libsitplus]
+file_filter = po/libsitplus/<lang>.po
+source_file = po/libsitplus/libsitplus.pot
+source_lang = en
+type = PO
+
diff --git a/3rdparty/CMakeLists.txt b/3rdparty/CMakeLists.txt
new file mode 100755
index 0000000..299088e
--- /dev/null
+++ b/3rdparty/CMakeLists.txt
@@ -0,0 +1,5 @@
+cmake_minimum_required(VERSION 2.6)
+add_subdirectory(wiiuse)
+if (WIN32)
+add_subdirectory(libconfig)
+endif(WIN32)
diff --git a/3rdparty/libconfig/AUTHORS b/3rdparty/libconfig/AUTHORS
new file mode 100644
index 0000000..f3f7465
--- /dev/null
+++ b/3rdparty/libconfig/AUTHORS
@@ -0,0 +1,5 @@
+
+Mark Lindner - Lead developer & maintainer.
+Daniel Marjamäki - Enhancements & bugfixes.
+Andrew Tytula - Windows port.
+Glenn Herteg - Enhancements, bugfixes, documentation corrections.
diff --git a/3rdparty/libconfig/CMakeLists.txt b/3rdparty/libconfig/CMakeLists.txt
new file mode 100755
index 0000000..d43c4cb
--- /dev/null
+++ b/3rdparty/libconfig/CMakeLists.txt
@@ -0,0 +1,26 @@
+cmake_minimum_required(VERSION 2.6)
+project(libconfig)
+
+set(libconfig_SRCS
+	grammar.c
+	grammar.h
+	libconfig.c
+	libconfig.h
+	parsectx.h
+	scanctx.c
+	scanctx.h
+	scanner.c
+	scanner.h
+	strbuf.c
+	strbuf.h
+	wincompat.h
+)
+
+SET (LibConfig_INCLUDE_DIR "${CMAKE_CURRENT_SOURCE_DIR}")
+MESSAGE (STATUS "LIBCONFIG: ${LibConfig_INCLUDE_DIR}")
+add_definitions (-DLIBCONFIG_EXPORTS -DYY_NO_UNISTD_H -DYY_USE_CONST -D_CRT_SECURE_NO_DEPRECATE -D_STDLIB_H)
+add_library (libconfig SHARED ${libconfig_SRCS})
+
+if(WIN32)
+	install (TARGETS libconfig RUNTIME DESTINATION ${BINDIR})
+endif(WIN32)
\ No newline at end of file
diff --git a/3rdparty/libconfig/COPYING.LIB b/3rdparty/libconfig/COPYING.LIB
new file mode 100644
index 0000000..b124cf5
--- /dev/null
+++ b/3rdparty/libconfig/COPYING.LIB
@@ -0,0 +1,510 @@
+
+                  GNU LESSER GENERAL PUBLIC LICENSE
+                       Version 2.1, February 1999
+
+ Copyright (C) 1991, 1999 Free Software Foundation, Inc.
+     59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+[This is the first released version of the Lesser GPL.  It also counts
+ as the successor of the GNU Library Public License, version 2, hence
+ the version number 2.1.]
+
+                            Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+Licenses are intended to guarantee your freedom to share and change
+free software--to make sure the software is free for all its users.
+
+  This license, the Lesser General Public License, applies to some
+specially designated software packages--typically libraries--of the
+Free Software Foundation and other authors who decide to use it.  You
+can use it too, but we suggest you first think carefully about whether
+this license or the ordinary General Public License is the better
+strategy to use in any particular case, based on the explanations
+below.
+
+  When we speak of free software, we are referring to freedom of use,
+not price.  Our General Public Licenses are designed to make sure that
+you have the freedom to distribute copies of free software (and charge
+for this service if you wish); that you receive source code or can get
+it if you want it; that you can change the software and use pieces of
+it in new free programs; and that you are informed that you can do
+these things.
+
+  To protect your rights, we need to make restrictions that forbid
+distributors to deny you these rights or to ask you to surrender these
+rights.  These restrictions translate to certain responsibilities for
+you if you distribute copies of the library or if you modify it.
+
+  For example, if you distribute copies of the library, whether gratis
+or for a fee, you must give the recipients all the rights that we gave
+you.  You must make sure that they, too, receive or can get the source
+code.  If you link other code with the library, you must provide
+complete object files to the recipients, so that they can relink them
+with the library after making changes to the library and recompiling
+it.  And you must show them these terms so they know their rights.
+
+  We protect your rights with a two-step method: (1) we copyright the
+library, and (2) we offer you this license, which gives you legal
+permission to copy, distribute and/or modify the library.
+
+  To protect each distributor, we want to make it very clear that
+there is no warranty for the free library.  Also, if the library is
+modified by someone else and passed on, the recipients should know
+that what they have is not the original version, so that the original
+author's reputation will not be affected by problems that might be
+introduced by others.
+

+  Finally, software patents pose a constant threat to the existence of
+any free program.  We wish to make sure that a company cannot
+effectively restrict the users of a free program by obtaining a
+restrictive license from a patent holder.  Therefore, we insist that
+any patent license obtained for a version of the library must be
+consistent with the full freedom of use specified in this license.
+
+  Most GNU software, including some libraries, is covered by the
+ordinary GNU General Public License.  This license, the GNU Lesser
+General Public License, applies to certain designated libraries, and
+is quite different from the ordinary General Public License.  We use
+this license for certain libraries in order to permit linking those
+libraries into non-free programs.
+
+  When a program is linked with a library, whether statically or using
+a shared library, the combination of the two is legally speaking a
+combined work, a derivative of the original library.  The ordinary
+General Public License therefore permits such linking only if the
+entire combination fits its criteria of freedom.  The Lesser General
+Public License permits more lax criteria for linking other code with
+the library.
+
+  We call this license the "Lesser" General Public License because it
+does Less to protect the user's freedom than the ordinary General
+Public License.  It also provides other free software developers Less
+of an advantage over competing non-free programs.  These disadvantages
+are the reason we use the ordinary General Public License for many
+libraries.  However, the Lesser license provides advantages in certain
+special circumstances.
+
+  For example, on rare occasions, there may be a special need to
+encourage the widest possible use of a certain library, so that it
+becomes a de-facto standard.  To achieve this, non-free programs must
+be allowed to use the library.  A more frequent case is that a free
+library does the same job as widely used non-free libraries.  In this
+case, there is little to gain by limiting the free library to free
+software only, so we use the Lesser General Public License.
+
+  In other cases, permission to use a particular library in non-free
+programs enables a greater number of people to use a large body of
+free software.  For example, permission to use the GNU C Library in
+non-free programs enables many more people to use the whole GNU
+operating system, as well as its variant, the GNU/Linux operating
+system.
+
+  Although the Lesser General Public License is Less protective of the
+users' freedom, it does ensure that the user of a program that is
+linked with the Library has the freedom and the wherewithal to run
+that program using a modified version of the Library.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.  Pay close attention to the difference between a
+"work based on the library" and a "work that uses the library".  The
+former contains code derived from the library, whereas the latter must
+be combined with the library in order to run.
+

+                  GNU LESSER GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License Agreement applies to any software library or other
+program which contains a notice placed by the copyright holder or
+other authorized party saying it may be distributed under the terms of
+this Lesser General Public License (also called "this License").
+Each licensee is addressed as "you".
+
+  A "library" means a collection of software functions and/or data
+prepared so as to be conveniently linked with application programs
+(which use some of those functions and data) to form executables.
+
+  The "Library", below, refers to any such software library or work
+which has been distributed under these terms.  A "work based on the
+Library" means either the Library or any derivative work under
+copyright law: that is to say, a work containing the Library or a
+portion of it, either verbatim or with modifications and/or translated
+straightforwardly into another language.  (Hereinafter, translation is
+included without limitation in the term "modification".)
+
+  "Source code" for a work means the preferred form of the work for
+making modifications to it.  For a library, complete source code means
+all the source code for all modules it contains, plus any associated
+interface definition files, plus the scripts used to control
+compilation and installation of the library.
+
+  Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running a program using the Library is not restricted, and output from
+such a program is covered only if its contents constitute a work based
+on the Library (independent of the use of the Library in a tool for
+writing it).  Whether that is true depends on what the Library does
+and what the program that uses the Library does.
+
+  1. You may copy and distribute verbatim copies of the Library's
+complete source code as you receive it, in any medium, provided that
+you conspicuously and appropriately publish on each copy an
+appropriate copyright notice and disclaimer of warranty; keep intact
+all the notices that refer to this License and to the absence of any
+warranty; and distribute a copy of this License along with the
+Library.
+
+  You may charge a fee for the physical act of transferring a copy,
+and you may at your option offer warranty protection in exchange for a
+fee.
+

+  2. You may modify your copy or copies of the Library or any portion
+of it, thus forming a work based on the Library, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) The modified work must itself be a software library.
+
+    b) You must cause the files modified to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    c) You must cause the whole of the work to be licensed at no
+    charge to all third parties under the terms of this License.
+
+    d) If a facility in the modified Library refers to a function or a
+    table of data to be supplied by an application program that uses
+    the facility, other than as an argument passed when the facility
+    is invoked, then you must make a good faith effort to ensure that,
+    in the event an application does not supply such function or
+    table, the facility still operates, and performs whatever part of
+    its purpose remains meaningful.
+
+    (For example, a function in a library to compute square roots has
+    a purpose that is entirely well-defined independent of the
+    application.  Therefore, Subsection 2d requires that any
+    application-supplied function or table used by this function must
+    be optional: if the application does not supply it, the square
+    root function must still compute square roots.)
+
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Library,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Library, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote
+it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Library.
+
+In addition, mere aggregation of another work not based on the Library
+with the Library (or with a work based on the Library) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may opt to apply the terms of the ordinary GNU General Public
+License instead of this License to a given copy of the Library.  To do
+this, you must alter all the notices that refer to this License, so
+that they refer to the ordinary GNU General Public License, version 2,
+instead of to this License.  (If a newer version than version 2 of the
+ordinary GNU General Public License has appeared, then you can specify
+that version instead if you wish.)  Do not make any other change in
+these notices.
+

+  Once this change is made in a given copy, it is irreversible for
+that copy, so the ordinary GNU General Public License applies to all
+subsequent copies and derivative works made from that copy.
+
+  This option is useful when you wish to copy part of the code of
+the Library into a program that is not a library.
+
+  4. You may copy and distribute the Library (or a portion or
+derivative of it, under Section 2) in object code or executable form
+under the terms of Sections 1 and 2 above provided that you accompany
+it with the complete corresponding machine-readable source code, which
+must be distributed under the terms of Sections 1 and 2 above on a
+medium customarily used for software interchange.
+
+  If distribution of object code is made by offering access to copy
+from a designated place, then offering equivalent access to copy the
+source code from the same place satisfies the requirement to
+distribute the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+  5. A program that contains no derivative of any portion of the
+Library, but is designed to work with the Library by being compiled or
+linked with it, is called a "work that uses the Library".  Such a
+work, in isolation, is not a derivative work of the Library, and
+therefore falls outside the scope of this License.
+
+  However, linking a "work that uses the Library" with the Library
+creates an executable that is a derivative of the Library (because it
+contains portions of the Library), rather than a "work that uses the
+library".  The executable is therefore covered by this License.
+Section 6 states terms for distribution of such executables.
+
+  When a "work that uses the Library" uses material from a header file
+that is part of the Library, the object code for the work may be a
+derivative work of the Library even though the source code is not.
+Whether this is true is especially significant if the work can be
+linked without the Library, or if the work is itself a library.  The
+threshold for this to be true is not precisely defined by law.
+
+  If such an object file uses only numerical parameters, data
+structure layouts and accessors, and small macros and small inline
+functions (ten lines or less in length), then the use of the object
+file is unrestricted, regardless of whether it is legally a derivative
+work.  (Executables containing this object code plus portions of the
+Library will still fall under Section 6.)
+
+  Otherwise, if the work is a derivative of the Library, you may
+distribute the object code for the work under the terms of Section 6.
+Any executables containing that work also fall under Section 6,
+whether or not they are linked directly with the Library itself.
+

+  6. As an exception to the Sections above, you may also combine or
+link a "work that uses the Library" with the Library to produce a
+work containing portions of the Library, and distribute that work
+under terms of your choice, provided that the terms permit
+modification of the work for the customer's own use and reverse
+engineering for debugging such modifications.
+
+  You must give prominent notice with each copy of the work that the
+Library is used in it and that the Library and its use are covered by
+this License.  You must supply a copy of this License.  If the work
+during execution displays copyright notices, you must include the
+copyright notice for the Library among them, as well as a reference
+directing the user to the copy of this License.  Also, you must do one
+of these things:
+
+    a) Accompany the work with the complete corresponding
+    machine-readable source code for the Library including whatever
+    changes were used in the work (which must be distributed under
+    Sections 1 and 2 above); and, if the work is an executable linked
+    with the Library, with the complete machine-readable "work that
+    uses the Library", as object code and/or source code, so that the
+    user can modify the Library and then relink to produce a modified
+    executable containing the modified Library.  (It is understood
+    that the user who changes the contents of definitions files in the
+    Library will not necessarily be able to recompile the application
+    to use the modified definitions.)
+
+    b) Use a suitable shared library mechanism for linking with the
+    Library.  A suitable mechanism is one that (1) uses at run time a
+    copy of the library already present on the user's computer system,
+    rather than copying library functions into the executable, and (2)
+    will operate properly with a modified version of the library, if
+    the user installs one, as long as the modified version is
+    interface-compatible with the version that the work was made with.
+
+    c) Accompany the work with a written offer, valid for at least
+    three years, to give the same user the materials specified in
+    Subsection 6a, above, for a charge no more than the cost of
+    performing this distribution.
+
+    d) If distribution of the work is made by offering access to copy
+    from a designated place, offer equivalent access to copy the above
+    specified materials from the same place.
+
+    e) Verify that the user has already received a copy of these
+    materials or that you have already sent this user a copy.
+
+  For an executable, the required form of the "work that uses the
+Library" must include any data and utility programs needed for
+reproducing the executable from it.  However, as a special exception,
+the materials to be distributed need not include anything that is
+normally distributed (in either source or binary form) with the major
+components (compiler, kernel, and so on) of the operating system on
+which the executable runs, unless that component itself accompanies
+the executable.
+
+  It may happen that this requirement contradicts the license
+restrictions of other proprietary libraries that do not normally
+accompany the operating system.  Such a contradiction means you cannot
+use both them and the Library together in an executable that you
+distribute.
+

+  7. You may place library facilities that are a work based on the
+Library side-by-side in a single library together with other library
+facilities not covered by this License, and distribute such a combined
+library, provided that the separate distribution of the work based on
+the Library and of the other library facilities is otherwise
+permitted, and provided that you do these two things:
+
+    a) Accompany the combined library with a copy of the same work
+    based on the Library, uncombined with any other library
+    facilities.  This must be distributed under the terms of the
+    Sections above.
+
+    b) Give prominent notice with the combined library of the fact
+    that part of it is a work based on the Library, and explaining
+    where to find the accompanying uncombined form of the same work.
+
+  8. You may not copy, modify, sublicense, link with, or distribute
+the Library except as expressly provided under this License.  Any
+attempt otherwise to copy, modify, sublicense, link with, or
+distribute the Library is void, and will automatically terminate your
+rights under this License.  However, parties who have received copies,
+or rights, from you under this License will not have their licenses
+terminated so long as such parties remain in full compliance.
+
+  9. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Library or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Library (or any work based on the
+Library), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Library or works based on it.
+
+  10. Each time you redistribute the Library (or any work based on the
+Library), the recipient automatically receives a license from the
+original licensor to copy, distribute, link with or modify the Library
+subject to these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties with
+this License.
+

+  11. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Library at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Library by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Library.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply, and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+  12. If the distribution and/or use of the Library is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Library under this License
+may add an explicit geographical distribution limitation excluding those
+countries, so that distribution is permitted only in or among
+countries not thus excluded.  In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+  13. The Free Software Foundation may publish revised and/or new
+versions of the Lesser General Public License from time to time.
+Such new versions will be similar in spirit to the present version,
+but may differ in detail to address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Library
+specifies a version number of this License which applies to it and
+"any later version", you have the option of following the terms and
+conditions either of that version or of any later version published by
+the Free Software Foundation.  If the Library does not specify a
+license version number, you may choose any version ever published by
+the Free Software Foundation.
+

+  14. If you wish to incorporate parts of the Library into other free
+programs whose distribution conditions are incompatible with these,
+write to the author to ask for permission.  For software which is
+copyrighted by the Free Software Foundation, write to the Free
+Software Foundation; we sometimes make exceptions for this.  Our
+decision will be guided by the two goals of preserving the free status
+of all derivatives of our free software and of promoting the sharing
+and reuse of software generally.
+
+                            NO WARRANTY
+
+  15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
+WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
+EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
+OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
+KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
+LIBRARY IS WITH YOU.  SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
+THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+  16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
+WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
+AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
+FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
+CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
+LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
+RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
+FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
+SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+DAMAGES.
+
+                     END OF TERMS AND CONDITIONS
+

+           How to Apply These Terms to Your New Libraries
+
+  If you develop a new library, and you want it to be of the greatest
+possible use to the public, we recommend making it free software that
+everyone can redistribute and change.  You can do so by permitting
+redistribution under these terms (or, alternatively, under the terms
+of the ordinary General Public License).
+
+  To apply these terms, attach the following notices to the library.
+It is safest to attach them to the start of each source file to most
+effectively convey the exclusion of warranty; and each file should
+have at least the "copyright" line and a pointer to where the full
+notice is found.
+
+
+    <one line to give the library's name and a brief idea of what it does.>
+    Copyright (C) <year>  <name of author>
+
+    This library is free software; you can redistribute it and/or
+    modify it under the terms of the GNU Lesser General Public
+    License as published by the Free Software Foundation; either
+    version 2.1 of the License, or (at your option) any later version.
+
+    This library is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+    Lesser General Public License for more details.
+
+    You should have received a copy of the GNU Lesser General Public
+    License along with this library; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA
+
+Also add information on how to contact you by electronic and paper mail.
+
+You should also get your employer (if you work as a programmer) or
+your school, if any, to sign a "copyright disclaimer" for the library,
+if necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the
+  library `Frob' (a library for tweaking knobs) written by James
+  Random Hacker.
+
+  <signature of Ty Coon>, 1 April 1990
+  Ty Coon, President of Vice
+
+That's all there is to it!
+
+
diff --git a/3rdparty/libconfig/ChangeLog b/3rdparty/libconfig/ChangeLog
new file mode 100644
index 0000000..b30c6a0
--- /dev/null
+++ b/3rdparty/libconfig/ChangeLog
@@ -0,0 +1,582 @@
+
+	----- version 1.4.7 ------
+
+2011-03-11  Mark Lindner  <markl at neuromancer>
+
+	* doc/libconfig.texi - fixed typo; updated docs
+	* TODO - updated list
+	* lib/libconfig.c, lib/libconfig.h, lib/libconfigcpp.c++,
+	  lib/libconfig.h++ - added config{get,set}_default_format(),
+	  Config::{get,set}DefaultFormat()
+
+2011-03-10  Mark Lindner  <markl at neuromancer>
+
+	* lib/libconfig.c - fixed memory leak when encountering a parse error
+	  in an @include'd file
+	* lib/libconfig.h, lib/libconfig.h++, lib/Makefile.am, configure.ac,
+	  doc/libconfig.texi - bump versions
+
+	----- version 1.4.6 ------
+
+2010-09-10  Mark Lindner  <markl at neuromancer>
+
+	* doc/libconfig.texi - documentation updates
+	* lib/libconfig.c, lib/libconfigcpp.c++, lib/libconfig.h,
+	  lib/libconfig.h++, lib/wincompat.h, lib/scanctx.c - added support
+	  for specifying an include directory
+	* m4/* - added local m4 directory
+	* contrib/* - added user-contributed files
+
+2010-09-07  Mark Lindner  <markl at neuromancer>
+
+	* lib/scanner.l - bugfix for parse error when there is a missing
+	  newline at the end of the file
+	* lib/libconfig.h, lib/libconfig.h++, lib/Makefile.am - bump version
+	* tinytest/* - added a simple unit testing framework
+	* tests/* - added preliminary unit tests
+	* configure.ac, ac_config.h, ac_config.h.in, Makefile.am,
+	  lib/Makefile.am, libtool, doc/libconfig.texi - bump versions/dates
+	* lib/grammar.h, lib/grammar.c - regenerated with newer version of
+	  Bison
+	* lib/libconfig.c - bugfix: explicitly set starting line number to 1
+	  when parsing from strings; otherwise line numbers reported in parse
+	  errors are undefined
+
+	----- version 1.4.5 ------
+
+2010-05-04  Mark Lindner  <markl at neuromancer>
+
+	* lib/libconfig.h, lib/libconfig.h++, lib/Makefile.am - bumped version
+	  numbers; removed #include for <map> and added one for <exception>
+	* lib/libconfigcpp.c++ - bugfix: properly handle TypeInt64 in add() and
+	  assertType()
+	* aux-build/*, ac_config.h, configure.ac, ac_config.h.in, libtool -
+	  regenerated with newer autotools
+	* libconfig.c - added declaration of libconfig_yylex_init_extra() to
+	  eliminate compiler warning
+	* scanner.l - added #define YY_NO_INPUT to prevent compiler warning
+	* libconfig.texi - Added example code for operator=()
+
+	----- version 1.4.4 ------
+
+2010-04-12  Mark Lindner  <markl at neuromancer>
+
+	* lib/Makefile.am - fixed shared library version info
+	* lib/libconfig.h++ - added Setting::c_str() method
+	* configure.ac, ac_config.h, libconfig.spec, lib/libconfig.h,
+	  lib/libconfig.h++ - bump versions
+	* lib/wincompat.h - fixed MinGW build error
+	* doc/libconfig.texi - doc updates
+	* README - added MinGW info
+
+	----- version 1.4.3 ------
+
+2010-02-13  Mark Lindner  <markl at neuromancer>
+
+	* lib/scanner.l - bugfix for matching @include with preceding
+	  whitespace
+
+	----- version 1.4.2 ------
+
+2010-01-19  Mark Lindner  <markl at neuromancer>
+
+	* lib/libconfigcpp.c++, lib/libconfig.h++ - bugfix for crash; added
+	  copy constructor for ParseException (from Frederic Heitzmann)
+	* lib/libconfig.h, lib/libconfig.h++, lib/Makefile.am,
+	  ac_config.h, libconfig.spec, configure.ac - bump versions
+
+2010-01-09  Mark Lindner  <markl at neuromancer>
+
+	* lib/libconfigcpp.c++ - bugfix in ParseException constructor (from
+	  Ilya Dogolazky)
+	* debian/* - more cleanup, and added debug rules (from Ilya Dogolazky)
+
+	----- version 1.4.1 ------
+
+2009-12-31  Mark Lindner  <markl at neuromancer>
+
+	* lib/libconfig.c - bugfix for crash; removed unnecessary buffer delete
+	  in __config_read()
+	* examples/c/Makefile.am, examples/c++/Makefile.am - fixed build issue
+	* configure.ac, Makefile.am - Added `--disable-examples' configure
+	  option
+	* configure.ac, lib/Makefile.am, libconfig.spec, ac_config.h - bumped
+	  version numbers
+
+	----- version 1.4 ------
+
+2009-10-24  Mark Lindner  <markl at neuromancer>
+
+	* grammar.y, scanner.l - properly report @include errors
+	* exmaples/example4.cpp - new example added
+
+2009-10-14  Mark Lindner  <markl at neuromancer>
+
+	* debian/* - more fixes; from Klaus Schneider-Zapp
+	* libconfig.c - when writing strings, escape only control characters
+	  with \x
+
+	----- version 1.4b4 ------
+
+2009-09-09  Mark Lindner  <markl at neuromancer>
+
+	* lib/Makefile.am - fixed MinGW build issues
+
+	----- version 1.4b3 ------
+
+2009-09-04  Mark Lindner  <markl at neuromancer>
+
+	* lib/libconfig.c, lib/scanner.l, lib/grammar.y - fixed all memory
+	  leaks reported by Valgrind; removed an unncessary strdup()/free().
+
+2009-09-01  Mark Lindner  <markl at neuromancer>
+
+	* lib/libconfig.c, lib/libconfig.h, lib/libconfigcpp.c++,
+	  lib/libconfig.h++ - added config_error_type() and fixed a segfault
+	   when throwing a ParseException.
+	* doc/libconfig.texi - doc updates
+
+	----- version 1.4b2 ------
+
+2009-08-29  Mark Lindner  <markl at neuromancer>
+
+	* examples/* - added new example programs to replace the less
+	  practical ones in samples/
+
+2009-08-25  Mark Lindner  <markl at neuromancer>
+
+	* lib/libconfig.c, lib/libconfig.h, lib/libconfigcpp.c++,
+	  lib/libconfig.h++ - added config_set_tab_width(),
+	  config_get_tab_width() and Config::setTabWidth(),
+	  Config::getTabWidth().
+	* doc/libconfig.texi - doc updates
+
+	----- version 1.4b1 ------
+
+2009-08-21  Mark Lindner  <markl at neuromancer>
+
+	* lib/libconfig.h++, lib/libconfigcpp.c++ - broke the public
+	  dependency on libconfig.h; updated VC++ projects on Windows so that
+	  the C++ DLL no longer exports any of the C API functions
+	* debian/* - updated for version 1.4
+	* lib/libconfig.c - fixed an isprint() assertion on Windows
+
+2009-08-20  Mark Lindner  <markl at neuromancer>
+
+	* lib/parsectx.c, lib/parsectx.h, lib/scanctx.c, lib/scanctx.h,
+	  lib/strbuf.c, lib/strbuf.h - code refactoring to reduce library size
+	  lib/Makefile.am - fixed 'make install' error
+
+	----- version 1.4b ------
+
+2009-08-16  Mark Lindner  <markl at neuromancer>
+
+	* lib/libconfig.c, lib/libconfig.h, lib/scanctx.c, lib/scanctx.h,
+	  lib/grammar.y, lib/grammar.c, lib/grammar.h - added
+	  config_read_string(); added config_setting_source_file() and
+	  management of list of input file names; added #ifdef guard for
+	  DllMain() function so that it's not included for static library
+	  builds
+	* lib/libconfigcpp.c++, lib/libconfig.h++ - added filename to
+	  ParseException; bugfix in Setting::setFormat(); made what() methods
+	  of exceptions public; added Setting::getSourceFile(),
+	  Config::readString().
+	* doc/libconfig.texi - documentation updates
+	* lib/Makefile.am - bump .so version
+	* ac_config.h, configure.ac, libtool - bump version
+
+2009-07-19  Mark Lindner  <markl at neuromancer>
+
+	* lib/libconfig.c, lib/libconfig.h, lib/libconfigcpp.c++,
+	  lib/libconfig.h++ - added config_read_string() and
+	  Config::readString() functions (contributed by Matthias Weisser).
+
+2009-07-02  Mark Lindner  <markl at neuromancer>
+
+	* lib/parsectx.c, lib/parsectx.h, lib/scanctx.c, lib/scanctx.h,
+	  lib/scanner.l, lib/grammar.y, lib/private.h, lib/Makefile.am,
+	  lib/libconfig.c, lib/libconfig.h - replaced ugly C code in scanner.l
+	  for processing strings with a new <STRING> scanner state and
+	  associated rules; added support for hex character literals (\xNN) in
+	  strings; refactored scanner and parser context into separate source
+	  files; added preliminary support for include files ("@include"
+	  directive).
+
+2009-05-27  Mark Lindner  <markl at neuromancer>
+
+	* ltmain.sh, ac_config.h, ac_config.h.in, configure.ac, libconfig.spec,
+	  libtool - upgraded to newer versions of autotools
+	* grammar.y, grammar.h, grammar.c, libconfigcpp.c++, libconfig.h++,
+	  libconfig.c, libconfig.h - added LIBCONFIG_VER_* macros, changed API
+	  to replace 'long' and 'unsigned long' with 'int' and 'unsigned int'
+	  to resolve a portability problem; added 'const' to declarations of
+	  getLine() and getError() methods on ParseException
+	* <multiple> - directory structure reorg
+
+	----- version 1.3.2 ------
+
+2009-02-18  Mark Lindner  <markl at neuromancer>
+
+	* libconfig.vcproj, libconfig++.vcproj - #define _STDLIB_H to
+	  eliminate 'inconsistent dll linkage' warnings for free & malloc
+
+2009-02-17  Mark Lindner  <markl at neuromancer>
+
+	* libconfig.c, libconfig.h - added config_setting_lookup*() functions;
+	  modified config_lookup_*() functions to have more consistent API
+	  (return status, and accept value-result param)
+	* debian/* - updates and cleanup (from Klaus Schneider-Zapp)
+	* libconfig.spec, Makefile.am, ac_config.h - update version number
+	* doc/libconfig.texi - documentation updates
+	* samples/c/sample1.c - patch from Rodolfo Giometti
+	* samples/c/stub.c - fixed relative to API changes
+
+2008-12-06  Mark Lindner  <markl at neuromancer>
+
+	* libconfig.c - fix memory leak in config_setting_remove_elem();
+	  reported by Timi Tuohenmaa
+	* configure.ac - fix incorrect processing of --enable-cxx option;
+	  reported by Thomas Gazzola
+
+2008-09-11  Mark Lindner  <markl at neuromancer>
+
+	* debian/libconfigduo2.postinst - fix typo in test stmt
+
+	----- version 1.3.1 ------
+
+2008-09-07  Mark Lindner  <markl at neuromancer>
+
+	* scanner.l, wincompat.h - workarounds for problems with parsing and
+	  formatting of 64-bit integers on MinGW
+	* scanner.c - regenerated
+
+2008-09-05  Mark Lindner  <markl at neuromancer>
+
+	* libconfig.spec - updated for 1.3.1
+	* Makefile.am - fix version
+	* scanner.l - add fromhex() function, since strtoull() seems broken
+	  on MinGW
+
+2008-08-25  Mark Lindner  <markl at neuromancer>
+
+	* libconfigcpp.c++, libconfig.h++ - derive exceptions from
+	  std::exception
+
+2008-08-10  Mark Lindner  <markl at neuromancer>
+
+	* wincompat.h - fix MinGW build issue
+	* configure.ac, ac_config.h, Makefile.am - bump version
+	* doc/libconfig.texi - doc updates
+	* libconfigcpp.c++, libconfig.h++ - include path information in
+	  setting exceptions
+	* libconfig.c - force "C" locale for parsing & formatting
+
+	----- version 1.3 ------
+
+2008-04-07  Mark Lindner  <markl at neuromancer>
+
+	* libconfig.spec - updated for 1.3
+
+2008-04-03  Mark Lindner  <markl at neuromancer>
+
+	* scanner.l, grammar.y, libconfig.c, libconfig.h, wincompat.h -
+	  fix/add comment headers, add C90 portability fixes from
+	  Chris Pickett (C-style comments, renamed 'index' to 'idx' to
+	  resolve name clash)
+	* scanner.c, grammar.c - regenerated
+	* configure.ac - enable more gcc warnings
+	* libconfigcpp.c++, libconfig.h++ - added getPath(), fixed impl of
+	  isRoot(), add portability fixes from Chris Pickett (renamed 'index'
+	  to 'idx' to resolve name clash), moved exception constructors into
+	  source file; changed SettingExistsException to SettingNameException
+	  to be more broad in scope
+	* Makefile.am - add wincompat.h to sources; add missing debian files
+	  to EXTRA_DIST
+	* test.cfg - added example 64-bit integer settings
+	* samples/* - expanded some examples
+	* doc/libconfig.texi - documentation updates
+	* Makefile.am, *msvc7* - added (generated) VS2003 projects/solution
+
+2008-03-22  Mark Lindner  <markl at neuromancer>
+
+	* debian/* - updates from Klaus Schneider
+
+2008-03-22  Mark Lindner  <markl at neuromancer>
+
+	* scanner.l, grammar.y, libconfig.h++, libconfig.c, libconfig.h,
+	  wincompat.h, libconfigcpp.c++, grammar.c, scanner.c, grammar.h -
+	  add support for 64-bit integer values
+	* libconfig.texi - documentation updates
+	* Makefile.am, ac_config.h, configure.ac, libtool - bump version
+	* libconfig.h - add config_setting_parent(), config_setting_is_root()
+	* libconfigcpp.c++, libconfig.h++ - add isRoot(), getParent() to
+	  Setting
+
+2008-03-15  Mark Lindner  <markl at neuromancer>
+
+	* scanner.l - made 'true' and 'false' tokens completely
+	  case-insensitive
+	* libconfigcpp.cc, libconfig.hh - added alias files for Windows
+	* libconfig.c, libconfig.h - modified __config_write_value() to write
+	  out floating point values in a more human-readable form; added name
+	  validation; added config_setting_remove_elem() and
+	  config_setting_index()
+	* libconfigcpp.c++, libconfig.h++ - added remove(unsigned int) and
+	  getIndex() to Setting
+	* libconfig.texi - documentation updates
+
+	----- version 1.2.1 ------
+	
+2007-12-21  Mark Lindner  <markl at neuromancer>
+
+	* libconfig.c - source cleanup
+	* config.guess, config.sub, ltmain.sh, libtool - updated to newer
+	* configure.ac, Makefile.am, ac_config.h.in, ac_config.h
+	  - MinGW-related fixes
+
+	----- version 1.2 ------
+
+2007-10-15  Mark Lindner  <markl at neuromancer>
+
+	* libconfig.h++, libconfigcpp.c++ - renamed "SettingFormat" to
+	  "Setting::Format" to reduce namespace pollution
+
+2007-10-13  Mark Lindner  <markl at neuromancer>
+
+	* scanner.l - updated regexp for float to allow for values which have
+	  an exponent but no decimal point
+	* grammar.y - capture input line number when parsing settings
+	* libconfig.c, libconfig.h - added config_setting_is*() macros;
+	  added config_setting_source_line(); added line member to
+	  config_setting_t struct
+	* libconfig.c++, libconfig.h++ - renamed "SettingType" enum to
+	  Setting::Type to reduce namespace pollution; added getSourceLine()
+	* samples/* - various updates
+	* debian/changelog - added entry
+	* ac_config.h, configure.ac, libtool, Makefile.am - new version #
+	* TODO - updates
+	* doc/libconfig.texi - documentation updates
+
+2007-10-12  Mark Lindner  <markl at neuromancer>
+
+	* libconfig.c, libconfig.h - added config_set_auto_convert(),
+	  config_get_auto_convert(), and number auto-conversion logic
+	* libconfigcpp.c++, libconfig.h++ - add setAutoConvert(),
+	  getAutoConvert(), lookupValue() that takes std::string&,
+	  corrected return values of assignment operators
+	* debian/rules - made file executable
+	* debian/libconfigduo-dev.install - add pkgconfig files to list
+	
+2007-09-22  Mark Lindner  <markl at neuromancer>
+
+	* libconfig.c, libconfig.h - change 'type' and 'format' members of
+	   config_setting_t to short, thereby saving 4 bytes
+
+2007-09-22  Mark Lindner  <markl at neuromancer>
+
+	* doc/libconfig.texi - add @direntry to fix install-info warnings
+	* libconfig.spec.in, Makefile.am, configure.ac - added RPM support
+	  (from Deneys S. Maartens)
+
+2007-09-18  Mark Lindner  <markl at neuromancer>
+
+	* libconfig.h - remove DLL_EXPORT; add LIBCONFIG_STATIC to fix
+	  static linking on Windows
+
+2007-09-18  Deneys S. Maartens  <dsm at tlabs.ac.za>
+	
+	* samples/c/Makefile.am, samples/c++/Makefile.am - Add
+	  AM_CPPFLAGS to fix distcheck build failure
+	* Makefile.am - expand wildcards in EXTRA_DIST to fix distcheck
+	  build failure
+
+	----- version 1.1.3 ------
+
+2007-08-03  Mark Lindner  <markl at neuromancer>
+
+	* libconfigcpp.c++ - bugfix in unsigned cast operators (incorrect value
+	  clipping logic)
+	* debian/control - made some corrections
+
+	----- version 1.1.2 ------
+
+2007-07-01  Mark Lindner  <markl at neuromancer>
+
+	* debian/* added debian package files from Klaus Schneider
+	* libconfig.h++ - added new predicate is<type>() functions
+	* libconfig.h - fix comments
+	* doc/libconfig.texi - documentation updates
+	* ac_config.h, configure.ac, Makefile.am - new version #
+	
+	----- version 1.1.1 ------
+
+2007-06-15  Mark Lindner  <markl at neuromancer>
+
+	* scanner.l - bugfix in string parsing
+	* test.cfg - added test case
+
+	----- version 1.1 ------
+
+2007-04-18  Mark Lindner  <markl at neuromancer>
+
+	* libconfigcpp.c++ - bugfix in add(SettingType)
+	* stubcpp.cpp - add more ad-hoc tests
+
+2007-04-05  Mark Lindner  <markl at neuromancer>
+
+	* scanner.l - Add string concatenation patch from Glenn Herteg.
+	  Add \f as a whitespace character.
+	* grammar.y - add mode directive emacs
+	* libconfigcpp.c++, libconfig.h++ - add exists() and lookupValue()
+	  methods; add Setting::operator std::string()
+	* libconfig.texi - documentation updates
+
+	----- version 1.0.1 ------
+
+2006-11-26  Mark Lindner  <markl at neuromancer>
+
+	* samples/c/Makefile.am, samples/c++/Makefile.am - fix linker error
+	* libconfig.texi - documentation update
+
+	----- version 1.0 ------
+
+2006-10-19  Mark Lindner  <markl at neuromancer>
+
+	* libconfigcpp.c++ - bugfix in add() for lists
+
+2006-10-11  Mark Lindner  <markl at neuromancer>
+
+	* scanner.l - allow asterisk in setting names (submitted by
+	  James McCann)
+	* libconfig.texi - documentation updates
+	* configure.ac, Makefile.am, samples/Makefile.am - add --disable-cxx
+	  configure option; conditionally build/install C++ components
+
+2006-10-01  Mark Lindner  <markl at neuromancer>
+
+	* <multiple> - samples cleanup
+
+2006-09-14  Mark Lindner  <markl at neuromancer>
+
+	* libconfig.c - Change %.8f to %e for double values in
+	  __config_write_value(). Submitted by Filipe Maia.
+
+2006-08-31  Mark Lindner  <markl at neuromancer>
+
+	* Makefile.am - changed bin_PROGRAMS to noinst_PROGRAMS; the stub
+	  programs are for testing and should not be installed.
+
+2006-08-26  Mark Lindner  <markl at neuromancer>
+
+	* libconfig.texi - documentation corrections & updates
+	* stub.c, stubcpp.c++ - check return value of fopen(); fix compiler
+	  warnings
+	* configure.ac, Makefile.am - add -Wall to CFLAGS only for gcc;
+	  add test.cfg to EXTRA_DIST
+	* grammar.y, libconfigcpp.c++ - fix compiler warnings
+	* libconfig.c - use CONFIG_TRUE & CONFIG_FALSE rather than 1 & 0
+	  for success/failure return values.
+
+	----- version 0.9 ------
+
+2006-07-29  Mark Lindner  <markl at neuromancer>
+
+	* <multiple> - major grammar redesign: groups are now values instead of
+	  distinct syntax constructs; this allows groups to be elements of
+	  lists
+	* libconfig.texi - documentation updates; added new chapter containing
+	  the BNF grammar
+	* test.cfg - modified to reflect new syntax and to demonstrate lists
+
+2006-06-23  Mark Lindner  <markl at neuromancer>
+
+	* <multiple> - added support for lists (collections of
+	  heterogeneous values of any type)
+	* libconfig.c - pretty-printing fixes in config_write()
+
+2006-06-08  Mark Lindner  <markl at neuromancer>
+
+	* libconfig.h++ - added private copy constructor & assignment operator
+	  (from Josef Meile)
+	* ligconfigcpp.c++, libconfig.h++ - added cast operators for unsigned
+	  int and unsigned long (from Scott Frazer)
+	* <multiple> - add support for value formats; the only non-default
+	  format currently supported is hexadecimal format for integer values
+	  (based on patch from Scott Frazer)
+
+2006-04-15  Mark Lindner  <markl at neuromancer>
+
+	* <multiple> - added pkg-config support
+
+2006-03-31  mlindner  <markl at neuromancer>
+
+	* <multiple> - cleaned up config.tab.h mess (this file was obsolete,
+	  and superseded by grammar.h ... problem identified by Scott Frazer)
+
+2006-03-30  mlindner  <mlindner at chimera>
+
+	* grammar.y - fixed includes for windows (missing decl of malloc/free)
+	* libconfig.c - fixed several signed/unsigned warnings
+	* doc/libconfig.texi - documentation updates, formatting fix
+	* scanner.l - allow lowercase 'true' and 'false' in addition to
+	  'TRUE' and 'FALSE'
+
+2006-03-27  Mark Lindner  <markl at neuromancer>
+
+	* libconfigcpp.c++ - added missing break statements in switch (from
+	  Lukas Zweifel)
+	* libconfig.c - don't strdup() a NULL string (from Lukas Zweifel)
+	* grammar.c, grammar.h - regenerated with bison 2.1
+
+2006-03-20  Mark Lindner  <markl at neuromancer>
+
+	* scanner.l - added '%option nounistd' and regenerated with newest
+	  version of flex; Windows doesn't have unistd.h.
+
+2006-03-17  Mark Lindner  <markl at neuromancer>
+
+	* grammar.y - bugfix; error & abort parsing if duplicate setting name
+	  encountered (previously caused a crash ... reported by Tobias Witek)
+	* scanner.l - bugfix; multi-line C-style comments were causing line
+	  number counting to be thrown off, because the newlines were being
+	  "eaten"
+	* <multiple> - various fixes to support building of DLLs on Windows.
+
+2005-11-26  Mark Lindner  <markl at neuromancer>
+
+	* grammar.y, scanner.l - always strdup() yytext, and free the memory
+	  in the grammar rules.
+
+2005-11-22  Mark Lindner  <markl at neuromancer>
+
+	* libconfigcpp.c++, libconfig.h++, libconfig.c, libconfig.h -
+	  Added Daniel's enhancements: methods & functions for reading/writing
+	  files, fixes for various memory leaks, etc.
+	* samples/* - Added Daniel's example code.
+	* docs/libconfig.texi - Updated documentation
+
+2005-09-28  Mark Lindner  <markl at neuromancer>
+
+	* libconfigcpp.c++, libconfig.h++, libconfig.c, libconfig.h
+	  Enhanced API to support modification of a configuration.
+	* libconfig.texi - updated manual
+
+2005-06-02  Mark Lindner  <markl at neuromancer>
+
+	* libconfigcpp.c++, libconfig.h++ - Added getName() method;
+	  fixed operator[](int) to work with groups; this allows iteration over
+	  a group's child settings. Added a missing break statement (bugfix
+	  submitted by Pablo Barrera Gonzalez). Added operator int() and
+	  operator float() to Setting; note that these may cause loss of
+	  precision since the actual values are stored internally as long
+	  and double, respectively.
+
+	* libconfig.h - added config_setting_name() macro
+
+	* libconfig.c - maintain two lists of children at each node; a sorted
+	  list and an unsorted list (to preserve the order of the settings as
+	  they appear in the file).
+	
+	* scanner.l - fixed scanner rule for comments. '#' no longer has to
+	  be in column 0 to be recognized as a comment. Added support for C
+	  and C++ style comments.
diff --git a/3rdparty/libconfig/README b/3rdparty/libconfig/README
new file mode 100644
index 0000000..e3def50
--- /dev/null
+++ b/3rdparty/libconfig/README
@@ -0,0 +1,58 @@
+
+To produce a PDF manual, issue the command "make pdf" after running
+`./configure'.
+
+				 -*-
+
+If you do not wish to build the C++ components, use:
+
+./configure --disable-cxx
+
+				 -*-
+
+The `examples' subdirectory contains some examples of using libconfig
+from C and C++.
+
+				 -*-
+
+The config file syntax changed between versions 0.8 and 0.9. In order
+to implement all of the feature/enhancement requests in an elegant and
+self-consistent way, the configuration grammar had to be changed in a
+non-backward-compatible way. In particular, groups are now values, so
+the old syntax:
+
+group
+{
+  ...
+}
+
+must now be written as:
+
+group =
+{
+  ...
+};
+
+Note that the trailing semicolon, which was previously optional, is
+now required. Also note that a colon (':') can be used in place of the
+equals sign.
+
+				 -*-
+
+Flex and Bison are not required in order to build this
+package. However, if you modify the .l or .y files, you must have Flex
+(2.5.31 or better) and Bison (2.1 or better), respectively.
+
+				 -*-
+
+To successfully compile using MinGW (with gcc 4.4.0 or later), it may
+be necessary to modify the file "mingw32\4.4.0\libstdc++.la", changing line 11
+from:
+
+library_names='libstdc++.dll.a'
+
+to:
+
+library_names='libstdc++.a'
+
+(See http://trac.osgeo.org/geos/ticket/282 for more information).
diff --git a/3rdparty/libconfig/README.sitplus b/3rdparty/libconfig/README.sitplus
new file mode 100644
index 0000000..d54c03b
--- /dev/null
+++ b/3rdparty/libconfig/README.sitplus
@@ -0,0 +1,3 @@
+libconfig-1.4.7
+
+http://www.hyperrealm.com/libconfig/
diff --git a/3rdparty/libconfig/TODO b/3rdparty/libconfig/TODO
new file mode 100644
index 0000000..0d7e058
--- /dev/null
+++ b/3rdparty/libconfig/TODO
@@ -0,0 +1,33 @@
+TO-DOs:
+
+These are features that have been requested, and have been considered,
+but are not yet implemented, because I'm undecided about how they
+should be implemented, and/or because they are difficult and/or time-consuming
+to implement.
+
+
+* Add an option for safe type conversions; that is, report an error
+  rather than silently truncating out-of-range values to 0 (namely int64 ->
+  int).
+
+
+* Add support for copying settings from one configuration to another. Need a
+  recursive function to copy a setting and call itself on all child settings.
+
+
+* Add a += operator, so that additional elements can be appended to a list or
+  array. The issue with this is defining a consistent syntax. For example:
+
+  x = ( 1, 2, 3 );
+  x += ( 4, 5 );
+
+  Should this result in ( 1, 2, 3, 4, 5 ), or ( 1, 2, 3, ( 4, 5 ))? I believe
+  it should be the latter. However, only the former makes sense for arrays.
+
+
+* Add limited support for preserving comments?
+
+
+* Add support for unicode strings? A bit problematic, since flex doesn't
+  support unicode input, AFAICT. But maybe supply convenience functions to
+  convert between parsed UTF-8 strings and std::wstring.
diff --git a/3rdparty/libconfig/grammar.c b/3rdparty/libconfig/grammar.c
new file mode 100644
index 0000000..cd1105c
--- /dev/null
+++ b/3rdparty/libconfig/grammar.c
@@ -0,0 +1,2001 @@
+
+/* A Bison parser, made by GNU Bison 2.4.1.  */
+
+/* Skeleton implementation for Bison's Yacc-like parsers in C
+   
+      Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006
+   Free Software Foundation, Inc.
+   
+   This program is free software: you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation, either version 3 of the License, or
+   (at your option) any later version.
+   
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+   
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+/* As a special exception, you may create a larger work that contains
+   part or all of the Bison parser skeleton and distribute that work
+   under terms of your choice, so long as that work isn't itself a
+   parser generator using the skeleton or a modified version thereof
+   as a parser skeleton.  Alternatively, if you modify or redistribute
+   the parser skeleton itself, you may (at your option) remove this
+   special exception, which will cause the skeleton and the resulting
+   Bison output files to be licensed under the GNU General Public
+   License without this special exception.
+   
+   This special exception was added by the Free Software Foundation in
+   version 2.2 of Bison.  */
+
+/* C LALR(1) parser skeleton written by Richard Stallman, by
+   simplifying the original so-called "semantic" parser.  */
+
+/* All symbols defined below should begin with yy or YY, to avoid
+   infringing on user name space.  This should be done even for local
+   variables, as they might otherwise be expanded by user macros.
+   There are some unavoidable exceptions within include files to
+   define necessary library symbols; they are noted "INFRINGES ON
+   USER NAME SPACE" below.  */
+
+/* Identify Bison output.  */
+#define YYBISON 1
+
+/* Bison version.  */
+#define YYBISON_VERSION "2.4.1"
+
+/* Skeleton name.  */
+#define YYSKELETON_NAME "yacc.c"
+
+/* Pure parsers.  */
+#define YYPURE 1
+
+/* Push parsers.  */
+#define YYPUSH 0
+
+/* Pull parsers.  */
+#define YYPULL 1
+
+/* Using locations.  */
+#define YYLSP_NEEDED 0
+
+/* Substitute the variable and function names.  */
+#define yyparse         libconfig_yyparse
+#define yylex           libconfig_yylex
+#define yyerror         libconfig_yyerror
+#define yylval          libconfig_yylval
+#define yychar          libconfig_yychar
+#define yydebug         libconfig_yydebug
+#define yynerrs         libconfig_yynerrs
+
+
+/* Copy the first part of user declarations.  */
+
+/* Line 189 of yacc.c  */
+#line 32 "grammar.y"
+
+#include <string.h>
+#include <stdlib.h>
+#include "libconfig.h"
+#ifdef WIN32
+#include "wincompat.h"
+
+/* prevent warnings about redefined malloc/free in generated code: */
+#ifndef _STDLIB_H
+#define _STDLIB_H
+#endif
+
+#include <malloc.h>
+#endif
+#include "parsectx.h"
+#include "scanctx.h"
+
+/* these delcarations are provided to suppress compiler warnings */
+extern int libconfig_yylex();
+extern int libconfig_yyget_lineno();
+
+static const char *err_array_elem_type = "mismatched element type in array";
+static const char *err_duplicate_setting = "duplicate setting name";
+
+#define _delete(P) free((void *)(P))
+
+#define IN_ARRAY() \
+  (ctx->parent && (ctx->parent->type == CONFIG_TYPE_ARRAY))
+
+#define IN_LIST() \
+  (ctx->parent && (ctx->parent->type == CONFIG_TYPE_LIST))
+
+static void capture_parse_pos(void *scanner, struct scan_context *scan_ctx,
+                              config_setting_t *setting)
+{
+  setting->line = (unsigned int)libconfig_yyget_lineno(scanner);
+  setting->file = scanctx_current_filename(scan_ctx);
+}
+
+#define CAPTURE_PARSE_POS(S) \
+  capture_parse_pos(scanner, scan_ctx, (S))
+
+void libconfig_yyerror(void *scanner, struct parse_context *ctx,
+                       struct scan_context *scan_ctx, char const *s)
+{
+  if(ctx->config->error_text) return;
+  ctx->config->error_line = libconfig_yyget_lineno(scanner);
+  ctx->config->error_text = s;
+}
+
+
+
+/* Line 189 of yacc.c  */
+#line 134 "grammar.c"
+
+/* Enabling traces.  */
+#ifndef YYDEBUG
+# define YYDEBUG 0
+#endif
+
+/* Enabling verbose error messages.  */
+#ifdef YYERROR_VERBOSE
+# undef YYERROR_VERBOSE
+# define YYERROR_VERBOSE 1
+#else
+# define YYERROR_VERBOSE 0
+#endif
+
+/* Enabling the token table.  */
+#ifndef YYTOKEN_TABLE
+# define YYTOKEN_TABLE 0
+#endif
+
+
+/* Tokens.  */
+#ifndef YYTOKENTYPE
+# define YYTOKENTYPE
+   /* Put the tokens into the symbol table, so that GDB and other debuggers
+      know about them.  */
+   enum yytokentype {
+     TOK_BOOLEAN = 258,
+     TOK_INTEGER = 259,
+     TOK_HEX = 260,
+     TOK_INTEGER64 = 261,
+     TOK_HEX64 = 262,
+     TOK_FLOAT = 263,
+     TOK_STRING = 264,
+     TOK_NAME = 265,
+     TOK_EQUALS = 266,
+     TOK_NEWLINE = 267,
+     TOK_ARRAY_START = 268,
+     TOK_ARRAY_END = 269,
+     TOK_LIST_START = 270,
+     TOK_LIST_END = 271,
+     TOK_COMMA = 272,
+     TOK_GROUP_START = 273,
+     TOK_GROUP_END = 274,
+     TOK_END = 275,
+     TOK_GARBAGE = 276,
+     TOK_ERROR = 277
+   };
+#endif
+/* Tokens.  */
+#define TOK_BOOLEAN 258
+#define TOK_INTEGER 259
+#define TOK_HEX 260
+#define TOK_INTEGER64 261
+#define TOK_HEX64 262
+#define TOK_FLOAT 263
+#define TOK_STRING 264
+#define TOK_NAME 265
+#define TOK_EQUALS 266
+#define TOK_NEWLINE 267
+#define TOK_ARRAY_START 268
+#define TOK_ARRAY_END 269
+#define TOK_LIST_START 270
+#define TOK_LIST_END 271
+#define TOK_COMMA 272
+#define TOK_GROUP_START 273
+#define TOK_GROUP_END 274
+#define TOK_END 275
+#define TOK_GARBAGE 276
+#define TOK_ERROR 277
+
+
+
+
+#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
+typedef union YYSTYPE
+{
+
+/* Line 214 of yacc.c  */
+#line 85 "grammar.y"
+
+  int ival;
+  long long llval;
+  double fval;
+  char *sval;
+
+
+
+/* Line 214 of yacc.c  */
+#line 223 "grammar.c"
+} YYSTYPE;
+# define YYSTYPE_IS_TRIVIAL 1
+# define yystype YYSTYPE /* obsolescent; will be withdrawn */
+# define YYSTYPE_IS_DECLARED 1
+#endif
+
+
+/* Copy the second part of user declarations.  */
+
+
+/* Line 264 of yacc.c  */
+#line 235 "grammar.c"
+
+#ifdef short
+# undef short
+#endif
+
+#ifdef YYTYPE_UINT8
+typedef YYTYPE_UINT8 yytype_uint8;
+#else
+typedef unsigned char yytype_uint8;
+#endif
+
+#ifdef YYTYPE_INT8
+typedef YYTYPE_INT8 yytype_int8;
+#elif (defined __STDC__ || defined __C99__FUNC__ \
+     || defined __cplusplus || defined _MSC_VER)
+typedef signed char yytype_int8;
+#else
+typedef short int yytype_int8;
+#endif
+
+#ifdef YYTYPE_UINT16
+typedef YYTYPE_UINT16 yytype_uint16;
+#else
+typedef unsigned short int yytype_uint16;
+#endif
+
+#ifdef YYTYPE_INT16
+typedef YYTYPE_INT16 yytype_int16;
+#else
+typedef short int yytype_int16;
+#endif
+
+#ifndef YYSIZE_T
+# ifdef __SIZE_TYPE__
+#  define YYSIZE_T __SIZE_TYPE__
+# elif defined size_t
+#  define YYSIZE_T size_t
+# elif ! defined YYSIZE_T && (defined __STDC__ || defined __C99__FUNC__ \
+     || defined __cplusplus || defined _MSC_VER)
+#  include <stddef.h> /* INFRINGES ON USER NAME SPACE */
+#  define YYSIZE_T size_t
+# else
+#  define YYSIZE_T unsigned int
+# endif
+#endif
+
+#define YYSIZE_MAXIMUM ((YYSIZE_T) -1)
+
+#ifndef YY_
+# if YYENABLE_NLS
+#  if ENABLE_NLS
+#   include <libintl.h> /* INFRINGES ON USER NAME SPACE */
+#   define YY_(msgid) dgettext ("bison-runtime", msgid)
+#  endif
+# endif
+# ifndef YY_
+#  define YY_(msgid) msgid
+# endif
+#endif
+
+/* Suppress unused-variable warnings by "using" E.  */
+#if ! defined lint || defined __GNUC__
+# define YYUSE(e) ((void) (e))
+#else
+# define YYUSE(e) /* empty */
+#endif
+
+/* Identity function, used to suppress warnings about constant conditions.  */
+#ifndef lint
+# define YYID(n) (n)
+#else
+#if (defined __STDC__ || defined __C99__FUNC__ \
+     || defined __cplusplus || defined _MSC_VER)
+static int
+YYID (int yyi)
+#else
+static int
+YYID (yyi)
+    int yyi;
+#endif
+{
+  return yyi;
+}
+#endif
+
+#if ! defined yyoverflow || YYERROR_VERBOSE
+
+/* The parser invokes alloca or malloc; define the necessary symbols.  */
+
+# ifdef YYSTACK_USE_ALLOCA
+#  if YYSTACK_USE_ALLOCA
+#   ifdef __GNUC__
+#    define YYSTACK_ALLOC __builtin_alloca
+#   elif defined __BUILTIN_VA_ARG_INCR
+#    include <alloca.h> /* INFRINGES ON USER NAME SPACE */
+#   elif defined _AIX
+#    define YYSTACK_ALLOC __alloca
+#   elif defined _MSC_VER
+#    include <malloc.h> /* INFRINGES ON USER NAME SPACE */
+#    define alloca _alloca
+#   else
+#    define YYSTACK_ALLOC alloca
+#    if ! defined _ALLOCA_H && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \
+     || defined __cplusplus || defined _MSC_VER)
+#     include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
+#     ifndef _STDLIB_H
+#      define _STDLIB_H 1
+#     endif
+#    endif
+#   endif
+#  endif
+# endif
+
+# ifdef YYSTACK_ALLOC
+   /* Pacify GCC's `empty if-body' warning.  */
+#  define YYSTACK_FREE(Ptr) do { /* empty */; } while (YYID (0))
+#  ifndef YYSTACK_ALLOC_MAXIMUM
+    /* The OS might guarantee only one guard page at the bottom of the stack,
+       and a page size can be as small as 4096 bytes.  So we cannot safely
+       invoke alloca (N) if N exceeds 4096.  Use a slightly smaller number
+       to allow for a few compiler-allocated temporary stack slots.  */
+#   define YYSTACK_ALLOC_MAXIMUM 4032 /* reasonable circa 2006 */
+#  endif
+# else
+#  define YYSTACK_ALLOC YYMALLOC
+#  define YYSTACK_FREE YYFREE
+#  ifndef YYSTACK_ALLOC_MAXIMUM
+#   define YYSTACK_ALLOC_MAXIMUM YYSIZE_MAXIMUM
+#  endif
+#  if (defined __cplusplus && ! defined _STDLIB_H \
+       && ! ((defined YYMALLOC || defined malloc) \
+	     && (defined YYFREE || defined free)))
+#   include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
+#   ifndef _STDLIB_H
+#    define _STDLIB_H 1
+#   endif
+#  endif
+#  ifndef YYMALLOC
+#   define YYMALLOC malloc
+#   if ! defined malloc && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \
+     || defined __cplusplus || defined _MSC_VER)
+void *malloc (YYSIZE_T); /* INFRINGES ON USER NAME SPACE */
+#   endif
+#  endif
+#  ifndef YYFREE
+#   define YYFREE free
+#   if ! defined free && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \
+     || defined __cplusplus || defined _MSC_VER)
+void free (void *); /* INFRINGES ON USER NAME SPACE */
+#   endif
+#  endif
+# endif
+#endif /* ! defined yyoverflow || YYERROR_VERBOSE */
+
+
+#if (! defined yyoverflow \
+     && (! defined __cplusplus \
+	 || (defined YYSTYPE_IS_TRIVIAL && YYSTYPE_IS_TRIVIAL)))
+
+/* A type that is properly aligned for any stack member.  */
+union yyalloc
+{
+  yytype_int16 yyss_alloc;
+  YYSTYPE yyvs_alloc;
+};
+
+/* The size of the maximum gap between one aligned stack and the next.  */
+# define YYSTACK_GAP_MAXIMUM (sizeof (union yyalloc) - 1)
+
+/* The size of an array large to enough to hold all stacks, each with
+   N elements.  */
+# define YYSTACK_BYTES(N) \
+     ((N) * (sizeof (yytype_int16) + sizeof (YYSTYPE)) \
+      + YYSTACK_GAP_MAXIMUM)
+
+/* Copy COUNT objects from FROM to TO.  The source and destination do
+   not overlap.  */
+# ifndef YYCOPY
+#  if defined __GNUC__ && 1 < __GNUC__
+#   define YYCOPY(To, From, Count) \
+      __builtin_memcpy (To, From, (Count) * sizeof (*(From)))
+#  else
+#   define YYCOPY(To, From, Count)		\
+      do					\
+	{					\
+	  YYSIZE_T yyi;				\
+	  for (yyi = 0; yyi < (Count); yyi++)	\
+	    (To)[yyi] = (From)[yyi];		\
+	}					\
+      while (YYID (0))
+#  endif
+# endif
+
+/* Relocate STACK from its old location to the new one.  The
+   local variables YYSIZE and YYSTACKSIZE give the old and new number of
+   elements in the stack, and YYPTR gives the new location of the
+   stack.  Advance YYPTR to a properly aligned location for the next
+   stack.  */
+# define YYSTACK_RELOCATE(Stack_alloc, Stack)				\
+    do									\
+      {									\
+	YYSIZE_T yynewbytes;						\
+	YYCOPY (&yyptr->Stack_alloc, Stack, yysize);			\
+	Stack = &yyptr->Stack_alloc;					\
+	yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \
+	yyptr += yynewbytes / sizeof (*yyptr);				\
+      }									\
+    while (YYID (0))
+
+#endif
+
+/* YYFINAL -- State number of the termination state.  */
+#define YYFINAL  6
+/* YYLAST -- Last index in YYTABLE.  */
+#define YYLAST   33
+
+/* YYNTOKENS -- Number of terminals.  */
+#define YYNTOKENS  23
+/* YYNNTS -- Number of nonterminals.  */
+#define YYNNTS  19
+/* YYNRULES -- Number of rules.  */
+#define YYNRULES  36
+/* YYNRULES -- Number of states.  */
+#define YYNSTATES  45
+
+/* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX.  */
+#define YYUNDEFTOK  2
+#define YYMAXUTOK   277
+
+#define YYTRANSLATE(YYX)						\
+  ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK)
+
+/* YYTRANSLATE[YYLEX] -- Bison symbol number corresponding to YYLEX.  */
+static const yytype_uint8 yytranslate[] =
+{
+       0,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     1,     2,     3,     4,
+       5,     6,     7,     8,     9,    10,    11,    12,    13,    14,
+      15,    16,    17,    18,    19,    20,    21,    22
+};
+
+#if YYDEBUG
+/* YYPRHS[YYN] -- Index of the first RHS symbol of rule number YYN in
+   YYRHS.  */
+static const yytype_uint8 yyprhs[] =
+{
+       0,     0,     3,     4,     6,     8,    11,    12,    14,    15,
+      21,    22,    27,    28,    33,    35,    37,    39,    41,    43,
+      46,    48,    50,    52,    54,    56,    58,    60,    62,    66,
+      67,    69,    71,    75,    76,    78,    79
+};
+
+/* YYRHS -- A `-1'-separated list of the rules' RHS.  */
+static const yytype_int8 yyrhs[] =
+{
+      24,     0,    -1,    -1,    25,    -1,    27,    -1,    25,    27,
+      -1,    -1,    25,    -1,    -1,    10,    28,    11,    33,    20,
+      -1,    -1,    13,    30,    39,    14,    -1,    -1,    15,    32,
+      37,    16,    -1,    35,    -1,    29,    -1,    31,    -1,    40,
+      -1,     9,    -1,    34,     9,    -1,     3,    -1,     4,    -1,
+       6,    -1,     5,    -1,     7,    -1,     8,    -1,    34,    -1,
+      33,    -1,    36,    17,    33,    -1,    -1,    36,    -1,    35,
+      -1,    38,    17,    35,    -1,    -1,    38,    -1,    -1,    18,
+      41,    26,    19,    -1
+};
+
+/* YYRLINE[YYN] -- source line where rule number YYN was defined.  */
+static const yytype_uint16 yyrline[] =
+{
+       0,   100,   100,   102,   106,   107,   110,   112,   117,   116,
+     136,   135,   159,   158,   181,   182,   183,   184,   188,   189,
+     193,   213,   235,   257,   279,   301,   319,   347,   348,   351,
+     353,   357,   358,   361,   363,   368,   367
+};
+#endif
+
+#if YYDEBUG || YYERROR_VERBOSE || YYTOKEN_TABLE
+/* YYTNAME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM.
+   First, the terminals, then, starting at YYNTOKENS, nonterminals.  */
+static const char *const yytname[] =
+{
+  "$end", "error", "$undefined", "TOK_BOOLEAN", "TOK_INTEGER", "TOK_HEX",
+  "TOK_INTEGER64", "TOK_HEX64", "TOK_FLOAT", "TOK_STRING", "TOK_NAME",
+  "TOK_EQUALS", "TOK_NEWLINE", "TOK_ARRAY_START", "TOK_ARRAY_END",
+  "TOK_LIST_START", "TOK_LIST_END", "TOK_COMMA", "TOK_GROUP_START",
+  "TOK_GROUP_END", "TOK_END", "TOK_GARBAGE", "TOK_ERROR", "$accept",
+  "configuration", "setting_list", "setting_list_optional", "setting",
+  "$@1", "array", "$@2", "list", "$@3", "value", "string", "simple_value",
+  "value_list", "value_list_optional", "simple_value_list",
+  "simple_value_list_optional", "group", "$@4", 0
+};
+#endif
+
+# ifdef YYPRINT
+/* YYTOKNUM[YYLEX-NUM] -- Internal token number corresponding to
+   token YYLEX-NUM.  */
+static const yytype_uint16 yytoknum[] =
+{
+       0,   256,   257,   258,   259,   260,   261,   262,   263,   264,
+     265,   266,   267,   268,   269,   270,   271,   272,   273,   274,
+     275,   276,   277
+};
+# endif
+
+/* YYR1[YYN] -- Symbol number of symbol that rule YYN derives.  */
+static const yytype_uint8 yyr1[] =
+{
+       0,    23,    24,    24,    25,    25,    26,    26,    28,    27,
+      30,    29,    32,    31,    33,    33,    33,    33,    34,    34,
+      35,    35,    35,    35,    35,    35,    35,    36,    36,    37,
+      37,    38,    38,    39,    39,    41,    40
+};
+
+/* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN.  */
+static const yytype_uint8 yyr2[] =
+{
+       0,     2,     0,     1,     1,     2,     0,     1,     0,     5,
+       0,     4,     0,     4,     1,     1,     1,     1,     1,     2,
+       1,     1,     1,     1,     1,     1,     1,     1,     3,     0,
+       1,     1,     3,     0,     1,     0,     4
+};
+
+/* YYDEFACT[STATE-NAME] -- Default rule to reduce with in state
+   STATE-NUM when YYTABLE doesn't specify something else to do.  Zero
+   means the default is an error.  */
+static const yytype_uint8 yydefact[] =
+{
+       2,     8,     0,     3,     4,     0,     1,     5,     0,    20,
+      21,    23,    22,    24,    25,    18,    10,    12,    35,    15,
+      16,     0,    26,    14,    17,    33,    29,     6,     9,    19,
+      31,    34,     0,    27,    30,     0,     7,     0,     0,    11,
+       0,    13,    36,    32,    28
+};
+
+/* YYDEFGOTO[NTERM-NUM].  */
+static const yytype_int8 yydefgoto[] =
+{
+      -1,     2,     3,    37,     4,     5,    19,    25,    20,    26,
+      21,    22,    23,    34,    35,    31,    32,    24,    27
+};
+
+/* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing
+   STATE-NUM.  */
+#define YYPACT_NINF -19
+static const yytype_int8 yypact[] =
+{
+      -1,   -19,    12,    -1,   -19,     3,   -19,   -19,    -2,   -19,
+     -19,   -19,   -19,   -19,   -19,   -19,   -19,   -19,   -19,   -19,
+     -19,    -5,     8,   -19,   -19,    21,    -2,    -1,   -19,   -19,
+     -19,     1,     5,   -19,     4,    15,    -1,    13,    21,   -19,
+      -2,   -19,   -19,   -19,   -19
+};
+
+/* YYPGOTO[NTERM-NUM].  */
+static const yytype_int8 yypgoto[] =
+{
+     -19,   -19,    -7,   -19,    -3,   -19,   -19,   -19,   -19,   -19,
+     -18,   -19,   -15,   -19,   -19,   -19,   -19,   -19,   -19
+};
+
+/* YYTABLE[YYPACT[STATE-NUM]].  What to do in state STATE-NUM.  If
+   positive, shift that token.  If negative, reduce the rule which
+   number is the opposite.  If zero, do what YYDEFACT says.
+   If YYTABLE_NINF, syntax error.  */
+#define YYTABLE_NINF -1
+static const yytype_uint8 yytable[] =
+{
+       7,     9,    10,    11,    12,    13,    14,    15,    33,     1,
+      30,    16,     6,    17,     8,    28,    18,    29,    38,    39,
+      36,    40,    44,    43,     9,    10,    11,    12,    13,    14,
+      15,    41,    42,     7
+};
+
+static const yytype_uint8 yycheck[] =
+{
+       3,     3,     4,     5,     6,     7,     8,     9,    26,    10,
+      25,    13,     0,    15,    11,    20,    18,     9,    17,    14,
+      27,    17,    40,    38,     3,     4,     5,     6,     7,     8,
+       9,    16,    19,    36
+};
+
+/* YYSTOS[STATE-NUM] -- The (internal number of the) accessing
+   symbol of state STATE-NUM.  */
+static const yytype_uint8 yystos[] =
+{
+       0,    10,    24,    25,    27,    28,     0,    27,    11,     3,
+       4,     5,     6,     7,     8,     9,    13,    15,    18,    29,
+      31,    33,    34,    35,    40,    30,    32,    41,    20,     9,
+      35,    38,    39,    33,    36,    37,    25,    26,    17,    14,
+      17,    16,    19,    35,    33
+};
+
+#define yyerrok		(yyerrstatus = 0)
+#define yyclearin	(yychar = YYEMPTY)
+#define YYEMPTY		(-2)
+#define YYEOF		0
+
+#define YYACCEPT	goto yyacceptlab
+#define YYABORT		goto yyabortlab
+#define YYERROR		goto yyerrorlab
+
+
+/* Like YYERROR except do call yyerror.  This remains here temporarily
+   to ease the transition to the new meaning of YYERROR, for GCC.
+   Once GCC version 2 has supplanted version 1, this can go.  */
+
+#define YYFAIL		goto yyerrlab
+
+#define YYRECOVERING()  (!!yyerrstatus)
+
+#define YYBACKUP(Token, Value)					\
+do								\
+  if (yychar == YYEMPTY && yylen == 1)				\
+    {								\
+      yychar = (Token);						\
+      yylval = (Value);						\
+      yytoken = YYTRANSLATE (yychar);				\
+      YYPOPSTACK (1);						\
+      goto yybackup;						\
+    }								\
+  else								\
+    {								\
+      yyerror (scanner, ctx, scan_ctx, YY_("syntax error: cannot back up")); \
+      YYERROR;							\
+    }								\
+while (YYID (0))
+
+
+#define YYTERROR	1
+#define YYERRCODE	256
+
+
+/* YYLLOC_DEFAULT -- Set CURRENT to span from RHS[1] to RHS[N].
+   If N is 0, then set CURRENT to the empty location which ends
+   the previous symbol: RHS[0] (always defined).  */
+
+#define YYRHSLOC(Rhs, K) ((Rhs)[K])
+#ifndef YYLLOC_DEFAULT
+# define YYLLOC_DEFAULT(Current, Rhs, N)				\
+    do									\
+      if (YYID (N))                                                    \
+	{								\
+	  (Current).first_line   = YYRHSLOC (Rhs, 1).first_line;	\
+	  (Current).first_column = YYRHSLOC (Rhs, 1).first_column;	\
+	  (Current).last_line    = YYRHSLOC (Rhs, N).last_line;		\
+	  (Current).last_column  = YYRHSLOC (Rhs, N).last_column;	\
+	}								\
+      else								\
+	{								\
+	  (Current).first_line   = (Current).last_line   =		\
+	    YYRHSLOC (Rhs, 0).last_line;				\
+	  (Current).first_column = (Current).last_column =		\
+	    YYRHSLOC (Rhs, 0).last_column;				\
+	}								\
+    while (YYID (0))
+#endif
+
+
+/* YY_LOCATION_PRINT -- Print the location on the stream.
+   This macro was not mandated originally: define only if we know
+   we won't break user code: when these are the locations we know.  */
+
+#ifndef YY_LOCATION_PRINT
+# if YYLTYPE_IS_TRIVIAL
+#  define YY_LOCATION_PRINT(File, Loc)			\
+     fprintf (File, "%d.%d-%d.%d",			\
+	      (Loc).first_line, (Loc).first_column,	\
+	      (Loc).last_line,  (Loc).last_column)
+# else
+#  define YY_LOCATION_PRINT(File, Loc) ((void) 0)
+# endif
+#endif
+
+
+/* YYLEX -- calling `yylex' with the right arguments.  */
+
+#ifdef YYLEX_PARAM
+# define YYLEX yylex (&yylval, YYLEX_PARAM)
+#else
+# define YYLEX yylex (&yylval, scanner)
+#endif
+
+/* Enable debugging if requested.  */
+#if YYDEBUG
+
+# ifndef YYFPRINTF
+#  include <stdio.h> /* INFRINGES ON USER NAME SPACE */
+#  define YYFPRINTF fprintf
+# endif
+
+# define YYDPRINTF(Args)			\
+do {						\
+  if (yydebug)					\
+    YYFPRINTF Args;				\
+} while (YYID (0))
+
+# define YY_SYMBOL_PRINT(Title, Type, Value, Location)			  \
+do {									  \
+  if (yydebug)								  \
+    {									  \
+      YYFPRINTF (stderr, "%s ", Title);					  \
+      yy_symbol_print (stderr,						  \
+		  Type, Value, scanner, ctx, scan_ctx); \
+      YYFPRINTF (stderr, "\n");						  \
+    }									  \
+} while (YYID (0))
+
+
+/*--------------------------------.
+| Print this symbol on YYOUTPUT.  |
+`--------------------------------*/
+
+/*ARGSUSED*/
+#if (defined __STDC__ || defined __C99__FUNC__ \
+     || defined __cplusplus || defined _MSC_VER)
+static void
+yy_symbol_value_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep, void *scanner, struct parse_context *ctx, struct scan_context *scan_ctx)
+#else
+static void
+yy_symbol_value_print (yyoutput, yytype, yyvaluep, scanner, ctx, scan_ctx)
+    FILE *yyoutput;
+    int yytype;
+    YYSTYPE const * const yyvaluep;
+    void *scanner;
+    struct parse_context *ctx;
+    struct scan_context *scan_ctx;
+#endif
+{
+  if (!yyvaluep)
+    return;
+  YYUSE (scanner);
+  YYUSE (ctx);
+  YYUSE (scan_ctx);
+# ifdef YYPRINT
+  if (yytype < YYNTOKENS)
+    YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep);
+# else
+  YYUSE (yyoutput);
+# endif
+  switch (yytype)
+    {
+      default:
+	break;
+    }
+}
+
+
+/*--------------------------------.
+| Print this symbol on YYOUTPUT.  |
+`--------------------------------*/
+
+#if (defined __STDC__ || defined __C99__FUNC__ \
+     || defined __cplusplus || defined _MSC_VER)
+static void
+yy_symbol_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep, void *scanner, struct parse_context *ctx, struct scan_context *scan_ctx)
+#else
+static void
+yy_symbol_print (yyoutput, yytype, yyvaluep, scanner, ctx, scan_ctx)
+    FILE *yyoutput;
+    int yytype;
+    YYSTYPE const * const yyvaluep;
+    void *scanner;
+    struct parse_context *ctx;
+    struct scan_context *scan_ctx;
+#endif
+{
+  if (yytype < YYNTOKENS)
+    YYFPRINTF (yyoutput, "token %s (", yytname[yytype]);
+  else
+    YYFPRINTF (yyoutput, "nterm %s (", yytname[yytype]);
+
+  yy_symbol_value_print (yyoutput, yytype, yyvaluep, scanner, ctx, scan_ctx);
+  YYFPRINTF (yyoutput, ")");
+}
+
+/*------------------------------------------------------------------.
+| yy_stack_print -- Print the state stack from its BOTTOM up to its |
+| TOP (included).                                                   |
+`------------------------------------------------------------------*/
+
+#if (defined __STDC__ || defined __C99__FUNC__ \
+     || defined __cplusplus || defined _MSC_VER)
+static void
+yy_stack_print (yytype_int16 *yybottom, yytype_int16 *yytop)
+#else
+static void
+yy_stack_print (yybottom, yytop)
+    yytype_int16 *yybottom;
+    yytype_int16 *yytop;
+#endif
+{
+  YYFPRINTF (stderr, "Stack now");
+  for (; yybottom <= yytop; yybottom++)
+    {
+      int yybot = *yybottom;
+      YYFPRINTF (stderr, " %d", yybot);
+    }
+  YYFPRINTF (stderr, "\n");
+}
+
+# define YY_STACK_PRINT(Bottom, Top)				\
+do {								\
+  if (yydebug)							\
+    yy_stack_print ((Bottom), (Top));				\
+} while (YYID (0))
+
+
+/*------------------------------------------------.
+| Report that the YYRULE is going to be reduced.  |
+`------------------------------------------------*/
+
+#if (defined __STDC__ || defined __C99__FUNC__ \
+     || defined __cplusplus || defined _MSC_VER)
+static void
+yy_reduce_print (YYSTYPE *yyvsp, int yyrule, void *scanner, struct parse_context *ctx, struct scan_context *scan_ctx)
+#else
+static void
+yy_reduce_print (yyvsp, yyrule, scanner, ctx, scan_ctx)
+    YYSTYPE *yyvsp;
+    int yyrule;
+    void *scanner;
+    struct parse_context *ctx;
+    struct scan_context *scan_ctx;
+#endif
+{
+  int yynrhs = yyr2[yyrule];
+  int yyi;
+  unsigned long int yylno = yyrline[yyrule];
+  YYFPRINTF (stderr, "Reducing stack by rule %d (line %lu):\n",
+	     yyrule - 1, yylno);
+  /* The symbols being reduced.  */
+  for (yyi = 0; yyi < yynrhs; yyi++)
+    {
+      YYFPRINTF (stderr, "   $%d = ", yyi + 1);
+      yy_symbol_print (stderr, yyrhs[yyprhs[yyrule] + yyi],
+		       &(yyvsp[(yyi + 1) - (yynrhs)])
+		       		       , scanner, ctx, scan_ctx);
+      YYFPRINTF (stderr, "\n");
+    }
+}
+
+# define YY_REDUCE_PRINT(Rule)		\
+do {					\
+  if (yydebug)				\
+    yy_reduce_print (yyvsp, Rule, scanner, ctx, scan_ctx); \
+} while (YYID (0))
+
+/* Nonzero means print parse trace.  It is left uninitialized so that
+   multiple parsers can coexist.  */
+int yydebug;
+#else /* !YYDEBUG */
+# define YYDPRINTF(Args)
+# define YY_SYMBOL_PRINT(Title, Type, Value, Location)
+# define YY_STACK_PRINT(Bottom, Top)
+# define YY_REDUCE_PRINT(Rule)
+#endif /* !YYDEBUG */
+
+
+/* YYINITDEPTH -- initial size of the parser's stacks.  */
+#ifndef	YYINITDEPTH
+# define YYINITDEPTH 200
+#endif
+
+/* YYMAXDEPTH -- maximum size the stacks can grow to (effective only
+   if the built-in stack extension method is used).
+
+   Do not make this value too large; the results are undefined if
+   YYSTACK_ALLOC_MAXIMUM < YYSTACK_BYTES (YYMAXDEPTH)
+   evaluated with infinite-precision integer arithmetic.  */
+
+#ifndef YYMAXDEPTH
+# define YYMAXDEPTH 10000
+#endif
+
+

+
+#if YYERROR_VERBOSE
+
+# ifndef yystrlen
+#  if defined __GLIBC__ && defined _STRING_H
+#   define yystrlen strlen
+#  else
+/* Return the length of YYSTR.  */
+#if (defined __STDC__ || defined __C99__FUNC__ \
+     || defined __cplusplus || defined _MSC_VER)
+static YYSIZE_T
+yystrlen (const char *yystr)
+#else
+static YYSIZE_T
+yystrlen (yystr)
+    const char *yystr;
+#endif
+{
+  YYSIZE_T yylen;
+  for (yylen = 0; yystr[yylen]; yylen++)
+    continue;
+  return yylen;
+}
+#  endif
+# endif
+
+# ifndef yystpcpy
+#  if defined __GLIBC__ && defined _STRING_H && defined _GNU_SOURCE
+#   define yystpcpy stpcpy
+#  else
+/* Copy YYSRC to YYDEST, returning the address of the terminating '\0' in
+   YYDEST.  */
+#if (defined __STDC__ || defined __C99__FUNC__ \
+     || defined __cplusplus || defined _MSC_VER)
+static char *
+yystpcpy (char *yydest, const char *yysrc)
+#else
+static char *
+yystpcpy (yydest, yysrc)
+    char *yydest;
+    const char *yysrc;
+#endif
+{
+  char *yyd = yydest;
+  const char *yys = yysrc;
+
+  while ((*yyd++ = *yys++) != '\0')
+    continue;
+
+  return yyd - 1;
+}
+#  endif
+# endif
+
+# ifndef yytnamerr
+/* Copy to YYRES the contents of YYSTR after stripping away unnecessary
+   quotes and backslashes, so that it's suitable for yyerror.  The
+   heuristic is that double-quoting is unnecessary unless the string
+   contains an apostrophe, a comma, or backslash (other than
+   backslash-backslash).  YYSTR is taken from yytname.  If YYRES is
+   null, do not copy; instead, return the length of what the result
+   would have been.  */
+static YYSIZE_T
+yytnamerr (char *yyres, const char *yystr)
+{
+  if (*yystr == '"')
+    {
+      YYSIZE_T yyn = 0;
+      char const *yyp = yystr;
+
+      for (;;)
+	switch (*++yyp)
+	  {
+	  case '\'':
+	  case ',':
+	    goto do_not_strip_quotes;
+
+	  case '\\':
+	    if (*++yyp != '\\')
+	      goto do_not_strip_quotes;
+	    /* Fall through.  */
+	  default:
+	    if (yyres)
+	      yyres[yyn] = *yyp;
+	    yyn++;
+	    break;
+
+	  case '"':
+	    if (yyres)
+	      yyres[yyn] = '\0';
+	    return yyn;
+	  }
+    do_not_strip_quotes: ;
+    }
+
+  if (! yyres)
+    return yystrlen (yystr);
+
+  return yystpcpy (yyres, yystr) - yyres;
+}
+# endif
+
+/* Copy into YYRESULT an error message about the unexpected token
+   YYCHAR while in state YYSTATE.  Return the number of bytes copied,
+   including the terminating null byte.  If YYRESULT is null, do not
+   copy anything; just return the number of bytes that would be
+   copied.  As a special case, return 0 if an ordinary "syntax error"
+   message will do.  Return YYSIZE_MAXIMUM if overflow occurs during
+   size calculation.  */
+static YYSIZE_T
+yysyntax_error (char *yyresult, int yystate, int yychar)
+{
+  int yyn = yypact[yystate];
+
+  if (! (YYPACT_NINF < yyn && yyn <= YYLAST))
+    return 0;
+  else
+    {
+      int yytype = YYTRANSLATE (yychar);
+      YYSIZE_T yysize0 = yytnamerr (0, yytname[yytype]);
+      YYSIZE_T yysize = yysize0;
+      YYSIZE_T yysize1;
+      int yysize_overflow = 0;
+      enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 };
+      char const *yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM];
+      int yyx;
+
+# if 0
+      /* This is so xgettext sees the translatable formats that are
+	 constructed on the fly.  */
+      YY_("syntax error, unexpected %s");
+      YY_("syntax error, unexpected %s, expecting %s");
+      YY_("syntax error, unexpected %s, expecting %s or %s");
+      YY_("syntax error, unexpected %s, expecting %s or %s or %s");
+      YY_("syntax error, unexpected %s, expecting %s or %s or %s or %s");
+# endif
+      char *yyfmt;
+      char const *yyf;
+      static char const yyunexpected[] = "syntax error, unexpected %s";
+      static char const yyexpecting[] = ", expecting %s";
+      static char const yyor[] = " or %s";
+      char yyformat[sizeof yyunexpected
+		    + sizeof yyexpecting - 1
+		    + ((YYERROR_VERBOSE_ARGS_MAXIMUM - 2)
+		       * (sizeof yyor - 1))];
+      char const *yyprefix = yyexpecting;
+
+      /* Start YYX at -YYN if negative to avoid negative indexes in
+	 YYCHECK.  */
+      int yyxbegin = yyn < 0 ? -yyn : 0;
+
+      /* Stay within bounds of both yycheck and yytname.  */
+      int yychecklim = YYLAST - yyn + 1;
+      int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS;
+      int yycount = 1;
+
+      yyarg[0] = yytname[yytype];
+      yyfmt = yystpcpy (yyformat, yyunexpected);
+
+      for (yyx = yyxbegin; yyx < yyxend; ++yyx)
+	if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR)
+	  {
+	    if (yycount == YYERROR_VERBOSE_ARGS_MAXIMUM)
+	      {
+		yycount = 1;
+		yysize = yysize0;
+		yyformat[sizeof yyunexpected - 1] = '\0';
+		break;
+	      }
+	    yyarg[yycount++] = yytname[yyx];
+	    yysize1 = yysize + yytnamerr (0, yytname[yyx]);
+	    yysize_overflow |= (yysize1 < yysize);
+	    yysize = yysize1;
+	    yyfmt = yystpcpy (yyfmt, yyprefix);
+	    yyprefix = yyor;
+	  }
+
+      yyf = YY_(yyformat);
+      yysize1 = yysize + yystrlen (yyf);
+      yysize_overflow |= (yysize1 < yysize);
+      yysize = yysize1;
+
+      if (yysize_overflow)
+	return YYSIZE_MAXIMUM;
+
+      if (yyresult)
+	{
+	  /* Avoid sprintf, as that infringes on the user's name space.
+	     Don't have undefined behavior even if the translation
+	     produced a string with the wrong number of "%s"s.  */
+	  char *yyp = yyresult;
+	  int yyi = 0;
+	  while ((*yyp = *yyf) != '\0')
+	    {
+	      if (*yyp == '%' && yyf[1] == 's' && yyi < yycount)
+		{
+		  yyp += yytnamerr (yyp, yyarg[yyi++]);
+		  yyf += 2;
+		}
+	      else
+		{
+		  yyp++;
+		  yyf++;
+		}
+	    }
+	}
+      return yysize;
+    }
+}
+#endif /* YYERROR_VERBOSE */
+

+
+/*-----------------------------------------------.
+| Release the memory associated to this symbol.  |
+`-----------------------------------------------*/
+
+/*ARGSUSED*/
+#if (defined __STDC__ || defined __C99__FUNC__ \
+     || defined __cplusplus || defined _MSC_VER)
+static void
+yydestruct (const char *yymsg, int yytype, YYSTYPE *yyvaluep, void *scanner, struct parse_context *ctx, struct scan_context *scan_ctx)
+#else
+static void
+yydestruct (yymsg, yytype, yyvaluep, scanner, ctx, scan_ctx)
+    const char *yymsg;
+    int yytype;
+    YYSTYPE *yyvaluep;
+    void *scanner;
+    struct parse_context *ctx;
+    struct scan_context *scan_ctx;
+#endif
+{
+  YYUSE (yyvaluep);
+  YYUSE (scanner);
+  YYUSE (ctx);
+  YYUSE (scan_ctx);
+
+  if (!yymsg)
+    yymsg = "Deleting";
+  YY_SYMBOL_PRINT (yymsg, yytype, yyvaluep, yylocationp);
+
+  switch (yytype)
+    {
+
+      default:
+	break;
+    }
+}
+
+/* Prevent warnings from -Wmissing-prototypes.  */
+#ifdef YYPARSE_PARAM
+#if defined __STDC__ || defined __cplusplus
+int yyparse (void *YYPARSE_PARAM);
+#else
+int yyparse ();
+#endif
+#else /* ! YYPARSE_PARAM */
+#if defined __STDC__ || defined __cplusplus
+int yyparse (void *scanner, struct parse_context *ctx, struct scan_context *scan_ctx);
+#else
+int yyparse ();
+#endif
+#endif /* ! YYPARSE_PARAM */
+
+
+
+
+
+/*-------------------------.
+| yyparse or yypush_parse.  |
+`-------------------------*/
+
+#ifdef YYPARSE_PARAM
+#if (defined __STDC__ || defined __C99__FUNC__ \
+     || defined __cplusplus || defined _MSC_VER)
+int
+yyparse (void *YYPARSE_PARAM)
+#else
+int
+yyparse (YYPARSE_PARAM)
+    void *YYPARSE_PARAM;
+#endif
+#else /* ! YYPARSE_PARAM */
+#if (defined __STDC__ || defined __C99__FUNC__ \
+     || defined __cplusplus || defined _MSC_VER)
+int
+yyparse (void *scanner, struct parse_context *ctx, struct scan_context *scan_ctx)
+#else
+int
+yyparse (scanner, ctx, scan_ctx)
+    void *scanner;
+    struct parse_context *ctx;
+    struct scan_context *scan_ctx;
+#endif
+#endif
+{
+/* The lookahead symbol.  */
+int yychar;
+
+/* The semantic value of the lookahead symbol.  */
+YYSTYPE yylval;
+
+    /* Number of syntax errors so far.  */
+    int yynerrs;
+
+    int yystate;
+    /* Number of tokens to shift before error messages enabled.  */
+    int yyerrstatus;
+
+    /* The stacks and their tools:
+       `yyss': related to states.
+       `yyvs': related to semantic values.
+
+       Refer to the stacks thru separate pointers, to allow yyoverflow
+       to reallocate them elsewhere.  */
+
+    /* The state stack.  */
+    yytype_int16 yyssa[YYINITDEPTH];
+    yytype_int16 *yyss;
+    yytype_int16 *yyssp;
+
+    /* The semantic value stack.  */
+    YYSTYPE yyvsa[YYINITDEPTH];
+    YYSTYPE *yyvs;
+    YYSTYPE *yyvsp;
+
+    YYSIZE_T yystacksize;
+
+  int yyn;
+  int yyresult;
+  /* Lookahead token as an internal (translated) token number.  */
+  int yytoken;
+  /* The variables used to return semantic value and location from the
+     action routines.  */
+  YYSTYPE yyval;
+
+#if YYERROR_VERBOSE
+  /* Buffer for error messages, and its allocated size.  */
+  char yymsgbuf[128];
+  char *yymsg = yymsgbuf;
+  YYSIZE_T yymsg_alloc = sizeof yymsgbuf;
+#endif
+
+#define YYPOPSTACK(N)   (yyvsp -= (N), yyssp -= (N))
+
+  /* The number of symbols on the RHS of the reduced rule.
+     Keep to zero when no symbol should be popped.  */
+  int yylen = 0;
+
+  yytoken = 0;
+  yyss = yyssa;
+  yyvs = yyvsa;
+  yystacksize = YYINITDEPTH;
+
+  YYDPRINTF ((stderr, "Starting parse\n"));
+
+  yystate = 0;
+  yyerrstatus = 0;
+  yynerrs = 0;
+  yychar = YYEMPTY; /* Cause a token to be read.  */
+
+  /* Initialize stack pointers.
+     Waste one element of value and location stack
+     so that they stay on the same level as the state stack.
+     The wasted elements are never initialized.  */
+  yyssp = yyss;
+  yyvsp = yyvs;
+
+  goto yysetstate;
+
+/*------------------------------------------------------------.
+| yynewstate -- Push a new state, which is found in yystate.  |
+`------------------------------------------------------------*/
+ yynewstate:
+  /* In all cases, when you get here, the value and location stacks
+     have just been pushed.  So pushing a state here evens the stacks.  */
+  yyssp++;
+
+ yysetstate:
+  *yyssp = yystate;
+
+  if (yyss + yystacksize - 1 <= yyssp)
+    {
+      /* Get the current used size of the three stacks, in elements.  */
+      YYSIZE_T yysize = yyssp - yyss + 1;
+
+#ifdef yyoverflow
+      {
+	/* Give user a chance to reallocate the stack.  Use copies of
+	   these so that the &'s don't force the real ones into
+	   memory.  */
+	YYSTYPE *yyvs1 = yyvs;
+	yytype_int16 *yyss1 = yyss;
+
+	/* Each stack pointer address is followed by the size of the
+	   data in use in that stack, in bytes.  This used to be a
+	   conditional around just the two extra args, but that might
+	   be undefined if yyoverflow is a macro.  */
+	yyoverflow (YY_("memory exhausted"),
+		    &yyss1, yysize * sizeof (*yyssp),
+		    &yyvs1, yysize * sizeof (*yyvsp),
+		    &yystacksize);
+
+	yyss = yyss1;
+	yyvs = yyvs1;
+      }
+#else /* no yyoverflow */
+# ifndef YYSTACK_RELOCATE
+      goto yyexhaustedlab;
+# else
+      /* Extend the stack our own way.  */
+      if (YYMAXDEPTH <= yystacksize)
+	goto yyexhaustedlab;
+      yystacksize *= 2;
+      if (YYMAXDEPTH < yystacksize)
+	yystacksize = YYMAXDEPTH;
+
+      {
+	yytype_int16 *yyss1 = yyss;
+	union yyalloc *yyptr =
+	  (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize));
+	if (! yyptr)
+	  goto yyexhaustedlab;
+	YYSTACK_RELOCATE (yyss_alloc, yyss);
+	YYSTACK_RELOCATE (yyvs_alloc, yyvs);
+#  undef YYSTACK_RELOCATE
+	if (yyss1 != yyssa)
+	  YYSTACK_FREE (yyss1);
+      }
+# endif
+#endif /* no yyoverflow */
+
+      yyssp = yyss + yysize - 1;
+      yyvsp = yyvs + yysize - 1;
+
+      YYDPRINTF ((stderr, "Stack size increased to %lu\n",
+		  (unsigned long int) yystacksize));
+
+      if (yyss + yystacksize - 1 <= yyssp)
+	YYABORT;
+    }
+
+  YYDPRINTF ((stderr, "Entering state %d\n", yystate));
+
+  if (yystate == YYFINAL)
+    YYACCEPT;
+
+  goto yybackup;
+
+/*-----------.
+| yybackup.  |
+`-----------*/
+yybackup:
+
+  /* Do appropriate processing given the current state.  Read a
+     lookahead token if we need one and don't already have one.  */
+
+  /* First try to decide what to do without reference to lookahead token.  */
+  yyn = yypact[yystate];
+  if (yyn == YYPACT_NINF)
+    goto yydefault;
+
+  /* Not known => get a lookahead token if don't already have one.  */
+
+  /* YYCHAR is either YYEMPTY or YYEOF or a valid lookahead symbol.  */
+  if (yychar == YYEMPTY)
+    {
+      YYDPRINTF ((stderr, "Reading a token: "));
+      yychar = YYLEX;
+    }
+
+  if (yychar <= YYEOF)
+    {
+      yychar = yytoken = YYEOF;
+      YYDPRINTF ((stderr, "Now at end of input.\n"));
+    }
+  else
+    {
+      yytoken = YYTRANSLATE (yychar);
+      YY_SYMBOL_PRINT ("Next token is", yytoken, &yylval, &yylloc);
+    }
+
+  /* If the proper action on seeing token YYTOKEN is to reduce or to
+     detect an error, take that action.  */
+  yyn += yytoken;
+  if (yyn < 0 || YYLAST < yyn || yycheck[yyn] != yytoken)
+    goto yydefault;
+  yyn = yytable[yyn];
+  if (yyn <= 0)
+    {
+      if (yyn == 0 || yyn == YYTABLE_NINF)
+	goto yyerrlab;
+      yyn = -yyn;
+      goto yyreduce;
+    }
+
+  /* Count tokens shifted since error; after three, turn off error
+     status.  */
+  if (yyerrstatus)
+    yyerrstatus--;
+
+  /* Shift the lookahead token.  */
+  YY_SYMBOL_PRINT ("Shifting", yytoken, &yylval, &yylloc);
+
+  /* Discard the shifted token.  */
+  yychar = YYEMPTY;
+
+  yystate = yyn;
+  *++yyvsp = yylval;
+
+  goto yynewstate;
+
+
+/*-----------------------------------------------------------.
+| yydefault -- do the default action for the current state.  |
+`-----------------------------------------------------------*/
+yydefault:
+  yyn = yydefact[yystate];
+  if (yyn == 0)
+    goto yyerrlab;
+  goto yyreduce;
+
+
+/*-----------------------------.
+| yyreduce -- Do a reduction.  |
+`-----------------------------*/
+yyreduce:
+  /* yyn is the number of a rule to reduce with.  */
+  yylen = yyr2[yyn];
+
+  /* If YYLEN is nonzero, implement the default value of the action:
+     `$$ = $1'.
+
+     Otherwise, the following line sets YYVAL to garbage.
+     This behavior is undocumented and Bison
+     users should not rely upon it.  Assigning to YYVAL
+     unconditionally makes the parser a bit smaller, and it avoids a
+     GCC warning that YYVAL may be used uninitialized.  */
+  yyval = yyvsp[1-yylen];
+
+
+  YY_REDUCE_PRINT (yyn);
+  switch (yyn)
+    {
+        case 8:
+
+/* Line 1455 of yacc.c  */
+#line 117 "grammar.y"
+    {
+    ctx->setting = config_setting_add(ctx->parent, (yyvsp[(1) - (1)].sval), CONFIG_TYPE_NONE);
+
+    if(ctx->setting == NULL)
+    {
+      libconfig_yyerror(scanner, ctx, scan_ctx, err_duplicate_setting);
+      YYABORT;
+    }
+    else
+    {
+      CAPTURE_PARSE_POS(ctx->setting);
+    }
+  }
+    break;
+
+  case 10:
+
+/* Line 1455 of yacc.c  */
+#line 136 "grammar.y"
+    {
+    if(IN_LIST())
+    {
+      ctx->parent = config_setting_add(ctx->parent, NULL, CONFIG_TYPE_ARRAY);
+      CAPTURE_PARSE_POS(ctx->parent);
+    }
+    else
+    {
+      ctx->setting->type = CONFIG_TYPE_ARRAY;
+      ctx->parent = ctx->setting;
+      ctx->setting = NULL;
+    }
+  }
+    break;
+
+  case 11:
+
+/* Line 1455 of yacc.c  */
+#line 151 "grammar.y"
+    {
+    if(ctx->parent)
+      ctx->parent = ctx->parent->parent;
+  }
+    break;
+
+  case 12:
+
+/* Line 1455 of yacc.c  */
+#line 159 "grammar.y"
+    {
+    if(IN_LIST())
+    {
+      ctx->parent = config_setting_add(ctx->parent, NULL, CONFIG_TYPE_LIST);
+      CAPTURE_PARSE_POS(ctx->parent);
+    }
+    else
+    {
+      ctx->setting->type = CONFIG_TYPE_LIST;
+      ctx->parent = ctx->setting;
+      ctx->setting = NULL;
+    }
+  }
+    break;
+
+  case 13:
+
+/* Line 1455 of yacc.c  */
+#line 174 "grammar.y"
+    {
+    if(ctx->parent)
+      ctx->parent = ctx->parent->parent;
+  }
+    break;
+
+  case 18:
+
+/* Line 1455 of yacc.c  */
+#line 188 "grammar.y"
+    { parsectx_append_string(ctx, (yyvsp[(1) - (1)].sval)); free((yyvsp[(1) - (1)].sval)); }
+    break;
+
+  case 19:
+
+/* Line 1455 of yacc.c  */
+#line 189 "grammar.y"
+    { parsectx_append_string(ctx, (yyvsp[(2) - (2)].sval)); free((yyvsp[(2) - (2)].sval)); }
+    break;
+
+  case 20:
+
+/* Line 1455 of yacc.c  */
+#line 194 "grammar.y"
+    {
+    if(IN_ARRAY() || IN_LIST())
+    {
+      config_setting_t *e = config_setting_set_bool_elem(ctx->parent, -1,
+                                                         (int)(yyvsp[(1) - (1)].ival));
+
+      if(! e)
+      {
+        libconfig_yyerror(scanner, ctx, scan_ctx, err_array_elem_type);
+        YYABORT;
+      }
+      else
+      {
+        CAPTURE_PARSE_POS(e);
+      }
+    }
+    else
+      config_setting_set_bool(ctx->setting, (int)(yyvsp[(1) - (1)].ival));
+  }
+    break;
+
+  case 21:
+
+/* Line 1455 of yacc.c  */
+#line 214 "grammar.y"
+    {
+    if(IN_ARRAY() || IN_LIST())
+    {
+      config_setting_t *e = config_setting_set_int_elem(ctx->parent, -1, (yyvsp[(1) - (1)].ival));
+      if(! e)
+      {
+        libconfig_yyerror(scanner, ctx, scan_ctx, err_array_elem_type);
+        YYABORT;
+      }
+      else
+      {
+        config_setting_set_format(e, CONFIG_FORMAT_DEFAULT);
+        CAPTURE_PARSE_POS(e);
+      }
+    }
+    else
+    {
+      config_setting_set_int(ctx->setting, (yyvsp[(1) - (1)].ival));
+      config_setting_set_format(ctx->setting, CONFIG_FORMAT_DEFAULT);
+    }
+  }
+    break;
+
+  case 22:
+
+/* Line 1455 of yacc.c  */
+#line 236 "grammar.y"
+    {
+    if(IN_ARRAY() || IN_LIST())
+    {
+      config_setting_t *e = config_setting_set_int64_elem(ctx->parent, -1, (yyvsp[(1) - (1)].llval));
+      if(! e)
+      {
+        libconfig_yyerror(scanner, ctx, scan_ctx, err_array_elem_type);
+        YYABORT;
+      }
+      else
+      {
+        config_setting_set_format(e, CONFIG_FORMAT_DEFAULT);
+        CAPTURE_PARSE_POS(e);
+      }
+    }
+    else
+    {
+      config_setting_set_int64(ctx->setting, (yyvsp[(1) - (1)].llval));
+      config_setting_set_format(ctx->setting, CONFIG_FORMAT_DEFAULT);
+    }
+  }
+    break;
+
+  case 23:
+
+/* Line 1455 of yacc.c  */
+#line 258 "grammar.y"
+    {
+    if(IN_ARRAY() || IN_LIST())
+    {
+      config_setting_t *e = config_setting_set_int_elem(ctx->parent, -1, (yyvsp[(1) - (1)].ival));
+      if(! e)
+      {
+        libconfig_yyerror(scanner, ctx, scan_ctx, err_array_elem_type);
+        YYABORT;
+      }
+      else
+      {
+        config_setting_set_format(e, CONFIG_FORMAT_HEX);
+        CAPTURE_PARSE_POS(e);
+      }
+    }
+    else
+    {
+      config_setting_set_int(ctx->setting, (yyvsp[(1) - (1)].ival));
+      config_setting_set_format(ctx->setting, CONFIG_FORMAT_HEX);
+    }
+  }
+    break;
+
+  case 24:
+
+/* Line 1455 of yacc.c  */
+#line 280 "grammar.y"
+    {
+    if(IN_ARRAY() || IN_LIST())
+    {
+      config_setting_t *e = config_setting_set_int64_elem(ctx->parent, -1, (yyvsp[(1) - (1)].llval));
+      if(! e)
+      {
+        libconfig_yyerror(scanner, ctx, scan_ctx, err_array_elem_type);
+        YYABORT;
+      }
+      else
+      {
+        config_setting_set_format(e, CONFIG_FORMAT_HEX);
+        CAPTURE_PARSE_POS(e);
+      }
+    }
+    else
+    {
+      config_setting_set_int64(ctx->setting, (yyvsp[(1) - (1)].llval));
+      config_setting_set_format(ctx->setting, CONFIG_FORMAT_HEX);
+    }
+  }
+    break;
+
+  case 25:
+
+/* Line 1455 of yacc.c  */
+#line 302 "grammar.y"
+    {
+    if(IN_ARRAY() || IN_LIST())
+    {
+      config_setting_t *e = config_setting_set_float_elem(ctx->parent, -1, (yyvsp[(1) - (1)].fval));
+      if(! e)
+      {
+        libconfig_yyerror(scanner, ctx, scan_ctx, err_array_elem_type);
+        YYABORT;
+      }
+      else
+      {
+        CAPTURE_PARSE_POS(e);
+      }
+    }
+    else
+      config_setting_set_float(ctx->setting, (yyvsp[(1) - (1)].fval));
+  }
+    break;
+
+  case 26:
+
+/* Line 1455 of yacc.c  */
+#line 320 "grammar.y"
+    {
+    if(IN_ARRAY() || IN_LIST())
+    {
+      const char *s = parsectx_take_string(ctx);
+      config_setting_t *e = config_setting_set_string_elem(ctx->parent, -1, s);
+      _delete(s);
+
+      if(! e)
+      {
+        libconfig_yyerror(scanner, ctx, scan_ctx, err_array_elem_type);
+        YYABORT;
+      }
+      else
+      {
+        CAPTURE_PARSE_POS(e);
+      }
+    }
+    else
+    {
+      const char *s = parsectx_take_string(ctx);
+      config_setting_set_string(ctx->setting, s);
+      _delete(s);
+    }
+  }
+    break;
+
+  case 35:
+
+/* Line 1455 of yacc.c  */
+#line 368 "grammar.y"
+    {
+    if(IN_LIST())
+    {
+      ctx->parent = config_setting_add(ctx->parent, NULL, CONFIG_TYPE_GROUP);
+      CAPTURE_PARSE_POS(ctx->parent);
+    }
+    else
+    {
+      ctx->setting->type = CONFIG_TYPE_GROUP;
+      ctx->parent = ctx->setting;
+      ctx->setting = NULL;
+    }
+  }
+    break;
+
+  case 36:
+
+/* Line 1455 of yacc.c  */
+#line 383 "grammar.y"
+    {
+    if(ctx->parent)
+      ctx->parent = ctx->parent->parent;
+  }
+    break;
+
+
+
+/* Line 1455 of yacc.c  */
+#line 1788 "grammar.c"
+      default: break;
+    }
+  YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc);
+
+  YYPOPSTACK (yylen);
+  yylen = 0;
+  YY_STACK_PRINT (yyss, yyssp);
+
+  *++yyvsp = yyval;
+
+  /* Now `shift' the result of the reduction.  Determine what state
+     that goes to, based on the state we popped back to and the rule
+     number reduced by.  */
+
+  yyn = yyr1[yyn];
+
+  yystate = yypgoto[yyn - YYNTOKENS] + *yyssp;
+  if (0 <= yystate && yystate <= YYLAST && yycheck[yystate] == *yyssp)
+    yystate = yytable[yystate];
+  else
+    yystate = yydefgoto[yyn - YYNTOKENS];
+
+  goto yynewstate;
+
+
+/*------------------------------------.
+| yyerrlab -- here on detecting error |
+`------------------------------------*/
+yyerrlab:
+  /* If not already recovering from an error, report this error.  */
+  if (!yyerrstatus)
+    {
+      ++yynerrs;
+#if ! YYERROR_VERBOSE
+      yyerror (scanner, ctx, scan_ctx, YY_("syntax error"));
+#else
+      {
+	YYSIZE_T yysize = yysyntax_error (0, yystate, yychar);
+	if (yymsg_alloc < yysize && yymsg_alloc < YYSTACK_ALLOC_MAXIMUM)
+	  {
+	    YYSIZE_T yyalloc = 2 * yysize;
+	    if (! (yysize <= yyalloc && yyalloc <= YYSTACK_ALLOC_MAXIMUM))
+	      yyalloc = YYSTACK_ALLOC_MAXIMUM;
+	    if (yymsg != yymsgbuf)
+	      YYSTACK_FREE (yymsg);
+	    yymsg = (char *) YYSTACK_ALLOC (yyalloc);
+	    if (yymsg)
+	      yymsg_alloc = yyalloc;
+	    else
+	      {
+		yymsg = yymsgbuf;
+		yymsg_alloc = sizeof yymsgbuf;
+	      }
+	  }
+
+	if (0 < yysize && yysize <= yymsg_alloc)
+	  {
+	    (void) yysyntax_error (yymsg, yystate, yychar);
+	    yyerror (scanner, ctx, scan_ctx, yymsg);
+	  }
+	else
+	  {
+	    yyerror (scanner, ctx, scan_ctx, YY_("syntax error"));
+	    if (yysize != 0)
+	      goto yyexhaustedlab;
+	  }
+      }
+#endif
+    }
+
+
+
+  if (yyerrstatus == 3)
+    {
+      /* If just tried and failed to reuse lookahead token after an
+	 error, discard it.  */
+
+      if (yychar <= YYEOF)
+	{
+	  /* Return failure if at end of input.  */
+	  if (yychar == YYEOF)
+	    YYABORT;
+	}
+      else
+	{
+	  yydestruct ("Error: discarding",
+		      yytoken, &yylval, scanner, ctx, scan_ctx);
+	  yychar = YYEMPTY;
+	}
+    }
+
+  /* Else will try to reuse lookahead token after shifting the error
+     token.  */
+  goto yyerrlab1;
+
+
+/*---------------------------------------------------.
+| yyerrorlab -- error raised explicitly by YYERROR.  |
+`---------------------------------------------------*/
+yyerrorlab:
+
+  /* Pacify compilers like GCC when the user code never invokes
+     YYERROR and the label yyerrorlab therefore never appears in user
+     code.  */
+  if (/*CONSTCOND*/ 0)
+     goto yyerrorlab;
+
+  /* Do not reclaim the symbols of the rule which action triggered
+     this YYERROR.  */
+  YYPOPSTACK (yylen);
+  yylen = 0;
+  YY_STACK_PRINT (yyss, yyssp);
+  yystate = *yyssp;
+  goto yyerrlab1;
+
+
+/*-------------------------------------------------------------.
+| yyerrlab1 -- common code for both syntax error and YYERROR.  |
+`-------------------------------------------------------------*/
+yyerrlab1:
+  yyerrstatus = 3;	/* Each real token shifted decrements this.  */
+
+  for (;;)
+    {
+      yyn = yypact[yystate];
+      if (yyn != YYPACT_NINF)
+	{
+	  yyn += YYTERROR;
+	  if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR)
+	    {
+	      yyn = yytable[yyn];
+	      if (0 < yyn)
+		break;
+	    }
+	}
+
+      /* Pop the current state because it cannot handle the error token.  */
+      if (yyssp == yyss)
+	YYABORT;
+
+
+      yydestruct ("Error: popping",
+		  yystos[yystate], yyvsp, scanner, ctx, scan_ctx);
+      YYPOPSTACK (1);
+      yystate = *yyssp;
+      YY_STACK_PRINT (yyss, yyssp);
+    }
+
+  *++yyvsp = yylval;
+
+
+  /* Shift the error token.  */
+  YY_SYMBOL_PRINT ("Shifting", yystos[yyn], yyvsp, yylsp);
+
+  yystate = yyn;
+  goto yynewstate;
+
+
+/*-------------------------------------.
+| yyacceptlab -- YYACCEPT comes here.  |
+`-------------------------------------*/
+yyacceptlab:
+  yyresult = 0;
+  goto yyreturn;
+
+/*-----------------------------------.
+| yyabortlab -- YYABORT comes here.  |
+`-----------------------------------*/
+yyabortlab:
+  yyresult = 1;
+  goto yyreturn;
+
+#if !defined(yyoverflow) || YYERROR_VERBOSE
+/*-------------------------------------------------.
+| yyexhaustedlab -- memory exhaustion comes here.  |
+`-------------------------------------------------*/
+yyexhaustedlab:
+  yyerror (scanner, ctx, scan_ctx, YY_("memory exhausted"));
+  yyresult = 2;
+  /* Fall through.  */
+#endif
+
+yyreturn:
+  if (yychar != YYEMPTY)
+     yydestruct ("Cleanup: discarding lookahead",
+		 yytoken, &yylval, scanner, ctx, scan_ctx);
+  /* Do not reclaim the symbols of the rule which action triggered
+     this YYABORT or YYACCEPT.  */
+  YYPOPSTACK (yylen);
+  YY_STACK_PRINT (yyss, yyssp);
+  while (yyssp != yyss)
+    {
+      yydestruct ("Cleanup: popping",
+		  yystos[*yyssp], yyvsp, scanner, ctx, scan_ctx);
+      YYPOPSTACK (1);
+    }
+#ifndef yyoverflow
+  if (yyss != yyssa)
+    YYSTACK_FREE (yyss);
+#endif
+#if YYERROR_VERBOSE
+  if (yymsg != yymsgbuf)
+    YYSTACK_FREE (yymsg);
+#endif
+  /* Make sure YYID is used.  */
+  return YYID (yyresult);
+}
+
+
+
+/* Line 1675 of yacc.c  */
+#line 389 "grammar.y"
+
+
diff --git a/3rdparty/libconfig/grammar.h b/3rdparty/libconfig/grammar.h
new file mode 100644
index 0000000..5310118
--- /dev/null
+++ b/3rdparty/libconfig/grammar.h
@@ -0,0 +1,113 @@
+
+/* A Bison parser, made by GNU Bison 2.4.1.  */
+
+/* Skeleton interface for Bison's Yacc-like parsers in C
+   
+      Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006
+   Free Software Foundation, Inc.
+   
+   This program is free software: you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation, either version 3 of the License, or
+   (at your option) any later version.
+   
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+   
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+/* As a special exception, you may create a larger work that contains
+   part or all of the Bison parser skeleton and distribute that work
+   under terms of your choice, so long as that work isn't itself a
+   parser generator using the skeleton or a modified version thereof
+   as a parser skeleton.  Alternatively, if you modify or redistribute
+   the parser skeleton itself, you may (at your option) remove this
+   special exception, which will cause the skeleton and the resulting
+   Bison output files to be licensed under the GNU General Public
+   License without this special exception.
+   
+   This special exception was added by the Free Software Foundation in
+   version 2.2 of Bison.  */
+
+
+/* Tokens.  */
+#ifndef YYTOKENTYPE
+# define YYTOKENTYPE
+   /* Put the tokens into the symbol table, so that GDB and other debuggers
+      know about them.  */
+   enum yytokentype {
+     TOK_BOOLEAN = 258,
+     TOK_INTEGER = 259,
+     TOK_HEX = 260,
+     TOK_INTEGER64 = 261,
+     TOK_HEX64 = 262,
+     TOK_FLOAT = 263,
+     TOK_STRING = 264,
+     TOK_NAME = 265,
+     TOK_EQUALS = 266,
+     TOK_NEWLINE = 267,
+     TOK_ARRAY_START = 268,
+     TOK_ARRAY_END = 269,
+     TOK_LIST_START = 270,
+     TOK_LIST_END = 271,
+     TOK_COMMA = 272,
+     TOK_GROUP_START = 273,
+     TOK_GROUP_END = 274,
+     TOK_END = 275,
+     TOK_GARBAGE = 276,
+     TOK_ERROR = 277
+   };
+#endif
+/* Tokens.  */
+#define TOK_BOOLEAN 258
+#define TOK_INTEGER 259
+#define TOK_HEX 260
+#define TOK_INTEGER64 261
+#define TOK_HEX64 262
+#define TOK_FLOAT 263
+#define TOK_STRING 264
+#define TOK_NAME 265
+#define TOK_EQUALS 266
+#define TOK_NEWLINE 267
+#define TOK_ARRAY_START 268
+#define TOK_ARRAY_END 269
+#define TOK_LIST_START 270
+#define TOK_LIST_END 271
+#define TOK_COMMA 272
+#define TOK_GROUP_START 273
+#define TOK_GROUP_END 274
+#define TOK_END 275
+#define TOK_GARBAGE 276
+#define TOK_ERROR 277
+
+
+
+
+#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
+typedef union YYSTYPE
+{
+
+/* Line 1676 of yacc.c  */
+#line 85 "grammar.y"
+
+  int ival;
+  long long llval;
+  double fval;
+  char *sval;
+
+
+
+/* Line 1676 of yacc.c  */
+#line 105 "grammar.h"
+} YYSTYPE;
+# define YYSTYPE_IS_TRIVIAL 1
+# define yystype YYSTYPE /* obsolescent; will be withdrawn */
+# define YYSTYPE_IS_DECLARED 1
+#endif
+
+
+
+
diff --git a/3rdparty/libconfig/grammar.y b/3rdparty/libconfig/grammar.y
new file mode 100644
index 0000000..bc78a9a
--- /dev/null
+++ b/3rdparty/libconfig/grammar.y
@@ -0,0 +1,389 @@
+/* -*- mode: C -*- */
+/* ----------------------------------------------------------------------------
+   libconfig - A library for processing structured configuration files
+   Copyright (C) 2005-2010  Mark A Lindner
+
+   This file is part of libconfig.
+
+   This library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public License
+   as published by the Free Software Foundation; either version 2.1 of
+   the License, or (at your option) any later version.
+
+   This library is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with this library; if not, see
+   <http://www.gnu.org/licenses/>.
+   ----------------------------------------------------------------------------
+*/
+
+%defines
+%output="y.tab.c"
+%pure-parser
+%lex-param{void *scanner}
+%parse-param{void *scanner}
+%parse-param{struct parse_context *ctx}
+%parse-param{struct scan_context *scan_ctx}
+
+%{
+#include <string.h>
+#include <stdlib.h>
+#include "libconfig.h"
+#ifdef WIN32
+#include "wincompat.h"
+
+/* prevent warnings about redefined malloc/free in generated code: */
+#ifndef _STDLIB_H
+#define _STDLIB_H
+#endif
+
+#include <malloc.h>
+#endif
+#include "parsectx.h"
+#include "scanctx.h"
+
+/* these delcarations are provided to suppress compiler warnings */
+extern int libconfig_yylex();
+extern int libconfig_yyget_lineno();
+
+static const char *err_array_elem_type = "mismatched element type in array";
+static const char *err_duplicate_setting = "duplicate setting name";
+
+#define _delete(P) free((void *)(P))
+
+#define IN_ARRAY() \
+  (ctx->parent && (ctx->parent->type == CONFIG_TYPE_ARRAY))
+
+#define IN_LIST() \
+  (ctx->parent && (ctx->parent->type == CONFIG_TYPE_LIST))
+
+static void capture_parse_pos(void *scanner, struct scan_context *scan_ctx,
+                              config_setting_t *setting)
+{
+  setting->line = (unsigned int)libconfig_yyget_lineno(scanner);
+  setting->file = scanctx_current_filename(scan_ctx);
+}
+
+#define CAPTURE_PARSE_POS(S) \
+  capture_parse_pos(scanner, scan_ctx, (S))
+
+void libconfig_yyerror(void *scanner, struct parse_context *ctx,
+                       struct scan_context *scan_ctx, char const *s)
+{
+  if(ctx->config->error_text) return;
+  ctx->config->error_line = libconfig_yyget_lineno(scanner);
+  ctx->config->error_text = s;
+}
+
+%}
+
+%union
+{
+  int ival;
+  long long llval;
+  double fval;
+  char *sval;
+}
+
+%token <ival> TOK_BOOLEAN TOK_INTEGER TOK_HEX
+%token <llval> TOK_INTEGER64 TOK_HEX64
+%token <fval> TOK_FLOAT
+%token <sval> TOK_STRING TOK_NAME
+%token TOK_EQUALS TOK_NEWLINE TOK_ARRAY_START TOK_ARRAY_END TOK_LIST_START TOK_LIST_END TOK_COMMA TOK_GROUP_START TOK_GROUP_END TOK_END TOK_GARBAGE TOK_ERROR
+
+%%
+
+configuration:
+    /* empty */
+  | setting_list
+  ;
+
+setting_list:
+    setting
+  | setting_list setting
+  ;
+
+setting_list_optional:
+    /* empty */
+  | setting_list
+  ;
+
+setting:
+  TOK_NAME
+  {
+    ctx->setting = config_setting_add(ctx->parent, $1, CONFIG_TYPE_NONE);
+
+    if(ctx->setting == NULL)
+    {
+      libconfig_yyerror(scanner, ctx, scan_ctx, err_duplicate_setting);
+      YYABORT;
+    }
+    else
+    {
+      CAPTURE_PARSE_POS(ctx->setting);
+    }
+  }
+
+  TOK_EQUALS value TOK_END
+  ;
+
+array:
+  TOK_ARRAY_START
+  {
+    if(IN_LIST())
+    {
+      ctx->parent = config_setting_add(ctx->parent, NULL, CONFIG_TYPE_ARRAY);
+      CAPTURE_PARSE_POS(ctx->parent);
+    }
+    else
+    {
+      ctx->setting->type = CONFIG_TYPE_ARRAY;
+      ctx->parent = ctx->setting;
+      ctx->setting = NULL;
+    }
+  }
+  simple_value_list_optional
+  TOK_ARRAY_END
+  {
+    if(ctx->parent)
+      ctx->parent = ctx->parent->parent;
+  }
+  ;
+
+list:
+  TOK_LIST_START
+  {
+    if(IN_LIST())
+    {
+      ctx->parent = config_setting_add(ctx->parent, NULL, CONFIG_TYPE_LIST);
+      CAPTURE_PARSE_POS(ctx->parent);
+    }
+    else
+    {
+      ctx->setting->type = CONFIG_TYPE_LIST;
+      ctx->parent = ctx->setting;
+      ctx->setting = NULL;
+    }
+  }
+  value_list_optional
+  TOK_LIST_END
+  {
+    if(ctx->parent)
+      ctx->parent = ctx->parent->parent;
+  }
+  ;
+
+value:
+    simple_value
+  | array
+  | list
+  | group
+  ;
+
+string:
+  TOK_STRING { parsectx_append_string(ctx, $1); free($1); }
+  | string TOK_STRING { parsectx_append_string(ctx, $2); free($2); }
+  ;
+
+simple_value:
+    TOK_BOOLEAN
+  {
+    if(IN_ARRAY() || IN_LIST())
+    {
+      config_setting_t *e = config_setting_set_bool_elem(ctx->parent, -1,
+                                                         (int)$1);
+
+      if(! e)
+      {
+        libconfig_yyerror(scanner, ctx, scan_ctx, err_array_elem_type);
+        YYABORT;
+      }
+      else
+      {
+        CAPTURE_PARSE_POS(e);
+      }
+    }
+    else
+      config_setting_set_bool(ctx->setting, (int)$1);
+  }
+  | TOK_INTEGER
+  {
+    if(IN_ARRAY() || IN_LIST())
+    {
+      config_setting_t *e = config_setting_set_int_elem(ctx->parent, -1, $1);
+      if(! e)
+      {
+        libconfig_yyerror(scanner, ctx, scan_ctx, err_array_elem_type);
+        YYABORT;
+      }
+      else
+      {
+        config_setting_set_format(e, CONFIG_FORMAT_DEFAULT);
+        CAPTURE_PARSE_POS(e);
+      }
+    }
+    else
+    {
+      config_setting_set_int(ctx->setting, $1);
+      config_setting_set_format(ctx->setting, CONFIG_FORMAT_DEFAULT);
+    }
+  }
+  | TOK_INTEGER64
+  {
+    if(IN_ARRAY() || IN_LIST())
+    {
+      config_setting_t *e = config_setting_set_int64_elem(ctx->parent, -1, $1);
+      if(! e)
+      {
+        libconfig_yyerror(scanner, ctx, scan_ctx, err_array_elem_type);
+        YYABORT;
+      }
+      else
+      {
+        config_setting_set_format(e, CONFIG_FORMAT_DEFAULT);
+        CAPTURE_PARSE_POS(e);
+      }
+    }
+    else
+    {
+      config_setting_set_int64(ctx->setting, $1);
+      config_setting_set_format(ctx->setting, CONFIG_FORMAT_DEFAULT);
+    }
+  }
+  | TOK_HEX
+  {
+    if(IN_ARRAY() || IN_LIST())
+    {
+      config_setting_t *e = config_setting_set_int_elem(ctx->parent, -1, $1);
+      if(! e)
+      {
+        libconfig_yyerror(scanner, ctx, scan_ctx, err_array_elem_type);
+        YYABORT;
+      }
+      else
+      {
+        config_setting_set_format(e, CONFIG_FORMAT_HEX);
+        CAPTURE_PARSE_POS(e);
+      }
+    }
+    else
+    {
+      config_setting_set_int(ctx->setting, $1);
+      config_setting_set_format(ctx->setting, CONFIG_FORMAT_HEX);
+    }
+  }
+  | TOK_HEX64
+  {
+    if(IN_ARRAY() || IN_LIST())
+    {
+      config_setting_t *e = config_setting_set_int64_elem(ctx->parent, -1, $1);
+      if(! e)
+      {
+        libconfig_yyerror(scanner, ctx, scan_ctx, err_array_elem_type);
+        YYABORT;
+      }
+      else
+      {
+        config_setting_set_format(e, CONFIG_FORMAT_HEX);
+        CAPTURE_PARSE_POS(e);
+      }
+    }
+    else
+    {
+      config_setting_set_int64(ctx->setting, $1);
+      config_setting_set_format(ctx->setting, CONFIG_FORMAT_HEX);
+    }
+  }
+  | TOK_FLOAT
+  {
+    if(IN_ARRAY() || IN_LIST())
+    {
+      config_setting_t *e = config_setting_set_float_elem(ctx->parent, -1, $1);
+      if(! e)
+      {
+        libconfig_yyerror(scanner, ctx, scan_ctx, err_array_elem_type);
+        YYABORT;
+      }
+      else
+      {
+        CAPTURE_PARSE_POS(e);
+      }
+    }
+    else
+      config_setting_set_float(ctx->setting, $1);
+  }
+  | string
+  {
+    if(IN_ARRAY() || IN_LIST())
+    {
+      const char *s = parsectx_take_string(ctx);
+      config_setting_t *e = config_setting_set_string_elem(ctx->parent, -1, s);
+      _delete(s);
+
+      if(! e)
+      {
+        libconfig_yyerror(scanner, ctx, scan_ctx, err_array_elem_type);
+        YYABORT;
+      }
+      else
+      {
+        CAPTURE_PARSE_POS(e);
+      }
+    }
+    else
+    {
+      const char *s = parsectx_take_string(ctx);
+      config_setting_set_string(ctx->setting, s);
+      _delete(s);
+    }
+  }
+  ;
+
+value_list:
+    value
+  | value_list TOK_COMMA value
+  ;
+
+value_list_optional:
+    /* empty */
+  | value_list
+  ;
+
+simple_value_list:
+    simple_value
+  | simple_value_list TOK_COMMA simple_value
+  ;
+
+simple_value_list_optional:
+    /* empty */
+  | simple_value_list
+  ;
+
+group:
+  TOK_GROUP_START
+  {
+    if(IN_LIST())
+    {
+      ctx->parent = config_setting_add(ctx->parent, NULL, CONFIG_TYPE_GROUP);
+      CAPTURE_PARSE_POS(ctx->parent);
+    }
+    else
+    {
+      ctx->setting->type = CONFIG_TYPE_GROUP;
+      ctx->parent = ctx->setting;
+      ctx->setting = NULL;
+    }
+  }
+  setting_list_optional
+  TOK_GROUP_END
+  {
+    if(ctx->parent)
+      ctx->parent = ctx->parent->parent;
+  }
+  ;
+
+%%
diff --git a/3rdparty/libconfig/libconfig.c b/3rdparty/libconfig/libconfig.c
new file mode 100644
index 0000000..77031fd
--- /dev/null
+++ b/3rdparty/libconfig/libconfig.c
@@ -0,0 +1,1595 @@
+/* ----------------------------------------------------------------------------
+   libconfig - A library for processing structured configuration files
+   Copyright (C) 2005-2010  Mark A Lindner
+
+   This file is part of libconfig.
+
+   This library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public License
+   as published by the Free Software Foundation; either version 2.1 of
+   the License, or (at your option) any later version.
+
+   This library is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with this library; if not, see
+   <http://www.gnu.org/licenses/>.
+   ----------------------------------------------------------------------------
+*/
+
+#ifdef HAVE_CONFIG_H
+#include "ac_config.h"
+#endif
+
+#include "libconfig.h"
+#include "grammar.h"
+#include "scanner.h"
+#include "scanctx.h"
+#include "parsectx.h"
+#include "wincompat.h"
+
+#include <locale.h>
+
+#ifdef HAVE_XLOCALE_H
+#include <xlocale.h>
+#endif
+
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+
+#define PATH_TOKENS ":./"
+#define CHUNK_SIZE 16
+#define FLOAT_PRECISION 10
+
+#define _new(T) (T *)calloc(sizeof(T), 1) /* zeroed */
+#define _delete(P) free((void *)(P))
+
+/* ------------------------------------------------------------------------- */
+
+#ifndef LIBCONFIG_STATIC
+#if (defined(WIN32) || defined(_WIN32) || defined(__WIN32__))
+
+BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
+{
+  return(TRUE);
+}
+
+#endif /* WIN32 */
+#endif /* LIBCONFIG_STATIC */
+
+/* ------------------------------------------------------------------------- */
+
+static const char *__io_error = "file I/O error";
+
+static void __config_list_destroy(config_list_t *list);
+static void __config_write_setting(const config_setting_t *setting,
+                                   FILE *stream, int depth,
+                                   unsigned short tab_width);
+
+extern int libconfig_yyparse(void *scanner, struct parse_context *ctx,
+                             struct scan_context *scan_ctx);
+extern int libconfig_yylex_init_extra(struct scan_context *scan_ctx,
+                                      yyscan_t *scanner);
+
+/* ------------------------------------------------------------------------- */
+
+static void __config_locale_override(void)
+{
+#if (defined(WIN32) || defined(_WIN32) || defined(__WIN32__)) \
+  && ! defined(__MINGW32__)
+
+  _configthreadlocale(_ENABLE_PER_THREAD_LOCALE);
+  setlocale(LC_NUMERIC, "C");
+
+#elif defined(__APPLE__)
+
+  locale_t loc = newlocale(LC_NUMERIC_MASK, "C", NULL);
+  uselocale(loc);
+
+#elif ((defined HAVE_NEWLOCALE) && (defined HAVE_USELOCALE))
+
+  locale_t loc = newlocale(LC_NUMERIC, "C", NULL);
+  uselocale(loc);
+
+#else
+
+#warning "No way to modify calling thread's locale!"
+
+#endif
+}
+
+/* ------------------------------------------------------------------------- */
+
+static void __config_locale_restore(void)
+{
+#if (defined(WIN32) || defined(_WIN32) || defined(__WIN32__)) \
+  && ! defined(__MINGW32__)
+
+    _configthreadlocale(_DISABLE_PER_THREAD_LOCALE);
+
+#elif ((defined HAVE_USELOCALE) && (defined HAVE_FREELOCALE))
+
+  locale_t loc = uselocale(LC_GLOBAL_LOCALE);
+  freelocale(loc);
+
+#else
+
+#warning "No way to modify calling thread's locale!"
+
+#endif
+}
+
+/* ------------------------------------------------------------------------- */
+
+static int __config_name_compare(const char *a, const char *b)
+{
+  const char *p, *q;
+
+  for(p = a, q = b; ; p++, q++)
+  {
+    int pd = ((! *p) || strchr(PATH_TOKENS, *p));
+    int qd = ((! *q) || strchr(PATH_TOKENS, *q));
+
+    if(pd && qd)
+      break;
+    else if(pd)
+      return(-1);
+    else if(qd)
+      return(1);
+    else if(*p < *q)
+      return(-1);
+    else if(*p > *q)
+      return(1);
+  }
+
+  return(0);
+}
+
+/* ------------------------------------------------------------------------- */
+
+static void __config_indent(FILE *stream, int depth, unsigned short w)
+{
+  if(w)
+    fprintf(stream, "%*s", (depth - 1) * w, " ");
+  else
+  {
+    int i;
+    for(i = 0; i < (depth - 1); ++i)
+      fputc('\t', stream);
+  }
+}
+
+/* ------------------------------------------------------------------------- */
+
+static void __config_write_value(const config_value_t *value, int type,
+                                 int format, int depth,
+                                 unsigned short tab_width, FILE *stream)
+{
+  char fbuf[64];
+
+  switch(type)
+  {
+    /* boolean */
+    case CONFIG_TYPE_BOOL:
+      fputs(value->ival ? "true" : "false", stream);
+      break;
+
+    /* int */
+    case CONFIG_TYPE_INT:
+      switch(format)
+      {
+        case CONFIG_FORMAT_HEX:
+          fprintf(stream, "0x%X", value->ival);
+          break;
+
+        case CONFIG_FORMAT_DEFAULT:
+        default:
+          fprintf(stream, "%d", value->ival);
+          break;
+      }
+      break;
+
+    /* 64-bit int */
+    case CONFIG_TYPE_INT64:
+      switch(format)
+      {
+        case CONFIG_FORMAT_HEX:
+          fprintf(stream, "0x" INT64_HEX_FMT "L", value->llval);
+          break;
+
+        case CONFIG_FORMAT_DEFAULT:
+        default:
+          fprintf(stream, INT64_FMT "L", value->llval);
+          break;
+      }
+      break;
+
+    /* float */
+    case CONFIG_TYPE_FLOAT:
+    {
+      char *q;
+
+      snprintf(fbuf, sizeof(fbuf) - 3, "%.*g", FLOAT_PRECISION, value->fval);
+
+      /* check for exponent */
+      q = strchr(fbuf, 'e');
+      if(! q)
+      {
+        /* no exponent */
+        if(! strchr(fbuf, '.')) /* no decimal point */
+          strcat(fbuf, ".0");
+        else
+        {
+          /* has decimal point */
+          char *p;
+
+          for(p = fbuf + strlen(fbuf) - 1; p > fbuf; --p)
+          {
+            if(*p != '0')
+            {
+              *(++p) = '\0';
+              break;
+            }
+          }
+        }
+      }
+
+      fputs(fbuf, stream);
+      break;
+    }
+
+    /* string */
+    case CONFIG_TYPE_STRING:
+    {
+      char *p;
+
+      fputc('\"', stream);
+
+      if(value->sval)
+      {
+        for(p = value->sval; *p; p++)
+        {
+          int c = (int)*p & 0xFF;
+          switch(c)
+          {
+            case '\"':
+            case '\\':
+              fputc('\\', stream);
+              fputc(c, stream);
+              break;
+
+            case '\n':
+              fputs("\\n", stream);
+              break;
+
+            case '\r':
+              fputs("\\r", stream);
+              break;
+
+            case '\f':
+              fputs("\\f", stream);
+              break;
+
+            case '\t':
+              fputs("\\t", stream);
+              break;
+
+            default:
+              if(c >= ' ')
+                fputc(c, stream);
+              else
+                fprintf(stream, "\\x%02X", c);
+          }
+        }
+      }
+      fputc('\"', stream);
+      break;
+    }
+
+    /* list */
+    case CONFIG_TYPE_LIST:
+    {
+      config_list_t *list = value->list;
+
+      fprintf(stream, "( ");
+
+      if(list)
+      {
+        int len = list->length;
+        config_setting_t **s;
+
+        for(s = list->elements; len--; s++)
+        {
+          __config_write_value(&((*s)->value), (*s)->type,
+                               config_setting_get_format(*s),
+                               depth + 1, tab_width, stream);
+
+          if(len)
+            fputc(',', stream);
+
+          fputc(' ', stream);
+        }
+      }
+
+      fputc(')', stream);
+      break;
+    }
+
+    /* array */
+    case CONFIG_TYPE_ARRAY:
+    {
+      config_list_t *list = value->list;
+
+      fprintf(stream, "[ ");
+
+      if(list)
+      {
+        int len = list->length;
+        config_setting_t **s;
+
+        for(s = list->elements; len--; s++)
+        {
+          __config_write_value(&((*s)->value), (*s)->type,
+                               config_setting_get_format(*s),
+                               depth + 1, tab_width, stream);
+
+          if(len)
+            fputc(',', stream);
+
+          fputc(' ', stream);
+        }
+      }
+
+      fputc(']', stream);
+      break;
+    }
+
+    /* group */
+    case CONFIG_TYPE_GROUP:
+    {
+      config_list_t *list = value->list;
+
+      if(depth > 0)
+      {
+#ifdef K_AND_R_STYLE /* Horrendous, but many people like it. */
+        fputc(' ', stream);
+#else
+        fputc('\n', stream);
+
+        if(depth > 1)
+          __config_indent(stream, depth, tab_width);
+#endif
+        fprintf(stream, "{\n");
+      }
+
+      if(list)
+      {
+        int len = list->length;
+        config_setting_t **s;
+
+        for(s = list->elements; len--; s++)
+          __config_write_setting(*s, stream, depth + 1, tab_width);
+      }
+
+      if(depth > 1)
+        __config_indent(stream, depth, tab_width);
+
+      if(depth > 0)
+        fputc('}', stream);
+
+      break;
+    }
+
+    default:
+      /* this shouldn't happen, but handle it gracefully... */
+      fputs("???", stream);
+      break;
+  }
+}
+
+/* ------------------------------------------------------------------------- */
+
+static void __config_list_add(config_list_t *list, config_setting_t *setting)
+{
+  if((list->length % CHUNK_SIZE) == 0)
+  {
+    list->elements = (config_setting_t **)realloc(
+      list->elements,
+      (list->length + CHUNK_SIZE) * sizeof(config_setting_t *));
+  }
+
+  list->elements[list->length] = setting;
+  list->length++;
+}
+
+/* ------------------------------------------------------------------------- */
+
+static config_setting_t *__config_list_search(config_list_t *list,
+                                              const char *name,
+                                              unsigned int *idx)
+{
+  config_setting_t **found = NULL;
+  unsigned int i;
+
+  if(! list)
+    return(NULL);
+
+  for(i = 0, found = list->elements; i < list->length; i++, found++)
+  {
+    if(! (*found)->name)
+      continue;
+
+    if(! __config_name_compare(name, (*found)->name))
+    {
+      if(idx)
+        *idx = i;
+
+      return(*found);
+    }
+  }
+
+  return(NULL);
+}
+
+/* ------------------------------------------------------------------------- */
+
+static config_setting_t *__config_list_remove(config_list_t *list, int idx)
+{
+  config_setting_t *removed = *(list->elements + idx);
+  int offset = (idx * sizeof(config_setting_t *));
+  int len = list->length - 1 - idx;
+  char *base = (char *)list->elements + offset;
+
+  memmove(base, base + sizeof(config_setting_t *),
+          len * sizeof(config_setting_t *));
+
+  list->length--;
+
+  /* possibly realloc smaller? */
+
+  return(removed);
+}
+
+/* ------------------------------------------------------------------------- */
+
+static void __config_setting_destroy(config_setting_t *setting)
+{
+  if(setting)
+  {
+    if(setting->name)
+      _delete(setting->name);
+
+    if(setting->type == CONFIG_TYPE_STRING)
+      _delete(setting->value.sval);
+
+    else if((setting->type == CONFIG_TYPE_GROUP)
+            || (setting->type == CONFIG_TYPE_ARRAY)
+            || (setting->type == CONFIG_TYPE_LIST))
+    {
+      if(setting->value.list)
+        __config_list_destroy(setting->value.list);
+    }
+
+    if(setting->hook && setting->config->destructor)
+      setting->config->destructor(setting->hook);
+
+    _delete(setting);
+  }
+}
+
+/* ------------------------------------------------------------------------- */
+
+static void __config_list_destroy(config_list_t *list)
+{
+  config_setting_t **p;
+  unsigned int i;
+
+  if(! list)
+    return;
+
+  if(list->elements)
+  {
+    for(p = list->elements, i = 0; i < list->length; p++, i++)
+      __config_setting_destroy(*p);
+
+    _delete(list->elements);
+  }
+
+  _delete(list);
+}
+
+/* ------------------------------------------------------------------------- */
+
+static int __config_vector_checktype(const config_setting_t *vector, int type)
+{
+  /* if the array is empty, then it has no type yet */
+
+  if(! vector->value.list)
+    return(CONFIG_TRUE);
+
+  if(vector->value.list->length == 0)
+    return(CONFIG_TRUE);
+
+  /* if it's a list, any type is allowed */
+
+  if(vector->type == CONFIG_TYPE_LIST)
+    return(CONFIG_TRUE);
+
+  /* otherwise the first element added determines the type of the array */
+
+  return((vector->value.list->elements[0]->type == type)
+         ? CONFIG_TRUE : CONFIG_FALSE);
+}
+
+/* ------------------------------------------------------------------------- */
+
+static int __config_validate_name(const char *name)
+{
+  const char *p = name;
+
+  if(*p == '\0')
+    return(CONFIG_FALSE);
+
+  if(! isalpha(*p) && (*p != '*'))
+    return(CONFIG_FALSE);
+
+  for(++p; *p; ++p)
+  {
+    if(! (isalpha(*p) || isdigit(*p) || strchr("*_-", (int)*p)))
+      return(CONFIG_FALSE);
+  }
+
+  return(CONFIG_TRUE);
+}
+
+/* ------------------------------------------------------------------------- */
+
+static int __config_read(config_t *config, FILE *stream, const char *filename,
+                         const char *str)
+{
+  yyscan_t scanner;
+  struct scan_context scan_ctx;
+  struct parse_context parse_ctx;
+  YY_BUFFER_STATE buffer = NULL;
+  int r;
+
+  /* Reinitialize the config */
+  void (*destructor)(void *) = config->destructor;
+  const char *include_dir = config->include_dir;
+  unsigned short tab_width = config->tab_width;
+  unsigned short flags = config->flags;
+
+  config->include_dir = NULL;
+  config_destroy(config);
+  config_init(config);
+
+  config->destructor = destructor;
+  config->include_dir = include_dir;
+  config->tab_width = tab_width;
+  config->flags = flags;
+
+  parsectx_init(&parse_ctx);
+  parse_ctx.config = config;
+  parse_ctx.parent = config->root;
+  parse_ctx.setting = config->root;
+
+  __config_locale_override();
+
+  scanctx_init(&scan_ctx, filename);
+  scan_ctx.config = config;
+  libconfig_yylex_init_extra(&scan_ctx, &scanner);
+
+  if(stream)
+    libconfig_yyrestart(stream, scanner);
+  else /* read from string */
+    buffer = libconfig_yy_scan_string(str, scanner);
+
+  libconfig_yyset_lineno(1, scanner);
+  r = libconfig_yyparse(scanner, &parse_ctx, &scan_ctx);
+
+  if(r != 0)
+  {
+    YY_BUFFER_STATE buf;
+
+    config->error_file = scanctx_current_filename(&scan_ctx);
+    config->error_type = CONFIG_ERR_PARSE;
+
+    /* Unwind the include stack, freeing the buffers and closing the files. */
+    while((buf = (YY_BUFFER_STATE)scanctx_pop_include(&scan_ctx)) != NULL)
+      libconfig_yy_delete_buffer(buf, scanner);
+  }
+
+  libconfig_yylex_destroy(scanner);
+  config->filenames = scanctx_cleanup(&scan_ctx, &(config->num_filenames));
+  parsectx_cleanup(&parse_ctx);
+
+  __config_locale_restore();
+
+  return(r == 0 ? CONFIG_TRUE : CONFIG_FALSE);
+}
+
+/* ------------------------------------------------------------------------- */
+
+int config_read(config_t *config, FILE *stream)
+{
+  return(__config_read(config, stream, NULL, NULL));
+}
+
+/* ------------------------------------------------------------------------- */
+
+int config_read_string(config_t *config, const char *str)
+{
+  return(__config_read(config, NULL, NULL, str));
+}
+
+/* ------------------------------------------------------------------------- */
+
+static void __config_write_setting(const config_setting_t *setting,
+                                   FILE *stream, int depth,
+                                   unsigned short tab_width)
+{
+  if(depth > 1)
+    __config_indent(stream, depth, tab_width);
+
+  if(setting->name)
+  {
+    fputs(setting->name, stream);
+    fprintf(stream, " %c ", (setting->type == CONFIG_TYPE_GROUP ? ':' : '='));
+  }
+
+  __config_write_value(&(setting->value), setting->type,
+                       config_setting_get_format(setting),
+                       depth, tab_width, stream);
+
+  if(depth > 0)
+  {
+    fputc(';', stream);
+    fputc('\n', stream);
+  }
+}
+
+/* ------------------------------------------------------------------------- */
+
+void config_write(const config_t *config, FILE *stream)
+{
+  __config_locale_override();
+
+  __config_write_setting(config->root, stream, 0, config->tab_width);
+
+  __config_locale_restore();
+}
+
+/* ------------------------------------------------------------------------- */
+
+int config_read_file(config_t *config, const char *filename)
+{
+  int ret;
+  FILE *stream = fopen(filename, "rt");
+  if(! stream)
+  {
+    config->error_text = __io_error;
+    config->error_type = CONFIG_ERR_FILE_IO;
+    return(CONFIG_FALSE);
+  }
+
+  ret = __config_read(config, stream, filename, NULL);
+  fclose(stream);
+
+  return(ret);
+}
+
+/* ------------------------------------------------------------------------- */
+
+int config_write_file(config_t *config, const char *filename)
+{
+  FILE *f = fopen(filename, "wt");
+  if(! f)
+  {
+    config->error_text = __io_error;
+    config->error_type = CONFIG_ERR_FILE_IO;
+    return(CONFIG_FALSE);
+  }
+
+  config_write(config, f);
+  fclose(f);
+  config->error_type = CONFIG_ERR_NONE;
+  return(CONFIG_TRUE);
+}
+
+/* ------------------------------------------------------------------------- */
+
+void config_destroy(config_t *config)
+{
+  unsigned int count = config->num_filenames;
+  const char **f;
+
+  __config_setting_destroy(config->root);
+
+  for(f = config->filenames; count > 0; ++f, --count)
+    _delete(*f);
+
+  _delete(config->filenames);
+  _delete(config->include_dir);
+
+  memset((void *)config, 0, sizeof(config_t));
+}
+
+/* ------------------------------------------------------------------------- */
+
+void config_init(config_t *config)
+{
+  memset((void *)config, 0, sizeof(config_t));
+
+  config->root = _new(config_setting_t);
+  config->root->type = CONFIG_TYPE_GROUP;
+  config->root->config = config;
+  config->tab_width = 2;
+}
+
+/* ------------------------------------------------------------------------- */
+
+void config_set_auto_convert(config_t *config, int flag)
+{
+  if(flag)
+    config->flags |= CONFIG_OPTION_AUTOCONVERT;
+  else
+    config->flags &= ~CONFIG_OPTION_AUTOCONVERT;
+}
+
+/* ------------------------------------------------------------------------- */
+
+int config_get_auto_convert(const config_t *config)
+{
+  return((config->flags & CONFIG_OPTION_AUTOCONVERT) != 0);
+}
+
+/* ------------------------------------------------------------------------- */
+
+static config_setting_t *config_setting_create(config_setting_t *parent,
+                                               const char *name, int type)
+{
+  config_setting_t *setting;
+  config_list_t *list;
+
+  if((parent->type != CONFIG_TYPE_GROUP)
+     && (parent->type != CONFIG_TYPE_ARRAY)
+     && (parent->type != CONFIG_TYPE_LIST))
+    return(NULL);
+
+  setting = _new(config_setting_t);
+  setting->parent = parent;
+  setting->name = (name == NULL) ? NULL : strdup(name);
+  setting->type = type;
+  setting->config = parent->config;
+  setting->hook = NULL;
+  setting->line = 0;
+
+  list = parent->value.list;
+
+  if(! list)
+    list = parent->value.list = _new(config_list_t);
+
+  __config_list_add(list, setting);
+
+  return(setting);
+}
+
+/* ------------------------------------------------------------------------- */
+
+int config_setting_get_int(const config_setting_t *setting)
+{
+  switch(setting->type)
+  {
+    case CONFIG_TYPE_INT:
+      return(setting->value.ival);
+
+    case CONFIG_TYPE_INT64:
+      if((setting->value.llval > INT32_MAX)
+         || (setting->value.llval < INT32_MIN))
+        return(0);
+      else
+        return((int)setting->value.llval);
+
+    case CONFIG_TYPE_FLOAT:
+      if((setting->config->flags & CONFIG_OPTION_AUTOCONVERT) != 0)
+        return((int)(setting->value.fval));
+      else
+        /* fall through */;
+
+    default:
+      return(0);
+  }
+}
+
+/* ------------------------------------------------------------------------- */
+
+long long config_setting_get_int64(const config_setting_t *setting)
+{
+  switch(setting->type)
+  {
+    case CONFIG_TYPE_INT64:
+      return(setting->value.llval);
+
+    case CONFIG_TYPE_INT:
+      return((long long)setting->value.ival);
+
+    case CONFIG_TYPE_FLOAT:
+      if((setting->config->flags & CONFIG_OPTION_AUTOCONVERT) != 0)
+        return((long long)(setting->value.fval));
+      else
+        /* fall through */;
+
+    default:
+      return(0);
+  }
+}
+
+/* ------------------------------------------------------------------------- */
+
+int config_setting_lookup_int(const config_setting_t *setting,
+                              const char *name, int *value)
+{
+  config_setting_t *member = config_setting_get_member(setting, name);
+  if(! member)
+    return(CONFIG_FALSE);
+
+  if(config_setting_type(member) != CONFIG_TYPE_INT)
+    return(CONFIG_FALSE);
+
+  *value = config_setting_get_int(member);
+  return(CONFIG_TRUE);
+}
+
+/* ------------------------------------------------------------------------- */
+
+int config_setting_lookup_int64(const config_setting_t *setting,
+                                const char *name, long long *value)
+{
+  config_setting_t *member = config_setting_get_member(setting, name);
+  if(! member)
+    return(CONFIG_FALSE);
+
+  if(config_setting_type(member) != CONFIG_TYPE_INT64)
+    return(CONFIG_FALSE);
+
+  *value = config_setting_get_int64(member);
+  return(CONFIG_TRUE);
+}
+
+/* ------------------------------------------------------------------------- */
+
+int config_setting_lookup_float(const config_setting_t *setting,
+                                const char *name, double *value)
+{
+  config_setting_t *member = config_setting_get_member(setting, name);
+  if(! member)
+    return(CONFIG_FALSE);
+
+  if(config_setting_type(member) != CONFIG_TYPE_FLOAT)
+    return(CONFIG_FALSE);
+
+  *value = config_setting_get_float(member);
+  return(CONFIG_TRUE);
+}
+
+/* ------------------------------------------------------------------------- */
+
+int config_setting_lookup_string(const config_setting_t *setting,
+                                 const char *name, const char **value)
+{
+  config_setting_t *member = config_setting_get_member(setting, name);
+  if(! member)
+    return(CONFIG_FALSE);
+
+  if(config_setting_type(member) != CONFIG_TYPE_STRING)
+    return(CONFIG_FALSE);
+
+  *value = config_setting_get_string(member);
+  return(CONFIG_TRUE);
+}
+
+/* ------------------------------------------------------------------------- */
+
+int config_setting_lookup_bool(const config_setting_t *setting,
+                               const char *name, int *value)
+{
+  config_setting_t *member = config_setting_get_member(setting, name);
+  if(! member)
+    return(CONFIG_FALSE);
+
+  if(config_setting_type(member) != CONFIG_TYPE_BOOL)
+    return(CONFIG_FALSE);
+
+  *value = config_setting_get_bool(member);
+  return(CONFIG_TRUE);
+}
+
+/* ------------------------------------------------------------------------- */
+
+int config_setting_set_int(config_setting_t *setting, int value)
+{
+  switch(setting->type)
+  {
+    case CONFIG_TYPE_NONE:
+      setting->type = CONFIG_TYPE_INT;
+      /* fall through */
+
+    case CONFIG_TYPE_INT:
+      setting->value.ival = value;
+      return(CONFIG_TRUE);
+
+    case CONFIG_TYPE_FLOAT:
+      if(config_get_auto_convert(setting->config))
+      {
+        setting->value.fval = (float)value;
+        return(CONFIG_TRUE);
+      }
+      else
+        return(CONFIG_FALSE);
+
+    default:
+      return(CONFIG_FALSE);
+  }
+}
+
+/* ------------------------------------------------------------------------- */
+
+int config_setting_set_int64(config_setting_t *setting, long long value)
+{
+  switch(setting->type)
+  {
+    case CONFIG_TYPE_NONE:
+      setting->type = CONFIG_TYPE_INT64;
+      /* fall through */
+
+    case CONFIG_TYPE_INT64:
+      setting->value.llval = value;
+      return(CONFIG_TRUE);
+
+    case CONFIG_TYPE_INT:
+      if((value > INT32_MAX) || (value < INT32_MIN))
+        setting->value.ival = 0;
+      else
+        setting->value.ival = (int)value;
+      return(CONFIG_TRUE);
+
+    case CONFIG_TYPE_FLOAT:
+      if(config_get_auto_convert(setting->config))
+      {
+        setting->value.fval = (float)value;
+        return(CONFIG_TRUE);
+      }
+      else
+        return(CONFIG_FALSE);
+
+    default:
+      return(CONFIG_FALSE);
+  }
+}
+
+/* ------------------------------------------------------------------------- */
+
+double config_setting_get_float(const config_setting_t *setting)
+{
+  switch(setting->type)
+  {
+    case CONFIG_TYPE_FLOAT:
+      return(setting->value.fval);
+
+    case CONFIG_TYPE_INT:
+      if(config_get_auto_convert(setting->config))
+        return((double)(setting->value.ival));
+      else
+        return(0.0);
+
+    case CONFIG_TYPE_INT64:
+      if(config_get_auto_convert(setting->config))
+        return((double)(setting->value.llval));
+      else
+        return(0.0);
+
+    default:
+      return(0.0);
+  }
+}
+
+/* ------------------------------------------------------------------------- */
+
+int config_setting_set_float(config_setting_t *setting, double value)
+{
+  switch(setting->type)
+  {
+    case CONFIG_TYPE_NONE:
+      setting->type = CONFIG_TYPE_FLOAT;
+      /* fall through */
+
+    case CONFIG_TYPE_FLOAT:
+      setting->value.fval = value;
+      return(CONFIG_TRUE);
+
+    case CONFIG_TYPE_INT:
+      if((setting->config->flags & CONFIG_OPTION_AUTOCONVERT) != 0)
+      {
+        setting->value.ival = (int)value;
+        return(CONFIG_TRUE);
+      }
+      else
+        return(CONFIG_FALSE);
+
+    case CONFIG_TYPE_INT64:
+      if((setting->config->flags & CONFIG_OPTION_AUTOCONVERT) != 0)
+      {
+        setting->value.llval = (long long)value;
+        return(CONFIG_TRUE);
+      }
+      else
+        return(CONFIG_FALSE);
+
+    default:
+      return(CONFIG_FALSE);
+  }
+}
+
+/* ------------------------------------------------------------------------- */
+
+int config_setting_get_bool(const config_setting_t *setting)
+{
+  return((setting->type == CONFIG_TYPE_BOOL) ? setting->value.ival : 0);
+}
+
+/* ------------------------------------------------------------------------- */
+
+int config_setting_set_bool(config_setting_t *setting, int value)
+{
+  if(setting->type == CONFIG_TYPE_NONE)
+    setting->type = CONFIG_TYPE_BOOL;
+  else if(setting->type != CONFIG_TYPE_BOOL)
+    return(CONFIG_FALSE);
+
+  setting->value.ival = value;
+  return(CONFIG_TRUE);
+}
+
+/* ------------------------------------------------------------------------- */
+
+const char *config_setting_get_string(const config_setting_t *setting)
+{
+  return((setting->type == CONFIG_TYPE_STRING) ? setting->value.sval : NULL);
+}
+
+/* ------------------------------------------------------------------------- */
+
+int config_setting_set_string(config_setting_t *setting, const char *value)
+{
+  if(setting->type == CONFIG_TYPE_NONE)
+    setting->type = CONFIG_TYPE_STRING;
+  else if(setting->type != CONFIG_TYPE_STRING)
+    return(CONFIG_FALSE);
+
+  if(setting->value.sval)
+    _delete(setting->value.sval);
+
+  setting->value.sval = (value == NULL) ? NULL : strdup(value);
+  return(CONFIG_TRUE);
+}
+
+/* ------------------------------------------------------------------------- */
+
+int config_setting_set_format(config_setting_t *setting, short format)
+{
+  if(((setting->type != CONFIG_TYPE_INT)
+      && (setting->type != CONFIG_TYPE_INT64))
+     || ((format != CONFIG_FORMAT_DEFAULT) && (format != CONFIG_FORMAT_HEX)))
+    return(CONFIG_FALSE);
+
+  setting->format = format;
+
+  return(CONFIG_TRUE);
+}
+
+/* ------------------------------------------------------------------------- */
+
+short config_setting_get_format(const config_setting_t *setting)
+{
+  return(setting->format != 0 ? setting->format
+         : setting->config->default_format);
+}
+
+/* ------------------------------------------------------------------------- */
+
+config_setting_t *config_lookup_from(config_setting_t *setting,
+                                     const char *path)
+{
+  const char *p = path;
+  config_setting_t *found;
+
+  for(;;)
+  {
+    while(*p && strchr(PATH_TOKENS, *p))
+      p++;
+
+    if(! *p)
+      break;
+
+    if(*p == '[')
+      found = config_setting_get_elem(setting, atoi(++p));
+    else
+      found = config_setting_get_member(setting, p);
+
+    if(! found)
+      break;
+
+    setting = found;
+
+    while(! strchr(PATH_TOKENS, *p))
+      p++;
+  }
+
+  return(*p ? NULL : setting);
+}
+
+/* ------------------------------------------------------------------------- */
+
+config_setting_t *config_lookup(const config_t *config, const char *path)
+{
+  return(config_lookup_from(config->root, path));
+}
+
+/* ------------------------------------------------------------------------- */
+
+int config_lookup_string(const config_t *config, const char *path,
+                         const char **value)
+{
+  const config_setting_t *s = config_lookup(config, path);
+  if(! s)
+    return(CONFIG_FALSE);
+
+  if(config_setting_type(s) != CONFIG_TYPE_STRING)
+    return(CONFIG_FALSE);
+
+  *value = config_setting_get_string(s);
+
+  return(CONFIG_TRUE);
+}
+
+/* ------------------------------------------------------------------------- */
+
+int config_lookup_int(const config_t *config, const char *path,
+                      int *value)
+{
+  const config_setting_t *s = config_lookup(config, path);
+  if(! s)
+    return(CONFIG_FALSE);
+
+  if(config_setting_type(s) != CONFIG_TYPE_INT)
+    return(CONFIG_FALSE);
+
+  *value = config_setting_get_int(s);
+
+  return(CONFIG_TRUE);
+}
+
+/* ------------------------------------------------------------------------- */
+
+int config_lookup_int64(const config_t *config, const char *path,
+                        long long *value)
+{
+  const config_setting_t *s = config_lookup(config, path);
+  if(! s)
+    return(CONFIG_FALSE);
+
+  if(config_setting_type(s) != CONFIG_TYPE_INT64)
+    return(CONFIG_FALSE);
+
+  *value = config_setting_get_int64(s);
+
+  return(CONFIG_TRUE);
+}
+
+/* ------------------------------------------------------------------------- */
+
+int config_lookup_float(const config_t *config, const char *path,
+                        double *value)
+{
+  const config_setting_t *s = config_lookup(config, path);
+  if(! s)
+    return(CONFIG_FALSE);
+
+  if(config_setting_type(s) != CONFIG_TYPE_FLOAT)
+    return(CONFIG_FALSE);
+
+  *value = config_setting_get_float(s);
+  return(CONFIG_TRUE);
+}
+
+/* ------------------------------------------------------------------------- */
+
+int config_lookup_bool(const config_t *config, const char *path, int *value)
+{
+  const config_setting_t *s = config_lookup(config, path);
+  if(! s)
+    return(CONFIG_FALSE);
+
+  if(config_setting_type(s) != CONFIG_TYPE_BOOL)
+    return(CONFIG_FALSE);
+
+  *value = config_setting_get_bool(s);
+  return(CONFIG_TRUE);
+}
+
+/* ------------------------------------------------------------------------- */
+
+int config_setting_get_int_elem(const config_setting_t *vector, int idx)
+{
+  const config_setting_t *element = config_setting_get_elem(vector, idx);
+
+  return(element ? config_setting_get_int(element) : 0);
+}
+
+/* ------------------------------------------------------------------------- */
+
+config_setting_t *config_setting_set_int_elem(config_setting_t *vector,
+                                              int idx, int value)
+{
+  config_setting_t *element = NULL;
+
+  if((vector->type != CONFIG_TYPE_ARRAY) && (vector->type != CONFIG_TYPE_LIST))
+    return(NULL);
+
+  if(idx < 0)
+  {
+    if(! __config_vector_checktype(vector, CONFIG_TYPE_INT))
+      return(NULL);
+
+    element = config_setting_create(vector, NULL, CONFIG_TYPE_INT);
+  }
+  else
+  {
+    element = config_setting_get_elem(vector, idx);
+
+    if(! element)
+      return(NULL);
+  }
+
+  if(! config_setting_set_int(element, value))
+    return(NULL);
+
+  return(element);
+}
+
+/* ------------------------------------------------------------------------- */
+
+long long config_setting_get_int64_elem(const config_setting_t *vector,
+                                        int idx)
+{
+  const config_setting_t *element = config_setting_get_elem(vector, idx);
+
+  return(element ? config_setting_get_int64(element) : 0);
+}
+
+/* ------------------------------------------------------------------------- */
+
+config_setting_t *config_setting_set_int64_elem(config_setting_t *vector,
+                                                int idx, long long value)
+{
+  config_setting_t *element = NULL;
+
+  if((vector->type != CONFIG_TYPE_ARRAY) && (vector->type != CONFIG_TYPE_LIST))
+    return(NULL);
+
+  if(idx < 0)
+  {
+    if(! __config_vector_checktype(vector, CONFIG_TYPE_INT64))
+      return(NULL);
+
+    element = config_setting_create(vector, NULL, CONFIG_TYPE_INT64);
+  }
+  else
+  {
+    element = config_setting_get_elem(vector, idx);
+
+    if(! element)
+      return(NULL);
+  }
+
+  if(! config_setting_set_int64(element, value))
+    return(NULL);
+
+  return(element);
+}
+
+/* ------------------------------------------------------------------------- */
+
+double config_setting_get_float_elem(const config_setting_t *vector, int idx)
+{
+  config_setting_t *element = config_setting_get_elem(vector, idx);
+
+  return(element ? config_setting_get_float(element) : 0.0);
+}
+
+/* ------------------------------------------------------------------------- */
+
+config_setting_t *config_setting_set_float_elem(config_setting_t *vector,
+                                                int idx, double value)
+{
+  config_setting_t *element = NULL;
+
+  if((vector->type != CONFIG_TYPE_ARRAY) && (vector->type != CONFIG_TYPE_LIST))
+    return(NULL);
+
+  if(idx < 0)
+  {
+    if(! __config_vector_checktype(vector, CONFIG_TYPE_FLOAT))
+      return(NULL);
+
+    element = config_setting_create(vector, NULL, CONFIG_TYPE_FLOAT);
+  }
+  else
+    element = config_setting_get_elem(vector, idx);
+
+  if(! element)
+    return(NULL);
+
+  if(! config_setting_set_float(element, value))
+    return(NULL);
+
+  return(element);
+}
+
+/* ------------------------------------------------------------------------- */
+
+int config_setting_get_bool_elem(const config_setting_t *vector, int idx)
+{
+  config_setting_t *element = config_setting_get_elem(vector, idx);
+
+  if(! element)
+    return(CONFIG_FALSE);
+
+  if(element->type != CONFIG_TYPE_BOOL)
+    return(CONFIG_FALSE);
+
+  return(element->value.ival);
+}
+
+/* ------------------------------------------------------------------------- */
+
+config_setting_t *config_setting_set_bool_elem(config_setting_t *vector,
+                                               int idx, int value)
+{
+  config_setting_t *element = NULL;
+
+  if((vector->type != CONFIG_TYPE_ARRAY) && (vector->type != CONFIG_TYPE_LIST))
+    return(NULL);
+
+  if(idx < 0)
+  {
+    if(! __config_vector_checktype(vector, CONFIG_TYPE_BOOL))
+      return(NULL);
+
+    element = config_setting_create(vector, NULL, CONFIG_TYPE_BOOL);
+  }
+  else
+    element = config_setting_get_elem(vector, idx);
+
+  if(! element)
+    return(NULL);
+
+  if(! config_setting_set_bool(element, value))
+    return(NULL);
+
+  return(element);
+}
+
+/* ------------------------------------------------------------------------- */
+
+const char *config_setting_get_string_elem(const config_setting_t *vector,
+                                           int idx)
+{
+  config_setting_t *element = config_setting_get_elem(vector, idx);
+
+  if(! element)
+    return(NULL);
+
+  if(element->type != CONFIG_TYPE_STRING)
+    return(NULL);
+
+  return(element->value.sval);
+}
+
+/* ------------------------------------------------------------------------- */
+
+config_setting_t *config_setting_set_string_elem(config_setting_t *vector,
+                                                 int idx, const char *value)
+{
+  config_setting_t *element = NULL;
+
+  if((vector->type != CONFIG_TYPE_ARRAY) && (vector->type != CONFIG_TYPE_LIST))
+    return(NULL);
+
+  if(idx < 0)
+  {
+    if(! __config_vector_checktype(vector, CONFIG_TYPE_STRING))
+      return(NULL);
+
+    element = config_setting_create(vector, NULL, CONFIG_TYPE_STRING);
+  }
+  else
+    element = config_setting_get_elem(vector, idx);
+
+  if(! element)
+    return(NULL);
+
+  if(! config_setting_set_string(element, value))
+    return(NULL);
+
+  return(element);
+}
+
+/* ------------------------------------------------------------------------- */
+
+config_setting_t *config_setting_get_elem(const config_setting_t *vector,
+                                          unsigned int idx)
+{
+  config_list_t *list = vector->value.list;
+
+  if(((vector->type != CONFIG_TYPE_ARRAY)
+      && (vector->type != CONFIG_TYPE_LIST)
+      && (vector->type != CONFIG_TYPE_GROUP)) || ! list)
+    return(NULL);
+
+  if(idx >= list->length)
+    return(NULL);
+
+  return(list->elements[idx]);
+}
+
+/* ------------------------------------------------------------------------- */
+
+config_setting_t *config_setting_get_member(const config_setting_t *setting,
+                                            const char *name)
+{
+  if(setting->type != CONFIG_TYPE_GROUP)
+    return(NULL);
+
+  return(__config_list_search(setting->value.list, name, NULL));
+}
+
+/* ------------------------------------------------------------------------- */
+
+void config_set_destructor(config_t *config, void (*destructor)(void *))
+{
+  config->destructor = destructor;
+}
+
+/* ------------------------------------------------------------------------- */
+
+void config_set_include_dir(config_t *config, const char *include_dir)
+{
+  _delete(config->include_dir);
+  config->include_dir = strdup(include_dir);
+}
+
+/* ------------------------------------------------------------------------- */
+
+int config_setting_length(const config_setting_t *setting)
+{
+  if((setting->type != CONFIG_TYPE_GROUP)
+     && (setting->type != CONFIG_TYPE_ARRAY)
+     && (setting->type != CONFIG_TYPE_LIST))
+    return(0);
+
+  if(! setting->value.list)
+    return(0);
+
+  return(setting->value.list->length);
+}
+
+/* ------------------------------------------------------------------------- */
+
+void config_setting_set_hook(config_setting_t *setting, void *hook)
+{
+  setting->hook = hook;
+}
+
+/* ------------------------------------------------------------------------- */
+
+config_setting_t *config_setting_add(config_setting_t *parent,
+                                     const char *name, int type)
+{
+  if((type < CONFIG_TYPE_NONE) || (type > CONFIG_TYPE_LIST))
+    return(NULL);
+
+  if(! parent)
+    return(NULL);
+
+  if((parent->type == CONFIG_TYPE_ARRAY) || (parent->type == CONFIG_TYPE_LIST))
+    name = NULL;
+
+  if(name)
+  {
+    if(! __config_validate_name(name))
+      return(NULL);
+  }
+
+  if(config_setting_get_member(parent, name) != NULL)
+    return(NULL); /* already exists */
+
+  return(config_setting_create(parent, name, type));
+}
+
+/* ------------------------------------------------------------------------- */
+
+int config_setting_remove(config_setting_t *parent, const char *name)
+{
+  unsigned int idx;
+  config_setting_t *setting;
+
+  if(! parent)
+    return(CONFIG_FALSE);
+
+  if(parent->type != CONFIG_TYPE_GROUP)
+    return(CONFIG_FALSE);
+
+  if(! (setting = __config_list_search(parent->value.list, name, &idx)))
+    return(CONFIG_FALSE);
+
+  __config_list_remove(parent->value.list, idx);
+  __config_setting_destroy(setting);
+
+  return(CONFIG_TRUE);
+}
+
+/* ------------------------------------------------------------------------- */
+
+int config_setting_remove_elem(config_setting_t *parent, unsigned int idx)
+{
+  config_list_t *list;
+  config_setting_t *removed = NULL;
+
+  if(! parent)
+    return(CONFIG_FALSE);
+
+  list = parent->value.list;
+
+  if(((parent->type != CONFIG_TYPE_ARRAY)
+      && (parent->type != CONFIG_TYPE_LIST)
+      && (parent->type != CONFIG_TYPE_GROUP)) || ! list)
+    return(CONFIG_FALSE);
+
+  if(idx >= list->length)
+    return(CONFIG_FALSE);
+
+  removed = __config_list_remove(list, idx);
+  __config_setting_destroy(removed);
+
+  return(CONFIG_TRUE);
+}
+
+/* ------------------------------------------------------------------------- */
+
+int config_setting_index(const config_setting_t *setting)
+{
+  config_setting_t **found = NULL;
+  config_list_t *list;
+  int i;
+
+  if(! setting->parent)
+    return(-1);
+
+  list = setting->parent->value.list;
+
+  for(i = 0, found = list->elements; i < list->length; ++i, ++found)
+  {
+    if(*found == setting)
+      return(i);
+  }
+
+  return(-1);
+}
+
+/* ------------------------------------------------------------------------- */
+/* eof */
diff --git a/3rdparty/libconfig/libconfig.h b/3rdparty/libconfig/libconfig.h
new file mode 100644
index 0000000..ca689bb
--- /dev/null
+++ b/3rdparty/libconfig/libconfig.h
@@ -0,0 +1,321 @@
+/* ----------------------------------------------------------------------------
+   libconfig - A library for processing structured configuration files
+   Copyright (C) 2005-2010  Mark A Lindner
+
+   This file is part of libconfig.
+
+   This library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public License
+   as published by the Free Software Foundation; either version 2.1 of
+   the License, or (at your option) any later version.
+
+   This library is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with this library; if not, see
+   <http://www.gnu.org/licenses/>.
+   ----------------------------------------------------------------------------
+*/
+
+#ifndef __libconfig_h
+#define __libconfig_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+#if defined(_WIN32) || defined(__WIN32__) || defined(WIN32)
+#if defined(LIBCONFIG_STATIC)
+#define LIBCONFIG_API
+#elif defined(LIBCONFIG_EXPORTS)
+#define LIBCONFIG_API __declspec(dllexport)
+#else /* ! LIBCONFIG_EXPORTS */
+#define LIBCONFIG_API __declspec(dllimport)
+#endif /* LIBCONFIG_STATIC */
+#else /* ! WIN32 */
+#define LIBCONFIG_API
+#endif /* WIN32 */
+
+#define LIBCONFIG_VER_MAJOR    1
+#define LIBCONFIG_VER_MINOR    4
+#define LIBCONFIG_VER_REVISION 7
+
+#include <stdio.h>
+
+#define CONFIG_TYPE_NONE    0
+#define CONFIG_TYPE_GROUP   1
+#define CONFIG_TYPE_INT     2
+#define CONFIG_TYPE_INT64   3
+#define CONFIG_TYPE_FLOAT   4
+#define CONFIG_TYPE_STRING  5
+#define CONFIG_TYPE_BOOL    6
+#define CONFIG_TYPE_ARRAY   7
+#define CONFIG_TYPE_LIST    8
+
+#define CONFIG_FORMAT_DEFAULT  0
+#define CONFIG_FORMAT_HEX      1
+
+#define CONFIG_OPTION_AUTOCONVERT 0x01
+
+#define CONFIG_TRUE  (1)
+#define CONFIG_FALSE (0)
+
+typedef union config_value_t
+{
+  int ival;
+  long long llval;
+  double fval;
+  char *sval;
+  struct config_list_t *list;
+} config_value_t;
+
+typedef struct config_setting_t
+{
+  char *name;
+  short type;
+  short format;
+  config_value_t value;
+  struct config_setting_t *parent;
+  struct config_t *config;
+  void *hook;
+  unsigned int line;
+  const char *file;
+} config_setting_t;
+
+typedef enum
+{
+  CONFIG_ERR_NONE = 0,
+  CONFIG_ERR_FILE_IO = 1,
+  CONFIG_ERR_PARSE = 2
+} config_error_t;
+
+typedef struct config_list_t
+{
+  unsigned int length;
+  config_setting_t **elements;
+} config_list_t;
+
+typedef struct config_t
+{
+  config_setting_t *root;
+  void (*destructor)(void *);
+  unsigned short flags;
+  unsigned short tab_width;
+  short default_format;
+  const char *include_dir;
+  const char *error_text;
+  const char *error_file;
+  int error_line;
+  config_error_t error_type;
+  const char **filenames;
+  unsigned int num_filenames;
+} config_t;
+
+extern LIBCONFIG_API int config_read(config_t *config, FILE *stream);
+extern LIBCONFIG_API void config_write(const config_t *config, FILE *stream);
+
+extern LIBCONFIG_API void config_set_default_format(config_t *config,
+                                                    short format);
+
+extern LIBCONFIG_API void config_set_auto_convert(config_t *config, int flag);
+extern LIBCONFIG_API int config_get_auto_convert(const config_t *config);
+
+extern LIBCONFIG_API int config_read_string(config_t *config, const char *str);
+
+extern LIBCONFIG_API int config_read_file(config_t *config,
+                                          const char *filename);
+extern LIBCONFIG_API int config_write_file(config_t *config,
+                                           const char *filename);
+
+extern LIBCONFIG_API void config_set_destructor(config_t *config,
+                                                void (*destructor)(void *));
+extern LIBCONFIG_API void config_set_include_dir(config_t *config,
+                                                 const char *include_dir);
+
+extern LIBCONFIG_API void config_init(config_t *config);
+extern LIBCONFIG_API void config_destroy(config_t *config);
+
+extern LIBCONFIG_API int config_setting_get_int(
+  const config_setting_t *setting);
+extern LIBCONFIG_API long long config_setting_get_int64(
+  const config_setting_t *setting);
+extern LIBCONFIG_API double config_setting_get_float(
+  const config_setting_t *setting);
+extern LIBCONFIG_API int config_setting_get_bool(
+  const config_setting_t *setting);
+extern LIBCONFIG_API const char *config_setting_get_string(
+  const config_setting_t *setting);
+
+extern LIBCONFIG_API int config_setting_lookup_int(
+  const config_setting_t *setting, const char *name, int *value);
+extern LIBCONFIG_API int config_setting_lookup_int64(
+  const config_setting_t *setting, const char *name, long long *value);
+extern LIBCONFIG_API int config_setting_lookup_float(
+  const config_setting_t *setting, const char *name, double *value);
+extern LIBCONFIG_API int config_setting_lookup_bool(
+  const config_setting_t *setting, const char *name, int *value);
+extern LIBCONFIG_API int config_setting_lookup_string(
+  const config_setting_t *setting, const char *name, const char **value);
+
+extern LIBCONFIG_API int config_setting_set_int(config_setting_t *setting,
+                                                int value);
+extern LIBCONFIG_API int config_setting_set_int64(config_setting_t *setting,
+                                                  long long value);
+extern LIBCONFIG_API int config_setting_set_float(config_setting_t *setting,
+                                                  double value);
+extern LIBCONFIG_API int config_setting_set_bool(config_setting_t *setting,
+                                                 int value);
+extern LIBCONFIG_API int config_setting_set_string(config_setting_t *setting,
+                                                   const char *value);
+
+extern LIBCONFIG_API int config_setting_set_format(config_setting_t *setting,
+                                                   short format);
+extern LIBCONFIG_API short config_setting_get_format(
+  const config_setting_t *setting);
+
+extern LIBCONFIG_API int config_setting_get_int_elem(
+  const config_setting_t *setting, int idx);
+extern LIBCONFIG_API long long config_setting_get_int64_elem(
+  const config_setting_t *setting, int idx);
+extern LIBCONFIG_API double config_setting_get_float_elem(
+  const config_setting_t *setting, int idx);
+extern LIBCONFIG_API int config_setting_get_bool_elem(
+  const config_setting_t *setting, int idx);
+extern LIBCONFIG_API const char *config_setting_get_string_elem(
+  const config_setting_t *setting, int idx);
+
+extern LIBCONFIG_API config_setting_t *config_setting_set_int_elem(
+  config_setting_t *setting, int idx, int value);
+extern LIBCONFIG_API config_setting_t *config_setting_set_int64_elem(
+  config_setting_t *setting, int idx, long long value);
+extern LIBCONFIG_API config_setting_t *config_setting_set_float_elem(
+  config_setting_t *setting, int idx, double value);
+extern LIBCONFIG_API config_setting_t *config_setting_set_bool_elem(
+  config_setting_t *setting, int idx, int value);
+extern LIBCONFIG_API config_setting_t *config_setting_set_string_elem(
+  config_setting_t *setting, int idx, const char *value);
+
+#define /* const char * */ config_get_include_dir(/* const config_t * */ C) \
+  ((C)->include_dir)
+
+#define /* int */ config_setting_type(/* const config_setting_t * */ S) \
+  ((S)->type)
+
+#define /* int */ config_setting_is_group(/* const config_setting_t * */ S) \
+  ((S)->type == CONFIG_TYPE_GROUP)
+#define /* int */ config_setting_is_array(/* const config_setting_t * */ S) \
+  ((S)->type == CONFIG_TYPE_ARRAY)
+#define /* int */ config_setting_is_list(/* const config_setting_t * */ S) \
+  ((S)->type == CONFIG_TYPE_LIST)
+
+#define /* int */ config_setting_is_aggregate( \
+  /* const config_setting_t * */ S)                                     \
+  (((S)->type == CONFIG_TYPE_GROUP) || ((S)->type == CONFIG_TYPE_LIST)  \
+   || ((S)->type == CONFIG_TYPE_ARRAY))
+
+#define /* int */ config_setting_is_number(/* const config_setting_t * */ S) \
+  (((S)->type == CONFIG_TYPE_INT)                                       \
+   || ((S)->type == CONFIG_TYPE_INT64)                                  \
+   || ((S)->type == CONFIG_TYPE_FLOAT))
+
+#define /* int */ config_setting_is_scalar(/* const config_setting_t * */ S) \
+  (((S)->type == CONFIG_TYPE_BOOL) || ((S)->type == CONFIG_TYPE_STRING) \
+   || config_setting_is_number(S))
+
+#define /* const char * */ config_setting_name( \
+  /* const config_setting_t * */ S)             \
+  ((S)->name)
+
+#define /* config_setting_t * */ config_setting_parent( \
+  /* const config_setting_t * */ S)                     \
+  ((S)->parent)
+
+#define /* int */ config_setting_is_root(       \
+  /* const config_setting_t * */ S)             \
+  ((S)->parent ? CONFIG_FALSE : CONFIG_TRUE)
+
+extern LIBCONFIG_API int config_setting_index(const config_setting_t *setting);
+
+extern LIBCONFIG_API int config_setting_length(
+  const config_setting_t *setting);
+extern LIBCONFIG_API config_setting_t *config_setting_get_elem(
+  const config_setting_t *setting, unsigned int idx);
+
+extern LIBCONFIG_API config_setting_t *config_setting_get_member(
+  const config_setting_t *setting, const char *name);
+
+extern LIBCONFIG_API config_setting_t *config_setting_add(
+  config_setting_t *parent, const char *name, int type);
+extern LIBCONFIG_API int config_setting_remove(config_setting_t *parent,
+                                               const char *name);
+extern LIBCONFIG_API int config_setting_remove_elem(config_setting_t *parent,
+                                                    unsigned int idx);
+extern LIBCONFIG_API void config_setting_set_hook(config_setting_t *setting,
+                                                  void *hook);
+
+#define config_setting_get_hook(S) ((S)->hook)
+
+extern LIBCONFIG_API config_setting_t *config_lookup(const config_t *config,
+                                                     const char *path);
+extern LIBCONFIG_API config_setting_t *config_lookup_from(
+  config_setting_t *setting, const char *path);
+
+extern LIBCONFIG_API int config_lookup_int(const config_t *config,
+                                           const char *path, int *value);
+extern LIBCONFIG_API int config_lookup_int64(const config_t *config,
+                                             const char *path,
+                                             long long *value);
+extern LIBCONFIG_API int config_lookup_float(const config_t *config,
+                                             const char *path, double *value);
+extern LIBCONFIG_API int config_lookup_bool(const config_t *config,
+                                            const char *path, int *value);
+extern LIBCONFIG_API int config_lookup_string(const config_t *config,
+                                              const char *path,
+                                              const char **value);
+
+#define /* config_setting_t * */ config_root_setting( \
+  /* const config_t * */ C)                           \
+  ((C)->root)
+
+#define  /* void */ config_set_default_format(/* config_t * */ C,       \
+                                              /* short */ F)            \
+  (C)->default_format = (F)
+
+#define /* short */ config_get_default_format(/* config_t * */ C)       \
+  ((C)->default_format)
+
+#define /* void */ config_set_tab_width(/* config_t * */ C,     \
+                                        /* unsigned short */ W) \
+  (C)->tab_width = ((W) & 0x0F)
+
+#define /* unsigned char */ config_get_tab_width(/* const config_t * */ C) \
+  ((C)->tab_width)
+
+#define /* unsigned short */ config_setting_source_line(   \
+  /* const config_setting_t * */ S)                        \
+  ((S)->line)
+
+#define /* const char */ config_setting_source_file(    \
+  /* const config_setting_t * */ S)                     \
+  ((S)->file)
+
+#define /* const char * */ config_error_text(/* const config_t * */ C)  \
+  ((C)->error_text)
+
+#define /* const char * */ config_error_file(/* const config_t * */ C)  \
+  ((C)->error_file)
+
+#define /* int */ config_error_line(/* const config_t * */ C)   \
+  ((C)->error_line)
+
+#define /* config_error_t */ config_error_type(/* const config_t * */ C) \
+  ((C)->error_type)
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* __libconfig_h */
diff --git a/3rdparty/libconfig/parsectx.h b/3rdparty/libconfig/parsectx.h
new file mode 100644
index 0000000..af09b56
--- /dev/null
+++ b/3rdparty/libconfig/parsectx.h
@@ -0,0 +1,48 @@
+/* ----------------------------------------------------------------------------
+   libconfig - A library for processing structured configuration files
+   Copyright (C) 2005-2010  Mark A Lindner
+
+   This file is part of libconfig.
+
+   This library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public License
+   as published by the Free Software Foundation; either version 2.1 of
+   the License, or (at your option) any later version.
+
+   This library is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with this library; if not, see
+   <http://www.gnu.org/licenses/>.
+   ----------------------------------------------------------------------------
+*/
+
+#ifndef __libconfig_parsectx_h
+#define __libconfig_parsectx_h
+
+#include "libconfig.h"
+#include "strbuf.h"
+
+struct parse_context
+{
+  config_t *config;
+  config_setting_t *parent;
+  config_setting_t *setting;
+  char *name;
+  strbuf_t string;
+};
+
+#define parsectx_init(C)                        \
+  memset((C), 0, sizeof(struct parse_context))
+#define parsectx_cleanup(C)                             \
+  free((void *)(strbuf_release(&((C)->string))))
+
+#define parsectx_append_string(C, S)            \
+  strbuf_append(&((C)->string), (S))
+#define parsectx_take_string(C)                 \
+  strbuf_release(&((C)->string))
+
+#endif /* __libconfig_parsectx_h */
diff --git a/3rdparty/libconfig/scanctx.c b/3rdparty/libconfig/scanctx.c
new file mode 100644
index 0000000..f287fdf
--- /dev/null
+++ b/3rdparty/libconfig/scanctx.c
@@ -0,0 +1,171 @@
+/* ----------------------------------------------------------------------------
+   libconfig - A library for processing structured configuration files
+   Copyright (C) 2005-2010  Mark A Lindner
+
+   This file is part of libconfig.
+
+   This library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public License
+   as published by the Free Software Foundation; either version 2.1 of
+   the License, or (at your option) any later version.
+
+   This library is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with this library; if not, see
+   <http://www.gnu.org/licenses/>.
+   ----------------------------------------------------------------------------
+*/
+
+#include "scanctx.h"
+#include "wincompat.h"
+
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define STRING_BLOCK_SIZE 64
+#define CHUNK_SIZE 32
+
+/* ------------------------------------------------------------------------- */
+
+static const char *err_bad_include = "cannot open include file";
+static const char *err_include_too_deep = "include file nesting too deep";
+
+/* ------------------------------------------------------------------------- */
+
+static const char *__scanctx_add_filename(struct scan_context *ctx,
+                                          const char *filename)
+{
+  unsigned int count = ctx->num_filenames;
+  const char **f;
+
+  for(f = ctx->filenames; count > 0; ++f, --count)
+  {
+    if(!strcmp(*f, filename))
+    {
+      free((void *)filename);
+      return(*f); /* already in list */
+    }
+  }
+
+  if((ctx->num_filenames % CHUNK_SIZE) == 0)
+  {
+    ctx->filenames = (const char **)realloc(
+      (void *)ctx->filenames,
+      (ctx->num_filenames + CHUNK_SIZE) * sizeof(const char *));
+  }
+
+  ctx->filenames[ctx->num_filenames] = filename;
+  ++ctx->num_filenames;
+  return(filename);
+}
+
+/* ------------------------------------------------------------------------- */
+
+void scanctx_init(struct scan_context *ctx, const char *top_filename)
+{
+  memset(ctx, 0, sizeof(struct scan_context));
+  if(top_filename)
+    ctx->top_filename = __scanctx_add_filename(ctx, strdup(top_filename));
+}
+
+/* ------------------------------------------------------------------------- */
+
+const char **scanctx_cleanup(struct scan_context *ctx,
+                             unsigned int *num_filenames)
+{
+  int i;
+
+  for(i = 0; i < ctx->depth; ++i)
+    fclose(ctx->streams[i]);
+
+  free((void *)(strbuf_release(&(ctx->string))));
+
+  *num_filenames = ctx->num_filenames;
+  return(ctx->filenames);
+}
+
+/* ------------------------------------------------------------------------- */
+
+FILE *scanctx_push_include(struct scan_context *ctx, void *buffer,
+                           const char **error)
+{
+  FILE *fp = NULL;
+  const char *file;
+  char *full_file = NULL;
+
+  *error = NULL;
+
+  if(ctx->depth == MAX_INCLUDE_DEPTH)
+  {
+    *error = err_include_too_deep;
+    return(NULL);
+  }
+
+  file = scanctx_take_string(ctx);
+  if(ctx->config->include_dir)
+  {
+    full_file = (char *)malloc(strlen(ctx->config->include_dir) + strlen(file)
+                               + 2);
+    strcpy(full_file, ctx->config->include_dir);
+    strcat(full_file, FILE_SEPARATOR);
+    strcat(full_file, file);
+  }
+
+  fp = fopen(full_file ? full_file : file, "rt");
+  free((void *)full_file);
+
+  if(fp)
+  {
+    ctx->streams[ctx->depth] = fp;
+    ctx->files[ctx->depth] = __scanctx_add_filename(ctx, file);
+    ctx->buffers[ctx->depth] = buffer;
+    ++(ctx->depth);
+  }
+  else
+  {
+    free((void *)file);
+    *error = err_bad_include;
+  }
+
+  return(fp);
+}
+
+/* ------------------------------------------------------------------------- */
+
+void *scanctx_pop_include(struct scan_context *ctx)
+{
+  void *buffer;
+
+  if(ctx->depth == 0)
+    return(NULL); /* stack underflow */
+
+  --(ctx->depth);
+  buffer = ctx->buffers[ctx->depth];
+  fclose(ctx->streams[ctx->depth]);
+
+  return(buffer);
+}
+
+/* ------------------------------------------------------------------------- */
+
+char *scanctx_take_string(struct scan_context *ctx)
+{
+  char *r = strbuf_release(&(ctx->string));
+
+  return(r ? r : strdup(""));
+}
+
+/* ------------------------------------------------------------------------- */
+
+const char *scanctx_current_filename(struct scan_context *ctx)
+{
+  return((ctx->depth == 0) ? ctx->top_filename : ctx->files[ctx->depth - 1]);
+}
+
+/* ------------------------------------------------------------------------- */
+/* eof */
diff --git a/3rdparty/libconfig/scanctx.h b/3rdparty/libconfig/scanctx.h
new file mode 100644
index 0000000..8ff934e
--- /dev/null
+++ b/3rdparty/libconfig/scanctx.h
@@ -0,0 +1,62 @@
+/* ----------------------------------------------------------------------------
+   libconfig - A library for processing structured configuration files
+   Copyright (C) 2005-2010  Mark A Lindner
+
+   This file is part of libconfig.
+
+   This library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public License
+   as published by the Free Software Foundation; either version 2.1 of
+   the License, or (at your option) any later version.
+
+   This library is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with this library; if not, see
+   <http://www.gnu.org/licenses/>.
+   ----------------------------------------------------------------------------
+*/
+
+#ifndef __libconfig_scanctx_h
+#define __libconfig_scanctx_h
+
+#include "libconfig.h"
+#include "strbuf.h"
+
+#include <stdio.h>
+#include <sys/types.h>
+
+#define MAX_INCLUDE_DEPTH 10
+
+struct scan_context
+{
+  config_t *config;
+  const char *top_filename;
+  const char *files[MAX_INCLUDE_DEPTH];
+  void *buffers[MAX_INCLUDE_DEPTH];
+  FILE *streams[MAX_INCLUDE_DEPTH];
+  int depth;
+  strbuf_t string;
+  const char **filenames;
+  unsigned int num_filenames;
+};
+
+extern void scanctx_init(struct scan_context *ctx, const char *top_filename);
+extern const char **scanctx_cleanup(struct scan_context *ctx,
+                                    unsigned int *num_filenames);
+
+extern FILE *scanctx_push_include(struct scan_context *ctx, void *prev_buffer,
+                                  const char **error);
+extern void *scanctx_pop_include(struct scan_context *ctx);
+
+#define scanctx_append_string(C, S)             \
+  strbuf_append(&((C)->string), (S))
+
+extern char *scanctx_take_string(struct scan_context *ctx);
+
+extern const char *scanctx_current_filename(struct scan_context *ctx);
+
+#endif /* __libconfig_scanctx_h */
diff --git a/3rdparty/libconfig/scanner.c b/3rdparty/libconfig/scanner.c
new file mode 100644
index 0000000..d0b8beb
--- /dev/null
+++ b/3rdparty/libconfig/scanner.c
@@ -0,0 +1,2362 @@
+#line 2 "scanner.c"
+
+#line 4 "scanner.c"
+
+#define  YY_INT_ALIGNED short int
+
+/* A lexical scanner generated by flex */
+
+#define FLEX_SCANNER
+#define YY_FLEX_MAJOR_VERSION 2
+#define YY_FLEX_MINOR_VERSION 5
+#define YY_FLEX_SUBMINOR_VERSION 35
+#if YY_FLEX_SUBMINOR_VERSION > 0
+#define FLEX_BETA
+#endif
+
+/* First, we deal with  platform-specific or compiler-specific issues. */
+
+/* begin standard C headers. */
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <stdlib.h>
+
+/* end standard C headers. */
+
+/* flex integer type definitions */
+
+#ifndef FLEXINT_H
+#define FLEXINT_H
+
+/* C99 systems have <inttypes.h>. Non-C99 systems may or may not. */
+
+#if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
+
+/* C99 says to define __STDC_LIMIT_MACROS before including stdint.h,
+ * if you want the limit (max/min) macros for int types. 
+ */
+#ifndef __STDC_LIMIT_MACROS
+#define __STDC_LIMIT_MACROS 1
+#endif
+
+#include <inttypes.h>
+typedef int8_t flex_int8_t;
+typedef uint8_t flex_uint8_t;
+typedef int16_t flex_int16_t;
+typedef uint16_t flex_uint16_t;
+typedef int32_t flex_int32_t;
+typedef uint32_t flex_uint32_t;
+#else
+typedef signed char flex_int8_t;
+typedef short int flex_int16_t;
+typedef int flex_int32_t;
+typedef unsigned char flex_uint8_t; 
+typedef unsigned short int flex_uint16_t;
+typedef unsigned int flex_uint32_t;
+
+/* Limits of integral types. */
+#ifndef INT8_MIN
+#define INT8_MIN               (-128)
+#endif
+#ifndef INT16_MIN
+#define INT16_MIN              (-32767-1)
+#endif
+#ifndef INT32_MIN
+#define INT32_MIN              (-2147483647-1)
+#endif
+#ifndef INT8_MAX
+#define INT8_MAX               (127)
+#endif
+#ifndef INT16_MAX
+#define INT16_MAX              (32767)
+#endif
+#ifndef INT32_MAX
+#define INT32_MAX              (2147483647)
+#endif
+#ifndef UINT8_MAX
+#define UINT8_MAX              (255U)
+#endif
+#ifndef UINT16_MAX
+#define UINT16_MAX             (65535U)
+#endif
+#ifndef UINT32_MAX
+#define UINT32_MAX             (4294967295U)
+#endif
+
+#endif /* ! C99 */
+
+#endif /* ! FLEXINT_H */
+
+#ifdef __cplusplus
+
+/* The "const" storage-class-modifier is valid. */
+#define YY_USE_CONST
+
+#else	/* ! __cplusplus */
+
+/* C99 requires __STDC__ to be defined as 1. */
+#if defined (__STDC__)
+
+#define YY_USE_CONST
+
+#endif	/* defined (__STDC__) */
+#endif	/* ! __cplusplus */
+
+#ifdef YY_USE_CONST
+#define yyconst const
+#else
+#define yyconst
+#endif
+
+/* Returned upon end-of-file. */
+#define YY_NULL 0
+
+/* Promotes a possibly negative, possibly signed char to an unsigned
+ * integer for use as an array index.  If the signed char is negative,
+ * we want to instead treat it as an 8-bit unsigned char, hence the
+ * double cast.
+ */
+#define YY_SC_TO_UI(c) ((unsigned int) (unsigned char) c)
+
+/* An opaque pointer. */
+#ifndef YY_TYPEDEF_YY_SCANNER_T
+#define YY_TYPEDEF_YY_SCANNER_T
+typedef void* yyscan_t;
+#endif
+
+/* For convenience, these vars (plus the bison vars far below)
+   are macros in the reentrant scanner. */
+#define yyin yyg->yyin_r
+#define yyout yyg->yyout_r
+#define yyextra yyg->yyextra_r
+#define yyleng yyg->yyleng_r
+#define yytext yyg->yytext_r
+#define yylineno (YY_CURRENT_BUFFER_LVALUE->yy_bs_lineno)
+#define yycolumn (YY_CURRENT_BUFFER_LVALUE->yy_bs_column)
+#define yy_flex_debug yyg->yy_flex_debug_r
+
+/* Enter a start condition.  This macro really ought to take a parameter,
+ * but we do it the disgusting crufty way forced on us by the ()-less
+ * definition of BEGIN.
+ */
+#define BEGIN yyg->yy_start = 1 + 2 *
+
+/* Translate the current start state into a value that can be later handed
+ * to BEGIN to return to the state.  The YYSTATE alias is for lex
+ * compatibility.
+ */
+#define YY_START ((yyg->yy_start - 1) / 2)
+#define YYSTATE YY_START
+
+/* Action number for EOF rule of a given start state. */
+#define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1)
+
+/* Special action meaning "start processing a new file". */
+#define YY_NEW_FILE libconfig_yyrestart(yyin ,yyscanner )
+
+#define YY_END_OF_BUFFER_CHAR 0
+
+/* Size of default input buffer. */
+#ifndef YY_BUF_SIZE
+#ifdef __ia64__
+/* On IA-64, the buffer size is 16k, not 8k.
+ * Moreover, YY_BUF_SIZE is 2*YY_READ_BUF_SIZE in the general case.
+ * Ditto for the __ia64__ case accordingly.
+ */
+#define YY_BUF_SIZE 32768
+#else
+#define YY_BUF_SIZE 16384
+#endif /* __ia64__ */
+#endif
+
+/* The state buf must be large enough to hold one state per character in the main buffer.
+ */
+#define YY_STATE_BUF_SIZE   ((YY_BUF_SIZE + 2) * sizeof(yy_state_type))
+
+#ifndef YY_TYPEDEF_YY_BUFFER_STATE
+#define YY_TYPEDEF_YY_BUFFER_STATE
+typedef struct yy_buffer_state *YY_BUFFER_STATE;
+#endif
+
+#define EOB_ACT_CONTINUE_SCAN 0
+#define EOB_ACT_END_OF_FILE 1
+#define EOB_ACT_LAST_MATCH 2
+
+    /* Note: We specifically omit the test for yy_rule_can_match_eol because it requires
+     *       access to the local variable yy_act. Since yyless() is a macro, it would break
+     *       existing scanners that call yyless() from OUTSIDE libconfig_yylex. 
+     *       One obvious solution it to make yy_act a global. I tried that, and saw
+     *       a 5% performance hit in a non-yylineno scanner, because yy_act is
+     *       normally declared as a register variable-- so it is not worth it.
+     */
+    #define  YY_LESS_LINENO(n) \
+            do { \
+                int yyl;\
+                for ( yyl = n; yyl < yyleng; ++yyl )\
+                    if ( yytext[yyl] == '\n' )\
+                        --yylineno;\
+            }while(0)
+    
+/* Return all but the first "n" matched characters back to the input stream. */
+#define yyless(n) \
+	do \
+		{ \
+		/* Undo effects of setting up yytext. */ \
+        int yyless_macro_arg = (n); \
+        YY_LESS_LINENO(yyless_macro_arg);\
+		*yy_cp = yyg->yy_hold_char; \
+		YY_RESTORE_YY_MORE_OFFSET \
+		yyg->yy_c_buf_p = yy_cp = yy_bp + yyless_macro_arg - YY_MORE_ADJ; \
+		YY_DO_BEFORE_ACTION; /* set up yytext again */ \
+		} \
+	while ( 0 )
+
+#define unput(c) yyunput( c, yyg->yytext_ptr , yyscanner )
+
+#ifndef YY_TYPEDEF_YY_SIZE_T
+#define YY_TYPEDEF_YY_SIZE_T
+typedef size_t yy_size_t;
+#endif
+
+#ifndef YY_STRUCT_YY_BUFFER_STATE
+#define YY_STRUCT_YY_BUFFER_STATE
+struct yy_buffer_state
+	{
+	FILE *yy_input_file;
+
+	char *yy_ch_buf;		/* input buffer */
+	char *yy_buf_pos;		/* current position in input buffer */
+
+	/* Size of input buffer in bytes, not including room for EOB
+	 * characters.
+	 */
+	yy_size_t yy_buf_size;
+
+	/* Number of characters read into yy_ch_buf, not including EOB
+	 * characters.
+	 */
+	int yy_n_chars;
+
+	/* Whether we "own" the buffer - i.e., we know we created it,
+	 * and can realloc() it to grow it, and should free() it to
+	 * delete it.
+	 */
+	int yy_is_our_buffer;
+
+	/* Whether this is an "interactive" input source; if so, and
+	 * if we're using stdio for input, then we want to use getc()
+	 * instead of fread(), to make sure we stop fetching input after
+	 * each newline.
+	 */
+	int yy_is_interactive;
+
+	/* Whether we're considered to be at the beginning of a line.
+	 * If so, '^' rules will be active on the next match, otherwise
+	 * not.
+	 */
+	int yy_at_bol;
+
+    int yy_bs_lineno; /**< The line count. */
+    int yy_bs_column; /**< The column count. */
+    
+	/* Whether to try to fill the input buffer when we reach the
+	 * end of it.
+	 */
+	int yy_fill_buffer;
+
+	int yy_buffer_status;
+
+#define YY_BUFFER_NEW 0
+#define YY_BUFFER_NORMAL 1
+	/* When an EOF's been seen but there's still some text to process
+	 * then we mark the buffer as YY_EOF_PENDING, to indicate that we
+	 * shouldn't try reading from the input source any more.  We might
+	 * still have a bunch of tokens to match, though, because of
+	 * possible backing-up.
+	 *
+	 * When we actually see the EOF, we change the status to "new"
+	 * (via libconfig_yyrestart()), so that the user can continue scanning by
+	 * just pointing yyin at a new input file.
+	 */
+#define YY_BUFFER_EOF_PENDING 2
+
+	};
+#endif /* !YY_STRUCT_YY_BUFFER_STATE */
+
+/* We provide macros for accessing buffer states in case in the
+ * future we want to put the buffer states in a more general
+ * "scanner state".
+ *
+ * Returns the top of the stack, or NULL.
+ */
+#define YY_CURRENT_BUFFER ( yyg->yy_buffer_stack \
+                          ? yyg->yy_buffer_stack[yyg->yy_buffer_stack_top] \
+                          : NULL)
+
+/* Same as previous macro, but useful when we know that the buffer stack is not
+ * NULL or when we need an lvalue. For internal use only.
+ */
+#define YY_CURRENT_BUFFER_LVALUE yyg->yy_buffer_stack[yyg->yy_buffer_stack_top]
+
+void libconfig_yyrestart (FILE *input_file ,yyscan_t yyscanner );
+void libconfig_yy_switch_to_buffer (YY_BUFFER_STATE new_buffer ,yyscan_t yyscanner );
+YY_BUFFER_STATE libconfig_yy_create_buffer (FILE *file,int size ,yyscan_t yyscanner );
+void libconfig_yy_delete_buffer (YY_BUFFER_STATE b ,yyscan_t yyscanner );
+void libconfig_yy_flush_buffer (YY_BUFFER_STATE b ,yyscan_t yyscanner );
+void libconfig_yypush_buffer_state (YY_BUFFER_STATE new_buffer ,yyscan_t yyscanner );
+void libconfig_yypop_buffer_state (yyscan_t yyscanner );
+
+static void libconfig_yyensure_buffer_stack (yyscan_t yyscanner );
+static void libconfig_yy_load_buffer_state (yyscan_t yyscanner );
+static void libconfig_yy_init_buffer (YY_BUFFER_STATE b,FILE *file ,yyscan_t yyscanner );
+
+#define YY_FLUSH_BUFFER libconfig_yy_flush_buffer(YY_CURRENT_BUFFER ,yyscanner)
+
+YY_BUFFER_STATE libconfig_yy_scan_buffer (char *base,yy_size_t size ,yyscan_t yyscanner );
+YY_BUFFER_STATE libconfig_yy_scan_string (yyconst char *yy_str ,yyscan_t yyscanner );
+YY_BUFFER_STATE libconfig_yy_scan_bytes (yyconst char *bytes,int len ,yyscan_t yyscanner );
+
+void *libconfig_yyalloc (yy_size_t ,yyscan_t yyscanner );
+void *libconfig_yyrealloc (void *,yy_size_t ,yyscan_t yyscanner );
+void libconfig_yyfree (void * ,yyscan_t yyscanner );
+
+#define yy_new_buffer libconfig_yy_create_buffer
+
+#define yy_set_interactive(is_interactive) \
+	{ \
+	if ( ! YY_CURRENT_BUFFER ){ \
+        libconfig_yyensure_buffer_stack (yyscanner); \
+		YY_CURRENT_BUFFER_LVALUE =    \
+            libconfig_yy_create_buffer(yyin,YY_BUF_SIZE ,yyscanner); \
+	} \
+	YY_CURRENT_BUFFER_LVALUE->yy_is_interactive = is_interactive; \
+	}
+
+#define yy_set_bol(at_bol) \
+	{ \
+	if ( ! YY_CURRENT_BUFFER ){\
+        libconfig_yyensure_buffer_stack (yyscanner); \
+		YY_CURRENT_BUFFER_LVALUE =    \
+            libconfig_yy_create_buffer(yyin,YY_BUF_SIZE ,yyscanner); \
+	} \
+	YY_CURRENT_BUFFER_LVALUE->yy_at_bol = at_bol; \
+	}
+
+#define YY_AT_BOL() (YY_CURRENT_BUFFER_LVALUE->yy_at_bol)
+
+#define libconfig_yywrap(n) 1
+#define YY_SKIP_YYWRAP
+
+typedef unsigned char YY_CHAR;
+
+typedef int yy_state_type;
+
+#define yytext_ptr yytext_r
+
+static yy_state_type yy_get_previous_state (yyscan_t yyscanner );
+static yy_state_type yy_try_NUL_trans (yy_state_type current_state  ,yyscan_t yyscanner);
+static int yy_get_next_buffer (yyscan_t yyscanner );
+static void yy_fatal_error (yyconst char msg[] ,yyscan_t yyscanner );
+
+/* Done after the current pattern has been matched and before the
+ * corresponding action - sets up yytext.
+ */
+#define YY_DO_BEFORE_ACTION \
+	yyg->yytext_ptr = yy_bp; \
+	yyleng = (size_t) (yy_cp - yy_bp); \
+	yyg->yy_hold_char = *yy_cp; \
+	*yy_cp = '\0'; \
+	yyg->yy_c_buf_p = yy_cp;
+
+#define YY_NUM_RULES 41
+#define YY_END_OF_BUFFER 42
+/* This struct is not used in this scanner,
+   but its presence is necessary. */
+struct yy_trans_info
+	{
+	flex_int32_t yy_verify;
+	flex_int32_t yy_nxt;
+	};
+static yyconst flex_int16_t yy_accept[103] =
+    {   0,
+        0,    0,    0,    0,    0,    0,    0,    0,   42,   40,
+       21,   20,   20,    5,   40,   36,   37,   28,   40,   23,
+       29,   40,   30,   30,   22,   38,   28,   28,   34,   35,
+       24,   25,   21,   40,    3,    4,    3,    6,   14,   41,
+       16,   19,   41,   21,    0,   39,   28,   29,   30,   29,
+        0,    1,    0,   29,    0,   31,    0,   28,   28,   21,
+        0,    0,    2,    6,   12,    0,   11,   10,    7,    8,
+        9,   16,   18,   17,    0,   29,   29,    0,    0,   29,
+       31,   32,   28,   28,    0,    0,    0,   29,   33,   28,
+       26,    0,   13,   33,   27,    0,    0,    0,    0,    0,
+
+       15,    0
+    } ;
+
+static yyconst flex_int32_t yy_ec[256] =
+    {   0,
+        1,    1,    1,    1,    1,    1,    1,    1,    2,    3,
+        1,    4,    5,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    2,    1,    6,    7,    1,    1,    1,    1,    8,
+        9,   10,   11,   12,   13,   14,   15,   16,   17,   17,
+       17,   17,   17,   17,   17,   17,   17,   18,   19,    1,
+       20,    1,    1,   21,   22,   23,   23,   23,   24,   25,
+       26,   26,   26,   26,   26,   27,   26,   26,   26,   26,
+       26,   28,   29,   30,   31,   26,   26,   32,   26,   26,
+       33,   34,   35,    1,   36,    1,   22,   23,   37,   38,
+
+       39,   40,   26,   26,   41,   26,   26,   42,   26,   43,
+       26,   26,   26,   44,   29,   45,   46,   26,   26,   32,
+       26,   26,   47,    1,   48,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1
+    } ;
+
+static yyconst flex_int32_t yy_meta[49] =
+    {   0,
+        1,    1,    1,    1,    1,    2,    1,    1,    1,    3,
+        1,    1,    3,    1,    1,    4,    4,    1,    1,    1,
+        1,    4,    4,    4,    4,    3,    3,    3,    3,    3,
+        3,    3,    1,    2,    1,    3,    4,    4,    4,    4,
+        3,    3,    3,    3,    3,    3,    1,    1
+    } ;
+
+static yyconst flex_int16_t yy_base[113] =
+    {   0,
+        0,   47,   47,   48,   46,   47,   48,   49,  203,  204,
+      200,  204,  204,  204,  198,  204,  204,    0,   45,  204,
+       47,   50,   60,   74,  204,  204,  178,   28,  204,  204,
+      204,  204,   64,  158,  204,  204,  183,    0,  204,   63,
+        0,  204,   83,  195,  193,  204,    0,   88,  102,   98,
+       62,  204,  190,  104,  119,  162,    0,   67,   65,  121,
+      127,  124,  204,    0,  204,    0,  204,  204,  204,  204,
+      204,    0,  204,  204,  108,  117,  122,  134,  132,  136,
+      204,  139,  136,  116,  126,    0,  140,  142,  135,  130,
+        0,  102,  204,  204,    0,   85,   72,   63,   98,  158,
+
+      204,  204,  169,  173,  177,  181,  183,  187,  191,   89,
+       66,   63
+    } ;
+
+static yyconst flex_int16_t yy_def[113] =
+    {   0,
+      102,    1,  103,  103,  104,  104,  105,  105,  102,  102,
+      102,  102,  102,  102,  106,  102,  102,  107,  102,  102,
+      102,  102,  102,  102,  102,  102,  107,  107,  102,  102,
+      102,  102,  102,  102,  102,  102,  102,  108,  102,  102,
+      109,  102,  102,  102,  106,  102,  107,  102,  102,  102,
+      102,  102,  106,  102,  102,  102,  110,  107,  107,  102,
+      102,  102,  102,  108,  102,  111,  102,  102,  102,  102,
+      102,  109,  102,  102,  102,  102,  102,  102,  102,  102,
+      102,  110,  107,  107,  102,  112,  102,  102,  102,  107,
+      107,  102,  102,  102,  107,  102,  102,  102,  102,  102,
+
+      102,    0,  102,  102,  102,  102,  102,  102,  102,  102,
+      102,  102
+    } ;
+
+static yyconst flex_int16_t yy_nxt[253] =
+    {   0,
+       10,   11,   12,   13,   13,   14,   15,   16,   17,   18,
+       19,   20,   19,   21,   22,   23,   24,   25,   26,   25,
+       10,   18,   18,   18,   27,   18,   18,   18,   18,   28,
+       18,   18,   29,   10,   30,   10,   18,   18,   18,   27,
+       18,   18,   18,   18,   28,   18,   31,   32,   33,   36,
+       36,   39,   39,   42,   42,   59,   37,   37,   48,   52,
+       49,   49,   50,   50,   53,   60,   93,   34,   65,   86,
+       51,   59,   75,   54,   75,   49,   49,   76,   76,   40,
+       40,   43,   43,   55,   61,   51,   56,   54,   73,   49,
+       49,   57,   82,   83,   66,   84,   67,   55,   55,  100,
+
+       56,   99,   68,   50,   50,   69,   70,   71,   83,   98,
+       84,   51,   55,   50,   50,   54,   74,   49,   49,   77,
+       77,   51,   60,   76,   76,   55,   51,   78,   56,   79,
+       97,   79,   76,   76,   80,   80,   51,   77,   77,   91,
+       55,   61,   78,   96,   87,   78,   87,   80,   80,   88,
+       88,   80,   80,   95,   91,   88,   88,   88,   88,  100,
+       78,   94,   92,  101,   90,   89,   85,   62,   95,   35,
+       35,   35,   35,   38,   38,   38,   38,   41,   41,   41,
+       41,   45,   45,   45,   45,   47,   47,   64,   81,   64,
+       64,   72,   46,   72,   72,   46,   44,   63,   62,   58,
+
+       46,   44,  102,    9,  102,  102,  102,  102,  102,  102,
+      102,  102,  102,  102,  102,  102,  102,  102,  102,  102,
+      102,  102,  102,  102,  102,  102,  102,  102,  102,  102,
+      102,  102,  102,  102,  102,  102,  102,  102,  102,  102,
+      102,  102,  102,  102,  102,  102,  102,  102,  102,  102,
+      102,  102
+    } ;
+
+static yyconst flex_int16_t yy_chk[253] =
+    {   0,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    2,    3,
+        4,    5,    6,    7,    8,   28,    3,    4,   19,   22,
+       19,   19,   21,   21,   22,   33,  112,    2,   40,  111,
+       21,   28,   51,   23,   51,   23,   23,   51,   51,    5,
+        6,    7,    8,   23,   33,   21,   23,   24,   43,   24,
+       24,   23,  110,   58,   40,   59,   40,   24,   23,   99,
+
+       24,   98,   40,   48,   48,   40,   40,   40,   58,   97,
+       59,   48,   24,   50,   50,   49,   43,   49,   49,   54,
+       54,   50,   60,   75,   75,   49,   48,   54,   49,   55,
+       96,   55,   76,   76,   55,   55,   50,   77,   77,   84,
+       49,   60,   54,   92,   78,   77,   78,   79,   79,   78,
+       78,   80,   80,   90,   84,   87,   87,   88,   88,  100,
+       77,   89,   85,  100,   83,   82,   62,   61,   90,  103,
+      103,  103,  103,  104,  104,  104,  104,  105,  105,  105,
+      105,  106,  106,  106,  106,  107,  107,  108,   56,  108,
+      108,  109,   53,  109,  109,   45,   44,   37,   34,   27,
+
+       15,   11,    9,  102,  102,  102,  102,  102,  102,  102,
+      102,  102,  102,  102,  102,  102,  102,  102,  102,  102,
+      102,  102,  102,  102,  102,  102,  102,  102,  102,  102,
+      102,  102,  102,  102,  102,  102,  102,  102,  102,  102,
+      102,  102,  102,  102,  102,  102,  102,  102,  102,  102,
+      102,  102
+    } ;
+
+/* Table of booleans, true if rule could match eol. */
+static yyconst flex_int32_t yy_rule_can_match_eol[42] =
+    {   0,
+0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 
+    1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+    0, 0,     };
+
+/* The intent behind this definition is that it'll catch
+ * any uses of REJECT which flex missed.
+ */
+#define REJECT reject_used_but_not_detected
+#define yymore() yymore_used_but_not_detected
+#define YY_MORE_ADJ 0
+#define YY_RESTORE_YY_MORE_OFFSET
+#line 1 "scanner.l"
+/* -*- mode: C -*- */
+/* --------------------------------------------------------------------------
+   libconfig - A library for processing structured configuration files
+   Copyright (C) 2005-2010  Mark A Lindner
+
+   This file is part of libconfig.
+
+   This library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public License
+   as published by the Free Software Foundation; either version 2.1 of
+   the License, or (at your option) any later version.
+
+   This library is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with this library; if not, see
+   <http://www.gnu.org/licenses/>.
+   ----------------------------------------------------------------------------
+*/
+#define YY_NO_UNISTD_H 1
+#line 35 "scanner.l"
+
+#ifdef _MSC_VER
+#pragma warning (disable: 4996)
+#endif
+
+#include <stdlib.h>
+#include <ctype.h>
+#include <string.h>
+#include "grammar.h"
+#include "wincompat.h"
+#include "parsectx.h"
+#include "scanctx.h"
+
+#define YY_NO_INPUT // Suppress generation of useless input() function
+
+static unsigned long long fromhex(const char *s)
+{
+#ifdef __MINGW32__
+
+  /* MinGW's strtoull() seems to be broken; it only returns the lower
+   * 32 bits...
+   */
+
+  const char *p = s;
+  unsigned long long val = 0;
+
+  if(*p != '0')
+    return(0);
+
+  ++p;
+
+  if(*p != 'x' && *p != 'X')
+    return(0);
+
+  for(++p; isxdigit(*p); ++p)
+  {
+    val <<= 4;
+    val |= ((*p < 'A') ? (*p & 0xF) : (9 + (*p & 0x7)));
+  }
+
+  return(val);
+
+#else /* ! __MINGW32__ */
+
+  return(strtoull(s, NULL, 16));
+
+#endif /* __MINGW32__ */
+}
+
+
+#line 626 "scanner.c"
+
+#define INITIAL 0
+#define COMMENT 1
+#define STRING 2
+#define INCLUDE 3
+
+#ifndef YY_NO_UNISTD_H
+/* Special case for "unistd.h", since it is non-ANSI. We include it way
+ * down here because we want the user's section 1 to have been scanned first.
+ * The user has a chance to override it with an option.
+ */
+#include <unistd.h>
+#endif
+
+#define YY_EXTRA_TYPE struct scan_context *
+
+/* Holds the entire state of the reentrant scanner. */
+struct yyguts_t
+    {
+
+    /* User-defined. Not touched by flex. */
+    YY_EXTRA_TYPE yyextra_r;
+
+    /* The rest are the same as the globals declared in the non-reentrant scanner. */
+    FILE *yyin_r, *yyout_r;
+    size_t yy_buffer_stack_top; /**< index of top of stack. */
+    size_t yy_buffer_stack_max; /**< capacity of stack. */
+    YY_BUFFER_STATE * yy_buffer_stack; /**< Stack as an array. */
+    char yy_hold_char;
+    int yy_n_chars;
+    int yyleng_r;
+    char *yy_c_buf_p;
+    int yy_init;
+    int yy_start;
+    int yy_did_buffer_switch_on_eof;
+    int yy_start_stack_ptr;
+    int yy_start_stack_depth;
+    int *yy_start_stack;
+    yy_state_type yy_last_accepting_state;
+    char* yy_last_accepting_cpos;
+
+    int yylineno_r;
+    int yy_flex_debug_r;
+
+    char *yytext_r;
+    int yy_more_flag;
+    int yy_more_len;
+
+    YYSTYPE * yylval_r;
+
+    }; /* end struct yyguts_t */
+
+static int yy_init_globals (yyscan_t yyscanner );
+
+    /* This must go here because YYSTYPE and YYLTYPE are included
+     * from bison output in section 1.*/
+    #    define yylval yyg->yylval_r
+    
+int libconfig_yylex_init (yyscan_t* scanner);
+
+int libconfig_yylex_init_extra (YY_EXTRA_TYPE user_defined,yyscan_t* scanner);
+
+/* Accessor methods to globals.
+   These are made visible to non-reentrant scanners for convenience. */
+
+int libconfig_yylex_destroy (yyscan_t yyscanner );
+
+int libconfig_yyget_debug (yyscan_t yyscanner );
+
+void libconfig_yyset_debug (int debug_flag ,yyscan_t yyscanner );
+
+YY_EXTRA_TYPE libconfig_yyget_extra (yyscan_t yyscanner );
+
+void libconfig_yyset_extra (YY_EXTRA_TYPE user_defined ,yyscan_t yyscanner );
+
+FILE *libconfig_yyget_in (yyscan_t yyscanner );
+
+void libconfig_yyset_in  (FILE * in_str ,yyscan_t yyscanner );
+
+FILE *libconfig_yyget_out (yyscan_t yyscanner );
+
+void libconfig_yyset_out  (FILE * out_str ,yyscan_t yyscanner );
+
+int libconfig_yyget_leng (yyscan_t yyscanner );
+
+char *libconfig_yyget_text (yyscan_t yyscanner );
+
+int libconfig_yyget_lineno (yyscan_t yyscanner );
+
+void libconfig_yyset_lineno (int line_number ,yyscan_t yyscanner );
+
+YYSTYPE * libconfig_yyget_lval (yyscan_t yyscanner );
+
+void libconfig_yyset_lval (YYSTYPE * yylval_param ,yyscan_t yyscanner );
+
+/* Macros after this point can all be overridden by user definitions in
+ * section 1.
+ */
+
+#ifndef YY_SKIP_YYWRAP
+#ifdef __cplusplus
+extern "C" int libconfig_yywrap (yyscan_t yyscanner );
+#else
+extern int libconfig_yywrap (yyscan_t yyscanner );
+#endif
+#endif
+
+#ifndef yytext_ptr
+static void yy_flex_strncpy (char *,yyconst char *,int ,yyscan_t yyscanner);
+#endif
+
+#ifdef YY_NEED_STRLEN
+static int yy_flex_strlen (yyconst char * ,yyscan_t yyscanner);
+#endif
+
+#ifndef YY_NO_INPUT
+
+#ifdef __cplusplus
+static int yyinput (yyscan_t yyscanner );
+#else
+static int input (yyscan_t yyscanner );
+#endif
+
+#endif
+
+/* Amount of stuff to slurp up with each read. */
+#ifndef YY_READ_BUF_SIZE
+#ifdef __ia64__
+/* On IA-64, the buffer size is 16k, not 8k */
+#define YY_READ_BUF_SIZE 16384
+#else
+#define YY_READ_BUF_SIZE 8192
+#endif /* __ia64__ */
+#endif
+
+/* Copy whatever the last rule matched to the standard output. */
+#ifndef ECHO
+/* This used to be an fputs(), but since the string might contain NUL's,
+ * we now use fwrite().
+ */
+#define ECHO do { if (fwrite( yytext, yyleng, 1, yyout )) {} } while (0)
+#endif
+
+/* Gets input and stuffs it into "buf".  number of characters read, or YY_NULL,
+ * is returned in "result".
+ */
+#ifndef YY_INPUT
+#define YY_INPUT(buf,result,max_size) \
+	if ( YY_CURRENT_BUFFER_LVALUE->yy_is_interactive ) \
+		{ \
+		int c = '*'; \
+		size_t n; \
+		for ( n = 0; n < max_size && \
+			     (c = getc( yyin )) != EOF && c != '\n'; ++n ) \
+			buf[n] = (char) c; \
+		if ( c == '\n' ) \
+			buf[n++] = (char) c; \
+		if ( c == EOF && ferror( yyin ) ) \
+			YY_FATAL_ERROR( "input in flex scanner failed" ); \
+		result = n; \
+		} \
+	else \
+		{ \
+		errno=0; \
+		while ( (result = fread(buf, 1, max_size, yyin))==0 && ferror(yyin)) \
+			{ \
+			if( errno != EINTR) \
+				{ \
+				YY_FATAL_ERROR( "input in flex scanner failed" ); \
+				break; \
+				} \
+			errno=0; \
+			clearerr(yyin); \
+			} \
+		}\
+\
+
+#endif
+
+/* No semi-colon after return; correct usage is to write "yyterminate();" -
+ * we don't want an extra ';' after the "return" because that will cause
+ * some compilers to complain about unreachable statements.
+ */
+#ifndef yyterminate
+#define yyterminate() return YY_NULL
+#endif
+
+/* Number of entries by which start-condition stack grows. */
+#ifndef YY_START_STACK_INCR
+#define YY_START_STACK_INCR 25
+#endif
+
+/* Report a fatal error. */
+#ifndef YY_FATAL_ERROR
+#define YY_FATAL_ERROR(msg) yy_fatal_error( msg , yyscanner)
+#endif
+
+/* end tables serialization structures and prototypes */
+
+/* Default declaration of generated scanner - a define so the user can
+ * easily add parameters.
+ */
+#ifndef YY_DECL
+#define YY_DECL_IS_OURS 1
+
+extern int libconfig_yylex \
+               (YYSTYPE * yylval_param ,yyscan_t yyscanner);
+
+#define YY_DECL int libconfig_yylex \
+               (YYSTYPE * yylval_param , yyscan_t yyscanner)
+#endif /* !YY_DECL */
+
+/* Code executed at the beginning of each rule, after yytext and yyleng
+ * have been set up.
+ */
+#ifndef YY_USER_ACTION
+#define YY_USER_ACTION
+#endif
+
+/* Code executed at the end of each rule. */
+#ifndef YY_BREAK
+#define YY_BREAK break;
+#endif
+
+#define YY_RULE_SETUP \
+	if ( yyleng > 0 ) \
+		YY_CURRENT_BUFFER_LVALUE->yy_at_bol = \
+				(yytext[yyleng - 1] == '\n'); \
+	YY_USER_ACTION
+
+/** The main scanner function which does all the work.
+ */
+YY_DECL
+{
+	register yy_state_type yy_current_state;
+	register char *yy_cp, *yy_bp;
+	register int yy_act;
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
+#line 100 "scanner.l"
+
+
+#line 869 "scanner.c"
+
+    yylval = yylval_param;
+
+	if ( !yyg->yy_init )
+		{
+		yyg->yy_init = 1;
+
+#ifdef YY_USER_INIT
+		YY_USER_INIT;
+#endif
+
+		if ( ! yyg->yy_start )
+			yyg->yy_start = 1;	/* first start state */
+
+		if ( ! yyin )
+			yyin = stdin;
+
+		if ( ! yyout )
+			yyout = stdout;
+
+		if ( ! YY_CURRENT_BUFFER ) {
+			libconfig_yyensure_buffer_stack (yyscanner);
+			YY_CURRENT_BUFFER_LVALUE =
+				libconfig_yy_create_buffer(yyin,YY_BUF_SIZE ,yyscanner);
+		}
+
+		libconfig_yy_load_buffer_state(yyscanner );
+		}
+
+	while ( 1 )		/* loops until end-of-file is reached */
+		{
+		yy_cp = yyg->yy_c_buf_p;
+
+		/* Support of yytext. */
+		*yy_cp = yyg->yy_hold_char;
+
+		/* yy_bp points to the position in yy_ch_buf of the start of
+		 * the current run.
+		 */
+		yy_bp = yy_cp;
+
+		yy_current_state = yyg->yy_start;
+		yy_current_state += YY_AT_BOL();
+yy_match:
+		do
+			{
+			register YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)];
+			if ( yy_accept[yy_current_state] )
+				{
+				yyg->yy_last_accepting_state = yy_current_state;
+				yyg->yy_last_accepting_cpos = yy_cp;
+				}
+			while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
+				{
+				yy_current_state = (int) yy_def[yy_current_state];
+				if ( yy_current_state >= 103 )
+					yy_c = yy_meta[(unsigned int) yy_c];
+				}
+			yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
+			++yy_cp;
+			}
+		while ( yy_base[yy_current_state] != 204 );
+
+yy_find_action:
+		yy_act = yy_accept[yy_current_state];
+		if ( yy_act == 0 )
+			{ /* have to back up */
+			yy_cp = yyg->yy_last_accepting_cpos;
+			yy_current_state = yyg->yy_last_accepting_state;
+			yy_act = yy_accept[yy_current_state];
+			}
+
+		YY_DO_BEFORE_ACTION;
+
+		if ( yy_act != YY_END_OF_BUFFER && yy_rule_can_match_eol[yy_act] )
+			{
+			int yyl;
+			for ( yyl = 0; yyl < yyleng; ++yyl )
+				if ( yytext[yyl] == '\n' )
+					   
+    do{ yylineno++;
+        yycolumn=0;
+    }while(0)
+;
+			}
+
+do_action:	/* This label is used only to access EOF actions. */
+
+		switch ( yy_act )
+	{ /* beginning of action switch */
+			case 0: /* must back up */
+			/* undo the effects of YY_DO_BEFORE_ACTION */
+			*yy_cp = yyg->yy_hold_char;
+			yy_cp = yyg->yy_last_accepting_cpos;
+			yy_current_state = yyg->yy_last_accepting_state;
+			goto yy_find_action;
+
+case 1:
+YY_RULE_SETUP
+#line 102 "scanner.l"
+{ BEGIN COMMENT; }
+	YY_BREAK
+case 2:
+YY_RULE_SETUP
+#line 103 "scanner.l"
+{ BEGIN INITIAL; }
+	YY_BREAK
+case 3:
+YY_RULE_SETUP
+#line 104 "scanner.l"
+{ /* ignore */ }
+	YY_BREAK
+case 4:
+/* rule 4 can match eol */
+YY_RULE_SETUP
+#line 105 "scanner.l"
+{ /* ignore */ }
+	YY_BREAK
+case 5:
+YY_RULE_SETUP
+#line 107 "scanner.l"
+{ BEGIN STRING; }
+	YY_BREAK
+case 6:
+/* rule 6 can match eol */
+YY_RULE_SETUP
+#line 108 "scanner.l"
+{ scanctx_append_string(yyextra, yytext); }
+	YY_BREAK
+case 7:
+YY_RULE_SETUP
+#line 109 "scanner.l"
+{ scanctx_append_string(yyextra, "\n"); }
+	YY_BREAK
+case 8:
+YY_RULE_SETUP
+#line 110 "scanner.l"
+{ scanctx_append_string(yyextra, "\r"); }
+	YY_BREAK
+case 9:
+YY_RULE_SETUP
+#line 111 "scanner.l"
+{ scanctx_append_string(yyextra, "\t"); }
+	YY_BREAK
+case 10:
+YY_RULE_SETUP
+#line 112 "scanner.l"
+{ scanctx_append_string(yyextra, "\f"); }
+	YY_BREAK
+case 11:
+YY_RULE_SETUP
+#line 113 "scanner.l"
+{ scanctx_append_string(yyextra, "\\"); }
+	YY_BREAK
+case 12:
+YY_RULE_SETUP
+#line 114 "scanner.l"
+{ scanctx_append_string(yyextra, "\""); }
+	YY_BREAK
+case 13:
+YY_RULE_SETUP
+#line 115 "scanner.l"
+{
+                    char c[2] = { (char)(strtol(yytext + 2, NULL, 16) & 0xFF),
+                                  0 };
+                    scanctx_append_string(yyextra, c);
+                  }
+	YY_BREAK
+case 14:
+YY_RULE_SETUP
+#line 120 "scanner.l"
+{
+                    yylval->sval = scanctx_take_string(yyextra);
+                    BEGIN INITIAL;
+                    return(TOK_STRING);
+                  }
+	YY_BREAK
+case 15:
+YY_RULE_SETUP
+#line 126 "scanner.l"
+{ BEGIN INCLUDE; }
+	YY_BREAK
+case 16:
+/* rule 16 can match eol */
+YY_RULE_SETUP
+#line 127 "scanner.l"
+{ scanctx_append_string(yyextra, yytext); }
+	YY_BREAK
+case 17:
+YY_RULE_SETUP
+#line 128 "scanner.l"
+{ scanctx_append_string(yyextra, "\\"); }
+	YY_BREAK
+case 18:
+YY_RULE_SETUP
+#line 129 "scanner.l"
+{ scanctx_append_string(yyextra, "\""); }
+	YY_BREAK
+case 19:
+YY_RULE_SETUP
+#line 130 "scanner.l"
+{
+                    const char *error;
+                    FILE *fp = scanctx_push_include(yyextra,
+                                                    (void *)YY_CURRENT_BUFFER,
+                                                    &error);
+                    if(fp)
+                    {
+                      yyin = fp;
+                      libconfig_yy_switch_to_buffer(libconfig_yy_create_buffer(yyin,YY_BUF_SIZE,yyscanner),yyscanner);
+                    }
+                    else
+                    {
+                      yyextra->config->error_text = error;
+                      yyextra->config->error_file = scanctx_current_filename(
+                        yyextra);
+                      yyextra->config->error_line = libconfig_yyget_lineno(
+                        yyscanner);
+                      return TOK_ERROR;
+                    }
+                    BEGIN INITIAL;
+                  }
+	YY_BREAK
+case 20:
+/* rule 20 can match eol */
+YY_RULE_SETUP
+#line 154 "scanner.l"
+{ /* ignore */ }
+	YY_BREAK
+case 21:
+YY_RULE_SETUP
+#line 155 "scanner.l"
+{ /* ignore */ }
+	YY_BREAK
+case 22:
+YY_RULE_SETUP
+#line 157 "scanner.l"
+{ return(TOK_EQUALS); }
+	YY_BREAK
+case 23:
+YY_RULE_SETUP
+#line 158 "scanner.l"
+{ return(TOK_COMMA); }
+	YY_BREAK
+case 24:
+YY_RULE_SETUP
+#line 159 "scanner.l"
+{ return(TOK_GROUP_START); }
+	YY_BREAK
+case 25:
+YY_RULE_SETUP
+#line 160 "scanner.l"
+{ return(TOK_GROUP_END); }
+	YY_BREAK
+case 26:
+YY_RULE_SETUP
+#line 161 "scanner.l"
+{ yylval->ival = 1; return(TOK_BOOLEAN); }
+	YY_BREAK
+case 27:
+YY_RULE_SETUP
+#line 162 "scanner.l"
+{ yylval->ival = 0; return(TOK_BOOLEAN); }
+	YY_BREAK
+case 28:
+YY_RULE_SETUP
+#line 163 "scanner.l"
+{ yylval->sval = yytext; return(TOK_NAME); }
+	YY_BREAK
+case 29:
+YY_RULE_SETUP
+#line 164 "scanner.l"
+{ yylval->fval = atof(yytext); return(TOK_FLOAT); }
+	YY_BREAK
+case 30:
+YY_RULE_SETUP
+#line 165 "scanner.l"
+{ yylval->ival = atoi(yytext); return(TOK_INTEGER); }
+	YY_BREAK
+case 31:
+YY_RULE_SETUP
+#line 166 "scanner.l"
+{ yylval->llval = atoll(yytext); return(TOK_INTEGER64); }
+	YY_BREAK
+case 32:
+YY_RULE_SETUP
+#line 167 "scanner.l"
+{
+                    yylval->ival = strtoul(yytext, NULL, 16);
+                    return(TOK_HEX);
+                  }
+	YY_BREAK
+case 33:
+YY_RULE_SETUP
+#line 171 "scanner.l"
+{ yylval->llval = fromhex(yytext); return(TOK_HEX64); }
+	YY_BREAK
+case 34:
+YY_RULE_SETUP
+#line 172 "scanner.l"
+{ return(TOK_ARRAY_START); }
+	YY_BREAK
+case 35:
+YY_RULE_SETUP
+#line 173 "scanner.l"
+{ return(TOK_ARRAY_END); }
+	YY_BREAK
+case 36:
+YY_RULE_SETUP
+#line 174 "scanner.l"
+{ return(TOK_LIST_START); }
+	YY_BREAK
+case 37:
+YY_RULE_SETUP
+#line 175 "scanner.l"
+{ return(TOK_LIST_END); }
+	YY_BREAK
+case 38:
+YY_RULE_SETUP
+#line 176 "scanner.l"
+{ return(TOK_END); }
+	YY_BREAK
+case 39:
+*yy_cp = yyg->yy_hold_char; /* undo effects of setting up yytext */
+yyg->yy_c_buf_p = yy_cp -= 1;
+YY_DO_BEFORE_ACTION; /* set up yytext again */
+YY_RULE_SETUP
+#line 177 "scanner.l"
+{ /* ignore */ }
+	YY_BREAK
+case 40:
+YY_RULE_SETUP
+#line 178 "scanner.l"
+{ return(TOK_GARBAGE); }
+	YY_BREAK
+case YY_STATE_EOF(INITIAL):
+case YY_STATE_EOF(COMMENT):
+case YY_STATE_EOF(STRING):
+case YY_STATE_EOF(INCLUDE):
+#line 180 "scanner.l"
+{
+                    YY_BUFFER_STATE buf = (YY_BUFFER_STATE)scanctx_pop_include(
+                      yyextra);
+                    if(buf)
+                    {
+                      libconfig_yy_delete_buffer(YY_CURRENT_BUFFER,yyscanner);
+                      libconfig_yy_switch_to_buffer(buf,yyscanner);
+                    }
+                    else
+                      yyterminate();
+                  }
+	YY_BREAK
+case 41:
+YY_RULE_SETUP
+#line 191 "scanner.l"
+ECHO;
+	YY_BREAK
+#line 1227 "scanner.c"
+
+	case YY_END_OF_BUFFER:
+		{
+		/* Amount of text matched not including the EOB char. */
+		int yy_amount_of_matched_text = (int) (yy_cp - yyg->yytext_ptr) - 1;
+
+		/* Undo the effects of YY_DO_BEFORE_ACTION. */
+		*yy_cp = yyg->yy_hold_char;
+		YY_RESTORE_YY_MORE_OFFSET
+
+		if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_NEW )
+			{
+			/* We're scanning a new file or input source.  It's
+			 * possible that this happened because the user
+			 * just pointed yyin at a new source and called
+			 * libconfig_yylex().  If so, then we have to assure
+			 * consistency between YY_CURRENT_BUFFER and our
+			 * globals.  Here is the right place to do so, because
+			 * this is the first action (other than possibly a
+			 * back-up) that will match for the new input source.
+			 */
+			yyg->yy_n_chars = YY_CURRENT_BUFFER_LVALUE->yy_n_chars;
+			YY_CURRENT_BUFFER_LVALUE->yy_input_file = yyin;
+			YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = YY_BUFFER_NORMAL;
+			}
+
+		/* Note that here we test for yy_c_buf_p "<=" to the position
+		 * of the first EOB in the buffer, since yy_c_buf_p will
+		 * already have been incremented past the NUL character
+		 * (since all states make transitions on EOB to the
+		 * end-of-buffer state).  Contrast this with the test
+		 * in input().
+		 */
+		if ( yyg->yy_c_buf_p <= &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars] )
+			{ /* This was really a NUL. */
+			yy_state_type yy_next_state;
+
+			yyg->yy_c_buf_p = yyg->yytext_ptr + yy_amount_of_matched_text;
+
+			yy_current_state = yy_get_previous_state( yyscanner );
+
+			/* Okay, we're now positioned to make the NUL
+			 * transition.  We couldn't have
+			 * yy_get_previous_state() go ahead and do it
+			 * for us because it doesn't know how to deal
+			 * with the possibility of jamming (and we don't
+			 * want to build jamming into it because then it
+			 * will run more slowly).
+			 */
+
+			yy_next_state = yy_try_NUL_trans( yy_current_state , yyscanner);
+
+			yy_bp = yyg->yytext_ptr + YY_MORE_ADJ;
+
+			if ( yy_next_state )
+				{
+				/* Consume the NUL. */
+				yy_cp = ++yyg->yy_c_buf_p;
+				yy_current_state = yy_next_state;
+				goto yy_match;
+				}
+
+			else
+				{
+				yy_cp = yyg->yy_c_buf_p;
+				goto yy_find_action;
+				}
+			}
+
+		else switch ( yy_get_next_buffer( yyscanner ) )
+			{
+			case EOB_ACT_END_OF_FILE:
+				{
+				yyg->yy_did_buffer_switch_on_eof = 0;
+
+				if ( libconfig_yywrap(yyscanner ) )
+					{
+					/* Note: because we've taken care in
+					 * yy_get_next_buffer() to have set up
+					 * yytext, we can now set up
+					 * yy_c_buf_p so that if some total
+					 * hoser (like flex itself) wants to
+					 * call the scanner after we return the
+					 * YY_NULL, it'll still work - another
+					 * YY_NULL will get returned.
+					 */
+					yyg->yy_c_buf_p = yyg->yytext_ptr + YY_MORE_ADJ;
+
+					yy_act = YY_STATE_EOF(YY_START);
+					goto do_action;
+					}
+
+				else
+					{
+					if ( ! yyg->yy_did_buffer_switch_on_eof )
+						YY_NEW_FILE;
+					}
+				break;
+				}
+
+			case EOB_ACT_CONTINUE_SCAN:
+				yyg->yy_c_buf_p =
+					yyg->yytext_ptr + yy_amount_of_matched_text;
+
+				yy_current_state = yy_get_previous_state( yyscanner );
+
+				yy_cp = yyg->yy_c_buf_p;
+				yy_bp = yyg->yytext_ptr + YY_MORE_ADJ;
+				goto yy_match;
+
+			case EOB_ACT_LAST_MATCH:
+				yyg->yy_c_buf_p =
+				&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars];
+
+				yy_current_state = yy_get_previous_state( yyscanner );
+
+				yy_cp = yyg->yy_c_buf_p;
+				yy_bp = yyg->yytext_ptr + YY_MORE_ADJ;
+				goto yy_find_action;
+			}
+		break;
+		}
+
+	default:
+		YY_FATAL_ERROR(
+			"fatal flex scanner internal error--no action found" );
+	} /* end of action switch */
+		} /* end of scanning one token */
+} /* end of libconfig_yylex */
+
+/* yy_get_next_buffer - try to read in a new buffer
+ *
+ * Returns a code representing an action:
+ *	EOB_ACT_LAST_MATCH -
+ *	EOB_ACT_CONTINUE_SCAN - continue scanning from current position
+ *	EOB_ACT_END_OF_FILE - end of file
+ */
+static int yy_get_next_buffer (yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+	register char *dest = YY_CURRENT_BUFFER_LVALUE->yy_ch_buf;
+	register char *source = yyg->yytext_ptr;
+	register int number_to_move, i;
+	int ret_val;
+
+	if ( yyg->yy_c_buf_p > &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars + 1] )
+		YY_FATAL_ERROR(
+		"fatal flex scanner internal error--end of buffer missed" );
+
+	if ( YY_CURRENT_BUFFER_LVALUE->yy_fill_buffer == 0 )
+		{ /* Don't try to fill the buffer, so this is an EOF. */
+		if ( yyg->yy_c_buf_p - yyg->yytext_ptr - YY_MORE_ADJ == 1 )
+			{
+			/* We matched a single character, the EOB, so
+			 * treat this as a final EOF.
+			 */
+			return EOB_ACT_END_OF_FILE;
+			}
+
+		else
+			{
+			/* We matched some text prior to the EOB, first
+			 * process it.
+			 */
+			return EOB_ACT_LAST_MATCH;
+			}
+		}
+
+	/* Try to read more data. */
+
+	/* First move last chars to start of buffer. */
+	number_to_move = (int) (yyg->yy_c_buf_p - yyg->yytext_ptr) - 1;
+
+	for ( i = 0; i < number_to_move; ++i )
+		*(dest++) = *(source++);
+
+	if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_EOF_PENDING )
+		/* don't do the read, it's not guaranteed to return an EOF,
+		 * just force an EOF
+		 */
+		YY_CURRENT_BUFFER_LVALUE->yy_n_chars = yyg->yy_n_chars = 0;
+
+	else
+		{
+			int num_to_read =
+			YY_CURRENT_BUFFER_LVALUE->yy_buf_size - number_to_move - 1;
+
+		while ( num_to_read <= 0 )
+			{ /* Not enough room in the buffer - grow it. */
+
+			/* just a shorter name for the current buffer */
+			YY_BUFFER_STATE b = YY_CURRENT_BUFFER;
+
+			int yy_c_buf_p_offset =
+				(int) (yyg->yy_c_buf_p - b->yy_ch_buf);
+
+			if ( b->yy_is_our_buffer )
+				{
+				int new_size = b->yy_buf_size * 2;
+
+				if ( new_size <= 0 )
+					b->yy_buf_size += b->yy_buf_size / 8;
+				else
+					b->yy_buf_size *= 2;
+
+				b->yy_ch_buf = (char *)
+					/* Include room in for 2 EOB chars. */
+					libconfig_yyrealloc((void *) b->yy_ch_buf,b->yy_buf_size + 2 ,yyscanner );
+				}
+			else
+				/* Can't grow it, we don't own it. */
+				b->yy_ch_buf = 0;
+
+			if ( ! b->yy_ch_buf )
+				YY_FATAL_ERROR(
+				"fatal error - scanner input buffer overflow" );
+
+			yyg->yy_c_buf_p = &b->yy_ch_buf[yy_c_buf_p_offset];
+
+			num_to_read = YY_CURRENT_BUFFER_LVALUE->yy_buf_size -
+						number_to_move - 1;
+
+			}
+
+		if ( num_to_read > YY_READ_BUF_SIZE )
+			num_to_read = YY_READ_BUF_SIZE;
+
+		/* Read in more data. */
+		YY_INPUT( (&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]),
+			yyg->yy_n_chars, (size_t) num_to_read );
+
+		YY_CURRENT_BUFFER_LVALUE->yy_n_chars = yyg->yy_n_chars;
+		}
+
+	if ( yyg->yy_n_chars == 0 )
+		{
+		if ( number_to_move == YY_MORE_ADJ )
+			{
+			ret_val = EOB_ACT_END_OF_FILE;
+			libconfig_yyrestart(yyin  ,yyscanner);
+			}
+
+		else
+			{
+			ret_val = EOB_ACT_LAST_MATCH;
+			YY_CURRENT_BUFFER_LVALUE->yy_buffer_status =
+				YY_BUFFER_EOF_PENDING;
+			}
+		}
+
+	else
+		ret_val = EOB_ACT_CONTINUE_SCAN;
+
+	if ((yy_size_t) (yyg->yy_n_chars + number_to_move) > YY_CURRENT_BUFFER_LVALUE->yy_buf_size) {
+		/* Extend the array by 50%, plus the number we really need. */
+		yy_size_t new_size = yyg->yy_n_chars + number_to_move + (yyg->yy_n_chars >> 1);
+		YY_CURRENT_BUFFER_LVALUE->yy_ch_buf = (char *) libconfig_yyrealloc((void *) YY_CURRENT_BUFFER_LVALUE->yy_ch_buf,new_size ,yyscanner );
+		if ( ! YY_CURRENT_BUFFER_LVALUE->yy_ch_buf )
+			YY_FATAL_ERROR( "out of dynamic memory in yy_get_next_buffer()" );
+	}
+
+	yyg->yy_n_chars += number_to_move;
+	YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars] = YY_END_OF_BUFFER_CHAR;
+	YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars + 1] = YY_END_OF_BUFFER_CHAR;
+
+	yyg->yytext_ptr = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[0];
+
+	return ret_val;
+}
+
+/* yy_get_previous_state - get the state just before the EOB char was reached */
+
+    static yy_state_type yy_get_previous_state (yyscan_t yyscanner)
+{
+	register yy_state_type yy_current_state;
+	register char *yy_cp;
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
+	yy_current_state = yyg->yy_start;
+	yy_current_state += YY_AT_BOL();
+
+	for ( yy_cp = yyg->yytext_ptr + YY_MORE_ADJ; yy_cp < yyg->yy_c_buf_p; ++yy_cp )
+		{
+		register YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1);
+		if ( yy_accept[yy_current_state] )
+			{
+			yyg->yy_last_accepting_state = yy_current_state;
+			yyg->yy_last_accepting_cpos = yy_cp;
+			}
+		while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
+			{
+			yy_current_state = (int) yy_def[yy_current_state];
+			if ( yy_current_state >= 103 )
+				yy_c = yy_meta[(unsigned int) yy_c];
+			}
+		yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
+		}
+
+	return yy_current_state;
+}
+
+/* yy_try_NUL_trans - try to make a transition on the NUL character
+ *
+ * synopsis
+ *	next_state = yy_try_NUL_trans( current_state );
+ */
+    static yy_state_type yy_try_NUL_trans  (yy_state_type yy_current_state , yyscan_t yyscanner)
+{
+	register int yy_is_jam;
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; /* This var may be unused depending upon options. */
+	register char *yy_cp = yyg->yy_c_buf_p;
+
+	register YY_CHAR yy_c = 1;
+	if ( yy_accept[yy_current_state] )
+		{
+		yyg->yy_last_accepting_state = yy_current_state;
+		yyg->yy_last_accepting_cpos = yy_cp;
+		}
+	while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
+		{
+		yy_current_state = (int) yy_def[yy_current_state];
+		if ( yy_current_state >= 103 )
+			yy_c = yy_meta[(unsigned int) yy_c];
+		}
+	yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
+	yy_is_jam = (yy_current_state == 102);
+
+	return yy_is_jam ? 0 : yy_current_state;
+}
+
+#ifndef YY_NO_INPUT
+#ifdef __cplusplus
+    static int yyinput (yyscan_t yyscanner)
+#else
+    static int input  (yyscan_t yyscanner)
+#endif
+
+{
+	int c;
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
+	*yyg->yy_c_buf_p = yyg->yy_hold_char;
+
+	if ( *yyg->yy_c_buf_p == YY_END_OF_BUFFER_CHAR )
+		{
+		/* yy_c_buf_p now points to the character we want to return.
+		 * If this occurs *before* the EOB characters, then it's a
+		 * valid NUL; if not, then we've hit the end of the buffer.
+		 */
+		if ( yyg->yy_c_buf_p < &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars] )
+			/* This was really a NUL. */
+			*yyg->yy_c_buf_p = '\0';
+
+		else
+			{ /* need more input */
+			int offset = yyg->yy_c_buf_p - yyg->yytext_ptr;
+			++yyg->yy_c_buf_p;
+
+			switch ( yy_get_next_buffer( yyscanner ) )
+				{
+				case EOB_ACT_LAST_MATCH:
+					/* This happens because yy_g_n_b()
+					 * sees that we've accumulated a
+					 * token and flags that we need to
+					 * try matching the token before
+					 * proceeding.  But for input(),
+					 * there's no matching to consider.
+					 * So convert the EOB_ACT_LAST_MATCH
+					 * to EOB_ACT_END_OF_FILE.
+					 */
+
+					/* Reset buffer status. */
+					libconfig_yyrestart(yyin ,yyscanner);
+
+					/*FALLTHROUGH*/
+
+				case EOB_ACT_END_OF_FILE:
+					{
+					if ( libconfig_yywrap(yyscanner ) )
+						return EOF;
+
+					if ( ! yyg->yy_did_buffer_switch_on_eof )
+						YY_NEW_FILE;
+#ifdef __cplusplus
+					return yyinput(yyscanner);
+#else
+					return input(yyscanner);
+#endif
+					}
+
+				case EOB_ACT_CONTINUE_SCAN:
+					yyg->yy_c_buf_p = yyg->yytext_ptr + offset;
+					break;
+				}
+			}
+		}
+
+	c = *(unsigned char *) yyg->yy_c_buf_p;	/* cast for 8-bit char's */
+	*yyg->yy_c_buf_p = '\0';	/* preserve yytext */
+	yyg->yy_hold_char = *++yyg->yy_c_buf_p;
+
+	YY_CURRENT_BUFFER_LVALUE->yy_at_bol = (c == '\n');
+	if ( YY_CURRENT_BUFFER_LVALUE->yy_at_bol )
+		   
+    do{ yylineno++;
+        yycolumn=0;
+    }while(0)
+;
+
+	return c;
+}
+#endif	/* ifndef YY_NO_INPUT */
+
+/** Immediately switch to a different input stream.
+ * @param input_file A readable stream.
+ * @param yyscanner The scanner object.
+ * @note This function does not reset the start condition to @c INITIAL .
+ */
+    void libconfig_yyrestart  (FILE * input_file , yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
+	if ( ! YY_CURRENT_BUFFER ){
+        libconfig_yyensure_buffer_stack (yyscanner);
+		YY_CURRENT_BUFFER_LVALUE =
+            libconfig_yy_create_buffer(yyin,YY_BUF_SIZE ,yyscanner);
+	}
+
+	libconfig_yy_init_buffer(YY_CURRENT_BUFFER,input_file ,yyscanner);
+	libconfig_yy_load_buffer_state(yyscanner );
+}
+
+/** Switch to a different input buffer.
+ * @param new_buffer The new input buffer.
+ * @param yyscanner The scanner object.
+ */
+    void libconfig_yy_switch_to_buffer  (YY_BUFFER_STATE  new_buffer , yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
+	/* TODO. We should be able to replace this entire function body
+	 * with
+	 *		libconfig_yypop_buffer_state();
+	 *		libconfig_yypush_buffer_state(new_buffer);
+     */
+	libconfig_yyensure_buffer_stack (yyscanner);
+	if ( YY_CURRENT_BUFFER == new_buffer )
+		return;
+
+	if ( YY_CURRENT_BUFFER )
+		{
+		/* Flush out information for old buffer. */
+		*yyg->yy_c_buf_p = yyg->yy_hold_char;
+		YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = yyg->yy_c_buf_p;
+		YY_CURRENT_BUFFER_LVALUE->yy_n_chars = yyg->yy_n_chars;
+		}
+
+	YY_CURRENT_BUFFER_LVALUE = new_buffer;
+	libconfig_yy_load_buffer_state(yyscanner );
+
+	/* We don't actually know whether we did this switch during
+	 * EOF (libconfig_yywrap()) processing, but the only time this flag
+	 * is looked at is after libconfig_yywrap() is called, so it's safe
+	 * to go ahead and always set it.
+	 */
+	yyg->yy_did_buffer_switch_on_eof = 1;
+}
+
+static void libconfig_yy_load_buffer_state  (yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+	yyg->yy_n_chars = YY_CURRENT_BUFFER_LVALUE->yy_n_chars;
+	yyg->yytext_ptr = yyg->yy_c_buf_p = YY_CURRENT_BUFFER_LVALUE->yy_buf_pos;
+	yyin = YY_CURRENT_BUFFER_LVALUE->yy_input_file;
+	yyg->yy_hold_char = *yyg->yy_c_buf_p;
+}
+
+/** Allocate and initialize an input buffer state.
+ * @param file A readable stream.
+ * @param size The character buffer size in bytes. When in doubt, use @c YY_BUF_SIZE.
+ * @param yyscanner The scanner object.
+ * @return the allocated buffer state.
+ */
+    YY_BUFFER_STATE libconfig_yy_create_buffer  (FILE * file, int  size , yyscan_t yyscanner)
+{
+	YY_BUFFER_STATE b;
+    
+	b = (YY_BUFFER_STATE) libconfig_yyalloc(sizeof( struct yy_buffer_state ) ,yyscanner );
+	if ( ! b )
+		YY_FATAL_ERROR( "out of dynamic memory in libconfig_yy_create_buffer()" );
+
+	b->yy_buf_size = size;
+
+	/* yy_ch_buf has to be 2 characters longer than the size given because
+	 * we need to put in 2 end-of-buffer characters.
+	 */
+	b->yy_ch_buf = (char *) libconfig_yyalloc(b->yy_buf_size + 2 ,yyscanner );
+	if ( ! b->yy_ch_buf )
+		YY_FATAL_ERROR( "out of dynamic memory in libconfig_yy_create_buffer()" );
+
+	b->yy_is_our_buffer = 1;
+
+	libconfig_yy_init_buffer(b,file ,yyscanner);
+
+	return b;
+}
+
+/** Destroy the buffer.
+ * @param b a buffer created with libconfig_yy_create_buffer()
+ * @param yyscanner The scanner object.
+ */
+    void libconfig_yy_delete_buffer (YY_BUFFER_STATE  b , yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
+	if ( ! b )
+		return;
+
+	if ( b == YY_CURRENT_BUFFER ) /* Not sure if we should pop here. */
+		YY_CURRENT_BUFFER_LVALUE = (YY_BUFFER_STATE) 0;
+
+	if ( b->yy_is_our_buffer )
+		libconfig_yyfree((void *) b->yy_ch_buf ,yyscanner );
+
+	libconfig_yyfree((void *) b ,yyscanner );
+}
+
+#ifndef __cplusplus
+extern int isatty (int );
+#endif /* __cplusplus */
+    
+/* Initializes or reinitializes a buffer.
+ * This function is sometimes called more than once on the same buffer,
+ * such as during a libconfig_yyrestart() or at EOF.
+ */
+    static void libconfig_yy_init_buffer  (YY_BUFFER_STATE  b, FILE * file , yyscan_t yyscanner)
+
+{
+	int oerrno = errno;
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
+	libconfig_yy_flush_buffer(b ,yyscanner);
+
+	b->yy_input_file = file;
+	b->yy_fill_buffer = 1;
+
+    /* If b is the current buffer, then libconfig_yy_init_buffer was _probably_
+     * called from libconfig_yyrestart() or through yy_get_next_buffer.
+     * In that case, we don't want to reset the lineno or column.
+     */
+    if (b != YY_CURRENT_BUFFER){
+        b->yy_bs_lineno = 1;
+        b->yy_bs_column = 0;
+    }
+
+        b->yy_is_interactive = file ? (isatty( fileno(file) ) > 0) : 0;
+    
+	errno = oerrno;
+}
+
+/** Discard all buffered characters. On the next scan, YY_INPUT will be called.
+ * @param b the buffer state to be flushed, usually @c YY_CURRENT_BUFFER.
+ * @param yyscanner The scanner object.
+ */
+    void libconfig_yy_flush_buffer (YY_BUFFER_STATE  b , yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+	if ( ! b )
+		return;
+
+	b->yy_n_chars = 0;
+
+	/* We always need two end-of-buffer characters.  The first causes
+	 * a transition to the end-of-buffer state.  The second causes
+	 * a jam in that state.
+	 */
+	b->yy_ch_buf[0] = YY_END_OF_BUFFER_CHAR;
+	b->yy_ch_buf[1] = YY_END_OF_BUFFER_CHAR;
+
+	b->yy_buf_pos = &b->yy_ch_buf[0];
+
+	b->yy_at_bol = 1;
+	b->yy_buffer_status = YY_BUFFER_NEW;
+
+	if ( b == YY_CURRENT_BUFFER )
+		libconfig_yy_load_buffer_state(yyscanner );
+}
+
+/** Pushes the new state onto the stack. The new state becomes
+ *  the current state. This function will allocate the stack
+ *  if necessary.
+ *  @param new_buffer The new state.
+ *  @param yyscanner The scanner object.
+ */
+void libconfig_yypush_buffer_state (YY_BUFFER_STATE new_buffer , yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+	if (new_buffer == NULL)
+		return;
+
+	libconfig_yyensure_buffer_stack(yyscanner);
+
+	/* This block is copied from libconfig_yy_switch_to_buffer. */
+	if ( YY_CURRENT_BUFFER )
+		{
+		/* Flush out information for old buffer. */
+		*yyg->yy_c_buf_p = yyg->yy_hold_char;
+		YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = yyg->yy_c_buf_p;
+		YY_CURRENT_BUFFER_LVALUE->yy_n_chars = yyg->yy_n_chars;
+		}
+
+	/* Only push if top exists. Otherwise, replace top. */
+	if (YY_CURRENT_BUFFER)
+		yyg->yy_buffer_stack_top++;
+	YY_CURRENT_BUFFER_LVALUE = new_buffer;
+
+	/* copied from libconfig_yy_switch_to_buffer. */
+	libconfig_yy_load_buffer_state(yyscanner );
+	yyg->yy_did_buffer_switch_on_eof = 1;
+}
+
+/** Removes and deletes the top of the stack, if present.
+ *  The next element becomes the new top.
+ *  @param yyscanner The scanner object.
+ */
+void libconfig_yypop_buffer_state (yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+	if (!YY_CURRENT_BUFFER)
+		return;
+
+	libconfig_yy_delete_buffer(YY_CURRENT_BUFFER ,yyscanner);
+	YY_CURRENT_BUFFER_LVALUE = NULL;
+	if (yyg->yy_buffer_stack_top > 0)
+		--yyg->yy_buffer_stack_top;
+
+	if (YY_CURRENT_BUFFER) {
+		libconfig_yy_load_buffer_state(yyscanner );
+		yyg->yy_did_buffer_switch_on_eof = 1;
+	}
+}
+
+/* Allocates the stack if it does not exist.
+ *  Guarantees space for at least one push.
+ */
+static void libconfig_yyensure_buffer_stack (yyscan_t yyscanner)
+{
+	int num_to_alloc;
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
+	if (!yyg->yy_buffer_stack) {
+
+		/* First allocation is just for 2 elements, since we don't know if this
+		 * scanner will even need a stack. We use 2 instead of 1 to avoid an
+		 * immediate realloc on the next call.
+         */
+		num_to_alloc = 1;
+		yyg->yy_buffer_stack = (struct yy_buffer_state**)libconfig_yyalloc
+								(num_to_alloc * sizeof(struct yy_buffer_state*)
+								, yyscanner);
+		if ( ! yyg->yy_buffer_stack )
+			YY_FATAL_ERROR( "out of dynamic memory in libconfig_yyensure_buffer_stack()" );
+								  
+		memset(yyg->yy_buffer_stack, 0, num_to_alloc * sizeof(struct yy_buffer_state*));
+				
+		yyg->yy_buffer_stack_max = num_to_alloc;
+		yyg->yy_buffer_stack_top = 0;
+		return;
+	}
+
+	if (yyg->yy_buffer_stack_top >= (yyg->yy_buffer_stack_max) - 1){
+
+		/* Increase the buffer to prepare for a possible push. */
+		int grow_size = 8 /* arbitrary grow size */;
+
+		num_to_alloc = yyg->yy_buffer_stack_max + grow_size;
+		yyg->yy_buffer_stack = (struct yy_buffer_state**)libconfig_yyrealloc
+								(yyg->yy_buffer_stack,
+								num_to_alloc * sizeof(struct yy_buffer_state*)
+								, yyscanner);
+		if ( ! yyg->yy_buffer_stack )
+			YY_FATAL_ERROR( "out of dynamic memory in libconfig_yyensure_buffer_stack()" );
+
+		/* zero only the new slots.*/
+		memset(yyg->yy_buffer_stack + yyg->yy_buffer_stack_max, 0, grow_size * sizeof(struct yy_buffer_state*));
+		yyg->yy_buffer_stack_max = num_to_alloc;
+	}
+}
+
+/** Setup the input buffer state to scan directly from a user-specified character buffer.
+ * @param base the character buffer
+ * @param size the size in bytes of the character buffer
+ * @param yyscanner The scanner object.
+ * @return the newly allocated buffer state object. 
+ */
+YY_BUFFER_STATE libconfig_yy_scan_buffer  (char * base, yy_size_t  size , yyscan_t yyscanner)
+{
+	YY_BUFFER_STATE b;
+    
+	if ( size < 2 ||
+	     base[size-2] != YY_END_OF_BUFFER_CHAR ||
+	     base[size-1] != YY_END_OF_BUFFER_CHAR )
+		/* They forgot to leave room for the EOB's. */
+		return 0;
+
+	b = (YY_BUFFER_STATE) libconfig_yyalloc(sizeof( struct yy_buffer_state ) ,yyscanner );
+	if ( ! b )
+		YY_FATAL_ERROR( "out of dynamic memory in libconfig_yy_scan_buffer()" );
+
+	b->yy_buf_size = size - 2;	/* "- 2" to take care of EOB's */
+	b->yy_buf_pos = b->yy_ch_buf = base;
+	b->yy_is_our_buffer = 0;
+	b->yy_input_file = 0;
+	b->yy_n_chars = b->yy_buf_size;
+	b->yy_is_interactive = 0;
+	b->yy_at_bol = 1;
+	b->yy_fill_buffer = 0;
+	b->yy_buffer_status = YY_BUFFER_NEW;
+
+	libconfig_yy_switch_to_buffer(b ,yyscanner );
+
+	return b;
+}
+
+/** Setup the input buffer state to scan a string. The next call to libconfig_yylex() will
+ * scan from a @e copy of @a str.
+ * @param yystr a NUL-terminated string to scan
+ * @param yyscanner The scanner object.
+ * @return the newly allocated buffer state object.
+ * @note If you want to scan bytes that may contain NUL values, then use
+ *       libconfig_yy_scan_bytes() instead.
+ */
+YY_BUFFER_STATE libconfig_yy_scan_string (yyconst char * yystr , yyscan_t yyscanner)
+{
+    
+	return libconfig_yy_scan_bytes(yystr,strlen(yystr) ,yyscanner);
+}
+
+/** Setup the input buffer state to scan the given bytes. The next call to libconfig_yylex() will
+ * scan from a @e copy of @a bytes.
+ * @param yybytes the byte buffer to scan
+ * @param _yybytes_len the number of bytes in the buffer pointed to by @a bytes.
+ * @param yyscanner The scanner object.
+ * @return the newly allocated buffer state object.
+ */
+YY_BUFFER_STATE libconfig_yy_scan_bytes  (yyconst char * yybytes, int  _yybytes_len , yyscan_t yyscanner)
+{
+	YY_BUFFER_STATE b;
+	char *buf;
+	yy_size_t n;
+	int i;
+    
+	/* Get memory for full buffer, including space for trailing EOB's. */
+	n = _yybytes_len + 2;
+	buf = (char *) libconfig_yyalloc(n ,yyscanner );
+	if ( ! buf )
+		YY_FATAL_ERROR( "out of dynamic memory in libconfig_yy_scan_bytes()" );
+
+	for ( i = 0; i < _yybytes_len; ++i )
+		buf[i] = yybytes[i];
+
+	buf[_yybytes_len] = buf[_yybytes_len+1] = YY_END_OF_BUFFER_CHAR;
+
+	b = libconfig_yy_scan_buffer(buf,n ,yyscanner);
+	if ( ! b )
+		YY_FATAL_ERROR( "bad buffer in libconfig_yy_scan_bytes()" );
+
+	/* It's okay to grow etc. this buffer, and we should throw it
+	 * away when we're done.
+	 */
+	b->yy_is_our_buffer = 1;
+
+	return b;
+}
+
+#ifndef YY_EXIT_FAILURE
+#define YY_EXIT_FAILURE 2
+#endif
+
+static void yy_fatal_error (yyconst char* msg , yyscan_t yyscanner)
+{
+    	(void) fprintf( stderr, "%s\n", msg );
+	exit( YY_EXIT_FAILURE );
+}
+
+/* Redefine yyless() so it works in section 3 code. */
+
+#undef yyless
+#define yyless(n) \
+	do \
+		{ \
+		/* Undo effects of setting up yytext. */ \
+        int yyless_macro_arg = (n); \
+        YY_LESS_LINENO(yyless_macro_arg);\
+		yytext[yyleng] = yyg->yy_hold_char; \
+		yyg->yy_c_buf_p = yytext + yyless_macro_arg; \
+		yyg->yy_hold_char = *yyg->yy_c_buf_p; \
+		*yyg->yy_c_buf_p = '\0'; \
+		yyleng = yyless_macro_arg; \
+		} \
+	while ( 0 )
+
+/* Accessor  methods (get/set functions) to struct members. */
+
+/** Get the user-defined data for this scanner.
+ * @param yyscanner The scanner object.
+ */
+YY_EXTRA_TYPE libconfig_yyget_extra  (yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+    return yyextra;
+}
+
+/** Get the current line number.
+ * @param yyscanner The scanner object.
+ */
+int libconfig_yyget_lineno  (yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+    
+        if (! YY_CURRENT_BUFFER)
+            return 0;
+    
+    return yylineno;
+}
+
+/** Get the current column number.
+ * @param yyscanner The scanner object.
+ */
+int libconfig_yyget_column  (yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+    
+        if (! YY_CURRENT_BUFFER)
+            return 0;
+    
+    return yycolumn;
+}
+
+/** Get the input stream.
+ * @param yyscanner The scanner object.
+ */
+FILE *libconfig_yyget_in  (yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+    return yyin;
+}
+
+/** Get the output stream.
+ * @param yyscanner The scanner object.
+ */
+FILE *libconfig_yyget_out  (yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+    return yyout;
+}
+
+/** Get the length of the current token.
+ * @param yyscanner The scanner object.
+ */
+int libconfig_yyget_leng  (yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+    return yyleng;
+}
+
+/** Get the current token.
+ * @param yyscanner The scanner object.
+ */
+
+char *libconfig_yyget_text  (yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+    return yytext;
+}
+
+/** Set the user-defined data. This data is never touched by the scanner.
+ * @param user_defined The data to be associated with this scanner.
+ * @param yyscanner The scanner object.
+ */
+void libconfig_yyset_extra (YY_EXTRA_TYPE  user_defined , yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+    yyextra = user_defined ;
+}
+
+/** Set the current line number.
+ * @param line_number
+ * @param yyscanner The scanner object.
+ */
+void libconfig_yyset_lineno (int  line_number , yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
+        /* lineno is only valid if an input buffer exists. */
+        if (! YY_CURRENT_BUFFER )
+           yy_fatal_error( "libconfig_yyset_lineno called with no buffer" , yyscanner); 
+    
+    yylineno = line_number;
+}
+
+/** Set the current column.
+ * @param line_number
+ * @param yyscanner The scanner object.
+ */
+void libconfig_yyset_column (int  column_no , yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
+        /* column is only valid if an input buffer exists. */
+        if (! YY_CURRENT_BUFFER )
+           yy_fatal_error( "libconfig_yyset_column called with no buffer" , yyscanner); 
+    
+    yycolumn = column_no;
+}
+
+/** Set the input stream. This does not discard the current
+ * input buffer.
+ * @param in_str A readable stream.
+ * @param yyscanner The scanner object.
+ * @see libconfig_yy_switch_to_buffer
+ */
+void libconfig_yyset_in (FILE *  in_str , yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+    yyin = in_str ;
+}
+
+void libconfig_yyset_out (FILE *  out_str , yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+    yyout = out_str ;
+}
+
+int libconfig_yyget_debug  (yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+    return yy_flex_debug;
+}
+
+void libconfig_yyset_debug (int  bdebug , yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+    yy_flex_debug = bdebug ;
+}
+
+/* Accessor methods for yylval and yylloc */
+
+YYSTYPE * libconfig_yyget_lval  (yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+    return yylval;
+}
+
+void libconfig_yyset_lval (YYSTYPE *  yylval_param , yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+    yylval = yylval_param;
+}
+
+/* User-visible API */
+
+/* libconfig_yylex_init is special because it creates the scanner itself, so it is
+ * the ONLY reentrant function that doesn't take the scanner as the last argument.
+ * That's why we explicitly handle the declaration, instead of using our macros.
+ */
+
+int libconfig_yylex_init(yyscan_t* ptr_yy_globals)
+
+{
+    if (ptr_yy_globals == NULL){
+        errno = EINVAL;
+        return 1;
+    }
+
+    *ptr_yy_globals = (yyscan_t) libconfig_yyalloc ( sizeof( struct yyguts_t ), NULL );
+
+    if (*ptr_yy_globals == NULL){
+        errno = ENOMEM;
+        return 1;
+    }
+
+    /* By setting to 0xAA, we expose bugs in yy_init_globals. Leave at 0x00 for releases. */
+    memset(*ptr_yy_globals,0x00,sizeof(struct yyguts_t));
+
+    return yy_init_globals ( *ptr_yy_globals );
+}
+
+/* libconfig_yylex_init_extra has the same functionality as libconfig_yylex_init, but follows the
+ * convention of taking the scanner as the last argument. Note however, that
+ * this is a *pointer* to a scanner, as it will be allocated by this call (and
+ * is the reason, too, why this function also must handle its own declaration).
+ * The user defined value in the first argument will be available to libconfig_yyalloc in
+ * the yyextra field.
+ */
+
+int libconfig_yylex_init_extra(YY_EXTRA_TYPE yy_user_defined,yyscan_t* ptr_yy_globals )
+
+{
+    struct yyguts_t dummy_yyguts;
+
+    libconfig_yyset_extra (yy_user_defined, &dummy_yyguts);
+
+    if (ptr_yy_globals == NULL){
+        errno = EINVAL;
+        return 1;
+    }
+	
+    *ptr_yy_globals = (yyscan_t) libconfig_yyalloc ( sizeof( struct yyguts_t ), &dummy_yyguts );
+	
+    if (*ptr_yy_globals == NULL){
+        errno = ENOMEM;
+        return 1;
+    }
+    
+    /* By setting to 0xAA, we expose bugs in
+    yy_init_globals. Leave at 0x00 for releases. */
+    memset(*ptr_yy_globals,0x00,sizeof(struct yyguts_t));
+    
+    libconfig_yyset_extra (yy_user_defined, *ptr_yy_globals);
+    
+    return yy_init_globals ( *ptr_yy_globals );
+}
+
+static int yy_init_globals (yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+    /* Initialization is the same as for the non-reentrant scanner.
+     * This function is called from libconfig_yylex_destroy(), so don't allocate here.
+     */
+
+    yyg->yy_buffer_stack = 0;
+    yyg->yy_buffer_stack_top = 0;
+    yyg->yy_buffer_stack_max = 0;
+    yyg->yy_c_buf_p = (char *) 0;
+    yyg->yy_init = 0;
+    yyg->yy_start = 0;
+
+    yyg->yy_start_stack_ptr = 0;
+    yyg->yy_start_stack_depth = 0;
+    yyg->yy_start_stack =  NULL;
+
+/* Defined in main.c */
+#ifdef YY_STDINIT
+    yyin = stdin;
+    yyout = stdout;
+#else
+    yyin = (FILE *) 0;
+    yyout = (FILE *) 0;
+#endif
+
+    /* For future reference: Set errno on error, since we are called by
+     * libconfig_yylex_init()
+     */
+    return 0;
+}
+
+/* libconfig_yylex_destroy is for both reentrant and non-reentrant scanners. */
+int libconfig_yylex_destroy  (yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
+    /* Pop the buffer stack, destroying each element. */
+	while(YY_CURRENT_BUFFER){
+		libconfig_yy_delete_buffer(YY_CURRENT_BUFFER ,yyscanner );
+		YY_CURRENT_BUFFER_LVALUE = NULL;
+		libconfig_yypop_buffer_state(yyscanner);
+	}
+
+	/* Destroy the stack itself. */
+	libconfig_yyfree(yyg->yy_buffer_stack ,yyscanner);
+	yyg->yy_buffer_stack = NULL;
+
+    /* Destroy the start condition stack. */
+        libconfig_yyfree(yyg->yy_start_stack ,yyscanner );
+        yyg->yy_start_stack = NULL;
+
+    /* Reset the globals. This is important in a non-reentrant scanner so the next time
+     * libconfig_yylex() is called, initialization will occur. */
+    yy_init_globals( yyscanner);
+
+    /* Destroy the main struct (reentrant only). */
+    libconfig_yyfree ( yyscanner , yyscanner );
+    yyscanner = NULL;
+    return 0;
+}
+
+/*
+ * Internal utility routines.
+ */
+
+#ifndef yytext_ptr
+static void yy_flex_strncpy (char* s1, yyconst char * s2, int n , yyscan_t yyscanner)
+{
+	register int i;
+	for ( i = 0; i < n; ++i )
+		s1[i] = s2[i];
+}
+#endif
+
+#ifdef YY_NEED_STRLEN
+static int yy_flex_strlen (yyconst char * s , yyscan_t yyscanner)
+{
+	register int n;
+	for ( n = 0; s[n]; ++n )
+		;
+
+	return n;
+}
+#endif
+
+void *libconfig_yyalloc (yy_size_t  size , yyscan_t yyscanner)
+{
+	return (void *) malloc( size );
+}
+
+void *libconfig_yyrealloc  (void * ptr, yy_size_t  size , yyscan_t yyscanner)
+{
+	/* The cast to (char *) in the following accommodates both
+	 * implementations that use char* generic pointers, and those
+	 * that use void* generic pointers.  It works with the latter
+	 * because both ANSI C and C++ allow castless assignment from
+	 * any pointer type to void*, and deal with argument conversions
+	 * as though doing an assignment.
+	 */
+	return (void *) realloc( (char *) ptr, size );
+}
+
+void libconfig_yyfree (void * ptr , yyscan_t yyscanner)
+{
+	free( (char *) ptr );	/* see libconfig_yyrealloc() for (char *) cast */
+}
+
+#define YYTABLES_NAME "yytables"
+
+#line 191 "scanner.l"
diff --git a/3rdparty/libconfig/scanner.h b/3rdparty/libconfig/scanner.h
new file mode 100644
index 0000000..baa6f77
--- /dev/null
+++ b/3rdparty/libconfig/scanner.h
@@ -0,0 +1,326 @@
+#ifndef libconfig_yyHEADER_H
+#define libconfig_yyHEADER_H 1
+#define libconfig_yyIN_HEADER 1
+
+#line 6 "scanner.h"
+
+#line 8 "scanner.h"
+
+#define  YY_INT_ALIGNED short int
+
+/* A lexical scanner generated by flex */
+
+#define FLEX_SCANNER
+#define YY_FLEX_MAJOR_VERSION 2
+#define YY_FLEX_MINOR_VERSION 5
+#define YY_FLEX_SUBMINOR_VERSION 33
+#if YY_FLEX_SUBMINOR_VERSION > 0
+#define FLEX_BETA
+#endif
+
+/* First, we deal with  platform-specific or compiler-specific issues. */
+
+/* begin standard C headers. */
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <stdlib.h>
+
+/* end standard C headers. */
+
+/* flex integer type definitions */
+
+#ifndef FLEXINT_H
+#define FLEXINT_H
+
+/* C99 systems have <inttypes.h>. Non-C99 systems may or may not. */
+
+#if __STDC_VERSION__ >= 199901L
+
+/* C99 says to define __STDC_LIMIT_MACROS before including stdint.h,
+ * if you want the limit (max/min) macros for int types. 
+ */
+#ifndef __STDC_LIMIT_MACROS
+#define __STDC_LIMIT_MACROS 1
+#endif
+
+#include <inttypes.h>
+typedef int8_t flex_int8_t;
+typedef uint8_t flex_uint8_t;
+typedef int16_t flex_int16_t;
+typedef uint16_t flex_uint16_t;
+typedef int32_t flex_int32_t;
+typedef uint32_t flex_uint32_t;
+#else
+typedef signed char flex_int8_t;
+typedef short int flex_int16_t;
+typedef int flex_int32_t;
+typedef unsigned char flex_uint8_t; 
+typedef unsigned short int flex_uint16_t;
+typedef unsigned int flex_uint32_t;
+#endif /* ! C99 */
+
+/* Limits of integral types. */
+#ifndef INT8_MIN
+#define INT8_MIN               (-128)
+#endif
+#ifndef INT16_MIN
+#define INT16_MIN              (-32767-1)
+#endif
+#ifndef INT32_MIN
+#define INT32_MIN              (-2147483647-1)
+#endif
+#ifndef INT8_MAX
+#define INT8_MAX               (127)
+#endif
+#ifndef INT16_MAX
+#define INT16_MAX              (32767)
+#endif
+#ifndef INT32_MAX
+#define INT32_MAX              (2147483647)
+#endif
+#ifndef UINT8_MAX
+#define UINT8_MAX              (255U)
+#endif
+#ifndef UINT16_MAX
+#define UINT16_MAX             (65535U)
+#endif
+#ifndef UINT32_MAX
+#define UINT32_MAX             (4294967295U)
+#endif
+
+#endif /* ! FLEXINT_H */
+
+#ifdef __cplusplus
+
+/* The "const" storage-class-modifier is valid. */
+#define YY_USE_CONST
+
+#else	/* ! __cplusplus */
+
+#if __STDC__
+
+#define YY_USE_CONST
+
+#endif	/* __STDC__ */
+#endif	/* ! __cplusplus */
+
+#ifdef YY_USE_CONST
+#define yyconst const
+#else
+#define yyconst
+#endif
+
+/* An opaque pointer. */
+#ifndef YY_TYPEDEF_YY_SCANNER_T
+#define YY_TYPEDEF_YY_SCANNER_T
+typedef void* yyscan_t;
+#endif
+
+/* For convenience, these vars (plus the bison vars far below)
+   are macros in the reentrant scanner. */
+#define yyin yyg->yyin_r
+#define yyout yyg->yyout_r
+#define yyextra yyg->yyextra_r
+#define yyleng yyg->yyleng_r
+#define yytext yyg->yytext_r
+#define yylineno (YY_CURRENT_BUFFER_LVALUE->yy_bs_lineno)
+#define yycolumn (YY_CURRENT_BUFFER_LVALUE->yy_bs_column)
+#define yy_flex_debug yyg->yy_flex_debug_r
+
+int libconfig_yylex_init (yyscan_t* scanner);
+
+#ifndef YY_TYPEDEF_YY_BUFFER_STATE
+#define YY_TYPEDEF_YY_BUFFER_STATE
+typedef struct yy_buffer_state *YY_BUFFER_STATE;
+#endif
+
+/* The following is because we cannot portably get our hands on size_t
+ * (without autoconf's help, which isn't available because we want
+ * flex-generated scanners to compile on their own).
+ */
+
+#ifndef YY_TYPEDEF_YY_SIZE_T
+#define YY_TYPEDEF_YY_SIZE_T
+typedef unsigned int yy_size_t;
+#endif
+
+#ifndef YY_STRUCT_YY_BUFFER_STATE
+#define YY_STRUCT_YY_BUFFER_STATE
+struct yy_buffer_state
+	{
+	FILE *yy_input_file;
+
+	char *yy_ch_buf;		/* input buffer */
+	char *yy_buf_pos;		/* current position in input buffer */
+
+	/* Size of input buffer in bytes, not including room for EOB
+	 * characters.
+	 */
+	yy_size_t yy_buf_size;
+
+	/* Number of characters read into yy_ch_buf, not including EOB
+	 * characters.
+	 */
+	int yy_n_chars;
+
+	/* Whether we "own" the buffer - i.e., we know we created it,
+	 * and can realloc() it to grow it, and should free() it to
+	 * delete it.
+	 */
+	int yy_is_our_buffer;
+
+	/* Whether this is an "interactive" input source; if so, and
+	 * if we're using stdio for input, then we want to use getc()
+	 * instead of fread(), to make sure we stop fetching input after
+	 * each newline.
+	 */
+	int yy_is_interactive;
+
+	/* Whether we're considered to be at the beginning of a line.
+	 * If so, '^' rules will be active on the next match, otherwise
+	 * not.
+	 */
+	int yy_at_bol;
+
+    int yy_bs_lineno; /**< The line count. */
+    int yy_bs_column; /**< The column count. */
+    
+	/* Whether to try to fill the input buffer when we reach the
+	 * end of it.
+	 */
+	int yy_fill_buffer;
+
+	int yy_buffer_status;
+
+	};
+#endif /* !YY_STRUCT_YY_BUFFER_STATE */
+
+void libconfig_yyrestart (FILE *input_file ,yyscan_t yyscanner );
+void libconfig_yy_switch_to_buffer (YY_BUFFER_STATE new_buffer ,yyscan_t yyscanner );
+YY_BUFFER_STATE libconfig_yy_create_buffer (FILE *file,int size ,yyscan_t yyscanner );
+void libconfig_yy_delete_buffer (YY_BUFFER_STATE b ,yyscan_t yyscanner );
+void libconfig_yy_flush_buffer (YY_BUFFER_STATE b ,yyscan_t yyscanner );
+void libconfig_yypush_buffer_state (YY_BUFFER_STATE new_buffer ,yyscan_t yyscanner );
+void libconfig_yypop_buffer_state (yyscan_t yyscanner );
+
+YY_BUFFER_STATE libconfig_yy_scan_buffer (char *base,yy_size_t size ,yyscan_t yyscanner );
+YY_BUFFER_STATE libconfig_yy_scan_string (yyconst char *yy_str ,yyscan_t yyscanner );
+YY_BUFFER_STATE libconfig_yy_scan_bytes (yyconst char *bytes,int len ,yyscan_t yyscanner );
+
+void *libconfig_yyalloc (yy_size_t ,yyscan_t yyscanner );
+void *libconfig_yyrealloc (void *,yy_size_t ,yyscan_t yyscanner );
+void libconfig_yyfree (void * ,yyscan_t yyscanner );
+
+#define libconfig_yywrap(n) 1
+#define YY_SKIP_YYWRAP
+
+#define yytext_ptr yytext_r
+
+#ifdef YY_HEADER_EXPORT_START_CONDITIONS
+#define INITIAL 0
+#define COMMENT 1
+
+#endif
+
+#ifndef YY_EXTRA_TYPE
+#define YY_EXTRA_TYPE void *
+#endif
+
+/* Accessor methods to globals.
+   These are made visible to non-reentrant scanners for convenience. */
+
+int libconfig_yylex_destroy (yyscan_t yyscanner );
+
+int libconfig_yyget_debug (yyscan_t yyscanner );
+
+void libconfig_yyset_debug (int debug_flag ,yyscan_t yyscanner );
+
+YY_EXTRA_TYPE libconfig_yyget_extra (yyscan_t yyscanner );
+
+void libconfig_yyset_extra (YY_EXTRA_TYPE user_defined ,yyscan_t yyscanner );
+
+FILE *libconfig_yyget_in (yyscan_t yyscanner );
+
+void libconfig_yyset_in  (FILE * in_str ,yyscan_t yyscanner );
+
+FILE *libconfig_yyget_out (yyscan_t yyscanner );
+
+void libconfig_yyset_out  (FILE * out_str ,yyscan_t yyscanner );
+
+int libconfig_yyget_leng (yyscan_t yyscanner );
+
+char *libconfig_yyget_text (yyscan_t yyscanner );
+
+int libconfig_yyget_lineno (yyscan_t yyscanner );
+
+void libconfig_yyset_lineno (int line_number ,yyscan_t yyscanner );
+
+YYSTYPE * libconfig_yyget_lval (yyscan_t yyscanner );
+
+void libconfig_yyset_lval (YYSTYPE * yylval_param ,yyscan_t yyscanner );
+
+/* Macros after this point can all be overridden by user definitions in
+ * section 1.
+ */
+
+#ifndef YY_SKIP_YYWRAP
+#ifdef __cplusplus
+extern "C" int libconfig_yywrap (yyscan_t yyscanner );
+#else
+extern int libconfig_yywrap (yyscan_t yyscanner );
+#endif
+#endif
+
+#ifndef yytext_ptr
+static void yy_flex_strncpy (char *,yyconst char *,int ,yyscan_t yyscanner);
+#endif
+
+#ifdef YY_NEED_STRLEN
+static int yy_flex_strlen (yyconst char * ,yyscan_t yyscanner);
+#endif
+
+#ifndef YY_NO_INPUT
+
+#endif
+
+/* Amount of stuff to slurp up with each read. */
+#ifndef YY_READ_BUF_SIZE
+#define YY_READ_BUF_SIZE 8192
+#endif
+
+/* Number of entries by which start-condition stack grows. */
+#ifndef YY_START_STACK_INCR
+#define YY_START_STACK_INCR 25
+#endif
+
+/* Default declaration of generated scanner - a define so the user can
+ * easily add parameters.
+ */
+#ifndef YY_DECL
+#define YY_DECL_IS_OURS 1
+
+extern int libconfig_yylex (YYSTYPE * yylval_param ,yyscan_t yyscanner);
+
+#define YY_DECL int libconfig_yylex (YYSTYPE * yylval_param , yyscan_t yyscanner)
+#endif /* !YY_DECL */
+
+/* yy_get_previous_state - get the state just before the EOB char was reached */
+
+#undef YY_NEW_FILE
+#undef YY_FLUSH_BUFFER
+#undef yy_set_bol
+#undef yy_new_buffer
+#undef yy_set_interactive
+#undef YY_DO_BEFORE_ACTION
+
+#ifdef YY_DECL_IS_OURS
+#undef YY_DECL_IS_OURS
+#undef YY_DECL
+#endif
+
+#line 130 "scanner.l"
+
+#line 325 "scanner.h"
+#undef libconfig_yyIN_HEADER
+#endif /* libconfig_yyHEADER_H */
diff --git a/3rdparty/libconfig/scanner.l b/3rdparty/libconfig/scanner.l
new file mode 100644
index 0000000..4d76ead
--- /dev/null
+++ b/3rdparty/libconfig/scanner.l
@@ -0,0 +1,190 @@
+/* -*- mode: C -*- */
+/* --------------------------------------------------------------------------
+   libconfig - A library for processing structured configuration files
+   Copyright (C) 2005-2010  Mark A Lindner
+
+   This file is part of libconfig.
+
+   This library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public License
+   as published by the Free Software Foundation; either version 2.1 of
+   the License, or (at your option) any later version.
+
+   This library is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with this library; if not, see
+   <http://www.gnu.org/licenses/>.
+   ----------------------------------------------------------------------------
+*/
+
+%option nounistd
+%option reentrant
+%option noyywrap
+%option yylineno
+%option nounput
+%option bison-bridge
+%option header-file="scanner.h"
+%option outfile="lex.yy.c"
+%option extra-type="struct scan_context *"
+
+%{
+
+#ifdef _MSC_VER
+#pragma warning (disable: 4996)
+#endif
+
+#include <stdlib.h>
+#include <ctype.h>
+#include <string.h>
+#include "grammar.h"
+#include "wincompat.h"
+#include "parsectx.h"
+#include "scanctx.h"
+
+#define YY_NO_INPUT // Suppress generation of useless input() function
+
+static unsigned long long fromhex(const char *s)
+{
+#ifdef __MINGW32__
+
+  /* MinGW's strtoull() seems to be broken; it only returns the lower
+   * 32 bits...
+   */
+
+  const char *p = s;
+  unsigned long long val = 0;
+
+  if(*p != '0')
+    return(0);
+
+  ++p;
+
+  if(*p != 'x' && *p != 'X')
+    return(0);
+
+  for(++p; isxdigit(*p); ++p)
+  {
+    val <<= 4;
+    val |= ((*p < 'A') ? (*p & 0xF) : (9 + (*p & 0x7)));
+  }
+
+  return(val);
+
+#else /* ! __MINGW32__ */
+
+  return(strtoull(s, NULL, 16));
+
+#endif /* __MINGW32__ */
+}
+
+%}
+
+true              [Tt][Rr][Uu][Ee]
+false             [Ff][Aa][Ll][Ss][Ee]
+name              [A-Za-z\*][-A-Za-z0-9_\*]*
+integer           [-+]?[0-9]+
+integer64         [-+]?[0-9]+L(L)?
+hex               0[Xx][0-9A-Fa-f]+
+hex64             0[Xx][0-9A-Fa-f]+L(L)?
+hexchar           \\[Xx][0-9A-Fa-f]{2}
+float             ([-+]?([0-9]*)?\.[0-9]*([eE][-+]?[0-9]+)?)|([-+]?([0-9]+)(\.[0-9]*)?[eE][-+]?[0-9]+)
+comment           (#|\/\/).*$
+include_open      ^[ \t]*@include[ \t]+\"
+
+%x COMMENT STRING INCLUDE
+
+%%
+
+\/\*              { BEGIN COMMENT; }
+<COMMENT>\*\/     { BEGIN INITIAL; }
+<COMMENT>.        { /* ignore */ }
+<COMMENT>\n       { /* ignore */ }
+
+\"                { BEGIN STRING; }
+<STRING>[^\"\\]+  { scanctx_append_string(yyextra, yytext); }
+<STRING>\\n       { scanctx_append_string(yyextra, "\n"); }
+<STRING>\\r       { scanctx_append_string(yyextra, "\r"); }
+<STRING>\\t       { scanctx_append_string(yyextra, "\t"); }
+<STRING>\\f       { scanctx_append_string(yyextra, "\f"); }
+<STRING>\\\\      { scanctx_append_string(yyextra, "\\"); }
+<STRING>\\\"      { scanctx_append_string(yyextra, "\""); }
+<STRING>{hexchar} {
+                    char c[2] = { (char)(strtol(yytext + 2, NULL, 16) & 0xFF),
+                                  0 };
+                    scanctx_append_string(yyextra, c);
+                  }
+<STRING>\"        {
+                    yylval->sval = scanctx_take_string(yyextra);
+                    BEGIN INITIAL;
+                    return(TOK_STRING);
+                  }
+
+{include_open}    { BEGIN INCLUDE; }
+<INCLUDE>[^\"\\]+ { scanctx_append_string(yyextra, yytext); }
+<INCLUDE>\\\\     { scanctx_append_string(yyextra, "\\"); }
+<INCLUDE>\\\"     { scanctx_append_string(yyextra, "\""); }
+<INCLUDE>\"       {
+                    const char *error;
+                    FILE *fp = scanctx_push_include(yyextra,
+                                                    (void *)YY_CURRENT_BUFFER,
+                                                    &error);
+                    if(fp)
+                    {
+                      yyin = fp;
+                      yy_switch_to_buffer(
+                        yy_create_buffer(yyin, YY_BUF_SIZE, yyscanner),
+                        yyscanner);
+                    }
+                    else
+                    {
+                      yyextra->config->error_text = error;
+                      yyextra->config->error_file = scanctx_current_filename(
+                        yyextra);
+                      yyextra->config->error_line = libconfig_yyget_lineno(
+                        yyscanner);
+                      return TOK_ERROR;
+                    }
+                    BEGIN INITIAL;
+                  }
+
+\n|\r|\f          { /* ignore */ }
+[ \t]+            { /* ignore */ }
+
+\=|\:             { return(TOK_EQUALS); }
+,                 { return(TOK_COMMA); }
+\{                { return(TOK_GROUP_START); }
+\}                { return(TOK_GROUP_END); }
+{true}            { yylval->ival = 1; return(TOK_BOOLEAN); }
+{false}           { yylval->ival = 0; return(TOK_BOOLEAN); }
+{name}            { yylval->sval = yytext; return(TOK_NAME); }
+{float}           { yylval->fval = atof(yytext); return(TOK_FLOAT); }
+{integer}         { yylval->ival = atoi(yytext); return(TOK_INTEGER); }
+{integer64}       { yylval->llval = atoll(yytext); return(TOK_INTEGER64); }
+{hex}             {
+                    yylval->ival = strtoul(yytext, NULL, 16);
+                    return(TOK_HEX);
+                  }
+{hex64}           { yylval->llval = fromhex(yytext); return(TOK_HEX64); }
+\[                { return(TOK_ARRAY_START); }
+\]                { return(TOK_ARRAY_END); }
+\(                { return(TOK_LIST_START); }
+\)                { return(TOK_LIST_END); }
+;                 { return(TOK_END); }
+{comment}         { /* ignore */ }
+.                 { return(TOK_GARBAGE); }
+
+<<EOF>>           {
+                    YY_BUFFER_STATE buf = (YY_BUFFER_STATE)scanctx_pop_include(
+                      yyextra);
+                    if(buf)
+                    {
+                      yy_delete_buffer(YY_CURRENT_BUFFER, yyscanner);
+                      yy_switch_to_buffer(buf, yyscanner);
+                    }
+                    else
+                      yyterminate();
+                  }
diff --git a/3rdparty/libconfig/strbuf.c b/3rdparty/libconfig/strbuf.c
new file mode 100644
index 0000000..f7f48d3
--- /dev/null
+++ b/3rdparty/libconfig/strbuf.c
@@ -0,0 +1,58 @@
+/* ----------------------------------------------------------------------------
+   libconfig - A library for processing structured configuration files
+   Copyright (C) 2005-2010  Mark A Lindner
+
+   This file is part of libconfig.
+
+   This library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public License
+   as published by the Free Software Foundation; either version 2.1 of
+   the License, or (at your option) any later version.
+
+   This library is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with this library; if not, see
+   <http://www.gnu.org/licenses/>.
+   ----------------------------------------------------------------------------
+*/
+
+#include "strbuf.h"
+
+#include <string.h>
+#include <stdlib.h>
+
+#define STRING_BLOCK_SIZE 64
+
+/* ------------------------------------------------------------------------- */
+
+char *strbuf_release(strbuf_t *buf)
+{
+  char *r = buf->string;
+  memset(buf, 0, sizeof(strbuf_t));
+  return(r);
+}
+
+/* ------------------------------------------------------------------------- */
+
+void strbuf_append(strbuf_t *buf, const char *text)
+{
+  static const size_t mask = ~(STRING_BLOCK_SIZE - 1);
+  size_t len = strlen(text);
+  size_t newlen = buf->length + len + 1; /* add 1 for NUL */
+
+  if(newlen > buf->capacity)
+  {
+    buf->capacity = (newlen + (STRING_BLOCK_SIZE - 1)) & mask;
+    buf->string = (char *)realloc(buf->string, buf->capacity);
+  }
+
+  strcpy(buf->string + buf->length, text);
+  buf->length += len;
+}
+
+/* ------------------------------------------------------------------------- */
+/* eof */
diff --git a/3rdparty/libconfig/strbuf.h b/3rdparty/libconfig/strbuf.h
new file mode 100644
index 0000000..62cd782
--- /dev/null
+++ b/3rdparty/libconfig/strbuf.h
@@ -0,0 +1,40 @@
+/* ----------------------------------------------------------------------------
+   libconfig - A library for processing structured configuration files
+   Copyright (C) 2005-2010  Mark A Lindner
+
+   This file is part of libconfig.
+
+   This library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public License
+   as published by the Free Software Foundation; either version 2.1 of
+   the License, or (at your option) any later version.
+
+   This library is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with this library; if not, see
+   <http://www.gnu.org/licenses/>.
+   ----------------------------------------------------------------------------
+*/
+
+#ifndef __libconfig_strbuf_h
+#define __libconfig_strbuf_h
+
+#include <string.h>
+#include <sys/types.h>
+
+typedef struct
+{
+  char *string;
+  size_t length;
+  size_t capacity;
+} strbuf_t;
+
+char *strbuf_release(strbuf_t *buf);
+
+void strbuf_append(strbuf_t *buf, const char *text);
+
+#endif /* __libconfig_strbuf_h */
diff --git a/3rdparty/libconfig/wincompat.h b/3rdparty/libconfig/wincompat.h
new file mode 100644
index 0000000..23d7379
--- /dev/null
+++ b/3rdparty/libconfig/wincompat.h
@@ -0,0 +1,90 @@
+/* ----------------------------------------------------------------------------
+   libconfig - A library for processing structured configuration files
+   Copyright (C) 2005-2010  Mark A Lindner
+
+   This file is part of libconfig.
+
+   This library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public License
+   as published by the Free Software Foundation; either version 2.1 of
+   the License, or (at your option) any later version.
+
+   This library is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with this library; if not, see
+   <http://www.gnu.org/licenses/>.
+   ----------------------------------------------------------------------------
+*/
+
+#ifndef __wincompat_h
+#define __wincompat_h
+
+#if defined(WIN32) || defined(_WIN32) || defined(__WIN32__)
+
+#ifdef _MSC_VER
+#pragma warning (disable: 4996)
+#endif
+
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+
+#define snprintf  _snprintf
+
+#ifndef __MINGW32__
+#define atoll     _atoi64
+#define strtoull  _strtoui64
+#endif /* __MINGW32__ */
+
+#endif
+
+#if (defined(WIN32) || defined(_WIN32) || defined(__WIN32__) \
+     || defined(__MINGW32__))
+
+/* Why does gcc on MinGW use the Visual C++ style format directives
+ * for 64-bit integers? Inquiring minds want to know....
+ */
+
+#define INT64_FMT "%I64d"
+#define UINT64_FMT "%I64u"
+
+#define INT64_HEX_FMT "%I64X"
+
+#define FILE_SEPARATOR "\\"
+
+#else /* defined(WIN32) || defined(__MINGW32__) */
+
+#define INT64_FMT "%lld"
+#define UINT64_FMT "%llu"
+
+#define INT64_HEX_FMT "%llX"
+
+#define FILE_SEPARATOR "/"
+
+#endif /* defined(WIN32) || defined(__MINGW32__) */
+
+#if (defined(WIN32) || defined(_WIN32) || defined(__WIN32__)) \
+  && ! defined(__MINGW32__)
+
+#define INT64_CONST(I)  (I ## i64)
+#define UINT64_CONST(I) (I ## Ui64)
+
+#ifndef INT32_MAX
+#define INT32_MAX (2147483647)
+#endif
+
+#ifndef INT32_MIN
+#define INT32_MIN (-2147483647-1)
+#endif
+
+#else /* defined(WIN32) && ! defined(__MINGW32__) */
+
+#define INT64_CONST(I)  (I ## LL)
+#define UINT64_CONST(I) (I ## ULL)
+
+#endif /* defined(WIN32) && ! defined(__MINGW32__) */
+
+#endif /* __wincompat_h */
diff --git a/3rdparty/wiiuse/CHANGELOG b/3rdparty/wiiuse/CHANGELOG
new file mode 100644
index 0000000..ccb831a
--- /dev/null
+++ b/3rdparty/wiiuse/CHANGELOG
@@ -0,0 +1,208 @@
+---------------------------
+-
+-  CHANGE LOG - Wiiuse
+-
+---------------------------
+
+http://wiiuse.net/
+http://wiiuse.sourceforge.net/
+http://sourceforge.net/projects/wiiuse/
+
+---------------------------
+v0.12 -- 2 Apr 2008
+---------------------------
+
+	Added:
+		- API function wiiuse_set_ir_sensitivity()
+		- Macro WIIUSE_GET_IR_SENSITIVITY()
+		- Event type WIIUSE_READ_DATA
+		- Event type WIIUSE_UNEXPECTED_DISCONNECT
+
+	Fixed:
+		- [Linux] Ability to try to select() nothing
+		- [Linux] Changed Makefile to include debug output when compiling in debug mode
+
+	Changed:
+		- wiiuse_set_nunchuk_orient_threshold() now takes a wiimote_t pointer
+		- wiiuse_set_nunchuk_accel_threshold() now takes a wiimote_t pointer
+		- wiiuse_read_data() generates an event WIIUSE_READ_DATA rather than executing a callback
+
+---------------------------
+v0.11 -- 25 Feb 2008
+---------------------------
+
+	Added:
+		- API function wiiuse_set_nunchuk_orient_threshold()
+		- API function wiiuse_set_nunchuk_accel_threshold()
+		- Event type WIIUSE_NUNCHUK_INSERTED
+		- Event type WIIUSE_NUNCHUK_REMOVED
+		- Event type WIIUSE_CLASSIC_CTRL_INSERTED
+		- Event type WIIUSE_CLASSIC_CTRL_REMOVED
+		- Event type WIIUSE_GUITAR_HERO_3_CTRL_INSERTED
+		- Event type WIIUSE_GUITAR_HERO_3_CTRL_REMOVED
+
+	Fixed:
+		- Added some missing function prototypes to wiiuse.h
+		- [Linux] Fixed Makefile to link libmath and libbluetooth
+		- Status event is set when a status report comes in
+		- Orientation threshold not being saved in lstate
+
+---------------------------
+v0.10 -- 11 Feb 2008
+---------------------------
+
+	Added:
+		- Real dynamic linking (by noisehole)
+		- Changed from callback to SDL style
+		- Guitar Hero 3 controller support
+		- API function wiiuse_set_accel_threshold()
+		- API function wiiuse_version()
+		- Macro WIIUSE_USING_SPEAKER()
+		- Macro WIIUSE_IS_LED_SET(wm, num)
+		- wiiuse_init() now autogenerates unids
+		- orient_t::a_roll/a_pitch
+		- wiiuse_resync()
+		- wiiuse_cleanup()
+		- wiiuse_set_timeout()
+
+	Fixed:
+		- [Windows] Fixed bug where it did not detect expansions on startup
+		- Renamed INFO/WARNING/DEBUG macros to WIIUSE_* (by noisehole)
+		- Updated Makefiles (by noisehole)
+		- Fixed incorrect roll/pitch when smoothing was enabled
+		- Fixed nunchuk and classic controller flooding events when significant changes occured
+		- Fixed bug where IR was not correct on roll if IR was enabled before handshake
+
+	Removed:
+		- wiiuse_startup(), no longer needed
+
+---------------------------
+v0.9 -- 3 Nov 2007
+---------------------------
+
+	Fixed:
+		- Can now use include/wiiuse.h in C++ projects.
+		- HOME button works again.
+		- IR now functions after expansion is connected or removed.
+
+---------------------------
+v0.8 -- 27 Oct 2007
+---------------------------
+
+	- Bumped API version to 8
+	- Exported all API functions for usage with non-C/C++ languages.
+	- Changed event callback to only trigger if a significant state change occurs.
+
+	Added:
+		- wiimote_t::lstate structure
+
+	Fixed:
+		- Bug 1820140 - Buffer overflow in io_nix.c. Thanks proppy.
+
+---------------------------
+v0.7 -- 19 Oct 2007
+---------------------------
+
+	- Bumped API version to 7
+	- Renamed Linux build from wii.so to wiiuse.so
+	- Changed version representation from float to const char*.
+
+	Added:
+		- [Windows] BlueSoleil support.
+		- [Windows] Bluetooth stack auto-detection (WinXP SP2, Bluesoleil, Widdcomm tested).
+		- [Windows] API function wiiuse_set_bluetooth_stack().
+		- Calculates yaw if IR tracking is enabled.
+
+	Fixed:
+		- [Windows] Problem where a connection is made to a wiimote that does not exist.
+		- [Windows] Issue that occured while using multiple wiimotes.
+
+---------------------------
+v0.6 -- 16 Oct 2007
+---------------------------
+
+	- Bumped API version to 0.6.
+	- Ported to Microsoft Windows.
+	- Improved IR tracking.
+	- Default IR virtual screen resolutions changed depending on 16:9 or 4:3.
+
+	Added:
+		- src/msvc/ and api/msvc/ - Microsoft Visual C++ 6.0 project files.
+
+---------------------------
+v0.5 -- 13 Oct 2007
+---------------------------
+
+	- Bumped API version to 0.5.
+	- Greatly improved IR tracking.
+	- Renamed function wiiuse_set_ir_correction() to wiiuse_set_ir_position().
+
+	Added:
+		- API function wiiuse_set_aspect_ratio()
+
+	Fixed:
+		- When rolling around 180 degree rotation smoothing would not be seemless.
+
+---------------------------
+v0.4 -- 08 Oct 2007
+---------------------------
+
+	- Bumped API version to 0.4.
+	- Greatly improved classic controller joystick functionality.
+	- Changed all functions named wiimote_*() to wiiuse_*()
+	- Renamed many macros from WIIMOTE_* to WIIUSE_*
+
+	Added:
+		- IR support
+		- New WIIMOTE_CONTINUOUS flag to set continuous reporting
+		- Macro IS_JUST_PRESSED()
+		- Macro WIIUSE_USING_ACC()
+		- Macro WIIUSE_USING_EXP()
+		- Macro WIIUSE_USING_IR()
+		- API function wiiuse_set_ir()
+		- API function wiiuse_set_ir_vres()
+		- API function wiiuse_set_ir_correction()
+
+		- gfx/ - A small OpenGL example that renders IR data
+
+	Fixed:
+		- Sometimes classic controller would only report infinite angle and magnitude for joysticks.
+
+---------------------------
+v0.3 -- 10 Sept 2007
+---------------------------
+
+	- Moved license to GPLv3.
+	- Bumped API version to 0.3.
+
+	Added:
+		- Support for Classic Controller
+		- Smoothing for roll and pitch values of the wiimote and nunchuk.
+
+		- API: wiimote_set_flags() to set or disable wiimote options.
+		- API: wiimote_set_smooth_alpha() to set smoothing alpha value.
+
+	Fixed:
+		- When the wiimote accelerates the roll or pitch is unreliable and was set to 0.
+		  It now remains at previous tilt value.
+		- If no event callback was specified then no events would be processed internally.
+
+---------------------------
+v0.2 -- 25 Aug 2007
+---------------------------
+
+	- Bumped API version to 0.2.
+
+	Added:
+		- Nunchuk support.
+		- Ability to write to flash memory.
+
+	Fixed:
+		- Roll and pitch rotation now ranges from -180 to 180 degrees (previously -90 to 90).
+		- Bug when reading data from flash memory would read wrong address.
+
+---------------------------
+v0.1 -- 23 Feb 2007
+---------------------------
+
+	- Initial release
diff --git a/3rdparty/wiiuse/CMakeLists.txt b/3rdparty/wiiuse/CMakeLists.txt
new file mode 100755
index 0000000..fe2fb71
--- /dev/null
+++ b/3rdparty/wiiuse/CMakeLists.txt
@@ -0,0 +1,58 @@
+cmake_minimum_required(VERSION 2.6)
+project(wiiuselib)
+
+set (WIIUSE_MAJOR_VERSION 0)
+set (WIIUSE_RELEASE_VERSION 13)
+set (WIIUSE_EPOCH_VERSION 0)
+
+#
+# Set default build mode
+#
+
+#IF(NOT CMAKE_BUILD_TYPE AND (${CMAKE_GENERATOR} MATCHES ".*Makefiles"))
+#  SET(CMAKE_BUILD_TYPE Debug CACHE STRING
+#      "Choose the type of build, options are: Debug Release"
+#      FORCE)
+#ENDIF()
+
+#IF (WIN32)
+	# On WIN32 force shared lib because wiiuse depends on many specific libraries
+#	SET(BUILD_SHARED_LIBS ON)
+#ELSE (WIN32)
+#	IF(NOT DEFINED BUILD_SHARED_LIBS)
+#		SET(BUILD_SHARED_LIBS OFF CACHE BOOL 
+#			"Build shared libraries as default?")
+#	ENDIF(NOT DEFINED BUILD_SHARED_LIBS)
+#ENDIF(WIN32)
+
+#
+# Compilation flags
+#
+
+#IF (CMAKE_BUILD_TYPE STREQUAL "Debug")
+#	ADD_DEFINITIONS (-DWITH_WIIUSE_DEBUG)
+#ENDIF()
+
+IF (CMAKE_COMPILER_IS_GNUCC)
+	ADD_DEFINITIONS (-Wall)
+ENDIF()
+
+SET (WIIUSE_INCLUDE_DIRECTORIES "${CMAKE_CURRENT_SOURCE_DIR}/include")
+INCLUDE_DIRECTORIES(${WIIUSE_INCLUDE_DIRECTORIES})
+
+#IF (NOT EXECUTABLE_OUTPUT_PATH)
+#	set (EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin)
+#ENDIF()
+
+#IF (NOT LIBRARY_OUTPUT_PATH)
+#	set (LIBRARY_OUTPUT_PATH ${EXECUTABLE_OUTPUT_PATH})
+#ENDIF()
+
+SET(WIIUSE_BUILD_EXAMPLES OFF CACHE BOOL "Build examples")
+
+add_subdirectory(src)
+
+IF (WIIUSE_BUILD_EXAMPLES)
+	add_subdirectory(example)
+	add_subdirectory(example-sdl)
+ENDIF()
diff --git a/3rdparty/wiiuse/LICENSE b/3rdparty/wiiuse/LICENSE
new file mode 100644
index 0000000..f6c1961
--- /dev/null
+++ b/3rdparty/wiiuse/LICENSE
@@ -0,0 +1,620 @@
+                    GNU GENERAL PUBLIC LICENSE
+                       Version 3, 29 June 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+                            Preamble
+
+  The GNU General Public License is a free, copyleft license for
+software and other kinds of works.
+
+  The licenses for most software and other practical works are designed
+to take away your freedom to share and change the works.  By contrast,
+the GNU General Public License is intended to guarantee your freedom to
+share and change all versions of a program--to make sure it remains free
+software for all its users.  We, the Free Software Foundation, use the
+GNU General Public License for most of our software; it applies also to
+any other work released this way by its authors.  You can apply it to
+your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+them if you wish), that you receive source code or can get it if you
+want it, that you can change the software or use pieces of it in new
+free programs, and that you know you can do these things.
+
+  To protect your rights, we need to prevent others from denying you
+these rights or asking you to surrender the rights.  Therefore, you have
+certain responsibilities if you distribute copies of the software, or if
+you modify it: responsibilities to respect the freedom of others.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must pass on to the recipients the same
+freedoms that you received.  You must make sure that they, too, receive
+or can get the source code.  And you must show them these terms so they
+know their rights.
+
+  Developers that use the GNU GPL protect your rights with two steps:
+(1) assert copyright on the software, and (2) offer you this License
+giving you legal permission to copy, distribute and/or modify it.
+
+  For the developers' and authors' protection, the GPL clearly explains
+that there is no warranty for this free software.  For both users' and
+authors' sake, the GPL requires that modified versions be marked as
+changed, so that their problems will not be attributed erroneously to
+authors of previous versions.
+
+  Some devices are designed to deny users access to install or run
+modified versions of the software inside them, although the manufacturer
+can do so.  This is fundamentally incompatible with the aim of
+protecting users' freedom to change the software.  The systematic
+pattern of such abuse occurs in the area of products for individuals to
+use, which is precisely where it is most unacceptable.  Therefore, we
+have designed this version of the GPL to prohibit the practice for those
+products.  If such problems arise substantially in other domains, we
+stand ready to extend this provision to those domains in future versions
+of the GPL, as needed to protect the freedom of users.
+
+  Finally, every program is threatened constantly by software patents.
+States should not allow patents to restrict development and use of
+software on general-purpose computers, but in those that do, we wish to
+avoid the special danger that patents applied to a free program could
+make it effectively proprietary.  To prevent this, the GPL assures that
+patents cannot be used to render the program non-free.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+
+                       TERMS AND CONDITIONS
+
+  0. Definitions.
+
+  "This License" refers to version 3 of the GNU General Public License.
+
+  "Copyright" also means copyright-like laws that apply to other kinds of
+works, such as semiconductor masks.
+
+  "The Program" refers to any copyrightable work licensed under this
+License.  Each licensee is addressed as "you".  "Licensees" and
+"recipients" may be individuals or organizations.
+
+  To "modify" a work means to copy from or adapt all or part of the work
+in a fashion requiring copyright permission, other than the making of an
+exact copy.  The resulting work is called a "modified version" of the
+earlier work or a work "based on" the earlier work.
+
+  A "covered work" means either the unmodified Program or a work based
+on the Program.
+
+  To "propagate" a work means to do anything with it that, without
+permission, would make you directly or secondarily liable for
+infringement under applicable copyright law, except executing it on a
+computer or modifying a private copy.  Propagation includes copying,
+distribution (with or without modification), making available to the
+public, and in some countries other activities as well.
+
+  To "convey" a work means any kind of propagation that enables other
+parties to make or receive copies.  Mere interaction with a user through
+a computer network, with no transfer of a copy, is not conveying.
+
+  An interactive user interface displays "Appropriate Legal Notices"
+to the extent that it includes a convenient and prominently visible
+feature that (1) displays an appropriate copyright notice, and (2)
+tells the user that there is no warranty for the work (except to the
+extent that warranties are provided), that licensees may convey the
+work under this License, and how to view a copy of this License.  If
+the interface presents a list of user commands or options, such as a
+menu, a prominent item in the list meets this criterion.
+
+  1. Source Code.
+
+  The "source code" for a work means the preferred form of the work
+for making modifications to it.  "Object code" means any non-source
+form of a work.
+
+  A "Standard Interface" means an interface that either is an official
+standard defined by a recognized standards body, or, in the case of
+interfaces specified for a particular programming language, one that
+is widely used among developers working in that language.
+
+  The "System Libraries" of an executable work include anything, other
+than the work as a whole, that (a) is included in the normal form of
+packaging a Major Component, but which is not part of that Major
+Component, and (b) serves only to enable use of the work with that
+Major Component, or to implement a Standard Interface for which an
+implementation is available to the public in source code form.  A
+"Major Component", in this context, means a major essential component
+(kernel, window system, and so on) of the specific operating system
+(if any) on which the executable work runs, or a compiler used to
+produce the work, or an object code interpreter used to run it.
+
+  The "Corresponding Source" for a work in object code form means all
+the source code needed to generate, install, and (for an executable
+work) run the object code and to modify the work, including scripts to
+control those activities.  However, it does not include the work's
+System Libraries, or general-purpose tools or generally available free
+programs which are used unmodified in performing those activities but
+which are not part of the work.  For example, Corresponding Source
+includes interface definition files associated with source files for
+the work, and the source code for shared libraries and dynamically
+linked subprograms that the work is specifically designed to require,
+such as by intimate data communication or control flow between those
+subprograms and other parts of the work.
+
+  The Corresponding Source need not include anything that users
+can regenerate automatically from other parts of the Corresponding
+Source.
+
+  The Corresponding Source for a work in source code form is that
+same work.
+
+  2. Basic Permissions.
+
+  All rights granted under this License are granted for the term of
+copyright on the Program, and are irrevocable provided the stated
+conditions are met.  This License explicitly affirms your unlimited
+permission to run the unmodified Program.  The output from running a
+covered work is covered by this License only if the output, given its
+content, constitutes a covered work.  This License acknowledges your
+rights of fair use or other equivalent, as provided by copyright law.
+
+  You may make, run and propagate covered works that you do not
+convey, without conditions so long as your license otherwise remains
+in force.  You may convey covered works to others for the sole purpose
+of having them make modifications exclusively for you, or provide you
+with facilities for running those works, provided that you comply with
+the terms of this License in conveying all material for which you do
+not control copyright.  Those thus making or running the covered works
+for you must do so exclusively on your behalf, under your direction
+and control, on terms that prohibit them from making any copies of
+your copyrighted material outside their relationship with you.
+
+  Conveying under any other circumstances is permitted solely under
+the conditions stated below.  Sublicensing is not allowed; section 10
+makes it unnecessary.
+
+  3. Protecting Users' Legal Rights From Anti-Circumvention Law.
+
+  No covered work shall be deemed part of an effective technological
+measure under any applicable law fulfilling obligations under article
+11 of the WIPO copyright treaty adopted on 20 December 1996, or
+similar laws prohibiting or restricting circumvention of such
+measures.
+
+  When you convey a covered work, you waive any legal power to forbid
+circumvention of technological measures to the extent such circumvention
+is effected by exercising rights under this License with respect to
+the covered work, and you disclaim any intention to limit operation or
+modification of the work as a means of enforcing, against the work's
+users, your or third parties' legal rights to forbid circumvention of
+technological measures.
+
+  4. Conveying Verbatim Copies.
+
+  You may convey verbatim copies of the Program's source code as you
+receive it, in any medium, provided that you conspicuously and
+appropriately publish on each copy an appropriate copyright notice;
+keep intact all notices stating that this License and any
+non-permissive terms added in accord with section 7 apply to the code;
+keep intact all notices of the absence of any warranty; and give all
+recipients a copy of this License along with the Program.
+
+  You may charge any price or no price for each copy that you convey,
+and you may offer support or warranty protection for a fee.
+
+  5. Conveying Modified Source Versions.
+
+  You may convey a work based on the Program, or the modifications to
+produce it from the Program, in the form of source code under the
+terms of section 4, provided that you also meet all of these conditions:
+
+    a) The work must carry prominent notices stating that you modified
+    it, and giving a relevant date.
+
+    b) The work must carry prominent notices stating that it is
+    released under this License and any conditions added under section
+    7.  This requirement modifies the requirement in section 4 to
+    "keep intact all notices".
+
+    c) You must license the entire work, as a whole, under this
+    License to anyone who comes into possession of a copy.  This
+    License will therefore apply, along with any applicable section 7
+    additional terms, to the whole of the work, and all its parts,
+    regardless of how they are packaged.  This License gives no
+    permission to license the work in any other way, but it does not
+    invalidate such permission if you have separately received it.
+
+    d) If the work has interactive user interfaces, each must display
+    Appropriate Legal Notices; however, if the Program has interactive
+    interfaces that do not display Appropriate Legal Notices, your
+    work need not make them do so.
+
+  A compilation of a covered work with other separate and independent
+works, which are not by their nature extensions of the covered work,
+and which are not combined with it such as to form a larger program,
+in or on a volume of a storage or distribution medium, is called an
+"aggregate" if the compilation and its resulting copyright are not
+used to limit the access or legal rights of the compilation's users
+beyond what the individual works permit.  Inclusion of a covered work
+in an aggregate does not cause this License to apply to the other
+parts of the aggregate.
+
+  6. Conveying Non-Source Forms.
+
+  You may convey a covered work in object code form under the terms
+of sections 4 and 5, provided that you also convey the
+machine-readable Corresponding Source under the terms of this License,
+in one of these ways:
+
+    a) Convey the object code in, or embodied in, a physical product
+    (including a physical distribution medium), accompanied by the
+    Corresponding Source fixed on a durable physical medium
+    customarily used for software interchange.
+
+    b) Convey the object code in, or embodied in, a physical product
+    (including a physical distribution medium), accompanied by a
+    written offer, valid for at least three years and valid for as
+    long as you offer spare parts or customer support for that product
+    model, to give anyone who possesses the object code either (1) a
+    copy of the Corresponding Source for all the software in the
+    product that is covered by this License, on a durable physical
+    medium customarily used for software interchange, for a price no
+    more than your reasonable cost of physically performing this
+    conveying of source, or (2) access to copy the
+    Corresponding Source from a network server at no charge.
+
+    c) Convey individual copies of the object code with a copy of the
+    written offer to provide the Corresponding Source.  This
+    alternative is allowed only occasionally and noncommercially, and
+    only if you received the object code with such an offer, in accord
+    with subsection 6b.
+
+    d) Convey the object code by offering access from a designated
+    place (gratis or for a charge), and offer equivalent access to the
+    Corresponding Source in the same way through the same place at no
+    further charge.  You need not require recipients to copy the
+    Corresponding Source along with the object code.  If the place to
+    copy the object code is a network server, the Corresponding Source
+    may be on a different server (operated by you or a third party)
+    that supports equivalent copying facilities, provided you maintain
+    clear directions next to the object code saying where to find the
+    Corresponding Source.  Regardless of what server hosts the
+    Corresponding Source, you remain obligated to ensure that it is
+    available for as long as needed to satisfy these requirements.
+
+    e) Convey the object code using peer-to-peer transmission, provided
+    you inform other peers where the object code and Corresponding
+    Source of the work are being offered to the general public at no
+    charge under subsection 6d.
+
+  A separable portion of the object code, whose source code is excluded
+from the Corresponding Source as a System Library, need not be
+included in conveying the object code work.
+
+  A "User Product" is either (1) a "consumer product", which means any
+tangible personal property which is normally used for personal, family,
+or household purposes, or (2) anything designed or sold for incorporation
+into a dwelling.  In determining whether a product is a consumer product,
+doubtful cases shall be resolved in favor of coverage.  For a particular
+product received by a particular user, "normally used" refers to a
+typical or common use of that class of product, regardless of the status
+of the particular user or of the way in which the particular user
+actually uses, or expects or is expected to use, the product.  A product
+is a consumer product regardless of whether the product has substantial
+commercial, industrial or non-consumer uses, unless such uses represent
+the only significant mode of use of the product.
+
+  "Installation Information" for a User Product means any methods,
+procedures, authorization keys, or other information required to install
+and execute modified versions of a covered work in that User Product from
+a modified version of its Corresponding Source.  The information must
+suffice to ensure that the continued functioning of the modified object
+code is in no case prevented or interfered with solely because
+modification has been made.
+
+  If you convey an object code work under this section in, or with, or
+specifically for use in, a User Product, and the conveying occurs as
+part of a transaction in which the right of possession and use of the
+User Product is transferred to the recipient in perpetuity or for a
+fixed term (regardless of how the transaction is characterized), the
+Corresponding Source conveyed under this section must be accompanied
+by the Installation Information.  But this requirement does not apply
+if neither you nor any third party retains the ability to install
+modified object code on the User Product (for example, the work has
+been installed in ROM).
+
+  The requirement to provide Installation Information does not include a
+requirement to continue to provide support service, warranty, or updates
+for a work that has been modified or installed by the recipient, or for
+the User Product in which it has been modified or installed.  Access to a
+network may be denied when the modification itself materially and
+adversely affects the operation of the network or violates the rules and
+protocols for communication across the network.
+
+  Corresponding Source conveyed, and Installation Information provided,
+in accord with this section must be in a format that is publicly
+documented (and with an implementation available to the public in
+source code form), and must require no special password or key for
+unpacking, reading or copying.
+
+  7. Additional Terms.
+
+  "Additional permissions" are terms that supplement the terms of this
+License by making exceptions from one or more of its conditions.
+Additional permissions that are applicable to the entire Program shall
+be treated as though they were included in this License, to the extent
+that they are valid under applicable law.  If additional permissions
+apply only to part of the Program, that part may be used separately
+under those permissions, but the entire Program remains governed by
+this License without regard to the additional permissions.
+
+  When you convey a copy of a covered work, you may at your option
+remove any additional permissions from that copy, or from any part of
+it.  (Additional permissions may be written to require their own
+removal in certain cases when you modify the work.)  You may place
+additional permissions on material, added by you to a covered work,
+for which you have or can give appropriate copyright permission.
+
+  Notwithstanding any other provision of this License, for material you
+add to a covered work, you may (if authorized by the copyright holders of
+that material) supplement the terms of this License with terms:
+
+    a) Disclaiming warranty or limiting liability differently from the
+    terms of sections 15 and 16 of this License; or
+
+    b) Requiring preservation of specified reasonable legal notices or
+    author attributions in that material or in the Appropriate Legal
+    Notices displayed by works containing it; or
+
+    c) Prohibiting misrepresentation of the origin of that material, or
+    requiring that modified versions of such material be marked in
+    reasonable ways as different from the original version; or
+
+    d) Limiting the use for publicity purposes of names of licensors or
+    authors of the material; or
+
+    e) Declining to grant rights under trademark law for use of some
+    trade names, trademarks, or service marks; or
+
+    f) Requiring indemnification of licensors and authors of that
+    material by anyone who conveys the material (or modified versions of
+    it) with contractual assumptions of liability to the recipient, for
+    any liability that these contractual assumptions directly impose on
+    those licensors and authors.
+
+  All other non-permissive additional terms are considered "further
+restrictions" within the meaning of section 10.  If the Program as you
+received it, or any part of it, contains a notice stating that it is
+governed by this License along with a term that is a further
+restriction, you may remove that term.  If a license document contains
+a further restriction but permits relicensing or conveying under this
+License, you may add to a covered work material governed by the terms
+of that license document, provided that the further restriction does
+not survive such relicensing or conveying.
+
+  If you add terms to a covered work in accord with this section, you
+must place, in the relevant source files, a statement of the
+additional terms that apply to those files, or a notice indicating
+where to find the applicable terms.
+
+  Additional terms, permissive or non-permissive, may be stated in the
+form of a separately written license, or stated as exceptions;
+the above requirements apply either way.
+
+  8. Termination.
+
+  You may not propagate or modify a covered work except as expressly
+provided under this License.  Any attempt otherwise to propagate or
+modify it is void, and will automatically terminate your rights under
+this License (including any patent licenses granted under the third
+paragraph of section 11).
+
+  However, if you cease all violation of this License, then your
+license from a particular copyright holder is reinstated (a)
+provisionally, unless and until the copyright holder explicitly and
+finally terminates your license, and (b) permanently, if the copyright
+holder fails to notify you of the violation by some reasonable means
+prior to 60 days after the cessation.
+
+  Moreover, your license from a particular copyright holder is
+reinstated permanently if the copyright holder notifies you of the
+violation by some reasonable means, this is the first time you have
+received notice of violation of this License (for any work) from that
+copyright holder, and you cure the violation prior to 30 days after
+your receipt of the notice.
+
+  Termination of your rights under this section does not terminate the
+licenses of parties who have received copies or rights from you under
+this License.  If your rights have been terminated and not permanently
+reinstated, you do not qualify to receive new licenses for the same
+material under section 10.
+
+  9. Acceptance Not Required for Having Copies.
+
+  You are not required to accept this License in order to receive or
+run a copy of the Program.  Ancillary propagation of a covered work
+occurring solely as a consequence of using peer-to-peer transmission
+to receive a copy likewise does not require acceptance.  However,
+nothing other than this License grants you permission to propagate or
+modify any covered work.  These actions infringe copyright if you do
+not accept this License.  Therefore, by modifying or propagating a
+covered work, you indicate your acceptance of this License to do so.
+
+  10. Automatic Licensing of Downstream Recipients.
+
+  Each time you convey a covered work, the recipient automatically
+receives a license from the original licensors, to run, modify and
+propagate that work, subject to this License.  You are not responsible
+for enforcing compliance by third parties with this License.
+
+  An "entity transaction" is a transaction transferring control of an
+organization, or substantially all assets of one, or subdividing an
+organization, or merging organizations.  If propagation of a covered
+work results from an entity transaction, each party to that
+transaction who receives a copy of the work also receives whatever
+licenses to the work the party's predecessor in interest had or could
+give under the previous paragraph, plus a right to possession of the
+Corresponding Source of the work from the predecessor in interest, if
+the predecessor has it or can get it with reasonable efforts.
+
+  You may not impose any further restrictions on the exercise of the
+rights granted or affirmed under this License.  For example, you may
+not impose a license fee, royalty, or other charge for exercise of
+rights granted under this License, and you may not initiate litigation
+(including a cross-claim or counterclaim in a lawsuit) alleging that
+any patent claim is infringed by making, using, selling, offering for
+sale, or importing the Program or any portion of it.
+
+  11. Patents.
+
+  A "contributor" is a copyright holder who authorizes use under this
+License of the Program or a work on which the Program is based.  The
+work thus licensed is called the contributor's "contributor version".
+
+  A contributor's "essential patent claims" are all patent claims
+owned or controlled by the contributor, whether already acquired or
+hereafter acquired, that would be infringed by some manner, permitted
+by this License, of making, using, or selling its contributor version,
+but do not include claims that would be infringed only as a
+consequence of further modification of the contributor version.  For
+purposes of this definition, "control" includes the right to grant
+patent sublicenses in a manner consistent with the requirements of
+this License.
+
+  Each contributor grants you a non-exclusive, worldwide, royalty-free
+patent license under the contributor's essential patent claims, to
+make, use, sell, offer for sale, import and otherwise run, modify and
+propagate the contents of its contributor version.
+
+  In the following three paragraphs, a "patent license" is any express
+agreement or commitment, however denominated, not to enforce a patent
+(such as an express permission to practice a patent or covenant not to
+sue for patent infringement).  To "grant" such a patent license to a
+party means to make such an agreement or commitment not to enforce a
+patent against the party.
+
+  If you convey a covered work, knowingly relying on a patent license,
+and the Corresponding Source of the work is not available for anyone
+to copy, free of charge and under the terms of this License, through a
+publicly available network server or other readily accessible means,
+then you must either (1) cause the Corresponding Source to be so
+available, or (2) arrange to deprive yourself of the benefit of the
+patent license for this particular work, or (3) arrange, in a manner
+consistent with the requirements of this License, to extend the patent
+license to downstream recipients.  "Knowingly relying" means you have
+actual knowledge that, but for the patent license, your conveying the
+covered work in a country, or your recipient's use of the covered work
+in a country, would infringe one or more identifiable patents in that
+country that you have reason to believe are valid.
+
+  If, pursuant to or in connection with a single transaction or
+arrangement, you convey, or propagate by procuring conveyance of, a
+covered work, and grant a patent license to some of the parties
+receiving the covered work authorizing them to use, propagate, modify
+or convey a specific copy of the covered work, then the patent license
+you grant is automatically extended to all recipients of the covered
+work and works based on it.
+
+  A patent license is "discriminatory" if it does not include within
+the scope of its coverage, prohibits the exercise of, or is
+conditioned on the non-exercise of one or more of the rights that are
+specifically granted under this License.  You may not convey a covered
+work if you are a party to an arrangement with a third party that is
+in the business of distributing software, under which you make payment
+to the third party based on the extent of your activity of conveying
+the work, and under which the third party grants, to any of the
+parties who would receive the covered work from you, a discriminatory
+patent license (a) in connection with copies of the covered work
+conveyed by you (or copies made from those copies), or (b) primarily
+for and in connection with specific products or compilations that
+contain the covered work, unless you entered into that arrangement,
+or that patent license was granted, prior to 28 March 2007.
+
+  Nothing in this License shall be construed as excluding or limiting
+any implied license or other defenses to infringement that may
+otherwise be available to you under applicable patent law.
+
+  12. No Surrender of Others' Freedom.
+
+  If conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot convey a
+covered work so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you may
+not convey it at all.  For example, if you agree to terms that obligate you
+to collect a royalty for further conveying from those to whom you convey
+the Program, the only way you could satisfy both those terms and this
+License would be to refrain entirely from conveying the Program.
+
+  13. Use with the GNU Affero General Public License.
+
+  Notwithstanding any other provision of this License, you have
+permission to link or combine any covered work with a work licensed
+under version 3 of the GNU Affero General Public License into a single
+combined work, and to convey the resulting work.  The terms of this
+License will continue to apply to the part which is the covered work,
+but the special requirements of the GNU Affero General Public License,
+section 13, concerning interaction through a network will apply to the
+combination as such.
+
+  14. Revised Versions of this License.
+
+  The Free Software Foundation may publish revised and/or new versions of
+the GNU General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+  Each version is given a distinguishing version number.  If the
+Program specifies that a certain numbered version of the GNU General
+Public License "or any later version" applies to it, you have the
+option of following the terms and conditions either of that numbered
+version or of any later version published by the Free Software
+Foundation.  If the Program does not specify a version number of the
+GNU General Public License, you may choose any version ever published
+by the Free Software Foundation.
+
+  If the Program specifies that a proxy can decide which future
+versions of the GNU General Public License can be used, that proxy's
+public statement of acceptance of a version permanently authorizes you
+to choose that version for the Program.
+
+  Later license versions may give you additional or different
+permissions.  However, no additional obligations are imposed on any
+author or copyright holder as a result of your choosing to follow a
+later version.
+
+  15. Disclaimer of Warranty.
+
+  THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
+APPLICABLE LAW.  EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
+HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
+OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
+THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
+IS WITH YOU.  SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
+ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+  16. Limitation of Liability.
+
+  IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
+THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
+GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
+USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
+DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
+PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
+EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGES.
+
+  17. Interpretation of Sections 15 and 16.
+
+  If the disclaimer of warranty and limitation of liability provided
+above cannot be given local legal effect according to their terms,
+reviewing courts shall apply local law that most closely approximates
+an absolute waiver of all civil liability in connection with the
+Program, unless a warranty or assumption of liability accompanies a
+copy of the Program in return for a fee.
+
diff --git a/3rdparty/wiiuse/LICENSE_noncommercial b/3rdparty/wiiuse/LICENSE_noncommercial
new file mode 100644
index 0000000..7efed89
--- /dev/null
+++ b/3rdparty/wiiuse/LICENSE_noncommercial
@@ -0,0 +1,170 @@
+This license can be used for any works that this license defines
+as "derived" or "combined" works that are strictly NON-COMMERCIAL.
+This license prohibits the use of any source or object code
+in works that are PROPRIETARY.
+
+		   GNU LESSER GENERAL PUBLIC LICENSE
+                       Version 3, 29 June 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+
+  This version of the GNU Lesser General Public License incorporates
+the terms and conditions of version 3 of the GNU General Public
+License, supplemented by the additional permissions listed below.
+
+  0. Additional Definitions. 
+
+  As used herein, "this License" refers to version 3 of the GNU Lesser
+General Public License, and the "GNU GPL" refers to version 3 of the GNU
+General Public License.
+
+  "The Library" refers to a covered work governed by this License,
+other than an Application or a Combined Work as defined below.
+
+  An "Application" is any work that makes use of an interface provided
+by the Library, but which is not otherwise based on the Library.
+Defining a subclass of a class defined by the Library is deemed a mode
+of using an interface provided by the Library.
+
+  A "Combined Work" is a work produced by combining or linking an
+Application with the Library.  The particular version of the Library
+with which the Combined Work was made is also called the "Linked
+Version".
+
+  The "Minimal Corresponding Source" for a Combined Work means the
+Corresponding Source for the Combined Work, excluding any source code
+for portions of the Combined Work that, considered in isolation, are
+based on the Application, and not on the Linked Version.
+
+  The "Corresponding Application Code" for a Combined Work means the
+object code and/or source code for the Application, including any data
+and utility programs needed for reproducing the Combined Work from the
+Application, but excluding the System Libraries of the Combined Work.
+
+  1. Exception to Section 3 of the GNU GPL.
+
+  You may convey a covered work under sections 3 and 4 of this License
+without being bound by section 3 of the GNU GPL.
+
+  2. Conveying Modified Versions.
+
+  If you modify a copy of the Library, and, in your modifications, a
+facility refers to a function or data to be supplied by an Application
+that uses the facility (other than as an argument passed when the
+facility is invoked), then you may convey a copy of the modified
+version:
+
+   a) under this License, provided that you make a good faith effort to
+   ensure that, in the event an Application does not supply the
+   function or data, the facility still operates, and performs
+   whatever part of its purpose remains meaningful, or
+
+   b) under the GNU GPL, with none of the additional permissions of
+   this License applicable to that copy.
+
+  3. Object Code Incorporating Material from Library Header Files.
+
+  The object code form of an Application may incorporate material from
+a header file that is part of the Library.  You may convey such object
+code under terms of your choice, provided that, if the incorporated
+material is not limited to numerical parameters, data structure
+layouts and accessors, or small macros, inline functions and templates
+(ten or fewer lines in length), you do both of the following:
+
+   a) Give prominent notice with each copy of the object code that the
+   Library is used in it and that the Library and its use are
+   covered by this License.
+
+   b) Accompany the object code with a copy of the GNU GPL and this license
+   document.
+
+  4. Combined Works.
+
+  You may convey a Combined Work under terms of your choice that,
+taken together, effectively do not restrict modification of the
+portions of the Library contained in the Combined Work and reverse
+engineering for debugging such modifications, if you also do each of
+the following:
+
+   a) Give prominent notice with each copy of the Combined Work that
+   the Library is used in it and that the Library and its use are
+   covered by this License.
+
+   b) Accompany the Combined Work with a copy of the GNU GPL and this license
+   document.
+
+   c) For a Combined Work that displays copyright notices during
+   execution, include the copyright notice for the Library among
+   these notices, as well as a reference directing the user to the
+   copies of the GNU GPL and this license document.
+
+   d) Do one of the following:
+
+       0) Convey the Minimal Corresponding Source under the terms of this
+       License, and the Corresponding Application Code in a form
+       suitable for, and under terms that permit, the user to
+       recombine or relink the Application with a modified version of
+       the Linked Version to produce a modified Combined Work, in the
+       manner specified by section 6 of the GNU GPL for conveying
+       Corresponding Source.
+
+       1) Use a suitable shared library mechanism for linking with the
+       Library.  A suitable mechanism is one that (a) uses at run time
+       a copy of the Library already present on the user's computer
+       system, and (b) will operate properly with a modified version
+       of the Library that is interface-compatible with the Linked
+       Version. 
+
+   e) Provide Installation Information, but only if you would otherwise
+   be required to provide such information under section 6 of the
+   GNU GPL, and only to the extent that such information is
+   necessary to install and execute a modified version of the
+   Combined Work produced by recombining or relinking the
+   Application with a modified version of the Linked Version. (If
+   you use option 4d0, the Installation Information must accompany
+   the Minimal Corresponding Source and Corresponding Application
+   Code. If you use option 4d1, you must provide the Installation
+   Information in the manner specified by section 6 of the GNU GPL
+   for conveying Corresponding Source.)
+
+  5. Combined Libraries.
+
+  You may place library facilities that are a work based on the
+Library side by side in a single library together with other library
+facilities that are not Applications and are not covered by this
+License, and convey such a combined library under terms of your
+choice, if you do both of the following:
+
+   a) Accompany the combined library with a copy of the same work based
+   on the Library, uncombined with any other library facilities,
+   conveyed under the terms of this License.
+
+   b) Give prominent notice with the combined library that part of it
+   is a work based on the Library, and explaining where to find the
+   accompanying uncombined form of the same work.
+
+  6. Revised Versions of the GNU Lesser General Public License.
+
+  The Free Software Foundation may publish revised and/or new versions
+of the GNU Lesser General Public License from time to time. Such new
+versions will be similar in spirit to the present version, but may
+differ in detail to address new problems or concerns.
+
+  Each version is given a distinguishing version number. If the
+Library as you received it specifies that a certain numbered version
+of the GNU Lesser General Public License "or any later version"
+applies to it, you have the option of following the terms and
+conditions either of that published version or of any later version
+published by the Free Software Foundation. If the Library as you
+received it does not specify a version number of the GNU Lesser
+General Public License, you may choose any version of the GNU Lesser
+General Public License ever published by the Free Software Foundation.
+
+  If the Library as you received it specifies that a proxy can decide
+whether future versions of the GNU Lesser General Public License shall
+apply, that proxy's public statement of acceptance of any version is
+permanent authorization for you to choose that version for the
+Library.
diff --git a/3rdparty/wiiuse/README b/3rdparty/wiiuse/README
new file mode 100644
index 0000000..12d9f71
--- /dev/null
+++ b/3rdparty/wiiuse/README
@@ -0,0 +1,155 @@
+---------------------------
+-
+-  README - Wiiuse
+-
+---------------------------
+
+http://wiiuse.net/
+http://wiiuse.sourceforge.net/
+http://sourceforge.net/projects/wiiuse/
+
+---------------------------
+
+ABOUT
+
+	Wiiuse is a library written in C that connects with several Nintendo Wii remotes.
+	Supports motion sensing, IR tracking, nunchuk, classic controller, and the Guitar Hero 3 controller.
+	Single threaded and nonblocking makes a light weight and clean API.
+
+	Distributed under the GPL and LGPL.
+
+
+AUTHORS
+
+	Michael Laforest        < para >
+	Email: < thepara (--AT--) g m a i l [--DOT--] com >
+
+	The following people have contributed patches to wiiuse:
+		- dhewg
+
+
+LICENSE
+
+	There are two licenses for wiiuse.  Please read them carefully before choosing which one
+	you use.  You may of course at any time switch the license you are currently using to
+	the other.
+
+	Briefly, the license options are:
+
+		a) GNU LGPL (modified for non-commercial usage only)
+		b) GNU GPL
+
+	PLEASE READ THE LICENSES!
+
+
+ACKNOWLEDGEMENTS
+
+	http://wiibrew.org/
+		This site and their users have contributed an immense amount of information
+		about the wiimote and its technical details.  I could not have written this program
+		without the vast amounts of reverse engineered information that was researched by them.
+
+	Nintendo
+		Of course Nintendo for designing and manufacturing the Wii and Wii remote.
+
+	BlueZ
+		Easy and intuitive bluetooth stack for Linux.
+
+	Thanks to Brent for letting me borrow his Guitar Hero 3 controller.
+
+
+DISCLAIMER AND WARNINGS
+
+	I am in no way responsible for any damages or effects, intended or not, caused by this program.
+
+	*** WARNING *** WARNING *** WARNING ***
+
+	Be aware that writing to memory may damage or destroy your wiimote or expansions.
+
+	*** WARNING *** WARNING *** WARNING ***
+
+	This program was written using reverse engineered specifications available from wiibrew.org.
+	Therefore the operation of this program may not be entirely correct.
+	Results obtained by using this program may vary.
+
+
+AUDIENCE
+
+	This project is intended for developers who wish to include support for the Nintendo Wii remote
+	with their third party application.  Please be aware that by using this software you are bound
+	to the terms of the GNU GPL.
+
+
+PLATFORMS AND DEPENDENCIES
+
+	Wiiuse currently operates on both Linux and Windows.
+	You will need:
+
+	For Linux:
+		- The kernel must support bluetooth
+		- The BlueZ bluetooth drivers must be installed
+
+	For Windows:
+		- Bluetooth driver (tested with Microsoft's stack with Windows XP SP2)
+		- If compiling, Microsoft Windows Driver Development Kit (DDK)
+
+
+COMPILING
+
+	Linux:
+		You need SDL and OpenGL installed to compile the SDL example.
+
+		# make [target]
+
+		If 'target' is omitted then everything is compiled.
+
+		Where 'target' can be any of the following:
+
+			- wiiuse
+				Compiles libwiiuse.so
+
+			- ex
+				Compiles wiiuse-example
+
+			- sdl-ex
+				Compiles wiiuse-sdl
+
+		Become root.
+
+		# make install
+
+		The above command will only install the binaries that you
+		selected to compile.
+
+		wiiuse.so is installed to /usr/lib
+		wiiuse-example and wiiuse-sdl are installed to /usr/bin
+
+	Windows:
+		A Microsoft Visual C++ 6.0 project file has been included.
+
+		You need the install the Windows DDK (driver development kit)
+		to compile wiiuse. Make sure you include the inc/ and lib/
+		directories from the DDK in your IDE include and library paths.
+		You can download this from here:
+			http://www.microsoft.com/whdc/devtools/ddk/default.mspx
+
+		You need to link the following libraries (already set in the
+		included project file):
+			- Ws2_32.lib
+			- hid.lib
+			- setupapi.lib
+
+
+USING THE LIBRARY IN A THIRD PARTY APPLICATION
+
+	To use the library in your own program you must first compile wiiuse as a module.
+	Include include/wiiuse.h in any file that uses wiiuse.
+
+	For Linux you must link wiiuse.so ( -lwiiuse ).
+	For Windows you must link wiiuse.lib.  When your program runs it will need wiiuse.dll.
+
+
+BUGS
+
+	On Windows using more than one wiimote (usually more than two wiimotes) may cause
+	significant latency.
diff --git a/3rdparty/wiiuse/README.sitplus b/3rdparty/wiiuse/README.sitplus
new file mode 100644
index 0000000..75c12fc
--- /dev/null
+++ b/3rdparty/wiiuse/README.sitplus
@@ -0,0 +1,72 @@
+SITPLUS Wiimote support README
+==============================
+
+This library is the based on the Michael Laforest's (para) 
+wiiuse version 0.12b (http://sourceforge.net/projects/wiiuse/)
+with some additions:
+
+- CMake based build system (cmauri)
+- Motion Plus support based on fWIIne_v0.4 http://sourceforge.net/projects/fwiine/
+- Balance Board support from B. Stultiens http://www.akhphd.au.dk/~bertho/wii/
+
+
+Compilation notes
+=================
+
+Debian GNU/Linux
+-----------------
+
+Library needs:
+	libbluetooth-dev
+	
+Examples needs:
+	freeglut3-dev
+	libgl1-mesa-dev
+	kernel>= 2.6.32
+		
+Windows + Visual C++ 2008
+-------------------------
+
+Library needs:
+	WINDDK
+	
+Examples needs:
+	GLUT installed on WINDDK dir.
+
+CMake tries to find it.
+
+Performance measures
+====================
+
+This test measures the number of loops per second the example performs
+under different working conditions. Screen printf have been suppresed
+
+Windows 7 - Visual C++ 2008 Release build 
+-----------------------------------------
+
+UPS (updates per second)
+
+Wiimote 
+	- Idle - 10 calls per second (basic polling interval, not events)
+	- Accelerometers 
+		- Still. Variable from 0 to ~50 UPS
+		- In motion. ~98 UPS
+	- Motion Plus. ~98 UPS		
+Balance Board. ~68 (error+/- 3) UPS
+
+Debian Lenny - GCC 4.4.4 Release (-O3)
+--------------------------------------
+Wiimote 
+	- Idle (basic polling interval, not events)
+		Original version: 1745 calls per second
+		Modified version: 30 calls per second
+	- Accelerometers 
+		- Still. Variable from 0 to ~90 UPS
+		- In motion. ~98 UPS
+	- Motion Plus. ~98 UPS		
+Balance Board. ~64 (error+/- 3) UPS
+
+Contact
+=======
+
+Cesar Mauri cesar at crea-si dot com
diff --git a/3rdparty/wiiuse/example-sdl/CMakeLists.txt b/3rdparty/wiiuse/example-sdl/CMakeLists.txt
new file mode 100644
index 0000000..a34f51f
--- /dev/null
+++ b/3rdparty/wiiuse/example-sdl/CMakeLists.txt
@@ -0,0 +1,33 @@
+cmake_minimum_required(VERSION 2.6)
+project(example-sdl)
+
+SET (SDL_BUILDING_LIBRARY ON)
+find_package ( SDL REQUIRED )
+find_package ( OpenGL REQUIRED )
+
+#
+# Help to find GLUT on Windows
+#
+
+IF (WIN32)
+	FIND_PATH(GLUT_ROOT_PATH "include/gl/glut.h" PATHS "C:/Program Files/Microsoft SDKs/Windows/v6.0A")
+ 	IF (EXISTS "${GLUT_ROOT_PATH}")
+		IF (NOT EXISTS ${OPENGL_LIBRARY_DIR})
+			SET (OPENGL_LIBRARY_DIR "${GLUT_ROOT_PATH}/lib")
+		ENDIF()
+	ELSE()
+		MESSAGE (FATAL_ERROR " GLUT not found. Please specify GLUT_ROOT_PATH")
+	ENDIF()
+ENDIF(WIN32)
+find_package ( GLUT REQUIRED )
+
+include_directories (${SDL_INCLUDE_DIR})
+include_directories (${OPENGL_INCLUDE_DIR})
+include_directories (${GLUT_INCLUDE_DIR})
+
+ADD_EXECUTABLE (example-sdl WIN32 sdl.c)
+
+TARGET_LINK_LIBRARIES (example-sdl wiiuse)
+TARGET_LINK_LIBRARIES (example-sdl ${SDL_LIBRARY})
+TARGET_LINK_LIBRARIES (example-sdl ${OPENGL_LIBRARIES})
+TARGET_LINK_LIBRARIES (example-sdl ${GLUT_glut_LIBRARY})
diff --git a/3rdparty/wiiuse/example-sdl/sdl.c b/3rdparty/wiiuse/example-sdl/sdl.c
new file mode 100644
index 0000000..06ec2c5
--- /dev/null
+++ b/3rdparty/wiiuse/example-sdl/sdl.c
@@ -0,0 +1,439 @@
+/*
+ *	Written By:
+ *		Michael Laforest	< para >
+ *		Email: < thepara (--AT--) g m a i l [--DOT--] com >
+ *
+ *	Copyright 2006-2007
+ *
+ *	This program is free software; you can redistribute it and/or modify
+ *	it under the terms of the GNU General Public License as published by
+ *	the Free Software Foundation; either version 3 of the License, or
+ *	(at your option) any later version.
+ *
+ *	This program is distributed in the hope that it will be useful,
+ *	but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *	GNU General Public License for more details.
+ *
+ *	You should have received a copy of the GNU General Public License
+ *	along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ *	$Header$
+ */
+
+#include <stdlib.h>
+#include <math.h>
+
+#ifndef WIN32
+	#include <unistd.h>
+	#include <sys/time.h>
+	#include <time.h>
+#else
+	#include <windows.h>
+#endif
+
+#include <GL/gl.h>
+#include <GL/glu.h>
+#include <GL/glut.h>
+#include <SDL.h>
+
+#include <wiiuse.h>
+
+#define PI 3.14159265358979323846
+#define PI_DIV_180 0.017453292519943296
+#define deg PI_DIV_180
+
+#define MAX_WIIMOTES				2
+
+GLint width = 1024, height = 768;
+GLfloat backColor[4] = {1.0,1.0,1.0,1.0};
+
+wiimote** wiimotes = NULL;
+
+int last_dots[4][2] = {{0}};
+int xcoord = 0;
+int ycoord = 0;
+
+#ifdef WIN32
+	DWORD last_render;
+#else
+	struct timeval last_render;
+	int last_sec = 0;
+	int fps = 0;
+#endif
+
+enum render_mode_t {
+	IR = 1,
+	TEAPOT
+};
+enum render_mode_t render_mode = IR;
+
+/* light information */
+struct light_t {
+	GLfloat position[4];
+	GLfloat spotDirection[3];
+	GLfloat ambient[4];
+	GLfloat diffuse[4];
+	GLfloat specular[4];
+	GLfloat spotCutoff;
+	GLfloat spotExponent;
+	GLfloat spotAttenuation[3];  /*  [0] = constant, [1] = linear, [2] = quadratic  */
+};
+struct light_t light = {
+	{ 1.0, 1.0, -2.0, 1.0	},
+	{ -1.0, -1.0, 2.0		},
+	{ 0.0, 0.0, 0.0, 1.0	},
+	{ 1.0, 1.0, 1.0, 1.0	},
+	{ 1.0, 1.0, 1.0, 1.0	},
+	180.0, 0.0,
+	{ 1.0, 0.0, 0.0			}
+};
+
+/* material information */
+struct material_t {
+	GLfloat ambient[4];
+	GLfloat diffuse[4];
+	GLfloat specular[4];
+	GLfloat emission[4];
+	GLfloat shininess;
+};
+struct material_t red_plastic = {
+	{ 0.3, 0.0, 0.0, 1.0 },
+	{ 0.3, 0.0, 0.0, 1.0 },
+	{ 0.8, 0.6, 0.6, 1.0 },
+	{ 0.0, 0.0, 0.0, 1.0 },
+	32.0
+};
+
+
+void handle_event(struct wiimote_t* wm);
+void display();
+void update_light(GLenum l, struct light_t* lptr);
+void set_material(struct material_t* mptr);
+void resize_window(GLint new_width, GLint new_height);
+
+void handle_event(struct wiimote_t* wm) {
+	if (IS_JUST_PRESSED(wm, WIIMOTE_BUTTON_PLUS))
+		wiiuse_motion_sensing(wm, 1);
+	if (IS_JUST_PRESSED(wm, WIIMOTE_BUTTON_MINUS))
+		wiiuse_motion_sensing(wm, 0);
+
+	if (IS_JUST_PRESSED(wm, WIIMOTE_BUTTON_UP))
+		wiiuse_set_ir(wm, 1);
+	if (IS_JUST_PRESSED(wm, WIIMOTE_BUTTON_DOWN))
+		wiiuse_set_ir(wm, 0);
+
+	if (IS_JUST_PRESSED(wm, WIIMOTE_BUTTON_B))
+		wiiuse_toggle_rumble(wm);
+
+	if (IS_JUST_PRESSED(wm, WIIMOTE_BUTTON_ONE)) {
+		int level;
+		WIIUSE_GET_IR_SENSITIVITY(wm, &level);
+		wiiuse_set_ir_sensitivity(wm, level+1);
+	}
+	if (IS_JUST_PRESSED(wm, WIIMOTE_BUTTON_TWO)) {
+		int level;
+		WIIUSE_GET_IR_SENSITIVITY(wm, &level);
+		wiiuse_set_ir_sensitivity(wm, level-1);
+	}
+
+	#if 0
+	if (IS_JUST_PRESSED(wm, WIIMOTE_BUTTON_A)) {
+		if (render_mode == IR)
+			render_mode = TEAPOT;
+		else
+			render_mode = IR;
+		resize_window(width, height);
+	}
+	#endif
+}
+
+#define DRAW_TRIANGLE(x, y, z, s)	do {							\
+										glVertex3f(x, y-s, z);		\
+										glVertex3f(x+s, y+s, z);	\
+										glVertex3f(x-s, y+s, z);	\
+									} while (0)
+
+int can_render() {
+	/* quick fps limit to ~60fps -- not too fancy, could be better */
+	#ifdef WIN32
+		if (GetTickCount() < (last_render + 16))
+			return 0;
+		last_render = GetTickCount();
+		return 1;
+	#else
+		struct timeval now;
+		long elapsed_usec = 0;
+
+		gettimeofday(&now, NULL);
+
+		if (now.tv_usec > 1000000) {
+			now.tv_usec -= 1000000;
+			++now.tv_sec;
+		}
+
+		if (now.tv_sec > last_render.tv_sec)
+			elapsed_usec = ((now.tv_sec - last_render.tv_sec) * 1000000);
+
+		if (now.tv_usec > last_render.tv_usec)
+			elapsed_usec += now.tv_usec - last_render.tv_usec;
+		else
+			elapsed_usec += last_render.tv_usec - now.tv_usec;
+
+		if (time(NULL) > last_sec) {
+			printf("fps: %i\n", fps);
+			fps = 0;
+			last_sec = time(NULL);
+		}
+
+		if (elapsed_usec < 16000)
+			return 0;
+
+		last_render = now;
+		++fps;
+
+		return 1;
+	#endif
+}
+
+void display() {
+	int i, wm;
+	float size = 5;
+
+	if (!can_render())
+		return;
+
+	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+	glMatrixMode(GL_MODELVIEW);
+	glLoadIdentity();
+
+	if (render_mode == IR) {
+		/* draw the IR stuff */
+
+		glDisable(GL_LIGHTING);
+
+		glBegin(GL_TRIANGLES);
+			/* green center */
+			glColor3f(0.0, 1.0, 0.0);
+			DRAW_TRIANGLE(width/2, height/2, 0, size);
+		glEnd();
+
+		for (wm = 0; wm < MAX_WIIMOTES; ++wm) {
+			glBegin(GL_TRIANGLES);
+				/* red ir */
+				glColor3f(1.0, 0.0, 0.0);
+				for (i = 0; i < 4; ++i) {
+					if (wiimotes[wm]->ir.dot[i].visible)
+						DRAW_TRIANGLE(wiimotes[wm]->ir.dot[i].rx, wiimotes[wm]->ir.dot[i].ry, 0, size);
+				}
+
+				/* yellow corrected ir */
+				glColor3f(1.0, 1.0, 0.0);
+				for (i = 0; i < 4; ++i) {
+					if (wiimotes[wm]->ir.dot[i].visible)
+						DRAW_TRIANGLE(wiimotes[wm]->ir.dot[i].x, wiimotes[wm]->ir.dot[i].y, 0, size);
+				}
+
+				/* blue cursor */
+				glColor3f(0.0, 0.0, 1.0);
+				DRAW_TRIANGLE(wiimotes[wm]->ir.x, wiimotes[wm]->ir.y-size, 0, size);
+			glEnd();
+		}
+	} else {
+		/* draw the teapot */
+		gluLookAt(0.0, 0.0, -5.0,
+				  0.0, 0.0, 0.0,
+				  0.0, 1.0, 0.0);
+
+		glEnable(GL_LIGHTING);
+		glEnable(GL_LIGHT0);
+		update_light(GL_LIGHT0, &light);
+		set_material(&red_plastic);
+
+		glRotatef(wiimotes[0]->orient.roll, 0.0f, 0.0f, 1.0f);
+		glRotatef(wiimotes[0]->orient.pitch, 1.0f, 0.0f, 0.0f);
+
+
+		glutSolidTeapot(1);
+	}
+
+	SDL_GL_SwapBuffers();
+}
+
+
+void update_light(GLenum l, struct light_t* lptr) {
+	glLightfv(l, GL_POSITION, lptr->position);
+	glLightfv(l, GL_DIFFUSE, lptr->diffuse);
+	glLightfv(l, GL_SPECULAR, lptr->specular);
+	glLightfv(l, GL_AMBIENT, lptr->ambient);
+	glLightfv(l, GL_SPOT_DIRECTION, lptr->spotDirection);
+	glLightf(l, GL_SPOT_CUTOFF, lptr->spotCutoff);
+	glLightf(l, GL_SPOT_EXPONENT, lptr->spotExponent);
+	glLightf(l, GL_CONSTANT_ATTENUATION, lptr->spotAttenuation[0]);
+	glLightf(l, GL_LINEAR_ATTENUATION, lptr->spotAttenuation[1]);
+	glLightf(l, GL_QUADRATIC_ATTENUATION, lptr->spotAttenuation[2]);
+}
+
+
+void set_material(struct material_t* mptr) {
+	glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, mptr->ambient);
+	glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mptr->diffuse);
+	glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, mptr->specular);
+	glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, mptr->shininess);
+	glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, mptr->emission);
+}
+
+
+void resize_window(GLint new_width, GLint new_height) {
+	int wm;
+
+	width = new_width;
+	height = new_height;
+
+	if (new_height == 0)
+		new_height = 1;
+
+	SDL_SetVideoMode(width, height, 16, SDL_RESIZABLE | SDL_OPENGL);
+
+	glViewport(0, 0, new_width, new_height);
+
+	glMatrixMode(GL_PROJECTION);
+	glLoadIdentity();
+
+	if (render_mode == IR)
+		gluOrtho2D(0, width, height, 0);
+	else
+		gluPerspective(60.0f, (float)new_width/(float)new_height, 0.1f, 100.0f);
+
+	glMatrixMode(GL_MODELVIEW);
+	glLoadIdentity();
+
+	width = new_width;
+	height = new_height;
+
+	for (wm = 0; wm < MAX_WIIMOTES; ++wm)
+		wiiuse_set_ir_vres(wiimotes[wm], width, height);
+}
+
+#ifndef WIN32
+int main(int argc, char** argv) {
+#else
+int WINAPI WinMain(HINSTANCE hInstance,	HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) {
+#endif
+	int found, connected;
+	int wm;
+
+	//printf("wiiuse version = %s\n", wiiuse_version());
+
+	wiimotes =  wiiuse_init(MAX_WIIMOTES);
+	found = wiiuse_find(wiimotes, MAX_WIIMOTES, 5);
+	if (!found)
+		return 0;
+	connected = wiiuse_connect(wiimotes, MAX_WIIMOTES);
+	if (connected)
+		printf("Connected to %i wiimotes (of %i found).\n", connected, found);
+	else {
+		printf("Failed to connect to any wiimote.\n");
+		return 0;
+	}
+	wiiuse_set_leds(wiimotes[0], WIIMOTE_LED_1 | WIIMOTE_LED_4);
+	wiiuse_set_leds(wiimotes[1], WIIMOTE_LED_2 | WIIMOTE_LED_4);
+	wiiuse_rumble(wiimotes[0], 1);
+
+	#ifndef WIN32
+		usleep(200000);
+	#else
+		Sleep(200);
+	#endif
+
+	wiiuse_rumble(wiimotes[0], 0);
+
+	/* enable IR and motion sensing for all wiimotes */
+	for (wm = 0; wm < MAX_WIIMOTES; ++wm) {
+		wiiuse_motion_sensing(wiimotes[wm], 1);
+		wiiuse_set_ir(wiimotes[wm], 1);
+	}
+
+	if (SDL_Init(SDL_INIT_VIDEO) < 0) {
+		printf("Failed to initialize SDL: %s\n", SDL_GetError());
+		return 0;
+	}
+
+	SDL_WM_SetCaption("wiiuse SDL IR Example", "wiiuse SDL IR Example");
+
+	SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
+	SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 16);
+
+	/* set window size */
+	width = wiimotes[0]->ir.vres[0];
+	height = wiimotes[0]->ir.vres[1];
+	SDL_SetVideoMode(width, height, 16, SDL_RESIZABLE | SDL_OPENGL);
+
+	for (wm = 0; wm < MAX_WIIMOTES; ++wm)
+		wiiuse_set_ir_vres(wiimotes[wm], width, height);
+
+	/* set OpenGL stuff */
+	glEnable(GL_DEPTH_TEST);
+    glEnable(GL_LIGHTING);
+	glEnable(GL_NORMALIZE);
+	glEnable(GL_BLEND);
+
+	glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+    glDepthFunc(GL_LEQUAL);
+    glClearColor(0, 0, 0, 0);
+
+	/* set the size of the window */
+	resize_window(width, height);
+
+	display();
+
+	#ifdef WIN32
+		last_render = GetTickCount();
+	#endif
+
+	while (1) {
+		SDL_Event event;
+
+		if (SDL_PollEvent(&event)) {
+			switch (event.type) {
+				case SDL_VIDEORESIZE:
+				{
+					/* resize the window */
+					resize_window(event.resize.w, event.resize.h);
+					break;
+				}
+				case SDL_QUIT:
+				{
+					/* shutdown */
+					SDL_Quit();
+					wiiuse_cleanup(wiimotes, MAX_WIIMOTES);
+					return 0;
+				}
+				default:
+				{
+				}
+			}
+		}
+
+		if (wiiuse_poll(wiimotes, MAX_WIIMOTES)) {
+			/*
+			 *	This happens if something happened on any wiimote.
+			 *	So go through each one and check if anything happened.
+			 */
+			int i = 0;
+			for (; i < MAX_WIIMOTES; ++i) {
+				switch (wiimotes[i]->event) {
+					case WIIUSE_EVENT:
+						/* a generic event occured */
+						handle_event(wiimotes[i]);
+						break;
+
+					default:
+						break;
+				}
+			}
+		}
+
+		display();
+	}
+}
diff --git a/3rdparty/wiiuse/example/CMakeLists.txt b/3rdparty/wiiuse/example/CMakeLists.txt
new file mode 100644
index 0000000..70b2e11
--- /dev/null
+++ b/3rdparty/wiiuse/example/CMakeLists.txt
@@ -0,0 +1,5 @@
+cmake_minimum_required(VERSION 2.6)
+project(wiiuse_example)
+
+ADD_EXECUTABLE(example example.c)
+TARGET_LINK_LIBRARIES(example wiiuse)
\ No newline at end of file
diff --git a/3rdparty/wiiuse/example/example.c b/3rdparty/wiiuse/example/example.c
new file mode 100644
index 0000000..354e8c0
--- /dev/null
+++ b/3rdparty/wiiuse/example/example.c
@@ -0,0 +1,546 @@
+/*
+ *	wiiuse
+ *
+ *	Written By:
+ *		Michael Laforest	< para >
+ *		Email: < thepara (--AT--) g m a i l [--DOT--] com >
+ *
+ *	Copyright 2006-2007
+ *
+ *	This file is part of wiiuse.
+ *
+ *	This program is free software; you can redistribute it and/or modify
+ *	it under the terms of the GNU General Public License as published by
+ *	the Free Software Foundation; either version 3 of the License, or
+ *	(at your option) any later version.
+ *
+ *	This program is distributed in the hope that it will be useful,
+ *	but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *	GNU General Public License for more details.
+ *
+ *	You should have received a copy of the GNU General Public License
+ *	along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ *	$Header$
+ *
+ */
+
+/**
+ *	@file
+ *
+ *	@brief Example using the wiiuse API.
+ *
+ *	This file is an example of how to use the wiiuse library.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#define _USE_MATH_DEFINES
+#include <math.h>
+#ifndef WIN32
+	#include <unistd.h>
+	#include <sys/time.h>
+#endif
+
+#include "wiiuse.h"
+
+
+#define MAX_WIIMOTES				4
+
+
+unsigned long get_mili_count()
+{
+#if defined(WIN32)
+	// Windows
+	return GetTickCount();
+#else
+	// Linux
+	struct timeval tv;
+	//struct timezone tz;
+	gettimeofday(&tv, NULL); //&tz);
+
+	return (((unsigned long) tv.tv_sec * 1000000 + (unsigned long) tv.tv_usec) / 1000);
+#endif	
+}
+
+/**
+ *	@brief Each second (aprox.) prints the number of calls made to this function
+ *
+ */
+void calls_per_second()
+{
+	static unsigned int call_count= 0;
+	static unsigned long prev_tstamp= 0;
+	unsigned long tstamp = get_mili_count();
+
+	++call_count;
+
+	if (!prev_tstamp) {
+		prev_tstamp= tstamp;
+		return;
+	}
+
+	if (tstamp - prev_tstamp>= 1000) {
+		printf ("call per second: %.2f\n", (float) (call_count * 1000) / (float) (tstamp - prev_tstamp) );
+		call_count= 0;
+		prev_tstamp= tstamp;
+	}	
+}
+
+
+/**
+ *	@brief Callback that handles an event.
+ *
+ *	@param wm		Pointer to a wiimote_t structure.
+ *
+ *	This function is called automatically by the wiiuse library when an
+ *	event occurs on the specified wiimote.
+ */
+void handle_event(struct wiimote_t* wm) {
+	//if (wm->exp.type != EXP_BALANCE_BOARD)
+	//	printf("\n\n--- EVENT [id %i] ---\n", wm->unid);
+	//else
+	//	printf("\n\n--- EVENT BB [id %i] ---\n", wm->unid);
+
+	/* if a button is pressed, report it */
+	if (IS_PRESSED(wm, WIIMOTE_BUTTON_A))		printf("A pressed\n");
+	if (IS_PRESSED(wm, WIIMOTE_BUTTON_B))		printf("B pressed\n");
+	if (IS_PRESSED(wm, WIIMOTE_BUTTON_UP))		printf("UP pressed\n");
+	if (IS_PRESSED(wm, WIIMOTE_BUTTON_DOWN))	printf("DOWN pressed\n");
+	if (IS_PRESSED(wm, WIIMOTE_BUTTON_LEFT))	printf("LEFT pressed\n");
+	if (IS_PRESSED(wm, WIIMOTE_BUTTON_RIGHT))	printf("RIGHT pressed\n");
+	if (IS_PRESSED(wm, WIIMOTE_BUTTON_MINUS))	printf("MINUS pressed\n");
+	if (IS_PRESSED(wm, WIIMOTE_BUTTON_PLUS))	printf("PLUS pressed\n");
+	if (IS_PRESSED(wm, WIIMOTE_BUTTON_ONE))		printf("ONE pressed\n");
+	if (IS_PRESSED(wm, WIIMOTE_BUTTON_TWO))		printf("TWO pressed\n");
+	if (IS_PRESSED(wm, WIIMOTE_BUTTON_HOME))	printf("HOME pressed\n");
+
+	/*
+	 *	Pressing minus will tell the wiimote we are no longer interested in movement.
+	 *	This is useful because it saves battery power.
+	 */
+	if (IS_JUST_PRESSED(wm, WIIMOTE_BUTTON_MINUS))
+		wiiuse_motion_sensing(wm, 0);
+
+	/*
+	 *	Pressing plus will tell the wiimote we are interested in movement.
+	 */
+	if (IS_JUST_PRESSED(wm, WIIMOTE_BUTTON_PLUS))
+		wiiuse_motion_sensing(wm, 1);
+
+	/*
+	 *	Pressing B will toggle the rumble
+	 *
+	 *	if B is pressed but is not held, toggle the rumble
+	 */
+	if (IS_JUST_PRESSED(wm, WIIMOTE_BUTTON_B))
+		wiiuse_toggle_rumble(wm);
+
+	if (IS_JUST_PRESSED(wm, WIIMOTE_BUTTON_UP))
+		wiiuse_set_ir(wm, 1);
+	if (IS_JUST_PRESSED(wm, WIIMOTE_BUTTON_DOWN))
+		wiiuse_set_ir(wm, 0);
+	/* motion plus test begin */
+	if (IS_JUST_PRESSED(wm, WIIMOTE_BUTTON_ONE))
+		wiiuse_set_motion_plus(wm, 1);
+	if (IS_JUST_PRESSED(wm, WIIMOTE_BUTTON_TWO))
+		wiiuse_set_motion_plus(wm, 0);
+	
+
+	/* motion plus test end */
+	/* if the accelerometer is turned on then print angles */
+	if (WIIUSE_USING_ACC(wm)) {
+		printf("wiimote roll  = %f [%f]\n", wm->orient.roll, wm->orient.a_roll);
+		printf("wiimote pitch = %f [%f]\n", wm->orient.pitch, wm->orient.a_pitch);
+		printf("wiimote yaw   = %f\n", wm->orient.yaw);
+	}
+
+	/*
+	 *	If IR tracking is enabled then print the coordinates
+	 *	on the virtual screen that the wiimote is pointing to.
+	 *
+	 *	Also make sure that we see at least 1 dot.
+	 */
+	if (WIIUSE_USING_IR(wm)) {
+		int i = 0;
+
+		/* go through each of the 4 possible IR sources */
+		for (; i < 4; ++i) {
+			/* check if the source is visible */
+			if (wm->ir.dot[i].visible)
+				printf("IR source %i: (%u, %u)\n", i, wm->ir.dot[i].x, wm->ir.dot[i].y);
+		}
+
+		printf("IR cursor: (%u, %u)\n", wm->ir.x, wm->ir.y);
+		printf("IR z distance: %f\n", wm->ir.z);
+	}
+
+	/* show events specific to supported expansions */
+	if (wm->exp.type == EXP_NUNCHUK) {
+		/* nunchuk */
+		struct nunchuk_t* nc = (nunchuk_t*)&wm->exp.nunchuk;
+
+		if (IS_PRESSED(nc, NUNCHUK_BUTTON_C))		printf("Nunchuk: C pressed\n");
+		if (IS_PRESSED(nc, NUNCHUK_BUTTON_Z))		printf("Nunchuk: Z pressed\n");
+
+		printf("nunchuk roll  = %f\n", nc->orient.roll);
+		printf("nunchuk pitch = %f\n", nc->orient.pitch);
+		printf("nunchuk yaw   = %f\n", nc->orient.yaw);
+
+		printf("nunchuk joystick angle:     %f\n", nc->js.ang);
+		printf("nunchuk joystick magnitude: %f\n", nc->js.mag);
+	} else if (wm->exp.type == EXP_CLASSIC) {
+		/* classic controller */
+		struct classic_ctrl_t* cc = (classic_ctrl_t*)&wm->exp.classic;
+
+		if (IS_PRESSED(cc, CLASSIC_CTRL_BUTTON_ZL))			printf("Classic: ZL pressed\n");
+		if (IS_PRESSED(cc, CLASSIC_CTRL_BUTTON_B))			printf("Classic: B pressed\n");
+		if (IS_PRESSED(cc, CLASSIC_CTRL_BUTTON_Y))			printf("Classic: Y pressed\n");
+		if (IS_PRESSED(cc, CLASSIC_CTRL_BUTTON_A))			printf("Classic: A pressed\n");
+		if (IS_PRESSED(cc, CLASSIC_CTRL_BUTTON_X))			printf("Classic: X pressed\n");
+		if (IS_PRESSED(cc, CLASSIC_CTRL_BUTTON_ZR))			printf("Classic: ZR pressed\n");
+		if (IS_PRESSED(cc, CLASSIC_CTRL_BUTTON_LEFT))		printf("Classic: LEFT pressed\n");
+		if (IS_PRESSED(cc, CLASSIC_CTRL_BUTTON_UP))			printf("Classic: UP pressed\n");
+		if (IS_PRESSED(cc, CLASSIC_CTRL_BUTTON_RIGHT))		printf("Classic: RIGHT pressed\n");
+		if (IS_PRESSED(cc, CLASSIC_CTRL_BUTTON_DOWN))		printf("Classic: DOWN pressed\n");
+		if (IS_PRESSED(cc, CLASSIC_CTRL_BUTTON_FULL_L))		printf("Classic: FULL L pressed\n");
+		if (IS_PRESSED(cc, CLASSIC_CTRL_BUTTON_MINUS))		printf("Classic: MINUS pressed\n");
+		if (IS_PRESSED(cc, CLASSIC_CTRL_BUTTON_HOME))		printf("Classic: HOME pressed\n");
+		if (IS_PRESSED(cc, CLASSIC_CTRL_BUTTON_PLUS))		printf("Classic: PLUS pressed\n");
+		if (IS_PRESSED(cc, CLASSIC_CTRL_BUTTON_FULL_R))		printf("Classic: FULL R pressed\n");
+
+		printf("classic L button pressed:         %f\n", cc->l_shoulder);
+		printf("classic R button pressed:         %f\n", cc->r_shoulder);
+		printf("classic left joystick angle:      %f\n", cc->ljs.ang);
+		printf("classic left joystick magnitude:  %f\n", cc->ljs.mag);
+		printf("classic right joystick angle:     %f\n", cc->rjs.ang);
+		printf("classic right joystick magnitude: %f\n", cc->rjs.mag);
+	} else if (wm->exp.type == EXP_GUITAR_HERO_3) {
+		/* guitar hero 3 guitar */
+		struct guitar_hero_3_t* gh3 = (guitar_hero_3_t*)&wm->exp.gh3;
+
+		if (IS_PRESSED(gh3, GUITAR_HERO_3_BUTTON_STRUM_UP))		printf("Guitar: Strum Up pressed\n");
+		if (IS_PRESSED(gh3, GUITAR_HERO_3_BUTTON_STRUM_DOWN))	printf("Guitar: Strum Down pressed\n");
+		if (IS_PRESSED(gh3, GUITAR_HERO_3_BUTTON_YELLOW))		printf("Guitar: Yellow pressed\n");
+		if (IS_PRESSED(gh3, GUITAR_HERO_3_BUTTON_GREEN))		printf("Guitar: Green pressed\n");
+		if (IS_PRESSED(gh3, GUITAR_HERO_3_BUTTON_BLUE))			printf("Guitar: Blue pressed\n");
+		if (IS_PRESSED(gh3, GUITAR_HERO_3_BUTTON_RED))			printf("Guitar: Red pressed\n");
+		if (IS_PRESSED(gh3, GUITAR_HERO_3_BUTTON_ORANGE))		printf("Guitar: Orange pressed\n");
+		if (IS_PRESSED(gh3, GUITAR_HERO_3_BUTTON_PLUS))			printf("Guitar: Plus pressed\n");
+		if (IS_PRESSED(gh3, GUITAR_HERO_3_BUTTON_MINUS))		printf("Guitar: Minus pressed\n");
+
+		printf("Guitar whammy bar:          %f\n", gh3->whammy_bar);
+		printf("Guitar joystick angle:      %f\n", gh3->js.ang);
+		printf("Guitar joystick magnitude:  %f\n", gh3->js.mag);
+	} else if (wm->exp.type == EXP_MOTION_PLUS) {
+		/* motion plus */
+		struct motion_plus_t* mp = (motion_plus_t*)&wm->exp.mp;
+		//printf("drx: %u\t dry: %u\t drz: %u\n", mp->rx, mp->ry, mp->rz);
+		printf("sx: %.2f\t sy: %.2f\t sz: %.2f\t status: %x\n", mp->sx, mp->sy, mp->sz, mp->status);
+		//printf("ext   = %u\n", mp->ext);
+		//printf("byte_status   = %f\n", mp->status);
+	} else if (wm->exp.type == EXP_BALANCE_BOARD) {
+		static int first = 1;
+		const struct balance_board_t *bb = &wm->exp.bb;
+		float total = bb->tr + bb->tl + bb->br + bb->bl;
+		//float x = ((bb->tr + bb->br) - (bb->tl + bb->bl));
+		//float y = ((bb->tl + bb->tr) - (bb->bl + bb->br));
+		//float a = atan2f(y, x) / M_PI * 180.0f;
+
+		/*
+		 * Board orientation:
+		 * +---------------------+
+		 * | tl               tr |
+		 * |        y            |
+		 * |        ^            |
+		 * |        |            |
+		 * |        +----> x     |
+		 * | bl               br |
+		 * +---------vvv---------+
+		 *           Button-A (power)
+		 */
+		if(first) {
+			printf("  tr    br    tl    bl  |   x     y    |v|   ang\n");
+			first = 0;
+		}
+		/* printf("% 5.1f % 5.1f % 5.1f % 5.1f | % 5.1f %5.1f % 5.1f % 6.1f\r", bb->tr, bb->br, bb->tl, bb->bl, x, y, total, a); */		
+		printf("-------------------------------\n");
+		printf("% 5.1f % 5.1f \n", bb->tl, bb->tr);
+		printf("% 5.1f % 5.1f \n", bb->bl, bb->br);
+		printf("\tTOTAL % 5.1f Kg\n", total);
+		printf("-------------------------------\n");
+	}
+}
+
+
+/**
+ *	@brief Callback that handles a read event.
+ *
+ *	@param wm		Pointer to a wiimote_t structure.
+ *	@param data		Pointer to the filled data block.
+ *	@param len		Length in bytes of the data block.
+ *
+ *	This function is called automatically by the wiiuse library when
+ *	the wiimote has returned the full data requested by a previous
+ *	call to wiiuse_read_data().
+ *
+ *	You can read data on the wiimote, such as Mii data, if
+ *	you know the offset address and the length.
+ *
+ *	The \a data pointer was specified on the call to wiiuse_read_data().
+ *	At the time of this function being called, it is not safe to deallocate
+ *	this buffer.
+ */
+void handle_read(struct wiimote_t* wm, byte* data, unsigned short len) {
+	int i = 0;
+
+	printf("\n\n--- DATA READ [wiimote id %i] ---\n", wm->unid);
+	printf("finished read of size %i\n", len);
+	for (; i < len; ++i) {
+		if (!(i%16))
+			printf("\n");
+		printf("%x ", data[i]);
+	}
+	printf("\n\n");
+}
+
+
+/**
+ *	@brief Callback that handles a controller status event.
+ *
+ *	@param wm				Pointer to a wiimote_t structure.
+ *	@param attachment		Is there an attachment? (1 for yes, 0 for no)
+ *	@param speaker			Is the speaker enabled? (1 for yes, 0 for no)
+ *	@param ir				Is the IR support enabled? (1 for yes, 0 for no)
+ *	@param led				What LEDs are lit.
+ *	@param battery_level	Battery level, between 0.0 (0%) and 1.0 (100%).
+ *
+ *	This occurs when either the controller status changed
+ *	or the controller status was requested explicitly by
+ *	wiiuse_status().
+ *
+ *	One reason the status can change is if the nunchuk was
+ *	inserted or removed from the expansion port.
+ */
+void handle_ctrl_status(struct wiimote_t* wm) {
+	printf("\n\n--- CONTROLLER STATUS [wiimote id %i] ---\n", wm->unid);
+
+	printf("attachment:      %i\n", wm->exp.type);
+	printf("speaker:         %i\n", WIIUSE_USING_SPEAKER(wm));
+	printf("ir:              %i\n", WIIUSE_USING_IR(wm));
+	printf("leds:            %i %i %i %i\n", WIIUSE_IS_LED_SET(wm, 1), WIIUSE_IS_LED_SET(wm, 2), WIIUSE_IS_LED_SET(wm, 3), WIIUSE_IS_LED_SET(wm, 4));
+	printf("battery:         %f %%\n", wm->battery_level);
+}
+
+
+/**
+ *	@brief Callback that handles a disconnection event.
+ *
+ *	@param wm				Pointer to a wiimote_t structure.
+ *
+ *	This can happen if the POWER button is pressed, or
+ *	if the connection is interrupted.
+ */
+void handle_disconnect(wiimote* wm) {
+	printf("\n\n--- DISCONNECTED [wiimote id %i] ---\n", wm->unid);
+}
+
+
+void test(struct wiimote_t* wm, byte* data, unsigned short len) {
+	printf("test: %i [%x %x %x %x]\n", len, data[0], data[1], data[2], data[3]);
+}
+
+
+
+/**
+ *	@brief main()
+ *
+ *	Connect to up to two wiimotes and print any events
+ *	that occur on either device.
+ */
+int old_main(int argc, char** argv) {
+	wiimote** wiimotes;
+	int found, connected;
+
+	/*
+	 *	Initialize an array of wiimote objects.
+	 *
+	 *	The parameter is the number of wiimotes I want to create.
+	 */
+	wiimotes =  wiiuse_init(MAX_WIIMOTES);
+
+	/*
+	 *	Find wiimote devices
+	 *
+	 *	Now we need to find some wiimotes.
+	 *	Give the function the wiimote array we created, and tell it there
+	 *	are MAX_WIIMOTES wiimotes we are interested in.
+	 *
+	 *	Set the timeout to be 5 seconds.
+	 *
+	 *	This will return the number of actual wiimotes that are in discovery mode.
+	 */
+	found = wiiuse_find(wiimotes, MAX_WIIMOTES, 5);
+	if (!found) {
+		printf ("No wiimotes found.");
+		return 0;
+	}
+
+	/*
+	 *	Connect to the wiimotes
+	 *
+	 *	Now that we found some wiimotes, connect to them.
+	 *	Give the function the wiimote array and the number
+	 *	of wiimote devices we found.
+	 *
+	 *	This will return the number of established connections to the found wiimotes.
+	 */
+	connected = wiiuse_connect(wiimotes, MAX_WIIMOTES);
+	if (connected)
+		printf("Connected to %i wiimotes (of %i found).\n", connected, found);
+	else {
+		printf("Failed to connect to any wiimote.\n");
+		return 0;
+	}
+
+	/*
+	 *	Now set the LEDs and rumble for a second so it's easy
+	 *	to tell which wiimotes are connected (just like the wii does).
+	 */
+	wiiuse_set_leds(wiimotes[0], WIIMOTE_LED_1);
+	wiiuse_set_leds(wiimotes[1], WIIMOTE_LED_2);
+	wiiuse_set_leds(wiimotes[2], WIIMOTE_LED_3);
+	wiiuse_set_leds(wiimotes[3], WIIMOTE_LED_4);
+	wiiuse_rumble(wiimotes[0], 1);
+	wiiuse_rumble(wiimotes[1], 1);
+
+	#ifndef WIN32
+		usleep(200000);
+	#else
+		Sleep(200);
+	#endif
+
+	wiiuse_rumble(wiimotes[0], 0);
+	wiiuse_rumble(wiimotes[1], 0);
+
+	/*
+	 *	Maybe I'm interested in the battery power of the 0th
+	 *	wiimote.  This should be WIIMOTE_ID_1 but to be sure
+	 *	you can get the wiimote assoicated with WIIMOTE_ID_1
+	 *	using the wiiuse_get_by_id() function.
+	 *
+	 *	A status request will return other things too, like
+	 *	if any expansions are plugged into the wiimote or
+	 *	what LEDs are lit.
+	 */
+	//wiiuse_status(wiimotes[0]);
+
+	/*
+	 *	This is the main loop
+	 *
+	 *	wiiuse_poll() needs to be called with the wiimote array
+	 *	and the number of wiimote structures in that array
+	 *	(it doesn't matter if some of those wiimotes are not used
+	 *	or are not connected).
+	 *
+	 *	This function will set the event flag for each wiimote
+	 *	when the wiimote has things to report.
+	 */
+	while (1) {		
+		if (wiiuse_poll(wiimotes, MAX_WIIMOTES)) {
+			/*
+			 *	This happens if something happened on any wiimote.
+			 *	So go through each one and check if anything happened.
+			 */
+			int i = 0;
+			for (; i < MAX_WIIMOTES; ++i) {
+				switch (wiimotes[i]->event) {
+					case WIIUSE_EVENT:
+						/* calls_per_second(); */
+						/* a generic event occured */
+						handle_event(wiimotes[i]);
+						if (IS_PRESSED(wiimotes[i], WIIMOTE_BUTTON_HOME)) goto exit_loop;
+						break;
+
+					case WIIUSE_STATUS:
+						/* a status event occured */
+						handle_ctrl_status(wiimotes[i]);
+						break;
+
+					case WIIUSE_DISCONNECT:
+					case WIIUSE_UNEXPECTED_DISCONNECT:
+						/* the wiimote disconnected */
+						handle_disconnect(wiimotes[i]);
+						break;
+
+					case WIIUSE_READ_DATA:
+						/*
+						 *	Data we requested to read was returned.
+						 *	Take a look at wiimotes[i]->read_req
+						 *	for the data.
+						 */
+						break;
+
+					case WIIUSE_NUNCHUK_INSERTED:
+						/*
+						 *	a nunchuk was inserted
+						 *	This is a good place to set any nunchuk specific
+						 *	threshold values.  By default they are the same
+						 *	as the wiimote.
+						 */
+						 //wiiuse_set_nunchuk_orient_threshold((struct nunchuk_t*)&wiimotes[i]->exp.nunchuk, 90.0f);
+						 //wiiuse_set_nunchuk_accel_threshold((struct nunchuk_t*)&wiimotes[i]->exp.nunchuk, 100);
+						printf("Nunchuk inserted.\n");
+						break;
+
+					case WIIUSE_CLASSIC_CTRL_INSERTED:
+						printf("Classic controller inserted.\n");
+						break;
+
+					case WIIUSE_MOTION_PLUS_ACTIVATED:
+						printf("Motion plus inserted.\n");
+						break;
+
+					case WIIUSE_GUITAR_HERO_3_CTRL_INSERTED:
+						/* some expansion was inserted */
+						handle_ctrl_status(wiimotes[i]);
+						printf("Guitar Hero 3 controller inserted.\n");
+						break;
+					case WIIUSE_BALANCE_BOARD_CTRL_INSERTED:
+						printf("Balance board controller inserted.\n");
+						break;
+
+					case WIIUSE_NUNCHUK_REMOVED:
+					case WIIUSE_CLASSIC_CTRL_REMOVED:
+					case WIIUSE_GUITAR_HERO_3_CTRL_REMOVED:
+					case WIIUSE_MOTION_PLUS_REMOVED:
+					case WIIUSE_BALANCE_BOARD_CTRL_REMOVED:
+						/* some expansion was removed */
+						handle_ctrl_status(wiimotes[i]);
+						printf("An expansion was removed.\n");
+						break;
+
+					default:
+						
+						break;
+				}
+			}
+		}
+	}
+
+	/*
+	 *	Disconnect the wiimotes
+	 */
+exit_loop:
+	wiiuse_cleanup(wiimotes, MAX_WIIMOTES);
+
+	return 0;
+}
+
+int main(int argc, char** argv) {
+//	for(;;) {
+		old_main(argc, argv);
+//	}
+	return 0;
+}
\ No newline at end of file
diff --git a/3rdparty/wiiuse/include/wiiuse.h b/3rdparty/wiiuse/include/wiiuse.h
new file mode 100755
index 0000000..050fd8d
--- /dev/null
+++ b/3rdparty/wiiuse/include/wiiuse.h
@@ -0,0 +1,805 @@
+/*
+ *	wiiuse
+ *
+ *	Written By:
+ *		Michael Laforest	< para >
+ *		Michal Wiedenbauer	< shagkur >
+ *		Dave Murphy			< WinterMute >
+ *		Hector Martin		< marcan >
+ *		William Alozy		< wiill >
+ *
+ *	Copyright 2009
+ *
+ *	This file is part of wiiuse and fWIIne.
+ *
+ *	This program is free software; you can redistribute it and/or modify
+ *	it under the terms of the GNU General Public License as published by
+ *	the Free Software Foundation; either version 3 of the License, or
+ *	(at your option) any later version.
+ *
+ *	This program is distributed in the hope that it will be useful,
+ *	but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *	GNU General Public License for more details.
+ *
+ *	You should have received a copy of the GNU General Public License
+ *	along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ *	$Header$
+ *
+ */
+
+/**
+ *	@file
+ *
+ *	@brief API header file.
+ *
+ *	If this file is included from inside the wiiuse source
+ *	and not from a third party program, then wiimote_internal.h
+ *	is also included which extends this file.
+ */
+
+#ifndef WIIUSE_H_INCLUDED
+#define WIIUSE_H_INCLUDED
+
+#ifdef _WIN32
+	/* windows */
+	#include <windows.h>
+#else
+	/* nix */
+	#include <bluetooth/bluetooth.h>
+#endif
+
+#ifdef WIIUSE_INTERNAL_H_INCLUDED
+	#define WCONST
+#else
+	#define WCONST		const
+#endif
+
+/* led bit masks */
+#define WIIMOTE_LED_NONE				0x00
+#define WIIMOTE_LED_1					0x10
+#define WIIMOTE_LED_2					0x20
+#define WIIMOTE_LED_3					0x40
+#define WIIMOTE_LED_4					0x80
+
+/* button codes */
+#define WIIMOTE_BUTTON_TWO				0x0001
+#define WIIMOTE_BUTTON_ONE				0x0002
+#define WIIMOTE_BUTTON_B				0x0004
+#define WIIMOTE_BUTTON_A				0x0008
+#define WIIMOTE_BUTTON_MINUS			0x0010
+#define WIIMOTE_BUTTON_ZACCEL_BIT6		0x0020
+#define WIIMOTE_BUTTON_ZACCEL_BIT7		0x0040
+#define WIIMOTE_BUTTON_HOME				0x0080
+#define WIIMOTE_BUTTON_LEFT				0x0100
+#define WIIMOTE_BUTTON_RIGHT			0x0200
+#define WIIMOTE_BUTTON_DOWN				0x0400
+#define WIIMOTE_BUTTON_UP				0x0800
+#define WIIMOTE_BUTTON_PLUS				0x1000
+#define WIIMOTE_BUTTON_ZACCEL_BIT4		0x2000
+#define WIIMOTE_BUTTON_ZACCEL_BIT5		0x4000
+#define WIIMOTE_BUTTON_UNKNOWN			0x8000
+#define WIIMOTE_BUTTON_ALL				0x1F9F
+
+/* nunchul button codes */
+#define NUNCHUK_BUTTON_Z				0x01
+#define NUNCHUK_BUTTON_C				0x02
+#define NUNCHUK_BUTTON_ALL				0x03
+
+/* classic controller button codes */
+#define CLASSIC_CTRL_BUTTON_UP			0x0001
+#define CLASSIC_CTRL_BUTTON_LEFT		0x0002
+#define CLASSIC_CTRL_BUTTON_ZR			0x0004
+#define CLASSIC_CTRL_BUTTON_X			0x0008
+#define CLASSIC_CTRL_BUTTON_A			0x0010
+#define CLASSIC_CTRL_BUTTON_Y			0x0020
+#define CLASSIC_CTRL_BUTTON_B			0x0040
+#define CLASSIC_CTRL_BUTTON_ZL			0x0080
+#define CLASSIC_CTRL_BUTTON_FULL_R		0x0200
+#define CLASSIC_CTRL_BUTTON_PLUS		0x0400
+#define CLASSIC_CTRL_BUTTON_HOME		0x0800
+#define CLASSIC_CTRL_BUTTON_MINUS		0x1000
+#define CLASSIC_CTRL_BUTTON_FULL_L		0x2000
+#define CLASSIC_CTRL_BUTTON_DOWN		0x4000
+#define CLASSIC_CTRL_BUTTON_RIGHT		0x8000
+#define CLASSIC_CTRL_BUTTON_ALL			0xFEFF
+
+/* guitar hero 3 button codes */
+#define GUITAR_HERO_3_BUTTON_STRUM_UP	0x0001
+#define GUITAR_HERO_3_BUTTON_YELLOW		0x0008
+#define GUITAR_HERO_3_BUTTON_GREEN		0x0010
+#define GUITAR_HERO_3_BUTTON_BLUE		0x0020
+#define GUITAR_HERO_3_BUTTON_RED		0x0040
+#define GUITAR_HERO_3_BUTTON_ORANGE		0x0080
+#define GUITAR_HERO_3_BUTTON_PLUS		0x0400
+#define GUITAR_HERO_3_BUTTON_MINUS		0x1000
+#define GUITAR_HERO_3_BUTTON_STRUM_DOWN	0x4000
+#define GUITAR_HERO_3_BUTTON_ALL		0xFEFF
+
+
+/* wiimote option flags */
+#define WIIUSE_SMOOTHING				0x01
+#define WIIUSE_CONTINUOUS				0x02
+#define WIIUSE_ORIENT_THRESH			0x04
+#define WIIUSE_ACCEL_THRESH				0x04
+#define WIIUSE_IR_THRESH				0x08
+#define WIIUSE_JS_THRESH				0x10
+#define WIIUSE_MP_AUTO_CALIBRATION		0x20
+#define WIIUSE_INIT_FLAGS				WIIUSE_SMOOTHING | WIIUSE_MP_AUTO_CALIBRATION //(WIIUSE_CONTINUOUS| WIIUSE_ORIENT_THRESH)   //(WIIUSE_SMOOTHING | WIIUSE_ORIENT_THRESH)  
+
+#define WIIUSE_ORIENT_PRECISION			100.0f
+
+/* expansion codes */
+#define EXP_NONE						0
+#define EXP_NUNCHUK						1
+#define EXP_CLASSIC						2
+#define EXP_GUITAR_HERO_3				3
+#define EXP_WII_BOARD					4
+#define EXP_BALANCE_BOARD				EXP_WII_BOARD
+#define EXP_MOTION_PLUS					5
+
+/* IR correction types */
+typedef enum ir_position_t {
+	WIIUSE_IR_ABOVE,
+	WIIUSE_IR_BELOW
+} ir_position_t;
+
+/**
+ *	@brief Check if a button is pressed.
+ *	@param dev		Pointer to a wiimote_t or expansion structure.
+ *	@param button	The button you are interested in.
+ *	@return 1 if the button is pressed, 0 if not.
+ */
+#define IS_PRESSED(dev, button)		((dev->btns & button) == button)
+
+/**
+ *	@brief Check if a button is being held.
+ *	@param dev		Pointer to a wiimote_t or expansion structure.
+ *	@param button	The button you are interested in.
+ *	@return 1 if the button is held, 0 if not.
+ */
+#define IS_HELD(dev, button)			((dev->btns_held & button) == button)
+
+/**
+ *	@brief Check if a button is released on this event.					\n\n
+ *			This does not mean the button is not pressed, it means		\n
+ *			this button was just now released.
+ *	@param dev		Pointer to a wiimote_t or expansion structure.
+ *	@param button	The button you are interested in.
+ *	@return 1 if the button is released, 0 if not.
+ *
+ */
+#define IS_RELEASED(dev, button)		((dev->btns_released & button) == button)
+
+/**
+ *	@brief Check if a button has just been pressed this event.
+ *	@param dev		Pointer to a wiimote_t or expansion structure.
+ *	@param button	The button you are interested in.
+ *	@return 1 if the button is pressed, 0 if not.
+ */
+#define IS_JUST_PRESSED(dev, button)	(IS_PRESSED(dev, button) && !IS_HELD(dev, button))
+
+/**
+ *	@brief Return the IR sensitivity level.
+ *	@param wm		Pointer to a wiimote_t structure.
+ *	@param lvl		[out] Pointer to an int that will hold the level setting.
+ *	If no level is set 'lvl' will be set to 0.
+ */
+#define WIIUSE_GET_IR_SENSITIVITY(dev, lvl)								\
+			do {														\
+				if ((wm->state & 0x01000) == 0x01000) 		*lvl = 1;	\
+				else if ((wm->state & 0x02000) == 0x02000) 	*lvl = 2;	\
+				else if ((wm->state & 0x04000) == 0x04000) 	*lvl = 3;	\
+				else if ((wm->state & 0x08000) == 0x08000) 	*lvl = 4;	\
+				else if ((wm->state & 0x10000) == 0x10000) 	*lvl = 5;	\
+				else										*lvl = 0;	\
+			} while (0)
+
+#define WIIUSE_USING_ACC(wm)			((wm->state & 0x00100) == 0x00100)
+#define WIIUSE_USING_EXP(wm)			((wm->state & 0x00200) == 0x00200)
+#define WIIUSE_USING_IR(wm)				((wm->state & 0x00400) == 0x00400)
+#define WIIUSE_USING_SPEAKER(wm)		((wm->state & 0x00800) == 0x00800)
+
+#define WIIUSE_IS_LED_SET(wm, num)		((wm->leds & WIIMOTE_LED_##num) == WIIMOTE_LED_##num)
+
+
+/*
+ *	Largest known payload is 21 bytes.
+ *	Add 2 for the prefix and round up to a power of 2.
+ */
+#define MAX_PAYLOAD			32
+
+/*
+ *	This is left over from an old hack, but it may actually
+ *	be a useful feature to keep so it wasn't removed.
+ */
+#ifdef WIN32
+	#define WIIMOTE_DEFAULT_TIMEOUT		100
+	#define WIIMOTE_EXP_TIMEOUT			100
+#endif
+
+typedef unsigned char byte;
+typedef unsigned char ubyte;
+typedef char sbyte;
+typedef unsigned short uword;
+typedef short sword;
+typedef unsigned int uint;
+typedef char sint;
+
+
+struct wiimote_t;
+struct vec3b_t;
+struct orient_t;
+struct gforce_t;
+
+
+/**
+ *      @brief Callback that handles a read event.
+ *
+ *      @param wm               Pointer to a wiimote_t structure.
+ *      @param data             Pointer to the filled data block.
+ *      @param len              Length in bytes of the data block.
+ *
+ *      @see wiiuse_init()
+ *
+ *      A registered function of this type is called automatically by the wiiuse
+ *      library when the wiimote has returned the full data requested by a previous
+ *      call to wiiuse_read_data().
+ */
+typedef void (*wiiuse_read_cb)(struct wiimote_t* wm, byte* data, unsigned short len);
+
+
+/**
+ *	@struct read_req_t
+ *	@brief Data read request structure.
+ */
+struct read_req_t {
+	wiiuse_read_cb cb;			/**< read data callback											*/
+	byte* buf;					/**< buffer where read data is written							*/
+	unsigned int addr;			/**< the offset that the read started at						*/
+	unsigned short size;		/**< the length of the data read								*/
+	unsigned short wait;		/**< num bytes still needed to finish read						*/
+	byte dirty;					/**< set to 1 if not using callback and needs to be cleaned up	*/
+
+	struct read_req_t* next;	/**< next read request in the queue								*/
+};
+
+/**
+ *      @brief Callback that handles a write event.
+ *
+ *      @param wm               Pointer to a wiimote_t structure.
+ *      @param data             Pointer to the sent data block.
+ *      @param len              Length in bytes of the data block.
+ *
+ *      @see wiiuse_init()
+ *
+ *      A registered function of this type is called automatically by the wiiuse
+ *      library when the wiimote has returned the full data requested by a previous
+ *      call to wiiuse_write_data().
+ */
+typedef void (*wiiuse_write_cb)(struct wiimote_t* wm, ubyte* data, unsigned short len);
+
+typedef enum data_req_s
+{
+	REQ_READY = 0,
+	REQ_SENT,
+	REQ_DONE
+} data_req_s;
+
+/**
+ *	@struct data_req_t
+ *	@brief Data write request structure.
+ */
+struct data_req_t {
+	
+	ubyte data[21];					/**< buffer where read data is written						*/
+	unsigned int len;
+	unsigned int addr;
+	data_req_s state;			/**< set to 1 if not using callback and needs to be cleaned up	*/
+	wiiuse_write_cb cb;			/**< read data callback											*/
+	struct data_req_t *next;
+};
+
+typedef void (*cmd_blk_cb)(struct wiimote_t *wm,ubyte *data,uword len);
+
+typedef enum cmd_blk_s
+{
+	CMD_READY = 0,
+	CMD_SENT,
+	CMD_DONE
+} cmd_blk_s;
+
+struct cmd_blk_t 
+{
+	
+	ubyte data[48];
+	uint len;
+
+	cmd_blk_s state;
+	cmd_blk_cb cb;
+
+	struct cmd_blk_t *next;
+};
+
+/**
+ *	@struct vec2b_t
+ *	@brief Unsigned x,y byte vector.
+ */
+typedef struct vec2b_t {
+	byte x, y;
+} vec2b_t;
+
+
+/**
+ *	@struct vec3b_t
+ *	@brief Unsigned x,y,z byte vector.
+ */
+typedef struct vec3b_t {
+	byte x, y, z;
+} vec3b_t;
+
+/**
+*	@struct vec3w_t
+*	@brief Unsigned x,y,z word vector.
+*/
+typedef struct vec3w_t {
+	uword x, y, z;
+} vec3w_t;
+
+
+/**
+ *	@struct vec3f_t
+ *	@brief Signed x,y,z float struct.
+ */
+typedef struct vec3f_t {
+	float x, y, z;
+} vec3f_t;
+
+
+/**
+ *	@struct orient_t
+ *	@brief Orientation struct.
+ *
+ *	Yaw, pitch, and roll range from -180 to 180 degrees.
+ */
+typedef struct orient_t {
+	float roll;						/**< roll, this may be smoothed if enabled	*/
+	float pitch;					/**< pitch, this may be smoothed if enabled	*/
+	float yaw;
+
+	float a_roll;					/**< absolute roll, unsmoothed				*/
+	float a_pitch;					/**< absolute pitch, unsmoothed				*/
+} orient_t;
+
+
+/**
+ *	@struct gforce_t
+ *	@brief Gravity force struct.
+ */
+typedef struct gforce_t {
+	float x, y, z;
+} gforce_t;
+
+
+/**
+ *	@struct accel_t
+ *	@brief Accelerometer struct. For any device with an accelerometer.
+ */
+typedef struct accel_t {
+	struct vec3w_t cal_zero;		/**< zero calibration					*/
+	struct vec3w_t cal_g;			/**< 1g difference around 0cal			*/
+
+	float st_roll;					/**< last smoothed roll value			*/
+	float st_pitch;					/**< last smoothed roll pitch			*/
+	float st_alpha;					/**< alpha value for smoothing [0-1]	*/
+} accel_t;
+
+
+/**
+ *	@struct ir_dot_t
+ *	@brief A single IR source.
+ */
+typedef struct ir_dot_t {
+	byte visible;					/**< if the IR source is visible		*/
+
+	unsigned int x;					/**< interpolated X coordinate			*/
+	unsigned int y;					/**< interpolated Y coordinate			*/
+
+	short rx;						/**< raw X coordinate (0-1023)			*/
+	short ry;						/**< raw Y coordinate (0-767)			*/
+
+	byte order;						/**< increasing order by x-axis value	*/
+
+	byte size;						/**< size of the IR dot (0-15)			*/
+} ir_dot_t;
+
+
+/**
+ *	@enum aspect_t
+ *	@brief Screen aspect ratio.
+ */
+typedef enum aspect_t {
+	WIIUSE_ASPECT_4_3,
+	WIIUSE_ASPECT_16_9
+} aspect_t;
+
+
+/**
+ *	@struct ir_t
+ *	@brief IR struct. Hold all data related to the IR tracking.
+ */
+typedef struct ir_t {
+	struct ir_dot_t dot[4];			/**< IR dots							*/
+	byte num_dots;					/**< number of dots at this time		*/
+
+	enum aspect_t aspect;			/**< aspect ratio of the screen			*/
+
+	enum ir_position_t pos;			/**< IR sensor bar position				*/
+
+	unsigned int vres[2];			/**< IR virtual screen resolution		*/
+	int offset[2];					/**< IR XY correction offset			*/
+	int state;						/**< keeps track of the IR state		*/
+
+	int ax;							/**< absolute X coordinate				*/
+	int ay;							/**< absolute Y coordinate				*/
+
+	int x;							/**< calculated X coordinate			*/
+	int y;							/**< calculated Y coordinate			*/
+
+	float distance;					/**< pixel distance between first 2 dots*/
+	float z;						/**< calculated distance				*/
+} ir_t;
+
+
+/**
+ *	@struct joystick_t
+ *	@brief Joystick calibration structure.
+ *
+ *	The angle \a ang is relative to the positive y-axis into quadrant I
+ *	and ranges from 0 to 360 degrees.  So if the joystick is held straight
+ *	upwards then angle is 0 degrees.  If it is held to the right it is 90,
+ *	down is 180, and left is 270.
+ *
+ *	The magnitude \a mag is the distance from the center to where the
+ *	joystick is being held.  The magnitude ranges from 0 to 1.
+ *	If the joystick is only slightly tilted from the center the magnitude
+ *	will be low, but if it is closer to the outter edge the value will
+ *	be higher.
+ */
+typedef struct joystick_t {
+	struct vec2b_t max;				/**< maximum joystick values	*/
+	struct vec2b_t min;				/**< minimum joystick values	*/
+	struct vec2b_t center;			/**< center joystick values		*/
+
+	float ang;						/**< angle the joystick is being held		*/
+	float mag;						/**< magnitude of the joystick (range 0-1)	*/
+} joystick_t;
+
+
+/**
+ *	@struct nunchuk_t
+ *	@brief Nunchuk expansion device.
+ */
+typedef struct nunchuk_t {
+	struct accel_t accel_calib;		/**< nunchuk accelerometer calibration		*/
+	struct joystick_t js;			/**< joystick calibration					*/
+
+	int* flags;						/**< options flag (points to wiimote_t.flags) */
+
+	byte btns;						/**< what buttons have just been pressed	*/
+	byte btns_last;				/**< what buttons have just been pressed	*/
+	byte btns_held;				/**< what buttons are being held down		*/
+	byte btns_released;			/**< what buttons were just released this	*/
+	float orient_threshold;			/**< threshold for orient to generate an event */
+	float accel_threshold;	
+	struct vec3w_t accel;			/**< current raw acceleration data			*/
+	struct orient_t orient;			/**< current orientation on each axis		*/
+	struct gforce_t gforce;			/**< current gravity forces on each axis	*/
+} nunchuk_t;
+
+
+/**
+ *	@struct classic_ctrl_t
+ *	@brief Classic controller expansion device.
+ */
+typedef struct classic_ctrl_t {
+	short btns;						/**< what buttons have just been pressed	*/
+	short btns_last;				/**< what buttons have just been pressed	*/
+	short btns_held;				/**< what buttons are being held down		*/
+	short btns_released;			/**< what buttons were just released this	*/
+	ubyte rs_raw;
+	ubyte ls_raw;
+
+	float r_shoulder;				/**< right shoulder button (range 0-1)		*/
+	float l_shoulder;				/**< left shoulder button (range 0-1)		*/
+
+	struct joystick_t ljs;			/**< left joystick calibration				*/
+	struct joystick_t rjs;			/**< right joystick calibration				*/
+} classic_ctrl_t;
+
+
+/**
+ *	@struct guitar_hero_3_t
+ *	@brief Guitar Hero 3 expansion device.
+ */
+typedef struct guitar_hero_3_t {
+	short btns;						/**< what buttons have just been pressed	*/
+	short btns_last;				/**< what buttons have just been pressed	*/
+	short btns_held;				/**< what buttons are being held down		*/
+	short btns_released;			/**< what buttons were just released this	*/
+
+	float whammy_bar;				/**< whammy bar (range 0-1)					*/
+
+	struct joystick_t js;			/**< joystick calibration					*/
+} guitar_hero_3_t;
+
+/**
+ *	@struct motion_plus_t
+ *	@brief Motion Plus expansion device.
+ */
+
+#define MOTION_PLUS_CALIB_BUFF_SIZE 20
+typedef struct motion_plus_t
+{
+	short rx, ry, rz;					/**< motion plus raw values */
+	short rx_zero, ry_zero, rz_zero;	/**< motion plus raw values */
+	float sx, sy, sz;					/**< motion plus values in deg/s */
+	ubyte status;
+	ubyte ext;
+	ubyte calib_buff_count;
+	ubyte calib_buff_index;
+	short rx_hist[MOTION_PLUS_CALIB_BUFF_SIZE];
+	short ry_hist[MOTION_PLUS_CALIB_BUFF_SIZE];
+	short rz_hist[MOTION_PLUS_CALIB_BUFF_SIZE];
+} motion_plus_t;
+
+/**
+ *	@struct balance_board_data_t
+ *	@brief Balance board l/r, t/b corner data data.
+ */
+typedef struct balance_board_data_t {
+	int tr;
+	int br;
+	int tl;
+	int bl;
+} balance_board_data_t;
+
+/**
+ *	@struct balance_board_t
+ *	@brief Balance board expansion device.
+ */
+typedef struct balance_board_t {
+	float tr;		/** Top Right weight */
+	float br;		/** Bottom Right weight */
+	float tl;		/** Top Left weight */
+	float bl;		/** Bottom Left weight */
+	struct balance_board_data_t raw;	/** Raw actual values */
+	struct balance_board_data_t cal_0;	/** Calibration values at 0kg */
+	struct balance_board_data_t cal_17;	/** Calibration values at 17kg */
+	struct balance_board_data_t cal_34;	/** Calibration values at 34kg */
+} balance_board_t;
+
+/**
+ *	@struct expansion_t
+ *	@brief Generic expansion device plugged into wiimote.
+ */
+typedef struct expansion_t {
+	int type;						/**< type of expansion attached				*/
+
+	union {
+		struct nunchuk_t nunchuk;
+		struct classic_ctrl_t classic;
+		struct guitar_hero_3_t gh3;
+		struct motion_plus_t mp;
+		struct balance_board_t bb;
+	};
+} expansion_t;
+
+
+/**
+ *	@enum win32_bt_stack_t
+ *	@brief	Available bluetooth stacks for Windows.
+ */
+typedef enum win_bt_stack_t {
+	WIIUSE_STACK_UNKNOWN,
+	WIIUSE_STACK_MS,
+	WIIUSE_STACK_BLUESOLEIL
+} win_bt_stack_t;
+
+
+/**
+ *	@struct wiimote_state_t
+ *	@brief Significant data from the previous event.
+ */
+typedef struct wiimote_state_t {
+	/* expansion_t */
+	float exp_ljs_ang;
+	float exp_rjs_ang;
+	float exp_ljs_mag;
+	float exp_rjs_mag;
+	unsigned short exp_btns;
+	struct orient_t exp_orient;
+	struct vec3w_t exp_accel;
+	float exp_r_shoulder;
+	float exp_l_shoulder;
+    
+	/* motion_plus_t */
+    short drx;
+	short dry;
+	short drz;
+	
+	struct balance_board_data_t exp_bb_raw;
+
+	/* ir_t */
+	int ir_ax;
+	int ir_ay;
+	float ir_distance;
+
+	struct orient_t orient;
+	unsigned short btns;
+
+	struct vec3w_t accel;
+	struct expansion_t exp;
+} wiimote_state_t;
+
+
+/**
+ *	@enum WIIUSE_EVENT_TYPE
+ *	@brief Events that wiiuse can generate from a poll.
+ */
+typedef enum WIIUSE_EVENT_TYPE {
+	WIIUSE_NONE = 0,
+	WIIUSE_EVENT,
+	WIIUSE_STATUS,
+	WIIUSE_CONNECT,
+	WIIUSE_DISCONNECT,
+	WIIUSE_UNEXPECTED_DISCONNECT,
+	WIIUSE_READ_DATA,
+	WIIUSE_WRITE_DATA,
+	WIIUSE_NUNCHUK_INSERTED,
+	WIIUSE_NUNCHUK_REMOVED,
+	WIIUSE_CLASSIC_CTRL_INSERTED,
+	WIIUSE_CLASSIC_CTRL_REMOVED,
+	WIIUSE_GUITAR_HERO_3_CTRL_INSERTED,
+	WIIUSE_GUITAR_HERO_3_CTRL_REMOVED,
+ 	WIIUSE_MOTION_PLUS_ACTIVATED,
+ 	WIIUSE_MOTION_PLUS_REMOVED,
+	WIIUSE_BALANCE_BOARD_CTRL_INSERTED,
+	WIIUSE_BALANCE_BOARD_CTRL_REMOVED
+} WIIUSE_EVENT_TYPE;
+
+/**
+ *	@struct wiimote_t
+ *	@brief Wiimote structure.
+ */
+typedef struct wiimote_t {
+	WCONST int unid;						/**< user specified id						*/
+
+	#ifndef WIN32
+		WCONST bdaddr_t bdaddr;				/**< bt address								*/
+		WCONST char bdaddr_str[18];			/**< readable bt address					*/
+		WCONST int out_sock;				/**< output socket							*/
+		WCONST int in_sock;					/**< input socket 							*/
+	#else
+		WCONST HANDLE dev_handle;			/**< HID handle								*/
+		WCONST OVERLAPPED hid_overlap;		/**< overlap handle							*/
+		WCONST enum win_bt_stack_t stack;	/**< type of bluetooth stack to use			*/
+		WCONST int timeout;					/**< read timeout							*/
+		WCONST byte normal_timeout;			/**< normal timeout							*/
+		WCONST byte exp_timeout;			/**< timeout for expansion handshake		*/
+	#endif
+
+	WCONST int state;						/**< various state flags					*/
+	WCONST byte leds;						/**< currently lit leds						*/
+	WCONST float battery_level;				/**< battery level							*/
+
+	WCONST int flags;						/**< options flag							*/
+
+	WCONST byte handshake_state;			/**< the state of the connection handshake	*/
+	WCONST ubyte expansion_state;			/**< the state of the expansion handshake	*/
+	WCONST struct read_req_t* read_req;		/**< list of data read requests				*/
+	WCONST struct data_req_t* data_req;		/**< list of data read requests				*/
+	
+	WCONST struct cmd_blk_t *cmd_head;
+	WCONST struct cmd_blk_t *cmd_tail;
+	WCONST struct accel_t accel_calib;		/**< wiimote accelerometer calibration		*/
+	WCONST struct expansion_t exp;			/**< wiimote expansion device				*/
+
+	WCONST struct vec3w_t accel;			/**< current raw acceleration data			*/
+	WCONST struct orient_t orient;			/**< current orientation on each axis		*/
+	WCONST struct gforce_t gforce;			/**< current gravity forces on each axis	*/
+
+	WCONST struct ir_t ir;					/**< IR data								*/
+
+	WCONST unsigned short btns;				/**< what buttons have just been pressed	*/
+	WCONST unsigned short btns_last;		/**< what buttons were down before			*/
+	WCONST unsigned short btns_held;		/**< what buttons are and were held down	*/
+	WCONST unsigned short btns_released;	/**< what buttons were just released		*/
+	WCONST float orient_threshold;			/**< threshold for orient to generate an event */
+	WCONST int accel_threshold;				/**< threshold for accel to generate an event */
+
+	WCONST struct wiimote_state_t lstate;	/**< last saved state						*/
+
+	WCONST WIIUSE_EVENT_TYPE event;			/**< type of event that occured				*/
+	WCONST byte event_buf[MAX_PAYLOAD];		/**< event buffer							*/
+	WCONST ubyte motion_plus_id[6];
+} wiimote;
+
+
+/*****************************************
+ *
+ *	Include API specific stuff
+ *
+ *****************************************/
+
+#ifdef _WIN32
+	#define WIIUSE_EXPORT_DECL __declspec(dllexport)
+	#define WIIUSE_IMPORT_DECL __declspec(dllimport)
+#else
+	#define WIIUSE_EXPORT_DECL
+	#define WIIUSE_IMPORT_DECL
+#endif
+
+#ifdef WIIUSE_COMPILE_LIB
+	#define WIIUSE_EXPORT WIIUSE_EXPORT_DECL
+#else
+	#define WIIUSE_EXPORT WIIUSE_IMPORT_DECL
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* wiiuse.c */
+WIIUSE_EXPORT extern const char* wiiuse_version();
+
+WIIUSE_EXPORT extern struct wiimote_t** wiiuse_init(int wiimotes);
+WIIUSE_EXPORT extern void wiiuse_disconnected(struct wiimote_t* wm);
+WIIUSE_EXPORT extern void wiiuse_cleanup(struct wiimote_t** wm, int wiimotes);
+WIIUSE_EXPORT extern void wiiuse_rumble(struct wiimote_t* wm, int status);
+WIIUSE_EXPORT extern void wiiuse_toggle_rumble(struct wiimote_t* wm);
+WIIUSE_EXPORT extern void wiiuse_set_leds(struct wiimote_t* wm, int leds);
+WIIUSE_EXPORT extern void wiiuse_motion_sensing(struct wiimote_t* wm, int status);
+WIIUSE_EXPORT extern int wiiuse_read_data(struct wiimote_t* wm, byte* buffer, unsigned int offset, unsigned short len);
+WIIUSE_EXPORT extern int wiiuse_write_data(struct wiimote_t* wm, unsigned int addr, byte* data, byte len);
+WIIUSE_EXPORT extern void wiiuse_status(struct wiimote_t* wm);
+WIIUSE_EXPORT extern struct wiimote_t* wiiuse_get_by_id(struct wiimote_t** wm, int wiimotes, int unid);
+WIIUSE_EXPORT extern int wiiuse_set_flags(struct wiimote_t* wm, int enable, int disable);
+WIIUSE_EXPORT extern float wiiuse_set_smooth_alpha(struct wiimote_t* wm, float alpha);
+WIIUSE_EXPORT extern void wiiuse_set_bluetooth_stack(struct wiimote_t** wm, int wiimotes, enum win_bt_stack_t type);
+WIIUSE_EXPORT extern void wiiuse_set_orient_threshold(struct wiimote_t* wm, float threshold);
+WIIUSE_EXPORT extern void wiiuse_resync(struct wiimote_t* wm);
+WIIUSE_EXPORT extern void wiiuse_set_timeout(struct wiimote_t** wm, int wiimotes, byte normal_timeout, byte exp_timeout);
+WIIUSE_EXPORT extern void wiiuse_set_accel_threshold(struct wiimote_t* wm, int threshold);
+
+/* connect.c */
+WIIUSE_EXPORT extern int wiiuse_find(struct wiimote_t** wm, int max_wiimotes, int timeout);
+WIIUSE_EXPORT extern int wiiuse_connect(struct wiimote_t** wm, int wiimotes);
+WIIUSE_EXPORT extern void wiiuse_disconnect(struct wiimote_t* wm);
+
+/* events.c */
+WIIUSE_EXPORT extern int wiiuse_poll(struct wiimote_t** wm, int wiimotes);
+
+/* ir.c */
+WIIUSE_EXPORT extern void wiiuse_set_ir_mode(struct wiimote_t *wm);
+WIIUSE_EXPORT extern void wiiuse_set_ir(struct wiimote_t* wm, int status);
+WIIUSE_EXPORT extern void wiiuse_set_ir_vres(struct wiimote_t* wm, unsigned int x, unsigned int y);
+WIIUSE_EXPORT extern void wiiuse_set_ir_position(struct wiimote_t* wm, enum ir_position_t pos);
+WIIUSE_EXPORT extern void wiiuse_set_aspect_ratio(struct wiimote_t* wm, enum aspect_t aspect);
+WIIUSE_EXPORT extern void wiiuse_set_ir_sensitivity(struct wiimote_t* wm, int level);
+
+/* nunchuk.c */
+WIIUSE_EXPORT extern void wiiuse_set_nunchuk_orient_threshold(struct wiimote_t* wm, float threshold);
+WIIUSE_EXPORT extern void wiiuse_set_nunchuk_accel_threshold(struct wiimote_t* wm, int threshold);
+
+/* motion_plus.c */
+WIIUSE_EXPORT extern void wiiuse_set_motion_plus(struct wiimote_t *wm, int status);
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif /* WIIUSE_H_INCLUDED */
+
diff --git a/3rdparty/wiiuse/src/CMakeLists.txt b/3rdparty/wiiuse/src/CMakeLists.txt
new file mode 100755
index 0000000..38c3237
--- /dev/null
+++ b/3rdparty/wiiuse/src/CMakeLists.txt
@@ -0,0 +1,125 @@
+cmake_minimum_required(VERSION 2.6)
+project(wiiuse)
+
+set(wiiuse_SRCS
+	balance_board.c
+	balance_board.h
+	classic.c
+	classic.h
+	definitions.h
+	dynamics.c
+	dynamics.h
+	events.c
+	events.h
+	guitar_hero_3.c
+	guitar_hero_3.h
+	io.c
+	io.h
+	ir.c
+	ir.h	
+	motion_plus.c
+	motion_plus.h
+	nunchuk.c
+	nunchuk.h
+	os.h
+	wiiuse.c
+	../include/wiiuse.h
+	wiiuse_internal.h
+)
+
+IF(CMAKE_SYSTEM_NAME MATCHES "Linux")
+
+	#
+	# Linux specific files
+	#
+
+	set(wiiuse_SRCS ${wiiuse_SRCS}
+		io_nix.c
+	)
+
+	#
+	# Find bluetooth library
+	#
+
+	FIND_PATH (
+		bluetooth_INCLUDE_DIR
+	  NAMES
+		bluetooth/bluetooth.h
+	  PATHS
+		/usr/include
+		/usr/local/include
+		/opt/local/include
+	)
+
+	FIND_LIBRARY (
+		libbluetooth_LIBRARY 
+	  NAMES
+		bluetooth
+	  PATHS
+		/opt/local/lib
+		/sw/lib
+		/usr/lib
+		/usr/local/lib
+	)
+
+	IF ( NOT (bluetooth_INCLUDE_DIR AND libbluetooth_LIBRARY) )
+		message(FATAL_ERROR " libbluetooth not found")
+	ENDIF()
+
+	INCLUDE_DIRECTORIES (${bluetooth_INCLUDE_DIR})
+
+ELSE()
+	set(wiiuse_SRCS ${wiiuse_SRCS}
+		io_win.c
+	)
+
+	FIND_PATH (
+		winddk_ROOT
+	  NAMES
+		inc/wxp/hidsdi.h
+	  PATHS	
+		"$ENV{DDKROOT}"
+		"$ENV{WINDDK}"	
+		"C:/Program Files/WINDDK/3790.1830"
+	)
+
+	IF ( NOT (winddk_ROOT) OR (${winddk_ROOT} MATCHES ".*NOTFOUND") )
+		message(FATAL_ERROR " WINDDK not found")
+	ENDIF()
+
+	message(STATUS "winddk_ROOT: ${winddk_ROOT}")
+
+	SET (winddk_INCLUDE_DIR "${winddk_ROOT}/inc/wxp")
+	SET (winddk_LIBRARY_DIR "${winddk_ROOT}/lib/wxp/i386")
+
+	INCLUDE_DIRECTORIES(${winddk_INCLUDE_DIR})
+	LINK_DIRECTORIES(${winddk_LIBRARY_DIR})
+
+ENDIF(CMAKE_SYSTEM_NAME MATCHES "Linux")
+
+#
+# Target
+#
+
+add_library (wiiuse SHARED ${wiiuse_SRCS})
+
+IF(CMAKE_SYSTEM_NAME MATCHES "Linux")
+	TARGET_LINK_LIBRARIES(wiiuse bluetooth m)
+ELSEIF(WIN32)
+	TARGET_LINK_LIBRARIES(wiiuse odbc32.lib odbccp32.lib Ws2_32.lib hid.lib setupapi.lib)
+ENDIF(CMAKE_SYSTEM_NAME MATCHES "Linux")
+
+#IF(BUILD_SHARED_LIBS)
+	# Remove transitive dependencies
+	set_target_properties(wiiuse
+      PROPERTIES
+      LINK_INTERFACE_LIBRARIES ""
+	)
+  
+	set_target_properties(wiiuse PROPERTIES 
+		VERSION "${WIIUSE_MAJOR_VERSION}.${WIIUSE_RELEASE_VERSION}.${WIIUSE_EPOCH_VERSION}"
+		SOVERSION ${WIIUSE_MAJOR_VERSION}
+	)
+	
+	INSTALL (TARGETS wiiuse RUNTIME DESTINATION ${LIBRUNTIMEDIR} LIBRARY DESTINATION ${LIBDIR})
+#ENDIF(BUILD_SHARED_LIBS)
diff --git a/3rdparty/wiiuse/src/balance_board.c b/3rdparty/wiiuse/src/balance_board.c
new file mode 100644
index 0000000..8a25cee
--- /dev/null
+++ b/3rdparty/wiiuse/src/balance_board.c
@@ -0,0 +1,139 @@
+/*
+ *	wiiuse
+ *
+ *	Written By:
+ *		Michael Laforest	< para >
+ *		Email: < thepara (--AT--) g m a i l [--DOT--] com >
+ *	This file:
+ *		Bertho Stultiens	< para >
+ *
+ *	Copyright 2009
+ *
+ *	This file is part of wiiuse.
+ *
+ *	This program is free software; you can redistribute it and/or modify
+ *	it under the terms of the GNU General Public License as published by
+ *	the Free Software Foundation; either version 3 of the License, or
+ *	(at your option) any later version.
+ *
+ *	This program is distributed in the hope that it will be useful,
+ *	but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *	GNU General Public License for more details.
+ *
+ *	You should have received a copy of the GNU General Public License
+ *	along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ *	$Header$
+ *
+ */
+
+/**
+ *	@file
+ *	@brief Balance Board expansion device.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <math.h>
+
+#ifdef WIN32
+	#include <Winsock2.h>
+#endif
+
+#include "definitions.h"
+#include "wiiuse_internal.h"
+#include "dynamics.h"
+#include "events.h"
+#include "balance_board.h"
+
+/**
+ *	@brief Handle the handshake data from the guitar.
+ *
+ *	@param cc		A pointer to a classic_ctrl_t structure.
+ *	@param data		The data read in from the device.
+ *	@param len		The length of the data block, in bytes.
+ *
+ *	@return	Returns 1 if handshake was successful, 0 if not.
+ */
+int balance_board_handshake(struct wiimote_t* wm, struct balance_board_t* bb, byte* data, unsigned short len) {
+	int i;
+
+	bb->tr = 0.0;
+	bb->br = 0.0;
+	bb->tl = 0.0;
+	bb->br = 0.0;
+
+	if (len < 0xe0)
+		return 0;
+
+	if (data[0xdc] != 0xa4) {
+		/* decrypt data */
+		for (i = 0; i < len; ++i)
+			data[i] = (data[i] ^ 0x17) + 0x17;
+	}
+
+	/* See: http://wiibrew.org/wiki/Wii_Balance_Board */
+	/* Unknown data at 0xa40020..23 (mine says: 0x44 0x69 0x00 0x00) */
+	bb->cal_0.tr = (data[0x04] << 8) + data[0x05];
+	bb->cal_0.br = (data[0x06] << 8) + data[0x07];
+	bb->cal_0.tl = (data[0x08] << 8) + data[0x09];
+	bb->cal_0.bl = (data[0x0a] << 8) + data[0x0b];
+	bb->cal_17.tr = (data[0x0c] << 8) + data[0x0d];
+	bb->cal_17.br = (data[0x0e] << 8) + data[0x0f];
+	bb->cal_17.tl = (data[0x10] << 8) + data[0x11];
+	bb->cal_17.bl = (data[0x12] << 8) + data[0x13];
+	bb->cal_34.tr = (data[0x14] << 8) + data[0x15];
+	bb->cal_34.br = (data[0x16] << 8) + data[0x17];
+	bb->cal_34.tl = (data[0x18] << 8) + data[0x19];
+	bb->cal_34.bl = (data[0x1a] << 8) + data[0x1b];
+	/* Unknown data at 0xa4003c..3f (mine says: 0x4c 0x81 0x59 0x95) */
+
+	WIIUSE_DEBUG("calibration  0: %04x %04x %04x %04x\n", bb->cal_0.tr, bb->cal_0.br, bb->cal_0.tl, bb->cal_0.br);
+	WIIUSE_DEBUG("calibration 17: %04x %04x %04x %04x\n", bb->cal_17.tr, bb->cal_17.br, bb->cal_17.tl, bb->cal_17.br);
+	WIIUSE_DEBUG("calibration 34: %04x %04x %04x %04x\n", bb->cal_34.tr, bb->cal_34.br, bb->cal_34.tl, bb->cal_34.br);
+
+	/* handshake done */
+	wm->exp.type = EXP_BALANCE_BOARD;
+
+	#ifdef WIN32
+	wm->timeout = WIIMOTE_DEFAULT_TIMEOUT;
+	#endif
+
+	return 1;
+}
+
+
+/**
+ *	@brief The balance board disconnected.
+ *
+ *	@param cc		A pointer to a balance_board_t structure.
+ */
+void balance_board_disconnected(struct balance_board_t* bb) {
+	memset(bb, 0, sizeof(*bb));
+}
+
+
+
+/**
+ *	@brief Handle balance board event.
+ *
+ *	@param cc		A pointer to a balance board_t structure.
+ *	@param msg		The message specified in the event packet.
+ */
+#define set_bbval(x)	do {\
+		if(bb->raw.x < bb->cal_17.x) \
+			bb->x = 17.0 * (float)(bb->raw.x - bb->cal_0.x) / (float)(bb->cal_17.x - bb->cal_0.x); \
+		else \
+			bb->x = 17.0 * (1.0 + (float)(bb->raw.x - bb->cal_17.x) / (float)(bb->cal_34.x - bb->cal_17.x)); \
+	} while(0)
+void balance_board_event(struct balance_board_t* bb, byte* msg) {
+	bb->raw.tr = (msg[0] << 8) + msg[1];
+	bb->raw.br = (msg[2] << 8) + msg[3];
+	bb->raw.tl = (msg[4] << 8) + msg[5];
+	bb->raw.bl = (msg[6] << 8) + msg[7];
+	set_bbval(tr);
+	set_bbval(br);
+	set_bbval(tl);
+	set_bbval(bl);
+}
diff --git a/3rdparty/wiiuse/src/balance_board.h b/3rdparty/wiiuse/src/balance_board.h
new file mode 100644
index 0000000..77cf0b4
--- /dev/null
+++ b/3rdparty/wiiuse/src/balance_board.h
@@ -0,0 +1,53 @@
+/*
+ *	wiiuse
+ *
+ *	Written By:
+ *		Michael Laforest	< para >
+ *		Email: < thepara (--AT--) g m a i l [--DOT--] com >
+ *	This file:
+ *		Bertho Stultiens	< para >
+ *
+ *	Copyright 2009
+ *
+ *	This file is part of wiiuse.
+ *
+ *	This program is free software; you can redistribute it and/or modify
+ *	it under the terms of the GNU General Public License as published by
+ *	the Free Software Foundation; either version 3 of the License, or
+ *	(at your option) any later version.
+ *
+ *	This program is distributed in the hope that it will be useful,
+ *	but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *	GNU General Public License for more details.
+ *
+ *	You should have received a copy of the GNU General Public License
+ *	along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ *	$Header$
+ *
+ */
+
+/**
+ *	@file
+ *	@brief Balance Board expansion device.
+ */
+
+#ifndef BALANCE_BOARD_H_INCLUDED
+#define BALANCE_BOARD_H_INCLUDED
+
+#include "wiiuse_internal.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+int balance_board_handshake(struct wiimote_t* wm, struct balance_board_t* bb, byte* data, unsigned short len);
+void balance_board_disconnected(struct balance_board_t* bb);
+void balance_board_event(struct balance_board_t* bb, byte* msg);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // BALANCE_BOARD_H_INCLUDED
diff --git a/3rdparty/wiiuse/src/classic.c b/3rdparty/wiiuse/src/classic.c
new file mode 100644
index 0000000..df5f4db
--- /dev/null
+++ b/3rdparty/wiiuse/src/classic.c
@@ -0,0 +1,195 @@
+/*
+ *	wiiuse
+ *
+ *	Written By:
+ *		Michael Laforest	< para >
+ *		Michal Wiedenbauer	< shagkur >
+ *		Dave Murphy			< WinterMute >
+ *		Hector Martin		< marcan >
+ *		William Alozy		< wiill >
+ *
+ *	Copyright 2009
+ *
+ *
+ *	This file is part of wiiuse and fWIIne.
+ *
+ *	This program is free software; you can redistribute it and/or modify
+ *	it under the terms of the GNU General Public License as published by
+ *	the Free Software Foundation; either version 3 of the License, or
+ *	(at your option) any later version.
+ *
+ *	This program is distributed in the hope that it will be useful,
+ *	but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *	GNU General Public License for more details.
+ *
+ *	You should have received a copy of the GNU General Public License
+ *	along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ *	$Header$
+ *
+ */
+
+/**
+ *	@file
+ *	@brief Classic controller expansion device.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <math.h>
+
+#ifdef WIN32
+	#include <Winsock2.h>
+#endif
+
+#include "definitions.h"
+#include "wiiuse_internal.h"
+#include "dynamics.h"
+#include "events.h"
+#include "classic.h"
+#include "io.h"
+
+static void classic_ctrl_pressed_buttons(struct classic_ctrl_t* cc, short now);
+
+/**
+ *	@brief Handle the handshake data from the classic controller.
+ *
+ *	@param cc		A pointer to a classic_ctrl_t structure.
+ *	@param data		The data read in from the device.
+ *	@param len		The length of the data block, in bytes.
+ *
+ *	@return	Returns 1 if handshake was successful, 0 if not.
+ */
+int classic_ctrl_handshake(struct wiimote_t* wm, struct classic_ctrl_t* cc, byte* data, unsigned short len) {
+	int i;
+	int offset = 0;
+
+	cc->btns = 0;
+	cc->btns_held = 0;
+	cc->btns_released = 0;
+	cc->r_shoulder = 0;
+	cc->l_shoulder = 0;
+
+	/* decrypt data */
+	for (i = 0; i < len; ++i)
+		data[i] = (data[i] ^ 0x17) + 0x17;
+
+	if (data[offset] == 0xFF) {
+		/*
+		 *	Sometimes the data returned here is not correct.
+		 *	This might happen because the wiimote is lagging
+		 *	behind our initialization sequence.
+		 *	To fix this just request the handshake again.
+		 *
+		 *	Other times it's just the first 16 bytes are 0xFF,
+		 *	but since the next 16 bytes are the same, just use
+		 *	those.
+		 */
+		if (data[offset + 16] == 0xFF) {
+			/* get the calibration data */
+			byte* handshake_buf = malloc(EXP_HANDSHAKE_LEN * sizeof(byte));
+
+			WIIUSE_DEBUG("Classic controller handshake appears invalid, trying again.");
+			wiiuse_read_data_cb(wm, handshake_expansion, handshake_buf, WM_EXP_MEM_CALIBR, EXP_HANDSHAKE_LEN);
+
+			return 0;
+		} else
+			offset += 16;
+	}
+
+
+	/* joystick stuff */
+	cc->ljs.max.x = data[0 + offset] / 4;
+	cc->ljs.min.x = data[1 + offset] / 4;
+	cc->ljs.center.x = data[2 + offset] / 4;
+	cc->ljs.max.y = data[3 + offset] / 4;
+	cc->ljs.min.y = data[4 + offset] / 4;
+	cc->ljs.center.y = data[5 + offset] / 4;
+
+	cc->rjs.max.x = data[6 + offset] / 8;
+	cc->rjs.min.x = data[7 + offset] / 8;
+	cc->rjs.center.x = data[8 + offset] / 8;
+	cc->rjs.max.y = data[9 + offset] / 8;
+	cc->rjs.min.y = data[10 + offset] / 8;
+	cc->rjs.center.y = data[11 + offset] / 8;
+
+	/* handshake done */
+	wm->exp.type = EXP_CLASSIC;
+
+	#ifdef WIN32
+	wm->timeout = WIIMOTE_DEFAULT_TIMEOUT;
+	#endif
+
+	return 1;
+}
+
+
+/**
+ *	@brief The classic controller disconnected.
+ *
+ *	@param cc		A pointer to a classic_ctrl_t structure.
+ */
+void classic_ctrl_disconnected(struct classic_ctrl_t* cc) {
+	memset(cc, 0, sizeof(struct classic_ctrl_t));
+}
+
+
+
+/**
+ *	@brief Handle classic controller event.
+ *
+ *	@param cc		A pointer to a classic_ctrl_t structure.
+ *	@param msg		The message specified in the event packet.
+ */
+void classic_ctrl_event(struct classic_ctrl_t* cc, byte* msg) {
+	int i, lx, ly, rx, ry;
+	byte l, r;
+
+	/* decrypt data */
+	for (i = 0; i < 6; ++i)
+		msg[i] = (msg[i] ^ 0x17) + 0x17;
+
+	classic_ctrl_pressed_buttons(cc, BIG_ENDIAN_SHORT(*(short*)(msg + 4)));
+
+	/* left/right buttons */
+	l = (((msg[2] & 0x60) >> 2) | ((msg[3] & 0xE0) >> 5));
+	r = (msg[3] & 0x1F);
+
+	/*
+	 *	TODO - LR range hardcoded from 0x00 to 0x1F.
+	 *	This is probably in the calibration somewhere.
+	 */
+	cc->r_shoulder = ((float)r / 0x1F);
+	cc->l_shoulder = ((float)l / 0x1F);
+
+	/* calculate joystick orientation */
+	lx = (msg[0] & 0x3F);
+	ly = (msg[1] & 0x3F);
+	rx = ((msg[0] & 0xC0) >> 3) | ((msg[1] & 0xC0) >> 5) | ((msg[2] & 0x80) >> 7);
+	ry = (msg[2] & 0x1F);
+
+	calc_joystick_state(&cc->ljs, lx, ly);
+	calc_joystick_state(&cc->rjs, rx, ry);
+}
+
+
+/**
+ *	@brief Find what buttons are pressed.
+ *
+ *	@param cc		A pointer to a classic_ctrl_t structure.
+ *	@param msg		The message byte specified in the event packet.
+ */
+static void classic_ctrl_pressed_buttons(struct classic_ctrl_t* cc, short now) {
+	/* message is inverted (0 is active, 1 is inactive) */
+	now = ~now & CLASSIC_CTRL_BUTTON_ALL;
+
+	/* pressed now & were pressed, then held */
+	cc->btns_held = (now & cc->btns);
+
+	/* were pressed or were held & not pressed now, then released */
+	cc->btns_released = ((cc->btns | cc->btns_held) & ~now);
+
+	/* buttons pressed now */
+	cc->btns = now;
+}
diff --git a/3rdparty/wiiuse/src/classic.h b/3rdparty/wiiuse/src/classic.h
new file mode 100644
index 0000000..215b534
--- /dev/null
+++ b/3rdparty/wiiuse/src/classic.h
@@ -0,0 +1,53 @@
+/*
+ *	wiiuse
+ *
+ *	Written By:
+ *		Michael Laforest	< para >
+ *		Email: < thepara (--AT--) g m a i l [--DOT--] com >
+ *
+ *	Copyright 2006-2007
+ *
+ *	This file is part of wiiuse.
+ *
+ *	This program is free software; you can redistribute it and/or modify
+ *	it under the terms of the GNU General Public License as published by
+ *	the Free Software Foundation; either version 3 of the License, or
+ *	(at your option) any later version.
+ *
+ *	This program is distributed in the hope that it will be useful,
+ *	but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *	GNU General Public License for more details.
+ *
+ *	You should have received a copy of the GNU General Public License
+ *	along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ *	$Header$
+ *
+ */
+
+/**
+ *	@file
+ *	@brief Classic controller expansion device.
+ */
+
+#ifndef CLASSIC_H_INCLUDED
+#define CLASSIC_H_INCLUDED
+
+#include "wiiuse_internal.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+int classic_ctrl_handshake(struct wiimote_t* wm, struct classic_ctrl_t* cc, byte* data, unsigned short len);
+
+void classic_ctrl_disconnected(struct classic_ctrl_t* cc);
+
+void classic_ctrl_event(struct classic_ctrl_t* cc, byte* msg);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // CLASSIC_H_INCLUDED
diff --git a/3rdparty/wiiuse/src/definitions.h b/3rdparty/wiiuse/src/definitions.h
new file mode 100644
index 0000000..8b33e1d
--- /dev/null
+++ b/3rdparty/wiiuse/src/definitions.h
@@ -0,0 +1,85 @@
+/*
+ *	wiiuse
+ *
+ *	Written By:
+ *		Michael Laforest	< para >
+ *		Email: < thepara (--AT--) g m a i l [--DOT--] com >
+ *
+ *	Copyright 2006-2007
+ *
+ *	This file is part of wiiuse.
+ *
+ *	This program is free software; you can redistribute it and/or modify
+ *	it under the terms of the GNU General Public License as published by
+ *	the Free Software Foundation; either version 3 of the License, or
+ *	(at your option) any later version.
+ *
+ *	This program is distributed in the hope that it will be useful,
+ *	but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *	GNU General Public License for more details.
+ *
+ *	You should have received a copy of the GNU General Public License
+ *	along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ *	$Header$
+ *
+ */
+
+/**
+ *	@file
+ *	@brief General definitions.
+ */
+
+#ifndef DEFINITIONS_H_INCLUDED
+#define DEFINITIONS_H_INCLUDED
+
+/* this is wiiuse - used to distinguish from third party programs using wiiuse.h */
+#include "os.h"
+
+#define WIIMOTE_PI			3.14159265f
+
+//#define WITH_WIIUSE_DEBUG
+//#define WITH_WIIUSE_INFO 
+
+/* Error output macros */
+#define WIIUSE_ERROR(fmt, ...)		fprintf(stderr, "[ERROR] " fmt "\n", ##__VA_ARGS__)
+
+/* Warning output macros */
+#define WIIUSE_WARNING(fmt, ...)	fprintf(stderr, "[WARNING] " fmt "\n",	##__VA_ARGS__)
+
+/* Information output macros */
+#ifdef WITH_WIIUSE_INFO
+	#define WIIUSE_INFO(fmt, ...)	fprintf(stderr, "[INFO] " fmt "\n", ##__VA_ARGS__)
+#else
+	#define WIIUSE_INFO(fmt, ...)
+#endif
+
+/* Debug output macros */
+#ifdef WITH_WIIUSE_DEBUG
+	#ifdef WIN32
+		#define WIIUSE_DEBUG(fmt, ...)		do {																				\
+												char* file = __FILE__;															\
+												int i = strlen(file) - 1;														\
+												for (; i && (file[i] != '\\'); --i);											\
+												fprintf(stderr, "[DEBUG] %s:%i: " fmt "\n", file+i+1, __LINE__, ##__VA_ARGS__);	\
+											} while (0)
+	#else
+		#define WIIUSE_DEBUG(fmt, ...)	fprintf(stderr, "[DEBUG] " __FILE__ ":%i: " fmt "\n", __LINE__, ##__VA_ARGS__)
+	#endif
+#else
+	#define WIIUSE_DEBUG(fmt, ...)
+#endif
+
+/* Convert between radians and degrees */
+#define RAD_TO_DEGREE(r)	((r * 180.0f) / WIIMOTE_PI)
+#define DEGREE_TO_RAD(d)	(d * (WIIMOTE_PI / 180.0f))
+
+/* Convert to big endian */
+#define BIG_ENDIAN_LONG(i)				(htonl(i))
+#define BIG_ENDIAN_SHORT(i)				(htons(i))
+
+#define absf(x)						((x >= 0) ? (x) : (x * -1.0f))
+#define diff_f(x, y)				((x >= y) ? (absf(x - y)) : (absf(y - x)))
+
+#endif // DEFINITIONS_H_INCLUDED
diff --git a/3rdparty/wiiuse/src/dynamics.c b/3rdparty/wiiuse/src/dynamics.c
new file mode 100644
index 0000000..3cf2c7f
--- /dev/null
+++ b/3rdparty/wiiuse/src/dynamics.c
@@ -0,0 +1,231 @@
+/*
+ *	wiiuse
+ *
+ *	Written By:
+ *		Michael Laforest	< para >
+ *		Michal Wiedenbauer	< shagkur >
+ *		Dave Murphy			< WinterMute >
+ *		Hector Martin		< marcan >
+ *
+ *	Copyright 2009
+ *
+ *
+ *	This file is part of wiiuse and fWIIne.
+ *
+ *	This program is free software; you can redistribute it and/or modify
+ *	it under the terms of the GNU General Public License as published by
+ *	the Free Software Foundation; either version 3 of the License, or
+ *	(at your option) any later version.
+ *
+ *	This program is distributed in the hope that it will be useful,
+ *	but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *	GNU General Public License for more details.
+ *
+ *	You should have received a copy of the GNU General Public License
+ *	along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ *	$Header$
+ *
+ */
+
+/**
+ *	@file
+ *	@brief Handles the dynamics of the wiimote.
+ *
+ *	The file includes functions that handle the dynamics
+ *	of the wiimote.  Such dynamics include orientation and
+ *	motion sensing.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <math.h>
+
+#ifdef WIN32
+	#include <float.h>
+#endif
+
+#include "definitions.h"
+#include "wiiuse_internal.h"
+#include "ir.h"
+#include "dynamics.h"
+
+/**
+ *	@brief Calculate the roll, pitch, yaw.
+ *
+ *	@param ac			An accelerometer (accel_t) structure.
+ *	@param accel		[in] Pointer to a vec3w_t structure that holds the raw acceleration data.
+ *	@param orient		[out] Pointer to a orient_t structure that will hold the orientation data.
+ *	@param rorient		[out] Pointer to a orient_t structure that will hold the non-smoothed orientation data.
+ *	@param smooth		If smoothing should be performed on the angles calculated. 1 to enable, 0 to disable.
+ *
+ *	Given the raw acceleration data from the accelerometer struct, calculate
+ *	the orientation of the device and set it in the \a orient parameter.
+ */
+void calculate_orientation(struct accel_t* ac, struct vec3w_t* accel, struct orient_t* orient, int smooth) {
+	float xg, yg, zg;
+	float x, y, z;
+
+	/*
+	 *	roll	- use atan(z / x)		[ ranges from -180 to 180 ]
+	 *	pitch	- use atan(z / y)		[ ranges from -180 to 180 ]
+	 *	yaw		- impossible to tell without IR
+	 */
+
+	/* yaw - set to 0, IR will take care of it if it's enabled */
+	orient->yaw = 0.0f;
+
+	/* find out how much it has to move to be 1g */
+	xg = (float)ac->cal_g.x;
+	yg = (float)ac->cal_g.y;
+	zg = (float)ac->cal_g.z;
+
+	/* find out how much it actually moved and normalize to +/- 1g */
+	x = ((float)accel->x - (float)ac->cal_zero.x) / xg;
+	y = ((float)accel->y - (float)ac->cal_zero.y) / yg;
+	z = ((float)accel->z - (float)ac->cal_zero.z) / zg;
+
+	/* make sure x,y,z are between -1 and 1 for the tan functions */
+	if (x < -1.0f)			x = -1.0f;
+	else if (x > 1.0f)		x = 1.0f;
+	if (y < -1.0f)			y = -1.0f;
+	else if (y > 1.0f)		y = 1.0f;
+	if (z < -1.0f)			z = -1.0f;
+	else if (z > 1.0f)		z = 1.0f;
+
+	/* if it is over 1g then it is probably accelerating and not reliable */
+	if (abs(accel->x - ac->cal_zero.x) <= ac->cal_g.x) {
+		/* roll */
+		x = RAD_TO_DEGREE(atan2f(x, z));
+
+		orient->roll = x;
+		orient->a_roll = x;
+	}
+
+	if (abs(accel->y - ac->cal_zero.y) <= ac->cal_g.y) {
+		/* pitch */
+		y = RAD_TO_DEGREE(atan2f(y, z));
+
+		orient->pitch = y;
+		orient->a_pitch = y;
+	}
+
+	/* smooth the angles if enabled */
+	if (smooth) {
+		apply_smoothing(ac, orient, SMOOTH_ROLL);
+		apply_smoothing(ac, orient, SMOOTH_PITCH);
+	}
+}
+
+
+/**
+ *	@brief Calculate the gravity forces on each axis.
+ *
+ *	@param ac			An accelerometer (accel_t) structure.
+ *	@param accel		[in] Pointer to a vec3w_t structure that holds the raw acceleration data.
+ *	@param gforce		[out] Pointer to a gforce_t structure that will hold the gravity force data.
+ */
+void calculate_gforce(struct accel_t* ac, struct vec3w_t* accel, struct gforce_t* gforce) {
+	float xg, yg, zg;
+
+	/* find out how much it has to move to be 1g */
+	xg = (float)ac->cal_g.x;
+	yg = (float)ac->cal_g.y;
+	zg = (float)ac->cal_g.z;
+
+	/* find out how much it actually moved and normalize to +/- 1g */
+	gforce->x = ((float)accel->x - (float)ac->cal_zero.x) / xg;
+	gforce->y = ((float)accel->y - (float)ac->cal_zero.y) / yg;
+	gforce->z = ((float)accel->z - (float)ac->cal_zero.z) / zg;
+}
+
+
+/**
+ *	@brief Calculate the angle and magnitude of a joystick.
+ *
+ *	@param js	[out] Pointer to a joystick_t structure.
+ *	@param x	The raw x-axis value.
+ *	@param y	The raw y-axis value.
+ */
+void calc_joystick_state(struct joystick_t* js, float x, float y) {
+	float rx, ry, ang;
+
+	/*
+	 *	Since the joystick center may not be exactly:
+	 *		(min + max) / 2
+	 *	Then the range from the min to the center and the center to the max
+	 *	may be different.
+	 *	Because of this, depending on if the current x or y value is greater
+	 *	or less than the assoicated axis center value, it needs to be interpolated
+	 *	between the center and the minimum or maxmimum rather than between
+	 *	the minimum and maximum.
+	 *
+	 *	So we have something like this:
+	 *		(x min) [-1] ---------*------ [0] (x center) [0] -------- [1] (x max)
+	 *	Where the * is the current x value.
+	 *	The range is therefore -1 to 1, 0 being the exact center rather than
+	 *	the middle of min and max.
+	 */
+	if (x == js->center.x)
+		rx = 0;
+	else if (x >= js->center.x)
+		rx = ((float)(x - js->center.x) / (float)(js->max.x - js->center.x));
+	else
+		rx = ((float)(x - js->min.x) / (float)(js->center.x - js->min.x)) - 1.0f;
+
+	if (y == js->center.y)
+		ry = 0;
+	else if (y >= js->center.y)
+		ry = ((float)(y - js->center.y) / (float)(js->max.y - js->center.y));
+	else
+		ry = ((float)(y - js->min.y) / (float)(js->center.y - js->min.y)) - 1.0f;
+
+	/* calculate the joystick angle and magnitude */
+	ang = RAD_TO_DEGREE(atanf(ry / rx));
+	ang -= 90.0f;
+	if (rx < 0.0f)
+		ang -= 180.0f;
+	js->ang = absf(ang);
+	js->mag = (float) sqrt((rx * rx) + (ry * ry));
+}
+
+
+void apply_smoothing(struct accel_t* ac, struct orient_t* orient, int type) {
+	switch (type) {
+		case SMOOTH_ROLL:
+		{
+			/* it's possible last iteration was nan or inf, so set it to 0 if that happened */
+			if (isnan(ac->st_roll) || isinf(ac->st_roll))
+				ac->st_roll = 0.0f;
+
+			/*
+			 *	If the sign changes (which will happen if going from -180 to 180)
+			 *	or from (-1 to 1) then don't smooth, just use the new angle.
+			 */
+			if (((ac->st_roll < 0) && (orient->roll > 0)) || ((ac->st_roll > 0) && (orient->roll < 0))) {
+				ac->st_roll = orient->roll;
+			} else {
+				orient->roll = ac->st_roll + (ac->st_alpha * (orient->a_roll - ac->st_roll));
+				ac->st_roll = orient->roll;
+			}
+
+			return;
+		}
+
+		case SMOOTH_PITCH:
+		{
+			if (isnan(ac->st_pitch) || isinf(ac->st_pitch))
+				ac->st_pitch = 0.0f;
+
+			if (((ac->st_pitch < 0) && (orient->pitch > 0)) || ((ac->st_pitch > 0) && (orient->pitch < 0))) {
+				ac->st_pitch = orient->pitch;
+			} else {
+				orient->pitch = ac->st_pitch + (ac->st_alpha * (orient->a_pitch - ac->st_pitch));
+				ac->st_pitch = orient->pitch;
+			}
+
+			return;
+		}
+	}
+}
diff --git a/3rdparty/wiiuse/src/dynamics.h b/3rdparty/wiiuse/src/dynamics.h
new file mode 100644
index 0000000..5437b4f
--- /dev/null
+++ b/3rdparty/wiiuse/src/dynamics.h
@@ -0,0 +1,56 @@
+/*
+ *	wiiuse
+ *
+ *	Written By:
+ *		Michael Laforest	< para >
+ *		Email: < thepara (--AT--) g m a i l [--DOT--] com >
+ *
+ *	Copyright 2006-2007
+ *
+ *	This file is part of wiiuse.
+ *
+ *	This program is free software; you can redistribute it and/or modify
+ *	it under the terms of the GNU General Public License as published by
+ *	the Free Software Foundation; either version 3 of the License, or
+ *	(at your option) any later version.
+ *
+ *	This program is distributed in the hope that it will be useful,
+ *	but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *	GNU General Public License for more details.
+ *
+ *	You should have received a copy of the GNU General Public License
+ *	along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ *	$Header$
+ *
+ */
+
+/**
+ *	@file
+ *	@brief Handles the dynamics of the wiimote.
+ *
+ *	The file includes functions that handle the dynamics
+ *	of the wiimote.  Such dynamics include orientation and
+ *	motion sensing.
+ */
+
+#ifndef DYNAMICS_H_INCLUDED
+#define DYNAMICS_H_INCLUDED
+
+#include "wiiuse_internal.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void calculate_orientation(struct accel_t* ac, struct vec3w_t* accel, struct orient_t* orient, int smooth);
+void calculate_gforce(struct accel_t* ac, struct vec3w_t* accel, struct gforce_t* gforce);
+void calc_joystick_state(struct joystick_t* js, float x, float y);
+void apply_smoothing(struct accel_t* ac, struct orient_t* orient, int type);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // DYNAMICS_H_INCLUDED
diff --git a/3rdparty/wiiuse/src/events.c b/3rdparty/wiiuse/src/events.c
new file mode 100644
index 0000000..cbb7a02
--- /dev/null
+++ b/3rdparty/wiiuse/src/events.c
@@ -0,0 +1,837 @@
+/*
+ *	wiiuse
+ *
+ *	Written By:
+ *		Michael Laforest	< para >
+ *		Michal Wiedenbauer	< shagkur >
+ *		Dave Murphy			< WinterMute >
+ *		Hector Martin		< marcan >
+ *		William Alozy		< wiill >
+ *
+ *	Copyright 2009
+ *
+ *
+ *	This file is part of wiiuse and fWIIne.
+ *
+ *	This program is free software; you can redistribute it and/or modify
+ *	it under the terms of the GNU General Public License as published by
+ *	the Free Software Foundation; either version 3 of the License, or
+ *	(at your option) any later version.
+ *
+ *	This program is distributed in the hope that it will be useful,
+ *	but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *	GNU General Public License for more details.
+ *
+ *	You should have received a copy of the GNU General Public License
+ *	along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ *	$Header$
+ *
+ */
+
+/**
+ *	@file
+ *	@brief Handles wiimote events.
+ *
+ *	The file includes functions that handle the events
+ *	that are sent from the wiimote to us.
+ */
+
+#include <stdio.h>
+
+#ifndef WIN32
+	#include <sys/time.h>
+	#include <unistd.h>
+	#include <errno.h>
+#else
+	#include <winsock2.h>
+#endif
+
+#include <sys/types.h>
+#include <stdlib.h>
+#include <math.h>
+
+#include "dynamics.h"
+#include "definitions.h"
+#include "wiiuse_internal.h"
+#include "events.h"
+#include "nunchuk.h"
+#include "classic.h"
+#include "guitar_hero_3.h"
+#include "balance_board.h"
+#include "motion_plus.h"
+#include "ir.h"
+#include "io.h"
+
+static void idle_cycle(struct wiimote_t* wm);
+static void clear_dirty_reads(struct wiimote_t* wm);
+static void propagate_event(struct wiimote_t* wm, byte event, byte* msg);
+static void event_data_read(struct wiimote_t* wm, byte* msg);
+static void event_status(struct wiimote_t* wm, byte* msg);
+static void handle_expansion(struct wiimote_t* wm, byte* msg);
+static void save_state(struct wiimote_t* wm);
+static int state_changed(struct wiimote_t* wm);
+
+/**
+ *	@brief Received a data packet from a read request.
+ *
+ *	@param wm		Pointer to a wiimote_t structure.
+ *	@param msg		The message specified in the event packet.
+ *
+ *	Data from the wiimote comes in packets.  If the requested
+ *	data segment size is bigger than one packet can hold then
+ *	several packets will be received.  These packets are first
+ *	reassembled into one, then the registered callback function
+ *	that handles data reads is invoked.
+ */
+static void event_data_read(struct wiimote_t* wm, byte* msg) {
+	/* we must always assume the packet received is from the most recent request */
+	byte err;
+	byte len;
+	unsigned short offset;
+	struct read_req_t* req = wm->read_req;
+
+	wiiuse_pressed_buttons(wm, msg);
+
+	/* find the next non-dirty request */
+	while (req && req->dirty)
+		req = req->next;
+
+	/* if we don't have a request out then we didn't ask for this packet */
+	if (!req) {
+		WIIUSE_WARNING("Received data packet when no request was made.");
+		return;
+	}
+/* Ctrl0 */
+	err = msg[2] & 0x0F;
+
+	if (err == 0x08)
+		WIIUSE_WARNING("Unable to read data - address does not exist.");
+	else if (err == 0x07)
+		WIIUSE_WARNING("Unable to read data - address is for write-only registers.");
+	else if (err)
+		WIIUSE_WARNING("Unable to read data - unknown error code %x.", err);
+
+	if (err) {
+		/* this request errored out, so skip it and go to the next one */
+
+		/* delete this request */
+		wm->read_req = req->next;
+		free(req);
+
+		/* if another request exists send it to the wiimote */
+		if (wm->read_req)
+			wiiuse_send_next_pending_read_request(wm);
+
+		return;
+	}
+/* Ctrl1 */
+
+	len = ((msg[2] & 0xF0) >> 4) + 1;
+	offset = BIG_ENDIAN_SHORT(*(unsigned short*)(msg + 3));
+	req->addr = (req->addr & 0xFFFF);
+
+	req->wait -= len;
+	if (req->wait >= req->size)
+		/* this should never happen */
+		req->wait = 0;
+
+	WIIUSE_DEBUG("Received read packet:");
+	WIIUSE_DEBUG("    Packet read offset:   %i bytes", offset);
+	WIIUSE_DEBUG("    Request read offset:  %i bytes", req->addr);
+	WIIUSE_DEBUG("    Read offset into buf: %i bytes", offset - req->addr);
+	WIIUSE_DEBUG("    Read data size:       %i bytes", len);
+	WIIUSE_DEBUG("    Still need:           %i bytes", req->wait);
+
+	/* reconstruct this part of the data */
+	memcpy((req->buf + offset - req->addr), (msg + 5), len);
+
+	#ifdef WITH_WIIUSE_DEBUG
+	{
+		int i = 0;
+		printf("Read: ");
+		for (; i < req->size - req->wait; ++i)
+			printf("%x ", req->buf[i]);
+		printf("\n");
+	}
+	#endif
+
+	/* if all data has been received, execute the read event callback or generate event */
+	if (!req->wait) {
+		if (req->cb) {
+			/* this was a callback, so invoke it now */
+			req->cb(wm, req->buf, req->size);
+
+			/* delete this request */
+			wm->read_req = req->next;
+			free(req);
+		} else {
+			/*
+			 *	This should generate an event.
+			 *	We need to leave the event in the array so the client
+			 *	can access it still.  We'll flag is as being 'dirty'
+			 *	and give the client one cycle to use it.  Next event
+			 *	we will remove it from the list.
+			 */
+			wm->event = WIIUSE_READ_DATA;
+			req->dirty = 1;
+		}
+
+		/* if another request exists send it to the wiimote */
+		if (wm->read_req)
+			wiiuse_send_next_pending_read_request(wm);
+	}
+}
+
+static void event_data_write(struct wiimote_t *wm,ubyte *msg)
+{
+
+	struct data_req_t* req = wm->data_req;
+
+	wiiuse_pressed_buttons(wm,msg);
+
+	/* if we don't have a request out then we didn't ask for this packet */
+	if (!req) {
+		WIIUSE_WARNING("Transmitting data packet when no request was made.");
+		return;
+	}
+	if(!(req->state==REQ_SENT)) {
+		WIIUSE_WARNING("Transmission is not necessary");	
+		/* delete this request */
+		wm->data_req = req->next; 
+		free(req);				
+		return;
+	}
+
+
+	req->state = REQ_DONE;
+	
+	if(req->cb) {
+		/* this was a callback, so invoke it now */
+		req->cb(wm,NULL,0);
+		/* delete this request */
+		wm->data_req = req->next;
+		free(req);
+	} else {
+			/*
+			 *	This should generate an event.
+			 *	We need to leave the event in the array so the client
+			 *	can access it still.  We'll flag is as being 'REQ_DONE'
+			 *	and give the client one cycle to use it.  Next event
+			 *	we will remove it from the list.
+			 */
+			wm->event = WIIUSE_WRITE_DATA;
+			
+		}
+	/* if another request exists send it to the wiimote */
+	if (wm->data_req)	{
+		wiiuse_send_next_pending_write_request(wm);
+	}
+}
+
+
+/**
+ *	@brief Read the controller status.
+ *
+ *	@param wm		Pointer to a wiimote_t structure.
+ *	@param msg		The message specified in the event packet.
+ *
+ *	Read the controller status and execute the registered status callback.
+ */
+static void event_status(struct wiimote_t* wm, byte* msg) {
+
+	int ir = 0;
+	int attachment = 0;
+	int exp_changed = 0;
+	int led[4] = {0};
+	struct data_req_t* req = wm->data_req;
+	/*
+	 *	An event occured.
+	 *	This event can be overwritten by a more specific
+	 *	event type during a handshake or expansion removal.
+	 */
+	wiiuse_pressed_buttons(wm, msg);
+	wm->event = WIIUSE_STATUS;
+	/* find what LEDs are lit */
+	if (msg[2] & WM_CTRL_STATUS_BYTE1_LED_1)	led[0] = 1;
+	if (msg[2] & WM_CTRL_STATUS_BYTE1_LED_2)	led[1] = 1;
+	if (msg[2] & WM_CTRL_STATUS_BYTE1_LED_3)	led[2] = 1;
+	if (msg[2] & WM_CTRL_STATUS_BYTE1_LED_4)	led[3] = 1;
+
+	if ((msg[2] & WM_CTRL_STATUS_BYTE1_ATTACHMENT) == WM_CTRL_STATUS_BYTE1_ATTACHMENT)				attachment = 1;	/* is an attachment connected to the expansion port? */
+	if ((msg[2] & WM_CTRL_STATUS_BYTE1_SPEAKER_ENABLED) == WM_CTRL_STATUS_BYTE1_SPEAKER_ENABLED)	WIIMOTE_ENABLE_STATE(wm, WIIMOTE_STATE_SPEAKER); 	/* is the speaker enabled? */
+	if ((msg[2] & WM_CTRL_STATUS_BYTE1_IR_ENABLED) == WM_CTRL_STATUS_BYTE1_IR_ENABLED)				ir = 1; /* is IR sensing enabled? */
+	
+	wm->battery_level = (msg[5] / (float)WM_MAX_BATTERY_CODE); /* find the battery level and normalize between 0 and 1 */
+
+	/* expansion port */
+	if (attachment && !WIIMOTE_IS_SET(wm, WIIMOTE_STATE_EXP)) {
+		/* send the initialization code for the attachment */
+		handshake_expansion_start(wm); //handshake_expansion(wm, NULL, 0);
+		//handshake_expansion(wm, NULL, 0); /* deviation : the commented line allowed a back to initial state without attachment */
+		exp_changed = 1;
+	} else if (!attachment && WIIMOTE_IS_SET(wm, WIIMOTE_STATE_EXP)) {
+		/* attachment removed */
+		disable_expansion(wm);
+		exp_changed = 1;
+	}
+
+	#ifdef WIN32
+	if (!attachment) {
+		WIIUSE_DEBUG("Setting timeout to normal %i ms.", wm->normal_timeout);
+		wm->timeout = wm->normal_timeout;
+	}
+	#endif
+
+	/*
+	 *	From now on the remote will only send status packets.
+	 *	We need to send a WIIMOTE_CMD_REPORT_TYPE packet to
+	 *	reenable other incoming reports.
+	 */
+	if (exp_changed)	{
+		if (exp_changed && WIIMOTE_IS_SET(wm, WIIMOTE_STATE_IR)) {
+			/*
+			 *	Since the expansion status changed IR needs to
+			 *	be reset for the new IR report mode.
+			 */
+			WIIMOTE_DISABLE_STATE(wm, WIIMOTE_STATE_IR);
+			wiiuse_set_ir(wm, 1);
+		} else {
+			wiiuse_set_report_type(wm);
+			return;
+		}
+		/* handling new Tx for changed exp */
+		if(!req) return;
+		if(!(req->state==REQ_SENT)) return;
+
+		wm->data_req = req->next;
+
+		req->state = REQ_DONE;
+		//if(req->cb!=NULL) req->cb(wm,msg,6);
+	
+		free(req);
+		wiiuse_send_next_pending_write_request(wm);
+
+	} else
+		wiiuse_set_report_type(wm);
+}
+
+
+
+/**
+ *	@brief Handle data from the expansion.
+ *
+ *	@param wm		A pointer to a wiimote_t structure.
+ *	@param msg		The message specified in the event packet for the expansion.
+ */
+static void handle_expansion(struct wiimote_t* wm, byte* msg) {
+	switch (wm->exp.type) {
+		case EXP_NUNCHUK:
+			nunchuk_event(&wm->exp.nunchuk, msg);
+			break;
+		case EXP_CLASSIC:
+			classic_ctrl_event(&wm->exp.classic, msg);
+			break;
+		case EXP_GUITAR_HERO_3:
+			guitar_hero_3_event(&wm->exp.gh3, msg);
+			break;
+ 		case EXP_BALANCE_BOARD:
+			balance_board_event(&wm->exp.bb, msg);
+			break;
+		case EXP_MOTION_PLUS:
+ 			motion_plus_event(&wm->exp.mp, msg);
+			break;
+		default:
+			break;
+	}
+}
+
+
+/**
+ *	@brief Called on a cycle where no significant change occurs.
+ *
+ *	@param wm		Pointer to a wiimote_t structure.
+ */
+static void idle_cycle(struct wiimote_t* wm) {
+	/*
+	 *	Smooth the angles.
+	 *
+	 *	This is done to make sure that on every cycle the orientation
+	 *	angles are smoothed.  Normally when an event occurs the angles
+	 *	are updated and smoothed, but if no packet comes in then the
+	 *	angles remain the same.  This means the angle wiiuse reports
+	 *	is still an old value.  Smoothing needs to be applied in this
+	 *	case in order for the angle it reports to converge to the true
+	 *	angle of the device.
+	 */
+	if (WIIUSE_USING_ACC(wm) && WIIMOTE_IS_FLAG_SET(wm, WIIUSE_SMOOTHING)) {
+		apply_smoothing(&wm->accel_calib, &wm->orient, SMOOTH_ROLL);
+		apply_smoothing(&wm->accel_calib, &wm->orient, SMOOTH_PITCH);
+	}
+
+	/* clear out any old read requests */
+	clear_dirty_reads(wm);
+}
+
+
+/**
+ *	@brief Clear out all old 'dirty' read requests.
+ *
+ *	@param wm		Pointer to a wiimote_t structure.
+ */
+static void clear_dirty_reads(struct wiimote_t* wm) {
+	struct read_req_t* req = wm->read_req;
+
+	while (req && req->dirty) {
+		WIIUSE_DEBUG("Cleared old read request for address: %x", req->addr);
+
+		wm->read_req = req->next;
+		free(req);
+		req = wm->read_req;
+	}
+}
+
+
+/**
+ *	@brief Analyze the event that occured on a wiimote.
+ *
+ *	@param wm		An array of pointers to wiimote_t structures.
+ *	@param event	The event that occured.
+ *	@param msg		The message specified in the event packet.
+ *
+ *	Pass the event to the registered event callback.
+ */
+static void propagate_event(struct wiimote_t* wm, byte event, byte* msg) {
+	save_state(wm);
+	//printf("parse_event(%02x,%p)\n",event,msg);
+
+	switch (event) {
+		case WM_RPT_CTRL_STATUS:
+			event_status(wm,msg); /* controller status */
+			return; /* don't execute the event callback */
+		case WM_RPT_READ:
+			event_data_read(wm,msg); /* data read */
+			return; /* yeah buttons may be pressed, but this wasn't an "event" */
+		case WM_RPT_WRITE:
+			event_data_write(wm,msg);
+			return;
+		case WM_RPT_BTN:
+			wiiuse_pressed_buttons(wm,msg); /* button */
+			break;
+		case WM_RPT_BTN_ACC:
+			wiiuse_pressed_buttons(wm,msg); /* button - motion */
+
+			/*wm->accel.x = msg[2];
+			wm->accel.y = msg[3];
+			wm->accel.z = msg[4];*/
+			wm->accel.x = (msg[2]<<2)|((msg[0]>>5)&3);
+			wm->accel.y = (msg[3]<<2)|((msg[1]>>4)&2);
+			wm->accel.z = (msg[4]<<2)|((msg[1]>>5)&2);
+
+			/* calculate the remote orientation */
+			calculate_orientation(&wm->accel_calib, &wm->accel, &wm->orient, WIIMOTE_IS_FLAG_SET(wm, WIIUSE_SMOOTHING));
+
+			/* calculate the gforces on each axis */
+			calculate_gforce(&wm->accel_calib, &wm->accel, &wm->gforce);
+
+			break;
+		case WM_RPT_BTN_ACC_IR:
+			wiiuse_pressed_buttons(wm,msg); /* button - motion - ir */
+
+			/*wm->accel.x = msg[2];
+			wm->accel.y = msg[3];
+			wm->accel.z = msg[4];*/
+			wm->accel.x = (msg[2]<<2)|((msg[0]>>5)&3);
+			wm->accel.y = (msg[3]<<2)|((msg[1]>>4)&2);
+			wm->accel.z = (msg[4]<<2)|((msg[1]>>5)&2);
+
+			/* calculate the remote orientation */
+			calculate_orientation(&wm->accel_calib, &wm->accel, &wm->orient, WIIMOTE_IS_FLAG_SET(wm, WIIUSE_SMOOTHING));
+			/* calculate the gforces on each axis */
+			calculate_gforce(&wm->accel_calib, &wm->accel, &wm->gforce);
+
+			calculate_extended_ir(wm, msg+5); /* ir */
+
+			break;
+		case WM_RPT_BTN_EXP:
+			wiiuse_pressed_buttons(wm,msg); /* button - expansion */
+			handle_expansion(wm, msg+2);
+
+			break;
+		case WM_RPT_BTN_ACC_EXP:
+			/* button - motion - expansion */
+			wiiuse_pressed_buttons(wm, msg);
+			/*wm->accel.x = msg[2];
+			wm->accel.y = msg[3];
+			wm->accel.z = msg[4];*/
+			wm->accel.x = (msg[2]<<2)|((msg[0]>>5)&3);
+			wm->accel.y = (msg[3]<<2)|((msg[1]>>4)&2);
+			wm->accel.z = (msg[4]<<2)|((msg[1]>>5)&2);
+
+			calculate_orientation(&wm->accel_calib, &wm->accel, &wm->orient, WIIMOTE_IS_FLAG_SET(wm, WIIUSE_SMOOTHING));
+			calculate_gforce(&wm->accel_calib, &wm->accel, &wm->gforce);
+
+			handle_expansion(wm, msg+5);
+
+			break;
+		case WM_RPT_BTN_IR_EXP:
+			wiiuse_pressed_buttons(wm,msg); /* button - ir - expansion */
+			calculate_basic_ir(wm, msg+2);/* ir */
+			handle_expansion(wm,msg+12);
+			break;
+		case WM_RPT_BTN_ACC_IR_EXP:
+			/* button - motion - ir - expansion */
+			wiiuse_pressed_buttons(wm, msg);
+			/*wm->accel.x = msg[2];
+			wm->accel.y = msg[3];
+			wm->accel.z = msg[4];*/
+			wm->accel.x = (msg[2]<<2)|((msg[0]>>5)&3);
+			wm->accel.y = (msg[3]<<2)|((msg[1]>>4)&2);
+			wm->accel.z = (msg[4]<<2)|((msg[1]>>5)&2);
+
+			calculate_orientation(&wm->accel_calib, &wm->accel, &wm->orient, WIIMOTE_IS_FLAG_SET(wm, WIIUSE_SMOOTHING));
+			calculate_gforce(&wm->accel_calib, &wm->accel, &wm->gforce);
+
+			/* ir */
+			calculate_basic_ir(wm, msg+5);
+
+			handle_expansion(wm, msg+15);
+			break;
+		default:
+			WIIUSE_WARNING("Unknown event, can not handle it [Code 0x%x].", event);
+			return;
+	}
+
+	/* was there an event? */
+	wm->event = WIIUSE_EVENT;
+}
+
+/**
+ *	@brief Find what buttons are pressed.
+ *
+ *	@param wm		Pointer to a wiimote_t structure.
+ *	@param msg		The message specified in the event packet.
+ */
+void wiiuse_pressed_buttons(struct wiimote_t* wm, byte* msg) {
+	short now;
+
+	/* convert to big endian */
+	now = BIG_ENDIAN_SHORT(*(short*)msg) & WIIMOTE_BUTTON_ALL;
+	/* preserve old btns pressed */
+	wm->btns_last = wm->btns;
+
+	/* pressed now & were pressed, then held */
+	wm->btns_held = (now & wm->btns);
+
+	/* were pressed or were held & not pressed now, then released */
+	wm->btns_released = ((wm->btns | wm->btns_held) & ~now);
+
+	/* buttons pressed now */
+	wm->btns = now;
+}
+
+
+
+
+
+/**
+ *	@brief Save important state data.
+ *	@param wm	A pointer to a wiimote_t structure.
+ */
+static void save_state(struct wiimote_t* wm) {
+	/* wiimote */
+	wm->lstate.btns = wm->btns;
+	wm->lstate.accel = wm->accel;
+
+	/* ir */
+	if (WIIUSE_USING_IR(wm)) {
+		wm->lstate.ir_ax = wm->ir.ax;
+		wm->lstate.ir_ay = wm->ir.ay;
+		wm->lstate.ir_distance = wm->ir.distance;
+	}
+
+	/* expansion */
+	switch (wm->exp.type) {
+		case EXP_NUNCHUK:
+			wm->lstate.exp_ljs_ang = wm->exp.nunchuk.js.ang;
+			wm->lstate.exp_ljs_mag = wm->exp.nunchuk.js.mag;
+			wm->lstate.exp_btns = wm->exp.nunchuk.btns;
+			wm->lstate.exp_accel = wm->exp.nunchuk.accel;
+			break;
+
+		case EXP_CLASSIC:
+			wm->lstate.exp_ljs_ang = wm->exp.classic.ljs.ang;
+			wm->lstate.exp_ljs_mag = wm->exp.classic.ljs.mag;
+			wm->lstate.exp_rjs_ang = wm->exp.classic.rjs.ang;
+			wm->lstate.exp_rjs_mag = wm->exp.classic.rjs.mag;
+			wm->lstate.exp_r_shoulder = wm->exp.classic.r_shoulder;
+			wm->lstate.exp_l_shoulder = wm->exp.classic.l_shoulder;
+			wm->lstate.exp_btns = wm->exp.classic.btns;
+			break;
+
+		case EXP_GUITAR_HERO_3:
+			wm->lstate.exp_ljs_ang = wm->exp.gh3.js.ang;
+			wm->lstate.exp_ljs_mag = wm->exp.gh3.js.mag;
+			wm->lstate.exp_r_shoulder = wm->exp.gh3.whammy_bar;
+			wm->lstate.exp_btns = wm->exp.gh3.btns;
+			break;
+
+		case EXP_MOTION_PLUS:
+			wm->lstate.drx = wm->lstate.exp.mp.rx;
+			wm->lstate.dry = wm->lstate.exp.mp.ry;
+			wm->lstate.drx = wm->lstate.exp.mp.rz;
+			break;
+			
+		case EXP_BALANCE_BOARD:
+			wm->lstate.exp_bb_raw = wm->exp.bb.raw;
+			break;
+
+		case EXP_NONE:
+			break;
+	}
+}
+
+
+/**
+ *	@brief Determine if the current state differs significantly from the previous.
+ *	@param wm	A pointer to a wiimote_t structure.
+ *	@return	1 if a significant change occured, 0 if not.
+ */
+static int state_changed(struct wiimote_t* wm) {
+	#define STATE_CHANGED(a, b)		if (a != b)				return 1
+
+	#define CROSS_THRESH(last, now, thresh)										\
+				do {															\
+					if (WIIMOTE_IS_FLAG_SET(wm, WIIUSE_ORIENT_THRESH)) {		\
+						if ((diff_f(last.roll, now.roll) >= thresh) ||			\
+							(diff_f(last.pitch, now.pitch) >= thresh) ||		\
+							(diff_f(last.yaw, now.yaw) >= thresh))				\
+						{														\
+							last = now;											\
+							return 1;											\
+						}														\
+					} else {													\
+						if (last.roll != now.roll)		return 1;				\
+						if (last.pitch != now.pitch)	return 1;				\
+						if (last.yaw != now.yaw)		return 1;				\
+					}															\
+				} while (0)
+
+	#define CROSS_THRESH_XYZ(last, now, thresh)									\
+				do {															\
+					if (WIIMOTE_IS_FLAG_SET(wm, WIIUSE_ORIENT_THRESH)) {		\
+						if ((diff_f(last.x, now.x) >= thresh) ||				\
+							(diff_f(last.y, now.y) >= thresh) ||				\
+							(diff_f(last.z, now.z) >= thresh))					\
+						{														\
+							last = now;											\
+							return 1;											\
+						}														\
+					} else {													\
+						if (last.x != now.x)		return 1;					\
+						if (last.y != now.y)		return 1;					\
+						if (last.z != now.z)		return 1;					\
+					}															\
+				} while (0)
+
+	/* ir */
+	if (WIIUSE_USING_IR(wm)) {
+		STATE_CHANGED(wm->lstate.ir_ax, wm->ir.ax);
+		STATE_CHANGED(wm->lstate.ir_ay, wm->ir.ay);
+		STATE_CHANGED(wm->lstate.ir_distance, wm->ir.distance);
+	}
+
+	/* accelerometer */
+	if (WIIUSE_USING_ACC(wm)) {
+		/* raw accelerometer */
+		CROSS_THRESH_XYZ(wm->lstate.accel, wm->accel, wm->accel_threshold);
+
+		/* orientation */
+ 		CROSS_THRESH(wm->lstate.orient, wm->orient, wm->orient_threshold);
+	}
+
+	/* expansion */
+	switch (wm->exp.type) {
+		case EXP_NUNCHUK:
+		{
+			STATE_CHANGED(wm->lstate.exp_ljs_ang, wm->exp.nunchuk.js.ang);
+			STATE_CHANGED(wm->lstate.exp_ljs_mag, wm->exp.nunchuk.js.mag);
+			STATE_CHANGED(wm->lstate.exp_btns, wm->exp.nunchuk.btns);
+
+			CROSS_THRESH(wm->lstate.exp_orient, wm->exp.nunchuk.orient, wm->exp.nunchuk.orient_threshold);
+			CROSS_THRESH_XYZ(wm->lstate.exp_accel, wm->exp.nunchuk.accel, wm->exp.nunchuk.accel_threshold);
+			break;
+		}
+		case EXP_CLASSIC:
+		{
+			STATE_CHANGED(wm->lstate.exp_ljs_ang, wm->exp.classic.ljs.ang);
+			STATE_CHANGED(wm->lstate.exp_ljs_mag, wm->exp.classic.ljs.mag);
+			STATE_CHANGED(wm->lstate.exp_rjs_ang, wm->exp.classic.rjs.ang);
+			STATE_CHANGED(wm->lstate.exp_rjs_mag, wm->exp.classic.rjs.mag);
+			STATE_CHANGED(wm->lstate.exp_r_shoulder, wm->exp.classic.r_shoulder);
+			STATE_CHANGED(wm->lstate.exp_l_shoulder, wm->exp.classic.l_shoulder);
+			STATE_CHANGED(wm->lstate.exp_btns, wm->exp.classic.btns);
+			break;
+		}
+		case EXP_GUITAR_HERO_3:
+		{
+			STATE_CHANGED(wm->lstate.exp_ljs_ang, wm->exp.gh3.js.ang);
+			STATE_CHANGED(wm->lstate.exp_ljs_mag, wm->exp.gh3.js.mag);
+			STATE_CHANGED(wm->lstate.exp_r_shoulder, wm->exp.gh3.whammy_bar);
+			STATE_CHANGED(wm->lstate.exp_btns, wm->exp.gh3.btns);
+			break;
+		}
+		case EXP_MOTION_PLUS:
+		{	
+			STATE_CHANGED(wm->lstate.drx,wm->lstate.exp.mp.rx);
+			STATE_CHANGED(wm->lstate.dry,wm->lstate.exp.mp.ry);
+			STATE_CHANGED(wm->lstate.drz,wm->lstate.exp.mp.rz);
+			break;
+		}
+		case EXP_BALANCE_BOARD:
+		{
+			STATE_CHANGED(wm->lstate.exp_bb_raw.tr, wm->exp.bb.raw.tr);
+			STATE_CHANGED(wm->lstate.exp_bb_raw.br, wm->exp.bb.raw.br);
+			STATE_CHANGED(wm->lstate.exp_bb_raw.tl, wm->exp.bb.raw.tl);
+			STATE_CHANGED(wm->lstate.exp_bb_raw.bl, wm->exp.bb.raw.bl);
+			break;
+		}
+		case EXP_NONE:
+		{
+			break;
+		}
+	}
+
+	STATE_CHANGED(wm->lstate.btns, wm->btns);
+
+	return 0;
+}
+/**
+ *	@brief Poll the wiimotes for any events.
+ *
+ *	@param wm		An array of pointers to wiimote_t structures.
+ *	@param wiimotes	The number of wiimote_t structures in the \a wm array.
+ *
+ *	@return Returns number of wiimotes that an event has occured on.
+ *
+ *	It is necessary to poll the wiimote devices for events
+ *	that occur.  If an event occurs on a particular wiimote,
+ *	the event variable will be set.
+ */
+int wiiuse_poll(struct wiimote_t** wm, int wiimotes) {
+	int evnt = 0;
+
+	#ifndef WIN32
+		/*
+		 *	*nix
+		 */
+		struct timeval tv;
+		fd_set fds;
+		int r;
+		int i;
+		int highest_fd = -1;
+
+		if (!wm) return 0;
+
+		/* block select() for 1/2000th of a second */
+		/* block select() for 1/30th of a second */
+		tv.tv_sec = 0;
+		//tv.tv_usec = 500;
+		tv.tv_usec = 33333;
+
+		FD_ZERO(&fds);
+
+		for (i = 0; i < wiimotes; ++i) {
+			/* only poll it if it is connected */
+			if (WIIMOTE_IS_SET(wm[i], WIIMOTE_STATE_CONNECTED)) {
+				FD_SET(wm[i]->in_sock, &fds);
+
+				/* find the highest fd of the connected wiimotes */
+				if (wm[i]->in_sock > highest_fd)
+					highest_fd = wm[i]->in_sock;
+			}
+
+			wm[i]->event = WIIUSE_NONE;
+		}
+
+		if (highest_fd == -1)
+			/* nothing to poll */
+			return 0;
+
+		if (select(highest_fd + 1, &fds, NULL, NULL, &tv) == -1) {
+			WIIUSE_ERROR("Unable to select() the wiimote interrupt socket(s).");
+			perror("Error Details");
+			return 0;
+		}
+
+		/* check each socket for an event */
+		for (i = 0; i < wiimotes; ++i) {
+			/* if this wiimote is not connected, skip it */
+			if (!WIIMOTE_IS_CONNECTED(wm[i]))
+				continue;
+
+			if (FD_ISSET(wm[i]->in_sock, &fds)) {
+				/* clear out the event buffer */
+				memset(wm[i]->event_buf, 0, sizeof(wm[i]->event_buf));
+
+				/* clear out any old read requests */
+				clear_dirty_reads(wm[i]);
+
+				/* read the pending message into the buffer */
+				r = read(wm[i]->in_sock, wm[i]->event_buf, sizeof(wm[i]->event_buf));
+				if (r == -1) {
+					/* error reading data */
+					WIIUSE_ERROR("Receiving wiimote data (id %i).", wm[i]->unid);
+					perror("Error Details");
+
+					if (errno == ENOTCONN) {
+						/* this can happen if the bluetooth dongle is disconnected */
+						WIIUSE_ERROR("Bluetooth appears to be disconnected.  Wiimote unid %i will be disconnected.", wm[i]->unid);
+						wiiuse_disconnect(wm[i]);
+						wm[i]->event = WIIUSE_UNEXPECTED_DISCONNECT;
+					}
+
+					continue;
+				}
+				if (!r) {
+					/* remote disconnect */
+					wiiuse_disconnected(wm[i]);
+					evnt = 1;
+					continue;
+				}
+
+				/* propagate the event */
+				propagate_event(wm[i], wm[i]->event_buf[1], wm[i]->event_buf+2);
+				evnt += (wm[i]->event != WIIUSE_NONE);
+			} else {
+				idle_cycle(wm[i]);
+			}
+		}
+	#else
+		/*
+		 *	Windows
+		 */
+		int i;
+
+		if (!wm) return 0;
+
+		for (i = 0; i < wiimotes; ++i) {
+			wm[i]->event = WIIUSE_NONE;
+
+			if (wiiuse_io_read(wm[i])) {
+				/* propagate the event */
+				propagate_event(wm[i], wm[i]->event_buf[0], wm[i]->event_buf+1);
+				evnt += (wm[i]->event != WIIUSE_NONE);
+
+				/* clear out the event buffer */
+				memset(wm[i]->event_buf, 0, sizeof(wm[i]->event_buf));
+			} else {
+				idle_cycle(wm[i]);
+			}
+		}
+	#endif
+
+	return evnt;
+}
+
diff --git a/3rdparty/wiiuse/src/events.h b/3rdparty/wiiuse/src/events.h
new file mode 100644
index 0000000..8a11122
--- /dev/null
+++ b/3rdparty/wiiuse/src/events.h
@@ -0,0 +1,52 @@
+/*
+ *	wiiuse
+ *
+ *	Written By:
+ *		Michael Laforest	< para >
+ *		Email: < thepara (--AT--) g m a i l [--DOT--] com >
+ *
+ *	Copyright 2006-2007
+ *
+ *	This file is part of wiiuse.
+ *
+ *	This program is free software; you can redistribute it and/or modify
+ *	it under the terms of the GNU General Public License as published by
+ *	the Free Software Foundation; either version 3 of the License, or
+ *	(at your option) any later version.
+ *
+ *	This program is distributed in the hope that it will be useful,
+ *	but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *	GNU General Public License for more details.
+ *
+ *	You should have received a copy of the GNU General Public License
+ *	along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ *	$Header$
+ *
+ */
+
+/**
+ *	@file
+ *	@brief Handles wiimote events.
+ *
+ *	The file includes functions that handle the events
+ *	that are sent from the wiimote to us.
+ */
+
+#ifndef EVENTS_H_INCLUDED
+#define EVENTS_H_INCLUDED
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void wiiuse_pressed_buttons(struct wiimote_t* wm, byte* msg);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif // EVENTS_H_INCLUDED
diff --git a/3rdparty/wiiuse/src/guitar_hero_3.c b/3rdparty/wiiuse/src/guitar_hero_3.c
new file mode 100644
index 0000000..2b99129
--- /dev/null
+++ b/3rdparty/wiiuse/src/guitar_hero_3.c
@@ -0,0 +1,173 @@
+/*
+ *	wiiuse
+ *
+ *	Written By:
+ *		Michael Laforest	< para >
+ *		Email: < thepara (--AT--) g m a i l [--DOT--] com >
+ *
+ *	Copyright 2006-2007
+ *
+ *	This file is part of wiiuse.
+ *
+ *	This program is free software; you can redistribute it and/or modify
+ *	it under the terms of the GNU General Public License as published by
+ *	the Free Software Foundation; either version 3 of the License, or
+ *	(at your option) any later version.
+ *
+ *	This program is distributed in the hope that it will be useful,
+ *	but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *	GNU General Public License for more details.
+ *
+ *	You should have received a copy of the GNU General Public License
+ *	along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ *	$Header$
+ *
+ */
+
+/**
+ *	@file
+ *	@brief Guitar Hero 3 expansion device.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <math.h>
+
+#ifdef WIN32
+	#include <Winsock2.h>
+#endif
+
+#include "definitions.h"
+#include "wiiuse_internal.h"
+#include "dynamics.h"
+#include "events.h"
+#include "guitar_hero_3.h"
+#include "io.h"
+
+static void guitar_hero_3_pressed_buttons(struct guitar_hero_3_t* gh3, short now);
+
+/**
+ *	@brief Handle the handshake data from the guitar.
+ *
+ *	@param cc		A pointer to a classic_ctrl_t structure.
+ *	@param data		The data read in from the device.
+ *	@param len		The length of the data block, in bytes.
+ *
+ *	@return	Returns 1 if handshake was successful, 0 if not.
+ */
+int guitar_hero_3_handshake(struct wiimote_t* wm, struct guitar_hero_3_t* gh3, byte* data, unsigned short len) {
+	int i;
+	int offset = 0;
+
+	/*
+	 *	The good fellows that made the Guitar Hero 3 controller
+	 *	failed to factory calibrate the devices.  There is no
+	 *	calibration data on the device.
+	 */
+
+	gh3->btns = 0;
+	gh3->btns_held = 0;
+	gh3->btns_released = 0;
+	gh3->whammy_bar = 0.0f;
+
+	/* decrypt data */
+	for (i = 0; i < len; ++i)
+		data[i] = (data[i] ^ 0x17) + 0x17;
+
+	if (data[offset] == 0xFF) {
+		/*
+		 *	Sometimes the data returned here is not correct.
+		 *	This might happen because the wiimote is lagging
+		 *	behind our initialization sequence.
+		 *	To fix this just request the handshake again.
+		 *
+		 *	Other times it's just the first 16 bytes are 0xFF,
+		 *	but since the next 16 bytes are the same, just use
+		 *	those.
+		 */
+		if (data[offset + 16] == 0xFF) {
+			/* get the calibration data */
+			byte* handshake_buf = malloc(EXP_HANDSHAKE_LEN * sizeof(byte));
+
+			WIIUSE_DEBUG("Guitar Hero 3 handshake appears invalid, trying again.");
+			wiiuse_read_data_cb(wm, handshake_expansion, handshake_buf, WM_EXP_MEM_CALIBR, EXP_HANDSHAKE_LEN);
+
+			return 0;
+		} else
+			offset += 16;
+	}
+
+	/* joystick stuff */
+	gh3->js.max.x = GUITAR_HERO_3_JS_MAX_X;
+	gh3->js.min.x = GUITAR_HERO_3_JS_MIN_X;
+	gh3->js.center.x = GUITAR_HERO_3_JS_CENTER_X;
+	gh3->js.max.y = GUITAR_HERO_3_JS_MAX_Y;
+	gh3->js.min.y = GUITAR_HERO_3_JS_MIN_Y;
+	gh3->js.center.y = GUITAR_HERO_3_JS_CENTER_Y;
+
+	/* handshake done */
+	wm->exp.type = EXP_GUITAR_HERO_3;
+
+	#ifdef WIN32
+	wm->timeout = WIIMOTE_DEFAULT_TIMEOUT;
+	#endif
+
+	return 1;
+}
+
+
+/**
+ *	@brief The guitar disconnected.
+ *
+ *	@param cc		A pointer to a classic_ctrl_t structure.
+ */
+void guitar_hero_3_disconnected(struct guitar_hero_3_t* gh3) {
+	memset(gh3, 0, sizeof(struct guitar_hero_3_t));
+}
+
+
+
+/**
+ *	@brief Handle guitar event.
+ *
+ *	@param cc		A pointer to a classic_ctrl_t structure.
+ *	@param msg		The message specified in the event packet.
+ */
+void guitar_hero_3_event(struct guitar_hero_3_t* gh3, byte* msg) {
+	int i;
+
+	/* decrypt data */
+	for (i = 0; i < 6; ++i)
+		msg[i] = (msg[i] ^ 0x17) + 0x17;
+
+	guitar_hero_3_pressed_buttons(gh3, BIG_ENDIAN_SHORT(*(short*)(msg + 4)));
+
+	/* whammy bar */
+	gh3->whammy_bar = (msg[3] - GUITAR_HERO_3_WHAMMY_BAR_MIN) / (float)(GUITAR_HERO_3_WHAMMY_BAR_MAX - GUITAR_HERO_3_WHAMMY_BAR_MIN);
+
+	/* joy stick */
+	calc_joystick_state(&gh3->js, msg[0], msg[1]);
+}
+
+
+/**
+ *	@brief Find what buttons are pressed.
+ *
+ *	@param cc		A pointer to a classic_ctrl_t structure.
+ *	@param msg		The message byte specified in the event packet.
+ */
+static void guitar_hero_3_pressed_buttons(struct guitar_hero_3_t* gh3, short now) {
+	/* message is inverted (0 is active, 1 is inactive) */
+	now = ~now & GUITAR_HERO_3_BUTTON_ALL;
+
+	/* pressed now & were pressed, then held */
+	gh3->btns_held = (now & gh3->btns);
+
+	/* were pressed or were held & not pressed now, then released */
+	gh3->btns_released = ((gh3->btns | gh3->btns_held) & ~now);
+
+	/* buttons pressed now */
+	gh3->btns = now;
+}
diff --git a/3rdparty/wiiuse/src/guitar_hero_3.h b/3rdparty/wiiuse/src/guitar_hero_3.h
new file mode 100644
index 0000000..3443d87
--- /dev/null
+++ b/3rdparty/wiiuse/src/guitar_hero_3.h
@@ -0,0 +1,62 @@
+/*
+ *	wiiuse
+ *
+ *	Written By:
+ *		Michael Laforest	< para >
+ *		Email: < thepara (--AT--) g m a i l [--DOT--] com >
+ *
+ *	Copyright 2006-2007
+ *
+ *	This file is part of wiiuse.
+ *
+ *	This program is free software; you can redistribute it and/or modify
+ *	it under the terms of the GNU General Public License as published by
+ *	the Free Software Foundation; either version 3 of the License, or
+ *	(at your option) any later version.
+ *
+ *	This program is distributed in the hope that it will be useful,
+ *	but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *	GNU General Public License for more details.
+ *
+ *	You should have received a copy of the GNU General Public License
+ *	along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ *	$Header$
+ *
+ */
+
+/**
+ *	@file
+ *	@brief Guitar Hero 3 expansion device.
+ */
+
+#ifndef GUITAR_HERO_3_H_INCLUDED
+#define GUITAR_HERO_3_H_INCLUDED
+
+#include "wiiuse_internal.h"
+
+#define GUITAR_HERO_3_JS_MIN_X				0xC5
+#define GUITAR_HERO_3_JS_MAX_X				0xFC
+#define GUITAR_HERO_3_JS_CENTER_X			0xE0
+#define GUITAR_HERO_3_JS_MIN_Y				0xC5
+#define GUITAR_HERO_3_JS_MAX_Y				0xFA
+#define GUITAR_HERO_3_JS_CENTER_Y			0xE0
+#define GUITAR_HERO_3_WHAMMY_BAR_MIN		0xEF
+#define GUITAR_HERO_3_WHAMMY_BAR_MAX		0xFA
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+int guitar_hero_3_handshake(struct wiimote_t* wm, struct guitar_hero_3_t* gh3, byte* data, unsigned short len);
+
+void guitar_hero_3_disconnected(struct guitar_hero_3_t* gh3);
+
+void guitar_hero_3_event(struct guitar_hero_3_t* gh3, byte* msg);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // GUITAR_HERO_3_H_INCLUDED
diff --git a/3rdparty/wiiuse/src/io.c b/3rdparty/wiiuse/src/io.c
new file mode 100644
index 0000000..ed33b38
--- /dev/null
+++ b/3rdparty/wiiuse/src/io.c
@@ -0,0 +1,276 @@
+/*
+ *	wiiuse
+ *
+ *	Written By:
+ *		Michael Laforest	< para >
+ *		Michal Wiedenbauer	< shagkur >
+ *		Dave Murphy			< WinterMute >
+ *		Hector Martin		< marcan >
+ *		William Alozy		< wiill >
+ *
+ *	Copyright 2009
+ *
+ *
+ *	This file is part of wiiuse and fWIIne.
+ *
+ *	This program is free software; you can redistribute it and/or modify
+ *	it under the terms of the GNU General Public License as published by
+ *	the Free Software Foundation; either version 3 of the License, or
+ *	(at your option) any later version.
+ *
+ *	This program is distributed in the hope that it will be useful,
+ *	but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *	GNU General Public License for more details.
+ *
+ *	You should have received a copy of the GNU General Public License
+ *	along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ *	$Header$
+ *
+ */
+
+/**
+ *	@file
+ *	@brief Handles device I/O (non-OS specific).
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "definitions.h"
+#include "wiiuse_internal.h"
+#include "nunchuk.h"
+#include "classic.h"
+#include "guitar_hero_3.h"
+#include "balance_board.h"
+#include "motion_plus.h"
+#include "io.h"
+
+
+ /**
+ *	@brief Get initialization data from the wiimote.
+ *
+ *	@param wm		Pointer to a wiimote_t structure.
+ *	@param data		unused
+ *	@param len		unused
+ *
+ *	When first called for a wiimote_t structure, a request
+ *	is sent to the wiimote for initialization information.
+ *	This includes factory set accelerometer data.
+ *	The handshake will be concluded when the wiimote responds
+ *	with this data.
+ */
+void wiiuse_handshake(struct wiimote_t* wm, byte* data, unsigned short len) {
+	if (!wm)	return;
+
+	switch (wm->handshake_state) {
+		case 0:
+		{
+			/* send request to wiimote for accelerometer calibration */
+			byte* buf;
+
+			WIIMOTE_ENABLE_STATE(wm, WIIMOTE_STATE_HANDSHAKE);
+			wiiuse_set_leds(wm, WIIMOTE_LED_NONE);
+
+			buf = (byte*)malloc(sizeof(byte) * 8);
+			wiiuse_read_data_cb(wm, wiiuse_handshake, buf, WM_MEM_OFFSET_CALIBRATION, 7);
+			wm->handshake_state++;
+			
+			wiiuse_set_leds(wm, WIIMOTE_LED_NONE);
+
+			break;
+		}
+		case 1:
+		{
+			struct read_req_t* req = wm->read_req;
+			struct accel_t* accel = &wm->accel_calib;
+
+			accel->cal_zero.x = ((data[0]<<2)|((data[3]>>4)&3));
+			accel->cal_zero.y = ((data[1]<<2)|((data[3]>>2)&3));
+			accel->cal_zero.z = ((data[2]<<2)|(data[3]&3));
+
+			accel->cal_g.x = (((data[4]<<2)|((data[7]>>4)&3)) - accel->cal_zero.x);
+			accel->cal_g.y = (((data[5]<<2)|((data[7]>>2)&3)) - accel->cal_zero.y);
+			accel->cal_g.z = (((data[6]<<2)|(data[7]&3)) - accel->cal_zero.z);
+			/* received read data */
+			/*accel->cal_zero.x = req->buf[0];
+			accel->cal_zero.y = req->buf[1];
+			accel->cal_zero.z = req->buf[2];
+
+			accel->cal_g.x = req->buf[4] - accel->cal_zero.x;
+			accel->cal_g.y = req->buf[5] - accel->cal_zero.y;
+			accel->cal_g.z = req->buf[6] - accel->cal_zero.z;*/
+
+			/* done with the buffer */
+			free(req->buf);
+
+			/* handshake is done */
+			WIIUSE_DEBUG("Handshake finished. Calibration: Idle: X=%x Y=%x Z=%x\t+1g: X=%x Y=%x Z=%x",
+					accel->cal_zero.x, accel->cal_zero.y, accel->cal_zero.z,
+					accel->cal_g.x, accel->cal_g.y, accel->cal_g.z);
+
+
+			/* request the status of the wiimote to see if there is an expansion */
+			wiiuse_status(wm);
+			
+			WIIMOTE_DISABLE_STATE(wm, WIIMOTE_STATE_HANDSHAKE);
+			WIIMOTE_ENABLE_STATE(wm, WIIMOTE_STATE_HANDSHAKE_COMPLETE);
+			wm->handshake_state++;
+
+			/* now enable IR if it was set before the handshake completed */
+			if (WIIMOTE_IS_SET(wm, WIIMOTE_STATE_IR)) {
+				WIIUSE_DEBUG("Handshake finished, enabling IR.");
+				WIIMOTE_DISABLE_STATE(wm, WIIMOTE_STATE_IR);
+				wiiuse_set_ir(wm, 1);
+			}
+			wm->event = WIIUSE_CONNECT;
+			wiiuse_status(wm);
+
+			break;
+		}
+		default:
+		{
+			break;
+		}
+	}
+}
+void handshake_expansion_start(struct wiimote_t *wm)
+{
+	if(WIIMOTE_IS_SET(wm,WIIMOTE_STATE_EXP) || WIIMOTE_IS_SET(wm,WIIMOTE_STATE_EXP_FAILED) || WIIMOTE_IS_SET(wm,WIIMOTE_STATE_EXP_HANDSHAKE))
+		return;
+
+	wm->expansion_state = 0;
+	WIIMOTE_ENABLE_STATE(wm, WIIMOTE_STATE_EXP_HANDSHAKE);
+	handshake_expansion(wm, NULL, 0);
+}
+
+/**
+ *	@brief Handle the handshake data from the expansion device.
+ *
+ *	@param wm		A pointer to a wiimote_t structure.
+ *	@param data		The data read in from the device.
+ *	@param len		The length of the data block, in bytes.
+ *
+ *	Tries to determine what kind of expansion was attached
+ *	and invoke the correct handshake function.
+ *
+ *	If the data is NULL then this function will try to start
+ *	a handshake with the expansion.
+ */
+void handshake_expansion(struct wiimote_t* wm, byte* data, unsigned short len) {
+	int id;
+	byte val;
+	byte* handshake_buf;
+
+	switch(wm->expansion_state) {
+		/* These two initialization writes disable the encryption */
+		case 0:
+			wm->expansion_state = 1;
+			/* increase the timeout until the handshake completes */
+			//#ifdef WIN32
+			//WIIUSE_DEBUG("write 0x55 - Setting timeout to expansion %i ms.", wm->exp_timeout);
+			//wm->timeout = wm->exp_timeout;
+			//#endif
+			val = 0x55;
+			wiiuse_write_data_cb(wm, WM_EXP_MEM_ENABLE1, &val, 1, handshake_expansion);
+			break;
+		case 1:
+			wm->expansion_state = 2;
+			/* increase the timeout until the handshake completes */
+			//#ifdef WIN32
+			//WIIUSE_DEBUG("write 0x00 - Setting timeout to expansion %i ms.", wm->exp_timeout);
+			//wm->timeout = wm->exp_timeout;
+			//#endif
+			val = 0x00;
+			wiiuse_write_data_cb(wm, WM_EXP_MEM_ENABLE2, &val, 1, handshake_expansion);
+			break;
+		case 2:
+			wm->expansion_state = 3;
+			/* get the calibration data */
+			if (WIIMOTE_IS_SET(wm, WIIMOTE_STATE_EXP))
+				disable_expansion(wm);
+			handshake_buf = malloc(EXP_HANDSHAKE_LEN * sizeof(byte));
+			wiiuse_read_data_cb(wm, handshake_expansion, handshake_buf, WM_EXP_MEM_CALIBR, EXP_HANDSHAKE_LEN);
+
+			/* tell the wiimote to send expansion data */
+			WIIMOTE_ENABLE_STATE(wm, WIIMOTE_STATE_EXP);
+			break;
+		case 3:
+			if(!data || !len) return;
+			id = BIG_ENDIAN_LONG(*(int*)(data + 220));
+			switch(id) {
+				case EXP_ID_CODE_NUNCHUK:
+					if (nunchuk_handshake(wm, &wm->exp.nunchuk, data, len)) 
+						wm->event = WIIUSE_NUNCHUK_INSERTED;
+					break;
+				case EXP_ID_CODE_CLASSIC_CONTROLLER:
+					if (classic_ctrl_handshake(wm, &wm->exp.classic, data, len)) 
+						wm->event = WIIUSE_CLASSIC_CTRL_INSERTED;
+					break;
+				case EXP_ID_CODE_GUITAR:
+					if (guitar_hero_3_handshake(wm, &wm->exp.gh3, data, len))
+						wm->event = WIIUSE_GUITAR_HERO_3_CTRL_INSERTED;
+					break;
+				case EXP_ID_CODE_BALANCE_BOARD:
+					if (balance_board_handshake(wm, &wm->exp.bb, data, len))
+						wm->event = WIIUSE_BALANCE_BOARD_CTRL_INSERTED;
+					break;				
+ 				default:
+					WIIUSE_WARNING("Unknown expansion type. Code: 0x%x", id);
+					break;
+			}
+			free(data);
+			WIIMOTE_DISABLE_STATE(wm,WIIMOTE_STATE_EXP_HANDSHAKE);
+			WIIMOTE_ENABLE_STATE(wm,WIIMOTE_STATE_EXP);
+			wiiuse_set_ir_mode(wm);
+			wiiuse_status(wm);
+			break;
+	}
+}
+
+
+/**
+ *	@brief Disable the expansion device if it was enabled.
+ *
+ *	@param wm		A pointer to a wiimote_t structure.
+ *	@param data		The data read in from the device.
+ *	@param len		The length of the data block, in bytes.
+ *
+ *	If the data is NULL then this function will try to start
+ *	a handshake with the expansion.
+ */
+void disable_expansion(struct wiimote_t* wm) {
+	if (!WIIMOTE_IS_SET(wm, WIIMOTE_STATE_EXP))
+		return;
+
+	/* tell the assoicated module the expansion was removed */
+	switch (wm->exp.type) {
+		case EXP_NUNCHUK:
+			nunchuk_disconnected(&wm->exp.nunchuk);
+			wm->event = WIIUSE_NUNCHUK_REMOVED;
+			break;
+		case EXP_CLASSIC:
+			classic_ctrl_disconnected(&wm->exp.classic);
+			wm->event = WIIUSE_CLASSIC_CTRL_REMOVED;
+			break;
+		case EXP_GUITAR_HERO_3:
+			guitar_hero_3_disconnected(&wm->exp.gh3);
+			wm->event = WIIUSE_GUITAR_HERO_3_CTRL_REMOVED;
+			break;
+		case EXP_MOTION_PLUS:
+ 			motion_plus_disconnected(&wm->exp.mp);
+ 			wm->event = WIIUSE_MOTION_PLUS_REMOVED;
+ 			break;
+		case EXP_BALANCE_BOARD:
+			balance_board_disconnected(&wm->exp.bb);
+			wm->event = WIIUSE_BALANCE_BOARD_CTRL_REMOVED;
+			break;
+		default:
+			break;
+	}
+
+	WIIMOTE_DISABLE_STATE(wm, WIIMOTE_STATE_EXP);
+	wm->exp.type = EXP_NONE;
+}
+
diff --git a/3rdparty/wiiuse/src/io.h b/3rdparty/wiiuse/src/io.h
new file mode 100644
index 0000000..d89adad
--- /dev/null
+++ b/3rdparty/wiiuse/src/io.h
@@ -0,0 +1,59 @@
+/*
+ *	wiiuse
+ *
+ *	Written By:
+ *		Michael Laforest	< para >
+ *		Email: < thepara (--AT--) g m a i l [--DOT--] com >
+ *
+ *	Copyright 2006-2007
+ *
+ *	This file is part of wiiuse.
+ *
+ *	This program is free software; you can redistribute it and/or modify
+ *	it under the terms of the GNU General Public License as published by
+ *	the Free Software Foundation; either version 3 of the License, or
+ *	(at your option) any later version.
+ *
+ *	This program is distributed in the hope that it will be useful,
+ *	but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *	GNU General Public License for more details.
+ *
+ *	You should have received a copy of the GNU General Public License
+ *	along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ *	$Header$
+ *
+ */
+
+/**
+ *	@file
+ *	@brief Handles device I/O.
+ */
+
+#ifndef CONNECT_H_INCLUDED
+#define CONNECT_H_INCLUDED
+
+#ifndef WIN32
+	#include <bluetooth/bluetooth.h>
+#endif
+
+#include "wiiuse_internal.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void wiiuse_handshake(struct wiimote_t* wm, byte* data, unsigned short len);
+void handshake_expansion_start(struct wiimote_t* wm);
+void handshake_expansion(struct wiimote_t* wm, byte* data, unsigned short len);
+void disable_expansion(struct wiimote_t* wm);
+
+int wiiuse_io_read(struct wiimote_t* wm);
+int wiiuse_io_write(struct wiimote_t* wm, byte* buf, int len);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // CONNECT_H_INCLUDED
diff --git a/3rdparty/wiiuse/src/io_nix.c b/3rdparty/wiiuse/src/io_nix.c
new file mode 100644
index 0000000..6b22942
--- /dev/null
+++ b/3rdparty/wiiuse/src/io_nix.c
@@ -0,0 +1,272 @@
+/*
+ *	wiiuse
+ *
+ *	Written By:
+ *		Michael Laforest	< para >
+ *		Email: < thepara (--AT--) g m a i l [--DOT--] com >
+ *
+ *	Copyright 2006-2007
+ *
+ *	This file is part of wiiuse.
+ *
+ *	This program is free software; you can redistribute it and/or modify
+ *	it under the terms of the GNU General Public License as published by
+ *	the Free Software Foundation; either version 3 of the License, or
+ *	(at your option) any later version.
+ *
+ *	This program is distributed in the hope that it will be useful,
+ *	but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *	GNU General Public License for more details.
+ *
+ *	You should have received a copy of the GNU General Public License
+ *	along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ *	$Header$
+ *
+ */
+
+/**
+ *	@file
+ *	@brief Handles device I/O for *nix.
+ */
+
+#ifndef WIN32
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include <bluetooth/bluetooth.h>
+#include <bluetooth/hci.h>
+#include <bluetooth/hci_lib.h>
+#include <bluetooth/l2cap.h>
+
+#include "definitions.h"
+#include "wiiuse_internal.h"
+#include "io.h"
+
+static int wiiuse_connect_single(struct wiimote_t* wm, char* address);
+
+/**
+ *	@brief Find a wiimote or wiimotes.
+ *
+ *	@param wm			An array of wiimote_t structures.
+ *	@param max_wiimotes	The number of wiimote structures in \a wm.
+ *	@param timeout		The number of seconds before the search times out.
+ *
+ *	@return The number of wiimotes found.
+ *
+ *	@see wiimote_connect()
+ *
+ *	This function will only look for wiimote devices.						\n
+ *	When a device is found the address in the structures will be set.		\n
+ *	You can then call wiimote_connect() to connect to the found				\n
+ *	devices.
+ */
+int wiiuse_find(struct wiimote_t** wm, int max_wiimotes, int timeout) {
+	int device_id;
+	int device_sock;
+	int found_devices;
+	int found_wiimotes;
+
+	/* reset all wiimote bluetooth device addresses */
+	for (found_wiimotes = 0; found_wiimotes < max_wiimotes; ++found_wiimotes)
+		wm[found_wiimotes]->bdaddr = *BDADDR_ANY;
+	found_wiimotes = 0;
+
+	/* get the id of the first bluetooth device. */
+	device_id = hci_get_route(NULL);
+	if (device_id < 0) {
+		perror("hci_get_route");
+		return 0;
+	}
+
+	/* create a socket to the device */
+	device_sock = hci_open_dev(device_id);
+	if (device_sock < 0) {
+		perror("hci_open_dev");
+		return 0;
+	}
+
+	inquiry_info scan_info_arr[128];
+	inquiry_info* scan_info = scan_info_arr;
+	memset(&scan_info_arr, 0, sizeof(scan_info_arr));
+
+	/* scan for bluetooth devices for 'timeout' seconds */
+	found_devices = hci_inquiry(device_id, timeout, 128, NULL, &scan_info, IREQ_CACHE_FLUSH);
+	if (found_devices < 0) {
+		perror("hci_inquiry");
+		return 0;
+	}
+
+	WIIUSE_INFO("Found %i bluetooth device(s).", found_devices);
+
+	int i = 0;
+
+	/* display discovered devices */
+	for (; (i < found_devices) && (found_wiimotes < max_wiimotes); ++i) {
+		if ((scan_info[i].dev_class[0] == WM_DEV_CLASS_0) &&
+			(scan_info[i].dev_class[1] == WM_DEV_CLASS_1) &&
+			(scan_info[i].dev_class[2] == WM_DEV_CLASS_2))
+		{
+			/* found a device */
+			ba2str(&scan_info[i].bdaddr, wm[found_wiimotes]->bdaddr_str);
+
+			WIIUSE_INFO("Found wiimote (%s) [id %i].", wm[found_wiimotes]->bdaddr_str, wm[found_wiimotes]->unid);
+
+			wm[found_wiimotes]->bdaddr = scan_info[i].bdaddr;
+			WIIMOTE_ENABLE_STATE(wm[found_wiimotes], WIIMOTE_STATE_DEV_FOUND);
+			++found_wiimotes;
+		}
+	}
+
+	close(device_sock);
+	return found_wiimotes;
+}
+
+
+/**
+ *	@brief Connect to a wiimote or wiimotes once an address is known.
+ *
+ *	@param wm			An array of wiimote_t structures.
+ *	@param wiimotes		The number of wiimote structures in \a wm.
+ *
+ *	@return The number of wiimotes that successfully connected.
+ *
+ *	@see wiiuse_find()
+ *	@see wiiuse_connect_single()
+ *	@see wiiuse_disconnect()
+ *
+ *	Connect to a number of wiimotes when the address is already set
+ *	in the wiimote_t structures.  These addresses are normally set
+ *	by the wiiuse_find() function, but can also be set manually.
+ */
+int wiiuse_connect(struct wiimote_t** wm, int wiimotes) {
+	int connected = 0;
+	int i = 0;
+
+	for (; i < wiimotes; ++i) {
+		if (!WIIMOTE_IS_SET(wm[i], WIIMOTE_STATE_DEV_FOUND))
+			/* if the device address is not set, skip it */
+			continue;
+
+		if (wiiuse_connect_single(wm[i], NULL))
+			++connected;
+	}
+
+	return connected;
+}
+
+
+/**
+ *	@brief Connect to a wiimote with a known address.
+ *
+ *	@param wm		Pointer to a wiimote_t structure.
+ *	@param address	The address of the device to connect to.
+ *					If NULL, use the address in the struct set by wiiuse_find().
+ *
+ *	@return 1 on success, 0 on failure
+ */
+static int wiiuse_connect_single(struct wiimote_t* wm, char* address) {
+	struct sockaddr_l2 addr;
+
+	if (!wm || WIIMOTE_IS_CONNECTED(wm))
+		return 0;
+
+    bzero (&addr, sizeof(addr));
+
+	addr.l2_family = AF_BLUETOOTH;
+
+	if (address)
+		/* use provided address */
+		str2ba(address, &addr.l2_bdaddr);
+	else
+		/* use address of device discovered */
+		addr.l2_bdaddr = wm->bdaddr;
+
+	/*
+	 *	OUTPUT CHANNEL
+	 */
+	wm->out_sock = socket(AF_BLUETOOTH, SOCK_SEQPACKET, BTPROTO_L2CAP);
+	if (wm->out_sock == -1)
+		return 0;
+
+	addr.l2_psm = htobs(WM_OUTPUT_CHANNEL);
+
+	/* connect to wiimote */
+	if (connect(wm->out_sock, (struct sockaddr*)&addr, sizeof(addr)) < 0) {
+		perror("connect() output sock");
+		return 0;
+	}
+
+	/*
+	 *	INPUT CHANNEL
+	 */
+	wm->in_sock = socket(AF_BLUETOOTH, SOCK_SEQPACKET, BTPROTO_L2CAP);
+	if (wm->in_sock == -1) {
+		close(wm->out_sock);
+		wm->out_sock = -1;
+		return 0;
+	}
+
+	addr.l2_psm = htobs(WM_INPUT_CHANNEL);
+
+	/* connect to wiimote */
+	if (connect(wm->in_sock, (struct sockaddr*)&addr, sizeof(addr)) < 0) {
+		perror("connect() interrupt sock");
+		close(wm->out_sock);
+		wm->out_sock = -1;
+		return 0;
+	}
+
+	WIIUSE_INFO("Connected to wiimote [id %i].", wm->unid);
+
+	/* do the handshake */
+	WIIMOTE_ENABLE_STATE(wm, WIIMOTE_STATE_CONNECTED);
+	wiiuse_handshake(wm, NULL, 0);
+
+	wiiuse_set_report_type(wm);
+
+	return 1;
+}
+
+
+/**
+ *	@brief Disconnect a wiimote.
+ *
+ *	@param wm		Pointer to a wiimote_t structure.
+ *
+ *	@see wiiuse_connect()
+ *
+ *	Note that this will not free the wiimote structure.
+ */
+void wiiuse_disconnect(struct wiimote_t* wm) {
+	if (!wm || WIIMOTE_IS_CONNECTED(wm))
+		return;
+
+	close(wm->out_sock);
+	close(wm->in_sock);
+
+	wm->out_sock = -1;
+	wm->in_sock = -1;
+	wm->event = WIIUSE_NONE;
+
+	WIIMOTE_DISABLE_STATE(wm, WIIMOTE_STATE_CONNECTED);
+	WIIMOTE_DISABLE_STATE(wm, WIIMOTE_STATE_HANDSHAKE);
+}
+
+
+int wiiuse_io_read(struct wiimote_t* wm) {
+	/* not used */
+	return 0;
+}
+
+
+int wiiuse_io_write(struct wiimote_t* wm, byte* buf, int len) {
+	return write(wm->out_sock, buf, len);
+}
+
+
+
+#endif /* ifndef WIN32 */
diff --git a/3rdparty/wiiuse/src/io_win.c b/3rdparty/wiiuse/src/io_win.c
new file mode 100644
index 0000000..12e5cdb
--- /dev/null
+++ b/3rdparty/wiiuse/src/io_win.c
@@ -0,0 +1,253 @@
+/*
+ *	wiiuse
+ *
+ *	Written By:
+ *		Michael Laforest	< para >
+ *		Email: < thepara (--AT--) g m a i l [--DOT--] com >
+ *
+ *	Copyright 2006-2007
+ *
+ *	This file is part of wiiuse.
+ *
+ *	This program is free software; you can redistribute it and/or modify
+ *	it under the terms of the GNU General Public License as published by
+ *	the Free Software Foundation; either version 3 of the License, or
+ *	(at your option) any later version.
+ *
+ *	This program is distributed in the hope that it will be useful,
+ *	but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *	GNU General Public License for more details.
+ *
+ *	You should have received a copy of the GNU General Public License
+ *	along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ *	$Header$
+ *
+ */
+
+/**
+ *	@file
+ *	@brief Handles device I/O for Windows.
+ */
+
+#ifdef WIN32
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <windows.h>
+#include <hidsdi.h>
+#include <setupapi.h>
+
+#include "definitions.h"
+#include "wiiuse_internal.h"
+#include "io.h"
+
+
+int wiiuse_find(struct wiimote_t** wm, int max_wiimotes, int timeout) {
+	GUID device_id;
+	HANDLE dev;
+	HDEVINFO device_info;
+	int i, index;
+	DWORD len;
+	SP_DEVICE_INTERFACE_DATA device_data;
+	PSP_DEVICE_INTERFACE_DETAIL_DATA detail_data = NULL;
+	HIDD_ATTRIBUTES	attr;
+	int found = 0;
+
+	(void) timeout; // unused
+
+	device_data.cbSize = sizeof(device_data);
+	index = 0;
+
+	/* get the device id */
+	HidD_GetHidGuid(&device_id);
+
+	/* get all hid devices connected */
+	device_info = SetupDiGetClassDevs(&device_id, NULL, NULL, (DIGCF_DEVICEINTERFACE | DIGCF_PRESENT));
+
+	for (;; ++index) {
+
+		if (detail_data) {
+			free(detail_data);
+			detail_data = NULL;
+		}
+
+		/* query the next hid device info */
+		if (!SetupDiEnumDeviceInterfaces(device_info, NULL, &device_id, index, &device_data))
+			break;
+
+		/* get the size of the data block required */
+		i = SetupDiGetDeviceInterfaceDetail(device_info, &device_data, NULL, 0, &len, NULL);
+		detail_data = malloc(len);
+		detail_data->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);
+
+		/* query the data for this device */
+		if (!SetupDiGetDeviceInterfaceDetail(device_info, &device_data, detail_data, len, NULL, NULL))
+			continue;
+
+		/* open the device */
+		dev = CreateFile(detail_data->DevicePath,
+						(GENERIC_READ | GENERIC_WRITE),
+						(FILE_SHARE_READ | FILE_SHARE_WRITE),
+						NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL);
+		if (dev == INVALID_HANDLE_VALUE)
+			continue;
+
+		/* get device attributes */
+		attr.Size = sizeof(attr);
+		i = HidD_GetAttributes(dev, &attr);
+
+		if ((attr.VendorID == WM_VENDOR_ID) && (attr.ProductID == WM_PRODUCT_ID)) {
+			/* this is a wiimote */
+			wm[found]->dev_handle = dev;
+
+			wm[found]->hid_overlap.hEvent = CreateEvent(NULL, 1, 1, NULL); //TEXT(""));
+			wm[found]->hid_overlap.Offset = 0;
+			wm[found]->hid_overlap.OffsetHigh = 0;
+
+			WIIMOTE_ENABLE_STATE(wm[found], WIIMOTE_STATE_DEV_FOUND);
+			WIIMOTE_ENABLE_STATE(wm[found], WIIMOTE_STATE_CONNECTED);
+
+			/* try to set the output report to see if the device is actually connected */
+			if (!wiiuse_set_report_type(wm[found])) {
+				wiiuse_disconnect(wm[found]);
+				WIIMOTE_DISABLE_STATE(wm[found], WIIMOTE_STATE_CONNECTED);								
+				continue;
+			}
+
+			/* do the handshake */
+			wiiuse_handshake(wm[found], NULL, 0);
+
+			WIIUSE_INFO("Connected to wiimote [id %i].", wm[found]->unid);
+
+			++found;
+			if (found >= max_wiimotes)
+				break;
+		} else {
+			/* not a wiimote */
+			CloseHandle(dev);
+		}
+	}
+
+	if (detail_data)
+		free(detail_data);
+
+	SetupDiDestroyDeviceInfoList(device_info);
+
+	return found;
+}
+
+
+int wiiuse_connect(struct wiimote_t** wm, int wiimotes) {
+	int connected = 0;
+	int i = 0;
+
+	for (; i < wiimotes; ++i) {
+		if (WIIMOTE_IS_SET(wm[i], WIIMOTE_STATE_CONNECTED))
+			++connected;
+	}
+
+	return connected;
+}
+
+
+void wiiuse_disconnect(struct wiimote_t* wm) {
+	if (!wm || !WIIMOTE_IS_CONNECTED(wm))
+		return;
+	
+	CloseHandle(wm->dev_handle);
+	wm->dev_handle = 0;
+
+//	ResetEvent(&wm->hid_overlap);
+	CloseHandle (wm->hid_overlap.hEvent);
+	wm->hid_overlap.hEvent= 0;
+
+	wm->event = WIIUSE_NONE;
+
+	WIIMOTE_DISABLE_STATE(wm, WIIMOTE_STATE_CONNECTED);
+	WIIMOTE_DISABLE_STATE(wm, WIIMOTE_STATE_HANDSHAKE);
+}
+
+
+int wiiuse_io_read(struct wiimote_t* wm) {
+	DWORD b, r;
+
+	if (!wm || !WIIMOTE_IS_CONNECTED(wm))
+		return 0;
+
+	if (!ReadFile(wm->dev_handle, wm->event_buf, sizeof(wm->event_buf), &b, &wm->hid_overlap)) {
+		/* partial read */
+		b = GetLastError();
+
+		if ((b == ERROR_HANDLE_EOF) || (b == ERROR_DEVICE_NOT_CONNECTED)) {
+			/* remote disconnect */
+			wiiuse_disconnected(wm);
+
+			/* return 1 to allow the event to be receive */
+			return 1;
+		}
+
+		// TODO: wait several remotes using WaitForMultipleObject
+		r = WaitForSingleObject(wm->hid_overlap.hEvent, wm->timeout);
+		if (r == WAIT_TIMEOUT) {
+			/* timeout - cancel and continue */
+
+			if (*wm->event_buf)
+				WIIUSE_WARNING("Packet ignored.  This may indicate a problem (timeout is %i ms).", wm->timeout);
+
+			CancelIo(wm->dev_handle);
+			ResetEvent(wm->hid_overlap.hEvent);
+			return 0;
+		} else if (r == WAIT_FAILED) {
+			WIIUSE_WARNING("A wait error occured on reading from wiimote %i.", wm->unid);
+			return 0;
+		}
+
+		if (!GetOverlappedResult(wm->dev_handle, &wm->hid_overlap, &b, 0))
+			return 0;
+	}
+
+	ResetEvent(wm->hid_overlap.hEvent);
+	return 1;
+}
+
+
+int wiiuse_io_write(struct wiimote_t* wm, byte* buf, int len) {
+	DWORD bytes;
+	int i;
+
+	if (!wm || !WIIMOTE_IS_CONNECTED(wm))
+		return 0;
+
+	switch (wm->stack) {
+		case WIIUSE_STACK_UNKNOWN:
+		{
+			/* try to auto-detect the stack type */
+			if (i = WriteFile(wm->dev_handle, buf, 22, &bytes, &wm->hid_overlap)) {
+				/* bluesoleil will always return 1 here, even if it's not connected */
+				wm->stack = WIIUSE_STACK_BLUESOLEIL;
+				return i;
+			}
+
+			if (i = HidD_SetOutputReport(wm->dev_handle, buf, len)) {
+				wm->stack = WIIUSE_STACK_MS;
+				return i;
+			}
+
+			WIIUSE_ERROR("Unable to determine bluetooth stack type.");
+			return 0;
+		}
+
+		case WIIUSE_STACK_MS:
+			return HidD_SetOutputReport(wm->dev_handle, buf, len);
+
+		case WIIUSE_STACK_BLUESOLEIL:
+			return WriteFile(wm->dev_handle, buf, 22, &bytes, &wm->hid_overlap);
+	}
+
+	return 0;
+}
+
+#endif /* ifdef WIN32 */
diff --git a/3rdparty/wiiuse/src/ir.c b/3rdparty/wiiuse/src/ir.c
new file mode 100644
index 0000000..83f949e
--- /dev/null
+++ b/3rdparty/wiiuse/src/ir.c
@@ -0,0 +1,758 @@
+/*
+ *	wiiuse
+ *
+ *	Written By:
+ *		Michael Laforest	< para >
+ *		Email: < thepara (--AT--) g m a i l [--DOT--] com >
+ *
+ *	Copyright 2006-2007
+ *
+ *	This file is part of wiiuse.
+ *
+ *	This program is free software; you can redistribute it and/or modify
+ *	it under the terms of the GNU General Public License as published by
+ *	the Free Software Foundation; either version 3 of the License, or
+ *	(at your option) any later version.
+ *
+ *	This program is distributed in the hope that it will be useful,
+ *	but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *	GNU General Public License for more details.
+ *
+ *	You should have received a copy of the GNU General Public License
+ *	along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ *	$Header$
+ *
+ */
+
+/**
+ *	@file
+ *	@brief Handles IR data.
+ */
+
+#include <stdio.h>
+#include <math.h>
+
+#ifndef WIN32
+	#include <unistd.h>
+#endif
+
+#include "definitions.h"
+#include "wiiuse_internal.h"
+#include "ir.h"
+
+static int get_ir_sens(struct wiimote_t* wm, char** block1, char** block2);
+static void interpret_ir_data(struct wiimote_t* wm);
+static void fix_rotated_ir_dots(struct ir_dot_t* dot, float ang);
+static void get_ir_dot_avg(struct ir_dot_t* dot, int* x, int* y);
+static void reorder_ir_dots(struct ir_dot_t* dot);
+static float ir_distance(struct ir_dot_t* dot);
+static int ir_correct_for_bounds(int* x, int* y, enum aspect_t aspect, int offset_x, int offset_y);
+static void ir_convert_to_vres(int* x, int* y, enum aspect_t aspect, int vx, int vy);
+
+void wiiuse_set_ir_mode(struct wiimote_t *wm)
+{
+	byte buf = 0x00;
+
+	if(!wm) return;
+	if(!WIIMOTE_IS_SET(wm,WIIMOTE_STATE_IR)) return;
+
+	if(WIIMOTE_IS_SET(wm,WIIMOTE_STATE_EXP)) buf = WM_IR_TYPE_BASIC;
+	else buf = WM_IR_TYPE_EXTENDED;
+	wiiuse_write_data(wm,WM_REG_IR_MODENUM, &buf, 1);
+}
+
+
+/**
+ *	@brief	Set if the wiimote should track IR targets.
+ *
+ *	@param wm		Pointer to a wiimote_t structure.
+ *	@param status	1 to enable, 0 to disable.
+ */
+void wiiuse_set_ir(struct wiimote_t* wm, int status) {
+	byte buf;
+	char* block1 = NULL;
+	char* block2 = NULL;
+	int ir_level;
+
+	if (!wm)
+		return;
+
+	/*
+	 *	Wait for the handshake to finish first.
+	 *	When it handshake finishes and sees that
+	 *	IR is enabled, it will call this function
+	 *	again to actually enable IR.
+	 */
+	if (!WIIMOTE_IS_SET(wm, WIIMOTE_STATE_HANDSHAKE_COMPLETE)) {
+		WIIUSE_DEBUG("Tried to enable IR, will wait until handshake finishes.");
+		WIIMOTE_ENABLE_STATE(wm, WIIMOTE_STATE_IR);
+		return;
+	}
+
+	/*
+	 *	Check to make sure a sensitivity setting is selected.
+	 */
+	ir_level = get_ir_sens(wm, &block1, &block2);
+	if (!ir_level) {
+		WIIUSE_ERROR("No IR sensitivity setting selected.");
+		return;
+	}
+
+	if (status) {
+		/* if already enabled then stop */
+		if (WIIMOTE_IS_SET(wm, WIIMOTE_STATE_IR))
+			return;
+		WIIMOTE_ENABLE_STATE(wm, WIIMOTE_STATE_IR);
+	} else {
+		/* if already disabled then stop */
+		if (!WIIMOTE_IS_SET(wm, WIIMOTE_STATE_IR))
+			return;
+		WIIMOTE_DISABLE_STATE(wm, WIIMOTE_STATE_IR);
+	}
+
+	/* set camera 1 and 2 */
+	buf = (status ? 0x04 : 0x00);
+	wiiuse_send(wm, WM_CMD_IR, &buf, 1);
+	wiiuse_send(wm, WM_CMD_IR_2, &buf, 1);
+
+	if (!status) {
+		WIIUSE_DEBUG("Disabled IR cameras for wiimote id %i.", wm->unid);
+		wiiuse_set_report_type(wm);
+		return;
+	}
+
+	/* enable IR, set sensitivity */
+	buf = 0x08;
+	wiiuse_write_data(wm, WM_REG_IR, &buf, 1);
+
+	/* wait for the wiimote to catch up */
+	#ifndef WIN32
+		usleep(50000);
+	#else
+		Sleep(50);
+	#endif
+
+	/* write sensitivity blocks */
+	wiiuse_write_data(wm, WM_REG_IR_BLOCK1, (byte*)block1, 9);
+	wiiuse_write_data(wm, WM_REG_IR_BLOCK2, (byte*)block2, 2);
+
+	/* set the IR mode */
+	if (WIIMOTE_IS_SET(wm, WIIMOTE_STATE_EXP))
+		buf = WM_IR_TYPE_BASIC;
+	else
+		buf = WM_IR_TYPE_EXTENDED;
+	wiiuse_write_data(wm, WM_REG_IR_MODENUM, &buf, 1);
+
+	#ifndef WIN32
+		usleep(50000);
+	#else
+		Sleep(50);
+	#endif
+
+	/* set the wiimote report type */
+	wiiuse_set_report_type(wm);
+
+	WIIUSE_DEBUG("Enabled IR camera for wiimote id %i (sensitivity level %i).", wm->unid, ir_level);
+}
+
+
+/**
+ *	@brief	Get the IR sensitivity settings.
+ *
+ *	@param wm		Pointer to a wiimote_t structure.
+ *	@param block1	[out] Pointer to where block1 will be set.
+ *	@param block2	[out] Pointer to where block2 will be set.
+ *
+ *	@return Returns the sensitivity level.
+ */
+static int get_ir_sens(struct wiimote_t* wm, char** block1, char** block2) {
+	if (WIIMOTE_IS_SET(wm, WIIMOTE_STATE_IR_SENS_LVL1)) {
+		*block1 = WM_IR_BLOCK1_LEVEL1;
+		*block2 = WM_IR_BLOCK2_LEVEL1;
+		return 1;
+	} else if (WIIMOTE_IS_SET(wm, WIIMOTE_STATE_IR_SENS_LVL2)) {
+		*block1 = WM_IR_BLOCK1_LEVEL2;
+		*block2 = WM_IR_BLOCK2_LEVEL2;
+		return 2;
+	} else if (WIIMOTE_IS_SET(wm, WIIMOTE_STATE_IR_SENS_LVL3)) {
+		*block1 = WM_IR_BLOCK1_LEVEL3;
+		*block2 = WM_IR_BLOCK2_LEVEL3;
+		return 3;
+	} else if (WIIMOTE_IS_SET(wm, WIIMOTE_STATE_IR_SENS_LVL4)) {
+		*block1 = WM_IR_BLOCK1_LEVEL4;
+		*block2 = WM_IR_BLOCK2_LEVEL4;
+		return 4;
+	} else if (WIIMOTE_IS_SET(wm, WIIMOTE_STATE_IR_SENS_LVL5)) {
+		*block1 = WM_IR_BLOCK1_LEVEL5;
+		*block2 = WM_IR_BLOCK2_LEVEL5;
+		return 5;
+	}
+
+	*block1 = NULL;
+	*block2 = NULL;
+	return 0;
+}
+
+
+/**
+ *	@brief	Set the virtual screen resolution for IR tracking.
+ *
+ *	@param wm		Pointer to a wiimote_t structure.
+ *	@param status	1 to enable, 0 to disable.
+ */
+void wiiuse_set_ir_vres(struct wiimote_t* wm, unsigned int x, unsigned int y) {
+	if (!wm)	return;
+
+	wm->ir.vres[0] = (x-1);
+	wm->ir.vres[1] = (y-1);
+}
+
+
+/**
+ *	@brief	Set the XY position for the IR cursor.
+ *
+ *	@param wm		Pointer to a wiimote_t structure.
+ */
+void wiiuse_set_ir_position(struct wiimote_t* wm, enum ir_position_t pos) {
+	if (!wm)	return;
+
+	wm->ir.pos = pos;
+
+	switch (pos) {
+
+		case WIIUSE_IR_ABOVE:
+			wm->ir.offset[0] = 0;
+
+			if (wm->ir.aspect == WIIUSE_ASPECT_16_9)
+				wm->ir.offset[1] = WM_ASPECT_16_9_Y/2 - 70;
+			else if (wm->ir.aspect == WIIUSE_ASPECT_4_3)
+				wm->ir.offset[1] = WM_ASPECT_4_3_Y/2 - 100;
+
+			return;
+
+		case WIIUSE_IR_BELOW:
+			wm->ir.offset[0] = 0;
+
+			if (wm->ir.aspect == WIIUSE_ASPECT_16_9)
+				wm->ir.offset[1] = -WM_ASPECT_16_9_Y/2 + 100;
+			else if (wm->ir.aspect == WIIUSE_ASPECT_4_3)
+				wm->ir.offset[1] = -WM_ASPECT_4_3_Y/2 + 70;
+
+			return;
+
+		default:
+			return;
+	};
+}
+
+
+/**
+ *	@brief	Set the aspect ratio of the TV/monitor.
+ *
+ *	@param wm		Pointer to a wiimote_t structure.
+ *	@param aspect	Either WIIUSE_ASPECT_16_9 or WIIUSE_ASPECT_4_3
+ */
+void wiiuse_set_aspect_ratio(struct wiimote_t* wm, enum aspect_t aspect) {
+	if (!wm)	return;
+
+	wm->ir.aspect = aspect;
+
+	if (aspect == WIIUSE_ASPECT_4_3) {
+		wm->ir.vres[0] = WM_ASPECT_4_3_X;
+		wm->ir.vres[1] = WM_ASPECT_4_3_Y;
+	} else {
+		wm->ir.vres[0] = WM_ASPECT_16_9_X;
+		wm->ir.vres[1] = WM_ASPECT_16_9_Y;
+	}
+
+	/* reset the position offsets */
+	wiiuse_set_ir_position(wm, wm->ir.pos);
+}
+
+
+/**
+ *	@brief	Set the IR sensitivity.
+ *
+ *	@param wm		Pointer to a wiimote_t structure.
+ *	@param level	1-5, same as Wii system sensitivity setting.
+ *
+ *	If the level is < 1, then level will be set to 1.
+ *	If the level is > 5, then level will be set to 5.
+ */
+void wiiuse_set_ir_sensitivity(struct wiimote_t* wm, int level) {
+	char* block1 = NULL;
+	char* block2 = NULL;
+
+	if (!wm)	return;
+
+	if (level > 5)		level = 5;
+	if (level < 1)		level = 1;
+
+	WIIMOTE_DISABLE_STATE(wm, (WIIMOTE_STATE_IR_SENS_LVL1 |
+								WIIMOTE_STATE_IR_SENS_LVL2 |
+								WIIMOTE_STATE_IR_SENS_LVL3 |
+								WIIMOTE_STATE_IR_SENS_LVL4 |
+								WIIMOTE_STATE_IR_SENS_LVL5));
+
+	switch (level) {
+		case 1:
+			WIIMOTE_ENABLE_STATE(wm, WIIMOTE_STATE_IR_SENS_LVL1);
+			break;
+		case 2:
+			WIIMOTE_ENABLE_STATE(wm, WIIMOTE_STATE_IR_SENS_LVL2);
+			break;
+		case 3:
+			WIIMOTE_ENABLE_STATE(wm, WIIMOTE_STATE_IR_SENS_LVL3);
+			break;
+		case 4:
+			WIIMOTE_ENABLE_STATE(wm, WIIMOTE_STATE_IR_SENS_LVL4);
+			break;
+		case 5:
+			WIIMOTE_ENABLE_STATE(wm, WIIMOTE_STATE_IR_SENS_LVL5);
+			break;
+		default:
+			return;
+	}
+
+	/* set the new sensitivity */
+	get_ir_sens(wm, &block1, &block2);
+
+	wiiuse_write_data(wm, WM_REG_IR_BLOCK1, (byte*)block1, 9);
+	wiiuse_write_data(wm, WM_REG_IR_BLOCK2, (byte*)block2, 2);
+
+	WIIUSE_DEBUG("Set IR sensitivity to level %i (unid %i)", level, wm->unid);
+}
+
+
+/**
+ *	@brief Calculate the data from the IR spots.  Basic IR mode.
+ *
+ *	@param wm		Pointer to a wiimote_t structure.
+ *	@param data		Data returned by the wiimote for the IR spots.
+ */
+void calculate_basic_ir(struct wiimote_t* wm, byte* data) {
+	struct ir_dot_t* dot = wm->ir.dot;
+	int i;
+
+	dot[0].rx = 1023 - (data[0] | ((data[2] & 0x30) << 4));
+	dot[0].ry = data[1] | ((data[2] & 0xC0) << 2);
+
+	dot[1].rx = 1023 - (data[3] | ((data[2] & 0x03) << 8));
+	dot[1].ry = data[4] | ((data[2] & 0x0C) << 6);
+
+	dot[2].rx = 1023 - (data[5] | ((data[7] & 0x30) << 4));
+	dot[2].ry = data[6] | ((data[7] & 0xC0) << 2);
+
+	dot[3].rx = 1023 - (data[8] | ((data[7] & 0x03) << 8));
+	dot[3].ry = data[9] | ((data[7] & 0x0C) << 6);
+
+	/* set each IR spot to visible if spot is in range */
+	for (i = 0; i < 4; ++i) {
+		if (dot[i].ry == 1023)
+			dot[i].visible = 0;
+		else {
+			dot[i].visible = 1;
+			dot[i].size = 0;		/* since we don't know the size, set it as 0 */
+		}
+	}
+
+	interpret_ir_data(wm);
+}
+
+
+/**
+ *	@brief Calculate the data from the IR spots.  Extended IR mode.
+ *
+ *	@param wm		Pointer to a wiimote_t structure.
+ *	@param data		Data returned by the wiimote for the IR spots.
+ */
+void calculate_extended_ir(struct wiimote_t* wm, byte* data) {
+	struct ir_dot_t* dot = wm->ir.dot;
+	int i;
+
+	for (i = 0; i < 4; ++i) {
+		dot[i].rx = 1023 - (data[3*i] | ((data[(3*i)+2] & 0x30) << 4));
+		dot[i].ry = data[(3*i)+1] | ((data[(3*i)+2] & 0xC0) << 2);
+
+		dot[i].size = data[(3*i)+2] & 0x0F;
+
+		/* if in range set to visible */
+		if (dot[i].ry == 1023)
+			dot[i].visible = 0;
+		else
+			dot[i].visible = 1;
+	}
+
+	interpret_ir_data(wm);
+}
+
+
+/**
+ *	@brief Interpret IR data into more user friendly variables.
+ *
+ *	@param wm		Pointer to a wiimote_t structure.
+ */
+static void interpret_ir_data(struct wiimote_t* wm) {
+	struct ir_dot_t* dot = wm->ir.dot;
+	int i;
+	float roll = 0.0f;
+	int last_num_dots = wm->ir.num_dots;
+
+	if (WIIMOTE_IS_SET(wm, WIIMOTE_STATE_ACC))
+		roll = wm->orient.roll;
+
+	/* count visible dots */
+	wm->ir.num_dots = 0;
+	for (i = 0; i < 4; ++i) {
+		if (dot[i].visible)
+			wm->ir.num_dots++;
+	}
+
+	switch (wm->ir.num_dots) {
+		case 0:
+		{
+			wm->ir.state = 0;
+
+			/* reset the dot ordering */
+			for (i = 0; i < 4; ++i)
+				dot[i].order = 0;
+
+			wm->ir.x = 0;
+			wm->ir.y = 0;
+			wm->ir.z = 0.0f;
+
+			return;
+		}
+		case 1:
+		{
+			fix_rotated_ir_dots(wm->ir.dot, roll);
+
+			if (wm->ir.state < 2) {
+				/*
+				 *	Only 1 known dot, so use just that.
+				 */
+				for (i = 0; i < 4; ++i) {
+					if (dot[i].visible) {
+						wm->ir.x = dot[i].x;
+						wm->ir.y = dot[i].y;
+
+						wm->ir.ax = wm->ir.x;
+						wm->ir.ay = wm->ir.y;
+
+						/*	can't calculate yaw because we don't have the distance */
+						//wm->orient.yaw = calc_yaw(&wm->ir);
+
+						ir_convert_to_vres(&wm->ir.x, &wm->ir.y, wm->ir.aspect, wm->ir.vres[0], wm->ir.vres[1]);
+						break;
+					}
+				}
+			} else {
+				/*
+				 *	Only see 1 dot but know theres 2.
+				 *	Try to estimate where the other one
+				 *	should be and use that.
+				 */
+				for (i = 0; i < 4; ++i) {
+					if (dot[i].visible) {
+						int ox = 0;
+						int x, y;
+
+						if (dot[i].order == 1)
+							/* visible is the left dot - estimate where the right is */
+							ox = dot[i].x + wm->ir.distance;
+						else if (dot[i].order == 2)
+							/* visible is the right dot - estimate where the left is */
+							ox = dot[i].x - wm->ir.distance;
+
+						x = ((signed int)dot[i].x + ox) / 2;
+						y = dot[i].y;
+
+						wm->ir.ax = x;
+						wm->ir.ay = y;
+						wm->orient.yaw = calc_yaw(&wm->ir);
+
+						if (ir_correct_for_bounds(&x, &y, wm->ir.aspect, wm->ir.offset[0], wm->ir.offset[1])) {
+							ir_convert_to_vres(&x, &y, wm->ir.aspect, wm->ir.vres[0], wm->ir.vres[1]);
+							wm->ir.x = x;
+							wm->ir.y = y;
+						}
+
+						break;
+					}
+				}
+			}
+
+			break;
+		}
+		case 2:
+		case 3:
+		case 4:
+		{
+			/*
+			 *	Two (or more) dots known and seen.
+			 *	Average them together to estimate the true location.
+			 */
+			int x, y;
+			wm->ir.state = 2;
+
+			fix_rotated_ir_dots(wm->ir.dot, roll);
+
+			/* if there is at least 1 new dot, reorder them all */
+			if (wm->ir.num_dots > last_num_dots) {
+				reorder_ir_dots(dot);
+				wm->ir.x = 0;
+				wm->ir.y = 0;
+			}
+
+			wm->ir.distance = ir_distance(dot);
+			wm->ir.z = 1023 - wm->ir.distance;
+
+			get_ir_dot_avg(wm->ir.dot, &x, &y);
+
+			wm->ir.ax = x;
+			wm->ir.ay = y;
+			wm->orient.yaw = calc_yaw(&wm->ir);
+
+			if (ir_correct_for_bounds(&x, &y, wm->ir.aspect, wm->ir.offset[0], wm->ir.offset[1])) {
+				ir_convert_to_vres(&x, &y, wm->ir.aspect, wm->ir.vres[0], wm->ir.vres[1]);
+				wm->ir.x = x;
+				wm->ir.y = y;
+			}
+
+			break;
+		}
+		default:
+		{
+			break;
+		}
+	}
+
+	#ifdef WITH_WIIUSE_DEBUG
+	{
+	int ir_level;
+	WIIUSE_GET_IR_SENSITIVITY(wm, &ir_level);
+	WIIUSE_DEBUG("IR sensitivity: %i", ir_level);
+	WIIUSE_DEBUG("IR visible dots: %i", wm->ir.num_dots);
+	for (i = 0; i < 4; ++i)
+		if (dot[i].visible)
+			WIIUSE_DEBUG("IR[%i][order %i] (%.3i, %.3i) -> (%.3i, %.3i)", i, dot[i].order, dot[i].rx, dot[i].ry, dot[i].x, dot[i].y);
+	WIIUSE_DEBUG("IR[absolute]: (%i, %i)", wm->ir.x, wm->ir.y);
+	}
+	#endif
+}
+
+
+
+/**
+ *	@brief Fix the rotation of the IR dots.
+ *
+ *	@param dot		An array of 4 ir_dot_t objects.
+ *	@param ang		The roll angle to correct by (-180, 180)
+ *
+ *	If there is roll then the dots are rotated
+ *	around the origin and give a false cursor
+ *	position. Correct for the roll.
+ *
+ *	If the accelerometer is off then obviously
+ *	this will not do anything and the cursor
+ *	position may be inaccurate.
+ */
+static void fix_rotated_ir_dots(struct ir_dot_t* dot, float ang) {
+	float s, c;
+	int x, y;
+	int i;
+
+	if (!ang) {
+		for (i = 0; i < 4; ++i) {
+			dot[i].x = dot[i].rx;
+			dot[i].y = dot[i].ry;
+		}
+		return;
+	}
+
+	s = sin(DEGREE_TO_RAD(ang));
+	c = cos(DEGREE_TO_RAD(ang));
+
+	/*
+	 *	[ cos(theta)  -sin(theta) ][ ir->rx ]
+	 *	[ sin(theta)  cos(theta)  ][ ir->ry ]
+	 */
+
+	for (i = 0; i < 4; ++i) {
+		if (!dot[i].visible)
+			continue;
+
+		x = dot[i].rx - (1024/2);
+		y = dot[i].ry - (768/2);
+
+		dot[i].x = (c * x) + (-s * y);
+		dot[i].y = (s * x) + (c * y);
+
+		dot[i].x += (1024/2);
+		dot[i].y += (768/2);
+	}
+}
+
+
+/**
+ *	@brief Average IR dots.
+ *
+ *	@param dot		An array of 4 ir_dot_t objects.
+ *	@param x		[out] Average X
+ *	@param y		[out] Average Y
+ */
+static void get_ir_dot_avg(struct ir_dot_t* dot, int* x, int* y) {
+	int vis = 0, i = 0;
+
+	*x = 0;
+	*y = 0;
+
+	for (; i < 4; ++i) {
+		if (dot[i].visible) {
+			*x += dot[i].x;
+			*y += dot[i].y;
+			++vis;
+		}
+	}
+
+	*x /= vis;
+	*y /= vis;
+}
+
+
+/**
+ *	@brief Reorder the IR dots.
+ *
+ *	@param dot		An array of 4 ir_dot_t objects.
+ */
+static void reorder_ir_dots(struct ir_dot_t* dot) {
+	int i, j, order;
+
+	/* reset the dot ordering */
+	for (i = 0; i < 4; ++i)
+		dot[i].order = 0;
+
+	for (order = 1; order < 5; ++order) {
+		for (i= 0; i< 4 && (!dot[i].visible || dot[i].order); ++i) {
+			if (i >= 4)     return;
+		}
+
+		for (j = 0; j < 4; ++j) {
+			if (dot[j].visible && !dot[j].order && (dot[j].x < dot[i].x))
+				i = j;
+		}
+
+		dot[i].order = order;
+	}
+}
+
+
+/**
+ *	@brief Calculate the distance between the first 2 visible IR dots.
+ *
+ *	@param dot		An array of 4 ir_dot_t objects.
+ */
+static float ir_distance(struct ir_dot_t* dot) {
+	int i1, i2;
+	int xd, yd;
+
+	for (i1 = 0; i1 < 4; ++i1)
+		if (dot[i1].visible)
+			break;
+	if (i1 == 4)
+		return 0.0f;
+
+	for (i2 = i1+1; i2 < 4; ++i2)
+		if (dot[i2].visible)
+			break;
+	if (i2 == 4)
+		return 0.0f;
+
+	xd = dot[i2].x - dot[i1].x;
+	yd = dot[i2].y - dot[i1].y;
+
+	return sqrt(xd*xd + yd*yd);
+}
+
+
+/**
+ *	@brief Correct for the IR bounding box.
+ *
+ *	@param x		[out] The current X, it will be updated if valid.
+ *	@param y		[out] The current Y, it will be updated if valid.
+ *	@param aspect	Aspect ratio of the screen.
+ *	@param offset_x	The X offset of the bounding box.
+ *	@param offset_y	The Y offset of the bounding box.
+ *
+ *	@return Returns 1 if the point is valid and was updated.
+ *
+ *	Nintendo was smart with this bit. They sacrifice a little
+ *	precision for a big increase in usability.
+ */
+static int ir_correct_for_bounds(int* x, int* y, enum aspect_t aspect, int offset_x, int offset_y) {
+	int x0, y0;
+	int xs, ys;
+
+	if (aspect == WIIUSE_ASPECT_16_9) {
+		xs = WM_ASPECT_16_9_X;
+		ys = WM_ASPECT_16_9_Y;
+	} else {
+		xs = WM_ASPECT_4_3_X;
+		ys = WM_ASPECT_4_3_Y;
+	}
+
+	x0 = ((1024 - xs) / 2) + offset_x;
+	y0 = ((768 - ys) / 2) + offset_y;
+
+	if ((*x >= x0)
+		&& (*x <= (x0 + xs))
+		&& (*y >= y0)
+		&& (*y <= (y0 + ys)))
+	{
+		*x -= offset_x;
+		*y -= offset_y;
+
+		return 1;
+	}
+
+	return 0;
+}
+
+
+/**
+ *	@brief Interpolate the point to the user defined virtual screen resolution.
+ */
+static void ir_convert_to_vres(int* x, int* y, enum aspect_t aspect, int vx, int vy) {
+	int xs, ys;
+
+	if (aspect == WIIUSE_ASPECT_16_9) {
+		xs = WM_ASPECT_16_9_X;
+		ys = WM_ASPECT_16_9_Y;
+	} else {
+		xs = WM_ASPECT_4_3_X;
+		ys = WM_ASPECT_4_3_Y;
+	}
+
+	*x -= ((1024-xs)/2);
+	*y -= ((768-ys)/2);
+
+	*x = (*x / (float)xs) * vx;
+	*y = (*y / (float)ys) * vy;
+}
+
+
+/**
+ *	@brief Calculate yaw given the IR data.
+ *
+ *	@param ir	IR data structure.
+ */
+float calc_yaw(struct ir_t* ir) {
+	float x;
+
+	x = ir->ax - 512;
+	x = x * (ir->z / 1024.0f);
+
+	return RAD_TO_DEGREE( atanf(x / ir->z) );
+}
diff --git a/3rdparty/wiiuse/src/ir.h b/3rdparty/wiiuse/src/ir.h
new file mode 100644
index 0000000..8ffae92
--- /dev/null
+++ b/3rdparty/wiiuse/src/ir.h
@@ -0,0 +1,57 @@
+/*
+ *	wiiuse
+ *
+ *	Written By:
+ *		Michael Laforest	< para >
+ *		Email: < thepara (--AT--) g m a i l [--DOT--] com >
+ *
+ *	Copyright 2006-2007
+ *
+ *	This file is part of wiiuse.
+ *
+ *	This program is free software; you can redistribute it and/or modify
+ *	it under the terms of the GNU General Public License as published by
+ *	the Free Software Foundation; either version 3 of the License, or
+ *	(at your option) any later version.
+ *
+ *	This program is distributed in the hope that it will be useful,
+ *	but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *	GNU General Public License for more details.
+ *
+ *	You should have received a copy of the GNU General Public License
+ *	along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ *	$Header$
+ *
+ */
+
+/**
+ *	@file
+ *	@brief Handles IR data.
+ */
+
+#ifndef IR_H_INCLUDED
+#define IR_H_INCLUDED
+
+#include "wiiuse_internal.h"
+
+#define WII_VRES_X		560
+#define WII_VRES_Y		340
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void calculate_basic_ir(struct wiimote_t* wm, byte* data);
+void calculate_extended_ir(struct wiimote_t* wm, byte* data);
+float calc_yaw(struct ir_t* ir);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // IR_H_INCLUDED
+
+
diff --git a/3rdparty/wiiuse/src/motion_plus.c b/3rdparty/wiiuse/src/motion_plus.c
new file mode 100644
index 0000000..e676ac3
--- /dev/null
+++ b/3rdparty/wiiuse/src/motion_plus.c
@@ -0,0 +1,250 @@
+/*
+ *	wiiuse
+ *
+ *	Written By:
+ *		Michal Wiedenbauer	< shagkur >
+ *		Dave Murphy			< WinterMute >
+ *		Hector Martin		< marcan >
+ *		Cesar Mauri
+ *
+ *	Copyright 2009 - 11
+ *
+ *	This file is part of wiiuse, fWIIne and SITPLUS.
+ *
+ *	This program is free software; you can redistribute it and/or modify
+ *	it under the terms of the GNU General Public License as published by
+ *	the Free Software Foundation; either version 3 of the License, or
+ *	(at your option) any later version.
+ *
+ *	This program is distributed in the hope that it will be useful,
+ *	but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *	GNU General Public License for more details.
+ *
+ *	You should have received a copy of the GNU General Public License
+ *	along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ *	$Header$
+ *
+ */
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <stdlib.h>
+#include <math.h>
+#include <string.h>
+
+#ifdef WIN32
+	#include <Winsock2.h>
+#endif
+
+#include "definitions.h"
+#include "wiiuse_internal.h"
+#include "dynamics.h"
+#include "events.h"
+#include "io.h"
+
+/* motion plus scaling factors for slow/normal and fast motion */
+#define SLOW_C 0.0726318359375f
+#define FAST_C 0.33014470880681818181818181818182f
+
+/* motion plus calibration */
+#define CALIBRATION_ZERO 8063				/* theorical motion plus zero */
+#define CALIBRATION_OFFSET 250				/* acceptance offset*/
+#define CALIBRATION_MAX_DEVIATION	5.0f	/* max. deviation */
+
+void wiiuse_motion_plus_check(struct wiimote_t *wm,byte *data,unsigned short len)
+{
+	int val;
+	if(data == NULL)
+	{
+	    wiiuse_read_data_cb(wm, wiiuse_motion_plus_check, wm->motion_plus_id, WM_EXP_ID, 6);
+	}
+	else
+	{
+		WIIMOTE_DISABLE_STATE(wm, WIIMOTE_STATE_EXP);
+		WIIMOTE_DISABLE_STATE(wm, WIIMOTE_STATE_EXP_FAILED);
+		WIIMOTE_DISABLE_STATE(wm, WIIMOTE_STATE_EXP_HANDSHAKE);
+		val = (data[3] << 16) | (data[2] << 24) | (data[4] << 8) | data[5];
+		if(val == EXP_ID_CODE_MOTION_PLUS)
+		{
+			/* handshake done */
+			wm->event = WIIUSE_MOTION_PLUS_ACTIVATED;
+			memset (&wm->exp.mp, 0, sizeof(struct motion_plus_t));
+			wm->exp.type = EXP_MOTION_PLUS;
+			wm->exp.mp.rx_zero= CALIBRATION_ZERO;
+			wm->exp.mp.ry_zero= CALIBRATION_ZERO;
+			wm->exp.mp.rz_zero= CALIBRATION_ZERO;
+			/* adjust counter to indicate if auto-calibration should be used */
+			if (!(wm->flags & WIIUSE_MP_AUTO_CALIBRATION)) 
+				wm->exp.mp.calib_buff_count= MOTION_PLUS_CALIB_BUFF_SIZE+1;
+			WIIUSE_DEBUG("Motion plus connected");			
+			WIIMOTE_ENABLE_STATE(wm,WIIMOTE_STATE_EXP);
+			wiiuse_set_ir_mode(wm);
+		}
+	}
+}
+
+static void wiiuse_set_motion_plus_clear2(struct wiimote_t *wm,byte *data,unsigned short len)
+{
+	WIIMOTE_DISABLE_STATE(wm, WIIMOTE_STATE_EXP);
+	WIIMOTE_DISABLE_STATE(wm, WIIMOTE_STATE_EXP_FAILED);
+	WIIMOTE_DISABLE_STATE(wm, WIIMOTE_STATE_EXP_HANDSHAKE);
+	wiiuse_set_ir_mode(wm);
+	wiiuse_status(wm);
+}
+
+static void wiiuse_set_motion_plus_clear1(struct wiimote_t *wm,byte *data,unsigned short len)
+{
+	ubyte val = 0x00;
+	wiiuse_write_data_cb(wm, WM_EXP_MEM_ENABLE1, &val, 1, wiiuse_set_motion_plus_clear2);
+}
+
+
+void wiiuse_set_motion_plus(struct wiimote_t *wm, int status)
+{
+	ubyte val;
+	
+	if(WIIMOTE_IS_SET(wm,WIIMOTE_STATE_EXP_HANDSHAKE))
+		return;
+
+	if (!status && wm->exp.type!= EXP_MOTION_PLUS) return;
+	if (status && wm->exp.type== EXP_MOTION_PLUS) return;
+
+	WIIMOTE_ENABLE_STATE(wm, WIIMOTE_STATE_EXP_HANDSHAKE);
+	if(status)
+	{
+		val = 0x04;
+		wiiuse_write_data_cb(wm, WM_EXP_MOTION_PLUS_ENABLE, &val, 1, wiiuse_motion_plus_check);
+	}
+	else
+	{
+		disable_expansion(wm);
+		val = 0x55;
+		wiiuse_write_data_cb(wm, WM_EXP_MEM_ENABLE1, &val, 1, wiiuse_set_motion_plus_clear1);
+	}
+}
+
+void motion_plus_disconnected(struct motion_plus_t* mp)
+{
+	WIIUSE_DEBUG("Motion plus disconnected");
+	memset(mp, 0, sizeof(struct motion_plus_t));
+}
+
+/* compute average of a set of values */
+static
+float average (short * values, int nvalues)
+{
+	int i;
+	int accum= 0;
+
+	for (i = 0; i< nvalues; ++i) accum+= values[i];
+
+	return (float) accum / (float) nvalues;
+}
+
+/* compute the average absolute deviation of a set of values */
+static
+float avg_abs_deviation (short * values, int nvalues, float average)
+{
+	int i;
+	float accum= 0.0f;
+
+	for (i = 0; i< nvalues; ++i) accum+= fabs(((float) values[i]) - average);		
+
+	return accum / (float) nvalues;
+}
+
+void motion_plus_event(struct motion_plus_t* mp, byte* msg)
+{
+	short rx, ry, rz;
+	unsigned char xslow, yslow, zslow;
+
+	/*
+	   Byte 7 6 5 4 3 2            1              0
+	   0    Yaw Down Speed<7:0>
+	   1    Roll Left Speed<7:0>
+	   2    Pitch Left Speed<7:0>
+	   3    Yaw Down Speed<13:8>   Yaw slow mode  Pitch slow mode
+	   4    Roll Left Speed<13:8>  Roll slow mode Extension connected
+	   5    Pitch Left Speed<13:8> 1              0
+
+	   See: http://wiibrew.org/wiki/Wiimote/Extension_Controllers
+	*/
+
+	rx = ((msg[5] & 0xFC) << 6) | msg[2]; // Pitch
+	ry = ((msg[4] & 0xFC) << 6) | msg[1]; // Roll
+	rz = ((msg[3] & 0xFC) << 6) | msg[0]; // Yaw
+
+	/* filter incorrect values */
+	if (rx == 0x3fff || ry == 0x3fff || rz == 0x3fff) return;
+
+	/* store raw values */
+	mp->rx = rx;
+	mp->ry = ry;
+	mp->rz = rz;
+
+	/* store flags */
+	mp->ext = msg[4] & 0x1;
+	mp->status = (msg[3] & 0x3) | ((msg[4] & 0x2) << 1); // roll, yaw, pitch
+
+	/* convert to deg/s */
+	xslow= msg[3] & 0x1;
+	yslow= msg[4] & 0x2;
+	zslow= msg[3] & 0x2;
+
+	mp->sx= (float) (rx - mp->rx_zero) * (xslow? SLOW_C : FAST_C);
+	mp->sy= (float) (ry - mp->ry_zero) * (yslow? SLOW_C : FAST_C);
+	mp->sz= (float) (rz - mp->rz_zero) * (zslow? -SLOW_C : -FAST_C);
+
+	/* auto-calibration */
+	if (mp->calib_buff_count<= MOTION_PLUS_CALIB_BUFF_SIZE) {		
+		/* ongoing calibration */
+
+		/* readings are within a reasonable range? */
+		if (!xslow || !yslow || !zslow ||
+			rx< (CALIBRATION_ZERO - CALIBRATION_OFFSET) || rx> (CALIBRATION_ZERO + CALIBRATION_OFFSET) ||
+			ry< (CALIBRATION_ZERO - CALIBRATION_OFFSET) || ry> (CALIBRATION_ZERO + CALIBRATION_OFFSET) ||
+			rz< (CALIBRATION_ZERO - CALIBRATION_OFFSET) || rz> (CALIBRATION_ZERO + CALIBRATION_OFFSET)) {
+			/* no, reset values */
+			mp->calib_buff_count= 0;
+			mp->calib_buff_index= 0;
+			return;
+		}
+
+		/* store values in calibration buffer */
+		mp->rx_hist[mp->calib_buff_index]= rx;
+		mp->ry_hist[mp->calib_buff_index]= ry;
+		mp->rz_hist[mp->calib_buff_index]= rz;
+		++mp->calib_buff_index;
+		if (mp->calib_buff_index== MOTION_PLUS_CALIB_BUFF_SIZE) mp->calib_buff_index= 0;
+		if (mp->calib_buff_count< MOTION_PLUS_CALIB_BUFF_SIZE) ++mp->calib_buff_count;
+
+		/* when buffer full compute averages and deviations */
+		if (mp->calib_buff_count== MOTION_PLUS_CALIB_BUFF_SIZE) {
+			float xavg, xdev, yavg, ydev, zavg, zdev;
+
+			xavg= average (mp->rx_hist, MOTION_PLUS_CALIB_BUFF_SIZE);
+			xdev= avg_abs_deviation (mp->rx_hist, MOTION_PLUS_CALIB_BUFF_SIZE, xavg);
+			if (xdev> CALIBRATION_MAX_DEVIATION) return;
+
+			yavg= average (mp->ry_hist, MOTION_PLUS_CALIB_BUFF_SIZE);
+			ydev= avg_abs_deviation (mp->ry_hist, MOTION_PLUS_CALIB_BUFF_SIZE, yavg);
+			if (ydev> CALIBRATION_MAX_DEVIATION) return;
+
+			zavg= average (mp->rz_hist, MOTION_PLUS_CALIB_BUFF_SIZE);
+			zdev= avg_abs_deviation (mp->rz_hist, MOTION_PLUS_CALIB_BUFF_SIZE, zavg);
+			if (zdev> CALIBRATION_MAX_DEVIATION) return;
+
+			/* calibration done, store values */
+			mp->rx_zero= (short) (xavg + 0.5f);
+			mp->ry_zero= (short) (yavg + 0.5f);
+			mp->rz_zero= (short) (zavg + 0.5f);
+
+			/* inc. counter to indicate finished calibration */
+			++mp->calib_buff_count;
+
+			WIIUSE_DEBUG("Motion plus auto-calibration done");
+		}
+	}		
+}
diff --git a/3rdparty/wiiuse/src/motion_plus.h b/3rdparty/wiiuse/src/motion_plus.h
new file mode 100644
index 0000000..cb2593d
--- /dev/null
+++ b/3rdparty/wiiuse/src/motion_plus.h
@@ -0,0 +1,23 @@
+/**
+ *	@file
+ *	@brief Motion plus extension
+ */
+
+#ifndef MOTION_PLUS_H_INCLUDED
+#define MOTION_PLUS_H_INCLUDED
+
+#include "wiiuse_internal.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void motion_plus_disconnected(struct motion_plus_t* mp);
+
+void motion_plus_event(struct motion_plus_t* mp, byte* msg);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/3rdparty/wiiuse/src/nunchuk.c b/3rdparty/wiiuse/src/nunchuk.c
new file mode 100644
index 0000000..a85ae50
--- /dev/null
+++ b/3rdparty/wiiuse/src/nunchuk.c
@@ -0,0 +1,235 @@
+/*
+ *	wiiuse
+ *
+ *	Written By:
+ *		Michael Laforest	< para >
+ *		Email: < thepara (--AT--) g m a i l [--DOT--] com >
+ *
+ *	Copyright 2006-2007
+ *
+ *	This file is part of wiiuse.
+ *
+ *	This program is free software; you can redistribute it and/or modify
+ *	it under the terms of the GNU General Public License as published by
+ *	the Free Software Foundation; either version 3 of the License, or
+ *	(at your option) any later version.
+ *
+ *	This program is distributed in the hope that it will be useful,
+ *	but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *	GNU General Public License for more details.
+ *
+ *	You should have received a copy of the GNU General Public License
+ *	along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ *	$Header$
+ *
+ */
+
+/**
+ *	@file
+ *	@brief Nunchuk expansion device.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <math.h>
+
+#include "definitions.h"
+#include "wiiuse_internal.h"
+#include "dynamics.h"
+#include "events.h"
+#include "nunchuk.h"
+#include "io.h"
+
+/**
+ *	@brief Find what buttons are pressed.
+ *
+ *	@param nc		Pointer to a nunchuk_t structure.
+ *	@param msg		The message byte specified in the event packet.
+ */
+static void nunchuk_pressed_buttons(struct nunchuk_t* nc, byte now) {
+	/* message is inverted (0 is active, 1 is inactive) */
+	now = ~now & NUNCHUK_BUTTON_ALL;
+
+	/* preserve old btns pressed */
+	nc->btns_last = nc->btns;
+
+	/* pressed now & were pressed, then held */
+	nc->btns_held = (now & nc->btns);
+
+	/* were pressed or were held & not pressed now, then released */
+	nc->btns_released = ((nc->btns | nc->btns_held) & ~now);
+
+	/* buttons pressed now */
+	nc->btns = now;
+}
+
+/**
+ *	@brief Handle the handshake data from the nunchuk.
+ *
+ *	@param nc		A pointer to a nunchuk_t structure.
+ *	@param data		The data read in from the device.
+ *	@param len		The length of the data block, in bytes.
+ *
+ *	@return	Returns 1 if handshake was successful, 0 if not.
+ */
+int nunchuk_handshake(struct wiimote_t* wm, struct nunchuk_t* nc, byte* data, unsigned short len) {
+	//int i;
+	int offset = 0;
+
+	nc->btns = 0;
+	nc->btns_held = 0;
+	nc->btns_released = 0;
+
+	/* set the smoothing to the same as the wiimote */
+	nc->flags = &wm->flags;
+	//nc->accel_calib.st_alpha = wm->accel_calib.st_alpha;
+	nc->accel_calib= wm->accel_calib;
+
+	/* decrypt data */
+	/* for (i = 0; i < len; ++i) data[i] = (data[i] ^ 0x17) + 0x17; */
+
+	if (data[offset] == 0xFF) {
+		/*
+		 *	Sometimes the data returned here is not correct.
+		 *	This might happen because the wiimote is lagging
+		 *	behind our initialization sequence.
+		 *	To fix this just request the handshake again.
+		 *
+		 *	Other times it's just the first 16 bytes are 0xFF,
+		 *	but since the next 16 bytes are the same, just use
+		 *	those.
+		 */
+		if (data[offset + 16] == 0xFF) {
+			/* get the calibration data */
+			byte* handshake_buf = malloc(EXP_HANDSHAKE_LEN * sizeof(byte));
+
+			WIIUSE_DEBUG("Nunchuk handshake appears invalid, trying again.");
+			wiiuse_read_data_cb(wm, handshake_expansion, handshake_buf, WM_EXP_MEM_CALIBR, EXP_HANDSHAKE_LEN);
+
+			return 0;
+		} else
+			offset += 16;
+	}
+
+	nc->accel_calib.cal_zero.x = (data[offset + 0]<<2)|((data[offset + 3]>>4)&3);
+	nc->accel_calib.cal_zero.y = (data[offset + 1]<<2)|((data[offset + 3]>>2)&3);
+	nc->accel_calib.cal_zero.z = (data[offset + 2]<<2)|(data[offset + 3]&3);
+	nc->accel_calib.cal_g.x = ((unsigned short) (data[offset + 4]<<2)|((data[offset + 7]>>4)&3)) - nc->accel_calib.cal_zero.x;
+	nc->accel_calib.cal_g.y = ((unsigned short) (data[offset + 5]<<2)|((data[offset + 7]>>2)&3)) - nc->accel_calib.cal_zero.y;
+	nc->accel_calib.cal_g.z = ((unsigned short) (data[offset + 6]<<2)|(data[offset + 7]&3)) - nc->accel_calib.cal_zero.z;
+	nc->js.max.x = data[offset + 8];
+	nc->js.min.x = data[offset + 9];
+	nc->js.center.x = data[offset + 10];
+	nc->js.max.y = data[offset + 11];
+	nc->js.min.y = data[offset + 12];
+	nc->js.center.y = data[offset + 13];
+
+	/* default the thresholds to the same as the wiimote */
+	nc->orient_threshold = wm->orient_threshold;
+	nc->accel_threshold = wm->accel_threshold;
+
+	/* handshake done */
+	wm->exp.type = EXP_NUNCHUK;
+
+	#ifdef WIN32
+	wm->timeout = WIIMOTE_DEFAULT_TIMEOUT;
+	#endif
+	/* if min and max are reported as 0, initialize them to usable values based on center, and fine tune in nunchuck_event() */
+	if (nc->js.center.x) {
+		if (nc->js.min.x == 0) nc->js.min.x = nc->js.center.x - 80;
+		if (nc->js.max.x == 0) nc->js.max.x = nc->js.center.x + 80;
+	}
+	if (nc->js.center.y) {
+		if (nc->js.min.y == 0) nc->js.min.y = nc->js.center.y - 80;
+		if (nc->js.max.y == 0) nc->js.max.y = nc->js.center.y + 80;
+	}
+
+	return 1;
+}
+
+
+/**
+ *	@brief The nunchuk disconnected.
+ *
+ *	@param nc		A pointer to a nunchuk_t structure.
+ */
+void nunchuk_disconnected(struct nunchuk_t* nc) {
+	//printf("nunchuk_disconnected()\n");
+	memset(nc, 0, sizeof(struct nunchuk_t));
+}
+
+
+
+/**
+ *	@brief Handle nunchuk event.
+ *
+ *	@param nc		A pointer to a nunchuk_t structure.
+ *	@param msg		The message specified in the event packet.
+ */
+void nunchuk_event(struct nunchuk_t* nc, byte* msg) {
+	//int i;
+
+	/* decrypt data */
+	/*
+	for (i = 0; i < 6; ++i)
+		msg[i] = (msg[i] ^ 0x17) + 0x17;
+	*/
+	/* get button states */
+	nunchuk_pressed_buttons(nc, msg[5]);
+
+
+	/* extend min and max values to physical range of motion */
+	if (nc->js.center.x) {
+		if (nc->js.min.x > msg[0]) nc->js.min.x = msg[0];
+		if (nc->js.max.x < msg[0]) nc->js.max.x = msg[0];
+	}
+	if (nc->js.center.y) {
+		if (nc->js.min.y > msg[1]) nc->js.min.y = msg[1];
+		if (nc->js.max.y < msg[1]) nc->js.max.y = msg[1];
+	}
+	/* calculate joystick state */
+	calc_joystick_state(&nc->js, msg[0], msg[1]);
+
+	/* calculate orientation */
+	nc->accel.x =  (msg[2]<<2) + ((msg[5]>>2)&3);
+	nc->accel.y =  (msg[3]<<2) + ((msg[5]>>4)&3);
+	nc->accel.z =  (msg[4]<<2) + ((msg[5]>>6)&3);
+
+	calculate_orientation(&nc->accel_calib, &nc->accel, &nc->orient, NUNCHUK_IS_FLAG_SET(nc, WIIUSE_SMOOTHING));
+	calculate_gforce(&nc->accel_calib, &nc->accel, &nc->gforce);
+}
+
+
+
+
+
+/**
+ *	@brief	Set the orientation event threshold for the nunchuk.
+ *
+ *	@param wm			Pointer to a wiimote_t structure with a nunchuk attached.
+ *	@param threshold	The decimal place that should be considered a significant change.
+ *
+ *	See wiiuse_set_orient_threshold() for details.
+ */
+void wiiuse_set_nunchuk_orient_threshold(struct wiimote_t* wm, float threshold) {
+	if (!wm)	return;
+
+	wm->exp.nunchuk.orient_threshold = threshold;
+}
+
+
+/**
+ *	@brief	Set the accelerometer event threshold for the nunchuk.
+ *
+ *	@param wm			Pointer to a wiimote_t structure with a nunchuk attached.
+ *	@param threshold	The decimal place that should be considered a significant change.
+ *
+ *	See wiiuse_set_orient_threshold() for details.
+ */
+void wiiuse_set_nunchuk_accel_threshold(struct wiimote_t* wm, int threshold) {
+	if (!wm)	return;
+
+	wm->exp.nunchuk.accel_threshold = threshold;
+}
diff --git a/3rdparty/wiiuse/src/nunchuk.h b/3rdparty/wiiuse/src/nunchuk.h
new file mode 100644
index 0000000..fccfc3c
--- /dev/null
+++ b/3rdparty/wiiuse/src/nunchuk.h
@@ -0,0 +1,53 @@
+/*
+ *	wiiuse
+ *
+ *	Written By:
+ *		Michael Laforest	< para >
+ *		Email: < thepara (--AT--) g m a i l [--DOT--] com >
+ *
+ *	Copyright 2006-2007
+ *
+ *	This file is part of wiiuse.
+ *
+ *	This program is free software; you can redistribute it and/or modify
+ *	it under the terms of the GNU General Public License as published by
+ *	the Free Software Foundation; either version 3 of the License, or
+ *	(at your option) any later version.
+ *
+ *	This program is distributed in the hope that it will be useful,
+ *	but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *	GNU General Public License for more details.
+ *
+ *	You should have received a copy of the GNU General Public License
+ *	along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ *	$Header$
+ *
+ */
+
+/**
+ *	@file
+ *	@brief Nunchuk expansion device.
+ */
+
+#ifndef NUNCHUK_H_INCLUDED
+#define NUNCHUK_H_INCLUDED
+
+#include "wiiuse_internal.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+int nunchuk_handshake(struct wiimote_t* wm, struct nunchuk_t* nc, byte* data, unsigned short len);
+
+void nunchuk_disconnected(struct nunchuk_t* nc);
+
+void nunchuk_event(struct nunchuk_t* nc, byte* msg);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // NUNCHUK_H_INCLUDED
diff --git a/3rdparty/wiiuse/src/os.h b/3rdparty/wiiuse/src/os.h
new file mode 100644
index 0000000..d23e17c
--- /dev/null
+++ b/3rdparty/wiiuse/src/os.h
@@ -0,0 +1,56 @@
+/*
+ *	wiiuse
+ *
+ *	Written By:
+ *		Michael Laforest	< para >
+ *		Email: < thepara (--AT--) g m a i l [--DOT--] com >
+ *
+ *	Copyright 2006-2007
+ *
+ *	This file is part of wiiuse.
+ *
+ *	This program is free software; you can redistribute it and/or modify
+ *	it under the terms of the GNU General Public License as published by
+ *	the Free Software Foundation; either version 3 of the License, or
+ *	(at your option) any later version.
+ *
+ *	This program is distributed in the hope that it will be useful,
+ *	but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *	GNU General Public License for more details.
+ *
+ *	You should have received a copy of the GNU General Public License
+ *	along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ *	$Header$
+ *
+ */
+
+
+/**
+ *	@file
+ *	@brief Operating system related definitions.
+ *
+ *	This file is an attempt to separate operating system
+ *	dependent functions and choose what should be used
+ *	at compile time.
+ */
+
+#ifndef OS_H_INCLUDED
+#define OS_H_INCLUDED
+
+#ifdef WIN32
+	/* windows */
+	#define isnan(x)		_isnan(x)
+	#define isinf(x)		!_finite(x)
+
+	/* disable warnings I don't care about */
+	#pragma warning(disable:4244)		/* possible loss of data conversion	*/
+	#pragma warning(disable:4273)		/* inconsistent dll linkage			*/
+	#pragma warning(disable:4217)
+#else
+	/* nix */
+#endif
+
+
+#endif // OS_H_INCLUDED
diff --git a/3rdparty/wiiuse/src/wiiuse.c b/3rdparty/wiiuse/src/wiiuse.c
new file mode 100644
index 0000000..1f4cc56
--- /dev/null
+++ b/3rdparty/wiiuse/src/wiiuse.c
@@ -0,0 +1,886 @@
+/*
+ *	wiiuse
+ *
+ *	Written By:
+ *		Michael Laforest	< para >
+ *		Michal Wiedenbauer	< shagkur >
+ *		Dave Murphy			< WinterMute >
+ *		Hector Martin		< marcan >
+ *		William Alozy		< wiill >
+ *
+ *	Copyright 2009
+ *
+ *
+ *	This file is part of wiiuse and fWIIne.
+ *
+ *	This program is free software; you can redistribute it and/or modify
+ *	it under the terms of the GNU General Public License as published by
+ *	the Free Software Foundation; either version 3 of the License, or
+ *	(at your option) any later version.
+ *
+ *	This program is distributed in the hope that it will be useful,
+ *	but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *	GNU General Public License for more details.
+ *
+ *	You should have received a copy of the GNU General Public License
+ *	along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ *	$Header$
+ *
+ */
+
+/**
+ *	@file
+ *	@brief General wiimote operations.
+ *
+ *	The file includes functions that handle general
+ *	tasks.  Most of these are functions that are part
+ *	of the API.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+
+#ifndef WIN32
+	#include <unistd.h>
+#else
+	#include <Winsock2.h>
+#endif
+
+#include "definitions.h"
+#include "wiiuse_internal.h"
+#include "events.h"
+#include "io.h"
+
+static int g_banner = 0;
+
+/**
+ *	@breif Returns the version of the library.
+ */
+const char* wiiuse_version() {
+	return WIIUSE_VERSION;
+}
+
+
+/**
+ *	@brief Clean up wiimote_t array created by wiiuse_init()
+ */
+void wiiuse_cleanup(struct wiimote_t** wm, int wiimotes) {
+	int i = 0;
+
+	if (!wm)
+		return;
+
+	WIIUSE_INFO("wiiuse clean up...");
+
+	for (; i < wiimotes; ++i) {
+		/* disable event reporting that could waste battery */
+		wiiuse_set_flags(wm[i], 0, WIIUSE_CONTINUOUS);
+		wiiuse_motion_sensing(wm[i], 0);
+		wiiuse_set_motion_plus(wm[i], 0);
+		wiiuse_disconnect(wm[i]);
+		free(wm[i]);
+	}
+
+	free(wm);
+
+	return;
+}
+
+
+/**
+ *	@brief Initialize an array of wiimote structures.
+ *
+ *	@param wiimotes		Number of wiimote_t structures to create.
+ *
+ *	@return An array of initialized wiimote_t structures.
+ *
+ *	@see wiiuse_connect()
+ *
+ *	The array returned by this function can be passed to various
+ *	functions, including wiiuse_connect().
+ */
+struct wiimote_t** wiiuse_init(int wiimotes) {
+	int i = 0;
+	struct wiimote_t** wm = NULL;
+
+	/*
+	 *	Please do not remove this banner.
+	 *	GPL asks that you please leave output credits intact.
+	 *	Thank you.
+	 *
+	 *	This banner is only displayed once so that if you need
+	 *	to call this function again it won't be intrusive.
+	 */
+	if (!g_banner) {
+		printf(	"wiiuse v" WIIUSE_VERSION " loaded.\n"
+				"  By: Michael Laforest <thepara[at]gmail{dot}com>\n"
+				"  http://wiiuse.net  http://fwiineur.blogspot.com\n");
+		g_banner = 1;
+	}
+
+	if (!wiimotes)
+		return NULL;
+
+	wm = malloc(sizeof(struct wiimote_t*) * wiimotes);
+
+	for (i = 0; i < wiimotes; ++i) {
+		wm[i] = malloc(sizeof(struct wiimote_t));
+		memset(wm[i], 0, sizeof(struct wiimote_t));
+
+		wm[i]->unid = i+1;
+
+		#ifndef WIN32
+			wm[i]->bdaddr = *BDADDR_ANY;
+			wm[i]->out_sock = -1;
+			wm[i]->in_sock = -1;
+		#else
+			wm[i]->dev_handle = 0;
+			wm[i]->stack = WIIUSE_STACK_UNKNOWN;
+			wm[i]->normal_timeout = WIIMOTE_DEFAULT_TIMEOUT;
+			wm[i]->exp_timeout = WIIMOTE_EXP_TIMEOUT;
+			wm[i]->timeout = wm[i]->normal_timeout;
+		#endif
+
+		wm[i]->state = WIIMOTE_INIT_STATES;
+		wm[i]->flags = WIIUSE_INIT_FLAGS;
+
+		wm[i]->event = WIIUSE_NONE;
+
+		wm[i]->exp.type = EXP_NONE;
+
+		wiiuse_set_aspect_ratio(wm[i], WIIUSE_ASPECT_4_3);
+		wiiuse_set_ir_position(wm[i], WIIUSE_IR_ABOVE);
+
+		wm[i]->orient_threshold = 0.5f;
+		wm[i]->accel_threshold = 5;
+
+		wm[i]->accel_calib.st_alpha = WIIUSE_DEFAULT_SMOOTH_ALPHA;
+	}
+
+	return wm;
+}
+
+
+/**
+ *	@brief	The wiimote disconnected.
+ *
+ *	@param wm	Pointer to a wiimote_t structure.
+ */
+void wiiuse_disconnected(struct wiimote_t* wm) {
+	if (!wm)	return;
+
+	WIIUSE_INFO("Wiimote disconnected [id %i].", wm->unid);
+	
+	wiiuse_disconnect(wm);
+
+	/* disable the connected flag */
+	WIIMOTE_DISABLE_STATE(wm, WIIMOTE_STATE_CONNECTED);
+
+	/* reset a bunch of stuff */
+	#ifndef WIN32
+		wm->out_sock = -1;
+		wm->in_sock = -1;
+	#else
+		wm->dev_handle = 0;
+	#endif
+
+	wm->leds = 0;
+	wm->state = WIIMOTE_INIT_STATES;
+	wm->read_req = NULL;
+	wm->data_req = NULL;
+	wm->handshake_state = 0;
+	wm->btns = 0;
+	wm->btns_held = 0;
+	wm->btns_released = 0;
+	memset(wm->event_buf, 0, sizeof(wm->event_buf));
+
+	wm->event = WIIUSE_DISCONNECT;
+}
+
+
+
+
+
+/**
+ *	@brief	Set if the wiimote should report motion sensing.
+ *
+ *	@param wm		Pointer to a wiimote_t structure.
+ *	@param status	1 to enable, 0 to disable.
+ *
+ *	Since reporting motion sensing sends a lot of data,
+ *	the wiimote saves power by not transmitting it
+ *	by default.
+ */
+void wiiuse_motion_sensing(struct wiimote_t* wm, int status) {
+	if (status)
+		WIIMOTE_ENABLE_STATE(wm, WIIMOTE_STATE_ACC);
+	else
+		WIIMOTE_DISABLE_STATE(wm, WIIMOTE_STATE_ACC);
+
+	wiiuse_set_report_type(wm);
+		if(!WIIMOTE_IS_SET(wm,WIIMOTE_STATE_HANDSHAKE_COMPLETE)) return;
+	wiiuse_status(wm);
+}
+
+
+/**
+ *	@brief	Toggle the state of the rumble.
+ *
+ *	@param wm		Pointer to a wiimote_t structure.
+ */
+void wiiuse_toggle_rumble(struct wiimote_t* wm) {
+	if (!wm)	return;
+
+	wiiuse_rumble(wm, !WIIMOTE_IS_SET(wm, WIIMOTE_STATE_RUMBLE));
+}
+
+/**
+ *	@brief	Enable or disable the rumble.
+ *
+ *	@param wm		Pointer to a wiimote_t structure.
+ *	@param status	1 to enable, 0 to disable.
+ */
+void wiiuse_rumble(struct wiimote_t* wm, int status) {
+	byte buf;
+
+	if (!wm || !WIIMOTE_IS_CONNECTED(wm))
+		return;
+
+	/* make sure to keep the current lit leds */
+	buf = wm->leds;
+
+	if (status) {
+		WIIUSE_DEBUG("Starting rumble...");
+		WIIMOTE_ENABLE_STATE(wm, WIIMOTE_STATE_RUMBLE);
+		buf |= 0x01;
+	} else {
+		WIIUSE_DEBUG("Stopping rumble...");
+		WIIMOTE_DISABLE_STATE(wm, WIIMOTE_STATE_RUMBLE);
+	}
+
+	/* preserve IR state */
+	if (WIIMOTE_IS_SET(wm, WIIMOTE_STATE_IR))
+		buf |= 0x04;
+
+	wiiuse_send(wm, WM_CMD_RUMBLE, &buf, 1);
+}
+
+/**
+ *	@brief	Set the enabled LEDs.
+ *
+ *	@param wm		Pointer to a wiimote_t structure.
+ *	@param leds		What LEDs to enable.
+ *
+ *	\a leds is a bitwise or of WIIMOTE_LED_1, WIIMOTE_LED_2, WIIMOTE_LED_3, or WIIMOTE_LED_4.
+ */
+void wiiuse_set_leds(struct wiimote_t* wm, int leds) {
+	byte buf;
+
+	if (!wm || !WIIMOTE_IS_CONNECTED(wm))
+		return;
+
+	/* remove the lower 4 bits because they control rumble */
+	wm->leds = (leds & 0xF0);
+
+	/* make sure if the rumble is on that we keep it on */
+	if (WIIMOTE_IS_SET(wm, WIIMOTE_STATE_RUMBLE))
+		wm->leds |= 0x01;
+
+	buf = wm->leds;
+
+	wiiuse_send(wm, WM_CMD_LED, &buf, 1);
+}
+
+/**
+ *	@brief	Set the report type based on the current wiimote state.
+ *
+ *	@param wm		Pointer to a wiimote_t structure.
+ *
+ *	@return The report type sent.
+ *
+ *	The wiimote reports formatted packets depending on the
+ *	report type that was last requested.  This function will
+ *	update the type of report that should be sent based on
+ *	the current state of the device.
+ */
+int wiiuse_set_report_type(struct wiimote_t* wm) {
+	byte buf[2];
+	int motion, exp, ir;
+
+	if (!wm || !WIIMOTE_IS_CONNECTED(wm))
+		return 0;
+
+	buf[0] = (WIIMOTE_IS_FLAG_SET(wm, WIIUSE_CONTINUOUS) ? 0x04 : 0x00);	/* set to 0x04 for continuous reporting */
+	buf[1] = 0x00;
+
+	/* if rumble is enabled, make sure we keep it */
+	if (WIIMOTE_IS_SET(wm, WIIMOTE_STATE_RUMBLE))
+		buf[0] |= 0x01;
+
+	motion = WIIMOTE_IS_SET(wm, WIIMOTE_STATE_ACC);
+	exp = WIIMOTE_IS_SET(wm, WIIMOTE_STATE_EXP);
+	ir = WIIMOTE_IS_SET(wm, WIIMOTE_STATE_IR);
+
+	if (motion && ir && exp)	buf[1] = WM_RPT_BTN_ACC_IR_EXP;
+	else if (motion && exp)		buf[1] = WM_RPT_BTN_ACC_EXP;
+	else if (motion && ir)		buf[1] = WM_RPT_BTN_ACC_IR;
+	else if (ir && exp)			buf[1] = WM_RPT_BTN_IR_EXP;
+	else if (ir)				buf[1] = WM_RPT_BTN_ACC_IR;
+	else if (exp)				buf[1] = WM_RPT_BTN_EXP;
+	else if (motion)			buf[1] = WM_RPT_BTN_ACC;
+	else						buf[1] = WM_RPT_BTN;
+
+	WIIUSE_DEBUG("Setting report type: 0x%x", buf[1]);
+
+	exp = wiiuse_send(wm, WM_CMD_REPORT_TYPE, buf, 2);
+	if (exp <= 0)
+		return exp;
+
+	return buf[1];
+}
+
+/**
+ *	@brief Request the wiimote controller status.
+ *
+ *	@param wm		Pointer to a wiimote_t structure.
+ *
+ *	Controller status includes: battery level, LED status, expansions
+ */
+void wiiuse_status(struct wiimote_t* wm) {
+	ubyte buf;
+
+	if(!wm || !WIIMOTE_IS_CONNECTED(wm)) return;
+	
+	buf = 0x00;
+	wiiuse_send(wm, WM_CMD_CTRL_STATUS, &buf, 1);
+	WIIUSE_DEBUG("Requested wiimote status.");
+}
+
+
+/**
+ *	@brief	Read data from the wiimote (callback version).
+ *
+ *	@param wm		Pointer to a wiimote_t structure.
+ *	@param read_cb	Function pointer to call when the data arrives from the wiimote.
+ *	@param buffer	An allocated buffer to store the data as it arrives from the wiimote.
+ *					Must be persistent in memory and large enough to hold the data.
+ *	@param addr		The address of wiimote memory to read from.
+ *	@param len		The length of the block to be read.
+ *
+ *	The library can only handle one data read request at a time
+ *	because it must keep track of the buffer and other
+ *	events that are specific to that request.  So if a request
+ *	has already been made, subsequent requests will be added
+ *	to a pending list and be sent out when the previous
+ *	finishes.
+ */
+int wiiuse_read_data_cb(struct wiimote_t* wm, wiiuse_read_cb read_cb, byte* buffer, unsigned int addr, unsigned short len) {
+	struct read_req_t* req;
+
+	if (!wm || !WIIMOTE_IS_CONNECTED(wm))
+		return 0;
+	if (!buffer || !len || !read_cb)
+		return 0;
+
+	/* make this request structure */
+	req = (struct read_req_t*)malloc(sizeof(struct read_req_t));
+	req->cb = read_cb;
+	req->buf = buffer;
+	req->addr = addr;
+	req->size = len;
+	req->wait = len;
+	req->dirty = 0;
+	req->next = NULL;
+
+	/* add this to the request list */
+	if (!wm->read_req) {
+		/* root node */
+		wm->read_req = req;
+
+		WIIUSE_DEBUG("Data read request can be sent out immediately.");
+
+		/* send the request out immediately */
+		wiiuse_send_next_pending_read_request(wm);
+	} else {
+		struct read_req_t* nptr = wm->read_req;
+		for (; nptr->next; nptr = nptr->next);
+		nptr->next = req;
+
+		WIIUSE_DEBUG("Added pending data read request.");
+	}
+
+	return 1;
+}
+
+
+/**
+ *	@brief	Read data from the wiimote (event version).
+ *
+ *	@param wm		Pointer to a wiimote_t structure.
+ *	@param buffer	An allocated buffer to store the data as it arrives from the wiimote.
+ *					Must be persistent in memory and large enough to hold the data.
+ *	@param addr		The address of wiimote memory to read from.
+ *	@param len		The length of the block to be read.
+ *
+ *	The library can only handle one data read request at a time
+ *	because it must keep track of the buffer and other
+ *	events that are specific to that request.  So if a request
+ *	has already been made, subsequent requests will be added
+ *	to a pending list and be sent out when the previous
+ *	finishes.
+ */
+int wiiuse_read_data(struct wiimote_t* wm, byte* buffer, unsigned int addr, unsigned short len) {
+	struct read_req_t* req;
+
+	if (!wm || !WIIMOTE_IS_CONNECTED(wm))
+		return 0;
+	if (!buffer || !len)
+		return 0;
+
+	/* make this request structure */
+	req = (struct read_req_t*)malloc(sizeof(struct read_req_t));
+	req->cb = NULL;
+	req->buf = buffer;
+	req->addr = addr;
+	req->size = len;
+	req->wait = len;
+	req->dirty = 0;
+	req->next = NULL;
+
+	/* add this to the request list */
+	if (!wm->read_req) {
+		/* root node */
+		wm->read_req = req;
+
+		WIIUSE_DEBUG("Data read request can be sent out immediately.");
+
+		/* send the request out immediately */
+		wiiuse_send_next_pending_read_request(wm);
+	} else {
+		struct read_req_t* nptr = wm->read_req;
+		for (; nptr->next; nptr = nptr->next);
+		nptr->next = req;
+
+		WIIUSE_DEBUG("Added pending data read request.");
+	}
+
+	return 1;
+}
+
+
+/**
+ *	@brief Send the next pending data read request to the wiimote.
+ *
+ *	@param wm		Pointer to a wiimote_t structure.
+ *
+ *	@see wiiuse_read_data()
+ *
+ *	This function is not part of the wiiuse API.
+ */
+void wiiuse_send_next_pending_read_request(struct wiimote_t* wm) {
+	byte buf[6];
+	int* p_addr = (int*) buf;
+	struct read_req_t* req;
+
+
+	if (!wm || !WIIMOTE_IS_CONNECTED(wm))
+		return;
+	if (!wm->read_req)	return;
+
+	/* skip over dirty ones since they have already been read */
+	req = wm->read_req;
+	while (req && req->dirty)
+		req = req->next;
+	if (!req)
+		return;
+
+	/* the offset is in big endian */
+	assert ( sizeof(int) == 4 );
+	*p_addr= BIG_ENDIAN_LONG(req->addr);
+	/* *(int*)(buf) = BIG_ENDIAN_LONG(req->addr); */
+
+	/* the length is in big endian */
+	assert (sizeof(short)== 2);
+	*(short*)(buf + 4) = BIG_ENDIAN_SHORT(req->size);
+
+	WIIUSE_DEBUG("Request read at address: 0x%x  length: %i", req->addr, req->size);
+	wiiuse_send(wm, WM_CMD_READ_DATA, buf, 6);
+}
+
+
+
+/**
+ *	@brief Find a wiimote_t structure by its unique identifier.
+ *
+ *	@param wm		Pointer to a wiimote_t structure.
+ *	@param wiimotes	The number of wiimote_t structures in \a wm.
+ *	@param unid		The unique identifier to search for.
+ *
+ *	@return Pointer to a wiimote_t structure, or NULL if not found.
+ */
+struct wiimote_t* wiiuse_get_by_id(struct wiimote_t** wm, int wiimotes, int unid) {
+	int i = 0;
+
+	for (; i < wiimotes; ++i) {
+		if (wm[i]->unid == unid)
+			return wm[i];
+	}
+
+	return NULL;
+}
+/**
+ *	@brief	Write data to the wiimote (callback version).
+ *
+ *	@param wm			Pointer to a wiimote_t structure.
+ *	@param addr			The address to write to.
+ *	@param data			The data to be written to the memory location.
+ *	@param len			The length of the block to be written.
+ *	@param cb			Function pointer to call when the data arrives from the wiimote.
+ *
+ *	The library can only handle one data read request at a time
+ *	because it must keep track of the buffer and other
+ *	events that are specific to that request.  So if a request
+ *	has already been made, subsequent requests will be added
+ *	to a pending list and be sent out when the previous
+ *	finishes.
+ */
+int wiiuse_write_data_cb(struct wiimote_t *wm,uint addr,ubyte *data,ubyte len,wiiuse_write_cb write_cb)
+{
+	struct data_req_t* req;
+
+	if(!wm || !WIIMOTE_IS_CONNECTED(wm)) return 0;
+	if( !data || !len ) return 0;
+
+	req = (struct data_req_t*)malloc(sizeof(struct data_req_t));
+	req->cb = write_cb;
+	req->len = len;
+	memcpy(req->data,data,req->len);
+	req->state = REQ_READY;
+	req->addr = addr;//BIG_ENDIAN_LONG(addr);
+	req->next = NULL;
+	/* add this to the request list */
+	if (!wm->data_req) {
+		/* root node */
+		wm->data_req = req;
+
+		WIIUSE_DEBUG("Data write request can be sent out immediately.");
+
+		/* send the request out immediately */
+		wiiuse_send_next_pending_write_request(wm);
+	} else {
+		struct data_req_t* nptr = wm->data_req;
+WIIUSE_DEBUG("chaud2fois");
+		for (; nptr->next; nptr = nptr->next);
+		nptr->next = req;
+
+		WIIUSE_DEBUG("Added pending data write request.");
+	}
+
+	return 1;
+}
+
+/**
+ *	@brief	Write data to the wiimote (event version).
+ *
+ *	@param wm			Pointer to a wiimote_t structure.
+ *	@param addr			The address to write to.
+ *	@param data			The data to be written to the memory location.
+ *	@param len			The length of the block to be written.
+ */
+int wiiuse_write_data(struct wiimote_t* wm, unsigned int addr, byte* data, byte len) {
+	byte buf[21] = {0};		/* the payload is always 23 */
+	int* p_addr= (int*) buf;
+
+	if (!wm || !WIIMOTE_IS_CONNECTED(wm))
+		return 0;
+	if (!data || !len)
+		return 0;
+
+	WIIUSE_DEBUG("Writing %i bytes to memory location 0x%x...", len, addr);
+
+	#ifdef WITH_WIIUSE_DEBUG
+	{
+		int i = 0;
+		printf("Write data is: ");
+		for (; i < len; ++i)
+			printf("%x ", data[i]);
+		printf("\n");
+	}
+	#endif
+
+	/* the offset is in big endian */
+	assert (sizeof(int) == 4);	
+	*p_addr = BIG_ENDIAN_LONG(addr);
+	//*(int*)(buf) = BIG_ENDIAN_LONG(addr);
+
+	/* length */
+	*(byte*)(buf + 4) = len;
+
+	/* data */
+	memcpy(buf + 5, data, len);
+
+	wiiuse_send(wm, WM_CMD_WRITE_DATA, buf, 21);
+	return 1;
+}
+
+
+/**
+ *	@brief Send the next pending data write request to the wiimote.
+ *
+ *	@param wm		Pointer to a wiimote_t structure.
+ *
+ *	@see wiiuse_write_data()
+ *
+ *	This function is not part of the wiiuse API.
+ */
+void wiiuse_send_next_pending_write_request(struct wiimote_t* wm) {
+	byte buf[21] = {0};		/* the payload is always 23 */
+	int* p_addr= (int*) buf;
+	struct data_req_t* req = wm->data_req;
+	assert (sizeof(int)== 4);
+
+	if (!wm || !WIIMOTE_IS_CONNECTED(wm))
+		return;
+	if (!req->data || !req->len)
+		return;
+	if(req->state!=REQ_READY) return;
+	req = wm->data_req;
+	if (!req)
+		return;
+
+	WIIUSE_DEBUG("Writing %i bytes to memory location 0x%x...", req->len, req->addr);
+
+	#ifdef WITH_WIIUSE_DEBUG
+	{
+		unsigned int i = 0;
+		printf("Write data is: ");
+		for (; i < req->len; ++i)
+			printf("%x ", req->data[i]);
+		printf("\n");
+	}
+	#endif
+
+	/* the offset is in big endian */
+	*p_addr= BIG_ENDIAN_LONG(req->addr);
+	/* *(int*)(buf) = BIG_ENDIAN_LONG(req->addr); */
+
+	/* length */
+	*(byte*)(buf + 4) = req->len;//BIG_ENDIAN_SHORT(req->len);
+
+	/* data */
+	memcpy(buf + 5, req->data, req->len);
+
+	wiiuse_send(wm, WM_CMD_WRITE_DATA, buf, 21);
+	req->state = REQ_SENT;
+	return;
+}
+
+
+/**
+ *	@brief	Send a packet to the wiimote.
+ *
+ *	@param wm			Pointer to a wiimote_t structure.
+ *	@param report_type	The report type to send (WIIMOTE_CMD_LED, WIIMOTE_CMD_RUMBLE, etc). Found in wiiuse.h
+ *	@param msg			The payload.
+ *	@param len			Length of the payload in bytes.
+ *
+ *	This function should replace any write()s directly to the wiimote device.
+ */
+int wiiuse_send(struct wiimote_t* wm, byte report_type, byte* msg, int len) {
+	byte buf[32];		/* no payload is better than this */
+	int rumble = 0;
+
+	#ifndef WIN32
+		buf[0] = WM_SET_REPORT | WM_BT_OUTPUT;
+		buf[1] = report_type;
+	#else
+		buf[0] = report_type;
+	#endif
+
+	switch (report_type) {
+		case WM_CMD_LED:
+		case WM_CMD_RUMBLE:
+		case WM_CMD_CTRL_STATUS:
+		{
+			/* Rumble flag for: 0x11, 0x13, 0x14, 0x15, 0x19 or 0x1a */
+			if (WIIMOTE_IS_SET(wm, WIIMOTE_STATE_RUMBLE))
+				rumble = 1;
+			break;
+		}
+		default:
+			break;
+	}
+
+	#ifndef WIN32
+		memcpy(buf+2, msg, len);
+		if (rumble)
+			buf[2] |= 0x01;
+	#else
+		memcpy(buf+1, msg, len);
+		if (rumble)
+			buf[1] |= 0x01;
+	#endif
+
+	#ifdef WITH_WIIUSE_DEBUG
+	{
+		int x = 2;
+		printf("[DEBUG] (id %i) SEND: (%x) %.2x ", wm->unid, buf[0], buf[1]);
+		#ifndef WIN32
+		for (; x < len+2; ++x)
+		#else
+		for (; x < len+1; ++x)
+		#endif
+			printf("%.2x ", buf[x]);
+		printf("\n");
+	}
+	#endif
+
+	#ifndef WIN32
+		return wiiuse_io_write(wm, buf, len+2);
+	#else
+		return wiiuse_io_write(wm, buf, len+1);
+	#endif
+}
+
+
+/**
+ *	@brief Set flags for the specified wiimote.
+ *
+ *	@param wm			Pointer to a wiimote_t structure.
+ *	@param enable		Flags to enable.
+ *	@param disable		Flags to disable.
+ *
+ *	@return The flags set after 'enable' and 'disable' have been applied.
+ *
+ *	The values 'enable' and 'disable' may be any flags OR'ed together.
+ *	Flags are defined in wiiuse.h.
+ */
+int wiiuse_set_flags(struct wiimote_t* wm, int enable, int disable) {
+	if (!wm)	return 0;
+
+	/* remove mutually exclusive flags */
+	enable &= ~disable;
+	disable &= ~enable;
+
+	wm->flags |= enable;
+	wm->flags &= ~disable;
+
+	return wm->flags;
+}
+
+
+/**
+ *	@brief Set the wiimote smoothing alpha value.
+ *
+ *	@param wm			Pointer to a wiimote_t structure.
+ *	@param alpha		The alpha value to set. Between 0 and 1.
+ *
+ *	@return Returns the old alpha value.
+ *
+ *	The alpha value is between 0 and 1 and is used in an exponential
+ *	smoothing algorithm.
+ *
+ *	Smoothing is only performed if the WIIMOTE_USE_SMOOTHING is set.
+ */
+float wiiuse_set_smooth_alpha(struct wiimote_t* wm, float alpha) {
+	float old;
+
+	if (!wm)	return 0.0f;
+
+	old = wm->accel_calib.st_alpha;
+
+	wm->accel_calib.st_alpha = alpha;
+
+	/* if there is a nunchuk set that too */
+	if (wm->exp.type == EXP_NUNCHUK)
+		wm->exp.nunchuk.accel_calib.st_alpha = alpha;
+
+	return old;
+}
+
+
+/**
+ *	@brief	Set the bluetooth stack type to use.
+ *
+ *	@param wm		Array of wiimote_t structures.
+ *	@param wiimotes	Number of objects in the wm array.
+ *	@param type		The type of bluetooth stack to use.
+ */
+void wiiuse_set_bluetooth_stack(struct wiimote_t** wm, int wiimotes, enum win_bt_stack_t type) {
+	#ifdef WIN32
+	int i;
+
+	if (!wm)	return;
+
+	for (i = 0; i < wiimotes; ++i)
+		wm[i]->stack = type;
+	#endif
+}
+
+
+/**
+ *	@brief	Set the orientation event threshold.
+ *
+ *	@param wm			Pointer to a wiimote_t structure.
+ *	@param threshold	The decimal place that should be considered a significant change.
+ *
+ *	If threshold is 0.01, and any angle changes by 0.01 then a significant change
+ *	has occured and the event callback will be invoked.  If threshold is 1 then
+ *	the angle has to change by a full degree to generate an event.
+ */
+void wiiuse_set_orient_threshold(struct wiimote_t* wm, float threshold) {
+	if (!wm)	return;
+
+	wm->orient_threshold = threshold;
+}
+
+
+/**
+ *	@brief	Set the accelerometer event threshold.
+ *
+ *	@param wm			Pointer to a wiimote_t structure.
+ *	@param threshold	The decimal place that should be considered a significant change.
+ */
+void wiiuse_set_accel_threshold(struct wiimote_t* wm, int threshold) {
+	if (!wm)	return;
+
+	wm->accel_threshold = threshold;
+}
+
+
+/**
+ *	@brief Try to resync with the wiimote by starting a new handshake.
+ *
+ *	@param wm			Pointer to a wiimote_t structure.
+ */
+void wiiuse_resync(struct wiimote_t* wm) {
+	if (!wm)	return;
+
+	wm->handshake_state = 0;
+	wiiuse_handshake(wm, NULL, 0);
+}
+
+
+/**
+ *	@brief Set the normal and expansion handshake timeouts.
+ *
+ *	@param wm				Array of wiimote_t structures.
+ *	@param wiimotes			Number of objects in the wm array.
+ *	@param normal_timeout	The timeout in milliseconds for a normal read.
+ *	@param exp_timeout		The timeout in millisecondsd to wait for an expansion handshake.
+ */
+void wiiuse_set_timeout(struct wiimote_t** wm, int wiimotes, byte normal_timeout, byte exp_timeout) {
+	#ifdef WIN32
+	int i;
+
+	if (!wm)	return;
+
+	for (i = 0; i < wiimotes; ++i) {
+		wm[i]->normal_timeout = normal_timeout;
+		wm[i]->exp_timeout = exp_timeout;
+	}
+	#endif
+}
diff --git a/3rdparty/wiiuse/src/wiiuse_internal.h b/3rdparty/wiiuse/src/wiiuse_internal.h
new file mode 100644
index 0000000..db1d4be
--- /dev/null
+++ b/3rdparty/wiiuse/src/wiiuse_internal.h
@@ -0,0 +1,261 @@
+/*
+ *	wiiuse
+ *
+ *	Written By:
+ *		Michael Laforest	< para >
+ *		Michal Wiedenbauer	< shagkur >
+ *		Dave Murphy			< WinterMute >
+ *		Hector Martin		< marcan >
+ *		William Alozy		< wiill >
+ *
+ *	Copyright 2009
+ *
+ *
+ *	This file is part of wiiuse and fWIIne.
+ *
+ *	This program is free software; you can redistribute it and/or modify
+ *	it under the terms of the GNU General Public License as published by
+ *	the Free Software Foundation; either version 3 of the License, or
+ *	(at your option) any later version.
+ *
+ *	This program is distributed in the hope that it will be useful,
+ *	but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *	GNU General Public License for more details.
+ *
+ *	You should have received a copy of the GNU General Public License
+ *	along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ *	$Header$
+ *
+ */
+
+/**
+ *	@file
+ *	@brief General internal wiiuse stuff.
+ *
+ *	Since Wiiuse is a library, wiiuse.h is a duplicate
+ *	of the API header.
+ *
+ *	The code that would normally go in that file, but
+ *	which is not needed by third party developers,
+ *	is put here.
+ *
+ *	So wiiuse_internal.h is included by other files
+ *	internally, wiiuse.h is included only here.
+ */
+
+#ifndef WIIUSE_INTERNAL_H_INCLUDED
+#define WIIUSE_INTERNAL_H_INCLUDED
+
+#ifndef WIN32
+	#include <arpa/inet.h>				/* htons() */
+	#include <bluetooth/bluetooth.h>
+#endif
+
+#include "definitions.h"
+
+/* wiiuse version */
+#define WIIUSE_VERSION					"0.12"
+
+/********************
+ *
+ *	Wiimote internal codes
+ *
+ ********************/
+
+/* Communication channels */
+#define WM_OUTPUT_CHANNEL			0x11
+#define WM_INPUT_CHANNEL			0x13
+
+#define WM_SET_REPORT				0x50
+
+/* commands */
+#define WM_CMD_RUMBLE				0x10
+#define WM_CMD_LED					0x11
+#define WM_CMD_REPORT_TYPE			0x12
+#define WM_CMD_IR					0x13
+#define WM_CMD_CTRL_STATUS			0x15
+#define WM_CMD_WRITE_DATA			0x16
+#define WM_CMD_READ_DATA			0x17
+#define WM_CMD_IR_2					0x1A
+
+/* input report ids */
+#define WM_RPT_CTRL_STATUS			0x20
+#define WM_RPT_READ					0x21
+#define WM_RPT_WRITE				0x22
+#define WM_RPT_BTN					0x30
+#define WM_RPT_BTN_ACC				0x31
+#define WM_RPT_BTN_ACC_IR			0x33
+#define WM_RPT_BTN_EXP				0x34
+#define WM_RPT_BTN_ACC_EXP			0x35
+#define WM_RPT_BTN_IR_EXP			0x36
+#define WM_RPT_BTN_ACC_IR_EXP		0x37
+
+#define WM_BT_INPUT					0x01
+#define WM_BT_OUTPUT				0x02
+
+/* Identify the wiimote device by its class */
+#define WM_DEV_CLASS_0				0x04
+#define WM_DEV_CLASS_1				0x25
+#define WM_DEV_CLASS_2				0x00
+#define WM_VENDOR_ID				0x057E
+#define WM_PRODUCT_ID				0x0306
+
+/* controller status stuff */
+#define WM_MAX_BATTERY_CODE			0xC8
+
+/* offsets in wiimote memory */
+#define WM_MEM_OFFSET_CALIBRATION	0x16
+#define WM_EXP_MEM_BASE				0x04A40000
+#define WM_EXP_MEM_ENABLE			0x04A40040
+#define WM_EXP_MEM_ENABLE1			0x04A400F0
+#define WM_EXP_MEM_ENABLE2			0x04A400FB
+#define WM_EXP_MEM_KEY				0x04A40040
+#define WM_EXP_MEM_CALIBR			0x04A40020
+#define WM_EXP_MOTION_PLUS_ENABLE   0x04A600FE
+#define WM_EXP_ID					0x04A400FA
+
+#define WM_REG_IR					0x04B00030
+#define WM_REG_IR_BLOCK1			0x04B00000
+#define WM_REG_IR_BLOCK2			0x04B0001A
+#define WM_REG_IR_MODENUM			0x04B00033
+
+/* ir block data */
+#define WM_IR_BLOCK1_LEVEL1			"\x02\x00\x00\x71\x01\x00\x64\x00\xfe"
+#define WM_IR_BLOCK2_LEVEL1			"\xfd\x05"
+#define WM_IR_BLOCK1_LEVEL2			"\x02\x00\x00\x71\x01\x00\x96\x00\xb4"
+#define WM_IR_BLOCK2_LEVEL2			"\xb3\x04"
+#define WM_IR_BLOCK1_LEVEL3			"\x02\x00\x00\x71\x01\x00\xaa\x00\x64"
+#define WM_IR_BLOCK2_LEVEL3			"\x63\x03"
+#define WM_IR_BLOCK1_LEVEL4			"\x02\x00\x00\x71\x01\x00\xc8\x00\x36"
+#define WM_IR_BLOCK2_LEVEL4			"\x35\x03"
+#define WM_IR_BLOCK1_LEVEL5			"\x07\x00\x00\x71\x01\x00\x72\x00\x20"
+#define WM_IR_BLOCK2_LEVEL5			"\x1f\x03"
+
+#define WM_IR_TYPE_BASIC			0x01
+#define WM_IR_TYPE_EXTENDED			0x03
+#define WM_IR_TYPE_FULL				0x05
+
+/* controller status flags for the first message byte */
+/* bit 1 is unknown */
+#define WM_CTRL_STATUS_BYTE1_ATTACHMENT			0x02
+#define WM_CTRL_STATUS_BYTE1_SPEAKER_ENABLED	0x04
+#define WM_CTRL_STATUS_BYTE1_IR_ENABLED			0x08
+#define WM_CTRL_STATUS_BYTE1_LED_1				0x10
+#define WM_CTRL_STATUS_BYTE1_LED_2				0x20
+#define WM_CTRL_STATUS_BYTE1_LED_3				0x40
+#define WM_CTRL_STATUS_BYTE1_LED_4				0x80
+
+/* aspect ratio */
+#define WM_ASPECT_16_9_X	660
+#define WM_ASPECT_16_9_Y	370
+#define WM_ASPECT_4_3_X		560
+#define WM_ASPECT_4_3_Y		420
+
+
+/**
+ *	Expansion stuff
+ */
+
+/* encrypted expansion id codes (located at 0x04A400FC) */
+#define EXP_ID_CODE_NUNCHUK					0xa4200000
+//#define EXP_ID_CODE_NUNCHUK					0x9A1EFEFE
+#define EXP_ID_CODE_CLASSIC_CONTROLLER		0xa4200101
+#define EXP_ID_CODE_GUITAR					0xa4200103
+#define EXP_ID_CODE_WIIBOARD				0xa4200402
+#define EXP_ID_CODE_BALANCE_BOARD			EXP_ID_CODE_WIIBOARD
+#define EXP_ID_CODE_MOTION_PLUS				0xa4200405
+
+#define EXP_HANDSHAKE_LEN					224
+
+/********************
+ *
+ *	End Wiimote internal codes
+ *
+ ********************/
+
+/* wiimote state flags - (some duplicated in wiiuse.h)*/
+//#define WIIMOTE_STATE_DEV_FOUND				0x0001
+//#define WIIMOTE_STATE_HANDSHAKE				0x0002	/* actual connection exists but no handshake yet */
+//#define WIIMOTE_STATE_HANDSHAKE_COMPLETE	0x0004	/* actual connection exists but no handshake yet */
+//#define WIIMOTE_STATE_CONNECTED				0x0008
+//#define WIIMOTE_STATE_RUMBLE				0x0010
+//#define WIIMOTE_STATE_ACC					0x0020
+//#define WIIMOTE_STATE_EXP					0x0040
+//#define WIIMOTE_STATE_IR					0x0080
+//#define WIIMOTE_STATE_SPEAKER				0x0100
+//#define WIIMOTE_STATE_IR_SENS_LVL1			0x0200
+//#define WIIMOTE_STATE_IR_SENS_LVL2			0x0400
+//#define WIIMOTE_STATE_IR_SENS_LVL3			0x0800
+//#define WIIMOTE_STATE_IR_SENS_LVL4			0x1000
+//#define WIIMOTE_STATE_IR_SENS_LVL5			0x2000
+#define WIIMOTE_STATE_DEV_FOUND					0x00001
+//#define WIIMOTE_STATE_DEV_REGISTER				0x00002
+#define WIIMOTE_STATE_HANDSHAKE					0x00004	/* actual connection exists but no handshake yet */
+#define WIIMOTE_STATE_HANDSHAKE_COMPLETE		0x00008	/* actual connection exists but no handshake yet */
+#define WIIMOTE_STATE_CONNECTED					0x00010
+#define WIIMOTE_STATE_EXP_HANDSHAKE				0x00020	/* actual connection exists but no handshake yet */
+#define WIIMOTE_STATE_EXP_FAILED				0x00040	/* actual connection exists but no handshake yet */
+#define WIIMOTE_STATE_RUMBLE					0x00080
+#define WIIMOTE_STATE_ACC						0x00100
+#define WIIMOTE_STATE_EXP						0x00200
+#define WIIMOTE_STATE_IR						0x00400
+#define WIIMOTE_STATE_SPEAKER					0x00800
+#define WIIMOTE_STATE_IR_SENS_LVL1				0x01000
+#define WIIMOTE_STATE_IR_SENS_LVL2				0x02000
+#define WIIMOTE_STATE_IR_SENS_LVL3				0x04000
+#define WIIMOTE_STATE_IR_SENS_LVL4				0x08000
+#define WIIMOTE_STATE_IR_SENS_LVL5				0x10000
+#define WIIMOTE_STATE_IR_INIT					0x20000
+#define WIIMOTE_STATE_SPEAKER_INIT				0x40000
+
+#define WIIMOTE_INIT_STATES					(WIIMOTE_STATE_IR_SENS_LVL3)
+
+/* macro to manage states */
+#define WIIMOTE_IS_SET(wm, s)			((wm->state & (s)) == (s))
+#define WIIMOTE_ENABLE_STATE(wm, s)		(wm->state |= (s))
+#define WIIMOTE_DISABLE_STATE(wm, s)	(wm->state &= ~(s))
+#define WIIMOTE_TOGGLE_STATE(wm, s)		((wm->state & (s)) ? WIIMOTE_DISABLE_STATE(wm, s) : WIIMOTE_ENABLE_STATE(wm, s))
+
+#define WIIMOTE_IS_FLAG_SET(wm, s)		((wm->flags & (s)) == (s))
+#define WIIMOTE_ENABLE_FLAG(wm, s)		(wm->flags |= (s))
+#define WIIMOTE_DISABLE_FLAG(wm, s)		(wm->flags &= ~(s))
+#define WIIMOTE_TOGGLE_FLAG(wm, s)		((wm->flags & (s)) ? WIIMOTE_DISABLE_FLAG(wm, s) : WIIMOTE_ENABLE_FLAG(wm, s))
+
+#define NUNCHUK_IS_FLAG_SET(wm, s)		((*(wm->flags) & (s)) == (s))
+
+/* misc macros */
+#define WIIMOTE_ID(wm)					(wm->unid)
+#define WIIMOTE_IS_CONNECTED(wm)		(WIIMOTE_IS_SET(wm, WIIMOTE_STATE_CONNECTED))
+
+/*
+ *	Smooth tilt calculations are computed with the
+ *	exponential moving average formula:
+ *		St = St_last + (alpha * (tilt - St_last))
+ *	alpha is between 0 and 1
+ */
+#define WIIUSE_DEFAULT_SMOOTH_ALPHA		0.3f
+
+#define SMOOTH_ROLL						0x01
+#define SMOOTH_PITCH					0x02
+
+#include "wiiuse.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* not part of the api */
+int wiiuse_set_report_type(struct wiimote_t* wm);
+void wiiuse_send_next_pending_read_request(struct wiimote_t* wm);
+int wiiuse_send(struct wiimote_t* wm, byte report_type, byte* msg, int len);
+int wiiuse_read_data_cb(struct wiimote_t* wm, wiiuse_read_cb read_cb, byte* buffer, unsigned int offset, unsigned short len);
+void wiiuse_send_next_pending_write_request(struct wiimote_t* wm);
+int wiiuse_write_data_cb(struct wiimote_t *wm,uint addr,ubyte *data,ubyte len,wiiuse_write_cb write_cb);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* WIIUSE_INTERNAL_H_INCLUDED */
diff --git a/AUTHORS b/AUTHORS
new file mode 100644
index 0000000..9f244de
--- /dev/null
+++ b/AUTHORS
@@ -0,0 +1 @@
+Cesar Mauri Loba <cesar at crea-si dot com>
diff --git a/CMakeLists.txt b/CMakeLists.txt
new file mode 100644
index 0000000..0a1f8b8
--- /dev/null
+++ b/CMakeLists.txt
@@ -0,0 +1,568 @@
+cmake_minimum_required(VERSION 2.8)
+
+#
+# Project information
+# 
+set(CMAKE_CONFIGURATION_TYPES "Debug;Release" CACHE STRING "Configs" FORCE)
+# Installation prefix
+IF (WIN32)
+    SET (CMAKE_INSTALL_PREFIX "C:\\Program Files\\libsitplus" CACHE PATH "Installation directory")
+ELSE (WIN32)
+	IF (${CMAKE_BUILD_TYPE} MATCHES "Debug")
+		SET (CMAKE_INSTALL_PREFIX "/usr/local" CACHE PATH "Installation directory")
+	ELSE()
+		SET (CMAKE_INSTALL_PREFIX "/usr" CACHE PATH "Installation directory")
+	ENDIF()
+ENDIF (WIN32)
+
+project(libsitplus)
+
+set(LIBSITPLUS_MAJOR_VERSION 1)
+set(LIBSITPLUS_MINOR_VERSION 1)
+set(LIBSITPLUS_REVISION_VERSION 0)
+set(LIBSITPLUS_VERSION "${LIBSITPLUS_MAJOR_VERSION}.${LIBSITPLUS_MINOR_VERSION}.${LIBSITPLUS_REVISION_VERSION}")
+
+# if this is set to ON, then all libraries are built as shared libraries by default.
+SET(BUILD_SHARED_LIBS OFF CACHE BOOL "Build shared libraries as default?")
+
+# DISABLED: tests need to be updated
+# Build automated test binaries
+#SET(BUILD_TESTS OFF CACHE BOOL "Build tests?")
+#IF (BUILD_TESTS)
+#	ENABLE_TESTING()
+#ENDIF(BUILD_TESTS)
+
+# Verbose makefile?
+SET(CMAKE_VERBOSE_MAKEFILE OFF CACHE BOOL "Verbose Makefile")
+
+# Generate Doxygen doc
+SET(GENERATE_DOXYGEN OFF CACHE BOOL "Generate Doxygen documentation?")
+
+# Default build mode
+IF(NOT CMAKE_BUILD_TYPE AND (${CMAKE_GENERATOR} MATCHES ".*Makefiles"))
+  SET(CMAKE_BUILD_TYPE Release CACHE STRING
+      "Choose the type of build, options are: Debug Release" FORCE)
+ENDIF()
+
+# Minimum windows version (Windows 2000)
+if(WIN32)
+	set(_WIN32_WINNT "0x0500")
+endif(WIN32)
+
+###############################################################################
+# Directories 
+###############################################################################
+# Project path name
+STRING (TOLOWER ${PROJECT_NAME} projectNameLower)
+
+# Install locations
+SET (INCLUDEDIR "include/${projectNameLower}")
+set (BINDIR "bin")
+set (LIBDIR "lib")
+IF(WIN32)
+	set (PLUGINDIR "${BINDIR}")
+	set (LIBRUNTIMEDIR ${BINDIR})
+ELSE(WIN32)
+	set (PLUGINDIR "lib/${projectNameLower}")
+	set (LIBRUNTIMEDIR ${LIBDIR})
+ENDIF(WIN32)
+set (LOCALEDIR "share/locale")
+set (DATADIR "share/${projectNameLower}")
+set (DOCDIR "share/doc/${projectNameLower}")
+
+#
+# RPATH (ignored on Win32)
+# 
+# use, i.e. don't skip the full RPATH for the build tree
+SET(CMAKE_SKIP_BUILD_RPATH FALSE)
+
+# when building, don't use the install RPATH already
+# (but later on when installing)
+SET(CMAKE_BUILD_WITH_INSTALL_RPATH FALSE) 
+set (CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/${LIBDIR}")
+
+SET(CMAKE_INSTALL_RPATH_USE_LINK_PATH FALSE)
+
+# the RPATH to be used when installing, but only if it's not a system directory
+LIST(FIND CMAKE_PLATFORM_IMPLICIT_LINK_DIRECTORIES "${CMAKE_INSTALL_PREFIX}/${LIBDIR}" isSystemDir)
+IF("${isSystemDir}" STREQUAL "-1")
+   SET(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/${LIBDIR}")
+ENDIF("${isSystemDir}" STREQUAL "-1")
+
+#
+# Build locations
+# 
+
+# Additional cmake modules
+set(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake_modules/")
+
+# Location for public headers
+set (CUSTOM_INCLUDE_PATH "${CMAKE_SOURCE_DIR}/include")
+
+# Additional include locations (config files, base src, public includes & 3rd party)
+INCLUDE_DIRECTORIES(BEFORE ${CMAKE_BINARY_DIR}/include ${CUSTOM_INCLUDE_PATH} ${CMAKE_SOURCE_DIR}/3rdparty)
+
+#
+# For the add_library & add_executable commands. 
+# Not using LIBRARY_OUTPUT_PATH & EXECUTABLE_OUTPUT_PATH any more
+#
+
+# Plugins
+set (LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/${PLUGINDIR})
+# Binaries
+set (RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/${BINDIR})
+# Compile time binary artefacts
+set (ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/${LIBDIR})
+
+# In case of Makefiles need to add directory
+if (${CMAKE_GENERATOR} MATCHES ".*Makefiles")
+	set (LIBRARY_OUTPUT_DIRECTORY ${LIBRARY_OUTPUT_DIRECTORY}/${CMAKE_BUILD_TYPE})
+	set (RUNTIME_OUTPUT_DIRECTORY ${RUNTIME_OUTPUT_DIRECTORY}/${CMAKE_BUILD_TYPE})
+	set (ARCHIVE_OUTPUT_DIRECTORY ${ARCHIVE_OUTPUT_DIRECTORY}/${CMAKE_BUILD_TYPE})
+else()
+	foreach(_BUILD_TYPE ${CMAKE_CONFIGURATION_TYPES})
+		file(MAKE_DIRECTORY ${RUNTIME_OUTPUT_DIRECTORY}/${_BUILD_TYPE})
+	endforeach(_BUILD_TYPE ${CMAKE_CONFIGURATION_TYPES})
+endif()
+
+set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${LIBRARY_OUTPUT_DIRECTORY})
+set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${RUNTIME_OUTPUT_DIRECTORY})
+set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${ARCHIVE_OUTPUT_DIRECTORY})
+
+#####################################################################
+# Configuration CMakeFile
+# 
+# Two versions are provided:
+#
+# - The first one is used when the library is fully installed
+# - The second one is used when library is used directly in its
+#   build directory (i.e. not installed)
+#####################################################################
+
+# Relative paths endings
+set(CMAKE_LIBRUNTIMEDIR_CONFIGCMAKE \"${LIBRUNTIMEDIR}\")
+set(CMAKE_LIBDIR_CONFIGCMAKE \"${LIBDIR}\")
+set(CMAKE_PLUGINDIR_CONFIGCMAKE \"${PLUGINDIR}\")
+set(CMAKE_LOCALEDIR_CONFIGCMAKE \"${LOCALEDIR}\")
+set(CMAKE_DOCDIR_CONFIGCMAKE \"${DOCDIR}\")
+
+#
+# Installed version
+# 
+set(CMAKE_INCLUDE_DIRS_CONFIGCMAKE \"${CMAKE_INSTALL_PREFIX}/${INCLUDEDIR}\")
+# Link libraries (including plugins) can be either in 
+# LIBDIR (WIN32 .lib, linux .a) or in PLUGINDIR (linux .so)
+set(CMAKE_LIB_DIRS_CONFIGCMAKE "\"${CMAKE_INSTALL_PREFIX}/${LIBDIR}\" \"${CMAKE_INSTALL_PREFIX}/${PLUGINDIR}\"")
+
+# Not used yet
+set (LIBSITPLUS_DLLVERSION "")
+set (LIBSITPLUS_DEBUG_POSTFIX "")
+#
+
+configure_file(
+	"${CMAKE_CURRENT_SOURCE_DIR}/LibSITPLUSConfig.cmake.in" 
+	"${CMAKE_BINARY_DIR}/${DATADIR}/LibSITPLUSConfig.cmake" 
+	@ONLY
+)
+
+install (FILES "${CMAKE_BINARY_DIR}/${DATADIR}/LibSITPLUSConfig.cmake" 
+	DESTINATION "${CMAKE_INSTALL_PREFIX}/${DATADIR}"
+)
+
+#
+# Non-installed version
+# 
+set(CMAKE_INCLUDE_DIRS_CONFIGCMAKE \"${CUSTOM_INCLUDE_PATH}\")
+# Link libraries (including plugins) can be either in 
+# LIBDIR (WIN32 .lib, linux .a) or in PLUGINDIR (linux .so)
+set(CMAKE_LIB_DIRS_CONFIGCMAKE "\"${CMAKE_BINARY_DIR}/${LIBDIR}\" \"${CMAKE_BINARY_DIR}/${PLUGINDIR}\"")
+
+# Leave in the root of the CMAKE_BINARY_DIR
+configure_file(
+	"${CMAKE_CURRENT_SOURCE_DIR}/LibSITPLUSConfig.cmake.in" 
+	"${CMAKE_BINARY_DIR}/LibSITPLUSConfig.cmake" 
+	@ONLY
+)
+
+#####################################################################
+# Compiler flags
+#####################################################################
+
+set(EXTRA_C_FLAGS "")
+set(EXTRA_C_FLAGS_RELEASE "")
+set(EXTRA_C_FLAGS_DEBUG "")
+set(EXTRA_EXE_LINKER_FLAGS "")
+set(EXTRA_EXE_LINKER_FLAGS_RELEASE "")
+set(EXTRA_EXE_LINKER_FLAGS_DEBUG "")
+
+# Additional compiler flags. Needed for Linux 64 bit 
+IF(CMAKE_SYSTEM_NAME MATCHES "Linux")
+	add_definitions(-fPIC)
+ENDIF(CMAKE_SYSTEM_NAME MATCHES "Linux")
+
+if(MSVC)
+    set(EXTRA_C_FLAGS "${EXTRA_C_FLAGS} /D _CRT_SECURE_NO_DEPRECATE /D _CRT_NONSTDC_NO_DEPRECATE /D _SCL_SECURE_NO_WARNINGS")
+    # 64-bit portability warnings, in MSVC8
+    if(MSVC80)
+        set(EXTRA_C_FLAGS "${EXTRA_C_FLAGS} /Wp64")
+    endif()
+    if(MSVC90)
+	set(EXTRA_C_FLAGS "${EXTRA_C_FLAGS} /D _BIND_TO_CURRENT_CRT_VERSION=1 /D _BIND_TO_CURRENT_VCLIBS_VERSION=1")
+    endif()
+
+    set(EXTRA_EXE_LINKER_FLAGS_RELEASE "${EXTRA_EXE_LINKER_FLAGS_RELEASE} /debug")
+
+    # Whole program optimization
+    if(WHOLE_PROGRAM_OPTIMIZATION AND MSVC_VERSION GREATER 1300)
+        set(EXTRA_C_FLAGS_RELEASE "${EXTRA_C_FLAGS_RELEASE} /GL")
+        set(CMAKE_EXE_LINKER_FLAGS_RELEASE "${CMAKE_EXE_LINKER_FLAGS_RELEASE} /LTCG")
+        set(CMAKE_MODULE_LINKER_FLAGS_RELEASE "${CMAKE_MODULE_LINKER_FLAGS_RELEASE} /LTCG")
+    endif()   
+endif()
+
+if(CMAKE_COMPILER_IS_GNUCXX)
+    # High level of warnings.
+    set(EXTRA_C_FLAGS "${EXTRA_C_FLAGS} -Wall")
+
+    # The -Wno-long-long is required in 64bit systems when including sytem headers.
+    if(${CMAKE_SYSTEM_PROCESSOR} MATCHES x86_64*)
+    set(EXTRA_C_FLAGS "${EXTRA_C_FLAGS} -Wno-long-long")
+    endif()
+    if(${CMAKE_SYSTEM_PROCESSOR} MATCHES amd64*)
+    set(EXTRA_C_FLAGS "${EXTRA_C_FLAGS} -Wno-long-long")
+    endif()
+
+    # Whole program optimization
+    if(WHOLE_PROGRAM_OPTIMIZATION)
+        set(EXTRA_C_FLAGS_RELEASE "${EXTRA_C_FLAGS_RELEASE} -fwhole-program --combine")
+    endif()
+
+    # Other optimizations
+    if(USE_OMIT_FRAME_POINTER)
+       set(EXTRA_C_FLAGS_RELEASE "${EXTRA_C_FLAGS_RELEASE} -fomit-frame-pointer")
+    endif()
+    if(USE_O2)
+       set(EXTRA_C_FLAGS_RELEASE "${EXTRA_C_FLAGS_RELEASE} -O2")
+    endif()
+    if(USE_O3)
+       set(EXTRA_C_FLAGS_RELEASE "${EXTRA_C_FLAGS_RELEASE} -O3")
+    endif()
+    if(USE_FAST_MATH)
+       set(EXTRA_C_FLAGS_RELEASE "${EXTRA_C_FLAGS_RELEASE} -ffast-math")
+    endif()
+    if(USE_POWERPC)
+       set(EXTRA_C_FLAGS_RELEASE "${EXTRA_C_FLAGS_RELEASE} -mcpu=G3 -mtune=G5")
+    endif()
+    if(USE_MMX)
+       set(EXTRA_C_FLAGS_RELEASE "${EXTRA_C_FLAGS_RELEASE} -mmmx")
+    endif()
+    # SSE should be disabled under MingW because it generates compiler errors
+    if(USE_SSE)
+       set(EXTRA_C_FLAGS_RELEASE "${EXTRA_C_FLAGS_RELEASE} -msse")
+    endif()
+    # SSE2 should be disabled under MingW because it generates compiler errors
+    if(USE_SSE2)
+       set(EXTRA_C_FLAGS_RELEASE "${EXTRA_C_FLAGS_RELEASE} -msse2")
+    endif()
+    # SSE3 should be disabled under MingW because it generates compiler errors
+    if(USE_SSE3 AND NOT MINGW)
+       set(EXTRA_C_FLAGS_RELEASE "${EXTRA_C_FLAGS_RELEASE} -msse3")
+    endif()
+
+    set(EXTRA_C_FLAGS_RELEASE "${EXTRA_C_FLAGS_RELEASE} -DNDEBUG")
+    set(EXTRA_C_FLAGS_DEBUG "${EXTRA_C_FLAGS_DEBUG} -O0 -DDEBUG -D_DEBUG")
+endif()
+
+set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${EXTRA_C_FLAGS}")
+set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${EXTRA_C_FLAGS}")
+set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} ${EXTRA_C_FLAGS_RELEASE}")
+set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} ${EXTRA_C_FLAGS_RELEASE}")
+set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} ${EXTRA_C_FLAGS_DEBUG}")
+set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} ${EXTRA_C_FLAGS_DEBUG}")
+set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${EXTRA_EXE_LINKER_FLAGS}")
+set(CMAKE_EXE_LINKER_FLAGS_RELEASE "${CMAKE_EXE_LINKER_FLAGS_RELEASE} ${EXTRA_EXE_LINKER_FLAGS_RELEASE}")
+set(CMAKE_EXE_LINKER_FLAGS_DEBUG "${CMAKE_EXE_LINKER_FLAGS_DEBUG} ${EXTRA_EXE_LINKER_FLAGS_DEBUG}")
+
+if (WIN32 AND MSVC)  
+    string(REPLACE "/W3" "/W4" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
+    string(REPLACE "/W3" "/W4" CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE}")
+    string(REPLACE "/W3" "/W4" CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG}")
+endif()
+
+#####################################################################
+# Documentation
+#####################################################################
+
+#
+# Add doc target if necessary
+# 
+get_target_property(DOC_TARGET doc TYPE)
+if(NOT DOC_TARGET)
+	add_custom_target(doc ALL)
+endif()
+	
+# Add doc-update dependency
+add_dependencies(doc doc-update)
+
+#####################################################################
+# Doxygen
+#####################################################################
+IF(GENERATE_DOXYGEN)
+	# check if doxygen is even installed
+	find_package(Doxygen)
+	if (DOXYGEN_FOUND STREQUAL "NO")
+		message(FATAL_ERROR "Doxygen not found. Please get a copy http://www.doxygen.org")
+	endif (DOXYGEN_FOUND STREQUAL "NO")
+
+	# prepare doxygen configuration file
+#	configure_file(${CMAKE_CURRENT_SOURCE_DIR}/Doxyfile.in ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile)
+
+	# add doxygen as target
+#	add_custom_target(doxygen ${DOXYGEN_EXECUTABLE} ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile)
+
+	# cleanup $build/api-doc on "make clean"
+#	set_property(DIRECTORY APPEND PROPERTY ADDITIONAL_MAKE_CLEAN_FILES api-doc)
+
+	# add doxygen as dependency to doc-target
+	add_dependencies(doc doxygen-spcore)
+ENDIF(GENERATE_DOXYGEN)
+
+# install HTML API documentation and manual pages
+#set(DOC_PATH "share/doc/${CPACK_PACKAGE_NAME}-${VERSION}")
+
+#install(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/api-doc/html
+#         DESTINATION ${DOC_PATH}
+#       )
+
+# install man pages into packages, scope is now project root..
+#install(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/api-doc/man/man3
+#         DESTINATION share/man/man3/
+#       )
+
+#####################################################################
+# Installation
+#####################################################################
+install(DIRECTORY sp DESTINATION "${DATADIR}")
+install(FILES AUTHORS COPYING NEWS README DESTINATION "${DOCDIR}")
+
+#
+# Binary installation
+# 
+if(WIN32)
+	SET(CPACK_GENERATOR "NSIS")
+else(WIN32)
+	SET(CPACK_GENERATOR "DEB")
+endif(WIN32)
+
+if (WIN32 AND MSVC)
+	include (InstallRequiredSystemLibraries)
+endif (WIN32 AND MSVC)
+
+SET(CPACK_NSIS_DISPLAY_NAME ${projectNameLower})
+#SET(CPACK_PACKAGE_DESCRIPTION_FILE "README")
+SET(CPACK_PACKAGE_DESCRIPTION_SUMMARY "libsitplus is a library which provides a framework to develop dataflow applications")
+SET(CPACK_PACKAGE_FILE_NAME ${projectNameLower}-${LIBSITPLUS_VERSION})
+#SET(CPACK_PACKAGE_NAME ${projectNameLower}-${LIBSITPLUS_VERSION})
+SET(CPACK_PACKAGE_VENDOR "Cesar Mauri Loba - CREA Software Systems")
+SET(CPACK_PACKAGE_VERSION ${LIBSITPLUS_VERSION})
+SET(CPACK_PACKAGE_VERSION_MAJOR ${LIBSITPLUS_MAJOR_VERSION})
+SET(CPACK_PACKAGE_VERSION_MINOR ${LIBSITPLUS_MINOR_VERSION})
+SET(CPACK_PACKAGE_VERSION_PATCH ${LIBSITPLUS_REVISION_VERSION})
+SET(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_SOURCE_DIR}/COPYING")
+#SET(CPACK_RESOURCE_FILE_README "README")
+#SET(CPACK_RESOURCE_FILE_WELCOME "${CMAKE_SOURCE_DIR}/installnote.rtf")
+
+if (NOT WIN32)
+	# Linux 
+	SET(CPACK_PACKAGING_INSTALL_PREFIX "/usr")
+	SET(CPACK_DEBIAN_PACKAGE_MAINTAINER "Debian Med Packaging Team")	
+	SET(CPACK_DEBIAN_PACKAGE_SECTION "libs")
+	SET(CPACK_DEBIAN_PACKAGE_SHLIBDEPS ON)
+else (NOT WIN32)
+	SET (CPACK_PACKAGE_INSTALL_DIRECTORY ${projectNameLower})
+endif(NOT WIN32)
+
+#
+# Sources
+# 
+SET(CPACK_SOURCE_GENERATOR "TGZ")
+SET(CPACK_SOURCE_PACKAGE_FILE_NAME "${projectNameLower}-${SITPLUS_VERSION}")
+SET(CPACK_SOURCE_STRIP_FILES "")
+SET(CPACK_STRIP_FILES "true")
+
+
+# Avoid installation for debug configuration
+install(FILES ERROR-INSTALLING_DEBUG_CONFIGURATION DESTINATION "${DATADIR}" CONFIGURATIONS Debug)
+# Prevent Debug package generation (only works when Makefiles generator is used)
+IF (NOT (${CMAKE_BUILD_TYPE} MATCHES Debug))
+	INCLUDE(CPack)
+ENDIF()
+
+#####################################################################
+# Required libraries
+#####################################################################
+
+#
+# Boost
+#
+
+IF(CMAKE_SYSTEM_NAME MATCHES "Linux")
+	set(Boost_USE_STATIC_LIBS OFF)
+	set(Boost_USE_STATIC_RUNTIME OFF)
+else ()
+	set(Boost_USE_STATIC_LIBS ON)
+	set(Boost_USE_STATIC_RUNTIME ON)
+endif()
+set(Boost_USE_MULTITHREAD ON)
+
+find_package(Boost REQUIRED)
+
+# Boost version 1.39 or greater required 
+# Lower versions fail to compile with g++ 4.4
+IF ((${Boost_MAJOR_VERSION} LESS 1) OR 
+	(${Boost_MAJOR_VERSION} EQUAL 1) AND (${Boost_MINOR_VERSION} LESS 39))
+	MESSAGE (FATAL_ERROR "Boost version less than 1.39")
+ENDIF()
+include_directories ( ${Boost_INCLUDE_DIRS} )
+link_directories ( ${Boost_LIBRARY_DIRS} )
+
+#
+# POCO
+#
+
+find_package(POCO)
+if(WIN32)
+	find_file (_POCO_FOUNDATION_RUNTIMED bin/PocoFoundationd.dll HINTS $ENV{POCO_ROOT})
+	find_file (_POCO_FOUNDATION_RUNTIME bin/PocoFoundation.dll HINTS $ENV{POCO_ROOT})
+	if (MSVC)
+		# Copy runtime to build directory
+		configure_file(${_POCO_FOUNDATION_RUNTIMED} ${RUNTIME_OUTPUT_DIRECTORY}/Debug COPYONLY)
+		configure_file(${_POCO_FOUNDATION_RUNTIME} ${RUNTIME_OUTPUT_DIRECTORY}/Release COPYONLY)
+	endif(MSVC)
+	
+	install(FILES ${_POCO_FOUNDATION_RUNTIMED} DESTINATION "${BINDIR}" CONFIGURATIONS Debug)
+	install(FILES ${_POCO_FOUNDATION_RUNTIME} DESTINATION "${BINDIR}" CONFIGURATIONS Release)
+	
+	unset (_POCO_FOUNDATION_RUNTIMED)
+	unset (_POCO_FOUNDATION_RUNTIME)
+endif(WIN32)
+
+#
+# wxWidgets
+#
+
+option(ENABLE_WXWIDGETS "Enable wxWidgets support" 1)
+
+if (ENABLE_WXWIDGETS)
+	set(wxWidgets_USE_UNICODE ON)
+	if(WIN32)
+		set(wxWidgets_CONFIGURATION "mswu")
+	else(WIN32)
+		if (CMAKE_BUILD_TYPE MATCHES Debug)
+			set(wxWidgets_USE_DEBUG ON)
+		else()
+			set(wxWidgets_USE_DEBUG OFF)
+		endif()		
+	endif(WIN32)
+	message (STATUS "wxWidgets_USE_DEBUG : ${wxWidgets_USE_DEBUG}")
+	
+	# Use shared libraries
+	set(wxWidgets_USE_STATIC OFF)
+	set(_SAVED_BUILD_SHARED_LIBS ${BUILD_SHARED_LIBS})
+	set(BUILD_SHARED_LIBS ON)	
+	find_package(wxWidgets COMPONENTS core base adv REQUIRED)
+	set(BUILD_SHARED_LIBS ${_SAVED_BUILD_SHARED_LIBS})
+	
+	include(${wxWidgets_USE_FILE})
+	
+	# Find wxWidgets runtime
+	if (WIN32)
+		find_file (_WX_CORE_RUNTIMED wxmsw28ud_core_vc_custom.dll PATHS ${wxWidgets_LIB_DIR})
+		find_file (_WX_CORE_RUNTIME wxmsw28u_core_vc_custom.dll PATHS ${wxWidgets_LIB_DIR})
+		
+		find_file (_WX_BASE_RUNTIMED wxbase28ud_vc_custom.dll PATHS ${wxWidgets_LIB_DIR})
+		find_file (_WX_BASE_RUNTIME wxbase28u_vc_custom.dll PATHS ${wxWidgets_LIB_DIR})
+		
+		find_file (_WX_ADV_RUNTIMED wxmsw28ud_adv_vc_custom.dll PATHS ${wxWidgets_LIB_DIR})
+		find_file (_WX_ADV_RUNTIME wxmsw28u_adv_vc_custom.dll PATHS ${wxWidgets_LIB_DIR})
+		
+		if (MSVC)
+			# Make sure wxWidgets is available in build path
+			configure_file(${_WX_CORE_RUNTIMED} ${RUNTIME_OUTPUT_DIRECTORY}/Debug COPYONLY)
+			configure_file(${_WX_CORE_RUNTIME} ${RUNTIME_OUTPUT_DIRECTORY}/Release COPYONLY)
+			
+			configure_file(${_WX_BASE_RUNTIMED} ${RUNTIME_OUTPUT_DIRECTORY}/Debug COPYONLY)
+			configure_file(${_WX_BASE_RUNTIME} ${RUNTIME_OUTPUT_DIRECTORY}/Release COPYONLY)
+			
+			configure_file(${_WX_ADV_RUNTIMED} ${RUNTIME_OUTPUT_DIRECTORY}/Debug COPYONLY)
+			configure_file(${_WX_ADV_RUNTIME} ${RUNTIME_OUTPUT_DIRECTORY}/Release COPYONLY)
+		endif(MSVC)
+		
+		install(FILES ${_WX_CORE_RUNTIMED} DESTINATION "${BINDIR}" CONFIGURATIONS Debug)
+		install(FILES ${_WX_CORE_RUNTIME} DESTINATION "${BINDIR}" CONFIGURATIONS Release)
+		
+		install(FILES ${_WX_BASE_RUNTIMED} DESTINATION "${BINDIR}" CONFIGURATIONS Debug)
+		install(FILES ${_WX_BASE_RUNTIME} DESTINATION "${BINDIR}" CONFIGURATIONS Release)
+		
+		install(FILES ${_WX_ADV_RUNTIMED} DESTINATION "${BINDIR}" CONFIGURATIONS Debug)
+		install(FILES ${_WX_ADV_RUNTIME} DESTINATION "${BINDIR}" CONFIGURATIONS Release)
+		
+		unset (_WX_CORE_RUNTIMED)
+		unset (_WX_CORE_RUNTIME)
+		
+		unset (_WX_BASE_RUNTIMED)
+		unset (_WX_BASE_RUNTIME)
+		
+		unset (_WX_ADV_RUNTIMED)
+		unset (_WX_ADV_RUNTIME)
+	endif(WIN32)
+endif (ENABLE_WXWIDGETS)
+
+#
+# i18n
+# 
+option(ENABLE_NLS "Enable translations support and building" ON)
+if (ENABLE_NLS)
+	if (WIN32)
+		option(ENABLE_POT_UPDATE_TARGET "Enables the tools to update the pot files." OFF)
+	else(WIN32)
+		option(ENABLE_POT_UPDATE_TARGET "Enables the tools to update the pot files." ON)
+	endif(WIN32)
+
+	find_package(Gettext REQUIRED)
+	find_package(Libintl REQUIRED)
+
+	if(ENABLE_POT_UPDATE_TARGET)
+		find_package(TranslationTools REQUIRED)
+	endif(ENABLE_POT_UPDATE_TARGET)
+	
+	# get languages
+	file(READ po/LINGUAS LINGUAS)
+	string(REPLACE "\n" "" LINGUAS ${LINGUAS})
+	separate_arguments(LINGUAS)
+	
+	INCLUDE_DIRECTORIES(BEFORE ${LIBINTL_INCLUDE_DIR})
+	add_subdirectory(po)
+	
+	if(WIN32)
+		configure_file("${LIBINTL_ROOT_PATH}/bin/libintl3.dll" ${RUNTIME_OUTPUT_DIRECTORY}/Debug COPYONLY)
+		configure_file("${LIBINTL_ROOT_PATH}/bin/libintl3.dll" ${RUNTIME_OUTPUT_DIRECTORY}/Release COPYONLY)
+		configure_file("${LIBINTL_ROOT_PATH}/bin/libiconv2.dll" ${RUNTIME_OUTPUT_DIRECTORY}/Debug COPYONLY)
+		configure_file("${LIBINTL_ROOT_PATH}/bin/libiconv2.dll" ${RUNTIME_OUTPUT_DIRECTORY}/Release COPYONLY)
+
+		install(FILES "${LIBINTL_ROOT_PATH}/bin/libintl3.dll"  "${LIBINTL_ROOT_PATH}/bin/libiconv2.dll" DESTINATION "${BINDIR}")
+	endif(WIN32)	
+endif (ENABLE_NLS)
+
+#####################################################################
+# configuration file
+#####################################################################
+configure_file ("${PROJECT_SOURCE_DIR}/include/config.h.in"
+                "${PROJECT_BINARY_DIR}/include/config.h" )
+
+#####################################################################
+# Subdirectories
+#####################################################################
+add_subdirectory(3rdparty)
+add_subdirectory(src)
+add_subdirectory(doc)
\ No newline at end of file
diff --git a/COPYING b/COPYING
new file mode 100644
index 0000000..94a9ed0
--- /dev/null
+++ b/COPYING
@@ -0,0 +1,674 @@
+                    GNU GENERAL PUBLIC LICENSE
+                       Version 3, 29 June 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+                            Preamble
+
+  The GNU General Public License is a free, copyleft license for
+software and other kinds of works.
+
+  The licenses for most software and other practical works are designed
+to take away your freedom to share and change the works.  By contrast,
+the GNU General Public License is intended to guarantee your freedom to
+share and change all versions of a program--to make sure it remains free
+software for all its users.  We, the Free Software Foundation, use the
+GNU General Public License for most of our software; it applies also to
+any other work released this way by its authors.  You can apply it to
+your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+them if you wish), that you receive source code or can get it if you
+want it, that you can change the software or use pieces of it in new
+free programs, and that you know you can do these things.
+
+  To protect your rights, we need to prevent others from denying you
+these rights or asking you to surrender the rights.  Therefore, you have
+certain responsibilities if you distribute copies of the software, or if
+you modify it: responsibilities to respect the freedom of others.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must pass on to the recipients the same
+freedoms that you received.  You must make sure that they, too, receive
+or can get the source code.  And you must show them these terms so they
+know their rights.
+
+  Developers that use the GNU GPL protect your rights with two steps:
+(1) assert copyright on the software, and (2) offer you this License
+giving you legal permission to copy, distribute and/or modify it.
+
+  For the developers' and authors' protection, the GPL clearly explains
+that there is no warranty for this free software.  For both users' and
+authors' sake, the GPL requires that modified versions be marked as
+changed, so that their problems will not be attributed erroneously to
+authors of previous versions.
+
+  Some devices are designed to deny users access to install or run
+modified versions of the software inside them, although the manufacturer
+can do so.  This is fundamentally incompatible with the aim of
+protecting users' freedom to change the software.  The systematic
+pattern of such abuse occurs in the area of products for individuals to
+use, which is precisely where it is most unacceptable.  Therefore, we
+have designed this version of the GPL to prohibit the practice for those
+products.  If such problems arise substantially in other domains, we
+stand ready to extend this provision to those domains in future versions
+of the GPL, as needed to protect the freedom of users.
+
+  Finally, every program is threatened constantly by software patents.
+States should not allow patents to restrict development and use of
+software on general-purpose computers, but in those that do, we wish to
+avoid the special danger that patents applied to a free program could
+make it effectively proprietary.  To prevent this, the GPL assures that
+patents cannot be used to render the program non-free.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+
+                       TERMS AND CONDITIONS
+
+  0. Definitions.
+
+  "This License" refers to version 3 of the GNU General Public License.
+
+  "Copyright" also means copyright-like laws that apply to other kinds of
+works, such as semiconductor masks.
+
+  "The Program" refers to any copyrightable work licensed under this
+License.  Each licensee is addressed as "you".  "Licensees" and
+"recipients" may be individuals or organizations.
+
+  To "modify" a work means to copy from or adapt all or part of the work
+in a fashion requiring copyright permission, other than the making of an
+exact copy.  The resulting work is called a "modified version" of the
+earlier work or a work "based on" the earlier work.
+
+  A "covered work" means either the unmodified Program or a work based
+on the Program.
+
+  To "propagate" a work means to do anything with it that, without
+permission, would make you directly or secondarily liable for
+infringement under applicable copyright law, except executing it on a
+computer or modifying a private copy.  Propagation includes copying,
+distribution (with or without modification), making available to the
+public, and in some countries other activities as well.
+
+  To "convey" a work means any kind of propagation that enables other
+parties to make or receive copies.  Mere interaction with a user through
+a computer network, with no transfer of a copy, is not conveying.
+
+  An interactive user interface displays "Appropriate Legal Notices"
+to the extent that it includes a convenient and prominently visible
+feature that (1) displays an appropriate copyright notice, and (2)
+tells the user that there is no warranty for the work (except to the
+extent that warranties are provided), that licensees may convey the
+work under this License, and how to view a copy of this License.  If
+the interface presents a list of user commands or options, such as a
+menu, a prominent item in the list meets this criterion.
+
+  1. Source Code.
+
+  The "source code" for a work means the preferred form of the work
+for making modifications to it.  "Object code" means any non-source
+form of a work.
+
+  A "Standard Interface" means an interface that either is an official
+standard defined by a recognized standards body, or, in the case of
+interfaces specified for a particular programming language, one that
+is widely used among developers working in that language.
+
+  The "System Libraries" of an executable work include anything, other
+than the work as a whole, that (a) is included in the normal form of
+packaging a Major Component, but which is not part of that Major
+Component, and (b) serves only to enable use of the work with that
+Major Component, or to implement a Standard Interface for which an
+implementation is available to the public in source code form.  A
+"Major Component", in this context, means a major essential component
+(kernel, window system, and so on) of the specific operating system
+(if any) on which the executable work runs, or a compiler used to
+produce the work, or an object code interpreter used to run it.
+
+  The "Corresponding Source" for a work in object code form means all
+the source code needed to generate, install, and (for an executable
+work) run the object code and to modify the work, including scripts to
+control those activities.  However, it does not include the work's
+System Libraries, or general-purpose tools or generally available free
+programs which are used unmodified in performing those activities but
+which are not part of the work.  For example, Corresponding Source
+includes interface definition files associated with source files for
+the work, and the source code for shared libraries and dynamically
+linked subprograms that the work is specifically designed to require,
+such as by intimate data communication or control flow between those
+subprograms and other parts of the work.
+
+  The Corresponding Source need not include anything that users
+can regenerate automatically from other parts of the Corresponding
+Source.
+
+  The Corresponding Source for a work in source code form is that
+same work.
+
+  2. Basic Permissions.
+
+  All rights granted under this License are granted for the term of
+copyright on the Program, and are irrevocable provided the stated
+conditions are met.  This License explicitly affirms your unlimited
+permission to run the unmodified Program.  The output from running a
+covered work is covered by this License only if the output, given its
+content, constitutes a covered work.  This License acknowledges your
+rights of fair use or other equivalent, as provided by copyright law.
+
+  You may make, run and propagate covered works that you do not
+convey, without conditions so long as your license otherwise remains
+in force.  You may convey covered works to others for the sole purpose
+of having them make modifications exclusively for you, or provide you
+with facilities for running those works, provided that you comply with
+the terms of this License in conveying all material for which you do
+not control copyright.  Those thus making or running the covered works
+for you must do so exclusively on your behalf, under your direction
+and control, on terms that prohibit them from making any copies of
+your copyrighted material outside their relationship with you.
+
+  Conveying under any other circumstances is permitted solely under
+the conditions stated below.  Sublicensing is not allowed; section 10
+makes it unnecessary.
+
+  3. Protecting Users' Legal Rights From Anti-Circumvention Law.
+
+  No covered work shall be deemed part of an effective technological
+measure under any applicable law fulfilling obligations under article
+11 of the WIPO copyright treaty adopted on 20 December 1996, or
+similar laws prohibiting or restricting circumvention of such
+measures.
+
+  When you convey a covered work, you waive any legal power to forbid
+circumvention of technological measures to the extent such circumvention
+is effected by exercising rights under this License with respect to
+the covered work, and you disclaim any intention to limit operation or
+modification of the work as a means of enforcing, against the work's
+users, your or third parties' legal rights to forbid circumvention of
+technological measures.
+
+  4. Conveying Verbatim Copies.
+
+  You may convey verbatim copies of the Program's source code as you
+receive it, in any medium, provided that you conspicuously and
+appropriately publish on each copy an appropriate copyright notice;
+keep intact all notices stating that this License and any
+non-permissive terms added in accord with section 7 apply to the code;
+keep intact all notices of the absence of any warranty; and give all
+recipients a copy of this License along with the Program.
+
+  You may charge any price or no price for each copy that you convey,
+and you may offer support or warranty protection for a fee.
+
+  5. Conveying Modified Source Versions.
+
+  You may convey a work based on the Program, or the modifications to
+produce it from the Program, in the form of source code under the
+terms of section 4, provided that you also meet all of these conditions:
+
+    a) The work must carry prominent notices stating that you modified
+    it, and giving a relevant date.
+
+    b) The work must carry prominent notices stating that it is
+    released under this License and any conditions added under section
+    7.  This requirement modifies the requirement in section 4 to
+    "keep intact all notices".
+
+    c) You must license the entire work, as a whole, under this
+    License to anyone who comes into possession of a copy.  This
+    License will therefore apply, along with any applicable section 7
+    additional terms, to the whole of the work, and all its parts,
+    regardless of how they are packaged.  This License gives no
+    permission to license the work in any other way, but it does not
+    invalidate such permission if you have separately received it.
+
+    d) If the work has interactive user interfaces, each must display
+    Appropriate Legal Notices; however, if the Program has interactive
+    interfaces that do not display Appropriate Legal Notices, your
+    work need not make them do so.
+
+  A compilation of a covered work with other separate and independent
+works, which are not by their nature extensions of the covered work,
+and which are not combined with it such as to form a larger program,
+in or on a volume of a storage or distribution medium, is called an
+"aggregate" if the compilation and its resulting copyright are not
+used to limit the access or legal rights of the compilation's users
+beyond what the individual works permit.  Inclusion of a covered work
+in an aggregate does not cause this License to apply to the other
+parts of the aggregate.
+
+  6. Conveying Non-Source Forms.
+
+  You may convey a covered work in object code form under the terms
+of sections 4 and 5, provided that you also convey the
+machine-readable Corresponding Source under the terms of this License,
+in one of these ways:
+
+    a) Convey the object code in, or embodied in, a physical product
+    (including a physical distribution medium), accompanied by the
+    Corresponding Source fixed on a durable physical medium
+    customarily used for software interchange.
+
+    b) Convey the object code in, or embodied in, a physical product
+    (including a physical distribution medium), accompanied by a
+    written offer, valid for at least three years and valid for as
+    long as you offer spare parts or customer support for that product
+    model, to give anyone who possesses the object code either (1) a
+    copy of the Corresponding Source for all the software in the
+    product that is covered by this License, on a durable physical
+    medium customarily used for software interchange, for a price no
+    more than your reasonable cost of physically performing this
+    conveying of source, or (2) access to copy the
+    Corresponding Source from a network server at no charge.
+
+    c) Convey individual copies of the object code with a copy of the
+    written offer to provide the Corresponding Source.  This
+    alternative is allowed only occasionally and noncommercially, and
+    only if you received the object code with such an offer, in accord
+    with subsection 6b.
+
+    d) Convey the object code by offering access from a designated
+    place (gratis or for a charge), and offer equivalent access to the
+    Corresponding Source in the same way through the same place at no
+    further charge.  You need not require recipients to copy the
+    Corresponding Source along with the object code.  If the place to
+    copy the object code is a network server, the Corresponding Source
+    may be on a different server (operated by you or a third party)
+    that supports equivalent copying facilities, provided you maintain
+    clear directions next to the object code saying where to find the
+    Corresponding Source.  Regardless of what server hosts the
+    Corresponding Source, you remain obligated to ensure that it is
+    available for as long as needed to satisfy these requirements.
+
+    e) Convey the object code using peer-to-peer transmission, provided
+    you inform other peers where the object code and Corresponding
+    Source of the work are being offered to the general public at no
+    charge under subsection 6d.
+
+  A separable portion of the object code, whose source code is excluded
+from the Corresponding Source as a System Library, need not be
+included in conveying the object code work.
+
+  A "User Product" is either (1) a "consumer product", which means any
+tangible personal property which is normally used for personal, family,
+or household purposes, or (2) anything designed or sold for incorporation
+into a dwelling.  In determining whether a product is a consumer product,
+doubtful cases shall be resolved in favor of coverage.  For a particular
+product received by a particular user, "normally used" refers to a
+typical or common use of that class of product, regardless of the status
+of the particular user or of the way in which the particular user
+actually uses, or expects or is expected to use, the product.  A product
+is a consumer product regardless of whether the product has substantial
+commercial, industrial or non-consumer uses, unless such uses represent
+the only significant mode of use of the product.
+
+  "Installation Information" for a User Product means any methods,
+procedures, authorization keys, or other information required to install
+and execute modified versions of a covered work in that User Product from
+a modified version of its Corresponding Source.  The information must
+suffice to ensure that the continued functioning of the modified object
+code is in no case prevented or interfered with solely because
+modification has been made.
+
+  If you convey an object code work under this section in, or with, or
+specifically for use in, a User Product, and the conveying occurs as
+part of a transaction in which the right of possession and use of the
+User Product is transferred to the recipient in perpetuity or for a
+fixed term (regardless of how the transaction is characterized), the
+Corresponding Source conveyed under this section must be accompanied
+by the Installation Information.  But this requirement does not apply
+if neither you nor any third party retains the ability to install
+modified object code on the User Product (for example, the work has
+been installed in ROM).
+
+  The requirement to provide Installation Information does not include a
+requirement to continue to provide support service, warranty, or updates
+for a work that has been modified or installed by the recipient, or for
+the User Product in which it has been modified or installed.  Access to a
+network may be denied when the modification itself materially and
+adversely affects the operation of the network or violates the rules and
+protocols for communication across the network.
+
+  Corresponding Source conveyed, and Installation Information provided,
+in accord with this section must be in a format that is publicly
+documented (and with an implementation available to the public in
+source code form), and must require no special password or key for
+unpacking, reading or copying.
+
+  7. Additional Terms.
+
+  "Additional permissions" are terms that supplement the terms of this
+License by making exceptions from one or more of its conditions.
+Additional permissions that are applicable to the entire Program shall
+be treated as though they were included in this License, to the extent
+that they are valid under applicable law.  If additional permissions
+apply only to part of the Program, that part may be used separately
+under those permissions, but the entire Program remains governed by
+this License without regard to the additional permissions.
+
+  When you convey a copy of a covered work, you may at your option
+remove any additional permissions from that copy, or from any part of
+it.  (Additional permissions may be written to require their own
+removal in certain cases when you modify the work.)  You may place
+additional permissions on material, added by you to a covered work,
+for which you have or can give appropriate copyright permission.
+
+  Notwithstanding any other provision of this License, for material you
+add to a covered work, you may (if authorized by the copyright holders of
+that material) supplement the terms of this License with terms:
+
+    a) Disclaiming warranty or limiting liability differently from the
+    terms of sections 15 and 16 of this License; or
+
+    b) Requiring preservation of specified reasonable legal notices or
+    author attributions in that material or in the Appropriate Legal
+    Notices displayed by works containing it; or
+
+    c) Prohibiting misrepresentation of the origin of that material, or
+    requiring that modified versions of such material be marked in
+    reasonable ways as different from the original version; or
+
+    d) Limiting the use for publicity purposes of names of licensors or
+    authors of the material; or
+
+    e) Declining to grant rights under trademark law for use of some
+    trade names, trademarks, or service marks; or
+
+    f) Requiring indemnification of licensors and authors of that
+    material by anyone who conveys the material (or modified versions of
+    it) with contractual assumptions of liability to the recipient, for
+    any liability that these contractual assumptions directly impose on
+    those licensors and authors.
+
+  All other non-permissive additional terms are considered "further
+restrictions" within the meaning of section 10.  If the Program as you
+received it, or any part of it, contains a notice stating that it is
+governed by this License along with a term that is a further
+restriction, you may remove that term.  If a license document contains
+a further restriction but permits relicensing or conveying under this
+License, you may add to a covered work material governed by the terms
+of that license document, provided that the further restriction does
+not survive such relicensing or conveying.
+
+  If you add terms to a covered work in accord with this section, you
+must place, in the relevant source files, a statement of the
+additional terms that apply to those files, or a notice indicating
+where to find the applicable terms.
+
+  Additional terms, permissive or non-permissive, may be stated in the
+form of a separately written license, or stated as exceptions;
+the above requirements apply either way.
+
+  8. Termination.
+
+  You may not propagate or modify a covered work except as expressly
+provided under this License.  Any attempt otherwise to propagate or
+modify it is void, and will automatically terminate your rights under
+this License (including any patent licenses granted under the third
+paragraph of section 11).
+
+  However, if you cease all violation of this License, then your
+license from a particular copyright holder is reinstated (a)
+provisionally, unless and until the copyright holder explicitly and
+finally terminates your license, and (b) permanently, if the copyright
+holder fails to notify you of the violation by some reasonable means
+prior to 60 days after the cessation.
+
+  Moreover, your license from a particular copyright holder is
+reinstated permanently if the copyright holder notifies you of the
+violation by some reasonable means, this is the first time you have
+received notice of violation of this License (for any work) from that
+copyright holder, and you cure the violation prior to 30 days after
+your receipt of the notice.
+
+  Termination of your rights under this section does not terminate the
+licenses of parties who have received copies or rights from you under
+this License.  If your rights have been terminated and not permanently
+reinstated, you do not qualify to receive new licenses for the same
+material under section 10.
+
+  9. Acceptance Not Required for Having Copies.
+
+  You are not required to accept this License in order to receive or
+run a copy of the Program.  Ancillary propagation of a covered work
+occurring solely as a consequence of using peer-to-peer transmission
+to receive a copy likewise does not require acceptance.  However,
+nothing other than this License grants you permission to propagate or
+modify any covered work.  These actions infringe copyright if you do
+not accept this License.  Therefore, by modifying or propagating a
+covered work, you indicate your acceptance of this License to do so.
+
+  10. Automatic Licensing of Downstream Recipients.
+
+  Each time you convey a covered work, the recipient automatically
+receives a license from the original licensors, to run, modify and
+propagate that work, subject to this License.  You are not responsible
+for enforcing compliance by third parties with this License.
+
+  An "entity transaction" is a transaction transferring control of an
+organization, or substantially all assets of one, or subdividing an
+organization, or merging organizations.  If propagation of a covered
+work results from an entity transaction, each party to that
+transaction who receives a copy of the work also receives whatever
+licenses to the work the party's predecessor in interest had or could
+give under the previous paragraph, plus a right to possession of the
+Corresponding Source of the work from the predecessor in interest, if
+the predecessor has it or can get it with reasonable efforts.
+
+  You may not impose any further restrictions on the exercise of the
+rights granted or affirmed under this License.  For example, you may
+not impose a license fee, royalty, or other charge for exercise of
+rights granted under this License, and you may not initiate litigation
+(including a cross-claim or counterclaim in a lawsuit) alleging that
+any patent claim is infringed by making, using, selling, offering for
+sale, or importing the Program or any portion of it.
+
+  11. Patents.
+
+  A "contributor" is a copyright holder who authorizes use under this
+License of the Program or a work on which the Program is based.  The
+work thus licensed is called the contributor's "contributor version".
+
+  A contributor's "essential patent claims" are all patent claims
+owned or controlled by the contributor, whether already acquired or
+hereafter acquired, that would be infringed by some manner, permitted
+by this License, of making, using, or selling its contributor version,
+but do not include claims that would be infringed only as a
+consequence of further modification of the contributor version.  For
+purposes of this definition, "control" includes the right to grant
+patent sublicenses in a manner consistent with the requirements of
+this License.
+
+  Each contributor grants you a non-exclusive, worldwide, royalty-free
+patent license under the contributor's essential patent claims, to
+make, use, sell, offer for sale, import and otherwise run, modify and
+propagate the contents of its contributor version.
+
+  In the following three paragraphs, a "patent license" is any express
+agreement or commitment, however denominated, not to enforce a patent
+(such as an express permission to practice a patent or covenant not to
+sue for patent infringement).  To "grant" such a patent license to a
+party means to make such an agreement or commitment not to enforce a
+patent against the party.
+
+  If you convey a covered work, knowingly relying on a patent license,
+and the Corresponding Source of the work is not available for anyone
+to copy, free of charge and under the terms of this License, through a
+publicly available network server or other readily accessible means,
+then you must either (1) cause the Corresponding Source to be so
+available, or (2) arrange to deprive yourself of the benefit of the
+patent license for this particular work, or (3) arrange, in a manner
+consistent with the requirements of this License, to extend the patent
+license to downstream recipients.  "Knowingly relying" means you have
+actual knowledge that, but for the patent license, your conveying the
+covered work in a country, or your recipient's use of the covered work
+in a country, would infringe one or more identifiable patents in that
+country that you have reason to believe are valid.
+
+  If, pursuant to or in connection with a single transaction or
+arrangement, you convey, or propagate by procuring conveyance of, a
+covered work, and grant a patent license to some of the parties
+receiving the covered work authorizing them to use, propagate, modify
+or convey a specific copy of the covered work, then the patent license
+you grant is automatically extended to all recipients of the covered
+work and works based on it.
+
+  A patent license is "discriminatory" if it does not include within
+the scope of its coverage, prohibits the exercise of, or is
+conditioned on the non-exercise of one or more of the rights that are
+specifically granted under this License.  You may not convey a covered
+work if you are a party to an arrangement with a third party that is
+in the business of distributing software, under which you make payment
+to the third party based on the extent of your activity of conveying
+the work, and under which the third party grants, to any of the
+parties who would receive the covered work from you, a discriminatory
+patent license (a) in connection with copies of the covered work
+conveyed by you (or copies made from those copies), or (b) primarily
+for and in connection with specific products or compilations that
+contain the covered work, unless you entered into that arrangement,
+or that patent license was granted, prior to 28 March 2007.
+
+  Nothing in this License shall be construed as excluding or limiting
+any implied license or other defenses to infringement that may
+otherwise be available to you under applicable patent law.
+
+  12. No Surrender of Others' Freedom.
+
+  If conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot convey a
+covered work so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you may
+not convey it at all.  For example, if you agree to terms that obligate you
+to collect a royalty for further conveying from those to whom you convey
+the Program, the only way you could satisfy both those terms and this
+License would be to refrain entirely from conveying the Program.
+
+  13. Use with the GNU Affero General Public License.
+
+  Notwithstanding any other provision of this License, you have
+permission to link or combine any covered work with a work licensed
+under version 3 of the GNU Affero General Public License into a single
+combined work, and to convey the resulting work.  The terms of this
+License will continue to apply to the part which is the covered work,
+but the special requirements of the GNU Affero General Public License,
+section 13, concerning interaction through a network will apply to the
+combination as such.
+
+  14. Revised Versions of this License.
+
+  The Free Software Foundation may publish revised and/or new versions of
+the GNU General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+  Each version is given a distinguishing version number.  If the
+Program specifies that a certain numbered version of the GNU General
+Public License "or any later version" applies to it, you have the
+option of following the terms and conditions either of that numbered
+version or of any later version published by the Free Software
+Foundation.  If the Program does not specify a version number of the
+GNU General Public License, you may choose any version ever published
+by the Free Software Foundation.
+
+  If the Program specifies that a proxy can decide which future
+versions of the GNU General Public License can be used, that proxy's
+public statement of acceptance of a version permanently authorizes you
+to choose that version for the Program.
+
+  Later license versions may give you additional or different
+permissions.  However, no additional obligations are imposed on any
+author or copyright holder as a result of your choosing to follow a
+later version.
+
+  15. Disclaimer of Warranty.
+
+  THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
+APPLICABLE LAW.  EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
+HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
+OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
+THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
+IS WITH YOU.  SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
+ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+  16. Limitation of Liability.
+
+  IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
+THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
+GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
+USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
+DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
+PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
+EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGES.
+
+  17. Interpretation of Sections 15 and 16.
+
+  If the disclaimer of warranty and limitation of liability provided
+above cannot be given local legal effect according to their terms,
+reviewing courts shall apply local law that most closely approximates
+an absolute waiver of all civil liability in connection with the
+Program, unless a warranty or assumption of liability accompanies a
+copy of the Program in return for a fee.
+
+                     END OF TERMS AND CONDITIONS
+
+            How to Apply These Terms to Your New Programs
+
+  If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+  To do so, attach the following notices to the program.  It is safest
+to attach them to the start of each source file to most effectively
+state the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the program's name and a brief idea of what it does.>
+    Copyright (C) <year>  <name of author>
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+Also add information on how to contact you by electronic and paper mail.
+
+  If the program does terminal interaction, make it output a short
+notice like this when it starts in an interactive mode:
+
+    <program>  Copyright (C) <year>  <name of author>
+    This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+    This is free software, and you are welcome to redistribute it
+    under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License.  Of course, your program's commands
+might be different; for a GUI interface, you would use an "about box".
+
+  You should also get your employer (if you work as a programmer) or school,
+if any, to sign a "copyright disclaimer" for the program, if necessary.
+For more information on this, and how to apply and follow the GNU GPL, see
+<http://www.gnu.org/licenses/>.
+
+  The GNU General Public License does not permit incorporating your program
+into proprietary programs.  If your program is a subroutine library, you
+may consider it more useful to permit linking proprietary applications with
+the library.  If this is what you want to do, use the GNU Lesser General
+Public License instead of this License.  But first, please read
+<http://www.gnu.org/philosophy/why-not-lgpl.html>.
diff --git a/Doxyfile.in b/Doxyfile.in
new file mode 100644
index 0000000..079ad59
--- /dev/null
+++ b/Doxyfile.in
@@ -0,0 +1,1419 @@
+# Doxyfile 1.5.6
+
+# This file describes the settings to be used by the documentation system
+# doxygen (www.doxygen.org) for a project
+#
+# All text after a hash (#) is considered a comment and will be ignored
+# The format is:
+#       TAG = value [value, ...]
+# For lists items can also be appended using:
+#       TAG += value [value, ...]
+# Values that contain spaces should be placed between quotes (" ")
+
+#---------------------------------------------------------------------------
+# Project related configuration options
+#---------------------------------------------------------------------------
+
+# This tag specifies the encoding used for all characters in the config file 
+# that follow. The default is UTF-8 which is also the encoding used for all 
+# text before the first occurrence of this tag. Doxygen uses libiconv (or the 
+# iconv built into libc) for the transcoding. See 
+# http://www.gnu.org/software/libiconv for the list of possible encodings.
+
+DOXYFILE_ENCODING      = UTF-8
+
+# The PROJECT_NAME tag is a single word (or a sequence of words surrounded 
+# by quotes) that should identify the project.
+
+PROJECT_NAME           = ${CPACK_PACKAGE_NAME}
+
+# The PROJECT_NUMBER tag can be used to enter a project or revision number. 
+# This could be handy for archiving the generated documentation or 
+# if some version control system is used.
+
+PROJECT_NUMBER         = ${VERSION}
+
+# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) 
+# base path where the generated documentation will be put. 
+# If a relative path is entered, it will be relative to the location 
+# where doxygen was started. If left blank the current directory will be used.
+
+OUTPUT_DIRECTORY       = api-doc
+
+# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create 
+# 4096 sub-directories (in 2 levels) under the output directory of each output 
+# format and will distribute the generated files over these directories. 
+# Enabling this option can be useful when feeding doxygen a huge amount of 
+# source files, where putting all generated files in the same directory would 
+# otherwise cause performance problems for the file system.
+
+CREATE_SUBDIRS         = NO
+
+# The OUTPUT_LANGUAGE tag is used to specify the language in which all 
+# documentation generated by doxygen is written. Doxygen will use this 
+# information to generate all constant output in the proper language. 
+# The default language is English, other supported languages are: 
+# Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional, 
+# Croatian, Czech, Danish, Dutch, Farsi, Finnish, French, German, Greek, 
+# Hungarian, Italian, Japanese, Japanese-en (Japanese with English messages), 
+# Korean, Korean-en, Lithuanian, Norwegian, Macedonian, Persian, Polish, 
+# Portuguese, Romanian, Russian, Serbian, Slovak, Slovene, Spanish, Swedish, 
+# and Ukrainian.
+
+OUTPUT_LANGUAGE        = English
+
+# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will 
+# include brief member descriptions after the members that are listed in 
+# the file and class documentation (similar to JavaDoc). 
+# Set to NO to disable this.
+
+BRIEF_MEMBER_DESC      = YES
+
+# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend 
+# the brief description of a member or function before the detailed description. 
+# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the 
+# brief descriptions will be completely suppressed.
+
+REPEAT_BRIEF           = YES
+
+# This tag implements a quasi-intelligent brief description abbreviator 
+# that is used to form the text in various listings. Each string 
+# in this list, if found as the leading text of the brief description, will be 
+# stripped from the text and the result after processing the whole list, is 
+# used as the annotated text. Otherwise, the brief description is used as-is. 
+# If left blank, the following values are used ("$name" is automatically 
+# replaced with the name of the entity): "The $name class" "The $name widget" 
+# "The $name file" "is" "provides" "specifies" "contains" 
+# "represents" "a" "an" "the"
+
+ABBREVIATE_BRIEF       = 
+
+# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then 
+# Doxygen will generate a detailed section even if there is only a brief 
+# description.
+
+ALWAYS_DETAILED_SEC    = NO
+
+# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all 
+# inherited members of a class in the documentation of that class as if those 
+# members were ordinary class members. Constructors, destructors and assignment 
+# operators of the base classes will not be shown.
+
+INLINE_INHERITED_MEMB  = NO
+
+# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full 
+# path before files name in the file list and in the header files. If set 
+# to NO the shortest path that makes the file name unique will be used.
+
+FULL_PATH_NAMES        = YES
+
+# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag 
+# can be used to strip a user-defined part of the path. Stripping is 
+# only done if one of the specified strings matches the left-hand part of 
+# the path. The tag can be used to show relative paths in the file list. 
+# If left blank the directory from which doxygen is run is used as the 
+# path to strip.
+
+STRIP_FROM_PATH        = ${CMAKE_CURRENT_SOURCE_DIR}
+
+# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of 
+# the path mentioned in the documentation of a class, which tells 
+# the reader which header file to include in order to use a class. 
+# If left blank only the name of the header file containing the class 
+# definition is used. Otherwise one should specify the include paths that 
+# are normally passed to the compiler using the -I flag.
+
+STRIP_FROM_INC_PATH    = 
+
+# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter 
+# (but less readable) file names. This can be useful is your file systems 
+# doesn't support long names like on DOS, Mac, or CD-ROM.
+
+SHORT_NAMES            = NO
+
+# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen 
+# will interpret the first line (until the first dot) of a JavaDoc-style 
+# comment as the brief description. If set to NO, the JavaDoc 
+# comments will behave just like regular Qt-style comments 
+# (thus requiring an explicit @brief command for a brief description.)
+
+JAVADOC_AUTOBRIEF      = NO
+
+# If the QT_AUTOBRIEF tag is set to YES then Doxygen will 
+# interpret the first line (until the first dot) of a Qt-style 
+# comment as the brief description. If set to NO, the comments 
+# will behave just like regular Qt-style comments (thus requiring 
+# an explicit \brief command for a brief description.)
+
+QT_AUTOBRIEF           = NO
+
+# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen 
+# treat a multi-line C++ special comment block (i.e. a block of //! or /// 
+# comments) as a brief description. This used to be the default behaviour. 
+# The new default is to treat a multi-line C++ comment block as a detailed 
+# description. Set this tag to YES if you prefer the old behaviour instead.
+
+MULTILINE_CPP_IS_BRIEF = NO
+
+# If the DETAILS_AT_TOP tag is set to YES then Doxygen 
+# will output the detailed description near the top, like JavaDoc.
+# If set to NO, the detailed description appears after the member 
+# documentation.
+
+# DEPRECATED
+#DETAILS_AT_TOP         = NO
+# DEPRECATED
+
+# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented 
+# member inherits the documentation from any documented member that it 
+# re-implements.
+
+INHERIT_DOCS           = YES
+
+# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce 
+# a new page for each member. If set to NO, the documentation of a member will 
+# be part of the file/class/namespace that contains it.
+
+SEPARATE_MEMBER_PAGES  = NO
+
+# The TAB_SIZE tag can be used to set the number of spaces in a tab. 
+# Doxygen uses this value to replace tabs by spaces in code fragments.
+
+TAB_SIZE               = 8
+
+# This tag can be used to specify a number of aliases that acts 
+# as commands in the documentation. An alias has the form "name=value". 
+# For example adding "sideeffect=\par Side Effects:\n" will allow you to 
+# put the command \sideeffect (or @sideeffect) in the documentation, which 
+# will result in a user-defined paragraph with heading "Side Effects:". 
+# You can put \n's in the value part of an alias to insert newlines.
+
+ALIASES                = 
+
+# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C 
+# sources only. Doxygen will then generate output that is more tailored for C. 
+# For instance, some of the names that are used will be different. The list 
+# of all members will be omitted, etc.
+
+OPTIMIZE_OUTPUT_FOR_C  = NO
+
+# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java 
+# sources only. Doxygen will then generate output that is more tailored for 
+# Java. For instance, namespaces will be presented as packages, qualified 
+# scopes will look different, etc.
+
+OPTIMIZE_OUTPUT_JAVA   = NO
+
+# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran 
+# sources only. Doxygen will then generate output that is more tailored for 
+# Fortran.
+
+OPTIMIZE_FOR_FORTRAN   = NO
+
+# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL 
+# sources. Doxygen will then generate output that is tailored for 
+# VHDL.
+
+OPTIMIZE_OUTPUT_VHDL   = NO
+
+# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want 
+# to include (a tag file for) the STL sources as input, then you should 
+# set this tag to YES in order to let doxygen match functions declarations and 
+# definitions whose arguments contain STL classes (e.g. func(std::string); v.s. 
+# func(std::string) {}). This also make the inheritance and collaboration 
+# diagrams that involve STL classes more complete and accurate.
+
+BUILTIN_STL_SUPPORT    = NO
+
+# If you use Microsoft's C++/CLI language, you should set this option to YES to
+# enable parsing support.
+
+CPP_CLI_SUPPORT        = NO
+
+# Set the SIP_SUPPORT tag to YES if your project consists of sip sources only. 
+# Doxygen will parse them like normal C++ but will assume all classes use public 
+# instead of private inheritance when no explicit protection keyword is present.
+
+SIP_SUPPORT            = NO
+
+# For Microsoft's IDL there are propget and propput attributes to indicate getter 
+# and setter methods for a property. Setting this option to YES (the default) 
+# will make doxygen to replace the get and set methods by a property in the 
+# documentation. This will only work if the methods are indeed getting or 
+# setting a simple type. If this is not the case, or you want to show the 
+# methods anyway, you should set this option to NO.
+
+IDL_PROPERTY_SUPPORT   = YES
+
+# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC 
+# tag is set to YES, then doxygen will reuse the documentation of the first 
+# member in the group (if any) for the other members of the group. By default 
+# all members of a group must be documented explicitly.
+
+DISTRIBUTE_GROUP_DOC   = NO
+
+# Set the SUBGROUPING tag to YES (the default) to allow class member groups of 
+# the same type (for instance a group of public functions) to be put as a 
+# subgroup of that type (e.g. under the Public Functions section). Set it to 
+# NO to prevent subgrouping. Alternatively, this can be done per class using 
+# the \nosubgrouping command.
+
+SUBGROUPING            = YES
+
+# When TYPEDEF_HIDES_STRUCT is enabled, a typedef of a struct, union, or enum 
+# is documented as struct, union, or enum with the name of the typedef. So 
+# typedef struct TypeS {} TypeT, will appear in the documentation as a struct 
+# with name TypeT. When disabled the typedef will appear as a member of a file, 
+# namespace, or class. And the struct will be named TypeS. This can typically 
+# be useful for C code in case the coding convention dictates that all compound 
+# types are typedef'ed and only the typedef is referenced, never the tag name.
+
+TYPEDEF_HIDES_STRUCT   = NO
+
+#---------------------------------------------------------------------------
+# Build related configuration options
+#---------------------------------------------------------------------------
+
+# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in 
+# documentation are documented, even if no documentation was available. 
+# Private class members and static file members will be hidden unless 
+# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES
+
+EXTRACT_ALL            = YES
+
+# If the EXTRACT_PRIVATE tag is set to YES all private members of a class 
+# will be included in the documentation.
+
+EXTRACT_PRIVATE        = NO
+
+# If the EXTRACT_STATIC tag is set to YES all static members of a file 
+# will be included in the documentation.
+
+EXTRACT_STATIC         = NO
+
+# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) 
+# defined locally in source files will be included in the documentation. 
+# If set to NO only classes defined in header files are included.
+
+EXTRACT_LOCAL_CLASSES  = YES
+
+# This flag is only useful for Objective-C code. When set to YES local 
+# methods, which are defined in the implementation section but not in 
+# the interface are included in the documentation. 
+# If set to NO (the default) only methods in the interface are included.
+
+EXTRACT_LOCAL_METHODS  = NO
+
+# If this flag is set to YES, the members of anonymous namespaces will be 
+# extracted and appear in the documentation as a namespace called 
+# 'anonymous_namespace{file}', where file will be replaced with the base 
+# name of the file that contains the anonymous namespace. By default 
+# anonymous namespace are hidden.
+
+EXTRACT_ANON_NSPACES   = NO
+
+# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all 
+# undocumented members of documented classes, files or namespaces. 
+# If set to NO (the default) these members will be included in the 
+# various overviews, but no documentation section is generated. 
+# This option has no effect if EXTRACT_ALL is enabled.
+
+HIDE_UNDOC_MEMBERS     = NO
+
+# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all 
+# undocumented classes that are normally visible in the class hierarchy. 
+# If set to NO (the default) these classes will be included in the various 
+# overviews. This option has no effect if EXTRACT_ALL is enabled.
+
+HIDE_UNDOC_CLASSES     = NO
+
+# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all 
+# friend (class|struct|union) declarations. 
+# If set to NO (the default) these declarations will be included in the 
+# documentation.
+
+HIDE_FRIEND_COMPOUNDS  = NO
+
+# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any 
+# documentation blocks found inside the body of a function. 
+# If set to NO (the default) these blocks will be appended to the 
+# function's detailed documentation block.
+
+HIDE_IN_BODY_DOCS      = NO
+
+# The INTERNAL_DOCS tag determines if documentation 
+# that is typed after a \internal command is included. If the tag is set 
+# to NO (the default) then the documentation will be excluded. 
+# Set it to YES to include the internal documentation.
+
+INTERNAL_DOCS          = NO
+
+# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate 
+# file names in lower-case letters. If set to YES upper-case letters are also 
+# allowed. This is useful if you have classes or files whose names only differ 
+# in case and if your file system supports case sensitive file names. Windows 
+# and Mac users are advised to set this option to NO.
+
+CASE_SENSE_NAMES       = YES
+
+# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen 
+# will show members with their full class and namespace scopes in the 
+# documentation. If set to YES the scope will be hidden.
+
+HIDE_SCOPE_NAMES       = NO
+
+# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen 
+# will put a list of the files that are included by a file in the documentation 
+# of that file.
+
+SHOW_INCLUDE_FILES     = YES
+
+# If the INLINE_INFO tag is set to YES (the default) then a tag [inline] 
+# is inserted in the documentation for inline members.
+
+INLINE_INFO            = YES
+
+# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen 
+# will sort the (detailed) documentation of file and class members 
+# alphabetically by member name. If set to NO the members will appear in 
+# declaration order.
+
+SORT_MEMBER_DOCS       = YES
+
+# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the 
+# brief documentation of file, namespace and class members alphabetically 
+# by member name. If set to NO (the default) the members will appear in 
+# declaration order.
+
+SORT_BRIEF_DOCS        = NO
+
+# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the 
+# hierarchy of group names into alphabetical order. If set to NO (the default) 
+# the group names will appear in their defined order.
+
+SORT_GROUP_NAMES       = NO
+
+# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be 
+# sorted by fully-qualified names, including namespaces. If set to 
+# NO (the default), the class list will be sorted only by class name, 
+# not including the namespace part. 
+# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES.
+# Note: This option applies only to the class list, not to the 
+# alphabetical list.
+
+SORT_BY_SCOPE_NAME     = NO
+
+# The GENERATE_TODOLIST tag can be used to enable (YES) or 
+# disable (NO) the todo list. This list is created by putting \todo 
+# commands in the documentation.
+
+GENERATE_TODOLIST      = YES
+
+# The GENERATE_TESTLIST tag can be used to enable (YES) or 
+# disable (NO) the test list. This list is created by putting \test 
+# commands in the documentation.
+
+GENERATE_TESTLIST      = YES
+
+# The GENERATE_BUGLIST tag can be used to enable (YES) or 
+# disable (NO) the bug list. This list is created by putting \bug 
+# commands in the documentation.
+
+GENERATE_BUGLIST       = YES
+
+# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or 
+# disable (NO) the deprecated list. This list is created by putting 
+# \deprecated commands in the documentation.
+
+GENERATE_DEPRECATEDLIST= YES
+
+# The ENABLED_SECTIONS tag can be used to enable conditional 
+# documentation sections, marked by \if sectionname ... \endif.
+
+ENABLED_SECTIONS       = 
+
+# The MAX_INITIALIZER_LINES tag determines the maximum number of lines 
+# the initial value of a variable or define consists of for it to appear in 
+# the documentation. If the initializer consists of more lines than specified 
+# here it will be hidden. Use a value of 0 to hide initializers completely. 
+# The appearance of the initializer of individual variables and defines in the 
+# documentation can be controlled using \showinitializer or \hideinitializer 
+# command in the documentation regardless of this setting.
+
+MAX_INITIALIZER_LINES  = 30
+
+# Set the SHOW_USED_FILES tag to NO to disable the list of files generated 
+# at the bottom of the documentation of classes and structs. If set to YES the 
+# list will mention the files that were used to generate the documentation.
+
+SHOW_USED_FILES        = YES
+
+# If the sources in your project are distributed over multiple directories 
+# then setting the SHOW_DIRECTORIES tag to YES will show the directory hierarchy 
+# in the documentation. The default is NO.
+
+SHOW_DIRECTORIES       = NO
+
+# Set the SHOW_FILES tag to NO to disable the generation of the Files page.
+# This will remove the Files entry from the Quick Index and from the 
+# Folder Tree View (if specified). The default is YES.
+
+SHOW_FILES             = YES
+
+# Set the SHOW_NAMESPACES tag to NO to disable the generation of the 
+# Namespaces page.  This will remove the Namespaces entry from the Quick Index
+# and from the Folder Tree View (if specified). The default is YES.
+
+SHOW_NAMESPACES        = YES
+
+# The FILE_VERSION_FILTER tag can be used to specify a program or script that 
+# doxygen should invoke to get the current version for each file (typically from 
+# the version control system). Doxygen will invoke the program by executing (via 
+# popen()) the command <command> <input-file>, where <command> is the value of 
+# the FILE_VERSION_FILTER tag, and <input-file> is the name of an input file 
+# provided by doxygen. Whatever the program writes to standard output 
+# is used as the file version. See the manual for examples.
+
+FILE_VERSION_FILTER    = 
+
+#---------------------------------------------------------------------------
+# configuration options related to warning and progress messages
+#---------------------------------------------------------------------------
+
+# The QUIET tag can be used to turn on/off the messages that are generated 
+# by doxygen. Possible values are YES and NO. If left blank NO is used.
+
+QUIET                  = NO
+
+# The WARNINGS tag can be used to turn on/off the warning messages that are 
+# generated by doxygen. Possible values are YES and NO. If left blank 
+# NO is used.
+
+WARNINGS               = YES
+
+# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings 
+# for undocumented members. If EXTRACT_ALL is set to YES then this flag will 
+# automatically be disabled.
+
+WARN_IF_UNDOCUMENTED   = YES
+
+# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for 
+# potential errors in the documentation, such as not documenting some 
+# parameters in a documented function, or documenting parameters that 
+# don't exist or using markup commands wrongly.
+
+WARN_IF_DOC_ERROR      = YES
+
+# This WARN_NO_PARAMDOC option can be abled to get warnings for 
+# functions that are documented, but have no documentation for their parameters 
+# or return value. If set to NO (the default) doxygen will only warn about 
+# wrong or incomplete parameter documentation, but not about the absence of 
+# documentation.
+
+WARN_NO_PARAMDOC       = NO
+
+# The WARN_FORMAT tag determines the format of the warning messages that 
+# doxygen can produce. The string should contain the $file, $line, and $text 
+# tags, which will be replaced by the file and line number from which the 
+# warning originated and the warning text. Optionally the format may contain 
+# $version, which will be replaced by the version of the file (if it could 
+# be obtained via FILE_VERSION_FILTER)
+
+WARN_FORMAT            = "$file:$line: $text"
+
+# The WARN_LOGFILE tag can be used to specify a file to which warning 
+# and error messages should be written. If left blank the output is written 
+# to stderr.
+
+WARN_LOGFILE           = 
+
+#---------------------------------------------------------------------------
+# configuration options related to the input files
+#---------------------------------------------------------------------------
+
+# The INPUT tag can be used to specify the files and/or directories that contain 
+# documented source files. You may enter file names like "myfile.cpp" or 
+# directories like "/usr/src/myproject". Separate the files or directories 
+# with spaces.
+
+INPUT                  = ${CMAKE_CURRENT_SOURCE_DIR}
+
+# This tag can be used to specify the character encoding of the source files 
+# that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is 
+# also the default input encoding. Doxygen uses libiconv (or the iconv built 
+# into libc) for the transcoding. See http://www.gnu.org/software/libiconv for 
+# the list of possible encodings.
+
+INPUT_ENCODING         = UTF-8
+
+# If the value of the INPUT tag contains directories, you can use the 
+# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp 
+# and *.h) to filter out the source-files in the directories. If left 
+# blank the following patterns are tested: 
+# *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx 
+# *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.py *.f90
+
+FILE_PATTERNS          = 
+
+# The RECURSIVE tag can be used to turn specify whether or not subdirectories 
+# should be searched for input files as well. Possible values are YES and NO. 
+# If left blank NO is used.
+
+RECURSIVE              = YES
+
+# The EXCLUDE tag can be used to specify files and/or directories that should 
+# excluded from the INPUT source files. This way you can easily exclude a 
+# subdirectory from a directory tree whose root is specified with the INPUT tag.
+
+EXCLUDE                = 
+
+# The EXCLUDE_SYMLINKS tag can be used select whether or not files or 
+# directories that are symbolic links (a Unix filesystem feature) are excluded 
+# from the input.
+
+EXCLUDE_SYMLINKS       = NO
+
+# If the value of the INPUT tag contains directories, you can use the 
+# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude 
+# certain files from those directories. Note that the wildcards are matched 
+# against the file with absolute path, so to exclude all test directories 
+# for example use the pattern */test/*
+
+EXCLUDE_PATTERNS       = 
+
+# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names 
+# (namespaces, classes, functions, etc.) that should be excluded from the 
+# output. The symbol name can be a fully qualified name, a word, or if the 
+# wildcard * is used, a substring. Examples: ANamespace, AClass, 
+# AClass::ANamespace, ANamespace::*Test
+
+EXCLUDE_SYMBOLS        = 
+
+# The EXAMPLE_PATH tag can be used to specify one or more files or 
+# directories that contain example code fragments that are included (see 
+# the \include command).
+
+EXAMPLE_PATH           = 
+
+# If the value of the EXAMPLE_PATH tag contains directories, you can use the 
+# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp 
+# and *.h) to filter out the source-files in the directories. If left 
+# blank all files are included.
+
+EXAMPLE_PATTERNS       = 
+
+# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be 
+# searched for input files to be used with the \include or \dontinclude 
+# commands irrespective of the value of the RECURSIVE tag. 
+# Possible values are YES and NO. If left blank NO is used.
+
+EXAMPLE_RECURSIVE      = NO
+
+# The IMAGE_PATH tag can be used to specify one or more files or 
+# directories that contain image that are included in the documentation (see 
+# the \image command).
+
+IMAGE_PATH             = 
+
+# The INPUT_FILTER tag can be used to specify a program that doxygen should 
+# invoke to filter for each input file. Doxygen will invoke the filter program 
+# by executing (via popen()) the command <filter> <input-file>, where <filter> 
+# is the value of the INPUT_FILTER tag, and <input-file> is the name of an 
+# input file. Doxygen will then use the output that the filter program writes 
+# to standard output.  If FILTER_PATTERNS is specified, this tag will be 
+# ignored.
+
+INPUT_FILTER           = 
+
+# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern 
+# basis.  Doxygen will compare the file name with each pattern and apply the 
+# filter if there is a match.  The filters are a list of the form: 
+# pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further 
+# info on how filters are used. If FILTER_PATTERNS is empty, INPUT_FILTER 
+# is applied to all files.
+
+FILTER_PATTERNS        = 
+
+# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using 
+# INPUT_FILTER) will be used to filter the input files when producing source 
+# files to browse (i.e. when SOURCE_BROWSER is set to YES).
+
+FILTER_SOURCE_FILES    = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to source browsing
+#---------------------------------------------------------------------------
+
+# If the SOURCE_BROWSER tag is set to YES then a list of source files will 
+# be generated. Documented entities will be cross-referenced with these sources. 
+# Note: To get rid of all source code in the generated output, make sure also 
+# VERBATIM_HEADERS is set to NO.
+
+SOURCE_BROWSER         = NO
+
+# Setting the INLINE_SOURCES tag to YES will include the body 
+# of functions and classes directly in the documentation.
+
+INLINE_SOURCES         = NO
+
+# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct 
+# doxygen to hide any special comment blocks from generated source code 
+# fragments. Normal C and C++ comments will always remain visible.
+
+STRIP_CODE_COMMENTS    = YES
+
+# If the REFERENCED_BY_RELATION tag is set to YES 
+# then for each documented function all documented 
+# functions referencing it will be listed.
+
+REFERENCED_BY_RELATION = NO
+
+# If the REFERENCES_RELATION tag is set to YES 
+# then for each documented function all documented entities 
+# called/used by that function will be listed.
+
+REFERENCES_RELATION    = NO
+
+# If the REFERENCES_LINK_SOURCE tag is set to YES (the default)
+# and SOURCE_BROWSER tag is set to YES, then the hyperlinks from
+# functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will
+# link to the source code.  Otherwise they will link to the documentstion.
+
+REFERENCES_LINK_SOURCE = YES
+
+# If the USE_HTAGS tag is set to YES then the references to source code 
+# will point to the HTML generated by the htags(1) tool instead of doxygen 
+# built-in source browser. The htags tool is part of GNU's global source 
+# tagging system (see http://www.gnu.org/software/global/global.html). You 
+# will need version 4.8.6 or higher.
+
+USE_HTAGS              = NO
+
+# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen 
+# will generate a verbatim copy of the header file for each class for 
+# which an include is specified. Set to NO to disable this.
+
+VERBATIM_HEADERS       = YES
+
+#---------------------------------------------------------------------------
+# configuration options related to the alphabetical class index
+#---------------------------------------------------------------------------
+
+# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index 
+# of all compounds will be generated. Enable this if the project 
+# contains a lot of classes, structs, unions or interfaces.
+
+ALPHABETICAL_INDEX     = NO
+
+# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then 
+# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns 
+# in which this list will be split (can be a number in the range [1..20])
+
+COLS_IN_ALPHA_INDEX    = 5
+
+# In case all classes in a project start with a common prefix, all 
+# classes will be put under the same header in the alphabetical index. 
+# The IGNORE_PREFIX tag can be used to specify one or more prefixes that 
+# should be ignored while generating the index headers.
+
+IGNORE_PREFIX          = 
+
+#---------------------------------------------------------------------------
+# configuration options related to the HTML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_HTML tag is set to YES (the default) Doxygen will 
+# generate HTML output.
+
+GENERATE_HTML          = YES
+
+# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. 
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be 
+# put in front of it. If left blank `html' will be used as the default path.
+
+HTML_OUTPUT            = html
+
+# The HTML_FILE_EXTENSION tag can be used to specify the file extension for 
+# each generated HTML page (for example: .htm,.php,.asp). If it is left blank 
+# doxygen will generate files with .html extension.
+
+HTML_FILE_EXTENSION    = .html
+
+# The HTML_HEADER tag can be used to specify a personal HTML header for 
+# each generated HTML page. If it is left blank doxygen will generate a 
+# standard header.
+
+HTML_HEADER            = 
+
+# The HTML_FOOTER tag can be used to specify a personal HTML footer for 
+# each generated HTML page. If it is left blank doxygen will generate a 
+# standard footer.
+
+HTML_FOOTER            = 
+
+# The HTML_STYLESHEET tag can be used to specify a user-defined cascading 
+# style sheet that is used by each HTML page. It can be used to 
+# fine-tune the look of the HTML output. If the tag is left blank doxygen 
+# will generate a default style sheet. Note that doxygen will try to copy 
+# the style sheet file to the HTML output directory, so don't put your own 
+# stylesheet in the HTML output directory as well, or it will be erased!
+
+HTML_STYLESHEET        = 
+
+# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes, 
+# files or namespaces will be aligned in HTML using tables. If set to 
+# NO a bullet list will be used.
+
+HTML_ALIGN_MEMBERS     = YES
+
+# If the GENERATE_HTMLHELP tag is set to YES, additional index files 
+# will be generated that can be used as input for tools like the 
+# Microsoft HTML help workshop to generate a compiled HTML help file (.chm) 
+# of the generated HTML documentation.
+
+GENERATE_HTMLHELP      = NO
+
+# If the GENERATE_DOCSET tag is set to YES, additional index files 
+# will be generated that can be used as input for Apple's Xcode 3 
+# integrated development environment, introduced with OSX 10.5 (Leopard). 
+# To create a documentation set, doxygen will generate a Makefile in the 
+# HTML output directory. Running make will produce the docset in that 
+# directory and running "make install" will install the docset in 
+# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find 
+# it at startup.
+
+GENERATE_DOCSET        = NO
+
+# When GENERATE_DOCSET tag is set to YES, this tag determines the name of the 
+# feed. A documentation feed provides an umbrella under which multiple 
+# documentation sets from a single provider (such as a company or product suite) 
+# can be grouped.
+
+DOCSET_FEEDNAME        = "Doxygen generated docs"
+
+# When GENERATE_DOCSET tag is set to YES, this tag specifies a string that 
+# should uniquely identify the documentation set bundle. This should be a 
+# reverse domain-name style string, e.g. com.mycompany.MyDocSet. Doxygen 
+# will append .docset to the name.
+
+DOCSET_BUNDLE_ID       = org.doxygen.Project
+
+# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML 
+# documentation will contain sections that can be hidden and shown after the 
+# page has loaded. For this to work a browser that supports 
+# JavaScript and DHTML is required (for instance Mozilla 1.0+, Firefox 
+# Netscape 6.0+, Internet explorer 5.0+, Konqueror, or Safari).
+
+HTML_DYNAMIC_SECTIONS  = NO
+
+# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can 
+# be used to specify the file name of the resulting .chm file. You 
+# can add a path in front of the file if the result should not be 
+# written to the html output directory.
+
+CHM_FILE               = 
+
+# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can 
+# be used to specify the location (absolute path including file name) of 
+# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run 
+# the HTML help compiler on the generated index.hhp.
+
+HHC_LOCATION           = 
+
+# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag 
+# controls if a separate .chi index file is generated (YES) or that 
+# it should be included in the master .chm file (NO).
+
+GENERATE_CHI           = NO
+
+# If the GENERATE_HTMLHELP tag is set to YES, the CHM_INDEX_ENCODING
+# is used to encode HtmlHelp index (hhk), content (hhc) and project file
+# content.
+
+CHM_INDEX_ENCODING     = 
+
+# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag 
+# controls whether a binary table of contents is generated (YES) or a 
+# normal table of contents (NO) in the .chm file.
+
+BINARY_TOC             = NO
+
+# The TOC_EXPAND flag can be set to YES to add extra items for group members 
+# to the contents of the HTML help documentation and to the tree view.
+
+TOC_EXPAND             = NO
+
+# The DISABLE_INDEX tag can be used to turn on/off the condensed index at 
+# top of each HTML page. The value NO (the default) enables the index and 
+# the value YES disables it.
+
+DISABLE_INDEX          = NO
+
+# This tag can be used to set the number of enum values (range [1..20]) 
+# that doxygen will group on one line in the generated HTML documentation.
+
+ENUM_VALUES_PER_LINE   = 4
+
+# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index
+# structure should be generated to display hierarchical information.
+# If the tag value is set to FRAME, a side panel will be generated
+# containing a tree-like index structure (just like the one that 
+# is generated for HTML Help). For this to work a browser that supports 
+# JavaScript, DHTML, CSS and frames is required (for instance Mozilla 1.0+, 
+# Netscape 6.0+, Internet explorer 5.0+, or Konqueror). Windows users are 
+# probably better off using the HTML help feature. Other possible values 
+# for this tag are: HIERARCHIES, which will generate the Groups, Directories,
+# and Class Hiererachy pages using a tree view instead of an ordered list;
+# ALL, which combines the behavior of FRAME and HIERARCHIES; and NONE, which
+# disables this behavior completely. For backwards compatibility with previous
+# releases of Doxygen, the values YES and NO are equivalent to FRAME and NONE
+# respectively.
+
+GENERATE_TREEVIEW      = NONE
+
+# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be 
+# used to set the initial width (in pixels) of the frame in which the tree 
+# is shown.
+
+TREEVIEW_WIDTH         = 250
+
+# Use this tag to change the font size of Latex formulas included 
+# as images in the HTML documentation. The default is 10. Note that 
+# when you change the font size after a successful doxygen run you need 
+# to manually remove any form_*.png images from the HTML output directory 
+# to force them to be regenerated.
+
+FORMULA_FONTSIZE       = 10
+
+#---------------------------------------------------------------------------
+# configuration options related to the LaTeX output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will 
+# generate Latex output.
+
+GENERATE_LATEX         = YES
+
+# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. 
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be 
+# put in front of it. If left blank `latex' will be used as the default path.
+
+LATEX_OUTPUT           = latex
+
+# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be 
+# invoked. If left blank `latex' will be used as the default command name.
+
+LATEX_CMD_NAME         = latex
+
+# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to 
+# generate index for LaTeX. If left blank `makeindex' will be used as the 
+# default command name.
+
+MAKEINDEX_CMD_NAME     = makeindex
+
+# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact 
+# LaTeX documents. This may be useful for small projects and may help to 
+# save some trees in general.
+
+COMPACT_LATEX          = NO
+
+# The PAPER_TYPE tag can be used to set the paper type that is used 
+# by the printer. Possible values are: a4, a4wide, letter, legal and 
+# executive. If left blank a4wide will be used.
+
+PAPER_TYPE             = a4wide
+
+# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX 
+# packages that should be included in the LaTeX output.
+
+EXTRA_PACKAGES         = 
+
+# The LATEX_HEADER tag can be used to specify a personal LaTeX header for 
+# the generated latex document. The header should contain everything until 
+# the first chapter. If it is left blank doxygen will generate a 
+# standard header. Notice: only use this tag if you know what you are doing!
+
+LATEX_HEADER           = 
+
+# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated 
+# is prepared for conversion to pdf (using ps2pdf). The pdf file will 
+# contain links (just like the HTML output) instead of page references 
+# This makes the output suitable for online browsing using a pdf viewer.
+
+PDF_HYPERLINKS         = YES
+
+# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of 
+# plain latex in the generated Makefile. Set this option to YES to get a 
+# higher quality PDF documentation.
+
+USE_PDFLATEX           = YES
+
+# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode. 
+# command to the generated LaTeX files. This will instruct LaTeX to keep 
+# running if errors occur, instead of asking the user for help. 
+# This option is also used when generating formulas in HTML.
+
+LATEX_BATCHMODE        = NO
+
+# If LATEX_HIDE_INDICES is set to YES then doxygen will not 
+# include the index chapters (such as File Index, Compound Index, etc.) 
+# in the output.
+
+LATEX_HIDE_INDICES     = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the RTF output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output 
+# The RTF output is optimized for Word 97 and may not look very pretty with 
+# other RTF readers or editors.
+
+GENERATE_RTF           = NO
+
+# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. 
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be 
+# put in front of it. If left blank `rtf' will be used as the default path.
+
+RTF_OUTPUT             = rtf
+
+# If the COMPACT_RTF tag is set to YES Doxygen generates more compact 
+# RTF documents. This may be useful for small projects and may help to 
+# save some trees in general.
+
+COMPACT_RTF            = NO
+
+# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated 
+# will contain hyperlink fields. The RTF file will 
+# contain links (just like the HTML output) instead of page references. 
+# This makes the output suitable for online browsing using WORD or other 
+# programs which support those fields. 
+# Note: wordpad (write) and others do not support links.
+
+RTF_HYPERLINKS         = NO
+
+# Load stylesheet definitions from file. Syntax is similar to doxygen's 
+# config file, i.e. a series of assignments. You only have to provide 
+# replacements, missing definitions are set to their default value.
+
+RTF_STYLESHEET_FILE    = 
+
+# Set optional variables used in the generation of an rtf document. 
+# Syntax is similar to doxygen's config file.
+
+RTF_EXTENSIONS_FILE    = 
+
+#---------------------------------------------------------------------------
+# configuration options related to the man page output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_MAN tag is set to YES (the default) Doxygen will 
+# generate man pages
+
+GENERATE_MAN           = NO
+
+# The MAN_OUTPUT tag is used to specify where the man pages will be put. 
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be 
+# put in front of it. If left blank `man' will be used as the default path.
+
+MAN_OUTPUT             = man
+
+# The MAN_EXTENSION tag determines the extension that is added to 
+# the generated man pages (default is the subroutine's section .3)
+
+MAN_EXTENSION          = .3
+
+# If the MAN_LINKS tag is set to YES and Doxygen generates man output, 
+# then it will generate one additional man file for each entity 
+# documented in the real man page(s). These additional files 
+# only source the real man page, but without them the man command 
+# would be unable to find the correct page. The default is NO.
+
+MAN_LINKS              = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the XML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_XML tag is set to YES Doxygen will 
+# generate an XML file that captures the structure of 
+# the code including all documentation.
+
+GENERATE_XML           = NO
+
+# The XML_OUTPUT tag is used to specify where the XML pages will be put. 
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be 
+# put in front of it. If left blank `xml' will be used as the default path.
+
+XML_OUTPUT             = xml
+
+# The XML_SCHEMA tag can be used to specify an XML schema, 
+# which can be used by a validating XML parser to check the 
+# syntax of the XML files.
+
+XML_SCHEMA             = 
+
+# The XML_DTD tag can be used to specify an XML DTD, 
+# which can be used by a validating XML parser to check the 
+# syntax of the XML files.
+
+XML_DTD                = 
+
+# If the XML_PROGRAMLISTING tag is set to YES Doxygen will 
+# dump the program listings (including syntax highlighting 
+# and cross-referencing information) to the XML output. Note that 
+# enabling this will significantly increase the size of the XML output.
+
+XML_PROGRAMLISTING     = YES
+
+#---------------------------------------------------------------------------
+# configuration options for the AutoGen Definitions output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will 
+# generate an AutoGen Definitions (see autogen.sf.net) file 
+# that captures the structure of the code including all 
+# documentation. Note that this feature is still experimental 
+# and incomplete at the moment.
+
+GENERATE_AUTOGEN_DEF   = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the Perl module output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_PERLMOD tag is set to YES Doxygen will 
+# generate a Perl module file that captures the structure of 
+# the code including all documentation. Note that this 
+# feature is still experimental and incomplete at the 
+# moment.
+
+GENERATE_PERLMOD       = NO
+
+# If the PERLMOD_LATEX tag is set to YES Doxygen will generate 
+# the necessary Makefile rules, Perl scripts and LaTeX code to be able 
+# to generate PDF and DVI output from the Perl module output.
+
+PERLMOD_LATEX          = NO
+
+# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be 
+# nicely formatted so it can be parsed by a human reader.  This is useful 
+# if you want to understand what is going on.  On the other hand, if this 
+# tag is set to NO the size of the Perl module output will be much smaller 
+# and Perl will parse it just the same.
+
+PERLMOD_PRETTY         = YES
+
+# The names of the make variables in the generated doxyrules.make file 
+# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. 
+# This is useful so different doxyrules.make files included by the same 
+# Makefile don't overwrite each other's variables.
+
+PERLMOD_MAKEVAR_PREFIX = 
+
+#---------------------------------------------------------------------------
+# Configuration options related to the preprocessor   
+#---------------------------------------------------------------------------
+
+# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will 
+# evaluate all C-preprocessor directives found in the sources and include 
+# files.
+
+ENABLE_PREPROCESSING   = YES
+
+# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro 
+# names in the source code. If set to NO (the default) only conditional 
+# compilation will be performed. Macro expansion can be done in a controlled 
+# way by setting EXPAND_ONLY_PREDEF to YES.
+
+MACRO_EXPANSION        = NO
+
+# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES 
+# then the macro expansion is limited to the macros specified with the 
+# PREDEFINED and EXPAND_AS_DEFINED tags.
+
+EXPAND_ONLY_PREDEF     = NO
+
+# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files 
+# in the INCLUDE_PATH (see below) will be search if a #include is found.
+
+SEARCH_INCLUDES        = YES
+
+# The INCLUDE_PATH tag can be used to specify one or more directories that 
+# contain include files that are not input files but should be processed by 
+# the preprocessor.
+
+INCLUDE_PATH           = 
+
+# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard 
+# patterns (like *.h and *.hpp) to filter out the header-files in the 
+# directories. If left blank, the patterns specified with FILE_PATTERNS will 
+# be used.
+
+INCLUDE_FILE_PATTERNS  = 
+
+# The PREDEFINED tag can be used to specify one or more macro names that 
+# are defined before the preprocessor is started (similar to the -D option of 
+# gcc). The argument of the tag is a list of macros of the form: name 
+# or name=definition (no spaces). If the definition and the = are 
+# omitted =1 is assumed. To prevent a macro definition from being 
+# undefined via #undef or recursively expanded use the := operator 
+# instead of the = operator.
+
+PREDEFINED             = 
+
+# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then 
+# this tag can be used to specify a list of macro names that should be expanded. 
+# The macro definition that is found in the sources will be used. 
+# Use the PREDEFINED tag if you want to use a different macro definition.
+
+EXPAND_AS_DEFINED      = 
+
+# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then 
+# doxygen's preprocessor will remove all function-like macros that are alone 
+# on a line, have an all uppercase name, and do not end with a semicolon. Such 
+# function macros are typically used for boiler-plate code, and will confuse 
+# the parser if not removed.
+
+SKIP_FUNCTION_MACROS   = YES
+
+#---------------------------------------------------------------------------
+# Configuration::additions related to external references   
+#---------------------------------------------------------------------------
+
+# The TAGFILES option can be used to specify one or more tagfiles. 
+# Optionally an initial location of the external documentation 
+# can be added for each tagfile. The format of a tag file without 
+# this location is as follows: 
+#   TAGFILES = file1 file2 ... 
+# Adding location for the tag files is done as follows: 
+#   TAGFILES = file1=loc1 "file2 = loc2" ... 
+# where "loc1" and "loc2" can be relative or absolute paths or 
+# URLs. If a location is present for each tag, the installdox tool 
+# does not have to be run to correct the links.
+# Note that each tag file must have a unique name
+# (where the name does NOT include the path)
+# If a tag file is not located in the directory in which doxygen 
+# is run, you must also specify the path to the tagfile here.
+
+TAGFILES               = 
+
+# When a file name is specified after GENERATE_TAGFILE, doxygen will create 
+# a tag file that is based on the input files it reads.
+
+GENERATE_TAGFILE       = 
+
+# If the ALLEXTERNALS tag is set to YES all external classes will be listed 
+# in the class index. If set to NO only the inherited external classes 
+# will be listed.
+
+ALLEXTERNALS           = NO
+
+# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed 
+# in the modules index. If set to NO, only the current project's groups will 
+# be listed.
+
+EXTERNAL_GROUPS        = YES
+
+# The PERL_PATH should be the absolute path and name of the perl script 
+# interpreter (i.e. the result of `which perl').
+
+PERL_PATH              = /usr/bin/perl
+
+#---------------------------------------------------------------------------
+# Configuration options related to the dot tool   
+#---------------------------------------------------------------------------
+
+# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will 
+# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base 
+# or super classes. Setting the tag to NO turns the diagrams off. Note that 
+# this option is superseded by the HAVE_DOT option below. This is only a 
+# fallback. It is recommended to install and use dot, since it yields more 
+# powerful graphs.
+
+CLASS_DIAGRAMS         = YES
+
+# You can define message sequence charts within doxygen comments using the \msc 
+# command. Doxygen will then run the mscgen tool (see 
+# http://www.mcternan.me.uk/mscgen/) to produce the chart and insert it in the 
+# documentation. The MSCGEN_PATH tag allows you to specify the directory where 
+# the mscgen tool resides. If left empty the tool is assumed to be found in the 
+# default search path.
+
+MSCGEN_PATH            = 
+
+# If set to YES, the inheritance and collaboration graphs will hide 
+# inheritance and usage relations if the target is undocumented 
+# or is not a class.
+
+HIDE_UNDOC_RELATIONS   = YES
+
+# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is 
+# available from the path. This tool is part of Graphviz, a graph visualization 
+# toolkit from AT&T and Lucent Bell Labs. The other options in this section 
+# have no effect if this option is set to NO (the default)
+
+HAVE_DOT               = NO
+
+# By default doxygen will write a font called FreeSans.ttf to the output 
+# directory and reference it in all dot files that doxygen generates. This 
+# font does not include all possible unicode characters however, so when you need 
+# these (or just want a differently looking font) you can specify the font name 
+# using DOT_FONTNAME. You need need to make sure dot is able to find the font, 
+# which can be done by putting it in a standard location or by setting the 
+# DOTFONTPATH environment variable or by setting DOT_FONTPATH to the directory 
+# containing the font.
+
+DOT_FONTNAME           = FreeSans
+
+# By default doxygen will tell dot to use the output directory to look for the 
+# FreeSans.ttf font (which doxygen will put there itself). If you specify a 
+# different font using DOT_FONTNAME you can set the path where dot 
+# can find it using this tag.
+
+DOT_FONTPATH           = 
+
+# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen 
+# will generate a graph for each documented class showing the direct and 
+# indirect inheritance relations. Setting this tag to YES will force the 
+# the CLASS_DIAGRAMS tag to NO.
+
+CLASS_GRAPH            = YES
+
+# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen 
+# will generate a graph for each documented class showing the direct and 
+# indirect implementation dependencies (inheritance, containment, and 
+# class references variables) of the class with other documented classes.
+
+COLLABORATION_GRAPH    = YES
+
+# If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen 
+# will generate a graph for groups, showing the direct groups dependencies
+
+GROUP_GRAPHS           = YES
+
+# If the UML_LOOK tag is set to YES doxygen will generate inheritance and 
+# collaboration diagrams in a style similar to the OMG's Unified Modeling 
+# Language.
+
+UML_LOOK               = NO
+
+# If set to YES, the inheritance and collaboration graphs will show the 
+# relations between templates and their instances.
+
+TEMPLATE_RELATIONS     = NO
+
+# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT 
+# tags are set to YES then doxygen will generate a graph for each documented 
+# file showing the direct and indirect include dependencies of the file with 
+# other documented files.
+
+INCLUDE_GRAPH          = YES
+
+# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and 
+# HAVE_DOT tags are set to YES then doxygen will generate a graph for each 
+# documented header file showing the documented files that directly or 
+# indirectly include this file.
+
+INCLUDED_BY_GRAPH      = YES
+
+# If the CALL_GRAPH and HAVE_DOT options are set to YES then 
+# doxygen will generate a call dependency graph for every global function 
+# or class method. Note that enabling this option will significantly increase 
+# the time of a run. So in most cases it will be better to enable call graphs 
+# for selected functions only using the \callgraph command.
+
+CALL_GRAPH             = NO
+
+# If the CALLER_GRAPH and HAVE_DOT tags are set to YES then 
+# doxygen will generate a caller dependency graph for every global function 
+# or class method. Note that enabling this option will significantly increase 
+# the time of a run. So in most cases it will be better to enable caller 
+# graphs for selected functions only using the \callergraph command.
+
+CALLER_GRAPH           = NO
+
+# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen 
+# will graphical hierarchy of all classes instead of a textual one.
+
+GRAPHICAL_HIERARCHY    = YES
+
+# If the DIRECTORY_GRAPH, SHOW_DIRECTORIES and HAVE_DOT tags are set to YES 
+# then doxygen will show the dependencies a directory has on other directories 
+# in a graphical way. The dependency relations are determined by the #include
+# relations between the files in the directories.
+
+DIRECTORY_GRAPH        = YES
+
+# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images 
+# generated by dot. Possible values are png, jpg, or gif
+# If left blank png will be used.
+
+DOT_IMAGE_FORMAT       = png
+
+# The tag DOT_PATH can be used to specify the path where the dot tool can be 
+# found. If left blank, it is assumed the dot tool can be found in the path.
+
+DOT_PATH               = 
+
+# The DOTFILE_DIRS tag can be used to specify one or more directories that 
+# contain dot files that are included in the documentation (see the 
+# \dotfile command).
+
+DOTFILE_DIRS           = 
+
+# The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of 
+# nodes that will be shown in the graph. If the number of nodes in a graph 
+# becomes larger than this value, doxygen will truncate the graph, which is 
+# visualized by representing a node as a red box. Note that doxygen if the 
+# number of direct children of the root node in a graph is already larger than 
+# DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note 
+# that the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH.
+
+DOT_GRAPH_MAX_NODES    = 50
+
+# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the 
+# graphs generated by dot. A depth value of 3 means that only nodes reachable 
+# from the root by following a path via at most 3 edges will be shown. Nodes 
+# that lay further from the root node will be omitted. Note that setting this 
+# option to 1 or 2 may greatly reduce the computation time needed for large 
+# code bases. Also note that the size of a graph can be further restricted by 
+# DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction.
+
+MAX_DOT_GRAPH_DEPTH    = 0
+
+# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent 
+# background. This is enabled by default, which results in a transparent 
+# background. Warning: Depending on the platform used, enabling this option 
+# may lead to badly anti-aliased labels on the edges of a graph (i.e. they 
+# become hard to read).
+
+DOT_TRANSPARENT        = YES
+
+# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output 
+# files in one run (i.e. multiple -o and -T options on the command line). This 
+# makes dot run faster, but since only newer versions of dot (>1.8.10) 
+# support this, this feature is disabled by default.
+
+DOT_MULTI_TARGETS      = NO
+
+# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will 
+# generate a legend page explaining the meaning of the various boxes and 
+# arrows in the dot generated graphs.
+
+GENERATE_LEGEND        = YES
+
+# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will 
+# remove the intermediate dot files that are used to generate 
+# the various graphs.
+
+DOT_CLEANUP            = YES
+
+#---------------------------------------------------------------------------
+# Configuration::additions related to the search engine   
+#---------------------------------------------------------------------------
+
+# The SEARCHENGINE tag specifies whether or not a search engine should be 
+# used. If set to NO the values of all tags below this one will be ignored.
+
+SEARCHENGINE           = NO
diff --git a/LibSITPLUSConfig.cmake.in b/LibSITPLUSConfig.cmake.in
new file mode 100644
index 0000000..8fe6ec1
--- /dev/null
+++ b/LibSITPLUSConfig.cmake.in
@@ -0,0 +1,123 @@
+# =============================================================================
+#  LibSITPLUS CMake configuration file
+#
+#             ** File generated automatically, do not modify **
+# =============================================================================
+# =============================================================================
+#  Defined variables:
+#
+#   - LibSITPLUS_INCLUDE_DIRS     : The LibSITPLUS include directories.
+#
+#   Library targets:
+#   - LibSITPLUS_core_LIB
+#   - LibSITPLUS_host_LIB
+#   - LibSITPLUS_widgets_base_LIB
+#   - LibSITPLUS_LIBS             : The list of libraries to links against.
+#
+#   Installation directories
+#
+#   - LibSITPLUS_LIBRUNTIMEDIR    : Dynamic libraries (.dll, .so). Not plugins
+#   - LibSITPLUS_PLUGINDIR        : Plugins (.dll, .so)
+#   - LibSITPLUS_LIBDIR           : Libraries for linking (.lib, .a)
+#   - LibSITPLUS_LOCALEDIR        : Locales
+#
+#   Version information
+#   - LibSITPLUS_VERSION          : The version of this LibSITPLUS build
+#   - LibSITPLUS_MAJOR_VERSION    : Major version part of LibSITPLUS_VERSION
+#   - LibSITPLUS_MINOR_VERSION    : Minor version part of LibSITPLUS_VERSION
+#   - LibSITPLUS_REVISION_VERSION : Revision version part of LibSITPLUS_VERSION
+# =============================================================================
+cmake_minimum_required(VERSION 2.6.3)
+cmake_policy (VERSION 2.6.3)
+
+#
+# Relative installation locations
+#
+
+# Dynamic libraries (.dll, .so). Plugins not included.
+set(LibSITPLUS_LIBRUNTIMEDIR @CMAKE_LIBRUNTIMEDIR_CONFIGCMAKE@)
+
+# Plugins (.dll, .so)
+set(LibSITPLUS_PLUGINDIR @CMAKE_PLUGINDIR_CONFIGCMAKE@)
+
+# Libraries for linking (.lib, .a)
+set(LibSITPLUS_LIBDIR @CMAKE_LIBDIR_CONFIGCMAKE@)
+
+# Locales
+set(LibSITPLUS_LOCALEDIR @CMAKE_LOCALEDIR_CONFIGCMAKE@)
+
+# Documentation
+set(LibSITPLUS_DOCDIR @CMAKE_DOCDIR_CONFIGCMAKE@)
+
+#
+# include directories
+# 
+SET(LibSITPLUS_INCLUDE_DIRS @CMAKE_INCLUDE_DIRS_CONFIGCMAKE@)
+INCLUDE_DIRECTORIES(${LibSITPLUS_INCLUDE_DIRS})
+
+#
+# Link targets
+#
+unset (LibSITPLUS_core_LIB_DEBUG CACHE)
+find_library (LibSITPLUS_core_LIB_DEBUG spcore 
+	PATHS @CMAKE_LIB_DIRS_CONFIGCMAKE@ 
+	PATH_SUFFIXES "./" Debug 
+	NO_DEFAULT_PATH)
+unset (LibSITPLUS_core_LIB_REL CACHE)
+find_library (LibSITPLUS_core_LIB_REL spcore 
+	PATHS @CMAKE_LIB_DIRS_CONFIGCMAKE@ 
+	PATH_SUFFIXES "./" Release 
+	NO_DEFAULT_PATH)
+set(LibSITPLUS_core_LIB "")
+IF (NOT ${LibSITPLUS_core_LIB_DEBUG} MATCHES ".*NOTFOUND")
+	set(LibSITPLUS_core_LIB debug ${LibSITPLUS_core_LIB_DEBUG})
+ENDIF()
+IF (NOT ${LibSITPLUS_core_LIB_REL} MATCHES ".*NOTFOUND")
+	set(LibSITPLUS_core_LIB ${LibSITPLUS_core_LIB} optimized ${LibSITPLUS_core_LIB_REL})
+ENDIF()
+
+unset (LibSITPLUS_host_LIB_DEBUG CACHE)
+find_library (LibSITPLUS_host_LIB_DEBUG sphost 
+	PATHS @CMAKE_LIB_DIRS_CONFIGCMAKE@ 
+	PATH_SUFFIXES "./" Debug 
+	NO_DEFAULT_PATH)
+unset (LibSITPLUS_host_LIB_REL CACHE)
+find_library (LibSITPLUS_host_LIB_REL sphost 
+	PATHS @CMAKE_LIB_DIRS_CONFIGCMAKE@ 
+	PATH_SUFFIXES "./" Release 
+	NO_DEFAULT_PATH) 
+set(LibSITPLUS_host_LIB "")
+IF (NOT ${LibSITPLUS_host_LIB_DEBUG} MATCHES ".*NOTFOUND")
+	set(LibSITPLUS_host_LIB debug ${LibSITPLUS_host_LIB_DEBUG})
+ENDIF()
+IF (NOT ${LibSITPLUS_host_LIB_REL} MATCHES ".*NOTFOUND")
+	set(LibSITPLUS_host_LIB ${LibSITPLUS_host_LIB} optimized ${LibSITPLUS_host_LIB_REL})
+ENDIF()
+
+unset (LibSITPLUS_widgets_base_LIB_DEBUG CACHE)
+find_library (LibSITPLUS_widgets_base_LIB_DEBUG widgets_base 
+	PATHS @CMAKE_LIB_DIRS_CONFIGCMAKE@ 
+	PATH_SUFFIXES "./" Debug 
+	NO_DEFAULT_PATH)
+unset (LibSITPLUS_widgets_base_LIB_REL CACHE) 
+find_library (LibSITPLUS_widgets_base_LIB_REL widgets_base 
+	PATHS @CMAKE_LIB_DIRS_CONFIGCMAKE@ 
+	PATH_SUFFIXES "./" Release 
+	NO_DEFAULT_PATH) 
+set(LibSITPLUS_widgets_base_LIB "")
+IF (NOT ${LibSITPLUS_widgets_base_LIB_DEBUG} MATCHES ".*NOTFOUND")
+	set(LibSITPLUS_widgets_base_LIB debug ${LibSITPLUS_widgets_base_LIB_DEBUG})
+ENDIF()
+IF (NOT ${LibSITPLUS_widgets_base_LIB_REL} MATCHES ".*NOTFOUND")
+	set(LibSITPLUS_widgets_base_LIB ${LibSITPLUS_widgets_base_LIB} optimized ${LibSITPLUS_widgets_base_LIB_REL})
+ENDIF()
+
+SET(LibSITPLUS_LIBS ${LibSITPLUS_core_LIB} ${LibSITPLUS_host_LIB} ${LibSITPLUS_widgets_base_LIB})
+
+#
+#  Version variables
+# 
+SET(LibSITPLUS_VERSION          @LIBSITPLUS_VERSION@)
+SET(LibSITPLUS_MAJOR_VERSION    @LIBSITPLUS_MAJOR_VERSION@)
+SET(LibSITPLUS_MINOR_VERSION    @LIBSITPLUS_MINOR_VERSION@)
+SET(LibSITPLUS_REVISION_VERSION @LIBSITPLUS_REVISION_VERSION@)
diff --git a/NEWS b/NEWS
new file mode 100644
index 0000000..11a9675
--- /dev/null
+++ b/NEWS
@@ -0,0 +1,12 @@
+libsitplus Release Notes
+========================
+2013-04-19 - 1.1.0
+* First release of libsitplus
+* Fix crash in score player (which only happened with specific CPUs)
+* Add 'forward' option and transposition support in score player
+* Support for basic conditional statements in script parser
+* Other minor fixes
+* Translations updated
+	Castellano
+	Catal�	
+	Galego (thanks to Miguel Bouzada)
\ No newline at end of file
diff --git a/README b/README
new file mode 100644
index 0000000..ff482ef
--- /dev/null
+++ b/README
@@ -0,0 +1,38 @@
+libsitplus is a library written in C++ derived from the project SITPLUS.
+
+libsitplus is built around a core C++ library (spcore) which provides basic 
+services such as module loading, component instantiation, basic types and 
+internalization among others, and base classes to develop new components.
+
+The basic building block is the component (IComponent interface). A component 
+is a processing unit which provides input and/or output pins and an optional
+UI panel. Components can be arranged in a composite and its pins can be
+connected to build dataflow oriented applications.
+
+Each component is identified by its type name and many instances of it can be 
+created. Each pin has an associated type, which can be an specific type (such 
+as integer, char or float) or any type. Only pins whose types match can be 
+connected together.
+
+To make this framework extensible, new components and types can be provided 
+though external loadable modules (plug-ins).
+
+Along with with the core, two helper libraries are also provided:
+
+- sphost: provides some helper functions and classes to develop final 
+  applications. It provides, for instance, a script parser to ease the 
+  creation of component composites.
+- widgets_base: provides user interface base classes.
+
+Finally, several modules are also provided, for instance:
+
+- mod_camera: components and types to deal with camera capture.
+- mod_io: components for file I/O.
+- mod_midi: components and types for MIDI output.
+- mod_sdl: components and types to draw on SDL surfaces.
+- mod_vision: components for computer vision.
+- mod_widgets: UI components such as buttons, combo boxes, etc.
+- mod_wiimotes: components and types to use Wii remotes
+
+libsitplus is (C) C�sar Mauri Loba 2012 - 13 <cesar at crea - si dot com>
+Released under the terms of the GNU GPL license. See COPYING.
\ No newline at end of file
diff --git a/TODO b/TODO
new file mode 100644
index 0000000..5317916
--- /dev/null
+++ b/TODO
@@ -0,0 +1,2 @@
+- Doxygen API doc. generation (needs some work)
+- Automatic dependencies generation (see CPACK_DEBIAN_PACKAGE_SHLIBDEPS)
diff --git a/cmake_modules/COPYING-CMAKE-SCRIPTS b/cmake_modules/COPYING-CMAKE-SCRIPTS
new file mode 100755
index 0000000..4b41776
--- /dev/null
+++ b/cmake_modules/COPYING-CMAKE-SCRIPTS
@@ -0,0 +1,22 @@
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+1. Redistributions of source code must retain the copyright
+   notice, this list of conditions and the following disclaimer.
+2. Redistributions in binary form must reproduce the copyright
+   notice, this list of conditions and the following disclaimer in the
+   documentation and/or other materials provided with the distribution.
+3. The name of the author may not be used to endorse or promote products 
+   derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/cmake_modules/FindGLIB2.cmake b/cmake_modules/FindGLIB2.cmake
new file mode 100755
index 0000000..942b045
--- /dev/null
+++ b/cmake_modules/FindGLIB2.cmake
@@ -0,0 +1,217 @@
+# - Try to find GLib2
+# Once done this will define
+#
+#  GLIB2_FOUND - system has GLib2
+#  GLIB2_INCLUDE_DIRS - the GLib2 include directory
+#  GLIB2_LIBRARIES - Link these to use GLib2
+#
+#  HAVE_GLIB_GREGEX_H  glib has gregex.h header and 
+#                      supports g_regex_match_simple
+#
+#  Copyright (c) 2006 Andreas Schneider <mail at cynapses.org>
+#  Copyright (c) 2006 Philippe Bernery <philippe.bernery at gmail.com>
+#  Copyright (c) 2007 Daniel Gollub <dgollub at suse.de>
+#  Copyright (c) 2007 Alban Browaeys <prahal at yahoo.com>
+#  Copyright (c) 2008 Michael Bell <michael.bell at web.de>
+#  Copyright (c) 2008 Bjoern Ricks <bjoern.ricks at googlemail.com>
+#
+#  Redistribution and use is allowed according to the terms of the New
+#  BSD license.
+#  For details see the accompanying COPYING-CMAKE-SCRIPTS file.
+#
+
+
+IF (GLIB2_LIBRARIES AND GLIB2_INCLUDE_DIRS )
+  # in cache already
+  SET(GLIB2_FOUND TRUE)
+ELSE (GLIB2_LIBRARIES AND GLIB2_INCLUDE_DIRS )
+
+  INCLUDE(FindPkgConfig)
+
+  ## Glib
+  IF ( GLIB2_FIND_REQUIRED )
+    SET( _pkgconfig_REQUIRED "REQUIRED" )
+  ELSE ( GLIB2_FIND_REQUIRED )
+    SET( _pkgconfig_REQUIRED "" )
+  ENDIF ( GLIB2_FIND_REQUIRED )
+
+  IF ( GLIB2_MIN_VERSION )
+    PKG_SEARCH_MODULE( GLIB2 ${_pkgconfig_REQUIRED} glib-2.0>=${GLIB2_MIN_VERSION} )
+  ELSE ( GLIB2_MIN_VERSION )
+    PKG_SEARCH_MODULE( GLIB2 ${_pkgconfig_REQUIRED} glib-2.0 )
+  ENDIF ( GLIB2_MIN_VERSION )
+  IF ( PKG_CONFIG_FOUND )
+    IF ( GLIB2_FOUND )
+      SET ( GLIB2_CORE_FOUND TRUE )
+    ELSE ( GLIB2_FOUND )
+      SET ( GLIB2_CORE_FOUND FALSE )
+    ENDIF ( GLIB2_FOUND )
+  ENDIF ( PKG_CONFIG_FOUND )
+
+  # Look for glib2 include dir and libraries w/o pkgconfig
+  IF ( NOT GLIB2_FOUND AND NOT PKG_CONFIG_FOUND )
+    FIND_PATH(
+      _glibconfig_include_DIR
+    NAMES
+      glibconfig.h
+    PATHS
+      /opt/gnome/lib64
+      /opt/gnome/lib
+      /opt/lib/
+      /opt/local/lib
+      /sw/lib/
+      /usr/lib64
+      /usr/lib
+      /usr/local/include
+      ${CMAKE_LIBRARY_PATH}
+    PATH_SUFFIXES
+      glib-2.0/include
+    )
+
+    FIND_PATH(
+      _glib2_include_DIR
+    NAMES
+      glib.h
+    PATHS
+      /opt/gnome/include
+      /opt/local/include
+      /sw/include
+      /usr/include
+      /usr/local/include
+    PATH_SUFFIXES
+      glib-2.0
+    )
+
+    #MESSAGE(STATUS "Glib headers: ${_glib2_include_DIR}")
+
+    FIND_LIBRARY(
+      _glib2_link_DIR
+    NAMES
+      glib-2.0
+      glib
+    PATHS
+      /opt/gnome/lib
+      /opt/local/lib
+      /sw/lib
+      /usr/lib
+      /usr/local/lib
+    )
+    IF ( _glib2_include_DIR AND _glib2_link_DIR )
+        SET ( _glib2_FOUND TRUE )
+    ENDIF ( _glib2_include_DIR AND _glib2_link_DIR )
+
+
+    IF ( _glib2_FOUND )
+        SET ( GLIB2_INCLUDE_DIRS ${_glib2_include_DIR} ${_glibconfig_include_DIR} )
+        SET ( GLIB2_LIBRARIES ${_glib2_link_DIR} )
+        SET ( GLIB2_CORE_FOUND TRUE )
+    ELSE ( _glib2_FOUND )
+        SET ( GLIB2_CORE_FOUND FALSE )
+    ENDIF ( _glib2_FOUND )
+
+    # Handle dependencies
+    # libintl
+    IF ( NOT LIBINTL_FOUND )
+      FIND_PATH(LIBINTL_INCLUDE_DIR
+      NAMES
+        libintl.h
+      PATHS
+        /opt/gnome/include
+        /opt/local/include
+        /sw/include
+        /usr/include
+        /usr/local/include
+      )
+
+      FIND_LIBRARY(LIBINTL_LIBRARY
+      NAMES
+        intl
+      PATHS
+        /opt/gnome/lib
+        /opt/local/lib
+        /sw/lib
+        /usr/local/lib
+        /usr/lib
+      )
+
+      IF (LIBINTL_LIBRARY AND LIBINTL_INCLUDE_DIR)
+        SET (LIBINTL_FOUND TRUE)
+      ENDIF (LIBINTL_LIBRARY AND LIBINTL_INCLUDE_DIR)
+    ENDIF ( NOT LIBINTL_FOUND )
+
+    # libiconv
+    IF ( NOT LIBICONV_FOUND )
+      FIND_PATH(LIBICONV_INCLUDE_DIR
+      NAMES
+        iconv.h
+      PATHS
+        /opt/gnome/include
+        /opt/local/include
+        /opt/local/include
+        /sw/include
+        /sw/include
+        /usr/local/include
+        /usr/include
+      PATH_SUFFIXES
+        glib-2.0
+      )
+
+      FIND_LIBRARY(LIBICONV_LIBRARY
+      NAMES
+        iconv
+      PATHS
+        /opt/gnome/lib
+        /opt/local/lib
+        /sw/lib
+        /usr/lib
+        /usr/local/lib
+      )
+
+      IF (LIBICONV_LIBRARY AND LIBICONV_INCLUDE_DIR)
+        SET (LIBICONV_FOUND TRUE)
+      ENDIF (LIBICONV_LIBRARY AND LIBICONV_INCLUDE_DIR)
+    ENDIF ( NOT LIBICONV_FOUND )
+
+    IF (LIBINTL_FOUND)
+      SET (GLIB2_LIBRARIES ${GLIB2_LIBRARIES} ${LIBINTL_LIBRARY})
+      SET (GLIB2_INCLUDE_DIRS ${GLIB2_INCLUDE_DIRS} ${LIBINTL_INCLUDE_DIR})
+    ENDIF (LIBINTL_FOUND)
+
+    IF (LIBICONV_FOUND)
+      SET (GLIB2_LIBRARIES ${GLIB2_LIBRARIES} ${LIBICONV_LIBRARY})
+      SET (GLIB2_INCLUDE_DIRS ${GLIB2_INCLUDE_DIRS} ${LIBICONV_INCLUDE_DIR})
+    ENDIF (LIBICONV_FOUND)
+
+  ENDIF ( NOT GLIB2_FOUND AND NOT PKG_CONFIG_FOUND )
+  ##
+
+  IF (GLIB2_CORE_FOUND AND GLIB2_INCLUDE_DIRS AND GLIB2_LIBRARIES)
+    SET (GLIB2_FOUND TRUE)
+  ENDIF (GLIB2_CORE_FOUND AND GLIB2_INCLUDE_DIRS AND GLIB2_LIBRARIES)
+
+  IF (GLIB2_FOUND)
+    IF (NOT GLIB2_FIND_QUIETLY)
+      MESSAGE (STATUS "Found GLib2: ${GLIB2_LIBRARIES} ${GLIB2_INCLUDE_DIRS}")
+    ENDIF (NOT GLIB2_FIND_QUIETLY)
+  ELSE (GLIB2_FOUND)
+    IF (GLIB2_FIND_REQUIRED)
+      MESSAGE (SEND_ERROR "Could not find GLib2")
+    ENDIF (GLIB2_FIND_REQUIRED)
+  ENDIF (GLIB2_FOUND)
+
+  # show the GLIB2_INCLUDE_DIRS and GLIB2_LIBRARIES variables only in the advanced view
+  MARK_AS_ADVANCED(GLIB2_INCLUDE_DIRS GLIB2_LIBRARIES)
+  MARK_AS_ADVANCED(LIBICONV_INCLUDE_DIR LIBICONV_LIBRARY)
+  MARK_AS_ADVANCED(LIBINTL_INCLUDE_DIR LIBINTL_LIBRARY)
+
+ENDIF (GLIB2_LIBRARIES AND GLIB2_INCLUDE_DIRS)
+
+IF ( GLIB2_FOUND )
+	# Check if system has a newer version of glib
+	# which supports g_regex_match_simple
+	INCLUDE( CheckIncludeFiles )
+	SET( CMAKE_REQUIRED_INCLUDES ${GLIB2_INCLUDE_DIRS} )
+	CHECK_INCLUDE_FILES ( glib/gregex.h HAVE_GLIB_GREGEX_H )
+	# Reset CMAKE_REQUIRED_INCLUDES
+	SET( CMAKE_REQUIRED_INCLUDES "" )
+ENDIF( GLIB2_FOUND )
diff --git a/cmake_modules/FindLibConfig.cmake b/cmake_modules/FindLibConfig.cmake
new file mode 100755
index 0000000..19755ff
--- /dev/null
+++ b/cmake_modules/FindLibConfig.cmake
@@ -0,0 +1,76 @@
+#
+# This module defines
+# LibConfig_INCLUDE_DIR, where to find cppunit include files, etc.
+# LibConfig_LIBRARIES, the libraries to link against to use CppUnit.
+# LibConfig_STATIC_LIBRARY_PATH
+# LibConfig_FOUND, If false, do not try to use CppUnit.
+
+# also defined, but not for general use are
+# LibConfig_LIBRARY, where to find the library.
+
+FIND_PATH(LibConfig_INCLUDE_DIR
+	libconfig.h
+	PATHS /usr/local/include /usr/include ~/libs/include ~/include
+)
+
+FIND_PATH(LibConfigCPP_INCLUDE_DIR libconfig.h++
+  PATHS /usr/local/include
+  /usr/include
+  ~/libs/include
+  ~/include
+)
+
+FIND_LIBRARY(LibConfig_LIBRARY config
+  PATHS /usr/local/lib
+  /usr/lib
+  ~/libs/lib
+)
+
+FIND_LIBRARY(LibConfigCPP_LIBRARY config++
+  PATHS /usr/local/lib
+  /usr/lib
+  ~/libs/lib
+)
+
+FIND_LIBRARY(LibConfig_STATIC_LIBRARY "libconfig${CMAKE_STATIC_LIBRARY_SUFFIX}"
+  PATHS /usr/local/lib
+  /usr/lib
+  ~/libs/lib
+)
+
+FIND_LIBRARY(LibConfigCPP_STATIC_LIBRARY "libconfig++${CMAKE_STATIC_LIBRARY_SUFFIX}"
+    PATHS /usr/local/lib
+    /usr/lib
+    ~/libs/lib
+)
+
+
+IF(LibConfig_INCLUDE_DIR)
+  IF(LibConfig_LIBRARY)
+    SET(LibConfig_FOUND TRUE)
+    SET(LibConfig_LIBRARIES ${LibConfig_LIBRARY})
+    SET(LibConfig_STATIC_LIBRARY_PATH ${LibConfig_STATIC_LIBRARY})
+  ENDIF(LibConfig_LIBRARY)
+ENDIF(LibConfig_INCLUDE_DIR)
+
+IF(LibConfigCPP_INCLUDE_DIR)
+  IF(LibConfigCPP_LIBRARY)
+    SET(LibConfigCPP_FOUND TRUE)
+    SET(LibConfigCPP_LIBRARIES ${LibConfigCPP_LIBRARY})
+    SET(LibConfigCPP_STATIC_LIBRARY_PATH ${LibConfigCPP_STATIC_LIBRARY})
+  ENDIF(LibConfigCPP_LIBRARY)
+ENDIF(LibConfigCPP_INCLUDE_DIR)
+
+IF (LibConfig_FOUND)
+   IF (NOT LibConfig_FIND_QUIETLY)
+      MESSAGE(STATUS "Found LibConfig++: ${LibConfigCPP_LIBRARIES}" )
+      MESSAGE(STATUS "Found LibConfig: ${LibConfig_LIBRARIES}")
+      MESSAGE(STATUS "static LibConfig path: ${LibConfig_STATIC_LIBRARY_PATH}")
+   ENDIF (NOT LibConfig_FIND_QUIETLY)
+ELSE (LibConfig_FOUND)
+   IF (LibConfig_FIND_REQUIRED)
+      MESSAGE(SEND_ERROR "Could NOT find LibConfig")
+   ENDIF (LibConfig_FIND_REQUIRED)
+ENDIF (LibConfig_FOUND)
+
+MARK_AS_ADVANCED(LibConfig_INCLUDE_DIR LibConfig_LIBRARIES)
\ No newline at end of file
diff --git a/cmake_modules/FindLibintl.cmake b/cmake_modules/FindLibintl.cmake
new file mode 100755
index 0000000..1b9f5a0
--- /dev/null
+++ b/cmake_modules/FindLibintl.cmake
@@ -0,0 +1,61 @@
+# Try to find Libintl functionality
+# Once done this will define
+#
+#  LIBINTL_FOUND - system has Libintl
+#  LIBINTL_INCLUDE_DIR - Libintl include directory
+#  LIBINTL_LIBRARIES - Libraries needed to use Libintl
+#
+# TODO: This will enable translations only if Gettext functionality is
+# present in libc. Must have more robust system for release, where Gettext
+# functionality can also reside in standalone Gettext library, or the one
+# embedded within kdelibs (cf. gettext.m4 from Gettext source).
+
+# Copyright (c) 2006, Chusslove Illich, <caslav.ilic at gmx.net>
+# Copyright (c) 2007, Alexander Neundorf, <neundorf at kde.org>
+#
+# Redistribution and use is allowed according to the terms of the BSD license.
+# For details see the accompanying COPYING-CMAKE-SCRIPTS file.
+
+if(LIBINTL_INCLUDE_DIR AND LIBINTL_LIB_FOUND)
+  set(Libintl_FIND_QUIETLY TRUE)
+endif(LIBINTL_INCLUDE_DIR AND LIBINTL_LIB_FOUND)
+
+include(FindPkgMacros)
+
+# Uses environtment variable as a hint
+getenv_path(GNUWIN32DIR)
+set(Libintl_PREFIX_PATH ${ENV_GNUWIN32DIR} )
+set(LIBINTL_ROOT_PATH ${Libintl_PREFIX_PATH})
+
+create_search_paths(Libintl)
+
+set(Libintl_INC_SEARCH_PATH ${Libintl_INC_SEARCH_PATH} ${Libintl_PREFIX_PATH})
+
+set(Libintl_LIBRARY_NAMES intl libintl)
+get_debug_names(Libintl_LIBRARY_NAMES)
+
+find_path(LIBINTL_INCLUDE_DIR NAMES libintl.h HINTS ${Libintl_INC_SEARCH_PATH})
+
+set(LIBINTL_LIB_FOUND FALSE)
+
+if(LIBINTL_INCLUDE_DIR)
+  include(CheckFunctionExists)
+  check_function_exists(dgettext LIBINTL_LIBC_HAS_DGETTEXT)
+
+  if (LIBINTL_LIBC_HAS_DGETTEXT)
+    set(LIBINTL_LIBRARIES)
+    set(LIBINTL_LIB_FOUND TRUE)
+  else (LIBINTL_LIBC_HAS_DGETTEXT)
+    #find_library(LIBINTL_LIBRARIES NAMES intl libintl )
+	find_library(LIBINTL_LIBRARIES NAMES ${Libintl_LIBRARY_NAMES} HINTS ${Libintl_LIB_SEARCH_PATH})
+    if(LIBINTL_LIBRARIES)
+      set(LIBINTL_LIB_FOUND TRUE)
+    endif(LIBINTL_LIBRARIES)
+  endif (LIBINTL_LIBC_HAS_DGETTEXT)
+
+endif(LIBINTL_INCLUDE_DIR)
+
+include(FindPackageHandleStandardArgs)
+find_package_handle_standard_args(Libintl  DEFAULT_MSG  LIBINTL_INCLUDE_DIR  LIBINTL_LIB_FOUND)
+
+mark_as_advanced(LIBINTL_INCLUDE_DIR  LIBINTL_LIBRARIES  LIBINTL_LIBC_HAS_DGETTEXT  LIBINTL_LIB_FOUND)
diff --git a/cmake_modules/FindPOCO.cmake b/cmake_modules/FindPOCO.cmake
new file mode 100644
index 0000000..779ed0e
--- /dev/null
+++ b/cmake_modules/FindPOCO.cmake
@@ -0,0 +1,102 @@
+#-------------------------------------------------------------------
+# This file is part of the CMake build system for OGRE
+#     (Object-oriented Graphics Rendering Engine)
+# For the latest info, see http://www.ogre3d.org/
+#
+# The contents of this file are placed in the public domain. Feel
+# free to make use of it in any way you like.
+#-------------------------------------------------------------------
+
+# - Try to find POCO libraries
+# Once done, this will define
+#
+#  POCO_FOUND - system has POCO
+#  POCO_INCLUDE_DIRS - the POCO include directories 
+#  POCO_LIBRARIES - link these to use POCO
+
+include(FindPkgMacros)
+findpkg_begin(POCO)
+
+# Get path, convert backslashes as ${ENV_${var}}
+getenv_path(POCO_HOME)
+getenv_path(POCO_ROOT)
+getenv_path(POCO_BASE)
+
+# construct search paths
+set(POCO_PREFIX_PATH 
+  ${POCO_HOME} ${ENV_POCO_HOME} 
+  ${POCO_ROOT} ${ENV_POCO_ROOT}
+  ${POCO_BASE} ${ENV_POCO_BASE}
+)
+# redo search if prefix path changed
+clear_if_changed(POCO_PREFIX_PATH
+  POCO_LIBRARY_FWK
+  POCO_LIBRARY_REL
+  POCO_LIBRARY_DBG
+  POCO_INCLUDE_DIR
+)
+
+create_search_paths(POCO)
+set(POCO_INC_SEARCH_PATH ${POCO_INC_SEARCH_PATH} ${POCO_PREFIX_PATH})
+
+
+set(POCO_LIBRARY_NAMES PocoFoundation PocoFoundationmt)
+get_debug_names(POCO_LIBRARY_NAMES)
+
+use_pkgconfig(POCO_PKGC POCO)
+
+findpkg_framework(POCO)
+
+find_path(POCO_INCLUDE_DIR NAMES Poco/Foundation.h HINTS ${POCO_INC_SEARCH_PATH} ${POCO_PKGC_INCLUDE_DIRS} PATH_SUFFIXES Foundation/include)
+find_library(POCO_LIBRARY_REL NAMES ${POCO_LIBRARY_NAMES} HINTS ${POCO_LIB_SEARCH_PATH} ${POCO_PKGC_LIBRARY_DIRS} PATH_SUFFIXES Linux/i686)
+find_library(POCO_LIBRARY_DBG NAMES ${POCO_LIBRARY_NAMES_DBG} HINTS ${POCO_LIB_SEARCH_PATH} ${POCO_PKGC_LIBRARY_DIRS} PATH_SUFFIXES Linux/i686)
+make_library_set(POCO_LIBRARY)
+
+findpkg_finish(POCO)
+
+if (NOT POCO_FOUND)
+  return()
+endif ()
+
+
+# Look for Poco's Util package
+findpkg_begin(POCO_Util)
+set(POCO_Util_LIBRARY_NAMES PocoUtil PocoUtilmt)
+get_debug_names(POCO_Util_LIBRARY_NAMES)
+find_path(POCO_Util_INCLUDE_DIR NAMES Poco/Util/Util.h HINTS ${POCO_INCLUDE_DIR} ${POCO_INC_SEARCH_PATH} ${POCO_PKGC_INCLUDE_DIRS} PATH_SUFFIXES Util/include)
+find_library(POCO_Util_LIBRARY_REL NAMES ${POCO_Util_LIBRARY_NAMES} HINTS ${POCO_LIB_SEARCH_PATH} ${POCO_PKGC_LIBRARY_DIRS} PATH_SUFFIXES Linux/i686)
+find_library(POCO_Util_LIBRARY_DBG NAMES ${POCO_Util_LIBRARY_NAMES_DBG} HINTS ${POCO_LIB_SEARCH_PATH} ${POCO_PKGC_LIBRARY_DIRS} PATH_SUFFIXES Linux/i686)
+make_library_set(POCO_Util_LIBRARY)
+findpkg_finish(POCO_Util)
+
+# Look for Poco's Net package
+findpkg_begin(POCO_Net)
+set(POCO_Net_LIBRARY_NAMES PocoNet PocoNetmt)
+get_debug_names(POCO_Net_LIBRARY_NAMES)
+find_path(POCO_Net_INCLUDE_DIR NAMES Poco/Net/Net.h HINTS ${POCO_INCLUDE_DIR} ${POCO_INC_SEARCH_PATH} ${POCO_PKGC_INCLUDE_DIRS} PATH_SUFFIXES Net/include)
+find_library(POCO_Net_LIBRARY_REL NAMES ${POCO_Net_LIBRARY_NAMES} HINTS ${POCO_LIB_SEARCH_PATH} ${POCO_PKGC_LIBRARY_DIRS} PATH_SUFFIXES Linux/i686)
+find_library(POCO_Net_LIBRARY_DBG NAMES ${POCO_Net_LIBRARY_NAMES_DBG} HINTS ${POCO_LIB_SEARCH_PATH} ${POCO_PKGC_LIBRARY_DIRS} PATH_SUFFIXES Linux/i686)
+make_library_set(POCO_Net_LIBRARY)
+findpkg_finish(POCO_Net)
+
+# Look for Poco's NetSSL package
+findpkg_begin(POCO_NetSSL)
+set(POCO_NetSSL_LIBRARY_NAMES PocoNetSSL PocoNetSSLmt)
+get_debug_names(POCO_NetSSL_LIBRARY_NAMES)
+find_path(POCO_NetSSL_INCLUDE_DIR NAMES Poco/Net/NetSSL.h HINTS ${POCO_INCLUDE_DIR} ${POCO_INC_SEARCH_PATH} ${POCO_PKGC_INCLUDE_DIRS} PATH_SUFFIXES NetSSL/include)
+find_library(POCO_NetSSL_LIBRARY_REL NAMES ${POCO_NetSSL_LIBRARY_NAMES} HINTS ${POCO_LIB_SEARCH_PATH} ${POCO_PKGC_LIBRARY_DIRS} PATH_SUFFIXES Linux/i686)
+find_library(POCO_NetSSL_LIBRARY_DBG NAMES ${POCO_NetSSL_LIBRARY_NAMES_DBG} HINTS ${POCO_LIB_SEARCH_PATH} ${POCO_PKGC_LIBRARY_DIRS} PATH_SUFFIXES Linux/i686)
+make_library_set(POCO_NetSSL_LIBRARY)
+findpkg_finish(POCO_NetSSL)
+
+# Look for Poco's XML package
+findpkg_begin(POCO_XML)
+set(POCO_XML_LIBRARY_NAMES PocoXML PocoXMLmt)
+get_debug_names(POCO_XML_LIBRARY_NAMES)
+find_path(POCO_XML_INCLUDE_DIR NAMES Poco/XML/XML.h HINTS ${POCO_INCLUDE_DIR} ${POCO_INC_SEARCH_PATH} ${POCO_PKGC_INCLUDE_DIRS} PATH_SUFFIXES XML/include)
+find_library(POCO_XML_LIBRARY_REL NAMES ${POCO_XML_LIBRARY_NAMES} HINTS ${POCO_LIB_SEARCH_PATH} ${POCO_PKGC_LIBRARY_DIRS} PATH_SUFFIXES Linux/i686)
+find_library(POCO_XML_LIBRARY_DBG NAMES ${POCO_XML_LIBRARY_NAMES_DBG} HINTS ${POCO_LIB_SEARCH_PATH} ${POCO_PKGC_LIBRARY_DIRS} PATH_SUFFIXES Linux/i686)
+make_library_set(POCO_XML_LIBRARY)
+findpkg_finish(POCO_XML)
+
+
diff --git a/cmake_modules/FindPkgMacros.cmake b/cmake_modules/FindPkgMacros.cmake
new file mode 100644
index 0000000..0e83c4e
--- /dev/null
+++ b/cmake_modules/FindPkgMacros.cmake
@@ -0,0 +1,147 @@
+#-------------------------------------------------------------------
+# This file is part of the CMake build system for OGRE
+#     (Object-oriented Graphics Rendering Engine)
+# For the latest info, see http://www.ogre3d.org/
+#
+# The contents of this file are placed in the public domain. Feel
+# free to make use of it in any way you like.
+#-------------------------------------------------------------------
+
+##################################################################
+# Provides some common functionality for the FindPackage modules
+##################################################################
+
+# Begin processing of package
+macro(findpkg_begin PREFIX)
+  if (NOT ${PREFIX}_FIND_QUIETLY)
+    message(STATUS "Looking for ${PREFIX}...")
+  endif ()
+endmacro(findpkg_begin)
+
+# Display a status message unless FIND_QUIETLY is set
+macro(pkg_message PREFIX)
+  if (NOT ${PREFIX}_FIND_QUIETLY)
+    message(STATUS ${ARGN})
+  endif ()
+endmacro(pkg_message)
+
+# Get environment variable, define it as ENV_$var and make sure backslashes are converted to forward slashes
+macro(getenv_path VAR)
+   set(ENV_${VAR} $ENV{${VAR}})
+   # replace won't work if var is blank
+   if (ENV_${VAR})
+     string( REGEX REPLACE "\\\\" "/" ENV_${VAR} ${ENV_${VAR}} )
+   endif ()
+endmacro(getenv_path)
+
+# Construct search paths for includes and libraries from a PREFIX_PATH
+macro(create_search_paths PREFIX)
+  foreach(dir ${${PREFIX}_PREFIX_PATH})
+    set(${PREFIX}_INC_SEARCH_PATH ${${PREFIX}_INC_SEARCH_PATH}
+      ${dir}/include ${dir}/Include ${dir}/include/${PREFIX} ${dir}/Headers)
+    set(${PREFIX}_LIB_SEARCH_PATH ${${PREFIX}_LIB_SEARCH_PATH}
+      ${dir}/lib ${dir}/Lib ${dir}/lib/${PREFIX} ${dir}/Libs)
+    set(${PREFIX}_BIN_SEARCH_PATH ${${PREFIX}_BIN_SEARCH_PATH}
+      ${dir}/bin)
+  endforeach(dir)
+  set(${PREFIX}_FRAMEWORK_SEARCH_PATH ${${PREFIX}_PREFIX_PATH})
+endmacro(create_search_paths)
+
+# clear cache variables if a certain variable changed
+macro(clear_if_changed TESTVAR)
+  # test against internal check variable
+  if (NOT "${${TESTVAR}}" STREQUAL "${${TESTVAR}_INT_CHECK}")
+    message(STATUS "${TESTVAR} changed.")
+    foreach(var ${ARGN})
+      set(${var} "NOTFOUND" CACHE STRING "x" FORCE)
+    endforeach(var)
+  endif ()
+  set(${TESTVAR}_INT_CHECK ${${TESTVAR}} CACHE INTERNAL "x" FORCE)
+endmacro(clear_if_changed)
+
+# Try to get some hints from pkg-config, if available
+macro(use_pkgconfig PREFIX PKGNAME)
+  find_package(PkgConfig)
+  if (PKG_CONFIG_FOUND)
+    pkg_check_modules(${PREFIX} ${PKGNAME})
+  endif ()
+endmacro (use_pkgconfig)
+
+# Couple a set of release AND debug libraries (or frameworks)
+macro(make_library_set PREFIX)
+  if (${PREFIX}_FWK)
+    set(${PREFIX} ${${PREFIX}_FWK})
+  elseif (${PREFIX}_REL AND ${PREFIX}_DBG)
+    set(${PREFIX} optimized ${${PREFIX}_REL} debug ${${PREFIX}_DBG})
+  elseif (${PREFIX}_REL)
+    set(${PREFIX} ${${PREFIX}_REL})
+  elseif (${PREFIX}_DBG)
+    set(${PREFIX} ${${PREFIX}_DBG})
+  endif ()
+endmacro(make_library_set)
+
+# Generate debug names from given release names
+macro(get_debug_names PREFIX)
+  foreach(i ${${PREFIX}})
+    set(${PREFIX}_DBG ${${PREFIX}_DBG} ${i}d ${i}D ${i}_d ${i}_D ${i}_debug ${i})
+  endforeach(i)
+endmacro(get_debug_names)
+
+# Add the parent dir from DIR to VAR 
+macro(add_parent_dir VAR DIR)
+  get_filename_component(${DIR}_TEMP "${${DIR}}/.." ABSOLUTE)
+  set(${VAR} ${${VAR}} ${${DIR}_TEMP})
+endmacro(add_parent_dir)
+
+# Do the final processing for the package find.
+macro(findpkg_finish PREFIX)
+  # skip if already processed during this run
+  if (NOT ${PREFIX}_FOUND)
+    if (${PREFIX}_INCLUDE_DIR AND ${PREFIX}_LIBRARY)
+      set(${PREFIX}_FOUND TRUE)
+      set(${PREFIX}_INCLUDE_DIRS ${${PREFIX}_INCLUDE_DIR})
+      set(${PREFIX}_LIBRARIES ${${PREFIX}_LIBRARY})
+      if (NOT ${PREFIX}_FIND_QUIETLY)
+        message(STATUS "Found ${PREFIX}: ${${PREFIX}_LIBRARIES}")
+      endif ()
+    else ()
+      if (NOT ${PREFIX}_FIND_QUIETLY)
+        message(STATUS "Could not locate ${PREFIX}")
+      endif ()
+      if (${PREFIX}_FIND_REQUIRED)
+        message(FATAL_ERROR "Required library ${PREFIX} not found! Install the library (including dev packages) and try again. If the library is already installed, set the missing variables manually in cmake.")
+      endif ()
+    endif ()
+
+    mark_as_advanced(${PREFIX}_INCLUDE_DIR ${PREFIX}_LIBRARY ${PREFIX}_LIBRARY_REL ${PREFIX}_LIBRARY_DBG ${PREFIX}_LIBRARY_FWK)
+  endif ()
+endmacro(findpkg_finish)
+
+
+# Slightly customised framework finder
+MACRO(findpkg_framework fwk)
+  IF(APPLE)
+    SET(${fwk}_FRAMEWORK_PATH
+      ${${fwk}_FRAMEWORK_SEARCH_PATH}
+      ${CMAKE_FRAMEWORK_PATH}
+      ~/Library/Frameworks
+      /Library/Frameworks
+      /System/Library/Frameworks
+      /Network/Library/Frameworks
+      /Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS3.0.sdk/System/Library/Frameworks/
+      ${CMAKE_CURRENT_SOURCE_DIR}/lib/Release
+      ${CMAKE_CURRENT_SOURCE_DIR}/lib/Debug
+    )
+    FOREACH(dir ${${fwk}_FRAMEWORK_PATH})
+      SET(fwkpath ${dir}/${fwk}.framework)
+      IF(EXISTS ${fwkpath})
+        SET(${fwk}_FRAMEWORK_INCLUDES ${${fwk}_FRAMEWORK_INCLUDES}
+          ${fwkpath}/Headers ${fwkpath}/PrivateHeaders)
+        SET(${fwk}_FRAMEWORK_PATH ${dir})
+        if (NOT ${fwk}_LIBRARY_FWK)
+          SET(${fwk}_LIBRARY_FWK "-framework ${fwk}")
+        endif ()
+      ENDIF(EXISTS ${fwkpath})
+    ENDFOREACH(dir)
+  ENDIF(APPLE)
+ENDMACRO(findpkg_framework)
diff --git a/cmake_modules/FindPortMidi.cmake b/cmake_modules/FindPortMidi.cmake
new file mode 100755
index 0000000..66d1011
--- /dev/null
+++ b/cmake_modules/FindPortMidi.cmake
@@ -0,0 +1,39 @@
+# - Try to find PortMidi
+# Once done, this will define
+#
+#  PortMidi_FOUND - system has PortMidi
+#  PortMidi_INCLUDE_DIRS - the PortMidi include directories
+#  PortMidi_LIBRARIES - link these to use PortMidi
+#
+
+include(FindPkgMacros)
+
+findpkg_begin(PortMidi)
+
+# Uses environtment variable as a hint
+getenv_path(PORTMIDIDIR)
+set(PortMidi_PREFIX_PATH ${ENV_PORTMIDIDIR} )
+
+# redo search if prefix path changed
+clear_if_changed(PortMidi_PREFIX_PATH
+	PortMidi_LIBRARY_REL
+	PortMidi_LIBRARY_DBG
+	PortMidi_INCLUDE_DIR
+)
+
+create_search_paths(PortMidi)
+
+set(PortMidi_INC_SEARCH_PATH ${PortMidi_INC_SEARCH_PATH} ${PortMidi_PREFIX_PATH})
+
+set(PortMidi_LIBRARY_NAMES portmidi)
+get_debug_names(PortMidi_LIBRARY_NAMES)
+
+find_path(PortMidi_INCLUDE_DIR NAMES portmidi.h HINTS ${PortMidi_INC_SEARCH_PATH})
+
+find_library(PortMidi_LIBRARY_REL NAMES ${PortMidi_LIBRARY_NAMES} HINTS ${PortMidi_LIB_SEARCH_PATH} PATH_SUFFIXES Linux/i686)
+
+find_library(PortMidi_LIBRARY_DBG NAMES ${PortMidi_LIBRARY_NAMES_DBG} HINTS ${PortMidi_LIB_SEARCH_PATH} PATH_SUFFIXES Linux/i686)
+
+make_library_set(PortMidi_LIBRARY)
+
+findpkg_finish(PortMidi)
diff --git a/cmake_modules/FindPotupdate.cmake b/cmake_modules/FindPotupdate.cmake
new file mode 100755
index 0000000..332b1d8
--- /dev/null
+++ b/cmake_modules/FindPotupdate.cmake
@@ -0,0 +1,178 @@
+# - Find Gettext run-time library and tools.
+# This module finds the GNU gettext run-time library (LGPL), include paths and 
+# associated tools (GPL). This code sets the following variables:
+#  GETTEXT_INCLUDE_DIR         = path(s) to gettext's include files
+#  GETTEXT_LIBRARIES           = the libraries to link against to use gettext
+#  GETTEXT_INTL_LIBRARY        = path to gettext's intl library
+#  GETTEXT_RUNTIME_FOUND       = true if runtime libs were found (intl)
+#  GETTEXT_INFO_MSG            = information string about gettext
+#  GETTEXT_XGETTEXT_EXECUTABLE = xgettext tool
+#  GETTEXT_MSGINIT_EXECUTABLE  = msginit tool
+#  GETTEXT_MSGCAT_EXECUTABLE   = msgcat tool
+#  GETTEXT_MSGCONV_EXECUTABLE  = msgconv tool
+#  GETTEXT_TOOLS_FOUND         = true if all the tools were found
+#  GETTEXT_FOUND               = true if both runtime and tools were found
+# As a convenience, the following variables can be set before including
+# this module to make its life easier:
+#  GETTEXT_SEARCH_PATH         = list of path to search gettext components for
+# --------------------------------------------------------------------------
+# As a convenience, try to find everything as soon as we set any one of
+# the cache variables.
+
+macro(GETTEXT_FIND_POTENTIAL_DIRS)
+
+  set(potential_bin_dirs)
+  set(potential_lib_dirs)
+  set(potential_include_dirs)
+  foreach(filepath 
+      "${GETTEXT_INTL_LIBRARY}"
+      "${GETTEXT_XGETTEXT_EXECUTABLE}"
+      "${GETTEXT_MSGINIT_EXECUTABLE}"
+      "${GETTEXT_MSGCAT_EXECUTABLE}"
+      "${GETTEXT_MSGCONV_EXECUTABLE}"
+      )
+    get_filename_component(path "${filepath}" PATH)
+    set(potential_bin_dirs ${potential_bin_dirs} "${path}/../bin")
+    set(potential_lib_dirs ${potential_lib_dirs} "${path}/../lib")
+    set(potential_include_dirs ${potential_include_dirs} "${path}/../include")
+  endforeach(filepath)
+
+  foreach(path 
+      "${GETTEXT_INCLUDE_DIR}"
+      "${GETTEXT_SEARCH_PATH}"
+      )
+    set(potential_bin_dirs ${potential_bin_dirs} "${path}/../bin")
+    set(potential_lib_dirs ${potential_lib_dirs} "${path}/../lib")
+    set(potential_include_dirs ${potential_include_dirs} "${path}/../include")
+  endforeach(path)
+
+endmacro(GETTEXT_FIND_POTENTIAL_DIRS)
+
+# --------------------------------------------------------------------------
+# Find the runtime lib
+
+macro(GETTEXT_FIND_RUNTIME_LIBRARY)
+
+  set(GETTEXT_RUNTIME_FOUND 1)
+
+  # The gettext intl include dir (libintl.h)
+  
+  find_path(GETTEXT_INCLUDE_DIR 
+    libintl.h 
+    ${potential_include_dirs}
+    DOC "Path to gettext include directory (where libintl.h can be found)")
+  mark_as_advanced(GETTEXT_INCLUDE_DIR)
+  if(NOT GETTEXT_INCLUDE_DIR)
+    set(GETTEXT_RUNTIME_FOUND 0)
+  endif(NOT GETTEXT_INCLUDE_DIR)
+
+  set(GETTEXT_LIBRARIES)
+
+  # The gettext intl library
+  # Some Unix system (like Linux) have gettext right into libc
+
+  if(WIN32)
+    set(HAVE_GETTEXT 0)
+  else(WIN32)
+    include(CheckFunctionExists)
+    check_function_exists(gettext HAVE_GETTEXT)
+  endif(WIN32)
+
+  if(HAVE_GETTEXT)
+    # Even if we have a system one, let the user provide another one
+    # eventually (i.e., more recent, or GNU).
+    set(GETTEXT_INTL_LIBRARY "" CACHE FILEPATH
+      "Path to gettext intl library (leave it empty to use the system one)")
+  else(HAVE_GETTEXT)
+    find_library(GETTEXT_INTL_LIBRARY 
+      NAMES intl 
+      PATHS ${potential_lib_dirs}
+      DOC "Path to gettext intl library")
+    if(NOT GETTEXT_INTL_LIBRARY)
+      set(GETTEXT_RUNTIME_FOUND 0)
+    endif(NOT GETTEXT_INTL_LIBRARY)
+  endif(HAVE_GETTEXT)
+
+  mark_as_advanced(GETTEXT_INTL_LIBRARY)
+  if(GETTEXT_INTL_LIBRARY)
+    set(GETTEXT_LIBRARIES ${GETTEXT_LIBRARIES} ${GETTEXT_INTL_LIBRARY})
+  endif(GETTEXT_INTL_LIBRARY)
+
+  # The gettext asprintf library
+  # Actually not useful as it does not seem to exist on Unix
+
+  #   IF(WIN32)
+  #     FIND_LIBRARY(GETTEXT_ASPRINTF_LIBRARY 
+  #       NAMES asprintf 
+  #       PATHS ${potential_lib_dirs}
+  #       DOC "Gettext asprintf library")
+  #     MARK_AS_ADVANCED(GETTEXT_ASPRINTF_LIBRARY)
+  #     IF(NOT GETTEXT_ASPRINTF_LIBRARY)
+  #       SET(GETTEXT_RUNTIME_FOUND 0)
+  #     ELSE(NOT GETTEXT_ASPRINTF_LIBRARY)
+  #       SET(GETTEXT_LIBRARIES ${GETTEXT_LIBRARIES} ${GETTEXT_ASPRINTF_LIBRARY})
+  #     ENDIF(NOT GETTEXT_ASPRINTF_LIBRARY)
+  #   ENDIF(WIN32)
+
+endmacro(GETTEXT_FIND_RUNTIME_LIBRARY)
+
+# --------------------------------------------------------------------------
+# Find the tools
+
+macro(GETTEXT_FIND_TOOLS)
+  set(GETTEXT_TOOLS_FOUND 1)
+  foreach(tool
+      xgettext
+      msginit
+      msgmerge
+      msgcat
+      msgconv
+      msgfmt
+      )
+    string(TOUPPER ${tool} tool_upper)
+    find_program(GETTEXT_${tool_upper}_EXECUTABLE
+      NAMES ${tool} 
+      PATHS ${potential_bin_dirs}
+      DOC "Path to gettext ${tool} tool")
+    mark_as_advanced(GETTEXT_${tool_upper}_EXECUTABLE)
+    if(NOT GETTEXT_${tool_upper}_EXECUTABLE)
+      set(GETTEXT_TOOLS_FOUND 0)
+    endif(NOT GETTEXT_${tool_upper}_EXECUTABLE)
+  endforeach(tool)
+endmacro(GETTEXT_FIND_TOOLS)
+
+# --------------------------------------------------------------------------
+# Some convenient info about gettext, where to get it, etc.
+
+set(GETTEXT_INFO_MSG "More information about gettext can be found at http://directory.fsf.org/gettext.html.")
+if(WIN32)
+  set(GETTEXT_INFO_MSG "${GETTEXT_INFO_MSG} Windows users can download gettext-runtime-0.13.1.bin.woe32.zip (LGPL), gettext-tools-0.13.1.bin.woe32.zip (GPL) as well as libiconv-1.9.1.bin.woe32.zip (LGPL) from any GNU mirror (say, http://mirrors.kernel.org/gnu/gettext/ and http://mirrors.kernel.org/gnu/libiconv/), unpack the archives in the same directory, then set GETTEXT_INTL_LIBRARY to 'lib/intl.lib' in and GETTEXT_INCLUDE_DIR to 'include' in that directory.\n\nWarning: if you are usin [...]
+endif(WIN32)
+
+# --------------------------------------------------------------------------
+# Found ?
+
+gettext_find_potential_dirs()
+gettext_find_runtime_library()
+gettext_find_tools()
+
+# Try again with new potential dirs now that we may have found the runtime
+# or the tools
+
+gettext_find_potential_dirs()
+if(NOT GETTEXT_RUNTIME_FOUND)
+  gettext_find_runtime_library()
+endif(NOT GETTEXT_RUNTIME_FOUND)
+if(NOT GETTEXT_TOOLS_FOUND)
+  gettext_find_tools()
+endif(NOT GETTEXT_TOOLS_FOUND)
+
+if(GETTEXT_RUNTIME_FOUND AND GETTEXT_TOOLS_FOUND)
+  set(GETTEXT_FOUND 1)
+else(GETTEXT_RUNTIME_FOUND AND GETTEXT_TOOLS_FOUND)
+  set(GETTEXT_FOUND 0)
+endif(GETTEXT_RUNTIME_FOUND AND GETTEXT_TOOLS_FOUND)
+
+if(NOT GETTEXT_FOUND AND NOT Gettext_FIND_QUIETLY AND Gettext_FIND_REQUIRED)
+  message(FATAL_ERROR "Could not find gettext runtime library and tools for internationalization purposes.\n\n${GETTEXT_INFO_MSG}")
+endif(NOT GETTEXT_FOUND AND NOT Gettext_FIND_QUIETLY AND Gettext_FIND_REQUIRED)
diff --git a/cmake_modules/FindSDL_gfx.cmake b/cmake_modules/FindSDL_gfx.cmake
new file mode 100644
index 0000000..b883d27
--- /dev/null
+++ b/cmake_modules/FindSDL_gfx.cmake
@@ -0,0 +1,75 @@
+# Locate SDL_gfx library
+# This module defines
+# SDLGFX_LIBRARY, the name of the library to link against
+# SDLGFX_FOUND, if false, do not try to link to SDL
+# SDLGFX_INCLUDE_DIR, where to find SDL/SDL.h
+#
+# $SDLDIR is an environment variable that would
+# correspond to the ./configure --prefix=$SDLDIR
+# used in building SDL.
+#
+# Created by Eric Wing. This was influenced by the FindSDL.cmake 
+# module, but with modifications to recognize OS X frameworks and 
+# additional Unix paths (FreeBSD, etc).
+
+#=============================================================================
+# Copyright 2005-2009 Kitware, Inc.
+#
+# Distributed under the OSI-approved BSD License (the "License");
+# see accompanying file Copyright.txt for details.
+#
+# This software is distributed WITHOUT ANY WARRANTY; without even the
+# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+# See the License for more information.
+#=============================================================================
+# (To distributed this file outside of CMake, substitute the full
+#  License text for the above reference.)
+
+FIND_PATH(SDLGFX_INCLUDE_DIR SDL_gfxPrimitives.h
+  HINTS
+  $ENV{SDLGFXDIR}
+  $ENV{SDLDIR}
+  PATH_SUFFIXES include
+  PATHS
+  ~/Library/Frameworks
+  /Library/Frameworks
+  /usr/local/include/SDL
+  /usr/include/SDL
+  /usr/local/include/SDL12
+  /usr/local/include/SDL11 # FreeBSD ports
+  /usr/include/SDL12
+  /usr/include/SDL11
+  /usr/local/include
+  /usr/include
+  /sw/include/SDL # Fink
+  /sw/include
+  /opt/local/include/SDL # DarwinPorts
+  /opt/local/include
+  /opt/csw/include/SDL # Blastwave
+  /opt/csw/include 
+  /opt/include/SDL
+  /opt/include
+)
+
+FIND_LIBRARY(SDLGFX_LIBRARY 
+  NAMES SDL_gfx
+  HINTS
+  $ENV{SDLGFXDIR}
+  $ENV{SDLDIR}
+  PATH_SUFFIXES lib64 lib
+  PATHS
+  ~/Library/Frameworks
+  /Library/Frameworks
+  /usr/local
+  /usr
+  /sw
+  /opt/local
+  /opt/csw
+  /opt
+)
+
+SET(SDLGFX_FOUND "NO")
+IF(SDLGFX_LIBRARY AND SDLGFX_INCLUDE_DIR)
+  SET(SDLGFX_FOUND "YES")
+ENDIF(SDLGFX_LIBRARY AND SDLGFX_INCLUDE_DIR)
+
diff --git a/cmake_modules/FindTranslationTools.cmake b/cmake_modules/FindTranslationTools.cmake
new file mode 100755
index 0000000..4366cbf
--- /dev/null
+++ b/cmake_modules/FindTranslationTools.cmake
@@ -0,0 +1,116 @@
+# - Find the tools needed for updating the potfiles and translations
+
+set(TRANSLATION_TOOLS_FOUND true)
+
+find_program(GETTEXT_MSGINIT_EXECUTABLE msginit)
+if(NOT GETTEXT_MSGINIT_EXECUTABLE)
+	message("msginit not found")
+	set(TRANSLATION_TOOLS_FOUND false)
+endif(NOT GETTEXT_MSGINIT_EXECUTABLE)
+
+find_program(GETTEXT_XGETTEXT_EXECUTABLE xgettext)
+if(NOT GETTEXT_XGETTEXT_EXECUTABLE)
+	message("xgettext not found")
+	set(TRANSLATION_TOOLS_FOUND false)
+endif(NOT GETTEXT_XGETTEXT_EXECUTABLE)
+set(GETTEXT_XGETTEXT_OPTIONS
+	--force-po
+	--add-comments=TRANSLATORS 
+	--copyright-holder=\"SITPLUS Project\"
+	--msgid-bugs-address=\"cesar at crea-si.com/\"
+	--from-code=UTF-8
+	--sort-by-file
+	--keyword=_
+	--keyword=__
+	--keyword=N_
+	--keyword=N__
+	--keyword=sgettext
+	--keyword=vgettext
+	--keyword=VGETTEXT
+	--keyword=_n:1,2
+	--keyword=sngettext:1,2
+	--keyword=vngettext:1,2
+)
+
+find_program(GETTEXT_MSGCAT_EXECUTABLE msgcat)
+if(NOT GETTEXT_MSGCAT_EXECUTABLE )
+	message("msgcat not found")
+	set(TRANSLATION_TOOLS_FOUND false)
+endif(NOT GETTEXT_MSGCAT_EXECUTABLE )
+
+find_program(GETTEXT_MSGATTRIB_EXECUTABLE msgattrib)
+if(NOT GETTEXT_MSGATTRIB_EXECUTABLE)
+	message("msgattrib not found")
+	set(TRANSLATION_TOOLS_FOUND false)
+endif(NOT GETTEXT_MSGATTRIB_EXECUTABLE)
+
+#find_program(ASCIIDOC_EXECUTABLE asciidoc)
+#set(ASCIIDOC_OPTIONS
+#	-b docbook
+#	-d book
+#	-n
+#	-a toc
+#)
+#if(NOT ASCIIDOC_EXECUTABLE)
+#	message("asciidoc not found")
+#	set(TRANSLATION_TOOLS_FOUND false)
+#endif(NOT ASCIIDOC_EXECUTABLE)
+
+#find_program(DOS2UNIX_EXECUTABLE dos2unix)
+#if(NOT DOS2UNIX_EXECUTABLE)
+#	message("dos2unix not found")
+#	set(TRANSLATION_TOOLS_FOUND false)
+#endif(NOT DOS2UNIX_EXECUTABLE)
+
+#find_program(PO4A-TRANSLATE_EXECUTABLE po4a-translate)
+#set(PO4A-TRANSLATE_OPTIONS
+#	-f docbook
+#	-k 80
+#	-M utf-8
+#	-L utf-8
+#)
+#if(NOT PO4A-TRANSLATE_EXECUTABLE)
+#	message("po4a-translate not found")
+#	set(TRANSLATION_TOOLS_FOUND false)
+#endif(NOT PO4A-TRANSLATE_EXECUTABLE)
+
+#find_program(PO4A-UPDATEPO_EXECUTABLE po4a-updatepo)
+#set(PO4A-UPDATEPO_OPTIONS
+#	-M utf-8
+#)
+#if(NOT PO4A-UPDATEPO_EXECUTABLE)
+#	message("po4a-updatepo not found")
+#	set(TRANSLATION_TOOLS_FOUND false)
+#endif(NOT PO4A-UPDATEPO_EXECUTABLE)
+
+#find_program(PO4A-GETTEXTIZE_EXECUTABLE po4a-gettextize)
+#set(PO4A-GETTEXTIZE_OPTIONS
+#	--copyright-holder "Wesnoth Development Team"
+#	-f docbook
+#	-M utf-8
+#	-L utf-8
+#)
+#if(NOT PO4A-GETTEXTIZE_EXECUTABLE)
+#	message("po4a-gettextize not found")
+#	set(TRANSLATION_TOOLS_FOUND false)
+#endif(NOT PO4A-GETTEXTIZE_EXECUTABLE)
+
+#find_program(XSLTPROC_EXECUTABLE xsltproc)
+#set(XSLTPROC_OPTIONS
+#	--nonet
+#	--stringparam callout.graphics 0
+#	--stringparam navig.graphics 0
+#	--stringparam admon.textlabel 1
+#	--stringparam admon.graphics 0
+#	--stringparam html.stylesheet "./styles/manual.css"
+#)
+#if(NOT XSLTPROC_EXECUTABLE)
+#	message("xsltproc not found")
+#	set(TRANSLATION_TOOLS_FOUND false)
+#endif(NOT XSLTPROC_EXECUTABLE)
+
+#if(NOT TRANSLATION_TOOLS_FOUND)
+#	if(TranslationTools_FIND_REQUIRED)
+#		message(FATAL_ERROR "Not all translation tools are found")
+#	endif(TranslationTools_FIND_REQUIRED)
+#endif(NOT TRANSLATION_TOOLS_FOUND)
diff --git a/cmake_modules/MacroLogFeature.cmake b/cmake_modules/MacroLogFeature.cmake
new file mode 100644
index 0000000..797c431
--- /dev/null
+++ b/cmake_modules/MacroLogFeature.cmake
@@ -0,0 +1,134 @@
+#-------------------------------------------------------------------
+# This file is part of the CMake build system for OGRE
+#     (Object-oriented Graphics Rendering Engine)
+# For the latest info, see http://www.ogre3d.org/
+#
+# The contents of this file are placed in the public domain. Feel
+# free to make use of it in any way you like.
+#-------------------------------------------------------------------
+
+# This file defines the Feature Logging macros.
+#
+# MACRO_LOG_FEATURE(VAR FEATURE DESCRIPTION URL [REQUIRED [MIN_VERSION [COMMENTS]]])
+#   Logs the information so that it can be displayed at the end
+#   of the configure run
+#   VAR : TRUE or FALSE, indicating whether the feature is supported
+#   FEATURE: name of the feature, e.g. "libjpeg"
+#   DESCRIPTION: description what this feature provides
+#   URL: home page
+#   REQUIRED: TRUE or FALSE, indicating whether the featue is required
+#   MIN_VERSION: minimum version number. empty string if unneeded
+#   COMMENTS: More info you may want to provide.  empty string if unnecessary
+#
+# MACRO_DISPLAY_FEATURE_LOG()
+#   Call this to display the collected results.
+#   Exits CMake with a FATAL error message if a required feature is missing
+#
+# Example:
+#
+# INCLUDE(MacroLogFeature)
+#
+# FIND_PACKAGE(JPEG)
+# MACRO_LOG_FEATURE(JPEG_FOUND "libjpeg" "Support JPEG images" "http://www.ijg.org" TRUE "3.2a" "")
+# ...
+# MACRO_DISPLAY_FEATURE_LOG()
+
+# Copyright (c) 2006, Alexander Neundorf, <neundorf at kde.org>
+# Copyright (c) 2006, Allen Winter, <winter at kde.org>
+#
+# Redistribution and use is allowed according to the terms of the BSD license.
+# For details see the accompanying COPYING-CMAKE-SCRIPTS file.
+
+IF (NOT _macroLogFeatureAlreadyIncluded)
+   SET(_file ${OGRE_BINARY_DIR}/MissingRequirements.txt)
+   IF (EXISTS ${_file})
+      FILE(REMOVE ${_file})
+   ENDIF (EXISTS ${_file})
+
+   SET(_file ${OGRE_BINARY_DIR}/EnabledFeatures.txt)
+   IF (EXISTS ${_file})
+      FILE(REMOVE ${_file})
+   ENDIF (EXISTS ${_file})
+
+   SET(_file ${OGRE_BINARY_DIR}/DisabledFeatures.txt)
+   IF (EXISTS ${_file})
+      FILE(REMOVE ${_file})
+  ENDIF (EXISTS ${_file})
+
+  SET(_macroLogFeatureAlreadyIncluded TRUE)
+ENDIF (NOT _macroLogFeatureAlreadyIncluded)
+
+
+MACRO(MACRO_LOG_FEATURE _var _package _description _url ) # _required _minvers _comments)
+
+   SET(_required "${ARGV4}")
+   SET(_minvers "${ARGV5}")
+   SET(_comments "${ARGV6}")
+
+   IF (${_var})
+     SET(_LOGFILENAME ${OGRE_BINARY_DIR}/EnabledFeatures.txt)
+   ELSE (${_var})
+     IF (${_required} MATCHES "[Tt][Rr][Uu][Ee]")
+       SET(_LOGFILENAME ${OGRE_BINARY_DIR}/MissingRequirements.txt)
+     ELSE (${_required} MATCHES "[Tt][Rr][Uu][Ee]")
+       SET(_LOGFILENAME ${OGRE_BINARY_DIR}/DisabledFeatures.txt)
+     ENDIF (${_required} MATCHES "[Tt][Rr][Uu][Ee]")
+   ENDIF (${_var})
+
+   SET(_logtext "+ ${_package}")
+
+   IF (NOT ${_var})
+      IF (${_minvers} MATCHES ".*")
+        SET(_logtext "${_logtext}, ${_minvers}")
+      ENDIF (${_minvers} MATCHES ".*")
+      SET(_logtext "${_logtext}: ${_description} <${_url}>")
+      IF (${_comments} MATCHES ".*")
+        SET(_logtext "${_logtext}\n${_comments}")
+      ENDIF (${_comments} MATCHES ".*")
+#      SET(_logtext "${_logtext}\n") #double-space missing features?
+   ENDIF (NOT ${_var})
+   FILE(APPEND "${_LOGFILENAME}" "${_logtext}\n")
+ 
+ENDMACRO(MACRO_LOG_FEATURE)
+
+
+MACRO(MACRO_DISPLAY_FEATURE_LOG)
+
+   SET(_file ${OGRE_BINARY_DIR}/MissingRequirements.txt)
+   IF (EXISTS ${_file})
+      FILE(READ ${_file} _requirements)
+      MESSAGE(FATAL_ERROR "\n-----------------------------------------------------------------------------\n-- The following REQUIRED packages could NOT be located on your system.\n-- Please install them before continuing this software installation.\n-- If you are in Windows, try passing -DOGRE_DEPENDENCIES_DIR=<path to dependencies>\n-----------------------------------------------------------------------------\n${_requirements}------------------------------------------------------------ [...]
+      FILE(REMOVE ${_file})
+      MESSAGE(FATAL_ERROR "Exiting: Missing Requirements")
+   ENDIF (EXISTS ${_file})
+
+   SET(_summary "\n")
+
+   SET(_elist 0)
+   SET(_file ${OGRE_BINARY_DIR}/EnabledFeatures.txt)
+   IF (EXISTS ${_file})
+      SET(_elist 1)
+      FILE(READ ${_file} _enabled)
+      FILE(REMOVE ${_file})
+      SET(_summary "${_summary}-----------------------------------------------------------------------------\n-- The following external packages were located on your system.\n-- This installation will have the extra features provided by these packages.\n${_enabled}")
+   ENDIF (EXISTS ${_file})
+
+   SET(_dlist 0)
+   SET(_file ${OGRE_BINARY_DIR}/DisabledFeatures.txt)
+   IF (EXISTS ${_file})
+      SET(_dlist 1)
+      FILE(READ ${_file} _disabled)
+      FILE(REMOVE ${_file})
+      SET(_summary "${_summary}-----------------------------------------------------------------------------\n-- The following OPTIONAL packages could NOT be located on your system.\n-- Consider installing them to enable more features from this software.\n${_disabled}")
+   ELSE (EXISTS ${_file})
+      IF (${_elist})
+        SET(_summary "${_summary}Congratulations! All external packages have been found.\n")
+      ENDIF (${_elist})
+   ENDIF (EXISTS ${_file})
+
+   IF (${_elist} OR ${_dlist})
+      SET(_summary "${_summary}-----------------------------------------------------------------------------\n")
+   ENDIF (${_elist} OR ${_dlist})
+   MESSAGE(STATUS "${_summary}")
+
+ENDMACRO(MACRO_DISPLAY_FEATURE_LOG)
diff --git a/cmake_modules/README.txt b/cmake_modules/README.txt
new file mode 100755
index 0000000..7569518
--- /dev/null
+++ b/cmake_modules/README.txt
@@ -0,0 +1,10 @@
+Files:
+
+	FindLibintl.cmake
+	FindPotupdate.cmake
+	FindTranslationTools.cmake
+
+adapted from original versions in:
+http://svn.gna.org/viewcvs/wesnoth/trunk	
+
+
diff --git a/cmake_modules/update_pot_source_dependencies.cmake b/cmake_modules/update_pot_source_dependencies.cmake
new file mode 100644
index 0000000..af5d14d
--- /dev/null
+++ b/cmake_modules/update_pot_source_dependencies.cmake
@@ -0,0 +1,40 @@
+# Update the source file dependencies of the pot file.
+#
+# This globs all files h and cpp in the src and include directories 
+#
+# Remove the old input file.
+# Dummy target with a non existing (and not created file) is always executed.
+add_custom_command(
+	OUTPUT ${PROJECT_SOURCE_DIR}/po/${DOMAIN}/POTFILES.in.dummy
+	# remove the old file.
+	COMMAND ${CMAKE_COMMAND} 
+			-E remove ${PROJECT_SOURCE_DIR}/po/${DOMAIN}/POTFILES.in
+	COMMENT "pot-update [${DOMAIN}]: Removed existing POTFILES.in."
+)
+
+add_custom_command(
+	OUTPUT ${PROJECT_SOURCE_DIR}/po/${DOMAIN}/POTFILES.in
+
+	# Create an empty new one, to be sure it will exist.
+	COMMAND ${CMAKE_COMMAND} 
+			-E touch ${PROJECT_SOURCE_DIR}/po/${DOMAIN}/POTFILES.in
+
+	# Find all h and cpp files
+	COMMAND find src -name '*h' -print -o -name '*cpp' -print |
+			sort |
+			while read file\; do
+				echo $$file >> 
+					${PROJECT_SOURCE_DIR}/po/${DOMAIN}/POTFILES.in \;
+			done
+	COMMAND find include -name '*h' -print |
+			sort |
+			while read file\; do
+				echo $$file >> 
+					${PROJECT_SOURCE_DIR}/po/${DOMAIN}/POTFILES.in \;
+			done
+
+	DEPENDS ${PROJECT_SOURCE_DIR}/po/${DOMAIN}/POTFILES.in.dummy
+	WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
+	COMMENT 
+		"pot-update [${DOMAIN}]: Created POTFILES.in for ${DOMAIN} domain."
+)
diff --git a/doc/CMakeLists.txt b/doc/CMakeLists.txt
new file mode 100755
index 0000000..f1a7681
--- /dev/null
+++ b/doc/CMakeLists.txt
@@ -0,0 +1,63 @@
+cmake_minimum_required(VERSION 2.8)
+
+set(ASCIIDOC_FILES
+	script_syntax
+)
+
+# Generate list of html files
+unset(ASCIIDOC_FILES_HTML)
+unset(ASCIIDOC_FILES_HTML_DEST)
+foreach(ASCIIDOC_FILE ${ASCIIDOC_FILES})
+	set (ASCIIDOC_FILES_HTML
+		${ASCIIDOC_FILES_HTML}
+		${ASCIIDOC_FILE}.html
+	)
+	set (ASCIIDOC_FILES_HTML_DEST
+		${ASCIIDOC_FILES_HTML_DEST}
+		${CMAKE_BINARY_DIR}/${DOCDIR}/${ASCIIDOC_FILE}.html
+	)
+endforeach(ASCIIDOC_FILE ${ASCIIDOC_FILES})	
+
+#	
+# We do not expect to find asciidoc, especially on Windows systems, so we
+# keep a copy of the .html files in source tree
+#	
+
+find_program(ASCIIDOC_EXECUTABLE asciidoc)
+set(ASCIIDOC_OPTIONS )
+if(NOT ASCIIDOC_EXECUTABLE)
+	if(WIN32)
+		message(STATUS "Warning: asciidoc not found")
+	else(WIN32)
+		message(WARNING "asciidoc not found")
+	endif(WIN32)
+endif(NOT ASCIIDOC_EXECUTABLE)
+	
+foreach(ASCIIDOC_FILE ${ASCIIDOC_FILES})
+	if(ASCIIDOC_EXECUTABLE)
+		# Generate html file from ascii files (if asciidoc present)
+		add_custom_command(
+			OUTPUT ${CMAKE_CURRENT_SOURCE_DIR}/${ASCIIDOC_FILE}.html
+			COMMAND ${ASCIIDOC_EXECUTABLE} ${ASCIIDOC_OPTIONS} ${ASCIIDOC_FILE}.txt
+			DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/${ASCIIDOC_FILE}.txt
+			WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
+			COMMENT "doc-update [${ASCIIDOC_FILE}]: Generated html doc file."
+		)
+	endif(ASCIIDOC_EXECUTABLE)
+	
+	# Copy file 
+	add_custom_command(
+		OUTPUT ${CMAKE_BINARY_DIR}/${DOCDIR}/${ASCIIDOC_FILE}.html
+		COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/${ASCIIDOC_FILE}.html ${CMAKE_BINARY_DIR}/${DOCDIR}/${ASCIIDOC_FILE}.html
+		DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/${ASCIIDOC_FILE}.html
+		WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
+		COMMENT "doc-update [${ASCIIDOC_FILE}]: Copied html doc file."
+	)
+endforeach(ASCIIDOC_FILE ${ASCIIDOC_FILES})
+
+add_custom_target(doc-update
+	COMMENT "doc-update: Done."
+	DEPENDS ${ASCIIDOC_FILES_HTML_DEST}	
+)
+
+install(FILES ${ASCIIDOC_FILES_HTML_DEST} DESTINATION "${DOCDIR}")
diff --git a/doc/script_syntax.html b/doc/script_syntax.html
new file mode 100644
index 0000000..fe36339
--- /dev/null
+++ b/doc/script_syntax.html
@@ -0,0 +1,776 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
+    "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+<meta name="generator" content="AsciiDoc 8.5.2" />
+<title>libsitplus script interpreter syntax</title>
+<style type="text/css">
+/* Debug borders */
+p, li, dt, dd, div, pre, h1, h2, h3, h4, h5, h6 {
+/*
+  border: 1px solid red;
+*/
+}
+
+body {
+  margin: 1em 5% 1em 5%;
+}
+
+a {
+  color: blue;
+  text-decoration: underline;
+}
+a:visited {
+  color: fuchsia;
+}
+
+em {
+  font-style: italic;
+  color: navy;
+}
+
+strong {
+  font-weight: bold;
+  color: #083194;
+}
+
+tt {
+  color: navy;
+}
+
+h1, h2, h3, h4, h5, h6 {
+  color: #527bbd;
+  font-family: sans-serif;
+  margin-top: 1.2em;
+  margin-bottom: 0.5em;
+  line-height: 1.3;
+}
+
+h1, h2, h3 {
+  border-bottom: 2px solid silver;
+}
+h2 {
+  padding-top: 0.5em;
+}
+h3 {
+  float: left;
+}
+h3 + * {
+  clear: left;
+}
+
+div.sectionbody {
+  font-family: serif;
+  margin-left: 0;
+}
+
+hr {
+  border: 1px solid silver;
+}
+
+p {
+  margin-top: 0.5em;
+  margin-bottom: 0.5em;
+}
+
+ul, ol, li > p {
+  margin-top: 0;
+}
+
+pre {
+  padding: 0;
+  margin: 0;
+}
+
+span#author {
+  color: #527bbd;
+  font-family: sans-serif;
+  font-weight: bold;
+  font-size: 1.1em;
+}
+span#email {
+}
+span#revnumber, span#revdate, span#revremark {
+  font-family: sans-serif;
+}
+
+div#footer {
+  font-family: sans-serif;
+  font-size: small;
+  border-top: 2px solid silver;
+  padding-top: 0.5em;
+  margin-top: 4.0em;
+}
+div#footer-text {
+  float: left;
+  padding-bottom: 0.5em;
+}
+div#footer-badges {
+  float: right;
+  padding-bottom: 0.5em;
+}
+
+div#preamble {
+  margin-top: 1.5em;
+  margin-bottom: 1.5em;
+}
+div.tableblock, div.imageblock, div.exampleblock, div.verseblock,
+div.quoteblock, div.literalblock, div.listingblock, div.sidebarblock,
+div.admonitionblock {
+  margin-top: 1.0em;
+  margin-bottom: 1.5em;
+}
+div.admonitionblock {
+  margin-top: 2.0em;
+  margin-bottom: 2.0em;
+  margin-right: 10%;
+  color: #606060;
+}
+
+div.content { /* Block element content. */
+  padding: 0;
+}
+
+/* Block element titles. */
+div.title, caption.title {
+  color: #527bbd;
+  font-family: sans-serif;
+  font-weight: bold;
+  text-align: left;
+  margin-top: 1.0em;
+  margin-bottom: 0.5em;
+}
+div.title + * {
+  margin-top: 0;
+}
+
+td div.title:first-child {
+  margin-top: 0.0em;
+}
+div.content div.title:first-child {
+  margin-top: 0.0em;
+}
+div.content + div.title {
+  margin-top: 0.0em;
+}
+
+div.sidebarblock > div.content {
+  background: #ffffee;
+  border: 1px solid silver;
+  padding: 0.5em;
+}
+
+div.listingblock > div.content {
+  border: 1px solid silver;
+  background: #f4f4f4;
+  padding: 0.5em;
+}
+
+div.quoteblock, div.verseblock {
+  padding-left: 1.0em;
+  margin-left: 1.0em;
+  margin-right: 10%;
+  border-left: 5px solid #dddddd;
+  color: #777777;
+}
+
+div.quoteblock > div.attribution {
+  padding-top: 0.5em;
+  text-align: right;
+}
+
+div.verseblock > div.content {
+  white-space: pre;
+}
+div.verseblock > div.attribution {
+  padding-top: 0.75em;
+  text-align: left;
+}
+/* DEPRECATED: Pre version 8.2.7 verse style literal block. */
+div.verseblock + div.attribution {
+  text-align: left;
+}
+
+div.admonitionblock .icon {
+  vertical-align: top;
+  font-size: 1.1em;
+  font-weight: bold;
+  text-decoration: underline;
+  color: #527bbd;
+  padding-right: 0.5em;
+}
+div.admonitionblock td.content {
+  padding-left: 0.5em;
+  border-left: 3px solid #dddddd;
+}
+
+div.exampleblock > div.content {
+  border-left: 3px solid #dddddd;
+  padding-left: 0.5em;
+}
+
+div.imageblock div.content { padding-left: 0; }
+span.image img { border-style: none; }
+a.image:visited { color: white; }
+
+dl {
+  margin-top: 0.8em;
+  margin-bottom: 0.8em;
+}
+dt {
+  margin-top: 0.5em;
+  margin-bottom: 0;
+  font-style: normal;
+  color: navy;
+}
+dd > *:first-child {
+  margin-top: 0.1em;
+}
+
+ul, ol {
+    list-style-position: outside;
+}
+ol.arabic {
+  list-style-type: decimal;
+}
+ol.loweralpha {
+  list-style-type: lower-alpha;
+}
+ol.upperalpha {
+  list-style-type: upper-alpha;
+}
+ol.lowerroman {
+  list-style-type: lower-roman;
+}
+ol.upperroman {
+  list-style-type: upper-roman;
+}
+
+div.compact ul, div.compact ol,
+div.compact p, div.compact p,
+div.compact div, div.compact div {
+  margin-top: 0.1em;
+  margin-bottom: 0.1em;
+}
+
+div.tableblock > table {
+  border: 3px solid #527bbd;
+}
+thead, p.table.header {
+  font-family: sans-serif;
+  font-weight: bold;
+}
+tfoot {
+  font-weight: bold;
+}
+td > div.verse {
+  white-space: pre;
+}
+p.table {
+  margin-top: 0;
+}
+/* Because the table frame attribute is overriden by CSS in most browsers. */
+div.tableblock > table[frame="void"] {
+  border-style: none;
+}
+div.tableblock > table[frame="hsides"] {
+  border-left-style: none;
+  border-right-style: none;
+}
+div.tableblock > table[frame="vsides"] {
+  border-top-style: none;
+  border-bottom-style: none;
+}
+
+
+div.hdlist {
+  margin-top: 0.8em;
+  margin-bottom: 0.8em;
+}
+div.hdlist tr {
+  padding-bottom: 15px;
+}
+dt.hdlist1.strong, td.hdlist1.strong {
+  font-weight: bold;
+}
+td.hdlist1 {
+  vertical-align: top;
+  font-style: normal;
+  padding-right: 0.8em;
+  color: navy;
+}
+td.hdlist2 {
+  vertical-align: top;
+}
+div.hdlist.compact tr {
+  margin: 0;
+  padding-bottom: 0;
+}
+
+.comment {
+  background: yellow;
+}
+
+.footnote, .footnoteref {
+  font-size: 0.8em;
+}
+
+span.footnote, span.footnoteref {
+  vertical-align: super;
+}
+
+#footnotes {
+  margin: 20px 0 20px 0;
+  padding: 7px 0 0 0;
+}
+
+#footnotes div.footnote {
+  margin: 0 0 5px 0;
+}
+
+#footnotes hr {
+  border: none;
+  border-top: 1px solid silver;
+  height: 1px;
+  text-align: left;
+  margin-left: 0;
+  width: 20%;
+  min-width: 100px;
+}
+
+
+ at media print {
+  div#footer-badges { display: none; }
+}
+
+div#toc {
+  margin-bottom: 2.5em;
+}
+
+div#toctitle {
+  color: #527bbd;
+  font-family: sans-serif;
+  font-size: 1.1em;
+  font-weight: bold;
+  margin-top: 1.0em;
+  margin-bottom: 0.1em;
+}
+
+div.toclevel1, div.toclevel2, div.toclevel3, div.toclevel4 {
+  margin-top: 0;
+  margin-bottom: 0;
+}
+div.toclevel2 {
+  margin-left: 2em;
+  font-size: 0.9em;
+}
+div.toclevel3 {
+  margin-left: 4em;
+  font-size: 0.9em;
+}
+div.toclevel4 {
+  margin-left: 6em;
+  font-size: 0.9em;
+}
+/* Workarounds for IE6's broken and incomplete CSS2. */
+
+div.sidebar-content {
+  background: #ffffee;
+  border: 1px solid silver;
+  padding: 0.5em;
+}
+div.sidebar-title, div.image-title {
+  color: #527bbd;
+  font-family: sans-serif;
+  font-weight: bold;
+  margin-top: 0.0em;
+  margin-bottom: 0.5em;
+}
+
+div.listingblock div.content {
+  border: 1px solid silver;
+  background: #f4f4f4;
+  padding: 0.5em;
+}
+
+div.quoteblock-attribution {
+  padding-top: 0.5em;
+  text-align: right;
+}
+
+div.verseblock-content {
+  white-space: pre;
+}
+div.verseblock-attribution {
+  padding-top: 0.75em;
+  text-align: left;
+}
+
+div.exampleblock-content {
+  border-left: 3px solid #dddddd;
+  padding-left: 0.5em;
+}
+
+/* IE6 sets dynamically generated links as visited. */
+div#toc a:visited { color: blue; }
+</style>
+<script type="text/javascript">
+/*<![CDATA[*/
+window.onload = function(){asciidoc.footnotes();}
+var asciidoc = {  // Namespace.
+
+/////////////////////////////////////////////////////////////////////
+// Table Of Contents generator
+/////////////////////////////////////////////////////////////////////
+
+/* Author: Mihai Bazon, September 2002
+ * http://students.infoiasi.ro/~mishoo
+ *
+ * Table Of Content generator
+ * Version: 0.4
+ *
+ * Feel free to use this script under the terms of the GNU General Public
+ * License, as long as you do not remove or alter this notice.
+ */
+
+ /* modified by Troy D. Hanson, September 2006. License: GPL */
+ /* modified by Stuart Rackham, 2006, 2009. License: GPL */
+
+// toclevels = 1..4.
+toc: function (toclevels) {
+
+  function getText(el) {
+    var text = "";
+    for (var i = el.firstChild; i != null; i = i.nextSibling) {
+      if (i.nodeType == 3 /* Node.TEXT_NODE */) // IE doesn't speak constants.
+        text += i.data;
+      else if (i.firstChild != null)
+        text += getText(i);
+    }
+    return text;
+  }
+
+  function TocEntry(el, text, toclevel) {
+    this.element = el;
+    this.text = text;
+    this.toclevel = toclevel;
+  }
+
+  function tocEntries(el, toclevels) {
+    var result = new Array;
+    var re = new RegExp('[hH]([2-'+(toclevels+1)+'])');
+    // Function that scans the DOM tree for header elements (the DOM2
+    // nodeIterator API would be a better technique but not supported by all
+    // browsers).
+    var iterate = function (el) {
+      for (var i = el.firstChild; i != null; i = i.nextSibling) {
+        if (i.nodeType == 1 /* Node.ELEMENT_NODE */) {
+          var mo = re.exec(i.tagName);
+          if (mo && (i.getAttribute("class") || i.getAttribute("className")) != "float") {
+            result[result.length] = new TocEntry(i, getText(i), mo[1]-1);
+          }
+          iterate(i);
+        }
+      }
+    }
+    iterate(el);
+    return result;
+  }
+
+  var toc = document.getElementById("toc");
+  var entries = tocEntries(document.getElementById("content"), toclevels);
+  for (var i = 0; i < entries.length; ++i) {
+    var entry = entries[i];
+    if (entry.element.id == "")
+      entry.element.id = "_toc_" + i;
+    var a = document.createElement("a");
+    a.href = "#" + entry.element.id;
+    a.appendChild(document.createTextNode(entry.text));
+    var div = document.createElement("div");
+    div.appendChild(a);
+    div.className = "toclevel" + entry.toclevel;
+    toc.appendChild(div);
+  }
+  if (entries.length == 0)
+    toc.parentNode.removeChild(toc);
+},
+
+
+/////////////////////////////////////////////////////////////////////
+// Footnotes generator
+/////////////////////////////////////////////////////////////////////
+
+/* Based on footnote generation code from:
+ * http://www.brandspankingnew.net/archive/2005/07/format_footnote.html
+ */
+
+footnotes: function () {
+  var cont = document.getElementById("content");
+  var noteholder = document.getElementById("footnotes");
+  var spans = cont.getElementsByTagName("span");
+  var refs = {};
+  var n = 0;
+  for (i=0; i<spans.length; i++) {
+    if (spans[i].className == "footnote") {
+      n++;
+      // Use [\s\S] in place of . so multi-line matches work.
+      // Because JavaScript has no s (dotall) regex flag.
+      note = spans[i].innerHTML.match(/\s*\[([\s\S]*)]\s*/)[1];
+      noteholder.innerHTML +=
+        "<div class='footnote' id='_footnote_" + n + "'>" +
+        "<a href='#_footnoteref_" + n + "' title='Return to text'>" +
+        n + "</a>. " + note + "</div>";
+      spans[i].innerHTML =
+        "[<a id='_footnoteref_" + n + "' href='#_footnote_" + n +
+        "' title='View footnote' class='footnote'>" + n + "</a>]";
+      var id =spans[i].getAttribute("id");
+      if (id != null) refs["#"+id] = n;
+    }
+  }
+  if (n == 0)
+    noteholder.parentNode.removeChild(noteholder);
+  else {
+    // Process footnoterefs.
+    for (i=0; i<spans.length; i++) {
+      if (spans[i].className == "footnoteref") {
+        var href = spans[i].getElementsByTagName("a")[0].getAttribute("href");
+        href = href.match(/#.*/)[0];  // Because IE return full URL.
+        n = refs[href];
+        spans[i].innerHTML =
+          "[<a href='#_footnote_" + n +
+          "' title='View footnote' class='footnote'>" + n + "</a>]";
+      }
+    }
+  }
+}
+
+}
+/*]]>*/
+</script>
+</head>
+<body>
+<div id="header">
+<h1>libsitplus script interpreter syntax</h1>
+<span id="author">Cesar Mauri</span><br />
+<span id="email"><tt><<a href="mailto:cesar at crea-si.com">cesar at crea-si.com</a>></tt></span><br />
+</div>
+<div id="content">
+<div id="preamble">
+<div class="sectionbody">
+<div class="paragraph"><p>This document the syntax of the scripting language used by the libsitplus
+project. These scripts usually have the .sp and .sps extensions.</p></div>
+</div>
+</div>
+<h2 id="_comments">Comments</h2>
+<div class="sectionbody">
+<div class="paragraph"><p>Line comments start with <em>#</em>.</p></div>
+<div class="paragraph"><p>Blank lines are ignored.</p></div>
+</div>
+<h2 id="_commands">Commands</h2>
+<div class="sectionbody">
+<div class="dlist"><dl>
+<dt class="hdlist1">
+<strong><tt>type <id></tt></strong>
+</dt>
+<dd>
+<p>
+        Sets the name which identifies the component class that is being
+        defined. Used when creating (see create below) instances of this component.
+</p>
+</dd>
+<dt class="hdlist1">
+<strong><tt>name <name></tt></strong>
+</dt>
+<dd>
+<p>
+        Name given to the component. Must appear at the very beginning
+        of the script, otherwise parsing will fail. It is usually used as a title
+        for GUI elements.
+</p>
+</dd>
+<dt class="hdlist1">
+<strong><tt>args <arguments_declaration></tt></strong>
+</dt>
+<dd>
+<p>
+        Allows to declare the formal parameters that the component expects. Each
+        parameter name must begin with a dash <tt>-</tt>. Once declared an argument
+        can be used inside the script by just enclosing its name between <tt>$</tt>
+        symbols. That is, if the argument is called <tt>-v</tt>, you can       instantiate it by
+        writing <tt>$-v$</tt>. When an argument is instantiated it is  simply replaced by
+        its value.
+</p>
+<div class="dlist"><dl>
+<dt class="hdlist1">
+Parameters are passed when the component is created (see <tt>create</tt> command       below) and all expected arguments are mandatory.
+</dt>
+<dt class="hdlist1">
+Apart from the formal parameters, the parameter <tt>$SP_DATA_DIR$</tt> is always       available an is replaced by the absolute path in which data files are   supposed to be.
+</dt>
+<dt class="hdlist1">
+See <tt>sp/examples/arguments</tt> for more information and examples.
+</dt>
+<dd>
+</dd>
+</dl></div>
+</dd>
+<dt class="hdlist1">
+<strong><tt>create <component type> <name> [args]</tt></strong>
+</dt>
+<dd>
+<p>
+        Creates a new component of a given type with the given name.
+        The type can refer a core registered type, a subcomponent or an imported
+        component. The name must be unique within the same scope.
+        args are optional and component dependent.
+</p>
+</dd>
+<dt class="hdlist1">
+<strong><tt>connect <src component> <src_pin> <dst component> <dst_pin></tt></strong>
+</dt>
+<dd>
+<p>
+        Connects src_pin of src component to dst_pin of dst component.
+</p>
+</dd>
+</dl></div>
+<div class="paragraph"><p><strong><tt>export_ipin <component> <pin name> [<new name> [<new type>]]</tt></strong></p></div>
+<div class="dlist"><dl>
+<dt class="hdlist1">
+<strong><tt>export_opin <component> <pin name> [<new name> [<new type>]]</tt></strong>
+</dt>
+<dd>
+<p>
+        Registers the input/output pin of a certain component as if where part of
+        this component and optionally rename it. NOTE: renaming the pin
+        actually means that     the pin name also changes for the original component.
+        If parameter new type is passed tries to change the type of the pin.
+        The new type must be only of the types registered in the core.
+        Note that changing the type is only possible for type "any" pins.
+</p>
+<div class="dlist"><dl>
+<dt class="hdlist1">
+As a rule of thumb always put the exportation statement at the end of the script or the subcomponent.
+</dt>
+<dd>
+</dd>
+</dl></div>
+</dd>
+<dt class="hdlist1">
+<strong><tt>import <file-name></tt></strong>
+</dt>
+<dd>
+<p>
+        Imports a component which is defined in an external file.
+</p>
+</dd>
+</dl></div>
+</div>
+<h2 id="_defining_subcomponents">Defining subcomponents</h2>
+<div class="sectionbody">
+<div class="paragraph"><p>Subcomponents allow to define new types of components which are
+composed of other components. Use</p></div>
+<div class="paragraph"><p><strong><tt>subcomponent</tt></strong></p></div>
+<div class="paragraph"><p>keyword to begin a subcomponent definition and end it with</p></div>
+<div class="paragraph"><p><strong><tt>subcomponent_end</tt></strong></p></div>
+</div>
+<h2 id="_conditional_statements">Conditional statements</h2>
+<div class="sectionbody">
+<div class="paragraph"><p>Execute the commands within the if, else, endif blocks depending on the
+evaluation of the condition. Operators == and != are supported for
+string comparison.</p></div>
+<div class="paragraph"><p><strong><tt>if <string1> <operator> <string2></tt></strong></p></div>
+<div class="paragraph"><p><strong><tt># executed if string1==string2</tt></strong></p></div>
+<div class="paragraph"><p><strong><tt>[else</tt></strong></p></div>
+<div class="paragraph"><p><strong><tt># executed if the condition is false]</tt></strong></p></div>
+<div class="paragraph"><p><strong><tt>endif</tt></strong></p></div>
+<div class="admonitionblock">
+<table><tr>
+<td class="icon">
+<div class="title">Note</div>
+</td>
+<td class="content">conditional statements do not have effect on commands import,
+subcomponent and subcomponent_end.</td>
+</tr></table>
+</div>
+</div>
+<h2 id="_gui_layout">GUI layout</h2>
+<div class="sectionbody">
+<div class="paragraph"><p>Each component inside a graph could provide a GUI panel. The layout definition
+allows to arrange those panels to build a consistent user interface.</p></div>
+<h3 id="_gui_layout_commands">GUI layout commands</h3><div style="clear:left"></div>
+<div class="paragraph"><p>The full layout definition must be enclosed between the commands
+<tt>begin_gui_layout</tt> and <tt>end_gui_layout</tt>.</p></div>
+<div class="paragraph"><p>The layout definition is composed of layout managers and components:</p></div>
+<div class="dlist"><dl>
+<dt class="hdlist1">
+<strong><tt>layout_begin <arg></tt></strong>
+</dt>
+<dd>
+<p>
+        Begins a layout manager. <tt>arg</tt> can be:
+</p>
+<div class="ulist"><ul>
+<li>
+<p>
+<tt>hbox [name]</tt>
+                        Horizontal box layout, if name is provided, a surrounding
+                        box with the name is painted around the enclosed GUI elements.
+</p>
+</li>
+<li>
+<p>
+<tt>vbox [name]</tt>
+                        Vertical box layout.
+</p>
+</li>
+<li>
+<p>
+<tt>book</tt>
+                        Notebook layout.
+</p>
+</li>
+<li>
+<p>
+<tt>book_page</tt>
+                        Notebook layout page.
+</p>
+</li>
+<li>
+<p>
+<tt>collapsible</tt>
+                        Panel which can be shown/hidden by pressing a button.
+</p>
+</li>
+</ul></div>
+</dd>
+<dt class="hdlist1">
+<strong><tt>layout_end</tt></strong>
+</dt>
+<dd>
+<p>
+        Ends a layout manager. Each layout_begin must have its corresponding
+        <tt>layout_end</tt>.
+</p>
+</dd>
+<dt class="hdlist1">
+<strong><tt>component <name></tt></strong>
+</dt>
+<dd>
+<p>
+        Places a component panel.
+</p>
+</dd>
+</dl></div>
+<div class="paragraph"><p>See <tt>sp/</tt> directory for more information and examples.</p></div>
+</div>
+</div>
+<div id="footnotes"><hr /></div>
+<div id="footer">
+<div id="footer-text">
+Last updated 2013-03-19 20:13:20 CEST
+</div>
+</div>
+</body>
+</html>
diff --git a/doc/script_syntax.txt b/doc/script_syntax.txt
new file mode 100755
index 0000000..a1cc0cd
--- /dev/null
+++ b/doc/script_syntax.txt
@@ -0,0 +1,135 @@
+libsitplus script interpreter syntax
+====================================
+Cesar Mauri <cesar at crea-si.com>
+
+
+This document the syntax of the scripting language used by the libsitplus 
+project. These scripts usually have the .sp and .sps extensions.
+
+Comments
+--------
+
+Line comments start with '#'. 
+
+Blank lines are ignored.
+
+Commands
+--------
+
+*`type <id>`*::
+	Sets the name which identifies the component class that is being 
+	defined. Used when creating (see create below) instances of this component.
+
+*`name <name>`*::
+
+	Name given to the component. Must appear at the very beginning	
+	of the script, otherwise parsing will fail. It is usually used as a title 	
+	for GUI elements.
+	
+*`args <arguments_declaration>`*::
+	Allows to declare the formal parameters that the component expects. Each
+	parameter name must begin with a dash `-`. Once declared an argument
+	can be used inside the script by just enclosing its name between `$` 
+	symbols. That is, if the argument is called `-v`, you can	instantiate it by
+	writing `$-v$`. When an argument is instantiated it is	simply replaced by
+	its value.
+	
+	Parameters are passed when the component is created (see `create` command	below) and all expected arguments are mandatory.;;
+	
+	Apart from the formal parameters, the parameter `$SP_DATA_DIR$` is always 	available an is replaced by the absolute path in which data files are	supposed to be.;;
+
+	See `sp/examples/arguments` for more information and examples.;;
+
+
+*`create <component type> <name> [args]`*::
+	Creates a new component of a given type with the given name.
+	The type can refer a core registered type, a subcomponent or an imported
+	component. The name must be unique within the same scope.
+	args are optional and component dependent.
+
+*`connect <src component> <src_pin> <dst component> <dst_pin>`*::
+	Connects src_pin of src component to dst_pin of dst component.
+
+*`export_ipin <component> <pin name> [<new name> [<new type>]]`*
+
+*`export_opin <component> <pin name> [<new name> [<new type>]]`*::
+	Registers the input/output pin of a certain component as if where part of
+	this component and optionally rename it. NOTE: renaming the pin 
+	actually means that	the pin name also changes for the original component.
+	If parameter new type is passed tries to change the type of the pin. 
+	The new type must be only of the types registered in the core.
+	Note that changing the type is only possible for type "any" pins.
+
+	As a rule of thumb always put the exportation statement at the end of the script or the subcomponent.;;
+
+*`import <file-name>`*::
+	Imports a component which is defined in an external file.
+
+Defining subcomponents
+----------------------
+
+Subcomponents allow to define new types of components which are 
+composed of other components. Use
+	
+*`subcomponent`*
+
+keyword to begin a subcomponent definition and end it with
+
+*`subcomponent_end`*
+
+Conditional statements
+----------------------
+Execute the commands within the if, else, endif blocks depending on the 
+evaluation of the condition. Operators == and != are supported for
+string comparison.
+
+*`if <string1> <operator> <string2>`*
+
+*`# executed if string1==string2`*
+
+*`[else`*
+
+*`# executed if the condition is false]`*
+
+*`endif`*
+
+NOTE: conditional statements do not have effect on commands import, 
+subcomponent and subcomponent_end.
+	
+GUI layout
+----------
+
+Each component inside a graph could provide a GUI panel. The layout definition
+allows to arrange those panels to build a consistent user interface.
+
+GUI layout commands
+~~~~~~~~~~~~~~~~~~~
+
+The full layout definition must be enclosed between the commands
+`begin_gui_layout` and `end_gui_layout`.
+	
+The layout definition is composed of layout managers and components:
+
+*`layout_begin <arg>`*::
+	Begins a layout manager. `arg` can be:
+	
+		- `hbox [name]`
+			Horizontal box layout, if name is provided, a surrounding 
+			box with the name is painted around the enclosed GUI elements.
+		- `vbox [name]` 
+			Vertical box layout.
+		- `book` 
+			Notebook layout.
+		- `book_page` 
+			Notebook layout page.
+		- `collapsible` 
+			Panel which can be shown/hidden by pressing a button.
+
+*`layout_end`*::
+	Ends a layout manager. Each layout_begin must have its corresponding
+	`layout_end`.
+
+*`component <name>`*::
+	Places a component panel.
+	
+See `sp/` directory for more information and examples.
diff --git a/include/config.h.in b/include/config.h.in
new file mode 100755
index 0000000..9f13e26
--- /dev/null
+++ b/include/config.h.in
@@ -0,0 +1,44 @@
+/////////////////////////////////////////////////////////////////////////////
+// File:        config.h
+// Author:      Cesar Mauri Loba (cesar at crea-si dot com)
+// Copyright:   (C) 2010-10 Cesar Mauri Loba - CREA Software Systems
+// 
+//  This program is free software: you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation, either version 3 of the License, or
+//  (at your option) any later version.
+//
+//  This program is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+/////////////////////////////////////////////////////////////////////////////
+#pragma once
+
+// uses WX
+#cmakedefine ENABLE_WXWIDGETS
+
+// uses i18n support
+#cmakedefine ENABLE_NLS
+
+#ifndef WIN32
+// This path is not realiable on Win32 because user might choose
+// a diferent directory to install
+//#define INSTALL_PREFIX "@CMAKE_INSTALL_PREFIX@"
+#endif
+
+// minimum windows version (for windows.h include)
+#ifdef WIN32
+	#ifndef _WIN32_WINNT
+		#cmakedefine _WIN32_WINNT @_WIN32_WINNT@
+	#endif
+#endif
+
+// version
+#define LIBSITPLUS_MAJOR_VERSION @LIBSITPLUS_MAJOR_VERSION@
+#define LIBSITPLUS_MINOR_VERSION @LIBSITPLUS_MINOR_VERSION@
+#define LIBSITPLUS_REVISION_VERSION @LIBSITPLUS_REVISION_VERSION@
+#define LIBSITPLUS_VERSION "@LIBSITPLUS_VERSION@"
\ No newline at end of file
diff --git a/include/mod_camera/iplimagetype.h b/include/mod_camera/iplimagetype.h
new file mode 100755
index 0000000..532bead
--- /dev/null
+++ b/include/mod_camera/iplimagetype.h
@@ -0,0 +1,59 @@
+/////////////////////////////////////////////////////////////////////////////
+// File:        iplimagetype.h
+// Author:      Cesar Mauri Loba (cesar at crea-si dot com)
+// Copyright:   (C) 2011 Cesar Mauri Loba - CREA Software Systems
+// 
+//  This program is free software: you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation, either version 3 of the License, or
+//  (at your option) any later version.
+//
+//  This program is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+/////////////////////////////////////////////////////////////////////////////
+#ifndef IPLIMAGETYPE_H
+#define IPLIMAGETYPE_H
+
+#include "spcore/pin.h"
+#include "spcore/pinimpl.h"
+#include "spcore/coreruntime.h"
+#include "spcore/basictypes.h"
+#include <cv.h>
+
+namespace mod_camera {
+/**
+	Class that carries an IplImage struct
+*/
+
+class CTypeIplImageContents : public spcore::CTypeAny {
+public:
+	static inline const char* getTypeName() { return "iplimage"; }
+	virtual const IplImage* getImage() const { return m_iplImage; }
+	virtual void setImage( IplImage* i) {
+		assert (i);
+		assert (i!= m_iplImage);
+		if (m_iplImage) cvReleaseImage( &m_iplImage );
+		m_iplImage= i;
+	}
+protected:
+	CTypeIplImageContents(int id) : CTypeAny(id) {
+		m_iplImage= NULL;
+	}
+	virtual ~CTypeIplImageContents() {
+		if (m_iplImage) cvReleaseImage( &m_iplImage );
+		m_iplImage= NULL;
+	}
+private:
+    IplImage* m_iplImage;
+};
+
+typedef spcore::SimpleType< CTypeIplImageContents > CTypeIplImage;
+
+}
+
+#endif
\ No newline at end of file
diff --git a/include/mod_camera/roitype.h b/include/mod_camera/roitype.h
new file mode 100755
index 0000000..66e2b13
--- /dev/null
+++ b/include/mod_camera/roitype.h
@@ -0,0 +1,181 @@
+/////////////////////////////////////////////////////////////////////////////
+// File:        roitype.h
+// Author:      Cesar Mauri Loba (cesar at crea-si dot com)
+// Copyright:   (C) 2011 Cesar Mauri Loba - CREA Software Systems
+// 
+//  This program is free software: you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation, either version 3 of the License, or
+//  (at your option) any later version.
+//
+//  This program is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+/////////////////////////////////////////////////////////////////////////////
+#ifndef ROITYPE_H
+#define ROITYPE_H
+
+#include "spcore/pin.h"
+#include "spcore/pinimpl.h"
+#include "spcore/coreruntime.h"
+#include "spcore/basictypes.h"
+#include "spcore/iterator.h"
+#include <vector>
+
+namespace mod_camera {
+/**
+	Class that carries a Region Of Interest (ROI)
+*/
+class CTypeROIContents;
+typedef spcore::SimpleType<CTypeROIContents> CTypeROI;
+
+class CTypeROIContents : public spcore::CTypeAny {
+public:
+	static inline const char* getTypeName() { return "roi"; }
+
+	virtual float GetX() const { return m_x; }
+	//virtual void SetX(float x) { assert (x>= 0.0f && x<= 1.0f); m_x= x; }
+	virtual float GetY() const { return m_y; }
+	//virtual void SetY(float y) { assert (y>= 0.0f && y<= 1.0f); m_y= y; }
+
+	virtual float GetWidth() const { return m_width; }
+	//virtual void SetWidth(float w) { assert (w>= 0.0f && w<= 1.0f); m_Width= w; }
+	virtual float GetHeight() const { return m_height; }
+	//virtual void SetHeight(float h) { assert (h>= 0.0f && h<= 1.0f); m_Height= h; }
+
+	// Set ROI origin
+	virtual void SetP1Move (float x, float y);
+	virtual void SetOrigin (float x, float y) { SetP1Move (x, y); }
+
+	// Resize ROI
+	virtual void SetSize (float width, float height);
+	virtual void GetSize (float& width, float& height) const;
+
+	virtual void SetP1Resize (float x, float y);	
+	virtual void SetP2Resize (float x, float y);	
+
+	virtual void SetCenter (float x, float y);
+	virtual void GetCenter (float& x, float& y) const;
+
+	virtual bool GetUseDirection() const { return m_useDirection; }
+	virtual void SetUseDirection(bool v)  { m_useDirection= v; }
+	
+	virtual float GetDirection() const { return m_direction; }
+	virtual void SetDirection(float d) { m_direction= d; }
+	
+	virtual bool GetIsVisible() const { return m_isVisible; }
+	virtual void SetIsVisible(bool v)  { m_isVisible= v; }
+	
+	virtual bool GetIsEditable() const { return m_isEditable; }
+	virtual void SetIsEditable(bool v)  { m_isEditable= v; }
+	
+	/**
+		@brief Return the drawing color of the ROI
+		@returns 32 bit int formatted as 0xAARRGGBB
+	*/
+	virtual unsigned int GetColor() const { return m_color; }
+	/**
+		@brief Sets the drawing color of the ROI
+		@param c	32 bit int formatted as 0xAARRGGBB
+	*/
+	virtual void SetColor(unsigned int c) { m_color= c; }
+
+	virtual unsigned int GetRegistrationId() const { return m_registrationId; }
+	virtual void SetRegistrationId(unsigned int id)  { m_registrationId= id; }
+	
+	virtual bool RegisterChildROI (CTypeROI* roi);
+	virtual bool UnregisterChildROI (CTypeROI* roi);
+
+	// Support composite behaviour but only allow to add ROIs
+	virtual int AddChild(SmartPtr<spcore::CTypeAny> component);
+	virtual SmartPtr<spcore::IIterator<spcore::CTypeAny*> > QueryChildren() const;
+
+protected:
+	CTypeROIContents(int id) : CTypeAny(id) {
+		m_x= m_y= 0.0f;
+		m_width= m_height= 1.0f;
+		m_useDirection= false;
+		m_direction= false;
+		m_isVisible= false;
+		m_isEditable= false;
+		m_color= 0;
+		m_registrationId= 0;		
+		m_pParentROI= NULL;
+	}
+
+	virtual ~CTypeROIContents();
+
+	virtual bool CopyTo ( CTypeAny& dst, bool ) const;
+	
+private:
+	// Normalized coordinates (0..1)
+    float m_x, m_y, m_width, m_height;
+	bool m_useDirection;
+	float m_direction; 	// In radians
+	bool m_isVisible;
+	bool m_isEditable;
+	unsigned int m_color;
+	unsigned int m_registrationId;
+
+	// ROI hierarchy
+	//typedef std::vector<CTypeROI*> ROICollection;
+	typedef std::vector<CTypeAny*> ROICollection;
+	ROICollection m_childROIs;
+	CTypeROI* m_pParentROI;
+
+	//
+	// private methods
+	//
+	// Find minimum child's P1 coordinates
+	void FindMinChildP1 (float& x, float& y) const;
+	void FindMinChildP1Rec (float& x, float& y) const;
+
+	// Find miaximum child's P2 coordinates
+	void FindMaxChildP2 (float& x, float& y) const;
+	void FindMaxChildP2Rec (float& x, float& y) const;
+
+	// Parse command line (see comment on class RoiStorage for details)
+	// 
+	// Return true if ok, false if error
+	bool ParseCommandline (int argc, const char* argv[]);
+
+	//
+	// friend access
+	//
+	friend class WXRoiControls;
+	friend class RoiStorage;
+};
+
+// Convert from normalized coordinates to real ones given a real size
+inline void Norm2Real (unsigned int width, unsigned int height, 
+		float in_x, float in_y, int & result_x, int & result_y)
+{
+	assert (in_x>= 0.0f && in_y>= 0.0f);
+	assert (width> 0);
+	assert (height> 0);
+
+	result_x= static_cast<int>(in_x * static_cast<float>(width) + 0.5f);
+	result_y= static_cast<int>(in_y * static_cast<float>(height) + 0.5f);
+}
+
+// Convert from real coordinates to normalized given a real size
+inline void Real2Norm (unsigned int width, unsigned int height, 
+		int in_x, int in_y, float & result_x, float & result_y)
+{
+	assert (width> 0);
+	assert (height> 0);
+	// we expect reasonable values
+	assert (in_x< 2000);
+	assert (in_y< 2000);
+	
+	result_x= static_cast<float>(in_x) / static_cast<float>(width);
+	result_y= static_cast<float>(in_y) / static_cast<float>(height);
+}
+
+}
+
+#endif
\ No newline at end of file
diff --git a/include/mod_midi/midi_types.h b/include/mod_midi/midi_types.h
new file mode 100644
index 0000000..a88f97d
--- /dev/null
+++ b/include/mod_midi/midi_types.h
@@ -0,0 +1,117 @@
+/////////////////////////////////////////////////////////////////////////////
+// File:        midi_types.h
+// Author:      Cesar Mauri Loba (cesar at crea-si dot com)
+// Copyright:   (C) 2011 Cesar Mauri Loba - CREA Software Systems
+//
+//  This program is free software: you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation, either version 3 of the License, or
+//  (at your option) any later version.
+//
+//  This program is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+/////////////////////////////////////////////////////////////////////////////
+#ifndef MIDI_TYPES
+#define MIDI_TYPES
+
+#include "spcore/basetypeimpl.h"
+
+namespace mod_midi {
+
+/**
+	MIDI message type
+*/
+class CTypeMIDIMessageContents : public spcore::CTypeAny {
+public:
+	static inline const char* getTypeName() { return "midi_message"; }
+
+	enum EMIDIKeys {
+		MIDI_NOTE_ON= 0x9,
+		MIDI_NOTE_OFF= 0x8,
+		MIDI_PROGRAM_CHANGE= 0xC
+	};
+
+	virtual void SetStatus (unsigned char status) {
+		m_message= (m_message & 0x00FFFF00) | status;
+	}
+
+	virtual void SetStatus (unsigned char key, unsigned char channel) {
+		assert (!(key & 0xF0));
+		assert (!(channel & 0xF0));
+		CTypeMIDIMessageContents::SetStatus ((key << 4) | channel);
+	}
+
+	virtual void SetData1 (unsigned char data1) {
+		m_message= (m_message & 0x00FF00FF) | (data1 << 8);
+	}
+
+	virtual void SetData2 (unsigned char data2) {
+		m_message= (m_message & 0x0000FFFF) | (data2 << 16);
+	}
+
+	virtual unsigned char GetStatus () const {
+		return (m_message & 0xFF);
+	}
+
+	virtual unsigned char GetKey () const {
+		return (CTypeMIDIMessageContents::GetStatus() >> 4);
+	}
+
+	virtual unsigned char GetChannel () const {
+		return (CTypeMIDIMessageContents::GetStatus() & 0xF);
+	}
+
+	virtual unsigned char GetData1 () const {
+		return ((m_message >> 8) & 0xFF);
+	}
+
+	virtual unsigned char GetData2 () const {
+		return ((m_message >> 16) & 0xFF);
+	}
+
+	virtual void SetNoteOn (unsigned char channel, unsigned char note, unsigned char velocity) {
+		assert (!(note & 0x80));
+		assert (!(velocity & 0x80));
+		CTypeMIDIMessageContents::SetStatus (MIDI_NOTE_ON, channel);
+		CTypeMIDIMessageContents::SetData1 (note);
+		CTypeMIDIMessageContents::SetData2 (velocity);
+	}
+
+	virtual void SetNoteOff (unsigned char channel, unsigned char note, unsigned char velocity) {
+		assert (!(note & 0x80));
+		assert (!(velocity & 0x80));
+		CTypeMIDIMessageContents::SetStatus (MIDI_NOTE_OFF, channel);
+		CTypeMIDIMessageContents::SetData1 (note);
+		CTypeMIDIMessageContents::SetData2 (velocity);
+	}
+
+	virtual void SetProgramChange (unsigned char channel, unsigned char instrument) {
+		assert (!(instrument & 0x80));
+		CTypeMIDIMessageContents::SetStatus (MIDI_PROGRAM_CHANGE, channel);
+		CTypeMIDIMessageContents::SetData1 (instrument);
+		CTypeMIDIMessageContents::SetData2 (0);
+	}
+
+	virtual unsigned int GetBuffer() const { return m_message; }
+
+protected:
+	CTypeMIDIMessageContents(int id)
+	: spcore::CTypeAny(id)
+	, m_message(0)
+	{}
+
+private:
+	// The three bytes of the MIDI message are stored packed
+	// in a single 32bit unsigned int
+	unsigned int m_message; //, m_timestamp;
+};
+
+typedef spcore::SimpleType<CTypeMIDIMessageContents> CTypeMIDIMessage;
+};
+
+#endif
diff --git a/include/mod_sdl/sdlsurfacetype.h b/include/mod_sdl/sdlsurfacetype.h
new file mode 100644
index 0000000..efd10df
--- /dev/null
+++ b/include/mod_sdl/sdlsurfacetype.h
@@ -0,0 +1,85 @@
+/////////////////////////////////////////////////////////////////////////////
+// File:        sdlsurfacetype.h
+// Author:      Cesar Mauri Loba (cesar at crea-si dot com)
+// Copyright:   (C) 2010 Cesar Mauri Loba - CREA Software Systems
+// 
+//  This program is free software: you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation, either version 3 of the License, or
+//  (at your option) any later version.
+//
+//  This program is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+/////////////////////////////////////////////////////////////////////////////
+#ifndef SDLSURFACETYPE_H
+#define SDLSURFACETYPE_H
+
+#include "spcore/pin.h"
+#include "spcore/pinimpl.h"
+#include "spcore/coreruntime.h"
+#include "spcore/basictypes.h"
+#include <SDL.h>
+#if defined(WIN32) && defined(ENABLE_WXWIDGETS)
+#include <wx/msw/winundef.h>
+#endif
+#include <boost/static_assert.hpp>
+
+#if defined(main)
+#undef main
+#endif
+
+
+namespace mod_sdl {
+
+/**
+	Class that carries a SDL_Surface
+*/
+
+class CTypeSDLSurfaceContents : public spcore::CTypeAny {
+public:
+	static inline const char* getTypeName() { return "sdl_surface"; }
+	virtual const SDL_Surface* getSurface() const { return m_surface; }
+	
+	virtual SDL_Surface* getSurface() { return m_surface; }
+	virtual void setSurface(SDL_Surface* s) {
+		// In principle setting the same pointer twice may 
+		// point some kind of problem using this class
+		assert (!s || s!= m_surface);
+		// Anyway, in release mode handle it accordingly
+		if (m_surface && s!= m_surface) SDL_FreeSurface(m_surface);
+		m_surface= s; 
+	}
+
+	virtual void setX (short x) { m_x=x; }
+	virtual short getX() const { return m_x; }
+	
+	virtual void setY (short y) { m_y=y; }
+	virtual short getY() const { return m_y; }
+
+protected:
+	CTypeSDLSurfaceContents(int id) 
+	: CTypeAny(id) 
+	, m_x(0)
+	, m_y(0)
+	, m_surface(NULL)
+	{}
+
+	virtual ~CTypeSDLSurfaceContents() {
+		if (m_surface) SDL_FreeSurface(m_surface);
+		m_surface= NULL;
+	}
+private:
+	short m_x, m_y;
+	SDL_Surface* m_surface;
+	BOOST_STATIC_ASSERT(sizeof(Sint16)== sizeof(short));
+};
+
+typedef spcore::SimpleType< CTypeSDLSurfaceContents > CTypeSDLSurface;
+
+}
+#endif
diff --git a/include/mod_wiimotes/wiimotes_types.h b/include/mod_wiimotes/wiimotes_types.h
new file mode 100755
index 0000000..ac8add9
--- /dev/null
+++ b/include/mod_wiimotes/wiimotes_types.h
@@ -0,0 +1,438 @@
+/////////////////////////////////////////////////////////////////////////////
+// File:        wiimotes_types.h
+// Author:      Cesar Mauri Loba (cesar at crea-si dot com)
+// Copyright:   (C) 2011 Cesar Mauri Loba - CREA Software Systems
+// 
+//  This program is free software: you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation, either version 3 of the License, or
+//  (at your option) any later version.
+//
+//  This program is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+/////////////////////////////////////////////////////////////////////////////
+#ifndef WIIMOTES_TYPES
+#define WIIMOTES_TYPES
+
+#include "spcore/basetypeimpl.h"
+
+namespace mod_wiimotes {
+
+/**
+ Class to store and notify wiimotes status
+*/
+class CTypeWiimotesStatusContents : public spcore::CTypeAny {
+public:
+	enum Status { IDLE= 0, CONNECTING, CONNECTED };
+	
+	static inline const char* getTypeName() { return "wiimotes_status"; }
+
+	virtual Status GetGeneralStatus() const { return m_generalStatus; }
+
+	// Query the number of max devices
+	virtual unsigned int GetMaxCount() const { return MAXWIIMOTES; }
+
+	// Query the number of connected wiimotes
+	virtual unsigned int GetConnectedCount() const { return m_connectedCount; }
+	
+	// Asks wheter a particular wiimote is connected
+	virtual bool IsConnected(unsigned int wiimote_n) const;
+
+	// Accessors to query which extensions are avalable
+	virtual bool HasNunchuk(unsigned int wiimote_n) const;
+	virtual bool HasClassicPad(unsigned int wiimote_n) const;
+	virtual bool HasGuitarHero(unsigned int wiimote_n) const;
+	virtual bool HasBalanceBoard(unsigned int wiimote_n) const;
+	virtual bool HasMotionPlus(unsigned int wiimote_n) const;
+
+	// Accessors to query which features are enabled
+	virtual bool IsAccelerometersEnabled(unsigned int wiimote_n) const;
+	virtual bool IsMotionPlusEnabled(unsigned int wiimote_n) const;
+	virtual bool IsNunchuckEnabled(unsigned int wiimote_n) const;
+
+protected:
+	CTypeWiimotesStatusContents(int id); 
+
+	virtual bool CopyTo ( CTypeAny& dst, bool ) const {
+		assert (dst.GetTypeID()== this->GetTypeID());
+		*(static_cast<CTypeWiimotesStatusContents*>(&dst))= *this;
+		return true;
+	}
+	
+private:
+	//
+	// Constants
+	// 
+	enum { MAXWIIMOTES= 4 };
+	enum Extension { 
+		NONE				= 0, 
+		NUNCHUK				= 0x1, 
+		CLASSIC				= 0x2, 
+		GUITAR_HERO			= 0x4, 
+		BALANCE_BOARD		= 0x10, 
+		MOTION_PLUS			= 0x20, 
+		WIIMOTE_CONNECTED	= 0x8000 
+	};
+
+	/**
+		Flags to tell whether accelerometers and/or gyros are enabled. We disable them when not used to save battery.
+	*/
+	enum EnabledFeatures { ENABLED_NONE= 0, ENABLED_ACC= 0x1, ENABLED_MP= 0x2, ENABLED_NUNCHUCK= 0x4 };
+
+	//
+	// Attributes
+	//
+	Status m_generalStatus;
+	unsigned int m_connectedCount;
+	Extension m_wiimoteStatus[MAXWIIMOTES];
+	unsigned int m_enabledFeatures[MAXWIIMOTES];
+
+	//
+	// Private opetarions
+	//
+	void SetGeneralStatus(Status e) { m_generalStatus= e; }
+
+	void SetConnectedCount(int c) { assert (c<=MAXWIIMOTES); m_connectedCount= c; }
+
+	void SetIsConnected(unsigned int wiimote_n, bool v);
+
+	// Sets one extension and disables the others
+	void SetExtension (unsigned int wiimote_n, Extension e);
+
+	// Sets/unsets enabled features
+	void SetEnabledFeature (unsigned int wiimote_n, EnabledFeatures f) {
+		assert (wiimote_n< MAXWIIMOTES);
+		assert (!(f & 0xFFF8));
+
+		unsigned int flags= m_enabledFeatures[wiimote_n];
+		flags|= f;		
+		m_enabledFeatures[wiimote_n]= flags;
+	}
+
+	void UnsetEnabledFeature (unsigned int wiimote_n, EnabledFeatures f) {
+		assert (wiimote_n< MAXWIIMOTES);
+		assert (!(f & 0xFFF8));
+		
+		unsigned int flags= m_enabledFeatures[wiimote_n];
+		flags&= ~f;
+		m_enabledFeatures[wiimote_n]= flags;
+	}
+
+	void Reset();
+
+	friend class WiiuseThread;
+	friend class WiiuseThreadController;
+	friend class WiimotesConfig;
+	friend class WiimotesInput;
+};
+
+typedef spcore::SimpleType<CTypeWiimotesStatusContents> CTypeWiimotesStatus;
+
+
+/**
+ Class to store and notify accelerometer events
+*/
+class CTypeWiimotesAccelerometerContents : public spcore::CTypeAny {
+public:
+	static inline const char* getTypeName() { return "wiimotes_accelerometers"; }
+
+	/**
+		Get force on the X axis
+		@return force on X axis in G's
+	*/
+	virtual float GetForceX() const { return m_forceX; }
+
+	/**
+		Set force on the X axis in G's
+	*/
+	virtual void SetForceX(float fx) { m_forceX= fx; }
+
+	/**
+		Get force on the Y axis
+		@return force on Y axis in G's
+	*/
+	virtual float GetForceY() const { return m_forceY; }
+
+	/**
+		Set force on the Y axis in G's
+	*/
+	virtual void SetForceY(float fy) { m_forceY= fy; }
+
+	/**
+		Get force on the Z axis
+		@return force on Z axis in G's
+	*/
+	virtual float GetForceZ() const { return m_forceZ; }
+
+	/**
+		Set force on the Z axis in G's
+	*/
+	virtual void SetForceZ(float fz) { m_forceZ= fz; }
+
+	/**
+		GetRoll		
+		@return roll in degrees (-180..180)
+	*/
+	virtual float GetRoll() const { return m_roll; }
+
+	/**
+		SetRoll		
+		Set roll in degrees (-180..180)
+	*/
+	virtual void SetRoll(float roll) { 
+		assert (-180.0f<= roll && roll<= 180.0f);
+		m_roll= roll;
+	}
+
+	/**
+		GetPitch		
+		Return pitch in degrees (-180..180)
+	*/
+	virtual float GetPitch() const { return m_pitch; }
+
+	/**
+		SetPitch	
+		Set pitch in degrees (-180..180)
+	*/
+	virtual void SetPitch(float pitch) { 
+		assert (-180.0f<= pitch && pitch<= 180.0f);
+		m_pitch= pitch;
+	}
+
+	/**
+		IsOrientationAccurate
+		@return whether roll and pitch are accurate enough to use it.
+	*/
+	virtual bool IsOrientationAccurate() const { 
+		return (m_forceX>= -1.1f && m_forceX<= 1.1f &&
+			m_forceY>= -1.1f && m_forceY<= 1.1f &&
+			m_forceZ>= -1.1f && m_forceZ<= 1.1f);
+	}
+
+protected:
+	CTypeWiimotesAccelerometerContents(int id) : spcore::CTypeAny(id) {
+		m_forceX= m_forceY= m_forceZ= m_roll= m_pitch= 0.0f;
+	}
+
+	virtual bool CopyTo ( CTypeAny& dst, bool ) const {
+		assert (dst.GetTypeID()== this->GetTypeID());
+		*(static_cast<CTypeWiimotesAccelerometerContents*>(&dst))= *this;
+
+		return true;
+	}
+
+private:
+	float m_forceX, m_forceY, m_forceZ, m_roll, m_pitch;
+};
+
+typedef spcore::SimpleType<CTypeWiimotesAccelerometerContents> CTypeWiimotesAccelerometer;
+
+/**
+ Class to store and notify button press events
+*/
+class CTypeWiimotesButtonsContents : public spcore::CTypeAny {
+public:
+	static inline const char* getTypeName() { return "wiimotes_buttons"; }
+
+	virtual bool IsPressedA() const;
+	virtual bool IsPressedB() const;
+	virtual bool IsPressedOne() const;
+	virtual bool IsPressedTwo() const;
+	virtual bool IsPressedMinus() const;
+	virtual bool IsPressedPlus() const;
+	virtual bool IsPressedHome() const;
+	virtual bool IsPressedUp() const;
+	virtual bool IsPressedDown() const;
+	virtual bool IsPressedLeft() const;
+	virtual bool IsPressedRight() const;
+	
+	// nunchuck
+	virtual bool IsPressedC() const;
+	virtual bool IsPressedZ() const;
+
+	// any button
+	virtual bool IsPressedAny() const;
+
+protected:
+	CTypeWiimotesButtonsContents(int id) : spcore::CTypeAny(id) {
+		m_wiimoteButtons= 0;
+		m_nunchuckButtons= 0;
+	}
+
+	virtual bool CopyTo ( CTypeAny& dst, bool ) const {
+		assert (dst.GetTypeID()== this->GetTypeID());
+		*(static_cast<CTypeWiimotesButtonsContents*>(&dst))= *this;
+		return true;
+	}
+
+private:
+	void SetWiimoteButtons (unsigned short mask) { m_wiimoteButtons= mask; }
+	unsigned short GetWiimoteButtons () const { return m_wiimoteButtons; }
+
+	void SetNunchuckButtons (unsigned char mask) { m_nunchuckButtons= mask; }
+	unsigned char GetNunchuckButtons () const { return m_nunchuckButtons; }
+
+	unsigned short m_wiimoteButtons;
+	unsigned char  m_nunchuckButtons;
+
+	friend class WiimotesInput;
+};
+
+typedef spcore::SimpleType<CTypeWiimotesButtonsContents> CTypeWiimotesButtons;
+
+/**
+ Class to store and notify button balance board status
+*/
+
+#define BB_MIN_WEIGHT 8.0f
+class CTypeWiimotesBalanceBoardContents : public spcore::CTypeAny {
+public:
+	static inline const char* getTypeName() { return "wiimotes_balance_board"; }
+
+	/**
+		Get top left corner weight in kg
+	*/
+	virtual float GetTopLeft() const { return m_topLeft; }
+
+	/**
+		Set top left corner weight in kg
+	*/
+	virtual void SetTopLeft(float w) { m_topLeft= w; }
+
+	/**
+		Get top right corner weight in kg
+	*/
+	virtual float GetTopRight() const { return m_topRight; }
+
+	/**
+		Set top right corner weight in kg
+	*/
+	virtual void SetTopRight(float w) { m_topRight= w; }
+
+	/**
+		Get bottom left corner weight in kg
+	*/
+	virtual float GetBottomLeft() const { return m_bottomLeft; }
+
+	/**
+		Set bottom left corner weight in kg
+	*/
+	virtual void SetBottomLeft(float w) { m_bottomLeft= w; }
+
+	/**
+		Get bottom right corner weight in kg
+	*/
+	virtual float GetBottomRight() const { return m_bottomRight; }
+
+	/**
+		Set bottom right corner weight in kg
+	*/
+	virtual void SetBottomRight(float w) { m_bottomRight= w; }
+
+	/**
+		Get total weight in kg
+	*/
+	virtual float GetTotal() const {
+		return m_topLeft + m_topRight + m_bottomLeft + m_bottomRight;
+	}
+
+	/**
+		Get centre of mass for the X axis (ranging from -1 to 1). 
+		If there is not enough weight on, returns 0		
+	*/
+	virtual float GetCenterOfMassX() const {
+		float total= GetTotal();
+		if (total< BB_MIN_WEIGHT) return 0.0f;
+		return ((m_topRight + m_bottomRight) - (m_topLeft+ m_bottomLeft)) / total;
+	}
+
+	/**
+		Get centre of mass for the Y axis (ranging from -1 to 1). 
+		If there is not enough weight on, returns 0		
+	*/
+	virtual float GetCenterOfMassY() const {
+		float total= GetTotal();
+		if (total< BB_MIN_WEIGHT) return 0.0f;
+		return ((m_topRight + m_topLeft) - (m_bottomRight + m_bottomLeft)) / total;
+	}
+
+protected:
+	CTypeWiimotesBalanceBoardContents(int id) : spcore::CTypeAny(id) {
+		m_topLeft= m_topRight= m_bottomLeft= m_bottomRight= 0;
+	}
+
+	virtual bool CopyTo ( CTypeAny& dst, bool ) const {
+		assert (dst.GetTypeID()== this->GetTypeID());
+		*(static_cast<CTypeWiimotesBalanceBoardContents*>(&dst))= *this;
+		return true;
+	}
+
+private:
+	float m_topLeft, m_topRight, m_bottomLeft, m_bottomRight;
+};
+
+typedef spcore::SimpleType<CTypeWiimotesBalanceBoardContents> CTypeWiimotesBalanceBoard;
+
+/**
+ Class to store and notify motion plus status
+*/
+class CTypeWiimotesMotionPlusContents : public spcore::CTypeAny {
+public:
+	static inline const char* getTypeName() { return "wiimotes_motion_plus"; }
+
+	/**
+		Get X speed (pitch) in deg/s
+	*/
+	virtual float GetXSpeed() const { return m_xSpeed; }
+
+	/**
+		Set X speed (pitch) in deg/s
+	*/
+	virtual void SetXSpeed(float sx) { m_xSpeed= sx; }
+
+	/**
+		Get Y speed (roll) in deg/s
+	*/
+	virtual float GetYSpeed() const { return m_ySpeed; }
+
+	/**
+		Set Y speed (roll) in deg/s
+	*/
+	virtual void SetYSpeed(float sy) { m_ySpeed= sy; }
+
+	/**
+		Get Z speed (yaw) in deg/s
+	*/
+	virtual float GetZSpeed() const { return m_zSpeed; }
+
+	/**
+		Set Z speed (yaw) in deg/s
+	*/
+	virtual void SetZSpeed(float sz) { m_zSpeed= sz; }
+
+protected:
+	CTypeWiimotesMotionPlusContents (int id) : spcore::CTypeAny(id)
+	{
+		m_xSpeed= m_ySpeed= m_zSpeed = 0.0f;
+	}
+
+	virtual bool CopyTo ( CTypeAny& dst, bool ) const {
+		assert (dst.GetTypeID()== this->GetTypeID());
+		*(static_cast<CTypeWiimotesMotionPlusContents*>(&dst))= *this;
+		return true;
+	}
+
+private:
+	float m_xSpeed, m_ySpeed, m_zSpeed;
+};
+
+typedef spcore::SimpleType<CTypeWiimotesMotionPlusContents> CTypeWiimotesMotionPlus;
+
+};
+
+#endif
\ No newline at end of file
diff --git a/include/spcore/baseobj.h b/include/spcore/baseobj.h
new file mode 100644
index 0000000..9533786
--- /dev/null
+++ b/include/spcore/baseobj.h
@@ -0,0 +1,155 @@
+/**
+* @file		baseobj.h
+* @brief	Reference counted base class for all other classes
+* @author	Cesar Mauri Loba (cesar at crea-si dot com)
+*	
+* -------------------------------------------------------------------------
+*
+* Copyright:   (C) 2010 Cesar Mauri Loba - CREA Software Systems
+* 
+*  This program is free software: you can redistribute it and/or modify
+*  it under the terms of the GNU General Public License as published by
+*  the Free Software Foundation, either version 3 of the License, or
+*  (at your option) any later version.
+*
+*  This program is distributed in the hope that it will be useful,
+*  but WITHOUT ANY WARRANTY; without even the implied warranty of
+*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+*  GNU General Public License for more details.
+*
+*  You should have received a copy of the GNU General Public License
+*  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+#ifndef SPCORE_BASEOBJ_H
+#define SPCORE_BASEOBJ_H
+
+#include <assert.h>
+#include <boost/detail/atomic_count.hpp>
+#include <boost/intrusive_ptr.hpp>
+#include "spcore/libimpexp.h"
+
+#ifdef _MSC_VER
+#pragma warning(push)
+// 'm_A' : class 'A' needs to have dll-interface to be used by clients of class 'B'
+#pragma warning(disable: 4251)
+// non dll-interface class 'A' used as base for dll-interface class 'B'
+#pragma warning(disable: 4275)
+#endif // _MSC_VER
+
+namespace spcore {
+
+/*
+	Smart pointers.
+
+	Here we use the instrusive_ptr from boost library which we expose
+	under the alias name "SmartPtr"
+
+	For convenience, although is ugly, we use define's to declare
+	the alias instead of the following idiom:
+
+	template <typename T>
+	struct SmartPtr { typedef boost::intrusive_ptr<T> type; };
+
+	Doing so to use the smart pointer we should write something like:
+
+	SmartPtr<MyType>::type
+
+	which complicates the syntax besides other problems. See:
+
+	http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2003/n1449.pdf
+*/
+/**
+	@todo, TODO: implement it using the template alias feature of the new
+	C++0x standard when it become more widespread.		
+*/	
+#define SmartPtr boost::intrusive_ptr
+#define smartptr_static_cast boost::static_pointer_cast
+#define smartptr_dynamic_cast boost::dynamic_pointer_cast
+
+/**
+	@brief Reference counted base class for all other classes
+
+	This class is used as base to derive other classes within
+	sitplus-lib that need to be reference counted.
+
+	Note that this implementation relies on inline methods due to
+	its simplicity and to make sure that the "delete this" instruction
+	it is defined within the specific module boundaries. In fact, on
+	WIN32 this class does no generate linkage.
+*/
+class IBaseObject {
+protected:
+	virtual ~IBaseObject() {}
+	/**
+		@brief Protected constructor.
+		
+		Initialises reference counter to 1.
+	*/
+	IBaseObject() : m_refCount(1) {}
+
+public:
+	/**
+		@brief Increment reference counter.
+
+		This method is thread safe.
+	*/
+	void AddRef() const {
+		assert (m_refCount> 0);
+  		++m_refCount;
+	}
+
+	/**
+		@brief Decrement reference counter.
+
+		Decrement reference counter and destroy the instance if it reaches 0.
+		This method is thread safe.
+	*/
+	void Release() const  {
+  		if (--m_refCount== 0) Destroy();
+	}
+
+protected:
+	/**
+		@brief Delete current object (this). 
+		
+		Inline, so ensure deletion is carried out within module.
+	*/
+	void Destroy() const {
+		delete this;
+	}
+
+	/**
+		@brief Assignment operator.
+	*/
+	IBaseObject& operator=( const IBaseObject& ) {
+		// Does nothing. The reference counter should never be copied
+		return *this;
+	}
+
+private:
+	// Copy constructor. Disabled
+	IBaseObject ( const IBaseObject& );
+
+	/**
+		@brief Atomic reference counter.
+	*/
+	mutable boost::detail::atomic_count m_refCount;
+};
+
+} // namespace spcore
+
+namespace boost
+{
+inline void intrusive_ptr_add_ref(const ::spcore::IBaseObject * p) {
+	p->AddRef();
+}
+inline void intrusive_ptr_release(const ::spcore::IBaseObject * p) {
+	p->Release();
+}
+};
+
+#ifdef _MSC_VER
+#pragma warning(pop)
+#endif
+
+#endif
diff --git a/include/spcore/basetype.h b/include/spcore/basetype.h
new file mode 100644
index 0000000..5cf2e6b
--- /dev/null
+++ b/include/spcore/basetype.h
@@ -0,0 +1,267 @@
+/**
+* @file		basetype.h
+* @brief	CTypeAny definition and associated helpers
+* @author	Cesar Mauri Loba (cesar at crea-si dot com)
+*	
+* -------------------------------------------------------------------------
+*
+* Copyright:   (C) 2010 Cesar Mauri Loba - CREA Software Systems
+* 
+*  This program is free software: you can redistribute it and/or modify
+*  it under the terms of the GNU General Public License as published by
+*  the Free Software Foundation, either version 3 of the License, or
+*  (at your option) any later version.
+*
+*  This program is distributed in the hope that it will be useful,
+*  but WITHOUT ANY WARRANTY; without even the implied warranty of
+*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+*  GNU General Public License for more details.
+*
+*  You should have received a copy of the GNU General Public License
+*  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+#ifndef SPCORE_BASETYPE_H
+#define SPCORE_BASETYPE_H
+
+#include "spcore/baseobj.h"
+#include "spcore/iterator.h"
+#include "spcore/coreruntime.h"
+
+namespace spcore {
+
+// Forward declarations
+class IOutputPin;
+
+/**
+	@brief Type identifiers.
+*/
+enum EBasicID {
+  TYPE_INVALID = -1,
+  TYPE_ANY = 0
+};
+
+/**
+	@brief Base class for all types.
+*/
+class CTypeAny : public IBaseObject {
+public:
+	/**
+		@brief Get type ID.
+		@return the identifier of this instance.
+	*/
+	virtual int GetTypeID() const { return m_typeID; }
+	
+	/**
+		@brief Add child instance (interface for composite types).
+		@param component smart pointer to an instance to add as child.
+		@return 0: child added successfully or -1 if error.
+
+		Default definition doesn't allow child instances.
+	*/
+	virtual int AddChild(SmartPtr<CTypeAny> component) {
+		return -1;
+	}
+
+	/**
+		@brief Query children instances (interface for composite types).
+		@return smart pointer to an iterator which can be NULL.
+
+		Default definition doesn't allow child instances.
+	*/
+    virtual SmartPtr<IIterator<CTypeAny*> > QueryChildren() const {
+		return SmartPtr<IIterator<CTypeAny*> >(NULL);
+	}
+
+	static const char* getTypeName() { return "any"; }
+
+	/**
+		@brief Performs a copy of this object.
+		@param dst if not NULL and its ID coincides with the ID of this then
+			overwrites dst. If type IDs mismatch a new instance is created and
+			returned.
+		@param recurse is passed untouched to CopyTo. if it is true
+			deep copies are performed on composite types, if false only
+			copies the instance but not its children.
+		@return smart pointer to the new instance which can be dst, a new one or 
+			NULL if this doesn't support copies.
+	*/
+	virtual SmartPtr<CTypeAny> Clone (CTypeAny * dst, bool recurse) const {
+		if (this== dst) return SmartPtr<CTypeAny>(dst);
+
+		if (dst && this->GetTypeID()== dst->GetTypeID()) {
+			if (CopyTo (*dst, recurse)) 
+				// Copy performed
+				return SmartPtr<CTypeAny>(dst);
+			else 
+				// Same type but copy cannot be performed
+				return SmartPtr<CTypeAny>();
+		}
+		else {
+			// Different types or dst NULL
+			ICoreRuntime* cr= getSpCoreRuntime(); assert (cr);
+			SmartPtr<CTypeAny> newInstance= cr->CreateTypeInstance(m_typeID);
+			if (newInstance.get()== NULL) {
+				// Something went really wrong
+				assert (false);
+				return newInstance;
+			}		
+						
+			if (CopyTo(*newInstance, recurse))
+				return newInstance;
+			else
+				// Copy failed
+				return SmartPtr<CTypeAny>();
+		}
+	}
+
+	/**
+		@brief Create output pins of type CTypeAny.
+		@param name name that will be given to the pin.
+		
+		Pins created with this function can be attached to components 
+		and instances of any type. If calls to api functions of the pin
+		need to be thread safe see CreateOutputPinLockAny() method.
+	*/
+	static SmartPtr<IOutputPin> CreateOutputPinAny(const char* name) {
+		return getSpCoreRuntime()->CreateOutputPin(CTypeAny::getTypeName(), name, false);
+	}
+	
+	/**
+		@brief Create thread safe output pins of type CTypeAny.
+		@param name name that will be given to the pin.
+		
+		Pins created with this function can be attached to components 
+		and instances of any type.
+	*/
+	static SmartPtr<IOutputPin> CreateOutputPinLockAny(const char* name) {
+		return getSpCoreRuntime()->CreateOutputPin(CTypeAny::getTypeName(), name, true);
+	}
+
+protected:
+	/**
+		@brief Protected constructor.
+		@param id numerical ID given to this instance.
+	*/
+	CTypeAny(int id) { assert (id>= 0); m_typeID= id; }
+	
+	/**
+		@brief Virtual destructor.
+	*/
+	virtual ~CTypeAny() {}
+
+	/**
+		@brief Copies this into dst
+		@param dst copy destination. Is always an existing instance.
+		@param recurse perform deep copies of	composite objects when true.
+		@todo make pure virtual?
+	*/
+	virtual bool CopyTo ( CTypeAny& dst, bool recurse) const {
+		// This method should not be called directly
+		// Calls are expected to be performed on derived classes
+		assert (false);
+		// Unused parameters
+		(void) dst;
+		(void) recurse;
+		return false;
+	}
+
+	/**
+		@brief Assignment operator. 
+
+		Available to derived classes to allow to use the compiler generated copy 
+		constructor. Note that copying between instances with different IDs it 
+		is not allowed and also derived classed must ensure this. Use with care.
+	*/
+	CTypeAny& operator=( const CTypeAny& that )	{
+		assert (this->m_typeID== that.m_typeID);
+		return *this;
+	}
+
+private:
+	// Disable copy constructor.
+	CTypeAny ( const CTypeAny& );      
+
+	//
+	// Attributes
+	//
+	int m_typeID;
+};
+
+/**
+	@brief Interface for intances factory.
+	
+	Conforming implementation should provide definition of GetName() and 
+	CreateInstance() methods.
+*/
+class ITypeFactory : public IBaseObject {
+protected:
+	virtual ~ITypeFactory() {}
+
+public:
+
+	/**
+		@brief Return the name of the type of the instances this factory creates.
+		@return name of the type of the instances this factory creates.
+	*/
+    virtual const char* GetName() const = 0;
+
+	/**
+		@brief Create instance.
+		@param id numerical ID of the type.
+		@todo store the ID in the factory once registered.
+	*/
+    virtual SmartPtr<CTypeAny> CreateInstance(int id) = 0;
+};
+
+
+
+//
+// Template functions for downcasting (smart pointed) CTypeAny instances
+//
+template <typename T>
+T* sptype_static_cast (CTypeAny* v){
+	return static_cast<T*>(v);
+}
+
+template <typename T>
+T const * sptype_static_cast (CTypeAny const * v){
+	return static_cast<T const *>(v);
+}
+
+template <typename T>
+T* sptype_dynamic_cast (CTypeAny* v){
+	if (T::getTypeID()!= v->GetTypeID()) return NULL;
+	return static_cast<T*>(v);
+}
+
+template <typename T>
+T const * sptype_dynamic_cast (CTypeAny const * v){
+	if (T::getTypeID()!= v->GetTypeID()) return NULL;
+	return static_cast<T const *>(v);
+}
+
+template <typename T>
+SmartPtr<T> sptype_static_cast (const SmartPtr<const CTypeAny> &v){
+	return smartptr_static_cast<T,const CTypeAny>(v);
+}
+
+template <typename T>
+SmartPtr<T> sptype_static_cast (const SmartPtr<CTypeAny> &v){
+	return smartptr_static_cast<T,CTypeAny>(v);
+}
+
+template <typename T>
+SmartPtr<T> sptype_dynamic_cast (const SmartPtr<const CTypeAny> &v){
+	if (T::getTypeID()!= v->GetTypeID()) return SmartPtr<T>(NULL);
+	return smartptr_static_cast<T,const CTypeAny>(v);
+}
+
+template <typename T>
+SmartPtr<T> sptype_dynamic_cast (const SmartPtr<CTypeAny> &v){
+	if (T::getTypeID()!= v->GetTypeID()) return SmartPtr<T>(NULL);
+	return smartptr_static_cast<T,CTypeAny>(v);
+}
+
+
+} // namespace spcore
+#endif
diff --git a/include/spcore/basetypeimpl.h b/include/spcore/basetypeimpl.h
new file mode 100644
index 0000000..fbb82e6
--- /dev/null
+++ b/include/spcore/basetypeimpl.h
@@ -0,0 +1,299 @@
+/** 
+* @file		basetypeimpl.h
+* @brief	Support classes to implement new types within lib-sitplus.
+* @author	Cesar Mauri Loba (cesar at crea-si dot com)
+*
+* -------------------------------------------------------------------------
+*
+* Copyright:   (C) 2011 Cesar Mauri Loba - CREA Software Systems
+* 
+*  This program is free software: you can redistribute it and/or modify
+*  it under the terms of the GNU General Public License as published by
+*  the Free Software Foundation, either version 3 of the License, or
+*  (at your option) any later version.
+*
+*  This program is distributed in the hope that it will be useful,
+*  but WITHOUT ANY WARRANTY; without even the implied warranty of
+*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+*  GNU General Public License for more details.
+*
+*  You should have received a copy of the GNU General Public License
+*  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+#ifndef SPCORE_BASETYPEIMPL_H
+#define SPCORE_BASETYPEIMPL_H
+
+#include "spcore/basetype.h"
+#include "spcore/coreruntime.h"
+#include "spcore/pinimpl.h"
+#include <boost/type_traits/is_pointer.hpp>
+
+namespace spcore {
+
+/**
+	@brief Template to create basic factories of basic types.
+	@tparam T class of objects this factory constructs.
+
+	This template allows to create type factories given a class
+	which provides an static method getTypeName() and a constructor
+	which accepts the ID as parameter.
+*/
+template<class T> 
+class SimpleTypeFactory : public ITypeFactory
+{
+public:
+	virtual const char * GetName() const {
+		return T::getTypeName();
+	}
+	virtual SmartPtr<CTypeAny> CreateInstance(int id) {
+		return SmartPtr<CTypeAny>(new T(id), false);
+	}
+};
+
+/**
+	@brief Adapter to implement composite types.
+	
+	For non-composite type inherit directly from CTypeAny.
+*/
+class CompositeTypeAdapter : public CTypeAny
+{
+public:
+	virtual int AddChild(SmartPtr<CTypeAny> component) {
+		std::vector<CTypeAny*>::iterator it=
+			find(m_children.begin(), m_children.end(), component.get());
+		if (it!= m_children.end()) return -1;	// Already registered
+		component->AddRef();
+		m_children.push_back(component.get());
+		return 0;
+	}
+	virtual SmartPtr<IIterator<CTypeAny*> > QueryChildren() const {
+		return SmartPtr<IIterator<CTypeAny*> > (new CIteratorVector<CTypeAny*>(m_children), false);		
+	}
+
+protected:
+	CompositeTypeAdapter(int id) : CTypeAny(id) {}
+	virtual ~CompositeTypeAdapter() {
+		std::vector<CTypeAny*>::iterator it= m_children.begin();
+		for (; it!= m_children.end(); ++it) (*it)->Release();
+	}
+
+	virtual bool CopyTo ( CTypeAny& dst, bool recurse) const {
+		assert (dst.GetTypeID()== this->GetTypeID());
+		assert (this!= &dst);
+
+		CompositeTypeAdapter* dst_cast= sptype_static_cast<CompositeTypeAdapter>(&dst);
+				
+		// Contents are copied by the derived class that should call this method
+
+		if (recurse) {
+			// 
+			// composite copy of a composite type. update structure and contents recursively 
+			//
+			std::vector<CTypeAny*>::const_iterator it_src= this->m_children.begin();
+			std::vector<CTypeAny*>::iterator it_dst= dst_cast->m_children.begin();	
+
+			// While both have children just copy
+			while (it_src!= this->m_children.end() && it_dst!= dst_cast->m_children.end()) {
+				SmartPtr<CTypeAny> newInstance= (*it_src)->Clone (*it_dst, recurse);
+				if (newInstance.get()== NULL) {
+					// Should not happen
+					assert (false);
+					return false;
+				}
+				if (newInstance.get()!= *it_dst) {
+					/**
+					 @todo, TODO: remove the following assert which is only intended to
+					 detect when this portion of code is used. Note that this means
+					 that the old dst had a different type form the src which is
+					 strange but not, in principle, wrong
+					*/
+					assert (false);
+
+					// Copy process created a new instance. Substitute in vector and
+					// and destroy the old one
+					(*it_dst)->Release();
+					*it_dst= newInstance.get();
+					(*it_dst)->AddRef();
+				}
+
+				++it_src;
+				++it_dst;		
+			}
+
+			if (it_src!= this->m_children.end()) {
+				// src has more children than dst, create and clone
+				while (it_src!= this->m_children.end()) {
+					SmartPtr<CTypeAny> new_child= (*it_src)->Clone (NULL, recurse);
+					if (new_child.get()== NULL) {
+						// Should not happen
+						assert (false);
+						return false;
+					}
+					new_child.get()->AddRef();	// Goes to non smart ptr'ed vector
+					dst_cast->m_children.push_back (new_child.get());
+					
+					++it_src;
+				}
+			}
+			else {
+				// dst has remaining children that need to be removed
+				while (it_dst!= dst_cast->m_children.end()) {
+					(*it_dst)->Release();
+					it_dst= dst_cast->m_children.erase(it_dst);
+				}
+			}
+		}
+		else {
+			// shallow copy, remove destination children if any
+			std::vector<CTypeAny*>::iterator it_dst= dst_cast->m_children.begin();
+			while (it_dst!= dst_cast->m_children.end()) {
+				(*it_dst)->Release();
+				it_dst= dst_cast->m_children.erase(it_dst);
+			}
+		}	
+
+		return true;
+	}
+
+private:
+	std::vector<CTypeAny*> m_children;
+};
+
+
+/**
+	@brief Template to define common static operations of a basic type.
+	@tparam BASE class which provide the basic operations of the type.
+	@tparam RESULT resulting class (i.e. the class of the type instances).
+		Used for return types and type castings.
+
+	Provides convenience functions to allow to obtain the type ID and to
+	create instances and pin using the name of the class directly in
+	in the C++ sources.	
+	
+	Intended for being used internally. Use SimpleType template class if you 
+	are	implementing a new sort of type.
+
+	Ex: CTypeInt::CreateInstance() creates a new integer instance.
+*/
+template <class BASE, class RESULT>
+class SimpleTypeBasicOperations
+{
+public:
+	/**
+		@brief Get numeral type identifier using core services.
+		@return type ID or TYPE_INVALID if type is undefined.
+
+		First call uses the type name to obtain the ID, but
+		further calls use a cached copy of the ID.
+	*/
+	static int getTypeID() { 
+		static int typeID= TYPE_INVALID;
+		if (typeID== TYPE_INVALID) typeID= getSpCoreRuntime()->ResolveTypeID(BASE::getTypeName());
+		return typeID;
+	}
+
+	/**
+		@brief Create an instance of the type.
+		@return smart pointer to the new instance which can store NULL when error.
+	*/
+	static SmartPtr<RESULT> CreateInstance() {
+		int typeID= SimpleTypeBasicOperations::getTypeID();
+		if (typeID== TYPE_INVALID) return SmartPtr<RESULT>(NULL, false);    			
+		return SmartPtr<RESULT>(static_cast<RESULT *>(getSpCoreRuntime()->CreateTypeInstance(typeID).get()));		
+	}
+
+	/**
+		@brief Create output pin of the type.
+		@param name identifier the new pin will be given.
+		@return smart pointer to the newly created output pin.
+		@todo check usage and decide whether to catch exceptions and log errors
+
+		Note that this method below can throw although shouldn't unless a fatal error occur.
+	*/	
+	static SmartPtr<IOutputPin> CreateOutputPin(const char* name) {
+		return SmartPtr<IOutputPin>(new COutputPin (name, BASE::getTypeName()), false);
+	}
+	
+	/**
+		@brief Create a thread safe output pin of the type.
+		@param name identifier the new pin will be given.
+		@return smart pointer to the newly created output pin.
+		@todo check usage and decide whether to catch exceptions and log errors
+
+		Note that this method below can throw although shouldn't unless a fatal error occur.
+	*/
+	static SmartPtr<IOutputPin> CreateOutputPinLock(const char* name) {
+		return SmartPtr<IOutputPin>(new COutputPinLock (name, BASE::getTypeName()), false);
+	}
+};
+
+/**
+	@brief Template to define basic types
+	@tparam BASE class which provide the basic operations of the type.
+*/
+
+template<class BASE>
+class SimpleType : public BASE, public SimpleTypeBasicOperations<BASE, SimpleType<BASE> >
+{
+	/**
+		Template class SimpleTypeFactory is the only allowed.
+		to create instances of this class.
+	*/
+	friend class SimpleTypeFactory<SimpleType>;
+
+protected:
+	/**
+		@brief Protected constructor.
+		@param typeID type identifier the new instance will be given. 
+		Note that this constructor only can be called from a 
+		SimpleTypeFactory instance.
+	*/
+	SimpleType(int typeID) : BASE(typeID) {}
+		
+private:
+	// Disable default copy constructor and operator
+	SimpleType( const SimpleType& );      // not implemented
+	SimpleType& operator=( const SimpleType& );     // not implemented
+};
+
+/**
+	@brief Contents template class for scalar types.
+	@tparam T scalar type to be stored.
+*/
+template<class T>
+class ScalarTypeContents : public CTypeAny {
+	BOOST_STATIC_ASSERT (!boost::is_pointer<T>::value);
+public:
+	/**
+		@brief Get the stored value
+		@return stored value
+		@todo remove const
+	*/
+	virtual const T getValue() const { return m_value; }
+
+	/**
+		@brief Store a new value
+		@param value
+	*/
+	virtual void setValue(T value) { m_value= value; }
+
+protected:
+	/**
+		@brief Protected constructor.
+		@param id identifier the new instance will be given.
+	*/
+	ScalarTypeContents(int id) : CTypeAny(id) { m_value= 0; }
+	
+	virtual bool CopyTo ( CTypeAny& dst, bool ) const {
+		assert (dst.GetTypeID()== this->GetTypeID());
+		sptype_static_cast<ScalarTypeContents>(&dst)->m_value= m_value;
+		return true;
+	}
+
+	// Destructor not needed
+    T m_value;
+};
+
+
+} // namespace spcore
+#endif
diff --git a/include/spcore/basictypes.h b/include/spcore/basictypes.h
new file mode 100644
index 0000000..a0237cc
--- /dev/null
+++ b/include/spcore/basictypes.h
@@ -0,0 +1,144 @@
+/**
+* @file		basictypes.h
+* @brief	Definition int, bool, float, string and composite core types.
+* @author	Cesar Mauri Loba (cesar at crea-si dot com)
+*
+* -------------------------------------------------------------------------
+*
+* Copyright:   (C) 2010-11 Cesar Mauri Loba - CREA Software Systems
+* 
+*  This program is free software: you can redistribute it and/or modify
+*  it under the terms of the GNU General Public License as published by
+*  the Free Software Foundation, either version 3 of the License, or
+*  (at your option) any later version.
+*
+*  This program is distributed in the hope that it will be useful,
+*  but WITHOUT ANY WARRANTY; without even the implied warranty of
+*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+*  GNU General Public License for more details.
+*
+*  You should have received a copy of the GNU General Public License
+*  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+#ifndef SPCORE_BASICTYPES_H
+#define SPCORE_BASICTYPES_H
+
+#include "spcore/basetypeimpl.h"
+#include "spcore/coreruntime.h"
+#include "spcore/module.h"
+#include <string>
+#include <vector>
+
+namespace spcore {
+
+//
+// Basic types definitions
+//
+
+// int
+class CTypeIntContents : public ScalarTypeContents<int> {
+public:
+	CTypeIntContents(int id) : ScalarTypeContents<int>(id) {}
+	static inline const char* getTypeName() { return "int"; }
+};
+
+/**
+	@brief Integer type for lib-sitplus.
+	
+	See class ScalarTypeContents and SimpleTypeBasicOperations for
+	available operations.
+*/
+typedef SimpleType< CTypeIntContents > CTypeInt;
+
+
+// float
+class CTypeFloatContents : public ScalarTypeContents<float> {
+public:
+	CTypeFloatContents(int id) : ScalarTypeContents<float>(id) {}
+	static inline const char* getTypeName() { return "float"; }
+};
+
+/**
+	@brief Float type for lib-sitplus.
+	
+	See class ScalarTypeContents and SimpleTypeBasicOperations for
+	available operations.
+*/
+typedef SimpleType< CTypeFloatContents > CTypeFloat;
+
+
+// bool
+class CTypeBoolContents : public ScalarTypeContents<bool> {
+public:
+	CTypeBoolContents(int id) : ScalarTypeContents<bool>(id) {}
+	static inline const char* getTypeName() { return "bool"; }
+};
+
+/**
+	@brief Boolean type for lib-sitplus.
+	
+	See class ScalarTypeContents and SimpleTypeBasicOperations for
+	available operations.
+*/
+typedef SimpleType< CTypeBoolContents > CTypeBool;
+
+
+// string
+class CTypeStringContents : public CTypeAny
+{
+public:
+	CTypeStringContents(int id) : CTypeAny(id) {}
+	static inline const char* getTypeName() { return "string"; }
+	virtual const char* getValue() const { return m_string.c_str(); }
+	virtual void setValue(const char* s) {
+		if (s== NULL) m_string.clear();
+		else m_string= s; 
+	}
+	virtual bool CopyTo ( CTypeAny& dst, bool ) const {
+		assert (dst.GetTypeID()== this->GetTypeID());
+		sptype_static_cast<CTypeStringContents>(&dst)->m_string= m_string;
+		return true;
+	}
+private:
+	std::string m_string;
+};
+
+/**
+	@brief String type for lib-sitplus.
+	
+	See class SimpleTypeBasicOperations for	additional operations.
+*/
+typedef spcore::SimpleType< CTypeStringContents > CTypeString;
+
+
+// composite
+class CTypeCompositeContents : public CompositeTypeAdapter
+{
+public:
+	CTypeCompositeContents(int id) : CompositeTypeAdapter(id) {}
+	static inline const char* getTypeName() { return "composite"; }
+
+	// Does not provide a specialised CopyTo method because
+	// this class has no data an so the base class method is enough
+};
+
+/**
+	@brief Composite type for lib-sitplus.
+	
+	See class CompositeTypeAdapter and SimpleTypeBasicOperations for
+	available operations.
+*/
+typedef spcore::SimpleType< CTypeCompositeContents > CTypeComposite;
+
+//
+// Module for basic types. Implemented in basictypesimpl.cpp
+// FOR INTERNAL USE ONLY!
+//
+class CBasicTypesModule : public CModuleAdapter {
+public:
+    CBasicTypesModule();
+    virtual const char * GetName() const;
+};
+
+} // namespace spcore
+#endif
diff --git a/include/spcore/component.h b/include/spcore/component.h
new file mode 100644
index 0000000..38c5fc4
--- /dev/null
+++ b/include/spcore/component.h
@@ -0,0 +1,630 @@
+/**
+* @file		component.h
+* @brief	Components' related stuff (interfaces and adapters)
+* @author	Cesar Mauri Loba (cesar at crea-si dot com)
+*
+* -------------------------------------------------------------------------
+*
+* Copyright:   (C) 2010-12 Cesar Mauri Loba - CREA Software Systems
+*
+*  This program is free software: you can redistribute it and/or modify
+*  it under the terms of the GNU General Public License as published by
+*  the Free Software Foundation, either version 3 of the License, or
+*  (at your option) any later version.
+*
+*  This program is distributed in the hope that it will be useful,
+*  but WITHOUT ANY WARRANTY; without even the implied warranty of
+*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+*  GNU General Public License for more details.
+*
+*  You should have received a copy of the GNU General Public License
+*  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+#ifndef SPCORE_COMPONENT_H
+#define SPCORE_COMPONENT_H
+
+#include "spcore/baseobj.h"
+#include "spcore/coreruntime.h"
+#include <vector>
+#include <string>
+#include "spcore/pin.h"
+#include "spcore/iterator.h"
+#include "spcore/configuration.h"
+#include <algorithm>
+#include <string.h>
+#include <boost/type_traits.hpp>
+#include <boost/static_assert.hpp>
+
+/**
+	@todo typedef as a neutral window type
+*/
+class wxWindow;
+
+namespace spcore {
+
+// Forward declarations
+template<class T> class IIterator; 
+class IInputPin; 
+class IOutputPin; 
+
+/**
+	@brief Interface for all components.
+*/
+class IComponent : public IBaseObject {
+protected:
+	virtual ~IComponent() {};
+
+public:
+	/**
+		@brief Return the name of the component.
+		@return Pointer to an internally managed string with the name of the component.
+	*/
+	virtual const char* GetName() const = 0;
+
+	/**
+		@brief Return the name of the type of the component.
+		@return Pointer to an internally managed string with the name.
+	*/
+	virtual const char* GetTypeName() const = 0;
+
+	/**
+		@brief Opens a window for this component (if it has one).
+		@param parent Pointer to the parent window.
+		@return Pointer to the window or NULL.
+
+		The lifetime of this instance belongs to the component and should never be deleted.
+	*/
+	virtual wxWindow* GetGUI(wxWindow * parent) = 0;
+
+	/**
+		@brief Add a child component.
+		@param component Smart pointer to the child component.
+		@return 0 when OK
+
+		Note not all components support composition.
+	*/
+	virtual int AddChild(SmartPtr<IComponent> component) = 0;
+
+	/**
+		@brief Get the list of children compoents.
+		@return Smart pointer to a component iterator. Can be NULL.
+
+		Note not all components support composition.
+	*/
+	virtual SmartPtr<IIterator<IComponent*> > QueryComponents() = 0;
+
+	/**
+		@brief Get the input pins of a component (if any).
+		@return Smart pointer to an iterator of input pins.
+	*/
+	virtual SmartPtr<IIterator<IInputPin*> > GetInputPins() = 0;
+
+	/**
+		@brief Get the output pins of a component (if any).
+		@return Smart pointer to an iterator of output pins.
+	*/
+	virtual SmartPtr<IIterator<IOutputPin*> > GetOutputPins() = 0;
+
+	/**
+		@brief Returns whether this component provides a thread of execution.
+		@return true or false.
+		
+		Use Start() and Stop() methods to control thread state.
+	*/
+	virtual bool ProvidesExecThread() const = 0;
+
+	/**
+		@brief Starts the component (and children if any). 
+		@return 0 if successfully started, -1 otherwise.
+
+		This call is used to start/stop the component which can perform specific
+		actions to enable/disable it and, when ProvidesExecThread is true then
+		also runs the thread.
+	*/
+	virtual int Start() = 0;
+
+	/**
+		@brief Stops the component. 
+		
+		See comment for Start() method.
+	*/
+	virtual void Stop() = 0;
+
+	/**
+		@brief	Initializes the component.
+		@return 0 if successfully initialized, -1 otherwise.		
+	*/
+	virtual int Initialize() = 0;
+
+	/**
+		@brief Finishes the component.
+	*/
+	virtual void Finish() = 0;
+
+	/**
+		@brief Store internal settings.
+		@param cfg Configuration object		
+	*/
+	virtual void SaveSettings(IConfiguration& cfg)= 0;
+
+	/**
+		@brief Store internal settings.
+		@param cfg Configuration object.		
+	*/
+	virtual void LoadSettings(IConfiguration& cfg)= 0;
+
+	/**
+		@brief Static method which searches an input pin given its name.
+		@param component Component
+		@param name Name of the input pin to look for.
+		@return Pointer to the pin or NULL if not found.
+	*/
+	static inline
+	IInputPin* FindInputPin(IComponent & component, const char * name) {
+		assert (name);
+  		if (!name) return NULL;
+  		SmartPtr<IIterator<IInputPin*> > ipit= component.GetInputPins();
+  		for (; !ipit->IsDone(); ipit->Next()) {
+  			if (strcmp(ipit->CurrentItem()->GetName(), name)== 0) return ipit->CurrentItem();
+  		}
+  		return NULL;
+	}
+
+	/**
+		@brief Static method which searches an output pin given its name.
+		@param component Component
+		@param name Name of the output pin to look for.
+		@return Pointer to the pin or NULL if not found.
+	*/
+	static inline 
+	IOutputPin* FindOutputPin(IComponent & component, const char * name) {
+		assert (name);
+  		if (!name) return NULL;
+  		SmartPtr<IIterator<IOutputPin*> > opit= component.GetOutputPins();
+  		for (; !opit->IsDone(); opit->Next()) {
+  			if (strcmp(opit->CurrentItem()->GetName(), name)== 0) return opit->CurrentItem();
+  		}
+  		return NULL;
+	}
+};
+
+/**
+	@brief Adapter class to implement IComponent conforming classes.
+	
+	This class is intended to be derived to implement leaf type components
+	(i.e. without child components). If you need to implement a component
+	that is composed of children use class CCompositeComponentAdapter instead.
+*/
+class CComponentAdapter : public IComponent {
+public:
+	/**
+		@brief Constructor 
+		@param name Name given to the component.
+		@param argc Number of arguments passed to the parameter argv.
+		@param argv Array of parameters (can be NULL if argc==0).
+
+		argc, argv are not used actually but these parameters are needed
+		to provide an uniform construction mechanism.
+	*/
+	CComponentAdapter(const char * name, int argc, const char * argv[]) 
+	: m_initialized(false)
+	, m_name(name)
+	{
+		// Construction is expected to happen within the main thread
+		assert (getSpCoreRuntime()->IsMainThread());
+
+		// Unused parameters
+		(void) argc;
+		(void) argv;
+	}
+
+	virtual ~CComponentAdapter() {
+		// Destruction is expected to happen within the main thread
+		assert (getSpCoreRuntime()->IsMainThread());
+
+		std::vector<IInputPin*>::iterator iti;
+		for (iti= m_inputPins.begin(); iti!= m_inputPins.end(); ++iti)
+			(*iti)->Release();
+		m_inputPins.clear();
+
+		std::vector<IOutputPin*>::iterator ito;
+		for (ito= m_outputPins.begin(); ito!= m_outputPins.end(); ++ito)
+			(*ito)->Release();
+		m_outputPins.clear();
+	}
+
+	virtual const char* GetName() const { return m_name.c_str(); }
+	virtual wxWindow* GetGUI(wxWindow * parent) { 
+		(void) parent;
+		return NULL; 
+	}
+
+	virtual int AddChild(SmartPtr<IComponent> component) { return -1; }
+	virtual SmartPtr<IIterator<IComponent*> > QueryComponents() {
+		return SmartPtr<IIterator<IComponent*> >(NULL, false);
+	}
+
+	virtual SmartPtr<IIterator<IInputPin*> > GetInputPins() {
+		return SmartPtr<IIterator<IInputPin*> >(new CIteratorVector<IInputPin *>(m_inputPins), false);
+	}
+	virtual SmartPtr<IIterator<IOutputPin*> > GetOutputPins() {
+		return SmartPtr<IIterator<IOutputPin*> >(new CIteratorVector<IOutputPin *>(m_outputPins), false);
+	}
+
+	virtual bool ProvidesExecThread() const { return false; }
+
+	virtual int Start() {
+		assert (getSpCoreRuntime()->IsMainThread());
+		int retval= Initialize();
+		if (retval) return retval;
+		return DoStart();
+	}
+	virtual void Stop() {
+		assert (getSpCoreRuntime()->IsMainThread());
+		DoStop();
+	}
+
+	virtual int Initialize() {
+		assert (getSpCoreRuntime()->IsMainThread());
+		if (m_initialized) return 0;
+
+		int retval= DoInitialize();
+		if (retval) return retval;
+		
+		m_initialized= true;
+			
+		return 0; 
+	}
+	virtual void Finish() {
+		assert (getSpCoreRuntime()->IsMainThread());
+		if (m_initialized) {
+			DoFinish();
+			m_initialized= false;
+		}
+	}
+
+	virtual void SaveSettings(IConfiguration&) {
+		assert (getSpCoreRuntime()->IsMainThread());
+	}
+	virtual void LoadSettings(IConfiguration&) {
+		assert (getSpCoreRuntime()->IsMainThread());
+	}
+
+protected:
+	/**
+		@brief	Perform the actual component initialization.
+		@return 0 if successfully initialized, -1 otherwise.		
+	*/
+	virtual int DoInitialize() { return 0; }
+
+	/**
+		@brief	Perform the actual component finalization.
+	*/
+	virtual void DoFinish() { }
+
+	/**
+		@brief	Return whether the component is initialized.
+	*/
+	virtual bool IsInitialized() const { return m_initialized; }
+
+	/**
+		@brief	Actual component start.
+	*/
+	virtual int DoStart() { return 0; }
+
+	/**
+		@brief	Actual component stop.
+	*/
+	virtual void DoStop() {}
+
+	/**
+		@brief Registers a new input pin. 
+		@return -1 when error (pin already registered).
+	*/
+	int RegisterInputPin(IInputPin & pin) {
+		std::vector<IInputPin*>::iterator it= find (m_inputPins.begin(), m_inputPins.end(), &pin);
+  		if (it!= m_inputPins.end())	return -1; // Already registered
+
+  		pin.AddRef();
+  		m_inputPins.push_back (&pin);
+
+  		return 0;
+	}
+
+	/**
+		@brief Registers a new output pin. 
+		@return -1 when error (pin already registered).
+	*/
+	int RegisterOutputPin(IOutputPin & pin) {
+		std::vector<IOutputPin*>::iterator it= find (m_outputPins.begin(), m_outputPins.end(), &pin);
+  		if (it!= m_outputPins.end()) return -1; // Already registered
+
+  		pin.AddRef();
+  		m_outputPins.push_back (&pin);
+
+  		return 0;
+	}
+
+private:
+	bool m_initialized;
+	std::vector<IInputPin *> m_inputPins;
+	std::vector<IOutputPin *> m_outputPins;
+	std::string m_name;
+};
+
+/**
+	@brief Adapter class to implement IComponent conforming classes which,
+	in turn, need composition support.
+*/
+class CCompositeComponentAdapter : public CComponentAdapter {
+public:
+	CCompositeComponentAdapter(const char * name, int argc, const char * argv[])
+	: CComponentAdapter(name, argc, argv) { }
+	
+	virtual ~CCompositeComponentAdapter() {
+		Stop();
+		Finish();
+		// Delete components
+		for (std::vector<IComponent*>::iterator it= m_components.begin(); it!= m_components.end(); ++it)
+			(*it)->Release();
+	}
+	
+
+	virtual int AddChild(SmartPtr<IComponent> component) {
+		std::vector<IComponent*>::iterator it= m_components.begin();
+
+		for(; it!= m_components.end(); ++it) {
+			// Check if the component (by pointer) has been already registered.
+			// TODO: check that component is not registered (comparing pointers)
+			// anywhere in this component composite
+			if ((*it)== component.get()) break;
+
+			// Check also by name
+			if (strcmp((*it)->GetName(), component->GetName())== 0) break;
+		}
+
+		if (it!= m_components.end()) {
+			// Component already registered
+			return -1;
+		}
+
+		// Finaly add component to vector
+		component->AddRef();
+		m_components.push_back(component.get());
+
+		return 0;
+	}
+
+	virtual SmartPtr<IIterator<IComponent*> > QueryComponents() {
+		return SmartPtr<IIterator<IComponent*> >(new CIteratorVector<IComponent*>(m_components), false);
+	}
+
+	virtual int Start() {
+		int retval= Initialize();
+		if (retval!= 0) return retval;
+
+		std::vector<IComponent*>::iterator it;
+		for (it= m_components.begin(); retval== 0 && it!= m_components.end(); ++it)
+			retval= (*it)->Start();
+
+		if (retval!= 0) Stop();
+
+		return retval;
+	}
+
+	virtual void Stop() {
+		std::vector<IComponent*>::iterator it;
+		for (it= m_components.begin(); it!= m_components.end(); ++it)
+			(*it)->Stop();
+	}
+
+	virtual int Initialize() {
+		int retval= 0;
+
+		retval= DoInitialize();
+		if (retval) return retval;
+
+		std::vector<IComponent*>::iterator it;
+		for (it= m_components.begin(); retval== 0 && it!= m_components.end(); ++it)
+			retval= (*it)->Initialize();
+
+		if (retval!= 0) Finish();
+
+		return retval;
+	}
+
+	virtual void Finish() {
+		Stop();
+		DoFinish();
+		std::vector<IComponent*>::iterator it;
+		for (it= m_components.begin(); it!= m_components.end(); ++it)
+			(*it)->Finish();
+	}
+
+private:
+	std::vector<IComponent *> m_components;
+};
+
+/**
+	@brief Interface class for factories of components.
+*/
+class IComponentFactory : public IBaseObject {
+protected:
+	virtual ~IComponentFactory() {}
+
+public:
+	/**
+		@brief Return the name of the type of components this factory creates.
+		@return Pointer to an internally managed string.
+	*/
+	virtual const char* GetName() const = 0;
+
+	/**
+		@brief Create a new component instance.
+		@param name Name the component will be given.
+		@param argc Number of arguments passed to the parameter argv.
+		@param argv Array of parameters (can be NULL if argc==0).
+		@return Smart pointer to the newly created component which can contain NULL if an error ocurred.
+	*/
+	virtual SmartPtr<IComponent> CreateInstance(const char * name, int argc, const char * argv[]) = 0;
+};
+
+/**
+	@brief Connects an output pin of a component with an input of another component.
+	@param srcComponent Source component.
+	@param srcPin Number of order of the output of the source component.
+	@param dstComponent Destination component.
+	@param dstPin Number of order of the input of the destination component.
+	@return 0 when success
+	@return -1 invalid component
+	@return -2 trying to connect the component with itself
+	@return -3 invalid pin number
+	@return -4 pin type mismatch
+
+	Uses pin number to refer to a specific pin
+*/
+inline int Connect(IComponent * srcComponent, unsigned int srcPin, IComponent * dstComponent, unsigned int dstPin) {
+  	if (srcComponent== NULL || dstComponent== NULL) return -1;	// Invalid component
+  	if (srcComponent== dstComponent) return -2;	// Forbids connecting pins of the same component
+
+  	unsigned int i;
+	SmartPtr<IIterator<IOutputPin*> > itop= srcComponent->GetOutputPins();
+  	itop->First();
+  	i= 0;
+  	while (i!= srcPin && !itop->IsDone()) {
+  		itop->Next();
+  		++i;
+  	}
+  	if (itop->IsDone()) return -3;	// Invalid pin number
+
+  	SmartPtr<IIterator<IInputPin*> > itip= dstComponent->GetInputPins();
+  	itip->First();
+  	i= 0;
+  	while (i!=dstPin && !itip->IsDone()) {
+  		itip->Next();
+  		++i;
+  	}
+  	if (itip->IsDone()) return -3; // Invalid pin number
+
+  	if (itop->CurrentItem()->Connect (*(itip->CurrentItem()))!= 0) return -4; // Pin type mismatch
+
+  	return 0;
+}
+
+/**
+	@brief Connects an output pin of a component with an input of another component.
+	@param srcComponent Source component.
+	@param srcPin Namne of the output of the source component.
+	@param dstComponent Destination component.
+	@param dstPin Name of the input of the destination component.
+	@return 0 when success
+	@return -1 invalid component
+	@return -2 trying to connect the component with itself
+	@return -3 invalid pin number
+	@return -4 pin type mismatch
+*/
+inline int Connect(IComponent * srcComponent, const char * srcPin, IComponent * dstComponent, const char * dstPin) {
+  	if (srcComponent== NULL || dstComponent== NULL) return -1;	// Invalid component
+  	if (srcComponent== dstComponent) return -2;	// Forbids connecting pins of the same component
+	if (srcPin== NULL || dstPin== NULL) return -3;	// Invalid pin name
+
+  	SmartPtr<IIterator<IOutputPin*> > itop= srcComponent->GetOutputPins();
+	for (itop->First(); !itop->IsDone(); itop->Next()) {
+		if (strcmp(srcPin, itop->CurrentItem()->GetName())== 0) break;
+	}
+	if (itop->IsDone()) return -3;	// Invalid pin name
+
+  	SmartPtr<IIterator<IInputPin*> > itip= dstComponent->GetInputPins();
+  	for (itip->First(); !itip->IsDone(); itip->Next()) {
+		if (strcmp(dstPin, itip->CurrentItem()->GetName())== 0) break;
+	}
+  	if (itip->IsDone()) return -3; // Invalid pin name
+
+  	if (itop->CurrentItem()->Connect (*(itip->CurrentItem()))!= 0) return -4; // Pin type mismatch
+
+  	return 0;
+}
+
+/**
+	@brief Helper template class to create simple component factories.
+
+	@tparam COTYPE Type of the component.
+*/
+template <typename COTYPE>
+class ComponentFactory : public spcore::IComponentFactory {
+	BOOST_STATIC_ASSERT( (boost::is_base_of<IComponent,COTYPE>::value) );
+
+public:
+	virtual const char* GetName() const { return COTYPE::getTypeName(); }
+
+	virtual SmartPtr<IComponent> CreateInstance(const char * name, int argc, const char * argv[]) {
+		std::string exceptionMessage;
+		try {
+			return SmartPtr<IComponent>(new COTYPE(name, argc, argv), false);
+		}
+		catch(std::exception& e) {
+			exceptionMessage= e.what();
+		}
+		catch(...) {
+			exceptionMessage= "unexpected error creating component: " + std::string(name);
+		}
+		// If code reaches this point means that an exception has been raised
+		// signal this error condition by adding a log entry and retuning a
+		// null instance
+		std::string msg("error creating instance:");
+		msg.append(name);
+		if (exceptionMessage.size()> 0) {
+			msg.append (":");
+			msg.append (exceptionMessage);
+		}
+		getSpCoreRuntime()->LogMessage(ICoreRuntime::LOG_ERROR, msg.c_str(), "spcore");
+		return SmartPtr<IComponent>(NULL);
+	}
+};
+
+/**
+	@brief Helper template to create simple singleton component factories.
+
+	@tparam COTYPE Type of the component.
+*/
+template <typename COTYPE>
+class SingletonComponentFactory : public spcore::IComponentFactory {
+	BOOST_STATIC_ASSERT( (boost::is_base_of<IComponent,COTYPE>::value) );
+
+public:
+	virtual const char* GetName() const { return COTYPE::getTypeName(); }
+
+	virtual SmartPtr<IComponent> CreateInstance(const char * name, int argc, const char * argv[]) {
+		if (m_instance.get()) return m_instance;
+
+		// Crete instance for the first time
+		std::string exceptionMessage;
+		try {
+			m_instance= SmartPtr<COTYPE>(new COTYPE(name, argc, argv), false);
+			return m_instance;
+		}
+		catch(std::exception& e) {
+			exceptionMessage= e.what();
+		}
+		catch(...) {
+			exceptionMessage= "unexpected error creating component: " + std::string(name);
+		}
+		// If code reaches this point means that an exception has been raised
+		// signal this error condition by adding a log entry and retuning a
+		// null instance
+		assert (m_instance.get()== NULL);
+		std::string msg("error creating instance:");
+		msg.append(name);
+		if (exceptionMessage.size()> 0) {
+			msg.append (":");
+			msg.append (exceptionMessage);
+		}
+		getSpCoreRuntime()->LogMessage(ICoreRuntime::LOG_ERROR, msg.c_str(), "spcore");
+		return SmartPtr<IComponent>(NULL);
+	}
+private:
+	SmartPtr<COTYPE> m_instance;
+};
+
+} // namespace spcore
+#endif
diff --git a/include/spcore/configuration.h b/include/spcore/configuration.h
new file mode 100644
index 0000000..0c25b59
--- /dev/null
+++ b/include/spcore/configuration.h
@@ -0,0 +1,158 @@
+/**
+* @file		configuration.h
+* @brief	Interfaces for loading/storing configuration values.
+* @author	Cesar Mauri Loba (cesar at crea-si dot com)
+*
+* -------------------------------------------------------------------------
+*
+* Copyright:   (C) 2010 Cesar Mauri Loba - CREA Software Systems
+*
+*  This program is free software: you can redistribute it and/or modify
+*  it under the terms of the GNU General Public License as published by
+*  the Free Software Foundation, either version 3 of the License, or
+*  (at your option) any later version.
+*
+*  This program is distributed in the hope that it will be useful,
+*  but WITHOUT ANY WARRANTY; without even the implied warranty of
+*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+*  GNU General Public License for more details.
+*
+*  You should have received a copy of the GNU General Public License
+*  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+#ifndef SPCORE_CONFIGURATION_H
+#define SPCORE_CONFIGURATION_H
+
+#include "spcore/baseobj.h"
+#include <stdio.h>
+
+namespace spcore {
+
+/**
+	@brief Interface class for configuration objects.
+
+	Paths may consist only of alphanumeric characters, dashes (�-�) and 
+	underscores (�_�). Slash character "/" is used to separate levels. 
+	If the first character is '/' denotes an absolute path, otherwise 
+	it is a relative to the current path. The current path can be changed 
+	using the SetPath() method.
+*/
+class IConfiguration : public IBaseObject {
+protected:
+	virtual ~IConfiguration() {}
+
+public:
+
+	/**
+		@brief Load configuration from file.
+		@param instream opened input file stream.
+		@return true when loaded successfully, false when error.
+	*/
+	virtual bool Load (FILE* instream)= 0;
+
+	/**
+		@brief Save current configuration to file.
+		@param outstream opened output file stream.
+		@return true when saved successfully, false when error.
+	*/
+	virtual bool Save (FILE* outstream) const= 0;
+   
+	/**
+		@brief Read a string.
+		@param path path that uniquely identifies the key.
+		@param str read string (storage is managed internally, so
+			the pointer SHOULD NOT be freed).
+		@return true if the value was read.
+	*/
+	virtual bool ReadString (const char* path, const char** str) const= 0;
+	
+	/**
+		@brief Read an integer.
+		@param path path that uniquely identifies the key.
+		@param i pointer to where the read value will be stored.
+		@return true if the value was read.
+	*/
+	virtual bool ReadInt (const char* path, int* i) const= 0;
+	
+	/**
+		@brief Read a 64bit integer.
+		@param path path that uniquely identifies the key.
+		@param i pointer to where the read value will be stored.
+		@return true if the value was read.
+	*/
+	virtual bool ReadInt64 (const char* path, long long* i) const= 0;
+	
+	/**
+		@brief Read a double.
+		@param path path that uniquely identifies the key.
+		@param d pointer to where the read value will be stored.
+		@return true if the value was read.
+	*/
+	virtual bool ReadDouble (const char* path, double* d) const= 0;
+	
+	/**
+		@brief Read a boolean.
+		@param path path that uniquely identifies the key.
+		@param b pointer to where the read value will be stored.
+		@return true if the value was read.
+	*/
+	virtual bool ReadBool (const char* path, bool* b) const= 0;
+	
+	
+	/**
+		@brief Write a string.
+		@param path path that uniquely identifies the key.
+		@param str string to write.
+		@return true if the value was written.
+	*/
+	virtual bool WriteString (const char* path, const char* str)= 0;
+	
+	/**
+		@brief Write an integer.
+		@param path path that uniquely identifies the key.
+		@param i integer to write.
+		@return true if the value was written.
+	*/
+	virtual bool WriteInt (const char* path, int i)= 0;
+	
+	/**
+		@brief Write a 64bit integer.
+		@param path path that uniquely identifies the key.
+		@param i 64bit integer to write.
+		@return true if the value was written.
+	*/
+	virtual bool WriteInt64 (const char* path, long long i)= 0;
+	
+	/**
+		@brief Write a double.
+		@param path path that uniquely identifies the key.
+		@param d floating point value to write.
+		@return true if the value was written.
+	*/
+	virtual bool WriteDouble (const char* path, double d)= 0;
+	
+	/**
+		@brief Write a boolean.
+		@param path path that uniquely identifies the key.
+		@param b value to write.
+		@return true if the value was written.
+	*/
+	virtual bool WriteBool (const char* path, bool b)= 0;
+	
+	/**
+		@brief Removes an element given its path.
+		@param path path that uniquely identifies the key.
+		@return true if the value was removed.
+	*/
+	virtual bool Remove (const char* path)= 0;
+
+	/**
+		@brief Set current path.
+		@param path New path to change to. '..' is supported. If path does not exists it is created.
+		@return true if the path was successfully set. 
+	*/
+	virtual bool SetPath (const char* path)= 0;
+};
+
+} // namespace spcore
+#endif
diff --git a/include/spcore/conversion.h b/include/spcore/conversion.h
new file mode 100644
index 0000000..62c86c2
--- /dev/null
+++ b/include/spcore/conversion.h
@@ -0,0 +1,70 @@
+/**
+* @file		conversion.h
+* @brief	Locale independent string to number conversion functions.
+* @author	Cesar Mauri Loba (cesar at crea-si dot com)
+*
+* -------------------------------------------------------------------------
+*
+* Copyright:   (C) 2010 Cesar Mauri Loba - CREA Software Systems
+*
+*  This program is free software: you can redistribute it and/or modify
+*  it under the terms of the GNU General Public License as published by
+*  the Free Software Foundation, either version 3 of the License, or
+*  (at your option) any later version.
+*
+*  This program is distributed in the hope that it will be useful,
+*  but WITHOUT ANY WARRANTY; without even the implied warranty of
+*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+*  GNU General Public License for more details.
+*
+*  You should have received a copy of the GNU General Public License
+*  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "spcore/libimpexp.h"
+
+namespace spcore {
+
+/**
+	@brief Converts a string into a float.
+	@return true is conversion successful, or false otherwise.
+*/
+SPEXPORT_FUNCTION 
+bool StrToFloat (const char* str, float* val);
+
+/**
+	@brief Converts a string into a double.
+	@return true is conversion successful, or false otherwise.
+*/
+SPEXPORT_FUNCTION 
+bool StrToDouble (const char* str, double* val);
+
+/**
+	@brief Converts a string into a long double.
+	@return true is conversion successful, or false otherwise.
+*/
+SPEXPORT_FUNCTION 
+bool StrToLongDouble (const char* str, long double* val);
+
+/**
+	@brief Converts a string into a int.
+	@return true is conversion successful, or false otherwise.
+*/
+SPEXPORT_FUNCTION 
+bool StrToInt (const char* str, int* val);
+
+/**
+	@brief Converts a string into an unsigned int.
+	@return true is conversion successful, or false otherwise.
+*/
+SPEXPORT_FUNCTION 
+bool StrToUint (const char* str, unsigned int* val);
+
+/**
+	@brief Converts a string into a long.
+	@return true is conversion successful, or false otherwise.
+*/
+SPEXPORT_FUNCTION 
+bool StrToLongInt (const char* str, long* val);
+
+} // namespace spcore
diff --git a/include/spcore/coreruntime.h b/include/spcore/coreruntime.h
new file mode 100644
index 0000000..0d322e3
--- /dev/null
+++ b/include/spcore/coreruntime.h
@@ -0,0 +1,293 @@
+/**
+* @file		coreruntime.h
+* @brief	Interface class for lib-sitplus core functions.
+* @author	Cesar Mauri Loba (cesar at crea-si dot com)
+*	
+* -------------------------------------------------------------------------
+*
+* Copyright:   (C) 2010 Cesar Mauri Loba - CREA Software Systems
+*
+*  This program is free software: you can redistribute it and/or modify
+*  it under the terms of the GNU General Public License as published by
+*  the Free Software Foundation, either version 3 of the License, or
+*  (at your option) any later version.
+*
+*  This program is distributed in the hope that it will be useful,
+*  but WITHOUT ANY WARRANTY; without even the implied warranty of
+*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+*  GNU General Public License for more details.
+*
+*  You should have received a copy of the GNU General Public License
+*  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+#ifndef SPCORE_CORERUNTIME_H
+#define SPCORE_CORERUNTIME_H
+
+#include "spcore/libimpexp.h"
+#include "spcore/baseobj.h"
+#include "config.h"		// ENABLE_WXWIDGETS define
+
+/**
+One of the goals of SITPLUS is to become GUI toolkit agnostic.
+Currently it uses wxWidgets and most modules provide GUI's based on this 
+toolkit, but the core itself has not an strong dependency (component's 
+method GetGUI expects wxWindows and wxPanel types though this is easyly 
+changeable by just defining a neutral window type, the core itself 
+provides methods such as InitGUISupport, RunMessageLoop and 
+CleanupGUISupport which are based on wx).
+
+ at todo provide an interface for non-wx apps and/or other toolkits
+and set this define as a build parameter
+*/
+
+#ifndef ENABLE_WXWIDGETS
+#error "Currently wxWidgets is necessary"
+#endif
+
+namespace spcore {
+
+// Forward class declarations
+template<class T> class IIterator;
+class ITypeFactory;
+class CTypeAny;
+class IComponentFactory;
+class IComponent;
+class IModule;
+class IInputPin;
+class IOutputPin;
+class IConfiguration;
+class ILogTarget;
+
+/**
+	@brief Interface class for lib-sitplus core functions.
+
+	Call spcore::getSpCoreRuntime() to get the only instance of the class 
+	that implements the core interface.
+**/
+class ICoreRuntime {
+public:
+	virtual ~ICoreRuntime() {}
+
+	/**
+		@brief Get the runtime ID of a named type.
+		@param name type name
+		@return the ID or TYPE_INVALID if the specified type doesn't exists.
+	**/
+	virtual int ResolveTypeID(const char * name) = 0;
+
+	/**
+		@brief Get all registered types.
+		@return an iterator to a collection of type factories.
+	**/
+	virtual SmartPtr<IIterator<ITypeFactory*> > QueryTypes() = 0;
+
+	/**
+		@brief Creates a new instance of certain type given its name.
+		@param typeName type name.
+		@return pointer to the new instance or NULL if the type doesn't exists 
+			or another error occurred.
+	**/
+	virtual SmartPtr<CTypeAny> CreateTypeInstance(const char * typeName) = 0;
+
+	/**
+		@brief Creates a new instance of certain type given its ID.
+		@param id type identifier.
+		@return pointer to the new instance or NULL if the type doesn't exists 
+			or another error occurred.
+	**/
+	virtual SmartPtr<CTypeAny> CreateTypeInstance(int id) = 0;
+
+	/**
+		@brief Get all registered components.
+		@return an iterator to a collection of component factories.
+	**/
+	virtual SmartPtr<IIterator<IComponentFactory*> > QueryComponents() = 0;
+
+	/**
+		@brief Create a new instance of a component.
+		@param typeName name of the component type.
+		@param name name given to the new instance.
+		@param argc number of arguments provided in argv array.
+		@param argv array of arguments.
+		@return smart pointer to the newly created component or NULL when error.
+
+		Creates a new instance of the component of type "typeName" and names it with
+		"name". Specific values for argc and argv are component type dependent.
+	**/
+	virtual SmartPtr<IComponent> CreateComponent(const char * typeName, const char * name, int argc, const char * argv[]) = 0;
+
+	/**
+		@brief Create an instance of an output pin.
+		@param type name of the type of the pin.
+		@param name name given to the pin.
+		@param locked if it is true constructs a looked (synchronized) pin.
+		@return smart pointer to the new pin or NULL when error.
+	**/
+	virtual SmartPtr<IOutputPin> CreateOutputPin(const char* type, const char* name, bool locked) = 0;
+
+	/**    
+		@brief Register a module inside spcore.
+		@param module module instance.
+		@return	0 on success,
+				-1 : module already registered,
+				-2 : wrong core version,
+				-3 : type name already registered,
+				-4 : component already registered.
+    **/
+	virtual int RegisterModule(SmartPtr<IModule> module) = 0;
+
+	/**
+		@brief Load and register a module.
+		@param name name of the shared library to load.
+		@param dir path where look for library files. If dir is NULL then
+			current working directory and system library paths are searched.
+		@return 0 on success,
+				-1 : module already registered,
+				-2 : wrong core version,
+				-3 : type name already registered,
+				-4 : component already registered,
+				-5 : defective element provided in library (e.g. anonymous factory),
+				-6 : library not found,
+				-7 : wrong library format (symbol not found),
+				-8 : no module.
+	**/
+	virtual int LoadModule(const char * name, const char * dir = NULL) = 0;
+
+	/**
+		@brief Log severity levels.
+	*/
+	enum LogSeverityLevel { 
+		LOG_FATAL= 0,	/**< reserved for special exceptions/conditions when recovery is not possible. */
+		LOG_ERROR,		/**< used to log all unhandled exceptions which prevent the application runing properly. */
+		LOG_WARNING,	/**< often used for handled 'exceptions' or other important log events. */
+		LOG_INFO,		/**< typically used to output information that is useful for the running and 
+							management of the system. */
+		LOG_DEBUG		/**< is the most verbose logging level. Only for development and testing. */
+	};
+
+	/**
+		@brief Send a message to the logging subsystem.
+		@param severity severity level of the message
+		@param message message to log
+		@param module module name (deprecated)
+	*/
+	virtual void LogMessage (LogSeverityLevel severity, const char* message, const char* module= NULL)= 0;
+
+	/**
+		@brief Register a new log target.
+		@param lt pointer to the log target to register.
+
+		After calling this method all log messages will be (also) sent to the registered target.
+		If the target was previously registered the request is ignored silently.
+	*/
+	virtual void RegisterLogTarget (ILogTarget* lt)= 0;
+
+	/**
+		@brief Unregister a log target.
+		@param lt pointer to the log target to unregister.
+	*/
+	virtual void UnregisterLogTarget (ILogTarget* lt)= 0;
+
+	/**
+		@brief Construct and return an IConfiguration object.
+		@return smart pointer to a new IConfiguration object.
+		@todo Remove this method and allow to create IConfiguration instances directly.
+	*/
+	virtual SmartPtr<IConfiguration> GetConfiguration() const= 0;
+
+	/**
+		@brief Return whether the caller thread is the main one.
+		@todo provide a regular function.
+	*/
+	virtual bool IsMainThread () const= 0;
+
+#ifdef ENABLE_WXWIDGETS
+
+	/**
+		@brief Initializes GUI subsystem (currently only wxWidgets is supported).
+		@return 0 on successful initialization or -1 when error
+
+		This method must be called before creating any window or calling RunMessageLoop.
+	*/
+	virtual int InitGUISupport (int argc, char** argv)= 0;
+
+	/**
+		@brief Runs the main message loop.
+		@return exit code
+
+		This function does not return until the last frame window has been destroyed 
+		as the regular wx message loop does.
+	*/
+	virtual int RunMessageLoop ()= 0;
+
+	/**
+		@brief Finalizes GUI subsystem (wxWidgets currently)
+
+		This method must be called after RunMessageLoop	has exited.
+	*/
+	virtual void CleanupGUISupport ()= 0;
+
+	/**
+		Forwards a message via the application main thread to the destination pin.
+		This method waits until the event has been processed.
+
+		\return		0:	message successfully sent
+					-1:	type mismatch or message could not be send
+		@todo remove this method (ans its implementation).
+	*/
+	virtual int SendMessageMainThreadSync (SmartPtr<const CTypeAny> msg, IInputPin & dst)= 0;
+
+	/**
+		@brief Callback type for SendMessageMainThreadAsync method.		
+	*/
+	typedef void ToMainThreadCallback (IComponent*, const CTypeAny*);
+
+	/**
+		@brief Forwards a message via the application main thread to a callback.
+
+		Some GUI toolkits (such as wx) and other libraries (e.g. SDL) only work 
+		properly when its API is called from the main thread. This method allows
+		to store a message which the application main thread will collect and 
+		deliver through a callback (i.e. asynchronously). Note that, though is 
+		possible to send a message synchronously (i.e. waiting until the main 
+		thread has delivered the message) this approach could easily cause a 
+		deadlock and so is not recommendable.
+	*/	
+	virtual void SendMessageMainThreadAsync (const CTypeAny&, IComponent&, ToMainThreadCallback*)= 0;
+
+#endif
+};
+
+/**
+	@brief Interface class for log targets.
+*/
+class ILogTarget
+{
+public:
+	/**
+		@brief Function which will be called each time a log message is received.
+		@param severity
+		@param message
+	*/
+	virtual void LogMessage (ICoreRuntime::LogSeverityLevel severity, const char* message)= 0;
+};
+
+/**
+	@brief Get the ICoreRuntime instance.
+	@return pointer to the ICoreRuntime instance.
+	The first call to this method will create the appropiate ICoreRuntime implementation instance.
+*/
+SPEXPORT_FUNCTION 
+ICoreRuntime* getSpCoreRuntime();
+
+/**
+	@brief Clean up the ICoreRuntime instance.
+
+	Free resources allocated by the ICoreRuntime instance. Should be called just before.
+	exiting your host application.
+*/
+SPEXPORT_FUNCTION 
+void freeSpCoreRuntime();
+
+} // namespace spcore
+#endif
diff --git a/include/spcore/coreversion.h b/include/spcore/coreversion.h
new file mode 100644
index 0000000..8d80895
--- /dev/null
+++ b/include/spcore/coreversion.h
@@ -0,0 +1,31 @@
+/**
+* @file		coreversion.h
+* @brief	Header which provide the current version of the core.
+* @author	Cesar Mauri Loba (cesar at crea-si dot com)
+* @todo		get values from CMakeLists.txt
+*
+* -------------------------------------------------------------------------
+*
+* Copyright:   (C) 2010 Cesar Mauri Loba - CREA Software Systems
+* 
+*  This program is free software: you can redistribute it and/or modify
+*  it under the terms of the GNU General Public License as published by
+*  the Free Software Foundation, either version 3 of the License, or
+*  (at your option) any later version.
+*
+*  This program is distributed in the hope that it will be useful,
+*  but WITHOUT ANY WARRANTY; without even the implied warranty of
+*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+*  GNU General Public License for more details.
+*
+*  You should have received a copy of the GNU General Public License
+*  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+#ifndef SPCORE_VERSION_H
+#define SPCORE_VERSION_H
+
+// Version number
+#define SPCORE_VERSION	1
+
+
+#endif
diff --git a/include/spcore/iterator.h b/include/spcore/iterator.h
new file mode 100644
index 0000000..7410d37
--- /dev/null
+++ b/include/spcore/iterator.h
@@ -0,0 +1,96 @@
+/**
+* @file		iterator.h
+* @brief	Iterators implementation.
+* @author	Cesar Mauri Loba (cesar at crea-si dot com)
+*	
+* -------------------------------------------------------------------------
+*
+* Copyright:   (C) 2010-12 Cesar Mauri Loba - CREA Software Systems
+* 
+*  This program is free software: you can redistribute it and/or modify
+*  it under the terms of the GNU General Public License as published by
+*  the Free Software Foundation, either version 3 of the License, or
+*  (at your option) any later version.
+*
+*  This program is distributed in the hope that it will be useful,
+*  but WITHOUT ANY WARRANTY; without even the implied warranty of
+*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+*  GNU General Public License for more details.
+*
+*  You should have received a copy of the GNU General Public License
+*  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+#ifndef SPCORE_ITERATOR_H
+#define SPCORE_ITERATOR_H
+
+#include "spcore/baseobj.h"
+#include <vector>
+#include <map>
+
+namespace spcore {
+
+/**
+	@brief Interface for iterators
+
+	Based on GOF iterator pattern
+**/
+template<class T>
+class IIterator : public IBaseObject {
+protected:
+	virtual ~IIterator() {}
+
+public:
+	virtual void First() = 0;
+	virtual void Next() = 0;
+	virtual bool IsDone() const = 0;
+	virtual T CurrentItem() const = 0;
+};
+
+/**
+	@brief Iterator implementation for std::vector
+**/
+template<class T>
+class CIteratorVector : public IIterator<T> {
+public:
+	CIteratorVector(const std::vector<T> & vector) {
+		m_vector= &vector;
+		m_iterator= vector.begin();
+	}
+
+	virtual ~CIteratorVector() { m_vector= NULL; }
+
+	virtual void First() { m_iterator= m_vector->begin(); }
+	virtual void Next() { ++m_iterator; }
+	virtual bool IsDone() const { return (m_iterator== m_vector->end()); }
+	virtual T CurrentItem() const { return (*m_iterator); }
+
+private:
+	const std::vector<T>* m_vector;
+	typename std::vector<T>::const_iterator m_iterator;
+};
+
+/**
+	@brief Iterator implementation for std::map
+**/
+template<class KEY, class VALUE>
+class CIteratorMap : public IIterator<VALUE> {
+public:
+	CIteratorMap(const std::map<KEY,VALUE> & map) {
+		m_map= ↦
+		m_iterator= map.begin();
+	}
+
+	virtual ~CIteratorMap() { m_map= NULL; }
+
+	virtual void First() { m_iterator= m_map->begin(); }
+	virtual void Next() { ++m_iterator; }
+	virtual bool IsDone() const { return (m_iterator== m_map->end()); }
+	virtual VALUE CurrentItem() const { return (m_iterator->second); }
+
+private:
+	const std::map<KEY,VALUE>* m_map;
+	typename std::map<KEY,VALUE>::const_iterator m_iterator;
+};
+
+} // namespace spcore
+#endif
diff --git a/include/spcore/language.h b/include/spcore/language.h
new file mode 100644
index 0000000..ac0899c
--- /dev/null
+++ b/include/spcore/language.h
@@ -0,0 +1,179 @@
+/**
+* @file		language.h
+* @brief	i18n related functions.
+* @author	Cesar Mauri Loba (cesar at crea-si dot com)
+*
+* -------------------------------------------------------------------------
+*
+* Copyright:   (C) 2010-12 Cesar Mauri Loba - CREA Software Systems
+* 
+*  This program is free software: you can redistribute it and/or modify
+*  it under the terms of the GNU General Public License as published by
+*  the Free Software Foundation, either version 3 of the License, or
+*  (at your option) any later version.
+*
+*  This program is distributed in the hope that it will be useful,
+*  but WITHOUT ANY WARRANTY; without even the implied warranty of
+*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+*  GNU General Public License for more details.
+*
+*  You should have received a copy of the GNU General Public License
+*  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+#pragma once
+#include "config.h"
+#include "spcore/libimpexp.h"
+
+#ifdef ENABLE_NLS
+
+	enum spLanguage	{
+		// Language identifiers. Based on <wx/intl.h>. 
+		// New supported languages to be added as necessary.
+		spLANGUAGE_FIRST= 0,
+		spLANGUAGE_DEFAULT= spLANGUAGE_FIRST,
+		spLANGUAGE_UNKNOWN,		
+		spLANGUAGE_BASQUE,
+		spLANGUAGE_CATALAN,
+		spLANGUAGE_CHINESE,
+		spLANGUAGE_ENGLISH,
+		spLANGUAGE_FRENCH,
+		spLANGUAGE_GALICIAN,
+		spLANGUAGE_GERMAN,
+		spLANGUAGE_GREEK,
+		spLANGUAGE_HEBREW,
+		spLANGUAGE_ITALIAN,
+		spLANGUAGE_JAPANESE,
+		spLANGUAGE_PORTUGUESE,
+		spLANGUAGE_RUSSIAN,
+		spLANGUAGE_SPANISH,
+		spLANGUAGE_SWEDISH,
+		spLANGUAGE_TURKISH,
+		spLANGUAGE_LAST
+	};
+
+	#ifdef ENABLE_WXWIDGETS
+		#include <wx/intl.h>
+	#endif
+
+	/**
+		@brief _(), __(), N_() and N__() macros
+
+		Macro _() is usually defined by some frameworks such as wx 
+		which usually expect unicode strings (UTF-16 on Win32 or UTF-32 on 
+		Unix), so we define our own translation macro __() for UTF-8 strings.
+		The N_ and N__ macros are used to mark string to be extracted but not
+		translated when found.
+	*/
+	#ifndef _
+		#define _(STRING)	spGettext(STRING)
+	#endif
+
+	#ifndef N_
+		#define N_(STRING)	(STRING)
+	#endif
+	
+	#define __(STRING)	spGettext(STRING)
+	#define N__(STRING)	(STRING)
+
+	/**
+		@brief Attempt to translate a text string into user's native language, by looking
+		looking all domains (in order) provided by spBindTextDomain
+		@param[in]	msgid	string to translate
+		@return If a translation was found, it is converted  to  the  locale's codeset 
+		and returned. The resulting string is statically allocated and must not be modified 
+		or freed. Otherwise msgid is returned.
+	*/
+	SPEXPORT_FUNCTION
+	const char * spGettext (const char * msgid);
+
+	/**
+		@brief Attempt to translate a text string into user's native language, by looking
+		a specific domain
+		@param[in]	domainname	name of the domain to look
+		@param[in]	msgid		string to translate
+		@return If a translation was found, it is converted  to  the  locale's codeset 
+		and returned. The resulting string is statically allocated and must not be modified 
+		or freed. Otherwise msgid is returned.
+	*/
+	SPEXPORT_FUNCTION
+	const char * spDGettext (const char * domainname, const char * msgid);
+
+	/**
+		@brief Set locale configuration given a language identifier (spLanguage enum value)
+		@param[in]	id	Language identifier.
+		@return 0 if ok, -1 if failed.
+
+		Caveats: this funtion should be called once, otherwise the behaviour is undefined.
+	*/
+	SPEXPORT_FUNCTION
+	int spSetLanguage (int id);
+
+	/**
+		@brief Get current locale configuration (spLanguage enum value)
+		@return language identifier or -1 if language has not been set.
+
+		The returned value is not suitable for storage purposes. See spGetLocaleId instead.
+	*/
+	SPEXPORT_FUNCTION
+	int spGetLanguage ();
+
+
+	/**
+		@brief Checks if a language id is valid.
+		@return true is valid, false otherwise.
+	*/
+	SPEXPORT_FUNCTION
+	bool isLanguageValid (int id);
+
+	/**
+		@brief set directory containing message catalogs
+		@param[in]	domain	Domain name.
+		@param[in]	dirname	Directory name.
+		@return 0 if OK, -1 if error.
+
+		Before calling this function the language must be set.
+	*/
+	SPEXPORT_FUNCTION
+	int spBindTextDomain(const char* domain, const char* dirname);
+
+	/**
+		@brief Obtains the number of available languages.
+		@return the number of available languages.
+	*/
+	SPEXPORT_FUNCTION
+	int spGetAvailableLanguages();
+
+	/**
+		@brief Obtains the locale identifier given the language id.
+		@param[in]	id	Language identifier. 
+		@return a pointer to an string whith the locale name or NULL if error.
+
+		The returned locale identifier can be stored and used later.
+	*/
+	SPEXPORT_FUNCTION
+	const char* spGetLocaleId (int id);
+
+	/**
+		@brief Obtains the language identifier given a locale identifier.
+		@param[in] locale identifier. 
+		@return language identifier or -1 if locale not found.
+	*/
+	SPEXPORT_FUNCTION
+	int spResolveLocaleId (const char* locale);
+
+	/**
+		@brief Obtains the language name given its language identifier.
+		@param[in]	id	Index of the parameter.
+		@param[in]	domain	When not NULL chooses the domain to translate "System 
+			default" language into a native version.
+		@return a pointer to an string whith the language name encoded as utf8 
+				or NULL if error.
+	*/
+	SPEXPORT_FUNCTION
+	const char* spGetLanguageNativeName (int id, const char* domain);
+
+#else
+	// If NLS disabled, macros do nothing.
+	#define __(STRING)	(STRING)
+	#define N__(STRING)	(STRING)
+#endif
\ No newline at end of file
diff --git a/include/spcore/libimpexp.h b/include/spcore/libimpexp.h
new file mode 100644
index 0000000..2393b08
--- /dev/null
+++ b/include/spcore/libimpexp.h
@@ -0,0 +1,46 @@
+/**
+* @file		libimpexp.h
+* @brief	Preprocessor macros when bulding dynamic library.
+* @author	Cesar Mauri Loba (cesar at crea-si dot com)
+*
+* -------------------------------------------------------------------------
+*
+* Copyright:   (C) 2010-11 Cesar Mauri Loba - CREA Software Systems
+*
+*  This program is free software: you can redistribute it and/or modify
+*  it under the terms of the GNU General Public License as published by
+*  the Free Software Foundation, either version 3 of the License, or
+*  (at your option) any later version.
+*
+*  This program is distributed in the hope that it will be useful,
+*  but WITHOUT ANY WARRANTY; without even the implied warranty of
+*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+*  GNU General Public License for more details.
+*
+*  You should have received a copy of the GNU General Public License
+*  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+#ifndef LIBEXPORTS_H
+#define LIBEXPORTS_H
+
+#ifdef WIN32
+	#define SPEXPORT_FUNCTION extern "C" __declspec(dllexport)
+	#define SPIMPORT_FUNCTION extern "C" __declspec(dllimport)
+	#define SPEXPORT_CLASS __declspec(dllexport)
+	#define SPIMPORT_CLASS __declspec(dllimport)
+#else
+	#define SPEXPORT_FUNCTION extern "C" 
+	#define SPIMPORT_FUNCTION extern "C" 
+	#define SPEXPORT_CLASS
+	#define SPIMPORT_CLASS
+#endif	// WIN32
+
+////////////////////////
+
+#ifdef SPMAKING_DLL_SPCORE
+	#define SPIMPEXP_CLASS_CORE SPEXPORT_CLASS
+#else
+	#define SPIMPEXP_CLASS_CORE SPIMPORT_CLASS
+#endif	// SPMAKING_DLL_SPCORE
+
+#endif	// LIBEXPORTS_H
diff --git a/include/spcore/module.h b/include/spcore/module.h
new file mode 100644
index 0000000..d569ddd
--- /dev/null
+++ b/include/spcore/module.h
@@ -0,0 +1,146 @@
+/**
+* @file		module.h
+* @brief	Module related stuff.
+* @author	Cesar Mauri Loba (cesar at crea-si dot com)
+*
+* -------------------------------------------------------------------------
+*
+* Copyright:   (C) 2010-12 Cesar Mauri Loba - CREA Software Systems
+* 
+*  This program is free software: you can redistribute it and/or modify
+*  it under the terms of the GNU General Public License as published by
+*  the Free Software Foundation, either version 3 of the License, or
+*  (at your option) any later version.
+*
+*  This program is distributed in the hope that it will be useful,
+*  but WITHOUT ANY WARRANTY; without even the implied warranty of
+*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+*  GNU General Public License for more details.
+*
+*  You should have received a copy of the GNU General Public License
+*  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+#ifndef SPCORE_MODULE_H
+#define SPCORE_MODULE_H
+
+#include "spcore/coreversion.h"
+#include "spcore/basetype.h"
+#include "spcore/iterator.h"
+#include "spcore/component.h"
+#include "spcore/baseobj.h"
+#include <vector>
+
+namespace spcore {
+
+// Forward declarations
+template<class T> class IIterator;
+class ITypeFactory;
+class IComponentFactory;
+class IActivity;
+
+/**
+	@brief Interface class for modules.
+*/
+class IModule : public IBaseObject {
+protected:
+	/**
+		@brief Protected destructor to prevent the use of the delete operator.
+	*/
+	inline virtual ~IModule() {}
+
+public:
+	/**
+		@brief Returns the version of spcore this module was build against.
+		@todo Check this.
+	*/
+	virtual int GetCoreVersion() const = 0;
+
+	/**
+		@brief Returns the version of this.
+		@todo Check this.
+	*/
+	virtual int GetModuleVersion() const = 0;
+
+	/**
+		@brief Return the name of the module.
+		@return Pointer to an internally managed string.
+	*/
+	virtual const char* GetName() const = 0;
+
+	/**
+		@brief Gets a human readable description of the module.
+		@return Pointer to an internally managed string encoded in UTF-8.
+	*/	
+	virtual const char* GetDescription() const = 0;
+
+	/**
+		@brief Get the names of the types this module provides.
+		@return Smart pointer to an iterator (which can be NULL) of type factories.
+	*/
+	virtual SmartPtr<IIterator<ITypeFactory*> > GetTypeFactories() = 0;
+
+	/**
+		@brief Get the names of the components this module provides.
+		@return Smart pointer to an iterator (which can be NULL) of component factories.
+	*/
+	virtual SmartPtr<IIterator<IComponentFactory*> > GetComponentFactories() = 0;
+};
+
+/**
+	@brief Adapter class to create new IModule conforming classes.
+*/
+class CModuleAdapter : public IModule {
+public:
+	virtual ~CModuleAdapter() {
+		std::vector<IComponentFactory *>::iterator itcf;
+  		for (itcf= m_componentFactories.begin(); itcf!= m_componentFactories.end(); ++itcf)
+  			(*itcf)->Release();
+  		m_componentFactories.clear();
+	  
+		std::vector<ITypeFactory *>::iterator ittf;
+  		for (ittf= m_typeFactories.begin(); ittf!= m_typeFactories.end(); ++ittf)
+  			(*ittf)->Release();
+  		m_typeFactories.clear();
+	}
+
+	virtual int GetCoreVersion() const { return SPCORE_VERSION; }
+	virtual int GetModuleVersion() const { return 1; }
+	virtual const char* GetDescription() const { return ""; }
+	virtual SmartPtr<IIterator<ITypeFactory*> > GetTypeFactories() {
+		return SmartPtr<IIterator<ITypeFactory*> >(
+			new CIteratorVector<ITypeFactory*>(m_typeFactories), false);
+	}
+	virtual SmartPtr<IIterator<IComponentFactory*> > GetComponentFactories() {
+		return SmartPtr<IIterator<IComponentFactory*> >(
+			new CIteratorVector<IComponentFactory*>(m_componentFactories), false);
+	}
+
+protected:
+	/**
+		@brief Register a type factory to this module.
+		@param f Smart pointer to a type factory.
+		@return 0 when success
+	*/
+	int RegisterTypeFactory(SmartPtr<ITypeFactory> f) {
+		m_typeFactories.push_back(f.get());
+  		f->AddRef();
+  		return 0;
+	}
+	/**
+		@brief Register a component factory to this module.
+		@param c Smart pointer to a component factory.
+		@return 0 when success
+	*/
+	int RegisterComponentFactory(SmartPtr<IComponentFactory> c) {
+		m_componentFactories.push_back(c.get());
+  		c->AddRef();
+  		return 0;
+	}
+
+private:
+	std::vector<IComponentFactory *> m_componentFactories;
+	std::vector<ITypeFactory *> m_typeFactories;
+};
+
+} // namespace spcore
+#endif
diff --git a/include/spcore/pin.h b/include/spcore/pin.h
new file mode 100644
index 0000000..3a8fa5d
--- /dev/null
+++ b/include/spcore/pin.h
@@ -0,0 +1,189 @@
+/**
+* @file		pin.h
+* @brief	Interface definition for component pins.
+* @author	Cesar Mauri Loba (cesar at crea-si dot com)
+*
+* -------------------------------------------------------------------------
+*
+* Copyright:   (C) 2010-12 Cesar Mauri Loba - CREA Software Systems
+* 
+*  This program is free software: you can redistribute it and/or modify
+*  it under the terms of the GNU General Public License as published by
+*  the Free Software Foundation, either version 3 of the License, or
+*  (at your option) any later version.
+*
+*  This program is distributed in the hope that it will be useful,
+*  but WITHOUT ANY WARRANTY; without even the implied warranty of
+*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+*  GNU General Public License for more details.
+*
+*  You should have received a copy of the GNU General Public License
+*  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+#ifndef SPCORE_PIN_H
+#define SPCORE_PIN_H
+
+#include "spcore/baseobj.h"
+#include <assert.h>
+
+namespace spcore {
+
+class CTypeAny;
+
+/**
+	@brief Interface for input pins
+
+	This interface declares operations that should be available to work 
+	with pins but not to implement it. Use CInputPin to create your 
+	specific (i.e. typed) pin implementation.
+*/
+class IInputPin : public IBaseObject {
+protected:
+	virtual ~IInputPin() {}
+
+public:
+	/**
+		@return the internal type ID for the type name of this pin, 
+		(which is execution) dependent or TYPE_ANY.
+	*/
+    virtual int GetTypeID() const = 0;
+
+    /**
+		@return the name of the pin.
+	*/
+    virtual const char* GetName() const = 0;
+
+    enum EIPinProperties {
+      ALLOW_WRITE = 1,
+      ALLOW_READ = 2
+
+    };
+
+    /**
+		@brief Get the properties of the pin.
+		@return Combination of flags.
+		@return ALLOW_WRITE: calls to Send method allowed.
+		@return ALLOW_READ: calls to Read method allowed.
+    */
+    virtual unsigned int GetProperties() const = 0;
+
+    /**
+		@brief Send a message to the pin. 			
+		@return  0 -> message successfully sent.
+		@return -1 -> type mismatch.
+
+		Intended only for calls outside the graph.
+    */
+    virtual int Send(SmartPtr<const CTypeAny> message) = 0;
+
+	/**
+		@brief Read the content of the pin.
+		
+		@return Copy of the content of a NULL pointer.
+	*/
+    virtual SmartPtr<const CTypeAny> Read() const = 0;
+
+	/**
+		@brief Rename the pin.
+		@param name New name of the pin.
+	*/
+	virtual void Rename (const char * name) = 0;
+
+	/**
+		@brief Allow to change the type of the pin. 
+		
+		The only change allowed	is to turn an any pin into a typed one. 
+		The change	might fail if the pin is already connected.
+
+		@param type_name Name of the new type.
+		@return  0 -> type changed correctly
+		@return	-1 -> type cannot be changed
+		@return	-2 -> type name does not exists
+	*/
+	virtual int ChangeType (const char * type_name) = 0;
+};
+
+/**
+	@brief Interface for output pins.
+
+	This interface declares operations that should be available to work 
+	with pins but not to implement it. Use COutputPin to create your 
+	specific (i.e. typed pin implementation)
+*/
+class IOutputPin : public IBaseObject {
+protected:
+	virtual ~IOutputPin() {}
+
+public:
+	/**
+		@return the internal type ID for the type name of this pin, which 
+		is execution dependent, or  TYPE_ANY if the type name doesn't exists.
+	*/
+    virtual int GetTypeID() const = 0;
+
+	/**
+		@brief Name of the pin.
+		@return Pointer to a internal char array which might not be freed.
+	*/
+    virtual const char* GetName() const = 0;
+
+    /**
+		@brief Connect this with a consumer input pin.
+		@param consumer Input pin to connect to.
+		@return 0 if all correct 
+		@return <0 when error
+    */
+    virtual int Connect(IInputPin & consumer) = 0;
+
+    /**
+		@brief Disconnects. 
+		@param consumer Input pin at the other end.
+		
+		If the two pins where not connected does nothing.
+    */
+    virtual void Disconnect(const IInputPin & consumer) = 0;
+
+    /**
+		@brief Checks whether two pins can be connected.
+		taking into account the type of each one.
+		@param consumer Input pin at the other end.
+		@return true or false
+	*/
+    virtual bool CanConnect(const IInputPin & consumer) const = 0;
+
+    /**
+		@brief Send a message to the connected pins. 
+		@return 0 if correct or <0 when error.
+
+		To be used by the component implementation.
+    */
+    virtual int Send(SmartPtr<const CTypeAny> message) = 0;
+
+	/**
+		@brief Return the number of consumers currently connected
+		@return number of consumers 
+	*/
+	virtual unsigned int GetNumComsumers() const = 0;
+
+	/**
+		@brief Rename the pin.
+		@param name New name for the pin.
+	*/
+	virtual void Rename (const char * name) = 0;
+
+	/**
+		Allow to change the type of the pin. The only change allowed
+		is to turn an any pin into a typed one. The change
+		might fail if the pin is already connected.
+
+		@param type_name Name of the new type.
+		@return  0 -> type changed correctly
+		@return	-1 -> type cannot be changed
+		@return	-2 -> type name does not exists
+	*/
+	virtual int ChangeType (const char * type_name) = 0;
+
+};
+
+} // namespace spcore
+#endif
diff --git a/include/spcore/pinimpl.h b/include/spcore/pinimpl.h
new file mode 100644
index 0000000..752f839
--- /dev/null
+++ b/include/spcore/pinimpl.h
@@ -0,0 +1,386 @@
+/**
+* @file		pinimpl.h
+* @brief	Helper classes to implement pins
+* @author	Cesar Mauri Loba (cesar at crea-si dot com)
+*
+* -------------------------------------------------------------------------
+*
+* Copyright:   (C) 2010 Cesar Mauri Loba - CREA Software Systems
+* 
+*  This program is free software: you can redistribute it and/or modify
+*  it under the terms of the GNU General Public License as published by
+*  the Free Software Foundation, either version 3 of the License, or
+*  (at your option) any later version.
+*
+*  This program is distributed in the hope that it will be useful,
+*  but WITHOUT ANY WARRANTY; without even the implied warranty of
+*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+*  GNU General Public License for more details.
+*
+*  You should have received a copy of the GNU General Public License
+*  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+#ifndef SPCORE_PINIMPL_H
+#define SPCORE_PINIMPL_H
+
+#include "spcore/basetype.h"
+#include "spcore/pin.h"
+#include "spcore/coreruntime.h"
+
+#include <string>
+#include <vector>
+#include <algorithm>
+#include <boost/thread/shared_mutex.hpp>
+#include <boost/thread/locks.hpp>
+
+namespace spcore {
+
+
+// Forward declaration for COutputPin
+template<class> class SimpleType;
+
+/**
+	@brief Adapter class to help to implement input pin classes.
+*/
+class CInputPinAdapter : public IInputPin {
+protected:
+	/**
+		@brief Constructor
+		@param name Name the input pin will be given.
+		@param type Type name of the input pin.
+
+		If the type does not exists throws an exception.
+	*/
+	CInputPinAdapter(const char * name, const char * type) {
+		m_name= name;
+		m_typeID= getSpCoreRuntime()->ResolveTypeID(type);
+		assert (m_typeID!= TYPE_INVALID);
+		if (m_typeID== TYPE_INVALID)
+			throw std::runtime_error("type not found while constructing input pin");
+	}
+
+	virtual ~CInputPinAdapter() {}
+
+public:
+	virtual int GetTypeID() const { return m_typeID; }
+
+	virtual const char* GetName() const { return m_name.c_str(); }
+
+	virtual int Send(SmartPtr<const CTypeAny> message) { return -1; }
+
+	virtual SmartPtr<const CTypeAny> Read() const { return SmartPtr<const CTypeAny>(); }
+
+	virtual void Rename (const char * name) { m_name= name;	}
+
+	virtual int ChangeType (const char * type_name) {
+		int typeId= getSpCoreRuntime()->ResolveTypeID(type_name);
+		if (typeId== TYPE_INVALID) return -2;
+		if (m_typeID!= TYPE_ANY && typeId!= m_typeID) return -1;	
+		m_typeID= typeId;
+		return 0;
+	}
+
+private:
+	int m_typeID;
+	std::string m_name;
+};
+
+
+/**
+	@brief General implementation for output pins.
+*/
+class COutputPin : public IOutputPin {
+	template <class, class> friend class SimpleTypeBasicOperations;
+	friend class CCoreRuntime;
+
+protected:
+	/**
+		@brief Constructor
+		@param name Name the output pin will be given.
+		@param type Type name of the output pin.
+
+		If the type does not exists throws an exception.
+	*/
+	COutputPin(const char * name, const char * type) {
+		m_name= name;
+		m_typeID= getSpCoreRuntime()->ResolveTypeID(type);
+		assert (m_typeID!= TYPE_INVALID);
+		if (m_typeID== TYPE_INVALID)
+			throw std::runtime_error("type not found while constructing output pin");
+	}
+	
+	virtual ~COutputPin() {}
+
+public:
+   
+	virtual int GetTypeID() const { return m_typeID; }
+    
+	virtual const char* GetName() const { return m_name.c_str(); }
+    
+    virtual int Connect(IInputPin & consumer) {
+		if (!CanConnect(consumer)) return -1;	
+		if (std::find<std::vector<IInputPin *>::iterator, IInputPin*> 
+			(m_consumers.begin(), m_consumers.end(), &consumer)== m_consumers.end())
+			m_consumers.push_back (&consumer);  
+
+		// If pins already connected ignore request
+		return 0;
+	}
+
+    virtual void Disconnect(const IInputPin & consumer) {
+		std::vector<IInputPin*>::iterator it= find (m_consumers.begin(), m_consumers.end(), &consumer);
+		if (it!= m_consumers.end()) m_consumers.erase(it);
+		// If not connected do nothing
+	}
+
+	virtual bool CanConnect(const IInputPin & dst) const {
+		// Check that iterator matches with destination pin type		
+		if (GetTypeID()== dst.GetTypeID()) return true;
+		if (dst.GetTypeID()== TYPE_ANY) return true;
+		if (GetTypeID()== TYPE_ANY) return true;
+		return false;
+	}
+
+	virtual int Send(SmartPtr<const CTypeAny> message) {
+		/** @todo check if is really necessary the checks (receiver
+			pin will also revise message) */
+  		int myType= this->GetTypeID();
+		if (myType!= TYPE_ANY && myType!= message->GetTypeID()) return -1;
+  		size_t size= m_consumers.size();  	
+		IInputPin* dst;
+  		for (size_t i= 0; i< size; ++i)	{
+  			dst= m_consumers[i];
+  			// Pass message when
+  			//	- Reveiver pin typeId coincides with message type
+  			//	- Receiver pin typeId is ANY
+	  
+  			int consumer_type= dst->GetTypeID();
+  			if (consumer_type== TYPE_ANY || consumer_type== message->GetTypeID())
+  				dst->Send(message);
+  			// In other cases consumer does not get called
+  		}
+		return 0;
+	}
+
+	virtual unsigned int GetNumComsumers() const { return m_consumers.size(); }
+
+	virtual void Rename (const char * name) { m_name= name; }
+
+	virtual int ChangeType (const char * type_name) {
+		int typeId= getSpCoreRuntime()->ResolveTypeID(type_name);
+		if (typeId== TYPE_INVALID) return -2;
+
+		if (m_typeID!= TYPE_ANY && typeId!= m_typeID) return -1;
+		
+		// Is connected to a pin of different type
+		std::vector<IInputPin *>::const_iterator it= m_consumers.begin();
+
+		for (; it!= m_consumers.end(); ++it) {
+			int consumerType= (*it)->GetTypeID();
+			if (consumerType!= TYPE_ANY && typeId!= consumerType) return -1;
+		}
+
+		m_typeID= typeId;
+
+		return 0;
+	}
+
+protected:
+	std::vector<IInputPin *> const * GetConsumers() const { return &m_consumers; }
+
+private:
+	int m_typeID;
+	std::vector<IInputPin *> m_consumers;
+	std::string m_name;	
+};
+
+/**
+	@brief Thread-safe output pin implementation.
+*/
+class COutputPinLock : public COutputPin {
+	template <class, class> friend class SimpleTypeBasicOperations;
+	friend class CCoreRuntime;
+
+protected:
+	/**
+		@brief Constructor
+		@param name Name the output pin will be given.
+		@param type Type name of the output pin.
+
+		If the type does not exists throws an exception.
+	*/
+	COutputPinLock (const char * name, const char * type) 
+	: COutputPin(name, type)
+	{}
+	virtual ~COutputPinLock() { }
+
+	virtual int Connect(IInputPin & consumer) {
+		boost::unique_lock< boost::shared_mutex > lock(m_sharedMutex);
+		return COutputPin::Connect(consumer);
+	}
+   
+	virtual void Disconnect(const IInputPin & consumer) {
+		boost::unique_lock< boost::shared_mutex > lock(m_sharedMutex);
+		COutputPin::Disconnect (consumer);
+	}
+
+	virtual int Send(SmartPtr<const CTypeAny> message) {
+		boost::shared_lock< boost::shared_mutex > lock(m_sharedMutex);
+		return COutputPin::Send (message);
+	}
+private:
+	boost::shared_mutex m_sharedMutex;
+};
+
+/**
+	@brief Template class helper to implement pins that refer to some other
+	object (usually the IComponent that contains it).
+	@tparam TCOMPONENT Type which this class will hold a pointer to.
+*/
+template<class TCOMPONENT>
+class CInputPinComponentRef : public CInputPinAdapter {
+public:
+	/**
+		@brief Constructor
+		@param name Name the pin will be given.
+		@param type Type name of the output pin.
+		@param component Component to point to.
+
+		If the type does not exists throws an exception.
+	*/
+	CInputPinComponentRef(const char * name, const char * type, TCOMPONENT & component)
+	: CInputPinAdapter(name, type)
+	, m_component(&component)
+	{}	
+
+protected:
+	TCOMPONENT* m_component;
+};
+
+/**
+	@brief Template class helper to implement a read-only input pins.
+	@tparam TDATA Compile time type class of the pin.
+	@tparam TCOMPONENT Type which this class will hold a pointer to.
+*/
+template<class TDATA, class TCOMPONENT>
+class CInputPinReadOnly : public CInputPinComponentRef<TCOMPONENT> {
+public:
+	/**
+		@brief Constructor
+		@param name Name the pin will be given.
+		@param component Component to point to.
+
+		Note that the type of the pin is provided as a template argument.
+	*/
+	CInputPinReadOnly(const char * name, TCOMPONENT & component) 
+	: CInputPinComponentRef<TCOMPONENT> (name, TDATA::getTypeName(), component) 
+	{}
+
+	virtual unsigned int GetProperties() const {
+		return (unsigned int) IInputPin::ALLOW_READ;
+	}
+
+	virtual SmartPtr<const CTypeAny> Read() const {
+		return this->DoRead();
+	}
+
+protected:
+	/**
+		@brief Method the derived class should provide to do the actual read.
+		@return Smart pointer to a type instance.
+	*/
+	virtual SmartPtr<TDATA> DoRead() const = 0;
+};
+
+/**
+	@brief Template class helper to implement a write-only input pins.
+	@tparam TDATA Compile time type class of the pin.
+	@tparam TCOMPONENT Type which this class will hold a pointer to.
+*/
+template<class TDATA, class TCOMPONENT>
+class CInputPinWriteOnly : public CInputPinComponentRef<TCOMPONENT> {
+public:
+	/**
+		@brief Constructor
+		@param name Name the pin will be given.
+		@param component Component to point to.
+
+		Note that the type of the pin is provided as a template argument.
+	*/
+	CInputPinWriteOnly(const char * name, TCOMPONENT & component) 
+	: CInputPinComponentRef<TCOMPONENT> (name, TDATA::getTypeName(), component) 
+	{}
+
+	virtual unsigned int GetProperties() const {
+		return (unsigned int) IInputPin::ALLOW_WRITE;
+	}
+
+	virtual int Send(SmartPtr<const CTypeAny> message) {
+		// Check message type
+		int myType= this->GetTypeID();
+		if (myType!= TYPE_ANY && myType!= message->GetTypeID()) return -1;
+	  
+  		return this->DoSend(*static_cast<const TDATA *>(message.get()));
+	}
+
+protected:
+	/**
+		@brief Method the derived class should provide to do the actual send.
+		@param message
+		@return 0 -> message successfully sent, -1 -> type mismatch
+	*/
+	virtual int DoSend(const TDATA & message) = 0;
+};
+
+/**
+	@brief Template class helper to implement a read-write input pins.
+	@tparam TDATA Compile time type class of the pin.
+	@tparam TCOMPONENT Type which this class will hold a pointer to.
+*/
+template<class TDATA, class TCOMPONENT>
+class CInputPinReadWrite : public CInputPinComponentRef<TCOMPONENT> {
+public:
+	/**
+		@brief Constructor
+		@param name Name the pin will be given.
+		@param component Component to point to.
+
+		Note that the type of the pin is provided as a template argument.
+	*/
+	CInputPinReadWrite(const char * name, TCOMPONENT & component)
+	: CInputPinComponentRef<TCOMPONENT> (name, TDATA::getTypeName(), component) 
+	{}
+
+	virtual unsigned int GetProperties() const {
+		return (unsigned int) (IInputPin::ALLOW_READ | IInputPin::ALLOW_WRITE);
+	}
+
+	virtual SmartPtr<const CTypeAny> Read() const {
+		return this->DoRead();
+	}
+
+	virtual int Send(SmartPtr<const CTypeAny> message){
+		// Check message type
+		int myType= this->GetTypeID();
+		if (myType!= TYPE_ANY && myType!= message->GetTypeID()) return -1;
+	  
+  		return this->DoSend(*static_cast<const TDATA *>(message.get()));
+	}
+
+protected:
+	/**
+		@brief Method the derived class should provide to do the actual read.
+		@return Smart pointer to a type instance.
+	*/
+	virtual SmartPtr<TDATA> DoRead() const = 0;
+
+	/**
+		@brief Method the derived class should provide to do the actual send.
+		@param message
+		@return 0 -> message successfully sent, -1 -> type mismatch
+	*/
+	virtual int DoSend(const TDATA & message) = 0;
+};
+
+} // namespace spcore
+#endif
diff --git a/include/sphost/componenthelper.h b/include/sphost/componenthelper.h
new file mode 100644
index 0000000..a10b487
--- /dev/null
+++ b/include/sphost/componenthelper.h
@@ -0,0 +1,141 @@
+/**
+* @file		componenthelper.h
+* @brief	sp script parser.
+* @author	Cesar Mauri Loba (cesar at crea-si dot com)
+* 
+* -------------------------------------------------------------------------
+*
+* Copyright:   (C) 2011 Cesar Mauri Loba - CREA Software Systems
+*
+*  This program is free software: you can redistribute it and/or modify
+*  it under the terms of the GNU General Public License as published by
+*  the Free Software Foundation, either version 3 of the License, or
+*  (at your option) any later version.
+*
+*  This program is distributed in the hope that it will be useful,
+*  but WITHOUT ANY WARRANTY; without even the implied warranty of
+*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+*  GNU General Public License for more details.
+*
+*  You should have received a copy of the GNU General Public License
+*  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+#ifndef COMPONENTHELPER_H
+#define COMPONENTHELPER_H
+
+#include "spcore/component.h"
+#include "sphost/libimpexp_sphost.h"
+
+#include <exception>
+#include <stdexcept>
+#include <istream>
+
+#ifdef _MSC_VER
+#pragma warning(push)
+// non dll-interface class 'A' used as base for dll-interface class 'B'
+#pragma warning(disable: 4275)
+#endif // _MSC_VER
+
+namespace sphost {
+
+//
+// Classes to signal errors during script parsing
+//
+
+// Full parser error
+class SPIMPEXP_CLASS_HOST parser_error : public std::runtime_error 
+{
+public:
+	parser_error (const std::string& what_arg) : std::runtime_error (what_arg) {}
+};
+
+// Partial error. Used when not enough information is known to fully complete the error message
+class SPIMPEXP_CLASS_HOST parser_partial_error : public std::runtime_error 
+{
+public:
+	parser_partial_error (const std::string& what_arg) : std::runtime_error (what_arg) {}
+};
+
+/**
+	This class is intended only to ease the task of working with components and so
+	it is only intended to be used by the host application not the modules. Therefore,
+	we export directly in the dynamic library.
+*/
+class SPIMPEXP_CLASS_HOST ComponentHelper {
+public:
+	/**
+		Flags to control parsing behaviour
+	*/
+	enum { 
+		IGNORE_CONNECT_SAME_COMPONENT= 1
+	};
+
+	/**
+		@brief Parse an instantiate a .sp script from a stream
+	
+		@param is input stream to parse
+		@param file actual file path (for error messages and import directive)
+		@param dataDir value for SP_DATA_DIR 
+		@param flags currently either 0 or ComponentHelper::IGNORE_CONNECT_SAME_COMPONENT
+			(0 default)
+		@param argc numbers of elements in array argv
+		@param argv argument values passed to the script
+
+		@return the created component
+
+		If any error is found throws an parser_error exception
+
+		See README.txt file on scripts directory for syntax details.
+	**/
+	static 
+	SmartPtr<spcore::IComponent> SimpleParser (
+		std::istream& is, 
+		const std::string& file, 
+		const char* dataDir, 
+		int flags= 0,
+		int argc= 0,
+		const char *argv[]= NULL);
+
+	/**
+		@brief Parse an instantiate a .sp script from a file
+	
+		@param file path to the file 
+		@param dataDir value for SP_DATA_DIR 
+		@param flags currently either 0 or ComponentHelper::IGNORE_CONNECT_SAME_COMPONENT
+			(0 default)
+		@param argc numbers of elements in array argv
+		@param argv argument values passed to the script
+
+		@return the created component
+
+		If any error is found throws an parser_error exception
+
+		See README.txt file on scripts directory for syntax details.
+	**/
+	static 
+	SmartPtr<spcore::IComponent> SimpleParserFile (
+		const char* file, 
+		const char* dataDir, 
+		int flags= 0,
+		int argc= 0,
+		const char *argv[]= NULL);
+	
+	/**
+		@brief Recursively find a component by name. 
+		
+		@param component: parent component where to search
+		@param name: parent component where to search
+		@param levels: maximum nesting deep. 0 means unlimited.
+		@return pointer to the component or NULL if not found
+	*/
+	static
+	spcore::IComponent* FindComponentByName (spcore::IComponent& component, const char* name, int deep);
+};
+
+} // namespace spcore
+
+#ifdef _MSC_VER
+#pragma warning(pop)
+#endif
+
+#endif
diff --git a/include/sphost/configutils.h b/include/sphost/configutils.h
new file mode 100755
index 0000000..fba0c46
--- /dev/null
+++ b/include/sphost/configutils.h
@@ -0,0 +1,53 @@
+/**
+* @file		configutils.h
+* @brief	Configuration utility functions.
+* @author	Cesar Mauri Loba
+*
+* -------------------------------------------------------------------------
+*
+* Copyright:   (C) 2011 Cesar Mauri Loba - CREA Software Systems
+* 
+*  This program is free software: you can redistribute it and/or modify
+*  it under the terms of the GNU General Public License as published by
+*  the Free Software Foundation, either version 3 of the License, or
+*  (at your option) any later version.
+*
+*  This program is distributed in the hope that it will be useful,
+*  but WITHOUT ANY WARRANTY; without even the implied warranty of
+*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+*  GNU General Public License for more details.
+*
+*  You should have received a copy of the GNU General Public License
+*  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+#ifndef SPHOST_CONFIGUTILS_H
+#define SPHOST_CONFIGUTILS_H
+
+#include "spcore/configuration.h"
+#include "sphost/libimpexp_sphost.h"
+
+namespace sphost {
+
+/**
+	@brief Try to load a configuration set
+	@param fname File name to load. If the path
+	is relative the user data directory is appended.
+	@return A smart pointer to the configuration which can be NULL if 
+	the configuration file does not exist or an error ocurred.
+*/
+SPIMPEXP_CLASS_HOST
+SmartPtr<spcore::IConfiguration> LoadConfiguration(const char* fname);
+
+/**
+	@brief Try to save a configuration set.
+	@param cfg Reference to the configuration set.
+	@param fname File name to load. If the path	is relative the user data 
+	directory is appended. Missing directories are created as needed.
+	@return true on success, false when an error ocurred.
+*/
+SPIMPEXP_CLASS_HOST
+bool SaveConfiguration(const spcore::IConfiguration& cfg, const char* fname);
+
+};
+
+#endif
diff --git a/include/sphost/langutils.h b/include/sphost/langutils.h
new file mode 100755
index 0000000..cc19c55
--- /dev/null
+++ b/include/sphost/langutils.h
@@ -0,0 +1,78 @@
+/**
+* @file		langutils.h
+* @brief	i18n utility functions.
+* @author	Cesar Mauri Loba
+*
+* -------------------------------------------------------------------------
+*
+* Copyright:   (C) 2011 Cesar Mauri Loba - CREA Software Systems
+* 
+*  This program is free software: you can redistribute it and/or modify
+*  it under the terms of the GNU General Public License as published by
+*  the Free Software Foundation, either version 3 of the License, or
+*  (at your option) any later version.
+*
+*  This program is distributed in the hope that it will be useful,
+*  but WITHOUT ANY WARRANTY; without even the implied warranty of
+*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+*  GNU General Public License for more details.
+*
+*  You should have received a copy of the GNU General Public License
+*  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+#ifndef SPHOST_LANGUTILS_H
+#define SPHOST_LANGUTILS_H
+
+#include "config.h"
+
+#ifdef ENABLE_NLS
+
+#include <string>
+
+#include "sphost/libimpexp_sphost.h"
+
+namespace sphost {
+
+/**
+	@brief Adds a language to the list of supported languages for this application
+	@param lang Language identifier
+	@return false if an error ocurred (invalid language id), true otherwise.
+*/
+SPIMPEXP_CLASS_HOST
+bool AddAvailableLanguage(int lang);
+
+/**
+	@brief Open a language selection dialog.
+	@param previous Language identifier to be selected in the dialog or -1 if none.
+	@return the selected language id or -1 if user cancelled.
+	@remarks wx must has been previously initialized.
+*/
+SPIMPEXP_CLASS_HOST
+int LanguageSelectionDialog(int previuos);
+
+/**
+	@brief Try to load the stored language setting if possible.
+	@param fname Language configuration path
+	@return the laguage id or
+		-1 error reading language from config file (not found).
+		-2 invalid language code.
+*/
+SPIMPEXP_CLASS_HOST
+int LoadLanguageFromConfiguration(const char* fname);
+
+/*!
+	@brief Save the language setting
+	@param lang Language identifier
+	@param fname Language configuration path
+	@return 0 if OK
+		-1 error writting language to config file.
+		-2 invalid language id
+*/
+SPIMPEXP_CLASS_HOST
+int SaveLanguageToConfiguration(int lang, const char* fname);
+
+};
+
+#endif	// ENABLE_NLS
+
+#endif	// SPHOST_LANGUTILS_H
\ No newline at end of file
diff --git a/include/sphost/libimpexp_sphost.h b/include/sphost/libimpexp_sphost.h
new file mode 100755
index 0000000..014977a
--- /dev/null
+++ b/include/sphost/libimpexp_sphost.h
@@ -0,0 +1,36 @@
+/**
+* @file		libimpexp_sphost.h
+* @brief	Preprocessor macros when bulding dynamic library.
+* @author	Cesar Mauri Loba (cesar at crea-si dot com)
+*
+* -------------------------------------------------------------------------
+*
+* Copyright:   (C) 2011 Cesar Mauri Loba - CREA Software Systems
+*
+*  This program is free software: you can redistribute it and/or modify
+*  it under the terms of the GNU General Public License as published by
+*  the Free Software Foundation, either version 3 of the License, or
+*  (at your option) any later version.
+*
+*  This program is distributed in the hope that it will be useful,
+*  but WITHOUT ANY WARRANTY; without even the implied warranty of
+*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+*  GNU General Public License for more details.
+*
+*  You should have received a copy of the GNU General Public License
+*  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+#pragma once
+
+#include "spcore/libimpexp.h"
+
+#ifdef SPMAKING_DLL_SPHOST
+	#define SPIMPEXP_CLASS_HOST SPEXPORT_CLASS
+	#define SPIMPEXT_FUNCTION_HOST SPEXPORT_FUNCTION
+#elif defined (SPUSING_DLL)
+	#define SPIMPEXP_CLASS_HOST SPIMPORT_CLASS
+	#define SPIMPEXT_FUNCTION_HOST SPIMPORT_FUNCTION
+#else
+	#define SPIMPEXP_CLASS_HOST
+	#define SPIMPEXT_FUNCTION_HOST
+#endif	// SPMAKING_DLL_SPHOST
diff --git a/include/sphost/paths.h b/include/sphost/paths.h
new file mode 100644
index 0000000..cee5cfe
--- /dev/null
+++ b/include/sphost/paths.h
@@ -0,0 +1,83 @@
+/**
+* @file		paths.h
+* @brief	Common path utilities.
+* @author	Cesar Mauri Loba (cesar at crea-si dot com)
+*
+* -------------------------------------------------------------------------
+*
+* Copyright:   (C) 2010-12 Cesar Mauri Loba - CREA Software Systems
+*
+*  This program is free software: you can redistribute it and/or modify
+*  it under the terms of the GNU General Public License as published by
+*  the Free Software Foundation, either version 3 of the License, or
+*  (at your option) any later version.
+*
+*  This program is distributed in the hope that it will be useful,
+*  but WITHOUT ANY WARRANTY; without even the implied warranty of
+*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+*  GNU General Public License for more details.
+*
+*  You should have received a copy of the GNU General Public License
+*  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+#ifndef SPHOST_PATHS_H
+#define SPHOST_PATHS_H
+#include "sphost/libimpexp_sphost.h"
+
+// REMOVE 
+#include <string>
+// REMOVE 
+
+
+namespace sphost {
+
+/**
+	@brief Class for path reporting 
+*/
+class SPIMPEXP_CLASS_HOST Paths {
+public:
+	/**
+		@brief Return full path of the command of the calling process
+	*/
+	static const std::string GetExecPath();
+
+	/**
+		@brief Given the full path of the command of the calling process
+		tries to guess the base path (installation path)
+		@param[in]  exePath full path of the command of the calling process
+		@param[out] development environment? (i.e. Debug or Release found on the path)
+
+		@remarks Examples:
+		c:\program files\appname\bin\exec.exe -> c:\program files\appname
+		c:\program files\appname\bin\Debug\exec.exe -> c:\program files\appname
+		c:\program files\appname\bin\Release\exec.exe -> c:\program files\appname
+		/usr/bin/appname -> /usr
+		/usr/local/bin/appname -> /usr/local
+		/home/user/devel/appname/bin/Debug/appname -> /home/user/devel/appname
+		/home/user/devel/appname/bin/Release/appname -> /home/user/devel/appname
+	*/
+	static const std::string GetBasePathFromExec(const std::string& fullPath, bool& devel);
+
+	/**
+		@brief Get the name of the directory for a full path
+	*/
+	static const std::string GetDirName(const std::string& fullPath);
+
+	/**
+		@brief Return the directory for the user-dependent application data 
+		and configuration files
+		The returned value is:
+		- Linux: the HOME directory
+		- Windows: the contents of the APPDATA usually something like
+			C:\Users\username\AppData\appname
+		  or like
+		    C:\Users\cesar\AppData\Roaming
+	*/
+	static const std::string GetUserDataDir();	
+
+private:
+	Paths() {}
+};
+
+} // namespace sphost
+#endif
diff --git a/include/sphost/testcommon.h b/include/sphost/testcommon.h
new file mode 100644
index 0000000..fdddaf7
--- /dev/null
+++ b/include/sphost/testcommon.h
@@ -0,0 +1,62 @@
+/////////////////////////////////////////////////////////////////////////////
+// File:        testcommon.h
+//	Common functions to perform testing
+// Author:      Cesar Mauri Loba (cesar at crea-si dot com)
+// Copyright:   (C) 2010 Cesar Mauri Loba - CREA Software Systems
+// 
+//  This program is free software: you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation, either version 3 of the License, or
+//  (at your option) any later version.
+//
+//  This program is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+/////////////////////////////////////////////////////////////////////////////
+#ifndef TESTCOMMON_H
+#define TESTCOMMON_H
+
+#ifdef WIN32
+#include <windows.h>
+#define SLEEP(x) Sleep((x)*1000)   /* Windows version */
+#ifdef ENABLE_WXWIDGETS
+#include <wx/msw/winundef.h>
+#endif
+#else
+#include <unistd.h>
+#define SLEEP(x) sleep((x))   /* Linux version */
+#endif 
+
+
+#include <assert.h>
+#include <iostream>
+#include <stdio.h>
+
+#include "spcore/component.h"
+#include "spcore/coreruntime.h"
+
+void DumpInputPin (spcore::IInputPin& ip);
+
+void DumpOutputPin (spcore::IOutputPin& op);
+
+void DumpComponent (spcore::IComponent &c);
+
+void DumpCoreRuntime(spcore::ICoreRuntime* core);
+
+void DumpTypeInstance (const spcore::CTypeAny& t, const char* indent= "");
+
+void ExitErr (const char* msg);
+
+int getch_no_block(void);
+
+unsigned long get_mili_count();
+
+void calls_per_second();
+
+void sleep_milliseconds(unsigned ms);
+
+#endif
diff --git a/include/widgets_base/containerbook.h b/include/widgets_base/containerbook.h
new file mode 100644
index 0000000..24356d5
--- /dev/null
+++ b/include/widgets_base/containerbook.h
@@ -0,0 +1,109 @@
+/////////////////////////////////////////////////////////////////////////////
+// Name:        containerbook.h
+// Purpose:     
+// Author:      C�sar Mauri Loba
+// Modified by: 
+// Created:     23/05/2011 20:24:54
+// Copyright:   (C) 2011 Cesar Mauri Loba - CREA Software Systems
+// 
+//  This program is free software: you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation, either version 3 of the License, or
+//  (at your option) any later version.
+//
+//  This program is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with this program.  If not, see <http://www.gnu.org/licenses/>.   
+/////////////////////////////////////////////////////////////////////////////
+
+#ifndef _CONTAINERBOOK_H_
+#define _CONTAINERBOOK_H_
+
+
+/*!
+ * Includes
+ */
+
+////@begin includes
+#include "wx/notebook.h"
+////@end includes
+#include "widgets_base/libimpexp_widgetsbase.h"
+
+/*!
+ * Forward declarations
+ */
+
+////@begin forward declarations
+////@end forward declarations
+
+/*!
+ * Control identifiers
+ */
+
+////@begin control identifiers
+#define ID_NOTEBOOK 10007
+#define SYMBOL_CONTAINERBOOK_STYLE wxNB_DEFAULT|wxNB_NOPAGETHEME
+#define SYMBOL_CONTAINERBOOK_IDNAME ID_NOTEBOOK
+#define SYMBOL_CONTAINERBOOK_SIZE wxDefaultSize
+#define SYMBOL_CONTAINERBOOK_POSITION wxDefaultPosition
+////@end control identifiers
+
+//namespace widgets_base {
+
+/*!
+ * ContainerBook class declaration
+ */
+
+class SPIMPEXP_CLASS_WIDGETSBASE ContainerBook: public wxNotebook
+{    
+    DECLARE_DYNAMIC_CLASS( ContainerBook )
+    DECLARE_EVENT_TABLE()
+
+public:
+    /// Constructors
+    ContainerBook();
+    ContainerBook(wxWindow* parent, wxWindowID id, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize, long style = wxBK_DEFAULT);
+
+    /// Creation
+    bool Create(wxWindow* parent, wxWindowID id, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize, long style = wxBK_DEFAULT);
+
+    /// Destructor
+    ~ContainerBook();
+
+    /// Initialises member variables
+    void Init();
+
+    /// Creates the controls and sizers
+    void CreateControls();
+
+////@begin ContainerBook event handler declarations
+
+    /// wxEVT_SIZE event handler for ID_NOTEBOOK
+    void OnSize( wxSizeEvent& event );
+
+////@end ContainerBook event handler declarations
+
+////@begin ContainerBook member function declarations
+
+    /// Retrieves bitmap resources
+    wxBitmap GetBitmapResource( const wxString& name );
+
+    /// Retrieves icon resources
+    wxIcon GetIconResource( const wxString& name );
+////@end ContainerBook member function declarations
+
+    /// Should we show tooltips?
+    static bool ShowToolTips();
+
+////@begin ContainerBook member variables
+////@end ContainerBook member variables
+};
+
+//};
+
+#endif
+    // _CONTAINERBOOK_H_
diff --git a/include/widgets_base/containercollapsible.h b/include/widgets_base/containercollapsible.h
new file mode 100644
index 0000000..1096c79
--- /dev/null
+++ b/include/widgets_base/containercollapsible.h
@@ -0,0 +1,109 @@
+/////////////////////////////////////////////////////////////////////////////
+// Name:        containercollapsible.h
+// Purpose:     
+// Author:      C�sar Mauri Loba
+// Modified by: 
+// Created:     01/06/2011 16:28:31
+// RCS-ID:      
+// Copyright:   (C) 2011 Cesar Mauri Loba - CREA Software Systems
+// 
+//  This program is free software: you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation, either version 3 of the License, or
+//  (at your option) any later version.
+//
+//  This program is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with this program.  If not, see <http://www.gnu.org/licenses/>.   
+/////////////////////////////////////////////////////////////////////////////
+
+#ifndef _CONTAINERCOLLAPSIBLE_H_
+#define _CONTAINERCOLLAPSIBLE_H_
+
+
+/*!
+ * Includes
+ */
+
+////@begin includes
+#include "wx/collpane.h"
+////@end includes
+#include "widgets_base/libimpexp_widgetsbase.h"
+
+/*!
+ * Forward declarations
+ */
+
+////@begin forward declarations
+////@end forward declarations
+
+/*!
+ * Control identifiers
+ */
+
+////@begin control identifiers
+#define ID_COLLAPSIBLEPANE -1
+#define SYMBOL_CONTAINERCOLLAPSIBLE_STYLE wxCP_DEFAULT_STYLE|wxCP_NO_TLW_RESIZE
+#define SYMBOL_CONTAINERCOLLAPSIBLE_IDNAME ID_COLLAPSIBLEPANE
+#define SYMBOL_CONTAINERCOLLAPSIBLE_SIZE wxDefaultSize
+#define SYMBOL_CONTAINERCOLLAPSIBLE_POSITION wxDefaultPosition
+////@end control identifiers
+
+namespace widgets_base {
+
+
+/*!
+ * ContainerCollapsible class declaration
+ */
+
+class SPIMPEXP_CLASS_WIDGETSBASE ContainerCollapsible: public wxGenericCollapsiblePane
+{    
+    DECLARE_DYNAMIC_CLASS( ContainerCollapsible )
+    DECLARE_EVENT_TABLE()
+
+public:
+    /// Constructors
+    ContainerCollapsible();
+    ContainerCollapsible(wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& label = wxEmptyString, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize, long style = wxCP_DEFAULT_STYLE, const wxValidator& validator = wxDefaultValidator);
+
+    /// Creation
+    bool Create(wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& label = wxEmptyString, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize, long style = wxCP_DEFAULT_STYLE, const wxValidator& validator = wxDefaultValidator);
+
+    /// Destructor
+    ~ContainerCollapsible();
+
+    /// Initialises member variables
+    void Init();
+
+    /// Creates the controls and sizers
+    void CreateControls();
+
+////@begin ContainerCollapsible event handler declarations
+    /// wxEVT_COMMAND_COLLPANE_CHANGED event handler for ID_COLLAPSIBLEPANE
+    void OnCollapsiblepanePaneChanged( wxCollapsiblePaneEvent& event );
+
+////@end ContainerCollapsible event handler declarations
+
+////@begin ContainerCollapsible member function declarations
+    /// Retrieves bitmap resources
+    wxBitmap GetBitmapResource( const wxString& name );
+
+    /// Retrieves icon resources
+    wxIcon GetIconResource( const wxString& name );
+////@end ContainerCollapsible member function declarations
+
+    /// Should we show tooltips?
+    static bool ShowToolTips();
+
+////@begin ContainerCollapsible member variables
+////@end ContainerCollapsible member variables
+};
+
+}; // namespace
+
+#endif
+    // _CONTAINERCOLLAPSIBLE_H_
diff --git a/include/widgets_base/containerpanel.h b/include/widgets_base/containerpanel.h
new file mode 100644
index 0000000..e7cbffa
--- /dev/null
+++ b/include/widgets_base/containerpanel.h
@@ -0,0 +1,111 @@
+/////////////////////////////////////////////////////////////////////////////
+// Name:        wxcontainerpanel.h
+// Purpose:     
+// Author:      C�sar Mauri Loba
+// Modified by: 
+// Created:     10/05/2011 21:00:30
+// RCS-ID:      
+// Copyright:   (C) 2011 Cesar Mauri Loba - CREA Software Systems
+// 
+//  This program is free software: you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation, either version 3 of the License, or
+//  (at your option) any later version.
+//
+//  This program is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with this program.  If not, see <http://www.gnu.org/licenses/>. 
+/////////////////////////////////////////////////////////////////////////////
+
+#ifndef _WXCONTAINERPANEL_H_
+#define _WXCONTAINERPANEL_H_
+
+
+/*!
+ * Includes
+ */
+
+////@begin includes
+////@end includes
+#include "widgets_base/libimpexp_widgetsbase.h"
+
+/*!
+ * Forward declarations
+ */
+
+////@begin forward declarations
+////@end forward declarations
+
+/*!
+ * Control identifiers
+ */
+
+////@begin control identifiers
+#define ID_CONTAINERPANEL 10004
+#define SYMBOL_CONTAINERPANEL_STYLE wxTAB_TRAVERSAL
+#define SYMBOL_CONTAINERPANEL_TITLE _("ContainerPanel")
+#define SYMBOL_CONTAINERPANEL_IDNAME ID_CONTAINERPANEL
+#define SYMBOL_CONTAINERPANEL_SIZE wxDefaultSize
+#define SYMBOL_CONTAINERPANEL_POSITION wxDefaultPosition
+////@end control identifiers
+
+
+namespace widgets_base {
+
+/*!
+ * ContainerPanel class declaration
+ */
+
+class SPIMPEXP_CLASS_WIDGETSBASE ContainerPanel: public wxPanel
+{    
+    DECLARE_DYNAMIC_CLASS( ContainerPanel )
+    DECLARE_EVENT_TABLE()
+
+public:
+    /// Constructors
+    ContainerPanel();
+    ContainerPanel( wxWindow* parent, wxWindowID id = SYMBOL_CONTAINERPANEL_IDNAME, const wxPoint& pos = SYMBOL_CONTAINERPANEL_POSITION, const wxSize& size = SYMBOL_CONTAINERPANEL_SIZE, long style = SYMBOL_CONTAINERPANEL_STYLE, const wxString& caption = SYMBOL_CONTAINERPANEL_TITLE );
+
+    /// Creation
+    bool Create( wxWindow* parent, wxWindowID id = SYMBOL_CONTAINERPANEL_IDNAME, const wxPoint& pos = SYMBOL_CONTAINERPANEL_POSITION, const wxSize& size = SYMBOL_CONTAINERPANEL_SIZE, long style = SYMBOL_CONTAINERPANEL_STYLE, const wxString& caption = SYMBOL_CONTAINERPANEL_TITLE );
+
+    /// Destructor
+    ~ContainerPanel();
+
+    /// Initialises member variables
+    void Init();
+
+    /// Creates the controls and sizers
+    void CreateControls();
+
+////@begin ContainerPanel event handler declarations
+
+    /// wxEVT_SIZE event handler for ID_CONTAINERPANEL
+    void OnSize( wxSizeEvent& event );
+
+////@end ContainerPanel event handler declarations
+
+////@begin ContainerPanel member function declarations
+
+    /// Retrieves bitmap resources
+    wxBitmap GetBitmapResource( const wxString& name );
+
+    /// Retrieves icon resources
+    wxIcon GetIconResource( const wxString& name );
+////@end ContainerPanel member function declarations
+
+    /// Should we show tooltips?
+    static bool ShowToolTips();
+
+////@begin ContainerPanel member variables
+////@end ContainerPanel member variables
+};
+
+};
+
+#endif
+    // _WXCONTAINERPANEL_H_
diff --git a/include/widgets_base/dialogcontainer.h b/include/widgets_base/dialogcontainer.h
new file mode 100644
index 0000000..a85cd82
--- /dev/null
+++ b/include/widgets_base/dialogcontainer.h
@@ -0,0 +1,114 @@
+/////////////////////////////////////////////////////////////////////////////
+// Name:        dialogcontainer.h
+// Purpose:     
+// Author:      C�sar Mauri Loba
+// Modified by: 
+// Created:     04/04/2011 18:59:05
+// RCS-ID:      
+// Copyright:   (C) 2011 Cesar Mauri Loba - CREA Software Systems
+// 
+//  This program is free software: you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation, either version 3 of the License, or
+//  (at your option) any later version.
+//
+//  This program is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with this program.  If not, see <http://www.gnu.org/licenses/>.   
+/////////////////////////////////////////////////////////////////////////////
+
+#ifndef _DIALOGCONTAINER_H_
+#define _DIALOGCONTAINER_H_
+
+
+/*!
+ * Includes
+ */
+
+////@begin includes
+////@end includes
+#include "widgets_base/libimpexp_widgetsbase.h"
+
+/*!
+ * Forward declarations
+ */
+
+////@begin forward declarations
+class wxBoxSizer;
+////@end forward declarations
+
+/*!
+ * Control identifiers
+ */
+
+////@begin control identifiers
+#define ID_DIALOGCONTAINER 10007
+#define SYMBOL_DIALOGCONTAINER_STYLE wxCAPTION|wxSYSTEM_MENU|wxCLOSE_BOX|wxTAB_TRAVERSAL
+#define SYMBOL_DIALOGCONTAINER_TITLE _("DialogContainer")
+#define SYMBOL_DIALOGCONTAINER_IDNAME ID_DIALOGCONTAINER
+#define SYMBOL_DIALOGCONTAINER_SIZE wxDefaultSize
+#define SYMBOL_DIALOGCONTAINER_POSITION wxDefaultPosition
+////@end control identifiers
+
+namespace widgets_base {
+/*!
+ * DialogContainer class declaration
+ */
+
+class SPIMPEXP_CLASS_WIDGETSBASE DialogContainer: public wxDialog
+{    
+    DECLARE_DYNAMIC_CLASS( DialogContainer )
+    DECLARE_EVENT_TABLE()
+
+public:
+    /// Constructors
+    DialogContainer();
+    DialogContainer( wxWindow* parent, wxWindowID id = SYMBOL_DIALOGCONTAINER_IDNAME, const wxString& caption = SYMBOL_DIALOGCONTAINER_TITLE, const wxPoint& pos = SYMBOL_DIALOGCONTAINER_POSITION, const wxSize& size = SYMBOL_DIALOGCONTAINER_SIZE, long style = SYMBOL_DIALOGCONTAINER_STYLE );
+
+    /// Creation
+    bool Create( wxWindow* parent, wxWindowID id = SYMBOL_DIALOGCONTAINER_IDNAME, const wxString& caption = SYMBOL_DIALOGCONTAINER_TITLE, const wxPoint& pos = SYMBOL_DIALOGCONTAINER_POSITION, const wxSize& size = SYMBOL_DIALOGCONTAINER_SIZE, long style = SYMBOL_DIALOGCONTAINER_STYLE );
+
+    /// Destructor
+    ~DialogContainer();
+
+	// Adds a panels from a component
+	void AddSitplusPanel (wxWindow* panel);
+private:
+    /// Initialises member variables
+    void Init();
+
+    /// Creates the controls and sizers
+    void CreateControls();
+
+////@begin DialogContainer event handler declarations
+
+    /// wxEVT_SIZE event handler for ID_DIALOGCONTAINER
+    void OnSize( wxSizeEvent& event );
+
+////@end DialogContainer event handler declarations
+
+////@begin DialogContainer member function declarations
+
+    /// Retrieves bitmap resources
+    wxBitmap GetBitmapResource( const wxString& name );
+
+    /// Retrieves icon resources
+    wxIcon GetIconResource( const wxString& name );
+////@end DialogContainer member function declarations
+
+    /// Should we show tooltips?
+    static bool ShowToolTips();
+
+////@begin DialogContainer member variables
+    wxBoxSizer* m_sizer;
+////@end DialogContainer member variables
+};
+
+};
+
+#endif
+    // _DIALOGCONTAINER_H_
diff --git a/include/widgets_base/libimpexp_widgetsbase.h b/include/widgets_base/libimpexp_widgetsbase.h
new file mode 100644
index 0000000..7bbd1b4
--- /dev/null
+++ b/include/widgets_base/libimpexp_widgetsbase.h
@@ -0,0 +1,33 @@
+/**
+* @file		libimpexp_widgetsbase.h
+* @brief	Preprocessor macros when bulding dynamic library.
+* @author	Cesar Mauri Loba (cesar at crea-si dot com)
+*
+* -------------------------------------------------------------------------
+*
+* Copyright:   (C) 2011 Cesar Mauri Loba - CREA Software Systems
+*
+*  This program is free software: you can redistribute it and/or modify
+*  it under the terms of the GNU General Public License as published by
+*  the Free Software Foundation, either version 3 of the License, or
+*  (at your option) any later version.
+*
+*  This program is distributed in the hope that it will be useful,
+*  but WITHOUT ANY WARRANTY; without even the implied warranty of
+*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+*  GNU General Public License for more details.
+*
+*  You should have received a copy of the GNU General Public License
+*  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+#pragma once
+
+#include "spcore/libimpexp.h"
+
+#ifdef SPMAKING_DLL_SPWIDGETSBASE
+	#define SPIMPEXP_CLASS_WIDGETSBASE SPEXPORT_CLASS
+	#define SPIMPEXT_FUNCTION_WIDGETSBASE SPEXPORT_FUNCTION
+#else
+	#define SPIMPEXP_CLASS_WIDGETSBASE
+	#define SPIMPEXT_FUNCTION_WIDGETSBASE
+#endif	// SPMAKING_DLL_SPWIDGETSBASE
diff --git a/include/widgets_base/mdichildcontainer.h b/include/widgets_base/mdichildcontainer.h
new file mode 100644
index 0000000..9163660
--- /dev/null
+++ b/include/widgets_base/mdichildcontainer.h
@@ -0,0 +1,116 @@
+/////////////////////////////////////////////////////////////////////////////
+// Name:        mdichildcontainer.h
+// Purpose:     
+// Author:      C�sar Mauri Loba
+// Modified by: 
+// Created:     04/04/2011 21:30:07
+// RCS-ID:      
+// Copyright:   (C) 2011 Cesar Mauri Loba - CREA Software Systems
+// 
+//  This program is free software: you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation, either version 3 of the License, or
+//  (at your option) any later version.
+//
+//  This program is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with this program.  If not, see <http://www.gnu.org/licenses/>.     
+/////////////////////////////////////////////////////////////////////////////
+
+#ifndef _MDICHILDCONTAINER_H_
+#define _MDICHILDCONTAINER_H_
+
+
+/*!
+ * Includes
+ */
+
+////@begin includes
+#include "wx/mdi.h"
+////@end includes
+#include "widgets_base/libimpexp_widgetsbase.h"
+
+/*!
+ * Forward declarations
+ */
+
+////@begin forward declarations
+class wxBoxSizer;
+////@end forward declarations
+
+/*!
+ * Control identifiers
+ */
+
+////@begin control identifiers
+#define ID_MDICHILDCONTAINER 10012
+#define SYMBOL_MDICHILDCONTAINER_STYLE wxCAPTION
+#define SYMBOL_MDICHILDCONTAINER_TITLE wxEmptyString
+#define SYMBOL_MDICHILDCONTAINER_IDNAME ID_MDICHILDCONTAINER
+#define SYMBOL_MDICHILDCONTAINER_SIZE wxDefaultSize
+#define SYMBOL_MDICHILDCONTAINER_POSITION wxDefaultPosition
+////@end control identifiers
+
+namespace widgets_base {
+
+/*!
+ * MDIChildContainer class declaration
+ */
+
+class SPIMPEXP_CLASS_WIDGETSBASE MDIChildContainer: public wxMDIChildFrame
+{    
+    DECLARE_CLASS( MDIChildContainer )
+    DECLARE_EVENT_TABLE()
+
+public:
+    /// Constructors
+    MDIChildContainer();
+    MDIChildContainer( wxMDIParentFrame* parent, wxWindowID id = SYMBOL_MDICHILDCONTAINER_IDNAME, const wxString& caption = SYMBOL_MDICHILDCONTAINER_TITLE, const wxPoint& pos = SYMBOL_MDICHILDCONTAINER_POSITION, const wxSize& size = SYMBOL_MDICHILDCONTAINER_SIZE, long style = SYMBOL_MDICHILDCONTAINER_STYLE );
+
+    bool Create( wxMDIParentFrame* parent, wxWindowID id = SYMBOL_MDICHILDCONTAINER_IDNAME, const wxString& caption = SYMBOL_MDICHILDCONTAINER_TITLE, const wxPoint& pos = SYMBOL_MDICHILDCONTAINER_POSITION, const wxSize& size = SYMBOL_MDICHILDCONTAINER_SIZE, long style = SYMBOL_MDICHILDCONTAINER_STYLE );
+
+    /// Destructor
+    ~MDIChildContainer();
+
+	// Adds a panels from a component
+	void AddSitplusPanel (wxWindow* panel);
+
+private:
+    /// Initialises member variables
+    void Init();
+
+    /// Creates the controls and sizers
+    void CreateControls();
+
+////@begin MDIChildContainer event handler declarations
+
+    /// wxEVT_SIZE event handler for ID_MDICHILDCONTAINER
+    void OnSize( wxSizeEvent& event );
+
+////@end MDIChildContainer event handler declarations
+
+////@begin MDIChildContainer member function declarations
+
+    /// Retrieves bitmap resources
+    wxBitmap GetBitmapResource( const wxString& name );
+
+    /// Retrieves icon resources
+    wxIcon GetIconResource( const wxString& name );
+////@end MDIChildContainer member function declarations
+
+    /// Should we show tooltips?
+    static bool ShowToolTips();
+
+////@begin MDIChildContainer member variables
+    wxBoxSizer* m_sizer;
+////@end MDIChildContainer member variables
+};
+
+};
+
+#endif
+    // _MDICHILDCONTAINER_H_
diff --git a/po/CMakeLists.txt b/po/CMakeLists.txt
new file mode 100644
index 0000000..4ca34e2
--- /dev/null
+++ b/po/CMakeLists.txt
@@ -0,0 +1,250 @@
+cmake_minimum_required(VERSION 2.6)
+set(NORMAL_DOMAINS
+	libsitplus
+)
+
+# All available domains.
+set(DOMAINS
+	${NORMAL_DOMAINS}
+	)
+
+############ pot update. ###########
+if(ENABLE_POT_UPDATE_TARGET)
+	foreach(DOMAIN ${NORMAL_DOMAINS})
+		# Update the source file dependencies.
+		include(update_pot_source_dependencies)
+
+		# Generate pot file for c++ data.
+		add_custom_command(
+			# misses bug address
+			OUTPUT ${PROJECT_BINARY_DIR}/po/${DOMAIN}.cpp.pot
+			# create the pot file make sure we always get output.
+			
+			COMMAND ${GETTEXT_XGETTEXT_EXECUTABLE} ${GETTEXT_XGETTEXT_OPTIONS}
+					--files-from=${PROJECT_SOURCE_DIR}/po/${DOMAIN}/POTFILES.in 
+					--output-dir=${PROJECT_BINARY_DIR}/po/
+					--output=${DOMAIN}.cpp.pot
+			# replace the chartype
+			COMMAND sed -i 
+				s/charset=CHARSET/charset=UTF-8/ 
+				${PROJECT_BINARY_DIR}/po/${DOMAIN}.cpp.pot
+			# Remove some header info - Need to test whether needed.
+			DEPENDS ${PROJECT_SOURCE_DIR}/po/${DOMAIN}/POTFILES.in			
+			WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
+			COMMENT "pot-update [${DOMAIN}]: Generated source pot file."
+		)
+
+		# Generate pot file for .sp scripts		
+		add_custom_command(
+			# misses bug address
+			OUTPUT ${PROJECT_BINARY_DIR}/po/${DOMAIN}.sp.pot
+			# create the pot file make sure we always get output.
+			
+			COMMAND ${GETTEXT_XGETTEXT_EXECUTABLE} ${GETTEXT_XGETTEXT_OPTIONS}
+					--files-from=${PROJECT_SOURCE_DIR}/po/${DOMAIN}/POTFILES.sp.in 
+					--output-dir=${PROJECT_BINARY_DIR}/po/
+					--language=awk
+					--output=${DOMAIN}.sp.pot
+			# replace the chartype
+			COMMAND sed -i 
+				s/charset=CHARSET/charset=UTF-8/ 
+				${PROJECT_BINARY_DIR}/po/${DOMAIN}.sp.pot
+			# Remove some header info - Need to test whether needed.
+			DEPENDS ${PROJECT_SOURCE_DIR}/po/${DOMAIN}/POTFILES.sp.in
+			WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
+			COMMENT "pot-update [${DOMAIN}]: Generated sp pot file."
+		)
+	
+		# Merge both pot files
+		add_custom_command(
+			# The old function checked for differences in the time in the header see
+			# what we need to do with it.
+			OUTPUT ${PROJECT_SOURCE_DIR}/po/${DOMAIN}/${DOMAIN}.pot
+
+			COMMAND ${GETTEXT_MSGCAT_EXECUTABLE} 
+				--sort-by-file 
+					 ${PROJECT_BINARY_DIR}/po/${DOMAIN}.cpp.pot
+					 ${PROJECT_BINARY_DIR}/po/${DOMAIN}.sp.pot
+				--output ${PROJECT_SOURCE_DIR}/po/${DOMAIN}/${DOMAIN}.pot
+
+			COMMAND ${CMAKE_COMMAND} -E remove 
+					 ${PROJECT_BINARY_DIR}/po/${DOMAIN}.cpp.pot
+					 ${PROJECT_BINARY_DIR}/po/${DOMAIN}.sp.pot
+
+			WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
+			DEPENDS 
+					${PROJECT_BINARY_DIR}/po/${DOMAIN}.cpp.pot
+					${PROJECT_BINARY_DIR}/po/${DOMAIN}.sp.pot
+			COMMENT "pot-update [${DOMAIN}]: Generated pot file."
+		)
+
+		# Update / generate the po files for all languages
+		foreach(LINGUA ${LINGUAS})
+
+			### Generate new po file.
+
+			# For some reason CMake is rather happy to delete the po file in
+			# some cases. To avoid that problem only generate the init rule
+			# if the po file doesn't exist. The case where a po file used to
+			# exist and no longer exists should never occur
+			if(NOT EXISTS ${PROJECT_SOURCE_DIR}/po/${DOMAIN}/${LINGUA}.po)			
+				add_custom_command(
+					OUTPUT ${PROJECT_SOURCE_DIR}/po/${DOMAIN}/${LINGUA}.po
+					COMMAND ${GETTEXT_MSGINIT_EXECUTABLE}
+							--no-translator 
+							--input=${PROJECT_SOURCE_DIR}/po/${DOMAIN}/${DOMAIN}.pot 
+							--output-file=${LINGUA}.po
+							--locale=${LINGUA}
+					WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}/po/${DOMAIN}
+					DEPENDS
+						${PROJECT_SOURCE_DIR}/po/${DOMAIN}/${DOMAIN}.pot
+					COMMENT 
+						"pot-update [${DOMAIN}-${LINGUA}]: Initialized po file."
+				)
+			endif(NOT EXISTS ${PROJECT_SOURCE_DIR}/po/${DOMAIN}/${LINGUA}.po)
+						
+			### Update existing po file.
+			add_custom_command(
+				# The pot-update depends on a dummy file which we promise to
+				# make. We don't make this dummy file but the pot-update
+				# still works.
+				OUTPUT ${PROJECT_SOURCE_DIR}/po/${DOMAIN}/${LINGUA}.po.dummy
+				COMMAND ${GETTEXT_MSGMERGE_EXECUTABLE} 
+						--backup=none
+						--previous
+						-U ${LINGUA}.po 
+						${PROJECT_SOURCE_DIR}/po/${DOMAIN}/${DOMAIN}.pot
+				DEPENDS
+					${PROJECT_SOURCE_DIR}/po/${DOMAIN}/${LINGUA}.po
+					${PROJECT_SOURCE_DIR}/po/${DOMAIN}/${DOMAIN}.pot					
+				WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}/po/${DOMAIN}
+				COMMENT "pot-update [${DOMAIN}-${LINGUA}]: Updated po file."
+			)
+
+			SET(pot-update-SRC ${pot-update-SRC} ${DOMAIN}/${LINGUA}.po.dummy)
+
+		endforeach(LINGUA ${LINGUAS})
+
+		# Add to target list
+		SET(pot-update-SRC 
+			${pot-update-SRC} 
+			${PROJECT_SOURCE_DIR}/po/${DOMAIN}/${DOMAIN}.pot # should depend on languages
+		)
+
+	endforeach(DOMAIN ${NORMAL_DOMAINS})
+
+	# The target to call
+	add_custom_target(pot-update
+		COMMENT "pot-update: Done."
+		DEPENDS ${pot-update-SRC}
+	)
+
+	##### po update per language #####
+	foreach(LINGUA ${LINGUAS})
+		foreach(DOMAIN ${DOMAINS})
+			add_custom_command(
+				# The pot-update depends on a dummy file which we promise to
+				# make. We don't make this dummy file but the pot-update
+				# still works.
+				OUTPUT ${PROJECT_SOURCE_DIR}/po/${DOMAIN}/${LINGUA}.po.lang.dummy
+				# After the po file is updated it might look not entirely as
+				# wanted, for example poedit reorders the file. Use msgattrib
+				# to reformat the file, use a helper file to do so.
+				COMMAND ${GETTEXT_MSGATTRIB_EXECUTABLE}
+						--output ${LINGUA}.po.tmp
+						${LINGUA}.po
+				COMMAND ${CMAKE_COMMAND} -E copy
+						${LINGUA}.po.tmp
+						${LINGUA}.po
+				COMMAND ${CMAKE_COMMAND} -E remove
+						${LINGUA}.po.tmp
+				# Now merge with the pot file.
+				COMMAND ${GETTEXT_MSGMERGE_EXECUTABLE}
+						--backup=none
+						--previous
+						-U ${LINGUA}.po
+						${PROJECT_SOURCE_DIR}/po/${DOMAIN}/${DOMAIN}.pot
+				WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}/po/${DOMAIN}
+				COMMENT "po-update [${DOMAIN}-${LINGUA}]: Updated po file."
+			)
+
+			set(po-update-LINGUA-SRC ${po-update-LINGUA-SRC} 
+				${PROJECT_SOURCE_DIR}/po/${DOMAIN}/${LINGUA}.po.lang.dummy
+			)
+
+		endforeach(DOMAIN ${DOMAINS})
+		add_custom_target(po-update-${LINGUA}
+			COMMENT "po-update ${LINGUA}: Done."
+			DEPENDS ${po-update-LINGUA-SRC}
+		)
+		set(po-update-LINGUA-SRC "")
+	endforeach(LINGUA ${LINGUAS})
+
+endif(ENABLE_POT_UPDATE_TARGET)
+
+if(ENABLE_NLS)
+
+	set(GETTEXT_MSGFMT_PARAMETER --check-format --check-domain )
+
+	if(ENABLE_POT_UPDATE_TARGET)
+		# Only set the verbose flag for maintainers.
+		set(GETTEXT_MSGFMT_PARAMETER -v ${GETTEXT_MSGFMT_PARAMETER} )
+	endif(ENABLE_POT_UPDATE_TARGET)
+
+	foreach(LINGUA ${LINGUAS})
+
+		foreach(DOMAIN ${DOMAINS})
+
+			add_custom_command(
+				OUTPUT ${PROJECT_BINARY_DIR}/${LOCALEDIR}/${LINGUA}/LC_MESSAGES
+				COMMAND ${CMAKE_COMMAND} -E make_directory 
+						${PROJECT_BINARY_DIR}/${LOCALEDIR}/${LINGUA}/LC_MESSAGES
+				COMMENT "mo-update [${LINGUA}]: Creating locale directory."
+			)
+
+			add_custom_command(
+				OUTPUT ${PROJECT_BINARY_DIR}/${LOCALEDIR}/${LINGUA}/LC_MESSAGES/${DOMAIN}.mo
+				COMMAND ${GETTEXT_MSGFMT_EXECUTABLE}
+						${GETTEXT_MSGFMT_PARAMETER}
+						-o ${PROJECT_BINARY_DIR}/${LOCALEDIR}/${LINGUA}/LC_MESSAGES/${DOMAIN}.mo ${LINGUA}.po
+				DEPENDS 
+					${PROJECT_BINARY_DIR}/${LOCALEDIR}/${LINGUA}/LC_MESSAGES
+					${PROJECT_SOURCE_DIR}/po/${DOMAIN}/${LINGUA}.po
+				WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}/po/${DOMAIN}
+				COMMENT "mo-update [${DOMAIN}-${LINGUA}]: Creating mo file."
+			)
+
+			install(FILES ${PROJECT_BINARY_DIR}/${LOCALEDIR}/${LINGUA}/LC_MESSAGES/${DOMAIN}.mo
+					DESTINATION ${LOCALEDIR}/${LINGUA}/LC_MESSAGES)
+
+			set(mo-update-SRC ${mo-update-SRC} 
+				${PROJECT_BINARY_DIR}/${LOCALEDIR}/${LINGUA}/LC_MESSAGES/${DOMAIN}.mo
+			)
+			set(mo-update-LINGUA-SRC ${mo-update-LINGUA-SRC} 
+				${PROJECT_BINARY_DIR}/${LOCALEDIR}/${LINGUA}/LC_MESSAGES/${DOMAIN}.mo
+			)
+
+		endforeach(DOMAIN ${DOMAINS})
+
+		if(ENABLE_POT_UPDATE_TARGET)
+			add_custom_target(mo-update-${LINGUA}
+				COMMENT "mo-update ${LINGUA}: Done."
+				DEPENDS ${mo-update-LINGUA-SRC}
+			)
+			set(mo-update-LINGUA-SRC "")
+		endif(ENABLE_POT_UPDATE_TARGET)
+
+	endforeach(LINGUA ${LINGUAS})
+
+	# The target to call
+	add_custom_target(mo-update ALL
+		COMMENT "mo-update: Done."
+		DEPENDS ${mo-update-SRC}
+	)
+
+	set_directory_properties(properties 
+		ADDITIONAL_MAKE_CLEAN_FILES ${PROJECT_BINARY_DIR}/${LOCALEDIR}
+	)
+
+endif(ENABLE_NLS)
+
diff --git a/po/LINGUAS b/po/LINGUAS
new file mode 100644
index 0000000..f7e12a8
--- /dev/null
+++ b/po/LINGUAS
@@ -0,0 +1 @@
+ca es gl
\ No newline at end of file
diff --git a/po/README.txt b/po/README.txt
new file mode 100644
index 0000000..4946852
--- /dev/null
+++ b/po/README.txt
@@ -0,0 +1 @@
+On Windows gettext is needed. NOTE: check that libintl.h does not define
new versions of printf functions family.


CMakeLists.txt inspired by http://svn.gna.org/viewcvs/wesnoth/trunk/cmake/


\ No newline at end of file
diff --git a/po/libsitplus/POTFILES.sp.in b/po/libsitplus/POTFILES.sp.in
new file mode 100644
index 0000000..e69de29
diff --git a/po/libsitplus/ca.po b/po/libsitplus/ca.po
new file mode 100644
index 0000000..e3df9a2
--- /dev/null
+++ b/po/libsitplus/ca.po
@@ -0,0 +1,720 @@
+# Catalan translations for libsitplus package.
+# Copyright (C) 2011-13 SITPLUS Project
+# This file is distributed under the same license as the libsitplus package.
+# Automatically generated, 2011.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: libsitplus 1.0\n"
+"Report-Msgid-Bugs-To: cesar at crea-si.com/\n"
+"POT-Creation-Date: 2013-04-11 16:05+0200\n"
+"PO-Revision-Date: 2013-04-11 18:36+0100\n"
+"Last-Translator: Cesar Mauri <cesar at crea-si.com>\n"
+"Language-Team: none\n"
+"Language: \n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"X-Poedit-Language: Catalan\n"
+
+#: include/widgets_base/containerpanel.h:50
+msgid "ContainerPanel"
+msgstr "PanellContenidor"
+
+#: include/widgets_base/dialogcontainer.h:51
+msgid "DialogContainer"
+msgstr "DiàlegContenidor"
+
+#: src/core/language.cpp:51
+msgid "System default"
+msgstr "Per defecte del sistema"
+
+#: src/host/componenthelper.cpp:619
+msgid "Advanced"
+msgstr "Avançat"
+
+#: src/host/langutils.cpp:59
+msgid "Language"
+msgstr "Idioma"
+
+#: src/mod_camera/wcameraconfiguration.cpp:156
+msgid "Camera properties"
+msgstr "Propietats de la càmera"
+
+#: src/mod_camera/wcameraconfiguration.cpp:165
+msgid "Selected camera:"
+msgstr "Càmera escollida:"
+
+#: src/mod_camera/wcameraconfiguration.cpp:174
+msgid "Format:"
+msgstr "Format:"
+
+#: src/mod_camera/wcameraconfiguration.cpp:183
+msgid "Capture speed:"
+msgstr "Velocitat captura:"
+
+#: src/mod_camera/wcameraconfiguration.cpp:192
+msgid "Driver settings:"
+msgstr "Ajustos controlador:"
+
+#: src/mod_camera/wcameraconfiguration.cpp:196
+msgid "Open driver settings"
+msgstr "Obrir ajustos del controlador"
+
+#: src/mod_camera/wcameraconfiguration.cpp:200
+msgid "Image mirror:"
+msgstr "Imatge mirall:"
+
+#: src/mod_camera/wcameraconfiguration.cpp:209
+msgid "Close"
+msgstr "Tancar"
+
+#: src/mod_camera/wcameraconfiguration.cpp:318
+msgid "Camera module"
+msgstr "Mòdul de la càmera"
+
+#: src/mod_camera/wcameraconfiguration.cpp:318
+msgid "Not detected any camera"
+msgstr "No s'ha detectat cap càmera"
+
+#: src/mod_camera/wcameraconfiguration.h:60
+msgid "Camera Configuration"
+msgstr "Configuració de la càmera"
+
+#: src/mod_camera/wcamerapanel.h:34
+msgid "Camera viewer"
+msgstr "Visor de càmera"
+
+#: src/mod_midi/midiconfiggui.cpp:176
+msgid "Select MIDI output device"
+msgstr "Escollir dispositiu sortida MIDI"
+
+#: src/mod_midi/midiconfiggui.cpp:187
+msgid "Test"
+msgstr "Prova"
+
+#: src/mod_midi/midiconfiggui.cpp:193
+#: src/mod_sdl/config_gui.cpp:174
+msgid "&OK"
+msgstr "&Acceptar"
+
+#: src/mod_midi/midiconfiggui.cpp:196
+#: src/mod_sdl/config_gui.cpp:177
+msgid "&Cancel"
+msgstr "&Cancel·lar"
+
+#: src/mod_midi/midiconfiggui.cpp:330
+msgid "Cannot open MIDI device. May be it is in use."
+msgstr "No es pot obrir el dispositiu MIDI. Potser està en ús."
+
+#: src/mod_midi/midiconfiggui.cpp:330
+msgid "MIDI error"
+msgstr "Error MIDI"
+
+#: src/mod_midi/midiconfiggui.h:56
+msgid "MIDI Config"
+msgstr "Configuració MIDI"
+
+#: src/mod_score_player/instrselect.cpp:38
+msgid "Acoustic Grand Piano"
+msgstr "Piano de cua"
+
+#: src/mod_score_player/instrselect.cpp:39
+msgid "Bright Acoustic Piano"
+msgstr "Piano vertical"
+
+#: src/mod_score_player/instrselect.cpp:40
+msgid "Electric Grand Piano"
+msgstr "Piano elèctric de cua'"
+
+#: src/mod_score_player/instrselect.cpp:41
+msgid "Honky-Tonk"
+msgstr "Piano de cantina"
+
+#: src/mod_score_player/instrselect.cpp:42
+msgid "Electric Piano 1"
+msgstr "Piano elèctric 1"
+
+#: src/mod_score_player/instrselect.cpp:43
+msgid "Electric Piano 2"
+msgstr "Piano elèctric 2"
+
+#: src/mod_score_player/instrselect.cpp:44
+msgid "Harpsichord"
+msgstr "Arpa"
+
+#: src/mod_score_player/instrselect.cpp:45
+msgid "Clavinet"
+msgstr "Clavecí"
+
+#: src/mod_score_player/instrselect.cpp:46
+msgid "Celesta"
+msgstr "Celesta"
+
+#: src/mod_score_player/instrselect.cpp:47
+msgid "Glockenspiel"
+msgstr "Glockenspiel"
+
+#: src/mod_score_player/instrselect.cpp:48
+msgid "Music Box"
+msgstr "Caixa de música"
+
+#: src/mod_score_player/instrselect.cpp:49
+msgid "Vibraphone"
+msgstr "Vibràfon"
+
+#: src/mod_score_player/instrselect.cpp:50
+msgid "Marimba"
+msgstr "Marimba"
+
+#: src/mod_score_player/instrselect.cpp:51
+msgid "Xylophone"
+msgstr "Xilofon"
+
+#: src/mod_score_player/instrselect.cpp:52
+msgid "Tubular Bells"
+msgstr "Campanes de tub"
+
+#: src/mod_score_player/instrselect.cpp:53
+msgid "Dulcimer"
+msgstr "Dulcemer (salteri alemany)"
+
+#: src/mod_score_player/instrselect.cpp:54
+msgid "Drawbar Organ"
+msgstr "Orgue Hammond"
+
+#: src/mod_score_player/instrselect.cpp:55
+msgid "Percussive Organ"
+msgstr "Orgue de percussió"
+
+#: src/mod_score_player/instrselect.cpp:56
+msgid "Rock Organ"
+msgstr "Orgue de rock"
+
+#: src/mod_score_player/instrselect.cpp:57
+msgid "Church Organ"
+msgstr "Orgue església"
+
+#: src/mod_score_player/instrselect.cpp:58
+msgid "Reed Organ"
+msgstr "Armoni"
+
+#: src/mod_score_player/instrselect.cpp:59
+msgid "Accordion"
+msgstr "Acordió"
+
+#: src/mod_score_player/instrselect.cpp:60
+msgid "Harmonica"
+msgstr "Harmònica"
+
+#: src/mod_score_player/instrselect.cpp:61
+msgid "Tango Accordion"
+msgstr "Bandoneó"
+
+#: src/mod_score_player/instrselect.cpp:62
+msgid "Nylon String Guitar"
+msgstr "Guitarra acústica (cordes de nylon)"
+
+#: src/mod_score_player/instrselect.cpp:63
+msgid "Steel String Guitar"
+msgstr "Guitarra acústica (cordes metàl·liques)"
+
+#: src/mod_score_player/instrselect.cpp:64
+msgid "Electric Jazz Guitar"
+msgstr "Guitarra elèctrica (jazz)"
+
+#: src/mod_score_player/instrselect.cpp:65
+msgid "Electric Clean Guitar"
+msgstr "Guitarra elèctrica"
+
+#: src/mod_score_player/instrselect.cpp:66
+msgid "Electric Muted Guitar"
+msgstr "Guitarra elèctrica (amb sordina)"
+
+#: src/mod_score_player/instrselect.cpp:67
+msgid "Overdriven Guitar"
+msgstr "Guitarra elèctrica (saturada)"
+
+#: src/mod_score_player/instrselect.cpp:68
+msgid "Distortion Guitar"
+msgstr "Guitarra elèctrica (distorsionada)"
+
+#: src/mod_score_player/instrselect.cpp:69
+msgid "Guitar Harmonics"
+msgstr "Guitarra d’harmònics"
+
+#: src/mod_score_player/instrselect.cpp:70
+msgid "Acoustic Bass"
+msgstr "Baix acústic"
+
+#: src/mod_score_player/instrselect.cpp:71
+msgid "Electric Bass(finger)"
+msgstr "Baix elèctric (digitat)"
+
+#: src/mod_score_player/instrselect.cpp:72
+msgid "Electric Bass(pick)"
+msgstr "Baix elèctric (amb pua)"
+
+#: src/mod_score_player/instrselect.cpp:73
+msgid "Fretless Bass"
+msgstr "Baix sense trasts"
+
+#: src/mod_score_player/instrselect.cpp:74
+msgid "Slap Bass 1"
+msgstr "Baix colpejat 1"
+
+#: src/mod_score_player/instrselect.cpp:75
+msgid "Slap Bass 2"
+msgstr "Baix colpejat 2"
+
+#: src/mod_score_player/instrselect.cpp:76
+msgid "Synth Bass 1"
+msgstr "Baix sintetitzat 1"
+
+#: src/mod_score_player/instrselect.cpp:77
+msgid "Synth Bass 2"
+msgstr "Baix sintetitzat 2"
+
+#: src/mod_score_player/instrselect.cpp:78
+msgid "Violin"
+msgstr "Violí"
+
+#: src/mod_score_player/instrselect.cpp:79
+msgid "Viola"
+msgstr "Viola"
+
+#: src/mod_score_player/instrselect.cpp:80
+msgid "Cello"
+msgstr "Violoncel"
+
+#: src/mod_score_player/instrselect.cpp:81
+msgid "Contrabass"
+msgstr "Contrabaix"
+
+#: src/mod_score_player/instrselect.cpp:82
+msgid "Tremolo Strings"
+msgstr "Cordes amb trèmolo"
+
+#: src/mod_score_player/instrselect.cpp:83
+msgid "Pizzicato Strings"
+msgstr "Cordes pessigades"
+
+#: src/mod_score_player/instrselect.cpp:84
+msgid "Orchestral Strings"
+msgstr "Corda"
+
+#: src/mod_score_player/instrselect.cpp:85
+msgid "Timpani"
+msgstr "Timbals"
+
+#: src/mod_score_player/instrselect.cpp:86
+msgid "String Ensemble 1"
+msgstr "Conjunt de corda 1"
+
+#: src/mod_score_player/instrselect.cpp:87
+msgid "String Ensemble 2"
+msgstr "Conjunt de corda 2"
+
+#: src/mod_score_player/instrselect.cpp:88
+msgid "SynthStrings 1"
+msgstr "Cordes sintetitzades 1"
+
+#: src/mod_score_player/instrselect.cpp:89
+msgid "SynthStrings 2"
+msgstr "Cordes sintetitzades 2"
+
+#: src/mod_score_player/instrselect.cpp:90
+msgid "Choir Aahs"
+msgstr "Coral de aah"
+
+#: src/mod_score_player/instrselect.cpp:91
+msgid "Voice Oohs"
+msgstr "Veus ooh"
+
+#: src/mod_score_player/instrselect.cpp:92
+msgid "Synth Voice"
+msgstr "Veus sintetitzades"
+
+#: src/mod_score_player/instrselect.cpp:93
+msgid "Orchestra Hit"
+msgstr "Cop orquestra"
+
+#: src/mod_score_player/instrselect.cpp:94
+msgid "Trumpet"
+msgstr "Trompeta"
+
+#: src/mod_score_player/instrselect.cpp:95
+msgid "Trombone"
+msgstr "Trombó"
+
+#: src/mod_score_player/instrselect.cpp:96
+msgid "Tuba"
+msgstr "Tuba"
+
+#: src/mod_score_player/instrselect.cpp:97
+msgid "Muted Trumpet"
+msgstr "Trompeta amb sordina"
+
+#: src/mod_score_player/instrselect.cpp:98
+msgid "French Horn"
+msgstr "Trompa"
+
+#: src/mod_score_player/instrselect.cpp:99
+msgid "Brass Section"
+msgstr "Grup de vent-metall"
+
+#: src/mod_score_player/instrselect.cpp:100
+msgid "SynthBrass 1"
+msgstr "Conjunt de metall (sint.1)"
+
+#: src/mod_score_player/instrselect.cpp:101
+msgid "SynthBrass 2"
+msgstr "Conjunt de metall (sint.2)"
+
+#: src/mod_score_player/instrselect.cpp:102
+msgid "Soprano Sax"
+msgstr "Saxòfon soprano"
+
+#: src/mod_score_player/instrselect.cpp:103
+msgid "Alto Sax"
+msgstr "Saxòfon contralt"
+
+#: src/mod_score_player/instrselect.cpp:104
+msgid "Tenor Sax"
+msgstr "Saxòfon tenor"
+
+#: src/mod_score_player/instrselect.cpp:105
+msgid "Baritone Sax"
+msgstr "Saxòfon baríton"
+
+#: src/mod_score_player/instrselect.cpp:106
+msgid "Oboe"
+msgstr "Oboè"
+
+#: src/mod_score_player/instrselect.cpp:107
+msgid "English Horn"
+msgstr "Corn anglès"
+
+#: src/mod_score_player/instrselect.cpp:108
+msgid "Bassoon"
+msgstr "Fagot"
+
+#: src/mod_score_player/instrselect.cpp:109
+msgid "Clarinet"
+msgstr "Clarinet"
+
+#: src/mod_score_player/instrselect.cpp:110
+msgid "Piccolo"
+msgstr "Flautí"
+
+#: src/mod_score_player/instrselect.cpp:111
+msgid "Flute"
+msgstr "Flauta travessera"
+
+#: src/mod_score_player/instrselect.cpp:112
+msgid "Recorder"
+msgstr "Flauta dolça"
+
+#: src/mod_score_player/instrselect.cpp:113
+msgid "Pan Flute"
+msgstr "Flauta de Pan"
+
+#: src/mod_score_player/instrselect.cpp:114
+msgid "Blown Bottle"
+msgstr "Botella bufada"
+
+#: src/mod_score_player/instrselect.cpp:115
+msgid "Shakuhachi"
+msgstr "Shakuhachi"
+
+#: src/mod_score_player/instrselect.cpp:116
+msgid "Whistle"
+msgstr "Xiulet"
+
+#: src/mod_score_player/instrselect.cpp:117
+msgid "Ocarina"
+msgstr "Ocarina"
+
+#: src/mod_score_player/instrselect.cpp:118
+msgid "Square Wave"
+msgstr "Ona quadrada"
+
+#: src/mod_score_player/instrselect.cpp:119
+msgid "Saw Wave"
+msgstr "Ona dent serra"
+
+#: src/mod_score_player/instrselect.cpp:120
+msgid "Syn. Calliope"
+msgstr "Orgue portàtil"
+
+#: src/mod_score_player/instrselect.cpp:121
+msgid "Chiffer Lead"
+msgstr "Orgue solista"
+
+#: src/mod_score_player/instrselect.cpp:122
+msgid "Charang"
+msgstr "Xaranga"
+
+#: src/mod_score_player/instrselect.cpp:123
+msgid "Solo Vox"
+msgstr "Veu sintetitzada"
+
+#: src/mod_score_player/instrselect.cpp:124
+msgid "5th Saw Wave"
+msgstr "5ena Ona de Serra"
+
+#: src/mod_score_player/instrselect.cpp:125
+msgid "Bass& Lead"
+msgstr "Baixos"
+
+#: src/mod_score_player/instrselect.cpp:126
+msgid "Fantasia"
+msgstr "Fantasia"
+
+#: src/mod_score_player/instrselect.cpp:127
+msgid "Warm Pad"
+msgstr "Fons càlid"
+
+#: src/mod_score_player/instrselect.cpp:128
+msgid "Polysynth"
+msgstr "Fons múltiple sintetitzat"
+
+#: src/mod_score_player/instrselect.cpp:129
+msgid "Space Voice"
+msgstr "Veus sintetitzades"
+
+#: src/mod_score_player/instrselect.cpp:130
+msgid "Bowed Glass"
+msgstr "Fons d’arcs"
+
+#: src/mod_score_player/instrselect.cpp:131
+msgid "Metal Pad"
+msgstr "Fons metàl·lic"
+
+#: src/mod_score_player/instrselect.cpp:132
+msgid "Halo Pad"
+msgstr "Fons celestial"
+
+#: src/mod_score_player/instrselect.cpp:133
+msgid "Sweep Pad"
+msgstr "Escombrats"
+
+#: src/mod_score_player/instrselect.cpp:134
+msgid "Ice Rain"
+msgstr "Pluja"
+
+#: src/mod_score_player/instrselect.cpp:135
+msgid "Soundtrack"
+msgstr "Efectes: banda sonora"
+
+#: src/mod_score_player/instrselect.cpp:136
+msgid "Crystal"
+msgstr "Cristall"
+
+#: src/mod_score_player/instrselect.cpp:137
+msgid "Atmosphere"
+msgstr "Efectes: atmosfera"
+
+#: src/mod_score_player/instrselect.cpp:138
+msgid "Brightness"
+msgstr "Efectes: brillant"
+
+#: src/mod_score_player/instrselect.cpp:139
+msgid "Goblin"
+msgstr "Follet"
+
+#: src/mod_score_player/instrselect.cpp:140
+msgid "Echo Drops"
+msgstr "Ecos"
+
+#: src/mod_score_player/instrselect.cpp:141
+msgid "Star Theme"
+msgstr "Tema estelar"
+
+#: src/mod_score_player/instrselect.cpp:142
+msgid "Sitar"
+msgstr "Sitar"
+
+#: src/mod_score_player/instrselect.cpp:143
+msgid "Banjo"
+msgstr "Banjo"
+
+#: src/mod_score_player/instrselect.cpp:144
+msgid "Shamisen"
+msgstr "Shamisen"
+
+#: src/mod_score_player/instrselect.cpp:145
+msgid "Koto"
+msgstr "Koto"
+
+#: src/mod_score_player/instrselect.cpp:146
+msgid "Kalimba"
+msgstr "Kalimba"
+
+#: src/mod_score_player/instrselect.cpp:147
+msgid "Bagpipe"
+msgstr "Gaita"
+
+#: src/mod_score_player/instrselect.cpp:148
+msgid "Fiddle"
+msgstr "Violí (arc)"
+
+#: src/mod_score_player/instrselect.cpp:149
+msgid "Shanai"
+msgstr "Shanai"
+
+#: src/mod_score_player/instrselect.cpp:150
+msgid "Tinkle Bell"
+msgstr "Campanetes"
+
+#: src/mod_score_player/instrselect.cpp:151
+msgid "Agogo"
+msgstr "Agogó"
+
+#: src/mod_score_player/instrselect.cpp:152
+msgid "Steel Drums"
+msgstr "Percussió metàl·lica"
+
+#: src/mod_score_player/instrselect.cpp:153
+msgid "Woodblock"
+msgstr "Blocs de fusta"
+
+#: src/mod_score_player/instrselect.cpp:154
+msgid "Taiko Drum"
+msgstr "Taiko"
+
+#: src/mod_score_player/instrselect.cpp:155
+msgid "Melodic Tom"
+msgstr "Tom melòdic"
+
+#: src/mod_score_player/instrselect.cpp:156
+msgid "Synth Drum"
+msgstr "Caixa sintetitzada"
+
+#: src/mod_score_player/instrselect.cpp:157
+msgid "Reverse Cymbal"
+msgstr "Plat (invertit)"
+
+#: src/mod_score_player/instrselect.cpp:158
+msgid "Guitar Fret Noise"
+msgstr "Efectes: so trasts guitarra"
+
+#: src/mod_score_player/instrselect.cpp:159
+msgid "Breath Noise"
+msgstr "Efectes: so de respiració"
+
+#: src/mod_score_player/instrselect.cpp:160
+msgid "Seashore"
+msgstr "Efectes: so onades"
+
+#: src/mod_score_player/instrselect.cpp:161
+msgid "Bird Tweet"
+msgstr "Efectes: refilet d’ocells "
+
+#: src/mod_score_player/instrselect.cpp:162
+msgid "Telephone Ring"
+msgstr "Efectes: timbre de telèfon"
+
+#: src/mod_score_player/instrselect.cpp:163
+msgid "Helicopter"
+msgstr "Efectes: helicòpter"
+
+#: src/mod_score_player/instrselect.cpp:164
+msgid "Applause"
+msgstr "Efectes: aplaudiments"
+
+#: src/mod_score_player/instrselect.cpp:165
+msgid "Gunshot"
+msgstr "Efectes: tret"
+
+#: src/mod_sdl/config_gui.cpp:150
+msgid "Width:"
+msgstr "Amplada:"
+
+#: src/mod_sdl/config_gui.cpp:157
+msgid "Height:"
+msgstr "Alçada:"
+
+#: src/mod_sdl/config_gui.cpp:164
+msgid "Full screen:"
+msgstr "Pantalla completa:"
+
+#: src/mod_sdl/config_gui.cpp:232
+msgid "SDL Configuration error: cannot create sdl_config component"
+msgstr "Error de configuració SDL: no es pot crear component sdl_config"
+
+#: src/mod_sdl/config_gui.h:52
+#| msgid "Camera Configuration"
+msgid "SDL Configuration"
+msgstr "Configuració SDL"
+
+#: src/mod_widgets/choice.h:57
+msgid "Choice"
+msgstr "Opció"
+
+#: src/mod_widgets/filepicker.cpp:322
+msgid "Choose..."
+msgstr "Escollir..."
+
+#: src/mod_widgets/filepicker.cpp:384
+msgid "Choose a directory"
+msgstr "Esculli un directori"
+
+#: src/mod_widgets/filepicker.cpp:390
+msgid "Choose a file to open"
+msgstr "Esculli un fitxer per obrir"
+
+#: src/mod_widgets/filepicker.h:60
+msgid "FilePicker"
+msgstr "SelectorFitrxer"
+
+#: src/mod_widgets/slider.h:60
+msgid "Slider"
+msgstr "Lliscador"
+
+#: src/mod_wiimotes/mod_wiimotes.cpp:1131
+#: src/mod_wiimotes/wwiimotesconfiguration.h:60
+msgid "Wiimotes Configuration"
+msgstr "Configuració Wiimotes"
+
+#: src/mod_wiimotes/wwiimotesconfiguration.cpp:144
+msgid "Wiimote device 1"
+msgstr "Dispositiu Wiimote 1"
+
+#: src/mod_wiimotes/wwiimotesconfiguration.cpp:152
+msgid "Wiimote device 2"
+msgstr "Dispositiu Wiimote 2"
+
+#: src/mod_wiimotes/wwiimotesconfiguration.cpp:162
+msgid "Wiimote device 3"
+msgstr "Dispositiu Wiimote 3"
+
+#: src/mod_wiimotes/wwiimotesconfiguration.cpp:172
+msgid "Wiimote device 4"
+msgstr "Dispositiu Wiimote 4"
+
+#: src/mod_wiimotes/wwiimotesconfiguration.cpp:183
+msgid "Reconnect"
+msgstr "Tornar a connectar"
+
+#: src/mod_wiimotes/wwiimotesproperties.cpp:150
+msgid "Connected"
+msgstr "Connectat"
+
+#: src/mod_wiimotes/wwiimotesproperties.cpp:156
+msgid "Accelerometers enabled"
+msgstr "Acceleròmetres activats"
+
+#: src/mod_wiimotes/wwiimotesproperties.cpp:162
+msgid "Nunchuck enabled"
+msgstr "Nunchuck activat"
+
+#: src/mod_wiimotes/wwiimotesproperties.cpp:168
+msgid "Motion plus enabled"
+msgstr "Motion plus activat"
+
+#~ msgid "Camera Dialog"
+#~ msgstr "Diàleg de càmera"
+#~ msgid "Select midi device to use"
+#~ msgstr "Escollir dispositiu MIDI a usar"
+
diff --git a/po/libsitplus/es.po b/po/libsitplus/es.po
new file mode 100644
index 0000000..6008046
--- /dev/null
+++ b/po/libsitplus/es.po
@@ -0,0 +1,721 @@
+# Spanish translations for libsitplus package.
+# Copyright (C) 2011-13 SITPLUS Project
+# This file is distributed under the same license as the libsitplus package.
+# Automatically generated, 2011.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: libsitplus 1.0\n"
+"Report-Msgid-Bugs-To: cesar at crea-si.com/\n"
+"POT-Creation-Date: 2013-04-11 16:05+0200\n"
+"PO-Revision-Date: 2013-04-11 18:38+0100\n"
+"Last-Translator: Cesar Mauri <cesar at crea-si.com>\n"
+"Language-Team: none\n"
+"Language: \n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+"X-Poedit-Language: Spanish\n"
+
+#: include/widgets_base/containerpanel.h:50
+msgid "ContainerPanel"
+msgstr "PanelContenedor"
+
+#: include/widgets_base/dialogcontainer.h:51
+msgid "DialogContainer"
+msgstr "DialogoContenedor"
+
+#: src/core/language.cpp:51
+msgid "System default"
+msgstr "Por defecto del sistema"
+
+#: src/host/componenthelper.cpp:619
+msgid "Advanced"
+msgstr "Avanzado"
+
+#: src/host/langutils.cpp:59
+msgid "Language"
+msgstr "Idioma"
+
+#: src/mod_camera/wcameraconfiguration.cpp:156
+msgid "Camera properties"
+msgstr "Propiedades cámara"
+
+#: src/mod_camera/wcameraconfiguration.cpp:165
+msgid "Selected camera:"
+msgstr "Cámara seleccionada:"
+
+#: src/mod_camera/wcameraconfiguration.cpp:174
+msgid "Format:"
+msgstr "Formato:"
+
+#: src/mod_camera/wcameraconfiguration.cpp:183
+msgid "Capture speed:"
+msgstr "Velocidad de captura:"
+
+#: src/mod_camera/wcameraconfiguration.cpp:192
+msgid "Driver settings:"
+msgstr "Ajustes del controlador:"
+
+#: src/mod_camera/wcameraconfiguration.cpp:196
+msgid "Open driver settings"
+msgstr "Abrir ajustes del controlador"
+
+#: src/mod_camera/wcameraconfiguration.cpp:200
+msgid "Image mirror:"
+msgstr "Imagen espejo:"
+
+#: src/mod_camera/wcameraconfiguration.cpp:209
+msgid "Close"
+msgstr "Cerrar"
+
+#: src/mod_camera/wcameraconfiguration.cpp:318
+msgid "Camera module"
+msgstr "Módulo de cámara"
+
+#: src/mod_camera/wcameraconfiguration.cpp:318
+msgid "Not detected any camera"
+msgstr "No se ha detectado ninguna cámara"
+
+#: src/mod_camera/wcameraconfiguration.h:60
+msgid "Camera Configuration"
+msgstr "Configuración de cámara"
+
+#: src/mod_camera/wcamerapanel.h:34
+msgid "Camera viewer"
+msgstr "Visor de cámara"
+
+#: src/mod_midi/midiconfiggui.cpp:176
+msgid "Select MIDI output device"
+msgstr "Escoger dispositivo salida MIDI"
+
+#: src/mod_midi/midiconfiggui.cpp:187
+msgid "Test"
+msgstr "Prueba"
+
+#: src/mod_midi/midiconfiggui.cpp:193
+#: src/mod_sdl/config_gui.cpp:174
+msgid "&OK"
+msgstr "&Aceptar"
+
+#: src/mod_midi/midiconfiggui.cpp:196
+#: src/mod_sdl/config_gui.cpp:177
+msgid "&Cancel"
+msgstr "&Cancelar"
+
+#: src/mod_midi/midiconfiggui.cpp:330
+msgid "Cannot open MIDI device. May be it is in use."
+msgstr "No se puede abrir dispositivo MIDI. Quizás esté en uso."
+
+#: src/mod_midi/midiconfiggui.cpp:330
+msgid "MIDI error"
+msgstr "Error MIDI"
+
+#: src/mod_midi/midiconfiggui.h:56
+msgid "MIDI Config"
+msgstr "Configuración MIDI"
+
+#: src/mod_score_player/instrselect.cpp:38
+msgid "Acoustic Grand Piano"
+msgstr "Piano de cola"
+
+#: src/mod_score_player/instrselect.cpp:39
+msgid "Bright Acoustic Piano"
+msgstr "Piano vertical"
+
+#: src/mod_score_player/instrselect.cpp:40
+msgid "Electric Grand Piano"
+msgstr "Piano eléctrico 'de cola'"
+
+#: src/mod_score_player/instrselect.cpp:41
+msgid "Honky-Tonk"
+msgstr "Piano de cantina"
+
+#: src/mod_score_player/instrselect.cpp:42
+msgid "Electric Piano 1"
+msgstr "Piano eléctrico 1"
+
+#: src/mod_score_player/instrselect.cpp:43
+msgid "Electric Piano 2"
+msgstr "Piano eléctrico 2"
+
+#: src/mod_score_player/instrselect.cpp:44
+msgid "Harpsichord"
+msgstr "Arpa"
+
+#: src/mod_score_player/instrselect.cpp:45
+msgid "Clavinet"
+msgstr "Clavecín"
+
+#: src/mod_score_player/instrselect.cpp:46
+msgid "Celesta"
+msgstr "Celesta"
+
+#: src/mod_score_player/instrselect.cpp:47
+msgid "Glockenspiel"
+msgstr "Glockenspiel"
+
+#: src/mod_score_player/instrselect.cpp:48
+msgid "Music Box"
+msgstr "Caja de música"
+
+#: src/mod_score_player/instrselect.cpp:49
+msgid "Vibraphone"
+msgstr "Vibráfono"
+
+#: src/mod_score_player/instrselect.cpp:50
+msgid "Marimba"
+msgstr "Marimba"
+
+#: src/mod_score_player/instrselect.cpp:51
+msgid "Xylophone"
+msgstr "Xilofón"
+
+#: src/mod_score_player/instrselect.cpp:52
+msgid "Tubular Bells"
+msgstr "Campanas de tubo"
+
+#: src/mod_score_player/instrselect.cpp:53
+msgid "Dulcimer"
+msgstr "Dulcemer (salterio alemán)"
+
+#: src/mod_score_player/instrselect.cpp:54
+msgid "Drawbar Organ"
+msgstr "Órgano Hammond"
+
+#: src/mod_score_player/instrselect.cpp:55
+msgid "Percussive Organ"
+msgstr "Órgano de percusión"
+
+#: src/mod_score_player/instrselect.cpp:56
+msgid "Rock Organ"
+msgstr "Órgano de rock"
+
+#: src/mod_score_player/instrselect.cpp:57
+msgid "Church Organ"
+msgstr "Órgano de iglesia"
+
+#: src/mod_score_player/instrselect.cpp:58
+msgid "Reed Organ"
+msgstr "Armonio"
+
+#: src/mod_score_player/instrselect.cpp:59
+msgid "Accordion"
+msgstr "Acordeón"
+
+#: src/mod_score_player/instrselect.cpp:60
+msgid "Harmonica"
+msgstr "Armónica"
+
+#: src/mod_score_player/instrselect.cpp:61
+msgid "Tango Accordion"
+msgstr "Bandoneón"
+
+#: src/mod_score_player/instrselect.cpp:62
+msgid "Nylon String Guitar"
+msgstr "Guitarra acústica (cuerdas de nylon)"
+
+#: src/mod_score_player/instrselect.cpp:63
+msgid "Steel String Guitar"
+msgstr "Guitarra acústica (cuerdas metálicas)"
+
+#: src/mod_score_player/instrselect.cpp:64
+msgid "Electric Jazz Guitar"
+msgstr "Guitarra eléctrica (jazz)"
+
+#: src/mod_score_player/instrselect.cpp:65
+msgid "Electric Clean Guitar"
+msgstr "Guitarra eléctrica"
+
+#: src/mod_score_player/instrselect.cpp:66
+msgid "Electric Muted Guitar"
+msgstr "Guitarra eléctrica (con sordina)"
+
+#: src/mod_score_player/instrselect.cpp:67
+msgid "Overdriven Guitar"
+msgstr "Guitarra eléctrica (saturada)"
+
+#: src/mod_score_player/instrselect.cpp:68
+msgid "Distortion Guitar"
+msgstr "Guitarra eléctrica (distorsionada)"
+
+#: src/mod_score_player/instrselect.cpp:69
+msgid "Guitar Harmonics"
+msgstr "Guitarra de armónicos"
+
+#: src/mod_score_player/instrselect.cpp:70
+msgid "Acoustic Bass"
+msgstr "Bajo acústico"
+
+#: src/mod_score_player/instrselect.cpp:71
+msgid "Electric Bass(finger)"
+msgstr "Bajo eléctrico (digitado)"
+
+#: src/mod_score_player/instrselect.cpp:72
+msgid "Electric Bass(pick)"
+msgstr "Bajo eléctrico (con púa)"
+
+#: src/mod_score_player/instrselect.cpp:73
+msgid "Fretless Bass"
+msgstr "Bajo sin trastes"
+
+#: src/mod_score_player/instrselect.cpp:74
+msgid "Slap Bass 1"
+msgstr "Bajo golpeado 1"
+
+#: src/mod_score_player/instrselect.cpp:75
+msgid "Slap Bass 2"
+msgstr "Bajo golpeado 2"
+
+#: src/mod_score_player/instrselect.cpp:76
+msgid "Synth Bass 1"
+msgstr "Bajo sintetizado 1"
+
+#: src/mod_score_player/instrselect.cpp:77
+msgid "Synth Bass 2"
+msgstr "Bajo sintetizado 2"
+
+#: src/mod_score_player/instrselect.cpp:78
+msgid "Violin"
+msgstr "Violín"
+
+#: src/mod_score_player/instrselect.cpp:79
+msgid "Viola"
+msgstr "Viola"
+
+#: src/mod_score_player/instrselect.cpp:80
+msgid "Cello"
+msgstr "Violoncelo"
+
+#: src/mod_score_player/instrselect.cpp:81
+msgid "Contrabass"
+msgstr "Contrabajo"
+
+#: src/mod_score_player/instrselect.cpp:82
+msgid "Tremolo Strings"
+msgstr "Cuerdas con trémolo"
+
+#: src/mod_score_player/instrselect.cpp:83
+msgid "Pizzicato Strings"
+msgstr "Cuerdas pellizcadas"
+
+#: src/mod_score_player/instrselect.cpp:84
+msgid "Orchestral Strings"
+msgstr "Cuerda"
+
+#: src/mod_score_player/instrselect.cpp:85
+msgid "Timpani"
+msgstr "Timbales"
+
+#: src/mod_score_player/instrselect.cpp:86
+msgid "String Ensemble 1"
+msgstr "Conjunto de cuerda 1"
+
+#: src/mod_score_player/instrselect.cpp:87
+msgid "String Ensemble 2"
+msgstr "Conjunto de cuerda 2"
+
+#: src/mod_score_player/instrselect.cpp:88
+msgid "SynthStrings 1"
+msgstr "Cuerdas sintetizadas 1"
+
+#: src/mod_score_player/instrselect.cpp:89
+msgid "SynthStrings 2"
+msgstr "Cuerdas sintetizadas 2"
+
+#: src/mod_score_player/instrselect.cpp:90
+msgid "Choir Aahs"
+msgstr "Coro de aah"
+
+#: src/mod_score_player/instrselect.cpp:91
+msgid "Voice Oohs"
+msgstr "Voces ooh"
+
+#: src/mod_score_player/instrselect.cpp:92
+msgid "Synth Voice"
+msgstr "Voces sintetizadas"
+
+#: src/mod_score_player/instrselect.cpp:93
+msgid "Orchestra Hit"
+msgstr "Toque orquesta"
+
+#: src/mod_score_player/instrselect.cpp:94
+msgid "Trumpet"
+msgstr "Trompeta"
+
+#: src/mod_score_player/instrselect.cpp:95
+msgid "Trombone"
+msgstr "Trombón"
+
+#: src/mod_score_player/instrselect.cpp:96
+msgid "Tuba"
+msgstr "Tuba"
+
+#: src/mod_score_player/instrselect.cpp:97
+msgid "Muted Trumpet"
+msgstr "Trompeta con sordina"
+
+#: src/mod_score_player/instrselect.cpp:98
+msgid "French Horn"
+msgstr "Trompa"
+
+#: src/mod_score_player/instrselect.cpp:99
+msgid "Brass Section"
+msgstr "Grupo de viento-metal"
+
+#: src/mod_score_player/instrselect.cpp:100
+msgid "SynthBrass 1"
+msgstr "Conjunto de metal (sint.1)"
+
+#: src/mod_score_player/instrselect.cpp:101
+msgid "SynthBrass 2"
+msgstr "Conjunto de metal (sint.2)"
+
+#: src/mod_score_player/instrselect.cpp:102
+msgid "Soprano Sax"
+msgstr "Saxofón soprano"
+
+#: src/mod_score_player/instrselect.cpp:103
+msgid "Alto Sax"
+msgstr "Saxofón contralto"
+
+#: src/mod_score_player/instrselect.cpp:104
+msgid "Tenor Sax"
+msgstr "Saxofón tenor"
+
+#: src/mod_score_player/instrselect.cpp:105
+msgid "Baritone Sax"
+msgstr "Saxofón barítono"
+
+#: src/mod_score_player/instrselect.cpp:106
+msgid "Oboe"
+msgstr "Oboe"
+
+#: src/mod_score_player/instrselect.cpp:107
+msgid "English Horn"
+msgstr "Corno inglés"
+
+#: src/mod_score_player/instrselect.cpp:108
+msgid "Bassoon"
+msgstr "Fagot"
+
+#: src/mod_score_player/instrselect.cpp:109
+msgid "Clarinet"
+msgstr "Clarinete"
+
+#: src/mod_score_player/instrselect.cpp:110
+msgid "Piccolo"
+msgstr "Flautín"
+
+#: src/mod_score_player/instrselect.cpp:111
+msgid "Flute"
+msgstr "Flauta travesera"
+
+#: src/mod_score_player/instrselect.cpp:112
+msgid "Recorder"
+msgstr "Flauta dulce"
+
+#: src/mod_score_player/instrselect.cpp:113
+msgid "Pan Flute"
+msgstr "Flauta de Pan"
+
+#: src/mod_score_player/instrselect.cpp:114
+msgid "Blown Bottle"
+msgstr "Botella soplada"
+
+#: src/mod_score_player/instrselect.cpp:115
+msgid "Shakuhachi"
+msgstr "Shakuhachi"
+
+#: src/mod_score_player/instrselect.cpp:116
+msgid "Whistle"
+msgstr "Silbato"
+
+#: src/mod_score_player/instrselect.cpp:117
+msgid "Ocarina"
+msgstr "Ocarina"
+
+#: src/mod_score_player/instrselect.cpp:118
+msgid "Square Wave"
+msgstr "Onda cuadrada"
+
+#: src/mod_score_player/instrselect.cpp:119
+msgid "Saw Wave"
+msgstr "Onda diente sierra"
+
+#: src/mod_score_player/instrselect.cpp:120
+msgid "Syn. Calliope"
+msgstr "Órgano portátil"
+
+#: src/mod_score_player/instrselect.cpp:121
+msgid "Chiffer Lead"
+msgstr "Órgano solista"
+
+#: src/mod_score_player/instrselect.cpp:122
+msgid "Charang"
+msgstr "Charanga"
+
+#: src/mod_score_player/instrselect.cpp:123
+msgid "Solo Vox"
+msgstr "Voz sintetizada"
+
+#: src/mod_score_player/instrselect.cpp:124
+msgid "5th Saw Wave"
+msgstr " 5ª Onda de Sierra"
+
+#: src/mod_score_player/instrselect.cpp:125
+msgid "Bass& Lead"
+msgstr "Bajos"
+
+#: src/mod_score_player/instrselect.cpp:126
+msgid "Fantasia"
+msgstr "Fantasía"
+
+#: src/mod_score_player/instrselect.cpp:127
+msgid "Warm Pad"
+msgstr "Fondo cálido"
+
+#: src/mod_score_player/instrselect.cpp:128
+msgid "Polysynth"
+msgstr "Fondo múltiple sintetizado"
+
+#: src/mod_score_player/instrselect.cpp:129
+msgid "Space Voice"
+msgstr "Voces sintetizadas"
+
+#: src/mod_score_player/instrselect.cpp:130
+msgid "Bowed Glass"
+msgstr "Fondo de arcos"
+
+#: src/mod_score_player/instrselect.cpp:131
+msgid "Metal Pad"
+msgstr "Fondo metálico"
+
+#: src/mod_score_player/instrselect.cpp:132
+msgid "Halo Pad"
+msgstr "Fondo celestial"
+
+#: src/mod_score_player/instrselect.cpp:133
+msgid "Sweep Pad"
+msgstr "Barridos"
+
+#: src/mod_score_player/instrselect.cpp:134
+msgid "Ice Rain"
+msgstr "Lluvia"
+
+#: src/mod_score_player/instrselect.cpp:135
+msgid "Soundtrack"
+msgstr "Efectos: banda sonora"
+
+#: src/mod_score_player/instrselect.cpp:136
+msgid "Crystal"
+msgstr "Cristal"
+
+#: src/mod_score_player/instrselect.cpp:137
+msgid "Atmosphere"
+msgstr "Efectos: atmósfera"
+
+#: src/mod_score_player/instrselect.cpp:138
+msgid "Brightness"
+msgstr "Efectos: brillante"
+
+#: src/mod_score_player/instrselect.cpp:139
+msgid "Goblin"
+msgstr "Duende"
+
+#: src/mod_score_player/instrselect.cpp:140
+msgid "Echo Drops"
+msgstr "Ecos"
+
+#: src/mod_score_player/instrselect.cpp:141
+msgid "Star Theme"
+msgstr "Tema estelar"
+
+#: src/mod_score_player/instrselect.cpp:142
+msgid "Sitar"
+msgstr "Sitar"
+
+#: src/mod_score_player/instrselect.cpp:143
+msgid "Banjo"
+msgstr "Banjo"
+
+#: src/mod_score_player/instrselect.cpp:144
+msgid "Shamisen"
+msgstr "Shamisen"
+
+#: src/mod_score_player/instrselect.cpp:145
+msgid "Koto"
+msgstr "Koto"
+
+#: src/mod_score_player/instrselect.cpp:146
+msgid "Kalimba"
+msgstr "Kalimba"
+
+#: src/mod_score_player/instrselect.cpp:147
+msgid "Bagpipe"
+msgstr "Gaita"
+
+#: src/mod_score_player/instrselect.cpp:148
+msgid "Fiddle"
+msgstr "Violín (arco)"
+
+#: src/mod_score_player/instrselect.cpp:149
+msgid "Shanai"
+msgstr "Shanai"
+
+#: src/mod_score_player/instrselect.cpp:150
+msgid "Tinkle Bell"
+msgstr "Campanillas"
+
+#: src/mod_score_player/instrselect.cpp:151
+msgid "Agogo"
+msgstr "Agogó"
+
+#: src/mod_score_player/instrselect.cpp:152
+msgid "Steel Drums"
+msgstr "Percusión metálica"
+
+#: src/mod_score_player/instrselect.cpp:153
+msgid "Woodblock"
+msgstr "Bloques de madera"
+
+#: src/mod_score_player/instrselect.cpp:154
+msgid "Taiko Drum"
+msgstr "Taiko"
+
+#: src/mod_score_player/instrselect.cpp:155
+msgid "Melodic Tom"
+msgstr "Tom melódico"
+
+#: src/mod_score_player/instrselect.cpp:156
+msgid "Synth Drum"
+msgstr "Caja sintetizada"
+
+#: src/mod_score_player/instrselect.cpp:157
+msgid "Reverse Cymbal"
+msgstr "Plato (invertido)"
+
+#: src/mod_score_player/instrselect.cpp:158
+msgid "Guitar Fret Noise"
+msgstr "Efectos: ruido de trastes de guitarra"
+
+#: src/mod_score_player/instrselect.cpp:159
+msgid "Breath Noise"
+msgstr "Efectos: ruido de respiración"
+
+#: src/mod_score_player/instrselect.cpp:160
+msgid "Seashore"
+msgstr "Efectos: ruido de olas"
+
+#: src/mod_score_player/instrselect.cpp:161
+msgid "Bird Tweet"
+msgstr "Efectos: trino de pájaros"
+
+#: src/mod_score_player/instrselect.cpp:162
+msgid "Telephone Ring"
+msgstr "Efectos: timbre de teléfono"
+
+#: src/mod_score_player/instrselect.cpp:163
+msgid "Helicopter"
+msgstr "Efectos: helicóptero"
+
+#: src/mod_score_player/instrselect.cpp:164
+msgid "Applause"
+msgstr "Efectos: aplausos"
+
+#: src/mod_score_player/instrselect.cpp:165
+msgid "Gunshot"
+msgstr "Efectos: disparo"
+
+#: src/mod_sdl/config_gui.cpp:150
+msgid "Width:"
+msgstr "Ancho:"
+
+#: src/mod_sdl/config_gui.cpp:157
+msgid "Height:"
+msgstr "Alto:"
+
+#: src/mod_sdl/config_gui.cpp:164
+msgid "Full screen:"
+msgstr "Pantalla completa:"
+
+#: src/mod_sdl/config_gui.cpp:232
+msgid "SDL Configuration error: cannot create sdl_config component"
+msgstr "Error configuración SDL: no se puede crear componente sdl_config"
+
+#: src/mod_sdl/config_gui.h:52
+#| msgid "Camera Configuration"
+msgid "SDL Configuration"
+msgstr "Configuración SDL"
+
+#: src/mod_widgets/choice.h:57
+msgid "Choice"
+msgstr "Elección"
+
+#: src/mod_widgets/filepicker.cpp:322
+msgid "Choose..."
+msgstr "Escoger..."
+
+#: src/mod_widgets/filepicker.cpp:384
+msgid "Choose a directory"
+msgstr "Escoja un directorio"
+
+#: src/mod_widgets/filepicker.cpp:390
+msgid "Choose a file to open"
+msgstr "Escoja un fichero para abrir"
+
+#: src/mod_widgets/filepicker.h:60
+msgid "FilePicker"
+msgstr "SelectorFichero"
+
+#: src/mod_widgets/slider.h:60
+msgid "Slider"
+msgstr "Deslizante"
+
+#: src/mod_wiimotes/mod_wiimotes.cpp:1131
+#: src/mod_wiimotes/wwiimotesconfiguration.h:60
+msgid "Wiimotes Configuration"
+msgstr "Configuración Wiimotes"
+
+#: src/mod_wiimotes/wwiimotesconfiguration.cpp:144
+msgid "Wiimote device 1"
+msgstr "Dispositivo Wiimote 1"
+
+#: src/mod_wiimotes/wwiimotesconfiguration.cpp:152
+msgid "Wiimote device 2"
+msgstr "Dispositivo Wiimote 2"
+
+#: src/mod_wiimotes/wwiimotesconfiguration.cpp:162
+msgid "Wiimote device 3"
+msgstr "Dispositivo Wiimote 3"
+
+#: src/mod_wiimotes/wwiimotesconfiguration.cpp:172
+msgid "Wiimote device 4"
+msgstr "Dispositivo Wiimote 4"
+
+#: src/mod_wiimotes/wwiimotesconfiguration.cpp:183
+msgid "Reconnect"
+msgstr "Volver a conectar"
+
+#: src/mod_wiimotes/wwiimotesproperties.cpp:150
+msgid "Connected"
+msgstr "Conectado"
+
+#: src/mod_wiimotes/wwiimotesproperties.cpp:156
+msgid "Accelerometers enabled"
+msgstr "Acelerómetros activados"
+
+#: src/mod_wiimotes/wwiimotesproperties.cpp:162
+msgid "Nunchuck enabled"
+msgstr "Nunchuck activado"
+
+#: src/mod_wiimotes/wwiimotesproperties.cpp:168
+msgid "Motion plus enabled"
+msgstr "Motion plus activado"
+
+#~ msgid "Camera Dialog"
+#~ msgstr "Diálogo de cámara"
+#~ msgid "Select midi device to use"
+#~ msgstr "Seleccione dispositivo MIDI a usar"
+
diff --git a/po/libsitplus/gl.po b/po/libsitplus/gl.po
new file mode 100644
index 0000000..fbc700c
--- /dev/null
+++ b/po/libsitplus/gl.po
@@ -0,0 +1,714 @@
+# SOME DESCRIPTIVE TITLE.
+# Copyright (C) YEAR SITPLUS Project
+# This file is distributed under the same license as the PACKAGE package.
+# 
+# Translators:
+# Automatically generated, 2011
+# mbouzada <mbouzada at gmail.com>, 2013
+# mbouzada <mbouzada at gmail.com>, 2011
+msgid ""
+msgstr ""
+"Project-Id-Version: libsitplus\n"
+"Report-Msgid-Bugs-To: cesar at crea-si.com/\n"
+"POT-Creation-Date: 2013-04-18 11:53+0200\n"
+"PO-Revision-Date: 2013-04-11 19:22+0000\n"
+"Last-Translator: mbouzada <mbouzada at gmail.com>\n"
+"Language-Team: Galician (http://www.transifex.com/projects/p/libsitplus/language/gl/)\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Language: gl\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+
+#: include/widgets_base/containerpanel.h:50
+msgid "ContainerPanel"
+msgstr "ContedorPanel"
+
+#: include/widgets_base/dialogcontainer.h:51
+msgid "DialogContainer"
+msgstr "DialogoContedor"
+
+#: src/core/language.cpp:51
+msgid "System default"
+msgstr "Predeterminado do sistema"
+
+#: src/host/componenthelper.cpp:619
+msgid "Advanced"
+msgstr "Avanzado"
+
+#: src/host/langutils.cpp:59
+msgid "Language"
+msgstr "Idioma"
+
+#: src/mod_camera/wcameraconfiguration.cpp:156
+msgid "Camera properties"
+msgstr "Propiedades da cámara"
+
+#: src/mod_camera/wcameraconfiguration.cpp:165
+msgid "Selected camera:"
+msgstr "Cámara seleccionada:"
+
+#: src/mod_camera/wcameraconfiguration.cpp:174
+msgid "Format:"
+msgstr "Formato:"
+
+#: src/mod_camera/wcameraconfiguration.cpp:183
+msgid "Capture speed:"
+msgstr "Velocidade de captura:"
+
+#: src/mod_camera/wcameraconfiguration.cpp:192
+msgid "Driver settings:"
+msgstr "Axustes do controlador:"
+
+#: src/mod_camera/wcameraconfiguration.cpp:196
+msgid "Open driver settings"
+msgstr "Abrir os axustes do controlador"
+
+#: src/mod_camera/wcameraconfiguration.cpp:200
+msgid "Image mirror:"
+msgstr "Imaxe en espello:"
+
+#: src/mod_camera/wcameraconfiguration.cpp:209
+msgid "Close"
+msgstr "Pechar"
+
+#: src/mod_camera/wcameraconfiguration.cpp:318
+msgid "Camera module"
+msgstr "Módulo de cámara"
+
+#: src/mod_camera/wcameraconfiguration.cpp:318
+msgid "Not detected any camera"
+msgstr "Non foi detectada ningunha cámara"
+
+#: src/mod_camera/wcameraconfiguration.h:60
+msgid "Camera Configuration"
+msgstr "Configuración da cámara"
+
+#: src/mod_camera/wcamerapanel.h:34
+msgid "Camera viewer"
+msgstr "Visor da cámara"
+
+#: src/mod_midi/midiconfiggui.cpp:176
+msgid "Select MIDI output device"
+msgstr "Escoller o dispositivo de saída MIDI"
+
+#: src/mod_midi/midiconfiggui.cpp:187
+msgid "Test"
+msgstr "Proba"
+
+#: src/mod_midi/midiconfiggui.cpp:193 src/mod_sdl/config_gui.cpp:174
+msgid "&OK"
+msgstr "&Aceptar"
+
+#: src/mod_midi/midiconfiggui.cpp:196 src/mod_sdl/config_gui.cpp:177
+msgid "&Cancel"
+msgstr "&Cancelar"
+
+#: src/mod_midi/midiconfiggui.cpp:330
+msgid "Cannot open MIDI device. May be it is in use."
+msgstr "Non é posíbel abrir o dispositivo MIDI. É probábel que estea en uso."
+
+#: src/mod_midi/midiconfiggui.cpp:330
+msgid "MIDI error"
+msgstr "Produciuse un erro de MIDI"
+
+#: src/mod_midi/midiconfiggui.h:56
+msgid "MIDI Config"
+msgstr "Configuración MIDI"
+
+#: src/mod_score_player/instrselect.cpp:38
+msgid "Acoustic Grand Piano"
+msgstr "Gran piano (de cola)"
+
+#: src/mod_score_player/instrselect.cpp:39
+msgid "Bright Acoustic Piano"
+msgstr "Piano vertical"
+
+#: src/mod_score_player/instrselect.cpp:40
+msgid "Electric Grand Piano"
+msgstr "Gran piano eléctrico"
+
+#: src/mod_score_player/instrselect.cpp:41
+msgid "Honky-Tonk"
+msgstr "Piano de cantina"
+
+#: src/mod_score_player/instrselect.cpp:42
+msgid "Electric Piano 1"
+msgstr "Piano eléctrico 1"
+
+#: src/mod_score_player/instrselect.cpp:43
+msgid "Electric Piano 2"
+msgstr "Piano eléctrico 2"
+
+#: src/mod_score_player/instrselect.cpp:44
+msgid "Harpsichord"
+msgstr "Arpa"
+
+#: src/mod_score_player/instrselect.cpp:45
+msgid "Clavinet"
+msgstr "Clavecín"
+
+#: src/mod_score_player/instrselect.cpp:46
+msgid "Celesta"
+msgstr "Celesta"
+
+#: src/mod_score_player/instrselect.cpp:47
+msgid "Glockenspiel"
+msgstr "Glockenspiel (lira)"
+
+#: src/mod_score_player/instrselect.cpp:48
+msgid "Music Box"
+msgstr "Caixa de música"
+
+#: src/mod_score_player/instrselect.cpp:49
+msgid "Vibraphone"
+msgstr "Vibráfono"
+
+#: src/mod_score_player/instrselect.cpp:50
+msgid "Marimba"
+msgstr "Marimba"
+
+#: src/mod_score_player/instrselect.cpp:51
+msgid "Xylophone"
+msgstr "Xilófono"
+
+#: src/mod_score_player/instrselect.cpp:52
+msgid "Tubular Bells"
+msgstr "Campás de tubo"
+
+#: src/mod_score_player/instrselect.cpp:53
+msgid "Dulcimer"
+msgstr "dulcimer (salterio alemán)"
+
+#: src/mod_score_player/instrselect.cpp:54
+msgid "Drawbar Organ"
+msgstr "Órgano tipo «Hammond»"
+
+#: src/mod_score_player/instrselect.cpp:55
+msgid "Percussive Organ"
+msgstr "Órgano de percusión"
+
+#: src/mod_score_player/instrselect.cpp:56
+msgid "Rock Organ"
+msgstr "Órgano de rock"
+
+#: src/mod_score_player/instrselect.cpp:57
+msgid "Church Organ"
+msgstr "Órgano de igrexa"
+
+#: src/mod_score_player/instrselect.cpp:58
+msgid "Reed Organ"
+msgstr "Harmonio"
+
+#: src/mod_score_player/instrselect.cpp:59
+msgid "Accordion"
+msgstr "Acordeón"
+
+#: src/mod_score_player/instrselect.cpp:60
+msgid "Harmonica"
+msgstr "Harmónica"
+
+#: src/mod_score_player/instrselect.cpp:61
+msgid "Tango Accordion"
+msgstr "Bandoneón"
+
+#: src/mod_score_player/instrselect.cpp:62
+msgid "Nylon String Guitar"
+msgstr "Guitarra acústica (cordas de nailon)"
+
+#: src/mod_score_player/instrselect.cpp:63
+msgid "Steel String Guitar"
+msgstr "Guitarra acústica (cordas metálicas)"
+
+#: src/mod_score_player/instrselect.cpp:64
+msgid "Electric Jazz Guitar"
+msgstr "Guitarra eléctrica (jazz)"
+
+#: src/mod_score_player/instrselect.cpp:65
+msgid "Electric Clean Guitar"
+msgstr "Guitarra eléctrica"
+
+#: src/mod_score_player/instrselect.cpp:66
+msgid "Electric Muted Guitar"
+msgstr "Guitarra eléctrica (con sordina)"
+
+#: src/mod_score_player/instrselect.cpp:67
+msgid "Overdriven Guitar"
+msgstr "Guitarra eléctrica (saturada)"
+
+#: src/mod_score_player/instrselect.cpp:68
+msgid "Distortion Guitar"
+msgstr "Guitarra eléctrica (distorsionada)"
+
+#: src/mod_score_player/instrselect.cpp:69
+msgid "Guitar Harmonics"
+msgstr "Harmónicos de guitarra"
+
+#: src/mod_score_player/instrselect.cpp:70
+msgid "Acoustic Bass"
+msgstr "Baixo acústico"
+
+#: src/mod_score_player/instrselect.cpp:71
+msgid "Electric Bass(finger)"
+msgstr "Baixo eléctrico (dixitado)"
+
+#: src/mod_score_player/instrselect.cpp:72
+msgid "Electric Bass(pick)"
+msgstr "Baixo eléctrico (con púa)"
+
+#: src/mod_score_player/instrselect.cpp:73
+msgid "Fretless Bass"
+msgstr "Baixo sen trastes"
+
+#: src/mod_score_player/instrselect.cpp:74
+msgid "Slap Bass 1"
+msgstr "Baixo golpeado 1"
+
+#: src/mod_score_player/instrselect.cpp:75
+msgid "Slap Bass 2"
+msgstr "Baixo golpeado 2"
+
+#: src/mod_score_player/instrselect.cpp:76
+msgid "Synth Bass 1"
+msgstr "Baixo sintetizado 1"
+
+#: src/mod_score_player/instrselect.cpp:77
+msgid "Synth Bass 2"
+msgstr "Baixo sintetizado 2"
+
+#: src/mod_score_player/instrselect.cpp:78
+msgid "Violin"
+msgstr "Violín"
+
+#: src/mod_score_player/instrselect.cpp:79
+msgid "Viola"
+msgstr "Viola"
+
+#: src/mod_score_player/instrselect.cpp:80
+msgid "Cello"
+msgstr "Violoncello"
+
+#: src/mod_score_player/instrselect.cpp:81
+msgid "Contrabass"
+msgstr "Contrabaixo"
+
+#: src/mod_score_player/instrselect.cpp:82
+msgid "Tremolo Strings"
+msgstr "Cordas con trémolo"
+
+#: src/mod_score_player/instrselect.cpp:83
+msgid "Pizzicato Strings"
+msgstr "Cordas beliscadas"
+
+#: src/mod_score_player/instrselect.cpp:84
+msgid "Orchestral Strings"
+msgstr "Cordas orquestrais"
+
+#: src/mod_score_player/instrselect.cpp:85
+msgid "Timpani"
+msgstr "Timbais"
+
+#: src/mod_score_player/instrselect.cpp:86
+msgid "String Ensemble 1"
+msgstr "Conxunto de corda 1"
+
+#: src/mod_score_player/instrselect.cpp:87
+msgid "String Ensemble 2"
+msgstr "Conxunto de corda 2"
+
+#: src/mod_score_player/instrselect.cpp:88
+msgid "SynthStrings 1"
+msgstr "Cordas sintetizadas 1"
+
+#: src/mod_score_player/instrselect.cpp:89
+msgid "SynthStrings 2"
+msgstr "Cordas sintetizadas 2"
+
+#: src/mod_score_player/instrselect.cpp:90
+msgid "Choir Aahs"
+msgstr "Coro de «aah»"
+
+#: src/mod_score_player/instrselect.cpp:91
+msgid "Voice Oohs"
+msgstr "Voces «ooh»"
+
+#: src/mod_score_player/instrselect.cpp:92
+msgid "Synth Voice"
+msgstr "Voces sintetizadas"
+
+#: src/mod_score_player/instrselect.cpp:93
+msgid "Orchestra Hit"
+msgstr "Toque orquestra"
+
+#: src/mod_score_player/instrselect.cpp:94
+msgid "Trumpet"
+msgstr "Trompeta"
+
+#: src/mod_score_player/instrselect.cpp:95
+msgid "Trombone"
+msgstr "Trombón"
+
+#: src/mod_score_player/instrselect.cpp:96
+msgid "Tuba"
+msgstr "Tuba"
+
+#: src/mod_score_player/instrselect.cpp:97
+msgid "Muted Trumpet"
+msgstr "Trompeta con sordina"
+
+#: src/mod_score_player/instrselect.cpp:98
+msgid "French Horn"
+msgstr "Trompa"
+
+#: src/mod_score_player/instrselect.cpp:99
+msgid "Brass Section"
+msgstr "Grupo de vento-metal"
+
+#: src/mod_score_player/instrselect.cpp:100
+msgid "SynthBrass 1"
+msgstr "Conxunto de metal (sint.1)"
+
+#: src/mod_score_player/instrselect.cpp:101
+msgid "SynthBrass 2"
+msgstr "Conxunto de metal (sint.2)"
+
+#: src/mod_score_player/instrselect.cpp:102
+msgid "Soprano Sax"
+msgstr "Saxofón soprano"
+
+#: src/mod_score_player/instrselect.cpp:103
+msgid "Alto Sax"
+msgstr "Saxofón contralto"
+
+#: src/mod_score_player/instrselect.cpp:104
+msgid "Tenor Sax"
+msgstr "Saxofón tenor"
+
+#: src/mod_score_player/instrselect.cpp:105
+msgid "Baritone Sax"
+msgstr "Saxofón barítono"
+
+#: src/mod_score_player/instrselect.cpp:106
+msgid "Oboe"
+msgstr "Óboe"
+
+#: src/mod_score_player/instrselect.cpp:107
+msgid "English Horn"
+msgstr "Corno inglés"
+
+#: src/mod_score_player/instrselect.cpp:108
+msgid "Bassoon"
+msgstr "Fagot"
+
+#: src/mod_score_player/instrselect.cpp:109
+msgid "Clarinet"
+msgstr "Clarinete"
+
+#: src/mod_score_player/instrselect.cpp:110
+msgid "Piccolo"
+msgstr "Frautín"
+
+#: src/mod_score_player/instrselect.cpp:111
+msgid "Flute"
+msgstr "Frauta traveseira"
+
+#: src/mod_score_player/instrselect.cpp:112
+msgid "Recorder"
+msgstr "Frauta doce"
+
+#: src/mod_score_player/instrselect.cpp:113
+msgid "Pan Flute"
+msgstr "Frauta de Pan"
+
+#: src/mod_score_player/instrselect.cpp:114
+msgid "Blown Bottle"
+msgstr "Botella soprada"
+
+#: src/mod_score_player/instrselect.cpp:115
+msgid "Shakuhachi"
+msgstr "Shakuhachi"
+
+#: src/mod_score_player/instrselect.cpp:116
+msgid "Whistle"
+msgstr "Asubío"
+
+#: src/mod_score_player/instrselect.cpp:117
+msgid "Ocarina"
+msgstr "Ocarina"
+
+#: src/mod_score_player/instrselect.cpp:118
+msgid "Square Wave"
+msgstr "Onda cadrada"
+
+#: src/mod_score_player/instrselect.cpp:119
+msgid "Saw Wave"
+msgstr "Onda dente de serra"
+
+#: src/mod_score_player/instrselect.cpp:120
+msgid "Syn. Calliope"
+msgstr "Órgano portátil"
+
+#: src/mod_score_player/instrselect.cpp:121
+msgid "Chiffer Lead"
+msgstr "Órgano solista"
+
+#: src/mod_score_player/instrselect.cpp:122
+msgid "Charang"
+msgstr "Charanga"
+
+#: src/mod_score_player/instrselect.cpp:123
+msgid "Solo Vox"
+msgstr "Voz sintetizada"
+
+#: src/mod_score_player/instrselect.cpp:124
+msgid "5th Saw Wave"
+msgstr "5ª onda de serra"
+
+#: src/mod_score_player/instrselect.cpp:125
+msgid "Bass& Lead"
+msgstr "Baixos"
+
+#: src/mod_score_player/instrselect.cpp:126
+msgid "Fantasia"
+msgstr "Fantasía"
+
+#: src/mod_score_player/instrselect.cpp:127
+msgid "Warm Pad"
+msgstr "Fondo cálido"
+
+#: src/mod_score_player/instrselect.cpp:128
+msgid "Polysynth"
+msgstr "Fondo múltiple sintetizado"
+
+#: src/mod_score_player/instrselect.cpp:129
+msgid "Space Voice"
+msgstr "Voces sintetizadas"
+
+#: src/mod_score_player/instrselect.cpp:130
+msgid "Bowed Glass"
+msgstr "Fondo de arcos"
+
+#: src/mod_score_player/instrselect.cpp:131
+msgid "Metal Pad"
+msgstr "Fondo metálico"
+
+#: src/mod_score_player/instrselect.cpp:132
+msgid "Halo Pad"
+msgstr "Fondo celestial"
+
+#: src/mod_score_player/instrselect.cpp:133
+msgid "Sweep Pad"
+msgstr "Varridos"
+
+#: src/mod_score_player/instrselect.cpp:134
+msgid "Ice Rain"
+msgstr "Choiva"
+
+#: src/mod_score_player/instrselect.cpp:135
+msgid "Soundtrack"
+msgstr "Banda sonora"
+
+#: src/mod_score_player/instrselect.cpp:136
+msgid "Crystal"
+msgstr "Cristal"
+
+#: src/mod_score_player/instrselect.cpp:137
+msgid "Atmosphere"
+msgstr "Atmosfera"
+
+#: src/mod_score_player/instrselect.cpp:138
+msgid "Brightness"
+msgstr "Brillo"
+
+#: src/mod_score_player/instrselect.cpp:139
+msgid "Goblin"
+msgstr "Trasno"
+
+#: src/mod_score_player/instrselect.cpp:140
+msgid "Echo Drops"
+msgstr "Pequenos ecos"
+
+#: src/mod_score_player/instrselect.cpp:141
+msgid "Star Theme"
+msgstr "Tema estelar"
+
+#: src/mod_score_player/instrselect.cpp:142
+msgid "Sitar"
+msgstr "Sitar"
+
+#: src/mod_score_player/instrselect.cpp:143
+msgid "Banjo"
+msgstr "Banjo"
+
+#: src/mod_score_player/instrselect.cpp:144
+msgid "Shamisen"
+msgstr "Shamisen"
+
+#: src/mod_score_player/instrselect.cpp:145
+msgid "Koto"
+msgstr "Koto"
+
+#: src/mod_score_player/instrselect.cpp:146
+msgid "Kalimba"
+msgstr "Kalimba"
+
+#: src/mod_score_player/instrselect.cpp:147
+msgid "Bagpipe"
+msgstr "Gaita"
+
+#: src/mod_score_player/instrselect.cpp:148
+msgid "Fiddle"
+msgstr "Violín (arco)"
+
+#: src/mod_score_player/instrselect.cpp:149
+msgid "Shanai"
+msgstr "Shanai"
+
+#: src/mod_score_player/instrselect.cpp:150
+msgid "Tinkle Bell"
+msgstr "Campaíñas"
+
+#: src/mod_score_player/instrselect.cpp:151
+msgid "Agogo"
+msgstr "Agogó"
+
+#: src/mod_score_player/instrselect.cpp:152
+msgid "Steel Drums"
+msgstr "Percusión metálica"
+
+#: src/mod_score_player/instrselect.cpp:153
+msgid "Woodblock"
+msgstr "Bloques de madeira"
+
+#: src/mod_score_player/instrselect.cpp:154
+msgid "Taiko Drum"
+msgstr "Taiko"
+
+#: src/mod_score_player/instrselect.cpp:155
+msgid "Melodic Tom"
+msgstr "Tomtom melódico"
+
+#: src/mod_score_player/instrselect.cpp:156
+msgid "Synth Drum"
+msgstr "Caixa sintetizada"
+
+#: src/mod_score_player/instrselect.cpp:157
+msgid "Reverse Cymbal"
+msgstr "Prato (invertido)"
+
+#: src/mod_score_player/instrselect.cpp:158
+msgid "Guitar Fret Noise"
+msgstr "Ruído de trastes de guitarra"
+
+#: src/mod_score_player/instrselect.cpp:159
+msgid "Breath Noise"
+msgstr "Ruído de respiración"
+
+#: src/mod_score_player/instrselect.cpp:160
+msgid "Seashore"
+msgstr "Ruído de olas"
+
+#: src/mod_score_player/instrselect.cpp:161
+msgid "Bird Tweet"
+msgstr "Trino de paxaros"
+
+#: src/mod_score_player/instrselect.cpp:162
+msgid "Telephone Ring"
+msgstr "Timbre de teléfono"
+
+#: src/mod_score_player/instrselect.cpp:163
+msgid "Helicopter"
+msgstr "Helicóptero"
+
+#: src/mod_score_player/instrselect.cpp:164
+msgid "Applause"
+msgstr "Aplausos"
+
+#: src/mod_score_player/instrselect.cpp:165
+msgid "Gunshot"
+msgstr "Disparo"
+
+#: src/mod_sdl/config_gui.cpp:150
+msgid "Width:"
+msgstr "Largo:"
+
+#: src/mod_sdl/config_gui.cpp:157
+msgid "Height:"
+msgstr "Alto:"
+
+#: src/mod_sdl/config_gui.cpp:164
+msgid "Full screen:"
+msgstr "Pantalla completa:"
+
+#: src/mod_sdl/config_gui.cpp:232
+msgid "SDL Configuration error: cannot create sdl_config component"
+msgstr "Produciuse un erro na configuración do SDL: non é posíbel crear o compoñente sdl_config"
+
+#: src/mod_sdl/config_gui.h:52
+msgid "SDL Configuration"
+msgstr "Configuración do SDL"
+
+#: src/mod_widgets/choice.h:57
+msgid "Choice"
+msgstr "Escolla"
+
+#: src/mod_widgets/filepicker.cpp:322
+msgid "Choose..."
+msgstr "Escoller..."
+
+#: src/mod_widgets/filepicker.cpp:384
+msgid "Choose a directory"
+msgstr "Escolla un directorio"
+
+#: src/mod_widgets/filepicker.cpp:390
+msgid "Choose a file to open"
+msgstr "Escolla un ficheiro para abrir"
+
+#: src/mod_widgets/filepicker.h:60
+msgid "FilePicker"
+msgstr "SelectorFicheiro"
+
+#: src/mod_widgets/slider.h:60
+msgid "Slider"
+msgstr "Esvarador"
+
+#: src/mod_wiimotes/mod_wiimotes.cpp:1131
+#: src/mod_wiimotes/wwiimotesconfiguration.h:60
+msgid "Wiimotes Configuration"
+msgstr "Configuración «Wiimotes»"
+
+#: src/mod_wiimotes/wwiimotesconfiguration.cpp:144
+msgid "Wiimote device 1"
+msgstr "Dispositivo «Wiimote 1»"
+
+#: src/mod_wiimotes/wwiimotesconfiguration.cpp:152
+msgid "Wiimote device 2"
+msgstr "Dispositivo «Wiimote 2»"
+
+#: src/mod_wiimotes/wwiimotesconfiguration.cpp:162
+msgid "Wiimote device 3"
+msgstr "Dispositivo «Wiimote 3»"
+
+#: src/mod_wiimotes/wwiimotesconfiguration.cpp:172
+msgid "Wiimote device 4"
+msgstr "Dispositivo «Wiimote 4»"
+
+#: src/mod_wiimotes/wwiimotesconfiguration.cpp:183
+msgid "Reconnect"
+msgstr "Volver a conectar"
+
+#: src/mod_wiimotes/wwiimotesproperties.cpp:150
+msgid "Connected"
+msgstr "Conectado"
+
+#: src/mod_wiimotes/wwiimotesproperties.cpp:156
+msgid "Accelerometers enabled"
+msgstr "Acelerómetros activados"
+
+#: src/mod_wiimotes/wwiimotesproperties.cpp:162
+msgid "Nunchuck enabled"
+msgstr "«Nunchuck» activado"
+
+#: src/mod_wiimotes/wwiimotesproperties.cpp:168
+msgid "Motion plus enabled"
+msgstr "«Motion plus» activado"
diff --git a/po/libsitplus/libsitplus.pot b/po/libsitplus/libsitplus.pot
new file mode 100644
index 0000000..c39457c
--- /dev/null
+++ b/po/libsitplus/libsitplus.pot
@@ -0,0 +1,711 @@
+# SOME DESCRIPTIVE TITLE.
+# Copyright (C) YEAR SITPLUS Project
+# This file is distributed under the same license as the PACKAGE package.
+# FIRST AUTHOR <EMAIL at ADDRESS>, YEAR.
+#
+#, fuzzy
+msgid ""
+msgstr ""
+"Project-Id-Version: PACKAGE VERSION\n"
+"Report-Msgid-Bugs-To: cesar at crea-si.com/\n"
+"POT-Creation-Date: 2013-04-18 11:53+0200\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: FULL NAME <EMAIL at ADDRESS>\n"
+"Language-Team: LANGUAGE <LL at li.org>\n"
+"Language: \n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+#: include/widgets_base/containerpanel.h:50
+msgid "ContainerPanel"
+msgstr ""
+
+#: include/widgets_base/dialogcontainer.h:51
+msgid "DialogContainer"
+msgstr ""
+
+#: src/core/language.cpp:51
+msgid "System default"
+msgstr ""
+
+#: src/host/componenthelper.cpp:619
+msgid "Advanced"
+msgstr ""
+
+#: src/host/langutils.cpp:59
+msgid "Language"
+msgstr ""
+
+#: src/mod_camera/wcameraconfiguration.cpp:156
+msgid "Camera properties"
+msgstr ""
+
+#: src/mod_camera/wcameraconfiguration.cpp:165
+msgid "Selected camera:"
+msgstr ""
+
+#: src/mod_camera/wcameraconfiguration.cpp:174
+msgid "Format:"
+msgstr ""
+
+#: src/mod_camera/wcameraconfiguration.cpp:183
+msgid "Capture speed:"
+msgstr ""
+
+#: src/mod_camera/wcameraconfiguration.cpp:192
+msgid "Driver settings:"
+msgstr ""
+
+#: src/mod_camera/wcameraconfiguration.cpp:196
+msgid "Open driver settings"
+msgstr ""
+
+#: src/mod_camera/wcameraconfiguration.cpp:200
+msgid "Image mirror:"
+msgstr ""
+
+#: src/mod_camera/wcameraconfiguration.cpp:209
+msgid "Close"
+msgstr ""
+
+#: src/mod_camera/wcameraconfiguration.cpp:318
+msgid "Camera module"
+msgstr ""
+
+#: src/mod_camera/wcameraconfiguration.cpp:318
+msgid "Not detected any camera"
+msgstr ""
+
+#: src/mod_camera/wcameraconfiguration.h:60
+msgid "Camera Configuration"
+msgstr ""
+
+#: src/mod_camera/wcamerapanel.h:34
+msgid "Camera viewer"
+msgstr ""
+
+#: src/mod_midi/midiconfiggui.cpp:176
+msgid "Select MIDI output device"
+msgstr ""
+
+#: src/mod_midi/midiconfiggui.cpp:187
+msgid "Test"
+msgstr ""
+
+#: src/mod_midi/midiconfiggui.cpp:193 src/mod_sdl/config_gui.cpp:174
+msgid "&OK"
+msgstr ""
+
+#: src/mod_midi/midiconfiggui.cpp:196 src/mod_sdl/config_gui.cpp:177
+msgid "&Cancel"
+msgstr ""
+
+#: src/mod_midi/midiconfiggui.cpp:330
+msgid "Cannot open MIDI device. May be it is in use."
+msgstr ""
+
+#: src/mod_midi/midiconfiggui.cpp:330
+msgid "MIDI error"
+msgstr ""
+
+#: src/mod_midi/midiconfiggui.h:56
+msgid "MIDI Config"
+msgstr ""
+
+#: src/mod_score_player/instrselect.cpp:38
+msgid "Acoustic Grand Piano"
+msgstr ""
+
+#: src/mod_score_player/instrselect.cpp:39
+msgid "Bright Acoustic Piano"
+msgstr ""
+
+#: src/mod_score_player/instrselect.cpp:40
+msgid "Electric Grand Piano"
+msgstr ""
+
+#: src/mod_score_player/instrselect.cpp:41
+msgid "Honky-Tonk"
+msgstr ""
+
+#: src/mod_score_player/instrselect.cpp:42
+msgid "Electric Piano 1"
+msgstr ""
+
+#: src/mod_score_player/instrselect.cpp:43
+msgid "Electric Piano 2"
+msgstr ""
+
+#: src/mod_score_player/instrselect.cpp:44
+msgid "Harpsichord"
+msgstr ""
+
+#: src/mod_score_player/instrselect.cpp:45
+msgid "Clavinet"
+msgstr ""
+
+#: src/mod_score_player/instrselect.cpp:46
+msgid "Celesta"
+msgstr ""
+
+#: src/mod_score_player/instrselect.cpp:47
+msgid "Glockenspiel"
+msgstr ""
+
+#: src/mod_score_player/instrselect.cpp:48
+msgid "Music Box"
+msgstr ""
+
+#: src/mod_score_player/instrselect.cpp:49
+msgid "Vibraphone"
+msgstr ""
+
+#: src/mod_score_player/instrselect.cpp:50
+msgid "Marimba"
+msgstr ""
+
+#: src/mod_score_player/instrselect.cpp:51
+msgid "Xylophone"
+msgstr ""
+
+#: src/mod_score_player/instrselect.cpp:52
+msgid "Tubular Bells"
+msgstr ""
+
+#: src/mod_score_player/instrselect.cpp:53
+msgid "Dulcimer"
+msgstr ""
+
+#: src/mod_score_player/instrselect.cpp:54
+msgid "Drawbar Organ"
+msgstr ""
+
+#: src/mod_score_player/instrselect.cpp:55
+msgid "Percussive Organ"
+msgstr ""
+
+#: src/mod_score_player/instrselect.cpp:56
+msgid "Rock Organ"
+msgstr ""
+
+#: src/mod_score_player/instrselect.cpp:57
+msgid "Church Organ"
+msgstr ""
+
+#: src/mod_score_player/instrselect.cpp:58
+msgid "Reed Organ"
+msgstr ""
+
+#: src/mod_score_player/instrselect.cpp:59
+msgid "Accordion"
+msgstr ""
+
+#: src/mod_score_player/instrselect.cpp:60
+msgid "Harmonica"
+msgstr ""
+
+#: src/mod_score_player/instrselect.cpp:61
+msgid "Tango Accordion"
+msgstr ""
+
+#: src/mod_score_player/instrselect.cpp:62
+msgid "Nylon String Guitar"
+msgstr ""
+
+#: src/mod_score_player/instrselect.cpp:63
+msgid "Steel String Guitar"
+msgstr ""
+
+#: src/mod_score_player/instrselect.cpp:64
+msgid "Electric Jazz Guitar"
+msgstr ""
+
+#: src/mod_score_player/instrselect.cpp:65
+msgid "Electric Clean Guitar"
+msgstr ""
+
+#: src/mod_score_player/instrselect.cpp:66
+msgid "Electric Muted Guitar"
+msgstr ""
+
+#: src/mod_score_player/instrselect.cpp:67
+msgid "Overdriven Guitar"
+msgstr ""
+
+#: src/mod_score_player/instrselect.cpp:68
+msgid "Distortion Guitar"
+msgstr ""
+
+#: src/mod_score_player/instrselect.cpp:69
+msgid "Guitar Harmonics"
+msgstr ""
+
+#: src/mod_score_player/instrselect.cpp:70
+msgid "Acoustic Bass"
+msgstr ""
+
+#: src/mod_score_player/instrselect.cpp:71
+msgid "Electric Bass(finger)"
+msgstr ""
+
+#: src/mod_score_player/instrselect.cpp:72
+msgid "Electric Bass(pick)"
+msgstr ""
+
+#: src/mod_score_player/instrselect.cpp:73
+msgid "Fretless Bass"
+msgstr ""
+
+#: src/mod_score_player/instrselect.cpp:74
+msgid "Slap Bass 1"
+msgstr ""
+
+#: src/mod_score_player/instrselect.cpp:75
+msgid "Slap Bass 2"
+msgstr ""
+
+#: src/mod_score_player/instrselect.cpp:76
+msgid "Synth Bass 1"
+msgstr ""
+
+#: src/mod_score_player/instrselect.cpp:77
+msgid "Synth Bass 2"
+msgstr ""
+
+#: src/mod_score_player/instrselect.cpp:78
+msgid "Violin"
+msgstr ""
+
+#: src/mod_score_player/instrselect.cpp:79
+msgid "Viola"
+msgstr ""
+
+#: src/mod_score_player/instrselect.cpp:80
+msgid "Cello"
+msgstr ""
+
+#: src/mod_score_player/instrselect.cpp:81
+msgid "Contrabass"
+msgstr ""
+
+#: src/mod_score_player/instrselect.cpp:82
+msgid "Tremolo Strings"
+msgstr ""
+
+#: src/mod_score_player/instrselect.cpp:83
+msgid "Pizzicato Strings"
+msgstr ""
+
+#: src/mod_score_player/instrselect.cpp:84
+msgid "Orchestral Strings"
+msgstr ""
+
+#: src/mod_score_player/instrselect.cpp:85
+msgid "Timpani"
+msgstr ""
+
+#: src/mod_score_player/instrselect.cpp:86
+msgid "String Ensemble 1"
+msgstr ""
+
+#: src/mod_score_player/instrselect.cpp:87
+msgid "String Ensemble 2"
+msgstr ""
+
+#: src/mod_score_player/instrselect.cpp:88
+msgid "SynthStrings 1"
+msgstr ""
+
+#: src/mod_score_player/instrselect.cpp:89
+msgid "SynthStrings 2"
+msgstr ""
+
+#: src/mod_score_player/instrselect.cpp:90
+msgid "Choir Aahs"
+msgstr ""
+
+#: src/mod_score_player/instrselect.cpp:91
+msgid "Voice Oohs"
+msgstr ""
+
+#: src/mod_score_player/instrselect.cpp:92
+msgid "Synth Voice"
+msgstr ""
+
+#: src/mod_score_player/instrselect.cpp:93
+msgid "Orchestra Hit"
+msgstr ""
+
+#: src/mod_score_player/instrselect.cpp:94
+msgid "Trumpet"
+msgstr ""
+
+#: src/mod_score_player/instrselect.cpp:95
+msgid "Trombone"
+msgstr ""
+
+#: src/mod_score_player/instrselect.cpp:96
+msgid "Tuba"
+msgstr ""
+
+#: src/mod_score_player/instrselect.cpp:97
+msgid "Muted Trumpet"
+msgstr ""
+
+#: src/mod_score_player/instrselect.cpp:98
+msgid "French Horn"
+msgstr ""
+
+#: src/mod_score_player/instrselect.cpp:99
+msgid "Brass Section"
+msgstr ""
+
+#: src/mod_score_player/instrselect.cpp:100
+msgid "SynthBrass 1"
+msgstr ""
+
+#: src/mod_score_player/instrselect.cpp:101
+msgid "SynthBrass 2"
+msgstr ""
+
+#: src/mod_score_player/instrselect.cpp:102
+msgid "Soprano Sax"
+msgstr ""
+
+#: src/mod_score_player/instrselect.cpp:103
+msgid "Alto Sax"
+msgstr ""
+
+#: src/mod_score_player/instrselect.cpp:104
+msgid "Tenor Sax"
+msgstr ""
+
+#: src/mod_score_player/instrselect.cpp:105
+msgid "Baritone Sax"
+msgstr ""
+
+#: src/mod_score_player/instrselect.cpp:106
+msgid "Oboe"
+msgstr ""
+
+#: src/mod_score_player/instrselect.cpp:107
+msgid "English Horn"
+msgstr ""
+
+#: src/mod_score_player/instrselect.cpp:108
+msgid "Bassoon"
+msgstr ""
+
+#: src/mod_score_player/instrselect.cpp:109
+msgid "Clarinet"
+msgstr ""
+
+#: src/mod_score_player/instrselect.cpp:110
+msgid "Piccolo"
+msgstr ""
+
+#: src/mod_score_player/instrselect.cpp:111
+msgid "Flute"
+msgstr ""
+
+#: src/mod_score_player/instrselect.cpp:112
+msgid "Recorder"
+msgstr ""
+
+#: src/mod_score_player/instrselect.cpp:113
+msgid "Pan Flute"
+msgstr ""
+
+#: src/mod_score_player/instrselect.cpp:114
+msgid "Blown Bottle"
+msgstr ""
+
+#: src/mod_score_player/instrselect.cpp:115
+msgid "Shakuhachi"
+msgstr ""
+
+#: src/mod_score_player/instrselect.cpp:116
+msgid "Whistle"
+msgstr ""
+
+#: src/mod_score_player/instrselect.cpp:117
+msgid "Ocarina"
+msgstr ""
+
+#: src/mod_score_player/instrselect.cpp:118
+msgid "Square Wave"
+msgstr ""
+
+#: src/mod_score_player/instrselect.cpp:119
+msgid "Saw Wave"
+msgstr ""
+
+#: src/mod_score_player/instrselect.cpp:120
+msgid "Syn. Calliope"
+msgstr ""
+
+#: src/mod_score_player/instrselect.cpp:121
+msgid "Chiffer Lead"
+msgstr ""
+
+#: src/mod_score_player/instrselect.cpp:122
+msgid "Charang"
+msgstr ""
+
+#: src/mod_score_player/instrselect.cpp:123
+msgid "Solo Vox"
+msgstr ""
+
+#: src/mod_score_player/instrselect.cpp:124
+msgid "5th Saw Wave"
+msgstr ""
+
+#: src/mod_score_player/instrselect.cpp:125
+msgid "Bass& Lead"
+msgstr ""
+
+#: src/mod_score_player/instrselect.cpp:126
+msgid "Fantasia"
+msgstr ""
+
+#: src/mod_score_player/instrselect.cpp:127
+msgid "Warm Pad"
+msgstr ""
+
+#: src/mod_score_player/instrselect.cpp:128
+msgid "Polysynth"
+msgstr ""
+
+#: src/mod_score_player/instrselect.cpp:129
+msgid "Space Voice"
+msgstr ""
+
+#: src/mod_score_player/instrselect.cpp:130
+msgid "Bowed Glass"
+msgstr ""
+
+#: src/mod_score_player/instrselect.cpp:131
+msgid "Metal Pad"
+msgstr ""
+
+#: src/mod_score_player/instrselect.cpp:132
+msgid "Halo Pad"
+msgstr ""
+
+#: src/mod_score_player/instrselect.cpp:133
+msgid "Sweep Pad"
+msgstr ""
+
+#: src/mod_score_player/instrselect.cpp:134
+msgid "Ice Rain"
+msgstr ""
+
+#: src/mod_score_player/instrselect.cpp:135
+msgid "Soundtrack"
+msgstr ""
+
+#: src/mod_score_player/instrselect.cpp:136
+msgid "Crystal"
+msgstr ""
+
+#: src/mod_score_player/instrselect.cpp:137
+msgid "Atmosphere"
+msgstr ""
+
+#: src/mod_score_player/instrselect.cpp:138
+msgid "Brightness"
+msgstr ""
+
+#: src/mod_score_player/instrselect.cpp:139
+msgid "Goblin"
+msgstr ""
+
+#: src/mod_score_player/instrselect.cpp:140
+msgid "Echo Drops"
+msgstr ""
+
+#: src/mod_score_player/instrselect.cpp:141
+msgid "Star Theme"
+msgstr ""
+
+#: src/mod_score_player/instrselect.cpp:142
+msgid "Sitar"
+msgstr ""
+
+#: src/mod_score_player/instrselect.cpp:143
+msgid "Banjo"
+msgstr ""
+
+#: src/mod_score_player/instrselect.cpp:144
+msgid "Shamisen"
+msgstr ""
+
+#: src/mod_score_player/instrselect.cpp:145
+msgid "Koto"
+msgstr ""
+
+#: src/mod_score_player/instrselect.cpp:146
+msgid "Kalimba"
+msgstr ""
+
+#: src/mod_score_player/instrselect.cpp:147
+msgid "Bagpipe"
+msgstr ""
+
+#: src/mod_score_player/instrselect.cpp:148
+msgid "Fiddle"
+msgstr ""
+
+#: src/mod_score_player/instrselect.cpp:149
+msgid "Shanai"
+msgstr ""
+
+#: src/mod_score_player/instrselect.cpp:150
+msgid "Tinkle Bell"
+msgstr ""
+
+#: src/mod_score_player/instrselect.cpp:151
+msgid "Agogo"
+msgstr ""
+
+#: src/mod_score_player/instrselect.cpp:152
+msgid "Steel Drums"
+msgstr ""
+
+#: src/mod_score_player/instrselect.cpp:153
+msgid "Woodblock"
+msgstr ""
+
+#: src/mod_score_player/instrselect.cpp:154
+msgid "Taiko Drum"
+msgstr ""
+
+#: src/mod_score_player/instrselect.cpp:155
+msgid "Melodic Tom"
+msgstr ""
+
+#: src/mod_score_player/instrselect.cpp:156
+msgid "Synth Drum"
+msgstr ""
+
+#: src/mod_score_player/instrselect.cpp:157
+msgid "Reverse Cymbal"
+msgstr ""
+
+#: src/mod_score_player/instrselect.cpp:158
+msgid "Guitar Fret Noise"
+msgstr ""
+
+#: src/mod_score_player/instrselect.cpp:159
+msgid "Breath Noise"
+msgstr ""
+
+#: src/mod_score_player/instrselect.cpp:160
+msgid "Seashore"
+msgstr ""
+
+#: src/mod_score_player/instrselect.cpp:161
+msgid "Bird Tweet"
+msgstr ""
+
+#: src/mod_score_player/instrselect.cpp:162
+msgid "Telephone Ring"
+msgstr ""
+
+#: src/mod_score_player/instrselect.cpp:163
+msgid "Helicopter"
+msgstr ""
+
+#: src/mod_score_player/instrselect.cpp:164
+msgid "Applause"
+msgstr ""
+
+#: src/mod_score_player/instrselect.cpp:165
+msgid "Gunshot"
+msgstr ""
+
+#: src/mod_sdl/config_gui.cpp:150
+msgid "Width:"
+msgstr ""
+
+#: src/mod_sdl/config_gui.cpp:157
+msgid "Height:"
+msgstr ""
+
+#: src/mod_sdl/config_gui.cpp:164
+msgid "Full screen:"
+msgstr ""
+
+#: src/mod_sdl/config_gui.cpp:232
+msgid "SDL Configuration error: cannot create sdl_config component"
+msgstr ""
+
+#: src/mod_sdl/config_gui.h:52
+msgid "SDL Configuration"
+msgstr ""
+
+#: src/mod_widgets/choice.h:57
+msgid "Choice"
+msgstr ""
+
+#: src/mod_widgets/filepicker.cpp:322
+msgid "Choose..."
+msgstr ""
+
+#: src/mod_widgets/filepicker.cpp:384
+msgid "Choose a directory"
+msgstr ""
+
+#: src/mod_widgets/filepicker.cpp:390
+msgid "Choose a file to open"
+msgstr ""
+
+#: src/mod_widgets/filepicker.h:60
+msgid "FilePicker"
+msgstr ""
+
+#: src/mod_widgets/slider.h:60
+msgid "Slider"
+msgstr ""
+
+#: src/mod_wiimotes/mod_wiimotes.cpp:1131
+#: src/mod_wiimotes/wwiimotesconfiguration.h:60
+msgid "Wiimotes Configuration"
+msgstr ""
+
+#: src/mod_wiimotes/wwiimotesconfiguration.cpp:144
+msgid "Wiimote device 1"
+msgstr ""
+
+#: src/mod_wiimotes/wwiimotesconfiguration.cpp:152
+msgid "Wiimote device 2"
+msgstr ""
+
+#: src/mod_wiimotes/wwiimotesconfiguration.cpp:162
+msgid "Wiimote device 3"
+msgstr ""
+
+#: src/mod_wiimotes/wwiimotesconfiguration.cpp:172
+msgid "Wiimote device 4"
+msgstr ""
+
+#: src/mod_wiimotes/wwiimotesconfiguration.cpp:183
+msgid "Reconnect"
+msgstr ""
+
+#: src/mod_wiimotes/wwiimotesproperties.cpp:150
+msgid "Connected"
+msgstr ""
+
+#: src/mod_wiimotes/wwiimotesproperties.cpp:156
+msgid "Accelerometers enabled"
+msgstr ""
+
+#: src/mod_wiimotes/wwiimotesproperties.cpp:162
+msgid "Nunchuck enabled"
+msgstr ""
+
+#: src/mod_wiimotes/wwiimotesproperties.cpp:168
+msgid "Motion plus enabled"
+msgstr ""
diff --git a/sp/README.txt b/sp/README.txt
new file mode 100755
index 0000000..3c42f1e
--- /dev/null
+++ b/sp/README.txt
@@ -0,0 +1 @@
+See doc/activities.txt or doc/activities.txt
\ No newline at end of file
diff --git a/sp/examples/arguments/test_arguments.sps b/sp/examples/arguments/test_arguments.sps
new file mode 100755
index 0000000..235ae80
--- /dev/null
+++ b/sp/examples/arguments/test_arguments.sps
@@ -0,0 +1,5 @@
+type test_arguments
+name "test_arguments"
+args -a -b -c
+
+create print print $-a$ $-b$ $-c$
diff --git a/sp/examples/arguments/test_arguments_fail.sp b/sp/examples/arguments/test_arguments_fail.sp
new file mode 100755
index 0000000..0e86861
--- /dev/null
+++ b/sp/examples/arguments/test_arguments_fail.sp
@@ -0,0 +1,4 @@
+type test_print_dump
+name "test_print_dump"
+
+create print print1 -p1 1 -p2 2 -p3 3 -path $SP_DATA_DIR
diff --git a/sp/examples/arguments/test_arguments_fail2.sp b/sp/examples/arguments/test_arguments_fail2.sp
new file mode 100755
index 0000000..f19fdb4
--- /dev/null
+++ b/sp/examples/arguments/test_arguments_fail2.sp
@@ -0,0 +1,4 @@
+type test_print_dump
+name "test_print_dump"
+
+create print print1 -p1 1 -p2 2 -p3 3 -path $
diff --git a/sp/examples/arguments/test_arguments_fail3.sp b/sp/examples/arguments/test_arguments_fail3.sp
new file mode 100755
index 0000000..0fd3068
--- /dev/null
+++ b/sp/examples/arguments/test_arguments_fail3.sp
@@ -0,0 +1,4 @@
+type test_print_dump
+name "test_print_dump"
+
+create print print1 -p1 1 -p2 2 -p3 3 -path $$
diff --git a/sp/examples/arguments/test_arguments_fail_missing.sp b/sp/examples/arguments/test_arguments_fail_missing.sp
new file mode 100755
index 0000000..af5980c
--- /dev/null
+++ b/sp/examples/arguments/test_arguments_fail_missing.sp
@@ -0,0 +1,12 @@
+#
+# Test and sample on how to use arguments
+#
+
+type test_arguments_main
+name "test"
+
+import test_arguments.sps
+
+# Error not enough arguments
+create test_arguments test_arguments -b bb -c cc
+
diff --git a/sp/examples/arguments/test_arguments_fail_repeated.sp b/sp/examples/arguments/test_arguments_fail_repeated.sp
new file mode 100755
index 0000000..f063948
--- /dev/null
+++ b/sp/examples/arguments/test_arguments_fail_repeated.sp
@@ -0,0 +1,5 @@
+type test_print_dump
+name "test_print_dump"
+args -a -b -c -a
+
+create print print
diff --git a/sp/examples/arguments/test_arguments_fail_twice.sp b/sp/examples/arguments/test_arguments_fail_twice.sp
new file mode 100755
index 0000000..3b85b86
--- /dev/null
+++ b/sp/examples/arguments/test_arguments_fail_twice.sp
@@ -0,0 +1,12 @@
+#
+# Test and sample on how to use arguments
+#
+
+type test_arguments_main
+name "test"
+
+import test_arguments.sps
+
+# Error not enough arguments
+create test_arguments test_arguments -a "" -b bb -c cc -a fg
+
diff --git a/sp/examples/arguments/test_arguments_fail_unexpected.sp b/sp/examples/arguments/test_arguments_fail_unexpected.sp
new file mode 100755
index 0000000..8423c99
--- /dev/null
+++ b/sp/examples/arguments/test_arguments_fail_unexpected.sp
@@ -0,0 +1,7 @@
+type test_arguments_main
+name "test"
+
+import test_arguments.sps
+
+create test_arguments test_arguments opsss -a aa -b bb -c cc 
+
diff --git a/sp/examples/arguments/test_arguments_i18n.sp b/sp/examples/arguments/test_arguments_i18n.sp
new file mode 100755
index 0000000..10201a4
--- /dev/null
+++ b/sp/examples/arguments/test_arguments_i18n.sp
@@ -0,0 +1,15 @@
+#
+# Test and sample on how to use arguments
+#
+
+type test_arguments_new
+name 'test_arguments_new'
+
+import test_arguments.sps
+
+create test_arguments test1 -a \'_"Hello world!"\' -b bb -c cc
+
+# TODO: currently does not work. Not handled properly
+#create test_arguments test2 -a \'_"Hello \"\"world\"!"\' -b bb -c cc
+
+create print print _"Simple message!"
\ No newline at end of file
diff --git a/sp/examples/arguments/test_arguments_main.sp b/sp/examples/arguments/test_arguments_main.sp
new file mode 100755
index 0000000..39ba527
--- /dev/null
+++ b/sp/examples/arguments/test_arguments_main.sp
@@ -0,0 +1,43 @@
+#
+# Test and sample on how to use arguments
+#
+
+type test_arguments_main
+name "test_arguments_main"
+
+import test_arguments.sps
+
+#
+# Simple argument passing
+#
+create test_arguments test_arguments1 -a aa -b bb -c cc
+
+#
+# Void argument value. Will expand into nothing
+#
+create test_arguments test_arguments2 -a -b bb -c cc
+
+#
+# Substitution of the same variable twice
+#
+create test_arguments test_arguments3 -a $SP_DATA_DIR$#$SP_DATA_DIR$ -b bb -c cc
+
+#
+# -a argument will expand into two new tokens "-sub" and "aa", note the
+# leading whitespace after "
+#
+create test_arguments test_arguments4 -a " -sub aa" -b bb -c cc
+
+#
+# The same as above but passing a list of arguments
+#
+create test_arguments test_arguments6 -a " -sub a a" -b bb -c cc
+
+#
+# The same as above but passing a list of arguments packed
+#
+create test_arguments test_arguments7 -a " -sub \"a a\"" -b bb -c cc
+
+
+#create test_arguments test_arguments4 -b bb -c cc
+
diff --git a/sp/examples/basic_components/test_storage.sp b/sp/examples/basic_components/test_storage.sp
new file mode 100644
index 0000000..eb5d106
--- /dev/null
+++ b/sp/examples/basic_components/test_storage.sp
@@ -0,0 +1,75 @@
+type test_storage
+name "test_storage"
+
+# int storage
+create int int_storage -v 10
+create widget_slider int_sld --min -100 --max 100 -v 0 -l "Set int value" -i
+connect int_sld value int_storage store
+create widget_button int_btn -l "Send int"
+connect int_btn pressed int_storage retrieve
+create print int_print "int print:"
+connect int_storage out int_print in
+
+# float
+create float float_storage -v 10.25
+create widget_slider float_sld --min 0 --max 100 -v 0 --log -l "Set float value"
+connect float_sld value float_storage store
+create widget_button float_btn -l "Send float"
+connect float_btn pressed float_storage retrieve
+create print float_print "float print:"
+connect float_storage out float_print in
+
+# bool
+create bool bool_storage
+create bool bool_storage_true -v true
+create bool bool_storage_false -v false
+
+create widget_button bool_set_true_btn -l "Set true"
+create widget_button bool_set_false_btn -l "Set false"
+
+connect bool_storage_true out bool_storage store
+connect bool_storage_false out bool_storage store
+connect bool_set_true_btn pressed bool_storage_true retrieve
+connect bool_set_false_btn pressed bool_storage_false retrieve
+
+create widget_button bool_retrieve_btn -l "Retrieve bool"
+connect bool_retrieve_btn pressed bool_storage retrieve
+create print bool_print "bool print:"
+connect bool_storage out bool_print in
+
+# string
+create string string_storage
+create string string_storage_one -v "One"
+create string string_storage_two -v "Two"
+
+create widget_button string_set_one_btn -l "Set One"
+create widget_button string_set_two_btn -l "Set Two"
+
+connect string_storage_one out string_storage store
+connect string_storage_two out string_storage store
+connect string_set_one_btn pressed string_storage_one retrieve
+connect string_set_two_btn pressed string_storage_two retrieve
+
+create widget_button string_retrieve_btn -l "Retrieve string"
+connect string_retrieve_btn pressed string_storage retrieve
+create print string_print "string print:"
+connect string_storage out string_print in
+
+
+begin_gui_layout
+	layout_begin vbox
+		component int_sld
+		component int_btn
+		component float_sld
+		component float_btn
+		
+		component bool_set_true_btn
+		component bool_set_false_btn
+		component bool_retrieve_btn
+		
+		component string_set_one_btn
+		component string_set_two_btn
+		component string_retrieve_btn
+	layout_end
+end_gui_layout
+
diff --git a/sp/examples/camera_sdl/test_ipl2sdl.sp b/sp/examples/camera_sdl/test_ipl2sdl.sp
new file mode 100644
index 0000000..a0fe3fb
--- /dev/null
+++ b/sp/examples/camera_sdl/test_ipl2sdl.sp
@@ -0,0 +1,30 @@
+
+type test_ipl2sdl
+name "IPL two SDL"
+
+# Camera source. 
+create camera_grabber grabber
+
+# Send to main
+create send_main_async to_main
+connect grabber image to_main in
+
+# Camera panel 
+create camera_viewer viewer
+connect to_main out viewer image
+
+# SDL drawer
+create sdl_drawer sdl_drawer
+
+# IPL2SDL
+create ipl2sdl ipl2sdl
+connect to_main out ipl2sdl in
+
+connect ipl2sdl out sdl_drawer queue
+connect ipl2sdl out sdl_drawer draw
+
+begin_gui_layout
+	layout_begin hbox
+		component viewer
+	layout_end
+end_gui_layout
diff --git a/sp/examples/camera_sdl/test_ipl2sdl2.sp b/sp/examples/camera_sdl/test_ipl2sdl2.sp
new file mode 100644
index 0000000..5ffc5b7
--- /dev/null
+++ b/sp/examples/camera_sdl/test_ipl2sdl2.sp
@@ -0,0 +1,27 @@
+
+type test_ipl2sdl2
+name "IPL two SDL"
+
+# Camera source. 
+create camera_grabber grabber
+
+import ../../lib/ipl2sdl.sps
+create ipl2sdl_chk ipl2sdl_chk
+
+# Camera panel 
+create camera_viewer viewer
+connect grabber image viewer image
+
+connect grabber image ipl2sdl_chk image
+
+# SDL drawer
+create sdl_drawer sdl_drawer
+connect ipl2sdl_chk surface sdl_drawer queue
+connect ipl2sdl_chk surface sdl_drawer draw
+
+begin_gui_layout
+	layout_begin vbox
+		component viewer
+		component ipl2sdl_chk
+	layout_end
+end_gui_layout
diff --git a/sp/examples/conditionals/test_conditionals1.sp b/sp/examples/conditionals/test_conditionals1.sp
new file mode 100644
index 0000000..1b35b85
--- /dev/null
+++ b/sp/examples/conditionals/test_conditionals1.sp
@@ -0,0 +1,27 @@
+type test_conditionals1
+name "test_contitionals1"
+
+if "test" == "test"
+	# should work fine
+	create widget_slider int_sld --min -100 --max 100 -v 0 -l "Set int value" -i
+	if "test" != "test"
+		if "test" == "test"
+			error
+		endif
+		error
+	else
+		create widget_slider int_sld2 --min -100 --max 100 -v 0 -l "THIS SHOULD NOT APPEAR" -i
+	endif
+endif
+
+begin_gui_layout
+	layout_begin vbox
+		if "test" == "test"
+			component int_sld
+		endif
+
+		if "test" != "test"
+			component int_sld2
+		endif
+	layout_end
+end_gui_layout
\ No newline at end of file
diff --git a/sp/examples/conditionals/test_conditionals2.sp b/sp/examples/conditionals/test_conditionals2.sp
new file mode 100644
index 0000000..01719d0
--- /dev/null
+++ b/sp/examples/conditionals/test_conditionals2.sp
@@ -0,0 +1,10 @@
+type test_conditionals2
+name "test_contitionals2"
+
+if "test" == "test"
+	if "test" != "test"
+		if "test" == "test"
+		endif
+	else
+#	endif
+#endif
diff --git a/sp/examples/conditionals/test_conditionals3.sp b/sp/examples/conditionals/test_conditionals3.sp
new file mode 100644
index 0000000..627fbf3
--- /dev/null
+++ b/sp/examples/conditionals/test_conditionals3.sp
@@ -0,0 +1,10 @@
+type test_conditionals2
+name "test_contitionals2"
+
+#if "test" == "test"
+	if "test" != "test"
+		if "test" == "test"
+		endif
+	else
+	endif
+endif
diff --git a/sp/examples/conditionals/test_conditionals4.sp b/sp/examples/conditionals/test_conditionals4.sp
new file mode 100644
index 0000000..d36911b
--- /dev/null
+++ b/sp/examples/conditionals/test_conditionals4.sp
@@ -0,0 +1,6 @@
+type test_conditionals2
+name "test_contitionals2"
+
+#if "test" == "test"
+else
+endif
diff --git a/sp/examples/conditionals/test_conditionals5.sp b/sp/examples/conditionals/test_conditionals5.sp
new file mode 100644
index 0000000..2bf20ff
--- /dev/null
+++ b/sp/examples/conditionals/test_conditionals5.sp
@@ -0,0 +1,9 @@
+type test_conditionals5
+name "test_conditionals5"
+
+import test_conditionals5.sps
+
+#
+# Simple argument passing
+#
+create test_conditionals5s test_conditionals5s_1 -a "test" -b "test" -c "no_test" -d "fail"
diff --git a/sp/examples/conditionals/test_conditionals5.sps b/sp/examples/conditionals/test_conditionals5.sps
new file mode 100644
index 0000000..cb35444
--- /dev/null
+++ b/sp/examples/conditionals/test_conditionals5.sps
@@ -0,0 +1,17 @@
+type test_conditionals5s
+name "test_conditionals5s"
+args -a -b -c -d
+
+create print print $-a$ $-b$ $-c$ $-d$
+
+if $-a$ == $-b$
+	create print print2 "OK 1"
+else
+	create print print2 "KO 1"
+endif
+
+if $-c$ == $-d$
+	create print print3 "KO 2"
+else
+	create print print3 "OK 2"
+endif
diff --git a/sp/examples/io/test_filebrowser.sp b/sp/examples/io/test_filebrowser.sp
new file mode 100755
index 0000000..ffbcbed
--- /dev/null
+++ b/sp/examples/io/test_filebrowser.sp
@@ -0,0 +1,40 @@
+type test_filebrowser
+name "test_filebrowser"
+
+create file_browser dirs -p $SP_DATA_DIR$ -t d
+create widget_choice slddirs_full -l "Full path"
+create widget_choice slddirs_names -l "File names"
+connect dirs paths slddirs_full options
+connect dirs files slddirs_names options
+
+create file_browser files -p $SP_DATA_DIR$ -t a
+create widget_choice sldfiles_full -l "Full path"
+create widget_choice sldfiles_names -l "File names"
+connect files paths sldfiles_full options
+connect files files sldfiles_names options
+
+create widget_filepicker pick -t d -l "Pick a directory" -v $SP_DATA_DIR$
+connect pick value dirs path
+connect pick value files path
+
+create widget_checkbox chk -l "Press to refresh"
+connect chk value dirs refresh
+connect chk value files refresh
+
+begin_gui_layout
+	layout_begin vbox
+		component pick
+		component chk
+		layout_begin hbox
+			layout_begin vbox "Directories"
+				component slddirs_full
+				component slddirs_names
+			layout_end
+			layout_begin vbox "Files"
+				component sldfiles_full
+				component sldfiles_names
+			layout_end
+		layout_end
+	layout_end
+end_gui_layout
+
diff --git a/sp/examples/io/test_textfiledump.sp b/sp/examples/io/test_textfiledump.sp
new file mode 100755
index 0000000..3b96baf
--- /dev/null
+++ b/sp/examples/io/test_textfiledump.sp
@@ -0,0 +1,15 @@
+type test_textfile_dump
+name "textfile_dump"
+
+create textfile_dump fd
+create widget_filepicker pick -l "Pick a file" 
+connect pick value fd path
+create print print
+connect fd contents print in
+
+begin_gui_layout
+	layout_begin vbox
+		component pick		
+	layout_end
+end_gui_layout
+
diff --git a/sp/examples/layout/test_layouts.sp b/sp/examples/layout/test_layouts.sp
new file mode 100755
index 0000000..35de243
--- /dev/null
+++ b/sp/examples/layout/test_layouts.sp
@@ -0,0 +1,42 @@
+type test_layout
+name "test_layout"
+
+create widget_checkbox chk1 -l "Boolean option" -v true
+create widget_checkbox chk2 -l "Another checkbox" -v true
+
+create widget_filepicker pick1 -l "Pick file" 
+
+create widget_slider sld1 -l "Adjustment 1"
+create widget_slider sld2 -l "Adjustment 2"
+create widget_slider sld3 -l "Adjustment 3"
+create widget_slider sld4 -l "Adjustment 4"
+
+create camera_viewer cam1
+
+
+begin_gui_layout
+	layout_begin hbox "All options"
+		# Left panel
+		layout_begin vbox "Left panel"
+			component cam1
+			component sld1
+			layout_begin collapsible "Superadvanced"
+				component chk1
+				component sld2
+			layout_end			
+		layout_end
+		# Right panel
+		layout_begin vbox "Right panel"
+			layout_begin book
+				layout_begin book_page "Page 1"
+					component sld3
+					component pick1
+				layout_end
+				layout_begin book_page "Page 2"
+					component sld4
+					component chk2
+				layout_end
+			layout_end
+		layout_end
+	layout_end
+end_gui_layout
\ No newline at end of file
diff --git a/sp/examples/print_dump/test_print_dump.sp b/sp/examples/print_dump/test_print_dump.sp
new file mode 100755
index 0000000..9fd2e7e
--- /dev/null
+++ b/sp/examples/print_dump/test_print_dump.sp
@@ -0,0 +1,4 @@
+type test_print_dump
+name "test_print_dump"
+
+create print print1 -p1 1 -p2 2 -p3 3 -path $SP_DATA_DIR$
diff --git a/sp/examples/widgets/test_choice.sp b/sp/examples/widgets/test_choice.sp
new file mode 100755
index 0000000..44aefdf
--- /dev/null
+++ b/sp/examples/widgets/test_choice.sp
@@ -0,0 +1,33 @@
+type testchoice
+name "Test choice"
+
+create widget_choice cho1 -l "Label 1" -o "First option|Second option|Third\"|\" option" 
+create print print
+connect cho1 selection print in
+connect cho1 selection_string print in
+
+create widget_choice cho2 -o "1st option|2nd option|3rd option" 
+create print print2
+connect cho2 selection print2 in
+connect cho2 selection_string print2 in
+
+connect cho1 selection cho2 selection
+connect cho2 selection cho1 selection
+
+create widget_choice cho3 -l "Label 3" -o "1st option|2nd option|3rd option" -v 2
+create print print3
+connect cho3 selection print3 in
+connect cho3 selection_string print3 in
+
+
+create widget_choice cho4 -l "Void"
+
+begin_gui_layout
+	layout_begin vbox
+		component cho1
+		component cho2
+		component cho3
+		component cho4
+	layout_end
+end_gui_layout
+
diff --git a/sp/examples/widgets/test_collapsible.sp b/sp/examples/widgets/test_collapsible.sp
new file mode 100755
index 0000000..8874037
--- /dev/null
+++ b/sp/examples/widgets/test_collapsible.sp
@@ -0,0 +1,22 @@
+type testcollapsible
+name "Test collapsible component"
+
+create widget_collapsible coll -l "The label"
+create widget_checkbox chk -l "Panel expanded"
+
+connect coll expanded chk value
+
+# Create more stuff just to fill the dialogue
+create widget_slider sld1 -l "Slider 1"
+create widget_slider sld2 -l "Slider 2"
+
+begin_gui_layout
+	layout_begin vbox
+		component chk
+		layout_begin component coll
+			component sld1
+			component sld2
+		layout_end
+	layout_end
+end_gui_layout
+
diff --git a/sp/examples/widgets/test_slider.sp b/sp/examples/widgets/test_slider.sp
new file mode 100755
index 0000000..ccb1b22
--- /dev/null
+++ b/sp/examples/widgets/test_slider.sp
@@ -0,0 +1,60 @@
+#
+# SITPLUS script syntax
+#
+# Line comments start with '#'. Blank lines are also ignored.
+#
+# Commands
+# 	type <id>
+#		Sets the type of the component, actually only meaningful when
+#		when defining subcomponents (see below)
+#
+#	name <name>
+#		Name given to the component. Must appear at the very beggining
+#		of the scripts, otherwise parsing will fail. 
+#		It is usually used as a title for GUI elements.	Not needed for 
+#		subcomponents.
+#
+#	create <component type> <name> [args]
+#		Creates a new component of a given type with the given name.
+#		The type can refer a core registered type or a subcomponent.
+#		The name must be unique among the same scope. 
+#		args are optional and component dependent (currently subcomponents
+#		do not support args)
+#
+#	connect <src component> <src_pin> <dst component> <dst_pin>
+#       Tries to connect src_pin of src component to dst_pin of dst component.
+#
+#	export_ipin <component> <pin name> [<new name> [<new type>]]
+#	export_opin <component> <pin name> [<new name> [<new type>]]
+#		Registers the input/output pin of a certain component as if where part of
+#		this component and optionally rename it. NOTE: renaming the pin 
+#		actually means that	the pin name also changes for the original component.
+#		If parameter new type is passed tries to change the type of the pin. 
+#		The new type must be only of the types registered in the core.
+#		Note that changing the type is only possible for type "any" pins.
+#	
+#	As a rule of thumb always put the exportation statatement at the end
+#	of the script or the subcomponent	
+#
+# Defining subcomponents
+#	
+#	Subcomponents allow to define new types of components which are 
+#	composed of other components. Use
+#		
+#		subcomponent
+#
+#	keyword to begin a subcomponent definition and end it with
+#
+#		subcomponent_end
+#
+
+type testslider
+name "Test slider"
+
+
+create widget_slider s1 --min -100 --max 100 -v 3 -l "This is the label"
+create widget_slider s2 --min -100 --max 100
+
+connect s1 value s2 value
+connect s2 value s1 value
+
diff --git a/sp/examples/widgets/test_slider_log.sp b/sp/examples/widgets/test_slider_log.sp
new file mode 100755
index 0000000..df6585f
--- /dev/null
+++ b/sp/examples/widgets/test_slider_log.sp
@@ -0,0 +1,10 @@
+type testslider2
+name "Test slider2"
+
+
+create widget_slider s1 --min -0 --max 1000 -v 10 -l "This is the label" --log 2
+create widget_slider s2 --min -0 --max 1000
+
+connect s1 value s2 value
+connect s2 value s1 value
+
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
new file mode 100755
index 0000000..4531300
--- /dev/null
+++ b/src/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.6)
+add_subdirectory(core)
+add_subdirectory(mod_sdl)
+add_subdirectory(creavision)
+IF(CMAKE_SYSTEM_NAME MATCHES "Linux")
+add_subdirectory(libwebcam)
+ENDIF(CMAKE_SYSTEM_NAME MATCHES "Linux")
+add_subdirectory(mod_camera)
+add_subdirectory(mod_wiimotes)
+add_subdirectory(mod_midi)
+add_subdirectory(widgets_base)
+add_subdirectory(mod_vision)
+add_subdirectory(host)
+add_subdirectory(mod_widgets)
+add_subdirectory(mod_score_player)
+add_subdirectory(mod_io)
+add_subdirectory(mod_hid)
+add_subdirectory(mod_audio)
+add_subdirectory(mod_ipl_sdl)
diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt
new file mode 100644
index 0000000..5b05686
--- /dev/null
+++ b/src/core/CMakeLists.txt
@@ -0,0 +1,109 @@
+cmake_minimum_required(VERSION 2.6)
+project(spcore)
+
+set (SPCORE_MAJOR_VERSION ${LIBSITPLUS_MAJOR_VERSION})
+set (SPCORE_RELEASE_VERSION ${LIBSITPLUS_MINOR_VERSION})
+set (SPCORE_EPOCH_VERSION ${LIBSITPLUS_REVISION_VERSION})
+
+set(spcore_HEADERS
+	${CUSTOM_INCLUDE_PATH}/spcore/baseobj.h
+	${CUSTOM_INCLUDE_PATH}/spcore/component.h
+	${CUSTOM_INCLUDE_PATH}/spcore/iterator.h
+	${CUSTOM_INCLUDE_PATH}/spcore/pinimpl.h
+	${CUSTOM_INCLUDE_PATH}/spcore/basetype.h
+	${CUSTOM_INCLUDE_PATH}/spcore/basetypeimpl.h
+	${CUSTOM_INCLUDE_PATH}/spcore/basictypes.h
+	${CUSTOM_INCLUDE_PATH}/spcore/coreruntime.h
+	${CUSTOM_INCLUDE_PATH}/spcore/pin.h
+	${CUSTOM_INCLUDE_PATH}/spcore/module.h
+	${CUSTOM_INCLUDE_PATH}/spcore/coreversion.h
+	${CUSTOM_INCLUDE_PATH}/spcore/libimpexp.h
+	${CUSTOM_INCLUDE_PATH}/spcore/conversion.h
+	${CUSTOM_INCLUDE_PATH}/spcore/language.h
+	${CUSTOM_INCLUDE_PATH}/spcore/configuration.h
+)
+
+set(spcore_SRCS
+	${spcore_HEADERS}
+	basictypesimpl.cpp
+	coreruntimeimpl.cpp
+	conversion.cpp
+	commoncomponents.h
+	timecomponents.h
+	language.cpp
+	configurationimpl.h
+)
+
+if (WIN32)
+	set(spcore_SRCS ${spcore_SRCS} win32env.cpp)
+endif(WIN32)
+
+include_directories (${POCO_INCLUDE_DIRS})
+
+#
+# This library should always be shared because several
+# plugings might use it.
+#
+
+add_library (spcore SHARED ${spcore_SRCS})
+
+target_link_libraries(spcore ${POCO_LIBRARIES})
+
+# libconfig
+if(WIN32)
+	include_directories("${CMAKE_SOURCE_DIR}/3rdparty/libconfig/")
+	target_link_libraries(spcore libconfig)
+else(WIN32)
+	find_package(LibConfig REQUIRED)
+	target_link_libraries(spcore ${LibConfig_LIBRARIES})
+	include_directories(${LibConfig_INCLUDE_DIR})
+endif(WIN32)
+
+
+target_link_libraries(spcore ${Boost_THREAD_LIBRARY})
+if (ENABLE_NLS)
+	target_link_libraries(spcore ${LIBINTL_LIBRARIES})
+endif(ENABLE_NLS)
+target_link_libraries(spcore ${wxWidgets_LIBRARIES})
+
+add_definitions(-DSPMAKING_DLL_SPCORE)
+set_target_properties(spcore PROPERTIES 
+	VERSION "${SPCORE_MAJOR_VERSION}.${SPCORE_RELEASE_VERSION}.${SPCORE_EPOCH_VERSION}"
+	SOVERSION ${SPCORE_MAJOR_VERSION}
+	)
+	
+install (FILES ${spcore_HEADERS} DESTINATION ${INCLUDEDIR}/${PROJECT_NAME})
+INSTALL (TARGETS spcore RUNTIME DESTINATION ${LIBRUNTIMEDIR} LIBRARY DESTINATION ${LIBDIR} ARCHIVE DESTINATION ${LIBDIR})
+
+IF(BUILD_TESTS)
+	ADD_SUBDIRECTORY(tests)
+ENDIF(BUILD_TESTS)
+
+#####################################################################
+# Doxygen
+#####################################################################
+IF(GENERATE_DOXYGEN)
+	#get_property(inc_dirs DIRECTORY PROPERTY INCLUDE_DIRECTORIES)
+	#message("inc_dirs = ${inc_dirs}")
+
+	# check if doxygen is even installed
+	find_package(Doxygen)
+	if (DOXYGEN_FOUND STREQUAL "NO")
+		message(SEND_ERROR "Doxygen not found. Please get a copy http://www.doxygen.org")
+	endif (DOXYGEN_FOUND STREQUAL "NO")
+
+	# prepare doxygen configuration file
+	configure_file(Doxyfile.in Doxyfile)
+
+	# add doxygen as target
+	add_custom_target(doxygen-spcore ${DOXYGEN_EXECUTABLE} ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile)
+
+	# cleanup $build/api-doc on "make clean"
+	set_property(DIRECTORY APPEND PROPERTY ADDITIONAL_MAKE_CLEAN_FILES api-doc)
+
+	# add doxygen as dependency to doc-target
+	get_target_property(DOC_TARGET doc TYPE)
+	if(NOT DOC_TARGET)
+		add_custom_target(doc)
+	endif()
+ENDIF(GENERATE_DOXYGEN)
diff --git a/src/core/Doxyfile.in b/src/core/Doxyfile.in
new file mode 100644
index 0000000..14981be
--- /dev/null
+++ b/src/core/Doxyfile.in
@@ -0,0 +1,1419 @@
+# Doxyfile 1.5.6
+
+# This file describes the settings to be used by the documentation system
+# doxygen (www.doxygen.org) for a project
+#
+# All text after a hash (#) is considered a comment and will be ignored
+# The format is:
+#       TAG = value [value, ...]
+# For lists items can also be appended using:
+#       TAG += value [value, ...]
+# Values that contain spaces should be placed between quotes (" ")
+
+#---------------------------------------------------------------------------
+# Project related configuration options
+#---------------------------------------------------------------------------
+
+# This tag specifies the encoding used for all characters in the config file 
+# that follow. The default is UTF-8 which is also the encoding used for all 
+# text before the first occurrence of this tag. Doxygen uses libiconv (or the 
+# iconv built into libc) for the transcoding. See 
+# http://www.gnu.org/software/libiconv for the list of possible encodings.
+
+DOXYFILE_ENCODING      = UTF-8
+
+# The PROJECT_NAME tag is a single word (or a sequence of words surrounded 
+# by quotes) that should identify the project.
+
+PROJECT_NAME           = ${CPACK_PACKAGE_NAME}
+
+# The PROJECT_NUMBER tag can be used to enter a project or revision number. 
+# This could be handy for archiving the generated documentation or 
+# if some version control system is used.
+
+PROJECT_NUMBER         = ${VERSION}
+
+# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) 
+# base path where the generated documentation will be put. 
+# If a relative path is entered, it will be relative to the location 
+# where doxygen was started. If left blank the current directory will be used.
+
+OUTPUT_DIRECTORY       = api-doc
+
+# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create 
+# 4096 sub-directories (in 2 levels) under the output directory of each output 
+# format and will distribute the generated files over these directories. 
+# Enabling this option can be useful when feeding doxygen a huge amount of 
+# source files, where putting all generated files in the same directory would 
+# otherwise cause performance problems for the file system.
+
+CREATE_SUBDIRS         = NO
+
+# The OUTPUT_LANGUAGE tag is used to specify the language in which all 
+# documentation generated by doxygen is written. Doxygen will use this 
+# information to generate all constant output in the proper language. 
+# The default language is English, other supported languages are: 
+# Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional, 
+# Croatian, Czech, Danish, Dutch, Farsi, Finnish, French, German, Greek, 
+# Hungarian, Italian, Japanese, Japanese-en (Japanese with English messages), 
+# Korean, Korean-en, Lithuanian, Norwegian, Macedonian, Persian, Polish, 
+# Portuguese, Romanian, Russian, Serbian, Slovak, Slovene, Spanish, Swedish, 
+# and Ukrainian.
+
+OUTPUT_LANGUAGE        = English
+
+# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will 
+# include brief member descriptions after the members that are listed in 
+# the file and class documentation (similar to JavaDoc). 
+# Set to NO to disable this.
+
+BRIEF_MEMBER_DESC      = YES
+
+# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend 
+# the brief description of a member or function before the detailed description. 
+# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the 
+# brief descriptions will be completely suppressed.
+
+REPEAT_BRIEF           = YES
+
+# This tag implements a quasi-intelligent brief description abbreviator 
+# that is used to form the text in various listings. Each string 
+# in this list, if found as the leading text of the brief description, will be 
+# stripped from the text and the result after processing the whole list, is 
+# used as the annotated text. Otherwise, the brief description is used as-is. 
+# If left blank, the following values are used ("$name" is automatically 
+# replaced with the name of the entity): "The $name class" "The $name widget" 
+# "The $name file" "is" "provides" "specifies" "contains" 
+# "represents" "a" "an" "the"
+
+ABBREVIATE_BRIEF       = 
+
+# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then 
+# Doxygen will generate a detailed section even if there is only a brief 
+# description.
+
+ALWAYS_DETAILED_SEC    = NO
+
+# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all 
+# inherited members of a class in the documentation of that class as if those 
+# members were ordinary class members. Constructors, destructors and assignment 
+# operators of the base classes will not be shown.
+
+INLINE_INHERITED_MEMB  = NO
+
+# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full 
+# path before files name in the file list and in the header files. If set 
+# to NO the shortest path that makes the file name unique will be used.
+
+FULL_PATH_NAMES        = YES
+
+# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag 
+# can be used to strip a user-defined part of the path. Stripping is 
+# only done if one of the specified strings matches the left-hand part of 
+# the path. The tag can be used to show relative paths in the file list. 
+# If left blank the directory from which doxygen is run is used as the 
+# path to strip.
+
+STRIP_FROM_PATH        = ${CUSTOM_INCLUDE_PATH}
+
+# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of 
+# the path mentioned in the documentation of a class, which tells 
+# the reader which header file to include in order to use a class. 
+# If left blank only the name of the header file containing the class 
+# definition is used. Otherwise one should specify the include paths that 
+# are normally passed to the compiler using the -I flag.
+
+STRIP_FROM_INC_PATH    = 
+
+# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter 
+# (but less readable) file names. This can be useful is your file systems 
+# doesn't support long names like on DOS, Mac, or CD-ROM.
+
+SHORT_NAMES            = NO
+
+# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen 
+# will interpret the first line (until the first dot) of a JavaDoc-style 
+# comment as the brief description. If set to NO, the JavaDoc 
+# comments will behave just like regular Qt-style comments 
+# (thus requiring an explicit @brief command for a brief description.)
+
+JAVADOC_AUTOBRIEF      = NO
+
+# If the QT_AUTOBRIEF tag is set to YES then Doxygen will 
+# interpret the first line (until the first dot) of a Qt-style 
+# comment as the brief description. If set to NO, the comments 
+# will behave just like regular Qt-style comments (thus requiring 
+# an explicit \brief command for a brief description.)
+
+QT_AUTOBRIEF           = NO
+
+# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen 
+# treat a multi-line C++ special comment block (i.e. a block of //! or /// 
+# comments) as a brief description. This used to be the default behaviour. 
+# The new default is to treat a multi-line C++ comment block as a detailed 
+# description. Set this tag to YES if you prefer the old behaviour instead.
+
+MULTILINE_CPP_IS_BRIEF = NO
+
+# If the DETAILS_AT_TOP tag is set to YES then Doxygen 
+# will output the detailed description near the top, like JavaDoc.
+# If set to NO, the detailed description appears after the member 
+# documentation.
+
+# DEPRECATED
+#DETAILS_AT_TOP         = NO
+# DEPRECATED
+
+# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented 
+# member inherits the documentation from any documented member that it 
+# re-implements.
+
+INHERIT_DOCS           = YES
+
+# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce 
+# a new page for each member. If set to NO, the documentation of a member will 
+# be part of the file/class/namespace that contains it.
+
+SEPARATE_MEMBER_PAGES  = NO
+
+# The TAB_SIZE tag can be used to set the number of spaces in a tab. 
+# Doxygen uses this value to replace tabs by spaces in code fragments.
+
+TAB_SIZE               = 8
+
+# This tag can be used to specify a number of aliases that acts 
+# as commands in the documentation. An alias has the form "name=value". 
+# For example adding "sideeffect=\par Side Effects:\n" will allow you to 
+# put the command \sideeffect (or @sideeffect) in the documentation, which 
+# will result in a user-defined paragraph with heading "Side Effects:". 
+# You can put \n's in the value part of an alias to insert newlines.
+
+ALIASES                = 
+
+# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C 
+# sources only. Doxygen will then generate output that is more tailored for C. 
+# For instance, some of the names that are used will be different. The list 
+# of all members will be omitted, etc.
+
+OPTIMIZE_OUTPUT_FOR_C  = NO
+
+# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java 
+# sources only. Doxygen will then generate output that is more tailored for 
+# Java. For instance, namespaces will be presented as packages, qualified 
+# scopes will look different, etc.
+
+OPTIMIZE_OUTPUT_JAVA   = NO
+
+# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran 
+# sources only. Doxygen will then generate output that is more tailored for 
+# Fortran.
+
+OPTIMIZE_FOR_FORTRAN   = NO
+
+# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL 
+# sources. Doxygen will then generate output that is tailored for 
+# VHDL.
+
+OPTIMIZE_OUTPUT_VHDL   = NO
+
+# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want 
+# to include (a tag file for) the STL sources as input, then you should 
+# set this tag to YES in order to let doxygen match functions declarations and 
+# definitions whose arguments contain STL classes (e.g. func(std::string); v.s. 
+# func(std::string) {}). This also make the inheritance and collaboration 
+# diagrams that involve STL classes more complete and accurate.
+
+BUILTIN_STL_SUPPORT    = NO
+
+# If you use Microsoft's C++/CLI language, you should set this option to YES to
+# enable parsing support.
+
+CPP_CLI_SUPPORT        = NO
+
+# Set the SIP_SUPPORT tag to YES if your project consists of sip sources only. 
+# Doxygen will parse them like normal C++ but will assume all classes use public 
+# instead of private inheritance when no explicit protection keyword is present.
+
+SIP_SUPPORT            = NO
+
+# For Microsoft's IDL there are propget and propput attributes to indicate getter 
+# and setter methods for a property. Setting this option to YES (the default) 
+# will make doxygen to replace the get and set methods by a property in the 
+# documentation. This will only work if the methods are indeed getting or 
+# setting a simple type. If this is not the case, or you want to show the 
+# methods anyway, you should set this option to NO.
+
+IDL_PROPERTY_SUPPORT   = YES
+
+# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC 
+# tag is set to YES, then doxygen will reuse the documentation of the first 
+# member in the group (if any) for the other members of the group. By default 
+# all members of a group must be documented explicitly.
+
+DISTRIBUTE_GROUP_DOC   = NO
+
+# Set the SUBGROUPING tag to YES (the default) to allow class member groups of 
+# the same type (for instance a group of public functions) to be put as a 
+# subgroup of that type (e.g. under the Public Functions section). Set it to 
+# NO to prevent subgrouping. Alternatively, this can be done per class using 
+# the \nosubgrouping command.
+
+SUBGROUPING            = YES
+
+# When TYPEDEF_HIDES_STRUCT is enabled, a typedef of a struct, union, or enum 
+# is documented as struct, union, or enum with the name of the typedef. So 
+# typedef struct TypeS {} TypeT, will appear in the documentation as a struct 
+# with name TypeT. When disabled the typedef will appear as a member of a file, 
+# namespace, or class. And the struct will be named TypeS. This can typically 
+# be useful for C code in case the coding convention dictates that all compound 
+# types are typedef'ed and only the typedef is referenced, never the tag name.
+
+TYPEDEF_HIDES_STRUCT   = NO
+
+#---------------------------------------------------------------------------
+# Build related configuration options
+#---------------------------------------------------------------------------
+
+# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in 
+# documentation are documented, even if no documentation was available. 
+# Private class members and static file members will be hidden unless 
+# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES
+
+EXTRACT_ALL            = YES
+
+# If the EXTRACT_PRIVATE tag is set to YES all private members of a class 
+# will be included in the documentation.
+
+EXTRACT_PRIVATE        = NO
+
+# If the EXTRACT_STATIC tag is set to YES all static members of a file 
+# will be included in the documentation.
+
+EXTRACT_STATIC         = NO
+
+# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) 
+# defined locally in source files will be included in the documentation. 
+# If set to NO only classes defined in header files are included.
+
+EXTRACT_LOCAL_CLASSES  = NO
+
+# This flag is only useful for Objective-C code. When set to YES local 
+# methods, which are defined in the implementation section but not in 
+# the interface are included in the documentation. 
+# If set to NO (the default) only methods in the interface are included.
+
+EXTRACT_LOCAL_METHODS  = NO
+
+# If this flag is set to YES, the members of anonymous namespaces will be 
+# extracted and appear in the documentation as a namespace called 
+# 'anonymous_namespace{file}', where file will be replaced with the base 
+# name of the file that contains the anonymous namespace. By default 
+# anonymous namespace are hidden.
+
+EXTRACT_ANON_NSPACES   = NO
+
+# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all 
+# undocumented members of documented classes, files or namespaces. 
+# If set to NO (the default) these members will be included in the 
+# various overviews, but no documentation section is generated. 
+# This option has no effect if EXTRACT_ALL is enabled.
+
+HIDE_UNDOC_MEMBERS     = NO
+
+# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all 
+# undocumented classes that are normally visible in the class hierarchy. 
+# If set to NO (the default) these classes will be included in the various 
+# overviews. This option has no effect if EXTRACT_ALL is enabled.
+
+HIDE_UNDOC_CLASSES     = NO
+
+# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all 
+# friend (class|struct|union) declarations. 
+# If set to NO (the default) these declarations will be included in the 
+# documentation.
+
+HIDE_FRIEND_COMPOUNDS  = NO
+
+# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any 
+# documentation blocks found inside the body of a function. 
+# If set to NO (the default) these blocks will be appended to the 
+# function's detailed documentation block.
+
+HIDE_IN_BODY_DOCS      = NO
+
+# The INTERNAL_DOCS tag determines if documentation 
+# that is typed after a \internal command is included. If the tag is set 
+# to NO (the default) then the documentation will be excluded. 
+# Set it to YES to include the internal documentation.
+
+INTERNAL_DOCS          = NO
+
+# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate 
+# file names in lower-case letters. If set to YES upper-case letters are also 
+# allowed. This is useful if you have classes or files whose names only differ 
+# in case and if your file system supports case sensitive file names. Windows 
+# and Mac users are advised to set this option to NO.
+
+CASE_SENSE_NAMES       = YES
+
+# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen 
+# will show members with their full class and namespace scopes in the 
+# documentation. If set to YES the scope will be hidden.
+
+HIDE_SCOPE_NAMES       = NO
+
+# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen 
+# will put a list of the files that are included by a file in the documentation 
+# of that file.
+
+SHOW_INCLUDE_FILES     = YES
+
+# If the INLINE_INFO tag is set to YES (the default) then a tag [inline] 
+# is inserted in the documentation for inline members.
+
+INLINE_INFO            = YES
+
+# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen 
+# will sort the (detailed) documentation of file and class members 
+# alphabetically by member name. If set to NO the members will appear in 
+# declaration order.
+
+SORT_MEMBER_DOCS       = YES
+
+# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the 
+# brief documentation of file, namespace and class members alphabetically 
+# by member name. If set to NO (the default) the members will appear in 
+# declaration order.
+
+SORT_BRIEF_DOCS        = NO
+
+# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the 
+# hierarchy of group names into alphabetical order. If set to NO (the default) 
+# the group names will appear in their defined order.
+
+SORT_GROUP_NAMES       = NO
+
+# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be 
+# sorted by fully-qualified names, including namespaces. If set to 
+# NO (the default), the class list will be sorted only by class name, 
+# not including the namespace part. 
+# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES.
+# Note: This option applies only to the class list, not to the 
+# alphabetical list.
+
+SORT_BY_SCOPE_NAME     = NO
+
+# The GENERATE_TODOLIST tag can be used to enable (YES) or 
+# disable (NO) the todo list. This list is created by putting \todo 
+# commands in the documentation.
+
+GENERATE_TODOLIST      = YES
+
+# The GENERATE_TESTLIST tag can be used to enable (YES) or 
+# disable (NO) the test list. This list is created by putting \test 
+# commands in the documentation.
+
+GENERATE_TESTLIST      = YES
+
+# The GENERATE_BUGLIST tag can be used to enable (YES) or 
+# disable (NO) the bug list. This list is created by putting \bug 
+# commands in the documentation.
+
+GENERATE_BUGLIST       = YES
+
+# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or 
+# disable (NO) the deprecated list. This list is created by putting 
+# \deprecated commands in the documentation.
+
+GENERATE_DEPRECATEDLIST= YES
+
+# The ENABLED_SECTIONS tag can be used to enable conditional 
+# documentation sections, marked by \if sectionname ... \endif.
+
+ENABLED_SECTIONS       = 
+
+# The MAX_INITIALIZER_LINES tag determines the maximum number of lines 
+# the initial value of a variable or define consists of for it to appear in 
+# the documentation. If the initializer consists of more lines than specified 
+# here it will be hidden. Use a value of 0 to hide initializers completely. 
+# The appearance of the initializer of individual variables and defines in the 
+# documentation can be controlled using \showinitializer or \hideinitializer 
+# command in the documentation regardless of this setting.
+
+MAX_INITIALIZER_LINES  = 30
+
+# Set the SHOW_USED_FILES tag to NO to disable the list of files generated 
+# at the bottom of the documentation of classes and structs. If set to YES the 
+# list will mention the files that were used to generate the documentation.
+
+SHOW_USED_FILES        = YES
+
+# If the sources in your project are distributed over multiple directories 
+# then setting the SHOW_DIRECTORIES tag to YES will show the directory hierarchy 
+# in the documentation. The default is NO.
+
+SHOW_DIRECTORIES       = NO
+
+# Set the SHOW_FILES tag to NO to disable the generation of the Files page.
+# This will remove the Files entry from the Quick Index and from the 
+# Folder Tree View (if specified). The default is YES.
+
+SHOW_FILES             = YES
+
+# Set the SHOW_NAMESPACES tag to NO to disable the generation of the 
+# Namespaces page.  This will remove the Namespaces entry from the Quick Index
+# and from the Folder Tree View (if specified). The default is YES.
+
+SHOW_NAMESPACES        = YES
+
+# The FILE_VERSION_FILTER tag can be used to specify a program or script that 
+# doxygen should invoke to get the current version for each file (typically from 
+# the version control system). Doxygen will invoke the program by executing (via 
+# popen()) the command <command> <input-file>, where <command> is the value of 
+# the FILE_VERSION_FILTER tag, and <input-file> is the name of an input file 
+# provided by doxygen. Whatever the program writes to standard output 
+# is used as the file version. See the manual for examples.
+
+FILE_VERSION_FILTER    = 
+
+#---------------------------------------------------------------------------
+# configuration options related to warning and progress messages
+#---------------------------------------------------------------------------
+
+# The QUIET tag can be used to turn on/off the messages that are generated 
+# by doxygen. Possible values are YES and NO. If left blank NO is used.
+
+QUIET                  = NO
+
+# The WARNINGS tag can be used to turn on/off the warning messages that are 
+# generated by doxygen. Possible values are YES and NO. If left blank 
+# NO is used.
+
+WARNINGS               = YES
+
+# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings 
+# for undocumented members. If EXTRACT_ALL is set to YES then this flag will 
+# automatically be disabled.
+
+WARN_IF_UNDOCUMENTED   = YES
+
+# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for 
+# potential errors in the documentation, such as not documenting some 
+# parameters in a documented function, or documenting parameters that 
+# don't exist or using markup commands wrongly.
+
+WARN_IF_DOC_ERROR      = YES
+
+# This WARN_NO_PARAMDOC option can be abled to get warnings for 
+# functions that are documented, but have no documentation for their parameters 
+# or return value. If set to NO (the default) doxygen will only warn about 
+# wrong or incomplete parameter documentation, but not about the absence of 
+# documentation.
+
+WARN_NO_PARAMDOC       = NO
+
+# The WARN_FORMAT tag determines the format of the warning messages that 
+# doxygen can produce. The string should contain the $file, $line, and $text 
+# tags, which will be replaced by the file and line number from which the 
+# warning originated and the warning text. Optionally the format may contain 
+# $version, which will be replaced by the version of the file (if it could 
+# be obtained via FILE_VERSION_FILTER)
+
+WARN_FORMAT            = "$file:$line: $text"
+
+# The WARN_LOGFILE tag can be used to specify a file to which warning 
+# and error messages should be written. If left blank the output is written 
+# to stderr.
+
+WARN_LOGFILE           = 
+
+#---------------------------------------------------------------------------
+# configuration options related to the input files
+#---------------------------------------------------------------------------
+
+# The INPUT tag can be used to specify the files and/or directories that contain 
+# documented source files. You may enter file names like "myfile.cpp" or 
+# directories like "/usr/src/myproject". Separate the files or directories 
+# with spaces.
+
+INPUT                  = ${CUSTOM_INCLUDE_PATH}/spcore
+
+# This tag can be used to specify the character encoding of the source files 
+# that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is 
+# also the default input encoding. Doxygen uses libiconv (or the iconv built 
+# into libc) for the transcoding. See http://www.gnu.org/software/libiconv for 
+# the list of possible encodings.
+
+INPUT_ENCODING         = UTF-8
+
+# If the value of the INPUT tag contains directories, you can use the 
+# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp 
+# and *.h) to filter out the source-files in the directories. If left 
+# blank the following patterns are tested: 
+# *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx 
+# *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.py *.f90
+
+FILE_PATTERNS          = 
+
+# The RECURSIVE tag can be used to turn specify whether or not subdirectories 
+# should be searched for input files as well. Possible values are YES and NO. 
+# If left blank NO is used.
+
+RECURSIVE              = NO
+
+# The EXCLUDE tag can be used to specify files and/or directories that should 
+# excluded from the INPUT source files. This way you can easily exclude a 
+# subdirectory from a directory tree whose root is specified with the INPUT tag.
+
+EXCLUDE                = 
+
+# The EXCLUDE_SYMLINKS tag can be used select whether or not files or 
+# directories that are symbolic links (a Unix filesystem feature) are excluded 
+# from the input.
+
+EXCLUDE_SYMLINKS       = NO
+
+# If the value of the INPUT tag contains directories, you can use the 
+# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude 
+# certain files from those directories. Note that the wildcards are matched 
+# against the file with absolute path, so to exclude all test directories 
+# for example use the pattern */test/*
+
+EXCLUDE_PATTERNS       = 
+
+# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names 
+# (namespaces, classes, functions, etc.) that should be excluded from the 
+# output. The symbol name can be a fully qualified name, a word, or if the 
+# wildcard * is used, a substring. Examples: ANamespace, AClass, 
+# AClass::ANamespace, ANamespace::*Test
+
+EXCLUDE_SYMBOLS        = 
+
+# The EXAMPLE_PATH tag can be used to specify one or more files or 
+# directories that contain example code fragments that are included (see 
+# the \include command).
+
+EXAMPLE_PATH           = 
+
+# If the value of the EXAMPLE_PATH tag contains directories, you can use the 
+# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp 
+# and *.h) to filter out the source-files in the directories. If left 
+# blank all files are included.
+
+EXAMPLE_PATTERNS       = 
+
+# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be 
+# searched for input files to be used with the \include or \dontinclude 
+# commands irrespective of the value of the RECURSIVE tag. 
+# Possible values are YES and NO. If left blank NO is used.
+
+EXAMPLE_RECURSIVE      = NO
+
+# The IMAGE_PATH tag can be used to specify one or more files or 
+# directories that contain image that are included in the documentation (see 
+# the \image command).
+
+IMAGE_PATH             = 
+
+# The INPUT_FILTER tag can be used to specify a program that doxygen should 
+# invoke to filter for each input file. Doxygen will invoke the filter program 
+# by executing (via popen()) the command <filter> <input-file>, where <filter> 
+# is the value of the INPUT_FILTER tag, and <input-file> is the name of an 
+# input file. Doxygen will then use the output that the filter program writes 
+# to standard output.  If FILTER_PATTERNS is specified, this tag will be 
+# ignored.
+
+INPUT_FILTER           = 
+
+# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern 
+# basis.  Doxygen will compare the file name with each pattern and apply the 
+# filter if there is a match.  The filters are a list of the form: 
+# pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further 
+# info on how filters are used. If FILTER_PATTERNS is empty, INPUT_FILTER 
+# is applied to all files.
+
+FILTER_PATTERNS        = 
+
+# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using 
+# INPUT_FILTER) will be used to filter the input files when producing source 
+# files to browse (i.e. when SOURCE_BROWSER is set to YES).
+
+FILTER_SOURCE_FILES    = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to source browsing
+#---------------------------------------------------------------------------
+
+# If the SOURCE_BROWSER tag is set to YES then a list of source files will 
+# be generated. Documented entities will be cross-referenced with these sources. 
+# Note: To get rid of all source code in the generated output, make sure also 
+# VERBATIM_HEADERS is set to NO.
+
+SOURCE_BROWSER         = NO
+
+# Setting the INLINE_SOURCES tag to YES will include the body 
+# of functions and classes directly in the documentation.
+
+INLINE_SOURCES         = NO
+
+# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct 
+# doxygen to hide any special comment blocks from generated source code 
+# fragments. Normal C and C++ comments will always remain visible.
+
+STRIP_CODE_COMMENTS    = YES
+
+# If the REFERENCED_BY_RELATION tag is set to YES 
+# then for each documented function all documented 
+# functions referencing it will be listed.
+
+REFERENCED_BY_RELATION = NO
+
+# If the REFERENCES_RELATION tag is set to YES 
+# then for each documented function all documented entities 
+# called/used by that function will be listed.
+
+REFERENCES_RELATION    = NO
+
+# If the REFERENCES_LINK_SOURCE tag is set to YES (the default)
+# and SOURCE_BROWSER tag is set to YES, then the hyperlinks from
+# functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will
+# link to the source code.  Otherwise they will link to the documentstion.
+
+REFERENCES_LINK_SOURCE = YES
+
+# If the USE_HTAGS tag is set to YES then the references to source code 
+# will point to the HTML generated by the htags(1) tool instead of doxygen 
+# built-in source browser. The htags tool is part of GNU's global source 
+# tagging system (see http://www.gnu.org/software/global/global.html). You 
+# will need version 4.8.6 or higher.
+
+USE_HTAGS              = NO
+
+# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen 
+# will generate a verbatim copy of the header file for each class for 
+# which an include is specified. Set to NO to disable this.
+
+VERBATIM_HEADERS       = YES
+
+#---------------------------------------------------------------------------
+# configuration options related to the alphabetical class index
+#---------------------------------------------------------------------------
+
+# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index 
+# of all compounds will be generated. Enable this if the project 
+# contains a lot of classes, structs, unions or interfaces.
+
+ALPHABETICAL_INDEX     = NO
+
+# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then 
+# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns 
+# in which this list will be split (can be a number in the range [1..20])
+
+COLS_IN_ALPHA_INDEX    = 5
+
+# In case all classes in a project start with a common prefix, all 
+# classes will be put under the same header in the alphabetical index. 
+# The IGNORE_PREFIX tag can be used to specify one or more prefixes that 
+# should be ignored while generating the index headers.
+
+IGNORE_PREFIX          = 
+
+#---------------------------------------------------------------------------
+# configuration options related to the HTML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_HTML tag is set to YES (the default) Doxygen will 
+# generate HTML output.
+
+GENERATE_HTML          = YES
+
+# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. 
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be 
+# put in front of it. If left blank `html' will be used as the default path.
+
+HTML_OUTPUT            = html
+
+# The HTML_FILE_EXTENSION tag can be used to specify the file extension for 
+# each generated HTML page (for example: .htm,.php,.asp). If it is left blank 
+# doxygen will generate files with .html extension.
+
+HTML_FILE_EXTENSION    = .html
+
+# The HTML_HEADER tag can be used to specify a personal HTML header for 
+# each generated HTML page. If it is left blank doxygen will generate a 
+# standard header.
+
+HTML_HEADER            = 
+
+# The HTML_FOOTER tag can be used to specify a personal HTML footer for 
+# each generated HTML page. If it is left blank doxygen will generate a 
+# standard footer.
+
+HTML_FOOTER            = 
+
+# The HTML_STYLESHEET tag can be used to specify a user-defined cascading 
+# style sheet that is used by each HTML page. It can be used to 
+# fine-tune the look of the HTML output. If the tag is left blank doxygen 
+# will generate a default style sheet. Note that doxygen will try to copy 
+# the style sheet file to the HTML output directory, so don't put your own 
+# stylesheet in the HTML output directory as well, or it will be erased!
+
+HTML_STYLESHEET        = 
+
+# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes, 
+# files or namespaces will be aligned in HTML using tables. If set to 
+# NO a bullet list will be used.
+
+HTML_ALIGN_MEMBERS     = YES
+
+# If the GENERATE_HTMLHELP tag is set to YES, additional index files 
+# will be generated that can be used as input for tools like the 
+# Microsoft HTML help workshop to generate a compiled HTML help file (.chm) 
+# of the generated HTML documentation.
+
+GENERATE_HTMLHELP      = NO
+
+# If the GENERATE_DOCSET tag is set to YES, additional index files 
+# will be generated that can be used as input for Apple's Xcode 3 
+# integrated development environment, introduced with OSX 10.5 (Leopard). 
+# To create a documentation set, doxygen will generate a Makefile in the 
+# HTML output directory. Running make will produce the docset in that 
+# directory and running "make install" will install the docset in 
+# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find 
+# it at startup.
+
+GENERATE_DOCSET        = NO
+
+# When GENERATE_DOCSET tag is set to YES, this tag determines the name of the 
+# feed. A documentation feed provides an umbrella under which multiple 
+# documentation sets from a single provider (such as a company or product suite) 
+# can be grouped.
+
+DOCSET_FEEDNAME        = "Doxygen generated docs"
+
+# When GENERATE_DOCSET tag is set to YES, this tag specifies a string that 
+# should uniquely identify the documentation set bundle. This should be a 
+# reverse domain-name style string, e.g. com.mycompany.MyDocSet. Doxygen 
+# will append .docset to the name.
+
+DOCSET_BUNDLE_ID       = org.doxygen.Project
+
+# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML 
+# documentation will contain sections that can be hidden and shown after the 
+# page has loaded. For this to work a browser that supports 
+# JavaScript and DHTML is required (for instance Mozilla 1.0+, Firefox 
+# Netscape 6.0+, Internet explorer 5.0+, Konqueror, or Safari).
+
+HTML_DYNAMIC_SECTIONS  = NO
+
+# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can 
+# be used to specify the file name of the resulting .chm file. You 
+# can add a path in front of the file if the result should not be 
+# written to the html output directory.
+
+CHM_FILE               = 
+
+# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can 
+# be used to specify the location (absolute path including file name) of 
+# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run 
+# the HTML help compiler on the generated index.hhp.
+
+HHC_LOCATION           = 
+
+# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag 
+# controls if a separate .chi index file is generated (YES) or that 
+# it should be included in the master .chm file (NO).
+
+GENERATE_CHI           = NO
+
+# If the GENERATE_HTMLHELP tag is set to YES, the CHM_INDEX_ENCODING
+# is used to encode HtmlHelp index (hhk), content (hhc) and project file
+# content.
+
+CHM_INDEX_ENCODING     = 
+
+# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag 
+# controls whether a binary table of contents is generated (YES) or a 
+# normal table of contents (NO) in the .chm file.
+
+BINARY_TOC             = NO
+
+# The TOC_EXPAND flag can be set to YES to add extra items for group members 
+# to the contents of the HTML help documentation and to the tree view.
+
+TOC_EXPAND             = NO
+
+# The DISABLE_INDEX tag can be used to turn on/off the condensed index at 
+# top of each HTML page. The value NO (the default) enables the index and 
+# the value YES disables it.
+
+DISABLE_INDEX          = NO
+
+# This tag can be used to set the number of enum values (range [1..20]) 
+# that doxygen will group on one line in the generated HTML documentation.
+
+ENUM_VALUES_PER_LINE   = 4
+
+# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index
+# structure should be generated to display hierarchical information.
+# If the tag value is set to FRAME, a side panel will be generated
+# containing a tree-like index structure (just like the one that 
+# is generated for HTML Help). For this to work a browser that supports 
+# JavaScript, DHTML, CSS and frames is required (for instance Mozilla 1.0+, 
+# Netscape 6.0+, Internet explorer 5.0+, or Konqueror). Windows users are 
+# probably better off using the HTML help feature. Other possible values 
+# for this tag are: HIERARCHIES, which will generate the Groups, Directories,
+# and Class Hiererachy pages using a tree view instead of an ordered list;
+# ALL, which combines the behavior of FRAME and HIERARCHIES; and NONE, which
+# disables this behavior completely. For backwards compatibility with previous
+# releases of Doxygen, the values YES and NO are equivalent to FRAME and NONE
+# respectively.
+
+GENERATE_TREEVIEW      = NONE
+
+# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be 
+# used to set the initial width (in pixels) of the frame in which the tree 
+# is shown.
+
+TREEVIEW_WIDTH         = 250
+
+# Use this tag to change the font size of Latex formulas included 
+# as images in the HTML documentation. The default is 10. Note that 
+# when you change the font size after a successful doxygen run you need 
+# to manually remove any form_*.png images from the HTML output directory 
+# to force them to be regenerated.
+
+FORMULA_FONTSIZE       = 10
+
+#---------------------------------------------------------------------------
+# configuration options related to the LaTeX output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will 
+# generate Latex output.
+
+GENERATE_LATEX         = YES
+
+# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. 
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be 
+# put in front of it. If left blank `latex' will be used as the default path.
+
+LATEX_OUTPUT           = latex
+
+# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be 
+# invoked. If left blank `latex' will be used as the default command name.
+
+LATEX_CMD_NAME         = latex
+
+# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to 
+# generate index for LaTeX. If left blank `makeindex' will be used as the 
+# default command name.
+
+MAKEINDEX_CMD_NAME     = makeindex
+
+# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact 
+# LaTeX documents. This may be useful for small projects and may help to 
+# save some trees in general.
+
+COMPACT_LATEX          = NO
+
+# The PAPER_TYPE tag can be used to set the paper type that is used 
+# by the printer. Possible values are: a4, a4wide, letter, legal and 
+# executive. If left blank a4wide will be used.
+
+PAPER_TYPE             = a4wide
+
+# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX 
+# packages that should be included in the LaTeX output.
+
+EXTRA_PACKAGES         = 
+
+# The LATEX_HEADER tag can be used to specify a personal LaTeX header for 
+# the generated latex document. The header should contain everything until 
+# the first chapter. If it is left blank doxygen will generate a 
+# standard header. Notice: only use this tag if you know what you are doing!
+
+LATEX_HEADER           = 
+
+# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated 
+# is prepared for conversion to pdf (using ps2pdf). The pdf file will 
+# contain links (just like the HTML output) instead of page references 
+# This makes the output suitable for online browsing using a pdf viewer.
+
+PDF_HYPERLINKS         = YES
+
+# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of 
+# plain latex in the generated Makefile. Set this option to YES to get a 
+# higher quality PDF documentation.
+
+USE_PDFLATEX           = YES
+
+# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode. 
+# command to the generated LaTeX files. This will instruct LaTeX to keep 
+# running if errors occur, instead of asking the user for help. 
+# This option is also used when generating formulas in HTML.
+
+LATEX_BATCHMODE        = NO
+
+# If LATEX_HIDE_INDICES is set to YES then doxygen will not 
+# include the index chapters (such as File Index, Compound Index, etc.) 
+# in the output.
+
+LATEX_HIDE_INDICES     = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the RTF output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output 
+# The RTF output is optimized for Word 97 and may not look very pretty with 
+# other RTF readers or editors.
+
+GENERATE_RTF           = NO
+
+# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. 
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be 
+# put in front of it. If left blank `rtf' will be used as the default path.
+
+RTF_OUTPUT             = rtf
+
+# If the COMPACT_RTF tag is set to YES Doxygen generates more compact 
+# RTF documents. This may be useful for small projects and may help to 
+# save some trees in general.
+
+COMPACT_RTF            = NO
+
+# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated 
+# will contain hyperlink fields. The RTF file will 
+# contain links (just like the HTML output) instead of page references. 
+# This makes the output suitable for online browsing using WORD or other 
+# programs which support those fields. 
+# Note: wordpad (write) and others do not support links.
+
+RTF_HYPERLINKS         = NO
+
+# Load stylesheet definitions from file. Syntax is similar to doxygen's 
+# config file, i.e. a series of assignments. You only have to provide 
+# replacements, missing definitions are set to their default value.
+
+RTF_STYLESHEET_FILE    = 
+
+# Set optional variables used in the generation of an rtf document. 
+# Syntax is similar to doxygen's config file.
+
+RTF_EXTENSIONS_FILE    = 
+
+#---------------------------------------------------------------------------
+# configuration options related to the man page output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_MAN tag is set to YES (the default) Doxygen will 
+# generate man pages
+
+GENERATE_MAN           = NO
+
+# The MAN_OUTPUT tag is used to specify where the man pages will be put. 
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be 
+# put in front of it. If left blank `man' will be used as the default path.
+
+MAN_OUTPUT             = man
+
+# The MAN_EXTENSION tag determines the extension that is added to 
+# the generated man pages (default is the subroutine's section .3)
+
+MAN_EXTENSION          = .3
+
+# If the MAN_LINKS tag is set to YES and Doxygen generates man output, 
+# then it will generate one additional man file for each entity 
+# documented in the real man page(s). These additional files 
+# only source the real man page, but without them the man command 
+# would be unable to find the correct page. The default is NO.
+
+MAN_LINKS              = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the XML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_XML tag is set to YES Doxygen will 
+# generate an XML file that captures the structure of 
+# the code including all documentation.
+
+GENERATE_XML           = NO
+
+# The XML_OUTPUT tag is used to specify where the XML pages will be put. 
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be 
+# put in front of it. If left blank `xml' will be used as the default path.
+
+XML_OUTPUT             = xml
+
+# The XML_SCHEMA tag can be used to specify an XML schema, 
+# which can be used by a validating XML parser to check the 
+# syntax of the XML files.
+
+XML_SCHEMA             = 
+
+# The XML_DTD tag can be used to specify an XML DTD, 
+# which can be used by a validating XML parser to check the 
+# syntax of the XML files.
+
+XML_DTD                = 
+
+# If the XML_PROGRAMLISTING tag is set to YES Doxygen will 
+# dump the program listings (including syntax highlighting 
+# and cross-referencing information) to the XML output. Note that 
+# enabling this will significantly increase the size of the XML output.
+
+XML_PROGRAMLISTING     = YES
+
+#---------------------------------------------------------------------------
+# configuration options for the AutoGen Definitions output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will 
+# generate an AutoGen Definitions (see autogen.sf.net) file 
+# that captures the structure of the code including all 
+# documentation. Note that this feature is still experimental 
+# and incomplete at the moment.
+
+GENERATE_AUTOGEN_DEF   = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the Perl module output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_PERLMOD tag is set to YES Doxygen will 
+# generate a Perl module file that captures the structure of 
+# the code including all documentation. Note that this 
+# feature is still experimental and incomplete at the 
+# moment.
+
+GENERATE_PERLMOD       = NO
+
+# If the PERLMOD_LATEX tag is set to YES Doxygen will generate 
+# the necessary Makefile rules, Perl scripts and LaTeX code to be able 
+# to generate PDF and DVI output from the Perl module output.
+
+PERLMOD_LATEX          = NO
+
+# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be 
+# nicely formatted so it can be parsed by a human reader.  This is useful 
+# if you want to understand what is going on.  On the other hand, if this 
+# tag is set to NO the size of the Perl module output will be much smaller 
+# and Perl will parse it just the same.
+
+PERLMOD_PRETTY         = YES
+
+# The names of the make variables in the generated doxyrules.make file 
+# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. 
+# This is useful so different doxyrules.make files included by the same 
+# Makefile don't overwrite each other's variables.
+
+PERLMOD_MAKEVAR_PREFIX = 
+
+#---------------------------------------------------------------------------
+# Configuration options related to the preprocessor   
+#---------------------------------------------------------------------------
+
+# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will 
+# evaluate all C-preprocessor directives found in the sources and include 
+# files.
+
+ENABLE_PREPROCESSING   = YES
+
+# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro 
+# names in the source code. If set to NO (the default) only conditional 
+# compilation will be performed. Macro expansion can be done in a controlled 
+# way by setting EXPAND_ONLY_PREDEF to YES.
+
+MACRO_EXPANSION        = NO
+
+# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES 
+# then the macro expansion is limited to the macros specified with the 
+# PREDEFINED and EXPAND_AS_DEFINED tags.
+
+EXPAND_ONLY_PREDEF     = NO
+
+# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files 
+# in the INCLUDE_PATH (see below) will be search if a #include is found.
+
+SEARCH_INCLUDES        = YES
+
+# The INCLUDE_PATH tag can be used to specify one or more directories that 
+# contain include files that are not input files but should be processed by 
+# the preprocessor.
+
+INCLUDE_PATH           = 
+
+# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard 
+# patterns (like *.h and *.hpp) to filter out the header-files in the 
+# directories. If left blank, the patterns specified with FILE_PATTERNS will 
+# be used.
+
+INCLUDE_FILE_PATTERNS  = 
+
+# The PREDEFINED tag can be used to specify one or more macro names that 
+# are defined before the preprocessor is started (similar to the -D option of 
+# gcc). The argument of the tag is a list of macros of the form: name 
+# or name=definition (no spaces). If the definition and the = are 
+# omitted =1 is assumed. To prevent a macro definition from being 
+# undefined via #undef or recursively expanded use the := operator 
+# instead of the = operator.
+
+PREDEFINED             = ENABLE_WXWIDGETS ENABLE_NLS
+
+# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then 
+# this tag can be used to specify a list of macro names that should be expanded. 
+# The macro definition that is found in the sources will be used. 
+# Use the PREDEFINED tag if you want to use a different macro definition.
+
+EXPAND_AS_DEFINED      = 
+
+# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then 
+# doxygen's preprocessor will remove all function-like macros that are alone 
+# on a line, have an all uppercase name, and do not end with a semicolon. Such 
+# function macros are typically used for boiler-plate code, and will confuse 
+# the parser if not removed.
+
+SKIP_FUNCTION_MACROS   = YES
+
+#---------------------------------------------------------------------------
+# Configuration::additions related to external references   
+#---------------------------------------------------------------------------
+
+# The TAGFILES option can be used to specify one or more tagfiles. 
+# Optionally an initial location of the external documentation 
+# can be added for each tagfile. The format of a tag file without 
+# this location is as follows: 
+#   TAGFILES = file1 file2 ... 
+# Adding location for the tag files is done as follows: 
+#   TAGFILES = file1=loc1 "file2 = loc2" ... 
+# where "loc1" and "loc2" can be relative or absolute paths or 
+# URLs. If a location is present for each tag, the installdox tool 
+# does not have to be run to correct the links.
+# Note that each tag file must have a unique name
+# (where the name does NOT include the path)
+# If a tag file is not located in the directory in which doxygen 
+# is run, you must also specify the path to the tagfile here.
+
+TAGFILES               = 
+
+# When a file name is specified after GENERATE_TAGFILE, doxygen will create 
+# a tag file that is based on the input files it reads.
+
+GENERATE_TAGFILE       = 
+
+# If the ALLEXTERNALS tag is set to YES all external classes will be listed 
+# in the class index. If set to NO only the inherited external classes 
+# will be listed.
+
+ALLEXTERNALS           = NO
+
+# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed 
+# in the modules index. If set to NO, only the current project's groups will 
+# be listed.
+
+EXTERNAL_GROUPS        = YES
+
+# The PERL_PATH should be the absolute path and name of the perl script 
+# interpreter (i.e. the result of `which perl').
+
+PERL_PATH              = /usr/bin/perl
+
+#---------------------------------------------------------------------------
+# Configuration options related to the dot tool   
+#---------------------------------------------------------------------------
+
+# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will 
+# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base 
+# or super classes. Setting the tag to NO turns the diagrams off. Note that 
+# this option is superseded by the HAVE_DOT option below. This is only a 
+# fallback. It is recommended to install and use dot, since it yields more 
+# powerful graphs.
+
+CLASS_DIAGRAMS         = YES
+
+# You can define message sequence charts within doxygen comments using the \msc 
+# command. Doxygen will then run the mscgen tool (see 
+# http://www.mcternan.me.uk/mscgen/) to produce the chart and insert it in the 
+# documentation. The MSCGEN_PATH tag allows you to specify the directory where 
+# the mscgen tool resides. If left empty the tool is assumed to be found in the 
+# default search path.
+
+MSCGEN_PATH            = 
+
+# If set to YES, the inheritance and collaboration graphs will hide 
+# inheritance and usage relations if the target is undocumented 
+# or is not a class.
+
+HIDE_UNDOC_RELATIONS   = YES
+
+# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is 
+# available from the path. This tool is part of Graphviz, a graph visualization 
+# toolkit from AT&T and Lucent Bell Labs. The other options in this section 
+# have no effect if this option is set to NO (the default)
+
+HAVE_DOT               = NO
+
+# By default doxygen will write a font called FreeSans.ttf to the output 
+# directory and reference it in all dot files that doxygen generates. This 
+# font does not include all possible unicode characters however, so when you need 
+# these (or just want a differently looking font) you can specify the font name 
+# using DOT_FONTNAME. You need need to make sure dot is able to find the font, 
+# which can be done by putting it in a standard location or by setting the 
+# DOTFONTPATH environment variable or by setting DOT_FONTPATH to the directory 
+# containing the font.
+
+DOT_FONTNAME           = FreeSans
+
+# By default doxygen will tell dot to use the output directory to look for the 
+# FreeSans.ttf font (which doxygen will put there itself). If you specify a 
+# different font using DOT_FONTNAME you can set the path where dot 
+# can find it using this tag.
+
+DOT_FONTPATH           = 
+
+# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen 
+# will generate a graph for each documented class showing the direct and 
+# indirect inheritance relations. Setting this tag to YES will force the 
+# the CLASS_DIAGRAMS tag to NO.
+
+CLASS_GRAPH            = YES
+
+# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen 
+# will generate a graph for each documented class showing the direct and 
+# indirect implementation dependencies (inheritance, containment, and 
+# class references variables) of the class with other documented classes.
+
+COLLABORATION_GRAPH    = YES
+
+# If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen 
+# will generate a graph for groups, showing the direct groups dependencies
+
+GROUP_GRAPHS           = YES
+
+# If the UML_LOOK tag is set to YES doxygen will generate inheritance and 
+# collaboration diagrams in a style similar to the OMG's Unified Modeling 
+# Language.
+
+UML_LOOK               = NO
+
+# If set to YES, the inheritance and collaboration graphs will show the 
+# relations between templates and their instances.
+
+TEMPLATE_RELATIONS     = NO
+
+# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT 
+# tags are set to YES then doxygen will generate a graph for each documented 
+# file showing the direct and indirect include dependencies of the file with 
+# other documented files.
+
+INCLUDE_GRAPH          = YES
+
+# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and 
+# HAVE_DOT tags are set to YES then doxygen will generate a graph for each 
+# documented header file showing the documented files that directly or 
+# indirectly include this file.
+
+INCLUDED_BY_GRAPH      = YES
+
+# If the CALL_GRAPH and HAVE_DOT options are set to YES then 
+# doxygen will generate a call dependency graph for every global function 
+# or class method. Note that enabling this option will significantly increase 
+# the time of a run. So in most cases it will be better to enable call graphs 
+# for selected functions only using the \callgraph command.
+
+CALL_GRAPH             = NO
+
+# If the CALLER_GRAPH and HAVE_DOT tags are set to YES then 
+# doxygen will generate a caller dependency graph for every global function 
+# or class method. Note that enabling this option will significantly increase 
+# the time of a run. So in most cases it will be better to enable caller 
+# graphs for selected functions only using the \callergraph command.
+
+CALLER_GRAPH           = NO
+
+# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen 
+# will graphical hierarchy of all classes instead of a textual one.
+
+GRAPHICAL_HIERARCHY    = YES
+
+# If the DIRECTORY_GRAPH, SHOW_DIRECTORIES and HAVE_DOT tags are set to YES 
+# then doxygen will show the dependencies a directory has on other directories 
+# in a graphical way. The dependency relations are determined by the #include
+# relations between the files in the directories.
+
+DIRECTORY_GRAPH        = YES
+
+# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images 
+# generated by dot. Possible values are png, jpg, or gif
+# If left blank png will be used.
+
+DOT_IMAGE_FORMAT       = png
+
+# The tag DOT_PATH can be used to specify the path where the dot tool can be 
+# found. If left blank, it is assumed the dot tool can be found in the path.
+
+DOT_PATH               = 
+
+# The DOTFILE_DIRS tag can be used to specify one or more directories that 
+# contain dot files that are included in the documentation (see the 
+# \dotfile command).
+
+DOTFILE_DIRS           = 
+
+# The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of 
+# nodes that will be shown in the graph. If the number of nodes in a graph 
+# becomes larger than this value, doxygen will truncate the graph, which is 
+# visualized by representing a node as a red box. Note that doxygen if the 
+# number of direct children of the root node in a graph is already larger than 
+# DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note 
+# that the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH.
+
+DOT_GRAPH_MAX_NODES    = 50
+
+# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the 
+# graphs generated by dot. A depth value of 3 means that only nodes reachable 
+# from the root by following a path via at most 3 edges will be shown. Nodes 
+# that lay further from the root node will be omitted. Note that setting this 
+# option to 1 or 2 may greatly reduce the computation time needed for large 
+# code bases. Also note that the size of a graph can be further restricted by 
+# DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction.
+
+MAX_DOT_GRAPH_DEPTH    = 0
+
+# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent 
+# background. This is enabled by default, which results in a transparent 
+# background. Warning: Depending on the platform used, enabling this option 
+# may lead to badly anti-aliased labels on the edges of a graph (i.e. they 
+# become hard to read).
+
+DOT_TRANSPARENT        = YES
+
+# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output 
+# files in one run (i.e. multiple -o and -T options on the command line). This 
+# makes dot run faster, but since only newer versions of dot (>1.8.10) 
+# support this, this feature is disabled by default.
+
+DOT_MULTI_TARGETS      = NO
+
+# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will 
+# generate a legend page explaining the meaning of the various boxes and 
+# arrows in the dot generated graphs.
+
+GENERATE_LEGEND        = YES
+
+# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will 
+# remove the intermediate dot files that are used to generate 
+# the various graphs.
+
+DOT_CLEANUP            = YES
+
+#---------------------------------------------------------------------------
+# Configuration::additions related to the search engine   
+#---------------------------------------------------------------------------
+
+# The SEARCHENGINE tag specifies whether or not a search engine should be 
+# used. If set to NO the values of all tags below this one will be ignored.
+
+SEARCHENGINE           = NO
diff --git a/src/core/TODO.txt b/src/core/TODO.txt
new file mode 100755
index 0000000..e3c7640
--- /dev/null
+++ b/src/core/TODO.txt
@@ -0,0 +1,3 @@
+- Remove SmartPtr for pin Send operation
+- Provide better allocators for frequently allocated/deallocated type instances
+- RegisterInputPin/RegisterOutputPin/CreateOutputPin/CreateInstance should thrown an excepcion when fail (check whether they are onnly used by component constructors)
diff --git a/src/core/basictypesimpl.cpp b/src/core/basictypesimpl.cpp
new file mode 100644
index 0000000..b97963f
--- /dev/null
+++ b/src/core/basictypesimpl.cpp
@@ -0,0 +1,1012 @@
+/////////////////////////////////////////////////////////////////////////////
+// File:        basictypesimpl.cpp
+// Author:      Cesar Mauri Loba (cesar at crea-si dot com)
+// Copyright:   (C) 2010 Cesar Mauri Loba - CREA Software Systems
+//
+//  This program is free software: you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation, either version 3 of the License, or
+//  (at your option) any later version.
+//
+//  This program is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+/////////////////////////////////////////////////////////////////////////////
+
+#include "commoncomponents.h"
+#include "timecomponents.h"
+
+#include "spcore/basictypes.h"
+#include "spcore/pin.h"
+#include "spcore/pinimpl.h"
+#include "spcore/module.h"
+#include "spcore/component.h"
+#include "spcore/conversion.h"
+#include <string>
+#include <exception>
+using namespace std;
+
+namespace spcore {
+
+/*
+	Template class for unary operations
+
+	TODO: use this for all unary operators
+*/
+template <typename CONTENTS, typename OPTYPE, typename RETYPE= OPTYPE>
+class UnaryOperation : public CComponentAdapter, public CONTENTS {
+  public:
+	virtual const char* GetTypeName() const { return CONTENTS::getTypeName(); }
+    UnaryOperation(const char * name, int argc, const char * argv[]) 
+	: CComponentAdapter(name, argc, argv) {
+
+		// Input pins
+  		if (RegisterInputPin(*SmartPtr<InputPin1>(new InputPin1("a", *this), false))!= 0)
+			throw std::runtime_error("error creating input pin a");
+
+		// Output pin
+		m_oResult= RETYPE::CreateOutputPin("result");
+		assert (m_oResult);
+		if (RegisterOutputPin(*m_oResult)!= 0)
+			throw std::runtime_error("error creating output pin");
+
+		// Result
+		m_result= RETYPE::CreateInstance(); assert (m_result);
+	}
+
+  private:
+	virtual ~UnaryOperation() {}
+
+	class InputPin1 : public CInputPinWriteOnly<OPTYPE, UnaryOperation > {
+	public:
+		InputPin1 (const char * name, UnaryOperation & component)
+		: CInputPinWriteOnly<OPTYPE, UnaryOperation >(name, component) {}
+
+		virtual int DoSend(const OPTYPE & message) {
+			this->m_component->m_result->setValue(this->m_component->Compute (message.getValue()));
+			this->m_component->m_oResult->Send (this->m_component->m_result);
+			return 0;
+		}
+	};	
+
+  private:
+    // Atributes
+	SmartPtr<IOutputPin> m_oResult;
+    SmartPtr<RETYPE> m_result;
+};
+
+
+/*
+	Template class for binary operations
+*/
+template <typename CONTENTS, typename OPTYPE, typename RETYPE= OPTYPE>
+class BinaryOperation : public CComponentAdapter, public CONTENTS {
+  public:
+	virtual const char* GetTypeName() const { return CONTENTS::getTypeName(); }
+    BinaryOperation(const char * name, int argc, const char * argv[]) 
+	: CComponentAdapter(name, argc, argv) {
+
+		if (argc) {
+			int i= 0;
+			for (; i< argc; ++i) if (strcmp("-v", argv[i])== 0) break;
+
+			if (i< argc) {
+				++i;
+				if (i>= argc) 
+					throw std::runtime_error("No value found for parameter -v");
+
+				// Found				
+				this->ParseOperandB(argv[i]);
+			}
+		}
+
+		// Input pins
+  		if (RegisterInputPin(*SmartPtr<InputPin1>(new InputPin1("a", *this), false))!= 0)
+			throw std::runtime_error("error creating input pin a");
+   		if (RegisterInputPin(*SmartPtr<InputPin2>(new InputPin2("b", *this), false))!= 0)
+			throw std::runtime_error("error creating input pin b");
+
+		// Output pin
+		m_oResult= RETYPE::CreateOutputPin("result");
+		assert (m_oResult);
+		if (RegisterOutputPin(*m_oResult)!= 0)
+			throw std::runtime_error("error creating output pin");
+
+		// Result
+		m_result= RETYPE::CreateInstance(); assert (m_result);
+	}
+
+  private:
+	virtual ~BinaryOperation() {}
+
+	class InputPin1 : public CInputPinWriteOnly<OPTYPE, BinaryOperation > {
+	public:
+		InputPin1 (const char * name, BinaryOperation & component)
+		: CInputPinWriteOnly<OPTYPE, BinaryOperation >(name, component) {}
+
+		virtual int DoSend(const OPTYPE & message) {
+			this->m_component->m_result->setValue(this->m_component->SetOperandA (message.getValue()));
+			this->m_component->m_oResult->Send (this->m_component->m_result);
+			return 0;
+		}
+	};
+
+	class InputPin2 : public CInputPinReadWrite<OPTYPE, BinaryOperation> {
+	public:
+		InputPin2 (const char * name, BinaryOperation & component)
+		: CInputPinReadWrite<OPTYPE, BinaryOperation>(name, component) {}
+
+		virtual int DoSend(const OPTYPE & message) {
+			this->m_component->SetOperandB(message.getValue());
+			return 0;
+		}
+
+		virtual SmartPtr<OPTYPE> DoRead() const {
+			SmartPtr<OPTYPE> result= OPTYPE::CreateInstance();
+			result->setValue (this->m_component->GetOperandB());
+			return result;
+		}
+	};
+
+  private:
+    // Atributes
+	SmartPtr<IOutputPin> m_oResult;
+    SmartPtr<RETYPE> m_result;
+};
+
+
+// Integer addition
+class AddIntContents {
+public:
+	static const char* getTypeName() { return "iadd"; }
+	AddIntContents() : m_b(0) { }
+	int SetOperandA (int a) { return a + m_b; }
+	void SetOperandB (int b) {	m_b= b; }
+	int GetOperandB () const {	return m_b; }
+	void ParseOperandB(const char* operand) {
+		int val= m_b;
+		StrToInt(operand, &val);
+		SetOperandB(val);
+	}
+
+private:
+	int m_b;
+};
+typedef ComponentFactory<BinaryOperation<AddIntContents, CTypeInt> > AddIntFactory;
+
+// Integer substraction
+class SubIntContents {
+public:
+	static const char* getTypeName() { return "isub"; }
+	SubIntContents() : m_b(0) { }
+	int SetOperandA (int a) { return a - m_b; }
+	void SetOperandB (int b) {	m_b= b; }
+	int GetOperandB () const {	return m_b; }
+	void ParseOperandB(const char* operand) {
+		int val= m_b;
+		StrToInt (operand, &val);
+		SetOperandB(val);
+	}
+
+private:
+	int m_b;
+};
+typedef ComponentFactory<BinaryOperation<SubIntContents, CTypeInt> > SubIntFactory;
+
+// Integer multiplication
+class MulIntContents {
+public:
+	static const char* getTypeName() { return "imul"; }
+	MulIntContents() : m_b(1) { }
+	int SetOperandA (int a) { return a * m_b; }
+	void SetOperandB (int b) {	m_b= b; }
+	int GetOperandB () const {	return m_b; }
+	void ParseOperandB(const char* operand) {
+		int val= m_b;
+		StrToInt (operand, &val);
+		SetOperandB(val);
+	}
+
+private:
+	int m_b;
+};
+typedef ComponentFactory<BinaryOperation<MulIntContents, CTypeInt> > MulIntFactory;
+
+// Integer division
+class DivIntContents {
+public:
+	static const char* getTypeName() { return "idiv"; }
+	DivIntContents() : m_b(1) { }
+	int SetOperandA (int a) { return a / m_b; }
+	void SetOperandB (int b) {
+		if (b== 0)
+			getSpCoreRuntime()->LogMessage(ICoreRuntime::LOG_ERROR, "intdiv: not stored 0 as divisor", "spcore");
+		else
+			m_b= b;
+	}
+	int GetOperandB () const {	return m_b; }
+	void ParseOperandB(const char* operand) {
+		int val= m_b;
+		StrToInt (operand, &val);
+		SetOperandB(val);
+	}
+
+private:
+	int m_b;
+};
+typedef ComponentFactory<BinaryOperation<DivIntContents, CTypeInt> > DivIntFactory;
+
+// Float addition
+class AddFloatContents {
+public:
+	static const char* getTypeName() { return "fadd"; }
+	AddFloatContents() : m_b(0) { }
+	float SetOperandA (float a) { return a + m_b; }
+	void SetOperandB (float b) {	m_b= b; }
+	float GetOperandB () const {	return m_b; }
+	void ParseOperandB(const char* operand) {
+		float val= m_b;
+		StrToFloat (operand, &val);
+		SetOperandB(val);
+	}
+
+private:
+	float m_b;
+};
+typedef ComponentFactory<BinaryOperation<AddFloatContents, CTypeFloat> > AddFloatFactory;
+
+// Float substraction
+class SubFloatContents {
+public:
+	static const char* getTypeName() { return "fsub"; }
+	SubFloatContents() : m_b(0) { }
+	float SetOperandA (float a) { return a - m_b; }
+	void SetOperandB (float b) {	m_b= b; }
+	float GetOperandB () const {	return m_b; }
+	void ParseOperandB(const char* operand) {
+		float val= m_b;
+		StrToFloat (operand, &val);
+		SetOperandB(val);
+	}
+
+private:
+	float m_b;
+};
+typedef ComponentFactory<BinaryOperation<SubFloatContents, CTypeFloat> > SubFloatFactory;
+
+// Float multiplication
+class MulFloatContents {
+public:
+	static const char* getTypeName() { return "fmul"; }
+	MulFloatContents() : m_b(1.0f) { }
+	float SetOperandA (float a) { return a * m_b; }
+	void SetOperandB (float b) { m_b= b; }
+	float GetOperandB () const {	return m_b; }
+	void ParseOperandB(const char* operand) {
+		float val= m_b;
+		StrToFloat (operand, &val);
+		SetOperandB(val);
+	}
+
+private:
+	float m_b;
+};
+typedef ComponentFactory<BinaryOperation<MulFloatContents, CTypeFloat> > MulFloatFactory;
+
+// Float division
+class DivFloatContents {
+public:
+	static const char* getTypeName() { return "fdiv"; }
+	DivFloatContents() : m_b(1.0f) { }
+	float SetOperandA (float a) { return a / m_b; }
+	void SetOperandB (float b) {
+		if (b== 0.0f)
+			getSpCoreRuntime()->LogMessage(ICoreRuntime::LOG_ERROR, "fdiv: not stored 0.0 as divisor", "spcore");
+		else
+			m_b= b;
+	}
+	float GetOperandB () const {	return m_b; }
+	void ParseOperandB(const char* operand) {
+		float val= m_b;
+		StrToFloat (operand, &val);
+		SetOperandB(val);
+	}
+
+private:
+	float m_b;
+};
+typedef ComponentFactory<BinaryOperation<DivFloatContents, CTypeFloat> > DivFloatFactory;
+
+///////////////////////////////////////////////////////////////////////////////
+/**
+	fsqrt - Computes the square root
+
+	Input pins:
+		a (float)
+
+	Output pins:
+		result (float)
+*/
+class FSqrtComponent : public CComponentAdapter {
+public:
+	static const char* getTypeName() { return "fsqrt"; }
+	virtual const char* GetTypeName() const { return FSqrtComponent::getTypeName(); }
+    FSqrtComponent(const char * name, int argc, const char * argv[]) 
+	: CComponentAdapter(name, argc, argv) {
+		
+		m_opin= CTypeFloat::CreateOutputPin("result");
+		if (RegisterOutputPin(*m_opin)!= 0)
+			throw std::runtime_error("error registering output pin");
+
+  		if (RegisterInputPin(*SmartPtr<IInputPin>(new InputPinIn("a", *m_opin), false))!= 0)
+			throw std::runtime_error("error creating input pin");
+	}
+
+private:
+	virtual ~FSqrtComponent() {}
+
+	class InputPinIn : public CInputPinWriteOnly<CTypeFloat, IOutputPin> {
+	public:
+		InputPinIn (const char * name, IOutputPin & component)
+		: CInputPinWriteOnly<CTypeFloat, IOutputPin>(name, component) {
+			m_result= CTypeFloat::CreateInstance();
+		}
+
+		virtual int DoSend(const CTypeFloat & msg) {
+			float v= msg.getValue();
+			if (v>= 0.0f) {
+				m_result->setValue(sqrtf(v));
+				m_component->Send(m_result);
+				return 0;
+			}
+			else
+				return -1;
+		}
+
+	private:		
+		SmartPtr<CTypeFloat> m_result;
+	};
+	
+	SmartPtr<IOutputPin> m_opin;	
+};
+
+typedef ComponentFactory<FSqrtComponent> FSqrtComponentFactory;
+
+///////////////////////////////////////////////////////////////////////////////
+//	Comparison operators
+///////////////////////////////////////////////////////////////////////////////
+
+template <typename T>
+class CmpOpCommonOps
+{
+public:
+	CmpOpCommonOps() : m_b(0) {}
+	void SetOperandB (T b) { m_b= b; }
+	T GetOperandB () const { return m_b; }
+	void ParseOperandB(const char* operand);
+
+protected:
+	T m_b;
+};
+
+template<> void CmpOpCommonOps<int>::ParseOperandB(const char *operand) {
+	int val= m_b;
+	StrToInt (operand, &val);
+	SetOperandB(val);
+}
+
+template<> void CmpOpCommonOps<float>::ParseOperandB(const char *operand) {
+	float val= m_b;
+	StrToFloat (operand, &val);
+	SetOperandB(val);
+}
+
+// Integer
+struct IntEqContents : public CmpOpCommonOps<int> {
+	static const char* getTypeName() { return "ieq"; }
+	bool SetOperandA (int a) { return (a== m_b); }
+};
+typedef ComponentFactory<BinaryOperation<IntEqContents, CTypeInt, CTypeBool> > IntEqFactory;
+
+struct IntNeqContents : public CmpOpCommonOps<int> {
+	static const char* getTypeName() { return "ineq"; }
+	bool SetOperandA (int a) { return (a!= m_b); }
+};
+typedef ComponentFactory<BinaryOperation<IntNeqContents, CTypeInt, CTypeBool> > IntNeqFactory;
+
+struct IntGtContents : public CmpOpCommonOps<int> {
+	static const char* getTypeName() { return "igt"; }
+	bool SetOperandA (int a) { return (a> m_b); }
+};
+typedef ComponentFactory<BinaryOperation<IntGtContents, CTypeInt, CTypeBool> > IntGtFactory;
+
+struct IntEgtContents : public CmpOpCommonOps<int> {
+	static const char* getTypeName() { return "iegt"; }
+	bool SetOperandA (int a) { return (a>= m_b); }
+};
+typedef ComponentFactory<BinaryOperation<IntEgtContents, CTypeInt, CTypeBool> > IntEgtFactory;
+
+struct IntLtContents : public CmpOpCommonOps<int> {
+	static const char* getTypeName() { return "ilt"; }
+	bool SetOperandA (int a) { return (a< m_b); }
+};
+typedef ComponentFactory<BinaryOperation<IntLtContents, CTypeInt, CTypeBool> > IntLtFactory;
+
+struct IntEltContents : public CmpOpCommonOps<int> {
+	static const char* getTypeName() { return "ielt"; }
+	bool SetOperandA (int a) { return (a<= m_b); }
+};
+typedef ComponentFactory<BinaryOperation<IntEltContents, CTypeInt, CTypeBool> > IntEltFactory;
+
+
+// Float
+struct FloatEqContents : public CmpOpCommonOps<float> {
+	static const char* getTypeName() { return "feq"; }
+	bool SetOperandA (float a) { return (a== m_b); }
+};
+typedef ComponentFactory<BinaryOperation<FloatEqContents, CTypeFloat, CTypeBool> > FloatEqFactory;
+
+struct FloatNeqContents : public CmpOpCommonOps<float> {
+	static const char* getTypeName() { return "fneq"; }
+	bool SetOperandA (float a) { return (a!= m_b); }
+};
+typedef ComponentFactory<BinaryOperation<FloatNeqContents, CTypeFloat, CTypeBool> > FloatNeqFactory;
+
+struct FloatGtContents : public CmpOpCommonOps<float> {
+	static const char* getTypeName() { return "fgt"; }
+	bool SetOperandA (float a) { return (a> m_b); }
+};
+typedef ComponentFactory<BinaryOperation<FloatGtContents, CTypeFloat, CTypeBool> > FloatGtFactory;
+
+struct FloatEgtContents : public CmpOpCommonOps<float> {
+	static const char* getTypeName() { return "fegt"; }
+	bool SetOperandA (float a) { return (a>= m_b); }
+};
+typedef ComponentFactory<BinaryOperation<FloatEgtContents, CTypeFloat, CTypeBool> > FloatEgtFactory;
+
+struct FloatLtContents : public CmpOpCommonOps<float> {
+	static const char* getTypeName() { return "flt"; }
+	bool SetOperandA (float a) { return (a< m_b); }
+};
+typedef ComponentFactory<BinaryOperation<FloatLtContents, CTypeFloat, CTypeBool> > FloatLtFactory;
+
+struct FloatEltContents : public CmpOpCommonOps<float> {
+	static const char* getTypeName() { return "felt"; }
+	bool SetOperandA (float a) { return (a<= m_b); }
+};
+typedef ComponentFactory<BinaryOperation<FloatEltContents, CTypeFloat, CTypeBool> > FloatEltFactory;
+
+///////////////////////////////////////////////////////////////////////////////
+//	Boolean operators
+///////////////////////////////////////////////////////////////////////////////
+class NotContents {
+public:
+	static const char* getTypeName() { return "not"; }
+	bool Compute(bool v) { return !v; }	
+};
+typedef ComponentFactory<UnaryOperation<NotContents, CTypeBool> > NotFactory;
+
+///////////////////////////////////////////////////////////////////////////////
+//	Casting operators
+///////////////////////////////////////////////////////////////////////////////
+/**
+	fcast - Convert an input value into float
+
+	Input pins:
+		in (any)
+
+		Input could be bool, int or float
+
+	Output pins:
+		out (float)
+*/
+class FCastComponent : public CComponentAdapter {
+public:
+	static const char* getTypeName() { return "fcast"; }
+	virtual const char* GetTypeName() const { return FCastComponent::getTypeName(); }
+    FCastComponent(const char * name, int argc, const char * argv[]) 
+	: CComponentAdapter(name, argc, argv) {
+		
+		m_opin= CTypeFloat::CreateOutputPin("out");
+		if (RegisterOutputPin(*m_opin)!= 0)
+			throw std::runtime_error("error registering output pin");
+
+  		if (RegisterInputPin(*SmartPtr<IInputPin>(new InputPinIn("in", *m_opin), false))!= 0)
+			throw std::runtime_error("error creating input pin");
+	}
+
+private:
+	virtual ~FCastComponent() {}
+
+	class InputPinIn : public CInputPinWriteOnly<CTypeAny, IOutputPin> {
+	public:
+		InputPinIn (const char * name, IOutputPin & component)
+		: CInputPinWriteOnly<CTypeAny, IOutputPin>(name, component) {
+			m_intTypeId= CTypeInt::getTypeID();
+			m_boolTypeId= CTypeBool::getTypeID();
+			m_floatTypeId= CTypeFloat::getTypeID();
+			m_result= CTypeFloat::CreateInstance();
+		}
+
+		virtual int DoSend(const CTypeAny & msg) {
+			int msgId= msg.GetTypeID();
+
+			if (msgId== m_intTypeId) {
+				m_result->setValue((float) sptype_static_cast<const CTypeInt>(&msg)->getValue());
+				return this->m_component->Send (m_result);
+			}
+			else if (msgId== m_boolTypeId) {
+				if (sptype_static_cast<const CTypeBool>(&msg)->getValue())
+					m_result->setValue(1.0f);
+				else
+					m_result->setValue(0.0f);
+				return this->m_component->Send (m_result);
+			}
+			else if (msgId== m_floatTypeId) {
+				m_result->setValue(sptype_static_cast<const CTypeFloat>(&msg)->getValue());
+				return this->m_component->Send (m_result);
+			}
+
+			return -1;
+		}
+
+	private:
+		int m_intTypeId, m_boolTypeId, m_floatTypeId;
+		SmartPtr<CTypeFloat> m_result;
+	};
+	
+	SmartPtr<IOutputPin> m_opin;	
+};
+
+typedef ComponentFactory<FCastComponent> FCastComponentFactory;
+
+/**
+	icast - Convert an input value into integer
+
+	Input pins:
+		in (any)
+
+		Input could be bool, int or float
+
+	Output pins:
+		out (int)
+*/
+class IntCastComponent : public CComponentAdapter {
+public:
+	static const char* getTypeName() { return "icast"; }
+	virtual const char* GetTypeName() const { return IntCastComponent::getTypeName(); }
+    IntCastComponent(const char * name, int argc, const char * argv[]) 
+	: CComponentAdapter(name, argc, argv) {
+		
+		m_opin= CTypeInt::CreateOutputPin("out");
+		if (RegisterOutputPin(*m_opin)!= 0)
+			throw std::runtime_error("error registering output pin");
+
+  		if (RegisterInputPin(*SmartPtr<IInputPin>(new InputPinIn("in", *m_opin), false))!= 0)
+			throw std::runtime_error("error creating input pin");
+	}
+
+private:
+	virtual ~IntCastComponent() {}
+
+	class InputPinIn : public CInputPinWriteOnly<CTypeAny, IOutputPin> {
+	public:
+		InputPinIn (const char * name, IOutputPin & component)
+		: CInputPinWriteOnly<CTypeAny, IOutputPin>(name, component) {
+			m_floatTypeId= CTypeFloat::getTypeID();
+			m_boolTypeId= CTypeBool::getTypeID();
+			m_intTypeId= CTypeInt::getTypeID();
+			m_result= CTypeInt::CreateInstance();
+		}
+
+		virtual int DoSend(const CTypeAny & msg) {
+			int msgId= msg.GetTypeID();
+
+			if (msgId== m_floatTypeId) {
+				m_result->setValue((int) sptype_static_cast<const CTypeFloat>(&msg)->getValue());
+				return this->m_component->Send (m_result);
+			}
+			else if (msgId== m_boolTypeId) {
+				if (sptype_static_cast<const CTypeBool>(&msg)->getValue())
+					m_result->setValue(1);
+				else
+					m_result->setValue(0);
+				return this->m_component->Send (m_result);
+			}
+			else if (msgId== m_intTypeId) {
+				m_result->setValue(sptype_static_cast<const CTypeInt>(&msg)->getValue());
+				return this->m_component->Send (m_result);
+			}
+
+			return -1;
+		}
+
+	private:
+		int m_floatTypeId, m_boolTypeId, m_intTypeId;
+		SmartPtr<CTypeInt> m_result;
+	};
+	
+	SmartPtr<IOutputPin> m_opin;	
+};
+
+typedef ComponentFactory<IntCastComponent> IntCastComponentFactory;
+
+/**
+	bcast - Convert an input value into boolean
+
+	Input pins:
+		in (any)
+
+		Input could be bool, int or float
+
+	Output pins:
+		out (bool)
+*/
+class BCastComponent : public CComponentAdapter {
+public:
+	static const char* getTypeName() { return "bcast"; }
+	virtual const char* GetTypeName() const { return BCastComponent::getTypeName(); }
+    BCastComponent(const char * name, int argc, const char * argv[]) 
+	: CComponentAdapter(name, argc, argv) {
+		
+		m_opin= CTypeBool::CreateOutputPin("out");
+		if (RegisterOutputPin(*m_opin)!= 0)
+			throw std::runtime_error("error registering output pin");
+
+  		if (RegisterInputPin(*SmartPtr<IInputPin>(new InputPinIn("in", *m_opin), false))!= 0)
+			throw std::runtime_error("error creating input pin");
+	}
+
+private:
+	virtual ~BCastComponent() {}
+
+	class InputPinIn : public CInputPinWriteOnly<CTypeAny, IOutputPin> {
+	public:
+		InputPinIn (const char * name, IOutputPin & component)
+		: CInputPinWriteOnly<CTypeAny, IOutputPin>(name, component) {
+			m_intTypeId= CTypeInt::getTypeID();
+			m_floatTypeId= CTypeFloat::getTypeID();
+			m_boolTypeId= CTypeBool::getTypeID();			
+			m_result= CTypeBool::CreateInstance();
+		}
+
+		virtual int DoSend(const CTypeAny & msg) {
+			int msgId= msg.GetTypeID();
+
+			if (msgId== m_intTypeId) {
+				m_result->setValue(sptype_static_cast<const CTypeInt>(&msg)->getValue()!= 0);
+				return this->m_component->Send (m_result);
+			}
+			else if (msgId== m_floatTypeId) {
+				// TODO: check wheter is better to allow for "almost zero" comparison 
+				m_result->setValue(sptype_static_cast<const CTypeFloat>(&msg)->getValue()!= 0.0f);
+				return this->m_component->Send (m_result);
+			}
+			else if (msgId== m_boolTypeId) {
+				m_result->setValue(sptype_static_cast<const CTypeBool>(&msg)->getValue());
+				return this->m_component->Send (m_result);
+			}
+
+			return -1;
+		}
+
+	private:
+		int m_intTypeId, m_floatTypeId, m_boolTypeId;
+		SmartPtr<CTypeBool> m_result;
+	};
+	
+	SmartPtr<IOutputPin> m_opin;	
+};
+
+typedef ComponentFactory<BCastComponent> BCastComponentFactory;
+
+///////////////////////////////////////////////////////////////////////////////
+
+/**
+	fabs - Absolute value component (float)
+
+	Input pins:
+		in (CTypeFloat)
+
+	Output pins:
+		out (CTypeFloat)
+*/
+class FAbsComponent : public CComponentAdapter {
+public:
+	static const char* getTypeName() { return "fabs"; }
+	virtual const char* GetTypeName() const { return FAbsComponent::getTypeName(); }
+    FAbsComponent(const char * name, int argc, const char * argv[]) 
+	: CComponentAdapter(name, argc, argv) {
+		
+		m_opin= CTypeFloat::CreateOutputPin("out");
+		if (RegisterOutputPin(*m_opin)!= 0)
+			throw std::runtime_error("error registering output pin");
+
+  		if (RegisterInputPin(*SmartPtr<IInputPin>(new InputPinIn("in", *m_opin), false))!= 0)
+			throw std::runtime_error("error creating input pin");
+	}
+
+private:
+	virtual ~FAbsComponent() {}
+
+	class InputPinIn : public CInputPinWriteOnly<CTypeFloat, IOutputPin> {
+	public:
+		InputPinIn (const char * name, IOutputPin & component)
+		: CInputPinWriteOnly<CTypeFloat, IOutputPin>(name, component) {	
+			m_result= CTypeFloat::CreateInstance();
+		}
+
+		virtual int DoSend(const CTypeFloat & message) {
+			m_result->setValue (fabsf(message.getValue()));
+			return this->m_component->Send (m_result);
+		}
+	private:
+		SmartPtr<CTypeFloat> m_result;
+	};
+	SmartPtr<IOutputPin> m_opin;
+};
+
+typedef ComponentFactory<FAbsComponent> FAbsComponentFactory;
+
+// Factories for basic types
+typedef SimpleTypeFactory<CTypeInt> CTypeIntFactory;
+typedef SimpleTypeFactory<CTypeBool> CTypeBoolFactory;
+typedef SimpleTypeFactory<CTypeFloat> CTypeFloatFactory;
+typedef SimpleTypeFactory<CTypeString> CTypeStringFactory;
+
+// Factories for other components
+typedef SimpleTypeFactory<CTypeComposite> CTypeCompositeFactory;
+
+
+/*
+	Template to implement type storages.	
+*/
+template <typename CONTENTS, typename OPTYPE>
+class InstanceStorage : public CComponentAdapter, public CONTENTS {
+  public:
+	virtual const char* GetTypeName() const { return CONTENTS::getTypeName(); }
+    InstanceStorage(const char * name, int argc, const char * argv[]) 
+	: CComponentAdapter(name, argc, argv) {
+		// Input pins
+  		if (RegisterInputPin(*SmartPtr<InputPinRetrieve>(new InputPinRetrieve("retrieve", *this), false))!= 0)
+			throw std::runtime_error("error creating input pin retrieve");
+   		if (RegisterInputPin(*SmartPtr<InputPinStore>(new InputPinStore("store", *this), false))!= 0)
+			throw std::runtime_error("error creating input pin store");
+
+		// Output pin
+		m_oOut= OPTYPE::CreateOutputPin("out");
+		assert (m_oOut);
+		if (RegisterOutputPin(*m_oOut)!= 0)
+			throw std::runtime_error("error creating output pin");
+
+		// Value
+		m_value= OPTYPE::CreateInstance(); assert (m_value);
+
+		// Parse command line
+		if (argc) {
+			int i= 0;
+			for (; i< argc; ++i) if (strcmp("-v", argv[i])== 0) break;
+
+			if (i< argc) {
+				++i;
+				if (i>= argc) 
+					throw std::runtime_error("No value found for parameter -v");
+
+				// Found				
+				m_value->setValue(this->ParseValue(argv[i]));
+			}
+		}
+	}
+
+  private:
+	virtual ~InstanceStorage() {}
+
+	class InputPinRetrieve : public CInputPinWriteOnly<CTypeAny, InstanceStorage > {
+	public:
+		InputPinRetrieve (const char * name, InstanceStorage & component)
+		: CInputPinWriteOnly<CTypeAny, InstanceStorage >(name, component) {}
+
+		virtual int DoSend(const CTypeAny &) {
+			this->m_component->m_oOut->Send (this->m_component->m_value);
+			return 0;
+		}
+	};
+
+	class InputPinStore : public CInputPinWriteOnly<OPTYPE, InstanceStorage> {
+	public:
+		InputPinStore (const char * name, InstanceStorage & component)
+		: CInputPinWriteOnly<OPTYPE, InstanceStorage>(name, component) {}
+
+		virtual int DoSend(const OPTYPE & message) {
+			this->m_component->m_value->setValue(message.getValue());
+			return 0;
+		}
+	};
+
+  private:
+    // Atributes
+	SmartPtr<IOutputPin> m_oOut;
+    SmartPtr<OPTYPE> m_value;
+};
+
+/**
+	int - Stores an integer
+
+	Input pins:
+		retrieve (any)	- Once a message is received in this pin the content is sent to output.
+		store (int)		- Stores an integer instance.
+
+	Output pins:
+		out (int)
+
+	Command line:
+		[-v <num> ]		Value used to initialize
+*/
+class IntStorageContents {
+public:
+	static const char* getTypeName() { return "int"; }
+	int ParseValue(const char* str) {
+		int val= 0;
+		if (!StrToInt(str, &val))
+			throw std::runtime_error("Error parsing integer value for -v");
+		return val;
+	}
+};
+typedef ComponentFactory<InstanceStorage<IntStorageContents, CTypeInt> > IntStorageFactory;
+
+/**
+	float - Stores an integer
+
+	Input pins:
+		retrieve (any)	- Once a message is received in this pin the content is sent to output.
+		store (float)		- Stores a float instance.
+
+	Output pins:
+		out (float)
+
+	Command line:
+		[-v <num> ]		Value used to initialize
+*/
+class FloatStorageContents {
+public:
+	static const char* getTypeName() { return "float"; }
+	float ParseValue(const char* str) {
+		float val= 0;
+		if (!StrToFloat(str, &val))
+			throw std::runtime_error("Error parsing float value for -v");
+		return val;
+	}
+};
+typedef ComponentFactory<InstanceStorage<FloatStorageContents, CTypeFloat> > FloatStorageFactory;
+
+/**
+	bool - Stores a boolean
+
+	Input pins:
+		retrieve (any)	- Once a message is received in this pin the content is sent to output.
+		store (bool)	- Stores a bool instance.
+
+	Output pins:
+		out (bool)
+
+	Command line:
+		[-v <num> ]		Value used to initialize. Possible values: 0,1,true, false
+*/	
+class BoolStorageContents {
+public:
+	static const char* getTypeName() { return "bool"; }
+	bool ParseValue(const char* str) {
+		int val= 0;
+		if (StrToInt(str, &val)) return (val? true : false);
+
+		if (strcmp(str, "true")== 0) return true;
+		if (strcmp(str, "false")== 0) return false;
+
+		throw std::runtime_error("Error parsing float value for -v");
+	}
+};
+typedef ComponentFactory<InstanceStorage<BoolStorageContents, CTypeBool> > BoolStorageFactory;
+
+
+/**
+	string - Stores a string
+
+	Input pins:
+		retrieve (any)	- Once a message is received in this pin the content is sent to output.
+		store (string)	- Stores a string instance.
+
+	Output pins:
+		out (string)
+
+	Command line:
+		[-v <num> ]		Value used to initialize. Possible values: 0,1,true, false
+*/	
+class StringStorageContents {
+public:
+	static const char* getTypeName() { return "string"; }
+	const char* ParseValue(const char* str) { return str; }
+};
+typedef ComponentFactory<InstanceStorage<StringStorageContents, CTypeString> > StringStorageFactory;
+
+//////////////////////////////////////////////////////////////////////////////////////////////////
+
+CBasicTypesModule::CBasicTypesModule() {
+	//
+	// Types
+	RegisterTypeFactory(SmartPtr<CTypeIntFactory>(new CTypeIntFactory(), false));
+	RegisterTypeFactory(SmartPtr<CTypeFloatFactory>(new CTypeFloatFactory(), false));
+	RegisterTypeFactory(SmartPtr<CTypeBoolFactory>(new CTypeBoolFactory(), false));
+	RegisterTypeFactory(SmartPtr<CTypeStringFactory>(new CTypeStringFactory(), false));
+	RegisterTypeFactory(SmartPtr<CTypeCompositeFactory>(new CTypeCompositeFactory(), false));
+
+	//
+	// Components
+	//
+	RegisterComponentFactory(SmartPtr<IComponentFactory>(new AddIntFactory(), false));
+	RegisterComponentFactory(SmartPtr<IComponentFactory>(new SubIntFactory(), false));
+	RegisterComponentFactory(SmartPtr<IComponentFactory>(new MulIntFactory(), false));
+	RegisterComponentFactory(SmartPtr<IComponentFactory>(new DivIntFactory(), false));
+
+	RegisterComponentFactory(SmartPtr<IComponentFactory>(new AddFloatFactory(), false));
+	RegisterComponentFactory(SmartPtr<IComponentFactory>(new SubFloatFactory(), false));
+	RegisterComponentFactory(SmartPtr<IComponentFactory>(new MulFloatFactory(), false));
+	RegisterComponentFactory(SmartPtr<IComponentFactory>(new DivFloatFactory(), false));
+
+	RegisterComponentFactory(SmartPtr<IComponentFactory>(new FSqrtComponentFactory(), false));
+
+	// Comparison operators
+	RegisterComponentFactory(SmartPtr<IComponentFactory>(new IntEqFactory(), false));
+	RegisterComponentFactory(SmartPtr<IComponentFactory>(new IntNeqFactory(), false));	
+	RegisterComponentFactory(SmartPtr<IComponentFactory>(new IntGtFactory(), false));
+	RegisterComponentFactory(SmartPtr<IComponentFactory>(new IntEgtFactory(), false));
+	RegisterComponentFactory(SmartPtr<IComponentFactory>(new IntLtFactory(), false));
+	RegisterComponentFactory(SmartPtr<IComponentFactory>(new IntEltFactory(), false));
+
+	RegisterComponentFactory(SmartPtr<IComponentFactory>(new FloatEqFactory(), false));
+	RegisterComponentFactory(SmartPtr<IComponentFactory>(new FloatNeqFactory(), false));
+	RegisterComponentFactory(SmartPtr<IComponentFactory>(new FloatGtFactory(), false));
+	RegisterComponentFactory(SmartPtr<IComponentFactory>(new FloatEgtFactory(), false));
+	RegisterComponentFactory(SmartPtr<IComponentFactory>(new FloatLtFactory(), false));
+	RegisterComponentFactory(SmartPtr<IComponentFactory>(new FloatEltFactory(), false));
+	
+	// Boolean operators
+	RegisterComponentFactory(SmartPtr<IComponentFactory>(new NotFactory(), false));
+
+	// Casting operators
+	RegisterComponentFactory(SmartPtr<IComponentFactory>(new FCastComponentFactory(), false));
+	RegisterComponentFactory(SmartPtr<IComponentFactory>(new IntCastComponentFactory(), false));
+	RegisterComponentFactory(SmartPtr<IComponentFactory>(new BCastComponentFactory(), false));
+	
+	RegisterComponentFactory(SmartPtr<IComponentFactory>(new FAbsComponentFactory(), false));
+
+	// Common components
+	RegisterComponentFactory(SmartPtr<IComponentFactory>(new SplitFactory(), false));
+	RegisterComponentFactory(SmartPtr<IComponentFactory>(new FAccumulatorFactory(), false));
+	RegisterComponentFactory(SmartPtr<IComponentFactory>(new FThresholdFactory(), false));
+	RegisterComponentFactory(SmartPtr<IComponentFactory>(new FLimitFactory(), false));
+	RegisterComponentFactory(SmartPtr<IComponentFactory>(new ForwardComponentFactory(), false));
+	RegisterComponentFactory(SmartPtr<IComponentFactory>(new FReductorFactory(), false));
+//	RegisterComponentFactory(SmartPtr<IComponentFactory>(new SendMainSyncFactory(), false));
+	RegisterComponentFactory(SmartPtr<IComponentFactory>(new SendMainAsyncFactory(), false));
+
+	RegisterComponentFactory(SmartPtr<IComponentFactory>(new PrintComponentFactory(), false));
+
+	// Time components
+	RegisterComponentFactory(SmartPtr<IComponentFactory>(new ChronoFactory(), false));
+
+	// Storage components
+	RegisterComponentFactory(SmartPtr<IComponentFactory>(new IntStorageFactory(), false));
+	RegisterComponentFactory(SmartPtr<IComponentFactory>(new FloatStorageFactory(), false));
+	RegisterComponentFactory(SmartPtr<IComponentFactory>(new BoolStorageFactory(), false));
+	RegisterComponentFactory(SmartPtr<IComponentFactory>(new StringStorageFactory(), false));
+}
+
+const char * CBasicTypesModule::GetName() const {
+  	return "basictypes";
+}
+
+} // namespace spcore
diff --git a/src/core/commoncomponents.h b/src/core/commoncomponents.h
new file mode 100644
index 0000000..37e865f
--- /dev/null
+++ b/src/core/commoncomponents.h
@@ -0,0 +1,1064 @@
+/////////////////////////////////////////////////////////////////////////////
+// File:        commoncomponents.cpp
+// Author:      Cesar Mauri Loba (cesar at crea-si dot com)
+// Copyright:   (C) 2010 Cesar Mauri Loba - CREA Software Systems
+//
+//  This program is free software: you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation, either version 3 of the License, or
+//  (at your option) any later version.
+//
+//  This program is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+/////////////////////////////////////////////////////////////////////////////
+#ifndef COMMONCOMPONENTS_H
+	#define COMMONCOMPONENTS_H
+#else
+	#error This file is intended to be included only once
+#endif
+
+#include "spcore/basictypes.h"
+#include "spcore/pinimpl.h"
+#include "spcore/component.h"
+#include "spcore/conversion.h"
+#include <vector>
+#include <string>
+#include <stdio.h>
+#include <boost/thread/mutex.hpp>
+#include <boost/thread/condition.hpp>
+
+using namespace std;
+
+namespace spcore {
+
+/**
+	split component
+
+	Send each child of the input type through each output pin.
+
+	Input pins:
+		input (CTypeAny)
+
+	Output pins:
+		one or more of type CTypeAny named with a number starting from 1
+
+	Command line:
+		[-o <num>] (= 1) number of outputs (from 1 to 100)
+*/
+
+class Split : public CComponentAdapter {
+public:
+	static const char* getTypeName() { return "split"; }
+	virtual const char* GetTypeName() const { return Split::getTypeName(); }
+    Split(const char * name, int argc, const char * argv[]) 
+	: CComponentAdapter(name, argc, argv) {
+		// Input pins
+  		if (RegisterInputPin(*SmartPtr<InputPinData>(new InputPinData("input", *this), false))!= 0)
+			throw std::runtime_error("error creating input pin");
+
+		// Parses command line
+		int output_count= 1;
+		if (argc) {
+			int i= 0;
+			for (; i< argc; ++i) if (strcmp("-o", argv[i])== 0) break;
+			if (i< argc) {
+				++i;
+				if (i>= argc) throw std::runtime_error("Missing value for parameter -o");
+
+				if (!StrToInt(argv[i], &output_count) || output_count< 1 || output_count> 100)
+					throw std::runtime_error("childs component: invalid value for parameter -o");
+			}
+		}
+
+		// Create output pins and permanent instances
+		for (int i= 0; i< output_count; ++i) {
+			// Output pins
+			char buff[10];
+			sprintf (buff, "%d", i+1);
+			SmartPtr<IOutputPin> pin= CTypeAny::CreateOutputPinAny(buff);
+			if (pin.get()== NULL)
+				throw std::runtime_error("error creating output pin");
+
+			if (RegisterOutputPin(*pin)!= 0)
+				throw std::runtime_error("error registering output pin");
+
+			// Permanent instances
+			m_outputInstances.push_back(SmartPtr<CTypeAny>());
+		}
+	}
+
+	void ForwardChildren (const CTypeAny & message) {
+
+		SmartPtr<IIterator<CTypeAny*> > it_children= message.QueryChildren();
+		if (it_children.get()== NULL) return;
+
+		SmartPtr<IIterator<IOutputPin*> > it_opins= this->GetOutputPins();
+		std::vector<SmartPtr<CTypeAny> >::iterator it_instances= m_outputInstances.begin();
+
+		while (!it_children->IsDone() && !it_opins->IsDone() && it_instances!= m_outputInstances.end()) {
+			// Copy instances
+			(*it_instances)= it_children->CurrentItem()->Clone((*it_instances).get(), true);
+
+			// Send
+			it_opins->CurrentItem()->Send((*it_instances));
+
+			// Advance iterators
+			it_children->Next();
+			it_opins->Next();
+			++it_instances;
+		}
+	}
+
+private:
+	virtual ~Split() {}
+
+	class InputPinData : public CInputPinWriteOnly<CTypeAny, Split > {
+	public:
+		InputPinData (const char * name, Split & component)
+		: CInputPinWriteOnly<CTypeAny, Split >(name, component) {}
+
+		virtual int DoSend(const CTypeAny & message) {
+			this->m_component->ForwardChildren (message);
+			return 0;
+		}
+	};
+
+	std::vector<SmartPtr<CTypeAny> > m_outputInstances;
+};
+
+typedef ComponentFactory<Split> SplitFactory;
+
+/**
+fthreshold component - Threshold component
+
+	Sends a value to the output pin taking into account if the input
+	value is below or above the threshold.		
+
+Input pins:
+	value (CTypeFloat)
+	thres (CTypeFloat)
+
+Output pins:
+	result (CTypeFloat)
+
+Command line:
+	[-a (orig|<value>)]	(default 1)
+	
+		Above value. Sets the value which will be sent to the output
+		when the input value is above the threshold. 
+		"orig" sends the input value as is.
+		"orig_minus_thres" sends the input value minus the threshold
+	
+	[-b (orig|<value>)]	(default 0)
+
+		Below value. Sets the value which will be sent to the output
+		when the input value is below the threshold. 
+		"orig" sends the input value as is.
+		"orig_minus_thres" sends the input value minus the threshold
+
+	[-t <value>] (default 0)
+
+		Set threshold.
+*/
+
+class FThreshold : public CComponentAdapter {
+public:
+	enum EThresholdMode { FIXED= 0, ORIG, ORIG_MINUS_THRES };
+
+	static const char* getTypeName() { return "fthreshold"; }
+	virtual const char* GetTypeName() const { return FThreshold::getTypeName(); }
+    FThreshold(const char * name, int argc, const char * argv[]) 
+	: CComponentAdapter(name, argc, argv)
+	, m_threshold(0)
+	, m_belowMode(FIXED)
+	, m_aboveMode(FIXED)
+	, m_belowValue(0)
+	, m_aboveValue(1.0f)
+	{
+		// Pins
+  		RegisterInputPin(*SmartPtr<IInputPin>(new InputPinValue("value", *this), false));
+		RegisterInputPin(*SmartPtr<IInputPin>(new InputPinThreshold("thres", *this), false));
+		m_oPin= CTypeFloat::CreateOutputPin("result");
+		RegisterOutputPin(*m_oPin);
+
+		// Result value
+		m_result= CTypeFloat::CreateInstance();
+
+		// Parse command line
+		if (argc) {
+			for (int i= 0; i< argc; ++i) {
+				if (strcmp ("-t", argv[i])== 0) {
+					++i;
+					if (i== argc || !StrToFloat(argv[i], &m_threshold))
+						throw std::runtime_error(string(FThreshold::getTypeName()) + ". Wrong value for option -t");
+				}
+				else if (strcmp ("-a", argv[i])== 0) {
+					++i;
+					bool err= false;
+					if (i== argc) err= true;
+					else {
+						if (strcmp("orig", argv[i])== 0) 
+							m_aboveMode= ORIG;
+						else if (strcmp("orig_minus_thres", argv[i])== 0) 
+							m_aboveMode= ORIG_MINUS_THRES;
+						else if (!StrToFloat(argv[i], &m_aboveValue)) 
+							err= true;
+					}
+					if (err) 
+						throw std::runtime_error(string(FThreshold::getTypeName()) + ". Wrong value for option -a");
+				}
+				else if (strcmp ("-b", argv[i])== 0) {
+					++i;
+					bool err= false;
+					if (i== argc) err= true;
+					else {
+						if (strcmp("orig", argv[i])== 0) 
+							m_belowMode= ORIG;
+						else if (strcmp("orig_minus_thres", argv[i])== 0) 
+							m_belowMode= ORIG_MINUS_THRES;
+						else if (!StrToFloat(argv[i], &m_belowValue)) 
+							err= true;
+					}
+					if (err) 
+						throw std::runtime_error(string(FThreshold::getTypeName()) + ". Wrong value for option -b");
+				}
+				else if (strlen(argv[i]))
+					throw std::runtime_error(string(FThreshold::getTypeName()) + ". Unknown option.");
+			}
+		}
+	}
+
+	void OnValue (const CTypeFloat & msg) {
+		float val= msg.getValue();
+
+		if (val< m_threshold) {
+			switch (m_belowMode) {
+				case FIXED: 
+					m_result->setValue(m_belowValue); 
+					break;
+				case ORIG:
+					m_result->setValue(val);
+					break;
+				case ORIG_MINUS_THRES:
+					m_result->setValue(val - m_threshold);
+					break;
+				default:
+					assert (false);
+			}
+		}
+		else {
+			switch (m_aboveMode) {
+				case FIXED: 
+					m_result->setValue(m_aboveValue); 
+					break;
+				case ORIG:
+					m_result->setValue(val);
+					break;
+				case ORIG_MINUS_THRES:
+					m_result->setValue(val - m_threshold);
+					break;
+				default:
+					assert (false);
+			}
+		}
+
+		m_oPin->Send(m_result);
+	}
+
+	void OnThreshold (const CTypeFloat & msg) {
+		m_threshold= msg.getValue();	
+	}
+
+private:
+	virtual ~FThreshold() {}
+
+	class InputPinValue : public CInputPinWriteOnly<CTypeFloat, FThreshold > {
+	public:
+		InputPinValue (const char * name, FThreshold & component)
+		: CInputPinWriteOnly<CTypeFloat, FThreshold >(name, component) {}
+
+		virtual int DoSend(const CTypeFloat & message) {
+			this->m_component->OnValue (message);
+			return 0;
+		}
+	};
+
+	class InputPinThreshold : public CInputPinWriteOnly<CTypeFloat, FThreshold > {
+	public:
+		InputPinThreshold (const char * name, FThreshold & component)
+		: CInputPinWriteOnly<CTypeFloat, FThreshold >(name, component) {}
+
+		virtual int DoSend(const CTypeFloat & message) {
+			this->m_component->OnThreshold (message);
+			return 0;
+		}
+	};
+
+	float m_threshold;
+	EThresholdMode m_belowMode;
+	EThresholdMode m_aboveMode;
+	float m_belowValue;
+	float m_aboveValue;
+
+	SmartPtr<IOutputPin> m_oPin;
+	SmartPtr<CTypeFloat> m_result;
+};
+
+typedef ComponentFactory<FThreshold> FThresholdFactory;
+
+/**
+	faccum component - Accumulator component
+
+		Accumulates the value received in the pin 'val' and sends
+		the result to the 'result' pin.
+
+	Input pins:
+		val (CTypeFloat)
+
+	Output pins:
+		result (CTypeFloat)
+
+	Command line:
+		[--min <num>]	(= 0) minimum limit
+		[--max <num>]	(= 1) maximum limit
+		[-w]			(= false) wrap value
+*/
+class FAccumulator : public CComponentAdapter {
+public:
+	static const char* getTypeName() { return "faccum"; }
+	virtual const char* GetTypeName() const { return FAccumulator::getTypeName(); }
+    FAccumulator(const char * name, int argc, const char * argv[]) 
+	: CComponentAdapter(name, argc, argv)
+	, m_wrap(false)
+	, m_offset(0)
+	, m_max(1.0f)
+	, m_current(0)	
+	{
+		// Input pins
+  		if (RegisterInputPin(*SmartPtr<InputPinVal>(new InputPinVal("val", *this), false))!= 0)
+			throw std::runtime_error("error creating input pin");		
+
+		m_oPin= CTypeFloat::CreateOutputPin("result");
+		if (RegisterOutputPin(*m_oPin)!= 0)
+			throw std::runtime_error("error registering output pin");
+
+		m_result= CTypeFloat::CreateInstance();
+
+		float min= 0, max= 1.0f;
+
+		// Parse command line
+		if (argc) {
+			for (int i= 0; i< argc; ++i) {
+				if (strcmp ("--min", argv[i])== 0) {
+					// Min
+					++i;
+					if (i== argc || !StrToFloat(argv[i], &min))
+						throw std::runtime_error("flimit. Wrong value for option --min");
+				}
+				else if (strcmp ("--max", argv[i])== 0) {
+					// Max
+					++i;
+					if (i== argc || !StrToFloat(argv[i], &max))
+						throw std::runtime_error("flimit. Wrong value for option --max");
+				}
+				else if (strcmp ("-w", argv[i])== 0) {
+					// Wrap value
+					m_wrap= true;					
+				}
+				else if (strlen(argv[i]))
+					throw std::runtime_error("flimit. Unknown option.");
+			}
+		}
+
+		if (min>= max)
+			throw std::runtime_error("flimit. min cannot be greater or equal than max");
+
+		// Compute interval range values. All operations are 0 based and then an offset is applied
+		m_offset= min;
+		m_max= max - min;
+	}
+
+	void OnValue (const CTypeFloat & msg) {
+		m_current+= msg.getValue();
+
+		if (m_wrap) {
+			if (m_current< 0) m_current= m_max + fmodf(m_current, m_max);
+			else if (m_current> m_max) m_current= fmodf(m_current, m_max);
+		}
+		else {
+			if (m_current< 0) m_current= 0;
+			else if (m_current> m_max) m_current= m_max;
+		}
+
+		assert (m_current>= 0 && m_current<= m_max);
+
+		m_result->setValue(m_current + m_offset);
+		m_oPin->Send(m_result);
+	}
+
+private:
+	virtual ~FAccumulator() {}
+
+	class InputPinVal : public CInputPinWriteOnly<CTypeFloat, FAccumulator > {
+	public:
+		InputPinVal (const char * name, FAccumulator & component)
+		: CInputPinWriteOnly<CTypeFloat, FAccumulator >(name, component) {}
+
+		virtual int DoSend(const CTypeFloat & message) {
+			this->m_component->OnValue (message);
+			return 0;
+		}
+	};
+
+	bool m_wrap;
+	float m_offset;
+	float m_max;
+	float m_current;
+	SmartPtr<IOutputPin> m_oPin;
+	SmartPtr<CTypeFloat> m_result;
+};
+
+typedef ComponentFactory<FAccumulator> FAccumulatorFactory;
+
+
+
+
+/**
+	flimit component - Limit component (float)
+
+		Limits the value within a specific range
+
+	Input pins:
+		in (CTypeFloat)
+
+	Output pins:
+		out (CTypeFloat)
+
+	Command line:
+		[--min <num>] (= 0) minimum limit
+		[--max <num>] (= 1) maximum limit
+*/
+class FLimit : public CComponentAdapter {
+public:
+	static const char* getTypeName() { return "flimit"; }
+	virtual const char* GetTypeName() const { return FLimit::getTypeName(); }
+    FLimit(const char * name, int argc, const char * argv[]) 
+	: CComponentAdapter(name, argc, argv) 
+	, m_min(0)
+	, m_max(1.0f) 
+	{
+		m_opin= CTypeFloat::CreateOutputPinAny("out");
+		if (RegisterOutputPin(*m_opin)!= 0)
+			throw std::runtime_error("error registering output pin");
+
+  		if (RegisterInputPin(*SmartPtr<IInputPin>(new InputPinVal("in", *this), false))!= 0)
+			throw std::runtime_error("error creating input pin");
+		
+		m_result= CTypeFloat::CreateInstance();
+
+		// Parse command line
+		if (argc) {
+			for (int i= 0; i< argc; ++i) {
+				if (strcmp ("--min", argv[i])== 0) {
+					// Min
+					++i;
+					if (i== argc || !StrToFloat(argv[i], &m_min))
+						throw std::runtime_error("flimit. Wrong value for option --min");
+				}
+				else if (strcmp ("--max", argv[i])== 0) {
+					// Max
+					++i;
+					if (i== argc || !StrToFloat(argv[i], &m_max))
+						throw std::runtime_error("flimit. Wrong value for option --max");
+				}
+				else if (strlen(argv[i]))
+					throw std::runtime_error("flimit. Unknown option.");
+			}
+		}
+
+		if (m_min> m_max)
+			throw std::runtime_error("flimit. min cannot be greater than max");
+	}
+
+	int OnValue(const CTypeFloat & message) {
+		float v= message.getValue();
+		if (v> m_max) v= m_max;
+		else if (v< m_min) v= m_min;
+		m_result->setValue (v);
+		return m_opin->Send (m_result);
+	}
+
+private:
+	virtual ~FLimit() {}
+
+	class InputPinVal : public CInputPinWriteOnly<CTypeFloat, FLimit > {
+	public:
+		InputPinVal (const char * name, FLimit & component)
+		: CInputPinWriteOnly<CTypeFloat, FLimit>(name, component) {}
+
+		virtual int DoSend(const CTypeFloat & message) {
+			return this->m_component->OnValue (message);			
+		}
+	};
+
+	float m_min;
+	float m_max;
+	SmartPtr<CTypeFloat> m_result;
+	SmartPtr<IOutputPin> m_opin;
+};
+
+typedef ComponentFactory<FLimit> FLimitFactory;
+
+/*!
+	forward component - Forward component
+
+		Forwards a message comming from the input pin to the output pin		
+
+	Input pins:
+		in (any)
+		gate (bool)
+
+	Output pins:
+		out (any)
+*/
+class ForwardComponent : public CComponentAdapter {
+public:
+	static const char* getTypeName() { return "forward"; }
+	virtual const char* GetTypeName() const { return ForwardComponent::getTypeName(); }
+    ForwardComponent(const char * name, int argc, const char * argv[]) 
+	: CComponentAdapter(name, argc, argv) {
+		
+		m_opin= CTypeAny::CreateOutputPinAny("out");
+		if (RegisterOutputPin(*m_opin)!= 0)
+			throw std::runtime_error("error registering output pin");
+
+		SmartPtr<InputPinIn> pinIn= SmartPtr<InputPinIn>(new InputPinIn("in", *m_opin), false);
+
+  		if (RegisterInputPin(*pinIn)!= 0)
+			throw std::runtime_error("error creating input pin");
+
+		if (RegisterInputPin(*SmartPtr<IInputPin>(new InputPinGate("gate", *pinIn), false))!= 0)
+			throw std::runtime_error("error creating input pin");
+	}
+
+private:
+	virtual ~ForwardComponent() {}
+
+	class InputPinIn : public CInputPinWriteOnly<CTypeAny, IOutputPin> {
+	public:
+		InputPinIn (const char * name, IOutputPin & component)
+		: CInputPinWriteOnly<CTypeAny, IOutputPin>(name, component)
+		, m_gate(true)
+		{
+		}
+
+		virtual int DoSend(const CTypeAny & message) {
+			if (m_gate)
+				return this->m_component->Send (SmartPtr<const CTypeAny>(&message));
+			else
+				return 0;
+		}
+
+		bool m_gate;
+	};
+
+	class InputPinGate : public CInputPinWriteOnly<CTypeBool, InputPinIn> {
+	public:
+		InputPinGate (const char * name, InputPinIn & component)
+		: CInputPinWriteOnly<CTypeBool, InputPinIn>(name, component) 
+		{
+
+		}
+
+		virtual int DoSend(const CTypeBool & message) {
+			return this->m_component->m_gate= message.getValue();
+		}
+	};
+
+	SmartPtr<IOutputPin> m_opin;
+};
+
+typedef ComponentFactory<ForwardComponent> ForwardComponentFactory;
+
+/**
+	freductor component - Reductor component (float)
+		
+		Allows to reduce the number of message of type float to a half, 
+		a third, etc. according to the supplied parameter. 
+		Intermediate values are  accumulated or averaged.
+
+	Input pins:
+		in (CTypeAny)
+
+	Output pins:
+		out (CTypeAny)
+
+	Command line
+		[- r <val> ] (= 1)	reduction (integer)
+		[-a ] average values. if this flag is not present, values accumulated
+*/
+class FReductor : public CComponentAdapter {
+public:
+	static const char* getTypeName() { return "freductor"; }
+	virtual const char* GetTypeName() const { return FReductor::getTypeName(); }
+	FReductor(const char * name, int argc, const char * argv[]) 
+	: CComponentAdapter(name, argc, argv)
+	, m_average(false)
+	, m_reduction(1)
+	, m_freduction(1.0f)
+	, m_msgCount(0)
+	{
+		m_opin= CTypeFloat::CreateOutputPin("out");
+		if (RegisterOutputPin(*m_opin)!= 0)
+			throw std::runtime_error("error registering output pin");
+
+  		if (RegisterInputPin(*SmartPtr<IInputPin>(new InputPinIn("in", *this), false))!= 0)
+			throw std::runtime_error("error creating input pin");
+
+		// Parse command line
+		if (argc) {
+			for (int i= 0; i< argc; ++i) {
+				if (strcmp ("-r", argv[i])== 0) {
+					++i;
+					if (i== argc || !StrToUint(argv[i], &m_reduction) || !m_reduction)
+						throw std::runtime_error("freductor. Wrong value for option -r");
+					
+					m_freduction= static_cast<float>(m_reduction);
+				}
+				else if (strcmp ("-a", argv[i])== 0) m_average= true;
+				else if (strlen(argv[i]))
+					throw std::runtime_error("flimit. Unknown option.");
+			}
+		}
+
+		m_result= CTypeFloat::CreateInstance();
+	}
+
+	int OnMessage (const CTypeFloat & message) {
+		if (!m_msgCount++) m_accum= message.getValue();
+		else m_accum+= message.getValue();
+
+		if (m_msgCount== m_reduction) {
+			if (m_average) m_accum/= m_freduction;
+			m_result->setValue(m_accum);
+			m_msgCount= 0;
+			return this->m_opin->Send (m_result);
+		}
+		return 0;
+	}
+
+private:
+	virtual ~FReductor() {}
+
+	class InputPinIn : public CInputPinWriteOnly<CTypeFloat, FReductor> {
+	public:
+		InputPinIn (const char * name, FReductor & component)
+		: CInputPinWriteOnly<CTypeFloat, FReductor>(name, component) 
+		{
+		}
+
+		virtual int DoSend(const CTypeFloat & message) {
+			return this->m_component->OnMessage(message);
+		}
+	};
+	bool m_average;
+	unsigned int m_reduction;
+	float m_freduction;
+	float m_accum;
+	unsigned int m_msgCount;
+	SmartPtr<IOutputPin> m_opin;
+	SmartPtr<CTypeFloat> m_result;
+
+};
+
+typedef ComponentFactory<FReductor> FReductorFactory;
+
+
+/**
+	send_main_sync
+
+		Sends a message synchronously thorugh the main thread
+
+	Input pins:
+		in (CTypeAny)
+
+	Output pins:
+		out (CTypeAny)
+*/
+static void CallbackSync (IComponent* compo, const CTypeAny* msg);
+
+class SendMainSync : public CComponentAdapter {
+public:
+	static const char* getTypeName() { return "send_main_sync"; }
+	virtual const char* GetTypeName() const { return SendMainSync::getTypeName(); }
+
+    SendMainSync(const char * name, int argc, const char * argv[]) 
+	: CComponentAdapter(name, argc, argv)
+	, m_threadWaiting(false)
+	, m_running(false)
+	, m_result(-1)
+	{
+		// Output pin
+		m_oPin= CTypeAny::CreateOutputPinAny("out");			
+		if (RegisterOutputPin(*m_oPin)!= 0)
+			throw std::runtime_error("error registering output pin");
+		
+		// Input pin
+  		if (RegisterInputPin(*SmartPtr<IInputPin>(new InputPinAny("in", *this), false))!= 0)
+			throw std::runtime_error("error creating input pin");
+
+		m_cr= getSpCoreRuntime();
+	}
+
+	virtual bool ProvidesExecThread() const { return true; }
+
+	virtual int DoStart() {
+		assert (m_cr->IsMainThread());
+
+		boost::mutex::scoped_lock (m_mutex);
+
+		m_running= true;
+		return 0;
+	}
+   
+	virtual void DoStop() {
+		assert (m_cr->IsMainThread());
+
+		boost::mutex::scoped_lock lock(m_mutex);
+
+		if (m_running) {
+			m_running= false;
+			if (m_threadWaiting) {
+				// Secondary thread is waiting so receiver has not 
+				// processed the message yet => awake it
+				m_condition.notify_one();
+			}
+		}
+	}
+
+	int OnSendReceived (const CTypeAny& msg) {
+		// We don't expect messages comming from the main thread, but if someone
+		// has connected this component when not is needed, just forward the message
+		assert (!m_cr->IsMainThread());
+		if (m_cr->IsMainThread()) return m_oPin->Send (SmartPtr<const CTypeAny>(&msg));
+	
+		boost::mutex::scoped_lock lock(m_mutex);
+
+		if (!m_running) return 0;
+
+		// If there are pending messages means that someone
+		// connected more than one ouput to our input pin
+		assert (!m_threadWaiting);
+		if (m_threadWaiting) return -1;
+
+		m_threadWaiting= true;
+		m_cr->SendMessageMainThreadAsync (msg, *this, CallbackSync);
+		
+		// Wait until request is completed		
+		m_condition.wait(lock);
+
+		m_threadWaiting= false;
+
+		return m_result;		
+	}
+
+	void OnCallbackReceived(const CTypeAny& msg) {
+		assert (m_cr->IsMainThread());
+		
+		boost::mutex::scoped_lock lock(m_mutex);
+
+		if (m_threadWaiting) {
+			if (m_running) 
+				m_result= m_oPin->Send (SmartPtr<const CTypeAny>(&msg));
+			else
+				m_result= -1;
+			m_condition.notify_one();
+		}
+		else {
+			m_result= -1;
+#ifndef NDEBUG		
+			m_cr->LogMessage (ICoreRuntime::LOG_DEBUG, "message discarded", SendMainSync::getTypeName());
+#endif
+		}
+	}
+
+private:
+	bool m_threadWaiting;
+	bool m_running;
+	int m_result;
+	boost::mutex m_mutex;
+	boost::condition m_condition;	
+	SmartPtr<IOutputPin> m_oPin;
+	ICoreRuntime* m_cr;
+	
+	virtual ~SendMainSync() {
+		// Before destructing this object must have been stopped
+		assert (!m_running);
+
+		// Finished receiving input pin calls
+		assert (!m_threadWaiting);
+		
+		//	Stop();
+	}
+
+	class InputPinAny : public CInputPinWriteOnly<CTypeAny, SendMainSync > {
+	public:
+		InputPinAny (const char * name, SendMainSync & component)
+		: CInputPinWriteOnly<CTypeAny, SendMainSync >(name, component) {}
+
+		virtual int DoSend(const CTypeAny & msg) {
+			return  m_component->OnSendReceived (msg);			
+		}	
+	};
+};
+
+typedef ComponentFactory<SendMainSync> SendMainSyncFactory;
+
+static void CallbackSync (IComponent* compo, const CTypeAny* msg)
+{
+	static_cast<SendMainSync*>(compo)->OnCallbackReceived(*msg);	
+}
+
+
+/**
+	send_main_async
+
+		Sends a message asynchronously thorugh the main thread
+
+	Input pins:
+		in (CTypeAny)
+
+	Output pins:
+		out (CTypeAny)
+*/
+static void CallbackAsync (IComponent* compo, const CTypeAny* msg);
+
+class SendMainAsync : public CComponentAdapter {
+public:
+	static const char* getTypeName() { return "send_main_async"; }
+	virtual const char* GetTypeName() const { return SendMainAsync::getTypeName(); }
+
+    SendMainAsync(const char * name, int argc, const char * argv[]) 
+	: CComponentAdapter(name, argc, argv)
+	, m_pendingMessage(false)
+	, m_running(false)
+	{
+		// Output pin
+		m_oPin= CTypeAny::CreateOutputPinAny("out");			
+		if (RegisterOutputPin(*m_oPin)!= 0)
+			throw std::runtime_error("error registering output pin");
+		
+		// Input pin
+  		if (RegisterInputPin(*SmartPtr<IInputPin>(new InputPinAny("in", *this), false))!= 0)
+			throw std::runtime_error("error creating input pin");
+
+		m_cr= getSpCoreRuntime();
+	}
+
+	virtual bool ProvidesExecThread() const { return true; }
+
+	virtual int DoStart() {
+		m_running= true;
+		return 0;
+	}
+   
+	virtual void DoStop() { m_running= false; }
+
+	int OnSendReceived (const CTypeAny& msg) {
+		// If no listeners, do nothing
+		if (m_oPin->GetNumComsumers()== 0) return 0;
+
+		// We don't expect messages comming from the main thread, but if someone
+		// has connected this component when not is needed, just forward the message
+		assert (!m_cr->IsMainThread());
+		if (m_cr->IsMainThread()) return m_oPin->Send (SmartPtr<const CTypeAny>(&msg));
+		
+		if (!m_running) return 0;
+
+		{
+			boost::mutex::scoped_lock (m_mutex);
+			// Message pending, discard current one
+			if (m_pendingMessage) {
+#ifndef NDEBUG
+				m_cr->LogMessage (ICoreRuntime::LOG_DEBUG, "message discarded", SendMainAsync::getTypeName());
+#endif
+				return 0;
+			}
+			m_pendingMessage= true;
+		}
+
+		//
+		// TODO: embed the information about if the type follows the "fire-and-forget"
+		// approach or not. Currently it checks the know types by name.
+		//
+		// Currently instances of:
+		//	CTypeInt
+		//	CTypeFloat
+		//	CTypeBool
+		//	CtypeString
+		//	CTypeROI
+		//
+		// need to be copied. Instances of:
+		//
+		// CTypeIplImage
+		//
+		// need not to be copied, and instances of
+		//
+		// CTypeSDLSurface are not supported (in fact Clone method will fail)	 
+		//
+		static int ipl_img_id= m_cr->ResolveTypeID("iplimage");
+		if (msg.GetTypeID()== ipl_img_id) 
+			// img, Just send
+			m_cr->SendMessageMainThreadAsync (msg, *this, CallbackAsync);
+		else {
+			// Copy and send
+			m_message= msg.Clone(m_message.get(), true);
+			m_cr->SendMessageMainThreadAsync (*m_message, *this, CallbackAsync);
+		}
+		return 0;
+	}
+
+	void OnCallbackReceived(const CTypeAny& msg) {
+		//assert (msg->GetTypeID()== CTypeIplImage::getTypeID());
+		assert (m_cr->IsMainThread());
+		if (m_running) m_oPin->Send (SmartPtr<const CTypeAny>(&msg));
+		m_pendingMessage= false;
+	}
+
+private:
+	bool m_pendingMessage;
+	bool m_running;
+	boost::mutex m_mutex;
+	SmartPtr<IOutputPin> m_oPin;
+	ICoreRuntime* m_cr;
+	SmartPtr<CTypeAny> m_message;
+	
+	virtual ~SendMainAsync() {
+		Stop();
+	}
+
+	class InputPinAny : public CInputPinWriteOnly<CTypeAny, SendMainAsync > {
+	public:
+		InputPinAny (const char * name, SendMainAsync & component)
+		: CInputPinWriteOnly<CTypeAny, SendMainAsync >(name, component) {}
+
+		virtual int DoSend(const CTypeAny & msg) {
+			return  m_component->OnSendReceived (msg);			
+		}	
+	};
+};
+
+typedef ComponentFactory<SendMainAsync> SendMainAsyncFactory;
+
+static void CallbackAsync (IComponent* compo, const CTypeAny* msg)
+{
+	static_cast<SendMainAsync*>(compo)->OnCallbackReceived(*msg);	
+}
+
+
+/**
+	print component - Dumps the contents of the type instance
+		
+	Input pins:
+		in (CTypeAny)
+
+	Command line
+*/
+class PrintComponent : public CComponentAdapter {
+public:
+	static const char* getTypeName() { return "print"; }
+	virtual const char* GetTypeName() const { return PrintComponent::getTypeName(); }
+	PrintComponent(const char * name, int argc, const char * argv[]) 
+	: CComponentAdapter(name, argc, argv)	
+	{
+		if (RegisterInputPin(*SmartPtr<IInputPin>(new InputPinIn("in", *this), false))!= 0)
+			throw std::runtime_error("error creating input pin");
+
+		// Dump arguments
+		if (argc) {
+			stringstream ss;
+			ss << "Arguments dump. argc: " << argc << "\t";
+			for (int i= 0; i< argc; ++i) {
+				ss << "argv[" << i << "]: \"" << argv[i] << "\" ";
+			}
+			getSpCoreRuntime()->LogMessage(ICoreRuntime::LOG_INFO, ss.str().c_str(), name);
+		}
+	}
+
+private:
+	virtual ~PrintComponent() {}
+
+	class InputPinIn : public CInputPinWriteOnly<CTypeAny, PrintComponent> {
+	public:
+		InputPinIn (const char * name, PrintComponent & component)
+		: CInputPinWriteOnly<CTypeAny, PrintComponent>(name, component) 
+		{
+		}
+
+		void PrintInt (ostream& s, int val)
+		{
+			s << "\tint: " << val;
+		}
+
+		void PrintBool (ostream& s, bool val)
+		{
+			s << "\tbool: " << val;
+		}
+
+		void PrintFloat (ostream& s, float val)
+		{
+			s << "\tfloat: " << val;
+		}
+
+		void PrintString (ostream& s, const char* val)
+		{
+			s << "\tstring: " << val;
+		}
+
+		void PrintInstance (ostream& s, const CTypeAny & val)
+		{
+			int tid= val.GetTypeID();
+			if (tid== CTypeFloat::getTypeID()) 
+				PrintFloat(s, sptype_static_cast<CTypeFloat>(&val)->getValue());
+			else if (tid== CTypeInt::getTypeID()) 
+				PrintInt(s, sptype_static_cast<CTypeInt>(&val)->getValue());
+			else if (tid== CTypeBool::getTypeID()) 
+				PrintBool(s, sptype_static_cast<CTypeBool>(&val)->getValue());
+			else if (tid== CTypeString::getTypeID()) 
+				PrintString(s, sptype_static_cast<CTypeString>(&val)->getValue());
+			else 
+				s << "\tnon-printable:" << val.GetTypeID();
+
+			// Recurse children
+			SmartPtr<IIterator<CTypeAny *> > it= val.QueryChildren();
+			if (it.get()) {
+				s << "composite {";
+				for (; !it->IsDone(); it->Next()) {
+					PrintInstance (s, *(it->CurrentItem()));
+					s << ", ";
+				}
+				s << "}";
+			}
+		}
+
+
+		virtual int DoSend(const CTypeAny & message) {
+			stringstream ss;
+
+			PrintInstance (ss, message);
+
+			getSpCoreRuntime()->LogMessage(ICoreRuntime::LOG_INFO, ss.str().c_str(), m_component->GetName());
+
+			return 0;
+		}
+	};
+};
+
+typedef ComponentFactory<PrintComponent> PrintComponentFactory;
+
+} // namespace spcore
diff --git a/src/core/configurationimpl.h b/src/core/configurationimpl.h
new file mode 100755
index 0000000..606f2b2
--- /dev/null
+++ b/src/core/configurationimpl.h
@@ -0,0 +1,343 @@
+/////////////////////////////////////////////////////////////////////////////
+// File:        configurationimpl.h
+// Author:      Cesar Mauri Loba (cesar at crea-si dot com)
+// Copyright:   (C) 2010-11 Cesar Mauri Loba - CREA Software Systems
+//
+//  This program is free software: you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation, either version 3 of the License, or
+//  (at your option) any later version.
+//
+//  This program is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+/////////////////////////////////////////////////////////////////////////////
+#ifdef SPCORE_CONFIGURATIONIMPL_H
+#error __FILE__ included twice
+#endif
+
+#define SPCORE_CONFIGURATIONIMPL_H
+
+#include "spcore/configuration.h"
+#include "libconfig.h"
+#include "spcore/coreruntime.h"
+
+#include <string>
+
+#ifdef WIN32
+// TODO: remove the following line when boost gets updated
+// See: https://svn.boost.org/trac/boost/ticket/4649
+#pragma warning (disable:4127)
+#endif
+#include <boost/tokenizer.hpp>
+#include <boost/foreach.hpp>
+#include <boost/static_assert.hpp>
+
+namespace spcore {
+
+/**
+	Configuration implementation based on libconfig
+**/
+class ConfigurationLibconfig : public IConfiguration {
+protected:
+	virtual ~ConfigurationLibconfig() {
+		config_destroy (&m_config);
+	}
+
+public:
+	// Constructor
+	ConfigurationLibconfig() {
+		config_init (&m_config);
+	}
+	
+	virtual bool Load (FILE* instream) {
+		int retval= config_read (&m_config, instream);
+		
+		if (retval== CONFIG_FALSE) {
+			getSpCoreRuntime()->LogMessage(
+				ICoreRuntime::LOG_ERROR, config_error_text(&m_config), "configuration load");
+			return false;
+		}
+		return true;
+	}
+	
+	virtual bool Save (FILE* outstream) const {
+		config_write (&m_config, outstream);
+
+		return true;
+	}
+
+private:
+	static
+	bool IsSane(const char* path) {
+		assert (path);
+		while (	(*path>= 'a' && *path<= 'z') ||
+				(*path>= 'A' && *path<= 'Z') ||
+				(*path>= '0' && *path<= '9') ||
+				*path== '-' || *path== '_' || *path== '/' )
+
+				++path;
+
+		return (*path== 0);
+	}
+
+	// Get effective path given an absolute path, relative path or '..'.
+	// Return true if successful
+	bool GetEffectivePathTranslate(const char* src, std::string& path) const {
+		if (!src || !*src) return false;
+
+		if (strcmp(src, "..")== 0) {
+			size_t dotpos= m_currentPath.find_last_of('.');
+			if (dotpos== std::string::npos) {
+				// Not found
+				if (!m_currentPath.empty())
+					path.clear();
+				else
+					// Already in the root path
+					return false;
+			}
+			else
+				path= m_currentPath.substr(0, dotpos);
+			return true;
+		}
+		if (!IsSane(src)) return false;
+
+		if (src[0]== '/') {
+			// Absolute path
+			
+			// Ignore slashes at the begining
+			for (++src; *src== '/'; ++src);
+
+			path= src;
+		}
+		else {
+			// Relative path
+			path= m_currentPath + '.';
+			path+= src;
+		}
+		
+		// Remove trailing slashes
+		size_t pos= path.find_last_not_of('/');
+		path= path.substr(0, pos + 1);
+
+		// Replace slashes by dots
+		for (size_t i= 0; i< path.size(); ++i) 
+			if (path[i]== '/') path[i]= '.';
+
+		return true;
+	}
+
+public:
+	virtual bool ReadString (const char* path, const char** str) const {
+		std::string epath;
+		if (!GetEffectivePathTranslate(path, epath)) return false;
+		return (config_lookup_string (&m_config, epath.c_str(), str)== CONFIG_TRUE);
+	}
+	
+	virtual bool ReadInt (const char* path, int* i) const {
+		std::string epath;
+		if (!GetEffectivePathTranslate(path, epath)) return false;
+		// Workaround for older versions of libconfig
+#ifdef WIN32
+		return (config_lookup_int (&m_config, epath.c_str(), i)== CONFIG_TRUE);
+#else
+		long tmp;
+		int retval= config_lookup_int (&m_config, epath.c_str(), &tmp);
+		if (retval!= CONFIG_TRUE) return false;
+		*i= (int) tmp;
+		return true;
+#endif
+	}
+	
+	virtual bool ReadInt64 (const char* path, long long* i) const {
+		std::string epath;
+		if (!GetEffectivePathTranslate(path, epath)) return false;
+		return (config_lookup_int64 (&m_config, epath.c_str(), i)== CONFIG_TRUE);
+	}
+	
+	virtual bool ReadDouble (const char* path, double* d) const {
+		std::string epath;
+		if (!GetEffectivePathTranslate(path, epath)) return false;
+		return (config_lookup_float (&m_config, epath.c_str(), d)== CONFIG_TRUE);
+	}
+	
+	virtual bool ReadBool (const char* path, bool* b) const {
+		std::string epath;
+		if (!GetEffectivePathTranslate(path, epath)) return false;
+		int value;
+		if (config_lookup_bool (&m_config, epath.c_str(), &value)== CONFIG_TRUE) {
+			*b= (value? true : false);
+			return true;
+		}
+		return false;
+	}
+
+private:
+
+	
+
+	// Return a pointer to a setting with a given path of a certain type
+	// NULL if the setting already exists and is a group or wrong path
+	config_setting_t* GetCreateScalarSetting (const char* path, int type) {
+		std::string epath;
+		if (!GetEffectivePathTranslate(path, epath)) return NULL;
+		if (epath.empty()) return NULL;
+
+		config_setting_t* cs= config_lookup (&m_config, path);
+		if (cs) {
+			// Setting exists
+
+			// Do not overwrite group!
+			if (config_setting_is_group(cs)) {
+				std::string error_msg= "Setting " + epath;
+				error_msg+= " won't be saved. A group has the same name.";
+				getSpCoreRuntime()->LogMessage(
+					ICoreRuntime::LOG_ERROR, error_msg.c_str(), "configuration");
+				return NULL;
+			}
+
+			// Has the same type?
+			if (config_setting_type (cs)== type) return cs;
+
+			// OK. Is scalar/vector/list an has a different type. Remove and create
+			// a new one of the requested type
+			config_setting_t* parent= config_setting_parent (cs);
+			assert (parent);	// An scalar/vector/list needs a parent
+
+			// Keep setting name
+			const char* cname= config_setting_name (cs);
+			assert (cname);		// Anonymous settings shouldn't exists
+			std::string cnames(cname);
+
+			// Remove child
+			int index= config_setting_index(cs);
+			assert (index>= 0);
+
+			if (config_setting_remove_elem (parent, (unsigned int) index)== CONFIG_FALSE) {
+				assert (false);
+				return NULL;
+			}
+
+			// Add new child
+			cs= config_setting_add (parent, cnames.c_str(), type);
+			if (!cs) {
+				assert (false);
+				return NULL;
+			}
+
+			return cs;
+		}
+		else {
+			// Tokenize path elements
+			std::vector<std::string> tokens;
+			boost::char_separator<char> sep(".");
+			boost::tokenizer<boost::char_separator<char> > tok(epath, sep);	
+			BOOST_FOREACH(std::string t, tok) {
+				tokens.push_back(t);
+			}
+			assert (!tokens.empty());
+
+
+			config_setting_t* parent= config_root_setting (&m_config);
+			config_setting_t* current= NULL;
+
+			// Check and create intermediate paths when needed
+			for (size_t level= 0; level< tokens.size()-1; ++level) {
+				current= config_setting_get_member (parent, tokens[level].c_str());
+				if (!current) {
+					// Does not exists. Create group.
+					current= config_setting_add (parent, tokens[level].c_str(), CONFIG_TYPE_GROUP);
+					assert (current);
+				}
+				else {
+					// Exists. Is not group?
+					if (!config_setting_is_group (current)) return NULL;	// Fail
+				}
+
+				parent= current;
+			}
+
+			// Create leaf setting of the desired type
+#ifndef NDEBUG
+			current= config_setting_get_member (parent, tokens[tokens.size()-1].c_str());
+			assert (!current);
+#endif
+			current= config_setting_add (parent, tokens[tokens.size()-1].c_str(), type);
+			assert (current);
+
+			return current;
+		}
+	}
+
+public:
+	virtual bool WriteString (const char* path, const char* str) {
+		config_setting_t* cs= GetCreateScalarSetting (path, CONFIG_TYPE_STRING);
+		if (!cs) return false;
+		return (config_setting_set_string (cs, str)== CONFIG_TRUE);
+	}
+	
+	virtual bool WriteInt (const char* path, int i) {
+		config_setting_t* cs= GetCreateScalarSetting (path, CONFIG_TYPE_INT);
+		if (!cs) return false;
+		return (config_setting_set_int (cs, i)== CONFIG_TRUE);
+	}
+	
+	virtual bool WriteInt64 (const char* path, long long i) {
+		config_setting_t* cs= GetCreateScalarSetting (path, CONFIG_TYPE_INT64);
+		if (!cs) return false;
+		return (config_setting_set_int64 (cs, i)== CONFIG_TRUE);
+	}
+	
+	virtual bool WriteDouble (const char* path, double d) {
+		config_setting_t* cs= GetCreateScalarSetting (path, CONFIG_TYPE_FLOAT);
+		if (!cs) return false;
+		return (config_setting_set_float (cs, d)== CONFIG_TRUE);
+	}
+	
+	virtual bool WriteBool (const char* path, bool b) {
+		config_setting_t* cs= GetCreateScalarSetting (path, CONFIG_TYPE_BOOL);
+		if (!cs) return false;
+		return (config_setting_set_bool (cs, (int) b)== CONFIG_TRUE);
+	}
+	
+	virtual bool Remove (const char* path) {
+		std::string epath;
+		if (!GetEffectivePathTranslate(path, epath)) return NULL;
+
+		config_setting_t* current= config_lookup (&m_config, path);
+		if (!current) return false;
+
+		int index= config_setting_index (current);
+		if (index< 0) return false;
+
+		config_setting_t* parent= config_setting_parent (current);
+		assert (parent);
+
+		return (config_setting_remove_elem (parent, index)== CONFIG_TRUE);
+	}
+
+	virtual bool SetPath (const char* path) {
+		std::string epath;
+		if (!GetEffectivePathTranslate(path, epath)) return false;
+
+		// New path should point to a group
+		config_setting_t* cs= config_lookup (&m_config, epath.c_str());
+		//if (!cs || !config_setting_is_group(cs)) return false;
+		if (cs && !config_setting_is_group(cs)) return false;
+
+		m_currentPath= epath;
+	
+		return true;
+	}
+
+private:
+
+	config_t m_config;
+	std::string m_currentPath;
+};
+
+} // namespace spcore
diff --git a/src/core/conversion.cpp b/src/core/conversion.cpp
new file mode 100755
index 0000000..1e54115
--- /dev/null
+++ b/src/core/conversion.cpp
@@ -0,0 +1,145 @@
+/////////////////////////////////////////////////////////////////////////////
+// File:        conversion.cpp
+// Author:      Cesar Mauri Loba (cesar at crea-si dot com)
+// Copyright:   (C) 2010 Cesar Mauri Loba - CREA Software Systems
+//
+//  This program is free software: you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation, either version 3 of the License, or
+//  (at your option) any later version.
+//
+//  This program is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+/////////////////////////////////////////////////////////////////////////////
+
+#include "spcore/conversion.h"
+
+#include <locale.h>
+#include <stdio.h>
+
+namespace spcore {
+
+/**
+	Converts a string to a float value in a locale independent fashion
+*/
+
+static char g_decimal_point= 0;
+
+// Assume that 100 is wide enough to hold a decimal number
+#define MAX_NUMBER_SIZE 100
+
+static inline 
+int CopySubsts (const char* orig, char* dst)
+{
+	if (!g_decimal_point) g_decimal_point = *(localeconv()->decimal_point);
+
+	// Copy & substs. Also manages buggy strings
+	int i= 0;
+	for (; i< MAX_NUMBER_SIZE; ++i) {
+		if (orig[i]== 0) {
+			dst[i]= 0;
+			break;
+		}
+		if (orig[i]== '.') 	dst[i]= g_decimal_point;
+		else if (orig[i]== ',') {
+			// Use comma as separator
+			dst[i]= 0;
+			break;
+		}
+		else dst[i]= orig[i];
+	}
+
+	return i;
+}
+
+
+/**
+	Converts a string into a float
+
+	\return true is conversion successful, or false otherwise
+*/
+SPEXPORT_FUNCTION
+bool StrToFloat (const char* str, float* val)
+{
+	char dst[MAX_NUMBER_SIZE];
+	
+	if (CopySubsts (str, dst)== MAX_NUMBER_SIZE) 
+		// Error, too long
+		return false;
+
+	return (sscanf(dst, "%g", val)== 1);
+}
+
+/**
+	Converts a string into a double
+
+	\return true is conversion successful, or false otherwise
+*/
+SPEXPORT_FUNCTION
+bool StrToDouble (const char* str, double* val)
+{
+	char dst[MAX_NUMBER_SIZE];
+	
+	if (CopySubsts (str, dst)== MAX_NUMBER_SIZE) 
+		// Error, too long
+		return false;
+
+	return (sscanf(dst, "%lg", val)== 1);
+}
+
+/**
+	Converts a string into a long double
+
+	\return true is conversion successful, or false otherwise
+*/
+SPEXPORT_FUNCTION
+bool StrToLongDouble (const char* str, long double* val)
+{
+	char dst[MAX_NUMBER_SIZE];
+	
+	if (CopySubsts (str, dst)== MAX_NUMBER_SIZE) 
+		// Error, too long
+		return false;
+
+	return (sscanf(dst, "%Lg", val)== 1);
+}
+
+/**
+	Converts a string into a int
+
+	\return true is conversion successful, or false otherwise
+*/
+SPEXPORT_FUNCTION
+bool StrToInt (const char* str, int* val)
+{
+	return (sscanf(str, "%d", val)== 1);
+}
+
+/**
+	Converts a string into an unsigned int
+
+	\return true is conversion successful, or false otherwise
+*/
+SPEXPORT_FUNCTION 
+bool StrToUint (const char* str, unsigned int* val)
+{
+	return (sscanf(str, "%u", val)== 1);
+}
+
+/**
+	Converts a string into a long
+
+	\return true is conversion successful, or false otherwise
+*/
+SPEXPORT_FUNCTION
+bool StrToLongInt (const char* str, long* val)
+{
+	return (sscanf(str, "%ld", val)== 1);
+}
+
+} // namespace spcore
diff --git a/src/core/coreruntimeimpl.cpp b/src/core/coreruntimeimpl.cpp
new file mode 100644
index 0000000..013a6c3
--- /dev/null
+++ b/src/core/coreruntimeimpl.cpp
@@ -0,0 +1,885 @@
+/////////////////////////////////////////////////////////////////////////////
+// File:        coreruntimeimpl.cpp
+// Author:      Cesar Mauri Loba (cesar at crea-si dot com)
+// Copyright:   (C) 2010-10 Cesar Mauri Loba - CREA Software Systems
+//
+//  This program is free software: you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation, either version 3 of the License, or
+//  (at your option) any later version.
+//
+//  This program is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+/////////////////////////////////////////////////////////////////////////////
+#include "spcore/coreruntime.h"
+#include "spcore/coreversion.h"
+#include "spcore/pinimpl.h"
+#include "spcore/basetype.h"
+#include "spcore/basictypes.h"
+#include "spcore/iterator.h"
+#include "spcore/pin.h"
+#include "spcore/component.h"
+#include "spcore/module.h"
+#include "configurationimpl.h"
+
+
+#include <algorithm>
+#include <iostream>
+#include <Poco/SharedLibrary.h>
+#include <Poco/Exception.h>
+#include <boost/thread.hpp>
+#include <boost/thread/thread.hpp>
+#include <boost/thread/mutex.hpp>
+#include <boost/static_assert.hpp>
+
+#ifdef ENABLE_WXWIDGETS
+#include <wx/app.h>
+#include <wx/image.h>
+#include <wx/event.h>
+#include <errno.h>
+
+using namespace spcore;
+using namespace std;
+
+#ifdef WIN32
+#include <io.h>
+#include <fcntl.h>
+#define pipe(x) _pipe(x,sizeof(int),_O_BINARY)
+#endif
+
+//
+// Custom event to forward secondary threads requests
+//
+DEFINE_EVENT_TYPE( wxEVT_SPCORE_MESSAGE_SYNC )
+
+class SpcoreMessageEventSync : public wxEvent
+{
+public:
+	SpcoreMessageEventSync (SmartPtr<const CTypeAny> msg, IInputPin & destPin, int pipeWrite)
+	: wxEvent (0, wxEVT_SPCORE_MESSAGE_SYNC)
+	, m_message(msg)
+	, m_destPin(&destPin)
+	, m_pipeWrite(pipeWrite)
+	{
+	}
+
+	SmartPtr<const CTypeAny> GetMessage() const { return m_message; }
+	IInputPin & GetInputPin() const { return *m_destPin; }
+	int GetPipeWrite() const { return m_pipeWrite; }
+
+	virtual wxEvent* Clone() const
+	{
+		return new SpcoreMessageEventSync(*this);
+	}
+
+private:
+	SmartPtr<const CTypeAny> m_message;
+	IInputPin * m_destPin;
+	// pipe write end to notify when the request has been completed
+	int m_pipeWrite;
+};
+
+DEFINE_EVENT_TYPE( wxEVT_SPCORE_MESSAGE_ASYNC )
+
+class SpcoreMessageEventAsync : public wxEvent
+{
+public:
+	SpcoreMessageEventAsync (const CTypeAny& msg, IComponent& compo, ICoreRuntime::ToMainThreadCallback* cb)
+	: wxEvent (0, wxEVT_SPCORE_MESSAGE_ASYNC)
+	, m_message(&msg)
+	, m_component(&compo)
+	, m_callback(cb)
+	{
+		assert (cb);
+	}
+
+	const CTypeAny& GetMessage() const { return *m_message; }
+	IComponent& GetComponent() const { return *m_component; }
+	ICoreRuntime::ToMainThreadCallback* GetCallback() const { return m_callback; }
+
+	virtual wxEvent* Clone() const
+	{
+		return new SpcoreMessageEventAsync(*m_message, *m_component, m_callback);
+	}
+
+private:
+	SmartPtr<const CTypeAny> m_message;
+	SmartPtr<IComponent> m_component;
+	ICoreRuntime::ToMainThreadCallback* m_callback;
+};
+
+
+/*
+	To provide support for wxWidgets we need an wxApp object along with
+	a custom filter which also processes internal SITPLUS events
+*/
+
+class SPwxApp: public wxApp
+{
+	DECLARE_CLASS( SPwxApp )
+public:
+	// Constructor
+	SPwxApp() {}
+
+private:
+	virtual bool OnInit() {
+		#if wxUSE_XPM
+			wxImage::AddHandler(new wxXPMHandler);
+		#endif
+		#if wxUSE_LIBPNG
+			wxImage::AddHandler(new wxPNGHandler);
+		#endif
+		#if wxUSE_LIBJPEG
+			wxImage::AddHandler(new wxJPEGHandler);
+		#endif
+		#if wxUSE_GIF
+			wxImage::AddHandler(new wxGIFHandler);
+		#endif
+
+		return wxApp::OnInit();
+		// return true;
+	}
+
+	virtual int FilterEvent (wxEvent& event)
+	{
+		assert (wxThread::IsMain());
+		if (event.GetEventType()== wxEVT_SPCORE_MESSAGE_ASYNC) {
+			SpcoreMessageEventAsync & spevt= static_cast<SpcoreMessageEventAsync &>(event);
+
+			ICoreRuntime::ToMainThreadCallback* callback= spevt.GetCallback();
+
+			callback(&spevt.GetComponent(), &spevt.GetMessage ());
+
+			return true;
+		}
+		else if (event.GetEventType()== wxEVT_SPCORE_MESSAGE_SYNC) {
+
+			// Send the message within the main thread
+			SpcoreMessageEventSync & spevt= static_cast<SpcoreMessageEventSync &>(event);
+			int send_result= spevt.GetInputPin().Send (spevt.GetMessage());
+
+			// send result through the pipe, this also let us to make the secondary
+			// thread until the request is completed
+	write_pipe:
+			int write_result= write (spevt.GetPipeWrite(), &send_result, sizeof(send_result));
+
+			// sizeof(int) means a correctly performed write operation which is
+			// the common case, so just return
+			if (write_result== sizeof(int)) return true;
+
+			// We just accept an interruption of the write operation. Retry.
+			if (write_result== -1 && errno== EINTR) goto write_pipe;
+
+			// In others cases a fatal error occured
+			getSpCoreRuntime()->LogMessage (ICoreRuntime::LOG_FATAL, "unexpected error writing to pipe", "spcore");
+
+			// return true anyway to notify that this event has been processed
+			return true;
+		}
+
+		return -1;
+	}
+};
+
+IMPLEMENT_CLASS( SPwxApp, wxApp )
+
+#endif
+
+namespace spcore {
+
+//
+// Provided component and its factory that allows to compose other components
+//
+class CCompositeComponent : public CCompositeComponentAdapter {
+public:
+    CCompositeComponent(const char * name, int argc, const char * argv[])
+    : CCompositeComponentAdapter(name, argc, argv) {}
+	virtual const char* GetTypeName() const {
+		return CCompositeComponent::getTypeName();
+	}
+	static const char* getTypeName() { return "component_composer"; }
+
+};
+
+class CCompositeComponentFactory : public IComponentFactory {
+public:
+	virtual const char* GetName() const {
+		return CCompositeComponent::getTypeName();
+	}
+	virtual SmartPtr<IComponent> CreateInstance(const char * name, int argc, const char * argv[]) {
+		return  SmartPtr<IComponent>(new CCompositeComponent(name, argc, argv), false);
+	}
+};
+
+//
+// Internal implementation of ICoreRuntime
+//
+class CCoreRuntime : public ICoreRuntime {
+public:
+	CCoreRuntime();
+
+    virtual ~CCoreRuntime();
+
+    virtual int ResolveTypeID(const char * name);
+
+    virtual SmartPtr<IIterator<ITypeFactory*> > QueryTypes();
+
+    virtual SmartPtr<CTypeAny> CreateTypeInstance(const char * typeName);
+
+    virtual SmartPtr<CTypeAny> CreateTypeInstance(int id);
+
+    virtual SmartPtr<IIterator<IComponentFactory*> > QueryComponents();
+
+    virtual SmartPtr<IComponent> CreateComponent(const char * typeName, const char * name, int argc, const char * argv[]);
+
+	virtual SmartPtr<IOutputPin> CreateOutputPin(const char* type, const char* name, bool locked);
+
+    virtual int RegisterModule(SmartPtr<IModule> module);
+
+	virtual int LoadModule(const char * name, const char * dir= NULL);
+
+	virtual void LogMessage (LogSeverityLevel severity, const char* message, const char* module= NULL);
+
+	virtual void RegisterLogTarget (ILogTarget* lt);
+
+	virtual void UnregisterLogTarget (ILogTarget* lt);
+
+	virtual SmartPtr<IConfiguration> GetConfiguration() const {
+		return SmartPtr<IConfiguration>(new ConfigurationLibconfig(), false);
+	}
+
+	virtual bool IsMainThread () const {
+		return (boost::this_thread::get_id()== m_mainThreadId);
+	}
+
+    
+
+#ifdef ENABLE_WXWIDGETS
+	virtual int InitGUISupport (int argc, char** argv) {
+		// Sanity checks
+		assert (wxThread::IsMain());
+		if (m_wxInitialized) {
+			LogMessage (LOG_ERROR, "wxWidgets GUI support already initialized. Ignoring request", "spcore");
+			return 0;
+		}
+
+		// Set our own wxApp implementation
+		wxApp::SetInstance( new SPwxApp() );
+
+		// Initializes wx
+		if (!wxEntryStart( argc, argv )) return -1;
+
+		// Call OnInit
+		wxTheApp->OnInit();
+
+		// wx has been initialized
+		m_wxInitialized= true;
+
+		return 0;
+	}
+
+	virtual int RunMessageLoop () {
+		// Sanity checks
+		assert (m_wxInitialized);
+		assert (wxThread::IsMain());
+		if (!m_wxInitialized) {
+			LogMessage (LOG_FATAL, "wxWidgets GUI support NOT iniatilized", "spcore");
+			return -1;
+		}
+
+		// Run wx main loop. This call does not return until last frame has been closed
+		int retval= wxTheApp->OnRun();
+
+		// Close all open write ends of the pipes to allow threads to continue execution
+		boost::mutex::scoped_lock lock(m_pipeWriteEndMutex);
+		std::vector<int>::iterator it= m_pipeWriteEnd.begin();
+		for (;it!= m_pipeWriteEnd.end(); ++it) close (*it);
+		m_pipeWriteEnd.clear();
+
+		return retval;
+	}
+
+	virtual void CleanupGUISupport () {
+		// Sanity checks
+		assert (m_wxInitialized);
+		if (!m_wxInitialized) return;
+		assert (wxThread::IsMain());
+
+		// wx cleanup
+		wxEntryCleanup();
+
+		// wx no longer initialized
+		m_wxInitialized= false;
+	}
+
+	virtual int SendMessageMainThreadSync (SmartPtr<const CTypeAny> msg, IInputPin & dst) {
+		// If this thread is already the main one simply send the message
+		if (IsMainThread()) dst.Send(msg);
+		
+
+		// Sanity checks
+		assert (m_wxInitialized);
+		if (!m_wxInitialized) {
+			LogMessage (LOG_FATAL, "wxWidgets GUI support NOT initialized", "spcore");
+			return -1;
+		}
+
+		// Check whether thread specific memory area has been initialitzed
+		if (mt_pipeEnds.get()== NULL) {
+			// Initialize memory
+			mt_pipeEnds.reset(new CCoreRuntime::PipeEnds);
+			mt_pipeEnds->fd_read= -1;
+			mt_pipeEnds->fd_write= -1;
+
+			// Create pipe
+			if (pipe ((int *) mt_pipeEnds.get())) {
+				LogMessage (LOG_FATAL, "cannot create pipe", "spcore");
+				mt_pipeEnds.reset();
+				return -1;
+			}
+
+			assert (mt_pipeEnds->fd_read!= -1);
+			assert (mt_pipeEnds->fd_write!= -1);
+
+			// Add the pipe write end to the vector
+			boost::mutex::scoped_lock lock(m_pipeWriteEndMutex);
+
+#ifndef NDEBUG
+			// In debuhg mode also check that the fd doesn't exists
+			std::vector<int>::iterator it=
+				::find(m_pipeWriteEnd.begin(), m_pipeWriteEnd.end(), mt_pipeEnds->fd_write);
+			assert(it== m_pipeWriteEnd.end());
+#endif
+			m_pipeWriteEnd.push_back (mt_pipeEnds->fd_write);
+		}
+
+		// Send message to the main loop
+		SpcoreMessageEventSync evt(msg, dst, mt_pipeEnds->fd_write);
+		::wxPostEvent (wxTheApp, evt);
+
+		// Wait until request is completed
+		int exitCode;
+read_pipe:
+		int retval= read(mt_pipeEnds->fd_read, &exitCode, sizeof(int));
+
+		// sizeof(int) means a correctly performed read operation which is
+		// the common case, so just return the provided return code
+		if (retval== sizeof(int)) return exitCode;
+
+		// 0 means EOF. The write end of the pipe has been closed. This
+		// happens as part of the normal application shutdown. Just ignore
+		// although we say that the operation has not been performed
+		if (retval== 0) return -1;
+
+		// we expect atomic reads of full integers each time. Shouldn't happen
+		if (retval > 0 && retval < static_cast<int>(sizeof(int))) {
+			LogMessage (LOG_FATAL, "unexpected size reading from pipe", "spcore");
+			return -1;
+		}
+
+		// At this point the only option is that read failed
+		assert (retval== -1);
+
+		// We just accept an interrution of the read operation and retry.
+		if (errno== EINTR) goto read_pipe;
+
+		// Otherwise log a fatal error
+		LogMessage (LOG_FATAL, "unexpected error reading from pipe", "spcore");
+
+		return -1;
+	}
+
+	// Removes a specific file descriptor from vector of pipes write end
+	// Return true if successfully removed or false if not found
+	// Note that if the vector is empty means that all descriptors
+	// have been closed as part of the normal shutdown process
+	bool CleanupPipeEnd (int pipeWrite) {
+		assert (!wxThread::IsMain());
+
+		boost::mutex::scoped_lock lock(m_pipeWriteEndMutex);
+
+		// Vector empty, normal situation, just return
+		if (m_pipeWriteEnd.size()== 0) return false;
+
+		// Find file descriptor
+		std::vector<int>::iterator it=
+			::find(m_pipeWriteEnd.begin(), m_pipeWriteEnd.end(), pipeWrite);
+
+
+		if (it!= m_pipeWriteEnd.end()) {
+			// Found. Remove and close.
+			m_pipeWriteEnd.erase (it);
+			close (pipeWrite);
+			return true;
+		}
+		else {
+			// Not found. Shouldn't happen. Log error.
+			LogMessage (LOG_FATAL, "CleanupPipeEnd: descriptor not found", "spcore");
+			assert (false);
+			return false;
+		}
+	}
+
+	//
+	// Attributtes
+	//
+	struct PipeEnds {
+		int fd_read;
+		int fd_write;
+	};
+	BOOST_STATIC_ASSERT(sizeof(PipeEnds) == sizeof(int)*2);
+
+	virtual void SendMessageMainThreadAsync (const CTypeAny& msg, IComponent& compo, ToMainThreadCallback* cb) {
+		assert (!wxThread::IsMain());
+
+		SpcoreMessageEventAsync evt(msg, compo, cb);			
+		::wxPostEvent (wxTheApp, evt);
+	}
+
+private:
+	// Local thread storage for the pipe ends
+	boost::thread_specific_ptr<PipeEnds> mt_pipeEnds;
+
+	bool m_wxInitialized;
+
+	// Vector to stored write ends of pipes, used on termination
+	std::vector<int> m_pipeWriteEnd;
+	boost::mutex m_pipeWriteEndMutex;
+#endif
+
+private:
+
+	//
+	// Private methods
+	//
+
+	// Check if a module with the same name exists
+	bool ExistsModule (const char * name) {
+		assert (name);
+		// Lookup module name
+		map<string,IModule*>::iterator it= m_modules.find(name);
+		return (it!= m_modules.end());
+	}
+
+	// Check if a type exists or not
+	bool ExistsType (const char * name) {
+		assert (name);
+		return (ResolveTypeID(name)!= TYPE_INVALID);
+	}
+
+	// Check if a component exists
+	bool ExistsComponent (const char * name) {
+		assert (name);
+		return (m_componentFactories.find(name)!= m_componentFactories.end());
+	}
+
+	// Register a type
+	void AddType (ITypeFactory& tf) {
+		assert (!ExistsType(tf.GetName()));
+		tf.AddRef();
+		m_typeFactories.push_back (&tf);
+  		m_name2TypeID.insert(pair<const char *,int>(tf.GetName(), m_typeFactories.size()));
+	}
+
+	// Register a component
+	void AddComponent (IComponentFactory& cf) {
+		assert (!ExistsComponent(cf.GetName()));
+		cf.AddRef();
+		m_componentFactories.insert(pair<const char *,IComponentFactory*>(cf.GetName(), &cf));
+	}
+
+	// Register a module
+	void AddModule (IModule& m) {
+		assert (!ExistsModule (m.GetName()));
+		m.AddRef();
+		m_modules.insert(pair<string, IModule*>(m.GetName(), &m));
+	}
+
+	//
+	// Types
+	//
+	map<string,int> m_name2TypeID;
+	vector<ITypeFactory*> m_typeFactories;
+
+	//
+	// Data members
+	//
+
+	// Components
+    map<string,IComponentFactory*> m_componentFactories;
+
+	// Modules
+    map<string,IModule*> m_modules;
+    vector<Poco::SharedLibrary*> m_sharedLibraries;
+
+	// Data dir
+	//mutable std::string m_dataDir;
+
+    boost::recursive_mutex m_mutex;
+	boost::thread::id m_mainThreadId;
+
+	// Log support
+	boost::mutex m_logMutex;
+	vector<ILogTarget*> m_logTargets;
+};
+
+typedef IModule*     module_create_instance();
+
+#ifdef ENABLE_WXWIDGETS
+// cleanup routine called after each thread has ended
+// TODO: check if this works with non boost threads
+void cleanup_pipe_ends(CCoreRuntime::PipeEnds * pends)
+{
+	if (pends->fd_read!= -1)
+		close (pends->fd_read);
+	if (pends->fd_write!= -1)		
+		static_cast<CCoreRuntime *>(getSpCoreRuntime())->CleanupPipeEnd (pends->fd_write);
+	delete pends;
+}
+
+#endif		// ENABLE_WXWIDGETS
+
+CCoreRuntime::CCoreRuntime()
+#ifdef ENABLE_WXWIDGETS
+: mt_pipeEnds(cleanup_pipe_ends)
+, m_wxInitialized(false)
+#endif
+{
+	// Assume that the core runtime is initialized from the main thread
+	// we record the ID to know wether a call comes from the main thread
+	m_mainThreadId= boost::this_thread::get_id();
+
+	// Add type ANY for translation but doesn't populate factory
+	m_name2TypeID.insert(pair<const char *,int>("any",  TYPE_ANY));
+
+	// Register base types
+	int retval= RegisterModule(SmartPtr<IModule>(new CBasicTypesModule(), false));
+	assert (retval== 0);
+
+	// Add composite component
+	IComponentFactory* component=new CCompositeComponentFactory();
+	AddComponent (*component);
+	component->Release();
+}
+
+CCoreRuntime::~CCoreRuntime(){
+	{
+		// Type factories
+		vector<ITypeFactory*>::iterator it(m_typeFactories.begin());
+		for (;it!= m_typeFactories.end(); ++it) (*it)->Release();
+		m_typeFactories.clear();
+	}
+
+	{
+		// Component factories
+		map<string,IComponentFactory*>::iterator it(m_componentFactories.begin());
+		for (;it!= m_componentFactories.end(); ++it) it->second->Release();
+		m_componentFactories.clear();
+	}
+
+	{
+		// Delete modules
+		map<string,IModule *>::iterator it(m_modules.begin());
+		//for(itm= m_modules.begin(); itm!= m_modules.end(); ++itm) itm->second->Release();
+		for (;it!= m_modules.end(); ++it) it->second->Release();
+		m_modules.clear();
+	}
+
+	{
+		// Delete shared libraries
+		vector<Poco::SharedLibrary*>::iterator it(m_sharedLibraries.begin());
+		for (; it!= m_sharedLibraries.end(); ++it) {
+			(*it)->unload();
+			delete (*it);
+		}
+		m_sharedLibraries.clear();
+	}
+#ifdef ENABLE_WXWIDGETS
+	assert (m_pipeWriteEnd.size()== 0);
+#endif
+}
+
+// Resolves the runtime ID of a named type. Returns the ID or TYPE_INVALID
+// if the specified type doesn't exists.
+int CCoreRuntime::ResolveTypeID(const char * name) {
+	boost::recursive_mutex::scoped_lock lock(m_mutex);
+
+	map<string,int>::iterator it= m_name2TypeID.find(name);
+	return (it!= m_name2TypeID.end() ? it->second : TYPE_INVALID);
+}
+
+SmartPtr<IIterator<ITypeFactory*> > CCoreRuntime::QueryTypes() {
+  	boost::recursive_mutex::scoped_lock lock(m_mutex);
+
+	return SmartPtr<IIterator<ITypeFactory*> > (new CIteratorVector<ITypeFactory*>(m_typeFactories), false);
+}
+
+// Creates a new type instance for a given type name. Returns a pointer
+// to the new instance or NULL if the type doesn't exists or another error
+// occurred.
+SmartPtr<CTypeAny> CCoreRuntime::CreateTypeInstance(const char * typeName) {
+	boost::recursive_mutex::scoped_lock lock(m_mutex);
+
+	return CreateTypeInstance(ResolveTypeID(typeName));
+}
+
+SmartPtr<CTypeAny> CCoreRuntime::CreateTypeInstance(int id) {
+  	boost::recursive_mutex::scoped_lock lock(m_mutex);
+
+	if (id< 1) return NULL;
+  	if ((unsigned int) id> m_typeFactories.size()) return NULL;
+  	return m_typeFactories[id-1]->CreateInstance(id);
+}
+
+SmartPtr<IIterator<IComponentFactory*> > CCoreRuntime::QueryComponents() {
+	boost::recursive_mutex::scoped_lock lock(m_mutex);
+
+	return SmartPtr<IIterator<IComponentFactory*> >
+		(new CIteratorMap<string,IComponentFactory*>(m_componentFactories), false);
+}
+
+SmartPtr<IComponent> CCoreRuntime::CreateComponent(const char * typeName, const char * name, int argc, const char * argv[]) {
+  	boost::recursive_mutex::scoped_lock lock(m_mutex);
+
+	// Lookup component type name
+  	map<string,IComponentFactory*>::iterator it;
+  	it= m_componentFactories.find(typeName);
+  	if (it== m_componentFactories.end()) return NULL;	// Component type not found
+
+	return it->second->CreateInstance(name, argc, argv);
+}
+
+SmartPtr<IOutputPin> CCoreRuntime::CreateOutputPin(const char* type, const char* name, bool locked)
+{
+	SmartPtr<IOutputPin> retval;
+
+	int typeID= this->ResolveTypeID(type);
+	if (typeID!= TYPE_INVALID) {
+		try {
+			// Really not needed the try block because we know that the type
+			// name exists. Just to be safe.
+			if (!locked)
+				retval= SmartPtr<IOutputPin>(new COutputPin (name, type), false);
+			else
+				retval= SmartPtr<IOutputPin>(new COutputPinLock (name, type), false);
+		}
+		catch(...) {}
+	}
+
+	return retval;
+}
+
+int CCoreRuntime::RegisterModule(SmartPtr<IModule> module) {
+  	boost::recursive_mutex::scoped_lock lock(m_mutex);
+
+	//
+	// Sanity checks
+	//
+
+	// Lookup module name. Error if already registered
+	{
+		const char* name= module->GetName();
+		if (name== NULL || *name== '\0') return -5;
+		if (ExistsModule(name)) return -1;
+	}
+
+    // Check api version number
+  	if (module->GetCoreVersion()!= SPCORE_VERSION)
+  		return -2;	// Wrong core version
+
+  	// Check types
+	SmartPtr<IIterator<ITypeFactory*> > ittf= module->GetTypeFactories();
+  	if (ittf.get())
+		for (ittf->First(); !ittf->IsDone(); ittf->Next()) {
+			const char* name= ittf->CurrentItem()->GetName();
+			if (name== NULL || *name== '\0') return -5;
+			// Error if type name already registered
+			if (ExistsType(name)) return -3;
+		}
+
+  	// Check component
+  	SmartPtr<IIterator<IComponentFactory*> > itcf= module->GetComponentFactories();
+  	if (itcf.get())
+		for (itcf->First(); !itcf->IsDone(); itcf->Next()) {
+			const char* name= itcf->CurrentItem()->GetName();
+			if (name== NULL || *name== '\0') return -5;
+			// Error if component already registered
+			if (ExistsComponent(name)) return -4;
+		}
+
+	//
+	// Register elements
+	//
+
+	// Register types
+	if (ittf.get())
+  		for (ittf->First(); !ittf->IsDone(); ittf->Next())
+			AddType (*ittf->CurrentItem());
+
+   	// Register components
+  	if (itcf.get())
+  		for (itcf->First(); !itcf->IsDone(); itcf->Next())
+			AddComponent (*itcf->CurrentItem());
+
+  	// Register the module itself
+	AddModule (*module);
+
+  	return 0;
+}
+
+int CCoreRuntime::LoadModule(const char * name, const char * dir) {
+	boost::recursive_mutex::scoped_lock lock(m_mutex);
+
+	std::string fullPath;
+	if (dir) {
+		fullPath.append(dir);
+		fullPath.append("/");
+	}
+
+#if !defined (WIN32)
+	// We assume *NIX system
+	// TODO: check for Mac
+	fullPath.append("lib");
+#endif
+	fullPath.append(name);
+#if defined (WIN32)
+	fullPath.append(".dll");
+#else
+	fullPath.append(".so");
+#endif
+
+	Poco::SharedLibrary* sl= NULL;
+
+	try {
+		sl= new Poco::SharedLibrary (fullPath.c_str());
+	}
+	catch (Poco::LibraryLoadException& e) {
+		// Library cannot be loaded
+		std::string message(e.displayText());
+		LogMessage (LOG_ERROR, message.c_str(), "spcore");
+		return -6;
+	}
+	catch (Poco::LibraryAlreadyLoadedException) {
+		return -1;
+	}
+
+	// Get library entry point
+	if (!sl->hasSymbol("module_create_instance")) {
+		delete sl;
+		return -7;
+	}
+	module_create_instance* mci= reinterpret_cast<module_create_instance*>(sl->getSymbol("module_create_instance"));
+
+	// Get IModule instance
+	IModule *mod= mci();
+	if (mod== NULL) {
+		delete sl;
+		return -8;
+	}
+
+	// Register module
+	int retval= RegisterModule(SmartPtr<IModule>(mod, false));
+
+	if (retval< 0) delete sl;
+	else this->m_sharedLibraries.push_back(sl);
+
+	return retval;
+}
+
+
+void CCoreRuntime::LogMessage (LogSeverityLevel severity, const char* message, const char* module)
+{
+	boost::mutex::scoped_lock lock(m_logMutex);
+
+	if (m_logTargets.empty()) {
+		switch (severity) {
+			case LOG_DEBUG: std::cerr << "DEBUG:"; break;
+			case LOG_INFO: std::cerr << "INFO:"; break;
+			case LOG_WARNING: std::cerr << "WARNING:"; break;
+			case LOG_ERROR: std::cerr << "ERROR:"; break;
+			case LOG_FATAL: std::cerr << "FATAL:"; break;
+			default: assert (false);
+		}
+
+		if (module)
+			std::cerr << module << ":";
+
+		std::cerr << message << std::endl;
+	}
+	else {
+		string theMessage;
+		if (module) { 
+			theMessage+= module;
+			theMessage+= ". ";
+		}
+
+		theMessage+= message;
+
+		vector<ILogTarget*>::iterator it= m_logTargets.begin();
+		for (; it!= m_logTargets.end(); ++it) (*it)->LogMessage(severity, theMessage.c_str());
+	}
+}
+
+void CCoreRuntime::RegisterLogTarget (ILogTarget* lt)
+{
+	boost::mutex::scoped_lock lock(m_logMutex);
+
+	vector<ILogTarget*>::const_iterator it= 
+		find (m_logTargets.begin(), m_logTargets.end(), lt);
+
+	if (it!= m_logTargets.end()) 
+		// Already registered, ignore request
+		return;
+
+	m_logTargets.push_back(lt);
+}
+
+void CCoreRuntime::UnregisterLogTarget (ILogTarget* lt)
+{
+	boost::mutex::scoped_lock lock(m_logMutex);
+
+	vector<ILogTarget*>::iterator it= 
+		find (m_logTargets.begin(), m_logTargets.end(), lt);
+
+	if (it== m_logTargets.end()) 
+		// Not registered, ignore request
+		return;
+
+	m_logTargets.erase(it);
+}
+
+//
+// The only two exported functions of the library
+//
+static CCoreRuntime* g_coreRuntime= NULL;
+static boost::mutex g_spcore_mutex;
+static bool g_spcore_freed= false;
+
+SPEXPORT_FUNCTION ICoreRuntime* getSpCoreRuntime()
+{
+	assert (!g_spcore_freed);
+	boost::mutex::scoped_lock lock(g_spcore_mutex);
+
+	if (!g_coreRuntime) g_coreRuntime= new CCoreRuntime();
+	return g_coreRuntime;
+}
+
+SPEXPORT_FUNCTION void freeSpCoreRuntime()
+{
+//	boost::mutex::scoped_lock lock(g_spcore_mutex);
+
+	if (g_coreRuntime) {
+		delete g_coreRuntime;
+		g_spcore_freed= true;
+		// Invalidate pointer
+		g_coreRuntime= NULL;
+	}
+}
+
+
+} // namespace spcore
diff --git a/src/core/language.cpp b/src/core/language.cpp
new file mode 100644
index 0000000..a7adbc9
--- /dev/null
+++ b/src/core/language.cpp
@@ -0,0 +1,306 @@
+/////////////////////////////////////////////////////////////////////////////
+// File:        language.cpp
+// Author:      Cesar Mauri Loba (cesar at crea-si dot com)
+// Copyright:   (C) 2010-10 Cesar Mauri Loba - CREA Software Systems
+// 
+//  This program is free software: you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation, either version 3 of the License, or
+//  (at your option) any later version.
+//
+//  This program is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+/////////////////////////////////////////////////////////////////////////////
+#include "spcore/language.h"
+#include "spcore/coreruntime.h"
+
+#include <clocale>
+#include <vector>
+#include <string>
+#include <iostream>
+#include <boost/static_assert.hpp>
+#include <libintl.h>
+
+/*	
+	Some versions of libintl.h for Win32 provide macros for printf 
+	funtion family. Those macros can cause crashes on Windows so
+	we do not want them.
+*/
+#ifdef printf
+	#error "libintl.h defines printf"
+#endif
+
+#define ARRAY_SIZE(foo) (sizeof(foo)/sizeof(foo[0]))
+
+/*
+	Language id's and names
+*/
+typedef struct {
+	const char* locale;
+	const char* native_name;
+	const char* winName;
+}  LangInfo;
+
+// NOTE: this file is encoded using UTF8
+static LangInfo g_supported_lang_ids[]= {
+	{ "", N__("System default"), ""},	// spLANGUAGE_DEFAULT,
+	{ "C", "", ""},						// spLANGUAGE_UNKNOWN,		
+	{ "eu_ES", "Euskara", "Basque" },	// spLANGUAGE_BASQUE,
+	{ "ca_ES", "Català", "Catalan" },	// spLANGUAGE_CATALAN,
+	{ "zh_TW", "汉语", "Chinese" },		// spLANGUAGE_CHINESE,
+	{ "en_GB", "English", "English" },	// spLANGUAGE_ENGLISH,
+	{ "fr_FR", "Français", "French" },	// spLANGUAGE_FRENCH,
+	{ "gl_ES", "Galego", "Galician" },	// spLANGUAGE_GALICIAN,
+	{ "de_DE", "Deutsch", "German" },	// spLANGUAGE_GERMAN,
+	{ "el_GR", "Ελληνικά", "Greek" },	// spLANGUAGE_GREEK,
+	{ "he_IL", "עברית", "Hebrew" },		// spLANGUAGE_HEBREW,
+	{ "it_IT", "Italino", "Italian" },	// spLANGUAGE_ITALIAN,
+	{ "ja_JP", "日本語", "Japanese" },	// spLANGUAGE_JAPANESE,
+	{ "pt_PT", "Português", "Portuguese" },	// spLANGUAGE_PORTUGUESE,
+	{ "ru_RU", "Русский", "Russian" },	// spLANGUAGE_RUSSIAN,
+	{ "es_ES", "Español", "Spanish" },		// spLANGUAGE_SPANISH,
+	{ "sv_SE", "Svenska", "Swedish" },		// spLANGUAGE_SWEDISH,
+	{ "tr_TR", "Türkçe", "Turkish" }		// spLANGUAGE_TURKISH
+};
+
+BOOST_STATIC_ASSERT(ARRAY_SIZE(g_supported_lang_ids)== spLANGUAGE_LAST);
+
+#ifdef ENABLE_WXWIDGETS
+static const int g_supported_lang_wxids[]= { 
+	wxLANGUAGE_DEFAULT,
+	wxLANGUAGE_UNKNOWN,		
+	wxLANGUAGE_BASQUE,
+	wxLANGUAGE_CATALAN,
+	wxLANGUAGE_CHINESE,
+	wxLANGUAGE_ENGLISH,
+	wxLANGUAGE_FRENCH,
+	wxLANGUAGE_GALICIAN,
+	wxLANGUAGE_GERMAN,
+	wxLANGUAGE_GREEK,
+	wxLANGUAGE_HEBREW,
+	wxLANGUAGE_ITALIAN,
+	wxLANGUAGE_JAPANESE,
+	wxLANGUAGE_PORTUGUESE,
+	wxLANGUAGE_RUSSIAN,
+	wxLANGUAGE_SPANISH,
+	wxLANGUAGE_SWEDISH,
+	wxLANGUAGE_TURKISH
+};
+BOOST_STATIC_ASSERT(ARRAY_SIZE(g_supported_lang_ids)== ARRAY_SIZE(g_supported_lang_wxids));
+#endif
+
+static int g_current_lang_id= -1;
+
+// List of domains
+static std::vector<std::string> g_text_domains;
+
+#ifdef WIN32
+
+// Functions in win32env.cpp
+extern int win32_putenv(const char *envval);
+extern void win32_unsetenv(const char *name);
+
+#ifndef _WIN32_WINNT
+	#error "_WIN32_WINNT not defined"
+#endif
+#include <windows.h>
+
+#endif	// WIN32
+
+// Code based on language.cpp from http://svn.gna.org/viewcvs/wesnoth/trunk/
+// TODO: consider using tinygettext on Win32 due to the problems which gettext has
+static 
+bool sp_setlocale(int category, int id, std::vector<std::string> const *alternates)
+{
+	std::string locale = g_supported_lang_ids[id].locale;
+
+#ifdef _WIN32	
+	{
+		// Pick language part (2 or 3 chars)
+		char gettextloc[4];
+		gettextloc[0]= 0;
+		unsigned int i= 0;
+		for (; i< 3 && i< locale.size() && locale[i]!='_' && locale[i]!='@' && locale[i]!= '.'; ++i)
+			gettextloc[i]= locale[i];
+		gettextloc[i]= 0;
+
+		if(category == LC_MESSAGES) {
+			// For windows we need to define the environtment variable LANGUAGE
+			std::string env = std::string("LANGUAGE=") + gettextloc;
+			win32_putenv(env.c_str());
+			//SetEnvironmentVariableA("LANG", locale.c_str());
+			return true;
+		}
+
+		// Get Win32 language name
+		locale= g_supported_lang_ids[id].winName;
+	}
+#endif
+
+	char *res = NULL;
+	std::vector<std::string>::const_iterator i;
+	if (alternates) i = alternates->begin();
+
+	for (;;) {
+		std::string lang = locale, extra;
+		std::string::size_type pos = locale.find('@');
+		if (pos != std::string::npos) {
+			lang.erase(pos);
+			extra = locale.substr(pos);
+		}
+
+		/*
+		 * The "" is the last item to work-around a problem in glibc picking
+		 * the non utf8 locale instead an utf8 version if available.
+		 */
+		char const *encoding[] = { ".utf-8", ".UTF-8", "" };
+		for (int j = 0; j != 3; ++j) {
+			locale = lang + encoding[j] + extra;
+			res = std::setlocale(category, locale.c_str());
+			if (res) return true;	// OK
+		}
+
+		if (!alternates || i == alternates->end()) break;
+		locale = *i;
+		++i;
+	}
+
+	std::cerr << "setlocale() failed for '" << g_supported_lang_ids[id].locale << "'.\n";
+	/*
+#ifndef _WIN32
+#ifndef __AMIGAOS4__
+	if(category == LC_MESSAGES) {
+		std::cerr << "Setting LANGUAGE to '" << slocale << "'.\n";
+		setenv("LANGUAGE", slocale.c_str(), 1);
+		std::setlocale(LC_MESSAGES, "");
+	}
+#endif
+#endif*/
+
+	//done:
+	//std::cerr << "Numeric locale: " << std::setlocale(LC_NUMERIC, NULL) << '\n';
+	//std::cerr << "Full locale: " << std::setlocale(LC_ALL, NULL) << '\n';
+
+	return false;
+}
+
+#ifdef ENABLE_WXWIDGETS
+static
+wxLocale& GetWxLocale()
+{
+	static wxLocale locale;
+	return locale;
+}
+#endif
+
+SPEXPORT_FUNCTION
+const char * spGettext (const char * msgid)
+{
+	std::vector<std::string>::const_iterator it= g_text_domains.begin();
+	while (it!= g_text_domains.end()) {
+		const char * retval= dgettext(it->c_str(), msgid);
+		if (retval!= msgid) return retval;
+		it++;
+	}
+	return msgid;
+}
+
+SPEXPORT_FUNCTION
+const char * spDGettext (const char * domainname, const char * msgid)
+{
+	return dgettext(domainname, msgid);
+}
+
+SPEXPORT_FUNCTION
+int spSetLanguage (int id)
+{
+	if (id< spLANGUAGE_FIRST || id> spLANGUAGE_LAST || g_current_lang_id!= -1) return -1;
+
+	g_current_lang_id= id;
+
+#ifdef WIN32
+	// Make sure associated runtime library is loaded
+	gettext(NULL);
+#endif
+
+	// configuration for gettext
+	// TODO: check errors
+	sp_setlocale(LC_COLLATE, id, NULL);
+	sp_setlocale(LC_TIME, id, NULL);
+	sp_setlocale(LC_MESSAGES, id, NULL);
+
+#ifdef ENABLE_WXWIDGETS
+	// configuration for wx
+	// TODO: consider using wxLOCALE_LOAD_DEFAULT flags (loads wxstd catalog)
+	if (!GetWxLocale().Init(g_supported_lang_wxids[id], 0)) return -1;
+#endif
+
+	return 0;
+}
+
+SPEXPORT_FUNCTION
+int spGetLanguage () { return g_current_lang_id; }
+
+SPEXPORT_FUNCTION
+bool isLanguageValid (int id) {
+	if (id< spLANGUAGE_FIRST || id> spLANGUAGE_LAST) return false;
+
+	return true;
+}
+
+SPEXPORT_FUNCTION
+int spBindTextDomain(const char* domain, const char* dirname)
+{
+#ifdef ENABLE_WXWIDGETS
+	GetWxLocale().AddCatalogLookupPathPrefix(wxString(dirname, wxConvUTF8));
+	if (!GetWxLocale().AddCatalog(wxString(domain, wxConvUTF8))) return -1;
+#endif
+	bindtextdomain( domain, dirname );
+	bind_textdomain_codeset (domain, "UTF-8");
+	g_text_domains.push_back(domain);
+	return 0;
+}
+
+SPEXPORT_FUNCTION
+int spGetAvailableLanguages()
+{
+	return (spLANGUAGE_LAST - spLANGUAGE_FIRST);
+}
+
+SPEXPORT_FUNCTION
+const char* spGetLocaleId (int id)
+{
+	if (!isLanguageValid(id)) return NULL;
+	
+	return g_supported_lang_ids[id].locale;
+}
+
+SPEXPORT_FUNCTION
+int spResolveLocaleId (const char* locale)
+{
+	if (!locale) return -1;
+
+	for (int i= 0; i< spGetAvailableLanguages(); ++i)
+		if (strcmp(locale, g_supported_lang_ids[i].locale)== 0) return (int) i;
+	
+	return -1;
+}
+
+SPEXPORT_FUNCTION
+const char* spGetLanguageNativeName (int id, const char* domain)
+{
+	if (!isLanguageValid(id)) return NULL;
+
+	if (id== spLANGUAGE_DEFAULT) {
+		if (domain) return dgettext(domain, g_supported_lang_ids[id].native_name);
+		else return gettext(g_supported_lang_ids[id].native_name);
+	}
+
+	return g_supported_lang_ids[id].native_name;
+}
+
diff --git a/src/core/tests/CMakeLists.txt b/src/core/tests/CMakeLists.txt
new file mode 100755
index 0000000..ee92bde
--- /dev/null
+++ b/src/core/tests/CMakeLists.txt
@@ -0,0 +1,63 @@
+cmake_minimum_required(VERSION 2.8)
+project(spcore_tests)
+
+#
+# Test smart pointer
+#
+
+add_executable(test_spcore_smart_ptr test_spcore_smart_ptr.cpp)
+target_link_libraries(test_spcore_smart_ptr spcore)
+target_link_libraries(test_spcore_smart_ptr sphost)
+target_link_libraries(test_spcore_smart_ptr nvwa)
+add_test (NAME test_spcore_smart_ptr COMMAND $<TARGET_FILE:nvwa_loader> $<TARGET_FILE:test_spcore_smart_ptr>)
+
+#
+# Test spcore runtime
+#
+
+add_executable(test_spcore_runtime test_spcore_runtime.cpp)
+target_link_libraries(test_spcore_runtime spcore)
+target_link_libraries(test_spcore_runtime sphost)
+target_link_libraries(test_spcore_runtime nvwa)
+add_test (NAME test_spcore_runtime COMMAND $<TARGET_FILE:nvwa_loader> $<TARGET_FILE:test_spcore_runtime>)
+
+#
+# Test basic types
+#
+
+add_executable(test_spcore_basic_types test_spcore_basic_types.cpp)
+target_link_libraries(test_spcore_basic_types spcore)
+target_link_libraries(test_spcore_basic_types sphost)
+target_link_libraries(test_spcore_basic_types nvwa)
+add_test (NAME test_spcore_basic_types COMMAND $<TARGET_FILE:nvwa_loader> $<TARGET_FILE:test_spcore_basic_types>)
+
+#
+# Test component
+#
+
+add_executable(test_spcore_component test_spcore_component.cpp)
+target_link_libraries(test_spcore_component spcore) 
+target_link_libraries(test_spcore_component sphost)
+target_link_libraries(test_spcore_component nvwa)
+add_test (NAME test_spcore_component COMMAND $<TARGET_FILE:nvwa_loader> $<TARGET_FILE:test_spcore_component>)
+
+#
+# Test wx_main_thread
+#
+
+add_executable(test_spcore_wx_main_thread test_spcore_wx_main_thread.cpp)
+target_link_libraries(test_spcore_wx_main_thread spcore) 
+target_link_libraries(test_spcore_wx_main_thread sphost)
+target_link_libraries(test_spcore_wx_main_thread nvwa)
+target_link_libraries(test_spcore_wx_main_thread ${wxWidgets_LIBRARIES})
+add_test (NAME test_spcore_wx_main_thread COMMAND $<TARGET_FILE:nvwa_loader> $<TARGET_FILE:test_spcore_wx_main_thread>)
+
+#
+# Test configuration
+#
+
+add_executable(test_spcore_configuration test_spcore_configuration.cpp)
+target_link_libraries(test_spcore_configuration spcore) 
+target_link_libraries(test_spcore_configuration sphost)
+target_link_libraries(test_spcore_configuration nvwa)
+add_test (NAME test_spcore_configuration COMMAND $<TARGET_FILE:nvwa_loader> $<TARGET_FILE:test_spcore_configuration>)
diff --git a/src/core/tests/test1.cpp b/src/core/tests/test1.cpp
new file mode 100644
index 0000000..73c364e
--- /dev/null
+++ b/src/core/tests/test1.cpp
@@ -0,0 +1,149 @@
+#include "sphost/testcommon.h"
+#include "spcore/basetypesimpl.h"
+
+using namespace spcore;
+using namespace std;
+
+class Container : public spcore::CComponentAdapter
+{
+public:
+	Container(const char *name) : CComponentAdapter(name)
+	{	
+		m_data= 0;
+		m_lis1= new MyListener1 (*this);
+		assert (m_lis1);
+		m_iPin1= getSpCoreRuntime()->CreateInputPin("my_in_pin", "int", *m_lis1);
+		assert (m_iPin1);
+		m_oPin1= getSpCoreRuntime()->CreateOutputPin("my_out_pin_1", "int");
+		assert (m_oPin1);
+		int retval= RegisterInputPin (*m_iPin1);
+		assert (retval== 0);
+		retval= RegisterOutputPin (*m_oPin1);
+		assert (retval== 0);
+	}
+	~Container()
+	{
+	}
+	string GetTypeName(void) const
+	{
+		return "Container";
+	}
+private:
+	// Listener
+	class MyListener1 : public CIntListener<Container> {
+	public:
+		MyListener1 (Container& c) : CIntListener<Container>(c) {}
+		virtual void Update(const CTypeInt & message) {
+			//this->m_component->m_data++;
+			cout << "MyListener1: " << message.getValue() << endl;
+		}
+	};	
+
+	int m_data;
+	MyListener1* m_lis1;
+	IInputPin* m_iPin1;
+	IOutputPin* m_oPin1;
+			
+public:		
+	void DoTest()
+	{
+		m_oPin1->Attach (*m_iPin1);
+		CTypeInt* i= CTypeInt::CreateInstance();
+		assert (i);
+		i->setValue(12);
+		m_oPin1->Send (*i);
+		i->Release();
+	}	
+};
+
+void TestContainer()
+{
+	Container* cont= new Container("my_cont");
+	cont->DoTest();
+
+	IIterator<IInputPin*>* ii= cont->GetInputPins();
+	for (ii->First(); !ii->IsDone(); ii->Next()) {
+		IInputPin* ip= ii->CurrentItem();
+		cout << "Input pin: " << ip->GetName() << " TypeID: " << ip->GetTypeID() << " Type name: " << ip->GetTypeName() << endl;
+	}
+	ii->Release();
+
+
+	IIterator<IOutputPin*>* io= cont->GetOutputPins();
+	for (io->First(); !io->IsDone(); io->Next()) {
+		IOutputPin* op= io->CurrentItem();
+		cout << "Input pin: " << op->GetName() << " TypeID: " << op->GetTypeID() << " Type name: " << op->GetTypeName() << endl;
+	}
+	io->Release();
+
+	delete cont;
+}
+
+void TestGraph()
+{
+	ICoreRuntime* core= getSpCoreRuntime();
+	IGraphManager* mgr= core->CreateGraphManager();	assert (mgr);
+
+	// Trying to register a new component should work
+	IComponent* cont= new Container("my_cont");
+	int retval= mgr->RegisterComponent(*cont); assert (retval== 0);
+	
+	// Trying to register again the same component should fail
+	retval= mgr->RegisterComponent(*cont); assert (retval!= 0);
+
+	// Trying to register a new component with the same name should fail
+	IComponent* tmpCont= new Container("my_cont");
+	retval= mgr->RegisterComponent(*tmpCont); assert (retval!= 0);
+	tmpCont->Release();
+
+	// Trying to register a new component should work
+	IComponent* adder= core->CreateComponent(COMPONENT_ADD_INT_NAME, "firstAdder"); assert (adder);
+	retval= mgr->RegisterComponent(*adder); assert (retval== 0);
+
+	// Dump graph manager status
+	DumpGraphManager(*mgr);
+
+	// Attach pins by number
+	//retval= mgr->Attach (adder, (unsigned int) 0, cont, (unsigned int) 0); assert (retval== 0);
+	retval= mgr->Attach (adder, "result", cont, "my_in_pin"); assert (retval== 0);
+
+	// Obtain adder input pins for testing
+	IteratorPtr<IInputPin*> it(adder->GetInputPins());
+	it->First();
+	CInputPin* iPinA= static_cast<CInputPin*>(it->CurrentItem());
+	it->Next(); assert (!it->IsDone());
+	CInputPin* iPinB= static_cast<CInputPin*>(it->CurrentItem());
+	CTypeInt *myInt= CTypeInt::CreateInstance(); assert (myInt);
+
+	// Perform addition
+	myInt->setValue(5);
+	//iPinB->GetListener()->Update(*myInt);
+	iPinB->Update(*myInt);
+	myInt->setValue(3);
+	//iPinA->GetListener()->Update(*myInt);
+	iPinA->Update(*myInt);
+
+
+	myInt->Release();
+}
+
+
+int main (int, char**)
+{
+	//RegisterModules();
+
+	DumpCoreRuntime();
+
+	//TestContainer();
+	
+	TestGraph();
+
+
+	// Cleanup
+	freeSpCoreRuntime();
+	
+	DUMP_LEAKS
+
+//	getchar();
+	return 0;
+}
\ No newline at end of file
diff --git a/src/core/tests/test_spcore_basic_types.cpp b/src/core/tests/test_spcore_basic_types.cpp
new file mode 100644
index 0000000..8495e5f
--- /dev/null
+++ b/src/core/tests/test_spcore_basic_types.cpp
@@ -0,0 +1,94 @@
+#include "sphost/testcommon.h"
+#include "spcore/coreruntime.h"
+#include "spcore/basictypes.h"
+
+#include <assert.h>
+#include <iostream>
+#include <stdio.h>
+
+using namespace spcore;
+
+static
+void DoTest()
+{
+	spcore::ICoreRuntime* core= spcore::getSpCoreRuntime();
+
+	DumpCoreRuntime(core);
+
+	{
+		/*
+		// Create using core runtime directly
+
+		CTypeInt* intVar= dynamic_cast<CTypeInt*>(core->CreateTypeInstance("int"));
+		if (!intVar) exit (-1);
+		intVar->Release();
+		CTypeFloat* floatVar= dynamic_cast<CTypeFloat*>(core->CreateTypeInstance("float"));
+		if (!floatVar) exit (-1);
+		floatVar->Release();
+		CTypeBool* boolVar= dynamic_cast<CTypeBool*>(core->CreateTypeInstance("bool"));
+		if (!boolVar) exit (-1);
+		boolVar->Release();
+		*/
+	}
+
+
+
+	// Create using static members of each type
+	SmartPtr<CTypeInt> intVar= CTypeInt::CreateInstance();
+	if (!intVar.get()) exit (-1);
+
+	SmartPtr<CTypeFloat> floatVar= CTypeFloat::CreateInstance();
+	if (!floatVar.get()) exit (-1);
+
+	SmartPtr<CTypeBool> boolVar= CTypeBool::CreateInstance();
+	if (!boolVar.get()) exit (-1);
+
+	SmartPtr<CTypeString> stringVar= CTypeString::CreateInstance();
+	if (!stringVar.get()) exit (-1);
+
+	SmartPtr<CTypeComposite> compositeVar= CTypeComposite::CreateInstance();
+	if (!compositeVar.get()) exit (-1);
+
+
+	// Test values
+	const int intValList[] = { 12, -5, 0, 40, 12345 };
+	for (unsigned int i= 0; i< sizeof(intValList)/sizeof(int); ++i) {
+		intVar->setValue (intValList[i]);
+		if (intVar->getValue()!= intValList[i]) exit (-1);
+	}
+
+	const float floatValList[] = { 12.23455f, -5.0f, 0, 4000000000.34545f, 12345.6789f };
+	for (unsigned int i= 0; i< sizeof(floatValList)/sizeof(int); ++i) {
+		floatVar->setValue (floatValList[i]);
+		if (floatVar->getValue()!= floatValList[i]) exit (-1);
+	}
+
+	const bool boolValList[] = { true, false };
+	for (unsigned int i= 0; i< sizeof(boolValList)/sizeof(int); ++i) {
+		boolVar->setValue (boolValList[i]);
+		if (boolVar->getValue()!= boolValList[i]) exit (-1);
+	}
+
+	const char* stringValList[] = { "str1", "str2", "longer string\n" };
+	for (unsigned int i= 0; i< sizeof(stringValList)/sizeof(char*); ++i) {
+		stringVar->setValue(stringValList[i]);
+		if (strcmp (stringVar->getValue(), stringValList[i])) exit (-1);
+	}
+	
+	if (compositeVar->AddChild(intVar)) exit (-1);
+	if (compositeVar->AddChild(floatVar)) exit (-1);
+	if (compositeVar->AddChild(boolVar)) exit (-1);
+	if (compositeVar->AddChild(stringVar)) exit (-1);
+
+	DumpTypeInstance (*compositeVar);
+}
+
+int main (int, char**)
+{
+	DoTest();
+	
+	// Cleanup
+	spcore::freeSpCoreRuntime();
+
+	return 0;
+}
diff --git a/src/core/tests/test_spcore_component.cpp b/src/core/tests/test_spcore_component.cpp
new file mode 100644
index 0000000..5ab25aa
--- /dev/null
+++ b/src/core/tests/test_spcore_component.cpp
@@ -0,0 +1,147 @@
+#include "sphost/testcommon.h"
+#include "spcore/basictypes.h"
+#include "spcore/pinimpl.h"
+
+using namespace spcore;
+using namespace std;
+
+class CExampleComponent : public spcore::CComponentAdapter
+{
+public:
+	CExampleComponent(const char *name, int argc, const char * argv[])
+	: CComponentAdapter(name, argc, argv)
+	{
+		m_data= 0;
+		m_iPin1= SmartPtr<IInputPin>(new CInputPin1("i_pin1", *this), false);
+		m_oPin1= CTypeInt::CreateOutputPin ("o_pin");
+		if (RegisterInputPin(*m_iPin1)!= 0) exit (-1);
+		if (RegisterOutputPin (*m_oPin1)!= 0) exit (-1);
+	}
+	~CExampleComponent() { }
+	const char* GetTypeName(void) const { return "CExampleComponent"; }
+
+private:
+	// Listener
+	class CInputPin1 : public CInputPinWriteOnly<CTypeInt, CExampleComponent> {
+	public:
+		CInputPin1 (const char * name, CExampleComponent & component) : CInputPinWriteOnly<CTypeInt, CExampleComponent>(name, component) {}
+		virtual int DoSend(const CTypeInt & message) {
+			cout << "CInputPin1: " << message.getValue() << endl;
+			return 0;
+		}
+	};
+
+	int m_data;
+	SmartPtr<IInputPin> m_iPin1;
+	SmartPtr<IOutputPin> m_oPin1;
+
+//public:
+/*
+	void DoTest()
+	{
+		m_oPin1->Attach (*m_iPin1);
+		CTypeInt* i= CTypeInt::CreateInstance();
+		assert (i);
+		i->setValue(12);
+		m_oPin1->Send (*i);
+		i->Release();
+	}
+	*/
+};
+/*
+void TestContainer()
+{
+	Container* cont= new Container("my_cont");
+	cont->DoTest();
+
+	IIterator<IInputPin*>* ii= cont->GetInputPins();
+	for (ii->First(); !ii->IsDone(); ii->Next()) {
+		IInputPin* ip= ii->CurrentItem();
+		cout << "Input pin: " << ip->GetName() << " TypeID: " << ip->GetTypeID() << " Type name: " << ip->GetTypeName() << endl;
+	}
+	ii->Release();
+
+
+	IIterator<IOutputPin*>* io= cont->GetOutputPins();
+	for (io->First(); !io->IsDone(); io->Next()) {
+		IOutputPin* op= io->CurrentItem();
+		cout << "Input pin: " << op->GetName() << " TypeID: " << op->GetTypeID() << " Type name: " << op->GetTypeName() << endl;
+	}
+	io->Release();
+
+	delete cont;
+}
+*/
+
+class CCompositeComponent : public CCompositeComponentAdapter
+{
+public:
+	CCompositeComponent(const char* name, int argc, const char * argv[])
+	: CCompositeComponentAdapter(name, argc, argv) {}
+};
+
+void DoTest()
+{
+	ICoreRuntime* core= getSpCoreRuntime();
+	if (!core) exit (-1);
+
+	// Root container component
+	SmartPtr<IComponent> ag= core->CreateComponent("component_composer", "test_composer", 0, NULL);
+
+	// Trying to register a new component should work
+	SmartPtr<IComponent> compo(new CExampleComponent("exemple", 0, NULL), false);
+	if (ag->AddChild(compo)!= 0) exit (-1);
+
+	// Trying to register again the same component should fail
+	if (ag->AddChild(compo)== 0) exit (-1);
+
+	// Trying to register a new component with the same name shouldn't fail
+	SmartPtr<IComponent> tmpCont (new CExampleComponent("my_cont", 0, NULL), false);
+	if (ag->AddChild(tmpCont)!= 0) exit (-1);
+
+	// Trying to register a new component should work
+	SmartPtr<IComponent> adder= core->CreateComponent("iadd", "firstAdder", 0, NULL);
+	if (!adder.get()) exit (-1);
+	if (ag->AddChild(adder)!= 0) exit (-1);
+
+	// Dump root component status
+	DumpComponent (*ag);
+
+
+	/*
+	// Attach pins by number
+	//retval= mgr->Attach (adder, (unsigned int) 0, cont, (unsigned int) 0); assert (retval== 0);
+	retval= mgr->Attach (adder, "result", cont, "my_in_pin"); assert (retval== 0);
+
+	// Obtain adder input pins for testing
+	IteratorPtr<IInputPin*> it(adder->GetInputPins());
+	it->First();
+	CInputPin* iPinA= static_cast<CInputPin*>(it->CurrentItem());
+	it->Next(); assert (!it->IsDone());
+	CInputPin* iPinB= static_cast<CInputPin*>(it->CurrentItem());
+	CTypeInt *myInt= CTypeInt::CreateInstance(); assert (myInt);
+
+	// Perform addition
+	myInt->setValue(5);
+	//iPinB->GetListener()->Update(*myInt);
+	iPinB->Update(*myInt);
+	myInt->setValue(3);
+	//iPinA->GetListener()->Update(*myInt);
+	iPinA->Update(*myInt);
+
+
+	myInt->Release();
+	*/
+
+}
+
+
+int main (int, char**)
+{
+	DoTest();
+
+	// Cleanup
+	spcore::freeSpCoreRuntime();
+
+	return 0;
+}
diff --git a/src/core/tests/test_spcore_configuration.cpp b/src/core/tests/test_spcore_configuration.cpp
new file mode 100755
index 0000000..b6ed650
--- /dev/null
+++ b/src/core/tests/test_spcore_configuration.cpp
@@ -0,0 +1,145 @@
+#include "sphost/testcommon.h"
+#include "spcore/coreruntime.h"
+#include "spcore/configuration.h"
+//#include "spcore/basictypes.h"
+
+#include <assert.h>
+#include <iostream>
+#include <stdio.h>
+
+using namespace spcore;
+
+#define STR_SIZE 100
+struct data {
+	bool the_bool_true;
+	bool the_bool_false;
+	double the_double;
+	double the_double_neg;
+	int the_int;
+	int the_int_neg;
+	long long the_int64;
+	long long the_int_neg64;
+	char the_string[STR_SIZE];
+};
+
+void set_data (struct data* d) {
+	memset (d, 0, sizeof(struct data));
+	d->the_bool_true= true;
+	d->the_bool_false= false;
+	d->the_double= 12345.6789;
+	d->the_double_neg= -12345.6789;
+	d->the_int= 2147483640;
+	d->the_int_neg= -2147483640;
+	d->the_int64= 1152921504606846976LL;
+	d->the_int_neg64= -1152921504606846976LL;
+	memset (d->the_string, 0, STR_SIZE);
+	strcpy (d->the_string, "String contents");
+}
+
+void write_data (IConfiguration* cfg, const struct data* d) {
+	// Write data
+	if (!cfg->WriteBool("the_bool_true", d->the_bool_true)) ExitErr ("Write: the_bool_true");
+	if (!cfg->WriteBool("the_bool_false", d->the_bool_false)) ExitErr ("Write: the_bool_false");
+	if (!cfg->WriteDouble("the_double", d->the_double)) ExitErr ("Write: the_double");
+	if (!cfg->WriteDouble("the_double_neg", d->the_double_neg)) ExitErr ("Write: the_double_neg");
+	if (!cfg->WriteInt("the_int", d->the_int)) ExitErr ("Write: the_int");
+	if (!cfg->WriteInt("the_int_neg", d->the_int_neg)) ExitErr ("Write: the_int_neg");
+	if (!cfg->WriteInt64("the_int64", d->the_int64)) ExitErr ("Write: the_int64");
+	if (!cfg->WriteInt64("the_int_neg64", d->the_int_neg64)) ExitErr ("Write: the_int_neg64");
+	if (!cfg->WriteString("the_string", d->the_string)) ExitErr ("Write: the_string");
+}
+
+void read_data (const IConfiguration* cfg, struct data* d)
+{
+	// Write data
+	if (!cfg->ReadBool("the_bool_true", &d->the_bool_true)) ExitErr ("Read: the_bool_true");
+	if (!cfg->ReadBool("the_bool_false", &d->the_bool_false)) ExitErr ("Read: the_bool_false");
+	if (!cfg->ReadDouble("the_double", &d->the_double)) ExitErr ("Read: the_double");
+	if (!cfg->ReadDouble("the_double_neg", &d->the_double_neg)) ExitErr ("Read: the_double_neg");
+	if (!cfg->ReadInt("the_int", &d->the_int)) ExitErr ("Read: the_int");
+	if (!cfg->ReadInt("the_int_neg", &d->the_int_neg)) ExitErr ("Read: the_int_neg");
+	if (!cfg->ReadInt64("the_int64", &d->the_int64)) ExitErr ("Read: the_int64");
+	if (!cfg->ReadInt64("the_int_neg64", &d->the_int_neg64)) ExitErr ("Read: the_int_neg64");
+	
+	const char* retStr;
+	if (!cfg->ReadString("the_string", &retStr)) ExitErr ("Read: the_string");
+	memset (d->the_string, 0, STR_SIZE);
+	strcpy (d->the_string, retStr);
+}
+
+void compare (const struct data* d1, const struct data* d2)
+{
+	if (memcmp(d1, d2, sizeof(struct data))) ExitErr ("comparison error");
+}
+
+static
+void DoTest()
+{
+	spcore::ICoreRuntime* core= spcore::getSpCoreRuntime();
+	//DumpCoreRuntime(core);
+	
+
+	FILE* file= NULL;
+
+	// Create 1 & save
+	SmartPtr<IConfiguration> cfg1= core->GetConfiguration();
+	file= fopen("test_spcore_configuration1.cfg", "w");
+	if (!file) ExitErr ("Cannot open test_spcore_configuration1.cfg");
+	struct data d1;
+	set_data (&d1);
+	write_data (cfg1.get(), &d1);
+	if (!cfg1->Save(file)) ExitErr ("save failed");
+	fclose (file);
+	file= NULL;
+
+	// Load 
+	SmartPtr<IConfiguration> cfg2= core->GetConfiguration();
+	file= fopen("test_spcore_configuration1.cfg", "r");
+	if (!file) ExitErr ("Cannot open test_spcore_configuration1.cfg");
+	struct data d2;
+	memset (&d2, 0, sizeof(struct data));
+	if (!cfg2->Load(file)) ExitErr ("load failed");
+	fclose (file);
+	file= NULL;
+	read_data (cfg2.get(), &d2);
+	compare (&d1, &d2);
+
+	// Create path
+	if (!cfg1->WriteBool("path/inside/one/path", true)) ExitErr ("path/inside/one/path");
+	file= fopen("test_spcore_configuration2.cfg", "w");
+	if (!file) ExitErr ("Cannot open test_spcore_configuration2.cfg");
+	if (!cfg1->Save(file)) ExitErr ("save failed");
+	fclose (file);
+
+	// Set path
+	if (cfg1->SetPath("..")) ExitErr ("..");
+	if (!cfg1->SetPath("/path")) ExitErr ("/path");
+	if (!cfg1->SetPath("..")) ExitErr ("..");
+	if (!cfg1->SetPath("/")) ExitErr ("/");
+	if (cfg1->SetPath("the_int64")) ExitErr ("the_int64");
+
+	// Overwrite
+	if (!cfg1->WriteBool("the_int64", false)) ExitErr ("overwrite the_int64");
+	if (cfg1->WriteBool("path", false)) ExitErr ("overwrite path");
+
+	// Remove
+	if (!cfg1->Remove("path/inside/one")) ExitErr ("the_int64");
+
+	// Save file
+	file= fopen("test_spcore_configuration3.cfg", "w");
+	if (!file) ExitErr ("Cannot open test_spcore_configuration3.cfg");
+	if (!cfg1->Save(file)) ExitErr ("save failed");
+	fclose (file);
+}
+
+int main (int, char**)
+{
+	DoTest();
+	
+	// Cleanup
+	spcore::freeSpCoreRuntime();
+
+	printf ("Test passed successfully\n");
+
+	return 0;
+}
diff --git a/src/core/tests/test_spcore_runtime.cpp b/src/core/tests/test_spcore_runtime.cpp
new file mode 100644
index 0000000..bd4af86
--- /dev/null
+++ b/src/core/tests/test_spcore_runtime.cpp
@@ -0,0 +1,27 @@
+#include "sphost/testcommon.h"
+#include "spcore/coreruntime.h"
+
+#include <assert.h>
+#include <iostream>
+#include <stdio.h>
+
+
+static
+void DoTest()
+{
+	spcore::ICoreRuntime* core= spcore::getSpCoreRuntime();
+
+	DumpCoreRuntime(core);
+	
+	
+}
+
+int main (int, char**)
+{
+	DoTest();
+	
+	// Cleanup
+	spcore::freeSpCoreRuntime();
+
+	return 0;
+}
diff --git a/src/core/tests/test_spcore_smart_ptr.cpp b/src/core/tests/test_spcore_smart_ptr.cpp
new file mode 100644
index 0000000..42c959f
--- /dev/null
+++ b/src/core/tests/test_spcore_smart_ptr.cpp
@@ -0,0 +1,80 @@
+#include "spcore/baseobj.h"
+#include "spcore/basictypes.h"
+#include "sphost/testcommon.h"
+
+#include <assert.h>
+#include <iostream>
+#include <stdio.h>
+
+using namespace spcore;
+
+static
+void DoTest()
+{
+	if (!spcore::getSpCoreRuntime())
+		ExitErr("getSpCoreRuntime() failed");
+
+	// Create CTypeInt instance
+	SmartPtr<CTypeInt> intPtr= spcore::CTypeInt::CreateInstance();
+	if (!intPtr.get()) ExitErr("cannot create CTypeInt instance");
+
+	// Assignement to the same smart pointed type but const
+	SmartPtr<const CTypeInt> intConstPtr= intPtr;
+
+	// Smart pointers to CTypeAny. const and non-const
+	SmartPtr<CTypeAny> anyPtr;
+	SmartPtr<const CTypeAny> anyConstPtr;
+
+	// Upcasting
+	anyPtr= intPtr;
+	//anyPtr= intConstPtr;	// Compilation error
+	anyConstPtr= intPtr;
+	anyConstPtr= intConstPtr;
+	
+	//
+	// Static downcasting
+	//
+	intPtr= sptype_static_cast<CTypeInt>(anyPtr);
+//	intPtr= sptype_static_cast<const CTypeInt>(anyPtr);	// Compilation error
+//	intPtr= sptype_static_cast<CTypeInt>(anyConstPtr); // Compilation error. Casting const away not allowed
+	intConstPtr= sptype_static_cast<const CTypeInt>(anyPtr);
+	intConstPtr= sptype_static_cast<const CTypeInt>(anyConstPtr);
+
+	// Usage
+	intPtr->setValue(12);
+	if (intConstPtr->getValue()!= 12) ExitErr("static downcasting. usage error");
+
+	//
+	// Dynamic downcasting
+	//
+	intPtr= sptype_dynamic_cast<CTypeInt>(anyPtr);
+	if (intPtr.get()== NULL) ExitErr("intPtr= sptype_dynamic_cast<CTypeInt>(anyPtr): failed");
+	intConstPtr= sptype_dynamic_cast<const CTypeInt>(anyPtr);
+	if (intConstPtr.get()== NULL) ExitErr("intConstPtr= sptype_dynamic_cast<const CTypeInt>(anyPtr): failed");
+	intConstPtr= sptype_dynamic_cast<const CTypeInt>(anyConstPtr);
+	if (intConstPtr.get()== NULL) ExitErr("intConstPtr= sptype_dynamic_cast<const CTypeInt>(anyConstPtr): failed");
+	
+	// These dynamic downcasts must fail
+	SmartPtr<CTypeBool> boolPtr= CTypeBool::CreateInstance();
+	SmartPtr<const CTypeBool> boolConstPtr= boolPtr;
+	anyPtr= boolPtr;
+	anyConstPtr= boolConstPtr;
+	intPtr= sptype_dynamic_cast<CTypeInt>(anyPtr);
+	if (intPtr.get()!= NULL) ExitErr("bool downcasting: intPtr= sptype_dynamic_cast<CTypeInt>(anyPtr): failed");
+	intConstPtr= sptype_dynamic_cast<const CTypeInt>(anyPtr);
+	if (intConstPtr.get()!= NULL) ExitErr("bool downcasting: intConstPtr= sptype_dynamic_cast<const CTypeInt>(anyPtr): failed");
+	intConstPtr= sptype_dynamic_cast<const CTypeInt>(anyConstPtr);
+	if (intConstPtr.get()!= NULL) ExitErr("bool downcasting: intConstPtr= sptype_dynamic_cast<const CTypeInt>(anyConstPtr): failed");
+
+	
+}
+
+int main (int, char**)
+{
+	DoTest();
+	
+	// Cleanup
+	spcore::freeSpCoreRuntime();
+	
+	return 0;
+}
diff --git a/src/core/tests/test_spcore_wx_main_thread.cpp b/src/core/tests/test_spcore_wx_main_thread.cpp
new file mode 100755
index 0000000..9e44892
--- /dev/null
+++ b/src/core/tests/test_spcore_wx_main_thread.cpp
@@ -0,0 +1,208 @@
+/////////////////////////////////////////////////////////////////////////////
+// Name:        test_spcore_wx.cpp
+// Author:      Cesar Mauri Loba
+// Copyright:   (C) 2011 Cesar Mauri Loba - CREA Software Systems
+// 
+//  This program is free software: you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation, either version 3 of the License, or
+//  (at your option) any later version.
+//
+//  This program is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+/////////////////////////////////////////////////////////////////////////////
+
+#include "spcore/coreruntime.h"
+#include "sphost/testcommon.h"
+#include "nvwa/debug_new.h"
+#include "spcore/basictypes.h"
+
+#if defined(__WXGTK__) || defined(__WXMOTIF__) || defined(__WXX11__)
+	// Include Xlib for latter use on main
+	#include <X11/Xlib.h>
+#endif
+
+#include <wx/msgdlg.h>
+#include <wx/frame.h>
+#include <wx/panel.h>
+#include <wx/sizer.h>
+#include <stdio.h>
+#include <wx/init.h>
+#include <wx/timer.h>
+
+#include <boost/thread/thread.hpp>
+
+using namespace spcore;
+
+/*
+	Check threads enabled
+*/
+#if !wxUSE_THREADS
+     #error "This program requires thread support."
+#endif // wxUSE_THREADS
+
+/*
+	main frame class
+*/
+class MyFrame : public wxFrame
+{
+public:
+    MyFrame();
+	~MyFrame() {
+		delete m_timer;
+	}
+	void OnCloseWindow( wxCloseEvent& event );
+private:
+	void OnSize(wxSizeEvent& event);
+	void OnTimer(wxTimerEvent& event);
+
+	wxTimer * m_timer;
+
+    // any class wishing to process wxWidgets events must use this macro
+    DECLARE_EVENT_TABLE()
+};
+
+/*
+	myframe event table
+*/
+BEGIN_EVENT_TABLE(MyFrame, wxFrame)
+	EVT_CLOSE	( MyFrame::OnCloseWindow )
+	EVT_SIZE	( MyFrame::OnSize )
+	EVT_TIMER	( wxID_ANY, MyFrame::OnTimer )
+END_EVENT_TABLE()
+
+void MyFrame::OnCloseWindow(wxCloseEvent &event)
+{
+	event.Skip(); // Equivalent to: wxFrame::OnCloseWindow(event);
+}
+
+void MyFrame::OnSize(wxSizeEvent& event)
+{
+	Layout();
+	Fit();
+
+	event.Skip (false);
+}
+
+// ============================================================================
+// implementation
+// ============================================================================
+
+// ----------------------------------------------------------------------------
+// main frame
+// ----------------------------------------------------------------------------
+MyFrame::MyFrame() 
+: wxFrame(NULL, wxID_ANY, _T(""), wxDefaultPosition, wxDefaultSize, wxCAPTION|wxSYSTEM_MENU|wxCLOSE_BOX)
+{
+	m_timer= new wxTimer(this);
+	m_timer->Start (2000, true);
+}
+
+void MyFrame::OnTimer(wxTimerEvent& )
+{
+	wxMessageDialog dlg(this, _T("Modal dialog"));
+	dlg.ShowModal();
+}
+
+// ----------------------------------------------------------------------------
+// thread func
+// ----------------------------------------------------------------------------
+class VoidClass{};
+static VoidClass g_voidClassInstance;
+
+// Input pin for testing
+class InputPinTest : public CInputPinWriteOnly<CTypeInt, VoidClass> {
+public:
+	InputPinTest (int id)
+	: CInputPinWriteOnly<CTypeInt, VoidClass>("test_status", g_voidClassInstance)
+	, m_id(id)
+	{
+	}
+
+	virtual int DoSend(const CTypeInt & msg) {
+		printf ("InputPinTest id: %d, called with value %d\n", m_id, msg.getValue());
+		return 0;
+	}
+private:
+	int m_id;
+};
+
+static bool g_exitThread= false;
+
+void ThreadFunc()
+{
+	static int ids= 0;
+	int my_id= ids++;
+
+	SmartPtr<CTypeInt> my_int= CTypeInt::CreateInstance();
+
+	SmartPtr<InputPinTest> pin(new InputPinTest(my_id), false);
+
+	while (!g_exitThread) {
+		printf ("Thread %d. Before send\n", my_id);
+		my_int->setValue (my_int->getValue() + 1);
+		int retval= getSpCoreRuntime()->SendMessageMainThreadSync (my_int, *pin);
+		printf ("Thread %d. After send. Retval: %d\n", my_id, retval);
+		sleep_milliseconds(100);
+	}
+
+	printf ("Thread %d. Exiting\n", my_id);
+}
+
+// ----------------------------------------------------------------------------
+// main
+// ----------------------------------------------------------------------------
+
+int main(int argc, char *argv[]) {
+	
+#if defined(__WXGTK__) || defined(__WXMOTIF__) || defined(__WXX11__)
+	// Under X11 it's necessary enable threading support
+	if ( XInitThreads() == 0 ) {
+		ExitErr("Unable to initialize multithreaded X11 code (XInitThreads failed)");		
+		exit( EXIT_FAILURE );
+	}
+#endif
+
+	// Initialize spcore
+	ICoreRuntime* cr= getSpCoreRuntime();
+	if (!cr) return false;
+
+	if (cr->InitGUISupport (argc, argv))
+		 ExitErr("wxEntryStart failed");
+
+	// Create dialog
+	MyFrame* mf= new MyFrame();
+	mf->Show();
+
+	// Create threads
+	boost::thread thread1(ThreadFunc);
+	assert (thread1.joinable());
+	boost::thread thread2(ThreadFunc);
+	assert (thread2.joinable());
+	sleep_milliseconds (200);
+
+	// Run wxWidgets message pump
+	cr->RunMessageLoop ();
+
+	// Wait to continue sending messages from threads
+	sleep_milliseconds (200);
+
+	// End threads
+	g_exitThread= true;
+	thread2.join();	
+	thread1.join();	
+
+	// GUI cleanup
+	cr->CleanupGUISupport();
+	
+	// Free spcore
+	freeSpCoreRuntime();
+
+	// If execution reaches this => all tests ok
+	return 0;
+}
diff --git a/src/core/timecomponents.h b/src/core/timecomponents.h
new file mode 100644
index 0000000..676281f
--- /dev/null
+++ b/src/core/timecomponents.h
@@ -0,0 +1,153 @@
+/////////////////////////////////////////////////////////////////////////////
+// File:        timecomponents.cpp
+// Author:      Cesar Mauri Loba (cesar at crea-si dot com)
+// Copyright:   (C) 2011 Cesar Mauri Loba - CREA Software Systems
+//
+//  This program is free software: you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation, either version 3 of the License, or
+//  (at your option) any later version.
+//
+//  This program is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+/////////////////////////////////////////////////////////////////////////////
+#ifndef TIMECOMPONENTS_H
+	#define TIMECOMPONENTS_H
+#else
+	#error This file is intended to be included only once
+#endif
+
+#include "spcore/basictypes.h"
+#include "spcore/pinimpl.h"
+#include "spcore/component.h"
+//#include <vector>
+//#include <string>
+//#include <stdio.h>
+//#include <boost/thread/mutex.hpp>
+//#include <boost/thread/condition.hpp>
+
+#if defined(WIN32)
+	#include <windows.h>
+#else
+	#include <time.h>
+#endif
+
+using namespace std;
+
+namespace spcore {
+
+/**
+	chrono component - Chronograph
+		
+		Provides elapsed time in ms since reset.
+		
+	Input pins:
+		reset (CTypeAny)- Any received message resets the chronograph
+		read (CTypeAny)	- Any received message sends current elapsed time to output
+
+	Output pins:
+		elapsed (CTypeInt)
+
+	Command line
+*/
+class Chrono : public CComponentAdapter {
+public:
+	static const char* getTypeName() { return "chrono"; }
+	virtual const char* GetTypeName() const { return Chrono::getTypeName(); }
+	Chrono(const char * name, int argc, const char * argv[]) 
+	: CComponentAdapter(name, argc, argv)
+	{
+		m_opinElapsed= CTypeInt::CreateOutputPin("elapsed");
+		if (RegisterOutputPin(*m_opinElapsed)!= 0)
+			throw std::runtime_error("error registering output pin");
+
+  		if (RegisterInputPin(*SmartPtr<IInputPin>(new InputPinInReset("reset", *this), false))!= 0)
+			throw std::runtime_error("error creating input pin reset");
+
+
+  		if (RegisterInputPin(*SmartPtr<IInputPin>(new InputPinInRead("read", *this), false))!= 0)
+			throw std::runtime_error("error creating input pin read");
+
+		m_elapsed= CTypeInt::CreateInstance();
+	}
+
+	int OnReset () {
+
+#if defined(WIN32)
+		m_lastTickCount= GetTickCount();
+#else
+		clock_gettime(CLOCK_MONOTONIC, &m_lastTStamp);
+#endif
+		return 0;
+	}
+
+	int OnRead () {
+
+#if defined(WIN32)
+		DWORD now= GetTickCount();
+		if (now - m_lastTickCount> MAX_CHRONO_MS)
+			m_elapsed->setValue (MAX_CHRONO_MS);
+		else
+			m_elapsed->setValue((int)(now - m_lastTickCount));
+#else
+		struct timespec now;
+		clock_gettime(CLOCK_MONOTONIC, &now);
+
+		if (now.tv_sec - m_lastTStamp.tv_sec>= MAX_CHRONO_MS / 1000)
+			m_elapsed->setValue (MAX_CHRONO_MS);
+		else {
+			m_elapsed->setValue ((int) (now.tv_sec - m_lastTStamp.tv_sec) * 1000 + 
+				(now.tv_nsec - m_lastTStamp.tv_nsec) / 1000000);
+		}
+#endif
+		return m_opinElapsed->Send(m_elapsed);
+	}
+
+	virtual int	DoInitialize () {
+		OnReset(); 
+		return 0;
+	}
+
+private:
+	virtual ~Chrono() {}
+
+	// Max. measured ms
+	enum { MAX_CHRONO_MS= 2147483646 };
+
+	class InputPinInReset : public CInputPinWriteOnly<CTypeAny, Chrono> {
+	public:
+		InputPinInReset (const char * name, Chrono & component)
+		: CInputPinWriteOnly<CTypeAny, Chrono>(name, component) { }
+
+		virtual int DoSend(const CTypeAny & ) {	return this->m_component->OnReset(); }
+	};
+
+	class InputPinInRead : public CInputPinWriteOnly<CTypeAny, Chrono> {
+	public:
+		InputPinInRead (const char * name, Chrono & component)
+		: CInputPinWriteOnly<CTypeAny, Chrono>(name, component) { }
+
+		virtual int DoSend(const CTypeAny & ) {	return this->m_component->OnRead(); }
+	};
+
+	//
+	// Data members
+	//
+	SmartPtr<IOutputPin> m_opinElapsed;
+	SmartPtr<CTypeInt> m_elapsed;
+
+#if defined(WIN32)
+	DWORD m_lastTickCount;
+#else
+	struct timespec m_lastTStamp;
+#endif
+};
+
+typedef ComponentFactory<Chrono> ChronoFactory;
+
+} // namespace spcore
diff --git a/src/core/win32env.cpp b/src/core/win32env.cpp
new file mode 100755
index 0000000..671dcd1
--- /dev/null
+++ b/src/core/win32env.cpp
@@ -0,0 +1,175 @@
+/*-------------------------------------------------------------------------
+ *
+ * win32env.c
+ *	  putenv() and unsetenv() for win32, that updates both process
+ *	  environment and the cached versions in (potentially multiple)
+ *	  MSVCRT.
+ *
+ * Portions Copyright (c) 1996-2011, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ *
+ * IDENTIFICATION
+ *	  src/port/win32env.c
+ *
+ *-------------------------------------------------------------------------
+ PostgreSQL is released under the PostgreSQL License, a liberal Open Source license, similar to the BSD or MIT licenses.
+
+PostgreSQL Database Management System
+(formerly known as Postgres, then as Postgres95)
+
+Portions Copyright (c) 1996-2010, The PostgreSQL Global Development Group
+
+Portions Copyright (c) 1994, The Regents of the University of California
+
+Permission to use, copy, modify, and distribute this software and its documentation for any purpose, without fee, and without a written agreement is hereby granted, provided that the above copyright notice and this paragraph and the following two paragraphs appear in all copies.
+
+IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATIONS TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ */
+
+#include "config.h"
+#include <windows.h>
+#include <stdio.h>
+
+int
+win32_putenv(const char *envval)
+{
+	char	   *envcpy;
+	char	   *cp;
+
+	/*
+	 * Each version of MSVCRT has its own _putenv() call in the runtime
+	 * library.
+	 *
+	 * mingw always uses MSVCRT.DLL, but if we are in a Visual C++
+	 * environment, attempt to update the environment in all MSVCRT modules
+	 * that are currently loaded, to work properly with any third party
+	 * libraries linked against a different MSVCRT but still relying on
+	 * environment variables.
+	 *
+	 * Also separately update the system environment that gets inherited by
+	 * subprocesses.
+	 */
+#ifdef _MSC_VER
+	typedef int (_cdecl * PUTENVPROC) (const char *);
+	static struct
+	{
+		char	   *modulename;
+		HMODULE		hmodule;
+		PUTENVPROC	putenvFunc;
+	}			rtmodules[] =
+	{
+		{
+			"msvcrt", 0, NULL
+		},						/* Visual Studio 6.0 / mingw */
+		{
+			"msvcr70", 0, NULL
+		},						/* Visual Studio 2002 */
+		{
+			"msvcr71", 0, NULL
+		},						/* Visual Studio 2003 */
+		{
+			"msvcr80", 0, NULL
+		},						/* Visual Studio 2005 */
+		{
+			"msvcr90", 0, NULL
+		},						/* Visual Studio 2008 */
+		{
+			NULL, 0, NULL
+		}
+	};
+	int			i;
+
+	for (i = 0; rtmodules[i].modulename; i++)
+	{
+		if (rtmodules[i].putenvFunc == NULL)
+		{
+			if (rtmodules[i].hmodule == 0)
+			{
+				/* Not attempted before, so try to find this DLL */
+				rtmodules[i].hmodule = GetModuleHandleA(rtmodules[i].modulename);
+				if (rtmodules[i].hmodule == NULL)
+				{
+					/*
+					 * Set to INVALID_HANDLE_VALUE so we know we have tried
+					 * this one before, and won't try again.
+					 */
+					rtmodules[i].hmodule = (HMODULE) INVALID_HANDLE_VALUE;
+					continue;
+				}
+				else
+				{
+					rtmodules[i].putenvFunc = (PUTENVPROC) GetProcAddress(rtmodules[i].hmodule, "_putenv");
+					if (rtmodules[i].putenvFunc == NULL)
+					{
+						CloseHandle(rtmodules[i].hmodule);
+						rtmodules[i].hmodule = (HMODULE) INVALID_HANDLE_VALUE;
+						continue;
+					}
+				}
+			}
+			else
+			{
+				/*
+				 * Module loaded, but we did not find the function last time.
+				 * We're not going to find it this time either...
+				 */
+				continue;
+			}
+		}
+		/* At this point, putenvFunc is set or we have exited the loop */
+		rtmodules[i].putenvFunc(envval);
+	}
+#endif   /* _MSC_VER */
+
+	/*
+	 * Update the process environment - to make modifications visible to child
+	 * processes.
+	 *
+	 * Need a copy of the string so we can modify it.
+	 */
+	envcpy = strdup(envval);
+	if (!envcpy)
+		return -1;
+	cp = strchr(envcpy, '=');
+	if (cp == NULL)
+	{
+		free(envcpy);
+		return -1;
+	}
+	*cp = '\0';
+	cp++;
+	if (strlen(cp))
+	{
+		/*
+		 * Only call SetEnvironmentVariable() when we are adding a variable,
+		 * not when removing it. Calling it on both crashes on at least
+		 * certain versions of MingW.
+		 */
+		if (!SetEnvironmentVariableA(envcpy, cp))
+		{
+			free(envcpy);
+			return -1;
+		}
+	}
+	free(envcpy);
+
+	/* Finally, update our "own" cache */
+	return _putenv(envval);
+}
+
+void
+win32_unsetenv(const char *name)
+{
+	char	   *envbuf;
+
+	envbuf = (char *) malloc(strlen(name) + 2);
+	if (!envbuf)
+		return;
+
+	sprintf(envbuf, "%s=", name);
+	win32_putenv(envbuf);
+	free(envbuf);
+}
diff --git a/src/creavision/CMakeLists.txt b/src/creavision/CMakeLists.txt
new file mode 100755
index 0000000..b71faa1
--- /dev/null
+++ b/src/creavision/CMakeLists.txt
@@ -0,0 +1,90 @@
+cmake_minimum_required(VERSION 2.6)
+project(creavision)
+
+set(creavision_SRCS
+	crvcamera.h
+	crvcamera.cpp
+	crvcamera_enum.h
+	crvcamera_enum.cpp	
+	crvcolor.cpp
+	crvcolor.h
+	crvgeomtry.cpp
+	crvgeomtry.h
+	crvhistogram.cpp
+	crvhistogram.h
+	crvimage.cpp
+	crvimage.h
+	crvmisc.cpp
+	crvmisc.h
+	crvnormroi.cpp
+	crvnormroi.h
+	crvskindetection.cpp
+	crvskindetection.h
+)
+
+IF(CMAKE_SYSTEM_NAME MATCHES "Linux")
+FIND_PACKAGE( GLIB2 REQUIRED )
+INCLUDE_DIRECTORIES (${GLIB2_INCLUDE_DIRS})
+INCLUDE_DIRECTORIES (../libwebcam)
+set(creavision_SRCS ${creavision_SRCS}
+	crvcamera_v4l2.cpp
+	crvcamera_v4l2.h
+	colorspaces.cpp
+	colorspaces.h
+	pwc-ioctl.h
+	defs.h
+)
+ELSEIF(WIN32)
+set(creavision_SRCS ${creavision_SRCS}
+	crvcamera_wdm.cpp
+	crvcamera_wdm.h
+	videoInput.cpp
+	videoInput.h
+)
+ELSE(CMAKE_SYSTEM_NAME MATCHES "Linux")
+set(creavision_SRCS ${creavision_SRCS}
+	crvcamera_cv.cpp
+	crvcamera_cv.h
+)
+ENDIF(CMAKE_SYSTEM_NAME MATCHES "Linux")
+
+if(UNIX)
+	# For UNIX platforms we assume OpenCV is under /usr which 
+	# would not be always true
+#	set (OpenCV_DIR "/usr")
+endif(UNIX)
+
+FIND_PACKAGE( OpenCV REQUIRED core video highgui imgproc)
+
+if(WIN32)
+	if (MSVC)
+		configure_file("${OpenCV_DIR}/bin/Debug/opencv_core220d.dll" ${RUNTIME_OUTPUT_DIRECTORY}/Debug COPYONLY)
+		configure_file("${OpenCV_DIR}/bin/opencv_core220.dll" ${RUNTIME_OUTPUT_DIRECTORY}/Release COPYONLY)
+		
+		configure_file("${OpenCV_DIR}/bin/Debug/opencv_highgui220d.dll" ${RUNTIME_OUTPUT_DIRECTORY}/Debug COPYONLY)
+		configure_file("${OpenCV_DIR}/bin/opencv_highgui220.dll" ${RUNTIME_OUTPUT_DIRECTORY}/Release COPYONLY)
+		
+		configure_file("${OpenCV_DIR}/bin/Debug/opencv_imgproc220d.dll" ${RUNTIME_OUTPUT_DIRECTORY}/Debug COPYONLY)
+		configure_file("${OpenCV_DIR}/bin/opencv_imgproc220.dll" ${RUNTIME_OUTPUT_DIRECTORY}/Release COPYONLY)
+		
+		configure_file("${OpenCV_DIR}/bin/Debug/opencv_video220d.dll" ${RUNTIME_OUTPUT_DIRECTORY}/Debug COPYONLY)
+		configure_file("${OpenCV_DIR}/bin/opencv_video220.dll" ${RUNTIME_OUTPUT_DIRECTORY}/Release COPYONLY)
+	endif(MSVC)
+
+	install (FILES 
+		"${OpenCV_DIR}/bin/opencv_core220.dll"
+		"${OpenCV_DIR}/bin/opencv_highgui220.dll"
+		"${OpenCV_DIR}/bin/opencv_imgproc220.dll"
+		"${OpenCV_DIR}/bin/opencv_video220.dll"
+		DESTINATION ${LIBRUNTIMEDIR}
+	)
+endif(WIN32)
+
+add_library (creavision STATIC ${creavision_SRCS})
+TARGET_LINK_LIBRARIES(creavision ${OpenCV_LIBS} )
+
+IF(CMAKE_SYSTEM_NAME MATCHES "Linux")
+	TARGET_LINK_LIBRARIES(creavision libwebcam v4l2)
+ELSEIF(WIN32)
+	TARGET_LINK_LIBRARIES(creavision ole32.lib strmiids.lib uuid.lib dxguid.lib)
+ENDIF(CMAKE_SYSTEM_NAME MATCHES "Linux")
diff --git a/src/creavision/CreaVision_eviacam.vcproj b/src/creavision/CreaVision_eviacam.vcproj
new file mode 100755
index 0000000..4a8924e
--- /dev/null
+++ b/src/creavision/CreaVision_eviacam.vcproj
@@ -0,0 +1,202 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+	ProjectType="Visual C++"
+	Version="7.10"
+	Name="creavision"
+	ProjectGUID="{FF220E89-E196-48A7-8FD6-6382A32502E7}"
+	SccProjectName=""
+	SccLocalPath="">
+	<Platforms>
+		<Platform
+			Name="Win32"/>
+	</Platforms>
+	<Configurations>
+		<Configuration
+			Name="Release|Win32"
+			OutputDirectory="$(SolutionDir)$(ConfigurationName)"
+			IntermediateDirectory="$(SolutionDir)$(ConfigurationName)\creavision"
+			ConfigurationType="4"
+			UseOfMFC="0"
+			ATLMinimizesCRunTimeLibraryUsage="FALSE"
+			CharacterSet="2">
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="2"
+				InlineFunctionExpansion="1"
+				AdditionalIncludeDirectories=""$(CVPATH)\cv\include";"$(CVPATH)\cxcore\include";"$(CVPATH)\otherlibs\highgui";"$(CVPATH)\cvaux\include";"$(PSDK_DIR)\Samples\Multimedia\DirectShow\BaseClasses""
+				PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;NOPCH;__WXMSW__"
+				StringPooling="TRUE"
+				RuntimeLibrary="2"
+				EnableFunctionLevelLinking="TRUE"
+				UsePrecompiledHeader="2"
+				AssemblerListingLocation="$(SolutionDir)$(ConfigurationName)\creavision\"
+				ObjectFile="$(SolutionDir)$(ConfigurationName)\creavision\"
+				ProgramDataBaseFileName="$(SolutionDir)$(ConfigurationName)\creavision.pdb"
+				WarningLevel="4"
+				SuppressStartupBanner="TRUE"
+				CompileAs="0"/>
+			<Tool
+				Name="VCCustomBuildTool"/>
+			<Tool
+				Name="VCLibrarianTool"
+				OutputFile="$(SolutionDir)$(ConfigurationName)\$(ProjectName).lib"
+				SuppressStartupBanner="TRUE"/>
+			<Tool
+				Name="VCMIDLTool"/>
+			<Tool
+				Name="VCPostBuildEventTool"/>
+			<Tool
+				Name="VCPreBuildEventTool"/>
+			<Tool
+				Name="VCPreLinkEventTool"/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="NDEBUG"
+				Culture="3082"/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"/>
+			<Tool
+				Name="VCManagedWrapperGeneratorTool"/>
+			<Tool
+				Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+		</Configuration>
+		<Configuration
+			Name="Debug|Win32"
+			OutputDirectory="$(SolutionDir)$(ConfigurationName)"
+			IntermediateDirectory="$(SolutionDir)$(ConfigurationName)\creavision"
+			ConfigurationType="4"
+			UseOfMFC="0"
+			ATLMinimizesCRunTimeLibraryUsage="FALSE"
+			CharacterSet="2">
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories=""$(CVPATH)\cv\include";"$(CVPATH)\cxcore\include";"$(CVPATH)\otherlibs\highgui";"$(CVPATH)\cvaux\include";"$(PSDK_DIR)\Samples\Multimedia\DirectShow\BaseClasses""
+				PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="3"
+				UsePrecompiledHeader="0"
+				AssemblerListingLocation="$(SolutionDir)$(ConfigurationName)\creavision\"
+				ObjectFile="$(SolutionDir)$(ConfigurationName)\creavision\"
+				ProgramDataBaseFileName="$(SolutionDir)$(ConfigurationName)\creavision.pdb"
+				WarningLevel="4"
+				SuppressStartupBanner="TRUE"
+				DebugInformationFormat="4"
+				CompileAs="0"/>
+			<Tool
+				Name="VCCustomBuildTool"/>
+			<Tool
+				Name="VCLibrarianTool"
+				OutputFile="$(SolutionDir)$(ConfigurationName)\$(ProjectName).lib"
+				SuppressStartupBanner="TRUE"/>
+			<Tool
+				Name="VCMIDLTool"/>
+			<Tool
+				Name="VCPostBuildEventTool"/>
+			<Tool
+				Name="VCPreBuildEventTool"/>
+			<Tool
+				Name="VCPreLinkEventTool"/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_DEBUG"
+				Culture="3082"/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"/>
+			<Tool
+				Name="VCManagedWrapperGeneratorTool"/>
+			<Tool
+				Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+		</Configuration>
+	</Configurations>
+	<References>
+	</References>
+	<Files>
+		<Filter
+			Name="Source Files"
+			Filter="cpp;c;cxx;rc;def;r;odl;idl;hpj;bat">
+			<File
+				RelativePath=".\crvcamera.cpp">
+			</File>
+			<File
+				RelativePath=".\crvcamera_cv.cpp">
+			</File>
+			<File
+				RelativePath=".\crvcamera_enum.cpp">
+			</File>
+			<File
+				RelativePath=".\crvcamera_wdm.cpp">
+			</File>
+			<File
+				RelativePath=".\crvcolor.cpp">
+			</File>
+			<File
+				RelativePath=".\crvgeomtry.cpp">
+			</File>
+			<File
+				RelativePath=".\crvhistogram.cpp">
+			</File>
+			<File
+				RelativePath=".\crvimage.cpp">
+			</File>
+			<File
+				RelativePath=".\crvmisc.cpp">
+			</File>
+			<File
+				RelativePath=".\crvnormroi.cpp">
+			</File>
+			<File
+				RelativePath=".\crvskindetection.cpp">
+			</File>
+			<File
+				RelativePath=".\videoInput.cpp">
+			</File>
+		</Filter>
+		<Filter
+			Name="Header Files"
+			Filter="h;hpp;hxx;hm;inl">
+			<File
+				RelativePath=".\crvcamera.h">
+			</File>
+			<File
+				RelativePath=".\crvcamera_cv.h">
+			</File>
+			<File
+				RelativePath=".\crvcamera_enum.h">
+			</File>
+			<File
+				RelativePath=".\crvcamera_wdm.h">
+			</File>
+			<File
+				RelativePath=".\crvcolor.h">
+			</File>
+			<File
+				RelativePath=".\crvgeomtry.h">
+			</File>
+			<File
+				RelativePath=".\crvhistogram.h">
+			</File>
+			<File
+				RelativePath=".\crvimage.h">
+			</File>
+			<File
+				RelativePath=".\crvmisc.h">
+			</File>
+			<File
+				RelativePath=".\crvnormroi.h">
+			</File>
+			<File
+				RelativePath=".\crvskindetection.h">
+			</File>
+			<File
+				RelativePath=".\videoInput.h">
+			</File>
+		</Filter>
+	</Files>
+	<Globals>
+	</Globals>
+</VisualStudioProject>
diff --git a/src/creavision/Makefile.am b/src/creavision/Makefile.am
new file mode 100755
index 0000000..02cdbf1
--- /dev/null
+++ b/src/creavision/Makefile.am
@@ -0,0 +1,18 @@
+noinst_HEADERS = crvimage.h crvskindetection.h crvcamera.h \
+	crvcamera_cv.h crvcolor.h crvgeomtry.h pwc-ioctl.h \
+	crvmisc.h crvhistogram.h crvnormroi.h crvcamera_v4l2.h \
+	crvcamera_enum.h colorspaces.h defs.h
+	
+dist_noinst_DATA = crvcamera_wdm.cpp videoInput.cpp \
+	CreaVision_eviacam.vcproj crvcamera_wdm.h videoInput.h
+
+libcreavision_la_LIBADD = $(OPENCV_LIBS) -lv4l2
+
+noinst_LTLIBRARIES = libcreavision.la
+
+INCLUDES = -I$(top_builddir)/libwebcam -I$(top_srcdir)/libwebcam
+
+libcreavision_la_SOURCES = crvcamera.cpp crvcamera_cv.cpp crvcamera_v4l2.cpp \
+	crvcolor.cpp crvgeomtry.cpp crvhistogram.cpp \
+	crvimage.cpp crvmisc.cpp crvskindetection.cpp \
+	crvnormroi.cpp crvcamera_enum.cpp colorspaces.cpp
diff --git a/src/creavision/colorspaces.cpp b/src/creavision/colorspaces.cpp
new file mode 100755
index 0000000..7ef57df
--- /dev/null
+++ b/src/creavision/colorspaces.cpp
@@ -0,0 +1,1398 @@
+/*******************************************************************************#
+#           guvcview              http://guvcview.berlios.de                    #
+#                                                                               #
+#           Paulo Assis <pj.assis at gmail.com>                                    #
+#           Nobuhiro Iwamatsu <iwamatsu at nigauri.org>                            # 
+#                                                                               #
+# This program is free software; you can redistribute it and/or modify          #
+# it under the terms of the GNU General Public License as published by          #
+# the Free Software Foundation; either version 2 of the License, or             #
+# (at your option) any later version.                                           #
+#                                                                               #
+# This program is distributed in the hope that it will be useful,               #
+# but WITHOUT ANY WARRANTY; without even the implied warranty of                #
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the                 #
+# GNU General Public License for more details.                                  #
+#                                                                               #
+# You should have received a copy of the GNU General Public License             #
+# along with this program; if not, write to the Free Software                   #
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA     #
+#                                                                               #
+********************************************************************************/
+
+#include <stdlib.h>
+#include <string.h>
+#include <glib.h>
+#include "colorspaces.h"
+//#include "v4l2uvc.h"
+
+/*------------------------------- Color space conversions --------------------*/
+/* regular yuv (YUYV) to rgb24*/
+void 
+yuyv2rgb (BYTE *pyuv, BYTE *prgb, int width, int height)
+{
+	int l=0;
+	int SizeYUV=height * width * 2; /* 2 bytes per pixel*/
+	for(l=0;l<SizeYUV;l=l+4) 
+	{	/*iterate every 4 bytes*/
+		/* standart: r = y0 + 1.402 (v-128) */
+		/* logitech: r = y0 + 1.370705 (v-128) */
+		*prgb++=CLIP(pyuv[l] + 1.402 * (pyuv[l+3]-128));
+		/* standart: g = y0 - 0.34414 (u-128) - 0.71414 (v-128)*/
+		/* logitech: g = y0 - 0.337633 (u-128)- 0.698001 (v-128)*/
+		*prgb++=CLIP(pyuv[l] - 0.34414 * (pyuv[l+1]-128) -0.71414*(pyuv[l+3]-128));
+		/* standart: b = y0 + 1.772 (u-128) */
+		/* logitech: b = y0 + 1.732446 (u-128) */
+		*prgb++=CLIP(pyuv[l] + 1.772 *( pyuv[l+1]-128));
+		/* standart: r1 =y1 + 1.402 (v-128) */
+		/* logitech: r1 = y1 + 1.370705 (v-128) */
+		*prgb++=CLIP(pyuv[l+2] + 1.402 * (pyuv[l+3]-128));
+		/* standart: g1 = y1 - 0.34414 (u-128) - 0.71414 (v-128)*/
+		/* logitech: g1 = y1 - 0.337633 (u-128)- 0.698001 (v-128)*/
+		*prgb++=CLIP(pyuv[l+2] - 0.34414 * (pyuv[l+1]-128) -0.71414 * (pyuv[l+3]-128));
+		/* standart: b1 = y1 + 1.772 (u-128) */
+		/* logitech: b1 = y1 + 1.732446 (u-128) */
+		*prgb++=CLIP(pyuv[l+2] + 1.772*(pyuv[l+1]-128));
+	}
+}
+
+/* used for rgb video (fourcc="RGB ")           */
+/* lines are on correct order                   */
+void 
+yuyv2bgr1 (BYTE *pyuv, BYTE *pbgr, int width, int height)
+{
+
+	int l=0;
+	int SizeYUV=height * width * 2; /* 2 bytes per pixel*/
+	for(l=0;l<SizeYUV;l=l+4) 
+	{	/*iterate every 4 bytes*/
+		/* standart: b = y0 + 1.772 (u-128) */
+		/* logitech: b = y0 + 1.732446 (u-128) */
+		*pbgr++=CLIP(pyuv[l] + 1.772 *( pyuv[l+1]-128));
+		/* standart: g = y0 - 0.34414 (u-128) - 0.71414 (v-128)*/
+		/* logitech: g = y0 - 0.337633 (u-128)- 0.698001 (v-128)*/
+		*pbgr++=CLIP(pyuv[l] - 0.34414 * (pyuv[l+1]-128) -0.71414*(pyuv[l+3]-128));
+		/* standart: r = y0 + 1.402 (v-128) */
+		/* logitech: r = y0 + 1.370705 (v-128) */
+		*pbgr++=CLIP(pyuv[l] + 1.402 * (pyuv[l+3]-128));
+		/* standart: b1 = y1 + 1.772 (u-128) */
+		/* logitech: b1 = y1 + 1.732446 (u-128) */
+		*pbgr++=CLIP(pyuv[l+2] + 1.772*(pyuv[l+1]-128));
+		/* standart: g1 = y1 - 0.34414 (u-128) - 0.71414 (v-128)*/
+		/* logitech: g1 = y1 - 0.337633 (u-128)- 0.698001 (v-128)*/
+		*pbgr++=CLIP(pyuv[l+2] - 0.34414 * (pyuv[l+1]-128) -0.71414 * (pyuv[l+3]-128));
+		/* standart: r1 =y1 + 1.402 (v-128) */
+		/* logitech: r1 = y1 + 1.370705 (v-128) */
+		*pbgr++=CLIP(pyuv[l+2] + 1.402 * (pyuv[l+3]-128));
+	}
+}
+
+/* yuv (YUYV) to bgr with lines upsidedown */
+/* used for bitmap files (DIB24)           */
+void 
+yuyv2bgr (BYTE *pyuv, BYTE *pbgr, int width, int height)
+{
+
+	int l=0;
+	int k=0;
+	BYTE *preverse;
+	int bytesUsed;
+	int SizeBGR=height * width * 3; /* 3 bytes per pixel*/
+	/* BMP byte order is bgr and the lines start from last to first*/
+	preverse=pbgr+SizeBGR;/*start at the end and decrement*/
+	for(l=0;l<height;l++) 
+	{	/*iterate every 1 line*/
+		preverse-=width*3;/*put pointer at begin of unprocessed line*/
+		bytesUsed=l*width*2;
+		for (k=0;k<(width*2);k=k+4)/*iterate every 4 bytes in the line*/
+		{                              
+			/* standart: b = y0 + 1.772 (u-128) */
+			/* logitech: b = y0 + 1.732446 (u-128) */
+			*preverse++=CLIP(pyuv[k+bytesUsed] + 1.772 *( pyuv[k+1+bytesUsed]-128)); 
+			/* standart: g = y0 - 0.34414 (u-128) - 0.71414 (v-128)*/
+			/* logitech: g = y0 - 0.337633 (u-128)- 0.698001 (v-128)*/
+			*preverse++=CLIP(pyuv[k+bytesUsed] - 0.34414 * (pyuv[k+1+bytesUsed]-128) 
+				-0.71414*(pyuv[k+3+bytesUsed]-128));
+			/* standart: r = y0 + 1.402 (v-128) */
+			/* logitech: r = y0 + 1.370705 (v-128) */
+			*preverse++=CLIP(pyuv[k+bytesUsed] + 1.402 * (pyuv[k+3+bytesUsed]-128));
+			/* standart: b1 = y1 + 1.772 (u-128) */
+			/* logitech: b1 = y1 + 1.732446 (u-128) */
+			*preverse++=CLIP(pyuv[k+2+bytesUsed] + 1.772*(pyuv[k+1+bytesUsed]-128));
+			/* standart: g1 = y1 - 0.34414 (u-128) - 0.71414 (v-128)*/
+			/* logitech: g1 = y1 - 0.337633 (u-128)- 0.698001 (v-128)*/
+			*preverse++=CLIP(pyuv[k+2+bytesUsed] - 0.34414 * (pyuv[k+1+bytesUsed]-128) 
+				-0.71414 * (pyuv[k+3+bytesUsed]-128)); 
+			/* standart: r1 =y1 + 1.402 (v-128) */
+			/* logitech: r1 = y1 + 1.370705 (v-128) */
+			*preverse++=CLIP(pyuv[k+2+bytesUsed] + 1.402 * (pyuv[k+3+bytesUsed]-128));
+		}
+		preverse-=width*3;/*get it back at the begin of processed line*/
+	}
+	preverse=NULL;
+}
+
+/*convert yyuv (packed) to yuyv (packed)
+* args: 
+*      framebuffer: pointer to frame buffer (yuyv)
+*      tmpbuffer: pointer to temp buffer containing yyuv packed data frame
+*      width: picture width
+*      height: picture height
+*/
+void yyuv_to_yuyv (BYTE *framebuffer, BYTE *tmpbuffer, int width, int height)
+{
+	BYTE *ptmp=NULL;
+	BYTE *pfmb=NULL;
+	ptmp = tmpbuffer;
+	pfmb = framebuffer;
+	
+	int h=0;
+	int w=0;
+	
+	for(h=0;h<height;h++) 
+	{
+		for(w=0;w<(width*2);w+=4) 
+		{
+			/* Y0 */
+			pfmb[0] = ptmp[0];
+			/* U */
+			pfmb[1] = ptmp[2];
+			/* Y1 */
+			pfmb[2] = ptmp[1];
+			/* V */
+			pfmb[3] = ptmp[3];
+			
+			ptmp += 4;
+			pfmb += 4;
+		}
+	}
+}
+
+
+/*convert uyvy (packed) to yuyv (packed)
+* args: 
+*      framebuffer: pointer to frame buffer (yuyv)
+*      tmpbuffer: pointer to temp buffer containing uyvy packed data frame
+*      width: picture width
+*      height: picture height
+*/
+void uyvy_to_yuyv (BYTE *framebuffer, BYTE *tmpbuffer, int width, int height)
+{
+	BYTE *ptmp = tmpbuffer;
+	BYTE *pfmb = framebuffer;
+	int h=0;
+	int w=0;
+	
+	for(h=0;h<height;h++) 
+	{
+		for(w=0;w<(width*2);w+=4) 
+		{
+			/* Y0 */
+			pfmb[0] = ptmp[1];
+			/* U */
+			pfmb[1] = ptmp[0];
+			/* Y1 */
+			pfmb[2] = ptmp[3];
+			/* V */
+			pfmb[3] = ptmp[2];
+			
+			ptmp += 4;
+			pfmb += 4;
+		}
+	}
+}
+
+
+/*convert yvyu (packed) to yuyv (packed)
+* args: 
+*      framebuffer: pointer to frame buffer (yuyv)
+*      tmpbuffer: pointer to temp buffer containing yvyu packed data frame
+*      width: picture width
+*      height: picture height
+*/
+void yvyu_to_yuyv (BYTE *framebuffer, BYTE *tmpbuffer, int width, int height)
+{
+	BYTE *ptmp=NULL;
+	BYTE *pfmb=NULL;
+	ptmp = tmpbuffer;
+	pfmb = framebuffer;
+	
+	int h=0;
+	int w=0;
+	
+	for(h=0;h<height;h++) 
+	{
+		for(w=0;w<(width*2);w+=4) 
+		{
+			/* Y0 */
+			pfmb[0] = ptmp[0];
+			/* U */
+			pfmb[1] = ptmp[3];
+			/* Y1 */
+			pfmb[2] = ptmp[2];
+			/* V */
+			pfmb[3] = ptmp[1];
+			
+			ptmp += 4;
+			pfmb += 4;
+		}
+	}
+}
+
+/*convert yuv 420 planar (yu12) to yuv 422
+* args: 
+*      framebuffer: pointer to frame buffer (yuyv)
+*      tmpbuffer: pointer to temp buffer containing yuv420 planar data frame
+*      width: picture width
+*      height: picture height
+*/
+void yuv420_to_yuyv (BYTE *framebuffer, BYTE *tmpbuffer, int width, int height) 
+{
+	BYTE *py;
+	BYTE *pu;
+	BYTE *pv;
+	
+	int linesize = width * 2;
+	int uvlinesize = width / 2;
+	int offset=0;
+	int offset1=0;
+	int offsety=0;
+	int offsety1=0;
+	int offsetuv=0;
+	
+	py=tmpbuffer;
+	pu=py+(width*height);
+	pv=pu+(width*height/4);
+	
+	int h=0;
+	int w=0;
+	
+	int wy=0;
+	int huv=0;
+	int wuv=0;
+	
+	for(h=0;h<height;h+=2) 
+	{
+		wy=0;
+		wuv=0;
+		offset = h * linesize;
+		offset1 = (h + 1) * linesize;
+		offsety = h * width;
+		offsety1 = (h + 1) * width;
+		offsetuv = huv * uvlinesize;
+		
+		for(w=0;w<linesize;w+=4) 
+		{
+			/*y00*/
+			framebuffer[w + offset] = py[wy + offsety];
+			/*u0*/
+			framebuffer[(w + 1) + offset] = pu[wuv + offsetuv];
+			/*y01*/
+			framebuffer[(w + 2) + offset] = py[(wy + 1) + offsety];
+			/*v0*/
+			framebuffer[(w + 3) + offset] = pv[wuv + offsetuv];
+			
+			/*y10*/
+			framebuffer[w + offset1] = py[wy + offsety1];
+			/*u0*/
+			framebuffer[(w + 1) + offset1] = pu[wuv + offsetuv];
+			/*y11*/
+			framebuffer[(w + 2) + offset1] = py[(wy + 1) + offsety1];
+			/*v0*/
+			framebuffer[(w + 3) + offset1] = pv[wuv + offsetuv];
+			
+			wuv++;
+			wy+=2;
+		}
+		huv++;
+	}
+}
+
+/*convert yvu 420 planar (yv12) to yuv 422
+* args: 
+*      framebuffer: pointer to frame buffer (yuyv)
+*      tmpbuffer: pointer to temp buffer containing yuv420 planar data frame
+*      width: picture width
+*      height: picture height
+*/
+void yvu420_to_yuyv (BYTE *framebuffer, BYTE *tmpbuffer, int width, int height) 
+{
+	BYTE *py;
+	BYTE *pv;
+	BYTE *pu;
+	
+	int linesize = width * 2;
+	int uvlinesize = width / 2;
+	int offset=0;
+	int offset1=0;
+	int offsety=0;
+	int offsety1=0;
+	int offsetuv=0;
+	
+	py=tmpbuffer;
+	pv=py+(width*height);
+	pu=pv+((width*height)/4);
+	
+	int h=0;
+	int w=0;
+	
+	int wy=0;
+	int huv=0;
+	int wuv=0;
+	
+	for(h=0;h<height;h+=2) 
+	{
+		wy=0;
+		wuv=0;
+		offset = h * linesize;
+		offset1 = (h + 1) * linesize;
+		offsety = h * width;
+		offsety1 = (h + 1) * width;
+		offsetuv = huv * uvlinesize;
+		
+		for(w=0;w<linesize;w+=4) 
+		{
+			/*y00*/
+			framebuffer[w + offset] = py[wy + offsety];
+			/*u0*/
+			framebuffer[(w + 1) + offset] = pu[wuv + offsetuv];
+			/*y01*/
+			framebuffer[(w + 2) + offset] = py[(wy + 1) + offsety];
+			/*v0*/
+			framebuffer[(w + 3) + offset] = pv[wuv + offsetuv];
+			
+			/*y10*/
+			framebuffer[w + offset1] = py[wy + offsety1];
+			/*u0*/
+			framebuffer[(w + 1) + offset1] = pu[wuv + offsetuv];
+			/*y11*/
+			framebuffer[(w + 2) + offset1] = py[(wy + 1) + offsety1];
+			/*v0*/
+			framebuffer[(w + 3) + offset1] = pv[wuv + offsetuv];
+			
+			wuv++;
+			wy+=2;
+		}
+		huv++;
+	}
+}
+
+/*convert yuv 420 planar (uv interleaved) (nv12) to yuv 422
+* args: 
+*      framebuffer: pointer to frame buffer (yuyv)
+*      tmpbuffer: pointer to temp buffer containing yuv420 (nv12) planar data frame
+*      width: picture width
+*      height: picture height
+*/
+void nv12_to_yuyv (BYTE *framebuffer, BYTE *tmpbuffer, int width, int height) 
+{
+	BYTE *py;
+	BYTE *puv;
+	
+	int linesize = width * 2;
+	int offset=0;
+	int offset1=0;
+	int offsety=0;
+	int offsety1=0;
+	int offsetuv=0;
+	
+	py=tmpbuffer;
+	puv=py+(width*height);
+	
+	int h=0;
+	int w=0;
+	
+	int wy=0;
+	int huv=0;
+	int wuv=0;
+	
+	for(h=0;h<height;h+=2) 
+	{
+		wy=0;
+		wuv=0;
+		offset = h * linesize;
+		offset1 = (h+1) * linesize;
+		offsety = h * width;
+		offsety1 = (h+1) * width;
+		offsetuv = huv * width;
+		for(w=0;w<linesize;w+=4) 
+		{
+			/*y00*/
+			framebuffer[w + offset] = py[wy + offsety];
+			/*u0*/
+			framebuffer[(w + 1) + offset] = puv[wuv + offsetuv];
+			/*y01*/
+			framebuffer[(w + 2) + offset] = py[(wy + 1) + offsety];
+			/*v0*/
+			framebuffer[(w + 3) + offset] = puv[(wuv + 1) + offsetuv];
+			
+			/*y10*/
+			framebuffer[w + offset1] = py[wy + offsety1];
+			/*u0*/
+			framebuffer[(w + 1) + offset1] = puv[wuv + offsetuv];
+			/*y11*/
+			framebuffer[(w + 2) + offset1] = py[(wy + 1) + offsety1];
+			/*v0*/
+			framebuffer[(w + 3) + offset1] = puv[(wuv + 1) + offsetuv];
+			
+			wuv+=2;
+			wy+=2;
+		}
+		huv++;
+	}
+}
+
+/*convert yuv 420 planar (vu interleaved) (nv21) to yuv 422
+* args: 
+*      framebuffer: pointer to frame buffer (yuyv)
+*      tmpbuffer: pointer to temp buffer containing yuv420 (nv21) planar data frame
+*      width: picture width
+*      height: picture height
+*/
+void nv21_to_yuyv (BYTE *framebuffer, BYTE *tmpbuffer, int width, int height) 
+{
+	BYTE *py;
+	BYTE *puv;
+	
+	int linesize = width * 2;
+	int offset=0;
+	int offset1=0;
+	int offsety=0;
+	int offsety1=0;
+	int offsetuv=0;
+	
+	py=tmpbuffer;
+	puv=py+(width*height);
+	
+	int h=0;
+	int w=0;
+	
+	int wy=0;
+	int huv=0;
+	int wuv=0;
+	
+	for(h=0;h<height;h+=2) 
+	{
+		wy=0;
+		wuv=0;
+		offset = h * linesize;
+		offset1 = (h+1) * linesize;
+		offsety = h * width;
+		offsety1 = (h+1) * width;
+		offsetuv = huv * width;
+		for(w=0;w<linesize;w+=4) 
+		{
+			/*y00*/
+			framebuffer[w + offset] = py[wy + offsety];
+			/*u0*/
+			framebuffer[(w + 1) + offset] = puv[(wuv + 1) + offsetuv];
+			/*y01*/
+			framebuffer[(w + 2) + offset] = py[(wy + 1) + offsety];
+			/*v0*/
+			framebuffer[(w + 3) + offset] = puv[wuv + offsetuv];
+			
+			/*y10*/
+			framebuffer[w + offset1] = py[wy + offsety1];
+			/*u0*/
+			framebuffer[(w + 1) + offset1] = puv[(wuv + 1) + offsetuv];
+			/*y11*/
+			framebuffer[(w + 2) + offset1] = py[(wy + 1) + offsety1];
+			/*v0*/
+			framebuffer[(w + 3) + offset1] = puv[wuv + offsetuv];
+			
+			wuv+=2;
+			wy+=2;
+		}
+		huv++;
+	}
+}
+
+/*convert yuv 422 planar (uv interleaved) (nv16) to yuv 422
+* args: 
+*      framebuffer: pointer to frame buffer (yuyv)
+*      tmpbuffer: pointer to temp buffer containing yuv422 (nv16) planar data frame
+*      width: picture width
+*      height: picture height
+*/
+void nv16_to_yuyv (BYTE *framebuffer, BYTE *tmpbuffer, int width, int height)
+{
+	BYTE *py;
+	BYTE *puv;
+	
+	int linesize = width * 2;
+	int offset=0;
+	int offsety=0;
+	int offsetuv=0;
+	
+	py=tmpbuffer;
+	puv=py+(width*height);
+	
+	int h=0;
+	int w=0;
+	
+	int wy=0;
+	int huv=0;
+	int wuv=0;
+	
+	for(h=0;h<height;h++) 
+	{
+		wy=0;
+		wuv=0;
+		offset = h * linesize;
+		offsety = h * width;
+		offsetuv = huv * width;
+		for(w=0;w<linesize;w+=4) 
+		{
+			/*y00*/
+			framebuffer[w + offset] = py[wy + offsety];
+			/*u0*/
+			framebuffer[(w + 1) + offset] = puv[wuv + offsetuv];
+			/*y01*/
+			framebuffer[(w + 2) + offset] = py[(wy + 1) + offsety];
+			/*v0*/
+			framebuffer[(w + 3) + offset] = puv[(wuv + 1) + offsetuv];
+			
+			wuv+=2;
+			wy+=2;
+		}
+		huv++;
+	}
+}
+
+/*convert yuv 422 planar (vu interleaved) (nv61) to yuv 422
+* args: 
+*      framebuffer: pointer to frame buffer (yuyv)
+*      tmpbuffer: pointer to temp buffer containing yuv422 (nv61) planar data frame
+*      width: picture width
+*      height: picture height
+*/
+void nv61_to_yuyv (BYTE *framebuffer, BYTE *tmpbuffer, int width, int height)
+{
+	BYTE *py;
+	BYTE *puv;
+	
+	int linesize = width * 2;
+	int offset=0;
+	int offsety=0;
+	int offsetuv=0;
+	
+	py=tmpbuffer;
+	puv=py+(width*height);
+	
+	int h=0;
+	int w=0;
+	
+	int wy=0;
+	int huv=0;
+	int wuv=0;
+	
+	for(h=0;h<height;h++) 
+	{
+		wy=0;
+		wuv=0;
+		offset = h * linesize;
+		offsety = h * width;
+		offsetuv = huv * width;
+		for(w=0;w<linesize;w+=4) 
+		{
+			/*y00*/
+			framebuffer[w + offset] = py[wy + offsety];
+			/*u0*/
+			framebuffer[(w + 1) + offset] = puv[(wuv + 1) + offsetuv];
+			/*y01*/
+			framebuffer[(w + 2) + offset] = py[(wy + 1) + offsety];
+			/*v0*/
+			framebuffer[(w + 3) + offset] = puv[wuv + offsetuv];
+			
+			wuv+=2;
+			wy+=2;
+		}
+		huv++;
+	}
+}
+
+/*convert yuv 411 packed (y41p) to yuv 422
+* args: 
+*      framebuffer: pointer to frame buffer (yuyv)
+*      tmpbuffer: pointer to temp buffer containing y41p data frame
+*      width: picture width
+*      height: picture height
+*/
+void y41p_to_yuyv (BYTE *framebuffer, BYTE *tmpbuffer, int width, int height)
+{
+	int h=0;
+	int w=0;
+	int linesize = width * 3 /2;
+	int offset = 0;
+	
+	for(h=0;h<height;h++)
+	{
+		offset = linesize * h;
+		for(w=0;w<linesize;w+=12)
+		{
+			*framebuffer++=tmpbuffer[w+1 + offset]; //Y0
+			*framebuffer++=tmpbuffer[w   + offset]; //U0
+			*framebuffer++=tmpbuffer[w+3 + offset]; //Y1
+			*framebuffer++=tmpbuffer[w+2 + offset]; //V0
+			*framebuffer++=tmpbuffer[w+5 + offset]; //Y2
+			*framebuffer++=tmpbuffer[w   + offset]; //U0
+			*framebuffer++=tmpbuffer[w+7 + offset]; //Y3
+			*framebuffer++=tmpbuffer[w+2 + offset]; //V0
+			*framebuffer++=tmpbuffer[w+8 + offset]; //Y4
+			*framebuffer++=tmpbuffer[w+4 + offset]; //U4
+			*framebuffer++=tmpbuffer[w+9 + offset]; //Y5
+			*framebuffer++=tmpbuffer[w+6 + offset]; //V4
+			*framebuffer++=tmpbuffer[w+10+ offset]; //Y6
+			*framebuffer++=tmpbuffer[w+4 + offset]; //U4
+			*framebuffer++=tmpbuffer[w+11+ offset]; //Y7
+			*framebuffer++=tmpbuffer[w+6 + offset]; //V4
+		}
+	}
+}
+
+/*convert yuv mono (grey) to yuv 422
+* args: 
+*      framebuffer: pointer to frame buffer (yuyv)
+*      tmpbuffer: pointer to temp buffer containing grey (y only) data frame
+*      width: picture width
+*      height: picture height
+*/
+void grey_to_yuyv (BYTE *framebuffer, BYTE *tmpbuffer, int width, int height)
+{
+	int h=0;
+	int w=0;
+	int offset = 0;
+	
+	for(h=0;h<height;h++)
+	{
+		offset = width * h;
+		for(w=0;w<width;w++)
+		{
+			*framebuffer++=tmpbuffer[w + offset]; //Y
+			*framebuffer++=0x80;                  //U or V
+		}
+	}
+}
+
+/*convert SPCA501 (s501) to yuv 422
+* s501  |Y0..width..Y0|U..width/2..U|Y1..width..Y1|V..width/2..V|
+* signed values (-128;+127) must be converted to unsigned (0; 255)
+* args: 
+*      framebuffer: pointer to frame buffer (yuyv)
+*      tmpbuffer: pointer to temp buffer containing s501 data frame
+*      width: picture width
+*      height: picture height
+*/
+void s501_to_yuyv(BYTE *framebuffer, BYTE *tmpbuffer, int width, int height)
+{
+	BYTE *U, *V, *Y0, *Y1;
+	BYTE *line2;
+	int h, w;
+
+	Y0 = tmpbuffer; /*fisrt line*/
+	for (h = 0; h < height/2; h++ ) 
+	{
+		line2 = framebuffer + width * 2;   /* next line          */
+		U = Y0 + width;
+		Y1 = U + width / 2;
+		V = Y1 + width;
+		for (w = width / 2; --w >= 0; ) 
+		{
+			*framebuffer++ = (BYTE) (0x80 + *Y0++);
+			*framebuffer++ = (BYTE) (0x80 + *U);
+			*framebuffer++ = (BYTE) (0x80 + *Y0++);
+			*framebuffer++ = (BYTE) (0x80 + *V);
+
+			*line2++ = (BYTE) (0x80 + *Y1++);
+			*line2++ = (BYTE) (0x80 + *U++);
+			*line2++ = (BYTE) (0x80 + *Y1++);
+			*line2++ = (BYTE) (0x80 + *V++);
+		}
+		Y0 += width * 2;                  /* next block of lines */
+		framebuffer = line2;
+	}
+}
+
+/*convert SPCA505 (s505) to yuv 422
+* s505  |Y0..width..Y0|Y1..width..Y1|U..width/2..U|V..width/2..V|
+* signed values (-128;+127) must be converted to unsigned (0; 255)
+* args: 
+*      framebuffer: pointer to frame buffer (yuyv)
+*      tmpbuffer: pointer to temp buffer containing s501 data frame
+*      width: picture width
+*      height: picture height
+*/
+void s505_to_yuyv(BYTE *framebuffer, BYTE *tmpbuffer, int width, int height)
+{
+	BYTE *U, *V, *Y0, *Y1;
+	BYTE *line2;
+	int h, w;
+
+	Y0 = tmpbuffer; /*fisrt line*/
+	for (h = 0; h < height/2; h++ ) 
+	{
+		line2 = framebuffer + width * 2;   /* next line          */
+		Y1 = Y0 + width;
+		U  = Y1 + width;
+		V  = U + width/2;
+		for (w = width / 2; --w >= 0; ) 
+		{
+			*framebuffer++ = (BYTE) (0x80 + *Y0++);
+			*framebuffer++ = (BYTE) (0x80 + *U);
+			*framebuffer++ = (BYTE) (0x80 + *Y0++);
+			*framebuffer++ = (BYTE) (0x80 + *V);
+
+			*line2++ = (BYTE) (0x80 + *Y1++);
+			*line2++ = (BYTE) (0x80 + *U++);
+			*line2++ = (BYTE) (0x80 + *Y1++);
+			*line2++ = (BYTE) (0x80 + *V++);
+		}
+		Y0 += width * 2;                  /* next block of lines */
+		framebuffer = line2;
+	}
+}
+
+/*convert SPCA508 (s508) to yuv 422
+* s508  |Y0..width..Y0|U..width/2..U|V..width/2..V|Y1..width..Y1|
+* signed values (-128;+127) must be converted to unsigned (0; 255)
+* args: 
+*      framebuffer: pointer to frame buffer (yuyv)
+*      tmpbuffer: pointer to temp buffer containing s501 data frame
+*      width: picture width
+*      height: picture height
+*/
+void s508_to_yuyv(BYTE *framebuffer, BYTE *tmpbuffer, int width, int height)
+{
+	BYTE *U, *V, *Y0, *Y1;
+	BYTE *line2;
+	int h, w;
+
+	Y0 = tmpbuffer; /*fisrt line*/
+	for (h = 0; h < height/2; h++ ) 
+	{
+		line2 = framebuffer + width * 2;   /* next line          */
+		U = Y0 + width;
+		V = U + width/2;
+		Y1= V + width/2;
+		for (w = width / 2; --w >= 0; ) 
+		{
+			*framebuffer++ = (BYTE) (0x80 + *Y0++);
+			*framebuffer++ = (BYTE) (0x80 + *U);
+			*framebuffer++ = (BYTE) (0x80 + *Y0++);
+			*framebuffer++ = (BYTE) (0x80 + *V);
+
+			*line2++ = (BYTE) (0x80 + *Y1++);
+			*line2++ = (BYTE) (0x80 + *U++);
+			*line2++ = (BYTE) (0x80 + *Y1++);
+			*line2++ = (BYTE) (0x80 + *V++);
+		}
+		Y0 += width * 2;                  /* next block of lines */
+		framebuffer = line2;
+	}
+}
+
+// raw bayer functions 
+// from libv4l bayer.c, (C) 2008 Hans de Goede <j.w.r.degoede at hhs.nl>
+//Note: original bayer_to_bgr24 code from :
+//  1394-Based Digital Camera Control Library
+// 
+//  Bayer pattern decoding functions
+// 
+//  Written by Damien Douxchamps and Frederic Devernay
+static void convert_border_bayer_line_to_bgr24( BYTE* bayer, BYTE* adjacent_bayer,
+	BYTE *bgr, int width, gboolean start_with_green, gboolean blue_line)
+{
+	int t0, t1;
+
+	if (start_with_green) 
+	{
+	/* First pixel */
+		if (blue_line) 
+		{
+			*bgr++ = bayer[1];
+			*bgr++ = bayer[0];
+			*bgr++ = adjacent_bayer[0];
+		} 
+		else 
+		{
+			*bgr++ = adjacent_bayer[0];
+			*bgr++ = bayer[0];
+			*bgr++ = bayer[1];
+		}
+		/* Second pixel */
+		t0 = (bayer[0] + bayer[2] + adjacent_bayer[1] + 1) / 3;
+		t1 = (adjacent_bayer[0] + adjacent_bayer[2] + 1) >> 1;
+		if (blue_line) 
+		{
+			*bgr++ = bayer[1];
+			*bgr++ = (BYTE) t0;
+			*bgr++ = (BYTE) t1;
+		} 
+		else 
+		{
+			*bgr++ = (BYTE) t1;
+			*bgr++ = (BYTE) t0;
+			*bgr++ = bayer[1];
+		}
+		bayer++;
+		adjacent_bayer++;
+		width -= 2;
+	} 
+	else 
+	{
+		/* First pixel */
+		t0 = (bayer[1] + adjacent_bayer[0] + 1) >> 1;
+		if (blue_line) 
+		{
+			*bgr++ = bayer[0];
+			*bgr++ = (BYTE) t0;
+			*bgr++ = adjacent_bayer[1];
+		} 
+		else 
+		{
+			*bgr++ = adjacent_bayer[1];
+			*bgr++ = (BYTE) t0;
+			*bgr++ = bayer[0];
+		}
+		width--;
+	}
+
+	if (blue_line) 
+	{
+		for ( ; width > 2; width -= 2) 
+		{
+			t0 = (bayer[0] + bayer[2] + 1) >> 1;
+			*bgr++ = (BYTE) t0;
+			*bgr++ = bayer[1];
+			*bgr++ = adjacent_bayer[1];
+			bayer++;
+			adjacent_bayer++;
+
+			t0 = (bayer[0] + bayer[2] + adjacent_bayer[1] + 1) / 3;
+			t1 = (adjacent_bayer[0] + adjacent_bayer[2] + 1) >> 1;
+			*bgr++ = bayer[1];
+			*bgr++ = (BYTE) t0;
+			*bgr++ = (BYTE) t1;
+			bayer++;
+			adjacent_bayer++;
+		}
+	} 
+	else 
+	{
+		for ( ; width > 2; width -= 2) 
+		{
+			t0 = (bayer[0] + bayer[2] + 1) >> 1;
+			*bgr++ = adjacent_bayer[1];
+			*bgr++ = bayer[1];
+			*bgr++ = (BYTE) t0;
+			bayer++;
+			adjacent_bayer++;
+
+			t0 = (bayer[0] + bayer[2] + adjacent_bayer[1] + 1) / 3;
+			t1 = (adjacent_bayer[0] + adjacent_bayer[2] + 1) >> 1;
+			*bgr++ = (BYTE) t1;
+			*bgr++ = (BYTE) t0;
+			*bgr++ = bayer[1];
+			bayer++;
+			adjacent_bayer++;
+		}
+	}
+
+	if (width == 2) 
+	{
+		/* Second to last pixel */
+		t0 = (bayer[0] + bayer[2] + 1) >> 1;
+		if (blue_line) 
+		{
+			*bgr++ = (BYTE) t0;
+			*bgr++ = bayer[1];
+			*bgr++ = adjacent_bayer[1];
+		} 
+		else 
+		{
+			*bgr++ = adjacent_bayer[1];
+			*bgr++ = bayer[1];
+			*bgr++ = (BYTE) t0;
+		}
+		/* Last pixel */
+		t0 = (bayer[1] + adjacent_bayer[2] + 1) >> 1;
+		if (blue_line) 
+		{
+			*bgr++ = bayer[2];
+			*bgr++ = (BYTE) t0;
+			*bgr++ = adjacent_bayer[1];
+		}
+		else 
+		{
+			*bgr++ = adjacent_bayer[1];
+			*bgr++ = (BYTE) t0;
+			*bgr++ = bayer[2];
+		}
+	} 
+	else 
+	{
+		/* Last pixel */
+		if (blue_line) 
+		{
+			*bgr++ = bayer[0];
+			*bgr++ = bayer[1];
+			*bgr++ = adjacent_bayer[1];
+		} 
+		else 
+		{
+			*bgr++ = adjacent_bayer[1];
+			*bgr++ = bayer[1];
+			*bgr++ = bayer[0];
+		}
+	}
+}
+
+/* From libdc1394, which on turn was based on OpenCV's Bayer decoding */
+static void bayer_to_rgbbgr24(BYTE *bayer,
+	BYTE *bgr, int width, int height,
+	gboolean start_with_green, gboolean blue_line)
+{
+	/* render the first line */
+	convert_border_bayer_line_to_bgr24(bayer, bayer + width, bgr, width,
+		start_with_green, blue_line);
+	bgr += width * 3;
+
+	/* reduce height by 2 because of the special case top/bottom line */
+	for (height -= 2; height; height--) 
+	{
+		int t0, t1;
+		/* (width - 2) because of the border */
+		BYTE *bayerEnd = bayer + (width - 2);
+
+		if (start_with_green) 
+		{
+			/* OpenCV has a bug in the next line, which was
+			t0 = (bayer[0] + bayer[width * 2] + 1) >> 1; */
+			t0 = (bayer[1] + bayer[width * 2 + 1] + 1) >> 1;
+			/* Write first pixel */
+			t1 = (bayer[0] + bayer[width * 2] + bayer[width + 1] + 1) / 3;
+			if (blue_line) 
+			{
+				*bgr++ = (BYTE) t0;
+				*bgr++ = (BYTE) t1;
+				*bgr++ = bayer[width];
+			} 
+			else 
+			{
+				*bgr++ = bayer[width];
+				*bgr++ = (BYTE) t1;
+				*bgr++ = (BYTE) t0;
+			}
+
+			/* Write second pixel */
+			t1 = (bayer[width] + bayer[width + 2] + 1) >> 1;
+			if (blue_line) 
+			{
+				*bgr++ = (BYTE) t0;
+				*bgr++ = bayer[width + 1];
+				*bgr++ = (BYTE) t1;
+			} 
+			else 
+			{
+				*bgr++ = (BYTE) t1;
+				*bgr++ = bayer[width + 1];
+				*bgr++ = (BYTE) t0;
+			}
+			bayer++;
+		} 
+		else 
+		{
+			/* Write first pixel */
+			t0 = (bayer[0] + bayer[width * 2] + 1) >> 1;
+			if (blue_line) 
+			{
+				*bgr++ = (BYTE) t0;
+				*bgr++ = bayer[width];
+				*bgr++ = bayer[width + 1];
+			} 
+			else 
+			{
+				*bgr++ = bayer[width + 1];
+				*bgr++ = bayer[width];
+				*bgr++ = (BYTE) t0;
+			}
+		}
+
+		if (blue_line) 
+		{
+			for (; bayer <= bayerEnd - 2; bayer += 2) 
+			{
+				t0 = (bayer[0] + bayer[2] + bayer[width * 2] +
+					bayer[width * 2 + 2] + 2) >> 2;
+				t1 = (bayer[1] + bayer[width] +
+					bayer[width + 2] + bayer[width * 2 + 1] +
+					2) >> 2;
+				*bgr++ = (BYTE) t0;
+				*bgr++ = (BYTE) t1;
+				*bgr++ = bayer[width + 1];
+
+				t0 = (bayer[2] + bayer[width * 2 + 2] + 1) >> 1;
+				t1 = (bayer[width + 1] + bayer[width + 3] +
+					1) >> 1;
+				*bgr++ = (BYTE) t0;
+				*bgr++ = bayer[width + 2];
+				*bgr++ = (BYTE) t1;
+			}
+		} 
+		else 
+		{
+			for (; bayer <= bayerEnd - 2; bayer += 2) 
+			{
+				t0 = (bayer[0] + bayer[2] + bayer[width * 2] +
+					bayer[width * 2 + 2] + 2) >> 2;
+				t1 = (bayer[1] + bayer[width] +
+					bayer[width + 2] + bayer[width * 2 + 1] +
+					2) >> 2;
+				*bgr++ = bayer[width + 1];
+				*bgr++ = (BYTE) t1;
+				*bgr++ = (BYTE) t0;
+
+				t0 = (bayer[2] + bayer[width * 2 + 2] + 1) >> 1;
+				t1 = (bayer[width + 1] + bayer[width + 3] +
+					1) >> 1;
+				*bgr++ = (BYTE) t1;
+				*bgr++ = bayer[width + 2];
+				*bgr++ = (BYTE) t0;
+			}
+		}
+
+		if (bayer < bayerEnd) 
+		{
+			/* write second to last pixel */
+			t0 = (bayer[0] + bayer[2] + bayer[width * 2] +
+				bayer[width * 2 + 2] + 2) >> 2;
+			t1 = (bayer[1] + bayer[width] +
+				bayer[width + 2] + bayer[width * 2 + 1] +
+				2) >> 2;
+			if (blue_line) 
+			{
+				*bgr++ = (BYTE) t0;
+				*bgr++ = (BYTE) t1;
+				*bgr++ = bayer[width + 1];
+			} 
+			else 
+			{
+				*bgr++ = bayer[width + 1];
+				*bgr++ = (BYTE) t1;
+				*bgr++ = (BYTE) t0;
+			}
+			/* write last pixel */
+			t0 = (bayer[2] + bayer[width * 2 + 2] + 1) >> 1;
+			if (blue_line) 
+			{
+				*bgr++ = (BYTE) t0;
+				*bgr++ = bayer[width + 2];
+				*bgr++ = bayer[width + 1];
+			} 
+			else 
+			{
+				*bgr++ = bayer[width + 1];
+				*bgr++ = bayer[width + 2];
+				*bgr++ = (BYTE) t0;
+			}
+			bayer++;
+		} 
+		else
+		{
+			/* write last pixel */
+			t0 = (bayer[0] + bayer[width * 2] + 1) >> 1;
+			t1 = (bayer[1] + bayer[width * 2 + 1] + bayer[width] + 1) / 3;
+			if (blue_line) 
+			{
+				*bgr++ = (BYTE) t0;
+				*bgr++ = (BYTE) t1;
+				*bgr++ = bayer[width + 1];
+			} 
+			else 
+			{
+				*bgr++ = bayer[width + 1];
+				*bgr++ = (BYTE) t1;
+				*bgr++ = (BYTE) t0;
+			}
+		}
+
+		/* skip 2 border pixels */
+		bayer += 2;
+
+		blue_line = !blue_line;
+		start_with_green = !start_with_green;
+	}
+
+	/* render the last line */
+	convert_border_bayer_line_to_bgr24(bayer + width, bayer, bgr, width,
+		!start_with_green, !blue_line);
+}
+
+/*convert bayer raw data to rgb24
+* args: 
+*      pBay: pointer to buffer containing Raw bayer data data
+*      pRGB24: pointer to buffer containing rgb24 data
+*      width: picture width
+*      height: picture height
+*      pix_order: bayer pixel order (0=gb/rg   1=gr/bg  2=bg/gr  3=rg/bg)
+*/
+void 
+bayer_to_rgb24(BYTE *pBay, BYTE *pRGB24, int width, int height, int pix_order)
+{
+	switch (pix_order) 
+	{
+		//conversion functions are build for bgr, by switching b and r lines we get rgb
+		case 0: /* gbgbgb... | rgrgrg... (V4L2_PIX_FMT_SGBRG8)*/
+			bayer_to_rgbbgr24(pBay, pRGB24, width, height, TRUE, FALSE);
+			break;
+		
+		case 1: /* grgrgr... | bgbgbg... (V4L2_PIX_FMT_SGRBG8)*/
+			bayer_to_rgbbgr24(pBay, pRGB24, width, height, TRUE, TRUE);
+			break;
+		
+		case 2: /* bgbgbg... | grgrgr... (V4L2_PIX_FMT_SBGGR8)*/
+			bayer_to_rgbbgr24(pBay, pRGB24, width, height, FALSE, FALSE);
+			break;
+		
+		case 3: /* rgrgrg... ! gbgbgb... (V4L2_PIX_FMT_SRGGB8)*/
+			bayer_to_rgbbgr24(pBay, pRGB24, width, height, FALSE, TRUE);
+			break;
+			
+		default: /* default is 0*/
+			bayer_to_rgbbgr24(pBay, pRGB24, width, height, TRUE, FALSE);
+			break;
+	}
+}
+
+
+void
+rgb2yuyv(BYTE *prgb, BYTE *pyuv, int width, int height) 
+{
+
+	int i=0;
+	for(i=0;i<(width*height*3);i=i+6) 
+	{
+		/* y */ 
+		*pyuv++ =CLIP(0.299 * (prgb[i] - 128) + 0.587 * (prgb[i+1] - 128) + 0.114 * (prgb[i+2] - 128) + 128);
+		/* u */
+		*pyuv++ =CLIP(((- 0.147 * (prgb[i] - 128) - 0.289 * (prgb[i+1] - 128) + 0.436 * (prgb[i+2] - 128) + 128) +
+			(- 0.147 * (prgb[i+3] - 128) - 0.289 * (prgb[i+4] - 128) + 0.436 * (prgb[i+5] - 128) + 128))/2);
+		/* y1 */ 
+		*pyuv++ =CLIP(0.299 * (prgb[i+3] - 128) + 0.587 * (prgb[i+4] - 128) + 0.114 * (prgb[i+5] - 128) + 128); 
+		/* v*/
+		*pyuv++ =CLIP(((0.615 * (prgb[i] - 128) - 0.515 * (prgb[i+1] - 128) - 0.100 * (prgb[i+2] - 128) + 128) +
+			(0.615 * (prgb[i+3] - 128) - 0.515 * (prgb[i+4] - 128) - 0.100 * (prgb[i+5] - 128) + 128))/2);
+	}
+}
+
+void
+bgr2yuyv(BYTE *pbgr, BYTE *pyuv, int width, int height) 
+{
+
+	int i=0;
+	for(i=0;i<(width*height*3);i=i+6) 
+	{
+		/* y */ 
+		*pyuv++ =CLIP(0.299 * (pbgr[i+2] - 128) + 0.587 * (pbgr[i+1] - 128) + 0.114 * (pbgr[i] - 128) + 128);
+		/* u */
+		*pyuv++ =CLIP(((- 0.147 * (pbgr[i+2] - 128) - 0.289 * (pbgr[i+1] - 128) + 0.436 * (pbgr[i] - 128) + 128) +
+			(- 0.147 * (pbgr[i+5] - 128) - 0.289 * (pbgr[i+4] - 128) + 0.436 * (pbgr[i+3] - 128) + 128))/2);
+		/* y1 */ 
+		*pyuv++ =CLIP(0.299 * (pbgr[i+5] - 128) + 0.587 * (pbgr[i+4] - 128) + 0.114 * (pbgr[i+3] - 128) + 128); 
+		/* v*/
+		*pyuv++ =CLIP(((0.615 * (pbgr[i+2] - 128) - 0.515 * (pbgr[i+1] - 128) - 0.100 * (pbgr[i] - 128) + 128) +
+			(0.615 * (pbgr[i+5] - 128) - 0.515 * (pbgr[i+4] - 128) - 0.100 * (pbgr[i+3] - 128) + 128))/2);
+	}
+}
+
+/*use in utils.c for jpeg decoding  420 planar to 422
+* args: 
+*      out: pointer to data output of idct (macroblocks yyyy u v)
+*      pic: pointer to picture buffer (yuyv)
+*      width: picture width
+*/
+void yuv420pto422(int * out,unsigned char *pic,int width)
+{
+	int j, k;
+	unsigned char *pic0, *pic1;
+	int *outy, *outu, *outv;
+	int outy1 = 0;
+	int outy2 = 8;
+
+	//yyyyuv
+	pic0 = pic;
+	pic1 = pic + width;
+	outy = out;
+	outu = out + 64 * 4;
+	outv = out + 64 * 5;    
+	for (j = 0; j < 8; j++) 
+	{
+		for (k = 0; k < 8; k++)
+		{
+			if( k == 4) 
+			{ 
+				outy1 += 56;
+				outy2 += 56;
+			}
+			*pic0++ = CLIP(outy[outy1]);   //y1 line 1
+			*pic0++ = CLIP(128 + *outu);   //u  line 1-2
+			*pic0++ = CLIP(outy[outy1+1]); //y2 line 1
+			*pic0++ = CLIP(128 + *outv);   //v  line 1-2
+			*pic1++ = CLIP(outy[outy2]);   //y1 line 2
+			*pic1++ = CLIP(128 + *outu);   //u  line 1-2
+			*pic1++ = CLIP(outy[outy2+1]); //y2 line 2
+			*pic1++ = CLIP(128 + *outv);   //v  line 1-2
+			outy1 +=2; outy2 += 2; outu++; outv++;
+		}
+		if(j==3)
+		{
+			outy = out + 128;
+		} 
+		else 
+		{
+			outy += 16;
+		}
+		outy1 = 0;
+		outy2 = 8;
+		pic0 += 2 * (width -16);
+		pic1 += 2 * (width -16);
+	}
+}
+
+/*use in utils.c for jpeg decoding 422 planar to 422
+* args: 
+*      out: pointer to data output of idct (macroblocks yyyy u v)
+*      pic: pointer to picture buffer (yuyv)
+*      width: picture width
+*/
+void yuv422pto422(int * out,unsigned char *pic,int width)
+{
+	int j, k;
+	unsigned char *pic0, *pic1;
+	int *outy, *outu, *outv;
+	int outy1 = 0;
+	int outy2 = 8;
+	int outu1 = 0;
+	int outv1 = 0;
+ 
+	//yyyyuv
+	pic0 = pic;
+	pic1 = pic + width;
+	outy = out;
+	outu = out + 64 * 4;
+	outv = out + 64 * 5;    
+	for (j = 0; j < 4; j++) 
+	{
+		for (k = 0; k < 8; k++) 
+		{
+			if( k == 4)
+			{ 
+				outy1 += 56;
+				outy2 += 56;
+			}
+			*pic0++ = CLIP(outy[outy1]);        //y1 line 1
+			*pic0++ = CLIP(128 + outu[outu1]);  //u  line 1
+			*pic0++ = CLIP(outy[outy1+1]);      //y2 line 1
+			*pic0++ = CLIP(128 + outv[outv1]);  //v  line 1
+			*pic1++ = CLIP(outy[outy2]);        //y1 line 2
+			*pic1++ = CLIP(128 + outu[outu1+8]);//u  line 2
+			*pic1++ = CLIP(outy[outy2+1]);      //y2 line 2
+			*pic1++ = CLIP(128 + outv[outv1+8]);//v  line 2
+			outv1 += 1; outu1 += 1;
+			outy1 +=2; outy2 +=2;
+		}
+		outy += 16;outu +=8; outv +=8;
+		outv1 = 0; outu1=0;
+		outy1 = 0;
+		outy2 = 8;
+		pic0 += 2 * (width -16);
+		pic1 += 2 * (width -16);
+	}
+}
+
+/*use in utils.c for jpeg decoding 444 planar to 422
+* args: 
+*      out: pointer to data output of idct (macroblocks yyyy u v)
+*      pic: pointer to picture buffer (yuyv)
+*      width: picture width
+*/
+void yuv444pto422(int * out,unsigned char *pic,int width)
+{
+	int j, k;
+	unsigned char *pic0, *pic1;
+	int *outy, *outu, *outv;
+	int outy1 = 0;
+	int outy2 = 8;
+	int outu1 = 0;
+	int outv1 = 0;
+
+	//yyyyuv
+	pic0 = pic;
+	pic1 = pic + width;
+	outy = out;
+	outu = out + 64 * 4; // Ooops where did i invert ??
+	outv = out + 64 * 5;    
+	for (j = 0; j < 4; j++) 
+	{
+		for (k = 0; k < 4; k++) 
+		{
+			*pic0++ =CLIP( outy[outy1]);        //y1 line 1
+			*pic0++ =CLIP( 128 + outu[outu1]);  //u  line 1
+			*pic0++ =CLIP( outy[outy1+1]);      //y2 line 1
+			*pic0++ =CLIP( 128 + outv[outv1]);  //v  line 1
+			*pic1++ =CLIP( outy[outy2]);        //y1 line 2
+			*pic1++ =CLIP( 128 + outu[outu1+8]);//u  line 2
+			*pic1++ =CLIP( outy[outy2+1]);      //y2 line 2
+			*pic1++ =CLIP( 128 + outv[outv1+8]);//v  line 2
+			outv1 += 2; outu1 += 2;
+			outy1 +=2; outy2 +=2;
+		}
+		outy += 16;outu +=16; outv +=16;
+		outv1 = 0; outu1=0;
+		outy1 = 0;
+		outy2 = 8;
+		pic0 += 2 * (width -8);
+		pic1 += 2 * (width -8);
+	}
+}
+
+/*use in utils.c for jpeg decoding 400 planar to 422
+* args: 
+*      out: pointer to data output of idct (macroblocks yyyy )
+*      pic: pointer to picture buffer (yuyv)
+*      width: picture width
+*/
+void yuv400pto422(int * out,unsigned char *pic,int width)
+{
+	int j, k;
+	unsigned char *pic0, *pic1;
+	int *outy ;
+	int outy1 = 0;
+	int outy2 = 8;
+	pic0 = pic;
+	pic1 = pic + width;
+	outy = out;
+
+	//yyyy
+	for (j = 0; j < 4; j++) 
+	{
+		for (k = 0; k < 4; k++) 
+		{
+			*pic0++ = CLIP(outy[outy1]);  //y1 line 1
+			*pic0++ = 128 ;               //u
+			*pic0++ = CLIP(outy[outy1+1]);//y2 line 1
+			*pic0++ = 128 ;               //v
+			*pic1++ = CLIP(outy[outy2]);  //y1 line 2
+			*pic1++ = 128 ;               //u
+			*pic1++ = CLIP(outy[outy2+1]);//y2 line 2
+			*pic1++ = 128 ;               //v
+			outy1 +=2; outy2 +=2;  
+		}
+		outy += 16;
+		outy1 = 0;
+		outy2 = 8;
+		pic0 += 2 * (width -8);
+		pic1 += 2 * (width -8);
+	}
+}
+
diff --git a/src/creavision/colorspaces.h b/src/creavision/colorspaces.h
new file mode 100755
index 0000000..2fcb3ef
--- /dev/null
+++ b/src/creavision/colorspaces.h
@@ -0,0 +1,257 @@
+/*******************************************************************************#
+#           guvcview              http://guvcview.berlios.de                    #
+#                                                                               #
+#           Paulo Assis <pj.assis at gmail.com>                                    #
+#                                                                               #
+# This program is free software; you can redistribute it and/or modify          #
+# it under the terms of the GNU General Public License as published by          #
+# the Free Software Foundation; either version 2 of the License, or             #
+# (at your option) any later version.                                           #
+#                                                                               #
+# This program is distributed in the hope that it will be useful,               #
+# but WITHOUT ANY WARRANTY; without even the implied warranty of                #
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the                 #
+# GNU General Public License for more details.                                  #
+#                                                                               #
+# You should have received a copy of the GNU General Public License             #
+# along with this program; if not, write to the Free Software                   #
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA     #
+#                                                                               #
+********************************************************************************/
+
+#ifndef COLORSPACES_H
+#define COLORSPACES_H
+
+#include "defs.h"
+
+/*convert yuv 420 planar (yu12) to yuv 422
+* args: 
+*      framebuffer: pointer to frame buffer (yuyv)
+*      tmpbuffer: pointer to temp buffer containing yuv420 planar data frame
+*      width: picture width
+*      height: picture height
+*/
+void 
+yuv420_to_yuyv (BYTE *framebuffer, BYTE *tmpbuffer, int width, int height);
+
+/*convert yvu 420 planar (yv12) to yuv 422 (yuyv)
+* args: 
+*      framebuffer: pointer to frame buffer (yuyv)
+*      tmpbuffer: pointer to temp buffer containing yvu420 planar data frame
+*      width: picture width
+*      height: picture height
+*/
+void yvu420_to_yuyv (BYTE *framebuffer, BYTE *tmpbuffer, int width, int height);
+
+/*convert yuv 420 planar (uv interleaved) (nv12) to yuv 422
+* args: 
+*      framebuffer: pointer to frame buffer (yuyv)
+*      tmpbuffer: pointer to temp buffer containing yuv420 (nv12) planar data frame
+*      width: picture width
+*      height: picture height
+*/
+void nv12_to_yuyv (BYTE *framebuffer, BYTE *tmpbuffer, int width, int height);
+
+/*convert yuv 420 planar (vu interleaved) (nv21) to yuv 422
+* args: 
+*      framebuffer: pointer to frame buffer (yuyv)
+*      tmpbuffer: pointer to temp buffer containing yuv420 (nv21) planar data frame
+*      width: picture width
+*      height: picture height
+*/
+void nv21_to_yuyv (BYTE *framebuffer, BYTE *tmpbuffer, int width, int height);
+
+/*convert yuv 422 planar (uv interleaved) (nv16) to yuv 422
+* args: 
+*      framebuffer: pointer to frame buffer (yuyv)
+*      tmpbuffer: pointer to temp buffer containing yuv422 (nv16) planar data frame
+*      width: picture width
+*      height: picture height
+*/
+void nv16_to_yuyv (BYTE *framebuffer, BYTE *tmpbuffer, int width, int height);
+
+/*convert yuv 422 planar (vu interleaved) (nv61) to yuv 422
+* args: 
+*      framebuffer: pointer to frame buffer (yuyv)
+*      tmpbuffer: pointer to temp buffer containing yuv422 (nv61) planar data frame
+*      width: picture width
+*      height: picture height
+*/
+void nv61_to_yuyv (BYTE *framebuffer, BYTE *tmpbuffer, int width, int height);
+
+/*convert yyuv to yuyv
+* args: 
+*      framebuffer: pointer to frame buffer (yuyv)
+*      tmpbuffer: pointer to temp buffer containing a yyuv data frame
+*      width: picture width
+*      height: picture height
+*/
+void 
+yyuv_to_yuyv (BYTE *framebuffer, BYTE *tmpbuffer, int width, int height);
+
+/*convert uyvy (packed) to yuyv (packed)
+* args: 
+*      framebuffer: pointer to frame buffer (yuyv)
+*      tmpbuffer: pointer to temp buffer containing uyvy packed data frame
+*      width: picture width
+*      height: picture height
+*/
+void uyvy_to_yuyv (BYTE *framebuffer, BYTE *tmpbuffer, int width, int height);
+
+/*convert yvyu (packed) to yuyv (packed)
+* args: 
+*      framebuffer: pointer to frame buffer (yuyv)
+*      tmpbuffer: pointer to temp buffer containing yvyu packed data frame
+*      width: picture width
+*      height: picture height
+*/
+void yvyu_to_yuyv (BYTE *framebuffer, BYTE *tmpbuffer, int width, int height);
+
+/*convert yuv 411 packed (y41p) to yuv 422
+* args: 
+*      framebuffer: pointer to frame buffer (yuyv)
+*      tmpbuffer: pointer to temp buffer containing y41p data frame
+*      width: picture width
+*      height: picture height
+*/
+void y41p_to_yuyv (BYTE *framebuffer, BYTE *tmpbuffer, int width, int height);
+
+/*convert yuv mono (grey) to yuv 422
+* args: 
+*      framebuffer: pointer to frame buffer (yuyv)
+*      tmpbuffer: pointer to temp buffer containing grey (y only) data frame
+*      width: picture width
+*      height: picture height
+*/
+void grey_to_yuyv (BYTE *framebuffer, BYTE *tmpbuffer, int width, int height);
+
+/*convert SPCA501 (s501) to yuv 422
+* s501  |Y0..width..Y0|U..width/2..U|Y1..width..Y1|V..width/2..V|
+* signed values (-128;+127) must be converted to unsigned (0; 255)
+* args: 
+*      framebuffer: pointer to frame buffer (yuyv)
+*      tmpbuffer: pointer to temp buffer containing s501 data frame
+*      width: picture width
+*      height: picture height
+*/
+void s501_to_yuyv(BYTE *framebuffer, BYTE *tmpbuffer, int width, int height);
+
+/*convert SPCA505 (s505) to yuv 422
+* s505  |Y0..width..Y0|Y1..width..Y1|U..width/2..U|V..width/2..V|
+* signed values (-128;+127) must be converted to unsigned (0; 255)
+* args: 
+*      framebuffer: pointer to frame buffer (yuyv)
+*      tmpbuffer: pointer to temp buffer containing s501 data frame
+*      width: picture width
+*      height: picture height
+*/
+void s505_to_yuyv(BYTE *framebuffer, BYTE *tmpbuffer, int width, int height);
+
+/*convert SPCA508 (s508) to yuv 422
+* s508  |Y0..width..Y0|U..width/2..U|V..width/2..V|Y1..width..Y1|
+* signed values (-128;+127) must be converted to unsigned (0; 255)
+* args: 
+*      framebuffer: pointer to frame buffer (yuyv)
+*      tmpbuffer: pointer to temp buffer containing s501 data frame
+*      width: picture width
+*      height: picture height
+*/
+void s508_to_yuyv(BYTE *framebuffer, BYTE *tmpbuffer, int width, int height);
+
+/*convert yuyv to rgb24
+* args: 
+*      pyuv: pointer to buffer containing yuv data (yuyv)
+*      prgb: pointer to buffer containing rgb24 data
+*      width: picture width
+*      height: picture height
+*/
+void 
+yuyv2rgb (BYTE *pyuv, BYTE *prgb, int width, int height);
+
+
+/*convert yuyv to bgr with lines upsidedown
+* used for bitmap files (DIB24)
+* args: 
+*      pyuv: pointer to buffer containing yuv data (yuyv)
+*      prgb: pointer to buffer containing rgb24 data
+*      width: picture width
+*      height: picture height
+*/
+void 
+yuyv2bgr (BYTE *pyuv, BYTE *pbgr, int width, int height);
+
+/* used for rgb video (fourcc="RGB ")
+*  lines are in correct order
+*/
+void 
+yuyv2bgr1 (BYTE *pyuv, BYTE *pbgr, int width, int height);
+
+/*convert bayer raw data to rgb24
+* args: 
+*      pBay: pointer to buffer containing Raw bayer data data
+*      pRGB24: pointer to buffer containing rgb24 data
+*      width: picture width
+*      height: picture height
+*      pix_order: bayer pixel order (0=gb/rg   1=gr/bg  2=bg/gr  3=rg/bg)
+*/
+void 
+bayer_to_rgb24(BYTE *pBay, BYTE *pRGB24, int width, int height, int pix_order);
+
+/*convert rgb24 to yuyv
+* args: 
+*      prgb: pointer to buffer containing rgb24 data
+*      pyuv: pointer to buffer containing yuv data (yuyv)
+*      width: picture width
+*      height: picture height
+*/
+void
+rgb2yuyv(BYTE *prgb, BYTE *pyuv, int width, int height);
+
+/*convert bgr24 to yuyv
+* args: 
+*      pbgr: pointer to buffer containing bgr24 data
+*      pyuv: pointer to buffer containing yuv data (yuyv)
+*      width: picture width
+*      height: picture height
+*/
+void
+bgr2yuyv(BYTE *pbgr, BYTE *pyuv, int width, int height);
+
+/*use in utils.c for jpeg decoding  420 planar to 422
+* args: 
+*      out: pointer to data output of idct (macroblocks yyyy u v)
+*      pic: pointer to picture buffer (yuyv)
+*      width: picture width
+*/
+void 
+yuv420pto422(int * out,unsigned char *pic,int width);
+
+/*use in utils.c for jpeg decoding 422 planar to 422
+* args: 
+*      out: pointer to data output of idct (macroblocks yyyy u v)
+*      pic: pointer to picture buffer (yuyv)
+*      width: picture width
+*/
+void 
+yuv422pto422(int * out,unsigned char *pic,int width);
+
+/*use in utils.c for jpeg decoding 444 planar to 422
+* args: 
+*      out: pointer to data output of idct (macroblocks yyyy u v)
+*      pic: pointer to picture buffer (yuyv)
+*      width: picture width
+*/
+void 
+yuv444pto422(int * out,unsigned char *pic,int width);
+
+/*use in utils.c for jpeg decoding 400 planar to 422
+* args: 
+*      out: pointer to data output of idct (macroblocks yyyy )
+*      pic: pointer to picture buffer (yuyv)
+*      width: picture width
+*/
+void 
+yuv400pto422(int * out,unsigned char *pic,int width);
+
+#endif
+
diff --git a/src/creavision/crvcamera.cpp b/src/creavision/crvcamera.cpp
new file mode 100755
index 0000000..2b28b0e
--- /dev/null
+++ b/src/creavision/crvcamera.cpp
@@ -0,0 +1,119 @@
+/////////////////////////////////////////////////////////////////////////////
+// Name:        crvcamera.cpp
+// Purpose:  
+// Author:      Cesar Mauri Loba (cesar at crea-si dot com)
+// Modified by: 
+// Created:     30/05/2008
+// Copyright:   (C) 2008-10 Cesar Mauri Loba - CREA Software Systems
+// 
+//  This program is free software: you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation, either version 3 of the License, or
+//  (at your option) any later version.
+//
+//  This program is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+/////////////////////////////////////////////////////////////////////////////
+#include "crvcamera.h"
+#include "crvimage.h"
+#include <cv.h>
+#include <sys/timeb.h>
+#include <sys/types.h>
+#include <stdio.h>
+#include <cassert>
+
+// Return timestamp in ms
+static unsigned int GetTime (void)
+{
+	struct timeb now;	
+	ftime(&now);
+	return now.time*1000 + now.millitm;
+}
+
+CCamera::CCamera() throw (camera_exception)
+{
+	m_RealWidth=0;
+	m_RealHeight= 0;
+	m_RealFrameRate= 0.0f;
+	m_LastRealFrameRate= 0.0f;
+	m_lastTimeStamp= GetTime();
+	m_horizontalFlip= false;
+}
+
+CCamera::~CCamera(void)
+{
+	// Should call Close but is not done here
+	// because DoClose is virtual. We rely on
+	// derived classes
+}
+
+bool CCamera::Open()
+{
+	bool retval= DoOpen();
+	if (retval) m_lastTimeStamp= GetTime();
+	return retval;
+}
+
+void CCamera::Close()
+{
+	DoClose();
+}
+
+bool CCamera::QueryFrame (CIplImage& image)
+{
+	if (!DoQueryFrame(image)) return false;
+
+	assert(image.Initialized());
+
+	PostQueryFrame(image.ptr());
+
+	return true;
+}
+
+IplImage* CCamera::QueryFrame()
+{
+	IplImage* pImage= DoQueryFrame();
+	if (!pImage) return NULL;
+
+	PostQueryFrame(pImage);
+
+	return pImage;
+}
+
+void CCamera::PostQueryFrame(IplImage* pImage)
+{
+	// Update real size
+	m_RealWidth= pImage->width;
+	m_RealHeight= pImage->height;
+
+	// Update real FPS
+	int now= GetTime();
+	m_elapsedTime= now - m_lastTimeStamp;
+	m_lastTimeStamp= now;
+	m_LastRealFrameRate= m_RealFrameRate;
+
+	float weight= ((float) m_elapsedTime / 1000.0f) * 1.5f;
+	if (weight> 1.0f) weight= 1.0f;
+	if (m_elapsedTime> 0)
+		m_RealFrameRate= (1000.0f / (float) m_elapsedTime) * weight + m_LastRealFrameRate * (1.0f - weight);
+	else
+		m_RealFrameRate= 0;
+
+	// Flip image when needed to provide an image with top-left origin
+	if ( pImage->origin == 1 ) {
+		if (m_horizontalFlip) 
+			cvFlip (pImage, NULL, -1);
+		else 
+			cvFlip (pImage, NULL, 0);
+
+		pImage->origin= 0;
+	}
+	else 
+		if (m_horizontalFlip) 
+			cvFlip (pImage, NULL, 1);
+}
\ No newline at end of file
diff --git a/src/creavision/crvcamera.h b/src/creavision/crvcamera.h
new file mode 100755
index 0000000..6e495c6
--- /dev/null
+++ b/src/creavision/crvcamera.h
@@ -0,0 +1,187 @@
+/////////////////////////////////////////////////////////////////////////////
+// Name:        crvcamera.h
+// Purpose:  
+// Author:      Cesar Mauri Loba (cesar at crea-si dot com)
+// Modified by: 
+// Created:     30/05/2008
+// Copyright:   (C) 2008-10 Cesar Mauri Loba - CREA Software Systems
+// 
+//  This program is free software: you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation, either version 3 of the License, or
+//  (at your option) any later version.
+//
+//  This program is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+/////////////////////////////////////////////////////////////////////////////
+#ifndef CRVCAMERA_H_
+#define CRVCAMERA_H_
+
+#include <stdexcept>
+
+// Forward declarations
+class CCameraControl;
+typedef struct _IplImage IplImage;
+class CIplImage;
+
+// Class to signal errors during camera object construction
+class camera_exception : public std::runtime_error
+{
+public:
+	camera_exception (const char* msg) : std::runtime_error (msg) {}
+};
+
+#if defined (_MSC_VER)
+#pragma warning(disable: 4290)
+#endif
+
+class CCamera
+{
+public:
+	CCamera() throw (camera_exception);
+	virtual ~CCamera (void);
+
+	// 
+	// Open, close and capture operations.
+	//
+	bool Open();
+	void Close();
+	IplImage* QueryFrame();	// TODO: return const ptr
+	bool QueryFrame (CIplImage& image);
+
+
+	//
+	// Capture information. Intended only for informational
+	// purposes. Values returned here may not be accurate
+	// (i.e. may change during capture).
+	//
+	int GetRealWidth () {return m_RealWidth; }
+	int GetRealHeight () {return m_RealHeight; }
+	float GetRealFrameRate () {return m_RealFrameRate; }
+
+	//
+	// Image flip control
+	//
+	bool GetHorizontalFlip () { return m_horizontalFlip; }
+	void SetHorizontalFlip (bool value) { m_horizontalFlip= value; }
+
+	//
+	// Settings dialogue provided by the driver
+	//
+	virtual bool HasSettingsDialog() { return false; }
+	virtual void ShowSettingsDialog () {}
+
+	//
+	// Settings directly supported by the camera class.
+	//
+	virtual bool HasCameraControls() { return false; }
+	virtual unsigned int GetCameraControlsCount() { return 0; }
+	virtual CCameraControl* GetCameraControl(unsigned int) { return 0; }
+	
+protected:
+	// Open, close and capture operations implemented using NVI idiom
+	virtual bool DoOpen()= 0;
+	virtual void DoClose()= 0;
+	virtual IplImage* DoQueryFrame()= 0;
+	virtual bool DoQueryFrame(CIplImage& image)= 0;
+
+private:
+	// Make CCamera non-copyable
+	CCamera( const CCamera& );	// not implemented
+	CCamera& operator=( const CCamera& );     // not implemented
+
+	void PostQueryFrame(IplImage* pImage);
+
+	int m_RealWidth, m_RealHeight;
+	float m_RealFrameRate, m_LastRealFrameRate;
+	unsigned int m_lastTimeStamp;
+	int m_elapsedTime;
+	bool m_horizontalFlip;
+};
+
+// Class that models each camera control
+class CCameraControl {
+public:
+	enum ECameraControlId {
+		CAM_BRIGHTNESS= 0,
+		CAM_CONTRAST,
+		CAM_GAIN,
+		CAM_SATURATION,
+		CAM_HUE,
+		CAM_GAMMA,
+		CAM_SHARPNESS,
+		CAM_WHITE_BALANCE_TEMPERATURE,		// White balance color temperature
+		CAM_AUTO_WHITE_BALANCE_TEMPERATURE,	// Enable/disable automatic balance color
+		CAM_WHITE_BALANCE_COMPONENT,		// White balance color component control (red, blue)
+		CAM_AUTO_WHITE_BALANCE_COMPONENT,	// Enable/disable automatic white balance color component selection		
+		CAM_BACKLIGHT_COMPENSATION,
+		CAM_POWER_LINE_FREQUENCY,	// Local power line frequency for anti-flicker processing
+		CAM_AUTO_HUE,			// Enable/disable automatic hue control
+		CAM_AUTO_EXPOSURE_MODE,		// Mode for automatic exposure control
+		CAM_AUTO_EXPOSURE_PRIORITY,	// Constraints for automatic exposure control (e.g. adaptive vs. constant frame rate)
+		CAM_EXPOSURE_TIME_ABSOLUTE,	// Length of exposure (electronic shutter speed)
+		CAM_EXPOSURE_TIME_RELATIVE,	// Relative change to the current length of exposure
+		// Optics control
+		CAM_AUTO_FOCUS,		// Enable/disable automatic focus
+		CAM_FOCUS_ABSOLUTE,	// Distance to the focused target
+		CAM_FOCUS_RELATIVE,	// Relative change in distance to currently focused target
+		CAM_IRIS_ABSOLUTE, 	// Aperture setting	
+		CAM_IRIS_RELATIVE, 	// Relative change to the current aperture setting	
+		CAM_ZOOM_ABSOLUTE, 	// Objective lens focal length	
+		CAM_ZOOM_RELATIVE, 	// Relative change to the current objective lens focal length	
+		CAM_DIGITAL_ZOOM,  	// Digital zoom multiplier applied to the optical image
+		// Motion control	
+		CAM_PAN_ABSOLUTE,	// Pan angle (rotation on a vertical axis)	
+		CAM_PAN_RELATIVE,	// Relative change to the current pan angle	
+		CAM_TILT_ABSOLUTE,	// Tilt angle (rotation in a vertical plane)	
+		CAM_TILT_RELATIVE,	// Relative change to the current tilt angle	
+		CAM_ROLL_ABSOLUTE,	// Roll angle (rotation along the image viewing axis)	
+		CAM_ROLL_RELATIVE,	// Relative change to the current roll angle
+		CAM_PRIVACY,		// Temporarily prevent image from being acquired
+		CAM_PAN_RESET,		// Reset pan angle to a safe default value.
+		CAM_TILT_RESET,		// Reset tilt angle to a safe default value.
+		// Logitech custom contols
+		CAM_LOGITECH_PANTILT_RELATIVE,	// Relative change to the current pan and tilt angles.
+		CAM_LOGITECH_PANTILT_RESET,	// Reset pan and tilt angles to a safe default value.
+		CAM_LOGITECH_LED1_MODE, 		// Illumination mode of the first LED.
+		CAM_LOGITECH_LED1_FREQUENCY, 	// Blinking frequency of the first LED.
+		CAM_LOGITECH_DISABLE_PROCESSING, // Disable video processing (enable raw mode)
+		CAM_LOGITECH_RAW_BITS_PER_PIXEL, 	// Bits per pixel for raw (Bayer) mode
+				
+		CAM_LATEST_ENTRY,
+		CAM_ERROR_ENTRY= CAM_LATEST_ENTRY
+	};
+	
+	// Types of controls
+	enum ECameraControlType { CCTYPE_BOOLEAN, CCTYPE_CHOICE, CCTYPE_NUMBER };
+
+	virtual ~CCameraControl() {};
+	
+	virtual ECameraControlId GetId() const= 0;
+	// Get the name of the control provided by the driver
+	virtual const char* GetName() const= 0;
+	virtual ECameraControlType GetType() const= 0;
+	
+	// Get/set the current value. For boolean controls 0 and 1 are the only
+	// possible values. For choice controls 0 represents the first option.
+	// Set method returns true on success, false otherwise
+	virtual int GetValue() const= 0;
+	virtual bool SetValue(int value)= 0;
+	
+	virtual int GetDefaultValue() const= 0;
+	
+	virtual int GetMinimumValue() const= 0;
+	virtual int GetMaximumValue() const= 0;
+	
+	// For choices only
+	virtual const char* GetChoiceName(unsigned int) const { return 0; }
+};
+
+
+
+#endif
diff --git a/src/creavision/crvcamera_cv.cpp b/src/creavision/crvcamera_cv.cpp
new file mode 100755
index 0000000..495cb3e
--- /dev/null
+++ b/src/creavision/crvcamera_cv.cpp
@@ -0,0 +1,198 @@
+/////////////////////////////////////////////////////////////////////////////
+// Name:        crvcamera_cv.cpp
+// Purpose:  
+// Author:      Cesar Mauri Loba (cesar at crea-si dot com)
+// Modified by: 
+// Created:     30/05/2008
+// Copyright:   (C) 2008 Cesar Mauri Loba - CREA Software Systems
+// 
+//  This program is free software: you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation, either version 3 of the License, or
+//  (at your option) any later version.
+//
+//  This program is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+/////////////////////////////////////////////////////////////////////////////
+#include "crvcamera_cv.h"
+#include <highgui.h>
+#include <sys/timeb.h>
+#include <sys/types.h>
+#include <stdio.h>
+#include <cassert>
+
+bool CCameraCV::g_cvInitialized= false;
+int CCameraCV::g_numDevices= 0;
+char CCameraCV::g_deviceNames[MAX_CV_DEVICES][50];
+
+#if defined(WIN32)
+#include <windows.h>
+
+#define MAX_KEY_LENGTH 255
+#define MAX_VALUE_NAME 16383
+
+// Workround to enable capture at 30fps for some camera models
+// Should be called with administrative rights
+// Return 0 if ok, -1 if permission denied
+int VfwCamFpsWorkaround ()
+{
+	HKEY hKey;    
+	TCHAR    achKey[MAX_KEY_LENGTH];   // buffer for subkey name
+    DWORD    cbName;                   // size of name string 
+    TCHAR    achClass[MAX_PATH] = TEXT("");  // buffer for class name 
+    DWORD    cchClassName = MAX_PATH;  // size of class string 
+    DWORD    cSubKeys=0;               // number of subkeys 
+    DWORD    cbMaxSubKey;              // longest subkey size 
+    DWORD    cchMaxClass;              // longest class string 
+    DWORD    cValues;              // number of values for key 
+    DWORD    cchMaxValue;          // longest value name 
+    DWORD    cbMaxValueData;       // longest value data 
+    DWORD    cbSecurityDescriptor; // size of security descriptor 
+    FILETIME ftLastWriteTime;      // last write time 
+	DWORD i, retCode;   
+   // DWORD cchValue = MAX_VALUE_NAME; 
+
+	// Open key
+	retCode= RegOpenKeyEx(HKEY_LOCAL_MACHINE, TEXT("SOFTWARE\\Microsoft\\VfWWDM Mapper"), 
+							0, KEY_ALL_ACCESS, &hKey);
+	if (retCode!= ERROR_SUCCESS) return -1;
+
+	// Get the class name and the value count. 
+    retCode = RegQueryInfoKey(
+        hKey,                    // key handle 
+        achClass,                // buffer for class name 
+        &cchClassName,           // size of class string 
+        NULL,                    // reserved 
+        &cSubKeys,               // number of subkeys 
+        &cbMaxSubKey,            // longest subkey size 
+        &cchMaxClass,            // longest class string 
+        &cValues,                // number of values for this key 
+        &cchMaxValue,            // longest value name 
+        &cbMaxValueData,         // longest value data 
+        &cbSecurityDescriptor,   // security descriptor 
+        &ftLastWriteTime);       // last write time 
+ 
+	// Enumerate the subkeys
+	if (cSubKeys) {
+		for (i=0; i<cSubKeys; i++) { 
+			cbName = MAX_KEY_LENGTH;
+			retCode = RegEnumKeyEx(hKey, i,	achKey, &cbName, NULL, 
+									NULL, NULL, &ftLastWriteTime); 
+
+			if (retCode == ERROR_SUCCESS) {
+				HKEY hKeyValue;
+
+				retCode= RegOpenKeyEx(hKey, achKey, 0, KEY_WRITE, &hKeyValue);
+				if (retCode== ERROR_SUCCESS) {
+					DWORD value= 333330;
+					retCode= RegSetValueEx(hKeyValue, TEXT("AvgTimePerFrame"), 0, REG_DWORD, 
+											(const BYTE *) &value, sizeof(DWORD));
+				}
+				RegCloseKey(hKeyValue);
+			}
+		}
+	} 
+
+	// Close key
+	RegCloseKey(hKey);
+
+	return 0;
+}
+
+#endif
+
+CCameraCV::CCameraCV(int cameraId, unsigned int width, int unsigned height, 
+		float fr) throw (camera_exception)
+{
+	if (cameraId>= GetNumDevices()) throw camera_exception("wrong camera id");
+	m_Id= cameraId;
+	m_Width= width;
+	m_Height= height;
+	m_FrameRate= fr;
+	m_pCvCapture= NULL;
+
+#if defined(WIN32)
+	VfwCamFpsWorkaround ();
+#endif
+}
+
+CCameraCV::~CCameraCV(void)
+{
+	Close ();	
+}
+
+bool CCameraCV::DoOpen ()
+{
+	if (m_pCvCapture!= NULL) return true;	// Already opened
+	m_pCvCapture= cvCaptureFromCAM (m_Id);
+	if (m_pCvCapture== NULL) return false;
+	
+	// Try to set capture parameters although not always works
+	cvSetCaptureProperty( m_pCvCapture, CV_CAP_PROP_FRAME_WIDTH, (double) m_Width );
+	cvSetCaptureProperty( m_pCvCapture, CV_CAP_PROP_FRAME_HEIGHT, (double) m_Height );
+	// The following line does nothing under MS Windows
+	cvSetCaptureProperty( m_pCvCapture, CV_CAP_PROP_FPS, (double) m_FrameRate );
+
+	return true;
+}
+
+void CCameraCV::DoClose ()
+{
+	if (m_pCvCapture== NULL) return;	// Already closed
+	cvReleaseCapture (&m_pCvCapture);
+	m_pCvCapture= NULL;
+}
+
+IplImage *CCameraCV::DoQueryFrame()
+{
+	assert (m_pCvCapture);
+	if (m_pCvCapture== NULL) return NULL;
+
+	IplImage *pImage= cvQueryFrame( m_pCvCapture );
+	assert (pImage);
+	if (pImage== NULL) return NULL;
+	
+#if defined(linux)
+	// It seems that under Linux no proper channelSeq is reported
+	// Tested with Logitech Quickcam pro 4000 
+	pImage->channelSeq[0]= 'B';
+	pImage->channelSeq[2]= 'R';
+#endif
+
+	return pImage;
+}
+
+int CCameraCV::GetNumDevices()
+{
+	if (!g_cvInitialized) {		
+		cvInitSystem (0, NULL); 
+		g_cvInitialized= true; 
+
+		int i;
+		CvCapture* tmpCapture;
+
+		// Detect number of connected devices
+		for (i= 0; i< MAX_CV_DEVICES; ++i) {
+			tmpCapture= cvCreateCameraCapture (i);
+			if (tmpCapture== NULL) break;
+
+			cvReleaseCapture (&tmpCapture);
+
+			// Generate device name
+			sprintf (g_deviceNames[i], "Camera (Id:%d)", i);
+		}		
+		g_numDevices= i;
+	}
+	return g_numDevices;
+}
+
+char* CCameraCV::GetDeviceName (unsigned int id)
+{
+	if ((int) id>= GetNumDevices()) return NULL;	
+	return g_deviceNames[id];
+}
diff --git a/src/creavision/crvcamera_cv.h b/src/creavision/crvcamera_cv.h
new file mode 100755
index 0000000..c41fa37
--- /dev/null
+++ b/src/creavision/crvcamera_cv.h
@@ -0,0 +1,64 @@
+/////////////////////////////////////////////////////////////////////////////
+// Name:        crvcamera_cv.h
+// Purpose:  
+// Author:      Cesar Mauri Loba (cesar at crea-si dot com)
+// Modified by: 
+// Created:     30/05/2008
+// Copyright:   (C) 2008 Cesar Mauri Loba - CREA Software Systems
+// 
+//  This program is free software: you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation, either version 3 of the License, or
+//  (at your option) any later version.
+//
+//  This program is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+/////////////////////////////////////////////////////////////////////////////
+#ifndef CRVCAMERA_CV_H_
+#define CRVCAMERA_CV_H_
+
+#include "crvcamera.h"
+
+typedef struct CvCapture CvCapture;
+
+class CCameraCV : public CCamera
+{	
+public:
+	enum { MAX_CV_DEVICES= 10 };
+	CCameraCV(int cameraId= -1, 
+		unsigned int width= 320, unsigned int height= 240,
+		float fr= 30.0f) throw (camera_exception);
+	virtual ~CCameraCV (void);
+
+protected:
+	virtual bool DoOpen();
+	virtual void DoClose();	
+	virtual IplImage *DoQueryFrame();
+
+public:
+	static int GetNumDevices();
+	static char *GetDeviceName (unsigned int id);
+
+private:
+	int m_Id;
+	unsigned int m_Width, m_Height;
+	float m_FrameRate;
+	CvCapture* m_pCvCapture;
+	static bool g_cvInitialized;
+	static int g_numDevices;
+	static char g_deviceNames[MAX_CV_DEVICES][50];
+};
+
+#if defined(WIN32)
+// Workround to enable capture at 30fps for some camera models
+// Should be called with administrative rights
+// Return 0 if ok, -1 if permission denied
+int VfwCamFpsWorkaround ();
+#endif
+
+#endif
diff --git a/src/creavision/crvcamera_enum.cpp b/src/creavision/crvcamera_enum.cpp
new file mode 100755
index 0000000..25fc25d
--- /dev/null
+++ b/src/creavision/crvcamera_enum.cpp
@@ -0,0 +1,73 @@
+/////////////////////////////////////////////////////////////////////////////
+// Name:        crvcamera_enum.cpp
+// Purpose:  	Detect, enumerate and create camera object
+// Author:      Cesar Mauri Loba (cesar at crea-si dot com)
+// Modified by: 
+// Created:     1/10/2010
+// Copyright:   (C) 2008 Cesar Mauri Loba - CREA Software Systems
+// 
+//  This program is free software: you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation, either version 3 of the License, or
+//  (at your option) any later version.
+//
+//  This program is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+/////////////////////////////////////////////////////////////////////////////
+
+#include <stdio.h>
+#ifdef WIN32
+	#include "videoInput.h"
+	#include "crvcamera_wdm.h"
+
+	#define CAMCLASS CCameraWDM
+#else
+	#include <string.h>
+	#include "webcam.h"
+	#include "crvcamera_cv.h"
+	#include "crvcamera_v4l2.h"
+
+	#define CAMCLASS CCameraV4L2
+#endif
+#include "crvcamera_enum.h"
+
+// 
+// Static member functions
+//
+int CCameraEnum::GetNumDevices()
+{
+	return CAMCLASS::GetNumDevices();
+}
+
+const char* CCameraEnum::GetDeviceName (unsigned int id)
+{
+	return CAMCLASS::GetDeviceName((int) id);
+}
+
+#define _unused(x) ((void)x)
+
+CCamera* CCameraEnum::GetCamera (unsigned int id, unsigned int width,
+		unsigned int height, float frameRate)
+{
+	if ((int) id>= GetNumDevices()) return NULL;
+
+	try{
+		return new CAMCLASS(id, width, height, frameRate);		
+	} 
+	catch (camera_exception &e)	{
+		#ifndef NDEBUG
+			fprintf (stderr, "error initializing camera:");
+			fprintf (stderr, e.what());
+			fprintf (stderr, "\n");
+		#else
+			_unused(e); // make production build happy
+		#endif		
+	}
+	
+	return NULL;
+}
diff --git a/src/creavision/crvcamera_enum.h b/src/creavision/crvcamera_enum.h
new file mode 100755
index 0000000..aaf8f65
--- /dev/null
+++ b/src/creavision/crvcamera_enum.h
@@ -0,0 +1,52 @@
+/////////////////////////////////////////////////////////////////////////////
+// Name:        crvcamera_enum.h
+// Purpose:  
+// Author:      Cesar Mauri Loba (cesar at crea-si dot com)
+// Modified by: 
+// Created:     1/10/2010
+// Copyright:   (C) 2008 Cesar Mauri Loba - CREA Software Systems
+// 
+//  This program is free software: you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation, either version 3 of the License, or
+//  (at your option) any later version.
+//
+//  This program is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+/////////////////////////////////////////////////////////////////////////////
+#ifndef CRVCAMERA_ENUM_H_
+#define CRVCAMERA_ENUM_H_
+
+class CCamera;
+
+class CCameraEnum
+{
+public:
+	// Return the number of cameras detected 
+	static int GetNumDevices();
+	
+	// Return the name of a camera given its number or NULL
+	// if the camera doesn't exist.
+	static const char *GetDeviceName (unsigned int id);
+	
+	// Create a camera instace given its number. 
+	// It allows to indicate desired frame size and rate.
+	// Returns NULL if the camera doesn't exist or another
+	// error occurred.
+	static CCamera* GetCamera 
+		(unsigned int id,
+		unsigned int width= 320,
+		unsigned int height= 240,
+		float frameRate= 30.0f);
+		
+private:
+	CCameraEnum();	// Object instantation forbiden	
+};
+
+
+#endif
diff --git a/src/creavision/crvcamera_v4l2.cpp b/src/creavision/crvcamera_v4l2.cpp
new file mode 100644
index 0000000..0d715c6
--- /dev/null
+++ b/src/creavision/crvcamera_v4l2.cpp
@@ -0,0 +1,1752 @@
+/////////////////////////////////////////////////////////////////////////////
+// Name:        crvcamera_v4l2.cpp
+// Purpose:	Provide a camera capture class around v4l2 and libwebcam
+// Author:      Cesar Mauri Loba (cesar at crea-si dot com)
+// Modified by: 
+// Created:     17/05/2010
+// Copyright:   (C) 2008-11 Cesar Mauri Loba - CREA Software Systems
+//              Portions of guvcview are (c) of Paulo Assis and others
+//
+//  This program is free software: you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation, either version 3 of the License, or
+//  (at your option) any later version.
+//
+//  This program is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+/////////////////////////////////////////////////////////////////////////////
+#include "crvcamera_v4l2.h"
+#include <string.h>
+#include <stdio.h>
+#include <sys/stat.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <limits.h>
+//#include <linux/videodev.h>
+#include "incvideodev.h"
+#include <libv4l2.h>
+#include <sys/ioctl.h>
+#include <sys/mman.h>
+#include <sys/time.h>
+#include <list>
+#include "pwc-ioctl.h"
+#include "colorspaces.h"
+#if !defined(NDEBUG)
+#include <iostream>
+#endif
+
+// TODO: thread safety
+
+
+// Define possibly missing entries from videodev2.h
+#ifndef V4L2_PIX_FMT_MJPEG
+#define V4L2_PIX_FMT_MJPEG  v4l2_fourcc('M', 'J', 'P', 'G') /*  MJPEG stream     */
+#endif
+
+#ifndef V4L2_PIX_FMT_JPEG
+#define V4L2_PIX_FMT_JPEG  v4l2_fourcc('J', 'P', 'E', 'G')  /*  JPEG stream      */
+#endif
+
+#ifndef V4L2_PIX_FMT_YUYV
+#define V4L2_PIX_FMT_YUYV    v4l2_fourcc('Y','U','Y','V')   /* YUV 4:2:2        */
+#endif
+
+#ifndef V4L2_PIX_FMT_YVYU
+#define V4L2_PIX_FMT_YVYU    v4l2_fourcc('Y','V','Y','U')   /* YUV 4:2:2        */
+#endif
+
+#ifndef V4L2_PIX_FMT_UYVY
+#define V4L2_PIX_FMT_UYVY    v4l2_fourcc('U','Y','V','Y')   /* YUV 4:2:2        */
+#endif
+
+#ifndef V4L2_PIX_FMT_YYUV
+#define V4L2_PIX_FMT_YYUV    v4l2_fourcc('Y','Y','U','V')   /* YUV 4:2:2        */
+#endif
+
+#ifndef V4L2_PIX_FMT_YUV420
+#define V4L2_PIX_FMT_YUV420  v4l2_fourcc('Y','U','1','2')   /* YUV 4:2:0 Planar  */
+#endif
+
+#ifndef V4L2_PIX_FMT_YVU420
+#define V4L2_PIX_FMT_YVU420  v4l2_fourcc('Y','V','1','2')   /* YUV 4:2:0 Planar  */
+#endif
+
+#ifndef V4L2_PIX_FMT_NV12
+#define V4L2_PIX_FMT_NV12  v4l2_fourcc('N','V','1','2')   /* YUV 4:2:0 Planar (u/v) interleaved */
+#endif
+
+#ifndef V4L2_PIX_FMT_NV21
+#define V4L2_PIX_FMT_NV21  v4l2_fourcc('N','V','2','1')   /* YUV 4:2:0 Planar (v/u) interleaved */
+#endif
+
+#ifndef V4L2_PIX_FMT_NV16
+#define V4L2_PIX_FMT_NV16  v4l2_fourcc('N','V','1','6')   /* YUV 4:2:2 Planar (u/v) interleaved */
+#endif
+
+#ifndef V4L2_PIX_FMT_NV61
+#define V4L2_PIX_FMT_NV61  v4l2_fourcc('N','V','6','1')   /* YUV 4:2:2 Planar (v/u) interleaved */
+#endif
+
+#ifndef V4L2_PIX_FMT_Y41P
+#define V4L2_PIX_FMT_Y41P  v4l2_fourcc('Y','4','1','P')    /* YUV 4:1:1          */
+#endif
+
+#ifndef V4L2_PIX_FMT_GREY
+#define V4L2_PIX_FMT_GREY  v4l2_fourcc('G','R','E','Y')    /*      Y only       */
+#endif
+
+#ifndef V4L2_PIX_FMT_SPCA501
+#define V4L2_PIX_FMT_SPCA501 v4l2_fourcc('S','5','0','1')  /* YUYV - by line     */
+#endif
+
+#ifndef V4L2_PIX_FMT_SPCA505
+#define V4L2_PIX_FMT_SPCA505 v4l2_fourcc('S','5','0','5')  /* YYUV - by line     */
+#endif
+
+#ifndef V4L2_PIX_FMT_SPCA508
+#define V4L2_PIX_FMT_SPCA508 v4l2_fourcc('S','5','0','8')  /* YUVY - by line     */
+#endif
+
+#ifndef V4L2_PIX_FMT_SGBRG8
+#define V4L2_PIX_FMT_SGBRG8  v4l2_fourcc('G', 'B', 'R', 'G') /* GBGB.. RGRG..    */
+#endif
+
+#ifndef V4L2_PIX_FMT_SGRBG8
+#define V4L2_PIX_FMT_SGRBG8  v4l2_fourcc('G', 'R', 'B', 'G') /* GRGR.. BGBG..    */
+#endif
+
+#ifndef V4L2_PIX_FMT_SBGGR8
+#define V4L2_PIX_FMT_SBGGR8  v4l2_fourcc('B', 'A', '8', '1') /* BGBG.. GRGR..    */
+#endif
+
+#ifndef V4L2_PIX_FMT_SRGGB8
+#define V4L2_PIX_FMT_SRGGB8  v4l2_fourcc('R', 'G', 'G', 'B') /* RGRG.. GBGB..    */
+#endif
+
+#ifndef V4L2_PIX_FMT_BGR24
+#define V4L2_PIX_FMT_BGR24   v4l2_fourcc('B', 'G', 'R', '3') /* 24  BGR-8-8-8    */
+#endif
+
+#ifndef V4L2_PIX_FMT_RGB24
+#define V4L2_PIX_FMT_RGB24   v4l2_fourcc('R', 'G', 'B', '3') /* 24  RGB-8-8-8    */
+#endif
+
+CCameraV4L2::CCameraV4L2(int cameraId, unsigned int width, unsigned int height, 
+		float fr) throw(camera_exception)
+{
+	InstanceCreated();
+	if (cameraId>= GetNumDevices()) {
+		InstanceDestroyed();
+		throw camera_exception("wrong camera id");
+	}
+	m_Id= cameraId;
+	
+	m_desiredFormat.frame_rate= (unsigned int) fr;
+	m_desiredFormat.width= width;
+	m_desiredFormat.height= height;
+	m_desiredFormat.pixelformat= 0;
+
+	m_libWebcamHandle= 0;
+	m_captureMethod= CAP_NONE;
+	m_isStreaming= false;
+	m_buffersReady= false;
+	memset(&m_captureBuffersInfo, 0, sizeof(struct v4l2_buffer) * STREAMING_CAPTURE_NBUFFERS);
+	memset(&m_captureBuffersPtr, 0, sizeof(void*) * STREAMING_CAPTURE_NBUFFERS);	
+	memset(&m_currentFormat, 0, sizeof(m_currentFormat));
+	AddSupportedPixelFormats ();
+}
+
+CCameraV4L2::~CCameraV4L2(void)
+{
+    Close ();
+	InstanceDestroyed();
+}
+
+bool CCameraV4L2::DoOpen ()
+{
+#if !defined(NDEBUG)
+	fprintf (stderr, "CCameraV4L2::DoOpen: begin\n");
+#endif
+	if (m_libWebcamHandle!= 0) {
+#if !defined(NDEBUG)
+		fprintf (stderr, "CCameraV4L2::DoOpen: already open\n");
+#endif
+		return true;	// Already open	
+	}
+	if (!InternalOpen()) {
+#if !defined(NDEBUG)
+		fprintf (stderr, "CCameraV4L2::DoOpen: open failed\n");
+#endif
+		return false;
+	}
+	
+	assert (m_desiredFormat.width && m_desiredFormat.height && m_desiredFormat.frame_rate);
+	m_currentFormat= m_desiredFormat;
+		
+	if (!DetectBestImageFormat()) {
+		fprintf (stderr, "Unable to find any suitable image format\n");
+		Close();
+		return false;
+	}
+	if (!SetImageFormat()) {
+		Close();
+		return false;
+	}
+	m_captureMethod= DetectCaptureMethod();
+	if (m_captureMethod== CAP_NONE) {
+		fprintf (stderr, "Unable to find a suitable capure mode\n");
+		Close();
+		return false;
+	}
+	
+	if (!AllocateBuffers()) {
+		fprintf (stderr, "Unable to allocate buffers\n");
+		Close();
+		return false;
+	}
+	
+	if (!EnableVideo(true)) {
+		fprintf (stderr, "Unable to enable video\n");
+		DeallocateBuffers();
+		Close();
+		return false;
+	}
+	
+	// TODO: Awful. This is a provisional solution to avoid broken frames while capturing.
+	// It seems as if the driver/camera needs some time before start grabbing.
+	usleep (2000000);
+	return true;
+}
+
+void CCameraV4L2::DoClose ()
+{
+	if (m_isStreaming) EnableVideo(false);	
+	if (m_buffersReady) DeallocateBuffers();
+	if (m_libWebcamHandle!= 0) {
+		c_close_device (m_libWebcamHandle);
+		m_libWebcamHandle= 0;
+	}
+	m_captureMethod= CAP_NONE;
+	m_cameraControls.clear();
+}
+
+bool CCameraV4L2::InternalOpen()
+{
+	char devName[CAM_DEVICE_SHORT_NAME_LENGHT+5];
+	struct stat st;	
+
+	// Create device name
+	snprintf (devName, CAM_DEVICE_SHORT_NAME_LENGHT+5, "/dev/%s", g_deviceShortNames[m_Id]); //m_deviceShortName);
+
+	// Check if exists and if it is a device
+	if (stat (devName, &st)== -1) {
+		fprintf (stderr, "ERROR: Cannot identify ’%s’: %d, %s\n", devName, errno, strerror (errno));
+		return false;
+	}
+	if (!S_ISCHR (st.st_mode)) {
+		fprintf (stderr, "ERROR: %s is no device\n", devName);
+		return false;
+	}
+	
+	// "Open" device via libwebcam 
+	m_libWebcamHandle= c_open_device (g_deviceShortNames[m_Id]); //m_deviceShortName);
+	if (m_libWebcamHandle== 0 || c_get_file_descriptor (m_libWebcamHandle)<= 0) {
+		fprintf (stderr, "ERROR: Cannot open ’%s’ via libwebcam\n", devName);
+		Close();
+		return false;
+	}
+	
+	PopulateCameraControls ();
+	 
+	return true;
+}
+
+/* ioctl with a number of retries in the case of failure
+* args:
+* fd - device descriptor
+* IOCTL_X - ioctl reference
+* arg - pointer to ioctl data
+* returns - ioctl result
+* Based on xioctl from guvcview
+*/
+// TODO: this is code borrowed from Paulo's guvcview, but here
+// it seems useless because we don't open the device in non-blocking mode
+// Considered either removing or opening device in non-blocking mode
+// See sleep TODO below
+
+#define IOCTL_RETRY 4
+static
+int xioctl(int fd, int IOCTL_X, void *arg)
+{
+	int ret = 0;
+	int tries= IOCTL_RETRY;
+	do {
+		ret = v4l2_ioctl(fd, IOCTL_X, arg);
+	} 
+	while (ret && tries-- && ((errno == EINTR) || (errno == EAGAIN) || (errno == ETIMEDOUT)));
+
+	if (ret && (tries <= 0)) fprintf(stderr, "ioctl (%i) retried %i times - giving up: %s)\n", IOCTL_X, IOCTL_RETRY, strerror(errno));
+	
+	return (ret);
+} 
+
+void CCameraV4L2::AddSupportedPixelFormats ()
+{
+	// Adds supported pixel formats in preferred order
+	m_supportedPixelFormats.push_back (V4L2_PIX_FMT_RGB24);
+	m_supportedPixelFormats.push_back (V4L2_PIX_FMT_YUYV);
+	m_supportedPixelFormats.push_back (V4L2_PIX_FMT_YUV420);
+	m_supportedPixelFormats.push_back (V4L2_PIX_FMT_SGBRG8);
+	m_supportedPixelFormats.push_back (V4L2_PIX_FMT_SGRBG8);
+	m_supportedPixelFormats.push_back (V4L2_PIX_FMT_SBGGR8);
+	m_supportedPixelFormats.push_back (V4L2_PIX_FMT_SRGGB8);
+	m_supportedPixelFormats.push_back (V4L2_PIX_FMT_UYVY);
+	m_supportedPixelFormats.push_back (V4L2_PIX_FMT_YVYU);
+	m_supportedPixelFormats.push_back (V4L2_PIX_FMT_YYUV);
+	m_supportedPixelFormats.push_back (V4L2_PIX_FMT_YVU420);
+	m_supportedPixelFormats.push_back (V4L2_PIX_FMT_NV12);
+	m_supportedPixelFormats.push_back (V4L2_PIX_FMT_NV21);
+	m_supportedPixelFormats.push_back (V4L2_PIX_FMT_NV16);
+	m_supportedPixelFormats.push_back (V4L2_PIX_FMT_NV61);
+	m_supportedPixelFormats.push_back (V4L2_PIX_FMT_Y41P);
+	m_supportedPixelFormats.push_back (V4L2_PIX_FMT_GREY);
+	m_supportedPixelFormats.push_back (V4L2_PIX_FMT_SPCA501);
+	m_supportedPixelFormats.push_back (V4L2_PIX_FMT_SPCA505);
+	m_supportedPixelFormats.push_back (V4L2_PIX_FMT_SPCA508);
+	m_supportedPixelFormats.push_back (V4L2_PIX_FMT_BGR24);
+}
+
+bool CCameraV4L2::PopulateCameraControls ()
+{
+	CControl *controls= NULL;
+	unsigned int size= 0, count= 0;
+
+	// First call to discover required buffer size
+	if (c_enum_controls(m_libWebcamHandle, controls, &size, &count)!= C_BUFFER_TOO_SMALL) return false;
+	else {
+		// Ok, allocate buffer and query information
+		assert (size> 0);
+		unsigned char buffer[size];
+		controls= (CControl *) buffer;
+		if (c_enum_controls(m_libWebcamHandle, controls, &size, &count)!= C_SUCCESS) return false;
+		
+		// Populate camera control vector
+		for (unsigned int i= 0; i< count; ++i) {
+			if (controls[i].type!=  CC_TYPE_RAW)
+				// Ignore raw controls
+				m_cameraControls.push_back(CCameraControlV4L2(m_libWebcamHandle, controls[i]));
+		}
+	}
+	return true;
+}
+
+unsigned int CCameraV4L2::GetCameraControlsCount()
+{
+	return static_cast<unsigned int>(m_cameraControls.size());
+}
+
+CCameraControl* CCameraV4L2::GetCameraControl(unsigned int numControl)
+{
+	if (numControl>= GetCameraControlsCount()) return NULL;
+	return &m_cameraControls[numControl];
+}
+
+// Do VIDIOC_REQBUFS	
+bool CCameraV4L2::RequestBuffers(enum v4l2_memory mem)
+{
+	struct v4l2_requestbuffers requestbuffers;
+
+	memset (&requestbuffers, 0, sizeof(requestbuffers));
+	requestbuffers.count= STREAMING_CAPTURE_NBUFFERS;
+	requestbuffers.type= V4L2_BUF_TYPE_VIDEO_CAPTURE;
+	requestbuffers.memory= mem; //V4L2_MEMORY_MMAP;
+	if (xioctl(c_get_file_descriptor (m_libWebcamHandle), VIDIOC_REQBUFS, &requestbuffers)== 0) {
+		if (requestbuffers.count== STREAMING_CAPTURE_NBUFFERS) return true;
+		if (requestbuffers.count> 0) UnRequestBuffers(mem);		
+	}
+	fprintf (stderr, "ERROR: RequestBuffers: failed\n");
+	return false;
+}
+
+// Undo VIDIOC_REQBUFS
+bool CCameraV4L2::UnRequestBuffers(enum v4l2_memory mem)
+{
+	struct v4l2_requestbuffers requestbuffers;
+
+	memset (&requestbuffers, 0, sizeof(requestbuffers));
+	requestbuffers.count= 0;
+	requestbuffers.type= V4L2_BUF_TYPE_VIDEO_CAPTURE;
+	requestbuffers.memory= mem; //V4L2_MEMORY_MMAP;
+	if (xioctl(c_get_file_descriptor (m_libWebcamHandle), VIDIOC_REQBUFS, &requestbuffers)== 0) return true;
+	fprintf (stderr, "ERROR: UnRequestBuffers: failed\n");
+	return false;
+}
+	
+// This method must be called AFTER desired format is set	
+CCameraV4L2::ECaptureMethod CCameraV4L2::DetectCaptureMethod()
+{
+	struct v4l2_capability capability;	
+
+	// Query basic capabilities. This never should fail
+	if (xioctl (c_get_file_descriptor (m_libWebcamHandle), VIDIOC_QUERYCAP, &capability)!= 0) {
+		fprintf (stderr, "WARNING: Cannot query camera capabilities: VIDIOC_QUERYCAP ioctl failed\n");
+		return CAP_NONE;
+	}
+
+	if (!(capability.capabilities & V4L2_CAP_VIDEO_CAPTURE)) {
+	    fprintf (stderr, "WARNING: is no video capture device\n");
+	    return CAP_NONE;
+	}
+
+	// Driver supports streaming
+	if ((capability.capabilities & V4L2_CAP_STREAMING)) {
+		// Streaming supported. Which kind?
+		// It can be V4L2_MEMORY_MMAP or V4L2_MEMORY_USERPTR
+
+		// Check MMAP first as preferent option
+		if (RequestBuffers(V4L2_MEMORY_MMAP)) {
+			UnRequestBuffers(V4L2_MEMORY_MMAP);
+			return CAP_STREAMING_MMAP;
+		}
+
+		// Check using user-allocated memory
+		if (RequestBuffers(V4L2_MEMORY_USERPTR)) {
+			UnRequestBuffers(V4L2_MEMORY_USERPTR);
+			return CAP_STREAMING_USR;
+		}
+	}
+	if (capability.capabilities & V4L2_CAP_READWRITE) return CAP_READ;
+
+	return CAP_NONE;
+}
+
+// Only used by DetectBestImageFormat
+typedef struct  {
+	unsigned int min_frame_rate;
+	unsigned int max_frame_rate;
+	unsigned int step_frame_rate;
+	unsigned int min_width;
+	unsigned int min_height;
+	unsigned int max_width;
+	unsigned int max_height;
+	unsigned int step_width;
+	unsigned int step_height;		
+	uint32_t pixelformat;	// Four character code	
+} TImageFormatEx;
+#if !defined(NDEBUG)
+static 
+void dump_TImageFormatEx (TImageFormatEx& ife)
+{
+	std::cout << "dump_TImageFormatEx. fr: " << ife.min_frame_rate << ", " << ife.max_frame_rate << ", " << ife.step_frame_rate 
+		<< "w:" << ife.min_width << ", " << ife.max_width << ", " << ife.step_width 
+		<< "h:" << ife.min_height << ", " << ife.max_height << ", " << ife.step_height 
+		<< "px;" << ife.pixelformat << std::endl;
+}
+#endif
+
+// Given a range returns the absolute distance to a value
+template <class T>
+T abs_distance_to_range (T min, T max, T val)
+{
+	if (val< min) return min-val;
+	if (val< max) return 0;
+	return val-max;
+}
+
+// Given a steped range and a desired value, selects a value within 
+// the range as near as possible to the desired value
+static 
+uint range_value_fit (uint min, uint max, uint step, uint val)
+{
+	if (val<= min) return min;
+	if (val>= max) return max;
+	
+	// Adjust step
+	if (step== 0) step= 1;
+	val-= (val % step);
+	if (val< min) val= min;
+	return val;	
+}
+
+
+// Look for best matching entries for a desired frame rate and remove all other entries
+// fr= 0 means that nothing is done (all formats are appropiate), fr=UINT_MAX selects highest
+// frame rate
+static void SelectBestFrameRate (unsigned int fr, std::list<TImageFormatEx>& availableFormats)
+{
+	if (fr> 0) {	
+		unsigned int bestdiff= UINT_MAX;
+		// Find closest frame ratio	
+		for (std::list<TImageFormatEx>::iterator i= availableFormats.begin(); i!= availableFormats.end(); ++i) {
+			unsigned int diff= abs_distance_to_range<uint> (i->min_frame_rate, i->max_frame_rate, fr);
+			if (diff< bestdiff) bestdiff= diff;
+		}
+		// Remove worse entries
+		for (std::list<TImageFormatEx>::iterator i= availableFormats.begin(); i!= availableFormats.end();)
+			if (abs_distance_to_range<uint> (i->min_frame_rate, i->max_frame_rate, fr)!= bestdiff) 
+				i= availableFormats.erase(i);
+			else
+				++i;
+		
+		assert (availableFormats.size()> 0);
+	}
+}
+
+// Sizes. Chooses closest number of pixels (width*height) to the requested
+static void SelectBestFramePixelNumber (unsigned int npixels, std::list<TImageFormatEx>& availableFormats)
+{
+	if (npixels> 0) {
+		unsigned int bestdiff= UINT_MAX;
+
+		// Find closest frame ratio	
+		for (std::list<TImageFormatEx>::iterator i= availableFormats.begin(); i!= availableFormats.end(); ++i) {
+			unsigned int diff= abs_distance_to_range<uint> (i->min_width * i->min_height, i->max_width * i->max_height, npixels);
+			if (diff< bestdiff) bestdiff= diff;
+		}
+		// Remove worse entries
+		for (std::list<TImageFormatEx>::iterator i= availableFormats.begin(); i!= availableFormats.end();)
+			if (abs_distance_to_range<uint> (i->min_width * i->min_height, i->max_width * i->max_height, npixels)!= bestdiff) 
+				i= availableFormats.erase(i);
+			else
+				++i;
+		
+		assert (availableFormats.size()> 0);		
+	}
+}
+
+
+// Given a set of desired parameters finds the most suitable configuration which the camera supports
+//
+// Initialize the fields of the TImageFormat struct with the desired value for
+// each field or 0 to express that any possibility is fine or UINT_MAX to request
+// the maximum available value. 
+
+bool CCameraV4L2::DetectBestImageFormat()
+{
+	std::list<TImageFormatEx> availableFormats;
+
+	//
+	// First build an array containing all possible formats
+	//
+	
+	unsigned int sformats, ssizes, sintervals;
+	unsigned int cformats, csizes, cintervals;
+	
+	// Request needed buffer to store formats
+	sformats= cformats= 0;	
+	if (c_enum_pixel_formats (m_libWebcamHandle, NULL, &sformats, &cformats)!= C_BUFFER_TOO_SMALL) return false;
+	else {
+		unsigned char bufferformats[sformats];
+		CPixelFormat* formats= (CPixelFormat*) bufferformats;
+		// Get formats
+		if (c_enum_pixel_formats (m_libWebcamHandle, formats, &sformats, &cformats)!= C_SUCCESS) return false;
+		
+		for (unsigned int ifo= 0; ifo< cformats; ++ifo) {
+			TImageFormatEx tmpif;
+			memset(&tmpif, 0, sizeof(tmpif));
+			
+			// Store pixel format
+			tmpif.pixelformat= v4l2_fourcc (formats[ifo].fourcc[0], formats[ifo].fourcc[1], formats[ifo].fourcc[2], formats[ifo].fourcc[3]);
+						
+			// Request needed buffer to store sizes
+			ssizes= csizes= 0;
+			if (c_enum_frame_sizes (m_libWebcamHandle, &formats[ifo], NULL, &ssizes, &csizes)!= C_BUFFER_TOO_SMALL)
+				// No frame sizes detected, should not happen but we cope with it anyway
+				availableFormats.push_back(tmpif);			
+			else {
+				unsigned char buffersizes[ssizes];
+				CFrameSize* sizes= (CFrameSize*) buffersizes;
+				// Get sizes
+				if (c_enum_frame_sizes (m_libWebcamHandle, &formats[ifo], sizes, &ssizes, &csizes)!= C_SUCCESS) {
+					// Unlikely but we cope with it anyway
+					availableFormats.push_back(tmpif);
+					continue;
+				}
+				
+				for (unsigned int is= 0; is< csizes; ++is) {
+					// Store size
+					if (sizes[is].type== CF_SIZE_CONTINUOUS) {
+						tmpif.min_width= sizes[is].min_width;
+						tmpif.min_height= sizes[is].min_height;
+						tmpif.max_width= sizes[is].max_width;
+						tmpif.max_height= sizes[is].max_height;
+						tmpif.step_width= sizes[is].step_width;
+						tmpif.step_height= sizes[is].step_height;
+					} 
+					else {
+						tmpif.min_width= sizes[is].width;
+						tmpif.min_height= sizes[is].height;
+						tmpif.max_width= sizes[is].width;
+						tmpif.max_height= sizes[is].height;
+						tmpif.step_width= 1;
+						tmpif.step_height= 1;
+					}
+					
+					// Request needed buffer to store intervals
+					sintervals= cintervals= 0;
+					if (c_enum_frame_intervals (m_libWebcamHandle, &formats[ifo], &sizes[is], NULL, &sintervals, &cintervals)!= C_BUFFER_TOO_SMALL)
+						// No intervals detected. Some cameras doesn't provide this information
+						availableFormats.push_back(tmpif);
+					else {
+						unsigned char bufferintervals[sintervals];
+						CFrameInterval* intervals= (CFrameInterval*) bufferintervals;
+						// Get intervals
+						if (c_enum_frame_intervals (m_libWebcamHandle, &formats[ifo], &sizes[is], intervals, &sintervals, &cintervals)!= C_SUCCESS) {
+							// Unlikely but we cope with it anyway
+							availableFormats.push_back(tmpif);
+							continue;
+						}
+						
+						for (unsigned int ii= 0; ii< cintervals; ++ii) {
+							// Store frame rate
+							if (intervals[ii].type== CF_INTERVAL_DISCRETE) {
+								tmpif.max_frame_rate= tmpif.min_frame_rate= (intervals[ii].n? intervals[ii].d / intervals[ii].n : 0);
+								tmpif.step_frame_rate= 1;
+							}
+							else {
+								tmpif.max_frame_rate= (intervals[ii].max_n? intervals[ii].max_d / intervals[ii].max_n : 0);
+								tmpif.min_frame_rate= (intervals[ii].min_n? intervals[ii].min_d / intervals[ii].min_n : 0);
+								tmpif.step_frame_rate= (intervals[ii].step_n? intervals[ii].step_d / intervals[ii].step_n : 0);
+								if (tmpif.step_frame_rate== 0) tmpif.step_frame_rate= 1;
+							}
+							
+							availableFormats.push_back(tmpif);				
+						}
+					}
+				}
+				
+			}			
+		}
+	}
+#if !defined(NDEBUG)
+	for (std::list<TImageFormatEx>::iterator i= availableFormats.begin(); i!= availableFormats.end(); ++i) {
+		dump_TImageFormatEx (*i);
+	}
+#endif
+	//
+	// Selection process
+	//
+	
+	// Filter by compatible pixel formats. Remove entries which use non supported encodings
+	for (std::list<TImageFormatEx>::iterator i= availableFormats.begin(); i!= availableFormats.end();) {
+		bool found= false;
+		for (unsigned int ienc= 0; !found && ienc< m_supportedPixelFormats.size(); ++ienc)
+			if (m_supportedPixelFormats[ienc]== i->pixelformat) found= true;
+		
+		if (!found) {
+#if !defined(NDEBUG)
+			char* tmp= (char *) &i->pixelformat;
+			std::cerr << "crvcamera_v4l2: discarding unsuported format: " << tmp[0] << tmp[1] << tmp[2] << tmp[3] << std::endl;
+#endif
+			i= availableFormats.erase (i);
+		}
+		else ++i;
+	}
+
+	// No available formats detected
+	if (availableFormats.size()== 0) return false;
+
+	// As for realtime computer vision frame rate is usually a critical parameter we first choose it.
+	SelectBestFrameRate (m_currentFormat.frame_rate, availableFormats);
+	
+	// Sizes. Chooses closest number of pixel (width*height) to the requested
+	SelectBestFramePixelNumber (m_currentFormat.width * m_currentFormat.height, availableFormats);
+	
+	// Check aspect ratio
+	//TODO: Check weird errors. floating point errors.	
+	if (m_currentFormat.width> 0 && m_currentFormat.height> 0) {
+		float bestdiff= FLT_MAX;
+		float aratio= (float) m_currentFormat.width / (float) m_currentFormat.height;
+		// Find closest frame ratio
+		for (std::list<TImageFormatEx>::iterator i= availableFormats.begin(); i!= availableFormats.end(); ++i) {
+			float diff= abs_distance_to_range<float> ((float)i->min_width / (float)i->max_height, (float)i->max_width / (float)i->min_height, aratio);
+			if (diff< bestdiff) bestdiff= diff;
+		}
+		// Remove worst entries
+		for (std::list<TImageFormatEx>::iterator i= availableFormats.begin(); i!= availableFormats.end();)
+		{
+			if (abs_distance_to_range<float> ((float)i->min_width / (float)i->max_height, (float)i->max_width / (float)i->min_height, aratio)> bestdiff) 
+				i= availableFormats.erase(i);
+			else
+				++i;
+		}
+		assert (availableFormats.size()> 0);
+	}
+
+	
+	// If frame rate not explicity specified then selects highest fr available
+	if (m_currentFormat.frame_rate== 0) {
+		m_currentFormat.frame_rate= UINT_MAX;
+		SelectBestFrameRate (m_currentFormat.frame_rate, availableFormats);
+	}
+	
+	// If frame size not explicity specified then selects bigger frame size available
+	if (m_currentFormat.width== 0 || m_currentFormat.height== 0) {
+		if (!m_currentFormat.width) m_currentFormat.width= UINT_MAX;
+		if (!m_currentFormat.height) m_currentFormat.height= UINT_MAX;		
+		SelectBestFramePixelNumber (UINT_MAX, availableFormats);
+	}
+	
+	// Finally chooses best available pixelformat
+	for (unsigned int ienc= 0; ienc< m_supportedPixelFormats.size(); ++ienc) {		
+		for (std::list<TImageFormatEx>::iterator i= availableFormats.begin(); i!= availableFormats.end(); ++i) {
+			if (m_supportedPixelFormats[ienc]== i->pixelformat) {
+				// Bingo! Store data and finish
+				m_currentFormat.pixelformat= m_supportedPixelFormats[ienc];
+				m_currentFormat.frame_rate= range_value_fit (i->min_frame_rate, i->max_frame_rate, i->step_frame_rate, m_currentFormat.frame_rate);
+				m_currentFormat.width= range_value_fit (i->min_width, i->max_width, i->step_width, m_currentFormat.width);
+				m_currentFormat.height= range_value_fit (i->min_height, i->max_height, i->step_height, m_currentFormat.height);
+			#if !defined(NDEBUG)
+				std::cout << "Choosen format:";
+				dump_TImageFormatEx (*i);
+			#endif
+				return true;
+			}
+		}
+	}
+	
+	// Execution should never reach this point
+	assert (false);
+	return false;
+}
+
+bool CCameraV4L2::SetImageFormat()
+{
+	struct v4l2_format format;
+	
+	//
+	// Set frame format, including width, height and pixelformat. First query current
+	// settings, then modify relevant values and finally query actual values
+	//
+	memset (&format, 0, sizeof (format));
+	format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+	if (xioctl (c_get_file_descriptor (m_libWebcamHandle), VIDIOC_G_FMT, &format)== -1) {
+		fprintf(stderr, "ERROR: Unable to get format.\n");
+		return false;	
+	}
+	
+	format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+	format.fmt.pix.width = m_currentFormat.width;
+	format.fmt.pix.height = m_currentFormat.height;
+	format.fmt.pix.pixelformat = m_currentFormat.pixelformat;
+	format.fmt.pix.field = V4L2_FIELD_ANY;
+
+	if (xioctl (c_get_file_descriptor (m_libWebcamHandle), VIDIOC_S_FMT, &format)== -1) {
+		fprintf(stderr, "ERROR: Unable to set format.\n");
+		return false;	
+	}
+	
+	// Store currently set format (last VIDIOC_S_FMT may have changed it)
+	//m_currentFormat.frame_rate= imgformat.frame_rate;
+	m_currentFormat.width= format.fmt.pix.width;
+	m_currentFormat.height= format.fmt.pix.height;
+	m_currentFormat.pixelformat= format.fmt.pix.pixelformat;	
+
+	//	
+	// Set framerate and other camera parameters.
+	// 
+	// We here try to cope with two common drivers: pwc and uvc. Unfortunately pwc driver versions above
+	// 10.0.12 removed support for many ioctls (including that to set the framerate VIDIOCSWIN).
+	// As of kernel version 3.0.0 (which ships pwc 10.0.14) this issue has not been fixed and the odds are
+	// it won't be as the hardware has been discontinued :-(
+	//
+	if (strcasestr(g_deviceDriverNames[m_Id], "pwc")!= NULL)  {
+		// Using a PWC based camera.
+		bool properlySet= false;
+		struct video_window vwin;		
+		if ((xioctl(c_get_file_descriptor (m_libWebcamHandle), VIDIOCGWIN, &vwin) == 0) && (vwin.flags & PWC_FPS_FRMASK)) {
+			vwin.flags &= ~PWC_FPS_FRMASK;
+			vwin.flags |= (m_currentFormat.frame_rate << PWC_FPS_SHIFT);
+			if (xioctl(c_get_file_descriptor (m_libWebcamHandle), VIDIOCSWIN, &vwin) == 0) properlySet= true;
+		}
+
+		if (!properlySet) fprintf (stderr, "Warning: cannot set FPS: %d for PWC camera\n", m_currentFormat.frame_rate);
+	}
+	else {
+		struct v4l2_streamparm parm;
+
+		// An UVC camera is assumed
+		memset(&parm, 0, sizeof (parm));
+		parm.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+	
+		// Firstly try to get current v4l2_streamparm parameters
+		if (xioctl (c_get_file_descriptor (m_libWebcamHandle), VIDIOC_G_PARM, &parm)== 0) {
+			parm.parm.capture.timeperframe.numerator = 1;
+			parm.parm.capture.timeperframe.denominator = m_currentFormat.frame_rate;
+			if (xioctl(c_get_file_descriptor (m_libWebcamHandle), VIDIOC_S_PARM, &parm)!= 0) {
+				// Show warning and continue
+				fprintf (stderr, "Warning: cannot set FPS: %d for UVC camera\n", m_currentFormat.frame_rate);
+			}
+			
+			// Read values again and store actual values
+			if (xioctl (c_get_file_descriptor (m_libWebcamHandle), VIDIOC_G_PARM, &parm)== 0) {
+				// Set failed, store read values
+				m_currentFormat.frame_rate= 0;
+				if (parm.parm.capture.timeperframe.denominator)
+					m_currentFormat.frame_rate= parm.parm.capture.timeperframe.denominator / parm.parm.capture.timeperframe.numerator;
+			}
+			else
+				fprintf (stderr, "Warning: cannot read again VIDIOC_G_PARM\n");
+		}
+		else {
+			fprintf (stderr, "Error: VIDIOC_G_PARM for UVC camera\n");
+			return false;
+		}
+	
+		//
+		// Control V4L2_CID_EXPOSURE_AUTO is key to get a constant capture rate & good
+		// lightning conditions. In order of preference, the value of this control should be:
+		//
+		//   - V4L2_EXPOSURE_APERTURE_PRIORITY: Auto exposure time, manual iris. In practice, 
+		//     when (V4L2_CID_EXPOSURE_AUTO_PRIORITY== false) and the frame rate is previously 
+		//     set via VIDIOC_S_PARM, provides a constant frame rate at top speed and changes 
+		//     exposure time and gain automatically according to the lightning conditions.
+		//     Tested with the Logitech Webcam 9000 (046d:0990). It seems that uvcvideo drivers 
+		//     for newer kernels (3.0 and above) set V4L2_CID_EXPOSURE_AUTO to V4L2_EXPOSURE_MANUAL 
+		//     by default instead of V4L2_EXPOSURE_SHUTTER_PRIORITY (at least for this camera model)
+		//     which came as default option for older kernels.
+		//
+		//   - V4L2_EXPOSURE_SHUTTER_PRIORITY: ??? (not tested)
+		//
+		//   - V4L2_EXPOSURE_MANUAL: Manual exposure time, manual iris. Provides maximum flexibility
+		//     and allows for constant frame but i) does not cope well variable lightnint conditions
+		//     (forces user to manually adjust settings when needed) ii) it seems that default gain 
+		//     and exposure values are undefined and thus they need to be set to reasonable 
+		//     defaults and also suggest that camera controls should be permanently stored.
+		//
+		//   - V4L2_EXPOSURE_AUTO: Automatic exposure time, automatic iris aperture. Automatically 
+		//     reduces the frame rate depending on the lightning conditions and thus should be avoided.
+		//
+		// TODO: now uses the V4L2 api directly instead of libwebcam as some controls are not available
+		// any more.
+		// TODO: store control settings permanently
+		//
+		
+	
+		struct v4l2_control control;
+		memset (&control, 0, sizeof (control));
+
+		/*
+		control.id= V4L2_CID_EXPOSURE_AUTO;
+		control.value= -1;
+		if (xioctl (c_get_file_descriptor (m_libWebcamHandle), VIDIOC_G_CTRL, &control))
+			fprintf (stderr, "Warning: cannot get V4L2_CID_EXPOSURE_AUTO\n");
+		else {
+			fprintf (stderr, "Info: V4L2_CID_EXPOSURE_AUTO= %d\n", control.value);
+		}
+		
+
+		for (int i= 0; i<= 16; ++i) {
+			control.id= V4L2_CID_EXPOSURE_AUTO;
+			control.value= i;
+			if (xioctl (c_get_file_descriptor (m_libWebcamHandle), VIDIOC_S_CTRL, &control))
+				fprintf (stderr, "Warning: cannot set V4L2_CID_EXPOSURE_AUTO to %d\n", i);
+			else
+				fprintf (stderr, "Info: set V4L2_CID_EXPOSURE_AUTO to %d\n", i);
+		}
+		*/
+
+		//
+		// First set manual mode with reasonable exposure and gain values.
+		//
+		control.id= V4L2_CID_EXPOSURE_AUTO;
+		control.value= V4L2_EXPOSURE_MANUAL;
+		if (xioctl (c_get_file_descriptor (m_libWebcamHandle), VIDIOC_S_CTRL, &control))
+			fprintf (stderr, "Warning: cannot set V4L2_CID_EXPOSURE_AUTO to V4L2_EXPOSURE_MANUAL\n");
+		else
+			fprintf (stderr, "Info: set V4L2_CID_EXPOSURE_AUTO to V4L2_EXPOSURE_MANUAL\n");
+			
+		// Exposure time to match requested FPS
+		control.id= V4L2_CID_EXPOSURE_ABSOLUTE;
+		control.value= 10000 / m_currentFormat.frame_rate;
+		if (xioctl (c_get_file_descriptor (m_libWebcamHandle), VIDIOC_S_CTRL, &control))
+			fprintf (stderr, "Warning: cannot set V4L2_CID_EXPOSURE_ABSOLUTE to %d\n", control.value);
+		else
+			fprintf (stderr, "Info: set V4L2_CID_EXPOSURE_ABSOLUTE to %d\n", control.value);
+		
+		// Sets gain to the maximum value
+		for (unsigned int i= 0; i< m_cameraControls.size(); ++i) {
+			if (m_cameraControls[i].GetId()== CCameraControl::CAM_GAIN) {
+				if (m_cameraControls[i].SetValue(m_cameraControls[i].GetMaximumValue()))
+					fprintf (stderr, "Info: set CAM_GAIN to %d\n", 
+						m_cameraControls[i].GetMaximumValue());
+				else
+					fprintf (stderr, "Warning: cannot set CAM_GAIN to %d\n", 
+						m_cameraControls[i].GetMaximumValue());
+				break;
+			}
+		}
+			
+		// Tries to set automatic gain
+		control.id= V4L2_CID_AUTOGAIN;
+		control.value= 1;
+		if (xioctl (c_get_file_descriptor (m_libWebcamHandle), VIDIOC_S_CTRL, &control))
+			fprintf (stderr, "Warning: cannot set V4L2_CID_AUTOGAIN\n");
+		else
+			fprintf (stderr, "Info: set V4L2_CID_AUTOGAIN\n");
+
+		// Set V4L2_CID_EXPOSURE_AUTO_PRIORITY to false
+		bool hasExposureAutoPriority= false;
+		for (unsigned int i= 0; i< m_cameraControls.size(); ++i) {
+			if (m_cameraControls[i].GetId()== CCameraControl::CAM_AUTO_EXPOSURE_PRIORITY) {
+				if (m_cameraControls[i].SetValue(0)) {
+					hasExposureAutoPriority= true;
+					fprintf (stderr, "Info: AUTO_EXPOSURE_PRIORITY disabled\n");
+				}
+				else
+					fprintf (stderr, "Warning: cannot disable AUTO_EXPOSURE_PRIORITY\n");
+				break;
+			}
+		}
+
+		// If EXPOSURE_AUTO_PRIORITY cannot be disabled does not attempt remaing settings 
+		if (!hasExposureAutoPriority) return true;	
+	
+		//
+		// Secondly tries to set V4L2_EXPOSURE_SHUTTER_PRIORITY mode
+		//
+		control.id= V4L2_CID_EXPOSURE_AUTO;
+		control.value= V4L2_EXPOSURE_SHUTTER_PRIORITY;
+		if (xioctl (c_get_file_descriptor (m_libWebcamHandle), VIDIOC_S_CTRL, &control))
+			fprintf (stderr, "Warning: cannot set V4L2_CID_EXPOSURE_AUTO to V4L2_EXPOSURE_SHUTTER_PRIORITY\n");
+		else
+			fprintf (stderr, "Info: set V4L2_CID_EXPOSURE_AUTO to V4L2_EXPOSURE_SHUTTER_PRIORITY\n");
+
+
+		// Finally tries to set V4L2_EXPOSURE_APERTURE_PRIORITY
+		control.id= V4L2_CID_EXPOSURE_AUTO;
+		control.value= V4L2_EXPOSURE_APERTURE_PRIORITY;
+		if (xioctl (c_get_file_descriptor (m_libWebcamHandle), VIDIOC_S_CTRL, &control))
+			fprintf (stderr, "Warning: cannot set V4L2_CID_EXPOSURE_AUTO to V4L2_EXPOSURE_APERTURE_PRIORITY\n");
+		else
+			fprintf (stderr, "Info: set V4L2_CID_EXPOSURE_AUTO to V4L2_EXPOSURE_APERTURE_PRIORITY\n");
+	}
+	return true;
+}
+
+void CCameraV4L2::UnmapBuffers()
+{
+	for (int i= STREAMING_CAPTURE_NBUFFERS-1; i>= 0; --i) {
+		if (m_captureBuffersPtr[i]!= NULL) {
+			if (munmap(m_captureBuffersPtr[i], m_captureBuffersInfo[i].length)!= 0) perror("couldn't unmap buff");
+			m_captureBuffersPtr[i]= NULL;
+		}
+	}
+}
+
+// Enable/disable video
+bool CCameraV4L2::EnableVideo(bool enable)
+{
+	if (m_libWebcamHandle== 0) return false;	// Camera not open, fail
+	if (enable== m_isStreaming) return true;
+	
+	switch(m_captureMethod)	{		
+	case CAP_READ:
+		// capture using read, nothing to enable
+		break;
+	case CAP_STREAMING_MMAP: 
+	    {
+		int type= V4L2_BUF_TYPE_VIDEO_CAPTURE;
+		int action= (enable? VIDIOC_STREAMON : VIDIOC_STREAMOFF);
+		if (xioctl(c_get_file_descriptor (m_libWebcamHandle), action, &type)!= 0) {
+			perror("VIDIOC_STREAMON - Unable to start capture");
+			return false;
+		}
+		break;
+	    }	
+	case CAP_STREAMING_USR:
+		// Not implemented
+		fprintf (stderr, "CAP_STREAMING_USR: feature not implemented\n");
+		assert (false);
+		return false;
+	default:
+		// Never should happen
+		assert (false);
+		return false;		
+	}
+	m_isStreaming= enable;
+
+	return true;
+}
+
+// Allocate buffers before start capturing
+bool CCameraV4L2::AllocateBuffers()
+{
+	if (m_isStreaming) {
+		fprintf (stderr, "ERROR: AllocateBuffers: trying to allocate buffers while streaming\n");
+		return false;
+	}
+	if (m_libWebcamHandle== 0) {
+		fprintf (stderr, "ERROR: AllocateBuffers: device not open\n");
+		return false;
+	}
+	if (m_buffersReady) return true; // Already allocated
+	
+	if (m_captureMethod== CAP_READ) {
+		// TODO
+	}
+	else if (m_captureMethod== CAP_STREAMING_MMAP) {
+		// Request buffers
+		if (!RequestBuffers(V4L2_MEMORY_MMAP)) {
+			perror("VIDIOC_REQBUFS - Unable to allocate buffers");
+			return false;
+		}
+		
+		//  Buffers details
+		for (int i= 0; i< STREAMING_CAPTURE_NBUFFERS; ++i) {
+			memset(&m_captureBuffersInfo[i], 0, sizeof(struct v4l2_buffer));
+			m_captureBuffersInfo[i].index= i;
+			m_captureBuffersInfo[i].type= V4L2_BUF_TYPE_VIDEO_CAPTURE;
+			m_captureBuffersInfo[i].memory= V4L2_MEMORY_MMAP;				
+			if (xioctl(c_get_file_descriptor (m_libWebcamHandle), VIDIOC_QUERYBUF, &m_captureBuffersInfo[i])!= 0) {
+				perror("VIDIOC_QUERYBUF - Unable to query buffer");
+				UnRequestBuffers(V4L2_MEMORY_MMAP);
+				return false;
+			}
+			if (m_captureBuffersInfo[i].length <= 0) 
+				fprintf (stderr, "WARNING VIDIOC_QUERYBUF - buffer length is %d\n", m_captureBuffersInfo[i].length);
+		}
+		
+		// MMap buffers
+		memset(&m_captureBuffersPtr, 0, sizeof(void*) * STREAMING_CAPTURE_NBUFFERS);
+		for (int i= 0; i< STREAMING_CAPTURE_NBUFFERS; ++i) {
+			m_captureBuffersPtr[i]= mmap(NULL, m_captureBuffersInfo[i].length, PROT_READ | PROT_WRITE, MAP_SHARED, c_get_file_descriptor (m_libWebcamHandle), m_captureBuffersInfo[i].m.offset);
+			if (m_captureBuffersPtr[i]== MAP_FAILED) {
+				m_captureBuffersPtr[i]= NULL;
+				perror("Unable to map buffer");
+				UnmapBuffers();
+				UnRequestBuffers(V4L2_MEMORY_MMAP);
+				return false;
+			}
+		}
+		
+		// Queue buffers
+		for (int i= 0; i< STREAMING_CAPTURE_NBUFFERS; ++i) {
+			if (xioctl(c_get_file_descriptor (m_libWebcamHandle), VIDIOC_QBUF, &m_captureBuffersInfo[i])!= 0) {
+				perror("VIDIOC_QBUF - Unable to queue buffer");
+				UnmapBuffers();
+				UnRequestBuffers(V4L2_MEMORY_MMAP);
+				return false;
+			}
+		}		
+	}
+	else if (m_captureMethod== CAP_STREAMING_USR) {
+		fprintf (stderr, "ERROR: AllocateBuffers: CAP_STREAMING_USR not implemented\n");
+		assert (false);
+		return false;
+	}
+	else {
+		fprintf (stderr, "ERROR: AllocateBuffers: capture method not set\n");
+		return false;
+	}
+	m_buffersReady= true;
+	return true;
+}
+
+// Deallocate buffers
+bool CCameraV4L2::DeallocateBuffers()
+{
+	if (m_isStreaming) {
+		fprintf (stderr, "ERROR: trying to deallocate buffers while streaming\n");
+		return false;
+	}
+	if (!m_buffersReady) return true; // Already deallocated
+
+	if (m_captureMethod== CAP_READ) {
+		// TODO
+	}
+	else if (m_captureMethod== CAP_STREAMING_MMAP) {
+		UnmapBuffers();
+		UnRequestBuffers(V4L2_MEMORY_MMAP);
+	}
+	else if (m_captureMethod== CAP_STREAMING_USR) {
+		fprintf (stderr, "ERROR: DeallocateBuffers: CAP_STREAMING_USR not implemented\n");
+		assert (false);
+		return false;
+	}
+	else {
+		fprintf (stderr, "ERROR: DeallocateBuffers: capture method not set\n");
+		return false;
+	}
+	m_buffersReady= false;
+	return true;
+}
+
+
+
+// From opencv (otherlibs/highgui/cvcap_v4l.cpp)
+/*
+ * Turn a YUV4:2:0 block into an RGB block
+ *
+ * Video4Linux seems to use the blue, green, red channel
+ * order convention-- rgb[0] is blue, rgb[1] is green, rgb[2] is red.
+ *
+ * Color space conversion coefficients taken from the excellent
+ * http://www.inforamp.net/~poynton/ColorFAQ.html
+ * In his terminology, this is a CCIR 601.1 YCbCr -> RGB.
+ * Y values are given for all 4 pixels, but the U (Pb)
+ * and V (Pr) are assumed constant over the 2x2 block.
+ *
+ * To avoid floating point arithmetic, the color conversion
+ * coefficients are scaled into 16.16 fixed-point integers.
+ * They were determined as follows:
+ *
+ *  double brightness = 1.0;  (0->black; 1->full scale)
+ *  double saturation = 1.0;  (0->greyscale; 1->full color)
+ *  double fixScale = brightness * 256 * 256;
+ *  int rvScale = (int)(1.402 * saturation * fixScale);
+ *  int guScale = (int)(-0.344136 * saturation * fixScale);
+ *  int gvScale = (int)(-0.714136 * saturation * fixScale);
+ *  int buScale = (int)(1.772 * saturation * fixScale);
+ *  int yScale = (int)(fixScale);
+ */
+
+/* LIMIT: convert a 16.16 fixed-point value to a byte, with clipping. */
+#define LIMIT(x) ((unsigned char)((x)>0xffffff?0xff: ((x)<=0xffff?0:((x)>>16))))
+
+static inline void move_420_block(int yTL, int yTR, int yBL, int yBR, int u, int v, int rowPixels, unsigned char * rgb)
+{
+	const int rvScale = 91881;
+	const int guScale = -22553;
+	const int gvScale = -46801;
+	const int buScale = 116129;
+	const int yScale  = 65536;
+	int r, g, b;
+	g = guScale * u + gvScale * v;
+    //  if (force_rgb) {
+    //      r = buScale * u;
+    //      b = rvScale * v;
+    //  } else {
+	r = rvScale * v;
+	b = buScale * u;
+    //  }
+
+	yTL *= yScale; yTR *= yScale;
+	yBL *= yScale; yBR *= yScale;
+
+	/* Write out top two pixels */
+	rgb[0] = LIMIT(b+yTL); rgb[1] = LIMIT(g+yTL);
+	rgb[2] = LIMIT(r+yTL);
+
+	rgb[3] = LIMIT(b+yTR); rgb[4] = LIMIT(g+yTR);
+	rgb[5] = LIMIT(r+yTR);
+
+	/* Skip down to next line to write out bottom two pixels */
+	rgb += 3 * rowPixels;
+	rgb[0] = LIMIT(b+yBL); rgb[1] = LIMIT(g+yBL);
+	rgb[2] = LIMIT(r+yBL);
+
+	rgb[3] = LIMIT(b+yBR); rgb[4] = LIMIT(g+yBR);
+	rgb[5] = LIMIT(r+yBR);
+}
+
+
+// From opencv (otherlibs/highgui/cvcap_v4l.cpp)
+// Consider a YUV420P image of 8x2 pixels.
+//
+// A plane of Y values    A B C D E F G H
+//                        I J K L M N O P
+//
+// A plane of U values    1   2   3   4
+// A plane of V values    1   2   3   4 ....
+//
+// The U1/V1 samples correspond to the ABIJ pixels.
+//     U2/V2 samples correspond to the CDKL pixels.
+//
+/* Converts from planar YUV420P to RGB24. */
+static void yuv420p_to_rgb24(int width, int height, unsigned char *pIn0, unsigned char *pOut0)
+{
+	const int numpix = width * height;
+	const int bytes = 24 >> 3;
+	int i, j, y00, y01, y10, y11, u, v;
+	unsigned char *pY = pIn0;
+	unsigned char *pU = pY + numpix;
+	unsigned char *pV = pU + numpix / 4;
+	unsigned char *pOut = pOut0;
+
+	for (j = 0; j <= height - 2; j += 2) {
+		for (i = 0; i <= width - 2; i += 2) {
+			y00 = *pY;
+			y01 = *(pY + 1);
+			y10 = *(pY + width);
+			y11 = *(pY + width + 1);
+			u = (*pU++) - 128;
+			v = (*pV++) - 128;
+
+			move_420_block(y00, y01, y10, y11, u, v, width, pOut);
+
+			pY += 2;
+			pOut += 2 * bytes;
+
+		}
+		pY += width;
+		pOut += width * bytes;
+	}
+}
+
+bool CCameraV4L2::DecodeToRGB (void* src, void* dst, int width, int height, uint32_t pixelformat)
+{
+	// TODO: check another codecs to allow direct conversions in all cases
+	
+	// Direct conversions
+	switch (pixelformat) 
+	{
+		case V4L2_PIX_FMT_YUYV:
+			yuyv2rgb ((BYTE*) src, (BYTE*) dst, width, height);
+			return true;
+		case V4L2_PIX_FMT_YUV420:
+			yuv420p_to_rgb24(width, height, (BYTE*)src, (BYTE*)dst);
+			return true;
+		case V4L2_PIX_FMT_SGBRG8:
+			bayer_to_rgb24 ((BYTE*) src, (BYTE*) dst, width, height, 0);
+			return true;
+		case V4L2_PIX_FMT_SGRBG8: //1
+			bayer_to_rgb24 ((BYTE*) src, (BYTE*) dst, width, height, 1);
+			return true;
+		case V4L2_PIX_FMT_SBGGR8: //2
+			bayer_to_rgb24 ((BYTE*) src, (BYTE*) dst, width, height, 2);
+			return true;
+		case V4L2_PIX_FMT_SRGGB8: //3
+			bayer_to_rgb24 ((BYTE*) src, (BYTE*) dst, width, height, 3);
+			return true;
+		case V4L2_PIX_FMT_RGB24:
+			memcpy(dst, src, width*height*3);
+			return true;
+	}
+	
+	// Indirect conversions through YUYV
+	BYTE tmp_buffer[width*height*2];
+	switch (pixelformat) 
+	{
+#if 0
+		// TODO jpeg format
+		case V4L2_PIX_FMT_JPEG:
+		case V4L2_PIX_FMT_MJPEG:
+			/*
+			if(vd->buf.bytesused <= HEADERFRAME1) 
+		{
+				// Prevent crash on empty image
+			g_printf("Ignoring empty buffer ...\n");
+			return (ret);
+	}
+			memcpy(src, vd->mem[vd->buf.index],vd->buf.bytesused);
+			*/
+
+			if (jpeg_decode(&dst, src, width, height) < 0) {
+				fprintf (stderr, "jpeg decode errors\n");
+				return false;
+			}
+			break;
+#endif
+		case V4L2_PIX_FMT_UYVY:
+			uyvy_to_yuyv(tmp_buffer, (BYTE*) src, width, height);
+			break;
+		case V4L2_PIX_FMT_YVYU:			
+			yvyu_to_yuyv(tmp_buffer, (BYTE*) src, width, height);
+			break;
+		case V4L2_PIX_FMT_YYUV:
+			yyuv_to_yuyv(tmp_buffer, (BYTE*) src, width, height);
+			break;
+		case V4L2_PIX_FMT_YVU420:
+			yvu420_to_yuyv(tmp_buffer, (BYTE*) src, width, height);
+			break;
+		case V4L2_PIX_FMT_NV12:
+			nv12_to_yuyv(tmp_buffer, (BYTE*) src, width, height);
+			break;
+		case V4L2_PIX_FMT_NV21:
+			nv21_to_yuyv(tmp_buffer, (BYTE*) src, width, height);
+			break;
+		case V4L2_PIX_FMT_NV16:
+			nv16_to_yuyv(tmp_buffer, (BYTE*) src, width, height);
+			break;
+		case V4L2_PIX_FMT_NV61:
+			nv61_to_yuyv(tmp_buffer, (BYTE*) src, width, height);
+			break;
+		case V4L2_PIX_FMT_Y41P: 
+			y41p_to_yuyv(tmp_buffer, (BYTE*) src, width, height);
+			break;
+		case V4L2_PIX_FMT_GREY:
+			grey_to_yuyv(tmp_buffer, (BYTE*) src, width, height);
+			break;
+		case V4L2_PIX_FMT_SPCA501:
+			s501_to_yuyv(tmp_buffer, (BYTE*) src, width, height);
+			break;
+		case V4L2_PIX_FMT_SPCA505:
+			s505_to_yuyv(tmp_buffer, (BYTE*) src, width, height);
+			break;
+		case V4L2_PIX_FMT_SPCA508:
+			s508_to_yuyv(tmp_buffer, (BYTE*) src, width, height);
+			break;
+		case V4L2_PIX_FMT_BGR24:
+			bgr2yuyv((BYTE*) src, tmp_buffer, width, height);
+			break;
+		default:
+			fprintf (stderr, "error grabbing (crvcamera_v4l2.cpp) unknown format: %i\n", pixelformat);
+			return false;
+	}
+	yuyv2rgb ((BYTE*) tmp_buffer, (BYTE*) dst, width, height);
+	
+	return true;
+}
+
+IplImage *CCameraV4L2::DoQueryFrame()
+{
+	if (!DoQueryFrame(m_resultImage)) return NULL;
+	
+	return m_resultImage.ptr();
+}
+
+bool CCameraV4L2::DoQueryFrame(CIplImage& image)
+{
+	if (!m_isStreaming) return false;
+	fd_set rdset;
+	struct timeval timeout;
+		
+	FD_ZERO(&rdset);
+	FD_SET(c_get_file_descriptor (m_libWebcamHandle), &rdset);
+	timeout.tv_sec = 1; // 1 sec timeout 
+	timeout.tv_usec = 0;
+	
+	// select - wait for data or timeout
+	int retval = select(c_get_file_descriptor (m_libWebcamHandle) + 1, &rdset, NULL, NULL, &timeout);
+	if (retval < 0) {
+		perror(" Could not grab image (select error)");
+		return false;
+	} else if (retval == 0) {
+		perror(" Could not grab image (select timeout)");
+		return false;
+	}
+	else if ((retval > 0) && (FD_ISSET(c_get_file_descriptor (m_libWebcamHandle), &rdset))) {
+		switch (m_captureMethod) {
+		case CAP_READ:
+			fprintf (stderr, "CAP_READ Capture method not implemented yet\n");
+			assert (false);
+			return false;	
+		case CAP_STREAMING_MMAP: {
+			struct v4l2_buffer buffer;
+			
+			// Dequeue buffer
+			memset(&buffer, 0, sizeof(struct v4l2_buffer));			
+			buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+			buffer.memory = V4L2_MEMORY_MMAP;
+			if (xioctl(c_get_file_descriptor (m_libWebcamHandle), VIDIOC_DQBUF, &buffer)!= 0) {
+				perror("VIDIOC_DQBUF - Unable to dequeue buffer ");
+				return false;
+			}
+			
+			// Allocate result image when necessary
+			bool allocFailed= false;
+			if (!image.Initialized() || 
+				m_currentFormat.width!= static_cast<unsigned int>(image.Width()) || 
+				m_currentFormat.height!= static_cast<unsigned int>(image.Height())) {
+				
+				// TODO: correct the V4L2_PIX_FMT_YUV420 conversion routine
+				const char* planeOrder;
+				if (m_currentFormat.pixelformat== V4L2_PIX_FMT_YUV420) planeOrder= "BGR";
+				else planeOrder= "RGB";
+				// TODO: make sure that image is not initialized with padded rows
+				if (!image.Create (m_currentFormat.width, m_currentFormat.height, IPL_DEPTH_8U, planeOrder, IPL_ORIGIN_TL, IPL_ALIGN_DWORD )) {
+					fprintf (stderr, "Cannot create result image\n");
+					allocFailed= true;					
+				}
+			}
+			// Convert to destination format (always RGB 24bit)
+			// TODO: check return value
+			if (!allocFailed) 
+				DecodeToRGB (m_captureBuffersPtr[buffer.index], (BYTE*) image.ptr()->imageData, 
+				     image.Width(), image.Height(), m_currentFormat.pixelformat);
+			
+			// Queue buffer again
+			if (xioctl(c_get_file_descriptor (m_libWebcamHandle), VIDIOC_QBUF, &buffer)!= 0) {
+				perror("VIDIOC_QBUF - Unable to queue buffer");			
+				return false;
+			}
+			return (!allocFailed);
+		}
+		case CAP_STREAMING_USR:
+			fprintf (stderr, "CAP_STREAMING_USR Capture method not implemented yet\n");
+			assert (false);
+			return false;			
+		default:
+			assert (false);
+			return false;
+		}		
+	}
+		
+	return true;
+
+#if 0
+	if (-1 == read (c_get_file_descriptor (m_libWebcamHandle), m_buffer.start, m_buffer.length)) {
+	switch (errno) {
+	case EAGAIN:
+	return 0;
+#endif
+}
+
+#if !defined(NDEBUG)
+void CCameraV4L2::Dump()
+{
+	std::cout << "CCameraV4L2::Dump(). Begin\n";
+	
+	std::cout << "m_libWebcamHandle:" << m_libWebcamHandle << std::endl;
+	std::cout << "m_captureMethod:" << m_captureMethod << std::endl;
+	std::cout << "m_isStreaming:" << m_isStreaming << std::endl;
+	std::cout << "m_buffersReady:" << m_buffersReady << std::endl;
+	
+	std::cout << "m_currentFormat.frame_rate:" <<  m_currentFormat.frame_rate << std::endl;
+	std::cout << "m_currentFormat.width" << m_currentFormat.width << std::endl;
+	std::cout << "m_currentFormat.height:" << m_currentFormat.height << std::endl;
+	std::cout << "m_currentFormat.pielformat:" <<  m_currentFormat.pixelformat << std::endl;	
+/*	
+	for (unsigned int i= 0; i< m_supportedPixelFormats.size(); ++i)
+		std::cout << "m_supportedPixelFormats[" << i << "]:" << m_supportedPixelFormats[i] << std::endl;
+	for (unsigned int i= 0; i< m_cameraControls.size(); ++i) {
+		std::cout << "m_cameraControls[" << i << "]:\n" << std::endl;
+		 m_cameraControls[i].Dump();
+	}
+	*/
+	std::cout << "CCameraV4L2::Dump(). End\n";
+}
+#endif
+///////////////////////////////////////////////////////////////////////////////
+//
+// Implementacion of CCameraControlV4L2 class
+//
+
+CCameraControlV4L2::CCameraControlV4L2 (CHandle handle, const CControl& control) :
+	m_name(control.name)
+{
+	m_handle= handle;	
+	m_id= control.id;
+	m_type= control.type;
+	m_default= control.value.value;
+		
+	if (CControlType2ECameraControlType (control.type)!= CCTYPE_CHOICE) {
+		m_min= control.min.value;
+		m_max= control.max.value;
+		// TODO: control.step is really necessary?
+	}
+	else {
+		m_min= 0;
+		m_max= control.choices.count-1;
+		for (int i= m_min; i<= m_max; ++i) m_choices.push_back(control.choices.list[i].name);		
+	}	
+}
+
+// Get/set the current value. For boolean controls 0 and 1 are the only
+// possible values. For choice controls 0 represents the first option.
+// Set method returns true on success, false otherwise
+int CCameraControlV4L2::GetValue() const
+{
+	CControlValue value;
+	value.type= m_type;
+	value.value= 0;
+	
+	if (c_get_control (m_handle, m_id, &value)!= C_SUCCESS) {
+		fprintf (stderr, "CCameraControlV4L2::GetValue() failed to query value\n");
+		return 0;
+	}
+	
+	return value.value;
+}
+
+bool CCameraControlV4L2::SetValue(int value)
+{
+	CControlValue cvalue;
+	cvalue.type= m_type;
+	cvalue.value= value;
+	
+	if (c_set_control (m_handle, m_id, &cvalue)!= C_SUCCESS) {
+		fprintf (stderr, "CCameraControlV4L2::SetValue() failed to set value\n");
+		return false;
+	}
+	return true;
+}
+
+const char* CCameraControlV4L2::GetChoiceName(unsigned int numOption) const
+{
+	if (numOption> (unsigned int) m_max) return NULL;
+	
+	return  m_choices[numOption].c_str();
+}
+
+bool CCameraControlV4L2::CheckSupportedLibwebcamId (CControlId id)
+{
+	return (LibwebcamId2ECameraControlId(id)!= CAM_ERROR_ENTRY);	
+}
+
+CCameraControl::ECameraControlId CCameraControlV4L2::LibwebcamId2ECameraControlId (CControlId id)
+{
+	switch(id) {
+		case CC_BRIGHTNESS: return CAM_BRIGHTNESS;
+		case CC_CONTRAST: return CAM_CONTRAST;
+		case CC_GAIN: return CAM_GAIN;
+		case CC_SATURATION: return CAM_SATURATION;
+		case CC_HUE: return CAM_HUE;
+		case CC_GAMMA: return CAM_GAMMA;
+		case CC_SHARPNESS: return CAM_SHARPNESS;
+		case CC_WHITE_BALANCE_TEMPERATURE: return CAM_WHITE_BALANCE_TEMPERATURE;
+		case CC_AUTO_WHITE_BALANCE_TEMPERATURE: return CAM_AUTO_WHITE_BALANCE_TEMPERATURE;
+		case CC_WHITE_BALANCE_COMPONENT: return CAM_WHITE_BALANCE_COMPONENT;
+		case CC_AUTO_WHITE_BALANCE_COMPONENT: return CAM_AUTO_WHITE_BALANCE_COMPONENT;
+		case CC_BACKLIGHT_COMPENSATION: return CAM_BACKLIGHT_COMPENSATION;
+		case CC_POWER_LINE_FREQUENCY: return CAM_POWER_LINE_FREQUENCY;
+		case CC_AUTO_HUE: return CAM_AUTO_HUE;
+		case CC_AUTO_EXPOSURE_MODE: return CAM_AUTO_EXPOSURE_MODE;
+		case CC_AUTO_EXPOSURE_PRIORITY: return CAM_AUTO_EXPOSURE_PRIORITY;
+		case CC_EXPOSURE_TIME_ABSOLUTE: return CAM_EXPOSURE_TIME_ABSOLUTE;
+		case CC_EXPOSURE_TIME_RELATIVE: return CAM_EXPOSURE_TIME_RELATIVE;
+		case CC_AUTO_FOCUS: return CAM_AUTO_FOCUS;
+		case CC_FOCUS_ABSOLUTE: return CAM_FOCUS_ABSOLUTE;
+		case CC_FOCUS_RELATIVE: return CAM_FOCUS_RELATIVE;
+		case CC_IRIS_ABSOLUTE: return CAM_IRIS_ABSOLUTE;
+		case CC_IRIS_RELATIVE: return CAM_IRIS_RELATIVE;
+		case CC_ZOOM_ABSOLUTE: return CAM_ZOOM_ABSOLUTE;
+		case CC_ZOOM_RELATIVE: return CAM_ZOOM_RELATIVE;
+		case CC_DIGITAL_ZOOM: return CAM_DIGITAL_ZOOM;
+		case CC_PAN_ABSOLUTE: return CAM_PAN_ABSOLUTE;
+		case CC_PAN_RELATIVE: return CAM_PAN_RELATIVE;
+		case CC_TILT_ABSOLUTE: return CAM_TILT_ABSOLUTE;
+		case CC_TILT_RELATIVE: return CAM_TILT_RELATIVE;
+		case CC_ROLL_ABSOLUTE: return CAM_ROLL_ABSOLUTE;
+		case CC_ROLL_RELATIVE: return CAM_ROLL_RELATIVE;
+		case CC_PRIVACY: return CAM_PRIVACY;
+		case CC_PAN_RESET: return CAM_PAN_RESET;
+		case CC_TILT_RESET: return CAM_TILT_RESET;
+		case CC_LOGITECH_PANTILT_RELATIVE: return CAM_LOGITECH_PANTILT_RELATIVE;
+		case CC_LOGITECH_PANTILT_RESET: return CAM_LOGITECH_PANTILT_RESET;
+		case CC_LOGITECH_LED1_MODE: return CAM_LOGITECH_LED1_MODE;
+		case CC_LOGITECH_LED1_FREQUENCY: return CAM_LOGITECH_LED1_FREQUENCY;
+		case CC_LOGITECH_DISABLE_PROCESSING: return CAM_LOGITECH_DISABLE_PROCESSING;
+		case CC_LOGITECH_RAW_BITS_PER_PIXEL: return CAM_LOGITECH_RAW_BITS_PER_PIXEL;
+		default: return CAM_ERROR_ENTRY;
+	}
+}
+
+CCameraControl::ECameraControlType CCameraControlV4L2::CControlType2ECameraControlType (CControlType type)
+{
+	ECameraControlType ownType= CCTYPE_NUMBER;
+	switch (type) {
+		case CC_TYPE_BOOLEAN:
+			ownType= CCTYPE_BOOLEAN;
+			break;
+		case CC_TYPE_BYTE:
+		case CC_TYPE_WORD:
+		case CC_TYPE_DWORD:
+			ownType= CCTYPE_NUMBER;
+			break;
+		case CC_TYPE_CHOICE:
+			ownType= CCTYPE_CHOICE;
+			break;
+		default:
+			// Unsupported control. Execution should never reach this point
+			assert (false);
+	}	
+	return ownType;
+}
+
+//
+// Debugging code
+//
+#if !defined(NDEBUG)
+
+static
+void print_device_info (CHandle handle, char *device_name)
+{
+	assert(handle || device_name);
+	unsigned int size = static_cast<unsigned int>(sizeof(CDevice)) + 
+		(device_name? static_cast<unsigned int>(strlen(device_name)): 32) + 84;
+	CDevice *info = (CDevice *)malloc(size);
+	assert(info);
+
+	if(handle)
+		printf("  Getting device information for handle %d ...\n", handle);
+	else if(device_name)
+		printf("  Getting device information for device name '%s' ...\n", device_name);
+	
+	int ret = c_get_device_info(handle, device_name, info, &size);
+	if(ret) {
+		fprintf(stderr, "  Failed to c_get_device_info (%d).\n", ret);
+	}
+	else {
+		printf("    { shortName = '%s', name = '%s', driver = '%s', location = '%s', vid = %04x, pid = %04x, bcd = %d }\n",
+				info->shortName, info->name, info->driver, info->location, info->usb.vendor, info->usb.product, info->usb.release);
+	}
+
+	free(info);
+}
+
+static
+void print_control_info(CControl *control)
+{
+	printf("      { id = %d, name = '%s', type = %d, flags = %d",
+			control->id, control->name, control->type, control->flags);
+	if(control->type == CC_TYPE_CHOICE) {
+		printf(", choice = {");
+		for(unsigned int index = 0; index < control->choices.count; index++) {
+			printf(" '%s'[%d]", control->choices.list[index].name, control->choices.list[index].index);
+		}
+		printf(" }");
+	}
+	else {
+		printf(", min = %d, max = %d, def = %d, step = %d",
+				control->min.value, control->max.value, control->def.value, control->step.value);
+	}
+	printf(" }\n");
+}
+
+static
+void print_device_controls(CHandle handle)
+{
+	unsigned int size = 0, count = 0;
+
+	printf("  Getting control information for handle %d ...\n", handle);
+	CResult ret = c_enum_controls(handle, NULL, &size, &count);
+	if(ret == C_BUFFER_TOO_SMALL) {
+		CControl *controls = (CControl *)malloc(size);
+		ret = c_enum_controls(handle, controls, &size, &count);
+		if(ret) fprintf(stderr, "Unable to c_enum_controls (%d).\n", ret);
+/*		printf("    Buffer size = %d (%d controls of %d bytes)\n", size, count, sizeof(CControl));*/
+
+		for(unsigned int i = 0; i < count; i++) {
+			CControl *control = &controls[i];
+			printf("    Control found: %s\n", control->name);
+			print_control_info(control);
+		}
+
+		free(controls);
+	}
+	else {
+		printf("  No controls found (ret = %d).\n", ret);
+	}
+}
+
+void CCameraControlV4L2::Dump()
+{
+	std::cout << " CCameraControlV4L2::Dump(). Begin\n";
+	std::cout << "m_handle:" << m_handle << std::endl;
+	std::cout << "m_id:" << m_id << std::endl;
+	std::cout << "m_id (converted):" << LibwebcamId2ECameraControlId (m_id) << std::endl;
+	std::cout << "m_name:" << m_name << std::endl;
+	std::cout << "m_type:" << m_type << std::endl;
+	std::cout << "m_type (converted):" << CControlType2ECameraControlType(m_type) << std::endl;
+	std::cout << "m_default:" << m_default << std::endl;
+	std::cout << "m_min:" << m_min << std::endl;
+	std::cout << "m_max:" << m_max << std::endl;
+	for (unsigned int i= 0; i< m_choices.size(); ++i)
+		std::cout << "m_choices[" << i << "]:" << m_choices[i] << std::endl;
+	std::cout << "Value:" << GetValue() << std::endl;	
+	std::cout << " CCameraControlV4L2::Dump(). End\n";
+}
+#endif
+//
+// End Debugging code
+//
+
+
+//
+// Static attributes
+//
+int CCameraV4L2::g_numDevices= -1;
+char CCameraV4L2::g_deviceNames[MAX_CAM_DEVICES][CAM_DEVICE_NAME_LENGHT];
+char CCameraV4L2::g_deviceShortNames[MAX_CAM_DEVICES][CAM_DEVICE_SHORT_NAME_LENGHT];
+char CCameraV4L2::g_deviceDriverNames[MAX_CAM_DEVICES][CAM_DEVICE_DRIVER_NAME_LENGHT];
+int CCameraV4L2::g_numInstances= 0;
+
+void CCameraV4L2::InstanceCreated() throw(camera_exception)
+{
+	// TODO: thread safety
+	if (g_numInstances== 0) {
+		GetNumDevices();	// Fill structures when needed
+		CResult retval= c_init();
+		if(retval) throw camera_exception("cannot initialize libwebcam");		
+	}
+	++g_numInstances;
+}
+
+void CCameraV4L2::InstanceDestroyed() 
+{
+	// TODO: thread safety
+	assert (g_numInstances> 0);
+
+	if (--g_numInstances== 0) {
+		c_cleanup();
+		g_numDevices= -1;
+	}
+}
+
+int CCameraV4L2::GetNumDevices()
+{
+	// Linux: uses libwebcam
+	if (g_numDevices== -1) {
+		CResult retval= c_init();
+		if(retval) { 
+			fprintf(stderr, "Unable to c_init (%d).\n", retval);
+			return 0;
+		}
+		
+		// Enumerate devices
+		unsigned int size = 0, count = 0;
+		retval= c_enum_devices(NULL, &size, &count);
+		if(retval == C_BUFFER_TOO_SMALL) {
+			char devices_buffer[size];
+			CDevice *devices = (CDevice *) devices_buffer;
+
+			retval = c_enum_devices(devices, &size, &count);
+			if(retval) { 
+				fprintf(stderr, "Unable to c_enum_devices (%d).\n", retval);
+				return 0;
+			}
+			// Adjust & store number of maximum devices
+			if (count> MAX_CAM_DEVICES) count= MAX_CAM_DEVICES;
+			g_numDevices= count;	
+		
+			// Store information about detected devices
+			for(unsigned int i = 0; i< count; ++i) {
+				CDevice *device = &devices[i];
+				
+				// Prepend device number and append device name
+				unsigned int j= count - 1 - i;
+				snprintf (g_deviceNames[j], CAM_DEVICE_NAME_LENGHT, " (Id:%d) %s", j, device->name);		
+				snprintf (g_deviceShortNames[j], CAM_DEVICE_SHORT_NAME_LENGHT, "%s", device->shortName);
+				snprintf (g_deviceDriverNames[j], CAM_DEVICE_DRIVER_NAME_LENGHT, "%s", device->driver);
+
+	#ifndef NDEBUG
+				//printf("  Device found: %s\n", device->name);
+				CHandle handle = c_open_device(device->shortName);
+				if(handle == 0) {
+					fprintf(stderr, "  Failed to open device '%s'.\n", device->shortName);
+					continue;
+				}
+				printf("  Opened device '%s' successfully (handle = %d)\n", device->shortName, handle);
+				print_device_info(handle, NULL);
+				print_device_controls(handle);
+				c_close_device(handle);
+				handle = 0;
+				printf("  Closed device '%s' (handle = %d)\n\n", device->shortName, handle);
+	#endif	// NDEBUG
+			}
+		}
+		else {
+			// No devices found
+			g_numDevices= 0;			
+		}
+		
+		// Frees libwebcam
+		c_cleanup();		
+	}
+
+	return g_numDevices;
+}
+
+const char* CCameraV4L2::GetDeviceName (unsigned int id)
+{
+	if ((int) id>= GetNumDevices()) return NULL;
+	return g_deviceNames[id];
+}
diff --git a/src/creavision/crvcamera_v4l2.h b/src/creavision/crvcamera_v4l2.h
new file mode 100755
index 0000000..b290440
--- /dev/null
+++ b/src/creavision/crvcamera_v4l2.h
@@ -0,0 +1,157 @@
+/////////////////////////////////////////////////////////////////////////////
+// Name:        crvcamera_v4l2.h
+// Purpose:	Provide a camera capture class around v4l2 and libwebcam
+// Author:      Cesar Mauri Loba (cesar at crea-si dot com)
+// Modified by: 
+// Created:     17/05/2010
+// Copyright:   (C) 2008-10 Cesar Mauri Loba - CREA Software Systems
+//              Portions of guvcview are (c) of Paulo Assis and others
+//
+//  This program is free software: you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation, either version 3 of the License, or
+//  (at your option) any later version.
+//
+//  This program is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+/////////////////////////////////////////////////////////////////////////////
+#ifndef CRVCAMERA_V4L2_H_
+#define CRVCAMERA_V4L2_H_
+
+#include <inttypes.h>
+#include <linux/videodev2.h>
+#include "crvcamera_enum.h"
+#include "crvcamera.h"
+#include "crvimage.h"
+#include "webcam.h"
+#include <vector>
+#include <string>
+
+// Forward declarations
+class CCameraControlV4L2;
+
+class CCameraV4L2 : public CCamera
+{
+public:
+	CCameraV4L2(int cameraId= -1, unsigned int width= 320, 
+		unsigned int height= 240, float fr= 30.0f) throw(camera_exception);
+	virtual ~CCameraV4L2 (void);
+
+	
+	virtual bool HasCameraControls() { return true; }
+	virtual unsigned int GetCameraControlsCount();
+	virtual CCameraControl* GetCameraControl(unsigned int numControl);
+	
+	static int GetNumDevices();
+	static const char* GetDeviceName (unsigned int id);
+#if !defined(NDEBUG)
+	void Dump();
+#endif
+
+protected:
+	virtual bool DoOpen();
+	virtual void DoClose();	
+	virtual IplImage *DoQueryFrame();
+	virtual bool DoQueryFrame(CIplImage& image);
+
+private:
+	// Private types
+	enum ECaptureMethod { CAP_NONE= 0, CAP_READ, CAP_STREAMING_MMAP, CAP_STREAMING_USR };
+	enum { STREAMING_CAPTURE_NBUFFERS= 2 };
+	struct TImageFormat { 
+		unsigned int frame_rate;
+		unsigned int width;
+		unsigned int height;
+		uint32_t pixelformat;	// Four character code
+	};
+	
+	int m_Id;
+	TImageFormat m_desiredFormat;
+	TImageFormat m_currentFormat;
+	CHandle m_libWebcamHandle;	
+	ECaptureMethod m_captureMethod;
+	bool m_isStreaming;
+	bool m_buffersReady;
+	struct v4l2_buffer m_captureBuffersInfo[STREAMING_CAPTURE_NBUFFERS];
+	void* m_captureBuffersPtr[STREAMING_CAPTURE_NBUFFERS];
+	CIplImage m_resultImage;	
+	std::vector<uint32_t> m_supportedPixelFormats;
+	std::vector<CCameraControlV4L2> m_cameraControls;
+
+	//
+	// Static members
+	//
+	enum { MAX_CAM_DEVICES= 10, CAM_DEVICE_NAME_LENGHT= 50 };
+	static int g_numDevices;
+	static char g_deviceNames[MAX_CAM_DEVICES][CAM_DEVICE_NAME_LENGHT];
+	enum { CAM_DEVICE_SHORT_NAME_LENGHT= 32, CAM_DEVICE_DRIVER_NAME_LENGHT= 20 };
+	static char g_deviceShortNames[MAX_CAM_DEVICES][CAM_DEVICE_SHORT_NAME_LENGHT];
+	static char g_deviceDriverNames[MAX_CAM_DEVICES][CAM_DEVICE_DRIVER_NAME_LENGHT];
+	// Instance count for automatic libwebcam cleanup
+	static int g_numInstances;
+	// Instances inc/dec
+	void InstanceCreated() throw(camera_exception);
+	void InstanceDestroyed();
+
+	// Private methods
+	bool InternalOpen();
+	ECaptureMethod DetectCaptureMethod();
+	bool DetectBestImageFormat();
+	bool SetImageFormat();
+	bool EnableVideo(bool enable);
+	bool AllocateBuffers();
+	bool DeallocateBuffers();
+	bool RequestBuffers(enum v4l2_memory mem);
+	bool UnRequestBuffers(enum v4l2_memory mem);
+	void UnmapBuffers();
+	bool DecodeToRGB (void* src, void* dst, int width, int height, uint32_t pixelformat);
+	void AddSupportedPixelFormats ();
+	bool PopulateCameraControls ();
+};
+
+// Class that models each camera control
+class CCameraControlV4L2 : public CCameraControl {
+public:
+	CCameraControlV4L2 (CHandle handle, const CControl& control);
+	
+	virtual ECameraControlId GetId() const { return LibwebcamId2ECameraControlId(m_id); }
+	// Get the name of the control provided by the driver
+	virtual const char* GetName() const { return m_name.c_str(); }
+	virtual ECameraControlType GetType() const { return CControlType2ECameraControlType (m_type); }
+
+	// Get/set the current value. For boolean controls 0 and 1 are the only
+	// possible values. For choice controls 0 represents the first option.
+	// Set method returns true on success, false otherwise
+	virtual int GetValue() const;
+	virtual bool SetValue(int value);
+
+	virtual int GetDefaultValue() const { return m_default; }
+	virtual int GetMinimumValue() const { return m_min; }
+	virtual int GetMaximumValue() const { return m_max; }
+
+	// For choices only
+	virtual const char* GetChoiceName(unsigned int numOption) const;
+	
+	// Check whether a certain control id is supported
+	static bool CheckSupportedLibwebcamId (CControlId id);
+#if !defined(NDEBUG)
+	void Dump();
+#endif
+private:
+	static ECameraControlId LibwebcamId2ECameraControlId (CControlId id);
+	static ECameraControlType CControlType2ECameraControlType (CControlType type);
+	
+	CHandle m_handle;
+	CControlId m_id;	// The identifier of the control
+	std::string m_name;	// The name of the control
+	CControlType m_type;	// The type of the control
+	int m_default, m_min, m_max;
+	std::vector<std::string> m_choices;
+};
+
+#endif
diff --git a/src/creavision/crvcamera_wdm.cpp b/src/creavision/crvcamera_wdm.cpp
new file mode 100755
index 0000000..56ffccb
--- /dev/null
+++ b/src/creavision/crvcamera_wdm.cpp
@@ -0,0 +1,143 @@
+/////////////////////////////////////////////////////////////////////////////
+// Name:        crvcamera_wdm.cpp
+// Purpose:  
+// Author:      Cesar Mauri Loba (cesar at crea-si dot com)
+// Modified by: 
+// Created:     30/01/2009
+// Copyright:   (C) 2009 Cesar Mauri Loba - CREA Software Systems
+// 
+//  This program is free software: you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation, either version 3 of the License, or
+//  (at your option) any later version.
+//
+//  This program is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+/////////////////////////////////////////////////////////////////////////////
+#include "crvcamera_wdm.h"
+
+#include <sys/timeb.h>
+#include <sys/types.h>
+#include <stdio.h>
+#include <cassert>
+#include <cv.h>
+#include "crvimage.h"
+#include "videoInput.h"
+
+CCameraWDM::CCameraWDM(int cameraId, unsigned int width, unsigned int height,
+		float fr) throw(camera_exception)
+{
+	if (cameraId>= GetNumDevices()) throw camera_exception("wrong camera id");
+	m_Id= cameraId;
+	m_Width= width;
+	m_Height= height;
+	m_FrameRate= fr;
+
+	m_VI= NULL;	
+
+#if defined (NDEBUG)
+	videoInput::setVerbose(false);
+#else
+	videoInput::setVerbose(true);
+#endif
+}
+
+CCameraWDM::~CCameraWDM(void)
+{
+	Close();
+}
+
+bool CCameraWDM::DoOpen ()
+{
+	// Already open? Do nothing
+	if (m_VI) return true;
+
+	// Create a videoInput object
+	m_VI= new videoInput;
+	assert (m_VI);
+
+	// BGR channel sequence assumed
+	//m_pImage= new CIplImage (m_Width, m_Height, IPL_DEPTH_8U, "BGR");
+	//assert (m_pImage);	
+
+	m_VI->setIdealFramerate(m_Id, (int) m_FrameRate);
+	if (!m_VI->setupDevice (m_Id, m_Width, m_Height)) {
+		Close();
+		return false;
+	}
+
+	return true;	
+}
+
+void CCameraWDM::DoClose ()
+{
+	if (m_VI) {
+		m_VI->stopDevice(m_Id);
+		delete m_VI;
+		m_VI= NULL;
+		//delete m_pImage;
+	}
+}
+
+IplImage *CCameraWDM::DoQueryFrame()
+{
+	if (!CCameraWDM::DoQueryFrame(m_Image)) return NULL;
+
+	return m_Image.ptr();
+}
+
+bool CCameraWDM::DoQueryFrame(CIplImage& image)
+{
+	if (!m_VI) return false;
+
+	if (!image.Initialized() || m_VI->getWidth(m_Id)!= image.Width() || m_VI->getHeight(m_Id)!= image.Height()) {
+		// Allocate image in case is not properly set up
+		if (!image.Create (m_Width, m_Height, IPL_DEPTH_8U, "BGR", 1)) {
+			assert (!"CCameraWDM::DoQueryFrame: cannot create image");
+			return false;
+		}
+	}		
+	assert (image.Initialized());
+	assert (image.ptr()->imageSize== m_VI->getSize(m_Id));
+	
+	m_VI->getPixels(m_Id, reinterpret_cast<unsigned char *>(image.ptr()->imageData), false, false);
+	// Set appropiate origin
+	image.ptr()->origin= 1;
+
+	return true;
+}
+
+void CCameraWDM::ShowSettingsDialog ()
+{
+	if (m_VI) m_VI->showSettingsWindow (m_Id);
+}
+
+int CCameraWDM::g_numDevices= -1;
+char CCameraWDM::g_deviceNames[MAX_CAM_DEVICES][CAM_DEVICE_NAME_LENGHT];
+
+int CCameraWDM::GetNumDevices() 
+{ 
+	// Win32: uses videoInput
+	if (g_numDevices== -1) {		
+		// First initialization
+		g_numDevices= videoInput::listDevices (true);
+		if (g_numDevices> MAX_CAM_DEVICES) g_numDevices= MAX_CAM_DEVICES;		
+		for (int i= 0; i< g_numDevices; ++i) {
+			// Prepend device number and append device name
+			_snprintf (g_deviceNames[i], CAM_DEVICE_NAME_LENGHT, " (Id:%d) %s\0", i, videoInput::getDeviceName(i));
+		}		
+	}
+
+	return g_numDevices;	
+}
+
+const char* CCameraWDM::GetDeviceName (unsigned int id)
+{ 
+	if ((int) id>= GetNumDevices()) return NULL;
+	return g_deviceNames[id];
+}
\ No newline at end of file
diff --git a/src/creavision/crvcamera_wdm.h b/src/creavision/crvcamera_wdm.h
new file mode 100755
index 0000000..918bb10
--- /dev/null
+++ b/src/creavision/crvcamera_wdm.h
@@ -0,0 +1,59 @@
+/////////////////////////////////////////////////////////////////////////////
+// Name:        crvcamera_wdm.h
+// Purpose:  
+// Author:      Cesar Mauri Loba (cesar at crea-si dot com)
+// Modified by: 
+// Created:     30/01/2009
+// Copyright:   (C) 2009 Cesar Mauri Loba - CREA Software Systems
+// 
+//  This program is free software: you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation, either version 3 of the License, or
+//  (at your option) any later version.
+//
+//  This program is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+/////////////////////////////////////////////////////////////////////////////
+#ifndef CRVCAMERA_WDM_H_
+#define CRVCAMERA_WDM_H_
+
+#include "crvcamera.h"
+#include "crvimage.h"
+class videoInput;
+
+class CCameraWDM : public CCamera
+{
+public:
+	CCameraWDM(int cameraId= -1, unsigned int width= 320, 
+		unsigned int height= 240, float fr= 30.0f) throw(camera_exception);
+	virtual ~CCameraWDM (void);
+
+	static int GetNumDevices();
+	static const char* GetDeviceName (unsigned int id);
+
+	virtual bool DoOpen();
+	virtual void DoClose();	
+	virtual IplImage *DoQueryFrame();
+	virtual bool DoQueryFrame(CIplImage& image);
+
+	virtual bool HasSettingsDialog() { return true; }
+	virtual void ShowSettingsDialog ();
+
+private:
+	enum { MAX_CAM_DEVICES= 10, CAM_DEVICE_NAME_LENGHT= 50 };
+	static int g_numDevices;
+	static char g_deviceNames[MAX_CAM_DEVICES][CAM_DEVICE_NAME_LENGHT];
+
+	int m_Id;
+	unsigned int m_Width, m_Height;
+	float m_FrameRate;
+	videoInput* m_VI;
+	CIplImage m_Image;
+};
+
+#endif
diff --git a/src/creavision/crvcolor.cpp b/src/creavision/crvcolor.cpp
new file mode 100755
index 0000000..e447542
--- /dev/null
+++ b/src/creavision/crvcolor.cpp
@@ -0,0 +1,220 @@
+/////////////////////////////////////////////////////////////////////////////
+// Name:        crvcolor.cpp
+// Purpose:  
+// Author:      Cesar Mauri Loba (cesar at crea-si dot com)
+// Modified by: 
+// Created:     
+// Copyright:   (C) 2008 Cesar Mauri Loba - CREA Software Systems
+// 
+//  This program is free software: you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation, either version 3 of the License, or
+//  (at your option) any later version.
+//
+//  This program is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+/////////////////////////////////////////////////////////////////////////////
+
+#include <string.h>
+#include <assert.h>
+#include "crvcolor.h"
+#include "crvmisc.h"
+#include "crvgeomtry.h"
+
+void CRGBCubicColor::Clear()
+{
+	memset (m_ColorLookup, 0, 256*256*256);
+}
+
+void CRGBCubicColor::TrainColor (unsigned char r, unsigned char g, unsigned char b, int radius, double dDivisor)
+{
+	int rRadius, gRadius, bRadius, iR, iG, iB;
+	t3DRPoint p1, p2;
+	double val;
+
+	if (r< radius) rRadius= r;
+	else if ((255 - r)< radius) rRadius= (255 - r);
+	else rRadius= radius;
+
+	if (g< radius) gRadius= g;
+	else if ((255 - g)< radius) gRadius= (255 - g);
+	else gRadius= radius;
+
+	if (b< radius) bRadius= b;
+	else if ((255 - b)< radius) bRadius= (255 - b);
+	else bRadius= radius;
+
+	p1.x= r; p1.y= g; p1.z= b;
+
+	for (iR= (int) r - rRadius; iR<= (int) r + rRadius; iR++) {
+		for (iG= (int) g - gRadius; iG<= (int) g + gRadius; iG++) {
+			for (iB= (int) b - bRadius; iB<= (int) b + bRadius; iB++) {
+				p2.x= iR; p2.y= iG; p2.z= iB;
+				val= 255.0 / (points3d_distance (&p1, &p2) / dDivisor + 1.0);
+				val+= m_ColorLookup[iR][iG][iB];
+				if (val>= 255.0) m_ColorLookup[iR][iG][iB]= 255;
+				else m_ColorLookup[iR][iG][iB]= (unsigned char) val;
+			}
+		}
+	}
+}
+
+// Realitza entrenament per una imatge IPL tenint en compte ROI
+void CRGBCubicColor::TrainImage (const IplImage *img, int radius, double dDivisor)
+{	
+	int x, y, xIni, yIni, xLim, yLim;
+	unsigned char *pImg;
+
+	assert (img && img->imageData);
+	assert (!strncmp (img->colorModel, "RGBA", 4) &&
+			!strncmp (img->channelSeq, "BGRA", 4));
+
+	// L�mits on s'ha d'aplicar la funci�
+	crvGetROILimits (img, xIni, yIni, xLim, yLim);
+	
+	// Aplica tractament a la ROI
+	for (y= yIni; y< yLim; y++) {
+		// Apuntador inici fila component R
+		pImg= (unsigned char *) crvImgOffset (img, xIni, y);		
+		for (x= xIni; x< xLim; x++) {
+			TrainColor (pImg[2], pImg[1], pImg[0], radius, dDivisor);
+			pImg+= 4;
+		}
+	}
+}
+
+// Genera imatge resultant d'indexar la taula 
+// per tots els p�xels
+// De moment nom�s v�lid per imatges RGBA
+void CRGBCubicColor::LookupImage (const IplImage *pSrc, IplImage *pDst)
+{
+	int x, y, xIni, yIni, xLim, yLim;
+	unsigned char *pSrcB, *pDstB;
+
+	assert (pSrc && pSrc->imageData &&
+			pDst && pDst->imageData);
+	assert (!strncmp (pSrc->colorModel, "RGBA", 4) &&
+			!strncmp (pSrc->channelSeq, "BGRA", 4) &&
+			!strncmp (pDst->colorModel, "GRAY", 4) &&
+			!strncmp (pDst->channelSeq, "GRAY", 4) );
+
+	// L�mits on s'ha d'aplicar la funci�
+	crvGetROILimits (pSrc, xIni, yIni, xLim, yLim);
+	
+	// Aplica tractament a la ROI
+	for (y= yIni; y< yLim; y++) {
+		// Apuntador inici fila component R
+		pSrcB= (unsigned char *) crvImgOffset (pSrc, xIni, y);
+		pDstB= (unsigned char *) crvImgOffset (pDst, xIni, y);
+		for (x= xIni; x< xLim; x++) {
+			*pDstB= m_ColorLookup[pSrcB[2]][pSrcB[1]][pSrcB[0]];
+			//pDstB[1]= pDstB[0];
+			//pDstB[2]= pDstB[0];
+			//pDstB[3]= pSrcB[3];
+
+			pSrcB+= 4;
+			pDstB++;
+		}
+	}
+}
+
+// Genera constants model de color a partir de la ROI
+// d'una imatge RGBA
+void crvExtractSkinColorModel (IplImage *pIpl, float &krg_min, float &krg_max,
+							   float &krb_min, float &krb_max)
+{
+	int x, y, xIni, yIni, xLim, yLim;
+	float krg, krb;
+	unsigned char *pSrc;
+
+	assert (pIpl);
+
+	// Inicialitzacions
+	krg_min= 9999999999.0f;
+	krb_min= 9999999999.0f;
+	krg_max= -9999999999.0f;
+	krb_max= -9999999999.0f;
+
+	// L�mits on s'ha d'aplicar la funci�
+	crvGetROILimits (pIpl, xIni, yIni, xLim, yLim);
+	
+	// Aplica tractament a la ROI
+	for (y= yIni; y< yLim; y++) {
+		// Apuntador inici fila component R
+		pSrc= (unsigned char *) crvImgOffset (pIpl, xIni, y);		
+		for (x= xIni; x< xLim; x++) {
+			krg= (float) pSrc[0] / (float) pSrc[1];
+			krb= (float) pSrc[0] / (float) pSrc[2];
+			pSrc+= 4;
+
+			if (krg< krg_min) krg_min= krg;
+			if (krg> krg_max) krg_max= krg;
+			if (krb< krb_min) krb_min= krb;
+			if (krb> krb_max) krb_max= krb;
+		}
+	}
+}
+
+
+
+// Converteix una imatge a color a escala de grisos
+void crvColorToGray (const IplImage *pImgSrc, IplImage *pImgDst)
+{
+	int x, y, xIni, yIni, xLim, yLim;
+	int xDstIni, yDstIni, xDstLim, yDstLim;
+	unsigned char *pSrcPix, *pDstPix;
+	unsigned int sum;
+
+	assert (pImgSrc && pImgDst && pImgSrc!= pImgDst && 
+			pImgSrc->imageData!= pImgDst->imageData);
+	assert (pImgSrc->depth== IPL_DEPTH_8U && 
+			pImgDst->depth== IPL_DEPTH_8U);
+	assert (((!strncmp (pImgSrc->channelSeq, "BGRA", 4) && pImgSrc->nChannels== 4) ||
+			 (!strncmp (pImgSrc->channelSeq, "BGR", 4) && pImgSrc->nChannels== 3) ||
+			 (!strncmp (pImgSrc->channelSeq, "RGB", 4) && pImgSrc->nChannels== 3)) &&
+			  !strncmp (pImgDst->channelSeq, "GRAY", 4) );
+
+	// PROV: les ROI han de ser ind�ntiques
+	crvGetROILimits (pImgSrc, xIni, yIni, xLim, yLim);
+	crvGetROILimits (pImgDst, xDstIni, yDstIni, xDstLim, yDstLim);
+
+	assert (xIni== xDstIni && yIni== yDstIni &&
+			xLim== xDstLim && yLim== yDstLim);
+
+	if (pImgSrc->nChannels== 3)
+	{
+		// 3 channels
+		for (y= yIni; y< yLim; y++) {
+			pSrcPix= (unsigned char *) crvImgOffset (pImgSrc, xIni, y);
+			pDstPix= (unsigned char *) crvImgOffset (pImgDst, xIni, y);
+			for (x= xIni; x< xLim; x++) {
+				sum= *pSrcPix; pSrcPix++;	// B
+				sum+= *pSrcPix; pSrcPix++;	// G
+				sum+= *pSrcPix; pSrcPix++;	// R
+				*pDstPix= (unsigned char) (sum / 3);
+				pDstPix++;
+			}
+		}
+	}
+	else
+	{
+		// 4 chanels
+		for (y= yIni; y< yLim; y++) {
+			pSrcPix= (unsigned char *) crvImgOffset (pImgSrc, xIni, y);
+			pDstPix= (unsigned char *) crvImgOffset (pImgDst, xIni, y);
+			for (x= xIni; x< xLim; x++) {
+				sum= *pSrcPix; pSrcPix++;	// B
+				sum+= *pSrcPix; pSrcPix++;	// G
+				sum+= *pSrcPix; pSrcPix++;	// R
+				pSrcPix++;					// A
+				*pDstPix= (unsigned char) (sum / 3);
+				pDstPix++;
+			}
+		}
+	}
+}
diff --git a/src/creavision/crvcolor.h b/src/creavision/crvcolor.h
new file mode 100755
index 0000000..a2ea3cd
--- /dev/null
+++ b/src/creavision/crvcolor.h
@@ -0,0 +1,57 @@
+/////////////////////////////////////////////////////////////////////////////
+// Name:        crvcolor.h
+// Purpose:  
+// Author:      Cesar Mauri Loba (cesar at crea-si dot com)
+// Modified by: 
+// Created:     
+// Copyright:   (C) 2008 Cesar Mauri Loba - CREA Software Systems
+// 
+//  This program is free software: you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation, either version 3 of the License, or
+//  (at your option) any later version.
+//
+//  This program is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+/////////////////////////////////////////////////////////////////////////////
+#ifndef CRVCOLOR_H
+#define CRVCOLOR_H
+
+#include <cv.h>
+
+class CRGBCubicColor
+{
+private:
+	unsigned char m_ColorLookup[256][256][256];
+	enum { DEFAULT_RADIUS= 2 };	
+public:
+	void Clear();
+	void TrainColor (unsigned char r, unsigned char g, unsigned char b, 
+					int radius= DEFAULT_RADIUS,
+					double dDivisor= 1.0);
+	void TrainImage (const IplImage *img, int radius= DEFAULT_RADIUS,
+				double dDivisor= 1.0);
+	void LookupImage (const IplImage *pSrc, IplImage *pDst);
+	unsigned char LookupColor (unsigned char r, unsigned char g, unsigned char b) {
+		return m_ColorLookup[r][g][b];
+	}
+};
+
+// Genera constants model de color a partir de la ROI
+// d'una imatge RGBA
+void crvExtractSkinColorModel (IplImage *pIpl, float &krg_min, float &krg_max,
+							   float &krb_min, float &krb_max);
+
+// Binaritza imatge a color segons model de color de la pell
+void crvBinarizeSkinColorModel (IplImage *pIpl, float &krg_min, float &krg_max,
+							   float &krb_min, float &krb_max);
+
+// Converteix una imatge a color a escala de grisos
+void crvColorToGray (const IplImage *pImgSrc, IplImage *pIplDst);
+
+#endif
diff --git a/src/creavision/crvgeomtry.cpp b/src/creavision/crvgeomtry.cpp
new file mode 100755
index 0000000..10e0213
--- /dev/null
+++ b/src/creavision/crvgeomtry.cpp
@@ -0,0 +1,345 @@
+/////////////////////////////////////////////////////////////////////////////
+// Name:        crvgeomtry.cpp
+// Purpose:  
+// Author:      Cesar Mauri Loba (cesar at crea-si dot com)
+// Modified by: 
+// Created:     22/02/2008
+// Copyright:   (C) 2008 Cesar Mauri Loba - CREA Software Systems
+// 
+//  This program is free software: you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation, either version 3 of the License, or
+//  (at your option) any later version.
+//
+//  This program is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+/////////////////////////////////////////////////////////////////////////////
+
+#include "crvgeomtry.h"
+#include <math.h>
+
+/* troba el punt mig d'un segment */
+inline
+void segment_mean_point (tRPoint *p1, tRPoint *p2, tRPoint *mp)
+{
+    mp->x= (p1->x + p2->x) / 2.0;
+    mp->y= (p1->y + p2->y) / 2.0;
+}
+
+/* distancia entre dos punts */
+inline
+Real points_distance (tRPoint *p1, tRPoint *p2)
+{
+    Real xd= p2->x - p1->x, yd= p2->y - p1->y;
+
+    return sqrt(xd*xd + yd*yd);
+}
+
+/* dist�ncia entre 2 punts 3D */
+Real points3d_distance (t3DRPoint *p1, t3DRPoint * p2)
+{
+	Real xd, yd, zd;
+
+	xd= p1->x - p2->x;
+	yd= p1->y - p2->y;
+	zd= p1->z - p2->z;
+
+	return sqrt (xd*xd + yd*yd + zd*zd);
+}
+
+/* equaci� de la recta que passa per dos punts  y= mx + n */
+void points2rect (tRPoint *p1, tRPoint *p2, tRect *r)
+{
+    Real v1, v2;
+
+    v1= p2->y - p1->y;
+    v2= p2->x - p1->x;
+    if (v2!= 0.0) {
+        r->m= v1 / v2;
+        r->n= p1->y - (r->m * p1->x);
+    }
+    else {
+        r->m= INF_M;
+        r->n= p1->x;
+    }
+}
+
+/* dist�ncia d'una recta a un punt */
+Real point_rect_distance (tRect *r, tRPoint *p)
+{
+    tRect nr;
+    tRPoint np;
+
+    if (r->m>= INF_M) return fabs(r->n - p->x);     /* pendent infinita */
+    if (r->m== 0.0) return fabs(p->y - r->n);       /* pendent 0 */
+
+    /* perpendicular a r que passa per p */
+    nr.m = -1.0 / r->m;
+    nr.n = p->y - (nr.m * p->x);
+
+    /* punt de tall */
+    np.x = (r->n - nr.n) / (nr.m - r->m);
+    np.y = r->m * np.x + r->n;
+
+    return points_distance (p, &np);
+}
+
+/* calcula l'angle del vector que va de p1 a p2 */
+Real segment_angle (tRPoint *p1, tRPoint *p2)
+{
+    Real dx, dy;
+
+    dx= p2->x - p1->x;
+    dy= p2->y - p1->y;
+
+    if (dx== 0.0) {
+        if (dy>= 0.0) return (M_PI / 2.0);
+        else return (3.0 * M_PI / 2.0);
+    }
+    if (dx> 0.0) {
+        if (dy< 0.0) return (2.0 * M_PI) + atan(dy / dx);
+        else return atan(dy / dx);
+    }
+    else return atan(dy / dx) + M_PI;
+
+//    return 0.0;     /* evitar warning */
+}
+
+/* donada una recta diu si un punt es troba sobre la recta (0)
+   o a la banda positiva (1) o negativa de la recta (-1) */
+int point_rect_where (tRect *r, tRPoint *p, Real error)
+{
+    Real result;
+
+    /* si la recta es vertical nom�s cal mirar la coordenada X */
+    if (r->m>= INF_M) result= p->x - r->n;
+    /* sin� s'ha de substituir el punt a l'equaci� de la recta
+       i avaluar-ne el resultat */
+    else result= r->m * p->x + r->n - p->y;
+
+    if (fabs(result)<= error) return 0;
+    else if (result> 0.0) return 1;
+    else return -1;
+}
+
+/* donat un segment retorna si un determinat punt es troba a la dreta (1),
+sobre el segment (0) o a l'esquerra (-1). La posici� es mira respecte
+la direcci� del vector entre p1 i p2 */
+int point_segment_where (tRPoint *p1, tRPoint *p2, tRPoint *p, Real error)
+{
+	Real vx= p2->x - p1->x, vy= p2->y - p1->y;
+	
+	Real ang= atan2 (vx, vy); 
+
+	tRect r;
+	points2rect (p1, p2, &r);
+	int rectWhere= point_rect_where (&r, p, error);
+
+	if (r.m>= INF_M) 
+	{
+		if (vy<= 0) return rectWhere;
+		else return -rectWhere;
+	}
+
+	if (rectWhere== 0) return 0;
+	if (ang> 0) return -rectWhere;
+	else return rectWhere;	
+}
+
+/* calcula la recta perpendicular a una donada que passa per un punt */
+void perpendicular_rect (tRect *r, tRPoint *p, tRect *perp)
+{
+    if (r->m>= INF_M) {
+        /* pendent infinita */
+        perp->m= 0.0;
+        perp->n= p->y;
+    }
+    else if (r->m== 0.0) {
+        /* pendent 0 */
+        perp->m= INF_M;
+        perp->n= p->x;
+    }
+    else {
+        /* perpendicular a r que passa per p */
+        perp->m = -1.0 / r->m;
+        perp->n = p->y - (perp->m * p->x);
+    }
+}
+
+/* troba el punt de tall entre dues rectes. retorna 0 si no hi ha
+   punt de tall, 1 altrament */
+int rects_cutting_point (tRect *r1, tRect *r2, tRPoint *p)
+{
+    if (r1->m== r2->m) return 0;
+    if (r1->m>= INF_M && r2->m>= INF_M) return 0;
+
+    if (r1->m>= INF_M) {
+        p->x= r1->n;
+        p->y = r2->m * p->x + r2->n;
+        return 1;
+    }
+    if (r2->m>= INF_M) {
+        p->x= r2->n;
+        p->y = r1->m * p->x + r1->n;
+        return 1;
+    }
+
+    p->x = (r1->n - r2->n) / (r2->m - r1->m);
+    p->y = r1->m * p->x + r1->n;
+
+    return 1;
+}
+
+/* determina si un punt que pertany a la recta que passa per un
+   segment es troba dins els l�mits del segment */
+static inline
+int point_rect_on_segment (tRPoint *p1, tRPoint *p2, tRPoint *ptest)
+{
+    tRPoint smin, smax;
+
+    /* caixa englobant del segment */
+    if (p1->x< p2->x) {
+        smin.x= p1->x;
+        smax.x= p2->x;
+    }
+    else {
+        smin.x= p2->x;
+        smax.x= p1->x;
+    }
+    if (p1->y< p2->y) {
+        smin.y= p1->y;
+        smax.y= p2->y;
+    }
+    else {
+        smin.y= p2->y;
+        smax.y= p1->y;
+    }
+
+    if (ptest->x> smax.x || ptest->x< smin.x ||
+        ptest->y> smax.y || ptest->y< smin.y)  return 0;
+
+    return 1;
+}
+
+/* diu si dos segments es tallen en algun punt */
+int segments_cutting (tRPoint *s1p1, tRPoint *s1p2, tRPoint *s2p1, tRPoint *s2p2)
+{
+    tRect r1, r2;
+    tRPoint pcut;
+
+    /* obt� equacions de les rectes dels segments */
+    points2rect (s1p1, s1p2, &r1);
+    points2rect (s2p1, s2p2, &r2);
+
+    /* punt de tall de les dues rectes */
+    if (rects_cutting_point (&r1, &r2, &pcut)== 0) return 0;
+
+    /* comprova si el punt de tall pertany als dos segments */
+    return (point_rect_on_segment (s1p1, s1p2, &pcut) &&
+            point_rect_on_segment (s2p1, s2p2, &pcut) );
+}
+
+/* calcula el centre d'una circumfer�ncia a partir de 3 punts del per�metre.
+   retorna 0 si no es possible determinar el center, 1 si tot correcte */
+int circle_center (tRPoint  *p1, tRPoint *p2, tRPoint *p3, tRPoint *center)
+{
+    tRect r1, r2, pr1, pr2;
+    tRPoint mp1, mp2;
+
+    points2rect (p1, p2, &r1);
+    points2rect (p2, p3, &r2);
+
+    /* punts mitjos de les rectes */
+    segment_mean_point (p1, p2, &mp1);
+    segment_mean_point (p2, p3, &mp2);
+
+    /* rectes perpendiculars que passen per aquestos punts */
+    perpendicular_rect (&r1, &mp1, &pr1);
+    perpendicular_rect (&r2, &mp2, &pr2);
+
+    /* punt de tall de les rectes anteriors */
+    return rects_cutting_point (&pr1, &pr2, center);
+}
+
+/* donat un punt el rota l'angle indicat respecte del centre */
+void point_rotate (tRPoint *p, tRPoint *center, Real ang)
+{
+    Real beta, dist;
+
+    beta= segment_angle (center, p) + ang;
+    dist= points_distance (center, p);
+
+    p->x= center->x + dist * cos (beta);
+    p->y= center->y + dist * sin (beta);
+}
+
+/* escalat d'un segment. es modifica el punt *target per tal que
+   el segment que va de *p a *target tingui la nova dist�ncia indicada  */
+void scale_segment (tRPoint *target, tRPoint *p, Real real_dist)
+{
+    Real modul;
+    Real dx, dy;
+
+    modul= points_distance (target, p);
+    if (modul== 0.0) return;
+    dx= (target->x - p->x) / modul;
+    dy= (target->y - p->y) / modul;
+
+    target->x= p->x + dx * real_dist;
+    target->y= p->y + dy * real_dist;
+}
+
+/* reescala un segment modificant la posici� dels 2 extrems per a
+   que tingui la mida desitjada */
+void rescale_segment (tRPoint *p1, tRPoint *p2, Real real_dist)
+{
+    Real modul;
+    Real dx, dy;
+
+    modul= points_distance (p1, p2);
+    if (modul== 0.0) return;
+    dx= (p2->x - p1->x) / modul;
+    dy= (p2->y - p1->y) / modul;
+
+    dx*= (real_dist - modul) / 2.0;
+    dy*= (real_dist - modul) / 2.0;
+
+    p1->x-= dx; p1->y-= dy;
+    p2->x+= dx; p2->y+= dy;
+}
+
+/* donada una llista de punts que formen un pol�gon tancat en calcula la seva caixa englobant */
+void calculate_englobing_box (tRPoint *lvertexs, int nvertexs, tRPoint *min_box, tRPoint *max_box)
+{
+    int i;
+    
+    min_box->x= max_box->x= lvertexs[0].x;
+    min_box->y= max_box->y= lvertexs[0].y;    
+    
+    for (i= 1; i< nvertexs; i++) {
+        if (lvertexs[i].x> max_box->x) max_box->x= lvertexs[i].x;
+        else if (lvertexs[i].x< min_box->x) min_box->x= lvertexs[i].x;
+        
+        if (lvertexs[i].y> max_box->y) max_box->y= lvertexs[i].y;
+        else if (lvertexs[i].y< min_box->y) min_box->y= lvertexs[i].y;
+    }
+}
+
+/* comprova si dos pol�gons tancats tenen alguna �rea solapada. 
+   NOTA: no es comprova si un pol�gon �s interior a un altre */
+int polys_intersect (tRPoint *v1, int lv1, tRPoint *v2, int lv2)
+{
+    int i, j;
+    
+    for (i= 0; i< lv1; i++) 
+        for (j= 0; j< lv2; j++) {
+            if (segments_cutting (&v1[i], &v1[(i + 1) % lv1], 
+                                  &v2[j], &v2[(j + 1) % lv2])) return 1;
+        }
+    return 0;
+}
diff --git a/src/creavision/crvgeomtry.h b/src/creavision/crvgeomtry.h
new file mode 100755
index 0000000..dd2ec50
--- /dev/null
+++ b/src/creavision/crvgeomtry.h
@@ -0,0 +1,131 @@
+/////////////////////////////////////////////////////////////////////////////
+// Name:        crvgeomtry.h
+// Purpose:  
+// Author:      Cesar Mauri Loba (cesar at crea-si dot com)
+// Modified by: 
+// Created:     22/02/2008
+// Copyright:   (C) 2008 Cesar Mauri Loba - CREA Software Systems
+// 
+//  This program is free software: you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation, either version 3 of the License, or
+//  (at your option) any later version.
+//
+//  This program is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+/////////////////////////////////////////////////////////////////////////////
+
+#ifndef CRVGEOMTRY_H
+#define CRVGEOMTRY_H
+
+typedef double Real;
+
+#define INF_M  999999999    /* valor pendent 'infinita' */
+#define PI	   3.1415926535897932384626433832795
+#ifndef M_PI
+#define M_PI	PI
+#endif
+
+/* TIPUS */
+
+typedef struct tRPoint {
+    Real x, y;
+} tRPoint;
+
+typedef struct t3DRPoint {
+    Real x, y, z;
+} t3DRPoint;
+
+/* equaci� recta en forma y = mx + n */
+typedef struct tRect{
+    Real m, n;
+} tRect;
+
+
+/* FUNCIONS */
+
+/* copia d'un punt */
+static inline
+void cp_point (tRPoint *dst, tRPoint *src)
+{
+    dst->x= src->x;
+    dst->y= src->y;
+}
+
+/* dist�ncia entre 2 punts */
+Real points_distance (tRPoint *p1, tRPoint *p2);
+
+/* dist�ncia entre 2 punts 3D */
+Real points3d_distance (t3DRPoint *p1, t3DRPoint * p2);
+
+/* equaci� de la recta que passa per dos punts */
+void points2rect (tRPoint *p1, tRPoint *p2, tRect *r);
+
+/* dist�ncia d'un punt a una recta */
+Real point_rect_distance (tRect *r, tRPoint *p);
+
+/* calcula l'angle del vector que va de p1 a p2 */
+Real segment_angle (tRPoint *p1, tRPoint *p2);
+
+/* donada una recta diu si un punt es troba sobre la recta (0)
+   o a la banda positiva (1) o negativa de la recta (-1) */
+int point_rect_where (tRect *r, tRPoint *p, Real error);
+
+/* donat un segment retorna si un determinat punt es troba a la dreta (1),
+sobre el segment (0) o a l'esquerra (-1). La posici� es mira respecte
+la direcci� del vector entre p1 i p2 */
+int point_segment_where (tRPoint *p1, tRPoint *p2, tRPoint *p, Real error);
+
+/* calcula la recta perpendicular a una donada que passa per un punt */
+void perpendicular_rect (tRect *r, tRPoint *p, tRect *perp);
+
+/* troba el punt mig d'un segment */
+void segment_mean_point (tRPoint *p1, tRPoint *p2, tRPoint *mp);
+
+/* troba el punt de tall entre dues rectes. retorna 0 si no hi ha
+   punt de tall, 1 altrament */
+int rects_cutting_point (tRect *r1, tRect *r2, tRPoint *p);
+
+/* calcula el centre d'una circumfer�ncia a partir de 3 punts del per�metre.
+   retorna 0 si no es possible determinar el center, 1 si tot correcte */
+int circle_center (tRPoint  *p1, tRPoint *p2, tRPoint *p3, tRPoint *center);
+
+/* donat un punt el rota l'angle indicat respecte del centre */
+void point_rotate (tRPoint *p, tRPoint *center, Real ang);
+
+/* escalat d'un segment. es modifica el punt *target per tal que
+   el segment que va de *p a *target tingui la nova dist�ncia indicada  */
+void scale_segment (tRPoint *target, tRPoint *p, Real real_dist);
+
+/* reescala un segment modificant la posici� dels 2 extrems per a
+   que tingui la mida desitjada */
+void rescale_segment (tRPoint *p1, tRPoint *p2, Real real_dist);
+
+/* donada una llista de punts que formen un pol�gon tancat
+   en calcula la seva caixa englobant */
+void calculate_englobing_box (tRPoint *lvertexs, int nvertexs,
+                              tRPoint *min_box, tRPoint *max_box);
+
+/* comprova si dos caixes englobants intersecten */
+static inline
+int englobing_box_instersection (tRPoint *min1, tRPoint *max1,
+                                 tRPoint *min2, tRPoint *max2)
+{
+    return (!(min1->x> max2->x || min1->y> max2->y ||
+              min2->x> max1->x || min2->y> max2->y )
+           );             
+}
+
+/* diu si dos segments es tallen en algun punt */
+int segments_cutting (tRPoint *s1p1, tRPoint *s1p2, tRPoint *s2p1, tRPoint *s2p2);
+
+/* comprova si dos pol�gons tancats tenen alguna �rea solapada. 
+   NOTA: no es comprova si un pol�gon �s interior a un altre */
+int polys_intersect (tRPoint *v1, int lv1, tRPoint *v2, int lv2);
+
+#endif
diff --git a/src/creavision/crvhistogram.cpp b/src/creavision/crvhistogram.cpp
new file mode 100755
index 0000000..995ecf1
--- /dev/null
+++ b/src/creavision/crvhistogram.cpp
@@ -0,0 +1,143 @@
+/////////////////////////////////////////////////////////////////////////////
+// Name:        crvhistogram.cpp
+// Purpose:  
+// Author:      Cesar Mauri Loba (cesar at crea-si dot com)
+// Modified by: 
+// Created:     30/05/2008
+// Copyright:   (C) 2008 Cesar Mauri Loba - CREA Software Systems
+// 
+//  This program is free software: you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation, either version 3 of the License, or
+//  (at your option) any later version.
+//
+//  This program is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+/////////////////////////////////////////////////////////////////////////////
+#include "crvhistogram.h"
+#include "crvmisc.h"
+
+// Computes the histogram of a gray image
+void crvHistogram (IplImage *srcImg, TCrvHistogram &his)
+{
+	int x, y, xIni, yIni, xLim, yLim;
+	unsigned char *pSrc= (unsigned char *) srcImg->imageData;
+	
+	assert (srcImg->depth== IPL_DEPTH_8U);
+
+	// ROI
+	crvGetROILimits (srcImg, xIni, yIni, xLim, yLim);
+
+	// Init
+	for (x= 0; x< 256; x++) his[x]= 0;
+
+	for (y= yIni; y< yLim; y++) {
+		// Begining row pointer
+		pSrc= (unsigned char *) crvImgByteOffset (srcImg, xIni, y);		
+		for (x= xIni; x< xLim; x++) {
+			his[*pSrc]++;
+			pSrc++;
+		}
+	}
+}
+
+// Computes where the histogram begins and ends (non-zero values)
+// Return false if histogram is void
+bool crvHistogramBeginEnd (TCrvHistogram &his, unsigned char &begin, unsigned char &end)
+{
+	int i;
+	
+	// Begining
+	for (i= 0; i< 256; i++) {
+		if (his[i]> 0) {
+			begin= (unsigned char) i;
+			break;
+		}
+	}
+
+	if (i== 256) return false;
+
+	// End
+	for (i= 255; i>= 0; i--) {
+		if (his[i]> 0) {
+			end= (unsigned char) i;
+			break;
+		}
+	}
+
+	assert (i> -1);
+
+	return true;
+}
+
+
+// Aplica a una imatge de grisos la transformaci� que imposa la
+// lookup-table passada com a par�metre (t� en compte ROI)
+void crvLUTTransform (IplImage *srcImg, IplImage *dstImg, TCrvLookupTable &lut)
+{
+	int x, y, xIni, yIni, xLim, yLim;
+	unsigned char *pSrc= (unsigned char *) srcImg->imageData,
+				  *pDst= (unsigned char *) dstImg->imageData;
+
+	assert (srcImg->depth== IPL_DEPTH_8U && 
+			dstImg->depth== IPL_DEPTH_8U);
+	
+	// L�mits on s'ha d'aplicar la funci�
+	crvGetROILimits (srcImg, xIni, yIni, xLim, yLim);
+
+	// Aplica tractament a la ROI
+	for (y= yIni; y< yLim; y++) {
+		// Apuntador inici fila
+		pSrc= (unsigned char *) crvImgByteOffset (srcImg, xIni, y);
+		pDst= (unsigned char *) crvImgByteOffset (dstImg, xIni, y);
+		for (x= xIni; x< xLim; x++) {
+			*pDst= lut[*pSrc];
+			pSrc++;
+			pDst++;
+		}
+	}
+}
+
+// Genera la LUT per normalitzar una imatge a partir del seu
+// histograma. Retorna la mida de l'histograma
+int crvNormalizeHistogram (TCrvHistogram &his, TCrvLookupTable &lut, unsigned char minRange)
+{
+	int i, range;
+	unsigned char min, max;
+
+	if (!crvHistogramBeginEnd (his, min, max)) return 0;
+	if (min== max) return 0;
+
+	range= max - min;
+	if (range< minRange) range= minRange;
+
+	for (i= min; i<= max; i++) {
+		lut[i]= (unsigned char) (((int) (i - min) * 255) / range);
+	}
+
+	return max - min;
+}
+
+
+// Normalitza una imatge en escala de grisos
+int crvNormalize (IplImage *src, IplImage *dst)
+{
+	TCrvHistogram his;
+	TCrvLookupTable lut;
+	int range;
+	 	
+	assert (src->depth== IPL_DEPTH_8U && src->depth== IPL_DEPTH_8U);
+
+	crvHistogram (src, his);
+
+	range= crvNormalizeHistogram (his, lut);
+
+	crvLUTTransform (src, dst, lut);
+
+	return range;
+}
diff --git a/src/creavision/crvhistogram.h b/src/creavision/crvhistogram.h
new file mode 100755
index 0000000..dc2bda1
--- /dev/null
+++ b/src/creavision/crvhistogram.h
@@ -0,0 +1,49 @@
+/////////////////////////////////////////////////////////////////////////////
+// Name:        crvhistogram.h
+// Purpose:  
+// Author:      Cesar Mauri Loba (cesar at crea-si dot com)
+// Modified by: 
+// Created:     30/05/2008
+// Copyright:   (C) 2008 Cesar Mauri Loba - CREA Software Systems
+// 
+//  This program is free software: you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation, either version 3 of the License, or
+//  (at your option) any later version.
+//
+//  This program is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+/////////////////////////////////////////////////////////////////////////////
+#ifndef CRVHISTOGRAM_H
+#define CRVHISTOGRAM_H
+
+#include <cv.h>
+
+typedef unsigned char TCrvLookupTable[256];
+typedef int TCrvHistogram[256];
+
+// Calcula l'histograma d'una imatge
+void crvHistogram (IplImage *srcImg, TCrvHistogram &his);
+
+// Calcula on comen�a i acaba un histograma. Retorna
+// false si l'histograma �s buit (tot zeros)
+bool crvHistogramBeginEnd (TCrvHistogram &his, unsigned char &begin, unsigned char &end);
+
+// Aplica a una imatge de grisos la transformaci� que imposa la
+// lookup-table passada com a par�metre (t� en compte ROI)
+void crvLUTTransform (IplImage *srcImg, IplImage *dstImg, TCrvLookupTable &lut);
+
+// Genera la LUT per normalitzar una imatge a partir del seu
+// histograma. Retorna la mida de l'histograma
+int crvNormalizeHistogram (TCrvHistogram &his, TCrvLookupTable &lut, unsigned char minRange= 0);
+
+// Normalitza una imatge en escala de grisos (impl. lenta)
+// Retorna mida histograma original
+int crvNormalize (IplImage *src, IplImage *dst);
+
+#endif
diff --git a/src/creavision/crvimage.cpp b/src/creavision/crvimage.cpp
new file mode 100755
index 0000000..5a3e577
--- /dev/null
+++ b/src/creavision/crvimage.cpp
@@ -0,0 +1,327 @@
+/////////////////////////////////////////////////////////////////////////////
+// Name:        crvimage.cpp
+// Purpose:  
+// Author:      Cesar Mauri Loba (cesar at crea-si dot com)
+// Modified by: 
+// Created:     10/01/2008
+// Copyright:   (C) 2008 Cesar Mauri Loba - CREA Software Systems
+// 
+//  This program is free software: you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation, either version 3 of the License, or
+//  (at your option) any later version.
+//
+//  This program is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+/////////////////////////////////////////////////////////////////////////////
+#include "crvimage.h"
+#include <highgui.h>
+#include <string.h>
+#include <stdio.h>
+#include <assert.h>
+
+// Construction
+CIplImage::CIplImage ()
+{
+	Init();
+}
+
+CIplImage::CIplImage (IplImage *pImg)
+{
+	Init();
+	Import (pImg);
+}
+
+CIplImage::CIplImage (int width, int height, int depth, const char *pColorOrder)
+{
+	Init();
+
+	bool retval= Create (width, height, depth, pColorOrder);
+#ifndef NDEBUG
+	assert (retval);
+#endif
+}
+
+CIplImage::~CIplImage ()
+{
+	Free ();
+}
+
+void CIplImage::Init()
+{
+	m_pIplImage= NULL;
+	m_importedImage= false;
+	m_importedROI= NULL;
+	m_roiStackPtr= 0;
+}
+
+void CIplImage::InitROIStack (int width, int height)
+{
+	m_roiStack[0].coi= 0;
+	m_roiStack[0].xOffset= 0;
+	m_roiStack[0].yOffset= 0;
+	m_roiStack[0].width= width;
+	m_roiStack[0].height= height;	
+	
+	m_roiStackPtr= 0;
+}
+
+// Creation
+bool CIplImage::Create (int width, int height, unsigned int depth, const char *pColorOrder, int origin, int align )
+{
+	int nChannels= 0;
+	const char *pColorModel= NULL;
+	bool alphaChannel= false;
+
+	assert (width> 0 && width< 4000);
+	assert (height> 0 && height< 4000);
+	assert (pColorOrder);
+	assert (depth== IPL_DEPTH_1U  || depth== IPL_DEPTH_8U  ||
+			depth== IPL_DEPTH_8S  || depth== IPL_DEPTH_16U ||
+			depth== IPL_DEPTH_16S || depth== IPL_DEPTH_32S ||
+			depth== IPL_DEPTH_32F);
+
+	Free ();
+
+	InitROIStack (width, height);
+
+	if ( !strcmp (pColorOrder, "GRAY") ||
+		 !strcmp (pColorOrder, "G") ) {
+		nChannels= 1; pColorModel= "GRAY";
+	}
+	else if ( !strcmp (pColorOrder, "BGR") ||
+			  !strcmp (pColorOrder, "RGB") ) {
+		nChannels= 3; pColorModel= "RGB";
+	}
+	else if ( !strcmp (pColorOrder, "RGBA") ||
+			  !strcmp (pColorOrder, "BGRA") ) {
+		nChannels= 4; pColorModel= "RGB"; alphaChannel= true;	
+	}
+	else if ( !strcmp (pColorOrder, "YUV") ) {
+		nChannels= 3; pColorModel= "YUV";
+	}
+	else assert (0);
+
+	m_pIplImage= cvCreateImageHeader( cvSize(width,height), depth, nChannels );
+	if (!m_pIplImage) {	assert (0);	return false; }
+	m_pIplImage->alphaChannel= (alphaChannel? 1 : 0);
+	strncpy (m_pIplImage->colorModel, pColorModel, 4);
+	strncpy (m_pIplImage->channelSeq, pColorOrder, 4);
+	m_pIplImage->dataOrder= IPL_DATA_ORDER_PIXEL;
+	m_pIplImage->origin= origin;
+	m_pIplImage->align=	align;
+	//m_pIplImage->widthStep=
+	m_pIplImage->roi= &m_roiStack[0];
+	//assert (m_pIplImage->roi== &m_roiStack[0]);
+	assert (m_pIplImage->imageData== NULL);
+
+	cvCreateData( m_pIplImage );
+	
+	if (CV_StsOk != cvGetErrStatus()) {
+		assert (0);
+		
+		m_pIplImage->roi= NULL;
+		cvReleaseImageHeader( &m_pIplImage );
+		m_pIplImage= NULL;
+		return false;
+	}
+
+	return true;
+}
+
+bool CIplImage::Import (IplImage *pImage, bool autodelete)
+{
+	assert (pImage);
+
+	// Cannot import the same image
+	assert (pImage!= this->m_pIplImage);
+	if (pImage== this->m_pIplImage) return false;
+
+	assert (!autodelete);	// Not supported
+
+	Free ();
+	
+	m_pIplImage= pImage;
+	m_importedImage= true;
+	InitROIStack (pImage->width, pImage->height);
+	m_importedROI= pImage->roi;
+	if (pImage->roi) m_roiStack[m_roiStackPtr]= *pImage->roi;
+	pImage->roi= &m_roiStack[m_roiStackPtr];
+	//m_roiStackPtr= 0;
+
+	return true;
+}
+
+void CIplImage::Free ()
+{
+	bool wasImported= m_importedImage;
+	IplImage* retval= this->Detach();
+	if (retval && !wasImported) cvReleaseImage( &retval );
+}
+
+IplImage* CIplImage::Detach()
+{
+	if (!m_pIplImage) return NULL;
+
+	if (m_importedImage) 
+		m_pIplImage->roi= m_importedROI;
+	else 
+		m_pIplImage->roi= NULL;
+
+	IplImage* retval= m_pIplImage;
+	
+	Init ();
+
+	return retval;	
+}
+
+void CIplImage::Swap (CIplImage *pOtherImg)
+{
+	int i;
+
+	if (this== pOtherImg) return;	// Nohing to do
+
+	// Copy other image to tmp
+	IplImage *tmp_pIplImage= pOtherImg->m_pIplImage;
+	bool tmp_importedImage= pOtherImg->m_importedImage;
+	IplROI *tmp_importedROI= pOtherImg->m_importedROI;
+	IplROI tmp_roiStack[ROI_STACK_SIZE];
+	int tmp_roiStackPtr= pOtherImg->m_roiStackPtr;
+	for (i= 0; i<= tmp_roiStackPtr; i++) {
+		tmp_roiStack[i]= pOtherImg->m_roiStack[i]; 
+	}
+	// 'Copy' current to other
+	pOtherImg->m_pIplImage= m_pIplImage;
+	pOtherImg->m_importedImage= m_importedImage;
+	pOtherImg->m_importedROI= m_importedROI;
+	pOtherImg->m_roiStackPtr= m_roiStackPtr;
+	for (i= 0; i<= pOtherImg->m_roiStackPtr; i++) {
+		pOtherImg->m_roiStack[i]= m_roiStack[i];
+	}
+	
+	if (pOtherImg->m_pIplImage) {
+		pOtherImg->m_pIplImage->roi= 
+			&pOtherImg->m_roiStack[pOtherImg->m_roiStackPtr];
+	}
+
+	// 'Copy' tmp to current
+	m_pIplImage= tmp_pIplImage;
+	m_importedImage= tmp_importedImage;
+	m_importedROI= tmp_importedROI;
+	m_roiStackPtr= tmp_roiStackPtr;
+	for (i= 0; i<= m_roiStackPtr; i++) {
+		m_roiStack[i]= tmp_roiStack[i];
+	}
+	if (m_pIplImage) { m_pIplImage->roi= &m_roiStack[m_roiStackPtr]; }
+}
+
+void CIplImage::Reset ()
+{
+	assert (m_pIplImage);
+	if (m_pIplImage== NULL) return;
+	cvSetZero(m_pIplImage);
+}
+
+// ROI
+bool CIplImage::SetROI (int x, int y, int width, 
+						int height, unsigned int coi)
+{
+	assert (m_pIplImage);
+	assert (m_pIplImage->roi== &m_roiStack[m_roiStackPtr]);
+	assert (x>= 0 && y>= 0 && width> 0 && height> 0);
+	
+	// Check limits for the ROI
+	if (x< 0 || (x + width > m_pIplImage->width)) {
+		assert (false);
+		return false;
+	}
+	if (y< 0 || (y + height > m_pIplImage->height)) {
+		assert (false);
+		return false;
+	}
+
+	// ROI Ok
+	m_roiStack[m_roiStackPtr].coi= coi;
+	m_roiStack[m_roiStackPtr].xOffset= x;
+	m_roiStack[m_roiStackPtr].yOffset= y;
+	m_roiStack[m_roiStackPtr].width= width;
+	m_roiStack[m_roiStackPtr].height= height;
+	
+	return true;
+}
+
+void CIplImage::GetROI (IplROI &roi)
+{
+	assert (m_pIplImage);
+	assert (m_pIplImage->roi== &m_roiStack[m_roiStackPtr]);
+
+	roi= m_roiStack[m_roiStackPtr];	
+}
+
+void CIplImage::ResetROI ()
+{
+	assert (m_pIplImage);
+	assert (m_pIplImage->roi== &m_roiStack[m_roiStackPtr]);
+	
+	m_pIplImage->roi->coi= 0;
+	m_pIplImage->roi->xOffset= 0;
+	m_pIplImage->roi->yOffset= 0;
+	m_pIplImage->roi->width= m_pIplImage->width;
+	m_pIplImage->roi->height= m_pIplImage->height;
+}
+
+void CIplImage::PushROI ()
+{
+	assert (m_pIplImage);
+	assert (m_pIplImage->roi== &m_roiStack[m_roiStackPtr]);
+	assert (m_roiStackPtr< ROI_STACK_SIZE - 1);
+
+	m_roiStack[m_roiStackPtr + 1]= m_roiStack[m_roiStackPtr];
+	m_roiStackPtr++;
+	m_pIplImage->roi= &m_roiStack[m_roiStackPtr];
+}
+
+void CIplImage::PopROI ()
+{
+	assert (m_pIplImage);
+//	assert (m_pIplImage->roi== &m_roiStack[m_roiStackPtr]);
+	assert (m_roiStackPtr> 0);
+
+	m_roiStackPtr--;
+	m_pIplImage->roi= &m_roiStack[m_roiStackPtr];
+}
+
+bool CIplImage::Load (char *pFilename)
+{
+	Free ();
+
+	m_pIplImage = cvvLoadImage( pFilename );
+
+	if (m_pIplImage== NULL) return false;
+
+	return true;
+}
+
+bool CIplImage::Save (char *pFilename)
+{
+	assert (m_pIplImage);
+	assert (pFilename);
+
+	return (cvvSaveImage (pFilename, m_pIplImage)== 0 ? false : true);
+}
+
+void CIplImage::Show (char *id)
+{
+    assert (m_pIplImage);
+	
+	cvvNamedWindow(id, CV_WINDOW_AUTOSIZE );  
+    cvvShowImage( id, m_pIplImage );
+#ifndef linux
+	cvWaitKey (1);
+#endif
+}
diff --git a/src/creavision/crvimage.h b/src/creavision/crvimage.h
new file mode 100755
index 0000000..78344cf
--- /dev/null
+++ b/src/creavision/crvimage.h
@@ -0,0 +1,101 @@
+/////////////////////////////////////////////////////////////////////////////
+// Name:        crvimage.h
+// Purpose:  
+// Author:      Cesar Mauri Loba (cesar at crea-si dot com)
+// Modified by: 
+// Created:     10/01/2008
+// Copyright:   (C) 2008 Cesar Mauri Loba - CREA Software Systems
+// 
+//  This program is free software: you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation, either version 3 of the License, or
+//  (at your option) any later version.
+//
+//  This program is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+/////////////////////////////////////////////////////////////////////////////
+#ifndef CRVIMAGE_H
+#define CRVIMAGE_H
+
+#include <assert.h>
+#include <cv.h>
+
+class CIplImage
+{
+public:
+
+  // Methods
+	// Construction
+	CIplImage ();
+	CIplImage (IplImage *pImg);
+	CIplImage (	int width, int height, int depth= IPL_DEPTH_8U,  
+				const char *pColorOrder= "GRAY");
+	~CIplImage ();
+
+	// Creation/Initialization
+	bool Create (int width, int height, 
+				unsigned int depth= IPL_DEPTH_8U, const char *pColorOrder= "GRAY", 
+				int origin= IPL_ORIGIN_TL, int align= IPL_ALIGN_QWORD );
+
+	bool Import (IplImage *pImage, bool autodelete= false);
+	
+	// Returns the internal pointer, which is set to NULL, and forgets 
+	// about its deallocation
+	IplImage* Detach();
+	void Free ();
+	void Swap (CIplImage *pOtherImg);
+	void Reset ();
+	
+
+	// ROI
+	bool SetROI (int x, int y, int width, 
+				 int height, unsigned int coi= 0);
+	bool SetROI (IplROI &roi) {
+		return SetROI (	roi.xOffset, roi.yOffset, 
+						roi.width, roi.height, roi.coi); }
+	bool SetROI (CvRect &rect) {
+		return SetROI (	rect.x, rect.y, rect.width, rect.height); }
+	void GetROI (IplROI &roi);
+	void ResetROI ();
+
+	void PushROI ();
+	void PopROI ();
+
+	// Data accessors
+	bool Initialized () const { return m_pIplImage!= NULL; }
+	IplImage *ptr () { return m_pIplImage; }
+	const IplImage *ptr () const { return m_pIplImage; }
+	int Width () const { assert (m_pIplImage); return m_pIplImage->width; }
+	int Height () const { assert (m_pIplImage); return m_pIplImage->height; }
+	CvSize GetSize() const { assert (m_pIplImage); return cvSize (m_pIplImage->width, m_pIplImage->height); }
+	// 0 - top-left origin, 1 - bottom-left origin (Windows bitmaps style) 
+	int Origin () const {	assert (m_pIplImage); return m_pIplImage->origin; }
+	int Depth () const { assert (m_pIplImage); return m_pIplImage->depth; }
+	int Align() const { assert (m_pIplImage); return m_pIplImage->align; }
+	
+	// IO
+	bool Load (char *pFilename);
+	bool Save (char *pFilename);
+	void Show (char *id);
+
+private:
+	enum { ROI_STACK_SIZE= 10 };
+
+  // Attributes
+	IplImage *m_pIplImage;
+	bool m_importedImage;
+	IplROI *m_importedROI;
+	IplROI m_roiStack[ROI_STACK_SIZE];
+	int m_roiStackPtr;
+
+  // Private methods
+	void InitROIStack (int width, int height);
+	void Init(); 
+};
+
+#endif	// IPLIMAGE_H
diff --git a/src/creavision/crvmisc.cpp b/src/creavision/crvmisc.cpp
new file mode 100755
index 0000000..8d8b024
--- /dev/null
+++ b/src/creavision/crvmisc.cpp
@@ -0,0 +1,488 @@
+/////////////////////////////////////////////////////////////////////////////
+// Name:        crvmisc.cpp
+// Purpose:  
+// Author:      Cesar Mauri Loba (cesar at crea-si dot com)
+// Modified by: 
+// Created:     23/05/2008
+// Copyright:   (C) 2008 Cesar Mauri Loba - CREA Software Systems
+// 
+//  This program is free software: you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation, either version 3 of the License, or
+//  (at your option) any later version.
+//
+//  This program is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+/////////////////////////////////////////////////////////////////////////////
+
+#include "crvmisc.h"
+#include <float.h>
+#include <assert.h>
+#include <stdio.h>
+#include <math.h>
+
+// uintptr_t type
+#if defined(WIN32)
+#include <stddef.h>
+#else
+#include <stdint.h>
+#endif
+
+
+// Dona l'adre�a de mem�ria del p�xel a la posici� X, Y (DEPRECAT)
+char *crvImgByteOffset (const IplImage *img, int x, int y)
+{
+	assert (img->nChannels== 1);
+
+	switch (img->depth) {
+	case IPL_DEPTH_8U:
+		return (char *)((uintptr_t) img->imageData + x + (y * img->widthStep));
+	case IPL_DEPTH_16U:
+		return (char *)((uintptr_t) img->imageData + x * 2 + (y * img->widthStep));
+	default: assert (0);
+	}
+
+	return NULL;	// Evitar Warning
+}
+
+// Dona l'adre�a de mem�ria del p�xel a la posici� X, Y
+void *crvImgOffset (const IplImage *img, int x, int y)
+{
+	switch (img->depth) {
+	case IPL_DEPTH_8U:
+	case IPL_DEPTH_8S:
+		return (void *)((uintptr_t) img->imageData + x * img->nChannels + (y * img->widthStep));
+	case IPL_DEPTH_16U:
+	case IPL_DEPTH_16S:
+		return (void *)((uintptr_t) img->imageData + x * 2 + (y * img->widthStep));
+	case IPL_DEPTH_32S:
+	case IPL_DEPTH_32F:
+		return (void *)((uintptr_t) img->imageData + x * 4 + (y * img->widthStep));
+	default: assert (0);
+	}
+
+	return NULL;	// Evitar Warning
+}
+
+// Calcula limits en X, Y segons el ROI d'una imatge
+void crvGetROILimits (const IplImage *img, int &xIni, int &yIni, int &xLim, int &yLim)
+{
+	if (img->roi== NULL) {
+		// No s'ha indicat regi� d'inter�s -> tota la imatge
+		xIni= 0; yIni= 0; xLim= img->width; yLim= img->height;
+	}
+	else {
+		// S'ha indicat regi� d'inter�s
+		xIni= img->roi->xOffset;
+		yIni= img->roi->yOffset;
+		xLim= xIni + img->roi->width;
+		yLim= yIni + img->roi->height;
+
+		// Trunca dins els l�mits reals de la imatge
+		if (xIni< 0) xIni= 0;
+		if (yIni< 0) yIni= 0;
+		if (xLim> img->width) xLim= img->width;
+		if (yLim> img->height) yLim= img->height;
+
+		//assert (xLim<= img->width && yLim<= img->height);
+	}
+}
+
+// Dona la intersecci� entre les ROI de 2 imatges
+void crvGetROIIntersectionLimits (IplImage *img1, IplImage *img2,
+								  int &xIni1, int &yIni1, int &xLim1, int &yLim1,
+								  int &xIni2, int &yIni2, int &xLim2, int &yLim2)
+{
+	int width, height;
+
+	if (img1->roi== NULL) {
+		xIni1= 0;
+		yIni1= 0;
+		width= img1->width;
+		height= img1->height;
+	}
+	else {
+		xIni1= img1->roi->xOffset;
+		yIni1= img1->roi->yOffset;
+		width= img1->roi->width;
+		height= img1->roi->height;
+	}
+
+	if (img2->roi== NULL) {
+		xIni2= 0;
+		yIni2= 0;
+		width= (width< img2->width ? width : img2->width);
+		height= (height< img2->height ? height : img2->height);
+	}
+	else {
+		xIni2= img2->roi->xOffset;
+		yIni2= img2->roi->yOffset;
+		width= (width< img2->roi->width ? width : img2->roi->width);
+		height= (height< img2->roi->height ? height : img2->roi->height);
+	}
+
+	// Limits
+	xLim1= xIni1 + width;
+	yLim1= yIni1 + height;
+	
+	xLim2= xIni2 + width;
+	yLim2= yIni2 + height;
+}
+
+
+
+// Pinta en ASCII una imatge binaria
+/*
+void crvAsciiPaint (IplImage *img, unsigned short thres)
+{
+	int x, y;
+	unsigned short pix;
+
+	for (y= 0; y< img->height; y++) {
+		for (x= 0; x< img->width; x++) {
+			pix= 0;
+			iplGetPixel (img, x, y, &pix);
+			printf ("%c", (pix< thres ? '.' : '#'));
+		}
+		printf ("\n");
+	}
+}*/
+
+// Copia una ROI d'una imatge sobre una nova imatge aplicant
+// l'escalat que s'indica per par�metre. La ROI de la imatge
+// dest� ha de ser suficientment gran com per encabir
+// la ROI origen un cop escalada.
+/*
+void crvCopyScaleImage (IplImage *src, IplImage *dst, float scale)
+{
+	int xDst, xSrc, yDst, ySrc;
+
+	assert (src && dst && scale> 0.0f); 
+	//assert (src->roi!= NULL && dst->roi!= NULL);
+
+	// Redimensiona imatge
+	if (scale== 1.0) {
+		xSrc= ySrc= xDst= yDst= 1;
+	}
+	else {
+		xSrc= 10000;
+		ySrc= xSrc;
+		xDst= (int) ((float) xSrc * scale);
+		yDst= xDst;
+	}
+	
+	iplResize(src, dst, xDst, xSrc, yDst, ySrc, IPL_INTER_CUBIC);
+}*/
+
+
+
+// Semi-binaritza una imatge de manera que per sobre o per sota
+// del llindar indicat no es modifiquen els valors dels p�xels
+/*
+void crvSemiBinarize (IplImage *img, unsigned char thres, unsigned char fillVal, bool fillLower)
+{
+	int xIni, yIni, xLim, yLim, x, y;
+	unsigned char *pBuff, min= 255;
+
+	assert (img->depth== IPL_DEPTH_8U);
+
+	crvGetROILimits (img, xIni, yIni, xLim, yLim);
+
+	if (fillLower) {
+		for (y= yIni; y< yLim; y++) {
+			pBuff= (unsigned char *) crvImgByteOffset (img, xIni, y);
+			for (x= xIni; x< xLim; x++) {
+				if (*pBuff< thres) *pBuff= fillVal;
+				pBuff++;
+			}
+		}
+	}
+	else {
+		for (y= yIni; y< yLim; y++) {
+			pBuff= (unsigned char *) crvImgByteOffset (img, xIni, y);
+			for (x= xIni; x< xLim; x++) {
+				if (*pBuff>= thres) *pBuff= fillVal;
+				//else *pBuff= MapRange (0, thres, 0, 40, *pBuff);
+				//if (*pBuff< 255 && *pBuff> 35) *pBuff= 35;
+				pBuff++;
+			}
+		}
+	}
+}
+*/
+
+// Calcula la diferencia de 2 imatges en valor absolut
+void crvAbsSubstract (IplImage *srcA, IplImage *srcB, IplImage *dst)
+{
+	int x, y, xIni, yIni, xLim, yLim;
+	unsigned char *pBuffA, *pBuffB, *pBuffRes;
+	
+	assert (srcA->depth== IPL_DEPTH_8U && 
+			srcB->depth== IPL_DEPTH_8U &&
+			dst->depth== IPL_DEPTH_8U);
+	assert (srcA->width== srcB->width &&
+			srcA->width== dst->width &&
+			srcA->height== srcB->height &&
+			srcA->height== dst->height);
+	assert (!srcA->roi && !srcB->roi && !dst->roi);
+
+	pBuffA= (unsigned char *) srcA->imageData;
+	pBuffB= (unsigned char *) srcB->imageData;
+	pBuffRes= (unsigned char *) dst->imageData;
+
+	crvGetROILimits (srcA, xIni, yIni, xLim, yLim);
+
+	for (y= yIni; y< yLim; y++) {
+		pBuffA= (unsigned char *) crvImgByteOffset (srcA, xIni, y);
+		pBuffB= (unsigned char *) crvImgByteOffset (srcB, xIni, y);
+		pBuffRes= (unsigned char *) crvImgByteOffset (dst, xIni, y);
+		for (x= xIni; x< xLim; x++) {
+			*pBuffRes = (unsigned char) abs ((int) *pBuffA - (int) *pBuffB);
+			pBuffA++;
+			pBuffB++;
+			pBuffRes++;
+		}
+	}
+}
+
+void crvConvert16BinToRGBA (IplImage *pSrcImg, IplImage *pDstImg)
+{
+	int i;	
+	unsigned short *pWordSrc;
+	unsigned char *pByteDst;
+
+	assert (pSrcImg && pDstImg);
+
+	pWordSrc= (unsigned short *) pSrcImg->imageData;
+	pByteDst= (unsigned char *) pDstImg->imageData;
+	int bytesPerPixel= pDstImg->depth / 8;
+
+	if (bytesPerPixel== 4)
+	{
+		for (i= 0; i< pDstImg->imageSize; i+= 4) {
+			if (*pWordSrc) {
+				*pByteDst++= 255;
+				*pByteDst++= 255;
+				*pByteDst++= 255;
+				pByteDst++;
+			}
+			else {
+				*pByteDst++= 0;
+				*pByteDst++= 0;
+				*pByteDst++= 0;
+				pByteDst++;
+			}
+			pWordSrc++;	
+		}
+	}
+	else
+	{
+		for (i= 0; i< pDstImg->imageSize; i+= 3) {
+			if (*pWordSrc) {
+				*pByteDst++= 255;
+				*pByteDst++= 255;
+				*pByteDst++= 255;				
+			}
+			else {
+				*pByteDst++= 0;
+				*pByteDst++= 0;
+				*pByteDst++= 0;				
+			}
+			pWordSrc++;	
+		}
+	}
+}
+
+// Ajusta un rectangle per que quedi dins uns limits establerts
+// Retorna true si s'ha modificat el rectangle
+// mode:
+bool crvFitRect (CvRect *rect, int width, int height)
+{
+	bool modif= false;
+
+	assert (rect->x<= width);
+	assert (rect->y<= height);
+
+	if (rect->x < 0) {
+		rect->width+= rect->x;
+		rect->x= 0;
+		assert (rect->width> 0);
+		modif= true;
+	}
+
+	if (rect->x + rect->width> width) {
+		rect->width= width - rect->x;
+		modif= true;
+	}
+
+	if (rect->y < 0) {
+		rect->height+= rect->y;
+		rect->y= 0;
+		assert (rect->height> 0);
+		modif= true;
+	}
+
+	if (rect->y + rect->height> height) {
+		rect->height= height - rect->y;
+		modif= true;
+	}
+
+	assert ((rect->x + width)>= rect->width);
+	assert ((rect->y + height)>= rect->height);
+
+	return (modif);
+}
+
+bool crvFitROI (IplImage *img, IplROI *roi)
+{
+	CvRect rect;
+	bool retval;
+
+	rect.x= roi->xOffset;
+	rect.y= roi->yOffset;
+	rect.width= roi->width;
+	rect.height= roi->height;
+
+	retval= crvFitRect (&rect, img->width, img->height);
+
+	roi->xOffset= rect.x;
+	roi->yOffset= rect.y;
+	roi->width= rect.width;
+	roi->height= rect.height;
+
+	return retval;
+}
+
+
+
+// Converteix una imatge 
+void crvConvert32FPToGray (IplImage *pSrcImg, IplImage *pDstImg,
+						   float min, float max)
+{
+	float *pOrig, factor;
+	unsigned char *pDst;
+	int x, y, xIni, yIni, xLim, yLim;
+	
+	assert (pSrcImg->depth== IPL_DEPTH_32F);
+	assert (pDstImg->depth== IPL_DEPTH_8U);
+	assert (pSrcImg->width== pDstImg->width &&
+			pSrcImg->height== pDstImg->height);
+
+	factor= 255.0f / (float)(max - min);
+
+	crvGetROILimits (pSrcImg, xIni, yIni, xLim, yLim);
+
+	for (y= yIni; y< yLim; y++) {
+		pOrig= (float *) crvImgOffset (pSrcImg, xIni, y);
+		pDst= (unsigned char *) crvImgOffset (pDstImg, xIni, y);
+		for (x= xIni; x< xLim; x++) {
+			*pDst= (unsigned char) ((*pOrig - min) * factor);
+			pOrig++; pDst++;
+		}
+	}
+}
+
+void crvThresholdFP (IplImage *pSrcImg, IplImage *pDstImg, 
+					 float threshold, float zero)
+{
+	int y, x, xIni, yIni, xLim, yLim;
+	float *pSrc, *pDst;
+
+	assert (pSrcImg && pDstImg);
+	assert (pSrcImg->depth== IPL_DEPTH_32F && 
+			pDstImg->depth== IPL_DEPTH_32F);
+	assert (pSrcImg->width== pDstImg->width &&
+			pSrcImg->height== pDstImg->height);
+
+	crvGetROILimits (pSrcImg, xIni, yIni, xLim, yLim);
+
+	for (y= yIni; y< yLim; y++) {
+		pSrc= (float *) crvImgOffset (pSrcImg, xIni, y);
+		pDst= (float *) crvImgOffset (pDstImg, xIni, y);
+		for (x= xIni; x< xLim; x++) {
+			if (*pSrc>= threshold) { *pDst= *pSrc; }
+			else { *pDst= zero; }
+			pSrc++; pDst++;
+		}
+	}
+}
+
+// Calcula el m�dul del gradient d'una imatge
+// Veure: iplConvolve2D
+/*
+void crvGradientModulus (IplImage *pSrcImg, IplImage *pDstImg)
+{
+
+	cvSobel (pSrcImg, pDstImg, 1, 1);
+
+	
+	int nShiftR;
+	IplConvKernel *kernels[2];
+
+	kernels[0]= iplCreateConvKernel(3, 3, 1, 1, 
+								{ -1, 0, 1, -2, 0, 2, -1, 0, 1 }, 
+								&nShiftR);
+	assert (kernels[0]);
+	kernels[1]= iplCreateConvKernel(3, 3, 1, 1, 
+								{ 1, 2, 1, 0, 0, 0, -1, -2, -1 }, 
+								&nShiftR);
+	assert (kernels[1]);
+
+	iplConvolve2D(pSrcImage, pDstImage, &kernels, 2, IPL_SUMSQROOT);
+
+	DeleteConvKernel (kernels[0]);
+	DeleteConvKernel (kernels[1]);
+	
+}
+*/
+
+/*
+void crvGradientModulus (IplImage *pSrcImg, IplImage *pDstImg, 
+						 IplImage *pTmpImg1, int *maxX, int *maxY)
+{
+	int retval;
+	unsigned char *pVVal, *pHVal, *pDst, max= 0;
+	int x, y, xIni, yIni, xLim, yLim;
+
+	retval= iplFixedFilter (pSrcImg, pDstImg, IPL_SOBEL_3x3_V);
+	assert (retval== 0);
+	retval= iplFixedFilter (pSrcImg, pTmpImg1, IPL_SOBEL_3x3_H);
+	assert (retval== 0);
+
+
+	crvGetROILimits (pSrcImg, xIni, yIni, xLim, yLim);
+
+	*maxX= 0;
+	*maxY= 0;
+
+
+	for (y= yIni; y< yLim; y++) {
+		pVVal= (unsigned char *) crvImgOffset (pDstImg, xIni, y);
+		pHVal= (unsigned char *) crvImgOffset (pTmpImg1, xIni, y);
+		pDst= (unsigned char *) crvImgOffset (pDstImg, xIni, y);
+
+		for (x= xIni; x< xLim; x++) {
+			*pDst= (unsigned char) (((int) *pVVal + (int) *pHVal) / 2);
+			
+			if (*pDst> max) {
+				max= *pDst;
+				*maxX= x;
+				*maxY= y;
+			}
+			//val= ((int) *pVVal) * ((int) *pVVal) + ((int) *pHVal) * ((int) *pHVal);
+			//val= (int) (sqrt (val) / 362.1f);
+			// *pDst= val;
+
+			pVVal++;
+			pHVal++;
+			pDst++;
+		}
+	}
+}
+*/
+
diff --git a/src/creavision/crvmisc.h b/src/creavision/crvmisc.h
new file mode 100755
index 0000000..f3f93a4
--- /dev/null
+++ b/src/creavision/crvmisc.h
@@ -0,0 +1,124 @@
+/////////////////////////////////////////////////////////////////////////////
+// Name:        crvmisc.h
+// Purpose:  
+// Author:      Cesar Mauri Loba (cesar at crea-si dot com)
+// Modified by: 
+// Created:     23/05/2008
+// Copyright:   (C) 2008 Cesar Mauri Loba - CREA Software Systems
+// 
+//  This program is free software: you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation, either version 3 of the License, or
+//  (at your option) any later version.
+//
+//  This program is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+/////////////////////////////////////////////////////////////////////////////
+#ifndef CRVMISC_H
+#define CRVMISC_H
+
+#include <cv.h>
+
+/*
+typedef struct {
+	double x, y;
+} RPoint;
+*/
+
+// Dona l'adre�a de mem�ria del p�xel a la posici� X, Y
+void *crvImgOffset (const IplImage *img, int x, int y);
+
+// Dona l'adre�a de mem�ria del p�xel a la posici� X, Y (DEPRECAT)
+char *crvImgByteOffset (const IplImage *img, int x, int y);
+
+// Calcula limits en X, Y segons el ROI d'una imatge
+void crvGetROILimits (const IplImage *img, int &xIni, int &yIni, 
+				   int &xLim, int &yLim);
+
+// Dona la intersecci� entre les ROI de 2 imatges
+void crvGetROIIntersectionLimits (IplImage* img1, IplImage* img2,
+								  int &xIni1, int &yIni1, int &xLim1, int &yLim1,
+								  int &xIni2, int &yIni2, int &xLim2, int &yLim2);
+
+
+// Ajusta un rectangle per que quedi dins uns limits establerts
+// Retorna true si s'ha modificat el rectangle
+bool crvFitRect (CvRect *rect, int width, int height);
+bool crvFitROI (IplImage *img, IplROI *roi);
+
+// Pinta en ASCII una imatge binaria
+//void IplAsciiPaint (IplImage *img, unsigned short thres);
+
+// Copia una ROI d'una imatge sobre una nova imatge aplicant
+// l'escalat que s'indica per par�metre. La ROI de la imatge
+// dest� ha de ser suficientment gran com per encabir
+// la ROI origen un cop escalada.
+//void IplCopyScaleImage (IplImage *src, IplImage *dst, float scale);
+
+// Semi-binaritza una imatge de manera que per sobre o per sota
+// del llindar indicat no es modifiquen els valors dels p�xels
+//void crvSemiBinarize (IplImage *img, unsigned char thres, unsigned char fillVal, bool fillLower);
+
+// Calcula la diferencia de 2 imatges en valor absolut
+void crvAbsSubstract (IplImage *srcA, IplImage *srcB, IplImage *dst);
+
+void crvConvert16BinToRGBA (IplImage *pSrcImg, IplImage *pDstImg);
+
+static inline
+void crvInvalidateCvPoint (CvPoint *p) 
+{
+	p->x= -1;
+}
+
+static inline 
+int crvCvPointIsValid (CvPoint *p)
+{
+	return (p->x> -1);
+}
+
+static inline
+void crvInvalidateCvPoint2D32f (CvPoint2D32f *p) 
+{
+	p->x= 999999999.0f;
+}
+
+static inline 
+int crvCvPoint2D32fIsValid (CvPoint2D32f *p)
+{
+	return (p->x<= 999999998.0f);
+}
+
+static inline
+void crvInvalidateCvRect (CvRect *p) 
+{
+	p->x= -1;
+}
+
+static inline 
+int crvCvRectIsValid (CvRect *p)
+{
+	return (p->x> -1);
+}
+
+
+
+void crvConvert32FPToGray (IplImage *pSrcImg, IplImage *pDstImg,
+						   float min, float max);
+
+void crvThresholdFP (IplImage *pSrcImg, IplImage *pDstImg, 
+					 float threshold, float zero= 0.0f);
+
+
+//void IplGradientModulus (IplImage *pSrcImg, IplImage *pDstImg);
+
+//void IplGradientModulus (IplImage *pSrcImg, IplImage *pDstImg, 
+//						 IplImage *pTmpImg1, int *maxX, int *maxY);
+
+
+
+#endif
diff --git a/src/creavision/crvnormroi.cpp b/src/creavision/crvnormroi.cpp
new file mode 100755
index 0000000..377bb73
--- /dev/null
+++ b/src/creavision/crvnormroi.cpp
@@ -0,0 +1,556 @@
+/////////////////////////////////////////////////////////////////////////////
+// Name:        crvnormroi.cpp
+// Purpose:  Stores normalized ROI coordinates. Image resize is supported.
+// Author:      Cesar Mauri Loba (cesar at crea-si dot com)
+// Modified by: 
+// Created:     30/05/2008
+// Copyright:   (C) 2008-11 Cesar Mauri Loba - CREA Software Systems
+// 
+//  This program is free software: you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation, either version 3 of the License, or
+//  (at your option) any later version.
+//
+//  This program is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+/////////////////////////////////////////////////////////////////////////////
+#include "crvnormroi.h"
+
+// Area limits
+#define MIN_WIDTH_HEIGHT	(float) 0.041666666666666666666666666666667		// 6 p�xels over 144
+#define MAX_WIDTH_HEIGHT	1.0f
+
+CNormROI::CNormROI(void)
+{
+	m_x= 0.0;
+	m_y= 0.0;
+	m_width= MIN_WIDTH_HEIGHT;
+	m_height= MIN_WIDTH_HEIGHT;	
+	m_rotation= 0.0;
+	m_pParentROI= NULL;
+	SetCenter (0.5f, 0.5f);
+}
+
+CNormROI::CNormROI(float width, float height, float x, float y)
+{
+	m_x= 0.0;
+	m_y= 0.0;
+	m_width= MIN_WIDTH_HEIGHT;
+	m_height= MIN_WIDTH_HEIGHT;	
+	m_rotation= 0.0;
+	m_pParentROI= NULL;
+
+	SetSize (width, height);
+	if (x!= -1.0f && y!= -1.0f)	SetCenter (x, y);
+	else SetCenter (0.5f, 0.5f);
+}
+
+void CNormROI::Destroy()
+{
+	// Detach itself from parent
+	if (m_pParentROI) {
+		bool check= m_pParentROI->UnregisterChildROI (this);
+		((void)check);	// Remove warning
+		assert (check);
+		assert (m_pParentROI== NULL);
+	}
+
+	TNormROIListIterator i;
+
+	i= m_childROIs.begin();
+
+	while (i!= m_childROIs.end())
+	{
+		delete (*i);
+		//i= m_childROIs.erase (i);
+		i= m_childROIs.begin();
+	}
+	
+	assert (m_childROIs.empty());
+}
+
+// delete registered childs
+CNormROI::~CNormROI(void)
+{
+	Destroy();
+}
+
+//
+// Working with native coordinates
+//
+
+void CNormROI::CheckInvariant() {
+	assert (m_x>= 0.0f && m_x< MAX_WIDTH_HEIGHT);
+	assert (m_y>= 0.0f && m_y< MAX_WIDTH_HEIGHT);
+	assert (m_width>= MIN_WIDTH_HEIGHT && m_width<= MAX_WIDTH_HEIGHT);
+	assert (m_height>= MIN_WIDTH_HEIGHT && m_height<= MAX_WIDTH_HEIGHT);
+	assert (m_x + m_width<= MAX_WIDTH_HEIGHT);
+	assert (m_y + m_height<= MAX_WIDTH_HEIGHT);
+}
+
+// Trick to see a float as int. Only for little-endian machines.
+// TODO: seriously, change the internal implementation of this class!
+typedef union {
+	float f;
+	int i32;
+} FloatInt32;
+
+#define COMPILE_TIME_ASSERT(pred) switch(0){case 0:case pred:;}
+
+void CNormROI::FitInternalState() {
+	// Fix internal state to make sure class invariant is honoured.
+	// Invariant may have been violated by imprecisions on FP calculations
+	// TODO: replace FP arithmetic with integer arithmetic.
+	COMPILE_TIME_ASSERT(sizeof(FloatInt32)== sizeof(float));
+	COMPILE_TIME_ASSERT(sizeof(FloatInt32)== sizeof(int));
+
+	if (m_width< MIN_WIDTH_HEIGHT) m_width= MIN_WIDTH_HEIGHT;
+	if (m_x + m_width> MAX_WIDTH_HEIGHT) {
+		FloatInt32 f2i;
+		if (m_width> MIN_WIDTH_HEIGHT) {
+			f2i.f= m_width;
+			f2i.i32--;
+			m_width= f2i.f;
+		}
+		else {
+			f2i.f= m_x;
+			f2i.i32--;
+			m_x= f2i.f;
+		}
+	}
+
+	if (m_height< MIN_WIDTH_HEIGHT) m_height= MIN_WIDTH_HEIGHT;
+	if (m_y + m_height> MAX_WIDTH_HEIGHT) {
+		FloatInt32 f2i;
+		if (m_height> MIN_WIDTH_HEIGHT) {
+			f2i.f= m_height;
+			f2i.i32--;
+			m_height= f2i.f;
+		}
+		else {
+			f2i.f= m_y;
+			f2i.i32--;
+			m_y= f2i.f;
+		}
+	}
+}
+
+// Find minimum child's P1 coordinates
+void CNormROI::FindMinChildP1 (float& x, float& y)
+{
+	TNormROIListIterator i;
+
+	for(i= m_childROIs.begin(); i != m_childROIs.end(); ++i)
+	{
+		(*i)->FindMinChildP1Rec (x, y);
+	}
+}
+
+void CNormROI::FindMinChildP1Rec (float& x, float& y)
+{
+	TNormROIListIterator i;
+
+	for(i= m_childROIs.begin(); i != m_childROIs.end(); ++i)
+	{
+		(*i)->FindMinChildP1Rec (x, y);
+	}
+
+	if (x> m_x) x= m_x;
+	if (y> m_y) y= m_y;
+}
+
+// Find miaximum child's P2 coordinates
+void CNormROI::FindMaxChildP2 (float& x, float& y)
+{
+	TNormROIListIterator i;
+
+	for(i= m_childROIs.begin(); i != m_childROIs.end(); ++i)
+	{
+		(*i)->FindMaxChildP2Rec (x, y);
+	}
+}
+
+void CNormROI::FindMaxChildP2Rec (float& x, float& y)
+{
+	TNormROIListIterator i;
+
+	for(i= m_childROIs.begin(); i != m_childROIs.end(); ++i)
+	{
+		(*i)->FindMaxChildP2Rec (x, y);
+	}
+
+	if (x< m_x + m_width) x= m_x + m_width;
+	if (y< m_y + m_height) y= m_y + m_height;
+}
+
+void CNormROI::SetP1Resize (const float x, const float y)
+{
+	float min_p1x, min_p1y, max_p1x, max_p1y;
+
+	CvPoint2D32f p2_lim;
+
+	p2_lim.x= m_x + m_width;
+	p2_lim.y= m_y + m_height;
+
+	if (m_pParentROI)
+	{
+		min_p1x= m_pParentROI->m_x;
+		min_p1y= m_pParentROI->m_y;
+	}
+	else
+	{
+		 min_p1x= min_p1y= 0.0f;
+	}
+	max_p1x= p2_lim.x - MIN_WIDTH_HEIGHT;
+	max_p1y= p2_lim.y - MIN_WIDTH_HEIGHT;
+	FindMinChildP1 (max_p1x, max_p1y);
+	assert (max_p1x>= 0.0f);
+	assert (max_p1y>= 0.0f);
+
+	if (x< min_p1x) m_x= min_p1x;
+	else if (x> max_p1x) m_x= max_p1x;
+	else m_x= x;
+
+	if (y< min_p1y) m_y= min_p1y;
+	else if (y> max_p1y) m_y= max_p1y;
+	else m_y= y;
+
+	m_width= p2_lim.x - m_x;
+	m_height= p2_lim.y - m_y;
+
+	FitInternalState();
+
+	CheckInvariant();
+}	
+		
+void CNormROI::SetP1Move (const float x, const float y)
+{
+	float min_p1x, min_p1y, max_p1x, max_p1y;
+	float min_p2x_lim, min_p2y_lim;
+
+	// Compute minimum valid p1 coordinates
+	if (m_pParentROI)
+	{
+		min_p1x= m_pParentROI->m_x;
+		min_p1y= m_pParentROI->m_y;
+	}
+	else
+	{
+		 min_p1x= min_p1y= 0.0f;
+	}
+	min_p2x_lim= min_p1x + m_width;
+	min_p2y_lim= min_p1y + m_height;
+	FindMaxChildP2 (min_p2x_lim, min_p2y_lim);
+		
+	min_p1x= min_p2x_lim - m_width;
+	min_p1y= min_p2y_lim - m_height;
+	if (min_p1x< 0.0f) min_p1x= 0.0f;
+	if (min_p1y< 0.0f) min_p1y= 0.0f;
+
+	// Compute maximum valid p1 coordinates
+	if (m_pParentROI)
+	{
+		max_p1x= m_pParentROI->m_x + m_pParentROI->m_width - m_width;
+		max_p1y= m_pParentROI->m_y + m_pParentROI->m_height - m_height;
+	}
+	else
+	{
+		max_p1x= MAX_WIDTH_HEIGHT - m_width;
+		max_p1y= MAX_WIDTH_HEIGHT - m_height;
+	}
+	FindMinChildP1 (max_p1x, max_p1y);
+	assert (max_p1x>= 0.0f);
+	assert (max_p1y>= 0.0f);
+
+	// Apply restrictions
+	if (x< min_p1x) m_x= min_p1x;
+	else if (x> max_p1x) m_x= max_p1x;
+	else m_x= x;
+
+	if (y< min_p1y) m_y= min_p1y;
+	else if (y> max_p1y) m_y= max_p1y;
+	else m_y= y;
+
+	FitInternalState();
+
+	CheckInvariant();
+}
+
+void CNormROI::SetP2Resize (const float x, const float y)
+{
+	// Setting P2 always resize
+	float min_p2x, min_p2y, max_p2x, max_p2y;
+
+	min_p2x= m_x + MIN_WIDTH_HEIGHT;
+	min_p2y= m_y + MIN_WIDTH_HEIGHT;
+	assert (min_p2x<= MAX_WIDTH_HEIGHT);
+	assert (min_p2y<= MAX_WIDTH_HEIGHT);
+	FindMaxChildP2 (min_p2x, min_p2y);
+
+	if (m_pParentROI)
+	{
+		max_p2x= m_pParentROI->m_x + m_pParentROI->m_width;
+		max_p2y= m_pParentROI->m_y + m_pParentROI->m_height;
+	}
+	else
+	{
+		max_p2x= max_p2y= MAX_WIDTH_HEIGHT;
+	}
+
+	if (x< min_p2x) m_width= min_p2x - m_x;
+	else if (x> max_p2x) m_width= max_p2x - m_x;
+	else m_width= x - m_x;
+
+	if (y< min_p2y) m_height= min_p2y - m_y;
+	else if (y> max_p2y) m_height= max_p2y - m_y;
+	else m_height= y - m_y;
+
+	FitInternalState();
+
+	CheckInvariant();
+}
+
+void CNormROI::SetCenter (const float x, const float y)
+{
+	SetP1Move (x - (m_width / 2.0f), y - (m_height / 2.0f));
+}
+
+void CNormROI::GetCenter (float& x, float& y)
+{
+	x= m_x + (m_width / 2.0f);
+	y= m_y + (m_height / 2.0f);
+}
+
+void CNormROI::SetSize (const float width, const float height)
+{
+	SetP2Resize (width + m_x, height + m_y);
+}
+
+void CNormROI::GetSize (float& width, float& height)
+{
+	width= m_width;
+	height= m_height;
+}
+
+//
+// Working with generic integer coordinates
+//
+inline void CNormROI::Integer2Normalized (const CvSize& size, const int ix, const int iy, float &nx, float &ny)
+{
+	assert (size.width> 0);
+	assert (size.height> 0);
+	
+	nx= (float) ix / (float) size.width;
+	ny= (float) iy / (float) size.height;
+}
+
+inline void CNormROI::Normalized2Integer (const CvSize& size, const float nx, const float ny, int &ix, int &iy)
+{
+	assert (size.width> 0);
+	assert (size.height> 0);
+
+	// Round using the float value just below 0.5. We do this way to avoid
+	// overflows when both coordinate and size finish with 0.5
+	ix= (int) (nx * (float) size.width + 0.4999999701976776f);
+	iy= (int) (ny * (float) size.height + 0.4999999701976776f);
+}
+
+//inline 
+void CNormROI::SetP1ResizeInteger (const CvSize& size, const int x, const int y)
+{
+	float new_x, new_y;
+
+	Integer2Normalized (size, x, y, new_x, new_y);
+
+	SetP1Resize (new_x, new_y);
+}
+
+//inline 
+void CNormROI::SetP1MoveInteger (const CvSize& size, const int x, const int y)
+{
+	float new_x, new_y;
+
+	Integer2Normalized (size, x, y, new_x, new_y);
+
+	SetP1Move (new_x, new_y);
+}
+
+//inline 
+void CNormROI::SetP2ResizeInteger (const CvSize& size, const int x, const int y)
+{
+	float new_x, new_y;
+
+	Integer2Normalized (size, x, y, new_x, new_y);
+
+	SetP2Resize (new_x, new_y);
+}
+
+//inline 
+void CNormROI::SetCenterInteger (const CvSize& size, const int x, const int y)
+{
+	float new_x, new_y;
+
+	Integer2Normalized (size, x, y, new_x, new_y);
+
+	SetCenter (new_x, new_y);
+}
+
+void CNormROI::GetCenterInteger (const CvSize& size, int& x, int& y)
+{
+	float fx, fy;
+
+	GetCenter (fx, fy);
+
+	Normalized2Integer (size, fx, fy, x, y);	
+}
+
+//inline 
+void CNormROI::SetSizeInteger (const CvSize& size, const int width, const int height)
+{
+	float new_width, new_height;
+
+	Integer2Normalized (size, width, height, new_width, new_height);
+
+	SetSize (new_width, new_height);
+}
+
+//inline 
+void CNormROI::GetBoxInteger (const CvSize& size, int& x, int& y, int& width, int& height)
+{
+	// DEBUG, 
+	CheckInvariant();
+
+	Normalized2Integer (size, m_x, m_y, x, y);
+	Normalized2Integer (size, m_width, m_height, width, height);
+
+	assert (x + width<= size.width);
+	assert (y + height<= size.height);
+}
+
+void CNormROI::GetBoxInteger (const CvSize& size, CvRect& box)
+{
+	GetBoxInteger (size, box.x, box.y, box.width, box.height);
+}
+
+void CNormROI::GetP1P2Integer (const CvSize& size, CvPoint& p1, CvPoint& p2)
+{
+	Normalized2Integer (size, m_x, m_y, p1.x, p1.y);
+	Normalized2Integer (size, m_x + m_width, m_y + m_height, p2.x, p2.y);
+}
+
+//
+// Facilities to work with CIplImage images
+//
+void CNormROI::SetP1ResizeImg (const CIplImage *pImg, const int x, const int y)
+{
+	assert (pImg);
+	assert (pImg->Origin()== IPL_ORIGIN_TL);
+
+	SetP1ResizeInteger (pImg->GetSize(), x, y);
+}
+
+void CNormROI::SetP1MoveImg (const CIplImage *pImg, const int x, const int y)
+{
+	assert (pImg);
+	assert (pImg->Origin()== IPL_ORIGIN_TL);
+
+	SetP1MoveInteger (pImg->GetSize(), x, y);
+}
+
+void CNormROI::SetP2ResizeImg (const CIplImage *pImg, const int x, const int y)
+{
+	assert (pImg);
+	assert (pImg->Origin()== IPL_ORIGIN_TL);
+
+	SetP2ResizeInteger (pImg->GetSize(), x, y);	
+}
+
+void CNormROI::SetCenterImg (const CIplImage *pImg, const int x, const int y)
+{
+	assert (pImg);
+	assert (pImg->Origin()== IPL_ORIGIN_TL);
+	
+	SetCenterInteger (pImg->GetSize(), x, y);
+}
+
+void CNormROI::GetCenterImg (const CIplImage *pImg, int& x, int& y)
+{
+	assert (pImg);
+	assert (pImg->Origin()== IPL_ORIGIN_TL);
+
+	GetCenterInteger (pImg->GetSize(), x, y);	
+}
+
+void CNormROI::SetSizeImg (const CIplImage *pImg, const int width, const int height)
+{
+	assert (pImg);
+	assert (pImg->Origin()== IPL_ORIGIN_TL);
+
+	SetSizeInteger (pImg->GetSize(), width, height);
+}
+
+void CNormROI::GetBoxImg (const CIplImage *pImg, int& x, int& y, int& width, int& height)
+{
+	assert (pImg);
+	assert (pImg->Origin()== IPL_ORIGIN_TL);
+
+	GetBoxInteger (pImg->GetSize(), x, y, width, height);
+}
+
+void CNormROI::GetBoxImg (const CIplImage *pImg, CvRect& box)
+{
+	GetBoxImg (pImg, box.x, box.y, box.width, box.height);
+}
+
+//
+// Registration service
+//
+bool CNormROI::RegisterChildROI (CNormROI* pNormROI)
+{
+	assert (pNormROI);
+	assert (pNormROI!= this);
+		
+	TNormROIListIterator i;
+
+	for(i= m_childROIs.begin(); i != m_childROIs.end(); ++i)
+	{
+		if ((*i)== pNormROI) return false;	// Already registered
+	}
+
+	// Check that no registered with other parent
+	if (pNormROI->m_pParentROI) return false;
+
+	m_childROIs.push_back (pNormROI);
+	pNormROI->m_pParentROI= this;
+
+	// Ensures that child is inside parent
+	if (pNormROI->m_width> m_width) pNormROI->m_width= m_width;
+	if (pNormROI->m_height> m_height) pNormROI->m_height= m_height;
+	pNormROI->SetP1Move (pNormROI->m_x, pNormROI->m_y);	
+
+	return true;
+}
+
+bool CNormROI::UnregisterChildROI (CNormROI* pNormROI)
+{
+	assert (pNormROI);
+
+	TNormROIListIterator i;
+
+	for(i= m_childROIs.begin(); i != m_childROIs.end(); ++i)
+	{
+		if ((*i)== pNormROI) break;	// Found!
+	}
+	if (i== m_childROIs.end()) return false;	// Not found
+	
+	assert ((*i)->m_pParentROI);
+	(*i)->m_pParentROI= NULL;
+	m_childROIs.erase (i);
+
+	return true;
+}
diff --git a/src/creavision/crvnormroi.h b/src/creavision/crvnormroi.h
new file mode 100755
index 0000000..388ebaf
--- /dev/null
+++ b/src/creavision/crvnormroi.h
@@ -0,0 +1,110 @@
+/////////////////////////////////////////////////////////////////////////////
+// Name:        crvnormroi.h
+// Purpose:  Stores normalized ROI coordinates. Image resize is supported.
+// Author:      Cesar Mauri Loba (cesar at crea-si dot com)
+// Modified by: 
+// Created:     30/05/2008
+// Copyright:   (C) 2008-11 Cesar Mauri Loba - CREA Software Systems
+// 
+//  This program is free software: you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation, either version 3 of the License, or
+//  (at your option) any later version.
+//
+//  This program is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+/////////////////////////////////////////////////////////////////////////////
+#ifndef CRV_NORMROI_H
+#define CRV_NORMROI_H
+
+#include "crvimage.h"
+#include <list>
+using namespace std;
+
+class CNormROI
+{
+public:
+	CNormROI(void);
+	CNormROI(float width, float height, float x= -1.0f, float y= -1.0f);
+	virtual ~CNormROI(void);
+
+	// Working with native coordinates
+	void SetP1Resize (const float x, const float y);
+	void SetP1Move (const float x, const float y);
+	void SetP2Resize (const float x, const float y);
+	void SetCenter (const float x, const float y);
+	void GetCenter (float& x, float& y);
+	void SetSize (const float width, const float height);
+	void GetSize (float& width, float& height);
+	
+	// Get/Set position using relative arbitrary integer coordinates
+	void SetP1ResizeInteger (const CvSize& size, const int x, const int y);
+	void SetP1MoveInteger (const CvSize& size, const int x, const int y);
+	void SetP2ResizeInteger (const CvSize& size, const int x, const int y);
+	void SetCenterInteger (const CvSize& size, const int x, const int y);
+	void GetCenterInteger (const CvSize& size, int& x, int& y);
+	void SetSizeInteger (const CvSize& size, const int width, const int height);
+	void GetBoxInteger (const CvSize& size, int& x, int& y, int& width, int& height);
+	void GetBoxInteger (const CvSize& size, CvRect& box);
+	void GetP1P2Integer (const CvSize& size, CvPoint& p1, CvPoint& p2);
+
+	float GetRotation () { return m_rotation; }
+	void SetRotation (float value) { m_rotation= value; }
+
+	// Get/Set position using real CIplImage coordinates.
+	// CIplImage object can change over time because
+	// there is no stored reference	
+	void SetP1ResizeImg (const CIplImage *pImg, const int x, const int y);
+	void SetP1MoveImg (const CIplImage *pImg, const int x, const int y);
+	void SetP2ResizeImg (const CIplImage *pImg, const int x, const int y);
+	void SetCenterImg (const CIplImage *pImg, const int x, const int y);
+	void GetCenterImg (const CIplImage *pImg, int& x, int& y);
+	void SetSizeImg (const CIplImage *pImg, const int width, const int height);
+	void GetBoxImg (const CIplImage *pImg, int& x, int& y, int& width, int& height);
+	void GetBoxImg (const CIplImage *pImg, CvRect& box);
+	
+	
+	// True if all ok, false if error
+	bool RegisterChildROI (CNormROI* pNormROI);
+	bool UnregisterChildROI (CNormROI* pNormROI);
+
+protected:
+    void FindMinChildP1 (float& x, float& y);
+	void FindMinChildP1Rec (float& x, float& y);
+	void FindMaxChildP2 (float& x, float& y);
+	void FindMaxChildP2Rec (float& x, float& y);
+
+	// Destruction
+	virtual void Destroy();
+
+	// Coordinate conversion
+	void Integer2Normalized (const CvSize& size, const int ix, const int iy, float &nx, float &ny);
+	void Normalized2Integer (const CvSize& size, const float nx, const float ny, int &ix, int &iy);
+
+	// ROI hierarchy
+	typedef std::list<CNormROI *> TNormROIList;
+	typedef TNormROIList::iterator TNormROIListIterator;
+	CNormROI* m_pParentROI;	
+	TNormROIList m_childROIs;
+
+private:
+	void CheckInvariant();
+	void FitInternalState();
+
+	// Normalized coordinates
+	//
+	// TODO: implement these using integer arithmethic only,
+	// for instance, using 32bit integers and a certain range 
+	// (say 0..32768) thus avoiding FP arithmethic ans its 
+	// inherent "unexpected" behaviour.
+	// 
+	float m_x, m_y, m_width, m_height;
+	float m_rotation;
+};
+
+#endif
diff --git a/src/creavision/crvskindetection.cpp b/src/creavision/crvskindetection.cpp
new file mode 100755
index 0000000..2784ea1
--- /dev/null
+++ b/src/creavision/crvskindetection.cpp
@@ -0,0 +1,174 @@
+/////////////////////////////////////////////////////////////////////////////
+// Name:        crvskindetection.cpp
+// Purpose:  
+// Author:      Cesar Mauri Loba (cesar at crea-si dot com)
+// Modified by: 
+// Created:     23/02/2008
+// Copyright:   (C) 2008 Cesar Mauri Loba - CREA Software Systems
+// 
+//  This program is free software: you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation, either version 3 of the License, or
+//  (at your option) any later version.
+//
+//  This program is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+/////////////////////////////////////////////////////////////////////////////
+#include "crvmisc.h"
+#include "crvskindetection.h"
+#include <assert.h>
+#include <string.h>
+
+void CSkinRegionModel::crvBinarizeSkin_KToyama (IplImage *pIpl, float &krg_min, 
+												  float &krg_max, float &krb_min, 
+												  float &krb_max)
+{
+	int x, y, xIni, yIni, xLim, yLim;
+	float krg, krb;
+	unsigned char *pSrc;
+
+	assert (pIpl);
+
+	crvGetROILimits (pIpl, xIni, yIni, xLim, yLim);
+	
+	for (y= yIni; y< yLim; y++) {
+		pSrc= (unsigned char *) crvImgOffset (pIpl, xIni, y);		
+		for (x= xIni; x< xLim; x++) {
+			krg= (float) pSrc[0] / (float) pSrc[1];
+			krb= (float) pSrc[0] / (float) pSrc[2];
+
+			if (krg_min<= krg && krg_max>= krg &&
+				krb_min<= krb && krb_max>= krb) {
+				pSrc[0]= pSrc[1]= pSrc[2]= 255;
+			}
+			else 
+				pSrc[0]= pSrc[1]= pSrc[2]= 0;
+
+			pSrc+= 4;
+		}
+	}
+}
+
+// 
+// Skin Models Definition
+//
+#define min(x,y) (x< y? x : y)
+#define max(x,y) (x> y? x : y)
+#define min3(x,y,z) (min(min(x,y),z))
+#define max3(x,y,z) (max(max(x,y),z))
+
+
+// The skin colour at uniform daylight illumination
+#define IS_SKIN_PEER(R,G,B)		(R> 95 && G> 40 && B> 20 && R> G && R> B && \
+								(max3(R,G,B) - min3(R,G,B))> 15	&& \
+								((R-G)> 15 || (G-R)> 15))
+
+// The skin colour under flashlight or (light) daylight
+// lateral illumination
+#define IS_SKIN_PEER2(R,G,B)	(R> 220 && G> 210 && B> 170 && \
+								((R-G)< 15 || (G-R)< 15) && \
+								R> B && G> B)
+								
+								
+
+inline bool IsSkin_GomezMorales_1 (int R, int G, int B)
+{
+	float r, g, b, rgb, rgb2;
+
+	r= (float) R / 255.0f;	g= (float) G / 255.0f;	b= (float) B / 255.0f;
+	rgb= r + g + b;
+	rgb2= rgb * rgb;
+
+	return ( ((r/g)> 1.185) && (((r*b)/rgb2)> 0.107) && (((r*g)/rgb2)> 0.112) );
+}
+
+inline bool IsSkin_GomezMorales_2 (int R, int G, int B)
+{
+	float r, g, b, rgb;
+
+	r= (float) R / 255.0f;	g= (float) G / 255.0f;	b= (float) B / 255.0f;
+	rgb= r + g + b;
+	
+	return ( (b/g)< 1.249 && (rgb / (3*r))> 0.696 && 
+			 ((1.0/3.0) - (b/rgb))> 0.014 && (g / (3*rgb))< 0.108 );
+}
+
+void CSkinRegionModel::crvBinarizeSkin  (IplImage *pSrc, IplImage *pDst)
+{
+	int x, y, xIni, yIni, xLim, yLim, srcBytesPPixel, dstBytesPPixel;
+	unsigned char *pSrcB, *pDstB;
+	bool isBGR= false;
+	
+	assert (pSrc && pSrc->imageData && pDst && pDst->imageData);
+	if (!strncmp (pSrc->channelSeq, "BGR", 4) || !strncmp (pSrc->channelSeq, "BGRA", 4))
+		isBGR= true;
+	else if (!strncmp (pSrc->channelSeq, "RGB", 4) || !strncmp (pSrc->channelSeq, "RGBA", 4))
+		isBGR= false;
+	else
+		assert (false);
+	assert (!strncmp (pDst->channelSeq, "GRAY", 4) || !strncmp (pDst->channelSeq, "BGRA", 4));
+
+	// Get depth
+	srcBytesPPixel= pSrc->nChannels;
+	dstBytesPPixel= pDst->depth / 8;
+	
+	cvSetZero(pDst);
+	
+	crvGetROILimits (pSrc, xIni, yIni, xLim, yLim);
+
+	if (isBGR)
+		for (y= yIni; y< yLim; y++) {
+			pSrcB= (unsigned char *) crvImgOffset (pSrc, xIni, y);
+			pDstB= (unsigned char *) crvImgOffset (pDst, xIni, y);
+
+			for (x= xIni; x< xLim; x++) {
+
+				if (IS_SKIN_PEER(pSrcB[2],pSrcB[1],pSrcB[0]))			
+				{
+					// Color acceptat
+					pDstB[0]= 255;
+					if (dstBytesPPixel> 1)
+					{
+						pDstB[1]= 255;
+						if (dstBytesPPixel> 2)
+						{
+							pDstB[2]= 255;
+						}
+					}
+				}			
+
+				pSrcB+= srcBytesPPixel;
+				pDstB+= dstBytesPPixel;
+			}
+		}
+	else
+		for (y= yIni; y< yLim; y++) {
+			pSrcB= (unsigned char *) crvImgOffset (pSrc, xIni, y);
+			pDstB= (unsigned char *) crvImgOffset (pDst, xIni, y);
+
+			for (x= xIni; x< xLim; x++) {
+
+				if (IS_SKIN_PEER(pSrcB[0],pSrcB[1],pSrcB[2]))			
+				{
+					// Color acceptat
+					pDstB[0]= 255;
+					if (dstBytesPPixel> 1)
+					{
+						pDstB[1]= 255;
+						if (dstBytesPPixel> 2)
+						{
+							pDstB[2]= 255;
+						}
+					}
+				}			
+
+				pSrcB+= srcBytesPPixel;
+				pDstB+= dstBytesPPixel;
+			}
+		}
+}
diff --git a/src/creavision/crvskindetection.h b/src/creavision/crvskindetection.h
new file mode 100755
index 0000000..0a64b9c
--- /dev/null
+++ b/src/creavision/crvskindetection.h
@@ -0,0 +1,41 @@
+/////////////////////////////////////////////////////////////////////////////
+// Name:        crvskindetection.h
+// Purpose:  
+// Author:      Cesar Mauri Loba (cesar at crea-si dot com)
+// Modified by: 
+// Created:     23/02/2008
+// Copyright:   (C) 2008 Cesar Mauri Loba - CREA Software Systems
+// 
+//  This program is free software: you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation, either version 3 of the License, or
+//  (at your option) any later version.
+//
+//  This program is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+/////////////////////////////////////////////////////////////////////////////
+#ifndef CRVSKINDETECTION_H
+#define CRVSKINDETECTION_H
+
+#include <cv.h>
+
+class CSkinRegionModel
+{
+	
+public:
+	// Binaritza imatge a color segons model de color de la pell
+	static void crvBinarizeSkin_KToyama (IplImage *pIpl, float &krg_min, 
+									   float &krg_max, float &krb_min, 
+									   float &krb_max);
+
+	// Binaritza imatge a color segons model de color de la pel
+	//static void IplBinarizeSkin	(IplImage *pIpl);
+	static void crvBinarizeSkin  (IplImage *pSrc, IplImage *pDst);
+};
+
+#endif	
diff --git a/src/creavision/defs.h b/src/creavision/defs.h
new file mode 100755
index 0000000..85775b0
--- /dev/null
+++ b/src/creavision/defs.h
@@ -0,0 +1,139 @@
+/*******************************************************************************#
+#           guvcview              http://guvcview.berlios.de                    #
+#                                                                               #
+#           Paulo Assis <pj.assis at gmail.com>                                    #
+#                                                                               #
+# This program is free software; you can redistribute it and/or modify          #
+# it under the terms of the GNU General Public License as published by          #
+# the Free Software Foundation; either version 2 of the License, or             #
+# (at your option) any later version.                                           #
+#                                                                               #
+# This program is distributed in the hope that it will be useful,               #
+# but WITHOUT ANY WARRANTY; without even the implied warranty of                #
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the                 #
+# GNU General Public License for more details.                                  #
+#                                                                               #
+# You should have received a copy of the GNU General Public License             #
+# along with this program; if not, write to the Free Software                   #
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA     #
+#                                                                               #
+********************************************************************************/
+
+#ifndef DEFS_H
+#define DEFS_H
+#include <inttypes.h>
+#include <sys/types.h>
+
+#define CLEAR_LINE "\x1B[K"
+
+#ifdef WORDS_BIGENDIAN
+  #define BIGENDIAN 1
+#else
+  #define BIGENDIAN 0
+#endif
+
+#define IO_MMAP 1
+#define IO_READ 2
+
+#define ODD(x) ((x%2)?TRUE:FALSE)
+
+/*next index of ring buffer with size elements*/
+#define NEXT_IND(ind,size) ind++;if(ind>=size) ind=0
+/*previous index of ring buffer with size elements*/
+//#define PREV_IND(ind,size) ind--;if(ind<0) ind=size-1
+
+#define VIDBUFF_SIZE 45    //number of video frames in the ring buffer
+#define AUDBUFF_SIZE 100   //number of audio mpeg frames in the ring buffer
+#define MPG_NUM_SAMP 1152  //number of samples in a audio MPEG frame 
+//#define MPG_NUM_FRAMES 2   //number of MPEG frames in a audio frame
+
+typedef uint64_t QWORD;
+typedef uint32_t DWORD;
+typedef uint16_t WORD;
+typedef uint8_t  BYTE;
+typedef unsigned int LONG;
+typedef unsigned int UINT;
+
+typedef unsigned long long ULLONG;
+typedef unsigned long      ULONG;
+
+typedef char* pchar;
+
+typedef int8_t     INT8;
+typedef uint8_t    UINT8;
+typedef int16_t    INT16;
+typedef uint16_t   UINT16;
+typedef int32_t    INT32;
+typedef uint32_t   UINT32;
+typedef int64_t    INT64;
+typedef uint64_t   UINT64;
+
+typedef float SAMPLE;
+
+/* 0 is device default*/
+static const int stdSampleRates[] = 
+{ 
+	0, 8000,  9600, 11025, 12000,
+	16000, 22050, 24000,
+	32000, 44100, 48000,
+	88200, 96000,
+	-1   /* Negative terminated list. */
+};
+
+/*----------- guvcview version ----------------*/
+//#define VERSION ("") /*defined in config.h*/
+//#define DEBUG (0)
+/*---------- Thread Stack Size (bytes) --------*/
+#define TSTACK (128*64*1024) /* Debian Default 128 pages of 64k = 8388608 bytes*/
+
+/*----------- AVI max file size ---------------*/
+#define AVI_MAX_SIZE (1900*1024*1024)
+/* extra size beyond MAX SIZE at wich we can still write data*/ 
+#define AVI_EXTRA_SIZE (20*1024*1024)
+
+#define INCPANTILT 64 // 1�
+
+#define WINSIZEX 480
+#define WINSIZEY 700
+
+#define AUTO_EXP 8
+#define MAN_EXP	1
+
+#define DHT_SIZE 432
+
+#define DEFAULT_WIDTH 640
+#define DEFAULT_HEIGHT 480
+
+#define DEFAULT_IMAGE_FNAME	"Image.jpg"
+#define DEFAULT_AVI_FNAME	"capture.avi"
+#define DEFAULT_FPS	25
+#define DEFAULT_FPS_NUM 1
+#define SDL_WAIT_TIME 30 /*SDL - Thread loop sleep time */
+
+/*clip value between 0 and 255*/
+#define CLIP(value) (BYTE)(((value)>0xFF)?0xff:(((value)<0)?0:(value)))
+
+/*MAX macro - gets the bigger value*/
+#ifndef MAX
+#define MAX(a,b) (((a) < (b)) ? (b) : (a))
+#endif
+
+/*FILTER FLAGS*/
+#define YUV_NOFILT (0)
+#define YUV_MIRROR (1<<0)
+#define YUV_UPTURN (1<<1)
+#define YUV_NEGATE (1<<2)
+#define YUV_MONOCR (1<<3)
+#define YUV_PIECES (1<<4)
+#define YUV_PARTICLES (1<<5)
+
+/*Audio Effects*/
+#define SND_NOEF   (0)
+#define SND_ECHO   (1<<0)
+#define SND_FUZZ   (1<<1)
+#define SND_REVERB (1<<2)
+#define SND_WAHWAH (1<<3)
+#define SND_DUCKY  (1<<4)
+
+#endif
+
diff --git a/src/creavision/pwc-ioctl.h b/src/creavision/pwc-ioctl.h
new file mode 100755
index 0000000..0f19779
--- /dev/null
+++ b/src/creavision/pwc-ioctl.h
@@ -0,0 +1,324 @@
+#ifndef PWC_IOCTL_H
+#define PWC_IOCTL_H
+
+/* (C) 2001-2004 Nemosoft Unv.
+   (C) 2004-2006 Luc Saillard (luc at saillard.org)
+
+   NOTE: this version of pwc is an unofficial (modified) release of pwc & pcwx
+   driver and thus may have bugs that are not present in the original version.
+   Please send bug reports and support requests to <luc at saillard.org>.
+   The decompression routines have been implemented by reverse-engineering the
+   Nemosoft binary pwcx module. Caveat emptor.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+/* This is pwc-ioctl.h belonging to PWC 10.0.10
+   It contains structures and defines to communicate from user space
+   directly to the driver.
+ */
+
+/*
+   Changes
+   2001/08/03  Alvarado   Added ioctl constants to access methods for
+			  changing white balance and red/blue gains
+   2002/12/15  G. H. Fernandez-Toribio   VIDIOCGREALSIZE
+   2003/12/13  Nemosft Unv. Some modifications to make interfacing to
+	       PWCX easier
+   2006/01/01  Luc Saillard Add raw format definition
+ */
+
+/* These are private ioctl() commands, specific for the Philips webcams.
+   They contain functions not found in other webcams, and settings not
+   specified in the Video4Linux API.
+
+   The #define names are built up like follows:
+   VIDIOC		VIDeo IOCtl prefix
+	 PWC		Philps WebCam
+	    G           optional: Get
+	    S           optional: Set
+	     ... 	the function
+ */
+
+#include <linux/types.h>
+#include <linux/version.h>
+
+/* Enumeration of image sizes */
+#define PSZ_SQCIF	0x00
+#define PSZ_QSIF	0x01
+#define PSZ_QCIF	0x02
+#define PSZ_SIF		0x03
+#define PSZ_CIF		0x04
+#define PSZ_VGA		0x05
+#define PSZ_MAX		6
+
+
+/* The frame rate is encoded in the video_window.flags parameter using
+   the upper 16 bits, since some flags are defined nowadays. The following
+   defines provide a mask and shift to filter out this value.
+   This value can also be passing using the private flag when using v4l2 and
+   VIDIOC_S_FMT ioctl.
+
+   In 'Snapshot' mode the camera freezes its automatic exposure and colour
+   balance controls.
+ */
+#define PWC_FPS_SHIFT		16
+#define PWC_FPS_MASK		0x00FF0000
+#define PWC_FPS_FRMASK		0x003F0000
+#define PWC_FPS_SNAPSHOT	0x00400000
+#define PWC_QLT_MASK		0x03000000
+#define PWC_QLT_SHIFT		24
+
+
+/* structure for transferring x & y coordinates */
+struct pwc_coord
+{
+	int x, y;		/* guess what */
+	int size;		/* size, or offset */
+};
+
+
+/* Used with VIDIOCPWCPROBE */
+struct pwc_probe
+{
+	char name[32];
+	int type;
+};
+
+struct pwc_serial
+{
+	char serial[30];	/* String with serial number. Contains terminating 0 */
+};
+
+/* pwc_whitebalance.mode values */
+#define PWC_WB_INDOOR		0
+#define PWC_WB_OUTDOOR		1
+#define PWC_WB_FL		2
+#define PWC_WB_MANUAL		3
+#define PWC_WB_AUTO		4
+
+/* Used with VIDIOCPWC[SG]AWB (Auto White Balance).
+   Set mode to one of the PWC_WB_* values above.
+   *red and *blue are the respective gains of these colour components inside
+   the camera; range 0..65535
+   When 'mode' == PWC_WB_MANUAL, 'manual_red' and 'manual_blue' are set or read;
+   otherwise undefined.
+   'read_red' and 'read_blue' are read-only.
+*/
+struct pwc_whitebalance
+{
+	int mode;
+	int manual_red, manual_blue;	/* R/W */
+	int read_red, read_blue;	/* R/O */
+};
+
+/*
+   'control_speed' and 'control_delay' are used in automatic whitebalance mode,
+   and tell the camera how fast it should react to changes in lighting, and
+   with how much delay. Valid values are 0..65535.
+*/
+struct pwc_wb_speed
+{
+	int control_speed;
+	int control_delay;
+
+};
+
+/* Used with VIDIOCPWC[SG]LED */
+struct pwc_leds
+{
+	int led_on;			/* Led on-time; range = 0..25000 */
+	int led_off;			/* Led off-time; range = 0..25000  */
+};
+
+/* Image size (used with GREALSIZE) */
+struct pwc_imagesize
+{
+	int width;
+	int height;
+};
+
+/* Defines and structures for Motorized Pan & Tilt */
+#define PWC_MPT_PAN		0x01
+#define PWC_MPT_TILT		0x02
+#define PWC_MPT_TIMEOUT		0x04 /* for status */
+
+/* Set angles; when absolute != 0, the angle is absolute and the
+   driver calculates the relative offset for you. This can only
+   be used with VIDIOCPWCSANGLE; VIDIOCPWCGANGLE always returns
+   absolute angles.
+ */
+struct pwc_mpt_angles
+{
+	int absolute;		/* write-only */
+	int pan;		/* degrees * 100 */
+	int tilt;		/* degress * 100 */
+};
+
+/* Range of angles of the camera, both horizontally and vertically.
+ */
+struct pwc_mpt_range
+{
+	int pan_min, pan_max;		/* degrees * 100 */
+	int tilt_min, tilt_max;
+};
+
+struct pwc_mpt_status
+{
+	int status;
+	int time_pan;
+	int time_tilt;
+};
+
+
+/* This is used for out-of-kernel decompression. With it, you can get
+   all the necessary information to initialize and use the decompressor
+   routines in standalone applications.
+ */
+struct pwc_video_command
+{
+	int type;		/* camera type (645, 675, 730, etc.) */
+	int release;		/* release number */
+
+	int size;		/* one of PSZ_* */
+	int alternate;
+	int command_len;	/* length of USB video command */
+	unsigned char command_buf[13];	/* Actual USB video command */
+	int bandlength;		/* >0 = compressed */
+	int frame_size;		/* Size of one (un)compressed frame */
+};
+
+/* Flags for PWCX subroutines. Not all modules honour all flags. */
+#define PWCX_FLAG_PLANAR	0x0001
+#define PWCX_FLAG_BAYER		0x0008
+
+
+/* IOCTL definitions */
+
+ /* Restore user settings */
+#define VIDIOCPWCRUSER		_IO('v', 192)
+ /* Save user settings */
+#define VIDIOCPWCSUSER		_IO('v', 193)
+ /* Restore factory settings */
+#define VIDIOCPWCFACTORY	_IO('v', 194)
+
+ /* You can manipulate the compression factor. A compression preference of 0
+    means use uncompressed modes when available; 1 is low compression, 2 is
+    medium and 3 is high compression preferred. Of course, the higher the
+    compression, the lower the bandwidth used but more chance of artefacts
+    in the image. The driver automatically chooses a higher compression when
+    the preferred mode is not available.
+  */
+ /* Set preferred compression quality (0 = uncompressed, 3 = highest compression) */
+#define VIDIOCPWCSCQUAL		_IOW('v', 195, int)
+ /* Get preferred compression quality */
+#define VIDIOCPWCGCQUAL		_IOR('v', 195, int)
+
+
+/* Retrieve serial number of camera */
+#define VIDIOCPWCGSERIAL	_IOR('v', 198, struct pwc_serial)
+
+ /* This is a probe function; since so many devices are supported, it
+    becomes difficult to include all the names in programs that want to
+    check for the enhanced Philips stuff. So in stead, try this PROBE;
+    it returns a structure with the original name, and the corresponding
+    Philips type.
+    To use, fill the structure with zeroes, call PROBE and if that succeeds,
+    compare the name with that returned from VIDIOCGCAP; they should be the
+    same. If so, you can be assured it is a Philips (OEM) cam and the type
+    is valid.
+ */
+#define VIDIOCPWCPROBE		_IOR('v', 199, struct pwc_probe)
+
+ /* Set AGC (Automatic Gain Control); int < 0 = auto, 0..65535 = fixed */
+#define VIDIOCPWCSAGC		_IOW('v', 200, int)
+ /* Get AGC; int < 0 = auto; >= 0 = fixed, range 0..65535 */
+#define VIDIOCPWCGAGC		_IOR('v', 200, int)
+ /* Set shutter speed; int < 0 = auto; >= 0 = fixed, range 0..65535 */
+#define VIDIOCPWCSSHUTTER	_IOW('v', 201, int)
+
+ /* Color compensation (Auto White Balance) */
+#define VIDIOCPWCSAWB           _IOW('v', 202, struct pwc_whitebalance)
+#define VIDIOCPWCGAWB           _IOR('v', 202, struct pwc_whitebalance)
+
+ /* Auto WB speed */
+#define VIDIOCPWCSAWBSPEED	_IOW('v', 203, struct pwc_wb_speed)
+#define VIDIOCPWCGAWBSPEED	_IOR('v', 203, struct pwc_wb_speed)
+
+ /* LEDs on/off/blink; int range 0..65535 */
+#define VIDIOCPWCSLED           _IOW('v', 205, struct pwc_leds)
+#define VIDIOCPWCGLED           _IOR('v', 205, struct pwc_leds)
+
+  /* Contour (sharpness); int < 0 = auto, 0..65536 = fixed */
+#define VIDIOCPWCSCONTOUR	_IOW('v', 206, int)
+#define VIDIOCPWCGCONTOUR	_IOR('v', 206, int)
+
+  /* Backlight compensation; 0 = off, otherwise on */
+#define VIDIOCPWCSBACKLIGHT	_IOW('v', 207, int)
+#define VIDIOCPWCGBACKLIGHT	_IOR('v', 207, int)
+
+  /* Flickerless mode; = 0 off, otherwise on */
+#define VIDIOCPWCSFLICKER	_IOW('v', 208, int)
+#define VIDIOCPWCGFLICKER	_IOR('v', 208, int)
+
+  /* Dynamic noise reduction; 0 off, 3 = high noise reduction */
+#define VIDIOCPWCSDYNNOISE	_IOW('v', 209, int)
+#define VIDIOCPWCGDYNNOISE	_IOR('v', 209, int)
+
+ /* Real image size as used by the camera; tells you whether or not there's a gray border around the image */
+#define VIDIOCPWCGREALSIZE	_IOR('v', 210, struct pwc_imagesize)
+
+ /* Motorized pan & tilt functions */
+#define VIDIOCPWCMPTRESET	_IOW('v', 211, int)
+#define VIDIOCPWCMPTGRANGE	_IOR('v', 211, struct pwc_mpt_range)
+#define VIDIOCPWCMPTSANGLE	_IOW('v', 212, struct pwc_mpt_angles)
+#define VIDIOCPWCMPTGANGLE	_IOR('v', 212, struct pwc_mpt_angles)
+#define VIDIOCPWCMPTSTATUS	_IOR('v', 213, struct pwc_mpt_status)
+
+ /* Get the USB set-video command; needed for initializing libpwcx */
+#define VIDIOCPWCGVIDCMD	_IOR('v', 215, struct pwc_video_command)
+struct pwc_table_init_buffer {
+   int len;
+   char *buffer;
+
+};
+#define VIDIOCPWCGVIDTABLE	_IOR('v', 216, struct pwc_table_init_buffer)
+
+/*
+ * This is private command used when communicating with v4l2.
+ * In the future all private ioctl will be remove/replace to
+ * use interface offer by v4l2.
+ */
+
+#define V4L2_CID_PRIVATE_SAVE_USER       (V4L2_CID_PRIVATE_BASE + 0)
+#define V4L2_CID_PRIVATE_RESTORE_USER    (V4L2_CID_PRIVATE_BASE + 1)
+#define V4L2_CID_PRIVATE_RESTORE_FACTORY (V4L2_CID_PRIVATE_BASE + 2)
+#define V4L2_CID_PRIVATE_COLOUR_MODE     (V4L2_CID_PRIVATE_BASE + 3)
+#define V4L2_CID_PRIVATE_AUTOCONTOUR     (V4L2_CID_PRIVATE_BASE + 4)
+#define V4L2_CID_PRIVATE_CONTOUR         (V4L2_CID_PRIVATE_BASE + 5)
+#define V4L2_CID_PRIVATE_BACKLIGHT       (V4L2_CID_PRIVATE_BASE + 6)
+#define V4L2_CID_PRIVATE_FLICKERLESS     (V4L2_CID_PRIVATE_BASE + 7)
+#define V4L2_CID_PRIVATE_NOISE_REDUCTION (V4L2_CID_PRIVATE_BASE + 8)
+
+struct pwc_raw_frame {
+   __le16 type;		/* type of the webcam */
+   __le16 vbandlength;	/* Size of 4lines compressed (used by the decompressor) */
+   __u8   cmd[4];	/* the four byte of the command (in case of nala,
+			   only the first 3 bytes is filled) */
+   __u8   rawframe[0];	/* frame_size = H/4*vbandlength */
+} __attribute__ ((packed));
+
+
+#endif
diff --git a/src/creavision/videoInput.cpp b/src/creavision/videoInput.cpp
new file mode 100755
index 0000000..f65d42e
--- /dev/null
+++ b/src/creavision/videoInput.cpp
@@ -0,0 +1,2360 @@
+// Modified by Cmauri 2010-03-31. See showSettingsWindow
+
+//THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+//IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+//FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+//AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+//LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+//OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+//THE SOFTWARE.
+
+//#define DEBUG 1
+//#define _DEBUG 1
+
+#include "videoInput.h"
+#include "tchar.h"
+
+/*
+	If you get errors when including Microsoft DirectShow or DirectDraw headers, the following message from Peter Whaite could help:
+
+	> This causes compilation errors within DirectShow:
+	>
+	> wxutil.h(125) : error C2065: 'EXECUTE_ASSERT' : undeclared identifier
+	> amfilter.h(1099) : error C2065: 'ASSERT' : undeclared identifier
+
+	The reason for this is that __WXDEBUG__ is also used by the DXSDK (9.0
+	in my case) to '#pragma once' the contents of
+	DXSDK/Samples/C++/DirectShow/BaseClasses/wxdebug.h.  So if __WXDEBUG__
+	is defined, then wxdebug.h doesn't get included, and the assert macros
+	don't get defined.  You have to #undef __WXDEBUG__ before including the
+	directshow baseclass's <streams.h>
+*/
+#undef __WXDEBUG__
+
+//Include Directshow stuff here so we don't worry about needing all the h files.
+#include "DShow.h"
+#include "streams.h"
+#include "qedit.h"
+#include "vector"
+#include "Aviriff.h"
+#include "Windows.h"
+
+//for threading
+#include <process.h>
+
+CFactoryTemplate * g_Templates;
+int g_cTemplates= 0;
+
+
+///////////////////////////  HANDY FUNCTIONS  /////////////////////////////
+
+void MyFreeMediaType(AM_MEDIA_TYPE& mt){
+    if (mt.cbFormat != 0)
+    {
+        CoTaskMemFree((PVOID)mt.pbFormat);
+        mt.cbFormat = 0;
+        mt.pbFormat = NULL;
+    }
+    if (mt.pUnk != NULL)
+    {
+        // Unecessary because pUnk should not be used, but safest.
+        mt.pUnk->Release();
+        mt.pUnk = NULL;
+    }
+}
+
+void MyDeleteMediaType(AM_MEDIA_TYPE *pmt)
+{
+    if (pmt != NULL)
+    {
+        MyFreeMediaType(*pmt); 
+        CoTaskMemFree(pmt);
+    }
+}
+
+//////////////////////////////  CALLBACK  ////////////////////////////////
+
+//Callback class
+class SampleGrabberCallback : public ISampleGrabberCB{
+public:
+
+	//------------------------------------------------
+	SampleGrabberCallback(){
+		InitializeCriticalSection(&critSection);
+		freezeCheck = 0;
+
+
+		bufferSetup 		= false;
+		newFrame			= false;
+		latestBufferLength 	= 0;
+		
+		hEvent = CreateEvent(NULL, true, false, NULL);
+	}
+
+
+	//------------------------------------------------
+	~SampleGrabberCallback(){
+		ptrBuffer = NULL;
+		DeleteCriticalSection(&critSection);
+		CloseHandle(hEvent);
+		if(bufferSetup){
+			delete pixels;
+		}
+	}	
+	
+	
+	//------------------------------------------------
+	bool setupBuffer(int numBytesIn){
+		if(bufferSetup){
+			return false;
+		}else{
+			numBytes 			= numBytesIn;
+			pixels 				= new unsigned char[numBytes];
+			bufferSetup 		= true;
+			newFrame			= false;
+			latestBufferLength 	= 0;
+		}
+		return true;
+	}
+
+
+	//------------------------------------------------
+    STDMETHODIMP_(ULONG) AddRef() { return 1; }
+    STDMETHODIMP_(ULONG) Release() { return 2; }
+
+
+	//------------------------------------------------
+    STDMETHODIMP QueryInterface(REFIID riid, void **ppvObject){
+        *ppvObject = static_cast<ISampleGrabberCB*>(this);
+        return S_OK;
+    }
+    
+    
+    //This method is meant to have less overhead
+	//------------------------------------------------
+    STDMETHODIMP SampleCB(double Time, IMediaSample *pSample){
+    	if(WaitForSingleObject(hEvent, 0) == WAIT_OBJECT_0) return S_OK;
+ 
+    	HRESULT hr = pSample->GetPointer(&ptrBuffer);  
+    		    	
+    	if(hr == S_OK){
+	    	latestBufferLength = pSample->GetActualDataLength();		    	
+	      	if(latestBufferLength == numBytes){
+				EnterCriticalSection(&critSection);
+	      			memcpy(pixels, ptrBuffer, latestBufferLength);	
+					newFrame	= true;
+					freezeCheck = 1;
+				LeaveCriticalSection(&critSection);
+				SetEvent(hEvent);
+			}else{
+				printf("ERROR: SampleCB() - buffer sizes do not match\n");
+			}
+		}
+						
+		return S_OK;
+    }
+    
+    
+    //This method is meant to have more overhead
+    STDMETHODIMP BufferCB(double Time, BYTE *pBuffer, long BufferLen){
+    	return E_NOTIMPL;
+    }
+
+	int freezeCheck;
+
+	int latestBufferLength;
+	int numBytes;
+	bool newFrame;
+	bool bufferSetup;
+	unsigned char * pixels;
+	unsigned char * ptrBuffer;
+	CRITICAL_SECTION critSection;
+	HANDLE hEvent;	
+};
+
+
+//////////////////////////////  VIDEO DEVICE  ////////////////////////////////
+
+// ---------------------------------------------------------------------- 
+//	Should this class also be the callback?		                                                
+//                                                                  
+// ---------------------------------------------------------------------- 
+
+videoDevice::videoDevice(){
+		
+		 pCaptureGraph      = NULL;	// Capture graph builder object
+		 pGraph             = NULL;	// Graph builder object
+	     pControl           = NULL;	// Media control object
+		 pVideoInputFilter  = NULL; // Video Capture filter
+		 pGrabber           = NULL; // Grabs frame
+		 pDestFilter 		= NULL; // Null Renderer Filter
+		 pGrabberF 			= NULL; // Grabber Filter
+		 pMediaEvent		= NULL; 
+		 streamConf			= NULL;
+		 pAmMediaType		= NULL;
+		 
+		 //This is our callback class that processes the frame.
+		 sgCallback			= new SampleGrabberCallback();
+		 sgCallback->newFrame = false;
+
+		 //Default values for capture type
+		 videoType 			= MEDIASUBTYPE_RGB24;
+	     connection     	= PhysConn_Video_Composite;
+		 storeConn			= 0;
+		 
+		 videoSize 			= 0;
+	     width     			= 0;
+	     height    			= 0;
+	     tryWidth			= 0;
+	     tryHeight			= 0;
+		 nFramesForReconnect= 10000;
+		 nFramesRunning     = 0;
+	     myID				= -1;
+	     
+	     tryDiffSize     	= false;
+	     useCrossbar     	= false;
+		 readyToCapture  	= false;
+		 sizeSet			= false;
+		 setupStarted		= false;
+		 specificFormat		= false;
+		 autoReconnect		= false;
+		 requestedFrameTime = -1;
+		 
+		 memset(wDeviceName, 0, sizeof(WCHAR) * 255);
+		 memset(nDeviceName, 0, sizeof(char) * 255);
+	     
+}
+
+
+// ---------------------------------------------------------------------- 
+//	The only place we are doing new	                                                
+//                                                                      
+// ---------------------------------------------------------------------- 
+
+void videoDevice::setSize(int w, int h){
+	if(sizeSet){
+		if(verbose)printf("SETUP: Error device size should not be set more than once \n");
+	}
+	else
+	{
+		width 				= w;
+		height 				= h;
+		videoSize 			= w*h*3;
+		sizeSet 			= true;
+		pixels				= new unsigned char[videoSize];
+		pBuffer				= new char[videoSize];
+
+		memset(pixels, 0 , videoSize);
+		sgCallback->setupBuffer(videoSize);
+		
+	}
+}
+
+
+// ---------------------------------------------------------------------- 
+//	Borrowed from the SDK, use it to take apart the graph from 	                                                
+//  the capture device downstream to the null renderer                                                                   
+// ---------------------------------------------------------------------- 
+
+void videoDevice::NukeDownstream(IBaseFilter *pBF){
+        IPin *pP, *pTo;
+        ULONG u;
+        IEnumPins *pins = NULL;
+        PIN_INFO pininfo;
+        HRESULT hr = pBF->EnumPins(&pins);
+        pins->Reset();
+        while (hr == NOERROR)
+        {
+                hr = pins->Next(1, &pP, &u);
+                if (hr == S_OK && pP)
+                {
+                        pP->ConnectedTo(&pTo);
+                        if (pTo)
+                        {
+                                hr = pTo->QueryPinInfo(&pininfo);
+                                if (hr == NOERROR)
+                                {
+                                        if (pininfo.dir == PINDIR_INPUT)
+                                        {
+                                                NukeDownstream(pininfo.pFilter);
+                                                pGraph->Disconnect(pTo);
+                                                pGraph->Disconnect(pP);
+                                                pGraph->RemoveFilter(pininfo.pFilter);
+                                        }
+                                        pininfo.pFilter->Release();
+										pininfo.pFilter = NULL;
+                                }
+                                pTo->Release();
+                        }
+                        pP->Release();
+                }
+        }
+        if (pins) pins->Release();
+} 
+
+
+// ---------------------------------------------------------------------- 
+//	Also from SDK 	                                                
+// ---------------------------------------------------------------------- 
+
+void videoDevice::destroyGraph(){
+	HRESULT hr = NULL;
+ 	int FuncRetval=0;
+ 	int NumFilters=0;
+
+	int i = 0;
+	while (hr == NOERROR)	
+	{
+		IEnumFilters * pEnum = 0;
+		ULONG cFetched;
+
+		// We must get the enumerator again every time because removing a filter from the graph
+		// invalidates the enumerator. We always get only the first filter from each enumerator.
+		hr = pGraph->EnumFilters(&pEnum);
+		if (FAILED(hr)) { if(verbose)printf("SETUP: pGraph->EnumFilters() failed. \n"); return; }
+
+		IBaseFilter * pFilter = NULL;
+		if (pEnum->Next(1, &pFilter, &cFetched) == S_OK)
+		{
+			FILTER_INFO FilterInfo={0};
+			hr = pFilter->QueryFilterInfo(&FilterInfo);
+			FilterInfo.pGraph->Release();
+
+			int count = 0;
+			char buffer[255];
+			memset(buffer, 0, 255 * sizeof(char));
+						
+			while( FilterInfo.achName[count] != 0x00 ) 
+			{
+				buffer[count] = FilterInfo.achName[count];
+				count++;
+			}
+			
+			if(verbose)printf("SETUP: removing filter %s...\n", buffer);
+			hr = pGraph->RemoveFilter(pFilter);
+			if (FAILED(hr)) { if(verbose)printf("SETUP: pGraph->RemoveFilter() failed. \n"); return; }
+			if(verbose)printf("SETUP: filter removed %s  \n",buffer);
+			
+			pFilter->Release();
+			pFilter = NULL;
+		}
+		else break;
+		pEnum->Release();
+		pEnum = NULL;
+		i++;
+	}
+
+ return;
+}
+
+
+// ---------------------------------------------------------------------- 
+// Our deconstructor, attempts to tear down graph and release filters etc
+// Does checking to make sure it only is freeing if it needs to
+// Probably could be a lot cleaner! :)                                                                
+// ---------------------------------------------------------------------- 
+
+videoDevice::~videoDevice(){
+
+	if(setupStarted){ if(verbose)printf("\nSETUP: Disconnecting device %i\n", myID); }
+	else{
+		if(sgCallback){
+			sgCallback->Release();
+			delete sgCallback;
+		}
+		return;
+	}
+		
+	HRESULT HR = NULL;
+	
+	//Stop the callback and free it
+    if( (sgCallback) && (pGrabber) )
+    {
+    	pGrabber->SetCallback(NULL, 1);
+        if(verbose)printf("SETUP: freeing Grabber Callback\n");
+        sgCallback->Release(); 	
+        
+		//delete our pixels 
+		if(sizeSet){
+			 delete[] pixels;
+			 delete[] pBuffer;
+		}
+		
+		delete sgCallback;
+	}
+	
+	//Check to see if the graph is running, if so stop it. 
+ 	if( (pControl) )
+	{
+		HR = pControl->Pause();
+		if (FAILED(HR)) if(verbose)printf("ERROR - Could not pause pControl\n");
+		
+		HR = pControl->Stop();
+		if (FAILED(HR)) if(verbose)printf("ERROR - Could not stop pControl\n");
+    }
+        	
+    //Disconnect filters from capture device
+    if( (pVideoInputFilter) )NukeDownstream(pVideoInputFilter);
+
+	//Release and zero pointers to our filters etc
+	if( (pDestFilter) ){ 		if(verbose)printf("SETUP: freeing Renderer \n");
+								(pDestFilter)->Release();
+								(pDestFilter) = 0;
+	}	
+	if( (pVideoInputFilter) ){ 	if(verbose)printf("SETUP: freeing Capture Source \n");
+								(pVideoInputFilter)->Release();		
+								(pVideoInputFilter) = 0;
+	}
+	if( (pGrabberF) ){ 			if(verbose)printf("SETUP: freeing Grabber Filter  \n");
+								(pGrabberF)->Release();
+								(pGrabberF) = 0;  			
+	}
+	if( (pGrabber) ){ 			if(verbose)printf("SETUP: freeing Grabber  \n"); 
+								(pGrabber)->Release();
+								(pGrabber) = 0;  			
+	}
+	if( (pControl) ){ 			if(verbose)printf("SETUP: freeing Control   \n");
+								(pControl)->Release();
+								(pControl) = 0; 			
+	}		
+	if( (pMediaEvent) ){ 		if(verbose)printf("SETUP: freeing Media Event  \n");
+								(pMediaEvent)->Release();				
+								(pMediaEvent) = 0;  		
+	}
+	if( (streamConf) ){ 		if(verbose)printf("SETUP: freeing Stream  \n");
+								(streamConf)->Release();					
+								(streamConf) = 0;  			
+	}
+
+	if( (pAmMediaType) ){ 		if(verbose)printf("SETUP: freeing Media Type  \n");
+								MyDeleteMediaType(pAmMediaType);  			
+	}
+
+	if((pMediaEvent)){
+			if(verbose)printf("SETUP: freeing Media Event  \n");
+			(pMediaEvent)->Release();					
+			(pMediaEvent) = 0;  
+	}
+
+	//Destroy the graph
+	if( (pGraph) )destroyGraph();
+
+	//Release and zero our capture graph and our main graph
+	if( (pCaptureGraph) ){ 		if(verbose)printf("SETUP: freeing Capture Graph \n");
+								(pCaptureGraph)->Release();
+								(pCaptureGraph) = 0;  		
+	}
+	if( (pGraph) ){ 			if(verbose)printf("SETUP: freeing Main Graph \n");
+								(pGraph)->Release();					
+								(pGraph) = 0;  				
+	}		
+
+	//delete our pointers
+	delete pDestFilter;
+	delete pVideoInputFilter;
+	delete pGrabberF;
+	delete pGrabber;
+	delete pControl;
+	delete streamConf;
+	delete pMediaEvent;
+	delete pCaptureGraph;
+	delete pGraph;
+
+	if(verbose)printf("SETUP: Device %i disconnected and freed\n\n",myID);
+}
+
+
+//////////////////////////////  VIDEO INPUT  ////////////////////////////////
+////////////////////////////  PUBLIC METHODS  ///////////////////////////////
+
+
+// ---------------------------------------------------------------------- 
+// Constructor - creates instances of videoDevice and adds the various
+// media subtypes to check.                                               
+// ---------------------------------------------------------------------- 
+
+videoInput::videoInput(){    
+	//start com
+	comInit();
+
+	devicesFound 		= 0;
+	callbackSetCount 	= 0;
+	bCallback	 		= true;
+	
+    //setup a max no of device objects
+    for(int i=0; i<VI_MAX_CAMERAS; i++)  VDList[i] = new videoDevice();
+     
+    if(verbose)printf("\n***** VIDEOINPUT LIBRARY - %2.04f - TFW07 *****\n\n",VI_VERSION);
+
+	//added for the pixelink firewire camera
+ 	MEDIASUBTYPE_Y800 = (GUID)FOURCCMap(FCC('Y800'));
+ 	MEDIASUBTYPE_Y8   = (GUID)FOURCCMap(FCC('Y8'));
+ 	MEDIASUBTYPE_GREY = (GUID)FOURCCMap(FCC('GREY'));
+
+	//The video types we support
+	//in order of preference
+	
+	mediaSubtypes[0] 	= MEDIASUBTYPE_RGB24;
+	mediaSubtypes[1] 	= MEDIASUBTYPE_RGB32;
+	mediaSubtypes[2] 	= MEDIASUBTYPE_RGB555;
+	mediaSubtypes[3] 	= MEDIASUBTYPE_RGB565;
+	mediaSubtypes[4] 	= MEDIASUBTYPE_YUY2;
+	mediaSubtypes[5] 	= MEDIASUBTYPE_YVYU;
+	mediaSubtypes[6] 	= MEDIASUBTYPE_YUYV;
+	mediaSubtypes[7] 	= MEDIASUBTYPE_IYUV;
+	mediaSubtypes[8] 	= MEDIASUBTYPE_UYVY;
+	mediaSubtypes[9] 	= MEDIASUBTYPE_YV12;
+	mediaSubtypes[10]	= MEDIASUBTYPE_YVU9;
+	mediaSubtypes[11] 	= MEDIASUBTYPE_Y411;
+	mediaSubtypes[12] 	= MEDIASUBTYPE_Y41P;
+	mediaSubtypes[13] 	= MEDIASUBTYPE_Y211;
+	mediaSubtypes[14]	= MEDIASUBTYPE_AYUV;
+
+	//non standard
+	mediaSubtypes[15]	= MEDIASUBTYPE_Y800;
+    mediaSubtypes[16]	= MEDIASUBTYPE_Y8;
+	mediaSubtypes[17]	= MEDIASUBTYPE_GREY;	
+	
+	//The video formats we support
+	formatTypes[VI_NTSC_M]		= AnalogVideo_NTSC_M;
+	formatTypes[VI_NTSC_M_J]	= AnalogVideo_NTSC_M_J;
+	formatTypes[VI_NTSC_433]	= AnalogVideo_NTSC_433;
+		
+	formatTypes[VI_PAL_B]		= AnalogVideo_PAL_B;
+	formatTypes[VI_PAL_D]		= AnalogVideo_PAL_D;
+	formatTypes[VI_PAL_G]		= AnalogVideo_PAL_G;
+	formatTypes[VI_PAL_H]		= AnalogVideo_PAL_H;
+	formatTypes[VI_PAL_I]		= AnalogVideo_PAL_I;
+	formatTypes[VI_PAL_M]		= AnalogVideo_PAL_M;
+	formatTypes[VI_PAL_N]		= AnalogVideo_PAL_N;
+	formatTypes[VI_PAL_NC]		= AnalogVideo_PAL_N_COMBO;
+	
+	formatTypes[VI_SECAM_B]		= AnalogVideo_SECAM_B;
+	formatTypes[VI_SECAM_D]		= AnalogVideo_SECAM_D;
+	formatTypes[VI_SECAM_G]		= AnalogVideo_SECAM_G;
+	formatTypes[VI_SECAM_H]		= AnalogVideo_SECAM_H;
+	formatTypes[VI_SECAM_K]		= AnalogVideo_SECAM_K;
+	formatTypes[VI_SECAM_K1]	= AnalogVideo_SECAM_K1;
+	formatTypes[VI_SECAM_L]		= AnalogVideo_SECAM_L;
+	
+	
+	propBrightness				= VideoProcAmp_Brightness;
+	propContrast			   	= VideoProcAmp_Contrast;
+	propHue						= VideoProcAmp_Hue;
+	propSaturation 				= VideoProcAmp_Saturation;
+	propSharpness			 	= VideoProcAmp_Sharpness;
+	propGamma	 				= VideoProcAmp_Gamma;
+	propColorEnable				= VideoProcAmp_ColorEnable;
+	propWhiteBalance 			= VideoProcAmp_WhiteBalance;
+	propBacklightCompensation 	= VideoProcAmp_BacklightCompensation;
+	propGain 					= VideoProcAmp_Gain;
+
+	propPan						= CameraControl_Pan;
+	propTilt					= CameraControl_Tilt;
+	propRoll					= CameraControl_Roll;
+	propZoom					= CameraControl_Zoom;
+	propExposure   				= CameraControl_Exposure;
+	propIris					= CameraControl_Iris;
+	propFocus					= CameraControl_Focus;
+						
+}
+
+
+// ---------------------------------------------------------------------- 
+// static - set whether messages get printed to console or not
+//                                            
+// ---------------------------------------------------------------------- 
+
+void videoInput::setVerbose(bool _verbose){
+	verbose = _verbose;
+}
+
+// ---------------------------------------------------------------------- 
+// change to use callback or regular capture
+// callback tells you when a new frame has arrived
+// but non-callback won't - but is single threaded
+// ---------------------------------------------------------------------- 
+void videoInput::setUseCallback(bool useCallback){
+	if(callbackSetCount == 0){
+		bCallback = useCallback;
+		callbackSetCount = 1;
+	}else{
+		printf("ERROR: setUseCallback can only be called before setup\n");
+	}
+}
+
+// ---------------------------------------------------------------------- 
+// Set the requested framerate - no guarantee you will get this
+//                                            
+// ---------------------------------------------------------------------- 
+
+void videoInput::setIdealFramerate(int deviceNumber, int idealFramerate){
+	if(deviceNumber >= VI_MAX_CAMERAS || VDList[deviceNumber]->readyToCapture) return;
+	
+	if( idealFramerate > 0 ){
+		VDList[deviceNumber]->requestedFrameTime = (unsigned long)(10000000 / idealFramerate);
+	}
+}
+
+
+// ---------------------------------------------------------------------- 
+// Set the requested framerate - no guarantee you will get this
+//                                            
+// ---------------------------------------------------------------------- 
+
+void videoInput::setAutoReconnectOnFreeze(int deviceNumber, bool doReconnect, int numMissedFramesBeforeReconnect){
+	if(deviceNumber >= VI_MAX_CAMERAS) return;
+
+	VDList[deviceNumber]->autoReconnect			= doReconnect;
+	VDList[deviceNumber]->nFramesForReconnect	= numMissedFramesBeforeReconnect;	
+
+}
+
+
+// ---------------------------------------------------------------------- 
+// Setup a device with the default settings
+//                                            
+// ---------------------------------------------------------------------- 
+
+bool videoInput::setupDevice(int deviceNumber){
+	if(deviceNumber >= VI_MAX_CAMERAS || VDList[deviceNumber]->readyToCapture) return false;
+
+	if(setup(deviceNumber))return true;
+	return false;
+}
+
+
+// ---------------------------------------------------------------------- 
+// Setup a device with the default size but specify input type
+//                                            
+// ---------------------------------------------------------------------- 
+
+bool videoInput::setupDevice(int deviceNumber, int connection){
+	if(deviceNumber >= VI_MAX_CAMERAS || VDList[deviceNumber]->readyToCapture) return false;
+
+	setPhyCon(deviceNumber, connection);
+	if(setup(deviceNumber))return true;
+	return false;
+}
+
+
+// ---------------------------------------------------------------------- 
+// Setup a device with the default connection but specify size
+//                                            
+// ---------------------------------------------------------------------- 
+
+bool videoInput::setupDevice(int deviceNumber, int w, int h){
+	if(deviceNumber >= VI_MAX_CAMERAS || VDList[deviceNumber]->readyToCapture) return false;
+
+	setAttemptCaptureSize(deviceNumber,w,h);
+	if(setup(deviceNumber))return true;
+	return false;
+}
+
+
+// ---------------------------------------------------------------------- 
+// Setup a device with specific size and connection
+//                                            
+// ---------------------------------------------------------------------- 
+
+bool videoInput::setupDevice(int deviceNumber, int w, int h, int connection){
+	if(deviceNumber >= VI_MAX_CAMERAS || VDList[deviceNumber]->readyToCapture) return false;
+
+	setAttemptCaptureSize(deviceNumber,w,h);
+	setPhyCon(deviceNumber, connection);
+	if(setup(deviceNumber))return true;
+	return false;
+}
+
+
+// ---------------------------------------------------------------------- 
+// Setup the default video format of the device
+// Must be called after setup!
+// See #define formats in header file (eg VI_NTSC_M )
+//                                            
+// ---------------------------------------------------------------------- 
+
+bool videoInput::setFormat(int deviceNumber, int format){
+	if(deviceNumber >= VI_MAX_CAMERAS || !VDList[deviceNumber]->readyToCapture) return false;
+	
+	bool returnVal = false;
+	
+	if(format >= 0 && format < VI_NUM_FORMATS){
+		VDList[deviceNumber]->formatType = formatTypes[format];	
+		VDList[deviceNumber]->specificFormat = true;
+		
+		if(VDList[deviceNumber]->specificFormat){
+		
+			HRESULT hr = getDevice(&VDList[deviceNumber]->pVideoInputFilter, deviceNumber, VDList[deviceNumber]->wDeviceName, VDList[deviceNumber]->nDeviceName);
+			if(hr != S_OK){
+				return false;
+			}
+
+			IAMAnalogVideoDecoder *pVideoDec = NULL;    	
+	   		hr = VDList[deviceNumber]->pCaptureGraph->FindInterface(NULL, &MEDIATYPE_Video, VDList[deviceNumber]->pVideoInputFilter, IID_IAMAnalogVideoDecoder, (void **)&pVideoDec);
+			
+			//in case the settings window some how freed them first
+			if(VDList[deviceNumber]->pVideoInputFilter)VDList[deviceNumber]->pVideoInputFilter->Release();  		
+			if(VDList[deviceNumber]->pVideoInputFilter)VDList[deviceNumber]->pVideoInputFilter = NULL;  
+
+			if(FAILED(hr)){
+				printf("SETUP: couldn't set requested format\n");
+			}else{
+				long lValue = 0;
+				hr = pVideoDec->get_AvailableTVFormats(&lValue);
+	    		if( SUCCEEDED(hr) && (lValue & VDList[deviceNumber]->formatType) )
+	   			{
+	       			hr = pVideoDec->put_TVFormat(VDList[deviceNumber]->formatType);
+					if( FAILED(hr) ){
+						printf("SETUP: couldn't set requested format\n");
+					}else{
+						returnVal = true;	
+					}
+			   	}
+				
+				pVideoDec->Release();
+	        	pVideoDec = NULL;			   	
+			}			
+		}		
+	}
+	
+	return returnVal;
+}
+
+// ---------------------------------------------------------------------- 
+// Our static function for returning device names - thanks Peter!
+// Must call listDevices first.
+//                                           
+// ---------------------------------------------------------------------- 
+char videoInput::deviceNames[VI_MAX_CAMERAS][255]={{0}};
+
+char * videoInput::getDeviceName(int deviceID){
+	if( deviceID >= VI_MAX_CAMERAS ){
+		return NULL;
+	}
+	return deviceNames[deviceID];
+}
+
+
+// ---------------------------------------------------------------------- 
+// Our static function for finding num devices available etc
+//                                           
+// ---------------------------------------------------------------------- 
+
+int videoInput::listDevices(bool silent){  
+
+    //COM Library Intialization
+	comInit();
+	
+    if(!silent)printf("\nVIDEOINPUT SPY MODE!\n\n");   
+   
+  	
+	ICreateDevEnum *pDevEnum = NULL;
+	IEnumMoniker *pEnum = NULL;	
+	int deviceCounter = 0;
+	
+	HRESULT hr = CoCreateInstance(CLSID_SystemDeviceEnum, NULL,
+	    CLSCTX_INPROC_SERVER, IID_ICreateDevEnum, 
+	    reinterpret_cast<void**>(&pDevEnum));
+	    
+	    
+	if (SUCCEEDED(hr))
+	{
+	    // Create an enumerator for the video capture category.
+	    hr = pDevEnum->CreateClassEnumerator(
+	    	CLSID_VideoInputDeviceCategory,
+	        &pEnum, 0);
+	        
+	   if(hr == S_OK){
+	   
+			 if(!silent)printf("SETUP: Looking For Capture Devices\n");
+			IMoniker *pMoniker = NULL;
+
+			while (pEnum->Next(1, &pMoniker, NULL) == S_OK){
+			    
+			    IPropertyBag *pPropBag;
+			    hr = pMoniker->BindToStorage(0, 0, IID_IPropertyBag, 
+			        (void**)(&pPropBag));
+			        
+			    if (FAILED(hr)){
+			        pMoniker->Release();
+			        continue;  // Skip this one, maybe the next one will work.
+			    } 
+			    
+			    
+ 				// Find the description or friendly name.
+			    VARIANT varName;
+			    VariantInit(&varName);
+			    hr = pPropBag->Read(L"Description", &varName, 0);
+		    			    
+			    if (FAILED(hr)) hr = pPropBag->Read(L"FriendlyName", &varName, 0);
+			  
+			    if (SUCCEEDED(hr)){
+			    
+			    	hr = pPropBag->Read(L"FriendlyName", &varName, 0);
+			     	
+					int count = 0;
+					int maxLen = sizeof(deviceNames[0])/sizeof(deviceNames[0][0]) - 2;
+					while( varName.bstrVal[count] != 0x00 && count < maxLen) {
+						deviceNames[deviceCounter][count] = varName.bstrVal[count];
+						count++;
+					}
+					deviceNames[deviceCounter][count] = 0;
+			                          
+			        if(!silent)printf("SETUP: %i) %s \n",deviceCounter, deviceNames[deviceCounter]);
+			    }
+			    
+			    pPropBag->Release();
+			    pPropBag = NULL;
+			    
+			    pMoniker->Release();
+			    pMoniker = NULL;
+			    
+			    deviceCounter++;
+			}   
+			
+			pDevEnum->Release();
+			pDevEnum = NULL;
+			
+			pEnum->Release();
+			pEnum = NULL;
+		}
+	
+		 if(!silent)printf("SETUP: %i Device(s) found\n\n", deviceCounter);
+	}
+	
+	comUnInit();
+	
+	return deviceCounter;		
+}
+
+
+// ---------------------------------------------------------------------- 
+// 
+//                                           
+// ---------------------------------------------------------------------- 
+
+int videoInput::getWidth(int id){
+	
+	if(isDeviceSetup(id))
+	{
+		return VDList[id] ->width;
+	}
+	
+	return 0;
+	
+}
+
+
+// ---------------------------------------------------------------------- 
+// 
+//                                           
+// ---------------------------------------------------------------------- 
+
+int videoInput::getHeight(int id){
+	
+	if(isDeviceSetup(id))
+	{
+		return VDList[id] ->height;
+	}
+	
+	return 0;
+	
+}
+
+
+// ---------------------------------------------------------------------- 
+// 
+//                                           
+// ---------------------------------------------------------------------- 
+
+int videoInput::getSize(int id){
+	
+	if(isDeviceSetup(id))
+	{
+		return VDList[id] ->videoSize;
+	}
+	
+	return 0;
+	
+}
+
+
+// ----------------------------------------------------------------------
+// Uses a supplied buffer
+// ---------------------------------------------------------------------- 
+
+bool videoInput::getPixels(int id, unsigned char * dstBuffer, bool flipRedAndBlue, bool flipImage){
+	
+	bool success = false;
+
+	if(isDeviceSetup(id)){		
+		if(bCallback){		
+			//callback capture	
+		
+			DWORD result = WaitForSingleObject(VDList[id]->sgCallback->hEvent, 1000);
+			if( result != WAIT_OBJECT_0) return false;
+						
+			//double paranoia - mutexing with both event and critical section
+			EnterCriticalSection(&VDList[id]->sgCallback->critSection);
+			
+				unsigned char * src = VDList[id]->sgCallback->pixels;
+				unsigned char * dst = dstBuffer;
+				int height 			= VDList[id]->height;
+				int width  			= VDList[id]->width; 
+			
+				processPixels(src, dst, width, height, flipRedAndBlue, flipImage);
+				VDList[id]->sgCallback->newFrame = false;
+				
+			LeaveCriticalSection(&VDList[id]->sgCallback->critSection);	
+
+			ResetEvent(VDList[id]->sgCallback->hEvent);
+			
+			success = true;
+			
+		}
+		else{	
+			//regular capture method
+			long bufferSize = VDList[id]->videoSize;
+			HRESULT hr = VDList[id]->pGrabber->GetCurrentBuffer(&bufferSize, (long *)VDList[id]->pBuffer);
+			if(hr==S_OK){
+				int numBytes = VDList[id]->videoSize;					
+				if (numBytes == bufferSize){
+					
+					unsigned char * src = (unsigned char * )VDList[id]->pBuffer;
+					unsigned char * dst = dstBuffer;
+					int height 			= VDList[id]->height;
+					int width 			= VDList[id]->width; 
+										
+					processPixels(src, dst, width, height, flipRedAndBlue, flipImage);
+					success = true;
+				}else{
+					if(verbose)printf("ERROR: GetPixels() - bufferSizes do not match!\n");
+				}
+			}else{
+				if(verbose)printf("ERROR: GetPixels() - Unable to grab frame for device %i\n", id);
+			}				
+		}
+	}
+	
+	return success;
+}
+
+
+// ----------------------------------------------------------------------
+// Returns a buffer
+// ---------------------------------------------------------------------- 
+unsigned char * videoInput::getPixels(int id, bool flipRedAndBlue, bool flipImage){
+
+	if(isDeviceSetup(id)){
+   		getPixels(id, VDList[id]->pixels, flipRedAndBlue, flipImage);
+	}
+	
+	return VDList[id]->pixels;
+}
+
+
+
+// ---------------------------------------------------------------------- 
+// 
+//                                           
+// ---------------------------------------------------------------------- 
+bool videoInput::isFrameNew(int id){
+	if(!isDeviceSetup(id)) return false;
+	if(!bCallback)return true;
+	
+	bool result = false;
+	bool freeze = false;
+	
+	//again super paranoia!
+	EnterCriticalSection(&VDList[id]->sgCallback->critSection);
+		result = VDList[id]->sgCallback->newFrame;
+
+		//we need to give it some time at the begining to start up so lets check after 400 frames
+		if(VDList[id]->nFramesRunning > 400 && VDList[id]->sgCallback->freezeCheck > VDList[id]->nFramesForReconnect ){
+			freeze = true;
+		}
+		
+		//we increment the freezeCheck var here - the callback resets it to 1 
+		//so as long as the callback is running this var should never get too high.
+		//if the callback is not running then this number will get high and trigger the freeze action below 
+		VDList[id]->sgCallback->freezeCheck++;
+	LeaveCriticalSection(&VDList[id]->sgCallback->critSection);	
+
+	VDList[id]->nFramesRunning++;
+
+	if(freeze && VDList[id]->autoReconnect){
+		if(verbose)printf("ERROR: Device seems frozen - attempting to reconnect\n"); 
+		if( !restartDevice(VDList[id]->myID) ){
+			if(verbose)printf("ERROR: Unable to reconnect to device\n");
+		}else{
+			if(verbose)printf("SUCCESS: Able to reconnect to device\n");
+		}
+	}
+		
+	return result;	
+}
+
+
+// ---------------------------------------------------------------------- 
+// 
+//                                           
+// ---------------------------------------------------------------------- 
+
+bool videoInput::isDeviceSetup(int id){
+	
+	if(id<devicesFound && VDList[id]->readyToCapture)return true;
+	else return false;
+
+}
+
+
+// ---------------------------------------------------------------------- 
+// Gives us a little pop up window to adjust settings           
+// We do this in a seperate thread now!
+// ---------------------------------------------------------------------- 
+
+
+void __cdecl videoInput::basicThread(void * objPtr){
+
+	//get a reference to the video device
+	//not a copy as we need to free the filter
+	videoDevice * vd = *( (videoDevice **)(objPtr) );
+	ShowFilterPropertyPages(vd->pVideoInputFilter);	
+
+	//now we free the filter and make sure it set to NULL
+	if(vd->pVideoInputFilter)vd->pVideoInputFilter->Release();
+	if(vd->pVideoInputFilter)vd->pVideoInputFilter = NULL;
+
+	return;
+}
+
+void videoInput::showSettingsWindow(int id){ 
+
+	if(isDeviceSetup(id)){
+
+//		HANDLE myTempThread;
+
+		//we reconnect to the device as we have freed our reference to it
+		//why have we freed our reference? because there seemed to be an issue 
+		//with some mpeg devices if we didn't
+		HRESULT hr = getDevice(&VDList[id]->pVideoInputFilter, id, VDList[id]->wDeviceName, VDList[id]->nDeviceName);
+		if(hr == S_OK){
+			// Modified by cmauri. Don't start a new thread
+			//myTempThread = (HANDLE)_beginthread(basicThread, 0, (void *)&VDList[id]);  
+			videoInput::basicThread ((void *)&VDList[id]);			
+		}
+	}
+}
+
+
+// Set a video signal setting using IAMVideoProcAmp
+bool videoInput::getVideoSettingFilter(int deviceID, long Property, long &min, long &max, long &SteppingDelta, long &currentValue, long &flags, long &defaultValue){
+	if( !isDeviceSetup(deviceID) )return false;
+
+	HRESULT hr;	
+	bool isSuccessful = false;
+	
+	videoDevice * VD = VDList[deviceID];
+	
+	hr = getDevice(&VD->pVideoInputFilter, deviceID, VD->wDeviceName, VD->nDeviceName);	
+	if (FAILED(hr)){
+		printf("setVideoSetting - getDevice Error\n");
+		return false;
+	}
+
+	IAMVideoProcAmp *pAMVideoProcAmp = NULL;
+	
+	hr = VD->pVideoInputFilter->QueryInterface(IID_IAMVideoProcAmp, (void**)&pAMVideoProcAmp);
+	if(FAILED(hr)){
+		printf("setVideoSetting - QueryInterface Error\n");
+		if(VD->pVideoInputFilter)VD->pVideoInputFilter->Release();
+		if(VD->pVideoInputFilter)VD->pVideoInputFilter = NULL;		
+		return false;			
+	}
+	
+	if (verbose) printf("Setting video setting %ld.\n", Property);
+	
+	pAMVideoProcAmp->GetRange(Property, &min, &max, &SteppingDelta, &defaultValue, &flags);
+	if (verbose) printf("Range for video setting %ld: Min:%ld Max:%ld SteppingDelta:%ld Default:%ld Flags:%ld\n", Property, min, max, SteppingDelta, defaultValue, flags);
+	pAMVideoProcAmp->Get(Property, &currentValue, &flags);
+	
+	if(pAMVideoProcAmp)pAMVideoProcAmp->Release();
+	if(VD->pVideoInputFilter)VD->pVideoInputFilter->Release();
+	if(VD->pVideoInputFilter)VD->pVideoInputFilter = NULL;	
+			
+	return true;
+	
+}
+
+
+// Set a video signal setting using IAMVideoProcAmp
+bool videoInput::setVideoSettingFilterPct(int deviceID, long Property, float pctValue, long Flags){
+	if( !isDeviceSetup(deviceID) )return false;
+	
+	long min, max, currentValue, flags, defaultValue, stepAmnt;
+	
+	if( !getVideoSettingFilter(deviceID, Property, min, max, stepAmnt, currentValue, flags, defaultValue) )return false;
+
+	if(pctValue > 1.0)pctValue = 1.0;
+	else if(pctValue < 0)pctValue = 0.0;
+	
+	float range = (float)max - (float)min;
+	if(range <= 0)return false;	 
+	if(stepAmnt == 0) return false;
+
+	long value 	= (long)( (float)min + range * pctValue ); 
+	long rasterValue = value;
+
+	//if the range is the stepAmnt then it is just a switch
+	//so we either set the value to low or high
+	if( range == stepAmnt ){
+		if( pctValue < 0.5)rasterValue = min;
+		else rasterValue = max;	
+	}else{
+		//we need to rasterize the value to the stepping amnt
+		long mod 		= value % stepAmnt;
+		float halfStep 	= (float)stepAmnt * 0.5f;
+		if( mod < halfStep ) rasterValue -= mod;
+		else rasterValue += stepAmnt - mod;	
+		printf("RASTER - pctValue is %f - value is %i - step is %i - mod is %i - rasterValue is %i\n", pctValue, value, stepAmnt, mod, rasterValue); 
+	}
+		
+	return setVideoSettingFilter(deviceID, Property, rasterValue, Flags, false);
+}
+
+
+// Set a video signal setting using IAMVideoProcAmp
+bool videoInput::setVideoSettingFilter(int deviceID, long Property, long lValue, long Flags, bool useDefaultValue){
+	if( !isDeviceSetup(deviceID) )return false;
+
+	HRESULT hr;	
+	bool isSuccessful = false;
+	
+	videoDevice * VD = VDList[deviceID];
+	
+	hr = getDevice(&VD->pVideoInputFilter, deviceID, VD->wDeviceName, VD->nDeviceName);	
+	if (FAILED(hr)){
+		printf("setVideoSetting - getDevice Error\n");
+		return false;
+	}
+
+	IAMVideoProcAmp *pAMVideoProcAmp = NULL;
+	
+	hr = VD->pVideoInputFilter->QueryInterface(IID_IAMVideoProcAmp, (void**)&pAMVideoProcAmp);
+	if(FAILED(hr)){
+		printf("setVideoSetting - QueryInterface Error\n");
+		if(VD->pVideoInputFilter)VD->pVideoInputFilter->Release();
+		if(VD->pVideoInputFilter)VD->pVideoInputFilter = NULL;		
+		return false;			
+	}
+	
+	if (verbose) printf("Setting video setting %ld.\n", Property);
+	long CurrVal, Min, Max, SteppingDelta, Default, CapsFlags, AvailableCapsFlags = 0;
+	
+	
+	pAMVideoProcAmp->GetRange(Property, &Min, &Max, &SteppingDelta, &Default, &AvailableCapsFlags);
+	if (verbose) printf("Range for video setting %ld: Min:%ld Max:%ld SteppingDelta:%ld Default:%ld Flags:%ld\n", Property, Min, Max, SteppingDelta, Default, AvailableCapsFlags);
+	pAMVideoProcAmp->Get(Property, &CurrVal, &CapsFlags);
+	
+	if (verbose) printf("Current value: %ld Flags %ld (%s)\n", CurrVal, CapsFlags, (CapsFlags == 1 ? "Auto" : (CapsFlags == 2 ? "Manual" : "Unknown")));
+	
+	if (useDefaultValue) {
+		pAMVideoProcAmp->Set(Property, Default, VideoProcAmp_Flags_Auto);
+	}
+	else{
+		// Perhaps add a check that lValue and Flags are within the range aquired from GetRange above
+		pAMVideoProcAmp->Set(Property, lValue, Flags);
+	}
+	
+	if(pAMVideoProcAmp)pAMVideoProcAmp->Release();
+	if(VD->pVideoInputFilter)VD->pVideoInputFilter->Release();
+	if(VD->pVideoInputFilter)VD->pVideoInputFilter = NULL;	
+			
+	return true;
+	
+}
+
+
+bool videoInput::setVideoSettingCameraPct(int deviceID, long Property, float pctValue, long Flags){
+	if( !isDeviceSetup(deviceID) )return false;
+	
+	long min, max, currentValue, flags, defaultValue, stepAmnt;
+	
+	if( !getVideoSettingCamera(deviceID, Property, min, max, stepAmnt, currentValue, flags, defaultValue) )return false;
+
+	if(pctValue > 1.0)pctValue = 1.0;
+	else if(pctValue < 0)pctValue = 0.0;
+	
+	float range = (float)max - (float)min;
+	if(range <= 0)return false;	 
+	if(stepAmnt == 0) return false;
+
+	long value 	= (long)( (float)min + range * pctValue ); 
+	long rasterValue = value;
+
+	//if the range is the stepAmnt then it is just a switch
+	//so we either set the value to low or high
+	if( range == stepAmnt ){
+		if( pctValue < 0.5)rasterValue = min;
+		else rasterValue = max;	
+	}else{
+		//we need to rasterize the value to the stepping amnt
+		long mod 		= value % stepAmnt;
+		float halfStep 	= (float)stepAmnt * 0.5f;
+		if( mod < halfStep ) rasterValue -= mod;
+		else rasterValue += stepAmnt - mod;	
+		printf("RASTER - pctValue is %f - value is %i - step is %i - mod is %i - rasterValue is %i\n", pctValue, value, stepAmnt, mod, rasterValue); 
+	}
+	
+	return setVideoSettingCamera(deviceID, Property, rasterValue, Flags, false);
+}
+
+
+bool videoInput::setVideoSettingCamera(int deviceID, long Property, long lValue, long Flags, bool useDefaultValue){
+	IAMCameraControl *pIAMCameraControl;
+	if(isDeviceSetup(deviceID))
+	{
+		HRESULT hr;
+		hr = getDevice(&VDList[deviceID]->pVideoInputFilter, deviceID, VDList[deviceID]->wDeviceName, VDList[deviceID]->nDeviceName);	
+	
+		if (verbose) printf("Setting video setting %ld.\n", Property);
+		hr = VDList[deviceID]->pVideoInputFilter->QueryInterface(IID_IAMCameraControl, (void**)&pIAMCameraControl);
+		if (FAILED(hr)) {
+			printf("Error\n");
+			return false;
+		}
+		else
+		{
+			long CurrVal, Min, Max, SteppingDelta, Default, CapsFlags, AvailableCapsFlags;
+			pIAMCameraControl->GetRange(Property, &Min, &Max, &SteppingDelta, &Default, &AvailableCapsFlags);
+			if (verbose) printf("Range for video setting %ld: Min:%ld Max:%ld SteppingDelta:%ld Default:%ld Flags:%ld\n", Property, Min, Max, SteppingDelta, Default, AvailableCapsFlags);
+			pIAMCameraControl->Get(Property, &CurrVal, &CapsFlags);
+			if (verbose) printf("Current value: %ld Flags %ld (%s)\n", CurrVal, CapsFlags, (CapsFlags == 1 ? "Auto" : (CapsFlags == 2 ? "Manual" : "Unknown")));
+			if (useDefaultValue) {
+				pIAMCameraControl->Set(Property, Default, CameraControl_Flags_Auto);
+			}
+			else
+			{
+				// Perhaps add a check that lValue and Flags are within the range aquired from GetRange above
+				pIAMCameraControl->Set(Property, lValue, Flags);
+			}
+			pIAMCameraControl->Release();
+			return true;
+		}
+	}
+	return false;
+}
+
+
+
+bool videoInput::getVideoSettingCamera(int deviceID, long Property, long &min, long &max, long &SteppingDelta, long &currentValue, long &flags, long &defaultValue){
+	if( !isDeviceSetup(deviceID) )return false;
+
+	HRESULT hr;	
+	bool isSuccessful = false;
+	
+	videoDevice * VD = VDList[deviceID];
+	
+	hr = getDevice(&VD->pVideoInputFilter, deviceID, VD->wDeviceName, VD->nDeviceName);	
+	if (FAILED(hr)){
+		printf("setVideoSetting - getDevice Error\n");
+		return false;
+	}
+
+	IAMCameraControl *pIAMCameraControl = NULL;
+	
+	hr = VD->pVideoInputFilter->QueryInterface(IID_IAMCameraControl, (void**)&pIAMCameraControl);
+	if(FAILED(hr)){
+		printf("setVideoSetting - QueryInterface Error\n");
+		if(VD->pVideoInputFilter)VD->pVideoInputFilter->Release();
+		if(VD->pVideoInputFilter)VD->pVideoInputFilter = NULL;		
+		return false;			
+	}
+	
+	if (verbose) printf("Setting video setting %ld.\n", Property);
+	
+	pIAMCameraControl->GetRange(Property, &min, &max, &SteppingDelta, &defaultValue, &flags);
+	if (verbose) printf("Range for video setting %ld: Min:%ld Max:%ld SteppingDelta:%ld Default:%ld Flags:%ld\n", Property, min, max, SteppingDelta, defaultValue, flags);
+	pIAMCameraControl->Get(Property, &currentValue, &flags);
+	
+	if(pIAMCameraControl)pIAMCameraControl->Release();
+	if(VD->pVideoInputFilter)VD->pVideoInputFilter->Release();
+	if(VD->pVideoInputFilter)VD->pVideoInputFilter = NULL;	
+			
+	return true;
+	
+}
+
+
+// ---------------------------------------------------------------------- 
+// Shutsdown the device, deletes the object and creates a new object
+// so it is ready to be setup again                                          
+// ---------------------------------------------------------------------- 
+
+void videoInput::stopDevice(int id){
+	if(id < VI_MAX_CAMERAS)
+	{	
+		delete VDList[id];
+		VDList[id] = new videoDevice();
+	}
+
+}
+
+// ---------------------------------------------------------------------- 
+// Restarts the device with the same settings it was using
+//                                           
+// ---------------------------------------------------------------------- 
+
+bool videoInput::restartDevice(int id){
+	if(isDeviceSetup(id))
+	{
+		int conn	 	= VDList[id]->storeConn;
+		int tmpW	   	= VDList[id]->width;
+		int tmpH	   	= VDList[id]->height;
+
+		bool bFormat    = VDList[id]->specificFormat;
+		long format     = VDList[id]->formatType;
+
+		int nReconnect	= VDList[id]->nFramesForReconnect;
+		bool bReconnect = VDList[id]->autoReconnect;
+
+		unsigned long avgFrameTime = VDList[id]->requestedFrameTime;
+	
+		stopDevice(id);
+
+		//set our fps if needed
+		if( avgFrameTime != -1){
+			VDList[id]->requestedFrameTime = avgFrameTime;
+		}
+
+		if( setupDevice(id, tmpW, tmpH, conn) ){
+			//reapply the format - ntsc / pal etc
+			if( bFormat ){
+				setFormat(id, format);
+			}
+			if( bReconnect ){
+				setAutoReconnectOnFreeze(id, true, nReconnect);
+			}
+			return true;
+		}
+	}
+	return false;
+}
+
+// ---------------------------------------------------------------------- 
+// Shuts down all devices, deletes objects and unitializes com if needed
+//                                           
+// ---------------------------------------------------------------------- 
+videoInput::~videoInput(){
+	
+	for(int i = 0; i < VI_MAX_CAMERAS; i++)
+	{
+		delete VDList[i];
+	}
+	//Unitialize com
+	comUnInit();
+}
+
+
+//////////////////////////////  VIDEO INPUT  ////////////////////////////////
+////////////////////////////  PRIVATE METHODS  //////////////////////////////
+
+// ---------------------------------------------------------------------- 
+// We only should init com if it hasn't been done so by our apps thread
+// Use a static counter to keep track of other times it has been inited
+// (do we need to worry about multithreaded apps?)                                             
+// ---------------------------------------------------------------------- 
+
+bool videoInput::comInit(){
+	HRESULT hr = NULL;
+
+	//no need for us to start com more than once
+	if(comInitCount == 0 ){
+
+	    // Initialize the COM library.
+    	//CoInitializeEx so videoInput can run in another thread
+	#ifdef VI_COM_MULTI_THREADED
+		hr = CoInitializeEx(NULL,COINIT_MULTITHREADED);
+	#else 
+		hr = CoInitialize(NULL);
+	#endif
+		//this is the only case where there might be a problem
+		//if another library has started com as single threaded 
+		//and we need it multi-threaded - send warning but don't fail
+		if( hr == RPC_E_CHANGED_MODE){
+			 if(verbose)printf("SETUP - COM already setup - threaded VI might not be possible\n");
+		}
+	}
+
+	comInitCount++; 
+	return true;
+}
+
+
+// ---------------------------------------------------------------------- 
+// Same as above but to unitialize com, decreases counter and frees com 
+// if no one else is using it                                           
+// ---------------------------------------------------------------------- 
+
+bool videoInput::comUnInit(){
+	if(comInitCount > 0)comInitCount--;		//decrease the count of instances using com
+
+   	if(comInitCount == 0){
+   		CoUninitialize();	//if there are no instances left - uninitialize com
+		return true;	
+	}
+	
+	return false;
+}
+
+
+// ---------------------------------------------------------------------- 
+// This is the size we ask for - we might not get it though :)
+//                                            
+// ---------------------------------------------------------------------- 
+
+void videoInput::setAttemptCaptureSize(int id, int w, int h){
+	
+	VDList[id]->tryWidth    = w;
+	VDList[id]->tryHeight   = h;
+	VDList[id]->tryDiffSize = true;	
+	
+}
+
+
+// ---------------------------------------------------------------------- 
+// Set the connection type
+// (maybe move to private?)                                           
+// ---------------------------------------------------------------------- 
+
+void videoInput::setPhyCon(int id, int conn){
+
+		switch(conn){
+		
+			case 0:
+				VDList[id]->connection = PhysConn_Video_Composite;
+				break;
+			case 1:		
+				VDList[id]->connection = PhysConn_Video_SVideo;
+				break;
+			case 2:
+				VDList[id]->connection = PhysConn_Video_Tuner;
+				break;
+			case 3:
+				VDList[id]->connection = PhysConn_Video_USB;
+				break;	
+			case 4:
+				VDList[id]->connection = PhysConn_Video_1394;
+				break;	
+			default:
+				return; //if it is not these types don't set crossbar
+			break;
+		}
+
+		VDList[id]->storeConn	= conn;
+		VDList[id]->useCrossbar	= true;
+}
+
+
+// ---------------------------------------------------------------------- 
+// Check that we are not trying to setup a non-existant device
+// Then start the graph building!                                           
+// ---------------------------------------------------------------------- 
+
+bool videoInput::setup(int deviceNumber){
+    devicesFound = getDeviceCount();
+    
+ 	if(deviceNumber>devicesFound-1)
+    {	
+    	if(verbose)printf("SETUP: device[%i] not found - you have %i devices available\n", deviceNumber, devicesFound);
+    	if(devicesFound>=0) if(verbose)printf("SETUP: this means that the last device you can use is device[%i] \n",  devicesFound-1);
+    	return false;
+    }
+    
+    if(VDList[deviceNumber]->readyToCapture)
+    {
+    	if(verbose)printf("SETUP: can't setup, device %i is currently being used\n",VDList[deviceNumber]->myID);
+    	return false;
+    }
+    
+    HRESULT hr = start(deviceNumber, VDList[deviceNumber]);
+    if(hr == S_OK)return true;
+	else return false;
+}
+
+
+// ---------------------------------------------------------------------- 
+// Does both vertical buffer flipping and bgr to rgb swapping
+// You have any combination of those.
+// ---------------------------------------------------------------------- 
+
+void videoInput::processPixels(unsigned char * src, unsigned char * dst, int width, int height, bool bRGB, bool bFlip){
+	
+	int widthInBytes = width * 3;
+	int numBytes = widthInBytes * height;
+	
+	if(!bRGB){
+		
+		int x = 0;
+		int y = 0;
+	
+		if(bFlip){
+			for(int y = 0; y < height; y++){
+				memcpy(dst + (y * widthInBytes), src + ( (height -y -1) * widthInBytes), widthInBytes);	
+			}
+									
+		}else{
+			memcpy(dst, src, numBytes);
+		}
+	}else{
+		if(bFlip){
+			
+			int x = 0;
+			int y = (height - 1) * widthInBytes;
+			src += y;
+			
+			for(int i = 0; i < numBytes; i+=3){
+				if(x >= width){
+					x = 0;
+					src -= widthInBytes*2;
+				}
+				
+				*dst = *(src+2);
+				dst++;
+				
+				*dst = *(src+1);
+				dst++; 
+				
+				*dst = *src;
+				dst++; 
+				
+				src+=3;	
+				x++;		
+			}
+		}
+		else{						
+			for(int i = 0; i < numBytes; i+=3){
+				*dst = *(src+2);
+				dst++;
+				
+				*dst = *(src+1);
+				dst++; 
+				
+				*dst = *src;
+				dst++; 
+				
+				src+=3;			
+			}
+		}
+	}
+}
+
+
+//------------------------------------------------------------------------------------------
+void videoInput::getMediaSubtypeAsString(GUID type, char * typeAsString){
+
+	char tmpStr[8];
+	if( type == MEDIASUBTYPE_RGB24) sprintf(tmpStr, "RGB24");
+	else if(type == MEDIASUBTYPE_RGB32) sprintf(tmpStr, "RGB32");
+	else if(type == MEDIASUBTYPE_RGB555)sprintf(tmpStr, "RGB555");
+	else if(type == MEDIASUBTYPE_RGB565)sprintf(tmpStr, "RGB565");					
+	else if(type == MEDIASUBTYPE_YUY2) 	sprintf(tmpStr, "YUY2");
+	else if(type == MEDIASUBTYPE_YVYU) 	sprintf(tmpStr, "YVYU");
+	else if(type == MEDIASUBTYPE_YUYV) 	sprintf(tmpStr, "YUYV");
+	else if(type == MEDIASUBTYPE_IYUV) 	sprintf(tmpStr, "IYUV");
+	else if(type == MEDIASUBTYPE_UYVY)  sprintf(tmpStr, "UYVY");
+	else if(type == MEDIASUBTYPE_YV12)  sprintf(tmpStr, "YV12");
+	else if(type == MEDIASUBTYPE_YVU9)  sprintf(tmpStr, "YVU9");
+	else if(type == MEDIASUBTYPE_Y411) 	sprintf(tmpStr, "Y411");
+	else if(type == MEDIASUBTYPE_Y41P) 	sprintf(tmpStr, "Y41P");
+	else if(type == MEDIASUBTYPE_Y211)  sprintf(tmpStr, "Y211");
+	else if(type == MEDIASUBTYPE_AYUV) 	sprintf(tmpStr, "AYUV");
+	else if(type == MEDIASUBTYPE_Y800) 	sprintf(tmpStr, "Y800");  
+	else if(type == MEDIASUBTYPE_Y8)   	sprintf(tmpStr, "Y8");  
+	else if(type == MEDIASUBTYPE_GREY) 	sprintf(tmpStr, "GREY");  
+	else sprintf(tmpStr, "OTHER");
+
+	memcpy(typeAsString, tmpStr, sizeof(char)*8);
+}
+
+//-------------------------------------------------------------------------------------------
+static void findClosestSizeAndSubtype(videoDevice * VD, int widthIn, int heightIn, int &widthOut, int &heightOut, GUID & mediatypeOut){
+	HRESULT hr;
+	
+	//find perfect match or closest size
+	int nearW				= 9999999;
+	int nearH				= 9999999;
+	bool foundClosestMatch 	= true;
+
+	int iCount = 0; 
+	int iSize = 0;
+	hr = VD->streamConf->GetNumberOfCapabilities(&iCount, &iSize);
+
+	if (iSize == sizeof(VIDEO_STREAM_CONFIG_CAPS))
+	{
+		//For each format type RGB24 YUV2 etc
+	    for (int iFormat = 0; iFormat < iCount; iFormat++)
+	    {
+			VIDEO_STREAM_CONFIG_CAPS scc;
+			AM_MEDIA_TYPE *pmtConfig;
+			hr =  VD->streamConf->GetStreamCaps(iFormat, &pmtConfig, (BYTE*)&scc);
+			
+			if (SUCCEEDED(hr)){
+
+				//his is how many diff sizes are available for the format
+	            int stepX = scc.OutputGranularityX;
+	            int stepY = scc.OutputGranularityY;
+	       		
+	       		int tempW = 999999;
+	       		int tempH = 999999;
+		       		
+	       		//Don't want to get stuck in a loop
+	       		if(stepX < 1 || stepY < 1) continue;
+	       		
+	       		//if(verbose)printf("min is %i %i max is %i %i - res is %i %i \n", scc.MinOutputSize.cx, scc.MinOutputSize.cy,  scc.MaxOutputSize.cx,  scc.MaxOutputSize.cy, stepX, stepY);
+	       		//if(verbose)printf("min frame duration is %i  max duration is %i\n", scc.MinFrameInterval, scc.MaxFrameInterval);
+
+	       		bool exactMatch 	= false;
+	       		bool exactMatchX	= false;
+				bool exactMatchY	= false;
+		
+	            for(int x = scc.MinOutputSize.cx; x <= scc.MaxOutputSize.cx; x+= stepX){           	
+	            	//If we find an exact match
+	            	if( widthIn == x ){
+						exactMatchX = true;
+	            		tempW = x;			            		
+	            	}
+	            	//Otherwise lets find the closest match based on width
+	            	else if( abs(widthIn-x) < abs(widthIn-tempW) ){
+	            		tempW = x;			            		
+	            	}
+	            }	
+		            
+	            for(int y = scc.MinOutputSize.cy; y <= scc.MaxOutputSize.cy; y+= stepY){           	
+	            	//If we find an exact match
+	            	if( heightIn == y){
+						exactMatchY = true;
+	            		tempH = y;		    			            		
+	            	}
+	            	//Otherwise lets find the closest match based on height
+	            	else if( abs(heightIn-y) < abs(heightIn-tempH) ){
+	            		tempH = y;		    			            		
+	            	}
+	            }			           		            
+			               
+		        //see if we have an exact match!
+		        if(exactMatchX && exactMatchY){
+		        	foundClosestMatch = false;
+		        	exactMatch = true;
+
+					widthOut		= widthIn;
+					heightOut		= heightIn;
+					mediatypeOut	= pmtConfig->subtype;	
+		        }       
+			      	
+		      	//otherwise lets see if this filters closest size is the closest 
+		      	//available. the closest size is determined by the sum difference
+		    	//of the widths and heights
+		      	else if( abs(widthIn - tempW) + abs(heightIn - tempH)  < abs(widthIn - nearW) + abs(heightIn - nearH) )
+		      	{
+		      		nearW = tempW;
+		      		nearH = tempH;
+
+					widthOut		= nearW;
+					heightOut		= nearH;
+					mediatypeOut	= pmtConfig->subtype;	
+		      	}
+			               
+		        MyDeleteMediaType(pmtConfig);
+		            			     		            
+		        //If we have found an exact match no need to search anymore
+		        if(exactMatch)break;
+	        }
+	     }
+	}	
+
+}
+
+
+//---------------------------------------------------------------------------------------------------
+static bool setSizeAndSubtype(videoDevice * VD, int attemptWidth, int attemptHeight, GUID mediatype){
+	VIDEOINFOHEADER *pVih =  reinterpret_cast<VIDEOINFOHEADER*>(VD->pAmMediaType->pbFormat);
+
+	//store current size
+	int tmpWidth  = HEADER(pVih)->biWidth;
+	int tmpHeight = HEADER(pVih)->biHeight;	
+	AM_MEDIA_TYPE * tmpType = NULL;
+	
+	HRESULT	hr = VD->streamConf->GetFormat(&tmpType);
+	if(hr != S_OK)return false;
+
+	//set new size:
+	//width and height
+	HEADER(pVih)->biWidth  = attemptWidth;
+	HEADER(pVih)->biHeight = attemptHeight;	
+
+	VD->pAmMediaType->formattype = FORMAT_VideoInfo;
+	VD->pAmMediaType->majortype  = MEDIATYPE_Video; 
+	VD->pAmMediaType->subtype	 = mediatype;
+	
+	//buffer size
+	VD->pAmMediaType->lSampleSize = attemptWidth*attemptHeight*3;
+	
+	//set fps if requested 
+	if( VD->requestedFrameTime != -1){
+		pVih->AvgTimePerFrame = VD->requestedFrameTime;
+	}		
+
+	//okay lets try new size	
+	hr = VD->streamConf->SetFormat(VD->pAmMediaType);		  
+	if(hr == S_OK){
+		if( tmpType != NULL )MyDeleteMediaType(tmpType);
+		return true;
+	}else{
+		VD->streamConf->SetFormat(tmpType);		
+		if( tmpType != NULL )MyDeleteMediaType(tmpType);
+	}
+
+	return false;
+}
+
+// ---------------------------------------------------------------------- 
+// Where all the work happens!
+// Attempts to build a graph for the specified device                                   
+// ---------------------------------------------------------------------- 
+
+int videoInput::start(int deviceID, videoDevice *VD){
+
+	HRESULT hr 			= NULL;
+	VD->myID 			= deviceID;
+	VD->setupStarted	= true;
+    CAPTURE_MODE   		= PIN_CATEGORY_CAPTURE; //Don't worry - it ends up being preview (which is faster)
+	callbackSetCount 	= 1;  //make sure callback method is not changed after setup called
+
+    if(verbose)printf("SETUP: Setting up device %i\n",deviceID);
+
+	// CREATE THE GRAPH BUILDER //
+    // Create the filter graph manager and query for interfaces.
+    hr = CoCreateInstance(CLSID_CaptureGraphBuilder2, NULL, CLSCTX_INPROC_SERVER, IID_ICaptureGraphBuilder2, (void **)&VD->pCaptureGraph);
+    if (FAILED(hr))	// FAILED is a macro that tests the return value
+    {
+        if(verbose)printf("ERROR - Could not create the Filter Graph Manager\n");
+        return hr;
+    }
+    
+	//FITLER GRAPH MANAGER//
+    // Create the Filter Graph Manager.
+    hr = CoCreateInstance(CLSID_FilterGraph, 0, CLSCTX_INPROC_SERVER,IID_IGraphBuilder, (void**)&VD->pGraph);
+    if (FAILED(hr))
+    {
+		if(verbose)printf("ERROR - Could not add the graph builder!\n");
+	    stopDevice(deviceID);
+        return hr;
+	}
+    
+    //SET THE FILTERGRAPH//
+    hr = VD->pCaptureGraph->SetFiltergraph(VD->pGraph);
+	if (FAILED(hr))
+    {
+		if(verbose)printf("ERROR - Could not set filtergraph\n");
+	    stopDevice(deviceID);
+        return hr;
+	}
+
+	//MEDIA CONTROL (START/STOPS STREAM)//
+	// Using QueryInterface on the graph builder, 
+    // Get the Media Control object.
+    hr = VD->pGraph->QueryInterface(IID_IMediaControl, (void **)&VD->pControl);
+    if (FAILED(hr))
+    {
+        if(verbose)printf("ERROR - Could not create the Media Control object\n");
+       	stopDevice(deviceID);
+        return hr;
+    }
+        
+    
+	//FIND VIDEO DEVICE AND ADD TO GRAPH//
+	//gets the device specified by the second argument.  
+	hr = getDevice(&VD->pVideoInputFilter, deviceID, VD->wDeviceName, VD->nDeviceName);
+
+	if (SUCCEEDED(hr)){
+		if(verbose)printf("SETUP: %s\n", VD->nDeviceName);
+		hr = VD->pGraph->AddFilter(VD->pVideoInputFilter, VD->wDeviceName);
+	}else{
+        if(verbose)printf("ERROR - Could not find specified video device\n");
+        stopDevice(deviceID);
+        return hr;		
+	}
+
+	//LOOK FOR PREVIEW PIN IF THERE IS NONE THEN WE USE CAPTURE PIN AND THEN SMART TEE TO PREVIEW
+	IAMStreamConfig *streamConfTest = NULL;
+    hr = VD->pCaptureGraph->FindInterface(&PIN_CATEGORY_PREVIEW, &MEDIATYPE_Video, VD->pVideoInputFilter, IID_IAMStreamConfig, (void **)&streamConfTest);		
+	if(FAILED(hr)){
+		if(verbose)printf("SETUP: Couldn't find preview pin using SmartTee\n");
+	}else{
+		 CAPTURE_MODE = PIN_CATEGORY_PREVIEW;
+		 streamConfTest->Release();
+		 streamConfTest = NULL;
+	}
+
+	//CROSSBAR (SELECT PHYSICAL INPUT TYPE)//
+	//my own function that checks to see if the device can support a crossbar and if so it routes it.  
+	//webcams tend not to have a crossbar so this function will also detect a webcams and not apply the crossbar 
+	if(VD->useCrossbar)
+	{
+		if(verbose)printf("SETUP: Checking crossbar\n");
+		routeCrossbar(&VD->pCaptureGraph, &VD->pVideoInputFilter, VD->connection, CAPTURE_MODE);
+	}
+
+
+	//we do this because webcams don't have a preview mode
+	hr = VD->pCaptureGraph->FindInterface(&CAPTURE_MODE, &MEDIATYPE_Video, VD->pVideoInputFilter, IID_IAMStreamConfig, (void **)&VD->streamConf);
+	if(FAILED(hr)){
+		if(verbose)printf("ERROR: Couldn't config the stream!\n");
+		stopDevice(deviceID);
+		return hr;
+	}
+	
+	//NOW LETS DEAL WITH GETTING THE RIGHT SIZE
+	hr = VD->streamConf->GetFormat(&VD->pAmMediaType);
+	if(FAILED(hr)){
+		if(verbose)printf("ERROR: Couldn't getFormat for pAmMediaType!\n");
+		stopDevice(deviceID);
+		return hr;
+	}
+
+	VIDEOINFOHEADER *pVih =  reinterpret_cast<VIDEOINFOHEADER*>(VD->pAmMediaType->pbFormat);
+	int currentWidth	=  HEADER(pVih)->biWidth;
+	int currentHeight	=  HEADER(pVih)->biHeight;
+
+	bool customSize = VD->tryDiffSize;
+	bool foundSize  = false;
+
+	if(customSize){
+		if(verbose)	printf("SETUP: Default Format is set to %i by %i \n", currentWidth, currentHeight);
+		
+		char guidStr[8];
+		for(int i = 0; i < VI_NUM_TYPES; i++){
+			
+			getMediaSubtypeAsString(mediaSubtypes[i], guidStr);
+
+			if(verbose)printf("SETUP: trying format %s @ %i by %i\n", guidStr, VD->tryWidth, VD->tryHeight);
+			if( setSizeAndSubtype(VD, VD->tryWidth, VD->tryHeight, mediaSubtypes[i]) ){
+				VD->setSize(VD->tryWidth, VD->tryHeight);
+				foundSize = true;
+				break;
+			}
+		}
+		
+		//if we didn't find the requested size - lets try and find the closest matching size
+		if( foundSize == false ){
+			if( verbose )printf("SETUP: couldn't find requested size - searching for closest matching size\n");
+
+			int closestWidth		= -1;
+			int closestHeight		= -1;
+			GUID newMediaSubtype;
+
+			findClosestSizeAndSubtype(VD, VD->tryWidth, VD->tryHeight, closestWidth, closestHeight, newMediaSubtype);
+				
+			if( closestWidth != -1 && closestHeight != -1){
+				getMediaSubtypeAsString(newMediaSubtype, guidStr);
+
+				if(verbose)printf("SETUP: closest supported size is %s @ %i %i\n", guidStr, closestWidth, closestHeight);
+				if( setSizeAndSubtype(VD, closestWidth, closestHeight, newMediaSubtype) ){
+					VD->setSize(closestWidth, closestHeight);
+					foundSize = true;
+				}
+			}
+		}
+	}
+	
+	//if we didn't specify a custom size or if we did but couldn't find it lets setup with the default settings
+	if(customSize == false || foundSize == false){
+		if( VD->requestedFrameTime != -1 ){
+			pVih->AvgTimePerFrame  = VD->requestedFrameTime;
+			hr = VD->streamConf->SetFormat(VD->pAmMediaType);		 
+		} 
+		VD->setSize(currentWidth, currentHeight);
+	}
+
+	//SAMPLE GRABBER (ALLOWS US TO GRAB THE BUFFER)//
+	// Create the Sample Grabber.
+	hr = CoCreateInstance(CLSID_SampleGrabber, NULL, CLSCTX_INPROC_SERVER,IID_IBaseFilter, (void**)&VD->pGrabberF);
+	if (FAILED(hr)){
+		if(verbose)printf("Could not Create Sample Grabber - CoCreateInstance()\n");
+		stopDevice(deviceID);
+		return hr;
+	}
+
+	hr = VD->pGraph->AddFilter(VD->pGrabberF, L"Sample Grabber");
+	if (FAILED(hr)){
+		if(verbose)printf("Could not add Sample Grabber - AddFilter()\n");
+		stopDevice(deviceID);
+		return hr;
+	}
+	
+	hr = VD->pGrabberF->QueryInterface(IID_ISampleGrabber, (void**)&VD->pGrabber);
+	if (FAILED(hr)){
+		if(verbose)printf("ERROR: Could not query SampleGrabber\n");
+		stopDevice(deviceID);
+		return hr;
+	}
+	
+		
+	//Set Params - One Shot should be false unless you want to capture just one buffer
+	hr = VD->pGrabber->SetOneShot(FALSE);
+	if(bCallback){ 
+		hr = VD->pGrabber->SetBufferSamples(FALSE);	
+	}else{
+		hr = VD->pGrabber->SetBufferSamples(TRUE);	
+	}
+		
+	if(bCallback){
+		//Tell the grabber to use our callback function - 0 is for SampleCB and 1 for BufferCB
+		//We use SampleCB
+		hr = VD->pGrabber->SetCallback(VD->sgCallback, 0); 
+		if (FAILED(hr)){
+			if(verbose)printf("ERROR: problem setting callback\n"); 
+			stopDevice(deviceID);
+			return hr;
+		}else{
+			if(verbose)printf("SETUP: Capture callback set\n");
+		}
+	}
+	
+	//MEDIA CONVERSION
+	//Get video properties from the stream's mediatype and apply to the grabber (otherwise we don't get an RGB image)	
+	//zero the media type - lets try this :) - maybe this works?
+	AM_MEDIA_TYPE mt;
+	ZeroMemory(&mt,sizeof(AM_MEDIA_TYPE));
+	
+	mt.majortype 	= MEDIATYPE_Video;
+	mt.subtype 		= MEDIASUBTYPE_RGB24;
+	mt.formattype 	= FORMAT_VideoInfo;
+	
+	//VD->pAmMediaType->subtype = VD->videoType; 
+	hr = VD->pGrabber->SetMediaType(&mt);
+	
+	//lets try freeing our stream conf here too 
+	//this will fail if the device is already running
+	if(VD->streamConf){
+		VD->streamConf->Release();
+		VD->streamConf = NULL;
+	}else{
+		if(verbose)printf("ERROR: connecting device - prehaps it is already being used?\n");
+		stopDevice(deviceID);
+		return S_FALSE;
+	}
+
+
+	//NULL RENDERER//
+	//used to give the video stream somewhere to go to.  
+	hr = CoCreateInstance(CLSID_NullRenderer, NULL, CLSCTX_INPROC_SERVER, IID_IBaseFilter, (void**)(&VD->pDestFilter));
+	if (FAILED(hr)){
+		if(verbose)printf("ERROR: Could not create filter - NullRenderer\n");
+		stopDevice(deviceID);
+		return hr;
+	}
+	
+	hr = VD->pGraph->AddFilter(VD->pDestFilter, L"NullRenderer");	
+	if (FAILED(hr)){
+		if(verbose)printf("ERROR: Could not add filter - NullRenderer\n");
+		stopDevice(deviceID);
+		return hr;
+	}
+	
+	//RENDER STREAM//
+	//This is where the stream gets put together. 
+	hr = VD->pCaptureGraph->RenderStream(&PIN_CATEGORY_PREVIEW, &MEDIATYPE_Video, VD->pVideoInputFilter, VD->pGrabberF, VD->pDestFilter);	
+
+	if (FAILED(hr)){
+		if(verbose)printf("ERROR: Could not connect pins - RenderStream()\n");
+		stopDevice(deviceID);
+		return hr;
+	}
+
+
+	//EXP - lets try setting the sync source to null - and make it run as fast as possible
+	{
+		IMediaFilter *pMediaFilter = 0;
+		hr = VD->pGraph->QueryInterface(IID_IMediaFilter, (void**)&pMediaFilter);
+		if (FAILED(hr)){
+			if(verbose)printf("ERROR: Could not get IID_IMediaFilter interface\n");
+		}else{
+			pMediaFilter->SetSyncSource(NULL);
+			pMediaFilter->Release();
+		}
+	}
+
+
+	//LETS RUN THE STREAM!
+	hr = VD->pControl->Run();
+
+	if (FAILED(hr)){
+		 if(verbose)printf("ERROR: Could not start graph\n");
+		 stopDevice(deviceID);
+		 return hr;
+	}
+	
+	
+	//MAKE SURE THE DEVICE IS SENDING VIDEO BEFORE WE FINISH
+	if(!bCallback){
+		
+		long bufferSize = VD->videoSize;
+		
+		while( hr != S_OK){
+			hr = VD->pGrabber->GetCurrentBuffer(&bufferSize, (long *)VD->pBuffer);
+			Sleep(10);
+		}
+	
+	}
+		
+	if(verbose)printf("SETUP: Device is setup and ready to capture.\n\n");
+	VD->readyToCapture = true;  
+		
+	//Release filters - seen someone else do this
+	//looks like it solved the freezes
+	
+	//if we release this then we don't have access to the settings
+	//we release our video input filter but then reconnect with it
+	//each time we need to use it
+	VD->pVideoInputFilter->Release();  		
+	VD->pVideoInputFilter = NULL;  		
+	
+	VD->pGrabberF->Release();
+	VD->pGrabberF = NULL;
+	
+	VD->pDestFilter->Release();
+	VD->pDestFilter = NULL;
+	
+	return S_OK;
+} 
+
+
+// ---------------------------------------------------------------------- 
+// Returns number of good devices
+//                                    
+// ---------------------------------------------------------------------- 
+
+int videoInput::getDeviceCount(){  
+
+    	
+	ICreateDevEnum *pDevEnum = NULL;
+	IEnumMoniker *pEnum = NULL;	
+	int deviceCounter = 0;
+	
+	HRESULT hr = CoCreateInstance(CLSID_SystemDeviceEnum, NULL,
+	    CLSCTX_INPROC_SERVER, IID_ICreateDevEnum, 
+	    reinterpret_cast<void**>(&pDevEnum));
+	    
+	    
+	if (SUCCEEDED(hr))
+	{
+	    // Create an enumerator for the video capture category.
+	    hr = pDevEnum->CreateClassEnumerator(
+	    	CLSID_VideoInputDeviceCategory,
+	        &pEnum, 0);
+	        
+	   if(hr == S_OK){
+			IMoniker *pMoniker = NULL;
+			while (pEnum->Next(1, &pMoniker, NULL) == S_OK){
+			    
+			    IPropertyBag *pPropBag;
+			    hr = pMoniker->BindToStorage(0, 0, IID_IPropertyBag, 
+			        (void**)(&pPropBag));
+			        
+			    if (FAILED(hr)){
+			        pMoniker->Release();
+			        continue;  // Skip this one, maybe the next one will work.
+			    } 
+			 
+			    pPropBag->Release();
+			    pPropBag = NULL;
+			    
+			    pMoniker->Release();
+			    pMoniker = NULL;
+			    
+			    deviceCounter++;
+			}   
+
+			pEnum->Release();
+			pEnum = NULL;
+		}
+
+		pDevEnum->Release();
+		pDevEnum = NULL;
+	}
+	return deviceCounter;	
+}
+   
+
+// ---------------------------------------------------------------------- 
+// Do we need this?  
+//    
+// Enumerate all of the video input devices
+// Return the filter with a matching friendly name                               
+// ----------------------------------------------------------------------   
+
+HRESULT videoInput::getDevice(IBaseFilter** gottaFilter, int deviceId, WCHAR * wDeviceName, char * nDeviceName){
+	BOOL done = false;
+	int deviceCounter = 0;
+
+	// Create the System Device Enumerator.
+	ICreateDevEnum *pSysDevEnum = NULL;
+	HRESULT hr = CoCreateInstance(CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC_SERVER, IID_ICreateDevEnum, (void **)&pSysDevEnum);
+	if (FAILED(hr))
+	{
+		return hr;
+	}
+
+	// Obtain a class enumerator for the video input category.
+	IEnumMoniker *pEnumCat = NULL;
+	hr = pSysDevEnum->CreateClassEnumerator(CLSID_VideoInputDeviceCategory, &pEnumCat, 0);
+
+	if (hr == S_OK) 
+	{
+		// Enumerate the monikers.
+		IMoniker *pMoniker = NULL;
+		ULONG cFetched;
+		while ((pEnumCat->Next(1, &pMoniker, &cFetched) == S_OK) && (!done))
+		{
+			if(deviceCounter == deviceId)
+			{
+				// Bind the first moniker to an object
+				IPropertyBag *pPropBag;
+				hr = pMoniker->BindToStorage(0, 0, IID_IPropertyBag, (void **)&pPropBag);
+				if (SUCCEEDED(hr))
+				{
+					// To retrieve the filter's friendly name, do the following:
+					VARIANT varName;
+					VariantInit(&varName);
+					hr = pPropBag->Read(L"FriendlyName", &varName, 0);
+					if (SUCCEEDED(hr))
+					{		
+						
+						//copy the name to nDeviceName & wDeviceName
+						int count = 0;
+						while( varName.bstrVal[count] != 0x00 ) {
+	                  		 wDeviceName[count] = varName.bstrVal[count];
+	                  		 nDeviceName[count] = (char)varName.bstrVal[count];
+	                  		 count++;
+	                 	}
+		                
+						// We found it, so send it back to the caller
+						hr = pMoniker->BindToObject(NULL, NULL, IID_IBaseFilter, (void**)gottaFilter);
+						done = true;
+					}
+					VariantClear(&varName);	
+					pPropBag->Release();
+					pPropBag = NULL;
+					pMoniker->Release();
+					pMoniker = NULL;
+				}
+			}
+			deviceCounter++;
+		}
+		pEnumCat->Release();
+		pEnumCat = NULL;
+	}
+	pSysDevEnum->Release();
+	pSysDevEnum = NULL;
+	
+	if (done) {
+		return hr;	// found it, return native error
+	} else {
+		return VFW_E_NOT_FOUND;	// didn't find it error
+	}
+}
+ 
+ 
+// ---------------------------------------------------------------------- 
+// Show the property pages for a filter
+// This is stolen from the DX9 SDK
+// ---------------------------------------------------------------------- 
+
+HRESULT videoInput::ShowFilterPropertyPages(IBaseFilter *pFilter){
+
+	ISpecifyPropertyPages *pProp;
+	HRESULT hr = pFilter->QueryInterface(IID_ISpecifyPropertyPages, (void **)&pProp);
+	if (SUCCEEDED(hr)) 
+	{
+		// Get the filter's name and IUnknown pointer.
+		FILTER_INFO FilterInfo;
+		hr = pFilter->QueryFilterInfo(&FilterInfo); 
+		IUnknown *pFilterUnk;
+		pFilter->QueryInterface(IID_IUnknown, (void **)&pFilterUnk);
+
+		// Show the page. 
+		CAUUID caGUID;
+		pProp->GetPages(&caGUID);
+		pProp->Release();
+		OleCreatePropertyFrame(
+			NULL,                   // Parent window
+			0, 0,                   // Reserved
+			FilterInfo.achName,     // Caption for the dialog box
+			1,                      // Number of objects (just the filter)
+			&pFilterUnk,            // Array of object pointers. 
+			caGUID.cElems,          // Number of property pages
+			caGUID.pElems,          // Array of property page CLSIDs
+			0,                      // Locale identifier
+			0, NULL                 // Reserved
+		);
+
+		// Clean up.
+		if(pFilterUnk)pFilterUnk->Release();
+		if(FilterInfo.pGraph)FilterInfo.pGraph->Release(); 
+		CoTaskMemFree(caGUID.pElems);
+	}
+	return hr;
+}
+   
+   
+// ---------------------------------------------------------------------- 
+// This code was also brazenly stolen from the DX9 SDK
+// Pass it a file name in wszPath, and it will save the filter graph to that file.
+// ---------------------------------------------------------------------- 
+
+HRESULT videoInput::SaveGraphFile(IGraphBuilder *pGraph, WCHAR *wszPath) {
+    const WCHAR wszStreamName[] = L"ActiveMovieGraph"; 
+    HRESULT hr;
+    IStorage *pStorage = NULL;
+
+	// First, create a document file which will hold the GRF file
+	hr = StgCreateDocfile(
+        wszPath,
+        STGM_CREATE | STGM_TRANSACTED | STGM_READWRITE | STGM_SHARE_EXCLUSIVE,
+        0, &pStorage);
+    if(FAILED(hr)) 
+    {
+        return hr;
+    }
+
+	// Next, create a stream to store.
+    IStream *pStream;
+    hr = pStorage->CreateStream(
+		wszStreamName,
+        STGM_WRITE | STGM_CREATE | STGM_SHARE_EXCLUSIVE,
+        0, 0, &pStream);
+    if (FAILED(hr)) 
+    {
+        pStorage->Release();    
+        return hr;
+    }
+
+	// The IPersistStream converts a stream into a persistent object.
+    IPersistStream *pPersist = NULL;
+    pGraph->QueryInterface(IID_IPersistStream, reinterpret_cast<void**>(&pPersist));
+    hr = pPersist->Save(pStream, TRUE);
+    pStream->Release();
+    pPersist->Release();
+    if (SUCCEEDED(hr)) 
+    {
+        hr = pStorage->Commit(STGC_DEFAULT);
+    }
+    pStorage->Release();
+    return hr;
+}
+
+
+// ---------------------------------------------------------------------- 
+// For changing the input types
+//
+// ----------------------------------------------------------------------  
+
+HRESULT videoInput::routeCrossbar(ICaptureGraphBuilder2 **ppBuild, IBaseFilter **pVidInFilter, int conType, GUID captureMode){
+    
+    //create local ICaptureGraphBuilder2
+	ICaptureGraphBuilder2 *pBuild = NULL;
+ 	pBuild = *ppBuild;
+ 	
+ 	//create local IBaseFilter
+ 	IBaseFilter *pVidFilter = NULL;
+ 	pVidFilter = * pVidInFilter;
+       
+	// Search upstream for a crossbar.
+	IAMCrossbar *pXBar1 = NULL;
+	HRESULT hr = pBuild->FindInterface(&LOOK_UPSTREAM_ONLY, NULL, pVidFilter,
+	        IID_IAMCrossbar, (void**)&pXBar1);
+	if (SUCCEEDED(hr)) 
+	{
+	    
+	    bool foundDevice = false;
+	    
+	    if(verbose)printf("SETUP: You are not a webcam! Setting Crossbar\n");
+	    pXBar1->Release();
+	    
+	    IAMCrossbar *Crossbar;
+	    hr = pBuild->FindInterface(&captureMode, &MEDIATYPE_Interleaved, pVidFilter, IID_IAMCrossbar, (void **)&Crossbar);
+	    
+	    if(hr != NOERROR){
+	        hr = pBuild->FindInterface(&captureMode, &MEDIATYPE_Video, pVidFilter, IID_IAMCrossbar, (void **)&Crossbar);
+		}
+
+		LONG lInpin, lOutpin;
+		hr = Crossbar->get_PinCounts(&lOutpin , &lInpin); 
+				
+		BOOL IPin=TRUE; LONG pIndex=0 , pRIndex=0 , pType=0;
+		
+		while( pIndex < lInpin)
+		{
+			hr = Crossbar->get_CrossbarPinInfo( IPin , pIndex , &pRIndex , &pType); 
+		
+			if( pType == conType){
+					if(verbose)printf("SETUP: Found Physical Interface");				
+					
+					switch(conType){
+
+						case PhysConn_Video_Composite:
+							if(verbose)printf(" - Composite\n");
+							break;
+						case PhysConn_Video_SVideo:	
+							if(verbose)printf(" - S-Video\n");	
+							break;
+						case PhysConn_Video_Tuner:
+							if(verbose)printf(" - Tuner\n");
+							break;
+						case PhysConn_Video_USB:
+							 if(verbose)printf(" - USB\n");
+							break;	
+						case PhysConn_Video_1394:
+							if(verbose)printf(" - Firewire\n");
+							break;
+					}				
+							
+				foundDevice = true;
+				break;
+			}
+			pIndex++;
+		
+		}
+		
+		if(foundDevice){
+			BOOL OPin=FALSE; LONG pOIndex=0 , pORIndex=0 , pOType=0;
+			while( pOIndex < lOutpin)
+			{
+				hr = Crossbar->get_CrossbarPinInfo( OPin , pOIndex , &pORIndex , &pOType); 
+				if( pOType == PhysConn_Video_VideoDecoder)
+					break;
+			}
+			Crossbar->Route(pOIndex,pIndex); 
+		}else{
+			if(verbose)printf("SETUP: Didn't find specified Physical Connection type. Using Defualt. \n");	
+		}			
+		
+		//we only free the crossbar when we close or restart the device
+		//we were getting a crash otherwise
+	    //if(Crossbar)Crossbar->Release();
+		//if(Crossbar)Crossbar = NULL;
+			
+		if(pXBar1)pXBar1->Release();
+		if(pXBar1)pXBar1 = NULL;
+		
+	}else{
+		if(verbose)printf("SETUP: You are a webcam or snazzy firewire cam! No Crossbar needed\n");
+		return hr;
+	}
+	
+	return hr;
+}
+   
diff --git a/src/creavision/videoInput.h b/src/creavision/videoInput.h
new file mode 100755
index 0000000..1f756ed
--- /dev/null
+++ b/src/creavision/videoInput.h
@@ -0,0 +1,385 @@
+#ifndef _VIDEOINPUT
+#define _VIDEOINPUT
+
+//THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+//IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+//FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+//AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+//LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+//OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+//THE SOFTWARE.
+
+//////////////////////////////////////////////////////////
+//Written by Theodore Watson - theo.watson at gmail.com    //
+//Do whatever you want with this code but if you find   //
+//a bug or make an improvement I would love to know!    //
+//														//
+//Warning This code is experimental 					//
+//use at your own risk :)								//
+//////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////
+/*                     Shoutouts 
+
+Thanks to: 
+			
+		   Dillip Kumar Kara for crossbar code.
+		   Zachary Lieberman for getting me into this stuff
+		   and for being so generous with time and code.
+		   The guys at Potion Design for helping me with VC++
+		   Josh Fisher for being a serious C++ nerd :)
+		   Golan Levin for helping me debug the strangest 
+		   and slowest bug in the world!
+		   
+		   And all the people using this library who send in 
+		   bugs, suggestions and improvements who keep me working on 
+		   the next version - yeah thanks a lot ;)
+		   
+*/
+/////////////////////////////////////////////////////////
+
+
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <math.h>
+#include <string.h>
+#include <wchar.h>
+
+//this is for TryEnterCriticalSection
+#ifndef _WIN32_WINNT
+	#   define _WIN32_WINNT 0x400
+#endif
+#include <windows.h>
+
+
+//Example Usage
+/*
+	//create a videoInput object
+	videoInput VI;
+	
+	//Prints out a list of available devices and returns num of devices found
+	int numDevices = VI.listDevices();	
+	
+	int device1 = 0;  //this could be any deviceID that shows up in listDevices
+	int device2 = 1;  //this could be any deviceID that shows up in listDevices
+	
+	//if you want to capture at a different frame rate (default is 30) 
+	//specify it here, you are not guaranteed to get this fps though.
+	//VI.setIdealFramerate(dev, 60);	
+	
+	//setup the first device - there are a number of options:
+	
+	VI.setupDevice(device1); 						  //setup the first device with the default settings
+	//VI.setupDevice(device1, VI_COMPOSITE); 			  //or setup device with specific connection type
+	//VI.setupDevice(device1, 320, 240);				  //or setup device with specified video size
+	//VI.setupDevice(device1, 320, 240, VI_COMPOSITE);  //or setup device with video size and connection type
+
+	//VI.setFormat(device1, VI_NTSC_M);					//if your card doesn't remember what format it should be
+														//call this with the appropriate format listed above
+														//NOTE: must be called after setupDevice!
+	
+	//optionally setup a second (or third, fourth ...) device - same options as above
+	VI.setupDevice(device2); 						  
+
+	//As requested width and height can not always be accomodated
+	//make sure to check the size once the device is setup
+
+	int width 	= VI.getWidth(device1);
+	int height 	= VI.getHeight(device1);
+	int size	= VI.getSize(device1);
+	
+	unsigned char * yourBuffer1 = new unsigned char[size];
+	unsigned char * yourBuffer2 = new unsigned char[size];
+	
+	//to get the data from the device first check if the data is new
+	if(VI.isFrameNew(device1)){
+		VI.getPixels(device1, yourBuffer1, false, false);	//fills pixels as a BGR (for openCV) unsigned char array - no flipping
+		VI.getPixels(device1, yourBuffer2, true, true); 	//fills pixels as a RGB (for openGL) unsigned char array - flipping!
+	}
+	
+	//same applies to device2 etc
+	
+	//to get a settings dialog for the device
+	VI.showSettingsWindow(device1);
+	
+	
+	//Shut down devices properly
+	VI.stopDevice(device1);
+	VI.stopDevice(device2);
+*/
+
+
+//////////////////////////////////////   VARS AND DEFS   //////////////////////////////////
+
+
+//STUFF YOU CAN CHANGE
+
+//change for verbose debug info
+static bool verbose = true;
+
+//if you need VI to use multi threaded com
+#define VI_COM_MULTI_THREADED
+
+//STUFF YOU DON'T CHANGE
+
+//videoInput defines
+#define VI_VERSION	 0.1995
+#define VI_MAX_CAMERAS  20
+#define VI_NUM_TYPES    18 //DON'T TOUCH
+#define VI_NUM_FORMATS  18 //DON'T TOUCH
+
+//defines for setPhyCon - tuner is not as well supported as composite and s-video 
+#define VI_COMPOSITE 0
+#define VI_S_VIDEO   1
+#define VI_TUNER     2
+#define VI_USB       3
+#define VI_1394		 4
+
+//defines for formats
+#define VI_NTSC_M	0
+#define VI_PAL_B	1
+#define VI_PAL_D	2
+#define VI_PAL_G	3
+#define VI_PAL_H	4
+#define VI_PAL_I	5
+#define VI_PAL_M	6
+#define VI_PAL_N	7
+#define VI_PAL_NC	8
+#define VI_SECAM_B	9
+#define VI_SECAM_D	10
+#define VI_SECAM_G	11
+#define VI_SECAM_H	12
+#define VI_SECAM_K	13
+#define VI_SECAM_K1	14
+#define VI_SECAM_L	15
+#define VI_NTSC_M_J	16
+#define VI_NTSC_433	17
+
+
+//allows us to directShow classes here with the includes in the cpp
+struct ICaptureGraphBuilder2;
+struct IGraphBuilder;
+struct IBaseFilter;
+struct IAMCrossbar;
+struct IMediaControl;
+struct ISampleGrabber;
+struct IMediaEventEx;
+struct IAMStreamConfig;
+struct _AMMediaType;
+class SampleGrabberCallback;
+typedef _AMMediaType AM_MEDIA_TYPE;
+
+//keeps track of how many instances of VI are being used
+//don't touch
+static int comInitCount = 0;
+
+
+////////////////////////////////////////   VIDEO DEVICE   ///////////////////////////////////
+
+class videoDevice{
+
+	
+	public:
+		 
+		videoDevice();
+		void setSize(int w, int h);
+		void NukeDownstream(IBaseFilter *pBF);
+		void destroyGraph();
+		~videoDevice();
+		
+		int videoSize;
+		int width;
+		int height;
+		int tryWidth;
+		int tryHeight;
+		
+		ICaptureGraphBuilder2 *pCaptureGraph;	// Capture graph builder object
+		IGraphBuilder *pGraph;					// Graph builder object
+	    IMediaControl *pControl;				// Media control object
+		IBaseFilter *pVideoInputFilter;  		// Video Capture filter
+		IBaseFilter *pGrabberF;
+		IBaseFilter * pDestFilter;
+		IAMStreamConfig *streamConf;
+		ISampleGrabber * pGrabber;    			// Grabs frame
+		AM_MEDIA_TYPE * pAmMediaType;
+		
+		IMediaEventEx * pMediaEvent;
+		
+		GUID videoType;
+		long formatType;
+		
+		SampleGrabberCallback * sgCallback;				
+		
+		bool tryDiffSize;
+		bool useCrossbar;
+		bool readyToCapture;
+		bool sizeSet;
+		bool setupStarted;
+		bool specificFormat;
+		bool autoReconnect;
+		int  nFramesForReconnect;
+		unsigned long nFramesRunning;
+		int  connection;
+		int	 storeConn;
+		int  myID;
+		long requestedFrameTime; //ie fps
+		
+		char 	nDeviceName[255];
+		WCHAR 	wDeviceName[255];
+		
+		unsigned char * pixels;
+		char * pBuffer;
+
+};
+
+
+
+
+//////////////////////////////////////   VIDEO INPUT   /////////////////////////////////////
+
+
+
+class videoInput{
+
+	public:
+		videoInput();
+		~videoInput();
+				
+		//turns off console messages - default is to print messages
+		static void setVerbose(bool _verbose);
+		
+		//Functions in rough order they should be used.
+		static int listDevices(bool silent = false);
+
+		//needs to be called after listDevices - otherwise returns NULL
+		static char * getDeviceName(int deviceID);
+		
+		//choose to use callback based capture - or single threaded
+		void setUseCallback(bool useCallback);	
+		
+		//call before setupDevice
+		//directshow will try and get the closest possible framerate to what is requested
+		void setIdealFramerate(int deviceID, int idealFramerate);
+
+		//some devices will stop delivering frames after a while - this method gives you the option to try and reconnect
+		//to a device if videoInput detects that a device has stopped delivering frames. 
+		//you MUST CALL isFrameNew every app loop for this to have any effect
+		void setAutoReconnectOnFreeze(int deviceNumber, bool doReconnect, int numMissedFramesBeforeReconnect);
+		
+		//Choose one of these four to setup your device
+		bool setupDevice(int deviceID);
+		bool setupDevice(int deviceID, int w, int h);
+
+		//These two are only for capture cards
+		//USB and Firewire cameras souldn't specify connection 
+		bool setupDevice(int deviceID, int connection);	
+		bool setupDevice(int deviceID, int w, int h, int connection); 
+		
+		//If you need to you can set your NTSC/PAL/SECAM
+		//preference here. if it is available it will be used.
+		//see #defines above for available formats - eg VI_NTSC_M or VI_PAL_B
+		//should be called after setupDevice
+		//can be called multiple times
+		bool setFormat(int deviceNumber, int format);	
+				
+		//Tells you when a new frame has arrived - you should call this if you have specified setAutoReconnectOnFreeze to true
+		bool isFrameNew(int deviceID); 
+		
+		bool isDeviceSetup(int deviceID);
+		    
+		//Returns the pixels - flipRedAndBlue toggles RGB/BGR flipping - and you can flip the image too
+		unsigned char * getPixels(int deviceID, bool flipRedAndBlue = true, bool flipImage = false);
+		
+		//Or pass in a buffer for getPixels to fill returns true if successful.
+		bool getPixels(int id, unsigned char * pixels, bool flipRedAndBlue = true, bool flipImage = false);
+		
+		//Launches a pop up settings window
+		//For some reason in GLUT you have to call it twice each time. 
+		void showSettingsWindow(int deviceID);
+		
+		//Manual control over settings thanks..... 
+		//These are experimental for now.
+		bool setVideoSettingFilter(int deviceID, long Property, long lValue, long Flags = NULL, bool useDefaultValue = false);
+		bool setVideoSettingFilterPct(int deviceID, long Property, float pctValue, long Flags = NULL);
+		bool getVideoSettingFilter(int deviceID, long Property, long &min, long &max, long &SteppingDelta, long &currentValue, long &flags, long &defaultValue);
+
+		bool setVideoSettingCamera(int deviceID, long Property, long lValue, long Flags = NULL, bool useDefaultValue = false);
+		bool setVideoSettingCameraPct(int deviceID, long Property, float pctValue, long Flags = NULL);
+		bool getVideoSettingCamera(int deviceID, long Property, long &min, long &max, long &SteppingDelta, long &currentValue, long &flags, long &defaultValue);
+
+		//bool setVideoSettingCam(int deviceID, long Property, long lValue, long Flags = NULL, bool useDefaultValue = false);
+
+		//get width, height and number of pixels
+		int  getWidth(int deviceID);
+		int  getHeight(int deviceID);
+		int  getSize(int deviceID);
+		
+		//completely stops and frees a device
+		void stopDevice(int deviceID);
+		
+		//as above but then sets it up with same settings
+		bool restartDevice(int deviceID);
+		
+		//number of devices available
+		int  devicesFound;
+		
+		long propBrightness;
+		long propContrast;
+		long propHue;
+		long propSaturation;
+		long propSharpness;
+		long propGamma;
+		long propColorEnable;
+		long propWhiteBalance;
+		long propBacklightCompensation;
+		long propGain;
+
+		long propPan;
+		long propTilt;
+		long propRoll;
+		long propZoom;
+		long propExposure;
+		long propIris;
+		long propFocus;
+				
+		
+	private:		
+		void setPhyCon(int deviceID, int conn);                   
+		void setAttemptCaptureSize(int deviceID, int w, int h);   
+		bool setup(int deviceID);
+		void processPixels(unsigned char * src, unsigned char * dst, int width, int height, bool bRGB, bool bFlip);
+		int  start(int deviceID, videoDevice * VD);                   
+		int  getDeviceCount();
+		void getMediaSubtypeAsString(GUID type, char * typeAsString);
+		
+		HRESULT getDevice(IBaseFilter **pSrcFilter, int deviceID, WCHAR * wDeviceName, char * nDeviceName);
+		static HRESULT ShowFilterPropertyPages(IBaseFilter *pFilter);
+		HRESULT SaveGraphFile(IGraphBuilder *pGraph, WCHAR *wszPath);
+		HRESULT routeCrossbar(ICaptureGraphBuilder2 **ppBuild, IBaseFilter **pVidInFilter, int conType, GUID captureMode);
+			
+		//don't touch
+		static bool comInit();
+		static bool comUnInit();
+
+		int  connection;
+		int  callbackSetCount;
+		bool bCallback;
+		
+		GUID CAPTURE_MODE;
+		
+		//Extra video subtypes
+		GUID MEDIASUBTYPE_Y800;
+		GUID MEDIASUBTYPE_Y8;
+		GUID MEDIASUBTYPE_GREY;
+
+		videoDevice * VDList[VI_MAX_CAMERAS];
+		GUID mediaSubtypes[VI_NUM_TYPES];
+		long formatTypes[VI_NUM_FORMATS];
+
+		static void __cdecl basicThread(void * objPtr);
+
+		static char deviceNames[VI_MAX_CAMERAS][255];
+
+}; 
+  
+ #endif
diff --git a/src/host/CMakeLists.txt b/src/host/CMakeLists.txt
new file mode 100644
index 0000000..197d3f9
--- /dev/null
+++ b/src/host/CMakeLists.txt
@@ -0,0 +1,64 @@
+cmake_minimum_required(VERSION 2.6)
+project(sphost)
+
+set (SPHOST_MAJOR_VERSION 1)
+set (SPHOST_RELEASE_VERSION 0)
+set (SPHOST_EPOCH_VERSION 0)
+
+set(sphost_HEADERS
+	${CUSTOM_INCLUDE_PATH}/sphost/componenthelper.h
+	${CUSTOM_INCLUDE_PATH}/sphost/configutils.h
+	${CUSTOM_INCLUDE_PATH}/sphost/libimpexp_sphost.h
+	${CUSTOM_INCLUDE_PATH}/sphost/paths.h
+	${CUSTOM_INCLUDE_PATH}/sphost/testcommon.h
+)
+
+set(sphost_SRCS
+	${sphost_HEADERS}
+	componenthelper.cpp	
+	configutils.cpp
+	paths.cpp
+	testcommon.cpp
+)
+
+if (ENABLE_NLS)
+set(sphost_SRCS 
+	${sphost_SRCS}
+	${CUSTOM_INCLUDE_PATH}/sphost/langutils.h
+	langutils.cpp
+)
+endif(ENABLE_NLS)
+
+# This library could be static
+
+add_library (sphost ${sphost_SRCS})
+
+target_link_libraries(sphost spcore)
+target_link_libraries(sphost widgets_base)
+
+# Boost
+find_package(Boost COMPONENTS filesystem thread system REQUIRED)
+target_link_libraries(sphost ${Boost_FILESYSTEM_LIBRARY})
+target_link_libraries(sphost ${Boost_THREAD_LIBRARY})
+target_link_libraries(sphost ${Boost_SYSTEM_LIBRARY})
+
+if (ENABLE_NLS)
+	target_link_libraries(sphost ${LIBINTL_LIBRARIES})
+	install (FILES ${CUSTOM_INCLUDE_PATH}/sphost/langutils.h DESTINATION ${INCLUDEDIR}/${PROJECT_NAME})
+endif(ENABLE_NLS)
+
+IF(BUILD_SHARED_LIBS)
+	add_definitions(-DSPMAKING_DLL_SPHOST)
+	add_definitions(-DSPUSING_DLL)
+
+	set_target_properties(sphost PROPERTIES 
+		VERSION "${SPHOST_MAJOR_VERSION}.${SPHOST_RELEASE_VERSION}.${SPHOST_EPOCH_VERSION}"
+		SOVERSION ${SPHOST_MAJOR_VERSION}
+	)
+	INSTALL (TARGETS sphost RUNTIME DESTINATION ${LIBRUNTIMEDIR} LIBRARY DESTINATION ${LIBDIR} ARCHIVE DESTINATION ${LIBDIR})
+ELSE(BUILD_SHARED_LIBS)
+	INSTALL (TARGETS sphost DESTINATION ${LIBDIR})
+ENDIF(BUILD_SHARED_LIBS)
+
+
+install (FILES ${sphost_HEADERS} DESTINATION ${INCLUDEDIR}/${PROJECT_NAME})
diff --git a/src/host/componenthelper.cpp b/src/host/componenthelper.cpp
new file mode 100644
index 0000000..a6dbf5a
--- /dev/null
+++ b/src/host/componenthelper.cpp
@@ -0,0 +1,1322 @@
+/////////////////////////////////////////////////////////////////////////////
+// File:        componenthelper.cpp
+// Author:      Cesar Mauri Loba (cesar at crea-si dot com)
+// Copyright:   (C) 2011 Cesar Mauri Loba - CREA Software Systems
+//
+//  This program is free software: you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation, either version 3 of the License, or
+//  (at your option) any later version.
+//
+//  This program is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+/////////////////////////////////////////////////////////////////////////////
+#include "sphost/componenthelper.h"
+#include "spcore/pin.h"
+#include "spcore/language.h"
+
+#include <string>
+#include <boost/algorithm/string.hpp>
+#include <boost/lexical_cast.hpp>
+#include <iostream>
+#include <fstream>
+#include <vector>
+#include <map>
+#include <stack>
+#include <set>
+#include <boost/shared_ptr.hpp>
+
+#ifdef WIN32
+#include <io.h>
+#define access(path,mode) _access(path,mode)
+#define R_OK    4               /* Test for read permission.  */
+#else
+#include <unistd.h>
+#endif
+
+#ifdef WIN32
+// TODO: remove the following line when boost gets updated
+// See: https://svn.boost.org/trac/boost/ticket/4649
+#pragma warning (disable:4127)
+#endif
+#include <boost/tokenizer.hpp>
+#include <boost/foreach.hpp>
+
+// wx includes
+// TODO: give away wx dependency
+#include <wx/panel.h>
+#include <wx/sizer.h>
+#include <wx/collpane.h>
+#include <wx/statbox.h>
+
+#include "widgets_base/containerpanel.h"
+#include "widgets_base/containerbook.h"
+#include "widgets_base/containercollapsible.h"
+
+using namespace spcore;
+using namespace std;
+using namespace boost;
+
+namespace sphost {
+
+/*
+	Comments about processing GUI layout.
+
+	Pass the list of strings to the script component and parse during
+	GUI construction. Add method to check syntax and semantics 
+	without actually building the GUI itself to detect errors ASAP
+
+	An intemediate representation (layout composite) would be great
+	when it comes to provide support for more than one GUI toolkit but
+	it requires to create an entire class hierarchy.
+*/
+
+/**
+	Struct to store lines of the script with context
+*/
+struct LineWithContext
+{
+	LineWithContext(const string& t, int ln, const string& f) 
+	: text(t), linenu(ln), file(f) {}
+
+	string text;
+	unsigned int linenu;
+	string file;
+};
+
+// Throw an error completing information
+static
+void ThrowError (const string & msg, unsigned int linenu, const char *line, const char* file) {
+	string error_msg(msg);
+
+	if (linenu) {
+		error_msg+= " line ";
+		error_msg+= boost::lexical_cast<std::string>(linenu);
+	}
+	if (line) {
+		error_msg+= "\n";
+		error_msg+= line;
+	}
+	if (file && file[0]!= 0) {
+		error_msg+= "\nfile ";
+		error_msg+= file;
+	}
+	throw parser_error(error_msg);
+}
+
+static
+void ThrowError (const string & msg, const LineWithContext* li)	{
+	if (li)
+		ThrowError (msg, li->linenu, li->text.c_str(), li->file.c_str());
+	else 
+		ThrowError (msg, 0, NULL, NULL);
+}
+
+static
+void ThrowPartialError (const string & msg) {
+	throw parser_partial_error(msg);
+}
+
+static
+void CheckNumTokens (const vector<string>& p, 
+	unsigned int min, unsigned int max, 
+	unsigned int linenum= 0, const string* line= NULL,
+	const string* file= NULL)		
+{
+	assert (p.size()> 0);
+	assert (max== 0 || min<= max);
+
+	string error_msg;
+
+	if (min> 0 && p.size()< min)
+		error_msg= "Not enough parameters for command " + p[0];
+	else if (max> 0 && p.size()> max)
+		error_msg= "Too many parameters for command " + p[0];
+	else 
+		return;
+
+	ThrowError (error_msg, linenum, (line? line->c_str() : NULL), (file? file->c_str() : NULL));
+}
+
+static
+void ExtractTokens (const string& s, vector<string>& result) {		
+	escaped_list_separator<char> sep("\\", "\t ", "\"'");
+	tokenizer<escaped_list_separator<char> > tok(s, sep);
+	BOOST_FOREACH(string t, tok) {
+		if (t.size()) result.push_back (t);
+	}
+}
+static
+void ArgumentSubstitution (	vector<string>& tokens, 
+						const map<string,string>& dict, 
+						vector<LineWithContext>::const_iterator& it_err)
+{
+	// Substitute tokens using the dictionary. The first token is not taken
+	// into account.
+
+	if (tokens.size()< 2) return;	// Nothing to do
+	
+	// Make iterator point to the second token
+	vector<string>::iterator it= tokens.begin();
+	++it;
+
+	while (it!= tokens.end()) {
+		//
+		// Argument substitution
+		//
+		bool changed= false;
+		size_t arg_index = 0, arg_size= 0;
+		while (true) {
+			// Locate substring
+			arg_index = it->find("$", arg_index);
+			if (arg_index== string::npos) break;
+			arg_size = it->find("$", arg_index + 1);	// Here returns the index, not size...
+			if (arg_size == string::npos)
+				ThrowError("Argument terminator $ not found", &(*it_err));
+			arg_size= arg_size - arg_index + 1;			// ... here computes the actual size
+			assert (arg_size>= 2);
+
+			// Extract arg name
+			string arg_name= it->substr(arg_index, arg_size);
+
+			// Dictionary look up
+			map<string, string>::const_iterator d_it;
+			d_it= dict.find (arg_name);
+			if (d_it== dict.end()) {
+				string error_msg("Argument ");
+				error_msg+= arg_name;
+				error_msg+= " not found";
+				ThrowError(error_msg, &(*it_err));
+			}
+			
+			// Make the replacement
+			it->replace(arg_index, arg_size, d_it->second);
+			changed= true;
+
+			// Make index point after substitution result
+			arg_index+= d_it->second.size();
+		}
+
+		//
+		// Fix tokenization
+		//
+		// As a result of substitution, the number of tokens could have changed
+		//
+		if (changed) {
+			trim(*it);
+			vector<string> newTokens;
+			try{
+				ExtractTokens (*it, newTokens);
+			}
+			catch(std::exception& e) {
+				ThrowError (e.what(), &(*it_err));
+			}
+			if (newTokens.size()== 0)
+				// Remove token
+				it= tokens.erase (it);
+			else {
+				// One or more tokens
+				*it= newTokens[0];
+				++it;
+				
+				for (unsigned int i= 1; i< newTokens.size(); ++i) {
+					it= tokens.insert(it, newTokens[i]);
+					assert (it!= tokens.end());
+					++it;
+				}
+			}
+		}
+		else 
+			++it;
+	}
+}
+
+static
+int SearchBeginTranslatable(const string& src, unsigned int pos)
+{
+	for (; pos< src.size(); ++pos) {
+		if (src[pos]== '\\') {
+			// Begin scape sequence ignore this character and the next one
+			pos++;
+		}
+		else if (src[pos]== '_' && pos< src.size()-1 && src[pos+1]== '"') return pos;
+	}
+
+	return -1;
+}
+
+static
+int SearchEndTranslatable(const string& src, unsigned int pos)
+{
+	for (; pos< src.size(); ++pos) {
+		if (src[pos]== '\\') {
+			// Begin scape sequence ignore this character and the next one
+			pos++;
+		}
+		else if (src[pos]== '"') return pos;
+	}
+
+	return -1;
+}
+
+// check that the new translation is sane which 
+// which basically means that does not contain unscaped quotes
+// TODO: check that it is a valid utf-8 string
+// TODO: manage properly strings containing scaped quotes
+static
+bool TranslationIsSane(const char* src)
+{
+	if (!src) return false;
+
+	for (unsigned int i= 0; src[i]; ++i) {
+		if (src[i]== '\\') {
+			// Begin scape sequence ignore this character and the next one
+			++i;
+			if (src[i]== 0) return false;
+		}
+		else if (src[i]== '"') return false;
+	}
+	
+	return true;
+}
+
+// Translation of translatable strings. First token is never translated.
+static
+void PerformStringTranslation (string& src)
+{
+	unsigned int pos= 0;
+
+	for (;;) {
+		int pos_ini= SearchBeginTranslatable(src, pos);
+		if (pos_ini== -1) break;
+
+		// Translatable sequence start found
+		int pos_end= SearchEndTranslatable(src, pos_ini + 2);
+		if (pos_end== -1) break;
+
+		assert(pos_end> pos_ini+1);
+
+		// Translatable sequence end found
+		// pos_ini points to '_' and pos_end to the closing quote
+		int text_pos_ini= pos_ini + 2;
+		int text_size= pos_end - text_pos_ini;
+		
+		string text= src.substr(text_pos_ini, text_size);
+		const char* text_ptr= text.c_str();
+
+		const char* trans_ptr= __(text_ptr);
+		if (text_ptr!= trans_ptr) {
+			// Text has been translated,
+			if (!TranslationIsSane(trans_ptr)) trans_ptr= text_ptr;
+		}
+
+		// Substitute original content with translated version
+		string trans("\"");
+		trans+= trans_ptr;
+		trans+= "\"";
+
+		src.replace(pos_ini, pos_end - pos_ini + 1, trans);
+
+		pos= pos_ini + trans.size();
+	}
+}
+
+static
+IComponent* FindComponentByName (IComponent& c, const char * name, const LineWithContext* li) {
+	IComponent* retval= ComponentHelper::FindComponentByName (c, name, 1);
+	if (!retval) 
+		ThrowError (string("Component ") + name + " not found", li);
+	return retval;
+}
+
+static
+IInputPin* FindInputPin(IComponent& c, const char * name, const LineWithContext* li) {
+	IInputPin* ip= IComponent::FindInputPin(c, name);
+	if (!ip) 
+		ThrowError (string("Input pin ") + name + " not found for component " + c.GetName(), li);
+	return ip;
+}
+
+static
+IOutputPin* FindOutputPin(IComponent& c, const char * name, const LineWithContext* li) {
+	IOutputPin* op= IComponent::FindOutputPin(c, name);
+	if (!op) 
+		ThrowError (string("Output pin ") + name + " not found for component " + c.GetName(), li);
+	return op;
+}
+
+static
+string GetDirectory(const string& fullPath) {
+	// Get directory part
+	string dir;
+	size_t ipathend= fullPath.find_last_of("\\/");
+	if (ipathend!= string::npos)
+		// Found
+		dir= fullPath.substr(0, ipathend);
+
+	return dir;
+}
+
+/**
+	Class GUIContainer
+
+	Models a GUI container, which can be a window or a layout helper (sizer).
+	Does not take ownship of the actual window or sizer.
+*/
+
+class GUIContainer
+{
+	enum { BORDER_SIZE= 2 };
+public:
+	GUIContainer(wxObject* obj) : m_theObj(obj) {
+		// Can be constructed with NULL object in test mode
+#ifndef NDEBUG
+		if (obj) assert (IsWindow() || IsLayout());
+#endif
+	}
+
+	bool IsWindow() const {
+		assert (m_theObj);
+		return m_theObj->IsKindOf(wxClassInfo::FindClass(_T("wxWindow")));
+	}
+
+	bool IsLayout() const {
+		assert (m_theObj);
+		return m_theObj->IsKindOf(wxClassInfo::FindClass(_T("wxSizer")));
+	}
+
+	bool IsBook() const {
+		assert (m_theObj);
+		return m_theObj->IsKindOf(wxClassInfo::FindClass(_T("wxNotebook")));
+	}
+
+	// Get the pointer to the window object associated with the
+	// window or sizer
+	wxWindow* GetEffectiveWindow() {
+		assert (m_theObj);
+		if (IsLayout()) {
+			assert (!static_cast<wxSizer*>(m_theObj)->GetContainingWindow()->IsKindOf(wxClassInfo::FindClass(_T("wxStaticBox"))));
+			return static_cast<wxSizer*>(m_theObj)->GetContainingWindow();
+		}
+
+		// Is window
+		if (IsCollapsiblePane())
+			return static_cast<wxGenericCollapsiblePane*>(m_theObj)->GetPane();
+		else
+			return static_cast<wxWindow*>(m_theObj);
+	}
+
+	void AddChild (GUIContainer& cld, const LineWithContext* li) {
+		assert (m_theObj);
+		assert (cld.IsWindow() || cld.IsLayout());
+
+		if (IsWindow()) {
+			wxWindow* theWin= GetEffectiveWindow();
+			assert (theWin);
+
+			if (cld.IsLayout()) {
+				// Parent is a window and child is a sizer => set the window sizer
+				if (IsBook())
+					ThrowError ("Cannot set a layout to a book (a book page is needed)", li);
+				theWin->SetSizer(static_cast<wxSizer*>(cld.m_theObj));				
+			}
+			else {
+				// Parent is a window and child is window 
+				
+				// Check if is a book
+				if (IsBook()) {
+					wxNotebook* book= static_cast<wxNotebook*>(m_theObj);
+					book->AddPage(static_cast<wxWindow*>(cld.m_theObj), static_cast<wxWindow*>(cld.m_theObj)->GetName());
+				}
+				else {
+					// In other cases check is there is a sizer available and use it
+					wxSizer* sizer= GetEffectiveWindow()->GetSizer();
+					if (sizer)
+						sizer->Add(static_cast<wxWindow*>(cld.m_theObj), 0, wxALIGN_LEFT|wxALL, BORDER_SIZE);
+				}
+				
+				// make sure the parent-child relationship already exists
+				assert (cld.GetEffectiveWindow()->GetParent()== GetEffectiveWindow());
+			}
+		}
+		else {
+			// Parent is a sizer
+			if (cld.IsLayout()) {
+				// Parent is a sizer and child is a sizer
+				static_cast<wxSizer*>(m_theObj)->Add(static_cast<wxSizer*>(cld.m_theObj), 0, wxALIGN_LEFT|wxALL, BORDER_SIZE);
+			}
+			else {
+				// Parent is a sizer and child is a window
+				static_cast<wxSizer*>(m_theObj)->Add(static_cast<wxWindow*>(cld.m_theObj), 0, wxALIGN_LEFT|wxALL, BORDER_SIZE);
+			}
+		}
+	}
+
+private:
+
+	bool IsCollapsiblePane() const {
+		assert (m_theObj);
+		return	m_theObj->IsKindOf(wxClassInfo::FindClass(_T("wxGenericCollapsiblePane")));
+	}
+
+	wxObject* m_theObj;
+};
+
+/**
+	Component class used to return instances loaded from scripts
+*/
+class ScriptComponent : public CCompositeComponentAdapter {
+public:
+    ScriptComponent(const char * type, const char * name, int argc, const char * argv[])
+    : CCompositeComponentAdapter(name, argc, argv)
+	, m_type(type)
+	{}
+
+	virtual const char* GetTypeName() const {
+		return m_type.c_str();
+	}
+
+	int RegisterInputPin (IInputPin& ipin) {
+		return CCompositeComponentAdapter::RegisterInputPin(ipin);
+	}
+
+	int RegisterOutputPin (IOutputPin& opin) {
+		return CCompositeComponentAdapter::RegisterOutputPin(opin);
+	}
+
+	void AddLayoutLine (const LineWithContext& l) {
+		m_layoutLines.push_back(l);
+	}
+
+	virtual wxWindow* GetGUI(wxWindow * parent) {
+		wxWindow* panel= NULL;
+		try {
+			panel= GetGUI(parent, false);
+		}
+		catch(std::exception& e) {
+			getSpCoreRuntime()->LogMessage(ICoreRuntime::LOG_ERROR, e.what(), "");
+			if (panel) panel->Destroy();
+		}
+
+		return panel;
+	}
+
+	wxWindow* GetGUI(wxWindow * parent, bool test) {
+		if (m_layoutLines.size()== 0) return NULL;
+		
+		// We need a stack to parse nested sizers and containers
+		std::stack<GUIContainer> containerStack;
+
+		// Create panel
+		if (!test) {
+			widgets_base::ContainerPanel* panel= NULL;
+			panel= new widgets_base::ContainerPanel();
+			panel->Create(parent);
+			panel->SetName (wxString(GetName(), wxConvUTF8));
+			containerStack.push(GUIContainer(panel));
+		}
+		else
+			containerStack.push(GUIContainer(NULL));
+
+		// A set is used to ensure component are not place more than once
+		std::set<string> usedComponents;
+
+		// For each stored line
+		vector<LineWithContext>::const_iterator it= m_layoutLines.begin();
+		for (; it!= m_layoutLines.end(); ++it) {
+			//
+			// Parse line
+			//			
+			vector<string> t;
+			try {
+				ExtractTokens (it->text, t);
+			}
+			catch(std::exception& e) {
+				ThrowError (e.what(), &(*it));
+			}
+
+			assert (containerStack.size());
+
+			if (t[0]== "layout_begin") {
+				CheckNumTokens (t, 2, 3, it->linenu, &it->text, &it->file);
+
+				if (t[1]== "hbox") {
+					wxSizer* sizer= NULL;
+					if (!test) {
+						if (t.size()== 3) {
+							wxStaticBox* box= 
+								new wxStaticBox(containerStack.top().GetEffectiveWindow(), 
+									wxID_ANY, wxString(t[2].c_str(), wxConvUTF8));
+
+								sizer= new wxStaticBoxSizer(box, wxHORIZONTAL);
+						}
+						else
+							sizer= new wxBoxSizer(wxHORIZONTAL);
+						GUIContainer child(sizer);
+						containerStack.top().AddChild (child, &(*it));
+					}
+					GUIContainer child(sizer);
+					containerStack.push(child);
+				}
+				else if (t[1]== "vbox") {
+					wxSizer* sizer= NULL;
+					if (!test) {
+						if (t.size()== 3) {
+							wxStaticBox* box= 
+								new wxStaticBox(containerStack.top().GetEffectiveWindow(), 
+									wxID_ANY, wxString(t[2].c_str(), wxConvUTF8));
+
+								sizer= new wxStaticBoxSizer(box, wxVERTICAL);
+						}
+						else
+							sizer= new wxBoxSizer(wxVERTICAL);
+						GUIContainer child(sizer);
+						containerStack.top().AddChild (child, &(*it));
+					}
+					GUIContainer child(sizer);
+					containerStack.push(child);
+				}
+				else if (t[1]== "book") {
+					CheckNumTokens (t, 2, 2, it->linenu, &it->text, &it->file);
+					wxNotebook* notebook= NULL;
+					if (!test) {
+						notebook= new ContainerBook (containerStack.top().GetEffectiveWindow(), wxID_ANY);
+						GUIContainer child(notebook);
+						containerStack.top().AddChild (child, &(*it));
+					}
+					GUIContainer child(notebook);
+					containerStack.push(child);
+				}
+				else if (t[1]== "book_page") {
+					wxWindow* panel= NULL;
+					if (!test) {
+						if (!containerStack.top().IsBook())
+							ThrowError ("Statement book_page without book", &(*it));
+						panel= new widgets_base::ContainerPanel(containerStack.top().GetEffectiveWindow(), wxID_ANY);
+						// Set sizer
+						panel->SetSizer(new wxBoxSizer(wxVERTICAL));
+
+						// Provides name?
+						if (t.size()== 3)
+							panel->SetName(wxString(t[2].c_str(), wxConvUTF8));
+
+						GUIContainer child(panel);
+						containerStack.top().AddChild (child, &(*it));
+					}
+					GUIContainer child(panel);
+					containerStack.push(child);
+				}
+				else if (t[1]== "collapsible") {
+					wxGenericCollapsiblePane* panel= NULL;
+
+					if (!test) {
+						//panel= new wxGenericCollapsiblePane(containerStack.top().GetEffectiveWindow(), wxID_ANY, _("Advanced"));
+						panel= new widgets_base::ContainerCollapsible(containerStack.top().GetEffectiveWindow(), wxID_ANY, _("Advanced"));
+						GUIContainer child(panel);
+						containerStack.top().AddChild (child, &(*it));
+						// Provides label?
+						if (t.size()== 3)
+							panel->SetLabel(wxString(t[2].c_str(), wxConvUTF8));
+
+						// Set sizer
+						panel->GetPane()->SetSizer(new wxBoxSizer(wxVERTICAL));
+
+					}
+					GUIContainer child(panel);
+					containerStack.push(child);
+				}
+				else if (t[1]== "component") {
+					CheckNumTokens (t, 2, 3, it->linenu, &it->text, &it->file);
+
+					IComponent* compo= FindComponentByName (*this, t[2].c_str(), &(*it));
+					if (!compo) {
+						assert (test);
+						string error_msg("Component ");
+						error_msg+= t[2] + " not found";
+						ThrowError (error_msg, &(*it));
+					}
+
+					if (strcmp(compo->GetTypeName(), "widget_collapsible")!= 0) {
+						// Only widget_collapsible is supported
+						assert (test);
+						ThrowError ("Only widget_collapsible components can be used here", &(*it));
+					}
+
+					wxGenericCollapsiblePane* panel= NULL;
+
+					if (!test) {
+						//panel= new widgets_base::ContainerCollapsible(containerStack.top().GetEffectiveWindow(), wxID_ANY, _("Advanced"));
+						wxWindow* w= compo->GetGUI(containerStack.top().GetEffectiveWindow());
+						assert (w);
+						assert (w->IsKindOf(wxClassInfo::FindClass(_T("wxGenericCollapsiblePane"))));
+						panel= static_cast<wxGenericCollapsiblePane*>(w);
+						GUIContainer child(panel);
+						containerStack.top().AddChild (child, &(*it));
+						// Set sizer
+						panel->GetPane()->SetSizer(new wxBoxSizer(wxVERTICAL));
+					}
+					GUIContainer child(panel);
+					containerStack.push(child);
+				}
+				else
+					ThrowError ("Unknown layout type", &(*it));
+			}
+			else if (t[0]== "layout_end") {
+				CheckNumTokens (t, 1, 1, it->linenu, &it->text, &it->file);
+
+				if (containerStack.size()== 1)
+					ThrowError ("Unmatched layout_end", &(*it));
+
+				containerStack.pop();
+			}
+			else if (t[0]== "component") {
+				CheckNumTokens (t, 2, 2, it->linenu, &it->text, &it->file);
+
+				// Already placed?
+				if (usedComponents.find(t[1])!= usedComponents.end())
+					ThrowError (string("Component ") + t[1] + " already placed on GUI", &(*it));
+
+				// Search if exists
+				IComponent* compo= FindComponentByName (*this, t[1].c_str(), &(*it));
+				assert (compo);
+
+				// Set as placed
+				usedComponents.insert(t[1]);
+
+				// Add
+				if (!test) {
+					wxWindow* newPan= compo->GetGUI(containerStack.top().GetEffectiveWindow());
+					if (!newPan) {
+						string msg("Component ");
+						msg+= t[1] + " has no GUI while building GUI.";
+						getSpCoreRuntime()->LogMessage(ICoreRuntime::LOG_WARNING, msg.c_str(), GetName());
+					}
+					else {
+						assert (containerStack.size());
+						GUIContainer child(newPan);
+						containerStack.top().AddChild(child, &(*it));
+					}
+				}
+			}
+			else 
+				ThrowError ("Syntax error while parsing GUI layout", &(*it));
+		}
+
+		assert (containerStack.size());
+		if (containerStack.size()> 1) {
+			ThrowError ("Missing layout_end after", m_layoutLines.rbegin()->linenu, 
+				NULL, m_layoutLines.rbegin()->file.c_str());
+		}
+
+
+		if (!test) {
+			assert (containerStack.top().GetEffectiveWindow()->IsKindOf(wxClassInfo::FindClass(_T("wxWindow"))));
+			return static_cast<wxWindow*>(containerStack.top().GetEffectiveWindow());
+		}
+		else 
+			return NULL;
+	}
+
+private:
+	string m_type;
+	vector< LineWithContext > m_layoutLines;
+};
+
+/**
+	Quick and dirty class to parse scripts
+*/
+class ParsingContext
+{
+public:
+	// Constructor
+	ParsingContext(int flags) : m_flags(flags) { }
+
+	// Parses an stream and returns a constructed component or
+	// throwns an exception if an error is detected
+	SmartPtr<IComponent> SimpleParse (
+		std::istream& is, const string& file, const char* dataDir, int argc, const char *argv[])
+	{
+		// Pre-processing stage
+		unsigned int linenum= 0;
+		PreProcess (is, true, linenum, file);
+		CheckComponentTypeName (linenum);
+
+		// Component build stage		
+		return BuildComponent(NULL, argc, argv, dataDir);
+	}
+
+private:
+	// Checks that the type of the component is not void and not already in use
+	void CheckComponentTypeName (int linenum) { //, const string& file) {
+		// Check child component type name
+		if (m_type.size()== 0)
+			ThrowError ("Parse error. Component type not found after", linenum, NULL, m_file.c_str());			
+
+		// Check registered components
+		SmartPtr<IIterator<IComponentFactory*> > it = getSpCoreRuntime()->QueryComponents();
+		for (; !it->IsDone(); it->Next()){
+			if (m_type== it->CurrentItem()->GetName()) {
+				string error_msg("Parse error. Component type ");
+				error_msg+= m_type + " clashes with one registered component type";
+				ThrowError (error_msg, linenum, NULL, m_file.c_str());
+			}
+		}		
+	}
+
+	// Peforms script preprocessing and builds a tree of parsing contexts
+	void PreProcess (istream& is, bool is_root, unsigned int& linenum, const string& file) {
+		string line;
+
+		m_file= file;
+
+		while (!is.eof()) {
+			getline (is, line);
+			trim (line);
+			++linenum;
+
+			// If blank or comment ignore line
+			if (line.size()== 0) continue;
+			if (line[0]== '#') continue;
+
+			PerformStringTranslation (line);
+			vector<string> t;
+			try {
+				ExtractTokens (line, t);
+			}
+			catch(std::exception& e) {
+				ThrowError (e.what(), linenum, line.c_str(), m_file.c_str());
+			}
+			
+			if (t[0]== "import") {
+				// Import script
+				CheckNumTokens (t, 2, 2, linenum, &line, &m_file);
+
+				// First try to access file directly
+				string fname;
+				if (access(t[1].c_str(), R_OK)== 0) fname= t[1];
+
+				// If not worked try appending current script path
+				if (!fname.size()) {
+					fname= GetDirectory(m_file);
+					fname+= "/";
+					fname+= t[1];
+				}
+
+				if (!fname.size()) {
+					string err_msg("Cannot open file ");
+					err_msg+= t[1];
+					ThrowError (err_msg, linenum, line.c_str(), m_file.c_str());
+				}
+
+				// File exists and is readable
+				ifstream ifs ( fname.c_str(), ifstream::in );
+				if (!ifs.is_open() || !ifs.good()) {
+					// Should not happen, but just in case...
+					string err_msg("Cannot open file ");
+					err_msg+= t[1];
+					ThrowError (err_msg, linenum, line.c_str(), m_file.c_str());
+				}
+
+				shared_ptr<ParsingContext> child= shared_ptr<ParsingContext>(new ParsingContext(m_flags));
+
+				unsigned int child_linenum= 0;
+				child->PreProcess (ifs, true, child_linenum, fname);
+
+				// Try to add to the subcomponents map
+				pair<map<string,shared_ptr<ParsingContext> >::iterator,bool> ret;
+				ret= m_subcomponents.insert (pair<string,shared_ptr<ParsingContext> >(child->m_type, child));
+				if (ret.second== false) {
+					// Component already found
+					string error_msg("Parse error. Component ");
+					error_msg+= child->m_type + " redefined before line ";
+					ThrowError (error_msg, linenum, NULL, m_file.c_str());
+				}
+			}
+			else if (t[0]== "args") {
+				CheckNumTokens (t, 2, 0, linenum, &line, &m_file);
+				
+				for (unsigned int i= 1; i< t.size(); i++) {
+					// All arguments must have a leading dash
+					assert (t[i].size());
+					if (t[i][0]!= '-')
+						ThrowError ("Missing leading dash '-' in argument declaration", linenum, line.c_str(), m_file.c_str());
+					
+					// Already declared?
+					if (m_expectedArguments.find(t[i])!= m_expectedArguments.end())
+						ThrowError (string("Argument ") + t[i] + " already defined", linenum, line.c_str(), m_file.c_str());
+					
+					// Add to expected arguments set
+					m_expectedArguments.insert(t[i]);
+				}
+			}
+			else if (t[0]== "subcomponent") {
+				// Subcomponent found
+				CheckNumTokens (t, 1, 1, linenum, &line, &m_file);
+		
+				shared_ptr<ParsingContext> child= shared_ptr<ParsingContext>(new ParsingContext(m_flags));
+
+				child->PreProcess (is, false, linenum, m_file);
+
+				// Try to add to the subcomponents map
+				pair<map<string,shared_ptr<ParsingContext> >::iterator,bool> ret;
+				ret= m_subcomponents.insert (pair<string,shared_ptr<ParsingContext> >(child->m_type, child));
+				if (ret.second== false) {
+					// Component already found
+					string error_msg("Parse error. Component ");
+					error_msg+= child->m_type + " redefined before line ";
+					error_msg+= boost::lexical_cast<std::string>(linenum);
+					throw parser_error(error_msg);
+				}
+			}
+			else if (t[0]== "subcomponent_end") {
+				
+				CheckNumTokens (t, 1, 1, linenum, &line, &m_file);
+
+				if (is_root) {
+					string error_msg("Unexpected subcomponent_end keyword");
+					ThrowError (error_msg, linenum, NULL, m_file.c_str());
+				}
+
+				CheckComponentTypeName (linenum); //, m_file);
+
+				// Ok, finished at context, just return
+				return;
+			}
+			else if (t[0]== "type") {
+				CheckNumTokens (t, 2, 2, linenum, &line, &m_file);
+				m_type= t[1];			
+				CheckComponentTypeName (linenum); //, m_file);				
+			}
+			else if (t[0]== "name") {
+				CheckNumTokens (t, 2, 2, linenum, &line, &m_file);
+				m_name= t[1];
+			}
+			else {
+				// Other lines are simply translated & stored for further processing
+				//PerformStringTranslation (line);
+				m_lines.push_back(LineWithContext(line, linenum, m_file));
+			}
+		}
+
+		if (!is_root) {
+			string error_msg("Missing subcomponent_end keyword");
+
+			ThrowError (error_msg, linenum, NULL, m_file.c_str());
+		}
+	}
+
+	
+	//
+	// Builds a component given this parsing context
+	//
+	// Param with_name tells to rename the component with the given name,
+	// otherwise keyword "name" is expected to appear at the very beggining of the script
+	//
+	SmartPtr<IComponent> BuildComponent(const char * with_name, int argc, const char* argv[], const char* dataDir) {		
+		// If no lines, flag error
+		if (m_lines.size()== 0)
+			ThrowError ("No elements found for", 0, with_name, m_file.c_str());
+		
+		SmartPtr<ScriptComponent> result;
+		
+		// 
+		// Process incoming arguments
+		//
+		// Map to allow to substitute arguments into its values
+		map<string, string> argumentsDict;
+
+		// Insert $SP_DATA_DIR$ value
+		//argumentsDict.insert(pair<string, string>("$SP_DATA_DIR$", getSpCoreRuntime()->GetPaths().GetDataDir()));
+		argumentsDict.insert(pair<string, string>("$SP_DATA_DIR$", dataDir));
+
+		if (argc) {
+			assert (argv);
+			for (int i= 0; i< argc; ++i) {
+				// Argument name
+				const char* aname= argv[i];
+				if (m_expectedArguments.find(aname)== m_expectedArguments.end()) {
+					string error_msg("Unexpected argument ");
+					error_msg+= string(argv[i]);
+					ThrowPartialError(error_msg);
+				}
+
+				// Decorate name
+				string aname_decor= string("$") + aname + string("$");
+
+				// Is already in map?
+				if (argumentsDict.find(aname_decor)!= argumentsDict.end()) {
+					string error_msg("Argument ");
+					error_msg+= argv[i];
+					error_msg+= " set more than once";
+					ThrowPartialError(error_msg);
+				}
+
+				// Argument values				
+				string value;
+				if (i+1< argc && argv[i+1][0]!= '-') {
+					value= argv[i+1];
+					++i;
+				}
+
+				// Add to map
+				pair<map<string, string>::iterator,bool> retval;
+				retval= argumentsDict.insert( pair<string, string> (aname_decor, value));
+				assert (retval.second);
+			}
+		}
+
+		// Check whether the number of expected arguments match
+		if (argumentsDict.size() - 1!= m_expectedArguments.size()) {
+			string error_msg("Not enough arguments");
+			ThrowPartialError(error_msg);
+		}
+
+		// Create the component on which children will be added
+		if (with_name) result= CreateScriptComponent (m_type.c_str(), with_name);
+		else {
+			if (m_name.size()== 0) ThrowError ("Component name not found.", NULL);
+			result= CreateScriptComponent (m_type.c_str(), m_name.c_str());
+		}
+		
+		// Flag for GUI layout script lines
+		bool parsingLayout= false;
+
+		// Variables to process conditional expressions
+		//
+		int condDepth= 0;
+		// Depth at which conditional was evaluated as false
+		int condFalseIdx= -1;
+		
+		// For each stored line
+		//vector<LineWithContext>::const_iterator it= m_lines.begin();
+		for (vector<LineWithContext>::const_iterator it= m_lines.begin(); it!= m_lines.end(); ++it) {
+			//
+			// Parse line
+			//			
+
+			// Extract tokens
+			vector<string> t;
+			try {
+				ExtractTokens (it->text, t);
+			}
+			catch(std::exception& e) {
+				ThrowError (e.what(), &(*it));
+			}
+
+			ArgumentSubstitution (t, argumentsDict, it);
+			
+			// Process conditionals
+			//
+			if (t[0]== "if") {
+				CheckNumTokens (t, 4, 4, it->linenu, &it->text, &it->file);
+
+				bool exprResult= false;	// Initialize to remove warning
+
+				if (t[2]== "==")
+					exprResult= (t[1]== t[3]);
+				else if (t[2]== "!=")
+					exprResult= (t[1]!= t[3]);
+				else
+					ThrowError (string("Unknown operator " + t[2] + " on if statement"), &(*it));
+
+				condDepth++;
+				if (condFalseIdx== -1 && !exprResult) condFalseIdx= condDepth;
+				continue;
+			}
+			else if (t[0]== "else") {
+				CheckNumTokens (t, 1, 1, it->linenu, &it->text, &it->file);
+
+				if (condDepth== 0)
+					ThrowError (string("else without if"), &(*it));
+				
+				
+				if (condFalseIdx== condDepth)
+					// conditional at this depth was false, turn into true
+					condFalseIdx= -1;
+				else if (condFalseIdx== -1)
+						// conditional at this depth was true, turn into false
+					condFalseIdx= condDepth;
+				//else
+					// conditional at lower depth is false, do nothing
+				continue;
+			}
+			else if (t[0]== "endif") {
+				CheckNumTokens (t, 1, 1, it->linenu, &it->text, &it->file);
+
+				if (condDepth== 0)
+					ThrowError (string("endif without if"), &(*it));
+				
+				if (condFalseIdx== condDepth)
+					// conditional at this depth was false, turn into true
+					condFalseIdx= -1;
+				//else
+					// conditional at lower depth is false, do nothing
+
+				condDepth--;
+				continue;
+			}
+
+			// Check whether need to go on processing
+			if (condFalseIdx!= -1) continue;
+
+			// Layout
+			//
+			if (parsingLayout) {
+				if (it->text== "end_gui_layout") parsingLayout= false;
+				else result->AddLayoutLine(*it);
+				continue;
+			}
+
+			if (t[0]== "create") {
+				CheckNumTokens (t, 3, 0, it->linenu, &it->text, &it->file);
+				
+				// Collect args
+				int argc= 0;
+				const char** argv= NULL;
+				if (t.size()> 3) {
+					argv= new const char*[t.size()-3];
+					for (unsigned int i= 3; i< t.size(); ++i) {
+						// Store argv argument
+						argv[argc++]= t[i].c_str();
+					}
+				}
+
+				// Create component
+				// TODO: check whether the component exists or not and provide better error message
+				SmartPtr<IComponent> compo;
+				try {
+					// Check subcomponents
+					map<string,shared_ptr<ParsingContext> >::iterator itm= m_subcomponents.find (t[1]);
+					if (itm!= m_subcomponents.end()) compo= itm->second->BuildComponent(t[2].c_str(), argc, argv, dataDir);
+					else {
+						compo= getSpCoreRuntime()->CreateComponent(t[1].c_str(), t[2].c_str(), argc, argv);				
+						if (compo.get()== NULL) {
+							ThrowError (string("Component " + t[1] + " not found or creation failed (see console)"), &(*it));
+						}
+					}
+				}
+				catch (parser_partial_error& e) {
+					delete[] argv;
+					ThrowError(e.what(), &(*it));
+				}
+				catch(...) {
+					delete[] argv;
+					throw;
+				}		
+
+				delete[] argv;
+				argv= NULL;
+
+				// Attach to parent				
+				if (result->AddChild(compo)!= 0) 
+					ThrowError (string("Another component with name " + t[2] + " already found"), &(*it));
+			}
+			else if (t[0]== "connect") {
+				CheckNumTokens (t, 5, 5, it->linenu, &it->text, &it->file);
+								
+				// Find components
+				IComponent* src_component= FindComponentByName (*result, t[1].c_str(), &(*it));
+				IComponent* dst_component= FindComponentByName (*result, t[3].c_str(), &(*it));
+				
+				// TODO: this is a security measure to avoid stack overflows in some cases
+				// but actually core must provide a built-in stack overflow protection
+				if (src_component== dst_component && !(m_flags & ComponentHelper::IGNORE_CONNECT_SAME_COMPONENT))
+					ThrowError ("Source and destination components are the same", &(*it));
+				
+				// Find pins
+				IOutputPin* out_pin= FindOutputPin(*src_component, t[2].c_str(), &(*it));				
+				IInputPin* in_pin= FindInputPin(*dst_component, t[4].c_str(), &(*it));
+				
+				// Connect pins
+				if (out_pin->Connect (*in_pin)!= 0) 
+					ThrowError ("Type mismatch connecting pins", &(*it));
+			}
+			else if (t[0]== "export_ipin") {
+				CheckNumTokens (t, 3, 5, it->linenu, &it->text, &it->file);
+				
+				IComponent* compo= FindComponentByName (*result, t[1].c_str(), &(*it));
+				IInputPin* ipin= FindInputPin(*compo, t[2].c_str(), &(*it));
+
+				// Check to see if already exported
+				{
+					SmartPtr<IIterator<IInputPin*> > itip= result->GetInputPins();
+					for (; !itip->IsDone(); itip->Next())
+						if (ipin== itip->CurrentItem())
+							ThrowError ("Input pin already exported", &(*it));
+				}
+
+				// Rename?
+				if (t.size()>= 4) {
+					const string& new_name= t[3];
+					// Check if the new name will clash with another pin 
+					// of the original component
+					if (new_name!= ipin->GetName()) {
+						// If the new name does not coincides with the old one
+						SmartPtr<IIterator<IInputPin*> > itip= compo->GetInputPins();
+						for (; !itip->IsDone(); itip->Next())
+							if (new_name== itip->CurrentItem()->GetName())
+								ThrowError (
+									"Another pin with the same name exists.\n"
+									"Cannot rename pin", &(*it)
+								);
+						ipin->Rename(new_name.c_str());
+					}
+				}
+
+				// Change type?
+				if (t.size()== 5)	
+					if (ipin->ChangeType (t[4].c_str())!= 0) 
+						ThrowError ("Cannot change type of the pin", &(*it));
+
+				// Try to register
+				if (result->RegisterInputPin(*ipin)!= 0)
+					ThrowError ("Input pin name clashes with an existing one", &(*it));
+			}
+			else if (t[0]== "export_opin") {
+				CheckNumTokens (t, 3, 5, it->linenu, &it->text, &it->file);
+				
+				IComponent* compo= FindComponentByName (*result, t[1].c_str(), &(*it));
+				IOutputPin* opin= FindOutputPin(*compo, t[2].c_str(), &(*it));
+
+				// Check to see if already exported
+				{
+					SmartPtr<IIterator<IOutputPin*> > itop= result->GetOutputPins();
+					for (; !itop->IsDone(); itop->Next())
+						if (opin== itop->CurrentItem())
+							ThrowError ("Output pin already exported", &(*it));
+				}
+				
+				// Rename?
+				if (t.size()>= 4) {
+					const string& new_name= t[3];
+					// Check if the new name will clash with another pin 
+					// of the original component
+					if (new_name!= opin->GetName()) {
+						// If the new name does not coincides with the old one
+						SmartPtr<IIterator<IOutputPin*> > itop= compo->GetOutputPins();
+						for (; !itop->IsDone(); itop->Next())
+							if (new_name== itop->CurrentItem()->GetName())
+								ThrowError (
+									"Another pin with the same name exists.\n"
+									"Cannot rename pin", &(*it)
+								);
+
+						opin->Rename(new_name.c_str());
+					}
+				}
+
+				// Change type?
+				if (t.size()== 5)	
+					if (opin->ChangeType (t[4].c_str())!= 0) 
+						ThrowError ("Cannot change type of the pin", &(*it));
+
+				// Try to register
+				if (result->RegisterOutputPin(*opin)!= 0)
+					ThrowError ("Output pin name clashes with an existing one", &(*it));
+			}
+			else if (t[0]== "begin_gui_layout") {
+				if (parsingLayout)
+					ThrowError ("Unexpected begin_gui_layout", &(*it));
+				parsingLayout= true;				
+			}
+			else 
+				// Syntax error
+				ThrowError ("Syntax error", &(*it));
+		}
+
+		// Conditional depth should be 0 at this point
+		if (condDepth> 0)
+			ThrowError (boost::lexical_cast<std::string>(condDepth) + " unmatched if statement(s) at the end of the input", 0, NULL, m_file.c_str());
+
+		assert (result.get());
+		
+		// Check GUI layout
+		result->GetGUI(NULL, true);
+		
+		return result;
+	}	
+
+	//
+	// Convenience functions
+	//
+
+	// Create instance of ScriptComponent class taking care of errors
+	static 
+	SmartPtr<ScriptComponent> CreateScriptComponent (const char * type, const char * name) {
+		SmartPtr<ScriptComponent> result= SmartPtr<ScriptComponent>(new ScriptComponent(type, name, 0, NULL), false);
+		assert (result.get());
+		if (result.get()== NULL) 
+			throw parser_error("Fatal error cannot create ScriptComponent");
+		return result;
+	}
+
+private:
+	string m_type;	// Name of the type of the component
+	string m_name;	// Name given to the component
+	string m_file;	// Associated file name (for error reporting)
+	int m_flags;	// Parser flags
+
+	// Expected arguments for this component
+	set<string> m_expectedArguments;
+
+	// Stores script lines with additional context information
+	vector< LineWithContext > m_lines;
+	// Subcomponents (stored in a vector for simplif
+	map<string,shared_ptr<ParsingContext> > m_subcomponents;
+};
+
+SmartPtr<IComponent> ComponentHelper::SimpleParser (
+	std::istream& is, const string& file, const char* dataDir, int flags, int argc, const char *argv[])
+{
+	ParsingContext pc (flags);
+
+	return pc.SimpleParse (is, file, dataDir, argc, argv);
+}
+
+
+SmartPtr<spcore::IComponent> ComponentHelper::SimpleParserFile (
+	const char* file, const char* dataDir, int flags, int argc, const char *argv[])
+{
+	ifstream ifs ( file , ifstream::in );
+
+	if (!ifs.is_open() || !ifs.good()) throw std::runtime_error("Error opening file");
+		
+	return SimpleParser (ifs, string(file), dataDir, flags, argc, argv);
+}
+
+
+#ifdef WIN32
+// It seems that MSVC compilers get fooled in the following function
+// due to an identical loop guard and prints an unreachable code warning
+#pragma warning (disable:4702)
+#endif
+
+IComponent* ComponentHelper::FindComponentByName (spcore::IComponent& component, const char* name, int deep)
+{
+	assert (deep>= 0);
+
+	SmartPtr< IIterator<IComponent*> > it= component.QueryComponents();
+	if (it.get()== NULL) return NULL;
+
+	for (; !it->IsDone(); it->Next()) {
+		if (strcmp(name, it->CurrentItem()->GetName())== 0)
+			return it->CurrentItem();	// Found
+	}
+
+
+	if (deep!= 1) {
+		for (it->First(); !it->IsDone(); it->Next()) {
+			if (deep> 0) --deep;
+			return FindComponentByName (*it->CurrentItem(), name, deep);
+		}
+	}
+
+	return NULL;
+}
+
+};
diff --git a/src/host/configutils.cpp b/src/host/configutils.cpp
new file mode 100755
index 0000000..9ab513d
--- /dev/null
+++ b/src/host/configutils.cpp
@@ -0,0 +1,115 @@
+/////////////////////////////////////////////////////////////////////////////
+// Name:        configutils.cpp
+// Author:      Cesar Mauri Loba
+// Copyright:   (C) 2011 Cesar Mauri Loba - CREA Software Systems
+// 
+//  This program is free software: you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation, either version 3 of the License, or
+//  (at your option) any later version.
+//
+//  This program is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+/////////////////////////////////////////////////////////////////////////////
+#include "sphost/configutils.h"
+#include "spcore/coreruntime.h"
+
+#define BOOST_FILESYSTEM_VERSION 3
+//#define BOOST_FILESYSTEM_NO_DEPRECATED 1
+#include <boost/filesystem.hpp>
+#include <boost/filesystem/exception.hpp>
+
+#include <string.h>
+
+using namespace spcore;
+using namespace std;
+using namespace boost::filesystem;
+
+namespace sphost {
+
+SmartPtr<IConfiguration> LoadConfiguration(const char* fname) 
+{
+	ICoreRuntime* cr= getSpCoreRuntime();
+
+	SmartPtr<IConfiguration> result;
+	
+	// Try to open config file
+	FILE* file= fopen(fname, "rb");
+	if (!file) {
+		if (errno!= ENOENT) {
+			// Log other errors than non-existing file
+			std::string error_msg= "Cannot open ";
+			error_msg+= fname;
+			error_msg+= " for reading. ";
+			error_msg+= strerror(errno);
+			
+			cr->LogMessage(ICoreRuntime::LOG_ERROR, error_msg.c_str(), "configutils");
+		}
+		return result;
+	}
+	
+	// Read contents
+	result= cr->GetConfiguration();
+	if (!result->Load(file)) {
+		fclose(file);
+		result.reset();
+
+		// Log error
+		std::string error_msg= "An error occurred while loading configuration file ";
+		error_msg+= fname;
+		cr->LogMessage(ICoreRuntime::LOG_ERROR, error_msg.c_str(), "configutils");
+
+		return result;
+	}
+	fclose(file);
+
+	return result;
+}
+
+bool SaveConfiguration(const IConfiguration& cfg, const char* fname)
+{
+	path fullpath= fname;
+	ICoreRuntime* cr= getSpCoreRuntime();
+	
+	// Make sure user configuration directory exists
+	try {
+		boost::filesystem::create_directories(fullpath.branch_path());
+	}
+	catch (const boost::filesystem::filesystem_error& e) {
+		cr->LogMessage(ICoreRuntime::LOG_ERROR, e.what(), "configutils");
+		return false;
+	}
+
+	// Try to open config file
+	FILE* file= fopen(fullpath.string().c_str(), "wb");
+	if (!file) {
+		std::string error_msg= "Cannot open ";
+		error_msg+= fullpath.string();
+		error_msg+= " for writing. ";
+		error_msg+= strerror(errno);
+
+		cr->LogMessage(ICoreRuntime::LOG_ERROR, error_msg.c_str(), "configutils");
+		return false;
+	}
+
+	// Create configuration instance
+	if (!cfg.Save(file)) {
+		fclose(file);
+		
+		// Log error
+		std::string error_msg= "An error occurred writing configuration file ";
+		error_msg+= fullpath.string();
+		cr->LogMessage(ICoreRuntime::LOG_ERROR, error_msg.c_str(), "configutils");
+		return false;
+	}
+	fclose(file);
+
+	return true;
+}
+
+};
diff --git a/src/host/langutils.cpp b/src/host/langutils.cpp
new file mode 100644
index 0000000..a1a6739
--- /dev/null
+++ b/src/host/langutils.cpp
@@ -0,0 +1,97 @@
+/////////////////////////////////////////////////////////////////////////////
+// Name:        langutils.cpp
+// Author:      Cesar Mauri Loba
+// Copyright:   (C) 2011 Cesar Mauri Loba - CREA Software Systems
+// 
+//  This program is free software: you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation, either version 3 of the License, or
+//  (at your option) any later version.
+//
+//  This program is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+/////////////////////////////////////////////////////////////////////////////
+
+#include "sphost/langutils.h"
+
+#ifdef ENABLE_NLS
+
+#include "sphost/configutils.h"
+
+#include "spcore/coreruntime.h"
+#include "spcore/language.h"
+
+#include <wx/choicdlg.h>
+#include <vector>
+
+using namespace spcore;
+using namespace std;
+
+static std::vector<int> g_available_languages;
+
+namespace sphost {
+
+bool AddAvailableLanguage(int lang)
+{	
+	if (!isLanguageValid(lang)) return false;
+
+	g_available_languages.push_back(lang);
+	
+	return true;
+}
+
+int LanguageSelectionDialog(int previous)
+{
+	// Let user choose
+	int selection= -1;
+	wxArrayString languages;
+	std::vector<int>::size_type numLangs= g_available_languages.size();
+	for (std::vector<int>::size_type i= 0; i< numLangs; ++i) {
+		languages.Add(wxString(::spGetLanguageNativeName(g_available_languages[i], NULL), wxConvUTF8));
+		if (previous== g_available_languages[i]) selection= i;
+	}
+
+	wxSingleChoiceDialog langDlg(NULL, _("Language"), _("Language"), languages);
+	if (selection!= -1) langDlg.SetSelection(selection);
+	if (langDlg.ShowModal()== wxID_OK)
+		return g_available_languages[langDlg.GetSelection()];		
+	
+	return -1;
+}
+
+int LoadLanguageFromConfiguration(const char* fname)
+{
+	SmartPtr<spcore::IConfiguration> cfg= LoadConfiguration(fname);
+	if (!cfg.get()) return -1;
+
+	const char* langPtr= NULL;
+	if (!cfg->ReadString("language", &langPtr)) return -1;
+
+	int id= spResolveLocaleId (langPtr);
+	if (id< 0) return -2;
+
+	return id;
+}
+
+int SaveLanguageToConfiguration(int lang, const char* fname)
+{
+	const char* locale= spGetLocaleId (lang);
+
+	if (!locale) return -2;
+
+	SmartPtr<IConfiguration> cfg= getSpCoreRuntime()->GetConfiguration();
+	if (!cfg.get()) return -1;
+
+	if (!cfg->WriteString("language", locale)) return -1;
+	
+	return (SaveConfiguration(*cfg, fname)? 0 : -1);
+}
+
+};
+
+#endif
\ No newline at end of file
diff --git a/src/host/paths.cpp b/src/host/paths.cpp
new file mode 100755
index 0000000..5802fe1
--- /dev/null
+++ b/src/host/paths.cpp
@@ -0,0 +1,98 @@
+/////////////////////////////////////////////////////////////////////////////
+// File:        paths.cpp
+// Author:      Cesar Mauri Loba (cesar at crea-si dot com)
+// Copyright:   (C) 2010-12 Cesar Mauri Loba - CREA Software Systems
+//
+//  This program is free software: you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation, either version 3 of the License, or
+//  (at your option) any later version.
+//
+//  This program is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+/////////////////////////////////////////////////////////////////////////////
+#include "sphost/paths.h"
+#include "config.h"
+#include <string.h>
+#include <string>
+#ifdef WIN32
+#include <windows.h>
+#endif
+
+#define BOOST_FILESYSTEM_VERSION 3
+//#define BOOST_FILESYSTEM_NO_DEPRECATED 1
+#include <boost/filesystem.hpp>
+#include <boost/filesystem/exception.hpp>
+using namespace boost::filesystem;
+
+namespace sphost {
+
+// Read the full path of the binary of the calling process
+const std::string Paths::GetExecPath () {	
+	std::string retPath;
+	char buff[1024];	// Assume a reasonable buffer size
+
+#ifdef WIN32
+	DWORD retval= GetModuleFileNameA(NULL, buff, 1024);
+	for(int i= 0; buff[i]; i++)
+		if (buff[i]== '\\') buff[i]= '/';
+	if (retval) retPath= buff;
+#else
+	// This code only works on linux...
+	int retval= readlink ("/proc/self/exe", buff, 1023);
+	if (retval!= -1) {
+		buff[retval]= 0;
+		retPath= buff;
+	}
+#endif
+	return retPath;	
+}
+
+const std::string Paths::GetBasePathFromExec(const std::string& exePath, bool& devel) {
+	devel= false;
+
+	if (!exePath.empty())  {
+		path p= exePath;
+		path pp= p.parent_path ();
+		path filename(pp.filename());
+		if (!filename.string().compare("bin")) {
+			return pp.parent_path().string();
+		}
+		else if (!filename.string().compare("Debug") || !filename.string().compare("Release")) {
+			devel= true;
+			return pp.parent_path().parent_path().string();
+		}
+	}
+
+	// Return void result
+	return exePath;
+}
+
+const std::string Paths::GetDirName(const std::string& fullPath) {
+	if (!fullPath.empty()) {
+		path p= fullPath;
+		path pp= p.parent_path ();
+		return pp.string();
+	}
+
+	// Return void result
+	return fullPath;
+}
+
+const std::string Paths::GetUserDataDir() {
+	std::string result;
+#ifdef WIN32
+	result= getenv("APPDATA");	
+#else
+	result= getenv("HOME");	
+#endif
+	return result;
+}
+
+} // namespace sphost
+
diff --git a/src/host/testcommon.cpp b/src/host/testcommon.cpp
new file mode 100644
index 0000000..23064d2
--- /dev/null
+++ b/src/host/testcommon.cpp
@@ -0,0 +1,235 @@
+/////////////////////////////////////////////////////////////////////////////
+// File:        testcommon.cpp
+//	Common functions to perform testing
+// Author:      Cesar Mauri Loba (cesar at crea-si dot com)
+// Copyright:   (C) 2010 Cesar Mauri Loba - CREA Software Systems
+// 
+//  This program is free software: you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation, either version 3 of the License, or
+//  (at your option) any later version.
+//
+//  This program is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+/////////////////////////////////////////////////////////////////////////////
+#include "sphost/testcommon.h"
+#include "spcore/module.h"
+#include "spcore/coreruntime.h"
+#include "spcore/iterator.h"
+#include "spcore/basictypes.h"
+
+#ifndef WIN32
+	#include <unistd.h>
+	#include <sys/time.h>
+	#include <sys/select.h>	
+	#include <termios.h>
+	#include <fcntl.h>
+#else
+	#include <conio.h>
+#endif
+
+
+using namespace spcore;
+using namespace std;
+
+
+void DumpTypeInstance (const spcore::CTypeAny& t, const char* indent)
+{
+	//cout << indent << "Type name: " << t.getTypeName() << endl;
+	cout << indent << "TypeID: " << t.GetTypeID() << endl;
+	
+	// Dump contents for known types
+	if (t.GetTypeID()== CTypeInt::getTypeID()) {
+		cout << indent << "Value: " << dynamic_cast<const CTypeInt*>(&t)->getValue() << endl;
+	}
+	else if (t.GetTypeID()== CTypeFloat::getTypeID()) {
+		cout << indent << "Value: " << dynamic_cast<const CTypeFloat*>(&t)->getValue() << endl;
+	}
+	else if (t.GetTypeID()== CTypeBool::getTypeID()) {
+		cout << indent << "Value: " << dynamic_cast<const CTypeBool*>(&t)->getValue() << endl;
+	}
+	else if (t.GetTypeID()== CTypeString::getTypeID()) {
+		cout << indent << "Value: " << dynamic_cast<const CTypeString*>(&t)->getValue() << endl;			
+	}
+
+	// Dump composed instances
+	SmartPtr<IIterator<CTypeAny*> > it= t.QueryChildren();
+	if (it.get()) {
+		std::string new_indent(indent);
+		new_indent.append("\t");
+		int i= 0;
+		for (it->First(); !it->IsDone(); it->Next()) {
+			cout << indent << "Dumping component " << ++i << endl;
+			DumpTypeInstance (*(it->CurrentItem()), new_indent.c_str());
+		}
+	}
+}
+
+
+void DumpInputPin (IInputPin& ip)
+{
+	cout << "\tInput pin: " << ip.GetName() << endl;
+//	cout << "\tPin type: " << ip.GetTypeName() << endl;
+	cout << "\tPin type ID: " << ip.GetTypeID() << endl;
+	cout << "\tProperties: ";
+	if (ip.GetProperties() & IInputPin::ALLOW_WRITE) cout << "ALLOW_WRITE ";
+	if (ip.GetProperties() & IInputPin::ALLOW_READ) cout << "ALLOW_READ";
+	cout << endl;
+
+	if (ip.GetProperties() & IInputPin::ALLOW_READ) {
+		SmartPtr<const CTypeAny> value= ip.Read();
+		if (value.get()== NULL) 
+			cout << "\tPin error: Read returned NULL result\n";
+		else
+			cout << "\tRead value type ID: " << value->GetTypeID() << endl;
+	}
+}
+
+void DumpOutputPin (IOutputPin& op)
+{
+	cout << "Output pin: " << op.GetName() << endl;
+//	cout << "\tPin type: " << op.GetTypeName() << endl;
+	cout << "\tPin type ID: " << op.GetTypeID() << endl;
+}
+
+void DumpComponent (IComponent &c)
+{
+	cout << "Component name:" << c.GetName() << endl;
+	cout << "\tComponent type:" << c.GetTypeName() << endl;
+	cout << "\tProvides thread:" << c.ProvidesExecThread() << endl;
+	
+	cout << "\tInput pins\n";
+	SmartPtr<IIterator<IInputPin*> > itipin= c.GetInputPins();
+	for (itipin->First(); !itipin->IsDone(); itipin->Next()) {
+		cout << "\t";
+		DumpInputPin(*itipin->CurrentItem());
+	}
+	
+	cout << "\tOutput pins\n";
+	SmartPtr<IIterator<IOutputPin*> > itopin= c.GetOutputPins();
+	for (itopin->First(); !itopin->IsDone(); itopin->Next()) {
+		cout << "\t";
+		DumpOutputPin (*itopin->CurrentItem());
+	}
+	
+	SmartPtr<IIterator<IComponent*> > itc= c.QueryComponents();
+	if (itc.get()) {
+		cout << "Child components\n";
+		cout << "---------------------------------------\n";
+		for (itc->First(); !itc->IsDone(); itc->Next()) {
+			cout << "\t";
+			DumpComponent (*itc->CurrentItem());
+		}
+	}
+}
+
+void DumpCoreRuntime(ICoreRuntime* core)
+{
+	if (!core) {
+		cout << "Critical error: getSpCoreRuntime() returned NULL\n" << endl;
+		return;
+	}
+
+	SmartPtr<IIterator<spcore::ITypeFactory*> > ittf= core->QueryTypes();
+	cout << "Dumping registered types\n";
+	for (ittf->First(); !ittf->IsDone(); ittf->Next()) {
+		spcore::ITypeFactory* item= ittf->CurrentItem();
+		cout << "\t" << item->GetName() << endl;
+	}
+	
+	SmartPtr<IIterator<IComponentFactory*> > itcf= core->QueryComponents();
+	cout << "Dumping registered components\n";
+	for (itcf->First(); !itcf->IsDone(); itcf->Next()) {
+		cout << "\t" << itcf->CurrentItem()->GetName() << endl;
+	}
+}
+
+void ExitErr (const char* msg)
+{
+	cerr << msg << endl;
+	exit (-1);
+}
+
+#ifndef WIN32	
+int getch_no_block(void)
+{
+	struct termios oldt, newt;
+	int ch;
+	int oldf;
+
+	tcgetattr(STDIN_FILENO, &oldt);
+	newt = oldt;
+	newt.c_lflag &= ~(ICANON | ECHO);
+	tcsetattr(STDIN_FILENO, TCSANOW, &newt);
+	oldf = fcntl(STDIN_FILENO, F_GETFL, 0);
+	fcntl(STDIN_FILENO, F_SETFL, oldf | O_NONBLOCK);
+
+	ch = getchar();
+
+	tcsetattr(STDIN_FILENO, TCSANOW, &oldt);
+	fcntl(STDIN_FILENO, F_SETFL, oldf);
+
+	if(ch != EOF)
+	{
+		//ungetc(ch, stdin);
+		return ch;
+	}
+
+	return 0;
+}
+#else
+int getch_no_block(void)
+{
+	if (kbhit()) return _getch();
+	return 0;
+}
+#endif
+
+unsigned long get_mili_count()
+{
+#if defined(WIN32)
+	// Windows
+	return GetTickCount();
+#else
+	// Linux
+	struct timeval tv;
+	//struct timezone tz;
+	gettimeofday(&tv, NULL); //&tz);
+
+	return (((unsigned long) tv.tv_sec * 1000000 + (unsigned long) tv.tv_usec) / 1000);
+#endif	
+}
+
+void calls_per_second()
+{
+	static unsigned int call_count= 0;
+	static unsigned long prev_tstamp= 0;
+	unsigned long tstamp = get_mili_count();
+
+	++call_count;
+
+	if (!prev_tstamp) {
+		prev_tstamp= tstamp;
+		return;
+	}
+
+	if (tstamp - prev_tstamp>= 1000) {
+		printf ("call per second: %.2f\n", (float) (call_count * 1000) / (float) (tstamp - prev_tstamp) );
+		call_count= 0;
+		prev_tstamp= tstamp;
+	}	
+}
+
+void sleep_milliseconds(unsigned ms)
+{
+#ifdef WIN32
+	Sleep (ms);
+#else
+	usleep (ms * 1000);
+#endif
+}
diff --git a/src/libwebcam/CMakeLists.txt b/src/libwebcam/CMakeLists.txt
new file mode 100755
index 0000000..ae90175
--- /dev/null
+++ b/src/libwebcam/CMakeLists.txt
@@ -0,0 +1,36 @@
+cmake_minimum_required(VERSION 2.6)
+project(libwebcam)
+
+IF(NOT CMAKE_SYSTEM_NAME MATCHES "Linux")
+	MESSAGE (FATAL_ERROR "libwebcam is only available for linux systems")
+ENDIF(NOT CMAKE_SYSTEM_NAME MATCHES "Linux")
+
+find_file(VIDEODEV_INCLUDE_FILE
+	videodev.h 
+	/usr/include/linux
+)
+
+if (NOT VIDEODEV_INCLUDE_FILE)
+find_file(VIDEODEV_INCLUDE_FILE
+	libv4l1-videodev.h
+	/usr/include/
+)
+endif()
+
+if (NOT VIDEODEV_INCLUDE_FILE)
+	message (FATAL_ERROR "Cannot find videodev.h nor libv4l1-videodev.h")
+endif()
+
+configure_file ("incvideodev.h.in" "${CMAKE_BINARY_DIR}/include/incvideodev.h" )
+
+set(libwebcam_SRCS
+	compat.h
+	dynctrl-logitech.h
+	libwebcam.c
+	libwebcam.h
+	uvcvideo.h
+	webcam.h
+)
+
+add_library (libwebcam STATIC ${libwebcam_SRCS})
+#TARGET_LINK_LIBRARIES(creavision ${OpenCV_LIBS} )
diff --git a/src/libwebcam/COPYING b/src/libwebcam/COPYING
new file mode 100644
index 0000000..94a9ed0
--- /dev/null
+++ b/src/libwebcam/COPYING
@@ -0,0 +1,674 @@
+                    GNU GENERAL PUBLIC LICENSE
+                       Version 3, 29 June 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+                            Preamble
+
+  The GNU General Public License is a free, copyleft license for
+software and other kinds of works.
+
+  The licenses for most software and other practical works are designed
+to take away your freedom to share and change the works.  By contrast,
+the GNU General Public License is intended to guarantee your freedom to
+share and change all versions of a program--to make sure it remains free
+software for all its users.  We, the Free Software Foundation, use the
+GNU General Public License for most of our software; it applies also to
+any other work released this way by its authors.  You can apply it to
+your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+them if you wish), that you receive source code or can get it if you
+want it, that you can change the software or use pieces of it in new
+free programs, and that you know you can do these things.
+
+  To protect your rights, we need to prevent others from denying you
+these rights or asking you to surrender the rights.  Therefore, you have
+certain responsibilities if you distribute copies of the software, or if
+you modify it: responsibilities to respect the freedom of others.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must pass on to the recipients the same
+freedoms that you received.  You must make sure that they, too, receive
+or can get the source code.  And you must show them these terms so they
+know their rights.
+
+  Developers that use the GNU GPL protect your rights with two steps:
+(1) assert copyright on the software, and (2) offer you this License
+giving you legal permission to copy, distribute and/or modify it.
+
+  For the developers' and authors' protection, the GPL clearly explains
+that there is no warranty for this free software.  For both users' and
+authors' sake, the GPL requires that modified versions be marked as
+changed, so that their problems will not be attributed erroneously to
+authors of previous versions.
+
+  Some devices are designed to deny users access to install or run
+modified versions of the software inside them, although the manufacturer
+can do so.  This is fundamentally incompatible with the aim of
+protecting users' freedom to change the software.  The systematic
+pattern of such abuse occurs in the area of products for individuals to
+use, which is precisely where it is most unacceptable.  Therefore, we
+have designed this version of the GPL to prohibit the practice for those
+products.  If such problems arise substantially in other domains, we
+stand ready to extend this provision to those domains in future versions
+of the GPL, as needed to protect the freedom of users.
+
+  Finally, every program is threatened constantly by software patents.
+States should not allow patents to restrict development and use of
+software on general-purpose computers, but in those that do, we wish to
+avoid the special danger that patents applied to a free program could
+make it effectively proprietary.  To prevent this, the GPL assures that
+patents cannot be used to render the program non-free.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+
+                       TERMS AND CONDITIONS
+
+  0. Definitions.
+
+  "This License" refers to version 3 of the GNU General Public License.
+
+  "Copyright" also means copyright-like laws that apply to other kinds of
+works, such as semiconductor masks.
+
+  "The Program" refers to any copyrightable work licensed under this
+License.  Each licensee is addressed as "you".  "Licensees" and
+"recipients" may be individuals or organizations.
+
+  To "modify" a work means to copy from or adapt all or part of the work
+in a fashion requiring copyright permission, other than the making of an
+exact copy.  The resulting work is called a "modified version" of the
+earlier work or a work "based on" the earlier work.
+
+  A "covered work" means either the unmodified Program or a work based
+on the Program.
+
+  To "propagate" a work means to do anything with it that, without
+permission, would make you directly or secondarily liable for
+infringement under applicable copyright law, except executing it on a
+computer or modifying a private copy.  Propagation includes copying,
+distribution (with or without modification), making available to the
+public, and in some countries other activities as well.
+
+  To "convey" a work means any kind of propagation that enables other
+parties to make or receive copies.  Mere interaction with a user through
+a computer network, with no transfer of a copy, is not conveying.
+
+  An interactive user interface displays "Appropriate Legal Notices"
+to the extent that it includes a convenient and prominently visible
+feature that (1) displays an appropriate copyright notice, and (2)
+tells the user that there is no warranty for the work (except to the
+extent that warranties are provided), that licensees may convey the
+work under this License, and how to view a copy of this License.  If
+the interface presents a list of user commands or options, such as a
+menu, a prominent item in the list meets this criterion.
+
+  1. Source Code.
+
+  The "source code" for a work means the preferred form of the work
+for making modifications to it.  "Object code" means any non-source
+form of a work.
+
+  A "Standard Interface" means an interface that either is an official
+standard defined by a recognized standards body, or, in the case of
+interfaces specified for a particular programming language, one that
+is widely used among developers working in that language.
+
+  The "System Libraries" of an executable work include anything, other
+than the work as a whole, that (a) is included in the normal form of
+packaging a Major Component, but which is not part of that Major
+Component, and (b) serves only to enable use of the work with that
+Major Component, or to implement a Standard Interface for which an
+implementation is available to the public in source code form.  A
+"Major Component", in this context, means a major essential component
+(kernel, window system, and so on) of the specific operating system
+(if any) on which the executable work runs, or a compiler used to
+produce the work, or an object code interpreter used to run it.
+
+  The "Corresponding Source" for a work in object code form means all
+the source code needed to generate, install, and (for an executable
+work) run the object code and to modify the work, including scripts to
+control those activities.  However, it does not include the work's
+System Libraries, or general-purpose tools or generally available free
+programs which are used unmodified in performing those activities but
+which are not part of the work.  For example, Corresponding Source
+includes interface definition files associated with source files for
+the work, and the source code for shared libraries and dynamically
+linked subprograms that the work is specifically designed to require,
+such as by intimate data communication or control flow between those
+subprograms and other parts of the work.
+
+  The Corresponding Source need not include anything that users
+can regenerate automatically from other parts of the Corresponding
+Source.
+
+  The Corresponding Source for a work in source code form is that
+same work.
+
+  2. Basic Permissions.
+
+  All rights granted under this License are granted for the term of
+copyright on the Program, and are irrevocable provided the stated
+conditions are met.  This License explicitly affirms your unlimited
+permission to run the unmodified Program.  The output from running a
+covered work is covered by this License only if the output, given its
+content, constitutes a covered work.  This License acknowledges your
+rights of fair use or other equivalent, as provided by copyright law.
+
+  You may make, run and propagate covered works that you do not
+convey, without conditions so long as your license otherwise remains
+in force.  You may convey covered works to others for the sole purpose
+of having them make modifications exclusively for you, or provide you
+with facilities for running those works, provided that you comply with
+the terms of this License in conveying all material for which you do
+not control copyright.  Those thus making or running the covered works
+for you must do so exclusively on your behalf, under your direction
+and control, on terms that prohibit them from making any copies of
+your copyrighted material outside their relationship with you.
+
+  Conveying under any other circumstances is permitted solely under
+the conditions stated below.  Sublicensing is not allowed; section 10
+makes it unnecessary.
+
+  3. Protecting Users' Legal Rights From Anti-Circumvention Law.
+
+  No covered work shall be deemed part of an effective technological
+measure under any applicable law fulfilling obligations under article
+11 of the WIPO copyright treaty adopted on 20 December 1996, or
+similar laws prohibiting or restricting circumvention of such
+measures.
+
+  When you convey a covered work, you waive any legal power to forbid
+circumvention of technological measures to the extent such circumvention
+is effected by exercising rights under this License with respect to
+the covered work, and you disclaim any intention to limit operation or
+modification of the work as a means of enforcing, against the work's
+users, your or third parties' legal rights to forbid circumvention of
+technological measures.
+
+  4. Conveying Verbatim Copies.
+
+  You may convey verbatim copies of the Program's source code as you
+receive it, in any medium, provided that you conspicuously and
+appropriately publish on each copy an appropriate copyright notice;
+keep intact all notices stating that this License and any
+non-permissive terms added in accord with section 7 apply to the code;
+keep intact all notices of the absence of any warranty; and give all
+recipients a copy of this License along with the Program.
+
+  You may charge any price or no price for each copy that you convey,
+and you may offer support or warranty protection for a fee.
+
+  5. Conveying Modified Source Versions.
+
+  You may convey a work based on the Program, or the modifications to
+produce it from the Program, in the form of source code under the
+terms of section 4, provided that you also meet all of these conditions:
+
+    a) The work must carry prominent notices stating that you modified
+    it, and giving a relevant date.
+
+    b) The work must carry prominent notices stating that it is
+    released under this License and any conditions added under section
+    7.  This requirement modifies the requirement in section 4 to
+    "keep intact all notices".
+
+    c) You must license the entire work, as a whole, under this
+    License to anyone who comes into possession of a copy.  This
+    License will therefore apply, along with any applicable section 7
+    additional terms, to the whole of the work, and all its parts,
+    regardless of how they are packaged.  This License gives no
+    permission to license the work in any other way, but it does not
+    invalidate such permission if you have separately received it.
+
+    d) If the work has interactive user interfaces, each must display
+    Appropriate Legal Notices; however, if the Program has interactive
+    interfaces that do not display Appropriate Legal Notices, your
+    work need not make them do so.
+
+  A compilation of a covered work with other separate and independent
+works, which are not by their nature extensions of the covered work,
+and which are not combined with it such as to form a larger program,
+in or on a volume of a storage or distribution medium, is called an
+"aggregate" if the compilation and its resulting copyright are not
+used to limit the access or legal rights of the compilation's users
+beyond what the individual works permit.  Inclusion of a covered work
+in an aggregate does not cause this License to apply to the other
+parts of the aggregate.
+
+  6. Conveying Non-Source Forms.
+
+  You may convey a covered work in object code form under the terms
+of sections 4 and 5, provided that you also convey the
+machine-readable Corresponding Source under the terms of this License,
+in one of these ways:
+
+    a) Convey the object code in, or embodied in, a physical product
+    (including a physical distribution medium), accompanied by the
+    Corresponding Source fixed on a durable physical medium
+    customarily used for software interchange.
+
+    b) Convey the object code in, or embodied in, a physical product
+    (including a physical distribution medium), accompanied by a
+    written offer, valid for at least three years and valid for as
+    long as you offer spare parts or customer support for that product
+    model, to give anyone who possesses the object code either (1) a
+    copy of the Corresponding Source for all the software in the
+    product that is covered by this License, on a durable physical
+    medium customarily used for software interchange, for a price no
+    more than your reasonable cost of physically performing this
+    conveying of source, or (2) access to copy the
+    Corresponding Source from a network server at no charge.
+
+    c) Convey individual copies of the object code with a copy of the
+    written offer to provide the Corresponding Source.  This
+    alternative is allowed only occasionally and noncommercially, and
+    only if you received the object code with such an offer, in accord
+    with subsection 6b.
+
+    d) Convey the object code by offering access from a designated
+    place (gratis or for a charge), and offer equivalent access to the
+    Corresponding Source in the same way through the same place at no
+    further charge.  You need not require recipients to copy the
+    Corresponding Source along with the object code.  If the place to
+    copy the object code is a network server, the Corresponding Source
+    may be on a different server (operated by you or a third party)
+    that supports equivalent copying facilities, provided you maintain
+    clear directions next to the object code saying where to find the
+    Corresponding Source.  Regardless of what server hosts the
+    Corresponding Source, you remain obligated to ensure that it is
+    available for as long as needed to satisfy these requirements.
+
+    e) Convey the object code using peer-to-peer transmission, provided
+    you inform other peers where the object code and Corresponding
+    Source of the work are being offered to the general public at no
+    charge under subsection 6d.
+
+  A separable portion of the object code, whose source code is excluded
+from the Corresponding Source as a System Library, need not be
+included in conveying the object code work.
+
+  A "User Product" is either (1) a "consumer product", which means any
+tangible personal property which is normally used for personal, family,
+or household purposes, or (2) anything designed or sold for incorporation
+into a dwelling.  In determining whether a product is a consumer product,
+doubtful cases shall be resolved in favor of coverage.  For a particular
+product received by a particular user, "normally used" refers to a
+typical or common use of that class of product, regardless of the status
+of the particular user or of the way in which the particular user
+actually uses, or expects or is expected to use, the product.  A product
+is a consumer product regardless of whether the product has substantial
+commercial, industrial or non-consumer uses, unless such uses represent
+the only significant mode of use of the product.
+
+  "Installation Information" for a User Product means any methods,
+procedures, authorization keys, or other information required to install
+and execute modified versions of a covered work in that User Product from
+a modified version of its Corresponding Source.  The information must
+suffice to ensure that the continued functioning of the modified object
+code is in no case prevented or interfered with solely because
+modification has been made.
+
+  If you convey an object code work under this section in, or with, or
+specifically for use in, a User Product, and the conveying occurs as
+part of a transaction in which the right of possession and use of the
+User Product is transferred to the recipient in perpetuity or for a
+fixed term (regardless of how the transaction is characterized), the
+Corresponding Source conveyed under this section must be accompanied
+by the Installation Information.  But this requirement does not apply
+if neither you nor any third party retains the ability to install
+modified object code on the User Product (for example, the work has
+been installed in ROM).
+
+  The requirement to provide Installation Information does not include a
+requirement to continue to provide support service, warranty, or updates
+for a work that has been modified or installed by the recipient, or for
+the User Product in which it has been modified or installed.  Access to a
+network may be denied when the modification itself materially and
+adversely affects the operation of the network or violates the rules and
+protocols for communication across the network.
+
+  Corresponding Source conveyed, and Installation Information provided,
+in accord with this section must be in a format that is publicly
+documented (and with an implementation available to the public in
+source code form), and must require no special password or key for
+unpacking, reading or copying.
+
+  7. Additional Terms.
+
+  "Additional permissions" are terms that supplement the terms of this
+License by making exceptions from one or more of its conditions.
+Additional permissions that are applicable to the entire Program shall
+be treated as though they were included in this License, to the extent
+that they are valid under applicable law.  If additional permissions
+apply only to part of the Program, that part may be used separately
+under those permissions, but the entire Program remains governed by
+this License without regard to the additional permissions.
+
+  When you convey a copy of a covered work, you may at your option
+remove any additional permissions from that copy, or from any part of
+it.  (Additional permissions may be written to require their own
+removal in certain cases when you modify the work.)  You may place
+additional permissions on material, added by you to a covered work,
+for which you have or can give appropriate copyright permission.
+
+  Notwithstanding any other provision of this License, for material you
+add to a covered work, you may (if authorized by the copyright holders of
+that material) supplement the terms of this License with terms:
+
+    a) Disclaiming warranty or limiting liability differently from the
+    terms of sections 15 and 16 of this License; or
+
+    b) Requiring preservation of specified reasonable legal notices or
+    author attributions in that material or in the Appropriate Legal
+    Notices displayed by works containing it; or
+
+    c) Prohibiting misrepresentation of the origin of that material, or
+    requiring that modified versions of such material be marked in
+    reasonable ways as different from the original version; or
+
+    d) Limiting the use for publicity purposes of names of licensors or
+    authors of the material; or
+
+    e) Declining to grant rights under trademark law for use of some
+    trade names, trademarks, or service marks; or
+
+    f) Requiring indemnification of licensors and authors of that
+    material by anyone who conveys the material (or modified versions of
+    it) with contractual assumptions of liability to the recipient, for
+    any liability that these contractual assumptions directly impose on
+    those licensors and authors.
+
+  All other non-permissive additional terms are considered "further
+restrictions" within the meaning of section 10.  If the Program as you
+received it, or any part of it, contains a notice stating that it is
+governed by this License along with a term that is a further
+restriction, you may remove that term.  If a license document contains
+a further restriction but permits relicensing or conveying under this
+License, you may add to a covered work material governed by the terms
+of that license document, provided that the further restriction does
+not survive such relicensing or conveying.
+
+  If you add terms to a covered work in accord with this section, you
+must place, in the relevant source files, a statement of the
+additional terms that apply to those files, or a notice indicating
+where to find the applicable terms.
+
+  Additional terms, permissive or non-permissive, may be stated in the
+form of a separately written license, or stated as exceptions;
+the above requirements apply either way.
+
+  8. Termination.
+
+  You may not propagate or modify a covered work except as expressly
+provided under this License.  Any attempt otherwise to propagate or
+modify it is void, and will automatically terminate your rights under
+this License (including any patent licenses granted under the third
+paragraph of section 11).
+
+  However, if you cease all violation of this License, then your
+license from a particular copyright holder is reinstated (a)
+provisionally, unless and until the copyright holder explicitly and
+finally terminates your license, and (b) permanently, if the copyright
+holder fails to notify you of the violation by some reasonable means
+prior to 60 days after the cessation.
+
+  Moreover, your license from a particular copyright holder is
+reinstated permanently if the copyright holder notifies you of the
+violation by some reasonable means, this is the first time you have
+received notice of violation of this License (for any work) from that
+copyright holder, and you cure the violation prior to 30 days after
+your receipt of the notice.
+
+  Termination of your rights under this section does not terminate the
+licenses of parties who have received copies or rights from you under
+this License.  If your rights have been terminated and not permanently
+reinstated, you do not qualify to receive new licenses for the same
+material under section 10.
+
+  9. Acceptance Not Required for Having Copies.
+
+  You are not required to accept this License in order to receive or
+run a copy of the Program.  Ancillary propagation of a covered work
+occurring solely as a consequence of using peer-to-peer transmission
+to receive a copy likewise does not require acceptance.  However,
+nothing other than this License grants you permission to propagate or
+modify any covered work.  These actions infringe copyright if you do
+not accept this License.  Therefore, by modifying or propagating a
+covered work, you indicate your acceptance of this License to do so.
+
+  10. Automatic Licensing of Downstream Recipients.
+
+  Each time you convey a covered work, the recipient automatically
+receives a license from the original licensors, to run, modify and
+propagate that work, subject to this License.  You are not responsible
+for enforcing compliance by third parties with this License.
+
+  An "entity transaction" is a transaction transferring control of an
+organization, or substantially all assets of one, or subdividing an
+organization, or merging organizations.  If propagation of a covered
+work results from an entity transaction, each party to that
+transaction who receives a copy of the work also receives whatever
+licenses to the work the party's predecessor in interest had or could
+give under the previous paragraph, plus a right to possession of the
+Corresponding Source of the work from the predecessor in interest, if
+the predecessor has it or can get it with reasonable efforts.
+
+  You may not impose any further restrictions on the exercise of the
+rights granted or affirmed under this License.  For example, you may
+not impose a license fee, royalty, or other charge for exercise of
+rights granted under this License, and you may not initiate litigation
+(including a cross-claim or counterclaim in a lawsuit) alleging that
+any patent claim is infringed by making, using, selling, offering for
+sale, or importing the Program or any portion of it.
+
+  11. Patents.
+
+  A "contributor" is a copyright holder who authorizes use under this
+License of the Program or a work on which the Program is based.  The
+work thus licensed is called the contributor's "contributor version".
+
+  A contributor's "essential patent claims" are all patent claims
+owned or controlled by the contributor, whether already acquired or
+hereafter acquired, that would be infringed by some manner, permitted
+by this License, of making, using, or selling its contributor version,
+but do not include claims that would be infringed only as a
+consequence of further modification of the contributor version.  For
+purposes of this definition, "control" includes the right to grant
+patent sublicenses in a manner consistent with the requirements of
+this License.
+
+  Each contributor grants you a non-exclusive, worldwide, royalty-free
+patent license under the contributor's essential patent claims, to
+make, use, sell, offer for sale, import and otherwise run, modify and
+propagate the contents of its contributor version.
+
+  In the following three paragraphs, a "patent license" is any express
+agreement or commitment, however denominated, not to enforce a patent
+(such as an express permission to practice a patent or covenant not to
+sue for patent infringement).  To "grant" such a patent license to a
+party means to make such an agreement or commitment not to enforce a
+patent against the party.
+
+  If you convey a covered work, knowingly relying on a patent license,
+and the Corresponding Source of the work is not available for anyone
+to copy, free of charge and under the terms of this License, through a
+publicly available network server or other readily accessible means,
+then you must either (1) cause the Corresponding Source to be so
+available, or (2) arrange to deprive yourself of the benefit of the
+patent license for this particular work, or (3) arrange, in a manner
+consistent with the requirements of this License, to extend the patent
+license to downstream recipients.  "Knowingly relying" means you have
+actual knowledge that, but for the patent license, your conveying the
+covered work in a country, or your recipient's use of the covered work
+in a country, would infringe one or more identifiable patents in that
+country that you have reason to believe are valid.
+
+  If, pursuant to or in connection with a single transaction or
+arrangement, you convey, or propagate by procuring conveyance of, a
+covered work, and grant a patent license to some of the parties
+receiving the covered work authorizing them to use, propagate, modify
+or convey a specific copy of the covered work, then the patent license
+you grant is automatically extended to all recipients of the covered
+work and works based on it.
+
+  A patent license is "discriminatory" if it does not include within
+the scope of its coverage, prohibits the exercise of, or is
+conditioned on the non-exercise of one or more of the rights that are
+specifically granted under this License.  You may not convey a covered
+work if you are a party to an arrangement with a third party that is
+in the business of distributing software, under which you make payment
+to the third party based on the extent of your activity of conveying
+the work, and under which the third party grants, to any of the
+parties who would receive the covered work from you, a discriminatory
+patent license (a) in connection with copies of the covered work
+conveyed by you (or copies made from those copies), or (b) primarily
+for and in connection with specific products or compilations that
+contain the covered work, unless you entered into that arrangement,
+or that patent license was granted, prior to 28 March 2007.
+
+  Nothing in this License shall be construed as excluding or limiting
+any implied license or other defenses to infringement that may
+otherwise be available to you under applicable patent law.
+
+  12. No Surrender of Others' Freedom.
+
+  If conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot convey a
+covered work so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you may
+not convey it at all.  For example, if you agree to terms that obligate you
+to collect a royalty for further conveying from those to whom you convey
+the Program, the only way you could satisfy both those terms and this
+License would be to refrain entirely from conveying the Program.
+
+  13. Use with the GNU Affero General Public License.
+
+  Notwithstanding any other provision of this License, you have
+permission to link or combine any covered work with a work licensed
+under version 3 of the GNU Affero General Public License into a single
+combined work, and to convey the resulting work.  The terms of this
+License will continue to apply to the part which is the covered work,
+but the special requirements of the GNU Affero General Public License,
+section 13, concerning interaction through a network will apply to the
+combination as such.
+
+  14. Revised Versions of this License.
+
+  The Free Software Foundation may publish revised and/or new versions of
+the GNU General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+  Each version is given a distinguishing version number.  If the
+Program specifies that a certain numbered version of the GNU General
+Public License "or any later version" applies to it, you have the
+option of following the terms and conditions either of that numbered
+version or of any later version published by the Free Software
+Foundation.  If the Program does not specify a version number of the
+GNU General Public License, you may choose any version ever published
+by the Free Software Foundation.
+
+  If the Program specifies that a proxy can decide which future
+versions of the GNU General Public License can be used, that proxy's
+public statement of acceptance of a version permanently authorizes you
+to choose that version for the Program.
+
+  Later license versions may give you additional or different
+permissions.  However, no additional obligations are imposed on any
+author or copyright holder as a result of your choosing to follow a
+later version.
+
+  15. Disclaimer of Warranty.
+
+  THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
+APPLICABLE LAW.  EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
+HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
+OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
+THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
+IS WITH YOU.  SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
+ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+  16. Limitation of Liability.
+
+  IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
+THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
+GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
+USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
+DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
+PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
+EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGES.
+
+  17. Interpretation of Sections 15 and 16.
+
+  If the disclaimer of warranty and limitation of liability provided
+above cannot be given local legal effect according to their terms,
+reviewing courts shall apply local law that most closely approximates
+an absolute waiver of all civil liability in connection with the
+Program, unless a warranty or assumption of liability accompanies a
+copy of the Program in return for a fee.
+
+                     END OF TERMS AND CONDITIONS
+
+            How to Apply These Terms to Your New Programs
+
+  If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+  To do so, attach the following notices to the program.  It is safest
+to attach them to the start of each source file to most effectively
+state the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the program's name and a brief idea of what it does.>
+    Copyright (C) <year>  <name of author>
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+Also add information on how to contact you by electronic and paper mail.
+
+  If the program does terminal interaction, make it output a short
+notice like this when it starts in an interactive mode:
+
+    <program>  Copyright (C) <year>  <name of author>
+    This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+    This is free software, and you are welcome to redistribute it
+    under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License.  Of course, your program's commands
+might be different; for a GUI interface, you would use an "about box".
+
+  You should also get your employer (if you work as a programmer) or school,
+if any, to sign a "copyright disclaimer" for the program, if necessary.
+For more information on this, and how to apply and follow the GNU GPL, see
+<http://www.gnu.org/licenses/>.
+
+  The GNU General Public License does not permit incorporating your program
+into proprietary programs.  If your program is a subroutine library, you
+may consider it more useful to permit linking proprietary applications with
+the library.  If this is what you want to do, use the GNU Lesser General
+Public License instead of this License.  But first, please read
+<http://www.gnu.org/philosophy/why-not-lgpl.html>.
diff --git a/src/libwebcam/COPYING.LESSER b/src/libwebcam/COPYING.LESSER
new file mode 100644
index 0000000..fc8a5de
--- /dev/null
+++ b/src/libwebcam/COPYING.LESSER
@@ -0,0 +1,165 @@
+		   GNU LESSER GENERAL PUBLIC LICENSE
+                       Version 3, 29 June 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+
+  This version of the GNU Lesser General Public License incorporates
+the terms and conditions of version 3 of the GNU General Public
+License, supplemented by the additional permissions listed below.
+
+  0. Additional Definitions. 
+
+  As used herein, "this License" refers to version 3 of the GNU Lesser
+General Public License, and the "GNU GPL" refers to version 3 of the GNU
+General Public License.
+
+  "The Library" refers to a covered work governed by this License,
+other than an Application or a Combined Work as defined below.
+
+  An "Application" is any work that makes use of an interface provided
+by the Library, but which is not otherwise based on the Library.
+Defining a subclass of a class defined by the Library is deemed a mode
+of using an interface provided by the Library.
+
+  A "Combined Work" is a work produced by combining or linking an
+Application with the Library.  The particular version of the Library
+with which the Combined Work was made is also called the "Linked
+Version".
+
+  The "Minimal Corresponding Source" for a Combined Work means the
+Corresponding Source for the Combined Work, excluding any source code
+for portions of the Combined Work that, considered in isolation, are
+based on the Application, and not on the Linked Version.
+
+  The "Corresponding Application Code" for a Combined Work means the
+object code and/or source code for the Application, including any data
+and utility programs needed for reproducing the Combined Work from the
+Application, but excluding the System Libraries of the Combined Work.
+
+  1. Exception to Section 3 of the GNU GPL.
+
+  You may convey a covered work under sections 3 and 4 of this License
+without being bound by section 3 of the GNU GPL.
+
+  2. Conveying Modified Versions.
+
+  If you modify a copy of the Library, and, in your modifications, a
+facility refers to a function or data to be supplied by an Application
+that uses the facility (other than as an argument passed when the
+facility is invoked), then you may convey a copy of the modified
+version:
+
+   a) under this License, provided that you make a good faith effort to
+   ensure that, in the event an Application does not supply the
+   function or data, the facility still operates, and performs
+   whatever part of its purpose remains meaningful, or
+
+   b) under the GNU GPL, with none of the additional permissions of
+   this License applicable to that copy.
+
+  3. Object Code Incorporating Material from Library Header Files.
+
+  The object code form of an Application may incorporate material from
+a header file that is part of the Library.  You may convey such object
+code under terms of your choice, provided that, if the incorporated
+material is not limited to numerical parameters, data structure
+layouts and accessors, or small macros, inline functions and templates
+(ten or fewer lines in length), you do both of the following:
+
+   a) Give prominent notice with each copy of the object code that the
+   Library is used in it and that the Library and its use are
+   covered by this License.
+
+   b) Accompany the object code with a copy of the GNU GPL and this license
+   document.
+
+  4. Combined Works.
+
+  You may convey a Combined Work under terms of your choice that,
+taken together, effectively do not restrict modification of the
+portions of the Library contained in the Combined Work and reverse
+engineering for debugging such modifications, if you also do each of
+the following:
+
+   a) Give prominent notice with each copy of the Combined Work that
+   the Library is used in it and that the Library and its use are
+   covered by this License.
+
+   b) Accompany the Combined Work with a copy of the GNU GPL and this license
+   document.
+
+   c) For a Combined Work that displays copyright notices during
+   execution, include the copyright notice for the Library among
+   these notices, as well as a reference directing the user to the
+   copies of the GNU GPL and this license document.
+
+   d) Do one of the following:
+
+       0) Convey the Minimal Corresponding Source under the terms of this
+       License, and the Corresponding Application Code in a form
+       suitable for, and under terms that permit, the user to
+       recombine or relink the Application with a modified version of
+       the Linked Version to produce a modified Combined Work, in the
+       manner specified by section 6 of the GNU GPL for conveying
+       Corresponding Source.
+
+       1) Use a suitable shared library mechanism for linking with the
+       Library.  A suitable mechanism is one that (a) uses at run time
+       a copy of the Library already present on the user's computer
+       system, and (b) will operate properly with a modified version
+       of the Library that is interface-compatible with the Linked
+       Version. 
+
+   e) Provide Installation Information, but only if you would otherwise
+   be required to provide such information under section 6 of the
+   GNU GPL, and only to the extent that such information is
+   necessary to install and execute a modified version of the
+   Combined Work produced by recombining or relinking the
+   Application with a modified version of the Linked Version. (If
+   you use option 4d0, the Installation Information must accompany
+   the Minimal Corresponding Source and Corresponding Application
+   Code. If you use option 4d1, you must provide the Installation
+   Information in the manner specified by section 6 of the GNU GPL
+   for conveying Corresponding Source.)
+
+  5. Combined Libraries.
+
+  You may place library facilities that are a work based on the
+Library side by side in a single library together with other library
+facilities that are not Applications and are not covered by this
+License, and convey such a combined library under terms of your
+choice, if you do both of the following:
+
+   a) Accompany the combined library with a copy of the same work based
+   on the Library, uncombined with any other library facilities,
+   conveyed under the terms of this License.
+
+   b) Give prominent notice with the combined library that part of it
+   is a work based on the Library, and explaining where to find the
+   accompanying uncombined form of the same work.
+
+  6. Revised Versions of the GNU Lesser General Public License.
+
+  The Free Software Foundation may publish revised and/or new versions
+of the GNU Lesser General Public License from time to time. Such new
+versions will be similar in spirit to the present version, but may
+differ in detail to address new problems or concerns.
+
+  Each version is given a distinguishing version number. If the
+Library as you received it specifies that a certain numbered version
+of the GNU Lesser General Public License "or any later version"
+applies to it, you have the option of following the terms and
+conditions either of that published version or of any later version
+published by the Free Software Foundation. If the Library as you
+received it does not specify a version number of the GNU Lesser
+General Public License, you may choose any version of the GNU Lesser
+General Public License ever published by the Free Software Foundation.
+
+  If the Library as you received it specifies that a proxy can decide
+whether future versions of the GNU Lesser General Public License shall
+apply, that proxy's public statement of acceptance of any version is
+permanent authorization for you to choose that version for the
+Library.
diff --git a/src/libwebcam/Makefile.am b/src/libwebcam/Makefile.am
new file mode 100644
index 0000000..285cd89
--- /dev/null
+++ b/src/libwebcam/Makefile.am
@@ -0,0 +1,9 @@
+noinst_HEADERS = compat.h  dynctrl-logitech.h  libwebcam.h  uvcvideo.h  webcam.h
+	
+dist_noinst_DATA = COPYING.LESSER README COPYING
+
+libwebcam_la_LIBADD = -lpthread
+	
+noinst_LTLIBRARIES = libwebcam.la
+
+libwebcam_la_SOURCES = libwebcam.c
diff --git a/src/libwebcam/README b/src/libwebcam/README
new file mode 100644
index 0000000..7c3635c
--- /dev/null
+++ b/src/libwebcam/README
@@ -0,0 +1,128 @@
+libwebcam Webcam Library
+========================
+
+Introduction
+------------
+
+The Webcam Library libwebcam is designed to simplify the development of webcam
+applications, primarily on Linux but with an option to be ported to other
+platforms, in particular Solaris. It realizes part of what the unwritten
+Video4Linux user space library was always supposed to be: an easy to use
+library that shields its users from many of the difficulties and problems of
+using the V4L2 API directly.
+
+Today libwebcam provides the following core features:
+
+* Enumeration of all cameras available in the system.
+* Provide detailed information about the detected devices and their controls.
+* Wrapper for the V4L2 frame format enumeration.
+* Convenient access to device controls.
+* Support for configuring the Linux UVC driver's dynamic controls (extension
+  unit controls).
+
+In addition, the interface is prepared to handle device events ranging from
+newly detected cameras over control value changes to device button events.
+It is easy to add new features without breaking application compatibility and
+the addition of new controls or events is straightforward.
+
+
+Change log
+----------
+
+0.2.0 (under development):
+- Reorganized the directory layout and build system (CMake 2.6 is required now).
+- Added packaging support (.deb and .tar.bz2).
+- Added support for raw/string controls.
+- Minor bugfixes and code cleanups
+
+0.1.4-pre (unreleased, SVN tag only):
+Note: This is the last version to use the old directory layout and CMake 2.4.
+- Improved udev support (udev >= 141 is required now).
+
+0.1.3-pre (unreleased, SVN tag only):
+Note: This is the last version to work with older versions of udev.
+- Added support for some Logitech specific dynamic controls: LED1 mode, LED1
+  frequency, Disable color processing, Raw bits per pixel
+- Added a check for driver misbehavior related to V4L2_CTRL_FLAG_NEXT_CTRL and
+  avoid an endless control enumeration loop.
+- Disable the UVC driver's caching mechanism for XU controls.
+- Build system: Use the CMAKE_INSTALL_LIBDIR variable for the library
+  installation path. This should fix problems on Fedora 64-bit.
+
+0.1.2 (2009-07-08):
+- Update the controls to work better with the latest version of the UVC driver
+  that is part of the kernel.
+- Improved control handling by adding a list of well-known controls. This
+  allows libwebcam to recognize certain controls even if header files on the
+  build system do not match the current system.
+- Better handling of unknown control IDs.
+- Improved warning/error messages related to controls.
+
+0.1.1 (2008-01-29):
+- Added support the V4L2_CTRL_FLAG_READ_ONLY flag.
+- Added per handle tracking of the last system error and a new
+  c_get_handle_error_text function that allows a handle's last system error
+  to be retrieved in certain cases (C_V4L2_ERROR).
+- Added a test to check whether the driver supports dynamic controls or not.
+  This should prevent some confusing error 22 messages when "uvcdynctrl -i" is
+  used with an old driver.
+- Process meta information and constants only while parsing the XML document
+  for the first time (during the first device).
+- Implemented support for processing statistics.
+- Added some informational messages, e.g. about skipped devices.
+- Added a define to suppress EEXIST errors for all but the first device.
+- Improved the way the device is picked. Instead of just taking the first
+  device, all devices are now looped through and supported UVC devices get
+  their controls and mappings added. This is not quite necessary at the moment
+  because the UVC driver still has global controls but that may change in the
+  future.
+- Added a stub implementation of c_add_control_mappings_from_file for when
+  DISABLE_UVCVIDEO_DYNCTRL is set.
+- Added a workaround for the current UVC driver's problematic
+  V4L2_CID_EXPOSURE_AUTO control. This is a menu control whose menu choices
+  don't have contiguous IDs but { 1, 2, 4, 8 } instead. For the moment, the
+  library just skips that control.
+- Improved detection of invalid menu controls whose full choice range is not
+  correctly queriable.
+- Fix: Bogus warning messages related to the V4L2 control types 'Button' and
+  'Integer64'. Support for these types in libwebcam is still missing, though.
+- Fix: Device enumeration issue with V4L1 devices present in the system.
+- Fix: Reorganizations in the control enumeration code and inclusion of a
+  workaround for some dangerous behavior in the bttv driver. (Thanks to Bruno
+  Grasland for his bttv testing!)
+- Fix: Problem in c_enum_frame_intervals if a non-discrete frame size was
+  passed. The function now returns C_INVALID_ARG in this case.
+- Fix: A segfault would occur in c_enum_pixel_formats with unknown pixel
+  formats (i.e. pixel formats without hardcoded MIME type).
+- Fix: Disabling USE_UVCVIDEO now works again and also sets
+  DISABLE_UVCVIDEO_DYNCTRL. This allows compiling libwebcam without the
+  uvcvideo header files.
+
+0.1: Initial release
+
+
+Building, questions, and feedback
+---------------------------------
+
+Please see the README file in the top level directory for building
+instructions and how to contact the developers.
+
+
+Copyright and license
+---------------------
+
+Copyright (c) 2006-2010 Logitech.
+
+libwebcam is free software: you can redistribute it and/or modify
+it under the terms of the GNU Lesser General Public License as published
+by the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+libwebcam is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public License
+along with libwebcam.  If not, see <http://www.gnu.org/licenses/>.
+
diff --git a/src/libwebcam/README.eviacam b/src/libwebcam/README.eviacam
new file mode 100644
index 0000000..b43a44f
--- /dev/null
+++ b/src/libwebcam/README.eviacam
@@ -0,0 +1 @@
+Temporarily added to the source tree for convenience until major distributions include libwebcam
diff --git a/src/libwebcam/compat.h b/src/libwebcam/compat.h
new file mode 100644
index 0000000..1984d64
--- /dev/null
+++ b/src/libwebcam/compat.h
@@ -0,0 +1,149 @@
+/**
+ * \file
+ * Declarations for compatibility with different V4L2 versions.
+ *
+ * \ingroup libwebcam
+ */
+
+/*
+ * Copyright (c) 2006-2009 Logitech.
+ *
+ * This file is part of libwebcam.
+ * 
+ * libwebcam is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ * 
+ * libwebcam is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with libwebcam.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef C_COMPAT_H
+#define C_COMPAT_H
+
+//#include <linux/videodev.h>
+#include "incvideodev.h"
+#include <linux/videodev2.h>
+
+#ifdef USE_UVCVIDEO
+#define __user
+#include "uvcvideo.h"
+#endif
+
+
+// uvcvideo.h
+
+// Old uvcvideo pre-r178 control IDs
+#define UVC_CID_BACKLIGHT_COMPENSATION			(V4L2_CID_PRIVATE_BASE+0)
+#define UVC_CID_POWER_LINE_FREQUENCY			(V4L2_CID_PRIVATE_BASE+1)
+#define UVC_CID_SHARPNESS						(V4L2_CID_PRIVATE_BASE+2)
+#define UVC_CID_HUE_AUTO						(V4L2_CID_PRIVATE_BASE+3)
+#define UVC_CID_FOCUS_AUTO						(V4L2_CID_PRIVATE_BASE+4)
+#define UVC_CID_FOCUS_ABSOLUTE					(V4L2_CID_PRIVATE_BASE+5)
+#define UVC_CID_FOCUS_RELATIVE					(V4L2_CID_PRIVATE_BASE+6)
+#define UVC_CID_PAN_RELATIVE					(V4L2_CID_PRIVATE_BASE+7)
+#define UVC_CID_TILT_RELATIVE					(V4L2_CID_PRIVATE_BASE+8)
+#define UVC_CID_PANTILT_RESET					(V4L2_CID_PRIVATE_BASE+9)
+#define UVC_CID_EXPOSURE_AUTO					(V4L2_CID_PRIVATE_BASE+10)
+#define UVC_CID_EXPOSURE_ABSOLUTE				(V4L2_CID_PRIVATE_BASE+11)
+#define UVC_CID_EXPOSURE_AUTO_PRIORITY			(V4L2_CID_PRIVATE_BASE+14)
+#define UVC_CID_WHITE_BALANCE_TEMPERATURE_AUTO	(V4L2_CID_PRIVATE_BASE+12)
+#define UVC_CID_WHITE_BALANCE_TEMPERATURE		(V4L2_CID_PRIVATE_BASE+13)
+
+
+// videodev2.h
+
+// Class IDs
+#ifndef V4L2_CTRL_CLASS_USER
+#define V4L2_CTRL_CLASS_USER			0x00980000
+#endif
+#ifndef V4L2_CTRL_CLASS_MPEG
+#define V4L2_CTRL_CLASS_MPEG			0x00990000
+#endif
+#ifndef V4L2_CTRL_CLASS_CAMERA
+#define V4L2_CTRL_CLASS_CAMERA			0x009a0000
+#endif
+
+// Macros
+#ifndef V4L2_CTRL_ID2CLASS
+#define V4L2_CTRL_ID2CLASS(id)			((id) & 0x0fff0000UL)
+#endif
+
+// User controls from newer V4L2 versions
+#ifndef V4L2_CID_POWER_LINE_FREQUENCY
+#define V4L2_CID_POWER_LINE_FREQUENCY		(V4L2_CID_BASE+24)
+#endif
+#ifndef V4L2_CID_HUE_AUTO
+#define V4L2_CID_HUE_AUTO					(V4L2_CID_BASE+25)
+#endif
+#ifndef V4L2_CID_WHITE_BALANCE_TEMPERATURE
+#define V4L2_CID_WHITE_BALANCE_TEMPERATURE	(V4L2_CID_BASE+26)
+#endif
+#ifndef V4L2_CID_SHARPNESS
+#define V4L2_CID_SHARPNESS					(V4L2_CID_BASE+27)
+#endif
+#ifndef V4L2_CID_BACKLIGHT_COMPENSATION
+#define V4L2_CID_BACKLIGHT_COMPENSATION		(V4L2_CID_BASE+28)
+#endif
+
+// Camera class controls from newer V4L2 versions
+#ifndef V4L2_CID_CAMERA_CLASS_BASE
+#define V4L2_CID_CAMERA_CLASS_BASE		(V4L2_CTRL_CLASS_CAMERA | 0x900)
+#endif
+#ifndef V4L2_CID_EXPOSURE_AUTO
+#define V4L2_CID_EXPOSURE_AUTO			(V4L2_CID_CAMERA_CLASS_BASE+1)
+#endif
+#ifndef V4L2_CID_EXPOSURE_ABSOLUTE
+#define V4L2_CID_EXPOSURE_ABSOLUTE		(V4L2_CID_CAMERA_CLASS_BASE+2)
+#endif
+#ifndef V4L2_CID_EXPOSURE_AUTO_PRIORITY
+#define V4L2_CID_EXPOSURE_AUTO_PRIORITY	(V4L2_CID_CAMERA_CLASS_BASE+3)
+#endif
+#ifndef V4L2_CID_PAN_RELATIVE
+#define V4L2_CID_PAN_RELATIVE			(V4L2_CID_CAMERA_CLASS_BASE+4)
+#endif
+#ifndef V4L2_CID_TILT_RELATIVE
+#define V4L2_CID_TILT_RELATIVE			(V4L2_CID_CAMERA_CLASS_BASE+5)
+#endif
+#ifndef V4L2_CID_PAN_RESET
+#define V4L2_CID_PAN_RESET				(V4L2_CID_CAMERA_CLASS_BASE+6)
+#endif
+#ifndef V4L2_CID_TILT_RESET
+#define V4L2_CID_TILT_RESET				(V4L2_CID_CAMERA_CLASS_BASE+7)
+#endif
+#ifndef V4L2_CID_PAN_ABSOLUTE
+#define V4L2_CID_PAN_ABSOLUTE			(V4L2_CID_CAMERA_CLASS_BASE+8)
+#endif
+#ifndef V4L2_CID_TILT_ABSOLUTE
+#define V4L2_CID_TILT_ABSOLUTE			(V4L2_CID_CAMERA_CLASS_BASE+9)
+#endif
+#ifndef V4L2_CID_FOCUS_ABSOLUTE
+#define V4L2_CID_FOCUS_ABSOLUTE			(V4L2_CID_CAMERA_CLASS_BASE+10)
+#endif
+#ifndef V4L2_CID_FOCUS_RELATIVE
+#define V4L2_CID_FOCUS_RELATIVE			(V4L2_CID_CAMERA_CLASS_BASE+11)
+#endif
+#ifndef V4L2_CID_FOCUS_AUTO
+#define V4L2_CID_FOCUS_AUTO				(V4L2_CID_CAMERA_CLASS_BASE+12)
+#endif
+#ifndef V4L2_CID_ZOOM_ABSOLUTE
+#define V4L2_CID_ZOOM_ABSOLUTE			(V4L2_CID_CAMERA_CLASS_BASE+13)
+#endif
+#ifndef V4L2_CID_ZOOM_RELATIVE
+#define V4L2_CID_ZOOM_RELATIVE			(V4L2_CID_CAMERA_CLASS_BASE+14)
+#endif
+#ifndef V4L2_CID_ZOOM_CONTINUOUS
+#define V4L2_CID_ZOOM_CONTINUOUS		(V4L2_CID_CAMERA_CLASS_BASE+15)
+#endif
+#ifndef V4L2_CID_PRIVACY
+#define V4L2_CID_PRIVACY				(V4L2_CID_CAMERA_CLASS_BASE+16)
+#endif
+
+
+#endif /* C_COMPAT_H */
diff --git a/src/libwebcam/dynctrl-logitech.h b/src/libwebcam/dynctrl-logitech.h
new file mode 100644
index 0000000..6cf68a7
--- /dev/null
+++ b/src/libwebcam/dynctrl-logitech.h
@@ -0,0 +1,108 @@
+
+/*
+ * UVC dynamic control mapping header file
+ *
+ * This file has been dynamically generated using the include.xsl XSLT
+ * transform stylesheet from a dynamic control mapping configuration file.
+ *
+ * Version: 1.0
+ * Author: Martin Rubli, Logitech
+ * Contact: http://www.quickcamteam.net/
+ * Revision: 0.16
+ *
+ * Copyright (c) 2006-2008 Logitech
+ */
+
+
+/* Start constants */
+	
+#ifndef UVC_GUID_LOGITECH_USER_HW_CONTROL
+#define UVC_GUID_LOGITECH_USER_HW_CONTROL { \
+	0x82, 0x06, 0x61, 0x63, 0x70, 0x50, 0xab, 0x49, \
+	0xb8, 0xcc, 0xb3, 0x85, 0x5e, 0x8d, 0x22, 0x1f  \
+}
+		
+#endif
+
+#ifndef UVC_GUID_LOGITECH_VIDEO_PIPE
+#define UVC_GUID_LOGITECH_VIDEO_PIPE { \
+	0x82, 0x06, 0x61, 0x63, 0x70, 0x50, 0xab, 0x49, \
+	0xb8, 0xcc, 0xb3, 0x85, 0x5e, 0x8d, 0x22, 0x50  \
+}
+		
+#endif
+
+#ifndef UVC_GUID_LOGITECH_MOTOR_CONTROL
+#define UVC_GUID_LOGITECH_MOTOR_CONTROL { \
+	0x82, 0x06, 0x61, 0x63, 0x70, 0x50, 0xab, 0x49, \
+	0xb8, 0xcc, 0xb3, 0x85, 0x5e, 0x8d, 0x22, 0x56  \
+}
+		
+#endif
+
+#ifndef XU_HW_CONTROL_LED1
+#define XU_HW_CONTROL_LED1 1
+#endif
+
+#ifndef XU_COLOR_PROCESSING_DISABLE
+#define XU_COLOR_PROCESSING_DISABLE 5
+#endif
+
+#ifndef XU_RAW_DATA_BITS_PER_PIXEL
+#define XU_RAW_DATA_BITS_PER_PIXEL 8
+#endif
+
+#ifndef XU_MOTORCONTROL_PANTILT_RELATIVE
+#define XU_MOTORCONTROL_PANTILT_RELATIVE 1
+#endif
+
+#ifndef XU_MOTORCONTROL_PANTILT_RESET
+#define XU_MOTORCONTROL_PANTILT_RESET 2
+#endif
+
+#ifndef XU_MOTORCONTROL_FOCUS
+#define XU_MOTORCONTROL_FOCUS 3
+#endif
+
+#ifndef V4L2_CID_PAN_RELATIVE
+#define V4L2_CID_PAN_RELATIVE 0x009A0904
+#endif
+
+#ifndef V4L2_CID_TILT_RELATIVE
+#define V4L2_CID_TILT_RELATIVE 0x009A0905
+#endif
+
+#ifndef V4L2_CID_PANTILT_RESET
+#define V4L2_CID_PANTILT_RESET 0x0A046D03
+#endif
+
+#ifndef V4L2_CID_PAN_RESET
+#define V4L2_CID_PAN_RESET 0x009A0906
+#endif
+
+#ifndef V4L2_CID_TILT_RESET
+#define V4L2_CID_TILT_RESET 0x009A0907
+#endif
+
+#ifndef V4L2_CID_FOCUS
+#define V4L2_CID_FOCUS 0x0A046D04
+#endif
+
+#ifndef V4L2_CID_LED1_MODE
+#define V4L2_CID_LED1_MODE 0x0A046D05
+#endif
+
+#ifndef V4L2_CID_LED1_FREQUENCY
+#define V4L2_CID_LED1_FREQUENCY 0x0A046D06
+#endif
+
+#ifndef V4L2_CID_DISABLE_PROCESSING
+#define V4L2_CID_DISABLE_PROCESSING 0x0A046D71
+#endif
+
+#ifndef V4L2_CID_RAW_BITS_PER_PIXEL
+#define V4L2_CID_RAW_BITS_PER_PIXEL 0x0A046D72
+#endif
+
+
+/* End constants */
diff --git a/src/libwebcam/incvideodev.h.in b/src/libwebcam/incvideodev.h.in
new file mode 100644
index 0000000..e313e1e
--- /dev/null
+++ b/src/libwebcam/incvideodev.h.in
@@ -0,0 +1 @@
+#include "@VIDEODEV_INCLUDE_FILE@"
diff --git a/src/libwebcam/libwebcam.c b/src/libwebcam/libwebcam.c
new file mode 100644
index 0000000..7af753d
--- /dev/null
+++ b/src/libwebcam/libwebcam.c
@@ -0,0 +1,2550 @@
+/**
+ * \file
+ * Webcam library implementation.
+ *
+ * \ingroup libwebcam
+ */
+
+/*
+ * Copyright (c) 2006-2008 Logitech.
+ *
+ * This file is part of libwebcam.
+ *
+ * libwebcam is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * libwebcam is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with libwebcam.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef _GNU_SOURCE
+	#define _GNU_SOURCE
+#endif
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include <limits.h>
+#include <dirent.h>
+#include <pthread.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdarg.h>
+#include <sys/ioctl.h>
+#include <errno.h>
+
+#include "webcam.h"
+#include "libwebcam.h"
+
+#include "compat.h"
+
+#ifdef USE_LOGITECH_DYNCTRL
+#include "dynctrl-logitech.h"
+#endif
+
+
+/// A flag indicating whether the library was initialized.
+int initialized = 0;
+/// A list of webcam devices found in the system.
+static DeviceList device_list;
+/// The fixed size list of file handles.
+HandleList handle_list;
+
+
+/*
+ * Forward declarations
+ */
+
+void print_libwebcam_error (char *format, ...);
+static void print_libwebcam_c_error (CResult error, char *format, ...);
+
+static unsigned int get_control_dynamics_length(Device *device, unsigned int *names_length, unsigned int *choices_length);
+static Control *find_control_by_id (Device *dev, CControlId id);
+
+static CResult refresh_device_list (void);
+static Device *find_device_by_name (const char *name);
+static int get_device_dynamics_length (CDevice *device);
+static int get_devices_dynamics_length (void);
+
+int open_v4l2_device(char *device_name);
+static CResult read_v4l2_control(Device *device, Control *control, CControlValue *value, CHandle hDevice);
+static CResult write_v4l2_control(Device *device, Control *control, const CControlValue *value, CHandle hDevice);
+static CControlId get_control_id_from_v4l2 (int v4l2_id, Device *dev);
+
+static CResult get_device_usb_info (Device *device, CUSBInfo *usbinfo);
+static CResult get_mimetype_from_fourcc(char **mimetype, unsigned int fourcc);
+
+static CHandle create_handle(Device *device);
+static void close_handle(CHandle handle);
+static void set_last_error(CHandle hDevice, int error);
+
+
+/*
+ * Devices
+ */
+
+/**
+ * Opens a camera device.
+ *
+ * The function returns a handle that can be used for all functions that require
+ * a device handle.
+ *
+ * @param device_name	Name of the device to open.
+ * 						Two different naming schemes are accepted: Full device names
+ * 						(e.g. '/dev/video0') and short names (e.g. 'video0') as
+ * 						returned by c_enum_devices().
+ * @return
+ * 		- a device handle greater than zero on success
+ * 		- 0 if an error has occurred
+ */
+CHandle c_open_device (const char *device_name)
+{
+	CHandle handle;
+	const char *v4l2_name;
+
+	if(device_name == NULL || !initialized) {
+		print_libwebcam_error("Unable to open device. No name given or library not initialized.");
+		return 0;
+	}
+
+	// Try to find the device with the given name.
+	// Note: If the given name is a device path (e.g. /dev/video0), the V4L2 name
+	// is simply generated by cutting off the '/dev/' part. If the given name
+	// starts with 'video', it is taken as is.
+	if(strstr(device_name, "/dev/video") == device_name)
+		v4l2_name = &device_name[5];
+	else if(strstr(device_name, "video") == device_name)
+		v4l2_name = device_name;
+	else {
+		print_libwebcam_error("Unable to open device '%s'. Unrecognized device name.", device_name);
+		return 0;
+	}
+	Device *device = find_device_by_name(v4l2_name);
+	if(device == NULL) {
+		print_libwebcam_error("Unable to open device '%s'. Device not found.", device_name);
+		return 0;
+	}
+
+	// Open device when needed
+	if (device->fd== 0) {
+		device->fd= open_v4l2_device(device->v4l2_name);
+		if (device->fd<= 0) {
+			print_libwebcam_error("open sys call failed for %s'.", device_name);
+			// Open error
+			device->fd= 0;
+			return 0;
+		}
+	}
+
+	// Create a handle for the given device
+	// TODO Race condition if delete_device is called here (via c_cleanup)
+	handle = create_handle(device);
+	if (handle== 0) {
+		close(device->fd);
+		device->fd= 0;
+	}
+	return handle;
+}
+
+
+/**
+ * Closes a device handle.
+ *
+ * @param	hDevice		a handle obtained from c_open_device()
+ */
+void c_close_device (CHandle hDevice)
+{
+	if(!initialized)
+		return;
+	close_handle(hDevice);
+}
+
+/**
+ * Given a handle returns the corresponding file descriptor.
+ *
+ * The function returns a file descriptor that can be used for low level operations outside
+ * this library.
+ *
+ * @param	hDevice		a handle obtained from c_open_device()
+ *
+ * @return
+ * 		- a file descriptor greater than zero on success
+ * 		- 0 if an error has occurred
+ */
+int c_get_file_descriptor (CHandle hDevice)
+{
+	// Check the given handle and arguments
+	if(!initialized)
+		return 0;
+	if(!HANDLE_OPEN(hDevice))
+		return 0;
+	if(!HANDLE_VALID(hDevice))
+		return 0;
+	Device *device = GET_HANDLE(hDevice).device;
+	if (!device) return 0;
+	
+	return device->fd;
+}
+
+/**
+ * Enumerates all devices available in the system.
+ *
+ * Users must call c_init() prior to using this function.
+ *
+ * If the buffer is not large enough, #C_BUFFER_TOO_SMALL is returned and
+ * the \a size parameter is modified to contain the required buffer size.
+ *
+ * @param	devices		a pointer to a buffer that retrieves the list of devices
+ * @param	size		a pointer to an integer that contains or receives the size
+ * 						of the @a devices buffer
+ * @param	count		a pointer to an integer that receives the number of devices
+ * 						available. Can be NULL. If this argument is not NULL, the
+ * 						device count is returned independent of whether or not the
+ * 						buffer is large enough.
+ * @return
+ * 		- #C_SUCCESS on success
+ * 		- #C_INIT_ERROR if the library has not been initialized
+ * 		- #C_SYNC_ERROR if the synchronization structures could not be initialized
+ * 		- #C_INVALID_ARG if no size pointer was given or if a size pointer was given
+ * 		  but no @a devices buffer was given
+ * 		- #C_BUFFER_TOO_SMALL if the supplied buffer is not large enough
+ */
+CResult c_enum_devices (CDevice *devices, unsigned int *size, unsigned int *count)
+{
+	CResult ret = C_SUCCESS;
+
+	if(!initialized)
+		return C_INIT_ERROR;
+	if(size == NULL)
+		return C_INVALID_ARG;
+
+	// Refresh the internal device list
+	ret = refresh_device_list();
+	if(ret) return ret;
+
+	if(lock_mutex(&device_list.mutex))
+		return C_SYNC_ERROR;
+
+	// Return the required size if the given size is not large enough
+	if(count)
+		*count = device_list.count;
+	int dynamics_length = get_devices_dynamics_length();
+	int req_size = device_list.count * sizeof(CDevice) + dynamics_length;
+	if(req_size > *size) {
+		*size = req_size;
+		ret = C_BUFFER_TOO_SMALL;
+		goto done;
+	}
+	if(device_list.count == 0)
+		goto done;
+	if(devices == NULL) {
+		ret = C_INVALID_ARG;
+		goto done;
+	}
+
+	// Loop through all devices and return a list of CDevice structs
+	CDevice *current = devices;
+	Device *elem = device_list.first;
+	unsigned int dynamics_offset = device_list.count * sizeof(CDevice);
+	while(elem) {
+		// Copy the simple attributes
+		memcpy(current, &elem->device, sizeof(elem->device));
+
+		// Copy the strings
+		copy_string_to_buffer(&current->shortName,	elem->device.shortName, devices, &dynamics_offset);
+		copy_string_to_buffer(&current->name,		elem->device.name,		devices, &dynamics_offset);
+		copy_string_to_buffer(&current->driver,		elem->device.driver,	devices, &dynamics_offset);
+		copy_string_to_buffer(&current->location,	elem->device.location,	devices, &dynamics_offset);
+
+		current++;
+		elem = elem->next;
+	}
+	assert(dynamics_offset == req_size);
+
+done:
+	unlock_mutex(&device_list.mutex);
+	return ret;
+}
+
+
+/**
+ * Returns information about a given camera device.
+ *
+ * The function returns information about a device specified using a device handle
+ * obtained from c_open_device() or a string that would be recognized by the same
+ * function. The @a hDevice and @a device_name arguments are mutually exclusive.
+ * If both are specified, the handle is used. If the device name should be used,
+ * @a hDevice should be set to zero.
+ *
+ * If the buffer is not large enough, #C_BUFFER_TOO_SMALL is returned and
+ * the \a size parameter is modified to contain the required buffer size.
+ *
+ * Specifying a size of sizeof(CDevice) + strlen(device_name) + 84 will usually
+ * be enough. This information can be used to try receiving device information in
+ * a statically allocated buffer first. The number comes from the field lengths
+ * that V4L2 uses internally. There is no guarantee, however, that this does not
+ * change in the future, so applications must be prepared to allocate more memory
+ * if indicated by a return value of #C_BUFFER_TOO_SMALL.
+ *
+ * @param hDevice		a handle obtained from c_open_device()
+ * @param device_name	a device name as accepted by c_open_device()
+ * @param info			a pointer to a buffer to receive the device information
+ * @param size			a pointer to an integer that contains or receives the size
+ * 						of the @a info buffer
+ * @return
+ * 		- #C_SUCCESS on success
+ * 		- #C_INIT_ERROR if the library has not been initialized
+ * 		- #C_SYNC_ERROR if the synchronization structures could not be initialized
+ * 		- #C_INVALID_ARG if no size pointer was given or if a size pointer was given
+ * 		  but no @a info buffer was given
+ * 		- #C_INVALID_HANDLE if a non-zero invalid handle was specified
+ * 		- #C_BUFFER_TOO_SMALL if the supplied buffer is not large enough
+ */
+CResult c_get_device_info (CHandle hDevice, const char *device_name, CDevice *info, unsigned int *size)
+{
+	CDevice *info_src;
+
+	if(!initialized)
+		return C_INIT_ERROR;
+	if(size == NULL)
+		return C_INVALID_ARG;
+
+	// Look for the device
+	if(hDevice) {				// By device handle
+		if(!HANDLE_OPEN(hDevice))
+			return C_INVALID_HANDLE;
+		if(!HANDLE_VALID(hDevice))
+			return C_NOT_EXIST;
+		info_src = &GET_HANDLE(hDevice).device->device;
+	}
+	else if(device_name) {		// By device name
+		Device *device = find_device_by_name(device_name);
+		if(device == NULL)
+			return C_NOT_FOUND;
+		info_src = &device->device;
+	}
+	else {
+		return C_INVALID_ARG;
+	}
+
+	// Return the required size if the given size is not large enough
+	int dynamics_length = get_device_dynamics_length(info_src);
+	int req_size = sizeof(*info_src) + dynamics_length;
+	if(req_size > *size) {
+		*size = req_size;
+		return C_BUFFER_TOO_SMALL;
+	}
+	if(info == NULL)
+		return C_INVALID_ARG;
+
+	// Copy the simple values
+	memcpy(info, info_src, sizeof(*info_src));
+
+	// Copy the strings
+	unsigned int dynamics_offset = sizeof(*info_src);
+	copy_string_to_buffer(&info->shortName,	info_src->shortName, info, &dynamics_offset);
+	copy_string_to_buffer(&info->name,		info_src->name,		 info, &dynamics_offset);
+	copy_string_to_buffer(&info->driver,	info_src->driver,	 info, &dynamics_offset);
+	copy_string_to_buffer(&info->location,	info_src->location,	 info, &dynamics_offset);
+	assert(dynamics_offset == req_size);
+
+	return C_SUCCESS;
+}
+
+
+
+/*
+ * Frame format enumeration
+ */
+
+/**
+ * Enumerates all pixel formats supported by the given camera.
+ *
+ * If the buffer is not large enough, #C_BUFFER_TOO_SMALL is returned and
+ * the \a size parameter is modified to contain the required buffer size.
+ *
+ * @param 	hDevice		a handle obtained from c_open_device()
+ * @param	formats		a pointer to a buffer that retrieves the list of pixel formats
+ * @param	size		a pointer to an integer that contains or receives the size
+ * 						of the @a formats buffer
+ * @param	count		a pointer to an integer that receives the number of pixel
+ * 						formats supported. Can be NULL. If this argument is not NULL,
+ * 						the device count is returned independent of whether or not
+ * 						the buffer is large enough.
+ * @return
+ * 		- #C_SUCCESS on success
+ * 		- #C_INIT_ERROR if the library has not been initialized
+ * 		- #C_INVALID_HANDLE if the given device handle is invalid
+ * 		- #C_INVALID_ARG if no size pointer was given or if a size pointer was given
+ * 		  but no @a formats buffer was given
+ * 		- #C_INVALID_DEVICE if the device could not be opened
+ * 		- #C_BUFFER_TOO_SMALL if the supplied buffer is not large enough
+ * 		- #C_NO_MEMORY if no temporary memory could be allocated
+ * 		- #C_V4L2_ERROR if a V4L2 error occurred during pixel format enumeration
+ */
+CResult c_enum_pixel_formats (CHandle hDevice, CPixelFormat *formats, unsigned int *size, unsigned int *count)
+{
+	CResult ret = C_SUCCESS;
+	int v4l2_dev;
+
+	// Check the given handle and arguments
+	if(!initialized)
+		return C_INIT_ERROR;
+	if(!HANDLE_OPEN(hDevice))
+		return C_INVALID_HANDLE;
+	if(!HANDLE_VALID(hDevice))
+		return C_NOT_EXIST;
+	Device *device = GET_HANDLE(hDevice).device;
+	if(size == NULL)
+		return C_INVALID_ARG;
+
+	// Open the corresponding V4L2 device
+	v4l2_dev = device->fd; //open_v4l2_device(device->v4l2_name);
+	if(!v4l2_dev)
+		return C_INVALID_DEVICE;
+
+	// Run V4L2 pixel format enumeration
+	typedef struct _PixelFormat {
+		CPixelFormat		format;
+		struct _PixelFormat	* next;
+	} PixelFormat;
+	PixelFormat *head = NULL, *tail = NULL;
+	unsigned int req_size = 0, format_count = 0;
+	struct v4l2_fmtdesc fmt;
+	memset(&fmt, 0, sizeof(fmt));
+	fmt.index = 0;
+	fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+	while(ioctl(v4l2_dev, VIDIOC_ENUM_FMT, &fmt) == 0) {
+		PixelFormat *format = (PixelFormat *)malloc(sizeof(PixelFormat));
+		if(!format) {
+			ret = C_NO_MEMORY;
+			goto done;
+		}
+		memset(format, 0, sizeof(PixelFormat));
+		fmt.index++;
+
+		// Copy the pixel format attributes
+		sprintf(format->format.fourcc, "%c%c%c%c",
+				fmt.pixelformat & 0xFF, (fmt.pixelformat >> 8) & 0xFF,
+				(fmt.pixelformat >> 16) & 0xFF, (fmt.pixelformat >> 24) & 0xFF);
+		format->format.name = strdup((char *)fmt.description);
+		req_size += sizeof(CPixelFormat) + strlen(format->format.name) + 1;
+		if(!get_mimetype_from_fourcc(&format->format.mimeType, fmt.pixelformat))
+			req_size += strlen(format->format.mimeType) + 1;
+		else
+			format->format.mimeType = NULL;
+		format_count++;
+
+		// Append the format to the list
+		if(head == NULL)
+			head = tail = format;
+		else
+			tail->next = format;
+		tail = format;
+	}
+	if(errno != EINVAL) {
+		ret = C_V4L2_ERROR;
+		set_last_error(hDevice, errno);
+		goto done;
+	}
+
+	// Return the required size if the given size is not large enough
+	if(count)
+		*count = format_count;
+	if(req_size > *size) {
+		*size = req_size;
+		ret = C_BUFFER_TOO_SMALL;
+		goto done;
+	}
+	if(format_count == 0)
+		goto done;
+	if(formats == NULL) {
+		ret = C_INVALID_ARG;
+		goto done;
+	}
+
+	// Loop through the formats and return a list of CPixelFormat structs
+	CPixelFormat *current = formats;
+	PixelFormat *elem = head;
+	unsigned int dynamics_offset = format_count * sizeof(CPixelFormat);
+	while(elem) {
+		// Copy the simple attributes
+		memcpy(current, &elem->format, sizeof(elem->format));
+
+		// Copy the strings
+		copy_string_to_buffer(&current->name, elem->format.name, formats, &dynamics_offset);
+		if(elem->format.mimeType)
+			copy_string_to_buffer(&current->mimeType, elem->format.mimeType, formats, &dynamics_offset);
+
+		current++;
+		elem = elem->next;
+	}
+	assert(dynamics_offset == req_size);
+
+done:
+	// Free the list of pixel formats and close the V4L2 device
+	//close(v4l2_dev);
+	elem = head;
+	while(elem) {
+		PixelFormat *next = elem->next;
+		if(elem->format.mimeType) free(elem->format.mimeType);
+		if(elem->format.name) free(elem->format.name);
+		free(elem);
+		elem = next;
+	}
+	return ret;
+}
+
+
+/**
+ * Enumerates all frame sizes supported for the given pixel format.
+ *
+ * If the buffer is not large enough, #C_BUFFER_TOO_SMALL is returned and
+ * the \a size parameter is modified to contain the required buffer size.
+ *
+ * A list of pixel formats can be obtained from c_enum_pixel_formats().
+ *
+ * @param 	hDevice		a handle obtained from c_open_device()
+ * @param	pixelformat	the pixel format for which the frame sizes should be
+ * 						enumerated
+ * @param	sizes		a pointer to a buffer that retrieves the list of frame sizes
+ * @param	size		a pointer to an integer that contains or receives the size
+ * 						of the @a sizes buffer
+ * @param	count		a pointer to an integer that receives the number of frame
+ * 						sizes supported for the given pixel format. Can be NULL.
+ * 						If this argument is not NULL, the frame size count is
+ * 						returned independent of whether or not the buffer is large
+ * 						enough.
+ * @return
+ * 		- #C_SUCCESS on success
+ * 		- #C_INIT_ERROR if the library has not been initialized
+ * 		- #C_INVALID_HANDLE if the given device handle is invalid
+ * 		- #C_INVALID_ARG if no size pointer was given; if a size pointer was given
+ * 		  but no @a sizes buffer was given; if no @a pixelformat was given
+ * 		- #C_INVALID_DEVICE if the device could not be opened
+ * 		- #C_BUFFER_TOO_SMALL if the supplied buffer is not large enough
+ * 		- #C_NO_MEMORY if no temporary memory could be allocated
+ * 		- #C_V4L2_ERROR if a V4L2 error occurred during frame size enumeration
+ */
+CResult c_enum_frame_sizes (CHandle hDevice, const CPixelFormat *pixelformat, CFrameSize *sizes, unsigned int *size, unsigned int *count)
+{
+	CResult ret = C_SUCCESS;
+	int v4l2_dev;
+
+	// Check the given handle and arguments
+	if(!initialized)
+		return C_INIT_ERROR;
+	if(!HANDLE_OPEN(hDevice))
+		return C_INVALID_HANDLE;
+	if(!HANDLE_VALID(hDevice))
+		return C_NOT_EXIST;
+	Device *device = GET_HANDLE(hDevice).device;
+	if(size == NULL || pixelformat == NULL)
+		return C_INVALID_ARG;
+
+	// Open the corresponding V4L2 device
+	v4l2_dev =  device->fd; //open_v4l2_device(device->v4l2_name);
+	if(!v4l2_dev)
+		return C_INVALID_DEVICE;
+
+	// Run V4L2 frame size enumeration
+	typedef struct _FrameSize {
+		CFrameSize			size;
+		struct _FrameSize	* next;
+	} FrameSize;
+	FrameSize *head = NULL, *tail = NULL;
+	unsigned int req_size = 0, size_count = 0;
+	struct v4l2_frmsizeenum fsize;
+	memset(&fsize, 0, sizeof(fsize));
+	fsize.index = 0;
+	fsize.pixel_format = pixelformat->fourcc[0] |
+			(unsigned long)pixelformat->fourcc[1] << 8 |
+			(unsigned long)pixelformat->fourcc[2] << 16 |
+			(unsigned long)pixelformat->fourcc[3] << 24;
+	fsize.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+	while(ioctl(v4l2_dev, VIDIOC_ENUM_FRAMESIZES, &fsize) == 0) {
+		FrameSize *framesize = (FrameSize *)malloc(sizeof(FrameSize));
+		if(!framesize) {
+			ret = C_NO_MEMORY;
+			goto done;
+		}
+		memset(framesize, 0, sizeof(FrameSize));
+		fsize.index++;
+
+		// Copy the frame size attributes
+		if(fsize.type == V4L2_FRMSIZE_TYPE_DISCRETE) {
+			framesize->size.type = CF_SIZE_DISCRETE;
+			framesize->size.width = fsize.discrete.width;
+			framesize->size.height = fsize.discrete.height;
+		}
+		else if(fsize.type == V4L2_FRMSIZE_TYPE_CONTINUOUS) {
+			framesize->size.type = CF_SIZE_CONTINUOUS;
+			framesize->size.min_width = fsize.stepwise.min_width;
+			framesize->size.max_width = fsize.stepwise.max_width;
+			framesize->size.step_width = 1;
+			framesize->size.min_height = fsize.stepwise.min_height;
+			framesize->size.max_height = fsize.stepwise.max_height;
+			framesize->size.step_height = 1;
+		}
+		else if(fsize.type == V4L2_FRMSIZE_TYPE_STEPWISE) {
+			framesize->size.type = CF_SIZE_STEPWISE;
+			framesize->size.min_width = fsize.stepwise.min_width;
+			framesize->size.max_width = fsize.stepwise.max_width;
+			framesize->size.step_width = fsize.stepwise.step_width;
+			framesize->size.min_height = fsize.stepwise.min_height;
+			framesize->size.max_height = fsize.stepwise.max_height;
+			framesize->size.step_height = fsize.stepwise.step_height;
+		}
+		req_size += sizeof(CFrameSize);
+		size_count++;
+
+		// Append the frame size to the list
+		if(head == NULL)
+			head = tail = framesize;
+		else
+			tail->next = framesize;
+		tail = framesize;
+	}
+	if(errno != EINVAL) {
+		ret = C_V4L2_ERROR;
+		set_last_error(hDevice, errno);
+		goto done;
+	}
+
+	// Return the required size if the given size is not large enough
+	if(count)
+		*count = size_count;
+	if(req_size > *size) {
+		*size = req_size;
+		ret = C_BUFFER_TOO_SMALL;
+		goto done;
+	}
+	if(size_count == 0)
+		goto done;
+	if(sizes == NULL)
+		return C_INVALID_ARG;
+
+	// Loop through the formats and return a list of CFrameSize structs
+	CFrameSize *current = sizes;
+	FrameSize *elem = head;
+	while(elem) {
+		memcpy(current, &elem->size, sizeof(elem->size));
+		current++;
+		elem = elem->next;
+	}
+
+done:
+	// Free the list of frame sizes and close the V4L2 device
+	//close(v4l2_dev);
+	elem = head;
+	while(elem) {
+		FrameSize *next = elem->next;
+		free(elem);
+		elem = next;
+	}
+	return ret;
+}
+
+
+/**
+ * Enumerates all frame intervals supported for the given pixel format and frame size.
+ *
+ * If the buffer is not large enough, #C_BUFFER_TOO_SMALL is returned and
+ * the \a size parameter is modified to contain the required buffer size.
+ *
+ * A list of pixel formats can be obtained from c_enum_pixel_formats(). In a
+ * similar manner the list of supported frame sizes for each pixel format can be
+ * obtained from c_enum_frame_sizes().
+ *
+ * @param 	hDevice		a handle obtained from c_open_device()
+ * @param	pixelformat	the pixel format for which the frame intervals should be
+ * 						enumerated
+ * @param	framesize	the frame size for which the frame intervals should be
+ * 						enumerated. Note that this frame size's type must be discrete.
+ * @param	intervals	a pointer to a buffer that retrieves the list of frame
+ * 						intervals
+ * @param	size		a pointer to an integer that contains or receives the size
+ * 						of the @a intervals buffer
+ * @param	count		a pointer to an integer that receives the number of frame
+ * 						intervals supported for the given pixel format and frame
+ * 						size. Can be NULL. If this argument is not NULL, the frame
+ * 						size count is returned independent of whether or not the
+ * 						buffer is large enough.
+ * @return
+ * 		- #C_SUCCESS on success
+ * 		- #C_INIT_ERROR if the library has not been initialized
+ * 		- #C_INVALID_HANDLE if the given device handle is invalid
+ * 		- #C_INVALID_ARG if no size pointer was given; if a size pointer was given
+ * 		  but no @a sizes buffer was given; if @a pixelformat or @a framesize were
+ * 		  not given; if a non-descrete frame size was given
+ * 		- #C_INVALID_DEVICE if the device could not be opened
+ * 		- #C_BUFFER_TOO_SMALL if the supplied buffer is not large enough
+ * 		- #C_NO_MEMORY if no temporary memory could be allocated
+ * 		- #C_V4L2_ERROR if a V4L2 error occurred during frame interval enumeration
+ */
+CResult c_enum_frame_intervals (CHandle hDevice, const CPixelFormat *pixelformat, const CFrameSize *framesize, CFrameInterval *intervals, unsigned int *size, unsigned int *count)
+{
+	CResult ret = C_SUCCESS;
+	int v4l2_dev;
+
+	// Check the given handle and arguments
+	if(!initialized)
+		return C_INIT_ERROR;
+	if(!HANDLE_OPEN(hDevice))
+		return C_INVALID_HANDLE;
+	if(!HANDLE_VALID(hDevice))
+		return C_NOT_EXIST;
+	Device *device = GET_HANDLE(hDevice).device;
+	if(size == NULL || pixelformat == NULL || framesize == NULL)
+		return C_INVALID_ARG;
+
+	// The frame size must be discrete because V4L2's VIDIOC_ENUM_FRAMEINTERVALS function
+	// only accepts a single width and height.
+	if(framesize->type != CF_SIZE_DISCRETE)
+		return C_INVALID_ARG;
+
+	// Open the corresponding V4L2 device
+	v4l2_dev = device->fd; //open_v4l2_device(device->v4l2_name);
+	if(!v4l2_dev)
+		return C_INVALID_DEVICE;
+
+	// Run V4L2 frame interval enumeration
+	typedef struct _FrameInterval {
+		CFrameInterval			interval;
+		struct _FrameInterval	* next;
+	} FrameInterval;
+	FrameInterval *head = NULL, *tail = NULL;
+	unsigned int req_size = 0, interval_count = 0;
+	struct v4l2_frmivalenum fival;
+	memset(&fival, 0, sizeof(fival));
+	fival.index = 0;
+	fival.pixel_format = pixelformat->fourcc[0] |
+			(unsigned long)pixelformat->fourcc[1] << 8 |
+			(unsigned long)pixelformat->fourcc[2] << 16 |
+			(unsigned long)pixelformat->fourcc[3] << 24;
+	fival.width = framesize->width;
+	fival.height = framesize->height;
+	fival.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+	while(ioctl(v4l2_dev, VIDIOC_ENUM_FRAMEINTERVALS, &fival) == 0) {
+		FrameInterval *frameinterval = (FrameInterval *)malloc(sizeof(FrameInterval));
+		if(!frameinterval) {
+			ret = C_NO_MEMORY;
+			goto done;
+		}
+		memset(frameinterval, 0, sizeof(FrameInterval));
+		fival.index++;
+
+		// Copy the frame interval attributes
+		if(fival.type == V4L2_FRMIVAL_TYPE_DISCRETE) {
+			frameinterval->interval.type = CF_INTERVAL_DISCRETE;
+			frameinterval->interval.n = fival.discrete.numerator;
+			frameinterval->interval.d = fival.discrete.denominator;
+		}
+		else if(fival.type == V4L2_FRMIVAL_TYPE_CONTINUOUS) {
+			frameinterval->interval.type = CF_INTERVAL_CONTINUOUS;
+			frameinterval->interval.min_n = fival.stepwise.min.numerator;
+			frameinterval->interval.min_d = fival.stepwise.min.denominator;
+			frameinterval->interval.max_n = fival.stepwise.max.numerator;
+			frameinterval->interval.max_d = fival.stepwise.max.denominator;
+			frameinterval->interval.step_n = 1;
+			frameinterval->interval.step_d = 1;
+		}
+		else if(fival.type == V4L2_FRMIVAL_TYPE_STEPWISE) {
+			frameinterval->interval.type = CF_INTERVAL_STEPWISE;
+			frameinterval->interval.min_n = fival.stepwise.min.numerator;
+			frameinterval->interval.min_d = fival.stepwise.min.denominator;
+			frameinterval->interval.max_n = fival.stepwise.max.numerator;
+			frameinterval->interval.max_d = fival.stepwise.max.denominator;
+			frameinterval->interval.step_n = fival.stepwise.step.numerator;
+			frameinterval->interval.step_d = fival.stepwise.step.denominator;
+		}
+		req_size += sizeof(CFrameInterval);
+		interval_count++;
+
+		// Append the frame interval to the list
+		if(head == NULL)
+			head = tail = frameinterval;
+		else
+			tail->next = frameinterval;
+		tail = frameinterval;
+	}
+	if(errno != EINVAL) {
+		ret = C_V4L2_ERROR;
+		set_last_error(hDevice, errno);
+		goto done;
+	}
+
+	// Return the required size if the given size is not large enough
+	if(count)
+		*count = interval_count;
+	if(req_size > *size) {
+		*size = req_size;
+		ret = C_BUFFER_TOO_SMALL;
+		goto done;
+	}
+	if(interval_count == 0)
+		goto done;
+	if(intervals == NULL)
+		return C_INVALID_ARG;
+
+	// Loop through the formats and return a list of CFrameInterval structs
+	CFrameInterval *current = intervals;
+	FrameInterval *elem = head;
+	while(elem) {
+		memcpy(current, &elem->interval, sizeof(elem->interval));
+		current++;
+		elem = elem->next;
+	}
+
+done:
+	// Free the list of frame sizes and close the V4L2 device
+	//close(v4l2_dev);
+	elem = head;
+	while(elem) {
+		FrameInterval *next = elem->next;
+		free(elem);
+		elem = next;
+	}
+	return ret;
+}
+
+
+
+/*
+ * Controls
+ */
+
+/**
+ * Enumerates all controls supported by the given device.
+ *
+ * If the buffer is not large enough, #C_BUFFER_TOO_SMALL is returned and
+ * the \a size parameter is modified to contain the required buffer size.
+ *
+ * @param hDevice	a device handle obtained from c_open_device()
+ * @param controls	a pointer to a buffer that retrieves the list of supported
+ * 					controls.
+ * @param size		a pointer to an integer that contains or receives the size of
+ * 					the \a controls buffer.
+ * @param count		a pointer to an integer that receives the number of controls
+ * 					supported. Can be NULL. If this argument is not NULL, the control
+ * 					count is returned independent of whether or not the buffer is
+ * 					large enough.
+ * @return
+ * 		- #C_SUCCESS on success
+ * 		- #C_INIT_ERROR if the library has not been initialized
+ * 		- #C_INVALID_HANDLE if the given device handle is invalid
+ * 		- #C_SYNC_ERROR if the synchronization structures could not be initialized
+ * 		- #C_INVALID_ARG if no size pointer was given or if a size pointer was given
+ * 		  but no @a controls buffer was given
+ * 		- #C_BUFFER_TOO_SMALL if the supplied buffer is not large enough
+ */
+CResult c_enum_controls (CHandle hDevice, CControl *controls, unsigned int *size, unsigned int *count)
+{
+	CResult ret = C_SUCCESS;
+	unsigned int names_length, choices_length;
+
+	// Check the given handle and arguments
+	if(!initialized)
+		return C_INIT_ERROR;
+	if(!HANDLE_OPEN(hDevice))
+		return C_INVALID_HANDLE;
+	if(!HANDLE_VALID(hDevice))
+		return C_NOT_EXIST;
+	Device *device = GET_HANDLE(hDevice).device;
+	if(size == NULL)
+		return C_INVALID_ARG;
+
+	if(lock_mutex(&device->controls.mutex))
+		return C_SYNC_ERROR;
+
+	// Determine the buffer size needed to describe all controls
+	if(count)
+		*count = device->controls.count;
+	get_control_dynamics_length(device, &names_length, &choices_length);
+	int req_size = device->controls.count * sizeof(CControl) + names_length + choices_length;
+	if(req_size > *size) {
+		*size = req_size;
+		ret = C_BUFFER_TOO_SMALL;
+		goto done;
+	}
+	if(device->controls.count == 0)
+		goto done;
+	if(controls == NULL)
+		return C_INVALID_ARG;
+
+	// Loop through all the device's controls and return a list of CControl structs
+	CControl *current = controls;
+	Control *elem = device->controls.first;
+	unsigned int names_offset = device->controls.count * sizeof(CControl);
+	unsigned int choices_offset = names_offset + names_length;
+	while(elem) {
+		// Copy the simple attributes
+		memcpy(current, &elem->control, sizeof(elem->control));
+
+		// Copy the name
+		unsigned int name_length = strlen(elem->control.name);
+		current->name = (char *)controls + names_offset;
+		memcpy(current->name, elem->control.name, name_length + 1);
+		assert(names_offset + name_length < req_size);
+		names_offset += name_length + 1;
+
+		// Copy the choices
+		if(elem->control.type == CC_TYPE_CHOICE) {
+			current->choices.count = elem->control.choices.count;
+			current->choices.list = (CControlChoice *)((char *)controls + choices_offset);
+			choices_offset += elem->control.choices.count * sizeof(CControlChoice);
+			current->choices.names = (char *)controls + choices_offset;
+
+			int index;
+			for(index = 0; index < elem->control.choices.count; index++) {
+				int name_length = strlen(elem->control.choices.list[index].name);
+				current->choices.list[index].index = elem->control.choices.list[index].index;
+				current->choices.list[index].name = (char *)controls + choices_offset;
+				memcpy(current->choices.list[index].name, elem->control.choices.list[index].name, name_length + 1);
+				assert(choices_offset + name_length < req_size);
+				choices_offset += name_length + 1;
+			}
+		}
+
+		current++;
+		elem = elem->next;
+	}
+	assert(choices_offset == req_size);
+
+done:
+	unlock_mutex(&device->controls.mutex);
+	return ret;
+}
+
+
+/**
+ * Sets the value of a device control.
+ *
+ * @param hDevice		a device handle obtained from c_open_device()
+ * @param control_id	the ID of the control whose value shall be set
+ * @param value			the value to which the control shall be set
+ * @return
+ * 		- #C_SUCCESS on success
+ * 		- #C_INIT_ERROR if the library has not been initialized
+ * 		- #C_INVALID_HANDLE if the given device handle is invalid
+ * 		- #C_INVALID_ARG if no value is given
+ * 		- #C_NOT_FOUND if the device does not support the given control
+ * 		- #C_CANNOT_WRITE if the given control is not writable
+ * 		- #C_INVALID_DEVICE if the device could not be opened
+ * 		- #C_V4L2_ERROR if a V4L2 error occurred during control access
+ */
+CResult c_set_control (CHandle hDevice, CControlId control_id, const CControlValue *value)
+{
+	CResult ret = C_SUCCESS;
+
+	// Check the given handle and arguments
+	if(!initialized)
+		return C_INIT_ERROR;
+	if(!HANDLE_OPEN(hDevice))
+		return C_INVALID_HANDLE;
+	if(!HANDLE_VALID(hDevice))
+		return C_NOT_EXIST;
+	Device *device = GET_HANDLE(hDevice).device;
+	if(value == NULL)
+		return C_INVALID_ARG;
+
+	// Look for the requested control within the given device
+	Control *control = find_control_by_id(device, control_id);
+	if(!control)
+		return C_NOT_FOUND;
+
+	// Check if the control is writable
+	if(!(control->control.flags & CC_CAN_WRITE))
+		return C_CANNOT_WRITE;
+
+	// Write the control in a way that depends on its source
+	if(control->v4l2_control) {		// V4L2
+		ret = write_v4l2_control(device, control, value, hDevice);
+	}
+	else {
+		assert(0);
+		return C_INVALID_ARG;
+	}
+
+	return ret;
+}
+
+
+/**
+ * Returns the value of a device control.
+ *
+ * @param hDevice		a device handle obtained from c_open_device()
+ * @param control_id	the ID of the control whose value shall be read
+ * @param value			a pointer to receive the value read
+ * @return
+ * 		- #C_SUCCESS on success
+ * 		- #C_INIT_ERROR if the library has not been initialized
+ * 		- #C_INVALID_HANDLE if the given device handle is invalid
+ * 		- #C_INVALID_ARG if no value is given
+ * 		- #C_NOT_FOUND if the device does not support the given control
+ * 		- #C_CANNOT_READ if the given control is not readable
+ * 		- #C_INVALID_DEVICE if the device could not be opened
+ * 		- #C_V4L2_ERROR if a V4L2 error occurred during control access
+ */
+CResult c_get_control (CHandle hDevice, CControlId control_id, CControlValue *value)
+{
+	CResult ret = C_SUCCESS;
+
+	// Check the given handle and arguments
+	if(!initialized)
+		return C_INIT_ERROR;
+	if(!HANDLE_OPEN(hDevice))
+		return C_INVALID_HANDLE;
+	if(!HANDLE_VALID(hDevice))
+		return C_NOT_EXIST;
+	Device *device = GET_HANDLE(hDevice).device;
+	if(value == NULL)
+		return C_INVALID_ARG;
+
+	// Look for the requested control within the given device
+	Control *control = find_control_by_id(device, control_id);
+	if(!control)
+		return C_NOT_FOUND;
+
+	// Check if the control is readable
+	if(!(control->control.flags & CC_CAN_READ))
+		return C_CANNOT_READ;
+
+	// Read the control in a way that depends on its source
+	if(control->v4l2_control) {			// V4L2
+		ret = read_v4l2_control(device, control, value, hDevice);
+	}
+	else {
+		assert(0);
+		return C_INVALID_ARG;
+	}
+
+	return ret;
+}
+
+
+/*
+ * Events
+ */
+
+/**
+ * Enumerates the events supported by the given device. @e [unimplemented]
+ *
+ * @return
+ * 		- #C_INIT_ERROR if the library has not been initialized
+ * 		- #C_NOT_IMPLEMENTED
+ */
+CResult c_enum_events (CHandle hDevice, CEvent *events, unsigned int *size, unsigned int *count)
+{
+	if(!initialized)
+		return C_INIT_ERROR;
+	return C_NOT_IMPLEMENTED;
+}
+
+
+/**
+ * Subscribes the caller to receive the given event. @e [unimplemented]
+ *
+ * @return
+ * 		- #C_INIT_ERROR if the library has not been initialized
+ * 		- #C_NOT_IMPLEMENTED
+ */
+CResult c_subscribe_event (CHandle hDevice, CEventId event_id, CEventHandler handler, void *context)
+{
+	if(!initialized)
+		return C_INIT_ERROR;
+	return C_NOT_IMPLEMENTED;
+}
+
+
+/**
+ * Unsubscribes the caller from the given event. @e [unimplemented]
+ *
+ * @return
+ * 		- #C_INIT_ERROR if the library has not been initialized
+ * 		- #C_NOT_IMPLEMENTED
+ */
+CResult c_unsubscribe_event (CHandle hDevice, CEventId event_id)
+{
+	if(!initialized)
+		return C_INIT_ERROR;
+	return C_NOT_IMPLEMENTED;
+}
+
+
+/**
+ * Returns the error message associated with a given error code.
+ *
+ * Note that the caller must free the buffer returned by this function.
+ *
+ * @param error		error code for which the message should be retrieved
+ * @return
+ * 		- a newly allocated string describing the given error code
+ * 		- NULL if not enough memory was available or if the error code is
+ * 		  unknown
+ */
+char *c_get_error_text (CResult error)
+{
+	return c_get_handle_error_text(0, error);
+}
+
+
+/**
+ * Returns the error message associated with a given error code and device handle.
+ *
+ * Note that the caller must free the buffer returned by this function. Compared to the
+ * #c_get_error_text() function, this function can take the handle's last system error
+ * into account.
+ *
+ * @param hDevice	an open device handle. If this parameter is 0, the function behaves
+ *					exactly like #c_get_error_text().
+ * @param error		error code for which the message should be retrieved
+ * @return
+ * 		- a newly allocated string describing the given error code
+ * 		- NULL if not enough memory was available or if the error code is
+ * 		  unknown
+ */
+char *c_get_handle_error_text (CHandle hDevice, CResult error)
+{
+	switch(error) {
+		case C_SUCCESS:				return strdup("Success");
+		case C_NOT_IMPLEMENTED:		return strdup("The function is not implemented");
+		case C_INIT_ERROR:			return strdup("Error during initialization or library not initialized");
+		case C_INVALID_ARG:			return strdup("Invalid argument");
+		case C_INVALID_HANDLE:		return strdup("Invalid handle");
+		case C_INVALID_DEVICE:		return strdup("Invalid device or device cannot be opened");
+		case C_NOT_FOUND:			return strdup("Object not found");
+		case C_BUFFER_TOO_SMALL:	return strdup("Buffer too small");
+		case C_SYNC_ERROR:			return strdup("Error during data synchronization");
+		case C_NO_MEMORY:			return strdup("Out of memory");
+		case C_NO_HANDLES:			return strdup("Out of handles");
+		case C_V4L2_ERROR:
+		{
+			char *text = NULL;
+			if(hDevice && HANDLE_OPEN(hDevice)) {
+				if(asprintf(&text, "A Video4Linux2 API call returned an unexpected error %d", GET_HANDLE(hDevice).last_system_error) == -1)
+					text = NULL;;
+			}
+			if(!text)
+				return strdup("A Video4Linux2 API call returned an unexpected error");
+			return text;
+		}
+		case C_SYSFS_ERROR:			return strdup("A sysfs file access returned an error");
+		case C_PARSE_ERROR:			return strdup("A control could not be parsed");
+		case C_CANNOT_WRITE:		return strdup("Writing not possible (e.g. read-only control)");
+		case C_CANNOT_READ:			return strdup("Reading not possible (e.g. write-only control)");
+		default:					return NULL;
+	}
+}
+
+
+
+/*
+ * Helper functions
+ */
+
+/**
+ * Prints a generic error message to stderr.
+ */
+void print_libwebcam_error (char *format, ...)
+{
+	char *newformat;
+	va_list ap;
+
+	if(asprintf(&newformat, "[libwebcam] %s\n", format) == -1)
+		newformat = format;
+
+	va_start(ap, format);
+	vfprintf(stderr, newformat, ap);
+	va_end(ap);
+
+	if(newformat != format)
+		free(newformat);
+	else
+		fprintf(stderr, "\n");
+}
+
+
+/**
+ * Prints a libwebcam error message to stderr.
+ *
+ * @param error		a #CResult error code whose error text is appended
+ * @param format	a @a printf compatible format
+ */
+static void print_libwebcam_c_error (CResult error, char *format, ...)
+{
+	char *unknown_text = "Unknown error";
+	char *text, *newformat;
+	va_list ap;
+
+	// Retrieve the libwebcam error text
+	text = c_get_error_text(error);
+	if(text == NULL)
+		text = unknown_text;
+
+	if(asprintf(&newformat, "[libwebcam] %s (error %d: %s)\n", format, error, text) == -1)
+		newformat = format;
+
+	if(text != unknown_text)
+		free(text);
+
+	va_start(ap, format);
+	vfprintf(stderr, newformat, ap);
+	va_end(ap);
+
+	if(newformat != format)
+		free(newformat);
+	else
+		fprintf(stderr, "\n");
+}
+
+
+
+/*
+ * Control management
+ */
+
+/**
+ * Queries the control choice values of the given V4L2 control and uses the results to
+ * fill in the choice structures of a libwebcam control.
+ *
+ * @param ctrl		Internal control for which the choice data is requested.
+ * @param v4l2_ctrl	Pointer to a structure obtained from VIDIOC_QUERYCTRL and containing
+ * 					the V4L2 control data.
+ * @param v4l2_dev	Open V4L2 device handle.
+ */
+static CResult create_control_choices (Control *ctrl, struct v4l2_queryctrl *v4l2_ctrl, int v4l2_dev)
+{
+	CResult ret = C_SUCCESS;
+
+	int choices_count = v4l2_ctrl->maximum - v4l2_ctrl->minimum + 1;
+	ctrl->control.choices.count = choices_count;
+
+	// Allocate memory for the choices.names and choices.list members
+	ctrl->control.choices.names = (char *)malloc(choices_count * V4L2_MENU_CTRL_MAX_NAME_SIZE);
+	if(ctrl->control.choices.names == NULL) {
+		ret = C_NO_MEMORY;
+		goto done;
+	}
+	ctrl->control.choices.list = (CControlChoice *)malloc(choices_count * sizeof(CControlChoice));
+	if(ctrl->control.choices.list == NULL) {
+		ret = C_NO_MEMORY;
+		goto done;
+	}
+
+	// Query the menu items of the given control and transform them
+	// into CControlChoice.
+	struct v4l2_querymenu v4l2_menu = { .id = v4l2_ctrl->id };
+	for(v4l2_menu.index = v4l2_ctrl->minimum; v4l2_menu.index <= v4l2_ctrl->maximum; v4l2_menu.index++) {
+		int choice_index = v4l2_menu.index - v4l2_ctrl->minimum;
+		if(ioctl(v4l2_dev, VIDIOC_QUERYMENU, &v4l2_menu)) {
+			if(errno == EINVAL) {
+#ifdef V4L2_CID_EXPOSURE_AUTO
+				// Some newer versions of the UVC driver implement an 'Exposure, Auto'
+				// menu control whose menu choices don't have contiguous IDs
+				// but { 1, 2, 4, 8 } instead.
+				if(v4l2_ctrl->id == V4L2_CID_EXPOSURE_AUTO && errno == EINVAL &&
+						v4l2_menu.index == 0) {
+					print_libwebcam_error(
+						"Unsupported V4L2_CID_EXPOSURE_AUTO control with a non-contiguous \n"
+						"  range of choice IDs found");
+				}
+				else
+#endif
+				{
+					print_libwebcam_error(
+						"Invalid menu control choice range encountered.\n"
+						"  Indicated range is [ %d .. %d ] but querying choice %d failed.",
+						v4l2_ctrl->minimum, v4l2_ctrl->maximum, v4l2_menu.index
+					);
+				}
+				ret = C_NOT_IMPLEMENTED;
+				goto done;
+			}
+			ret = C_V4L2_ERROR;
+			goto done;
+		}
+		ctrl->control.choices.list[choice_index].index = v4l2_menu.index;
+		ctrl->control.choices.list[choice_index].name = ctrl->control.choices.names + choice_index * V4L2_MENU_CTRL_MAX_NAME_SIZE;
+		if(strlen((char *)v4l2_menu.name))
+			memcpy(ctrl->control.choices.list[choice_index].name, v4l2_menu.name, V4L2_MENU_CTRL_MAX_NAME_SIZE);
+		else
+			snprintf(ctrl->control.choices.list[choice_index].name, V4L2_MENU_CTRL_MAX_NAME_SIZE, "%d", v4l2_menu.index);
+
+	}
+
+done:
+	if(ret != C_SUCCESS) {
+		if(ctrl->control.choices.names)
+			free(ctrl->control.choices.names);
+		if(ctrl->control.choices.list)
+			free(ctrl->control.choices.list);
+	}
+	return ret;
+}
+
+
+/**
+ * Create a libwebcam control from a V4L2 control.
+ *
+ * If necessary, further information is requested by this function, e.g. in the case
+ * of a choice control.
+ *
+ * @param device	Device to which the control should be appended.
+ * @param v4l2_ctrl	Pointer to a structure obtained from VIDIOC_QUERYCTRL and containing
+ * 					the V4L2 control data.
+ * @param v4l2_dev	Open V4L2 device handle.
+ * @param pret		Pointer to receive the error code in the case of an error.
+ * 					(Can be NULL.)
+ *
+ * @return
+ * 		- NULL if an error occurred. The associated error can be found in @a pret.
+ * 		- Pointer to the newly created control.
+ */
+static Control *create_v4l2_control (Device *device, struct v4l2_queryctrl *v4l2_ctrl, int v4l2_dev, CResult *pret)
+{
+	CResult ret = C_SUCCESS;
+	Control *ctrl = NULL;
+
+	// Map V4L2 control types to libwebcam control types
+	CControlType type;
+	switch(v4l2_ctrl->type) {
+		case V4L2_CTRL_TYPE_INTEGER:	type = CC_TYPE_DWORD;		break;
+		case V4L2_CTRL_TYPE_BOOLEAN:	type = CC_TYPE_BOOLEAN;		break;
+		case V4L2_CTRL_TYPE_MENU:		type = CC_TYPE_CHOICE;		break;
+#ifdef ENABLE_RAW_CONTROLS
+		case V4L2_CTRL_TYPE_STRING:		type = CC_TYPE_RAW;			break;
+#endif
+		case V4L2_CTRL_TYPE_BUTTON:		// TODO implement
+		case V4L2_CTRL_TYPE_INTEGER64:	// TODO implement
+			ret = C_NOT_IMPLEMENTED;
+			print_libwebcam_error("Warning: Unsupported V4L2 control type encountered: ctrl_id = 0x%08X, "
+					"name = '%s', type = %d",
+					v4l2_ctrl->id, v4l2_ctrl->name, v4l2_ctrl->type);
+			goto done;
+		default:
+			ret = C_PARSE_ERROR;
+			print_libwebcam_error("Invalid V4L2 control type encountered: ctrl_id = 0x%08X, "
+					"name = '%s', type = %d",
+					v4l2_ctrl->id, v4l2_ctrl->name, v4l2_ctrl->type);
+			goto done;
+	}
+
+	// Map the V4L2 control ID to a libwebcam ID
+	CControlId ctrl_id = get_control_id_from_v4l2(v4l2_ctrl->id, device);
+	//printf("Mapping V4L2 control ID 0x%08X => 0x%08X\n", v4l2_ctrl->id, ctrl_id);
+	if(ctrl_id == 0) {
+		ret = C_NOT_IMPLEMENTED;
+		goto done;
+	}
+
+	// Create the internal control info structure
+	ctrl = (Control *)malloc(sizeof(*ctrl));
+	if(ctrl) {
+		memset(ctrl, 0, sizeof(*ctrl));
+		ctrl->control.id		= ctrl_id;
+		ctrl->v4l2_control		= v4l2_ctrl->id;
+		if(strlen((char *)v4l2_ctrl->name))
+			ctrl->control.name		= strdup((char *)v4l2_ctrl->name);
+		else
+			ctrl->control.name		= strdup(UNKNOWN_CONTROL_NAME);
+		ctrl->control.type		= type;
+		ctrl->control.flags		= CC_CAN_READ;
+		if(!(v4l2_ctrl->flags & V4L2_CTRL_FLAG_READ_ONLY))
+			ctrl->control.flags	|= CC_CAN_WRITE;
+		if(v4l2_ctrl->id >= V4L2_CID_PRIVATE_BASE)
+			ctrl->control.flags |= CC_IS_CUSTOM;
+		ctrl->control.def.value	= v4l2_ctrl->default_value;
+
+		// Process V4L2 menu-style and raw controls
+		if(type == CC_TYPE_CHOICE) {
+			ret = create_control_choices(ctrl, v4l2_ctrl, v4l2_dev);
+			if(ret) goto done;
+		}
+		else if(type == CC_TYPE_RAW) {
+			if(v4l2_ctrl->minimum != v4l2_ctrl->maximum || v4l2_ctrl->step != 1) {
+				print_libwebcam_error("Unsupported V4L2 string control encountered: ctrl_id = 0x%08X, "
+					"name = '%s', min = %u, max = %u, step = %u",
+					v4l2_ctrl->id, v4l2_ctrl->name,
+					v4l2_ctrl->minimum, v4l2_ctrl->maximum, v4l2_ctrl->step);
+				ret = C_NOT_IMPLEMENTED;
+				goto done;
+			}
+			ctrl->control.value.raw.size =
+			ctrl->control.min.raw.size =
+			ctrl->control.max.raw.size =
+			ctrl->control.def.raw.size = v4l2_ctrl->maximum;
+		}
+		else {
+			ctrl->control.min.value		= v4l2_ctrl->minimum;
+			ctrl->control.max.value		= v4l2_ctrl->maximum;
+			ctrl->control.step.value	= v4l2_ctrl->step;
+		}
+
+		// Add the new control to the control list of the given device
+		ctrl->next = device->controls.first;
+		device->controls.first = ctrl;
+		device->controls.count++;
+	}
+	else {
+		ret = C_NO_MEMORY;
+	}
+
+done:
+	if(ret != C_SUCCESS && ctrl) {
+		if(ctrl->control.name) {
+			free(ctrl->control.name);
+			ctrl->control.name = NULL;
+		}
+		free(ctrl);
+		ctrl = NULL;
+	}
+	if(pret)
+		*pret = ret;
+	return ctrl;
+}
+
+
+/**
+ * Frees all resources associated with the given control, including choice data.
+ *
+ * Note that this functino does not remove the control from its device's control list.
+ */
+static void delete_control (Control *ctrl)
+{
+	if(ctrl->control.type == CC_TYPE_CHOICE) {
+		if(ctrl->control.choices.list)
+			free(ctrl->control.choices.list);
+		if(ctrl->control.choices.names)
+			free(ctrl->control.choices.names);
+	}
+	if(ctrl->control.name)
+		free(ctrl->control.name);
+	free(ctrl);
+}
+
+
+/**
+ * Looks up the control with the given ID for the given device.
+ *
+ * @return
+ * 		- NULL if no corresponding control was found for the given device.
+ * 		- Pointer to the control if it was found.
+ */
+static Control *find_control_by_id (Device *dev, CControlId id)
+{
+	Control *elem = dev->controls.first;
+	while(elem) {
+		if(elem->control.id == id)
+			break;
+		elem = elem->next;
+	}
+	return elem;
+}
+
+
+/**
+ * Clears the control list of the given device and frees all associated resources.
+ */
+static void clear_control_list (Device *dev)
+{
+	lock_mutex(&dev->controls.mutex);
+
+	Control *elem = dev->controls.first;
+	while(elem) {
+		Control *next = elem->next;
+		delete_control(elem);
+		elem = next;
+	}
+	dev->controls.first = NULL;
+	dev->controls.count = 0;
+
+	unlock_mutex(&dev->controls.mutex);
+}
+
+
+/**
+ * Scans the given device for supported controls and adds them to the internal list.
+ *
+ * Note that this function clears all existing controls prior to reenumerating them.
+ */
+static CResult refresh_control_list (Device *dev)
+{
+	CResult ret = C_SUCCESS;
+	int v4l2_dev;
+	struct v4l2_queryctrl v4l2_ctrl = { 0 };
+
+	// Clear control list first
+	clear_control_list(dev);
+
+	// Open the corresponding V4L2 device	
+	if (dev->fd) v4l2_dev = dev->fd;
+	else v4l2_dev = open_v4l2_device(dev->v4l2_name);
+	if(!v4l2_dev)
+		return C_INVALID_DEVICE;
+
+	if(lock_mutex(&dev->controls.mutex)) {
+		ret = C_SYNC_ERROR;
+		goto done;
+	}
+
+	// Test if the driver supports the V4L2_CTRL_FLAG_NEXT_CTRL flag
+#ifdef ENABLE_V4L2_ADVANCED_CONTROL_ENUMERATION
+	v4l2_ctrl.id = 0 | V4L2_CTRL_FLAG_NEXT_CTRL;
+	if(ioctl(v4l2_dev, VIDIOC_QUERYCTRL, &v4l2_ctrl) == 0) {
+		// The driver supports the V4L2_CTRL_FLAG_NEXT_CTRL flag, so go ahead with
+		// the advanced enumeration way.
+
+		int r;
+		v4l2_ctrl.id = 0;
+		int current_ctrl = v4l2_ctrl.id;
+		v4l2_ctrl.id |= V4L2_CTRL_FLAG_NEXT_CTRL;
+		// Loop as long as ioctl does not return EINVAL
+		while((r = ioctl(v4l2_dev, VIDIOC_QUERYCTRL, &v4l2_ctrl)), r ? errno != EINVAL : 1) {
+#ifdef CONTROL_IO_ERROR_RETRIES
+			if(r && (errno == EIO || errno == EPIPE || errno == ETIMEDOUT)) {
+				// An I/O error occurred, so retry the query a few times.
+				// This part is a little tricky. On the one hand, we want to retrieve the ID
+				// of the next control in case the query succeeds or we give up on retrying.
+				// On the other hand we want to retry the erroneous control instead of just
+				// skipping to the next one, wo we needed to backup the ID of the failing
+				// control first (above in current_ctrl).
+				// Keep in mind that with the NEXT_CTRL flag VIDIO_QUERYCTRL returns the
+				// first control with a *higher* ID than the specified one.
+				int tries = CONTROL_IO_ERROR_RETRIES;
+				v4l2_ctrl.id = current_ctrl | V4L2_CTRL_FLAG_NEXT_CTRL;
+				while(tries-- &&
+					  (r = ioctl(v4l2_dev, VIDIOC_QUERYCTRL, &v4l2_ctrl)) &&
+					  (errno == EIO || errno == EPIPE || errno == ETIMEDOUT)) {
+					v4l2_ctrl.id = current_ctrl | V4L2_CTRL_FLAG_NEXT_CTRL;
+				}
+			}
+#endif
+			// Prevent infinite loops for buggy NEXT_CTRL implementations
+			if(r && v4l2_ctrl.id <= current_ctrl) {
+				// If there was an error but the driver failed to provide us with the ID
+				// of the next control, we have to manually increase the control ID,
+				// otherwise we risk getting stuck querying the erroneous control.
+				current_ctrl++;
+				print_libwebcam_error(
+						"Warning: The driver behind device %s has a slightly buggy implementation\n"
+						"  of the V4L2_CTRL_FLAG_NEXT_CTRL flag. It does not return the next higher\n"
+						"  control ID if a control query fails. A workaround has been enabled.",
+						dev->v4l2_name);
+				goto next_control;
+			}
+			else if(!r && v4l2_ctrl.id == current_ctrl) {
+				// If there was no error but the driver did not increase the control ID
+				// we simply cancel the enumeration.
+				print_libwebcam_error(
+						"Error: The driver %s behind device %s has a buggy\n"
+						"  implementation of the V4L2_CTRL_FLAG_NEXT_CTRL flag. It does not raise an\n"
+						"  error or return the next control. Canceling control enumeration.",
+						dev->device.driver, dev->v4l2_name);
+				goto done;
+			}
+
+			current_ctrl = v4l2_ctrl.id;
+
+			// Skip failed and disabled controls
+			if(r || v4l2_ctrl.flags & V4L2_CTRL_FLAG_DISABLED)
+				goto next_control;
+
+			Control *ctrl = create_v4l2_control(dev, &v4l2_ctrl, v4l2_dev, &ret);
+			if(ctrl == NULL) {
+				if(ret == C_PARSE_ERROR || ret == C_NOT_IMPLEMENTED) {
+					print_libwebcam_error("Invalid or unsupported V4L2 control encountered: "
+							"ctrl_id = 0x%08X, name = '%s'", v4l2_ctrl.id, v4l2_ctrl.name);
+					ret = C_SUCCESS;
+				}
+				else {
+					goto done;
+				}
+			}
+
+next_control:
+			v4l2_ctrl.id |= V4L2_CTRL_FLAG_NEXT_CTRL;
+		}
+	}
+	else
+#endif
+	{
+		// The driver does not support the V4L2_CTRL_FLAG_NEXT_CTRL flag, so we need
+		// to fall back to the old way of enumerating controls, i.e. enumerating the
+		// standard V4L2 controls first, followed by the driver's private controls.
+		// It won't be possible to enumerate controls with non-contiguous IDs but in
+		// this case the driver probably doesn't implement any.
+
+		// Enumerate default V4L2 controls.
+		// We use a separate variable instead of v4l2_ctrl.id for the loop counter because
+		// some drivers (bttv) simply return a fake control with ID 0 when the device
+		// doesn't support a control in the [V4L2_CID_BASE, V4L2_CID_LASTP1) interval,
+		// thereby overwriting our loop variable and causing us to restart from 0.
+		int current_ctrl;
+		for(current_ctrl = V4L2_CID_BASE; current_ctrl < V4L2_CID_LASTP1; current_ctrl++) {
+			v4l2_ctrl.id = current_ctrl;
+#ifndef CONTROL_IO_ERROR_RETRIES
+			if(ioctl(v4l2_dev, VIDIOC_QUERYCTRL, &v4l2_ctrl) ||
+			   v4l2_ctrl.flags & V4L2_CTRL_FLAG_DISABLED)
+				continue;
+#else
+			int r = 0, tries = 1 + CONTROL_IO_ERROR_RETRIES;
+			while(tries-- &&
+				  (r = ioctl(v4l2_dev, VIDIOC_QUERYCTRL, &v4l2_ctrl)) &&
+				  (errno == EIO || errno == EPIPE || errno == ETIMEDOUT));
+			if(r || v4l2_ctrl.flags & V4L2_CTRL_FLAG_DISABLED)
+				continue;
+#endif
+
+			Control *ctrl = create_v4l2_control(dev, &v4l2_ctrl, v4l2_dev, &ret);
+			if(ctrl == NULL) {
+				if(ret == C_PARSE_ERROR || ret == C_NOT_IMPLEMENTED) {
+					print_libwebcam_error("Invalid or unsupported V4L2 control encountered: "
+							"ctrl_id = 0x%08X, name = '%s'", v4l2_ctrl.id, v4l2_ctrl.name);
+					ret = C_SUCCESS;
+					continue;
+				}
+				goto done;
+			}
+		}
+
+		// Enumerate custom controls
+		for(v4l2_ctrl.id = V4L2_CID_PRIVATE_BASE;; v4l2_ctrl.id++) {
+#ifndef CONTROL_IO_ERROR_RETRIES
+			if(ioctl(v4l2_dev, VIDIOC_QUERYCTRL, &v4l2_ctrl))
+				break;
+#else
+			int r = 0, tries = 1 + CONTROL_IO_ERROR_RETRIES;
+			while(tries-- &&
+				  (r = ioctl(v4l2_dev, VIDIOC_QUERYCTRL, &v4l2_ctrl)) &&
+				  (errno == EIO || errno == EPIPE || errno == ETIMEDOUT));
+			if(r)
+				break;
+#endif
+			if(v4l2_ctrl.flags & V4L2_CTRL_FLAG_DISABLED)
+				continue;
+
+			Control *ctrl = create_v4l2_control(dev, &v4l2_ctrl, v4l2_dev, &ret);
+			if(ctrl == NULL) {
+				if(ret == C_PARSE_ERROR || ret == C_NOT_IMPLEMENTED) {
+					print_libwebcam_error("Invalid or unsupported custom V4L2 control encountered: "
+							"ctrl_id = 0x%08X, name = '%s'", v4l2_ctrl.id, v4l2_ctrl.name);
+					ret = C_SUCCESS;
+					continue;
+				}
+				goto done;
+			}
+		}
+	}
+
+done:
+	unlock_mutex(&dev->controls.mutex);
+	if (!dev->fd) close(v4l2_dev);
+
+	return ret;
+}
+
+
+/**
+ * Retrieve device information for the given device.
+ */
+static CResult refresh_device_details (Device *dev)
+{
+	CResult ret = C_SUCCESS;
+	int v4l2_dev;
+	struct v4l2_capability v4l2_cap;
+
+	// Open the corresponding V4L2 device
+	if (dev->fd) v4l2_dev = dev->fd;
+	else v4l2_dev = open_v4l2_device(dev->v4l2_name);
+	if(!v4l2_dev)
+		return C_INVALID_DEVICE;
+
+	// Query the device
+	if(!ioctl(v4l2_dev, VIDIOC_QUERYCAP, &v4l2_cap)) {
+		if(v4l2_cap.card[0])
+			dev->device.name = strdup((char *)v4l2_cap.card);
+		else
+			dev->device.name = dev->v4l2_name;
+		dev->device.driver = strdup((char *)v4l2_cap.driver);
+		if(v4l2_cap.bus_info[0])
+			dev->device.location = strdup((char *)v4l2_cap.bus_info);
+		else
+			dev->device.location = dev->v4l2_name;
+	}
+	else {
+		ret = C_V4L2_ERROR;
+	}
+
+	if (!dev->fd) close(v4l2_dev);
+
+	return ret;
+}
+
+
+/**
+ * Returns the length required to store all the (null-terminated) names of the given
+ * device's controls in a buffer.
+ *
+ * Note: The control list should be locked before calling this function.
+ */
+static unsigned int get_control_dynamics_length(Device *device, unsigned int *names_length, unsigned int *choices_length)
+{
+	unsigned int names = 0, choices = 0;
+	Control *elem = device->controls.first;
+	while(elem) {
+		// Add length of the control name
+		if(elem->control.name)
+			names += strlen(elem->control.name) + 1;
+
+		// Add length of the control choice names
+		if(elem->control.type == CC_TYPE_CHOICE) {
+			int index;
+			for(index = 0; index < elem->control.choices.count; index++) {
+				choices += sizeof(CControlChoice);
+				choices += strlen(elem->control.choices.list[index].name) + 1;
+			}
+		}
+
+		elem = elem->next;
+	}
+	if(names_length)
+		*names_length = names;
+	if(choices_length)
+		*choices_length = choices;
+	return names + choices;
+}
+
+
+/**
+ * Converts a V4L2 control ID to a libwebcam control ID.
+ *
+ * @param v4l2_id	V4L2 ID that should be converted.
+ * @param dev		Pointer to the device to which the control belongs.
+ */
+static CControlId get_control_id_from_v4l2 (int v4l2_id, Device *dev)
+{
+	switch(v4l2_id) {
+		// Basic V4L2 controls
+		case V4L2_CID_BRIGHTNESS:			return CC_BRIGHTNESS;
+		case V4L2_CID_CONTRAST:				return CC_CONTRAST;
+		case V4L2_CID_SATURATION:			return CC_SATURATION;
+		case V4L2_CID_HUE:					return CC_HUE;
+		case V4L2_CID_AUDIO_VOLUME:			break;	// not supported by libwebcam
+		case V4L2_CID_AUDIO_BALANCE:		break;	// not supported by libwebcam
+		case V4L2_CID_AUDIO_BASS:			break;	// not supported by libwebcam
+		case V4L2_CID_AUDIO_TREBLE:			break;	// not supported by libwebcam
+		case V4L2_CID_AUDIO_MUTE:			break;	// not supported by libwebcam
+		case V4L2_CID_AUDIO_LOUDNESS:		break;	// not supported by libwebcam
+		case V4L2_CID_BLACK_LEVEL:			break;	// deprecated
+		case V4L2_CID_AUTO_WHITE_BALANCE:	return CC_AUTO_WHITE_BALANCE_TEMPERATURE;
+		case V4L2_CID_DO_WHITE_BALANCE:		break;	// not supported by libwebcam
+		case V4L2_CID_RED_BALANCE:			break;	// not supported by libwebcam
+		case V4L2_CID_BLUE_BALANCE:			break;	// not supported by libwebcam
+		case V4L2_CID_GAMMA:				return CC_GAMMA;
+		case V4L2_CID_EXPOSURE:				return CC_EXPOSURE_TIME_ABSOLUTE;
+		case V4L2_CID_AUTOGAIN:				break;	// not supported by libwebcam
+		case V4L2_CID_GAIN:					return CC_GAIN;
+		case V4L2_CID_HFLIP:				break;	// not supported by libwebcam
+		case V4L2_CID_VFLIP:				break;	// not supported by libwebcam
+		case V4L2_CID_HCENTER:				break;	// deprecated
+		case V4L2_CID_VCENTER:				break;	// deprecated
+#ifdef V4L2_CID_POWER_LINE_FREQUENCY
+		case V4L2_CID_POWER_LINE_FREQUENCY:		return CC_POWER_LINE_FREQUENCY;
+#endif
+#ifdef V4L2_CID_HUE_AUTO
+		case V4L2_CID_HUE_AUTO:					return CC_AUTO_HUE;
+#endif
+#ifdef V4L2_CID_WHITE_BALANCE_TEMPERATURE
+		case V4L2_CID_WHITE_BALANCE_TEMPERATURE:	return CC_WHITE_BALANCE_TEMPERATURE;
+#endif
+#ifdef V4L2_CID_SHARPNESS
+		case V4L2_CID_SHARPNESS:				return CC_SHARPNESS;
+#endif
+#ifdef V4L2_CID_BACKLIGHT_COMPENSATION
+		case V4L2_CID_BACKLIGHT_COMPENSATION:	return CC_BACKLIGHT_COMPENSATION;
+#endif
+#ifdef V4L2_CID_CHROMA_AGC
+		case V4L2_CID_CHROMA_AGC:				break;	// not supported by libwebcam
+#endif
+#ifdef V4L2_CID_COLOR_KILLER
+		case V4L2_CID_COLOR_KILLER:				break;	// not supported by libwebcam
+#endif
+#ifdef V4L2_CID_COLORFX
+		case V4L2_CID_COLORFX:					break;	// not supported by libwebcam
+#endif
+
+		// Camera/UVC driver controls
+#ifdef V4L2_CID_EXPOSURE_AUTO
+		case V4L2_CID_EXPOSURE_AUTO:			return CC_AUTO_EXPOSURE_MODE;
+#endif
+#ifdef V4L2_CID_EXPOSURE_ABSOLUTE
+		case V4L2_CID_EXPOSURE_ABSOLUTE:		return CC_EXPOSURE_TIME_ABSOLUTE;
+#endif
+#ifdef V4L2_CID_EXPOSURE_AUTO_PRIORITY
+		case V4L2_CID_EXPOSURE_AUTO_PRIORITY:	return CC_AUTO_EXPOSURE_PRIORITY;
+#endif
+#ifdef V4L2_CID_PAN_RELATIVE
+		case V4L2_CID_PAN_RELATIVE:				return CC_PAN_RELATIVE;
+#endif
+#ifdef V4L2_CID_TILT_RELATIVE
+		case V4L2_CID_TILT_RELATIVE:			return CC_TILT_RELATIVE;
+#endif
+#ifdef V4L2_CID_PAN_RESET
+		case V4L2_CID_PAN_RESET:				return CC_PAN_RESET;
+#endif
+#ifdef V4L2_CID_TILT_RESET
+		case V4L2_CID_TILT_RESET:				return CC_TILT_RESET;
+#endif
+#ifdef V4L2_CID_PAN_ABSOLUTE
+		case V4L2_CID_PAN_ABSOLUTE:				return CC_PAN_ABSOLUTE;
+#endif
+#ifdef V4L2_CID_TILT_ABSOLUTE
+		case V4L2_CID_TILT_ABSOLUTE:			return CC_TILT_ABSOLUTE;
+#endif
+#ifdef V4L2_CID_FOCUS_ABSOLUTE
+		case V4L2_CID_FOCUS_ABSOLUTE:			return CC_FOCUS_ABSOLUTE;
+#endif
+#ifdef V4L2_CID_FOCUS_RELATIVE
+		case V4L2_CID_FOCUS_RELATIVE:			return CC_FOCUS_RELATIVE;
+#endif
+#ifdef V4L2_CID_FOCUS_AUTO
+		case V4L2_CID_FOCUS_AUTO:				return CC_AUTO_FOCUS;
+#endif
+#ifdef V4L2_CID_ZOOM_ABSOLUTE
+		case V4L2_CID_ZOOM_ABSOLUTE:			return CC_ZOOM_ABSOLUTE;
+#endif
+#ifdef V4L2_CID_ZOOM_RELATIVE
+		case V4L2_CID_ZOOM_RELATIVE:			return CC_ZOOM_RELATIVE;
+#endif
+#ifdef V4L2_CID_ZOOM_CONTINUOUS
+		case V4L2_CID_ZOOM_CONTINUOUS:			break;	// not supported by libwebcam
+#endif
+#ifdef V4L2_CID_PRIVACY
+		case V4L2_CID_PRIVACY:					return CC_PRIVACY;
+#endif
+#ifdef V4L2_CID_LED1_MODE
+		case V4L2_CID_LED1_MODE:				return CC_LOGITECH_LED1_MODE;
+#endif
+#ifdef V4L2_CID_LED1_FREQUENCY
+		case V4L2_CID_LED1_FREQUENCY:			return CC_LOGITECH_LED1_FREQUENCY;
+#endif
+#ifdef V4L2_CID_DISABLE_PROCESSING
+		case V4L2_CID_DISABLE_PROCESSING:		return CC_LOGITECH_DISABLE_PROCESSING;
+#endif
+#ifdef V4L2_CID_RAW_BITS_PER_PIXEL
+		case V4L2_CID_RAW_BITS_PER_PIXEL:		return CC_LOGITECH_RAW_BITS_PER_PIXEL;
+#endif
+	};
+
+#ifdef USE_UVCVIDEO
+	// Controls contained only in older UVC drivers
+	//printf("*** 0x%08X 0x%08X\n", v4l2_id, UVC_CID_EXPOSURE_AUTO);
+	if(strcmp(dev->device.driver, "uvcvideo") == 0) {
+		switch(v4l2_id) {
+#ifdef UVC_CID_BACKLIGHT_COMPENSATION
+			case UVC_CID_BACKLIGHT_COMPENSATION:			return CC_BACKLIGHT_COMPENSATION;
+#endif
+#ifdef UVC_CID_POWER_LINE_FREQUENCY
+			case UVC_CID_POWER_LINE_FREQUENCY:				return CC_POWER_LINE_FREQUENCY;
+#endif
+#ifdef UVC_CID_SHARPNESS
+			case UVC_CID_SHARPNESS:							return CC_SHARPNESS;
+#endif
+#ifdef UVC_CID_HUE_AUTO
+			case UVC_CID_HUE_AUTO:							return CC_AUTO_HUE;
+#endif
+#ifdef UVC_CID_FOCUS_AUTO
+			case UVC_CID_FOCUS_AUTO:						return CC_AUTO_FOCUS;
+#endif
+#ifdef UVC_CID_FOCUS_ABSOLUTE
+			case UVC_CID_FOCUS_ABSOLUTE:					return CC_FOCUS_ABSOLUTE;
+#endif
+#ifdef UVC_CID_FOCUS_RELATIVE
+			case UVC_CID_FOCUS_RELATIVE:					return CC_FOCUS_RELATIVE;
+#endif
+#ifdef UVC_CID_PAN_RELATIVE
+			case UVC_CID_PAN_RELATIVE:						return CC_PAN_RELATIVE;
+#endif
+#ifdef UVC_CID_TILT_RELATIVE
+			case UVC_CID_TILT_RELATIVE:						return CC_TILT_RELATIVE;
+#endif
+#ifdef UVC_CID_PANTILT_RESET
+			case UVC_CID_PANTILT_RESET:						return CC_LOGITECH_PANTILT_RESET;
+#endif
+#ifdef UVC_CID_EXPOSURE_AUTO
+			case UVC_CID_EXPOSURE_AUTO:						return CC_AUTO_EXPOSURE_MODE;
+#endif
+#ifdef UVC_CID_EXPOSURE_ABSOLUTE
+			case UVC_CID_EXPOSURE_ABSOLUTE:					return CC_EXPOSURE_TIME_ABSOLUTE;
+#endif
+#ifdef UVC_CID_EXPOSURE_AUTO_PRIORITY
+			case UVC_CID_EXPOSURE_AUTO_PRIORITY:			return CC_AUTO_EXPOSURE_PRIORITY;
+#endif
+#ifdef UVC_CID_WHITE_BALANCE_TEMPERATURE_AUTO
+			case UVC_CID_WHITE_BALANCE_TEMPERATURE_AUTO:	return CC_AUTO_WHITE_BALANCE_TEMPERATURE;
+#endif
+#ifdef UVC_CID_WHITE_BALANCE_TEMPERATURE
+			case UVC_CID_WHITE_BALANCE_TEMPERATURE:			return CC_WHITE_BALANCE_TEMPERATURE;
+#endif
+#ifdef V4L2_CID_PANTILT_RELATIVE
+			case V4L2_CID_PANTILT_RELATIVE:					return CC_LOGITECH_PANTILT_RELATIVE;
+#endif
+		}
+	}
+#endif
+
+	// Unknown V4L2 controls
+	// Note that there is a margin of 256 control values for controls that are added
+	// after libwebcam compilation time.
+	if(V4L2_CTRL_ID2CLASS(v4l2_id) == V4L2_CTRL_CLASS_USER) {
+		// Unknown user control
+		print_libwebcam_error(
+			"Unknown V4L2 user control ID encountered: 0x%08X (V4L2_CID_USER_BASE + %d)",
+			v4l2_id, v4l2_id - V4L2_CID_USER_BASE
+		);
+		return CC_V4L2_BASE + (v4l2_id - V4L2_CID_USER_BASE);
+	}
+	else if(V4L2_CTRL_ID2CLASS(v4l2_id) == V4L2_CTRL_CLASS_MPEG) {
+		// Unknown MPEG control
+		print_libwebcam_error(
+			"Unknown V4L2 MPEG control ID encountered: 0x%08X (V4L2_CID_MPEG_BASE + %d)",
+			v4l2_id, v4l2_id - V4L2_CID_MPEG_BASE
+		);
+		return CC_V4L2_MPEG_BASE + (v4l2_id - V4L2_CID_MPEG_BASE);
+	}
+	else if(V4L2_CTRL_ID2CLASS(v4l2_id) == V4L2_CTRL_CLASS_CAMERA) {
+		// Unknown camera class (UVC) control
+		print_libwebcam_error(
+			"Unknown V4L2 camera class (UVC) control ID encountered: 0x%08X (V4L2_CID_CAMERA_CLASS_BASE + %d)",
+			v4l2_id, v4l2_id - V4L2_CID_CAMERA_CLASS_BASE
+		);
+		return CC_V4L2_CAMERA_CLASS_BASE + (v4l2_id - V4L2_CID_CAMERA_CLASS_BASE);
+	}
+	else if(v4l2_id >= V4L2_CID_PRIVATE_BASE) {
+		// Unknown private control
+		print_libwebcam_error(
+			"Unknown V4L2 private control ID encountered: 0x%08X (V4L2_CID_PRIVATE_BASE + %d)",
+			v4l2_id, v4l2_id - V4L2_CID_PRIVATE_BASE
+		);
+		return CC_V4L2_CUSTOM_BASE + (v4l2_id - V4L2_CID_PRIVATE_BASE);
+	}
+
+	print_libwebcam_error("Unknown V4L2 control ID encountered: 0x%08X", v4l2_id);
+	return 0;
+}
+
+
+/*
+ * Device management
+ */
+
+/**
+ * Allocate a new device with the given name and add it to the global device list.
+ */
+static Device *create_device (char *name)
+{
+	Device *dev = NULL;
+
+	dev = (Device *)malloc(sizeof(*dev));
+	if(dev) {
+		memset(dev, 0, sizeof(*dev));
+		strcpy(dev->v4l2_name, name);
+		dev->device.shortName = strdup(name);
+		dev->valid = 1;
+
+		// Add the new device to the global device list
+		dev->next = device_list.first;
+		device_list.first = dev;
+		device_list.count++;
+	}
+
+	return dev;
+}
+
+
+/**
+ * Free up the given device.
+ *
+ * Note that this function does not remove the device from the global device list.
+ */
+static void delete_device (Device *dev)
+{
+	// Free all the handles that point to this device
+	lock_mutex(&handle_list.mutex);
+	if(dev->handles > 0) {
+		CHandle hDevice;
+		for(hDevice = 1; hDevice < MAX_HANDLES; hDevice++) {
+			if(HANDLE_OPEN(hDevice) && GET_HANDLE(hDevice).device == dev) {
+				// Remove the device link from the handle but leave the handle around
+				dev->handles--;
+				GET_HANDLE(hDevice).device = NULL;
+			}
+		}
+	}
+	unlock_mutex(&handle_list.mutex);
+
+	// Free all controls of this device
+	clear_control_list(dev);
+
+	if(dev->device.shortName)
+		free(dev->device.shortName);
+	if(dev->device.name && dev->device.name != dev->v4l2_name)
+		free(dev->device.name);
+	if(dev->device.driver)
+		free(dev->device.driver);
+	if(dev->device.location && dev->device.location != dev->v4l2_name)
+		free(dev->device.location);
+	free(dev);
+}
+
+
+/**
+ * Mark all entries in the device list as invalid. This allows the cleanup_device_list()
+ * function to be used to clear the entire device list.
+ *
+ * Note: The device list should be locked before calling this function.
+ */
+static void invalidate_device_list (void)
+{
+	Device *elem = device_list.first;
+	while(elem) {
+		elem->valid = 0;
+		elem = elem->next;
+	}
+}
+
+
+/**
+ * Remove all entries marked as invalid from the device list.
+ *
+ * Note: The device list should be locked before calling this function.
+ */
+static void cleanup_device_list (void)
+{
+	Device *elem = device_list.first;
+	Device *prev = NULL, *next;
+	while(elem) {
+		next = elem->next;
+		if(!elem->valid) {
+			if(prev)
+				prev->next = next;
+			else
+				device_list.first = next;
+			delete_device(elem);
+			device_list.count--;
+		}
+		else {
+			prev = elem;
+		}
+		elem = next;
+	}
+}
+
+
+/**
+ * Searches the device list for the device with the given name.
+ */
+static Device *find_device_by_name (const char *name)
+{
+	Device *elem = device_list.first;
+	while(elem) {
+		if(strcmp(name, elem->v4l2_name) == 0)
+			return elem;
+		elem = elem->next;
+	}
+	return NULL;
+}
+
+
+/**
+ * Returns the length required to store all the (null-terminated) strings of the
+ * given device in a buffer.
+ */
+static int get_device_dynamics_length (CDevice *device)
+{
+	return strlen(device->shortName)	+ 1 +
+		   strlen(device->name)			+ 1 +
+		   strlen(device->driver)		+ 1 +
+		   strlen(device->location)		+ 1;
+}
+
+
+/**
+ * Returns the length required to store all the (null-terminated) strings of the
+ * current devices in a buffer.
+ *
+ * Note: The device list should be locked before calling this function.
+ */
+static int get_devices_dynamics_length (void)
+{
+	int size = 0;
+	Device *elem = device_list.first;
+	while(elem) {
+		size += get_device_dynamics_length(&elem->device);
+		elem = elem->next;
+	}
+	return size;
+}
+
+
+/**
+ * Synchronizes the device list with the information available in sysfs.
+ */
+static CResult refresh_device_list (void)
+{
+	CResult ret = C_SUCCESS;
+	DIR *v4l_dir = NULL;
+	struct dirent *dir_entry;
+
+	if(lock_mutex(&device_list.mutex))
+		return C_SYNC_ERROR;
+
+	// Invalidate all list entries
+	invalidate_device_list();
+
+	// Go through all devices in sysfs and validate the list entries that have
+	// correspondences in sysfs.
+	v4l_dir = opendir("/sys/class/video4linux");
+	if(v4l_dir) {
+		while((dir_entry = readdir(v4l_dir))) {
+			// Ignore non-video devices
+			if(strstr(dir_entry->d_name, "video") != dir_entry->d_name)
+				continue;
+
+			Device *dev = find_device_by_name(dir_entry->d_name);
+			if(dev) {
+				dev->valid = 1;
+			}
+			else {
+				dev = create_device(dir_entry->d_name);
+				if(dev == NULL) {
+					ret = C_NO_MEMORY;
+					goto done;
+				}
+
+				// Read detail information about the device
+				ret = refresh_device_details(dev);
+				if(ret) {
+					// Invalidate the device immediately, so it gets deleted by the call
+					// to cleanup_device_list() below.
+					dev->valid = 0;
+
+					// If there was a V4L2 error reset the error code, so that device enumeration
+					// continues. This is necessary because V4L1 devices will let
+					// refresh_device_details fail as they don't understand VIDIOC_QUERYCAP.
+					if(ret == C_V4L2_ERROR) {
+						print_libwebcam_error(
+								"Warning: The driver behind device %s does not seem to support V4L2.",
+								dev->v4l2_name);
+						ret = C_SUCCESS;
+						continue;
+					}
+					break;
+				}
+				get_device_usb_info(dev, &dev->device.usb);
+
+				// Create the control list for the given device
+				ret = refresh_control_list(dev);
+				if(ret) goto done;
+			}
+		}
+	}
+
+	// Clean out all invalid device list entries
+	cleanup_device_list();
+
+done:
+	if(v4l_dir)
+		closedir(v4l_dir);
+	unlock_mutex(&device_list.mutex);
+	if(ret)
+		print_libwebcam_c_error(ret, "Unable to refresh device list.");
+	return ret;
+}
+
+
+/**
+ * Open the V4L2 device node with the given name.
+ *
+ * @param device_name	A device name as accepted by c_open_device()
+ *
+ * @return
+ * 		- 0 if the device could not be opened
+ * 		- a device handle > 0 on success
+ */
+int open_v4l2_device(char *device_name)
+{
+	int v4l2_dev;
+	char *dev_node;
+
+	if(device_name == NULL)
+		return C_INVALID_ARG;
+
+	dev_node = (char *)malloc(5 + strlen(device_name) + 1);
+	if(!dev_node)
+		return 0;
+	sprintf(dev_node, "/dev/%s", device_name);
+	v4l2_dev = open(dev_node, O_RDWR);
+	free(dev_node);
+	return v4l2_dev;
+}
+
+
+/**
+ * Retrieves the value of a given V4L2 control.
+ */
+static CResult read_v4l2_control(Device *device, Control *control, CControlValue *value, CHandle hDevice)
+{
+	CResult ret = C_SUCCESS;
+
+	if(device == NULL || control == NULL || value == NULL)
+		return C_INVALID_ARG;
+
+	int v4l2_dev = device->fd; //open_v4l2_device(device->v4l2_name);
+	if(!v4l2_dev)
+		return C_INVALID_DEVICE;
+
+#ifdef ENABLE_RAW_CONTROLS
+	if(control->control.type == CC_TYPE_RAW) {
+		unsigned int ctrl_size = control->control.max.raw.size;
+
+		if(value->raw.data == NULL)
+			return C_INVALID_ARG;
+		if(value->raw.size < ctrl_size)
+			return C_INVALID_ARG;
+
+		struct v4l2_ext_control v4l2_ext_ctrl = {
+			.id		= control->v4l2_control,
+			.size	= ctrl_size,
+		};
+		v4l2_ext_ctrl.string = value->raw.data;
+		struct v4l2_ext_controls v4l2_ext_ctrls = {
+			.ctrl_class	= V4L2_CTRL_CLASS_USER,
+			.count		= 1,
+			.controls	= &v4l2_ext_ctrl
+		};
+		if(ioctl(v4l2_dev, VIDIOC_G_EXT_CTRLS, &v4l2_ext_ctrls)) {
+			ret = C_V4L2_ERROR;
+			set_last_error(hDevice, errno);
+			goto done;
+		}
+
+		// Set the raw data size to the size of the control
+		value->raw.size = ctrl_size;
+	}
+	else
+#endif
+	{
+		struct v4l2_control v4l2_ctrl = { .id = control->v4l2_control };
+		if(ioctl(v4l2_dev, VIDIOC_G_CTRL, &v4l2_ctrl)) {
+			ret = C_V4L2_ERROR;
+			set_last_error(hDevice, errno);
+			goto done;
+		}
+		value->value	= v4l2_ctrl.value;
+	}
+
+	value->type		= control->control.type;
+
+done:
+	//close(v4l2_dev);
+	return ret;
+}
+
+
+/**
+ * Changes the value of a given V4L2 control.
+ */
+static CResult write_v4l2_control(Device *device, Control *control, const CControlValue *value, CHandle hDevice)
+{
+	CResult ret = C_SUCCESS;
+
+	if(device == NULL || control == NULL || value == NULL)
+		return C_INVALID_ARG;
+
+	int v4l2_dev = device->fd; //open_v4l2_device(device->v4l2_name);
+	if(!v4l2_dev)
+		return C_INVALID_DEVICE;
+
+#ifdef ENABLE_RAW_CONTROLS
+	if(control->control.type == CC_TYPE_RAW) {
+		unsigned int ctrl_size = control->control.max.raw.size;
+
+		if(value->raw.data == NULL)
+			return C_INVALID_ARG;
+		if(value->raw.size < ctrl_size)
+			return C_INVALID_ARG;
+
+		struct v4l2_ext_control v4l2_ext_ctrl = {
+			.id		= control->v4l2_control,
+			.size	= ctrl_size,
+		};
+		v4l2_ext_ctrl.string = value->raw.data;
+		struct v4l2_ext_controls v4l2_ext_ctrls = {
+			.ctrl_class	= V4L2_CTRL_CLASS_USER,
+			.count		= 1,
+			.controls	= &v4l2_ext_ctrl
+		};
+		if(ioctl(v4l2_dev, VIDIOC_S_EXT_CTRLS, &v4l2_ext_ctrls)) {
+			ret = C_V4L2_ERROR;
+			set_last_error(hDevice, errno);
+			goto done;
+		}
+	}
+	else
+#endif
+	{
+		struct v4l2_control v4l2_ctrl = {
+			.id		= control->v4l2_control,
+			.value	= value->value
+		};
+		if(ioctl(v4l2_dev, VIDIOC_S_CTRL, &v4l2_ctrl)) {
+			ret = C_V4L2_ERROR;
+			set_last_error(hDevice, errno);
+		}
+	}
+
+#ifdef ENABLE_RAW_CONTROLS
+done:
+#endif
+	//close(v4l2_dev);
+	return ret;
+}
+
+
+/**
+ * Reads the USB information for the given device into the given #CUSBInfo structure.
+ */
+static CResult get_device_usb_info (Device *device, CUSBInfo *usbinfo)
+{
+	if(device == NULL || usbinfo == NULL)
+		return C_INVALID_ARG;
+
+	// File names in the /sys/class/video4linux/video?/device directory and
+	// corresponding pointers in the CUSBInfo structure.
+	char *files[] = {
+		"idVendor",
+		"idProduct",
+		"bcdDevice"
+	};
+	unsigned short *fields[] = {
+		&usbinfo->vendor,
+		&usbinfo->product,
+		&usbinfo->release
+	};
+
+	// Read USB information
+	int i;
+	for(i = 0; i < 3; i++) {
+		char *filename = NULL;
+		if(asprintf(&filename, "/sys/class/video4linux/%s/device/%s",
+					device->v4l2_name, files[i]) < 0)
+			return C_NO_MEMORY;
+
+		FILE *input = fopen(filename, "r");
+		if(input) {
+			if(fscanf(input, "%hx", fields[i]) != 1)
+				*fields[i] = 0;
+			fclose(input);
+		}
+
+		free(filename);
+	}
+
+	return C_SUCCESS;
+}
+
+
+/*
+ * Utility functions
+ */
+
+/**
+ * Converts a FourCC code into a MIME type string.
+ */
+static CResult get_mimetype_from_fourcc(char **mimetype, unsigned int fourcc)
+{
+	if(mimetype == NULL)
+		return C_INVALID_ARG;
+
+	char *result;
+	switch(fourcc) {
+		case MAKE_FOURCC('Y','U','Y','2'):
+		case MAKE_FOURCC('Y','U','Y','V'):
+			result = "video/x-raw-yuv";
+			break;
+		case MAKE_FOURCC('M','J','P','G'):
+			result = "image/jpeg";
+			break;
+		default:
+			return C_NOT_FOUND;
+	};
+
+	*mimetype = strdup(result);
+	return C_SUCCESS;
+}
+
+
+/*
+ * Handle management
+ */
+
+/**
+ * Creates a new device handle for the given device.
+ *
+ * @return
+ * 		- 0 if there are no free handles left.
+ * 		- A libwebcam handle > 0 on success.
+ */
+static CHandle create_handle(Device *device)
+{
+	CHandle handle = handle_list.first_free;
+	int first_free, next_free;
+	if(device == NULL)
+		return 0;
+	if(handle == 0) {
+		print_libwebcam_error("No free device handles left. Unable to create handle "
+				"for device '%s'.", device->v4l2_name);
+		return 0;
+	}
+
+	if(lock_mutex(&handle_list.mutex))
+		return C_SYNC_ERROR;
+
+	GET_HANDLE(handle).device = device;
+	GET_HANDLE(handle).open = 1;
+	device->handles++;
+
+	// Look for the next free handle index
+	first_free = handle_list.first_free;
+	next_free = first_free;
+	do {
+		next_free = (next_free + 1) % MAX_HANDLES;
+		if(next_free == 0) next_free = 1;
+
+		if(!HANDLE_OPEN(next_free)) {
+			handle_list.first_free = next_free;
+			break;
+		}
+	}
+	while(next_free != first_free);
+	if(next_free == first_free)
+		handle_list.first_free = 0;		// No free handles left
+
+	unlock_mutex(&handle_list.mutex);
+	return handle;
+}
+
+
+/**
+ * Closes the given handle.
+ */
+static void close_handle(CHandle hDevice)
+{
+	if(!HANDLE_OPEN(hDevice))
+		return;
+
+	// If the handle is open, close it. If it is also valid, remove the device reference.
+	if(HANDLE_VALID(hDevice)) {
+		lock_mutex(&handle_list.mutex);
+		GET_HANDLE(hDevice).device->handles--;
+		// Closes device when reference count reaches 0
+		if (GET_HANDLE(hDevice).device->handles== 0) {
+			close (GET_HANDLE(hDevice).device->fd);
+			GET_HANDLE(hDevice).device->fd= 0;
+		}
+		GET_HANDLE(hDevice).device = NULL;
+		GET_HANDLE(hDevice).open = 0;
+		unlock_mutex(&handle_list.mutex);
+	}
+	else {
+		GET_HANDLE(hDevice).open = 0;
+	}
+	GET_HANDLE(hDevice).last_system_error = 0;
+}
+
+
+/**
+ * Sets the last system error for the given handle.
+ */
+static void set_last_error(CHandle hDevice, int error)
+{
+	if(HANDLE_OPEN(hDevice))
+		GET_HANDLE(hDevice).last_system_error = error;
+}
+
+
+
+/*
+ * Initialization and cleanup
+ */
+
+/**
+ * Initializes libwebcam.
+ * This method must be called prior to using most of the other methods.
+ * To release resources allocated during initialization, users should make a call
+ * to c_cleanup() when the library is no longer used.
+ */
+CResult c_init(void)
+{
+	CResult ret = C_SUCCESS;
+
+	// Don't reinitialize
+	if(initialized)
+		return C_SUCCESS;
+
+	// Initialize the handle list
+	memset(&handle_list, 0, sizeof(handle_list));
+	handle_list.first_free = 1;
+	if(pthread_mutex_init(&handle_list.mutex, NULL))
+		return C_INIT_ERROR;
+
+	// Initialize the device list
+	device_list.first = NULL;
+	if(pthread_mutex_init(&device_list.mutex, NULL))
+		return C_INIT_ERROR;
+	device_list.count = 0;
+	ret = refresh_device_list();
+
+	if(ret == C_SUCCESS)
+		initialized = 1;
+	return ret;
+}
+
+
+/**
+ * Clean up resources.
+ * This method should be called when the library is no longer used.
+ */
+void c_cleanup(void)
+{
+	if(!initialized)
+		return;
+	initialized = 0;
+
+	// Clear the device list
+	lock_mutex(&device_list.mutex);
+	invalidate_device_list();
+	cleanup_device_list();
+	unlock_mutex(&device_list.mutex);
+
+	pthread_mutex_destroy(&device_list.mutex);
+	pthread_mutex_destroy(&handle_list.mutex);
+}
+
+
+/**
+ * Make sure the library resources are cleaned up when the library is unloaded.
+ */
+static void __attribute__ ((constructor)) c_unload(void)
+{
+	c_cleanup();
+}
diff --git a/src/libwebcam/libwebcam.h b/src/libwebcam/libwebcam.h
new file mode 100644
index 0000000..3e12640
--- /dev/null
+++ b/src/libwebcam/libwebcam.h
@@ -0,0 +1,312 @@
+/**
+ * \file
+ * Webcam library declarations.
+ *
+ * \ingroup libwebcam
+ */
+
+/*
+ * Copyright (c) 2006-2008 Logitech.
+ *
+ * This file is part of libwebcam.
+ * 
+ * libwebcam is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ * 
+ * libwebcam is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with libwebcam.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef C_LIBWEBCAM_H
+#define C_LIBWEBCAM_H
+
+
+#include <assert.h>
+
+
+/*
+ * Features
+ */
+
+/// Whether private controls of the Linux UVC driver should be used or not
+#define	USE_UVCVIDEO
+#ifdef USE_UVCVIDEO
+
+	/// Whether to compile in support functions for the Linux UVC driver's dynamic
+	/// controls.
+	#define	ENABLE_UVCVIDEO_DYNCTRL
+	#ifdef	ENABLE_UVCVIDEO_DYNCTRL
+
+		/// Whether to include the automatically generated Logitech dynamic controls
+		/// header file.
+		#define USE_LOGITECH_DYNCTRL
+
+		/// Whether to include support for raw controls.
+		/// Note that this requires V4L2_CTRL_TYPE_STRING to be available (i.e. V4L2 >= 2.6.32).
+		/// This is disabled by default but CMake enables it if it finds V4L2_CTRL_TYPE_STRING.
+		//#define ENABLE_RAW_CONTROLS
+
+	#endif
+
+#endif
+
+
+/*
+ * Constants
+ */
+
+/// Whether to use the V4L2_CTRL_FLAG_NEXT_CTRL flag when enumerating V4L2 controls
+#define	ENABLE_V4L2_ADVANCED_CONTROL_ENUMERATION
+
+/// Ignore EEXIST errors for the UVCIOC_CTRL_ADD and UVCIOC_CTRL_MAP ioctls for
+/// all but the first device. This is required if the driver uses global controls
+/// instead of per-device controls.
+#define DYNCTRL_IGNORE_EEXIST_AFTER_PASS1
+
+/// The maximum number (plus 1) of handles libwebcam supports
+#define	MAX_HANDLES						32
+
+/// Debug option to disable locking
+#define	DISABLE_LOCKING					1
+/// Debug option to add verbosity to locking and unlocking
+#define	DEBUG_LOCKING					1
+
+/// The name used for controls whose name could not be retrieved.
+#define	UNKNOWN_CONTROL_NAME			"Unknown control"
+/// Number of retries for failed V4L2 ioctl requests.
+/// This is a workaround for faulty devices.
+#define	CONTROL_IO_ERROR_RETRIES		2
+
+/// Size of a GUID in bytes
+#define GUID_SIZE		16
+
+
+
+/*
+ * Macros
+ */
+
+/// Returns the given handle structure
+#define GET_HANDLE(handle)		(handle_list.handles[(handle)])
+/// Returns true if the given handle is open (valid or invalid)
+#define HANDLE_OPEN(handle)		((handle) < MAX_HANDLES && GET_HANDLE(handle).open)
+/// Returns true if the given handle is open and valid
+#define HANDLE_VALID(handle)	(HANDLE_OPEN(handle) && GET_HANDLE(handle).device)
+
+/// Returns the maximum number of characters that a menu-type control choice
+/// can have in V4L2.
+#define V4L2_MENU_CTRL_MAX_NAME_SIZE	sizeof(((struct v4l2_querymenu *)NULL)->name)
+
+/// Converts the given characters into a FourCC code
+#define MAKE_FOURCC(c1,c2,c3,c4) \
+	(unsigned int)((long)c1 | (long)c2 << 8 | (long)c3 << 16 | (long)c4 << 24)
+
+/// Format string to print a GUID byte array with printf
+#define GUID_FORMAT		"%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x"
+/// Argument macro to print a GUID byte array with printf
+#define GUID_ARGS(guid) \
+        (guid)[3],  (guid)[2],  (guid)[1],  (guid)[0], \
+        (guid)[5],  (guid)[4], \
+        (guid)[7],  (guid)[6], \
+        (guid)[8],  (guid)[9], \
+        (guid)[10], (guid)[11], (guid)[12], \
+        (guid)[13], (guid)[14], (guid)[15]
+
+
+
+/*
+ * Structures
+ */
+
+/**
+ * An internal control description associated with a device.
+ */
+typedef struct _Control {
+	/// Control description
+	CControl		control;
+	/// V4L2 ioctl mapping (non-0 for V4L2 controls)
+	int				v4l2_control;
+	/// Pointer to the next control in the list
+	struct _Control	* next;
+
+} Control;
+
+/**
+ * Base structure that contains a list of controls and associated data.
+ */
+typedef struct _ControlList {
+	/// The first control in the list
+	Control			* first;
+	/// The mutex used to serialize access to the control list
+	pthread_mutex_t mutex;
+	/// The number of controls contained in the list
+	int				count;
+
+} ControlList;
+
+/**
+ * Internal device information.
+ */
+typedef struct _Device {
+	/// Device information
+	CDevice			device;
+	/// Short V4L2 device name (e.g. 'video0')
+	char			v4l2_name[NAME_MAX];
+	/// Number of handles associated with this device
+	int				handles;
+	/// List of controls supported by this device
+	ControlList		controls;
+	/// Boolean whether the device is still valid, i.e. exists in the system.
+	/// Devices marked as invalid will be cleared out by cleanup_device_list().
+	int				valid;
+	/// File descriptor returned by open
+	int				fd;
+	/// Next device in the global device list
+	struct _Device	* next;
+
+} Device;
+
+/**
+ * Base structure that contains a list of devices and associated data.
+ */
+typedef struct _DeviceList {
+	/// The first device in the list
+	Device			* first;
+	/// The mutex used to serialize access to the device list
+	pthread_mutex_t mutex;
+	/// The number of devices contained in the list
+	int				count;
+
+} DeviceList;
+
+/**
+ * Information associated with a device handle.
+ *
+ * Note that a handle can have three different states:
+ * - Closed/free: The device handle is not being used by an application.
+ * - Valid: The device handle is open by an application and points to a valid device.
+ * - Invalid: The device handle is open by an application but does not point to a
+ *     (valid) device anymore. This happens when a device is removed from the system
+ *     but there are still open handles around.
+ * An "open" handle can be both valid or invalid.
+ */
+typedef struct _Handle {
+	/// Pointer to the device structure associated with this handle
+	Device			* device;
+	/// True if the handle is open (valid or invalid)
+	int				open;
+	/// The number of the last system error (e.g. a V4L2 return value)
+	int				last_system_error;
+	
+} Handle;
+
+/**
+ * Base structure that contains an array of device handles and associated data.
+ */
+typedef struct _HandleList {
+	/// The array of handles
+	Handle			handles[MAX_HANDLES];
+	/// The mutex used to serialize access to the handle list
+	pthread_mutex_t	mutex;
+	/// The index of the first free handle.
+	/// Zero if there are now free handles at this time.
+	int				first_free;
+	
+} HandleList;
+
+
+
+/*
+ * Globals
+ */
+
+extern int initialized;
+extern HandleList handle_list;
+
+extern void print_error (char *format, ...);
+extern int open_v4l2_device(char *device_name);
+
+
+
+/*
+ * Helper functions
+ */
+
+/**
+ * Acquire a mutex.
+ * 
+ * This function is identical to pthread_mutex_lock except that it has different
+ * return values and supports some debug flags.
+ *
+ * @return
+ * 		C_SUCCESS if the mutex was successfully acquired
+ * 		C_SYNC_ERROR if an error occured while trying to acquire the mutex
+ */
+static inline CResult lock_mutex (pthread_mutex_t *mutex)
+{
+#ifndef DISABLE_LOCKING
+#ifdef DEBUG_LOCKING
+	fprintf(stderr, "Acquiring mutex 0x%08x ...\n", (unsigned int)mutex);
+#endif
+	int ret = pthread_mutex_lock(mutex);
+#ifdef DEBUG_LOCKING
+	fprintf(stderr, "Acquisition of mutex 0x%08x %s.\n", (unsigned int)mutex,
+			ret ? "failed" : "successful");
+#endif
+	assert(ret == 0);
+	return ret ? C_SYNC_ERROR : C_SUCCESS;
+#else
+	return C_SUCCESS;
+#endif
+}
+
+
+/**
+ * Release a mutex.
+ * 
+ * This function is identical to pthread_mutex_unlock except that it has different
+ * return values and supports some debug flags.
+ *
+ * @return
+ * 		C_SUCCESS if the mutex was successfully released
+ * 		C_SYNC_ERROR if an error occured while trying to release the mutex
+ */
+static inline void unlock_mutex (pthread_mutex_t *mutex)
+{
+#ifndef DISABLE_LOCKING
+#ifdef DEBUG_LOCKING
+	fprintf(stderr, "Releasing mutex 0x%08x ...\n", (unsigned int)mutex);
+#endif
+	int ret = pthread_mutex_unlock(mutex);
+#ifdef DEBUG_LOCKING
+	fprintf(stderr, "Release of mutex 0x%08x %s.\n", (unsigned int)mutex,
+			ret ? "failed" : "successful");
+#endif
+	assert(ret == 0);
+#endif
+}
+
+
+/**
+ * Copies a variable-length string to the part of an enumeration buffer that is
+ * reserved for dynamic data.
+ *
+ * This function is used by the enumeration functions.
+ */
+static inline void copy_string_to_buffer (char **target, char *source, void *buffer, unsigned int *offset)
+{
+	unsigned int length = strlen(source);
+	*target = (char *)buffer + *offset;
+	memcpy(*target, source, length + 1);
+	*offset += length + 1;
+}
+
+
+#endif /* C_LIBWEBCAM_H */
diff --git a/src/libwebcam/uvcvideo.h b/src/libwebcam/uvcvideo.h
new file mode 100644
index 0000000..c6c9014
--- /dev/null
+++ b/src/libwebcam/uvcvideo.h
@@ -0,0 +1,664 @@
+#ifndef _USB_VIDEO_H_
+#define _USB_VIDEO_H_
+
+#include <linux/kernel.h>
+#include <linux/videodev2.h>
+
+/*
+ * Dynamic controls
+ */
+
+/* Data types for UVC control data */
+#define UVC_CTRL_DATA_TYPE_RAW		0
+#define UVC_CTRL_DATA_TYPE_SIGNED	1
+#define UVC_CTRL_DATA_TYPE_UNSIGNED	2
+#define UVC_CTRL_DATA_TYPE_BOOLEAN	3
+#define UVC_CTRL_DATA_TYPE_ENUM		4
+#define UVC_CTRL_DATA_TYPE_BITMASK	5
+
+/* Control flags */
+#define UVC_CONTROL_SET_CUR	(1 << 0)
+#define UVC_CONTROL_GET_CUR	(1 << 1)
+#define UVC_CONTROL_GET_MIN	(1 << 2)
+#define UVC_CONTROL_GET_MAX	(1 << 3)
+#define UVC_CONTROL_GET_RES	(1 << 4)
+#define UVC_CONTROL_GET_DEF	(1 << 5)
+/* Control should be saved at suspend and restored at resume. */
+#define UVC_CONTROL_RESTORE	(1 << 6)
+/* Control can be updated by the camera. */
+#define UVC_CONTROL_AUTO_UPDATE	(1 << 7)
+
+#define UVC_CONTROL_GET_RANGE	(UVC_CONTROL_GET_CUR | UVC_CONTROL_GET_MIN | \
+				 UVC_CONTROL_GET_MAX | UVC_CONTROL_GET_RES | \
+				 UVC_CONTROL_GET_DEF)
+
+struct uvc_xu_control_info {
+	__u8 entity[16];
+	__u8 index;
+	__u8 selector;
+	__u16 size;
+	__u32 flags;
+};
+
+struct uvc_xu_control_mapping {
+	__u32 id;
+	__u8 name[32];
+	__u8 entity[16];
+	__u8 selector;
+
+	__u8 size;
+	__u8 offset;
+	enum v4l2_ctrl_type v4l2_type;
+	__u32 data_type;
+};
+
+struct uvc_xu_control {
+	__u8 unit;
+	__u8 selector;
+	__u16 size;
+	__u8 __user *data;
+};
+
+#define UVCIOC_CTRL_ADD		_IOW('U', 1, struct uvc_xu_control_info)
+#define UVCIOC_CTRL_MAP		_IOWR('U', 2, struct uvc_xu_control_mapping)
+#define UVCIOC_CTRL_GET		_IOWR('U', 3, struct uvc_xu_control)
+#define UVCIOC_CTRL_SET		_IOW('U', 4, struct uvc_xu_control)
+
+#ifdef __KERNEL__
+
+#include <linux/poll.h>
+#include <linux/usb/video.h>
+#include "compat.h"
+
+/* --------------------------------------------------------------------------
+ * UVC constants
+ */
+
+#define UVC_TERM_INPUT			0x0000
+#define UVC_TERM_OUTPUT			0x8000
+#define UVC_TERM_DIRECTION(term)	((term)->type & 0x8000)
+
+#define UVC_ENTITY_TYPE(entity)		((entity)->type & 0x7fff)
+#define UVC_ENTITY_IS_UNIT(entity)	(((entity)->type & 0xff00) == 0)
+#define UVC_ENTITY_IS_TERM(entity)	(((entity)->type & 0xff00) != 0)
+#define UVC_ENTITY_IS_ITERM(entity) \
+	(UVC_ENTITY_IS_TERM(entity) && \
+	((entity)->type & 0x8000) == UVC_TERM_INPUT)
+#define UVC_ENTITY_IS_OTERM(entity) \
+	(UVC_ENTITY_IS_TERM(entity) && \
+	((entity)->type & 0x8000) == UVC_TERM_OUTPUT)
+
+
+/* ------------------------------------------------------------------------
+ * GUIDs
+ */
+#define UVC_GUID_UVC_CAMERA \
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
+	 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01}
+#define UVC_GUID_UVC_OUTPUT \
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
+	 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02}
+#define UVC_GUID_UVC_MEDIA_TRANSPORT_INPUT \
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
+	 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03}
+#define UVC_GUID_UVC_PROCESSING \
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
+	 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01}
+#define UVC_GUID_UVC_SELECTOR \
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
+	 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02}
+
+#define UVC_GUID_FORMAT_MJPEG \
+	{ 'M',  'J',  'P',  'G', 0x00, 0x00, 0x10, 0x00, \
+	 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}
+#define UVC_GUID_FORMAT_YUY2 \
+	{ 'Y',  'U',  'Y',  '2', 0x00, 0x00, 0x10, 0x00, \
+	 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}
+#define UVC_GUID_FORMAT_YUY2_ISIGHT \
+	{ 'Y',  'U',  'Y',  '2', 0x00, 0x00, 0x10, 0x00, \
+	 0x80, 0x00, 0x00, 0x00, 0x00, 0x38, 0x9b, 0x71}
+#define UVC_GUID_FORMAT_NV12 \
+	{ 'N',  'V',  '1',  '2', 0x00, 0x00, 0x10, 0x00, \
+	 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}
+#define UVC_GUID_FORMAT_YV12 \
+	{ 'Y',  'V',  '1',  '2', 0x00, 0x00, 0x10, 0x00, \
+	 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}
+#define UVC_GUID_FORMAT_I420 \
+	{ 'I',  '4',  '2',  '0', 0x00, 0x00, 0x10, 0x00, \
+	 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}
+#define UVC_GUID_FORMAT_UYVY \
+	{ 'U',  'Y',  'V',  'Y', 0x00, 0x00, 0x10, 0x00, \
+	 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}
+#define UVC_GUID_FORMAT_Y800 \
+	{ 'Y',  '8',  '0',  '0', 0x00, 0x00, 0x10, 0x00, \
+	 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}
+#define UVC_GUID_FORMAT_Y16 \
+	{ 'Y',  '1',  '6',  ' ', 0x00, 0x00, 0x10, 0x00, \
+	 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}
+#define UVC_GUID_FORMAT_BY8 \
+	{ 'B',  'Y',  '8',  ' ', 0x00, 0x00, 0x10, 0x00, \
+	 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}
+
+/* ------------------------------------------------------------------------
+ * Driver specific constants.
+ */
+
+#define DRIVER_VERSION_NUMBER	KERNEL_VERSION(0, 1, 0)
+
+/* Number of isochronous URBs. */
+#define UVC_URBS		5
+/* Maximum number of packets per URB. */
+#define UVC_MAX_PACKETS		32
+/* Maximum number of video buffers. */
+#define UVC_MAX_VIDEO_BUFFERS	32
+/* Maximum status buffer size in bytes of interrupt URB. */
+#define UVC_MAX_STATUS_SIZE	16
+
+#define UVC_CTRL_CONTROL_TIMEOUT	300
+#define UVC_CTRL_STREAMING_TIMEOUT	5000
+
+/* Devices quirks */
+#define UVC_QUIRK_STATUS_INTERVAL	0x00000001
+#define UVC_QUIRK_PROBE_MINMAX		0x00000002
+#define UVC_QUIRK_PROBE_EXTRAFIELDS	0x00000004
+#define UVC_QUIRK_BUILTIN_ISIGHT	0x00000008
+#define UVC_QUIRK_STREAM_NO_FID		0x00000010
+#define UVC_QUIRK_IGNORE_SELECTOR_UNIT	0x00000020
+#define UVC_QUIRK_FIX_BANDWIDTH		0x00000080
+#define UVC_QUIRK_PROBE_DEF		0x00000100
+
+/* Format flags */
+#define UVC_FMT_FLAG_COMPRESSED		0x00000001
+#define UVC_FMT_FLAG_STREAM		0x00000002
+
+/* ------------------------------------------------------------------------
+ * Structures.
+ */
+
+struct uvc_device;
+
+/* TODO: Put the most frequently accessed fields at the beginning of
+ * structures to maximize cache efficiency.
+ */
+struct uvc_streaming_control {
+	__u16 bmHint;
+	__u8  bFormatIndex;
+	__u8  bFrameIndex;
+	__u32 dwFrameInterval;
+	__u16 wKeyFrameRate;
+	__u16 wPFrameRate;
+	__u16 wCompQuality;
+	__u16 wCompWindowSize;
+	__u16 wDelay;
+	__u32 dwMaxVideoFrameSize;
+	__u32 dwMaxPayloadTransferSize;
+	__u32 dwClockFrequency;
+	__u8  bmFramingInfo;
+	__u8  bPreferedVersion;
+	__u8  bMinVersion;
+	__u8  bMaxVersion;
+};
+
+struct uvc_menu_info {
+	__u32 value;
+	__u8 name[32];
+};
+
+struct uvc_control_info {
+	struct list_head list;
+	struct list_head mappings;
+
+	__u8 entity[16];
+	__u8 index;
+	__u8 selector;
+
+	__u16 size;
+	__u32 flags;
+};
+
+struct uvc_control_mapping {
+	struct list_head list;
+
+	struct uvc_control_info *ctrl;
+
+	__u32 id;
+	__u8 name[32];
+	__u8 entity[16];
+	__u8 selector;
+
+	__u8 size;
+	__u8 offset;
+	enum v4l2_ctrl_type v4l2_type;
+	__u32 data_type;
+
+	struct uvc_menu_info *menu_info;
+	__u32 menu_count;
+
+	__s32 (*get) (struct uvc_control_mapping *mapping, __u8 query,
+		      const __u8 *data);
+	void (*set) (struct uvc_control_mapping *mapping, __s32 value,
+		     __u8 *data);
+};
+
+struct uvc_control {
+	struct uvc_entity *entity;
+	struct uvc_control_info *info;
+
+	__u8 index;	/* Used to match the uvc_control entry with a
+			   uvc_control_info. */
+	__u8 dirty : 1,
+	     loaded : 1,
+	     modified : 1,
+	     cached : 1;
+
+	__u8 *data;
+};
+
+struct uvc_format_desc {
+	char *name;
+	__u8 guid[16];
+	__u32 fcc;
+};
+
+/* The term 'entity' refers to both UVC units and UVC terminals.
+ *
+ * The type field is either the terminal type (wTerminalType in the terminal
+ * descriptor), or the unit type (bDescriptorSubtype in the unit descriptor).
+ * As the bDescriptorSubtype field is one byte long, the type value will
+ * always have a null MSB for units. All terminal types defined by the UVC
+ * specification have a non-null MSB, so it is safe to use the MSB to
+ * differentiate between units and terminals as long as the descriptor parsing
+ * code makes sure terminal types have a non-null MSB.
+ *
+ * For terminals, the type's most significant bit stores the terminal
+ * direction (either UVC_TERM_INPUT or UVC_TERM_OUTPUT). The type field should
+ * always be accessed with the UVC_ENTITY_* macros and never directly.
+ */
+
+struct uvc_entity {
+	struct list_head list;		/* Entity as part of a UVC device. */
+	struct list_head chain;		/* Entity as part of a video device
+					 * chain. */
+	__u8 id;
+	__u16 type;
+	char name[64];
+
+	union {
+		struct {
+			__u16 wObjectiveFocalLengthMin;
+			__u16 wObjectiveFocalLengthMax;
+			__u16 wOcularFocalLength;
+			__u8  bControlSize;
+			__u8  *bmControls;
+		} camera;
+
+		struct {
+			__u8  bControlSize;
+			__u8  *bmControls;
+			__u8  bTransportModeSize;
+			__u8  *bmTransportModes;
+		} media;
+
+		struct {
+		} output;
+
+		struct {
+			__u16 wMaxMultiplier;
+			__u8  bControlSize;
+			__u8  *bmControls;
+			__u8  bmVideoStandards;
+		} processing;
+
+		struct {
+		} selector;
+
+		struct {
+			__u8  guidExtensionCode[16];
+			__u8  bNumControls;
+			__u8  bControlSize;
+			__u8  *bmControls;
+			__u8  *bmControlsType;
+		} extension;
+	};
+
+	__u8 bNrInPins;
+	__u8 *baSourceID;
+
+	unsigned int ncontrols;
+	struct uvc_control *controls;
+};
+
+struct uvc_frame {
+	__u8  bFrameIndex;
+	__u8  bmCapabilities;
+	__u16 wWidth;
+	__u16 wHeight;
+	__u32 dwMinBitRate;
+	__u32 dwMaxBitRate;
+	__u32 dwMaxVideoFrameBufferSize;
+	__u8  bFrameIntervalType;
+	__u32 dwDefaultFrameInterval;
+	__u32 *dwFrameInterval;
+};
+
+struct uvc_format {
+	__u8 type;
+	__u8 index;
+	__u8 bpp;
+	__u8 colorspace;
+	__u32 fcc;
+	__u32 flags;
+
+	char name[32];
+
+	unsigned int nframes;
+	struct uvc_frame *frame;
+};
+
+struct uvc_streaming_header {
+	__u8 bNumFormats;
+	__u8 bEndpointAddress;
+	__u8 bTerminalLink;
+	__u8 bControlSize;
+	__u8 *bmaControls;
+	/* The following fields are used by input headers only. */
+	__u8 bmInfo;
+	__u8 bStillCaptureMethod;
+	__u8 bTriggerSupport;
+	__u8 bTriggerUsage;
+};
+
+enum uvc_buffer_state {
+	UVC_BUF_STATE_IDLE	= 0,
+	UVC_BUF_STATE_QUEUED	= 1,
+	UVC_BUF_STATE_ACTIVE	= 2,
+	UVC_BUF_STATE_READY	= 3,
+	UVC_BUF_STATE_DONE	= 4,
+	UVC_BUF_STATE_ERROR	= 5,
+};
+
+struct uvc_buffer {
+	unsigned long vma_use_count;
+	struct list_head stream;
+
+	/* Touched by interrupt handler. */
+	struct v4l2_buffer buf;
+	struct list_head queue;
+	wait_queue_head_t wait;
+	enum uvc_buffer_state state;
+};
+
+#define UVC_QUEUE_STREAMING		(1 << 0)
+#define UVC_QUEUE_DISCONNECTED		(1 << 1)
+#define UVC_QUEUE_DROP_INCOMPLETE	(1 << 2)
+
+struct uvc_video_queue {
+	enum v4l2_buf_type type;
+
+	void *mem;
+	unsigned int flags;
+	__u32 sequence;
+
+	unsigned int count;
+	unsigned int buf_size;
+	unsigned int buf_used;
+	struct uvc_buffer buffer[UVC_MAX_VIDEO_BUFFERS];
+	struct mutex mutex;	/* protects buffers and mainqueue */
+	spinlock_t irqlock;	/* protects irqqueue */
+
+	struct list_head mainqueue;
+	struct list_head irqqueue;
+};
+
+struct uvc_video_chain {
+	struct uvc_device *dev;
+	struct list_head list;
+
+	struct list_head entities;		/* All entities */
+	struct uvc_entity *processing;		/* Processing unit */
+	struct uvc_entity *selector;		/* Selector unit */
+
+	struct mutex ctrl_mutex;
+};
+
+struct uvc_streaming {
+	struct list_head list;
+	struct uvc_device *dev;
+	struct video_device *vdev;
+	struct uvc_video_chain *chain;
+	atomic_t active;
+
+	struct usb_interface *intf;
+	int intfnum;
+	__u16 maxpsize;
+
+	struct uvc_streaming_header header;
+	enum v4l2_buf_type type;
+
+	unsigned int nformats;
+	struct uvc_format *format;
+
+	struct uvc_streaming_control ctrl;
+	struct uvc_format *cur_format;
+	struct uvc_frame *cur_frame;
+
+	struct mutex mutex;
+
+	unsigned int frozen : 1;
+	struct uvc_video_queue queue;
+	void (*decode) (struct urb *urb, struct uvc_streaming *video,
+			struct uvc_buffer *buf);
+
+	/* Context data used by the bulk completion handler. */
+	struct {
+		__u8 header[256];
+		unsigned int header_size;
+		int skip_payload;
+		__u32 payload_size;
+		__u32 max_payload_size;
+	} bulk;
+
+	struct urb *urb[UVC_URBS];
+	char *urb_buffer[UVC_URBS];
+	dma_addr_t urb_dma[UVC_URBS];
+	unsigned int urb_size;
+
+	__u8 last_fid;
+};
+
+enum uvc_device_state {
+	UVC_DEV_DISCONNECTED = 1,
+};
+
+struct uvc_device {
+	struct usb_device *udev;
+	struct usb_interface *intf;
+	unsigned long warnings;
+	__u32 quirks;
+	int intfnum;
+	char name[32];
+
+	enum uvc_device_state state;
+	struct list_head list;
+	atomic_t users;
+
+	/* Video control interface */
+	__u16 uvc_version;
+	__u32 clock_frequency;
+
+	struct list_head entities;
+	struct list_head chains;
+
+	/* Video Streaming interfaces */
+	struct list_head streams;
+	atomic_t nstreams;
+
+	/* Status Interrupt Endpoint */
+	struct usb_host_endpoint *int_ep;
+	struct urb *int_urb;
+	__u8 *status;
+	struct input_dev *input;
+	char input_phys[64];
+};
+
+enum uvc_handle_state {
+	UVC_HANDLE_PASSIVE	= 0,
+	UVC_HANDLE_ACTIVE	= 1,
+};
+
+struct uvc_fh {
+	struct uvc_video_chain *chain;
+	struct uvc_streaming *stream;
+	enum uvc_handle_state state;
+};
+
+struct uvc_driver {
+	struct usb_driver driver;
+
+	struct list_head devices;	/* struct uvc_device list */
+	struct list_head controls;	/* struct uvc_control_info list */
+	struct mutex ctrl_mutex;	/* protects controls and devices
+					   lists */
+};
+
+/* ------------------------------------------------------------------------
+ * Debugging, printing and logging
+ */
+
+#define UVC_TRACE_PROBE		(1 << 0)
+#define UVC_TRACE_DESCR		(1 << 1)
+#define UVC_TRACE_CONTROL	(1 << 2)
+#define UVC_TRACE_FORMAT	(1 << 3)
+#define UVC_TRACE_CAPTURE	(1 << 4)
+#define UVC_TRACE_CALLS		(1 << 5)
+#define UVC_TRACE_IOCTL		(1 << 6)
+#define UVC_TRACE_FRAME		(1 << 7)
+#define UVC_TRACE_SUSPEND	(1 << 8)
+#define UVC_TRACE_STATUS	(1 << 9)
+#define UVC_TRACE_VIDEO		(1 << 10)
+
+#define UVC_WARN_MINMAX		0
+#define UVC_WARN_PROBE_DEF	1
+
+extern unsigned int uvc_clock_param;
+extern unsigned int uvc_no_drop_param;
+extern unsigned int uvc_trace_param;
+extern unsigned int uvc_timeout_param;
+
+#define uvc_trace(flag, msg...) \
+	do { \
+		if (uvc_trace_param & flag) \
+			printk(KERN_DEBUG "uvcvideo: " msg); \
+	} while (0)
+
+#define uvc_warn_once(dev, warn, msg...) \
+	do { \
+		if (!test_and_set_bit(warn, &dev->warnings)) \
+			printk(KERN_INFO "uvcvideo: " msg); \
+	} while (0)
+
+#define uvc_printk(level, msg...) \
+	printk(level "uvcvideo: " msg)
+
+/* --------------------------------------------------------------------------
+ * Internal functions.
+ */
+
+/* Core driver */
+extern struct uvc_driver uvc_driver;
+
+/* Video buffers queue management. */
+extern void uvc_queue_init(struct uvc_video_queue *queue,
+		enum v4l2_buf_type type);
+extern int uvc_alloc_buffers(struct uvc_video_queue *queue,
+		unsigned int nbuffers, unsigned int buflength);
+extern int uvc_free_buffers(struct uvc_video_queue *queue);
+extern int uvc_query_buffer(struct uvc_video_queue *queue,
+		struct v4l2_buffer *v4l2_buf);
+extern int uvc_queue_buffer(struct uvc_video_queue *queue,
+		struct v4l2_buffer *v4l2_buf);
+extern int uvc_dequeue_buffer(struct uvc_video_queue *queue,
+		struct v4l2_buffer *v4l2_buf, int nonblocking);
+extern int uvc_queue_enable(struct uvc_video_queue *queue, int enable);
+extern void uvc_queue_cancel(struct uvc_video_queue *queue, int disconnect);
+extern struct uvc_buffer *uvc_queue_next_buffer(struct uvc_video_queue *queue,
+		struct uvc_buffer *buf);
+extern unsigned int uvc_queue_poll(struct uvc_video_queue *queue,
+		struct file *file, poll_table *wait);
+extern int uvc_queue_allocated(struct uvc_video_queue *queue);
+static inline int uvc_queue_streaming(struct uvc_video_queue *queue)
+{
+	return queue->flags & UVC_QUEUE_STREAMING;
+}
+
+/* V4L2 interface */
+extern const struct v4l2_file_operations uvc_fops;
+
+/* Video */
+extern int uvc_video_init(struct uvc_streaming *stream);
+extern int uvc_video_suspend(struct uvc_streaming *stream);
+extern int uvc_video_resume(struct uvc_streaming *stream);
+extern int uvc_video_enable(struct uvc_streaming *stream, int enable);
+extern int uvc_probe_video(struct uvc_streaming *stream,
+		struct uvc_streaming_control *probe);
+extern int uvc_commit_video(struct uvc_streaming *stream,
+		struct uvc_streaming_control *ctrl);
+extern int uvc_query_ctrl(struct uvc_device *dev, __u8 query, __u8 unit,
+		__u8 intfnum, __u8 cs, void *data, __u16 size);
+
+/* Status */
+extern int uvc_status_init(struct uvc_device *dev);
+extern void uvc_status_cleanup(struct uvc_device *dev);
+extern int uvc_status_start(struct uvc_device *dev);
+extern void uvc_status_stop(struct uvc_device *dev);
+extern int uvc_status_suspend(struct uvc_device *dev);
+extern int uvc_status_resume(struct uvc_device *dev);
+
+/* Controls */
+extern struct uvc_control *uvc_find_control(struct uvc_video_chain *chain,
+		__u32 v4l2_id, struct uvc_control_mapping **mapping);
+extern int uvc_query_v4l2_ctrl(struct uvc_video_chain *chain,
+		struct v4l2_queryctrl *v4l2_ctrl);
+
+extern int uvc_ctrl_add_info(struct uvc_control_info *info);
+extern int uvc_ctrl_add_mapping(struct uvc_control_mapping *mapping);
+extern int uvc_ctrl_init_device(struct uvc_device *dev);
+extern void uvc_ctrl_cleanup_device(struct uvc_device *dev);
+extern int uvc_ctrl_resume_device(struct uvc_device *dev);
+extern void uvc_ctrl_init(void);
+
+extern int uvc_ctrl_begin(struct uvc_video_chain *chain);
+extern int __uvc_ctrl_commit(struct uvc_video_chain *chain, int rollback);
+static inline int uvc_ctrl_commit(struct uvc_video_chain *chain)
+{
+	return __uvc_ctrl_commit(chain, 0);
+}
+static inline int uvc_ctrl_rollback(struct uvc_video_chain *chain)
+{
+	return __uvc_ctrl_commit(chain, 1);
+}
+
+extern int uvc_ctrl_get(struct uvc_video_chain *chain,
+		struct v4l2_ext_control *xctrl);
+extern int uvc_ctrl_set(struct uvc_video_chain *chain,
+		struct v4l2_ext_control *xctrl);
+
+extern int uvc_xu_ctrl_query(struct uvc_video_chain *chain,
+		struct uvc_xu_control *ctrl, int set);
+
+/* Utility functions */
+extern void uvc_simplify_fraction(uint32_t *numerator, uint32_t *denominator,
+		unsigned int n_terms, unsigned int threshold);
+extern uint32_t uvc_fraction_to_interval(uint32_t numerator,
+		uint32_t denominator);
+extern struct usb_host_endpoint *uvc_find_endpoint(
+		struct usb_host_interface *alts, __u8 epaddr);
+
+/* Quirks support */
+void uvc_video_decode_isight(struct urb *urb, struct uvc_streaming *stream,
+		struct uvc_buffer *buf);
+
+#endif /* __KERNEL__ */
+
+#endif
+
diff --git a/src/libwebcam/webcam.h b/src/libwebcam/webcam.h
new file mode 100644
index 0000000..e981499
--- /dev/null
+++ b/src/libwebcam/webcam.h
@@ -0,0 +1,721 @@
+/**
+ * \file
+ * Webcam library interface definition.
+ *
+ * \ingroup libwebcam
+ */
+
+/*
+ * Copyright (c) 2006-2007 Logitech.
+ *
+ * This file is part of libwebcam.
+ * 
+ * libwebcam is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ * 
+ * libwebcam is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with libwebcam.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef C_WEBCAM_H
+#define C_WEBCAM_H
+
+
+/*
+ * Basic type definitions
+ */
+
+/// Device handle for libwebcam
+typedef unsigned int CHandle;
+/// Function return type for libwebcam
+typedef unsigned int CResult;
+
+
+
+/*
+ * Enums
+ */
+
+/**
+ * Return values for libwebcam functions.
+ */
+enum _CResults {
+	C_SUCCESS				= 0,	///< Success
+	C_NOT_IMPLEMENTED,		///< The function is not implemented
+	C_INIT_ERROR,			///< Error during initialization or library not initialized
+	C_INVALID_ARG,			///< Invalid argument
+	C_INVALID_HANDLE,		///< Invalid handle
+	C_INVALID_DEVICE,		///< Invalid device or device cannot be opened
+	C_NOT_EXIST,			///< The device to which the handle points no longer exists
+	C_NOT_FOUND,			///< Object not found
+	C_BUFFER_TOO_SMALL,		///< Buffer too small
+	C_SYNC_ERROR,			///< Error during data synchronization
+	C_NO_MEMORY,			///< Out of memory
+	C_NO_HANDLES,			///< Out of handles
+	C_V4L2_ERROR,			///< A Video4Linux2 API call returned an unexpected error
+	C_SYSFS_ERROR,			///< A sysfs file access returned an error
+	C_PARSE_ERROR,			///< A control could not be parsed
+	C_CANNOT_WRITE,			///< Writing not possible (e.g. read-only control)
+	C_CANNOT_READ,			///< Reading not possible (e.g. write-only control)
+};
+
+
+/**
+ * Control identifiers.
+ * This is an exhaustive list of all controls supported by libwebcam. As new
+ * controls appear, these should be added to this list.
+ */
+typedef enum _CControlId {
+	// UVC: Basic image control
+	CC_BRIGHTNESS		= 1,			///< Image brightness
+	CC_CONTRAST,						///< Image contrast
+	CC_GAIN,							///< Gain control
+	CC_SATURATION,						///< Image color saturation
+	CC_HUE,								///< Hue
+	CC_GAMMA,							///< Gamma correction
+	CC_SHARPNESS,						///< Image sharpness
+
+	// UVC: Advanced image control
+	/// White balance color temperature
+	CC_WHITE_BALANCE_TEMPERATURE,
+	/// Enable/disable automatic while balance color temperature selection
+	CC_AUTO_WHITE_BALANCE_TEMPERATURE,
+	/// White balance color component control (red, blue)
+	CC_WHITE_BALANCE_COMPONENT,
+	/// Enable/disable automatic white balance color component selection
+	CC_AUTO_WHITE_BALANCE_COMPONENT,
+	/// Backlight compensation mode
+	CC_BACKLIGHT_COMPENSATION,
+	/// Local power line frequency for anti-flicker processing
+	CC_POWER_LINE_FREQUENCY,
+	/// Enable/disable automatic hue control
+	CC_AUTO_HUE,
+	/// Mode for automatic exposure control
+	CC_AUTO_EXPOSURE_MODE,
+	/// Constraints for automatic exposure control (e.g. adaptive vs. constant frame rate)
+	CC_AUTO_EXPOSURE_PRIORITY,
+	/// Length of exposure (electronic shutter speed)
+	CC_EXPOSURE_TIME_ABSOLUTE,
+	/// Relative change to the current length of exposure
+	CC_EXPOSURE_TIME_RELATIVE,
+
+	// UVC: Optics control
+	/// Enable/disable automatic focus adjustment
+	CC_AUTO_FOCUS,
+	/// Distance to optimally focused target
+	CC_FOCUS_ABSOLUTE,
+	/// Relative change in distance to currently focused target
+	CC_FOCUS_RELATIVE,
+	/// Aperture setting
+	CC_IRIS_ABSOLUTE,
+	/// Relative change to the current aperture setting
+	CC_IRIS_RELATIVE,
+	/// Objective lens focal length
+	CC_ZOOM_ABSOLUTE,
+	/// Relative change to the current objective lens focal length
+	CC_ZOOM_RELATIVE,
+	/// Digital zoom multiplier applied to the optical image
+	CC_DIGITAL_ZOOM,
+
+	// UVC: Motion control
+	/// Pan angle (rotation on a vertical axis)
+	CC_PAN_ABSOLUTE,
+	/// Relative change to the current pan angle
+	CC_PAN_RELATIVE,
+	/// Tilt angle (rotation in a vertical plane)
+	CC_TILT_ABSOLUTE,
+	/// Relative change to the current tilt angle
+	CC_TILT_RELATIVE,
+	/// Roll angle (rotation along the image viewing axis)
+	CC_ROLL_ABSOLUTE,
+	/// Relative change to the current roll angle
+	CC_ROLL_RELATIVE,
+
+	// UVC: Misc
+	/// Temporarily prevent image from being acquired
+	CC_PRIVACY,
+
+	// V4L2: Motion control (new since 2.6.26)
+	/// Reset pan angle to a safe default value.
+	CC_PAN_RESET,
+	/// Reset tilt angle to a safe default value.
+	CC_TILT_RESET,
+
+	// V4L2: Unknown controls
+	/// Base for unknown V4L2 controls
+	CC_V4L2_BASE				= 0x1000,
+	/// Base for custom V4L2 driver controls
+	CC_V4L2_CUSTOM_BASE			= 0x2000,
+	/// Base for unknown V4L2 MPEG controls
+	CC_V4L2_MPEG_BASE			= 0x3000,
+	/// Base for unknown V4L2 camera class controls
+	CC_V4L2_CAMERA_CLASS_BASE	= 0x4000,
+
+	// Logitech (USB vendor ID: 0x046d)
+	CC_LOGITECH_BASE = 0x046d0000,
+	/// Relative change to the current pan and tilt angles.
+	/// This control is specific to Logitech cameras that support panning and
+	/// tilting such as the QuickCam Orbit series.
+	CC_LOGITECH_PANTILT_RELATIVE,
+	/// Reset pan and tilt angles to a safe default value.
+	/// This control is specific to Logitech cameras that support panning and
+	/// tilting such as the QuickCam Orbit series.
+	CC_LOGITECH_PANTILT_RESET,
+	// Illumination mode of the first LED.
+	CC_LOGITECH_LED1_MODE,
+	// Blinking frequency of the first LED.
+	CC_LOGITECH_LED1_FREQUENCY,
+	// Disable video processing (enable raw mode)
+	CC_LOGITECH_DISABLE_PROCESSING,
+	// Bits per pixel for raw (Bayer) mode
+	CC_LOGITECH_RAW_BITS_PER_PIXEL,
+
+
+} CControlId;
+
+
+/**
+ * Flags specifying control properties and capabilities.
+ */
+typedef enum _CControlFlags {
+	/// The control can be read, i.e. its current value can be queried.
+	/// This flag is usually not set for action controls.
+	CC_CAN_READ				= 1 << 0,
+	/// The control can be changed, i.e. it can be set to a new value.
+	/// Note that this flag does not imply CC_CAN_READ. Action controls accept
+	/// values but cannot necessarily be queried.
+	CC_CAN_WRITE			= 1 << 1,
+	/// The control supports value change notification.
+	CC_CAN_NOTIFY			= 1 << 2,
+
+	// The control is a custom vendor control and not standardized in V4L2 or UVC.
+	CC_IS_CUSTOM			= 1 << 8,
+	// Set values are interpreted as being relative to the current value.
+	CC_IS_RELATIVE			= 1 << 9,
+	// The control triggers an action.
+	CC_IS_ACTION			= 1 << 10,
+
+} CControlFlags;
+
+
+/**
+ * Types for controls.
+ * These types give both hints to graphical user interfaces on how to display
+ * the control to the user as well as to the implementation in terms of data
+ * length required to store control values.
+ */
+typedef enum _CControlType {
+	/// The control uses raw binary data.
+	/// Usually (but not necessarily) this includes values that cannot be easily
+	/// mapped to simple data types.
+	CC_TYPE_RAW				= 1,
+	/// The control knows only one enabled/disabled state.
+	/// Controls of this type are typically displayed as checkboxes.
+	CC_TYPE_BOOLEAN,
+	/// The control accepts a defined list of values.
+	/// Controls of this type are typically displayed as combo boxes or lists.
+	CC_TYPE_CHOICE,
+	/// The control accepts 8-bit integer values.
+	CC_TYPE_BYTE,
+	/// The control accepts 16-bit integer values.
+	CC_TYPE_WORD,
+	/// The control accepts 32-bit integer values.
+	CC_TYPE_DWORD,
+
+} CControlType;
+
+
+/**
+ * Event identifiers.
+ */
+typedef enum _CEventId {
+	CE_CONTROL_INVALID		= 0,
+
+} CEventId;
+
+
+/**
+ * Flags specifying properties of events.
+ */
+typedef enum _CEventFlags {
+	CE_INVALID				= 0,
+
+} CEventFlags;
+
+
+/**
+ * Types of frame size specifications.
+ */
+typedef enum _CFrameSizeTypes {
+	/// One discrete width/height combination.
+	CF_SIZE_DISCRETE		= 1,
+	/// Minimum and maximum values for both width and height.
+	CF_SIZE_CONTINUOUS,
+	/// Minimum, maximum, and step values for both width and height.
+	CF_SIZE_STEPWISE,
+
+} CFrameSizeTypes;
+
+
+/**
+ * Types of frame interval specification.
+ */
+typedef enum _CFrameIntervalTypes {
+	/// One discrete time interval.
+	CF_INTERVAL_DISCRETE		= 1,
+	/// Minimum and maximum values for the time interval.
+	CF_INTERVAL_CONTINUOUS,
+	/// Minimum, maximum, and step values for the time interval.
+	CF_INTERVAL_STEPWISE,
+
+} CFrameIntervalTypes;
+
+
+/**
+ * Flags specifying control properties and capabilities.
+ */
+typedef enum _CDynctrlFlags {
+	/// Disable XML schema validation.
+	CD_DONT_VALIDATE		= 1 << 0,
+	/// Collect errors and warnings during the process
+	CD_REPORT_ERRORS		= 1 << 1,
+	/// Return meta data during the XML parsing process
+	CD_RETRIEVE_META_INFO	= 1 << 2,
+
+} CDynctrlFlags;
+
+
+/**
+ * Severity levels for messages returned by the dynamic control functions
+ */
+typedef enum _CDynctrlMessageSeverity {
+	CD_SEVERITY_ERROR		= 2,		///< Error
+	CD_SEVERITY_WARNING		= 3,		///< Warning
+	CD_SEVERITY_INFO		= 4,		///< Informational
+
+} CDynctrlMessageSeverity;
+
+
+
+/*
+ * Structs
+ */
+
+/**
+ * USB specific information about a device.
+ */
+typedef struct _CUSBInfo {
+	/// The vendor ID.
+	unsigned short	vendor;
+	/// The product ID.
+	unsigned short	product;
+	/// The product revision number.
+	unsigned short	release;
+
+} CUSBInfo;
+
+
+/**
+ * Webcam device information.
+ */
+typedef struct _CDevice {
+	/// A unique short name.
+	/// For V4L2 devices this is the name of the device file. For example, if
+	/// a device appears as '/dev/video0', the short name is 'video0'.
+	/// This member is never NULL.
+	char			* shortName;
+	
+	/// The human-readable name of the device.
+	/// This member is never NULL.
+	char			* name;
+
+	/// The name of the driver providing the camera interface.
+	/// This member is never NULL.
+	char			* driver;
+
+	/// The location of the camera.
+	/// This string is dependent on the implementation that provides the device.
+	/// It could either be a string provided by the driver or a device name.
+	/// This member is never NULL.
+	char			* location;
+
+	/// USB related information about the camera.
+	CUSBInfo		usb;
+
+} CDevice;
+
+
+/**
+ * A raw control value.
+ */
+typedef struct _CControlRawValue {
+	/// Pointer to the raw data.
+	void			* data;
+	/// Size of the raw data.
+	unsigned int	size;
+
+} CControlRawValue;
+
+
+/**
+ * A value of a control.
+ */
+typedef struct _CControlValue {
+	/// The type of the control to which the value belongs.
+	/// This member is used to determine which of the members of the union are
+	/// valid. The type is a duplicate of the corresponding CControl#type value.
+	CControlType	type;
+
+	union {
+		/// The value of the control for number based controls.
+		/// This member is valid for the following control types:
+		/// #CC_TYPE_BOOLEAN, #CC_TYPE_CHOICE, #CC_TYPE_BYTE,
+		/// #CC_TYPE_WORD, #CC_TYPE_DWORD
+		int				value;
+
+		/// The value of the control for raw cntrols.
+		/// This member is valid only for control type #CC_TYPE_RAW.
+		CControlRawValue	raw;
+	};
+
+} CControlValue;
+
+
+/**
+ * A list of choices for a choice type of control.
+ * @see CC_TYPE_CHOICE
+ */
+typedef struct _CControlChoice {
+	/// The index of the choice within the list of choices.
+	/// Note that this index is not necessarily zero-based and can therefore @a not
+	/// be used as an index into CControl#choices#list[].
+	int				index;
+
+	/// The name of the choice.
+	/// This member is never NULL.
+	char			* name;
+
+} CControlChoice;
+
+
+/**
+ * A description of a camera control.
+ */
+typedef struct _CControl {
+	/// The identifier of the control
+	CControlId		id;
+	/// The human-readable name of the control
+	char			* name;
+	/// The type of the control
+	CControlType	type;
+	/// Flags describing properties and capabilities of the control
+	CControlFlags	flags;
+
+	/// The current value of the control
+	CControlValue	value;
+	/// The default value of the control
+	CControlValue	def;
+
+	union {
+		/// Additional control attributes for non-choice controls.
+		/// The members of this struct are only valid for control types other
+		/// than #CC_TYPE_CHOICE.
+		struct {
+			/// The minimum value of the control
+			CControlValue	min;
+			/// The maximum value of the control
+			CControlValue	max;
+			/// The resolution of the control values
+			CControlValue	step;
+		};
+
+		/// List of the possible choices that this control allows.
+		/// The members of this struct are only valid if the type is #CC_TYPE_CHOICE.
+		struct {
+			/// The number of choices in the list
+			unsigned int	count;
+			/// The list of choice values
+			CControlChoice	* list;
+			
+			/// A buffer that contains the names of the #CControlChoice items.
+			/// The @a name fields of the items point to strings within this buffer,
+			/// so there is no need to work with this member directly except
+			/// freeing the buffer if the control is disposed of.
+			char			* names;
+
+		} choices;
+	};
+
+} CControl;
+
+
+/**
+ * A description of a pixel format.
+ */
+typedef struct _CPixelFormat {
+	/// A FourCC code identifying the pixel format.
+	/// Note that this member contains an extra byte which will contain a \\0
+	/// character when returned by c_enum_pixel_formats(). This allows the field
+	/// to be treated like a NUL terminated string.
+	char			fourcc[5];
+
+	/// A human-readable description of the pixel format.
+	char			* name;
+
+	/// The MIME type corresponding to the pixel format.
+	/// This member can be NULL.
+	char			* mimeType;
+
+} CPixelFormat;
+
+
+/**
+ * A description of one or multiple frame sizes.
+ */
+typedef struct _CFrameSize {
+	/// Type of the frame size(s) described (discrete, continuous, step-wise)
+	CFrameSizeTypes	type;
+	
+	union {
+		/// Discrete frame size.
+		/// This member is only valid if @a type is #CF_SIZE_DISCRETE.
+		struct {
+			/// Width
+			unsigned int	width;
+			/// Height
+			unsigned int	height;
+		};
+
+		/// Continuous or step-wise frame size.
+		/// This member is only valid if @a type is #CF_SIZE_CONTINUOUS or
+		/// #CF_SIZE_STEPWISE.
+		struct {
+			/// Minimum width
+			unsigned int	min_width;
+			/// Maximum width
+			unsigned int	max_width;
+			/// Step size for the width (usually 1 if @a type is #CF_SIZE_CONTINUOUS)
+			unsigned int	step_width;
+			/// Minimum height
+			unsigned int	min_height;
+			/// Maximum height
+			unsigned int	max_height;
+			/// Step size for the height (usually 1 if @a type is #CF_SIZE_CONTINUOUS)
+			unsigned int	step_height;
+		};
+	};
+
+} CFrameSize;
+
+
+/**
+ * A description of one or multiple frame intervals.
+ * Each frame interval is described as a fraction of a second.
+ */
+typedef struct _CFrameInterval {
+	/// Type of the frame interval(s) described (discrete, continuous, step-wise)
+	CFrameIntervalTypes	type;
+
+	union {
+		/// Discrete frame interval.
+		/// This member is only valid if @a type is #CF_INTERVAL_DISCRETE.
+		struct {
+			/// Numerator of the frame interval
+			unsigned int	n;
+			/// Denominator of the frame interval
+			unsigned int	d;
+		};
+
+		/// Continuous or step-wise frame interval.
+		/// This member is only valid if @a type is #CF_INTERVAL_CONTINUOUS or
+		/// #CF_INTERVAL_STEPWISE.
+		struct {
+			/// Numerator of the minimum frame interval
+			unsigned int	min_n;
+			/// Denominator of the minimum frame interval
+			unsigned int	min_d;
+			/// Numerator of the maximum frame interval
+			unsigned int	max_n;
+			/// Denominator of the maximum frame interval
+			unsigned int	max_d;
+			/// Numerator of the frame interval step size (usually 1 if @a type is #CF_INTERVAL_CONTINUOUS
+			unsigned int	step_n;
+			/// Denominator of the frame interval step size (usually 1 if @a type is #CF_INTERVAL_CONTINUOUS
+			unsigned int	step_d;
+		};
+	};
+
+} CFrameInterval;
+
+
+/**
+ * An event descriptor.
+ */
+typedef struct _CEvent {
+	/// Unique identifier of the event
+	CEventId		id;
+
+	/// Human-readable name of the event
+	char			* name;
+
+	/// Flags descripting properties of the event
+	CEventFlags		flags;
+
+} CEvent;
+
+
+/**
+ * Message returned by the dynamic control configuration parser.
+ */
+typedef struct _CDynctrlMessage {
+	/// Line number that the message concerns
+	int				line;
+
+	/// Column that the message concerns
+	int				col;
+
+	/// Severity level
+	CDynctrlMessageSeverity	severity;
+
+	/// Pointer to the message text
+	char			* text;
+
+} CDynctrlMessage;
+
+
+/**
+ * Version number in the "major.minor" format.
+ */
+typedef struct _CVersionNumber {
+	/// Major version number
+	unsigned int	major;
+
+	/// Minor version number
+	unsigned int	minor;
+
+} CVersionNumber;
+
+
+/**
+ * Statistics on the number of list elements that were processed.
+ */
+typedef struct _CDynctrlInfoListStats {
+	/// Number of elements in the list that were processed successfully
+	unsigned int	successful;
+
+	/// Number of elements in the list that could not be processed successfully
+	unsigned int	failed;
+
+} CDynctrlInfoListStats;
+
+
+/**
+ * Input flags and output data used/returned by the control configuration parser.
+ */
+typedef struct _CDynctrlInfo {
+	/// Flags controlling operations related to dynamic controls
+	CDynctrlFlags	flags;
+
+	/// Processing statistics
+	struct {
+		/// Statistics on the constants that were processed
+		CDynctrlInfoListStats	constants;
+
+		/// Statistics on the controls that were processed
+		CDynctrlInfoListStats	controls;
+
+		/// Statistics on the mappings that were processed
+		CDynctrlInfoListStats	mappings;
+
+	}				stats;
+
+	/// Meta information about the XML control configuration
+	struct {
+		/// File format version
+		CVersionNumber	version;
+
+		/// Name of the configuration author
+		char			* author;
+
+		/// Contact information of the configuration author (e.g. e-mail address)
+		char			* contact;
+
+		/// Copyright information about the configuration file
+		char			* copyright;
+
+		/// Revision number of the configuration file (configuration version)
+		CVersionNumber	revision;
+
+	}				meta;
+
+	/// Number of messages in the @a messages array
+	unsigned int	message_count;
+
+	/// Pointer to the array with the messages concerning the operation
+	CDynctrlMessage	* messages;
+
+} CDynctrlInfo;
+
+
+
+/*
+ * Type definitions
+ */
+
+/**
+ * Prototype for event handlers
+ */
+typedef void (*CEventHandler)(CHandle hDevice, CEventId event_id, void *context);
+
+
+
+/*
+ * Functions
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern CResult		c_init (void);
+extern void			c_cleanup (void);
+
+extern CHandle		c_open_device (const char *device_name);
+extern void			c_close_device (CHandle hDevice);
+extern int 		c_get_file_descriptor (CHandle hDevice);
+
+extern CResult		c_enum_devices (CDevice *devices, unsigned int *size, unsigned int *count);
+extern CResult		c_get_device_info (CHandle hDevice, const char *device_name, CDevice *info, unsigned int *size);
+
+extern CResult		c_enum_pixel_formats (CHandle hDevice, CPixelFormat *formats, unsigned int *size, unsigned int *count);
+extern CResult		c_enum_frame_sizes (CHandle hDevice, const CPixelFormat *pixelformat, CFrameSize *sizes, unsigned int *size, unsigned int *count);
+extern CResult		c_enum_frame_intervals (CHandle hDevice, const CPixelFormat *pixelformat, const CFrameSize *framesize, CFrameInterval *intervals, unsigned int *size, unsigned int *count);
+
+extern CResult		c_enum_controls (CHandle hDevice, CControl *controls, unsigned int *size, unsigned int *count);
+extern CResult		c_set_control (CHandle hDevice, CControlId control_id, const CControlValue *value);
+extern CResult		c_get_control (CHandle hDevice, CControlId control_id, CControlValue *value);
+
+extern CResult		c_enum_events (CHandle hDevice, CEvent *events, unsigned int *size, unsigned int *count);
+extern CResult		c_subscribe_event (CHandle hDevice, CEventId event_id, CEventHandler handler, void *context);
+extern CResult		c_unsubscribe_event (CHandle hDevice, CEventId event_id);
+
+#ifndef DISABLE_UVCVIDEO_DYNCTRL
+extern CResult		c_add_control_mappings_from_file (const char *file_name, CDynctrlInfo *info);
+#endif
+
+extern char			*c_get_error_text (CResult error);
+extern char			*c_get_handle_error_text (CHandle hDevice, CResult error);
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif /* C_WEBCAM_H */
diff --git a/src/mod_audio/CMakeLists.txt b/src/mod_audio/CMakeLists.txt
new file mode 100755
index 0000000..3b62c3c
--- /dev/null
+++ b/src/mod_audio/CMakeLists.txt
@@ -0,0 +1,12 @@
+cmake_minimum_required(VERSION 2.6)
+project(mod_audio)
+
+set(mod_audio_SRCS	
+	mod_audio.cpp
+)
+
+add_library (mod_audio MODULE ${mod_audio_SRCS})
+target_link_libraries(mod_audio spcore)
+target_link_libraries(mod_audio ${wxWidgets_LIBRARIES})
+
+INSTALL (TARGETS mod_audio RUNTIME DESTINATION ${LIBRUNTIMEDIR} LIBRARY DESTINATION ${PLUGINDIR})
diff --git a/src/mod_audio/mod_audio.cpp b/src/mod_audio/mod_audio.cpp
new file mode 100644
index 0000000..21882e2
--- /dev/null
+++ b/src/mod_audio/mod_audio.cpp
@@ -0,0 +1,162 @@
+/////////////////////////////////////////////////////////////////////////////
+// File:        mod_audio.cpp
+// Author:      Cesar Mauri Loba (cesar at crea-si dot com)
+// Copyright:   (C) 2011 Cesar Mauri Loba - CREA Software Systems
+//
+//  This program is free software: you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation, either version 3 of the License, or
+//  (at your option) any later version.
+//
+//  This program is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+/////////////////////////////////////////////////////////////////////////////
+#include "spcore/component.h"
+#include "spcore/module.h"
+#include "spcore/libimpexp.h"
+#include "spcore/basictypes.h"
+
+#include <wx/sound.h>
+
+#include <string>
+
+/**
+	Quick and dirty audio player implementation based on wx.
+
+	@todo consider better audio libraries such as:
+		- http://audiere.sourceforge.net/
+		- http://www.xiph.org/ao/doc/
+		- http://connect.creativelabs.com/openal/default.aspx
+		- http://sourceforge.net/projects/osalp/
+		- http://ffmpeg.org/about.html
+		- http://www.portaudio.com/docs.html (streaming only)
+		- Gstreamer???
+
+*/
+
+using namespace spcore;
+
+namespace mod_audio {
+
+/**
+	wav_player component
+
+		Plays a WAV file.
+		
+	Input pins:
+		play (any)			- Start playing
+		stop (any)			- Stop playing
+			
+	Ouput pins:		
+
+	Command line:
+		[-p <path>]		Set initial path
+*/
+class WavPlayer : public CComponentAdapter {
+public:
+	static const char* getTypeName() { return "wav_player"; }
+	virtual const char* GetTypeName() const { return WavPlayer::getTypeName(); }
+	WavPlayer(const char * name, int argc, const char * argv[]) 
+	: CComponentAdapter(name, argc, argv)
+	{
+		//m_opinElapsed= CTypeInt::CreateOutputPin("elapsed");
+		//if (RegisterOutputPin(*m_opinElapsed)!= 0)
+		//	throw std::runtime_error("error registering output pin");
+
+		if (RegisterInputPin(*SmartPtr<IInputPin>(new InputPinPlay("play", *this), false))!= 0)
+			throw std::runtime_error("error creating input pin play");
+
+		if (RegisterInputPin(*SmartPtr<IInputPin>(new InputPinStop("stop", *this), false))!= 0)
+			throw std::runtime_error("error creating input pin stop");
+
+		// Process arguments
+		if (argc) {			
+			for (int i= 0; i< argc; ++i) {
+				if (argv[i] && strcmp ("-p", argv[i])== 0) {
+					// Path					
+				
+					++i;
+					if (i< argc && argv[i]) {						
+						wxString filePath(argv[i], wxConvUTF8);
+						if (!m_sound.Create (filePath) && m_sound.IsOk()) {
+							std::string error_msg("wav_player. Cannot open file:");
+							error_msg+= argv[i];
+							throw std::runtime_error(error_msg);
+						}
+					}
+					else throw std::runtime_error("wav_player. Missing value for option -p");
+				}			
+				else if (argv[i] && strlen(argv[i])) {
+					std::string error_msg("wave_player. Unknown option:");
+					error_msg+= argv[i];
+					throw std::runtime_error(error_msg);
+				}
+			}
+		}
+	}
+
+private:
+	virtual ~WavPlayer() {}
+
+	class InputPinPlay : public CInputPinWriteOnly<CTypeAny, WavPlayer> {
+	public:
+		InputPinPlay (const char * name, WavPlayer & component)
+		: CInputPinWriteOnly<CTypeAny, WavPlayer>(name, component) { }
+
+		virtual int DoSend(const CTypeAny & ) {
+			m_component->m_sound.Play();
+			return 0;
+		}
+	};
+
+	class InputPinStop : public CInputPinWriteOnly<CTypeAny, WavPlayer> {
+	public:
+		InputPinStop (const char * name, WavPlayer & component)
+		: CInputPinWriteOnly<CTypeAny, WavPlayer>(name, component) { }
+
+		virtual int DoSend(const CTypeAny & ) {
+			m_component->m_sound.Stop();
+			return 0;
+		}
+	};
+
+	//
+	// Data members
+	//
+	//SmartPtr<IOutputPin> m_opinElapsed;
+	wxSound m_sound;
+};
+
+typedef ComponentFactory<WavPlayer> WavPlayerFactory;
+
+/* ******************************************************************************
+	audio  module
+****************************************************************************** */
+class AudioModule : public CModuleAdapter {
+public:
+	AudioModule() {
+		//
+		// components
+		//
+		RegisterComponentFactory(SmartPtr<spcore::IComponentFactory>(new WavPlayerFactory(), false));
+	}
+
+	~AudioModule() {
+	}
+
+	virtual const char * GetName() const { return "mod_audio"; }
+};
+
+static spcore::IModule* g_module= NULL;
+SPEXPORT_FUNCTION spcore::IModule* module_create_instance()
+{
+	if (g_module== NULL) g_module= new AudioModule();
+	return g_module;
+}
+
+};
diff --git a/src/mod_camera/CMakeLists.txt b/src/mod_camera/CMakeLists.txt
new file mode 100755
index 0000000..cf90a85
--- /dev/null
+++ b/src/mod_camera/CMakeLists.txt
@@ -0,0 +1,39 @@
+cmake_minimum_required(VERSION 2.6)
+project(mod_camera)
+
+set(mod_camera_HEADERS
+	${CUSTOM_INCLUDE_PATH}/mod_camera/iplimagetype.h
+	${CUSTOM_INCLUDE_PATH}/mod_camera/roitype.h
+)
+set(mod_camera_SRCS
+	${mod_camera_HEADERS}
+	roitype.cpp
+	mod_camera.cpp
+	mod_camera.h
+	wcameraconfiguration.cpp
+	wcameraconfiguration.h
+	wcamerapanel.cpp
+	wcamerapanel.h
+	wxroicontrol.h
+	wxroicontrol.cpp
+)
+
+# Base library
+FIND_PACKAGE( OpenCV REQUIRED core)
+INCLUDE_DIRECTORIES (${OpenCV_INCLUDE_DIR})
+INCLUDE_DIRECTORIES (..)
+find_package(Boost COMPONENTS thread program_options REQUIRED)
+
+add_library (mod_camera MODULE ${mod_camera_SRCS})
+target_link_libraries(mod_camera creavision)
+target_link_libraries(mod_camera spcore)
+target_link_libraries(mod_camera ${Boost_THREAD_LIBRARY})
+target_link_libraries(mod_camera ${Boost_PROGRAM_OPTIONS_LIBRARY})
+target_link_libraries(mod_camera ${wxWidgets_LIBRARIES})
+
+IF(BUILD_TESTS)
+	ADD_SUBDIRECTORY(tests)
+ENDIF(BUILD_TESTS)
+
+install (FILES ${mod_camera_HEADERS} DESTINATION ${INCLUDEDIR}/${PROJECT_NAME})
+INSTALL (TARGETS mod_camera RUNTIME DESTINATION ${LIBRUNTIMEDIR} LIBRARY DESTINATION ${PLUGINDIR})
diff --git a/src/mod_camera/mod_camera.cpp b/src/mod_camera/mod_camera.cpp
new file mode 100644
index 0000000..9f6309d
--- /dev/null
+++ b/src/mod_camera/mod_camera.cpp
@@ -0,0 +1,425 @@
+/////////////////////////////////////////////////////////////////////////////
+// File:        mod_camera.cpp
+// Author:      Cesar Mauri Loba (cesar at crea-si dot com)
+// Copyright:   (C) 2011 Cesar Mauri Loba - CREA Software Systems
+//
+//  This program is free software: you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation, either version 3 of the License, or
+//  (at your option) any later version.
+//
+//  This program is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+/////////////////////////////////////////////////////////////////////////////
+#include "mod_camera.h"
+#include "wcameraconfiguration.h"
+#include "wcamerapanel.h"
+#include "mod_camera/roitype.h"
+#include "wxroicontrol.h"
+#include "spcore/libimpexp.h"
+
+#include <boost/bind.hpp>
+#include <boost/shared_ptr.hpp>
+#include <boost/thread/recursive_mutex.hpp>
+
+using namespace spcore;
+
+namespace mod_camera {
+
+
+wxWindow * CameraConfig::GetGUI(wxWindow * parent) {
+	return new CCameraConfiguration(parent);
+}
+
+typedef SingletonComponentFactory<CameraConfig> CameraConfigFactory;
+
+/*
+	camera_grabber component
+*/
+class CameraGrabber : public spcore::CComponentAdapter, public CameraCaptureListener
+{
+public:
+	static const char * getTypeName() { return "camera_grabber"; }
+	virtual const char * GetTypeName() const { return CameraGrabber::getTypeName(); }
+
+	CameraGrabber(const char * name, int argc, const char * argv[])
+	: CComponentAdapter(name, argc, argv)
+	{
+		// Create output pin
+		m_oPinResult= CTypeIplImage::CreateOutputPin("image");
+		if (m_oPinResult.get()== NULL)
+			// Output pin creation failed. Shouldn't happen but...
+			throw std::runtime_error("camera_grabber. output pin creation failed.");
+		RegisterOutputPin (*m_oPinResult);
+
+		m_cameraConfig= smartptr_dynamic_cast<CameraConfig,IComponent>(
+			getSpCoreRuntime()->CreateComponent("camera_config", "camera_config", 0, NULL));
+
+		if (!m_cameraConfig.get()) {
+			getSpCoreRuntime()->LogMessage(ICoreRuntime::LOG_FATAL, "cannot create camera_config module", "mod_camera");
+			throw std::runtime_error("cannot create camera_config module");
+		}
+	}
+	
+private:
+	SmartPtr<spcore::IOutputPin> m_oPinResult;	// output pin
+	SmartPtr<mod_camera::CameraConfig> m_cameraConfig;
+
+	virtual ~CameraGrabber() {
+		Stop();
+	}
+	virtual void CameraCaptureCallback (SmartPtr<const CTypeIplImage> img) {
+		// TODO: send image as the MAIN THREAD
+		m_oPinResult->Send(img);
+	}
+
+	virtual bool ProvidesExecThread() const { return true; }
+
+	// Starts the component
+    // \return 0 if successfully started, -1 otherwise
+	virtual int DoStart() {
+		m_cameraConfig->RegisterListener (*this);
+		return 0;
+	}
+
+    //Stops the component.
+	virtual void DoStop() {
+		m_cameraConfig->UnregisterListener (*this);
+	}
+};
+
+// camera_grabber component factory
+typedef ComponentFactory<CameraGrabber> CameraGrabberFactory;
+
+/*
+	camera_viewer component
+*/
+
+class CameraViewer : public spcore::CComponentAdapter
+{
+public:
+	CameraViewer(const char * name, int argc, const char * argv[])
+	: CComponentAdapter(name, argc, argv)
+	, m_viewerPanel(NULL) {
+		m_oPinResult= CTypeROI::CreateOutputPin("roi");
+		if (m_oPinResult.get()== NULL)
+			// Output pin creation failed. Shouldn't happen but...
+			throw std::runtime_error("camera_viewer. output pin creation failed.");
+		RegisterOutputPin (*m_oPinResult);
+
+		m_roiControls=  boost::shared_ptr<WXRoiControls>(
+			new WXRoiControls(boost::bind(&CameraViewer::NotifyROIModification, this, _1)));
+		if (m_roiControls.get()== NULL) {
+			// Output pin creation failed. Shouldn't happen but...
+			throw std::runtime_error("camera_viewer. WXRoiControls creation failed.");
+		}
+
+		RegisterInputPin (*SmartPtr<InputPinImage>(new InputPinImage(*this), false));
+		RegisterInputPin (*SmartPtr<InputPinROI>(new InputPinROI(*this), false));
+	}
+
+	static const char * getTypeName() { return "camera_viewer"; }
+	virtual const char * GetTypeName() const { return CameraViewer::getTypeName(); }
+
+	virtual wxWindow* GetGUI(wxWindow * parent) {
+		assert (wxIsMainThread());
+		boost::recursive_mutex::scoped_lock lock(m_mutex);
+		if (m_viewerPanel) {
+			// Already created change parent ????
+			assert (false);
+			getSpCoreRuntime()->LogMessage(ICoreRuntime::LOG_ERROR, "camera panel alredy open", "mod_camera");
+			return NULL;
+		}
+		else {
+			m_viewerPanel= new CameraPanel(
+				CameraPanel::CleanupFunctor(boost::bind (&CameraViewer::OnPanelDestroyed, this)),
+				m_roiControls.get()
+			);
+			//m_viewerPanel->SetReziseParent ( true );
+			m_viewerPanel->Create (parent);
+		}
+
+		return m_viewerPanel;
+	}
+private:
+	boost::shared_ptr<WXRoiControls> m_roiControls;
+	CameraPanel *m_viewerPanel;
+	SmartPtr<spcore::IOutputPin> m_oPinResult;
+	boost::recursive_mutex m_mutex;
+
+	void NotifyROIModification (SmartPtr<const CTypeROI> roi)
+	{
+		m_oPinResult->Send(roi);
+	}
+
+	virtual ~CameraViewer() {
+		assert (wxIsMainThread());
+		boost::recursive_mutex::scoped_lock lock(m_mutex);
+		if (m_viewerPanel) {
+			m_viewerPanel->RemoveCleanupFunctor();
+			m_viewerPanel->Close();
+			m_viewerPanel= NULL;
+		}
+	}
+
+	void OnPanelDestroyed() {
+		assert (wxIsMainThread());
+		boost::recursive_mutex::scoped_lock lock(m_mutex);
+		m_viewerPanel= NULL;
+	}
+	void OnImage(const CTypeIplImage & img) {
+		if (wxIsMainThread()) {
+			if (m_viewerPanel) m_viewerPanel->DrawCam(img.getImage());
+		}
+		else {
+			boost::recursive_mutex::scoped_lock lock(m_mutex);
+			if (m_viewerPanel) m_viewerPanel->DrawCam(img.getImage());
+		}
+	}
+
+	// Write-only pin to send the image
+	class InputPinImage : public spcore::CInputPinWriteOnly<CTypeIplImage, CameraViewer> {
+	public:
+		InputPinImage (CameraViewer & component)
+		: CInputPinWriteOnly<CTypeIplImage, CameraViewer>("image", component) { }
+
+		virtual int DoSend(const CTypeIplImage & img) {
+			m_component->OnImage(img);
+			return 0;
+		}
+	};
+
+	// Write-only pin to send a ROI
+	class InputPinROI : public spcore::CInputPinWriteOnly<CTypeROI, CameraViewer> {
+	public:
+		InputPinROI (CameraViewer & component)
+		: CInputPinWriteOnly<CTypeROI, CameraViewer>("roi", component) { }
+
+		virtual int DoSend(const CTypeROI & roi) {
+			m_component->m_roiControls->UpdateRootROI (roi);
+			return 0;
+		}
+	};
+};
+
+// camera_viewer component factory
+typedef ComponentFactory<CameraViewer> CameraViewerFactory;
+
+/* ******************************************************************************
+	roi_storage component
+
+	Input pins:
+		roi (roi): internally stores a copy of the ROI object and sends the
+			result through the output pin
+
+		roi_same_id:  internally stores a copy of the ROI object if has the same ID 
+			and sends the result through the output pin
+
+		centre (compsite of 2 floats):
+			centres the roi around the given point and sends the
+			result through the output pin
+
+		visible (bool)
+			shows or hides the roi
+						
+	Output pins:
+		roi (roi): resulting roi
+
+	Command line flags:
+		-s x y		roi size. two floats between 0 and 1. (default 1 1)
+		-c x y		roi centre. two floats between 0 and 1 (default 0,5 0,5)
+		-v [0|1]	is visible (default 1)
+		-e [0|1]	is editable (default 1)
+		-d [0|1]	use direction arrow (default 0)
+		-col int	24bit integer with the color code (default black)
+*/
+
+class RoiStorage : public CComponentAdapter
+{
+public:
+	static const char * getTypeName() { return "roi_storage"; }
+	virtual const char * GetTypeName() const { return RoiStorage::getTypeName(); }
+
+	RoiStorage(const char * name, int argc, const char * argv[])
+	: CComponentAdapter(name, argc, argv)
+	{
+		m_oPinResult= CTypeROI::CreateOutputPin("roi");
+		if (m_oPinResult.get()== NULL)
+			// Output pin creation failed. Shouldn't happen but...
+			throw std::runtime_error("roi_storage. output pin creation failed.");
+		RegisterOutputPin (*m_oPinResult);		
+		RegisterInputPin (*SmartPtr<InputPinROI>(new InputPinROI(*this), false));
+		RegisterInputPin (*SmartPtr<InputPinROISameID>(new InputPinROISameID(*this), false));
+		RegisterInputPin (*SmartPtr<InputPinCentre>(new InputPinCentre(*this), false));
+		RegisterInputPin (*SmartPtr<InputPinVisible>(new InputPinVisible(*this), false));
+
+		m_ROI= CTypeROI::CreateInstance();
+		if (m_ROI.get()== NULL)
+			throw std::runtime_error("roi_storage. cannot create internal instance.");
+
+		
+		// We create an ID from the pointer, just to obtain a unique value
+		m_Id= (unsigned int) ((unsigned long) m_ROI.get());
+		m_ROI->SetRegistrationId (m_Id);
+
+		// parse command line
+		if (!m_ROI->ParseCommandline (argc, argv))
+			throw std::runtime_error("error parsing options");
+	}
+
+	virtual int DoInitialize() {
+		return m_oPinResult->Send (m_ROI);
+	}
+
+private:
+	// TODO: take into account concurrency
+	SmartPtr<CTypeROI> m_ROI;
+	SmartPtr<spcore::IOutputPin> m_oPinResult;
+	unsigned int m_Id;
+
+	// Read/Write pin to send/read the ROI
+	class InputPinROI : public CInputPinReadWrite<CTypeROI, RoiStorage> {
+	public:
+		InputPinROI (RoiStorage & component) : CInputPinReadWrite<CTypeROI, RoiStorage>("roi", component) {}
+		virtual SmartPtr<CTypeROI> DoRead() const {
+			SmartPtr<CTypeROI> result= CTypeROI::CreateInstance();
+			m_component->m_ROI->Clone(NULL, true);
+			return result;
+		}
+		virtual int DoSend(const CTypeROI &src) {
+			src.Clone(m_component->m_ROI.get(), true);
+			// restore ID
+			m_component->m_ROI->SetRegistrationId (m_component->m_Id);
+			return m_component->m_oPinResult->Send (m_component->m_ROI);
+		}
+	};
+
+	// Write pin to send ROIs. Only these with the same ID are taken into account
+	class InputPinROISameID : public CInputPinWriteOnly<CTypeROI, RoiStorage> {
+	public:
+		InputPinROISameID (RoiStorage & component) : CInputPinWriteOnly<CTypeROI, RoiStorage>("roi_same_id", component) {}		
+		virtual int DoSend(const CTypeROI &src) {
+			if (m_component->m_Id== src.GetRegistrationId()) {
+				src.Clone(m_component->m_ROI.get(), true);
+				return m_component->m_oPinResult->Send (m_component->m_ROI);
+			}
+			return 0;
+		}
+	};
+
+	// Allows to centre the ROI around a given point. Expects a composite type with 2 normalized float values (x,y)
+	class InputPinCentre : public CInputPinWriteOnly<CTypeAny, RoiStorage> {
+	public:
+		InputPinCentre (RoiStorage & component) : CInputPinWriteOnly<CTypeAny, RoiStorage>("centre", component) {}
+		virtual int DoSend(const CTypeAny &centre) {
+			SmartPtr<IIterator<CTypeAny *> > it= centre.QueryChildren();
+
+			SmartPtr<CTypeFloat> x=
+				spcore::sptype_dynamic_cast<spcore::CTypeFloat>(SmartPtr<CTypeAny>(it->CurrentItem()));
+			if (!x.get()) goto malformed_msg;
+			it->Next();
+			if (it->IsDone()) goto malformed_msg;
+
+			{
+				SmartPtr<CTypeFloat> y=
+					spcore::sptype_dynamic_cast<spcore::CTypeFloat>(SmartPtr<CTypeAny>(it->CurrentItem()));
+				if (!y.get()) goto malformed_msg;
+
+				// Sanity check
+				if (x->getValue()< 0.0f || x->getValue()> 1.0f ||
+					y->getValue()< 0.0f || y->getValue()> 1.0f) goto wrong_values;
+
+				m_component->m_ROI->SetCenter(x->getValue(), y->getValue());
+			}
+			return m_component->m_oPinResult->Send (m_component->m_ROI);
+		malformed_msg:
+			spcore::getSpCoreRuntime()->LogMessage
+					(spcore::ICoreRuntime::LOG_WARNING, "setting ROI centre. request ignored. invalid message", "mod_camera");
+			return -1;
+		wrong_values:
+			spcore::getSpCoreRuntime()->LogMessage
+					(spcore::ICoreRuntime::LOG_WARNING, "setting ROI centre. request ignored. invalid value", "mod_camera");
+			return -1;
+		}
+	};
+
+	// Write pin to hide/show the roi
+	class InputPinVisible : public CInputPinWriteOnly<CTypeBool, RoiStorage> {
+	public:
+		InputPinVisible (RoiStorage & component) : CInputPinWriteOnly<CTypeBool, RoiStorage>("visible", component) {}		
+		virtual int DoSend(const CTypeBool &val) {
+			m_component->m_ROI->SetIsVisible(val.getValue());
+			return m_component->m_oPinResult->Send (m_component->m_ROI);
+		}
+	};
+};
+
+// camera_viewer component factory
+typedef ComponentFactory<RoiStorage> RoiStorageFactory;
+
+
+/* ******************************************************************************
+	TODO: roi_decomposer (can be generalized for composite types)
+
+	Inputs:
+	- "roi", CTypeROI
+
+	Outputs:
+	- "parent", CTypeROI
+	- "1st_son", CTypeROI
+	- "right_brother", CTypeROI
+****************************************************************************** */
+
+/* ******************************************************************************
+	TODO: roi_composer (can be generalized for composite types)
+
+	Inputs:
+	- "parent", CTypeROI -> stores parent internally
+	- "child", CTypeROI  -> adds son and sends result
+
+	Outputs:
+	- "roi", CTypeROI
+****************************************************************************** */
+
+
+
+/* ******************************************************************************
+	Type CTypeIplImage factory class
+*/
+typedef spcore::SimpleTypeFactory<CTypeIplImage> CTypeIplImageFactory;
+
+/* ******************************************************************************
+	Type CTypeROI factory class
+*/
+typedef spcore::SimpleTypeFactory<CTypeROI> CTypeROIFactory;
+
+
+/* ******************************************************************************
+	sdl_base module
+*/
+class CCameraModule : public spcore::CModuleAdapter {
+public:
+	CCameraModule() {
+		RegisterTypeFactory(SmartPtr<spcore::ITypeFactory>(new CTypeIplImageFactory(), false));
+		RegisterTypeFactory(SmartPtr<spcore::ITypeFactory>(new CTypeROIFactory(), false));
+		RegisterComponentFactory(SmartPtr<spcore::IComponentFactory>(new CameraConfigFactory(), false));
+		RegisterComponentFactory(SmartPtr<spcore::IComponentFactory>(new CameraGrabberFactory(), false));
+		RegisterComponentFactory(SmartPtr<spcore::IComponentFactory>(new CameraViewerFactory(), false));
+		RegisterComponentFactory(SmartPtr<spcore::IComponentFactory>(new RoiStorageFactory(), false));
+	}
+	virtual const char * GetName() const { return "mod_camera"; }
+};
+
+static spcore::IModule* g_module= NULL;
+SPEXPORT_FUNCTION spcore::IModule* module_create_instance()
+{
+	if (g_module== NULL) g_module= new CCameraModule();
+	return g_module;
+}
+
+};
diff --git a/src/mod_camera/mod_camera.h b/src/mod_camera/mod_camera.h
new file mode 100644
index 0000000..e3a5eec
--- /dev/null
+++ b/src/mod_camera/mod_camera.h
@@ -0,0 +1,562 @@
+/////////////////////////////////////////////////////////////////////////////
+// File:        mod_camera.h
+// Author:      Cesar Mauri Loba (cesar at crea-si dot com)
+// Copyright:   (C) 2011 Cesar Mauri Loba - CREA Software Systems
+//
+//  This program is free software: you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation, either version 3 of the License, or
+//  (at your option) any later version.
+//
+//  This program is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+/////////////////////////////////////////////////////////////////////////////
+#ifndef MOD_CAMERA_H
+#define MOD_CAMERA_H
+
+#include "mod_camera/iplimagetype.h"
+#include "spcore/component.h"
+#include "creavision/crvimage.h"
+#include "creavision/crvcamera.h"
+#include "creavision/crvcamera_enum.h"
+
+#include <string>
+#include <boost/thread/thread.hpp>
+#include <boost/thread/xtime.hpp>
+#include <boost/thread/mutex.hpp>
+#include <boost/thread/condition_variable.hpp>
+
+namespace mod_camera {
+
+/*
+	camera_capture thread
+*/
+
+// camera capture listener
+class CameraCaptureListener
+{
+public:
+	virtual void CameraCaptureCallback (SmartPtr<const CTypeIplImage>)= 0;
+};
+
+// camera capture thread
+class CameraCaptureThread
+{
+private:
+	std::vector<CameraCaptureListener*> m_listeners;
+	bool volatile m_Life;
+	CCamera* volatile m_pCamera;
+
+	bool volatile m_pause;
+	boost::mutex m_pause_mutex;
+	boost::condition_variable m_pause_changed;
+
+	bool volatile m_pause2;
+	boost::mutex m_pause_mutex2;
+	boost::condition_variable m_pause_changed2;
+
+public:
+	CameraCaptureThread ()
+	: m_Life(true)
+	, m_pCamera(NULL)
+	, m_pause(true)
+	, m_pause2(true)
+	{
+	}
+
+	~CameraCaptureThread () {
+		Finish();
+	}
+
+	void Finish() {
+		if (m_Life) {
+			assert (!m_pCamera);
+			m_Life= false;
+			Pause(false);
+		}
+	}
+
+	void Pause(bool pause) {
+		{
+			boost::unique_lock<boost::mutex> lock(m_pause_mutex);
+			if (m_pause== pause) return;	// No change
+			m_pause = pause;
+		}
+		if (!pause) {
+			assert (m_pause2);
+			m_pause2= false;
+			m_pause_changed.notify_one();	// Remove pause
+		}
+		else {
+			// Wait until is actually paused
+			boost::unique_lock<boost::mutex> lock(m_pause_mutex2);
+			while (!m_pause2) {
+				m_pause_changed2.wait(lock);
+			}
+		}
+	}
+
+	bool IsPaused() { return m_pause; }
+
+private:
+	void BlockWhilePaused () {
+		boost::unique_lock<boost::mutex> lock(m_pause_mutex);
+		while(m_pause) {
+			{
+				boost::unique_lock<boost::mutex> lock(m_pause_mutex2);
+				m_pause2= true;
+			}			
+			m_pause_changed2.notify_one();
+			m_pause_changed.wait(lock);			
+		}
+	}
+
+public:
+	bool HasListeners() { return (m_listeners.size()> 0); }
+
+	// Changes the camera
+	void SetCamera (CCamera* new_cam) {
+		assert (m_pause && m_pause2);
+		if (new_cam== m_pCamera) return;
+		m_pCamera= new_cam;
+	}
+
+	void RegisterListener (CameraCaptureListener& ccl) {
+		assert (m_pause && m_pause2);
+
+		// If listener not already registered add to the vector
+		std::vector<CameraCaptureListener*>::iterator it=
+			find(m_listeners.begin(), m_listeners.end(), &ccl);
+
+		if (it== m_listeners.end())	m_listeners.push_back (&ccl);
+	}
+
+	void UnregisterListener (CameraCaptureListener& ccl) {
+		assert (m_pause && m_pause2);
+
+		std::vector<CameraCaptureListener*>::iterator it=
+			find(m_listeners.begin(), m_listeners.end(), &ccl);
+
+		if (it!= m_listeners.end())	m_listeners.erase (it);
+	}
+
+	// Thread entry point
+	void Entry() {
+		CIplImage image;
+
+		// Start thread main loop
+		for (;;) {
+			BlockWhilePaused ();
+			if (!m_Life) break;
+			
+			CCamera* camera= m_pCamera;
+			if (!camera) {
+				// No camera. should never happen.				
+				assert(false);
+				sleep_miliseconds( 200 );
+				continue;
+			}
+
+			// Note that memory is automatically allocated
+			// TODO: provide a smarter allocator to avoid continuous new's/delete's
+			if (!camera->QueryFrame(image)) {
+				// YUPS! error grabbing
+				spcore::getSpCoreRuntime()->LogMessage (spcore::ICoreRuntime::LOG_ERROR, "error grabbing from camera.", "mod_camera");
+				// Wait some amount of time... just in case
+				sleep_miliseconds( 30 );
+				continue;
+			}
+
+			SmartPtr<CTypeIplImage> spImage(CTypeIplImage::CreateInstance());
+			spImage->setImage (image.Detach());
+
+			// Call listeners
+			std::vector<CameraCaptureListener*>::iterator it= m_listeners.begin();
+			for(; it!= m_listeners.end(); ++it) (*it)->CameraCaptureCallback(spImage);
+		}
+	}
+
+private:
+
+	static void sleep_miliseconds( unsigned int ms )
+	{
+		boost::xtime xt;
+		boost::xtime_get(&xt, boost::TIME_UTC);
+		xt.nsec+= ms * 1000000;
+		boost::thread::sleep(xt);
+	}
+};
+
+
+/*
+	camera_config component
+
+	This is a singleton class that manages the camera configuration
+	providing a dialog
+*/
+
+
+class CameraConfig : public spcore::CComponentAdapter {
+private:
+	unsigned int m_width, m_height;
+	unsigned int m_fps;
+	int m_selectedCamera;
+	CCamera* m_pCamera;
+	bool m_mirrorImage;
+	CameraCaptureThread m_worker;
+	boost::thread m_thread;
+
+public:
+	static const char* getTypeName() { return "camera_config"; };
+	virtual const char* GetTypeName() const { return CameraConfig::getTypeName(); };
+
+	CameraConfig(const char * name, int argc, const char * argv[])
+	: CComponentAdapter(name, argc, argv)
+	, m_width (320)
+	, m_height (240)
+	, m_fps(30)
+	, m_selectedCamera(-1)
+	, m_pCamera(NULL)
+	, m_mirrorImage(true)
+	, m_worker()
+	, m_thread(&CameraCaptureThread::Entry, &m_worker)
+	{
+		assert (m_thread.joinable());
+		RegisterInputPin (*SmartPtr<InputPinCameras>(new InputPinCameras(*this), false));
+		RegisterInputPin (*SmartPtr<InputPinSelectedCamera>(new InputPinSelectedCamera(*this), false));
+		RegisterInputPin (*SmartPtr<InputPinCaptureParameters>(new InputPinCaptureParameters(*this), false));
+		RegisterInputPin (*SmartPtr<InputPinMirrorImage>(new InputPinMirrorImage(*this), false));
+		RegisterInputPin (*SmartPtr<InputPinSettingDialog>(new InputPinSettingDialog(*this), false));
+
+		// Set cam 0 as default (if exists)
+		SetDesiredCam(0);
+	}
+
+private:
+	~CameraConfig() {
+		m_worker.Pause(true);
+		m_worker.SetCamera(NULL);
+		delete m_pCamera;		
+		
+		m_worker.Finish();
+		m_thread.join();
+	}
+
+	int StartStopCameraWhenNeeded() {
+
+		assert (m_worker.IsPaused());
+
+		if (m_selectedCamera< 0) {
+			// No camera currently selected, give out
+			spcore::getSpCoreRuntime()->LogMessage (spcore::ICoreRuntime::LOG_ERROR,
+				"No active camera available", "mod_camera");
+			return -1;
+		}
+
+		// Is camera object created?
+		if (!m_pCamera) {
+			m_pCamera= CCameraEnum::GetCamera(m_selectedCamera, m_width, m_height, static_cast<float>(m_fps));
+			if (!m_pCamera) {
+				m_selectedCamera= 1;
+
+				spcore::getSpCoreRuntime()->LogMessage (
+					spcore::ICoreRuntime::LOG_ERROR, 
+					"Cannot create camera.", "mod_camera");
+
+				return -1;
+			}
+			m_pCamera->SetHorizontalFlip(m_mirrorImage);
+			m_worker.SetCamera(m_pCamera);
+		}
+
+		
+		if (m_worker.HasListeners()) {
+			// Need to be started
+			if (!m_pCamera->Open()) {
+				// Cannot open camera
+				delete m_pCamera;
+				m_pCamera= NULL;
+				m_selectedCamera= -1;
+				spcore::getSpCoreRuntime()->LogMessage (
+					spcore::ICoreRuntime::LOG_ERROR, 
+					"Cannot open camera", "mod_camera");
+				return -1;
+			}
+
+			// Camera successfully opened
+			m_worker.Pause(false);
+		}
+		else {
+			// Need to be stopped (already paused thread)
+			m_pCamera->Close();
+		}
+
+		return 0;
+	}
+
+	int SetDesiredCam(int camNum) {
+		if (camNum== m_selectedCamera) return 0;
+		if (camNum< 0 || camNum>= CCameraEnum::GetNumDevices()) {
+			spcore::getSpCoreRuntime()->LogMessage (
+				spcore::ICoreRuntime::LOG_WARNING, 
+				"Invalid camera number", "mod_camera");
+			return -1;
+		}
+
+		// Try to create new camera
+		CCamera* cam= CCameraEnum::GetCamera(camNum, m_width, m_height, static_cast<float>(m_fps));
+		if (!cam) {
+			spcore::getSpCoreRuntime()->LogMessage (
+				spcore::ICoreRuntime::LOG_ERROR, 
+				"Cannot create camera", "mod_camera");
+			return -1;
+		}
+		cam->SetHorizontalFlip(m_mirrorImage);
+
+		// OK. New camera created. Set as available camera.
+		m_worker.Pause(true);
+		delete m_pCamera;
+		m_pCamera= cam;
+		m_selectedCamera= camNum;
+		m_worker.SetCamera(cam);
+		
+		return StartStopCameraWhenNeeded();
+	}
+
+	int SetCameraParameters (unsigned int width, unsigned int height, unsigned int fps, bool mirrorImage)
+	{
+		if (m_selectedCamera< 0) {
+			// No camera currently selected, give out
+			spcore::getSpCoreRuntime()->LogMessage (spcore::ICoreRuntime::LOG_ERROR,
+				"No active camera available", "mod_camera");
+			return -1;
+		}
+
+		assert (m_pCamera);
+
+		if (width== m_width && height== m_height && fps== m_fps) {
+			// only requested mirrorImage change (or nothing). do it and that's all.
+			m_pCamera->SetHorizontalFlip (mirrorImage);
+			m_mirrorImage= mirrorImage;
+			return 0;
+		}
+
+		// Sanity checks
+		if (width< 160 || width> 1280 || height< 120 || height> 720 || fps< 1 || fps> 30) {
+			spcore::getSpCoreRuntime()->LogMessage (spcore::ICoreRuntime::LOG_WARNING,
+				"Setting capture parameters, request ignored, invalid values", "mod_camera");
+			return -1;
+		}
+
+		// Destroy current camera
+		m_worker.Pause(true);
+		m_pCamera->Close();
+		delete m_pCamera;
+		m_pCamera= NULL;
+
+		// Keep old settings
+		int oldSelectedCamera= m_selectedCamera;
+		unsigned int oldWidth= m_width, oldHeight= m_height, oldFps= m_fps;
+		bool oldMirrorImage= m_mirrorImage;
+
+		// Set new settings			
+		m_width= width;
+		m_height= height;
+		m_fps= fps;
+		m_mirrorImage= mirrorImage;
+
+		// Try to create & start the camera with the new configuration
+		if (!StartStopCameraWhenNeeded()) return 0;
+
+		// Didn't work. Restore previous settings and cross fingers...
+		delete m_pCamera;
+		m_pCamera= NULL;
+
+		m_selectedCamera= oldSelectedCamera;
+		m_width= oldWidth;
+		m_height= oldHeight;
+		m_fps= oldFps;
+		m_mirrorImage= oldMirrorImage;
+
+		return StartStopCameraWhenNeeded();
+	}
+
+public:
+	void RegisterListener (CameraCaptureListener& ccl) {
+		// TODO: insead of assert's way to signal globally that graph construction must be made within the main thread
+		assert (spcore::getSpCoreRuntime()->IsMainThread());
+
+		m_worker.Pause(true);
+		m_worker.RegisterListener(ccl);
+		StartStopCameraWhenNeeded();
+	}
+
+	void UnregisterListener (CameraCaptureListener& ccl) {
+		assert (spcore::getSpCoreRuntime()->IsMainThread());
+
+		m_worker.Pause(true);
+		m_worker.UnregisterListener(ccl);
+		StartStopCameraWhenNeeded();
+	}
+
+	virtual wxWindow* GetGUI(wxWindow * parent);
+
+private:
+
+	#define SELECTED_CAMERA_SETTING_NAME "selected_camera"
+	#define WIDTH_SETTING_NAME "width"
+	#define HEIGHT_SETTING_NAME "height"
+	#define FPS_SETTING_NAME "fps"
+	#define MIRROR_SETTING_NAME "mirror"
+
+	virtual void SaveSettings(spcore::IConfiguration& cfg) {
+		cfg.WriteInt(SELECTED_CAMERA_SETTING_NAME, m_selectedCamera);
+		cfg.WriteInt(WIDTH_SETTING_NAME, m_width);
+		cfg.WriteInt(HEIGHT_SETTING_NAME, m_height);
+		cfg.WriteInt(FPS_SETTING_NAME, (int) m_fps);
+		cfg.WriteBool(MIRROR_SETTING_NAME, m_mirrorImage);
+	}
+
+	virtual void LoadSettings(spcore::IConfiguration& cfg) {
+		int selectedCamera;
+		if (cfg.ReadInt(SELECTED_CAMERA_SETTING_NAME, &selectedCamera))
+			SetDesiredCam(selectedCamera);
+
+		int width, height, fps;
+		bool mirror;
+
+		if (!cfg.ReadInt(WIDTH_SETTING_NAME, &width)) return;
+		if (!cfg.ReadInt(HEIGHT_SETTING_NAME, &height)) return;
+		if (!cfg.ReadInt(FPS_SETTING_NAME, &fps)) return;
+		if (!cfg.ReadBool(MIRROR_SETTING_NAME, &mirror)) return;
+		SetCameraParameters ((unsigned int) width, (unsigned int) height, (unsigned int) fps, mirror);
+	}
+
+	void OpenCameraSettings ()
+	{
+		if (m_selectedCamera< 0) {
+			// No camera currently selected, give out
+			spcore::getSpCoreRuntime()->LogMessage (spcore::ICoreRuntime::LOG_ERROR,
+				"no active camera available", "mod_camera");
+			return;
+		}
+
+		assert (m_pCamera);
+
+		if (!m_pCamera->HasSettingsDialog())
+			spcore::getSpCoreRuntime()->LogMessage (spcore::ICoreRuntime::LOG_ERROR,
+				"no settings dialog available", "mod_camera");
+		else
+			m_pCamera->ShowSettingsDialog();
+	}
+
+	
+
+	// Read-only input pin to request available cameras
+	class InputPinCameras : public spcore::CInputPinReadOnly<spcore::CTypeComposite, CameraConfig> {
+	public:
+		InputPinCameras (CameraConfig & component) : spcore::CInputPinReadOnly<spcore::CTypeComposite, CameraConfig>("cameras", component) {}
+		virtual SmartPtr<spcore::CTypeComposite> DoRead() const {
+			SmartPtr<spcore::CTypeComposite> retval= spcore::CTypeComposite::CreateInstance();
+
+			int ndev= CCameraEnum::GetNumDevices();
+			if (ndev< 1) {
+				spcore::getSpCoreRuntime()->LogMessage (spcore::ICoreRuntime::LOG_WARNING, "not detected any camera", "mod_camera");
+			}
+			else {
+				for (int i= 0; i< ndev; ++i) {
+					SmartPtr<spcore::CTypeString> camname(spcore::CTypeString::CreateInstance());
+					camname->setValue(CCameraEnum::GetDeviceName(i));
+					retval->AddChild (camname);
+				}
+			}
+			return retval;
+		}
+	};
+
+
+	class InputPinSelectedCamera : public spcore::CInputPinReadWrite<spcore::CTypeInt, CameraConfig> {
+	public:
+		InputPinSelectedCamera (CameraConfig & component) : spcore::CInputPinReadWrite<spcore::CTypeInt, CameraConfig>("selected_camera", component) {}
+		virtual int DoSend(const spcore::CTypeInt & message) {
+			return m_component->SetDesiredCam(message.getValue());
+		}
+		virtual SmartPtr<spcore::CTypeInt> DoRead() const {
+			SmartPtr<spcore::CTypeInt> retval= spcore::CTypeInt::CreateInstance();
+			retval->setValue(m_component->m_selectedCamera);
+			return retval;
+		}
+	};
+
+	// The message is a composite with three values: width, height and fps
+	class InputPinCaptureParameters : public spcore::CInputPinReadWrite<spcore::CTypeComposite, CameraConfig> {
+	public:
+		InputPinCaptureParameters (CameraConfig & component) : spcore::CInputPinReadWrite<spcore::CTypeComposite, CameraConfig>("capture_parameters", component) {}
+		virtual int DoSend(const spcore::CTypeComposite & message) {
+			const SmartPtr<spcore::IIterator<spcore::CTypeAny*> > it= message.QueryChildren();
+
+			int width= -1, height= -1, fps= -1;
+			for (int i= 0; !it->IsDone() && i< 3; it->Next(), ++i) {
+				SmartPtr<spcore::CTypeInt> val= spcore::sptype_dynamic_cast<spcore::CTypeInt>(SmartPtr<spcore::CTypeAny>(it->CurrentItem()));
+				if (!val.get()) {
+					spcore::getSpCoreRuntime()->LogMessage (spcore::ICoreRuntime::LOG_WARNING, "setting capture parameters, request ignored, invalid message", "mod_camera");
+					return -1;
+				}
+
+				switch(i) {
+				case 0: width= val->getValue(); break;
+				case 1: height= val->getValue(); break;
+				case 2: fps= val->getValue(); break;
+				default: assert (false);
+				}
+			}
+
+			return m_component->SetCameraParameters (width, height, fps, m_component->m_mirrorImage);
+		}
+		virtual SmartPtr<spcore::CTypeComposite> DoRead() const {
+			SmartPtr<spcore::CTypeComposite> retval= spcore::CTypeComposite::CreateInstance();
+			SmartPtr<spcore::CTypeInt> width= spcore::CTypeInt::CreateInstance();
+			SmartPtr<spcore::CTypeInt> height= spcore::CTypeInt::CreateInstance();
+			SmartPtr<spcore::CTypeInt> fps= spcore::CTypeInt::CreateInstance();
+			width->setValue(m_component->m_width);
+			height->setValue(m_component->m_height);
+			fps->setValue(m_component->m_fps);
+			retval->AddChild (width);
+			retval->AddChild (height);
+			retval->AddChild (fps);
+			return retval;
+		}
+	};
+
+	class InputPinMirrorImage : public spcore::CInputPinReadWrite<spcore::CTypeBool, CameraConfig> {
+	public:
+		InputPinMirrorImage (CameraConfig & component) : spcore::CInputPinReadWrite<spcore::CTypeBool, CameraConfig>("mirror_image", component) {}
+		virtual int DoSend(const spcore::CTypeBool & message) {
+			return m_component->SetCameraParameters (m_component->m_width, m_component->m_height, m_component->m_fps, message.getValue());
+		}
+		virtual SmartPtr<spcore::CTypeBool> DoRead() const {
+			SmartPtr<spcore::CTypeBool> retval= spcore::CTypeBool::CreateInstance();
+			retval->setValue(m_component->m_mirrorImage);
+			return retval;
+		}
+	};
+
+	// Write-only to open camera settings dialog (if available)
+	class InputPinSettingDialog : public spcore::CInputPinWriteOnly<spcore::CTypeAny, CameraConfig> {
+	public:
+		InputPinSettingDialog (CameraConfig & component) : spcore::CInputPinWriteOnly<spcore::CTypeAny, CameraConfig>("settings_dialog", component) {}
+		virtual int DoSend(const spcore::CTypeAny &) {
+			m_component->OpenCameraSettings ();
+			return 0;
+		}
+	};
+};
+
+};
+
+#endif
diff --git a/src/mod_camera/mod_camera.pjd b/src/mod_camera/mod_camera.pjd
new file mode 100644
index 0000000..4eff004
--- /dev/null
+++ b/src/mod_camera/mod_camera.pjd
@@ -0,0 +1,1238 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<anthemion-project version="1.0.0.0" xmlns="http://www.anthemion.co.uk">
+  <header>
+    <long name="name_counter">0</long>
+    <string name="html_path">""</string>
+    <string name="title">""</string>
+    <string name="author">""</string>
+    <string name="description">""</string>
+    <string name="xrc_filename">""</string>
+    <long name="image_mode">0</long>
+    <bool name="inline_images">0</bool>
+    <bool name="generate_cpp_for_xrc">0</bool>
+    <long name="working_mode">1</long>
+    <bool name="use_help_text_for_tooltips">1</bool>
+    <bool name="translate_strings">1</bool>
+    <bool name="make_unicode_strings">1</bool>
+    <bool name="extract_strings">0</bool>
+    <string name="user_name">"César Mauri Loba"</string>
+    <string name="copyright_string">"(C) 2009 Cesar Mauri from CREA Sistemes Informatics"</string>
+    <string name="resource_prefix">""</string>
+    <bool name="use_two_step_construction">1</bool>
+    <bool name="use_enums">0</bool>
+    <bool name="generate_for_xrced">0</bool>
+    <bool name="generate_virtual_eventhandlers">0</bool>
+    <string name="current_platform">"<All platforms>"</string>
+    <string name="target_wx_version">"2.8.7"</string>
+    <string name="app_kind">"Standard"</string>
+    <string name="cpp_header_comment">"/////////////////////////////////////////////////////////////////////////////
+// Name:        %HEADER-FILENAME%
+// Purpose:     
+// Author:      %AUTHOR%
+// Modified by: 
+// Created:     %DATE%
+// RCS-ID:      
+// Copyright:   %COPYRIGHT%
+// Licence:     
+/////////////////////////////////////////////////////////////////////////////
+
+"</string>
+    <string name="cpp_implementation_comment">"/////////////////////////////////////////////////////////////////////////////
+// Name:        %SOURCE-FILENAME%
+// Purpose:     
+// Author:      %AUTHOR%
+// Modified by: 
+// Created:     %DATE%
+// RCS-ID:      
+// Copyright:   %COPYRIGHT%
+// Licence:     
+/////////////////////////////////////////////////////////////////////////////
+
+"</string>
+    <string name="cpp_symbols_file_comment">"/////////////////////////////////////////////////////////////////////////////
+// Name:        %SYMBOLS-FILENAME%
+// Purpose:     Symbols file
+// Author:      %AUTHOR%
+// Modified by: 
+// Created:     %DATE%
+// RCS-ID:      
+// Copyright:   %COPYRIGHT%
+// Licence:     
+/////////////////////////////////////////////////////////////////////////////
+
+"</string>
+    <string name="cpp_header_preamble">""</string>
+    <string name="cpp_implementation_preamble">"// For compilers that support precompilation, includes "wx/wx.h".
+#include "wx/wxprec.h"
+
+#ifdef __BORLANDC__
+#pragma hdrstop
+#endif
+
+#ifndef WX_PRECOMP
+#include "wx/wx.h"
+#endif
+
+"</string>
+    <string name="cpp_function_declaration_comment">"	/// %BODY%
+"</string>
+    <string name="cpp_function_implementation_comment">"
+/*!
+ * %BODY%
+ */
+
+"</string>
+    <string name="resource_file_header">"app_resources.h"</string>
+    <string name="resource_file_implementation">"app_resources.cpp"</string>
+    <string name="resource_class_name">"AppResources"</string>
+    <string name="app_file_header">"app.h"</string>
+    <string name="app_file_implementation">"app.cpp"</string>
+    <string name="app_class_name">"Application"</string>
+    <bool name="generate_app_class">0</bool>
+    <string name="external_symbol_filenames">""</string>
+    <string name="configuration">"<None>"</string>
+    <string name="source_encoding">"iso-8859-1"</string>
+    <string name="xrc_encoding">"utf-8"</string>
+    <string name="project_encoding">"utf-8"</string>
+    <string name="resource_archive">""</string>
+    <long name="text_file_type">0</long>
+    <bool name="use_tabs">0</bool>
+    <long name="indent_size">4</long>
+    <string name="whitespace_after_return_type">" "</string>
+    <string name="resource_xrc_cpp">""</string>
+    <bool name="use_resource_archive">0</bool>
+    <bool name="use_generated_xrc_cpp">0</bool>
+    <bool name="always_generate_xrc">1</bool>
+    <bool name="use_id_name_for_name">0</bool>
+    <bool name="archive_xrc_files">1</bool>
+    <bool name="archive_image_files">1</bool>
+    <bool name="archive_all_image_files">0</bool>
+    <bool name="xrc_retain_relative_paths">1</bool>
+    <bool name="xrc_generate_id_tags">0</bool>
+    <bool name="xrc_use_name_property">0</bool>
+  </header>
+  <data>
+    <document>
+      <string name="title">""</string>
+      <string name="type">"data-document"</string>
+      <string name="filename">""</string>
+      <string name="icon-name">""</string>
+      <long name="is-transient">0</long>
+      <long name="owns-file">1</long>
+      <long name="title-mode">0</long>
+      <long name="locked">0</long>
+      <document>
+        <string name="title">"Configurations"</string>
+        <string name="type">"config-data-document"</string>
+        <string name="filename">""</string>
+        <string name="icon-name">""</string>
+        <long name="is-transient">0</long>
+        <long name="owns-file">1</long>
+        <long name="title-mode">0</long>
+        <long name="locked">0</long>
+        <string name="template-name">""</string>
+        <bool name="dirty">1</bool>
+        <long name="makefile-last-written">-8519680</long>
+        <string name="Compiler name">""</string>
+        <string name="Build mode">"Debug"</string>
+        <string name="Unicode mode">"ANSI"</string>
+        <string name="Shared mode">"Static"</string>
+        <string name="Modularity">"Modular"</string>
+        <string name="GUI mode">"GUI"</string>
+        <string name="Toolkit">"wxMSW"</string>
+        <string name="Processor type">"Default"</string>
+        <string name="Runtime linking">"Dynamic"</string>
+        <string name="Use exceptions">"Yes"</string>
+        <string name="Use ODBC">"No"</string>
+        <string name="Use XRC">"Yes"</string>
+        <string name="Use OpenGL">"No"</string>
+        <string name="Use wxMediaCtrl">"No"</string>
+        <string name="Use wxRichTextCtrl">"Yes"</string>
+        <string name="Use wxHTML">"Yes"</string>
+        <string name="Use wxPropertyGrid">"Yes"</string>
+        <string name="Use wxAUI">"Yes"</string>
+        <string name="Use wxSTC">"Yes"</string>
+        <string name="Use wxRegEx">"builtin"</string>
+        <string name="Use wxRibbonControl">"Yes"</string>
+        <string name="Executable name">"%EXECUTABLE%"</string>
+        <string name="Program arguments">""</string>
+        <string name="Working path">"%AUTO%"</string>
+        <string name="Output path">"%AUTO%"</string>
+        <string name="Objects path">"%AUTO%"</string>
+        <string name="Project makefile">"%AUTO%"</string>
+        <string name="wxWidgets version">"%WXVERSION%"</string>
+        <string name="wxWidgets makefile">"%AUTO%"</string>
+        <string name="wxWidgets location">"%AUTO%"</string>
+        <string name="wxWidgets build path">"%AUTO%"</string>
+        <string name="wxWidgets build command">"%AUTO%"</string>
+        <string name="wxWidgets clean command">"%AUTO%"</string>
+        <string name="CFG">""</string>
+        <string name="Compiler location">"%AUTO%"</string>
+        <string name="Compiler bin path">"%AUTO%"</string>
+        <string name="Compiler include path">"%AUTO%"</string>
+        <string name="Compiler lib path">"%AUTO%"</string>
+        <string name="PATH variable">"%AUTO%"</string>
+        <string name="C++ command">"%AUTO%"</string>
+        <string name="C command">"%AUTO%"</string>
+        <string name="Linker command">"%AUTO%"</string>
+        <string name="Resource compiler">"%AUTO%"</string>
+        <string name="Make command">"%AUTO%"</string>
+        <string name="Preprocessor flags">"%AUTO%"</string>
+        <string name="Optimizations">"%AUTO%"</string>
+        <string name="Warnings">"%AUTO%"</string>
+        <string name="Debug flags">"%AUTO%"</string>
+        <string name="Extra compile flags">"%AUTO%"</string>
+        <string name="Libraries">"%AUTO%"</string>
+        <string name="Library path">"%AUTO%"</string>
+        <string name="Linker flags">"%AUTO%"</string>
+        <string name="Include path">"%AUTO%"</string>
+        <string name="Resource flags">"%AUTO%"</string>
+        <string name="Resource path">"%AUTO%"</string>
+        <string name="Extra dependencies">"%AUTO%"</string>
+        <bool name="Suppress source rules">0</bool>
+        <bool name="Enable makefile generation">1</bool>
+      </document>
+    </document>
+  </data>
+
+  <documents>
+    <document>
+      <string name="title">"Projects"</string>
+      <string name="type">"root-document"</string>
+      <string name="filename">""</string>
+      <string name="icon-name">"project"</string>
+      <long name="is-transient">1</long>
+      <long name="owns-file">1</long>
+      <long name="title-mode">0</long>
+      <long name="locked">1</long>
+      <document>
+        <string name="title">"Windows"</string>
+        <string name="type">"html-document"</string>
+        <string name="filename">""</string>
+        <string name="icon-name">"dialogsfolder"</string>
+        <long name="is-transient">1</long>
+        <long name="owns-file">1</long>
+        <long name="title-mode">0</long>
+        <long name="locked">1</long>
+        <document>
+          <string name="title">"Camera Configuration"</string>
+          <string name="type">"dialog-document"</string>
+          <string name="filename">""</string>
+          <string name="icon-name">"dialog"</string>
+          <long name="is-transient">0</long>
+          <long name="owns-file">1</long>
+          <long name="title-mode">0</long>
+          <long name="locked">0</long>
+          <string name="proxy-type">"wbDialogProxy"</string>
+          <long name="base-id">10000</long>
+          <bool name="use-id-prefix">0</bool>
+          <string name="id-prefix">""</string>
+          <bool name="use-id-suffix">0</bool>
+          <string name="id-suffix">""</string>
+          <string name="app-kind">"Standard"</string>
+          <long name="use-xrc">0</long>
+          <long name="working-mode">0</long>
+          <string name="proxy-Id name">"ID_CCAMERACONFIGURATION"</string>
+          <long name="proxy-Id value">10060</long>
+          <string name="proxy-Class">"CCameraConfiguration"</string>
+          <string name="proxy-Base class">"wxPanel"</string>
+          <string name="proxy-Window kind">"wxPanel"</string>
+          <string name="proxy-Implementation filename">"wcameraconfiguration.cpp"</string>
+          <string name="proxy-Header filename">"wcameraconfiguration.h"</string>
+          <string name="proxy-XRC filename">""</string>
+          <string name="proxy-Title">"Camera Configuration"</string>
+          <bool name="proxy-Centre">1</bool>
+          <string name="proxy-Icon">""</string>
+          <bool name="proxy-Dialog units">0</bool>
+          <string name="proxy-Help text">""</string>
+          <string name="proxy-Tooltip text">""</string>
+          <string name="proxy-Background colour">""</string>
+          <string name="proxy-Foreground colour">""</string>
+          <string name="proxy-Font">""</string>
+          <bool name="proxy-Hidden">0</bool>
+          <bool name="proxy-Enabled">1</bool>
+          <string name="proxy-Platform">"<Any platform>"</string>
+          <string name="proxy-Data source">""</string>
+          <string name="proxy-Data class name">""</string>
+          <string name="proxy-Data class implementation filename">""</string>
+          <string name="proxy-Data class header filename">""</string>
+          <string name="proxy-Data class manager window">""</string>
+          <string name="proxy-Texture">""</string>
+          <string name="proxy-Texture style">"Tiled"</string>
+          <bool name="proxy-wxDEFAULT_DIALOG_STYLE">0</bool>
+          <bool name="proxy-wxCAPTION">1</bool>
+          <bool name="proxy-wxRESIZE_BORDER">0</bool>
+          <bool name="proxy-wxSYSTEM_MENU">0</bool>
+          <bool name="proxy-wxSTAY_ON_TOP">0</bool>
+          <bool name="proxy-wxDIALOG_NO_PARENT">0</bool>
+          <bool name="proxy-wxCLOSE_BOX">0</bool>
+          <bool name="proxy-wxMAXIMIZE_BOX">0</bool>
+          <bool name="proxy-wxMINIMIZE_BOX">0</bool>
+          <bool name="proxy-wxDIALOG_MODAL">1</bool>
+          <bool name="proxy-wxNO_BORDER">0</bool>
+          <bool name="proxy-wxSIMPLE_BORDER">0</bool>
+          <bool name="proxy-wxDOUBLE_BORDER">0</bool>
+          <bool name="proxy-wxBORDER_THEME">0</bool>
+          <bool name="proxy-wxSUNKEN_BORDER">0</bool>
+          <bool name="proxy-wxRAISED_BORDER">0</bool>
+          <bool name="proxy-wxSTATIC_BORDER">0</bool>
+          <bool name="proxy-wxWANTS_CHARS">0</bool>
+          <bool name="proxy-wxNO_FULL_REPAINT_ON_RESIZE">0</bool>
+          <bool name="proxy-wxFULL_REPAINT_ON_RESIZE">0</bool>
+          <bool name="proxy-wxCLIP_CHILDREN">0</bool>
+          <bool name="proxy-wxTAB_TRAVERSAL">1</bool>
+          <bool name="proxy-wxWS_EX_VALIDATE_RECURSIVELY">0</bool>
+          <bool name="proxy-wxWS_EX_BLOCK_EVENTS">1</bool>
+          <bool name="proxy-wxWS_EX_TRANSIENT">0</bool>
+          <string name="proxy-Custom styles">""</string>
+          <bool name="proxy-wxDIALOG_EX_CONTEXTHELP">0</bool>
+          <bool name="proxy-Fit to content">1</bool>
+          <long name="proxy-X">-1</long>
+          <long name="proxy-Y">-1</long>
+          <long name="proxy-Width">-1</long>
+          <long name="proxy-Height">-1</long>
+          <bool name="proxy-AUI manager">0</bool>
+          <string name="proxy-Event sources">""</string>
+          <document>
+            <string name="title">"wxBoxSizer V"</string>
+            <string name="type">"dialog-control-document"</string>
+            <string name="filename">""</string>
+            <string name="icon-name">"sizer"</string>
+            <long name="is-transient">0</long>
+            <long name="owns-file">1</long>
+            <long name="title-mode">0</long>
+            <long name="locked">0</long>
+            <string name="proxy-type">"wbBoxSizerProxy"</string>
+            <string name="proxy-Orientation">"Vertical"</string>
+            <string name="proxy-Member variable name">""</string>
+            <bool name="proxy-wxSHAPED">0</bool>
+            <bool name="proxy-wxADJUST_MINSIZE">0</bool>
+            <bool name="proxy-wxFIXED_MINSIZE">0</bool>
+            <string name="proxy-Platform">"<Any platform>"</string>
+            <document>
+              <string name="title">"wxStaticBoxSizer V"</string>
+              <string name="type">"dialog-control-document"</string>
+              <string name="filename">""</string>
+              <string name="icon-name">"sizer"</string>
+              <long name="is-transient">0</long>
+              <long name="owns-file">1</long>
+              <long name="title-mode">0</long>
+              <long name="locked">0</long>
+              <string name="proxy-type">"wbStaticBoxSizerProxy"</string>
+              <string name="proxy-Id name">"wxID_ANY"</string>
+              <long name="proxy-Id value">-1</long>
+              <string name="proxy-Label">""</string>
+              <string name="proxy-Member variable name">""</string>
+              <string name="proxy-Sizer member variable name">""</string>
+              <string name="proxy-Foreground colour">""</string>
+              <string name="proxy-Font">""</string>
+              <bool name="proxy-Hidden">0</bool>
+              <bool name="proxy-Enabled">1</bool>
+              <string name="proxy-Parenting">"Use wxWidgets version"</string>
+              <string name="proxy-Static box class">"wxStaticBox"</string>
+              <string name="proxy-Orientation">"Vertical"</string>
+              <string name="proxy-AlignH">"Centre"</string>
+              <string name="proxy-AlignV">"Centre"</string>
+              <long name="proxy-Stretch factor">0</long>
+              <long name="proxy-Border">5</long>
+              <bool name="proxy-wxLEFT">1</bool>
+              <bool name="proxy-wxRIGHT">1</bool>
+              <bool name="proxy-wxTOP">1</bool>
+              <bool name="proxy-wxBOTTOM">1</bool>
+              <bool name="proxy-wxSHAPED">0</bool>
+              <bool name="proxy-wxADJUST_MINSIZE">0</bool>
+              <bool name="proxy-wxFIXED_MINSIZE">0</bool>
+              <string name="proxy-Platform">"<Any platform>"</string>
+              <document>
+                <string name="title">"CameraPanel: ID_PANEL_CAMERA"</string>
+                <string name="type">"dialog-control-document"</string>
+                <string name="filename">""</string>
+                <string name="icon-name">"panel"</string>
+                <long name="is-transient">0</long>
+                <long name="owns-file">1</long>
+                <long name="title-mode">0</long>
+                <long name="locked">0</long>
+                <string name="proxy-type">"wbPanelProxy"</string>
+                <string name="proxy-Id name">"ID_PANEL_CAMERA"</string>
+                <long name="proxy-Id value">10061</long>
+                <string name="proxy-Name">""</string>
+                <string name="proxy-Class">"CameraPanel"</string>
+                <string name="proxy-Base class">"wxPanel"</string>
+                <bool name="proxy-External implementation">1</bool>
+                <bool name="proxy-Separate files">0</bool>
+                <string name="proxy-Implementation filename">""</string>
+                <string name="proxy-Header filename">""</string>
+                <string name="proxy-Member variable name">"m_camPanel"</string>
+                <string name="proxy-Help text">""</string>
+                <string name="proxy-Tooltip text">""</string>
+                <string name="proxy-Background colour">""</string>
+                <string name="proxy-Foreground colour">""</string>
+                <string name="proxy-Font">""</string>
+                <bool name="proxy-Hidden">0</bool>
+                <bool name="proxy-Enabled">1</bool>
+                <string name="proxy-Platform">"<Any platform>"</string>
+                <string name="proxy-Data source">""</string>
+                <string name="proxy-Data class name">""</string>
+                <string name="proxy-Data class implementation filename">""</string>
+                <string name="proxy-Data class header filename">""</string>
+                <string name="proxy-Data class manager window">""</string>
+                <string name="proxy-Texture">""</string>
+                <string name="proxy-Texture style">"Tiled"</string>
+                <bool name="proxy-wxNO_BORDER">0</bool>
+                <bool name="proxy-wxSIMPLE_BORDER">0</bool>
+                <bool name="proxy-wxDOUBLE_BORDER">0</bool>
+                <bool name="proxy-wxBORDER_THEME">0</bool>
+                <bool name="proxy-wxSUNKEN_BORDER">1</bool>
+                <bool name="proxy-wxRAISED_BORDER">0</bool>
+                <bool name="proxy-wxSTATIC_BORDER">0</bool>
+                <bool name="proxy-wxWANTS_CHARS">0</bool>
+                <bool name="proxy-wxNO_FULL_REPAINT_ON_RESIZE">0</bool>
+                <bool name="proxy-wxFULL_REPAINT_ON_RESIZE">0</bool>
+                <bool name="proxy-wxCLIP_CHILDREN">0</bool>
+                <bool name="proxy-wxHSCROLL">0</bool>
+                <bool name="proxy-wxVSCROLL">0</bool>
+                <bool name="proxy-wxTAB_TRAVERSAL">1</bool>
+                <bool name="proxy-wxALWAYS_SHOW_SB">0</bool>
+                <bool name="proxy-wxWS_EX_VALIDATE_RECURSIVELY">0</bool>
+                <bool name="proxy-wxWS_EX_BLOCK_EVENTS">0</bool>
+                <string name="proxy-Custom styles">""</string>
+                <bool name="proxy-Fit to content">0</bool>
+                <long name="proxy-X">-1</long>
+                <long name="proxy-Y">-1</long>
+                <long name="proxy-Width">320</long>
+                <long name="proxy-Height">240</long>
+                <string name="proxy-AlignH">"Centre"</string>
+                <string name="proxy-AlignV">"Centre"</string>
+                <long name="proxy-Stretch factor">0</long>
+                <long name="proxy-Border">5</long>
+                <bool name="proxy-wxLEFT">1</bool>
+                <bool name="proxy-wxRIGHT">1</bool>
+                <bool name="proxy-wxTOP">1</bool>
+                <bool name="proxy-wxBOTTOM">1</bool>
+                <bool name="proxy-wxSHAPED">0</bool>
+                <bool name="proxy-wxADJUST_MINSIZE">0</bool>
+                <bool name="proxy-wxFIXED_MINSIZE">0</bool>
+                <string name="proxy-Custom arguments">""</string>
+                <string name="proxy-Custom ctor arguments">""</string>
+                <string name="proxy-Event sources">""</string>
+                <bool name="proxy-AUI manager">0</bool>
+              </document>
+              <document>
+                <string name="title">"wxStaticBoxSizer V"</string>
+                <string name="type">"dialog-control-document"</string>
+                <string name="filename">""</string>
+                <string name="icon-name">"sizer"</string>
+                <long name="is-transient">0</long>
+                <long name="owns-file">1</long>
+                <long name="title-mode">0</long>
+                <long name="locked">0</long>
+                <string name="proxy-type">"wbStaticBoxSizerProxy"</string>
+                <string name="proxy-Id name">"wxID_ANY"</string>
+                <long name="proxy-Id value">-1</long>
+                <string name="proxy-Label">"Camera properties"</string>
+                <string name="proxy-Member variable name">""</string>
+                <string name="proxy-Sizer member variable name">""</string>
+                <string name="proxy-Foreground colour">""</string>
+                <string name="proxy-Font">""</string>
+                <bool name="proxy-Hidden">0</bool>
+                <bool name="proxy-Enabled">1</bool>
+                <string name="proxy-Parenting">"Use wxWidgets version"</string>
+                <string name="proxy-Static box class">"wxStaticBox"</string>
+                <string name="proxy-Orientation">"Vertical"</string>
+                <string name="proxy-AlignH">"Expand"</string>
+                <string name="proxy-AlignV">"Centre"</string>
+                <long name="proxy-Stretch factor">0</long>
+                <long name="proxy-Border">5</long>
+                <bool name="proxy-wxLEFT">1</bool>
+                <bool name="proxy-wxRIGHT">1</bool>
+                <bool name="proxy-wxTOP">1</bool>
+                <bool name="proxy-wxBOTTOM">1</bool>
+                <bool name="proxy-wxSHAPED">0</bool>
+                <bool name="proxy-wxADJUST_MINSIZE">0</bool>
+                <bool name="proxy-wxFIXED_MINSIZE">0</bool>
+                <string name="proxy-Platform">"<Any platform>"</string>
+                <document>
+                  <string name="title">"wxFlexGridSizer"</string>
+                  <string name="type">"dialog-control-document"</string>
+                  <string name="filename">""</string>
+                  <string name="icon-name">"sizer"</string>
+                  <long name="is-transient">0</long>
+                  <long name="owns-file">1</long>
+                  <long name="title-mode">0</long>
+                  <long name="locked">0</long>
+                  <string name="proxy-type">"wbFlexGridSizerProxy"</string>
+                  <string name="proxy-GrowableColumns">"1"</string>
+                  <string name="proxy-GrowableRows">""</string>
+                  <long name="proxy-Columns">2</long>
+                  <long name="proxy-Rows">0</long>
+                  <long name="proxy-ColumnSpacing">0</long>
+                  <long name="proxy-RowSpacing">0</long>
+                  <string name="proxy-Member variable name">""</string>
+                  <string name="proxy-Platform">"<Any platform>"</string>
+                  <string name="proxy-AlignH">"Expand"</string>
+                  <string name="proxy-AlignV">"Centre"</string>
+                  <long name="proxy-Stretch factor">0</long>
+                  <long name="proxy-Border">5</long>
+                  <bool name="proxy-wxLEFT">1</bool>
+                  <bool name="proxy-wxRIGHT">1</bool>
+                  <bool name="proxy-wxTOP">1</bool>
+                  <bool name="proxy-wxBOTTOM">1</bool>
+                  <bool name="proxy-wxSHAPED">0</bool>
+                  <bool name="proxy-wxADJUST_MINSIZE">0</bool>
+                  <bool name="proxy-wxFIXED_MINSIZE">0</bool>
+                  <document>
+                    <string name="title">"wxStaticText: wxID_STATIC"</string>
+                    <string name="type">"dialog-control-document"</string>
+                    <string name="filename">""</string>
+                    <string name="icon-name">"statictext"</string>
+                    <long name="is-transient">0</long>
+                    <long name="owns-file">1</long>
+                    <long name="title-mode">0</long>
+                    <long name="locked">0</long>
+                    <string name="proxy-type">"wbStaticTextProxy"</string>
+                    <string name="proxy-Id name">"wxID_STATIC"</string>
+                    <long name="proxy-Id value">5105</long>
+                    <string name="proxy-Name">""</string>
+                    <string name="proxy-Class">"wxStaticText"</string>
+                    <string name="proxy-Base class">"wxStaticText"</string>
+                    <bool name="proxy-External implementation">1</bool>
+                    <bool name="proxy-Separate files">0</bool>
+                    <string name="proxy-Implementation filename">""</string>
+                    <string name="proxy-Header filename">""</string>
+                    <string name="proxy-Member variable name">""</string>
+                    <string name="proxy-Label">"Selected camera:"</string>
+                    <long name="proxy-Wrapping width">-1</long>
+                    <string name="proxy-Help text">""</string>
+                    <string name="proxy-Tooltip text">""</string>
+                    <string name="proxy-Background colour">""</string>
+                    <string name="proxy-Foreground colour">""</string>
+                    <string name="proxy-Font">""</string>
+                    <bool name="proxy-Hidden">0</bool>
+                    <bool name="proxy-Enabled">1</bool>
+                    <string name="proxy-Platform">"<Any platform>"</string>
+                    <string name="proxy-Data variable">""</string>
+                    <string name="proxy-Data validator">""</string>
+                    <string name="proxy-Data source">""</string>
+                    <string name="proxy-Data class name">""</string>
+                    <string name="proxy-Data class implementation filename">""</string>
+                    <string name="proxy-Data class header filename">""</string>
+                    <string name="proxy-Data class manager window">""</string>
+                    <bool name="proxy-wxALIGN_LEFT">0</bool>
+                    <bool name="proxy-wxALIGN_RIGHT">0</bool>
+                    <bool name="proxy-wxALIGN_CENTRE">0</bool>
+                    <bool name="proxy-wxST_NO_AUTORESIZE">0</bool>
+                    <bool name="proxy-wxNO_BORDER">0</bool>
+                    <bool name="proxy-wxSIMPLE_BORDER">0</bool>
+                    <bool name="proxy-wxDOUBLE_BORDER">0</bool>
+                    <bool name="proxy-wxBORDER_THEME">0</bool>
+                    <bool name="proxy-wxSUNKEN_BORDER">0</bool>
+                    <bool name="proxy-wxRAISED_BORDER">0</bool>
+                    <bool name="proxy-wxSTATIC_BORDER">0</bool>
+                    <bool name="proxy-wxWANTS_CHARS">0</bool>
+                    <bool name="proxy-wxNO_FULL_REPAINT_ON_RESIZE">0</bool>
+                    <bool name="proxy-wxFULL_REPAINT_ON_RESIZE">0</bool>
+                    <string name="proxy-Custom styles">""</string>
+                    <long name="proxy-X">-1</long>
+                    <long name="proxy-Y">-1</long>
+                    <long name="proxy-Width">-1</long>
+                    <long name="proxy-Height">-1</long>
+                    <string name="proxy-AlignH">"Left"</string>
+                    <string name="proxy-AlignV">"Centre"</string>
+                    <long name="proxy-Stretch factor">0</long>
+                    <long name="proxy-Border">5</long>
+                    <bool name="proxy-wxLEFT">1</bool>
+                    <bool name="proxy-wxRIGHT">1</bool>
+                    <bool name="proxy-wxTOP">1</bool>
+                    <bool name="proxy-wxBOTTOM">1</bool>
+                    <bool name="proxy-wxSHAPED">0</bool>
+                    <bool name="proxy-wxADJUST_MINSIZE">0</bool>
+                    <bool name="proxy-wxFIXED_MINSIZE">0</bool>
+                    <string name="proxy-Custom arguments">""</string>
+                    <string name="proxy-Custom ctor arguments">""</string>
+                  </document>
+                  <document>
+                    <string name="title">"wxChoice: ID_CHOICE_SELECTED_CAMERA"</string>
+                    <string name="type">"dialog-control-document"</string>
+                    <string name="filename">""</string>
+                    <string name="icon-name">"choice"</string>
+                    <long name="is-transient">0</long>
+                    <long name="owns-file">1</long>
+                    <long name="title-mode">0</long>
+                    <long name="locked">0</long>
+                    <string name="proxy-type">"wbChoiceProxy"</string>
+                    <string name="event-handler-0">"wxEVT_COMMAND_CHOICE_SELECTED|OnChoiceSelectedCameraSelected|NONE||CCameraConfiguration"</string>
+                    <string name="proxy-Id name">"ID_CHOICE_SELECTED_CAMERA"</string>
+                    <long name="proxy-Id value">10000</long>
+                    <string name="proxy-Name">""</string>
+                    <string name="proxy-Class">"wxChoice"</string>
+                    <string name="proxy-Base class">"wxChoice"</string>
+                    <bool name="proxy-External implementation">1</bool>
+                    <bool name="proxy-Separate files">0</bool>
+                    <string name="proxy-Implementation filename">""</string>
+                    <string name="proxy-Header filename">""</string>
+                    <string name="proxy-Member variable name">"m_choSelectedCamera"</string>
+                    <string name="proxy-Strings">""</string>
+                    <string name="proxy-Initial value">""</string>
+                    <string name="proxy-Help text">""</string>
+                    <string name="proxy-Tooltip text">""</string>
+                    <string name="proxy-Background colour">""</string>
+                    <string name="proxy-Foreground colour">""</string>
+                    <string name="proxy-Font">""</string>
+                    <bool name="proxy-Hidden">0</bool>
+                    <bool name="proxy-Enabled">1</bool>
+                    <string name="proxy-Platform">"<Any platform>"</string>
+                    <string name="proxy-Data variable">""</string>
+                    <string name="proxy-Data validator">""</string>
+                    <string name="proxy-Data source">""</string>
+                    <string name="proxy-Data class name">""</string>
+                    <string name="proxy-Data class implementation filename">""</string>
+                    <string name="proxy-Data class header filename">""</string>
+                    <string name="proxy-Data class manager window">""</string>
+                    <bool name="proxy-wxWANTS_CHARS">0</bool>
+                    <bool name="proxy-wxNO_FULL_REPAINT_ON_RESIZE">0</bool>
+                    <bool name="proxy-wxFULL_REPAINT_ON_RESIZE">0</bool>
+                    <string name="proxy-Custom styles">""</string>
+                    <long name="proxy-X">-1</long>
+                    <long name="proxy-Y">-1</long>
+                    <long name="proxy-Width">-1</long>
+                    <long name="proxy-Height">-1</long>
+                    <string name="proxy-AlignH">"Expand"</string>
+                    <string name="proxy-AlignV">"Centre"</string>
+                    <long name="proxy-Stretch factor">0</long>
+                    <long name="proxy-Border">5</long>
+                    <bool name="proxy-wxLEFT">1</bool>
+                    <bool name="proxy-wxRIGHT">1</bool>
+                    <bool name="proxy-wxTOP">1</bool>
+                    <bool name="proxy-wxBOTTOM">1</bool>
+                    <bool name="proxy-wxSHAPED">0</bool>
+                    <bool name="proxy-wxADJUST_MINSIZE">0</bool>
+                    <bool name="proxy-wxFIXED_MINSIZE">0</bool>
+                    <string name="proxy-Custom arguments">""</string>
+                    <string name="proxy-Custom ctor arguments">""</string>
+                  </document>
+                  <document>
+                    <string name="title">"wxStaticText: wxID_STATIC"</string>
+                    <string name="type">"dialog-control-document"</string>
+                    <string name="filename">""</string>
+                    <string name="icon-name">"statictext"</string>
+                    <long name="is-transient">0</long>
+                    <long name="owns-file">1</long>
+                    <long name="title-mode">0</long>
+                    <long name="locked">0</long>
+                    <string name="proxy-type">"wbStaticTextProxy"</string>
+                    <string name="proxy-Id name">"wxID_STATIC"</string>
+                    <long name="proxy-Id value">5105</long>
+                    <string name="proxy-Name">""</string>
+                    <string name="proxy-Class">"wxStaticText"</string>
+                    <string name="proxy-Base class">"wxStaticText"</string>
+                    <bool name="proxy-External implementation">1</bool>
+                    <bool name="proxy-Separate files">0</bool>
+                    <string name="proxy-Implementation filename">""</string>
+                    <string name="proxy-Header filename">""</string>
+                    <string name="proxy-Member variable name">""</string>
+                    <string name="proxy-Label">"Format:"</string>
+                    <long name="proxy-Wrapping width">-1</long>
+                    <string name="proxy-Help text">""</string>
+                    <string name="proxy-Tooltip text">""</string>
+                    <string name="proxy-Background colour">""</string>
+                    <string name="proxy-Foreground colour">""</string>
+                    <string name="proxy-Font">""</string>
+                    <bool name="proxy-Hidden">0</bool>
+                    <bool name="proxy-Enabled">1</bool>
+                    <string name="proxy-Platform">"<Any platform>"</string>
+                    <string name="proxy-Data variable">""</string>
+                    <string name="proxy-Data validator">""</string>
+                    <string name="proxy-Data source">""</string>
+                    <string name="proxy-Data class name">""</string>
+                    <string name="proxy-Data class implementation filename">""</string>
+                    <string name="proxy-Data class header filename">""</string>
+                    <string name="proxy-Data class manager window">""</string>
+                    <bool name="proxy-wxALIGN_LEFT">0</bool>
+                    <bool name="proxy-wxALIGN_RIGHT">0</bool>
+                    <bool name="proxy-wxALIGN_CENTRE">0</bool>
+                    <bool name="proxy-wxST_NO_AUTORESIZE">0</bool>
+                    <bool name="proxy-wxNO_BORDER">0</bool>
+                    <bool name="proxy-wxSIMPLE_BORDER">0</bool>
+                    <bool name="proxy-wxDOUBLE_BORDER">0</bool>
+                    <bool name="proxy-wxBORDER_THEME">0</bool>
+                    <bool name="proxy-wxSUNKEN_BORDER">0</bool>
+                    <bool name="proxy-wxRAISED_BORDER">0</bool>
+                    <bool name="proxy-wxSTATIC_BORDER">0</bool>
+                    <bool name="proxy-wxWANTS_CHARS">0</bool>
+                    <bool name="proxy-wxNO_FULL_REPAINT_ON_RESIZE">0</bool>
+                    <bool name="proxy-wxFULL_REPAINT_ON_RESIZE">0</bool>
+                    <string name="proxy-Custom styles">""</string>
+                    <long name="proxy-X">-1</long>
+                    <long name="proxy-Y">-1</long>
+                    <long name="proxy-Width">-1</long>
+                    <long name="proxy-Height">-1</long>
+                    <string name="proxy-AlignH">"Left"</string>
+                    <string name="proxy-AlignV">"Centre"</string>
+                    <long name="proxy-Stretch factor">0</long>
+                    <long name="proxy-Border">5</long>
+                    <bool name="proxy-wxLEFT">1</bool>
+                    <bool name="proxy-wxRIGHT">1</bool>
+                    <bool name="proxy-wxTOP">1</bool>
+                    <bool name="proxy-wxBOTTOM">1</bool>
+                    <bool name="proxy-wxSHAPED">0</bool>
+                    <bool name="proxy-wxADJUST_MINSIZE">0</bool>
+                    <bool name="proxy-wxFIXED_MINSIZE">0</bool>
+                    <string name="proxy-Custom arguments">""</string>
+                    <string name="proxy-Custom ctor arguments">""</string>
+                  </document>
+                  <document>
+                    <string name="title">"wxChoice: ID_CHOICE_FORMAT"</string>
+                    <string name="type">"dialog-control-document"</string>
+                    <string name="filename">""</string>
+                    <string name="icon-name">"choice"</string>
+                    <long name="is-transient">0</long>
+                    <long name="owns-file">1</long>
+                    <long name="title-mode">0</long>
+                    <long name="locked">0</long>
+                    <string name="proxy-type">"wbChoiceProxy"</string>
+                    <string name="event-handler-0">"wxEVT_COMMAND_CHOICE_SELECTED|OnChoiceFormatSelected|NONE||CCameraConfiguration"</string>
+                    <string name="proxy-Id name">"ID_CHOICE_FORMAT"</string>
+                    <long name="proxy-Id value">10001</long>
+                    <string name="proxy-Name">""</string>
+                    <string name="proxy-Class">"wxChoice"</string>
+                    <string name="proxy-Base class">"wxChoice"</string>
+                    <bool name="proxy-External implementation">1</bool>
+                    <bool name="proxy-Separate files">0</bool>
+                    <string name="proxy-Implementation filename">""</string>
+                    <string name="proxy-Header filename">""</string>
+                    <string name="proxy-Member variable name">"m_choFormat"</string>
+                    <string name="proxy-Strings">""</string>
+                    <string name="proxy-Initial value">""</string>
+                    <string name="proxy-Help text">""</string>
+                    <string name="proxy-Tooltip text">""</string>
+                    <string name="proxy-Background colour">""</string>
+                    <string name="proxy-Foreground colour">""</string>
+                    <string name="proxy-Font">""</string>
+                    <bool name="proxy-Hidden">0</bool>
+                    <bool name="proxy-Enabled">1</bool>
+                    <string name="proxy-Platform">"<Any platform>"</string>
+                    <string name="proxy-Data variable">""</string>
+                    <string name="proxy-Data validator">""</string>
+                    <string name="proxy-Data source">""</string>
+                    <string name="proxy-Data class name">""</string>
+                    <string name="proxy-Data class implementation filename">""</string>
+                    <string name="proxy-Data class header filename">""</string>
+                    <string name="proxy-Data class manager window">""</string>
+                    <bool name="proxy-wxWANTS_CHARS">0</bool>
+                    <bool name="proxy-wxNO_FULL_REPAINT_ON_RESIZE">0</bool>
+                    <bool name="proxy-wxFULL_REPAINT_ON_RESIZE">0</bool>
+                    <string name="proxy-Custom styles">""</string>
+                    <long name="proxy-X">-1</long>
+                    <long name="proxy-Y">-1</long>
+                    <long name="proxy-Width">-1</long>
+                    <long name="proxy-Height">-1</long>
+                    <string name="proxy-AlignH">"Expand"</string>
+                    <string name="proxy-AlignV">"Centre"</string>
+                    <long name="proxy-Stretch factor">0</long>
+                    <long name="proxy-Border">5</long>
+                    <bool name="proxy-wxLEFT">1</bool>
+                    <bool name="proxy-wxRIGHT">1</bool>
+                    <bool name="proxy-wxTOP">1</bool>
+                    <bool name="proxy-wxBOTTOM">1</bool>
+                    <bool name="proxy-wxSHAPED">0</bool>
+                    <bool name="proxy-wxADJUST_MINSIZE">0</bool>
+                    <bool name="proxy-wxFIXED_MINSIZE">0</bool>
+                    <string name="proxy-Custom arguments">""</string>
+                    <string name="proxy-Custom ctor arguments">""</string>
+                  </document>
+                  <document>
+                    <string name="title">"wxStaticText: wxID_STATIC"</string>
+                    <string name="type">"dialog-control-document"</string>
+                    <string name="filename">""</string>
+                    <string name="icon-name">"statictext"</string>
+                    <long name="is-transient">0</long>
+                    <long name="owns-file">1</long>
+                    <long name="title-mode">0</long>
+                    <long name="locked">0</long>
+                    <string name="proxy-type">"wbStaticTextProxy"</string>
+                    <string name="proxy-Id name">"wxID_STATIC"</string>
+                    <long name="proxy-Id value">5105</long>
+                    <string name="proxy-Name">""</string>
+                    <string name="proxy-Class">"wxStaticText"</string>
+                    <string name="proxy-Base class">"wxStaticText"</string>
+                    <bool name="proxy-External implementation">1</bool>
+                    <bool name="proxy-Separate files">0</bool>
+                    <string name="proxy-Implementation filename">""</string>
+                    <string name="proxy-Header filename">""</string>
+                    <string name="proxy-Member variable name">""</string>
+                    <string name="proxy-Label">"Capture speed:"</string>
+                    <long name="proxy-Wrapping width">-1</long>
+                    <string name="proxy-Help text">""</string>
+                    <string name="proxy-Tooltip text">""</string>
+                    <string name="proxy-Background colour">""</string>
+                    <string name="proxy-Foreground colour">""</string>
+                    <string name="proxy-Font">""</string>
+                    <bool name="proxy-Hidden">0</bool>
+                    <bool name="proxy-Enabled">1</bool>
+                    <string name="proxy-Platform">"<Any platform>"</string>
+                    <string name="proxy-Data variable">""</string>
+                    <string name="proxy-Data validator">""</string>
+                    <string name="proxy-Data source">""</string>
+                    <string name="proxy-Data class name">""</string>
+                    <string name="proxy-Data class implementation filename">""</string>
+                    <string name="proxy-Data class header filename">""</string>
+                    <string name="proxy-Data class manager window">""</string>
+                    <bool name="proxy-wxALIGN_LEFT">0</bool>
+                    <bool name="proxy-wxALIGN_RIGHT">0</bool>
+                    <bool name="proxy-wxALIGN_CENTRE">0</bool>
+                    <bool name="proxy-wxST_NO_AUTORESIZE">0</bool>
+                    <bool name="proxy-wxNO_BORDER">0</bool>
+                    <bool name="proxy-wxSIMPLE_BORDER">0</bool>
+                    <bool name="proxy-wxDOUBLE_BORDER">0</bool>
+                    <bool name="proxy-wxBORDER_THEME">0</bool>
+                    <bool name="proxy-wxSUNKEN_BORDER">0</bool>
+                    <bool name="proxy-wxRAISED_BORDER">0</bool>
+                    <bool name="proxy-wxSTATIC_BORDER">0</bool>
+                    <bool name="proxy-wxWANTS_CHARS">0</bool>
+                    <bool name="proxy-wxNO_FULL_REPAINT_ON_RESIZE">0</bool>
+                    <bool name="proxy-wxFULL_REPAINT_ON_RESIZE">0</bool>
+                    <string name="proxy-Custom styles">""</string>
+                    <long name="proxy-X">-1</long>
+                    <long name="proxy-Y">-1</long>
+                    <long name="proxy-Width">-1</long>
+                    <long name="proxy-Height">-1</long>
+                    <string name="proxy-AlignH">"Left"</string>
+                    <string name="proxy-AlignV">"Centre"</string>
+                    <long name="proxy-Stretch factor">0</long>
+                    <long name="proxy-Border">5</long>
+                    <bool name="proxy-wxLEFT">1</bool>
+                    <bool name="proxy-wxRIGHT">1</bool>
+                    <bool name="proxy-wxTOP">1</bool>
+                    <bool name="proxy-wxBOTTOM">1</bool>
+                    <bool name="proxy-wxSHAPED">0</bool>
+                    <bool name="proxy-wxADJUST_MINSIZE">0</bool>
+                    <bool name="proxy-wxFIXED_MINSIZE">0</bool>
+                    <string name="proxy-Custom arguments">""</string>
+                    <string name="proxy-Custom ctor arguments">""</string>
+                  </document>
+                  <document>
+                    <string name="title">"wxChoice: ID_CHOICE_FPS"</string>
+                    <string name="type">"dialog-control-document"</string>
+                    <string name="filename">""</string>
+                    <string name="icon-name">"choice"</string>
+                    <long name="is-transient">0</long>
+                    <long name="owns-file">1</long>
+                    <long name="title-mode">0</long>
+                    <long name="locked">0</long>
+                    <string name="proxy-type">"wbChoiceProxy"</string>
+                    <string name="event-handler-0">"wxEVT_COMMAND_CHOICE_SELECTED|OnChoiceFpsSelected|NONE||CCameraConfiguration"</string>
+                    <string name="proxy-Id name">"ID_CHOICE_FPS"</string>
+                    <long name="proxy-Id value">10002</long>
+                    <string name="proxy-Name">""</string>
+                    <string name="proxy-Class">"wxChoice"</string>
+                    <string name="proxy-Base class">"wxChoice"</string>
+                    <bool name="proxy-External implementation">1</bool>
+                    <bool name="proxy-Separate files">0</bool>
+                    <string name="proxy-Implementation filename">""</string>
+                    <string name="proxy-Header filename">""</string>
+                    <string name="proxy-Member variable name">"m_choFPS"</string>
+                    <string name="proxy-Strings">""</string>
+                    <string name="proxy-Initial value">""</string>
+                    <string name="proxy-Help text">""</string>
+                    <string name="proxy-Tooltip text">""</string>
+                    <string name="proxy-Background colour">""</string>
+                    <string name="proxy-Foreground colour">""</string>
+                    <string name="proxy-Font">""</string>
+                    <bool name="proxy-Hidden">0</bool>
+                    <bool name="proxy-Enabled">1</bool>
+                    <string name="proxy-Platform">"<Any platform>"</string>
+                    <string name="proxy-Data variable">""</string>
+                    <string name="proxy-Data validator">""</string>
+                    <string name="proxy-Data source">""</string>
+                    <string name="proxy-Data class name">""</string>
+                    <string name="proxy-Data class implementation filename">""</string>
+                    <string name="proxy-Data class header filename">""</string>
+                    <string name="proxy-Data class manager window">""</string>
+                    <bool name="proxy-wxWANTS_CHARS">0</bool>
+                    <bool name="proxy-wxNO_FULL_REPAINT_ON_RESIZE">0</bool>
+                    <bool name="proxy-wxFULL_REPAINT_ON_RESIZE">0</bool>
+                    <string name="proxy-Custom styles">""</string>
+                    <long name="proxy-X">-1</long>
+                    <long name="proxy-Y">-1</long>
+                    <long name="proxy-Width">-1</long>
+                    <long name="proxy-Height">-1</long>
+                    <string name="proxy-AlignH">"Expand"</string>
+                    <string name="proxy-AlignV">"Centre"</string>
+                    <long name="proxy-Stretch factor">0</long>
+                    <long name="proxy-Border">5</long>
+                    <bool name="proxy-wxLEFT">1</bool>
+                    <bool name="proxy-wxRIGHT">1</bool>
+                    <bool name="proxy-wxTOP">1</bool>
+                    <bool name="proxy-wxBOTTOM">1</bool>
+                    <bool name="proxy-wxSHAPED">0</bool>
+                    <bool name="proxy-wxADJUST_MINSIZE">0</bool>
+                    <bool name="proxy-wxFIXED_MINSIZE">0</bool>
+                    <string name="proxy-Custom arguments">""</string>
+                    <string name="proxy-Custom ctor arguments">""</string>
+                  </document>
+                  <document>
+                    <string name="title">"wxStaticText: wxID_STATIC"</string>
+                    <string name="type">"dialog-control-document"</string>
+                    <string name="filename">""</string>
+                    <string name="icon-name">"statictext"</string>
+                    <long name="is-transient">0</long>
+                    <long name="owns-file">1</long>
+                    <long name="title-mode">0</long>
+                    <long name="locked">0</long>
+                    <string name="proxy-type">"wbStaticTextProxy"</string>
+                    <string name="proxy-Id name">"wxID_STATIC"</string>
+                    <long name="proxy-Id value">5105</long>
+                    <string name="proxy-Name">""</string>
+                    <string name="proxy-Class">"wxStaticText"</string>
+                    <string name="proxy-Base class">"wxStaticText"</string>
+                    <bool name="proxy-External implementation">1</bool>
+                    <bool name="proxy-Separate files">0</bool>
+                    <string name="proxy-Implementation filename">""</string>
+                    <string name="proxy-Header filename">""</string>
+                    <string name="proxy-Member variable name">""</string>
+                    <string name="proxy-Label">"Driver settings:"</string>
+                    <long name="proxy-Wrapping width">-1</long>
+                    <string name="proxy-Help text">""</string>
+                    <string name="proxy-Tooltip text">""</string>
+                    <string name="proxy-Background colour">""</string>
+                    <string name="proxy-Foreground colour">""</string>
+                    <string name="proxy-Font">""</string>
+                    <bool name="proxy-Hidden">0</bool>
+                    <bool name="proxy-Enabled">1</bool>
+                    <string name="proxy-Platform">"<Any platform>"</string>
+                    <string name="proxy-Data variable">""</string>
+                    <string name="proxy-Data validator">""</string>
+                    <string name="proxy-Data source">""</string>
+                    <string name="proxy-Data class name">""</string>
+                    <string name="proxy-Data class implementation filename">""</string>
+                    <string name="proxy-Data class header filename">""</string>
+                    <string name="proxy-Data class manager window">""</string>
+                    <bool name="proxy-wxALIGN_LEFT">0</bool>
+                    <bool name="proxy-wxALIGN_RIGHT">0</bool>
+                    <bool name="proxy-wxALIGN_CENTRE">0</bool>
+                    <bool name="proxy-wxST_NO_AUTORESIZE">0</bool>
+                    <bool name="proxy-wxNO_BORDER">0</bool>
+                    <bool name="proxy-wxSIMPLE_BORDER">0</bool>
+                    <bool name="proxy-wxDOUBLE_BORDER">0</bool>
+                    <bool name="proxy-wxBORDER_THEME">0</bool>
+                    <bool name="proxy-wxSUNKEN_BORDER">0</bool>
+                    <bool name="proxy-wxRAISED_BORDER">0</bool>
+                    <bool name="proxy-wxSTATIC_BORDER">0</bool>
+                    <bool name="proxy-wxWANTS_CHARS">0</bool>
+                    <bool name="proxy-wxNO_FULL_REPAINT_ON_RESIZE">0</bool>
+                    <bool name="proxy-wxFULL_REPAINT_ON_RESIZE">0</bool>
+                    <string name="proxy-Custom styles">""</string>
+                    <long name="proxy-X">-1</long>
+                    <long name="proxy-Y">-1</long>
+                    <long name="proxy-Width">-1</long>
+                    <long name="proxy-Height">-1</long>
+                    <string name="proxy-AlignH">"Left"</string>
+                    <string name="proxy-AlignV">"Centre"</string>
+                    <long name="proxy-Stretch factor">0</long>
+                    <long name="proxy-Border">5</long>
+                    <bool name="proxy-wxLEFT">1</bool>
+                    <bool name="proxy-wxRIGHT">1</bool>
+                    <bool name="proxy-wxTOP">1</bool>
+                    <bool name="proxy-wxBOTTOM">1</bool>
+                    <bool name="proxy-wxSHAPED">0</bool>
+                    <bool name="proxy-wxADJUST_MINSIZE">0</bool>
+                    <bool name="proxy-wxFIXED_MINSIZE">0</bool>
+                    <string name="proxy-Custom arguments">""</string>
+                    <string name="proxy-Custom ctor arguments">""</string>
+                  </document>
+                  <document>
+                    <string name="title">"wxButton: ID_BUTTON_DRIVER_SETTINGS"</string>
+                    <string name="type">"dialog-control-document"</string>
+                    <string name="filename">""</string>
+                    <string name="icon-name">"dialogcontrol"</string>
+                    <long name="is-transient">0</long>
+                    <long name="owns-file">1</long>
+                    <long name="title-mode">0</long>
+                    <long name="locked">0</long>
+                    <string name="proxy-type">"wbButtonProxy"</string>
+                    <string name="event-handler-0">"wxEVT_COMMAND_BUTTON_CLICKED|OnButtonDriverSettingsClick|NONE||CCameraConfiguration"</string>
+                    <string name="proxy-Id name">"ID_BUTTON_DRIVER_SETTINGS"</string>
+                    <long name="proxy-Id value">10064</long>
+                    <string name="proxy-Name">""</string>
+                    <string name="proxy-Class">"wxButton"</string>
+                    <string name="proxy-Base class">"wxButton"</string>
+                    <bool name="proxy-External implementation">1</bool>
+                    <bool name="proxy-Separate files">0</bool>
+                    <string name="proxy-Implementation filename">""</string>
+                    <string name="proxy-Header filename">""</string>
+                    <string name="proxy-Member variable name">""</string>
+                    <string name="proxy-Label">"Open driver settings"</string>
+                    <bool name="proxy-Default">0</bool>
+                    <string name="proxy-Help text">""</string>
+                    <string name="proxy-Tooltip text">""</string>
+                    <string name="proxy-Data variable">""</string>
+                    <string name="proxy-Data validator">""</string>
+                    <string name="proxy-Data source">""</string>
+                    <string name="proxy-Data class name">""</string>
+                    <string name="proxy-Data class implementation filename">""</string>
+                    <string name="proxy-Data class header filename">""</string>
+                    <string name="proxy-Data class manager window">""</string>
+                    <string name="proxy-Background colour">""</string>
+                    <string name="proxy-Foreground colour">""</string>
+                    <string name="proxy-Font">""</string>
+                    <bool name="proxy-Hidden">0</bool>
+                    <bool name="proxy-Enabled">1</bool>
+                    <string name="proxy-Platform">"<Any platform>"</string>
+                    <bool name="proxy-wxBU_LEFT">0</bool>
+                    <bool name="proxy-wxBU_RIGHT">0</bool>
+                    <bool name="proxy-wxBU_TOP">0</bool>
+                    <bool name="proxy-wxBU_BOTTOM">0</bool>
+                    <bool name="proxy-wxBU_EXACTFIT">0</bool>
+                    <bool name="proxy-wxNO_BORDER">0</bool>
+                    <bool name="proxy-wxWANTS_CHARS">0</bool>
+                    <bool name="proxy-wxNO_FULL_REPAINT_ON_RESIZE">0</bool>
+                    <bool name="proxy-wxFULL_REPAINT_ON_RESIZE">0</bool>
+                    <string name="proxy-Custom styles">""</string>
+                    <long name="proxy-X">-1</long>
+                    <long name="proxy-Y">-1</long>
+                    <long name="proxy-Width">-1</long>
+                    <long name="proxy-Height">-1</long>
+                    <string name="proxy-AlignH">"Expand"</string>
+                    <string name="proxy-AlignV">"Centre"</string>
+                    <long name="proxy-Stretch factor">0</long>
+                    <long name="proxy-Border">5</long>
+                    <bool name="proxy-wxLEFT">1</bool>
+                    <bool name="proxy-wxRIGHT">1</bool>
+                    <bool name="proxy-wxTOP">1</bool>
+                    <bool name="proxy-wxBOTTOM">1</bool>
+                    <bool name="proxy-wxSHAPED">0</bool>
+                    <bool name="proxy-wxADJUST_MINSIZE">0</bool>
+                    <bool name="proxy-wxFIXED_MINSIZE">0</bool>
+                    <string name="proxy-Custom arguments">""</string>
+                    <string name="proxy-Custom ctor arguments">""</string>
+                  </document>
+                  <document>
+                    <string name="title">"wxStaticText: wxID_STATIC"</string>
+                    <string name="type">"dialog-control-document"</string>
+                    <string name="filename">""</string>
+                    <string name="icon-name">"statictext"</string>
+                    <long name="is-transient">0</long>
+                    <long name="owns-file">1</long>
+                    <long name="title-mode">0</long>
+                    <long name="locked">0</long>
+                    <string name="proxy-type">"wbStaticTextProxy"</string>
+                    <string name="proxy-Id name">"wxID_STATIC"</string>
+                    <long name="proxy-Id value">5105</long>
+                    <string name="proxy-Name">""</string>
+                    <string name="proxy-Class">"wxStaticText"</string>
+                    <string name="proxy-Base class">"wxStaticText"</string>
+                    <bool name="proxy-External implementation">1</bool>
+                    <bool name="proxy-Separate files">0</bool>
+                    <string name="proxy-Implementation filename">""</string>
+                    <string name="proxy-Header filename">""</string>
+                    <string name="proxy-Member variable name">""</string>
+                    <string name="proxy-Label">"Image mirror:"</string>
+                    <long name="proxy-Wrapping width">-1</long>
+                    <string name="proxy-Help text">""</string>
+                    <string name="proxy-Tooltip text">""</string>
+                    <string name="proxy-Background colour">""</string>
+                    <string name="proxy-Foreground colour">""</string>
+                    <string name="proxy-Font">""</string>
+                    <bool name="proxy-Hidden">0</bool>
+                    <bool name="proxy-Enabled">1</bool>
+                    <string name="proxy-Platform">"<Any platform>"</string>
+                    <string name="proxy-Data variable">""</string>
+                    <string name="proxy-Data validator">""</string>
+                    <string name="proxy-Data source">""</string>
+                    <string name="proxy-Data class name">""</string>
+                    <string name="proxy-Data class implementation filename">""</string>
+                    <string name="proxy-Data class header filename">""</string>
+                    <string name="proxy-Data class manager window">""</string>
+                    <bool name="proxy-wxALIGN_LEFT">0</bool>
+                    <bool name="proxy-wxALIGN_RIGHT">0</bool>
+                    <bool name="proxy-wxALIGN_CENTRE">0</bool>
+                    <bool name="proxy-wxST_NO_AUTORESIZE">0</bool>
+                    <bool name="proxy-wxNO_BORDER">0</bool>
+                    <bool name="proxy-wxSIMPLE_BORDER">0</bool>
+                    <bool name="proxy-wxDOUBLE_BORDER">0</bool>
+                    <bool name="proxy-wxBORDER_THEME">0</bool>
+                    <bool name="proxy-wxSUNKEN_BORDER">0</bool>
+                    <bool name="proxy-wxRAISED_BORDER">0</bool>
+                    <bool name="proxy-wxSTATIC_BORDER">0</bool>
+                    <bool name="proxy-wxWANTS_CHARS">0</bool>
+                    <bool name="proxy-wxNO_FULL_REPAINT_ON_RESIZE">0</bool>
+                    <bool name="proxy-wxFULL_REPAINT_ON_RESIZE">0</bool>
+                    <string name="proxy-Custom styles">""</string>
+                    <long name="proxy-X">-1</long>
+                    <long name="proxy-Y">-1</long>
+                    <long name="proxy-Width">-1</long>
+                    <long name="proxy-Height">-1</long>
+                    <string name="proxy-AlignH">"Left"</string>
+                    <string name="proxy-AlignV">"Centre"</string>
+                    <long name="proxy-Stretch factor">0</long>
+                    <long name="proxy-Border">5</long>
+                    <bool name="proxy-wxLEFT">1</bool>
+                    <bool name="proxy-wxRIGHT">1</bool>
+                    <bool name="proxy-wxTOP">1</bool>
+                    <bool name="proxy-wxBOTTOM">1</bool>
+                    <bool name="proxy-wxSHAPED">0</bool>
+                    <bool name="proxy-wxADJUST_MINSIZE">0</bool>
+                    <bool name="proxy-wxFIXED_MINSIZE">0</bool>
+                    <string name="proxy-Custom arguments">""</string>
+                    <string name="proxy-Custom ctor arguments">""</string>
+                  </document>
+                  <document>
+                    <string name="title">"wxCheckBox: ID_CHECKBOX_MIRROR_IMAGE"</string>
+                    <string name="type">"dialog-control-document"</string>
+                    <string name="filename">""</string>
+                    <string name="icon-name">"checkbox"</string>
+                    <long name="is-transient">0</long>
+                    <long name="owns-file">1</long>
+                    <long name="title-mode">0</long>
+                    <long name="locked">0</long>
+                    <string name="proxy-type">"wbCheckBoxProxy"</string>
+                    <string name="event-handler-0">"wxEVT_COMMAND_CHECKBOX_CLICKED|OnCheckboxMirrorImageClick|NONE||CCameraConfiguration"</string>
+                    <string name="proxy-Id name">"ID_CHECKBOX_MIRROR_IMAGE"</string>
+                    <long name="proxy-Id value">10003</long>
+                    <string name="proxy-Name">""</string>
+                    <string name="proxy-Class">"wxCheckBox"</string>
+                    <string name="proxy-Base class">"wxCheckBox"</string>
+                    <bool name="proxy-External implementation">1</bool>
+                    <bool name="proxy-Separate files">0</bool>
+                    <string name="proxy-Implementation filename">""</string>
+                    <string name="proxy-Header filename">""</string>
+                    <string name="proxy-Member variable name">"m_chkMirrorImage"</string>
+                    <string name="proxy-Label">""</string>
+                    <bool name="proxy-Initial value">0</bool>
+                    <string name="proxy-Help text">""</string>
+                    <string name="proxy-Tooltip text">""</string>
+                    <string name="proxy-Data variable">""</string>
+                    <string name="proxy-Data validator">""</string>
+                    <string name="proxy-Data source">""</string>
+                    <string name="proxy-Data class name">""</string>
+                    <string name="proxy-Data class implementation filename">""</string>
+                    <string name="proxy-Data class header filename">""</string>
+                    <string name="proxy-Data class manager window">""</string>
+                    <string name="proxy-Background colour">""</string>
+                    <string name="proxy-Foreground colour">""</string>
+                    <string name="proxy-Font">""</string>
+                    <bool name="proxy-Hidden">0</bool>
+                    <bool name="proxy-Enabled">1</bool>
+                    <string name="proxy-Platform">"<Any platform>"</string>
+                    <bool name="proxy-wxALIGN_RIGHT">0</bool>
+                    <bool name="proxy-wxCHK_2STATE">0</bool>
+                    <bool name="proxy-wxCHK_3STATE">0</bool>
+                    <bool name="proxy-wxCHK_ALLOW_3RD_STATE_FOR_USER">0</bool>
+                    <bool name="proxy-wxWANTS_CHARS">0</bool>
+                    <bool name="proxy-wxNO_FULL_REPAINT_ON_RESIZE">0</bool>
+                    <bool name="proxy-wxFULL_REPAINT_ON_RESIZE">0</bool>
+                    <string name="proxy-Custom styles">""</string>
+                    <long name="proxy-X">-1</long>
+                    <long name="proxy-Y">-1</long>
+                    <long name="proxy-Width">-1</long>
+                    <long name="proxy-Height">-1</long>
+                    <string name="proxy-AlignH">"Left"</string>
+                    <string name="proxy-AlignV">"Centre"</string>
+                    <long name="proxy-Stretch factor">0</long>
+                    <long name="proxy-Border">5</long>
+                    <bool name="proxy-wxLEFT">1</bool>
+                    <bool name="proxy-wxRIGHT">1</bool>
+                    <bool name="proxy-wxTOP">1</bool>
+                    <bool name="proxy-wxBOTTOM">1</bool>
+                    <bool name="proxy-wxSHAPED">0</bool>
+                    <bool name="proxy-wxADJUST_MINSIZE">0</bool>
+                    <bool name="proxy-wxFIXED_MINSIZE">0</bool>
+                    <string name="proxy-Custom arguments">""</string>
+                    <string name="proxy-Custom ctor arguments">""</string>
+                  </document>
+                </document>
+              </document>
+            </document>
+            <document>
+              <string name="title">"wxButton: ID_BUTTON_CLOSE_CCONFIG"</string>
+              <string name="type">"dialog-control-document"</string>
+              <string name="filename">""</string>
+              <string name="icon-name">"dialogcontrol"</string>
+              <long name="is-transient">0</long>
+              <long name="owns-file">1</long>
+              <long name="title-mode">0</long>
+              <long name="locked">0</long>
+              <string name="proxy-type">"wbButtonProxy"</string>
+              <string name="event-handler-0">"wxEVT_COMMAND_BUTTON_CLICKED|OnButtonCloseCconfigClick|NONE|ID_CCAMERACONFIGURATION|CCameraConfiguration"</string>
+              <string name="proxy-Id name">"ID_BUTTON_CLOSE_CCONFIG"</string>
+              <long name="proxy-Id value">10065</long>
+              <string name="proxy-Name">""</string>
+              <string name="proxy-Class">"wxButton"</string>
+              <string name="proxy-Base class">"wxButton"</string>
+              <bool name="proxy-External implementation">1</bool>
+              <bool name="proxy-Separate files">0</bool>
+              <string name="proxy-Implementation filename">""</string>
+              <string name="proxy-Header filename">""</string>
+              <string name="proxy-Member variable name">""</string>
+              <string name="proxy-Label">"Close"</string>
+              <bool name="proxy-Default">0</bool>
+              <string name="proxy-Help text">""</string>
+              <string name="proxy-Tooltip text">""</string>
+              <string name="proxy-Data variable">""</string>
+              <string name="proxy-Data validator">""</string>
+              <string name="proxy-Data source">""</string>
+              <string name="proxy-Data class name">""</string>
+              <string name="proxy-Data class implementation filename">""</string>
+              <string name="proxy-Data class header filename">""</string>
+              <string name="proxy-Data class manager window">""</string>
+              <string name="proxy-Background colour">""</string>
+              <string name="proxy-Foreground colour">""</string>
+              <string name="proxy-Font">""</string>
+              <bool name="proxy-Hidden">0</bool>
+              <bool name="proxy-Enabled">1</bool>
+              <string name="proxy-Platform">"<Any platform>"</string>
+              <bool name="proxy-wxBU_LEFT">0</bool>
+              <bool name="proxy-wxBU_RIGHT">0</bool>
+              <bool name="proxy-wxBU_TOP">0</bool>
+              <bool name="proxy-wxBU_BOTTOM">0</bool>
+              <bool name="proxy-wxBU_EXACTFIT">0</bool>
+              <bool name="proxy-wxNO_BORDER">0</bool>
+              <bool name="proxy-wxWANTS_CHARS">0</bool>
+              <bool name="proxy-wxNO_FULL_REPAINT_ON_RESIZE">0</bool>
+              <bool name="proxy-wxFULL_REPAINT_ON_RESIZE">0</bool>
+              <string name="proxy-Custom styles">""</string>
+              <long name="proxy-X">-1</long>
+              <long name="proxy-Y">-1</long>
+              <long name="proxy-Width">-1</long>
+              <long name="proxy-Height">-1</long>
+              <string name="proxy-AlignH">"Centre"</string>
+              <string name="proxy-AlignV">"Centre"</string>
+              <long name="proxy-Stretch factor">0</long>
+              <long name="proxy-Border">5</long>
+              <bool name="proxy-wxLEFT">1</bool>
+              <bool name="proxy-wxRIGHT">1</bool>
+              <bool name="proxy-wxTOP">1</bool>
+              <bool name="proxy-wxBOTTOM">1</bool>
+              <bool name="proxy-wxSHAPED">0</bool>
+              <bool name="proxy-wxADJUST_MINSIZE">0</bool>
+              <bool name="proxy-wxFIXED_MINSIZE">0</bool>
+              <string name="proxy-Custom arguments">""</string>
+              <string name="proxy-Custom ctor arguments">""</string>
+            </document>
+          </document>
+        </document>
+      </document>
+      <document>
+        <string name="title">"Sources"</string>
+        <string name="type">"html-document"</string>
+        <string name="filename">""</string>
+        <string name="icon-name">"sourcesfolder"</string>
+        <long name="is-transient">1</long>
+        <long name="owns-file">1</long>
+        <long name="title-mode">0</long>
+        <long name="locked">1</long>
+      </document>
+      <document>
+        <string name="title">"Images"</string>
+        <string name="type">"html-document"</string>
+        <string name="filename">""</string>
+        <string name="icon-name">"bitmapsfolder"</string>
+        <long name="is-transient">1</long>
+        <long name="owns-file">1</long>
+        <long name="title-mode">0</long>
+        <long name="locked">1</long>
+      </document>
+    </document>
+  </documents>
+
+</anthemion-project>
diff --git a/src/mod_camera/roitype.cpp b/src/mod_camera/roitype.cpp
new file mode 100755
index 0000000..0ea2323
--- /dev/null
+++ b/src/mod_camera/roitype.cpp
@@ -0,0 +1,653 @@
+/////////////////////////////////////////////////////////////////////////////
+// Name:        roitype.cpp
+// Author:      Cesar Mauri Loba (cesar at crea-si dot com)
+// Modified by: 
+// Created:     11/02/2011
+// Copyright:   (C) 2011 Cesar Mauri Loba - CREA Software Systems
+// 
+//  This program is free software: you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation, either version 3 of the License, or
+//  (at your option) any later version.
+//
+//  This program is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+/////////////////////////////////////////////////////////////////////////////
+#include "mod_camera/roitype.h"
+#ifdef WIN32
+// TODO: remove the following line when boost gets updated
+// See: https://svn.boost.org/trac/boost/ticket/4649
+#pragma warning (disable:4127)
+#endif
+#include <boost/tokenizer.hpp>
+
+#include <boost/program_options.hpp>
+
+#include <iostream>
+
+namespace po = boost::program_options;
+
+#include <boost/foreach.hpp>
+#include <boost/algorithm/string.hpp>
+//#include <boost/lexical_cast.hpp>
+
+#define MIN_WIDTH_HEIGHT	0.041666666666666666666666666666667f		// 6 p�xels over 144
+#define MAX_WIDTH_HEIGHT	1.0f 
+
+using namespace spcore;
+using namespace boost;
+using namespace std;
+
+namespace mod_camera {
+
+// delete registered childs
+CTypeROIContents::~CTypeROIContents()
+{
+	// Destroy children ROI
+	ROICollection::iterator i;
+	while ((i= m_childROIs.begin())!= m_childROIs.end()) {	
+#if !defined(NDEBUG)
+		CTypeROI* child= static_cast<CTypeROI*>(*i);
+		child->AddRef();
+#endif
+		// Note that this effectively removes the child
+		// and invalidates iterator
+		UnregisterChildROI(static_cast<CTypeROI*>(*i));
+#if !defined(NDEBUG)
+		assert (child->m_pParentROI== NULL);
+		child->Release();
+#endif		
+	}
+
+	m_childROIs.clear();
+	
+	assert (m_childROIs.empty());
+
+	// Detach itself from parent
+	if (m_pParentROI) {
+		ROICollection::iterator i= find (m_pParentROI->m_childROIs.begin(), m_pParentROI->m_childROIs.end(), this);
+		assert (i!= m_pParentROI->m_childROIs.end());
+		m_pParentROI->m_childROIs.erase(i);			
+		m_pParentROI= NULL;		
+	}
+}
+
+bool CTypeROIContents::ParseCommandline (int argc, const char* argv[])
+{
+	if (!argc) return true;
+
+	bool no_errors= true;
+	string errMsg;
+
+	try {
+		po::options_description desc("Allowed roi options");
+		desc.add_options()
+			("help,h", "produce help message")
+			("size,s", po::value<vector<float> >()->multitoken(), "roi size. two floats between 0 and 1. (default 1 1)")
+			("center,c", po::value<vector<float> >()->multitoken(), "roi size. two floats between 0 and 1. (default 0.5 0.5)")
+			("visible,v", po::value<bool>(&m_isVisible)->default_value(true), "is visible")
+			("editable,e", po::value<bool>(&m_isEditable)->default_value(true), "is editable")
+			("direction,d", po::value<bool>(&m_useDirection)->default_value(false), "use direction arrow")
+			("color", po::value<unsigned int>(&m_color)->default_value(0), "color of the rectangle")			
+		;
+
+		try {			
+			// TODO: parse directly argc, argv instead of building a vector of tokens
+			vector< string > tokens;
+			for (int i= 0; i< argc; i++) tokens.push_back(argv[i]);
+
+			// Try to process input parameters
+			po::variables_map vm;
+			po::store(po::command_line_parser(tokens).options(desc).run(), vm);
+
+			// Doing this way ignores multitoken parameters :-(
+			//po::store(po::command_line_parser(argc, (char **) argv).options(desc).run(), vm);
+			//po::store(po::parse_command_line(argc, (char **) argv, desc), vm);
+
+			po::notify(vm);    
+
+			if (vm.count("help")) no_errors= false;
+			else {
+				// Get size values
+				if (vm.count("size")) {
+					if (vm["size"].as< vector<float> >().size()!= 2) 
+						throw std::runtime_error("wrong number of size values");
+
+					float width= vm["size"].as<vector<float> >()[0];
+					float height= vm["size"].as<vector<float> >()[1];
+
+					if (width< 0 || width> 1.0f || height< 0 || height> 1.0f)
+						throw std::runtime_error("wrong values for size");
+
+					SetSize (width,height);
+				}
+
+				float x= 0.5f;
+				float y= 0.5f;
+				// Get centre values
+				if (vm.count("center")) {
+					if (vm["center"].as<vector<float> >().size()!= 2) 
+						throw std::runtime_error("wrong number of center values");
+
+					x= vm["center"].as<vector<float> >()[0];
+					y= vm["center"].as<vector<float> >()[1];
+
+					if (x< 0 || x> 1.0f || y< 0 || y> 1.0f)
+						throw std::runtime_error("wrong values for center");
+				}
+				SetCenter (x, y);
+			}
+		}
+		catch(std::exception& e) {
+			errMsg= e.what();			
+			no_errors= false;
+		}
+		catch(...) {
+			no_errors= false;
+		}
+
+		if (!no_errors) {
+			// Show help
+			ostringstream oss (errMsg);
+			oss << desc << "\n";
+			getSpCoreRuntime()->LogMessage(ICoreRuntime::LOG_INFO, oss.str().c_str(), "roi");
+		}
+	}
+	catch(...) {
+		getSpCoreRuntime()->LogMessage(ICoreRuntime::LOG_ERROR, "internal error: malformed options description", "roi");
+		no_errors= false;
+	}
+
+	return no_errors;
+}
+
+
+//
+// Working with native coordinates
+//
+
+// Find minimum child's P1 coordinates
+void CTypeROIContents::FindMinChildP1 (float& x, float& y) const
+{
+	ROICollection::const_iterator i;
+
+	for(i= m_childROIs.begin(); i != m_childROIs.end(); ++i) {
+		static_cast<CTypeROI*>(*i)->FindMinChildP1Rec (x, y);
+	}
+}
+
+void CTypeROIContents::FindMinChildP1Rec (float& x, float& y) const
+{
+	ROICollection::const_iterator i;
+
+	for(i= m_childROIs.begin(); i != m_childROIs.end(); ++i) {
+		static_cast<CTypeROI*>(*i)->FindMinChildP1Rec (x, y);
+	}
+
+	if (x> m_x) x= m_x;
+	if (y> m_y) y= m_y;
+}
+
+// Find miaximum child's P2 coordinates
+void CTypeROIContents::FindMaxChildP2 (float& x, float& y) const
+{
+	ROICollection::const_iterator i;
+
+	for(i= m_childROIs.begin(); i != m_childROIs.end(); ++i) {
+		static_cast<CTypeROI*>(*i)->FindMaxChildP2Rec (x, y);
+	}
+}
+
+void CTypeROIContents::FindMaxChildP2Rec (float& x, float& y) const
+{
+	ROICollection::const_iterator i;
+
+	for(i= m_childROIs.begin(); i != m_childROIs.end(); ++i) {
+		static_cast<CTypeROI*>(*i)->FindMaxChildP2Rec (x, y);
+	}
+
+	if (x< m_x + m_width) x= m_x + m_width;
+	if (y< m_y + m_height) y= m_y + m_height;
+}
+
+void CTypeROIContents::SetP1Resize (float x, float y)
+{
+	float min_p1x, min_p1y, max_p1x, max_p1y;
+	float p2x, p2y;
+
+	//CvPoint2D32f p2;
+
+	p2x= m_x + m_width;
+	p2y= m_y + m_height;
+
+	if (m_pParentROI) {
+		min_p1x= m_pParentROI->m_x;
+		min_p1y= m_pParentROI->m_y;
+	}
+	else {
+		 min_p1x= min_p1y= 0.0f;
+	}
+	max_p1x= p2x - MIN_WIDTH_HEIGHT;
+	max_p1y= p2y - MIN_WIDTH_HEIGHT;
+	FindMinChildP1 (max_p1x, max_p1y);
+	assert (max_p1x>= 0.0f);
+	assert (max_p1y>= 0.0f);
+
+	if (x< min_p1x) m_x= min_p1x;
+	else if (x> max_p1x) m_x= max_p1x;
+	else m_x= x;
+
+	if (y< min_p1y) m_y= min_p1y;
+	else if (y> max_p1y) m_y= max_p1y;
+	else m_y= y;
+
+	m_width= p2x - m_x;
+	m_height= p2y - m_y;
+}	
+		
+void CTypeROIContents::SetP1Move (float x, float y)
+{
+	float min_p1x, min_p1y, max_p1x, max_p1y;
+	float min_p2x, min_p2y;
+
+	// Compute minimum valid p1 coordinates
+	if (m_pParentROI) {
+		min_p1x= m_pParentROI->m_x;
+		min_p1y= m_pParentROI->m_y;
+	}
+	else {
+		 min_p1x= min_p1y= 0.0f;
+	}
+	min_p2x= min_p1x + m_width;
+	min_p2y= min_p1y + m_height;
+	FindMaxChildP2 (min_p2x, min_p2y);
+	min_p1x= min_p2x - m_width;
+	min_p1y= min_p2y - m_height;
+	if (min_p1x< 0.0f) min_p1x= 0.0f;
+	if (min_p1y< 0.0f) min_p1y= 0.0f;
+
+	// Compute maximum valid p1 coordinates
+	if (m_pParentROI) {
+		max_p1x= m_pParentROI->m_x + m_pParentROI->m_width - m_width;
+		max_p1y= m_pParentROI->m_y + m_pParentROI->m_height - m_height;
+	}
+	else {
+		max_p1x= MAX_WIDTH_HEIGHT - m_width;
+		max_p1y= MAX_WIDTH_HEIGHT - m_height;
+	}
+	FindMinChildP1 (max_p1x, max_p1y);
+	assert (max_p1x>= 0.0f);
+	assert (max_p1y>= 0.0f);
+
+	// Apply restrictions
+	if (x< min_p1x) m_x= min_p1x;
+	else if (x> max_p1x) m_x= max_p1x;
+	else m_x= x;
+
+	if (y< min_p1y) m_y= min_p1y;
+	else if (y> max_p1y) m_y= max_p1y;
+	else m_y= y;	
+}
+
+void CTypeROIContents::SetP2Resize (float x, float y)
+{
+	// Setting P2 always resize
+	float min_p2x, min_p2y, max_p2x, max_p2y;
+
+	min_p2x= m_x + MIN_WIDTH_HEIGHT;
+	min_p2y= m_y + MIN_WIDTH_HEIGHT;
+	assert (min_p2x<= MAX_WIDTH_HEIGHT);
+	assert (min_p2y<= MAX_WIDTH_HEIGHT);
+	FindMaxChildP2 (min_p2x, min_p2y);
+
+	if (m_pParentROI) {
+		max_p2x= m_pParentROI->m_x + m_pParentROI->m_width;
+		max_p2y= m_pParentROI->m_y + m_pParentROI->m_height;
+	}
+	else {
+		max_p2x= max_p2y= MAX_WIDTH_HEIGHT;
+	}
+
+	if (x< min_p2x) m_width= min_p2x - m_x;
+	else if (x> max_p2x) m_width= max_p2x - m_x;
+	else m_width= x - m_x;
+
+	if (y< min_p2y) m_height= min_p2y - m_y;
+	else if (y> max_p2y) m_height= max_p2y - m_y;
+	else m_height= y - m_y;	
+}
+
+void CTypeROIContents::SetCenter (float x, float y)
+{
+	SetP1Move (x - (m_width / 2.0f), y - (m_height / 2.0f));
+}
+
+void CTypeROIContents::GetCenter (float& x, float& y) const
+{
+	x= m_x + (m_width / 2.0f);
+	y= m_y + (m_height / 2.0f);
+}
+
+void CTypeROIContents::SetSize (float width, float height)
+{
+	SetP2Resize (width + m_x, height + m_y);
+}
+
+void CTypeROIContents::GetSize (float& width, float& height) const
+{
+	width= m_width;
+	height= m_height;
+}
+#if 0
+//
+// Working with generic integer coordinates
+//
+inline void CTypeROIContents::Integer2Normalized (const CvSize& size, const int ix, const int iy, float &nx, float &ny)
+{
+	assert (size.width> 0);
+	assert (size.height> 0);
+	
+	nx= (float) ix / (float) size.width;
+	ny= (float) iy / (float) size.height;
+}
+
+inline void CTypeROIContents::Normalized2Integer (const CvSize& size, const float nx, const float ny, int &ix, int &iy)
+{
+	assert (size.width> 0);
+	assert (size.height> 0);
+
+	ix= (int) (nx * (float) size.width + 0.5f);
+	iy= (int) (ny * (float) size.height + 0.5f);
+}
+
+//inline 
+void CTypeROIContents::SetP1ResizeInteger (const CvSize& size, const int x, const int y)
+{
+	float new_x, new_y;
+
+	Integer2Normalized (size, x, y, new_x, new_y);
+
+	SetP1Resize (new_x, new_y);
+}
+
+//inline 
+void CTypeROIContents::SetP1MoveInteger (const CvSize& size, const int x, const int y)
+{
+	float new_x, new_y;
+
+	Integer2Normalized (size, x, y, new_x, new_y);
+
+	SetP1Move (new_x, new_y);
+}
+
+//inline 
+void CTypeROIContents::SetP2ResizeInteger (const CvSize& size, const int x, const int y)
+{
+	float new_x, new_y;
+
+	Integer2Normalized (size, x, y, new_x, new_y);
+
+	SetP2Resize (new_x, new_y);
+}
+
+//inline 
+void CTypeROIContents::SetCenterInteger (const CvSize& size, const int x, const int y)
+{
+	float new_x, new_y;
+
+	Integer2Normalized (size, x, y, new_x, new_y);
+
+	SetCenter (new_x, new_y);
+}
+
+void CTypeROIContents::GetCenterInteger (const CvSize& size, int& x, int& y)
+{
+	float fx, fy;
+
+	GetCenter (fx, fy);
+
+	Normalized2Integer (size, fx, fy, x, y);	
+}
+
+//inline 
+void CTypeROIContents::SetSizeInteger (const CvSize& size, const int width, const int height)
+{
+	float new_width, new_height;
+
+	Integer2Normalized (size, width, height, new_width, new_height);
+
+	SetSize (new_width, new_height);
+}
+
+//inline 
+void CTypeROIContents::GetBoxInteger (const CvSize& size, int& x, int& y, int& width, int& height)
+{
+	Normalized2Integer (size, m_x, m_y, x, y);
+	Normalized2Integer (size, m_width, m_height, width, height);
+}
+
+void CTypeROIContents::GetBoxInteger (const CvSize& size, CvRect& box)
+{
+	GetBoxInteger (size, box.x, box.y, box.width, box.height);
+}
+
+void CTypeROIContents::GetP1P2Integer (const CvSize& size, CvPoint& p1, CvPoint& p2)
+{
+	Normalized2Integer (size, m_x, m_y, p1.x, p1.y);
+	Normalized2Integer (size, m_x + m_width, m_y + m_height, p2.x, p2.y);
+}
+
+//
+// Facilities to work with CIplImage images
+//
+void CTypeROIContents::SetP1ResizeImg (const CIplImage *pImg, const int x, const int y)
+{
+	assert (pImg);
+	assert (pImg->Origin()== IPL_ORIGIN_TL);
+
+	SetP1ResizeInteger (pImg->GetSize(), x, y);
+}
+
+void CTypeROIContents::SetP1MoveImg (const CIplImage *pImg, const int x, const int y)
+{
+	assert (pImg);
+	assert (pImg->Origin()== IPL_ORIGIN_TL);
+
+	SetP1MoveInteger (pImg->GetSize(), x, y);
+}
+
+void CTypeROIContents::SetP2ResizeImg (const CIplImage *pImg, const int x, const int y)
+{
+	assert (pImg);
+	assert (pImg->Origin()== IPL_ORIGIN_TL);
+
+	SetP2ResizeInteger (pImg->GetSize(), x, y);	
+}
+
+void CTypeROIContents::SetCenterImg (const CIplImage *pImg, const int x, const int y)
+{
+	assert (pImg);
+	assert (pImg->Origin()== IPL_ORIGIN_TL);
+	
+	SetCenterInteger (pImg->GetSize(), x, y);
+}
+
+void CTypeROIContents::GetCenterImg (const CIplImage *pImg, int& x, int& y)
+{
+	assert (pImg);
+	assert (pImg->Origin()== IPL_ORIGIN_TL);
+
+	GetCenterInteger (pImg->GetSize(), x, y);	
+}
+
+void CTypeROIContents::SetSizeImg (const CIplImage *pImg, const int width, const int height)
+{
+	assert (pImg);
+	assert (pImg->Origin()== IPL_ORIGIN_TL);
+
+	SetSizeInteger (pImg->GetSize(), width, height);
+}
+
+void CTypeROIContents::GetBoxImg (const CIplImage *pImg, int& x, int& y, int& width, int& height)
+{
+	assert (pImg);
+	assert (pImg->Origin()== IPL_ORIGIN_TL);
+
+	GetBoxInteger (pImg->GetSize(), x, y, width, height);
+}
+
+void CTypeROIContents::GetBoxImg (const CIplImage *pImg, CvRect& box)
+{
+	GetBoxImg (pImg, box.x, box.y, box.width, box.height);
+}
+#endif
+
+//
+// Registration service
+//
+bool CTypeROIContents::RegisterChildROI (CTypeROI* roi)
+{
+	assert (roi);
+	assert (roi!= this);
+	if (roi== this) return false;
+		
+	ROICollection::const_iterator i;
+
+	for(i= m_childROIs.begin(); i != m_childROIs.end(); ++i) {
+		if ((*i)== roi) return false;	// Already registered
+	}
+
+	// Check that no registered with other parent
+	if (roi->m_pParentROI) return false;
+
+	// Add to collection
+	roi->AddRef();
+	roi->m_pParentROI= static_cast<CTypeROI*>(this);
+	m_childROIs.push_back (roi);	
+
+	// Make sure child is inside parent
+	if (roi->m_width> m_width) roi->m_width= m_width;
+	if (roi->m_height> m_height) roi->m_height= m_height;
+	roi->SetP1Move (roi->m_x, roi->m_y);	
+
+	return true;
+}
+
+bool CTypeROIContents::UnregisterChildROI (CTypeROI* roi)
+{
+	assert (roi);
+
+	if (roi== NULL) return false;
+
+	ROICollection::iterator i;
+
+	for(i= m_childROIs.begin(); i != m_childROIs.end(); ++i) {
+		if ((*i)== roi) break;	// Found!
+	}
+	if (i== m_childROIs.end()) return false;	// Not found
+	
+	assert (static_cast<CTypeROI*>(*i)->m_pParentROI== this);
+	static_cast<CTypeROI*>(*i)->m_pParentROI= NULL;
+	m_childROIs.erase (i);
+
+	roi->Release();
+
+	return true;
+}
+
+bool CTypeROIContents::CopyTo ( CTypeAny& dst, bool recurse ) const {
+	assert (dst.GetTypeID()== this->GetTypeID());
+	assert (this!= &dst);
+
+	CTypeROI* dst_cast= sptype_static_cast<CTypeROI>(&dst);
+	assert (dst_cast);
+	
+	// copy contents
+	dst_cast->m_x= m_x;
+	dst_cast->m_y= m_y;
+	dst_cast->m_width= m_width;
+	dst_cast->m_height= m_height;
+	dst_cast->m_useDirection= m_useDirection;
+	dst_cast->m_direction= m_direction;
+	dst_cast->m_isVisible= m_isVisible;
+	dst_cast->m_isEditable= m_isEditable;
+	dst_cast->m_color= m_color;
+	dst_cast->m_registrationId= m_registrationId;
+
+	if (recurse) {
+		// 
+		// composite copy of a composite type. update structure and contents recursively 
+		//
+		ROICollection::const_iterator it_src= this->m_childROIs.begin();
+		ROICollection::iterator it_dst= dst_cast->m_childROIs.begin();	
+
+		// While both have children just copy
+		while (it_src!= this->m_childROIs.end() && it_dst!= dst_cast->m_childROIs.end()) {
+#ifndef NDEBUG
+			SmartPtr<CTypeAny> retval=
+#endif
+			(*it_src)->Clone (*it_dst, recurse);
+#ifndef NDEBUG
+			assert (retval.get());
+#endif
+			++it_src;
+			++it_dst;		
+		}
+
+		if (it_src!= this->m_childROIs.end()) {
+			// src has more children than dst, create and clone
+			while (it_src!= this->m_childROIs.end()) {
+				SmartPtr<CTypeROI> new_child= CTypeROI::CreateInstance();
+				if (!new_child.get()) return false;
+				new_child.get()->AddRef();	// Goes to non smart ptr'ed vector
+				new_child->m_pParentROI= static_cast<CTypeROI*>(dst_cast);
+				dst_cast->m_childROIs.push_back (new_child.get());
+	#ifndef NDEBUG
+				SmartPtr<CTypeAny> retval=
+	#endif
+				static_cast<CTypeROI*>(*it_src)->Clone (new_child.get(), recurse);
+	#ifndef NDEBUG
+				assert (retval.get());
+	#endif
+				++it_src;
+			}
+		}
+		else {
+			// dst has remaining children that need to be removed
+			while (it_dst!= dst_cast->m_childROIs.end()) {
+				static_cast<CTypeROI*>(*it_dst)->m_pParentROI= NULL;
+				static_cast<CTypeROI*>(*it_dst)->Release();
+				it_dst= dst_cast->m_childROIs.erase(it_dst);
+			}
+		}
+	}
+	else {
+		// shallow copy, remove destination children if any
+		ROICollection::iterator it_dst= dst_cast->m_childROIs.begin();
+		while (it_dst!= dst_cast->m_childROIs.end()) {
+			static_cast<CTypeROI*>(*it_dst)->m_pParentROI= NULL;
+			static_cast<CTypeROI*>(*it_dst)->Release();
+			it_dst= dst_cast->m_childROIs.erase(it_dst);
+		}
+	}	
+
+	return true;
+}
+
+// Support composite behaviour but only allow to add ROIs
+int CTypeROIContents::AddChild(SmartPtr<CTypeAny> component) {
+	CTypeROI * tmp= spcore::sptype_dynamic_cast<CTypeROI>(component.get());
+	if (!tmp) return -1;
+	return (RegisterChildROI(tmp)? 0 : -1);
+}
+
+SmartPtr<IIterator<CTypeAny*> > CTypeROIContents::QueryChildren() const {
+	return SmartPtr<IIterator<CTypeAny*> > (new CIteratorVector<CTypeAny*>(m_childROIs), false);
+}
+
+}
\ No newline at end of file
diff --git a/src/mod_camera/tests/CMakeLists.txt b/src/mod_camera/tests/CMakeLists.txt
new file mode 100755
index 0000000..66a8b8d
--- /dev/null
+++ b/src/mod_camera/tests/CMakeLists.txt
@@ -0,0 +1,25 @@
+cmake_minimum_required(VERSION 2.8)
+project(test_mod_camera)
+
+add_executable(test_mod_camera_gui test_mod_camera_gui.cpp)
+target_link_libraries(test_mod_camera_gui spcore)
+target_link_libraries(test_mod_camera_gui sphost)
+target_link_libraries(test_mod_camera_gui ${wxWidgets_LIBRARIES})
+target_link_libraries(test_mod_camera_gui nvwa)
+#target_link_libraries(test_mod_camera_gui spmod_camera)
+add_test (NAME test_mod_camera_gui COMMAND $<TARGET_FILE:nvwa_loader> $<TARGET_FILE:test_mod_camera_gui>)
+
+add_executable(test_mod_camera_viewer test_mod_camera_viewer.cpp)
+target_link_libraries(test_mod_camera_viewer spcore)
+target_link_libraries(test_mod_camera_viewer sphost)
+target_link_libraries(test_mod_camera_viewer ${wxWidgets_LIBRARIES})
+target_link_libraries(test_mod_camera_viewer nvwa)
+#target_link_libraries(test_mod_camera_viewer spmod_camera)
+add_test (NAME test_mod_camera_viewer COMMAND $<TARGET_FILE:nvwa_loader> $<TARGET_FILE:test_mod_camera_viewer>)
+
+add_executable(test_mod_camera_rois test_mod_camera_rois.cpp)
+target_link_libraries(test_mod_camera_rois spcore)
+target_link_libraries(test_mod_camera_rois sphost)
+target_link_libraries(test_mod_camera_rois nvwa)
+#target_link_libraries(test_mod_camera_rois spmod_camera)
+add_test (NAME test_mod_camera_rois COMMAND $<TARGET_FILE:nvwa_loader> $<TARGET_FILE:test_mod_camera_rois>)
\ No newline at end of file
diff --git a/src/mod_camera/tests/test_mod_camera_gui.cpp b/src/mod_camera/tests/test_mod_camera_gui.cpp
new file mode 100644
index 0000000..fa68cf2
--- /dev/null
+++ b/src/mod_camera/tests/test_mod_camera_gui.cpp
@@ -0,0 +1,235 @@
+/////////////////////////////////////////////////////////////////////////////
+// Name:        test_mod_camera_gui.cpp
+// Author:      Cesar Mauri Loba
+// Copyright:   (C) 2011 Cesar Mauri Loba - CREA Software Systems
+//
+//  This program is free software: you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation, either version 3 of the License, or
+//  (at your option) any later version.
+//
+//  This program is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+/////////////////////////////////////////////////////////////////////////////
+
+
+#include "spcore/coreruntime.h"
+#include "sphost/testcommon.h"
+#include "nvwa/debug_new.h"
+
+#if defined(__WXGTK__) || defined(__WXMOTIF__) || defined(__WXX11__)
+	// Include Xlib for latter use on main
+	#include <X11/Xlib.h>
+#endif
+#include <wx/app.h>
+#include <wx/image.h>
+#include <wx/msgdlg.h>
+#include <wx/frame.h>
+#include <wx/panel.h>
+#include <wx/sizer.h>
+
+using namespace spcore;
+
+/*
+	Check threads enabled
+*/
+#if !wxUSE_THREADS
+     #error "This program requires thread support."
+#endif // wxUSE_THREADS
+
+/*
+	main app class
+*/
+class TestWXApp: public wxApp
+{
+	DECLARE_CLASS( TestWXApp )
+public:
+	TestWXApp();	// Constructor
+
+private:
+	virtual bool OnInit();	// Initialises the application
+	virtual int OnExit();	// Called on exit
+
+	SmartPtr<spcore::IComponent> m_comp;
+};
+
+/*
+	main frame class
+*/
+class MyFrame : public wxFrame
+{
+public:
+    MyFrame();
+	void OnCloseWindow( wxCloseEvent& event );
+	static MyFrame* CreateAddPanel ( spcore::IComponent& component );
+private:
+	void OnSize(wxSizeEvent& event);
+    // any class wishing to process wxWidgets events must use this macro
+    DECLARE_EVENT_TABLE()
+};
+
+/*
+	myframe event table
+*/
+BEGIN_EVENT_TABLE(MyFrame, wxFrame)
+	EVT_CLOSE( MyFrame::OnCloseWindow )
+	EVT_SIZE ( MyFrame::OnSize)
+END_EVENT_TABLE()
+
+void MyFrame::OnCloseWindow(wxCloseEvent &event)
+{
+	event.Skip(); // Equivalent to: wxFrame::OnCloseWindow(event);
+}
+
+void MyFrame::OnSize(wxSizeEvent& event)
+{
+	Layout();
+	Fit();
+
+	event.Skip (false);
+}
+
+/*!
+ * Application instance declaration
+ */
+DECLARE_APP(TestWXApp)
+
+/*!
+ * TestWXApp type definition
+ */
+IMPLEMENT_CLASS( TestWXApp, wxApp )
+
+/*
+	Application instance implementation
+
+	we use IMPLEMENT_APP_NO_MAIN instead of IMPLEMENT_APP
+	because we define our own main
+ */
+IMPLEMENT_APP_NO_MAIN(TestWXApp)
+
+// ============================================================================
+// implementation
+// ============================================================================
+
+// ----------------------------------------------------------------------------
+// main frame
+// ----------------------------------------------------------------------------
+MyFrame::MyFrame()
+: wxFrame(NULL, wxID_ANY, _T(""), wxDefaultPosition, wxDefaultSize, wxCAPTION|wxSYSTEM_MENU|wxCLOSE_BOX)
+{
+
+}
+
+MyFrame* MyFrame::CreateAddPanel ( spcore::IComponent& component )
+{
+	MyFrame* mf= new MyFrame;
+	wxBoxSizer* sizer= new wxBoxSizer(wxVERTICAL);
+	mf->SetSizer(sizer);
+	wxWindow* pan= component.GetGUI(mf);
+	if (!pan) {
+		delete mf;
+		return NULL;
+	}
+	sizer->Add (static_cast<wxWindow*>(pan), 0, wxALIGN_CENTER_HORIZONTAL|wxALL, 0);
+	mf->GetSizer()->SetSizeHints(mf);	// Fit to content
+
+	return mf;
+}
+
+// ----------------------------------------------------------------------------
+// the application class
+// ----------------------------------------------------------------------------
+
+TestWXApp::TestWXApp() {
+}
+
+/*
+  Initialisation for TestWXApp
+
+  Return true to signal correct initialization or false when error
+ */
+bool TestWXApp::OnInit()
+{
+#if wxUSE_XPM
+	wxImage::AddHandler(new wxXPMHandler);
+#endif
+#if wxUSE_LIBPNG
+	wxImage::AddHandler(new wxPNGHandler);
+#endif
+#if wxUSE_LIBJPEG
+	wxImage::AddHandler(new wxJPEGHandler);
+#endif
+#if wxUSE_GIF
+	wxImage::AddHandler(new wxGIFHandler);
+#endif
+
+#if defined(WIN32)
+	// Uncomment this to enable a console in Windows for debug purposes
+	//AllocConsole(); freopen("CONOUT$", "wb", stdout);
+#endif
+
+	ICoreRuntime* cr= getSpCoreRuntime();
+
+	int retval= cr->LoadModule("D:/computing/builds/libsitplus/lib/Debug/mod_camera");
+	DumpCoreRuntime(cr);
+	if (retval!= 0)
+		ExitErr("error loading mod_camera");
+
+
+	// Create camera_config component
+	m_comp= cr->CreateComponent ("camera_config", "testcomponent", 0, NULL);
+	if (!m_comp.get())
+		ExitErr("error cannot create component");
+
+
+	// Create dialog
+	MyFrame* mf= MyFrame::CreateAddPanel ( *m_comp );
+	if (!mf) ExitErr("error error creating pannel");
+
+	mf->Show();
+
+	return true;
+}
+
+
+/*!
+  Cleanup for TestWXApp
+ */
+
+int TestWXApp::OnExit()
+{
+	return wxApp::OnExit();
+}
+
+// ----------------------------------------------------------------------------
+// main
+// ----------------------------------------------------------------------------
+
+int main(int argc, char *argv[]) {
+
+#if defined(__WXGTK__) || defined(__WXMOTIF__) || defined(__WXX11__)
+	// Under X11 it's necessary enable threading support
+	if ( XInitThreads() == 0 ) {
+		ExitErr("Unable to initialize multithreaded X11 code (XInitThreads failed)");
+		exit( EXIT_FAILURE );
+	}
+#endif
+
+	// Initialize spcore
+	ICoreRuntime* cr= getSpCoreRuntime();
+	if (!cr) return false;
+
+	// Run wxWidgets message pump
+	wxEntry(argc, argv);
+
+	// Free spcore
+	freeSpCoreRuntime();
+
+	// If execution reaches this => all tests ok
+	return 0;
+}
diff --git a/src/mod_camera/tests/test_mod_camera_rois.cpp b/src/mod_camera/tests/test_mod_camera_rois.cpp
new file mode 100644
index 0000000..c9943a1
--- /dev/null
+++ b/src/mod_camera/tests/test_mod_camera_rois.cpp
@@ -0,0 +1,188 @@
+/////////////////////////////////////////////////////////////////////////////
+// Name:        test_mod_camera_rois.cpp
+// Author:      Cesar Mauri Loba
+// Copyright:   (C) 2011 Cesar Mauri Loba - CREA Software Systems
+// 
+//  This program is free software: you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation, either version 3 of the License, or
+//  (at your option) any later version.
+//
+//  This program is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+/////////////////////////////////////////////////////////////////////////////
+
+
+#include "spcore/coreruntime.h"
+#include "sphost/testcommon.h"
+#include "nvwa/debug_new.h"
+
+#include "mod_camera/roitype.h"
+
+#include <ostream>
+#include <sstream>
+#include <iostream>
+#include <math.h>
+
+using namespace spcore;
+using namespace mod_camera;
+using namespace std;
+
+void dump_roi ( const CTypeROI& roi,  std::ostream& stream= std::cout, char const * tab = "")
+{
+	stream << tab << "X:" << roi.GetX() << std::endl;
+	stream << tab << "Y:" << roi.GetY() << std::endl;
+	stream << tab << "Width:" << roi.GetWidth() << std::endl;
+	stream << tab << "Height:" << roi.GetHeight() << std::endl;
+	stream << tab << "UseDirection:" << roi.GetUseDirection() << std::endl;
+	stream << tab << "Direction:" << roi.GetDirection() << std::endl;
+	stream << tab << "IsVisible:" << roi.GetIsVisible() << std::endl;
+	stream << tab << "IsEditable:" << roi.GetIsEditable() << std::endl;
+	stream << tab << "RegistrationId:" << roi.GetRegistrationId() << std::endl;
+
+	SmartPtr<spcore::IIterator<spcore::CTypeAny*> > it= roi.QueryChildren();
+	if (it.get()== NULL) ExitErr("CTypeROI cannot returna a NULL iterator");
+
+	string new_tab(tab);
+	new_tab.append("\t");
+	for (; !it->IsDone(); it->Next()) {
+		CTypeROI* child= sptype_dynamic_cast<CTypeROI>( it->CurrentItem());
+		if (!child) ExitErr("non CTypeROI type children found!");
+		dump_roi(*child, stream, new_tab.c_str());
+	}
+}
+
+bool areSimilar (float a, float b)
+{
+	if (a== b) return true;
+
+	if (fabs(a-b)< 0.0000001f) return true;
+
+	return false;
+}
+
+void test_rois()
+{
+	ICoreRuntime* cr= getSpCoreRuntime();
+
+	int retval= cr->LoadModule("spmod_camera");
+	DumpCoreRuntime(cr);
+	if (retval!= 0) 
+		ExitErr("error loading mod_camera");
+
+	//
+	// perform some foo tests
+	//
+
+	SmartPtr<CTypeROI> roi1= CTypeROI::CreateInstance();
+	roi1->SetUseDirection(true);	
+	roi1->SetDirection(10.0f);
+	roi1->SetIsVisible(true);	
+	roi1->SetIsEditable(true);
+	roi1->SetRegistrationId(10000);
+	dump_roi (*roi1);
+
+	if (!areSimilar(roi1->GetX(), 0.0f) || 
+		!areSimilar(roi1->GetY(), 0.0f) || 
+		!areSimilar(roi1->GetWidth(), 1.0f) || 
+		!areSimilar(roi1->GetHeight(), 1.0f)) ExitErr("ROI calculation error");
+	
+	// Without changing size, ROI shouldn't change
+	roi1->SetCenter(0.8f, 0.8f);
+	if (!areSimilar(roi1->GetX(), 0.0f) || 
+		!areSimilar(roi1->GetY(), 0.0f) || 
+		!areSimilar(roi1->GetWidth(), 1.0f) || 
+		!areSimilar(roi1->GetHeight(), 1.0f)) ExitErr("ROI calculation error");
+	
+	// Changing size only affects size
+	roi1->SetSize (0.5f, 0.5f);
+	if (!areSimilar(roi1->GetX(), 0.0f) || 
+		!areSimilar(roi1->GetY(), 0.0f) || 
+		!areSimilar(roi1->GetWidth(), 0.5f) || 
+		!areSimilar(roi1->GetHeight(), 0.5f)) ExitErr("ROI calculation error");
+	
+	roi1->SetCenter(0.9f, 0.9f);
+	if (!areSimilar(roi1->GetX(), 0.5f) || 
+		!areSimilar(roi1->GetY(), 0.5f) || 
+		!areSimilar(roi1->GetWidth(), 0.5f) || 
+		!areSimilar(roi1->GetHeight(), 0.5f)) ExitErr("ROI calculation error");
+	
+	roi1->SetCenter(-0.9f, -0.9f);
+	if (!areSimilar(roi1->GetX(), 0.0f) || 
+		!areSimilar(roi1->GetY(), 0.0f) || 
+		!areSimilar(roi1->GetWidth(), 0.5f) || 
+		!areSimilar(roi1->GetHeight(), 0.5f)) ExitErr("ROI calculation error");
+	dump_roi (*roi1);
+
+	//
+	// Composite
+	//
+	roi1->SetCenter(0.6f, 0.6f);
+	SmartPtr<CTypeInt> int1= CTypeInt::CreateInstance();
+	SmartPtr<CTypeROI> roi2= CTypeROI::CreateInstance();
+	SmartPtr<CTypeROI> roi3= CTypeROI::CreateInstance();
+	SmartPtr<CTypeROI> roi4= CTypeROI::CreateInstance();
+
+	if (roi1->AddChild(int1)== 0) ExitErr("non CTypeROI non allowed");
+	if (roi1->AddChild(roi2)== -1) ExitErr("AddChild failed");
+	if (roi1->AddChild(roi3)== -1) ExitErr("AddChild failed");
+	if (roi1->AddChild(roi3)== 0) ExitErr("adding the same child again not allowed");
+	if (roi2->AddChild(roi4)== -1) ExitErr("AddChild failed");
+
+	// check copy
+	SmartPtr<CTypeROI> roi5= CTypeROI::CreateInstance();
+
+	{
+		SmartPtr<CTypeAny> tmp= roi1->Clone(roi5.get(), true);
+		assert (tmp.get()== roi5.get());
+	}
+
+	std::stringstream result1;
+	std::stringstream result5;
+
+	dump_roi(*roi1, result1);
+	dump_roi(*roi5, result5);
+
+	if (result1.str().compare(result5.str())!= 0) ExitErr("composite copy error. results differ");
+	
+	SmartPtr<CTypeROI> roi6= CTypeROI::CreateInstance();
+	SmartPtr<CTypeROI> roi7= CTypeROI::CreateInstance();
+
+	if (roi5->AddChild(roi6)== -1) ExitErr("AddChild failed");
+	if (roi5->AddChild(roi7)== -1) ExitErr("AddChild failed");
+
+	{
+		SmartPtr<CTypeAny> tmp= roi1->Clone(roi5.get(), true);
+		assert (tmp.get()== roi5.get());
+	}
+
+	dump_roi(*roi1, result1);
+	dump_roi(*roi5, result5);
+
+	if (result1.str().compare(result5.str())!= 0) ExitErr("composite copy error. results differ");
+}
+
+
+// ----------------------------------------------------------------------------
+// main
+// ----------------------------------------------------------------------------
+
+int main(int, char *[]) {
+	
+	// Initialize spcore
+	ICoreRuntime* cr= getSpCoreRuntime();
+	if (!cr) return false;
+
+	test_rois();
+	
+	// Free spcore
+	freeSpCoreRuntime();
+
+	// If execution reaches this => all tests ok
+	return 0;
+}
diff --git a/src/mod_camera/tests/test_mod_camera_viewer.cpp b/src/mod_camera/tests/test_mod_camera_viewer.cpp
new file mode 100644
index 0000000..ba0ed98
--- /dev/null
+++ b/src/mod_camera/tests/test_mod_camera_viewer.cpp
@@ -0,0 +1,300 @@
+/////////////////////////////////////////////////////////////////////////////
+// Name:        test_mod_camera_viewer.cpp
+// Author:      Cesar Mauri Loba
+// Copyright:   (C) 2011 Cesar Mauri Loba - CREA Software Systems
+//
+//  This program is free software: you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation, either version 3 of the License, or
+//  (at your option) any later version.
+//
+//  This program is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+/////////////////////////////////////////////////////////////////////////////
+
+
+#include "spcore/coreruntime.h"
+#include "sphost/testcommon.h"
+#include "nvwa/debug_new.h"
+#include "mod_camera/roitype.h"
+
+#if defined(__WXGTK__) || defined(__WXMOTIF__) || defined(__WXX11__)
+	// Include Xlib for latter use on main
+	#include <X11/Xlib.h>
+#endif
+#include <wx/app.h>
+#include <wx/image.h>
+#include <wx/msgdlg.h>
+#include <wx/frame.h>
+#include <wx/panel.h>
+#include <wx/sizer.h>
+
+using namespace spcore;
+using namespace mod_camera;
+
+/*
+	Check threads enabled
+*/
+#if !wxUSE_THREADS
+     #error "This program requires thread support."
+#endif // wxUSE_THREADS
+
+/*
+	main app class
+*/
+class TestWXApp: public wxApp
+{
+	DECLARE_CLASS( TestWXApp )
+public:
+	TestWXApp();	// Constructor
+
+private:
+	virtual bool OnInit();	// Initialises the application
+	virtual int OnExit();	// Called on exit
+
+	SmartPtr<spcore::IComponent> m_comp;
+};
+
+/*
+	main frame class
+*/
+class MyFrame : public wxFrame
+{
+public:
+    MyFrame();
+	void OnCloseWindow( wxCloseEvent& event );
+	static MyFrame* CreateAddPanel ( spcore::IComponent& component );
+private:
+	void OnSize(wxSizeEvent& event);
+    // any class wishing to process wxWidgets events must use this macro
+    DECLARE_EVENT_TABLE()
+};
+
+/*
+	myframe event table
+*/
+BEGIN_EVENT_TABLE(MyFrame, wxFrame)
+	EVT_CLOSE( MyFrame::OnCloseWindow )
+	EVT_SIZE ( MyFrame::OnSize)
+END_EVENT_TABLE()
+
+void MyFrame::OnCloseWindow(wxCloseEvent &event)
+{
+	event.Skip(); // Equivalent to: wxFrame::OnCloseWindow(event);
+}
+
+void MyFrame::OnSize(wxSizeEvent& event)
+{
+	Layout();
+	Fit();
+
+	event.Skip (false);
+}
+
+
+/*!
+ * Application instance declaration
+ */
+DECLARE_APP(TestWXApp)
+
+/*!
+ * TestWXApp type definition
+ */
+IMPLEMENT_CLASS( TestWXApp, wxApp )
+
+/*
+	Application instance implementation
+
+	we use IMPLEMENT_APP_NO_MAIN instead of IMPLEMENT_APP
+	because we define our own main
+ */
+IMPLEMENT_APP_NO_MAIN(TestWXApp)
+
+// ============================================================================
+// implementation
+// ============================================================================
+
+// ----------------------------------------------------------------------------
+// main frame
+// ----------------------------------------------------------------------------
+MyFrame::MyFrame()
+: wxFrame(NULL, wxID_ANY, _T(""), wxDefaultPosition, wxDefaultSize, wxCAPTION|wxSYSTEM_MENU|wxCLOSE_BOX)
+{
+
+}
+
+MyFrame* MyFrame::CreateAddPanel ( spcore::IComponent& component )
+{
+	MyFrame* mf= new MyFrame;
+	wxBoxSizer* sizer= new wxBoxSizer(wxVERTICAL);
+	mf->SetSizer(sizer);
+	wxWindow* pan= component.GetGUI(mf);
+	if (!pan) {
+		delete mf;
+		return NULL;
+	}
+	sizer->Add (static_cast<wxWindow*>(pan), 0, wxALIGN_CENTER_HORIZONTAL|wxALL, 0);
+	mf->GetSizer()->SetSizeHints(mf);	// Fit to content
+
+	return mf;
+}
+
+// ----------------------------------------------------------------------------
+// the application class
+// ----------------------------------------------------------------------------
+
+TestWXApp::TestWXApp() {
+}
+
+/*
+  Initialisation for TestWXApp
+
+  Return true to signal correct initialization or false when error
+ */
+bool TestWXApp::OnInit()
+{
+#if wxUSE_XPM
+	wxImage::AddHandler(new wxXPMHandler);
+#endif
+#if wxUSE_LIBPNG
+	wxImage::AddHandler(new wxPNGHandler);
+#endif
+#if wxUSE_LIBJPEG
+	wxImage::AddHandler(new wxJPEGHandler);
+#endif
+#if wxUSE_GIF
+	wxImage::AddHandler(new wxGIFHandler);
+#endif
+
+#if defined(WIN32)
+	// Uncomment this to enable a console in Windows for debug purposes
+	//AllocConsole(); freopen("CONOUT$", "wb", stdout);
+#endif
+
+	ICoreRuntime* cr= getSpCoreRuntime();
+
+	int retval= cr->LoadModule("spmod_camera");
+	DumpCoreRuntime(cr);
+	if (retval!= 0)
+		ExitErr("error loading mod_camera");
+
+	// root_component
+	m_comp= cr->CreateComponent ("component_composer", "root_component", 0, NULL);
+	if (!m_comp.get()) ExitErr("error cannot create component");
+
+	// camera_grabber
+	SmartPtr<spcore::IComponent> grabber= cr->CreateComponent ("camera_grabber", "grabber", 0, NULL);
+	if (!grabber.get()) ExitErr("error cannot create grabber component");
+	retval= m_comp->AddChild(grabber);
+	if (retval!= 0) ExitErr("error adding grabber");
+
+	// camera_viewer
+	SmartPtr<spcore::IComponent> viewer= cr->CreateComponent ("camera_viewer", "viewer", 0, NULL);
+	if (!viewer.get()) ExitErr("error cannot create viewer component");
+	retval= m_comp->AddChild(viewer);
+	if (retval!= 0) ExitErr("error adding viewer");
+
+	// roi_storage
+	SmartPtr<spcore::IComponent> roi_storage= cr->CreateComponent ("roi_storage", "root_roi", 0, NULL);
+	if (!roi_storage.get()) ExitErr("error cannot create roi_storage component");
+	if (m_comp->AddChild(roi_storage)!= 0) ExitErr("error adding viewer");
+
+	// Connect pins
+	if (spcore::Connect (grabber.get(), "image", viewer.get(), "image")!= 0) ExitErr("cannot connect pins");
+	if (spcore::Connect (roi_storage.get(), "roi", viewer.get(), "roi")!= 0) ExitErr("cannot connect pins");
+	if (spcore::Connect (viewer.get(), "roi", roi_storage.get(), "roi")!= 0) ExitErr("cannot connect pins");
+
+	SmartPtr<CTypeROI> roi_root= CTypeROI::CreateInstance();
+	if (!roi_root.get()) ExitErr("cannot create ROI instance");
+
+
+	roi_root->SetSize (0.8f, 0.8f);
+	roi_root->SetCenter (0.5f, 0.5f);
+	//roi_root->SetIsEditable (true);
+	roi_root->SetIsVisible (true);
+	//roi_root->SetUseDirection(true);
+	roi_root->SetColor (0xFF0000);
+
+	SmartPtr<CTypeROI> roi2= CTypeROI::CreateInstance();
+	if (!roi2.get()) ExitErr("cannot create ROI instance");
+	roi2->SetSize(0.5f, 0.5f);
+	roi2->SetIsVisible(true);
+	roi2->SetIsEditable(true);
+	roi2->SetUseDirection(true);
+	roi2->SetColor(0x00FF00);
+	if (roi_root->AddChild(roi2)!= 0) ExitErr("cannot add child");
+
+	SmartPtr<CTypeROI> roi3= CTypeROI::CreateInstance();
+	if (!roi3.get()) ExitErr("cannot create ROI instance");
+	roi3->SetSize(0.3f, 0.3f);
+	roi3->SetIsVisible(true);
+	roi3->SetIsEditable(true);
+	roi3->SetUseDirection(false);
+	roi3->SetColor(0x0000FF);
+	if (roi_root->AddChild(roi3)!= 0) ExitErr("cannot add child");
+
+
+	spcore::IInputPin* ipin= IComponent::FindInputPin(*roi_storage, "roi");
+	if (!ipin) ExitErr("cannot find input pin");
+	ipin->Send (roi_root);
+
+
+	// Create dialog
+	MyFrame* mf= MyFrame::CreateAddPanel ( *viewer );
+	if (!mf) ExitErr("error error creating pannel");
+
+	mf->Show();
+
+	retval= m_comp->Initialize();
+	if (retval!= 0) ExitErr("initialization failed");
+	retval= m_comp->Start();
+	if (retval!= 0) ExitErr("start root component failed");
+
+	return true;
+}
+
+
+/*!
+  Cleanup for TestWXApp
+ */
+
+int TestWXApp::OnExit()
+{
+	m_comp->Stop();
+	m_comp->Finish();
+
+	return wxApp::OnExit();
+}
+
+// ----------------------------------------------------------------------------
+// main
+// ----------------------------------------------------------------------------
+
+int main(int argc, char *argv[]) {
+
+#if defined(__WXGTK__) || defined(__WXMOTIF__) || defined(__WXX11__)
+	// Under X11 it's necessary enable threading support
+	if ( XInitThreads() == 0 ) {
+		ExitErr("Unable to initialize multithreaded X11 code (XInitThreads failed)");
+		exit( EXIT_FAILURE );
+	}
+#endif
+
+	// Initialize spcore
+	ICoreRuntime* cr= getSpCoreRuntime();
+	if (!cr) return false;
+
+	// Run wxWidgets message pump
+	wxEntry(argc, argv);
+
+	// Free spcore
+	freeSpCoreRuntime();
+
+	// If execution reaches this => all tests ok
+	return 0;
+}
diff --git a/src/mod_camera/wcameraconfiguration.cpp b/src/mod_camera/wcameraconfiguration.cpp
new file mode 100644
index 0000000..17239c4
--- /dev/null
+++ b/src/mod_camera/wcameraconfiguration.cpp
@@ -0,0 +1,671 @@
+/////////////////////////////////////////////////////////////////////////////
+// Name:        wcameraconfiguration.cpp
+// Author:      Cesar Mauri Loba (cesar at crea-si dot com)
+// Copyright:   (C) 2011 Cesar Mauri Loba - CREA Software Systems
+//
+//  This program is free software: you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation, either version 3 of the License, or
+//  (at your option) any later version.
+//
+//  This program is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+/////////////////////////////////////////////////////////////////////////////
+
+#include "wcameraconfiguration.h"
+#include "wcamerapanel.h"
+#include "mod_camera/iplimagetype.h"
+
+////@begin includes
+////@end includes
+
+#include <wx/sizer.h>
+#include <wx/statbox.h>
+#include <wx/button.h>
+#include <wx/icon.h>
+#include <wx/msgdlg.h>
+#include <stdlib.h>
+
+////@begin XPM images
+////@end XPM images
+namespace mod_camera {
+
+using namespace spcore;
+
+/*!
+ * CCameraConfiguration type definition
+ */
+
+IMPLEMENT_DYNAMIC_CLASS( CCameraConfiguration, wxPanel )
+
+
+/*!
+ * CCameraConfiguration event table definition
+ */
+
+BEGIN_EVENT_TABLE( CCameraConfiguration, wxPanel )
+
+////@begin CCameraConfiguration event table entries
+    EVT_CHOICE( ID_CHOICE_SELECTED_CAMERA, CCameraConfiguration::OnChoiceSelectedCameraSelected )
+
+    EVT_CHOICE( ID_CHOICE_FORMAT, CCameraConfiguration::OnChoiceFormatSelected )
+
+    EVT_CHOICE( ID_CHOICE_FPS, CCameraConfiguration::OnChoiceFpsSelected )
+
+    EVT_BUTTON( ID_BUTTON_DRIVER_SETTINGS, CCameraConfiguration::OnButtonDriverSettingsClick )
+
+    EVT_CHECKBOX( ID_CHECKBOX_MIRROR_IMAGE, CCameraConfiguration::OnCheckboxMirrorImageClick )
+
+    EVT_BUTTON( ID_BUTTON_CLOSE_CCONFIG, CCameraConfiguration::OnButtonCloseCconfigClick )
+
+////@end CCameraConfiguration event table entries
+
+END_EVENT_TABLE()
+
+
+/*!
+ * CCameraConfiguration constructors
+ */
+
+CCameraConfiguration::CCameraConfiguration()
+{
+    Init();
+}
+
+CCameraConfiguration::CCameraConfiguration( wxWindow* parent, wxWindowID id, const wxPoint& pos, const wxSize& size, long style, const wxString& name )
+{
+    Init();
+    Create(parent, id, pos, size, style, name);
+}
+
+
+/*!
+ * CCameraConfiguration creator
+ */
+
+bool CCameraConfiguration::Create( wxWindow* parent, wxWindowID id, const wxPoint& pos, const wxSize& size, long style, const wxString& name )
+{
+////@begin CCameraConfiguration creation
+    SetExtraStyle(wxWS_EX_BLOCK_EVENTS);
+    wxPanel::Create( parent, id, pos, size, style, name );
+
+    CreateControls();
+    if (GetSizer())
+    {
+        GetSizer()->SetSizeHints(this);
+    }
+    Centre();
+////@end CCameraConfiguration creation
+    return true;
+}
+
+
+/*!
+ * CCameraConfiguration destructor
+ */
+
+CCameraConfiguration::~CCameraConfiguration()
+{
+	m_cameraConfig->UnregisterListener (*this);
+////@begin CCameraConfiguration destruction
+////@end CCameraConfiguration destruction
+}
+
+
+/*!
+ * Member initialisation
+ */
+
+void CCameraConfiguration::Init()
+{
+////@begin CCameraConfiguration member initialisation
+    m_camPanel = NULL;
+    m_choSelectedCamera = NULL;
+    m_choFormat = NULL;
+    m_choFPS = NULL;
+    m_chkMirrorImage = NULL;
+////@end CCameraConfiguration member initialisation
+}
+
+
+/*!
+ * Control creation for CCameraConfiguration
+ */
+
+void CCameraConfiguration::CreateControls()
+{
+////@begin CCameraConfiguration content construction
+    CCameraConfiguration* itemPanel1 = this;
+
+    wxBoxSizer* itemBoxSizer2 = new wxBoxSizer(wxVERTICAL);
+    itemPanel1->SetSizer(itemBoxSizer2);
+
+    wxStaticBox* itemStaticBoxSizer3Static = new wxStaticBox(itemPanel1, wxID_ANY, wxEmptyString);
+    wxStaticBoxSizer* itemStaticBoxSizer3 = new wxStaticBoxSizer(itemStaticBoxSizer3Static, wxVERTICAL);
+    itemBoxSizer2->Add(itemStaticBoxSizer3, 0, wxALIGN_CENTER_HORIZONTAL|wxALL, 5);
+
+    m_camPanel = new CameraPanel;
+    m_camPanel->Create( itemPanel1, ID_PANEL_CAMERA, wxDefaultPosition, wxSize(320, 240), wxSUNKEN_BORDER|wxTAB_TRAVERSAL );
+    itemStaticBoxSizer3->Add(m_camPanel, 0, wxALIGN_CENTER_HORIZONTAL|wxALL, 5);
+
+    wxStaticBox* itemStaticBoxSizer5Static = new wxStaticBox(itemPanel1, wxID_ANY, _("Camera properties"));
+    wxStaticBoxSizer* itemStaticBoxSizer5 = new wxStaticBoxSizer(itemStaticBoxSizer5Static, wxVERTICAL);
+    itemStaticBoxSizer3->Add(itemStaticBoxSizer5, 0, wxGROW|wxALL, 5);
+
+    wxFlexGridSizer* itemFlexGridSizer6 = new wxFlexGridSizer(0, 2, 0, 0);
+    itemFlexGridSizer6->AddGrowableCol(1);
+    itemStaticBoxSizer5->Add(itemFlexGridSizer6, 0, wxGROW|wxALL, 5);
+
+    wxStaticText* itemStaticText7 = new wxStaticText;
+    itemStaticText7->Create( itemPanel1, wxID_STATIC, _("Selected camera:"), wxDefaultPosition, wxDefaultSize, 0 );
+    itemFlexGridSizer6->Add(itemStaticText7, 0, wxALIGN_LEFT|wxALIGN_CENTER_VERTICAL|wxALL, 5);
+
+    wxArrayString m_choSelectedCameraStrings;
+    m_choSelectedCamera = new wxChoice;
+    m_choSelectedCamera->Create( itemPanel1, ID_CHOICE_SELECTED_CAMERA, wxDefaultPosition, wxDefaultSize, m_choSelectedCameraStrings, 0 );
+    itemFlexGridSizer6->Add(m_choSelectedCamera, 0, wxGROW|wxALIGN_CENTER_VERTICAL|wxALL, 5);
+
+    wxStaticText* itemStaticText9 = new wxStaticText;
+    itemStaticText9->Create( itemPanel1, wxID_STATIC, _("Format:"), wxDefaultPosition, wxDefaultSize, 0 );
+    itemFlexGridSizer6->Add(itemStaticText9, 0, wxALIGN_LEFT|wxALIGN_CENTER_VERTICAL|wxALL, 5);
+
+    wxArrayString m_choFormatStrings;
+    m_choFormat = new wxChoice;
+    m_choFormat->Create( itemPanel1, ID_CHOICE_FORMAT, wxDefaultPosition, wxDefaultSize, m_choFormatStrings, 0 );
+    itemFlexGridSizer6->Add(m_choFormat, 0, wxGROW|wxALIGN_CENTER_VERTICAL|wxALL, 5);
+
+    wxStaticText* itemStaticText11 = new wxStaticText;
+    itemStaticText11->Create( itemPanel1, wxID_STATIC, _("Capture speed:"), wxDefaultPosition, wxDefaultSize, 0 );
+    itemFlexGridSizer6->Add(itemStaticText11, 0, wxALIGN_LEFT|wxALIGN_CENTER_VERTICAL|wxALL, 5);
+
+    wxArrayString m_choFPSStrings;
+    m_choFPS = new wxChoice;
+    m_choFPS->Create( itemPanel1, ID_CHOICE_FPS, wxDefaultPosition, wxDefaultSize, m_choFPSStrings, 0 );
+    itemFlexGridSizer6->Add(m_choFPS, 0, wxGROW|wxALIGN_CENTER_VERTICAL|wxALL, 5);
+
+    wxStaticText* itemStaticText13 = new wxStaticText;
+    itemStaticText13->Create( itemPanel1, wxID_STATIC, _("Driver settings:"), wxDefaultPosition, wxDefaultSize, 0 );
+    itemFlexGridSizer6->Add(itemStaticText13, 0, wxALIGN_LEFT|wxALIGN_CENTER_VERTICAL|wxALL, 5);
+
+    wxButton* itemButton14 = new wxButton;
+    itemButton14->Create( itemPanel1, ID_BUTTON_DRIVER_SETTINGS, _("Open driver settings"), wxDefaultPosition, wxDefaultSize, 0 );
+    itemFlexGridSizer6->Add(itemButton14, 0, wxGROW|wxALIGN_CENTER_VERTICAL|wxALL, 5);
+
+    wxStaticText* itemStaticText15 = new wxStaticText;
+    itemStaticText15->Create( itemPanel1, wxID_STATIC, _("Image mirror:"), wxDefaultPosition, wxDefaultSize, 0 );
+    itemFlexGridSizer6->Add(itemStaticText15, 0, wxALIGN_LEFT|wxALIGN_CENTER_VERTICAL|wxALL, 5);
+
+    m_chkMirrorImage = new wxCheckBox;
+    m_chkMirrorImage->Create( itemPanel1, ID_CHECKBOX_MIRROR_IMAGE, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 );
+    m_chkMirrorImage->SetValue(false);
+    itemFlexGridSizer6->Add(m_chkMirrorImage, 0, wxALIGN_LEFT|wxALIGN_CENTER_VERTICAL|wxALL, 5);
+
+    wxButton* itemButton17 = new wxButton;
+    itemButton17->Create( itemPanel1, ID_BUTTON_CLOSE_CCONFIG, _("Close"), wxDefaultPosition, wxDefaultSize, 0 );
+    itemBoxSizer2->Add(itemButton17, 0, wxALIGN_CENTER_HORIZONTAL|wxALL, 5);
+
+////@end CCameraConfiguration content construction
+
+	m_cameraConfig= smartptr_dynamic_cast<CameraConfig,IComponent>(
+		getSpCoreRuntime()->CreateComponent("camera_config", "camera_config", 0, NULL));
+
+	if (!m_cameraConfig.get()) {
+		getSpCoreRuntime()->LogMessage(ICoreRuntime::LOG_FATAL, "cannot create camera_config module", "mod_camera");
+	}
+	m_cameraConfig->RegisterListener (*this);
+
+	PopulateControls();
+
+}
+
+IInputPin* CCameraConfiguration::GetCamerasPin()
+{
+	IInputPin* iPin= IComponent::FindInputPin(*m_cameraConfig, "cameras");
+	if (!iPin) {
+		getSpCoreRuntime()->LogMessage(ICoreRuntime::LOG_ERROR, "cameras pin not found", "mod_camera");
+		return NULL;
+	}
+
+	assert (iPin->GetProperties() & IInputPin::ALLOW_READ);
+	return iPin;
+}
+
+IInputPin* CCameraConfiguration::GetSelectedCameraPin()
+{
+	IInputPin* iPin= IComponent::FindInputPin(*m_cameraConfig, "selected_camera");
+	if (!iPin) {
+		getSpCoreRuntime()->LogMessage(ICoreRuntime::LOG_ERROR, "selected_camera pin not found", "mod_camera");
+		return NULL;
+	}
+
+	assert ((iPin->GetProperties() & IInputPin::ALLOW_READ) && (iPin->GetProperties() & IInputPin::ALLOW_WRITE));
+	return iPin;
+}
+
+IInputPin* CCameraConfiguration::GetCaptureParametersPin()
+{
+	IInputPin* iPin= IComponent::FindInputPin(*m_cameraConfig, "capture_parameters");
+	if (!iPin) {
+		getSpCoreRuntime()->LogMessage(ICoreRuntime::LOG_ERROR, "capture_parameters pin not found", "mod_camera");
+		return NULL;
+	}
+
+	assert ((iPin->GetProperties() & IInputPin::ALLOW_READ) && (iPin->GetProperties() & IInputPin::ALLOW_WRITE));
+	return iPin;
+}
+
+IInputPin* CCameraConfiguration::GetMirrorEffectPin()
+{
+	IInputPin* iPin= IComponent::FindInputPin(*m_cameraConfig, "mirror_image");
+	if (!iPin) {
+		getSpCoreRuntime()->LogMessage(ICoreRuntime::LOG_ERROR, "mirror_image pin not found", "mod_camera");
+		return NULL;
+	}
+	assert ((iPin->GetProperties() & IInputPin::ALLOW_READ) && (iPin->GetProperties() & IInputPin::ALLOW_WRITE));
+
+	return iPin;
+}
+
+IInputPin* CCameraConfiguration::GetSettingsDialogPin()
+{
+	IInputPin* iPin= IComponent::FindInputPin(*m_cameraConfig, "settings_dialog");
+	if (!iPin) {
+		getSpCoreRuntime()->LogMessage(ICoreRuntime::LOG_ERROR, "settings_dialog pin not found", "mod_camera");
+		return NULL;
+	}
+	assert (iPin->GetProperties() & IInputPin::ALLOW_WRITE);
+
+	return iPin;
+}
+
+
+
+void CCameraConfiguration::PopulateControls()
+{
+	//
+	// cameras
+	//
+	IInputPin* iPin= GetCamerasPin();
+	if (!iPin) return;
+	SmartPtr<const CTypeAny> cameras= iPin->Read();
+	if (cameras.get()== NULL) {
+		getSpCoreRuntime()->LogMessage(ICoreRuntime::LOG_ERROR, "error reading cameras pin", "mod_camera");
+		return;
+	}
+
+	SmartPtr<IIterator<CTypeAny*> > camerasIt= cameras->QueryChildren();
+	if (camerasIt.get()== NULL) {
+		getSpCoreRuntime()->LogMessage(ICoreRuntime::LOG_ERROR, "error reading cameras iterator", "mod_camera");
+		return;
+	}
+
+	m_choSelectedCamera->Clear();
+	for(camerasIt->First(); !camerasIt->IsDone(); camerasIt->Next()) {
+		SmartPtr<CTypeString> str= sptype_dynamic_cast<CTypeString>(SmartPtr<CTypeAny>(camerasIt->CurrentItem()));
+		if (!str.get()) {
+			getSpCoreRuntime()->LogMessage(ICoreRuntime::LOG_ERROR, "type mismatch enumerating cameras", "mod_camera");
+			return;
+		}
+		m_choSelectedCamera->Append (wxString(str->getValue(), wxConvUTF8));
+	}
+
+	if (m_choSelectedCamera->GetCount()== 0) {
+		wxMessageDialog dlg(this, _("Not detected any camera"), _("Camera module"), wxICON_EXCLAMATION | wxOK);
+		dlg.ShowModal();
+		return;
+	}
+
+	//
+	// selected camera
+	//
+	iPin= GetSelectedCameraPin();
+	if (!iPin) return;
+	SmartPtr<const CTypeInt> selected_camera= sptype_dynamic_cast<const CTypeInt>(SmartPtr<const CTypeAny>(iPin->Read()));
+	if (selected_camera.get()== NULL) {
+		getSpCoreRuntime()->LogMessage(ICoreRuntime::LOG_ERROR, "error reading selected_camera pin", "mod_camera");
+		return;
+	}
+
+	if (selected_camera->getValue()>= 0) {
+		if (static_cast<unsigned int>(selected_camera->getValue())>= m_choSelectedCamera->GetCount())
+			getSpCoreRuntime()->LogMessage(ICoreRuntime::LOG_ERROR, "wrong selected_camera value", "mod_camera");
+		else
+			m_choSelectedCamera->SetSelection(selected_camera->getValue());
+	}
+
+	//
+	// capture parameters
+	//
+	iPin= GetCaptureParametersPin();
+	if (!iPin) return;
+	SmartPtr<const CTypeAny> capture_parameters= iPin->Read();
+	if (capture_parameters.get()== NULL) {
+		getSpCoreRuntime()->LogMessage(ICoreRuntime::LOG_ERROR, "error reading capture_parameters pin", "mod_camera");
+		return;
+	}
+
+	SmartPtr<IIterator<CTypeAny*> > capture_parametersIt= capture_parameters->QueryChildren();
+	if (capture_parametersIt.get()== NULL) {
+		getSpCoreRuntime()->LogMessage(ICoreRuntime::LOG_ERROR, "error reading capture_parameters iterator", "mod_camera");
+		return;
+	}
+
+	int width= -1;
+	if (!capture_parametersIt->IsDone()) {
+		SmartPtr<const CTypeInt> sptr_width= sptype_dynamic_cast<const CTypeInt>(SmartPtr<const CTypeAny>(capture_parametersIt->CurrentItem()));
+		if (sptr_width.get()== NULL) {
+			getSpCoreRuntime()->LogMessage(ICoreRuntime::LOG_ERROR, "error reading capture_parameters width", "mod_camera");
+			return;
+		}
+		width= sptr_width->getValue();
+	}
+	else {
+		getSpCoreRuntime()->LogMessage(ICoreRuntime::LOG_ERROR, "unexpected capture_parameters message format (1)", "mod_camera");
+		return;
+	}
+
+	int height= -1;
+	capture_parametersIt->Next();
+	if (!capture_parametersIt->IsDone()) {
+		SmartPtr<const CTypeInt> sptr_height= sptype_dynamic_cast<const CTypeInt>(SmartPtr<const CTypeAny>(capture_parametersIt->CurrentItem()));
+		if (sptr_height.get()== NULL) {
+			getSpCoreRuntime()->LogMessage(ICoreRuntime::LOG_ERROR, "error reading capture_parameters height", "mod_camera");
+			return;
+		}
+		height= sptr_height->getValue();
+	}
+	else {
+		getSpCoreRuntime()->LogMessage(ICoreRuntime::LOG_ERROR, "unexpected capture_parameters message format (2)", "mod_camera");
+		return;
+	}
+
+	assert (width> 0 && height> 0);
+
+	// set up pre-defined values for image size
+	// TODO: obtain the actual parameters from the camera
+	m_choFormat->Clear();
+	m_choFormat->Append (_T("160x120"));
+	m_choFormat->Append (_T("320x240"));
+	m_choFormat->Append (_T("640x480"));
+
+	// choose the closest image size
+	int max_diff= abs(640*480 - width*height);
+	int choice= 2;
+
+	if (abs(320*240 - width*height)< max_diff) {
+		max_diff= abs(320*240 - width*height);
+		choice= 1;
+	}
+
+	if (abs(160*120 - width*height)< max_diff) {
+		choice= 0;
+	}
+	m_choFormat->SetSelection(choice);
+
+	// frame rate
+	int fps= -1;
+	capture_parametersIt->Next();
+	if (!capture_parametersIt->IsDone()) {
+		SmartPtr<const CTypeInt> sptr_fps= sptype_dynamic_cast<const CTypeInt>(SmartPtr<const CTypeAny>(capture_parametersIt->CurrentItem()));
+		if (sptr_fps.get()== NULL) {
+			getSpCoreRuntime()->LogMessage(ICoreRuntime::LOG_ERROR, "error reading capture_parameters fps", "mod_camera");
+			return;
+		}
+		fps= sptr_fps->getValue();
+	}
+	else {
+		getSpCoreRuntime()->LogMessage(ICoreRuntime::LOG_ERROR, "unexpected capture_parameters message format (3)", "mod_camera");
+		return;
+	}
+	assert (fps> 0);
+
+	// set up pre-defined values for frame rate
+	// TODO: obtain the actual parameters from the camera
+	m_choFPS->Clear();
+	m_choFPS->Append (_T("5"));
+	m_choFPS->Append (_T("10"));
+	m_choFPS->Append (_T("15"));
+	m_choFPS->Append (_T("20"));
+	m_choFPS->Append (_T("25"));
+	m_choFPS->Append (_T("30"));
+
+	// select closest value
+	max_diff= abs(30 - fps);
+	choice= 5;
+
+	if (abs(25 - fps)< max_diff) {
+		max_diff= abs(25 - fps);
+		choice= 4;
+	}
+
+	if (abs(20 - fps)< max_diff) {
+		max_diff= abs(20 - fps);
+		choice= 3;
+	}
+
+	if (abs(15 - fps)< max_diff) {
+		max_diff= abs(15 - fps);
+		choice= 2;
+	}
+
+	if (abs(10 - fps)< max_diff) {
+		max_diff= abs(10 - fps);
+		choice= 1;
+	}
+
+	if (abs(5 - fps)< max_diff) {
+		max_diff= abs(5 - fps);
+		choice= 0;
+	}
+
+	m_choFPS->SetSelection (choice);
+
+	// mirror effect
+	//
+	iPin= GetMirrorEffectPin();
+	if (!iPin) return;
+	SmartPtr<const CTypeBool> mirror_image= sptype_dynamic_cast<const CTypeBool>(SmartPtr<const CTypeAny>(iPin->Read()));
+	if (mirror_image.get()== NULL) {
+		getSpCoreRuntime()->LogMessage(ICoreRuntime::LOG_ERROR, "error reading mirror_image pin", "mod_camera");
+		return;
+	}
+
+	m_chkMirrorImage->SetValue(mirror_image->getValue());
+}
+
+/*!
+ * wxEVT_COMMAND_CHOICE_SELECTED event handler for ID_CHOICE_SELECTED_CAMERA
+ */
+
+void CCameraConfiguration::OnChoiceSelectedCameraSelected( wxCommandEvent& event )
+{
+	IInputPin* iPin= GetSelectedCameraPin();
+	if (!iPin) return;
+
+	SmartPtr<CTypeInt> value= CTypeInt::CreateInstance();
+	value->setValue(event.GetSelection());
+	iPin->Send (value);
+
+    event.Skip(false);
+}
+
+/*!
+ * wxEVT_COMMAND_CHOICE_SELECTED event handler for ID_CHOICE_FORMAT
+ */
+
+void CCameraConfiguration::OnChoiceFormatSelected( wxCommandEvent& event )
+{
+	IInputPin* iPin= GetCaptureParametersPin();
+	if (!iPin) return;
+	SmartPtr<const CTypeAny> capture_parameters= iPin->Read();
+	if (capture_parameters.get()== NULL) {
+		getSpCoreRuntime()->LogMessage(ICoreRuntime::LOG_ERROR, "error reading capture_parameters pin", "mod_camera");
+		return;
+	}
+
+	SmartPtr<IIterator<CTypeAny*> > capture_parametersIt= capture_parameters->QueryChildren();
+	if (capture_parametersIt.get()== NULL) {
+		getSpCoreRuntime()->LogMessage(ICoreRuntime::LOG_ERROR, "error reading capture_parameters iterator", "mod_camera");
+		return;
+	}
+
+	int width= -1, height= -1;
+	switch (event.GetSelection()) {
+	case 0: width= 160; height= 120; break;
+	case 1: width= 320; height= 240; break;
+	case 2: width= 640; height= 480; break;
+	}
+
+	if (capture_parametersIt->IsDone()) return;
+
+	// TODO: add const iterators which must prevent doing things like this
+	sptype_dynamic_cast<CTypeInt>(SmartPtr<CTypeAny>(capture_parametersIt->CurrentItem()))->setValue(width);
+
+	capture_parametersIt->Next();
+
+	if (capture_parametersIt->IsDone()) return;
+
+	sptype_dynamic_cast<CTypeInt>(SmartPtr<CTypeAny>(capture_parametersIt->CurrentItem()))->setValue(height);
+
+	iPin->Send (capture_parameters);
+
+	event.Skip(false);
+}
+
+/*!
+ * wxEVT_COMMAND_CHOICE_SELECTED event handler for ID_CHOICE_FPS
+ */
+
+void CCameraConfiguration::OnChoiceFpsSelected( wxCommandEvent& event )
+{
+	IInputPin* iPin= GetCaptureParametersPin();
+	if (!iPin) return;
+	SmartPtr<const CTypeAny> capture_parameters= iPin->Read();
+	if (capture_parameters.get()== NULL) {
+		getSpCoreRuntime()->LogMessage(ICoreRuntime::LOG_ERROR, "error reading capture_parameters pin", "mod_camera");
+		return;
+	}
+
+	SmartPtr<IIterator<CTypeAny*> > capture_parametersIt= capture_parameters->QueryChildren();
+	if (capture_parametersIt.get()== NULL) {
+		getSpCoreRuntime()->LogMessage(ICoreRuntime::LOG_ERROR, "error reading capture_parameters iterator", "mod_camera");
+		return;
+	}
+
+	int fps= event.GetSelection() * 5 + 5;
+
+	if (capture_parametersIt->IsDone()) return;
+	capture_parametersIt->Next();
+	if (capture_parametersIt->IsDone()) return;
+	capture_parametersIt->Next();
+	if (capture_parametersIt->IsDone()) return;
+
+	// TODO: add const iterators which must prevent doing things like this
+	sptype_dynamic_cast<CTypeInt>(SmartPtr<CTypeAny>(capture_parametersIt->CurrentItem()))->setValue(fps);
+
+	iPin->Send (capture_parameters);
+
+    event.Skip(false);
+}
+
+/*!
+ * wxEVT_COMMAND_CHECKBOX_CLICKED event handler for ID_CHECKBOX_MIRROR_IMAGE
+ */
+
+void CCameraConfiguration::OnCheckboxMirrorImageClick( wxCommandEvent& event )
+{
+	IInputPin* iPin= GetMirrorEffectPin();
+	if (!iPin) return;
+
+	SmartPtr<CTypeBool> value= CTypeBool::CreateInstance();
+
+	value->setValue(event.IsChecked());
+
+	iPin->Send(value);
+
+    event.Skip(false);
+}
+
+
+/*!
+ * wxEVT_COMMAND_BUTTON_CLICKED event handler for ID_BUTTON_PROPERTIES
+ */
+
+void CCameraConfiguration::OnButtonDriverSettingsClick( wxCommandEvent& event )
+{
+	IInputPin * iPin= GetSettingsDialogPin();
+	if (!iPin) return;
+
+	SmartPtr<CTypeBool> value= CTypeBool::CreateInstance();
+	iPin->Send(value);
+
+    event.Skip(false);
+}
+
+
+void CCameraConfiguration::CameraCaptureCallback (SmartPtr<const CTypeIplImage> img)
+{
+	m_camPanel->DrawCam(img->getImage());
+}
+
+
+
+/*!
+ * wxEVT_COMMAND_BUTTON_CLICKED event handler for ID_BUTTON_CLOSE_CCONFIG
+ */
+
+void CCameraConfiguration::OnButtonCloseCconfigClick( wxCommandEvent& event )
+{
+	wxWindow* parent= GetParent();
+
+	assert (parent);
+	if (parent) parent->Close();
+
+    event.Skip(false);
+}
+
+
+/*!
+ * Should we show tooltips?
+ */
+
+bool CCameraConfiguration::ShowToolTips()
+{
+    return true;
+}
+
+/*!
+ * Get bitmap resources
+ */
+
+wxBitmap CCameraConfiguration::GetBitmapResource( const wxString& name )
+{
+    // Bitmap retrieval
+////@begin CCameraConfiguration bitmap retrieval
+    wxUnusedVar(name);
+    return wxNullBitmap;
+////@end CCameraConfiguration bitmap retrieval
+}
+
+/*!
+ * Get icon resources
+ */
+
+wxIcon CCameraConfiguration::GetIconResource( const wxString& name )
+{
+    // Icon retrieval
+////@begin CCameraConfiguration icon retrieval
+    wxUnusedVar(name);
+    return wxNullIcon;
+////@end CCameraConfiguration icon retrieval
+}
+
+
+
+
+}
diff --git a/src/mod_camera/wcameraconfiguration.h b/src/mod_camera/wcameraconfiguration.h
new file mode 100755
index 0000000..51c1dc2
--- /dev/null
+++ b/src/mod_camera/wcameraconfiguration.h
@@ -0,0 +1,152 @@
+/////////////////////////////////////////////////////////////////////////////
+// Name:        wcameraconfiguration.h
+// Author:      Cesar Mauri Loba (cesar at crea-si dot com)
+// Copyright:   (C) 2011 Cesar Mauri Loba - CREA Software Systems
+// 
+//  This program is free software: you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation, either version 3 of the License, or
+//  (at your option) any later version.
+//
+//  This program is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+/////////////////////////////////////////////////////////////////////////////
+
+#ifndef _WCAMERACONFIGURATION_H_
+#define _WCAMERACONFIGURATION_H_
+
+
+/*!
+ * Includes
+ */
+
+#include "mod_camera.h"
+////@begin includes
+////@end includes
+#include <wx/panel.h>
+#include <wx/stattext.h>
+#include <wx/choice.h>
+#include <wx/checkbox.h>
+
+namespace mod_camera {
+
+/*!
+ * Forward declarations
+ */
+
+////@begin forward declarations
+class CameraPanel;
+////@end forward declarations
+
+/*!
+ * Control identifiers
+ */
+
+////@begin control identifiers
+#define ID_CCAMERACONFIGURATION 10060
+#define ID_PANEL_CAMERA 10061
+#define ID_CHOICE_SELECTED_CAMERA 10000
+#define ID_CHOICE_FORMAT 10001
+#define ID_CHOICE_FPS 10002
+#define ID_BUTTON_DRIVER_SETTINGS 10064
+#define ID_CHECKBOX_MIRROR_IMAGE 10003
+#define ID_BUTTON_CLOSE_CCONFIG 10065
+#define SYMBOL_CCAMERACONFIGURATION_STYLE wxCAPTION|wxTAB_TRAVERSAL
+#define SYMBOL_CCAMERACONFIGURATION_TITLE _("Camera Configuration")
+#define SYMBOL_CCAMERACONFIGURATION_IDNAME ID_CCAMERACONFIGURATION
+#define SYMBOL_CCAMERACONFIGURATION_SIZE wxDefaultSize
+#define SYMBOL_CCAMERACONFIGURATION_POSITION wxDefaultPosition
+////@end control identifiers
+//#define SYMBOL_CCAMERACONFIGURATION_STYLE wxCAPTION|wxRESIZE_BORDER|wxSYSTEM_MENU|wxCLOSE_BOX|wxTAB_TRAVERSAL
+
+/*!
+ * CCameraConfiguration class declaration
+ */
+
+class CCameraConfiguration: public wxPanel, protected mod_camera::CameraCaptureListener
+{    
+    DECLARE_DYNAMIC_CLASS( CCameraConfiguration )
+    DECLARE_EVENT_TABLE()
+
+public:
+    /// Constructors
+    CCameraConfiguration();
+    CCameraConfiguration( wxWindow* parent, wxWindowID id = SYMBOL_CCAMERACONFIGURATION_IDNAME, const wxPoint& pos = SYMBOL_CCAMERACONFIGURATION_POSITION, const wxSize& size = SYMBOL_CCAMERACONFIGURATION_SIZE, long style = SYMBOL_CCAMERACONFIGURATION_STYLE, const wxString& name= SYMBOL_CCAMERACONFIGURATION_TITLE );
+
+    /// Creation
+    bool Create( wxWindow* parent, wxWindowID id = SYMBOL_CCAMERACONFIGURATION_IDNAME, const wxPoint& pos = SYMBOL_CCAMERACONFIGURATION_POSITION, const wxSize& size = SYMBOL_CCAMERACONFIGURATION_SIZE, long style = SYMBOL_CCAMERACONFIGURATION_STYLE, const wxString& name= SYMBOL_CCAMERACONFIGURATION_TITLE );
+
+    /// Destructor
+    ~CCameraConfiguration();
+
+protected:
+	virtual void CameraCaptureCallback (SmartPtr<const mod_camera::CTypeIplImage> img);
+
+private:
+    /// Initialises member variables
+    void Init();
+
+    /// Creates the controls and sizers
+    void CreateControls();
+
+////@begin CCameraConfiguration event handler declarations
+
+    /// wxEVT_COMMAND_CHOICE_SELECTED event handler for ID_CHOICE_SELECTED_CAMERA
+    void OnChoiceSelectedCameraSelected( wxCommandEvent& event );
+
+    /// wxEVT_COMMAND_CHOICE_SELECTED event handler for ID_CHOICE_FORMAT
+    void OnChoiceFormatSelected( wxCommandEvent& event );
+
+    /// wxEVT_COMMAND_CHOICE_SELECTED event handler for ID_CHOICE_FPS
+    void OnChoiceFpsSelected( wxCommandEvent& event );
+
+    /// wxEVT_COMMAND_BUTTON_CLICKED event handler for ID_BUTTON_DRIVER_SETTINGS
+    void OnButtonDriverSettingsClick( wxCommandEvent& event );
+
+    /// wxEVT_COMMAND_CHECKBOX_CLICKED event handler for ID_CHECKBOX_MIRROR_IMAGE
+    void OnCheckboxMirrorImageClick( wxCommandEvent& event );
+
+    /// wxEVT_COMMAND_BUTTON_CLICKED event handler for ID_BUTTON_CLOSE_CCONFIG
+    void OnButtonCloseCconfigClick( wxCommandEvent& event );
+
+////@end CCameraConfiguration event handler declarations
+
+////@begin CCameraConfiguration member function declarations
+
+    /// Retrieves bitmap resources
+    wxBitmap GetBitmapResource( const wxString& name );
+
+    /// Retrieves icon resources
+    wxIcon GetIconResource( const wxString& name );
+////@end CCameraConfiguration member function declarations
+
+    /// Should we show tooltips?
+    static bool ShowToolTips();
+
+	void PopulateControls();
+
+	spcore::IInputPin* GetCamerasPin();
+	spcore::IInputPin* GetSelectedCameraPin();
+	spcore::IInputPin* GetCaptureParametersPin();
+	spcore::IInputPin* GetMirrorEffectPin();
+	spcore::IInputPin* GetSettingsDialogPin();
+
+////@begin CCameraConfiguration member variables
+    CameraPanel* m_camPanel;
+    wxChoice* m_choSelectedCamera;
+    wxChoice* m_choFormat;
+    wxChoice* m_choFPS;
+    wxCheckBox* m_chkMirrorImage;
+////@end CCameraConfiguration member variables
+	SmartPtr<mod_camera::CameraConfig> m_cameraConfig;
+};
+
+}
+
+#endif
+    // _WCAMERACONFIGURATION_H_
diff --git a/src/mod_camera/wcamerapanel.cpp b/src/mod_camera/wcamerapanel.cpp
new file mode 100755
index 0000000..07e53db
--- /dev/null
+++ b/src/mod_camera/wcamerapanel.cpp
@@ -0,0 +1,353 @@
+/////////////////////////////////////////////////////////////////////////////
+// Name:        wcamerapanel.cpp
+// Purpose:		wxPanel derived class to show live camera image
+// Author:      Cesar Mauri Loba (cesar at crea-si dot com)
+// Modified by: 
+// Created:     
+// Copyright:   (C) 2008-11 Cesar Mauri Loba - CREA Software Systems
+// 
+//  This program is free software: you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation, either version 3 of the License, or
+//  (at your option) any later version.
+//
+//  This program is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+/////////////////////////////////////////////////////////////////////////////
+
+//
+// TODO
+// 
+// - On CameraPanel::OnPaint when (m_autoResize== true) check if is this 
+//   the best method to notify parent a resize
+// - On CameraPanel::DrawCam avoid copying image when the call is 
+//   made from the main thread
+//
+
+#include "wcamerapanel.h"
+#include "wxroicontrol.h"
+
+#include <wx/dcclient.h>
+#include <wx/image.h>
+#include <wx/string.h>
+#include <highgui.h>
+
+namespace mod_camera {
+
+#define MIN_WIDTH 160
+#define MIN_HEIGHT 120
+#define VP_ALIGNMENT 4
+
+// New event to comunicate worker and GUI
+DECLARE_LOCAL_EVENT_TYPE(wxEVT_MY_REFRESH, -1)
+DEFINE_LOCAL_EVENT_TYPE(wxEVT_MY_REFRESH)
+
+// implement message map
+BEGIN_EVENT_TABLE(CameraPanel, wxPanel)
+	EVT_PAINT (CameraPanel::OnPaint)
+//	EVT_SIZE (CameraPanel::OnSize) 
+	EVT_MOUSE_EVENTS(CameraPanel::OnMouse)
+	EVT_COMMAND  (wxID_ANY, wxEVT_MY_REFRESH, CameraPanel::OnRecvRefresh)	
+END_EVENT_TABLE()
+
+CameraPanel::CameraPanel(CleanupFunctor functor, WXRoiControls* roi_controls)
+{
+	Init();
+	m_cleanupFunctor= functor;
+	m_roiControls= roi_controls;
+}
+
+CameraPanel::CameraPanel(wxWindow* parent, wxWindowID id, const wxPoint& pos, const wxSize& size, long style, const wxString& name)
+{
+	Init();
+    Create( parent, id, pos, size, style, name );
+}
+
+bool CameraPanel::Create(wxWindow* parent, wxWindowID id, const wxPoint& pos, const wxSize& size, long style, const wxString& name)
+{
+	if (size.GetWidth()== -1 && size.GetHeight()== -1) 
+		m_autoResize= true;
+	else 
+		m_autoResize= false;
+	bool retval= wxPanel::Create (parent, id, pos, size, style, name);
+
+//	SetMinSize(wxSize (MIN_WIDTH, MIN_HEIGHT));
+
+	return retval;
+}
+
+// asserts if registered controls found
+CameraPanel::~CameraPanel(void)
+{
+	if (m_cleanupFunctor!= NULL) {
+		m_cleanupFunctor();
+		m_cleanupFunctor= NULL;
+	}
+}
+
+void CameraPanel::RemoveCleanupFunctor()
+{
+	m_cleanupFunctor= NULL;
+}
+
+void CameraPanel::Init()
+{
+	// Get canvas width/height
+	m_nImgWidth= 1;
+	m_nImgHeight= 1;
+
+	m_ImageShowed= true;
+	m_AccessingImage= false;
+
+	m_SharedImage.Create (1, 1);
+	m_DisplayImage.Create (1, 1);	
+
+	m_autoResize= false;
+
+	m_cleanupFunctor= NULL;
+	m_roiControls= NULL;	
+}
+
+#if 0
+// If parent is a top level window resizes it's client area
+void CameraPanel::ResizeParentClientArea(int width, int height)
+{	
+	assert ((width % VP_ALIGNMENT)== 0);
+
+	if (m_resizeParent) {
+		// TODO: parent should set size automatically changing own size
+		// as a workdaround size is propagated to parent if is top level window
+		wxWindow* pParent= GetParent();
+
+		if (pParent) pParent->SetClientSize (width, height);
+		//if (pParent->IsTopLevel()) pParent->SetClientSize (width, height);	
+	}
+}
+
+
+// OnSize
+void CameraPanel::OnSize (wxSizeEvent& event)
+{
+	bool changed= false;
+
+	int width = event.GetSize().GetWidth();
+	int height = event.GetSize().GetHeight();
+	
+	// New requested size should be aligned to 4 or 8 bytes.
+	// So test it and force the alignment when necessary
+	if (width % VP_ALIGNMENT) 
+	{
+		width= width + VP_ALIGNMENT - (width % VP_ALIGNMENT);
+		changed= true;
+	}
+	
+	if (width< MIN_WIDTH) { width= MIN_WIDTH; changed= true; }
+	if (height< MIN_HEIGHT) { height= MIN_HEIGHT; changed= true; }
+	
+	if (changed) ResizeParentClientArea(width, height);
+	event.Skip (true);
+}
+#endif
+
+wxSize CameraPanel::DoGetBestSize() const
+{
+	if (m_autoResize) {
+
+		// Return best size based on the size of the image to show or minimum size
+		int width= MIN_WIDTH;
+		int height= MIN_HEIGHT;
+
+		if (m_nImgWidth> width) width= m_nImgWidth;
+		if (m_nImgHeight> height) height= m_nImgHeight;
+		return wxSize(width, height);
+	}
+	else
+		return wxPanel::DoGetBestSize();
+}
+
+// DrawCam. Called from the worker thread
+void CameraPanel::DrawCam (IplImage const * pImg)
+{	
+	int convertFlags= 0;
+
+	// If last image not shown yet don't update
+	assert (pImg);
+	if (m_ImageShowed && pImg)
+	{
+		m_ImageCopyMutex.Enter();
+
+		if (m_AccessingImage) 
+		{
+			// GUI thread is processing image, don't update
+			m_ImageCopyMutex.Leave();
+			return;
+		}
+		else
+		{
+			// Exclusive access to shared image
+			m_AccessingImage= true;		
+		}
+		m_ImageCopyMutex.Leave();
+		
+		// Check that image is RGB with channel order RGB or BGR
+		wxASSERT_MSG 
+			(pImg->nChannels== 3 &&
+			((pImg->channelSeq[0]== 'R' && pImg->channelSeq[1]== 'G' && pImg->channelSeq[2]== 'B') ||
+			(pImg->channelSeq[0]== 'B' && pImg->channelSeq[1]== 'G' && pImg->channelSeq[2]== 'R')),
+			_T("Wrong image format. It should be RGB or BGR") );
+		
+		//
+		// Adapt image format to show on the screen
+		//			
+		
+		// Allocate shared image if size changed	
+		if (pImg->width!= m_SharedImage.Width() || pImg->height!= m_SharedImage.Height())
+			m_SharedImage.Create (pImg->width, pImg->height, pImg->depth, "RGB", pImg->origin, pImg->align);
+		
+		
+		assert (pImg->origin== 0);
+		if (pImg->channelSeq[0]== 'B' && pImg->channelSeq[1]== 'G' && pImg->channelSeq[2]== 'R')
+		{
+			convertFlags|= CV_CVTIMG_SWAP_RB;
+		//	pImg->channelSeq[0]= 'R';
+		//	pImg->channelSeq[2]= 'B';
+		}
+		if (convertFlags) cvConvertImage ( pImg, m_SharedImage.ptr(), convertFlags );
+		else cvCopy( pImg, m_SharedImage.ptr() );
+		m_ImageShowed= false;
+		
+		// Release exclusive access to image
+		m_AccessingImage= false;
+
+		// When calling a GUI function from a thread different than 
+		// the main one (this method is usually called from a worker thread)
+		// synchonization is needed (under GTK+ is mandatory, for example).
+		// but it seems that under Windows no GUI Mutex is needed. Futhermore,
+		// wxMutexGuiEnter() blocks when pull down a menu from the menu bar
+		// For more info check WX source thread sample 
+		
+		// As wxPostEvent is the recommended synchronization mechanism we'll use it.
+		// Hug! wxPostEvent also blocks if main thread is processing an event :-(		
+		// This problem has been reported as being caused on gtk by the call to
+		// wxWakeUpIdle() inside wxPostEvent. See, for instance:
+		// http://osdir.com/ml/lib.wxwindows.general/2003-10/msg00026.html
+		// In theory if the macro __WXGTK20__ is defined this must not happen.
+		// Since version 2.9.0 there is another funtion to post events "wxQueueEvent"
+		// That should be investigated
+		wxCommandEvent event(wxEVT_MY_REFRESH);
+		wxPostEvent(this, event);
+	}	
+}
+
+// OnPaint. Called on paint event
+void CameraPanel::OnPaint (wxPaintEvent& event)
+{
+	event.Skip();	// Avoid compilation warning. This is the default behavior
+
+	// Create and check DC 
+	// Note that In a paint event handler, the application must always create a wxPaintDC object, 
+	// even if you do not use it. Otherwise, under MS Windows, refreshing for this and other 
+	// windows will go wrong.
+	wxPaintDC dc(this);
+	if(!dc.IsOk()) return;
+
+	// TODO: does nothing under Linux KDE	
+	if (!IsShown()) return;
+
+	// Not implemented for 2.6?
+	//if (!IsShownOnScreen()) return;	
+
+	// If current image already shown wait for the next frame.
+	// Note this is also necessary to avoid program crash due a void 
+	// shared image during the initialization process
+	if (m_ImageShowed) return;
+
+	// Exclusive access to shared image
+	m_ImageCopyMutex.Enter();
+	if (m_AccessingImage) 
+	{
+		// Worker thread is processing image, don't update
+		m_ImageCopyMutex.Leave();
+		return;
+	}
+	else
+	{
+		// Exclusive access to shared image
+		m_AccessingImage= true;	
+	}
+	m_ImageCopyMutex.Leave();
+
+	// Image size changed
+	if (m_nImgWidth!= m_SharedImage.Width() || m_nImgHeight!= m_SharedImage.Height())
+	{
+		m_nImgWidth= m_SharedImage.Width();
+		m_nImgHeight= m_SharedImage.Height();
+		if (m_autoResize) {
+			SetSize (m_nImgWidth, m_nImgHeight);
+			InvalidateBestSize();
+
+			if (GetParent()) {
+				wxSizeEvent event;
+				wxPostEvent (GetParent(), event);
+				//ResizeParentClientArea(m_nImgWidth, m_nImgHeight);
+			}
+		}		
+	}
+
+	// Allocate DisplayImage when needed
+	int vpWidth, vpHeight;
+	GetSize(&vpWidth, &vpHeight);
+	if (vpWidth % 4) vpWidth= vpWidth + 4 - (vpWidth % 4);
+	if (vpWidth!= m_DisplayImage.Width() || vpHeight!= m_DisplayImage.Height())
+	{
+		// Allocate shared image if size changed
+		m_DisplayImage.Create (vpWidth, vpHeight, m_SharedImage.Depth(), "RGB", m_SharedImage.Origin(), m_SharedImage.Align());		
+	}
+
+	// Scale image
+	cvResize( m_SharedImage.ptr(), m_DisplayImage.ptr(), CV_INTER_NN );
+	
+   	// Working with shared image finished
+	m_AccessingImage= false;
+
+	// Draw controls
+	if (m_roiControls) {
+		m_roiControls->Paint (*m_DisplayImage.ptr(), *this);
+	}
+
+	// To wxWidgets
+	unsigned char *rawData;
+	CvSize roiSize;
+	int step = 0;
+	cvGetRawData( m_DisplayImage.ptr(), &rawData, &step, &roiSize );
+	
+	wxImage wxImg= wxImage(vpWidth, vpHeight, rawData, true );
+	
+	// convert to bitmap to be used by the window to draw
+	m_Bitmap= wxBitmap( wxImg );
+		
+	wxCoord x, y, width, height;
+	dc.GetClippingBox( &x, &y, &width, &height );
+	dc.DrawBitmap( m_Bitmap, x, y );
+	
+	m_ImageShowed= true;
+}
+
+void CameraPanel::OnMouse ( wxMouseEvent& event )
+{
+	if (m_roiControls) {
+		m_roiControls->MouseEvent (event);		
+	}
+}
+
+void CameraPanel::OnRecvRefresh( wxCommandEvent& WXUNUSED(event) )
+{
+	Refresh(false);		
+}
+
+}
\ No newline at end of file
diff --git a/src/mod_camera/wcamerapanel.h b/src/mod_camera/wcamerapanel.h
new file mode 100755
index 0000000..f57b8af
--- /dev/null
+++ b/src/mod_camera/wcamerapanel.h
@@ -0,0 +1,91 @@
+/////////////////////////////////////////////////////////////////////////////
+// Name:        wcamerapanel.h
+// Purpose:		wxPanel derived class to show live camera image
+// Author:      Cesar Mauri Loba (cesar at crea-si dot com)
+// Modified by: 
+// Created:     
+// Copyright:   (C) 2008-11 Cesar Mauri Loba - CREA Software Systems
+// 
+//  This program is free software: you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation, either version 3 of the License, or
+//  (at your option) any later version.
+//
+//  This program is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+/////////////////////////////////////////////////////////////////////////////
+
+#ifndef CAMERAPANEL_H_
+#define CAMERAPANEL_H_
+
+#include "creavision/crvimage.h"
+#include <wx/panel.h>
+#include <wx/bitmap.h>
+#include <wx/event.h>
+#include <boost/function.hpp>
+
+namespace mod_camera {
+
+#define CAMERA_PANEL_NAME _("Camera viewer")
+
+class WXRoiControls;
+
+class CameraPanel : public wxPanel
+{     
+public:
+	// Functor typedef to install a callback when an instance is destroyed
+	typedef boost::function0<void> CleanupFunctor;
+
+	//CameraPanel();
+	CameraPanel(CleanupFunctor functor= NULL, WXRoiControls* roi_controls= NULL);
+	CameraPanel(wxWindow* parent, wxWindowID id = wxID_ANY, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize, long style = wxSIMPLE_BORDER, const wxString& name= CAMERA_PANEL_NAME ); 
+	
+	bool Create(wxWindow* parent, wxWindowID id = wxID_ANY, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize, long style = wxSIMPLE_BORDER, const wxString& name= CAMERA_PANEL_NAME ); 
+	
+	virtual ~CameraPanel(void);
+
+	// Draw method
+	void DrawCam (IplImage const * pImg);
+
+	void SetAllowAutoRezise ( bool value ) { m_autoResize= value; }
+
+	void RemoveCleanupFunctor();
+private:
+	virtual wxSize DoGetBestSize() const;
+	void OnPaint(wxPaintEvent& event);
+	
+	void OnRecvRefresh( wxCommandEvent &event );
+	void OnEvtMotion ( wxMouseEvent& event );
+	void OnEvtLeftDClick ( wxMouseEvent& event );
+	void OnMouse ( wxMouseEvent& event );	
+
+	void Init();
+
+protected:
+	DECLARE_EVENT_TABLE()
+
+private:
+	wxCriticalSection	m_ImageCopyMutex;
+	wxBitmap	m_Bitmap;
+	volatile bool	m_ImageShowed;
+	volatile bool	m_AccessingImage;
+	bool m_autoResize;
+	
+	// Previous captured image size
+	int		m_nImgWidth;
+	int		m_nImgHeight;
+	CIplImage m_SharedImage;
+	CIplImage m_DisplayImage;	
+
+	CleanupFunctor m_cleanupFunctor;
+	WXRoiControls* m_roiControls;
+};
+
+}
+
+#endif
diff --git a/src/mod_camera/wxroicontrol.cpp b/src/mod_camera/wxroicontrol.cpp
new file mode 100755
index 0000000..65aebc8
--- /dev/null
+++ b/src/mod_camera/wxroicontrol.cpp
@@ -0,0 +1,427 @@
+/////////////////////////////////////////////////////////////////////////////
+// Name:        wxroicontrol.cpp
+// Purpose:		
+// Author:      Cesar Mauri Loba (cesar at crea-si dot com)
+// Modified by: 
+// Created:     
+// Copyright:   (C) 2008-11 Cesar Mauri Loba - CREA Software Systems
+// 
+//  This program is free software: you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation, either version 3 of the License, or
+//  (at your option) any later version.
+//
+//  This program is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+/////////////////////////////////////////////////////////////////////////////
+#include "wxroicontrol.h"
+
+#include <wx/event.h>
+#include <wx/window.h>
+#include <math.h>
+#include <cv.h>
+#include <limits>
+
+#define SELECTION_TOLERANCE 3
+
+using namespace std;
+
+namespace mod_camera {
+
+WXRoiControls::WXRoiControls(ROIModifiedNotification rmn) 
+: m_prevCursorLocation(std::numeric_limits<int>::min(), std::numeric_limits<int>::min())
+, m_roiModifiedNotification(rmn)
+{			
+	m_mouseHoverInfo.loc= OVER_NONE;
+	m_mouseHoverInfo.roi= NULL;
+	m_temporaryROI= CTypeROI::CreateInstance();
+}
+
+WXRoiControls::~WXRoiControls()
+{	
+}
+
+
+void WXRoiControls::UpdateRootROI (const CTypeROI& roi)
+{
+	wxCriticalSectionLocker locker(m_csROIAccess);
+
+	// Find if previously registered
+	vector <SmartPtr<CTypeROI> >::const_iterator it= m_rootROIs.begin();
+
+	for (; it!= m_rootROIs.end(); ++it) {
+		if ((*it)->GetRegistrationId()== roi.GetRegistrationId()) break;	// found
+	}
+
+	SmartPtr<CTypeROI> dst_roi;
+	if (it== m_rootROIs.end()) {
+		// not found, create a new instance
+		dst_roi= CTypeROI::CreateInstance();
+		m_rootROIs.push_back(dst_roi);
+	}
+	else {
+		dst_roi= *it;
+	}
+
+	roi.Clone(dst_roi.get(), true);
+}
+
+void WXRoiControls::ClearRootROIs ()
+{
+	wxCriticalSectionLocker locker(m_csROIAccess);
+
+	m_rootROIs.clear();
+}
+
+//
+// Mouse events processing code
+//
+bool WXRoiControls::MouseEvent (wxMouseEvent& event)
+{
+	assert (wxThread::IsMain());
+
+	// obtain window that sent the event
+	wxWindow* win= dynamic_cast<wxWindow *> (event.GetEventObject());
+	assert (win);
+	if (!win) return false;
+
+	// win size
+	wxSize winSize= win->GetClientSize();
+
+	// pointer location
+	wxPoint location= event.GetPosition();
+
+	bool processed= true;
+
+	if (!event.LeftIsDown()) {
+		m_csROIAccess.Enter();
+
+		// No click. Check if the pointer is hovering some control and update the pointer icon
+		vector <SmartPtr<CTypeROI> >::const_iterator i_root= m_rootROIs.begin();
+		for (; i_root!= m_rootROIs.end(); ++i_root) {
+			WXRoiControls::UpdateMouseHoverInfoRec (*(*i_root), winSize,  location, m_mouseHoverInfo);
+			if (m_mouseHoverInfo.loc!= OVER_NONE) break;		// Found
+		}
+
+		switch (m_mouseHoverInfo.loc)
+		{
+		case WXRoiControls::OVER_NONE:
+			win->SetCursor (wxNullCursor);
+			processed= false;
+			break;
+		case WXRoiControls::OVER_LEFT_LINE:
+		case WXRoiControls::OVER_RIGHT_LINE:
+			{
+				wxCursor cur (wxCURSOR_SIZEWE);
+				win->SetCursor (cur);
+			}
+			break;
+		case WXRoiControls::OVER_BOTTOM_LINE:
+		case WXRoiControls::OVER_UPPER_LINE:
+			{
+				wxCursor cur (wxCURSOR_SIZENS);
+				win->SetCursor (cur);
+			}
+			break;
+		case WXRoiControls::OVER_ARROW:
+		case WXRoiControls::OVER_UL_CORNER:
+		case WXRoiControls::OVER_BR_CORNER:
+			{
+				wxCursor cur (wxCURSOR_HAND);
+				win->SetCursor (cur);
+			}
+			break;
+		default:
+			assert (false);
+		}
+
+		m_csROIAccess.Leave();
+	}
+	else {
+		m_csROIAccess.Enter();
+
+		// When click
+		assert (m_prevCursorLocation.x> std::numeric_limits<int>::min() && m_prevCursorLocation.y> std::numeric_limits<int>::min());
+		processed= false;
+		vector<SmartPtr<CTypeROI> >::const_iterator i_root;
+		if (m_mouseHoverInfo.loc!= OVER_NONE) {
+			for (i_root= m_rootROIs.begin(); i_root!= m_rootROIs.end(); ++i_root) {
+				processed= ModifyROIRec (*(*i_root), winSize, location, m_prevCursorLocation, m_mouseHoverInfo);
+				if (processed) break;
+			}			
+		}
+
+		// Notify listener
+		if (processed && m_roiModifiedNotification) {
+			assert (m_mouseHoverInfo.loc!= OVER_NONE && m_mouseHoverInfo.roi);			
+			assert (i_root!= m_rootROIs.end() && *i_root);
+			(*i_root)->Clone(m_temporaryROI.get(), true);
+			m_csROIAccess.Leave();
+
+			m_roiModifiedNotification(m_temporaryROI);
+		}
+		else
+			m_csROIAccess.Leave();
+	}
+
+	m_prevCursorLocation= location;
+
+	return processed;	
+} 
+
+// Compute both points of the arrow used to set the orientation for a given ROI
+void WXRoiControls::GetArrowSegment (const CTypeROI& roi, const wxSize& winSize, wxPoint& p1, wxPoint& p2)
+{
+	Norm2Real (winSize.GetWidth(), winSize.GetHeight(), roi.m_x, roi.m_y, p1.x, p1.y);
+	Norm2Real (winSize.GetWidth(), winSize.GetHeight(), roi.m_x + roi.m_width, roi.m_y + roi.m_height, p2.x, p2.y);
+
+	float line_lenght= sqrtf (powf(p2.x - p1.x, 2) + powf(p2.y - p1.y,2)) * 1.1f / 2.0f;
+	
+	float cx= (p1.x + p2.x) / 2.0f;
+	float cy= (p1.y + p2.y) / 2.0f;
+
+	p1.x= static_cast<int>(cx);
+	p1.y= static_cast<int>(cy);
+	float direction= roi.m_direction;
+	p2.x= static_cast<int>(cx + line_lenght * cosf (direction));
+	p2.y= static_cast<int>(cy - line_lenght * sinf (direction));
+}
+
+void WXRoiControls::UpdateMouseHoverInfoRec (
+		const CTypeROI& roi, const wxSize& winSize, 
+		const wxPoint& location, MouseHoverInfo& info)
+{
+	info.loc= OVER_NONE;
+	info.roi= NULL;
+
+	// 
+	// First look this ROI before checking children
+	//
+	if (roi.m_isVisible && roi.m_isEditable) {
+		wxPoint p1, p2;
+
+		// Pointer is over arrow?
+		if (roi.m_useDirection) {	
+			GetArrowSegment (roi, winSize, p1, p2);		
+			if (location.x>= p2.x - SELECTION_TOLERANCE && location.x<= p2.x + SELECTION_TOLERANCE &&
+				location.y>= p2.y - SELECTION_TOLERANCE && location.y<= p2.y + SELECTION_TOLERANCE)	{
+				info.loc= OVER_ARROW;
+				info.roi= &roi;
+				return;
+			}
+		}
+
+		// obtain ROI coordinates
+		Norm2Real (winSize.GetWidth(), winSize.GetHeight(), roi.m_x, roi.m_y, p1.x, p1.y);
+		Norm2Real (winSize.GetWidth(), winSize.GetHeight(), roi.m_x + roi.m_width, roi.m_y + roi.m_height, p2.x, p2.y);
+
+		if (location.x>= p1.x - SELECTION_TOLERANCE && location.x<= p1.x + SELECTION_TOLERANCE &&
+				 location.y>= p1.y - SELECTION_TOLERANCE && location.y<= p1.y + SELECTION_TOLERANCE)
+		{
+			info.loc= OVER_UL_CORNER;
+		}
+		else if (location.x>= p2.x - SELECTION_TOLERANCE && location.x<= p2.x + SELECTION_TOLERANCE &&
+				 location.y>= p2.y - SELECTION_TOLERANCE && location.y<= p2.y + SELECTION_TOLERANCE)
+		{	
+			info.loc= OVER_BR_CORNER;
+		}
+		else
+		{
+			if (location.y>= p1.y - SELECTION_TOLERANCE && location.y<= p2.y + SELECTION_TOLERANCE)
+			{
+				// Cursor in Y range, check is cursor over vertical lines
+				if (location.x>= p1.x - SELECTION_TOLERANCE && location.x<= p1.x + SELECTION_TOLERANCE) 
+					info.loc= OVER_LEFT_LINE;
+				else if (location.x>= p2.x - SELECTION_TOLERANCE && location.x<= p2.x + SELECTION_TOLERANCE)
+					info.loc= OVER_RIGHT_LINE;
+			}
+			if (location.x>= p1.x - SELECTION_TOLERANCE && location.x<= p2.x + SELECTION_TOLERANCE)
+			{
+				// Cursor in X range, check is cursor over horizontal lines
+				if (location.y>=  p1.y - SELECTION_TOLERANCE && location.y<=  p1.y + SELECTION_TOLERANCE) 
+					info.loc= OVER_UPPER_LINE;
+				else if (location.y>= p2.y - SELECTION_TOLERANCE && location.y<= p2.y + SELECTION_TOLERANCE)
+					info.loc= OVER_BOTTOM_LINE;
+			}
+		}	
+
+		// any control below the pointer?
+		if (info.loc!= OVER_NONE) {
+			// yes, finish lookup
+			info.roi= &roi;
+			return;
+		}
+	}
+
+	//
+	// process children ROIs
+	//
+	CTypeROIContents::ROICollection::const_iterator i_children= roi.m_childROIs.begin();
+	for (; i_children!= roi.m_childROIs.end(); ++i_children) {
+		UpdateMouseHoverInfoRec (*static_cast<CTypeROI*>(*i_children), winSize, location, info);
+		if (info.loc!= OVER_NONE) return;	// Found
+	}
+}
+
+bool WXRoiControls::ModifyROIRec (
+		CTypeROI& roi, const wxSize& winSize, const wxPoint& location, 
+		const wxPoint& location_prev, const MouseHoverInfo& info)
+{
+	// 
+	// First look this ROI before checking children
+	//
+	if (roi.m_isVisible && roi.m_isEditable && info.roi== &roi) {
+		wxPoint p1, p2;
+
+		if (info.loc== OVER_ARROW) {
+			GetArrowSegment (roi, winSize, p1, p2);
+			p2.x= location.x;
+			p2.y= location.y;
+			roi.SetDirection (atan2f(static_cast<float>(p1.y - p2.y), static_cast<float>(p2.x - p1.x)));			
+		}
+		else {		
+			// obtain ROI coordinates
+			Norm2Real (winSize.GetWidth(), winSize.GetHeight(), roi.m_x, roi.m_y, p1.x, p1.y);
+			Norm2Real (winSize.GetWidth(), winSize.GetHeight(), roi.m_x + roi.m_width, roi.m_y + roi.m_height, p2.x, p2.y);
+							
+			switch (info.loc)
+			{
+				float norm_x;
+				float norm_y;
+
+				case OVER_LEFT_LINE: 
+					p1.x+= location.x - location_prev.x;
+					Real2Norm(winSize.GetWidth(), winSize.GetHeight(), p1.x, p1.y, norm_x, norm_y);
+					roi.SetP1Resize (norm_x, norm_y);
+					break;
+				case OVER_BOTTOM_LINE: 
+					p2.y+= location.y - location_prev.y;
+					Real2Norm(winSize.GetWidth(), winSize.GetHeight(), p2.x, p2.y, norm_x, norm_y);
+					roi.SetP2Resize (norm_x, norm_y);
+					break;
+				case OVER_RIGHT_LINE: 
+					p2.x+= location.x - location_prev.x;
+					Real2Norm(winSize.GetWidth(), winSize.GetHeight(), p2.x, p2.y, norm_x, norm_y);
+					roi.SetP2Resize (norm_x, norm_y);
+					break;			
+				case OVER_UPPER_LINE: 
+					p1.y+= location.y - location_prev.y;
+					Real2Norm(winSize.GetWidth(), winSize.GetHeight(), p1.x, p1.y, norm_x, norm_y);
+					roi.SetP1Resize (norm_x, norm_y);
+					break;				
+				case OVER_UL_CORNER:
+				case OVER_BR_CORNER:
+					p1.x+= location.x - location_prev.x;
+					p1.y+= location.y - location_prev.y;
+					Real2Norm(winSize.GetWidth(), winSize.GetHeight(), p1.x, p1.y, norm_x, norm_y);
+					roi.SetP1Move (norm_x, norm_y);					
+					break;
+				default:
+					assert(false);
+			}
+		}
+
+		return true;
+	}
+
+	//
+	// process children ROIs
+	//
+	CTypeROIContents::ROICollection::const_iterator i_children= roi.m_childROIs.begin();
+	for (; i_children!= roi.m_childROIs.end(); ++i_children) {
+		if (ModifyROIRec (*static_cast<CTypeROI*>(*i_children), winSize, location, location_prev, info)) return true;
+	}
+
+	return false;
+}
+
+/*
+bool CWXNormROI::OnEvtLeftDClick ( wxMouseEvent& WXUNUSED(event) )
+{
+	//m_pVisibleNormROI->SetCenterWindow (m_pWindow->GetClientSize(), event.GetX(), event.GetY());
+	return true;
+}*/
+
+/////////////////////////////////////////////////////////////////////////////////77
+//
+// Painting code
+//
+
+void WXRoiControls::Paint (IplImage& img, const wxWindow& win)
+{
+	assert (wxThread::IsMain());
+
+	wxSize winSize= win.GetClientSize();
+
+	wxCriticalSectionLocker locker(m_csROIAccess);
+
+	vector <SmartPtr<CTypeROI> >::const_iterator i_root= m_rootROIs.begin();
+	for (; i_root!= m_rootROIs.end(); ++i_root) {
+		PaintRec (*(*i_root), img, winSize, m_mouseHoverInfo);		
+	}
+}
+
+void WXRoiControls::PaintRec (const CTypeROI& roi, IplImage& img, const wxSize& winSize, const MouseHoverInfo& info)
+{
+	if (roi.m_isVisible) {
+		CvPoint p1, p2;
+
+		// obtain ROI coordinates
+		Norm2Real (winSize.GetWidth(), winSize.GetHeight(), roi.m_x, roi.m_y, p1.x, p1.y);
+		Norm2Real (winSize.GetWidth(), winSize.GetHeight(), roi.m_x + roi.m_width, roi.m_y + roi.m_height, p2.x, p2.y);
+
+		int thickness= 1;
+		if (roi.m_isEditable && info.roi== &roi && info.loc>= OVER_LEFT_LINE && info.loc<= OVER_BR_CORNER)  
+			thickness= 3;
+
+		unsigned int color= roi.GetColor(); 
+		CvScalar cv_color= CV_RGB ( color & 0xFF, (color >> 8) & 0xFF, (color >> 16) & 0xFF );
+		// TODO: color
+		cvRectangle (&img, p1, p2, cv_color, thickness, 4);
+
+		// Affordances
+		if (roi.GetIsEditable()) {
+			CvPoint pa, pb;
+			pa.x= p1.x - thickness;
+			pa.y= p1.y - thickness;
+			pb.x= p1.x + thickness;
+			pb.y= p1.y + thickness;
+
+			cvRectangle (&img, pa, pb, cv_color, CV_FILLED );
+
+			pa.x= p2.x - thickness;
+			pa.y= p2.y - thickness;
+			pb.x= p2.x + thickness;
+			pb.y= p2.y + thickness;
+
+			cvRectangle (&img, pa, pb, cv_color, CV_FILLED );
+		}
+
+		if (roi.m_useDirection)
+		{
+			wxPoint tmp_p1, tmp_p2;
+			GetArrowSegment (roi, winSize, tmp_p1, tmp_p2);
+			p1.x= tmp_p1.x; p1.y= tmp_p1.y;
+			p2.x= tmp_p2.x; p2.y= tmp_p2.y;
+			if (roi.m_isEditable && info.roi== &roi && info.loc== OVER_ARROW)  thickness= 3;
+			else thickness= 1;
+			cvLine (&img, p1, p2, cv_color, thickness, CV_AA );
+			cvCircle(&img, p2, SELECTION_TOLERANCE, cv_color, thickness, CV_AA );
+		}
+	}
+
+	//
+	// process children ROIs
+	//
+	CTypeROIContents::ROICollection::const_iterator i_children= roi.m_childROIs.begin();
+	for (; i_children!= roi.m_childROIs.end(); ++i_children) {
+		PaintRec (*static_cast<CTypeROI*>(*i_children), img, winSize, info);
+	}
+} 
+
+}
\ No newline at end of file
diff --git a/src/mod_camera/wxroicontrol.h b/src/mod_camera/wxroicontrol.h
new file mode 100755
index 0000000..c67cfbd
--- /dev/null
+++ b/src/mod_camera/wxroicontrol.h
@@ -0,0 +1,97 @@
+/////////////////////////////////////////////////////////////////////////////
+// Name:        wxroicontrols.h
+// Author:      Cesar Mauri Loba (cesar at crea-si dot com)
+// Modified by: 
+// Created:     
+// Copyright:   (C) 2008-11 Cesar Mauri Loba - CREA Software Systems
+// 
+//  This program is free software: you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation, either version 3 of the License, or
+//  (at your option) any later version.
+//
+//  This program is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+/////////////////////////////////////////////////////////////////////////////
+#ifndef WXROICONTROLS_H
+#define WXROICONTROLS_H
+
+#include "mod_camera/roitype.h"
+#include <wx/gdicmn.h>
+#include <wx/thread.h>
+#include <boost/function.hpp>
+#include <vector>
+
+typedef struct _IplImage IplImage;
+class wxMouseEvent;
+
+namespace mod_camera {
+
+class WXRoiControls
+{
+public:
+	// Functor typedef to install a callback when one ROI is updated
+	typedef boost::function1<void, SmartPtr<const CTypeROI> > ROIModifiedNotification;
+
+	WXRoiControls(ROIModifiedNotification rmn= NULL);
+	virtual ~WXRoiControls();
+	
+	// Update a root ROI given its id.
+	void UpdateRootROI (const CTypeROI& roi);
+
+	// Clear all "registered" root ROIs
+	void ClearRootROIs ();
+
+	void Paint (IplImage& img, const wxWindow& win);
+	bool MouseEvent (wxMouseEvent& event);
+
+private:
+	
+	//
+	// types to store where is the pointer after an event.
+	//
+	enum MouseHoverLoc {
+		OVER_NONE= 0, OVER_LEFT_LINE, OVER_BOTTOM_LINE, 
+		OVER_RIGHT_LINE, OVER_UPPER_LINE, 
+		OVER_UL_CORNER, OVER_BR_CORNER, OVER_ARROW
+	};
+	struct MouseHoverInfo {
+		MouseHoverLoc loc;		// Where is the cursor
+		const CTypeROI* roi;	// ROI pointer (for comparison purposes only)
+	};
+
+	//
+	// Attributes
+	//
+	struct MouseHoverInfo m_mouseHoverInfo;
+	wxCriticalSection m_csROIAccess;
+	wxPoint m_prevCursorLocation;
+	std::vector <SmartPtr<CTypeROI> > m_rootROIs;
+	ROIModifiedNotification m_roiModifiedNotification;
+
+	SmartPtr<CTypeROI> m_temporaryROI;
+
+	//
+	// private operations
+	//
+	static void GetArrowSegment (const CTypeROI& roi, const wxSize& winSize, wxPoint& p1, wxPoint& p2);
+
+	static void UpdateMouseHoverInfoRec (
+		const CTypeROI& roi, const wxSize& winSize, 
+		const wxPoint& location, MouseHoverInfo& info);
+
+	static bool ModifyROIRec (
+		CTypeROI& roi, const wxSize& winSize, const wxPoint& location, 
+		const wxPoint& location_prev, const MouseHoverInfo& info);
+
+	static void PaintRec (const CTypeROI& roi, IplImage& img, const wxSize& winSize, const MouseHoverInfo& info);
+};
+
+}
+
+#endif
\ No newline at end of file
diff --git a/src/mod_hid/CMakeLists.txt b/src/mod_hid/CMakeLists.txt
new file mode 100755
index 0000000..bf9a433
--- /dev/null
+++ b/src/mod_hid/CMakeLists.txt
@@ -0,0 +1,44 @@
+cmake_minimum_required(VERSION 2.6)
+project(mod_hid)
+
+set(mod_hid_SRCS	
+	mod_hid.cpp
+	mousecontrol.h
+	mousecontrol.cpp
+	keyboardcode.h
+	keyboardcode.cpp
+)
+
+
+if(NOT WIN32)
+set(mod_hid_SRCS 
+	${mod_hid_SRCS}
+	ucs2keysym.h
+	ucs2keysym.c
+	)
+endif(NOT WIN32)
+
+add_library (mod_hid MODULE ${mod_hid_SRCS})
+target_link_libraries(mod_hid spcore)
+#target_link_libraries(mod_hid ${Boost_THREAD_LIBRARY})
+
+#
+# X11
+#
+
+if(NOT WIN32)
+	find_package(X11 REQUIRED)
+	if (NOT X11_XTest_FOUND)
+		message (FATAL_ERROR "X11_XTest extensions not found.")
+	endif(NOT X11_XTest_FOUND)
+	include_directories(${X11_INCLUDE_DIR})
+	target_link_libraries(mod_hid ${X11_X11_LIB})
+	target_link_libraries(mod_hid ${X11_XTest_LIB})
+endif(NOT WIN32)
+
+# Uncomment for manually commanded tests
+IF(BUILD_TESTS)
+	ADD_SUBDIRECTORY(tests)
+ENDIF(BUILD_TESTS)
+
+INSTALL (TARGETS mod_hid RUNTIME DESTINATION ${LIBRUNTIMEDIR} LIBRARY DESTINATION ${PLUGINDIR})
diff --git a/src/mod_hid/keyboardcode.cpp b/src/mod_hid/keyboardcode.cpp
new file mode 100644
index 0000000..2e2e2bd
--- /dev/null
+++ b/src/mod_hid/keyboardcode.cpp
@@ -0,0 +1,1029 @@
+/////////////////////////////////////////////////////////////////////////////
+// Name:        keyboardcode.cpp
+// Author:      Cesar Mauri Loba (cesar at crea-si dot com)
+// Created:     28/09/2010
+// Copyright:   (C) 2010-12 Cesar Mauri Loba - CREA Software Systems
+//
+//  This program is free software: you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation, either version 3 of the License, or
+//  (at your option) any later version.
+//
+//  This program is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+/////////////////////////////////////////////////////////////////////////////
+#include "keyboardcode.h"
+
+#ifdef USING_WXWIDGETS
+	#include <wx/utils.h>
+	#include <wx/stdpaths.h>
+	#include <wx/defs.h>
+#endif
+
+#if defined(WIN32)
+	#define _WIN32_WINNT 0x0500
+	#include <windows.h>
+#else
+	#include <X11/extensions/XTest.h>
+	#define XK_MISCELLANY 1
+	#define XK_LATIN1 1
+	#include <X11/keysymdef.h>
+	#include "ucs2keysym.h"
+#endif
+#include <assert.h>
+#include <stdexcept>
+#include <string.h>
+
+#if !defined(WIN32)
+	// Make sure that an unsinged long is wide enough to store a KeySym
+	//wxCOMPILE_TIME_ASSERT( sizeof(KeySym)== sizeof(unsigned long), KeySymDifferentThanLongError );
+	//wxCOMPILE_TIME_ASSERT( sizeof(KeyCode)<= sizeof(unsigned int), KeyCodeGreaterThanIntError );
+	
+	// Class to store a connection to a display which is automatically closed when destructor is called
+	class DisplayHolder {
+	private:
+		Display* m_display;
+	public:
+		DisplayHolder() : m_display(NULL) {} 
+		~DisplayHolder() {
+			if (m_display) XCloseDisplay(m_display);
+			m_display= NULL;
+		}
+		Display* get() { return m_display; }
+		void set(Display* d) { m_display= d; }
+	};
+
+	static
+	DisplayHolder g_displayHolder;
+
+	Display* KeyboardCode::getDisplay() {
+		if (!g_displayHolder.get()) {
+			g_displayHolder.set(XOpenDisplay(NULL));
+			if (!g_displayHolder.get()) throw std::runtime_error("KeyboardCode: cannot open display");
+		}
+		return g_displayHolder.get();
+	}
+#else
+	char KeyboardCode::g_keyCodeName[KEY_CODE_NAME_LENGHT];
+
+	// Convert EUnicode (inc. Unicode) to Virtual-Key Code. Return 0 if no translation available.
+	static
+	WORD EUnicode2VirtualKeyCode (unsigned int c) {
+		// First try special codes
+		switch (c) {
+			case KeyboardCode::KC_BACK: return VK_BACK;
+			case KeyboardCode::KC_TAB: return VK_TAB;			
+			case KeyboardCode::KC_RETURN: return VK_RETURN;
+			case KeyboardCode::KC_ESCAPE: return VK_ESCAPE;
+			case KeyboardCode::KC_SPACE: return VK_SPACE;
+			case KeyboardCode::KC_DELETE: return VK_DELETE;
+			
+			case KeyboardCode::KC_CLEAR: return VK_CLEAR;
+			case KeyboardCode::KC_SHIFT: return VK_SHIFT;
+			case KeyboardCode::KC_LSHIFT: return VK_LSHIFT;
+			case KeyboardCode::KC_RSHIFT: return VK_RSHIFT;
+			case KeyboardCode::KC_CONTROL: return VK_CONTROL;
+			case KeyboardCode::KC_LCONTROL: return VK_LCONTROL;
+			case KeyboardCode::KC_RCONTROL: return VK_RCONTROL;
+			case KeyboardCode::KC_MENU: return VK_MENU;
+			case KeyboardCode::KC_PAUSE: return VK_PAUSE;
+			case KeyboardCode::KC_CAPSLOCK: return VK_CAPITAL;
+			case KeyboardCode::KC_PAGEUP: return VK_PRIOR;
+			case KeyboardCode::KC_PAGEDOWN: return VK_NEXT;
+			case KeyboardCode::KC_END: return VK_END;
+			case KeyboardCode::KC_HOME: return VK_HOME;
+			case KeyboardCode::KC_LEFT: return VK_LEFT;
+			case KeyboardCode::KC_UP: return VK_UP;
+			case KeyboardCode::KC_RIGHT: return VK_RIGHT;
+			case KeyboardCode::KC_DOWN: return VK_DOWN;
+			case KeyboardCode::KC_SELECT: return VK_SELECT;
+			case KeyboardCode::KC_PRINT: return VK_PRINT;
+			case KeyboardCode::KC_EXECUTE: return VK_EXECUTE;
+			case KeyboardCode::KC_SNAPSHOT: return VK_SNAPSHOT;
+			case KeyboardCode::KC_INSERT: return VK_INSERT;
+			case KeyboardCode::KC_HELP: return VK_HELP;
+			case KeyboardCode::KC_CANCEL: return VK_CANCEL;
+			case KeyboardCode::KC_ALT: return VK_MENU;
+			case KeyboardCode::KC_LALT: return VK_MENU;
+			// AltGr is a combination of ctrl + alt on WIN32. No translation provided.
+			case KeyboardCode::KC_RALT: return 0;
+			case KeyboardCode::KC_NUMPAD0: return VK_NUMPAD0;
+			case KeyboardCode::KC_NUMPAD1: return VK_NUMPAD1;
+			case KeyboardCode::KC_NUMPAD2: return VK_NUMPAD2;
+			case KeyboardCode::KC_NUMPAD3: return VK_NUMPAD3;
+			case KeyboardCode::KC_NUMPAD4: return VK_NUMPAD4;
+			case KeyboardCode::KC_NUMPAD5: return VK_NUMPAD5;
+			case KeyboardCode::KC_NUMPAD6: return VK_NUMPAD6;
+			case KeyboardCode::KC_NUMPAD7: return VK_NUMPAD7;
+			case KeyboardCode::KC_NUMPAD8: return VK_NUMPAD8;
+			case KeyboardCode::KC_NUMPAD9: return VK_NUMPAD9;
+			case KeyboardCode::KC_MULTIPLY: c= 0x2A; break; // let VkKeyScanW do the job
+			case KeyboardCode::KC_ADD: c= 0x2B; break; // let VkKeyScanW do the job
+			case KeyboardCode::KC_SEPARATOR: return 0;	// Ni est�, ni se le espera.
+			case KeyboardCode::KC_SUBTRACT: c= 0x2D; break; // let VkKeyScanW do the job
+			case KeyboardCode::KC_DECIMAL: return VK_DECIMAL;
+			case KeyboardCode::KC_DIVIDE: c= 0x2F; break; // let VkKeyScanW do the job
+			case KeyboardCode::KC_F1: return VK_F1;
+			case KeyboardCode::KC_F2: return VK_F2;
+			case KeyboardCode::KC_F3: return VK_F3;
+			case KeyboardCode::KC_F4: return VK_F4;
+			case KeyboardCode::KC_F5: return VK_F5;
+			case KeyboardCode::KC_F6: return VK_F6;
+			case KeyboardCode::KC_F7: return VK_F7;
+			case KeyboardCode::KC_F8: return VK_F8;
+			case KeyboardCode::KC_F9: return VK_F9;
+			case KeyboardCode::KC_F10: return VK_F10;
+			case KeyboardCode::KC_F11: return VK_F11;
+			case KeyboardCode::KC_F12: return VK_F12;
+			case KeyboardCode::KC_F13: return VK_F13;
+			case KeyboardCode::KC_F14: return VK_F14;
+			case KeyboardCode::KC_F15: return VK_F15;
+			case KeyboardCode::KC_F16: return VK_F16;
+			case KeyboardCode::KC_F17: return VK_F17;
+			case KeyboardCode::KC_F18: return VK_F18;
+			case KeyboardCode::KC_F19: return VK_F19;
+			case KeyboardCode::KC_F20: return VK_F20;
+			case KeyboardCode::KC_F21: return VK_F21;
+			case KeyboardCode::KC_F22: return VK_F22;
+			case KeyboardCode::KC_F23: return VK_F23;
+			case KeyboardCode::KC_F24: return VK_F24;
+			case KeyboardCode::KC_NUMLOCK: return VK_NUMLOCK;
+			case KeyboardCode::KC_SCROLL: return VK_SCROLL;
+			case KeyboardCode::KC_NUMPAD_SPACE: return VK_SPACE;
+			case KeyboardCode::KC_NUMPAD_TAB: return VK_TAB;
+			case KeyboardCode::KC_NUMPAD_ENTER: return VK_RETURN;
+			case KeyboardCode::KC_NUMPAD_HOME: return VK_HOME;
+			case KeyboardCode::KC_NUMPAD_LEFT: return VK_LEFT;
+			case KeyboardCode::KC_NUMPAD_UP: return VK_UP;
+			case KeyboardCode::KC_NUMPAD_RIGHT: return VK_RIGHT;
+			case KeyboardCode::KC_NUMPAD_DOWN: return VK_DOWN;
+			case KeyboardCode::KC_NUMPAD_PAGEUP: return VK_PRIOR;
+			case KeyboardCode::KC_NUMPAD_PAGEDOWN: return VK_NEXT;
+			case KeyboardCode::KC_NUMPAD_END: return VK_END;
+			case KeyboardCode::KC_NUMPAD_BEGIN: return VK_NUMPAD5;
+			case KeyboardCode::KC_NUMPAD_INSERT: return VK_INSERT;
+			case KeyboardCode::KC_NUMPAD_DELETE: return VK_DELETE;
+			case KeyboardCode::KC_NUMPAD_EQUAL: return 0;
+			case KeyboardCode::KC_NUMPAD_MULTIPLY: return VK_MULTIPLY;
+			case KeyboardCode::KC_NUMPAD_ADD: return VK_ADD;
+			case KeyboardCode::KC_NUMPAD_SEPARATOR: return VK_SEPARATOR;
+			case KeyboardCode::KC_NUMPAD_SUBTRACT: return VK_SUBTRACT;
+			case KeyboardCode::KC_NUMPAD_DECIMAL: return VK_DECIMAL;
+			case KeyboardCode::KC_NUMPAD_DIVIDE: return VK_DIVIDE;
+			case KeyboardCode::KC_WINDOWS_LEFT: return VK_LWIN;
+			case KeyboardCode::KC_WINDOWS_RIGHT: return VK_RWIN;
+			case KeyboardCode::KC_WINDOWS_MENU: return VK_APPS;
+		}
+		// At this point we assume an unicode character was provided.
+		// On WIN32, VkKeyScanW function only takes one 16bit unicode 
+		// character (encoded using UTF-16), so in theory characters
+		// in the Supplementary Multilingual Plane cannot be translated
+		// using this function.
+		assert (c<= 0xFFFF);
+		WORD evkc= VkKeyScanW((WCHAR) c);
+		if (evkc== 0xFFFF) return 0;
+
+		unsigned char hi= evkc >> 8;
+		// If control XOR alt pressed then is a special control code without translation
+		if (hi & 2 && !(hi & 4)) return 0;
+		if (hi & 4 && !(hi & 2)) return 0;
+
+		// Sometimes VkKeyScanW returns an undefined VKC
+		unsigned char lo= evkc & 0xFF;
+		if (lo== 64) return 0;
+
+		return (WORD) lo;
+	}
+
+	// Convert a native WIN32 Virtual-Key Code to EUnicode (inc. Unicode). 
+	// Return 0 if no translation available.
+	// NOTE that on WIN32 given a virtual-key code can be converted into 
+	// many characters
+	static
+	unsigned int VirtualKeyCode2EUnicode (WORD vkc) {
+		// First try to transate the virtual key-code into a character
+		UINT c= MapVirtualKeyW(vkc, MAPVK_VK_TO_CHAR);
+		// Ignore whether is a dead key
+		c= c & 0xFFFF;		
+		if (c) return c;	// Finish if translation successful
+
+		// OK. Untranslatable VKC. Switch/case mapping.
+		switch (vkc) {
+			case VK_LBUTTON:
+			case VK_RBUTTON: return 0;
+			case VK_CANCEL: return KeyboardCode::KC_CANCEL;
+			case VK_MBUTTON:
+			case VK_XBUTTON1:
+			case VK_XBUTTON2: return 0;
+			case VK_BACK: return KeyboardCode::KC_BACK;
+			case VK_TAB: return KeyboardCode::KC_TAB;
+			case VK_CLEAR: return KeyboardCode::KC_CLEAR;			
+			case VK_RETURN: return KeyboardCode::KC_RETURN; // WIN32 cannot tell between main & keypad RETURN
+			case VK_SHIFT: return KeyboardCode::KC_SHIFT;
+			case VK_CONTROL: return KeyboardCode::KC_CONTROL;
+			case VK_MENU: return KeyboardCode::KC_ALT; // VK_MENU is ALT key, no matter left or right
+			case VK_PAUSE: return KeyboardCode::KC_PAUSE;
+			case VK_CAPITAL: return KeyboardCode::KC_CAPSLOCK;
+			case VK_KANA: /* VK_HANGUL */
+			case VK_JUNJA:
+			case VK_FINAL:
+			case VK_HANJA: /* VK_KANJI */ return 0;			
+			case VK_ESCAPE: return KeyboardCode::KC_ESCAPE;
+			case VK_CONVERT: 
+			case VK_NONCONVERT: 
+			case VK_ACCEPT:
+			case VK_MODECHANGE: return 0;
+			case VK_SPACE: return KeyboardCode::KC_SPACE;
+			case VK_PRIOR: return KeyboardCode::KC_PAGEUP;
+			case VK_NEXT: return KeyboardCode::KC_PAGEDOWN;
+			case VK_END: return KeyboardCode::KC_END;
+			case VK_HOME: return KeyboardCode::KC_HOME;
+			case VK_LEFT: return KeyboardCode::KC_LEFT;
+			case VK_UP: return KeyboardCode::KC_UP;
+			case VK_RIGHT: return KeyboardCode::KC_RIGHT;
+			case VK_DOWN: return KeyboardCode::KC_DOWN;
+			case VK_SELECT: return KeyboardCode::KC_SELECT;
+			case VK_PRINT: return KeyboardCode::KC_PRINT;
+			case VK_EXECUTE: return KeyboardCode::KC_EXECUTE;
+			case VK_SNAPSHOT: return KeyboardCode::KC_SNAPSHOT;
+			case VK_INSERT: return KeyboardCode::KC_INSERT;
+			case VK_DELETE: return KeyboardCode::KC_DELETE;		
+			case VK_HELP: return KeyboardCode::KC_HELP;
+			case VK_LWIN: return KeyboardCode::KC_WINDOWS_LEFT;
+			case VK_RWIN: return KeyboardCode::KC_WINDOWS_RIGHT;
+			case VK_APPS: return KeyboardCode::KC_WINDOWS_MENU;
+			case VK_SLEEP: return 0;
+			case VK_NUMPAD0: return KeyboardCode::KC_NUMPAD0;
+			case VK_NUMPAD1: return KeyboardCode::KC_NUMPAD1;
+			case VK_NUMPAD2: return KeyboardCode::KC_NUMPAD2;
+			case VK_NUMPAD3: return KeyboardCode::KC_NUMPAD3;
+			case VK_NUMPAD4: return KeyboardCode::KC_NUMPAD4;
+			case VK_NUMPAD5: return KeyboardCode::KC_NUMPAD5;
+			case VK_NUMPAD6: return KeyboardCode::KC_NUMPAD6;
+			case VK_NUMPAD7: return KeyboardCode::KC_NUMPAD7;
+			case VK_NUMPAD8: return KeyboardCode::KC_NUMPAD8;
+			case VK_NUMPAD9: return KeyboardCode::KC_NUMPAD9;
+			case VK_MULTIPLY: return KeyboardCode::KC_NUMPAD_MULTIPLY;
+			case VK_ADD: return KeyboardCode::KC_NUMPAD_ADD;
+			case VK_SEPARATOR: return KeyboardCode::KC_NUMPAD_SEPARATOR;
+			case VK_SUBTRACT: return KeyboardCode::KC_NUMPAD_SUBTRACT;
+			case VK_DECIMAL: return KeyboardCode::KC_NUMPAD_DECIMAL;
+			case VK_DIVIDE: return KeyboardCode::KC_NUMPAD_DIVIDE;
+			case VK_F1: return KeyboardCode::KC_F1;
+			case VK_F2: return KeyboardCode::KC_F2;
+			case VK_F3: return KeyboardCode::KC_F3;
+			case VK_F4: return KeyboardCode::KC_F4;
+			case VK_F5: return KeyboardCode::KC_F5;
+			case VK_F6: return KeyboardCode::KC_F6;
+			case VK_F7: return KeyboardCode::KC_F7;
+			case VK_F8: return KeyboardCode::KC_F8;
+			case VK_F9: return KeyboardCode::KC_F9;
+			case VK_F10: return KeyboardCode::KC_F10;
+			case VK_F11: return KeyboardCode::KC_F11;
+			case VK_F12: return KeyboardCode::KC_F12;
+			case VK_F13: return KeyboardCode::KC_F13;
+			case VK_F14: return KeyboardCode::KC_F14;
+			case VK_F15: return KeyboardCode::KC_F15;
+			case VK_F16: return KeyboardCode::KC_F16;
+			case VK_F17: return KeyboardCode::KC_F17;
+			case VK_F18: return KeyboardCode::KC_F18;
+			case VK_F19: return KeyboardCode::KC_F19;
+			case VK_F20: return KeyboardCode::KC_F20;
+			case VK_F21: return KeyboardCode::KC_F21;
+			case VK_F22: return KeyboardCode::KC_F22;
+			case VK_F23: return KeyboardCode::KC_F23;
+			case VK_F24: return KeyboardCode::KC_F24;
+			case VK_NUMLOCK: return KeyboardCode::KC_NUMLOCK;
+			case VK_SCROLL: return KeyboardCode::KC_SCROLL;
+			case VK_LSHIFT: return KeyboardCode::KC_LSHIFT;
+			case VK_RSHIFT: return KeyboardCode::KC_RSHIFT;
+			case VK_LCONTROL: return KeyboardCode::KC_LCONTROL;
+			case VK_RCONTROL: return KeyboardCode::KC_RCONTROL;
+			case VK_LMENU: return KeyboardCode::KC_LALT;
+			case VK_RMENU: return KeyboardCode::KC_RALT;
+			/* gap of browser, multimedia and internet buttons */
+
+			// these with assert should have been translated before
+			case VK_OEM_1: assert (0); return 0;
+			case VK_OEM_PLUS: assert (0); return '+';
+			case VK_OEM_COMMA: assert (0); return ',';
+			case VK_OEM_MINUS: assert (0); return '-';
+			case VK_OEM_PERIOD: assert (0); return '.';
+		}
+		return 0;
+	}
+
+#endif 
+
+const char* KeyboardCode::GetName() const
+{	 
+#if !defined(WIN32)	
+	return XKeysymToString(m_keyCode);
+#else
+	// This function only returns the name of a key identified by its scan code
+	WORD vkc= EUnicode2VirtualKeyCode (m_keyCode);
+	if (!vkc) return "";
+	// Note that when translating from a virtual-key code multiple scan codes
+	// are possible (e.g. arrow keys, delete, etc.) and this function does not
+	// allow to choose. The only effective workaround would be to store the
+	// original scan code is the object is constructed using this.
+	UINT scanCode= ::MapVirtualKeyW(vkc, MAPVK_VK_TO_VSC);
+	scanCode= scanCode << 16;
+	*g_keyCodeName= '\0';
+	::GetKeyNameTextA ((LONG) scanCode, g_keyCodeName, KEY_CODE_NAME_LENGHT);
+	return g_keyCodeName;
+#endif	
+}
+
+void KeyboardCode::SendKeystroke()
+{
+	if (!m_keyCode) return;
+#if !defined(WIN32)
+	Display* d= getDisplay();
+
+	KeyCode k= XKeysymToKeycode(d, m_keyCode);
+	XTestFakeKeyEvent(d, k, True, 0);
+	XTestFakeKeyEvent(d, k, False, 1);
+	XFlush(d);
+#else
+	// It seems that, to work properly, SendInput() need both the virtual-key code and the scan code. 
+	// Note that KEYEVENTF_EXTENDEDKEY flag is not used.
+	WORD vkc= EUnicode2VirtualKeyCode (m_keyCode);
+	if (!vkc) return;
+	unsigned int scanCode = MapVirtualKey(vkc, MAPVK_VK_TO_VSC);
+
+	INPUT ip;
+	memset(&ip, 0, sizeof(ip));
+	ip.type= INPUT_KEYBOARD;
+	ip.ki.wVk= vkc;
+	ip.ki.wScan= (WORD) scanCode;
+
+	// Key press
+	SendInput(1, &ip, sizeof(ip));
+
+	// Key release
+	ip.ki.dwFlags|= KEYEVENTF_KEYUP;
+	SendInput(1, &ip, sizeof(ip));
+#endif
+}
+
+// Reads a keycode from keyboard and returns a KeyboardCode object
+KeyboardCode KeyboardCode::ReadKeyCode()
+{
+#if !defined(WIN32)
+	char keys_return[32];
+	unsigned char keys;
+	unsigned int kc = 0;
+	
+	XQueryKeymap(getDisplay(), keys_return);
+
+	// TODO: implement this correctly
+	for(int i=0; i<32; i++) {
+		keys = (unsigned char) keys_return[i];
+		if (keys > 0) {
+			switch (keys) {
+				case 1:   kc = 0; break;
+				case 2:   kc = 1; break;
+				case 4:   kc = 2; break;
+				case 8:   kc = 3; break;
+				case 16:  kc = 4; break;
+				case 32:  kc = 5; break;
+				case 64:  kc = 6; break;
+				case 128: kc = 7; break;
+			}
+			kc += 8 * i;
+		}
+	}	
+	return FromScanCode (kc);
+#else
+	// Still not available for Windows
+	assert(0);
+	return KeyboardCode();
+#endif
+}
+
+// Given an scan code returns the corresponding KeyboardCode object
+KeyboardCode KeyboardCode::FromScanCode (unsigned int scanCode)
+{	
+#if !defined(WIN32)
+	return KeyboardCode (static_cast<unsigned long> (XKeycodeToKeysym(getDisplay(), (KeyCode) scanCode, 0)));
+#else
+	UINT vKCode= ::MapVirtualKey(scanCode, MAPVK_VSC_TO_VK_EX);
+	assert (vKCode< 0xFFFF);
+	return KeyboardCode(VirtualKeyCode2EUnicode (static_cast<WORD>(vKCode)));
+#endif
+}
+
+// Given a platform dependent virtual-key or KeySym returns the 
+// corresponding KeyboardCode object
+KeyboardCode KeyboardCode::FromVirtualKeyCode (unsigned long vkCode)
+{
+#if !defined(WIN32)
+	return KeyboardCode (vkCode);
+#else
+	assert (vkCode<= 0xFFFF);
+	return KeyboardCode(VirtualKeyCode2EUnicode (static_cast<WORD>(vkCode)));
+#endif
+}
+
+// Given an EUnicode value which could include any 8 bit latin1 character,
+// a full unicode character or a special EUnicode value as defined above
+KeyboardCode KeyboardCode::FromEUnicode (unsigned int kc)
+{
+#if !defined(WIN32)
+	KeySym ks= ucs2keysym(kc);
+	if (ks) return KeyboardCode(ks);
+
+	switch (kc) {
+		case KeyboardCode::KC_BACK: return KeyboardCode(XK_BackSpace);
+		case KeyboardCode::KC_TAB: return KeyboardCode(XK_Tab);
+		case KeyboardCode::KC_RETURN: return KeyboardCode(XK_Return);
+		case KeyboardCode::KC_ESCAPE: return KeyboardCode(XK_Escape);
+		case KeyboardCode::KC_SPACE: return KeyboardCode(XK_KP_Space);
+		case KeyboardCode::KC_DELETE: return KeyboardCode(XK_Delete);
+
+		case KeyboardCode::KC_CLEAR: return KeyboardCode(XK_Clear);
+		case KeyboardCode::KC_SHIFT: return KeyboardCode(XK_Shift_L);
+		case KeyboardCode::KC_LSHIFT: return KeyboardCode(XK_Shift_L);
+		case KeyboardCode::KC_RSHIFT: return KeyboardCode(XK_Shift_R);
+		case KeyboardCode::KC_CONTROL: return KeyboardCode(XK_Control_L);
+		case KeyboardCode::KC_LCONTROL: return KeyboardCode(XK_Control_L);
+		case KeyboardCode::KC_RCONTROL: return KeyboardCode(XK_Control_R);
+		case KeyboardCode::KC_MENU: return KeyboardCode(XK_Menu);
+		case KeyboardCode::KC_PAUSE: return KeyboardCode(XK_Pause);
+		case KeyboardCode::KC_CAPSLOCK: return KeyboardCode(XK_Caps_Lock);
+		case KeyboardCode::KC_PAGEUP: return KeyboardCode(XK_Page_Up);
+		case KeyboardCode::KC_PAGEDOWN: return KeyboardCode(XK_Page_Down); 
+		case KeyboardCode::KC_END: return KeyboardCode(XK_End);
+		case KeyboardCode::KC_HOME: return KeyboardCode(XK_Home);
+		case KeyboardCode::KC_LEFT: return KeyboardCode(XK_Left);
+		case KeyboardCode::KC_UP: return KeyboardCode(XK_Up);
+		case KeyboardCode::KC_RIGHT: return KeyboardCode(XK_Right);
+		case KeyboardCode::KC_DOWN: return KeyboardCode(XK_Down);
+		case KeyboardCode::KC_SELECT: return KeyboardCode(XK_Select);
+		case KeyboardCode::KC_PRINT: return KeyboardCode(XK_Print);
+		case KeyboardCode::KC_EXECUTE: return KeyboardCode(XK_Execute);
+		case KeyboardCode::KC_SNAPSHOT: return KeyboardCode(XK_Print);
+		case KeyboardCode::KC_INSERT: return KeyboardCode(XK_Insert);
+		case KeyboardCode::KC_HELP: return KeyboardCode(XK_Help);
+		case KeyboardCode::KC_CANCEL: return KeyboardCode(XK_Break);
+		case KeyboardCode::KC_ALT: return KeyboardCode(XK_Alt_L);
+		case KeyboardCode::KC_LALT: return KeyboardCode(XK_Alt_L);
+		case KeyboardCode::KC_RALT: return KeyboardCode(XK_Alt_R);
+		case KeyboardCode::KC_NUMPAD0: return KeyboardCode(XK_KP_0);
+		case KeyboardCode::KC_NUMPAD1: return KeyboardCode(XK_KP_1);
+		case KeyboardCode::KC_NUMPAD2: return KeyboardCode(XK_KP_2);
+		case KeyboardCode::KC_NUMPAD3: return KeyboardCode(XK_KP_3);
+		case KeyboardCode::KC_NUMPAD4: return KeyboardCode(XK_KP_4);
+		case KeyboardCode::KC_NUMPAD5: return KeyboardCode(XK_KP_5);
+		case KeyboardCode::KC_NUMPAD6: return KeyboardCode(XK_KP_6);
+		case KeyboardCode::KC_NUMPAD7: return KeyboardCode(XK_KP_7);
+		case KeyboardCode::KC_NUMPAD8: return KeyboardCode(XK_KP_8);
+		case KeyboardCode::KC_NUMPAD9: return KeyboardCode(XK_KP_9);
+		case KeyboardCode::KC_MULTIPLY: return KeyboardCode(XK_multiply);
+		case KeyboardCode::KC_ADD: return KeyboardCode(XK_plus);
+		case KeyboardCode::KC_SEPARATOR: return KeyboardCode(0);
+		case KeyboardCode::KC_SUBTRACT: return KeyboardCode(XK_minus);
+		case KeyboardCode::KC_DECIMAL: return KeyboardCode(XK_period);
+		case KeyboardCode::KC_DIVIDE: return KeyboardCode(XK_division);
+		case KeyboardCode::KC_F1: return KeyboardCode(XK_F1);
+		case KeyboardCode::KC_F2: return KeyboardCode(XK_F2);
+		case KeyboardCode::KC_F3: return KeyboardCode(XK_F3);
+		case KeyboardCode::KC_F4: return KeyboardCode(XK_F4);
+		case KeyboardCode::KC_F5: return KeyboardCode(XK_F5);
+		case KeyboardCode::KC_F6: return KeyboardCode(XK_F6);
+		case KeyboardCode::KC_F7: return KeyboardCode(XK_F7);
+		case KeyboardCode::KC_F8: return KeyboardCode(XK_F8);
+		case KeyboardCode::KC_F9: return KeyboardCode(XK_F9);
+		case KeyboardCode::KC_F10: return KeyboardCode(XK_F10);
+		case KeyboardCode::KC_F11: return KeyboardCode(XK_F11);
+		case KeyboardCode::KC_F12: return KeyboardCode(XK_F12);
+		case KeyboardCode::KC_F13: return KeyboardCode(XK_F13);
+		case KeyboardCode::KC_F14: return KeyboardCode(XK_F14);
+		case KeyboardCode::KC_F15: return KeyboardCode(XK_F15);
+		case KeyboardCode::KC_F16: return KeyboardCode(XK_F16);
+		case KeyboardCode::KC_F17: return KeyboardCode(XK_F17);
+		case KeyboardCode::KC_F18: return KeyboardCode(XK_F18);
+		case KeyboardCode::KC_F19: return KeyboardCode(XK_F19);
+		case KeyboardCode::KC_F20: return KeyboardCode(XK_F20);
+		case KeyboardCode::KC_F21: return KeyboardCode(XK_F21);
+		case KeyboardCode::KC_F22: return KeyboardCode(XK_F22);
+		case KeyboardCode::KC_F23: return KeyboardCode(XK_F23);
+		case KeyboardCode::KC_F24: return KeyboardCode(XK_F24);
+		case KeyboardCode::KC_NUMLOCK: return KeyboardCode(XK_Num_Lock);
+		case KeyboardCode::KC_SCROLL: return KeyboardCode(XK_Scroll_Lock);		
+		case KeyboardCode::KC_NUMPAD_SPACE: return KeyboardCode(XK_KP_Space);
+		case KeyboardCode::KC_NUMPAD_TAB: return KeyboardCode(XK_KP_Tab);
+		case KeyboardCode::KC_NUMPAD_ENTER: return KeyboardCode(XK_KP_Enter);
+		case KeyboardCode::KC_NUMPAD_HOME: return KeyboardCode(XK_KP_Home);
+		case KeyboardCode::KC_NUMPAD_LEFT: return KeyboardCode(XK_KP_Left);
+		case KeyboardCode::KC_NUMPAD_UP: return KeyboardCode(XK_KP_Up);
+		case KeyboardCode::KC_NUMPAD_RIGHT: return KeyboardCode(XK_KP_Right);
+		case KeyboardCode::KC_NUMPAD_DOWN: return KeyboardCode(XK_KP_Down);
+		case KeyboardCode::KC_NUMPAD_PAGEUP: return KeyboardCode(XK_KP_Page_Up);
+		case KeyboardCode::KC_NUMPAD_PAGEDOWN: return KeyboardCode(XK_KP_Page_Down);
+		case KeyboardCode::KC_NUMPAD_END: return KeyboardCode(XK_KP_End);
+		case KeyboardCode::KC_NUMPAD_BEGIN: return KeyboardCode(XK_KP_Begin);
+		case KeyboardCode::KC_NUMPAD_INSERT: return KeyboardCode(XK_KP_Insert);
+		case KeyboardCode::KC_NUMPAD_DELETE: return KeyboardCode(XK_KP_Delete);
+		case KeyboardCode::KC_NUMPAD_EQUAL: return KeyboardCode(XK_KP_Equal);
+		case KeyboardCode::KC_NUMPAD_MULTIPLY: return KeyboardCode(XK_KP_Multiply);
+		case KeyboardCode::KC_NUMPAD_ADD: return KeyboardCode(XK_KP_Add);
+		case KeyboardCode::KC_NUMPAD_SEPARATOR: return KeyboardCode(XK_KP_Separator);
+		case KeyboardCode::KC_NUMPAD_SUBTRACT: return KeyboardCode(XK_KP_Subtract);
+		case KeyboardCode::KC_NUMPAD_DECIMAL: return KeyboardCode(XK_KP_Decimal);
+		case KeyboardCode::KC_NUMPAD_DIVIDE: return KeyboardCode(XK_KP_Divide);		
+		case KeyboardCode::KC_WINDOWS_LEFT: return KeyboardCode(XK_Super_L);
+		case KeyboardCode::KC_WINDOWS_RIGHT: return KeyboardCode(XK_Super_R);
+		case KeyboardCode::KC_WINDOWS_MENU: return KeyboardCode(XK_Menu);
+		default:
+			//assert (false);
+			return KeyboardCode(0);
+	}
+#else
+	// Make sure input value is translatable
+	if (EUnicode2VirtualKeyCode(kc)) return KeyboardCode(kc);
+	else return KeyboardCode(0);
+#endif
+}
+
+// Given the name of the key (which is formed removing th prepending KC_ of the
+// entries in the EUnicode enumeration or its printed character (only ascii standard 
+// characters are supported currently) returns its KeyboardCode. 
+
+static struct name2eunicode {
+	const char *name;
+	unsigned int code;
+} name2eunicode_tab[] = {
+	{ "ADD", KeyboardCode::KC_ADD },
+	{ "ALT", KeyboardCode::KC_ALT },
+	{ "BACK", KeyboardCode::KC_BACK },
+	{ "CANCEL", KeyboardCode::KC_CANCEL },
+	{ "CAPSLOCK", KeyboardCode::KC_CAPSLOCK },
+	{ "CLEAR", KeyboardCode::KC_CLEAR },
+	{ "CONTROL", KeyboardCode::KC_CONTROL },
+	{ "DECIMAL", KeyboardCode::KC_DECIMAL },
+	{ "DELETE", KeyboardCode::KC_DELETE },
+	{ "DIVIDE", KeyboardCode::KC_DIVIDE },
+	{ "DOWN", KeyboardCode::KC_DOWN },
+	{ "END", KeyboardCode::KC_END },
+	{ "ESCAPE", KeyboardCode::KC_ESCAPE },
+	{ "EXECUTE", KeyboardCode::KC_EXECUTE },
+	{ "F1", KeyboardCode::KC_F1 },
+	{ "F10", KeyboardCode::KC_F10 },
+	{ "F11", KeyboardCode::KC_F11 },
+	{ "F12", KeyboardCode::KC_F12 },
+	{ "F13", KeyboardCode::KC_F13 },
+	{ "F14", KeyboardCode::KC_F14 },
+	{ "F15", KeyboardCode::KC_F15 },
+	{ "F16", KeyboardCode::KC_F16 },
+	{ "F17", KeyboardCode::KC_F17 },
+	{ "F18", KeyboardCode::KC_F18 },
+	{ "F19", KeyboardCode::KC_F19 },
+	{ "F2", KeyboardCode::KC_F2 },
+	{ "F20", KeyboardCode::KC_F20 },
+	{ "F21", KeyboardCode::KC_F21 },
+	{ "F22", KeyboardCode::KC_F22 },
+	{ "F23", KeyboardCode::KC_F23 },
+	{ "F24", KeyboardCode::KC_F24 },
+	{ "F3", KeyboardCode::KC_F3 },
+	{ "F4", KeyboardCode::KC_F4 },
+	{ "F5", KeyboardCode::KC_F5 },
+	{ "F6", KeyboardCode::KC_F6 },
+	{ "F7", KeyboardCode::KC_F7 },
+	{ "F8", KeyboardCode::KC_F8 },
+	{ "F9", KeyboardCode::KC_F9 },
+	{ "FIRST", KeyboardCode::KC_FIRST },
+	{ "HELP", KeyboardCode::KC_HELP },
+	{ "HOME", KeyboardCode::KC_HOME },
+	{ "INSERT", KeyboardCode::KC_INSERT },
+	{ "LALT", KeyboardCode::KC_LALT },
+	{ "LCONTROL", KeyboardCode::KC_LCONTROL },
+	{ "LEFT", KeyboardCode::KC_LEFT },
+	{ "LSHIFT", KeyboardCode::KC_LSHIFT },
+	{ "MENU", KeyboardCode::KC_MENU },
+	{ "MULTIPLY", KeyboardCode::KC_MULTIPLY },
+	{ "NUMLOCK", KeyboardCode::KC_NUMLOCK },
+	{ "NUMPAD0", KeyboardCode::KC_NUMPAD0 },
+	{ "NUMPAD1", KeyboardCode::KC_NUMPAD1 },
+	{ "NUMPAD2", KeyboardCode::KC_NUMPAD2 },
+	{ "NUMPAD3", KeyboardCode::KC_NUMPAD3 },
+	{ "NUMPAD4", KeyboardCode::KC_NUMPAD4 },
+	{ "NUMPAD5", KeyboardCode::KC_NUMPAD5 },
+	{ "NUMPAD6", KeyboardCode::KC_NUMPAD6 },
+	{ "NUMPAD7", KeyboardCode::KC_NUMPAD7 },
+	{ "NUMPAD8", KeyboardCode::KC_NUMPAD8 },
+	{ "NUMPAD9", KeyboardCode::KC_NUMPAD9 },
+	{ "NUMPAD_ADD", KeyboardCode::KC_NUMPAD_ADD },
+	{ "NUMPAD_BEGIN", KeyboardCode::KC_NUMPAD_BEGIN },
+	{ "NUMPAD_DECIMAL", KeyboardCode::KC_NUMPAD_DECIMAL },
+	{ "NUMPAD_DELETE", KeyboardCode::KC_NUMPAD_DELETE },
+	{ "NUMPAD_DIVIDE", KeyboardCode::KC_NUMPAD_DIVIDE },
+	{ "NUMPAD_DOWN", KeyboardCode::KC_NUMPAD_DOWN },
+	{ "NUMPAD_END", KeyboardCode::KC_NUMPAD_END },
+	{ "NUMPAD_ENTER", KeyboardCode::KC_NUMPAD_ENTER },
+	{ "NUMPAD_EQUAL", KeyboardCode::KC_NUMPAD_EQUAL },
+	{ "NUMPAD_HOME", KeyboardCode::KC_NUMPAD_HOME },
+	{ "NUMPAD_INSERT", KeyboardCode::KC_NUMPAD_INSERT },
+	{ "NUMPAD_LEFT", KeyboardCode::KC_NUMPAD_LEFT },
+	{ "NUMPAD_MULTIPLY", KeyboardCode::KC_NUMPAD_MULTIPLY },
+	{ "NUMPAD_PAGEDOWN", KeyboardCode::KC_NUMPAD_PAGEDOWN },
+	{ "NUMPAD_PAGEUP", KeyboardCode::KC_NUMPAD_PAGEUP },
+	{ "NUMPAD_RIGHT", KeyboardCode::KC_NUMPAD_RIGHT },
+	{ "NUMPAD_SEPARATOR", KeyboardCode::KC_NUMPAD_SEPARATOR },
+	{ "NUMPAD_SPACE", KeyboardCode::KC_NUMPAD_SPACE },
+	{ "NUMPAD_SUBTRACT", KeyboardCode::KC_NUMPAD_SUBTRACT },
+	{ "NUMPAD_TAB", KeyboardCode::KC_NUMPAD_TAB },
+	{ "NUMPAD_UP", KeyboardCode::KC_NUMPAD_UP },
+	{ "PAGEDOWN", KeyboardCode::KC_PAGEDOWN },
+	{ "PAGEUP", KeyboardCode::KC_PAGEUP },
+	{ "PAUSE", KeyboardCode::KC_PAUSE },
+	{ "PRINT", KeyboardCode::KC_PRINT },
+	{ "RALT", KeyboardCode::KC_RALT },
+	{ "RCONTROL", KeyboardCode::KC_RCONTROL },
+	{ "RETURN", KeyboardCode::KC_RETURN },
+	{ "RIGHT", KeyboardCode::KC_RIGHT },
+	{ "RSHIFT", KeyboardCode::KC_RSHIFT },
+	{ "SCROLL", KeyboardCode::KC_SCROLL },
+	{ "SELECT", KeyboardCode::KC_SELECT },
+	{ "SEPARATOR", KeyboardCode::KC_SEPARATOR },
+	{ "SHIFT", KeyboardCode::KC_SHIFT },
+	{ "SNAPSHOT", KeyboardCode::KC_SNAPSHOT },
+	{ "SPACE", KeyboardCode::KC_SPACE },
+	{ "SUBTRACT", KeyboardCode::KC_SUBTRACT },
+	{ "TAB", KeyboardCode::KC_TAB },
+	{ "UP", KeyboardCode::KC_UP },
+	{ "WINDOWS_LEFT", KeyboardCode::KC_WINDOWS_LEFT },
+	{ "WINDOWS_MENU", KeyboardCode::KC_WINDOWS_MENU },
+	{ "WINDOWS_RIGHT", KeyboardCode::KC_WINDOWS_RIGHT }
+};
+
+#define NAME2ENICODE_TAB_SIZE (sizeof(name2eunicode_tab)/sizeof(struct name2eunicode))
+
+KeyboardCode KeyboardCode::FromKeyName (const char *kname)
+{
+	// Lookup in name2eunicode_tab
+	char kname_up[256];
+	int i= 0;
+	for (; kname[i] && i< 255; i++)
+		kname_up[i]= (char) toupper(kname[i]);
+	kname_up[i]= 0;
+	
+	int min = 0;
+	int max = NAME2ENICODE_TAB_SIZE - 1;
+	int mid;
+
+	// binary search in table
+	while (max >= min) {
+		mid = (min + max) / 2;
+		int cmp= strcmp(name2eunicode_tab[mid].name, kname_up);
+		if (cmp< 0) min = mid + 1;
+		else if (cmp> 0) max = mid - 1;
+		else {
+			// found it
+			return KeyboardCode::FromEUnicode(name2eunicode_tab[mid].code);
+		}
+	}
+
+#if !defined(WIN32)
+	if (*kname && kname[1]== 0) {
+		KeySym ks= ucs2keysym(*kname);
+		if (ks) return KeyboardCode(ks);
+	}
+
+	KeySym ks= XStringToKeysym(kname);
+	if (ks!= NoSymbol) return KeyboardCode::FromVirtualKeyCode(ks);
+#else
+	// On Windows and when only 1 character passed
+	if (*kname && kname[1]== 0) {
+		const char c= *kname;
+		if (EUnicode2VirtualKeyCode(c)) return KeyboardCode(c);
+	}
+#endif
+
+	// Not found. 
+	return KeyboardCode(0);
+}
+
+KeyboardCode KeyboardCode::FromRawValue (unsigned long kc)
+{
+	return FromVirtualKeyCode (kc);
+}
+
+// Get the internal raw value. NOTE: intended only
+// for storage purposes not to work with
+unsigned long KeyboardCode::GetRawValue() const
+{
+	return m_keyCode;
+}
+
+#if !defined(NDEBUG)
+#include <stdio.h>
+void KeyboardCode::Dump() const
+{
+#if !defined(WIN32)
+	printf ("KeySym: %lu	KeyCode: %u Name: %s\n", m_keyCode, XKeysymToKeycode(getDisplay(), m_keyCode), GetName());
+#else
+	printf ("V. Key Code: %u Name: %s\n", m_keyCode, GetName());
+#endif
+}
+#endif
+
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////
+#ifdef USING_WXWIDGETS
+
+#error Code not tested
+
+// Given an wxKeyCode code returns the corresponding KeyboardCode object
+KeyboardCode KeyboardCode::FromWXKeyCode (wxKeyCode kc)
+{
+#if !defined(WIN32)
+	switch (kc) {
+		case WXK_BACK: return KeyboardCode(XK_BackSpace);
+		case WXK_TAB: return KeyboardCode(XK_Tab);
+		case WXK_RETURN: return KeyboardCode(XK_Return);
+		case WXK_ESCAPE: return KeyboardCode(XK_Escape);		
+		case WXK_DELETE: return KeyboardCode(XK_Delete);
+		case WXK_CLEAR: return KeyboardCode(XK_Clear);
+		case WXK_SHIFT: return KeyboardCode(XK_Shift_L);
+		case WXK_ALT: return KeyboardCode(XK_Alt_L);
+		case WXK_CONTROL: return KeyboardCode(XK_Control_L);
+		case WXK_MENU: return KeyboardCode(XK_Menu);
+		case WXK_PAUSE: return KeyboardCode(XK_Pause);
+		case WXK_END: return KeyboardCode(XK_End);
+		case WXK_HOME: return KeyboardCode(XK_Home);
+		case WXK_LEFT: return KeyboardCode(XK_Left);
+		case WXK_UP: return KeyboardCode(XK_Up);
+		case WXK_RIGHT: return KeyboardCode(XK_Right);
+		case WXK_DOWN: return KeyboardCode(XK_Down);
+		case WXK_SELECT: return KeyboardCode(XK_Select);
+		case WXK_PRINT: return KeyboardCode(XK_Print);
+		case WXK_EXECUTE: return KeyboardCode(XK_Execute);
+		case WXK_SNAPSHOT: return KeyboardCode(XK_Print);
+		case WXK_INSERT: return KeyboardCode(XK_Insert);
+		case WXK_HELP: return KeyboardCode(XK_Help);
+		case WXK_NUMPAD0: return KeyboardCode(XK_KP_0);
+		case WXK_NUMPAD1: return KeyboardCode(XK_KP_1);
+		case WXK_NUMPAD2: return KeyboardCode(XK_KP_2);
+		case WXK_NUMPAD3: return KeyboardCode(XK_KP_3);
+		case WXK_NUMPAD4: return KeyboardCode(XK_KP_4);
+		case WXK_NUMPAD5: return KeyboardCode(XK_KP_5);
+		case WXK_NUMPAD6: return KeyboardCode(XK_KP_6);
+		case WXK_NUMPAD7: return KeyboardCode(XK_KP_7);
+		case WXK_NUMPAD8: return KeyboardCode(XK_KP_8);
+		case WXK_NUMPAD9: return KeyboardCode(XK_KP_9);
+		case WXK_MULTIPLY: return KeyboardCode(XK_KP_Multiply);
+		case WXK_ADD: return KeyboardCode(XK_KP_Add);
+		case WXK_SEPARATOR: return KeyboardCode(XK_KP_Separator);
+		case WXK_SUBTRACT: return KeyboardCode(XK_KP_Subtract);
+		case WXK_DECIMAL: return KeyboardCode(XK_KP_Decimal);
+		case WXK_DIVIDE: return KeyboardCode(XK_KP_Divide);
+		case WXK_F1: return KeyboardCode(XK_F1);
+		case WXK_F2: return KeyboardCode(XK_F2);
+		case WXK_F3: return KeyboardCode(XK_F3);
+		case WXK_F4: return KeyboardCode(XK_F4);
+		case WXK_F5: return KeyboardCode(XK_F5);
+		case WXK_F6: return KeyboardCode(XK_F6);
+		case WXK_F7: return KeyboardCode(XK_F7);
+		case WXK_F8: return KeyboardCode(XK_F8);
+		case WXK_F9: return KeyboardCode(XK_F9);
+		case WXK_F10: return KeyboardCode(XK_F10);
+		case WXK_F11: return KeyboardCode(XK_F11);
+		case WXK_F12: return KeyboardCode(XK_F12);
+		case WXK_F13: return KeyboardCode(XK_F13);
+		case WXK_F14: return KeyboardCode(XK_F14);
+		case WXK_F15: return KeyboardCode(XK_F15);
+		case WXK_F16: return KeyboardCode(XK_F16);
+		case WXK_F17: return KeyboardCode(XK_F17);
+		case WXK_F18: return KeyboardCode(XK_F18);
+		case WXK_F19: return KeyboardCode(XK_F19);
+		case WXK_F20: return KeyboardCode(XK_F20);
+		case WXK_F21: return KeyboardCode(XK_F21);
+		case WXK_F22: return KeyboardCode(XK_F22);
+		case WXK_F23: return KeyboardCode(XK_F23);
+		case WXK_F24: return KeyboardCode(XK_F24);
+		case WXK_NUMLOCK: return KeyboardCode(XK_Num_Lock);
+		case WXK_SCROLL: return KeyboardCode(XK_Scroll_Lock);
+		case WXK_PAGEUP: return KeyboardCode(XK_Page_Up);
+		case WXK_PAGEDOWN: return KeyboardCode(XK_Page_Down); 
+		case WXK_NUMPAD_SPACE: return KeyboardCode(XK_KP_Space);
+		case WXK_NUMPAD_TAB: return KeyboardCode(XK_KP_Tab);
+		case WXK_NUMPAD_ENTER: return KeyboardCode(XK_KP_Enter);
+		case WXK_NUMPAD_F1: return KeyboardCode(XK_KP_F1);
+		case WXK_NUMPAD_F2: return KeyboardCode(XK_KP_F2);
+		case WXK_NUMPAD_F3: return KeyboardCode(XK_KP_F3);
+		case WXK_NUMPAD_F4: return KeyboardCode(XK_KP_F4);
+		case WXK_NUMPAD_HOME: return KeyboardCode(XK_KP_Home);
+		case WXK_NUMPAD_LEFT: return KeyboardCode(XK_KP_Left);
+		case WXK_NUMPAD_UP: return KeyboardCode(XK_KP_Up);
+		case WXK_NUMPAD_RIGHT: return KeyboardCode(XK_KP_Right);
+		case WXK_NUMPAD_DOWN: return KeyboardCode(XK_KP_Down);
+		case WXK_NUMPAD_PAGEUP: return KeyboardCode(XK_KP_Page_Up);
+		case WXK_NUMPAD_PAGEDOWN: return KeyboardCode(XK_KP_Page_Down);
+		case WXK_NUMPAD_END: return KeyboardCode(XK_KP_End);
+		case WXK_NUMPAD_BEGIN: return KeyboardCode(XK_KP_Begin);
+		case WXK_NUMPAD_INSERT: return KeyboardCode(XK_KP_Insert);
+		case WXK_NUMPAD_DELETE: return KeyboardCode(XK_KP_Delete);
+		case WXK_NUMPAD_EQUAL: return KeyboardCode(XK_KP_Equal);
+		case WXK_NUMPAD_MULTIPLY: return KeyboardCode(XK_KP_Multiply);
+		case WXK_NUMPAD_ADD: return KeyboardCode(XK_KP_Add);
+		case WXK_NUMPAD_SEPARATOR: return KeyboardCode(XK_KP_Separator);
+		case WXK_NUMPAD_SUBTRACT: return KeyboardCode(XK_KP_Subtract);
+		case WXK_NUMPAD_DECIMAL: return KeyboardCode(XK_KP_Decimal);
+		case WXK_NUMPAD_DIVIDE: return KeyboardCode(XK_KP_Divide);		
+		// the following key codes are only generated under Windows currently
+		case WXK_WINDOWS_LEFT: return KeyboardCode(XK_Super_L);
+		case WXK_WINDOWS_RIGHT: return KeyboardCode(XK_Super_R);
+		case WXK_WINDOWS_MENU: return KeyboardCode(XK_Menu);
+		case WXK_SPACE: return KeyboardCode(XK_KP_Space);
+		case WXK_CANCEL: return KeyboardCode(XK_Break);
+		case WXK_CAPITAL: return KeyboardCode(XK_Caps_Lock);
+
+		//
+		// Untranslated codes
+		//		
+		case WXK_START:
+		case WXK_LBUTTON:
+		case WXK_RBUTTON:		
+		case WXK_MBUTTON:
+		case WXK_COMMAND:
+
+		// Hardware-specific buttons
+		case WXK_SPECIAL1:
+		case WXK_SPECIAL2:
+		case WXK_SPECIAL3:
+		case WXK_SPECIAL4:
+		case WXK_SPECIAL5:
+		case WXK_SPECIAL6:
+		case WXK_SPECIAL7:
+		case WXK_SPECIAL8:
+		case WXK_SPECIAL9:
+		case WXK_SPECIAL10:
+		case WXK_SPECIAL11:
+		case WXK_SPECIAL12:
+		case WXK_SPECIAL13:
+		case WXK_SPECIAL14:
+		case WXK_SPECIAL15:
+		case WXK_SPECIAL16:
+		case WXK_SPECIAL17:
+		case WXK_SPECIAL18:
+		case WXK_SPECIAL19:
+		case WXK_SPECIAL20:
+			assert (false);
+			return KeyboardCode(0);
+			break;
+	}
+
+	// If the code reaches this point it means that wxKeyCode kc carries 
+	// an unicode character (see wxKeyEvent::GetUnicodeKey)
+	// TODO: translate these unicode char to a keysym
+	return KeyboardCode(0);
+#else
+	
+	switch (kc) {
+		case WXK_BACK: return KeyboardCode(VK_BACK);
+		case WXK_TAB: return KeyboardCode(VK_TAB);			
+		case WXK_RETURN: return KeyboardCode(VK_RETURN);
+		case WXK_ESCAPE: return KeyboardCode(VK_ESCAPE);
+		case WXK_DELETE: return KeyboardCode(VK_DELETE);
+		case WXK_CLEAR: return KeyboardCode(VK_CLEAR);
+		case WXK_SHIFT: return KeyboardCode(VK_SHIFT);
+		case WXK_ALT: return KeyboardCode(VK_MENU);
+		case WXK_CONTROL: return KeyboardCode(VK_CONTROL);
+		case WXK_MENU: return KeyboardCode(VK_MENU);
+		case WXK_PAUSE: return KeyboardCode(VK_PAUSE);
+		case WXK_END: return KeyboardCode(VK_END);
+		case WXK_HOME: return KeyboardCode(VK_HOME);
+		case WXK_LEFT: return KeyboardCode(VK_LEFT);
+		case WXK_UP: return KeyboardCode(VK_UP);
+		case WXK_RIGHT: return KeyboardCode(VK_RIGHT);
+		case WXK_DOWN: return KeyboardCode(VK_DOWN);
+		case WXK_SELECT: return KeyboardCode(VK_SELECT);
+		case WXK_PRINT: return KeyboardCode(VK_PRINT);
+		case WXK_EXECUTE: return KeyboardCode(VK_EXECUTE);
+		case WXK_SNAPSHOT: return KeyboardCode(VK_SNAPSHOT);
+		case WXK_INSERT: return KeyboardCode(VK_INSERT);
+		case WXK_HELP: return KeyboardCode(VK_HELP);
+		case WXK_NUMPAD0: return KeyboardCode(VK_NUMPAD0);
+		case WXK_NUMPAD1: return KeyboardCode(VK_NUMPAD1);
+		case WXK_NUMPAD2: return KeyboardCode(VK_NUMPAD2);
+		case WXK_NUMPAD3: return KeyboardCode(VK_NUMPAD3);
+		case WXK_NUMPAD4: return KeyboardCode(VK_NUMPAD4);
+		case WXK_NUMPAD5: return KeyboardCode(VK_NUMPAD5);
+		case WXK_NUMPAD6: return KeyboardCode(VK_NUMPAD6);
+		case WXK_NUMPAD7: return KeyboardCode(VK_NUMPAD7);
+		case WXK_NUMPAD8: return KeyboardCode(VK_NUMPAD8);
+		case WXK_NUMPAD9: return KeyboardCode(VK_NUMPAD9);
+		case WXK_MULTIPLY: return KeyboardCode(VK_MULTIPLY);
+		case WXK_ADD: return KeyboardCode(VK_ADD);
+		case WXK_SEPARATOR: return KeyboardCode(VK_SEPARATOR);
+		case WXK_SUBTRACT: return KeyboardCode(VK_SUBTRACT);
+		case WXK_DECIMAL: return KeyboardCode(VK_DECIMAL);
+		case WXK_DIVIDE: return KeyboardCode(VK_DIVIDE);
+		case WXK_F1: return KeyboardCode(VK_F1);
+		case WXK_F2: return KeyboardCode(VK_F2);
+		case WXK_F3: return KeyboardCode(VK_F3);
+		case WXK_F4: return KeyboardCode(VK_F4);
+		case WXK_F5: return KeyboardCode(VK_F5);
+		case WXK_F6: return KeyboardCode(VK_F6);
+		case WXK_F7: return KeyboardCode(VK_F7);
+		case WXK_F8: return KeyboardCode(VK_F8);
+		case WXK_F9: return KeyboardCode(VK_F9);
+		case WXK_F10: return KeyboardCode(VK_F10);
+		case WXK_F11: return KeyboardCode(VK_F11);
+		case WXK_F12: return KeyboardCode(VK_F12);
+		case WXK_F13: return KeyboardCode(VK_F13);
+		case WXK_F14: return KeyboardCode(VK_F14);
+		case WXK_F15: return KeyboardCode(VK_F15);
+		case WXK_F16: return KeyboardCode(VK_F16);
+		case WXK_F17: return KeyboardCode(VK_F17);
+		case WXK_F18: return KeyboardCode(VK_F18);
+		case WXK_F19: return KeyboardCode(VK_F19);
+		case WXK_F20: return KeyboardCode(VK_F20);
+		case WXK_F21: return KeyboardCode(VK_F21);
+		case WXK_F22: return KeyboardCode(VK_F22);
+		case WXK_F23: return KeyboardCode(VK_F23);
+		case WXK_F24: return KeyboardCode(VK_F24);
+		case WXK_NUMLOCK: return KeyboardCode(VK_NUMLOCK);
+		case WXK_SCROLL: return KeyboardCode(VK_SCROLL);
+		case WXK_PAGEUP: return KeyboardCode(VK_PRIOR);
+		case WXK_PAGEDOWN: return KeyboardCode(VK_NEXT);
+		case WXK_NUMPAD_SPACE: return KeyboardCode(VK_SPACE);
+		case WXK_NUMPAD_TAB: return KeyboardCode(VK_TAB);
+		case WXK_NUMPAD_ENTER: return KeyboardCode(VK_RETURN);
+		case WXK_NUMPAD_F1: return KeyboardCode(VK_F1);
+		case WXK_NUMPAD_F2: return KeyboardCode(VK_F2);
+		case WXK_NUMPAD_F3: return KeyboardCode(VK_F3);
+		case WXK_NUMPAD_F4: return KeyboardCode(VK_F4);
+		case WXK_NUMPAD_HOME: return KeyboardCode(VK_HOME);
+		case WXK_NUMPAD_LEFT: return KeyboardCode(VK_LEFT);
+		case WXK_NUMPAD_UP: return KeyboardCode(VK_UP);
+		case WXK_NUMPAD_RIGHT: return KeyboardCode(VK_RIGHT);
+		case WXK_NUMPAD_DOWN: return KeyboardCode(VK_DOWN);
+		case WXK_NUMPAD_PAGEUP: return KeyboardCode(VK_PRIOR);
+		case WXK_NUMPAD_PAGEDOWN: return KeyboardCode(VK_NEXT);
+		case WXK_NUMPAD_END: return KeyboardCode(VK_END);
+		case WXK_NUMPAD_BEGIN: return KeyboardCode(VK_NUMPAD5);
+		case WXK_NUMPAD_INSERT: return KeyboardCode(VK_INSERT);
+		case WXK_NUMPAD_DELETE: return KeyboardCode(VK_DELETE);		
+		case WXK_NUMPAD_MULTIPLY: return KeyboardCode(VK_MULTIPLY);
+		case WXK_NUMPAD_ADD: return KeyboardCode(VK_ADD);
+		case WXK_NUMPAD_SEPARATOR: return KeyboardCode(VK_SEPARATOR);
+		case WXK_NUMPAD_SUBTRACT: return KeyboardCode(VK_SUBTRACT);
+		case WXK_NUMPAD_DECIMAL: return KeyboardCode(VK_DECIMAL);
+		case WXK_NUMPAD_DIVIDE: return KeyboardCode(VK_DIVIDE);
+		
+		// the following key codes are only generated under Windows currently
+		case WXK_WINDOWS_LEFT: return KeyboardCode(VK_LWIN);
+		case WXK_WINDOWS_RIGHT: return KeyboardCode(VK_RWIN);
+		case WXK_WINDOWS_MENU: return KeyboardCode(VK_APPS);
+		case WXK_SPACE: return KeyboardCode(VK_SPACE);
+		case WXK_CANCEL: return KeyboardCode(VK_CANCEL);
+		case WXK_CAPITAL: return KeyboardCode(VK_CAPITAL);
+
+		//
+		// Untranslated codes
+		//		
+		case WXK_NUMPAD_EQUAL:
+		case WXK_START:
+		case WXK_LBUTTON:
+		case WXK_RBUTTON:		
+		case WXK_MBUTTON:
+		case WXK_COMMAND:
+
+		// Hardware-specific buttons
+		case WXK_SPECIAL1:
+		case WXK_SPECIAL2:
+		case WXK_SPECIAL3:
+		case WXK_SPECIAL4:
+		case WXK_SPECIAL5:
+		case WXK_SPECIAL6:
+		case WXK_SPECIAL7:
+		case WXK_SPECIAL8:
+		case WXK_SPECIAL9:
+		case WXK_SPECIAL10:
+		case WXK_SPECIAL11:
+		case WXK_SPECIAL12:
+		case WXK_SPECIAL13:
+		case WXK_SPECIAL14:
+		case WXK_SPECIAL15:
+		case WXK_SPECIAL16:
+		case WXK_SPECIAL17:
+		case WXK_SPECIAL18:
+		case WXK_SPECIAL19:
+		case WXK_SPECIAL20:
+			assert (false);
+			return KeyboardCode(0);
+			break;
+	}
+
+	return KeyboardCode(0);
+#endif
+}
+#endif
diff --git a/src/mod_hid/keyboardcode.h b/src/mod_hid/keyboardcode.h
new file mode 100644
index 0000000..37410b7
--- /dev/null
+++ b/src/mod_hid/keyboardcode.h
@@ -0,0 +1,241 @@
+/////////////////////////////////////////////////////////////////////////////
+// Name:        keyboardcode.h
+// Author:      Cesar Mauri Loba (cesar at crea-si dot com)
+// Created:     28/09/2010
+// Copyright:   (C) 2010-12 Cesar Mauri Loba - CREA Software Systems
+// 
+//  This program is free software: you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation, either version 3 of the License, or
+//  (at your option) any later version.
+//
+//  This program is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+/////////////////////////////////////////////////////////////////////////////
+#ifndef KEYBOARDCODE_H
+#define KEYBOARDCODE_H
+
+
+// DEBUG
+//#define USING_WXWIDGETS
+// DEBUG
+
+#ifdef USING_WXWIDGETS
+	#include <wx/string.h>
+#endif
+
+#if !defined(WIN32)
+	#include <X11/Xlib.h>
+#endif
+
+class KeyboardCode
+{
+public:
+	// EUnicode is used to encode a character using Unicode plus additional
+	// keystrokes. These are defined using standard special purpose ASCII codes
+	// (e.g. BACKSPACE) or Private Use Area of Unicode.
+	enum EUnicode {
+		KC_BACK=	0x8,
+		KC_TAB=		0x9,
+		KC_RETURN=	0xD,
+		KC_ESCAPE=	0x1B,
+		KC_SPACE=	0x20,
+		KC_DELETE=	0x7F,
+
+		// Unicode PUA
+		KC_FIRST= 0xE000,
+		KC_CLEAR= KC_FIRST,
+		KC_SHIFT,
+		KC_LSHIFT,
+		KC_RSHIFT,
+		KC_CONTROL,
+		KC_LCONTROL,
+		KC_RCONTROL,
+		KC_MENU,
+		KC_PAUSE,
+		KC_CAPSLOCK,
+		KC_PAGEUP,
+		KC_PAGEDOWN,
+		KC_END,
+		KC_HOME,
+		KC_LEFT,
+		KC_UP,
+		KC_RIGHT,
+		KC_DOWN,
+		KC_SELECT,
+		KC_PRINT,
+		KC_EXECUTE,
+		KC_SNAPSHOT,
+		KC_INSERT,
+		KC_HELP,
+		KC_CANCEL,
+		KC_ALT,
+		KC_LALT,
+		KC_RALT,
+		KC_NUMPAD0,
+		KC_NUMPAD1,
+		KC_NUMPAD2,
+		KC_NUMPAD3,
+		KC_NUMPAD4,
+		KC_NUMPAD5,
+		KC_NUMPAD6,
+		KC_NUMPAD7,
+		KC_NUMPAD8,
+		KC_NUMPAD9,
+		KC_MULTIPLY,
+		KC_ADD,
+		KC_SEPARATOR,
+		KC_SUBTRACT,
+		KC_DECIMAL,
+		KC_DIVIDE,
+		KC_F1,
+		KC_F2,
+		KC_F3,
+		KC_F4,
+		KC_F5,
+		KC_F6,
+		KC_F7,
+		KC_F8,
+		KC_F9,
+		KC_F10,
+		KC_F11,
+		KC_F12,
+		KC_F13,
+		KC_F14,
+		KC_F15,
+		KC_F16,
+		KC_F17,
+		KC_F18,
+		KC_F19,
+		KC_F20,
+		KC_F21,
+		KC_F22,
+		KC_F23,
+		KC_F24,
+		KC_NUMLOCK,
+		KC_SCROLL,
+		KC_NUMPAD_SPACE,
+		KC_NUMPAD_TAB,
+		KC_NUMPAD_ENTER,
+		KC_NUMPAD_HOME,
+		KC_NUMPAD_LEFT,
+		KC_NUMPAD_UP,
+		KC_NUMPAD_RIGHT,
+		KC_NUMPAD_DOWN,
+		KC_NUMPAD_PAGEUP,
+		KC_NUMPAD_PAGEDOWN,
+		KC_NUMPAD_END,
+		KC_NUMPAD_BEGIN,
+		KC_NUMPAD_INSERT,
+		KC_NUMPAD_DELETE,
+		KC_NUMPAD_EQUAL,
+		KC_NUMPAD_MULTIPLY,
+		KC_NUMPAD_ADD,
+		KC_NUMPAD_SEPARATOR,
+		KC_NUMPAD_SUBTRACT,
+		KC_NUMPAD_DECIMAL,
+		KC_NUMPAD_DIVIDE,
+		KC_WINDOWS_LEFT,
+		KC_WINDOWS_RIGHT,
+		KC_WINDOWS_MENU,
+		KC_LAST= KC_WINDOWS_MENU
+	};
+
+	// Default constructor. Initializes internal keycode to a invalid value
+    KeyboardCode() : m_keyCode(0) {}
+	
+	// Default destructor, copy constructor and copy operator are fine
+	bool operator==(const KeyboardCode &other) const {
+		return m_keyCode== other.m_keyCode;
+	}
+
+	bool operator!=(const KeyboardCode &other) const {
+		return !(*this== other);
+	} 
+	
+	// Get its readable name
+	const char* GetName() const;
+
+	// Send a keystoke to the system
+	void SendKeystroke();
+
+	// TODO: for future use
+	// void SendCharacter();
+
+	bool IsValid() const { return m_keyCode!= 0; }
+	
+	// Reads a keycode from keyboard and returns a KeyboardCode object
+	static 
+	KeyboardCode ReadKeyCode();
+
+	// Given an scan code returns the corresponding KeyboardCode object
+	static 
+	KeyboardCode FromScanCode (unsigned int scanCode);
+
+	// Given a platform dependent virtual-key or KeySym returns the 
+	// corresponding KeyboardCode object
+	static 
+	KeyboardCode FromVirtualKeyCode (unsigned long kCode);
+
+	// Given an EUnicode value which could include any 8 bit latin1 character,
+	// a full unicode character or a special EUnicode value as defined above
+	static
+	KeyboardCode FromEUnicode (unsigned int kc);
+
+	// Given the name of the key (which is formed removing th prepending KC_ of the
+	// entries in the EUnicode enumeration or its printed character (only ascii standard 
+	// characters are supported currently) returns its KeyboardCode. 
+	static
+	KeyboardCode FromKeyName (const char *kname);
+
+	// Set the internal raw value. NOTE: intended only
+	// for storage purposes not to work with
+	static 
+	KeyboardCode FromRawValue (unsigned long kc);
+
+	// Get the internal raw value. NOTE: intended only
+	// for storage purposes not to work with
+	unsigned long GetRawValue() const;
+
+#ifdef USING_WXWIDGETS
+	// Given an wxKeyCode code returns the corresponding KeyboardCode object
+	static KeyboardCode FromWXKeyCode (wxKeyCode kc);
+#endif
+
+#if !defined(NDEBUG)
+	void Dump() const;
+#endif	
+private:
+	// Stores the virtual key code. This corresponds to a unique key
+	// after taking into account the keyboard layout (the keyboard
+	// returns a scan code which, using the layout, is	ed to 
+	// this value). In Unix systems this corresponds to KeySym
+	// while for Windows systems it is called virtual-key code.
+#if defined(WIN32)
+	// Construct object from an EUnicode entry
+	KeyboardCode(unsigned int code) : m_keyCode(code) {}
+	
+	// On Windows store a EUnicode as a full 32bit integer,
+	// although WIN32 works internally with UTF-16.
+	unsigned int m_keyCode;
+	enum { KEY_CODE_NAME_LENGHT= 100 };
+	// TODO. NOT THREAD SAFE. Use thread-local storage. 
+	// Note that VS keyword __declspec(thread) does not work with DLLs loaded using LoadLibrary()
+	// See: http://msdn.microsoft.com/en-us/library/2s9wt68x.aspx
+	static char g_keyCodeName[KEY_CODE_NAME_LENGHT];	
+#else
+	// Construct object from a KeySym
+	KeyboardCode(KeySym code) : m_keyCode(code) { }
+	
+	KeySym m_keyCode;
+	static Display* getDisplay();
+#endif
+	
+};
+
+#endif
diff --git a/src/mod_hid/mod_hid.cpp b/src/mod_hid/mod_hid.cpp
new file mode 100644
index 0000000..7917048
--- /dev/null
+++ b/src/mod_hid/mod_hid.cpp
@@ -0,0 +1,214 @@
+/////////////////////////////////////////////////////////////////////////////
+// File:        mod_hid.cpp
+// Author:      Cesar Mauri Loba (cesar at crea-si dot com)
+// Copyright:   (C) 2011 Cesar Mauri Loba - CREA Software Systems
+//
+//  This program is free software: you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation, either version 3 of the License, or
+//  (at your option) any later version.
+//
+//  This program is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+/////////////////////////////////////////////////////////////////////////////
+#include "spcore/component.h"
+#include "spcore/module.h"
+#include "spcore/libimpexp.h"
+#include "spcore/basictypes.h"
+
+#include "mousecontrol.h"
+#include "keyboardcode.h"
+
+#include <string.h>
+
+using namespace spcore;
+
+namespace mod_hid {
+
+/**
+	mouse_output component
+
+		Send mouse events.
+		
+	Input pins:
+		left_click (any)	- Perform left click when message received.
+		right_click (any)	- Perform right click when message received.
+		middle_click (any)	- Perform middle click when message received.
+	
+	Ouput pins:		
+
+	Command line:
+*/
+class MouseOutput : public CComponentAdapter {
+public:
+	static const char* getTypeName() { return "mouse_output"; }
+	virtual const char* GetTypeName() const { return MouseOutput::getTypeName(); }
+	MouseOutput(const char * name, int argc, const char * argv[]) 
+	: CComponentAdapter(name, argc, argv)
+	{
+
+		if (RegisterInputPin(*SmartPtr<IInputPin>(new InputPinClick("left_click", *this, MouseOutput::LEFT_CLICK), false))!= 0)
+			throw std::runtime_error("error creating input pin left_click");
+
+		if (RegisterInputPin(*SmartPtr<IInputPin>(new InputPinClick("right_click", *this, MouseOutput::RIGHT_CLICK), false))!= 0)
+			throw std::runtime_error("error creating input pin right_click");
+
+		if (RegisterInputPin(*SmartPtr<IInputPin>(new InputPinClick("middle_click", *this, MouseOutput::MIDDLE_CLICK), false))!= 0)
+			throw std::runtime_error("error creating input pin middle_click");
+	}
+
+	enum EClickType { LEFT_CLICK= 0, RIGHT_CLICK= 1, MIDDLE_CLICK= 2 } ;
+
+private:
+	virtual ~MouseOutput() {}
+
+	class InputPinClick : public CInputPinWriteOnly<CTypeAny, MouseOutput> {
+	public:
+		InputPinClick (const char * name, MouseOutput & component, MouseOutput::EClickType ct)
+		: CInputPinWriteOnly<CTypeAny, MouseOutput>(name, component) 
+		, m_clickType(ct) 
+		{			
+		}
+
+		virtual int DoSend(const CTypeAny & ) {
+			switch (m_clickType) {
+				case MouseOutput::LEFT_CLICK:
+					this->m_component->m_mouseControl.LeftClick();
+					break;
+				case MouseOutput::RIGHT_CLICK:
+					this->m_component->m_mouseControl.RightClick();
+					break;
+				case MouseOutput::MIDDLE_CLICK:
+					this->m_component->m_mouseControl.MiddleClick();
+					break;
+				default:
+					assert(false);
+			}
+			return 0;
+		}
+
+	private:
+		MouseOutput::EClickType m_clickType;
+	};
+
+	//
+	// Data members
+	//
+	CMouseControl m_mouseControl;
+};
+
+typedef ComponentFactory<MouseOutput> MouseOutputFactory;
+
+/**
+	keystroke_mouse_output component
+
+		Send keystrokes or mouse events. Note that that for keystrokes it only 
+		emulates the corresponding keypress regarless the CONTROL, SHIFT and ALT
+		states needed to form a certain character.
+
+		
+	Input pins:
+		event_name (string)	- Name of the event to send
+			Available mouse events: 
+				MOUSE_LEFT,	MOUSE_RIGHT, MOUSE_MIDDLE
+			Available keyboard events:
+				BACK, TAB, RETURN, ESCAPE, SPACE, DELETE, CLEAR, SHIFT, LSHIFT, RSHIFT, 
+				CONTROL, LCONTROL, RCONTROL, MENU, PAUSE, CAPSLOCK, PAGEUP, PAGEDOWN, 
+				END, HOME, LEFT, UP, RIGHT, DOWN, SELECT, PRINT, EXECUTE, SNAPSHOT, 
+				INSERT, HELP, CANCEL, ALT, LALT, RALT, NUMPAD0, NUMPAD1, NUMPAD2, NUMPAD3, 
+				NUMPAD4, NUMPAD5, NUMPAD6, NUMPAD7, NUMPAD8, NUMPAD9, MULTIPLY, ADD, 
+				SEPARATOR, SUBTRACT, DECIMAL, DIVIDE, F1, F2, F3, F4, F5, F6, F7, F8, F9, 
+				F10, F11, F12, F13, F14, F15, F16, F17, F18, F19, F20, F21, F22, F23, F24, 
+				NUMLOCK, SCROLL, NUMPAD_SPACE, NUMPAD_TAB, NUMPAD_ENTER, NUMPAD_HOME, 
+				NUMPAD_LEFT, NUMPAD_UP, NUMPAD_RIGHT, NUMPAD_DOWN, NUMPAD_PAGEUP, 
+				NUMPAD_PAGEDOWN, NUMPAD_END, NUMPAD_BEGIN, NUMPAD_INSERT, NUMPAD_DELETE, 
+				NUMPAD_EQUAL, NUMPAD_MULTIPLY, NUMPAD_ADD, NUMPAD_SEPARATOR, NUMPAD_SUBTRACT, 
+				NUMPAD_DECIMAL, NUMPAD_DIVIDE, WINDOWS_LEFT, WINDOWS_RIGHT,WINDOWS_MENU
+				and standard ASCII characters
+	Ouput pins:		
+
+	Command line:
+*/
+class KeystrokeMouseOutput : public CComponentAdapter {
+public:
+	static const char* getTypeName() { return "keystroke_mouse_output"; }
+	virtual const char* GetTypeName() const { return KeystrokeMouseOutput::getTypeName(); }
+	KeystrokeMouseOutput(const char * name, int argc, const char * argv[]) 
+	: CComponentAdapter(name, argc, argv)
+	{
+		if (RegisterInputPin(*SmartPtr<IInputPin>(new InputPinEventName("event_name", *this), false))!= 0)
+			throw std::runtime_error("error creating input pin event_name");
+	}
+
+private:
+	virtual ~KeystrokeMouseOutput() {}
+
+	class InputPinEventName : public CInputPinWriteOnly<CTypeString, KeystrokeMouseOutput> {
+	public:
+		InputPinEventName (const char * name, KeystrokeMouseOutput & component)
+		: CInputPinWriteOnly<CTypeString, KeystrokeMouseOutput>(name, component) 
+		{			
+		}
+
+		#if defined(WIN32)
+			#define strcasecmp stricmp
+		#endif
+
+		virtual int DoSend(const CTypeString & name) {
+			if (strcasecmp(name.getValue(), "MOUSE_LEFT")== 0)
+				this->m_component->m_mouseControl.LeftClick();
+			else if (strcasecmp(name.getValue(), "MOUSE_RIGHT")== 0)
+				this->m_component->m_mouseControl.RightClick();
+			else if (strcasecmp(name.getValue(), "MOUSE_MIDDLE")== 0)
+				this->m_component->m_mouseControl.MiddleClick();
+			else {
+				// Keyboard event
+				KeyboardCode c= KeyboardCode::FromKeyName(name.getValue());
+				if (c.IsValid()) c.SendKeystroke();
+			}
+			return 0;
+		}
+	};
+
+	//
+	// Data members
+	//
+	CMouseControl m_mouseControl;
+
+};
+
+typedef ComponentFactory<KeystrokeMouseOutput> KeystrokeMouseOutputFactory;
+
+
+/* ******************************************************************************
+	hid  module
+****************************************************************************** */
+class HidModule : public CModuleAdapter {
+public:
+	HidModule() {
+		//
+		// components
+		//
+		RegisterComponentFactory(SmartPtr<spcore::IComponentFactory>(new MouseOutputFactory(), false));
+		RegisterComponentFactory(SmartPtr<spcore::IComponentFactory>(new KeystrokeMouseOutputFactory(), false));
+	}
+
+	~HidModule() {
+	}
+
+	virtual const char * GetName() const { return "mod_hid"; }
+};
+
+static spcore::IModule* g_module= NULL;
+SPEXPORT_FUNCTION spcore::IModule* module_create_instance()
+{
+	if (g_module== NULL) g_module= new HidModule();
+	return g_module;
+}
+
+};
diff --git a/src/mod_hid/mousecontrol.cpp b/src/mod_hid/mousecontrol.cpp
new file mode 100644
index 0000000..83c6a6c
--- /dev/null
+++ b/src/mod_hid/mousecontrol.cpp
@@ -0,0 +1,552 @@
+/////////////////////////////////////////////////////////////////////////////
+// Name:        mousecontrol.cpp
+// Purpose: cross platform mouse control api
+// Author:      Cesar Mauri Loba (cesar at crea-si dot com)
+// Modified by: 
+// Created:     
+// Copyright:   (C) 2008-11 Cesar Mauri Loba - CREA Software Systems
+// 
+//  This program is free software: you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation, either version 3 of the License, or
+//  (at your option) any later version.
+//
+//  This program is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+/////////////////////////////////////////////////////////////////////////////
+
+// TODO: under X11. Test XTest extensions enabled
+//if(!XTestQueryExtension(display, &ev, &er, &ma, &mi))
+//{
+//fprintf(stderr, "XTest extension not supported on server.\n");
+//exit(1);
+//}
+#include <math.h>
+#include <stdio.h>
+
+#if defined(WIN32)
+//
+// Windows
+//
+#define _WIN32_WINNT 0x0500
+#include <windows.h>
+#define MOUSE_EXTRA_INFO 69
+
+inline float roundf(float x) { return (x-floorf(x))>0.5 ? ceilf(x) : floorf(x); }
+
+#else	// WIN32
+//
+// Linux
+//
+#include <X11/extensions/XTest.h>
+#include <stdexcept>
+
+#endif // WIN32
+
+#include <assert.h>
+#include <string.h>
+#include "mousecontrol.h"
+
+// Mouse actions
+#define MOUSE_MOVE_ABS	0x8000		// Absolute motion
+#define MOUSE_MOVE_REL	0x0000		// Relative motion
+#define MOUSE_LEFTDOWN  0x0002		// Left button down
+#define MOUSE_LEFTUP    0x0004		// Left button up
+#define MOUSE_RIGHTDOWN   0x0008	// Right button down
+#define MOUSE_RIGHTUP     0x0010	// Right button up 
+#define MOUSE_MIDDLEDOWN  0x0020	// Middle button down
+#define MOUSE_MIDDLEUP    0x0040	// Middle button up 
+
+CMouseControl::CMouseControl (void* pDisplay)
+: m_enabledRestrictedWorkingArea(false)
+, m_enabledWrapPointer(false)
+#if !defined(WIN32)
+, m_closeDisplay(false)
+#endif
+{
+	m_leftPercent= m_rightPercent= m_topPercent= m_bottomPercent= 1.0f;
+        
+	// Under Windows display parameter is ignored
+	#if defined(WIN32)
+	assert (pDisplay== NULL);
+	#else
+	if (pDisplay) m_pDisplay= (Display *) pDisplay;
+	else {
+		m_pDisplay= XOpenDisplay(NULL);
+		m_closeDisplay= true;
+		assert (m_pDisplay);
+		if (!m_pDisplay) throw std::runtime_error("mousecontrol: cannot open display");
+	}	
+	#endif	
+
+	// Read screen size
+	OnDisplayChanged ();
+
+	m_VirtualXIni= m_VirtualYIni= 0;
+	m_VirtualHeight= (float) m_ScreenHeight; 
+	m_VirtualWidth= (float) m_ScreenWidth;
+
+	ResetClickArea ();
+
+	m_fDx= m_fDy= 1.0f;
+	m_minDeltaThreshold= 0.0f;
+	m_actualMotionWeight= 1.0f;
+	m_dxant= 0.0f; m_dyant= 0.0f;
+
+	for (int i= 0; i< ACCEL_ARRAY_SIZE; i++) m_accelArray[i]= (float) 1;
+}
+
+CMouseControl::~CMouseControl()
+{
+#if !defined(WIN32)
+	if (m_closeDisplay) XCloseDisplay(m_pDisplay);
+#endif
+}
+
+void CMouseControl::GetScreenSize()
+{
+#if defined(WIN32)
+	DEVMODE devMode;
+	// Get screen size. TODO: test with multiple displays
+	BOOL retval= EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &devMode);
+	if (!retval) { exit (-1); }
+
+	m_ScreenHeight= devMode.dmPelsHeight;
+	m_ScreenWidth= devMode.dmPelsWidth;
+#else // Linux
+//	BEGIN_GUI_CALL_MUTEX();
+	m_ScreenHeight= DisplayHeight (m_pDisplay, DefaultScreen (m_pDisplay));
+	m_ScreenWidth= DisplayWidth (m_pDisplay, DefaultScreen (m_pDisplay));
+//	END_GUI_CALL_MUTEX();	
+#endif
+
+}
+
+void CMouseControl::GetPointerLocation (long& x, long& y)
+{
+#if defined(WIN32)
+
+	CURSORINFO pci;
+
+	pci.cbSize= sizeof(CURSORINFO);
+	pci.ptScreenPos.x= 0;
+	pci.ptScreenPos.y= 0;
+
+	GetCursorInfo(&pci);
+
+	x= pci.ptScreenPos.x;
+	y= pci.ptScreenPos.y;
+
+#else // Linux
+	
+	Window root, child;
+	int rootX, rootY, winX, winY;
+	unsigned int xstate;
+
+//	BEGIN_GUI_CALL_MUTEX();
+	Window rootWin= RootWindow (m_pDisplay, DefaultScreen (m_pDisplay));
+	XQueryPointer( m_pDisplay, rootWin, &root, &child, &rootX, &rootY, &winX, &winY, &xstate );
+//	END_GUI_CALL_MUTEX();
+	x= winX;
+	y= winY;
+#endif
+}
+
+void CMouseControl::OnDisplayChanged ()
+{
+	GetScreenSize();
+	RecomputeWorkingArea ();
+}
+
+void CMouseControl::SetAbsVirtualResolution (float xIni, float yIni, float width, float height)
+{
+	assert (xIni>= 0 && yIni>= 0 && width> 0 && height> 0);
+	
+	m_VirtualXIni= xIni;
+	m_VirtualYIni= yIni;
+	m_VirtualWidth= width;
+	m_VirtualHeight= height;
+}
+
+void CMouseControl::SetWorkingArea (float leftPercent, float rightPercent, float topPercent, float bottomPercent)
+{
+	SetTopPercent (topPercent);		
+	SetLeftPercent (leftPercent);
+	SetRightPercent (rightPercent);
+	SetBottomPercent (bottomPercent);
+}
+
+void CMouseControl::RecomputeWorkingArea ()
+{
+	m_minScreenX=	(m_ScreenWidth - 
+					 (int) ((float) m_ScreenWidth * m_leftPercent)) / 2;
+	m_minScreenY=	(m_ScreenHeight - 
+					 (int) ((float) m_ScreenHeight * m_topPercent)) / 2;
+	m_maxScreenX=	(m_ScreenWidth - 1) - (m_ScreenWidth - 
+					 (int) ((float) m_ScreenWidth * m_rightPercent)) / 2;
+	m_maxScreenY=	(m_ScreenHeight - 1) - (m_ScreenHeight - 
+					 (int) ((float) m_ScreenHeight * m_bottomPercent)) / 2;
+}
+
+void CMouseControl::SetClickArea (long minX, long minY, long maxX, long maxY)
+{
+	assert (minX>= 0 && minY>= 0);
+	assert (maxX< m_ScreenWidth && maxY< m_ScreenHeight);
+
+	m_minClicAreaX= minX;
+	m_minClicAreaY= minY;
+	m_maxClicAreaX= maxX;
+	m_maxClicAreaY= maxY;
+}
+
+void CMouseControl::ResetClickArea ()
+{
+	m_minClicAreaX= m_minClicAreaY= 0;
+	m_maxClicAreaX= m_maxScreenX;
+	m_maxClicAreaY= m_maxScreenY;
+}
+
+bool CMouseControl::CheckClickArea ()
+{
+	long x, y;
+
+	GetPointerLocation (x, y);
+	
+	return (x>= m_minClicAreaX && x<= m_maxClicAreaX &&
+			y>= m_minClicAreaY && y<= m_maxClicAreaY );		
+}
+
+void CMouseControl::SetRelAcceleration2 (long delta0, float factor0,
+						long delta1, float factor1)
+{
+	assert (delta0> 2 &&delta1> 2); 
+	assert (factor0> 0.0f && factor1> 0.0f);
+	
+	if (delta0>= ACCEL_ARRAY_SIZE) delta0= ACCEL_ARRAY_SIZE;
+	if (delta1>= ACCEL_ARRAY_SIZE) delta1= ACCEL_ARRAY_SIZE;
+
+	int i;
+
+	for (i= 0; i< delta0; i++) m_accelArray[i]= 1;
+	for (;i< delta1; i++) m_accelArray[i]= factor0;
+	float j= 0;
+	for (;i< ACCEL_ARRAY_SIZE; i++) {
+		m_accelArray[i]= factor0 * factor1 + j;
+		j+= 0.1f;
+	}
+}
+
+bool CMouseControl::EnforceWorkingAreaLimits (long &x, long &y)
+{
+	bool retval= false;
+
+	if (x< m_minScreenX) { x= m_minScreenX; retval= true; }
+	else if (x> m_maxScreenX) { x= m_maxScreenX; retval= true; }
+	
+	if (y< m_minScreenY) { y= m_minScreenY; retval= true; }
+	else if (y> m_maxScreenY) { y= m_maxScreenY; retval= true; }
+
+	return retval;
+}
+
+void CMouseControl::Virt2Fis (float virtX, float virtY, float &fisX, float &fisY)
+{
+	float fFisX, fFisY, fVirtWidth, fVirtHeight;
+
+	fFisX= virtX - m_VirtualXIni;
+	fFisY= virtY - m_VirtualYIni;
+	fVirtWidth= m_VirtualWidth; 
+	fVirtHeight= m_VirtualHeight;
+
+	if (fFisX< 0.0f) fFisX= 0.0f;
+	else if (fFisX>= fVirtWidth) fFisX= 1.0f; 
+	else fFisX/= fVirtWidth;
+
+	if (fFisY< 0.0f) fFisY= 0.0f;
+	else if (fFisY>= fVirtHeight) fFisY= 1.0f; 
+	else fFisY/= fVirtHeight;
+
+	// To integer
+	fisX= fFisX * (float) (m_ScreenWidth - 1);
+	fisY= fFisY * (float) (m_ScreenHeight - 1);
+}
+
+void CMouseControl::MovePointerAbs (float x, float y)
+{
+//	OnDisplayChanged ();
+
+	long iX, iY;
+	float fisX, fisY, dx, dy;	
+
+	Virt2Fis (x, y, fisX, fisY);
+
+	GetPointerLocation (iX, iY);	
+	dx= fisX - (float) iX;
+	dy= fisY - (float) iY;
+	
+	// Low-pass filter	
+	dx= dx * (1.0f - m_actualMotionWeight) + m_dxant * m_actualMotionWeight;
+	dy= dy * (1.0f - m_actualMotionWeight) + m_dyant * m_actualMotionWeight;
+	m_dxant= dx; m_dyant= dy;
+
+	// Map to screen coordinates
+	iX= iX + (long) dx;
+	iY= iY + (long) dy;
+	
+	EnforceWorkingAreaLimits (iX, iY);
+	DoMovePointerAbs (iX, iY);
+}
+
+float CMouseControl::MovePointerRel (float dx, float dy, int* dxRes, int* dyRes)
+{
+	OnDisplayChanged ();
+
+	// Apply factors
+	dx*= m_fDx;
+	dy*= m_fDy;
+
+	// Low-pass filter	
+	dx= dx * (1.0f - m_actualMotionWeight) + m_dxant * m_actualMotionWeight;
+	dy= dy * (1.0f - m_actualMotionWeight) + m_dyant * m_actualMotionWeight;
+	m_dxant= dx; m_dyant= dy;
+
+	// Acceleration
+	float distance= (float) ::sqrt (dx * dx + dy * dy);
+
+	unsigned int iAccelArray= (unsigned int) (distance + 0.5f);
+	if (iAccelArray>= ACCEL_ARRAY_SIZE) iAccelArray= ACCEL_ARRAY_SIZE - 1;
+	dx*= m_accelArray[iAccelArray];
+	dy*= m_accelArray[iAccelArray];
+
+	// Apply delta threshold
+	if (-m_minDeltaThreshold < dx && dx < m_minDeltaThreshold) dx= 0.0f;
+	if (-m_minDeltaThreshold < dy && dy < m_minDeltaThreshold) dy= 0.0f;
+	
+	int idx= (int) roundf(dx);
+	int idy= (int) roundf(dy);
+	long mouseX, mouseY;
+	if (m_enabledRestrictedWorkingArea && !m_enabledWrapPointer) {
+		GetPointerLocation (mouseX, mouseY);
+		if (mouseX + idx< m_minScreenX) idx= m_minScreenX - mouseX;
+		else if (mouseX + idx > m_maxScreenX) idx= m_maxScreenX - mouseX;
+		if (mouseY + idy < m_minScreenY) idy= m_minScreenY - mouseY;
+		else if (mouseY + idy > m_maxScreenY) idy= m_maxScreenY - mouseY;
+	}
+	
+	if (m_enabledWrapPointer) {
+		int minWrapX= 0;
+		int maxWrapX= m_ScreenWidth;
+		int minWrapY= 0;
+		int maxWrapY= m_ScreenHeight;
+				
+		if (m_enabledRestrictedWorkingArea) {
+			minWrapX= m_minScreenX;
+			maxWrapX= m_maxScreenX;
+			minWrapY= m_minScreenY;
+			maxWrapY= m_maxScreenY;
+		}
+
+		GetPointerLocation(mouseX, mouseY);
+		if (mouseX + idx < minWrapX) {
+			idx -= mouseX - minWrapX;
+			DoMovePointerAbs(maxWrapX, mouseY);
+		}		
+		if (mouseX + idx > maxWrapX) {
+			idx -= maxWrapX - mouseX;
+			DoMovePointerAbs(minWrapX, mouseY);
+		}
+		if (mouseY + idy < minWrapY) {
+			idy -= mouseY - minWrapY;
+			DoMovePointerAbs(mouseX, maxWrapY);
+		}
+		if (mouseY + idy > maxWrapY) {
+			idy -= maxWrapY - mouseY;
+			DoMovePointerAbs(mouseX, minWrapY);
+		}
+	}
+
+	DoMovePointerRel (idx, idy);
+	if (dxRes) *dxRes= idx;
+	if (dyRes) *dyRes= idy;
+
+	return (float) sqrt((double)(idx * idx + idy * idy));
+}
+
+void CMouseControl::DoMovePointerAbs (long x, long y)
+{
+	SendMouseCommand (x, y, MOUSE_MOVE_ABS);
+}
+
+void CMouseControl::DoMovePointerRel (long dx, long dy)
+{
+	SendMouseCommand (dx, dy, MOUSE_MOVE_REL);
+}
+
+// Send a mouse control system command
+void CMouseControl::SendMouseCommand (long x, long y, int flags)
+{
+#if defined(WIN32)
+	INPUT ip;
+
+	// Allways define MOUSEEVENTF_MOVE flag, other flags are coincident
+	// with native flags under windows
+	flags|= MOUSEEVENTF_MOVE;
+
+	if (flags & MOUSE_MOVE_ABS)
+	{
+		// Normalize absolute motion
+		x= (x * 65535) / (m_ScreenWidth - 1);
+		y= (y * 65535) / (m_ScreenHeight - 1);
+	}
+	ip.type = INPUT_MOUSE;
+	ip.mi.dwFlags = flags;
+	ip.mi.mouseData = 0;
+	ip.mi.dwExtraInfo = MOUSE_EXTRA_INFO;
+	ip.mi.time = 0;
+	ip.mi.dx= x;
+	ip.mi.dy= y;
+
+	SendInput(1, &ip, sizeof(ip));
+#else
+//	BEGIN_GUI_CALL_MUTEX();
+	if (flags== MOUSE_MOVE_ABS) 
+		// Absolute motion
+		XTestFakeMotionEvent(m_pDisplay, DefaultScreen(m_pDisplay), x, y, CurrentTime);
+	else if (flags== MOUSE_MOVE_REL) 
+		// Relative motion
+		XTestFakeRelativeMotionEvent(m_pDisplay, x, y, CurrentTime);		
+	else
+	{
+		// Button press
+		bool is_press= false;
+		unsigned int button= 0;;
+
+		switch (flags)
+		{		
+		case MOUSE_LEFTDOWN:  	// Left button down
+			button= 1; is_press= true;
+			break;
+		case MOUSE_LEFTUP:		// Left button up
+			button= 1; is_press= false;
+			break;
+		case MOUSE_RIGHTDOWN:	// Right button down
+			button= 3; is_press= true;
+			break;
+		case MOUSE_RIGHTUP:		// Right button up
+			button= 3; is_press= false;
+			break;
+		case MOUSE_MIDDLEDOWN:	// Middle button down
+			button= 2; is_press= true;
+			break;
+		case MOUSE_MIDDLEUP:	// Middle button up
+			button= 2; is_press= false;
+			break;
+		default:
+			assert (false);
+		}
+
+		XTestFakeButtonEvent(m_pDisplay, button, is_press, CurrentTime);
+	}
+	XFlush (m_pDisplay);
+//	END_GUI_CALL_MUTEX();
+#endif
+}
+
+void CMouseControl::CenterPointer ()
+{
+	DoMovePointerAbs(m_ScreenWidth/2, m_ScreenHeight/2);
+}
+
+bool CMouseControl::LeftDown ()
+{
+	if (CheckClickArea ()) {
+		SendMouseCommand (0, 0,	MOUSE_LEFTDOWN);
+		return true;
+	}
+
+	return false;
+}
+
+void CMouseControl::LeftUp ()
+{
+	SendMouseCommand (0, 0,	MOUSE_LEFTUP);
+}
+
+bool CMouseControl::MiddleDown ()
+{
+	if (CheckClickArea ()) {
+		SendMouseCommand (0, 0,	MOUSE_MIDDLEDOWN);
+		return true;
+	}
+
+	return false;
+}
+
+void CMouseControl::MiddleUp ()
+{
+	SendMouseCommand (0, 0,	MOUSE_MIDDLEUP);
+}
+
+bool CMouseControl::RightDown ()
+{
+	if (CheckClickArea ()) {
+		SendMouseCommand (0, 0,	MOUSE_RIGHTDOWN);
+		return true;
+	}
+	
+	return false;
+}
+
+void CMouseControl::RightUp ()
+{
+	SendMouseCommand (0, 0,	MOUSE_RIGHTUP);
+}
+
+bool CMouseControl::LeftClick ()
+{
+	if (CheckClickArea ()) {
+		LeftDown ();
+		LeftUp ();
+		return true;
+	}
+
+	return false;
+}
+
+bool CMouseControl::MiddleClick ()
+{
+	if (CheckClickArea ()) {
+		MiddleDown ();
+		MiddleUp ();
+		return true;
+	}
+
+	return false;
+}
+
+bool CMouseControl::RightClick ()
+{	
+	if (CheckClickArea ()) {
+		RightDown ();
+		RightUp ();
+		return true;
+	}
+
+	return false;
+}
+
+bool CMouseControl::LeftDblClick ()
+{
+	if (CheckClickArea ()) {
+		LeftClick ();
+		LeftClick ();
+		return true;
+	}
+
+	return false;
+}
diff --git a/src/mod_hid/mousecontrol.h b/src/mod_hid/mousecontrol.h
new file mode 100644
index 0000000..082e204
--- /dev/null
+++ b/src/mod_hid/mousecontrol.h
@@ -0,0 +1,167 @@
+/////////////////////////////////////////////////////////////////////////////
+// Name:        mousecontrol.h
+// Purpose: cross platform mouse control api
+// Author:      Cesar Mauri Loba (cesar at crea-si dot com)
+// Modified by: 
+// Created:     
+// Copyright:   (C) 2008-11 Cesar Mauri Loba - CREA Software Systems
+// 
+//  This program is free software: you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation, either version 3 of the License, or
+//  (at your option) any later version.
+//
+//  This program is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+/////////////////////////////////////////////////////////////////////////////
+#if !defined(MOUSECONTROL_H)
+#define MOUSECONTROL_H
+
+#if !defined(WIN32)
+#include <X11/Xlib.h>		// Display struct
+#endif
+#include <stdlib.h>		// NULL
+#include <assert.h>		
+
+class CMouseControl
+{
+public:
+	CMouseControl(void* pDisplay= NULL);
+	virtual ~CMouseControl();
+
+	void SetRestrictedWorkingArea (bool value) { m_enabledRestrictedWorkingArea = value; }
+	bool GetRestrictedWorkingArea() const { return m_enabledRestrictedWorkingArea; }
+	void SetWorkingArea (float leftPercent, float rightPercent, float topPercent, float bottomPercent);
+	
+	void SetWrapPointer (bool value) { m_enabledWrapPointer = value; }
+	bool GetWrapPointer() const { return m_enabledWrapPointer; }
+
+	float GetTopPercent () const { return m_topPercent; }
+	void SetTopPercent (float topPercent) { 
+		//assert (0.009f < topPercent && topPercent <= 1.0f);
+		assert (0 <= topPercent && topPercent <= 1.0f);
+		m_topPercent = topPercent; 
+	}
+	float GetLeftPercent () const { return m_leftPercent; }
+	void SetLeftPercent (float leftPercent) { 
+		assert (0 <=  leftPercent && leftPercent <= 1.0f);
+		m_leftPercent = leftPercent; 
+	}
+	float GetRightPercent () const { return m_rightPercent; }
+	void SetRightPercent (float rightPercent) { 
+		assert (0 <=  rightPercent && rightPercent <= 1.0f);
+		m_rightPercent = rightPercent; 
+	}
+	float GetBottomPercent () const { return m_bottomPercent; }
+	void SetBottomPercent (float bottomPercent) { 
+		assert (0 <=  bottomPercent && bottomPercent <= 1.0f);
+		m_bottomPercent = bottomPercent;
+	}
+	
+	void SetClickArea (long minX, long minY, long maxX, long maxY);
+	void ResetClickArea ();
+	
+	void SetAbsVirtualResolution (float xIni, float yIni, 
+								  float width, float height);
+	void SetRelFactorX (float fDx) { m_fDx= fDx; }
+	void SetRelFactorY (float fDy) { m_fDy= fDy; }
+        
+	void SetRelFactors (float fDx, float fDy) {	SetRelFactorX (fDx); SetRelFactorY (fDy); }
+	void SetRelAcceleration2 (long delta0= 9999, float factor0= 1.0f,
+					long delta1= 9999, float factor1= 1.0f);
+
+	inline float GetRelDeltaThreshold () const;
+	inline void SetRelDeltaThreshold (float deltaThreshold);
+	
+	inline float GetLowPassFilterWeight () const;
+	inline void SetLowPassFilterWeight (float w);
+	
+	void MovePointerAbs (float x, float y);
+	void DoMovePointerAbs (long x, long y);
+	float MovePointerRel (float dx, float dy, int* dxRes= NULL, int* dyRes= NULL);
+	
+	void CenterPointer ();
+
+	// Click actions
+	bool LeftDown ();
+	void LeftUp ();
+	bool MiddleDown ();
+	void MiddleUp ();
+	bool RightDown ();
+	void RightUp ();
+	bool LeftClick ();
+	bool MiddleClick ();
+	bool RightClick ();
+	bool LeftDblClick ();
+
+	void GetPointerLocation (long& x, long& y);
+
+	// Display properties change (resolution)
+	void OnDisplayChanged ();
+
+protected:
+
+	void Virt2Fis (float virtX, float virtY, float &fisX, float &fisY);
+	bool CheckClickArea ();
+	bool EnforceWorkingAreaLimits (long &x, long &y);
+	void SendMouseCommand (long x, long y, int flags);
+	
+	void DoMovePointerRel (long dx, long dy);
+	void RecomputeWorkingArea ();
+
+	// TODO: derive a X11 file stuff for these
+	void GetScreenSize();
+	
+	
+private:	
+	int m_ScreenWidth, m_ScreenHeight;
+	int m_minScreenX, m_minScreenY, m_maxScreenX, m_maxScreenY;
+	float m_leftPercent, m_rightPercent, m_topPercent, m_bottomPercent;
+	int m_minClicAreaX, m_minClicAreaY, m_maxClicAreaX, m_maxClicAreaY;
+	float m_VirtualXIni, m_VirtualYIni;
+	float m_VirtualWidth, m_VirtualHeight;
+	float m_fDx, m_fDy;
+	float m_minDeltaThreshold;
+	float m_dxant, m_dyant;
+	// Motion low pass filter (relative motion)
+	float m_actualMotionWeight;
+	bool m_enabledRestrictedWorkingArea;
+	bool m_enabledWrapPointer;
+	
+#if !defined(WIN32)
+	bool m_closeDisplay;	// Destructor should close display connection?
+	Display* m_pDisplay;
+#endif
+	enum { ACCEL_ARRAY_SIZE= 30 };
+	float m_accelArray[ACCEL_ARRAY_SIZE];
+};
+
+inline float CMouseControl::GetLowPassFilterWeight () const
+{
+	return m_actualMotionWeight;
+}
+
+inline void CMouseControl::SetLowPassFilterWeight (float w)
+{ 
+	assert (0.0f<= w && 1.0f>= w);
+	m_actualMotionWeight= w; 
+}
+
+inline float CMouseControl::GetRelDeltaThreshold () const	
+{
+	return m_minDeltaThreshold;
+}
+
+inline void CMouseControl::SetRelDeltaThreshold (float deltaThreshold)	
+{
+	assert (deltaThreshold>= 0);
+
+	m_minDeltaThreshold= deltaThreshold;
+}
+
+#endif
diff --git a/src/mod_hid/tests/CMakeLists.txt b/src/mod_hid/tests/CMakeLists.txt
new file mode 100644
index 0000000..d6cadba
--- /dev/null
+++ b/src/mod_hid/tests/CMakeLists.txt
@@ -0,0 +1,30 @@
+cmake_minimum_required(VERSION 2.8)
+project(test_mod_hid)
+
+set(test_key_codes_SRCS	
+	test_keycodes.cpp 
+	../keyboardcode.cpp
+	../keyboardcode.h
+)
+
+if(NOT WIN32)
+	set(test_key_codes_SRCS	${test_key_codes_SRCS}
+		../ucs2keysym.h
+		../ucs2keysym.c
+	)
+endif(NOT WIN32)
+	
+add_executable(test_key_codes ${test_key_codes_SRCS})
+
+if(NOT WIN32)
+	find_package(X11 REQUIRED)
+	if (NOT X11_XTest_FOUND)
+		message (FATAL_ERROR "X11_XTest extensions not found.")
+	endif(NOT X11_XTest_FOUND)
+	include_directories(${X11_INCLUDE_DIR})
+	target_link_libraries(test_key_codes ${X11_X11_LIB})
+	target_link_libraries(test_key_codes ${X11_XTest_LIB})
+endif(NOT WIN32)
+
+add_test (test_key_codes test_key_codes)
+
diff --git a/src/mod_hid/tests/test_keycodes.cpp b/src/mod_hid/tests/test_keycodes.cpp
new file mode 100644
index 0000000..0c2bf64
--- /dev/null
+++ b/src/mod_hid/tests/test_keycodes.cpp
@@ -0,0 +1,294 @@
+/////////////////////////////////////////////////////////////////////////////
+// Name:		test_keycodes.cpp
+// Author:      Cesar Mauri Loba
+// Copyright:   (C) 2012 Cesar Mauri Loba - CREA Software Systems
+//
+//  This program is free software: you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation, either version 3 of the License, or
+//  (at your option) any later version.
+//
+//  This program is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+/////////////////////////////////////////////////////////////////////////////
+#include "../keyboardcode.h"
+
+#include <ostream>
+#include <sstream>
+#include <iostream>
+#include <math.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+
+static
+void print (KeyboardCode c) {
+	printf ("Raw code: %lu, 0x%lx. Description: %s\n", c.GetRawValue(), c.GetRawValue(), c.GetName());
+}
+
+static
+void test_from_unicode () {
+
+	// Test latin1 codes
+	for (unsigned int i= 0; i< 256; ++i) {
+		KeyboardCode c= KeyboardCode::FromEUnicode (i);
+		print (c);
+	}
+
+	// Test EUnicode special codes
+	for (unsigned int i= KeyboardCode::KC_FIRST; i<= KeyboardCode::KC_LAST; ++i) {
+		KeyboardCode c= KeyboardCode::FromEUnicode (i);
+		print (c);
+	}
+}
+
+static
+void test_from_virtual_key_code () {
+#if defined(WIN32)
+	// Only on Win32, test full VK range
+	printf ("DUMPING FromVirtualKeyCodes\n");
+	for (unsigned int i= 0; i< 256; ++i) {
+		KeyboardCode c= KeyboardCode::FromVirtualKeyCode (i);
+		printf ("i: %x ", i);
+		print (c);
+	}
+#endif
+
+	// No linux test. It stores KeySym values directly.
+}
+
+static
+void test_from_scan_code () {
+	printf ("FromScanCode\n");
+	for (unsigned int i= 0; i< 256; ++i) {
+		KeyboardCode c= KeyboardCode::FromScanCode (i);
+		printf ("SC: %x ", i);
+		print (c);
+	}
+}
+
+static
+int test_write () {
+	KeyboardCode intro= KeyboardCode::FromEUnicode(KeyboardCode::KC_RETURN);
+	for (char c= '0'; c<= '9'; c++) {
+		KeyboardCode cc= KeyboardCode::FromEUnicode(c);
+		cc.SendKeystroke();
+		intro.SendKeystroke();
+		int rc= getchar();
+		if (rc!= c) {
+			printf ("Wrong read: %c, %d\n", (char) rc, rc);
+			return -1;
+		}
+		getchar();	// Remove enter
+	}
+
+	for (char c= 'a'; c<= 'z'; c++) {
+		KeyboardCode cc= KeyboardCode::FromEUnicode(c);
+		cc.SendKeystroke();
+		intro.SendKeystroke();
+		int rc= getchar();
+		if (rc!= c && rc!= c-32) {
+			printf ("Wrong read: %c, %d\n", (char) rc, rc);
+			return -1;
+		}
+		getchar();	// Remove enter
+	}
+
+	return 0;
+}
+
+static const char* knames[]= {
+	"ADD",
+	"ALT",
+	"BACK",
+	"CANCEL",
+	"CAPSLOCK",
+	"CLEAR",
+	"CONTROL",
+	"DECIMAL",
+	"DELETE",
+	"DIVIDE",
+	"DOWN",
+	"END",
+	"ESCAPE",
+	"EXECUTE",
+	"F10",
+	"F11",
+	"F12",
+	"F13",
+	"F14",
+	"F15",
+	"F16",
+	"F17",
+	"F18",
+	"F19",
+	"F1",
+	"F20",
+	"F21",
+	"F22",
+	"F23",
+	"F24",
+	"F2",
+	"F3",
+	"F4",
+	"F5",
+	"F6",
+	"F7",
+	"F8",
+	"F9",
+	"FIRST",
+	"HELP",
+	"HOME",
+	"INSERT",
+	"LALT",
+	"LCONTROL",
+	"LEFT",
+	"LSHIFT",
+	"MENU",
+	"MULTIPLY",
+	"NUMLOCK",
+	"NUMPAD0",
+	"NUMPAD1",
+	"NUMPAD2",
+	"NUMPAD3",
+	"NUMPAD4",
+	"NUMPAD5",
+	"NUMPAD6",
+	"NUMPAD7",
+	"NUMPAD8",
+	"NUMPAD9",
+	"NUMPAD_ADD",
+	"NUMPAD_BEGIN",
+	"NUMPAD_DECIMAL",
+	"NUMPAD_DELETE",
+	"NUMPAD_DIVIDE",
+	"NUMPAD_DOWN",
+	"NUMPAD_END",
+	"NUMPAD_ENTER",
+	"NUMPAD_EQUAL",
+	"NUMPAD_HOME",
+	"NUMPAD_INSERT",
+	"NUMPAD_LEFT",
+	"NUMPAD_MULTIPLY",
+	"NUMPAD_PAGEDOWN",
+	"NUMPAD_PAGEUP",
+	"NUMPAD_RIGHT",
+	"NUMPAD_SEPARATOR",
+	"NUMPAD_SPACE",
+	"NUMPAD_SUBTRACT",
+	"NUMPAD_TAB",
+	"NUMPAD_UP",
+	"PAGEDOWN",
+	"PAGEUP",
+	"PAUSE",
+	"PRINT",
+	"RALT",
+	"RCONTROL",
+	"RETURN",
+	"RIGHT",
+	"RSHIFT",
+	"SCROLL",
+	"SELECT",
+	"SEPARATOR",
+	"SHIFT",
+	"SNAPSHOT",
+	"SPACE",
+	"SUBTRACT",
+	"TAB",
+	"UP",
+	"WINDOWS_LEFT",
+	"WINDOWS_MENU",
+	"WINDOWS_RIGHT"
+};
+
+#define KNAMES_SIZE (sizeof(knames)/sizeof(char*))
+
+static
+int test_from_key_name () {
+	KeyboardCode intro= KeyboardCode::FromEUnicode(KeyboardCode::KC_RETURN);
+	char buff[2];
+	buff[1]= 0;
+
+	for (buff[0]= '0'; buff[0]<= '9'; buff[0]++) {
+		KeyboardCode cc= KeyboardCode::FromKeyName(buff);
+		cc.SendKeystroke();
+		intro.SendKeystroke();
+		int rc= getchar();
+		if (rc!= buff[0]) {
+			printf ("Wrong read: %c, %d\n", (char) rc, rc);
+			return -1;
+		}
+		getchar();	// Remove enter
+	}
+
+	for (buff[0]= 'a'; buff[0]<= 'z'; buff[0]++) {
+		KeyboardCode cc= KeyboardCode::FromKeyName(buff);
+		cc.SendKeystroke();
+		intro.SendKeystroke();
+		int rc= getchar();
+		if (rc!= buff[0] && rc!= buff[0]-32) {
+			printf ("Wrong read: %c, %d\n", (char) rc, rc);
+			return -1;
+		}
+		getchar();	// Remove enter
+	}
+
+	for (buff[0]= 32; buff[0]<= 64; buff[0]++) {
+		KeyboardCode cc= KeyboardCode::FromKeyName(buff);
+		print (cc);
+	}
+
+	for (buff[0]= 91; buff[0]<= 96; buff[0]++) {
+		KeyboardCode cc= KeyboardCode::FromKeyName(buff);
+		print (cc);
+	}
+
+	for (buff[0]= 123; buff[0]<= 126; buff[0]++) {
+		KeyboardCode cc= KeyboardCode::FromKeyName(buff);
+		print (cc);
+	}
+
+	for (unsigned int i= 0; i< KNAMES_SIZE; i++) {
+		printf("Trans: %s. ", knames[i]);
+		KeyboardCode c= KeyboardCode::FromKeyName(knames[i]);
+		print (c);
+	}
+
+	return 0;
+}
+
+int main(int, char *[]) {
+	test_from_unicode ();
+
+	test_from_virtual_key_code ();
+
+	test_from_scan_code ();
+
+#if !defined(WIN32)
+	// On Linux and without this sleep the test gets stuck waiting
+	// for a enter keypress.
+	sleep (1);
+#endif
+
+	if (test_write ()) return -1;
+
+	if (test_from_key_name ()) return -1;
+
+	// Manual tests
+	KeyboardCode c;
+	c= KeyboardCode::FromEUnicode(KeyboardCode::KC_NUMLOCK);
+	c.SendKeystroke();
+	c= KeyboardCode::FromEUnicode(KeyboardCode::KC_CAPSLOCK);
+	c.SendKeystroke();
+	c= KeyboardCode::FromEUnicode(KeyboardCode::KC_SCROLL);
+	c.SendKeystroke();
+
+	// If execution reaches this => all tests ok
+	return 0;
+}
+
diff --git a/src/mod_hid/ucs2keysym.c b/src/mod_hid/ucs2keysym.c
new file mode 100644
index 0000000..dffdf4a
--- /dev/null
+++ b/src/mod_hid/ucs2keysym.c
@@ -0,0 +1,870 @@
+//
+//  ucs2keysym.c
+//  RemotePad Server
+//
+//  Derived from a code keysym2ucs.c of xterm.
+//  Modified by iKawamoto Yosihisa! on 09/03/04.
+//  Copyright 2009 tenjin.org. All rights reserved.
+//
+
+/* $XTermId: keysym2ucs.c,v 1.15 2007/06/13 00:16:56 tom Exp $
+ * This module converts keysym values into the corresponding ISO 10646
+ * (UCS, Unicode) values.
+ *
+ * The array keysymtab[] contains pairs of X11 keysym values for graphical
+ * characters and the corresponding Unicode value. The function
+ * keysym2ucs() maps a keysym onto a Unicode value using a binary search,
+ * therefore keysymtab[] must remain SORTED by keysym value.
+ *
+ * The keysym -> UTF-8 conversion will hopefully one day be provided
+ * by Xlib via XmbLookupString() and should ideally not have to be
+ * done in X applications. But we are not there yet.
+ *
+ * We allow to represent any UCS character in the range U-00000000 to
+ * U-00FFFFFF by a keysym value in the range 0x01000000 to 0x01ffffff.
+ * This admittedly does not cover the entire 31-bit space of UCS, but
+ * it does cover all of the characters up to U-10FFFF, which can be
+ * represented by UTF-16, and more, and it is very unlikely that higher
+ * UCS codes will ever be assigned by ISO. So to get Unicode character
+ * U+ABCD you can directly use keysym 0x0100abcd.
+ *
+ * NOTE: The comments in the table below contain the actual character
+ * encoded in UTF-8, so for viewing and editing best use an editor in
+ * UTF-8 mode.
+ *
+ * Author: Markus G. Kuhn <mkuhn at acm.org>, University of Cambridge, April 2001
+ *
+ * Special thanks to Richard Verhoeven <river at win.tue.nl> for preparing
+ * an initial draft of the mapping table.
+ *
+ * This software is in the public domain. Share and enjoy!
+ *
+ * AUTOMATICALLY GENERATED FILE, DO NOT EDIT !!! (unicode/convmap.pl)
+ */
+
+#include <X11/X.h>
+#include <assert.h>
+
+static struct codepair {
+  unsigned short keysym;
+  unsigned short ucs;
+} keysymtab[] = {
+  { 0xff08, 0x0008 }, /* BackSpace */
+  { 0xff0d, 0x000a }, /* Linefeed */
+  { 0x0abd, 0x002e }, /*                decimalpoint . FULL STOP */
+  { 0x0ba3, 0x003c }, /*                   leftcaret < LESS-THAN SIGN */
+  { 0x0ba6, 0x003e }, /*                  rightcaret > GREATER-THAN SIGN */
+  { 0x0bc6, 0x005f }, /*                    underbar _ LOW LINE */
+  { 0x0bc0, 0x00af }, /*                     overbar ¯ MACRON */
+  { 0x03c0, 0x0100 }, /*                     Amacron Ā LATIN CAPITAL LETTER A WITH MACRON */
+  { 0x03e0, 0x0101 }, /*                     amacron ā LATIN SMALL LETTER A WITH MACRON */
+  { 0x01c3, 0x0102 }, /*                      Abreve Ă LATIN CAPITAL LETTER A WITH BREVE */
+  { 0x01e3, 0x0103 }, /*                      abreve ă LATIN SMALL LETTER A WITH BREVE */
+  { 0x01a1, 0x0104 }, /*                     Aogonek Ą LATIN CAPITAL LETTER A WITH OGONEK */
+  { 0x01b1, 0x0105 }, /*                     aogonek ą LATIN SMALL LETTER A WITH OGONEK */
+  { 0x01c6, 0x0106 }, /*                      Cacute Ć LATIN CAPITAL LETTER C WITH ACUTE */
+  { 0x01e6, 0x0107 }, /*                      cacute ć LATIN SMALL LETTER C WITH ACUTE */
+  { 0x02c6, 0x0108 }, /*                 Ccircumflex Ĉ LATIN CAPITAL LETTER C WITH CIRCUMFLEX */
+  { 0x02e6, 0x0109 }, /*                 ccircumflex ĉ LATIN SMALL LETTER C WITH CIRCUMFLEX */
+  { 0x02c5, 0x010a }, /*                   Cabovedot Ċ LATIN CAPITAL LETTER C WITH DOT ABOVE */
+  { 0x02e5, 0x010b }, /*                   cabovedot ċ LATIN SMALL LETTER C WITH DOT ABOVE */
+  { 0x01c8, 0x010c }, /*                      Ccaron Č LATIN CAPITAL LETTER C WITH CARON */
+  { 0x01e8, 0x010d }, /*                      ccaron č LATIN SMALL LETTER C WITH CARON */
+  { 0x01cf, 0x010e }, /*                      Dcaron Ď LATIN CAPITAL LETTER D WITH CARON */
+  { 0x01ef, 0x010f }, /*                      dcaron ď LATIN SMALL LETTER D WITH CARON */
+  { 0x01d0, 0x0110 }, /*                     Dstroke Đ LATIN CAPITAL LETTER D WITH STROKE */
+  { 0x01f0, 0x0111 }, /*                     dstroke đ LATIN SMALL LETTER D WITH STROKE */
+  { 0x03aa, 0x0112 }, /*                     Emacron Ē LATIN CAPITAL LETTER E WITH MACRON */
+  { 0x03ba, 0x0113 }, /*                     emacron ē LATIN SMALL LETTER E WITH MACRON */
+  { 0x03cc, 0x0116 }, /*                   Eabovedot Ė LATIN CAPITAL LETTER E WITH DOT ABOVE */
+  { 0x03ec, 0x0117 }, /*                   eabovedot ė LATIN SMALL LETTER E WITH DOT ABOVE */
+  { 0x01ca, 0x0118 }, /*                     Eogonek Ę LATIN CAPITAL LETTER E WITH OGONEK */
+  { 0x01ea, 0x0119 }, /*                     eogonek ę LATIN SMALL LETTER E WITH OGONEK */
+  { 0x01cc, 0x011a }, /*                      Ecaron Ě LATIN CAPITAL LETTER E WITH CARON */
+  { 0x01ec, 0x011b }, /*                      ecaron ě LATIN SMALL LETTER E WITH CARON */
+  { 0x02d8, 0x011c }, /*                 Gcircumflex Ĝ LATIN CAPITAL LETTER G WITH CIRCUMFLEX */
+  { 0x02f8, 0x011d }, /*                 gcircumflex ĝ LATIN SMALL LETTER G WITH CIRCUMFLEX */
+  { 0x02ab, 0x011e }, /*                      Gbreve Ğ LATIN CAPITAL LETTER G WITH BREVE */
+  { 0x02bb, 0x011f }, /*                      gbreve ğ LATIN SMALL LETTER G WITH BREVE */
+  { 0x02d5, 0x0120 }, /*                   Gabovedot Ġ LATIN CAPITAL LETTER G WITH DOT ABOVE */
+  { 0x02f5, 0x0121 }, /*                   gabovedot ġ LATIN SMALL LETTER G WITH DOT ABOVE */
+  { 0x03ab, 0x0122 }, /*                    Gcedilla Ģ LATIN CAPITAL LETTER G WITH CEDILLA */
+  { 0x03bb, 0x0123 }, /*                    gcedilla ģ LATIN SMALL LETTER G WITH CEDILLA */
+  { 0x02a6, 0x0124 }, /*                 Hcircumflex Ĥ LATIN CAPITAL LETTER H WITH CIRCUMFLEX */
+  { 0x02b6, 0x0125 }, /*                 hcircumflex ĥ LATIN SMALL LETTER H WITH CIRCUMFLEX */
+  { 0x02a1, 0x0126 }, /*                     Hstroke Ħ LATIN CAPITAL LETTER H WITH STROKE */
+  { 0x02b1, 0x0127 }, /*                     hstroke ħ LATIN SMALL LETTER H WITH STROKE */
+  { 0x03a5, 0x0128 }, /*                      Itilde Ĩ LATIN CAPITAL LETTER I WITH TILDE */
+  { 0x03b5, 0x0129 }, /*                      itilde ĩ LATIN SMALL LETTER I WITH TILDE */
+  { 0x03cf, 0x012a }, /*                     Imacron Ī LATIN CAPITAL LETTER I WITH MACRON */
+  { 0x03ef, 0x012b }, /*                     imacron ī LATIN SMALL LETTER I WITH MACRON */
+  { 0x03c7, 0x012e }, /*                     Iogonek Į LATIN CAPITAL LETTER I WITH OGONEK */
+  { 0x03e7, 0x012f }, /*                     iogonek į LATIN SMALL LETTER I WITH OGONEK */
+  { 0x02a9, 0x0130 }, /*                   Iabovedot İ LATIN CAPITAL LETTER I WITH DOT ABOVE */
+  { 0x02b9, 0x0131 }, /*                    idotless ı LATIN SMALL LETTER DOTLESS I */
+  { 0x02ac, 0x0134 }, /*                 Jcircumflex Ĵ LATIN CAPITAL LETTER J WITH CIRCUMFLEX */
+  { 0x02bc, 0x0135 }, /*                 jcircumflex ĵ LATIN SMALL LETTER J WITH CIRCUMFLEX */
+  { 0x03d3, 0x0136 }, /*                    Kcedilla Ķ LATIN CAPITAL LETTER K WITH CEDILLA */
+  { 0x03f3, 0x0137 }, /*                    kcedilla ķ LATIN SMALL LETTER K WITH CEDILLA */
+  { 0x03a2, 0x0138 }, /*                         kra ĸ LATIN SMALL LETTER KRA */
+  { 0x01c5, 0x0139 }, /*                      Lacute Ĺ LATIN CAPITAL LETTER L WITH ACUTE */
+  { 0x01e5, 0x013a }, /*                      lacute ĺ LATIN SMALL LETTER L WITH ACUTE */
+  { 0x03a6, 0x013b }, /*                    Lcedilla Ļ LATIN CAPITAL LETTER L WITH CEDILLA */
+  { 0x03b6, 0x013c }, /*                    lcedilla ļ LATIN SMALL LETTER L WITH CEDILLA */
+  { 0x01a5, 0x013d }, /*                      Lcaron Ľ LATIN CAPITAL LETTER L WITH CARON */
+  { 0x01b5, 0x013e }, /*                      lcaron ľ LATIN SMALL LETTER L WITH CARON */
+  { 0x01a3, 0x0141 }, /*                     Lstroke Ł LATIN CAPITAL LETTER L WITH STROKE */
+  { 0x01b3, 0x0142 }, /*                     lstroke ł LATIN SMALL LETTER L WITH STROKE */
+  { 0x01d1, 0x0143 }, /*                      Nacute Ń LATIN CAPITAL LETTER N WITH ACUTE */
+  { 0x01f1, 0x0144 }, /*                      nacute ń LATIN SMALL LETTER N WITH ACUTE */
+  { 0x03d1, 0x0145 }, /*                    Ncedilla Ņ LATIN CAPITAL LETTER N WITH CEDILLA */
+  { 0x03f1, 0x0146 }, /*                    ncedilla ņ LATIN SMALL LETTER N WITH CEDILLA */
+  { 0x01d2, 0x0147 }, /*                      Ncaron Ň LATIN CAPITAL LETTER N WITH CARON */
+  { 0x01f2, 0x0148 }, /*                      ncaron ň LATIN SMALL LETTER N WITH CARON */
+  { 0x03bd, 0x014a }, /*                         ENG Ŋ LATIN CAPITAL LETTER ENG */
+  { 0x03bf, 0x014b }, /*                         eng ŋ LATIN SMALL LETTER ENG */
+  { 0x03d2, 0x014c }, /*                     Omacron Ō LATIN CAPITAL LETTER O WITH MACRON */
+  { 0x03f2, 0x014d }, /*                     omacron ō LATIN SMALL LETTER O WITH MACRON */
+  { 0x01d5, 0x0150 }, /*                Odoubleacute Ő LATIN CAPITAL LETTER O WITH DOUBLE ACUTE */
+  { 0x01f5, 0x0151 }, /*                odoubleacute ő LATIN SMALL LETTER O WITH DOUBLE ACUTE */
+  { 0x13bc, 0x0152 }, /*                          OE ΠLATIN CAPITAL LIGATURE OE */
+  { 0x13bd, 0x0153 }, /*                          oe œ LATIN SMALL LIGATURE OE */
+  { 0x01c0, 0x0154 }, /*                      Racute Ŕ LATIN CAPITAL LETTER R WITH ACUTE */
+  { 0x01e0, 0x0155 }, /*                      racute ŕ LATIN SMALL LETTER R WITH ACUTE */
+  { 0x03a3, 0x0156 }, /*                    Rcedilla Ŗ LATIN CAPITAL LETTER R WITH CEDILLA */
+  { 0x03b3, 0x0157 }, /*                    rcedilla ŗ LATIN SMALL LETTER R WITH CEDILLA */
+  { 0x01d8, 0x0158 }, /*                      Rcaron Ř LATIN CAPITAL LETTER R WITH CARON */
+  { 0x01f8, 0x0159 }, /*                      rcaron ř LATIN SMALL LETTER R WITH CARON */
+  { 0x01a6, 0x015a }, /*                      Sacute Ś LATIN CAPITAL LETTER S WITH ACUTE */
+  { 0x01b6, 0x015b }, /*                      sacute ś LATIN SMALL LETTER S WITH ACUTE */
+  { 0x02de, 0x015c }, /*                 Scircumflex Ŝ LATIN CAPITAL LETTER S WITH CIRCUMFLEX */
+  { 0x02fe, 0x015d }, /*                 scircumflex ŝ LATIN SMALL LETTER S WITH CIRCUMFLEX */
+  { 0x01aa, 0x015e }, /*                    Scedilla Ş LATIN CAPITAL LETTER S WITH CEDILLA */
+  { 0x01ba, 0x015f }, /*                    scedilla ş LATIN SMALL LETTER S WITH CEDILLA */
+  { 0x01a9, 0x0160 }, /*                      Scaron Š LATIN CAPITAL LETTER S WITH CARON */
+  { 0x01b9, 0x0161 }, /*                      scaron š LATIN SMALL LETTER S WITH CARON */
+  { 0x01de, 0x0162 }, /*                    Tcedilla Ţ LATIN CAPITAL LETTER T WITH CEDILLA */
+  { 0x01fe, 0x0163 }, /*                    tcedilla ţ LATIN SMALL LETTER T WITH CEDILLA */
+  { 0x01ab, 0x0164 }, /*                      Tcaron Ť LATIN CAPITAL LETTER T WITH CARON */
+  { 0x01bb, 0x0165 }, /*                      tcaron ť LATIN SMALL LETTER T WITH CARON */
+  { 0x03ac, 0x0166 }, /*                      Tslash Ŧ LATIN CAPITAL LETTER T WITH STROKE */
+  { 0x03bc, 0x0167 }, /*                      tslash ŧ LATIN SMALL LETTER T WITH STROKE */
+  { 0x03dd, 0x0168 }, /*                      Utilde Ũ LATIN CAPITAL LETTER U WITH TILDE */
+  { 0x03fd, 0x0169 }, /*                      utilde ũ LATIN SMALL LETTER U WITH TILDE */
+  { 0x03de, 0x016a }, /*                     Umacron Ū LATIN CAPITAL LETTER U WITH MACRON */
+  { 0x03fe, 0x016b }, /*                     umacron ū LATIN SMALL LETTER U WITH MACRON */
+  { 0x02dd, 0x016c }, /*                      Ubreve Ŭ LATIN CAPITAL LETTER U WITH BREVE */
+  { 0x02fd, 0x016d }, /*                      ubreve ŭ LATIN SMALL LETTER U WITH BREVE */
+  { 0x01d9, 0x016e }, /*                       Uring Ů LATIN CAPITAL LETTER U WITH RING ABOVE */
+  { 0x01f9, 0x016f }, /*                       uring ů LATIN SMALL LETTER U WITH RING ABOVE */
+  { 0x01db, 0x0170 }, /*                Udoubleacute Ű LATIN CAPITAL LETTER U WITH DOUBLE ACUTE */
+  { 0x01fb, 0x0171 }, /*                udoubleacute ű LATIN SMALL LETTER U WITH DOUBLE ACUTE */
+  { 0x03d9, 0x0172 }, /*                     Uogonek Ų LATIN CAPITAL LETTER U WITH OGONEK */
+  { 0x03f9, 0x0173 }, /*                     uogonek ų LATIN SMALL LETTER U WITH OGONEK */
+  { 0x13be, 0x0178 }, /*                  Ydiaeresis Ÿ LATIN CAPITAL LETTER Y WITH DIAERESIS */
+  { 0x01ac, 0x0179 }, /*                      Zacute Ź LATIN CAPITAL LETTER Z WITH ACUTE */
+  { 0x01bc, 0x017a }, /*                      zacute ź LATIN SMALL LETTER Z WITH ACUTE */
+  { 0x01af, 0x017b }, /*                   Zabovedot Ż LATIN CAPITAL LETTER Z WITH DOT ABOVE */
+  { 0x01bf, 0x017c }, /*                   zabovedot ż LATIN SMALL LETTER Z WITH DOT ABOVE */
+  { 0x01ae, 0x017d }, /*                      Zcaron Ž LATIN CAPITAL LETTER Z WITH CARON */
+  { 0x01be, 0x017e }, /*                      zcaron ž LATIN SMALL LETTER Z WITH CARON */
+  { 0x08f6, 0x0192 }, /*                    function ƒ LATIN SMALL LETTER F WITH HOOK */
+  { 0x01b7, 0x02c7 }, /*                       caron ˇ CARON */
+  { 0x01a2, 0x02d8 }, /*                       breve ˘ BREVE */
+  { 0x01ff, 0x02d9 }, /*                    abovedot ˙ DOT ABOVE */
+  { 0x01b2, 0x02db }, /*                      ogonek ˛ OGONEK */
+  { 0x01bd, 0x02dd }, /*                 doubleacute ˝ DOUBLE ACUTE ACCENT */
+  { 0x07ae, 0x0385 }, /*        Greek_accentdieresis ΅ GREEK DIALYTIKA TONOS */
+  { 0x07a1, 0x0386 }, /*           Greek_ALPHAaccent Ά GREEK CAPITAL LETTER ALPHA WITH TONOS */
+  { 0x07a2, 0x0388 }, /*         Greek_EPSILONaccent Έ GREEK CAPITAL LETTER EPSILON WITH TONOS */
+  { 0x07a3, 0x0389 }, /*             Greek_ETAaccent Ή GREEK CAPITAL LETTER ETA WITH TONOS */
+  { 0x07a4, 0x038a }, /*            Greek_IOTAaccent Ί GREEK CAPITAL LETTER IOTA WITH TONOS */
+  { 0x07a7, 0x038c }, /*         Greek_OMICRONaccent Ό GREEK CAPITAL LETTER OMICRON WITH TONOS */
+  { 0x07a8, 0x038e }, /*         Greek_UPSILONaccent Ύ GREEK CAPITAL LETTER UPSILON WITH TONOS */
+  { 0x07ab, 0x038f }, /*           Greek_OMEGAaccent Ώ GREEK CAPITAL LETTER OMEGA WITH TONOS */
+  { 0x07b6, 0x0390 }, /*    Greek_iotaaccentdieresis ΐ GREEK SMALL LETTER IOTA WITH DIALYTIKA AND TONOS */
+  { 0x07c1, 0x0391 }, /*                 Greek_ALPHA Α GREEK CAPITAL LETTER ALPHA */
+  { 0x07c2, 0x0392 }, /*                  Greek_BETA Β GREEK CAPITAL LETTER BETA */
+  { 0x07c3, 0x0393 }, /*                 Greek_GAMMA Γ GREEK CAPITAL LETTER GAMMA */
+  { 0x07c4, 0x0394 }, /*                 Greek_DELTA Δ GREEK CAPITAL LETTER DELTA */
+  { 0x07c5, 0x0395 }, /*               Greek_EPSILON Ε GREEK CAPITAL LETTER EPSILON */
+  { 0x07c6, 0x0396 }, /*                  Greek_ZETA Ζ GREEK CAPITAL LETTER ZETA */
+  { 0x07c7, 0x0397 }, /*                   Greek_ETA Η GREEK CAPITAL LETTER ETA */
+  { 0x07c8, 0x0398 }, /*                 Greek_THETA Θ GREEK CAPITAL LETTER THETA */
+  { 0x07c9, 0x0399 }, /*                  Greek_IOTA Ι GREEK CAPITAL LETTER IOTA */
+  { 0x07ca, 0x039a }, /*                 Greek_KAPPA Κ GREEK CAPITAL LETTER KAPPA */
+  { 0x07cb, 0x039b }, /*                Greek_LAMBDA Λ GREEK CAPITAL LETTER LAMDA */
+  { 0x07cc, 0x039c }, /*                    Greek_MU Μ GREEK CAPITAL LETTER MU */
+  { 0x07cd, 0x039d }, /*                    Greek_NU Ν GREEK CAPITAL LETTER NU */
+  { 0x07ce, 0x039e }, /*                    Greek_XI Ξ GREEK CAPITAL LETTER XI */
+  { 0x07cf, 0x039f }, /*               Greek_OMICRON Ο GREEK CAPITAL LETTER OMICRON */
+  { 0x07d0, 0x03a0 }, /*                    Greek_PI Π GREEK CAPITAL LETTER PI */
+  { 0x07d1, 0x03a1 }, /*                   Greek_RHO Ρ GREEK CAPITAL LETTER RHO */
+  { 0x07d2, 0x03a3 }, /*                 Greek_SIGMA Σ GREEK CAPITAL LETTER SIGMA */
+  { 0x07d4, 0x03a4 }, /*                   Greek_TAU Τ GREEK CAPITAL LETTER TAU */
+  { 0x07d5, 0x03a5 }, /*               Greek_UPSILON Υ GREEK CAPITAL LETTER UPSILON */
+  { 0x07d6, 0x03a6 }, /*                   Greek_PHI Φ GREEK CAPITAL LETTER PHI */
+  { 0x07d7, 0x03a7 }, /*                   Greek_CHI Χ GREEK CAPITAL LETTER CHI */
+  { 0x07d8, 0x03a8 }, /*                   Greek_PSI Ψ GREEK CAPITAL LETTER PSI */
+  { 0x07d9, 0x03a9 }, /*                 Greek_OMEGA Ω GREEK CAPITAL LETTER OMEGA */
+  { 0x07a5, 0x03aa }, /*         Greek_IOTAdiaeresis Ϊ GREEK CAPITAL LETTER IOTA WITH DIALYTIKA */
+  { 0x07a9, 0x03ab }, /*       Greek_UPSILONdieresis Ϋ GREEK CAPITAL LETTER UPSILON WITH DIALYTIKA */
+  { 0x07b1, 0x03ac }, /*           Greek_alphaaccent ά GREEK SMALL LETTER ALPHA WITH TONOS */
+  { 0x07b2, 0x03ad }, /*         Greek_epsilonaccent έ GREEK SMALL LETTER EPSILON WITH TONOS */
+  { 0x07b3, 0x03ae }, /*             Greek_etaaccent ή GREEK SMALL LETTER ETA WITH TONOS */
+  { 0x07b4, 0x03af }, /*            Greek_iotaaccent ί GREEK SMALL LETTER IOTA WITH TONOS */
+  { 0x07ba, 0x03b0 }, /* Greek_upsilonaccentdieresis ΰ GREEK SMALL LETTER UPSILON WITH DIALYTIKA AND TONOS */
+  { 0x07e1, 0x03b1 }, /*                 Greek_alpha α GREEK SMALL LETTER ALPHA */
+  { 0x07e2, 0x03b2 }, /*                  Greek_beta β GREEK SMALL LETTER BETA */
+  { 0x07e3, 0x03b3 }, /*                 Greek_gamma γ GREEK SMALL LETTER GAMMA */
+  { 0x07e4, 0x03b4 }, /*                 Greek_delta δ GREEK SMALL LETTER DELTA */
+  { 0x07e5, 0x03b5 }, /*               Greek_epsilon ε GREEK SMALL LETTER EPSILON */
+  { 0x07e6, 0x03b6 }, /*                  Greek_zeta ζ GREEK SMALL LETTER ZETA */
+  { 0x07e7, 0x03b7 }, /*                   Greek_eta η GREEK SMALL LETTER ETA */
+  { 0x07e8, 0x03b8 }, /*                 Greek_theta θ GREEK SMALL LETTER THETA */
+  { 0x07e9, 0x03b9 }, /*                  Greek_iota ι GREEK SMALL LETTER IOTA */
+  { 0x07ea, 0x03ba }, /*                 Greek_kappa κ GREEK SMALL LETTER KAPPA */
+  { 0x07eb, 0x03bb }, /*                Greek_lambda λ GREEK SMALL LETTER LAMDA */
+  { 0x07ec, 0x03bc }, /*                    Greek_mu μ GREEK SMALL LETTER MU */
+  { 0x07ed, 0x03bd }, /*                    Greek_nu ν GREEK SMALL LETTER NU */
+  { 0x07ee, 0x03be }, /*                    Greek_xi ξ GREEK SMALL LETTER XI */
+  { 0x07ef, 0x03bf }, /*               Greek_omicron ο GREEK SMALL LETTER OMICRON */
+  { 0x07f0, 0x03c0 }, /*                    Greek_pi π GREEK SMALL LETTER PI */
+  { 0x07f1, 0x03c1 }, /*                   Greek_rho ρ GREEK SMALL LETTER RHO */
+  { 0x07f3, 0x03c2 }, /*       Greek_finalsmallsigma ς GREEK SMALL LETTER FINAL SIGMA */
+  { 0x07f2, 0x03c3 }, /*                 Greek_sigma σ GREEK SMALL LETTER SIGMA */
+  { 0x07f4, 0x03c4 }, /*                   Greek_tau τ GREEK SMALL LETTER TAU */
+  { 0x07f5, 0x03c5 }, /*               Greek_upsilon υ GREEK SMALL LETTER UPSILON */
+  { 0x07f6, 0x03c6 }, /*                   Greek_phi φ GREEK SMALL LETTER PHI */
+  { 0x07f7, 0x03c7 }, /*                   Greek_chi χ GREEK SMALL LETTER CHI */
+  { 0x07f8, 0x03c8 }, /*                   Greek_psi ψ GREEK SMALL LETTER PSI */
+  { 0x07f9, 0x03c9 }, /*                 Greek_omega ω GREEK SMALL LETTER OMEGA */
+  { 0x07b5, 0x03ca }, /*          Greek_iotadieresis ϊ GREEK SMALL LETTER IOTA WITH DIALYTIKA */
+  { 0x07b9, 0x03cb }, /*       Greek_upsilondieresis ϋ GREEK SMALL LETTER UPSILON WITH DIALYTIKA */
+  { 0x07b7, 0x03cc }, /*         Greek_omicronaccent ό GREEK SMALL LETTER OMICRON WITH TONOS */
+  { 0x07b8, 0x03cd }, /*         Greek_upsilonaccent ύ GREEK SMALL LETTER UPSILON WITH TONOS */
+  { 0x07bb, 0x03ce }, /*           Greek_omegaaccent ώ GREEK SMALL LETTER OMEGA WITH TONOS */
+  { 0x06b3, 0x0401 }, /*                 Cyrillic_IO Ё CYRILLIC CAPITAL LETTER IO */
+  { 0x06b1, 0x0402 }, /*                 Serbian_DJE Ђ CYRILLIC CAPITAL LETTER DJE */
+  { 0x06b2, 0x0403 }, /*               Macedonia_GJE Ѓ CYRILLIC CAPITAL LETTER GJE */
+  { 0x06b4, 0x0404 }, /*                Ukrainian_IE Є CYRILLIC CAPITAL LETTER UKRAINIAN IE */
+  { 0x06b5, 0x0405 }, /*               Macedonia_DSE Ѕ CYRILLIC CAPITAL LETTER DZE */
+  { 0x06b6, 0x0406 }, /*                 Ukrainian_I І CYRILLIC CAPITAL LETTER BYELORUSSIAN-UKRAINIAN I */
+  { 0x06b7, 0x0407 }, /*                Ukrainian_YI Ї CYRILLIC CAPITAL LETTER YI */
+  { 0x06b8, 0x0408 }, /*                 Cyrillic_JE Ј CYRILLIC CAPITAL LETTER JE */
+  { 0x06b9, 0x0409 }, /*                Cyrillic_LJE Љ CYRILLIC CAPITAL LETTER LJE */
+  { 0x06ba, 0x040a }, /*                Cyrillic_NJE Њ CYRILLIC CAPITAL LETTER NJE */
+  { 0x06bb, 0x040b }, /*                Serbian_TSHE Ћ CYRILLIC CAPITAL LETTER TSHE */
+  { 0x06bc, 0x040c }, /*               Macedonia_KJE Ќ CYRILLIC CAPITAL LETTER KJE */
+  { 0x06be, 0x040e }, /*         Byelorussian_SHORTU Ў CYRILLIC CAPITAL LETTER SHORT U */
+  { 0x06bf, 0x040f }, /*               Cyrillic_DZHE Џ CYRILLIC CAPITAL LETTER DZHE */
+  { 0x06e1, 0x0410 }, /*                  Cyrillic_A А CYRILLIC CAPITAL LETTER A */
+  { 0x06e2, 0x0411 }, /*                 Cyrillic_BE Б CYRILLIC CAPITAL LETTER BE */
+  { 0x06f7, 0x0412 }, /*                 Cyrillic_VE В CYRILLIC CAPITAL LETTER VE */
+  { 0x06e7, 0x0413 }, /*                Cyrillic_GHE Г CYRILLIC CAPITAL LETTER GHE */
+  { 0x06e4, 0x0414 }, /*                 Cyrillic_DE Д CYRILLIC CAPITAL LETTER DE */
+  { 0x06e5, 0x0415 }, /*                 Cyrillic_IE Е CYRILLIC CAPITAL LETTER IE */
+  { 0x06f6, 0x0416 }, /*                Cyrillic_ZHE Ж CYRILLIC CAPITAL LETTER ZHE */
+  { 0x06fa, 0x0417 }, /*                 Cyrillic_ZE З CYRILLIC CAPITAL LETTER ZE */
+  { 0x06e9, 0x0418 }, /*                  Cyrillic_I И CYRILLIC CAPITAL LETTER I */
+  { 0x06ea, 0x0419 }, /*             Cyrillic_SHORTI Й CYRILLIC CAPITAL LETTER SHORT I */
+  { 0x06eb, 0x041a }, /*                 Cyrillic_KA К CYRILLIC CAPITAL LETTER KA */
+  { 0x06ec, 0x041b }, /*                 Cyrillic_EL Л CYRILLIC CAPITAL LETTER EL */
+  { 0x06ed, 0x041c }, /*                 Cyrillic_EM М CYRILLIC CAPITAL LETTER EM */
+  { 0x06ee, 0x041d }, /*                 Cyrillic_EN Н CYRILLIC CAPITAL LETTER EN */
+  { 0x06ef, 0x041e }, /*                  Cyrillic_O О CYRILLIC CAPITAL LETTER O */
+  { 0x06f0, 0x041f }, /*                 Cyrillic_PE П CYRILLIC CAPITAL LETTER PE */
+  { 0x06f2, 0x0420 }, /*                 Cyrillic_ER Р CYRILLIC CAPITAL LETTER ER */
+  { 0x06f3, 0x0421 }, /*                 Cyrillic_ES С CYRILLIC CAPITAL LETTER ES */
+  { 0x06f4, 0x0422 }, /*                 Cyrillic_TE Т CYRILLIC CAPITAL LETTER TE */
+  { 0x06f5, 0x0423 }, /*                  Cyrillic_U У CYRILLIC CAPITAL LETTER U */
+  { 0x06e6, 0x0424 }, /*                 Cyrillic_EF Ф CYRILLIC CAPITAL LETTER EF */
+  { 0x06e8, 0x0425 }, /*                 Cyrillic_HA Х CYRILLIC CAPITAL LETTER HA */
+  { 0x06e3, 0x0426 }, /*                Cyrillic_TSE Ц CYRILLIC CAPITAL LETTER TSE */
+  { 0x06fe, 0x0427 }, /*                Cyrillic_CHE Ч CYRILLIC CAPITAL LETTER CHE */
+  { 0x06fb, 0x0428 }, /*                Cyrillic_SHA Ш CYRILLIC CAPITAL LETTER SHA */
+  { 0x06fd, 0x0429 }, /*              Cyrillic_SHCHA Щ CYRILLIC CAPITAL LETTER SHCHA */
+  { 0x06ff, 0x042a }, /*           Cyrillic_HARDSIGN Ъ CYRILLIC CAPITAL LETTER HARD SIGN */
+  { 0x06f9, 0x042b }, /*               Cyrillic_YERU Ы CYRILLIC CAPITAL LETTER YERU */
+  { 0x06f8, 0x042c }, /*           Cyrillic_SOFTSIGN Ь CYRILLIC CAPITAL LETTER SOFT SIGN */
+  { 0x06fc, 0x042d }, /*                  Cyrillic_E Э CYRILLIC CAPITAL LETTER E */
+  { 0x06e0, 0x042e }, /*                 Cyrillic_YU Ю CYRILLIC CAPITAL LETTER YU */
+  { 0x06f1, 0x042f }, /*                 Cyrillic_YA Я CYRILLIC CAPITAL LETTER YA */
+  { 0x06c1, 0x0430 }, /*                  Cyrillic_a а CYRILLIC SMALL LETTER A */
+  { 0x06c2, 0x0431 }, /*                 Cyrillic_be б CYRILLIC SMALL LETTER BE */
+  { 0x06d7, 0x0432 }, /*                 Cyrillic_ve в CYRILLIC SMALL LETTER VE */
+  { 0x06c7, 0x0433 }, /*                Cyrillic_ghe г CYRILLIC SMALL LETTER GHE */
+  { 0x06c4, 0x0434 }, /*                 Cyrillic_de д CYRILLIC SMALL LETTER DE */
+  { 0x06c5, 0x0435 }, /*                 Cyrillic_ie е CYRILLIC SMALL LETTER IE */
+  { 0x06d6, 0x0436 }, /*                Cyrillic_zhe ж CYRILLIC SMALL LETTER ZHE */
+  { 0x06da, 0x0437 }, /*                 Cyrillic_ze з CYRILLIC SMALL LETTER ZE */
+  { 0x06c9, 0x0438 }, /*                  Cyrillic_i и CYRILLIC SMALL LETTER I */
+  { 0x06ca, 0x0439 }, /*             Cyrillic_shorti й CYRILLIC SMALL LETTER SHORT I */
+  { 0x06cb, 0x043a }, /*                 Cyrillic_ka к CYRILLIC SMALL LETTER KA */
+  { 0x06cc, 0x043b }, /*                 Cyrillic_el л CYRILLIC SMALL LETTER EL */
+  { 0x06cd, 0x043c }, /*                 Cyrillic_em м CYRILLIC SMALL LETTER EM */
+  { 0x06ce, 0x043d }, /*                 Cyrillic_en н CYRILLIC SMALL LETTER EN */
+  { 0x06cf, 0x043e }, /*                  Cyrillic_o о CYRILLIC SMALL LETTER O */
+  { 0x06d0, 0x043f }, /*                 Cyrillic_pe п CYRILLIC SMALL LETTER PE */
+  { 0x06d2, 0x0440 }, /*                 Cyrillic_er р CYRILLIC SMALL LETTER ER */
+  { 0x06d3, 0x0441 }, /*                 Cyrillic_es с CYRILLIC SMALL LETTER ES */
+  { 0x06d4, 0x0442 }, /*                 Cyrillic_te т CYRILLIC SMALL LETTER TE */
+  { 0x06d5, 0x0443 }, /*                  Cyrillic_u у CYRILLIC SMALL LETTER U */
+  { 0x06c6, 0x0444 }, /*                 Cyrillic_ef ф CYRILLIC SMALL LETTER EF */
+  { 0x06c8, 0x0445 }, /*                 Cyrillic_ha х CYRILLIC SMALL LETTER HA */
+  { 0x06c3, 0x0446 }, /*                Cyrillic_tse ц CYRILLIC SMALL LETTER TSE */
+  { 0x06de, 0x0447 }, /*                Cyrillic_che ч CYRILLIC SMALL LETTER CHE */
+  { 0x06db, 0x0448 }, /*                Cyrillic_sha ш CYRILLIC SMALL LETTER SHA */
+  { 0x06dd, 0x0449 }, /*              Cyrillic_shcha щ CYRILLIC SMALL LETTER SHCHA */
+  { 0x06df, 0x044a }, /*           Cyrillic_hardsign ъ CYRILLIC SMALL LETTER HARD SIGN */
+  { 0x06d9, 0x044b }, /*               Cyrillic_yeru ы CYRILLIC SMALL LETTER YERU */
+  { 0x06d8, 0x044c }, /*           Cyrillic_softsign ь CYRILLIC SMALL LETTER SOFT SIGN */
+  { 0x06dc, 0x044d }, /*                  Cyrillic_e э CYRILLIC SMALL LETTER E */
+  { 0x06c0, 0x044e }, /*                 Cyrillic_yu ю CYRILLIC SMALL LETTER YU */
+  { 0x06d1, 0x044f }, /*                 Cyrillic_ya я CYRILLIC SMALL LETTER YA */
+  { 0x06a3, 0x0451 }, /*                 Cyrillic_io ё CYRILLIC SMALL LETTER IO */
+  { 0x06a1, 0x0452 }, /*                 Serbian_dje ђ CYRILLIC SMALL LETTER DJE */
+  { 0x06a2, 0x0453 }, /*               Macedonia_gje ѓ CYRILLIC SMALL LETTER GJE */
+  { 0x06a4, 0x0454 }, /*                Ukrainian_ie є CYRILLIC SMALL LETTER UKRAINIAN IE */
+  { 0x06a5, 0x0455 }, /*               Macedonia_dse ѕ CYRILLIC SMALL LETTER DZE */
+  { 0x06a6, 0x0456 }, /*                 Ukrainian_i і CYRILLIC SMALL LETTER BYELORUSSIAN-UKRAINIAN I */
+  { 0x06a7, 0x0457 }, /*                Ukrainian_yi ї CYRILLIC SMALL LETTER YI */
+  { 0x06a8, 0x0458 }, /*                 Cyrillic_je ј CYRILLIC SMALL LETTER JE */
+  { 0x06a9, 0x0459 }, /*                Cyrillic_lje љ CYRILLIC SMALL LETTER LJE */
+  { 0x06aa, 0x045a }, /*                Cyrillic_nje њ CYRILLIC SMALL LETTER NJE */
+  { 0x06ab, 0x045b }, /*                Serbian_tshe ћ CYRILLIC SMALL LETTER TSHE */
+  { 0x06ac, 0x045c }, /*               Macedonia_kje ќ CYRILLIC SMALL LETTER KJE */
+  { 0x06ae, 0x045e }, /*         Byelorussian_shortu ў CYRILLIC SMALL LETTER SHORT U */
+  { 0x06af, 0x045f }, /*               Cyrillic_dzhe џ CYRILLIC SMALL LETTER DZHE */
+  { 0x06bd, 0x0490 }, /*   Ukrainian_GHE_WITH_UPTURN Ґ CYRILLIC CAPITAL LETTER GHE WITH UPTURN */
+  { 0x06ad, 0x0491 }, /*   Ukrainian_ghe_with_upturn ґ CYRILLIC SMALL LETTER GHE WITH UPTURN */
+  { 0x0ce0, 0x05d0 }, /*                hebrew_aleph א HEBREW LETTER ALEF */
+  { 0x0ce1, 0x05d1 }, /*                  hebrew_bet ב HEBREW LETTER BET */
+  { 0x0ce2, 0x05d2 }, /*                hebrew_gimel ג HEBREW LETTER GIMEL */
+  { 0x0ce3, 0x05d3 }, /*                hebrew_dalet ד HEBREW LETTER DALET */
+  { 0x0ce4, 0x05d4 }, /*                   hebrew_he ה HEBREW LETTER HE */
+  { 0x0ce5, 0x05d5 }, /*                  hebrew_waw ו HEBREW LETTER VAV */
+  { 0x0ce6, 0x05d6 }, /*                 hebrew_zain ז HEBREW LETTER ZAYIN */
+  { 0x0ce7, 0x05d7 }, /*                 hebrew_chet ח HEBREW LETTER HET */
+  { 0x0ce8, 0x05d8 }, /*                  hebrew_tet ט HEBREW LETTER TET */
+  { 0x0ce9, 0x05d9 }, /*                  hebrew_yod י HEBREW LETTER YOD */
+  { 0x0cea, 0x05da }, /*            hebrew_finalkaph ך HEBREW LETTER FINAL KAF */
+  { 0x0ceb, 0x05db }, /*                 hebrew_kaph כ HEBREW LETTER KAF */
+  { 0x0cec, 0x05dc }, /*                hebrew_lamed ל HEBREW LETTER LAMED */
+  { 0x0ced, 0x05dd }, /*             hebrew_finalmem ם HEBREW LETTER FINAL MEM */
+  { 0x0cee, 0x05de }, /*                  hebrew_mem מ HEBREW LETTER MEM */
+  { 0x0cef, 0x05df }, /*             hebrew_finalnun ן HEBREW LETTER FINAL NUN */
+  { 0x0cf0, 0x05e0 }, /*                  hebrew_nun נ HEBREW LETTER NUN */
+  { 0x0cf1, 0x05e1 }, /*               hebrew_samech ס HEBREW LETTER SAMEKH */
+  { 0x0cf2, 0x05e2 }, /*                 hebrew_ayin ע HEBREW LETTER AYIN */
+  { 0x0cf3, 0x05e3 }, /*              hebrew_finalpe ף HEBREW LETTER FINAL PE */
+  { 0x0cf4, 0x05e4 }, /*                   hebrew_pe פ HEBREW LETTER PE */
+  { 0x0cf5, 0x05e5 }, /*            hebrew_finalzade ץ HEBREW LETTER FINAL TSADI */
+  { 0x0cf6, 0x05e6 }, /*                 hebrew_zade צ HEBREW LETTER TSADI */
+  { 0x0cf7, 0x05e7 }, /*                 hebrew_qoph ק HEBREW LETTER QOF */
+  { 0x0cf8, 0x05e8 }, /*                 hebrew_resh ר HEBREW LETTER RESH */
+  { 0x0cf9, 0x05e9 }, /*                 hebrew_shin ש HEBREW LETTER SHIN */
+  { 0x0cfa, 0x05ea }, /*                  hebrew_taw ת HEBREW LETTER TAV */
+  { 0x05ac, 0x060c }, /*                Arabic_comma ، ARABIC COMMA */
+  { 0x05bb, 0x061b }, /*            Arabic_semicolon ؛ ARABIC SEMICOLON */
+  { 0x05bf, 0x061f }, /*        Arabic_question_mark ؟ ARABIC QUESTION MARK */
+  { 0x05c1, 0x0621 }, /*                Arabic_hamza ء ARABIC LETTER HAMZA */
+  { 0x05c2, 0x0622 }, /*          Arabic_maddaonalef آ ARABIC LETTER ALEF WITH MADDA ABOVE */
+  { 0x05c3, 0x0623 }, /*          Arabic_hamzaonalef أ ARABIC LETTER ALEF WITH HAMZA ABOVE */
+  { 0x05c4, 0x0624 }, /*           Arabic_hamzaonwaw ؤ ARABIC LETTER WAW WITH HAMZA ABOVE */
+  { 0x05c5, 0x0625 }, /*       Arabic_hamzaunderalef إ ARABIC LETTER ALEF WITH HAMZA BELOW */
+  { 0x05c6, 0x0626 }, /*           Arabic_hamzaonyeh ئ ARABIC LETTER YEH WITH HAMZA ABOVE */
+  { 0x05c7, 0x0627 }, /*                 Arabic_alef ا ARABIC LETTER ALEF */
+  { 0x05c8, 0x0628 }, /*                  Arabic_beh ب ARABIC LETTER BEH */
+  { 0x05c9, 0x0629 }, /*           Arabic_tehmarbuta ة ARABIC LETTER TEH MARBUTA */
+  { 0x05ca, 0x062a }, /*                  Arabic_teh ت ARABIC LETTER TEH */
+  { 0x05cb, 0x062b }, /*                 Arabic_theh ث ARABIC LETTER THEH */
+  { 0x05cc, 0x062c }, /*                 Arabic_jeem ج ARABIC LETTER JEEM */
+  { 0x05cd, 0x062d }, /*                  Arabic_hah ح ARABIC LETTER HAH */
+  { 0x05ce, 0x062e }, /*                 Arabic_khah خ ARABIC LETTER KHAH */
+  { 0x05cf, 0x062f }, /*                  Arabic_dal د ARABIC LETTER DAL */
+  { 0x05d0, 0x0630 }, /*                 Arabic_thal ذ ARABIC LETTER THAL */
+  { 0x05d1, 0x0631 }, /*                   Arabic_ra ر ARABIC LETTER REH */
+  { 0x05d2, 0x0632 }, /*                 Arabic_zain ز ARABIC LETTER ZAIN */
+  { 0x05d3, 0x0633 }, /*                 Arabic_seen س ARABIC LETTER SEEN */
+  { 0x05d4, 0x0634 }, /*                Arabic_sheen ش ARABIC LETTER SHEEN */
+  { 0x05d5, 0x0635 }, /*                  Arabic_sad ص ARABIC LETTER SAD */
+  { 0x05d6, 0x0636 }, /*                  Arabic_dad ض ARABIC LETTER DAD */
+  { 0x05d7, 0x0637 }, /*                  Arabic_tah ط ARABIC LETTER TAH */
+  { 0x05d8, 0x0638 }, /*                  Arabic_zah ظ ARABIC LETTER ZAH */
+  { 0x05d9, 0x0639 }, /*                  Arabic_ain ع ARABIC LETTER AIN */
+  { 0x05da, 0x063a }, /*                Arabic_ghain غ ARABIC LETTER GHAIN */
+  { 0x05e0, 0x0640 }, /*              Arabic_tatweel ـ ARABIC TATWEEL */
+  { 0x05e1, 0x0641 }, /*                  Arabic_feh ف ARABIC LETTER FEH */
+  { 0x05e2, 0x0642 }, /*                  Arabic_qaf ق ARABIC LETTER QAF */
+  { 0x05e3, 0x0643 }, /*                  Arabic_kaf ك ARABIC LETTER KAF */
+  { 0x05e4, 0x0644 }, /*                  Arabic_lam ل ARABIC LETTER LAM */
+  { 0x05e5, 0x0645 }, /*                 Arabic_meem م ARABIC LETTER MEEM */
+  { 0x05e6, 0x0646 }, /*                 Arabic_noon ن ARABIC LETTER NOON */
+  { 0x05e7, 0x0647 }, /*                   Arabic_ha ه ARABIC LETTER HEH */
+  { 0x05e8, 0x0648 }, /*                  Arabic_waw و ARABIC LETTER WAW */
+  { 0x05e9, 0x0649 }, /*          Arabic_alefmaksura ى ARABIC LETTER ALEF MAKSURA */
+  { 0x05ea, 0x064a }, /*                  Arabic_yeh ي ARABIC LETTER YEH */
+  { 0x05eb, 0x064b }, /*             Arabic_fathatan ً ARABIC FATHATAN */
+  { 0x05ec, 0x064c }, /*             Arabic_dammatan ٌ ARABIC DAMMATAN */
+  { 0x05ed, 0x064d }, /*             Arabic_kasratan ٍ ARABIC KASRATAN */
+  { 0x05ee, 0x064e }, /*                Arabic_fatha َ ARABIC FATHA */
+  { 0x05ef, 0x064f }, /*                Arabic_damma ُ ARABIC DAMMA */
+  { 0x05f0, 0x0650 }, /*                Arabic_kasra ِ ARABIC KASRA */
+  { 0x05f1, 0x0651 }, /*               Arabic_shadda ّ ARABIC SHADDA */
+  { 0x05f2, 0x0652 }, /*                Arabic_sukun ْ ARABIC SUKUN */
+  { 0x0da1, 0x0e01 }, /*                  Thai_kokai ก THAI CHARACTER KO KAI */
+  { 0x0da2, 0x0e02 }, /*                Thai_khokhai ข THAI CHARACTER KHO KHAI */
+  { 0x0da3, 0x0e03 }, /*               Thai_khokhuat ฃ THAI CHARACTER KHO KHUAT */
+  { 0x0da4, 0x0e04 }, /*               Thai_khokhwai ค THAI CHARACTER KHO KHWAI */
+  { 0x0da5, 0x0e05 }, /*                Thai_khokhon ฅ THAI CHARACTER KHO KHON */
+  { 0x0da6, 0x0e06 }, /*             Thai_khorakhang ฆ THAI CHARACTER KHO RAKHANG */
+  { 0x0da7, 0x0e07 }, /*                 Thai_ngongu ง THAI CHARACTER NGO NGU */
+  { 0x0da8, 0x0e08 }, /*                Thai_chochan จ THAI CHARACTER CHO CHAN */
+  { 0x0da9, 0x0e09 }, /*               Thai_choching ฉ THAI CHARACTER CHO CHING */
+  { 0x0daa, 0x0e0a }, /*               Thai_chochang ช THAI CHARACTER CHO CHANG */
+  { 0x0dab, 0x0e0b }, /*                   Thai_soso ซ THAI CHARACTER SO SO */
+  { 0x0dac, 0x0e0c }, /*                Thai_chochoe ฌ THAI CHARACTER CHO CHOE */
+  { 0x0dad, 0x0e0d }, /*                 Thai_yoying ญ THAI CHARACTER YO YING */
+  { 0x0dae, 0x0e0e }, /*                Thai_dochada ฎ THAI CHARACTER DO CHADA */
+  { 0x0daf, 0x0e0f }, /*                Thai_topatak ฏ THAI CHARACTER TO PATAK */
+  { 0x0db0, 0x0e10 }, /*                Thai_thothan ฐ THAI CHARACTER THO THAN */
+  { 0x0db1, 0x0e11 }, /*          Thai_thonangmontho ฑ THAI CHARACTER THO NANGMONTHO */
+  { 0x0db2, 0x0e12 }, /*             Thai_thophuthao ฒ THAI CHARACTER THO PHUTHAO */
+  { 0x0db3, 0x0e13 }, /*                  Thai_nonen ณ THAI CHARACTER NO NEN */
+  { 0x0db4, 0x0e14 }, /*                  Thai_dodek ด THAI CHARACTER DO DEK */
+  { 0x0db5, 0x0e15 }, /*                  Thai_totao ต THAI CHARACTER TO TAO */
+  { 0x0db6, 0x0e16 }, /*               Thai_thothung ถ THAI CHARACTER THO THUNG */
+  { 0x0db7, 0x0e17 }, /*              Thai_thothahan ท THAI CHARACTER THO THAHAN */
+  { 0x0db8, 0x0e18 }, /*               Thai_thothong ธ THAI CHARACTER THO THONG */
+  { 0x0db9, 0x0e19 }, /*                   Thai_nonu น THAI CHARACTER NO NU */
+  { 0x0dba, 0x0e1a }, /*               Thai_bobaimai บ THAI CHARACTER BO BAIMAI */
+  { 0x0dbb, 0x0e1b }, /*                  Thai_popla ป THAI CHARACTER PO PLA */
+  { 0x0dbc, 0x0e1c }, /*               Thai_phophung ผ THAI CHARACTER PHO PHUNG */
+  { 0x0dbd, 0x0e1d }, /*                   Thai_fofa ฝ THAI CHARACTER FO FA */
+  { 0x0dbe, 0x0e1e }, /*                Thai_phophan พ THAI CHARACTER PHO PHAN */
+  { 0x0dbf, 0x0e1f }, /*                  Thai_fofan ฟ THAI CHARACTER FO FAN */
+  { 0x0dc0, 0x0e20 }, /*             Thai_phosamphao ภ THAI CHARACTER PHO SAMPHAO */
+  { 0x0dc1, 0x0e21 }, /*                   Thai_moma ม THAI CHARACTER MO MA */
+  { 0x0dc2, 0x0e22 }, /*                  Thai_yoyak ย THAI CHARACTER YO YAK */
+  { 0x0dc3, 0x0e23 }, /*                  Thai_rorua ร THAI CHARACTER RO RUA */
+  { 0x0dc4, 0x0e24 }, /*                     Thai_ru ฤ THAI CHARACTER RU */
+  { 0x0dc5, 0x0e25 }, /*                 Thai_loling ล THAI CHARACTER LO LING */
+  { 0x0dc6, 0x0e26 }, /*                     Thai_lu ฦ THAI CHARACTER LU */
+  { 0x0dc7, 0x0e27 }, /*                 Thai_wowaen ว THAI CHARACTER WO WAEN */
+  { 0x0dc8, 0x0e28 }, /*                 Thai_sosala ศ THAI CHARACTER SO SALA */
+  { 0x0dc9, 0x0e29 }, /*                 Thai_sorusi ษ THAI CHARACTER SO RUSI */
+  { 0x0dca, 0x0e2a }, /*                  Thai_sosua ส THAI CHARACTER SO SUA */
+  { 0x0dcb, 0x0e2b }, /*                  Thai_hohip ห THAI CHARACTER HO HIP */
+  { 0x0dcc, 0x0e2c }, /*                Thai_lochula ฬ THAI CHARACTER LO CHULA */
+  { 0x0dcd, 0x0e2d }, /*                   Thai_oang อ THAI CHARACTER O ANG */
+  { 0x0dce, 0x0e2e }, /*               Thai_honokhuk ฮ THAI CHARACTER HO NOKHUK */
+  { 0x0dcf, 0x0e2f }, /*              Thai_paiyannoi ฯ THAI CHARACTER PAIYANNOI */
+  { 0x0dd0, 0x0e30 }, /*                  Thai_saraa ะ THAI CHARACTER SARA A */
+  { 0x0dd1, 0x0e31 }, /*             Thai_maihanakat ั THAI CHARACTER MAI HAN-AKAT */
+  { 0x0dd2, 0x0e32 }, /*                 Thai_saraaa า THAI CHARACTER SARA AA */
+  { 0x0dd3, 0x0e33 }, /*                 Thai_saraam ำ THAI CHARACTER SARA AM */
+  { 0x0dd4, 0x0e34 }, /*                  Thai_sarai ิ THAI CHARACTER SARA I */
+  { 0x0dd5, 0x0e35 }, /*                 Thai_saraii ี THAI CHARACTER SARA II */
+  { 0x0dd6, 0x0e36 }, /*                 Thai_saraue ึ THAI CHARACTER SARA UE */
+  { 0x0dd7, 0x0e37 }, /*                Thai_sarauee ื THAI CHARACTER SARA UEE */
+  { 0x0dd8, 0x0e38 }, /*                  Thai_sarau ุ THAI CHARACTER SARA U */
+  { 0x0dd9, 0x0e39 }, /*                 Thai_sarauu ู THAI CHARACTER SARA UU */
+  { 0x0dda, 0x0e3a }, /*                Thai_phinthu ฺ THAI CHARACTER PHINTHU */
+  { 0x0dde, 0x0e3e }, /*      Thai_maihanakat_maitho ฾ ??? */
+  { 0x0ddf, 0x0e3f }, /*                   Thai_baht ฿ THAI CURRENCY SYMBOL BAHT */
+  { 0x0de0, 0x0e40 }, /*                  Thai_sarae เ THAI CHARACTER SARA E */
+  { 0x0de1, 0x0e41 }, /*                 Thai_saraae แ THAI CHARACTER SARA AE */
+  { 0x0de2, 0x0e42 }, /*                  Thai_sarao โ THAI CHARACTER SARA O */
+  { 0x0de3, 0x0e43 }, /*          Thai_saraaimaimuan ใ THAI CHARACTER SARA AI MAIMUAN */
+  { 0x0de4, 0x0e44 }, /*         Thai_saraaimaimalai ไ THAI CHARACTER SARA AI MAIMALAI */
+  { 0x0de5, 0x0e45 }, /*            Thai_lakkhangyao ๅ THAI CHARACTER LAKKHANGYAO */
+  { 0x0de6, 0x0e46 }, /*               Thai_maiyamok ๆ THAI CHARACTER MAIYAMOK */
+  { 0x0de7, 0x0e47 }, /*              Thai_maitaikhu ็ THAI CHARACTER MAITAIKHU */
+  { 0x0de8, 0x0e48 }, /*                  Thai_maiek ่ THAI CHARACTER MAI EK */
+  { 0x0de9, 0x0e49 }, /*                 Thai_maitho ้ THAI CHARACTER MAI THO */
+  { 0x0dea, 0x0e4a }, /*                 Thai_maitri ๊ THAI CHARACTER MAI TRI */
+  { 0x0deb, 0x0e4b }, /*            Thai_maichattawa ๋ THAI CHARACTER MAI CHATTAWA */
+  { 0x0dec, 0x0e4c }, /*            Thai_thanthakhat ์ THAI CHARACTER THANTHAKHAT */
+  { 0x0ded, 0x0e4d }, /*               Thai_nikhahit ํ THAI CHARACTER NIKHAHIT */
+  { 0x0df0, 0x0e50 }, /*                 Thai_leksun ๐ THAI DIGIT ZERO */
+  { 0x0df1, 0x0e51 }, /*                Thai_leknung ๑ THAI DIGIT ONE */
+  { 0x0df2, 0x0e52 }, /*                Thai_leksong ๒ THAI DIGIT TWO */
+  { 0x0df3, 0x0e53 }, /*                 Thai_leksam ๓ THAI DIGIT THREE */
+  { 0x0df4, 0x0e54 }, /*                  Thai_leksi ๔ THAI DIGIT FOUR */
+  { 0x0df5, 0x0e55 }, /*                  Thai_lekha ๕ THAI DIGIT FIVE */
+  { 0x0df6, 0x0e56 }, /*                 Thai_lekhok ๖ THAI DIGIT SIX */
+  { 0x0df7, 0x0e57 }, /*                Thai_lekchet ๗ THAI DIGIT SEVEN */
+  { 0x0df8, 0x0e58 }, /*                Thai_lekpaet ๘ THAI DIGIT EIGHT */
+  { 0x0df9, 0x0e59 }, /*                 Thai_lekkao ๙ THAI DIGIT NINE */
+  { 0x0ed4, 0x11a8 }, /*             Hangul_J_Kiyeog ᆨ HANGUL JONGSEONG KIYEOK */
+  { 0x0ed5, 0x11a9 }, /*        Hangul_J_SsangKiyeog ᆩ HANGUL JONGSEONG SSANGKIYEOK */
+  { 0x0ed6, 0x11aa }, /*         Hangul_J_KiyeogSios ᆪ HANGUL JONGSEONG KIYEOK-SIOS */
+  { 0x0ed7, 0x11ab }, /*              Hangul_J_Nieun ᆫ HANGUL JONGSEONG NIEUN */
+  { 0x0ed8, 0x11ac }, /*         Hangul_J_NieunJieuj ᆬ HANGUL JONGSEONG NIEUN-CIEUC */
+  { 0x0ed9, 0x11ad }, /*         Hangul_J_NieunHieuh ᆭ HANGUL JONGSEONG NIEUN-HIEUH */
+  { 0x0eda, 0x11ae }, /*             Hangul_J_Dikeud ᆮ HANGUL JONGSEONG TIKEUT */
+  { 0x0edb, 0x11af }, /*              Hangul_J_Rieul ᆯ HANGUL JONGSEONG RIEUL */
+  { 0x0edc, 0x11b0 }, /*        Hangul_J_RieulKiyeog ᆰ HANGUL JONGSEONG RIEUL-KIYEOK */
+  { 0x0edd, 0x11b1 }, /*         Hangul_J_RieulMieum ᆱ HANGUL JONGSEONG RIEUL-MIEUM */
+  { 0x0ede, 0x11b2 }, /*         Hangul_J_RieulPieub ᆲ HANGUL JONGSEONG RIEUL-PIEUP */
+  { 0x0edf, 0x11b3 }, /*          Hangul_J_RieulSios ᆳ HANGUL JONGSEONG RIEUL-SIOS */
+  { 0x0ee0, 0x11b4 }, /*         Hangul_J_RieulTieut ᆴ HANGUL JONGSEONG RIEUL-THIEUTH */
+  { 0x0ee1, 0x11b5 }, /*        Hangul_J_RieulPhieuf ᆵ HANGUL JONGSEONG RIEUL-PHIEUPH */
+  { 0x0ee2, 0x11b6 }, /*         Hangul_J_RieulHieuh ᆶ HANGUL JONGSEONG RIEUL-HIEUH */
+  { 0x0ee3, 0x11b7 }, /*              Hangul_J_Mieum ᆷ HANGUL JONGSEONG MIEUM */
+  { 0x0ee4, 0x11b8 }, /*              Hangul_J_Pieub ᆸ HANGUL JONGSEONG PIEUP */
+  { 0x0ee5, 0x11b9 }, /*          Hangul_J_PieubSios ᆹ HANGUL JONGSEONG PIEUP-SIOS */
+  { 0x0ee6, 0x11ba }, /*               Hangul_J_Sios ᆺ HANGUL JONGSEONG SIOS */
+  { 0x0ee7, 0x11bb }, /*          Hangul_J_SsangSios ᆻ HANGUL JONGSEONG SSANGSIOS */
+  { 0x0ee8, 0x11bc }, /*              Hangul_J_Ieung ᆼ HANGUL JONGSEONG IEUNG */
+  { 0x0ee9, 0x11bd }, /*              Hangul_J_Jieuj ᆽ HANGUL JONGSEONG CIEUC */
+  { 0x0eea, 0x11be }, /*              Hangul_J_Cieuc ᆾ HANGUL JONGSEONG CHIEUCH */
+  { 0x0eeb, 0x11bf }, /*             Hangul_J_Khieuq ᆿ HANGUL JONGSEONG KHIEUKH */
+  { 0x0eec, 0x11c0 }, /*              Hangul_J_Tieut ᇀ HANGUL JONGSEONG THIEUTH */
+  { 0x0eed, 0x11c1 }, /*             Hangul_J_Phieuf ᇁ HANGUL JONGSEONG PHIEUPH */
+  { 0x0eee, 0x11c2 }, /*              Hangul_J_Hieuh ᇂ HANGUL JONGSEONG HIEUH */
+  { 0x0ef8, 0x11eb }, /*            Hangul_J_PanSios ᇫ HANGUL JONGSEONG PANSIOS */
+  { 0x0ef9, 0x11f0 }, /*  Hangul_J_KkogjiDalrinIeung ᇰ HANGUL JONGSEONG YESIEUNG */
+  { 0x0efa, 0x11f9 }, /*        Hangul_J_YeorinHieuh ᇹ HANGUL JONGSEONG YEORINHIEUH */
+  { 0x0aa2, 0x2002 }, /*                     enspace   EN SPACE */
+  { 0x0aa1, 0x2003 }, /*                     emspace   EM SPACE */
+  { 0x0aa3, 0x2004 }, /*                    em3space   THREE-PER-EM SPACE */
+  { 0x0aa4, 0x2005 }, /*                    em4space   FOUR-PER-EM SPACE */
+  { 0x0aa5, 0x2007 }, /*                  digitspace   FIGURE SPACE */
+  { 0x0aa6, 0x2008 }, /*                  punctspace   PUNCTUATION SPACE */
+  { 0x0aa7, 0x2009 }, /*                   thinspace   THIN SPACE */
+  { 0x0aa8, 0x200a }, /*                   hairspace   HAIR SPACE */
+  { 0x0abb, 0x2012 }, /*                     figdash ‒ FIGURE DASH */
+  { 0x0aaa, 0x2013 }, /*                      endash – EN DASH */
+  { 0x0aa9, 0x2014 }, /*                      emdash — EM DASH */
+  { 0x07af, 0x2015 }, /*              Greek_horizbar ― HORIZONTAL BAR */
+  { 0x0cdf, 0x2017 }, /*        hebrew_doublelowline ‗ DOUBLE LOW LINE */
+  { 0x0ad0, 0x2018 }, /*         leftsinglequotemark ‘ LEFT SINGLE QUOTATION MARK */
+  { 0x0ad1, 0x2019 }, /*        rightsinglequotemark ’ RIGHT SINGLE QUOTATION MARK */
+  { 0x0afd, 0x201a }, /*          singlelowquotemark ‚ SINGLE LOW-9 QUOTATION MARK */
+  { 0x0ad2, 0x201c }, /*         leftdoublequotemark “ LEFT DOUBLE QUOTATION MARK */
+  { 0x0ad3, 0x201d }, /*        rightdoublequotemark ” RIGHT DOUBLE QUOTATION MARK */
+  { 0x0afe, 0x201e }, /*          doublelowquotemark „ DOUBLE LOW-9 QUOTATION MARK */
+  { 0x0af1, 0x2020 }, /*                      dagger † DAGGER */
+  { 0x0af2, 0x2021 }, /*                doubledagger ‡ DOUBLE DAGGER */
+  { 0x0ae6, 0x2022 }, /*          enfilledcircbullet • BULLET */
+  { 0x0aaf, 0x2025 }, /*             doubbaselinedot ‥ TWO DOT LEADER */
+  { 0x0aae, 0x2026 }, /*                    ellipsis … HORIZONTAL ELLIPSIS */
+  { 0x0ad6, 0x2032 }, /*                     minutes ′ PRIME */
+  { 0x0ad7, 0x2033 }, /*                     seconds ″ DOUBLE PRIME */
+  { 0x0afc, 0x2038 }, /*                       caret ‸ CARET */
+  { 0x047e, 0x203e }, /*                    overline ‾ OVERLINE */
+  { 0x20a0, 0x20a0 }, /*                     EcuSign ₠ EURO-CURRENCY SIGN */
+  { 0x20a1, 0x20a1 }, /*                   ColonSign ₡ COLON SIGN */
+  { 0x20a2, 0x20a2 }, /*                CruzeiroSign ₢ CRUZEIRO SIGN */
+  { 0x20a3, 0x20a3 }, /*                  FFrancSign ₣ FRENCH FRANC SIGN */
+  { 0x20a4, 0x20a4 }, /*                    LiraSign ₤ LIRA SIGN */
+  { 0x20a5, 0x20a5 }, /*                    MillSign ₥ MILL SIGN */
+  { 0x20a6, 0x20a6 }, /*                   NairaSign ₦ NAIRA SIGN */
+  { 0x20a7, 0x20a7 }, /*                  PesetaSign ₧ PESETA SIGN */
+  { 0x20a8, 0x20a8 }, /*                   RupeeSign ₨ RUPEE SIGN */
+//  { 0x0eff, 0x20a9 }, /*                  Korean_Won ₩ WON SIGN */
+  { 0x20a9, 0x20a9 }, /*                     WonSign ₩ WON SIGN */
+  { 0x20aa, 0x20aa }, /*               NewSheqelSign ₪ NEW SHEQEL SIGN */
+  { 0x20ab, 0x20ab }, /*                    DongSign ₫ DONG SIGN */
+//  { 0x13a4, 0x20ac }, /*                        Euro € EURO SIGN */
+  { 0x20ac, 0x20ac }, /*                    EuroSign € EURO SIGN */
+  { 0x0ab8, 0x2105 }, /*                      careof ℅ CARE OF */
+  { 0x06b0, 0x2116 }, /*                  numerosign № NUMERO SIGN */
+  { 0x0afb, 0x2117 }, /*         phonographcopyright ℗ SOUND RECORDING COPYRIGHT */
+  { 0x0ad4, 0x211e }, /*                prescription ℞ PRESCRIPTION TAKE */
+  { 0x0ac9, 0x2122 }, /*                   trademark ™ TRADE MARK SIGN */
+  { 0x0ab0, 0x2153 }, /*                    onethird ⅓ VULGAR FRACTION ONE THIRD */
+  { 0x0ab1, 0x2154 }, /*                   twothirds ⅔ VULGAR FRACTION TWO THIRDS */
+  { 0x0ab2, 0x2155 }, /*                    onefifth ⅕ VULGAR FRACTION ONE FIFTH */
+  { 0x0ab3, 0x2156 }, /*                   twofifths ⅖ VULGAR FRACTION TWO FIFTHS */
+  { 0x0ab4, 0x2157 }, /*                 threefifths ⅗ VULGAR FRACTION THREE FIFTHS */
+  { 0x0ab5, 0x2158 }, /*                  fourfifths ⅘ VULGAR FRACTION FOUR FIFTHS */
+  { 0x0ab6, 0x2159 }, /*                    onesixth ⅙ VULGAR FRACTION ONE SIXTH */
+  { 0x0ab7, 0x215a }, /*                  fivesixths ⅚ VULGAR FRACTION FIVE SIXTHS */
+  { 0x0ac3, 0x215b }, /*                   oneeighth ⅛ VULGAR FRACTION ONE EIGHTH */
+  { 0x0ac4, 0x215c }, /*                threeeighths ⅜ VULGAR FRACTION THREE EIGHTHS */
+  { 0x0ac5, 0x215d }, /*                 fiveeighths ⅝ VULGAR FRACTION FIVE EIGHTHS */
+  { 0x0ac6, 0x215e }, /*                seveneighths ⅞ VULGAR FRACTION SEVEN EIGHTHS */
+  { 0x08fb, 0x2190 }, /*                   leftarrow ← LEFTWARDS ARROW */
+  { 0x08fc, 0x2191 }, /*                     uparrow ↑ UPWARDS ARROW */
+  { 0x08fd, 0x2192 }, /*                  rightarrow → RIGHTWARDS ARROW */
+  { 0x08fe, 0x2193 }, /*                   downarrow ↓ DOWNWARDS ARROW */
+  { 0x08ce, 0x21d2 }, /*                     implies ⇒ RIGHTWARDS DOUBLE ARROW */
+  { 0x08cd, 0x21d4 }, /*                    ifonlyif ⇔ LEFT RIGHT DOUBLE ARROW */
+  { 0x08ef, 0x2202 }, /*           partialderivative ∂ PARTIAL DIFFERENTIAL */
+  { 0x08c5, 0x2207 }, /*                       nabla ∇ NABLA */
+  { 0x0bca, 0x2218 }, /*                         jot ∘ RING OPERATOR */
+  { 0x08d6, 0x221a }, /*                     radical √ SQUARE ROOT */
+  { 0x08c1, 0x221d }, /*                   variation ∝ PROPORTIONAL TO */
+  { 0x08c2, 0x221e }, /*                    infinity ∞ INFINITY */
+  { 0x08de, 0x2227 }, /*                  logicaland ∧ LOGICAL AND */
+//  { 0x0ba9, 0x2227 }, /*                     upcaret ∧ LOGICAL AND */
+  { 0x08df, 0x2228 }, /*                   logicalor ∨ LOGICAL OR */
+//  { 0x0ba8, 0x2228 }, /*                   downcaret ∨ LOGICAL OR */
+  { 0x08dc, 0x2229 }, /*                intersection ∩ INTERSECTION */
+//  { 0x0bc3, 0x2229 }, /*                      upshoe ∩ INTERSECTION */
+  { 0x08dd, 0x222a }, /*                       union ∪ UNION */
+//  { 0x0bd6, 0x222a }, /*                    downshoe ∪ UNION */
+  { 0x08bf, 0x222b }, /*                    integral ∫ INTEGRAL */
+  { 0x08c0, 0x2234 }, /*                   therefore ∴ THEREFORE */
+  { 0x08c8, 0x223c }, /*                 approximate ∼ TILDE OPERATOR */
+  { 0x08c9, 0x2243 }, /*                similarequal ≃ ASYMPTOTICALLY EQUAL TO */
+  { 0x08bd, 0x2260 }, /*                    notequal ≠ NOT EQUAL TO */
+  { 0x08cf, 0x2261 }, /*                   identical ≡ IDENTICAL TO */
+  { 0x08bc, 0x2264 }, /*               lessthanequal ≤ LESS-THAN OR EQUAL TO */
+  { 0x08be, 0x2265 }, /*            greaterthanequal ≥ GREATER-THAN OR EQUAL TO */
+  { 0x08da, 0x2282 }, /*                  includedin ⊂ SUBSET OF */
+//  { 0x0bda, 0x2282 }, /*                    leftshoe ⊂ SUBSET OF */
+  { 0x08db, 0x2283 }, /*                    includes ⊃ SUPERSET OF */
+//  { 0x0bd8, 0x2283 }, /*                   rightshoe ⊃ SUPERSET OF */
+  { 0x0bdc, 0x22a2 }, /*                    lefttack ⊢ RIGHT TACK */
+  { 0x0bfc, 0x22a3 }, /*                   righttack ⊣ LEFT TACK */
+  { 0x0bce, 0x22a4 }, /*                      uptack ⊤ DOWN TACK */
+  { 0x0bc2, 0x22a5 }, /*                    downtack ⊥ UP TACK */
+  { 0x0bd3, 0x2308 }, /*                     upstile ⌈ LEFT CEILING */
+  { 0x0bc4, 0x230a }, /*                   downstile ⌊ LEFT FLOOR */
+  { 0x0afa, 0x2315 }, /*           telephonerecorder ⌕ TELEPHONE RECORDER */
+  { 0x08a4, 0x2320 }, /*                 topintegral ⌠ TOP HALF INTEGRAL */
+  { 0x08a5, 0x2321 }, /*                 botintegral ⌡ BOTTOM HALF INTEGRAL */
+  { 0x0abc, 0x2329 }, /*            leftanglebracket 〈 LEFT-POINTING ANGLE BRACKET */
+  { 0x0abe, 0x232a }, /*           rightanglebracket 〉 RIGHT-POINTING ANGLE BRACKET */
+  { 0x0bcc, 0x2395 }, /*                        quad ⎕ APL FUNCTIONAL SYMBOL QUAD */
+  { 0x08ab, 0x239b }, /*               topleftparens ⎛ LEFT PARENTHESIS UPPER HOOK */
+  { 0x08ac, 0x239d }, /*               botleftparens ⎝ LEFT PARENTHESIS LOWER HOOK */
+  { 0x08ad, 0x239e }, /*              toprightparens ⎞ RIGHT PARENTHESIS UPPER HOOK */
+  { 0x08ae, 0x23a0 }, /*              botrightparens ⎠ RIGHT PARENTHESIS LOWER HOOK */
+  { 0x08a7, 0x23a1 }, /*            topleftsqbracket ⎡ LEFT SQUARE BRACKET UPPER CORNER */
+  { 0x08a8, 0x23a3 }, /*            botleftsqbracket ⎣ LEFT SQUARE BRACKET LOWER CORNER */
+  { 0x08a9, 0x23a4 }, /*           toprightsqbracket ⎤ RIGHT SQUARE BRACKET UPPER CORNER */
+  { 0x08aa, 0x23a6 }, /*           botrightsqbracket ⎦ RIGHT SQUARE BRACKET LOWER CORNER */
+  { 0x08af, 0x23a8 }, /*        leftmiddlecurlybrace ⎨ LEFT CURLY BRACKET MIDDLE PIECE */
+  { 0x08b0, 0x23ac }, /*       rightmiddlecurlybrace ⎬ RIGHT CURLY BRACKET MIDDLE PIECE */
+  { 0x08a1, 0x23b7 }, /*                 leftradical ⎷ RADICAL SYMBOL BOTTOM */
+  { 0x09ef, 0x23ba }, /*              horizlinescan1 ⎺ HORIZONTAL SCAN LINE-1 */
+  { 0x09f0, 0x23bb }, /*              horizlinescan3 ⎻ HORIZONTAL SCAN LINE-3 */
+  { 0x09f2, 0x23bc }, /*              horizlinescan7 ⎼ HORIZONTAL SCAN LINE-7 */
+  { 0x09f3, 0x23bd }, /*              horizlinescan9 ⎽ HORIZONTAL SCAN LINE-9 */
+  { 0x09e2, 0x2409 }, /*                          ht ␉ SYMBOL FOR HORIZONTAL TABULATION */
+  { 0x09e5, 0x240a }, /*                          lf ␊ SYMBOL FOR LINE FEED */
+  { 0x09e9, 0x240b }, /*                          vt ␋ SYMBOL FOR VERTICAL TABULATION */
+  { 0x09e3, 0x240c }, /*                          ff ␌ SYMBOL FOR FORM FEED */
+  { 0x09e4, 0x240d }, /*                          cr ␍ SYMBOL FOR CARRIAGE RETURN */
+  { 0x09df, 0x2422 }, /*                       blank ␢ BLANK SYMBOL */
+  { 0x0aac, 0x2423 }, /*                 signifblank ␣ OPEN BOX */
+  { 0x09e8, 0x2424 }, /*                          nl ␤ SYMBOL FOR NEWLINE */
+  { 0x08a3, 0x2500 }, /*              horizconnector ─ BOX DRAWINGS LIGHT HORIZONTAL */
+//  { 0x09f1, 0x2500 }, /*              horizlinescan5 ─ BOX DRAWINGS LIGHT HORIZONTAL */
+  { 0x08a6, 0x2502 }, /*               vertconnector │ BOX DRAWINGS LIGHT VERTICAL */
+//  { 0x09f8, 0x2502 }, /*                     vertbar │ BOX DRAWINGS LIGHT VERTICAL */
+  { 0x08a2, 0x250c }, /*              topleftradical ┌ BOX DRAWINGS LIGHT DOWN AND RIGHT */
+//  { 0x09ec, 0x250c }, /*                upleftcorner ┌ BOX DRAWINGS LIGHT DOWN AND RIGHT */
+  { 0x09eb, 0x2510 }, /*               uprightcorner ┐ BOX DRAWINGS LIGHT DOWN AND LEFT */
+  { 0x09ed, 0x2514 }, /*               lowleftcorner └ BOX DRAWINGS LIGHT UP AND RIGHT */
+  { 0x09ea, 0x2518 }, /*              lowrightcorner ┘ BOX DRAWINGS LIGHT UP AND LEFT */
+  { 0x09f4, 0x251c }, /*                       leftt ├ BOX DRAWINGS LIGHT VERTICAL AND RIGHT */
+  { 0x09f5, 0x2524 }, /*                      rightt ┤ BOX DRAWINGS LIGHT VERTICAL AND LEFT */
+  { 0x09f7, 0x252c }, /*                        topt ┬ BOX DRAWINGS LIGHT DOWN AND HORIZONTAL */
+  { 0x09f6, 0x2534 }, /*                        bott ┴ BOX DRAWINGS LIGHT UP AND HORIZONTAL */
+  { 0x09ee, 0x253c }, /*               crossinglines ┼ BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL */
+  { 0x09e1, 0x2592 }, /*                checkerboard ▒ MEDIUM SHADE */
+  { 0x0ae7, 0x25aa }, /*            enfilledsqbullet ▪ BLACK SMALL SQUARE */
+  { 0x0ae1, 0x25ab }, /*          enopensquarebullet ▫ WHITE SMALL SQUARE */
+  { 0x0adb, 0x25ac }, /*            filledrectbullet ▬ BLACK RECTANGLE */
+  { 0x0ae2, 0x25ad }, /*              openrectbullet ▭ WHITE RECTANGLE */
+  { 0x0adf, 0x25ae }, /*                emfilledrect ▮ BLACK VERTICAL RECTANGLE */
+  { 0x0acf, 0x25af }, /*             emopenrectangle ▯ WHITE VERTICAL RECTANGLE */
+  { 0x0ae8, 0x25b2 }, /*           filledtribulletup ▲ BLACK UP-POINTING TRIANGLE */
+  { 0x0ae3, 0x25b3 }, /*             opentribulletup △ WHITE UP-POINTING TRIANGLE */
+  { 0x0add, 0x25b6 }, /*        filledrighttribullet ▶ BLACK RIGHT-POINTING TRIANGLE */
+  { 0x0acd, 0x25b7 }, /*           rightopentriangle ▷ WHITE RIGHT-POINTING TRIANGLE */
+  { 0x0ae9, 0x25bc }, /*         filledtribulletdown ▼ BLACK DOWN-POINTING TRIANGLE */
+  { 0x0ae4, 0x25bd }, /*           opentribulletdown ▽ WHITE DOWN-POINTING TRIANGLE */
+  { 0x0adc, 0x25c0 }, /*         filledlefttribullet ◀ BLACK LEFT-POINTING TRIANGLE */
+  { 0x0acc, 0x25c1 }, /*            leftopentriangle ◁ WHITE LEFT-POINTING TRIANGLE */
+  { 0x09e0, 0x25c6 }, /*                soliddiamond ◆ BLACK DIAMOND */
+  { 0x0ace, 0x25cb }, /*                emopencircle ○ WHITE CIRCLE */
+//  { 0x0bcf, 0x25cb }, /*                      circle ○ WHITE CIRCLE */
+  { 0x0ade, 0x25cf }, /*              emfilledcircle ● BLACK CIRCLE */
+  { 0x0ae0, 0x25e6 }, /*            enopencircbullet ◦ WHITE BULLET */
+  { 0x0ae5, 0x2606 }, /*                    openstar ☆ WHITE STAR */
+  { 0x0af9, 0x260e }, /*                   telephone ☎ BLACK TELEPHONE */
+  { 0x0aca, 0x2613 }, /*               signaturemark ☓ SALTIRE */
+  { 0x0aea, 0x261c }, /*                 leftpointer ☜ WHITE LEFT POINTING INDEX */
+  { 0x0aeb, 0x261e }, /*                rightpointer ☞ WHITE RIGHT POINTING INDEX */
+  { 0x0af8, 0x2640 }, /*                femalesymbol ♀ FEMALE SIGN */
+  { 0x0af7, 0x2642 }, /*                  malesymbol ♂ MALE SIGN */
+  { 0x0aec, 0x2663 }, /*                        club ♣ BLACK CLUB SUIT */
+  { 0x0aee, 0x2665 }, /*                       heart ♥ BLACK HEART SUIT */
+  { 0x0aed, 0x2666 }, /*                     diamond ♦ BLACK DIAMOND SUIT */
+  { 0x0af6, 0x266d }, /*                 musicalflat ♭ MUSIC FLAT SIGN */
+  { 0x0af5, 0x266f }, /*                musicalsharp ♯ MUSIC SHARP SIGN */
+  { 0x0af3, 0x2713 }, /*                   checkmark ✓ CHECK MARK */
+  { 0x0af4, 0x2717 }, /*                 ballotcross ✗ BALLOT X */
+  { 0x0ad9, 0x271d }, /*                  latincross ✝ LATIN CROSS */
+  { 0x0af0, 0x2720 }, /*                maltesecross ✠ MALTESE CROSS */
+  { 0x04a4, 0x3001 }, /*                  kana_comma 、 IDEOGRAPHIC COMMA */
+  { 0x04a1, 0x3002 }, /*               kana_fullstop 。 IDEOGRAPHIC FULL STOP */
+  { 0x04a2, 0x300c }, /*         kana_openingbracket 「 LEFT CORNER BRACKET */
+  { 0x04a3, 0x300d }, /*         kana_closingbracket 」 RIGHT CORNER BRACKET */
+  { 0x04de, 0x309b }, /*                 voicedsound ゛ KATAKANA-HIRAGANA VOICED SOUND MARK */
+  { 0x04df, 0x309c }, /*             semivoicedsound ゜ KATAKANA-HIRAGANA SEMI-VOICED SOUND MARK */
+  { 0x04a7, 0x30a1 }, /*                      kana_a ァ KATAKANA LETTER SMALL A */
+  { 0x04b1, 0x30a2 }, /*                      kana_A ア KATAKANA LETTER A */
+  { 0x04a8, 0x30a3 }, /*                      kana_i ィ KATAKANA LETTER SMALL I */
+  { 0x04b2, 0x30a4 }, /*                      kana_I イ KATAKANA LETTER I */
+  { 0x04a9, 0x30a5 }, /*                      kana_u ゥ KATAKANA LETTER SMALL U */
+  { 0x04b3, 0x30a6 }, /*                      kana_U ウ KATAKANA LETTER U */
+  { 0x04aa, 0x30a7 }, /*                      kana_e ェ KATAKANA LETTER SMALL E */
+  { 0x04b4, 0x30a8 }, /*                      kana_E エ KATAKANA LETTER E */
+  { 0x04ab, 0x30a9 }, /*                      kana_o ォ KATAKANA LETTER SMALL O */
+  { 0x04b5, 0x30aa }, /*                      kana_O オ KATAKANA LETTER O */
+  { 0x04b6, 0x30ab }, /*                     kana_KA カ KATAKANA LETTER KA */
+  { 0x04b7, 0x30ad }, /*                     kana_KI キ KATAKANA LETTER KI */
+  { 0x04b8, 0x30af }, /*                     kana_KU ク KATAKANA LETTER KU */
+  { 0x04b9, 0x30b1 }, /*                     kana_KE ケ KATAKANA LETTER KE */
+  { 0x04ba, 0x30b3 }, /*                     kana_KO コ KATAKANA LETTER KO */
+  { 0x04bb, 0x30b5 }, /*                     kana_SA サ KATAKANA LETTER SA */
+  { 0x04bc, 0x30b7 }, /*                    kana_SHI シ KATAKANA LETTER SI */
+  { 0x04bd, 0x30b9 }, /*                     kana_SU ス KATAKANA LETTER SU */
+  { 0x04be, 0x30bb }, /*                     kana_SE セ KATAKANA LETTER SE */
+  { 0x04bf, 0x30bd }, /*                     kana_SO ソ KATAKANA LETTER SO */
+  { 0x04c0, 0x30bf }, /*                     kana_TA タ KATAKANA LETTER TA */
+  { 0x04c1, 0x30c1 }, /*                    kana_CHI チ KATAKANA LETTER TI */
+  { 0x04af, 0x30c3 }, /*                    kana_tsu ッ KATAKANA LETTER SMALL TU */
+  { 0x04c2, 0x30c4 }, /*                    kana_TSU ツ KATAKANA LETTER TU */
+  { 0x04c3, 0x30c6 }, /*                     kana_TE テ KATAKANA LETTER TE */
+  { 0x04c4, 0x30c8 }, /*                     kana_TO ト KATAKANA LETTER TO */
+  { 0x04c5, 0x30ca }, /*                     kana_NA ナ KATAKANA LETTER NA */
+  { 0x04c6, 0x30cb }, /*                     kana_NI ニ KATAKANA LETTER NI */
+  { 0x04c7, 0x30cc }, /*                     kana_NU ヌ KATAKANA LETTER NU */
+  { 0x04c8, 0x30cd }, /*                     kana_NE ネ KATAKANA LETTER NE */
+  { 0x04c9, 0x30ce }, /*                     kana_NO ノ KATAKANA LETTER NO */
+  { 0x04ca, 0x30cf }, /*                     kana_HA ハ KATAKANA LETTER HA */
+  { 0x04cb, 0x30d2 }, /*                     kana_HI ヒ KATAKANA LETTER HI */
+  { 0x04cc, 0x30d5 }, /*                     kana_FU フ KATAKANA LETTER HU */
+  { 0x04cd, 0x30d8 }, /*                     kana_HE ヘ KATAKANA LETTER HE */
+  { 0x04ce, 0x30db }, /*                     kana_HO ホ KATAKANA LETTER HO */
+  { 0x04cf, 0x30de }, /*                     kana_MA マ KATAKANA LETTER MA */
+  { 0x04d0, 0x30df }, /*                     kana_MI ミ KATAKANA LETTER MI */
+  { 0x04d1, 0x30e0 }, /*                     kana_MU ム KATAKANA LETTER MU */
+  { 0x04d2, 0x30e1 }, /*                     kana_ME メ KATAKANA LETTER ME */
+  { 0x04d3, 0x30e2 }, /*                     kana_MO モ KATAKANA LETTER MO */
+  { 0x04ac, 0x30e3 }, /*                     kana_ya ャ KATAKANA LETTER SMALL YA */
+  { 0x04d4, 0x30e4 }, /*                     kana_YA ヤ KATAKANA LETTER YA */
+  { 0x04ad, 0x30e5 }, /*                     kana_yu ュ KATAKANA LETTER SMALL YU */
+  { 0x04d5, 0x30e6 }, /*                     kana_YU ユ KATAKANA LETTER YU */
+  { 0x04ae, 0x30e7 }, /*                     kana_yo ョ KATAKANA LETTER SMALL YO */
+  { 0x04d6, 0x30e8 }, /*                     kana_YO ヨ KATAKANA LETTER YO */
+  { 0x04d7, 0x30e9 }, /*                     kana_RA ラ KATAKANA LETTER RA */
+  { 0x04d8, 0x30ea }, /*                     kana_RI リ KATAKANA LETTER RI */
+  { 0x04d9, 0x30eb }, /*                     kana_RU ル KATAKANA LETTER RU */
+  { 0x04da, 0x30ec }, /*                     kana_RE レ KATAKANA LETTER RE */
+  { 0x04db, 0x30ed }, /*                     kana_RO ロ KATAKANA LETTER RO */
+  { 0x04dc, 0x30ef }, /*                     kana_WA ワ KATAKANA LETTER WA */
+  { 0x04a6, 0x30f2 }, /*                     kana_WO ヲ KATAKANA LETTER WO */
+  { 0x04dd, 0x30f3 }, /*                      kana_N ン KATAKANA LETTER N */
+  { 0x04a5, 0x30fb }, /*            kana_conjunctive ・ KATAKANA MIDDLE DOT */
+  { 0x04b0, 0x30fc }, /*              prolongedsound ー KATAKANA-HIRAGANA PROLONGED SOUND MARK */
+  { 0x0ea1, 0x3131 }, /*               Hangul_Kiyeog ㄱ HANGUL LETTER KIYEOK */
+  { 0x0ea2, 0x3132 }, /*          Hangul_SsangKiyeog ㄲ HANGUL LETTER SSANGKIYEOK */
+  { 0x0ea3, 0x3133 }, /*           Hangul_KiyeogSios ㄳ HANGUL LETTER KIYEOK-SIOS */
+  { 0x0ea4, 0x3134 }, /*                Hangul_Nieun ㄴ HANGUL LETTER NIEUN */
+  { 0x0ea5, 0x3135 }, /*           Hangul_NieunJieuj ㄵ HANGUL LETTER NIEUN-CIEUC */
+  { 0x0ea6, 0x3136 }, /*           Hangul_NieunHieuh ㄶ HANGUL LETTER NIEUN-HIEUH */
+  { 0x0ea7, 0x3137 }, /*               Hangul_Dikeud ㄷ HANGUL LETTER TIKEUT */
+  { 0x0ea8, 0x3138 }, /*          Hangul_SsangDikeud ㄸ HANGUL LETTER SSANGTIKEUT */
+  { 0x0ea9, 0x3139 }, /*                Hangul_Rieul ㄹ HANGUL LETTER RIEUL */
+  { 0x0eaa, 0x313a }, /*          Hangul_RieulKiyeog ㄺ HANGUL LETTER RIEUL-KIYEOK */
+  { 0x0eab, 0x313b }, /*           Hangul_RieulMieum ㄻ HANGUL LETTER RIEUL-MIEUM */
+  { 0x0eac, 0x313c }, /*           Hangul_RieulPieub ㄼ HANGUL LETTER RIEUL-PIEUP */
+  { 0x0ead, 0x313d }, /*            Hangul_RieulSios ㄽ HANGUL LETTER RIEUL-SIOS */
+  { 0x0eae, 0x313e }, /*           Hangul_RieulTieut ㄾ HANGUL LETTER RIEUL-THIEUTH */
+  { 0x0eaf, 0x313f }, /*          Hangul_RieulPhieuf ㄿ HANGUL LETTER RIEUL-PHIEUPH */
+  { 0x0eb0, 0x3140 }, /*           Hangul_RieulHieuh ㅀ HANGUL LETTER RIEUL-HIEUH */
+  { 0x0eb1, 0x3141 }, /*                Hangul_Mieum ㅁ HANGUL LETTER MIEUM */
+  { 0x0eb2, 0x3142 }, /*                Hangul_Pieub ㅂ HANGUL LETTER PIEUP */
+  { 0x0eb3, 0x3143 }, /*           Hangul_SsangPieub ㅃ HANGUL LETTER SSANGPIEUP */
+  { 0x0eb4, 0x3144 }, /*            Hangul_PieubSios ㅄ HANGUL LETTER PIEUP-SIOS */
+  { 0x0eb5, 0x3145 }, /*                 Hangul_Sios ㅅ HANGUL LETTER SIOS */
+  { 0x0eb6, 0x3146 }, /*            Hangul_SsangSios ㅆ HANGUL LETTER SSANGSIOS */
+  { 0x0eb7, 0x3147 }, /*                Hangul_Ieung ㅇ HANGUL LETTER IEUNG */
+  { 0x0eb8, 0x3148 }, /*                Hangul_Jieuj ㅈ HANGUL LETTER CIEUC */
+  { 0x0eb9, 0x3149 }, /*           Hangul_SsangJieuj ㅉ HANGUL LETTER SSANGCIEUC */
+  { 0x0eba, 0x314a }, /*                Hangul_Cieuc ㅊ HANGUL LETTER CHIEUCH */
+  { 0x0ebb, 0x314b }, /*               Hangul_Khieuq ㅋ HANGUL LETTER KHIEUKH */
+  { 0x0ebc, 0x314c }, /*                Hangul_Tieut ㅌ HANGUL LETTER THIEUTH */
+  { 0x0ebd, 0x314d }, /*               Hangul_Phieuf ㅍ HANGUL LETTER PHIEUPH */
+  { 0x0ebe, 0x314e }, /*                Hangul_Hieuh ㅎ HANGUL LETTER HIEUH */
+  { 0x0ebf, 0x314f }, /*                    Hangul_A ㅏ HANGUL LETTER A */
+  { 0x0ec0, 0x3150 }, /*                   Hangul_AE ㅐ HANGUL LETTER AE */
+  { 0x0ec1, 0x3151 }, /*                   Hangul_YA ㅑ HANGUL LETTER YA */
+  { 0x0ec2, 0x3152 }, /*                  Hangul_YAE ㅒ HANGUL LETTER YAE */
+  { 0x0ec3, 0x3153 }, /*                   Hangul_EO ㅓ HANGUL LETTER EO */
+  { 0x0ec4, 0x3154 }, /*                    Hangul_E ㅔ HANGUL LETTER E */
+  { 0x0ec5, 0x3155 }, /*                  Hangul_YEO ㅕ HANGUL LETTER YEO */
+  { 0x0ec6, 0x3156 }, /*                   Hangul_YE ㅖ HANGUL LETTER YE */
+  { 0x0ec7, 0x3157 }, /*                    Hangul_O ㅗ HANGUL LETTER O */
+  { 0x0ec8, 0x3158 }, /*                   Hangul_WA ㅘ HANGUL LETTER WA */
+  { 0x0ec9, 0x3159 }, /*                  Hangul_WAE ㅙ HANGUL LETTER WAE */
+  { 0x0eca, 0x315a }, /*                   Hangul_OE ㅚ HANGUL LETTER OE */
+  { 0x0ecb, 0x315b }, /*                   Hangul_YO ㅛ HANGUL LETTER YO */
+  { 0x0ecc, 0x315c }, /*                    Hangul_U ㅜ HANGUL LETTER U */
+  { 0x0ecd, 0x315d }, /*                  Hangul_WEO ㅝ HANGUL LETTER WEO */
+  { 0x0ece, 0x315e }, /*                   Hangul_WE ㅞ HANGUL LETTER WE */
+  { 0x0ecf, 0x315f }, /*                   Hangul_WI ㅟ HANGUL LETTER WI */
+  { 0x0ed0, 0x3160 }, /*                   Hangul_YU ㅠ HANGUL LETTER YU */
+  { 0x0ed1, 0x3161 }, /*                   Hangul_EU ㅡ HANGUL LETTER EU */
+  { 0x0ed2, 0x3162 }, /*                   Hangul_YI ㅢ HANGUL LETTER YI */
+  { 0x0ed3, 0x3163 }, /*                    Hangul_I ㅣ HANGUL LETTER I */
+  { 0x0eef, 0x316d }, /*     Hangul_RieulYeorinHieuh ㅭ HANGUL LETTER RIEUL-YEORINHIEUH */
+  { 0x0ef0, 0x3171 }, /*    Hangul_SunkyeongeumMieum ㅱ HANGUL LETTER KAPYEOUNMIEUM */
+  { 0x0ef1, 0x3178 }, /*    Hangul_SunkyeongeumPieub ㅸ HANGUL LETTER KAPYEOUNPIEUP */
+  { 0x0ef2, 0x317f }, /*              Hangul_PanSios ㅿ HANGUL LETTER PANSIOS */
+  { 0x0ef3, 0x3181 }, /*    Hangul_KkogjiDalrinIeung ㆁ HANGUL LETTER YESIEUNG */
+  { 0x0ef4, 0x3184 }, /*   Hangul_SunkyeongeumPhieuf ㆄ HANGUL LETTER KAPYEOUNPHIEUPH */
+  { 0x0ef5, 0x3186 }, /*          Hangul_YeorinHieuh ㆆ HANGUL LETTER YEORINHIEUH */
+  { 0x0ef6, 0x318d }, /*                Hangul_AraeA ㆍ HANGUL LETTER ARAEA */
+  { 0x0ef7, 0x318e }, /*               Hangul_AraeAE ㆎ HANGUL LETTER ARAEAE */
+/*  0x08b1                          topleftsummation ? ??? */
+/*  0x08b2                          botleftsummation ? ??? */
+/*  0x08b3                 topvertsummationconnector ? ??? */
+/*  0x08b4                 botvertsummationconnector ? ??? */
+/*  0x08b5                         toprightsummation ? ??? */
+/*  0x08b6                         botrightsummation ? ??? */
+/*  0x08b7                      rightmiddlesummation ? ??? */
+/*  0x0abf                                    marker ? ??? */
+/*  0x0acb                         trademarkincircle ? ??? */
+/*  0x0ada                                  hexagram ? ??? */
+/*  0x0aff                                    cursor ? ??? */
+};
+
+KeySym ucs2keysym(unsigned int ucs)
+{
+    int min = 0;
+    int max = sizeof(keysymtab) / sizeof(struct codepair) - 1;
+    int mid;
+
+    /* first check for Latin-1 characters (1:1 mapping) */
+    if ((ucs >= 0x0020 && ucs <= 0x007e) ||
+        (ucs >= 0x00a0 && ucs <= 0x00ff))
+        return ucs;
+
+    /* binary search in table */
+    while (max >= min) {
+		mid = (min + max) / 2;
+		if (keysymtab[mid].ucs < ucs)
+			min = mid + 1;
+		else if (keysymtab[mid].ucs > ucs)
+			max = mid - 1;
+		else {
+			/* found it */
+			assert (keysymtab[mid].ucs== ucs);
+			return keysymtab[mid].keysym;
+		}
+    }
+
+    /* no matching Unicode value found */
+    return 0;
+}
diff --git a/src/mod_hid/ucs2keysym.h b/src/mod_hid/ucs2keysym.h
new file mode 100644
index 0000000..5a607e2
--- /dev/null
+++ b/src/mod_hid/ucs2keysym.h
@@ -0,0 +1,6 @@
+#include <X11/X.h>
+extern "C" {
+
+KeySym ucs2keysym(unsigned int ucs);
+
+}
\ No newline at end of file
diff --git a/src/mod_io/CMakeLists.txt b/src/mod_io/CMakeLists.txt
new file mode 100644
index 0000000..6a7fdd2
--- /dev/null
+++ b/src/mod_io/CMakeLists.txt
@@ -0,0 +1,24 @@
+cmake_minimum_required(VERSION 2.6)
+project(mod_io)
+
+set(mod_io_SRCS
+	mod_io.cpp
+	filebrowser.h
+	filebrowser.cpp
+	textfiledump.h
+	textfiledump.cpp
+)
+
+add_library (mod_io MODULE ${mod_io_SRCS})
+
+# Boost
+find_package(Boost COMPONENTS filesystem system REQUIRED)
+target_link_libraries(mod_io ${Boost_FILESYSTEM_LIBRARY})
+target_link_libraries(mod_io ${Boost_SYSTEM_LIBRARY})
+target_link_libraries(mod_io spcore)
+
+if (ENABLE_NLS)
+	target_link_libraries(mod_io ${LIBINTL_LIBRARIES})
+endif(ENABLE_NLS)
+
+INSTALL (TARGETS mod_io RUNTIME DESTINATION ${LIBRUNTIMEDIR} LIBRARY DESTINATION ${PLUGINDIR})
diff --git a/src/mod_io/filebrowser.cpp b/src/mod_io/filebrowser.cpp
new file mode 100644
index 0000000..413717c
--- /dev/null
+++ b/src/mod_io/filebrowser.cpp
@@ -0,0 +1,185 @@
+/////////////////////////////////////////////////////////////////////////////
+// File:        filebrowser.cpp
+// Author:      Cesar Mauri Loba (cesar at crea-si dot com)
+// Copyright:   (C) 2010-11 Cesar Mauri Loba - CREA Software Systems
+//
+//  This program is free software: you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation, either version 3 of the License, or
+//  (at your option) any later version.
+//
+//  This program is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+/////////////////////////////////////////////////////////////////////////////
+#include "filebrowser.h"
+
+#define BOOST_FILESYSTEM_VERSION 3
+#define BOOST_FILESYSTEM_NO_DEPRECATED 1
+#include <boost/filesystem.hpp>
+
+#ifndef NDEBUG
+#include <iostream>
+#endif
+
+using namespace spcore;
+using namespace boost::filesystem;
+using namespace std;
+
+namespace mod_io {
+
+FileBrowserComponent::FileBrowserComponent(const char * name, int argc, const char * argv[])
+: CComponentAdapter(name, argc, argv)
+, m_selectDirs(false)
+
+{
+	// Create pins and storage
+	RegisterInputPin(*SmartPtr<IInputPin>(new InputPinPath(*this), false));
+	RegisterInputPin(*SmartPtr<IInputPin>(new InputPinRefresh(*this), false));
+
+	m_oPinPaths= CTypeAny::CreateOutputPinAny("paths");
+	RegisterOutputPin(*m_oPinPaths);
+	m_oPinFiles= CTypeAny::CreateOutputPinAny("files");
+	RegisterOutputPin(*m_oPinFiles);
+
+	m_pathNames= CTypeComposite::CreateInstance();
+	m_fileNames= CTypeComposite::CreateInstance();
+	
+	// Process arguments
+	if (argc) {
+		for (int i= 0; i< argc; ++i) {
+			if (strcmp ("-p", argv[i])== 0) {
+				// Path
+			
+				++i;
+				if (i< argc) m_currentPath= argv[i];
+				else throw std::runtime_error("file_browser. Missing value for option -p");
+			}
+			else if (strcmp ("-t", argv[i])== 0) {
+				// Type of listing
+				++i;
+
+				char opt= 0;
+
+				if (i< argc && (opt= argv[i][0]) && argv[i][1]== 0 && (opt== 'd' || opt== 'a' )) {
+					if (opt== 'd') m_selectDirs= true;
+					else m_selectDirs= false;
+				}
+				else throw std::runtime_error("file_browser. Wrong value for option -t. Use either d or a.");				
+			}
+			else if (strcmp ("-w", argv[i])== 0) {
+				// Wildcard 
+				
+				// TODO
+				assert (false);
+
+				++i;
+
+				if (i== argc) throw std::runtime_error("file_browser. Missing value for -w argument.");
+				m_wildcard= argv[i];
+			}
+			else if (strlen(argv[i])) {
+				string error_msg("file_browser. Unknown option:");
+				error_msg+= argv[i];
+				throw std::runtime_error(error_msg);
+			}
+		}
+	}
+}
+
+int FileBrowserComponent::DoInitialize()
+{
+	Refresh();
+
+	return 0;
+}
+
+void FileBrowserComponent::Refresh ()
+{
+	if (!m_currentPath.empty() && ReScanPath (m_currentPath.c_str())) {
+		// Send result
+		m_oPinPaths->Send(m_pathNames);
+		m_oPinFiles->Send(m_fileNames);
+	}
+}
+
+void FileBrowserComponent::OnPinPath (const CTypeString & msg)
+{
+	const char* newpath= msg.getValue();
+
+	if (newpath && m_currentPath!= newpath && newpath[0]) {
+		// Path changed and is not void
+		if (ReScanPath (newpath)) {
+			m_currentPath= newpath;
+			m_oPinPaths->Send(m_pathNames);
+			m_oPinFiles->Send(m_fileNames);
+		}
+	}
+}
+
+bool FileBrowserComponent::ReScanPath (const char* path_name)
+{
+	// Check path
+	try {
+		path p(path_name);
+
+		// Is directory?
+		if (!is_directory(p)) {
+			std::string error_msg("Path ");
+			error_msg+= path_name;
+			error_msg+= " is not a directory.";
+			getSpCoreRuntime()->LogMessage(ICoreRuntime::LOG_ERROR, error_msg.c_str(), "filebrowser");
+			return false;
+		}
+
+		// Create result holders
+		SmartPtr<CTypeComposite> resultPaths= CTypeComposite::CreateInstance();
+		SmartPtr<CTypeComposite> resultNames= CTypeComposite::CreateInstance();
+
+		// List contents
+		vector<string> pathList, nameList;
+
+		directory_iterator end_it;	// Default ctor yields past-the-end
+		for(directory_iterator dit(p); dit!= end_it; ++dit) {
+			if ((m_selectDirs && is_directory(dit->path())) || (!m_selectDirs && is_regular_file(dit->path())) ) {
+				// Workaround to cope with both BOOST_FILESYSTEM_VERSION 2 and 3
+				pathList.push_back(dit->path().string().c_str());
+				path tmpfname(dit->path().filename());
+				nameList.push_back(tmpfname.string().c_str());
+			}
+		}
+
+		// Sort
+		sort(pathList.begin(), pathList.end());
+		sort(nameList.begin(), nameList.end());
+
+		vector<string>::const_iterator itp= pathList.begin();
+		vector<string>::const_iterator itn= nameList.begin();
+		for (; itp!= pathList.end() && itn!= nameList.end(); ++itp, ++itn) {
+			SmartPtr<CTypeString> strPath= CTypeString::CreateInstance();
+			strPath->setValue(itp->c_str());
+			resultPaths->AddChild(strPath);
+
+			SmartPtr<CTypeString> strName= CTypeString::CreateInstance();
+			strName->setValue(itn->c_str());
+			resultNames->AddChild(strName);
+		}
+		assert (itp== pathList.end() && itn== nameList.end());
+
+		// Update internal instances
+		m_pathNames= resultPaths;
+		m_fileNames= resultNames;
+	}
+	catch (const std::exception& ex) {
+		getSpCoreRuntime()->LogMessage(ICoreRuntime::LOG_ERROR, ex.what(), "filebrowser");
+		return false;
+	}
+
+	return true;
+}
+
+} // namespace spcore
diff --git a/src/mod_io/filebrowser.h b/src/mod_io/filebrowser.h
new file mode 100755
index 0000000..c3e8aed
--- /dev/null
+++ b/src/mod_io/filebrowser.h
@@ -0,0 +1,119 @@
+/////////////////////////////////////////////////////////////////////////////
+// File:        filebrowser.h
+// Author:      Cesar Mauri Loba (cesar at crea-si dot com)
+// Copyright:   (C) 2010-11 Cesar Mauri Loba - CREA Software Systems
+//
+//  This program is free software: you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation, either version 3 of the License, or
+//  (at your option) any later version.
+//
+//  This program is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+/////////////////////////////////////////////////////////////////////////////
+#pragma once
+
+#include "spcore/basictypes.h"
+#include "spcore/pinimpl.h"
+#include "spcore/component.h"
+#include <string>
+
+namespace mod_io {
+
+/**
+	file_browser component
+
+	This component allows to list the contents of a directory of the hard disk
+
+	Input pins:
+		path (string)	
+			Path to explore. If path exists the lists of files is dumped.
+
+		refresh (any)
+			Re-scans the contents of the current directory and dumps the result
+
+	Output pins:
+		paths (any)		List of file names (full absolute paths)
+		files (any)		List of files names (only names of files)
+
+	Command line:
+		[-p <path>]		Set initial path
+		[-t [d|f] ]		Selects between directories (d) or files (f). Def.: f
+		// TODO
+		[-w <string>]	Wildcard. Ex: *.jpg;*.png
+
+	Notes:
+*/
+class FileBrowserComponent : public spcore::CComponentAdapter {
+public:
+	static const char* getTypeName() { return "file_browser"; };
+	virtual const char* GetTypeName() const { return FileBrowserComponent::getTypeName(); };
+
+	//
+	// Component methods
+	//
+	FileBrowserComponent(const char * name, int argc, const char * argv[]);
+	
+	virtual int DoInitialize();
+
+private:
+	//
+	// Data members
+	//
+	bool m_selectDirs;
+	SmartPtr<spcore::IOutputPin> m_oPinPaths;
+	SmartPtr<spcore::IOutputPin> m_oPinFiles;
+
+	SmartPtr<spcore::CTypeComposite> m_pathNames;
+	SmartPtr<spcore::CTypeComposite> m_fileNames;
+		
+	std::string m_currentPath;
+	std::string m_wildcard;
+
+	//
+	// Methods
+	//
+
+	// Re-scan path and update m_pathNames & m_pathNames. 
+	// Return false if an error ocurred in which case members are not updated
+	bool ReScanPath (const char* path_name);
+	void OnPinPath (const spcore::CTypeString & msg);
+	void Refresh ();
+
+	// 
+	// Input pins classes
+	//
+	class InputPinPath
+		: public spcore::CInputPinWriteOnly<spcore::CTypeString, FileBrowserComponent> {
+	public:
+		InputPinPath (FileBrowserComponent & component)
+		: spcore::CInputPinWriteOnly<spcore::CTypeString, FileBrowserComponent>("path", component) { }
+
+		virtual int DoSend(const spcore::CTypeString & msg) {
+			m_component->OnPinPath(msg);
+			return 0;
+		}
+	};
+
+	class InputPinRefresh
+		: public spcore::CInputPinWriteOnly<spcore::CTypeAny, FileBrowserComponent> {
+	public:
+		InputPinRefresh (FileBrowserComponent & component)
+		: spcore::CInputPinWriteOnly<spcore::CTypeAny, FileBrowserComponent>("refresh", component) { }
+
+		virtual int DoSend(const spcore::CTypeAny &) {
+			m_component->Refresh();
+			return 0;
+		}
+	};
+};
+
+// Component factory
+typedef spcore::ComponentFactory<FileBrowserComponent> FileBrowserComponentFactory;
+
+} // namespace spcore
diff --git a/src/mod_io/mod_io.cpp b/src/mod_io/mod_io.cpp
new file mode 100644
index 0000000..8f64908
--- /dev/null
+++ b/src/mod_io/mod_io.cpp
@@ -0,0 +1,49 @@
+/////////////////////////////////////////////////////////////////////////////
+// File:        mod_io.cpp
+// Author:      Cesar Mauri Loba (cesar at crea-si dot com)
+// Copyright:   (C) 2011 Cesar Mauri Loba - CREA Software Systems
+// 
+//  This program is free software: you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation, either version 3 of the License, or
+//  (at your option) any later version.
+//
+//  This program is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+/////////////////////////////////////////////////////////////////////////////
+
+#include "spcore/libimpexp.h"
+#include "spcore/module.h"
+#include "filebrowser.h"
+#include "textfiledump.h"
+
+using namespace spcore;
+
+namespace mod_io {
+
+/* ******************************************************************************
+	io module
+*/
+class IoModule : public spcore::CModuleAdapter {
+public:
+	IoModule() {
+		
+		RegisterComponentFactory(SmartPtr<spcore::IComponentFactory>(new FileBrowserComponentFactory(), false));
+		RegisterComponentFactory(SmartPtr<spcore::IComponentFactory>(new TextFileDumpComponentFactory(), false));
+	}
+	virtual const char * GetName() const { return "mod_io"; }
+};
+
+static spcore::IModule* g_module= NULL;
+SPEXPORT_FUNCTION spcore::IModule* module_create_instance()
+{
+	if (g_module== NULL) g_module= new IoModule();
+	return g_module;
+}
+
+};
\ No newline at end of file
diff --git a/src/mod_io/textfiledump.cpp b/src/mod_io/textfiledump.cpp
new file mode 100644
index 0000000..e3d3e45
--- /dev/null
+++ b/src/mod_io/textfiledump.cpp
@@ -0,0 +1,139 @@
+/////////////////////////////////////////////////////////////////////////////
+// File:        textfiledump.cpp
+// Author:      Cesar Mauri Loba (cesar at crea-si dot com)
+// Copyright:   (C) 2010-11 Cesar Mauri Loba - CREA Software Systems
+//
+//  This program is free software: you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation, either version 3 of the License, or
+//  (at your option) any later version.
+//
+//  This program is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+/////////////////////////////////////////////////////////////////////////////
+#include "textfiledump.h"
+
+#include <stdio.h>
+
+using namespace spcore;
+using namespace std;
+
+namespace mod_io {
+
+TextFileDumpComponent::TextFileDumpComponent(const char * name, int argc, const char * argv[])
+: CComponentAdapter(name, argc, argv)
+{
+	// Create pins and storage
+	RegisterInputPin(*SmartPtr<IInputPin>(new InputPinPath(*this), false));
+	RegisterInputPin(*SmartPtr<IInputPin>(new InputPinRefresh(*this), false));
+
+	m_oPinContents= CTypeString::CreateOutputPin("contents");
+	RegisterOutputPin(*m_oPinContents);
+	
+	m_contents= CTypeString::CreateInstance();
+		
+	// Process arguments
+	if (argc) {
+		for (int i= 0; i< argc; ++i) {
+			if (argv[i] && strcmp ("-p", argv[i])== 0) {
+				// Path
+			
+				++i;
+				if (i< argc && argv[i]) m_path= argv[i];
+				else throw std::runtime_error("textfile_dump. Missing value for option -p");
+			}			
+			else if (argv[i] && strlen(argv[i])) {
+				string error_msg("textfile_dump. Unknown option:");
+				error_msg+= argv[i];
+				throw std::runtime_error(error_msg);
+			}
+		}
+	}
+}
+
+int TextFileDumpComponent::DoInitialize()
+{
+	Refresh();
+
+	return 0;
+}
+
+void TextFileDumpComponent::Refresh ()
+{
+	if (!m_path.empty()) {
+		
+		size_t readbytes= 0;
+		char* buff= NULL;
+
+		FILE* file= fopen(m_path.c_str(), "rb");
+		if (!file) {
+			string error_msg("Cannot open file ");
+			error_msg+= m_path;
+			getSpCoreRuntime()->LogMessage(ICoreRuntime::LOG_ERROR, error_msg.c_str(), GetName());
+			return;
+		}
+
+		// Obtain size
+		fseek(file, 0L, SEEK_END);
+		long size= ftell(file);
+		fseek(file, 0L, SEEK_SET);
+
+		if (size< 0) {
+			string error_msg("Error reading file ");
+			error_msg+= m_path;
+			getSpCoreRuntime()->LogMessage(ICoreRuntime::LOG_ERROR, error_msg.c_str(), GetName());
+			goto done;
+		}
+		else if (size> MAX_FILE_SIZE) {
+			string error_msg("File too large ");
+			error_msg+= m_path;
+			getSpCoreRuntime()->LogMessage(ICoreRuntime::LOG_ERROR, error_msg.c_str(), GetName());
+			goto done;
+		}
+
+		// Allocate buffer 
+		buff= (char *) malloc (size + 1);
+		if (!buff) {
+			getSpCoreRuntime()->LogMessage(ICoreRuntime::LOG_ERROR, "Memory allocation failed.", GetName());
+			goto done;
+		}
+
+		// Read contents
+		readbytes= fread(buff, 1, size, file);
+		if (ferror(file) || readbytes!= (size_t) size) {
+			getSpCoreRuntime()->LogMessage(ICoreRuntime::LOG_ERROR, "Error reading file.", GetName());
+			goto done_malloc;
+		}
+		buff[size]= 0;
+
+		// Set to output value		
+		m_contents->setValue(buff);
+
+		// Send result
+		m_oPinContents->Send(m_contents);
+
+done_malloc:
+		free (buff);
+
+done:
+		if (file) fclose(file);
+	}
+}
+
+void TextFileDumpComponent::OnPinPath (const CTypeString & msg)
+{
+	const char* newpath= msg.getValue();
+
+	if (newpath && m_path!= newpath && newpath[0]) {
+		// Path changed and is not void
+		m_path= newpath;
+		Refresh();
+	}
+}
+
+} // namespace spcore
diff --git a/src/mod_io/textfiledump.h b/src/mod_io/textfiledump.h
new file mode 100755
index 0000000..f201af9
--- /dev/null
+++ b/src/mod_io/textfiledump.h
@@ -0,0 +1,109 @@
+/////////////////////////////////////////////////////////////////////////////
+// File:        textfiledump.h
+// Author:      Cesar Mauri Loba (cesar at crea-si dot com)
+// Copyright:   (C) 2010-11 Cesar Mauri Loba - CREA Software Systems
+//
+//  This program is free software: you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation, either version 3 of the License, or
+//  (at your option) any later version.
+//
+//  This program is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+/////////////////////////////////////////////////////////////////////////////
+#pragma once
+
+#include "spcore/basictypes.h"
+#include "spcore/pinimpl.h"
+#include "spcore/component.h"
+#include <string>
+
+namespace mod_io {
+
+/**
+	textfile_dump component
+
+	Dumps the contets of a text file as a string
+
+	Input pins:
+		path (string)	
+			Path to explore. If path exists the lists of files is dumped.
+
+		refresh (any)
+			Re-reads the contents of the file and dumps the result
+
+	Output pins:
+		contents (string)		Contents of the text file
+
+	Command line:
+		[-p <path>]		Set initial path
+
+	Notes:
+*/
+class TextFileDumpComponent : public spcore::CComponentAdapter {
+public:
+	static const char* getTypeName() { return "textfile_dump"; };
+	virtual const char* GetTypeName() const { return TextFileDumpComponent::getTypeName(); };
+
+	//
+	// Component methods
+	//
+	TextFileDumpComponent(const char * name, int argc, const char * argv[]);
+	
+	virtual int DoInitialize();
+
+private:
+	// Set a reasonable maximum size
+	enum { MAX_FILE_SIZE= 0xFFFFFF };
+	//
+	// Data members
+	//
+	SmartPtr<spcore::IOutputPin> m_oPinContents;
+	SmartPtr<spcore::CTypeString> m_contents;
+	std::string m_path;
+	
+	//
+	// Methods
+	//
+
+	void OnPinPath (const spcore::CTypeString & msg);
+	void Refresh ();
+
+	// 
+	// Input pins classes
+	//
+	class InputPinPath
+		: public spcore::CInputPinWriteOnly<spcore::CTypeString, TextFileDumpComponent> {
+	public:
+		InputPinPath (TextFileDumpComponent & component)
+		: spcore::CInputPinWriteOnly<spcore::CTypeString, TextFileDumpComponent>("path", component) { }
+
+		virtual int DoSend(const spcore::CTypeString & msg) {
+			m_component->OnPinPath(msg);
+			return 0;
+		}
+	};
+
+	class InputPinRefresh
+		: public spcore::CInputPinWriteOnly<spcore::CTypeAny, TextFileDumpComponent> {
+	public:
+		InputPinRefresh (TextFileDumpComponent & component)
+		: spcore::CInputPinWriteOnly<spcore::CTypeAny, TextFileDumpComponent>("refresh", component) { }
+
+		virtual int DoSend(const spcore::CTypeAny &) {
+			m_component->Refresh();
+			return 0;
+		}
+	};
+
+};
+
+// Component factory
+typedef spcore::ComponentFactory<TextFileDumpComponent> TextFileDumpComponentFactory;
+
+} // namespace spcore
diff --git a/src/mod_ipl_sdl/CMakeLists.txt b/src/mod_ipl_sdl/CMakeLists.txt
new file mode 100644
index 0000000..0f93ae8
--- /dev/null
+++ b/src/mod_ipl_sdl/CMakeLists.txt
@@ -0,0 +1,31 @@
+cmake_minimum_required(VERSION 2.6)
+project(mod_ipl_sdl)
+
+set(mod_ipl_sdl_SRCS
+	mod_ipl_sdl.cpp
+)
+
+FIND_PACKAGE( OpenCV REQUIRED imgproc)
+INCLUDE_DIRECTORIES (${OpenCV_INCLUDE_DIR})
+INCLUDE_DIRECTORIES (..)
+
+set (SDL_BUILDING_LIBRARY ON)
+find_package ( SDL REQUIRED )
+find_package ( SDL_gfx REQUIRED )
+include_directories (${SDL_INCLUDE_DIR})
+include_directories (${SDLGFX_INCLUDE_DIR})
+
+add_library (mod_ipl_sdl MODULE ${mod_ipl_sdl_SRCS})
+
+#
+# Cannot link against other modules
+#
+#target_link_libraries(mod_ipl_sdl mod_camera)
+#target_link_libraries(mod_ipl_sdl mod_sdl)
+
+target_link_libraries(mod_ipl_sdl spcore)
+target_link_libraries(mod_ipl_sdl ${SDL_LIBRARY})
+target_link_libraries(mod_ipl_sdl ${SDLGFX_LIBRARY})
+target_link_libraries(mod_ipl_sdl creavision)
+
+INSTALL (TARGETS mod_ipl_sdl RUNTIME DESTINATION ${LIBRUNTIMEDIR} LIBRARY DESTINATION ${PLUGINDIR})
diff --git a/src/mod_ipl_sdl/mod_ipl_sdl.cpp b/src/mod_ipl_sdl/mod_ipl_sdl.cpp
new file mode 100644
index 0000000..96a5d20
--- /dev/null
+++ b/src/mod_ipl_sdl/mod_ipl_sdl.cpp
@@ -0,0 +1,360 @@
+/////////////////////////////////////////////////////////////////////////////
+// File:        mod_ipl_sdl.cpp
+// Author:      Cesar Mauri Loba (cesar at crea-si dot com)
+// Copyright:   (C) 2012 Cesar Mauri Loba - CREA Software Systems
+//
+//  This program is free software: you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation, either version 3 of the License, or
+//  (at your option) any later version.
+//
+//  This program is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+/////////////////////////////////////////////////////////////////////////////
+#include "mod_camera/iplimagetype.h"
+#include "mod_sdl/sdlsurfacetype.h"
+#include "spcore/libimpexp.h"
+#include <SDL_rotozoom.h>
+
+#include "creavision/crvimage.h"
+
+using namespace spcore;
+using namespace mod_sdl;
+using namespace mod_camera;
+
+namespace mod_ipl_sdl {
+
+static int Ipl2SDL_zoomSurface (const CTypeIplImage &src, SmartPtr<CTypeSDLSurface>& dst)
+{
+	const SDL_VideoInfo* vi= SDL_GetVideoInfo();
+	if (!vi) {
+		getSpCoreRuntime()->LogMessage(ICoreRuntime::LOG_ERROR, "SDL_GetVideoInfo call failed", "mod_collage");
+		return -1;
+	}
+
+	if (src.getImage()->depth!= IPL_DEPTH_8U) {
+		getSpCoreRuntime()->LogMessage(ICoreRuntime::LOG_ERROR, "IPL image format non-supported (depth).", "mod_collage");
+		return -1;
+	}
+
+	Uint32 rmask, gmask, bmask, amask= 0;
+	int nChannels= src.getImage()->nChannels;
+	const char* channelSeq= src.getImage()->channelSeq;
+
+	if (nChannels== 2) {
+		getSpCoreRuntime()->LogMessage(ICoreRuntime::LOG_ERROR, "IPL image format non-supported (# channels).", "mod_collage");
+		return -1;
+	}
+
+	if (nChannels== 1) { rmask= gmask= bmask= 0xff; }				
+	else {
+		if (channelSeq[0]== 'R' && channelSeq[1]== 'G' && channelSeq[2]== 'B') {
+			// RGB channel sequence
+			if (nChannels== 4) {
+				#if SDL_BYTEORDER == SDL_BIG_ENDIAN
+					rmask = 0xff000000;
+					gmask = 0x00ff0000;
+					bmask = 0x0000ff00;
+					amask = 0x000000ff;
+				#else
+					rmask = 0x000000ff;
+					gmask = 0x0000ff00;
+					bmask = 0x00ff0000;
+					amask = 0xff000000;
+				#endif
+			}
+			else {
+				#if SDL_BYTEORDER == SDL_BIG_ENDIAN
+					rmask = 0xff0000;
+					gmask = 0x00ff00;
+					bmask = 0x0000ff;
+				#else
+					rmask = 0x0000ff;
+					gmask = 0x00ff00;
+					bmask = 0xff0000;
+				#endif
+			}
+		}
+		else {
+			// BGR channel sequence
+			if (nChannels== 4) {
+			#if SDL_BYTEORDER == SDL_BIG_ENDIAN
+				rmask = 0x000000ff;
+				gmask = 0x0000ff00;
+				bmask = 0x00ff0000;
+				amask = 0xff000000;
+			#else
+				rmask = 0xff000000;
+				gmask = 0x00ff0000;
+				bmask = 0x0000ff00;
+				amask = 0x000000ff;
+			#endif
+			}
+			else {
+			#if SDL_BYTEORDER == SDL_BIG_ENDIAN
+				rmask = 0x0000ff;
+				gmask = 0x00ff00;
+				bmask = 0xff0000;
+			#else
+				rmask = 0xff0000;
+				gmask = 0x00ff00;
+				bmask = 0x0000ff;							
+			#endif
+			}
+		}
+	}			
+
+	int depth= nChannels * 8;
+
+	// Create surface from ipl image pixels
+	SDL_Surface *orig_surface= 
+		SDL_CreateRGBSurfaceFrom(
+			src.getImage()->imageData, 
+			src.getImage()->width, 
+			src.getImage()->height,
+			depth, 
+			src.getImage()->widthStep,
+			rmask, gmask, bmask, amask);
+	
+	if (!orig_surface) {
+		getSpCoreRuntime()->LogMessage(ICoreRuntime::LOG_ERROR, "SDL_CreateRGBSurfaceFrom failed", "mod_collage");
+		return -1;
+	}
+
+	assert (orig_surface->flags & SDL_SWSURFACE);
+
+	// Compute zoom ratio
+	double zoomx= (double) vi->current_w / (double) src.getImage()->width;
+	double zoomy= (double) vi->current_h / (double) src.getImage()->height;
+	
+	SDL_Surface* result_surface= zoomSurface (orig_surface, zoomx, zoomy, SMOOTHING_OFF);
+	
+	dst->setSurface(result_surface);
+	
+	// Free orig_surface
+	SDL_FreeSurface(orig_surface);
+
+	return 0;
+}
+
+// -2 not-supported error, -1 fatal error
+static int Ipl2SDL_opencv (const CTypeIplImage &src, SmartPtr<CTypeSDLSurface>& dst)
+{
+	const SDL_VideoInfo* vi= SDL_GetVideoInfo();
+	if (!vi) {
+		getSpCoreRuntime()->LogMessage(ICoreRuntime::LOG_ERROR, "SDL_GetVideoInfo call failed", "mod_collage");
+		return -1;
+	}
+
+	//
+	// Temporal IPL image to match colorspace
+	//
+	
+	// frame buffer channel sequence
+	if (vi->vfmt->BytesPerPixel== 2) return -2; // Not supported.
+	int fbOrder;	// false RGB, true BGR
+	int fbHasAlpha= 0;
+	if (vi->vfmt->BytesPerPixel== 4) fbHasAlpha= 1;
+
+#if SDL_BYTEORDER == SDL_BIG_ENDIAN
+	if (vi->vfmt->Rmask> vi->vfmt->Bmask) fbOrder= 0;
+	else fbOrder= 1;
+#else		
+	if (vi->vfmt->Rmask> vi->vfmt->Bmask) fbOrder= 1;
+	else fbOrder= 0;
+#endif
+
+	// src image channel order
+	int srcOrder;	// false RGB, true BGR
+	int srcHasAlpha= 0;
+	if (src.getImage()->nChannels== 2) return -2;	// Non-supported
+	if (src.getImage()->nChannels== 4) srcHasAlpha= 1;
+
+	if (src.getImage()->channelSeq[0]== 'R' || src.getImage()->channelSeq[0]== 'r') srcOrder= 0;
+	else srcOrder= 1;
+
+	// conversion code
+	int code= -1;
+	if (src.getImage()->nChannels== 1) {
+		// source is GRAY
+		if (fbOrder) {
+			if (fbHasAlpha) code= CV_GRAY2BGRA;
+			else code= CV_GRAY2BGR;
+		}
+		else {
+			if (fbHasAlpha) code= CV_GRAY2RGBA;
+			else code= CV_GRAY2RGB;
+		}
+	}
+	else {
+		// source has colour
+		static const int codeArray[]=	// srcOrder, srcHasAlpha, fbOrder, fbHasAlpha
+		{
+			-1,				// b0000
+			CV_RGB2RGBA,	// b0001
+			CV_RGB2BGR,		// b0010
+			CV_RGB2BGRA,	// b0011
+			CV_RGBA2RGB,	// b0100
+			-1,				// b0101
+			CV_RGBA2BGR,	// b0110
+			CV_RGBA2BGRA,	// b0111
+			CV_BGR2RGB,		// b1000
+			CV_BGR2RGBA,	// b1001
+			-1,				// b1010
+			CV_BGR2BGRA,	// b1011
+			CV_BGRA2RGB,	// b1100
+			CV_BGRA2RGBA,	// b1101
+			CV_BGRA2BGR,	// b1110
+			-1				// b1111
+		};
+		
+		code= codeArray[(srcOrder << 3) | (srcHasAlpha << 2) | (fbOrder << 1) | fbHasAlpha];
+	}
+
+	// Create tmp img
+	CIplImage* srcImg_tmp= NULL;
+	if (code!= -1) {
+		const char* fbChannelSeq= NULL;
+		if (fbOrder) {
+			if (fbHasAlpha) fbChannelSeq= "BGRA";
+			else fbChannelSeq= "BGR";
+		}
+		else {
+			if (fbHasAlpha) fbChannelSeq= "RGBA";
+			else fbChannelSeq= "RGB";
+		}
+		srcImg_tmp= new CIplImage (src.getImage()->width, src.getImage()->height, IPL_DEPTH_8U, fbChannelSeq);
+		cvCvtColor(src.getImage(), srcImg_tmp->ptr(), code );
+	}
+
+	//
+	// Temporal IPL image using the SDL pixels (on hardware)
+	//
+
+	// Create surface
+	SDL_Surface* surface_result= SDL_CreateRGBSurface(
+		SDL_HWSURFACE, 
+		vi->current_w, vi->current_h, 
+		vi->vfmt->BitsPerPixel, 
+		vi->vfmt->Rmask, vi->vfmt->Gmask, vi->vfmt->Bmask, vi->vfmt->Amask);
+
+	// Create IPL image with the same properties as the resulting sdl format
+	IplImage* img_result= cvCreateImageHeader( cvSize(vi->current_w, vi->current_h), IPL_DEPTH_8U, vi->vfmt->BytesPerPixel );
+
+	// Adjust fields to meet fb format
+	for (int i= 0; i< 4; ++i) img_result->channelSeq[i]= src.getImage()->channelSeq[i];
+	img_result->widthStep= surface_result->pitch;
+	img_result->imageData= static_cast<char*>(surface_result->pixels);	// Point to SDL pixels
+	img_result->imageSize= surface_result->pitch * surface_result->h;
+
+	// Resize
+	if (SDL_MUSTLOCK(surface_result)) SDL_LockSurface(surface_result);
+	//cvConvertScale (src.getImage(), img_result, scale, 0);
+	if (code!= -1)
+		cvResize(srcImg_tmp->ptr(), img_result, CV_INTER_LINEAR);
+	else
+		cvResize(src.getImage(), img_result, CV_INTER_LINEAR);
+	if (SDL_MUSTLOCK(surface_result)) SDL_UnlockSurface(surface_result);
+
+	// Release resources
+	cvReleaseImageHeader(&img_result);
+	delete srcImg_tmp;
+
+	// Store result
+	dst->setSurface(surface_result);
+
+	return 0;
+}
+
+
+
+
+/* ******************************************************************************
+	ipl2sdl		Convert IPL image into SDL surfaces
+
+	Input pins:
+		in (iplimage): input image
+
+	Output pins:
+		out (sdl_surface): output sdl surface
+
+	Command line flags:		
+*/
+
+class Ipl2Sdl : public CComponentAdapter
+{
+public:
+	static const char * getTypeName() { return "ipl2sdl"; }
+	virtual const char * GetTypeName() const { return Ipl2Sdl::getTypeName(); }
+
+	Ipl2Sdl(const char * name, int argc, const char * argv[])
+	: CComponentAdapter(name, argc, argv)
+	{
+		m_oPinResult= CTypeSDLSurface::CreateOutputPin("out");
+		if (m_oPinResult.get()== NULL)
+			// Output pin creation failed. Shouldn't happen but...
+			throw std::runtime_error("Ipl2Sdl: output pin creation failed.");
+		RegisterOutputPin (*m_oPinResult);
+
+		RegisterInputPin (*SmartPtr<InputPinIPL>(new InputPinIPL(*this), false));
+		
+		m_SDLSurface= CTypeSDLSurface::CreateInstance();
+		if (m_SDLSurface.get()== NULL)
+			throw std::runtime_error("Ipl2Sdl: cannot create internal instance.");
+	}
+
+private:
+	SmartPtr<CTypeSDLSurface> m_SDLSurface;
+	SmartPtr<spcore::IOutputPin> m_oPinResult;
+
+	// Write pin to send the SDL surface
+	class InputPinIPL : public CInputPinWriteOnly<CTypeIplImage, Ipl2Sdl> {
+	public:
+		InputPinIPL (Ipl2Sdl & component) : CInputPinWriteOnly<CTypeIplImage, Ipl2Sdl>("in", component) {}
+		virtual int DoSend(const CTypeIplImage &src) {
+			assert (getSpCoreRuntime()->IsMainThread());
+			if (!getSpCoreRuntime()->IsMainThread()) {
+				getSpCoreRuntime()->LogMessage (ICoreRuntime::LOG_ERROR, "message from non-main thread. ignoring", "ipl2sdl");
+				return -1;
+			}
+			else {
+				// First try the fastest function
+				int retval= Ipl2SDL_opencv(src, m_component->m_SDLSurface);
+				if (retval== -2) 
+					// If the previous function failed by a non-fatal error try the slow function
+					retval= Ipl2SDL_zoomSurface (src, m_component->m_SDLSurface);
+				if (retval) return retval;
+				
+				return m_component->m_oPinResult->Send (m_component->m_SDLSurface);
+			}
+		}
+	};
+};
+
+// camera_viewer component factory
+typedef ComponentFactory<Ipl2Sdl> Ipl2SdlFactory;
+
+/* ******************************************************************************
+	sdl_base module
+*/
+class Ipl2SdlModule : public spcore::CModuleAdapter {
+public:
+	Ipl2SdlModule() {
+		RegisterComponentFactory(SmartPtr<spcore::IComponentFactory>(new Ipl2SdlFactory(), false));
+	}
+	virtual const char * GetName() const { return "mod_ipl_sdl"; }
+};
+
+static spcore::IModule* g_module= NULL;
+SPEXPORT_FUNCTION spcore::IModule* module_create_instance()
+{
+	if (g_module== NULL) g_module= new Ipl2SdlModule();
+	return g_module;
+}
+
+};
diff --git a/src/mod_midi/CMakeLists.txt b/src/mod_midi/CMakeLists.txt
new file mode 100755
index 0000000..f055100
--- /dev/null
+++ b/src/mod_midi/CMakeLists.txt
@@ -0,0 +1,39 @@
+cmake_minimum_required(VERSION 2.8)
+project(mod_midi)
+
+#
+# Required libraries
+# 
+find_package ( PortMidi REQUIRED )
+if (MSVC)	
+	find_file (PortMidi_RUNTIME_REL portmidi.dll HINTS $ENV{PORTMIDIDIR}/lib $ENV{PORTMIDIDIR}/bin)
+	find_file (PortMidi_RUNTIME_DBG portmidid.dll HINTS $ENV{PORTMIDIDIR}/lib $ENV{PORTMIDIDIR}/bin)
+	
+	configure_file("${PortMidi_RUNTIME_DBG}" ${RUNTIME_OUTPUT_DIRECTORY}/Debug COPYONLY)
+	configure_file("${PortMidi_RUNTIME_REL}" ${RUNTIME_OUTPUT_DIRECTORY}/Release COPYONLY)
+endif(MSVC)
+
+if(WIN32)
+	install(FILES ${PortMidi_RUNTIME_DBG} DESTINATION "${LIBRUNTIMEDIR}" CONFIGURATIONS Debug)
+	install(FILES ${PortMidi_RUNTIME_REL} DESTINATION "${LIBRUNTIMEDIR}" CONFIGURATIONS Release)
+endif(WIN32)
+
+set(mod_midi_SRCS
+	${CUSTOM_INCLUDE_PATH}/mod_midi/midi_types.h
+	mod_midi.cpp
+	midiconfiggui.h
+	midiconfiggui.cpp
+)
+
+include_directories (${PortMidi_INCLUDE_DIRS})
+add_library (mod_midi MODULE ${mod_midi_SRCS})
+target_link_libraries(mod_midi spcore)
+target_link_libraries(mod_midi ${PortMidi_LIBRARIES})
+target_link_libraries(mod_midi ${wxWidgets_LIBRARIES})
+
+install (FILES ${CUSTOM_INCLUDE_PATH}/mod_midi/midi_types.h DESTINATION ${INCLUDEDIR}/${PROJECT_NAME})
+INSTALL (TARGETS mod_midi RUNTIME DESTINATION ${LIBRUNTIMEDIR} LIBRARY DESTINATION ${PLUGINDIR})
+
+IF(BUILD_TESTS)
+	ADD_SUBDIRECTORY(tests)
+ENDIF(BUILD_TESTS)
diff --git a/src/mod_midi/midi_config_gui.pjd b/src/mod_midi/midi_config_gui.pjd
new file mode 100755
index 0000000..805b2c8
--- /dev/null
+++ b/src/mod_midi/midi_config_gui.pjd
@@ -0,0 +1,685 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<anthemion-project version="1.0.0.0" xmlns="http://www.anthemion.co.uk">
+  <header>
+    <long name="name_counter">0</long>
+    <string name="html_path">""</string>
+    <string name="title">""</string>
+    <string name="author">""</string>
+    <string name="description">""</string>
+    <string name="xrc_filename">""</string>
+    <long name="image_mode">0</long>
+    <bool name="inline_images">0</bool>
+    <bool name="generate_cpp_for_xrc">0</bool>
+    <long name="working_mode">1</long>
+    <bool name="use_help_text_for_tooltips">1</bool>
+    <bool name="translate_strings">1</bool>
+    <bool name="make_unicode_strings">1</bool>
+    <bool name="extract_strings">0</bool>
+    <string name="user_name">"César Mauri Loba"</string>
+    <string name="copyright_string">"3DB07020-865C504F-B8F7B01B"</string>
+    <string name="resource_prefix">""</string>
+    <bool name="use_two_step_construction">0</bool>
+    <bool name="use_enums">0</bool>
+    <bool name="generate_for_xrced">0</bool>
+    <bool name="generate_virtual_eventhandlers">0</bool>
+    <string name="current_platform">"<All platforms>"</string>
+    <string name="target_wx_version">"2.8.7"</string>
+    <string name="app_kind">"Standard"</string>
+    <string name="cpp_header_comment">"/////////////////////////////////////////////////////////////////////////////
+// Name:        %HEADER-FILENAME%
+// Purpose:     
+// Author:      %AUTHOR%
+// Modified by: 
+// Created:     %DATE%
+// RCS-ID:      
+// Copyright:   %COPYRIGHT%
+// Licence:     
+/////////////////////////////////////////////////////////////////////////////
+
+"</string>
+    <string name="cpp_implementation_comment">"/////////////////////////////////////////////////////////////////////////////
+// Name:        %SOURCE-FILENAME%
+// Purpose:     
+// Author:      %AUTHOR%
+// Modified by: 
+// Created:     %DATE%
+// RCS-ID:      
+// Copyright:   %COPYRIGHT%
+// Licence:     
+/////////////////////////////////////////////////////////////////////////////
+
+"</string>
+    <string name="cpp_symbols_file_comment">"/////////////////////////////////////////////////////////////////////////////
+// Name:        %SYMBOLS-FILENAME%
+// Purpose:     Symbols file
+// Author:      %AUTHOR%
+// Modified by: 
+// Created:     %DATE%
+// RCS-ID:      
+// Copyright:   %COPYRIGHT%
+// Licence:     
+/////////////////////////////////////////////////////////////////////////////
+
+"</string>
+    <string name="cpp_header_preamble">""</string>
+    <string name="cpp_implementation_preamble">"// For compilers that support precompilation, includes "wx/wx.h".
+#include "wx/wxprec.h"
+
+#ifdef __BORLANDC__
+#pragma hdrstop
+#endif
+
+#ifndef WX_PRECOMP
+#include "wx/wx.h"
+#endif
+
+"</string>
+    <string name="cpp_function_declaration_comment">"	/// %BODY%
+"</string>
+    <string name="cpp_function_implementation_comment">"
+/*
+ * %BODY%
+ */
+
+"</string>
+    <string name="resource_file_header">"app_resources.h"</string>
+    <string name="resource_file_implementation">"app_resources.cpp"</string>
+    <string name="resource_class_name">"AppResources"</string>
+    <string name="app_file_header">"app.h"</string>
+    <string name="app_file_implementation">"app.cpp"</string>
+    <string name="app_class_name">"Application"</string>
+    <bool name="generate_app_class">0</bool>
+    <string name="external_symbol_filenames">""</string>
+    <string name="configuration">"<None>"</string>
+    <string name="source_encoding">"iso-8859-1"</string>
+    <string name="xrc_encoding">"utf-8"</string>
+    <string name="project_encoding">"utf-8"</string>
+    <string name="resource_archive">""</string>
+    <long name="text_file_type">1</long>
+    <bool name="use_tabs">0</bool>
+    <long name="indent_size">4</long>
+    <string name="whitespace_after_return_type">" "</string>
+    <string name="resource_xrc_cpp">""</string>
+    <bool name="use_resource_archive">0</bool>
+    <bool name="use_generated_xrc_cpp">0</bool>
+    <bool name="always_generate_xrc">1</bool>
+    <bool name="use_id_name_for_name">0</bool>
+    <bool name="archive_xrc_files">1</bool>
+    <bool name="archive_image_files">1</bool>
+    <bool name="archive_all_image_files">0</bool>
+    <bool name="xrc_retain_relative_paths">1</bool>
+    <bool name="xrc_generate_id_tags">0</bool>
+    <bool name="xrc_use_name_property">0</bool>
+  </header>
+  <data>
+    <document>
+      <string name="title">""</string>
+      <string name="type">"data-document"</string>
+      <string name="filename">""</string>
+      <string name="icon-name">""</string>
+      <long name="is-transient">0</long>
+      <long name="owns-file">1</long>
+      <long name="title-mode">0</long>
+      <long name="locked">0</long>
+      <document>
+        <string name="title">"Configurations"</string>
+        <string name="type">"config-data-document"</string>
+        <string name="filename">""</string>
+        <string name="icon-name">""</string>
+        <long name="is-transient">0</long>
+        <long name="owns-file">1</long>
+        <long name="title-mode">0</long>
+        <long name="locked">0</long>
+        <string name="template-name">""</string>
+        <bool name="dirty">1</bool>
+        <long name="makefile-last-written">-8519680</long>
+        <string name="Compiler name">""</string>
+        <string name="Build mode">"Debug"</string>
+        <string name="Unicode mode">"Unicode"</string>
+        <string name="Shared mode">"Static"</string>
+        <string name="Modularity">"Modular"</string>
+        <string name="GUI mode">"GUI"</string>
+        <string name="Toolkit">"wxMSW"</string>
+        <string name="Processor type">"Default"</string>
+        <string name="Runtime linking">"Dynamic"</string>
+        <string name="Use exceptions">"Yes"</string>
+        <string name="Use ODBC">"No"</string>
+        <string name="Use XRC">"Yes"</string>
+        <string name="Use OpenGL">"No"</string>
+        <string name="Use wxMediaCtrl">"No"</string>
+        <string name="Use wxRichTextCtrl">"Yes"</string>
+        <string name="Use wxHTML">"Yes"</string>
+        <string name="Use wxPropertyGrid">"Yes"</string>
+        <string name="Use wxAUI">"Yes"</string>
+        <string name="Use wxSTC">"Yes"</string>
+        <string name="Use wxRibbonControl">"Yes"</string>
+        <string name="Executable name">"%EXECUTABLE%"</string>
+        <string name="Program arguments">""</string>
+        <string name="Working path">"%AUTO%"</string>
+        <string name="Output path">"%AUTO%"</string>
+        <string name="Objects path">"%AUTO%"</string>
+        <string name="Project makefile">"%AUTO%"</string>
+        <string name="wxWidgets version">"%WXVERSION%"</string>
+        <string name="wxWidgets makefile">"%AUTO%"</string>
+        <string name="wxWidgets location">"%AUTO%"</string>
+        <string name="wxWidgets build path">"%AUTO%"</string>
+        <string name="wxWidgets build command">"%AUTO%"</string>
+        <string name="wxWidgets clean command">"%AUTO%"</string>
+        <string name="CFG">""</string>
+        <string name="Compiler location">"%AUTO%"</string>
+        <string name="Compiler bin path">"%AUTO%"</string>
+        <string name="Compiler include path">"%AUTO%"</string>
+        <string name="Compiler lib path">"%AUTO%"</string>
+        <string name="PATH variable">"%AUTO%"</string>
+        <string name="C++ command">"%AUTO%"</string>
+        <string name="C command">"%AUTO%"</string>
+        <string name="Linker command">"%AUTO%"</string>
+        <string name="Resource compiler">"%AUTO%"</string>
+        <string name="Make command">"%AUTO%"</string>
+        <string name="Preprocessor flags">"%AUTO%"</string>
+        <string name="Optimizations">"%AUTO%"</string>
+        <string name="Warnings">"%AUTO%"</string>
+        <string name="Debug flags">"%AUTO%"</string>
+        <string name="Extra compile flags">"%AUTO%"</string>
+        <string name="Libraries">"%AUTO%"</string>
+        <string name="Library path">"%AUTO%"</string>
+        <string name="Linker flags">"%AUTO%"</string>
+        <string name="Include path">"%AUTO%"</string>
+        <string name="Resource flags">"%AUTO%"</string>
+        <string name="Resource path">"%AUTO%"</string>
+        <bool name="Suppress source rules">0</bool>
+        <bool name="Enable makefile generation">1</bool>
+      </document>
+    </document>
+  </data>
+
+  <documents>
+    <document>
+      <string name="title">"Projects"</string>
+      <string name="type">"root-document"</string>
+      <string name="filename">""</string>
+      <string name="icon-name">"project"</string>
+      <long name="is-transient">1</long>
+      <long name="owns-file">1</long>
+      <long name="title-mode">0</long>
+      <long name="locked">1</long>
+      <document>
+        <string name="title">"Windows"</string>
+        <string name="type">"html-document"</string>
+        <string name="filename">""</string>
+        <string name="icon-name">"dialogsfolder"</string>
+        <long name="is-transient">1</long>
+        <long name="owns-file">1</long>
+        <long name="title-mode">0</long>
+        <long name="locked">1</long>
+        <document>
+          <string name="title">"MIDI Config"</string>
+          <string name="type">"dialog-document"</string>
+          <string name="filename">""</string>
+          <string name="icon-name">"dialog"</string>
+          <long name="is-transient">0</long>
+          <long name="owns-file">1</long>
+          <long name="title-mode">0</long>
+          <long name="locked">0</long>
+          <string name="proxy-type">"wbDialogProxy"</string>
+          <long name="base-id">10000</long>
+          <bool name="use-id-prefix">0</bool>
+          <string name="id-prefix">""</string>
+          <bool name="use-id-suffix">0</bool>
+          <string name="id-suffix">""</string>
+          <string name="app-kind">"Standard"</string>
+          <long name="use-xrc">0</long>
+          <long name="working-mode">0</long>
+          <string name="event-handler-0">"wxEVT_CLOSE_WINDOW|OnCloseWindow|NONE||MIDIConfigGui"</string>
+          <string name="proxy-Id name">"ID_MIDICONFIGGUI"</string>
+          <long name="proxy-Id value">10000</long>
+          <string name="proxy-Class">"MIDIConfigGui"</string>
+          <string name="proxy-Base class">"wxPanel"</string>
+          <string name="proxy-Window kind">"wxPanel"</string>
+          <string name="proxy-Implementation filename">"midiconfiggui.cpp"</string>
+          <string name="proxy-Header filename">"midiconfiggui.h"</string>
+          <string name="proxy-XRC filename">""</string>
+          <string name="proxy-Title">"MIDI Config"</string>
+          <bool name="proxy-Centre">1</bool>
+          <string name="proxy-Icon">""</string>
+          <bool name="proxy-Dialog units">0</bool>
+          <string name="proxy-Help text">""</string>
+          <string name="proxy-Tooltip text">""</string>
+          <string name="proxy-Background colour">""</string>
+          <string name="proxy-Foreground colour">""</string>
+          <string name="proxy-Font">""</string>
+          <bool name="proxy-Hidden">0</bool>
+          <bool name="proxy-Enabled">1</bool>
+          <string name="proxy-Platform">"<Any platform>"</string>
+          <string name="proxy-Data source">""</string>
+          <string name="proxy-Data class name">""</string>
+          <string name="proxy-Data class implementation filename">""</string>
+          <string name="proxy-Data class header filename">""</string>
+          <string name="proxy-Data class manager window">""</string>
+          <string name="proxy-Texture">""</string>
+          <string name="proxy-Texture style">"Tiled"</string>
+          <bool name="proxy-wxDEFAULT_DIALOG_STYLE">0</bool>
+          <bool name="proxy-wxCAPTION">1</bool>
+          <bool name="proxy-wxRESIZE_BORDER">0</bool>
+          <bool name="proxy-wxSYSTEM_MENU">0</bool>
+          <bool name="proxy-wxSTAY_ON_TOP">0</bool>
+          <bool name="proxy-wxDIALOG_NO_PARENT">0</bool>
+          <bool name="proxy-wxCLOSE_BOX">0</bool>
+          <bool name="proxy-wxMAXIMIZE_BOX">0</bool>
+          <bool name="proxy-wxMINIMIZE_BOX">0</bool>
+          <bool name="proxy-wxDIALOG_MODAL">0</bool>
+          <bool name="proxy-wxNO_BORDER">0</bool>
+          <bool name="proxy-wxSIMPLE_BORDER">0</bool>
+          <bool name="proxy-wxDOUBLE_BORDER">0</bool>
+          <bool name="proxy-wxBORDER_THEME">0</bool>
+          <bool name="proxy-wxSUNKEN_BORDER">0</bool>
+          <bool name="proxy-wxRAISED_BORDER">0</bool>
+          <bool name="proxy-wxSTATIC_BORDER">0</bool>
+          <bool name="proxy-wxWANTS_CHARS">0</bool>
+          <bool name="proxy-wxNO_FULL_REPAINT_ON_RESIZE">0</bool>
+          <bool name="proxy-wxFULL_REPAINT_ON_RESIZE">0</bool>
+          <bool name="proxy-wxCLIP_CHILDREN">0</bool>
+          <bool name="proxy-wxTAB_TRAVERSAL">1</bool>
+          <bool name="proxy-wxWS_EX_VALIDATE_RECURSIVELY">0</bool>
+          <bool name="proxy-wxWS_EX_BLOCK_EVENTS">1</bool>
+          <bool name="proxy-wxWS_EX_TRANSIENT">0</bool>
+          <string name="proxy-Custom styles">""</string>
+          <bool name="proxy-wxDIALOG_EX_CONTEXTHELP">0</bool>
+          <bool name="proxy-Fit to content">1</bool>
+          <long name="proxy-X">-1</long>
+          <long name="proxy-Y">-1</long>
+          <long name="proxy-Width">400</long>
+          <long name="proxy-Height">300</long>
+          <bool name="proxy-AUI manager">0</bool>
+          <string name="proxy-Event sources">""</string>
+          <document>
+            <string name="title">"wxBoxSizer V"</string>
+            <string name="type">"dialog-control-document"</string>
+            <string name="filename">""</string>
+            <string name="icon-name">"sizer"</string>
+            <long name="is-transient">0</long>
+            <long name="owns-file">1</long>
+            <long name="title-mode">0</long>
+            <long name="locked">0</long>
+            <string name="proxy-type">"wbBoxSizerProxy"</string>
+            <string name="proxy-Orientation">"Vertical"</string>
+            <string name="proxy-Member variable name">""</string>
+            <bool name="proxy-wxSHAPED">0</bool>
+            <bool name="proxy-wxADJUST_MINSIZE">0</bool>
+            <bool name="proxy-wxFIXED_MINSIZE">0</bool>
+            <string name="proxy-Platform">"<Any platform>"</string>
+            <document>
+              <string name="title">"wxStaticBoxSizer V"</string>
+              <string name="type">"dialog-control-document"</string>
+              <string name="filename">""</string>
+              <string name="icon-name">"sizer"</string>
+              <long name="is-transient">0</long>
+              <long name="owns-file">1</long>
+              <long name="title-mode">0</long>
+              <long name="locked">0</long>
+              <string name="proxy-type">"wbStaticBoxSizerProxy"</string>
+              <string name="proxy-Id name">"wxID_ANY"</string>
+              <long name="proxy-Id value">-1</long>
+              <string name="proxy-Label">"Select MIDI output device"</string>
+              <string name="proxy-Member variable name">""</string>
+              <string name="proxy-Sizer member variable name">""</string>
+              <string name="proxy-Foreground colour">""</string>
+              <string name="proxy-Font">""</string>
+              <bool name="proxy-Hidden">0</bool>
+              <bool name="proxy-Enabled">1</bool>
+              <string name="proxy-Static box class">"wxStaticBox"</string>
+              <string name="proxy-Orientation">"Vertical"</string>
+              <string name="proxy-AlignH">"Left"</string>
+              <string name="proxy-AlignV">"Centre"</string>
+              <long name="proxy-Stretch factor">0</long>
+              <long name="proxy-Border">5</long>
+              <bool name="proxy-wxLEFT">1</bool>
+              <bool name="proxy-wxRIGHT">1</bool>
+              <bool name="proxy-wxTOP">1</bool>
+              <bool name="proxy-wxBOTTOM">1</bool>
+              <bool name="proxy-wxSHAPED">0</bool>
+              <bool name="proxy-wxADJUST_MINSIZE">0</bool>
+              <bool name="proxy-wxFIXED_MINSIZE">0</bool>
+              <string name="proxy-Platform">"<Any platform>"</string>
+              <document>
+                <string name="title">"wxBoxSizer H"</string>
+                <string name="type">"dialog-control-document"</string>
+                <string name="filename">""</string>
+                <string name="icon-name">"sizer"</string>
+                <long name="is-transient">0</long>
+                <long name="owns-file">1</long>
+                <long name="title-mode">0</long>
+                <long name="locked">0</long>
+                <string name="proxy-type">"wbBoxSizerProxy"</string>
+                <string name="proxy-Orientation">"Horizontal"</string>
+                <string name="proxy-Member variable name">""</string>
+                <string name="proxy-AlignH">"Left"</string>
+                <string name="proxy-AlignV">"Centre"</string>
+                <long name="proxy-Stretch factor">0</long>
+                <long name="proxy-Border">5</long>
+                <bool name="proxy-wxLEFT">1</bool>
+                <bool name="proxy-wxRIGHT">1</bool>
+                <bool name="proxy-wxTOP">1</bool>
+                <bool name="proxy-wxBOTTOM">1</bool>
+                <bool name="proxy-wxSHAPED">0</bool>
+                <bool name="proxy-wxADJUST_MINSIZE">0</bool>
+                <bool name="proxy-wxFIXED_MINSIZE">0</bool>
+                <string name="proxy-Platform">"<Any platform>"</string>
+                <document>
+                  <string name="title">"wxChoice: ID_CHOICE_MIDI_OUT"</string>
+                  <string name="type">"dialog-control-document"</string>
+                  <string name="filename">""</string>
+                  <string name="icon-name">"choice"</string>
+                  <long name="is-transient">0</long>
+                  <long name="owns-file">1</long>
+                  <long name="title-mode">0</long>
+                  <long name="locked">0</long>
+                  <string name="proxy-type">"wbChoiceProxy"</string>
+                  <string name="proxy-Id name">"ID_CHOICE_MIDI_OUT"</string>
+                  <long name="proxy-Id value">10001</long>
+                  <string name="proxy-Name">""</string>
+                  <string name="proxy-Class">"wxChoice"</string>
+                  <string name="proxy-Base class">"wxChoice"</string>
+                  <bool name="proxy-External implementation">1</bool>
+                  <bool name="proxy-Separate files">0</bool>
+                  <string name="proxy-Implementation filename">""</string>
+                  <string name="proxy-Header filename">""</string>
+                  <string name="proxy-Member variable name">"m_choMidiOut"</string>
+                  <string name="proxy-Strings">""</string>
+                  <string name="proxy-Initial value">""</string>
+                  <string name="proxy-Help text">""</string>
+                  <string name="proxy-Tooltip text">""</string>
+                  <string name="proxy-Background colour">""</string>
+                  <string name="proxy-Foreground colour">""</string>
+                  <string name="proxy-Font">""</string>
+                  <bool name="proxy-Hidden">0</bool>
+                  <bool name="proxy-Enabled">1</bool>
+                  <string name="proxy-Platform">"<Any platform>"</string>
+                  <string name="proxy-Data variable">""</string>
+                  <string name="proxy-Data validator">""</string>
+                  <string name="proxy-Data source">""</string>
+                  <string name="proxy-Data class name">""</string>
+                  <string name="proxy-Data class implementation filename">""</string>
+                  <string name="proxy-Data class header filename">""</string>
+                  <string name="proxy-Data class manager window">""</string>
+                  <bool name="proxy-wxWANTS_CHARS">0</bool>
+                  <bool name="proxy-wxNO_FULL_REPAINT_ON_RESIZE">0</bool>
+                  <bool name="proxy-wxFULL_REPAINT_ON_RESIZE">0</bool>
+                  <string name="proxy-Custom styles">""</string>
+                  <long name="proxy-X">-1</long>
+                  <long name="proxy-Y">-1</long>
+                  <long name="proxy-Width">-1</long>
+                  <long name="proxy-Height">-1</long>
+                  <string name="proxy-AlignH">"Expand"</string>
+                  <string name="proxy-AlignV">"Centre"</string>
+                  <long name="proxy-Stretch factor">0</long>
+                  <long name="proxy-Border">5</long>
+                  <bool name="proxy-wxLEFT">1</bool>
+                  <bool name="proxy-wxRIGHT">1</bool>
+                  <bool name="proxy-wxTOP">1</bool>
+                  <bool name="proxy-wxBOTTOM">1</bool>
+                  <bool name="proxy-wxSHAPED">0</bool>
+                  <bool name="proxy-wxADJUST_MINSIZE">0</bool>
+                  <bool name="proxy-wxFIXED_MINSIZE">0</bool>
+                  <string name="proxy-Custom arguments">""</string>
+                  <string name="proxy-Custom ctor arguments">""</string>
+                </document>
+                <document>
+                  <string name="title">"wxButton: ID_BUTTON_MIDI_TEST"</string>
+                  <string name="type">"dialog-control-document"</string>
+                  <string name="filename">""</string>
+                  <string name="icon-name">"dialogcontrol"</string>
+                  <long name="is-transient">0</long>
+                  <long name="owns-file">1</long>
+                  <long name="title-mode">0</long>
+                  <long name="locked">0</long>
+                  <string name="proxy-type">"wbButtonProxy"</string>
+                  <string name="event-handler-0">"wxEVT_COMMAND_BUTTON_CLICKED|OnButtonMidiTestClick|NONE||MIDIConfigGui"</string>
+                  <string name="proxy-Id name">"ID_BUTTON_MIDI_TEST"</string>
+                  <long name="proxy-Id value">10002</long>
+                  <string name="proxy-Name">""</string>
+                  <string name="proxy-Class">"wxButton"</string>
+                  <string name="proxy-Base class">"wxButton"</string>
+                  <bool name="proxy-External implementation">1</bool>
+                  <bool name="proxy-Separate files">0</bool>
+                  <string name="proxy-Implementation filename">""</string>
+                  <string name="proxy-Header filename">""</string>
+                  <string name="proxy-Member variable name">""</string>
+                  <string name="proxy-Label">"Test"</string>
+                  <bool name="proxy-Default">0</bool>
+                  <string name="proxy-Help text">""</string>
+                  <string name="proxy-Tooltip text">""</string>
+                  <string name="proxy-Data variable">""</string>
+                  <string name="proxy-Data validator">""</string>
+                  <string name="proxy-Data source">""</string>
+                  <string name="proxy-Data class name">""</string>
+                  <string name="proxy-Data class implementation filename">""</string>
+                  <string name="proxy-Data class header filename">""</string>
+                  <string name="proxy-Data class manager window">""</string>
+                  <string name="proxy-Background colour">""</string>
+                  <string name="proxy-Foreground colour">""</string>
+                  <string name="proxy-Font">""</string>
+                  <bool name="proxy-Hidden">0</bool>
+                  <bool name="proxy-Enabled">1</bool>
+                  <string name="proxy-Platform">"<Any platform>"</string>
+                  <bool name="proxy-wxBU_LEFT">0</bool>
+                  <bool name="proxy-wxBU_RIGHT">0</bool>
+                  <bool name="proxy-wxBU_TOP">0</bool>
+                  <bool name="proxy-wxBU_BOTTOM">0</bool>
+                  <bool name="proxy-wxBU_EXACTFIT">0</bool>
+                  <bool name="proxy-wxNO_BORDER">0</bool>
+                  <bool name="proxy-wxWANTS_CHARS">0</bool>
+                  <bool name="proxy-wxNO_FULL_REPAINT_ON_RESIZE">0</bool>
+                  <bool name="proxy-wxFULL_REPAINT_ON_RESIZE">0</bool>
+                  <string name="proxy-Custom styles">""</string>
+                  <long name="proxy-X">-1</long>
+                  <long name="proxy-Y">-1</long>
+                  <long name="proxy-Width">-1</long>
+                  <long name="proxy-Height">-1</long>
+                  <string name="proxy-AlignH">"Centre"</string>
+                  <string name="proxy-AlignV">"Centre"</string>
+                  <long name="proxy-Stretch factor">0</long>
+                  <long name="proxy-Border">5</long>
+                  <bool name="proxy-wxLEFT">1</bool>
+                  <bool name="proxy-wxRIGHT">1</bool>
+                  <bool name="proxy-wxTOP">1</bool>
+                  <bool name="proxy-wxBOTTOM">1</bool>
+                  <bool name="proxy-wxSHAPED">0</bool>
+                  <bool name="proxy-wxADJUST_MINSIZE">0</bool>
+                  <bool name="proxy-wxFIXED_MINSIZE">0</bool>
+                  <string name="proxy-Custom arguments">""</string>
+                  <string name="proxy-Custom ctor arguments">""</string>
+                </document>
+              </document>
+            </document>
+            <document>
+              <string name="title">"wxStdDialogButtonSizer"</string>
+              <string name="type">"dialog-control-document"</string>
+              <string name="filename">""</string>
+              <string name="icon-name">"sizer"</string>
+              <long name="is-transient">0</long>
+              <long name="owns-file">1</long>
+              <long name="title-mode">0</long>
+              <long name="locked">0</long>
+              <string name="proxy-type">"wbStdDialogButtonSizerProxy"</string>
+              <bool name="proxy-wxID_OK">1</bool>
+              <bool name="proxy-wxID_CANCEL">1</bool>
+              <bool name="proxy-wxID_YES">0</bool>
+              <bool name="proxy-wxID_NO">0</bool>
+              <bool name="proxy-wxID_HELP">0</bool>
+              <bool name="proxy-wxID_APPLY">0</bool>
+              <bool name="proxy-wxID_SAVE">0</bool>
+              <bool name="proxy-wxID_CONTEXT_HELP">0</bool>
+              <string name="proxy-Member variable name">""</string>
+              <string name="proxy-AlignH">"Right"</string>
+              <string name="proxy-AlignV">"Centre"</string>
+              <long name="proxy-Stretch factor">0</long>
+              <long name="proxy-Border">5</long>
+              <bool name="proxy-wxLEFT">1</bool>
+              <bool name="proxy-wxRIGHT">1</bool>
+              <bool name="proxy-wxTOP">1</bool>
+              <bool name="proxy-wxBOTTOM">1</bool>
+              <bool name="proxy-wxSHAPED">0</bool>
+              <bool name="proxy-wxADJUST_MINSIZE">0</bool>
+              <bool name="proxy-wxFIXED_MINSIZE">0</bool>
+              <string name="proxy-Platform">"<Any platform>"</string>
+              <document>
+                <string name="title">"wxButton: wxID_OK"</string>
+                <string name="type">"dialog-control-document"</string>
+                <string name="filename">""</string>
+                <string name="icon-name">"dialogcontrol"</string>
+                <long name="is-transient">0</long>
+                <long name="owns-file">1</long>
+                <long name="title-mode">0</long>
+                <long name="locked">1</long>
+                <string name="proxy-type">"wbButtonProxy"</string>
+                <string name="event-handler-0">"wxEVT_COMMAND_BUTTON_CLICKED|OnOkClick|NONE||MIDIConfigGui"</string>
+                <string name="proxy-Id name">"wxID_OK"</string>
+                <long name="proxy-Id value">5100</long>
+                <string name="proxy-Name">""</string>
+                <string name="proxy-Class">"wxButton"</string>
+                <string name="proxy-Base class">"wxButton"</string>
+                <bool name="proxy-External implementation">1</bool>
+                <bool name="proxy-Separate files">0</bool>
+                <string name="proxy-Implementation filename">""</string>
+                <string name="proxy-Header filename">""</string>
+                <string name="proxy-Member variable name">""</string>
+                <string name="proxy-Label">"&OK"</string>
+                <bool name="proxy-Default">0</bool>
+                <string name="proxy-Help text">""</string>
+                <string name="proxy-Tooltip text">""</string>
+                <string name="proxy-Data variable">""</string>
+                <string name="proxy-Data validator">""</string>
+                <string name="proxy-Data source">""</string>
+                <string name="proxy-Data class name">""</string>
+                <string name="proxy-Data class implementation filename">""</string>
+                <string name="proxy-Data class header filename">""</string>
+                <string name="proxy-Data class manager window">""</string>
+                <string name="proxy-Background colour">""</string>
+                <string name="proxy-Foreground colour">""</string>
+                <string name="proxy-Font">""</string>
+                <bool name="proxy-Hidden">0</bool>
+                <bool name="proxy-Enabled">1</bool>
+                <string name="proxy-Platform">"<Any platform>"</string>
+                <bool name="proxy-wxBU_LEFT">0</bool>
+                <bool name="proxy-wxBU_RIGHT">0</bool>
+                <bool name="proxy-wxBU_TOP">0</bool>
+                <bool name="proxy-wxBU_BOTTOM">0</bool>
+                <bool name="proxy-wxBU_EXACTFIT">0</bool>
+                <bool name="proxy-wxNO_BORDER">0</bool>
+                <bool name="proxy-wxWANTS_CHARS">0</bool>
+                <bool name="proxy-wxNO_FULL_REPAINT_ON_RESIZE">0</bool>
+                <bool name="proxy-wxFULL_REPAINT_ON_RESIZE">0</bool>
+                <string name="proxy-Custom styles">""</string>
+                <long name="proxy-X">-1</long>
+                <long name="proxy-Y">-1</long>
+                <long name="proxy-Width">-1</long>
+                <long name="proxy-Height">-1</long>
+                <string name="proxy-AlignH">"Centre"</string>
+                <string name="proxy-AlignV">"Centre"</string>
+                <long name="proxy-Stretch factor">0</long>
+                <long name="proxy-Border">5</long>
+                <bool name="proxy-wxLEFT">1</bool>
+                <bool name="proxy-wxRIGHT">1</bool>
+                <bool name="proxy-wxTOP">1</bool>
+                <bool name="proxy-wxBOTTOM">1</bool>
+                <bool name="proxy-wxSHAPED">0</bool>
+                <bool name="proxy-wxADJUST_MINSIZE">0</bool>
+                <bool name="proxy-wxFIXED_MINSIZE">0</bool>
+                <string name="proxy-Custom arguments">""</string>
+                <string name="proxy-Custom ctor arguments">""</string>
+              </document>
+              <document>
+                <string name="title">"wxButton: wxID_CANCEL"</string>
+                <string name="type">"dialog-control-document"</string>
+                <string name="filename">""</string>
+                <string name="icon-name">"dialogcontrol"</string>
+                <long name="is-transient">0</long>
+                <long name="owns-file">1</long>
+                <long name="title-mode">0</long>
+                <long name="locked">1</long>
+                <string name="proxy-type">"wbButtonProxy"</string>
+                <string name="event-handler-0">"wxEVT_COMMAND_BUTTON_CLICKED|OnCancelClick|NONE||MIDIConfigGui"</string>
+                <string name="proxy-Id name">"wxID_CANCEL"</string>
+                <long name="proxy-Id value">5101</long>
+                <string name="proxy-Name">""</string>
+                <string name="proxy-Class">"wxButton"</string>
+                <string name="proxy-Base class">"wxButton"</string>
+                <bool name="proxy-External implementation">1</bool>
+                <bool name="proxy-Separate files">0</bool>
+                <string name="proxy-Implementation filename">""</string>
+                <string name="proxy-Header filename">""</string>
+                <string name="proxy-Member variable name">""</string>
+                <string name="proxy-Label">"&Cancel"</string>
+                <bool name="proxy-Default">0</bool>
+                <string name="proxy-Help text">""</string>
+                <string name="proxy-Tooltip text">""</string>
+                <string name="proxy-Data variable">""</string>
+                <string name="proxy-Data validator">""</string>
+                <string name="proxy-Data source">""</string>
+                <string name="proxy-Data class name">""</string>
+                <string name="proxy-Data class implementation filename">""</string>
+                <string name="proxy-Data class header filename">""</string>
+                <string name="proxy-Data class manager window">""</string>
+                <string name="proxy-Background colour">""</string>
+                <string name="proxy-Foreground colour">""</string>
+                <string name="proxy-Font">""</string>
+                <bool name="proxy-Hidden">0</bool>
+                <bool name="proxy-Enabled">1</bool>
+                <string name="proxy-Platform">"<Any platform>"</string>
+                <bool name="proxy-wxBU_LEFT">0</bool>
+                <bool name="proxy-wxBU_RIGHT">0</bool>
+                <bool name="proxy-wxBU_TOP">0</bool>
+                <bool name="proxy-wxBU_BOTTOM">0</bool>
+                <bool name="proxy-wxBU_EXACTFIT">0</bool>
+                <bool name="proxy-wxNO_BORDER">0</bool>
+                <bool name="proxy-wxWANTS_CHARS">0</bool>
+                <bool name="proxy-wxNO_FULL_REPAINT_ON_RESIZE">0</bool>
+                <bool name="proxy-wxFULL_REPAINT_ON_RESIZE">0</bool>
+                <string name="proxy-Custom styles">""</string>
+                <long name="proxy-X">-1</long>
+                <long name="proxy-Y">-1</long>
+                <long name="proxy-Width">-1</long>
+                <long name="proxy-Height">-1</long>
+                <string name="proxy-AlignH">"Centre"</string>
+                <string name="proxy-AlignV">"Centre"</string>
+                <long name="proxy-Stretch factor">0</long>
+                <long name="proxy-Border">5</long>
+                <bool name="proxy-wxLEFT">1</bool>
+                <bool name="proxy-wxRIGHT">1</bool>
+                <bool name="proxy-wxTOP">1</bool>
+                <bool name="proxy-wxBOTTOM">1</bool>
+                <bool name="proxy-wxSHAPED">0</bool>
+                <bool name="proxy-wxADJUST_MINSIZE">0</bool>
+                <bool name="proxy-wxFIXED_MINSIZE">0</bool>
+                <string name="proxy-Custom arguments">""</string>
+                <string name="proxy-Custom ctor arguments">""</string>
+              </document>
+            </document>
+          </document>
+        </document>
+      </document>
+      <document>
+        <string name="title">"Sources"</string>
+        <string name="type">"html-document"</string>
+        <string name="filename">""</string>
+        <string name="icon-name">"sourcesfolder"</string>
+        <long name="is-transient">1</long>
+        <long name="owns-file">1</long>
+        <long name="title-mode">0</long>
+        <long name="locked">1</long>
+      </document>
+      <document>
+        <string name="title">"Images"</string>
+        <string name="type">"html-document"</string>
+        <string name="filename">""</string>
+        <string name="icon-name">"bitmapsfolder"</string>
+        <long name="is-transient">1</long>
+        <long name="owns-file">1</long>
+        <long name="title-mode">0</long>
+        <long name="locked">1</long>
+      </document>
+    </document>
+  </documents>
+
+</anthemion-project>
diff --git a/src/mod_midi/midiconfiggui.cpp b/src/mod_midi/midiconfiggui.cpp
new file mode 100644
index 0000000..0bad9e1
--- /dev/null
+++ b/src/mod_midi/midiconfiggui.cpp
@@ -0,0 +1,361 @@
+/////////////////////////////////////////////////////////////////////////////
+// Name:        midiconfiggui.cpp
+// Purpose:
+// Author:      C�sar Mauri Loba
+// Modified by:
+// Created:     01/04/2011 18:13:36
+// RCS-ID:
+// Copyright:   (C) 2011 Cesar Mauri Loba - CREA Software Systems
+// 
+//  This program is free software: you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation, either version 3 of the License, or
+//  (at your option) any later version.
+//
+//  This program is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with this program.  If not, see <http://www.gnu.org/licenses/>. 
+/////////////////////////////////////////////////////////////////////////////
+
+// For compilers that support precompilation, includes "wx/wx.h".
+#include "wx/wxprec.h"
+
+#ifdef __BORLANDC__
+#pragma hdrstop
+#endif
+
+#ifndef WX_PRECOMP
+#include "wx/wx.h"
+#endif
+
+////@begin includes
+////@end includes
+
+#include "midiconfiggui.h"
+#include "mod_midi/midi_types.h"
+
+#include "spcore/coreruntime.h"
+#include "spcore/pinimpl.h"
+#include "spcore/iterator.h"
+#include "spcore/basictypes.h"
+
+////@begin XPM images
+////@end XPM images
+
+using namespace spcore;
+
+namespace mod_midi {
+
+// Pin to receive the list of output devices
+class InputPinDevices : public CInputPinWriteOnly<CTypeAny, MIDIConfigGui> {
+public:
+	InputPinDevices (MIDIConfigGui & component)
+	:  CInputPinWriteOnly<CTypeAny, MIDIConfigGui>("device_list", component) {}
+
+	virtual int DoSend(const CTypeAny & msg) {
+		// Clean entries
+		m_component->m_choMidiOut->Clear();
+
+		// Populate output midi devices
+		SmartPtr<IIterator<CTypeAny*> > it=	msg.QueryChildren();
+
+		for (it->First(); !it->IsDone(); it->Next()) {
+			CTypeString* name= sptype_dynamic_cast<CTypeString>(it->CurrentItem());
+			if (name) {
+				m_component->m_choMidiOut->Append (wxString(name->getValue(), wxConvUTF8));
+			}
+		}
+
+		return 0;
+	}
+};
+
+/*
+ * MIDIConfigGui type definition
+ */
+
+IMPLEMENT_DYNAMIC_CLASS( MIDIConfigGui, wxPanel )
+
+
+/*
+ * MIDIConfigGui event table definition
+ */
+
+BEGIN_EVENT_TABLE( MIDIConfigGui, wxPanel )
+
+////@begin MIDIConfigGui event table entries
+    EVT_CLOSE( MIDIConfigGui::OnCloseWindow )
+
+    EVT_BUTTON( ID_BUTTON_MIDI_TEST, MIDIConfigGui::OnButtonMidiTestClick )
+
+    EVT_BUTTON( wxID_OK, MIDIConfigGui::OnOkClick )
+
+    EVT_BUTTON( wxID_CANCEL, MIDIConfigGui::OnCancelClick )
+
+////@end MIDIConfigGui event table entries
+
+END_EVENT_TABLE()
+
+
+/*
+ * MIDIConfigGui constructors
+ */
+
+MIDIConfigGui::MIDIConfigGui()
+{
+    Init();
+}
+
+MIDIConfigGui::MIDIConfigGui( wxWindow* parent, wxWindowID id, const wxPoint& pos, const wxSize& size, long style, const wxString& name )
+{
+    Init();
+    Create(parent, id, pos, size, style, name);
+}
+
+
+/*
+ * MIDIConfigGui creator
+ */
+
+bool MIDIConfigGui::Create( wxWindow* parent, wxWindowID id, const wxPoint& pos, const wxSize& size, long style, const wxString& name )
+{
+////@begin MIDIConfigGui creation
+    SetExtraStyle(wxWS_EX_BLOCK_EVENTS);
+    wxPanel::Create( parent, id, pos, size, style, name );
+
+    CreateControls();
+    if (GetSizer())
+    {
+        GetSizer()->SetSizeHints(this);
+    }
+    Centre();
+////@end MIDIConfigGui creation
+    return true;
+}
+
+
+/*
+ * MIDIConfigGui destructor
+ */
+
+MIDIConfigGui::~MIDIConfigGui()
+{
+////@begin MIDIConfigGui destruction
+////@end MIDIConfigGui destruction
+}
+
+
+/*
+ * Member initialisation
+ */
+
+void MIDIConfigGui::Init()
+{
+////@begin MIDIConfigGui member initialisation
+    m_choMidiOut = NULL;
+////@end MIDIConfigGui member initialisation
+}
+
+
+/*
+ * Control creation for MIDIConfigGui
+ */
+
+void MIDIConfigGui::CreateControls()
+{
+////@begin MIDIConfigGui content construction
+    MIDIConfigGui* itemPanel1 = this;
+
+    wxBoxSizer* itemBoxSizer2 = new wxBoxSizer(wxVERTICAL);
+    itemPanel1->SetSizer(itemBoxSizer2);
+
+    wxStaticBox* itemStaticBoxSizer3Static = new wxStaticBox(itemPanel1, wxID_ANY, _("Select MIDI output device"));
+    wxStaticBoxSizer* itemStaticBoxSizer3 = new wxStaticBoxSizer(itemStaticBoxSizer3Static, wxVERTICAL);
+    itemBoxSizer2->Add(itemStaticBoxSizer3, 0, wxALIGN_LEFT|wxALL, 5);
+
+    wxBoxSizer* itemBoxSizer4 = new wxBoxSizer(wxHORIZONTAL);
+    itemStaticBoxSizer3->Add(itemBoxSizer4, 0, wxALIGN_LEFT|wxALL, 5);
+
+    wxArrayString m_choMidiOutStrings;
+    m_choMidiOut = new wxChoice( itemPanel1, ID_CHOICE_MIDI_OUT, wxDefaultPosition, wxDefaultSize, m_choMidiOutStrings, 0 );
+    itemBoxSizer4->Add(m_choMidiOut, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5);
+
+    wxButton* itemButton6 = new wxButton( itemPanel1, ID_BUTTON_MIDI_TEST, _("Test"), wxDefaultPosition, wxDefaultSize, 0 );
+    itemBoxSizer4->Add(itemButton6, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5);
+
+    wxStdDialogButtonSizer* itemStdDialogButtonSizer7 = new wxStdDialogButtonSizer;
+
+    itemBoxSizer2->Add(itemStdDialogButtonSizer7, 0, wxALIGN_RIGHT|wxALL, 5);
+    wxButton* itemButton8 = new wxButton( itemPanel1, wxID_OK, _("&OK"), wxDefaultPosition, wxDefaultSize, 0 );
+    itemStdDialogButtonSizer7->AddButton(itemButton8);
+
+    wxButton* itemButton9 = new wxButton( itemPanel1, wxID_CANCEL, _("&Cancel"), wxDefaultPosition, wxDefaultSize, 0 );
+    itemStdDialogButtonSizer7->AddButton(itemButton9);
+
+    itemStdDialogButtonSizer7->Realize();
+
+////@end MIDIConfigGui content construction
+
+	// Create midi_config component
+	m_midiConfigComponent= getSpCoreRuntime()->CreateComponent("midi_config", "mc", 0, NULL);
+	if (m_midiConfigComponent.get()== NULL) {
+		getSpCoreRuntime()->LogMessage (ICoreRuntime::LOG_FATAL, "cannot create midi_config component", "midi_module");
+		return;
+	}
+
+	// Find output pin
+	IOutputPin* opin= IComponent::FindOutputPin(*m_midiConfigComponent, "device_list");
+	assert (opin);
+
+	// Create a temporary input pin and connect
+	InputPinDevices devicesPin(*this);
+	int retval= opin->Connect(devicesPin);
+	assert (!retval);
+
+	// Send message to fill available midi devices
+	SmartPtr<CTypeBool> foo= CTypeBool::CreateInstance();
+	IInputPin* ipinReqStatus= IComponent::FindInputPin(*m_midiConfigComponent, "req_status");
+	assert (opin);
+	ipinReqStatus->Send(foo);
+	opin->Disconnect(devicesPin);
+
+	// Read current configured device
+	IInputPin* devicePin= IComponent::FindInputPin(*m_midiConfigComponent, "out_device");
+	assert (devicePin);
+	SmartPtr<const CTypeInt> outDev= sptype_dynamic_cast<const CTypeInt>(devicePin->Read());
+	m_choMidiOut->SetSelection(outDev->getValue());
+}
+
+
+/*
+ * Should we show tooltips?
+ */
+
+bool MIDIConfigGui::ShowToolTips()
+{
+    return true;
+}
+
+/*
+ * Get bitmap resources
+ */
+
+wxBitmap MIDIConfigGui::GetBitmapResource( const wxString& name )
+{
+    // Bitmap retrieval
+////@begin MIDIConfigGui bitmap retrieval
+    wxUnusedVar(name);
+    return wxNullBitmap;
+////@end MIDIConfigGui bitmap retrieval
+}
+
+/*
+ * Get icon resources
+ */
+
+wxIcon MIDIConfigGui::GetIconResource( const wxString& name )
+{
+    // Icon retrieval
+////@begin MIDIConfigGui icon retrieval
+    wxUnusedVar(name);
+    return wxNullIcon;
+////@end MIDIConfigGui icon retrieval
+}
+
+
+
+
+/*
+ * wxEVT_COMMAND_BUTTON_CLICKED event handler for wxID_OK
+ */
+
+void MIDIConfigGui::OnOkClick( wxCommandEvent& event )
+{
+	// Store new selection and finish
+	SmartPtr<CTypeInt> outDev= CTypeInt::CreateInstance();
+	outDev->setValue (m_choMidiOut->GetSelection());
+
+	IInputPin* devicePin= IComponent::FindInputPin(*m_midiConfigComponent, "out_device");
+	assert (devicePin);
+	devicePin->Send(outDev);
+
+	GetParent()->Close();
+	event.Skip(false);
+}
+
+
+/*
+ * wxEVT_COMMAND_BUTTON_CLICKED event handler for wxID_CANCEL
+ */
+
+void MIDIConfigGui::OnCancelClick( wxCommandEvent& event )
+{
+	GetParent()->Close();
+    event.Skip(false);
+}
+
+/*
+ * wxEVT_CLOSE_WINDOW event handler for ID_MIDICONFIGGUI
+ */
+
+void MIDIConfigGui::OnCloseWindow( wxCloseEvent& event )
+{
+////@begin wxEVT_CLOSE_WINDOW event handler for ID_MIDICONFIGGUI in MIDIConfigGui.
+    // Before editing this code, remove the block markers.
+    event.Skip();
+////@end wxEVT_CLOSE_WINDOW event handler for ID_MIDICONFIGGUI in MIDIConfigGui.
+}
+
+/*
+ * wxEVT_COMMAND_BUTTON_CLICKED event handler for ID_BUTTON_MIDI_TEST
+ */
+
+void MIDIConfigGui::OnButtonMidiTestClick( wxCommandEvent& event )
+{
+	event.Skip(false);
+
+	SmartPtr<IComponent> midiOut= getSpCoreRuntime()->CreateComponent ("midi_out", "mo", 0, NULL);
+	assert (midiOut.get());
+	if (midiOut.get()== NULL) return;
+
+	SmartPtr<CTypeMIDIMessage> msg= CTypeMIDIMessage::CreateInstance();
+	assert (msg.get());
+	if (msg.get()== NULL) return;
+
+	if (midiOut->Initialize()!= 0) {
+		wxMessageDialog dlg(this, _("Cannot open MIDI device. May be it is in use."), _("MIDI error"), wxOK | wxICON_ERROR);
+		dlg.ShowModal();
+		return;
+	}
+
+	// Play scale
+	for (unsigned char note= 40; note< 60; ++note) {
+		msg->SetNoteOn (0, note, 127);
+		IComponent::FindInputPin(*midiOut, "message")->Send(msg);
+		wxMilliSleep(100);
+		msg->SetNoteOff (0, note, 127);
+		IComponent::FindInputPin(*midiOut, "message")->Send(msg);
+	}
+
+	// Change instrument
+	msg->SetProgramChange (0, 16);
+	IComponent::FindInputPin(*midiOut, "message")->Send(msg);
+
+	// Play scale
+	for (unsigned char note= 40; note< 60; ++note) {
+		msg->SetNoteOn (0, note, 127);
+		IComponent::FindInputPin(*midiOut, "message")->Send(msg);
+		wxMilliSleep(100);
+		msg->SetNoteOff (0, note, 127);
+		IComponent::FindInputPin(*midiOut, "message")->Send(msg);
+	}
+
+	midiOut->Finish();
+}
+
+
+};
diff --git a/src/mod_midi/midiconfiggui.h b/src/mod_midi/midiconfiggui.h
new file mode 100755
index 0000000..8e35f56
--- /dev/null
+++ b/src/mod_midi/midiconfiggui.h
@@ -0,0 +1,127 @@
+/////////////////////////////////////////////////////////////////////////////
+// Name:        midiconfiggui.h
+// Purpose:     
+// Author:      C�sar Mauri Loba
+// Modified by: 
+// Created:     01/04/2011 18:13:37
+// RCS-ID:      
+// Copyright:   (C) 2011 Cesar Mauri Loba - CREA Software Systems
+// 
+//  This program is free software: you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation, either version 3 of the License, or
+//  (at your option) any later version.
+//
+//  This program is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with this program.  If not, see <http://www.gnu.org/licenses/>.     
+/////////////////////////////////////////////////////////////////////////////
+
+#ifndef _MIDICONFIGGUI_H_
+#define _MIDICONFIGGUI_H_
+
+
+/*!
+ * Includes
+ */
+#include "spcore/component.h"
+
+#include <wx/panel.h>
+
+////@begin includes
+////@end includes
+
+/*!
+ * Forward declarations
+ */
+
+////@begin forward declarations
+////@end forward declarations
+class wxChoice;
+
+namespace mod_midi {
+/*!
+ * Control identifiers
+ */
+
+////@begin control identifiers
+#define ID_MIDICONFIGGUI 10000
+#define ID_CHOICE_MIDI_OUT 10001
+#define ID_BUTTON_MIDI_TEST 10002
+#define SYMBOL_MIDICONFIGGUI_STYLE wxCAPTION|wxTAB_TRAVERSAL
+#define SYMBOL_MIDICONFIGGUI_TITLE _("MIDI Config")
+#define SYMBOL_MIDICONFIGGUI_IDNAME ID_MIDICONFIGGUI
+#define SYMBOL_MIDICONFIGGUI_SIZE wxSize(400, 300)
+#define SYMBOL_MIDICONFIGGUI_POSITION wxDefaultPosition
+////@end control identifiers
+
+
+/*!
+ * MIDIConfigGui class declaration
+ */
+
+class MIDIConfigGui: public wxPanel
+{    
+    DECLARE_DYNAMIC_CLASS( MIDIConfigGui )
+    DECLARE_EVENT_TABLE()
+
+public:
+    /// Constructors
+    MIDIConfigGui();
+    MIDIConfigGui( wxWindow* parent, wxWindowID id = SYMBOL_MIDICONFIGGUI_IDNAME, const wxPoint& pos = SYMBOL_MIDICONFIGGUI_POSITION, const wxSize& size = SYMBOL_MIDICONFIGGUI_SIZE, long style = SYMBOL_MIDICONFIGGUI_STYLE, const wxString& name = SYMBOL_MIDICONFIGGUI_TITLE);
+
+    /// Creation
+    bool Create( wxWindow* parent, wxWindowID id = SYMBOL_MIDICONFIGGUI_IDNAME, const wxPoint& pos = SYMBOL_MIDICONFIGGUI_POSITION, const wxSize& size = SYMBOL_MIDICONFIGGUI_SIZE, long style = SYMBOL_MIDICONFIGGUI_STYLE, const wxString& name = SYMBOL_MIDICONFIGGUI_TITLE);
+
+    /// Destructor
+    ~MIDIConfigGui();
+
+    /// Initialises member variables
+    void Init();
+
+    /// Creates the controls and sizers
+    void CreateControls();
+
+////@begin MIDIConfigGui event handler declarations
+
+    /// wxEVT_CLOSE_WINDOW event handler for ID_MIDICONFIGGUI
+    void OnCloseWindow( wxCloseEvent& event );
+
+    /// wxEVT_COMMAND_BUTTON_CLICKED event handler for ID_BUTTON_MIDI_TEST
+    void OnButtonMidiTestClick( wxCommandEvent& event );
+
+    /// wxEVT_COMMAND_BUTTON_CLICKED event handler for wxID_OK
+    void OnOkClick( wxCommandEvent& event );
+
+    /// wxEVT_COMMAND_BUTTON_CLICKED event handler for wxID_CANCEL
+    void OnCancelClick( wxCommandEvent& event );
+
+////@end MIDIConfigGui event handler declarations
+
+////@begin MIDIConfigGui member function declarations
+
+    /// Retrieves bitmap resources
+    wxBitmap GetBitmapResource( const wxString& name );
+
+    /// Retrieves icon resources
+    wxIcon GetIconResource( const wxString& name );
+////@end MIDIConfigGui member function declarations
+
+    /// Should we show tooltips?
+    static bool ShowToolTips();
+
+////@begin MIDIConfigGui member variables
+    wxChoice* m_choMidiOut;
+////@end MIDIConfigGui member variables
+
+	SmartPtr<spcore::IComponent> m_midiConfigComponent;
+};
+
+};
+
+#endif
+    // _MIDICONFIGGUI_H_
diff --git a/src/mod_midi/mod_midi.cpp b/src/mod_midi/mod_midi.cpp
new file mode 100644
index 0000000..d84b32f
--- /dev/null
+++ b/src/mod_midi/mod_midi.cpp
@@ -0,0 +1,382 @@
+/////////////////////////////////////////////////////////////////////////////
+// File:        mod_midi.cpp
+// Author:      Cesar Mauri Loba (cesar at crea-si dot com)
+// Copyright:   (C) 2011 Cesar Mauri Loba - CREA Software Systems
+//
+//  This program is free software: you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation, either version 3 of the License, or
+//  (at your option) any later version.
+//
+//  This program is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+/////////////////////////////////////////////////////////////////////////////
+
+#include "spcore/component.h"
+#include "spcore/module.h"
+#include "spcore/basictypes.h"
+#include "spcore/libimpexp.h"
+#include "spcore/pinimpl.h"
+#include "portmidi.h"
+#include "midiconfiggui.h"
+#include "mod_midi/midi_types.h"
+
+#include <string>
+#include <boost/static_assert.hpp>
+#include <boost/thread/mutex.hpp>
+
+BOOST_STATIC_ASSERT(sizeof(unsigned int) == sizeof(PmTimestamp));
+BOOST_STATIC_ASSERT(sizeof(unsigned int) == sizeof(PmMessage));
+
+using namespace spcore;
+using namespace std;
+
+namespace mod_midi {
+
+static boost::mutex g_portMidiMutex;
+
+/* ******************************************************************************
+	midi_config_gui component
+****************************************************************************** */
+class MidiConfigGui : public spcore::CComponentAdapter {
+public:
+	static const char* getTypeName() { return "midi_config_gui"; };
+	virtual const char* GetTypeName() const { return MidiConfigGui::getTypeName(); };
+
+	MidiConfigGui(const char * name, int argc, const char * argv[])
+	: CComponentAdapter(name, argc, argv)
+	{
+	}
+
+	virtual wxWindow* GetGUI(wxWindow * parent) {
+		return new MIDIConfigGui( parent );
+	}
+};
+
+typedef ComponentFactory<MidiConfigGui> MidiConfigGuiFactory;
+
+
+/* ******************************************************************************
+	midi_config component
+	This manages the midi subsystem configuration
+****************************************************************************** */
+
+class MidiConfig : public spcore::CComponentAdapter {
+
+private:
+	typedef struct {
+		const PmDeviceInfo* devInfo;
+		PmDeviceID id;
+	} DevInfo;
+
+public:
+	static const char* getTypeName() { return "midi_config"; };
+	virtual const char* GetTypeName() const { return MidiConfig::getTypeName(); };
+
+	MidiConfig(const char * name, int argc, const char * argv[])
+	: CComponentAdapter(name, argc, argv)
+	, m_outDevice(0)
+	{
+		// mutex not needed
+
+		// Initialize portmidi subsystem
+		PmError errVal= Pm_Initialize();
+		if (errVal!= pmNoError)
+			throw std::runtime_error("midi_config. portmidi initialization failed");
+
+		// Counts the number of devices
+		int numDevices= Pm_CountDevices( );
+
+		// Store output devices
+		for (int i= 0; i< numDevices; ++i) {
+			DevInfo devInfo;
+
+			devInfo.devInfo= Pm_GetDeviceInfo( i );
+			assert (devInfo.devInfo);
+			if (devInfo.devInfo->output) {
+				devInfo.id= i;
+				m_outDevices.push_back(devInfo);
+				if (i == Pm_GetDefaultOutputDeviceID())
+					// Is this the default device? Otherwise the default is 0
+					m_outDevice= m_outDevices.size() - 1;
+			}
+		}
+
+		// Check if is any output device available
+		if (m_outDevices.size() == 0)
+			getSpCoreRuntime()->LogMessage (ICoreRuntime::LOG_WARNING, "no output midi devices found", "mod_midi");
+
+		RegisterInputPin (*SmartPtr<InputPinOutDevice>(new InputPinOutDevice(*this), false));
+		RegisterInputPin (*SmartPtr<InputPinReqStatus>(new InputPinReqStatus(*this), false));
+
+		m_oPinDevList= CTypeComposite::CreateOutputPinLock("device_list");
+		if (m_oPinDevList.get()== NULL)
+			// Output pin creation failed. Shouldn't happen but...
+			throw std::runtime_error("midi_config. output pin creation failed.");
+		RegisterOutputPin (*m_oPinDevList);
+	}
+
+	// returns pmNoDevice if no device available
+	PmDeviceID GetOutDevice() const {
+		if (m_outDevices.size() == 0) {
+			getSpCoreRuntime()->LogMessage (ICoreRuntime::LOG_WARNING, "no output midi devices found", "mod_midi");
+			return pmNoDevice;
+		}
+		else if ((unsigned int) m_outDevice>= m_outDevices.size()) {
+			getSpCoreRuntime()->LogMessage (ICoreRuntime::LOG_WARNING, "wrong output MIDI device", "mod_midi");
+			return pmNoDevice;
+		}
+
+		return m_outDevices[m_outDevice].id;
+	}
+
+	#define OUT_DEVICE_SETTING_NAME "out_device"
+
+	virtual void SaveSettings(IConfiguration& cfg) {
+		assert (getSpCoreRuntime()->IsMainThread());
+		cfg.WriteInt(OUT_DEVICE_SETTING_NAME, m_outDevice);
+	}
+
+	virtual void LoadSettings(IConfiguration& cfg) {
+		assert (getSpCoreRuntime()->IsMainThread());
+		int outDev= 0;
+		if (cfg.ReadInt(OUT_DEVICE_SETTING_NAME, &outDev)) {
+			if ((unsigned) outDev< m_outDevices.size()) m_outDevice= outDev;
+		}
+	}
+
+private:
+	virtual ~MidiConfig()
+	{
+		// portmidi cleanup
+		Pm_Terminate();
+	}
+
+	void SendStatus()
+	{
+		SmartPtr<CTypeComposite> result= CTypeComposite::CreateInstance();
+
+		for (unsigned int i= 0; i< m_outDevices.size(); ++i) {
+			SmartPtr<CTypeString> name= CTypeString::CreateInstance();
+			name->setValue(m_outDevices[i].devInfo->name);
+			result->AddChild(name);
+		}
+
+		m_oPinDevList->Send(result);
+	}
+
+	//
+	// Attributes
+	//
+	int m_outDevice;
+	vector<DevInfo> m_outDevices;
+	SmartPtr<spcore::IOutputPin> m_oPinDevList;
+
+	// Read/Write pin to send/read selected MIDI output device
+	class InputPinOutDevice : public CInputPinReadWrite<CTypeInt, MidiConfig> {
+	public:
+		InputPinOutDevice (MidiConfig & component)
+		: CInputPinReadWrite<CTypeInt, MidiConfig>("out_device", component) {}
+
+		virtual SmartPtr<CTypeInt> DoRead() const {
+			SmartPtr<CTypeInt> result= CTypeInt::CreateInstance();
+			result->setValue(m_component->m_outDevice);
+			return result;
+		}
+		virtual int DoSend(const CTypeInt &src) {
+			// Sanity check
+			if ((unsigned) src.getValue()>= m_component->m_outDevices.size()) return -1;
+
+			// Simply change the selected device
+			m_component->m_outDevice= src.getValue();
+
+			return 0;
+		}
+	};
+
+	// Write pin to request send/read selected MIDI output device
+	class InputPinReqStatus : public CInputPinWriteOnly<CTypeAny, MidiConfig> {
+	public:
+		InputPinReqStatus (MidiConfig & component)
+		: CInputPinWriteOnly<CTypeAny, MidiConfig>("req_status", component) {}
+
+		virtual int DoSend(const CTypeAny &) {
+			m_component->SendStatus();
+			return 0;
+		}
+	};
+};
+
+// MidiConfig component factory
+typedef SingletonComponentFactory<MidiConfig> MidiConfigFactory;
+
+/** *****************************************************************************
+	midi_out component
+
+	Input pins:
+		message (midi_message): input message to be executed
+
+		all_off (any): stop all notes
+****************************************************************************** */
+class MidiOut : public spcore::CComponentAdapter {
+public:
+	static const char* getTypeName() { return "midi_out"; };
+	virtual const char* GetTypeName() const { return MidiOut::getTypeName(); };
+
+	MidiOut(const char * name, int argc, const char * argv[])
+	: CComponentAdapter(name, argc, argv)
+	, m_stream(NULL)
+	{
+		RegisterInputPin (*SmartPtr<InputPinMessage>(new InputPinMessage(*this), false));
+		RegisterInputPin (*SmartPtr<InputPinAllOff>(new InputPinAllOff(*this), false));
+	}
+
+	virtual int DoInitialize() {
+		boost::mutex::scoped_lock lock(g_portMidiMutex);
+
+		if (m_stream)
+			// Already initialized
+			return 0;
+
+		// Obtain midi device to use
+		SmartPtr<IComponent> midiConfig= getSpCoreRuntime()->CreateComponent("midi_config", "mc", 0, NULL);
+
+		PmDeviceID outDevID= (static_cast<MidiConfig *>(midiConfig.get()))->GetOutDevice();
+
+		// Try to open device
+		PmError retcode= Pm_OpenOutput( &m_stream, outDevID,  NULL, 0, NULL, NULL, 0);
+
+		if (retcode!= pmNoError) {
+			// An error occurred
+			m_stream= NULL;
+			getSpCoreRuntime()->LogMessage (ICoreRuntime::LOG_ERROR, Pm_GetErrorText( retcode ), "mod_midi");
+			return -1;
+		}
+
+		// Device successfully opened
+		return 0;
+	}
+
+	virtual void DoFinish() {
+		boost::mutex::scoped_lock lock(g_portMidiMutex);
+		if (m_stream) {
+			// Stop sound
+			AllNotesOff ();
+			// Close device
+			Pm_Close (m_stream);
+			m_stream= NULL;
+		}
+	}
+
+	virtual void DoStop() {
+		boost::mutex::scoped_lock lock(g_portMidiMutex);
+		if (m_stream) {
+			// Stop sound
+			AllNotesOff ();			
+		}
+	}
+private:
+	//
+	// Attributes
+	//
+	PortMidiStream*	m_stream;
+
+	virtual ~MidiOut() {
+		Finish();
+	}
+
+	void ProcessMIDIMessage (const CTypeMIDIMessage & msg) {
+		boost::mutex::scoped_lock lock(g_portMidiMutex);
+		assert (m_stream);
+		if (m_stream) {
+			PmEvent evt;
+
+			evt.message= msg.GetBuffer();
+			evt.timestamp= 0;
+
+			Pm_Write(m_stream, &evt, 1);
+		}
+	}
+
+	void AllNotesOff () {
+		assert (m_stream);
+		if (m_stream) {
+			PmEvent buffer[32];
+			int i= 0, channel= 0;
+			for (; channel < 16; ++channel) {
+				buffer[i].message = Pm_Message(0xB0+channel, 0x78, 0);
+				buffer[i++].timestamp = 0;
+				buffer[i].message = Pm_Message(0xB0+channel, 0x7B, 0);
+				buffer[i++].timestamp = 0;
+			}
+			Pm_Write(m_stream, buffer, 32);
+		}
+	}
+
+	// Write pin which receives and executes MIDI messages
+	class InputPinMessage : public CInputPinWriteOnly<CTypeMIDIMessage, MidiOut> {
+	public:
+		InputPinMessage (MidiOut & component)
+		: CInputPinWriteOnly<CTypeMIDIMessage, MidiOut>("message", component) {}
+
+		virtual int DoSend(const CTypeMIDIMessage & msg) {
+			m_component->ProcessMIDIMessage (msg);
+			return 0;
+		}
+	};
+
+	// Write pin which turns all notes off
+	class InputPinAllOff : public CInputPinWriteOnly<CTypeAny, MidiOut> {
+	public:
+		InputPinAllOff (MidiOut & component)
+		: CInputPinWriteOnly<CTypeAny, MidiOut>("all_off", component) {}
+
+		virtual int DoSend(const CTypeAny &) {
+			boost::mutex::scoped_lock lock(g_portMidiMutex);
+			m_component->AllNotesOff ();
+			return 0;
+		}
+	};
+};
+
+typedef ComponentFactory<MidiOut> MidiOutFactory;
+
+/* ******************************************************************************
+	midi types factories
+****************************************************************************** */
+typedef spcore::SimpleTypeFactory<CTypeMIDIMessage> CTypeMIDIMessageFactory;
+
+/* ******************************************************************************
+	midi  module
+****************************************************************************** */
+class MidiModule : public CModuleAdapter {
+public:
+	MidiModule() {
+		//
+		// types
+		//
+		RegisterTypeFactory(SmartPtr<spcore::ITypeFactory>(new CTypeMIDIMessageFactory(), false));
+
+		//
+		// components
+		//
+		RegisterComponentFactory(SmartPtr<spcore::IComponentFactory>(new MidiConfigFactory(), false));
+		RegisterComponentFactory(SmartPtr<spcore::IComponentFactory>(new MidiConfigGuiFactory(), false));
+		RegisterComponentFactory(SmartPtr<spcore::IComponentFactory>(new MidiOutFactory(), false));
+	}
+	virtual const char * GetName() const { return "mod_midi"; }
+};
+
+static MidiModule* g_module= NULL;
+SPEXPORT_FUNCTION spcore::IModule* module_create_instance()
+{
+	if (g_module== NULL) g_module= new MidiModule();
+	return g_module;
+}
+
+};
diff --git a/src/mod_midi/tests/CMakeLists.txt b/src/mod_midi/tests/CMakeLists.txt
new file mode 100755
index 0000000..19febce
--- /dev/null
+++ b/src/mod_midi/tests/CMakeLists.txt
@@ -0,0 +1,11 @@
+cmake_minimum_required(VERSION 2.8)
+project(test_mod_midi)
+
+add_executable(test_mod_midi_config_gui test_mod_midi_config_gui.cpp)
+target_link_libraries(test_mod_midi_config_gui spcore)
+target_link_libraries(test_mod_midi_config_gui sphost)
+target_link_libraries(test_mod_midi_config_gui nvwa)
+#target_link_libraries(test_mod_midi_config_gui mod_wiimotes)
+target_link_libraries(test_mod_midi_config_gui ${wxWidgets_LIBRARIES})
+add_test (NAME test_mod_midi_config_gui COMMAND $<TARGET_FILE:nvwa_loader> $<TARGET_FILE:test_mod_midi_config_gui>)
+
diff --git a/src/mod_midi/tests/test_mod_midi_config_gui.cpp b/src/mod_midi/tests/test_mod_midi_config_gui.cpp
new file mode 100644
index 0000000..75e91e9
--- /dev/null
+++ b/src/mod_midi/tests/test_mod_midi_config_gui.cpp
@@ -0,0 +1,214 @@
+/////////////////////////////////////////////////////////////////////////////
+// Name:        test_mod_midi_config_gui.cpp
+// Author:      Cesar Mauri Loba
+// Copyright:   (C) 2011 Cesar Mauri Loba - CREA Software Systems
+//
+//  This program is free software: you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation, either version 3 of the License, or
+//  (at your option) any later version.
+//
+//  This program is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+/////////////////////////////////////////////////////////////////////////////
+
+#include "spcore/coreruntime.h"
+#include "sphost/testcommon.h"
+#include "nvwa/debug_new.h"
+#include "spcore/basictypes.h"
+#include "mod_midi/midi_types.h"
+
+#if defined(__WXGTK__) || defined(__WXMOTIF__) || defined(__WXX11__)
+	// Include Xlib for latter use on main
+	#include <X11/Xlib.h>
+#endif
+
+//#include <wx/msgdlg.h>
+#include <wx/frame.h>
+#include <wx/panel.h>
+#include <wx/sizer.h>
+#include <stdio.h>
+//#include <wx/init.h>
+#include <wx/button.h>
+#include <wx/dialog.h>
+
+using namespace spcore;
+using namespace mod_midi;
+
+/*
+	Check threads enabled
+*/
+#if !wxUSE_THREADS
+     #error "This program requires thread support."
+#endif // wxUSE_THREADS
+
+
+/*
+	dialogue to held the config dialogue
+*/
+class ConfigDialog : public wxDialog
+{
+public:
+	ConfigDialog(wxWindow* parent) {
+		Create (parent, wxID_ANY, _T(""));
+		m_midi_gui= getSpCoreRuntime()->CreateComponent("midi_config_gui","mcg", 0, NULL);
+		if (m_midi_gui.get()== NULL) ExitErr("cannot create midi_config_gui");
+
+		// Request panel
+		wxWindow* panel= m_midi_gui->GetGUI(this);
+
+		wxBoxSizer* sizer= new wxBoxSizer(wxVERTICAL);
+		SetSizer(sizer);
+		sizer->Add (panel, 0, wxALIGN_CENTER_HORIZONTAL|wxALL, 0);
+		GetSizer()->SetSizeHints(this);
+		SetTitle (panel->GetName());
+		Layout();
+		Fit();
+	}
+private:
+	SmartPtr<IComponent> m_midi_gui;
+
+	//DECLARE_EVENT_TABLE()
+};
+
+/*
+	ConfigFrame event table
+
+BEGIN_EVENT_TABLE(ConfigDialog, wxDialog)
+//	EVT_CLOSE	( ConfigDialog::OnCloseWindow )
+//	EVT_SIZE	( ConfigDialog::OnSize )
+END_EVENT_TABLE()
+*/
+
+/*
+	main frame class
+*/
+class MyFrame : public wxFrame
+{
+public:
+    MyFrame();
+	~MyFrame() {
+	}
+
+private:
+	void OnTestButton( wxCommandEvent& event );
+	void OnConfigButton( wxCommandEvent& event );
+
+    // any class wishing to process wxWidgets events must use this macro
+    DECLARE_EVENT_TABLE()
+};
+
+#define ID_TEST_BUTTON 10020
+#define ID_CONFIG_BUTTON 10021
+
+/*
+	myframe event table
+*/
+BEGIN_EVENT_TABLE(MyFrame, wxFrame)
+	EVT_BUTTON	( ID_TEST_BUTTON, MyFrame::OnTestButton )
+	EVT_BUTTON	( ID_CONFIG_BUTTON, MyFrame::OnConfigButton )
+END_EVENT_TABLE()
+
+
+// ----------------------------------------------------------------------------
+// main frame
+// ----------------------------------------------------------------------------
+MyFrame::MyFrame()
+: wxFrame(NULL, wxID_ANY, _T(""), wxDefaultPosition, wxDefaultSize, wxCAPTION|wxSYSTEM_MENU|wxCLOSE_BOX)
+{
+	wxBoxSizer* sizer= new wxBoxSizer(wxHORIZONTAL);
+	SetSizer(sizer);
+	wxButton* itemButtonTest= new wxButton( this, ID_TEST_BUTTON , _T("Test"), wxDefaultPosition, wxDefaultSize, 0 );
+	sizer->Add(itemButtonTest, 0, wxALIGN_CENTER_VERTICAL|wxALL, 0);
+	wxButton* itemButtonConfig= new wxButton( this, ID_CONFIG_BUTTON , _T("Config"), wxDefaultPosition, wxDefaultSize, 0 );
+	sizer->Add(itemButtonConfig, 0, wxALIGN_CENTER_VERTICAL|wxALL, 0);
+	GetSizer()->SetSizeHints(this);
+}
+
+void MyFrame::OnTestButton( wxCommandEvent& )
+{
+	SmartPtr<IComponent> midiOut= getSpCoreRuntime()->CreateComponent ("midi_out", "mo", 0, NULL);
+	if (midiOut.get()== NULL) ExitErr("error creating component mod_out");
+
+	SmartPtr<CTypeMIDIMessage> msg= CTypeMIDIMessage::CreateInstance();
+	if (msg.get()== NULL) ExitErr("cannot create midi message");
+
+	if (midiOut->Initialize()!= 0) ExitErr("error initializing midi_out component");
+
+	// Play scale
+	for (unsigned char note= 40; note< 60; ++note) {
+		msg->SetNoteOn (0, note, 127);
+		IComponent::FindInputPin(*midiOut, "message")->Send(msg);
+		sleep_milliseconds(100);
+		msg->SetNoteOff (0, note, 127);
+		IComponent::FindInputPin(*midiOut, "message")->Send(msg);
+	}
+
+	// Change instrument
+	msg->SetProgramChange (0, 16);
+	IComponent::FindInputPin(*midiOut, "message")->Send(msg);
+
+	// Play scale
+	for (unsigned char note= 40; note< 60; ++note) {
+		msg->SetNoteOn (0, note, 127);
+		IComponent::FindInputPin(*midiOut, "message")->Send(msg);
+		sleep_milliseconds(100);
+		msg->SetNoteOff (0, note, 127);
+		IComponent::FindInputPin(*midiOut, "message")->Send(msg);
+	}
+
+	midiOut->Finish();
+}
+
+void MyFrame::OnConfigButton( wxCommandEvent& )
+{
+	ConfigDialog cfgDlg(this);
+
+	cfgDlg.ShowModal();
+}
+
+// ----------------------------------------------------------------------------
+// main
+// ----------------------------------------------------------------------------
+
+int main(int argc, char *argv[]) {
+
+#if defined(__WXGTK__) || defined(__WXMOTIF__) || defined(__WXX11__)
+	// Under X11 it's necessary enable threading support
+	if ( XInitThreads() == 0 ) {
+		ExitErr("Unable to initialize multithreaded X11 code (XInitThreads failed)");
+		exit( EXIT_FAILURE );
+	}
+#endif
+
+	// Initialize spcore
+	ICoreRuntime* cr= getSpCoreRuntime();
+	if (!cr) return false;
+
+	// Load module
+	if (cr->LoadModule("mod_midi")!= 0)
+		ExitErr("error loading mod_midi");
+
+	if (cr->InitGUISupport (argc, argv))
+		ExitErr("wxEntryStart failed");
+
+	MyFrame* mf= new MyFrame();
+	mf->Show();
+
+	// Run wxWidgets message pump
+	cr->RunMessageLoop ();
+
+	// GUI cleanup
+	cr->CleanupGUISupport();
+
+	// Free spcore
+	freeSpCoreRuntime();
+
+	// If execution reaches this => all tests ok
+	return 0;
+}
diff --git a/src/mod_score_player/CMakeLists.txt b/src/mod_score_player/CMakeLists.txt
new file mode 100755
index 0000000..4181e0c
--- /dev/null
+++ b/src/mod_score_player/CMakeLists.txt
@@ -0,0 +1,16 @@
+cmake_minimum_required(VERSION 2.6)
+project(mod_score_player)
+
+set(mod_score_player_SRCS
+	mod_score_player.cpp
+	scoreplayer.h
+	scoreplayer.cpp
+	instrselect.h
+	instrselect.cpp
+)
+
+add_library (mod_score_player MODULE ${mod_score_player_SRCS})
+target_link_libraries(mod_score_player spcore)
+target_link_libraries(mod_score_player ${Boost_THREAD_LIBRARY})
+
+INSTALL (TARGETS mod_score_player RUNTIME DESTINATION ${LIBRUNTIMEDIR} LIBRARY DESTINATION ${PLUGINDIR} COMPONENT "sitplus")
\ No newline at end of file
diff --git a/src/mod_score_player/instrselect.cpp b/src/mod_score_player/instrselect.cpp
new file mode 100644
index 0000000..e3bb96b
--- /dev/null
+++ b/src/mod_score_player/instrselect.cpp
@@ -0,0 +1,311 @@
+/////////////////////////////////////////////////////////////////////////////
+// Name:
+// Purpose:		instrselect.cpp
+// Author:      Cesar Mauri Loba (cesar at crea-si dot com)
+// Modified by:
+// Created:
+// Copyright:   (C) 2010-11 Cesar Mauri Loba - CREA Software Systems
+//
+//  This program is free software: you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation, either version 3 of the License, or
+//  (at your option) any later version.
+//
+//  This program is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+/////////////////////////////////////////////////////////////////////////////
+
+#include "instrselect.h"
+#include "spcore/language.h"
+#include "spcore/conversion.h"
+
+#include <boost/tokenizer.hpp>
+#include <boost/foreach.hpp>
+#include <boost/lexical_cast.hpp>
+
+using namespace spcore;
+using namespace boost;
+using namespace std;
+
+namespace mod_score_player {
+
+static const char* g_instruments[]= {
+	N__("Acoustic Grand Piano"),
+	N__("Bright Acoustic Piano"),
+	N__("Electric Grand Piano"),
+	N__("Honky-Tonk"),
+	N__("Electric Piano 1"),
+	N__("Electric Piano 2"),
+	N__("Harpsichord"),
+	N__("Clavinet"),
+	N__("Celesta"),
+	N__("Glockenspiel"),
+	N__("Music Box"),
+	N__("Vibraphone"),
+	N__("Marimba"),
+	N__("Xylophone"),
+	N__("Tubular Bells"),
+	N__("Dulcimer"),
+	N__("Drawbar Organ"),
+	N__("Percussive Organ"),
+	N__("Rock Organ"),
+	N__("Church Organ"),
+	N__("Reed Organ"),
+	N__("Accordion"),
+	N__("Harmonica"),
+	N__("Tango Accordion"),
+	N__("Nylon String Guitar"),
+	N__("Steel String Guitar"),
+	N__("Electric Jazz Guitar"),
+	N__("Electric Clean Guitar"),
+	N__("Electric Muted Guitar"),
+	N__("Overdriven Guitar"),
+	N__("Distortion Guitar"),
+	N__("Guitar Harmonics"),
+	N__("Acoustic Bass"),
+	N__("Electric Bass(finger)"),
+	N__("Electric Bass(pick)"),
+	N__("Fretless Bass"),
+	N__("Slap Bass 1"),
+	N__("Slap Bass 2"),
+	N__("Synth Bass 1"),
+	N__("Synth Bass 2"),
+	N__("Violin"),
+	N__("Viola"),
+	N__("Cello"),
+	N__("Contrabass"),
+	N__("Tremolo Strings"),
+	N__("Pizzicato Strings"),
+	N__("Orchestral Strings"),
+	N__("Timpani"),
+	N__("String Ensemble 1"),
+	N__("String Ensemble 2"),
+	N__("SynthStrings 1"),
+	N__("SynthStrings 2"),
+	N__("Choir Aahs"),
+	N__("Voice Oohs"),
+	N__("Synth Voice"),
+	N__("Orchestra Hit"),
+	N__("Trumpet"),
+	N__("Trombone"),
+	N__("Tuba"),
+	N__("Muted Trumpet"),
+	N__("French Horn"),
+	N__("Brass Section"),
+	N__("SynthBrass 1"),
+	N__("SynthBrass 2"),
+	N__("Soprano Sax"),
+	N__("Alto Sax"),
+	N__("Tenor Sax"),
+	N__("Baritone Sax"),
+	N__("Oboe"),
+	N__("English Horn"),
+	N__("Bassoon"),
+	N__("Clarinet"),
+	N__("Piccolo"),
+	N__("Flute"),
+	N__("Recorder"),
+	N__("Pan Flute"),
+	N__("Blown Bottle"),
+	N__("Shakuhachi"),
+	N__("Whistle"),
+	N__("Ocarina"),
+	N__("Square Wave"),
+	N__("Saw Wave"),
+	N__("Syn. Calliope"),
+	N__("Chiffer Lead"),
+	N__("Charang"),
+	N__("Solo Vox"),
+	N__("5th Saw Wave"),
+	N__("Bass& Lead"),
+	N__("Fantasia"),
+	N__("Warm Pad"),
+	N__("Polysynth"),
+	N__("Space Voice"),
+	N__("Bowed Glass"),
+	N__("Metal Pad"),
+	N__("Halo Pad"),
+	N__("Sweep Pad"),
+	N__("Ice Rain"),
+	N__("Soundtrack"),
+	N__("Crystal"),
+	N__("Atmosphere"),
+	N__("Brightness"),
+	N__("Goblin"),
+	N__("Echo Drops"),
+	N__("Star Theme"),
+	N__("Sitar"),
+	N__("Banjo"),
+	N__("Shamisen"),
+	N__("Koto"),
+	N__("Kalimba"),
+	N__("Bagpipe"),
+	N__("Fiddle"),
+	N__("Shanai"),
+	N__("Tinkle Bell"),
+	N__("Agogo"),
+	N__("Steel Drums"),
+	N__("Woodblock"),
+	N__("Taiko Drum"),
+	N__("Melodic Tom"),
+	N__("Synth Drum"),
+	N__("Reverse Cymbal"),
+	N__("Guitar Fret Noise"),
+	N__("Breath Noise"),
+	N__("Seashore"),
+	N__("Bird Tweet"),
+	N__("Telephone Ring"),
+	N__("Helicopter"),
+	N__("Applause"),
+	N__("Gunshot")
+};
+
+static const unsigned int g_instruments_size= sizeof(g_instruments) / sizeof(g_instruments[0]);
+
+InstrumentSelectorComponent::InstrumentSelectorComponent(const char * name, int argc, const char * argv[])
+: CComponentAdapter(name, argc, argv)
+, m_instrIdx(0)	
+{
+	//
+	// Pins
+	//
+	RegisterInputPin (*SmartPtr<IInputPin>(new InputPinInstrument(*this), false));
+
+	m_oPinInstruments= CTypeComposite::CreateOutputPin("instruments");
+	m_oPinName= CTypeString::CreateOutputPin("name");
+	m_oPinMIDINumber= CTypeInt::CreateOutputPin("midi_number");
+
+	RegisterOutputPin (*m_oPinInstruments);
+	RegisterOutputPin (*m_oPinName);
+	RegisterOutputPin (*m_oPinMIDINumber);
+
+	// 
+	// Parse arguments
+	//
+	bool appendNumber= false;
+	if (argc) {
+		// Seach -n option
+		for (int i= 0; i< argc; ++i) {
+			if (argv[i] && strcmp ("-n", argv[i])== 0) {
+				// Append numbers
+				appendNumber= true;
+				break;
+			}
+		}
+
+		// Process remaining options
+		for (int i= 0; i< argc; ++i) {
+			if (argv[i] && strcmp ("-s", argv[i])== 0) {
+				// Instrument set
+				m_instrumentSet.clear();
+
+				bool err= false;
+				
+				++i;
+				if (i< argc && argv[i]) {
+					// Parse instrument list
+					char_separator<char> sep(", ");
+					string str(argv[i]);
+					tokenizer<char_separator<char> > tokens(str, sep);
+					BOOST_FOREACH(string t, tokens)	{
+						unsigned int instrNum;
+						if (!StrToUint(t.c_str(), &instrNum) || instrNum< 1 || instrNum> g_instruments_size) {
+							err= true;
+							break;
+						}
+						else
+							AddInstrumentToSet(instrNum - 1, appendNumber);
+					}
+				}
+				else err= true;
+				if (err) throw std::runtime_error("instrument_selector. Wrong value for option -s");
+			}
+			else if (argv[i] && strcmp ("-n", argv[i])== 0) {
+				// Append numbers
+
+				// ... already done
+			}
+			else if (argv[i] && strlen(argv[i])) {
+				string error_msg("instrument_selector. Unknown option:");
+				error_msg+= argv[i];
+				throw std::runtime_error(error_msg);
+			}
+		}
+	}
+
+	// Empty instrument set?
+	if (m_instrumentSet.empty())
+		// Add the full set
+		for (unsigned int i= 0; i< g_instruments_size; ++i)
+			AddInstrumentToSet(i, appendNumber);
+}
+
+void InstrumentSelectorComponent::AddInstrumentToSet(unsigned int num, bool appendNum)
+{
+	assert (num< 128);
+
+	struct Name_MIDINum nn;
+	nn.number= (unsigned char) num;
+	if (appendNum) {
+		nn.name+= boost::lexical_cast<std::string>(num+1);
+		nn.name+= "-";
+	}
+	nn.name+= __(g_instruments[num]);
+	m_instrumentSet.push_back(nn);
+}
+
+int InstrumentSelectorComponent::DoInitialize()
+{
+	assert (m_instrIdx< m_instrumentSet.size());
+
+	//
+	// Instruments
+	//
+	SmartPtr<CTypeComposite> instruments= CTypeComposite::CreateInstance();
+	vector<Name_MIDINum>::const_iterator it= m_instrumentSet.begin();
+	for (; it!= m_instrumentSet.end(); ++it) {
+		SmartPtr<CTypeString> instrument_name= CTypeString::CreateInstance();
+		instrument_name->setValue(it->name.c_str());
+		instruments->AddChild(instrument_name);
+	}
+	m_oPinInstruments->Send(instruments);
+
+	//
+	// Selected instrument
+	//
+	SendNameAndMIDINumber();
+
+	return 0;
+}
+
+void InstrumentSelectorComponent::SendNameAndMIDINumber()
+{
+	// Name
+	SmartPtr<CTypeString> name= CTypeString::CreateInstance();
+	name->setValue(m_instrumentSet[m_instrIdx].name.c_str());
+	m_oPinName->Send(name);
+
+	// MIDI number (0..127)
+	SmartPtr<CTypeInt> number= CTypeInt::CreateInstance();
+	number->setValue(m_instrumentSet[m_instrIdx].number);
+	m_oPinMIDINumber->Send(number);
+}
+
+void InstrumentSelectorComponent::OnPinInstrument (const CTypeInt & msg)
+{
+	unsigned char newInstr= (unsigned char) msg.getValue();
+
+	if (newInstr<= m_instrumentSet.size() && newInstr!= m_instrIdx) {
+		m_instrIdx= newInstr;
+
+		SendNameAndMIDINumber();
+	}
+}
+
+
+};	// namespace end
diff --git a/src/mod_score_player/instrselect.h b/src/mod_score_player/instrselect.h
new file mode 100755
index 0000000..35ff61a
--- /dev/null
+++ b/src/mod_score_player/instrselect.h
@@ -0,0 +1,108 @@
+/////////////////////////////////////////////////////////////////////////////
+// Name:       instrselect.h
+// Purpose:
+// Author:      Cesar Mauri Loba (cesar at crea-si dot com)
+// Modified by:
+// Created:     26/05/2010 11:05:03
+// Copyright:   (C) 2010-11 Cesar Mauri Loba - CREA Software Systems
+//
+//  This program is free software: you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation, either version 3 of the License, or
+//  (at your option) any later version.
+//
+//  This program is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+/////////////////////////////////////////////////////////////////////////////
+#ifndef INSTRSELECTOR_H
+#define INSTRSELECTOR_H
+
+#include "spcore/component.h"
+#include "spcore/pinimpl.h"
+#include "spcore/basictypes.h"
+
+namespace mod_score_player {
+
+/** *****************************************************************************
+	Component: instrument_selector
+
+	Input pins:
+		instrument (int)
+			Selects the instrument by its number (starting at 0). 
+			If no instrument set is given by command line the full general MIDI 
+			is available 
+			
+	Output pins:
+		instruments (any)	List of instrument which are part of the set
+		name (string)		Localized name of the selected instrument
+		midi_number	(int)	MIDI number of the selected instrument
+
+	Command line:
+		[-s <list> ]	
+			List of instruments numbers to include in the set (range 1..128). 
+			If this parameter is not provided the full set of instruments is available.
+		[-n ] 	Append the number of the instrument before its name
+****************************************************************************** */
+class InstrumentSelectorComponent : public spcore::CComponentAdapter {
+public:
+	static const char* getTypeName() { return "instrument_selector"; };
+	virtual const char* GetTypeName() const { return InstrumentSelectorComponent::getTypeName(); };
+
+	InstrumentSelectorComponent(const char * name, int argc, const char * argv[]);
+
+	virtual int DoInitialize();
+
+private:
+	//
+	// Private types
+	//
+	struct Name_MIDINum	{
+		unsigned char number;
+		std::string name;
+	};
+	
+	//
+	// Data members
+	//
+	unsigned char m_instrIdx;	
+	std::vector<struct Name_MIDINum> m_instrumentSet;
+	SmartPtr<spcore::IOutputPin> m_oPinInstruments;
+	SmartPtr<spcore::IOutputPin> m_oPinName;
+	SmartPtr<spcore::IOutputPin> m_oPinMIDINumber;
+	
+	//
+	// Private methods
+	//	
+	void OnPinInstrument (const spcore::CTypeInt & msg);
+
+	// Adds an instrument to the set givent its number (0..127)
+	void AddInstrumentToSet(unsigned int num, bool appendNum);
+
+	void SendNameAndMIDINumber();
+
+	//
+	// Input pin classes
+	//
+	class InputPinInstrument : public spcore::CInputPinWriteOnly<spcore::CTypeInt, InstrumentSelectorComponent> {
+	public:
+		InputPinInstrument (InstrumentSelectorComponent & component)
+		: spcore::CInputPinWriteOnly<spcore::CTypeInt, InstrumentSelectorComponent>("instrument", component) { }
+
+		virtual int DoSend(const spcore::CTypeInt & msg) {
+			m_component->OnPinInstrument(msg);
+			return 0;
+		}
+	};
+};
+
+typedef spcore::ComponentFactory<InstrumentSelectorComponent> InstrumentSelectorFactory;
+
+
+};
+
+#endif
diff --git a/src/mod_score_player/mod_score_player.cpp b/src/mod_score_player/mod_score_player.cpp
new file mode 100644
index 0000000..4bcb422
--- /dev/null
+++ b/src/mod_score_player/mod_score_player.cpp
@@ -0,0 +1,49 @@
+/////////////////////////////////////////////////////////////////////////////
+// File:        mod_score_player.cpp
+// Author:      Cesar Mauri Loba (cesar at crea-si dot com)
+// Copyright:   (C) 2011 Cesar Mauri Loba - CREA Software Systems
+// 
+//  This program is free software: you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation, either version 3 of the License, or
+//  (at your option) any later version.
+//
+//  This program is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+/////////////////////////////////////////////////////////////////////////////
+
+#include "spcore/libimpexp.h"
+#include "spcore/module.h"
+#include "scoreplayer.h"
+#include "instrselect.h"
+
+using namespace spcore;
+
+namespace mod_score_player {
+
+/* ******************************************************************************
+	score player module
+*/
+class ScorePlayerModule : public spcore::CModuleAdapter {
+public:
+	ScorePlayerModule() {
+		
+		RegisterComponentFactory(SmartPtr<spcore::IComponentFactory>(new ScorePlayerFactory(), false));
+		RegisterComponentFactory(SmartPtr<spcore::IComponentFactory>(new InstrumentSelectorFactory(), false));
+	}
+	virtual const char * GetName() const { return "mod_score_player"; }
+};
+
+static spcore::IModule* g_module= NULL;
+SPEXPORT_FUNCTION spcore::IModule* module_create_instance()
+{
+	if (g_module== NULL) g_module= new ScorePlayerModule();
+	return g_module;
+}
+
+};
\ No newline at end of file
diff --git a/src/mod_score_player/mod_score_player.pjd b/src/mod_score_player/mod_score_player.pjd
new file mode 100755
index 0000000..572fe97
--- /dev/null
+++ b/src/mod_score_player/mod_score_player.pjd
@@ -0,0 +1,960 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<anthemion-project version="1.0.0.0" xmlns="http://www.anthemion.co.uk">
+  <header>
+    <long name="name_counter">0</long>
+    <string name="html_path">""</string>
+    <string name="title">""</string>
+    <string name="author">""</string>
+    <string name="description">""</string>
+    <string name="xrc_filename">""</string>
+    <long name="image_mode">0</long>
+    <bool name="inline_images">0</bool>
+    <bool name="generate_cpp_for_xrc">0</bool>
+    <long name="working_mode">1</long>
+    <bool name="use_help_text_for_tooltips">1</bool>
+    <bool name="translate_strings">1</bool>
+    <bool name="make_unicode_strings">1</bool>
+    <bool name="extract_strings">0</bool>
+    <string name="user_name">"César Mauri Loba"</string>
+    <string name="copyright_string">"(C) 2009 Cesar Mauri from CREA Sistemes Informatics"</string>
+    <string name="resource_prefix">""</string>
+    <bool name="use_two_step_construction">1</bool>
+    <bool name="use_enums">0</bool>
+    <bool name="generate_for_xrced">0</bool>
+    <bool name="generate_virtual_eventhandlers">0</bool>
+    <string name="current_platform">"<All platforms>"</string>
+    <string name="target_wx_version">"2.8.7"</string>
+    <string name="app_kind">"Standard"</string>
+    <string name="cpp_header_comment">"/////////////////////////////////////////////////////////////////////////////
+// Name:        %HEADER-FILENAME%
+// Purpose:     
+// Author:      %AUTHOR%
+// Modified by: 
+// Created:     %DATE%
+// RCS-ID:      
+// Copyright:   %COPYRIGHT%
+// Licence:     
+/////////////////////////////////////////////////////////////////////////////
+
+"</string>
+    <string name="cpp_implementation_comment">"/////////////////////////////////////////////////////////////////////////////
+// Name:        %SOURCE-FILENAME%
+// Purpose:     
+// Author:      %AUTHOR%
+// Modified by: 
+// Created:     %DATE%
+// RCS-ID:      
+// Copyright:   %COPYRIGHT%
+// Licence:     
+/////////////////////////////////////////////////////////////////////////////
+
+"</string>
+    <string name="cpp_symbols_file_comment">"/////////////////////////////////////////////////////////////////////////////
+// Name:        %SYMBOLS-FILENAME%
+// Purpose:     Symbols file
+// Author:      %AUTHOR%
+// Modified by: 
+// Created:     %DATE%
+// RCS-ID:      
+// Copyright:   %COPYRIGHT%
+// Licence:     
+/////////////////////////////////////////////////////////////////////////////
+
+"</string>
+    <string name="cpp_header_preamble">""</string>
+    <string name="cpp_implementation_preamble">"// For compilers that support precompilation, includes "wx/wx.h".
+#include "wx/wxprec.h"
+
+#ifdef __BORLANDC__
+#pragma hdrstop
+#endif
+
+#ifndef WX_PRECOMP
+#include "wx/wx.h"
+#endif
+
+"</string>
+    <string name="cpp_function_declaration_comment">"	/// %BODY%
+"</string>
+    <string name="cpp_function_implementation_comment">"
+/*!
+ * %BODY%
+ */
+
+"</string>
+    <string name="resource_file_header">"app_resources.h"</string>
+    <string name="resource_file_implementation">"app_resources.cpp"</string>
+    <string name="resource_class_name">"AppResources"</string>
+    <string name="app_file_header">"app.h"</string>
+    <string name="app_file_implementation">"app.cpp"</string>
+    <string name="app_class_name">"Application"</string>
+    <bool name="generate_app_class">0</bool>
+    <string name="external_symbol_filenames">""</string>
+    <string name="configuration">"<None>"</string>
+    <string name="source_encoding">"iso-8859-1"</string>
+    <string name="xrc_encoding">"utf-8"</string>
+    <string name="project_encoding">"utf-8"</string>
+    <string name="resource_archive">""</string>
+    <long name="text_file_type">0</long>
+    <bool name="use_tabs">0</bool>
+    <long name="indent_size">4</long>
+    <string name="whitespace_after_return_type">" "</string>
+    <string name="resource_xrc_cpp">""</string>
+    <bool name="use_resource_archive">0</bool>
+    <bool name="use_generated_xrc_cpp">0</bool>
+    <bool name="always_generate_xrc">1</bool>
+    <bool name="use_id_name_for_name">0</bool>
+    <bool name="archive_xrc_files">1</bool>
+    <bool name="archive_image_files">1</bool>
+    <bool name="archive_all_image_files">0</bool>
+    <bool name="xrc_retain_relative_paths">1</bool>
+    <bool name="xrc_generate_id_tags">0</bool>
+    <bool name="xrc_use_name_property">0</bool>
+  </header>
+  <data>
+    <document>
+      <string name="title">""</string>
+      <string name="type">"data-document"</string>
+      <string name="filename">""</string>
+      <string name="icon-name">""</string>
+      <long name="is-transient">0</long>
+      <long name="owns-file">1</long>
+      <long name="title-mode">0</long>
+      <long name="locked">0</long>
+      <document>
+        <string name="title">"Configurations"</string>
+        <string name="type">"config-data-document"</string>
+        <string name="filename">""</string>
+        <string name="icon-name">""</string>
+        <long name="is-transient">0</long>
+        <long name="owns-file">1</long>
+        <long name="title-mode">0</long>
+        <long name="locked">0</long>
+        <string name="template-name">""</string>
+        <bool name="dirty">1</bool>
+        <long name="makefile-last-written">-8519680</long>
+        <string name="Compiler name">""</string>
+        <string name="Build mode">"Debug"</string>
+        <string name="Unicode mode">"ANSI"</string>
+        <string name="Shared mode">"Static"</string>
+        <string name="Modularity">"Modular"</string>
+        <string name="GUI mode">"GUI"</string>
+        <string name="Toolkit">"wxMSW"</string>
+        <string name="Processor type">"Default"</string>
+        <string name="Runtime linking">"Dynamic"</string>
+        <string name="Use exceptions">"Yes"</string>
+        <string name="Use ODBC">"No"</string>
+        <string name="Use XRC">"Yes"</string>
+        <string name="Use OpenGL">"No"</string>
+        <string name="Use wxMediaCtrl">"No"</string>
+        <string name="Use wxRichTextCtrl">"Yes"</string>
+        <string name="Use wxHTML">"Yes"</string>
+        <string name="Use wxPropertyGrid">"Yes"</string>
+        <string name="Use wxAUI">"Yes"</string>
+        <string name="Use wxSTC">"Yes"</string>
+        <string name="Use wxRibbonControl">"Yes"</string>
+        <string name="Executable name">"%EXECUTABLE%"</string>
+        <string name="Program arguments">""</string>
+        <string name="Working path">"%AUTO%"</string>
+        <string name="Output path">"%AUTO%"</string>
+        <string name="Objects path">"%AUTO%"</string>
+        <string name="Project makefile">"%AUTO%"</string>
+        <string name="wxWidgets version">"%WXVERSION%"</string>
+        <string name="wxWidgets makefile">"%AUTO%"</string>
+        <string name="wxWidgets location">"%AUTO%"</string>
+        <string name="wxWidgets build path">"%AUTO%"</string>
+        <string name="wxWidgets build command">"%AUTO%"</string>
+        <string name="wxWidgets clean command">"%AUTO%"</string>
+        <string name="CFG">""</string>
+        <string name="Compiler location">"%AUTO%"</string>
+        <string name="Compiler bin path">"%AUTO%"</string>
+        <string name="Compiler include path">"%AUTO%"</string>
+        <string name="Compiler lib path">"%AUTO%"</string>
+        <string name="PATH variable">"%AUTO%"</string>
+        <string name="C++ command">"%AUTO%"</string>
+        <string name="C command">"%AUTO%"</string>
+        <string name="Linker command">"%AUTO%"</string>
+        <string name="Resource compiler">"%AUTO%"</string>
+        <string name="Make command">"%AUTO%"</string>
+        <string name="Preprocessor flags">"%AUTO%"</string>
+        <string name="Optimizations">"%AUTO%"</string>
+        <string name="Warnings">"%AUTO%"</string>
+        <string name="Debug flags">"%AUTO%"</string>
+        <string name="Extra compile flags">"%AUTO%"</string>
+        <string name="Libraries">"%AUTO%"</string>
+        <string name="Library path">"%AUTO%"</string>
+        <string name="Linker flags">"%AUTO%"</string>
+        <string name="Include path">"%AUTO%"</string>
+        <string name="Resource flags">"%AUTO%"</string>
+        <string name="Resource path">"%AUTO%"</string>
+        <bool name="Suppress source rules">0</bool>
+        <bool name="Enable makefile generation">1</bool>
+      </document>
+    </document>
+  </data>
+
+  <documents>
+    <document>
+      <string name="title">"Projects"</string>
+      <string name="type">"root-document"</string>
+      <string name="filename">""</string>
+      <string name="icon-name">"project"</string>
+      <long name="is-transient">1</long>
+      <long name="owns-file">1</long>
+      <long name="title-mode">0</long>
+      <long name="locked">1</long>
+      <document>
+        <string name="title">"Windows"</string>
+        <string name="type">"html-document"</string>
+        <string name="filename">""</string>
+        <string name="icon-name">"dialogsfolder"</string>
+        <long name="is-transient">1</long>
+        <long name="owns-file">1</long>
+        <long name="title-mode">0</long>
+        <long name="locked">1</long>
+        <document>
+          <string name="title">"Virtual Instrument"</string>
+          <string name="type">"dialog-document"</string>
+          <string name="filename">""</string>
+          <string name="icon-name">"dialog"</string>
+          <long name="is-transient">0</long>
+          <long name="owns-file">1</long>
+          <long name="title-mode">0</long>
+          <long name="locked">0</long>
+          <string name="proxy-type">"wbDialogProxy"</string>
+          <long name="base-id">10000</long>
+          <bool name="use-id-prefix">0</bool>
+          <string name="id-prefix">""</string>
+          <bool name="use-id-suffix">0</bool>
+          <string name="id-suffix">""</string>
+          <string name="app-kind">"Standard"</string>
+          <long name="use-xrc">0</long>
+          <long name="working-mode">0</long>
+          <string name="proxy-Id name">"ID_SCORE_PLAYER_PANEL"</string>
+          <long name="proxy-Id value">10076</long>
+          <string name="proxy-Class">"ScorePlayerPanel"</string>
+          <string name="proxy-Base class">"wxPanel"</string>
+          <string name="proxy-Window kind">"wxPanel"</string>
+          <string name="proxy-Implementation filename">"scoreplayer.cpp"</string>
+          <string name="proxy-Header filename">"scoreplayer.h"</string>
+          <string name="proxy-XRC filename">""</string>
+          <string name="proxy-Title">"Score player"</string>
+          <bool name="proxy-Centre">1</bool>
+          <string name="proxy-Icon">""</string>
+          <bool name="proxy-Dialog units">0</bool>
+          <string name="proxy-Help text">""</string>
+          <string name="proxy-Tooltip text">""</string>
+          <string name="proxy-Background colour">""</string>
+          <string name="proxy-Foreground colour">""</string>
+          <string name="proxy-Font">""</string>
+          <bool name="proxy-Hidden">0</bool>
+          <bool name="proxy-Enabled">1</bool>
+          <string name="proxy-Platform">"<Any platform>"</string>
+          <string name="proxy-Data source">""</string>
+          <string name="proxy-Data class name">""</string>
+          <string name="proxy-Data class implementation filename">""</string>
+          <string name="proxy-Data class header filename">""</string>
+          <string name="proxy-Data class manager window">""</string>
+          <string name="proxy-Texture">""</string>
+          <string name="proxy-Texture style">"Tiled"</string>
+          <bool name="proxy-wxDEFAULT_DIALOG_STYLE">0</bool>
+          <bool name="proxy-wxCAPTION">0</bool>
+          <bool name="proxy-wxRESIZE_BORDER">0</bool>
+          <bool name="proxy-wxSYSTEM_MENU">0</bool>
+          <bool name="proxy-wxSTAY_ON_TOP">0</bool>
+          <bool name="proxy-wxDIALOG_NO_PARENT">0</bool>
+          <bool name="proxy-wxCLOSE_BOX">0</bool>
+          <bool name="proxy-wxMAXIMIZE_BOX">0</bool>
+          <bool name="proxy-wxMINIMIZE_BOX">0</bool>
+          <bool name="proxy-wxDIALOG_MODAL">0</bool>
+          <bool name="proxy-wxNO_BORDER">0</bool>
+          <bool name="proxy-wxSIMPLE_BORDER">0</bool>
+          <bool name="proxy-wxDOUBLE_BORDER">0</bool>
+          <bool name="proxy-wxBORDER_THEME">0</bool>
+          <bool name="proxy-wxSUNKEN_BORDER">0</bool>
+          <bool name="proxy-wxRAISED_BORDER">0</bool>
+          <bool name="proxy-wxSTATIC_BORDER">0</bool>
+          <bool name="proxy-wxWANTS_CHARS">0</bool>
+          <bool name="proxy-wxNO_FULL_REPAINT_ON_RESIZE">0</bool>
+          <bool name="proxy-wxFULL_REPAINT_ON_RESIZE">0</bool>
+          <bool name="proxy-wxCLIP_CHILDREN">0</bool>
+          <bool name="proxy-wxTAB_TRAVERSAL">0</bool>
+          <bool name="proxy-wxWS_EX_VALIDATE_RECURSIVELY">0</bool>
+          <bool name="proxy-wxWS_EX_BLOCK_EVENTS">0</bool>
+          <bool name="proxy-wxWS_EX_TRANSIENT">0</bool>
+          <string name="proxy-Custom styles">""</string>
+          <bool name="proxy-wxDIALOG_EX_CONTEXTHELP">0</bool>
+          <bool name="proxy-Fit to content">1</bool>
+          <long name="proxy-X">-1</long>
+          <long name="proxy-Y">-1</long>
+          <long name="proxy-Width">-1</long>
+          <long name="proxy-Height">-1</long>
+          <bool name="proxy-AUI manager">0</bool>
+          <string name="proxy-Event sources">""</string>
+          <document>
+            <string name="title">"wxGridBagSizer"</string>
+            <string name="type">"dialog-control-document"</string>
+            <string name="filename">""</string>
+            <string name="icon-name">"sizer"</string>
+            <long name="is-transient">0</long>
+            <long name="owns-file">1</long>
+            <long name="title-mode">0</long>
+            <long name="locked">0</long>
+            <string name="proxy-type">"wbGridBagSizerProxy"</string>
+            <string name="proxy-GrowableColumns">"0,1,2"</string>
+            <string name="proxy-GrowableRows">""</string>
+            <long name="proxy-ColumnSpacing">0</long>
+            <long name="proxy-RowSpacing">0</long>
+            <long name="proxy-Empty cell width">10</long>
+            <long name="proxy-Empty cell height">20</long>
+            <string name="proxy-Member variable name">""</string>
+            <string name="proxy-AlignH">"Expand"</string>
+            <string name="proxy-AlignV">"Centre"</string>
+            <long name="proxy-Stretch factor">0</long>
+            <long name="proxy-Border">5</long>
+            <bool name="proxy-wxLEFT">1</bool>
+            <bool name="proxy-wxRIGHT">1</bool>
+            <bool name="proxy-wxTOP">1</bool>
+            <bool name="proxy-wxBOTTOM">1</bool>
+            <bool name="proxy-wxSHAPED">0</bool>
+            <bool name="proxy-wxADJUST_MINSIZE">0</bool>
+            <bool name="proxy-wxFIXED_MINSIZE">0</bool>
+            <string name="proxy-Platform">"<Any platform>"</string>
+            <document>
+              <string name="title">"wxStaticText: wxID_STATIC"</string>
+              <string name="type">"dialog-control-document"</string>
+              <string name="filename">""</string>
+              <string name="icon-name">"statictext"</string>
+              <long name="is-transient">0</long>
+              <long name="owns-file">1</long>
+              <long name="title-mode">0</long>
+              <long name="locked">0</long>
+              <string name="proxy-type">"wbStaticTextProxy"</string>
+              <string name="proxy-Id name">"wxID_STATIC"</string>
+              <long name="proxy-Id value">5105</long>
+              <string name="proxy-Name">""</string>
+              <string name="proxy-Class">"wxStaticText"</string>
+              <string name="proxy-Base class">"wxStaticText"</string>
+              <bool name="proxy-External implementation">1</bool>
+              <bool name="proxy-Separate files">0</bool>
+              <string name="proxy-Implementation filename">""</string>
+              <string name="proxy-Header filename">""</string>
+              <string name="proxy-Member variable name">""</string>
+              <string name="proxy-Label">"Score:"</string>
+              <long name="proxy-Wrapping width">-1</long>
+              <string name="proxy-Help text">""</string>
+              <string name="proxy-Tooltip text">""</string>
+              <string name="proxy-Background colour">""</string>
+              <string name="proxy-Foreground colour">""</string>
+              <string name="proxy-Font">""</string>
+              <bool name="proxy-Hidden">0</bool>
+              <bool name="proxy-Enabled">1</bool>
+              <string name="proxy-Platform">"<Any platform>"</string>
+              <string name="proxy-Data variable">""</string>
+              <string name="proxy-Data validator">""</string>
+              <string name="proxy-Data source">""</string>
+              <string name="proxy-Data class name">""</string>
+              <string name="proxy-Data class implementation filename">""</string>
+              <string name="proxy-Data class header filename">""</string>
+              <string name="proxy-Data class manager window">""</string>
+              <bool name="proxy-wxALIGN_LEFT">0</bool>
+              <bool name="proxy-wxALIGN_RIGHT">0</bool>
+              <bool name="proxy-wxALIGN_CENTRE">0</bool>
+              <bool name="proxy-wxST_NO_AUTORESIZE">0</bool>
+              <bool name="proxy-wxNO_BORDER">0</bool>
+              <bool name="proxy-wxSIMPLE_BORDER">0</bool>
+              <bool name="proxy-wxDOUBLE_BORDER">0</bool>
+              <bool name="proxy-wxBORDER_THEME">0</bool>
+              <bool name="proxy-wxSUNKEN_BORDER">0</bool>
+              <bool name="proxy-wxRAISED_BORDER">0</bool>
+              <bool name="proxy-wxSTATIC_BORDER">0</bool>
+              <bool name="proxy-wxWANTS_CHARS">0</bool>
+              <bool name="proxy-wxNO_FULL_REPAINT_ON_RESIZE">0</bool>
+              <bool name="proxy-wxFULL_REPAINT_ON_RESIZE">0</bool>
+              <string name="proxy-Custom styles">""</string>
+              <long name="proxy-X">-1</long>
+              <long name="proxy-Y">-1</long>
+              <long name="proxy-Width">-1</long>
+              <long name="proxy-Height">-1</long>
+              <string name="proxy-AlignH">"Left"</string>
+              <string name="proxy-AlignV">"Centre"</string>
+              <long name="proxy-Stretch factor">0</long>
+              <long name="proxy-Border">5</long>
+              <bool name="proxy-wxLEFT">1</bool>
+              <bool name="proxy-wxRIGHT">1</bool>
+              <bool name="proxy-wxTOP">1</bool>
+              <bool name="proxy-wxBOTTOM">1</bool>
+              <bool name="proxy-wxSHAPED">0</bool>
+              <bool name="proxy-wxADJUST_MINSIZE">0</bool>
+              <bool name="proxy-wxFIXED_MINSIZE">0</bool>
+              <string name="proxy-Custom arguments">""</string>
+              <string name="proxy-Custom ctor arguments">""</string>
+              <long name="proxy-Grid x">0</long>
+              <long name="proxy-Grid y">0</long>
+              <long name="proxy-Span x">1</long>
+              <long name="proxy-Span y">1</long>
+            </document>
+            <document>
+              <string name="title">"wxChoice: ID_CHOICE_MUSIC_SCORE"</string>
+              <string name="type">"dialog-control-document"</string>
+              <string name="filename">""</string>
+              <string name="icon-name">"choice"</string>
+              <long name="is-transient">0</long>
+              <long name="owns-file">1</long>
+              <long name="title-mode">0</long>
+              <long name="locked">0</long>
+              <string name="proxy-type">"wbChoiceProxy"</string>
+              <string name="event-handler-0">"wxEVT_COMMAND_CHOICE_SELECTED|OnChoiceMusicScoreSelected|NONE||ScorePlayerPanel"</string>
+              <string name="proxy-Id name">"ID_CHOICE_MUSIC_SCORE"</string>
+              <long name="proxy-Id value">10081</long>
+              <string name="proxy-Name">""</string>
+              <string name="proxy-Class">"wxChoice"</string>
+              <string name="proxy-Base class">"wxChoice"</string>
+              <bool name="proxy-External implementation">1</bool>
+              <bool name="proxy-Separate files">0</bool>
+              <string name="proxy-Implementation filename">""</string>
+              <string name="proxy-Header filename">""</string>
+              <string name="proxy-Member variable name">"m_choMusicalScore"</string>
+              <string name="proxy-Strings">"Chromatic scale|Major natural|Minor natural|Major pentatonic|Minor pentatonic|Blues"</string>
+              <string name="proxy-Initial value">"Major pentatonic"</string>
+              <string name="proxy-Help text">""</string>
+              <string name="proxy-Tooltip text">""</string>
+              <string name="proxy-Background colour">""</string>
+              <string name="proxy-Foreground colour">""</string>
+              <string name="proxy-Font">""</string>
+              <bool name="proxy-Hidden">0</bool>
+              <bool name="proxy-Enabled">1</bool>
+              <string name="proxy-Platform">"<Any platform>"</string>
+              <string name="proxy-Data variable">""</string>
+              <string name="proxy-Data validator">""</string>
+              <string name="proxy-Data source">""</string>
+              <string name="proxy-Data class name">""</string>
+              <string name="proxy-Data class implementation filename">""</string>
+              <string name="proxy-Data class header filename">""</string>
+              <string name="proxy-Data class manager window">""</string>
+              <bool name="proxy-wxWANTS_CHARS">0</bool>
+              <bool name="proxy-wxNO_FULL_REPAINT_ON_RESIZE">0</bool>
+              <bool name="proxy-wxFULL_REPAINT_ON_RESIZE">0</bool>
+              <string name="proxy-Custom styles">""</string>
+              <long name="proxy-X">-1</long>
+              <long name="proxy-Y">-1</long>
+              <long name="proxy-Width">-1</long>
+              <long name="proxy-Height">-1</long>
+              <string name="proxy-AlignH">"Expand"</string>
+              <string name="proxy-AlignV">"Centre"</string>
+              <long name="proxy-Stretch factor">0</long>
+              <long name="proxy-Border">5</long>
+              <bool name="proxy-wxLEFT">1</bool>
+              <bool name="proxy-wxRIGHT">1</bool>
+              <bool name="proxy-wxTOP">1</bool>
+              <bool name="proxy-wxBOTTOM">1</bool>
+              <bool name="proxy-wxSHAPED">0</bool>
+              <bool name="proxy-wxADJUST_MINSIZE">0</bool>
+              <bool name="proxy-wxFIXED_MINSIZE">0</bool>
+              <string name="proxy-Custom arguments">""</string>
+              <string name="proxy-Custom ctor arguments">""</string>
+              <long name="proxy-Grid x">1</long>
+              <long name="proxy-Grid y">0</long>
+              <long name="proxy-Span x">2</long>
+              <long name="proxy-Span y">1</long>
+            </document>
+            <document>
+              <string name="title">"wxStaticText: wxID_STATIC"</string>
+              <string name="type">"dialog-control-document"</string>
+              <string name="filename">""</string>
+              <string name="icon-name">"statictext"</string>
+              <long name="is-transient">0</long>
+              <long name="owns-file">1</long>
+              <long name="title-mode">0</long>
+              <long name="locked">0</long>
+              <string name="proxy-type">"wbStaticTextProxy"</string>
+              <string name="proxy-Id name">"wxID_STATIC"</string>
+              <long name="proxy-Id value">5105</long>
+              <string name="proxy-Name">""</string>
+              <string name="proxy-Class">"wxStaticText"</string>
+              <string name="proxy-Base class">"wxStaticText"</string>
+              <bool name="proxy-External implementation">1</bool>
+              <bool name="proxy-Separate files">0</bool>
+              <string name="proxy-Implementation filename">""</string>
+              <string name="proxy-Header filename">""</string>
+              <string name="proxy-Member variable name">""</string>
+              <string name="proxy-Label">"Instrument:"</string>
+              <long name="proxy-Wrapping width">-1</long>
+              <string name="proxy-Help text">""</string>
+              <string name="proxy-Tooltip text">""</string>
+              <string name="proxy-Background colour">""</string>
+              <string name="proxy-Foreground colour">""</string>
+              <string name="proxy-Font">""</string>
+              <bool name="proxy-Hidden">0</bool>
+              <bool name="proxy-Enabled">1</bool>
+              <string name="proxy-Platform">"<Any platform>"</string>
+              <string name="proxy-Data variable">""</string>
+              <string name="proxy-Data validator">""</string>
+              <string name="proxy-Data source">""</string>
+              <string name="proxy-Data class name">""</string>
+              <string name="proxy-Data class implementation filename">""</string>
+              <string name="proxy-Data class header filename">""</string>
+              <string name="proxy-Data class manager window">""</string>
+              <bool name="proxy-wxALIGN_LEFT">0</bool>
+              <bool name="proxy-wxALIGN_RIGHT">0</bool>
+              <bool name="proxy-wxALIGN_CENTRE">0</bool>
+              <bool name="proxy-wxST_NO_AUTORESIZE">0</bool>
+              <bool name="proxy-wxNO_BORDER">0</bool>
+              <bool name="proxy-wxSIMPLE_BORDER">0</bool>
+              <bool name="proxy-wxDOUBLE_BORDER">0</bool>
+              <bool name="proxy-wxBORDER_THEME">0</bool>
+              <bool name="proxy-wxSUNKEN_BORDER">0</bool>
+              <bool name="proxy-wxRAISED_BORDER">0</bool>
+              <bool name="proxy-wxSTATIC_BORDER">0</bool>
+              <bool name="proxy-wxWANTS_CHARS">0</bool>
+              <bool name="proxy-wxNO_FULL_REPAINT_ON_RESIZE">0</bool>
+              <bool name="proxy-wxFULL_REPAINT_ON_RESIZE">0</bool>
+              <string name="proxy-Custom styles">""</string>
+              <long name="proxy-X">-1</long>
+              <long name="proxy-Y">-1</long>
+              <long name="proxy-Width">-1</long>
+              <long name="proxy-Height">-1</long>
+              <string name="proxy-AlignH">"Left"</string>
+              <string name="proxy-AlignV">"Centre"</string>
+              <long name="proxy-Stretch factor">0</long>
+              <long name="proxy-Border">5</long>
+              <bool name="proxy-wxLEFT">1</bool>
+              <bool name="proxy-wxRIGHT">1</bool>
+              <bool name="proxy-wxTOP">1</bool>
+              <bool name="proxy-wxBOTTOM">1</bool>
+              <bool name="proxy-wxSHAPED">0</bool>
+              <bool name="proxy-wxADJUST_MINSIZE">0</bool>
+              <bool name="proxy-wxFIXED_MINSIZE">0</bool>
+              <string name="proxy-Custom arguments">""</string>
+              <string name="proxy-Custom ctor arguments">""</string>
+              <long name="proxy-Grid x">0</long>
+              <long name="proxy-Grid y">1</long>
+              <long name="proxy-Span x">1</long>
+              <long name="proxy-Span y">1</long>
+            </document>
+            <document>
+              <string name="title">"wxStaticText: wxID_STATIC"</string>
+              <string name="type">"dialog-control-document"</string>
+              <string name="filename">""</string>
+              <string name="icon-name">"statictext"</string>
+              <long name="is-transient">0</long>
+              <long name="owns-file">1</long>
+              <long name="title-mode">0</long>
+              <long name="locked">0</long>
+              <string name="proxy-type">"wbStaticTextProxy"</string>
+              <string name="proxy-Id name">"wxID_STATIC"</string>
+              <long name="proxy-Id value">5105</long>
+              <string name="proxy-Name">""</string>
+              <string name="proxy-Class">"wxStaticText"</string>
+              <string name="proxy-Base class">"wxStaticText"</string>
+              <bool name="proxy-External implementation">1</bool>
+              <bool name="proxy-Separate files">0</bool>
+              <string name="proxy-Implementation filename">""</string>
+              <string name="proxy-Header filename">""</string>
+              <string name="proxy-Member variable name">""</string>
+              <string name="proxy-Label">"Note duration:"</string>
+              <long name="proxy-Wrapping width">-1</long>
+              <string name="proxy-Help text">""</string>
+              <string name="proxy-Tooltip text">""</string>
+              <string name="proxy-Background colour">""</string>
+              <string name="proxy-Foreground colour">""</string>
+              <string name="proxy-Font">""</string>
+              <bool name="proxy-Hidden">0</bool>
+              <bool name="proxy-Enabled">1</bool>
+              <string name="proxy-Platform">"<Any platform>"</string>
+              <string name="proxy-Data variable">""</string>
+              <string name="proxy-Data validator">""</string>
+              <string name="proxy-Data source">""</string>
+              <string name="proxy-Data class name">""</string>
+              <string name="proxy-Data class implementation filename">""</string>
+              <string name="proxy-Data class header filename">""</string>
+              <string name="proxy-Data class manager window">""</string>
+              <bool name="proxy-wxALIGN_LEFT">0</bool>
+              <bool name="proxy-wxALIGN_RIGHT">0</bool>
+              <bool name="proxy-wxALIGN_CENTRE">0</bool>
+              <bool name="proxy-wxST_NO_AUTORESIZE">0</bool>
+              <bool name="proxy-wxNO_BORDER">0</bool>
+              <bool name="proxy-wxSIMPLE_BORDER">0</bool>
+              <bool name="proxy-wxDOUBLE_BORDER">0</bool>
+              <bool name="proxy-wxBORDER_THEME">0</bool>
+              <bool name="proxy-wxSUNKEN_BORDER">0</bool>
+              <bool name="proxy-wxRAISED_BORDER">0</bool>
+              <bool name="proxy-wxSTATIC_BORDER">0</bool>
+              <bool name="proxy-wxWANTS_CHARS">0</bool>
+              <bool name="proxy-wxNO_FULL_REPAINT_ON_RESIZE">0</bool>
+              <bool name="proxy-wxFULL_REPAINT_ON_RESIZE">0</bool>
+              <string name="proxy-Custom styles">""</string>
+              <long name="proxy-X">-1</long>
+              <long name="proxy-Y">-1</long>
+              <long name="proxy-Width">-1</long>
+              <long name="proxy-Height">-1</long>
+              <string name="proxy-AlignH">"Left"</string>
+              <string name="proxy-AlignV">"Centre"</string>
+              <long name="proxy-Stretch factor">0</long>
+              <long name="proxy-Border">5</long>
+              <bool name="proxy-wxLEFT">1</bool>
+              <bool name="proxy-wxRIGHT">1</bool>
+              <bool name="proxy-wxTOP">1</bool>
+              <bool name="proxy-wxBOTTOM">1</bool>
+              <bool name="proxy-wxSHAPED">0</bool>
+              <bool name="proxy-wxADJUST_MINSIZE">0</bool>
+              <bool name="proxy-wxFIXED_MINSIZE">0</bool>
+              <string name="proxy-Custom arguments">""</string>
+              <string name="proxy-Custom ctor arguments">""</string>
+              <long name="proxy-Grid x">0</long>
+              <long name="proxy-Grid y">2</long>
+              <long name="proxy-Span x">1</long>
+              <long name="proxy-Span y">1</long>
+            </document>
+            <document>
+              <string name="title">"wxSpinCtrl: ID_SPINCTRL_NOTE_DURATION"</string>
+              <string name="type">"dialog-control-document"</string>
+              <string name="filename">""</string>
+              <string name="icon-name">"spinctrl"</string>
+              <long name="is-transient">0</long>
+              <long name="owns-file">1</long>
+              <long name="title-mode">0</long>
+              <long name="locked">0</long>
+              <string name="proxy-type">"wbSpinCtrlProxy"</string>
+              <string name="event-handler-0">"wxEVT_COMMAND_SPINCTRL_UPDATED|OnSpinctrlNoteDurationUpdated|NONE||ScorePlayerPanel"</string>
+              <string name="proxy-Id name">"ID_SPINCTRL_NOTE_DURATION"</string>
+              <long name="proxy-Id value">10082</long>
+              <string name="proxy-Name">""</string>
+              <string name="proxy-Class">"wxSpinCtrl"</string>
+              <string name="proxy-Base class">"wxSpinCtrl"</string>
+              <bool name="proxy-External implementation">1</bool>
+              <bool name="proxy-Separate files">0</bool>
+              <string name="proxy-Implementation filename">""</string>
+              <string name="proxy-Header filename">""</string>
+              <string name="proxy-Member variable name">"m_spinNoteDuration"</string>
+              <long name="proxy-Minimum value">0</long>
+              <long name="proxy-Maximum value">100</long>
+              <long name="proxy-Initial value">0</long>
+              <string name="proxy-Help text">""</string>
+              <string name="proxy-Tooltip text">""</string>
+              <string name="proxy-Background colour">""</string>
+              <string name="proxy-Foreground colour">""</string>
+              <string name="proxy-Font">""</string>
+              <bool name="proxy-Hidden">0</bool>
+              <bool name="proxy-Enabled">1</bool>
+              <string name="proxy-Platform">"<Any platform>"</string>
+              <string name="proxy-Data variable">""</string>
+              <string name="proxy-Data validator">""</string>
+              <string name="proxy-Data source">""</string>
+              <string name="proxy-Data class name">""</string>
+              <string name="proxy-Data class implementation filename">""</string>
+              <string name="proxy-Data class header filename">""</string>
+              <string name="proxy-Data class manager window">""</string>
+              <bool name="proxy-wxSP_ARROW_KEYS">1</bool>
+              <bool name="proxy-wxSP_WRAP">0</bool>
+              <bool name="proxy-wxNO_BORDER">0</bool>
+              <bool name="proxy-wxSIMPLE_BORDER">0</bool>
+              <bool name="proxy-wxDOUBLE_BORDER">0</bool>
+              <bool name="proxy-wxBORDER_THEME">0</bool>
+              <bool name="proxy-wxSUNKEN_BORDER">0</bool>
+              <bool name="proxy-wxRAISED_BORDER">0</bool>
+              <bool name="proxy-wxSTATIC_BORDER">0</bool>
+              <bool name="proxy-wxWANTS_CHARS">0</bool>
+              <bool name="proxy-wxNO_FULL_REPAINT_ON_RESIZE">0</bool>
+              <bool name="proxy-wxFULL_REPAINT_ON_RESIZE">0</bool>
+              <string name="proxy-Custom styles">""</string>
+              <long name="proxy-X">-1</long>
+              <long name="proxy-Y">-1</long>
+              <long name="proxy-Width">70</long>
+              <long name="proxy-Height">-1</long>
+              <string name="proxy-AlignH">"Left"</string>
+              <string name="proxy-AlignV">"Centre"</string>
+              <long name="proxy-Stretch factor">0</long>
+              <long name="proxy-Border">5</long>
+              <bool name="proxy-wxLEFT">1</bool>
+              <bool name="proxy-wxRIGHT">1</bool>
+              <bool name="proxy-wxTOP">1</bool>
+              <bool name="proxy-wxBOTTOM">1</bool>
+              <bool name="proxy-wxSHAPED">0</bool>
+              <bool name="proxy-wxADJUST_MINSIZE">0</bool>
+              <bool name="proxy-wxFIXED_MINSIZE">0</bool>
+              <string name="proxy-Custom arguments">""</string>
+              <string name="proxy-Custom ctor arguments">""</string>
+              <long name="proxy-Grid x">1</long>
+              <long name="proxy-Grid y">2</long>
+              <long name="proxy-Span x">1</long>
+              <long name="proxy-Span y">1</long>
+            </document>
+            <document>
+              <string name="title">"wxStaticText: wxID_STATIC"</string>
+              <string name="type">"dialog-control-document"</string>
+              <string name="filename">""</string>
+              <string name="icon-name">"statictext"</string>
+              <long name="is-transient">0</long>
+              <long name="owns-file">1</long>
+              <long name="title-mode">0</long>
+              <long name="locked">0</long>
+              <string name="proxy-type">"wbStaticTextProxy"</string>
+              <string name="proxy-Id name">"wxID_STATIC"</string>
+              <long name="proxy-Id value">5105</long>
+              <string name="proxy-Name">""</string>
+              <string name="proxy-Class">"wxStaticText"</string>
+              <string name="proxy-Base class">"wxStaticText"</string>
+              <bool name="proxy-External implementation">1</bool>
+              <bool name="proxy-Separate files">0</bool>
+              <string name="proxy-Implementation filename">""</string>
+              <string name="proxy-Header filename">""</string>
+              <string name="proxy-Member variable name">""</string>
+              <string name="proxy-Label">"ms"</string>
+              <long name="proxy-Wrapping width">-1</long>
+              <string name="proxy-Help text">""</string>
+              <string name="proxy-Tooltip text">""</string>
+              <string name="proxy-Background colour">""</string>
+              <string name="proxy-Foreground colour">""</string>
+              <string name="proxy-Font">""</string>
+              <bool name="proxy-Hidden">0</bool>
+              <bool name="proxy-Enabled">1</bool>
+              <string name="proxy-Platform">"<Any platform>"</string>
+              <string name="proxy-Data variable">""</string>
+              <string name="proxy-Data validator">""</string>
+              <string name="proxy-Data source">""</string>
+              <string name="proxy-Data class name">""</string>
+              <string name="proxy-Data class implementation filename">""</string>
+              <string name="proxy-Data class header filename">""</string>
+              <string name="proxy-Data class manager window">""</string>
+              <bool name="proxy-wxALIGN_LEFT">0</bool>
+              <bool name="proxy-wxALIGN_RIGHT">0</bool>
+              <bool name="proxy-wxALIGN_CENTRE">0</bool>
+              <bool name="proxy-wxST_NO_AUTORESIZE">0</bool>
+              <bool name="proxy-wxNO_BORDER">0</bool>
+              <bool name="proxy-wxSIMPLE_BORDER">0</bool>
+              <bool name="proxy-wxDOUBLE_BORDER">0</bool>
+              <bool name="proxy-wxBORDER_THEME">0</bool>
+              <bool name="proxy-wxSUNKEN_BORDER">0</bool>
+              <bool name="proxy-wxRAISED_BORDER">0</bool>
+              <bool name="proxy-wxSTATIC_BORDER">0</bool>
+              <bool name="proxy-wxWANTS_CHARS">0</bool>
+              <bool name="proxy-wxNO_FULL_REPAINT_ON_RESIZE">0</bool>
+              <bool name="proxy-wxFULL_REPAINT_ON_RESIZE">0</bool>
+              <string name="proxy-Custom styles">""</string>
+              <long name="proxy-X">-1</long>
+              <long name="proxy-Y">-1</long>
+              <long name="proxy-Width">-1</long>
+              <long name="proxy-Height">-1</long>
+              <string name="proxy-AlignH">"Left"</string>
+              <string name="proxy-AlignV">"Centre"</string>
+              <long name="proxy-Stretch factor">0</long>
+              <long name="proxy-Border">5</long>
+              <bool name="proxy-wxLEFT">1</bool>
+              <bool name="proxy-wxRIGHT">1</bool>
+              <bool name="proxy-wxTOP">1</bool>
+              <bool name="proxy-wxBOTTOM">1</bool>
+              <bool name="proxy-wxSHAPED">0</bool>
+              <bool name="proxy-wxADJUST_MINSIZE">0</bool>
+              <bool name="proxy-wxFIXED_MINSIZE">0</bool>
+              <string name="proxy-Custom arguments">""</string>
+              <string name="proxy-Custom ctor arguments">""</string>
+              <long name="proxy-Grid x">2</long>
+              <long name="proxy-Grid y">2</long>
+              <long name="proxy-Span x">1</long>
+              <long name="proxy-Span y">1</long>
+            </document>
+            <document>
+              <string name="title">"wxCheckBox: ID_CHECKBOX_MUTE_PREVIOUS_NOTE"</string>
+              <string name="type">"dialog-control-document"</string>
+              <string name="filename">""</string>
+              <string name="icon-name">"checkbox"</string>
+              <long name="is-transient">0</long>
+              <long name="owns-file">1</long>
+              <long name="title-mode">0</long>
+              <long name="locked">0</long>
+              <string name="proxy-type">"wbCheckBoxProxy"</string>
+              <string name="event-handler-0">"wxEVT_COMMAND_CHECKBOX_CLICKED|OnCheckboxMutePreviousNoteClick|NONE||ScorePlayerPanel"</string>
+              <string name="proxy-Id name">"ID_CHECKBOX_MUTE_PREVIOUS_NOTE"</string>
+              <long name="proxy-Id value">10083</long>
+              <string name="proxy-Name">""</string>
+              <string name="proxy-Class">"wxCheckBox"</string>
+              <string name="proxy-Base class">"wxCheckBox"</string>
+              <bool name="proxy-External implementation">1</bool>
+              <bool name="proxy-Separate files">0</bool>
+              <string name="proxy-Implementation filename">""</string>
+              <string name="proxy-Header filename">""</string>
+              <string name="proxy-Member variable name">"m_chkMutePreviousNote"</string>
+              <string name="proxy-Label">"Mute previous"</string>
+              <bool name="proxy-Initial value">0</bool>
+              <string name="proxy-Help text">""</string>
+              <string name="proxy-Tooltip text">""</string>
+              <string name="proxy-Data variable">""</string>
+              <string name="proxy-Data validator">""</string>
+              <string name="proxy-Data source">""</string>
+              <string name="proxy-Data class name">""</string>
+              <string name="proxy-Data class implementation filename">""</string>
+              <string name="proxy-Data class header filename">""</string>
+              <string name="proxy-Data class manager window">""</string>
+              <string name="proxy-Background colour">""</string>
+              <string name="proxy-Foreground colour">""</string>
+              <string name="proxy-Font">""</string>
+              <bool name="proxy-Hidden">1</bool>
+              <bool name="proxy-Enabled">0</bool>
+              <string name="proxy-Platform">"<Any platform>"</string>
+              <bool name="proxy-wxALIGN_RIGHT">0</bool>
+              <bool name="proxy-wxCHK_2STATE">0</bool>
+              <bool name="proxy-wxCHK_3STATE">0</bool>
+              <bool name="proxy-wxCHK_ALLOW_3RD_STATE_FOR_USER">0</bool>
+              <bool name="proxy-wxWANTS_CHARS">0</bool>
+              <bool name="proxy-wxNO_FULL_REPAINT_ON_RESIZE">0</bool>
+              <bool name="proxy-wxFULL_REPAINT_ON_RESIZE">0</bool>
+              <string name="proxy-Custom styles">""</string>
+              <long name="proxy-X">-1</long>
+              <long name="proxy-Y">-1</long>
+              <long name="proxy-Width">-1</long>
+              <long name="proxy-Height">-1</long>
+              <string name="proxy-AlignH">"Left"</string>
+              <string name="proxy-AlignV">"Centre"</string>
+              <long name="proxy-Stretch factor">0</long>
+              <long name="proxy-Border">5</long>
+              <bool name="proxy-wxLEFT">1</bool>
+              <bool name="proxy-wxRIGHT">1</bool>
+              <bool name="proxy-wxTOP">1</bool>
+              <bool name="proxy-wxBOTTOM">1</bool>
+              <bool name="proxy-wxSHAPED">0</bool>
+              <bool name="proxy-wxADJUST_MINSIZE">0</bool>
+              <bool name="proxy-wxFIXED_MINSIZE">0</bool>
+              <string name="proxy-Custom arguments">""</string>
+              <string name="proxy-Custom ctor arguments">""</string>
+              <long name="proxy-Grid x">0</long>
+              <long name="proxy-Grid y">3</long>
+              <long name="proxy-Span x">2</long>
+              <long name="proxy-Span y">1</long>
+            </document>
+            <document>
+              <string name="title">"wxChoice: ID_CHOICE_MUSICAL_INSTRUMENT"</string>
+              <string name="type">"dialog-control-document"</string>
+              <string name="filename">""</string>
+              <string name="icon-name">"choice"</string>
+              <long name="is-transient">0</long>
+              <long name="owns-file">1</long>
+              <long name="title-mode">0</long>
+              <long name="locked">0</long>
+              <string name="proxy-type">"wbChoiceProxy"</string>
+              <string name="event-handler-0">"wxEVT_COMMAND_CHOICE_SELECTED|OnChoiceMusicalInstrumentSelected|NONE||ScorePlayerPanel"</string>
+              <string name="proxy-Id name">"ID_CHOICE_MUSICAL_INSTRUMENT"</string>
+              <long name="proxy-Id value">10084</long>
+              <string name="proxy-Name">""</string>
+              <string name="proxy-Class">"wxChoice"</string>
+              <string name="proxy-Base class">"wxChoice"</string>
+              <bool name="proxy-External implementation">1</bool>
+              <bool name="proxy-Separate files">0</bool>
+              <string name="proxy-Implementation filename">""</string>
+              <string name="proxy-Header filename">""</string>
+              <string name="proxy-Member variable name">"m_choMusicalInstrument"</string>
+              <string name="proxy-Strings">"1-Acoustic Grand|2-Bright Acoustic|3-Electric Grand|4-Honky-Tonk|5-Electric Piano 1|6-Electric Piano 2|7-Harpsichord|8-Clavinet|9-Celesta|10-Glockenspiel|11-Music Box|12-Vibraphone|13-Marimba|14-Xylophone|15-Tubular Bells|16-Dulcimer|17-Drawbar Organ|18-Percussive Organ|19-Rock Organ|20-Church Organ|21-Reed Organ|22-Accoridan|23-Harmonica|24-Tango Accordian|25-Nylon String Guitar|26-Steel String Guitar|27-Electric Jazz Guitar|28-Electric Clean  [...]
+              <string name="proxy-Initial value">"0"</string>
+              <string name="proxy-Help text">""</string>
+              <string name="proxy-Tooltip text">""</string>
+              <string name="proxy-Background colour">""</string>
+              <string name="proxy-Foreground colour">""</string>
+              <string name="proxy-Font">""</string>
+              <bool name="proxy-Hidden">0</bool>
+              <bool name="proxy-Enabled">1</bool>
+              <string name="proxy-Platform">"<Any platform>"</string>
+              <string name="proxy-Data variable">""</string>
+              <string name="proxy-Data validator">""</string>
+              <string name="proxy-Data source">""</string>
+              <string name="proxy-Data class name">""</string>
+              <string name="proxy-Data class implementation filename">""</string>
+              <string name="proxy-Data class header filename">""</string>
+              <string name="proxy-Data class manager window">""</string>
+              <bool name="proxy-wxWANTS_CHARS">0</bool>
+              <bool name="proxy-wxNO_FULL_REPAINT_ON_RESIZE">0</bool>
+              <bool name="proxy-wxFULL_REPAINT_ON_RESIZE">0</bool>
+              <string name="proxy-Custom styles">""</string>
+              <long name="proxy-X">-1</long>
+              <long name="proxy-Y">-1</long>
+              <long name="proxy-Width">-1</long>
+              <long name="proxy-Height">-1</long>
+              <string name="proxy-AlignH">"Left"</string>
+              <string name="proxy-AlignV">"Centre"</string>
+              <long name="proxy-Stretch factor">0</long>
+              <long name="proxy-Border">5</long>
+              <bool name="proxy-wxLEFT">1</bool>
+              <bool name="proxy-wxRIGHT">1</bool>
+              <bool name="proxy-wxTOP">1</bool>
+              <bool name="proxy-wxBOTTOM">1</bool>
+              <bool name="proxy-wxSHAPED">0</bool>
+              <bool name="proxy-wxADJUST_MINSIZE">0</bool>
+              <bool name="proxy-wxFIXED_MINSIZE">0</bool>
+              <string name="proxy-Custom arguments">""</string>
+              <string name="proxy-Custom ctor arguments">""</string>
+              <long name="proxy-Grid x">1</long>
+              <long name="proxy-Grid y">1</long>
+              <long name="proxy-Span x">2</long>
+              <long name="proxy-Span y">1</long>
+            </document>
+          </document>
+        </document>
+      </document>
+      <document>
+        <string name="title">"Sources"</string>
+        <string name="type">"html-document"</string>
+        <string name="filename">""</string>
+        <string name="icon-name">"sourcesfolder"</string>
+        <long name="is-transient">1</long>
+        <long name="owns-file">1</long>
+        <long name="title-mode">0</long>
+        <long name="locked">1</long>
+        <document>
+          <string name="title">"mviacam.rc"</string>
+          <string name="type">"source-editor-document"</string>
+          <string name="filename">"mviacam.rc"</string>
+          <string name="icon-name">"source-editor"</string>
+          <long name="is-transient">0</long>
+          <long name="owns-file">0</long>
+          <long name="title-mode">1</long>
+          <long name="locked">0</long>
+          <string name="created">"3/8/2009"</string>
+          <string name="language">""</string>
+        </document>
+      </document>
+      <document>
+        <string name="title">"Images"</string>
+        <string name="type">"html-document"</string>
+        <string name="filename">""</string>
+        <string name="icon-name">"bitmapsfolder"</string>
+        <long name="is-transient">1</long>
+        <long name="owns-file">1</long>
+        <long name="title-mode">0</long>
+        <long name="locked">1</long>
+        <document>
+          <string name="title">"disable_icon.xpm"</string>
+          <string name="type">"image-document"</string>
+          <string name="filename">"bitmaps/disable_icon.xpm"</string>
+          <string name="icon-name">"image"</string>
+          <long name="is-transient">0</long>
+          <long name="owns-file">0</long>
+          <long name="title-mode">0</long>
+          <long name="locked">0</long>
+          <long name="zoom-level">100</long>
+        </document>
+        <document>
+          <string name="title">"sitplus_logo_16x16.xpm"</string>
+          <string name="type">"image-document"</string>
+          <string name="filename">"bitmaps/sitplus_logo_16x16.xpm"</string>
+          <string name="icon-name">"image"</string>
+          <long name="is-transient">0</long>
+          <long name="owns-file">0</long>
+          <long name="title-mode">0</long>
+          <long name="locked">0</long>
+          <long name="zoom-level">100</long>
+        </document>
+        <document>
+          <string name="title">"sitplus_logo_32x32.xpm"</string>
+          <string name="type">"image-document"</string>
+          <string name="filename">"bitmaps/sitplus_logo_32x32.xpm"</string>
+          <string name="icon-name">"image"</string>
+          <long name="is-transient">0</long>
+          <long name="owns-file">0</long>
+          <long name="title-mode">0</long>
+          <long name="locked">0</long>
+          <long name="zoom-level">100</long>
+        </document>
+      </document>
+    </document>
+  </documents>
+
+</anthemion-project>
diff --git a/src/mod_score_player/scoreplayer.cpp b/src/mod_score_player/scoreplayer.cpp
new file mode 100644
index 0000000..da9601e
--- /dev/null
+++ b/src/mod_score_player/scoreplayer.cpp
@@ -0,0 +1,478 @@
+/////////////////////////////////////////////////////////////////////////////
+// Name:
+// Purpose:		scoreplayer.cpp
+// Author:      Cesar Mauri Loba (cesar at crea-si dot com)
+// Modified by:
+// Created:
+// Copyright:   (C) 2010-11 Cesar Mauri Loba - CREA Software Systems
+//
+//  This program is free software: you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation, either version 3 of the License, or
+//  (at your option) any later version.
+//
+//  This program is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+/////////////////////////////////////////////////////////////////////////////
+
+#include "scoreplayer.h"
+#include "spcore/conversion.h"
+
+#include <boost/static_assert.hpp>
+#include <boost/algorithm/string.hpp>
+#ifdef WIN32
+// TODO: remove the following line when boost gets updated
+// See: https://svn.boost.org/trac/boost/ticket/4649
+#pragma warning (disable:4127)
+#endif
+#include <boost/tokenizer.hpp>
+#include <boost/foreach.hpp>
+#include <sys/timeb.h>
+#include <sys/types.h>
+
+using namespace spcore;
+using namespace boost;
+using namespace std;
+
+namespace mod_score_player {
+
+static unsigned long long GetTStamp (void)
+{
+	struct timeb now;
+	ftime(&now);
+	return (unsigned long long) now.time * 1000 + now.millitm;
+}
+
+ScorePlayerComponent::ScorePlayerComponent(const char * name, int argc, const char * argv[])
+: CComponentAdapter(name, argc, argv)
+, m_volume(127)		// Maximum volume default
+, m_instrument(0)	// Piano default
+, m_newInstrument(0)
+, m_channel(0)		// Channel 0 default
+, m_newChannel(0)
+, m_originalChannel(0)
+, m_transpose(0)
+, m_newTranspose(0)
+, m_scoreWrap(false)
+, m_scoreAlwaysForward(false)
+, m_duration(500)
+, m_runningChord(-1)
+, m_lastPlayedChord(-1)
+, m_timeStamp(0)
+, m_progressPointer(0.0f)
+, m_progressFactor(1.0f)
+{
+	//
+	// Pins
+	//
+
+	// Input pins
+	RegisterInputPin (*SmartPtr<IInputPin>(new InputPinPointer(*this), false));
+	RegisterInputPin (*SmartPtr<IInputPin>(new InputPinProgress(*this), false));
+	RegisterInputPin (*SmartPtr<IInputPin>(new InputPinVolume(*this), false));
+	RegisterInputPin (*SmartPtr<IInputPin>(new InputPinInstrument(*this), false));
+	RegisterInputPin (*SmartPtr<IInputPin>(new InputPinDuration(*this), false));
+	RegisterInputPin (*SmartPtr<IInputPin>(new InputPinScore(*this), false));
+	RegisterInputPin (*SmartPtr<IInputPin>(new InputPinWrap(*this), false));
+	RegisterInputPin (*SmartPtr<IInputPin>(new InputPinTranspose(*this), false));
+
+	// Output pins
+	m_oPinNote= CTypeMIDIMessage::CreateOutputPin("note");
+	if (m_oPinNote.get()== NULL) throw std::runtime_error("output pin creation failed.");
+	RegisterOutputPin (*m_oPinNote);
+	m_oPinNotesPlayed= CTypeInt::CreateOutputPin("notes_played");
+	RegisterOutputPin (*m_oPinNotesPlayed);
+
+	// Instances
+	m_note= CTypeMIDIMessage::CreateInstance();
+	m_notesPlayed= CTypeInt::CreateInstance();
+
+	//
+	// Parse arguments
+	//
+	if (argc) {
+		for (int i= 0; i< argc; ++i) {
+			if (argv[i] && strcmp ("-c", argv[i])== 0) {
+				// Channel
+				unsigned int channel;
+
+				++i;
+				if (i< argc && argv[i] && StrToUint(argv[i], &channel) && channel<= 15) 
+					m_channel= m_originalChannel= m_newChannel= (unsigned char) channel;
+				else throw std::runtime_error("score_player. Wrong value for option -c");
+			}			
+			else if (argv[i] && strlen(argv[i])) {
+				string error_msg("score_player. Unknown option:");
+				error_msg+= argv[i];
+				throw std::runtime_error(error_msg);
+			}
+		}
+	}
+
+	//
+	// Add a chromatic scale for testing purposes
+	for (unsigned char i= 40; i<= 50; ++i) {
+		struct Chord c;
+		c.notes[0]= i;
+		m_score.push_back(c);
+	}
+	m_progressFactor= 1.0f / (float) m_score.size();
+}
+
+void ScorePlayerComponent::StopAllNotes()
+{
+	assert (IsInitialized());
+
+	m_note->SetStatus(0xB, m_channel);
+	m_note->SetData1(123);
+	m_note->SetData2(0);
+	m_oPinNote->Send(m_note);
+	m_runningChord= -1;
+	m_lastPlayedChord= -1;
+}
+
+// Given the value of the score pointer in the range 0..1 returns
+// the appropiate index for m_score vector
+int ScorePlayerComponent::Pointer2Index (float pointer)
+{
+	// Convert to int to index the appropiate note
+	int ichord= (int) ((float) (m_score.size() + 1) * pointer);
+
+	// Make sure ichord is whithin expected range
+	if (ichord>= (int) m_score.size()) ichord= (int) m_score.size() - 1;
+	else if (ichord< 0) ichord= 0;
+	assert (ichord>= 0 && ichord< (int) m_score.size());
+
+	return ichord;
+}
+
+void ScorePlayerComponent::PlayChord(Chord const& chord)
+{
+	for (int i= 0; i< POLYPHONY && chord.notes[i]!= -1; ++i) {
+		if (m_transpose && m_channel!= 9) {		// Doesn't transpose percussion kit
+			int newNote= (int) chord.notes[i] + (int) m_transpose * 12;
+			if (newNote> 0 && newNote< 127) {
+				m_note->SetNoteOn (m_channel, (char) newNote, m_volume);
+				m_oPinNote->Send(m_note);
+			}
+		}
+		else {
+			m_note->SetNoteOn (m_channel, chord.notes[i], m_volume);
+			m_oPinNote->Send(m_note);
+		}
+	}
+}
+
+void ScorePlayerComponent::StopChord(Chord const& chord)
+{
+	for (int i= 0; i< POLYPHONY && chord.notes[i]!= -1; ++i) {
+		if (m_transpose && m_channel!= 9) {		// Doesn't transpose percussion kit
+			int newNote= (int) chord.notes[i] + (int) m_transpose * 12;
+			if (newNote> 0 && newNote< 127) {
+				m_note->SetNoteOff (m_channel, (char) newNote, 127);
+				m_oPinNote->Send(m_note);
+			}
+		}
+		else {
+			m_note->SetNoteOff (m_channel, chord.notes[i], 127);
+			m_oPinNote->Send(m_note);
+		}
+	}
+}
+
+
+void ScorePlayerComponent::ProcessPointerUpdate (float pointer)
+{
+	//assert (pointer>= 0.0f && pointer<= 1.0f);
+#ifndef NDEBUG
+	if (pointer< 0.0f)
+		fprintf (stderr, "FP: inconsistency (pointer< 0.0f): %f\n", pointer);
+	else if (pointer> 1.0f)
+		fprintf (stderr, "FP: inconsistency (pointer> 1.0f): %f\n", pointer);
+#endif 
+
+	// Convert to int to index the appropiate note
+	int ichord= Pointer2Index (pointer);
+
+	// Need to stop previous chord?
+	unsigned long long now= GetTStamp ();
+	if (m_runningChord>= 0 && (ichord!= m_runningChord || (now - m_timeStamp)>= m_duration)) {
+		StopChord(m_score[m_runningChord]);
+		m_runningChord= -1;	// Note stopped
+	}
+
+	m_mutex.lock();
+
+	// Need to stop all notes?
+	bool needStopNotes=
+		!m_newScore.empty() || m_channel!= m_newChannel || m_transpose!= m_newTranspose;
+
+	// Score change?
+	if (!m_newScore.empty()) {
+		m_score= m_newScore;
+		m_newScore.clear();
+
+		m_progressFactor= 1.0f / (float) m_score.size();
+		ichord= Pointer2Index (pointer);
+	}
+
+	m_mutex.unlock();
+	
+	if (needStopNotes) StopAllNotes();
+
+	// Channel change
+	m_channel= m_newChannel;
+	
+	// Transposition change
+	m_transpose= m_newTranspose;
+
+	// Program change?
+	if (m_newInstrument!= m_instrument && m_channel!= 9) {
+		m_instrument= m_newInstrument;
+		m_note->SetProgramChange (m_channel, m_instrument);
+		m_oPinNote->Send(m_note);
+	}
+
+	// Need to start a new note?
+	if (ichord!= m_lastPlayedChord) {
+		m_runningChord= ichord;
+		m_lastPlayedChord= ichord;
+		PlayChord(m_score[m_runningChord]);
+		m_timeStamp= now;
+		m_notesPlayed->setValue(1);
+	}
+	else 
+		m_notesPlayed->setValue(0);
+
+	// Send number of chords played
+	m_oPinNotesPlayed->Send(m_notesPlayed);
+}
+
+void ScorePlayerComponent::OnPinPointer (const CTypeFloat & msg)
+{
+	assert (this->IsInitialized());
+	if (!this->IsInitialized()) return;
+
+	// In principle pointer should be between 0 and 1.0f, so in debug
+	// mode we assert to help developers to detect the error
+//	assert (msg.getValue()>= 0.0f && msg.getValue()<= 1.0f);
+
+	// In release mode we make sure this limit is enforced
+	float newPointer= fabsf (msg.getValue());
+	if (newPointer> 1.0f) 
+		newPointer= modff(newPointer, &newPointer);
+
+	ProcessPointerUpdate (newPointer);
+}
+
+
+void ScorePlayerComponent::OnPinProgress (const CTypeFloat & msg)
+{
+	assert (IsInitialized());
+	if (!IsInitialized()) return;
+
+	if (m_scoreAlwaysForward)
+		m_progressPointer+= fabsf(msg.getValue()) * m_progressFactor;
+	else
+		m_progressPointer+= msg.getValue() * m_progressFactor;
+
+	if (!m_scoreWrap) {
+		if (m_progressPointer> 1.0f) m_progressPointer= 1.0f;
+		else if (m_progressPointer< 0.0f) m_progressPointer= 0.0f;
+	}
+	else {
+		if (m_progressPointer< 0.0f) {
+			float foo;
+			m_progressPointer= 1.0f + modff(m_progressPointer, &foo);
+		}
+		else if (m_progressPointer> 1.0f) {
+			float foo;
+			m_progressPointer= modff(m_progressPointer, &foo);
+		}		
+	}
+
+	ProcessPointerUpdate (m_progressPointer);
+}
+
+void ScorePlayerComponent::OnPinVolume (const CTypeInt & msg)
+{
+	int newVol= msg.getValue();
+	if (newVol>= 0 && newVol<= 127)
+		m_volume= (unsigned char) newVol;
+	else
+		getSpCoreRuntime()->LogMessage(ICoreRuntime::LOG_WARNING, "Volume out of range. Ignored.", GetName());
+}
+
+void ScorePlayerComponent::OnPinInstrument (const CTypeInt & msg)
+{
+	unsigned char newInstrument= (unsigned char) msg.getValue();
+
+	if (newInstrument<= 127)
+		m_newInstrument= newInstrument;
+	else
+		getSpCoreRuntime()->LogMessage(ICoreRuntime::LOG_WARNING, "Instrument out of range. Ignored.", GetName());
+	
+}
+
+void ScorePlayerComponent::OnPinDuration (const CTypeInt & msg)
+{
+	int newDuration= msg.getValue();
+	if (newDuration>= 20 && newDuration<= 10000)
+		m_duration= (unsigned int) newDuration;		
+	else
+		getSpCoreRuntime()->LogMessage(ICoreRuntime::LOG_WARNING, "Duration out of range. Ignored.", GetName());
+}
+
+
+/* Parse score line. Return values:
+	[0 POLYPHONY] -> number of notes found (of 0 means blank/comment line)
+	-1			  -> percussion set selected
+	-2			  -> play always forward found
+	-3			  -> line contains syntax errors
+	-4			  -> line contains note values out of range
+*/
+static
+int ParseScoreLine (string& line, std::vector<ScorePlayerComponent::Chord>& score)
+{
+	boost::trim(line);
+
+	// Skip blank and comments
+	if (line.empty() || line[0]== '#') return 0;
+
+	// Tokenize
+	ScorePlayerComponent::Chord chord;
+	int nnotes= 0;
+	char_separator<char> sep("\t ,");
+	tokenizer<char_separator<char> > tok(line, sep);	
+	BOOST_FOREACH(string t, tok) {
+		if (t== "percussion") return -1;
+		if (t== "forward") return -2;
+
+		// Try to extract note
+		unsigned int note;
+		if (!StrToUint(t.c_str(), &note)) return -3;
+		if (note> 127) return -4;
+
+		// Store note
+		chord.notes[nnotes++]= (unsigned char) note;
+
+		if (nnotes== ScorePlayerComponent::POLYPHONY) break;
+	}
+
+	if (nnotes) score.push_back(chord);
+		
+	return nnotes;
+}
+
+/* Parse score. Return -1 if an error has ocurred 
+	If return value is equal or greater than 0 means that the score has been
+	successfully parsed. One or more values can be ored
+	0x00000000: parsing successful
+	0x00000001: percussive set has been selected
+	0x00000002: forward only score
+*/
+static
+int ParseScore (const char* contents, std::vector<ScorePlayerComponent::Chord>& score)
+{
+	if (!contents) return -1;
+
+	int result= 0;
+
+	const char* line_beg= contents;
+	const char* line_end= NULL;
+
+	for(;;) {
+		// Search line begining (skip LF, VT, FF & CR)
+		while (*line_beg>= 0xA && *line_beg<= 0xD) ++line_beg;
+		if (!*line_beg) break;
+
+		// Search line end
+		line_end= line_beg;
+		while (*line_end && (*line_end< 0xA || *line_end> 0xD)) ++line_end;
+
+		// Line lenght
+		int len= line_end - line_beg;
+		assert (len> 0);
+
+		// Extract line
+		std::string line(line_beg, len);
+
+		// Parse line
+		int retval= ParseScoreLine (line, score);
+		if (retval== -1) result|= 0x1;
+		else if (retval== -2) result|= 0x2;
+		else if (retval== -3) {
+			// Syntax error
+			getSpCoreRuntime()->LogMessage(
+				ICoreRuntime::LOG_ERROR,  
+				"Syntax error while parsing score",
+				ScorePlayerComponent::getTypeName());
+			return -1;
+		}
+		else if (retval== -4) {
+			getSpCoreRuntime()->LogMessage(
+				ICoreRuntime::LOG_WARNING,  
+				"Some notes are out of range while parsing score",
+				ScorePlayerComponent::getTypeName());
+		}
+
+		line_beg= line_end;
+	}
+
+	return result;
+}
+
+void ScorePlayerComponent::OnPinScore (const CTypeString & msg)
+{
+	std::vector<Chord> newScore;
+
+	int retval= ParseScore (msg.getValue(), newScore);
+
+	// Check errors
+	if (retval== -1) return;
+
+	// Check that the new score provides, at least, 2 chords
+	if (newScore.size()< 2) {
+		getSpCoreRuntime()->LogMessage(
+			ICoreRuntime::LOG_ERROR,  
+			"New score has not enough chords (minimum 2)",
+			ScorePlayerComponent::getTypeName());
+		return;
+	}
+
+	m_mutex.lock();
+
+	// Need to change channel?
+	if (retval & 0x1) m_newChannel= 9;
+	else m_newChannel= m_originalChannel;
+
+	// Always forward?
+	if (retval & 0x2) m_scoreAlwaysForward= true;
+	else m_scoreAlwaysForward= false;
+
+	// Set new score
+	m_newScore= newScore;
+
+	m_mutex.unlock();
+}
+
+void ScorePlayerComponent::OnPinWrap (const CTypeBool & msg)
+{
+	m_scoreWrap= msg.getValue();
+}
+
+void ScorePlayerComponent::OnPinTranspose (const CTypeInt & msg)
+{
+	int t= msg.getValue();
+	if (t< -8 || t> 8) 
+		spcore::getSpCoreRuntime()->LogMessage(ICoreRuntime::LOG_WARNING, "transposition out of range", GetTypeName());
+	else
+		m_newTranspose= static_cast<char>(t);
+}
+
+};	// namespace end
diff --git a/src/mod_score_player/scoreplayer.h b/src/mod_score_player/scoreplayer.h
new file mode 100644
index 0000000..d0e8298
--- /dev/null
+++ b/src/mod_score_player/scoreplayer.h
@@ -0,0 +1,265 @@
+/////////////////////////////////////////////////////////////////////////////
+// Name:       scoreplayer.h
+// Purpose:
+// Author:      Cesar Mauri Loba (cesar at crea-si dot com)
+// Modified by:
+// Created:     26/04/2010 11:05:03
+// Copyright:   (C) 2010-11 Cesar Mauri Loba - CREA Software Systems
+//
+//  This program is free software: you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation, either version 3 of the License, or
+//  (at your option) any later version.
+//
+//  This program is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+/////////////////////////////////////////////////////////////////////////////
+#ifndef SCOREPLAYER_H
+#define SCOREPLAYER_H
+
+#include "spcore/component.h"
+#include "spcore/pinimpl.h"
+#include "spcore/basictypes.h"
+#include "mod_midi/midi_types.h"
+
+#include <boost/thread/mutex.hpp>
+
+using namespace spcore;
+using namespace mod_midi;
+
+namespace mod_score_player {
+
+/** *****************************************************************************
+	Component: score_player
+
+	Purpose:
+		Given a float value between 0 and 1 selects the corresponding note
+		from a selected score and sends to the output
+
+	Input pins:
+		pointer (float)
+			Value between 0 and 1 which is used to play the note from a score
+			Allows to directly play notes from the score.
+
+		progress (float)
+			Allows to progress through the notes of the score (and play them) 
+			either back or forth. Each time the accumulated progress is 1.0f a 
+			new note is played.
+
+		volume (int)
+			Notes volume. Range 0..127
+
+		instrument (int)
+			Instrument to use. Range 0..127 (standard midi)
+
+		duration (int)
+			Note duration in ms
+
+		score (string)
+			List of notes which conform the score
+
+		wrap (bool)
+			Sets whether the score pointer should wrap once reaches 
+			the begining or the end of the score.
+
+		transpose (int)
+			Shift a certain number of octaves the notes being played. Range -8..8
+	
+	Output pins:
+		note (midi_message): MIDI message with the note to play
+
+		notes_played (int)
+			Number of notes played for the last progress message
+
+	Command line:
+		[ -c <num> ]	From 0 to 15 (9 percussion). Default: 0.
+
+	Notes:
+		If both "pointer" and "progress" receive messages from different
+		threads at the same time the behaviour is undefined.
+****************************************************************************** */
+class ScorePlayerComponent : public spcore::CComponentAdapter {
+public:
+	static const char* getTypeName() { return "score_player"; };
+	virtual const char* GetTypeName() const { return ScorePlayerComponent::getTypeName(); };
+
+	ScorePlayerComponent(const char * name, int argc, const char * argv[]);
+
+	//
+	// Types
+	//
+	enum { POLYPHONY= 4 };
+	struct Chord {
+		char notes[POLYPHONY];
+		Chord() {
+			for (int i= 0; i< POLYPHONY; ++i)
+				notes[i]= -1;
+		}
+	};
+
+private:
+	//
+	// Data members
+	//
+	unsigned char m_volume;
+
+	unsigned char m_instrument;
+	unsigned char m_newInstrument;
+
+	unsigned char m_channel;
+	unsigned char m_newChannel;
+	unsigned char m_originalChannel;
+
+	char m_transpose;
+	char m_newTranspose;
+
+	bool m_scoreWrap;
+	bool m_scoreAlwaysForward;
+
+	// Note duration
+	unsigned int m_duration;
+
+	// Score
+	std::vector<Chord> m_score;
+	std::vector<Chord> m_newScore;
+
+	// Running chord -1, none
+	int m_runningChord;
+	// Last played chord
+	int m_lastPlayedChord;
+	
+	// Timestamp which stores when was started the last note
+	unsigned long long m_timeStamp;
+
+	// Progress pointer
+	float m_progressPointer;
+	float m_progressFactor;
+
+	SmartPtr<IOutputPin> m_oPinNote;
+	SmartPtr<CTypeMIDIMessage> m_note;
+
+	SmartPtr<IOutputPin> m_oPinNotesPlayed;
+	SmartPtr<CTypeInt> m_notesPlayed;
+
+	boost::mutex m_mutex;
+
+	//
+	// Private methods
+	//	
+	void OnPinPointer (const CTypeFloat & msg);
+	void OnPinProgress (const CTypeFloat & msg);
+	void OnPinVolume (const CTypeInt & msg);
+	void OnPinInstrument (const CTypeInt & msg);
+	void OnPinDuration (const CTypeInt & msg);
+	void OnPinScore (const CTypeString & msg);
+	void OnPinWrap (const CTypeBool & msg);
+	void OnPinTranspose (const CTypeInt & msg);
+
+	void ProcessPointerUpdate (float pointer);
+	int Pointer2Index (float pointer);
+	void StopAllNotes();
+	void PlayChord(Chord const& chord);
+	void StopChord(Chord const& chord);
+
+	//
+	// Input pin classes
+	//
+	class InputPinPointer : public spcore::CInputPinWriteOnly<CTypeFloat, ScorePlayerComponent> {
+	public:
+		InputPinPointer (ScorePlayerComponent & component)
+		: CInputPinWriteOnly<CTypeFloat, ScorePlayerComponent>("pointer", component) { }
+
+		virtual int DoSend(const CTypeFloat & msg) {
+			m_component->OnPinPointer(msg);
+			return 0;
+		}
+	};
+
+	class InputPinProgress : public spcore::CInputPinWriteOnly<CTypeFloat, ScorePlayerComponent> {
+	public:
+		InputPinProgress (ScorePlayerComponent & component)
+		: CInputPinWriteOnly<CTypeFloat, ScorePlayerComponent>("progress", component) { }
+
+		virtual int DoSend(const CTypeFloat & msg) {
+			m_component->OnPinProgress(msg);
+			return 0;
+		}
+	};
+
+	class InputPinVolume : public spcore::CInputPinWriteOnly<CTypeInt, ScorePlayerComponent> {
+	public:
+		InputPinVolume (ScorePlayerComponent & component)
+		: CInputPinWriteOnly<CTypeInt, ScorePlayerComponent>("volume", component) { }
+
+		virtual int DoSend(const CTypeInt & msg) {
+			m_component->OnPinVolume(msg);
+			return 0;
+		}
+	};
+
+	class InputPinInstrument : public spcore::CInputPinWriteOnly<CTypeInt, ScorePlayerComponent> {
+	public:
+		InputPinInstrument (ScorePlayerComponent & component)
+		: CInputPinWriteOnly<CTypeInt, ScorePlayerComponent>("instrument", component) { }
+
+		virtual int DoSend(const CTypeInt & msg) {
+			m_component->OnPinInstrument(msg);
+			return 0;
+		}
+	};
+
+	class InputPinDuration : public spcore::CInputPinWriteOnly<CTypeInt, ScorePlayerComponent> {
+	public:
+		InputPinDuration (ScorePlayerComponent & component)
+		: CInputPinWriteOnly<CTypeInt, ScorePlayerComponent>("duration", component) { }
+
+		virtual int DoSend(const CTypeInt & msg) {
+			m_component->OnPinDuration(msg);
+			return 0;
+		}
+	};
+
+	class InputPinScore : public spcore::CInputPinWriteOnly<CTypeString, ScorePlayerComponent> {
+	public:
+		InputPinScore (ScorePlayerComponent & component)
+		: CInputPinWriteOnly<CTypeString, ScorePlayerComponent>("score", component) { }
+
+		virtual int DoSend(const CTypeString & msg) {
+			m_component->OnPinScore(msg);
+			return 0;
+		}
+	};
+
+	class InputPinWrap : public spcore::CInputPinWriteOnly<CTypeBool, ScorePlayerComponent> {
+	public:
+		InputPinWrap (ScorePlayerComponent & component)
+		: CInputPinWriteOnly<CTypeBool, ScorePlayerComponent>("wrap", component) { }
+
+		virtual int DoSend(const CTypeBool & msg) {
+			m_component->OnPinWrap(msg);
+			return 0;
+		}
+	};
+
+	class InputPinTranspose : public spcore::CInputPinWriteOnly<CTypeInt, ScorePlayerComponent> {
+	public:
+		InputPinTranspose (ScorePlayerComponent & component)
+		: CInputPinWriteOnly<CTypeInt, ScorePlayerComponent>("transpose", component) { }
+
+		virtual int DoSend(const CTypeInt & msg) {
+			m_component->OnPinTranspose(msg);
+			return 0;
+		}
+	};
+};
+
+typedef ComponentFactory<ScorePlayerComponent> ScorePlayerFactory;
+
+};
+
+#endif
diff --git a/src/mod_sdl/CMakeLists.txt b/src/mod_sdl/CMakeLists.txt
new file mode 100755
index 0000000..3e667a7
--- /dev/null
+++ b/src/mod_sdl/CMakeLists.txt
@@ -0,0 +1,54 @@
+cmake_minimum_required(VERSION 2.6)
+project(mod_sdl)
+
+set (SDL_BUILDING_LIBRARY ON)
+find_package ( SDL REQUIRED )
+
+set(mod_sdl_SRCS
+	${CUSTOM_INCLUDE_PATH}/mod_sdl/sdlsurfacetype.h
+	mod_sdl.cpp
+)
+
+set(mod_sdl_gui_SRCS
+	config_gui.h
+	config_gui.cpp
+)
+
+include_directories (${SDL_INCLUDE_DIR})
+
+# Base library
+add_library (mod_sdl MODULE ${mod_sdl_SRCS})
+target_link_libraries(mod_sdl spcore)
+target_link_libraries(mod_sdl ${SDL_LIBRARY})
+
+# Base gui library
+add_library (mod_sdl_gui MODULE ${mod_sdl_gui_SRCS})
+target_link_libraries(mod_sdl_gui spcore)
+target_link_libraries(mod_sdl_gui ${wxWidgets_LIBRARIES})
+
+IF(BUILD_TESTS)
+	ADD_SUBDIRECTORY(tests)
+ENDIF(BUILD_TESTS)
+
+install (FILES ${CUSTOM_INCLUDE_PATH}/mod_sdl/sdlsurfacetype.h DESTINATION ${INCLUDEDIR}/${PROJECT_NAME})
+INSTALL (TARGETS mod_sdl RUNTIME DESTINATION ${LIBRUNTIMEDIR} LIBRARY DESTINATION ${PLUGINDIR})
+
+IF (WIN32)
+	FIND_PATH (SDL_RUNTIME_LIBS_DIR SDL.dll
+		HINTS
+		$ENV{SDLDIR}
+		PATH_SUFFIXES lib64 lib
+		PATHS)
+	FILE (GLOB SDL_RUNTIME_LIBS ${SDL_RUNTIME_LIBS_DIR}/*.dll)
+	
+	if (MSVC)
+		foreach(_BUILD_TYPE ${CMAKE_CONFIGURATION_TYPES})
+			foreach(_SDL_RUNTIME_LIB ${SDL_RUNTIME_LIBS})
+				configure_file("${_SDL_RUNTIME_LIB}" "${RUNTIME_OUTPUT_DIRECTORY}/${_BUILD_TYPE}" COPYONLY)
+			endforeach(_SDL_RUNTIME_LIB ${SDL_RUNTIME_LIBS})
+		endforeach(_BUILD_TYPE ${CMAKE_CONFIGURATION_TYPES})
+	endif(MSVC)
+	
+	INSTALL (PROGRAMS ${SDL_RUNTIME_LIBS} DESTINATION ${LIBRUNTIMEDIR})
+ENDIF (WIN32)
+
diff --git a/src/mod_sdl/config_gui.cpp b/src/mod_sdl/config_gui.cpp
new file mode 100644
index 0000000..1475710
--- /dev/null
+++ b/src/mod_sdl/config_gui.cpp
@@ -0,0 +1,312 @@
+/////////////////////////////////////////////////////////////////////////////
+// Name:        sdlconfiguration.cpp
+// Purpose:
+// Author:      C�sar Mauri Loba
+// Modified by:
+// Created:     09/01/2011 03:25:06
+// RCS-ID:
+// Copyright:   (c) 2011 C�sar Mauri Loba
+// Licence:
+//  This program is free software: you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation, either version 3 of the License, or
+//  (at your option) any later version.
+//
+//  This program is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with this program.  If not, see <http://www.gnu.org/licenses/>
+/////////////////////////////////////////////////////////////////////////////
+
+// For compilers that support precompilation, includes "wx/wx.h".
+#include "wx/wxprec.h"
+
+#ifdef __BORLANDC__
+#pragma hdrstop
+#endif
+
+#ifndef WX_PRECOMP
+#include "wx/wx.h"
+#endif
+
+////@begin includes
+////@end includes
+
+#include "config_gui.h"
+#include "spcore/coreruntime.h"
+#include "spcore/component.h"
+#include "spcore/module.h"
+#include "spcore/pin.h"
+#include "spcore/basictypes.h"
+using namespace spcore;
+
+////@begin XPM images
+////@end XPM images
+
+
+/*
+ * SDLConfigurationGUI type definition
+ */
+
+IMPLEMENT_DYNAMIC_CLASS( SDLConfigurationGUI, wxPanel )
+
+
+/*
+ * SDLConfigurationGUI event table definition
+ */
+
+BEGIN_EVENT_TABLE( SDLConfigurationGUI, wxPanel )
+
+////@begin SDLConfigurationGUI event table entries
+    EVT_INIT_DIALOG( SDLConfigurationGUI::OnInitDialog )
+
+    EVT_BUTTON( wxID_CANCEL, SDLConfigurationGUI::OnCancelClick )
+
+////@end SDLConfigurationGUI event table entries
+
+END_EVENT_TABLE()
+
+
+/*
+ * SDLConfigurationGUI constructors
+ */
+
+SDLConfigurationGUI::SDLConfigurationGUI()
+{
+    Init();
+}
+
+SDLConfigurationGUI::SDLConfigurationGUI( wxWindow* parent, wxWindowID id, const wxString& caption, const wxPoint& pos, const wxSize& size, long style )
+{
+    Init();
+    Create(parent, id, caption, pos, size, style);
+}
+
+
+/*
+ * SDLConfiguration creator
+ */
+
+bool SDLConfigurationGUI::Create( wxWindow* parent, wxWindowID id, const wxString& caption, const wxPoint& pos, const wxSize& size, long style )
+{
+////@begin SDLConfigurationGUI creation
+    SetExtraStyle(wxWS_EX_BLOCK_EVENTS);
+    wxPanel::Create( parent, id, pos, size, style );
+
+    CreateControls();
+    if (GetSizer())
+    {
+        GetSizer()->SetSizeHints(this);
+    }
+    Centre();
+////@end SDLConfigurationGUI creation
+    return true;
+}
+
+
+/*
+ * SDLConfigurationGUI destructor
+ */
+
+SDLConfigurationGUI::~SDLConfigurationGUI()
+{
+////@begin SDLConfigurationGUI destruction
+////@end SDLConfigurationGUI destruction
+}
+
+
+/*
+ * Member initialisation
+ */
+
+void SDLConfigurationGUI::Init()
+{
+////@begin SDLConfigurationGUI member initialisation
+    m_txtWidth = NULL;
+    m_txtHeight = NULL;
+    m_chkFullscreen = NULL;
+////@end SDLConfigurationGUI member initialisation
+}
+
+
+/*
+ * Control creation for SDLConfiguration
+ */
+
+void SDLConfigurationGUI::CreateControls()
+{
+////@begin SDLConfigurationGUI content construction
+    SDLConfigurationGUI* itemPanel1 = this;
+
+    wxBoxSizer* itemBoxSizer2 = new wxBoxSizer(wxVERTICAL);
+    itemPanel1->SetSizer(itemBoxSizer2);
+
+    wxFlexGridSizer* itemFlexGridSizer3 = new wxFlexGridSizer(0, 2, 0, 0);
+    itemBoxSizer2->Add(itemFlexGridSizer3, 0, wxALIGN_CENTER_HORIZONTAL|wxALL, 5);
+
+    wxStaticText* itemStaticText4 = new wxStaticText( itemPanel1, wxID_STATIC, _("Width:"), wxDefaultPosition, wxDefaultSize, 0 );
+    itemFlexGridSizer3->Add(itemStaticText4, 0, wxALIGN_LEFT|wxALIGN_CENTER_VERTICAL|wxALL, 5);
+
+    m_txtWidth = new wxTextCtrl( itemPanel1, ID_TEXTCTRL, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 );
+    m_txtWidth->SetMaxLength(4);
+    itemFlexGridSizer3->Add(m_txtWidth, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL|wxALL, 5);
+
+    wxStaticText* itemStaticText6 = new wxStaticText( itemPanel1, wxID_STATIC, _("Height:"), wxDefaultPosition, wxDefaultSize, 0 );
+    itemFlexGridSizer3->Add(itemStaticText6, 0, wxALIGN_LEFT|wxALIGN_CENTER_VERTICAL|wxALL, 5);
+
+    m_txtHeight = new wxTextCtrl( itemPanel1, ID_TEXTCTRL1, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 );
+    m_txtHeight->SetMaxLength(4);
+    itemFlexGridSizer3->Add(m_txtHeight, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL|wxALL, 5);
+
+    wxStaticText* itemStaticText8 = new wxStaticText( itemPanel1, wxID_STATIC, _("Full screen:"), wxDefaultPosition, wxDefaultSize, 0 );
+    itemFlexGridSizer3->Add(itemStaticText8, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL|wxALL, 5);
+
+    m_chkFullscreen = new wxCheckBox( itemPanel1, ID_CHECKBOX, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 );
+    m_chkFullscreen->SetValue(false);
+    itemFlexGridSizer3->Add(m_chkFullscreen, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL|wxALL, 5);
+
+    wxStdDialogButtonSizer* itemStdDialogButtonSizer10 = new wxStdDialogButtonSizer;
+
+    itemBoxSizer2->Add(itemStdDialogButtonSizer10, 0, wxALIGN_CENTER_HORIZONTAL|wxALL, 5);
+    wxButton* itemButton11 = new wxButton( itemPanel1, wxID_OK, _("&OK"), wxDefaultPosition, wxDefaultSize, 0 );
+    itemStdDialogButtonSizer10->AddButton(itemButton11);
+
+    wxButton* itemButton12 = new wxButton( itemPanel1, wxID_CANCEL, _("&Cancel"), wxDefaultPosition, wxDefaultSize, 0 );
+    itemStdDialogButtonSizer10->AddButton(itemButton12);
+
+    itemStdDialogButtonSizer10->Realize();
+
+////@end SDLConfigurationGUI content construction
+}
+
+
+/*
+ * Should we show tooltips?
+ */
+
+bool SDLConfigurationGUI::ShowToolTips()
+{
+    return true;
+}
+
+/*
+ * Get bitmap resources
+ */
+
+wxBitmap SDLConfigurationGUI::GetBitmapResource( const wxString& name )
+{
+    // Bitmap retrieval
+////@begin SDLConfigurationGUI bitmap retrieval
+    wxUnusedVar(name);
+    return wxNullBitmap;
+////@end SDLConfigurationGUI bitmap retrieval
+}
+
+/*
+ * Get icon resources
+ */
+
+wxIcon SDLConfigurationGUI::GetIconResource( const wxString& name )
+{
+    // Icon retrieval
+////@begin SDLConfigurationGUI icon retrieval
+    wxUnusedVar(name);
+    return wxNullIcon;
+////@end SDLConfigurationGUI icon retrieval
+}
+
+
+/*
+ * wxEVT_INIT_DIALOG event handler for ID_SDLCONFIGURATION
+ */
+
+
+void SDLConfigurationGUI::OnInitDialog( wxInitDialogEvent& event )
+{
+    spcore::ICoreRuntime* cr= spcore::getSpCoreRuntime();
+	SmartPtr<IComponent> cfgCompo= cr->CreateComponent("sdl_config", "sdl_config", 0, NULL);
+	if (!cfgCompo.get()) {
+		wxMessageDialog dlg(this, _("SDL Configuration error: cannot create sdl_config component"));
+		dlg.ShowModal();
+	}
+	else {
+		// Update gui controls
+		IInputPin* ipin= IComponent::FindInputPin(*cfgCompo, "width");
+		assert (ipin);
+		SmartPtr<const CTypeInt> width= sptype_dynamic_cast<const CTypeInt>(ipin->Read());
+		assert (width.get());
+		m_txtWidth->SetValue (wxString::Format(_T("%d"), width->getValue()));
+
+		ipin= IComponent::FindInputPin(*cfgCompo, "height");
+		assert (ipin);
+		SmartPtr<const CTypeInt> height= sptype_dynamic_cast<const CTypeInt>(ipin->Read());
+		assert (height.get());
+		m_txtHeight->SetValue (wxString::Format(_T("%d"), height->getValue()));
+
+		ipin= IComponent::FindInputPin(*cfgCompo, "fullscreen");
+		assert (ipin);
+		SmartPtr<const CTypeBool> fullscreen= sptype_dynamic_cast<const CTypeBool>(ipin->Read());
+		assert (fullscreen.get());
+		m_chkFullscreen->SetValue(fullscreen->getValue());
+	}
+
+    event.Skip(false);
+}
+
+/*
+	SDLConfigGUI
+
+	GUI support for SDLConfig
+
+	This module only provides a pannel to set up SDL parameters
+*/
+class CSDLConfigGUIComp : public CComponentAdapter {
+public:
+	CSDLConfigGUIComp(const char * name, int argc, const char * argv[]) 
+	: CComponentAdapter(name, argc, argv) {}
+
+	static const char* getTypeName() { return "sdl_config_gui"; };
+	virtual const char* GetTypeName() const { return CSDLConfigGUIComp::getTypeName(); };
+
+	virtual wxWindow* GetGUI(wxWindow* parent) {
+		return new SDLConfigurationGUI(parent);
+	}
+
+private:
+	~CSDLConfigGUIComp() {
+	}
+};
+
+
+/**
+	Module
+*/
+class CSDLConfigGUIModule : public spcore::CModuleAdapter {
+public:
+	CSDLConfigGUIModule() {
+		RegisterComponentFactory(SmartPtr<spcore::IComponentFactory>(new ComponentFactory<CSDLConfigGUIComp>(), false));
+	}
+	virtual const char * GetName() const { return "sdl_config_gui"; }
+};
+
+static spcore::IModule* g_module= NULL;
+SPEXPORT_FUNCTION spcore::IModule* module_create_instance()
+{
+	if (g_module== NULL) g_module= new CSDLConfigGUIModule();
+	return g_module;
+}
+
+
+/*
+ * wxEVT_COMMAND_BUTTON_CLICKED event handler for wxID_CANCEL
+ */
+
+void SDLConfigurationGUI::OnCancelClick( wxCommandEvent& event )
+{
+    Close();
+    event.Skip(false);
+}
+
diff --git a/src/mod_sdl/config_gui.h b/src/mod_sdl/config_gui.h
new file mode 100644
index 0000000..41ceaf5
--- /dev/null
+++ b/src/mod_sdl/config_gui.h
@@ -0,0 +1,115 @@
+/////////////////////////////////////////////////////////////////////////////
+// Name:        sdlconfiguration.h
+// Purpose:     
+// Author:      C�sar Mauri Loba
+// Modified by: 
+// Created:     09/01/2011 03:25:06
+// RCS-ID:      
+// Copyright:   (c) 2011 C�sar Mauri Loba
+// Licence: 
+//  This program is free software: you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation, either version 3 of the License, or
+//  (at your option) any later version.
+//
+//  This program is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with this program.  If not, see <http://www.gnu.org/licenses/>
+/////////////////////////////////////////////////////////////////////////////
+
+#ifndef _SDLCONFIGURATION_H_
+#define _SDLCONFIGURATION_H_
+
+
+/*!
+ * Includes
+ */
+
+////@begin includes
+////@end includes
+
+/*!
+ * Forward declarations
+ */
+
+////@begin forward declarations
+////@end forward declarations
+
+/*!
+ * Control identifiers
+ */
+
+////@begin control identifiers
+#define ID_SDLCONFIGURATION 10002
+#define ID_TEXTCTRL 10000
+#define ID_TEXTCTRL1 10001
+#define ID_CHECKBOX 10003
+#define SYMBOL_SDLCONFIGURATIONGUI_STYLE wxCAPTION|wxRESIZE_BORDER|wxSYSTEM_MENU|wxCLOSE_BOX|wxTAB_TRAVERSAL
+#define SYMBOL_SDLCONFIGURATIONGUI_TITLE _("SDL Configuration")
+#define SYMBOL_SDLCONFIGURATIONGUI_IDNAME ID_SDLCONFIGURATION
+#define SYMBOL_SDLCONFIGURATIONGUI_SIZE wxSize(400, 300)
+#define SYMBOL_SDLCONFIGURATIONGUI_POSITION wxDefaultPosition
+////@end control identifiers
+
+
+/*!
+ * SDLConfigurationGUI class declaration
+ */
+
+class SDLConfigurationGUI: public wxPanel
+{    
+    DECLARE_DYNAMIC_CLASS( SDLConfigurationGUI )
+    DECLARE_EVENT_TABLE()
+
+public:
+    /// Constructors
+    SDLConfigurationGUI();
+    SDLConfigurationGUI( wxWindow* parent, wxWindowID id = SYMBOL_SDLCONFIGURATIONGUI_IDNAME, const wxString& caption = SYMBOL_SDLCONFIGURATIONGUI_TITLE, const wxPoint& pos = SYMBOL_SDLCONFIGURATIONGUI_POSITION, const wxSize& size = SYMBOL_SDLCONFIGURATIONGUI_SIZE, long style = SYMBOL_SDLCONFIGURATIONGUI_STYLE );
+
+    /// Creation
+    bool Create( wxWindow* parent, wxWindowID id = SYMBOL_SDLCONFIGURATIONGUI_IDNAME, const wxString& caption = SYMBOL_SDLCONFIGURATIONGUI_TITLE, const wxPoint& pos = SYMBOL_SDLCONFIGURATIONGUI_POSITION, const wxSize& size = SYMBOL_SDLCONFIGURATIONGUI_SIZE, long style = SYMBOL_SDLCONFIGURATIONGUI_STYLE );
+
+    /// Destructor
+    ~SDLConfigurationGUI();
+
+    /// Initialises member variables
+    void Init();
+
+    /// Creates the controls and sizers
+    void CreateControls();
+
+////@begin SDLConfigurationGUI event handler declarations
+
+    /// wxEVT_INIT_DIALOG event handler for ID_SDLCONFIGURATION
+    void OnInitDialog( wxInitDialogEvent& event );
+
+    /// wxEVT_COMMAND_BUTTON_CLICKED event handler for wxID_CANCEL
+    void OnCancelClick( wxCommandEvent& event );
+
+////@end SDLConfigurationGUI event handler declarations
+
+////@begin SDLConfigurationGUI member function declarations
+
+    /// Retrieves bitmap resources
+    wxBitmap GetBitmapResource( const wxString& name );
+
+    /// Retrieves icon resources
+    wxIcon GetIconResource( const wxString& name );
+////@end SDLConfigurationGUI member function declarations
+
+    /// Should we show tooltips?
+    static bool ShowToolTips();
+
+////@begin SDLConfigurationGUI member variables
+    wxTextCtrl* m_txtWidth;
+    wxTextCtrl* m_txtHeight;
+    wxCheckBox* m_chkFullscreen;
+////@end SDLConfigurationGUI member variables
+};
+
+#endif
+    // _SDLCONFIGURATION_H_
diff --git a/src/mod_sdl/mod_sdl.cpp b/src/mod_sdl/mod_sdl.cpp
new file mode 100644
index 0000000..0aea34c
--- /dev/null
+++ b/src/mod_sdl/mod_sdl.cpp
@@ -0,0 +1,383 @@
+/////////////////////////////////////////////////////////////////////////////
+// File:        mod_sdl.cpp
+// Author:      Cesar Mauri Loba (cesar at crea-si dot com)
+// Copyright:   (C) 2010 Cesar Mauri Loba - CREA Software Systems
+//
+//  This program is free software: you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation, either version 3 of the License, or
+//  (at your option) any later version.
+//
+//  This program is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+/////////////////////////////////////////////////////////////////////////////
+#include "spcore/basictypes.h"
+#include "spcore/pin.h"
+#include "spcore/component.h"
+#include "spcore/libimpexp.h"
+#include "mod_sdl/sdlsurfacetype.h"
+
+#ifdef WIN32
+#include "windows.h"
+#endif
+
+using namespace spcore;
+using namespace std;
+
+namespace mod_sdl {
+
+/*
+	sdl_config component (singleton)
+
+	Components that provides global SDL Video initialization and
+	termination and allows to store the configuration parameters.
+
+	Input pins:
+		width (int, rw)
+		heiht (int, rw)
+		fullscreen (int, rw)
+
+	Output pins:
+
+	Command line:
+*/
+class SDLConfig : public CComponentAdapter
+{
+public:
+	static const char* getTypeName() { return "sdl_config"; }
+	virtual const char* GetTypeName() const { return SDLConfig::getTypeName(); }
+	
+	SDLConfig(const char * name, int argc, const char * argv[]) 
+	: CComponentAdapter(name, argc, argv) 
+	, m_fullscreen(false)
+	, m_existsDrawer(false)
+	, m_width(640)
+	, m_height(480)	
+	{
+		assert (getSpCoreRuntime()->IsMainThread());
+		if (!getSpCoreRuntime()->IsMainThread())
+			throw std::runtime_error("attempting to initialize sdl_config from other thread than the main one");
+		
+		RegisterInputPin (*SmartPtr<IInputPin>(new InputPinWidth(*this), false));
+		RegisterInputPin (*SmartPtr<IInputPin>(new InputPinHeight(*this), false));
+		RegisterInputPin (*SmartPtr<IInputPin>(new InputPinFullscreen(*this), false));
+
+		if (SDL_Init(SDL_INIT_NOPARACHUTE)== -1) 
+			throw std::runtime_error(SDL_GetError());
+
+#ifdef WIN32
+		/* Sam:
+		   We still need to pass in the application handle so that
+		   DirectInput will initialize properly when SDL_RegisterApp()
+		   is called later in the video initialization.
+		 */
+		HMODULE handle= GetModuleHandle(NULL);
+		SDL_SetModuleHandle(handle);
+#endif
+	}
+
+	//
+	// Convenience methods for drawers
+	//
+
+	// Methods to make sure there is only one drawer
+	bool ExistsDrawer(bool exists) { 
+		bool retval= m_existsDrawer;
+		m_existsDrawer= exists;
+		return retval;
+	}
+
+	int GetWidth() const { return m_width; }
+	int GetHeight() const { return m_height; }
+	
+	// Copy not allowed
+	SDLConfig(const SDLConfig &);
+	SDLConfig operator= (const SDLConfig &);
+
+private:
+	virtual ~SDLConfig() {
+		SDL_Quit();
+	}
+
+	bool m_fullscreen;
+	bool m_existsDrawer;
+	int m_width;
+	int m_height;
+	
+
+	class InputPinWidth : public CInputPinReadWrite<CTypeInt, SDLConfig> {
+	public:
+		InputPinWidth (SDLConfig & component) : CInputPinReadWrite<CTypeInt, SDLConfig>("width", component) {}
+		virtual int DoSend(const CTypeInt & message) {
+			if (message.getValue()> 0) {
+				m_component->m_width= message.getValue();
+				return 0;
+			}
+			return -1;
+		}
+		virtual SmartPtr<CTypeInt> DoRead() const {
+			SmartPtr<CTypeInt> retval= CTypeInt::CreateInstance();
+			retval->setValue(m_component->m_width);
+			return retval;
+		}
+	};
+
+	class InputPinHeight : public CInputPinReadWrite<CTypeInt, SDLConfig> {
+	public:
+		InputPinHeight (SDLConfig & component) : CInputPinReadWrite<CTypeInt, SDLConfig>("height", component) {}
+		virtual int DoSend(const CTypeInt & message) {
+			if (message.getValue()> 0) {
+				m_component->m_height= message.getValue();
+				return 0;
+			}
+			return -1;
+		}
+		virtual SmartPtr<CTypeInt> DoRead() const {
+			SmartPtr<CTypeInt> retval= CTypeInt::CreateInstance();
+			retval->setValue(m_component->m_height);
+			return retval;
+		}
+	};
+
+	class InputPinFullscreen : public CInputPinReadWrite<CTypeBool, SDLConfig> {
+	public:
+		InputPinFullscreen (SDLConfig & component) : CInputPinReadWrite<CTypeBool, SDLConfig>("fullscreen", component) {}
+		virtual int DoSend(const CTypeBool & message) {
+			m_component->m_fullscreen= message.getValue();
+			return 0;
+		}
+		virtual SmartPtr<CTypeBool> DoRead() const {
+			SmartPtr<CTypeBool> retval =CTypeBool::CreateInstance();
+			retval->setValue(m_component->m_fullscreen);
+			return retval;
+		}
+	};
+};
+
+typedef SingletonComponentFactory<SDLConfig> SDLConfigFactory;
+
+/**
+	sdl_drawer component
+
+	Input pins:
+		- draw (any)
+
+		Used to trigger the drawing routine. It draws and but NOT releases all queued 
+		surfaces since last "do_draw". If the object passed to this pin is an 
+		"sdl_surface" it is also drawn BEFORE the queued ones (as background).
+	
+		- queue (sdl_surface)
+
+		adds a surface to the queue
+
+	Output pins:
+	Command line:
+	Comments:
+		
+*/
+class SDLDrawer : public CComponentAdapter {
+public:
+	static const char* getTypeName() { return "sdl_drawer"; };
+	virtual const char* GetTypeName() const { return SDLDrawer::getTypeName(); };
+
+	SDLDrawer(const char * name, int argc, const char * argv[])
+	: CComponentAdapter(name, argc, argv) 
+	, m_frameBuffer(NULL)	
+	{
+		assert (getSpCoreRuntime()->IsMainThread());
+		if (!getSpCoreRuntime()->IsMainThread())
+			throw std::runtime_error("attempting to initialize sdl_drawer from other thread than the main one");
+
+		// Store a pointer to the (single) sdl config component
+		SmartPtr<IComponent> configComponent= getSpCoreRuntime()->CreateComponent("sdl_config", "", 0, NULL);
+		assert (configComponent.get());
+		m_sdlConfig= SmartPtr<SDLConfig>(static_cast<SDLConfig*> (configComponent.get()));
+		assert (m_sdlConfig.get());
+
+		// and check that this is the only one drawer present within the system	
+		if (m_sdlConfig->ExistsDrawer(true)) 
+			throw std::runtime_error(string("Cannot create drawer ") + name + ". Another drawer exists.");
+		
+		// now comes SDL Video stuff
+		if (SDL_WasInit(SDL_INIT_VIDEO)) {
+			// Another component is not playing nice and decided to init SDL
+			// by its own or indirectly by calling some SDL function.
+
+			//
+			// NOTE to SDL based components implementors. Remember that you component
+			// should NEVER initialize the SDL library nor use any SDL function BEFORE
+			// the method Initialize gets called and AFTER the method Finish gets called.
+			// You MUST implement both methods. Moreover, your Finish() method MUST 
+			// free all SDL related resources otherwise a crash is almost guaranteed. Finally 
+			// remember to be aware of calls before Initialize is called.
+			//			
+			assert (false);	// Read above
+
+			throw std::runtime_error("SDL library was previously initialized/used");
+		}
+
+		// Finaly set video mode and open SDL window
+		m_frameBuffer= SDL_SetVideoMode(m_sdlConfig->GetWidth(), m_sdlConfig->GetHeight(), 0, DRAWER_SDL_FLAGS);
+		if (!m_frameBuffer) {
+			assert (false);
+			m_sdlConfig->ExistsDrawer(false);
+			throw std::runtime_error("SDL_SetVideoMode failed!");
+		}
+		
+		RegisterInputPin (*SmartPtr<InputPinDoDraw>(new InputPinDoDraw("draw", *this), false));
+		RegisterInputPin (*SmartPtr<InputPinQueue>(new InputPinQueue("queue", *this), false));
+	}
+
+private:
+	enum { DRAWER_SDL_FLAGS= SDL_HWSURFACE | SDL_DOUBLEBUF | SDL_RESIZABLE };
+
+	SDL_Surface* m_frameBuffer;
+	vector<SmartPtr<const CTypeSDLSurface> > m_surfaceQueue;
+	SmartPtr<SDLConfig> m_sdlConfig;
+
+	~SDLDrawer() {
+		SDL_QuitSubSystem(SDL_INIT_VIDEO);
+		m_sdlConfig->ExistsDrawer(false);
+		assert (!IsInitialized());
+		if (IsInitialized())
+			getSpCoreRuntime()->LogMessage(ICoreRuntime::LOG_WARNING,
+				"destroyed uninitialized", SDLDrawer::getTypeName());
+	}
+
+	bool SanityCheck() {
+		if (!getSpCoreRuntime()->IsMainThread()) {
+			// Messages should come only from the main thread
+			assert (false);
+			getSpCoreRuntime()->LogMessage(ICoreRuntime::LOG_ERROR, 
+				"received message from other thread other than the main one", SDLDrawer::getTypeName());
+			return false;
+		}
+		if (!IsInitialized()) {
+			// Message received before initialitzation completed
+			// This could happen if the component which calls us has been initialized
+			// before than us. This message could have been generated as part of the initialization
+			// proces but not as a result of runing the entire graph, so we issue a warning and
+			// ignore the message
+			getSpCoreRuntime()->LogMessage(ICoreRuntime::LOG_WARNING,
+				"ignored message because component is not initialized", SDLDrawer::getTypeName());
+			return false;
+		}
+		return true;
+	}
+
+	int Queue (const CTypeSDLSurface& message) {
+		if (!SanityCheck()) return -1;
+		m_surfaceQueue.push_back (SmartPtr<const CTypeSDLSurface>(&message));
+		return 0;
+	}
+
+	inline
+	void DrawSurface (const CTypeSDLSurface& s) {
+		SDL_Rect position;
+		
+		position.x= s.getX();
+		position.y= s.getY();
+		// Cast away constantness (needed to call C API, hope surface isn't modified)
+		// TODO: currently return value is not checked
+		SDL_BlitSurface( const_cast<SDL_Surface*>(s.getSurface()), NULL, m_frameBuffer, &position);
+	}
+
+	int DrawBuffers (const CTypeAny & message) {
+		if (!SanityCheck()) return -1;
+
+		// Time to draw everything
+
+		// Clear background
+		if (SDL_MUSTLOCK(m_frameBuffer))
+			SDL_LockSurface(m_frameBuffer);
+		SDL_FillRect(m_frameBuffer, NULL, 0);
+
+		// IF draw message contains a surface use it as background
+		if (message.GetTypeID()== CTypeSDLSurface::getTypeID()) 		
+			DrawSurface (*sptype_static_cast<CTypeSDLSurface>(&message));
+		
+		// Finaly blit each queued surface
+		vector<SmartPtr<const CTypeSDLSurface> >::iterator it= m_surfaceQueue.begin();
+		for (;it!= m_surfaceQueue.end(); ++it) DrawSurface (**it);		
+
+		// Flip buffers
+		SDL_Flip(m_frameBuffer);
+		if (SDL_MUSTLOCK(m_frameBuffer))
+			SDL_UnlockSurface(m_frameBuffer);
+
+		// Clear queue
+		m_surfaceQueue.clear();
+
+		// Process SDL events
+		SDL_Event event; 
+		memset(&event, 0, sizeof(event));
+		while(SDL_PollEvent(&event)) {  
+			// Loop until there are no events left on the queue 
+			switch(event.type)
+			{ 
+			case SDL_VIDEORESIZE:  
+				m_frameBuffer= SDL_SetVideoMode(event.resize.w, event.resize.h, 0, DRAWER_SDL_FLAGS);
+				assert (m_frameBuffer);
+				break;
+			// Ignore SDL window close
+			//case SDL_QUIT:
+			//	return false;
+			}
+		}
+		return 0;
+	}
+
+	class InputPinDoDraw : public CInputPinWriteOnly<CTypeAny, SDLDrawer> {
+	public:
+		InputPinDoDraw (const char * name, SDLDrawer & component) : CInputPinWriteOnly<CTypeAny, SDLDrawer>(name, component) {}
+		virtual int DoSend(const CTypeAny & message) {
+			return m_component->DrawBuffers(message);
+		}
+	};
+
+	class InputPinQueue : public CInputPinWriteOnly<CTypeSDLSurface, SDLDrawer> {
+	public:
+		InputPinQueue (const char * name, SDLDrawer & component) : CInputPinWriteOnly<CTypeSDLSurface, SDLDrawer>(name, component) {}
+		virtual int DoSend(const CTypeSDLSurface & message) {			
+			return m_component->Queue (message);
+		}
+	};
+};
+
+typedef ComponentFactory<SDLDrawer> SDLDrawerFactory;
+
+/*
+	Type CTypeSDLSurface factory class
+*/
+typedef SimpleTypeFactory<CTypeSDLSurface> CTypeSDLSurfaceFactory;
+
+
+/**
+	mod_sdl module
+*/
+class SDLBaseModule : public spcore::CModuleAdapter {
+public:
+	SDLBaseModule() {
+		// Types
+		RegisterTypeFactory(SmartPtr<spcore::ITypeFactory>(new CTypeSDLSurfaceFactory(), false));
+		// Components
+		RegisterComponentFactory(SmartPtr<spcore::IComponentFactory>(new SDLDrawerFactory(), false));
+		RegisterComponentFactory(SmartPtr<spcore::IComponentFactory>(new SDLConfigFactory(), false));
+	}
+	virtual const char * GetName() const { return "mod_sdl"; }
+};
+
+static spcore::IModule* g_module= NULL;
+SPEXPORT_FUNCTION spcore::IModule* module_create_instance()
+{
+	if (g_module== NULL) g_module= new SDLBaseModule();
+	return g_module;
+}
+
+}
+
diff --git a/src/mod_sdl/sdl_config_gui.pjd b/src/mod_sdl/sdl_config_gui.pjd
new file mode 100644
index 0000000..a5fd59d
--- /dev/null
+++ b/src/mod_sdl/sdl_config_gui.pjd
@@ -0,0 +1,967 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<anthemion-project version="1.0.0.0" xmlns="http://www.anthemion.co.uk">
+  <header>
+    <long name="name_counter">0</long>
+    <string name="html_path">""</string>
+    <string name="title">""</string>
+    <string name="author">""</string>
+    <string name="description">""</string>
+    <string name="xrc_filename">""</string>
+    <long name="image_mode">0</long>
+    <bool name="inline_images">0</bool>
+    <bool name="generate_cpp_for_xrc">0</bool>
+    <long name="working_mode">1</long>
+    <bool name="use_help_text_for_tooltips">1</bool>
+    <bool name="translate_strings">1</bool>
+    <bool name="make_unicode_strings">1</bool>
+    <bool name="extract_strings">0</bool>
+    <string name="user_name">"César Mauri Loba"</string>
+    <string name="copyright_string">"3DB07020-865C504F-B8F7B01B"</string>
+    <string name="resource_prefix">""</string>
+    <bool name="use_two_step_construction">0</bool>
+    <bool name="use_enums">0</bool>
+    <bool name="generate_for_xrced">0</bool>
+    <bool name="generate_virtual_eventhandlers">0</bool>
+    <string name="current_platform">"<All platforms>"</string>
+    <string name="target_wx_version">"2.8.7"</string>
+    <string name="app_kind">"Standard"</string>
+    <string name="cpp_header_comment">"/////////////////////////////////////////////////////////////////////////////
+// Name:        %HEADER-FILENAME%
+// Purpose:     
+// Author:      %AUTHOR%
+// Modified by: 
+// Created:     %DATE%
+// RCS-ID:      
+// Copyright:   %COPYRIGHT%
+// Licence:     
+/////////////////////////////////////////////////////////////////////////////
+
+"</string>
+    <string name="cpp_implementation_comment">"/////////////////////////////////////////////////////////////////////////////
+// Name:        %SOURCE-FILENAME%
+// Purpose:     
+// Author:      %AUTHOR%
+// Modified by: 
+// Created:     %DATE%
+// RCS-ID:      
+// Copyright:   %COPYRIGHT%
+// Licence:     
+/////////////////////////////////////////////////////////////////////////////
+
+"</string>
+    <string name="cpp_symbols_file_comment">"/////////////////////////////////////////////////////////////////////////////
+// Name:        %SYMBOLS-FILENAME%
+// Purpose:     Symbols file
+// Author:      %AUTHOR%
+// Modified by: 
+// Created:     %DATE%
+// RCS-ID:      
+// Copyright:   %COPYRIGHT%
+// Licence:     
+/////////////////////////////////////////////////////////////////////////////
+
+"</string>
+    <string name="cpp_header_preamble">""</string>
+    <string name="cpp_implementation_preamble">"// For compilers that support precompilation, includes "wx/wx.h".
+#include "wx/wxprec.h"
+
+#ifdef __BORLANDC__
+#pragma hdrstop
+#endif
+
+#ifndef WX_PRECOMP
+#include "wx/wx.h"
+#endif
+
+"</string>
+    <string name="cpp_function_declaration_comment">"	/// %BODY%
+"</string>
+    <string name="cpp_function_implementation_comment">"
+/*
+ * %BODY%
+ */
+
+"</string>
+    <string name="resource_file_header">"app_resources.h"</string>
+    <string name="resource_file_implementation">"app_resources.cpp"</string>
+    <string name="resource_class_name">"AppResources"</string>
+    <string name="app_file_header">"app.h"</string>
+    <string name="app_file_implementation">"app.cpp"</string>
+    <string name="app_class_name">"Application"</string>
+    <bool name="generate_app_class">0</bool>
+    <string name="external_symbol_filenames">""</string>
+    <string name="configuration">"<None>"</string>
+    <string name="source_encoding">"iso-8859-1"</string>
+    <string name="xrc_encoding">"utf-8"</string>
+    <string name="project_encoding">"utf-8"</string>
+    <string name="resource_archive">""</string>
+    <long name="text_file_type">1</long>
+    <bool name="use_tabs">0</bool>
+    <long name="indent_size">4</long>
+    <string name="whitespace_after_return_type">" "</string>
+    <string name="resource_xrc_cpp">""</string>
+    <bool name="use_resource_archive">0</bool>
+    <bool name="use_generated_xrc_cpp">0</bool>
+    <bool name="always_generate_xrc">1</bool>
+    <bool name="use_id_name_for_name">0</bool>
+    <bool name="archive_xrc_files">1</bool>
+    <bool name="archive_image_files">1</bool>
+    <bool name="archive_all_image_files">0</bool>
+    <bool name="xrc_retain_relative_paths">1</bool>
+    <bool name="xrc_generate_id_tags">0</bool>
+    <bool name="xrc_use_name_property">0</bool>
+  </header>
+  <data>
+    <document>
+      <string name="title">""</string>
+      <string name="type">"data-document"</string>
+      <string name="filename">""</string>
+      <string name="icon-name">""</string>
+      <long name="is-transient">0</long>
+      <long name="owns-file">1</long>
+      <long name="title-mode">0</long>
+      <long name="locked">0</long>
+      <document>
+        <string name="title">"Configurations"</string>
+        <string name="type">"config-data-document"</string>
+        <string name="filename">""</string>
+        <string name="icon-name">""</string>
+        <long name="is-transient">0</long>
+        <long name="owns-file">1</long>
+        <long name="title-mode">0</long>
+        <long name="locked">0</long>
+        <string name="template-name">""</string>
+        <bool name="dirty">1</bool>
+        <long name="makefile-last-written">-8519680</long>
+        <string name="Compiler name">""</string>
+        <string name="Build mode">"Debug"</string>
+        <string name="Unicode mode">"Unicode"</string>
+        <string name="Shared mode">"Static"</string>
+        <string name="Modularity">"Modular"</string>
+        <string name="GUI mode">"GUI"</string>
+        <string name="Toolkit">"wxMSW"</string>
+        <string name="Processor type">"Default"</string>
+        <string name="Runtime linking">"Dynamic"</string>
+        <string name="Use exceptions">"Yes"</string>
+        <string name="Use ODBC">"No"</string>
+        <string name="Use XRC">"Yes"</string>
+        <string name="Use OpenGL">"No"</string>
+        <string name="Use wxMediaCtrl">"No"</string>
+        <string name="Use wxRichTextCtrl">"Yes"</string>
+        <string name="Use wxHTML">"Yes"</string>
+        <string name="Use wxPropertyGrid">"Yes"</string>
+        <string name="Use wxAUI">"Yes"</string>
+        <string name="Use wxSTC">"Yes"</string>
+        <string name="Use wxRibbonControl">"Yes"</string>
+        <string name="Executable name">"%EXECUTABLE%"</string>
+        <string name="Program arguments">""</string>
+        <string name="Working path">"%AUTO%"</string>
+        <string name="Output path">"%AUTO%"</string>
+        <string name="Objects path">"%AUTO%"</string>
+        <string name="Project makefile">"%AUTO%"</string>
+        <string name="wxWidgets version">"%WXVERSION%"</string>
+        <string name="wxWidgets makefile">"%AUTO%"</string>
+        <string name="wxWidgets location">"%AUTO%"</string>
+        <string name="wxWidgets build path">"%AUTO%"</string>
+        <string name="wxWidgets build command">"%AUTO%"</string>
+        <string name="wxWidgets clean command">"%AUTO%"</string>
+        <string name="CFG">""</string>
+        <string name="Compiler location">"%AUTO%"</string>
+        <string name="Compiler bin path">"%AUTO%"</string>
+        <string name="Compiler include path">"%AUTO%"</string>
+        <string name="Compiler lib path">"%AUTO%"</string>
+        <string name="PATH variable">"%AUTO%"</string>
+        <string name="C++ command">"%AUTO%"</string>
+        <string name="C command">"%AUTO%"</string>
+        <string name="Linker command">"%AUTO%"</string>
+        <string name="Resource compiler">"%AUTO%"</string>
+        <string name="Make command">"%AUTO%"</string>
+        <string name="Preprocessor flags">"%AUTO%"</string>
+        <string name="Optimizations">"%AUTO%"</string>
+        <string name="Warnings">"%AUTO%"</string>
+        <string name="Debug flags">"%AUTO%"</string>
+        <string name="Extra compile flags">"%AUTO%"</string>
+        <string name="Libraries">"%AUTO%"</string>
+        <string name="Library path">"%AUTO%"</string>
+        <string name="Linker flags">"%AUTO%"</string>
+        <string name="Include path">"%AUTO%"</string>
+        <string name="Resource flags">"%AUTO%"</string>
+        <string name="Resource path">"%AUTO%"</string>
+        <bool name="Suppress source rules">0</bool>
+        <bool name="Enable makefile generation">1</bool>
+      </document>
+    </document>
+  </data>
+
+  <documents>
+    <document>
+      <string name="title">"Projects"</string>
+      <string name="type">"root-document"</string>
+      <string name="filename">""</string>
+      <string name="icon-name">"project"</string>
+      <long name="is-transient">1</long>
+      <long name="owns-file">1</long>
+      <long name="title-mode">0</long>
+      <long name="locked">1</long>
+      <document>
+        <string name="title">"Windows"</string>
+        <string name="type">"html-document"</string>
+        <string name="filename">""</string>
+        <string name="icon-name">"dialogsfolder"</string>
+        <long name="is-transient">1</long>
+        <long name="owns-file">1</long>
+        <long name="title-mode">0</long>
+        <long name="locked">1</long>
+        <document>
+          <string name="title">"SDL Configuration"</string>
+          <string name="type">"dialog-document"</string>
+          <string name="filename">""</string>
+          <string name="icon-name">"dialog"</string>
+          <long name="is-transient">0</long>
+          <long name="owns-file">1</long>
+          <long name="title-mode">0</long>
+          <long name="locked">0</long>
+          <string name="proxy-type">"wbDialogProxy"</string>
+          <long name="base-id">10000</long>
+          <bool name="use-id-prefix">0</bool>
+          <string name="id-prefix">""</string>
+          <bool name="use-id-suffix">0</bool>
+          <string name="id-suffix">""</string>
+          <string name="app-kind">"Standard"</string>
+          <long name="use-xrc">0</long>
+          <long name="working-mode">0</long>
+          <string name="event-handler-0">"wxEVT_INIT_DIALOG|OnInitDialog|NONE||SDLConfigurationGUI"</string>
+          <string name="proxy-Id name">"ID_SDLCONFIGURATION"</string>
+          <long name="proxy-Id value">10002</long>
+          <string name="proxy-Class">"SDLConfigurationGUI"</string>
+          <string name="proxy-Base class">"wxPanel"</string>
+          <string name="proxy-Window kind">"wxPanel"</string>
+          <string name="proxy-Implementation filename">"config_gui.cpp"</string>
+          <string name="proxy-Header filename">"config_gui.h"</string>
+          <string name="proxy-XRC filename">""</string>
+          <string name="proxy-Title">"SDL Configuration"</string>
+          <bool name="proxy-Centre">1</bool>
+          <string name="proxy-Icon">""</string>
+          <bool name="proxy-Dialog units">0</bool>
+          <string name="proxy-Help text">""</string>
+          <string name="proxy-Tooltip text">""</string>
+          <string name="proxy-Background colour">""</string>
+          <string name="proxy-Foreground colour">""</string>
+          <string name="proxy-Font">""</string>
+          <bool name="proxy-Hidden">0</bool>
+          <bool name="proxy-Enabled">1</bool>
+          <string name="proxy-Platform">"<Any platform>"</string>
+          <string name="proxy-Data source">""</string>
+          <string name="proxy-Data class name">""</string>
+          <string name="proxy-Data class implementation filename">""</string>
+          <string name="proxy-Data class header filename">""</string>
+          <string name="proxy-Data class manager window">""</string>
+          <string name="proxy-Texture">""</string>
+          <string name="proxy-Texture style">"Tiled"</string>
+          <bool name="proxy-wxDEFAULT_DIALOG_STYLE">0</bool>
+          <bool name="proxy-wxCAPTION">1</bool>
+          <bool name="proxy-wxRESIZE_BORDER">1</bool>
+          <bool name="proxy-wxSYSTEM_MENU">1</bool>
+          <bool name="proxy-wxSTAY_ON_TOP">0</bool>
+          <bool name="proxy-wxDIALOG_NO_PARENT">0</bool>
+          <bool name="proxy-wxCLOSE_BOX">1</bool>
+          <bool name="proxy-wxMAXIMIZE_BOX">0</bool>
+          <bool name="proxy-wxMINIMIZE_BOX">0</bool>
+          <bool name="proxy-wxDIALOG_MODAL">1</bool>
+          <bool name="proxy-wxNO_BORDER">0</bool>
+          <bool name="proxy-wxSIMPLE_BORDER">0</bool>
+          <bool name="proxy-wxDOUBLE_BORDER">0</bool>
+          <bool name="proxy-wxBORDER_THEME">0</bool>
+          <bool name="proxy-wxSUNKEN_BORDER">0</bool>
+          <bool name="proxy-wxRAISED_BORDER">0</bool>
+          <bool name="proxy-wxSTATIC_BORDER">0</bool>
+          <bool name="proxy-wxWANTS_CHARS">0</bool>
+          <bool name="proxy-wxNO_FULL_REPAINT_ON_RESIZE">0</bool>
+          <bool name="proxy-wxFULL_REPAINT_ON_RESIZE">0</bool>
+          <bool name="proxy-wxCLIP_CHILDREN">0</bool>
+          <bool name="proxy-wxTAB_TRAVERSAL">1</bool>
+          <bool name="proxy-wxWS_EX_VALIDATE_RECURSIVELY">0</bool>
+          <bool name="proxy-wxWS_EX_BLOCK_EVENTS">1</bool>
+          <bool name="proxy-wxWS_EX_TRANSIENT">0</bool>
+          <string name="proxy-Custom styles">""</string>
+          <bool name="proxy-wxDIALOG_EX_CONTEXTHELP">0</bool>
+          <bool name="proxy-Fit to content">1</bool>
+          <long name="proxy-X">-1</long>
+          <long name="proxy-Y">-1</long>
+          <long name="proxy-Width">400</long>
+          <long name="proxy-Height">300</long>
+          <bool name="proxy-AUI manager">0</bool>
+          <string name="proxy-Event sources">""</string>
+          <document>
+            <string name="title">"wxBoxSizer V"</string>
+            <string name="type">"dialog-control-document"</string>
+            <string name="filename">""</string>
+            <string name="icon-name">"sizer"</string>
+            <long name="is-transient">0</long>
+            <long name="owns-file">1</long>
+            <long name="title-mode">0</long>
+            <long name="locked">0</long>
+            <string name="proxy-type">"wbBoxSizerProxy"</string>
+            <string name="proxy-Orientation">"Vertical"</string>
+            <string name="proxy-Member variable name">""</string>
+            <bool name="proxy-wxSHAPED">0</bool>
+            <bool name="proxy-wxADJUST_MINSIZE">0</bool>
+            <bool name="proxy-wxFIXED_MINSIZE">0</bool>
+            <string name="proxy-Platform">"<Any platform>"</string>
+            <document>
+              <string name="title">"wxFlexGridSizer"</string>
+              <string name="type">"dialog-control-document"</string>
+              <string name="filename">""</string>
+              <string name="icon-name">"sizer"</string>
+              <long name="is-transient">0</long>
+              <long name="owns-file">1</long>
+              <long name="title-mode">0</long>
+              <long name="locked">0</long>
+              <string name="proxy-type">"wbFlexGridSizerProxy"</string>
+              <string name="proxy-GrowableColumns">""</string>
+              <string name="proxy-GrowableRows">""</string>
+              <long name="proxy-Columns">2</long>
+              <long name="proxy-Rows">0</long>
+              <long name="proxy-ColumnSpacing">0</long>
+              <long name="proxy-RowSpacing">0</long>
+              <string name="proxy-Member variable name">""</string>
+              <string name="proxy-Platform">"<Any platform>"</string>
+              <string name="proxy-AlignH">"Centre"</string>
+              <string name="proxy-AlignV">"Centre"</string>
+              <long name="proxy-Stretch factor">0</long>
+              <long name="proxy-Border">5</long>
+              <bool name="proxy-wxLEFT">1</bool>
+              <bool name="proxy-wxRIGHT">1</bool>
+              <bool name="proxy-wxTOP">1</bool>
+              <bool name="proxy-wxBOTTOM">1</bool>
+              <bool name="proxy-wxSHAPED">0</bool>
+              <bool name="proxy-wxADJUST_MINSIZE">0</bool>
+              <bool name="proxy-wxFIXED_MINSIZE">0</bool>
+              <document>
+                <string name="title">"wxStaticText: wxID_STATIC"</string>
+                <string name="type">"dialog-control-document"</string>
+                <string name="filename">""</string>
+                <string name="icon-name">"statictext"</string>
+                <long name="is-transient">0</long>
+                <long name="owns-file">1</long>
+                <long name="title-mode">0</long>
+                <long name="locked">0</long>
+                <string name="proxy-type">"wbStaticTextProxy"</string>
+                <string name="proxy-Id name">"wxID_STATIC"</string>
+                <long name="proxy-Id value">5105</long>
+                <string name="proxy-Name">""</string>
+                <string name="proxy-Class">"wxStaticText"</string>
+                <string name="proxy-Base class">"wxStaticText"</string>
+                <bool name="proxy-External implementation">1</bool>
+                <bool name="proxy-Separate files">0</bool>
+                <string name="proxy-Implementation filename">""</string>
+                <string name="proxy-Header filename">""</string>
+                <string name="proxy-Member variable name">""</string>
+                <string name="proxy-Label">"Width:"</string>
+                <long name="proxy-Wrapping width">-1</long>
+                <string name="proxy-Help text">""</string>
+                <string name="proxy-Tooltip text">""</string>
+                <string name="proxy-Background colour">""</string>
+                <string name="proxy-Foreground colour">""</string>
+                <string name="proxy-Font">""</string>
+                <bool name="proxy-Hidden">0</bool>
+                <bool name="proxy-Enabled">1</bool>
+                <string name="proxy-Platform">"<Any platform>"</string>
+                <string name="proxy-Data variable">""</string>
+                <string name="proxy-Data validator">""</string>
+                <string name="proxy-Data source">""</string>
+                <string name="proxy-Data class name">""</string>
+                <string name="proxy-Data class implementation filename">""</string>
+                <string name="proxy-Data class header filename">""</string>
+                <string name="proxy-Data class manager window">""</string>
+                <bool name="proxy-wxALIGN_LEFT">0</bool>
+                <bool name="proxy-wxALIGN_RIGHT">0</bool>
+                <bool name="proxy-wxALIGN_CENTRE">0</bool>
+                <bool name="proxy-wxST_NO_AUTORESIZE">0</bool>
+                <bool name="proxy-wxNO_BORDER">0</bool>
+                <bool name="proxy-wxSIMPLE_BORDER">0</bool>
+                <bool name="proxy-wxDOUBLE_BORDER">0</bool>
+                <bool name="proxy-wxBORDER_THEME">0</bool>
+                <bool name="proxy-wxSUNKEN_BORDER">0</bool>
+                <bool name="proxy-wxRAISED_BORDER">0</bool>
+                <bool name="proxy-wxSTATIC_BORDER">0</bool>
+                <bool name="proxy-wxWANTS_CHARS">0</bool>
+                <bool name="proxy-wxNO_FULL_REPAINT_ON_RESIZE">0</bool>
+                <bool name="proxy-wxFULL_REPAINT_ON_RESIZE">0</bool>
+                <string name="proxy-Custom styles">""</string>
+                <long name="proxy-X">-1</long>
+                <long name="proxy-Y">-1</long>
+                <long name="proxy-Width">-1</long>
+                <long name="proxy-Height">-1</long>
+                <string name="proxy-AlignH">"Left"</string>
+                <string name="proxy-AlignV">"Centre"</string>
+                <long name="proxy-Stretch factor">0</long>
+                <long name="proxy-Border">5</long>
+                <bool name="proxy-wxLEFT">1</bool>
+                <bool name="proxy-wxRIGHT">1</bool>
+                <bool name="proxy-wxTOP">1</bool>
+                <bool name="proxy-wxBOTTOM">1</bool>
+                <bool name="proxy-wxSHAPED">0</bool>
+                <bool name="proxy-wxADJUST_MINSIZE">0</bool>
+                <bool name="proxy-wxFIXED_MINSIZE">0</bool>
+                <string name="proxy-Custom arguments">""</string>
+                <string name="proxy-Custom ctor arguments">""</string>
+              </document>
+              <document>
+                <string name="title">"wxTextCtrl: ID_TEXTCTRL"</string>
+                <string name="type">"dialog-control-document"</string>
+                <string name="filename">""</string>
+                <string name="icon-name">"textctrl"</string>
+                <long name="is-transient">0</long>
+                <long name="owns-file">1</long>
+                <long name="title-mode">0</long>
+                <long name="locked">0</long>
+                <string name="proxy-type">"wbTextCtrlProxy"</string>
+                <string name="proxy-Id name">"ID_TEXTCTRL"</string>
+                <long name="proxy-Id value">10000</long>
+                <string name="proxy-Name">""</string>
+                <string name="proxy-Class">"wxTextCtrl"</string>
+                <string name="proxy-Base class">"wxTextCtrl"</string>
+                <bool name="proxy-External implementation">1</bool>
+                <bool name="proxy-Separate files">0</bool>
+                <string name="proxy-Implementation filename">""</string>
+                <string name="proxy-Header filename">""</string>
+                <string name="proxy-Member variable name">"m_txtWidth"</string>
+                <string name="proxy-Initial value">""</string>
+                <long name="proxy-Max length">4</long>
+                <string name="proxy-Help text">""</string>
+                <string name="proxy-Tooltip text">""</string>
+                <string name="proxy-Background colour">""</string>
+                <string name="proxy-Foreground colour">""</string>
+                <string name="proxy-Font">""</string>
+                <bool name="proxy-Hidden">0</bool>
+                <bool name="proxy-Enabled">1</bool>
+                <string name="proxy-Platform">"<Any platform>"</string>
+                <string name="proxy-Data variable">""</string>
+                <string name="proxy-Data validator">""</string>
+                <string name="proxy-Data source">""</string>
+                <string name="proxy-Data class name">""</string>
+                <string name="proxy-Data class implementation filename">""</string>
+                <string name="proxy-Data class header filename">""</string>
+                <string name="proxy-Data class manager window">""</string>
+                <bool name="proxy-wxTE_MULTILINE">0</bool>
+                <bool name="proxy-wxTE_PROCESS_ENTER">0</bool>
+                <bool name="proxy-wxTE_PROCESS_TAB">0</bool>
+                <bool name="proxy-wxTE_PASSWORD">0</bool>
+                <bool name="proxy-wxTE_READONLY">0</bool>
+                <bool name="proxy-wxTE_RICH">0</bool>
+                <bool name="proxy-wxTE_RICH2">0</bool>
+                <bool name="proxy-wxTE_AUTO_URL">0</bool>
+                <bool name="proxy-wxTE_NOHIDESEL">0</bool>
+                <bool name="proxy-wxTE_LEFT">0</bool>
+                <bool name="proxy-wxTE_CENTRE">0</bool>
+                <bool name="proxy-wxTE_RIGHT">0</bool>
+                <bool name="proxy-wxHSCROLL">0</bool>
+                <bool name="proxy-wxTE_CHARWRAP">0</bool>
+                <bool name="proxy-wxTE_WORDWRAP">0</bool>
+                <bool name="proxy-wxTE_CAPITALIZE">0</bool>
+                <bool name="proxy-wxNO_BORDER">0</bool>
+                <bool name="proxy-wxSIMPLE_BORDER">0</bool>
+                <bool name="proxy-wxDOUBLE_BORDER">0</bool>
+                <bool name="proxy-wxBORDER_THEME">0</bool>
+                <bool name="proxy-wxSUNKEN_BORDER">0</bool>
+                <bool name="proxy-wxRAISED_BORDER">0</bool>
+                <bool name="proxy-wxSTATIC_BORDER">0</bool>
+                <bool name="proxy-wxWANTS_CHARS">0</bool>
+                <bool name="proxy-wxNO_FULL_REPAINT_ON_RESIZE">0</bool>
+                <bool name="proxy-wxFULL_REPAINT_ON_RESIZE">0</bool>
+                <string name="proxy-Custom styles">""</string>
+                <long name="proxy-X">-1</long>
+                <long name="proxy-Y">-1</long>
+                <long name="proxy-Width">-1</long>
+                <long name="proxy-Height">-1</long>
+                <string name="proxy-AlignH">"Centre"</string>
+                <string name="proxy-AlignV">"Centre"</string>
+                <long name="proxy-Stretch factor">0</long>
+                <long name="proxy-Border">5</long>
+                <bool name="proxy-wxLEFT">1</bool>
+                <bool name="proxy-wxRIGHT">1</bool>
+                <bool name="proxy-wxTOP">1</bool>
+                <bool name="proxy-wxBOTTOM">1</bool>
+                <bool name="proxy-wxSHAPED">0</bool>
+                <bool name="proxy-wxADJUST_MINSIZE">0</bool>
+                <bool name="proxy-wxFIXED_MINSIZE">0</bool>
+                <string name="proxy-Custom arguments">""</string>
+                <string name="proxy-Custom ctor arguments">""</string>
+              </document>
+              <document>
+                <string name="title">"wxStaticText: wxID_STATIC"</string>
+                <string name="type">"dialog-control-document"</string>
+                <string name="filename">""</string>
+                <string name="icon-name">"statictext"</string>
+                <long name="is-transient">0</long>
+                <long name="owns-file">1</long>
+                <long name="title-mode">0</long>
+                <long name="locked">0</long>
+                <string name="proxy-type">"wbStaticTextProxy"</string>
+                <string name="proxy-Id name">"wxID_STATIC"</string>
+                <long name="proxy-Id value">5105</long>
+                <string name="proxy-Name">""</string>
+                <string name="proxy-Class">"wxStaticText"</string>
+                <string name="proxy-Base class">"wxStaticText"</string>
+                <bool name="proxy-External implementation">1</bool>
+                <bool name="proxy-Separate files">0</bool>
+                <string name="proxy-Implementation filename">""</string>
+                <string name="proxy-Header filename">""</string>
+                <string name="proxy-Member variable name">""</string>
+                <string name="proxy-Label">"Height:"</string>
+                <long name="proxy-Wrapping width">-1</long>
+                <string name="proxy-Help text">""</string>
+                <string name="proxy-Tooltip text">""</string>
+                <string name="proxy-Background colour">""</string>
+                <string name="proxy-Foreground colour">""</string>
+                <string name="proxy-Font">""</string>
+                <bool name="proxy-Hidden">0</bool>
+                <bool name="proxy-Enabled">1</bool>
+                <string name="proxy-Platform">"<Any platform>"</string>
+                <string name="proxy-Data variable">""</string>
+                <string name="proxy-Data validator">""</string>
+                <string name="proxy-Data source">""</string>
+                <string name="proxy-Data class name">""</string>
+                <string name="proxy-Data class implementation filename">""</string>
+                <string name="proxy-Data class header filename">""</string>
+                <string name="proxy-Data class manager window">""</string>
+                <bool name="proxy-wxALIGN_LEFT">0</bool>
+                <bool name="proxy-wxALIGN_RIGHT">0</bool>
+                <bool name="proxy-wxALIGN_CENTRE">0</bool>
+                <bool name="proxy-wxST_NO_AUTORESIZE">0</bool>
+                <bool name="proxy-wxNO_BORDER">0</bool>
+                <bool name="proxy-wxSIMPLE_BORDER">0</bool>
+                <bool name="proxy-wxDOUBLE_BORDER">0</bool>
+                <bool name="proxy-wxBORDER_THEME">0</bool>
+                <bool name="proxy-wxSUNKEN_BORDER">0</bool>
+                <bool name="proxy-wxRAISED_BORDER">0</bool>
+                <bool name="proxy-wxSTATIC_BORDER">0</bool>
+                <bool name="proxy-wxWANTS_CHARS">0</bool>
+                <bool name="proxy-wxNO_FULL_REPAINT_ON_RESIZE">0</bool>
+                <bool name="proxy-wxFULL_REPAINT_ON_RESIZE">0</bool>
+                <string name="proxy-Custom styles">""</string>
+                <long name="proxy-X">-1</long>
+                <long name="proxy-Y">-1</long>
+                <long name="proxy-Width">-1</long>
+                <long name="proxy-Height">-1</long>
+                <string name="proxy-AlignH">"Left"</string>
+                <string name="proxy-AlignV">"Centre"</string>
+                <long name="proxy-Stretch factor">0</long>
+                <long name="proxy-Border">5</long>
+                <bool name="proxy-wxLEFT">1</bool>
+                <bool name="proxy-wxRIGHT">1</bool>
+                <bool name="proxy-wxTOP">1</bool>
+                <bool name="proxy-wxBOTTOM">1</bool>
+                <bool name="proxy-wxSHAPED">0</bool>
+                <bool name="proxy-wxADJUST_MINSIZE">0</bool>
+                <bool name="proxy-wxFIXED_MINSIZE">0</bool>
+                <string name="proxy-Custom arguments">""</string>
+                <string name="proxy-Custom ctor arguments">""</string>
+              </document>
+              <document>
+                <string name="title">"wxTextCtrl: ID_TEXTCTRL1"</string>
+                <string name="type">"dialog-control-document"</string>
+                <string name="filename">""</string>
+                <string name="icon-name">"textctrl"</string>
+                <long name="is-transient">0</long>
+                <long name="owns-file">1</long>
+                <long name="title-mode">0</long>
+                <long name="locked">0</long>
+                <string name="proxy-type">"wbTextCtrlProxy"</string>
+                <string name="proxy-Id name">"ID_TEXTCTRL1"</string>
+                <long name="proxy-Id value">10001</long>
+                <string name="proxy-Name">""</string>
+                <string name="proxy-Class">"wxTextCtrl"</string>
+                <string name="proxy-Base class">"wxTextCtrl"</string>
+                <bool name="proxy-External implementation">1</bool>
+                <bool name="proxy-Separate files">0</bool>
+                <string name="proxy-Implementation filename">""</string>
+                <string name="proxy-Header filename">""</string>
+                <string name="proxy-Member variable name">"m_txtHeight"</string>
+                <string name="proxy-Initial value">""</string>
+                <long name="proxy-Max length">4</long>
+                <string name="proxy-Help text">""</string>
+                <string name="proxy-Tooltip text">""</string>
+                <string name="proxy-Background colour">""</string>
+                <string name="proxy-Foreground colour">""</string>
+                <string name="proxy-Font">""</string>
+                <bool name="proxy-Hidden">0</bool>
+                <bool name="proxy-Enabled">1</bool>
+                <string name="proxy-Platform">"<Any platform>"</string>
+                <string name="proxy-Data variable">""</string>
+                <string name="proxy-Data validator">""</string>
+                <string name="proxy-Data source">""</string>
+                <string name="proxy-Data class name">""</string>
+                <string name="proxy-Data class implementation filename">""</string>
+                <string name="proxy-Data class header filename">""</string>
+                <string name="proxy-Data class manager window">""</string>
+                <bool name="proxy-wxTE_MULTILINE">0</bool>
+                <bool name="proxy-wxTE_PROCESS_ENTER">0</bool>
+                <bool name="proxy-wxTE_PROCESS_TAB">0</bool>
+                <bool name="proxy-wxTE_PASSWORD">0</bool>
+                <bool name="proxy-wxTE_READONLY">0</bool>
+                <bool name="proxy-wxTE_RICH">0</bool>
+                <bool name="proxy-wxTE_RICH2">0</bool>
+                <bool name="proxy-wxTE_AUTO_URL">0</bool>
+                <bool name="proxy-wxTE_NOHIDESEL">0</bool>
+                <bool name="proxy-wxTE_LEFT">0</bool>
+                <bool name="proxy-wxTE_CENTRE">0</bool>
+                <bool name="proxy-wxTE_RIGHT">0</bool>
+                <bool name="proxy-wxHSCROLL">0</bool>
+                <bool name="proxy-wxTE_CHARWRAP">0</bool>
+                <bool name="proxy-wxTE_WORDWRAP">0</bool>
+                <bool name="proxy-wxTE_CAPITALIZE">0</bool>
+                <bool name="proxy-wxNO_BORDER">0</bool>
+                <bool name="proxy-wxSIMPLE_BORDER">0</bool>
+                <bool name="proxy-wxDOUBLE_BORDER">0</bool>
+                <bool name="proxy-wxBORDER_THEME">0</bool>
+                <bool name="proxy-wxSUNKEN_BORDER">0</bool>
+                <bool name="proxy-wxRAISED_BORDER">0</bool>
+                <bool name="proxy-wxSTATIC_BORDER">0</bool>
+                <bool name="proxy-wxWANTS_CHARS">0</bool>
+                <bool name="proxy-wxNO_FULL_REPAINT_ON_RESIZE">0</bool>
+                <bool name="proxy-wxFULL_REPAINT_ON_RESIZE">0</bool>
+                <string name="proxy-Custom styles">""</string>
+                <long name="proxy-X">-1</long>
+                <long name="proxy-Y">-1</long>
+                <long name="proxy-Width">-1</long>
+                <long name="proxy-Height">-1</long>
+                <string name="proxy-AlignH">"Centre"</string>
+                <string name="proxy-AlignV">"Centre"</string>
+                <long name="proxy-Stretch factor">0</long>
+                <long name="proxy-Border">5</long>
+                <bool name="proxy-wxLEFT">1</bool>
+                <bool name="proxy-wxRIGHT">1</bool>
+                <bool name="proxy-wxTOP">1</bool>
+                <bool name="proxy-wxBOTTOM">1</bool>
+                <bool name="proxy-wxSHAPED">0</bool>
+                <bool name="proxy-wxADJUST_MINSIZE">0</bool>
+                <bool name="proxy-wxFIXED_MINSIZE">0</bool>
+                <string name="proxy-Custom arguments">""</string>
+                <string name="proxy-Custom ctor arguments">""</string>
+              </document>
+              <document>
+                <string name="title">"wxStaticText: wxID_STATIC"</string>
+                <string name="type">"dialog-control-document"</string>
+                <string name="filename">""</string>
+                <string name="icon-name">"statictext"</string>
+                <long name="is-transient">0</long>
+                <long name="owns-file">1</long>
+                <long name="title-mode">0</long>
+                <long name="locked">0</long>
+                <string name="proxy-type">"wbStaticTextProxy"</string>
+                <string name="proxy-Id name">"wxID_STATIC"</string>
+                <long name="proxy-Id value">5105</long>
+                <string name="proxy-Name">""</string>
+                <string name="proxy-Class">"wxStaticText"</string>
+                <string name="proxy-Base class">"wxStaticText"</string>
+                <bool name="proxy-External implementation">1</bool>
+                <bool name="proxy-Separate files">0</bool>
+                <string name="proxy-Implementation filename">""</string>
+                <string name="proxy-Header filename">""</string>
+                <string name="proxy-Member variable name">""</string>
+                <string name="proxy-Label">"Full screen:"</string>
+                <long name="proxy-Wrapping width">-1</long>
+                <string name="proxy-Help text">""</string>
+                <string name="proxy-Tooltip text">""</string>
+                <string name="proxy-Background colour">""</string>
+                <string name="proxy-Foreground colour">""</string>
+                <string name="proxy-Font">""</string>
+                <bool name="proxy-Hidden">0</bool>
+                <bool name="proxy-Enabled">1</bool>
+                <string name="proxy-Platform">"<Any platform>"</string>
+                <string name="proxy-Data variable">""</string>
+                <string name="proxy-Data validator">""</string>
+                <string name="proxy-Data source">""</string>
+                <string name="proxy-Data class name">""</string>
+                <string name="proxy-Data class implementation filename">""</string>
+                <string name="proxy-Data class header filename">""</string>
+                <string name="proxy-Data class manager window">""</string>
+                <bool name="proxy-wxALIGN_LEFT">0</bool>
+                <bool name="proxy-wxALIGN_RIGHT">0</bool>
+                <bool name="proxy-wxALIGN_CENTRE">0</bool>
+                <bool name="proxy-wxST_NO_AUTORESIZE">0</bool>
+                <bool name="proxy-wxNO_BORDER">0</bool>
+                <bool name="proxy-wxSIMPLE_BORDER">0</bool>
+                <bool name="proxy-wxDOUBLE_BORDER">0</bool>
+                <bool name="proxy-wxBORDER_THEME">0</bool>
+                <bool name="proxy-wxSUNKEN_BORDER">0</bool>
+                <bool name="proxy-wxRAISED_BORDER">0</bool>
+                <bool name="proxy-wxSTATIC_BORDER">0</bool>
+                <bool name="proxy-wxWANTS_CHARS">0</bool>
+                <bool name="proxy-wxNO_FULL_REPAINT_ON_RESIZE">0</bool>
+                <bool name="proxy-wxFULL_REPAINT_ON_RESIZE">0</bool>
+                <string name="proxy-Custom styles">""</string>
+                <long name="proxy-X">-1</long>
+                <long name="proxy-Y">-1</long>
+                <long name="proxy-Width">-1</long>
+                <long name="proxy-Height">-1</long>
+                <string name="proxy-AlignH">"Centre"</string>
+                <string name="proxy-AlignV">"Centre"</string>
+                <long name="proxy-Stretch factor">0</long>
+                <long name="proxy-Border">5</long>
+                <bool name="proxy-wxLEFT">1</bool>
+                <bool name="proxy-wxRIGHT">1</bool>
+                <bool name="proxy-wxTOP">1</bool>
+                <bool name="proxy-wxBOTTOM">1</bool>
+                <bool name="proxy-wxSHAPED">0</bool>
+                <bool name="proxy-wxADJUST_MINSIZE">0</bool>
+                <bool name="proxy-wxFIXED_MINSIZE">0</bool>
+                <string name="proxy-Custom arguments">""</string>
+                <string name="proxy-Custom ctor arguments">""</string>
+              </document>
+              <document>
+                <string name="title">"wxCheckBox: ID_CHECKBOX"</string>
+                <string name="type">"dialog-control-document"</string>
+                <string name="filename">""</string>
+                <string name="icon-name">"checkbox"</string>
+                <long name="is-transient">0</long>
+                <long name="owns-file">1</long>
+                <long name="title-mode">0</long>
+                <long name="locked">0</long>
+                <string name="proxy-type">"wbCheckBoxProxy"</string>
+                <string name="proxy-Id name">"ID_CHECKBOX"</string>
+                <long name="proxy-Id value">10003</long>
+                <string name="proxy-Name">""</string>
+                <string name="proxy-Class">"wxCheckBox"</string>
+                <string name="proxy-Base class">"wxCheckBox"</string>
+                <bool name="proxy-External implementation">1</bool>
+                <bool name="proxy-Separate files">0</bool>
+                <string name="proxy-Implementation filename">""</string>
+                <string name="proxy-Header filename">""</string>
+                <string name="proxy-Member variable name">"m_chkFullscreen"</string>
+                <string name="proxy-Label">""</string>
+                <bool name="proxy-Initial value">0</bool>
+                <string name="proxy-Help text">""</string>
+                <string name="proxy-Tooltip text">""</string>
+                <string name="proxy-Data variable">""</string>
+                <string name="proxy-Data validator">""</string>
+                <string name="proxy-Data source">""</string>
+                <string name="proxy-Data class name">""</string>
+                <string name="proxy-Data class implementation filename">""</string>
+                <string name="proxy-Data class header filename">""</string>
+                <string name="proxy-Data class manager window">""</string>
+                <string name="proxy-Background colour">""</string>
+                <string name="proxy-Foreground colour">""</string>
+                <string name="proxy-Font">""</string>
+                <bool name="proxy-Hidden">0</bool>
+                <bool name="proxy-Enabled">1</bool>
+                <string name="proxy-Platform">"<Any platform>"</string>
+                <bool name="proxy-wxALIGN_RIGHT">0</bool>
+                <bool name="proxy-wxCHK_2STATE">0</bool>
+                <bool name="proxy-wxCHK_3STATE">0</bool>
+                <bool name="proxy-wxCHK_ALLOW_3RD_STATE_FOR_USER">0</bool>
+                <bool name="proxy-wxWANTS_CHARS">0</bool>
+                <bool name="proxy-wxNO_FULL_REPAINT_ON_RESIZE">0</bool>
+                <bool name="proxy-wxFULL_REPAINT_ON_RESIZE">0</bool>
+                <string name="proxy-Custom styles">""</string>
+                <long name="proxy-X">-1</long>
+                <long name="proxy-Y">-1</long>
+                <long name="proxy-Width">-1</long>
+                <long name="proxy-Height">-1</long>
+                <string name="proxy-AlignH">"Centre"</string>
+                <string name="proxy-AlignV">"Centre"</string>
+                <long name="proxy-Stretch factor">0</long>
+                <long name="proxy-Border">5</long>
+                <bool name="proxy-wxLEFT">1</bool>
+                <bool name="proxy-wxRIGHT">1</bool>
+                <bool name="proxy-wxTOP">1</bool>
+                <bool name="proxy-wxBOTTOM">1</bool>
+                <bool name="proxy-wxSHAPED">0</bool>
+                <bool name="proxy-wxADJUST_MINSIZE">0</bool>
+                <bool name="proxy-wxFIXED_MINSIZE">0</bool>
+                <string name="proxy-Custom arguments">""</string>
+                <string name="proxy-Custom ctor arguments">""</string>
+              </document>
+            </document>
+            <document>
+              <string name="title">"wxStdDialogButtonSizer"</string>
+              <string name="type">"dialog-control-document"</string>
+              <string name="filename">""</string>
+              <string name="icon-name">"sizer"</string>
+              <long name="is-transient">0</long>
+              <long name="owns-file">1</long>
+              <long name="title-mode">0</long>
+              <long name="locked">0</long>
+              <string name="proxy-type">"wbStdDialogButtonSizerProxy"</string>
+              <bool name="proxy-wxID_OK">1</bool>
+              <bool name="proxy-wxID_CANCEL">1</bool>
+              <bool name="proxy-wxID_YES">0</bool>
+              <bool name="proxy-wxID_NO">0</bool>
+              <bool name="proxy-wxID_HELP">0</bool>
+              <bool name="proxy-wxID_APPLY">0</bool>
+              <bool name="proxy-wxID_SAVE">0</bool>
+              <bool name="proxy-wxID_CONTEXT_HELP">0</bool>
+              <string name="proxy-Member variable name">""</string>
+              <string name="proxy-AlignH">"Centre"</string>
+              <string name="proxy-AlignV">"Centre"</string>
+              <long name="proxy-Stretch factor">0</long>
+              <long name="proxy-Border">5</long>
+              <bool name="proxy-wxLEFT">1</bool>
+              <bool name="proxy-wxRIGHT">1</bool>
+              <bool name="proxy-wxTOP">1</bool>
+              <bool name="proxy-wxBOTTOM">1</bool>
+              <bool name="proxy-wxSHAPED">0</bool>
+              <bool name="proxy-wxADJUST_MINSIZE">0</bool>
+              <bool name="proxy-wxFIXED_MINSIZE">0</bool>
+              <string name="proxy-Platform">"<Any platform>"</string>
+              <document>
+                <string name="title">"wxButton: wxID_OK"</string>
+                <string name="type">"dialog-control-document"</string>
+                <string name="filename">""</string>
+                <string name="icon-name">"dialogcontrol"</string>
+                <long name="is-transient">0</long>
+                <long name="owns-file">1</long>
+                <long name="title-mode">0</long>
+                <long name="locked">1</long>
+                <string name="proxy-type">"wbButtonProxy"</string>
+                <string name="proxy-Id name">"wxID_OK"</string>
+                <long name="proxy-Id value">5100</long>
+                <string name="proxy-Name">""</string>
+                <string name="proxy-Class">"wxButton"</string>
+                <string name="proxy-Base class">"wxButton"</string>
+                <bool name="proxy-External implementation">1</bool>
+                <bool name="proxy-Separate files">0</bool>
+                <string name="proxy-Implementation filename">""</string>
+                <string name="proxy-Header filename">""</string>
+                <string name="proxy-Member variable name">""</string>
+                <string name="proxy-Label">"&OK"</string>
+                <bool name="proxy-Default">0</bool>
+                <string name="proxy-Help text">""</string>
+                <string name="proxy-Tooltip text">""</string>
+                <string name="proxy-Data variable">""</string>
+                <string name="proxy-Data validator">""</string>
+                <string name="proxy-Data source">""</string>
+                <string name="proxy-Data class name">""</string>
+                <string name="proxy-Data class implementation filename">""</string>
+                <string name="proxy-Data class header filename">""</string>
+                <string name="proxy-Data class manager window">""</string>
+                <string name="proxy-Background colour">""</string>
+                <string name="proxy-Foreground colour">""</string>
+                <string name="proxy-Font">""</string>
+                <bool name="proxy-Hidden">0</bool>
+                <bool name="proxy-Enabled">1</bool>
+                <string name="proxy-Platform">"<Any platform>"</string>
+                <bool name="proxy-wxBU_LEFT">0</bool>
+                <bool name="proxy-wxBU_RIGHT">0</bool>
+                <bool name="proxy-wxBU_TOP">0</bool>
+                <bool name="proxy-wxBU_BOTTOM">0</bool>
+                <bool name="proxy-wxBU_EXACTFIT">0</bool>
+                <bool name="proxy-wxNO_BORDER">0</bool>
+                <bool name="proxy-wxWANTS_CHARS">0</bool>
+                <bool name="proxy-wxNO_FULL_REPAINT_ON_RESIZE">0</bool>
+                <bool name="proxy-wxFULL_REPAINT_ON_RESIZE">0</bool>
+                <string name="proxy-Custom styles">""</string>
+                <long name="proxy-X">-1</long>
+                <long name="proxy-Y">-1</long>
+                <long name="proxy-Width">-1</long>
+                <long name="proxy-Height">-1</long>
+                <string name="proxy-AlignH">"Centre"</string>
+                <string name="proxy-AlignV">"Centre"</string>
+                <long name="proxy-Stretch factor">0</long>
+                <long name="proxy-Border">5</long>
+                <bool name="proxy-wxLEFT">1</bool>
+                <bool name="proxy-wxRIGHT">1</bool>
+                <bool name="proxy-wxTOP">1</bool>
+                <bool name="proxy-wxBOTTOM">1</bool>
+                <bool name="proxy-wxSHAPED">0</bool>
+                <bool name="proxy-wxADJUST_MINSIZE">0</bool>
+                <bool name="proxy-wxFIXED_MINSIZE">0</bool>
+                <string name="proxy-Custom arguments">""</string>
+                <string name="proxy-Custom ctor arguments">""</string>
+              </document>
+              <document>
+                <string name="title">"wxButton: wxID_CANCEL"</string>
+                <string name="type">"dialog-control-document"</string>
+                <string name="filename">""</string>
+                <string name="icon-name">"dialogcontrol"</string>
+                <long name="is-transient">0</long>
+                <long name="owns-file">1</long>
+                <long name="title-mode">0</long>
+                <long name="locked">1</long>
+                <string name="proxy-type">"wbButtonProxy"</string>
+                <string name="event-handler-0">"wxEVT_COMMAND_BUTTON_CLICKED|OnCancelClick|NONE||SDLConfigurationGUI"</string>
+                <string name="proxy-Id name">"wxID_CANCEL"</string>
+                <long name="proxy-Id value">5101</long>
+                <string name="proxy-Name">""</string>
+                <string name="proxy-Class">"wxButton"</string>
+                <string name="proxy-Base class">"wxButton"</string>
+                <bool name="proxy-External implementation">1</bool>
+                <bool name="proxy-Separate files">0</bool>
+                <string name="proxy-Implementation filename">""</string>
+                <string name="proxy-Header filename">""</string>
+                <string name="proxy-Member variable name">""</string>
+                <string name="proxy-Label">"&Cancel"</string>
+                <bool name="proxy-Default">0</bool>
+                <string name="proxy-Help text">""</string>
+                <string name="proxy-Tooltip text">""</string>
+                <string name="proxy-Data variable">""</string>
+                <string name="proxy-Data validator">""</string>
+                <string name="proxy-Data source">""</string>
+                <string name="proxy-Data class name">""</string>
+                <string name="proxy-Data class implementation filename">""</string>
+                <string name="proxy-Data class header filename">""</string>
+                <string name="proxy-Data class manager window">""</string>
+                <string name="proxy-Background colour">""</string>
+                <string name="proxy-Foreground colour">""</string>
+                <string name="proxy-Font">""</string>
+                <bool name="proxy-Hidden">0</bool>
+                <bool name="proxy-Enabled">1</bool>
+                <string name="proxy-Platform">"<Any platform>"</string>
+                <bool name="proxy-wxBU_LEFT">0</bool>
+                <bool name="proxy-wxBU_RIGHT">0</bool>
+                <bool name="proxy-wxBU_TOP">0</bool>
+                <bool name="proxy-wxBU_BOTTOM">0</bool>
+                <bool name="proxy-wxBU_EXACTFIT">0</bool>
+                <bool name="proxy-wxNO_BORDER">0</bool>
+                <bool name="proxy-wxWANTS_CHARS">0</bool>
+                <bool name="proxy-wxNO_FULL_REPAINT_ON_RESIZE">0</bool>
+                <bool name="proxy-wxFULL_REPAINT_ON_RESIZE">0</bool>
+                <string name="proxy-Custom styles">""</string>
+                <long name="proxy-X">-1</long>
+                <long name="proxy-Y">-1</long>
+                <long name="proxy-Width">-1</long>
+                <long name="proxy-Height">-1</long>
+                <string name="proxy-AlignH">"Centre"</string>
+                <string name="proxy-AlignV">"Centre"</string>
+                <long name="proxy-Stretch factor">0</long>
+                <long name="proxy-Border">5</long>
+                <bool name="proxy-wxLEFT">1</bool>
+                <bool name="proxy-wxRIGHT">1</bool>
+                <bool name="proxy-wxTOP">1</bool>
+                <bool name="proxy-wxBOTTOM">1</bool>
+                <bool name="proxy-wxSHAPED">0</bool>
+                <bool name="proxy-wxADJUST_MINSIZE">0</bool>
+                <bool name="proxy-wxFIXED_MINSIZE">0</bool>
+                <string name="proxy-Custom arguments">""</string>
+                <string name="proxy-Custom ctor arguments">""</string>
+              </document>
+            </document>
+          </document>
+        </document>
+      </document>
+      <document>
+        <string name="title">"Sources"</string>
+        <string name="type">"html-document"</string>
+        <string name="filename">""</string>
+        <string name="icon-name">"sourcesfolder"</string>
+        <long name="is-transient">1</long>
+        <long name="owns-file">1</long>
+        <long name="title-mode">0</long>
+        <long name="locked">1</long>
+      </document>
+      <document>
+        <string name="title">"Images"</string>
+        <string name="type">"html-document"</string>
+        <string name="filename">""</string>
+        <string name="icon-name">"bitmapsfolder"</string>
+        <long name="is-transient">1</long>
+        <long name="owns-file">1</long>
+        <long name="title-mode">0</long>
+        <long name="locked">1</long>
+      </document>
+    </document>
+  </documents>
+
+</anthemion-project>
diff --git a/src/mod_sdl/tests/CMakeLists.txt b/src/mod_sdl/tests/CMakeLists.txt
new file mode 100755
index 0000000..429f39e
--- /dev/null
+++ b/src/mod_sdl/tests/CMakeLists.txt
@@ -0,0 +1,22 @@
+cmake_minimum_required(VERSION 2.8)
+project(mod_sdl_tests)
+
+add_executable(test_mod_sdl_loadlib test_mod_sdl_loadlib.cpp)
+target_link_libraries(test_mod_sdl_loadlib nvwa)
+target_link_libraries(test_mod_sdl_loadlib spcore)
+target_link_libraries(test_mod_sdl_loadlib sphost)
+add_test (NAME test_mod_sdl_loadlib COMMAND $<TARGET_FILE:nvwa_loader> $<TARGET_FILE:test_mod_sdl_loadlib>)
+
+add_executable(test_mod_sdl_drawer test_mod_sdl_drawer.cpp)
+target_link_libraries(test_mod_sdl_drawer nvwa)
+target_link_libraries(test_mod_sdl_drawer spcore)
+target_link_libraries(test_mod_sdl_drawer sphost)
+target_link_libraries(test_mod_sdl_drawer ${SDL_LIBRARY})
+add_test (NAME test_mod_sdl_drawer COMMAND $<TARGET_FILE:nvwa_loader> $<TARGET_FILE:test_mod_sdl_drawer>)
+
+add_executable(test_mod_sdl_gui test_mod_sdl_gui.cpp)
+target_link_libraries(test_mod_sdl_gui nvwa)
+target_link_libraries(test_mod_sdl_gui spcore)
+target_link_libraries(test_mod_sdl_gui sphost)
+target_link_libraries(test_mod_sdl_gui ${wxWidgets_LIBRARIES})
+add_test (NAME test_mod_sdl_gui COMMAND $<TARGET_FILE:nvwa_loader> $<TARGET_FILE:test_mod_sdl_gui>)
diff --git a/src/mod_sdl/tests/test_mod_sdl_drawer.cpp b/src/mod_sdl/tests/test_mod_sdl_drawer.cpp
new file mode 100644
index 0000000..7f22d7d
--- /dev/null
+++ b/src/mod_sdl/tests/test_mod_sdl_drawer.cpp
@@ -0,0 +1,85 @@
+#include "sphost/testcommon.h"
+#include "spcore/coreruntime.h"
+#include "mod_sdl/sdlsurfacetype.h"
+#include <boost/thread.hpp>
+#include <stdlib.h>
+
+using namespace spcore;
+using namespace mod_sdl;
+
+static int TestCreation()
+{
+	SmartPtr<IComponent> compo= getSpCoreRuntime()->CreateComponent ("sdl_drawer", "my_drawer", 0, NULL);
+	if (!compo.get())  ExitErr ("error creating sdl_drawer");
+	compo->Initialize();
+
+	if (compo->Initialize()) ExitErr ("A second Initialize should work");
+	SLEEP(2);
+
+	SmartPtr<IComponent> compo2= getSpCoreRuntime()->CreateComponent ("sdl_drawer", "my_drawer2", 0, NULL);
+	if (compo2.get()) ExitErr ("error 2nd sdl_drawer creation allowed");
+	compo->Finish();
+
+	return 0;
+}
+
+static void TestSimpleDraw ()
+{
+	// Create a drawer component
+	SmartPtr<IComponent> compo= getSpCoreRuntime()->CreateComponent ("sdl_drawer", "my_drawer", 0, NULL);
+	if (!compo.get()) ExitErr ("TestSimpleDraw: error creating sdl_drawer");
+	compo->Initialize();
+
+	const SDL_VideoInfo* vi= SDL_GetVideoInfo();
+	if (!vi) ExitErr ("SDL_GetVideoInfo() returned NULL");
+
+	SDL_Surface* mySurface= SDL_CreateRGBSurface(SDL_HWSURFACE, 300, 400, vi->vfmt->BitsPerPixel, 0,0,0,0);
+	if (mySurface== NULL) ExitErr(SDL_GetError());
+	SmartPtr<CTypeSDLSurface> sur= CTypeSDLSurface::CreateInstance();
+	sur->setSurface(mySurface);
+
+	// Draw some randow shapes
+	for (int i= 0; i< 10; ++i) {
+		SDL_Rect rect;
+		rect.x= rand() % 250;
+		rect.y= rand() % 350;
+		rect.w= rand() % 100;
+		rect.h= rand() % 150;
+
+		if (SDL_FillRect(mySurface, &rect, SDL_MapRGB(vi->vfmt, rand() % 256, rand() % 256, rand() % 256) ))
+			ExitErr(SDL_GetError());
+	}
+
+	// Display surface
+	IInputPin* drawPin= IComponent::FindInputPin(*compo, "draw");
+	if (!drawPin) ExitErr("input pin 'draw' not found");
+	drawPin->Send(sur);
+
+	SLEEP(2);
+
+	compo->Finish();
+}
+
+
+static void DoTests()
+{
+	// Initialization
+	spcore::ICoreRuntime* cr= spcore::getSpCoreRuntime();
+	assert (cr);
+
+	if (cr->LoadModule ("mod_sdl")< 0) exit(-1);
+
+	if (TestCreation()!= 0) exit (-1);
+
+	TestSimpleDraw ();
+}
+
+int main(int, char *[]) 
+{
+	DoTests();
+
+	// Cleanup
+	spcore::freeSpCoreRuntime();
+
+	return 0;
+}
diff --git a/src/mod_sdl/tests/test_mod_sdl_gui.cpp b/src/mod_sdl/tests/test_mod_sdl_gui.cpp
new file mode 100644
index 0000000..bd9bda1
--- /dev/null
+++ b/src/mod_sdl/tests/test_mod_sdl_gui.cpp
@@ -0,0 +1,227 @@
+/////////////////////////////////////////////////////////////////////////////
+// Name:        test_mod_sdl_gui.cpp
+// Author:      Cesar Mauri Loba
+// Copyright:   (C) 2011 Cesar Mauri Loba - CREA Software Systems
+//
+//  This program is free software: you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation, either version 3 of the License, or
+//  (at your option) any later version.
+//
+//  This program is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+/////////////////////////////////////////////////////////////////////////////
+
+
+#include "spcore/coreruntime.h"
+#include "sphost/testcommon.h"
+#include "nvwa/debug_new.h"
+
+#if defined(__WXGTK__) || defined(__WXMOTIF__) || defined(__WXX11__)
+	// Include Xlib for latter use on main
+	#include <X11/Xlib.h>
+#endif
+#include <wx/app.h>
+#include <wx/image.h>
+#include <wx/msgdlg.h>
+#include <wx/frame.h>
+#include <wx/panel.h>
+#include <wx/sizer.h>
+
+using namespace spcore;
+
+/*
+	Check threads enabled
+*/
+#if !wxUSE_THREADS
+     #error "This program requires thread support."
+#endif // wxUSE_THREADS
+
+/*
+	main app class
+*/
+class TestWXApp: public wxApp
+{
+	DECLARE_CLASS( TestWXApp )
+public:
+	TestWXApp();	// Constructor
+
+private:
+	virtual bool OnInit();	// Initialises the application
+	virtual int OnExit();	// Called on exit
+
+	SmartPtr<spcore::IComponent> m_comp;
+};
+
+/*
+	main frame class
+*/
+class MyFrame : public wxFrame
+{
+public:
+    MyFrame();
+	void OnCloseWindow( wxCloseEvent& event );
+	static MyFrame* CreateAddPanel ( spcore::IComponent& component );
+private:
+    // any class wishing to process wxWidgets events must use this macro
+    DECLARE_EVENT_TABLE()
+};
+
+/*
+	myframe event table
+*/
+BEGIN_EVENT_TABLE(MyFrame, wxFrame)
+	EVT_CLOSE( MyFrame::OnCloseWindow )
+END_EVENT_TABLE()
+
+void MyFrame::OnCloseWindow(wxCloseEvent &event)
+{
+	event.Skip(); // Equivalent to: wxFrame::OnCloseWindow(event);
+}
+
+/*!
+ * Application instance declaration
+ */
+DECLARE_APP(TestWXApp)
+
+/*!
+ * TestWXApp type definition
+ */
+IMPLEMENT_CLASS( TestWXApp, wxApp )
+
+/*
+	Application instance implementation
+
+	we use IMPLEMENT_APP_NO_MAIN instead of IMPLEMENT_APP
+	because we define our own main
+ */
+IMPLEMENT_APP_NO_MAIN(TestWXApp)
+
+// ============================================================================
+// implementation
+// ============================================================================
+
+// ----------------------------------------------------------------------------
+// main frame
+// ----------------------------------------------------------------------------
+MyFrame::MyFrame()
+: wxFrame(NULL, wxID_ANY, _T(""), wxDefaultPosition, wxDefaultSize, wxCAPTION|wxSYSTEM_MENU|wxCLOSE_BOX)
+{
+
+}
+
+MyFrame* MyFrame::CreateAddPanel ( spcore::IComponent& component )
+{
+	MyFrame* mf= new MyFrame;
+	wxBoxSizer* sizer= new wxBoxSizer(wxVERTICAL);
+	mf->SetSizer(sizer);
+	wxWindow* pan= component.GetGUI(mf);
+	if (!pan) {
+		delete mf;
+		return NULL;
+	}
+	sizer->Add (static_cast<wxWindow*>(pan), 0, wxALIGN_CENTER_HORIZONTAL|wxALL, 0);
+	mf->GetSizer()->SetSizeHints(mf);	// Fit to content
+
+	return mf;
+}
+
+// ----------------------------------------------------------------------------
+// the application class
+// ----------------------------------------------------------------------------
+
+TestWXApp::TestWXApp() {
+}
+
+/*
+  Initialisation for TestWXApp
+
+  Return true to signal correct initialization or false when error
+ */
+bool TestWXApp::OnInit()
+{
+#if wxUSE_XPM
+	wxImage::AddHandler(new wxXPMHandler);
+#endif
+#if wxUSE_LIBPNG
+	wxImage::AddHandler(new wxPNGHandler);
+#endif
+#if wxUSE_LIBJPEG
+	wxImage::AddHandler(new wxJPEGHandler);
+#endif
+#if wxUSE_GIF
+	wxImage::AddHandler(new wxGIFHandler);
+#endif
+
+#if defined(WIN32)
+	// Uncomment this to enable a console in Windows for debug purposes
+	//AllocConsole(); freopen("CONOUT$", "wb", stdout);
+#endif
+
+	ICoreRuntime* cr= getSpCoreRuntime();
+
+	int retval= cr->LoadModule("mod_sdl");
+	if (retval!= 0)
+		ExitErr("error loading mod_sdl");
+	retval= cr->LoadModule("mod_sdl_gui");
+	if (retval!= 0)
+		ExitErr("error loading mod_sdl_gui");
+
+	DumpCoreRuntime(cr);
+
+	// Create sdl_config_gui component
+	m_comp= cr->CreateComponent ("sdl_config_gui", "testcomponent", 0, NULL);
+	if (!m_comp.get())
+		ExitErr("error cannot create component");
+
+	// Create dialog
+	MyFrame* mf= MyFrame::CreateAddPanel ( *m_comp );
+	if (!mf) ExitErr("error error creating pannel");
+
+	mf->Show();
+
+	return true;
+}
+
+
+/*!
+  Cleanup for TestWXApp
+ */
+
+int TestWXApp::OnExit()
+{
+	return wxApp::OnExit();
+}
+
+// ----------------------------------------------------------------------------
+// main
+// ----------------------------------------------------------------------------
+
+int main(int argc, char *argv[]) {
+
+#if defined(__WXGTK__) || defined(__WXMOTIF__) || defined(__WXX11__)
+	// Under X11 it's necessary enable threading support
+	if ( XInitThreads() == 0 ) {
+		ExitErr("Unable to initialize multithreaded X11 code (XInitThreads failed)");
+		exit( EXIT_FAILURE );
+	}
+#endif
+
+	// Initialize spcore
+	ICoreRuntime* cr= getSpCoreRuntime();
+	if (!cr) return false;
+
+	// Run wxWidgets message pump
+	wxEntry(argc, argv);
+
+	// Free spcore
+	freeSpCoreRuntime();
+
+	// If execution reaches this => all tests ok
+	return 0;
+}
diff --git a/src/mod_sdl/tests/test_mod_sdl_loadlib.cpp b/src/mod_sdl/tests/test_mod_sdl_loadlib.cpp
new file mode 100644
index 0000000..8782022
--- /dev/null
+++ b/src/mod_sdl/tests/test_mod_sdl_loadlib.cpp
@@ -0,0 +1,40 @@
+#include "sphost/testcommon.h"
+#include "spcore/coreruntime.h"
+#include "mod_sdl/sdlsurfacetype.h"
+
+using namespace spcore;
+
+static void DoTests()
+{
+	// Initialization
+	spcore::ICoreRuntime* cr= spcore::getSpCoreRuntime();
+	if (!cr) ExitErr("spcore::getSpCoreRuntime(); failed");
+
+	int retval= cr->LoadModule ("mod_sdl");
+	if (retval< 0) {
+		std::cerr << "Cannot load shared library. Error code: " << retval << std::endl;
+		exit(-1);
+	}
+
+	DumpCoreRuntime(cr);
+
+	// Check symbols
+
+	SmartPtr<IComponent> compo= cr->CreateComponent("sdl_drawer", "my_drawer", 0, NULL);
+	if (!compo.get()) ExitErr("sdl_drawer component not found");
+
+	SmartPtr<CTypeAny> sur= cr->CreateTypeInstance("sdl_surface");
+	if (!sur.get()) ExitErr("sdl_surface component not found");
+
+
+}
+
+int main (int argc, char* argv[])
+{
+	DoTests();
+
+	// Cleanup
+	spcore::freeSpCoreRuntime();
+
+	return 0;
+}
diff --git a/src/mod_vision/CMakeLists.txt b/src/mod_vision/CMakeLists.txt
new file mode 100755
index 0000000..772a48c
--- /dev/null
+++ b/src/mod_vision/CMakeLists.txt
@@ -0,0 +1,18 @@
+cmake_minimum_required(VERSION 2.8)
+project(mod_vision)
+
+FIND_PACKAGE( OpenCV REQUIRED core imgproc legacy)
+INCLUDE_DIRECTORIES (${OpenCV_INCLUDE_DIR})
+INCLUDE_DIRECTORIES (..)
+
+set(mod_vision_SRCS
+	mod_vision.cpp	
+	oftracker.h
+	oftracker.cpp
+)
+
+add_library (mod_vision MODULE ${mod_vision_SRCS})
+target_link_libraries(mod_vision creavision)
+target_link_libraries(mod_vision spcore)
+
+INSTALL (TARGETS mod_vision RUNTIME DESTINATION ${LIBRUNTIMEDIR} LIBRARY DESTINATION ${PLUGINDIR})
diff --git a/src/mod_vision/mod_vision.cpp b/src/mod_vision/mod_vision.cpp
new file mode 100644
index 0000000..4e1f7d4
--- /dev/null
+++ b/src/mod_vision/mod_vision.cpp
@@ -0,0 +1,159 @@
+/////////////////////////////////////////////////////////////////////////////
+// File:        mod_vision.cpp
+// Author:      Cesar Mauri Loba (cesar at crea-si dot com)
+// Copyright:   (C) 2011 Cesar Mauri Loba - CREA Software Systems
+//
+//  This program is free software: you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation, either version 3 of the License, or
+//  (at your option) any later version.
+//
+//  This program is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+/////////////////////////////////////////////////////////////////////////////
+
+#include "spcore/component.h"
+#include "spcore/module.h"
+#include "spcore/basictypes.h"
+#include "spcore/libimpexp.h"
+#include "spcore/pinimpl.h"
+#include "mod_camera/iplimagetype.h"
+#include "oftracker.h"
+
+#include <string>
+#include <boost/thread/mutex.hpp>
+#include <time.h>
+
+
+using namespace spcore;
+using namespace mod_camera;
+
+namespace mod_vision {
+
+
+enum {
+	MAX_INTERFRAME_TIME= 2
+};
+
+/* ******************************************************************************
+	optical_flow_tracker component
+****************************************************************************** */
+class OpticalFlowTracker : public spcore::CComponentAdapter {
+public:
+	static const char* getTypeName() { return "optical_flow_tracker"; };
+	virtual const char* GetTypeName() const { return OpticalFlowTracker::getTypeName(); };
+
+	OpticalFlowTracker(const char * name, int argc, const char * argv[])
+	: CComponentAdapter(name, argc, argv)
+	, m_lastSeen(0)
+	{
+		m_oPinResult= CTypeComposite::CreateOutputPin("motion");
+		if (m_oPinResult.get()== NULL)
+			// Output pin creation failed. Shouldn't happen but...
+			throw std::runtime_error("optical_flow_tracker. output pin creation failed.");
+		RegisterOutputPin (*m_oPinResult);
+		RegisterInputPin (*SmartPtr<InputPinImage>(new InputPinImage(*this), false));
+		RegisterInputPin (*SmartPtr<InputPinROI>(new InputPinROI(*this), false));
+
+		m_result= CTypeComposite::CreateInstance();
+		m_rx= CTypeFloat::CreateInstance();
+		m_ry= CTypeFloat::CreateInstance();
+		m_result->AddChild (m_rx);
+		m_result->AddChild (m_ry);
+	}
+
+	void OnImage(const CTypeIplImage & img)
+	{
+		float vx= 0.0, vy= 0.0;
+		m_mutex.lock();
+		m_tracker.ProcessImage(*img.getImage(), vx, vy);
+		m_mutex.unlock();
+
+		time_t now= time(NULL);
+
+		if (now - m_lastSeen< MAX_INTERFRAME_TIME) {
+			// If too many time passed since last frame don't send output
+			m_rx->setValue(vx);
+			m_ry->setValue(vy);
+
+			m_oPinResult->Send(m_result);
+		}
+		m_lastSeen= now;
+	}
+
+	void UpdateRootROI (const CTypeROI & roi)
+	{
+		boost::mutex::scoped_lock lock(m_mutex);
+
+		m_tracker.SetROI(roi);
+	}
+
+private:
+	//
+	// Attributes
+	//
+
+	// Output pin is a composite of 2 floats with the motion direction
+	SmartPtr<IOutputPin> m_oPinResult;
+	COfTracker m_tracker;
+	boost::mutex m_mutex;
+	time_t m_lastSeen;
+	SmartPtr<CTypeComposite> m_result;
+	SmartPtr<CTypeFloat> m_rx;
+	SmartPtr<CTypeFloat> m_ry;
+
+
+	// Write-only pin to send the image
+	class InputPinImage : public spcore::CInputPinWriteOnly<CTypeIplImage, OpticalFlowTracker> {
+	public:
+		InputPinImage (OpticalFlowTracker & component)
+		: CInputPinWriteOnly<CTypeIplImage, OpticalFlowTracker>("image", component) { }
+
+		virtual int DoSend(const CTypeIplImage & img) {
+			m_component->OnImage(img);
+			return 0;
+		}
+	};
+
+	// Write-only pin to send a ROI
+	class InputPinROI : public spcore::CInputPinWriteOnly<CTypeROI, OpticalFlowTracker> {
+	public:
+		InputPinROI (OpticalFlowTracker & component)
+		: CInputPinWriteOnly<CTypeROI, OpticalFlowTracker>("roi", component) { }
+
+		virtual int DoSend(const CTypeROI & roi) {
+			m_component->UpdateRootROI (roi);
+			return 0;
+		}
+	};
+};
+
+typedef ComponentFactory<OpticalFlowTracker> OpticalFlowTrackerFactory;
+
+/* ******************************************************************************
+	 vision  module
+****************************************************************************** */
+class VisionModule : public CModuleAdapter {
+public:
+	VisionModule() {
+		//
+		// components
+		//
+		RegisterComponentFactory(SmartPtr<spcore::IComponentFactory>(new OpticalFlowTrackerFactory(), false));
+	}
+	virtual const char * GetName() const { return "mod_vision"; }
+};
+
+static VisionModule* g_module= NULL;
+SPEXPORT_FUNCTION spcore::IModule* module_create_instance()
+{
+	if (g_module== NULL) g_module= new VisionModule();
+	return g_module;
+}
+
+};
diff --git a/src/mod_vision/oftracker.cpp b/src/mod_vision/oftracker.cpp
new file mode 100755
index 0000000..cdc2fa2
--- /dev/null
+++ b/src/mod_vision/oftracker.cpp
@@ -0,0 +1,186 @@
+/////////////////////////////////////////////////////////////////////////////
+// Copyright:   (C) 2008 Cesar Mauri (cesar at crea-si dot com)
+// 
+//  This program is free software: you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation, either version 3 of the License, or
+//  (at your option) any later version.
+//
+//  This program is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+/////////////////////////////////////////////////////////////////////////////
+#include "oftracker.h"
+//#include "crvimage.h"
+#include "creavision/crvcolor.h"
+//#include "crvdraw.h"
+
+using namespace mod_camera;
+using namespace spcore;
+
+namespace mod_vision {
+
+COfTracker::COfTracker() //CCamWindow2* pCamWindow) 
+//: m_bigArea (0.9f, 0.9f)
+//, m_smallArea (0.2f, 0.2f)
+//, m_sensitivy (1.0f)
+//, m_autoTrack (false)
+//, m_pCamWindow (pCamWindow)
+{
+//	m_smallArea.SetShowOrientation (true);
+//	m_bigArea.getInstance()->RegisterChildROI (&m_smallArea);
+	m_roi= CTypeROI::CreateInstance();
+}
+
+COfTracker::~COfTracker(void)
+{
+//	m_bigArea.getInstance()->UnregisterChildROI (&m_smallArea);
+}
+
+// TODO: manage allocation errors
+bool COfTracker::AllocateImages(const IplImage& image)
+{
+	bool changed= false;
+
+    // Current/Previous
+	if (!m_currentImg.Initialized() || 
+		m_currentImg.Width()!= image.width || m_currentImg.Height()!= image.height)
+	{
+		m_currentImg.Free();
+		m_currentImg.Create (image.width, image.height, IPL_DEPTH_8U, "GRAY", IPL_ORIGIN_TL, IPL_ALIGN_DWORD);
+
+		m_previousImg.Free();
+		m_previousImg.Create (image.width, image.height, IPL_DEPTH_8U, "GRAY", IPL_ORIGIN_TL, IPL_ALIGN_DWORD);
+
+		m_diffImg.Free();
+		m_diffImg.Create (image.width, image.height, IPL_DEPTH_8U, "GRAY", IPL_ORIGIN_TL, IPL_ALIGN_DWORD);
+
+		changed= true;
+	}
+
+	if (!m_velX.Initialized() || m_velX.Width()!= image.width || m_velX.Height()!= image.height)
+	{
+		m_velX.Free();
+		m_velX.Create (image.width, image.height, IPL_DEPTH_32F, "GRAY", IPL_ORIGIN_TL, IPL_ALIGN_DWORD);
+	
+		m_velY.Free();
+		m_velY.Create (image.width, image.height, IPL_DEPTH_32F, "GRAY", IPL_ORIGIN_TL, IPL_ALIGN_DWORD);
+	
+		changed= true;
+	}
+
+	return changed;
+}
+
+int COfTracker::ProcessImage(const IplImage& image, float &x, float &y)
+{
+	if (AllocateImages(image))
+	{
+		// Changed
+		crvColorToGray (&image, m_previousImg.ptr());
+		x= y= 0;
+	}
+	else
+	{
+		//cvSplit( pImage, NULL, NULL, currentImg.ptr(), NULL);
+		crvColorToGray (&image, m_currentImg.ptr());
+
+#if 0
+		//
+		// Locate motion and position box
+		//
+		if (GetAutoTrack())
+		{
+			double m0;
+			CvMoments moments;
+
+			int roiX, roiY, roiWidth, roiHeight;
+			m_bigArea.getInstance()->GetBoxImg (&m_previousImg, roiX, roiY, roiWidth, roiHeight);
+
+			m_previousImg.PushROI();
+			m_previousImg.SetROI (roiX, roiY, roiWidth, roiHeight);
+
+			m_currentImg.PushROI();
+			m_currentImg.SetROI (roiX, roiY, roiWidth, roiHeight);
+
+			m_diffImg.PushROI();
+			m_diffImg.SetROI (roiX, roiY, roiWidth, roiHeight);
+
+			cvAbsDiff( m_previousImg.ptr(), m_currentImg.ptr(), m_diffImg.ptr() );
+			cvThreshold( m_diffImg.ptr(), m_diffImg.ptr(), 20.0, 0.0, CV_THRESH_TOZERO);
+			cvMoments ( m_diffImg.ptr(), &moments, 0 );
+			m0= cvGetSpatialMoment( &moments, 0, 0 );
+
+			m_diffImg.PopROI();
+			m_currentImg.PopROI();
+			m_previousImg.PopROI();
+
+			if (m0> 0)
+			{
+				m_smallArea.SetCenterImg (&m_currentImg, 
+										(int) ((cvGetSpatialMoment( &moments, 1, 0 ) / m0) + 0.5f) + roiX,
+										(int) ((cvGetSpatialMoment( &moments, 0, 1 ) / m0) + 0.5f) + roiY);
+			}
+		}
+#endif
+
+		//
+		// Optical Flow motion analisys
+		//
+
+		int roiX= (int) ((float) m_previousImg.Width() * m_roi->GetX());
+		int roiY= (int) ((float) m_previousImg.Height() * m_roi->GetY());
+		int roiWidth= (int) ((float) m_previousImg.Width() * m_roi->GetWidth());
+		int roiHeight= (int) ((float) m_previousImg.Height() * m_roi->GetHeight());
+
+		assert (roiX>= 0 && roiX< m_previousImg.Width());
+		assert (roiY>= 0 && roiY< m_previousImg.Height());
+		assert (roiWidth>= 0 && roiWidth<= m_previousImg.Width());
+		assert (roiHeight>= 0 && roiHeight<= m_previousImg.Height());
+//		m_smallArea.GetBoxImg (&m_previousImg, roiX, roiY, roiWidth, roiHeight);
+		
+		m_previousImg.PushROI();
+        m_previousImg.SetROI (roiX, roiY, roiWidth, roiHeight);
+
+		m_currentImg.PushROI();
+		m_currentImg.SetROI (roiX, roiY, roiWidth, roiHeight);
+
+		m_velX.SetROI (roiX, roiY, roiWidth, roiHeight);
+		m_velY.SetROI (roiX, roiY, roiWidth, roiHeight);
+
+		CvTermCriteria term;
+		term.type= CV_TERMCRIT_ITER;
+		term.max_iter= 6;
+		cvCalcOpticalFlowHS (m_previousImg.ptr(), m_currentImg.ptr(), 0,
+							 m_velX.ptr(), m_velY.ptr(), 0.001, term);
+
+		m_currentImg.PopROI();
+		m_previousImg.PopROI();
+						
+		// Compute mean
+		cvSmooth( m_velX.ptr(), m_velX.ptr(), CV_GAUSSIAN, 3, 3);               
+
+		CvScalar cs;
+		cs= cvSum( m_velX.ptr() );
+		x= (float) cs.val[0] / (float) (roiWidth * roiHeight);
+		cs= cvSum( m_velY.ptr() );
+		y= (float) cs.val[0] / (float) (roiWidth * roiHeight);
+
+		// Apply rotation
+		float rotation= atan2 (y,x);
+		rotation+= m_roi->GetDirection(); //m_smallArea.GetRotation ();
+		float modulus= sqrt (x*x + y*y);
+		x= modulus * cos (rotation);
+		y= modulus * sin (rotation);
+	
+		m_currentImg.Swap (&m_previousImg);
+	}
+
+	return 1;
+}
+
+};
\ No newline at end of file
diff --git a/src/mod_vision/oftracker.h b/src/mod_vision/oftracker.h
new file mode 100755
index 0000000..0fe7838
--- /dev/null
+++ b/src/mod_vision/oftracker.h
@@ -0,0 +1,57 @@
+/////////////////////////////////////////////////////////////////////////////
+// Name:        oftracker.h
+// Purpose:     
+// Author:      Cesar Mauri Loba
+// Modified by: 
+// Created:    04/09/2009
+// Copyright:   (C) 2010 Cesar Mauri (cesar at crea-si dot com)
+// 
+//  This program is free software: you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation, either version 3 of the License, or
+//  (at your option) any later version.
+//
+//  This program is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+/////////////////////////////////////////////////////////////////////////////
+#ifndef OFTRACKER_H
+#define OFTRACKER_H
+
+#include "creavision/crvimage.h"
+#include "mod_camera/roitype.h"
+
+namespace mod_vision {
+
+class COfTracker 
+{
+public:
+	COfTracker(); 
+	~COfTracker(void);
+
+	// TODO: optimization: accept only gray images through an smart pointer
+   // int ProcessImage(const CIplImage& image, float &x, float &y);
+	int ProcessImage(const IplImage& image, float &x, float &y);
+	
+	void SetROI (const mod_camera::CTypeROI & roi) {
+		roi.Clone(m_roi.get(), true);
+	}
+
+private:	
+	bool AllocateImages(const IplImage& image);
+
+    CIplImage m_velX;
+    CIplImage m_velY;
+    CIplImage m_previousImg;
+	CIplImage m_currentImg;
+	CIplImage m_diffImg; 
+	SmartPtr<mod_camera::CTypeROI> m_roi;
+};
+
+};
+
+#endif
diff --git a/src/mod_widgets/CMakeLists.txt b/src/mod_widgets/CMakeLists.txt
new file mode 100755
index 0000000..9b737b5
--- /dev/null
+++ b/src/mod_widgets/CMakeLists.txt
@@ -0,0 +1,27 @@
+cmake_minimum_required(VERSION 2.6)
+project(mod_widgets)
+
+set(mod_widgets_SRCS
+	mod_widgets.cpp
+	base_widget.h
+	slider.h
+	slider.cpp
+	linear2exp.h
+	checkbox.h
+	checkbox.cpp
+	filepicker.h
+	filepicker.cpp
+	choice.h
+	choice.cpp
+	collapsible.h
+	collapsible.cpp
+	button.h
+	button.cpp
+)
+
+add_library (mod_widgets MODULE ${mod_widgets_SRCS})
+target_link_libraries(mod_widgets spcore)
+#target_link_libraries(mod_widgets widgets_base)
+target_link_libraries(mod_widgets ${wxWidgets_LIBRARIES})
+
+INSTALL (TARGETS mod_widgets RUNTIME DESTINATION ${LIBRUNTIMEDIR} LIBRARY DESTINATION ${PLUGINDIR})
diff --git a/src/mod_widgets/TODO.txt b/src/mod_widgets/TODO.txt
new file mode 100755
index 0000000..3ad7cd1
--- /dev/null
+++ b/src/mod_widgets/TODO.txt
@@ -0,0 +1 @@
+- Modify controls older than button to use base_widget.h classes
\ No newline at end of file
diff --git a/src/mod_widgets/base_widget.h b/src/mod_widgets/base_widget.h
new file mode 100755
index 0000000..7639407
--- /dev/null
+++ b/src/mod_widgets/base_widget.h
@@ -0,0 +1,260 @@
+/////////////////////////////////////////////////////////////////////////////
+// Name:        base_widget_component.h
+// Purpose:     
+// Author:      C�sar Mauri Loba
+// Modified by: 
+// Created:     26/05/2011 21:44:47
+// RCS-ID:      
+// Copyright:   (C) 2011 Cesar Mauri Loba - CREA Software Systems
+// 
+//  This program is free software: you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation, either version 3 of the License, or
+//  (at your option) any later version.
+//
+//  This program is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with this program.  If not, see <http://www.gnu.org/licenses/>.    
+/////////////////////////////////////////////////////////////////////////////
+
+#ifndef _base_widget_component_H_
+#define _base_widget_component_H_
+
+#include "spcore/component.h"
+#include "spcore/pinimpl.h"
+#include "spcore/basictypes.h"
+
+#include <wx/thread.h>
+
+namespace mod_widgets {
+
+/**
+	Common base class for all widget components
+*/
+
+template<class PANEL_CLASS, class DERIVED>
+class BaseWidgetComponent : public spcore::CComponentAdapter {
+public:
+	//
+	// Component methods
+	//
+	BaseWidgetComponent(const char * name, int argc, const char * argv[]) 
+	: spcore::CComponentAdapter(name, argc, argv)
+	, m_enabled(true)
+	, m_panel(NULL)
+	{
+		//
+		// Create pin
+		//
+		spcore::CComponentAdapter::RegisterInputPin(
+			*SmartPtr<spcore::IInputPin>(new InputPinEnable(*this), false));
+		
+		//
+		// Process arguments
+		//
+		std::string error_msg(name);
+		if (argc) {
+			for (int i= 0; i< argc; ++i) {
+				if (argv[i] && strcmp ("-l", argv[i])== 0) {
+					// Label
+					++i;
+
+					if (i== argc || argv[i]== NULL) {
+						error_msg+= ". Missing value for -l argument.";
+						throw std::runtime_error(error_msg.c_str());
+					}
+					m_label= argv[i];
+					
+					// Remove arguments
+					argv[i-1]= NULL;
+					argv[i]= NULL;
+				}
+				else if (argv[i] && strcmp ("-e", argv[i])== 0) {
+					// Initially enabled
+					++i;
+
+					if (i== argc || argv[i]== NULL) {
+						error_msg+= ". Missing value for -e argument.";
+						throw std::runtime_error(error_msg.c_str());
+					}
+
+					if (argv[i][0]== '1' || strcmp(argv[i], "true"))
+						m_enabled= true;
+					else if (argv[i][0]== '0' || strcmp(argv[i], "false"))
+						m_enabled= false;
+					else {
+						error_msg+= ". Wrong value for -e argument. Syntax: -e [0|1|false|true].";
+						throw std::runtime_error(error_msg.c_str());
+					}
+					
+					// Remove arguments
+					argv[i-1]= NULL;
+					argv[i]= NULL;
+				}
+			}			
+		}
+	}
+	
+	virtual int DoInitialize()= 0;
+
+	virtual wxWindow* GetGUI(wxWindow * parent) {
+		assert (wxIsMainThread());
+		if (this->m_panel) {
+			// Already created
+			assert (false);
+			spcore::getSpCoreRuntime()->LogMessage(spcore::ICoreRuntime::LOG_ERROR, "panel already open", 
+				this->GetTypeName());
+			return NULL;
+		}
+		else {
+			this->m_panel= new PANEL_CLASS();
+			this->m_panel->SetComponent(static_cast<DERIVED*>(this));
+			this->m_panel->Create(parent);
+		}
+
+		return m_panel;
+	}
+
+	// 
+	// Called from GUI
+	//
+	bool GetEnabled() const { return this->m_enabled; }
+	const std::string& GetLabel() const { return this->m_label; }	
+	void OnPanelDestroyed () {
+		assert (wxIsMainThread());
+		this->m_panel= NULL;
+	}
+
+private:
+	//
+	// Data members
+	//
+	bool m_enabled;
+protected:
+	PANEL_CLASS* m_panel;
+private:
+	std::string m_label;
+
+protected:
+	//
+	// Private methods
+	//
+	virtual ~BaseWidgetComponent() {
+		assert (wxIsMainThread());
+		if (this->m_panel) {
+			this->m_panel->SetComponent(NULL);
+			this->m_panel->Close();
+			this->m_panel= NULL;
+		}
+	}
+
+private:	
+	void OnPinEnable (const spcore::CTypeBool & msg) {
+		assert (wxIsMainThread());
+		if (wxIsMainThread()) {
+			if (m_panel) m_panel->Enable(msg.getValue());
+		}
+		else {
+			spcore::getSpCoreRuntime()->LogMessage(spcore::ICoreRuntime::LOG_ERROR, 
+				"Pin \"enable\" can only receive messages from the main thread.", GetTypeName());
+		}
+	}
+
+	//
+	// Input pin classes
+	//
+	class InputPinEnable
+		: public spcore::CInputPinWriteOnly<spcore::CTypeBool, BaseWidgetComponent> {
+	public:
+		InputPinEnable (BaseWidgetComponent & component)
+		: spcore::CInputPinWriteOnly<spcore::CTypeBool, BaseWidgetComponent>("enable", component) { }
+
+		virtual int DoSend(const spcore::CTypeBool & msg) {
+			this->m_component->OnPinEnable(msg);
+			return 0;
+		}
+	};
+};
+
+/**
+	Additional base class for all widget panel
+*/
+template<class COMPONENT_CLASS>
+class BaseWidgetPanel {
+public:
+	// Constructor
+	BaseWidgetPanel() : m_component(NULL) {}
+
+	// Destructor
+	virtual ~BaseWidgetPanel() {
+		if (m_component!= NULL) {
+			m_component->OnPanelDestroyed();
+			m_component= NULL;
+		}
+	}
+
+	// Set destruction callback. NULL removes.
+	void SetComponent(COMPONENT_CLASS* component) { m_component= component; }
+
+protected:
+	COMPONENT_CLASS* m_component;
+};
+
+/*
+	This class (commented) is a variation of the above class and might be useful 
+	to intercept events. Not used currently (tried wxEVT_ENTER_WINDOW and
+	wxEVT_LEAVE_WINDOW without success)
+*/
+/*
+template<class COMPONENT_CLASS, class BASE_WIDGET>
+class BaseWidgetPanel : public BASE_WIDGET {
+public:
+	// Constructor
+	BaseWidgetPanel() : m_component(NULL) {}
+
+	// Destructor
+	virtual ~BaseWidgetPanel() {
+		if (m_component!= NULL) {
+			m_component->OnPanelDestroyed();
+			m_component= NULL;
+		}
+	}
+
+	// Set destruction callback. NULL removes.
+	void SetComponent(COMPONENT_CLASS* component) { m_component= component; }
+
+	bool Create (wxWindow* parent) { 
+		if (!BASE_WIDGET::Create(parent, wxID_ANY)) return false;
+		
+		// Connect events 
+		//	this->Connect (wxEVT_ENTER_WINDOW, wxMouseEventHandler(BaseWidgetPanel2::OnEnterWindow));
+		// wxEVT_ENTER_WINDOW does not work well in GTK (e.g. with buttons does not allow to click)
+
+		//	this->Connect (wxEVT_LEAVE_WINDOW, wxMouseEventHandler(BaseWidgetPanel::OnLeaveWindow));
+		// wxEVT_LEAVE_WINDOW does not work when control disabled
+
+		return true;
+	}
+
+	// Event handlers
+	//void OnEnterWindow( wxMouseEvent&  ) { 
+	//	if (m_component) this->m_component->OnEnterWindow();
+	//}
+
+	//void OnLeaveWindow( wxMouseEvent&  ) {
+	//	if (m_component) this->m_component->OnLeaveWindow();
+	//}
+
+protected:
+	COMPONENT_CLASS* m_component;
+};
+*/
+
+};	// namespace
+
+#endif
+
diff --git a/src/mod_widgets/button.cpp b/src/mod_widgets/button.cpp
new file mode 100755
index 0000000..8a52957
--- /dev/null
+++ b/src/mod_widgets/button.cpp
@@ -0,0 +1,187 @@
+/////////////////////////////////////////////////////////////////////////////
+// Name:        buttonpanel.cpp
+// Purpose:     
+// Author:      C�sar Mauri Loba
+// Modified by: 
+// Created:     03/06/2011 18:34:35
+// RCS-ID:      
+// Copyright:   (C) 2011 Cesar Mauri Loba - CREA Software Systems
+// 
+//  This program is free software: you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation, either version 3 of the License, or
+//  (at your option) any later version.
+//
+//  This program is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with this program.  If not, see <http://www.gnu.org/licenses/>.    
+/////////////////////////////////////////////////////////////////////////////
+
+// For compilers that support precompilation, includes "wx/wx.h".
+#include "wx/wxprec.h"
+
+#ifdef __BORLANDC__
+#pragma hdrstop
+#endif
+
+#ifndef WX_PRECOMP
+#include "wx/wx.h"
+#endif
+
+////@begin includes
+////@end includes
+
+#include "button.h"
+
+////@begin XPM images
+////@end XPM images
+
+using namespace spcore;
+using namespace std;
+
+namespace mod_widgets {
+
+ButtonComponent::ButtonComponent(const char * name, int argc, const char * argv[])
+: BaseWidgetComponent<ButtonPanel,ButtonComponent>(name, argc, argv)
+{
+	//
+	// Create pins
+	//
+	m_oPinPressed=  CTypeBool::CreateOutputPin("pressed");
+	m_valuePressed= CTypeBool::CreateInstance();
+
+	RegisterOutputPin (*m_oPinPressed);
+
+	//
+	// Process arguments
+	//
+	if (argc) {	
+		for (int i= 0; i< argc; ++i) {
+			if (argv[i] && strlen(argv[i])) {
+				string error_msg("widget_button. Unknown option:");
+				error_msg+= argv[i];
+				throw std::runtime_error(error_msg);
+			}
+		}
+	}
+}
+
+// 
+// Private methods
+//	
+
+// 
+// Called from GUI
+//	
+
+void ButtonComponent::Pressed()
+{
+	m_valuePressed->setValue(true);
+	m_oPinPressed->Send(m_valuePressed);
+}
+
+
+//////////////////////////////////////////////////////////////////////////////
+/*!
+ * ButtonPanel type definition
+ */
+
+IMPLEMENT_DYNAMIC_CLASS( ButtonPanel, wxButton )
+
+
+/*!
+ * ButtonPanel event table definition
+ */
+
+BEGIN_EVENT_TABLE( ButtonPanel, wxButton )
+
+////@begin ButtonPanel event table entries
+    EVT_BUTTON( ID_BUTTON, ButtonPanel::OnButtonClick )
+
+////@end ButtonPanel event table entries
+
+END_EVENT_TABLE()
+
+
+/*!
+ * ButtonPanel constructors
+ */
+
+ButtonPanel::ButtonPanel()
+{
+    Init();
+}
+
+ButtonPanel::ButtonPanel(wxWindow* parent, wxWindowID id, const wxString& label, const wxPoint& pos, const wxSize& size, long style, const wxValidator& validator)
+{
+    Init();
+    Create(parent, id, label, pos, size, style, validator);
+}
+
+
+/*!
+ * ButtonPanel creator
+ */
+
+bool ButtonPanel::Create(wxWindow* parent, wxWindowID id, const wxString& label, const wxPoint& pos, const wxSize& size, long style, const wxValidator& validator)
+{
+////@begin ButtonPanel creation
+    wxButton::Create(parent, id, label, pos, size, style, validator);
+    CreateControls();
+////@end ButtonPanel creation
+    return true;
+}
+
+
+/*!
+ * ButtonPanel destructor
+ */
+
+ButtonPanel::~ButtonPanel()
+{
+////@begin ButtonPanel destruction
+////@end ButtonPanel destruction
+}
+
+
+/*!
+ * Member initialisation
+ */
+
+void ButtonPanel::Init()
+{
+////@begin ButtonPanel member initialisation
+////@end ButtonPanel member initialisation
+}
+
+
+/*!
+ * Control creation for ButtonPanel
+ */
+
+void ButtonPanel::CreateControls()
+{    
+////@begin ButtonPanel content construction
+////@end ButtonPanel content construction
+	if (this->m_component && this->m_component->GetLabel().size()) {
+		wxString label(m_component->GetLabel().c_str(), wxConvUTF8);
+		this->SetLabel(label);
+	}
+}
+
+/*!
+ * wxEVT_COMMAND_BUTTON_CLICKED event handler for ID_BUTTON
+ */
+
+void ButtonPanel::OnButtonClick( wxCommandEvent& event )
+{
+	if (this->m_component) this->m_component->Pressed();
+
+    event.Skip(false);
+}
+
+}; // namespace
diff --git a/src/mod_widgets/button.h b/src/mod_widgets/button.h
new file mode 100755
index 0000000..9817fe4
--- /dev/null
+++ b/src/mod_widgets/button.h
@@ -0,0 +1,155 @@
+/////////////////////////////////////////////////////////////////////////////
+// Name:        button.h
+// Purpose:     
+// Author:      C�sar Mauri Loba
+// Modified by: 
+// Created:     03/06/2011 18:34:49
+// RCS-ID:      
+// Copyright:   (C) 2011 Cesar Mauri Loba - CREA Software Systems
+// 
+//  This program is free software: you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation, either version 3 of the License, or
+//  (at your option) any later version.
+//
+//  This program is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with this program.  If not, see <http://www.gnu.org/licenses/>.    
+/////////////////////////////////////////////////////////////////////////////
+
+#ifndef _BUTTON_H_
+#define _BUTTON_H_
+
+
+/*!
+ * Includes
+ */
+
+////@begin includes
+////@end includes
+#include "base_widget.h"
+
+#include <wx/button.h>
+
+/*!
+ * Forward declarations
+ */
+
+////@begin forward declarations
+////@end forward declarations
+
+/*!
+ * Control identifiers
+ */
+
+////@begin control identifiers
+#define ID_BUTTON -1
+#define SYMBOL_BUTTONPANEL_STYLE 0
+#define SYMBOL_BUTTONPANEL_IDNAME ID_BUTTON
+#define SYMBOL_BUTTONPANEL_SIZE wxDefaultSize
+#define SYMBOL_BUTTONPANEL_POSITION wxDefaultPosition
+////@end control identifiers
+
+namespace mod_widgets {
+
+class ButtonComponent;
+
+/*!
+ * ButtonPanel class declaration
+ */
+
+class ButtonPanel: public wxButton, public BaseWidgetPanel<ButtonComponent>
+{    
+    DECLARE_DYNAMIC_CLASS( ButtonPanel )
+    DECLARE_EVENT_TABLE()
+
+public:
+    /// Constructors
+    ButtonPanel();
+    ButtonPanel(wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& label = wxEmptyString, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize, long style = 0, const wxValidator& validator = wxDefaultValidator);
+
+    /// Creation
+    bool Create(wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& label = wxEmptyString, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize, long style = 0, const wxValidator& validator = wxDefaultValidator);
+
+    /// Destructor
+    ~ButtonPanel();
+
+private:
+    /// Initialises member variables
+    void Init();
+
+    /// Creates the controls and sizers
+    void CreateControls();
+
+////@begin ButtonPanel event handler declarations
+
+    /// wxEVT_COMMAND_BUTTON_CLICKED event handler for ID_BUTTON
+    void OnButtonClick( wxCommandEvent& event );
+
+////@end ButtonPanel event handler declarations
+
+////@begin ButtonPanel member function declarations
+
+////@end ButtonPanel member function declarations
+
+////@begin ButtonPanel member variables
+////@end ButtonPanel member variables
+};
+
+/**
+	widget_button component
+
+	Input pins:
+		enable (bool)	Enable/disable control
+
+	Output pins:
+		pressed (bool)	True when pressed
+
+	Command line:
+		[-e [0|1|false|true]]	Enabled. Control will be initially enabled (def. 1)
+		[-l <label> ]	Label. If empty, no label is shown.
+*/
+class ButtonComponent : public BaseWidgetComponent<ButtonPanel,ButtonComponent> {
+public:
+	static const char* getTypeName() { return "widget_button"; };
+	virtual const char* GetTypeName() const { return ButtonComponent::getTypeName(); };
+
+	//
+	// Component methods
+	//
+	ButtonComponent(const char * name, int argc, const char * argv[]);
+	
+	virtual int DoInitialize() { return 0; }
+
+	// 
+	// Called from GUI
+	//	
+
+	void Pressed();	
+
+private:
+	//
+	// Data members
+	//
+	SmartPtr<spcore::IOutputPin> m_oPinPressed;
+	SmartPtr<spcore::CTypeBool> m_valuePressed;
+
+	//
+	// Private methods
+	//
+	
+
+	//
+	// Input pin classes
+	//
+};
+
+typedef spcore::ComponentFactory<ButtonComponent> ButtonComponentFactory;
+};	// namespace
+
+#endif
+    // _BUTTON_H_
diff --git a/src/mod_widgets/checkbox.cpp b/src/mod_widgets/checkbox.cpp
new file mode 100755
index 0000000..ac9cbbf
--- /dev/null
+++ b/src/mod_widgets/checkbox.cpp
@@ -0,0 +1,336 @@
+/////////////////////////////////////////////////////////////////////////////
+// Name:        checkbox.cpp
+// Purpose:     
+// Author:      C�sar Mauri Loba
+// Modified by: 
+// Created:     15/05/2011 19:42:16
+// RCS-ID:      
+// Copyright:   (C) 2011 Cesar Mauri Loba - CREA Software Systems
+// 
+//  This program is free software: you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation, either version 3 of the License, or
+//  (at your option) any later version.
+//
+//  This program is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with this program.  If not, see <http://www.gnu.org/licenses/>.   
+/////////////////////////////////////////////////////////////////////////////
+
+////@begin includes
+////@end includes
+
+#include "checkbox.h"
+#include <wx/sizer.h>
+#include <wx/bitmap.h>
+
+////@begin XPM images
+////@end XPM images
+
+using namespace spcore;
+using namespace std;
+
+namespace mod_widgets {
+
+CheckboxComponent::CheckboxComponent(const char * name, int argc, const char * argv[])
+: CComponentAdapter(name, argc, argv)
+, m_panel(NULL)
+{
+	// Create pins and storage
+	m_iPin= SmartPtr<IInputPin>(new InputPinValue(*this), false);
+	m_oPin= CTypeBool::CreateOutputPin("value");		
+	m_value= CTypeBool::CreateInstance();
+	RegisterInputPin (*m_iPin);
+	RegisterOutputPin (*m_oPin);		
+	
+	// Process arguments
+	if (argc) {
+		for (int i= 0; i< argc; ++i) {
+			if (strcmp ("-v", argv[i])== 0) {
+				// Value
+				bool err= false;
+				
+				++i;
+				if (i< argc) {
+					if (strcmp("1", argv[i])== 0 || strcmp("true", argv[i])== 0) m_value->setValue(true);
+					else if (strcmp("0", argv[i])== 0 || strcmp("false", argv[i])== 0) {  }
+					else err= true;
+				}
+				else err= true;
+				if (err) throw std::runtime_error("widget_checkbox. Wrong value for option --v");
+			}
+			else if (strcmp ("-l", argv[i])== 0) {
+				// Label
+				++i;
+
+				if (i== argc) throw std::runtime_error("widget_checkbox. Missing value for -l argument");
+				m_label= argv[i];
+			}			
+			else if (strlen(argv[i])) {
+				string error_msg("widget_checkbox. Unknown option:");
+				error_msg+= argv[i];
+				throw std::runtime_error(error_msg);
+			}
+		}
+	}
+}
+
+int CheckboxComponent::DoInitialize()
+{
+	m_oPin->Send(m_value);
+
+	return 0;
+}
+
+wxWindow* CheckboxComponent::GetGUI(wxWindow * parent) {
+	assert (wxIsMainThread());
+	if (m_panel) {
+		// Already created
+		assert (false);
+		getSpCoreRuntime()->LogMessage(ICoreRuntime::LOG_ERROR, "panel alredy open", "checkbox");
+		return NULL;
+	}
+	else {
+		m_panel= new CheckboxPanel();
+		m_panel->SetComponent(this);
+		m_panel->Create(parent);
+	}
+
+	return m_panel;
+}
+
+// 
+// Called from GUI
+//	
+
+void CheckboxComponent::SetCheckboxValue (bool v)
+{
+	if (m_value->getValue()!= v) {
+		m_value->setValue(v);
+		m_oPin->Send(m_value);
+	}
+}
+
+bool CheckboxComponent::GetCheckboxValue() const
+{
+	return m_value->getValue();
+}
+
+void CheckboxComponent::OnPanelDestroyed ()
+{
+	assert (wxIsMainThread());
+	m_panel= NULL;
+}
+
+// 
+// Private methods
+//	
+
+void CheckboxComponent::OnPinValue (const CTypeBool & msg)
+{
+	m_value->setValue(msg.getValue());
+	if (m_panel) m_panel->ValueChanged();
+}
+
+CheckboxComponent::~CheckboxComponent()
+{
+	assert (wxIsMainThread());
+	if (m_panel) {
+		m_panel->SetComponent(NULL);
+		m_panel->Close();
+		m_panel= NULL;
+	}
+}
+
+//////////////////////////////////////////////////////////////////////////////
+
+/*!
+ * CheckboxPanel type definition
+ */
+
+IMPLEMENT_DYNAMIC_CLASS( CheckboxPanel, wxPanel )
+
+// New event to comunicate updates to GUI
+DECLARE_LOCAL_EVENT_TYPE(wxEVT_SPCHECKBOX_VALUE_CHANGE, -1)
+DEFINE_LOCAL_EVENT_TYPE(wxEVT_SPCHECKBOX_VALUE_CHANGE)
+
+/*!
+ * CheckboxPanel event table definition
+ */
+
+BEGIN_EVENT_TABLE( CheckboxPanel, wxPanel )
+
+////@begin CheckboxPanel event table entries
+    EVT_CHECKBOX( ID_CHECKBOX, CheckboxPanel::OnCheckboxClick )
+
+////@end CheckboxPanel event table entries
+
+	EVT_COMMAND  (wxID_ANY, wxEVT_SPCHECKBOX_VALUE_CHANGE, CheckboxPanel::OnValueChanged)	
+
+END_EVENT_TABLE()
+
+
+/*!
+ * CheckboxPanel constructors
+ */
+
+CheckboxPanel::CheckboxPanel()
+{
+    Init();
+}
+
+CheckboxPanel::CheckboxPanel( wxWindow* parent, wxWindowID id, const wxPoint& pos, const wxSize& size, long style, const wxString& name )
+{
+    Init();
+    Create(parent, id, pos, size, style, name);
+}
+
+
+/*!
+ * CheckboxPanel creator
+ */
+
+bool CheckboxPanel::Create( wxWindow* parent, wxWindowID id, const wxPoint& pos, const wxSize& size, long style, const wxString& name )
+{
+////@begin CheckboxPanel creation
+    SetExtraStyle(wxWS_EX_BLOCK_EVENTS);
+    wxPanel::Create( parent, id, pos, size, style, name );
+
+    CreateControls();
+    if (GetSizer())
+    {
+        GetSizer()->SetSizeHints(this);
+    }
+    Centre();
+////@end CheckboxPanel creation
+    return true;
+}
+
+
+/*!
+ * CheckboxPanel destructor
+ */
+
+CheckboxPanel::~CheckboxPanel()
+{
+	if (m_component!= NULL) {
+		m_component->OnPanelDestroyed();
+		m_component= NULL;
+	}
+////@begin CheckboxPanel destruction
+////@end CheckboxPanel destruction
+}
+
+
+/*!
+ * Member initialisation
+ */
+
+void CheckboxPanel::Init()
+{
+	m_component= NULL;
+////@begin CheckboxPanel member initialisation
+    m_theCheckbox = NULL;
+////@end CheckboxPanel member initialisation
+}
+
+
+/*!
+ * Control creation for CheckboxPanel
+ */
+
+void CheckboxPanel::CreateControls()
+{    
+////@begin CheckboxPanel content construction
+    CheckboxPanel* itemPanel1 = this;
+
+    wxBoxSizer* itemBoxSizer2 = new wxBoxSizer(wxVERTICAL);
+    itemPanel1->SetSizer(itemBoxSizer2);
+
+    m_theCheckbox = new wxCheckBox;
+    m_theCheckbox->Create( itemPanel1, ID_CHECKBOX, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 );
+    m_theCheckbox->SetValue(false);
+    m_theCheckbox->SetName(_T("Checkbox"));
+    itemBoxSizer2->Add(m_theCheckbox, 0, wxALIGN_CENTER_HORIZONTAL|wxALL, 5);
+
+////@end CheckboxPanel content construction
+
+	assert (m_component);
+
+	// Label
+	if (m_component->GetLabel().size()) {
+		wxString label(m_component->GetLabel().c_str(), wxConvUTF8);
+		m_theCheckbox->SetLabel(label);
+	}
+
+	m_theCheckbox->SetValue(m_component->GetCheckboxValue());
+}
+
+
+/*!
+ * Should we show tooltips?
+ */
+
+bool CheckboxPanel::ShowToolTips()
+{
+    return true;
+}
+
+/*!
+ * Get bitmap resources
+ */
+
+wxBitmap CheckboxPanel::GetBitmapResource( const wxString& name )
+{
+    // Bitmap retrieval
+////@begin CheckboxPanel bitmap retrieval
+    wxUnusedVar(name);
+    return wxNullBitmap;
+////@end CheckboxPanel bitmap retrieval
+}
+
+/*!
+ * Get icon resources
+ */
+
+wxIcon CheckboxPanel::GetIconResource( const wxString& name )
+{
+    // Icon retrieval
+////@begin CheckboxPanel icon retrieval
+    wxUnusedVar(name);
+    return wxNullIcon;
+////@end CheckboxPanel icon retrieval
+}
+
+
+/*!
+ * wxEVT_COMMAND_CHECKBOX_CLICKED event handler for ID_CHECKBOX
+ */
+
+void CheckboxPanel::OnCheckboxClick( wxCommandEvent& event )
+{
+	if (m_component)
+		m_component->SetCheckboxValue(event.IsChecked());
+	
+    event.Skip(false);
+}
+
+void CheckboxPanel::ValueChanged()
+{
+	wxCommandEvent event(wxEVT_SPCHECKBOX_VALUE_CHANGE);
+		
+	if (!wxIsMainThread()) wxPostEvent(this, event);
+	else OnValueChanged( event );
+}
+
+void CheckboxPanel::OnValueChanged( wxCommandEvent& )
+{
+	if (m_component)
+		m_theCheckbox->SetValue(m_component->GetCheckboxValue());
+}
+
+};
diff --git a/src/mod_widgets/checkbox.h b/src/mod_widgets/checkbox.h
new file mode 100755
index 0000000..0474627
--- /dev/null
+++ b/src/mod_widgets/checkbox.h
@@ -0,0 +1,199 @@
+/////////////////////////////////////////////////////////////////////////////
+// Name:        checkbox.h
+// Purpose:     
+// Author:      C�sar Mauri Loba
+// Modified by: 
+// Created:     15/05/2011 19:42:16
+// RCS-ID:      
+// Copyright:   (C) 2011 Cesar Mauri Loba - CREA Software Systems
+// 
+//  This program is free software: you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation, either version 3 of the License, or
+//  (at your option) any later version.
+//
+//  This program is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with this program.  If not, see <http://www.gnu.org/licenses/>.    
+/////////////////////////////////////////////////////////////////////////////
+
+#ifndef _CHECKBOX_H_
+#define _CHECKBOX_H_
+
+
+/*!
+ * Includes
+ */
+
+////@begin includes
+////@end includes
+#include "spcore/component.h"
+#include "spcore/pinimpl.h"
+#include "spcore/basictypes.h"
+
+#include <wx/panel.h>
+#include <wx/checkbox.h>
+#include <wx/icon.h>
+
+/*!
+ * Forward declarations
+ */
+
+////@begin forward declarations
+////@end forward declarations
+
+/*!
+ * Control identifiers
+ */
+
+////@begin control identifiers
+#define ID_CHECKBOXPANEL 10004
+#define ID_CHECKBOX 10005
+#define SYMBOL_CHECKBOXPANEL_STYLE wxTAB_TRAVERSAL
+#define SYMBOL_CHECKBOXPANEL_TITLE wxEmptyString
+#define SYMBOL_CHECKBOXPANEL_IDNAME ID_CHECKBOXPANEL
+#define SYMBOL_CHECKBOXPANEL_SIZE wxDefaultSize
+#define SYMBOL_CHECKBOXPANEL_POSITION wxDefaultPosition
+////@end control identifiers
+
+namespace mod_widgets {
+
+class CheckboxComponent;
+
+/*!
+ * CheckboxPanel class declaration
+ */
+
+class CheckboxPanel: public wxPanel
+{    
+    DECLARE_DYNAMIC_CLASS( CheckboxPanel )
+    DECLARE_EVENT_TABLE()
+
+public:
+    /// Constructors
+    CheckboxPanel();
+    CheckboxPanel( wxWindow* parent, wxWindowID id = SYMBOL_CHECKBOXPANEL_IDNAME, const wxPoint& pos = SYMBOL_CHECKBOXPANEL_POSITION, const wxSize& size = SYMBOL_CHECKBOXPANEL_SIZE, long style = SYMBOL_CHECKBOXPANEL_STYLE, const wxString& name = SYMBOL_CHECKBOXPANEL_TITLE );
+
+    /// Creation
+    bool Create( wxWindow* parent, wxWindowID id = SYMBOL_CHECKBOXPANEL_IDNAME, const wxPoint& pos = SYMBOL_CHECKBOXPANEL_POSITION, const wxSize& size = SYMBOL_CHECKBOXPANEL_SIZE, long style = SYMBOL_CHECKBOXPANEL_STYLE, const wxString& name = SYMBOL_CHECKBOXPANEL_TITLE );
+
+    /// Destructor
+    ~CheckboxPanel();
+
+	// Set destruction callback. NULL removes.
+	void SetComponent(CheckboxComponent* component) { m_component= component; }
+
+	// Notify value change
+	void ValueChanged();
+
+private:
+    /// Initialises member variables
+    void Init();
+
+    /// Creates the controls and sizers
+    void CreateControls();
+
+////@begin CheckboxPanel event handler declarations
+
+    /// wxEVT_COMMAND_CHECKBOX_CLICKED event handler for ID_CHECKBOX
+    void OnCheckboxClick( wxCommandEvent& event );
+
+////@end CheckboxPanel event handler declarations
+
+	// Value change event
+	void OnValueChanged( wxCommandEvent& );
+
+////@begin CheckboxPanel member function declarations
+
+    /// Retrieves bitmap resources
+    wxBitmap GetBitmapResource( const wxString& name );
+
+    /// Retrieves icon resources
+    wxIcon GetIconResource( const wxString& name );
+////@end CheckboxPanel member function declarations
+
+    /// Should we show tooltips?
+    static bool ShowToolTips();
+
+////@begin CheckboxPanel member variables
+    wxCheckBox* m_theCheckbox;
+////@end CheckboxPanel member variables
+
+	CheckboxComponent* m_component;
+};
+
+/**
+	widget_checkbox component
+
+	Input pins:
+		value (bool)
+
+		Sets the value of the widget.		
+
+	Output pins:
+		value (bool)
+
+		Sends the value when the slider is manipulated
+
+	Command line:
+		[-l <label> ]	Label. If empty, no label is shown.
+		[-v [0|1|true|false]]	Value (default min)
+*/
+class CheckboxComponent : public spcore::CComponentAdapter {
+public:
+	static const char* getTypeName() { return "widget_checkbox"; };
+	virtual const char* GetTypeName() const { return CheckboxComponent::getTypeName(); };
+
+	//
+	// Component methods
+	//
+	CheckboxComponent(const char * name, int argc, const char * argv[]);
+	
+	virtual int DoInitialize();
+
+	virtual wxWindow* GetGUI(wxWindow * parent);
+
+	// 
+	// Called from GUI
+	//	
+	void SetCheckboxValue (bool v);
+	bool GetCheckboxValue() const;
+	
+	const std::string& GetLabel() const { return m_label; }
+	
+	void OnPanelDestroyed ();
+
+private:
+	CheckboxPanel* m_panel;
+	SmartPtr<spcore::IInputPin> m_iPin;
+	SmartPtr<spcore::IOutputPin> m_oPin;
+	SmartPtr<spcore::CTypeBool> m_value;
+	std::string m_label;	
+
+	virtual ~CheckboxComponent();
+
+	void OnPinValue (const spcore::CTypeBool & msg);
+	
+	class InputPinValue 
+		: public spcore::CInputPinWriteOnly<spcore::CTypeBool, CheckboxComponent> {
+	public:
+		InputPinValue (CheckboxComponent & component)
+		: spcore::CInputPinWriteOnly<spcore::CTypeBool, CheckboxComponent>("value", component) { }
+
+		virtual int DoSend(const spcore::CTypeBool & msg) {
+			m_component->OnPinValue(msg);
+			return 0;
+		}
+	};
+};
+
+typedef spcore::ComponentFactory<CheckboxComponent> CheckboxComponentFactory;
+
+};	// namespace
+
+#endif
+    // _CHECKBOX_H_
diff --git a/src/mod_widgets/choice.cpp b/src/mod_widgets/choice.cpp
new file mode 100644
index 0000000..4790ef4
--- /dev/null
+++ b/src/mod_widgets/choice.cpp
@@ -0,0 +1,447 @@
+/////////////////////////////////////////////////////////////////////////////
+// Name:        choice.cpp
+// Purpose:     
+// Author:      C�sar Mauri Loba
+// Modified by: 
+// Created:     26/05/2011 21:44:47
+// RCS-ID:      
+// Copyright:   (C) 2011 Cesar Mauri Loba - CREA Software Systems
+// 
+//  This program is free software: you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation, either version 3 of the License, or
+//  (at your option) any later version.
+//
+//  This program is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with this program.  If not, see <http://www.gnu.org/licenses/>.    
+/////////////////////////////////////////////////////////////////////////////
+
+////@begin includes
+////@end includes
+
+#include "choice.h"
+#include "spcore/conversion.h"
+
+#include <wx/sizer.h>
+#include <wx/bitmap.h>
+
+#include <boost/tokenizer.hpp>
+#include <boost/foreach.hpp>
+
+////@begin XPM images
+////@end XPM images
+using namespace spcore;
+using namespace boost;
+using namespace std;
+
+namespace mod_widgets {
+
+ChoiceComponent::ChoiceComponent(const char * name, int argc, const char * argv[])
+: BaseWidgetComponent<ChoicePanel,ChoiceComponent>(name, argc, argv)
+, m_selection(-1)
+{
+	//
+	// Create pins
+	//
+	RegisterInputPin(*SmartPtr<IInputPin>(new InputPinOptions(*this), false));
+	RegisterInputPin(*SmartPtr<IInputPin>(new InputPinSelect(*this), false));
+
+	m_oPinSelection= CTypeInt::CreateOutputPin("selection");
+	m_oPinSelectionString= CTypeString::CreateOutputPin("selection_string");
+
+	RegisterOutputPin (*m_oPinSelection);
+	RegisterOutputPin (*m_oPinSelectionString);
+
+	//
+	// Process arguments
+	//
+	if (argc) {
+		int selected= -1;
+
+		for (int i= 0; i< argc; ++i) {
+			if (argv[i] && strcmp ("-o", argv[i])== 0) {
+				// Options
+				if (m_options.size())
+					throw std::runtime_error("widget_choice. Option -o can only be set once.");
+
+				bool err= false;
+				
+				++i;
+				if (i< argc && argv[i]) {
+					escaped_list_separator<char> sep("\\", "|", "\"");
+					string options(argv[i]);
+					tokenizer<escaped_list_separator<char> > tok(options, sep);
+					BOOST_FOREACH(string t, tok) {
+						m_options.push_back (t);
+					}
+
+					if (m_options.size()== 0) err= true;
+				}
+				else err= true;
+				if (err) throw std::runtime_error("widget_choice. Wrong value for option -o");
+			}
+			else if (argv[i] && strcmp ("-v", argv[i])== 0) {
+				// Selected option
+				++i;
+				if (i>= argc || !argv[i] || !StrToInt(argv[i], &selected) || selected< 0)
+					throw std::runtime_error("widget_choice. Wrong value for option -v");
+			}
+			else if (argv[i] && strlen(argv[i])) {
+				string error_msg("widget_choice. Unknown option:");
+				error_msg+= argv[i];
+				throw std::runtime_error(error_msg);
+			}
+		}
+
+		// Check that selected option is correct
+		if (selected== -1 && m_options.size()) selected= 0;
+		if (selected>= (int) m_options.size())
+			std::runtime_error("widget_choice. Value for option -v out of range");
+
+		m_selection= selected;
+	}
+}
+
+int ChoiceComponent::DoInitialize()
+{
+	// No sync needed here, by definition Initialize is called before
+	// any data is flowing through the graph
+	if (m_options.size()) {
+		assert (m_selection>= 0);
+		
+		SmartPtr<CTypeInt> selection= CTypeInt::CreateInstance();
+		selection->setValue(m_selection);
+		m_oPinSelection->Send(selection);
+
+		SmartPtr<CTypeString> selectionString= CTypeString::CreateInstance();
+		if (m_selection>= 0) selectionString->setValue(m_options[m_selection].c_str());
+		m_oPinSelectionString->Send(selectionString);
+	}
+	return 0;
+}
+
+// 
+// Private methods
+//	
+
+void ChoiceComponent::OnPinOptions (const spcore::CTypeAny & msg)
+{
+	// Make sure no one else is touching internal data
+	m_mutex.lock();
+
+	// Clear previous options
+	m_options.clear();
+
+	// Get new options
+	SmartPtr<IIterator<CTypeAny*> > cit= msg.QueryChildren();
+	if (cit.get()) {
+		int str_type_id= CTypeString::getTypeID();
+		for (; !cit->IsDone(); cit->Next()) {
+			if (cit->CurrentItem()->GetTypeID()== str_type_id)
+				m_options.push_back(sptype_static_cast<const CTypeString>(cit->CurrentItem())->getValue());
+			else
+				getSpCoreRuntime()->LogMessage(
+					ICoreRuntime::LOG_WARNING, "Unexpected value on list of options", "widget_choice");
+		}
+	}
+
+	if (m_options.size()) {
+		// If options added then notify listeners
+		m_selection= 0;
+	
+		SmartPtr<CTypeInt> selection= CTypeInt::CreateInstance();
+		selection->setValue(m_selection);		
+		SmartPtr<CTypeString> selectionString= CTypeString::CreateInstance();
+		selectionString->setValue(m_options[m_selection].c_str());
+
+		m_mutex.unlock();
+
+		m_oPinSelection->Send(selection);
+		m_oPinSelectionString->Send(selectionString);
+	}
+	else {
+		m_selection= -1;
+		m_mutex.unlock();
+	}
+
+	// Notify GUI
+	if (m_panel) m_panel->ValueChanged();
+}
+
+void ChoiceComponent::OnPinSelect (const spcore::CTypeInt & msg)
+{
+	int newSel= msg.getValue();
+
+	if (newSel< 0) {
+		getSpCoreRuntime()->LogMessage(ICoreRuntime::LOG_WARNING, "Selection index out of range.", "widget_choice");
+		return;
+	}
+
+	if (SetSelection(newSel))
+		// Notify GUI
+		if (m_panel) m_panel->ValueChanged();
+}
+
+// 
+// Called from GUI
+//	
+
+bool ChoiceComponent::SetSelection(int s)
+{
+	assert (s>= 0);
+
+	m_mutex.lock();
+	
+	// Could happen that an incorrect selection value arrive, just ignore
+	// If not change, don't do anything
+	if (s< (int) m_options.size() && s!= m_selection) {		
+		m_selection= s;
+
+		// Don't take risks and sends full data copies
+		SmartPtr<CTypeInt> selection= CTypeInt::CreateInstance();
+		selection->setValue(s);
+		
+		SmartPtr<CTypeString> selectionString= CTypeString::CreateInstance();
+		selectionString->setValue(m_options[s].c_str());
+			
+		m_mutex.unlock();
+
+		m_oPinSelection->Send(selection);
+		m_oPinSelectionString->Send(selectionString);
+
+		return true;
+	}	
+	else 
+		m_mutex.unlock();
+
+	return false;
+}
+
+void ChoiceComponent::GetOptionsAndSelection(vector<string>& op, int& selection) const
+{
+	m_mutex.lock();
+
+	selection= m_selection;
+	op= m_options;
+	
+	m_mutex.unlock();
+}
+
+//////////////////////////////////////////////////////////////////////////////
+
+/*!
+ * ChoicePanel type definition
+ */
+
+IMPLEMENT_DYNAMIC_CLASS( ChoicePanel, wxPanel )
+
+// New event to comunicate updates to GUI
+DECLARE_LOCAL_EVENT_TYPE(wxEVT_SPCHOICE_VALUE_CHANGE, -1)
+DEFINE_LOCAL_EVENT_TYPE(wxEVT_SPCHOICE_VALUE_CHANGE)
+
+/*!
+ * ChoicePanel event table definition
+ */
+
+BEGIN_EVENT_TABLE( ChoicePanel, wxPanel )
+
+////@begin ChoicePanel event table entries
+    EVT_CHOICE( ID_CHOICE, ChoicePanel::OnChoiceSelected )
+
+////@end ChoicePanel event table entries
+
+	EVT_COMMAND  (wxID_ANY, wxEVT_SPCHOICE_VALUE_CHANGE, ChoicePanel::OnValueChanged)
+
+END_EVENT_TABLE()
+
+
+/*!
+ * ChoicePanel constructors
+ */
+
+ChoicePanel::ChoicePanel()
+{
+    Init();
+}
+
+ChoicePanel::ChoicePanel( wxWindow* parent, wxWindowID id, const wxPoint& pos, const wxSize& size, long style )
+{
+    Init();
+    Create(parent, id, pos, size, style);
+}
+
+
+/*!
+ * ChoicePanel creator
+ */
+
+bool ChoicePanel::Create( wxWindow* parent, wxWindowID id, const wxPoint& pos, const wxSize& size, long style )
+{
+////@begin ChoicePanel creation
+    SetExtraStyle(wxWS_EX_BLOCK_EVENTS);
+    wxPanel::Create( parent, id, pos, size, style );
+
+    CreateControls();
+    if (GetSizer())
+    {
+        GetSizer()->SetSizeHints(this);
+    }
+    Centre();
+////@end ChoicePanel creation
+    return true;
+}
+
+
+/*!
+ * ChoicePanel destructor
+ */
+
+ChoicePanel::~ChoicePanel()
+{
+	if (m_component!= NULL) {
+		m_component->OnPanelDestroyed();
+		m_component= NULL;
+	}
+////@begin ChoicePanel destruction
+////@end ChoicePanel destruction
+}
+
+
+/*!
+ * Member initialisation
+ */
+
+void ChoicePanel::Init()
+{
+	m_component= NULL;
+////@begin ChoicePanel member initialisation
+    m_staLabel = NULL;
+    m_theChoice = NULL;
+////@end ChoicePanel member initialisation
+}
+
+
+/*!
+ * Control creation for ChoicePanel
+ */
+
+void ChoicePanel::CreateControls()
+{    
+////@begin ChoicePanel content construction
+    ChoicePanel* itemPanel1 = this;
+
+    wxBoxSizer* itemBoxSizer2 = new wxBoxSizer(wxVERTICAL);
+    itemPanel1->SetSizer(itemBoxSizer2);
+
+    m_staLabel = new wxStaticText;
+    m_staLabel->Create( itemPanel1, wxID_STATIC, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 );
+    itemBoxSizer2->Add(m_staLabel, 0, wxALIGN_LEFT|wxLEFT|wxRIGHT, 5);
+
+    wxArrayString m_theChoiceStrings;
+    m_theChoice = new wxChoice;
+    m_theChoice->Create( itemPanel1, ID_CHOICE, wxDefaultPosition, wxDefaultSize, m_theChoiceStrings, 0 );
+    itemBoxSizer2->Add(m_theChoice, 0, wxALIGN_LEFT|wxALL, 5);
+
+////@end ChoicePanel content construction
+
+	assert (m_component);
+
+	// Label
+	if (m_component->GetLabel().size()) {
+		wxString label(m_component->GetLabel().c_str(), wxConvUTF8);
+		m_staLabel->SetLabel(label);
+	}
+	else
+		m_staLabel->Show(false);
+
+	ValueChanged();
+}
+
+
+/*!
+ * Should we show tooltips?
+ */
+
+bool ChoicePanel::ShowToolTips()
+{
+    return true;
+}
+
+/*!
+ * Get bitmap resources
+ */
+
+wxBitmap ChoicePanel::GetBitmapResource( const wxString& name )
+{
+    // Bitmap retrieval
+////@begin ChoicePanel bitmap retrieval
+    wxUnusedVar(name);
+    return wxNullBitmap;
+////@end ChoicePanel bitmap retrieval
+}
+
+/*!
+ * Get icon resources
+ */
+
+wxIcon ChoicePanel::GetIconResource( const wxString& name )
+{
+    // Icon retrieval
+////@begin ChoicePanel icon retrieval
+    wxUnusedVar(name);
+    return wxNullIcon;
+////@end ChoicePanel icon retrieval
+}
+
+/*!
+ * wxEVT_COMMAND_CHOICE_SELECTED event handler for ID_CHOICE
+ */
+
+void ChoicePanel::OnChoiceSelected( wxCommandEvent& event )
+{
+	if (m_component)
+		m_component->SetSelection(event.GetSelection());
+	
+    event.Skip(false);
+}
+
+void ChoicePanel::ValueChanged()
+{
+	wxCommandEvent event(wxEVT_SPCHOICE_VALUE_CHANGE);
+		
+	if (!wxIsMainThread()) wxPostEvent(this, event);
+	else OnValueChanged( event );
+}
+
+void ChoicePanel::OnValueChanged( wxCommandEvent& )
+{
+	if (m_component) {
+		// Clear control		
+		m_theChoice->Clear();
+
+		// Get options and selection
+		vector<string> options;
+		int selection;
+		m_component->GetOptionsAndSelection(options, selection);
+		assert (selection== -1 || selection< (int) options.size());
+
+		// Populate control with options
+		vector<string>::const_iterator it= options.begin();
+		for (; it!= options.end(); ++it)
+			m_theChoice->Append (wxString((*it).c_str(), wxConvUTF8));
+
+		// Select item
+		if (selection== -1) m_theChoice->SetSelection(wxNOT_FOUND);
+		else m_theChoice->SetSelection(selection);
+	}
+}
+
+}; // namespace end
+
+
+
diff --git a/src/mod_widgets/choice.h b/src/mod_widgets/choice.h
new file mode 100755
index 0000000..ce6b695
--- /dev/null
+++ b/src/mod_widgets/choice.h
@@ -0,0 +1,217 @@
+/////////////////////////////////////////////////////////////////////////////
+// Name:        choice.h
+// Purpose:     
+// Author:      C�sar Mauri Loba
+// Modified by: 
+// Created:     26/05/2011 21:44:47
+// RCS-ID:      
+// Copyright:   (C) 2011 Cesar Mauri Loba - CREA Software Systems
+// 
+//  This program is free software: you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation, either version 3 of the License, or
+//  (at your option) any later version.
+//
+//  This program is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with this program.  If not, see <http://www.gnu.org/licenses/>.    
+/////////////////////////////////////////////////////////////////////////////
+
+#ifndef _CHOICE_H_
+#define _CHOICE_H_
+
+
+/*!
+ * Includes
+ */
+
+////@begin includes
+////@end includes
+#include "base_widget.h"
+#include <wx/panel.h>
+#include <wx/choice.h>
+#include <wx/icon.h>
+#include <wx/stattext.h>
+
+#include <boost/thread/mutex.hpp>
+
+/*!
+ * Forward declarations
+ */
+
+////@begin forward declarations
+////@end forward declarations
+
+/*!
+ * Control identifiers
+ */
+
+////@begin control identifiers
+#define ID_CHOICEPANEL 10009
+#define ID_CHOICE 10010
+#define SYMBOL_CHOICEPANEL_STYLE wxTAB_TRAVERSAL
+#define SYMBOL_CHOICEPANEL_TITLE _("Choice")
+#define SYMBOL_CHOICEPANEL_IDNAME ID_CHOICEPANEL
+#define SYMBOL_CHOICEPANEL_SIZE wxSize(400, 300)
+#define SYMBOL_CHOICEPANEL_POSITION wxDefaultPosition
+////@end control identifiers
+
+namespace mod_widgets {
+
+class ChoiceComponent;
+
+
+/*!
+ * ChoicePanel class declaration
+ */
+
+class ChoicePanel: public wxPanel
+{    
+    DECLARE_DYNAMIC_CLASS( ChoicePanel )
+    DECLARE_EVENT_TABLE()
+
+public:
+    /// Constructors
+    ChoicePanel();
+    ChoicePanel( wxWindow* parent, wxWindowID id = SYMBOL_CHOICEPANEL_IDNAME, const wxPoint& pos = SYMBOL_CHOICEPANEL_POSITION, const wxSize& size = SYMBOL_CHOICEPANEL_SIZE, long style = SYMBOL_CHOICEPANEL_STYLE );
+
+    /// Creation
+    bool Create( wxWindow* parent, wxWindowID id = SYMBOL_CHOICEPANEL_IDNAME, const wxPoint& pos = SYMBOL_CHOICEPANEL_POSITION, const wxSize& size = SYMBOL_CHOICEPANEL_SIZE, long style = SYMBOL_CHOICEPANEL_STYLE );
+
+    /// Destructor
+    ~ChoicePanel();
+
+	// Set destruction callback. NULL removes.
+	void SetComponent(ChoiceComponent* component) { m_component= component; }
+
+	// Notify changes
+	void ValueChanged();
+
+private:
+    /// Initialises member variables
+    void Init();
+
+    /// Creates the controls and sizers
+    void CreateControls();
+
+////@begin ChoicePanel event handler declarations
+
+    /// wxEVT_COMMAND_CHOICE_SELECTED event handler for ID_CHOICE
+    void OnChoiceSelected( wxCommandEvent& event );
+
+////@end ChoicePanel event handler declarations
+	void OnValueChanged( wxCommandEvent& event );
+
+////@begin ChoicePanel member function declarations
+
+    /// Retrieves bitmap resources
+    wxBitmap GetBitmapResource( const wxString& name );
+
+    /// Retrieves icon resources
+    wxIcon GetIconResource( const wxString& name );
+////@end ChoicePanel member function declarations
+
+    /// Should we show tooltips?
+    static bool ShowToolTips();
+
+////@begin ChoicePanel member variables
+    wxStaticText* m_staLabel;
+    wxChoice* m_theChoice;
+////@end ChoicePanel member variables
+	ChoiceComponent* m_component;
+};
+
+/**
+	widget_choice component
+
+	Input pins:
+		options (any)	List of strings to show
+		selection (int)	Index to select (-1 is none)
+		enable (bool)	Enable/disable control
+
+	Output pins:
+		selection (int)	Index selected when changed
+		selection_string (string)	String selected when changed
+
+	Command line:
+		[-e [0|1|false|true]]	Enabled. Control will be initially enabled (def. 1)
+		[-l <label> ]	Label. If empty, no label is shown.
+		[-o <options>]	Initial options list separeted by '|'
+		[-v <num> ]		Option number initially selected.
+*/
+class ChoiceComponent : public BaseWidgetComponent<ChoicePanel,ChoiceComponent> {
+public:
+	static const char* getTypeName() { return "widget_choice"; };
+	virtual const char* GetTypeName() const { return ChoiceComponent::getTypeName(); };
+
+	//
+	// Component methods
+	//
+	ChoiceComponent(const char * name, int argc, const char * argv[]);
+	
+	virtual int DoInitialize();
+
+	// 
+	// Called from GUI
+	//	
+
+	void GetOptionsAndSelection(std::vector<std::string>& op, int& selection) const;
+	
+	// Return true if a new item has been selected
+	bool SetSelection(int s);
+
+private:
+	//
+	// Data members
+	//
+	int m_selection;
+	mutable boost::mutex m_mutex;
+	std::vector<std::string> m_options;
+	
+	SmartPtr<spcore::IOutputPin> m_oPinSelection;
+	SmartPtr<spcore::IOutputPin> m_oPinSelectionString;
+
+	//
+	// Private methods
+	//
+	void OnPinOptions (const spcore::CTypeAny & msg);
+	void OnPinSelect (const spcore::CTypeInt & msg);
+
+	//
+	// Input pin classes
+	//
+	class InputPinOptions
+		: public spcore::CInputPinWriteOnly<spcore::CTypeAny, ChoiceComponent> {
+	public:
+		InputPinOptions (ChoiceComponent & component)
+		: spcore::CInputPinWriteOnly<spcore::CTypeAny, ChoiceComponent>("options", component) { }
+
+		virtual int DoSend(const spcore::CTypeAny & msg) {
+			m_component->OnPinOptions(msg);
+			return 0;
+		}
+	};
+
+	class InputPinSelect
+		: public spcore::CInputPinWriteOnly<spcore::CTypeInt, ChoiceComponent> {
+	public:
+		InputPinSelect (ChoiceComponent & component)
+		: spcore::CInputPinWriteOnly<spcore::CTypeInt, ChoiceComponent>("selection", component) { }
+
+		virtual int DoSend(const spcore::CTypeInt & msg) {
+			m_component->OnPinSelect(msg);
+			return 0;
+		}
+	};
+};
+
+typedef spcore::ComponentFactory<ChoiceComponent> ChoiceComponentFactory;
+
+};	// namespace
+
+#endif
+    // _CHOICE_H_
diff --git a/src/mod_widgets/collapsible.cpp b/src/mod_widgets/collapsible.cpp
new file mode 100755
index 0000000..4cea025
--- /dev/null
+++ b/src/mod_widgets/collapsible.cpp
@@ -0,0 +1,281 @@
+/////////////////////////////////////////////////////////////////////////////
+// Name:        collapsiblepanel.cpp
+// Purpose:     
+// Author:      C�sar Mauri Loba
+// Modified by: 
+// Created:     01/06/2011 18:17:58
+// RCS-ID:      
+// Copyright:   (C) 2011 Cesar Mauri Loba - CREA Software Systems
+// 
+//  This program is free software: you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation, either version 3 of the License, or
+//  (at your option) any later version.
+//
+//  This program is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with this program.  If not, see <http://www.gnu.org/licenses/>.    
+/////////////////////////////////////////////////////////////////////////////
+// For compilers that support precompilation, includes "wx/wx.h".
+#include "wx/wxprec.h"
+
+#ifdef __BORLANDC__
+#pragma hdrstop
+#endif
+
+#ifndef WX_PRECOMP
+#include "wx/wx.h"
+#endif
+
+////@begin includes
+////@end includes
+
+#include "collapsible.h"
+
+////@begin XPM images
+////@end XPM images
+
+using namespace spcore;
+using namespace boost;
+using namespace std;
+
+namespace mod_widgets {
+
+CollapsibleComponent::CollapsibleComponent(const char * name, int argc, const char * argv[])
+: CComponentAdapter(name, argc, argv)
+, m_panel(NULL)
+{
+	//
+	// Create pins and storage
+	//
+	m_oPinExpanded= CTypeBool::CreateOutputPin("expanded");
+	RegisterOutputPin (*m_oPinExpanded);
+	
+	m_expanded= CTypeBool::CreateInstance();
+
+	//
+	// Process arguments
+	//
+	if (argc) {
+		for (int i= 0; i< argc; ++i) {
+			if (strcmp ("-l", argv[i])== 0) {
+				// Label
+				++i;
+
+				if (i== argc) throw std::runtime_error("widget_collapsible. Missing value for -l argument");
+				m_label= argv[i];
+			}			
+			else if (strlen(argv[i])) {
+				string error_msg("widget_collapsible. Unknown option:");
+				error_msg+= argv[i];
+				throw std::runtime_error(error_msg);
+			}
+		}
+	}
+}
+
+int CollapsibleComponent::DoInitialize()
+{
+	m_oPinExpanded->Send(m_expanded);
+	return 0;
+}
+
+// 
+// Private methods
+//	
+
+wxWindow* CollapsibleComponent::GetGUI(wxWindow * parent) {
+	assert (wxIsMainThread());
+	if (m_panel) {
+		// Already created
+		assert (false);
+		getSpCoreRuntime()->LogMessage(ICoreRuntime::LOG_ERROR, "panel alredy open", "collapsible");
+		return NULL;
+	}
+	else {
+		m_panel= new CollapsiblePanel();
+		m_panel->SetComponent(this);
+		m_panel->Create(parent);
+	}
+
+	return m_panel;
+}
+
+// 
+// Called from GUI
+//	
+void CollapsibleComponent::SetIsExpanded(bool v)
+{
+	if (m_expanded->getValue()!= v) {
+		m_expanded->setValue(v);
+		m_oPinExpanded->Send(m_expanded);
+	}
+}
+
+void CollapsibleComponent::OnPanelDestroyed ()
+{
+	assert (wxIsMainThread());
+	m_panel= NULL;
+}
+
+CollapsibleComponent::~CollapsibleComponent()
+{
+	assert (wxIsMainThread());
+	if (m_panel) {
+		m_panel->SetComponent(NULL);
+		m_panel->Close();
+		m_panel= NULL;
+	}
+}
+
+//////////////////////////////////////////////////////////////////////////////
+
+
+/*!
+ * CollapsiblePanel type definition
+ */
+
+IMPLEMENT_DYNAMIC_CLASS( CollapsiblePanel, wxGenericCollapsiblePane )
+
+
+/*!
+ * CollapsiblePanel event table definition
+ */
+
+BEGIN_EVENT_TABLE( CollapsiblePanel, wxGenericCollapsiblePane )
+
+////@begin CollapsiblePanel event table entries
+    EVT_COLLAPSIBLEPANE_CHANGED( ID_COLLAPSIBLEPANE_PANEL, CollapsiblePanel::OnCollapsiblepanePanelPaneChanged )
+
+////@end CollapsiblePanel event table entries
+
+END_EVENT_TABLE()
+
+
+/*!
+ * CollapsiblePanel constructors
+ */
+
+CollapsiblePanel::CollapsiblePanel()
+{
+    Init();
+}
+
+CollapsiblePanel::CollapsiblePanel(wxWindow* parent, wxWindowID id, const wxString& label, const wxPoint& pos, const wxSize& size, long style, const wxValidator& validator)
+{
+    Init();
+    Create(parent, id, label, pos, size, style, validator);
+}
+
+
+/*!
+ * CollapsiblePanel creator
+ */
+
+bool CollapsiblePanel::Create(wxWindow* parent, wxWindowID id, const wxString& label, const wxPoint& pos, const wxSize& size, long style, const wxValidator& validator)
+{
+////@begin CollapsiblePanel creation
+    wxGenericCollapsiblePane::Create(parent, id, label, pos, size, style, validator);
+    CreateControls();
+////@end CollapsiblePanel creation
+    return true;
+}
+
+
+/*!
+ * CollapsiblePanel destructor
+ */
+
+CollapsiblePanel::~CollapsiblePanel()
+{
+	if (m_component!= NULL) {
+		m_component->OnPanelDestroyed();
+		m_component= NULL;
+	}
+////@begin CollapsiblePanel destruction
+////@end CollapsiblePanel destruction
+}
+
+
+/*!
+ * Member initialisation
+ */
+
+void CollapsiblePanel::Init()
+{
+	m_component= NULL;
+////@begin CollapsiblePanel member initialisation
+////@end CollapsiblePanel member initialisation
+}
+
+
+/*!
+ * Control creation for CollapsiblePanel
+ */
+
+void CollapsiblePanel::CreateControls()
+{    
+////@begin CollapsiblePanel content construction
+////@end CollapsiblePanel content construction
+	if (m_component->GetLabel().size()) {
+		wxString label(m_component->GetLabel().c_str(), wxConvUTF8);
+		this->SetLabel(label);
+	}
+}
+
+
+/*!
+ * wxEVT_COMMAND_COLLPANE_CHANGED event handler for ID_COLLAPSIBLEPANE_PANEL
+ */
+
+void CollapsiblePanel::OnCollapsiblepanePanelPaneChanged( wxCollapsiblePaneEvent& event )
+{
+	if (GetParent()) {
+		wxSizeEvent ev;
+		wxPostEvent (GetParent(), ev);
+	}
+	m_component->SetIsExpanded(!event.GetCollapsed());
+    event.Skip(false);
+}
+
+
+/*!
+ * Should we show tooltips?
+ */
+
+bool CollapsiblePanel::ShowToolTips()
+{
+    return true;
+}
+
+/*!
+ * Get bitmap resources
+ */
+
+wxBitmap CollapsiblePanel::GetBitmapResource( const wxString& name )
+{
+    // Bitmap retrieval
+////@begin CollapsiblePanel bitmap retrieval
+    wxUnusedVar(name);
+    return wxNullBitmap;
+////@end CollapsiblePanel bitmap retrieval
+}
+
+/*!
+ * Get icon resources
+ */
+
+wxIcon CollapsiblePanel::GetIconResource( const wxString& name )
+{
+    // Icon retrieval
+////@begin CollapsiblePanel icon retrieval
+    wxUnusedVar(name);
+    return wxNullIcon;
+////@end CollapsiblePanel icon retrieval
+}
+
+}; // namespace
diff --git a/src/mod_widgets/collapsible.h b/src/mod_widgets/collapsible.h
new file mode 100755
index 0000000..cc2ee0d
--- /dev/null
+++ b/src/mod_widgets/collapsible.h
@@ -0,0 +1,172 @@
+/////////////////////////////////////////////////////////////////////////////
+// Name:        collapsible.h
+// Purpose:     
+// Author:      C�sar Mauri Loba
+// Modified by: 
+// Created:     01/06/2011 18:18:15
+// RCS-ID:      
+// Copyright:   (C) 2011 Cesar Mauri Loba - CREA Software Systems
+// 
+//  This program is free software: you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation, either version 3 of the License, or
+//  (at your option) any later version.
+//
+//  This program is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with this program.  If not, see <http://www.gnu.org/licenses/>.     
+/////////////////////////////////////////////////////////////////////////////
+
+#ifndef _COLLAPSIBLE_H_
+#define _COLLAPSIBLE_H_
+
+
+/*!
+ * Includes
+ */
+
+
+////@begin includes
+#include "wx/collpane.h"
+////@end includes
+#include "spcore/component.h"
+#include "spcore/pinimpl.h"
+#include "spcore/basictypes.h"
+
+
+/*!
+ * Forward declarations
+ */
+
+////@begin forward declarations
+////@end forward declarations
+
+/*!
+ * Control identifiers
+ */
+
+////@begin control identifiers
+#define ID_COLLAPSIBLEPANE_PANEL -1
+#define SYMBOL_COLLAPSIBLEPANEL_STYLE wxCP_DEFAULT_STYLE|wxCP_NO_TLW_RESIZE
+#define SYMBOL_COLLAPSIBLEPANEL_IDNAME ID_COLLAPSIBLEPANE_PANEL
+#define SYMBOL_COLLAPSIBLEPANEL_SIZE wxDefaultSize
+#define SYMBOL_COLLAPSIBLEPANEL_POSITION wxDefaultPosition
+////@end control identifiers
+
+namespace mod_widgets {
+
+class CollapsibleComponent;
+/*!
+ * CollapsiblePanel class declaration
+ */
+// TODO: derive from ContainerCollapsible. On Windows there are problems importing
+// static data members. See: 
+// http://social.msdn.microsoft.com/Forums/en-US/vcgeneral/thread/6b73c234-46f7-4905-a7ae-9c679544e878
+class CollapsiblePanel: public wxGenericCollapsiblePane
+{    
+    DECLARE_DYNAMIC_CLASS( CollapsiblePanel )
+    DECLARE_EVENT_TABLE()
+
+public:
+    /// Constructors
+    CollapsiblePanel();
+    CollapsiblePanel(wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& label = wxEmptyString, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize, long style = wxCP_DEFAULT_STYLE, const wxValidator& validator = wxDefaultValidator);
+
+    /// Creation
+    bool Create(wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& label = wxEmptyString, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize, long style = wxCP_DEFAULT_STYLE, const wxValidator& validator = wxDefaultValidator);
+
+    /// Destructor
+    ~CollapsiblePanel();
+
+	// Set destruction callback. NULL removes.
+	void SetComponent(CollapsibleComponent* component) { m_component= component; }
+
+	// Notify changes
+	void ValueChanged();
+
+private:
+    /// Initialises member variables
+    void Init();
+
+    /// Creates the controls and sizers
+    void CreateControls();
+
+////@begin CollapsiblePanel event handler declarations
+
+    /// wxEVT_COMMAND_COLLPANE_CHANGED event handler for ID_COLLAPSIBLEPANE_PANEL
+    void OnCollapsiblepanePanelPaneChanged( wxCollapsiblePaneEvent& event );
+
+////@end CollapsiblePanel event handler declarations
+
+////@begin CollapsiblePanel member function declarations
+
+    /// Retrieves bitmap resources
+    wxBitmap GetBitmapResource( const wxString& name );
+
+    /// Retrieves icon resources
+    wxIcon GetIconResource( const wxString& name );
+////@end CollapsiblePanel member function declarations
+
+    /// Should we show tooltips?
+    static bool ShowToolTips();
+
+////@begin CollapsiblePanel member variables
+////@end CollapsiblePanel member variables
+	CollapsibleComponent* m_component;
+};
+
+/**
+	widget_collapsible component
+
+	Input pins:		
+
+	Output pins:
+		expanded (bool)	True when expanded, false when collapsed
+
+	Command line:
+		[-l <label> ]	Label. If empty, no label is shown.
+*/
+class CollapsibleComponent : public spcore::CComponentAdapter {
+public:
+	static const char* getTypeName() { return "widget_collapsible"; };
+	virtual const char* GetTypeName() const { return CollapsibleComponent::getTypeName(); };
+
+	//
+	// Component methods
+	//
+	CollapsibleComponent(const char * name, int argc, const char * argv[]);
+	
+	virtual int DoInitialize();
+
+	virtual wxWindow* GetGUI(wxWindow * parent);
+
+	// 
+	// Called from GUI
+	//	
+
+	//bool IsExpanded() const { return m_expanded->getValue(); }
+	void SetIsExpanded(bool v);
+
+	const std::string& GetLabel() const { return m_label; }
+	
+	void OnPanelDestroyed ();
+
+private:
+	CollapsiblePanel* m_panel;
+	SmartPtr<spcore::IOutputPin> m_oPinExpanded;
+	SmartPtr<spcore::CTypeBool> m_expanded;
+	std::string m_label;
+	
+	virtual ~CollapsibleComponent();
+};
+
+typedef spcore::ComponentFactory<CollapsibleComponent> CollapsibleComponentFactory;
+
+
+}; // namespace end
+#endif
+    // _COLLAPSIBLE_H_
diff --git a/src/mod_widgets/filepicker.cpp b/src/mod_widgets/filepicker.cpp
new file mode 100644
index 0000000..5588d6a
--- /dev/null
+++ b/src/mod_widgets/filepicker.cpp
@@ -0,0 +1,416 @@
+/////////////////////////////////////////////////////////////////////////////
+// Name:        filepicker.cpp
+// Purpose:     
+// Author:      C�sar Mauri Loba
+// Modified by: 
+// Created:     18/05/2011 09:45:13
+// RCS-ID:      
+// Copyright:   (C) 2011 Cesar Mauri Loba - CREA Software Systems
+// 
+//  This program is free software: you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation, either version 3 of the License, or
+//  (at your option) any later version.
+//
+//  This program is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with this program.  If not, see <http://www.gnu.org/licenses/>.    
+/////////////////////////////////////////////////////////////////////////////
+
+////@begin includes
+////@end includes
+
+#include "filepicker.h"
+#include <wx/filedlg.h>
+#include <wx/dirdlg.h>
+#include <wx/sizer.h>
+#include <wx/bitmap.h>
+#include <wx/statbox.h>
+#include <wx/textctrl.h>
+#include <wx/button.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#ifdef WIN32
+#include <io.h>
+#define access(path,mode) _access(path,mode)
+#define stat(path,buf) _stat(path,buf)
+#define R_OK    4               /* Test for read permission.  */
+typedef struct _stat t_stat;
+#define S_ISDIR(x) (x & _S_IFDIR)
+#define S_ISREG(x) (x & _S_IFREG)
+#else
+#include <unistd.h>
+typedef struct stat t_stat;
+#endif
+
+////@begin XPM images
+////@end XPM images
+
+using namespace spcore;
+using namespace std;
+
+namespace mod_widgets {
+
+FilePickerComponent::FilePickerComponent(const char * name, int argc, const char * argv[])
+: CComponentAdapter(name, argc, argv)
+, m_pickDirectory(false)
+, m_panel(NULL)
+{
+	// Create pins and storage
+	m_iPin= SmartPtr<IInputPin>(new InputPinValue(*this), false);
+	m_oPin= CTypeString::CreateOutputPin("value");		
+	m_value= CTypeString::CreateInstance();
+	RegisterInputPin (*m_iPin);
+	RegisterOutputPin (*m_oPin);		
+	
+	// Process arguments
+	if (argc) {
+		for (int i= 0; i< argc; ++i) {
+			if (strcmp ("-v", argv[i])== 0) {
+				// Value
+			
+				++i;
+				if (i< argc) m_value->setValue(argv[i]);				
+				else throw std::runtime_error("widget_filepicker. Wrong value for option --v");
+			}
+			else if (strcmp ("-l", argv[i])== 0) {
+				// Label
+				++i;
+
+				if (i== argc) throw std::runtime_error("widget_filepicker. Missing value for -l argument");
+				m_label= argv[i];
+			}
+			else if (strcmp ("-w", argv[i])== 0) {
+				// Wildcard
+				++i;
+
+				if (i== argc) throw std::runtime_error("widget_filepicker. Missing value for -w argument");
+				m_wildcard= argv[i];
+			}
+			else if (strcmp ("-t", argv[i])== 0) {
+				// Type
+				++i;
+
+				char opt= 0;
+
+				if (i< argc && (opt= argv[i][0]) && argv[i][1]== 0 && (opt== 'd' || opt== 'a' )) {
+					if (opt== 'd') m_pickDirectory= true;
+					else m_pickDirectory= false;
+				}
+				else throw std::runtime_error("widget_filepicker. Wrong value for option -t. Use either d or a.");				
+			}
+			else if (strlen(argv[i])) {
+				string error_msg("widget_slider. Unknown option:");
+				error_msg+= argv[i];
+				throw std::runtime_error(error_msg);
+			}
+		}
+	}
+}
+
+bool FilePickerComponent::IsValid(const char* path) const
+{
+	if (access(path, R_OK)!= 0) return false;
+
+	// Is file or directory?
+	t_stat statbuf;
+	if (stat(path,&statbuf)== 0) {
+		if (m_pickDirectory)
+			return (S_ISDIR(statbuf.st_mode)? true : false);
+		else
+			return (S_ISREG(statbuf.st_mode)? true : false);
+	}
+	else 
+		return false;
+}
+
+int FilePickerComponent::DoInitialize()
+{
+	if (IsValid(m_value->getValue())) {
+		if (m_panel) m_panel->ValueChanged();
+		m_oPin->Send(m_value);
+	}
+	else
+		m_value->setValue("");
+
+	return 0;
+}
+
+wxWindow* FilePickerComponent::GetGUI(wxWindow * parent) {
+	assert (wxIsMainThread());
+	if (m_panel) {
+		// Already created
+		assert (false);
+		getSpCoreRuntime()->LogMessage(ICoreRuntime::LOG_ERROR, "panel alredy open", "filepicker");
+		return NULL;
+	}
+	else {
+		m_panel= new FilePickerPanel();
+		m_panel->SetComponent(this);
+		m_panel->Create(parent);
+	}
+
+	return m_panel;
+}
+
+// 
+// Called from GUI
+//	
+
+bool FilePickerComponent::SetFilePickerValue (const char* v)
+{
+	if (strcmp(m_value->getValue(), v)!= 0 && IsValid(v)) {
+		m_value->setValue(v);
+		m_oPin->Send(m_value);
+		return true;
+	}
+	return false;
+}
+
+const char* FilePickerComponent::GetFilePickerValue() const
+{
+	return m_value->getValue();
+}
+
+void FilePickerComponent::OnPanelDestroyed ()
+{
+	assert (wxIsMainThread());
+	m_panel= NULL;
+}
+
+// 
+// Private methods
+//	
+
+void FilePickerComponent::OnPinValue (const CTypeString & msg)
+{
+	if (SetFilePickerValue (msg.getValue()) && m_panel) m_panel->ValueChanged();
+}
+
+FilePickerComponent::~FilePickerComponent()
+{
+	assert (wxIsMainThread());
+	if (m_panel) {
+		m_panel->SetComponent(NULL);
+		m_panel->Close();
+		m_panel= NULL;
+	}
+}
+
+//////////////////////////////////////////////////////////////////////////////
+
+
+/*!
+ * FilePickerPanel type definition
+ */
+
+IMPLEMENT_DYNAMIC_CLASS( FilePickerPanel, wxPanel )
+
+// New event to comunicate updates to GUI
+DECLARE_LOCAL_EVENT_TYPE(wxEVT_SPFILEPICKER_VALUE_CHANGE, -1)
+DEFINE_LOCAL_EVENT_TYPE(wxEVT_SPFILEPICKER_VALUE_CHANGE)
+
+/*!
+ * FilePickerPanel event table definition
+ */
+
+BEGIN_EVENT_TABLE( FilePickerPanel, wxPanel )
+
+////@begin FilePickerPanel event table entries
+    EVT_BUTTON( ID_BUTTON_CHOOSE, FilePickerPanel::OnButtonChooseClick )
+
+////@end FilePickerPanel event table entries
+
+	EVT_COMMAND  (wxID_ANY,wxEVT_SPFILEPICKER_VALUE_CHANGE, FilePickerPanel::OnValueChanged)
+
+END_EVENT_TABLE()
+
+
+/*!
+ * FilePickerPanel constructors
+ */
+
+FilePickerPanel::FilePickerPanel()
+{
+    Init();
+}
+
+FilePickerPanel::FilePickerPanel( wxWindow* parent, wxWindowID id, const wxPoint& pos, const wxSize& size, long style, const wxString& name )
+{
+    Init();
+    Create(parent, id, pos, size, style, name);
+}
+
+
+/*!
+ * FilePickerPanel creator
+ */
+
+bool FilePickerPanel::Create( wxWindow* parent, wxWindowID id, const wxPoint& pos, const wxSize& size, long style, const wxString& )
+{
+////@begin FilePickerPanel creation
+    SetExtraStyle(wxWS_EX_BLOCK_EVENTS);
+    wxPanel::Create( parent, id, pos, size, style );
+
+    CreateControls();
+    if (GetSizer())
+    {
+        GetSizer()->SetSizeHints(this);
+    }
+    Centre();
+////@end FilePickerPanel creation
+    return true;
+}
+
+
+/*!
+ * FilePickerPanel destructor
+ */
+
+FilePickerPanel::~FilePickerPanel()
+{
+	if (m_component!= NULL) {
+		m_component->OnPanelDestroyed();
+		m_component= NULL;
+	}
+////@begin FilePickerPanel destruction
+////@end FilePickerPanel destruction
+}
+
+
+/*!
+ * Member initialisation
+ */
+
+void FilePickerPanel::Init()
+{
+	m_component= NULL;
+////@begin FilePickerPanel member initialisation
+    m_staSizer = NULL;
+    m_txtFilePath = NULL;
+////@end FilePickerPanel member initialisation
+}
+
+
+/*!
+ * Control creation for FilePickerPanel
+ */
+
+void FilePickerPanel::CreateControls()
+{    
+////@begin FilePickerPanel content construction
+    FilePickerPanel* itemPanel1 = this;
+
+    wxBoxSizer* itemBoxSizer2 = new wxBoxSizer(wxVERTICAL);
+    itemPanel1->SetSizer(itemBoxSizer2);
+
+    m_staSizer = new wxStaticBox(itemPanel1, wxID_ANY, wxEmptyString);
+    wxStaticBoxSizer* itemStaticBoxSizer3 = new wxStaticBoxSizer(m_staSizer, wxHORIZONTAL);
+    itemBoxSizer2->Add(itemStaticBoxSizer3, 0, wxGROW|wxLEFT|wxRIGHT, 5);
+
+    m_txtFilePath = new wxTextCtrl;
+    m_txtFilePath->Create( itemPanel1, ID_TEXTCTRL_FILE_PATH, wxEmptyString, wxDefaultPosition, wxSize(200, -1), wxTE_READONLY );
+    itemStaticBoxSizer3->Add(m_txtFilePath, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5);
+
+    wxButton* itemButton5 = new wxButton;
+    itemButton5->Create( itemPanel1, ID_BUTTON_CHOOSE, _("Choose..."), wxDefaultPosition, wxDefaultSize, 0 );
+    itemStaticBoxSizer3->Add(itemButton5, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5);
+
+////@end FilePickerPanel content construction
+
+	assert (m_component);
+
+	// Label
+	if (m_component->GetLabel().size()) {
+		wxString label(m_component->GetLabel().c_str(), wxConvUTF8);
+		m_staSizer->SetLabel(label);
+	}
+}
+
+
+/*!
+ * Should we show tooltips?
+ */
+
+bool FilePickerPanel::ShowToolTips()
+{
+    return true;
+}
+
+/*!
+ * Get bitmap resources
+ */
+
+wxBitmap FilePickerPanel::GetBitmapResource( const wxString& name )
+{
+    // Bitmap retrieval
+////@begin FilePickerPanel bitmap retrieval
+    wxUnusedVar(name);
+    return wxNullBitmap;
+////@end FilePickerPanel bitmap retrieval
+}
+
+/*!
+ * Get icon resources
+ */
+
+wxIcon FilePickerPanel::GetIconResource( const wxString& name )
+{
+    // Icon retrieval
+////@begin FilePickerPanel icon retrieval
+    wxUnusedVar(name);
+    return wxNullIcon;
+////@end FilePickerPanel icon retrieval
+}
+
+
+/*!
+ * wxEVT_COMMAND_BUTTON_CLICKED event handler for ID_BUTTON_CHOOSE
+ */
+
+void FilePickerPanel::OnButtonChooseClick( wxCommandEvent& event )
+{
+	wxString wildcard(m_component->GetWildcard().c_str(), wxConvUTF8);
+	
+	if (m_component) {
+		if (m_component->GetPickDirectory()) {
+			// Pick a directory
+			wxDirDialog dlg(this, _("Choose a directory"), _T(""), wxDD_DEFAULT_STYLE | wxDD_DIR_MUST_EXIST);
+			if (dlg.ShowModal()== wxID_OK && m_component->SetFilePickerValue(dlg.GetPath().mb_str()))
+				OnValueChanged( event );
+		}
+		else {
+			// Pick a regular file
+			wxFileDialog dlg(this, _("Choose a file to open"), _T(""), _T(""), wildcard, wxFD_OPEN);
+			if (dlg.ShowModal()== wxID_OK && m_component->SetFilePickerValue(dlg.GetPath().mb_str()))
+				OnValueChanged( event );
+		}
+	}
+	
+    event.Skip(false);
+}
+
+void FilePickerPanel::ValueChanged()
+{
+	wxCommandEvent event(wxEVT_SPFILEPICKER_VALUE_CHANGE);
+		
+	if (!wxIsMainThread()) wxPostEvent(this, event);
+	else OnValueChanged( event );
+}
+
+void FilePickerPanel::OnValueChanged( wxCommandEvent& )
+{
+	if (m_component) {
+		wxString path(m_component->GetFilePickerValue(), wxConvUTF8);
+		m_txtFilePath->SetValue(path);		
+	}
+}
+
+}; // namespace
+
diff --git a/src/mod_widgets/filepicker.h b/src/mod_widgets/filepicker.h
new file mode 100755
index 0000000..7bb4cee
--- /dev/null
+++ b/src/mod_widgets/filepicker.h
@@ -0,0 +1,218 @@
+/////////////////////////////////////////////////////////////////////////////
+// Name:        filepicker.h
+// Purpose:     
+// Author:      C�sar Mauri Loba
+// Modified by: 
+// Created:     18/05/2011 09:45:13
+// RCS-ID:      
+// Copyright:   (C) 2011 Cesar Mauri Loba - CREA Software Systems
+// 
+//  This program is free software: you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation, either version 3 of the License, or
+//  (at your option) any later version.
+//
+//  This program is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with this program.  If not, see <http://www.gnu.org/licenses/>.    
+/////////////////////////////////////////////////////////////////////////////
+
+#ifndef _FILEPICKER_H_
+#define _FILEPICKER_H_
+
+
+/*!
+ * Includes
+ */
+
+////@begin includes
+////@end includes
+#include "spcore/component.h"
+#include "spcore/pinimpl.h"
+#include "spcore/basictypes.h"
+
+#include <wx/panel.h>
+
+#include <wx/icon.h>
+
+/*!
+ * Forward declarations
+ */
+
+////@begin forward declarations
+////@end forward declarations
+class wxStaticBox;
+class wxTextCtrl;
+
+/*!
+ * Control identifiers
+ */
+
+////@begin control identifiers
+#define ID_FILEPICKERPANEL 10006
+#define ID_TEXTCTRL_FILE_PATH 10007
+#define ID_BUTTON_CHOOSE 10008
+#define SYMBOL_FILEPICKERPANEL_STYLE wxTAB_TRAVERSAL
+#define SYMBOL_FILEPICKERPANEL_TITLE _("FilePicker")
+#define SYMBOL_FILEPICKERPANEL_IDNAME ID_FILEPICKERPANEL
+#define SYMBOL_FILEPICKERPANEL_SIZE wxDefaultSize
+#define SYMBOL_FILEPICKERPANEL_POSITION wxDefaultPosition
+////@end control identifiers
+
+namespace mod_widgets {
+
+class FilePickerComponent;
+
+/*!
+ * FilePickerPanel class declaration
+ */
+
+class FilePickerPanel: public wxPanel
+{    
+    DECLARE_DYNAMIC_CLASS( FilePickerPanel )
+    DECLARE_EVENT_TABLE()
+
+public:
+    /// Constructors
+    FilePickerPanel();
+    FilePickerPanel( wxWindow* parent, wxWindowID id = SYMBOL_FILEPICKERPANEL_IDNAME, const wxPoint& pos = SYMBOL_FILEPICKERPANEL_POSITION, const wxSize& size = SYMBOL_FILEPICKERPANEL_SIZE, long style = SYMBOL_FILEPICKERPANEL_STYLE, const wxString& name = SYMBOL_FILEPICKERPANEL_TITLE );
+
+    /// Creation
+    bool Create( wxWindow* parent, wxWindowID id = SYMBOL_FILEPICKERPANEL_IDNAME, const wxPoint& pos = SYMBOL_FILEPICKERPANEL_POSITION, const wxSize& size = SYMBOL_FILEPICKERPANEL_SIZE, long style = SYMBOL_FILEPICKERPANEL_STYLE, const wxString& name = SYMBOL_FILEPICKERPANEL_TITLE );
+
+    /// Destructor
+    ~FilePickerPanel();
+
+	// Set destruction callback. NULL removes.
+	void SetComponent(FilePickerComponent* component) { m_component= component; }
+
+	// Notify value change
+	void ValueChanged();
+
+private:
+    /// Initialises member variables
+    void Init();
+
+    /// Creates the controls and sizers
+    void CreateControls();
+
+////@begin FilePickerPanel event handler declarations
+
+    /// wxEVT_COMMAND_BUTTON_CLICKED event handler for ID_BUTTON_CHOOSE
+    void OnButtonChooseClick( wxCommandEvent& event );
+
+////@end FilePickerPanel event handler declarations
+	
+	// Value change event
+	void OnValueChanged( wxCommandEvent& );
+
+////@begin FilePickerPanel member function declarations
+
+    /// Retrieves bitmap resources
+    wxBitmap GetBitmapResource( const wxString& name );
+
+    /// Retrieves icon resources
+    wxIcon GetIconResource( const wxString& name );
+////@end FilePickerPanel member function declarations
+
+    /// Should we show tooltips?
+    static bool ShowToolTips();
+
+////@begin FilePickerPanel member variables
+    wxStaticBox* m_staSizer;
+    wxTextCtrl* m_txtFilePath;
+////@end FilePickerPanel member variables
+
+	FilePickerComponent* m_component;
+};
+
+/**
+	widget_filepicker component
+
+	Input pins:
+		value (string)
+
+		Sets the initial path of the widget. If the path doesn't exists then
+		the widget is not updated nor the path is sent during initialization.
+
+	Output pins:
+		value (string)
+
+		Set path.
+
+	Command line:
+		[-l <label> ]	Label. If empty, no label is shown.
+		[-v <path>]		Set initial value
+		[-w <string>]	Wildcard. Ex: *.jpg;*.png
+		[-t [d|a]]		Type. d -> directory, a -> regular file (def. a)
+
+	Notes:
+		Currently supports only open file pickers
+*/
+class FilePickerComponent : public spcore::CComponentAdapter {
+public:
+	static const char* getTypeName() { return "widget_filepicker"; };
+	virtual const char* GetTypeName() const { return FilePickerComponent::getTypeName(); };
+
+	//
+	// Component methods
+	//
+	FilePickerComponent(const char * name, int argc, const char * argv[]);
+	
+	virtual int DoInitialize();
+
+	virtual wxWindow* GetGUI(wxWindow * parent);
+
+	// 
+	// Called from GUI
+	//	
+
+	// Return true if value successfuly set
+	bool SetFilePickerValue (const char* v);
+	const char* GetFilePickerValue() const;
+
+	bool GetPickDirectory() const { return m_pickDirectory; }
+	
+	const std::string& GetLabel() const { return m_label; }
+	const std::string& GetWildcard() const { return m_wildcard; }
+	
+	void OnPanelDestroyed ();
+
+private:
+	bool m_pickDirectory;
+	FilePickerPanel* m_panel;
+	SmartPtr<spcore::IInputPin> m_iPin;
+	SmartPtr<spcore::IOutputPin> m_oPin;
+	SmartPtr<spcore::CTypeString> m_value;
+	std::string m_label;
+	std::string m_wildcard;
+
+	virtual ~FilePickerComponent();
+
+	bool IsValid(const char* path) const;
+
+	void OnPinValue (const spcore::CTypeString & msg);
+
+	
+	class InputPinValue 
+		: public spcore::CInputPinWriteOnly<spcore::CTypeString, FilePickerComponent> {
+	public:
+		InputPinValue (FilePickerComponent & component)
+		: spcore::CInputPinWriteOnly<spcore::CTypeString, FilePickerComponent>("value", component) { }
+
+		virtual int DoSend(const spcore::CTypeString & msg) {
+			m_component->OnPinValue(msg);
+			return 0;
+		}
+	};
+};
+
+typedef spcore::ComponentFactory<FilePickerComponent> FilePickerComponentFactory;
+
+};	// namespace
+#endif
+    // _FILEPICKER_H_
diff --git a/src/mod_widgets/linear2exp.h b/src/mod_widgets/linear2exp.h
new file mode 100755
index 0000000..077788b
--- /dev/null
+++ b/src/mod_widgets/linear2exp.h
@@ -0,0 +1,107 @@
+/////////////////////////////////////////////////////////////////////////////
+// Name:		linear2exp.h
+// Purpose:  
+// Author:      Cesar Mauri Loba (cesar at crea-si dot com)
+// Modified by: 
+// Created:     
+// Copyright:   (C) 2010-11 Cesar Mauri Loba - CREA Software Systems
+// 
+//  This program is free software: you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation, either version 3 of the License, or
+//  (at your option) any later version.
+//
+//  This program is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+/////////////////////////////////////////////////////////////////////////////
+#ifndef LINEAR2EXP_H
+#define LINEAR2EXP_H
+
+#include <assert.h>
+#include <math.h>
+#include <stdexcept>
+
+//
+// This class is intended for helping mapping between linear to exp scales.
+// The main purpose is to allow linear sliders produce a exp range of values
+// The following function is used:
+//
+//  y= A*e^(x*B)-A+C  (defined for x>= 0)
+//
+// Where 
+//  *	x is the input value (linear)
+//	*	y is the output value (exp)
+//	*	A is the "speed" constant (for large values the above function grows faster)
+//		For convenience A=e^a where "a" is a parameter set by the user and can be 
+//		either positive or negative.
+//	*	B and C are constants determined by two points the function should cross
+//			p1=(min_linear>= 0, min_exp)  
+//				and  
+//			p2=(max_linear> 0, maxexp> min_exp)
+//
+// For simplicity min_linear= 0. This yields the following solutions for
+// the equation system:
+//
+//		C= min_exp	
+//		B= (1/max_lin) * ln ((A+max_exp-min_exp)/A)
+//
+// The inverse function is:
+//
+//  x= (1/B) * ln ((y+A-C)/A)
+//
+
+class Linear2ExpMapping
+{
+public:
+	Linear2ExpMapping ()
+	: m_A(2.0f)
+	, m_B(1.0f)
+	, m_C(1.0f)
+	{}
+
+	Linear2ExpMapping (float min_linear, float min_exp, float max_linear, float max_exp, float grow= 0)
+	{
+		SetParams (min_linear, min_exp, max_linear, max_exp, grow);		
+	}
+
+	float ToExp (float x) const {
+		return m_A * exp (x*m_B) - m_A + m_C;
+	}
+
+	float ToLinear (float y) const {
+		assert ((y+m_A-m_C)>= 0);
+		return (1.0f/m_B) * logf ((y+m_A-m_C)/m_A);
+	}
+	
+	void SetParams (float min_linear, float min_exp, float max_linear, float max_exp, float grow)
+	{
+		assert (min_linear== 0);
+		if (min_linear!= 0) throw std::out_of_range("Linear2ExpMapping: wrong min_linear");
+        assert (min_exp>= 0);
+		if (!(min_exp>= 0)) throw std::out_of_range("Linear2ExpMapping: wrong min_exp");
+		assert (max_linear> min_linear);
+		if (!(max_linear> min_linear)) throw std::out_of_range("Linear2ExpMapping: wrong max_linear");
+		assert (max_exp> min_exp);
+		if (!(max_exp> min_exp)) throw std::out_of_range("Linear2ExpMapping: wrong max_exp");
+			
+		m_A= exp (grow);
+		m_C= min_exp;
+		m_B= (1.0f / max_linear) * logf ((m_A + max_exp - m_C) / m_A);
+	}
+
+private:
+	float m_A;
+	float m_B;
+	float m_C;	// Equal to min_exp
+
+protected:
+	
+	float GetC() const { return m_C; }
+};
+
+#endif
\ No newline at end of file
diff --git a/src/mod_widgets/mod_widgets.cpp b/src/mod_widgets/mod_widgets.cpp
new file mode 100644
index 0000000..e4cce87
--- /dev/null
+++ b/src/mod_widgets/mod_widgets.cpp
@@ -0,0 +1,57 @@
+/////////////////////////////////////////////////////////////////////////////
+// File:        mod_widgets.cpp
+// Author:      Cesar Mauri Loba (cesar at crea-si dot com)
+// Copyright:   (C) 2011 Cesar Mauri Loba - CREA Software Systems
+// 
+//  This program is free software: you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation, either version 3 of the License, or
+//  (at your option) any later version.
+//
+//  This program is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+/////////////////////////////////////////////////////////////////////////////
+
+#include "spcore/libimpexp.h"
+#include "spcore/module.h"
+#include "slider.h"
+#include "checkbox.h"
+#include "filepicker.h"
+#include "choice.h"
+#include "collapsible.h"
+#include "button.h"
+
+using namespace spcore;
+
+namespace mod_widgets {
+
+/* ******************************************************************************
+	widgets module
+*/
+class WidgetsModule : public spcore::CModuleAdapter {
+public:
+	WidgetsModule() {
+		
+		RegisterComponentFactory(SmartPtr<spcore::IComponentFactory>(new SliderComponentFactory(), false));
+		RegisterComponentFactory(SmartPtr<spcore::IComponentFactory>(new CheckboxComponentFactory(), false));
+		RegisterComponentFactory(SmartPtr<spcore::IComponentFactory>(new FilePickerComponentFactory(), false));
+		RegisterComponentFactory(SmartPtr<spcore::IComponentFactory>(new ChoiceComponentFactory(), false));
+		RegisterComponentFactory(SmartPtr<spcore::IComponentFactory>(new CollapsibleComponentFactory(), false));
+		RegisterComponentFactory(SmartPtr<spcore::IComponentFactory>(new ButtonComponentFactory(), false));
+	}
+	virtual const char * GetName() const { return "mod_widgets"; }
+};
+
+static spcore::IModule* g_module= NULL;
+SPEXPORT_FUNCTION spcore::IModule* module_create_instance()
+{
+	if (g_module== NULL) g_module= new WidgetsModule();
+	return g_module;
+}
+
+};
\ No newline at end of file
diff --git a/src/mod_widgets/mod_widgets.pjd b/src/mod_widgets/mod_widgets.pjd
new file mode 100644
index 0000000..7a1759f
--- /dev/null
+++ b/src/mod_widgets/mod_widgets.pjd
@@ -0,0 +1,1570 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<anthemion-project version="1.0.0.0" xmlns="http://www.anthemion.co.uk">
+  <header>
+    <long name="name_counter">0</long>
+    <string name="html_path">""</string>
+    <string name="title">""</string>
+    <string name="author">""</string>
+    <string name="description">""</string>
+    <string name="xrc_filename">""</string>
+    <long name="image_mode">0</long>
+    <bool name="inline_images">0</bool>
+    <bool name="generate_cpp_for_xrc">0</bool>
+    <long name="working_mode">1</long>
+    <bool name="use_help_text_for_tooltips">1</bool>
+    <bool name="translate_strings">1</bool>
+    <bool name="make_unicode_strings">1</bool>
+    <bool name="extract_strings">0</bool>
+    <string name="user_name">"César Mauri Loba"</string>
+    <string name="copyright_string">"(C) 2009 Cesar Mauri from CREA Sistemes Informatics"</string>
+    <string name="resource_prefix">""</string>
+    <bool name="use_two_step_construction">1</bool>
+    <bool name="use_enums">0</bool>
+    <bool name="generate_for_xrced">0</bool>
+    <bool name="generate_virtual_eventhandlers">0</bool>
+    <string name="current_platform">"<All platforms>"</string>
+    <string name="target_wx_version">"2.8.7"</string>
+    <string name="app_kind">"Standard"</string>
+    <string name="cpp_header_comment">"/////////////////////////////////////////////////////////////////////////////
+// Name:        %HEADER-FILENAME%
+// Purpose:     
+// Author:      %AUTHOR%
+// Modified by: 
+// Created:     %DATE%
+// RCS-ID:      
+// Copyright:   %COPYRIGHT%
+// Licence:     
+/////////////////////////////////////////////////////////////////////////////
+
+"</string>
+    <string name="cpp_implementation_comment">"/////////////////////////////////////////////////////////////////////////////
+// Name:        %SOURCE-FILENAME%
+// Purpose:     
+// Author:      %AUTHOR%
+// Modified by: 
+// Created:     %DATE%
+// RCS-ID:      
+// Copyright:   %COPYRIGHT%
+// Licence:     
+/////////////////////////////////////////////////////////////////////////////
+
+"</string>
+    <string name="cpp_symbols_file_comment">"/////////////////////////////////////////////////////////////////////////////
+// Name:        %SYMBOLS-FILENAME%
+// Purpose:     Symbols file
+// Author:      %AUTHOR%
+// Modified by: 
+// Created:     %DATE%
+// RCS-ID:      
+// Copyright:   %COPYRIGHT%
+// Licence:     
+/////////////////////////////////////////////////////////////////////////////
+
+"</string>
+    <string name="cpp_header_preamble">""</string>
+    <string name="cpp_implementation_preamble">"// For compilers that support precompilation, includes "wx/wx.h".
+#include "wx/wxprec.h"
+
+#ifdef __BORLANDC__
+#pragma hdrstop
+#endif
+
+#ifndef WX_PRECOMP
+#include "wx/wx.h"
+#endif
+
+"</string>
+    <string name="cpp_function_declaration_comment">"	/// %BODY%
+"</string>
+    <string name="cpp_function_implementation_comment">"
+/*!
+ * %BODY%
+ */
+
+"</string>
+    <string name="resource_file_header">"app_resources.h"</string>
+    <string name="resource_file_implementation">"app_resources.cpp"</string>
+    <string name="resource_class_name">"AppResources"</string>
+    <string name="app_file_header">"app.h"</string>
+    <string name="app_file_implementation">"app.cpp"</string>
+    <string name="app_class_name">"Application"</string>
+    <bool name="generate_app_class">0</bool>
+    <string name="external_symbol_filenames">""</string>
+    <string name="configuration">"<None>"</string>
+    <string name="source_encoding">"iso-8859-1"</string>
+    <string name="xrc_encoding">"utf-8"</string>
+    <string name="project_encoding">"utf-8"</string>
+    <string name="resource_archive">""</string>
+    <long name="text_file_type">0</long>
+    <bool name="use_tabs">0</bool>
+    <long name="indent_size">4</long>
+    <string name="whitespace_after_return_type">" "</string>
+    <string name="resource_xrc_cpp">""</string>
+    <bool name="use_resource_archive">0</bool>
+    <bool name="use_generated_xrc_cpp">0</bool>
+    <bool name="always_generate_xrc">1</bool>
+    <bool name="use_id_name_for_name">0</bool>
+    <bool name="archive_xrc_files">1</bool>
+    <bool name="archive_image_files">1</bool>
+    <bool name="archive_all_image_files">0</bool>
+    <bool name="xrc_retain_relative_paths">1</bool>
+    <bool name="xrc_generate_id_tags">0</bool>
+    <bool name="xrc_use_name_property">0</bool>
+  </header>
+  <data>
+    <document>
+      <string name="title">""</string>
+      <string name="type">"data-document"</string>
+      <string name="filename">""</string>
+      <string name="icon-name">""</string>
+      <long name="is-transient">0</long>
+      <long name="owns-file">1</long>
+      <long name="title-mode">0</long>
+      <long name="locked">0</long>
+      <document>
+        <string name="title">"Configurations"</string>
+        <string name="type">"config-data-document"</string>
+        <string name="filename">""</string>
+        <string name="icon-name">""</string>
+        <long name="is-transient">0</long>
+        <long name="owns-file">1</long>
+        <long name="title-mode">0</long>
+        <long name="locked">0</long>
+        <string name="template-name">""</string>
+        <bool name="dirty">1</bool>
+        <long name="makefile-last-written">-8519680</long>
+        <string name="Compiler name">""</string>
+        <string name="Build mode">"Debug"</string>
+        <string name="Unicode mode">"ANSI"</string>
+        <string name="Shared mode">"Static"</string>
+        <string name="Modularity">"Modular"</string>
+        <string name="GUI mode">"GUI"</string>
+        <string name="Toolkit">"wxMSW"</string>
+        <string name="Processor type">"Default"</string>
+        <string name="Runtime linking">"Dynamic"</string>
+        <string name="Use exceptions">"Yes"</string>
+        <string name="Use ODBC">"No"</string>
+        <string name="Use XRC">"Yes"</string>
+        <string name="Use OpenGL">"No"</string>
+        <string name="Use wxMediaCtrl">"No"</string>
+        <string name="Use wxRichTextCtrl">"Yes"</string>
+        <string name="Use wxHTML">"Yes"</string>
+        <string name="Use wxPropertyGrid">"Yes"</string>
+        <string name="Use wxAUI">"Yes"</string>
+        <string name="Use wxSTC">"Yes"</string>
+        <string name="Use wxRegEx">"builtin"</string>
+        <string name="Use wxRibbonControl">"Yes"</string>
+        <string name="Executable name">"%EXECUTABLE%"</string>
+        <string name="Program arguments">""</string>
+        <string name="Working path">"%AUTO%"</string>
+        <string name="Output path">"%AUTO%"</string>
+        <string name="Objects path">"%AUTO%"</string>
+        <string name="Project makefile">"%AUTO%"</string>
+        <string name="wxWidgets version">"%WXVERSION%"</string>
+        <string name="wxWidgets makefile">"%AUTO%"</string>
+        <string name="wxWidgets location">"%AUTO%"</string>
+        <string name="wxWidgets build path">"%AUTO%"</string>
+        <string name="wxWidgets build command">"%AUTO%"</string>
+        <string name="wxWidgets clean command">"%AUTO%"</string>
+        <string name="CFG">""</string>
+        <string name="Compiler location">"%AUTO%"</string>
+        <string name="Compiler bin path">"%AUTO%"</string>
+        <string name="Compiler include path">"%AUTO%"</string>
+        <string name="Compiler lib path">"%AUTO%"</string>
+        <string name="PATH variable">"%AUTO%"</string>
+        <string name="C++ command">"%AUTO%"</string>
+        <string name="C command">"%AUTO%"</string>
+        <string name="Linker command">"%AUTO%"</string>
+        <string name="Resource compiler">"%AUTO%"</string>
+        <string name="Make command">"%AUTO%"</string>
+        <string name="Preprocessor flags">"%AUTO%"</string>
+        <string name="Optimizations">"%AUTO%"</string>
+        <string name="Warnings">"%AUTO%"</string>
+        <string name="Debug flags">"%AUTO%"</string>
+        <string name="Extra compile flags">"%AUTO%"</string>
+        <string name="Libraries">"%AUTO%"</string>
+        <string name="Library path">"%AUTO%"</string>
+        <string name="Linker flags">"%AUTO%"</string>
+        <string name="Include path">"%AUTO%"</string>
+        <string name="Resource flags">"%AUTO%"</string>
+        <string name="Resource path">"%AUTO%"</string>
+        <string name="Extra dependencies">"%AUTO%"</string>
+        <bool name="Suppress source rules">0</bool>
+        <bool name="Enable makefile generation">1</bool>
+      </document>
+    </document>
+  </data>
+
+  <documents>
+    <document>
+      <string name="title">"Projects"</string>
+      <string name="type">"root-document"</string>
+      <string name="filename">""</string>
+      <string name="icon-name">"project"</string>
+      <long name="is-transient">1</long>
+      <long name="owns-file">1</long>
+      <long name="title-mode">0</long>
+      <long name="locked">1</long>
+      <document>
+        <string name="title">"Windows"</string>
+        <string name="type">"html-document"</string>
+        <string name="filename">""</string>
+        <string name="icon-name">"dialogsfolder"</string>
+        <long name="is-transient">1</long>
+        <long name="owns-file">1</long>
+        <long name="title-mode">0</long>
+        <long name="locked">1</long>
+        <document>
+          <string name="title">"Slider"</string>
+          <string name="type">"dialog-document"</string>
+          <string name="filename">""</string>
+          <string name="icon-name">"dialog"</string>
+          <long name="is-transient">0</long>
+          <long name="owns-file">1</long>
+          <long name="title-mode">0</long>
+          <long name="locked">0</long>
+          <string name="proxy-type">"wbDialogProxy"</string>
+          <long name="base-id">10000</long>
+          <bool name="use-id-prefix">0</bool>
+          <string name="id-prefix">""</string>
+          <bool name="use-id-suffix">0</bool>
+          <string name="id-suffix">""</string>
+          <string name="app-kind">"Standard"</string>
+          <long name="use-xrc">0</long>
+          <long name="working-mode">0</long>
+          <string name="proxy-Id name">"ID_SLIDER"</string>
+          <long name="proxy-Id value">10000</long>
+          <string name="proxy-Class">"SliderPanel"</string>
+          <string name="proxy-Base class">"wxPanel"</string>
+          <string name="proxy-Window kind">"wxPanel"</string>
+          <string name="proxy-Implementation filename">"slider.cpp"</string>
+          <string name="proxy-Header filename">"slider.h"</string>
+          <string name="proxy-XRC filename">""</string>
+          <string name="proxy-Title">"Slider"</string>
+          <bool name="proxy-Centre">1</bool>
+          <string name="proxy-Icon">""</string>
+          <bool name="proxy-Dialog units">0</bool>
+          <string name="proxy-Help text">""</string>
+          <string name="proxy-Tooltip text">""</string>
+          <string name="proxy-Background colour">""</string>
+          <string name="proxy-Foreground colour">""</string>
+          <string name="proxy-Font">""</string>
+          <bool name="proxy-Hidden">0</bool>
+          <bool name="proxy-Enabled">1</bool>
+          <string name="proxy-Platform">"<Any platform>"</string>
+          <string name="proxy-Data source">""</string>
+          <string name="proxy-Data class name">""</string>
+          <string name="proxy-Data class implementation filename">""</string>
+          <string name="proxy-Data class header filename">""</string>
+          <string name="proxy-Data class manager window">""</string>
+          <string name="proxy-Texture">""</string>
+          <string name="proxy-Texture style">"Tiled"</string>
+          <bool name="proxy-wxDEFAULT_DIALOG_STYLE">0</bool>
+          <bool name="proxy-wxCAPTION">0</bool>
+          <bool name="proxy-wxRESIZE_BORDER">0</bool>
+          <bool name="proxy-wxSYSTEM_MENU">0</bool>
+          <bool name="proxy-wxSTAY_ON_TOP">0</bool>
+          <bool name="proxy-wxDIALOG_NO_PARENT">0</bool>
+          <bool name="proxy-wxCLOSE_BOX">0</bool>
+          <bool name="proxy-wxMAXIMIZE_BOX">0</bool>
+          <bool name="proxy-wxMINIMIZE_BOX">0</bool>
+          <bool name="proxy-wxDIALOG_MODAL">0</bool>
+          <bool name="proxy-wxNO_BORDER">0</bool>
+          <bool name="proxy-wxSIMPLE_BORDER">0</bool>
+          <bool name="proxy-wxDOUBLE_BORDER">0</bool>
+          <bool name="proxy-wxBORDER_THEME">0</bool>
+          <bool name="proxy-wxSUNKEN_BORDER">0</bool>
+          <bool name="proxy-wxRAISED_BORDER">0</bool>
+          <bool name="proxy-wxSTATIC_BORDER">0</bool>
+          <bool name="proxy-wxWANTS_CHARS">0</bool>
+          <bool name="proxy-wxNO_FULL_REPAINT_ON_RESIZE">0</bool>
+          <bool name="proxy-wxFULL_REPAINT_ON_RESIZE">0</bool>
+          <bool name="proxy-wxCLIP_CHILDREN">0</bool>
+          <bool name="proxy-wxTAB_TRAVERSAL">1</bool>
+          <bool name="proxy-wxWS_EX_VALIDATE_RECURSIVELY">0</bool>
+          <bool name="proxy-wxWS_EX_BLOCK_EVENTS">1</bool>
+          <bool name="proxy-wxWS_EX_TRANSIENT">0</bool>
+          <string name="proxy-Custom styles">""</string>
+          <bool name="proxy-wxDIALOG_EX_CONTEXTHELP">0</bool>
+          <bool name="proxy-Fit to content">1</bool>
+          <long name="proxy-X">-1</long>
+          <long name="proxy-Y">-1</long>
+          <long name="proxy-Width">-1</long>
+          <long name="proxy-Height">-1</long>
+          <bool name="proxy-AUI manager">0</bool>
+          <string name="proxy-Event sources">""</string>
+          <document>
+            <string name="title">"wxBoxSizer V"</string>
+            <string name="type">"dialog-control-document"</string>
+            <string name="filename">""</string>
+            <string name="icon-name">"sizer"</string>
+            <long name="is-transient">0</long>
+            <long name="owns-file">1</long>
+            <long name="title-mode">0</long>
+            <long name="locked">0</long>
+            <string name="proxy-type">"wbBoxSizerProxy"</string>
+            <string name="proxy-Orientation">"Vertical"</string>
+            <string name="proxy-Member variable name">""</string>
+            <bool name="proxy-wxSHAPED">0</bool>
+            <bool name="proxy-wxADJUST_MINSIZE">0</bool>
+            <bool name="proxy-wxFIXED_MINSIZE">0</bool>
+            <string name="proxy-Platform">"<Any platform>"</string>
+            <document>
+              <string name="title">"wxStaticText: wxID_STATIC_LABEL"</string>
+              <string name="type">"dialog-control-document"</string>
+              <string name="filename">""</string>
+              <string name="icon-name">"statictext"</string>
+              <long name="is-transient">0</long>
+              <long name="owns-file">1</long>
+              <long name="title-mode">0</long>
+              <long name="locked">0</long>
+              <string name="proxy-type">"wbStaticTextProxy"</string>
+              <string name="proxy-Id name">"wxID_STATIC_LABEL"</string>
+              <long name="proxy-Id value">10003</long>
+              <string name="proxy-Name">""</string>
+              <string name="proxy-Class">"wxStaticText"</string>
+              <string name="proxy-Base class">"wxStaticText"</string>
+              <bool name="proxy-External implementation">1</bool>
+              <bool name="proxy-Separate files">0</bool>
+              <string name="proxy-Implementation filename">""</string>
+              <string name="proxy-Header filename">""</string>
+              <string name="proxy-Member variable name">"m_staLabel"</string>
+              <string name="proxy-Label">""</string>
+              <long name="proxy-Wrapping width">-1</long>
+              <string name="proxy-Help text">""</string>
+              <string name="proxy-Tooltip text">""</string>
+              <string name="proxy-Background colour">""</string>
+              <string name="proxy-Foreground colour">""</string>
+              <string name="proxy-Font">""</string>
+              <bool name="proxy-Hidden">0</bool>
+              <bool name="proxy-Enabled">1</bool>
+              <string name="proxy-Platform">"<Any platform>"</string>
+              <string name="proxy-Data variable">""</string>
+              <string name="proxy-Data validator">""</string>
+              <string name="proxy-Data source">""</string>
+              <string name="proxy-Data class name">""</string>
+              <string name="proxy-Data class implementation filename">""</string>
+              <string name="proxy-Data class header filename">""</string>
+              <string name="proxy-Data class manager window">""</string>
+              <bool name="proxy-wxALIGN_LEFT">0</bool>
+              <bool name="proxy-wxALIGN_RIGHT">0</bool>
+              <bool name="proxy-wxALIGN_CENTRE">0</bool>
+              <bool name="proxy-wxST_NO_AUTORESIZE">0</bool>
+              <bool name="proxy-wxNO_BORDER">0</bool>
+              <bool name="proxy-wxSIMPLE_BORDER">0</bool>
+              <bool name="proxy-wxDOUBLE_BORDER">0</bool>
+              <bool name="proxy-wxBORDER_THEME">0</bool>
+              <bool name="proxy-wxSUNKEN_BORDER">0</bool>
+              <bool name="proxy-wxRAISED_BORDER">0</bool>
+              <bool name="proxy-wxSTATIC_BORDER">0</bool>
+              <bool name="proxy-wxWANTS_CHARS">0</bool>
+              <bool name="proxy-wxNO_FULL_REPAINT_ON_RESIZE">0</bool>
+              <bool name="proxy-wxFULL_REPAINT_ON_RESIZE">0</bool>
+              <string name="proxy-Custom styles">""</string>
+              <long name="proxy-X">-1</long>
+              <long name="proxy-Y">-1</long>
+              <long name="proxy-Width">-1</long>
+              <long name="proxy-Height">-1</long>
+              <string name="proxy-AlignH">"Left"</string>
+              <string name="proxy-AlignV">"Centre"</string>
+              <long name="proxy-Stretch factor">0</long>
+              <long name="proxy-Border">5</long>
+              <bool name="proxy-wxLEFT">1</bool>
+              <bool name="proxy-wxRIGHT">1</bool>
+              <bool name="proxy-wxTOP">0</bool>
+              <bool name="proxy-wxBOTTOM">0</bool>
+              <bool name="proxy-wxSHAPED">0</bool>
+              <bool name="proxy-wxADJUST_MINSIZE">0</bool>
+              <bool name="proxy-wxFIXED_MINSIZE">0</bool>
+              <string name="proxy-Custom arguments">""</string>
+              <string name="proxy-Custom ctor arguments">""</string>
+            </document>
+            <document>
+              <string name="title">"wxBoxSizer H"</string>
+              <string name="type">"dialog-control-document"</string>
+              <string name="filename">""</string>
+              <string name="icon-name">"sizer"</string>
+              <long name="is-transient">0</long>
+              <long name="owns-file">1</long>
+              <long name="title-mode">0</long>
+              <long name="locked">0</long>
+              <string name="proxy-type">"wbBoxSizerProxy"</string>
+              <string name="proxy-Orientation">"Horizontal"</string>
+              <string name="proxy-Member variable name">""</string>
+              <string name="proxy-AlignH">"Expand"</string>
+              <string name="proxy-AlignV">"Centre"</string>
+              <long name="proxy-Stretch factor">0</long>
+              <long name="proxy-Border">5</long>
+              <bool name="proxy-wxLEFT">0</bool>
+              <bool name="proxy-wxRIGHT">0</bool>
+              <bool name="proxy-wxTOP">0</bool>
+              <bool name="proxy-wxBOTTOM">0</bool>
+              <bool name="proxy-wxSHAPED">0</bool>
+              <bool name="proxy-wxADJUST_MINSIZE">0</bool>
+              <bool name="proxy-wxFIXED_MINSIZE">0</bool>
+              <string name="proxy-Platform">"<Any platform>"</string>
+              <document>
+                <string name="title">"wxSlider: ID_SLIDER_CONTROL"</string>
+                <string name="type">"dialog-control-document"</string>
+                <string name="filename">""</string>
+                <string name="icon-name">"slider"</string>
+                <long name="is-transient">0</long>
+                <long name="owns-file">1</long>
+                <long name="title-mode">0</long>
+                <long name="locked">0</long>
+                <string name="proxy-type">"wbSliderProxy"</string>
+                <string name="event-handler-0">"wxEVT_COMMAND_SLIDER_UPDATED|OnSliderControlUpdated|NONE||SliderPanel"</string>
+                <string name="proxy-Id name">"ID_SLIDER_CONTROL"</string>
+                <long name="proxy-Id value">10001</long>
+                <string name="proxy-Name">""</string>
+                <string name="proxy-Class">"wxSlider"</string>
+                <string name="proxy-Base class">"wxSlider"</string>
+                <bool name="proxy-External implementation">1</bool>
+                <bool name="proxy-Separate files">0</bool>
+                <string name="proxy-Implementation filename">""</string>
+                <string name="proxy-Header filename">""</string>
+                <string name="proxy-Member variable name">"m_sldSlider"</string>
+                <long name="proxy-Minimum value">0</long>
+                <long name="proxy-Maximum value">1</long>
+                <long name="proxy-Initial value">0</long>
+                <string name="proxy-Help text">""</string>
+                <string name="proxy-Tooltip text">""</string>
+                <string name="proxy-Background colour">""</string>
+                <string name="proxy-Foreground colour">""</string>
+                <string name="proxy-Font">""</string>
+                <bool name="proxy-Hidden">0</bool>
+                <bool name="proxy-Enabled">1</bool>
+                <string name="proxy-Platform">"<Any platform>"</string>
+                <string name="proxy-Data variable">""</string>
+                <string name="proxy-Data validator">""</string>
+                <string name="proxy-Data source">""</string>
+                <string name="proxy-Data class name">""</string>
+                <string name="proxy-Data class implementation filename">""</string>
+                <string name="proxy-Data class header filename">""</string>
+                <string name="proxy-Data class manager window">""</string>
+                <bool name="proxy-wxSL_HORIZONTAL">1</bool>
+                <bool name="proxy-wxSL_VERTICAL">0</bool>
+                <bool name="proxy-wxSL_AUTOTICKS">0</bool>
+                <bool name="proxy-wxSL_LABELS">0</bool>
+                <bool name="proxy-wxSL_LEFT">0</bool>
+                <bool name="proxy-wxSL_RIGHT">0</bool>
+                <bool name="proxy-wxSL_TOP">0</bool>
+                <bool name="proxy-wxSL_SELRANGE">0</bool>
+                <bool name="proxy-wxSL_INVERSE">0</bool>
+                <bool name="proxy-wxNO_BORDER">0</bool>
+                <bool name="proxy-wxSIMPLE_BORDER">0</bool>
+                <bool name="proxy-wxDOUBLE_BORDER">0</bool>
+                <bool name="proxy-wxBORDER_THEME">0</bool>
+                <bool name="proxy-wxSUNKEN_BORDER">0</bool>
+                <bool name="proxy-wxRAISED_BORDER">0</bool>
+                <bool name="proxy-wxSTATIC_BORDER">0</bool>
+                <bool name="proxy-wxWANTS_CHARS">0</bool>
+                <bool name="proxy-wxNO_FULL_REPAINT_ON_RESIZE">0</bool>
+                <bool name="proxy-wxFULL_REPAINT_ON_RESIZE">0</bool>
+                <string name="proxy-Custom styles">""</string>
+                <long name="proxy-X">-1</long>
+                <long name="proxy-Y">-1</long>
+                <long name="proxy-Width">150</long>
+                <long name="proxy-Height">-1</long>
+                <string name="proxy-AlignH">"Centre"</string>
+                <string name="proxy-AlignV">"Centre"</string>
+                <long name="proxy-Stretch factor">0</long>
+                <long name="proxy-Border">5</long>
+                <bool name="proxy-wxLEFT">1</bool>
+                <bool name="proxy-wxRIGHT">1</bool>
+                <bool name="proxy-wxTOP">1</bool>
+                <bool name="proxy-wxBOTTOM">1</bool>
+                <bool name="proxy-wxSHAPED">0</bool>
+                <bool name="proxy-wxADJUST_MINSIZE">0</bool>
+                <bool name="proxy-wxFIXED_MINSIZE">0</bool>
+                <string name="proxy-Custom arguments">""</string>
+                <string name="proxy-Custom ctor arguments">""</string>
+              </document>
+              <document>
+                <string name="title">"wxTextCtrl: ID_TEXTCTRL"</string>
+                <string name="type">"dialog-control-document"</string>
+                <string name="filename">""</string>
+                <string name="icon-name">"textctrl"</string>
+                <long name="is-transient">0</long>
+                <long name="owns-file">1</long>
+                <long name="title-mode">0</long>
+                <long name="locked">0</long>
+                <string name="proxy-type">"wbTextCtrlProxy"</string>
+                <string name="proxy-Id name">"ID_TEXTCTRL"</string>
+                <long name="proxy-Id value">10002</long>
+                <string name="proxy-Name">""</string>
+                <string name="proxy-Class">"wxTextCtrl"</string>
+                <string name="proxy-Base class">"wxTextCtrl"</string>
+                <bool name="proxy-External implementation">1</bool>
+                <bool name="proxy-Separate files">0</bool>
+                <string name="proxy-Implementation filename">""</string>
+                <string name="proxy-Header filename">""</string>
+                <string name="proxy-Member variable name">"m_txtNumber"</string>
+                <string name="proxy-Initial value">""</string>
+                <long name="proxy-Max length">0</long>
+                <string name="proxy-Help text">""</string>
+                <string name="proxy-Tooltip text">""</string>
+                <string name="proxy-Background colour">""</string>
+                <string name="proxy-Foreground colour">""</string>
+                <string name="proxy-Font">""</string>
+                <bool name="proxy-Hidden">0</bool>
+                <bool name="proxy-Enabled">1</bool>
+                <string name="proxy-Platform">"<Any platform>"</string>
+                <string name="proxy-Data variable">""</string>
+                <string name="proxy-Data validator">""</string>
+                <string name="proxy-Data source">""</string>
+                <string name="proxy-Data class name">""</string>
+                <string name="proxy-Data class implementation filename">""</string>
+                <string name="proxy-Data class header filename">""</string>
+                <string name="proxy-Data class manager window">""</string>
+                <bool name="proxy-wxTE_MULTILINE">0</bool>
+                <bool name="proxy-wxTE_PROCESS_ENTER">0</bool>
+                <bool name="proxy-wxTE_PROCESS_TAB">0</bool>
+                <bool name="proxy-wxTE_PASSWORD">0</bool>
+                <bool name="proxy-wxTE_READONLY">1</bool>
+                <bool name="proxy-wxTE_RICH">0</bool>
+                <bool name="proxy-wxTE_RICH2">0</bool>
+                <bool name="proxy-wxTE_AUTO_URL">0</bool>
+                <bool name="proxy-wxTE_NOHIDESEL">0</bool>
+                <bool name="proxy-wxTE_LEFT">0</bool>
+                <bool name="proxy-wxTE_CENTRE">0</bool>
+                <bool name="proxy-wxTE_RIGHT">1</bool>
+                <bool name="proxy-wxHSCROLL">0</bool>
+                <bool name="proxy-wxTE_CHARWRAP">0</bool>
+                <bool name="proxy-wxTE_WORDWRAP">0</bool>
+                <bool name="proxy-wxTE_CAPITALIZE">0</bool>
+                <bool name="proxy-wxNO_BORDER">0</bool>
+                <bool name="proxy-wxSIMPLE_BORDER">0</bool>
+                <bool name="proxy-wxDOUBLE_BORDER">0</bool>
+                <bool name="proxy-wxBORDER_THEME">0</bool>
+                <bool name="proxy-wxSUNKEN_BORDER">0</bool>
+                <bool name="proxy-wxRAISED_BORDER">0</bool>
+                <bool name="proxy-wxSTATIC_BORDER">0</bool>
+                <bool name="proxy-wxWANTS_CHARS">0</bool>
+                <bool name="proxy-wxNO_FULL_REPAINT_ON_RESIZE">0</bool>
+                <bool name="proxy-wxFULL_REPAINT_ON_RESIZE">0</bool>
+                <string name="proxy-Custom styles">""</string>
+                <long name="proxy-X">-1</long>
+                <long name="proxy-Y">-1</long>
+                <long name="proxy-Width">75</long>
+                <long name="proxy-Height">-1</long>
+                <string name="proxy-AlignH">"Centre"</string>
+                <string name="proxy-AlignV">"Centre"</string>
+                <long name="proxy-Stretch factor">0</long>
+                <long name="proxy-Border">5</long>
+                <bool name="proxy-wxLEFT">1</bool>
+                <bool name="proxy-wxRIGHT">1</bool>
+                <bool name="proxy-wxTOP">1</bool>
+                <bool name="proxy-wxBOTTOM">1</bool>
+                <bool name="proxy-wxSHAPED">0</bool>
+                <bool name="proxy-wxADJUST_MINSIZE">0</bool>
+                <bool name="proxy-wxFIXED_MINSIZE">0</bool>
+                <string name="proxy-Custom arguments">""</string>
+                <string name="proxy-Custom ctor arguments">""</string>
+              </document>
+            </document>
+          </document>
+        </document>
+        <document>
+          <string name="title">"Checkbox"</string>
+          <string name="type">"dialog-document"</string>
+          <string name="filename">""</string>
+          <string name="icon-name">"dialog"</string>
+          <long name="is-transient">0</long>
+          <long name="owns-file">1</long>
+          <long name="title-mode">0</long>
+          <long name="locked">0</long>
+          <string name="proxy-type">"wbDialogProxy"</string>
+          <long name="base-id">10000</long>
+          <bool name="use-id-prefix">0</bool>
+          <string name="id-prefix">""</string>
+          <bool name="use-id-suffix">0</bool>
+          <string name="id-suffix">""</string>
+          <string name="app-kind">"Standard"</string>
+          <long name="use-xrc">0</long>
+          <long name="working-mode">0</long>
+          <string name="proxy-Id name">"ID_CHECKBOXPANEL"</string>
+          <long name="proxy-Id value">10004</long>
+          <string name="proxy-Class">"CheckboxPanel"</string>
+          <string name="proxy-Base class">"wxPanel"</string>
+          <string name="proxy-Window kind">"wxPanel"</string>
+          <string name="proxy-Implementation filename">"checkbox.cpp"</string>
+          <string name="proxy-Header filename">"checkbox.h"</string>
+          <string name="proxy-XRC filename">""</string>
+          <string name="proxy-Title">""</string>
+          <bool name="proxy-Centre">1</bool>
+          <string name="proxy-Icon">""</string>
+          <bool name="proxy-Dialog units">0</bool>
+          <string name="proxy-Help text">""</string>
+          <string name="proxy-Tooltip text">""</string>
+          <string name="proxy-Background colour">""</string>
+          <string name="proxy-Foreground colour">""</string>
+          <string name="proxy-Font">""</string>
+          <bool name="proxy-Hidden">0</bool>
+          <bool name="proxy-Enabled">1</bool>
+          <string name="proxy-Platform">"<Any platform>"</string>
+          <string name="proxy-Data source">""</string>
+          <string name="proxy-Data class name">""</string>
+          <string name="proxy-Data class implementation filename">""</string>
+          <string name="proxy-Data class header filename">""</string>
+          <string name="proxy-Data class manager window">""</string>
+          <string name="proxy-Texture">""</string>
+          <string name="proxy-Texture style">"Tiled"</string>
+          <bool name="proxy-wxDEFAULT_DIALOG_STYLE">0</bool>
+          <bool name="proxy-wxCAPTION">0</bool>
+          <bool name="proxy-wxRESIZE_BORDER">0</bool>
+          <bool name="proxy-wxSYSTEM_MENU">0</bool>
+          <bool name="proxy-wxSTAY_ON_TOP">0</bool>
+          <bool name="proxy-wxDIALOG_NO_PARENT">0</bool>
+          <bool name="proxy-wxCLOSE_BOX">0</bool>
+          <bool name="proxy-wxMAXIMIZE_BOX">0</bool>
+          <bool name="proxy-wxMINIMIZE_BOX">0</bool>
+          <bool name="proxy-wxDIALOG_MODAL">0</bool>
+          <bool name="proxy-wxNO_BORDER">0</bool>
+          <bool name="proxy-wxSIMPLE_BORDER">0</bool>
+          <bool name="proxy-wxDOUBLE_BORDER">0</bool>
+          <bool name="proxy-wxBORDER_THEME">0</bool>
+          <bool name="proxy-wxSUNKEN_BORDER">0</bool>
+          <bool name="proxy-wxRAISED_BORDER">0</bool>
+          <bool name="proxy-wxSTATIC_BORDER">0</bool>
+          <bool name="proxy-wxWANTS_CHARS">0</bool>
+          <bool name="proxy-wxNO_FULL_REPAINT_ON_RESIZE">0</bool>
+          <bool name="proxy-wxFULL_REPAINT_ON_RESIZE">0</bool>
+          <bool name="proxy-wxCLIP_CHILDREN">0</bool>
+          <bool name="proxy-wxTAB_TRAVERSAL">1</bool>
+          <bool name="proxy-wxWS_EX_VALIDATE_RECURSIVELY">0</bool>
+          <bool name="proxy-wxWS_EX_BLOCK_EVENTS">1</bool>
+          <bool name="proxy-wxWS_EX_TRANSIENT">0</bool>
+          <string name="proxy-Custom styles">""</string>
+          <bool name="proxy-wxDIALOG_EX_CONTEXTHELP">0</bool>
+          <bool name="proxy-Fit to content">1</bool>
+          <long name="proxy-X">-1</long>
+          <long name="proxy-Y">-1</long>
+          <long name="proxy-Width">-1</long>
+          <long name="proxy-Height">-1</long>
+          <bool name="proxy-AUI manager">0</bool>
+          <string name="proxy-Event sources">""</string>
+          <document>
+            <string name="title">"wxBoxSizer V"</string>
+            <string name="type">"dialog-control-document"</string>
+            <string name="filename">""</string>
+            <string name="icon-name">"sizer"</string>
+            <long name="is-transient">0</long>
+            <long name="owns-file">1</long>
+            <long name="title-mode">0</long>
+            <long name="locked">0</long>
+            <string name="proxy-type">"wbBoxSizerProxy"</string>
+            <string name="proxy-Orientation">"Vertical"</string>
+            <string name="proxy-Member variable name">""</string>
+            <string name="proxy-AlignH">"Centre"</string>
+            <string name="proxy-AlignV">"Centre"</string>
+            <long name="proxy-Stretch factor">0</long>
+            <long name="proxy-Border">5</long>
+            <bool name="proxy-wxLEFT">1</bool>
+            <bool name="proxy-wxRIGHT">1</bool>
+            <bool name="proxy-wxTOP">1</bool>
+            <bool name="proxy-wxBOTTOM">1</bool>
+            <bool name="proxy-wxSHAPED">0</bool>
+            <bool name="proxy-wxADJUST_MINSIZE">0</bool>
+            <bool name="proxy-wxFIXED_MINSIZE">0</bool>
+            <string name="proxy-Platform">"<Any platform>"</string>
+            <document>
+              <string name="title">"wxCheckBox: ID_CHECKBOX"</string>
+              <string name="type">"dialog-control-document"</string>
+              <string name="filename">""</string>
+              <string name="icon-name">"checkbox"</string>
+              <long name="is-transient">0</long>
+              <long name="owns-file">1</long>
+              <long name="title-mode">0</long>
+              <long name="locked">0</long>
+              <string name="proxy-type">"wbCheckBoxProxy"</string>
+              <string name="event-handler-0">"wxEVT_COMMAND_CHECKBOX_CLICKED|OnCheckboxClick|NONE||CheckboxPanel"</string>
+              <string name="proxy-Id name">"ID_CHECKBOX"</string>
+              <long name="proxy-Id value">10005</long>
+              <string name="proxy-Name">"Checkbox"</string>
+              <string name="proxy-Class">"wxCheckBox"</string>
+              <string name="proxy-Base class">"wxCheckBox"</string>
+              <bool name="proxy-External implementation">1</bool>
+              <bool name="proxy-Separate files">0</bool>
+              <string name="proxy-Implementation filename">""</string>
+              <string name="proxy-Header filename">""</string>
+              <string name="proxy-Member variable name">"m_theCheckbox"</string>
+              <string name="proxy-Label">""</string>
+              <bool name="proxy-Initial value">0</bool>
+              <string name="proxy-Help text">""</string>
+              <string name="proxy-Tooltip text">""</string>
+              <string name="proxy-Data variable">""</string>
+              <string name="proxy-Data validator">""</string>
+              <string name="proxy-Data source">""</string>
+              <string name="proxy-Data class name">""</string>
+              <string name="proxy-Data class implementation filename">""</string>
+              <string name="proxy-Data class header filename">""</string>
+              <string name="proxy-Data class manager window">""</string>
+              <string name="proxy-Background colour">""</string>
+              <string name="proxy-Foreground colour">""</string>
+              <string name="proxy-Font">""</string>
+              <bool name="proxy-Hidden">0</bool>
+              <bool name="proxy-Enabled">1</bool>
+              <string name="proxy-Platform">"<Any platform>"</string>
+              <bool name="proxy-wxALIGN_RIGHT">0</bool>
+              <bool name="proxy-wxCHK_2STATE">0</bool>
+              <bool name="proxy-wxCHK_3STATE">0</bool>
+              <bool name="proxy-wxCHK_ALLOW_3RD_STATE_FOR_USER">0</bool>
+              <bool name="proxy-wxWANTS_CHARS">0</bool>
+              <bool name="proxy-wxNO_FULL_REPAINT_ON_RESIZE">0</bool>
+              <bool name="proxy-wxFULL_REPAINT_ON_RESIZE">0</bool>
+              <string name="proxy-Custom styles">""</string>
+              <long name="proxy-X">-1</long>
+              <long name="proxy-Y">-1</long>
+              <long name="proxy-Width">-1</long>
+              <long name="proxy-Height">-1</long>
+              <string name="proxy-AlignH">"Centre"</string>
+              <string name="proxy-AlignV">"Centre"</string>
+              <long name="proxy-Stretch factor">0</long>
+              <long name="proxy-Border">5</long>
+              <bool name="proxy-wxLEFT">1</bool>
+              <bool name="proxy-wxRIGHT">1</bool>
+              <bool name="proxy-wxTOP">1</bool>
+              <bool name="proxy-wxBOTTOM">1</bool>
+              <bool name="proxy-wxSHAPED">0</bool>
+              <bool name="proxy-wxADJUST_MINSIZE">0</bool>
+              <bool name="proxy-wxFIXED_MINSIZE">0</bool>
+              <string name="proxy-Custom arguments">""</string>
+              <string name="proxy-Custom ctor arguments">""</string>
+            </document>
+          </document>
+        </document>
+        <document>
+          <string name="title">"FilePicker"</string>
+          <string name="type">"dialog-document"</string>
+          <string name="filename">""</string>
+          <string name="icon-name">"dialog"</string>
+          <long name="is-transient">0</long>
+          <long name="owns-file">1</long>
+          <long name="title-mode">0</long>
+          <long name="locked">0</long>
+          <string name="proxy-type">"wbDialogProxy"</string>
+          <long name="base-id">10000</long>
+          <bool name="use-id-prefix">0</bool>
+          <string name="id-prefix">""</string>
+          <bool name="use-id-suffix">0</bool>
+          <string name="id-suffix">""</string>
+          <string name="app-kind">"Standard"</string>
+          <long name="use-xrc">0</long>
+          <long name="working-mode">0</long>
+          <string name="proxy-Id name">"ID_FILEPICKERPANEL"</string>
+          <long name="proxy-Id value">10006</long>
+          <string name="proxy-Class">"FilePickerPanel"</string>
+          <string name="proxy-Base class">"wxPanel"</string>
+          <string name="proxy-Window kind">"wxPanel"</string>
+          <string name="proxy-Implementation filename">"filepicker.cpp"</string>
+          <string name="proxy-Header filename">"filepicker.h"</string>
+          <string name="proxy-XRC filename">""</string>
+          <string name="proxy-Title">"FilePicker"</string>
+          <bool name="proxy-Centre">1</bool>
+          <string name="proxy-Icon">""</string>
+          <bool name="proxy-Dialog units">0</bool>
+          <string name="proxy-Help text">""</string>
+          <string name="proxy-Tooltip text">""</string>
+          <string name="proxy-Background colour">""</string>
+          <string name="proxy-Foreground colour">""</string>
+          <string name="proxy-Font">""</string>
+          <bool name="proxy-Hidden">0</bool>
+          <bool name="proxy-Enabled">1</bool>
+          <string name="proxy-Platform">"<Any platform>"</string>
+          <string name="proxy-Data source">""</string>
+          <string name="proxy-Data class name">""</string>
+          <string name="proxy-Data class implementation filename">""</string>
+          <string name="proxy-Data class header filename">""</string>
+          <string name="proxy-Data class manager window">""</string>
+          <string name="proxy-Texture">""</string>
+          <string name="proxy-Texture style">"Tiled"</string>
+          <bool name="proxy-wxDEFAULT_DIALOG_STYLE">0</bool>
+          <bool name="proxy-wxCAPTION">0</bool>
+          <bool name="proxy-wxRESIZE_BORDER">0</bool>
+          <bool name="proxy-wxSYSTEM_MENU">0</bool>
+          <bool name="proxy-wxSTAY_ON_TOP">0</bool>
+          <bool name="proxy-wxDIALOG_NO_PARENT">0</bool>
+          <bool name="proxy-wxCLOSE_BOX">0</bool>
+          <bool name="proxy-wxMAXIMIZE_BOX">0</bool>
+          <bool name="proxy-wxMINIMIZE_BOX">0</bool>
+          <bool name="proxy-wxDIALOG_MODAL">0</bool>
+          <bool name="proxy-wxNO_BORDER">0</bool>
+          <bool name="proxy-wxSIMPLE_BORDER">0</bool>
+          <bool name="proxy-wxDOUBLE_BORDER">0</bool>
+          <bool name="proxy-wxBORDER_THEME">0</bool>
+          <bool name="proxy-wxSUNKEN_BORDER">0</bool>
+          <bool name="proxy-wxRAISED_BORDER">0</bool>
+          <bool name="proxy-wxSTATIC_BORDER">0</bool>
+          <bool name="proxy-wxWANTS_CHARS">0</bool>
+          <bool name="proxy-wxNO_FULL_REPAINT_ON_RESIZE">0</bool>
+          <bool name="proxy-wxFULL_REPAINT_ON_RESIZE">0</bool>
+          <bool name="proxy-wxCLIP_CHILDREN">0</bool>
+          <bool name="proxy-wxTAB_TRAVERSAL">1</bool>
+          <bool name="proxy-wxWS_EX_VALIDATE_RECURSIVELY">0</bool>
+          <bool name="proxy-wxWS_EX_BLOCK_EVENTS">1</bool>
+          <bool name="proxy-wxWS_EX_TRANSIENT">0</bool>
+          <string name="proxy-Custom styles">""</string>
+          <bool name="proxy-wxDIALOG_EX_CONTEXTHELP">0</bool>
+          <bool name="proxy-Fit to content">1</bool>
+          <long name="proxy-X">-1</long>
+          <long name="proxy-Y">-1</long>
+          <long name="proxy-Width">-1</long>
+          <long name="proxy-Height">-1</long>
+          <bool name="proxy-AUI manager">0</bool>
+          <string name="proxy-Event sources">""</string>
+          <document>
+            <string name="title">"wxBoxSizer V"</string>
+            <string name="type">"dialog-control-document"</string>
+            <string name="filename">""</string>
+            <string name="icon-name">"sizer"</string>
+            <long name="is-transient">0</long>
+            <long name="owns-file">1</long>
+            <long name="title-mode">0</long>
+            <long name="locked">0</long>
+            <string name="proxy-type">"wbBoxSizerProxy"</string>
+            <string name="proxy-Orientation">"Vertical"</string>
+            <string name="proxy-Member variable name">""</string>
+            <string name="proxy-AlignH">"Centre"</string>
+            <string name="proxy-AlignV">"Centre"</string>
+            <long name="proxy-Stretch factor">0</long>
+            <long name="proxy-Border">5</long>
+            <bool name="proxy-wxLEFT">1</bool>
+            <bool name="proxy-wxRIGHT">1</bool>
+            <bool name="proxy-wxTOP">1</bool>
+            <bool name="proxy-wxBOTTOM">1</bool>
+            <bool name="proxy-wxSHAPED">0</bool>
+            <bool name="proxy-wxADJUST_MINSIZE">0</bool>
+            <bool name="proxy-wxFIXED_MINSIZE">0</bool>
+            <string name="proxy-Platform">"<Any platform>"</string>
+            <document>
+              <string name="title">"wxStaticBoxSizer H"</string>
+              <string name="type">"dialog-control-document"</string>
+              <string name="filename">""</string>
+              <string name="icon-name">"sizer"</string>
+              <long name="is-transient">0</long>
+              <long name="owns-file">1</long>
+              <long name="title-mode">0</long>
+              <long name="locked">0</long>
+              <string name="proxy-type">"wbStaticBoxSizerProxy"</string>
+              <string name="proxy-Id name">"wxID_ANY"</string>
+              <long name="proxy-Id value">-1</long>
+              <string name="proxy-Label">""</string>
+              <string name="proxy-Member variable name">"m_staSizer"</string>
+              <string name="proxy-Sizer member variable name">""</string>
+              <string name="proxy-Foreground colour">""</string>
+              <string name="proxy-Font">""</string>
+              <bool name="proxy-Hidden">0</bool>
+              <bool name="proxy-Enabled">1</bool>
+              <string name="proxy-Parenting">"Use wxWidgets version"</string>
+              <string name="proxy-Static box class">"wxStaticBox"</string>
+              <string name="proxy-Orientation">"Horizontal"</string>
+              <string name="proxy-AlignH">"Expand"</string>
+              <string name="proxy-AlignV">"Centre"</string>
+              <long name="proxy-Stretch factor">0</long>
+              <long name="proxy-Border">5</long>
+              <bool name="proxy-wxLEFT">1</bool>
+              <bool name="proxy-wxRIGHT">1</bool>
+              <bool name="proxy-wxTOP">0</bool>
+              <bool name="proxy-wxBOTTOM">0</bool>
+              <bool name="proxy-wxSHAPED">0</bool>
+              <bool name="proxy-wxADJUST_MINSIZE">0</bool>
+              <bool name="proxy-wxFIXED_MINSIZE">0</bool>
+              <string name="proxy-Platform">"<Any platform>"</string>
+              <document>
+                <string name="title">"wxTextCtrl: ID_TEXTCTRL_FILE_PATH"</string>
+                <string name="type">"dialog-control-document"</string>
+                <string name="filename">""</string>
+                <string name="icon-name">"textctrl"</string>
+                <long name="is-transient">0</long>
+                <long name="owns-file">1</long>
+                <long name="title-mode">0</long>
+                <long name="locked">0</long>
+                <string name="proxy-type">"wbTextCtrlProxy"</string>
+                <string name="proxy-Id name">"ID_TEXTCTRL_FILE_PATH"</string>
+                <long name="proxy-Id value">10007</long>
+                <string name="proxy-Name">""</string>
+                <string name="proxy-Class">"wxTextCtrl"</string>
+                <string name="proxy-Base class">"wxTextCtrl"</string>
+                <bool name="proxy-External implementation">1</bool>
+                <bool name="proxy-Separate files">0</bool>
+                <string name="proxy-Implementation filename">""</string>
+                <string name="proxy-Header filename">""</string>
+                <string name="proxy-Member variable name">"m_txtFilePath"</string>
+                <string name="proxy-Initial value">""</string>
+                <long name="proxy-Max length">0</long>
+                <string name="proxy-Help text">""</string>
+                <string name="proxy-Tooltip text">""</string>
+                <string name="proxy-Background colour">""</string>
+                <string name="proxy-Foreground colour">""</string>
+                <string name="proxy-Font">""</string>
+                <bool name="proxy-Hidden">0</bool>
+                <bool name="proxy-Enabled">1</bool>
+                <string name="proxy-Platform">"<Any platform>"</string>
+                <string name="proxy-Data variable">""</string>
+                <string name="proxy-Data validator">""</string>
+                <string name="proxy-Data source">""</string>
+                <string name="proxy-Data class name">""</string>
+                <string name="proxy-Data class implementation filename">""</string>
+                <string name="proxy-Data class header filename">""</string>
+                <string name="proxy-Data class manager window">""</string>
+                <bool name="proxy-wxTE_MULTILINE">0</bool>
+                <bool name="proxy-wxTE_PROCESS_ENTER">0</bool>
+                <bool name="proxy-wxTE_PROCESS_TAB">0</bool>
+                <bool name="proxy-wxTE_PASSWORD">0</bool>
+                <bool name="proxy-wxTE_READONLY">1</bool>
+                <bool name="proxy-wxTE_RICH">0</bool>
+                <bool name="proxy-wxTE_RICH2">0</bool>
+                <bool name="proxy-wxTE_AUTO_URL">0</bool>
+                <bool name="proxy-wxTE_NOHIDESEL">0</bool>
+                <bool name="proxy-wxTE_LEFT">0</bool>
+                <bool name="proxy-wxTE_CENTRE">0</bool>
+                <bool name="proxy-wxTE_RIGHT">0</bool>
+                <bool name="proxy-wxHSCROLL">0</bool>
+                <bool name="proxy-wxTE_CHARWRAP">0</bool>
+                <bool name="proxy-wxTE_WORDWRAP">0</bool>
+                <bool name="proxy-wxTE_CAPITALIZE">0</bool>
+                <bool name="proxy-wxNO_BORDER">0</bool>
+                <bool name="proxy-wxSIMPLE_BORDER">0</bool>
+                <bool name="proxy-wxDOUBLE_BORDER">0</bool>
+                <bool name="proxy-wxBORDER_THEME">0</bool>
+                <bool name="proxy-wxSUNKEN_BORDER">0</bool>
+                <bool name="proxy-wxRAISED_BORDER">0</bool>
+                <bool name="proxy-wxSTATIC_BORDER">0</bool>
+                <bool name="proxy-wxWANTS_CHARS">0</bool>
+                <bool name="proxy-wxNO_FULL_REPAINT_ON_RESIZE">0</bool>
+                <bool name="proxy-wxFULL_REPAINT_ON_RESIZE">0</bool>
+                <string name="proxy-Custom styles">""</string>
+                <long name="proxy-X">-1</long>
+                <long name="proxy-Y">-1</long>
+                <long name="proxy-Width">200</long>
+                <long name="proxy-Height">-1</long>
+                <string name="proxy-AlignH">"Left"</string>
+                <string name="proxy-AlignV">"Centre"</string>
+                <long name="proxy-Stretch factor">0</long>
+                <long name="proxy-Border">5</long>
+                <bool name="proxy-wxLEFT">1</bool>
+                <bool name="proxy-wxRIGHT">1</bool>
+                <bool name="proxy-wxTOP">1</bool>
+                <bool name="proxy-wxBOTTOM">1</bool>
+                <bool name="proxy-wxSHAPED">0</bool>
+                <bool name="proxy-wxADJUST_MINSIZE">0</bool>
+                <bool name="proxy-wxFIXED_MINSIZE">0</bool>
+                <string name="proxy-Custom arguments">""</string>
+                <string name="proxy-Custom ctor arguments">""</string>
+              </document>
+              <document>
+                <string name="title">"wxButton: ID_BUTTON_CHOOSE"</string>
+                <string name="type">"dialog-control-document"</string>
+                <string name="filename">""</string>
+                <string name="icon-name">"dialogcontrol"</string>
+                <long name="is-transient">0</long>
+                <long name="owns-file">1</long>
+                <long name="title-mode">0</long>
+                <long name="locked">0</long>
+                <string name="proxy-type">"wbButtonProxy"</string>
+                <string name="event-handler-0">"wxEVT_COMMAND_BUTTON_CLICKED|OnButtonChooseClick|NONE||FilePickerPanel"</string>
+                <string name="proxy-Id name">"ID_BUTTON_CHOOSE"</string>
+                <long name="proxy-Id value">10008</long>
+                <string name="proxy-Name">""</string>
+                <string name="proxy-Class">"wxButton"</string>
+                <string name="proxy-Base class">"wxButton"</string>
+                <bool name="proxy-External implementation">1</bool>
+                <bool name="proxy-Separate files">0</bool>
+                <string name="proxy-Implementation filename">""</string>
+                <string name="proxy-Header filename">""</string>
+                <string name="proxy-Member variable name">""</string>
+                <string name="proxy-Label">"Choose..."</string>
+                <bool name="proxy-Default">0</bool>
+                <string name="proxy-Help text">""</string>
+                <string name="proxy-Tooltip text">""</string>
+                <string name="proxy-Data variable">""</string>
+                <string name="proxy-Data validator">""</string>
+                <string name="proxy-Data source">""</string>
+                <string name="proxy-Data class name">""</string>
+                <string name="proxy-Data class implementation filename">""</string>
+                <string name="proxy-Data class header filename">""</string>
+                <string name="proxy-Data class manager window">""</string>
+                <string name="proxy-Background colour">""</string>
+                <string name="proxy-Foreground colour">""</string>
+                <string name="proxy-Font">""</string>
+                <bool name="proxy-Hidden">0</bool>
+                <bool name="proxy-Enabled">1</bool>
+                <string name="proxy-Platform">"<Any platform>"</string>
+                <bool name="proxy-wxBU_LEFT">0</bool>
+                <bool name="proxy-wxBU_RIGHT">0</bool>
+                <bool name="proxy-wxBU_TOP">0</bool>
+                <bool name="proxy-wxBU_BOTTOM">0</bool>
+                <bool name="proxy-wxBU_EXACTFIT">0</bool>
+                <bool name="proxy-wxNO_BORDER">0</bool>
+                <bool name="proxy-wxWANTS_CHARS">0</bool>
+                <bool name="proxy-wxNO_FULL_REPAINT_ON_RESIZE">0</bool>
+                <bool name="proxy-wxFULL_REPAINT_ON_RESIZE">0</bool>
+                <string name="proxy-Custom styles">""</string>
+                <long name="proxy-X">-1</long>
+                <long name="proxy-Y">-1</long>
+                <long name="proxy-Width">-1</long>
+                <long name="proxy-Height">-1</long>
+                <string name="proxy-AlignH">"Centre"</string>
+                <string name="proxy-AlignV">"Centre"</string>
+                <long name="proxy-Stretch factor">0</long>
+                <long name="proxy-Border">5</long>
+                <bool name="proxy-wxLEFT">1</bool>
+                <bool name="proxy-wxRIGHT">1</bool>
+                <bool name="proxy-wxTOP">1</bool>
+                <bool name="proxy-wxBOTTOM">1</bool>
+                <bool name="proxy-wxSHAPED">0</bool>
+                <bool name="proxy-wxADJUST_MINSIZE">0</bool>
+                <bool name="proxy-wxFIXED_MINSIZE">0</bool>
+                <string name="proxy-Custom arguments">""</string>
+                <string name="proxy-Custom ctor arguments">""</string>
+              </document>
+            </document>
+          </document>
+        </document>
+        <document>
+          <string name="title">"Choice"</string>
+          <string name="type">"dialog-document"</string>
+          <string name="filename">""</string>
+          <string name="icon-name">"dialog"</string>
+          <long name="is-transient">0</long>
+          <long name="owns-file">1</long>
+          <long name="title-mode">0</long>
+          <long name="locked">0</long>
+          <string name="proxy-type">"wbDialogProxy"</string>
+          <long name="base-id">10000</long>
+          <bool name="use-id-prefix">0</bool>
+          <string name="id-prefix">""</string>
+          <bool name="use-id-suffix">0</bool>
+          <string name="id-suffix">""</string>
+          <string name="app-kind">"Standard"</string>
+          <long name="use-xrc">0</long>
+          <long name="working-mode">0</long>
+          <string name="proxy-Id name">"ID_CHOICEPANEL"</string>
+          <long name="proxy-Id value">10009</long>
+          <string name="proxy-Class">"ChoicePanel"</string>
+          <string name="proxy-Base class">"wxPanel"</string>
+          <string name="proxy-Window kind">"wxPanel"</string>
+          <string name="proxy-Implementation filename">"choice.cpp"</string>
+          <string name="proxy-Header filename">"choice.h"</string>
+          <string name="proxy-XRC filename">""</string>
+          <string name="proxy-Title">"Choice"</string>
+          <bool name="proxy-Centre">1</bool>
+          <string name="proxy-Icon">""</string>
+          <bool name="proxy-Dialog units">0</bool>
+          <string name="proxy-Help text">""</string>
+          <string name="proxy-Tooltip text">""</string>
+          <string name="proxy-Background colour">""</string>
+          <string name="proxy-Foreground colour">""</string>
+          <string name="proxy-Font">""</string>
+          <bool name="proxy-Hidden">0</bool>
+          <bool name="proxy-Enabled">1</bool>
+          <string name="proxy-Platform">"<Any platform>"</string>
+          <string name="proxy-Data source">""</string>
+          <string name="proxy-Data class name">""</string>
+          <string name="proxy-Data class implementation filename">""</string>
+          <string name="proxy-Data class header filename">""</string>
+          <string name="proxy-Data class manager window">""</string>
+          <string name="proxy-Texture">""</string>
+          <string name="proxy-Texture style">"Tiled"</string>
+          <bool name="proxy-wxDEFAULT_DIALOG_STYLE">0</bool>
+          <bool name="proxy-wxCAPTION">0</bool>
+          <bool name="proxy-wxRESIZE_BORDER">0</bool>
+          <bool name="proxy-wxSYSTEM_MENU">0</bool>
+          <bool name="proxy-wxSTAY_ON_TOP">0</bool>
+          <bool name="proxy-wxDIALOG_NO_PARENT">0</bool>
+          <bool name="proxy-wxCLOSE_BOX">0</bool>
+          <bool name="proxy-wxMAXIMIZE_BOX">0</bool>
+          <bool name="proxy-wxMINIMIZE_BOX">0</bool>
+          <bool name="proxy-wxDIALOG_MODAL">0</bool>
+          <bool name="proxy-wxNO_BORDER">0</bool>
+          <bool name="proxy-wxSIMPLE_BORDER">0</bool>
+          <bool name="proxy-wxDOUBLE_BORDER">0</bool>
+          <bool name="proxy-wxBORDER_THEME">0</bool>
+          <bool name="proxy-wxSUNKEN_BORDER">0</bool>
+          <bool name="proxy-wxRAISED_BORDER">0</bool>
+          <bool name="proxy-wxSTATIC_BORDER">0</bool>
+          <bool name="proxy-wxWANTS_CHARS">0</bool>
+          <bool name="proxy-wxNO_FULL_REPAINT_ON_RESIZE">0</bool>
+          <bool name="proxy-wxFULL_REPAINT_ON_RESIZE">0</bool>
+          <bool name="proxy-wxCLIP_CHILDREN">0</bool>
+          <bool name="proxy-wxTAB_TRAVERSAL">1</bool>
+          <bool name="proxy-wxWS_EX_VALIDATE_RECURSIVELY">0</bool>
+          <bool name="proxy-wxWS_EX_BLOCK_EVENTS">1</bool>
+          <bool name="proxy-wxWS_EX_TRANSIENT">0</bool>
+          <string name="proxy-Custom styles">""</string>
+          <bool name="proxy-wxDIALOG_EX_CONTEXTHELP">0</bool>
+          <bool name="proxy-Fit to content">1</bool>
+          <long name="proxy-X">-1</long>
+          <long name="proxy-Y">-1</long>
+          <long name="proxy-Width">400</long>
+          <long name="proxy-Height">300</long>
+          <bool name="proxy-AUI manager">0</bool>
+          <string name="proxy-Event sources">""</string>
+          <document>
+            <string name="title">"wxBoxSizer V"</string>
+            <string name="type">"dialog-control-document"</string>
+            <string name="filename">""</string>
+            <string name="icon-name">"sizer"</string>
+            <long name="is-transient">0</long>
+            <long name="owns-file">1</long>
+            <long name="title-mode">0</long>
+            <long name="locked">0</long>
+            <string name="proxy-type">"wbBoxSizerProxy"</string>
+            <string name="proxy-Orientation">"Vertical"</string>
+            <string name="proxy-Member variable name">""</string>
+            <string name="proxy-AlignH">"Centre"</string>
+            <string name="proxy-AlignV">"Centre"</string>
+            <long name="proxy-Stretch factor">0</long>
+            <long name="proxy-Border">5</long>
+            <bool name="proxy-wxLEFT">1</bool>
+            <bool name="proxy-wxRIGHT">1</bool>
+            <bool name="proxy-wxTOP">1</bool>
+            <bool name="proxy-wxBOTTOM">1</bool>
+            <bool name="proxy-wxSHAPED">0</bool>
+            <bool name="proxy-wxADJUST_MINSIZE">0</bool>
+            <bool name="proxy-wxFIXED_MINSIZE">0</bool>
+            <string name="proxy-Platform">"<Any platform>"</string>
+            <document>
+              <string name="title">"wxStaticText: wxID_STATIC"</string>
+              <string name="type">"dialog-control-document"</string>
+              <string name="filename">""</string>
+              <string name="icon-name">"statictext"</string>
+              <long name="is-transient">0</long>
+              <long name="owns-file">1</long>
+              <long name="title-mode">0</long>
+              <long name="locked">0</long>
+              <string name="proxy-type">"wbStaticTextProxy"</string>
+              <string name="proxy-Id name">"wxID_STATIC"</string>
+              <long name="proxy-Id value">5105</long>
+              <string name="proxy-Name">""</string>
+              <string name="proxy-Class">"wxStaticText"</string>
+              <string name="proxy-Base class">"wxStaticText"</string>
+              <bool name="proxy-External implementation">1</bool>
+              <bool name="proxy-Separate files">0</bool>
+              <string name="proxy-Implementation filename">""</string>
+              <string name="proxy-Header filename">""</string>
+              <string name="proxy-Member variable name">"m_staLabel"</string>
+              <string name="proxy-Label">""</string>
+              <long name="proxy-Wrapping width">-1</long>
+              <string name="proxy-Help text">""</string>
+              <string name="proxy-Tooltip text">""</string>
+              <string name="proxy-Background colour">""</string>
+              <string name="proxy-Foreground colour">""</string>
+              <string name="proxy-Font">""</string>
+              <bool name="proxy-Hidden">0</bool>
+              <bool name="proxy-Enabled">1</bool>
+              <string name="proxy-Platform">"<Any platform>"</string>
+              <string name="proxy-Data variable">""</string>
+              <string name="proxy-Data validator">""</string>
+              <string name="proxy-Data source">""</string>
+              <string name="proxy-Data class name">""</string>
+              <string name="proxy-Data class implementation filename">""</string>
+              <string name="proxy-Data class header filename">""</string>
+              <string name="proxy-Data class manager window">""</string>
+              <bool name="proxy-wxALIGN_LEFT">0</bool>
+              <bool name="proxy-wxALIGN_RIGHT">0</bool>
+              <bool name="proxy-wxALIGN_CENTRE">0</bool>
+              <bool name="proxy-wxST_NO_AUTORESIZE">0</bool>
+              <bool name="proxy-wxNO_BORDER">0</bool>
+              <bool name="proxy-wxSIMPLE_BORDER">0</bool>
+              <bool name="proxy-wxDOUBLE_BORDER">0</bool>
+              <bool name="proxy-wxBORDER_THEME">0</bool>
+              <bool name="proxy-wxSUNKEN_BORDER">0</bool>
+              <bool name="proxy-wxRAISED_BORDER">0</bool>
+              <bool name="proxy-wxSTATIC_BORDER">0</bool>
+              <bool name="proxy-wxWANTS_CHARS">0</bool>
+              <bool name="proxy-wxNO_FULL_REPAINT_ON_RESIZE">0</bool>
+              <bool name="proxy-wxFULL_REPAINT_ON_RESIZE">0</bool>
+              <string name="proxy-Custom styles">""</string>
+              <long name="proxy-X">-1</long>
+              <long name="proxy-Y">-1</long>
+              <long name="proxy-Width">-1</long>
+              <long name="proxy-Height">-1</long>
+              <string name="proxy-AlignH">"Left"</string>
+              <string name="proxy-AlignV">"Centre"</string>
+              <long name="proxy-Stretch factor">0</long>
+              <long name="proxy-Border">5</long>
+              <bool name="proxy-wxLEFT">1</bool>
+              <bool name="proxy-wxRIGHT">1</bool>
+              <bool name="proxy-wxTOP">0</bool>
+              <bool name="proxy-wxBOTTOM">0</bool>
+              <bool name="proxy-wxSHAPED">0</bool>
+              <bool name="proxy-wxADJUST_MINSIZE">0</bool>
+              <bool name="proxy-wxFIXED_MINSIZE">0</bool>
+              <string name="proxy-Custom arguments">""</string>
+              <string name="proxy-Custom ctor arguments">""</string>
+            </document>
+            <document>
+              <string name="title">"wxChoice: ID_CHOICE"</string>
+              <string name="type">"dialog-control-document"</string>
+              <string name="filename">""</string>
+              <string name="icon-name">"choice"</string>
+              <long name="is-transient">0</long>
+              <long name="owns-file">1</long>
+              <long name="title-mode">0</long>
+              <long name="locked">0</long>
+              <string name="proxy-type">"wbChoiceProxy"</string>
+              <string name="event-handler-0">"wxEVT_COMMAND_CHOICE_SELECTED|OnChoiceSelected|NONE||ChoicePanel"</string>
+              <string name="proxy-Id name">"ID_CHOICE"</string>
+              <long name="proxy-Id value">10010</long>
+              <string name="proxy-Name">""</string>
+              <string name="proxy-Class">"wxChoice"</string>
+              <string name="proxy-Base class">"wxChoice"</string>
+              <bool name="proxy-External implementation">1</bool>
+              <bool name="proxy-Separate files">0</bool>
+              <string name="proxy-Implementation filename">""</string>
+              <string name="proxy-Header filename">""</string>
+              <string name="proxy-Member variable name">"m_theChoice"</string>
+              <string name="proxy-Strings">""</string>
+              <string name="proxy-Initial value">""</string>
+              <string name="proxy-Help text">""</string>
+              <string name="proxy-Tooltip text">""</string>
+              <string name="proxy-Background colour">""</string>
+              <string name="proxy-Foreground colour">""</string>
+              <string name="proxy-Font">""</string>
+              <bool name="proxy-Hidden">0</bool>
+              <bool name="proxy-Enabled">1</bool>
+              <string name="proxy-Platform">"<Any platform>"</string>
+              <string name="proxy-Data variable">""</string>
+              <string name="proxy-Data validator">""</string>
+              <string name="proxy-Data source">""</string>
+              <string name="proxy-Data class name">""</string>
+              <string name="proxy-Data class implementation filename">""</string>
+              <string name="proxy-Data class header filename">""</string>
+              <string name="proxy-Data class manager window">""</string>
+              <bool name="proxy-wxWANTS_CHARS">0</bool>
+              <bool name="proxy-wxNO_FULL_REPAINT_ON_RESIZE">0</bool>
+              <bool name="proxy-wxFULL_REPAINT_ON_RESIZE">0</bool>
+              <string name="proxy-Custom styles">""</string>
+              <long name="proxy-X">-1</long>
+              <long name="proxy-Y">-1</long>
+              <long name="proxy-Width">-1</long>
+              <long name="proxy-Height">-1</long>
+              <string name="proxy-AlignH">"Left"</string>
+              <string name="proxy-AlignV">"Centre"</string>
+              <long name="proxy-Stretch factor">0</long>
+              <long name="proxy-Border">5</long>
+              <bool name="proxy-wxLEFT">1</bool>
+              <bool name="proxy-wxRIGHT">1</bool>
+              <bool name="proxy-wxTOP">1</bool>
+              <bool name="proxy-wxBOTTOM">1</bool>
+              <bool name="proxy-wxSHAPED">0</bool>
+              <bool name="proxy-wxADJUST_MINSIZE">0</bool>
+              <bool name="proxy-wxFIXED_MINSIZE">0</bool>
+              <string name="proxy-Custom arguments">""</string>
+              <string name="proxy-Custom ctor arguments">""</string>
+            </document>
+          </document>
+        </document>
+        <document>
+          <string name="title">"GENERATOR"</string>
+          <string name="type">"dialog-document"</string>
+          <string name="filename">""</string>
+          <string name="icon-name">"dialog"</string>
+          <long name="is-transient">0</long>
+          <long name="owns-file">1</long>
+          <long name="title-mode">0</long>
+          <long name="locked">0</long>
+          <string name="proxy-type">"wbDialogProxy"</string>
+          <long name="base-id">10000</long>
+          <bool name="use-id-prefix">0</bool>
+          <string name="id-prefix">""</string>
+          <bool name="use-id-suffix">0</bool>
+          <string name="id-suffix">""</string>
+          <string name="app-kind">"Standard"</string>
+          <long name="use-xrc">0</long>
+          <long name="working-mode">0</long>
+          <string name="proxy-Id name">"ID_GENERATOR"</string>
+          <long name="proxy-Id value">10011</long>
+          <string name="proxy-Class">"GENERATOR"</string>
+          <string name="proxy-Base class">"wxDialog"</string>
+          <string name="proxy-Window kind">"wxDialog"</string>
+          <string name="proxy-Implementation filename">""</string>
+          <string name="proxy-Header filename">""</string>
+          <string name="proxy-XRC filename">""</string>
+          <string name="proxy-Title">"GENERATOR. USED TO GENERATE CONTROLS."</string>
+          <bool name="proxy-Centre">1</bool>
+          <string name="proxy-Icon">""</string>
+          <bool name="proxy-Dialog units">0</bool>
+          <string name="proxy-Help text">""</string>
+          <string name="proxy-Tooltip text">""</string>
+          <string name="proxy-Background colour">""</string>
+          <string name="proxy-Foreground colour">""</string>
+          <string name="proxy-Font">""</string>
+          <bool name="proxy-Hidden">0</bool>
+          <bool name="proxy-Enabled">1</bool>
+          <string name="proxy-Platform">"<Any platform>"</string>
+          <string name="proxy-Data source">""</string>
+          <string name="proxy-Data class name">""</string>
+          <string name="proxy-Data class implementation filename">""</string>
+          <string name="proxy-Data class header filename">""</string>
+          <string name="proxy-Data class manager window">""</string>
+          <string name="proxy-Texture">""</string>
+          <string name="proxy-Texture style">"Tiled"</string>
+          <bool name="proxy-wxDEFAULT_DIALOG_STYLE">0</bool>
+          <bool name="proxy-wxCAPTION">1</bool>
+          <bool name="proxy-wxRESIZE_BORDER">1</bool>
+          <bool name="proxy-wxSYSTEM_MENU">1</bool>
+          <bool name="proxy-wxSTAY_ON_TOP">0</bool>
+          <bool name="proxy-wxDIALOG_NO_PARENT">0</bool>
+          <bool name="proxy-wxCLOSE_BOX">1</bool>
+          <bool name="proxy-wxMAXIMIZE_BOX">0</bool>
+          <bool name="proxy-wxMINIMIZE_BOX">0</bool>
+          <bool name="proxy-wxDIALOG_MODAL">1</bool>
+          <bool name="proxy-wxNO_BORDER">0</bool>
+          <bool name="proxy-wxSIMPLE_BORDER">0</bool>
+          <bool name="proxy-wxDOUBLE_BORDER">0</bool>
+          <bool name="proxy-wxBORDER_THEME">0</bool>
+          <bool name="proxy-wxSUNKEN_BORDER">0</bool>
+          <bool name="proxy-wxRAISED_BORDER">0</bool>
+          <bool name="proxy-wxSTATIC_BORDER">0</bool>
+          <bool name="proxy-wxWANTS_CHARS">0</bool>
+          <bool name="proxy-wxNO_FULL_REPAINT_ON_RESIZE">0</bool>
+          <bool name="proxy-wxFULL_REPAINT_ON_RESIZE">0</bool>
+          <bool name="proxy-wxCLIP_CHILDREN">0</bool>
+          <bool name="proxy-wxTAB_TRAVERSAL">1</bool>
+          <bool name="proxy-wxWS_EX_VALIDATE_RECURSIVELY">0</bool>
+          <bool name="proxy-wxWS_EX_BLOCK_EVENTS">1</bool>
+          <bool name="proxy-wxWS_EX_TRANSIENT">0</bool>
+          <string name="proxy-Custom styles">""</string>
+          <bool name="proxy-wxDIALOG_EX_CONTEXTHELP">0</bool>
+          <bool name="proxy-Fit to content">1</bool>
+          <long name="proxy-X">-1</long>
+          <long name="proxy-Y">-1</long>
+          <long name="proxy-Width">400</long>
+          <long name="proxy-Height">300</long>
+          <bool name="proxy-AUI manager">0</bool>
+          <string name="proxy-Event sources">""</string>
+          <document>
+            <string name="title">"wxBoxSizer V"</string>
+            <string name="type">"dialog-control-document"</string>
+            <string name="filename">""</string>
+            <string name="icon-name">"sizer"</string>
+            <long name="is-transient">0</long>
+            <long name="owns-file">1</long>
+            <long name="title-mode">0</long>
+            <long name="locked">0</long>
+            <string name="proxy-type">"wbBoxSizerProxy"</string>
+            <string name="proxy-Orientation">"Vertical"</string>
+            <string name="proxy-Member variable name">""</string>
+            <string name="proxy-AlignH">"Centre"</string>
+            <string name="proxy-AlignV">"Centre"</string>
+            <long name="proxy-Stretch factor">0</long>
+            <long name="proxy-Border">5</long>
+            <bool name="proxy-wxLEFT">1</bool>
+            <bool name="proxy-wxRIGHT">1</bool>
+            <bool name="proxy-wxTOP">1</bool>
+            <bool name="proxy-wxBOTTOM">1</bool>
+            <bool name="proxy-wxSHAPED">0</bool>
+            <bool name="proxy-wxADJUST_MINSIZE">0</bool>
+            <bool name="proxy-wxFIXED_MINSIZE">0</bool>
+            <string name="proxy-Platform">"<Any platform>"</string>
+            <document>
+              <string name="title">"CollapsiblePanel: ID_COLLAPSIBLEPANE_PANEL"</string>
+              <string name="type">"dialog-control-document"</string>
+              <string name="filename">""</string>
+              <string name="icon-name">"panel"</string>
+              <long name="is-transient">0</long>
+              <long name="owns-file">1</long>
+              <long name="title-mode">0</long>
+              <long name="locked">0</long>
+              <string name="proxy-type">"wbCollapsiblePaneProxy"</string>
+              <string name="event-handler-0">"wxEVT_COMMAND_COLLPANE_CHANGED|OnCollapsiblepanePanelPaneChanged|NONE||"</string>
+              <string name="proxy-Id name">"ID_COLLAPSIBLEPANE_PANEL"</string>
+              <long name="proxy-Id value">-1</long>
+              <string name="proxy-Name">""</string>
+              <string name="proxy-Class">"CollapsiblePanel"</string>
+              <string name="proxy-Base class">"wxGenericCollapsiblePane"</string>
+              <bool name="proxy-External implementation">0</bool>
+              <bool name="proxy-Separate files">1</bool>
+              <string name="proxy-Implementation filename">"collapsible.cpp"</string>
+              <string name="proxy-Header filename">"collapsible.h"</string>
+              <string name="proxy-Member variable name">""</string>
+              <string name="proxy-Label">"Label"</string>
+              <bool name="proxy-Collapsed">1</bool>
+              <string name="proxy-Help text">""</string>
+              <string name="proxy-Tooltip text">""</string>
+              <string name="proxy-Background colour">""</string>
+              <string name="proxy-Foreground colour">""</string>
+              <string name="proxy-Font">""</string>
+              <bool name="proxy-Hidden">0</bool>
+              <bool name="proxy-Enabled">1</bool>
+              <string name="proxy-Platform">"<Any platform>"</string>
+              <string name="proxy-Data variable">""</string>
+              <string name="proxy-Data validator">""</string>
+              <string name="proxy-Data source">""</string>
+              <string name="proxy-Data class name">""</string>
+              <string name="proxy-Data class implementation filename">""</string>
+              <string name="proxy-Data class header filename">""</string>
+              <string name="proxy-Data class manager window">""</string>
+              <bool name="proxy-wxCP_DEFAULT_STYLE">1</bool>
+              <bool name="proxy-wxCP_NO_TLW_RESIZE">1</bool>
+              <bool name="proxy-wxNO_BORDER">0</bool>
+              <bool name="proxy-wxSIMPLE_BORDER">0</bool>
+              <bool name="proxy-wxDOUBLE_BORDER">0</bool>
+              <bool name="proxy-wxBORDER_THEME">0</bool>
+              <bool name="proxy-wxSUNKEN_BORDER">0</bool>
+              <bool name="proxy-wxRAISED_BORDER">0</bool>
+              <bool name="proxy-wxSTATIC_BORDER">0</bool>
+              <bool name="proxy-wxWANTS_CHARS">0</bool>
+              <bool name="proxy-wxNO_FULL_REPAINT_ON_RESIZE">0</bool>
+              <bool name="proxy-wxFULL_REPAINT_ON_RESIZE">0</bool>
+              <string name="proxy-Custom styles">""</string>
+              <long name="proxy-X">-1</long>
+              <long name="proxy-Y">-1</long>
+              <long name="proxy-Width">-1</long>
+              <long name="proxy-Height">-1</long>
+              <string name="proxy-AlignH">"Centre"</string>
+              <string name="proxy-AlignV">"Centre"</string>
+              <long name="proxy-Stretch factor">0</long>
+              <long name="proxy-Border">5</long>
+              <bool name="proxy-wxLEFT">1</bool>
+              <bool name="proxy-wxRIGHT">1</bool>
+              <bool name="proxy-wxTOP">1</bool>
+              <bool name="proxy-wxBOTTOM">1</bool>
+              <bool name="proxy-wxSHAPED">0</bool>
+              <bool name="proxy-wxADJUST_MINSIZE">0</bool>
+              <bool name="proxy-wxFIXED_MINSIZE">0</bool>
+              <string name="proxy-Custom arguments">""</string>
+              <string name="proxy-Custom ctor arguments">""</string>
+              <string name="proxy-Event sources">""</string>
+            </document>
+            <document>
+              <string name="title">"ButtonPanel: ID_BUTTON"</string>
+              <string name="type">"dialog-control-document"</string>
+              <string name="filename">""</string>
+              <string name="icon-name">"dialogcontrol"</string>
+              <long name="is-transient">0</long>
+              <long name="owns-file">1</long>
+              <long name="title-mode">0</long>
+              <long name="locked">0</long>
+              <string name="proxy-type">"wbButtonProxy"</string>
+              <string name="event-handler-0">"wxEVT_COMMAND_BUTTON_CLICKED|OnButtonClick|NONE||ButtonPanel"</string>
+              <string name="proxy-Id name">"ID_BUTTON"</string>
+              <long name="proxy-Id value">-1</long>
+              <string name="proxy-Name">""</string>
+              <string name="proxy-Class">"ButtonPanel"</string>
+              <string name="proxy-Base class">"wxButton"</string>
+              <bool name="proxy-External implementation">0</bool>
+              <bool name="proxy-Separate files">1</bool>
+              <string name="proxy-Implementation filename">"button.cpp"</string>
+              <string name="proxy-Header filename">"button.h"</string>
+              <string name="proxy-Member variable name">""</string>
+              <string name="proxy-Label">"Button"</string>
+              <bool name="proxy-Default">0</bool>
+              <string name="proxy-Help text">""</string>
+              <string name="proxy-Tooltip text">""</string>
+              <string name="proxy-Data variable">""</string>
+              <string name="proxy-Data validator">""</string>
+              <string name="proxy-Data source">""</string>
+              <string name="proxy-Data class name">""</string>
+              <string name="proxy-Data class implementation filename">""</string>
+              <string name="proxy-Data class header filename">""</string>
+              <string name="proxy-Data class manager window">""</string>
+              <string name="proxy-Background colour">""</string>
+              <string name="proxy-Foreground colour">""</string>
+              <string name="proxy-Font">""</string>
+              <bool name="proxy-Hidden">0</bool>
+              <bool name="proxy-Enabled">1</bool>
+              <string name="proxy-Platform">"<Any platform>"</string>
+              <bool name="proxy-wxBU_LEFT">0</bool>
+              <bool name="proxy-wxBU_RIGHT">0</bool>
+              <bool name="proxy-wxBU_TOP">0</bool>
+              <bool name="proxy-wxBU_BOTTOM">0</bool>
+              <bool name="proxy-wxBU_EXACTFIT">0</bool>
+              <bool name="proxy-wxNO_BORDER">0</bool>
+              <bool name="proxy-wxWANTS_CHARS">0</bool>
+              <bool name="proxy-wxNO_FULL_REPAINT_ON_RESIZE">0</bool>
+              <bool name="proxy-wxFULL_REPAINT_ON_RESIZE">0</bool>
+              <string name="proxy-Custom styles">""</string>
+              <long name="proxy-X">-1</long>
+              <long name="proxy-Y">-1</long>
+              <long name="proxy-Width">-1</long>
+              <long name="proxy-Height">-1</long>
+              <string name="proxy-AlignH">"Centre"</string>
+              <string name="proxy-AlignV">"Centre"</string>
+              <long name="proxy-Stretch factor">0</long>
+              <long name="proxy-Border">5</long>
+              <bool name="proxy-wxLEFT">1</bool>
+              <bool name="proxy-wxRIGHT">1</bool>
+              <bool name="proxy-wxTOP">1</bool>
+              <bool name="proxy-wxBOTTOM">1</bool>
+              <bool name="proxy-wxSHAPED">0</bool>
+              <bool name="proxy-wxADJUST_MINSIZE">0</bool>
+              <bool name="proxy-wxFIXED_MINSIZE">0</bool>
+              <string name="proxy-Custom arguments">""</string>
+              <string name="proxy-Custom ctor arguments">""</string>
+            </document>
+          </document>
+        </document>
+      </document>
+      <document>
+        <string name="title">"Sources"</string>
+        <string name="type">"html-document"</string>
+        <string name="filename">""</string>
+        <string name="icon-name">"sourcesfolder"</string>
+        <long name="is-transient">1</long>
+        <long name="owns-file">1</long>
+        <long name="title-mode">0</long>
+        <long name="locked">1</long>
+        <document>
+          <string name="title">"mviacam.rc"</string>
+          <string name="type">"source-editor-document"</string>
+          <string name="filename">"mviacam.rc"</string>
+          <string name="icon-name">"source-editor"</string>
+          <long name="is-transient">0</long>
+          <long name="owns-file">0</long>
+          <long name="title-mode">1</long>
+          <long name="locked">0</long>
+          <string name="created">"3/8/2009"</string>
+          <string name="language">""</string>
+        </document>
+      </document>
+      <document>
+        <string name="title">"Images"</string>
+        <string name="type">"html-document"</string>
+        <string name="filename">""</string>
+        <string name="icon-name">"bitmapsfolder"</string>
+        <long name="is-transient">1</long>
+        <long name="owns-file">1</long>
+        <long name="title-mode">0</long>
+        <long name="locked">1</long>
+        <document>
+          <string name="title">"disable_icon.xpm"</string>
+          <string name="type">"image-document"</string>
+          <string name="filename">"bitmaps/disable_icon.xpm"</string>
+          <string name="icon-name">"image"</string>
+          <long name="is-transient">0</long>
+          <long name="owns-file">0</long>
+          <long name="title-mode">0</long>
+          <long name="locked">0</long>
+          <long name="zoom-level">100</long>
+        </document>
+        <document>
+          <string name="title">"sitplus_logo_16x16.xpm"</string>
+          <string name="type">"image-document"</string>
+          <string name="filename">"bitmaps/sitplus_logo_16x16.xpm"</string>
+          <string name="icon-name">"image"</string>
+          <long name="is-transient">0</long>
+          <long name="owns-file">0</long>
+          <long name="title-mode">0</long>
+          <long name="locked">0</long>
+          <long name="zoom-level">100</long>
+        </document>
+        <document>
+          <string name="title">"sitplus_logo_32x32.xpm"</string>
+          <string name="type">"image-document"</string>
+          <string name="filename">"bitmaps/sitplus_logo_32x32.xpm"</string>
+          <string name="icon-name">"image"</string>
+          <long name="is-transient">0</long>
+          <long name="owns-file">0</long>
+          <long name="title-mode">0</long>
+          <long name="locked">0</long>
+          <long name="zoom-level">100</long>
+        </document>
+      </document>
+    </document>
+  </documents>
+
+</anthemion-project>
diff --git a/src/mod_widgets/slider.cpp b/src/mod_widgets/slider.cpp
new file mode 100644
index 0000000..d10f722
--- /dev/null
+++ b/src/mod_widgets/slider.cpp
@@ -0,0 +1,559 @@
+/////////////////////////////////////////////////////////////////////////////
+// Name:        slider.cpp
+// Purpose:
+// Author:      Cesar Mauri Loba
+// Modified by:
+// Created:     13/04/2011 18:37:56
+// RCS-ID:
+// Copyright:   (C) 2011 Cesar Mauri Loba - CREA Software Systems
+// 
+//  This program is free software: you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation, either version 3 of the License, or
+//  (at your option) any later version.
+//
+//  This program is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with this program.  If not, see <http://www.gnu.org/licenses/>. 
+/////////////////////////////////////////////////////////////////////////////
+
+/*
+
+Sample pattern on how to close to the close event of the parent window and forward it accordingly
+
+bool MyClass::Create( wxWindow* parent, wxWindowID id, const wxPoint& pos, const wxSize& size, long style, const wxString& name )
+{
+////@begin PureDataConfigPanel creation
+    SetExtraStyle(wxWS_EX_BLOCK_EVENTS);
+    wxPanel::Create( parent, id, pos, size, style, name );
+
+    CreateControls();
+    if (GetSizer())
+    {
+        GetSizer()->SetSizeHints(this);
+    }
+    Centre();
+////@end PureDataConfigPanel creation
+
+	//
+	// Connect parent class close event. This way this panel will receive close events when
+	// user clicks on the close box or the application if forced to quit. Note that this
+	// events should be managed carefully in the OnCloseWindow method (see below).
+	//
+	if (parent)
+		parent->Connect (wxEVT_CLOSE_WINDOW, wxCloseEventHandler(MyClass::OnCloseWindow), 0, this);
+
+    return true;
+}
+
+void MyClass::OnCloseWindow( wxCloseEvent& event )
+{
+	//
+	// We need to tell if the event has been originated from this window
+	// or in the parent window.
+	//
+	if (event.GetEventObject()== this) {
+		//
+		// If the event has been generated by this object
+		// we need to propagate to parent
+		//
+		if (GetParent()) GetParent()->Close();
+		event.Skip(false);
+	}
+	else {
+		// 
+		// This branch can be customized to allow close process to complete
+		// using event.Skip(true) or blocking it calling event.Skip(false)
+		//
+		event.Skip();
+	}
+}
+
+*/
+
+// For compilers that support precompilation, includes "wx/wx.h".
+#include "wx/wxprec.h"
+
+#ifdef __BORLANDC__
+#pragma hdrstop
+#endif
+
+#ifndef WX_PRECOMP
+#include "wx/wx.h"
+#endif
+
+////@begin includes
+////@end includes
+#include "slider.h"
+#include "spcore/conversion.h"
+#include <boost/format.hpp>
+
+////@begin XPM images
+////@end XPM images
+
+using namespace std;
+
+namespace mod_widgets {
+
+//
+// Component methods
+//
+
+SliderComponent::SliderComponent(const char * name, int argc, const char * argv[])
+: BaseWidgetComponent<SliderPanel,SliderComponent>(name, argc, argv)
+, m_sldType(SLD_FLOAT)
+, m_sliderMin(0)
+, m_sliderMax(1)
+, m_fmin(0)
+, m_fmax(1.0f)
+{
+	bool setValue= false;
+	float logSpeed= 0;
+
+	// Integer or float?
+	if (argc)
+		for (int i= 0; i< argc; ++i)
+			if (argv[i] && strcmp("-i", argv[i])== 0) {
+				m_sldType= SLD_INT;
+				break;
+			}
+	
+	// Create pins and internal storage
+	if (m_sldType!= SLD_INT) {
+		// float slider (either linear or log)
+		m_iPin= SmartPtr<InputPinFloat>(new InputPinFloat(*this), false);
+		m_oPin= CTypeFloat::CreateOutputPin("value");		
+		m_valueFloat= CTypeFloat::CreateInstance();
+		// wxSlider uses always integer values. 200 should provide enough resolution
+		m_sliderMax= 200;
+	}
+	else {
+		m_iPin= SmartPtr<InputPinInt>(new InputPinInt(*this), false);
+		m_oPin= CTypeInt::CreateOutputPin("value");		
+		m_valueInt= CTypeInt::CreateInstance();
+	}
+	RegisterInputPin (*m_iPin);
+	RegisterOutputPin (*m_oPin);		
+	
+	// Process remaining arguments
+	if (argc) {
+		for (int i= 0; i< argc; ++i) {
+			if (argv[i] && strcmp ("--min", argv[i])== 0) {
+				// Min
+				bool err= false;
+				
+				++i;
+				if (i< argc && argv[i]) {
+					if (m_sldType!= SLD_INT) err= !StrToFloat(argv[i], &m_fmin);
+					else err= !StrToInt(argv[i], &m_sliderMin);
+				}
+				else err= true;
+				if (err) throw std::runtime_error("widget_slider. Wrong value for option --min");
+			}
+			else if (argv[i] && strcmp ("--max", argv[i])== 0) {
+				// Max
+				bool err= false;
+				
+				++i;
+				if (i< argc && argv[i]) {
+					if (m_sldType!= SLD_INT) err= !StrToFloat(argv[i], &m_fmax);
+					else err= !StrToInt(argv[i], &m_sliderMax);
+				}
+				else err= true;
+				if (err) throw std::runtime_error("widget_slider. Wrong value for option --max");
+			}
+			else if (argv[i] && strcmp ("-v", argv[i])== 0) {
+				// Value
+				bool err= false;
+				
+				++i;
+				if (i< argc && argv[i]) {
+					if (m_sldType!= SLD_INT) {
+						float val= 0;
+						err= !StrToFloat(argv[i], &val);
+						m_valueFloat->setValue(val);
+					}
+					else {
+						int val= 0;
+						err= !StrToInt(argv[i], &val);
+						m_valueInt->setValue(val);
+					}
+				}
+				else err= true;
+				if (err) throw std::runtime_error("widget_slider. Wrong value for option --v");
+				setValue= true;
+			}
+			else if (argv[i] && strcmp ("--log", argv[i])== 0) {
+				// Log slider
+				if (m_sldType== SLD_INT) {
+					throw std::runtime_error("widget_slider. Integer slider cannot use log scale.");
+				}
+
+				m_sldType= SLD_LOG;
+
+				// Provides speed argument?
+				if (i+1< argc  && argv[i+1]) {
+					if (StrToFloat(argv[i+1], &logSpeed)) ++i;
+				}
+			}
+			else if (argv[i] && strcmp ("-i", argv[i])== 0) {
+				// Ignore, handled previously
+			}
+			else if (argv[i] && strlen(argv[i])) {
+				string error_msg("widget_slider. Unknown option:");
+				error_msg+= argv[i];
+				throw std::runtime_error(error_msg);
+			}
+		}
+	}
+
+	// Set default value when needed
+	if (!setValue) {
+		if (m_sldType!= SLD_INT) m_valueFloat->setValue(m_fmin);
+		else m_valueInt->setValue(m_sliderMin);
+	}
+
+	// Check ranges
+	if (m_sliderMin>= m_sliderMax || m_fmin>= m_fmax)
+		throw std::runtime_error("widget_slider. Wrong numeric range.");
+	if (((m_sldType!= SLD_INT) && (m_valueFloat->getValue()< m_fmin || m_valueFloat->getValue()> m_fmax)) ||
+	    ((m_sldType== SLD_INT) && (m_valueInt->getValue()< m_sliderMin || m_valueInt->getValue()> m_sliderMax)))
+	   throw std::runtime_error("widget_slider. Value out of range.");
+
+	// Set log parameters when needed
+	if (m_sldType== SLD_LOG)
+		m_linear2exp.SetParams ((float) m_sliderMin,  m_fmin, (float) m_sliderMax, m_fmax, logSpeed);
+}
+
+int SliderComponent::DoInitialize()
+{
+	if (m_sldType!= SLD_INT)
+		m_oPin->Send(m_valueFloat);
+	else
+		m_oPin->Send(m_valueInt);
+
+	return 0;
+}
+
+// 
+// Called from GUI
+//	
+
+void SliderComponent::SetSliderValue (int v)
+{
+	assert (v>= m_sliderMin && v<= m_sliderMax);
+
+	switch (m_sldType) {
+		case SLD_FLOAT: {
+			assert (m_sliderMin== 0);
+
+			float newVal= (m_fmax - m_fmin) * ((float) v / (float) m_sliderMax) + m_fmin;
+			if (newVal!= m_valueFloat->getValue()) {
+				m_valueFloat->setValue(newVal);
+				m_oPin->Send(m_valueFloat);
+			}
+			break;
+		}
+		case SLD_INT:
+			if (v!= m_valueInt->getValue()) {
+				m_valueInt->setValue(v);
+				m_oPin->Send(m_valueInt);
+			}
+			break;
+		case SLD_LOG: {
+			assert (m_sliderMin== 0);
+
+			float newVal= this->m_linear2exp.ToExp((float) v);
+			if (newVal!= m_valueFloat->getValue()) {
+				m_valueFloat->setValue(newVal);
+				m_oPin->Send(m_valueFloat);
+			}
+			break;
+		}
+		default: 
+			assert(false);
+	}
+}
+
+int SliderComponent::GetSliderValue() const
+{
+	switch (m_sldType) {
+		case SLD_FLOAT:
+			assert (m_sliderMin== 0);
+			return (int) (((m_valueFloat->getValue() - m_fmin) / (m_fmax - m_fmin)) * (float) m_sliderMax + 0.5f);
+		case SLD_INT:
+			return m_valueInt->getValue();
+		case SLD_LOG:
+			return (int) m_linear2exp.ToLinear(m_valueFloat->getValue());
+		default: 
+			assert(false);
+	}
+	return 0;	// Make the compiler happy
+}
+
+std::string SliderComponent::GetTextboxValue() const
+{
+	if (m_sldType!= SLD_INT) {
+		return str( boost::format("%.4g") % m_valueFloat->getValue() );
+	}
+	else {
+		return str( boost::format("%d") % m_valueInt->getValue() );
+	}
+}
+
+// 
+// Private methods
+//	
+
+void SliderComponent::OnPinValueFloat (const CTypeFloat & msg)
+{
+	m_valueFloat->setValue(msg.getValue());
+	if (m_panel) m_panel->ValueChanged();
+}
+
+void SliderComponent::OnPinValueInt (const CTypeInt & msg)
+{
+	m_valueInt->setValue(msg.getValue());
+	if (m_panel) m_panel->ValueChanged();
+}
+
+//////////////////////////////////////////////////////////////////////////////
+
+/*!
+ * SliderPanel type definition
+ */
+
+IMPLEMENT_DYNAMIC_CLASS( SliderPanel, wxPanel )
+
+// New event to comunicate updates to GUI
+DECLARE_LOCAL_EVENT_TYPE(wxEVT_SPSLIDER_VALUE_CHANGE, -1)
+DEFINE_LOCAL_EVENT_TYPE(wxEVT_SPSLIDER_VALUE_CHANGE)
+
+/*!
+ * SliderPanel event table definition
+ */
+
+BEGIN_EVENT_TABLE( SliderPanel, wxPanel )
+
+////@begin SliderPanel event table entries
+    EVT_SLIDER( ID_SLIDER_CONTROL, SliderPanel::OnSliderControlUpdated )
+
+////@end SliderPanel event table entries
+
+	EVT_COMMAND  (wxID_ANY, wxEVT_SPSLIDER_VALUE_CHANGE, SliderPanel::OnValueChanged)
+
+END_EVENT_TABLE()
+
+
+/*!
+ * SliderPanel constructors
+ */
+
+SliderPanel::SliderPanel()
+{
+    Init();
+}
+
+SliderPanel::SliderPanel( wxWindow* parent, wxWindowID id, const wxPoint& pos, const wxSize& size, long style, const wxString& name )
+{
+    Init();
+    Create(parent, id, pos, size, style, name);
+}
+
+
+/*!
+ * Slider creator
+ */
+
+bool SliderPanel::Create( wxWindow* parent, wxWindowID id, const wxPoint& pos, const wxSize& size, long style, const wxString& )
+{
+////@begin SliderPanel creation
+    SetExtraStyle(wxWS_EX_BLOCK_EVENTS);
+    wxPanel::Create( parent, id, pos, size, style );
+
+    CreateControls();
+    if (GetSizer())
+    {
+        GetSizer()->SetSizeHints(this);
+    }
+    Centre();
+////@end SliderPanel creation
+    return true;
+}
+
+
+/*!
+ * SliderPanel destructor
+ */
+
+SliderPanel::~SliderPanel()
+{
+////@begin SliderPanel destruction
+////@end SliderPanel destruction
+}
+
+
+/*!
+ * Member initialisation
+ */
+
+void SliderPanel::Init()
+{
+////@begin SliderPanel member initialisation
+    m_staLabel = NULL;
+    m_sldSlider = NULL;
+    m_txtNumber = NULL;
+////@end SliderPanel member initialisation
+}
+
+
+/*!
+ * Control creation for Slider
+ */
+
+void SliderPanel::CreateControls()
+{
+
+////@begin SliderPanel content construction
+    SliderPanel* itemPanel1 = this;
+
+    wxBoxSizer* itemBoxSizer2 = new wxBoxSizer(wxVERTICAL);
+    itemPanel1->SetSizer(itemBoxSizer2);
+
+    m_staLabel = new wxStaticText;
+    m_staLabel->Create( itemPanel1, wxID_STATIC_LABEL, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 );
+    itemBoxSizer2->Add(m_staLabel, 0, wxALIGN_LEFT|wxLEFT|wxRIGHT, 5);
+
+    wxBoxSizer* itemBoxSizer4 = new wxBoxSizer(wxHORIZONTAL);
+    itemBoxSizer2->Add(itemBoxSizer4, 0, wxGROW, 5);
+
+    m_sldSlider = new wxSlider;
+    m_sldSlider->Create( itemPanel1, ID_SLIDER_CONTROL, 0, 0, 1, wxDefaultPosition, wxSize(150, -1), wxSL_HORIZONTAL );
+    itemBoxSizer4->Add(m_sldSlider, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5);
+
+    m_txtNumber = new wxTextCtrl;
+    m_txtNumber->Create( itemPanel1, ID_TEXTCTRL, wxEmptyString, wxDefaultPosition, wxSize(75, -1), wxTE_READONLY|wxTE_RIGHT );
+    itemBoxSizer4->Add(m_txtNumber, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5);
+
+////@end SliderPanel content construction
+
+	assert (m_component);
+/*
+    SliderPanel* itemPanel1 = this;
+
+    wxBoxSizer* itemBoxSizer2 = new wxBoxSizer(wxVERTICAL);
+    itemPanel1->SetSizer(itemBoxSizer2);
+
+    wxStaticText* itemStaticText3 = NULL;
+    if (m_component->GetLabel().size()) {
+        itemStaticText3 = new wxStaticText;
+        itemStaticText3->Create( itemPanel1, wxID_STATIC_LABEL, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 );
+        itemBoxSizer2->Add(itemStaticText3, 0, wxALIGN_LEFT|wxLEFT|wxRIGHT, 5);
+    }
+
+    wxBoxSizer* itemBoxSizer4 = new wxBoxSizer(wxHORIZONTAL);
+    itemBoxSizer2->Add(itemBoxSizer4, 0, wxGROW, 5);
+
+    m_sldSlider = new wxSlider;
+    m_sldSlider->Create( itemPanel1, ID_SLIDER_CONTROL, 0, 0, 0, wxDefaultPosition, wxSize(150, -1), wxSL_HORIZONTAL );
+    itemBoxSizer4->Add(m_sldSlider, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5);
+
+    m_txtNumber = new wxTextCtrl;
+    m_txtNumber->Create( itemPanel1, ID_TEXTCTRL, wxEmptyString, wxDefaultPosition, wxSize(75, -1), wxTE_READONLY|wxTE_RIGHT );
+    itemBoxSizer4->Add(m_txtNumber, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5);
+*/
+	// Label
+	if (m_component->GetLabel().size()) {
+		wxString label(m_component->GetLabel().c_str(), wxConvUTF8);
+		m_staLabel->SetLabel(label);
+	}
+	else
+		m_staLabel->Show(false);
+
+    // Fill values
+	/*
+    if (itemStaticText3) {
+        wxString label(m_component->GetLabel().c_str(), wxConvUTF8);
+        itemStaticText3->SetLabel(label);
+    }*/
+	m_sldSlider->SetRange(m_component->GetSliderMin(), m_component->GetSliderMax());
+    m_sldSlider->SetValue(m_component->GetSliderValue());
+    wxString number(m_component->GetTextboxValue().c_str(), wxConvUTF8);
+    m_txtNumber->SetValue(number);
+}
+
+
+/*!
+ * Should we show tooltips?
+ */
+
+bool SliderPanel::ShowToolTips()
+{
+    return true;
+}
+
+/*!
+ * Get bitmap resources
+ */
+
+wxBitmap SliderPanel::GetBitmapResource( const wxString& name )
+{
+    // Bitmap retrieval
+////@begin SliderPanel bitmap retrieval
+    wxUnusedVar(name);
+    return wxNullBitmap;
+////@end SliderPanel bitmap retrieval
+}
+
+/*!
+ * Get icon resources
+ */
+
+wxIcon SliderPanel::GetIconResource( const wxString& name )
+{
+    // Icon retrieval
+////@begin SliderPanel icon retrieval
+    wxUnusedVar(name);
+    return wxNullIcon;
+////@end SliderPanel icon retrieval
+}
+
+
+/*!
+ * wxEVT_COMMAND_SLIDER_UPDATED event handler for ID_SLIDER1
+ */
+
+void SliderPanel::OnSliderControlUpdated( wxCommandEvent& event )
+{
+	if (m_component) {
+		m_component->SetSliderValue(m_sldSlider->GetValue());
+		wxString txtBoxVal(m_component->GetTextboxValue().c_str(), wxConvUTF8);
+		m_txtNumber->SetValue(txtBoxVal);
+	}
+	
+    event.Skip(false);
+}
+
+void SliderPanel::ValueChanged()
+{
+	wxCommandEvent event(wxEVT_SPSLIDER_VALUE_CHANGE);
+	
+	if (!wxIsMainThread()) wxPostEvent(this, event);
+	else OnValueChanged( event );
+}
+
+void SliderPanel::OnValueChanged( wxCommandEvent& )
+{
+	if (m_component) {
+		// TODO: sync
+		m_sldSlider->SetValue(m_component->GetSliderValue());
+		wxString txtBoxVal(m_component->GetTextboxValue().c_str(), wxConvUTF8);
+		m_txtNumber->SetValue(txtBoxVal);
+	}
+}
+
+};
diff --git a/src/mod_widgets/slider.h b/src/mod_widgets/slider.h
new file mode 100755
index 0000000..58ce01f
--- /dev/null
+++ b/src/mod_widgets/slider.h
@@ -0,0 +1,234 @@
+/////////////////////////////////////////////////////////////////////////////
+// Name:        slider.h
+// Purpose:
+// Author:      Cesar Mauri Loba
+// Modified by:
+// Created:     13/04/2011 18:37:56
+// RCS-ID:
+// Copyright:   (C) 2011 Cesar Mauri Loba - CREA Software Systems
+// 
+//  This program is free software: you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation, either version 3 of the License, or
+//  (at your option) any later version.
+//
+//  This program is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with this program.  If not, see <http://www.gnu.org/licenses/>. 
+/////////////////////////////////////////////////////////////////////////////
+
+#ifndef _SLIDER_H_
+#define _SLIDER_H_
+
+
+/*!
+ * Includes
+ */
+
+////@begin includes
+////@end includes
+#include "base_widget.h"
+
+#include "linear2exp.h"
+
+#include <wx/panel.h>
+#include <wx/stattext.h>
+#include <wx/slider.h>
+#include <wx/textctrl.h>
+
+/*!
+ * Forward declarations
+ */
+
+////@begin forward declarations
+////@end forward declarations
+
+/*!
+ * Control identifiers
+ */
+
+////@begin control identifiers
+#define ID_SLIDER 10000
+#define wxID_STATIC_LABEL 10003
+#define ID_SLIDER_CONTROL 10001
+#define ID_TEXTCTRL 10002
+#define SYMBOL_SLIDERPANEL_STYLE wxTAB_TRAVERSAL
+#define SYMBOL_SLIDERPANEL_TITLE _("Slider")
+#define SYMBOL_SLIDERPANEL_IDNAME ID_SLIDER
+#define SYMBOL_SLIDERPANEL_SIZE wxDefaultSize
+#define SYMBOL_SLIDERPANEL_POSITION wxDefaultPosition
+////@end control identifiers
+
+using namespace spcore;
+
+namespace mod_widgets {
+
+class SliderComponent;
+
+/*!
+ * SliderPanel class declaration
+ */
+
+class SliderPanel: public wxPanel, public BaseWidgetPanel<SliderComponent>
+{
+    DECLARE_DYNAMIC_CLASS( SliderPanel )
+    DECLARE_EVENT_TABLE()
+
+public:
+    /// Constructors
+    SliderPanel();
+    SliderPanel( wxWindow* parent, wxWindowID id = SYMBOL_SLIDERPANEL_IDNAME, const wxPoint& pos = SYMBOL_SLIDERPANEL_POSITION, const wxSize& size = SYMBOL_SLIDERPANEL_SIZE, long style = SYMBOL_SLIDERPANEL_STYLE, const wxString& name = SYMBOL_SLIDERPANEL_TITLE );
+
+    /// Creation
+    bool Create( wxWindow* parent, wxWindowID id = SYMBOL_SLIDERPANEL_IDNAME, const wxPoint& pos = SYMBOL_SLIDERPANEL_POSITION, const wxSize& size = SYMBOL_SLIDERPANEL_SIZE, long style = SYMBOL_SLIDERPANEL_STYLE, const wxString& name = SYMBOL_SLIDERPANEL_TITLE );
+
+    /// Destructor
+    ~SliderPanel();
+
+	// Notify value change
+	void ValueChanged();
+
+private:
+    /// Initialises member variables
+    void Init();
+
+    /// Creates the controls and sizers
+    void CreateControls();
+
+////@begin SliderPanel event handler declarations
+
+    /// wxEVT_COMMAND_SLIDER_UPDATED event handler for ID_SLIDER_CONTROL
+    void OnSliderControlUpdated( wxCommandEvent& event );
+
+////@end SliderPanel event handler declarations
+
+	// Value change event
+	void OnValueChanged( wxCommandEvent& );
+
+
+////@begin SliderPanel member function declarations
+
+    /// Retrieves bitmap resources
+    wxBitmap GetBitmapResource( const wxString& name );
+
+    /// Retrieves icon resources
+    wxIcon GetIconResource( const wxString& name );
+////@end SliderPanel member function declarations
+
+    /// Should we show tooltips?
+    static bool ShowToolTips();
+
+////@begin SliderPanel member variables
+    wxStaticText* m_staLabel;
+    wxSlider* m_sldSlider;
+    wxTextCtrl* m_txtNumber;
+////@end SliderPanel member variables
+};
+
+/**
+	widget_slider component
+
+	Slider component widget
+
+	Input pins:
+		value (CTypeFloat or CTypeInt)
+
+		Sets the value of the widget. 
+		The type of the pin depends on the construction parameters
+
+	Output pins:
+		value (CTypeFloat or CTypeInt)
+
+		Sends the value when the slider is manipulated
+
+	Command line:
+		[-e [0|1|false|true]]	Enabled. Control will be initially enabled (def. 1)
+		[-l <label> ]	Label. If empty, no label is shown.
+		[-i ]			Integer slider (default float).
+		[-v <val> ]		Value (default min).
+		[--min <val>]	(= 0) Minimum range value.
+		[--max <val>]	(= 1) Maximum range value.
+		[--log [<val>]] 
+			Use logarithmic scale. "val" set how fast the logarithmic curve
+			grows (default 0)
+*/
+class SliderComponent : public BaseWidgetComponent<SliderPanel,SliderComponent> {
+public:
+	static const char* getTypeName() { return "widget_slider"; };
+	virtual const char* GetTypeName() const { return SliderComponent::getTypeName(); };
+
+	//
+	// Component methods
+	//
+	SliderComponent(const char * name, int argc, const char * argv[]);
+	
+	virtual int DoInitialize();
+
+	// 
+	// Called from GUI
+	//	
+	int GetSliderMin() const { return m_sliderMin; }
+	int GetSliderMax() const { return m_sliderMax; }
+
+	void SetSliderValue (int v);
+	int GetSliderValue() const;
+
+	std::string GetTextboxValue() const;
+
+private:
+	enum ESliderType { SLD_FLOAT= 0, SLD_INT, SLD_LOG };
+
+	//
+	// Data members
+	//
+	ESliderType m_sldType;
+	Linear2ExpMapping m_linear2exp;
+	int m_sliderMin, m_sliderMax;
+	float m_fmin, m_fmax;
+	SmartPtr<IInputPin> m_iPin;
+	SmartPtr<IOutputPin> m_oPin;
+	SmartPtr<CTypeFloat> m_valueFloat;
+	SmartPtr<CTypeInt> m_valueInt;
+
+	//
+	// Private methods
+	//	
+	void OnPinValueFloat (const CTypeFloat & msg);
+	void OnPinValueInt (const CTypeInt & msg);
+
+	//
+	// Input pin classes
+	//
+	class InputPinFloat : public spcore::CInputPinWriteOnly<CTypeFloat, SliderComponent> {
+	public:
+		InputPinFloat (SliderComponent & component)
+		: CInputPinWriteOnly<CTypeFloat, SliderComponent>("value", component) { }
+
+		virtual int DoSend(const CTypeFloat & msg) {
+			m_component->OnPinValueFloat(msg);
+			return 0;
+		}
+	};
+
+	class InputPinInt : public spcore::CInputPinWriteOnly<CTypeInt, SliderComponent> {
+	public:
+		InputPinInt (SliderComponent & component)
+		: CInputPinWriteOnly<CTypeInt, SliderComponent>("value", component) { }
+
+		virtual int DoSend(const CTypeInt & msg) {
+			m_component->OnPinValueInt(msg);
+			return 0;
+		}
+	};
+};
+
+typedef ComponentFactory<SliderComponent> SliderComponentFactory;
+
+};
+
+#endif
+    // _SLIDER_H_
diff --git a/src/mod_wiimotes/CMakeLists.txt b/src/mod_wiimotes/CMakeLists.txt
new file mode 100755
index 0000000..580c0ce
--- /dev/null
+++ b/src/mod_wiimotes/CMakeLists.txt
@@ -0,0 +1,26 @@
+cmake_minimum_required(VERSION 2.6)
+project(mod_wiimotes)
+
+set(mod_wiimotes_SRCS
+	${CUSTOM_INCLUDE_PATH}/mod_wiimotes/wiimotes_types.h
+	wiimotes_types.cpp
+	mod_wiimotes.cpp
+	mod_wiimotes.h
+	wwiimotesconfiguration.h
+	wwiimotesconfiguration.cpp
+	wwiimotesproperties.h
+	wwiimotesproperties.cpp
+)
+
+add_library (mod_wiimotes MODULE ${mod_wiimotes_SRCS})
+target_link_libraries(mod_wiimotes wiiuse)
+target_link_libraries(mod_wiimotes spcore)
+target_link_libraries(mod_wiimotes ${Boost_THREAD_LIBRARY})
+target_link_libraries(mod_wiimotes ${wxWidgets_LIBRARIES})
+
+IF(BUILD_TESTS)
+	ADD_SUBDIRECTORY(tests)
+ENDIF(BUILD_TESTS)
+
+install (FILES ${CUSTOM_INCLUDE_PATH}/mod_wiimotes/wiimotes_types.h DESTINATION ${INCLUDEDIR}/${PROJECT_NAME})
+INSTALL (TARGETS mod_wiimotes RUNTIME DESTINATION ${LIBRUNTIMEDIR} LIBRARY DESTINATION ${PLUGINDIR} )
diff --git a/src/mod_wiimotes/icons/balance-board.xpm b/src/mod_wiimotes/icons/balance-board.xpm
new file mode 100755
index 0000000..4bd61d4
--- /dev/null
+++ b/src/mod_wiimotes/icons/balance-board.xpm
@@ -0,0 +1,231 @@
+/* XPM */
+static const char *balance_board[] = {
+/* columns rows colors chars-per-pixel */
+"64 42 183 2",
+"   c #050405",
+".  c #050609",
+"X  c #06090C",
+"o  c #0A0A0C",
+"O  c #050C12",
+"+  c #0A0E12",
+"@  c #100F12",
+"#  c #0A1116",
+"$  c #0A1318",
+"%  c #131215",
+"&  c #151418",
+"*  c #0E1B24",
+"=  c #141E25",
+"-  c #15232C",
+";  c #1A232B",
+":  c #192730",
+">  c #1A2C37",
+",  c #1D2E38",
+"<  c #27262A",
+"1  c #2D2C2F",
+"2  c #2E2C30",
+"3  c #302E33",
+"4  c #253037",
+"5  c #24333D",
+"6  c #343237",
+"7  c #37353A",
+"8  c #38363B",
+"9  c #3B393E",
+"0  c #243542",
+"q  c #2D3741",
+"w  c #2E3D47",
+"e  c #243B49",
+"r  c #2E3F4A",
+"t  c #343D46",
+"y  c #3E3C40",
+"u  c #403E44",
+"i  c #2A404F",
+"p  c #32434E",
+"a  c #3F4148",
+"s  c #2C4554",
+"d  c #374752",
+"f  c #304855",
+"g  c #3B4B54",
+"h  c #344A59",
+"j  c #3E4F58",
+"k  c #3F525D",
+"l  c #334F64",
+"z  c #3C5464",
+"x  c #3E596C",
+"c  c #3B5D78",
+"v  c #424045",
+"b  c #43444A",
+"n  c #49474D",
+"m  c #42535D",
+"M  c #4A535E",
+"N  c #545357",
+"B  c #565459",
+"V  c #425662",
+"C  c #455966",
+"Z  c #4C5A67",
+"A  c #435C6D",
+"S  c #4C5D6A",
+"D  c #5E5B61",
+"F  c #435F70",
+"G  c #4C616E",
+"H  c #5D636A",
+"J  c #436275",
+"K  c #496375",
+"L  c #45667B",
+"P  c #4A667A",
+"I  c #47687E",
+"U  c #4B687D",
+"Y  c #546877",
+"T  c #526C7D",
+"R  c #5E6E79",
+"E  c #5F707C",
+"W  c #666367",
+"Q  c #68666B",
+"!  c #6D6C70",
+"~  c #716F73",
+"^  c #7B797E",
+"/  c #4D6982",
+"(  c #526D83",
+")  c #557185",
+"_  c #597183",
+"`  c #5D7688",
+"'  c #637483",
+"]  c #687A86",
+"[  c #647B8B",
+"{  c #697E8E",
+"}  c #767A81",
+"|  c #7E7F82",
+" . c #727E89",
+".. c #6B7F90",
+"X. c #817F84",
+"o. c #74818C",
+"O. c #798289",
+"+. c #6D8291",
+"@. c #718493",
+"#. c #768896",
+"$. c #798A96",
+"%. c #7C8C99",
+"&. c #828084",
+"*. c #868588",
+"=. c #8A878B",
+"-. c #8C898D",
+";. c #838D96",
+":. c #8F8E91",
+">. c #818F99",
+",. c #908F92",
+"<. c #85929E",
+"1. c #8C939C",
+"2. c #90969C",
+"3. c #989699",
+"4. c #9B999C",
+"5. c #8795A0",
+"6. c #8996A1",
+"7. c #8D99A4",
+"8. c #8F9DA8",
+"9. c #9197A0",
+"0. c #939CA6",
+"q. c #989EA7",
+"w. c #949EA9",
+"e. c #999FA8",
+"r. c #A19FA1",
+"t. c #98A0A7",
+"y. c #96A1AA",
+"u. c #9CA3AC",
+"i. c #9DA8AE",
+"p. c #9DA6B0",
+"a. c #9EA8B0",
+"s. c #A5A3A5",
+"d. c #A1A5AE",
+"f. c #A8A6A8",
+"g. c #A2A8AF",
+"h. c #ACABAD",
+"j. c #A2A7B0",
+"k. c #A4AAB2",
+"l. c #A9ADB5",
+"z. c #A9AFB8",
+"x. c #A7B0B6",
+"c. c #ABB0B7",
+"v. c #A6B0B8",
+"b. c #ADB2B9",
+"n. c #AEB8BE",
+"m. c #B2B1B4",
+"M. c #B2B5BC",
+"N. c #B4B9BE",
+"B. c #B8B9BD",
+"V. c #B5B7C0",
+"C. c #B6BAC1",
+"Z. c #B9BDC3",
+"A. c #BDC2C5",
+"S. c #BEC1C8",
+"D. c #C2C4C6",
+"F. c #C3C8C6",
+"G. c #C2C6C9",
+"H. c #C5CACB",
+"J. c #CBCDCC",
+"K. c #CCD1CF",
+"L. c #CBCED2",
+"P. c #D2CFD0",
+"I. c #CED1D3",
+"U. c #D3D4D4",
+"Y. c #D9D7D7",
+"T. c #D6D8D6",
+"R. c #D9D8D7",
+"E. c #D3D6D9",
+"W. c #DBDADA",
+"Q. c #D9DDE0",
+"!. c #E1DFE0",
+"~. c #DEE1E4",
+"^. c #E3E3E4",
+"/. c #E8E7E7",
+"(. c #E4E6E8",
+"). c #ECEBEC",
+"_. c #F0EFEF",
+"`. c #EEF0F1",
+"'. c #F5F4F4",
+"]. c #F8F7F7",
+"[. c #F6F6F8",
+"{. c #F8F7F8",
+"}. c #FFFFFF",
+/* pixels */
+"}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.",
+"}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.`.I.b.u.a.n.(.}.}.}.}.}.}.}.}.}.}.}.}.}.}.",
+"}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.[.Q.S.u.0.0.y.8.8.u.$.G.}.}.}.}.}.}.}.}.}.}.}.}.}.",
+"}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.{.^.H.n.u.d.e.9.0.0.y.y.8.8.8._ R.}.}.}.}.}.}.}.}.}.}.}.}.",
+"}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.{.(.I.Z.z.z.p.u.u.w.j.k.d.u.u.u.i.8.u.` h.}.}.}.}.}.}.}.}.}.}.}.}.",
+"}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.{.(.I.Z.n.M.N.M.u.k.b.z.z.k.k.j.u.u.u.u.d.y.0.7.1.].}.}.}.}.}.}.}.}.}.}.}.",
+"}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.`.~.I.v.b.N.N.C.A.Z.V.u.M.b.c.z.l.k.k.j.j.u.u.u.0.k.8.p.>.).}.}.}.}.}.}.}.}.}.}.}.",
+"}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.{.).E.H.A.C.A.J.C.c.A.A.A.A.Z.C.g.M.M.l.l.z.k.k.d.d.u.u.u.e.u.y.8.0.J.}.}.}.}.}.}.}.}.}.}.}.",
+"}.}.}.}.}.}.}.}.}.}.}.}.}.}.`.Q.I.G.Z.D.J.J.K.H.F.F.G.u.S.S.Z.Z.V.V.z.z.M.z.k.l.k.g.i.u.u.u.u.u.y.k.8.p.g.].}.}.}.}.}.}.}.}.}.}.",
+"}.}.}.}.}.}.}.}.}.'.^.E.H.G.H.L.G.D.G.J.K.J.H.H.G.G.S.z.M.Z.Z.Z.C.C.M.k.M.c.c.l.k.g.u.d.u.u.t.u.u.u.u.8.u.^.}.}.}.}.}.}.}.}.}.}.",
+"}.}.}.}.{.(.E.H.G.H.I.U.G.G.G.G.U.K.J.J.U.K.F.F.G.S.Z.Z.e.Z.Z.C.C.Z.M.z.c.c.l.l.k.d.g.u.u.u.u.u.u.0.k.7.t.m.{.}.}.}.}.}.}.}.}.}.",
+"}.}.{.H.b.A.E.W.I.J.H.L.U.U.U.K.J.J.J.H.H.K.A.F.Z.A.Z.Z.u.M.Z.C.C.V.M.b.i.c.l.k.k.k.k.k.u.u.e.u.y.u.y.u.8.g.^.}.}.}.}.}.}.}.}.}.",
+"}.'.y.N.A.R.R.J.I.T.T.T.U.K.K.H.H.F.H.F.G.J.G.Z.Z.Z.Z.Z.C.q.Z.Z.V.M.M.M.d.z.z.l.k.l.k.u.u.a.u.u.u.u.w.u.8.y.n.{.}.}.}.}.}.}.}.}.",
+"}.6.%.M.A.T.R.H.T.U.U.I.K.K.J.H.H.F.D.A.A.H.H.Z.Z.C.C.Z.V.q.V.V.M.M.M.M.z.u.c.k.a.k.k.a.l.u.u.u.u.e.u.w.a.7.u.U.}.}.}.}.}.}.}.}.",
+"_.G +.8.b.I.U.F.U.K.K.K.H.H.F.A.D.Z.A.Z.Z.Z.H.Z.V.V.C.C.V.z.q.V.V.M.V.b.j.u.k.c.b.l.k.j.k.u.u.u.u.w.0.0.u.8.8.l.).}.}.}.}.}.}.}.",
+").g T $.g.A.K.A.K.K.H.H.F.F.A.A.A.Z.B.Z.B.Z.G.Z.C.V.V.V.V.M.9.M.l.z.z.z.M.z.u.z.l.a.a.k.u.d.u.u.e.e.e.0.0.u.7.u.N.{.}.}.}.}.}.}.",
+"}.| e ` <.c.F.F.Z.F.S.A.A.A.C.A.N.N.N.N.N.A.N.F.V.M.M.m.z.z.j.9.V.M.M.M.M.z.d.k.k.k.k.k.d.u.u.e.e.e.0.0.0.0.t.7.i.G.}.}.}.}.}.}.",
+"}.^.b l +.y.M.A.b.Z.A.Z.C.C.N.C.N.C.N.N.N.N.M.G.z.l.z.z.M.V.V.9.V.m.M.M.l.l.k.e.k.k.u.g.u.u.u.u.e.w.0.0.0.7.u.6.7.u.T.}.}.}.}.}.",
+"}.}.D.7 P %.k.M.k.C.C.M.N.M.n.M.N.b.N.N.b.N.N.N.S.M.m.M.M.V.b.d.r.V.b.z.M.l.l.d.k.k.g.u.d.u.u.0.w.t.e.0.0.7.y.y.6.u.8.^.}.}.}.}.",
+"}.}.].3.q ` 0.c.z.k.b.b.v.b.b.b.v.N.n.b.C.b.M.b.S.M.b.M.M.m.b.b.9.z.b.z.m.l.j.l.t.g.d.u.u.u.u.e.0.w.0.0.8.7.0.y.6.5.i.6.).}.}.}.",
+"}.}.}._.~ A >.u.l.e.z.z.k.v.v.z.M.M.b.b.b.b.b.b.Z.B.m.b.m.z.z.z.q.j.z.z.l.l.l.h.0.d.u.u.u.u.0.e.e.0.0.8.8.0.i.6.6.7.w.%.u.{.}.}.",
+"}.}.}.}.R.V [ w.e.0.k.l.z.k.l.v.z.b.v.c.v.b.b.b.l.S.b.l.l.m.z.l.l.1.l.l.l.l.j.j.d.0.j.u.u.y.y.0.0.w.i.y.u.t.6.y.y.0.#.#.{ A.}.}.",
+"}.}.}.}.{.:.K 5.d.d.0.j.j.k.k.k.k.z.c.z.x.c.x.x.l.S.l.l.z.l.l.j.l.3.l.l.l.j.h.d.s.e.u.u.u.t.i.a.k.i.y.y.u.y.<. at .[ +. at .@.` O.'.}.",
+"}.}.}.}.}.Y.Z #.w.d.7.p.p.p.k.k.k.k.k.k.k.k.l.k.l.l.B.j.l.l.l.h.j.l.1.j.l.k.j.d.d.d.u.u.g.k.u.i.k.y.5.+.) / I / ( [ ..` x H /.}.",
+"}.}.}.}.}.'.} ` w.y.7.y.u.u.j.j.u.k.k.k.j.k.k.k.k.k.C.k.k.h.j.j.j.j.:.j.j.j.j.d.d.d.u.k.k.u.<.{ ( L U / / ( / ( ( ) U A ; ! ).}.",
+"}.}.}.}.}.}.m.T 7.0.y.6.u.u.u.p.u.u.u.u.p.p.p.j.j.k.z.z.d.d.j.j.d.j.d.1.u.e.q.j.k.u.;.' P J L I U / / / F z h i 0 > - + 6 m.].}.",
+"}.}.}.}.}.}.!.Y 5.8.y.%.e.w.w.u.u.u.y.u.p.u.u.p.j.j.l.m.s.d.d.d.d.d.r.9.V.e.;.' K F J L L I P x f 0 = % X . X . o X & n f.'.}.}.",
+"}.}.}.}.}.}.'. .#.8.8.5.6.w.w.w.w.e.y.y.u.u.u.u.u.u.N.d.u.d.d.g.m.j.9.[ z F F / L U F h 5 = X o @ < u D } *.-.4.4.4.h.U.].}.}.}.",
+"}.}.}.}.}.}.}.1.+.w.6.7.%.0.0.w.0.w.y.0.y.y.y.v.b.b.d.u.h.k.0.o.T F F F l F x r , # . @ < b Q -.h.D.Y./.'.'.{.{.{.{.}.}.}.}.}.}.",
+"}.}.}.}.}.}.}.d.[ u.6.6.>.6.6.7.0.0.0.p.v.v.v.p.u.l.i.>.R C V J F c / F V V $ & 2 N X.f.D.W.).'.{.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.",
+"}.}.}.}.}.}.}.m.[ u.6.5.5.6.w.p.a.k.k.u.0.a.k.0.o.S k m C J J h e * l t u B X.l.J.^.'.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.",
+"}.}.}.}.}.}.}.B.[ y.w.<.5.5.6.6.6.8.a.y.<.E V g j m A x s : o # < B X.l.P./.{.{.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.",
+"}.}.}.}.}.}.}.Z.[ y.N.u.6.5.y.u.0.$.Y m d j m V z i - X % 6 W 4.G./.[.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.",
+"}.}.}.}.}.}.}.B.[ <.k.k.u.0.%.` P m k m m m r ; X % 9 ~ s.J.).{.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.",
+"}.}.}.}.}.}.}.g.) +.$.%.$.+.) L C V m p ; + @ 8 ~ f.P.).{.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.",
+"}.}.}.}.}.}.}.,.z ( ` +.{ / J C j 5 $ . 1 W r.J._.{.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.",
+"}.}.}.}.}.}.}.s.- d V A A V t - + X v :.D./.{.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.",
+"}.}.}.}.}.}.}.J.7 o - 4 4 = O o y =.J.'.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.",
+"}.}.}.}.}.}.}.'.f.9 o   . & u :.J.'.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.",
+"}.}.}.}.}.}.}.}.'.J.r.=.,.h.U.'.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.",
+"}.}.}.}.}.}.}.}.}.}.{.'.{.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.",
+"}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}.}."
+};
diff --git a/src/mod_wiimotes/icons/none.xpm b/src/mod_wiimotes/icons/none.xpm
new file mode 100755
index 0000000..04114ac
--- /dev/null
+++ b/src/mod_wiimotes/icons/none.xpm
@@ -0,0 +1,151 @@
+/* XPM */
+static const char *none[] = {
+/* columns rows colors chars-per-pixel */
+"64 42 103 2",
+"   c gray40",
+".  c #686868",
+"X  c #6A6A6A",
+"o  c gray42",
+"O  c #6D6D6D",
+"+  c gray43",
+"@  c gray44",
+"#  c #717171",
+"$  c gray45",
+"%  c #747474",
+"&  c #767676",
+"*  c #797979",
+"=  c #7F7F7F",
+"-  c #808080",
+";  c #818181",
+":  c gray51",
+">  c #838383",
+",  c #868686",
+"<  c #898989",
+"1  c gray55",
+"2  c #8D8D8D",
+"3  c #8E8E8E",
+"4  c gray56",
+"5  c #909090",
+"6  c #929292",
+"7  c #959595",
+"8  c gray59",
+"9  c #979797",
+"0  c #989898",
+"q  c gray60",
+"w  c #9B9B9B",
+"e  c #9D9D9D",
+"r  c gray62",
+"t  c #A0A0A0",
+"y  c #A4A4A4",
+"u  c #A5A5A5",
+"i  c gray65",
+"p  c #A7A7A7",
+"a  c gray66",
+"s  c #A9A9A9",
+"d  c #AAAAAA",
+"f  c #ACACAC",
+"g  c gray68",
+"h  c #AEAEAE",
+"j  c #B1B1B1",
+"k  c #B2B2B2",
+"l  c gray70",
+"z  c #B4B4B4",
+"x  c gray71",
+"c  c #B6B6B6",
+"v  c #B7B7B7",
+"b  c gray72",
+"n  c #B9B9B9",
+"m  c gray73",
+"M  c #BBBBBB",
+"N  c #BCBCBC",
+"B  c gray74",
+"V  c gray",
+"C  c gray75",
+"Z  c #C0C0C0",
+"A  c #C1C1C1",
+"S  c gray76",
+"D  c #C3C3C3",
+"F  c gray77",
+"G  c #C5C5C5",
+"H  c #C6C6C6",
+"J  c gray78",
+"K  c #CACACA",
+"L  c gray80",
+"P  c #CECECE",
+"I  c gray81",
+"U  c #D0D0D0",
+"Y  c LightGray",
+"T  c gray83",
+"R  c #D5D5D5",
+"E  c #D8D8D8",
+"W  c #DADADA",
+"Q  c gray86",
+"!  c gainsboro",
+"~  c #DFDFDF",
+"^  c gray88",
+"/  c #E1E1E1",
+"(  c #E2E2E2",
+")  c gray89",
+"_  c #E7E7E7",
+"`  c gray91",
+"'  c #E9E9E9",
+"]  c gray92",
+"[  c #EEEEEE",
+"{  c #EFEFEF",
+"}  c gray94",
+"|  c #F1F1F1",
+" . c gray95",
+".. c #F4F4F4",
+"X. c gray96",
+"o. c #F6F6F6",
+"O. c gray97",
+"+. c #F8F8F8",
+"@. c gray98",
+"#. c #FBFBFB",
+"$. c #FDFDFD",
+"%. c #FEFEFE",
+"&. c gray100",
+/* pixels */
+"&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.",
+"&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.",
+"&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.",
+"&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.",
+"&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.",
+"&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.",
+"&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.",
+"&.&.&.&.&.&.&.&.&.&.&.&.&.&.&. at .] o.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.W S Z D ! &.&.&.&.&.&.&.",
+"&.&.&.&.&.&.&.&.&.&.&.&.&.F d @   O i B ` &.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.R f           a U &.&.&.&.&.",
+"&.&.&.&.&.&.&.&.&.&.&.&.N               * m _ &.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.+.N %               = o.&.&.&.&.",
+"&.&.&.&.&.&.&.&.&.&.&.&.i                   = V @.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.F 0                   w #.&.&.&.&.",
+"&.&.&.&.&.&.&.&.&.&.&.&.U 8                     t I &.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.H u                     y ~ &.&.&.&.&.",
+"&.&.&.&.&.&.&.&.&.&.&.&.&. at .Z 7                   + N @.&.&.&.&.&.&.&.&.&.&.&.&.&.&.%.F u                     * N @.&.&.&.&.&.&.",
+"&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.+.V -                   u E &.&.&.&.&.&.&.&.&.&.&.O.Z e                     & n ) &.&.&.&.&.&.&.&.",
+"&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.) z                   & V %.&.&.&.&.&.&.&.{ B 2                     ; M _ &.&.&.&.&.&.&.&.&.&.",
+"&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.S :                   h ^ &.&.&.&./ M =                     2 B } &.&.&.&.&.&.&.&.&.&.&.&.",
+"&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&./ g                   ; A &.R v @                     q C O.&.&.&.&.&.&.&.&.&.&.&.&.&.&.",
+"&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.%.B @                   r .                     w A $.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.",
+"&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.P 8                                     w A $.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.",
+"&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.} c                               w A $.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.",
+"&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.m                         w A $.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.",
+"&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.T k .                         s E &.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.",
+"&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.W c X                               & B #.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.",
+"&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.( b @                                       y Y &.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.",
+"&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.' M %                     w N :                   # N +.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.",
+"&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.} N =                     7 A $.&.) k                     r P &.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.",
+"&.&.&.&.&.&.&.&.&.&.&.&.&.&.] N >                     4 Z @.&.&.&.&.&.S ,                   O M X.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.",
+"&.&.&.&.&.&.&.&.&.&.&.&.Q n *                     < V O.&.&.&.&.&.&.&.&.` x                     0 K &.&.&.&.&.&.&.&.&.&.&.&.&.&.",
+"&.&.&.&.&.&.&.&.&.&.U l o                     > V ..&.&.&.&.&.&.&.&.&.&.&.&.G 4                   X n } &.&.&.&.&.&.&.&.&.&.&.&.",
+"&.&.&.&.&.&.&.&.E k .                     3 B } &.&.&.&.&.&.&.&.&.&.&.&.&.&.&.[ n X                   6 J &.&.&.&.&.&.&.&.&.&.&.",
+"&.&.&.&.&.&.&.C $                     9 C O.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.L e                   . c ] &.&.&.&.&.&.&.&.&.",
+"&.&.&.&.&.&.&.%                   w A $.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.+.N $                   1 K &.&.&.&.&.&.&.&.",
+"&.&.&.&.&.&.&.b               t F %.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.W g                   5 &.&.&.&.&.&.&.&.",
+"&.&.&.&.&.&.&.&.G k 3 = < j F %.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.S 3               c &.&.&.&.&.&.&.&.",
+"&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.| N 0     + p Z $.&.&.&.&.&.&.&.&.",
+"&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&. .] @.&.&.&.&.&.&.&.&.&.&.&.",
+"&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.",
+"&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.",
+"&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.",
+"&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.",
+"&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.",
+"&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&."
+};
diff --git a/src/mod_wiimotes/icons/wiimote-small.xpm b/src/mod_wiimotes/icons/wiimote-small.xpm
new file mode 100755
index 0000000..d9bd13b
--- /dev/null
+++ b/src/mod_wiimotes/icons/wiimote-small.xpm
@@ -0,0 +1,284 @@
+/* XPM */
+static const char *wiimote_small[] = {
+/* columns rows colors chars-per-pixel */
+"64 42 236 2",
+"   c #020202",
+".  c #040404",
+"X  c #060606",
+"o  c #070707",
+"O  c gray3",
+"+  c #0B0B0B",
+"@  c #0C0C0C",
+"#  c #0E0E0E",
+"$  c gray9",
+"%  c #191919",
+"&  c #1B1B1B",
+"*  c #1E1E1E",
+"=  c #202020",
+"-  c #222222",
+";  c #232323",
+":  c gray14",
+">  c gray15",
+",  c #282828",
+"<  c gray16",
+"1  c #2A2A2A",
+"2  c gray17",
+"3  c #2C2C2C",
+"4  c #2D2D2D",
+"5  c gray18",
+"6  c #2F2F2F",
+"7  c gray19",
+"8  c #323232",
+"9  c gray20",
+"0  c #343434",
+"q  c #353535",
+"w  c gray21",
+"e  c #373737",
+"r  c gray22",
+"t  c #393939",
+"y  c #3A3A3A",
+"u  c gray23",
+"i  c #3C3C3C",
+"p  c gray24",
+"a  c #3F3F3F",
+"s  c gray25",
+"d  c #414141",
+"f  c gray26",
+"g  c #434343",
+"h  c #444444",
+"j  c gray27",
+"k  c #464646",
+"l  c gray28",
+"z  c #484848",
+"x  c #494949",
+"c  c gray29",
+"v  c #4B4B4B",
+"b  c #4C4C4C",
+"n  c #4E4E4E",
+"m  c #505050",
+"M  c #515151",
+"N  c gray32",
+"B  c #535353",
+"V  c #555555",
+"C  c #565656",
+"Z  c gray34",
+"A  c #585858",
+"S  c gray35",
+"D  c #5A5A5A",
+"F  c #5B5B5B",
+"G  c gray36",
+"H  c #5D5D5D",
+"J  c gray37",
+"K  c #5F5F5F",
+"L  c #606060",
+"P  c gray38",
+"I  c #626262",
+"U  c gray39",
+"Y  c #646464",
+"T  c #656565",
+"R  c gray40",
+"E  c #676767",
+"W  c #686868",
+"Q  c DimGray",
+"!  c #6A6A6A",
+"~  c gray42",
+"^  c #6D6D6D",
+"/  c gray43",
+"(  c #6F6F6F",
+")  c gray44",
+"_  c #717171",
+"`  c #727272",
+"'  c gray45",
+"]  c #747474",
+"[  c gray46",
+"{  c #767676",
+"}  c #777777",
+"|  c gray47",
+" . c #797979",
+".. c #7B7B7B",
+"X. c #7C7C7C",
+"o. c gray49",
+"O. c #7E7E7E",
+"+. c #7F7F7F",
+"@. c #808080",
+"#. c #818181",
+"$. c gray51",
+"%. c #838383",
+"&. c #848484",
+"*. c gray52",
+"=. c #868686",
+"-. c gray53",
+";. c #888888",
+":. c #898989",
+">. c gray54",
+",. c #8B8B8B",
+"<. c gray55",
+"1. c #8E8E8E",
+"2. c gray56",
+"3. c #909090",
+"4. c gray57",
+"5. c #939393",
+"6. c gray58",
+"7. c #959595",
+"8. c gray59",
+"9. c #979797",
+"0. c #989898",
+"q. c gray60",
+"w. c #9A9A9A",
+"e. c #9B9B9B",
+"r. c gray61",
+"t. c #9D9D9D",
+"y. c gray62",
+"u. c #9F9F9F",
+"i. c #A0A0A0",
+"p. c gray63",
+"a. c #A2A2A2",
+"s. c gray64",
+"d. c #A4A4A4",
+"f. c #A5A5A5",
+"g. c gray65",
+"h. c #A7A7A7",
+"j. c gray66",
+"k. c #A9A9A9",
+"l. c #AAAAAA",
+"z. c gray67",
+"x. c #ACACAC",
+"c. c gray68",
+"v. c #AEAEAE",
+"b. c #AFAFAF",
+"n. c gray69",
+"m. c #B1B1B1",
+"M. c #B2B2B2",
+"N. c gray70",
+"B. c #B4B4B4",
+"V. c gray71",
+"C. c #B6B6B6",
+"Z. c #B7B7B7",
+"A. c gray72",
+"S. c #B9B9B9",
+"D. c gray73",
+"F. c #BBBBBB",
+"G. c #BCBCBC",
+"H. c gray74",
+"J. c gray",
+"K. c gray75",
+"L. c #B9C9E4",
+"P. c #C0C0C0",
+"I. c #C1C1C1",
+"U. c gray76",
+"Y. c #C3C3C3",
+"T. c gray77",
+"R. c #C5C5C5",
+"E. c #C6C6C6",
+"W. c gray78",
+"Q. c #C8C8C8",
+"!. c gray79",
+"~. c #CACACA",
+"^. c #CBCBCB",
+"/. c gray80",
+"(. c #CDCDCD",
+"). c #CECECE",
+"_. c gray81",
+"`. c #D4D0CE",
+"'. c #C3C8D1",
+"]. c #CFD2D7",
+"[. c #D0D0D0",
+"{. c gray82",
+"}. c #D2D2D2",
+"|. c LightGray",
+" X c gray83",
+".X c #D5D5D5",
+"XX c gray84",
+"oX c #D7D7D7",
+"OX c #DCD3D4",
+"+X c #D8D8D8",
+"@X c gray85",
+"#X c #DADADA",
+"$X c gray86",
+"%X c gainsboro",
+"&X c #DDDDDD",
+"*X c gray87",
+"=X c #DFDFDF",
+"-X c #E0E0DF",
+";X c #CAD2E2",
+":X c gray88",
+">X c #E1E1E1",
+",X c #E1E1E2",
+"<X c #E1E2E3",
+"1X c #E2E2E2",
+"2X c gray89",
+"3X c #E4E4E4",
+"4X c gray90",
+"5X c #E6E6E6",
+"6X c #E7E7E7",
+"7X c gray91",
+"8X c #E9E9E9",
+"9X c #EAEAEA",
+"0X c gray92",
+"qX c #ECEBEA",
+"wX c #ECECEC",
+"eX c gray93",
+"rX c #EEEEEE",
+"tX c #EFEFEF",
+"yX c gray94",
+"uX c #F1F1F1",
+"iX c gray95",
+"pX c #F3F2F2",
+"aX c #F3F3F3",
+"sX c #F4F4F4",
+"dX c gray96",
+"fX c #F6F6F6",
+"gX c gray97",
+"hX c #F8F8F8",
+"jX c #F9F9F9",
+"kX c gray98",
+"lX c #FBFBFB",
+"zX c #FBFCFC",
+"xX c gray99",
+"cX c #FDFDFD",
+"vX c #FEFEFE",
+"bX c gray100",
+/* pixels */
+"bXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXeX9XqXiXjXbXbXbXbXbXbXbXbXbXbXbX",
+"bXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXeX5X1X at X`.OX1XeXjXbXbXbXbXbXbXbXbXbX",
+"bXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXsX9X*X1XS.T.1X*X*X*X1X1X9XiXjXbXbXbXbXbXbX",
+"bXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXzXaX5X:X*X1X1XS.' G.*X1X at XS.1X1X1X5XeXsXbXbXbXbX",
+"bXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXeX2X*X:X1X1X*X1X2X] ' h.6.;.k.Y.1X1X1X5XeXsXbXbXbX",
+"bXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXsX9X*X*X1X1X1X Xm.k.b.G.~.h.m.).s.>.P.1X5X9X9X}.1XbXbXbX",
+"bXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXsX5X*X1X1X1X1X1X1XG.>.d.h.s.S.1X1X1X1X1X1X5XeX1XG.>.1XbXbXbX",
+"bXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXjXeX1X).}. at X*X1X1X1X1X1X1XP.r.t.s./.1X1X1X1X5XwX9X).3.' w.sXbXbXbX",
+"bXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXjX9X1X*X1X}.m.G.XX1X1X1X1X1X1X2X:X%X*X1X1X1X5X9XeX*Xk.$.( ( m.bXbXbXbX",
+"bXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXsX5X*X*X1X1X1X1X1X1X1X}.L.;X%X1X1X2X1X1X1X1X5X5XeX5XP.<.( ' K ] 9XbXbXbXbX",
+"bXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXjXiX1X*X*X1X1X1X1X1X1X1X1XXXR.'.]. at X*X%X1X1X1X1X5X9X9X}.s...( ( Q m.9XbXbXbXbXbX",
+"bXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXjX9X1X*X1X1X1X1X1X1X1X*X1X1X1X1X*X*X1X*Xh.Q. at X*X5X7XeX1XC.*.( ' R o.XXbXbXbXbXbXbXbX",
+"bXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXsX5X*X*X1X1X1X1X1X1X1X*X*X}. at X@X*X1X1X1X1X1X}.G.~.5XwX9X~.w.( ( ' U <.iXbXbXbXbXbXbXbXbX",
+"bXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXiX5X*X*X1X1X1X1X1X1X1X1X1X*X*XXX at X@X1X1X1X1X1X1X2X5XwXeX*XC.o.R ' ' K 6.iXbXbXbXbXbXbXbXbXbX",
+"bXbXbXbXbXbXbXbXbXbXbXbXbXbXbXjXeX1X at X1X1X1X1X1X1X*X*X*X1X1X1X1X1X*X1X1X1X1X1X1X1X5X9XeX2XP.<.Q Q ..R K 6.sXbXbXbXbXbXbXbXbXbXbX",
+"bXbXbXbXbXbXbXbXbXbXbXbXbXjX9X*X*X1X1X1X1X1X1X1X*XXX*X at X1X1X1X1X1X1X1X1X1X1X1X5X6XeX9X Xh...R ' ( U S *.eXbXbXbXbXbXbXbXbXbXbXbX",
+"bXbXbXbXbXbXbXbXbXbXbXiX5X*X*X1X5X1X1X1X1X1X1X1X}.*.P.}.C.}.1X1X1X1X1X1X1X1X5X9XeX1XS.*.Q Q ..R S S ..9XbXbXbXbXbXbXbXbXbXbXbXbX",
+"bXbXbXbXbXbXbXbXjXiX1X at X@XXX1X1X1X1X1X1X at X@X*X1X1XG.b.m.R.*X1X1X1X1X1X1X5X9XeX5X~.w.] R $.' K S V Q *XbXbXbXbXbXbXbXbXbXbXbXbXbX",
+"bXbXbXbXbXbXjX9X*X at X*X1Xb.6.1X1X1X1X1X).*X at X*X at X*X1X1X1X1X1X1X1X1X1X5X9XeXeX*Xb.*.R Q ..Q S S V R ).bXbXbXbXbXbXbXbXbXbXbXbXbXbX",
+"bXbXbXbXsX5X at X*X1X1X1X1X at X@X1X). at X1X1X<.b.~.G.k.*X1X1X1X1X1X1X1X5X5XeXeX1XG.3.' R ] ' K S S U *.1XbXbXbXbXbXbXbXbXbXbXbXbXbXbXbX",
+"bXbXbX9X*X*X1X1X1X1X1XXX*X1X at X$.C.1X1X}.m.m.S. at X1X1X1X1X1X1X1X5X9XeX9XXXk.o.R Q ..Q K S S U h.9XbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbX",
+"bXbX1X~.1X5X5X1X1X at Xb.w.P.XX1X1X1X@XG.*X1X1X1X1X1X1X1X1X1X1X9XeXeX*XC.>.Q R ] ] S S S K $.~.jXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbX",
+"bXbXXX*.P.1X5X5X1Xk...t.*.R. at X1X1X~.o.).1X1X1X1X1X1X1X5X5X9XeX9X~.t.] R Q o.R S S S R <.*XbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbX",
+"bXbX9XV U m. at X5X5X*XXX$.6.h.h.G.1X1X1X1X*XR.1X1X1X1X5X9XeXeXXXb.$.Q U ..] K S S K ' m.jXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbX",
+"bXbXjXR u S t. at X5X5X1X~.P.w.h.R.m.*X1X1XG.] ~.1X5X5XeXeX*XP.6.' U Q o.R S S S U o.XXjXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbX",
+"bXbXbX*.v q b 6.).5X5X5X~.b.6.b.1X1X1X1X1X*X5X5X9XiX9X}.h.o.Q U o.] K S S K R s.9XbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbX",
+"bXbXbXw.u b u h ..R.1X5X5X at XXX1X1X1X1X1X1X5X9XeXeX@XC.<.( U ' o.R S S S K ..G.jXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbX",
+"bXbXbXG.2 u V 9 p ] S.1X5X5X1X1X1X5X1X1X9XeXiX9X).t.o.Q U o.' U S S S Q $. at XbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbX",
+"bXbXbX*Xh u $ g p q S h. at X5X5X5X1X5X9X9XiX9XXXk.*.Q U ( $.U S S S U ' k.jXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbX",
+"bXbXbX9XU V % + q g u V w.}.5X9X9X9XeXeX1XG.t.] R R $.] K S S S U ] ~.jXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbX",
+"bXbXbXjX..2 > * + 6 h 9 b *.~.5XiXiX9X).k.$.Q K ' o.R S S S K U w.5XbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbX",
+"bXbXbXbXS.q 2 * X   > b q h o.P.9X*XC.3.' U U o.' K S S S K ] C.sXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbX",
+"bXbXbXbXjX] 2 2 * X   2 m q g Q t.t.o.Q S ' $.Q S S S S R $.XXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbX",
+"bXbXbXbXbX1XK 2 2 - + # q m g m ( ' R K o.] U S S S U ( s.eXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbX",
+"bXbXbXbXbXbX at Xu > 2 - * 2 9 m Q R U U *.' K S S S R ( P.sXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbX",
+"bXbXbXbXbXbXbXR.v u 2 2 6 v q V $.o.>.R S S V K R 3.5XbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbX",
+"bXbXbXbXbXbXbXbX).m.g 2 6 ' p v U R U S S S K ( k.iXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbX",
+"bXbXbXbXbXbXbXbXbX9X$.2 2 S g h U R K S V K ..}.bXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbX",
+"bXbXbXbXbXbXbXbXbXjX~.g > 2 6 h K U S m K w.9XbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbX",
+"bXbXbXbXbXbXbXbXbXbXbXXXK - 6 g V S v K P.jXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbX",
+"bXbXbXbXbXbXbXbXbXbXbXbXeXw.p q g v >.5XbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbX",
+"bXbXbXbXbXbXbXbXbXbXbXbXbXbX}.w.>.G.sXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbXbX"
+};
diff --git a/src/mod_wiimotes/mod_wiimotes.cpp b/src/mod_wiimotes/mod_wiimotes.cpp
new file mode 100644
index 0000000..2d2cdb6
--- /dev/null
+++ b/src/mod_wiimotes/mod_wiimotes.cpp
@@ -0,0 +1,1192 @@
+/////////////////////////////////////////////////////////////////////////////
+// File:        mod_wiimotes.cpp
+// Author:      Cesar Mauri Loba (cesar at crea-si dot com)
+// Copyright:   (C) 2011 Cesar Mauri Loba - CREA Software Systems
+//
+//  This program is free software: you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation, either version 3 of the License, or
+//  (at your option) any later version.
+//
+//  This program is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+/////////////////////////////////////////////////////////////////////////////
+// TODO: fix linux working issue, may require permanent pairing
+#include "spcore/component.h"
+#include "spcore/module.h"
+#include "spcore/libimpexp.h"
+#include "spcore/basictypes.h"
+#include "mod_wiimotes.h"
+#include "wwiimotesconfiguration.h"
+
+#include <string>
+#include <boost/thread/thread.hpp>
+#include <boost/thread/xtime.hpp>
+#include <boost/thread/mutex.hpp>
+#include <boost/bind.hpp>
+#include <boost/shared_ptr.hpp>
+#include <boost/thread/recursive_mutex.hpp>
+#include <stdio.h>
+
+using namespace spcore;
+
+namespace mod_wiimotes {
+
+static void sleep_miliseconds( unsigned int ms )
+{
+	boost::xtime xt;
+	boost::xtime_get(&xt, boost::TIME_UTC);
+	xt.nsec+= ms * 1000000;
+	boost::thread::sleep(xt);
+}
+
+/*
+	wii_use main thread
+*/
+
+// wii capture thread
+class WiiuseThread
+{
+public:
+	/**
+		TODO: filter desired wiimote according to desired type & number
+		Device filter flags
+	*/
+	/*
+	enum FilterWiimotes {
+		FILTER_WIIMOTE			= 0x100,	// Take only into account Wiimote devices
+		FILTER_BALANCE_BOARD	= 0x200		// Take only into account Balance Board devices
+	};*/
+
+	enum DesiredFeatures { NONE= 0x0, ACC= 0x1, MOTION_PLUS= 0x2, NUNCHUCK= 0x4 };
+
+	WiiuseThread ()
+	: m_wiimotes(NULL)
+	, m_Life(true)
+	, m_hasListeners(false)
+	, m_enabledFeaturesChanged(false)
+	, m_statusRequested(false)
+	, m_state(DO_CONNECT)
+	{
+		m_status= CTypeWiimotesStatus::CreateInstance();
+		assert (m_status.get());
+	}
+
+	~WiiuseThread () {
+		Stop();
+	}
+
+	void Stop() {
+		if (m_Life) {
+			m_Life= false;
+		}
+	}
+
+	/**
+		Register a listener
+
+	*/
+	//void RegisterListener (WiimoteListener& wl, CTypeWiimotesStatus::EnableFeatures flags, unsigned int filter) {
+	void RegisterListener (WiimoteListener& wl, unsigned int desiredFea, unsigned int filter) {
+		boost::mutex::scoped_lock mutex(m_mutex);
+
+		assert (filter< CTypeWiimotesStatus::MAXWIIMOTES);
+		assert (!(desiredFea & 0xFFF8));
+
+		// Check if already registered
+		std::vector<struct ListenerConfiguration>::iterator it= m_listeners.begin();
+		for (; it != m_listeners.end() && it->callBack!= &wl; ++it);
+
+		if (it!= m_listeners.end()) {
+			// Already registered. Update desired features and filter
+			it->df= desiredFea;
+			it->filter= filter;
+		}
+		else {
+			// Not registered. Add
+			struct ListenerConfiguration lc;
+			lc.callBack= &wl;
+			lc.df= desiredFea;
+			lc.filter= filter;
+			m_listeners.push_back (lc);
+		}
+
+		m_hasListeners= (m_listeners.size()> 0);
+		m_enabledFeaturesChanged= true;
+	}
+
+	/**
+		Unregister a listener
+
+	*/
+	void UnregisterListener (WiimoteListener& wl) {
+		boost::mutex::scoped_lock mutex(m_mutex);
+
+		// Check if already registered
+		std::vector<struct ListenerConfiguration>::iterator it= m_listeners.begin();
+		for (; it != m_listeners.end() && it->callBack!= &wl; ++it);
+
+		if (it== m_listeners.end()) return; // Not found
+
+		m_listeners.erase (it);
+
+		m_hasListeners= (m_listeners.size()> 0);
+		m_enabledFeaturesChanged= true;
+	}
+
+	// Thread entry point
+	void Entry() {
+		// Start thread main loop
+		while (m_Life) {
+			switch (m_state) {
+			case DO_CONNECT: DoConnectState(); break;
+			case CONNECTED: ConnectedState(); break;
+			case DO_RECONNECT:
+				Cleanup();
+				m_state= DO_CONNECT;
+				break;
+			case IDLE:
+				if (!m_hasListeners) m_state= DO_CONNECT;
+				else sleep_miliseconds(500);
+				break;
+			default: assert (false);
+			}
+
+			if (m_statusRequested) NotifyStatus (*m_status);
+		}
+
+		Cleanup();
+	}
+
+	// Issues a reconnection request. Disconnects all wiimotes and tries to reconnect them
+	void Reconnect()
+	{
+		m_state= DO_RECONNECT;
+	}
+
+	// Request wiimotes status
+	void ReqStatus()
+	{
+		boost::mutex::scoped_lock mutex(m_mutex);
+
+		m_statusRequested= true;
+	}
+
+private:
+	enum WiimoteThreadState { DO_CONNECT= 0, CONNECTED, DO_RECONNECT, IDLE };
+
+	void NotifyStatus (CTypeWiimotesStatus& s) {
+		boost::mutex::scoped_lock mutex(m_mutex);
+
+		std::vector<struct ListenerConfiguration>::iterator it= m_listeners.begin();
+		for(; it!= m_listeners.end(); ++it) it->callBack->StatusNotification(s);
+
+		m_statusRequested= false;
+	}
+
+	void Cleanup() {
+		wiiuse_cleanup(m_wiimotes, CTypeWiimotesStatus::MAXWIIMOTES);
+		m_wiimotes= NULL;
+		m_status->Reset();
+	}
+
+	void DoConnectState() {
+		ICoreRuntime& core= *getSpCoreRuntime();
+
+		// Are there any listener?
+		if (!m_hasListeners) {
+			// TODO: avoid polling
+			sleep_miliseconds( 500 );
+			return;
+		}
+
+		//
+		// New listeners found.
+		//
+
+		//	Initialize an array of wiimote objects.
+		assert (!m_wiimotes);
+		m_wiimotes =  wiiuse_init(CTypeWiimotesStatus::MAXWIIMOTES);
+		if (!m_wiimotes) {
+			core.LogMessage(ICoreRuntime::LOG_ERROR, "wiiuse_init failed!", "mod_wiimotes");
+			assert (false);
+			sleep_miliseconds( 500 );
+			return;
+		}
+
+		// Change status to say connecting and notify listeners
+		assert (m_status->GetGeneralStatus()== CTypeWiimotesStatus::IDLE);
+		m_status->SetGeneralStatus (CTypeWiimotesStatus::CONNECTING);
+		NotifyStatus (*m_status);
+
+		// Find wiimote devices. Set a timeout of 5 seconds.
+		// This will return the number of actual wiimotes that are in discovery mode.
+		int found = wiiuse_find(m_wiimotes, CTypeWiimotesStatus::MAXWIIMOTES, 5);
+		if (!found) {
+			core.LogMessage(ICoreRuntime::LOG_WARNING, "No wiimotes found.", "mod_wiimotes");
+			Cleanup();
+			m_state= IDLE;
+			NotifyStatus (*m_status);
+			sleep_miliseconds( 500 );
+			return;
+		}
+
+		// Now that we found some wiimotes, connect to them.
+		// Give the function the wiimote array and the number
+		// of wiimote devices we found.
+		// This will return the number of established connections to the found wiimotes.
+		int connected= wiiuse_connect(m_wiimotes, CTypeWiimotesStatus::MAXWIIMOTES);
+		assert (connected<= CTypeWiimotesStatus::MAXWIIMOTES);
+		if (!connected) {
+			core.LogMessage(ICoreRuntime::LOG_INFO, "Failed to connect to any wiimote.", "mod_wiimotes");
+			Cleanup();
+			m_state= IDLE;
+			NotifyStatus (*m_status);
+			sleep_miliseconds( 500 );
+			return;
+		}
+
+		// Connected. Update status & notify listeners
+		m_status->SetGeneralStatus(CTypeWiimotesStatus::CONNECTED);
+		m_status->SetConnectedCount(connected);
+		for (int i= 0; i< connected; ++i) {
+			// Simply set as WIIMOTE_CONNECTED. Extensions are discovered later.
+			m_status->SetIsConnected (i, true);
+		}
+		NotifyStatus (*m_status);
+
+		// Add log
+		{
+			char buff[100];
+			snprintf(buff, 100, "Connected to %i wiimotes (of %i found)", connected, found);
+			core.LogMessage(ICoreRuntime::LOG_INFO, buff, "mod_wiimotes");
+		}
+
+		// Now set the LEDs
+		wiiuse_set_leds(m_wiimotes[0], WIIMOTE_LED_1);
+		wiiuse_set_leds(m_wiimotes[1], WIIMOTE_LED_2);
+		wiiuse_set_leds(m_wiimotes[2], WIIMOTE_LED_3);
+		wiiuse_set_leds(m_wiimotes[3], WIIMOTE_LED_4);
+
+		// And rumble briefly
+		for (int i= 0; i< connected; ++i) wiiuse_rumble(m_wiimotes[i], 1);
+		sleep_miliseconds( 200 );
+		for (int i= 0; i< connected; ++i) wiiuse_rumble(m_wiimotes[i], 0);
+
+		// Finally change thread state
+		m_state= CONNECTED;
+	}
+
+	// This method should be called every time the enabled features (i.e.
+	// accelerometers or motion plus) are changed. Returns if status changed.
+	bool UpdateEnabledFeatures () {
+		bool changed= false;
+
+		boost::mutex::scoped_lock mutex(m_mutex);
+
+		for (unsigned int i = 0; i < m_status->GetMaxCount(); ++i) {
+			if (!m_status->IsConnected(i)) continue;
+
+			// Compute desired features flags
+			unsigned int desiredFeatures= 0;
+			std::vector<struct ListenerConfiguration>::iterator it= m_listeners.begin();
+			for (; it != m_listeners.end(); ++it)
+				if (it->filter== i) desiredFeatures|= it->df;
+
+			//
+			// Manage continouous mode. It should be enabled whenever accelerometers
+			// or motion plus are requested or when nunchuck is requested, is not enabled
+			// but is present.
+			//
+			// It should be disabled when
+			//
+			if ((desiredFeatures & NUNCHUCK && m_status->HasNunchuk(i) && !m_status->IsNunchuckEnabled(i)) ||
+				desiredFeatures & ACC || desiredFeatures & MOTION_PLUS)
+				wiiuse_set_flags(m_wiimotes[i], WIIUSE_CONTINUOUS, 0);
+			else
+				wiiuse_set_flags(m_wiimotes[i], 0, WIIUSE_CONTINUOUS);
+
+			//
+			// Nunchuck does not need to be explicitly enabled, just update status
+			//
+			if (desiredFeatures & NUNCHUCK && m_status->HasNunchuk(i) && !m_status->IsNunchuckEnabled(i))
+				m_status->SetEnabledFeature (i, CTypeWiimotesStatus::ENABLED_NUNCHUCK);
+			else if (!(desiredFeatures & NUNCHUCK) || !m_status->HasNunchuk(i))
+				m_status->UnsetEnabledFeature (i, CTypeWiimotesStatus::ENABLED_NUNCHUCK);
+
+			//
+			// Check whether accelerometers need to be enabled or disabled
+			//
+			if (m_status->IsAccelerometersEnabled(i)) {
+				// Acc enabled. Check if need to be disabled
+				if (!(desiredFeatures & ACC)) {
+					// Disable accelerometers
+					wiiuse_motion_sensing(m_wiimotes[i], 0);
+					m_status->UnsetEnabledFeature (i, CTypeWiimotesStatus::ENABLED_ACC);
+					changed= true;
+				}
+			}
+			else {
+				if (desiredFeatures & ACC) {
+					// Enable accelerometers
+					wiiuse_motion_sensing(m_wiimotes[i], 1);
+					m_status->SetEnabledFeature (i, CTypeWiimotesStatus::ENABLED_ACC);
+					changed= true;
+				}
+			}
+
+			//
+			// Check whether motion plus needs to be enabled or disabled
+			//
+			if (m_status->IsMotionPlusEnabled(i)) {
+				// Acc enabled. Check if need to be disabled
+				if (!(desiredFeatures & MOTION_PLUS)) {
+					// Disable motion plus
+					wiiuse_set_motion_plus(m_wiimotes[i], 0);
+					m_status->UnsetEnabledFeature (i, CTypeWiimotesStatus::ENABLED_MP);
+					changed= true;
+				}
+			}
+			else {
+				if (desiredFeatures & MOTION_PLUS) {
+					// Enable motion plus
+					wiiuse_set_motion_plus(m_wiimotes[i], 1);
+					m_status->SetEnabledFeature (i, CTypeWiimotesStatus::ENABLED_MP);
+					changed= true;
+				}
+			}
+		}
+		m_enabledFeaturesChanged= false;
+
+		return changed;
+	}
+
+	void HandleGenericEvent (unsigned int wiimote_n)
+	{
+		// Notify all listeners interested on this wiimote
+		boost::mutex::scoped_lock mutex(m_mutex);
+
+		std::vector<struct ListenerConfiguration>::iterator it= m_listeners.begin();
+		for(; it!= m_listeners.end(); ++it) {
+			if (it->filter== wiimote_n)
+				it->callBack->WiimoteNotification (m_wiimotes[wiimote_n]);
+		}
+	}
+
+	void ConnectedState()
+	{
+		if (!m_hasListeners) {
+			// No more listeners available. Finish
+			Cleanup();
+			m_state= IDLE;
+			return;
+		}
+
+		assert (m_status->GetConnectedCount());
+
+		// Poll events
+		if (wiiuse_poll(m_wiimotes, CTypeWiimotesStatus::MAXWIIMOTES)) {
+			for (unsigned int i = 0; i < CTypeWiimotesStatus::MAXWIIMOTES; ++i) {
+				switch (m_wiimotes[i]->event) {
+					case WIIUSE_NONE:
+						break;
+
+					case WIIUSE_EVENT:
+						// a generic event occured
+						HandleGenericEvent (i);
+						break;
+
+					case WIIUSE_STATUS:
+					case WIIUSE_CONNECT:
+						// Once connected enable accelerometers or motion
+						// plus when needed
+						if (UpdateEnabledFeatures()) NotifyStatus (*m_status);
+						break;
+
+					case WIIUSE_DISCONNECT:
+					case WIIUSE_UNEXPECTED_DISCONNECT:
+					{
+						// the wiimote disconnected
+						int count= m_status->GetConnectedCount() - 1;
+						assert (count>= 0);
+						if (count== 0) {
+							Cleanup();
+							m_state= IDLE;
+							NotifyStatus (*m_status);
+							getSpCoreRuntime()->LogMessage(ICoreRuntime::LOG_WARNING, "All wiimotes disconnected", "mod_wiimotes");
+							return;
+						}
+						else {
+							m_status->SetConnectedCount(count);
+							m_status->SetIsConnected(i, false);
+							NotifyStatus (*m_status);
+							getSpCoreRuntime()->LogMessage(ICoreRuntime::LOG_WARNING, "Wiimote disconnected", "mod_wiimotes");
+						}
+						break;
+					}
+					case WIIUSE_READ_DATA:
+					case WIIUSE_WRITE_DATA:
+						break;
+
+					case WIIUSE_NUNCHUK_INSERTED:
+						//wiiuse_set_nunchuk_orient_threshold((struct nunchuk_t*)&wiimotes[i]->exp.nunchuk, 90.0f);
+						//wiiuse_set_nunchuk_accel_threshold((struct nunchuk_t*)&m_wiimotes[i]->exp.nunchuk, 0);
+						//wiiuse_set_nunchuk_accel_threshold(m_wiimotes[i], 0);
+
+						m_status->SetExtension (i, CTypeWiimotesStatus::NUNCHUK);
+						UpdateEnabledFeatures();
+						NotifyStatus (*m_status);
+						break;
+
+					case WIIUSE_CLASSIC_CTRL_INSERTED:
+						m_status->SetExtension (i, CTypeWiimotesStatus::CLASSIC);
+						NotifyStatus (*m_status);
+						break;
+
+					case WIIUSE_GUITAR_HERO_3_CTRL_INSERTED:
+						m_status->SetExtension (i, CTypeWiimotesStatus::GUITAR_HERO);
+						NotifyStatus (*m_status);
+						break;
+
+					case WIIUSE_BALANCE_BOARD_CTRL_INSERTED:
+						m_status->SetExtension (i, CTypeWiimotesStatus::BALANCE_BOARD);
+						NotifyStatus (*m_status);
+						break;
+
+					case WIIUSE_MOTION_PLUS_ACTIVATED:
+						// TODO: detect motion plus presence.
+						// FIXME: fix wiiuse library to manage properly nunchuck
+						// insertion/extraction when motion plus is enabled
+						m_status->SetExtension (i, CTypeWiimotesStatus::MOTION_PLUS);
+						NotifyStatus (*m_status);
+						break;
+
+					case WIIUSE_NUNCHUK_REMOVED:
+					case WIIUSE_CLASSIC_CTRL_REMOVED:
+					case WIIUSE_GUITAR_HERO_3_CTRL_REMOVED:
+					case WIIUSE_MOTION_PLUS_REMOVED:
+					case WIIUSE_BALANCE_BOARD_CTRL_REMOVED:
+						// some expansion was removed
+						switch (m_wiimotes[i]->exp.type) {
+						case EXP_NONE:
+							m_status->SetExtension (i, CTypeWiimotesStatus::NONE);
+							break;
+						case EXP_NUNCHUK:
+							m_status->SetExtension (i, CTypeWiimotesStatus::NUNCHUK);
+							break;
+						case EXP_CLASSIC:
+							m_status->SetExtension (i, CTypeWiimotesStatus::CLASSIC);
+							break;
+						case EXP_GUITAR_HERO_3:
+							m_status->SetExtension (i, CTypeWiimotesStatus::GUITAR_HERO);
+							break;
+						case EXP_WII_BOARD:
+							m_status->SetExtension (i, CTypeWiimotesStatus::BALANCE_BOARD);
+							break;
+						case EXP_MOTION_PLUS:
+							m_status->SetExtension (i, CTypeWiimotesStatus::MOTION_PLUS);
+							break;
+						default:
+							assert (false);
+						}
+						UpdateEnabledFeatures();
+						NotifyStatus (*m_status);
+						break;
+
+					default:
+						assert (false);
+						break;
+				}
+			}
+		}
+
+		if (m_enabledFeaturesChanged)
+			if (UpdateEnabledFeatures()) NotifyStatus (*m_status);
+	}
+
+private:
+
+	wiimote** m_wiimotes;
+	bool volatile m_Life;
+	bool volatile m_hasListeners;
+	bool volatile m_enabledFeaturesChanged;
+	bool volatile m_statusRequested;
+	WiimoteThreadState volatile m_state;
+	SmartPtr<CTypeWiimotesStatus> m_status;
+	boost::mutex m_mutex;
+	struct ListenerConfiguration {
+		WiimoteListener* callBack;					// object that is called
+		unsigned int filter;						// filter to select wiimote, current the wiimote number
+		unsigned int df;							// features that the listener asked for
+	};
+	std::vector<struct ListenerConfiguration> m_listeners;
+};
+
+
+/*
+	Thread controller
+
+	This is a singleton class which starts/stops the wiimotes thread and forwards requests
+*/
+WiiuseThreadController::WiiuseThreadController()
+{
+	m_worker= new WiiuseThread();
+	m_thread= new boost::thread(&WiiuseThread::Entry, m_worker);
+	assert (m_thread->joinable());
+}
+
+WiiuseThreadController::~WiiuseThreadController()
+{
+	m_worker->Stop();
+	m_thread->join();
+	delete m_thread;
+	delete m_worker;
+}
+
+WiiuseThreadController * WiiuseThreadController::getInstance() {
+	if (!g_instance) {
+		g_instance= new WiiuseThreadController();
+	}
+	return g_instance;
+}
+
+void WiiuseThreadController::destroyInstance() {
+	delete g_instance;
+	g_instance= NULL;
+}
+
+void WiiuseThreadController::RegisterListener (WiimoteListener& wl, unsigned int df, unsigned int filter) {
+	m_worker->RegisterListener(wl, df, filter);
+}
+
+void WiiuseThreadController::UnregisterListener (WiimoteListener& wl) {
+	m_worker->UnregisterListener(wl);
+}
+
+void WiiuseThreadController::Reconnect() {
+	m_worker->Reconnect ();
+}
+
+void WiiuseThreadController::ReqStatus() {
+	m_worker->ReqStatus();
+}
+
+WiiuseThreadController * WiiuseThreadController::g_instance= NULL;
+
+
+/*
+	wii_config component
+
+	This manages the wiimotes configuration
+*/
+
+class WiimotesConfig : public spcore::CComponentAdapter, public WiimoteListener {
+public:
+	WiimotesConfig(const char * name, int argc, const char * argv[])
+	: CComponentAdapter(name, argc, argv)
+	{
+		RegisterInputPin (*SmartPtr<InputPinReconnect>(new InputPinReconnect(*this), false));
+		RegisterInputPin (*SmartPtr<InputPinReqStatus>(new InputPinReqStatus(*this), false));
+
+		m_oPinStatus= CTypeWiimotesStatus::CreateOutputPin("status");
+		if (m_oPinStatus.get()== NULL)
+			// Output pin creation failed. Shouldn't happen but...
+			throw std::runtime_error("wiimotes_config. output pin creation failed.");
+		RegisterOutputPin (*m_oPinStatus);
+
+		m_status= CTypeWiimotesStatus::CreateInstance();
+		if (m_status.get()== NULL)
+			// Output pin creation failed. Shouldn't happen but...
+			throw std::runtime_error("wiimotes_config. instance creation failed.");
+	}
+
+	static const char* getTypeName() { return "wiimotes_config"; };
+	virtual const char* GetTypeName() const { return WiimotesConfig::getTypeName(); };
+
+	virtual bool ProvidesExecThread() const { return true; }
+
+	virtual int DoInitialize() {
+		if (m_oPinStatus->GetNumComsumers()> 0) {
+			WiiuseThreadController::getInstance()->RegisterListener(*this, WiiuseThread::NONE, 0);
+		}
+		return 0;
+	}
+
+	virtual void DoFinish() {
+		WiiuseThreadController::getInstance()->UnregisterListener(*this);
+	}
+
+	virtual void StatusNotification (const CTypeWiimotesStatus & msg) {
+		msg.Clone (m_status.get(), true);
+		m_oPinStatus->Send(m_status);
+	}
+	virtual void WiimoteNotification (wiimote *) {
+		// Do nothing
+	}
+
+private:
+	virtual ~WiimotesConfig()
+	{
+	}
+
+	// Write-only pin which issues a reconnect event
+	class InputPinReconnect : public spcore::CInputPinWriteOnly<CTypeAny, WiimotesConfig> {
+	public:
+		InputPinReconnect (WiimotesConfig & component) : CInputPinWriteOnly<CTypeAny, WiimotesConfig>("reconnect", component) {}
+		virtual int DoSend(const CTypeAny &) {
+			WiiuseThreadController::getInstance()->Reconnect();
+			return 0;
+		}
+	};
+
+	// Write-only pin which requests an status notification
+	class InputPinReqStatus : public spcore::CInputPinWriteOnly<CTypeAny, WiimotesConfig> {
+	public:
+		InputPinReqStatus (WiimotesConfig & component) : CInputPinWriteOnly<CTypeAny, WiimotesConfig>("req_status", component) {}
+		virtual int DoSend(const CTypeAny &) {
+			WiiuseThreadController::getInstance()->ReqStatus();
+			return 0;
+		}
+	};
+
+private:
+	SmartPtr<spcore::IOutputPin> m_oPinStatus;
+	SmartPtr<CTypeWiimotesStatus> m_status;
+};
+
+// WiimotesConfig component factory
+typedef ComponentFactory<WiimotesConfig> WiimotesConfigFactory;
+
+
+/* *****************************************************************************
+	wiimotes_input component
+
+		Provides events from diffent Wii remote devices. Currently supports:
+		classic Wii remote, nunchuck, motion plus and balance board
+
+	Input pins:
+	
+	Ouput pins:
+		accelerometers (wiimotes_accelerometers)
+			Main wiimote accelerometers
+			
+		nunchuck_accelerometers (wiimotes_accelerometers)
+			Nunchuck accelerometers
+
+		buttons (wiimotes_buttons)
+			Button events including wiimote, nunchuck and balance board
+
+		balance_board (wiimotes_balance_board)
+			Balance board data
+
+		motion_plus (wiimotes_motion_plus)
+			Motion plus speed data
+
+	Command line:
+		// TODO
+		[- r <val> ] (= 1)	reduction (integer)
+			Reduction. Wii remotes send events at approximately 95Hz which
+			is too much for most applications. So this parameters allows to
+			reduce the cadence of events to a half, a third, etc. Reduction
+			does not have effect on button events.
+		// TODO
+***************************************************************************** */
+class WiimotesInput : public spcore::CComponentAdapter, public WiimoteListener {
+public:
+	// TODO: process commandline parameters to:
+	//	- reduce fps
+	//  - choose which wiimote will be used (numer and/or type)
+	WiimotesInput(const char * name, int argc, const char * argv[])
+	: CComponentAdapter(name, argc, argv)
+	{
+		// wiimote accelerometers
+		m_oPinWiimoteAcc= CTypeWiimotesAccelerometer::CreateOutputPin("accelerometers");
+		if (m_oPinWiimoteAcc.get()== NULL || RegisterOutputPin (*m_oPinWiimoteAcc))
+			// Output pin creation failed. Shouldn't happen but...
+			throw std::runtime_error("wiimotes_input. output pin accelerometers creation/registration failed.");
+		m_wiimoteAcc= CTypeWiimotesAccelerometer::CreateInstance();
+		if (m_wiimoteAcc.get()== NULL)
+			throw std::runtime_error("wiimotes_input. accelerometers instance creation failed.");
+
+		// nunchuck accelerometers
+		m_oPinNunchuckAcc= CTypeWiimotesAccelerometer::CreateOutputPin("nunchuck_accelerometers");
+		if (m_oPinNunchuckAcc.get()== NULL || RegisterOutputPin (*m_oPinNunchuckAcc))
+			// Output pin creation failed. Shouldn't happen but...
+			throw std::runtime_error("wiimotes_input. output pin nunchuck creation/registration failed.");
+		m_nunchuckAcc= CTypeWiimotesAccelerometer::CreateInstance();
+		if (m_nunchuckAcc.get()== NULL)
+			throw std::runtime_error("wiimotes_input. nunchuck instance creation failed.");
+
+		// buttons
+		m_oPinButtons= CTypeWiimotesButtons::CreateOutputPin("buttons");
+		if (m_oPinButtons.get()== NULL || RegisterOutputPin (*m_oPinButtons))
+			// Output pin creation failed. Shouldn't happen but...
+			throw std::runtime_error("wiimotes_input. output pin buttons creation/registration failed.");
+		m_buttons= CTypeWiimotesButtons::CreateInstance();
+		if (m_buttons.get()== NULL)
+			throw std::runtime_error("wiimotes_input. buttons instance creation failed.");
+
+		// balance board
+		m_oPinBalanceBoard= CTypeWiimotesBalanceBoard::CreateOutputPin("balance_board");
+		if (m_oPinBalanceBoard.get()== NULL || RegisterOutputPin (*m_oPinBalanceBoard))
+			// Output pin creation failed. Shouldn't happen but...
+			throw std::runtime_error("wiimotes_input. output pin balance board creation/registration failed.");
+		m_balanceBoard= CTypeWiimotesBalanceBoard::CreateInstance();
+		if (m_balanceBoard.get()== NULL)
+			throw std::runtime_error("wiimotes_input. balance board instance creation failed.");
+
+		// motion plus
+		m_oPinMotionPlus= CTypeWiimotesMotionPlus::CreateOutputPin("motion_plus");
+		if (m_oPinMotionPlus.get()== NULL || RegisterOutputPin (*m_oPinMotionPlus))
+			// Output pin creation failed. Shouldn't happen but...
+			throw std::runtime_error("wiimotes_input. output pin motion plus creation/registration failed.");
+		m_motionPlus= CTypeWiimotesMotionPlus::CreateInstance();
+		if (m_motionPlus.get()== NULL)
+			throw std::runtime_error("wiimotes_input. motion plus instance creation failed.");
+	}
+
+	static const char* getTypeName() { return "wiimotes_input"; };
+	virtual const char* GetTypeName() const { return WiimotesInput::getTypeName(); };
+
+	virtual bool ProvidesExecThread() const { return true; }
+
+	virtual int DoStart() {
+		unsigned int flags= 0, consumers= 0;
+
+		if (m_oPinWiimoteAcc->GetNumComsumers() > 0) {
+			flags|= WiiuseThread::ACC;
+			++consumers;
+		}
+
+		if (m_oPinNunchuckAcc->GetNumComsumers() > 0) {
+			flags|= WiiuseThread::NUNCHUCK;
+			++consumers;
+		}
+
+		if (m_oPinButtons->GetNumComsumers() > 0) ++consumers;
+
+		if (m_oPinBalanceBoard->GetNumComsumers() > 0) ++consumers;
+
+		if (m_oPinMotionPlus->GetNumComsumers() > 0) {
+			flags|= WiiuseThread::MOTION_PLUS;
+			++consumers;
+		}
+
+		if (consumers) {
+			// TODO: currently only takes into account the first wiimote
+			WiiuseThreadController::getInstance()->RegisterListener
+				(*this, static_cast<WiiuseThread::DesiredFeatures>(flags), 0);
+		}
+		return 0;
+	}
+
+	virtual void DoStop() {
+		WiiuseThreadController::getInstance()->UnregisterListener(*this);
+	}
+
+	virtual void StatusNotification (const CTypeWiimotesStatus &) {
+		// Do nothing
+	}
+	virtual void WiimoteNotification (wiimote *wm) {
+		//
+		// Wiimote accelerometers
+		//
+		if (m_oPinWiimoteAcc->GetNumComsumers() && WIIUSE_USING_ACC(wm)) {
+			CTypeWiimotesAccelerometer * result= m_wiimoteAcc.get();
+			result->SetForceX (wm->gforce.x);
+			result->SetForceY (wm->gforce.y);
+			result->SetForceZ (wm->gforce.z);
+			result->SetPitch (wm->orient.pitch);
+			result->SetRoll (wm->orient.roll);
+
+			m_oPinWiimoteAcc->Send (m_wiimoteAcc);
+		}
+
+		//
+		// Nunchuck accelerometers
+		//
+		if (wm->exp.type == EXP_NUNCHUK && m_oPinNunchuckAcc->GetNumComsumers()) {
+			CTypeWiimotesAccelerometer * result= m_nunchuckAcc.get();
+			result->SetForceX (wm->exp.nunchuk.gforce.x);
+			result->SetForceY (wm->exp.nunchuk.gforce.y);
+			result->SetForceZ (wm->exp.nunchuk.gforce.z);
+			result->SetPitch (wm->exp.nunchuk.orient.pitch);
+			result->SetRoll (wm->exp.nunchuk.orient.roll);
+
+			m_oPinNunchuckAcc->Send(m_nunchuckAcc);
+		}
+
+		//
+		// Buttons
+		//
+		if (m_oPinButtons->GetNumComsumers()) {
+			bool buttons_changed= false;
+
+			if ((wm->btns & 0x1F9F) != m_buttons->GetWiimoteButtons()) {
+				m_buttons->SetWiimoteButtons(wm->btns & 0x1F9F);
+				buttons_changed= true;
+			}
+
+			// Check if nunchuck button state changed
+			if (wm->exp.type == EXP_NUNCHUK) {
+				if ((wm->exp.nunchuk.btns & NUNCHUK_BUTTON_ALL) != m_buttons->GetNunchuckButtons()) {
+					m_buttons->SetNunchuckButtons(wm->exp.nunchuk.btns & NUNCHUK_BUTTON_ALL);
+					buttons_changed= true;
+				}
+			}
+			else if (m_buttons->GetNunchuckButtons()) {
+				m_buttons->SetNunchuckButtons(0);
+				buttons_changed= true;
+			}
+
+			// Notify buttons
+			if (buttons_changed) m_oPinButtons->Send(m_buttons);
+		}
+
+		//
+		// Balance board
+		//
+		if (wm->exp.type == EXP_BALANCE_BOARD && m_oPinBalanceBoard->GetNumComsumers()) {
+			CTypeWiimotesBalanceBoard * result= m_balanceBoard.get();
+
+			result->SetTopLeft (wm->exp.bb.tl);
+			result->SetTopRight (wm->exp.bb.tr);
+			result->SetBottomRight (wm->exp.bb.br);
+			result->SetBottomLeft (wm->exp.bb.bl);
+
+			m_oPinBalanceBoard->Send (m_balanceBoard);
+		}
+
+		//
+		// Motion plus
+		//
+		if (wm->exp.type == EXP_MOTION_PLUS && m_oPinMotionPlus->GetNumComsumers()) {
+			CTypeWiimotesMotionPlus * result= m_motionPlus.get();
+
+			result->SetXSpeed (wm->exp.mp.sx);
+			result->SetYSpeed (wm->exp.mp.sy);
+			result->SetZSpeed (wm->exp.mp.sz);
+
+			m_oPinMotionPlus->Send (m_motionPlus);
+		}
+	}
+
+private:
+	virtual ~WiimotesInput() {}
+
+private:
+	unsigned int m_reduction;
+	unsigned int m_storedCount;
+
+	SmartPtr<IOutputPin> m_oPinWiimoteAcc;
+	SmartPtr<CTypeWiimotesAccelerometer> m_wiimoteAcc;
+
+	SmartPtr<IOutputPin> m_oPinNunchuckAcc;
+	SmartPtr<CTypeWiimotesAccelerometer> m_nunchuckAcc;
+
+	SmartPtr<IOutputPin> m_oPinButtons;
+	SmartPtr<CTypeWiimotesButtons> m_buttons;
+
+	SmartPtr<IOutputPin> m_oPinBalanceBoard;
+	SmartPtr<CTypeWiimotesBalanceBoard> m_balanceBoard;
+
+	SmartPtr<IOutputPin> m_oPinMotionPlus;
+	SmartPtr<CTypeWiimotesMotionPlus> m_motionPlus;
+};
+
+// WiimotesConfig component factory
+typedef ComponentFactory<WiimotesInput> WiimotesInputFactory;
+
+
+/* *****************************************************************************
+	wii_mp_to_composite
+	
+		Converts an object wiimotes_motion_plus into a composite of 
+		three float which contains the speed values for x, y and z
+
+	Input pins:
+		in (wiimotes_motion_plus)
+
+	Ouput pins:
+		out (any) containing three float with the information of each axis
+***************************************************************************** */
+class WiiMpToCompo : public CComponentAdapter {
+public:
+	static const char* getTypeName() { return "wii_mp_to_composite"; }
+	virtual const char* GetTypeName() const { return WiiMpToCompo::getTypeName(); }
+    WiiMpToCompo(const char * name, int argc, const char * argv[]) 
+	: CComponentAdapter(name, argc, argv) {
+		// Input pins
+  		if (RegisterInputPin(*SmartPtr<IInputPin>(new InputPinMotionPlus("in", *this), false))!= 0)
+			throw std::runtime_error("error creating input pin");
+		// Output pin
+		m_oPin= CTypeComposite::CreateOutputPin("out");
+		if (RegisterOutputPin(*m_oPin)!= 0)	throw std::runtime_error("error registering output pin");
+		// Result instance
+		m_result= CTypeComposite::CreateInstance();
+		m_x= CTypeFloat::CreateInstance();
+		m_y= CTypeFloat::CreateInstance();
+		m_z= CTypeFloat::CreateInstance();
+		m_result->AddChild(m_x);
+		m_result->AddChild(m_y);
+		m_result->AddChild(m_z);
+	}
+
+	int OnValue (const CTypeWiimotesMotionPlus & message) {
+		m_x->setValue(message.GetXSpeed());
+		m_y->setValue(message.GetYSpeed());
+		m_z->setValue(message.GetZSpeed());
+		return m_oPin->Send(m_result);
+	}
+
+private:
+	virtual ~WiiMpToCompo() {}
+
+	class InputPinMotionPlus : public CInputPinWriteOnly<CTypeWiimotesMotionPlus, WiiMpToCompo> {
+	public:
+		InputPinMotionPlus (const char * name, WiiMpToCompo & component)
+		: CInputPinWriteOnly<CTypeWiimotesMotionPlus, WiiMpToCompo>(name, component) {}
+
+		virtual int DoSend(const CTypeWiimotesMotionPlus & message) {
+			return this->m_component->OnValue (message);			
+		}
+	};
+	
+	SmartPtr<IOutputPin> m_oPin;
+	SmartPtr<CTypeComposite> m_result;
+	SmartPtr<CTypeFloat> m_x, m_y, m_z;
+
+};
+
+typedef ComponentFactory<WiiMpToCompo> WiiMpToCompoFactory;
+
+/* *****************************************************************************
+	wii_bb_to_composite
+	
+		Converts an object wiimotes_balance_board into a composite of 
+		two float which contains the centre of masses
+
+	Input pins:
+		in (wiimotes_balance_board)
+
+	Ouput pins:
+		out (any) containing two float with the information of each axis
+***************************************************************************** */
+class WiiBbToCompo : public CComponentAdapter {
+public:
+	static const char* getTypeName() { return "wii_bb_to_composite"; }
+	virtual const char* GetTypeName() const { return WiiBbToCompo::getTypeName(); }
+    WiiBbToCompo(const char * name, int argc, const char * argv[]) 
+	: CComponentAdapter(name, argc, argv) {
+		// Input pins
+  		if (RegisterInputPin(*SmartPtr<IInputPin>(new InputPinMotionPlus("in", *this), false))!= 0)
+			throw std::runtime_error("error creating input pin");
+		// Output pin
+		m_oPin= CTypeComposite::CreateOutputPin("out");
+		if (RegisterOutputPin(*m_oPin)!= 0)	throw std::runtime_error("error registering output pin");
+		// Result instance
+		m_result= CTypeComposite::CreateInstance();
+		m_x= CTypeFloat::CreateInstance();
+		m_y= CTypeFloat::CreateInstance();
+		
+		m_result->AddChild(m_x);
+		m_result->AddChild(m_y);
+	}
+
+	int OnValue (const CTypeWiimotesBalanceBoard & message) {
+		m_x->setValue(message.GetCenterOfMassX());
+		m_y->setValue(message.GetCenterOfMassY());
+
+		return m_oPin->Send(m_result);
+	}
+
+private:
+	virtual ~WiiBbToCompo() {}
+
+	class InputPinMotionPlus : public CInputPinWriteOnly<CTypeWiimotesBalanceBoard, WiiBbToCompo> {
+	public:
+		InputPinMotionPlus (const char * name, WiiBbToCompo & component)
+		: CInputPinWriteOnly<CTypeWiimotesBalanceBoard, WiiBbToCompo>(name, component) {}
+
+		virtual int DoSend(const CTypeWiimotesBalanceBoard & message) {
+			return this->m_component->OnValue (message);			
+		}
+	};
+	
+	SmartPtr<IOutputPin> m_oPin;
+	SmartPtr<CTypeComposite> m_result;
+	SmartPtr<CTypeFloat> m_x, m_y;
+};
+
+typedef ComponentFactory<WiiBbToCompo> WiiBbToCompoFactory;
+
+
+/* *****************************************************************************
+	wii_acc_estimate
+	
+		
+	Input pins:
+		in (wiimotes_accelerometers)
+
+	Ouput pins:
+		out (any) containing three float with the information of each axis
+***************************************************************************** */
+class WiiAccEstimate : public CComponentAdapter {
+public:
+	static const char* getTypeName() { return "wii_acc_estimate"; }
+	virtual const char* GetTypeName() const { return WiiAccEstimate::getTypeName(); }
+    WiiAccEstimate(const char * name, int argc, const char * argv[]) 
+	: CComponentAdapter(name, argc, argv) 
+	, m_lastX(0)
+	, m_lastY(0)
+	, m_lastZ(0)
+	, m_error(0.08f) {
+		// Input pins
+  		if (RegisterInputPin(*SmartPtr<IInputPin>(new InputPinAcc("in", *this), false))!= 0)
+			throw std::runtime_error("error creating input pin");
+		// Output pin
+		m_oPin= CTypeComposite::CreateOutputPin("out");
+		if (RegisterOutputPin(*m_oPin)!= 0)	throw std::runtime_error("error registering output pin");
+		// Result instance
+		m_result= CTypeComposite::CreateInstance();
+		m_x= CTypeFloat::CreateInstance();
+		m_y= CTypeFloat::CreateInstance();
+		m_z= CTypeFloat::CreateInstance();
+		m_result->AddChild(m_x);
+		m_result->AddChild(m_y);
+		m_result->AddChild(m_z);
+	}
+
+	int OnValue (const CTypeWiimotesAccelerometer & message) {
+		float x= message.GetForceX();
+		float y= message.GetForceY();
+		float z= message.GetForceZ();
+
+		if (fabsf(x - m_lastX)> fabs(m_error * x))
+			m_x->setValue(x);
+		else
+			m_x->setValue(0);
+
+		if (fabsf(y - m_lastY)> fabs(m_error * y))
+			m_y->setValue(y);
+		else
+			m_y->setValue(0);
+
+		if (fabsf(z - m_lastZ)> fabs(m_error * z))
+			m_z->setValue(z);
+		else
+			m_z->setValue(0);
+
+		m_lastX= x;
+		m_lastY= y;
+		m_lastZ= z;
+
+		return m_oPin->Send(m_result);
+	}
+
+private:
+	virtual ~WiiAccEstimate() {}
+
+	class InputPinAcc : public CInputPinWriteOnly<CTypeWiimotesAccelerometer,WiiAccEstimate> {
+	public:
+		InputPinAcc (const char * name, WiiAccEstimate & component)
+		: CInputPinWriteOnly<CTypeWiimotesAccelerometer, WiiAccEstimate>(name, component) {}
+
+		virtual int DoSend(const CTypeWiimotesAccelerometer & message) {
+			return this->m_component->OnValue (message);			
+		}
+	};
+	
+	SmartPtr<IOutputPin> m_oPin;
+	SmartPtr<CTypeComposite> m_result;
+	SmartPtr<CTypeFloat> m_x, m_y, m_z;
+	float m_lastX, m_lastY, m_lastZ;
+	float m_error;
+};
+
+typedef ComponentFactory<WiiAccEstimate> WiiAccEstimateFactory;
+
+
+/* *****************************************************************************
+	wiimote_config_gui component
+
+	Component which provides an wxPanel to interactively configure wiimotes
+***************************************************************************** */
+class WiimotesConfigGUI : public spcore::CComponentAdapter {
+public:
+
+	WiimotesConfigGUI(const char * name, int argc, const char * argv[]) 
+	: CComponentAdapter(name, argc, argv) { }
+
+	static const char* getTypeName() { return "wiimotes_config_gui"; };
+	virtual const char* GetTypeName() const { return WiimotesConfigGUI::getTypeName(); };
+
+	virtual wxWindow* GetGUI(wxWindow * parent) {
+		wxWindow* w= new WiimotesConfiguration(parent);
+		w->SetName(_("Wiimotes Configuration"));
+		return w;
+	}
+
+private:
+	virtual ~WiimotesConfigGUI() { }
+};
+
+// WiimotesConfigGUI component factory
+typedef ComponentFactory<WiimotesConfigGUI> WiimotesConfigGUIFactory;
+
+/* ******************************************************************************
+	type factories
+****************************************************************************** */
+typedef spcore::SimpleTypeFactory<CTypeWiimotesStatus> CTypeWiimotesStatusFactory;
+typedef spcore::SimpleTypeFactory<CTypeWiimotesAccelerometer> CTypeWiimotesAccelerometerFactory;
+typedef spcore::SimpleTypeFactory<CTypeWiimotesButtons> CTypeWiimotesButtonsFactory;
+typedef spcore::SimpleTypeFactory<CTypeWiimotesBalanceBoard> CTypeWiimotesBalanceBoardFactory;
+typedef spcore::SimpleTypeFactory<CTypeWiimotesMotionPlus> CTypeWiimotesMotionPlusFactory;
+
+/* ******************************************************************************
+	wii  module
+****************************************************************************** */
+class WiiMotesModule : public CModuleAdapter {
+public:
+	WiiMotesModule() {
+		//
+		// types
+		//
+		RegisterTypeFactory(SmartPtr<spcore::ITypeFactory>(new CTypeWiimotesStatusFactory(), false));
+		RegisterTypeFactory(SmartPtr<spcore::ITypeFactory>(new CTypeWiimotesAccelerometerFactory(), false));
+		RegisterTypeFactory(SmartPtr<spcore::ITypeFactory>(new CTypeWiimotesButtonsFactory(), false));
+		RegisterTypeFactory(SmartPtr<spcore::ITypeFactory>(new CTypeWiimotesBalanceBoardFactory(), false));
+		RegisterTypeFactory(SmartPtr<spcore::ITypeFactory>(new CTypeWiimotesMotionPlusFactory(), false));
+
+		//
+		// components
+		//
+		RegisterComponentFactory(SmartPtr<spcore::IComponentFactory>(new WiimotesConfigFactory(), false));
+		RegisterComponentFactory(SmartPtr<spcore::IComponentFactory>(new WiimotesInputFactory(), false));
+		RegisterComponentFactory(SmartPtr<spcore::IComponentFactory>(new WiimotesConfigGUIFactory(), false));
+
+		RegisterComponentFactory(SmartPtr<spcore::IComponentFactory>(new WiiMpToCompoFactory(), false));
+		RegisterComponentFactory(SmartPtr<spcore::IComponentFactory>(new WiiBbToCompoFactory(), false));
+		RegisterComponentFactory(SmartPtr<spcore::IComponentFactory>(new WiiAccEstimateFactory(), false));
+	}
+
+	~WiiMotesModule() {
+		WiiuseThreadController::destroyInstance();
+	}
+
+	virtual const char * GetName() const { return "mod_wiimotes"; }
+};
+
+static spcore::IModule* g_module= NULL;
+SPEXPORT_FUNCTION spcore::IModule* module_create_instance()
+{
+	if (g_module== NULL) g_module= new WiiMotesModule();
+	return g_module;
+}
+
+};
diff --git a/src/mod_wiimotes/mod_wiimotes.h b/src/mod_wiimotes/mod_wiimotes.h
new file mode 100755
index 0000000..e2f4646
--- /dev/null
+++ b/src/mod_wiimotes/mod_wiimotes.h
@@ -0,0 +1,76 @@
+/////////////////////////////////////////////////////////////////////////////
+// File:        mod_wiimotes.h
+// Author:      Cesar Mauri Loba (cesar at crea-si dot com)
+// Copyright:   (C) 2011 Cesar Mauri Loba - CREA Software Systems
+// 
+//  This program is free software: you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation, either version 3 of the License, or
+//  (at your option) any later version.
+//
+//  This program is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+/////////////////////////////////////////////////////////////////////////////
+#ifndef MOD_WIIMOTES_H
+#define MOD_WIIMOTES_H
+
+#include "mod_wiimotes/wiimotes_types.h"
+// Visual C++ complains about the structs defined in wiiuse.h
+// so we disable the meaningless warnings
+#if defined(_MSC_VER)
+#pragma warning (disable:4510)
+#pragma warning (disable:4512)
+#pragma warning (disable:4610)
+#define snprintf _snprintf
+#endif
+#include "wiiuse/include/wiiuse.h"
+#include <boost/thread/thread.hpp>
+
+using namespace spcore;
+
+namespace mod_wiimotes {
+
+// wiimote listener
+class WiimoteListener
+{
+public:
+	virtual void StatusNotification (const CTypeWiimotesStatus &)= 0;
+	virtual void WiimoteNotification (wiimote *)= 0;
+};
+
+/*
+	Thread controller
+
+	This is a singleton class which starts/stops the wiimotes thread and forwards requests
+*/
+class WiiuseThread;
+
+class WiiuseThreadController {
+public:
+	static WiiuseThreadController * getInstance();
+	static void destroyInstance();
+
+
+	void RegisterListener (WiimoteListener& wl, unsigned int df, unsigned int filter);
+	void UnregisterListener (WiimoteListener& wl);
+
+	void Reconnect();
+	void ReqStatus();
+
+private:
+	WiiuseThreadController();
+	virtual ~WiiuseThreadController();
+
+	WiiuseThread* m_worker;
+	boost::thread* m_thread;
+	static WiiuseThreadController *g_instance;
+};
+
+};
+
+#endif
\ No newline at end of file
diff --git a/src/mod_wiimotes/mod_wiimotes.pjd b/src/mod_wiimotes/mod_wiimotes.pjd
new file mode 100755
index 0000000..559e1ea
--- /dev/null
+++ b/src/mod_wiimotes/mod_wiimotes.pjd
@@ -0,0 +1,1329 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<anthemion-project version="1.0.0.0" xmlns="http://www.anthemion.co.uk">
+  <header>
+    <long name="name_counter">0</long>
+    <string name="html_path">""</string>
+    <string name="title">""</string>
+    <string name="author">""</string>
+    <string name="description">""</string>
+    <string name="xrc_filename">""</string>
+    <long name="image_mode">0</long>
+    <bool name="inline_images">0</bool>
+    <bool name="generate_cpp_for_xrc">0</bool>
+    <long name="working_mode">1</long>
+    <bool name="use_help_text_for_tooltips">1</bool>
+    <bool name="translate_strings">1</bool>
+    <bool name="make_unicode_strings">1</bool>
+    <bool name="extract_strings">0</bool>
+    <string name="user_name">"César Mauri Loba"</string>
+    <string name="copyright_string">"(C) 2009 Cesar Mauri from CREA Sistemes Informatics"</string>
+    <string name="resource_prefix">""</string>
+    <bool name="use_two_step_construction">1</bool>
+    <bool name="use_enums">0</bool>
+    <bool name="generate_for_xrced">0</bool>
+    <bool name="generate_virtual_eventhandlers">0</bool>
+    <string name="current_platform">"<All platforms>"</string>
+    <string name="target_wx_version">"2.8.7"</string>
+    <string name="app_kind">"Standard"</string>
+    <string name="cpp_header_comment">"/////////////////////////////////////////////////////////////////////////////
+// Name:        %HEADER-FILENAME%
+// Purpose:     
+// Author:      %AUTHOR%
+// Modified by: 
+// Created:     %DATE%
+// RCS-ID:      
+// Copyright:   %COPYRIGHT%
+// Licence:     
+/////////////////////////////////////////////////////////////////////////////
+
+"</string>
+    <string name="cpp_implementation_comment">"/////////////////////////////////////////////////////////////////////////////
+// Name:        %SOURCE-FILENAME%
+// Purpose:     
+// Author:      %AUTHOR%
+// Modified by: 
+// Created:     %DATE%
+// RCS-ID:      
+// Copyright:   %COPYRIGHT%
+// Licence:     
+/////////////////////////////////////////////////////////////////////////////
+
+"</string>
+    <string name="cpp_symbols_file_comment">"/////////////////////////////////////////////////////////////////////////////
+// Name:        %SYMBOLS-FILENAME%
+// Purpose:     Symbols file
+// Author:      %AUTHOR%
+// Modified by: 
+// Created:     %DATE%
+// RCS-ID:      
+// Copyright:   %COPYRIGHT%
+// Licence:     
+/////////////////////////////////////////////////////////////////////////////
+
+"</string>
+    <string name="cpp_header_preamble">""</string>
+    <string name="cpp_implementation_preamble">"// For compilers that support precompilation, includes "wx/wx.h".
+#include "wx/wxprec.h"
+
+#ifdef __BORLANDC__
+#pragma hdrstop
+#endif
+
+#ifndef WX_PRECOMP
+#include "wx/wx.h"
+#endif
+
+"</string>
+    <string name="cpp_function_declaration_comment">"	/// %BODY%
+"</string>
+    <string name="cpp_function_implementation_comment">"
+/*!
+ * %BODY%
+ */
+
+"</string>
+    <string name="resource_file_header">"app_resources.h"</string>
+    <string name="resource_file_implementation">"app_resources.cpp"</string>
+    <string name="resource_class_name">"AppResources"</string>
+    <string name="app_file_header">"app.h"</string>
+    <string name="app_file_implementation">"app.cpp"</string>
+    <string name="app_class_name">"Application"</string>
+    <bool name="generate_app_class">0</bool>
+    <string name="external_symbol_filenames">""</string>
+    <string name="configuration">"<None>"</string>
+    <string name="source_encoding">"iso-8859-1"</string>
+    <string name="xrc_encoding">"utf-8"</string>
+    <string name="project_encoding">"utf-8"</string>
+    <string name="resource_archive">""</string>
+    <long name="text_file_type">0</long>
+    <bool name="use_tabs">0</bool>
+    <long name="indent_size">4</long>
+    <string name="whitespace_after_return_type">" "</string>
+    <string name="resource_xrc_cpp">""</string>
+    <bool name="use_resource_archive">0</bool>
+    <bool name="use_generated_xrc_cpp">0</bool>
+    <bool name="always_generate_xrc">1</bool>
+    <bool name="use_id_name_for_name">0</bool>
+    <bool name="archive_xrc_files">1</bool>
+    <bool name="archive_image_files">1</bool>
+    <bool name="archive_all_image_files">0</bool>
+    <bool name="xrc_retain_relative_paths">1</bool>
+    <bool name="xrc_generate_id_tags">0</bool>
+    <bool name="xrc_use_name_property">0</bool>
+  </header>
+  <data>
+    <document>
+      <string name="title">""</string>
+      <string name="type">"data-document"</string>
+      <string name="filename">""</string>
+      <string name="icon-name">""</string>
+      <long name="is-transient">0</long>
+      <long name="owns-file">1</long>
+      <long name="title-mode">0</long>
+      <long name="locked">0</long>
+      <document>
+        <string name="title">"Configurations"</string>
+        <string name="type">"config-data-document"</string>
+        <string name="filename">""</string>
+        <string name="icon-name">""</string>
+        <long name="is-transient">0</long>
+        <long name="owns-file">1</long>
+        <long name="title-mode">0</long>
+        <long name="locked">0</long>
+        <string name="template-name">""</string>
+        <bool name="dirty">1</bool>
+        <long name="makefile-last-written">-8519680</long>
+        <string name="Compiler name">""</string>
+        <string name="Build mode">"Debug"</string>
+        <string name="Unicode mode">"ANSI"</string>
+        <string name="Shared mode">"Static"</string>
+        <string name="Modularity">"Modular"</string>
+        <string name="GUI mode">"GUI"</string>
+        <string name="Toolkit">"wxMSW"</string>
+        <string name="Processor type">"Default"</string>
+        <string name="Runtime linking">"Dynamic"</string>
+        <string name="Use exceptions">"Yes"</string>
+        <string name="Use ODBC">"No"</string>
+        <string name="Use XRC">"Yes"</string>
+        <string name="Use OpenGL">"No"</string>
+        <string name="Use wxMediaCtrl">"No"</string>
+        <string name="Use wxRichTextCtrl">"Yes"</string>
+        <string name="Use wxHTML">"Yes"</string>
+        <string name="Use wxPropertyGrid">"Yes"</string>
+        <string name="Use wxAUI">"Yes"</string>
+        <string name="Use wxSTC">"Yes"</string>
+        <string name="Use wxRibbonControl">"Yes"</string>
+        <string name="Executable name">"%EXECUTABLE%"</string>
+        <string name="Program arguments">""</string>
+        <string name="Working path">"%AUTO%"</string>
+        <string name="Output path">"%AUTO%"</string>
+        <string name="Objects path">"%AUTO%"</string>
+        <string name="Project makefile">"%AUTO%"</string>
+        <string name="wxWidgets version">"%WXVERSION%"</string>
+        <string name="wxWidgets makefile">"%AUTO%"</string>
+        <string name="wxWidgets location">"%AUTO%"</string>
+        <string name="wxWidgets build path">"%AUTO%"</string>
+        <string name="wxWidgets build command">"%AUTO%"</string>
+        <string name="wxWidgets clean command">"%AUTO%"</string>
+        <string name="CFG">""</string>
+        <string name="Compiler location">"%AUTO%"</string>
+        <string name="Compiler bin path">"%AUTO%"</string>
+        <string name="Compiler include path">"%AUTO%"</string>
+        <string name="Compiler lib path">"%AUTO%"</string>
+        <string name="PATH variable">"%AUTO%"</string>
+        <string name="C++ command">"%AUTO%"</string>
+        <string name="C command">"%AUTO%"</string>
+        <string name="Linker command">"%AUTO%"</string>
+        <string name="Resource compiler">"%AUTO%"</string>
+        <string name="Make command">"%AUTO%"</string>
+        <string name="Preprocessor flags">"%AUTO%"</string>
+        <string name="Optimizations">"%AUTO%"</string>
+        <string name="Warnings">"%AUTO%"</string>
+        <string name="Debug flags">"%AUTO%"</string>
+        <string name="Extra compile flags">"%AUTO%"</string>
+        <string name="Libraries">"%AUTO%"</string>
+        <string name="Library path">"%AUTO%"</string>
+        <string name="Linker flags">"%AUTO%"</string>
+        <string name="Include path">"%AUTO%"</string>
+        <string name="Resource flags">"%AUTO%"</string>
+        <string name="Resource path">"%AUTO%"</string>
+        <bool name="Suppress source rules">0</bool>
+        <bool name="Enable makefile generation">1</bool>
+      </document>
+    </document>
+  </data>
+
+  <documents>
+    <document>
+      <string name="title">"Projects"</string>
+      <string name="type">"root-document"</string>
+      <string name="filename">""</string>
+      <string name="icon-name">"project"</string>
+      <long name="is-transient">1</long>
+      <long name="owns-file">1</long>
+      <long name="title-mode">0</long>
+      <long name="locked">1</long>
+      <document>
+        <string name="title">"Windows"</string>
+        <string name="type">"html-document"</string>
+        <string name="filename">""</string>
+        <string name="icon-name">"dialogsfolder"</string>
+        <long name="is-transient">1</long>
+        <long name="owns-file">1</long>
+        <long name="title-mode">0</long>
+        <long name="locked">1</long>
+        <document>
+          <string name="title">"Wiimotes Configuration"</string>
+          <string name="type">"dialog-document"</string>
+          <string name="filename">""</string>
+          <string name="icon-name">"dialog"</string>
+          <long name="is-transient">0</long>
+          <long name="owns-file">1</long>
+          <long name="title-mode">0</long>
+          <long name="locked">0</long>
+          <string name="proxy-type">"wbDialogProxy"</string>
+          <long name="base-id">10000</long>
+          <bool name="use-id-prefix">0</bool>
+          <string name="id-prefix">""</string>
+          <bool name="use-id-suffix">0</bool>
+          <string name="id-suffix">""</string>
+          <string name="app-kind">"Standard"</string>
+          <long name="use-xrc">0</long>
+          <long name="working-mode">0</long>
+          <string name="proxy-Id name">"ID_WIIMOTESCONFIGURATION"</string>
+          <long name="proxy-Id value">10060</long>
+          <string name="proxy-Class">"WiimotesConfiguration"</string>
+          <string name="proxy-Base class">"wxPanel"</string>
+          <string name="proxy-Window kind">"wxPanel"</string>
+          <string name="proxy-Implementation filename">"wwiimotesconfiguration.cpp"</string>
+          <string name="proxy-Header filename">"wwiimotesconfiguration.h"</string>
+          <string name="proxy-XRC filename">""</string>
+          <string name="proxy-Title">"Wiimotes Configuration"</string>
+          <bool name="proxy-Centre">1</bool>
+          <string name="proxy-Icon">""</string>
+          <bool name="proxy-Dialog units">0</bool>
+          <string name="proxy-Help text">""</string>
+          <string name="proxy-Tooltip text">""</string>
+          <string name="proxy-Background colour">""</string>
+          <string name="proxy-Foreground colour">""</string>
+          <string name="proxy-Font">""</string>
+          <bool name="proxy-Hidden">0</bool>
+          <bool name="proxy-Enabled">1</bool>
+          <string name="proxy-Platform">"<Any platform>"</string>
+          <string name="proxy-Data source">""</string>
+          <string name="proxy-Data class name">""</string>
+          <string name="proxy-Data class implementation filename">""</string>
+          <string name="proxy-Data class header filename">""</string>
+          <string name="proxy-Data class manager window">""</string>
+          <string name="proxy-Texture">""</string>
+          <string name="proxy-Texture style">"Tiled"</string>
+          <bool name="proxy-wxDEFAULT_DIALOG_STYLE">0</bool>
+          <bool name="proxy-wxCAPTION">1</bool>
+          <bool name="proxy-wxRESIZE_BORDER">0</bool>
+          <bool name="proxy-wxSYSTEM_MENU">0</bool>
+          <bool name="proxy-wxSTAY_ON_TOP">0</bool>
+          <bool name="proxy-wxDIALOG_NO_PARENT">0</bool>
+          <bool name="proxy-wxCLOSE_BOX">0</bool>
+          <bool name="proxy-wxMAXIMIZE_BOX">0</bool>
+          <bool name="proxy-wxMINIMIZE_BOX">0</bool>
+          <bool name="proxy-wxDIALOG_MODAL">1</bool>
+          <bool name="proxy-wxNO_BORDER">0</bool>
+          <bool name="proxy-wxSIMPLE_BORDER">0</bool>
+          <bool name="proxy-wxDOUBLE_BORDER">0</bool>
+          <bool name="proxy-wxBORDER_THEME">0</bool>
+          <bool name="proxy-wxSUNKEN_BORDER">0</bool>
+          <bool name="proxy-wxRAISED_BORDER">0</bool>
+          <bool name="proxy-wxSTATIC_BORDER">0</bool>
+          <bool name="proxy-wxWANTS_CHARS">0</bool>
+          <bool name="proxy-wxNO_FULL_REPAINT_ON_RESIZE">0</bool>
+          <bool name="proxy-wxFULL_REPAINT_ON_RESIZE">0</bool>
+          <bool name="proxy-wxCLIP_CHILDREN">0</bool>
+          <bool name="proxy-wxTAB_TRAVERSAL">1</bool>
+          <bool name="proxy-wxWS_EX_VALIDATE_RECURSIVELY">0</bool>
+          <bool name="proxy-wxWS_EX_BLOCK_EVENTS">1</bool>
+          <bool name="proxy-wxWS_EX_TRANSIENT">0</bool>
+          <string name="proxy-Custom styles">""</string>
+          <bool name="proxy-wxDIALOG_EX_CONTEXTHELP">0</bool>
+          <bool name="proxy-Fit to content">1</bool>
+          <long name="proxy-X">-1</long>
+          <long name="proxy-Y">-1</long>
+          <long name="proxy-Width">-1</long>
+          <long name="proxy-Height">-1</long>
+          <bool name="proxy-AUI manager">0</bool>
+          <string name="proxy-Event sources">""</string>
+          <document>
+            <string name="title">"wxBoxSizer V"</string>
+            <string name="type">"dialog-control-document"</string>
+            <string name="filename">""</string>
+            <string name="icon-name">"sizer"</string>
+            <long name="is-transient">0</long>
+            <long name="owns-file">1</long>
+            <long name="title-mode">0</long>
+            <long name="locked">0</long>
+            <string name="proxy-type">"wbBoxSizerProxy"</string>
+            <string name="proxy-Orientation">"Vertical"</string>
+            <string name="proxy-Member variable name">""</string>
+            <bool name="proxy-wxSHAPED">0</bool>
+            <bool name="proxy-wxADJUST_MINSIZE">0</bool>
+            <bool name="proxy-wxFIXED_MINSIZE">0</bool>
+            <string name="proxy-Platform">"<Any platform>"</string>
+            <document>
+              <string name="title">"wxStaticBoxSizer H"</string>
+              <string name="type">"dialog-control-document"</string>
+              <string name="filename">""</string>
+              <string name="icon-name">"sizer"</string>
+              <long name="is-transient">0</long>
+              <long name="owns-file">1</long>
+              <long name="title-mode">0</long>
+              <long name="locked">0</long>
+              <string name="proxy-type">"wbStaticBoxSizerProxy"</string>
+              <string name="proxy-Id name">"wxID_ANY"</string>
+              <long name="proxy-Id value">-1</long>
+              <string name="proxy-Label">"Wiimote device 1"</string>
+              <string name="proxy-Member variable name">""</string>
+              <string name="proxy-Sizer member variable name">""</string>
+              <string name="proxy-Foreground colour">""</string>
+              <string name="proxy-Font">""</string>
+              <bool name="proxy-Hidden">0</bool>
+              <bool name="proxy-Enabled">1</bool>
+              <string name="proxy-Static box class">"wxStaticBox"</string>
+              <string name="proxy-Orientation">"Horizontal"</string>
+              <string name="proxy-AlignH">"Left"</string>
+              <string name="proxy-AlignV">"Centre"</string>
+              <long name="proxy-Stretch factor">0</long>
+              <long name="proxy-Border">5</long>
+              <bool name="proxy-wxLEFT">1</bool>
+              <bool name="proxy-wxRIGHT">1</bool>
+              <bool name="proxy-wxTOP">1</bool>
+              <bool name="proxy-wxBOTTOM">1</bool>
+              <bool name="proxy-wxSHAPED">0</bool>
+              <bool name="proxy-wxADJUST_MINSIZE">0</bool>
+              <bool name="proxy-wxFIXED_MINSIZE">0</bool>
+              <string name="proxy-Platform">"<Any platform>"</string>
+              <document>
+                <string name="title">"Wiimotesproperties: ID_WIIMOTESPROPERTIES1"</string>
+                <string name="type">"dialog-control-document"</string>
+                <string name="filename">""</string>
+                <string name="icon-name">"panel"</string>
+                <long name="is-transient">0</long>
+                <long name="owns-file">1</long>
+                <long name="title-mode">0</long>
+                <long name="locked">0</long>
+                <string name="proxy-type">"wbPanelProxy"</string>
+                <string name="proxy-Id name">"ID_WIIMOTESPROPERTIES1"</string>
+                <long name="proxy-Id value">10006</long>
+                <string name="proxy-Name">""</string>
+                <string name="proxy-Class">"Wiimotesproperties"</string>
+                <string name="proxy-Base class">"wxPanel"</string>
+                <bool name="proxy-External implementation">1</bool>
+                <bool name="proxy-Separate files">0</bool>
+                <string name="proxy-Implementation filename">""</string>
+                <string name="proxy-Header filename">""</string>
+                <string name="proxy-Member variable name">"m_panProperties_1"</string>
+                <string name="proxy-Help text">""</string>
+                <string name="proxy-Tooltip text">""</string>
+                <string name="proxy-Background colour">""</string>
+                <string name="proxy-Foreground colour">""</string>
+                <string name="proxy-Font">""</string>
+                <bool name="proxy-Hidden">0</bool>
+                <bool name="proxy-Enabled">1</bool>
+                <string name="proxy-Platform">"<Any platform>"</string>
+                <string name="proxy-Data source">""</string>
+                <string name="proxy-Data class name">""</string>
+                <string name="proxy-Data class implementation filename">""</string>
+                <string name="proxy-Data class header filename">""</string>
+                <string name="proxy-Data class manager window">""</string>
+                <string name="proxy-Texture">""</string>
+                <string name="proxy-Texture style">"Tiled"</string>
+                <bool name="proxy-wxNO_BORDER">0</bool>
+                <bool name="proxy-wxSIMPLE_BORDER">0</bool>
+                <bool name="proxy-wxDOUBLE_BORDER">0</bool>
+                <bool name="proxy-wxBORDER_THEME">0</bool>
+                <bool name="proxy-wxSUNKEN_BORDER">0</bool>
+                <bool name="proxy-wxRAISED_BORDER">0</bool>
+                <bool name="proxy-wxSTATIC_BORDER">0</bool>
+                <bool name="proxy-wxWANTS_CHARS">0</bool>
+                <bool name="proxy-wxNO_FULL_REPAINT_ON_RESIZE">0</bool>
+                <bool name="proxy-wxFULL_REPAINT_ON_RESIZE">0</bool>
+                <bool name="proxy-wxCLIP_CHILDREN">0</bool>
+                <bool name="proxy-wxHSCROLL">0</bool>
+                <bool name="proxy-wxVSCROLL">0</bool>
+                <bool name="proxy-wxTAB_TRAVERSAL">0</bool>
+                <bool name="proxy-wxALWAYS_SHOW_SB">0</bool>
+                <bool name="proxy-wxWS_EX_VALIDATE_RECURSIVELY">0</bool>
+                <bool name="proxy-wxWS_EX_BLOCK_EVENTS">0</bool>
+                <string name="proxy-Custom styles">""</string>
+                <bool name="proxy-Fit to content">1</bool>
+                <long name="proxy-X">-1</long>
+                <long name="proxy-Y">-1</long>
+                <long name="proxy-Width">-1</long>
+                <long name="proxy-Height">-1</long>
+                <string name="proxy-AlignH">"Centre"</string>
+                <string name="proxy-AlignV">"Centre"</string>
+                <long name="proxy-Stretch factor">0</long>
+                <long name="proxy-Border">5</long>
+                <bool name="proxy-wxLEFT">1</bool>
+                <bool name="proxy-wxRIGHT">1</bool>
+                <bool name="proxy-wxTOP">1</bool>
+                <bool name="proxy-wxBOTTOM">1</bool>
+                <bool name="proxy-wxSHAPED">0</bool>
+                <bool name="proxy-wxADJUST_MINSIZE">0</bool>
+                <bool name="proxy-wxFIXED_MINSIZE">0</bool>
+                <string name="proxy-Custom arguments">""</string>
+                <string name="proxy-Custom ctor arguments">""</string>
+                <string name="proxy-Event sources">""</string>
+                <bool name="proxy-AUI manager">0</bool>
+              </document>
+            </document>
+            <document>
+              <string name="title">"wxStaticBoxSizer H"</string>
+              <string name="type">"dialog-control-document"</string>
+              <string name="filename">""</string>
+              <string name="icon-name">"sizer"</string>
+              <long name="is-transient">0</long>
+              <long name="owns-file">1</long>
+              <long name="title-mode">0</long>
+              <long name="locked">0</long>
+              <string name="proxy-type">"wbStaticBoxSizerProxy"</string>
+              <string name="proxy-Id name">"wxID_ANY"</string>
+              <long name="proxy-Id value">-1</long>
+              <string name="proxy-Label">"Wiimote device 2"</string>
+              <string name="proxy-Member variable name">""</string>
+              <string name="proxy-Sizer member variable name">""</string>
+              <string name="proxy-Foreground colour">""</string>
+              <string name="proxy-Font">""</string>
+              <bool name="proxy-Hidden">1</bool>
+              <bool name="proxy-Enabled">1</bool>
+              <string name="proxy-Static box class">"wxStaticBox"</string>
+              <string name="proxy-Orientation">"Horizontal"</string>
+              <string name="proxy-AlignH">"Left"</string>
+              <string name="proxy-AlignV">"Centre"</string>
+              <long name="proxy-Stretch factor">0</long>
+              <long name="proxy-Border">5</long>
+              <bool name="proxy-wxLEFT">1</bool>
+              <bool name="proxy-wxRIGHT">1</bool>
+              <bool name="proxy-wxTOP">1</bool>
+              <bool name="proxy-wxBOTTOM">1</bool>
+              <bool name="proxy-wxSHAPED">0</bool>
+              <bool name="proxy-wxADJUST_MINSIZE">0</bool>
+              <bool name="proxy-wxFIXED_MINSIZE">0</bool>
+              <string name="proxy-Platform">"<Any platform>"</string>
+              <document>
+                <string name="title">"Wiimotesproperties: ID_WIIMOTESPROPERTIES2"</string>
+                <string name="type">"dialog-control-document"</string>
+                <string name="filename">""</string>
+                <string name="icon-name">"panel"</string>
+                <long name="is-transient">0</long>
+                <long name="owns-file">1</long>
+                <long name="title-mode">0</long>
+                <long name="locked">0</long>
+                <string name="proxy-type">"wbPanelProxy"</string>
+                <string name="proxy-Id name">"ID_WIIMOTESPROPERTIES2"</string>
+                <long name="proxy-Id value">10000</long>
+                <string name="proxy-Name">""</string>
+                <string name="proxy-Class">"Wiimotesproperties"</string>
+                <string name="proxy-Base class">"wxPanel"</string>
+                <bool name="proxy-External implementation">1</bool>
+                <bool name="proxy-Separate files">0</bool>
+                <string name="proxy-Implementation filename">""</string>
+                <string name="proxy-Header filename">""</string>
+                <string name="proxy-Member variable name">"m_panProperties_2"</string>
+                <string name="proxy-Help text">""</string>
+                <string name="proxy-Tooltip text">""</string>
+                <string name="proxy-Background colour">""</string>
+                <string name="proxy-Foreground colour">""</string>
+                <string name="proxy-Font">""</string>
+                <bool name="proxy-Hidden">1</bool>
+                <bool name="proxy-Enabled">1</bool>
+                <string name="proxy-Platform">"<Any platform>"</string>
+                <string name="proxy-Data source">""</string>
+                <string name="proxy-Data class name">""</string>
+                <string name="proxy-Data class implementation filename">""</string>
+                <string name="proxy-Data class header filename">""</string>
+                <string name="proxy-Data class manager window">""</string>
+                <string name="proxy-Texture">""</string>
+                <string name="proxy-Texture style">"Tiled"</string>
+                <bool name="proxy-wxNO_BORDER">0</bool>
+                <bool name="proxy-wxSIMPLE_BORDER">0</bool>
+                <bool name="proxy-wxDOUBLE_BORDER">0</bool>
+                <bool name="proxy-wxBORDER_THEME">0</bool>
+                <bool name="proxy-wxSUNKEN_BORDER">0</bool>
+                <bool name="proxy-wxRAISED_BORDER">0</bool>
+                <bool name="proxy-wxSTATIC_BORDER">0</bool>
+                <bool name="proxy-wxWANTS_CHARS">0</bool>
+                <bool name="proxy-wxNO_FULL_REPAINT_ON_RESIZE">0</bool>
+                <bool name="proxy-wxFULL_REPAINT_ON_RESIZE">0</bool>
+                <bool name="proxy-wxCLIP_CHILDREN">0</bool>
+                <bool name="proxy-wxHSCROLL">0</bool>
+                <bool name="proxy-wxVSCROLL">0</bool>
+                <bool name="proxy-wxTAB_TRAVERSAL">0</bool>
+                <bool name="proxy-wxALWAYS_SHOW_SB">0</bool>
+                <bool name="proxy-wxWS_EX_VALIDATE_RECURSIVELY">0</bool>
+                <bool name="proxy-wxWS_EX_BLOCK_EVENTS">0</bool>
+                <string name="proxy-Custom styles">""</string>
+                <bool name="proxy-Fit to content">1</bool>
+                <long name="proxy-X">-1</long>
+                <long name="proxy-Y">-1</long>
+                <long name="proxy-Width">-1</long>
+                <long name="proxy-Height">-1</long>
+                <string name="proxy-AlignH">"Centre"</string>
+                <string name="proxy-AlignV">"Centre"</string>
+                <long name="proxy-Stretch factor">0</long>
+                <long name="proxy-Border">5</long>
+                <bool name="proxy-wxLEFT">1</bool>
+                <bool name="proxy-wxRIGHT">1</bool>
+                <bool name="proxy-wxTOP">1</bool>
+                <bool name="proxy-wxBOTTOM">1</bool>
+                <bool name="proxy-wxSHAPED">0</bool>
+                <bool name="proxy-wxADJUST_MINSIZE">0</bool>
+                <bool name="proxy-wxFIXED_MINSIZE">0</bool>
+                <string name="proxy-Custom arguments">""</string>
+                <string name="proxy-Custom ctor arguments">""</string>
+                <string name="proxy-Event sources">""</string>
+                <bool name="proxy-AUI manager">0</bool>
+              </document>
+            </document>
+            <document>
+              <string name="title">"wxStaticBoxSizer H"</string>
+              <string name="type">"dialog-control-document"</string>
+              <string name="filename">""</string>
+              <string name="icon-name">"sizer"</string>
+              <long name="is-transient">0</long>
+              <long name="owns-file">1</long>
+              <long name="title-mode">0</long>
+              <long name="locked">0</long>
+              <string name="proxy-type">"wbStaticBoxSizerProxy"</string>
+              <string name="proxy-Id name">"wxID_ANY"</string>
+              <long name="proxy-Id value">-1</long>
+              <string name="proxy-Label">"Wiimote device 3"</string>
+              <string name="proxy-Member variable name">""</string>
+              <string name="proxy-Sizer member variable name">""</string>
+              <string name="proxy-Foreground colour">""</string>
+              <string name="proxy-Font">""</string>
+              <bool name="proxy-Hidden">1</bool>
+              <bool name="proxy-Enabled">1</bool>
+              <string name="proxy-Static box class">"wxStaticBox"</string>
+              <string name="proxy-Orientation">"Horizontal"</string>
+              <string name="proxy-AlignH">"Left"</string>
+              <string name="proxy-AlignV">"Centre"</string>
+              <long name="proxy-Stretch factor">0</long>
+              <long name="proxy-Border">5</long>
+              <bool name="proxy-wxLEFT">1</bool>
+              <bool name="proxy-wxRIGHT">1</bool>
+              <bool name="proxy-wxTOP">1</bool>
+              <bool name="proxy-wxBOTTOM">1</bool>
+              <bool name="proxy-wxSHAPED">0</bool>
+              <bool name="proxy-wxADJUST_MINSIZE">0</bool>
+              <bool name="proxy-wxFIXED_MINSIZE">0</bool>
+              <string name="proxy-Platform">"<Any platform>"</string>
+              <document>
+                <string name="title">"Wiimotesproperties: ID_WIIMOTESPROPERTIES3"</string>
+                <string name="type">"dialog-control-document"</string>
+                <string name="filename">""</string>
+                <string name="icon-name">"panel"</string>
+                <long name="is-transient">0</long>
+                <long name="owns-file">1</long>
+                <long name="title-mode">0</long>
+                <long name="locked">0</long>
+                <string name="proxy-type">"wbPanelProxy"</string>
+                <string name="proxy-Id name">"ID_WIIMOTESPROPERTIES3"</string>
+                <long name="proxy-Id value">10001</long>
+                <string name="proxy-Name">""</string>
+                <string name="proxy-Class">"Wiimotesproperties"</string>
+                <string name="proxy-Base class">"wxPanel"</string>
+                <bool name="proxy-External implementation">1</bool>
+                <bool name="proxy-Separate files">0</bool>
+                <string name="proxy-Implementation filename">""</string>
+                <string name="proxy-Header filename">""</string>
+                <string name="proxy-Member variable name">"m_panProperties_3"</string>
+                <string name="proxy-Help text">""</string>
+                <string name="proxy-Tooltip text">""</string>
+                <string name="proxy-Background colour">""</string>
+                <string name="proxy-Foreground colour">""</string>
+                <string name="proxy-Font">""</string>
+                <bool name="proxy-Hidden">1</bool>
+                <bool name="proxy-Enabled">1</bool>
+                <string name="proxy-Platform">"<Any platform>"</string>
+                <string name="proxy-Data source">""</string>
+                <string name="proxy-Data class name">""</string>
+                <string name="proxy-Data class implementation filename">""</string>
+                <string name="proxy-Data class header filename">""</string>
+                <string name="proxy-Data class manager window">""</string>
+                <string name="proxy-Texture">""</string>
+                <string name="proxy-Texture style">"Tiled"</string>
+                <bool name="proxy-wxNO_BORDER">0</bool>
+                <bool name="proxy-wxSIMPLE_BORDER">0</bool>
+                <bool name="proxy-wxDOUBLE_BORDER">0</bool>
+                <bool name="proxy-wxBORDER_THEME">0</bool>
+                <bool name="proxy-wxSUNKEN_BORDER">0</bool>
+                <bool name="proxy-wxRAISED_BORDER">0</bool>
+                <bool name="proxy-wxSTATIC_BORDER">0</bool>
+                <bool name="proxy-wxWANTS_CHARS">0</bool>
+                <bool name="proxy-wxNO_FULL_REPAINT_ON_RESIZE">0</bool>
+                <bool name="proxy-wxFULL_REPAINT_ON_RESIZE">0</bool>
+                <bool name="proxy-wxCLIP_CHILDREN">0</bool>
+                <bool name="proxy-wxHSCROLL">0</bool>
+                <bool name="proxy-wxVSCROLL">0</bool>
+                <bool name="proxy-wxTAB_TRAVERSAL">0</bool>
+                <bool name="proxy-wxALWAYS_SHOW_SB">0</bool>
+                <bool name="proxy-wxWS_EX_VALIDATE_RECURSIVELY">0</bool>
+                <bool name="proxy-wxWS_EX_BLOCK_EVENTS">0</bool>
+                <string name="proxy-Custom styles">""</string>
+                <bool name="proxy-Fit to content">1</bool>
+                <long name="proxy-X">-1</long>
+                <long name="proxy-Y">-1</long>
+                <long name="proxy-Width">-1</long>
+                <long name="proxy-Height">-1</long>
+                <string name="proxy-AlignH">"Centre"</string>
+                <string name="proxy-AlignV">"Centre"</string>
+                <long name="proxy-Stretch factor">0</long>
+                <long name="proxy-Border">5</long>
+                <bool name="proxy-wxLEFT">1</bool>
+                <bool name="proxy-wxRIGHT">1</bool>
+                <bool name="proxy-wxTOP">1</bool>
+                <bool name="proxy-wxBOTTOM">1</bool>
+                <bool name="proxy-wxSHAPED">0</bool>
+                <bool name="proxy-wxADJUST_MINSIZE">0</bool>
+                <bool name="proxy-wxFIXED_MINSIZE">0</bool>
+                <string name="proxy-Custom arguments">""</string>
+                <string name="proxy-Custom ctor arguments">""</string>
+                <string name="proxy-Event sources">""</string>
+                <bool name="proxy-AUI manager">0</bool>
+              </document>
+            </document>
+            <document>
+              <string name="title">"wxStaticBoxSizer H"</string>
+              <string name="type">"dialog-control-document"</string>
+              <string name="filename">""</string>
+              <string name="icon-name">"sizer"</string>
+              <long name="is-transient">0</long>
+              <long name="owns-file">1</long>
+              <long name="title-mode">0</long>
+              <long name="locked">0</long>
+              <string name="proxy-type">"wbStaticBoxSizerProxy"</string>
+              <string name="proxy-Id name">"wxID_ANY"</string>
+              <long name="proxy-Id value">-1</long>
+              <string name="proxy-Label">"Wiimote device 4"</string>
+              <string name="proxy-Member variable name">""</string>
+              <string name="proxy-Sizer member variable name">""</string>
+              <string name="proxy-Foreground colour">""</string>
+              <string name="proxy-Font">""</string>
+              <bool name="proxy-Hidden">1</bool>
+              <bool name="proxy-Enabled">1</bool>
+              <string name="proxy-Static box class">"wxStaticBox"</string>
+              <string name="proxy-Orientation">"Horizontal"</string>
+              <string name="proxy-AlignH">"Left"</string>
+              <string name="proxy-AlignV">"Centre"</string>
+              <long name="proxy-Stretch factor">0</long>
+              <long name="proxy-Border">5</long>
+              <bool name="proxy-wxLEFT">1</bool>
+              <bool name="proxy-wxRIGHT">1</bool>
+              <bool name="proxy-wxTOP">1</bool>
+              <bool name="proxy-wxBOTTOM">1</bool>
+              <bool name="proxy-wxSHAPED">0</bool>
+              <bool name="proxy-wxADJUST_MINSIZE">0</bool>
+              <bool name="proxy-wxFIXED_MINSIZE">0</bool>
+              <string name="proxy-Platform">"<Any platform>"</string>
+              <document>
+                <string name="title">"Wiimotesproperties: ID_WIIMOTESPROPERTIES4"</string>
+                <string name="type">"dialog-control-document"</string>
+                <string name="filename">""</string>
+                <string name="icon-name">"panel"</string>
+                <long name="is-transient">0</long>
+                <long name="owns-file">1</long>
+                <long name="title-mode">0</long>
+                <long name="locked">0</long>
+                <string name="proxy-type">"wbPanelProxy"</string>
+                <string name="proxy-Id name">"ID_WIIMOTESPROPERTIES4"</string>
+                <long name="proxy-Id value">10002</long>
+                <string name="proxy-Name">""</string>
+                <string name="proxy-Class">"Wiimotesproperties"</string>
+                <string name="proxy-Base class">"wxPanel"</string>
+                <bool name="proxy-External implementation">1</bool>
+                <bool name="proxy-Separate files">0</bool>
+                <string name="proxy-Implementation filename">""</string>
+                <string name="proxy-Header filename">""</string>
+                <string name="proxy-Member variable name">"m_panProperties_4"</string>
+                <string name="proxy-Help text">""</string>
+                <string name="proxy-Tooltip text">""</string>
+                <string name="proxy-Background colour">""</string>
+                <string name="proxy-Foreground colour">""</string>
+                <string name="proxy-Font">""</string>
+                <bool name="proxy-Hidden">1</bool>
+                <bool name="proxy-Enabled">1</bool>
+                <string name="proxy-Platform">"<Any platform>"</string>
+                <string name="proxy-Data source">""</string>
+                <string name="proxy-Data class name">""</string>
+                <string name="proxy-Data class implementation filename">""</string>
+                <string name="proxy-Data class header filename">""</string>
+                <string name="proxy-Data class manager window">""</string>
+                <string name="proxy-Texture">""</string>
+                <string name="proxy-Texture style">"Tiled"</string>
+                <bool name="proxy-wxNO_BORDER">0</bool>
+                <bool name="proxy-wxSIMPLE_BORDER">0</bool>
+                <bool name="proxy-wxDOUBLE_BORDER">0</bool>
+                <bool name="proxy-wxBORDER_THEME">0</bool>
+                <bool name="proxy-wxSUNKEN_BORDER">0</bool>
+                <bool name="proxy-wxRAISED_BORDER">0</bool>
+                <bool name="proxy-wxSTATIC_BORDER">0</bool>
+                <bool name="proxy-wxWANTS_CHARS">0</bool>
+                <bool name="proxy-wxNO_FULL_REPAINT_ON_RESIZE">0</bool>
+                <bool name="proxy-wxFULL_REPAINT_ON_RESIZE">0</bool>
+                <bool name="proxy-wxCLIP_CHILDREN">0</bool>
+                <bool name="proxy-wxHSCROLL">0</bool>
+                <bool name="proxy-wxVSCROLL">0</bool>
+                <bool name="proxy-wxTAB_TRAVERSAL">0</bool>
+                <bool name="proxy-wxALWAYS_SHOW_SB">0</bool>
+                <bool name="proxy-wxWS_EX_VALIDATE_RECURSIVELY">0</bool>
+                <bool name="proxy-wxWS_EX_BLOCK_EVENTS">0</bool>
+                <string name="proxy-Custom styles">""</string>
+                <bool name="proxy-Fit to content">1</bool>
+                <long name="proxy-X">-1</long>
+                <long name="proxy-Y">-1</long>
+                <long name="proxy-Width">-1</long>
+                <long name="proxy-Height">-1</long>
+                <string name="proxy-AlignH">"Centre"</string>
+                <string name="proxy-AlignV">"Centre"</string>
+                <long name="proxy-Stretch factor">0</long>
+                <long name="proxy-Border">5</long>
+                <bool name="proxy-wxLEFT">1</bool>
+                <bool name="proxy-wxRIGHT">1</bool>
+                <bool name="proxy-wxTOP">1</bool>
+                <bool name="proxy-wxBOTTOM">1</bool>
+                <bool name="proxy-wxSHAPED">0</bool>
+                <bool name="proxy-wxADJUST_MINSIZE">0</bool>
+                <bool name="proxy-wxFIXED_MINSIZE">0</bool>
+                <string name="proxy-Custom arguments">""</string>
+                <string name="proxy-Custom ctor arguments">""</string>
+                <string name="proxy-Event sources">""</string>
+                <bool name="proxy-AUI manager">0</bool>
+              </document>
+            </document>
+            <document>
+              <string name="title">"wxButton: ID_BUTTON_RECONNECT"</string>
+              <string name="type">"dialog-control-document"</string>
+              <string name="filename">""</string>
+              <string name="icon-name">"dialogcontrol"</string>
+              <long name="is-transient">0</long>
+              <long name="owns-file">1</long>
+              <long name="title-mode">0</long>
+              <long name="locked">0</long>
+              <string name="proxy-type">"wbButtonProxy"</string>
+              <string name="event-handler-0">"wxEVT_COMMAND_BUTTON_CLICKED|OnButtonReconnectClick|NONE||WiimotesConfiguration"</string>
+              <string name="proxy-Id name">"ID_BUTTON_RECONNECT"</string>
+              <long name="proxy-Id value">10007</long>
+              <string name="proxy-Name">""</string>
+              <string name="proxy-Class">"wxButton"</string>
+              <string name="proxy-Base class">"wxButton"</string>
+              <bool name="proxy-External implementation">1</bool>
+              <bool name="proxy-Separate files">0</bool>
+              <string name="proxy-Implementation filename">""</string>
+              <string name="proxy-Header filename">""</string>
+              <string name="proxy-Member variable name">""</string>
+              <string name="proxy-Label">"Reconnect"</string>
+              <bool name="proxy-Default">0</bool>
+              <string name="proxy-Help text">""</string>
+              <string name="proxy-Tooltip text">""</string>
+              <string name="proxy-Data variable">""</string>
+              <string name="proxy-Data validator">""</string>
+              <string name="proxy-Data source">""</string>
+              <string name="proxy-Data class name">""</string>
+              <string name="proxy-Data class implementation filename">""</string>
+              <string name="proxy-Data class header filename">""</string>
+              <string name="proxy-Data class manager window">""</string>
+              <string name="proxy-Background colour">""</string>
+              <string name="proxy-Foreground colour">""</string>
+              <string name="proxy-Font">""</string>
+              <bool name="proxy-Hidden">0</bool>
+              <bool name="proxy-Enabled">1</bool>
+              <string name="proxy-Platform">"<Any platform>"</string>
+              <bool name="proxy-wxBU_LEFT">0</bool>
+              <bool name="proxy-wxBU_RIGHT">0</bool>
+              <bool name="proxy-wxBU_TOP">0</bool>
+              <bool name="proxy-wxBU_BOTTOM">0</bool>
+              <bool name="proxy-wxBU_EXACTFIT">0</bool>
+              <bool name="proxy-wxNO_BORDER">0</bool>
+              <bool name="proxy-wxWANTS_CHARS">0</bool>
+              <bool name="proxy-wxNO_FULL_REPAINT_ON_RESIZE">0</bool>
+              <bool name="proxy-wxFULL_REPAINT_ON_RESIZE">0</bool>
+              <string name="proxy-Custom styles">""</string>
+              <long name="proxy-X">-1</long>
+              <long name="proxy-Y">-1</long>
+              <long name="proxy-Width">-1</long>
+              <long name="proxy-Height">-1</long>
+              <string name="proxy-AlignH">"Centre"</string>
+              <string name="proxy-AlignV">"Centre"</string>
+              <long name="proxy-Stretch factor">0</long>
+              <long name="proxy-Border">5</long>
+              <bool name="proxy-wxLEFT">1</bool>
+              <bool name="proxy-wxRIGHT">1</bool>
+              <bool name="proxy-wxTOP">1</bool>
+              <bool name="proxy-wxBOTTOM">1</bool>
+              <bool name="proxy-wxSHAPED">0</bool>
+              <bool name="proxy-wxADJUST_MINSIZE">0</bool>
+              <bool name="proxy-wxFIXED_MINSIZE">0</bool>
+              <string name="proxy-Custom arguments">""</string>
+              <string name="proxy-Custom ctor arguments">""</string>
+            </document>
+          </document>
+        </document>
+        <document>
+          <string name="title">"Wiimotes properties"</string>
+          <string name="type">"dialog-document"</string>
+          <string name="filename">""</string>
+          <string name="icon-name">"dialog"</string>
+          <long name="is-transient">0</long>
+          <long name="owns-file">1</long>
+          <long name="title-mode">0</long>
+          <long name="locked">0</long>
+          <string name="proxy-type">"wbDialogProxy"</string>
+          <long name="base-id">10000</long>
+          <bool name="use-id-prefix">0</bool>
+          <string name="id-prefix">""</string>
+          <bool name="use-id-suffix">0</bool>
+          <string name="id-suffix">""</string>
+          <string name="app-kind">"Standard"</string>
+          <long name="use-xrc">0</long>
+          <long name="working-mode">0</long>
+          <string name="proxy-Id name">"ID_WIIMOTESPROPERTIES"</string>
+          <long name="proxy-Id value">10005</long>
+          <string name="proxy-Class">"Wiimotesproperties"</string>
+          <string name="proxy-Base class">"wxPanel"</string>
+          <string name="proxy-Window kind">"wxPanel"</string>
+          <string name="proxy-Implementation filename">"wwiimotesproperties.cpp"</string>
+          <string name="proxy-Header filename">"wwiimotesproperties.h"</string>
+          <string name="proxy-XRC filename">""</string>
+          <string name="proxy-Title">"Wiimotes properties"</string>
+          <bool name="proxy-Centre">1</bool>
+          <string name="proxy-Icon">""</string>
+          <bool name="proxy-Dialog units">0</bool>
+          <string name="proxy-Help text">""</string>
+          <string name="proxy-Tooltip text">""</string>
+          <string name="proxy-Background colour">""</string>
+          <string name="proxy-Foreground colour">""</string>
+          <string name="proxy-Font">""</string>
+          <bool name="proxy-Hidden">0</bool>
+          <bool name="proxy-Enabled">1</bool>
+          <string name="proxy-Platform">"<Any platform>"</string>
+          <string name="proxy-Data source">""</string>
+          <string name="proxy-Data class name">""</string>
+          <string name="proxy-Data class implementation filename">""</string>
+          <string name="proxy-Data class header filename">""</string>
+          <string name="proxy-Data class manager window">""</string>
+          <string name="proxy-Texture">""</string>
+          <string name="proxy-Texture style">"Tiled"</string>
+          <bool name="proxy-wxDEFAULT_DIALOG_STYLE">0</bool>
+          <bool name="proxy-wxCAPTION">0</bool>
+          <bool name="proxy-wxRESIZE_BORDER">0</bool>
+          <bool name="proxy-wxSYSTEM_MENU">0</bool>
+          <bool name="proxy-wxSTAY_ON_TOP">0</bool>
+          <bool name="proxy-wxDIALOG_NO_PARENT">0</bool>
+          <bool name="proxy-wxCLOSE_BOX">0</bool>
+          <bool name="proxy-wxMAXIMIZE_BOX">0</bool>
+          <bool name="proxy-wxMINIMIZE_BOX">0</bool>
+          <bool name="proxy-wxDIALOG_MODAL">0</bool>
+          <bool name="proxy-wxNO_BORDER">0</bool>
+          <bool name="proxy-wxSIMPLE_BORDER">0</bool>
+          <bool name="proxy-wxDOUBLE_BORDER">0</bool>
+          <bool name="proxy-wxBORDER_THEME">0</bool>
+          <bool name="proxy-wxSUNKEN_BORDER">0</bool>
+          <bool name="proxy-wxRAISED_BORDER">0</bool>
+          <bool name="proxy-wxSTATIC_BORDER">0</bool>
+          <bool name="proxy-wxWANTS_CHARS">0</bool>
+          <bool name="proxy-wxNO_FULL_REPAINT_ON_RESIZE">0</bool>
+          <bool name="proxy-wxFULL_REPAINT_ON_RESIZE">0</bool>
+          <bool name="proxy-wxCLIP_CHILDREN">0</bool>
+          <bool name="proxy-wxTAB_TRAVERSAL">0</bool>
+          <bool name="proxy-wxWS_EX_VALIDATE_RECURSIVELY">0</bool>
+          <bool name="proxy-wxWS_EX_BLOCK_EVENTS">0</bool>
+          <bool name="proxy-wxWS_EX_TRANSIENT">0</bool>
+          <string name="proxy-Custom styles">""</string>
+          <bool name="proxy-wxDIALOG_EX_CONTEXTHELP">0</bool>
+          <bool name="proxy-Fit to content">1</bool>
+          <long name="proxy-X">-1</long>
+          <long name="proxy-Y">-1</long>
+          <long name="proxy-Width">-1</long>
+          <long name="proxy-Height">-1</long>
+          <bool name="proxy-AUI manager">0</bool>
+          <string name="proxy-Event sources">""</string>
+          <document>
+            <string name="title">"wxBoxSizer H"</string>
+            <string name="type">"dialog-control-document"</string>
+            <string name="filename">""</string>
+            <string name="icon-name">"sizer"</string>
+            <long name="is-transient">0</long>
+            <long name="owns-file">1</long>
+            <long name="title-mode">0</long>
+            <long name="locked">0</long>
+            <string name="proxy-type">"wbBoxSizerProxy"</string>
+            <string name="proxy-Orientation">"Horizontal"</string>
+            <string name="proxy-Member variable name">""</string>
+            <string name="proxy-AlignH">"Centre"</string>
+            <string name="proxy-AlignV">"Centre"</string>
+            <long name="proxy-Stretch factor">0</long>
+            <long name="proxy-Border">5</long>
+            <bool name="proxy-wxLEFT">1</bool>
+            <bool name="proxy-wxRIGHT">1</bool>
+            <bool name="proxy-wxTOP">1</bool>
+            <bool name="proxy-wxBOTTOM">1</bool>
+            <bool name="proxy-wxSHAPED">0</bool>
+            <bool name="proxy-wxADJUST_MINSIZE">0</bool>
+            <bool name="proxy-wxFIXED_MINSIZE">0</bool>
+            <string name="proxy-Platform">"<Any platform>"</string>
+            <document>
+              <string name="title">"wxStaticBitmap: wxID_ICON"</string>
+              <string name="type">"dialog-control-document"</string>
+              <string name="filename">""</string>
+              <string name="icon-name">"staticbitmap"</string>
+              <long name="is-transient">0</long>
+              <long name="owns-file">1</long>
+              <long name="title-mode">0</long>
+              <long name="locked">0</long>
+              <string name="proxy-type">"wbStaticBitmapProxy"</string>
+              <string name="proxy-Id name">"wxID_ICON"</string>
+              <long name="proxy-Id value">10004</long>
+              <string name="proxy-Name">""</string>
+              <string name="proxy-Class">"wxStaticBitmap"</string>
+              <string name="proxy-Base class">"wxStaticBitmap"</string>
+              <bool name="proxy-External implementation">1</bool>
+              <bool name="proxy-Separate files">0</bool>
+              <string name="proxy-Implementation filename">""</string>
+              <string name="proxy-Header filename">""</string>
+              <string name="proxy-Member variable name">"m_icon"</string>
+              <string name="proxy-Bitmap">"icons/none.xpm"</string>
+              <string name="proxy-Help text">""</string>
+              <string name="proxy-Tooltip text">""</string>
+              <string name="proxy-Data variable">""</string>
+              <string name="proxy-Data validator">""</string>
+              <string name="proxy-Data source">""</string>
+              <string name="proxy-Data class name">""</string>
+              <string name="proxy-Data class implementation filename">""</string>
+              <string name="proxy-Data class header filename">""</string>
+              <string name="proxy-Data class manager window">""</string>
+              <string name="proxy-Background colour">""</string>
+              <string name="proxy-Foreground colour">""</string>
+              <string name="proxy-Font">""</string>
+              <bool name="proxy-Hidden">0</bool>
+              <bool name="proxy-Enabled">1</bool>
+              <string name="proxy-Platform">"<Any platform>"</string>
+              <bool name="proxy-wxNO_BORDER">0</bool>
+              <bool name="proxy-wxSIMPLE_BORDER">0</bool>
+              <bool name="proxy-wxDOUBLE_BORDER">0</bool>
+              <bool name="proxy-wxBORDER_THEME">0</bool>
+              <bool name="proxy-wxSUNKEN_BORDER">0</bool>
+              <bool name="proxy-wxRAISED_BORDER">0</bool>
+              <bool name="proxy-wxSTATIC_BORDER">0</bool>
+              <bool name="proxy-wxWANTS_CHARS">0</bool>
+              <bool name="proxy-wxNO_FULL_REPAINT_ON_RESIZE">0</bool>
+              <bool name="proxy-wxFULL_REPAINT_ON_RESIZE">0</bool>
+              <string name="proxy-Custom styles">""</string>
+              <long name="proxy-X">-1</long>
+              <long name="proxy-Y">-1</long>
+              <long name="proxy-Width">64</long>
+              <long name="proxy-Height">42</long>
+              <string name="proxy-AlignH">"Centre"</string>
+              <string name="proxy-AlignV">"Top"</string>
+              <long name="proxy-Stretch factor">0</long>
+              <long name="proxy-Border">5</long>
+              <bool name="proxy-wxLEFT">1</bool>
+              <bool name="proxy-wxRIGHT">1</bool>
+              <bool name="proxy-wxTOP">1</bool>
+              <bool name="proxy-wxBOTTOM">1</bool>
+              <bool name="proxy-wxSHAPED">0</bool>
+              <bool name="proxy-wxADJUST_MINSIZE">0</bool>
+              <bool name="proxy-wxFIXED_MINSIZE">0</bool>
+              <string name="proxy-Custom arguments">""</string>
+              <string name="proxy-Custom ctor arguments">""</string>
+            </document>
+            <document>
+              <string name="title">"wxGridSizerProxy"</string>
+              <string name="type">"dialog-control-document"</string>
+              <string name="filename">""</string>
+              <string name="icon-name">"sizer"</string>
+              <long name="is-transient">0</long>
+              <long name="owns-file">1</long>
+              <long name="title-mode">0</long>
+              <long name="locked">0</long>
+              <string name="proxy-type">"wbGridSizerProxy"</string>
+              <long name="proxy-Columns">2</long>
+              <long name="proxy-Rows">2</long>
+              <long name="proxy-ColumnSpacing">0</long>
+              <long name="proxy-RowSpacing">0</long>
+              <string name="proxy-Member variable name">""</string>
+              <string name="proxy-Platform">"<Any platform>"</string>
+              <string name="proxy-AlignH">"Centre"</string>
+              <string name="proxy-AlignV">"Centre"</string>
+              <long name="proxy-Stretch factor">0</long>
+              <long name="proxy-Border">5</long>
+              <bool name="proxy-wxLEFT">1</bool>
+              <bool name="proxy-wxRIGHT">1</bool>
+              <bool name="proxy-wxTOP">1</bool>
+              <bool name="proxy-wxBOTTOM">1</bool>
+              <bool name="proxy-wxSHAPED">0</bool>
+              <bool name="proxy-wxADJUST_MINSIZE">0</bool>
+              <bool name="proxy-wxFIXED_MINSIZE">0</bool>
+              <document>
+                <string name="title">"wxCheckBox: ID_CHK_CONNECTED"</string>
+                <string name="type">"dialog-control-document"</string>
+                <string name="filename">""</string>
+                <string name="icon-name">"checkbox"</string>
+                <long name="is-transient">0</long>
+                <long name="owns-file">1</long>
+                <long name="title-mode">0</long>
+                <long name="locked">0</long>
+                <string name="proxy-type">"wbCheckBoxProxy"</string>
+                <string name="proxy-Id name">"ID_CHK_CONNECTED"</string>
+                <long name="proxy-Id value">10003</long>
+                <string name="proxy-Name">""</string>
+                <string name="proxy-Class">"wxCheckBox"</string>
+                <string name="proxy-Base class">"wxCheckBox"</string>
+                <bool name="proxy-External implementation">1</bool>
+                <bool name="proxy-Separate files">0</bool>
+                <string name="proxy-Implementation filename">""</string>
+                <string name="proxy-Header filename">""</string>
+                <string name="proxy-Member variable name">"m_chkConnected"</string>
+                <string name="proxy-Label">"Connected"</string>
+                <bool name="proxy-Initial value">0</bool>
+                <string name="proxy-Help text">""</string>
+                <string name="proxy-Tooltip text">""</string>
+                <string name="proxy-Data variable">""</string>
+                <string name="proxy-Data validator">""</string>
+                <string name="proxy-Data source">""</string>
+                <string name="proxy-Data class name">""</string>
+                <string name="proxy-Data class implementation filename">""</string>
+                <string name="proxy-Data class header filename">""</string>
+                <string name="proxy-Data class manager window">""</string>
+                <string name="proxy-Background colour">""</string>
+                <string name="proxy-Foreground colour">""</string>
+                <string name="proxy-Font">""</string>
+                <bool name="proxy-Hidden">0</bool>
+                <bool name="proxy-Enabled">0</bool>
+                <string name="proxy-Platform">"<Any platform>"</string>
+                <bool name="proxy-wxALIGN_RIGHT">0</bool>
+                <bool name="proxy-wxCHK_2STATE">0</bool>
+                <bool name="proxy-wxCHK_3STATE">0</bool>
+                <bool name="proxy-wxCHK_ALLOW_3RD_STATE_FOR_USER">0</bool>
+                <bool name="proxy-wxWANTS_CHARS">0</bool>
+                <bool name="proxy-wxNO_FULL_REPAINT_ON_RESIZE">0</bool>
+                <bool name="proxy-wxFULL_REPAINT_ON_RESIZE">0</bool>
+                <string name="proxy-Custom styles">""</string>
+                <long name="proxy-X">-1</long>
+                <long name="proxy-Y">-1</long>
+                <long name="proxy-Width">-1</long>
+                <long name="proxy-Height">-1</long>
+                <string name="proxy-AlignH">"Left"</string>
+                <string name="proxy-AlignV">"Centre"</string>
+                <long name="proxy-Stretch factor">0</long>
+                <long name="proxy-Border">5</long>
+                <bool name="proxy-wxLEFT">1</bool>
+                <bool name="proxy-wxRIGHT">1</bool>
+                <bool name="proxy-wxTOP">1</bool>
+                <bool name="proxy-wxBOTTOM">1</bool>
+                <bool name="proxy-wxSHAPED">0</bool>
+                <bool name="proxy-wxADJUST_MINSIZE">0</bool>
+                <bool name="proxy-wxFIXED_MINSIZE">0</bool>
+                <string name="proxy-Custom arguments">""</string>
+                <string name="proxy-Custom ctor arguments">""</string>
+              </document>
+              <document>
+                <string name="title">"wxCheckBox: ID_CHK_ACC"</string>
+                <string name="type">"dialog-control-document"</string>
+                <string name="filename">""</string>
+                <string name="icon-name">"checkbox"</string>
+                <long name="is-transient">0</long>
+                <long name="owns-file">1</long>
+                <long name="title-mode">0</long>
+                <long name="locked">0</long>
+                <string name="proxy-type">"wbCheckBoxProxy"</string>
+                <string name="proxy-Id name">"ID_CHK_ACC"</string>
+                <long name="proxy-Id value">10000</long>
+                <string name="proxy-Name">""</string>
+                <string name="proxy-Class">"wxCheckBox"</string>
+                <string name="proxy-Base class">"wxCheckBox"</string>
+                <bool name="proxy-External implementation">1</bool>
+                <bool name="proxy-Separate files">0</bool>
+                <string name="proxy-Implementation filename">""</string>
+                <string name="proxy-Header filename">""</string>
+                <string name="proxy-Member variable name">"m_chkAcc"</string>
+                <string name="proxy-Label">"Accelerometers enabled"</string>
+                <bool name="proxy-Initial value">0</bool>
+                <string name="proxy-Help text">""</string>
+                <string name="proxy-Tooltip text">""</string>
+                <string name="proxy-Data variable">""</string>
+                <string name="proxy-Data validator">""</string>
+                <string name="proxy-Data source">""</string>
+                <string name="proxy-Data class name">""</string>
+                <string name="proxy-Data class implementation filename">""</string>
+                <string name="proxy-Data class header filename">""</string>
+                <string name="proxy-Data class manager window">""</string>
+                <string name="proxy-Background colour">""</string>
+                <string name="proxy-Foreground colour">""</string>
+                <string name="proxy-Font">""</string>
+                <bool name="proxy-Hidden">0</bool>
+                <bool name="proxy-Enabled">0</bool>
+                <string name="proxy-Platform">"<Any platform>"</string>
+                <bool name="proxy-wxALIGN_RIGHT">0</bool>
+                <bool name="proxy-wxCHK_2STATE">0</bool>
+                <bool name="proxy-wxCHK_3STATE">0</bool>
+                <bool name="proxy-wxCHK_ALLOW_3RD_STATE_FOR_USER">0</bool>
+                <bool name="proxy-wxWANTS_CHARS">0</bool>
+                <bool name="proxy-wxNO_FULL_REPAINT_ON_RESIZE">0</bool>
+                <bool name="proxy-wxFULL_REPAINT_ON_RESIZE">0</bool>
+                <string name="proxy-Custom styles">""</string>
+                <long name="proxy-X">-1</long>
+                <long name="proxy-Y">-1</long>
+                <long name="proxy-Width">-1</long>
+                <long name="proxy-Height">-1</long>
+                <string name="proxy-AlignH">"Left"</string>
+                <string name="proxy-AlignV">"Centre"</string>
+                <long name="proxy-Stretch factor">0</long>
+                <long name="proxy-Border">5</long>
+                <bool name="proxy-wxLEFT">1</bool>
+                <bool name="proxy-wxRIGHT">1</bool>
+                <bool name="proxy-wxTOP">1</bool>
+                <bool name="proxy-wxBOTTOM">1</bool>
+                <bool name="proxy-wxSHAPED">0</bool>
+                <bool name="proxy-wxADJUST_MINSIZE">0</bool>
+                <bool name="proxy-wxFIXED_MINSIZE">0</bool>
+                <string name="proxy-Custom arguments">""</string>
+                <string name="proxy-Custom ctor arguments">""</string>
+              </document>
+              <document>
+                <string name="title">"wxCheckBox: ID_CHK_NUNCHUCK"</string>
+                <string name="type">"dialog-control-document"</string>
+                <string name="filename">""</string>
+                <string name="icon-name">"checkbox"</string>
+                <long name="is-transient">0</long>
+                <long name="owns-file">1</long>
+                <long name="title-mode">0</long>
+                <long name="locked">0</long>
+                <string name="proxy-type">"wbCheckBoxProxy"</string>
+                <string name="proxy-Id name">"ID_CHK_NUNCHUCK"</string>
+                <long name="proxy-Id value">10001</long>
+                <string name="proxy-Name">""</string>
+                <string name="proxy-Class">"wxCheckBox"</string>
+                <string name="proxy-Base class">"wxCheckBox"</string>
+                <bool name="proxy-External implementation">1</bool>
+                <bool name="proxy-Separate files">0</bool>
+                <string name="proxy-Implementation filename">""</string>
+                <string name="proxy-Header filename">""</string>
+                <string name="proxy-Member variable name">"m_chkNunchuck"</string>
+                <string name="proxy-Label">"Nunchuck enabled"</string>
+                <bool name="proxy-Initial value">0</bool>
+                <string name="proxy-Help text">""</string>
+                <string name="proxy-Tooltip text">""</string>
+                <string name="proxy-Data variable">""</string>
+                <string name="proxy-Data validator">""</string>
+                <string name="proxy-Data source">""</string>
+                <string name="proxy-Data class name">""</string>
+                <string name="proxy-Data class implementation filename">""</string>
+                <string name="proxy-Data class header filename">""</string>
+                <string name="proxy-Data class manager window">""</string>
+                <string name="proxy-Background colour">""</string>
+                <string name="proxy-Foreground colour">""</string>
+                <string name="proxy-Font">""</string>
+                <bool name="proxy-Hidden">0</bool>
+                <bool name="proxy-Enabled">0</bool>
+                <string name="proxy-Platform">"<Any platform>"</string>
+                <bool name="proxy-wxALIGN_RIGHT">0</bool>
+                <bool name="proxy-wxCHK_2STATE">0</bool>
+                <bool name="proxy-wxCHK_3STATE">0</bool>
+                <bool name="proxy-wxCHK_ALLOW_3RD_STATE_FOR_USER">0</bool>
+                <bool name="proxy-wxWANTS_CHARS">0</bool>
+                <bool name="proxy-wxNO_FULL_REPAINT_ON_RESIZE">0</bool>
+                <bool name="proxy-wxFULL_REPAINT_ON_RESIZE">0</bool>
+                <string name="proxy-Custom styles">""</string>
+                <long name="proxy-X">-1</long>
+                <long name="proxy-Y">-1</long>
+                <long name="proxy-Width">-1</long>
+                <long name="proxy-Height">-1</long>
+                <string name="proxy-AlignH">"Left"</string>
+                <string name="proxy-AlignV">"Centre"</string>
+                <long name="proxy-Stretch factor">0</long>
+                <long name="proxy-Border">5</long>
+                <bool name="proxy-wxLEFT">1</bool>
+                <bool name="proxy-wxRIGHT">1</bool>
+                <bool name="proxy-wxTOP">1</bool>
+                <bool name="proxy-wxBOTTOM">1</bool>
+                <bool name="proxy-wxSHAPED">0</bool>
+                <bool name="proxy-wxADJUST_MINSIZE">0</bool>
+                <bool name="proxy-wxFIXED_MINSIZE">0</bool>
+                <string name="proxy-Custom arguments">""</string>
+                <string name="proxy-Custom ctor arguments">""</string>
+              </document>
+              <document>
+                <string name="title">"wxCheckBox: ID_CHK_MOTION_PLUS"</string>
+                <string name="type">"dialog-control-document"</string>
+                <string name="filename">""</string>
+                <string name="icon-name">"checkbox"</string>
+                <long name="is-transient">0</long>
+                <long name="owns-file">1</long>
+                <long name="title-mode">0</long>
+                <long name="locked">0</long>
+                <string name="proxy-type">"wbCheckBoxProxy"</string>
+                <string name="proxy-Id name">"ID_CHK_MOTION_PLUS"</string>
+                <long name="proxy-Id value">10002</long>
+                <string name="proxy-Name">""</string>
+                <string name="proxy-Class">"wxCheckBox"</string>
+                <string name="proxy-Base class">"wxCheckBox"</string>
+                <bool name="proxy-External implementation">1</bool>
+                <bool name="proxy-Separate files">0</bool>
+                <string name="proxy-Implementation filename">""</string>
+                <string name="proxy-Header filename">""</string>
+                <string name="proxy-Member variable name">"m_chkMotionPlus"</string>
+                <string name="proxy-Label">"Motion plus enabled"</string>
+                <bool name="proxy-Initial value">0</bool>
+                <string name="proxy-Help text">""</string>
+                <string name="proxy-Tooltip text">""</string>
+                <string name="proxy-Data variable">""</string>
+                <string name="proxy-Data validator">""</string>
+                <string name="proxy-Data source">""</string>
+                <string name="proxy-Data class name">""</string>
+                <string name="proxy-Data class implementation filename">""</string>
+                <string name="proxy-Data class header filename">""</string>
+                <string name="proxy-Data class manager window">""</string>
+                <string name="proxy-Background colour">""</string>
+                <string name="proxy-Foreground colour">""</string>
+                <string name="proxy-Font">""</string>
+                <bool name="proxy-Hidden">0</bool>
+                <bool name="proxy-Enabled">0</bool>
+                <string name="proxy-Platform">"<Any platform>"</string>
+                <bool name="proxy-wxALIGN_RIGHT">0</bool>
+                <bool name="proxy-wxCHK_2STATE">0</bool>
+                <bool name="proxy-wxCHK_3STATE">0</bool>
+                <bool name="proxy-wxCHK_ALLOW_3RD_STATE_FOR_USER">0</bool>
+                <bool name="proxy-wxWANTS_CHARS">0</bool>
+                <bool name="proxy-wxNO_FULL_REPAINT_ON_RESIZE">0</bool>
+                <bool name="proxy-wxFULL_REPAINT_ON_RESIZE">0</bool>
+                <string name="proxy-Custom styles">""</string>
+                <long name="proxy-X">-1</long>
+                <long name="proxy-Y">-1</long>
+                <long name="proxy-Width">-1</long>
+                <long name="proxy-Height">-1</long>
+                <string name="proxy-AlignH">"Left"</string>
+                <string name="proxy-AlignV">"Centre"</string>
+                <long name="proxy-Stretch factor">0</long>
+                <long name="proxy-Border">5</long>
+                <bool name="proxy-wxLEFT">1</bool>
+                <bool name="proxy-wxRIGHT">1</bool>
+                <bool name="proxy-wxTOP">1</bool>
+                <bool name="proxy-wxBOTTOM">1</bool>
+                <bool name="proxy-wxSHAPED">0</bool>
+                <bool name="proxy-wxADJUST_MINSIZE">0</bool>
+                <bool name="proxy-wxFIXED_MINSIZE">0</bool>
+                <string name="proxy-Custom arguments">""</string>
+                <string name="proxy-Custom ctor arguments">""</string>
+              </document>
+            </document>
+          </document>
+        </document>
+      </document>
+      <document>
+        <string name="title">"Sources"</string>
+        <string name="type">"html-document"</string>
+        <string name="filename">""</string>
+        <string name="icon-name">"sourcesfolder"</string>
+        <long name="is-transient">1</long>
+        <long name="owns-file">1</long>
+        <long name="title-mode">0</long>
+        <long name="locked">1</long>
+        <document>
+          <string name="title">"mviacam.rc"</string>
+          <string name="type">"source-editor-document"</string>
+          <string name="filename">"mviacam.rc"</string>
+          <string name="icon-name">"source-editor"</string>
+          <long name="is-transient">0</long>
+          <long name="owns-file">0</long>
+          <long name="title-mode">1</long>
+          <long name="locked">0</long>
+          <string name="created">"3/8/2009"</string>
+          <string name="language">""</string>
+        </document>
+      </document>
+      <document>
+        <string name="title">"Images"</string>
+        <string name="type">"html-document"</string>
+        <string name="filename">""</string>
+        <string name="icon-name">"bitmapsfolder"</string>
+        <long name="is-transient">1</long>
+        <long name="owns-file">1</long>
+        <long name="title-mode">0</long>
+        <long name="locked">1</long>
+        <document>
+          <string name="title">"wiimote-small.xpm"</string>
+          <string name="type">"image-document"</string>
+          <string name="filename">"icons/wiimote-small.xpm"</string>
+          <string name="icon-name">"image"</string>
+          <long name="is-transient">0</long>
+          <long name="owns-file">0</long>
+          <long name="title-mode">0</long>
+          <long name="locked">0</long>
+          <long name="zoom-level">100</long>
+        </document>
+        <document>
+          <string name="title">"none.xpm"</string>
+          <string name="type">"image-document"</string>
+          <string name="filename">"icons/none.xpm"</string>
+          <string name="icon-name">"image"</string>
+          <long name="is-transient">0</long>
+          <long name="owns-file">0</long>
+          <long name="title-mode">0</long>
+          <long name="locked">0</long>
+          <long name="zoom-level">100</long>
+        </document>
+        <document>
+          <string name="title">"balance-board.xpm"</string>
+          <string name="type">"image-document"</string>
+          <string name="filename">"icons/balance-board.xpm"</string>
+          <string name="icon-name">"image"</string>
+          <long name="is-transient">0</long>
+          <long name="owns-file">0</long>
+          <long name="title-mode">0</long>
+          <long name="locked">0</long>
+          <long name="zoom-level">100</long>
+        </document>
+      </document>
+    </document>
+  </documents>
+
+</anthemion-project>
diff --git a/src/mod_wiimotes/tests/CMakeLists.txt b/src/mod_wiimotes/tests/CMakeLists.txt
new file mode 100755
index 0000000..f56c10c
--- /dev/null
+++ b/src/mod_wiimotes/tests/CMakeLists.txt
@@ -0,0 +1,16 @@
+cmake_minimum_required(VERSION 2.8)
+project(test_mod_wiimotes)
+
+add_executable(test_mod_wiimotes_basic test_mod_wiimotes_basic.cpp)
+target_link_libraries(test_mod_wiimotes_basic spcore)
+target_link_libraries(test_mod_wiimotes_basic sphost)
+target_link_libraries(test_mod_wiimotes_basic nvwa)
+#add_test (NAME test_mod_wiimotes_basic COMMAND $<TARGET_FILE:nvwa_loader> $<TARGET_FILE:test_mod_wiimotes_basic>)
+
+add_executable(test_mod_wiimites_config_gui test_mod_wiimites_config_gui.cpp)
+target_link_libraries(test_mod_wiimites_config_gui spcore)
+target_link_libraries(test_mod_wiimites_config_gui sphost)
+target_link_libraries(test_mod_wiimites_config_gui nvwa)
+target_link_libraries(test_mod_wiimites_config_gui ${wxWidgets_LIBRARIES})
+add_test (NAME test_mod_wiimites_config_gui COMMAND $<TARGET_FILE:nvwa_loader> $<TARGET_FILE:test_mod_wiimites_config_gui>)
+
diff --git a/src/mod_wiimotes/tests/test_mod_wiimites_config_gui.cpp b/src/mod_wiimotes/tests/test_mod_wiimites_config_gui.cpp
new file mode 100644
index 0000000..1189795
--- /dev/null
+++ b/src/mod_wiimotes/tests/test_mod_wiimites_config_gui.cpp
@@ -0,0 +1,257 @@
+/////////////////////////////////////////////////////////////////////////////
+// Name:        test_mod_wiimotes_config_gui.cpp
+// Author:      Cesar Mauri Loba
+// Copyright:   (C) 2011 Cesar Mauri Loba - CREA Software Systems
+//
+//  This program is free software: you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation, either version 3 of the License, or
+//  (at your option) any later version.
+//
+//  This program is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+/////////////////////////////////////////////////////////////////////////////
+
+// Dirty, but useful
+#define TEST_NO_MAIN	1
+#include "test_mod_wiimotes_basic.cpp"
+
+#include "spcore/coreruntime.h"
+#include "sphost/testcommon.h"
+#include "nvwa/debug_new.h"
+#include "mod_wiimotes/wiimotes_types.h"
+
+#if defined(__WXGTK__) || defined(__WXMOTIF__) || defined(__WXX11__)
+	// Include Xlib for latter use on main
+	#include <X11/Xlib.h>
+#endif
+#include <wx/app.h>
+#include <wx/image.h>
+#include <wx/msgdlg.h>
+#include <wx/frame.h>
+#include <wx/panel.h>
+#include <wx/sizer.h>
+#include <stdio.h>
+
+#include <boost/thread/thread.hpp>
+
+using namespace spcore;
+using namespace mod_wiimotes;
+
+/*
+	Check threads enabled
+*/
+#if !wxUSE_THREADS
+     #error "This program requires thread support."
+#endif // wxUSE_THREADS
+
+/*
+	main app class
+*/
+class TestWXApp: public wxApp
+{
+	DECLARE_CLASS( TestWXApp )
+public:
+	TestWXApp();	// Constructor
+
+private:
+	virtual bool OnInit();	// Initialises the application
+	virtual int OnExit();	// Called on exit
+
+	SmartPtr<spcore::IComponent> m_comp;
+	boost::thread* m_thread;
+};
+
+/*
+	main frame class
+*/
+class MyFrame : public wxFrame
+{
+public:
+    MyFrame();
+	void OnCloseWindow( wxCloseEvent& event );
+	static MyFrame* CreateAddPanel ( spcore::IComponent& component );
+private:
+	void OnSize(wxSizeEvent& event);
+    // any class wishing to process wxWidgets events must use this macro
+    DECLARE_EVENT_TABLE()
+};
+
+/*
+	myframe event table
+*/
+BEGIN_EVENT_TABLE(MyFrame, wxFrame)
+	EVT_CLOSE( MyFrame::OnCloseWindow )
+	EVT_SIZE ( MyFrame::OnSize)
+END_EVENT_TABLE()
+
+void MyFrame::OnCloseWindow(wxCloseEvent &event)
+{
+	event.Skip(); // Equivalent to: wxFrame::OnCloseWindow(event);
+}
+
+void MyFrame::OnSize(wxSizeEvent& event)
+{
+	Layout();
+	Fit();
+
+	event.Skip (false);
+}
+
+
+/*!
+ * Application instance declaration
+ */
+DECLARE_APP(TestWXApp)
+
+/*!
+ * TestWXApp type definition
+ */
+IMPLEMENT_CLASS( TestWXApp, wxApp )
+
+/*
+	Application instance implementation
+
+	we use IMPLEMENT_APP_NO_MAIN instead of IMPLEMENT_APP
+	because we define our own main
+ */
+IMPLEMENT_APP_NO_MAIN(TestWXApp)
+
+// ============================================================================
+// implementation
+// ============================================================================
+
+// ----------------------------------------------------------------------------
+// main frame
+// ----------------------------------------------------------------------------
+MyFrame::MyFrame()
+: wxFrame(NULL, wxID_ANY, _T(""), wxDefaultPosition, wxDefaultSize, wxCAPTION|wxSYSTEM_MENU|wxCLOSE_BOX)
+{
+
+}
+
+MyFrame* MyFrame::CreateAddPanel ( spcore::IComponent& component )
+{
+	MyFrame* mf= new MyFrame;
+	wxBoxSizer* sizer= new wxBoxSizer(wxVERTICAL);
+	mf->SetSizer(sizer);
+	wxWindow* pan= component.GetGUI(mf);
+	if (!pan) {
+		delete mf;
+		return NULL;
+	}
+	sizer->Add (static_cast<wxWindow*>(pan), 0, wxALIGN_CENTER_HORIZONTAL|wxALL, 0);
+	mf->GetSizer()->SetSizeHints(mf);	// Fit to content
+
+	return mf;
+}
+
+// ----------------------------------------------------------------------------
+// the application class
+// ----------------------------------------------------------------------------
+
+TestWXApp::TestWXApp() {
+}
+
+/*
+  Initialisation for TestWXApp
+
+  Return true to signal correct initialization or false when error
+ */
+bool TestWXApp::OnInit()
+{
+#if wxUSE_XPM
+	wxImage::AddHandler(new wxXPMHandler);
+#endif
+#if wxUSE_LIBPNG
+	wxImage::AddHandler(new wxPNGHandler);
+#endif
+#if wxUSE_LIBJPEG
+	wxImage::AddHandler(new wxJPEGHandler);
+#endif
+#if wxUSE_GIF
+	wxImage::AddHandler(new wxGIFHandler);
+#endif
+
+#if defined(WIN32)
+	// Uncomment this to enable a console in Windows for debug purposes
+	//AllocConsole(); freopen("CONOUT$", "wb", stdout);
+#endif
+
+	ICoreRuntime* cr= getSpCoreRuntime();
+
+	int retval= cr->LoadModule("mod_wiimotes");
+	DumpCoreRuntime(cr);
+	if (retval!= 0) ExitErr("error loading mod_wiimotes");
+
+
+
+	m_thread= new boost::thread(test_wiimotes_basic);
+	assert (m_thread->joinable());
+
+
+
+	m_comp= cr->CreateComponent("wiimotes_config_gui", "wcg", 0, NULL);
+	if (!m_comp.get()) ExitErr("error cannot create component");
+
+	// Create dialog
+	MyFrame* mf= MyFrame::CreateAddPanel ( *m_comp );
+	if (!mf) ExitErr("error error creating pannel");
+
+	mf->Show();
+	//if (m_comp->Initialize()!= 0) ExitErr("initialization failed");
+	//if (m_comp->Start()!= 0) ExitErr("start root component failed");
+
+	return true;
+}
+
+
+/*!
+  Cleanup for TestWXApp
+ */
+
+int TestWXApp::OnExit()
+{
+//	m_comp->Stop();
+//	m_comp->Finish();
+
+	g_exit_loop= true;
+
+	m_thread->join();
+	delete m_thread;
+
+	return wxApp::OnExit();
+}
+
+// ----------------------------------------------------------------------------
+// main
+// ----------------------------------------------------------------------------
+
+int main(int argc, char *argv[]) {
+
+#if defined(__WXGTK__) || defined(__WXMOTIF__) || defined(__WXX11__)
+	// Under X11 it's necessary enable threading support
+	if ( XInitThreads() == 0 ) {
+		ExitErr("Unable to initialize multithreaded X11 code (XInitThreads failed)");
+		exit( EXIT_FAILURE );
+	}
+#endif
+
+	// Initialize spcore
+	ICoreRuntime* cr= getSpCoreRuntime();
+	if (!cr) return false;
+
+	// Run wxWidgets message pump
+	wxEntry(argc, argv);
+
+	// Free spcore
+	freeSpCoreRuntime();
+
+	// If execution reaches this => all tests ok
+	return 0;
+}
diff --git a/src/mod_wiimotes/tests/test_mod_wiimotes_basic.cpp b/src/mod_wiimotes/tests/test_mod_wiimotes_basic.cpp
new file mode 100644
index 0000000..5025543
--- /dev/null
+++ b/src/mod_wiimotes/tests/test_mod_wiimotes_basic.cpp
@@ -0,0 +1,345 @@
+/////////////////////////////////////////////////////////////////////////////
+// Name:        test_mod_wiimotes_basic.cpp
+// Author:      Cesar Mauri Loba
+// Copyright:   (C) 2011 Cesar Mauri Loba - CREA Software Systems
+//
+//  This program is free software: you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation, either version 3 of the License, or
+//  (at your option) any later version.
+//
+//  This program is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+/////////////////////////////////////////////////////////////////////////////
+// TODO: fix memory leak when a reconnect is issued while motion plus
+
+#include "spcore/coreruntime.h"
+#include "sphost/testcommon.h"
+#include "nvwa/debug_new.h"
+
+#include "mod_wiimotes/wiimotes_types.h"
+
+#include "spcore/basictypes.h"
+
+#include <ostream>
+#include <sstream>
+#include <iostream>
+#include <math.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+
+using namespace spcore;
+using namespace mod_wiimotes;
+
+class VoidClass{};
+
+VoidClass voidClassInstance;
+
+static
+void DumpStatus (const CTypeWiimotesStatus & msg)
+{
+	std::cout << "Dumping status message\n";
+	std::cout << "Status: " << msg.GetGeneralStatus() << std::endl;
+	if (msg.GetGeneralStatus() == CTypeWiimotesStatus::CONNECTED) {
+		std::cout << "Connected count:" << msg.GetConnectedCount() << std::endl;
+		for (unsigned int i= 0; i< msg.GetMaxCount(); ++i) {
+			if (msg.IsConnected(i)) {
+				std::cout << "Wiimote " << i+1 << " is connected\n";
+				if (msg.HasNunchuk(i)) std::cout << "Nunchuck found\n";
+				if (msg.HasBalanceBoard(i)) std::cout << "Balance board\n";
+				if (msg.HasMotionPlus(i)) std::cout << "Motion plus\n";
+				if (msg.IsAccelerometersEnabled(i)) std::cout << "Accelerometers enabled\n";
+				if (msg.IsMotionPlusEnabled(i)) std::cout << "Motion plus enabled\n";
+			}
+			else
+				std::cout << "Wiimote " << i+1 << " is NOT connected\n";
+		}
+	}
+}
+
+static
+void DumpStatus (const CTypeWiimotesAccelerometer & msg)
+{
+	std::cout << "Dumping acc\n";
+
+	std::cout << "Forces: (" << msg.GetForceX() << ", " << msg.GetForceY() << ", " << msg.GetForceZ() << ")\n";
+	if (msg.IsOrientationAccurate()) {
+		std::cout << "Orientation: (Pitch: " << msg.GetPitch() << ", Roll: " << msg.GetRoll() << ")\n";
+	}
+
+	calls_per_second();
+}
+
+static
+void DumpStatus (const CTypeWiimotesButtons & msg)
+{
+	std::cout << "Dumping buttons\n";
+
+	if (msg.IsPressedA()) std::cout << "IsPressedA\n";
+	if (msg.IsPressedB()) std::cout << "IsPressedB\n";
+	if (msg.IsPressedOne()) std::cout << "IsPressedOne\n";
+	if (msg.IsPressedTwo()) std::cout << "IsPressedTwo\n";
+	if (msg.IsPressedMinus()) std::cout << "IsPressedMinus\n";
+	if (msg.IsPressedPlus()) std::cout << "IsPressedPlus\n";
+	if (msg.IsPressedHome()) std::cout << "IsPressedHome\n";
+	if (msg.IsPressedUp()) std::cout << "IsPressedUp\n";
+	if (msg.IsPressedDown()) std::cout << "IsPressedDown\n";
+	if (msg.IsPressedLeft()) std::cout << "IsPressedLeft\n";
+	if (msg.IsPressedRight()) std::cout << "IsPressedRight\n";
+	if (msg.IsPressedC()) std::cout << "IsPressedC\n";
+	if (msg.IsPressedZ()) std::cout << "IsPressedZ\n";
+}
+
+static
+void DumpStatus (const CTypeWiimotesBalanceBoard & msg)
+{
+//	std::cout << "Dumping balance board\n";
+
+	//std::cout << msg.GetTopLeft() << ", " << msg.GetTopRight() << std::endl;
+	//std::cout << msg.GetBottomLeft() << ", " << msg.GetBottomRight() << std::endl;
+
+	printf ("%.2f\t %.2f\t %.2f\t %.2f\t %.2f\t %.2f\n",
+		msg.GetTopLeft(), msg.GetTopRight(), msg.GetBottomLeft(), msg.GetBottomRight(),
+		msg.GetCenterOfMassX(), msg.GetCenterOfMassY());
+
+	//std::cout << "(X: " << msg.GetCenterOfMassX() << ", Y: " << msg.GetCenterOfMassY() << ")\n";
+}
+
+static
+void DumpStatus (const CTypeWiimotesMotionPlus & msg)
+{
+//	std::cout << "Dumping motion plus\n";
+
+//	std::cout << msg.GetXSpeed() << "\t" << msg.GetYSpeed() << "\t" << msg.GetZSpeed() << std::endl;
+
+	printf ("%.2f\t %.2f\t %.2f\n", msg.GetXSpeed(), msg.GetYSpeed(), msg.GetZSpeed());
+}
+
+
+// Status input pin
+class InputPinStatus : public CInputPinWriteOnly<CTypeWiimotesStatus, VoidClass> {
+public:
+	InputPinStatus (VoidClass & component) : CInputPinWriteOnly<CTypeWiimotesStatus, VoidClass>("test_status", component) {}
+	virtual int DoSend(const CTypeWiimotesStatus & msg) {
+		DumpStatus (msg);
+		return 0;
+	}
+};
+
+// CTypeWiimotesAccelerometer
+class InputPinAccelerometer : public CInputPinWriteOnly<CTypeWiimotesAccelerometer, VoidClass> {
+public:
+	InputPinAccelerometer (VoidClass & component) : CInputPinWriteOnly<CTypeWiimotesAccelerometer, VoidClass>("test_acc", component) {}
+	virtual int DoSend(const CTypeWiimotesAccelerometer & msg) {
+		DumpStatus (msg);
+		return 0;
+	}
+};
+
+
+// CTypeWiimotesButtons
+class InputPinButtons : public CInputPinWriteOnly<CTypeWiimotesButtons, VoidClass> {
+public:
+	InputPinButtons (VoidClass & component) : CInputPinWriteOnly<CTypeWiimotesButtons, VoidClass>("test_buttons", component) {}
+	virtual int DoSend(const CTypeWiimotesButtons & msg) {
+		DumpStatus (msg);
+		return 0;
+	}
+};
+
+// BalanceBoard
+class InputPinBalanceBoard : public CInputPinWriteOnly<CTypeWiimotesBalanceBoard, VoidClass> {
+public:
+	InputPinBalanceBoard (VoidClass & component) : CInputPinWriteOnly<CTypeWiimotesBalanceBoard, VoidClass>("test_balance_board", component) {}
+	virtual int DoSend(const CTypeWiimotesBalanceBoard & msg) {
+		DumpStatus (msg);
+		return 0;
+	}
+};
+
+// MotionPlus
+class InputPinMotionPlus : public CInputPinWriteOnly<CTypeWiimotesMotionPlus, VoidClass> {
+public:
+	InputPinMotionPlus (VoidClass & component) : CInputPinWriteOnly<CTypeWiimotesMotionPlus, VoidClass>("test_motion_plus", component) {}
+	virtual int DoSend(const CTypeWiimotesMotionPlus & msg) {
+		DumpStatus (msg);
+		return 0;
+	}
+};
+
+bool g_exit_loop= false;
+
+void test_wiimotes_basic()
+{
+	ICoreRuntime* cr= getSpCoreRuntime();
+
+
+
+	//
+	// Create wiimotes configuration component
+	//
+	SmartPtr<spcore::IComponent> config= cr->CreateComponent("wiimotes_config", "wc", 0, NULL);
+	if (config.get()== NULL) ExitErr("error creating wiimotes_config");
+
+	// Create & connect input pin to dump status
+	SmartPtr<IInputPin> statusPin(new InputPinStatus(voidClassInstance), false);
+	if (statusPin.get()== NULL) ExitErr("error creating input status test pin");
+	IOutputPin* status_opin= config->FindOutputPin(*config, "status");
+	if (!status_opin) ExitErr("output pin status not found");
+	if (status_opin->Connect (*statusPin)) ExitErr("error connecting pin");
+
+	//
+	// Create wiimotes input component
+	//
+	SmartPtr<spcore::IComponent> wiinput= cr->CreateComponent("wiimotes_input", "wi", 0, NULL);
+	if (wiinput.get()== NULL) ExitErr("error creating wiimotes_input");
+
+
+	// Create & connect input pin to dump nunchuck
+	SmartPtr<IInputPin> nuncPin(new InputPinAccelerometer(voidClassInstance), false);
+	if (nuncPin.get()== NULL) ExitErr("error creating input nunchuck test pin");
+	IOutputPin* nunc_opin= wiinput->FindOutputPin(*wiinput, "nunchuck_accelerometers");
+	if (!nunc_opin) ExitErr("output pin nunchuck not found");
+	if (nunc_opin->Connect (*nuncPin)) ExitErr("error connecting pin");
+
+
+	// Create & connect input pin to dump buttons
+	SmartPtr<IInputPin> btnPin(new InputPinButtons(voidClassInstance), false);
+	if (btnPin.get()== NULL) ExitErr("error creating input button test pin");
+	IOutputPin* btn_opin= wiinput->FindOutputPin(*wiinput, "buttons");
+	if (!btn_opin) ExitErr("output pin buttons not found");
+	if (btn_opin->Connect (*btnPin)) ExitErr("error connecting pin");
+
+	// Create & connect input pin to dump balance board
+	SmartPtr<IInputPin> bbPin(new InputPinBalanceBoard(voidClassInstance), false);
+	if (bbPin.get()== NULL) ExitErr("error creating input balance board test pin");
+	IOutputPin* bb_opin= wiinput->FindOutputPin(*wiinput, "balance_board");
+	if (!bb_opin) ExitErr("output pin balance board not found");
+	if (bb_opin->Connect (*bbPin)) ExitErr("error connecting pin");
+
+
+	// Create & connect input pin to dump accelerometers
+	SmartPtr<IInputPin> accPin(new InputPinAccelerometer(voidClassInstance), false);
+	if (accPin.get()== NULL) ExitErr("error creating input acc test pin");
+	IOutputPin* acc_opin= wiinput->FindOutputPin(*wiinput, "accelerometers");
+	if (!acc_opin) ExitErr("output pin acc not found");
+	//if (acc_opin->Connect (*accPin)) ExitErr("error connecting pin");
+
+
+
+	// Create & connect input pin to dump motion plus
+	SmartPtr<IInputPin> mpPin(new InputPinMotionPlus(voidClassInstance), false);
+	if (mpPin.get()== NULL) ExitErr("error creating input motion plus test pin");
+	IOutputPin* mp_opin= wiinput->FindOutputPin(*wiinput, "motion_plus");
+	if (!mp_opin) ExitErr("output pin motion plus not found");
+//	if (mp_opin->Connect (*mpPin)) ExitErr("error connecting pin");
+
+	//
+	// Find "reconnect" input pin
+	//
+	IInputPin* reconnect_ipin= config->FindInputPin(*config, "reconnect");
+	if (!reconnect_ipin) ExitErr("reconnect input pin not found");
+	SmartPtr<CTypeBool> dummyValue= CTypeBool::CreateInstance();
+	if (!dummyValue.get()) ExitErr("cannot create boolean value");
+
+	//
+	// Run them all
+	//
+	config->Initialize();
+	wiinput->Initialize();
+	config->Start();
+	wiinput->Start();
+
+	int key= 0;
+	while (key!= 'q' && key!= 'Q') {
+		if (key!= '\n') {
+			#ifdef WIN32
+				Sleep (1000);
+			#else
+				sleep (1);
+			#endif
+			std::cout << "Keystrokes:\n";
+			std::cout << "\t q -> quit\n";
+			std::cout << "\t r -> reconnect\n";
+			std::cout << "\t a -> enable accelerometers\n";
+			std::cout << "\t m -> enable motion plus\n";
+			std::cout << "\t d -> disable accelerometers/motion plus\n";
+		}
+
+		key= getch_no_block();
+		while (!key && !g_exit_loop) {
+			#ifdef WIN32
+				Sleep (100);
+			#else
+				usleep (100000);
+			#endif
+			key= getch_no_block();
+		}
+		if (g_exit_loop) break;
+
+		switch (key) {
+			case 'r': case 'R':
+				// Reconnect
+				reconnect_ipin->Send(dummyValue);
+				break;
+			case 'a': case 'A':
+				wiinput->Stop();
+				acc_opin->Connect (*accPin);
+				wiinput->Start();
+				break;
+			case 'm': case 'M':
+				wiinput->Stop();
+				mp_opin->Connect (*mpPin);
+				wiinput->Start();
+				break;
+			case 'd': case 'D':
+				wiinput->Stop();
+				acc_opin->Disconnect (*accPin);
+				mp_opin->Disconnect(*mpPin);
+				wiinput->Start();
+				break;
+		}
+	}
+
+	//
+	// Finish them all
+	//
+	std::cout << "Begin finish\n";
+	wiinput->Stop();
+	config->Stop();
+	wiinput->Finish();
+	config->Finish();
+	std::cout << "End finish\n";
+}
+
+
+// ----------------------------------------------------------------------------
+// main
+// ----------------------------------------------------------------------------
+#ifndef TEST_NO_MAIN
+int main(int, char *[]) {
+
+	// Initialize spcore
+	ICoreRuntime* cr= getSpCoreRuntime();
+	if (!cr) return false;
+
+	// Load module
+	int retval= cr->LoadModule("mod_wiimotes");
+	DumpCoreRuntime(cr);
+	if (retval!= 0) ExitErr("error loading mod_wiimotes");
+
+	test_wiimotes_basic();
+
+	// Free spcore
+	freeSpCoreRuntime();
+
+	// If execution reaches this => all tests ok
+	return 0;
+}
+#endif
diff --git a/src/mod_wiimotes/wiimotes_types.cpp b/src/mod_wiimotes/wiimotes_types.cpp
new file mode 100755
index 0000000..f04b3ca
--- /dev/null
+++ b/src/mod_wiimotes/wiimotes_types.cpp
@@ -0,0 +1,194 @@
+/////////////////////////////////////////////////////////////////////////////
+// File:        wiimotes_types.cpp
+// Author:      Cesar Mauri Loba (cesar at crea-si dot com)
+// Copyright:   (C) 2011 Cesar Mauri Loba - CREA Software Systems
+// 
+//  This program is free software: you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation, either version 3 of the License, or
+//  (at your option) any later version.
+//
+//  This program is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+/////////////////////////////////////////////////////////////////////////////
+
+#include "mod_wiimotes/wiimotes_types.h"
+#include <string.h>
+// Visual C++ complains about the structs defined in wiiuse.h
+// so we disable the meaningless warnings
+#if defined(_MSC_VER)
+#pragma warning (disable:4510)
+#pragma warning (disable:4512)
+#pragma warning (disable:4610)
+#define snprintf _snprintf
+#endif
+#include "wiiuse/include/wiiuse.h"
+
+using namespace spcore;
+
+namespace mod_wiimotes {
+
+/**
+ Class to store and notify wiimotes status
+*/
+
+CTypeWiimotesStatusContents::CTypeWiimotesStatusContents(int id) 
+: CTypeAny(id)
+{
+	Reset();	
+}
+
+void CTypeWiimotesStatusContents::Reset()
+{
+	m_generalStatus= IDLE;
+	m_connectedCount= 0;
+	for (int i= 0; i< MAXWIIMOTES; ++i) { 
+		m_wiimoteStatus[i]= NONE;
+		m_enabledFeatures[i]= ENABLED_NONE;
+	}
+}
+
+bool CTypeWiimotesStatusContents::IsConnected(unsigned int wiimote_n) const {
+	assert (wiimote_n< MAXWIIMOTES);
+	if (wiimote_n>= MAXWIIMOTES) return 0;
+	return ((m_wiimoteStatus[wiimote_n] & WIIMOTE_CONNECTED)== WIIMOTE_CONNECTED);
+}
+
+bool CTypeWiimotesStatusContents::HasNunchuk(unsigned int wiimote_n) const {
+	assert (wiimote_n< MAXWIIMOTES);
+	if (wiimote_n>= MAXWIIMOTES) return NONE;
+	return (m_wiimoteStatus[wiimote_n] & NUNCHUK)!= 0;
+}
+
+bool CTypeWiimotesStatusContents::HasClassicPad(unsigned int wiimote_n) const {
+	assert (wiimote_n< MAXWIIMOTES);
+	if (wiimote_n>= MAXWIIMOTES) return NONE;
+	return (m_wiimoteStatus[wiimote_n] & CLASSIC)!= 0;
+}
+
+bool CTypeWiimotesStatusContents::HasGuitarHero(unsigned int wiimote_n) const {
+	assert (wiimote_n< MAXWIIMOTES);
+	if (wiimote_n>= MAXWIIMOTES) return NONE;
+	return (m_wiimoteStatus[wiimote_n] & GUITAR_HERO)!= 0;
+}
+
+bool CTypeWiimotesStatusContents::HasBalanceBoard(unsigned int wiimote_n) const {
+	assert (wiimote_n< MAXWIIMOTES);
+	if (wiimote_n>= MAXWIIMOTES) return NONE;
+	return (m_wiimoteStatus[wiimote_n] & BALANCE_BOARD)!= 0;
+}
+
+bool CTypeWiimotesStatusContents::HasMotionPlus(unsigned int wiimote_n) const {
+	assert (wiimote_n< MAXWIIMOTES);
+	if (wiimote_n>= MAXWIIMOTES) return NONE;
+	return (m_wiimoteStatus[wiimote_n] & MOTION_PLUS)!= 0;
+}
+
+//
+// Accessors to query which features are enabled
+//
+bool CTypeWiimotesStatusContents::IsAccelerometersEnabled(unsigned int wiimote_n) const {
+	assert (wiimote_n< MAXWIIMOTES);
+	if (wiimote_n>= MAXWIIMOTES) return false;
+	return (m_enabledFeatures[wiimote_n] & CTypeWiimotesStatusContents::ENABLED_ACC? true : false);
+}
+
+bool CTypeWiimotesStatusContents::IsMotionPlusEnabled(unsigned int wiimote_n) const {
+	assert (wiimote_n< MAXWIIMOTES);
+	if (wiimote_n>= MAXWIIMOTES) return false;
+	return (m_enabledFeatures[wiimote_n] & CTypeWiimotesStatusContents::ENABLED_MP? true : false);
+}
+
+bool CTypeWiimotesStatusContents::IsNunchuckEnabled(unsigned int wiimote_n) const
+{
+	assert (wiimote_n< MAXWIIMOTES);
+	if (wiimote_n>= MAXWIIMOTES) return false;
+	return (m_enabledFeatures[wiimote_n] & CTypeWiimotesStatusContents::ENABLED_NUNCHUCK? true : false);
+}
+
+void CTypeWiimotesStatusContents::SetIsConnected(unsigned int wiimote_n, bool v) {
+	unsigned int value= m_wiimoteStatus[wiimote_n];
+	assert (wiimote_n< MAXWIIMOTES);
+	if (v) {
+		value|= WIIMOTE_CONNECTED;
+		m_wiimoteStatus[wiimote_n]= static_cast<Extension>(value);
+	}
+	else 
+		m_wiimoteStatus[wiimote_n]= NONE;	
+}
+
+void CTypeWiimotesStatusContents::SetExtension (unsigned int wiimote_n, Extension e) {
+	assert (wiimote_n< MAXWIIMOTES);
+	// clear lower bits, only one extensions is allowed
+	unsigned int value= m_wiimoteStatus[wiimote_n] & WIIMOTE_CONNECTED;
+	// store lower bytes
+	value|= e;
+	m_wiimoteStatus[wiimote_n]= static_cast<Extension>(value);
+}
+
+/* *****************************************************************************
+	CTypeWiimotesButtonsContents
+***************************************************************************** */
+bool CTypeWiimotesButtonsContents::IsPressedA() const {
+	return (m_wiimoteButtons & WIIMOTE_BUTTON_A? true : false);
+}
+
+bool CTypeWiimotesButtonsContents::IsPressedB() const {
+	return (m_wiimoteButtons & WIIMOTE_BUTTON_B? true : false);
+}
+
+bool CTypeWiimotesButtonsContents::IsPressedOne() const {
+	return (m_wiimoteButtons & WIIMOTE_BUTTON_ONE? true : false);
+}
+
+bool CTypeWiimotesButtonsContents::IsPressedTwo() const {
+	return (m_wiimoteButtons & WIIMOTE_BUTTON_TWO? true : false);
+}
+
+bool CTypeWiimotesButtonsContents::IsPressedMinus() const {
+	return (m_wiimoteButtons & WIIMOTE_BUTTON_MINUS? true : false);
+}
+
+bool CTypeWiimotesButtonsContents::IsPressedPlus() const {
+	return (m_wiimoteButtons & WIIMOTE_BUTTON_PLUS? true : false);
+}
+
+bool CTypeWiimotesButtonsContents::IsPressedHome() const {
+	return (m_wiimoteButtons & WIIMOTE_BUTTON_HOME? true : false);
+}
+
+bool CTypeWiimotesButtonsContents::IsPressedUp() const {
+	return (m_wiimoteButtons & WIIMOTE_BUTTON_UP? true : false);
+}
+
+bool CTypeWiimotesButtonsContents::IsPressedDown() const {
+	return (m_wiimoteButtons & WIIMOTE_BUTTON_DOWN? true : false);
+}
+
+bool CTypeWiimotesButtonsContents::IsPressedLeft() const {
+	return (m_wiimoteButtons & WIIMOTE_BUTTON_LEFT? true : false);
+}
+
+bool CTypeWiimotesButtonsContents::IsPressedRight() const {
+	return (m_wiimoteButtons & WIIMOTE_BUTTON_RIGHT? true : false);
+}
+
+// nunchuck
+bool CTypeWiimotesButtonsContents::IsPressedC() const {
+	return (m_nunchuckButtons & NUNCHUK_BUTTON_C? true : false);
+}
+
+bool CTypeWiimotesButtonsContents::IsPressedZ() const {
+	return (m_nunchuckButtons & NUNCHUK_BUTTON_Z? true : false);
+}
+
+bool CTypeWiimotesButtonsContents::IsPressedAny() const {
+	return (m_wiimoteButtons | m_nunchuckButtons? true : false);
+}
+
+};
\ No newline at end of file
diff --git a/src/mod_wiimotes/wwiimotesconfiguration.cpp b/src/mod_wiimotes/wwiimotesconfiguration.cpp
new file mode 100755
index 0000000..e884d19
--- /dev/null
+++ b/src/mod_wiimotes/wwiimotesconfiguration.cpp
@@ -0,0 +1,259 @@
+/////////////////////////////////////////////////////////////////////////////
+// Name:        wwiimotesconfiguration.cpp
+// Author:      Cesar Mauri Loba (cesar at crea-si dot com)
+// Copyright:   (C) 2011 Cesar Mauri Loba - CREA Software Systems
+// 
+//  This program is free software: you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation, either version 3 of the License, or
+//  (at your option) any later version.
+//
+//  This program is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+/////////////////////////////////////////////////////////////////////////////
+
+#include "wwiimotesconfiguration.h"
+#include "wwiimotesproperties.h"
+
+////@begin includes
+////@end includes
+
+#include <wx/sizer.h>
+#include <wx/statbox.h>
+#include <wx/button.h>
+#include <wx/icon.h>
+#include <wx/bitmap.h>
+#include <wx/msgdlg.h>
+#include <stdlib.h>
+
+////@begin XPM images
+////@end XPM images
+namespace mod_wiimotes {
+
+using namespace spcore;
+
+/*!
+ * WiimotesConfiguration type definition
+ */
+
+IMPLEMENT_DYNAMIC_CLASS( WiimotesConfiguration, wxPanel )
+
+// New event to update GUI when status changed
+DECLARE_LOCAL_EVENT_TYPE(wxEVT_REFRESH_STATUS, -1)
+DEFINE_LOCAL_EVENT_TYPE(wxEVT_REFRESH_STATUS)
+
+
+
+/*!
+ * WiimotesConfiguration event table definition
+ */
+
+BEGIN_EVENT_TABLE( WiimotesConfiguration, wxPanel )
+
+////@begin WiimotesConfiguration event table entries
+    EVT_BUTTON( ID_BUTTON_RECONNECT, WiimotesConfiguration::OnButtonReconnectClick )
+
+////@end WiimotesConfiguration event table entries
+	EVT_COMMAND  (wxID_ANY, wxEVT_REFRESH_STATUS, WiimotesConfiguration::StatusNotificationGUI)	
+END_EVENT_TABLE()
+
+
+/*!
+ * WiimotesConfiguration constructors
+ */
+
+WiimotesConfiguration::WiimotesConfiguration()
+{
+    Init();
+}
+
+WiimotesConfiguration::WiimotesConfiguration( wxWindow* parent, wxWindowID id, const wxPoint& pos, const wxSize& size, long style, const wxString& name )
+{
+    Init();
+    Create(parent, id, pos, size, style, name);
+}
+
+
+/*!
+ * CCameraConfiguration creator
+ */
+
+bool WiimotesConfiguration::Create( wxWindow* parent, wxWindowID id, const wxPoint& pos, const wxSize& size, long style, const wxString& name )
+{
+////@begin WiimotesConfiguration creation
+    SetExtraStyle(wxWS_EX_BLOCK_EVENTS);
+    wxPanel::Create( parent, id, pos, size, style );
+
+    CreateControls();
+    if (GetSizer())
+    {
+        GetSizer()->SetSizeHints(this);
+    }
+    Centre();
+////@end WiimotesConfiguration creation
+    return true;
+}
+
+
+/*!
+ * WiimotesConfiguration destructor
+ */
+
+WiimotesConfiguration::~WiimotesConfiguration()
+{
+	WiiuseThreadController::getInstance()->UnregisterListener(*this);
+////@begin WiimotesConfiguration destruction
+////@end WiimotesConfiguration destruction	
+}
+
+
+/*!
+ * Member initialisation
+ */
+
+void WiimotesConfiguration::Init()
+{
+////@begin WiimotesConfiguration member initialisation
+    m_panProperties_1 = NULL;
+    m_panProperties_2 = NULL;
+    m_panProperties_3 = NULL;
+    m_panProperties_4 = NULL;
+////@end WiimotesConfiguration member initialisation
+	m_sharedStatus= CTypeWiimotesStatus::CreateInstance();
+	m_privateStatus= CTypeWiimotesStatus::CreateInstance();
+}
+
+
+/*!
+ * Control creation for CCameraConfiguration
+ */
+
+void WiimotesConfiguration::CreateControls()
+{    
+////@begin WiimotesConfiguration content construction
+    WiimotesConfiguration* itemPanel1 = this;
+
+    wxBoxSizer* itemBoxSizer2 = new wxBoxSizer(wxVERTICAL);
+    itemPanel1->SetSizer(itemBoxSizer2);
+
+    wxStaticBox* itemStaticBoxSizer3Static = new wxStaticBox(itemPanel1, wxID_ANY, _("Wiimote device 1"));
+    wxStaticBoxSizer* itemStaticBoxSizer3 = new wxStaticBoxSizer(itemStaticBoxSizer3Static, wxHORIZONTAL);
+    itemBoxSizer2->Add(itemStaticBoxSizer3, 0, wxALIGN_LEFT|wxALL, 5);
+
+    m_panProperties_1 = new Wiimotesproperties;
+    m_panProperties_1->Create( itemPanel1, ID_WIIMOTESPROPERTIES1, wxDefaultPosition, wxDefaultSize, 0 );
+    itemStaticBoxSizer3->Add(m_panProperties_1, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5);
+
+    wxStaticBox* itemStaticBoxSizer5Static = new wxStaticBox(itemPanel1, wxID_ANY, _("Wiimote device 2"));
+    wxStaticBoxSizer* itemStaticBoxSizer5 = new wxStaticBoxSizer(itemStaticBoxSizer5Static, wxHORIZONTAL);
+    itemStaticBoxSizer5Static->Show(false);
+    itemBoxSizer2->Add(itemStaticBoxSizer5, 0, wxALIGN_LEFT|wxALL, 5);
+
+    m_panProperties_2 = new Wiimotesproperties;
+    m_panProperties_2->Create( itemPanel1, ID_WIIMOTESPROPERTIES2, wxDefaultPosition, wxDefaultSize, 0 );
+    m_panProperties_2->Show(false);
+    itemStaticBoxSizer5->Add(m_panProperties_2, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5);
+
+    wxStaticBox* itemStaticBoxSizer7Static = new wxStaticBox(itemPanel1, wxID_ANY, _("Wiimote device 3"));
+    wxStaticBoxSizer* itemStaticBoxSizer7 = new wxStaticBoxSizer(itemStaticBoxSizer7Static, wxHORIZONTAL);
+    itemStaticBoxSizer7Static->Show(false);
+    itemBoxSizer2->Add(itemStaticBoxSizer7, 0, wxALIGN_LEFT|wxALL, 5);
+
+    m_panProperties_3 = new Wiimotesproperties;
+    m_panProperties_3->Create( itemPanel1, ID_WIIMOTESPROPERTIES3, wxDefaultPosition, wxDefaultSize, 0 );
+    m_panProperties_3->Show(false);
+    itemStaticBoxSizer7->Add(m_panProperties_3, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5);
+
+    wxStaticBox* itemStaticBoxSizer9Static = new wxStaticBox(itemPanel1, wxID_ANY, _("Wiimote device 4"));
+    wxStaticBoxSizer* itemStaticBoxSizer9 = new wxStaticBoxSizer(itemStaticBoxSizer9Static, wxHORIZONTAL);
+    itemStaticBoxSizer9Static->Show(false);
+    itemBoxSizer2->Add(itemStaticBoxSizer9, 0, wxALIGN_LEFT|wxALL, 5);
+
+    m_panProperties_4 = new Wiimotesproperties;
+    m_panProperties_4->Create( itemPanel1, ID_WIIMOTESPROPERTIES4, wxDefaultPosition, wxDefaultSize, 0 );
+    m_panProperties_4->Show(false);
+    itemStaticBoxSizer9->Add(m_panProperties_4, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5);
+
+    wxButton* itemButton11 = new wxButton;
+    itemButton11->Create( itemPanel1, ID_BUTTON_RECONNECT, _("Reconnect"), wxDefaultPosition, wxDefaultSize, 0 );
+    itemBoxSizer2->Add(itemButton11, 0, wxALIGN_CENTER_HORIZONTAL|wxALL, 5);
+
+////@end WiimotesConfiguration content construction
+
+	WiiuseThreadController::getInstance()->RegisterListener(*this, 0, 0);
+	WiiuseThreadController::getInstance()->ReqStatus();
+}
+
+void WiimotesConfiguration::StatusNotification (const CTypeWiimotesStatus & status)
+{
+	m_mutex.lock();
+	status.Clone (m_sharedStatus.get(), true);
+	m_mutex.unlock();
+
+	wxCommandEvent event(wxEVT_REFRESH_STATUS);
+	wxPostEvent(this, event);
+}
+
+void WiimotesConfiguration::StatusNotificationGUI( wxCommandEvent& WXUNUSED(event) )
+{
+	m_mutex.lock();
+	m_sharedStatus->Clone(m_privateStatus.get(), true);
+	m_mutex.unlock();
+
+	m_panProperties_1->Update (*m_privateStatus, 0);
+	m_panProperties_2->Update (*m_privateStatus, 1);
+	m_panProperties_3->Update (*m_privateStatus, 2);
+	m_panProperties_4->Update (*m_privateStatus, 3);	
+}
+
+/*!
+ * Should we show tooltips?
+ */
+
+bool WiimotesConfiguration::ShowToolTips()
+{
+    return true;
+}
+
+/*!
+ * Get bitmap resources
+ */
+
+wxBitmap WiimotesConfiguration::GetBitmapResource( const wxString& name )
+{
+    // Bitmap retrieval
+////@begin WiimotesConfiguration bitmap retrieval
+    wxUnusedVar(name);
+    return wxNullBitmap;
+////@end WiimotesConfiguration bitmap retrieval
+}
+
+/*!
+ * Get icon resources
+ */
+
+wxIcon WiimotesConfiguration::GetIconResource( const wxString& name )
+{
+    // Icon retrieval
+////@begin WiimotesConfiguration icon retrieval
+    wxUnusedVar(name);
+    return wxNullIcon;
+////@end WiimotesConfiguration icon retrieval
+}
+
+/*!
+ * wxEVT_COMMAND_BUTTON_CLICKED event handler for ID_BUTTON_RECONNECT
+ */
+
+void WiimotesConfiguration::OnButtonReconnectClick( wxCommandEvent& event )
+{
+	WiiuseThreadController::getInstance()->Reconnect();
+    event.Skip(false);
+}
+
+}
diff --git a/src/mod_wiimotes/wwiimotesconfiguration.h b/src/mod_wiimotes/wwiimotesconfiguration.h
new file mode 100755
index 0000000..680f7db
--- /dev/null
+++ b/src/mod_wiimotes/wwiimotesconfiguration.h
@@ -0,0 +1,134 @@
+/////////////////////////////////////////////////////////////////////////////
+// Name:        wwiimotesconfiguration.h
+// Author:      Cesar Mauri Loba (cesar at crea-si dot com)
+// Copyright:   (C) 2011 Cesar Mauri Loba - CREA Software Systems
+// 
+//  This program is free software: you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation, either version 3 of the License, or
+//  (at your option) any later version.
+//
+//  This program is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+/////////////////////////////////////////////////////////////////////////////
+
+#ifndef _WWIIMOTESCONFIGURATION_H_
+#define _WWIIMOTESCONFIGURATION_H_
+
+
+/*!
+ * Includes
+ */
+
+#include "mod_wiimotes.h"
+
+////@begin includes
+////@end includes
+#include <wx/panel.h>
+#include <wx/stattext.h>
+#include <wx/choice.h>
+#include <wx/checkbox.h>
+#include <boost/thread/mutex.hpp>
+
+namespace mod_wiimotes {
+
+/*!
+ * Forward declarations
+ */
+
+////@begin forward declarations
+class Wiimotesproperties;
+////@end forward declarations
+
+/*!
+ * Control identifiers
+ */
+
+////@begin control identifiers
+#define ID_WIIMOTESCONFIGURATION 10060
+#define ID_WIIMOTESPROPERTIES1 10006
+#define ID_WIIMOTESPROPERTIES2 10000
+#define ID_WIIMOTESPROPERTIES3 10001
+#define ID_WIIMOTESPROPERTIES4 10002
+#define ID_BUTTON_RECONNECT 10007
+#define SYMBOL_WIIMOTESCONFIGURATION_STYLE wxCAPTION|wxTAB_TRAVERSAL
+#define SYMBOL_WIIMOTESCONFIGURATION_TITLE _("Wiimotes Configuration")
+#define SYMBOL_WIIMOTESCONFIGURATION_IDNAME ID_WIIMOTESCONFIGURATION
+#define SYMBOL_WIIMOTESCONFIGURATION_SIZE wxDefaultSize
+#define SYMBOL_WIIMOTESCONFIGURATION_POSITION wxDefaultPosition
+////@end control identifiers
+//#define SYMBOL_WIIMOTESCONFIGURATION_STYLE wxCAPTION|wxRESIZE_BORDER|wxSYSTEM_MENU|wxCLOSE_BOX|wxTAB_TRAVERSAL
+
+/*!
+ * WiimotesConfiguration class declaration
+ */
+
+class WiimotesConfiguration: public wxPanel, protected WiimoteListener
+{    
+    DECLARE_DYNAMIC_CLASS( WiimotesConfiguration )
+    DECLARE_EVENT_TABLE()
+
+public:
+    /// Constructors
+    WiimotesConfiguration();
+    WiimotesConfiguration( wxWindow* parent, wxWindowID id = SYMBOL_WIIMOTESCONFIGURATION_IDNAME, const wxPoint& pos = SYMBOL_WIIMOTESCONFIGURATION_POSITION, const wxSize& size = SYMBOL_WIIMOTESCONFIGURATION_SIZE, long style = SYMBOL_WIIMOTESCONFIGURATION_STYLE, const wxString& name= SYMBOL_WIIMOTESCONFIGURATION_TITLE );
+
+    /// Creation
+    bool Create( wxWindow* parent, wxWindowID id = SYMBOL_WIIMOTESCONFIGURATION_IDNAME, const wxPoint& pos = SYMBOL_WIIMOTESCONFIGURATION_POSITION, const wxSize& size = SYMBOL_WIIMOTESCONFIGURATION_SIZE, long style = SYMBOL_WIIMOTESCONFIGURATION_STYLE, const wxString& name= SYMBOL_WIIMOTESCONFIGURATION_TITLE );
+
+    /// Destructor
+    ~WiimotesConfiguration();
+
+protected:
+//	virtual void CameraCaptureCallback (SmartPtr<const mod_camera::CTypeIplImage> img);
+	virtual void StatusNotification (const CTypeWiimotesStatus &);
+	virtual void WiimoteNotification (wiimote *) {  /* void  */	};
+
+private:
+    /// Initialises member variables
+    void Init();
+
+    /// Creates the controls and sizers
+    void CreateControls();
+
+////@begin WiimotesConfiguration event handler declarations
+
+    /// wxEVT_COMMAND_BUTTON_CLICKED event handler for ID_BUTTON_RECONNECT
+    void OnButtonReconnectClick( wxCommandEvent& event );
+
+////@end WiimotesConfiguration event handler declarations
+
+////@begin WiimotesConfiguration member function declarations
+
+    /// Retrieves bitmap resources
+    wxBitmap GetBitmapResource( const wxString& name );
+
+    /// Retrieves icon resources
+    wxIcon GetIconResource( const wxString& name );
+////@end WiimotesConfiguration member function declarations
+
+    /// Should we show tooltips?
+    static bool ShowToolTips();
+
+	void StatusNotificationGUI( wxCommandEvent& );
+
+////@begin WiimotesConfiguration member variables
+    Wiimotesproperties* m_panProperties_1;
+    Wiimotesproperties* m_panProperties_2;
+    Wiimotesproperties* m_panProperties_3;
+    Wiimotesproperties* m_panProperties_4;
+////@end WiimotesConfiguration member variables
+
+	SmartPtr<CTypeWiimotesStatus> m_sharedStatus, m_privateStatus;
+	boost::mutex m_mutex;
+};
+
+}
+
+#endif
+    // _WWIIMOTESCONFIGURATION_H_
diff --git a/src/mod_wiimotes/wwiimotesproperties.cpp b/src/mod_wiimotes/wwiimotesproperties.cpp
new file mode 100755
index 0000000..f0d5d71
--- /dev/null
+++ b/src/mod_wiimotes/wwiimotesproperties.cpp
@@ -0,0 +1,240 @@
+/////////////////////////////////////////////////////////////////////////////
+// Name:        wiimotesproperties.cpp
+// Purpose:     
+// Author:      C�sar Mauri Loba
+// Modified by: 
+// Created:     18/03/2011 13:00:20
+// RCS-ID:      
+// Copyright:   (C) 2011 Cesar Mauri Loba - CREA Software Systems
+// 
+//  This program is free software: you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation, either version 3 of the License, or
+//  (at your option) any later version.
+//
+//  This program is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with this program.  If not, see <http://www.gnu.org/licenses/>.    
+/////////////////////////////////////////////////////////////////////////////
+
+// For compilers that support precompilation, includes "wx/wx.h".
+#include "wx/wxprec.h"
+
+#ifdef __BORLANDC__
+#pragma hdrstop
+#endif
+
+#ifndef WX_PRECOMP
+#include "wx/wx.h"
+#endif
+
+////@begin includes
+////@end includes
+
+#include "wwiimotesproperties.h"
+
+////@begin XPM images
+#include "icons/none.xpm"
+////@end XPM images
+#include "icons/balance-board.xpm"
+#include "icons/wiimote-small.xpm"
+
+namespace mod_wiimotes {
+
+/*!
+ * Wiimotesproperties type definition
+ */
+
+IMPLEMENT_DYNAMIC_CLASS( Wiimotesproperties, wxPanel )
+
+
+/*!
+ * Wiimotesproperties event table definition
+ */
+
+BEGIN_EVENT_TABLE( Wiimotesproperties, wxPanel )
+
+////@begin Wiimotesproperties event table entries
+////@end Wiimotesproperties event table entries
+
+END_EVENT_TABLE()
+
+
+/*!
+ * Wiimotesproperties constructors
+ */
+
+Wiimotesproperties::Wiimotesproperties()
+{
+    Init();
+}
+
+Wiimotesproperties::Wiimotesproperties( wxWindow* parent, wxWindowID id, const wxPoint& pos, const wxSize& size, long style )
+{
+    Init();
+    Create(parent, id, pos, size, style);
+}
+
+
+/*!
+ * Wiimotesproperties creator
+ */
+
+bool Wiimotesproperties::Create( wxWindow* parent, wxWindowID id, const wxPoint& pos, const wxSize& size, long style )
+{
+////@begin Wiimotesproperties creation
+    wxPanel::Create( parent, id, pos, size, style );
+
+    CreateControls();
+    if (GetSizer())
+    {
+        GetSizer()->SetSizeHints(this);
+    }
+    Centre();
+////@end Wiimotesproperties creation
+    return true;
+}
+
+
+/*!
+ * Wiimotesproperties destructor
+ */
+
+Wiimotesproperties::~Wiimotesproperties()
+{
+////@begin Wiimotesproperties destruction
+////@end Wiimotesproperties destruction
+}
+
+
+/*!
+ * Member initialisation
+ */
+
+void Wiimotesproperties::Init()
+{
+////@begin Wiimotesproperties member initialisation
+    m_icon = NULL;
+    m_chkConnected = NULL;
+    m_chkAcc = NULL;
+    m_chkNunchuck = NULL;
+    m_chkMotionPlus = NULL;
+////@end Wiimotesproperties member initialisation
+}
+
+
+/*!
+ * Control creation for Wiimotesproperties
+ */
+
+void Wiimotesproperties::CreateControls()
+{    
+////@begin Wiimotesproperties content construction
+    Wiimotesproperties* itemPanel1 = this;
+
+    wxBoxSizer* itemBoxSizer2 = new wxBoxSizer(wxHORIZONTAL);
+    itemPanel1->SetSizer(itemBoxSizer2);
+
+    m_icon = new wxStaticBitmap;
+    m_icon->Create( itemPanel1, wxID_ICON, itemPanel1->GetBitmapResource(wxT("icons/none.xpm")), wxDefaultPosition, wxSize(64, 42), 0 );
+    itemBoxSizer2->Add(m_icon, 0, wxALIGN_TOP|wxALL, 5);
+
+    wxGridSizer* itemGridSizer4 = new wxGridSizer(2, 2, 0, 0);
+    itemBoxSizer2->Add(itemGridSizer4, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5);
+
+    m_chkConnected = new wxCheckBox;
+    m_chkConnected->Create( itemPanel1, ID_CHK_CONNECTED, _("Connected"), wxDefaultPosition, wxDefaultSize, 0 );
+    m_chkConnected->SetValue(false);
+    m_chkConnected->Enable(false);
+    itemGridSizer4->Add(m_chkConnected, 0, wxALIGN_LEFT|wxALIGN_CENTER_VERTICAL|wxALL, 5);
+
+    m_chkAcc = new wxCheckBox;
+    m_chkAcc->Create( itemPanel1, ID_CHK_ACC, _("Accelerometers enabled"), wxDefaultPosition, wxDefaultSize, 0 );
+    m_chkAcc->SetValue(false);
+    m_chkAcc->Enable(false);
+    itemGridSizer4->Add(m_chkAcc, 0, wxALIGN_LEFT|wxALIGN_CENTER_VERTICAL|wxALL, 5);
+
+    m_chkNunchuck = new wxCheckBox;
+    m_chkNunchuck->Create( itemPanel1, ID_CHK_NUNCHUCK, _("Nunchuck enabled"), wxDefaultPosition, wxDefaultSize, 0 );
+    m_chkNunchuck->SetValue(false);
+    m_chkNunchuck->Enable(false);
+    itemGridSizer4->Add(m_chkNunchuck, 0, wxALIGN_LEFT|wxALIGN_CENTER_VERTICAL|wxALL, 5);
+
+    m_chkMotionPlus = new wxCheckBox;
+    m_chkMotionPlus->Create( itemPanel1, ID_CHK_MOTION_PLUS, _("Motion plus enabled"), wxDefaultPosition, wxDefaultSize, 0 );
+    m_chkMotionPlus->SetValue(false);
+    m_chkMotionPlus->Enable(false);
+    itemGridSizer4->Add(m_chkMotionPlus, 0, wxALIGN_LEFT|wxALIGN_CENTER_VERTICAL|wxALL, 5);
+
+////@end Wiimotesproperties content construction
+}
+
+
+/*!
+ * Should we show tooltips?
+ */
+
+bool Wiimotesproperties::ShowToolTips()
+{
+    return true;
+}
+
+/*!
+ * Get bitmap resources
+ */
+
+wxBitmap Wiimotesproperties::GetBitmapResource( const wxString& name )
+{
+    // Bitmap retrieval
+////@begin Wiimotesproperties bitmap retrieval
+    wxUnusedVar(name);
+    if (name == _T("icons/none.xpm"))
+    {
+        wxBitmap bitmap(none);
+        return bitmap;
+    }
+    return wxNullBitmap;
+////@end Wiimotesproperties bitmap retrieval
+}
+
+/*!
+ * Get icon resources
+ */
+
+wxIcon Wiimotesproperties::GetIconResource( const wxString& name )
+{
+    // Icon retrieval
+////@begin Wiimotesproperties icon retrieval
+    wxUnusedVar(name);
+    return wxNullIcon;
+////@end Wiimotesproperties icon retrieval
+}
+
+void Wiimotesproperties::Update (const CTypeWiimotesStatus & status, unsigned int n)
+{
+	if (status.IsConnected(n)) {
+		m_chkConnected->SetValue(true);
+		if (status.HasBalanceBoard(n)) {
+			m_icon->SetBitmap(wxBitmap(balance_board));
+		}
+		else {
+			m_icon->SetBitmap(wxBitmap(wiimote_small));
+			m_chkAcc->SetValue(status.IsAccelerometersEnabled(n));
+			m_chkMotionPlus->SetValue(status.IsMotionPlusEnabled(n));
+			m_chkNunchuck->SetValue(status.IsNunchuckEnabled(n));				
+		}
+	}
+	else {
+		m_chkConnected->SetValue(false);
+		m_icon->SetBitmap(wxBitmap(none));
+		m_chkAcc->SetValue(false);
+		m_chkMotionPlus->SetValue(false);
+		m_chkNunchuck->SetValue(false);
+	}
+}
+
+};
diff --git a/src/mod_wiimotes/wwiimotesproperties.h b/src/mod_wiimotes/wwiimotesproperties.h
new file mode 100755
index 0000000..95e3c44
--- /dev/null
+++ b/src/mod_wiimotes/wwiimotesproperties.h
@@ -0,0 +1,122 @@
+/////////////////////////////////////////////////////////////////////////////
+// Name:        wiimotesproperties.h
+// Purpose:     
+// Author:      C�sar Mauri Loba
+// Modified by: 
+// Created:     18/03/2011 13:00:20
+// RCS-ID:      
+// Copyright:   (C) 2011 Cesar Mauri Loba - CREA Software Systems
+// 
+//  This program is free software: you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation, either version 3 of the License, or
+//  (at your option) any later version.
+//
+//  This program is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with this program.  If not, see <http://www.gnu.org/licenses/>.     
+/////////////////////////////////////////////////////////////////////////////
+
+#ifndef _WIIMOTESPROPERTIES_H_
+#define _WIIMOTESPROPERTIES_H_
+
+
+/*!
+ * Includes
+ */
+
+#include "mod_wiimotes/wiimotes_types.h"
+////@begin includes
+////@end includes
+#include <wx/statbmp.h>
+#include <wx/panel.h>
+
+
+/*!
+ * Forward declarations
+ */
+
+////@begin forward declarations
+////@end forward declarations
+
+/*!
+ * Control identifiers
+ */
+
+////@begin control identifiers
+#define ID_WIIMOTESPROPERTIES 10005
+#define wxID_ICON 10004
+#define ID_CHK_CONNECTED 10003
+#define ID_CHK_ACC 10000
+#define ID_CHK_NUNCHUCK 10001
+#define ID_CHK_MOTION_PLUS 10002
+#define SYMBOL_WIIMOTESPROPERTIES_STYLE 0
+//#define SYMBOL_WIIMOTESPROPERTIES_TITLE _("Wiimotes properties")
+#define SYMBOL_WIIMOTESPROPERTIES_IDNAME ID_WIIMOTESPROPERTIES
+#define SYMBOL_WIIMOTESPROPERTIES_SIZE wxDefaultSize
+#define SYMBOL_WIIMOTESPROPERTIES_POSITION wxDefaultPosition
+////@end control identifiers
+
+namespace mod_wiimotes {
+
+/*!
+ * Wiimotesproperties class declaration
+ */
+
+class Wiimotesproperties: public wxPanel
+{    
+    DECLARE_DYNAMIC_CLASS( Wiimotesproperties )
+    DECLARE_EVENT_TABLE()
+
+public:
+    /// Constructors
+    Wiimotesproperties();
+    Wiimotesproperties( wxWindow* parent, wxWindowID id = SYMBOL_WIIMOTESPROPERTIES_IDNAME, const wxPoint& pos = SYMBOL_WIIMOTESPROPERTIES_POSITION, const wxSize& size = SYMBOL_WIIMOTESPROPERTIES_SIZE, long style = SYMBOL_WIIMOTESPROPERTIES_STYLE );
+
+    /// Creation
+    bool Create( wxWindow* parent, wxWindowID id = SYMBOL_WIIMOTESPROPERTIES_IDNAME, const wxPoint& pos = SYMBOL_WIIMOTESPROPERTIES_POSITION, const wxSize& size = SYMBOL_WIIMOTESPROPERTIES_SIZE, long style = SYMBOL_WIIMOTESPROPERTIES_STYLE );
+
+    /// Destructor
+    ~Wiimotesproperties();
+    
+    void Update (const CTypeWiimotesStatus &, unsigned int n);
+private:
+    /// Initialises member variables
+    void Init();
+
+    /// Creates the controls and sizers
+    void CreateControls();
+
+////@begin Wiimotesproperties event handler declarations
+
+////@end Wiimotesproperties event handler declarations
+
+////@begin Wiimotesproperties member function declarations
+
+    /// Retrieves bitmap resources
+    wxBitmap GetBitmapResource( const wxString& name );
+
+    /// Retrieves icon resources
+    wxIcon GetIconResource( const wxString& name );
+////@end Wiimotesproperties member function declarations
+
+    /// Should we show tooltips?
+    static bool ShowToolTips();
+
+////@begin Wiimotesproperties member variables
+    wxStaticBitmap* m_icon;
+    wxCheckBox* m_chkConnected;
+    wxCheckBox* m_chkAcc;
+    wxCheckBox* m_chkNunchuck;
+    wxCheckBox* m_chkMotionPlus;
+////@end Wiimotesproperties member variables
+};
+
+};
+
+#endif
+    // _WIIMOTESPROPERTIES_H_
diff --git a/src/widgets_base/CMakeLists.txt b/src/widgets_base/CMakeLists.txt
new file mode 100755
index 0000000..3c43b3b
--- /dev/null
+++ b/src/widgets_base/CMakeLists.txt
@@ -0,0 +1,42 @@
+cmake_minimum_required(VERSION 2.6)
+project(widgets_base)
+
+set (SPWIDGETSBASE_MAJOR_VERSION ${LIBSITPLUS_MAJOR_VERSION})
+set (SPWIDGETSBASE_RELEASE_VERSION ${LIBSITPLUS_MINOR_VERSION})
+set (SPWIDGETSBASE_EPOCH_VERSION ${LIBSITPLUS_REVISION_VERSION})
+
+set(widgets_base_HEADERS
+	${CUSTOM_INCLUDE_PATH}/widgets_base/containerpanel.h
+	${CUSTOM_INCLUDE_PATH}/widgets_base/dialogcontainer.h
+	${CUSTOM_INCLUDE_PATH}/widgets_base/mdichildcontainer.h
+	${CUSTOM_INCLUDE_PATH}/widgets_base/containerbook.h
+	${CUSTOM_INCLUDE_PATH}/widgets_base/containercollapsible.h
+	${CUSTOM_INCLUDE_PATH}/widgets_base/libimpexp_widgetsbase.h
+)
+set(widgets_base_SRCS
+	${widgets_base_HEADERS}
+	containerpanel.cpp	
+	dialogcontainer.cpp	
+	mdichildcontainer.cpp	
+	containerbook.cpp	
+	containercollapsible.cpp
+)
+
+#
+# This library should always be shared because several
+# plugings might use it.
+#
+
+add_library (widgets_base SHARED ${widgets_base_SRCS})
+target_link_libraries(widgets_base ${wxWidgets_LIBRARIES})
+
+
+add_definitions(-DSPMAKING_DLL_SPWIDGETSBASE)
+#add_definitions(-DSPUSING_DLL)
+
+set_target_properties(widgets_base PROPERTIES 
+	VERSION "${SPWIDGETSBASE_MAJOR_VERSION}.${SPWIDGETSBASE_RELEASE_VERSION}.${SPWIDGETSBASE_EPOCH_VERSION}"
+	SOVERSION ${SPWIDGETSBASE_MAJOR_VERSION}
+)
+install (FILES ${widgets_base_HEADERS} DESTINATION ${INCLUDEDIR}/${PROJECT_NAME})
+INSTALL (TARGETS widgets_base RUNTIME DESTINATION ${LIBRUNTIMEDIR} LIBRARY DESTINATION ${LIBDIR} ARCHIVE DESTINATION ${LIBDIR})
diff --git a/src/widgets_base/bitmaps/sitplus.ico b/src/widgets_base/bitmaps/sitplus.ico
new file mode 100755
index 0000000..b40c55b
Binary files /dev/null and b/src/widgets_base/bitmaps/sitplus.ico differ
diff --git a/src/widgets_base/bitmaps/sitplus_logo_16x16.xpm b/src/widgets_base/bitmaps/sitplus_logo_16x16.xpm
new file mode 100755
index 0000000..64b09d7
--- /dev/null
+++ b/src/widgets_base/bitmaps/sitplus_logo_16x16.xpm
@@ -0,0 +1,156 @@
+/* XPM */
+static const char *sitplus_logo_16x16[] = {
+/* columns rows colors chars-per-pixel */
+"16 16 134 2",
+"   c #003466",
+".  c #003668",
+"X  c #00396B",
+"o  c #003B6D",
+"O  c #003C6E",
+"+  c #003D6F",
+"@  c #004072",
+"#  c #004274",
+"$  c #004376",
+"%  c #004476",
+"&  c #004D7F",
+"*  c #084676",
+"=  c #144978",
+"-  c #004F82",
+";  c #005183",
+":  c #005385",
+">  c #005486",
+",  c #005588",
+"<  c #005789",
+"1  c #00588A",
+"2  c #005A8C",
+"3  c #006193",
+"4  c #006194",
+"5  c #006295",
+"6  c #00679A",
+"7  c #00689A",
+"8  c #006A9D",
+"9  c #006B9D",
+"0  c #006B9E",
+"q  c #006C9E",
+"w  c #006DA0",
+"e  c #006EA0",
+"r  c #0071A4",
+"t  c #0072A4",
+"y  c #0075A7",
+"u  c #0076A9",
+"i  c #0078AA",
+"p  c #0079AB",
+"a  c #0079AC",
+"s  c #007AAC",
+"d  c #007DB0",
+"f  c #2E739C",
+"g  c #0099CB",
+"h  c #0099CC",
+"j  c #069BCC",
+"k  c #0C9ECD",
+"l  c #12A0CF",
+"z  c #1AA3D0",
+"x  c #1CA4D1",
+"c  c #1EA5D1",
+"v  c #1FA5D1",
+"b  c #00B8EB",
+"n  c #00BCEF",
+"m  c #239AC6",
+"M  c #2AAAD4",
+"N  c #34AED6",
+"B  c #39B0D6",
+"V  c #00C1F4",
+"C  c #00C4F7",
+"Z  c #00CCFF",
+"A  c #0CCEFF",
+"S  c #19C4F2",
+"D  c #32D6FF",
+"F  c #47B5D9",
+"G  c #50B9DB",
+"H  c #56BBDC",
+"J  c #57BCDD",
+"K  c #59BDDD",
+"L  c #5EBFDE",
+"P  c #62BDDC",
+"I  c #40D9FF",
+"U  c #4BDBFF",
+"Y  c #4EDCFF",
+"T  c #52DCFF",
+"R  c #59DEFF",
+"E  c #5CDEFF",
+"W  c #5DDFFF",
+"Q  c #6DC4E1",
+"!  c #6EC5E1",
+"~  c #74C7E3",
+"^  c #7ACAE4",
+"/  c #7BCAE4",
+"(  c #7DCBE4",
+")  c #7ECBE5",
+"_  c #64E0FF",
+"`  c #67E1FF",
+"'  c #69E1FF",
+"]  c #70E2FF",
+"[  c #75E3FF",
+"{  c #7CE3FD",
+"}  c #7EE5FF",
+"|  c #95C8DD",
+" . c #9DCADD",
+".. c #80CCE5",
+"X. c #81CDE5",
+"o. c #8AD0E7",
+"O. c #8CD1E8",
+"+. c #96D7EC",
+"@. c #9AD7EA",
+"#. c #98DBEF",
+"$. c #84E2FA",
+"%. c #97E1F5",
+"&. c #99E6FA",
+"*. c #ABDFEE",
+"=. c #AFDFEF",
+"-. c #A2DEF0",
+";. c #A7E0F1",
+":. c #A3E8FB",
+">. c #ADE2F2",
+",. c #ADEFFF",
+"<. c #B4E4F3",
+"1. c #B4ECFB",
+"2. c #B9E3F1",
+"3. c #B8EDFB",
+"4. c #B6F0FF",
+"5. c #BEF0FD",
+"6. c #C5EBF6",
+"7. c #C7EAF4",
+"8. c #D3F4FC",
+"9. c #DAF0F7",
+"0. c #D8F7FF",
+"q. c #DFF4FA",
+"w. c #E1F3F9",
+"e. c #E0F7FD",
+"r. c #E6F7FB",
+"t. c #E7F7FC",
+"y. c #E7F9FE",
+"u. c #ECFBFE",
+"i. c #EEFAFE",
+"p. c #F3FBFD",
+"a. c #F2FCFE",
+"s. c #F2FCFF",
+"d. c gray100",
+"f. c None",
+/* pixels */
+"f.f.f.f.f.p 0 6 6 0 p f.f.f.f.f.",
+"f.f.f.p > O < 0 e > . > p f.f.f.",
+"f.f.u % d V Z Z Z Z C t @ u f.f.",
+"f.p # w.} D Z A T R Z Z h # a f.",
+"f.f | e.y.8.i.5.a.&.Z Z Z t > f.",
+"p = i.r.p.t.q.<.7.:.' _ W S X p ",
+"0 < Y ;.x g z j M / X./ *.T - 0 ",
+"6 0 Z 1.B ( G g g J @.O./ ' 6 6 ",
+"6 6 Z 1.! ,.9.g x 0.] 2.! [ 5 6 ",
+"0 1 Z 1.H =.~ g l a.4.K L $.& 0 ",
+"a O n 1.x g g g h k N g F %.. p ",
+"f.> a 3.X.) X.o.+.#.-.>.6. .> f.",
+"f.s % P { ' _ W Y U I D m * a f.",
+"f.f.u @ t C Z Z Z Z b q @ u f.f.",
+"f.f.f.p ; o ; 5 3 ; X > a f.f.f.",
+"f.f.f.f.f.p 0 6 6 0 a f.f.f.f.f."
+};
diff --git a/src/widgets_base/bitmaps/sitplus_logo_32x32.xpm b/src/widgets_base/bitmaps/sitplus_logo_32x32.xpm
new file mode 100755
index 0000000..de1422f
--- /dev/null
+++ b/src/widgets_base/bitmaps/sitplus_logo_32x32.xpm
@@ -0,0 +1,148 @@
+/* XPM */
+static const char *sitplus_logo_32x32[] = {
+/* columns rows colors chars-per-pixel */
+"32 32 110 2",
+"   c #003466",
+".  c #005285",
+"X  c #005688",
+"o  c #005A8C",
+"O  c #005E90",
+"+  c #006294",
+"@  c #006698",
+"#  c #00699B",
+"$  c #006EA0",
+"%  c #0071A4",
+"&  c #007CAE",
+"*  c #007EB0",
+"=  c #0081B4",
+"-  c #0085B8",
+";  c #008DB0",
+":  c #0089BB",
+">  c #0099BF",
+",  c #008EC1",
+"<  c #0094C6",
+"1  c #0095C8",
+"2  c #0099CB",
+"3  c #0B9ECD",
+"4  c #009ED0",
+"5  c #109FCE",
+"6  c #00A6CF",
+"7  c #00A3D5",
+"8  c #00A6D9",
+"9  c #00A8DA",
+"0  c #14A1CF",
+"q  c #1BA4D0",
+"w  c #00AFE2",
+"e  c #00B4E7",
+"r  c #00B5E8",
+"t  c #00BAED",
+"y  c #00BEF1",
+"u  c #2697C3",
+"i  c #22A6D2",
+"p  c #27A9D3",
+"a  c #2BAAD3",
+"s  c #38A6CE",
+"d  c #30ACD5",
+"f  c #38AFD6",
+"g  c #3AB0D7",
+"h  c #3FB2D8",
+"j  c #2CBCE0",
+"k  c #00C2F5",
+"l  c #00C5F8",
+"z  c #00CBFE",
+"x  c #11CEFD",
+"c  c #13D0FF",
+"v  c #1DD1FF",
+"b  c #21D3FF",
+"n  c #2CD4FF",
+"m  c #35D3FC",
+"M  c #3ED8FF",
+"N  c #41B3D8",
+"B  c #4AB6DA",
+"V  c #4EB8DB",
+"C  c #52BADB",
+"Z  c #5BBDDD",
+"A  c #44D9FF",
+"S  c #4BDBFF",
+"D  c #51DCFF",
+"F  c #5DDFFF",
+"G  c #63C1DF",
+"H  c #6CC4E0",
+"J  c #71C6E2",
+"K  c #76C8E3",
+"L  c #7CCAE4",
+"P  c #64E0FF",
+"I  c #6AE1FF",
+"U  c #74E3FF",
+"Y  c #7AE3FE",
+"T  c #82CDE5",
+"R  c #8AD0E7",
+"E  c #8FD2E8",
+"W  c #94D4EA",
+"Q  c #99D8EB",
+"!  c #82E5FE",
+"~  c #8CE6FC",
+"^  c #8AE8FF",
+"/  c #97E5F9",
+"(  c #9AE6FA",
+")  c #9AEAFE",
+"_  c #A3DBED",
+"`  c #AEDFEE",
+"'  c #A4E8FA",
+"]  c #ADE2F2",
+"[  c #ACECFC",
+"{  c #B3E5F4",
+"}  c #B2EDFC",
+"|  c #BAE3F1",
+" . c #BAE9F6",
+".. c #BAECFA",
+"X. c #BAF1FF",
+"o. c #C4E9F4",
+"O. c #C4EEF9",
+"+. c #CAEDF7",
+"@. c #CAEEF8",
+"#. c #C5F0FD",
+"$. c #CEF0FA",
+"%. c #D4EEF6",
+"&. c #D3F3FB",
+"*. c #DBF4FA",
+"=. c #E7F7FC",
+"-. c #E7F8FC",
+";. c #EFFAFD",
+":. c #F4FCFE",
+">. c gray100",
+",. c None",
+/* pixels */
+",.,.,.,.,.,.,.,.,.,.,.,.,.,.= = & = ,.,.,.,.,.,.,.,.,.,.,.,.,.,.",
+",.,.,.,.,.,.,.,.,.,.= % + X @ @ @ + o o # = ,.,.,.,.,.,.,.,.,.,.",
+",.,.,.,.,.,.,.,.= @ @ = 9 k l z z z l 9 - @ + & ,.,.,.,.,.,.,.,.",
+",.,.,.,.,.,.: # @ 2 k z z z z z z z z z z l 2 @ @ : ,.,.,.,.,.,.",
+",.,.,.,.,.= O - t z z z z z z z z z z z z z z k - X = ,.,.,.,.,.",
+",.,.,.,.= o s A z z z z z z z z z z z z z z z z z 2 o = ,.,.,.,.",
+",.,.,.: o < Y &.z z z z z z z z z z x z z z z z z l 1 X : ,.,.,.",
+",.,.,.# = z I *.v U D z S z z z ) A :.z z z z z z z z : @ ,.,.,.",
+",.,.= @ t z P o.P &...n *.n z ^ *.' :.z z z z z z z z k % & ,.,.",
+",.,.@ o.$.A P _ #.{ *.^ | I D @.o. .>.z z z z z z z z z 7 o ,.,.",
+",.= + m @.] ..K :.J _ @.G [ { p o.H >.z z z z z z z z z l @ & ,.",
+",.$ = l ! W Z C 0 0 C ] 0 *.N 2 i 3 >.P P I P P P P n z z < # ,.",
+",.o 8 z x ' h 2 2 2 2 2 2 d 2 2 2 2 V L L T L L L T -.z z r X ,.",
+",.o k z z A +.2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 :.z z l X - ",
+"= @ z z z z } B 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 %.v z z + = ",
+"= # z z z z [ V 2 0 g q 2 2 2 2 2 2 2 2 h R R Z 2 2 O.n z z # & ",
+"= @ z z z z ' V q o.[ _ i 2 2 2 2 2 2 N } P ^ | 0 2  .M z z @ = ",
+"= @ z z z z [ V E Y > ^ C 2 2 2 2 2 2 | S 6 x X.q 2 Q F z z + = ",
+",.X l z z z [ V G ) j X.h 2 2 2 2 2 q &.z ; U T 2 2 R I z z X = ",
+",.@ w z z z ( B 5 Q ` J 2 2 2 2 2 2 3 %.Y Y | q 2 2 H ^ z r X ,.",
+",.% : z z z ' B 2 2 2 2 2 2 2 2 2 2 2 0 W E q 2 2 2 Z ) z - $ ,.",
+",.= @ k z z ' B 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 N ..l @ & ,.",
+",.,.@ 2 z z ' V 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 a #.4 + ,.,.",
+",.,.= @ t l ' V 2 2 2 2 3 0 q p a g B B C Z G J K L W -.# & ,.,.",
+",.,.,.@ & l ' o. .O.O.$. at .O...} [ [ / / ~ ^ ! U U I F u @ ,.,.,.",
+",.,.,.: + < x v b x x z z z z z z z z z l z z z z l 1 o - ,.,.,.",
+",.,.,.,.= o : l z z z z z z z z z z z z z z z z z < o = ,.,.,.,.",
+",.,.,.,.,.- + = t z z z z z z z z z z z z z z t = X = ,.,.,.,.,.",
+",.,.,.,.,.,.: % + 2 k z z z z z z z z z z l 2 # # : ,.,.,.,.,.,.",
+",.,.,.,.,.,.,.,.= @ o & 7 t z z z z k 7 & O # = ,.,.,.,.,.,.,.,.",
+",.,.,.,.,.,.,.,.,.,.= % O . X + + o X + % = ,.,.,.,.,.,.,.,.,.,.",
+",.,.,.,.,.,.,.,.,.,.,.,.,.,.= = = = ,.,.,.,.,.,.,.,.,.,.,.,.,.,."
+};
diff --git a/src/widgets_base/containerbook.cpp b/src/widgets_base/containerbook.cpp
new file mode 100755
index 0000000..191b48a
--- /dev/null
+++ b/src/widgets_base/containerbook.cpp
@@ -0,0 +1,192 @@
+/////////////////////////////////////////////////////////////////////////////
+// Name:        custombook.cpp
+// Purpose:     
+// Author:      C�sar Mauri Loba
+// Modified by: 
+// Created:     23/05/2011 18:51:40
+// RCS-ID:      
+// Copyright:   (C) 2011 Cesar Mauri Loba - CREA Software Systems
+// 
+//  This program is free software: you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation, either version 3 of the License, or
+//  (at your option) any later version.
+//
+//  This program is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with this program.  If not, see <http://www.gnu.org/licenses/>.   
+/////////////////////////////////////////////////////////////////////////////
+
+// For compilers that support precompilation, includes "wx/wx.h".
+
+#include "wx/wxprec.h"
+
+#ifdef __BORLANDC__
+#pragma hdrstop
+#endif
+
+#ifndef WX_PRECOMP
+#include "wx/wx.h"
+#endif
+
+
+////@begin includes
+#include "wx/imaglist.h"
+////@end includes
+
+#include "widgets_base/containerbook.h"
+
+////@begin XPM images
+////@end XPM images
+
+//namespace widgets_base {
+
+/*
+ * ContainerBook type definition
+ */
+
+IMPLEMENT_DYNAMIC_CLASS( ContainerBook, wxNotebook )
+
+
+/*
+ * ContainerBook event table definition
+ */
+
+BEGIN_EVENT_TABLE( ContainerBook, wxNotebook )
+
+////@begin ContainerBook event table entries
+    EVT_SIZE( ContainerBook::OnSize )
+
+////@end ContainerBook event table entries
+
+END_EVENT_TABLE()
+
+
+/*
+ * ContainerBook constructors
+ */
+
+ContainerBook::ContainerBook()
+{
+    Init();
+}
+
+ContainerBook::ContainerBook(wxWindow* parent, wxWindowID id, const wxPoint& pos, const wxSize& size, long style)
+{
+    Init();
+    Create(parent, id, pos, size, style);
+}
+
+
+/*
+ * CustomBook creator
+ */
+
+bool ContainerBook::Create(wxWindow* parent, wxWindowID id, const wxPoint& pos, const wxSize& size, long style)
+{
+////@begin ContainerBook creation
+    wxNotebook::Create(parent, id, pos, size, style);
+    CreateControls();
+////@end ContainerBook creation
+    return true;
+}
+
+
+/*
+ * ContainerBook destructor
+ */
+
+ContainerBook::~ContainerBook()
+{
+////@begin ContainerBook destruction
+////@end ContainerBook destruction
+}
+
+
+/*
+ * Member initialisation
+ */
+
+void ContainerBook::Init()
+{
+////@begin ContainerBook member initialisation
+////@end ContainerBook member initialisation
+}
+
+
+/*
+ * Control creation for CustomBook
+ */
+
+void ContainerBook::CreateControls()
+{    
+////@begin ContainerBook content construction
+////@end ContainerBook content construction
+}
+
+
+/*
+ * Should we show tooltips?
+ */
+
+bool ContainerBook::ShowToolTips()
+{
+    return true;
+}
+
+/*
+ * Get bitmap resources
+ */
+
+wxBitmap ContainerBook::GetBitmapResource( const wxString& name )
+{
+    // Bitmap retrieval
+////@begin ContainerBook bitmap retrieval
+    wxUnusedVar(name);
+    return wxNullBitmap;
+////@end ContainerBook bitmap retrieval
+}
+
+/*
+ * Get icon resources
+ */
+
+wxIcon ContainerBook::GetIconResource( const wxString& name )
+{
+    // Icon retrieval
+////@begin ContainerBook icon retrieval
+    wxUnusedVar(name);
+    return wxNullIcon;
+////@end ContainerBook icon retrieval
+}
+
+
+/*
+ * wxEVT_SIZE event handler for ID_NOTEBOOK
+ */
+
+void ContainerBook::OnSize( wxSizeEvent& event )
+{
+	if (event.GetSize().GetX() || event.GetSize().GetY())
+		wxNotebook::OnSize(event);
+	else {
+//		wxSize sbef= GetSize();
+		Layout();
+		Fit();
+
+//		wxSize safter= GetSize();
+
+//		if (sbef!= safter) {
+			wxSizeEvent evt;
+			wxPostEvent (GetParent(), evt);
+//		}
+		event.Skip(false);
+	}
+}
+
+//};
+
diff --git a/src/widgets_base/containercollapsible.cpp b/src/widgets_base/containercollapsible.cpp
new file mode 100755
index 0000000..5fd4ad1
--- /dev/null
+++ b/src/widgets_base/containercollapsible.cpp
@@ -0,0 +1,177 @@
+/////////////////////////////////////////////////////////////////////////////
+// Name:        containercollapsible.cpp
+// Purpose:     
+// Author:      C�sar Mauri Loba
+// Modified by: 
+// Created:     01/06/2011 16:25:48
+// RCS-ID:      
+// Copyright:   (C) 2011 Cesar Mauri Loba - CREA Software Systems
+// 
+//  This program is free software: you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation, either version 3 of the License, or
+//  (at your option) any later version.
+//
+//  This program is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with this program.  If not, see <http://www.gnu.org/licenses/>.    
+/////////////////////////////////////////////////////////////////////////////
+
+// For compilers that support precompilation, includes "wx/wx.h".
+#include "wx/wxprec.h"
+
+#ifdef __BORLANDC__
+#pragma hdrstop
+#endif
+
+#ifndef WX_PRECOMP
+#include "wx/wx.h"
+#endif
+
+////@begin includes
+////@end includes
+
+#include "widgets_base/containercollapsible.h"
+
+////@begin XPM images
+////@end XPM images
+
+namespace widgets_base {
+/*
+ * ContainerCollapsible type definition
+ */
+
+IMPLEMENT_DYNAMIC_CLASS( ContainerCollapsible, wxGenericCollapsiblePane )
+
+
+/*
+ * ContainerCollapsible event table definition
+ */
+
+BEGIN_EVENT_TABLE( ContainerCollapsible, wxGenericCollapsiblePane )
+
+////@begin ContainerCollapsible event table entries
+    EVT_COLLAPSIBLEPANE_CHANGED( ID_COLLAPSIBLEPANE, ContainerCollapsible::OnCollapsiblepanePaneChanged )
+
+////@end ContainerCollapsible event table entries
+
+END_EVENT_TABLE()
+
+
+/*
+ * ContainerCollapsible constructors
+ */
+
+ContainerCollapsible::ContainerCollapsible()
+{
+    Init();
+}
+
+ContainerCollapsible::ContainerCollapsible(wxWindow* parent, wxWindowID id, const wxString& label, const wxPoint& pos, const wxSize& size, long style, const wxValidator& validator)
+{
+    Init();
+    Create(parent, id, label, pos, size, style, validator);
+}
+
+
+/*
+ * ContainerCollapsible creator
+ */
+
+bool ContainerCollapsible::Create(wxWindow* parent, wxWindowID id, const wxString& label, const wxPoint& pos, const wxSize& size, long style, const wxValidator& validator)
+{
+////@begin ContainerCollapsible creation
+    wxGenericCollapsiblePane::Create(parent, id, label, pos, size, style, validator);
+    CreateControls();
+////@end ContainerCollapsible creation
+    return true;
+}
+
+
+/*
+ * ContainerCollapsible destructor
+ */
+
+ContainerCollapsible::~ContainerCollapsible()
+{
+////@begin ContainerCollapsible destruction
+////@end ContainerCollapsible destruction
+}
+
+
+/*
+ * Member initialisation
+ */
+
+void ContainerCollapsible::Init()
+{
+////@begin ContainerCollapsible member initialisation
+////@end ContainerCollapsible member initialisation
+}
+
+
+/*
+ * Control creation for ContainerCollapsible
+ */
+
+void ContainerCollapsible::CreateControls()
+{    
+////@begin ContainerCollapsible content construction
+////@end ContainerCollapsible content construction
+}
+
+
+/*
+ * Should we show tooltips?
+ */
+
+bool ContainerCollapsible::ShowToolTips()
+{
+    return true;
+}
+
+/*
+ * Get bitmap resources
+ */
+
+wxBitmap ContainerCollapsible::GetBitmapResource( const wxString& name )
+{
+    // Bitmap retrieval
+////@begin ContainerCollapsible bitmap retrieval
+    wxUnusedVar(name);
+    return wxNullBitmap;
+////@end ContainerCollapsible bitmap retrieval
+}
+
+/*
+ * Get icon resources
+ */
+
+wxIcon ContainerCollapsible::GetIconResource( const wxString& name )
+{
+    // Icon retrieval
+////@begin ContainerCollapsible icon retrieval
+    wxUnusedVar(name);
+    return wxNullIcon;
+////@end ContainerCollapsible icon retrieval
+}
+
+
+/*
+ * wxEVT_COMMAND_COLLPANE_CHANGED event handler for ID_COLLAPSIBLEPANE
+ */
+
+void ContainerCollapsible::OnCollapsiblepanePaneChanged( wxCollapsiblePaneEvent& event )
+{
+	if (GetParent()) {
+		wxSizeEvent ev;
+		wxPostEvent (GetParent(), ev);
+	}
+    event.Skip(false);
+}
+
+}
diff --git a/src/widgets_base/containerpanel.cpp b/src/widgets_base/containerpanel.cpp
new file mode 100755
index 0000000..f0dd6a1
--- /dev/null
+++ b/src/widgets_base/containerpanel.cpp
@@ -0,0 +1,202 @@
+/////////////////////////////////////////////////////////////////////////////
+// Name:        wxcontainerpanel.cpp
+// Purpose:     
+// Author:      C�sar Mauri Loba
+// Modified by: 
+// Created:     10/05/2011 21:00:30
+// RCS-ID:      
+// Copyright:   (C) 2011 Cesar Mauri Loba - CREA Software Systems
+// 
+//  This program is free software: you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation, either version 3 of the License, or
+//  (at your option) any later version.
+//
+//  This program is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with this program.  If not, see <http://www.gnu.org/licenses/>.   
+/////////////////////////////////////////////////////////////////////////////
+
+// For compilers that support precompilation, includes "wx/wx.h".
+#include "wx/wxprec.h"
+
+#ifdef __BORLANDC__
+#pragma hdrstop
+#endif
+
+#ifndef WX_PRECOMP
+#include "wx/wx.h"
+#endif
+
+////@begin includes
+////@end includes
+
+#include "widgets_base/containerpanel.h"
+
+////@begin XPM images
+////@end XPM images
+
+namespace widgets_base {
+
+/*
+ * ContainerPanel type definition
+ */
+
+IMPLEMENT_DYNAMIC_CLASS( ContainerPanel, wxPanel )
+
+
+/*
+ * ContainerPanel event table definition
+ */
+
+BEGIN_EVENT_TABLE( ContainerPanel, wxPanel )
+
+////@begin ContainerPanel event table entries
+    EVT_SIZE( ContainerPanel::OnSize )
+
+////@end ContainerPanel event table entries
+
+END_EVENT_TABLE()
+
+
+/*
+ * ContainerPanel constructors
+ */
+
+ContainerPanel::ContainerPanel()
+{
+    Init();
+}
+
+ContainerPanel::ContainerPanel( wxWindow* parent, wxWindowID id, const wxPoint& pos, const wxSize& size, long style, const wxString& name )
+{
+    Init();
+    Create(parent, id, pos, size, style, name);
+}
+
+
+/*
+ * wxContainerPanel creator
+ */
+
+bool ContainerPanel::Create( wxWindow* parent, wxWindowID id, const wxPoint& pos, const wxSize& size, long style, const wxString& name  )
+{
+////@begin ContainerPanel creation
+    wxPanel::Create( parent, id, pos, size, style, name );
+
+    CreateControls();
+    Centre();
+////@end ContainerPanel creation
+    return true;
+}
+
+
+/*
+ * ContainerPanel destructor
+ */
+
+ContainerPanel::~ContainerPanel()
+{
+////@begin ContainerPanel destruction
+////@end ContainerPanel destruction
+}
+
+
+/*
+ * Member initialisation
+ */
+
+void ContainerPanel::Init()
+{
+////@begin ContainerPanel member initialisation
+////@end ContainerPanel member initialisation
+}
+
+
+/*
+ * Control creation for wxContainerPanel
+ */
+
+void ContainerPanel::CreateControls()
+{    
+////@begin ContainerPanel content construction
+////@end ContainerPanel content construction
+}
+
+
+/*
+ * Should we show tooltips?
+ */
+
+bool ContainerPanel::ShowToolTips()
+{
+    return true;
+}
+
+/*
+ * Get bitmap resources
+ */
+
+wxBitmap ContainerPanel::GetBitmapResource( const wxString& name )
+{
+    // Bitmap retrieval
+////@begin ContainerPanel bitmap retrieval
+    wxUnusedVar(name);
+    return wxNullBitmap;
+////@end ContainerPanel bitmap retrieval
+}
+
+/*
+ * Get icon resources
+ */
+
+wxIcon ContainerPanel::GetIconResource( const wxString& name )
+{
+    // Icon retrieval
+////@begin ContainerPanel icon retrieval
+    wxUnusedVar(name);
+    return wxNullIcon;
+////@end ContainerPanel icon retrieval
+}
+
+
+/*
+ * wxEVT_SIZE event handler for ID_WXCONTAINERPANEL
+ */
+
+void ContainerPanel::OnSize( wxSizeEvent& event )
+{
+	if (event.GetSize().GetX() || event.GetSize().GetY())
+		wxPanel::OnSize(event);
+	else {
+	//	wxSize sbef= GetSize();
+		Layout();
+		Fit();
+		
+		//wxPanel::OnSize(event);
+		//InvalidateBestSize();
+	//	wxSize safter= GetSize();
+
+	//	if (sbef!= safter) {
+			wxSizeEvent evt;
+			wxPostEvent (GetParent(), evt);
+	//	}
+	//	wxPostEvent(GetParent(), event);
+		event.Skip(false);
+	}
+}
+
+/*
+Works on windows, Infinite loop on linux
+
+wxPanel::OnSize(event);
+
+	wxPostEvent(GetParent(), event);
+	event.Skip(false); 
+	*/
+
+}
\ No newline at end of file
diff --git a/src/widgets_base/dialogcontainer.cpp b/src/widgets_base/dialogcontainer.cpp
new file mode 100755
index 0000000..2b7e789
--- /dev/null
+++ b/src/widgets_base/dialogcontainer.cpp
@@ -0,0 +1,206 @@
+/////////////////////////////////////////////////////////////////////////////
+// Name:        dialogcontainer.cpp
+// Purpose:     
+// Author:      C�sar Mauri Loba
+// Modified by: 
+// Created:     04/04/2011 18:59:05
+// RCS-ID:      
+// Copyright:   (C) 2011 Cesar Mauri Loba - CREA Software Systems
+// 
+//  This program is free software: you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation, either version 3 of the License, or
+//  (at your option) any later version.
+//
+//  This program is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with this program.  If not, see <http://www.gnu.org/licenses/>.    
+/////////////////////////////////////////////////////////////////////////////
+
+// For compilers that support precompilation, includes "wx/wx.h".
+#include "wx/wxprec.h"
+
+#ifdef __BORLANDC__
+#pragma hdrstop
+#endif
+
+#ifndef WX_PRECOMP
+#include "wx/wx.h"
+#endif
+
+////@begin includes
+////@end includes
+
+#include "widgets_base/dialogcontainer.h"
+
+////@begin XPM images
+#include "bitmaps/sitplus_logo_16x16.xpm"
+////@end XPM images
+
+namespace widgets_base {
+
+/*
+ * DialogContainer type definition
+ */
+
+IMPLEMENT_DYNAMIC_CLASS( DialogContainer, wxDialog )
+
+
+/*
+ * DialogContainer event table definition
+ */
+
+BEGIN_EVENT_TABLE( DialogContainer, wxDialog )
+
+////@begin DialogContainer event table entries
+    EVT_SIZE( DialogContainer::OnSize )
+
+////@end DialogContainer event table entries
+
+END_EVENT_TABLE()
+
+
+/*
+ * DialogContainer constructors
+ */
+
+DialogContainer::DialogContainer()
+{
+    Init();
+}
+
+DialogContainer::DialogContainer( wxWindow* parent, wxWindowID id, const wxString& caption, const wxPoint& pos, const wxSize& size, long style )
+{
+    Init();
+    Create(parent, id, caption, pos, size, style);
+}
+
+
+/*
+ * DialogContainer creator
+ */
+
+bool DialogContainer::Create( wxWindow* parent, wxWindowID id, const wxString& caption, const wxPoint& pos, const wxSize& size, long style )
+{
+////@begin DialogContainer creation
+    SetExtraStyle(wxWS_EX_BLOCK_EVENTS);
+    wxDialog::Create( parent, id, caption, pos, size, style );
+
+    CreateControls();
+    SetIcon(GetIconResource(wxT("bitmaps/sitplus_logo_16x16.xpm")));
+    if (GetSizer())
+    {
+        GetSizer()->SetSizeHints(this);
+    }
+    Centre();
+////@end DialogContainer creation
+    return true;
+}
+
+
+/*
+ * DialogContainer destructor
+ */
+
+DialogContainer::~DialogContainer()
+{
+////@begin DialogContainer destruction
+////@end DialogContainer destruction
+}
+
+
+/*
+ * Member initialisation
+ */
+
+void DialogContainer::Init()
+{
+////@begin DialogContainer member initialisation
+    m_sizer = NULL;
+////@end DialogContainer member initialisation
+}
+
+
+/*
+ * Control creation for DialogContainer
+ */
+
+void DialogContainer::CreateControls()
+{    
+////@begin DialogContainer content construction
+    DialogContainer* itemDialog1 = this;
+
+    m_sizer = new wxBoxSizer(wxVERTICAL);
+    itemDialog1->SetSizer(m_sizer);
+
+////@end DialogContainer content construction
+}
+
+
+/*
+ * Should we show tooltips?
+ */
+
+bool DialogContainer::ShowToolTips()
+{
+    return true;
+}
+
+/*
+ * Get bitmap resources
+ */
+
+wxBitmap DialogContainer::GetBitmapResource( const wxString& name )
+{
+    // Bitmap retrieval
+////@begin DialogContainer bitmap retrieval
+    wxUnusedVar(name);
+    return wxNullBitmap;
+////@end DialogContainer bitmap retrieval
+}
+
+/*
+ * Get icon resources
+ */
+
+wxIcon DialogContainer::GetIconResource( const wxString& name )
+{
+    // Icon retrieval
+////@begin DialogContainer icon retrieval
+    wxUnusedVar(name);
+    if (name == _T("bitmaps/sitplus_logo_16x16.xpm"))
+    {
+        wxIcon icon(sitplus_logo_16x16);
+        return icon;
+    }
+    return wxNullIcon;
+////@end DialogContainer icon retrieval
+}
+
+void DialogContainer::AddSitplusPanel (wxWindow* panel)
+{
+	m_sizer->Add (panel, 0, wxALIGN_CENTER_HORIZONTAL|wxALL, 0);	
+	m_sizer->SetSizeHints(this);
+	SetTitle (panel->GetName());
+	//Layout();
+	//Fit();
+}
+
+
+/*
+ * wxEVT_SIZE event handler for ID_DIALOGCONTAINER
+ */
+
+void DialogContainer::OnSize( wxSizeEvent& event )
+{
+	Layout();
+	Fit();
+
+	event.Skip (false);
+}
+
+};
\ No newline at end of file
diff --git a/src/widgets_base/mdichildcontainer.cpp b/src/widgets_base/mdichildcontainer.cpp
new file mode 100755
index 0000000..f5db988
--- /dev/null
+++ b/src/widgets_base/mdichildcontainer.cpp
@@ -0,0 +1,198 @@
+/////////////////////////////////////////////////////////////////////////////
+// Name:        mdichildcontainer.cpp
+// Purpose:     
+// Author:      C�sar Mauri Loba
+// Modified by: 
+// Created:     04/04/2011 21:30:07
+// RCS-ID:      
+// Copyright:   (C) 2011 Cesar Mauri Loba - CREA Software Systems
+// 
+//  This program is free software: you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation, either version 3 of the License, or
+//  (at your option) any later version.
+//
+//  This program is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with this program.  If not, see <http://www.gnu.org/licenses/>.     
+/////////////////////////////////////////////////////////////////////////////
+
+// For compilers that support precompilation, includes "wx/wx.h".
+#include "wx/wxprec.h"
+
+#ifdef __BORLANDC__
+#pragma hdrstop
+#endif
+
+#ifndef WX_PRECOMP
+#include "wx/wx.h"
+#endif
+
+////@begin includes
+////@end includes
+
+#include "widgets_base/mdichildcontainer.h"
+
+////@begin XPM images
+////@end XPM images
+
+namespace widgets_base {
+
+/*
+ * MDIChildContainer type definition
+ */
+
+IMPLEMENT_CLASS( MDIChildContainer, wxMDIChildFrame )
+
+
+/*
+ * MDIChildContainer event table definition
+ */
+
+BEGIN_EVENT_TABLE( MDIChildContainer, wxMDIChildFrame )
+
+////@begin MDIChildContainer event table entries
+    EVT_SIZE( MDIChildContainer::OnSize )
+
+////@end MDIChildContainer event table entries
+
+END_EVENT_TABLE()
+
+
+/*
+ * MDIChildContainer constructors
+ */
+
+MDIChildContainer::MDIChildContainer()
+{
+    Init();
+}
+
+MDIChildContainer::MDIChildContainer( wxMDIParentFrame* parent, wxWindowID id, const wxString& caption, const wxPoint& pos, const wxSize& size, long style )
+{
+    Init();
+    Create( parent, id, caption, pos, size, style );
+}
+
+
+/*
+ * MDIChildContainer creator
+ */
+
+bool MDIChildContainer::Create( wxMDIParentFrame* parent, wxWindowID id, const wxString& caption, const wxPoint& pos, const wxSize& size, long style )
+{
+////@begin MDIChildContainer creation
+    wxMDIChildFrame::Create( parent, id, caption, pos, size, style );
+
+    CreateControls();
+    if (GetSizer())
+    {
+        GetSizer()->SetSizeHints(this);
+    }
+    Centre();
+////@end MDIChildContainer creation
+    return true;
+}
+
+
+/*
+ * MDIChildContainer destructor
+ */
+
+MDIChildContainer::~MDIChildContainer()
+{
+////@begin MDIChildContainer destruction
+////@end MDIChildContainer destruction
+}
+
+
+/*
+ * Member initialisation
+ */
+
+void MDIChildContainer::Init()
+{
+////@begin MDIChildContainer member initialisation
+    m_sizer = NULL;
+////@end MDIChildContainer member initialisation
+}
+
+
+/*
+ * Control creation for MDIChildContainer
+ */
+
+void MDIChildContainer::CreateControls()
+{    
+////@begin MDIChildContainer content construction
+    MDIChildContainer* itemMDIChildFrame1 = this;
+
+    m_sizer = new wxBoxSizer(wxVERTICAL);
+    itemMDIChildFrame1->SetSizer(m_sizer);
+
+////@end MDIChildContainer content construction
+}
+
+
+/*
+ * Should we show tooltips?
+ */
+
+bool MDIChildContainer::ShowToolTips()
+{
+    return true;
+}
+
+/*
+ * Get bitmap resources
+ */
+
+wxBitmap MDIChildContainer::GetBitmapResource( const wxString& name )
+{
+    // Bitmap retrieval
+////@begin MDIChildContainer bitmap retrieval
+    wxUnusedVar(name);
+    return wxNullBitmap;
+////@end MDIChildContainer bitmap retrieval
+}
+
+/*
+ * Get icon resources
+ */
+
+wxIcon MDIChildContainer::GetIconResource( const wxString& name )
+{
+    // Icon retrieval
+////@begin MDIChildContainer icon retrieval
+    wxUnusedVar(name);
+    return wxNullIcon;
+////@end MDIChildContainer icon retrieval
+}
+
+void MDIChildContainer::AddSitplusPanel (wxWindow* panel)
+{
+	m_sizer->Add (panel, 0, wxALIGN_CENTER_HORIZONTAL|wxALL, 0);	
+	m_sizer->SetSizeHints(this);
+	SetTitle (panel->GetName());
+	//Layout();
+	//Fit();
+}
+
+
+/*
+ * wxEVT_SIZE event handler for ID_MDICHILDCONTAINER
+ */
+
+void MDIChildContainer::OnSize( wxSizeEvent& event )
+{
+	Layout();
+	Fit();
+
+	event.Skip (false);
+}
+
+};
\ No newline at end of file
diff --git a/src/widgets_base/widgets_base.pjd b/src/widgets_base/widgets_base.pjd
new file mode 100755
index 0000000..5d71b04
--- /dev/null
+++ b/src/widgets_base/widgets_base.pjd
@@ -0,0 +1,640 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<anthemion-project version="1.0.0.0" xmlns="http://www.anthemion.co.uk">
+  <header>
+    <long name="name_counter">0</long>
+    <string name="html_path">""</string>
+    <string name="title">""</string>
+    <string name="author">""</string>
+    <string name="description">""</string>
+    <string name="xrc_filename">""</string>
+    <long name="image_mode">0</long>
+    <bool name="inline_images">0</bool>
+    <bool name="generate_cpp_for_xrc">0</bool>
+    <long name="working_mode">1</long>
+    <bool name="use_help_text_for_tooltips">1</bool>
+    <bool name="translate_strings">1</bool>
+    <bool name="make_unicode_strings">1</bool>
+    <bool name="extract_strings">0</bool>
+    <string name="user_name">"César Mauri Loba"</string>
+    <string name="copyright_string">"3DB07020-865C504F-B8F7B01B"</string>
+    <string name="resource_prefix">""</string>
+    <bool name="use_two_step_construction">0</bool>
+    <bool name="use_enums">0</bool>
+    <bool name="generate_for_xrced">0</bool>
+    <bool name="generate_virtual_eventhandlers">0</bool>
+    <string name="current_platform">"<All platforms>"</string>
+    <string name="target_wx_version">"2.8.7"</string>
+    <string name="app_kind">"Standard"</string>
+    <string name="cpp_header_comment">"/////////////////////////////////////////////////////////////////////////////
+// Name:        %HEADER-FILENAME%
+// Purpose:     
+// Author:      %AUTHOR%
+// Modified by: 
+// Created:     %DATE%
+// RCS-ID:      
+// Copyright:   %COPYRIGHT%
+// Licence:     
+/////////////////////////////////////////////////////////////////////////////
+
+"</string>
+    <string name="cpp_implementation_comment">"/////////////////////////////////////////////////////////////////////////////
+// Name:        %SOURCE-FILENAME%
+// Purpose:     
+// Author:      %AUTHOR%
+// Modified by: 
+// Created:     %DATE%
+// RCS-ID:      
+// Copyright:   %COPYRIGHT%
+// Licence:     
+/////////////////////////////////////////////////////////////////////////////
+
+"</string>
+    <string name="cpp_symbols_file_comment">"/////////////////////////////////////////////////////////////////////////////
+// Name:        %SYMBOLS-FILENAME%
+// Purpose:     Symbols file
+// Author:      %AUTHOR%
+// Modified by: 
+// Created:     %DATE%
+// RCS-ID:      
+// Copyright:   %COPYRIGHT%
+// Licence:     
+/////////////////////////////////////////////////////////////////////////////
+
+"</string>
+    <string name="cpp_header_preamble">""</string>
+    <string name="cpp_implementation_preamble">"// For compilers that support precompilation, includes "wx/wx.h".
+#include "wx/wxprec.h"
+
+#ifdef __BORLANDC__
+#pragma hdrstop
+#endif
+
+#ifndef WX_PRECOMP
+#include "wx/wx.h"
+#endif
+
+"</string>
+    <string name="cpp_function_declaration_comment">"	/// %BODY%
+"</string>
+    <string name="cpp_function_implementation_comment">"
+/*
+ * %BODY%
+ */
+
+"</string>
+    <string name="resource_file_header">"app_resources.h"</string>
+    <string name="resource_file_implementation">"app_resources.cpp"</string>
+    <string name="resource_class_name">"AppResources"</string>
+    <string name="app_file_header">"app.h"</string>
+    <string name="app_file_implementation">"app.cpp"</string>
+    <string name="app_class_name">"Application"</string>
+    <bool name="generate_app_class">0</bool>
+    <string name="external_symbol_filenames">""</string>
+    <string name="configuration">"<None>"</string>
+    <string name="source_encoding">"iso-8859-1"</string>
+    <string name="xrc_encoding">"utf-8"</string>
+    <string name="project_encoding">"utf-8"</string>
+    <string name="resource_archive">""</string>
+    <long name="text_file_type">1</long>
+    <bool name="use_tabs">0</bool>
+    <long name="indent_size">4</long>
+    <string name="whitespace_after_return_type">" "</string>
+    <string name="resource_xrc_cpp">""</string>
+    <bool name="use_resource_archive">0</bool>
+    <bool name="use_generated_xrc_cpp">0</bool>
+    <bool name="always_generate_xrc">1</bool>
+    <bool name="use_id_name_for_name">0</bool>
+    <bool name="archive_xrc_files">1</bool>
+    <bool name="archive_image_files">1</bool>
+    <bool name="archive_all_image_files">0</bool>
+    <bool name="xrc_retain_relative_paths">1</bool>
+    <bool name="xrc_generate_id_tags">0</bool>
+    <bool name="xrc_use_name_property">0</bool>
+  </header>
+  <data>
+    <document>
+      <string name="title">""</string>
+      <string name="type">"data-document"</string>
+      <string name="filename">""</string>
+      <string name="icon-name">""</string>
+      <long name="is-transient">0</long>
+      <long name="owns-file">1</long>
+      <long name="title-mode">0</long>
+      <long name="locked">0</long>
+      <document>
+        <string name="title">"Configurations"</string>
+        <string name="type">"config-data-document"</string>
+        <string name="filename">""</string>
+        <string name="icon-name">""</string>
+        <long name="is-transient">0</long>
+        <long name="owns-file">1</long>
+        <long name="title-mode">0</long>
+        <long name="locked">0</long>
+        <string name="template-name">""</string>
+        <bool name="dirty">1</bool>
+        <long name="makefile-last-written">-8519680</long>
+        <string name="Compiler name">""</string>
+        <string name="Build mode">"Debug"</string>
+        <string name="Unicode mode">"Unicode"</string>
+        <string name="Shared mode">"Static"</string>
+        <string name="Modularity">"Modular"</string>
+        <string name="GUI mode">"GUI"</string>
+        <string name="Toolkit">"wxMSW"</string>
+        <string name="Processor type">"Default"</string>
+        <string name="Runtime linking">"Dynamic"</string>
+        <string name="Use exceptions">"Yes"</string>
+        <string name="Use ODBC">"No"</string>
+        <string name="Use XRC">"Yes"</string>
+        <string name="Use OpenGL">"No"</string>
+        <string name="Use wxMediaCtrl">"No"</string>
+        <string name="Use wxRichTextCtrl">"Yes"</string>
+        <string name="Use wxHTML">"Yes"</string>
+        <string name="Use wxPropertyGrid">"Yes"</string>
+        <string name="Use wxAUI">"Yes"</string>
+        <string name="Use wxSTC">"Yes"</string>
+        <string name="Use wxRibbonControl">"Yes"</string>
+        <string name="Executable name">"%EXECUTABLE%"</string>
+        <string name="Program arguments">""</string>
+        <string name="Working path">"%AUTO%"</string>
+        <string name="Output path">"%AUTO%"</string>
+        <string name="Objects path">"%AUTO%"</string>
+        <string name="Project makefile">"%AUTO%"</string>
+        <string name="wxWidgets version">"%WXVERSION%"</string>
+        <string name="wxWidgets makefile">"%AUTO%"</string>
+        <string name="wxWidgets location">"%AUTO%"</string>
+        <string name="wxWidgets build path">"%AUTO%"</string>
+        <string name="wxWidgets build command">"%AUTO%"</string>
+        <string name="wxWidgets clean command">"%AUTO%"</string>
+        <string name="CFG">""</string>
+        <string name="Compiler location">"%AUTO%"</string>
+        <string name="Compiler bin path">"%AUTO%"</string>
+        <string name="Compiler include path">"%AUTO%"</string>
+        <string name="Compiler lib path">"%AUTO%"</string>
+        <string name="PATH variable">"%AUTO%"</string>
+        <string name="C++ command">"%AUTO%"</string>
+        <string name="C command">"%AUTO%"</string>
+        <string name="Linker command">"%AUTO%"</string>
+        <string name="Resource compiler">"%AUTO%"</string>
+        <string name="Make command">"%AUTO%"</string>
+        <string name="Preprocessor flags">"%AUTO%"</string>
+        <string name="Optimizations">"%AUTO%"</string>
+        <string name="Warnings">"%AUTO%"</string>
+        <string name="Debug flags">"%AUTO%"</string>
+        <string name="Extra compile flags">"%AUTO%"</string>
+        <string name="Libraries">"%AUTO%"</string>
+        <string name="Library path">"%AUTO%"</string>
+        <string name="Linker flags">"%AUTO%"</string>
+        <string name="Include path">"%AUTO%"</string>
+        <string name="Resource flags">"%AUTO%"</string>
+        <string name="Resource path">"%AUTO%"</string>
+        <bool name="Suppress source rules">0</bool>
+        <bool name="Enable makefile generation">1</bool>
+      </document>
+    </document>
+  </data>
+
+  <documents>
+    <document>
+      <string name="title">"Projects"</string>
+      <string name="type">"root-document"</string>
+      <string name="filename">""</string>
+      <string name="icon-name">"project"</string>
+      <long name="is-transient">1</long>
+      <long name="owns-file">1</long>
+      <long name="title-mode">0</long>
+      <long name="locked">1</long>
+      <document>
+        <string name="title">"Windows"</string>
+        <string name="type">"html-document"</string>
+        <string name="filename">""</string>
+        <string name="icon-name">"dialogsfolder"</string>
+        <long name="is-transient">1</long>
+        <long name="owns-file">1</long>
+        <long name="title-mode">0</long>
+        <long name="locked">1</long>
+        <document>
+          <string name="title">"DialogContainer"</string>
+          <string name="type">"dialog-document"</string>
+          <string name="filename">""</string>
+          <string name="icon-name">"dialog"</string>
+          <long name="is-transient">0</long>
+          <long name="owns-file">1</long>
+          <long name="title-mode">0</long>
+          <long name="locked">0</long>
+          <string name="proxy-type">"wbDialogProxy"</string>
+          <long name="base-id">10000</long>
+          <bool name="use-id-prefix">0</bool>
+          <string name="id-prefix">""</string>
+          <bool name="use-id-suffix">0</bool>
+          <string name="id-suffix">""</string>
+          <string name="app-kind">"Standard"</string>
+          <long name="use-xrc">0</long>
+          <long name="working-mode">0</long>
+          <string name="event-handler-0">"wxEVT_SIZE|OnSize|NONE||"</string>
+          <string name="proxy-Id name">"ID_DIALOGCONTAINER"</string>
+          <long name="proxy-Id value">10007</long>
+          <string name="proxy-Class">"DialogContainer"</string>
+          <string name="proxy-Base class">"wxDialog"</string>
+          <string name="proxy-Window kind">"wxDialog"</string>
+          <string name="proxy-Implementation filename">"dialogcontainer.cpp"</string>
+          <string name="proxy-Header filename">"../../include/widgets_base/dialogcontainer.h"</string>
+          <string name="proxy-XRC filename">""</string>
+          <string name="proxy-Title">"DialogContainer"</string>
+          <bool name="proxy-Centre">1</bool>
+          <string name="proxy-Icon">"bitmaps/sitplus_logo_16x16.xpm"</string>
+          <bool name="proxy-Dialog units">0</bool>
+          <string name="proxy-Help text">""</string>
+          <string name="proxy-Tooltip text">""</string>
+          <string name="proxy-Background colour">""</string>
+          <string name="proxy-Foreground colour">""</string>
+          <string name="proxy-Font">""</string>
+          <bool name="proxy-Hidden">0</bool>
+          <bool name="proxy-Enabled">1</bool>
+          <string name="proxy-Platform">"<Any platform>"</string>
+          <string name="proxy-Data source">""</string>
+          <string name="proxy-Data class name">""</string>
+          <string name="proxy-Data class implementation filename">""</string>
+          <string name="proxy-Data class header filename">""</string>
+          <string name="proxy-Data class manager window">""</string>
+          <string name="proxy-Texture">""</string>
+          <string name="proxy-Texture style">"Tiled"</string>
+          <bool name="proxy-wxDEFAULT_DIALOG_STYLE">0</bool>
+          <bool name="proxy-wxCAPTION">1</bool>
+          <bool name="proxy-wxRESIZE_BORDER">0</bool>
+          <bool name="proxy-wxSYSTEM_MENU">1</bool>
+          <bool name="proxy-wxSTAY_ON_TOP">0</bool>
+          <bool name="proxy-wxDIALOG_NO_PARENT">0</bool>
+          <bool name="proxy-wxCLOSE_BOX">1</bool>
+          <bool name="proxy-wxMAXIMIZE_BOX">0</bool>
+          <bool name="proxy-wxMINIMIZE_BOX">0</bool>
+          <bool name="proxy-wxDIALOG_MODAL">1</bool>
+          <bool name="proxy-wxNO_BORDER">0</bool>
+          <bool name="proxy-wxSIMPLE_BORDER">0</bool>
+          <bool name="proxy-wxDOUBLE_BORDER">0</bool>
+          <bool name="proxy-wxBORDER_THEME">0</bool>
+          <bool name="proxy-wxSUNKEN_BORDER">0</bool>
+          <bool name="proxy-wxRAISED_BORDER">0</bool>
+          <bool name="proxy-wxSTATIC_BORDER">0</bool>
+          <bool name="proxy-wxWANTS_CHARS">0</bool>
+          <bool name="proxy-wxNO_FULL_REPAINT_ON_RESIZE">0</bool>
+          <bool name="proxy-wxFULL_REPAINT_ON_RESIZE">0</bool>
+          <bool name="proxy-wxCLIP_CHILDREN">0</bool>
+          <bool name="proxy-wxTAB_TRAVERSAL">1</bool>
+          <bool name="proxy-wxWS_EX_VALIDATE_RECURSIVELY">0</bool>
+          <bool name="proxy-wxWS_EX_BLOCK_EVENTS">1</bool>
+          <bool name="proxy-wxWS_EX_TRANSIENT">0</bool>
+          <string name="proxy-Custom styles">""</string>
+          <bool name="proxy-wxDIALOG_EX_CONTEXTHELP">0</bool>
+          <bool name="proxy-Fit to content">1</bool>
+          <long name="proxy-X">-1</long>
+          <long name="proxy-Y">-1</long>
+          <long name="proxy-Width">-1</long>
+          <long name="proxy-Height">-1</long>
+          <bool name="proxy-AUI manager">0</bool>
+          <string name="proxy-Event sources">""</string>
+          <document>
+            <string name="title">"wxBoxSizer V"</string>
+            <string name="type">"dialog-control-document"</string>
+            <string name="filename">""</string>
+            <string name="icon-name">"sizer"</string>
+            <long name="is-transient">0</long>
+            <long name="owns-file">1</long>
+            <long name="title-mode">0</long>
+            <long name="locked">0</long>
+            <string name="proxy-type">"wbBoxSizerProxy"</string>
+            <string name="proxy-Orientation">"Vertical"</string>
+            <string name="proxy-Member variable name">"m_sizer"</string>
+            <string name="proxy-AlignH">"Centre"</string>
+            <string name="proxy-AlignV">"Centre"</string>
+            <long name="proxy-Stretch factor">0</long>
+            <long name="proxy-Border">5</long>
+            <bool name="proxy-wxLEFT">1</bool>
+            <bool name="proxy-wxRIGHT">1</bool>
+            <bool name="proxy-wxTOP">1</bool>
+            <bool name="proxy-wxBOTTOM">1</bool>
+            <bool name="proxy-wxSHAPED">0</bool>
+            <bool name="proxy-wxADJUST_MINSIZE">0</bool>
+            <bool name="proxy-wxFIXED_MINSIZE">0</bool>
+            <string name="proxy-Platform">"<Any platform>"</string>
+          </document>
+        </document>
+        <document>
+          <string name="title">"MDIChildContainer"</string>
+          <string name="type">"dialog-document"</string>
+          <string name="filename">""</string>
+          <string name="icon-name">"frame"</string>
+          <long name="is-transient">0</long>
+          <long name="owns-file">1</long>
+          <long name="title-mode">0</long>
+          <long name="locked">0</long>
+          <string name="proxy-type">"wbFrameProxy"</string>
+          <long name="base-id">10000</long>
+          <bool name="use-id-prefix">0</bool>
+          <string name="id-prefix">""</string>
+          <bool name="use-id-suffix">0</bool>
+          <string name="id-suffix">""</string>
+          <string name="app-kind">"Standard"</string>
+          <long name="use-xrc">0</long>
+          <long name="working-mode">0</long>
+          <string name="event-handler-0">"wxEVT_SIZE|OnSize|NONE||"</string>
+          <string name="proxy-Id name">"ID_MDICHILDCONTAINER"</string>
+          <long name="proxy-Id value">10012</long>
+          <string name="proxy-Class">"MDIChildContainer"</string>
+          <string name="proxy-Base class">"wxMDIChildFrame"</string>
+          <string name="proxy-Implementation filename">"mdichildcontainer.cpp"</string>
+          <string name="proxy-Header filename">"../../include/widgets_base/mdichildcontainer.h"</string>
+          <string name="proxy-XRC filename">""</string>
+          <string name="proxy-Title">""</string>
+          <bool name="proxy-Centre">1</bool>
+          <string name="proxy-Icon">""</string>
+          <bool name="proxy-Dialog units">0</bool>
+          <string name="proxy-Help text">""</string>
+          <string name="proxy-Tooltip text">""</string>
+          <string name="proxy-Background colour">""</string>
+          <string name="proxy-Foreground colour">""</string>
+          <string name="proxy-Font">""</string>
+          <bool name="proxy-Hidden">0</bool>
+          <bool name="proxy-Enabled">1</bool>
+          <string name="proxy-Platform">"<Any platform>"</string>
+          <string name="proxy-Data source">""</string>
+          <string name="proxy-Data class name">""</string>
+          <string name="proxy-Data class implementation filename">""</string>
+          <string name="proxy-Data class header filename">""</string>
+          <string name="proxy-Data class manager window">""</string>
+          <bool name="proxy-wxDEFAULT_FRAME_STYLE">0</bool>
+          <bool name="proxy-wxCAPTION">1</bool>
+          <bool name="proxy-wxRESIZE_BORDER">0</bool>
+          <bool name="proxy-wxSYSTEM_MENU">0</bool>
+          <bool name="proxy-wxMINIMIZE">0</bool>
+          <bool name="proxy-wxMAXIMIZE">0</bool>
+          <bool name="proxy-wxMINIMIZE_BOX">0</bool>
+          <bool name="proxy-wxMAXIMIZE_BOX">0</bool>
+          <bool name="proxy-wxCLOSE_BOX">0</bool>
+          <bool name="proxy-wxFRAME_TOOL_WINDOW">0</bool>
+          <bool name="proxy-wxFRAME_FLOAT_ON_PARENT">0</bool>
+          <bool name="proxy-wxFRAME_NO_TASKBAR">0</bool>
+          <bool name="proxy-wxSTAY_ON_TOP">0</bool>
+          <bool name="proxy-wxNO_BORDER">0</bool>
+          <bool name="proxy-wxSIMPLE_BORDER">0</bool>
+          <bool name="proxy-wxDOUBLE_BORDER">0</bool>
+          <bool name="proxy-wxBORDER_THEME">0</bool>
+          <bool name="proxy-wxSUNKEN_BORDER">0</bool>
+          <bool name="proxy-wxRAISED_BORDER">0</bool>
+          <bool name="proxy-wxSTATIC_BORDER">0</bool>
+          <bool name="proxy-wxWANTS_CHARS">0</bool>
+          <bool name="proxy-wxNO_FULL_REPAINT_ON_RESIZE">0</bool>
+          <bool name="proxy-wxFULL_REPAINT_ON_RESIZE">0</bool>
+          <bool name="proxy-wxCLIP_CHILDREN">0</bool>
+          <bool name="proxy-wxTAB_TRAVERSAL">0</bool>
+          <bool name="proxy-wxWS_EX_VALIDATE_RECURSIVELY">0</bool>
+          <bool name="proxy-wxWS_EX_BLOCK_EVENTS">0</bool>
+          <bool name="proxy-wxWS_EX_TRANSIENT">0</bool>
+          <string name="proxy-Custom styles">""</string>
+          <bool name="proxy-wxFRAME_EX_CONTEXTHELP">0</bool>
+          <bool name="proxy-Fit to content">1</bool>
+          <long name="proxy-X">-1</long>
+          <long name="proxy-Y">-1</long>
+          <long name="proxy-Width">-1</long>
+          <long name="proxy-Height">-1</long>
+          <bool name="proxy-AUI manager">0</bool>
+          <string name="proxy-Event sources">""</string>
+          <document>
+            <string name="title">"wxBoxSizer V"</string>
+            <string name="type">"dialog-control-document"</string>
+            <string name="filename">""</string>
+            <string name="icon-name">"sizer"</string>
+            <long name="is-transient">0</long>
+            <long name="owns-file">1</long>
+            <long name="title-mode">0</long>
+            <long name="locked">0</long>
+            <string name="proxy-type">"wbBoxSizerProxy"</string>
+            <string name="proxy-Orientation">"Vertical"</string>
+            <string name="proxy-Member variable name">"m_sizer"</string>
+            <string name="proxy-AlignH">"Centre"</string>
+            <string name="proxy-AlignV">"Centre"</string>
+            <long name="proxy-Stretch factor">0</long>
+            <long name="proxy-Border">5</long>
+            <bool name="proxy-wxLEFT">1</bool>
+            <bool name="proxy-wxRIGHT">1</bool>
+            <bool name="proxy-wxTOP">1</bool>
+            <bool name="proxy-wxBOTTOM">1</bool>
+            <bool name="proxy-wxSHAPED">0</bool>
+            <bool name="proxy-wxADJUST_MINSIZE">0</bool>
+            <bool name="proxy-wxFIXED_MINSIZE">0</bool>
+            <string name="proxy-Platform">"<Any platform>"</string>
+          </document>
+        </document>
+        <document>
+          <string name="title">"GENERATOR"</string>
+          <string name="type">"dialog-document"</string>
+          <string name="filename">""</string>
+          <string name="icon-name">"dialog"</string>
+          <long name="is-transient">0</long>
+          <long name="owns-file">1</long>
+          <long name="title-mode">0</long>
+          <long name="locked">0</long>
+          <string name="proxy-type">"wbDialogProxy"</string>
+          <long name="base-id">10000</long>
+          <bool name="use-id-prefix">0</bool>
+          <string name="id-prefix">""</string>
+          <bool name="use-id-suffix">0</bool>
+          <string name="id-suffix">""</string>
+          <string name="app-kind">"Standard"</string>
+          <long name="use-xrc">0</long>
+          <long name="working-mode">0</long>
+          <string name="proxy-Id name">"ID_GENERATOR"</string>
+          <long name="proxy-Id value">10000</long>
+          <string name="proxy-Class">"DeleteMe"</string>
+          <string name="proxy-Base class">"wxDialog"</string>
+          <string name="proxy-Window kind">"wxDialog"</string>
+          <string name="proxy-Implementation filename">""</string>
+          <string name="proxy-Header filename">""</string>
+          <string name="proxy-XRC filename">""</string>
+          <string name="proxy-Title">"INTENDED TO GENERATE CUSTOM CONTROLS"</string>
+          <bool name="proxy-Centre">1</bool>
+          <string name="proxy-Icon">""</string>
+          <bool name="proxy-Dialog units">0</bool>
+          <string name="proxy-Help text">""</string>
+          <string name="proxy-Tooltip text">""</string>
+          <string name="proxy-Background colour">""</string>
+          <string name="proxy-Foreground colour">""</string>
+          <string name="proxy-Font">""</string>
+          <bool name="proxy-Hidden">0</bool>
+          <bool name="proxy-Enabled">1</bool>
+          <string name="proxy-Platform">"<Any platform>"</string>
+          <string name="proxy-Data source">""</string>
+          <string name="proxy-Data class name">""</string>
+          <string name="proxy-Data class implementation filename">""</string>
+          <string name="proxy-Data class header filename">""</string>
+          <string name="proxy-Data class manager window">""</string>
+          <string name="proxy-Texture">""</string>
+          <string name="proxy-Texture style">"Tiled"</string>
+          <bool name="proxy-wxDEFAULT_DIALOG_STYLE">0</bool>
+          <bool name="proxy-wxCAPTION">1</bool>
+          <bool name="proxy-wxRESIZE_BORDER">1</bool>
+          <bool name="proxy-wxSYSTEM_MENU">1</bool>
+          <bool name="proxy-wxSTAY_ON_TOP">0</bool>
+          <bool name="proxy-wxDIALOG_NO_PARENT">0</bool>
+          <bool name="proxy-wxCLOSE_BOX">1</bool>
+          <bool name="proxy-wxMAXIMIZE_BOX">0</bool>
+          <bool name="proxy-wxMINIMIZE_BOX">0</bool>
+          <bool name="proxy-wxDIALOG_MODAL">1</bool>
+          <bool name="proxy-wxNO_BORDER">0</bool>
+          <bool name="proxy-wxSIMPLE_BORDER">0</bool>
+          <bool name="proxy-wxDOUBLE_BORDER">0</bool>
+          <bool name="proxy-wxBORDER_THEME">0</bool>
+          <bool name="proxy-wxSUNKEN_BORDER">0</bool>
+          <bool name="proxy-wxRAISED_BORDER">0</bool>
+          <bool name="proxy-wxSTATIC_BORDER">0</bool>
+          <bool name="proxy-wxWANTS_CHARS">0</bool>
+          <bool name="proxy-wxNO_FULL_REPAINT_ON_RESIZE">0</bool>
+          <bool name="proxy-wxFULL_REPAINT_ON_RESIZE">0</bool>
+          <bool name="proxy-wxCLIP_CHILDREN">0</bool>
+          <bool name="proxy-wxTAB_TRAVERSAL">1</bool>
+          <bool name="proxy-wxWS_EX_VALIDATE_RECURSIVELY">0</bool>
+          <bool name="proxy-wxWS_EX_BLOCK_EVENTS">1</bool>
+          <bool name="proxy-wxWS_EX_TRANSIENT">0</bool>
+          <string name="proxy-Custom styles">""</string>
+          <bool name="proxy-wxDIALOG_EX_CONTEXTHELP">0</bool>
+          <bool name="proxy-Fit to content">1</bool>
+          <long name="proxy-X">-1</long>
+          <long name="proxy-Y">-1</long>
+          <long name="proxy-Width">400</long>
+          <long name="proxy-Height">300</long>
+          <bool name="proxy-AUI manager">0</bool>
+          <string name="proxy-Event sources">""</string>
+          <document>
+            <string name="title">"wxBoxSizer V"</string>
+            <string name="type">"dialog-control-document"</string>
+            <string name="filename">""</string>
+            <string name="icon-name">"sizer"</string>
+            <long name="is-transient">0</long>
+            <long name="owns-file">1</long>
+            <long name="title-mode">0</long>
+            <long name="locked">0</long>
+            <string name="proxy-type">"wbBoxSizerProxy"</string>
+            <string name="proxy-Orientation">"Vertical"</string>
+            <string name="proxy-Member variable name">""</string>
+            <bool name="proxy-wxSHAPED">0</bool>
+            <bool name="proxy-wxADJUST_MINSIZE">0</bool>
+            <bool name="proxy-wxFIXED_MINSIZE">0</bool>
+            <string name="proxy-Platform">"<Any platform>"</string>
+            <document>
+              <string name="title">"ContainerCollapsible: ID_COLLAPSIBLEPANE"</string>
+              <string name="type">"dialog-control-document"</string>
+              <string name="filename">""</string>
+              <string name="icon-name">"panel"</string>
+              <long name="is-transient">0</long>
+              <long name="owns-file">1</long>
+              <long name="title-mode">0</long>
+              <long name="locked">0</long>
+              <string name="proxy-type">"wbCollapsiblePaneProxy"</string>
+              <string name="event-handler-0">"wxEVT_COMMAND_COLLPANE_CHANGED|OnCollapsiblepanePaneChanged|NONE||ContainerCollapsible"</string>
+              <string name="proxy-Id name">"ID_COLLAPSIBLEPANE"</string>
+              <long name="proxy-Id value">-1</long>
+              <string name="proxy-Name">""</string>
+              <string name="proxy-Class">"ContainerCollapsible"</string>
+              <string name="proxy-Base class">"wxGenericCollapsiblePane"</string>
+              <bool name="proxy-External implementation">0</bool>
+              <bool name="proxy-Separate files">1</bool>
+              <string name="proxy-Implementation filename">"containercollapsible.cpp"</string>
+              <string name="proxy-Header filename">"../../include/widgets_base/containercollapsible.h"</string>
+              <string name="proxy-Member variable name">""</string>
+              <string name="proxy-Label">"Label"</string>
+              <bool name="proxy-Collapsed">1</bool>
+              <string name="proxy-Help text">""</string>
+              <string name="proxy-Tooltip text">""</string>
+              <string name="proxy-Background colour">""</string>
+              <string name="proxy-Foreground colour">""</string>
+              <string name="proxy-Font">""</string>
+              <bool name="proxy-Hidden">0</bool>
+              <bool name="proxy-Enabled">1</bool>
+              <string name="proxy-Platform">"<Any platform>"</string>
+              <string name="proxy-Data variable">""</string>
+              <string name="proxy-Data validator">""</string>
+              <string name="proxy-Data source">""</string>
+              <string name="proxy-Data class name">""</string>
+              <string name="proxy-Data class implementation filename">""</string>
+              <string name="proxy-Data class header filename">""</string>
+              <string name="proxy-Data class manager window">""</string>
+              <bool name="proxy-wxCP_DEFAULT_STYLE">1</bool>
+              <bool name="proxy-wxCP_NO_TLW_RESIZE">1</bool>
+              <bool name="proxy-wxNO_BORDER">0</bool>
+              <bool name="proxy-wxSIMPLE_BORDER">0</bool>
+              <bool name="proxy-wxDOUBLE_BORDER">0</bool>
+              <bool name="proxy-wxBORDER_THEME">0</bool>
+              <bool name="proxy-wxSUNKEN_BORDER">0</bool>
+              <bool name="proxy-wxRAISED_BORDER">0</bool>
+              <bool name="proxy-wxSTATIC_BORDER">0</bool>
+              <bool name="proxy-wxWANTS_CHARS">0</bool>
+              <bool name="proxy-wxNO_FULL_REPAINT_ON_RESIZE">0</bool>
+              <bool name="proxy-wxFULL_REPAINT_ON_RESIZE">0</bool>
+              <string name="proxy-Custom styles">""</string>
+              <long name="proxy-X">-1</long>
+              <long name="proxy-Y">-1</long>
+              <long name="proxy-Width">-1</long>
+              <long name="proxy-Height">-1</long>
+              <string name="proxy-AlignH">"Centre"</string>
+              <string name="proxy-AlignV">"Centre"</string>
+              <long name="proxy-Stretch factor">0</long>
+              <long name="proxy-Border">5</long>
+              <bool name="proxy-wxLEFT">1</bool>
+              <bool name="proxy-wxRIGHT">1</bool>
+              <bool name="proxy-wxTOP">1</bool>
+              <bool name="proxy-wxBOTTOM">1</bool>
+              <bool name="proxy-wxSHAPED">0</bool>
+              <bool name="proxy-wxADJUST_MINSIZE">0</bool>
+              <bool name="proxy-wxFIXED_MINSIZE">0</bool>
+              <string name="proxy-Custom arguments">""</string>
+              <string name="proxy-Custom ctor arguments">""</string>
+              <string name="proxy-Event sources">""</string>
+            </document>
+          </document>
+        </document>
+      </document>
+      <document>
+        <string name="title">"Sources"</string>
+        <string name="type">"html-document"</string>
+        <string name="filename">""</string>
+        <string name="icon-name">"sourcesfolder"</string>
+        <long name="is-transient">1</long>
+        <long name="owns-file">1</long>
+        <long name="title-mode">0</long>
+        <long name="locked">1</long>
+      </document>
+      <document>
+        <string name="title">"Images"</string>
+        <string name="type">"html-document"</string>
+        <string name="filename">""</string>
+        <string name="icon-name">"bitmapsfolder"</string>
+        <long name="is-transient">1</long>
+        <long name="owns-file">1</long>
+        <long name="title-mode">0</long>
+        <long name="locked">1</long>
+        <document>
+          <string name="title">"sitplus_logo_16x16.xpm"</string>
+          <string name="type">"image-document"</string>
+          <string name="filename">"bitmaps/sitplus_logo_16x16.xpm"</string>
+          <string name="icon-name">"image"</string>
+          <long name="is-transient">0</long>
+          <long name="owns-file">0</long>
+          <long name="title-mode">0</long>
+          <long name="locked">0</long>
+          <long name="zoom-level">100</long>
+        </document>
+        <document>
+          <string name="title">"sitplus_logo_32x32.xpm"</string>
+          <string name="type">"image-document"</string>
+          <string name="filename">"bitmaps/sitplus_logo_32x32.xpm"</string>
+          <string name="icon-name">"image"</string>
+          <long name="is-transient">0</long>
+          <long name="owns-file">0</long>
+          <long name="title-mode">0</long>
+          <long name="locked">0</long>
+          <long name="zoom-level">100</long>
+        </document>
+      </document>
+    </document>
+  </documents>
+
+</anthemion-project>

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/debian-med/libsitplus.git



More information about the debian-med-commit mailing list