init
This commit is contained in:
+380
@@ -0,0 +1,380 @@
|
||||
<?xml version="1.0"?>
|
||||
<interface>
|
||||
<!-- interface-requires gtk+ 2.6 -->
|
||||
<!-- interface-naming-policy toplevel-contextual -->
|
||||
<object class="GtkAdjustment" id="adjustment1">
|
||||
<property name="value">18</property>
|
||||
<property name="upper">100</property>
|
||||
<property name="step_increment">1</property>
|
||||
<property name="page_increment">10</property>
|
||||
</object>
|
||||
<object class="GtkAdjustment" id="adjustment2">
|
||||
<property name="upper">100</property>
|
||||
<property name="step_increment">1</property>
|
||||
<property name="page_increment">10</property>
|
||||
</object>
|
||||
<object class="GtkAdjustment" id="adjustment3">
|
||||
<property name="value">64</property>
|
||||
<property name="lower">1</property>
|
||||
<property name="upper">64</property>
|
||||
<property name="step_increment">1</property>
|
||||
<property name="page_increment">10</property>
|
||||
</object>
|
||||
<object class="GtkAdjustment" id="adjustment4">
|
||||
<property name="value">120</property>
|
||||
<property name="lower">1</property>
|
||||
<property name="upper">65536</property>
|
||||
<property name="step_increment">1</property>
|
||||
<property name="page_increment">10</property>
|
||||
</object>
|
||||
<object class="GtkListStore" id="model1">
|
||||
<columns>
|
||||
<!-- column-name gchararray -->
|
||||
<column type="gchararray"/>
|
||||
</columns>
|
||||
<data>
|
||||
<row>
|
||||
<col id="0" translatable="yes">unspecified</col>
|
||||
</row>
|
||||
<row>
|
||||
<col id="0" translatable="yes">female</col>
|
||||
</row>
|
||||
<row>
|
||||
<col id="0" translatable="yes">male</col>
|
||||
</row>
|
||||
<row>
|
||||
<col id="0" translatable="yes">unknown</col>
|
||||
</row>
|
||||
</data>
|
||||
</object>
|
||||
<object class="GtkListStore" id="model2">
|
||||
<columns>
|
||||
<!-- column-name gchararray -->
|
||||
<column type="gchararray"/>
|
||||
</columns>
|
||||
<data>
|
||||
<row>
|
||||
<col id="0" translatable="yes">250</col>
|
||||
</row>
|
||||
</data>
|
||||
</object>
|
||||
<object class="GtkDialog" id="openvibe-acquisition-server-settings">
|
||||
<property name="border_width">5</property>
|
||||
<property name="title" translatable="yes">Device configuration</property>
|
||||
<property name="window_position">center</property>
|
||||
<property name="type_hint">dialog</property>
|
||||
<property name="gravity">center</property>
|
||||
<property name="has_separator">False</property>
|
||||
<child internal-child="vbox">
|
||||
<object class="GtkVBox" id="dialog-vbox">
|
||||
<property name="visible">True</property>
|
||||
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_ENTER_NOTIFY_MASK</property>
|
||||
<property name="orientation">vertical</property>
|
||||
<property name="spacing">8</property>
|
||||
<child>
|
||||
<object class="GtkLabel" id="label_title">
|
||||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes">Encephalan</property>
|
||||
<property name="justify">center</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkHSeparator" id="hseparator">
|
||||
<property name="visible">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="position">2</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkVBox" id="vbox">
|
||||
<property name="visible">True</property>
|
||||
<property name="border_width">8</property>
|
||||
<property name="orientation">vertical</property>
|
||||
<property name="spacing">8</property>
|
||||
<child>
|
||||
<object class="GtkHBox" id="hbox">
|
||||
<property name="visible">True</property>
|
||||
<property name="spacing">8</property>
|
||||
<child>
|
||||
<object class="GtkTable" id="table2">
|
||||
<property name="visible">True</property>
|
||||
<property name="n_rows">7</property>
|
||||
<property name="n_columns">2</property>
|
||||
<property name="homogeneous">True</property>
|
||||
<child>
|
||||
<object class="GtkComboBox" id="combobox_gender">
|
||||
<property name="visible">True</property>
|
||||
<property name="model">model1</property>
|
||||
<child>
|
||||
<object class="GtkCellRendererText" id="renderer1"/>
|
||||
<attributes>
|
||||
<attribute name="text">0</attribute>
|
||||
</attributes>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">1</property>
|
||||
<property name="right_attach">2</property>
|
||||
<property name="top_attach">2</property>
|
||||
<property name="bottom_attach">3</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkSpinButton" id="spinbutton_age">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="adjustment">adjustment1</property>
|
||||
<property name="snap_to_ticks">True</property>
|
||||
<property name="numeric">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">1</property>
|
||||
<property name="right_attach">2</property>
|
||||
<property name="top_attach">1</property>
|
||||
<property name="bottom_attach">2</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkSpinButton" id="spinbutton_identifier">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="adjustment">adjustment2</property>
|
||||
<property name="snap_to_ticks">True</property>
|
||||
<property name="numeric">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">1</property>
|
||||
<property name="right_attach">2</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel" id="label_sampling_frequency">
|
||||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes">Sampling frequency :</property>
|
||||
<property name="justify">right</property>
|
||||
<property name="single_line_mode">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="top_attach">4</property>
|
||||
<property name="bottom_attach">5</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel" id="label_number_of_channels">
|
||||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes">Number of channels :</property>
|
||||
<property name="justify">right</property>
|
||||
<property name="single_line_mode">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="top_attach">3</property>
|
||||
<property name="bottom_attach">4</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel" id="label_gender">
|
||||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes">Gender :</property>
|
||||
<property name="justify">right</property>
|
||||
<property name="single_line_mode">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="top_attach">2</property>
|
||||
<property name="bottom_attach">3</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel" id="label_age">
|
||||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes">Age :</property>
|
||||
<property name="justify">right</property>
|
||||
<property name="single_line_mode">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="top_attach">1</property>
|
||||
<property name="bottom_attach">2</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel" id="label_identifier">
|
||||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes">Identifier :</property>
|
||||
<property name="justify">right</property>
|
||||
<property name="single_line_mode">True</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkComboBox" id="combobox_sampling_frequency">
|
||||
<property name="visible">True</property>
|
||||
<property name="model">model2</property>
|
||||
<property name="active">0</property>
|
||||
<child>
|
||||
<object class="GtkCellRendererText" id="renderer2"/>
|
||||
<attributes>
|
||||
<attribute name="text">0</attribute>
|
||||
</attributes>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">1</property>
|
||||
<property name="right_attach">2</property>
|
||||
<property name="top_attach">4</property>
|
||||
<property name="bottom_attach">5</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkSpinButton" id="spinbutton_number_of_channels">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="adjustment">adjustment3</property>
|
||||
<property name="snap_to_ticks">True</property>
|
||||
<property name="numeric">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">1</property>
|
||||
<property name="right_attach">2</property>
|
||||
<property name="top_attach">3</property>
|
||||
<property name="bottom_attach">4</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel" id="label_connection_ip">
|
||||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes">Connection IP :</property>
|
||||
<property name="justify">right</property>
|
||||
<property name="single_line_mode">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="top_attach">5</property>
|
||||
<property name="bottom_attach">6</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel" id="label_connection_port">
|
||||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes">Connection Port :</property>
|
||||
<property name="justify">right</property>
|
||||
<property name="single_line_mode">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="top_attach">6</property>
|
||||
<property name="bottom_attach">7</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkSpinButton" id="spinbutton_port">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="adjustment">adjustment4</property>
|
||||
<property name="snap_to_ticks">True</property>
|
||||
<property name="numeric">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">1</property>
|
||||
<property name="right_attach">2</property>
|
||||
<property name="top_attach">6</property>
|
||||
<property name="bottom_attach">7</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkEntry" id="entry_ip">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="max_length">30</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">1</property>
|
||||
<property name="right_attach">2</property>
|
||||
<property name="top_attach">5</property>
|
||||
<property name="bottom_attach">6</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkButton" id="button_change_channel_names">
|
||||
<property name="label" translatable="yes">Change channel names</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="receives_default">False</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="position">3</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkHSeparator" id="hseparator1">
|
||||
<property name="visible">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="position">4</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child internal-child="action_area">
|
||||
<object class="GtkHButtonBox" id="dialog-action_area">
|
||||
<property name="visible">True</property>
|
||||
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_ENTER_NOTIFY_MASK</property>
|
||||
<property name="layout_style">end</property>
|
||||
<child>
|
||||
<object class="GtkButton" id="button_apply">
|
||||
<property name="label">gtk-apply</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="receives_default">False</property>
|
||||
<property name="use_stock">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">False</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkButton" id="button_cancel">
|
||||
<property name="label">gtk-cancel</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="receives_default">False</property>
|
||||
<property name="use_stock">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">False</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="pack_type">end</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
<action-widgets>
|
||||
<action-widget response="-10">button_apply</action-widget>
|
||||
<action-widget response="-6">button_cancel</action-widget>
|
||||
</action-widgets>
|
||||
</object>
|
||||
</interface>
|
||||
+42
@@ -0,0 +1,42 @@
|
||||
#include "ovasCConfigurationEncephalan.h"
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
namespace OpenViBE {
|
||||
namespace AcquisitionServer {
|
||||
|
||||
//---------------------------------------------------------------------------------------------------
|
||||
CConfigurationEncephalan::CConfigurationEncephalan(IDriverContext& driverContext, const char* gtkFileName, uint32_t& connectionPort, char* connectionIp)
|
||||
: CConfigurationBuilder(gtkFileName), m_driverContext(driverContext), m_connectionPort(connectionPort), m_connectionIp(connectionIp) { }
|
||||
//---------------------------------------------------------------------------------------------------
|
||||
|
||||
//---------------------------------------------------------------------------------------------------
|
||||
bool CConfigurationEncephalan::preConfigure()
|
||||
{
|
||||
if (!CConfigurationBuilder::preConfigure()) { return false; }
|
||||
|
||||
GtkSpinButton* port = GTK_SPIN_BUTTON(gtk_builder_get_object(m_builder, "spinbutton_port"));
|
||||
gtk_spin_button_set_value(port, m_connectionPort);
|
||||
GtkEntry* ip = GTK_ENTRY(gtk_builder_get_object(m_builder, "entry_ip"));
|
||||
gtk_entry_set_text(ip, m_connectionIp);
|
||||
|
||||
return true;
|
||||
}
|
||||
//---------------------------------------------------------------------------------------------------
|
||||
|
||||
//---------------------------------------------------------------------------------------------------
|
||||
bool CConfigurationEncephalan::postConfigure()
|
||||
{
|
||||
if (m_applyConfig)
|
||||
{
|
||||
GtkSpinButton* port = GTK_SPIN_BUTTON(gtk_builder_get_object(m_builder, "spinbutton_port"));
|
||||
m_connectionPort = uint32_t(gtk_spin_button_get_value_as_int(port));
|
||||
GtkEntry* ip = GTK_ENTRY(gtk_builder_get_object(m_builder, "entry_ip"));
|
||||
m_connectionIp = const_cast<char*>(gtk_entry_get_text(ip));
|
||||
}
|
||||
|
||||
return CConfigurationBuilder::postConfigure();
|
||||
}
|
||||
//---------------------------------------------------------------------------------------------------
|
||||
|
||||
} // namespace AcquisitionServer
|
||||
} // namespace OpenViBE
|
||||
+36
@@ -0,0 +1,36 @@
|
||||
///-------------------------------------------------------------------------------------------------
|
||||
///
|
||||
/// \file ovasCConfigurationEncephalan.h
|
||||
/// \brief The CConfigurationEncephalan handles the configuration dialog specific to the Encephalan device.
|
||||
/// \author Alexey Minin (UrFU)
|
||||
/// \version 1.0.
|
||||
/// \date 02/01/2019.
|
||||
/// \copyright <a href="https://choosealicense.com/licenses/agpl-3.0/">GNU Affero General Public License v3.0</a>.
|
||||
///
|
||||
///-------------------------------------------------------------------------------------------------
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "../ovasCConfigurationBuilder.h"
|
||||
#include "ovasIDriver.h"
|
||||
|
||||
namespace OpenViBE {
|
||||
namespace AcquisitionServer {
|
||||
/// <summary> The CConfigurationEncephalan handles the configuration dialog specific to the Encephalan device. </summary>
|
||||
/// <seealso cref="CDriverEncephalan" />
|
||||
class CConfigurationEncephalan final : public CConfigurationBuilder
|
||||
{
|
||||
public:
|
||||
CConfigurationEncephalan(IDriverContext& driverContext, const char* gtkFileName, uint32_t& connectionPort, char* connectionIp);
|
||||
|
||||
bool preConfigure() override;
|
||||
bool postConfigure() override;
|
||||
char* getConnectionIp() const { return m_connectionIp; }
|
||||
|
||||
protected:
|
||||
IDriverContext& m_driverContext;
|
||||
uint32_t& m_connectionPort;
|
||||
char* m_connectionIp = nullptr;
|
||||
};
|
||||
} // namespace AcquisitionServer
|
||||
} // namespace OpenViBE
|
||||
+274
@@ -0,0 +1,274 @@
|
||||
#if defined TARGET_OS_Windows
|
||||
|
||||
#include "ovasCDriverEncephalan.h"
|
||||
#include "ovasCConfigurationEncephalan.h"
|
||||
|
||||
namespace OpenViBE {
|
||||
namespace AcquisitionServer {
|
||||
|
||||
//---------------------------------------------------------------------------------------------------
|
||||
CDriverEncephalan::CDriverEncephalan(IDriverContext& driverContext)
|
||||
: IDriver(driverContext), m_settings("AcquisitionServer_Driver_Encephalan", m_driverCtx.getConfigurationManager())
|
||||
{
|
||||
m_connectionIp = static_cast<char*>("127.0.0.1");
|
||||
m_header.setSamplingFrequency(250);
|
||||
m_header.setChannelCount(8);
|
||||
|
||||
m_settings.add("Header", &m_header);
|
||||
m_settings.load();
|
||||
}
|
||||
//---------------------------------------------------------------------------------------------------
|
||||
|
||||
//---------------------------------------------------------------------------------------------------
|
||||
bool CDriverEncephalan::initialize(const uint32_t sampleCountPerBlock, IDriverCallback& callback)
|
||||
{
|
||||
if (m_driverCtx.isConnected() || !m_header.isChannelCountSet() || !m_header.isSamplingFrequencySet()) { return false; }
|
||||
|
||||
m_sample = new float[m_header.getChannelCount() * sampleCountPerBlock];
|
||||
if (!m_sample)
|
||||
{
|
||||
delete[] m_sample;
|
||||
m_sample = nullptr;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Saves parameters
|
||||
m_callback = &callback;
|
||||
m_nSamplePerBlock = sampleCountPerBlock;
|
||||
return connectEncephalan();
|
||||
}
|
||||
//---------------------------------------------------------------------------------------------------
|
||||
|
||||
//---------------------------------------------------------------------------------------------------
|
||||
bool CDriverEncephalan::start()
|
||||
{
|
||||
if (!m_driverCtx.isConnected() || m_driverCtx.isStarted()) { return false; }
|
||||
|
||||
// request hardware to start
|
||||
return sendRequestForData();
|
||||
}
|
||||
//---------------------------------------------------------------------------------------------------
|
||||
|
||||
//---------------------------------------------------------------------------------------------------
|
||||
bool CDriverEncephalan::loop()
|
||||
{
|
||||
if (!m_driverCtx.isConnected()) { return false; }
|
||||
if (!m_driverCtx.isStarted()) { return true; }
|
||||
|
||||
m_currentPoint = 0;
|
||||
ZeroMemory(m_sample, sizeof(float)*m_nSamplePerBlock*m_header.getChannelCount());
|
||||
while (m_currentPoint < m_nSamplePerBlock) { receiveData(); }
|
||||
m_callback->setSamples(m_sample);
|
||||
|
||||
return true;
|
||||
}
|
||||
//---------------------------------------------------------------------------------------------------
|
||||
|
||||
//---------------------------------------------------------------------------------------------------
|
||||
bool CDriverEncephalan::stop() { return m_driverCtx.isConnected() && m_driverCtx.isStarted(); }
|
||||
//---------------------------------------------------------------------------------------------------
|
||||
|
||||
//---------------------------------------------------------------------------------------------------
|
||||
bool CDriverEncephalan::uninitialize()
|
||||
{
|
||||
if (!m_driverCtx.isConnected() || m_driverCtx.isStarted()) { return false; }
|
||||
|
||||
delete[] m_sample;
|
||||
m_sample = nullptr;
|
||||
m_callback = nullptr;
|
||||
|
||||
closesocket(m_client);
|
||||
WSACleanup();
|
||||
|
||||
return true;
|
||||
}
|
||||
//---------------------------------------------------------------------------------------------------
|
||||
|
||||
//---------------------------------------------------------------------------------------------------
|
||||
bool CDriverEncephalan::connectEncephalan()
|
||||
{
|
||||
WSADATA wsaData;
|
||||
const int wsaret = WSAStartup(0x101, &wsaData);
|
||||
if (wsaret != 0)
|
||||
{
|
||||
m_driverCtx.getLogManager() << Kernel::LogLevel_Error << "Error WSAStartup (initialization windows socket api): " << WSAGetLastError() << "\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
m_client = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
|
||||
if (m_client == INVALID_SOCKET)
|
||||
{
|
||||
m_driverCtx.getLogManager() << Kernel::LogLevel_Error << "Error socket (creation a socket): " << WSAGetLastError() << "\n";
|
||||
WSACleanup();
|
||||
return false;
|
||||
}
|
||||
|
||||
sockaddr_in sockaddrIn;
|
||||
sockaddrIn.sin_family = AF_INET;
|
||||
sockaddrIn.sin_addr.s_addr = inet_addr(m_connectionIp);
|
||||
sockaddrIn.sin_port = htons(u_short(m_connectionPort));
|
||||
const int connectError = connect(m_client, reinterpret_cast<sockaddr*>(&sockaddrIn), sizeof(sockaddrIn));
|
||||
if (connectError != 0)
|
||||
{
|
||||
m_driverCtx.getLogManager() << Kernel::LogLevel_Error << "Error connect (connection to a specified socket): " << WSAGetLastError() << "\n";
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
//---------------------------------------------------------------------------------------------------
|
||||
|
||||
//---------------------------------------------------------------------------------------------------
|
||||
bool CDriverEncephalan::sendRequestForData() const
|
||||
{
|
||||
BYTE* sendDataBuffer = new BYTE;
|
||||
|
||||
unsigned long ID = 0x0001; //EEG_ONLY_MODE
|
||||
//unsigned long ID = 0x000C; //ALL_CHANNELS_MODE
|
||||
//unsigned long ID = 0x000E; //HD_CHANNELS_MODE
|
||||
|
||||
CopyMemory(sendDataBuffer, &ID, sizeof(ID));
|
||||
if (!sendData(sendDataBuffer, sizeof(ID)))
|
||||
{
|
||||
m_driverCtx.getLogManager() << Kernel::LogLevel_Error << "Error sendRequestForData: " << WSAGetLastError() << "\n";
|
||||
return false;
|
||||
}
|
||||
m_driverCtx.getLogManager() << Kernel::LogLevel_Info << "sendRequestForData\n";
|
||||
return true;
|
||||
}
|
||||
//---------------------------------------------------------------------------------------------------
|
||||
|
||||
//---------------------------------------------------------------------------------------------------
|
||||
bool CDriverEncephalan::sendData(BYTE* data, int dataSize) const
|
||||
{
|
||||
if (m_client == INVALID_SOCKET) { return false; }
|
||||
|
||||
const long fullLen = dataSize + long(sizeof(int));
|
||||
char* outData = new char[fullLen];
|
||||
|
||||
CopyMemory(&outData[0], &dataSize, sizeof(int));
|
||||
CopyMemory(&outData[sizeof(int)], &data[0], dataSize);
|
||||
|
||||
if (send(m_client, outData, fullLen, 0) != fullLen)
|
||||
{
|
||||
delete[] outData;
|
||||
return false;
|
||||
}
|
||||
|
||||
delete[]outData;
|
||||
return true;
|
||||
}
|
||||
//---------------------------------------------------------------------------------------------------
|
||||
|
||||
//---------------------------------------------------------------------------------------------------
|
||||
bool CDriverEncephalan::receiveData()
|
||||
{
|
||||
int inpSize = 0;
|
||||
char* inpData = new char[sizeof(inpSize) * sizeof(BYTE)];
|
||||
const int nReadSize = recv(m_client, inpData, sizeof(inpSize), 0);
|
||||
if (nReadSize <= 0) { return false; }
|
||||
|
||||
CopyMemory(&inpSize, &inpData[0], sizeof(inpSize));
|
||||
delete[]inpData;
|
||||
|
||||
if ((inpSize > 0) && (inpSize < 1024 * 512))
|
||||
{
|
||||
//unsigned long ID = 0;
|
||||
inpData = new char[inpSize * sizeof(BYTE)];
|
||||
if (recv(m_client, inpData, inpSize, 0) == inpSize) { readData(reinterpret_cast<BYTE*>(inpData), inpSize); }
|
||||
delete[]inpData;
|
||||
inpData = nullptr;
|
||||
}
|
||||
else { return false; }
|
||||
return true;
|
||||
}
|
||||
//---------------------------------------------------------------------------------------------------
|
||||
|
||||
//---------------------------------------------------------------------------------------------------
|
||||
void CDriverEncephalan::readData(BYTE* data, const int dataSize)
|
||||
{
|
||||
BYTE* pCurData = data;
|
||||
int curDataSize = dataSize;
|
||||
|
||||
unsigned long ID = 0;
|
||||
getData(pCurData, curDataSize, &ID, sizeof(ID));
|
||||
switch (ID)
|
||||
{
|
||||
case 0x0002: // Information on research
|
||||
m_driverCtx.getLogManager() << Kernel::LogLevel_Info << "Recieved information on research\n";
|
||||
break;
|
||||
case 0x00E2: // This prompted all the data including the kilohertz
|
||||
m_driverCtx.getLogManager() << Kernel::LogLevel_Info << "Recieved all the data including the kilohertz\n";
|
||||
break;
|
||||
case 0x0003: m_driverCtx.getLogManager() << Kernel::LogLevel_Info << "0x0003 data package\n";
|
||||
break;
|
||||
case 0x0006: m_driverCtx.getLogManager() << Kernel::LogLevel_Info << "0x0006 data package\n";
|
||||
break;
|
||||
case 0x0008: // We came signal data
|
||||
receiveEEGData(pCurData, curDataSize);
|
||||
break;
|
||||
case 0x00E8: // Packet came with HD data
|
||||
m_driverCtx.getLogManager() << Kernel::LogLevel_Info << "Packet came with HD data\n";
|
||||
break;
|
||||
case 0x0009: m_driverCtx.getLogManager() << Kernel::LogLevel_Info << "0x0009 data package\n";
|
||||
break;
|
||||
case 0x000A: m_driverCtx.getLogManager() << Kernel::LogLevel_Info << "0x000A data package\n";
|
||||
break;
|
||||
case 0x0101: m_driverCtx.getLogManager() << Kernel::LogLevel_Info << "0x0101 data package\n";
|
||||
break;
|
||||
default: m_driverCtx.getLogManager() << Kernel::LogLevel_Info << "Undefined data package\n";
|
||||
}
|
||||
}
|
||||
//---------------------------------------------------------------------------------------------------
|
||||
|
||||
//---------------------------------------------------------------------------------------------------
|
||||
// Parsing package with EEG data
|
||||
void CDriverEncephalan::receiveEEGData(BYTE* curData, int curDataSize)
|
||||
{
|
||||
int sliceNum = 0;
|
||||
int pointsNumber = 0;
|
||||
getData(curData, curDataSize, &sliceNum, sizeof(sliceNum));
|
||||
getData(curData, curDataSize, &pointsNumber, sizeof(pointsNumber));
|
||||
|
||||
short* dstData = new short[pointsNumber];
|
||||
ZeroMemory(dstData, sizeof(short)*pointsNumber);
|
||||
getData(curData, curDataSize, dstData, pointsNumber * int(sizeof(short)));
|
||||
|
||||
for (size_t iPos = 0; iPos < m_header.getChannelCount(); ++iPos)
|
||||
{
|
||||
float val = float(dstData[iPos]);
|
||||
CopyMemory(m_sample + (m_currentPoint + iPos * m_nSamplePerBlock), &val, sizeof(float));
|
||||
}
|
||||
m_currentPoint++;
|
||||
|
||||
delete[] dstData;
|
||||
}
|
||||
//---------------------------------------------------------------------------------------------------
|
||||
|
||||
//---------------------------------------------------------------------------------------------------
|
||||
void CDriverEncephalan::getData(BYTE* & data, int& dataSize, void* dstData, const int dstSize)
|
||||
{
|
||||
if (dataSize < dstSize) { return; }
|
||||
CopyMemory(dstData, data, dstSize);
|
||||
data += dstSize;
|
||||
dataSize -= dstSize;
|
||||
}
|
||||
//---------------------------------------------------------------------------------------------------
|
||||
|
||||
//---------------------------------------------------------------------------------------------------
|
||||
bool CDriverEncephalan::configure()
|
||||
{
|
||||
// Change this line if you need to specify some references to your driver attribute that need configuration, e.g. the connection ID.
|
||||
CConfigurationEncephalan configuration(m_driverCtx, Directories::getDataDir() + "/applications/acquisition-server/interface-Encephalan.ui",
|
||||
m_connectionPort, m_connectionIp);
|
||||
|
||||
if (!configuration.configure(m_header)) { return false; }
|
||||
m_connectionIp = configuration.getConnectionIp();
|
||||
m_settings.save();
|
||||
|
||||
return true;
|
||||
}
|
||||
//---------------------------------------------------------------------------------------------------
|
||||
|
||||
} // namespace AcquisitionServer
|
||||
} // namespace OpenViBE
|
||||
#endif // TARGET_OS_Windows
|
||||
+72
@@ -0,0 +1,72 @@
|
||||
///-------------------------------------------------------------------------------------------------
|
||||
///
|
||||
/// \file ovasCDriverEncephalan.h
|
||||
/// \brief The CDriverEncephalan allows the acquisition server to acquire data from a Encephalan device.
|
||||
/// \author Alexey Minin (UrFU)
|
||||
/// \version 1.0.
|
||||
/// \date 02/01/2019.
|
||||
/// \copyright <a href="https://choosealicense.com/licenses/agpl-3.0/">GNU Affero General Public License v3.0</a>.
|
||||
///
|
||||
///-------------------------------------------------------------------------------------------------
|
||||
|
||||
#pragma once
|
||||
|
||||
#if defined TARGET_OS_Windows
|
||||
|
||||
#include "ovasIDriver.h"
|
||||
#include "../ovasCHeader.h"
|
||||
#include <openvibe/ov_all.h>
|
||||
|
||||
#include "../ovasCSettingsHelper.h"
|
||||
#include "../ovasCSettingsHelperOperators.h"
|
||||
|
||||
#include "winsock.h"
|
||||
|
||||
namespace OpenViBE {
|
||||
namespace AcquisitionServer {
|
||||
/// <summary> The CDriverEncephalan allows the acquisition server to acquire data from a Encephalan device. </summary>
|
||||
/// <seealso cref="CConfigurationEncephalan" />
|
||||
class CDriverEncephalan final : public IDriver
|
||||
{
|
||||
public:
|
||||
|
||||
explicit CDriverEncephalan(IDriverContext& driverContext);
|
||||
~CDriverEncephalan() override = default;
|
||||
const char* getName() override { return "Encephalan"; }
|
||||
|
||||
bool initialize(const uint32_t sampleCountPerBlock, IDriverCallback& callback) override;
|
||||
bool uninitialize() override;
|
||||
|
||||
bool start() override;
|
||||
bool stop() override;
|
||||
bool loop() override;
|
||||
|
||||
bool isConfigurable() override { return true; } // change to false if your device is not configurable
|
||||
bool configure() override;
|
||||
const IHeader* getHeader() override { return &m_header; }
|
||||
|
||||
bool isFlagSet(const EDriverFlag flag) const override { return flag == EDriverFlag::IsUnstable; }
|
||||
|
||||
protected:
|
||||
bool connectEncephalan();
|
||||
bool sendRequestForData() const;
|
||||
bool sendData(BYTE* data, int dataSize) const;
|
||||
bool receiveData();
|
||||
void readData(BYTE* data, int dataSize);
|
||||
static void getData(BYTE* & data, int& dataSize, void* dstData, int dstSize);
|
||||
void receiveEEGData(BYTE* curData, int curDataSize);
|
||||
|
||||
SettingsHelper m_settings;
|
||||
IDriverCallback* m_callback = nullptr;
|
||||
CHeader m_header;
|
||||
uint32_t m_nSamplePerBlock = 0;
|
||||
float* m_sample = nullptr;
|
||||
|
||||
char* m_connectionIp = nullptr;
|
||||
uint32_t m_connectionPort = 120;
|
||||
uint32_t m_currentPoint = 0;
|
||||
SOCKET m_client = 0;
|
||||
};
|
||||
} // namespace AcquisitionServer
|
||||
} // namespace OpenViBE
|
||||
#endif // TARGET_OS_Windows
|
||||
Reference in New Issue
Block a user