From 49c87e7432637ee8c4a386fcb0bc5815656eeea0 Mon Sep 17 00:00:00 2001 From: Qihang Yang Date: Tue, 26 Mar 2019 15:16:48 +0800 Subject: [PATCH] add impedence --- .gitignore | 1 + CMakeLists.txt | 49 ++ eegoSports.sln | 26 - eegoSports.vcproj | 319 -------- eemagine/sdk/amplifier.h | 6 +- eemagine/sdk/buffer.h | 202 +++-- eemagine/sdk/channel.h | 18 +- eemagine/sdk/factory.h | 10 +- eemagine/sdk/stream.h | 6 +- eemagine/sdk/version.h | 18 +- eemagine/sdk/wrapper.cc | 1645 ++++++++++++++++++++------------------ eemagine/sdk/wrapper.h | 378 ++++----- main.cpp | 2 +- mainwindow.cpp | 131 ++- mainwindow.h | 23 +- mainwindow.ui | 27 +- 16 files changed, 1348 insertions(+), 1513 deletions(-) create mode 100644 .gitignore create mode 100644 CMakeLists.txt delete mode 100644 eegoSports.sln delete mode 100644 eegoSports.vcproj diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..cf25ac6 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +CMakeLists.txt.user* diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..6f508ef --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,49 @@ +cmake_minimum_required(VERSION 3.5) +project(eegoSports + LANGUAGES CXX + VERSION 0.1.0) +add_compile_options(-std=c++17) +# set up LSL if not done already +if(NOT TARGET LSL::lsl) + # when building out of tree LSL_ROOT needs to be specified on the cmd line + file(TO_CMAKE_PATH "${LSL_INSTALL_ROOT}" LSL_INSTALL_ROOT) + list(APPEND LSL_INSTALL_ROOT "${CMAKE_CURRENT_LIST_DIR}/../../LSL/liblsl/build/install") + find_package(LSL HINTS ${LSL_INSTALL_ROOT}/share/LSL/ ${LSL_INSTALL_ROOT}/LSL/share/LSL QUIET) + if(NOT LSL_FOUND) + message(FATAL_ERROR "Precompiled LSL was not found. Set LSL_INSTALL_ROOT to the LSL installation path ( cmake -DLSL_INSTALL_ROOT=/path/to/installed/lsl)") + endif() + list(APPEND CMAKE_MODULE_PATH ${LSL_DIR}) + message(STATUS "Looking for LSLCMake in ${LSL_DIR}") + include(LSLCMake) +endif() + +find_package(Qt5 REQUIRED COMPONENTS Widgets Network Charts) +find_package(Boost REQUIRED) +include_directories(eemagine/sdk ${LSL_INSTALL_ROOT}/include) +link_directories(${EEMAGINE_SDK_DIR}) + +add_executable(${PROJECT_NAME} MACOSX_BUNDLE + #eemagine/sdk/wrapper.cc + main.cpp + mainwindow.cpp + mainwindow.h + mainwindow.ui + +) +target_link_libraries(${PROJECT_NAME} + PRIVATE + Qt5::Widgets + Qt5::Network + Qt5::Charts + LSL::lsl + ${Boost_LIBRARIES} + ${CMAKE_DL_LIBS} + eego-SDK +) + + + +installLSLApp(${PROJECT_NAME}) + +LSLGenerateCPackConfig() + diff --git a/eegoSports.sln b/eegoSports.sln deleted file mode 100644 index 70b7c72..0000000 --- a/eegoSports.sln +++ /dev/null @@ -1,26 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 10.00 -# Visual Studio 2008 -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "eegoSports", "eegoSports.vcproj", "{8D9A8AE1-87C9-3AA9-886C-3F4EA93CDCB3}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Win32 = Debug|Win32 - Debug|x64 = Debug|x64 - Release|Win32 = Release|Win32 - Release|x64 = Release|x64 - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {8D9A8AE1-87C9-3AA9-886C-3F4EA93CDCB3}.Debug|Win32.ActiveCfg = Debug|Win32 - {8D9A8AE1-87C9-3AA9-886C-3F4EA93CDCB3}.Debug|Win32.Build.0 = Debug|Win32 - {8D9A8AE1-87C9-3AA9-886C-3F4EA93CDCB3}.Debug|x64.ActiveCfg = Debug|Win32 - {8D9A8AE1-87C9-3AA9-886C-3F4EA93CDCB3}.Debug|x64.Build.0 = Debug|Win32 - {8D9A8AE1-87C9-3AA9-886C-3F4EA93CDCB3}.Release|Win32.ActiveCfg = Release|Win32 - {8D9A8AE1-87C9-3AA9-886C-3F4EA93CDCB3}.Release|Win32.Build.0 = Release|Win32 - {8D9A8AE1-87C9-3AA9-886C-3F4EA93CDCB3}.Release|x64.ActiveCfg = Release|Win32 - {8D9A8AE1-87C9-3AA9-886C-3F4EA93CDCB3}.Release|x64.Build.0 = Release|Win32 - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection -EndGlobal diff --git a/eegoSports.vcproj b/eegoSports.vcproj deleted file mode 100644 index 0a2bd7e..0000000 --- a/eegoSports.vcproj +++ /dev/null @@ -1,319 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/eemagine/sdk/amplifier.h b/eemagine/sdk/amplifier.h index c76a092..7c2cc63 100644 --- a/eemagine/sdk/amplifier.h +++ b/eemagine/sdk/amplifier.h @@ -32,9 +32,9 @@ #include #include // eemagine -#include -#include -#include +#include +#include +#include namespace eemagine { namespace sdk { diff --git a/eemagine/sdk/buffer.h b/eemagine/sdk/buffer.h index bc78c19..dbfb7c5 100644 --- a/eemagine/sdk/buffer.h +++ b/eemagine/sdk/buffer.h @@ -1,102 +1,100 @@ -/* - * License: eego amplifier Interface SDK, rev. 1.3 - * - * - * Copyright 2015, eemagine Medical Imaging Solutions GmbH - * - * - * 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 above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - * - * 3. All advertising materials mentioning features or use of this software must display the following acknowledgement: This product includes software developed by the eemagine Medical Imaging Solutions GmbH. - * - * 4. Neither the name of the eemagine Medical Imaging Solutions GmbH nor the names of its contributors or products may be used to endorse or promote products derived from this software without specific prior written permission by eemagine - * - * - * This Software is provided by eemagine Medical Imaging Solutions GmbH ''As Is'' and any express or implied warranties, including, but not limited to, the implied warranties merchantability and fitness for a particular purpose are disclaimed. In no event shall eemagine 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. - * - * The eego amplifier comes with its own user manual, which must be read carefully before making use of this SDK or any derived software. - * - * - * You need to run full testing and qualification based on your own requirements to claim any performance of the combined system. - * - * - * Please be especially advised that any certification holding for the eego amplifier is not valid for a combined system of your application software and the eego amplifier. You must obtain your own certification for a combined system of amplifier and software. - */ - -#ifndef __eemagine_sdk_buffer_h__ -#define __eemagine_sdk_buffer_h__ - -// system -#include -#include -// eemagine -#include - -namespace eemagine { - namespace sdk { - /// Wrapper around array to provide indexed access to values - class buffer { - public: - /** - * \brief default constructor - */ - buffer(unsigned int channel_count = 0, unsigned int sample_count = 0) - : _data(channel_count * sample_count) - , _channel_count(channel_count) - , _sample_count(sample_count) - { - } - /** - * \brief get the number of channels - * @return number of channels - */ - const unsigned int& getChannelCount() const - { - return _channel_count; - } - - /** - * \brief get the number of samples - * @return number of samples - */ - const unsigned int& getSampleCount() const - { - return _sample_count; - } - /** - * \brief get sample value - * @param channel the channel index(start indexing at zero) - * @param sample the sample index(start indexing at zero) - * @return returns that value for channel at sample - */ - const double& getSample(unsigned int channel, unsigned int sample) const - { - if (channel >= _channel_count || sample >= _sample_count) { - throw(eemagine::sdk::exceptions::incorrectValue("invalid getSample index")); - } - return _data[channel + sample * _channel_count]; - } - /** - * \brief get number of samples - * @return number of samples - */ - size_t size() const { return _data.size(); } - /** - * \brief direct pointer to data - */ - double * data() { - //return &_data.front(); //this might fail and is a pre-C++11 hack for _data.data() - //return _data.data(); - return &(_data[0]); - } - protected: - std::vector < double > _data; - unsigned int _channel_count; - unsigned int _sample_count; - }; - } -} - -#endif +/* + * License: eego amplifier Interface SDK, rev. 1.3 + * + * + * Copyright 2015, eemagine Medical Imaging Solutions GmbH + * + * + * 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 above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + * + * 3. All advertising materials mentioning features or use of this software must display the following acknowledgement: This product includes software developed by the eemagine Medical Imaging Solutions GmbH. + * + * 4. Neither the name of the eemagine Medical Imaging Solutions GmbH nor the names of its contributors or products may be used to endorse or promote products derived from this software without specific prior written permission by eemagine + * + * + * This Software is provided by eemagine Medical Imaging Solutions GmbH ''As Is'' and any express or implied warranties, including, but not limited to, the implied warranties merchantability and fitness for a particular purpose are disclaimed. In no event shall eemagine 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. + * + * The eego amplifier comes with its own user manual, which must be read carefully before making use of this SDK or any derived software. + * + * + * You need to run full testing and qualification based on your own requirements to claim any performance of the combined system. + * + * + * Please be especially advised that any certification holding for the eego amplifier is not valid for a combined system of your application software and the eego amplifier. You must obtain your own certification for a combined system of amplifier and software. + */ + +#ifndef __eemagine_sdk_buffer_h__ +#define __eemagine_sdk_buffer_h__ + +// system +#include +#include +// eemagine +#include + +namespace eemagine { + namespace sdk { + /// Wrapper around array to provide indexed access to values + class buffer { + public: + /** + * \brief default constructor + */ + buffer(unsigned int channel_count = 0, unsigned int sample_count = 0) + : _data(channel_count * sample_count) + , _channel_count(channel_count) + , _sample_count(sample_count) + { + } + /** + * \brief get the number of channels + * @return number of channels + */ + const unsigned int& getChannelCount() const + { + return _channel_count; + } + + /** + * \brief get the number of samples + * @return number of samples + */ + const unsigned int& getSampleCount() const + { + return _sample_count; + } + /** + * \brief get sample value + * @param channel the channel index(start indexing at zero) + * @param sample the sample index(start indexing at zero) + * @return returns that value for channel at sample + */ + const double& getSample(unsigned int channel, unsigned int sample) const + { + if (channel >= _channel_count || sample >= _sample_count) { + throw(eemagine::sdk::exceptions::incorrectValue("invalid getSample index")); + } + return _data[channel + sample * _channel_count]; + } + /** + * \brief get number of samples + * @return number of samples + */ + size_t size() const { return _data.size(); } + /** + * \brief direct pointer to data + */ + double * data() { + return _data.data(); + } + protected: + std::vector < double > _data; + unsigned int _channel_count; + unsigned int _sample_count; + }; + } +} + +#endif diff --git a/eemagine/sdk/channel.h b/eemagine/sdk/channel.h index e903466..9395e10 100644 --- a/eemagine/sdk/channel.h +++ b/eemagine/sdk/channel.h @@ -38,7 +38,7 @@ namespace eemagine { /** * type of channel */ - enum channel_type { none, reference, bipolar, trigger, sample_counter, impedance_reference, impedance_ground }; + enum channel_type { none, reference, bipolar, trigger, sample_counter, impedance_reference, impedance_ground, accelerometer, gyroscope, magnetometer }; /** * \brief default constructor @@ -67,9 +67,7 @@ namespace eemagine { // conversion for writing the channel into an ostream. inline std::ostream & -operator<<(std::ostream &out, const eemagine::sdk::channel &c) -{ - +operator<<(std::ostream &out, const eemagine::sdk::channel &c) { out << "channel("; out << c.getIndex(); out << ", "; @@ -92,6 +90,18 @@ operator<<(std::ostream &out, const eemagine::sdk::channel &c) case eemagine::sdk::channel::impedance_ground: out << "impedance_ground"; break; + case eemagine::sdk::channel::accelerometer: + out << "accel"; + break; + case eemagine::sdk::channel::gyroscope: + out << "gyro"; + break; + case eemagine::sdk::channel::magnetometer: + out << "magneto"; + break; + default: + out << "?"; + break; } out << ")"; diff --git a/eemagine/sdk/factory.h b/eemagine/sdk/factory.h index 0752d5e..df0c3ba 100644 --- a/eemagine/sdk/factory.h +++ b/eemagine/sdk/factory.h @@ -31,7 +31,7 @@ // system #include // eemagine -#include +#include // It has to be either dynamic or static #if !(defined(EEGO_SDK_BIND_DYNAMIC) ^ defined(EEGO_SDK_BIND_STATIC)) @@ -56,12 +56,12 @@ namespace eemagine { * constructor */ #ifdef EEGO_SDK_BIND_STATIC - factory(); + factory(void * data = NULL); #else -#ifdef WIN32 - factory(const std::wstring& path); +#ifdef _WIN32 + factory(const std::wstring& path, void * data = NULL); #endif - factory(const std::string& path); + factory(const std::string& path, void * data = NULL); #endif // EEGO_SDK_BIND_STATIC /** diff --git a/eemagine/sdk/stream.h b/eemagine/sdk/stream.h index 6541517..72a2a7c 100644 --- a/eemagine/sdk/stream.h +++ b/eemagine/sdk/stream.h @@ -32,9 +32,9 @@ #include #include // eemagine -#include -#include -#include +#include +#include +#include namespace eemagine { namespace sdk { diff --git a/eemagine/sdk/version.h b/eemagine/sdk/version.h index 7ef121c..580e6b4 100644 --- a/eemagine/sdk/version.h +++ b/eemagine/sdk/version.h @@ -1,9 +1,9 @@ -#ifndef __eemagine_sdk_version_h__ -#define __eemagine_sdk_version_h__ - -#define EEGO_SDK_VERSION_MAJOR 1 -#define EEGO_SDK_VERSION_MINOR 3 -#define EEGO_SDK_VERSION_MICRO 4 -#define EEGO_SDK_VERSION 31165 - -#endif +#ifndef __eemagine_sdk_version_h__ +#define __eemagine_sdk_version_h__ + +#define EEGO_SDK_VERSION_MAJOR 1 +#define EEGO_SDK_VERSION_MINOR 3 +#define EEGO_SDK_VERSION_MICRO 19 +#define EEGO_SDK_VERSION 40453 + +#endif diff --git a/eemagine/sdk/wrapper.cc b/eemagine/sdk/wrapper.cc index 804ac3d..4efa6ba 100644 --- a/eemagine/sdk/wrapper.cc +++ b/eemagine/sdk/wrapper.cc @@ -1,795 +1,850 @@ -/* - * License: eego amplifier Interface SDK, rev. 1.3 - * - * - * Copyright 2015, eemagine Medical Imaging Solutions GmbH - * - * - * 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 above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - * - * 3. All advertising materials mentioning features or use of this software must display the following acknowledgement: This product includes software developed by the eemagine Medical Imaging Solutions GmbH. - * - * 4. Neither the name of the eemagine Medical Imaging Solutions GmbH nor the names of its contributors or products may be used to endorse or promote products derived from this software without specific prior written permission by eemagine - * - * - * This Software is provided by eemagine Medical Imaging Solutions GmbH ''As Is'' and any express or implied warranties, including, but not limited to, the implied warranties merchantability and fitness for a particular purpose are disclaimed. In no event shall eemagine 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. - * - * The eego amplifier comes with its own user manual, which must be read carefully before making use of this SDK or any derived software. - * - * - * You need to run full testing and qualification based on your own requirements to claim any performance of the combined system. - * - * - * Please be especially advised that any certification holding for the eego amplifier is not valid for a combined system of your application software and the eego amplifier. You must obtain your own certification for a combined system of amplifier and software. - */ - -// system -#pragma warning(disable: 4996) -#include -#include -#include -#include - -// eemagine -#include -#include -#include - -// It has to be either dynamic or static -#if !(defined(EEGO_SDK_BIND_DYNAMIC) ^ defined(EEGO_SDK_BIND_STATIC)) -#pragma message ("Neither EEGO_SDK_BIND_DYNAMIC nor EEGO_SDK_BIND_STATIC has been defined. Default to EEGO_SDK_BIND_DYNAMIC.") -#define EEGO_SDK_BIND_DYNAMIC -#endif - -#ifdef EEGO_SDK_BIND_DYNAMIC -#if !(defined(_UNICODE) ^ defined(_MBCS)) -#pragma message ("Neither _UNICODE nor _MBCS has been defined. Default to _UNICODE.") -#define _UNICODE -#endif - -// Find out what operating system we are using and default to WIN32 -#if !(defined(WIN32) ^ defined(__unix__)) -#pragma message ("Neither WIN32 nor __unix__ has been defined. Default to WIN32.") -#define WIN32 -#endif - -// For windows we are using UTF16 in any case! -#ifndef _UNICODE -#define _UNICODE -#endif -#ifndef UNICODE -#define UNICODE -#endif -#ifdef WIN32 -# include // For library loading -#endif -#ifdef __unix__ -# ifdef EEGO_SDK_BIND_DYNAMIC -# include -# endif -#endif -#endif - -// Function pointers to API functions to enable late bindings -class _sdkBindings -{ -public: - bool initialized; - /** - * @brief initialze sdk library - */ - eemagine_sdk_init_t init; - /** - * finalize sdk library - */ - eemagine_sdk_exit_t exit; - /** - * get the current sdk version - */ - eemagine_sdk_get_version_t get_version; - /** - * @brief get an array of connected amplifiers - */ - eemagine_sdk_get_amplifiers_info_t get_amplifiers_info; - /** - * get the channel list from an amplifier - */ - eemagine_sdk_get_amplifier_channel_list_t get_amplifier_channel_list; - /** - * close amplifier - */ - eemagine_sdk_close_amplifier_t close_amplifier; - /** - * get the serial from an amplifier - */ - eemagine_sdk_get_amplifier_serial_t get_amplifier_serial; - /** - * get the firmware version of the amplifier - */ - eemagine_sdk_get_amplifier_version_t get_amplifier_version; - /** - * get the type for this amplifier - */ - eemagine_sdk_get_amplifier_type_t get_amplifier_type; - /** - * get a list of sampling rates that are available - */ - eemagine_sdk_get_amplifier_sampling_rates_available_t get_amplifier_sampling_rates_available; - /** - * get a list of reference ranges that are available - */ - eemagine_sdk_get_amplifier_reference_ranges_available_t get_amplifier_reference_ranges_available; - /** - * get a list of bipolar ranges that are available - */ - eemagine_sdk_get_amplifier_bipolar_ranges_available_t get_amplifier_bipolar_ranges_available; - /** - * open eeg stream, returns handle on success. if handle is negative, it indicates an error - */ - eemagine_sdk_open_eeg_stream_t open_eeg_stream; - /** - * open impedance stream, returns handle on success. if handle is negative, it indicates an error - */ - eemagine_sdk_open_impedance_stream_t open_impedance_stream; - /** - * close stream - */ - eemagine_sdk_close_stream_t close_stream; - /** - * get the channel list from a stream - */ - eemagine_sdk_get_stream_channel_list_t get_stream_channel_list; - /** - * get the channel count from a stream - */ - eemagine_sdk_get_stream_channel_count_t get_stream_channel_count; - /** - * prefetch - */ - eemagine_sdk_prefetch_t prefetch; - /** - * get data - */ - eemagine_sdk_get_data_t get_data; - /** - * get error string - */ - eemagine_sdk_get_error_string_t get_error_string; - - // Mark a freshly constructed class as unintialized - _sdkBindings() - : initialized(false) - {} -}; - -// The binding itself -_sdkBindings _sdk; - -/////////////////////////////////////////////////////////////////////////////// -// Creates an exception from an returned error value -int -_return_value_guard(int rv) { - char msg[1024]; - switch (rv) { - case EEMAGINE_SDK_NOT_CONNECTED: - _sdk.get_error_string(msg, 1024); - throw(eemagine::sdk::exceptions::notConnected(msg)); - break; - case EEMAGINE_SDK_ALREADY_EXISTS: - _sdk.get_error_string(msg, 1024); - throw(eemagine::sdk::exceptions::alreadyExists(msg)); - break; - case EEMAGINE_SDK_NOT_FOUND: - _sdk.get_error_string(msg, 1024); - throw(eemagine::sdk::exceptions::notFound(msg)); - break; - case EEMAGINE_SDK_INCORRECT_VALUE: - _sdk.get_error_string(msg, 1024); - throw(eemagine::sdk::exceptions::incorrectValue(msg)); - break; - case EEMAGINE_SDK_UNKNOWN: - _sdk.get_error_string(msg, 1024); - throw(eemagine::sdk::exceptions::unknown(msg)); - break; - } - return rv; -} - -std::vector _channelArrayToVector(eemagine_sdk_channel_info* channelPtr, unsigned int channelCount) -{ - std::vector rv; // the list to be filled - rv.reserve(channelCount); - - for(unsigned channel = 0; channel < channelCount; ++channel) - { - eemagine_sdk_channel_info* read_ptr = channelPtr + channel; - if (read_ptr->index < 0) - { - throw eemagine::sdk::exceptions::unknown("Channel index is below zero: " + read_ptr->index); - } - unsigned index = read_ptr->index; - switch (read_ptr->type) { - case EEMAGINE_SDK_CHANNEL_TYPE_REFERENCE: - rv.push_back(eemagine::sdk::channel(index, eemagine::sdk::channel::reference)); - break; - case EEMAGINE_SDK_CHANNEL_TYPE_BIPOLAR: - rv.push_back(eemagine::sdk::channel(index, eemagine::sdk::channel::bipolar)); - break; - case EEMAGINE_SDK_CHANNEL_TYPE_TRIGGER: - rv.push_back(eemagine::sdk::channel(index, eemagine::sdk::channel::trigger)); - break; - case EEMAGINE_SDK_CHANNEL_TYPE_SAMPLE_COUNTER: - rv.push_back(eemagine::sdk::channel(index, eemagine::sdk::channel::sample_counter)); - break; - case EEMAGINE_SDK_CHANNEL_TYPE_IMPEDANCE_REFERENCE: - rv.push_back(eemagine::sdk::channel(index, eemagine::sdk::channel::impedance_reference)); - break; - case EEMAGINE_SDK_CHANNEL_TYPE_IMPEDANCE_GROUND: - rv.push_back(eemagine::sdk::channel(index, eemagine::sdk::channel::impedance_ground)); - break; - default: - throw eemagine::sdk::exceptions::unknown("Channel type unknown: " + read_ptr->type); - } - } - - return rv; -} - -/////////////////////////////////////////////////////////////////////////////// -class _sdk_stream : public eemagine::sdk::stream -{ -public: - _sdk_stream(int stream_id) - : _stream_id(stream_id) - , _channelCount(_return_value_guard(_sdk.get_stream_channel_count(_stream_id))) - { - } - - ~_sdk_stream() { - _sdk.close_stream(_stream_id); - } - - unsigned int getChannelCount() { - return _channelCount; - } - - eemagine::sdk::buffer getData() { - int bytes_to_allocate(_return_value_guard(_sdk.prefetch(_stream_id))); - size_t double_count(bytes_to_allocate / sizeof(double)); - eemagine::sdk::buffer rv(getChannelCount(), double_count / getChannelCount()); - _return_value_guard(_sdk.get_data(_stream_id, rv.data(), bytes_to_allocate)); - return rv; - } - - std::vector getChannelList() const - { - // get amount of channels first and transform it into external format - eemagine_sdk_channel_info channel_info_array[1024]; - int channel_count = _return_value_guard(_sdk.get_stream_channel_list(_stream_id, channel_info_array, 1024)); - return _channelArrayToVector(channel_info_array, channel_count); - } - -protected: - const int _stream_id; - const unsigned int _channelCount; -}; - -/////////////////////////////////////////////////////////////////////////////// -class _sdk_amplifier : public eemagine::sdk::amplifier { -public: - _sdk_amplifier(eemagine_sdk_amplifier_info info) : _amplifier_id(info.id) { } - ~_sdk_amplifier() { _sdk.close_amplifier(_amplifier_id); } - - std::string getSerialNumber() const override { - char serial[1024]; - _return_value_guard(_sdk.get_amplifier_serial(_amplifier_id, serial, 1024)); - return std::string(serial); - } - - int getFirmwareVersion() const override { - return _return_value_guard(_sdk.get_amplifier_version(_amplifier_id)); - } - - std::string getType() const override { - char type[1024]; - _return_value_guard(_sdk.get_amplifier_type(_amplifier_id, type, 1024)); - return std::string(type); - } - - std::vector getChannelList() const override { - std::vector rv; - eemagine_sdk_channel_info channel_info_array[1024]; - int channel_count = _return_value_guard(_sdk.get_amplifier_channel_list(_amplifier_id, channel_info_array, 1024)); - return _channelArrayToVector(channel_info_array, channel_count); - } - - std::vector getSamplingRatesAvailable() const override { - std::vector rv; - int sampling_rate_array[1024]; - int sampling_rate_count = _return_value_guard(_sdk.get_amplifier_sampling_rates_available(_amplifier_id, sampling_rate_array, 1024)); - rv.resize(sampling_rate_count); - std::vector::iterator rv_iter(rv.begin()); - const int * read_ptr(sampling_rate_array); - while (sampling_rate_count) { - *rv_iter = *read_ptr; - ++rv_iter; - ++read_ptr; - --sampling_rate_count; - } - return rv; - } - - std::vector getReferenceRangesAvailable() const override { - std::vector rv; - double reference_range_array[1024]; - int reference_range_count = _return_value_guard(_sdk.get_amplifier_reference_ranges_available(_amplifier_id, reference_range_array, 1024)); - rv.resize(reference_range_count); - std::vector::iterator rv_iter(rv.begin()); - const double * read_ptr(reference_range_array); - while (reference_range_count) { - *rv_iter = *read_ptr; - ++rv_iter; - ++read_ptr; - --reference_range_count; - } - return rv; - } - - std::vector getBipolarRangesAvailable() const override { - std::vector rv; - double bipolar_range_array[1024]; - int bipolar_range_count = _return_value_guard(_sdk.get_amplifier_bipolar_ranges_available(_amplifier_id, bipolar_range_array, 1024)); - rv.resize(bipolar_range_count); - std::vector::iterator rv_iter(rv.begin()); - const double * read_ptr(bipolar_range_array); - while (bipolar_range_count) { - *rv_iter = *read_ptr; - ++rv_iter; - ++read_ptr; - --bipolar_range_count; - } - return rv; - } - - eemagine::sdk::stream * OpenEegStream(int sampling_rate, double reference_range, double bipolar_range, unsigned long long ref_mask, unsigned long long bip_mask) { - int stream_id = _return_value_guard(_sdk.open_eeg_stream(_amplifier_id, sampling_rate, reference_range, bipolar_range, ref_mask, bip_mask)); - return new _sdk_stream(stream_id); - } - - eemagine::sdk::stream * OpenImpedanceStream(unsigned long long ref_mask) { - int stream_id = _return_value_guard(_sdk.open_impedance_stream(_amplifier_id, ref_mask)); - return new _sdk_stream(stream_id); - } -protected: - int _amplifier_id; -}; -/////////////////////////////////////////////////////////////////////////////// -class _sdk_guard { -public: - _sdk_guard() { - _sdk.init(); - } - ~_sdk_guard() { - _sdk.exit(); - } - - void incrementAmplifierReferenceCount(const eemagine_sdk_amplifier_info & info) { - for (std::vector<_amp_ref_count>::iterator i = _amplifier_reference_count_vector.begin(); - i != _amplifier_reference_count_vector.end(); - ++i) - { - if (info.id == i->info.id) { - ++i->ref_count; - return; - } - } - // if we got here, we didn't find one, so create - _amp_ref_count arc; - arc.ref_count = 2; - arc.info.id = info.id; - strncpy(arc.info.serial, info.serial, 64); - arc.amp = new _sdk_amplifier(info); - _amplifier_reference_count_vector.push_back(arc); - } - - void sweepAmplifierReferenceCounts() { - for (std::vector<_amp_ref_count>::iterator i = _amplifier_reference_count_vector.begin(); i != _amplifier_reference_count_vector.end();) { - --i->ref_count; - if (i->ref_count == 0) { - i = _amplifier_reference_count_vector.erase(i); - } - else { - ++i; - } - } - } - - std::vector getAmplifiers() { - std::vector rv; - for (std::vector<_amp_ref_count>::iterator i = _amplifier_reference_count_vector.begin(); i != _amplifier_reference_count_vector.end(); ++i) { - rv.push_back(i->amp); - } - return rv; - } - -protected: - struct _amp_ref_count { - int ref_count; - eemagine_sdk_amplifier_info info; - eemagine::sdk::amplifier * amp; - }; - std::vector<_amp_ref_count> _amplifier_reference_count_vector; -}; - -/////////////////////////////////////////////////////////////////////////////// -_sdk_guard * -_get_sdk_guard_singleton(bool release = false) { - // singleton to sdk initializer guard - static _sdk_guard * _guard = NULL; - - if (release && _guard != NULL) { - delete _guard; - _guard = NULL; - return NULL; - } - if (_guard == NULL) { - _guard = new _sdk_guard(); - } - - return _guard; -} - -/////////////////////////////////////////////////////////////////////////////// -#ifdef EEGO_SDK_BIND_STATIC -// trivial case: The dll is bound during compile time. All we have to do is -// assign the defined symbols to the _sdk structure. -eemagine::sdk::factory::factory() -{ - // Check version first - if (eemagine_sdk_get_version() != EEGO_SDK_VERSION) - { - throw(exceptions::incorrectValue("Eego SDK version mismatch")); - } - - if (_sdk.initialized == false) - { - _sdk.init = eemagine_sdk_init; - _sdk.exit = eemagine_sdk_exit; - _sdk.get_version = eemagine_sdk_get_version; - _sdk.get_amplifiers_info = eemagine_sdk_get_amplifiers_info; - _sdk.close_amplifier = eemagine_sdk_close_amplifier; - _sdk.get_amplifier_channel_list = eemagine_sdk_get_amplifier_channel_list; - _sdk.get_amplifier_serial = eemagine_sdk_get_amplifier_serial; - _sdk.get_amplifier_version = eemagine_sdk_get_amplifier_version; - _sdk.get_amplifier_type = eemagine_sdk_get_amplifier_type; - _sdk.get_amplifier_sampling_rates_available = eemagine_sdk_get_amplifier_sampling_rates_available; - _sdk.get_amplifier_reference_ranges_available = eemagine_sdk_get_amplifier_reference_ranges_available; - _sdk.get_amplifier_bipolar_ranges_available = eemagine_sdk_get_amplifier_bipolar_ranges_available; - _sdk.open_eeg_stream = eemagine_sdk_open_eeg_stream; - _sdk.open_impedance_stream = eemagine_sdk_open_impedance_stream; - _sdk.close_stream = eemagine_sdk_close_stream; - _sdk.get_stream_channel_list = eemagine_sdk_get_stream_channel_list; - _sdk.get_stream_channel_count = eemagine_sdk_get_stream_channel_count; - _sdk.prefetch = eemagine_sdk_prefetch; - _sdk.get_data = eemagine_sdk_get_data; - _sdk.get_error_string = eemagine_sdk_get_error_string; - _sdk.initialized = true; - } -} -#else -// More complicated case. The path to the dll is provided by call to the factory. -// That DLL has to be loaded and the function pointers have to be searched in there. -// When found they are assigned to the right place in the _sdk structure. -// If they are not found raise a runtime exception - -/////////////////////////////////////////////////////////////////////////////////////////////////////// -/// All the diffenrent string encodings have to be normalized to utf-8 string for internal handling. -/// To connect to windows methods wide character strings have to be used. -/// String handling methods follow. -/////////////////////////////////////////////////////////////////////////////////////////////////////// -#ifdef WIN32 -static std::string UTF16toUTF8(const std::wstring& utf16String) -{ - // empty - if (utf16String.empty()) - return std::string(); - - // get length of conversion first or see if there is an error - const int utf8length = ::WideCharToMultiByte( - CP_UTF8, WC_ERR_INVALID_CHARS, utf16String.data(), utf16String.length(), // Input - NULL, 0, // just check - NULL, NULL); // invalid for utf8 - - if (utf8length == 0) // Must be error, as empty string should not happen here anymore - { - const DWORD error = ::GetLastError(); - if (error == ERROR_NO_UNICODE_TRANSLATION) - throw eemagine::sdk::exceptions::incorrectValue("Failure of string conversion from utf16, invalid characters."); - - throw eemagine::sdk::exceptions::incorrectValue("Failure to classify utf16 string. errorcode: " + error); - } - - std::string retvalUTF8; - retvalUTF8.resize(utf8length); - - const int convertedLength = ::WideCharToMultiByte( - CP_UTF8, 0, utf16String.data(), utf16String.length(), // Input - &retvalUTF8[0], retvalUTF8.length(), - NULL, NULL); // invalid for utf8 - - if (convertedLength == 0) - { - throw eemagine::sdk::exceptions::incorrectValue("Failure to convert utf16 string."); - } - - return retvalUTF8; -} - -static std::wstring MBCStoUTF16(const std::string& mbcsString) -{ - // empty - if (mbcsString.empty()) - return std::wstring(); - - // get length of conversion first or see if there is an error - const int wideLength = ::MultiByteToWideChar( - CP_ACP, MB_ERR_INVALID_CHARS, mbcsString.data(), mbcsString.length(), // Input - NULL, 0); // just check - if (wideLength == 0) // Must be error, as empty string should not happen here anymore - { - const DWORD error = ::GetLastError(); - if (error == ERROR_NO_UNICODE_TRANSLATION) - throw eemagine::sdk::exceptions::incorrectValue("Failure of string conversion from mbcsString, invalid characters: " + mbcsString); - - std::stringstream errormsg; - errormsg << "Failure to convert mbcsString: " << mbcsString << " Error code: " << error; - throw eemagine::sdk::exceptions::incorrectValue(errormsg.str()); - } - - // conversion exists! Let's do it - std::wstring returnStringUTF16; - returnStringUTF16.resize(wideLength); - - const int convertResult = ::MultiByteToWideChar( - CP_ACP, 0, mbcsString.data(), mbcsString.length(), // Input - &returnStringUTF16[0], returnStringUTF16.length()); // fill it - - if (convertResult == 0) // We already verified the string. Not recoverable - { - const DWORD error = ::GetLastError(); - std::stringstream errormsg; - errormsg << "Conversion failed from mbcsString: " << mbcsString << " Error code: " << error; - throw eemagine::sdk::exceptions::incorrectValue(errormsg.str()); - } - - return returnStringUTF16; -} - -static std::wstring UTF8ToUTF16(const std::string& utf8String) -{ - // empty - if (utf8String.empty()) - return std::wstring(); - - // get length of conversion first or see if there is an error - const int wideLength = ::MultiByteToWideChar( - CP_UTF8, MB_ERR_INVALID_CHARS, utf8String.data(), utf8String.length(), // Input - NULL, 0); // just check - if (wideLength == 0) // Must be error, as empty string should not happen here anymore - { - const DWORD error = ::GetLastError(); - if (error == ERROR_NO_UNICODE_TRANSLATION) - throw eemagine::sdk::exceptions::incorrectValue("Failure of string conversion from utf8, invalid characters: " + utf8String); - - std::stringstream errormsg; - errormsg << "Failure to convert utf8 string: " << utf8String << " Error code: " << error; - throw eemagine::sdk::exceptions::incorrectValue(errormsg.str()); - } - - // conversion exists! Let's do it - std::wstring returnStringUTF16; - returnStringUTF16.resize(wideLength); - - const int convertResult = ::MultiByteToWideChar( - CP_UTF8, 0, utf8String.data(), utf8String.length(), // Input - &returnStringUTF16[0], returnStringUTF16.length()); // fill it - - if (convertResult == 0) // - { - const DWORD error = ::GetLastError(); - std::stringstream errormsg; - errormsg << "Conversion failed from utf8: " << utf8String << " Error code: " << error; - throw eemagine::sdk::exceptions::incorrectValue(errormsg.str()); - } - - return returnStringUTF16; -} - -static std::string MBCStoUTF8(const std::string& mbcsString) -{ - return UTF16toUTF8(MBCStoUTF16(mbcsString)); -} -#endif - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/// String conversion ends here. -/// -/// In the following functions we will load the exported functions from the DLL loaded from the path provided by the user. -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -// Helper class for library loading: -// Find funcName in dll specified by libHandle -// If the function can not be found or another error has occured raise runtime_error. -#ifdef WIN32 -typedef HINSTANCE library_handle_type; -template -static T getFunc(library_handle_type libHandle, const char* funcName) -{ - // load - T func = (T)::GetProcAddress(libHandle, funcName); - - // check - if (func == NULL) - { - throw(eemagine::sdk::exceptions::incorrectValue(std::string("Can't load function: ") + funcName)); - } - - return func; -} -library_handle_type -LoadSDKLibrary(const std::string &libPathUtf8) { - const std::wstring libPathUTF16(UTF8ToUTF16(libPathUtf8)); - - library_handle_type oLibHandle = ::LoadLibrary(libPathUTF16.c_str()); - if (oLibHandle == NULL) - { - throw(eemagine::sdk::exceptions::incorrectValue("Could not load Library: " + libPathUtf8)); - } - return oLibHandle; -} -#endif -#ifdef __unix__ -typedef void * library_handle_type; -template -static T getFunc(library_handle_type libHandle, const char* funcName) -{ - void * symbol(dlsym(libHandle, funcName)); - if (symbol == NULL) - { - throw(eemagine::sdk::exceptions::incorrectValue(std::string("Can't load function: ") + funcName)); - } - - return (T)(symbol); -} -library_handle_type -LoadSDKLibrary(const std::string &filename) { - library_handle_type rv(dlopen(filename.c_str(), RTLD_LAZY)); - if (rv == NULL) - { - throw(eemagine::sdk::exceptions::incorrectValue("Could not load Library: " + filename + " error: " + dlerror())); - } - return rv; -} -#endif - -static void loadLibraryUTF8(const std::string& libPathUTF8) -{ - // Only load functions once - if (_sdk.initialized == false) - { - // Load DLL and check - library_handle_type oLibHandle = LoadSDKLibrary(libPathUTF8); - - // Let us load the get version pointer first to have more meaningful error messages - // if some functions do not exist. - _sdk.get_version = getFunc(oLibHandle, "eemagine_sdk_get_version"); - if (_sdk.get_version() != EEGO_SDK_VERSION) - { - throw(eemagine::sdk::exceptions::incorrectValue("Eego SDK version mismatch")); - } - - - // Load function pointers from DLL; - _sdk.init = getFunc(oLibHandle, "eemagine_sdk_init"); - _sdk.exit = getFunc(oLibHandle, "eemagine_sdk_exit"); - _sdk.get_amplifiers_info = getFunc(oLibHandle, "eemagine_sdk_get_amplifiers_info"); - _sdk.close_amplifier = getFunc(oLibHandle, "eemagine_sdk_close_amplifier"); - _sdk.get_amplifier_channel_list = getFunc(oLibHandle, "eemagine_sdk_get_amplifier_channel_list"); - _sdk.get_amplifier_serial = getFunc(oLibHandle, "eemagine_sdk_get_amplifier_serial"); - _sdk.get_amplifier_version = getFunc(oLibHandle, "eemagine_sdk_get_amplifier_version"); - _sdk.get_amplifier_type = getFunc(oLibHandle, "eemagine_sdk_get_amplifier_type"); - _sdk.get_amplifier_sampling_rates_available = getFunc(oLibHandle, "eemagine_sdk_get_amplifier_sampling_rates_available"); - _sdk.get_amplifier_reference_ranges_available = getFunc(oLibHandle, "eemagine_sdk_get_amplifier_reference_ranges_available"); - _sdk.get_amplifier_bipolar_ranges_available = getFunc(oLibHandle, "eemagine_sdk_get_amplifier_bipolar_ranges_available"); - _sdk.open_eeg_stream = getFunc(oLibHandle, "eemagine_sdk_open_eeg_stream"); - _sdk.open_impedance_stream = getFunc(oLibHandle, "eemagine_sdk_open_impedance_stream"); - _sdk.close_stream = getFunc(oLibHandle, "eemagine_sdk_close_stream"); - _sdk.get_stream_channel_list = getFunc(oLibHandle, "eemagine_sdk_get_stream_channel_list"); - _sdk.get_stream_channel_count = getFunc(oLibHandle, "eemagine_sdk_get_stream_channel_count"); - _sdk.prefetch = getFunc(oLibHandle, "eemagine_sdk_prefetch"); - _sdk.get_data = getFunc(oLibHandle, "eemagine_sdk_get_data"); - _sdk.get_error_string = getFunc(oLibHandle, "eemagine_sdk_get_error_string"); - - _sdk.initialized = true; - } - - // all ok! -} - -#ifdef WIN32 -eemagine::sdk::factory::factory(const std::wstring& libPath) -{ - loadLibraryUTF8(UTF16toUTF8(libPath)); -} -#endif - -eemagine::sdk::factory::factory(const std::string& libPath) -{ -#if defined(_MBCS) - loadLibraryUTF8(MBCStoUTF8(libPath)); -#elif defined(_UNICODE) - loadLibraryUTF8(libPath); -#else -#error "Undefined string handling" -#endif -} -#endif - -/////////////////////////////////////////////////////////////////////////////// -eemagine::sdk::factory::~factory() { - _get_sdk_guard_singleton()->sweepAmplifierReferenceCounts(); - _get_sdk_guard_singleton(true); -} - -/////////////////////////////////////////////////////////////////////////////// -std::vector -eemagine::sdk::factory::getAmplifiers() { - _sdk_guard * sg = _get_sdk_guard_singleton(); - - // get list from c layer first - eemagine_sdk_amplifier_info amplifier_info_array[64]; - int amplifier_count = _sdk.get_amplifiers_info(amplifier_info_array, 64); - - // mark - for (int amp_id = 0; amp_id < amplifier_count; ++amp_id) { - sg->incrementAmplifierReferenceCount(amplifier_info_array[amp_id]); - } - - // sweep - sg->sweepAmplifierReferenceCounts(); - - return sg->getAmplifiers(); -} - -/////////////////////////////////////////////////////////////////////////////// -eemagine::sdk::amplifier * -eemagine::sdk::factory::getAmplifier() { - eemagine::sdk::amplifier * rv = NULL; - std::vector amplifier_list = getAmplifiers(); - - if (amplifier_list.empty()) { - throw(eemagine::sdk::exceptions::notFound("amplifier list is empty")); - } - - std::vector::iterator iter = amplifier_list.begin(); - rv = *iter; - // clean references - while (++iter != amplifier_list.end()) { - delete *iter; - } - - return rv; -} - -/////////////////////////////////////////////////////////////////////////////// -eemagine::sdk::factory::version -eemagine::sdk::factory::getVersion() const { - eemagine::sdk::factory::version rv; - rv.major = EEGO_SDK_VERSION_MAJOR; - rv.minor = EEGO_SDK_VERSION_MINOR; - rv.micro = EEGO_SDK_VERSION_MICRO; - rv.build = EEGO_SDK_VERSION; - return rv; -} +/* + * License: eego amplifier Interface SDK, rev. 1.3 + * + * + * Copyright 2015, eemagine Medical Imaging Solutions GmbH + * + * + * 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 above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + * + * 3. All advertising materials mentioning features or use of this software must display the following acknowledgement: This product includes software developed by the eemagine Medical Imaging Solutions GmbH. + * + * 4. Neither the name of the eemagine Medical Imaging Solutions GmbH nor the names of its contributors or products may be used to endorse or promote products derived from this software without specific prior written permission by eemagine + * + * + * This Software is provided by eemagine Medical Imaging Solutions GmbH ''As Is'' and any express or implied warranties, including, but not limited to, the implied warranties merchantability and fitness for a particular purpose are disclaimed. In no event shall eemagine 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. + * + * The eego amplifier comes with its own user manual, which must be read carefully before making use of this SDK or any derived software. + * + * + * You need to run full testing and qualification based on your own requirements to claim any performance of the combined system. + * + * + * Please be especially advised that any certification holding for the eego amplifier is not valid for a combined system of your application software and the eego amplifier. You must obtain your own certification for a combined system of amplifier and software. + */ + +// system +#pragma warning(disable: 4996) +#include +#include +#include +#include + +// eemagine +#include +#include +#include + +// It has to be either dynamic or static +#if !(defined(EEGO_SDK_BIND_DYNAMIC) ^ defined(EEGO_SDK_BIND_STATIC)) +#pragma message ("Neither EEGO_SDK_BIND_DYNAMIC nor EEGO_SDK_BIND_STATIC has been defined. Default to EEGO_SDK_BIND_DYNAMIC.") +#define EEGO_SDK_BIND_DYNAMIC +#endif + +#ifdef EEGO_SDK_BIND_DYNAMIC +#if !(defined(_UNICODE) ^ defined(_MBCS)) +#pragma message ("Neither _UNICODE nor _MBCS has been defined. Default to _UNICODE.") +#define _UNICODE +#endif + +// Find out what operating system we are using and default to _WIN32 +#if !(defined(_WIN32) ^ defined(__unix__)) +#pragma message ("Neither _WIN32 nor __unix__ has been defined. Default to _WIN32.") +#define _WIN32 +#endif + +// For windows we are using UTF16 in any case! +#ifndef _UNICODE +#define _UNICODE +#endif +#ifndef UNICODE +#define UNICODE +#endif +#ifdef _WIN32 +# include // For library loading +#endif +#ifdef __unix__ +# ifdef EEGO_SDK_BIND_DYNAMIC +# include +# endif +#endif +#endif + +// Function pointers to API functions to enable late bindings +class _sdkBindings +{ +public: + bool initialized; + /** + * @brief setup sdk library + */ + eemagine_sdk_setup_t setup; + /** + * @brief initialze sdk library + */ + eemagine_sdk_init_t init; + /** + * finalize sdk library + */ + eemagine_sdk_exit_t exit; + /** + * get the current sdk version + */ + eemagine_sdk_get_version_t get_version; + /** + * @brief get an array of connected amplifiers + */ + eemagine_sdk_get_amplifiers_info_t get_amplifiers_info; + /** + * get the channel list from an amplifier + */ + eemagine_sdk_get_amplifier_channel_list_t get_amplifier_channel_list; + /** + * close amplifier + */ + eemagine_sdk_close_amplifier_t close_amplifier; + /** + * get the serial from an amplifier + */ + eemagine_sdk_get_amplifier_serial_t get_amplifier_serial; + /** + * get the firmware version of the amplifier + */ + eemagine_sdk_get_amplifier_version_t get_amplifier_version; + /** + * get the type for this amplifier + */ + eemagine_sdk_get_amplifier_type_t get_amplifier_type; + /** + * get a list of sampling rates that are available + */ + eemagine_sdk_get_amplifier_sampling_rates_available_t get_amplifier_sampling_rates_available; + /** + * get a list of reference ranges that are available + */ + eemagine_sdk_get_amplifier_reference_ranges_available_t get_amplifier_reference_ranges_available; + /** + * get a list of bipolar ranges that are available + */ + eemagine_sdk_get_amplifier_bipolar_ranges_available_t get_amplifier_bipolar_ranges_available; + /** + * open eeg stream, returns handle on success. if handle is negative, it indicates an error + */ + eemagine_sdk_open_eeg_stream_t open_eeg_stream; + /** + * open impedance stream, returns handle on success. if handle is negative, it indicates an error + */ + eemagine_sdk_open_impedance_stream_t open_impedance_stream; + /** + * close stream + */ + eemagine_sdk_close_stream_t close_stream; + /** + * get the channel list from a stream + */ + eemagine_sdk_get_stream_channel_list_t get_stream_channel_list; + /** + * get the channel count from a stream + */ + eemagine_sdk_get_stream_channel_count_t get_stream_channel_count; + /** + * prefetch + */ + eemagine_sdk_prefetch_t prefetch; + /** + * get data + */ + eemagine_sdk_get_data_t get_data; + /** + * get error string + */ + eemagine_sdk_get_error_string_t get_error_string; + + // Mark a freshly constructed class as unintialized + _sdkBindings() + : initialized(false) + {} +}; + +// The binding itself +_sdkBindings _sdk; + +/////////////////////////////////////////////////////////////////////////////// +// Creates an exception from an returned error value +int +_return_value_guard(int rv) { + char msg[1024]; + switch (rv) { + case EEMAGINE_SDK_NOT_CONNECTED: + _sdk.get_error_string(msg, 1024); + throw(eemagine::sdk::exceptions::notConnected(msg)); + break; + case EEMAGINE_SDK_ALREADY_EXISTS: + _sdk.get_error_string(msg, 1024); + throw(eemagine::sdk::exceptions::alreadyExists(msg)); + break; + case EEMAGINE_SDK_NOT_FOUND: + _sdk.get_error_string(msg, 1024); + throw(eemagine::sdk::exceptions::notFound(msg)); + break; + case EEMAGINE_SDK_INCORRECT_VALUE: + _sdk.get_error_string(msg, 1024); + throw(eemagine::sdk::exceptions::incorrectValue(msg)); + break; + case EEMAGINE_SDK_UNKNOWN: + _sdk.get_error_string(msg, 1024); + throw(eemagine::sdk::exceptions::unknown(msg)); + break; + } + return rv; +} + +std::vector _channelArrayToVector(eemagine_sdk_channel_info* channelPtr, unsigned int channelCount) +{ + std::vector rv; // the list to be filled + rv.reserve(channelCount); + + for (unsigned channel = 0; channel < channelCount; ++channel) + { + eemagine_sdk_channel_info* read_ptr = channelPtr + channel; + if (read_ptr->index < 0) + { + throw eemagine::sdk::exceptions::unknown("Channel index is below zero: " + read_ptr->index); + } + unsigned index = read_ptr->index; + switch (read_ptr->type) { + case EEMAGINE_SDK_CHANNEL_TYPE_REFERENCE: + rv.push_back(eemagine::sdk::channel(index, eemagine::sdk::channel::reference)); + break; + case EEMAGINE_SDK_CHANNEL_TYPE_BIPOLAR: + rv.push_back(eemagine::sdk::channel(index, eemagine::sdk::channel::bipolar)); + break; + case EEMAGINE_SDK_CHANNEL_TYPE_TRIGGER: + rv.push_back(eemagine::sdk::channel(index, eemagine::sdk::channel::trigger)); + break; + case EEMAGINE_SDK_CHANNEL_TYPE_SAMPLE_COUNTER: + rv.push_back(eemagine::sdk::channel(index, eemagine::sdk::channel::sample_counter)); + break; + case EEMAGINE_SDK_CHANNEL_TYPE_IMPEDANCE_REFERENCE: + rv.push_back(eemagine::sdk::channel(index, eemagine::sdk::channel::impedance_reference)); + break; + case EEMAGINE_SDK_CHANNEL_TYPE_IMPEDANCE_GROUND: + rv.push_back(eemagine::sdk::channel(index, eemagine::sdk::channel::impedance_ground)); + break; + case EEMAGINE_SDK_CHANNEL_TYPE_ACCELEROMETER: + rv.push_back(eemagine::sdk::channel(index, eemagine::sdk::channel::accelerometer)); + break; + case EEMAGINE_SDK_CHANNEL_TYPE_GYROSCOPE: + rv.push_back(eemagine::sdk::channel(index, eemagine::sdk::channel::gyroscope)); + break; + case EEMAGINE_SDK_CHANNEL_TYPE_MAGNETOMETER: + rv.push_back(eemagine::sdk::channel(index, eemagine::sdk::channel::magnetometer)); + break; + default: + throw eemagine::sdk::exceptions::unknown("Channel type unknown: " + read_ptr->type); + } + } + + return rv; +} + +/////////////////////////////////////////////////////////////////////////////// +class _sdk_stream : public eemagine::sdk::stream +{ +public: + _sdk_stream(int stream_id) + : _stream_id(stream_id) + , _channelCount(_return_value_guard(_sdk.get_stream_channel_count(_stream_id))) + { + } + + ~_sdk_stream() { + _sdk.close_stream(_stream_id); + } + + unsigned int getChannelCount() { + return _channelCount; + } + + eemagine::sdk::buffer getData() { + int bytes_to_allocate(_return_value_guard(_sdk.prefetch(_stream_id))); + int double_count(bytes_to_allocate / sizeof(double)); + eemagine::sdk::buffer rv(getChannelCount(), double_count / getChannelCount()); + _return_value_guard(_sdk.get_data(_stream_id, rv.data(), bytes_to_allocate)); + return rv; + } + + std::vector getChannelList() const + { + // get amount of channels first and transform it into external format + eemagine_sdk_channel_info channel_info_array[1024]; + int channel_count = _return_value_guard(_sdk.get_stream_channel_list(_stream_id, channel_info_array, 1024)); + return _channelArrayToVector(channel_info_array, channel_count); + } + +protected: + const int _stream_id; + const unsigned int _channelCount; +}; + +/////////////////////////////////////////////////////////////////////////////// + +void increment_amplifier_reference_count(const eemagine_sdk_amplifier_info & info); +void decrement_amplifier_reference_count(const eemagine_sdk_amplifier_info & info); + +/////////////////////////////////////////////////////////////////////////////// +class _sdk_amplifier : public eemagine::sdk::amplifier { +public: + _sdk_amplifier(eemagine_sdk_amplifier_info info) : _amplifier_info(info) { + } + ~_sdk_amplifier() { + _sdk.close_amplifier(_amplifier_info.id); + decrement_amplifier_reference_count(_amplifier_info); + } + + std::string getSerialNumber() const override { + char serial[1024]; + _return_value_guard(_sdk.get_amplifier_serial(_amplifier_info.id, serial, 1024)); + return std::string(serial); + } + + int getFirmwareVersion() const override { + return _return_value_guard(_sdk.get_amplifier_version(_amplifier_info.id)); + } + + std::string getType() const override { + char type[1024]; + _return_value_guard(_sdk.get_amplifier_type(_amplifier_info.id, type, 1024)); + return std::string(type); + } + + std::vector getChannelList() const override { + std::vector rv; + eemagine_sdk_channel_info channel_info_array[1024]; + int channel_count = _return_value_guard(_sdk.get_amplifier_channel_list(_amplifier_info.id, channel_info_array, 1024)); + return _channelArrayToVector(channel_info_array, channel_count); + } + + std::vector getSamplingRatesAvailable() const override { + std::vector rv; + int sampling_rate_array[1024]; + int sampling_rate_count = _return_value_guard(_sdk.get_amplifier_sampling_rates_available(_amplifier_info.id, sampling_rate_array, 1024)); + rv.resize(sampling_rate_count); + std::vector::iterator rv_iter(rv.begin()); + const int * read_ptr(sampling_rate_array); + while (sampling_rate_count) { + *rv_iter = *read_ptr; + ++rv_iter; + ++read_ptr; + --sampling_rate_count; + } + return rv; + } + + std::vector getReferenceRangesAvailable() const override { + std::vector rv; + double reference_range_array[1024]; + int reference_range_count = _return_value_guard(_sdk.get_amplifier_reference_ranges_available(_amplifier_info.id, reference_range_array, 1024)); + rv.resize(reference_range_count); + std::vector::iterator rv_iter(rv.begin()); + const double * read_ptr(reference_range_array); + while (reference_range_count) { + *rv_iter = *read_ptr; + ++rv_iter; + ++read_ptr; + --reference_range_count; + } + return rv; + } + + std::vector getBipolarRangesAvailable() const override { + std::vector rv; + double bipolar_range_array[1024]; + int bipolar_range_count = _return_value_guard(_sdk.get_amplifier_bipolar_ranges_available(_amplifier_info.id, bipolar_range_array, 1024)); + rv.resize(bipolar_range_count); + std::vector::iterator rv_iter(rv.begin()); + const double * read_ptr(bipolar_range_array); + while (bipolar_range_count) { + *rv_iter = *read_ptr; + ++rv_iter; + ++read_ptr; + --bipolar_range_count; + } + return rv; + } + + eemagine::sdk::stream * OpenEegStream(int sampling_rate, double reference_range, double bipolar_range, unsigned long long ref_mask, unsigned long long bip_mask) { + int stream_id = _return_value_guard(_sdk.open_eeg_stream(_amplifier_info.id, sampling_rate, reference_range, bipolar_range, ref_mask, bip_mask)); + return new _sdk_stream(stream_id); + } + + eemagine::sdk::stream * OpenImpedanceStream(unsigned long long ref_mask) { + int stream_id = _return_value_guard(_sdk.open_impedance_stream(_amplifier_info.id, ref_mask)); + return new _sdk_stream(stream_id); + } +protected: + eemagine_sdk_amplifier_info _amplifier_info; +}; +/////////////////////////////////////////////////////////////////////////////// +class _sdk_guard { +public: + _sdk_guard() { + _sdk.init(); + } + ~_sdk_guard() { + _sdk.exit(); + } + + void decrementAmplifierReferenceCount(const eemagine_sdk_amplifier_info & info) { + for (std::vector<_amp_ref_count>::iterator i = _amplifier_reference_count_vector.begin(); + i != _amplifier_reference_count_vector.end(); + ++i) + { + if (info.id != i->info.id) { + ++i->ref_count; + return; + } + } + } + void incrementAmplifierReferenceCount(const eemagine_sdk_amplifier_info & info) { + for (std::vector<_amp_ref_count>::iterator i = _amplifier_reference_count_vector.begin(); + i != _amplifier_reference_count_vector.end(); + ++i) + { + if (info.id == i->info.id) { + ++i->ref_count; + return; + } + } + // if we got here, we didn't find one, so create + _amp_ref_count arc; + arc.ref_count = 2; + arc.info.id = info.id; + strncpy(arc.info.serial, info.serial, 64); + arc.amp = new _sdk_amplifier(info); + _amplifier_reference_count_vector.push_back(arc); + } + + void sweepAmplifierReferenceCounts() { + for (std::vector<_amp_ref_count>::iterator i = _amplifier_reference_count_vector.begin(); i != _amplifier_reference_count_vector.end();) { + --i->ref_count; + if (i->ref_count == 0) { + i = _amplifier_reference_count_vector.erase(i); + } + else { + ++i; + } + } + } + + std::vector getAmplifiers() { + std::vector rv; + for (std::vector<_amp_ref_count>::iterator i = _amplifier_reference_count_vector.begin(); i != _amplifier_reference_count_vector.end(); ++i) { + rv.push_back(i->amp); + } + return rv; + } + +protected: + struct _amp_ref_count { + int ref_count; + eemagine_sdk_amplifier_info info; + eemagine::sdk::amplifier * amp; + }; + std::vector<_amp_ref_count> _amplifier_reference_count_vector; +}; +/////////////////////////////////////////////////////////////////////////////// +_sdk_guard * +_get_sdk_guard_singleton(bool release = false) { +#if _WIN32 && (_MSC_VER < 1900) + // singleton to sdk initializer guard + static _sdk_guard * _guard = NULL; + + if (release) { + if (_guard != NULL) { + delete _guard; + _guard = NULL; + } + } + else { + if (_guard == NULL) { + _guard = new _sdk_guard(); + } + } + return _guard; +#else + static _sdk_guard _guard_instance; + return & _guard_instance; +#endif +} +/////////////////////////////////////////////////////////////////////////////// +void increment_amplifier_reference_count(const eemagine_sdk_amplifier_info & info) { + _get_sdk_guard_singleton()->incrementAmplifierReferenceCount(info); +} +void decrement_amplifier_reference_count(const eemagine_sdk_amplifier_info & info) { + _get_sdk_guard_singleton()->decrementAmplifierReferenceCount(info); + _get_sdk_guard_singleton()->sweepAmplifierReferenceCounts(); +} +/////////////////////////////////////////////////////////////////////////////// +#ifdef EEGO_SDK_BIND_STATIC +// trivial case: The dll is bound during compile time. All we have to do is +// assign the defined symbols to the _sdk structure. +eemagine::sdk::factory::factory(void * data) +{ + // Check version first + if (eemagine_sdk_get_version() != EEGO_SDK_VERSION) + { + throw(exceptions::incorrectValue("Eego SDK version mismatch")); + } + + if (!_sdk.initialized) { + _sdk.setup = eemagine_sdk_setup; + _sdk.init = eemagine_sdk_init; + _sdk.exit = eemagine_sdk_exit; + _sdk.get_version = eemagine_sdk_get_version; + _sdk.get_amplifiers_info = eemagine_sdk_get_amplifiers_info; + _sdk.close_amplifier = eemagine_sdk_close_amplifier; + _sdk.get_amplifier_channel_list = eemagine_sdk_get_amplifier_channel_list; + _sdk.get_amplifier_serial = eemagine_sdk_get_amplifier_serial; + _sdk.get_amplifier_version = eemagine_sdk_get_amplifier_version; + _sdk.get_amplifier_type = eemagine_sdk_get_amplifier_type; + _sdk.get_amplifier_sampling_rates_available = eemagine_sdk_get_amplifier_sampling_rates_available; + _sdk.get_amplifier_reference_ranges_available = eemagine_sdk_get_amplifier_reference_ranges_available; + _sdk.get_amplifier_bipolar_ranges_available = eemagine_sdk_get_amplifier_bipolar_ranges_available; + _sdk.open_eeg_stream = eemagine_sdk_open_eeg_stream; + _sdk.open_impedance_stream = eemagine_sdk_open_impedance_stream; + _sdk.close_stream = eemagine_sdk_close_stream; + _sdk.get_stream_channel_list = eemagine_sdk_get_stream_channel_list; + _sdk.get_stream_channel_count = eemagine_sdk_get_stream_channel_count; + _sdk.prefetch = eemagine_sdk_prefetch; + _sdk.get_data = eemagine_sdk_get_data; + _sdk.get_error_string = eemagine_sdk_get_error_string; + _sdk.setup(data); + _sdk.initialized = true; + } +} +#else +// More complicated case. The path to the dll is provided by call to the factory. +// That DLL has to be loaded and the function pointers have to be searched in there. +// When found they are assigned to the right place in the _sdk structure. +// If they are not found raise a runtime exception + +/////////////////////////////////////////////////////////////////////////////////////////////////////// +/// All the diffenrent string encodings have to be normalized to utf-8 string for internal handling. +/// To connect to windows methods wide character strings have to be used. +/// String handling methods follow. +/////////////////////////////////////////////////////////////////////////////////////////////////////// +#ifdef _WIN32 +static std::string UTF16toUTF8(const std::wstring& utf16String) +{ + // empty + if (utf16String.empty()) + return std::string(); + + // get length of conversion first or see if there is an error + const int utf8length = ::WideCharToMultiByte( + CP_UTF8, WC_ERR_INVALID_CHARS, utf16String.data(), (int)utf16String.length(), // Input + NULL, 0, // just check + NULL, NULL); // invalid for utf8 + + if (utf8length == 0) // Must be error, as empty string should not happen here anymore + { + const DWORD error = ::GetLastError(); + if (error == ERROR_NO_UNICODE_TRANSLATION) + throw eemagine::sdk::exceptions::incorrectValue("Failure of string conversion from utf16, invalid characters."); + + throw eemagine::sdk::exceptions::incorrectValue("Failure to classify utf16 string. errorcode: " + error); + } + + std::string retvalUTF8; + retvalUTF8.resize(utf8length); + + const int convertedLength = ::WideCharToMultiByte( + CP_UTF8, 0, utf16String.data(), (int)utf16String.length(), // Input + &retvalUTF8[0], (int)retvalUTF8.length(), + NULL, NULL); // invalid for utf8 + + if (convertedLength == 0) + { + throw eemagine::sdk::exceptions::incorrectValue("Failure to convert utf16 string."); + } + + return retvalUTF8; +} + +static std::wstring MBCStoUTF16(const std::string& mbcsString) +{ + // empty + if (mbcsString.empty()) + return std::wstring(); + + // get length of conversion first or see if there is an error + const int wideLength = ::MultiByteToWideChar( + CP_ACP, MB_ERR_INVALID_CHARS, mbcsString.data(), (int)mbcsString.length(), // Input + NULL, 0); // just check + if (wideLength == 0) // Must be error, as empty string should not happen here anymore + { + const DWORD error = ::GetLastError(); + if (error == ERROR_NO_UNICODE_TRANSLATION) + throw eemagine::sdk::exceptions::incorrectValue("Failure of string conversion from mbcsString, invalid characters: " + mbcsString); + + std::stringstream errormsg; + errormsg << "Failure to convert mbcsString: " << mbcsString << " Error code: " << error; + throw eemagine::sdk::exceptions::incorrectValue(errormsg.str()); + } + + // conversion exists! Let's do it + std::wstring returnStringUTF16; + returnStringUTF16.resize(wideLength); + + const int convertResult = ::MultiByteToWideChar( + CP_ACP, 0, mbcsString.data(), (int)mbcsString.length(), // Input + &returnStringUTF16[0], (int)returnStringUTF16.length()); // fill it + + if (convertResult == 0) // We already verified the string. Not recoverable + { + const DWORD error = ::GetLastError(); + std::stringstream errormsg; + errormsg << "Conversion failed from mbcsString: " << mbcsString << " Error code: " << error; + throw eemagine::sdk::exceptions::incorrectValue(errormsg.str()); + } + + return returnStringUTF16; +} + +static std::wstring UTF8ToUTF16(const std::string& utf8String) +{ + // empty + if (utf8String.empty()) + return std::wstring(); + + // get length of conversion first or see if there is an error + const int wideLength = ::MultiByteToWideChar( + CP_UTF8, MB_ERR_INVALID_CHARS, utf8String.data(), (int)utf8String.length(), // Input + NULL, 0); // just check + if (wideLength == 0) // Must be error, as empty string should not happen here anymore + { + const DWORD error = ::GetLastError(); + if (error == ERROR_NO_UNICODE_TRANSLATION) + throw eemagine::sdk::exceptions::incorrectValue("Failure of string conversion from utf8, invalid characters: " + utf8String); + + std::stringstream errormsg; + errormsg << "Failure to convert utf8 string: " << utf8String << " Error code: " << error; + throw eemagine::sdk::exceptions::incorrectValue(errormsg.str()); + } + + // conversion exists! Let's do it + std::wstring returnStringUTF16; + returnStringUTF16.resize(wideLength); + + const int convertResult = ::MultiByteToWideChar( + CP_UTF8, 0, utf8String.data(), (int)utf8String.length(), // Input + &returnStringUTF16[0], (int)returnStringUTF16.length()); // fill it + + if (convertResult == 0) // + { + const DWORD error = ::GetLastError(); + std::stringstream errormsg; + errormsg << "Conversion failed from utf8: " << utf8String << " Error code: " << error; + throw eemagine::sdk::exceptions::incorrectValue(errormsg.str()); + } + + return returnStringUTF16; +} + +static std::string MBCStoUTF8(const std::string& mbcsString) +{ + return UTF16toUTF8(MBCStoUTF16(mbcsString)); +} +#endif + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/// String conversion ends here. +/// +/// In the following functions we will load the exported functions from the DLL loaded from the path provided by the user. +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +// Helper class for library loading: +// Find funcName in dll specified by libHandle +// If the function can not be found or another error has occured raise runtime_error. +#ifdef _WIN32 +typedef HINSTANCE library_handle_type; +template +static T getFunc(library_handle_type libHandle, const char* funcName) +{ + // load + T func = (T)::GetProcAddress(libHandle, funcName); + + // check + if (func == NULL) + { + throw(eemagine::sdk::exceptions::incorrectValue(std::string("Can't load function: ") + funcName)); + } + + return func; +} +library_handle_type +LoadSDKLibrary(const std::string &libPathUtf8) { + const std::wstring libPathUTF16(UTF8ToUTF16(libPathUtf8)); + + library_handle_type oLibHandle = ::LoadLibrary(libPathUTF16.c_str()); + if (oLibHandle == NULL) + { + throw(eemagine::sdk::exceptions::incorrectValue("Could not load Library: " + libPathUtf8)); + } + return oLibHandle; +} +#endif +#ifdef __unix__ +typedef void * library_handle_type; +template +static T getFunc(library_handle_type libHandle, const char* funcName) +{ + void * symbol(dlsym(libHandle, funcName)); + if (symbol == NULL) + { + throw(eemagine::sdk::exceptions::incorrectValue(std::string("Can't load function: ") + funcName)); + } + + return (T)(symbol); +} +library_handle_type +LoadSDKLibrary(const std::string &filename) { + library_handle_type rv(dlopen(filename.c_str(), RTLD_LAZY)); + if (rv == NULL) + { + throw(eemagine::sdk::exceptions::incorrectValue("Could not load Library: " + filename + " error: " + dlerror())); + } + return rv; +} +#endif + +static void loadLibraryUTF8(const std::string& libPathUTF8, void * data) +{ + // Only load functions once + if (_sdk.initialized == false) + { + // Load DLL and check + library_handle_type oLibHandle = LoadSDKLibrary(libPathUTF8); + + // Let us load the get version pointer first to have more meaningful error messages + // if some functions do not exist. + _sdk.get_version = getFunc(oLibHandle, "eemagine_sdk_get_version"); + if (_sdk.get_version() != EEGO_SDK_VERSION) + { + throw(eemagine::sdk::exceptions::incorrectValue("Eego SDK version mismatch")); + } + + + // Load function pointers from DLL; + _sdk.setup = getFunc(oLibHandle, "eemagine_sdk_setup"); + _sdk.init = getFunc(oLibHandle, "eemagine_sdk_init"); + _sdk.exit = getFunc(oLibHandle, "eemagine_sdk_exit"); + _sdk.get_amplifiers_info = getFunc(oLibHandle, "eemagine_sdk_get_amplifiers_info"); + _sdk.close_amplifier = getFunc(oLibHandle, "eemagine_sdk_close_amplifier"); + _sdk.get_amplifier_channel_list = getFunc(oLibHandle, "eemagine_sdk_get_amplifier_channel_list"); + _sdk.get_amplifier_serial = getFunc(oLibHandle, "eemagine_sdk_get_amplifier_serial"); + _sdk.get_amplifier_version = getFunc(oLibHandle, "eemagine_sdk_get_amplifier_version"); + _sdk.get_amplifier_type = getFunc(oLibHandle, "eemagine_sdk_get_amplifier_type"); + _sdk.get_amplifier_sampling_rates_available = getFunc(oLibHandle, "eemagine_sdk_get_amplifier_sampling_rates_available"); + _sdk.get_amplifier_reference_ranges_available = getFunc(oLibHandle, "eemagine_sdk_get_amplifier_reference_ranges_available"); + _sdk.get_amplifier_bipolar_ranges_available = getFunc(oLibHandle, "eemagine_sdk_get_amplifier_bipolar_ranges_available"); + _sdk.open_eeg_stream = getFunc(oLibHandle, "eemagine_sdk_open_eeg_stream"); + _sdk.open_impedance_stream = getFunc(oLibHandle, "eemagine_sdk_open_impedance_stream"); + _sdk.close_stream = getFunc(oLibHandle, "eemagine_sdk_close_stream"); + _sdk.get_stream_channel_list = getFunc(oLibHandle, "eemagine_sdk_get_stream_channel_list"); + _sdk.get_stream_channel_count = getFunc(oLibHandle, "eemagine_sdk_get_stream_channel_count"); + _sdk.prefetch = getFunc(oLibHandle, "eemagine_sdk_prefetch"); + _sdk.get_data = getFunc(oLibHandle, "eemagine_sdk_get_data"); + _sdk.get_error_string = getFunc(oLibHandle, "eemagine_sdk_get_error_string"); + _sdk.setup(data); + _sdk.initialized = true; + } + + // all ok! +} + +#ifdef _WIN32 +eemagine::sdk::factory::factory(const std::wstring& libPath, void * data) +{ + loadLibraryUTF8(UTF16toUTF8(libPath), data); +} +#endif + +eemagine::sdk::factory::factory(const std::string& libPath, void * data) +{ +#if defined(_MBCS) + loadLibraryUTF8(MBCStoUTF8(libPath), data); +#elif defined(_UNICODE) + loadLibraryUTF8(libPath, data); +#else +#error "Undefined string handling" +#endif +} +#endif + +/////////////////////////////////////////////////////////////////////////////// +eemagine::sdk::factory::~factory() { + try { + _get_sdk_guard_singleton()->sweepAmplifierReferenceCounts(); + _get_sdk_guard_singleton(true); + } + catch (const std::exception &e) { + std::cerr << "exception in ~factory: " << e.what() << std::endl; + } catch (...) { + std::cerr << "exception in ~factory" << std::endl; + } +} + +/////////////////////////////////////////////////////////////////////////////// +std::vector +eemagine::sdk::factory::getAmplifiers() { + _sdk_guard * sg = _get_sdk_guard_singleton(); + + // get list from c layer first + eemagine_sdk_amplifier_info amplifier_info_array[64]; + int amplifier_count = _sdk.get_amplifiers_info(amplifier_info_array, 64); + + // mark + for (int amp_id = 0; amp_id < amplifier_count; ++amp_id) { + sg->incrementAmplifierReferenceCount(amplifier_info_array[amp_id]); + } + + // sweep + sg->sweepAmplifierReferenceCounts(); + + return sg->getAmplifiers(); +} + +/////////////////////////////////////////////////////////////////////////////// +eemagine::sdk::amplifier * +eemagine::sdk::factory::getAmplifier() { + eemagine::sdk::amplifier * rv = NULL; + std::vector amplifier_list = getAmplifiers(); + + if (amplifier_list.empty()) { + throw(eemagine::sdk::exceptions::notFound("amplifier list is empty")); + } + + std::vector::iterator iter = amplifier_list.begin(); + rv = *iter; + // clean references + while (++iter != amplifier_list.end()) { + delete *iter; + } + + return rv; +} + +/////////////////////////////////////////////////////////////////////////////// +eemagine::sdk::factory::version +eemagine::sdk::factory::getVersion() const { + eemagine::sdk::factory::version rv; + rv.major = EEGO_SDK_VERSION_MAJOR; + rv.minor = EEGO_SDK_VERSION_MINOR; + rv.micro = EEGO_SDK_VERSION_MICRO; + rv.build = EEGO_SDK_VERSION; + return rv; +} diff --git a/eemagine/sdk/wrapper.h b/eemagine/sdk/wrapper.h index d964b4e..e57babb 100644 --- a/eemagine/sdk/wrapper.h +++ b/eemagine/sdk/wrapper.h @@ -1,185 +1,193 @@ -/* - * License: eego amplifier Interface SDK, rev. 1.3 - * - * - * Copyright 2015, eemagine Medical Imaging Solutions GmbH - * - * - * 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 above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - * - * 3. All advertising materials mentioning features or use of this software must display the following acknowledgement: This product includes software developed by the eemagine Medical Imaging Solutions GmbH. - * - * 4. Neither the name of the eemagine Medical Imaging Solutions GmbH nor the names of its contributors or products may be used to endorse or promote products derived from this software without specific prior written permission by eemagine - * - * - * This Software is provided by eemagine Medical Imaging Solutions GmbH ''As Is'' and any express or implied warranties, including, but not limited to, the implied warranties merchantability and fitness for a particular purpose are disclaimed. In no event shall eemagine 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. - * - * The eego amplifier comes with its own user manual, which must be read carefully before making use of this SDK or any derived software. - * - * - * You need to run full testing and qualification based on your own requirements to claim any performance of the combined system. - * - * - * Please be especially advised that any certification holding for the eego amplifier is not valid for a combined system of your application software and the eego amplifier. You must obtain your own certification for a combined system of amplifier and software. - */ - -#ifndef __eemagine_sdk_h__ -#define __eemagine_sdk_h__ - -#ifdef EEGO_SDK_EXPORT -# ifdef WIN32 -# define EEGO_SDK_API __declspec(dllexport) -# endif -# ifdef __unix__ -# define EEGO_SDK_API __attribute__ ((visibility ("default"))) -# endif -#else // We are importing -# define EEGO_SDK_API -#endif // #ifdef EEGO_SDK_EXPORT - -#ifdef __cplusplus -extern "C" { -#endif - /** - * error codes - */ - enum eemagine_sdk_error { - EEMAGINE_SDK_NOT_CONNECTED = -1, - EEMAGINE_SDK_ALREADY_EXISTS = -2, - EEMAGINE_SDK_NOT_FOUND = -3, - EEMAGINE_SDK_INCORRECT_VALUE = -4, - EEMAGINE_SDK_UNKNOWN = -5 - }; - /** - * @brief structure to support amplifier info - */ - typedef struct { - int id; - char serial[64]; - } eemagine_sdk_amplifier_info; - /** - * @brief channel type enum - */ - typedef enum { - EEMAGINE_SDK_CHANNEL_TYPE_REFERENCE, - EEMAGINE_SDK_CHANNEL_TYPE_BIPOLAR, - EEMAGINE_SDK_CHANNEL_TYPE_TRIGGER, - EEMAGINE_SDK_CHANNEL_TYPE_SAMPLE_COUNTER, - EEMAGINE_SDK_CHANNEL_TYPE_IMPEDANCE_REFERENCE, - EEMAGINE_SDK_CHANNEL_TYPE_IMPEDANCE_GROUND, - } eemagine_sdk_channel_type; - /** - * @brief structure to hold channel information - */ - typedef struct { - int index; - eemagine_sdk_channel_type type; - } eemagine_sdk_channel_info; - /** - * @brief initialze sdk library - */ - typedef void(*eemagine_sdk_init_t)(void); - EEGO_SDK_API void eemagine_sdk_init(); - /** - * finalize sdk library - */ - typedef void(*eemagine_sdk_exit_t)(void); - EEGO_SDK_API void eemagine_sdk_exit(); - /** - * get the current sdk version - */ - typedef int(*eemagine_sdk_get_version_t)(void); - EEGO_SDK_API int eemagine_sdk_get_version(); - /** - * @brief get an array of connected amplifiers - */ - typedef int(*eemagine_sdk_get_amplifiers_info_t)(eemagine_sdk_amplifier_info * amplifier_info_array, int amplifier_info_array_size); - EEGO_SDK_API int eemagine_sdk_get_amplifiers_info(eemagine_sdk_amplifier_info * amplifier_info_array, int amplifier_info_array_size); - /** - * close amplifier - */ - typedef int(*eemagine_sdk_close_amplifier_t)(int amplifier_id); - EEGO_SDK_API int eemagine_sdk_close_amplifier(int amplifier_id); - /** - * @brief get the serial number from the amplifier - */ - typedef int(*eemagine_sdk_get_amplifier_serial_t)(int amplifier_id, char * serial, int serial_size); - EEGO_SDK_API int eemagine_sdk_get_amplifier_serial(int amplifier_id, char * serial, int serial_size); - /** - * @brief get the firmware version for this amplifier - */ - typedef int(*eemagine_sdk_get_amplifier_version_t)(int amplifier_id); - EEGO_SDK_API int eemagine_sdk_get_amplifier_version(int amplifier_id); - /** - * @brief get the type of the amplifier - */ - typedef int(*eemagine_sdk_get_amplifier_type_t)(int amplifier_id, char * type, int type_size); - EEGO_SDK_API int eemagine_sdk_get_amplifier_type(int amplifier_id, char * type, int type_size); - /** - * @brief get the channel list from an amplifier - */ - typedef int(*eemagine_sdk_get_amplifier_channel_list_t)(int amplifier_id, eemagine_sdk_channel_info * channel_info_array, int channel_info_array_size); - EEGO_SDK_API int eemagine_sdk_get_amplifier_channel_list(int amplifier_id, eemagine_sdk_channel_info * channel_info_array, int channel_info_array_size); - /** - * @brief get a list of sampling rates that are available - */ - typedef int(*eemagine_sdk_get_amplifier_sampling_rates_available_t)(int amplifier_id, int * sampling_rate_array, int sampling_rate_array_size); - EEGO_SDK_API int eemagine_sdk_get_amplifier_sampling_rates_available(int amplifier_id, int * sampling_rate_array, int sampling_rate_array_size); - /** - * @brief get a list of reference ranges that are available - */ - typedef int(*eemagine_sdk_get_amplifier_reference_ranges_available_t)(int amplifier_id, double * reference_range_array, int reference_range_array_size); - EEGO_SDK_API int eemagine_sdk_get_amplifier_reference_ranges_available(int amplifier_id, double * reference_range_array, int reference_range_array_size); - /** - * @brief get a list of bipolar ranges that are available - */ - typedef int(*eemagine_sdk_get_amplifier_bipolar_ranges_available_t)(int amplifier_id, double * bipolar_range_array, int bipolar_range_array_size); - EEGO_SDK_API int eemagine_sdk_get_amplifier_bipolar_ranges_available(int amplifier_id, double * bipolar_range_array, int bipolar_range_array_size); - /** - * open eeg stream, returns handle on success. if handle is negative, it indicates an error - */ - typedef int(*eemagine_sdk_open_eeg_stream_t)(int amplifier_id, int sampling_rate, double reference_range, double bipolar_range, unsigned long long ref_mask, unsigned long long bip_mask); - EEGO_SDK_API int eemagine_sdk_open_eeg_stream(int amplifier_id, int sampling_rate, double reference_range, double bipolar_range, unsigned long long ref_mask, unsigned long long bip_mask); - /** - * open impedance stream, returns handle on success. if handle is negative, it indicates an error - */ - typedef int(*eemagine_sdk_open_impedance_stream_t)(int amplifier_id, unsigned long long ref_mask); - EEGO_SDK_API int eemagine_sdk_open_impedance_stream(int amplifier_id, unsigned long long ref_mask); - /** - * close stream - */ - typedef int(*eemagine_sdk_close_stream_t)(int stream_id); - EEGO_SDK_API int eemagine_sdk_close_stream(int stream_id); - /** - * @brief get the channel list from a stream - */ - typedef int(*eemagine_sdk_get_stream_channel_list_t)(int stream_id, eemagine_sdk_channel_info * channel_info_array, int channel_info_array_size); - EEGO_SDK_API int eemagine_sdk_get_stream_channel_list(int stream_id, eemagine_sdk_channel_info * channel_info_array, int channel_info_array_size); - /** - * @brief get the channel count from a stream - */ - typedef int(*eemagine_sdk_get_stream_channel_count_t)(int stream_id); - EEGO_SDK_API int eemagine_sdk_get_stream_channel_count(int stream_id); - /** - * @brief prefetch will return the number of bytes the next call to get_data will need; - */ - typedef int(*eemagine_sdk_prefetch_t)(int stream_id); - EEGO_SDK_API int eemagine_sdk_prefetch(int stream_id); - /** - * get data - */ - typedef int(*eemagine_sdk_get_data_t)(int stream_id, double *buffer, int buffer_size_in_bytes); - EEGO_SDK_API int eemagine_sdk_get_data(int stream_id, double *buffer, int buffer_size_in_bytes); - /** - * get error string - */ - typedef int(*eemagine_sdk_get_error_string_t)(char *error_string, int error_string_size); - EEGO_SDK_API int eemagine_sdk_get_error_string(char *error_string, int error_string_size); - -#ifdef __cplusplus -} -#endif - -#endif +/* + * License: eego amplifier Interface SDK, rev. 1.3 + * + * + * Copyright 2015, eemagine Medical Imaging Solutions GmbH + * + * + * 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 above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + * + * 3. All advertising materials mentioning features or use of this software must display the following acknowledgement: This product includes software developed by the eemagine Medical Imaging Solutions GmbH. + * + * 4. Neither the name of the eemagine Medical Imaging Solutions GmbH nor the names of its contributors or products may be used to endorse or promote products derived from this software without specific prior written permission by eemagine + * + * + * This Software is provided by eemagine Medical Imaging Solutions GmbH ''As Is'' and any express or implied warranties, including, but not limited to, the implied warranties merchantability and fitness for a particular purpose are disclaimed. In no event shall eemagine 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. + * + * The eego amplifier comes with its own user manual, which must be read carefully before making use of this SDK or any derived software. + * + * + * You need to run full testing and qualification based on your own requirements to claim any performance of the combined system. + * + * + * Please be especially advised that any certification holding for the eego amplifier is not valid for a combined system of your application software and the eego amplifier. You must obtain your own certification for a combined system of amplifier and software. + */ + +#ifndef __eemagine_sdk_h__ +#define __eemagine_sdk_h__ + +#ifdef EEGO_SDK_EXPORT +# ifdef _WIN32 +# define EEGO_SDK_API __declspec(dllexport) +# endif +# ifdef __unix__ +# define EEGO_SDK_API __attribute__ ((visibility ("default"))) +# endif +#else // We are importing +# define EEGO_SDK_API +#endif // #ifdef EEGO_SDK_EXPORT + +#ifdef __cplusplus +extern "C" { +#endif + /** + * error codes + */ + enum eemagine_sdk_error { + EEMAGINE_SDK_NOT_CONNECTED = -1, + EEMAGINE_SDK_ALREADY_EXISTS = -2, + EEMAGINE_SDK_NOT_FOUND = -3, + EEMAGINE_SDK_INCORRECT_VALUE = -4, + EEMAGINE_SDK_UNKNOWN = -5 + }; + /** + * @brief structure to support amplifier info + */ + typedef struct { + int id; + char serial[64]; + } eemagine_sdk_amplifier_info; + /** + * @brief channel type enum + */ + typedef enum { + EEMAGINE_SDK_CHANNEL_TYPE_REFERENCE, + EEMAGINE_SDK_CHANNEL_TYPE_BIPOLAR, + EEMAGINE_SDK_CHANNEL_TYPE_ACCELEROMETER, + EEMAGINE_SDK_CHANNEL_TYPE_GYROSCOPE, + EEMAGINE_SDK_CHANNEL_TYPE_MAGNETOMETER, + EEMAGINE_SDK_CHANNEL_TYPE_TRIGGER, + EEMAGINE_SDK_CHANNEL_TYPE_SAMPLE_COUNTER, + EEMAGINE_SDK_CHANNEL_TYPE_IMPEDANCE_REFERENCE, + EEMAGINE_SDK_CHANNEL_TYPE_IMPEDANCE_GROUND, + } eemagine_sdk_channel_type; + /** + * @brief structure to hold channel information + */ + typedef struct { + int index; + eemagine_sdk_channel_type type; + } eemagine_sdk_channel_info; + /** + * @brief setup sdk library + */ + typedef void(*eemagine_sdk_setup_t)(void *); + EEGO_SDK_API void eemagine_sdk_setup(void *); + /** + * @brief initialze sdk library + */ + typedef void(*eemagine_sdk_init_t)(void); + EEGO_SDK_API void eemagine_sdk_init(); + /** + * finalize sdk library + */ + typedef void(*eemagine_sdk_exit_t)(void); + EEGO_SDK_API void eemagine_sdk_exit(); + /** + * get the current sdk version + */ + typedef int(*eemagine_sdk_get_version_t)(void); + EEGO_SDK_API int eemagine_sdk_get_version(); + /** + * @brief get an array of connected amplifiers + */ + typedef int(*eemagine_sdk_get_amplifiers_info_t)(eemagine_sdk_amplifier_info * amplifier_info_array, int amplifier_info_array_size); + EEGO_SDK_API int eemagine_sdk_get_amplifiers_info(eemagine_sdk_amplifier_info * amplifier_info_array, int amplifier_info_array_size); + /** + * close amplifier + */ + typedef int(*eemagine_sdk_close_amplifier_t)(int amplifier_id); + EEGO_SDK_API int eemagine_sdk_close_amplifier(int amplifier_id); + /** + * @brief get the serial number from the amplifier + */ + typedef int(*eemagine_sdk_get_amplifier_serial_t)(int amplifier_id, char * serial, int serial_size); + EEGO_SDK_API int eemagine_sdk_get_amplifier_serial(int amplifier_id, char * serial, int serial_size); + /** + * @brief get the firmware version for this amplifier + */ + typedef int(*eemagine_sdk_get_amplifier_version_t)(int amplifier_id); + EEGO_SDK_API int eemagine_sdk_get_amplifier_version(int amplifier_id); + /** + * @brief get the type of the amplifier + */ + typedef int(*eemagine_sdk_get_amplifier_type_t)(int amplifier_id, char * type, int type_size); + EEGO_SDK_API int eemagine_sdk_get_amplifier_type(int amplifier_id, char * type, int type_size); + /** + * @brief get the channel list from an amplifier + */ + typedef int(*eemagine_sdk_get_amplifier_channel_list_t)(int amplifier_id, eemagine_sdk_channel_info * channel_info_array, int channel_info_array_size); + EEGO_SDK_API int eemagine_sdk_get_amplifier_channel_list(int amplifier_id, eemagine_sdk_channel_info * channel_info_array, int channel_info_array_size); + /** + * @brief get a list of sampling rates that are available + */ + typedef int(*eemagine_sdk_get_amplifier_sampling_rates_available_t)(int amplifier_id, int * sampling_rate_array, int sampling_rate_array_size); + EEGO_SDK_API int eemagine_sdk_get_amplifier_sampling_rates_available(int amplifier_id, int * sampling_rate_array, int sampling_rate_array_size); + /** + * @brief get a list of reference ranges that are available + */ + typedef int(*eemagine_sdk_get_amplifier_reference_ranges_available_t)(int amplifier_id, double * reference_range_array, int reference_range_array_size); + EEGO_SDK_API int eemagine_sdk_get_amplifier_reference_ranges_available(int amplifier_id, double * reference_range_array, int reference_range_array_size); + /** + * @brief get a list of bipolar ranges that are available + */ + typedef int(*eemagine_sdk_get_amplifier_bipolar_ranges_available_t)(int amplifier_id, double * bipolar_range_array, int bipolar_range_array_size); + EEGO_SDK_API int eemagine_sdk_get_amplifier_bipolar_ranges_available(int amplifier_id, double * bipolar_range_array, int bipolar_range_array_size); + /** + * open eeg stream, returns handle on success. if handle is negative, it indicates an error + */ + typedef int(*eemagine_sdk_open_eeg_stream_t)(int amplifier_id, int sampling_rate, double reference_range, double bipolar_range, unsigned long long ref_mask, unsigned long long bip_mask); + EEGO_SDK_API int eemagine_sdk_open_eeg_stream(int amplifier_id, int sampling_rate, double reference_range, double bipolar_range, unsigned long long ref_mask, unsigned long long bip_mask); + /** + * open impedance stream, returns handle on success. if handle is negative, it indicates an error + */ + typedef int(*eemagine_sdk_open_impedance_stream_t)(int amplifier_id, unsigned long long ref_mask); + EEGO_SDK_API int eemagine_sdk_open_impedance_stream(int amplifier_id, unsigned long long ref_mask); + /** + * close stream + */ + typedef int(*eemagine_sdk_close_stream_t)(int stream_id); + EEGO_SDK_API int eemagine_sdk_close_stream(int stream_id); + /** + * @brief get the channel list from a stream + */ + typedef int(*eemagine_sdk_get_stream_channel_list_t)(int stream_id, eemagine_sdk_channel_info * channel_info_array, int channel_info_array_size); + EEGO_SDK_API int eemagine_sdk_get_stream_channel_list(int stream_id, eemagine_sdk_channel_info * channel_info_array, int channel_info_array_size); + /** + * @brief get the channel count from a stream + */ + typedef int(*eemagine_sdk_get_stream_channel_count_t)(int stream_id); + EEGO_SDK_API int eemagine_sdk_get_stream_channel_count(int stream_id); + /** + * @brief prefetch will return the number of bytes the next call to get_data will need; + */ + typedef int(*eemagine_sdk_prefetch_t)(int stream_id); + EEGO_SDK_API int eemagine_sdk_prefetch(int stream_id); + /** + * get data + */ + typedef int(*eemagine_sdk_get_data_t)(int stream_id, double *buffer, int buffer_size_in_bytes); + EEGO_SDK_API int eemagine_sdk_get_data(int stream_id, double *buffer, int buffer_size_in_bytes); + /** + * get error string + */ + typedef int(*eemagine_sdk_get_error_string_t)(char *error_string, int error_string_size); + EEGO_SDK_API int eemagine_sdk_get_error_string(char *error_string, int error_string_size); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/main.cpp b/main.cpp index 922533f..586f499 100644 --- a/main.cpp +++ b/main.cpp @@ -1,5 +1,5 @@ #include "mainwindow.h" -#include +#include int main(int argc, char *argv[]) { diff --git a/mainwindow.cpp b/mainwindow.cpp index 705eeca..6899806 100644 --- a/mainwindow.cpp +++ b/mainwindow.cpp @@ -3,17 +3,20 @@ #include #include #include -#include -#include -#include #include #include "wrapper.cc" +#include +#include using namespace eemagine::sdk; +#include +#include +#include MainWindow::MainWindow(QWidget *parent, const std::string &config_file, const bool linkOnStart) : QMainWindow(parent) { - reader = NULL; + qRegisterMetaType>("QVector"); + reader = nullptr; ui.setupUi(this); // make GUI connections @@ -39,7 +42,7 @@ void MainWindow::save_config_dialog() { } void MainWindow::closeEvent(QCloseEvent *ev) { - if (reader != NULL) { + if (reader != nullptr) { ev->ignore(); } } @@ -60,6 +63,7 @@ void MainWindow::load_config(const std::string &filename) { // get config values try { ui.samplingRate->setCurrentIndex(pt.get("settings.samplingrate", 3)); + } catch (std::exception &) { QMessageBox::information(this, "Error in Config File", "Could not read out config parameters.", QMessageBox::Ok); @@ -90,9 +94,15 @@ void MainWindow::save_config(const std::string &filename) { void MainWindow::link() { - if (reader != NULL) { + static int status = 0; + if (reader != nullptr) { reader->setStop(true); - ui.linkButton->setText("Link"); + if(status==1){ + ui.linkButton->setText("Stop Sending Data"); + status=0; + }else{ + ui.linkButton->setText("Link"); + } } else { // === perform link action === @@ -115,6 +125,7 @@ void MainWindow::link() { connect(reader, SIGNAL(timeout()), this, SLOT(threadTimeout())); connect(reader, SIGNAL(connectionLost()), this, SLOT(connectionLost())); connect(reader, SIGNAL(ampNotFound()), this, SLOT(ampNotFound())); + connect(reader, &Reader::displayImp, this, &MainWindow::displayImp); thread->start(); } catch (std::exception &e) { @@ -125,14 +136,30 @@ void MainWindow::link() { } // done, all successful - ui.linkButton->setText("Unlink"); + ui.linkButton->setText("Stop Preparing"); + status = 1; } } - +void MainWindow::displayImp(QVector impData){ + if(impData.size()!=imps.size()){ + for(int i=0;ideleteLater(); + } + imps.clear(); + imps.resize(impData.size()); + for(int i=0;isetNum(impData[i]); + } + return; +} void MainWindow::threadFinished() { - reader = NULL; + reader = nullptr; delete thread; - thread = NULL; + thread = nullptr; ui.linkButton->setText("Link"); } @@ -148,6 +175,7 @@ void MainWindow::connectionLost() { QMessageBox::critical(this, "Error", (std::string("Error: Amp connection lost")).c_str(), QMessageBox::Ok); } + // --- CONSTRUCTOR --- Reader::Reader() { stop = false; @@ -163,16 +191,46 @@ void Reader::setParams(int samplingRate) { this->samplingRate = samplingRate; } +void Reader::setParams(QString chs) { + auto ss = std::stringstream(chs.toStdString()); + channels.clear(); + int num; + while(ss>>num){ + channels.push_back(num); + } +} + // --- PROCESS --- + // Start processing data. void Reader::read() { - bool ampFound = true; try { - factory fact; - amp = fact.getAmplifier(); - eegStream = amp->OpenEegStream(samplingRate); - + qDebug()<<"start to construct"; + fact.reset(new factory()); + qDebug()<<"constructed"; + amp.reset(fact->getAmplifier()); + + // get imp data + qDebug()<<"Getting impStream"; + std::shared_ptr impStream(amp->OpenImpedanceStream()); + qDebug()<<"Get impStream"; + // get impedance data + while(!stop){ + auto buf = impStream->getData(); + //qDebug()<OpenEegStream(samplingRate)); std::vector channelList = eegStream->getChannelList(); + for(auto ch:channelList){ + qDebug()<getSerialNumber(), "EEG", channelList.size() - 2, samplingRate, lsl::cf_float32, "eegoSports_" + amp->getSerialNumber()); @@ -180,13 +238,15 @@ void Reader::read() { for (int k = 0; k < channelList.size() - 2; k++) { channels.append_child("channel") - .append_child_value("label", "Ch" + k) + .append_child_value("label", "Ch" + std::to_string(k)) .append_child_value("type", "EEG") .append_child_value("unit", "microvolts"); + //qDebug()<<("ch"+std::to_string(k)).c_str(); } data_info.desc().append_child("acquisition") .append_child_value("manufacturer", "antneuro") - .append_child_value("serial_number", boost::lexical_cast(amp->getSerialNumber()).c_str()); + //.append_child_value("serial_number", boost::lexical_cast(amp->getSerialNumber()).c_str()); + .append_child_value("serial_number", amp->getSerialNumber()); // make a data outlet lsl::stream_outlet data_outlet(data_info); @@ -195,13 +255,11 @@ void Reader::read() { lsl::stream_info marker_info("eegoSports-" + amp->getSerialNumber() + "_markers" + "Markers", "Markers", 1, 0, lsl::cf_string, "eegoSports_" + boost::lexical_cast(amp->getSerialNumber()) + "_markers"); lsl::stream_outlet marker_outlet(marker_info); - std::vector eegChannelList = eegStream->getChannelList(); - - int timeout_count = 0; while (!stop) { buffer buffer = eegStream->getData(); - int channelCount = buffer.getChannelCount(); - int sampleCount = buffer.size() / channelCount; + auto channelCount = buffer.getChannelCount(); + auto sampleCount = buffer.size() / channelCount; + std::vector> send_buffer(sampleCount, std::vector(channelCount - 2)); for (int s = 0; s < sampleCount; s++) { for (int c = 0; c < channelCount - 2; c++) { @@ -211,6 +269,10 @@ void Reader::read() { double now = lsl::local_clock(); data_outlet.push_chunk(send_buffer, now); + if(sampleCount>0){ + qDebug()< +#include #include "ui_mainwindow.h" #include #include #include #include +#include #include #include +#include // LSL API -#include "../../LSL/liblsl/include/lsl_cpp.h" +#include // eegoSports -#define WIN32_LEAN_AND_MEAN +//#define WIN32_LEAN_AND_MEAN #define EEGO_SDK_BIND_STATIC -#include +//#include #include "eemagine/sdk/factory.h" class Reader : public QObject { @@ -32,17 +34,21 @@ class Reader : public QObject { this->stop = stop; } void setParams(int samplingRate); + void setParams(QString chs); signals: void finished(); void timeout(); void ampNotFound(); void connectionLost(); + void displayImp(QVector); private: - eemagine::sdk::amplifier* amp; - eemagine::sdk::stream* eegStream; + std::shared_ptr fact; + std::shared_ptr amp; + std::shared_ptr eegStream; int samplingRate; + std::vector channels; bool stop; }; @@ -59,6 +65,7 @@ class MainWindow : public QMainWindow void threadTimeout(); void connectionLost(); void ampNotFound(); + void displayImp(QVector); void load_config_dialog(); void save_config_dialog(); @@ -76,11 +83,9 @@ class MainWindow : public QMainWindow void load_config(const std::string &filename); void save_config(const std::string &filename); - eemagine::sdk::amplifier* amp; - eemagine::sdk::stream* eegStream; Reader *reader; QThread *thread; - + QVector imps; Ui::MainWindowClass ui; }; diff --git a/mainwindow.ui b/mainwindow.ui index 99db95a..7b0c116 100644 --- a/mainwindow.ui +++ b/mainwindow.ui @@ -6,8 +6,8 @@ 0 0 - 342 - 145 + 372 + 290 @@ -107,20 +107,7 @@ - - - - - Qt::Horizontal - - - - 40 - 20 - - - - + @@ -139,8 +126,8 @@ 0 0 - 342 - 21 + 372 + 30 @@ -176,8 +163,6 @@ - - - +